From 46e1967760b25d853328671a85c741172bee3e98 Mon Sep 17 00:00:00 2001 From: Hai Sullivan Date: Mon, 1 Dec 2025 06:01:01 +1100 Subject: [PATCH] chore: optimisation of several UI components of the mobile app (#24098) * fix(mobile): normalize scrolling behavior in networking settings Remove ClampingScrollPhysics from networking settings page to match the scrolling behavior of other settings pages. This restores the standard iOS bounce/elastic scrolling effect. * fix(mobile): use consistent native transitions for Library pages Change Trash, Shared Links, and Folders routes from CustomRoute to AutoRoute to enable native iOS transitions with swipe-back gesture support. * fix(mobile): remove SafeArea wrapper and ClampingScrollPhysics from Settings Remove SafeArea wrapper (Scaffold handles safe areas automatically) and ClampingScrollPhysics to enable native iOS bounce scrolling. * fix(mobile): remove bottom white space in Sync Status page Replace Padding wrapper with ListView padding to match other Settings pages and eliminate bottom white space. * chore: fix Dart formatting Run dart format to fix formatting issues in settings.page.dart and sync_status_and_actions.dart * Format Dart files --------- Co-authored-by: Claude Co-authored-by: kao-byte --- mobile/lib/pages/common/settings.page.dart | 8 +- mobile/lib/routing/router.dart | 14 +- .../sync_status_and_actions.dart | 138 +++++++++--------- .../networking_settings.dart | 1 - 4 files changed, 73 insertions(+), 88 deletions(-) diff --git a/mobile/lib/pages/common/settings.page.dart b/mobile/lib/pages/common/settings.page.dart index 0fe2ccec09..86c80253dc 100644 --- a/mobile/lib/pages/common/settings.page.dart +++ b/mobile/lib/pages/common/settings.page.dart @@ -58,7 +58,7 @@ class SettingsPage extends StatelessWidget { context.locale; return Scaffold( appBar: AppBar(centerTitle: false, title: const Text('settings').tr()), - body: context.isMobile ? const SafeArea(child: _MobileLayout()) : const SafeArea(child: _TabletLayout()), + body: context.isMobile ? const _MobileLayout() : const _TabletLayout(), ); } } @@ -89,11 +89,7 @@ class _MobileLayout extends StatelessWidget { ], ) .toList(); - return ListView( - physics: const ClampingScrollPhysics(), - padding: const EdgeInsets.only(top: 10.0, bottom: 16), - children: [...settings], - ); + return ListView(padding: const EdgeInsets.only(top: 10.0, bottom: 16), children: [...settings]); } } diff --git a/mobile/lib/routing/router.dart b/mobile/lib/routing/router.dart index abe7ac3fa2..30f43cf3b2 100644 --- a/mobile/lib/routing/router.dart +++ b/mobile/lib/routing/router.dart @@ -245,23 +245,15 @@ class AppRouter extends RootStackRouter { guards: [_authGuard, _duplicateGuard], transitionsBuilder: TransitionsBuilders.slideLeft, ), - CustomRoute(page: FolderRoute.page, guards: [_authGuard], transitionsBuilder: TransitionsBuilders.fadeIn), + AutoRoute(page: FolderRoute.page, guards: [_authGuard]), AutoRoute(page: PartnerDetailRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: PersonResultRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: AllPeopleRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: MemoryRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: MapRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: AlbumOptionsRoute.page, guards: [_authGuard, _duplicateGuard]), - CustomRoute( - page: TrashRoute.page, - guards: [_authGuard, _duplicateGuard], - transitionsBuilder: TransitionsBuilders.slideLeft, - ), - CustomRoute( - page: SharedLinkRoute.page, - guards: [_authGuard, _duplicateGuard], - transitionsBuilder: TransitionsBuilders.slideLeft, - ), + AutoRoute(page: TrashRoute.page, guards: [_authGuard, _duplicateGuard]), + AutoRoute(page: SharedLinkRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: SharedLinkEditRoute.page, guards: [_authGuard, _duplicateGuard]), CustomRoute( page: ActivitiesRoute.page, diff --git a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart index 0296a6bd99..64c3d9b832 100644 --- a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart +++ b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart @@ -108,82 +108,80 @@ class SyncStatusAndActions extends HookConsumerWidget { ); } - return Padding( - padding: const EdgeInsets.only(top: 16, bottom: 32), - child: ListView( - children: [ - const _SyncStatsCounts(), - const Divider(height: 1, indent: 16, endIndent: 16), - const SizedBox(height: 24), - _SectionHeaderText(text: "jobs".t(context: context)), - ListTile( - title: Text( - "sync_local".t(context: context), - style: const TextStyle(fontWeight: FontWeight.w500), - ), - subtitle: Text("tap_to_run_job".t(context: context)), - leading: const Icon(Icons.sync), - trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).localSyncStatus), - onTap: () { - ref.read(backgroundSyncProvider).syncLocal(full: true); - }, + return ListView( + padding: const EdgeInsets.only(top: 16, bottom: 96), + children: [ + const _SyncStatsCounts(), + const Divider(height: 1, indent: 16, endIndent: 16), + const SizedBox(height: 24), + _SectionHeaderText(text: "jobs".t(context: context)), + ListTile( + title: Text( + "sync_local".t(context: context), + style: const TextStyle(fontWeight: FontWeight.w500), ), - ListTile( - title: Text( - "sync_remote".t(context: context), - style: const TextStyle(fontWeight: FontWeight.w500), - ), - subtitle: Text("tap_to_run_job".t(context: context)), - leading: const Icon(Icons.cloud_sync), - trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).remoteSyncStatus), - onTap: () { - ref.read(backgroundSyncProvider).syncRemote(); - }, + subtitle: Text("tap_to_run_job".t(context: context)), + leading: const Icon(Icons.sync), + trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).localSyncStatus), + onTap: () { + ref.read(backgroundSyncProvider).syncLocal(full: true); + }, + ), + ListTile( + title: Text( + "sync_remote".t(context: context), + style: const TextStyle(fontWeight: FontWeight.w500), ), - ListTile( - title: Text( - "hash_asset".t(context: context), - style: const TextStyle(fontWeight: FontWeight.w500), - ), - leading: const Icon(Icons.tag), - subtitle: Text("tap_to_run_job".t(context: context)), - trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).hashJobStatus), - onTap: () { - ref.read(backgroundSyncProvider).hashAssets(); - }, + subtitle: Text("tap_to_run_job".t(context: context)), + leading: const Icon(Icons.cloud_sync), + trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).remoteSyncStatus), + onTap: () { + ref.read(backgroundSyncProvider).syncRemote(); + }, + ), + ListTile( + title: Text( + "hash_asset".t(context: context), + style: const TextStyle(fontWeight: FontWeight.w500), ), - const Divider(height: 1, indent: 16, endIndent: 16), - const SizedBox(height: 24), - _SectionHeaderText(text: "actions".t(context: context)), - ListTile( - title: Text( - "clear_file_cache".t(context: context), - style: const TextStyle(fontWeight: FontWeight.w500), - ), - leading: const Icon(Icons.playlist_remove_rounded), - onTap: clearFileCache, + leading: const Icon(Icons.tag), + subtitle: Text("tap_to_run_job".t(context: context)), + trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).hashJobStatus), + onTap: () { + ref.read(backgroundSyncProvider).hashAssets(); + }, + ), + const Divider(height: 1, indent: 16, endIndent: 16), + const SizedBox(height: 24), + _SectionHeaderText(text: "actions".t(context: context)), + ListTile( + title: Text( + "clear_file_cache".t(context: context), + style: const TextStyle(fontWeight: FontWeight.w500), ), - ListTile( - title: Text( - "export_database".t(context: context), - style: const TextStyle(fontWeight: FontWeight.w500), - ), - subtitle: Text("export_database_description".t(context: context)), - leading: const Icon(Icons.download), - onTap: exportDatabase, + leading: const Icon(Icons.playlist_remove_rounded), + onTap: clearFileCache, + ), + ListTile( + title: Text( + "export_database".t(context: context), + style: const TextStyle(fontWeight: FontWeight.w500), ), - ListTile( - title: Text( - "reset_sqlite".t(context: context), - style: TextStyle(color: context.colorScheme.error, fontWeight: FontWeight.w500), - ), - leading: Icon(Icons.settings_backup_restore_rounded, color: context.colorScheme.error), - onTap: () async { - await resetSqliteDb(context); - }, + subtitle: Text("export_database_description".t(context: context)), + leading: const Icon(Icons.download), + onTap: exportDatabase, + ), + ListTile( + title: Text( + "reset_sqlite".t(context: context), + style: TextStyle(color: context.colorScheme.error, fontWeight: FontWeight.w500), ), - ], - ), + leading: Icon(Icons.settings_backup_restore_rounded, color: context.colorScheme.error), + onTap: () async { + await resetSqliteDb(context); + }, + ), + ], ); } } diff --git a/mobile/lib/widgets/settings/networking_settings/networking_settings.dart b/mobile/lib/widgets/settings/networking_settings/networking_settings.dart index 426ea5ac0f..272b83c9aa 100644 --- a/mobile/lib/widgets/settings/networking_settings/networking_settings.dart +++ b/mobile/lib/widgets/settings/networking_settings/networking_settings.dart @@ -86,7 +86,6 @@ class NetworkingSettings extends HookConsumerWidget { return ListView( padding: const EdgeInsets.only(bottom: 96), - physics: const ClampingScrollPhysics(), children: [ Padding( padding: const EdgeInsets.only(top: 8, left: 16, bottom: 8),