Refine views for mobile-first and responsive layouts
This commit is contained in:
@@ -16,81 +16,106 @@ class SettingsView extends ConsumerWidget {
|
||||
.asData
|
||||
?.value;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(28, 24, 28, 28),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text('Settings', style: Theme.of(context).textTheme.headlineMedium),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
'Environment and integration configuration for this build.',
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.bodyLarge?.copyWith(color: AppTheme.textSecondary),
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
final bool compact = constraints.maxWidth < 760;
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
compact ? 16 : 28,
|
||||
compact ? 16 : 24,
|
||||
compact ? 16 : 28,
|
||||
compact ? 20 : 28,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FrostedCard(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
_SettingRow(
|
||||
label: 'Signed in as',
|
||||
value:
|
||||
session?.user.email ??
|
||||
session?.user.id ??
|
||||
'Not signed in',
|
||||
Text(
|
||||
'Settings',
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_SettingRow(
|
||||
label: 'Gateway mode',
|
||||
value: AppConfig.useFakeBackend
|
||||
? 'Fake (offline-safe)'
|
||||
: 'REST',
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
'Environment and integration configuration for this build.',
|
||||
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
color: AppTheme.textSecondary,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_SettingRow(label: 'Base URL', value: AppConfig.backendBaseUrl),
|
||||
const SizedBox(height: 12),
|
||||
const _SettingRow(
|
||||
label: 'Realtime',
|
||||
value: 'Planned later (SSE/WebSocket)',
|
||||
const SizedBox(height: 16),
|
||||
FrostedCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
_SettingRow(
|
||||
compact: compact,
|
||||
label: 'Signed in as',
|
||||
value:
|
||||
session?.user.email ??
|
||||
session?.user.id ??
|
||||
'Not signed in',
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_SettingRow(
|
||||
compact: compact,
|
||||
label: 'Gateway mode',
|
||||
value: AppConfig.useFakeBackend
|
||||
? 'Fake (offline-safe)'
|
||||
: 'REST',
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_SettingRow(
|
||||
compact: compact,
|
||||
label: 'Base URL',
|
||||
value: AppConfig.backendBaseUrl,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_SettingRow(
|
||||
compact: compact,
|
||||
label: 'Realtime',
|
||||
value: 'Planned later (SSE/WebSocket)',
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: <Widget>[
|
||||
FilledButton.icon(
|
||||
onPressed: session == null
|
||||
? null
|
||||
: () => _signOut(context, ref),
|
||||
icon: const Icon(Icons.logout_rounded),
|
||||
label: const Text('Sign Out'),
|
||||
),
|
||||
OutlinedButton.icon(
|
||||
onPressed: session == null
|
||||
? null
|
||||
: () {
|
||||
ref
|
||||
.read(
|
||||
sessionControllerProvider.notifier,
|
||||
)
|
||||
.refreshProfile();
|
||||
},
|
||||
icon: const Icon(Icons.refresh_rounded),
|
||||
label: const Text('Refresh Profile'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
FilledButton.icon(
|
||||
onPressed: session == null
|
||||
? null
|
||||
: () => _signOut(context, ref),
|
||||
icon: const Icon(Icons.logout_rounded),
|
||||
label: const Text('Sign Out'),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
OutlinedButton.icon(
|
||||
onPressed: session == null
|
||||
? null
|
||||
: () {
|
||||
ref
|
||||
.read(sessionControllerProvider.notifier)
|
||||
.refreshProfile();
|
||||
},
|
||||
icon: const Icon(Icons.refresh_rounded),
|
||||
label: const Text('Refresh Profile'),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 16),
|
||||
FrostedCard(
|
||||
child: Text(
|
||||
'Run options\n• Fake mode: flutter run --dart-define=USE_FAKE_BACKEND=true\n• REST mode: flutter run --dart-define=USE_FAKE_BACKEND=false --dart-define=BACKEND_BASE_URL=https://your-api',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FrostedCard(
|
||||
child: Text(
|
||||
'Run options\n• Fake mode: flutter run --dart-define=USE_FAKE_BACKEND=true\n• REST mode: flutter run --dart-define=USE_FAKE_BACKEND=false --dart-define=BACKEND_BASE_URL=https://your-api',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -105,13 +130,34 @@ class SettingsView extends ConsumerWidget {
|
||||
}
|
||||
|
||||
class _SettingRow extends StatelessWidget {
|
||||
const _SettingRow({required this.label, required this.value});
|
||||
const _SettingRow({
|
||||
required this.label,
|
||||
required this.value,
|
||||
required this.compact,
|
||||
});
|
||||
|
||||
final String label;
|
||||
final String value;
|
||||
final bool compact;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (compact) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
label,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleMedium?.copyWith(color: AppTheme.textSecondary),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(value, style: Theme.of(context).textTheme.bodyLarge),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
|
||||
Reference in New Issue
Block a user