99 lines
3.0 KiB
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),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|