feat(train): Settings over the tabs from a cog on Home and Profile, the account near its foot (ADR 0030, D60)
As Learn's: a cog atop Home and Profile, with the count of accounts waiting for whoever operates the instance, opens Settings over the tabs, where an account sheet had held the account and the training's screens. Grouped in cards: the operator's card, the training (your body, Health Connect, the Polar Loop, music, those the device has), the account near the foot, About Halkyon Train last, and the version small at the very bottom. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
d4d749eb9f
commit
25191055ae
12 changed files with 322 additions and 150 deletions
|
|
@ -12,7 +12,7 @@
|
|||
"accountTitle": "Konto",
|
||||
"accountDeleteMessage": "Dein Konto wird auf dem Server und auf all deinen Geräten gelöscht. Dies kann nicht rückgängig gemacht werden.",
|
||||
|
||||
"aboutTitle": "Über",
|
||||
"aboutTitle": "Über Halkyon Train",
|
||||
|
||||
"homeRecordHint": "Zeichne eins mit dem Knopf unten auf.",
|
||||
"recordAction": "Aufzeichnen",
|
||||
|
|
@ -563,5 +563,8 @@
|
|||
"shellTabGroups": "Gruppen",
|
||||
"shellTabProfile": "Profil",
|
||||
"groupsLaterTitle": "Gruppen kommen später",
|
||||
"groupsLaterHint": "Mit anderen trainieren, in euren eigenen Gruppen, kommt in einer späteren Version von Train."
|
||||
"groupsLaterHint": "Mit anderen trainieren, in euren eigenen Gruppen, kommt in einer späteren Version von Train.",
|
||||
"settingsTitle": "Einstellungen",
|
||||
"settingsTraining": "Training",
|
||||
"settingsVersion": "Version {version} (Build {build})"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
"accountTitle": "Account",
|
||||
"accountDeleteMessage": "Your account is deleted on the server and on all your devices. This can't be undone.",
|
||||
|
||||
"aboutTitle": "About",
|
||||
"aboutTitle": "About Halkyon Train",
|
||||
|
||||
"homeRecordHint": "Record one with the button below.",
|
||||
"recordAction": "Record",
|
||||
|
|
@ -710,5 +710,9 @@
|
|||
"shellTabGroups": "Groups",
|
||||
"shellTabProfile": "Profile",
|
||||
"groupsLaterTitle": "Groups come later",
|
||||
"groupsLaterHint": "Training with others, in groups of your own, comes in a later version of Train."
|
||||
"groupsLaterHint": "Training with others, in groups of your own, comes in a later version of Train.",
|
||||
"settingsTitle": "Settings",
|
||||
"settingsTraining": "Training",
|
||||
"settingsVersion": "Version {version} (build {build})",
|
||||
"@settingsVersion": {"placeholders": {"version": {"type": "String"}, "build": {"type": "String"}}}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ abstract class AppLocalizations {
|
|||
/// No description provided for @aboutTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'About'**
|
||||
/// **'About Halkyon Train'**
|
||||
String get aboutTitle;
|
||||
|
||||
/// No description provided for @homeRecordHint.
|
||||
|
|
@ -3405,6 +3405,24 @@ abstract class AppLocalizations {
|
|||
/// In en, this message translates to:
|
||||
/// **'Training with others, in groups of your own, comes in a later version of Train.'**
|
||||
String get groupsLaterHint;
|
||||
|
||||
/// No description provided for @settingsTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Settings'**
|
||||
String get settingsTitle;
|
||||
|
||||
/// No description provided for @settingsTraining.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Training'**
|
||||
String get settingsTraining;
|
||||
|
||||
/// No description provided for @settingsVersion.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Version {version} (build {build})'**
|
||||
String settingsVersion(String version, String build);
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
'Dein Konto wird auf dem Server und auf all deinen Geräten gelöscht. Dies kann nicht rückgängig gemacht werden.';
|
||||
|
||||
@override
|
||||
String get aboutTitle => 'Über';
|
||||
String get aboutTitle => 'Über Halkyon Train';
|
||||
|
||||
@override
|
||||
String get homeRecordHint => 'Zeichne eins mit dem Knopf unten auf.';
|
||||
|
|
@ -2041,4 +2041,15 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
@override
|
||||
String get groupsLaterHint =>
|
||||
'Mit anderen trainieren, in euren eigenen Gruppen, kommt in einer späteren Version von Train.';
|
||||
|
||||
@override
|
||||
String get settingsTitle => 'Einstellungen';
|
||||
|
||||
@override
|
||||
String get settingsTraining => 'Training';
|
||||
|
||||
@override
|
||||
String settingsVersion(String version, String build) {
|
||||
return 'Version $version (Build $build)';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
'Your account is deleted on the server and on all your devices. This can\'t be undone.';
|
||||
|
||||
@override
|
||||
String get aboutTitle => 'About';
|
||||
String get aboutTitle => 'About Halkyon Train';
|
||||
|
||||
@override
|
||||
String get homeRecordHint => 'Record one with the button below.';
|
||||
|
|
@ -2029,6 +2029,17 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
@override
|
||||
String get groupsLaterHint =>
|
||||
'Training with others, in groups of your own, comes in a later version of Train.';
|
||||
|
||||
@override
|
||||
String get settingsTitle => 'Settings';
|
||||
|
||||
@override
|
||||
String get settingsTraining => 'Training';
|
||||
|
||||
@override
|
||||
String settingsVersion(String version, String build) {
|
||||
return 'Version $version (build $build)';
|
||||
}
|
||||
}
|
||||
|
||||
/// The translations for English, as used in the United Kingdom (`en_GB`).
|
||||
|
|
|
|||
|
|
@ -1,97 +0,0 @@
|
|||
import 'package:halkyon_app/halkyon_app.dart';
|
||||
import 'package:halkyon_train_flutter/l10n/app_localizations.dart';
|
||||
import 'package:halkyon_train_flutter/src/app/train_dependencies.dart';
|
||||
import 'package:halkyon_train_flutter/src/app/train_frame.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/health/widget/health_screen.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/loop/widget/loop_screen.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/music/widget/music_screen.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/profile/widget/profile_screen.dart';
|
||||
import 'package:halkyon_ui/halkyon_ui.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
/// The account: halkyon_app's sections (whose it is, on which instance,
|
||||
/// switching to the account on another, signing out and deleting it;
|
||||
/// SimpleLogin; its password and authenticators) in Train's words where only
|
||||
/// Train can say it; and About.
|
||||
Future<void> showAccountSheet(BuildContext context) => showAdaptiveSheet(
|
||||
context,
|
||||
builder: (context) => const _AccountSheet(),
|
||||
);
|
||||
|
||||
class const _AccountSheet() extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context);
|
||||
return SheetScaffold(
|
||||
title: l10n.accountTitle,
|
||||
// What failed (signing out, deleting the account, reading it) shows
|
||||
// on the sheet, not behind its barrier.
|
||||
hasSnackBars: true,
|
||||
body: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
AccountTiles(deleteMessage: l10n.accountDeleteMessage),
|
||||
// Accounts waiting for approval, for whoever operates the
|
||||
// instance alone (Halkyon Learn's ADR 0021, D34).
|
||||
const InstanceOperatorTiles(),
|
||||
// SimpleLogin keeps the account where the instance offers it
|
||||
// (ADR 0020, D21), and a password and an authenticator, signing
|
||||
// in on other devices and in the instance's other apps (ADR 0017).
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [SimpleLoginSection(), AccountSecuritySection()],
|
||||
),
|
||||
),
|
||||
// The figures of the person's body (ADR 0030, D33), here until
|
||||
// Train has settings.
|
||||
ListTile(
|
||||
leading: const Icon(LucideIcons.personStanding),
|
||||
title: Text(l10n.profileTitle),
|
||||
subtitle: Text(l10n.profileHint),
|
||||
onTap: () => openProfileScreen(context),
|
||||
),
|
||||
// Health Connect on this phone (ADR 0030, D31), here until Train
|
||||
// has settings.
|
||||
if (PersonScope.of<TrainPerson>(context).health != null)
|
||||
ListTile(
|
||||
leading: const Icon(LucideIcons.heartPulse),
|
||||
title: Text(l10n.healthTitle),
|
||||
subtitle: Text(l10n.healthHint),
|
||||
onTap: () => openHealthScreen(context),
|
||||
),
|
||||
// The person's Polar Loop on this phone (D34).
|
||||
if (PersonScope.of<TrainPerson>(context).loop != null)
|
||||
ListTile(
|
||||
leading: const Icon(LucideIcons.watch),
|
||||
title: Text(l10n.loopTitle),
|
||||
subtitle: Text(l10n.loopHint),
|
||||
onTap: () => openLoopScreen(context),
|
||||
),
|
||||
// Music from Jellyfin on this phone (D47).
|
||||
if (PersonScope.of<TrainPerson>(context).music != null)
|
||||
ListTile(
|
||||
leading: const Icon(LucideIcons.music),
|
||||
title: Text(l10n.musicTitle),
|
||||
subtitle: Text(l10n.musicHint),
|
||||
onTap: () => openMusicScreen(context),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(LucideIcons.info),
|
||||
title: Text(l10n.aboutTitle),
|
||||
// halkyon_app's About: the app's name and icon, the source of
|
||||
// what the instance runs, which both licences ask to offer, and
|
||||
// the licence list.
|
||||
onTap: () => showAppAbout(
|
||||
context,
|
||||
icon: const Image(image: trainIcon, width: 48, height: 48),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -200,6 +200,10 @@ class TrainDependencies({
|
|||
|
||||
/// Opens a signed-in person's dependencies ([openPerson]).
|
||||
required final OpenTrainPerson _openPerson,
|
||||
|
||||
/// This build's version and number, which Settings shows at its foot so
|
||||
/// that a report can name the release; none in tests that don't say.
|
||||
final ({String version, int? build}) appVersion = (version: '', build: null),
|
||||
final Future<void> Function()? _onDispose,
|
||||
}) implements AppDependencies<TrainPerson> {
|
||||
/// The dependencies above [context] ([AppScope]).
|
||||
|
|
@ -291,6 +295,7 @@ class TrainDependencies({
|
|||
assistants: assistants,
|
||||
assistantOperators: assistantOperators,
|
||||
fileSaver: PlatformFileSaver(),
|
||||
appVersion: (version: device.appVersion, build: device.appBuild),
|
||||
sourceCodeUrl: () async =>
|
||||
(await client.modules.base.instance.basics()).sourceCodeUrl,
|
||||
openPerson: (person) async {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import 'package:halkyon_train_flutter/src/feature/day/model/day.dart';
|
|||
|
||||
/// The app's locations (ADR 0030, D60): the five tabs, a workout's page in
|
||||
/// Home and a day's in Profile, and the editors and the recording over the
|
||||
/// tabs.
|
||||
/// tabs, and Settings.
|
||||
abstract final class TrainPaths() {
|
||||
/// Home, where the app opens: the workouts.
|
||||
static const home = '/';
|
||||
|
|
@ -34,4 +34,7 @@ abstract final class TrainPaths() {
|
|||
|
||||
/// The recording under way or stopped, over the tabs.
|
||||
static const recording = '/recording';
|
||||
|
||||
/// Settings, over the tabs.
|
||||
static const settings = '/settings';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import 'package:halkyon_train_flutter/src/feature/recording/widget/recording_scr
|
|||
import 'package:halkyon_train_flutter/src/feature/route/model/route.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/route/widget/route_screen.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/workout/widget/workout_screen.dart';
|
||||
import 'package:halkyon_train_flutter/src/settings/settings_screen.dart';
|
||||
import 'package:halkyon_train_flutter/src/tabs/groups_tab.dart';
|
||||
import 'package:halkyon_train_flutter/src/tabs/home_tab.dart';
|
||||
import 'package:halkyon_train_flutter/src/tabs/maps_tab.dart';
|
||||
|
|
@ -109,6 +110,11 @@ GoRouter buildTrainRouter() => GoRouter(
|
|||
path: TrainPaths.recording,
|
||||
builder: (context, state) => const RecordingScreen(),
|
||||
),
|
||||
// In the frame without the rail from medium windows on, as Learn's.
|
||||
GoRoute(
|
||||
path: TrainPaths.settings,
|
||||
builder: (context, state) => const FramedScreen(child: SettingsScreen()),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,181 @@
|
|||
import 'package:go_router/go_router.dart';
|
||||
import 'package:halkyon_app/halkyon_app.dart';
|
||||
import 'package:halkyon_train_flutter/l10n/app_localizations.dart';
|
||||
import 'package:halkyon_train_flutter/src/app/train_dependencies.dart';
|
||||
import 'package:halkyon_train_flutter/src/app/train_frame.dart';
|
||||
import 'package:halkyon_train_flutter/src/app/train_paths.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/health/widget/health_screen.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/loop/widget/loop_screen.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/music/widget/music_screen.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/profile/widget/profile_screen.dart';
|
||||
import 'package:halkyon_ui/halkyon_ui.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
/// The cog to [SettingsScreen], atop Home and Profile as Learn's, with the
|
||||
/// count of accounts waiting for whoever operates the instance.
|
||||
class const SettingsButton({super.key}) extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) => IconButton(
|
||||
tooltip: AppLocalizations.of(context).settingsTitle,
|
||||
icon: const WaitingAccountsBadge(child: Icon(LucideIcons.settings)),
|
||||
onPressed: () => context.push(TrainPaths.settings),
|
||||
);
|
||||
}
|
||||
|
||||
/// Settings, over the tabs (ADR 0030, D60), grouped in cards as Learn's:
|
||||
/// the operator's card for whoever operates the instance; the training's
|
||||
/// screens (the body's figures, Health Connect, the Polar Loop, music,
|
||||
/// those the device has); the account, near the foot (halkyon_app's
|
||||
/// sections: whose it is on which instance, switching, signing out and
|
||||
/// deleting it, SimpleLogin, its password and authenticators) in Train's
|
||||
/// words where only Train can say it; About Halkyon Train last; and at the
|
||||
/// very foot which release this is.
|
||||
class const SettingsScreen({super.key}) extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context);
|
||||
final theme = Theme.of(context);
|
||||
final train = PersonScope.of<TrainPerson>(context);
|
||||
Widget heading(String text) => Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 8, 16, 4),
|
||||
child: Text(text, style: theme.textTheme.titleMedium),
|
||||
);
|
||||
return TopGradient(
|
||||
background: theme.colorScheme.surfaceContainerLow,
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
systemOverlayStyle: TopGradient.overlayStyle(context),
|
||||
title: Text(l10n.settingsTitle),
|
||||
),
|
||||
body: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: readableContentMaxWidth,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// Accounts waiting for approval, for whoever operates
|
||||
// the instance alone (Halkyon Learn's ADR 0021, D34),
|
||||
// first, as the cog's count leads here.
|
||||
const InstanceOperatorCard(below: 12),
|
||||
SectionCard(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
heading(l10n.settingsTraining),
|
||||
// The figures of the person's body (D33).
|
||||
ListTile(
|
||||
leading: const Icon(LucideIcons.personStanding),
|
||||
title: Text(l10n.profileTitle),
|
||||
subtitle: Text(l10n.profileHint),
|
||||
onTap: () => openProfileScreen(context),
|
||||
),
|
||||
// Health Connect on this phone (D31).
|
||||
if (train.health != null)
|
||||
ListTile(
|
||||
leading: const Icon(LucideIcons.heartPulse),
|
||||
title: Text(l10n.healthTitle),
|
||||
subtitle: Text(l10n.healthHint),
|
||||
onTap: () => openHealthScreen(context),
|
||||
),
|
||||
// The person's Polar Loop on this phone (D34).
|
||||
if (train.loop != null)
|
||||
ListTile(
|
||||
leading: const Icon(LucideIcons.watch),
|
||||
title: Text(l10n.loopTitle),
|
||||
subtitle: Text(l10n.loopHint),
|
||||
onTap: () => openLoopScreen(context),
|
||||
),
|
||||
// Music from Jellyfin on this phone (D47).
|
||||
if (train.music != null)
|
||||
ListTile(
|
||||
leading: const Icon(LucideIcons.music),
|
||||
title: Text(l10n.musicTitle),
|
||||
subtitle: Text(l10n.musicHint),
|
||||
onTap: () => openMusicScreen(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SectionCard(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
heading(l10n.accountTitle),
|
||||
AccountTiles(deleteMessage: l10n.accountDeleteMessage),
|
||||
// SimpleLogin keeps the account where the instance
|
||||
// offers it (ADR 0020, D21), and a password and an
|
||||
// authenticator, signing in on other devices and in
|
||||
// the instance's other apps (ADR 0017).
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
SimpleLoginSection(),
|
||||
AccountSecuritySection(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SectionCard(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: ListTile(
|
||||
leading: const Icon(LucideIcons.info),
|
||||
title: Text(l10n.aboutTitle),
|
||||
// halkyon_app's About: the app's name and icon, the
|
||||
// source of what the instance runs, which both
|
||||
// licences ask to offer, and the licence list.
|
||||
onTap: () => showAppAbout(
|
||||
context,
|
||||
icon: const Image(
|
||||
image: trainIcon,
|
||||
width: 48,
|
||||
height: 48,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const _Version(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Which release of the app this is, so that a report can name it.
|
||||
class const _Version() extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final (:version, :build) = TrainDependencies.of(context).appVersion;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: Text(
|
||||
AppLocalizations.of(context).settingsVersion(version, '${build ?? ''}'),
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,13 +2,14 @@ import 'package:halkyon_app/halkyon_app.dart';
|
|||
import 'package:halkyon_train_flutter/l10n/app_localizations.dart';
|
||||
import 'package:halkyon_train_flutter/src/app/train_dependencies.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/workout/widget/workouts_list.dart';
|
||||
import 'package:halkyon_train_flutter/src/settings/settings_screen.dart';
|
||||
import 'package:halkyon_train_flutter/src/tabs/tab_screen.dart';
|
||||
import 'package:halkyon_ui/halkyon_ui.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
/// Home (ADR 0030, D60): the person's workouts (D24), a reset of their keys
|
||||
/// waiting above them (`KeysResetBanner`).
|
||||
/// waiting above them (`KeysResetBanner`); the cog to Settings.
|
||||
class const HomeTab({super.key}) extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -16,6 +17,7 @@ class const HomeTab({super.key}) extends StatelessWidget {
|
|||
final records = PersonScope.of<TrainPerson>(context).recording != null;
|
||||
return TabScreen(
|
||||
title: l10n.shellTabHome,
|
||||
actions: const [SettingsButton()],
|
||||
body: Column(
|
||||
children: [
|
||||
const KeysResetBanner(),
|
||||
|
|
|
|||
|
|
@ -1,32 +1,25 @@
|
|||
import 'package:halkyon_app/halkyon_app.dart';
|
||||
import 'package:halkyon_train_flutter/l10n/app_localizations.dart';
|
||||
import 'package:halkyon_train_flutter/src/account/account_sheet.dart';
|
||||
import 'package:halkyon_train_flutter/src/app/train_dependencies.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/day/widget/days_list.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/plan/widget/plans_list.dart';
|
||||
import 'package:halkyon_train_flutter/src/settings/settings_screen.dart';
|
||||
import 'package:halkyon_train_flutter/src/tabs/tab_screen.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
/// Profile (ADR 0030, D60): the person's days from the Loop (D37), and the
|
||||
/// way to their account. Where the device doesn't record, and so has no
|
||||
/// cog to Settings. Where the device doesn't record, and so has no
|
||||
/// Record tab, the interval plans (D42) are here beside the days.
|
||||
class const ProfileTab({super.key}) extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context);
|
||||
final records = PersonScope.of<TrainPerson>(context).recording != null;
|
||||
final account = IconButton(
|
||||
tooltip: l10n.accountTitle,
|
||||
icon: const WaitingAccountsBadge(
|
||||
child: Icon(LucideIcons.circleUserRound),
|
||||
),
|
||||
onPressed: () => showAccountSheet(context),
|
||||
);
|
||||
const settings = SettingsButton();
|
||||
if (records) {
|
||||
return TabScreen(
|
||||
title: l10n.shellTabProfile,
|
||||
actions: [account],
|
||||
actions: const [settings],
|
||||
body: const DaysList(),
|
||||
);
|
||||
}
|
||||
|
|
@ -34,7 +27,7 @@ class const ProfileTab({super.key}) extends StatelessWidget {
|
|||
length: 2,
|
||||
child: TabScreen(
|
||||
title: l10n.shellTabProfile,
|
||||
actions: [account],
|
||||
actions: const [settings],
|
||||
bottom: TabBar(
|
||||
tabs: [
|
||||
Tab(text: l10n.homeDays),
|
||||
|
|
|
|||
Loading…
Reference in a new issue