Files
sxchnge/frontend/app/lib/security/settings.dart

99 lines
3.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:sxchnge_analytics/sxchnge_analytics.dart';
import 'package:sxchnge_auth/sxchnge_auth.dart';
import 'challenge.dart';
import '../generated/i18n/app_localizations.dart';
class SecuritySettings extends StatefulWidget {
const SecuritySettings({super.key});
@override
State<SecuritySettings> createState() => _SecuritySettingsState();
}
class _SecuritySettingsState extends State<SecuritySettings> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) context.read<SecurityProvider>().refresh();
});
}
Future<void> _change(SecurityProvider p, bool enabled) async {
final challenge = await p.prepare(enabled);
if (!mounted || challenge == null) return;
final grant = await verifyFactor(
context,
challenge: challenge,
service: p.service,
recorder: p.recorder,
journey: JourneyKind.security,
);
if (mounted && grant != null) await p.apply(enabled, grant);
}
@override
Widget build(BuildContext context) {
final p = context.watch<SecurityProvider>();
final l = AppLocalizations.of(context)!;
final t = Theme.of(context);
return Card(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(l.factorSettings, style: t.textTheme.titleLarge),
const SizedBox(height: 12),
Text(l.factorSettingsHelp),
const SizedBox(height: 16),
if (p.busy) const LinearProgressIndicator(),
if (p.data != null) ...[
Semantics(
liveRegion: true,
child: Text(
p.data!.enabled ? l.factorOn : l.factorOff,
key: const ValueKey('two-factor-status'),
style: t.textTheme.titleMedium,
),
),
const SizedBox(height: 8),
Text(
p.data!.method == FactorMethod.email
? l.factorEmailMethod
: l.factorAppMethod,
),
const SizedBox(height: 16),
FilledButton.tonal(
key: const ValueKey('two-factor-setting'),
onPressed: p.busy ? null : () => _change(p, !p.data!.enabled),
child: Text(p.data!.enabled ? l.factorDisable : l.factorEnable),
),
],
if (p.error != null) ...[
const SizedBox(height: 12),
Semantics(
liveRegion: true,
child: Text(
factorErrorText(l, p.error!),
style: TextStyle(color: t.colorScheme.error),
),
),
TextButton(
onPressed: p.busy ? null : p.refresh,
child: Text(l.wRefresh),
),
],
],
),
),
);
}
}