chore: bump dart sdk to 3.8 (#20355)

* chore: bump dart sdk to 3.8

* chore: make build

* make pigeon

* chore: format files

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
shenlong 2025-07-29 00:34:03 +05:30 committed by GitHub
parent 9b3718120b
commit e52b9d15b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
643 changed files with 32561 additions and 35292 deletions

View file

@ -22,23 +22,17 @@ class AlbumPreviewPage extends HookConsumerWidget {
assets.value = await ref.read(albumMediaRepositoryProvider).getAssets(album.localId!);
}
useEffect(
() {
getAssetsInAlbum();
return null;
},
[],
);
useEffect(() {
getAssetsInAlbum();
return null;
}, []);
return Scaffold(
appBar: AppBar(
elevation: 0,
title: Column(
children: [
Text(
album.name,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
Text(album.name, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Text(
@ -52,10 +46,7 @@ class AlbumPreviewPage extends HookConsumerWidget {
),
],
),
leading: IconButton(
onPressed: () => context.maybePop(),
icon: const Icon(Icons.arrow_back_ios_new_rounded),
),
leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_new_rounded)),
),
body: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
@ -65,11 +56,7 @@ class AlbumPreviewPage extends HookConsumerWidget {
),
itemCount: assets.value.length,
itemBuilder: (context, index) {
return ImmichThumbnail(
asset: assets.value[index],
width: 100,
height: 100,
);
return ImmichThumbnail(asset: assets.value[index], width: 100, height: 100);
},
),
);

View file

@ -23,45 +23,29 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
final isDarkTheme = context.isDarkTheme;
final albums = ref.watch(backupProvider).availableAlbums;
useEffect(
() {
ref.watch(backupProvider.notifier).getBackupInfo();
return null;
},
[],
);
useEffect(() {
ref.watch(backupProvider.notifier).getBackupInfo();
return null;
}, []);
buildAlbumSelectionList() {
if (albums.isEmpty) {
return const SliverToBoxAdapter(
child: Center(
child: CircularProgressIndicator(),
),
);
return const SliverToBoxAdapter(child: Center(child: CircularProgressIndicator()));
}
return SliverPadding(
padding: const EdgeInsets.symmetric(vertical: 12.0),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
((context, index) {
return AlbumInfoListTile(
album: albums[index],
);
}),
childCount: albums.length,
),
delegate: SliverChildBuilderDelegate(((context, index) {
return AlbumInfoListTile(album: albums[index]);
}), childCount: albums.length),
),
);
}
buildAlbumSelectionGrid() {
if (albums.isEmpty) {
return const SliverToBoxAdapter(
child: Center(
child: CircularProgressIndicator(),
),
);
return const SliverToBoxAdapter(child: Center(child: CircularProgressIndicator()));
}
return SliverPadding(
@ -74,9 +58,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
),
itemCount: albums.length,
itemBuilder: ((context, index) {
return AlbumInfoCard(
album: albums[index],
);
return AlbumInfoCard(album: albums[index]);
}),
),
);
@ -101,10 +83,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
),
backgroundColor: context.primaryColor,
deleteIconColor: isDarkTheme ? Colors.black : Colors.white,
deleteIcon: const Icon(
Icons.cancel_rounded,
size: 15,
),
deleteIcon: const Icon(Icons.cancel_rounded, size: 15),
onDeleted: removeSelection,
),
),
@ -125,18 +104,11 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
child: Chip(
label: Text(
album.name,
style: TextStyle(
fontSize: 12,
color: context.scaffoldBackgroundColor,
fontWeight: FontWeight.bold,
),
style: TextStyle(fontSize: 12, color: context.scaffoldBackgroundColor, fontWeight: FontWeight.bold),
),
backgroundColor: Colors.red[300],
deleteIconColor: context.scaffoldBackgroundColor,
deleteIcon: const Icon(
Icons.cancel_rounded,
size: 15,
),
deleteIcon: const Icon(Icons.cancel_rounded, size: 15),
onDeleted: removeSelection,
),
),
@ -155,13 +127,8 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () => context.maybePop(),
icon: const Icon(Icons.arrow_back_ios_rounded),
),
title: const Text(
"backup_album_selection_page_select_albums",
).tr(),
leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_rounded)),
title: const Text("backup_album_selection_page_select_albums").tr(),
elevation: 0,
),
body: CustomScrollView(
@ -172,25 +139,14 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 16.0,
),
child: Text(
"backup_album_selection_page_selection_info",
style: context.textTheme.titleSmall,
).tr(),
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: Text("backup_album_selection_page_selection_info", style: context.textTheme.titleSmall).tr(),
),
// Selected Album Chips
// Selected Album Chips
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Wrap(
children: [
...buildSelectedAlbumNameChip(),
...buildExcludedAlbumNameChip(),
],
),
child: Wrap(children: [...buildSelectedAlbumNameChip(), ...buildExcludedAlbumNameChip()]),
),
SettingsSwitchListTile(
@ -198,21 +154,15 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
title: "sync_albums".tr(),
subtitle: "sync_upload_album_setting_subtitle".tr(),
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
titleStyle: context.textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.bold,
),
subtitleStyle: context.textTheme.labelLarge?.copyWith(
color: context.colorScheme.primary,
),
titleStyle: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.bold),
subtitleStyle: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.primary),
onChanged: handleSyncAlbumToggle,
),
ListTile(
title: Text(
"backup_album_selection_page_albums_device".tr(
namedArgs: {
'count': ref.watch(backupProvider).availableAlbums.length.toString(),
},
namedArgs: {'count': ref.watch(backupProvider).availableAlbums.length.toString()},
),
style: context.textTheme.titleSmall,
),
@ -220,46 +170,30 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
"backup_album_selection_page_albums_tap",
style: context.textTheme.labelLarge?.copyWith(
color: context.primaryColor,
),
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
).tr(),
),
trailing: IconButton(
splashRadius: 16,
icon: Icon(
Icons.info,
size: 20,
color: context.primaryColor,
),
icon: Icon(Icons.info, size: 20, color: context.primaryColor),
onPressed: () {
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10),
),
),
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
elevation: 5,
title: Text(
'backup_album_selection_page_selection_info',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: context.primaryColor,
),
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: context.primaryColor),
).tr(),
content: SingleChildScrollView(
child: ListBody(
children: [
const Text(
'backup_album_selection_page_assets_scatter',
style: TextStyle(
fontSize: 14,
),
style: TextStyle(fontSize: 14),
).tr(),
],
),

View file

@ -31,52 +31,44 @@ class BackupControllerPage extends HookConsumerWidget {
final didGetBackupInfo = useState(false);
bool hasExclusiveAccess = backupState.backupProgress != BackUpProgressEnum.inBackground;
bool shouldBackup = backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length == 0 ||
bool shouldBackup =
backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length == 0 ||
!hasExclusiveAccess
? false
: true;
useEffect(
() {
// Update the background settings information just to make sure we
// have the latest, since the platform channel will not update
// automatically
if (Platform.isIOS) {
ref.watch(iOSBackgroundSettingsProvider.notifier).refresh();
}
useEffect(() {
// Update the background settings information just to make sure we
// have the latest, since the platform channel will not update
// automatically
if (Platform.isIOS) {
ref.watch(iOSBackgroundSettingsProvider.notifier).refresh();
}
ref.watch(websocketProvider.notifier).stopListenToEvent('on_upload_success');
ref.watch(websocketProvider.notifier).stopListenToEvent('on_upload_success');
return () {
WakelockPlus.disable();
};
},
[],
);
return () {
WakelockPlus.disable();
};
}, []);
useEffect(
() {
if (backupState.backupProgress == BackUpProgressEnum.idle && !didGetBackupInfo.value) {
ref.watch(backupProvider.notifier).getBackupInfo();
didGetBackupInfo.value = true;
}
return null;
},
[backupState.backupProgress],
);
useEffect(() {
if (backupState.backupProgress == BackUpProgressEnum.idle && !didGetBackupInfo.value) {
ref.watch(backupProvider.notifier).getBackupInfo();
didGetBackupInfo.value = true;
}
return null;
}, [backupState.backupProgress]);
useEffect(
() {
if (backupState.backupProgress == BackUpProgressEnum.inProgress) {
WakelockPlus.enable();
} else {
WakelockPlus.disable();
}
useEffect(() {
if (backupState.backupProgress == BackUpProgressEnum.inProgress) {
WakelockPlus.enable();
} else {
WakelockPlus.disable();
}
return null;
},
[backupState.backupProgress],
);
return null;
}, [backupState.backupProgress]);
Widget buildSelectedAlbumName() {
var text = "backup_controller_page_backup_selected".tr();
@ -95,9 +87,7 @@ class BackupControllerPage extends HookConsumerWidget {
padding: const EdgeInsets.only(top: 8.0),
child: Text(
text.trim().substring(0, text.length - 2),
style: context.textTheme.labelLarge?.copyWith(
color: context.primaryColor,
),
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
),
);
} else {
@ -105,9 +95,7 @@ class BackupControllerPage extends HookConsumerWidget {
padding: const EdgeInsets.only(top: 8.0),
child: Text(
"backup_controller_page_none_selected".tr(),
style: context.textTheme.labelLarge?.copyWith(
color: context.primaryColor,
),
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
),
);
}
@ -126,9 +114,7 @@ class BackupControllerPage extends HookConsumerWidget {
padding: const EdgeInsets.only(top: 8.0),
child: Text(
text.trim().substring(0, text.length - 2),
style: context.textTheme.labelLarge?.copyWith(
color: Colors.red[300],
),
style: context.textTheme.labelLarge?.copyWith(color: Colors.red[300]),
),
);
} else {
@ -141,22 +127,14 @@ class BackupControllerPage extends HookConsumerWidget {
padding: const EdgeInsets.only(top: 8.0),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(
Radius.circular(20),
),
side: BorderSide(
color: context.colorScheme.outlineVariant,
width: 1,
),
borderRadius: const BorderRadius.all(Radius.circular(20)),
side: BorderSide(color: context.colorScheme.outlineVariant, width: 1),
),
elevation: 0,
borderOnForeground: false,
child: ListTile(
minVerticalPadding: 18,
title: Text(
"backup_controller_page_albums",
style: context.textTheme.titleMedium,
).tr(),
title: Text("backup_controller_page_albums", style: context.textTheme.titleMedium).tr(),
subtitle: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Column(
@ -164,9 +142,7 @@ class BackupControllerPage extends HookConsumerWidget {
children: [
Text(
"backup_controller_page_to_backup",
style: context.textTheme.bodyMedium?.copyWith(
color: context.colorScheme.onSurfaceSecondary,
),
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary),
).tr(),
buildSelectedAlbumName(),
buildExcludedAlbumName(),
@ -181,12 +157,7 @@ class BackupControllerPage extends HookConsumerWidget {
// waited until backup albums are stored in DB
ref.read(albumProvider.notifier).refreshDeviceAlbums();
},
child: const Text(
"select",
style: TextStyle(
fontWeight: FontWeight.bold,
),
).tr(),
child: const Text("select", style: TextStyle(fontWeight: FontWeight.bold)).tr(),
),
),
),
@ -202,11 +173,10 @@ class BackupControllerPage extends HookConsumerWidget {
Widget buildBackupButton() {
return Padding(
padding: const EdgeInsets.only(
top: 24,
),
padding: const EdgeInsets.only(top: 24),
child: Container(
child: backupState.backupProgress == BackUpProgressEnum.inProgress ||
child:
backupState.backupProgress == BackUpProgressEnum.inProgress ||
backupState.backupProgress == BackUpProgressEnum.manualInProgress
? ElevatedButton(
style: ElevatedButton.styleFrom(
@ -221,22 +191,13 @@ class BackupControllerPage extends HookConsumerWidget {
ref.read(backupProvider.notifier).cancelBackup();
}
},
child: const Text(
"cancel",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
).tr(),
child: const Text("cancel", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)).tr(),
)
: ElevatedButton(
onPressed: shouldBackup ? startBackup : null,
child: const Text(
"backup_controller_page_start_backup",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
).tr(),
),
),
@ -246,36 +207,28 @@ class BackupControllerPage extends HookConsumerWidget {
buildBackgroundBackupInfo() {
return const ListTile(
leading: Icon(Icons.info_outline_rounded),
title: Text(
"Background backup is currently running, cannot start manual backup",
),
title: Text("Background backup is currently running, cannot start manual backup"),
);
}
buildLoadingIndicator() {
return const Padding(
padding: EdgeInsets.only(top: 42.0),
child: Center(
child: CircularProgressIndicator(),
),
child: Center(child: CircularProgressIndicator()),
);
}
return Scaffold(
appBar: AppBar(
elevation: 0,
title: const Text(
"backup_controller_page_backup",
).tr(),
title: const Text("backup_controller_page_backup").tr(),
leading: IconButton(
onPressed: () {
ref.watch(websocketProvider.notifier).listenUploadEvent();
context.maybePop(true);
},
splashRadius: 24,
icon: const Icon(
Icons.arrow_back_ios_rounded,
),
icon: const Icon(Icons.arrow_back_ios_rounded),
),
actions: [
Padding(
@ -283,9 +236,7 @@ class BackupControllerPage extends HookConsumerWidget {
child: IconButton(
onPressed: () => context.pushRoute(const BackupOptionsRoute()),
splashRadius: 24,
icon: const Icon(
Icons.settings_outlined,
),
icon: const Icon(Icons.settings_outlined),
),
),
],
@ -325,10 +276,7 @@ class BackupControllerPage extends HookConsumerWidget {
if (!hasExclusiveAccess) buildBackgroundBackupInfo(),
buildBackupButton(),
]
: [
buildFolderSelectionTile(),
if (!didGetBackupInfo.value) buildLoadingIndicator(),
],
: [buildFolderSelectionTile(), if (!didGetBackupInfo.value) buildLoadingIndicator()],
),
),
],

View file

@ -15,9 +15,7 @@ class BackupOptionsPage extends StatelessWidget {
leading: IconButton(
onPressed: () => context.maybePop(true),
splashRadius: 24,
icon: const Icon(
Icons.arrow_back_ios_rounded,
),
icon: const Icon(Icons.arrow_back_ios_rounded),
),
),
body: const BackupSettings(),

View file

@ -51,35 +51,25 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
Widget build(BuildContext context) {
final selectedAlbum = ref
.watch(backupAlbumProvider)
.where(
(album) => album.backupSelection == BackupSelection.selected,
)
.where((album) => album.backupSelection == BackupSelection.selected)
.toList();
return Scaffold(
appBar: AppBar(
elevation: 0,
title: Text(
"backup_controller_page_backup".t(),
),
title: Text("backup_controller_page_backup".t()),
leading: IconButton(
onPressed: () {
context.maybePop(true);
},
splashRadius: 24,
icon: const Icon(
Icons.arrow_back_ios_rounded,
),
icon: const Icon(Icons.arrow_back_ios_rounded),
),
),
body: Stack(
children: [
Padding(
padding: const EdgeInsets.only(
left: 16.0,
right: 16,
bottom: 32,
),
padding: const EdgeInsets.only(left: 16.0, right: 16, bottom: 32),
child: ListView(
children: [
const SizedBox(height: 8),
@ -89,15 +79,10 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
const _BackupCard(),
const _RemainderCard(),
const Divider(),
BackupToggleButton(
onStart: () async => await startBackup(),
onStop: () async => await stopBackup(),
),
BackupToggleButton(onStart: () async => await startBackup(), onStop: () async => await stopBackup()),
TextButton.icon(
icon: const Icon(Icons.info_outline_rounded),
onPressed: () => context.pushRoute(
const DriftUploadDetailRoute(),
),
onPressed: () => context.pushRoute(const DriftUploadDetailRoute()),
label: Text("view_details".t(context: context)),
),
],
@ -119,9 +104,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
String text = "backup_controller_page_backup_selected".tr();
final albums = ref
.watch(backupAlbumProvider)
.where(
(album) => album.backupSelection == BackupSelection.selected,
)
.where((album) => album.backupSelection == BackupSelection.selected)
.toList();
if (albums.isNotEmpty) {
@ -137,9 +120,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
padding: const EdgeInsets.only(top: 8.0),
child: Text(
text.trim().substring(0, text.length - 2),
style: context.textTheme.labelLarge?.copyWith(
color: context.primaryColor,
),
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
),
);
} else {
@ -147,9 +128,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
padding: const EdgeInsets.only(top: 8.0),
child: Text(
"backup_controller_page_none_selected".tr(),
style: context.textTheme.labelLarge?.copyWith(
color: context.primaryColor,
),
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
),
);
}
@ -159,9 +138,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
String text = "backup_controller_page_excluded".tr();
final albums = ref
.watch(backupAlbumProvider)
.where(
(album) => album.backupSelection == BackupSelection.excluded,
)
.where((album) => album.backupSelection == BackupSelection.excluded)
.toList();
if (albums.isNotEmpty) {
@ -173,9 +150,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
padding: const EdgeInsets.only(top: 8.0),
child: Text(
text.trim().substring(0, text.length - 2),
style: context.textTheme.labelLarge?.copyWith(
color: Colors.red[300],
),
style: context.textTheme.labelLarge?.copyWith(color: Colors.red[300]),
),
);
} else {
@ -186,19 +161,13 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
return Card(
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(Radius.circular(20)),
side: BorderSide(
color: context.colorScheme.outlineVariant,
width: 1,
),
side: BorderSide(color: context.colorScheme.outlineVariant, width: 1),
),
elevation: 0,
borderOnForeground: false,
child: ListTile(
minVerticalPadding: 18,
title: Text(
"backup_controller_page_albums",
style: context.textTheme.titleMedium,
).tr(),
title: Text("backup_controller_page_albums", style: context.textTheme.titleMedium).tr(),
subtitle: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Column(
@ -206,9 +175,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
children: [
Text(
"backup_controller_page_to_backup",
style: context.textTheme.bodyMedium?.copyWith(
color: context.colorScheme.onSurfaceSecondary,
),
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary),
).tr(),
buildSelectedAlbumName(),
buildExcludedAlbumName(),
@ -224,12 +191,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
}
ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
},
child: const Text(
"select",
style: TextStyle(
fontWeight: FontWeight.bold,
),
).tr(),
child: const Text("select", style: TextStyle(fontWeight: FontWeight.bold)).tr(),
),
),
);

View file

@ -119,9 +119,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
focusNode: _searchFocusNode,
onChanged: (value) => setState(() => _searchQuery = value.trim()),
)
: const Text(
"backup_album_selection_page_select_albums",
).t(context: context),
: const Text("backup_album_selection_page_select_albums").t(context: context),
actions: [
if (!_isSearchMode)
IconButton(
@ -151,27 +149,20 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 16.0,
),
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: Text(
"backup_album_selection_page_selection_info",
style: context.textTheme.titleSmall,
).t(context: context),
),
// Selected Album Chips
// Selected Album Chips
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Wrap(
children: [
_SelectedAlbumNameChips(
selectedBackupAlbums: selectedBackupAlbums,
),
_ExcludedAlbumNameChips(
excludedBackupAlbums: excludedBackupAlbums,
),
_SelectedAlbumNameChips(selectedBackupAlbums: selectedBackupAlbums),
_ExcludedAlbumNameChips(excludedBackupAlbums: excludedBackupAlbums),
],
),
),
@ -181,48 +172,33 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
title: "sync_albums".t(context: context),
subtitle: "sync_upload_album_setting_subtitle".t(context: context),
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
titleStyle: context.textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.bold,
),
subtitleStyle: context.textTheme.labelLarge?.copyWith(
color: context.colorScheme.primary,
),
titleStyle: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.bold),
subtitleStyle: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.primary),
onChanged: handleSyncAlbumToggle,
),
ListTile(
title: Text(
"albums_on_device_count".t(
context: context,
args: {'count': albumCount.toString()},
),
"albums_on_device_count".t(context: context, args: {'count': albumCount.toString()}),
style: context.textTheme.titleSmall,
),
subtitle: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
"backup_album_selection_page_albums_tap",
style: context.textTheme.labelLarge?.copyWith(
color: context.primaryColor,
),
style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
).t(context: context),
),
trailing: IconButton(
splashRadius: 16,
icon: Icon(
Icons.info,
size: 20,
color: context.primaryColor,
),
icon: Icon(Icons.info, size: 20, color: context.primaryColor),
onPressed: () {
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
elevation: 5,
title: Text(
'backup_album_selection_page_selection_info',
@ -237,9 +213,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
children: [
const Text(
'backup_album_selection_page_assets_scatter',
style: TextStyle(
fontSize: 14,
),
style: TextStyle(fontSize: 14),
).t(context: context),
],
),
@ -252,25 +226,16 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
),
if (Platform.isAndroid)
_SelectAllButton(
filteredAlbums: filteredAlbums,
selectedBackupAlbums: selectedBackupAlbums,
),
_SelectAllButton(filteredAlbums: filteredAlbums, selectedBackupAlbums: selectedBackupAlbums),
],
),
),
SliverLayoutBuilder(
builder: (context, constraints) {
if (constraints.crossAxisExtent > 600) {
return _AlbumSelectionGrid(
filteredAlbums: filteredAlbums,
searchQuery: _searchQuery,
);
return _AlbumSelectionGrid(filteredAlbums: filteredAlbums, searchQuery: _searchQuery);
} else {
return _AlbumSelectionList(
filteredAlbums: filteredAlbums,
searchQuery: _searchQuery,
);
return _AlbumSelectionList(filteredAlbums: filteredAlbums, searchQuery: _searchQuery);
}
},
),
@ -285,10 +250,7 @@ class _AlbumSelectionList extends StatelessWidget {
final List<LocalAlbum> filteredAlbums;
final String searchQuery;
const _AlbumSelectionList({
required this.filteredAlbums,
required this.searchQuery,
});
const _AlbumSelectionList({required this.filteredAlbums, required this.searchQuery});
@override
Widget build(BuildContext context) {
@ -304,24 +266,15 @@ class _AlbumSelectionList extends StatelessWidget {
}
if (filteredAlbums.isEmpty) {
return const SliverToBoxAdapter(
child: Center(
child: CircularProgressIndicator(),
),
);
return const SliverToBoxAdapter(child: Center(child: CircularProgressIndicator()));
}
return SliverPadding(
padding: const EdgeInsets.symmetric(vertical: 12.0),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
((context, index) {
return DriftAlbumInfoListTile(
album: filteredAlbums[index],
);
}),
childCount: filteredAlbums.length,
),
delegate: SliverChildBuilderDelegate(((context, index) {
return DriftAlbumInfoListTile(album: filteredAlbums[index]);
}), childCount: filteredAlbums.length),
),
);
}
@ -331,10 +284,7 @@ class _AlbumSelectionGrid extends StatelessWidget {
final List<LocalAlbum> filteredAlbums;
final String searchQuery;
const _AlbumSelectionGrid({
required this.filteredAlbums,
required this.searchQuery,
});
const _AlbumSelectionGrid({required this.filteredAlbums, required this.searchQuery});
@override
Widget build(BuildContext context) {
@ -350,11 +300,7 @@ class _AlbumSelectionGrid extends StatelessWidget {
}
if (filteredAlbums.isEmpty) {
return const SliverToBoxAdapter(
child: Center(
child: CircularProgressIndicator(),
),
);
return const SliverToBoxAdapter(child: Center(child: CircularProgressIndicator()));
}
return SliverPadding(
@ -367,9 +313,7 @@ class _AlbumSelectionGrid extends StatelessWidget {
),
itemCount: filteredAlbums.length,
itemBuilder: ((context, index) {
return DriftAlbumInfoListTile(
album: filteredAlbums[index],
);
return DriftAlbumInfoListTile(album: filteredAlbums[index]);
}),
),
);
@ -379,9 +323,7 @@ class _AlbumSelectionGrid extends StatelessWidget {
class _SelectedAlbumNameChips extends ConsumerWidget {
final List<LocalAlbum> selectedBackupAlbums;
const _SelectedAlbumNameChips({
required this.selectedBackupAlbums,
});
const _SelectedAlbumNameChips({required this.selectedBackupAlbums});
@override
Widget build(BuildContext context, WidgetRef ref) {
@ -411,10 +353,7 @@ class _SelectedAlbumNameChips extends ConsumerWidget {
),
backgroundColor: context.primaryColor,
deleteIconColor: context.isDarkTheme ? Colors.black : Colors.white,
deleteIcon: const Icon(
Icons.cancel_rounded,
size: 15,
),
deleteIcon: const Icon(Icons.cancel_rounded, size: 15),
onDeleted: removeSelection,
),
),
@ -428,9 +367,7 @@ class _SelectedAlbumNameChips extends ConsumerWidget {
class _ExcludedAlbumNameChips extends ConsumerWidget {
final List<LocalAlbum> excludedBackupAlbums;
const _ExcludedAlbumNameChips({
required this.excludedBackupAlbums,
});
const _ExcludedAlbumNameChips({required this.excludedBackupAlbums});
@override
Widget build(BuildContext context, WidgetRef ref) {
@ -452,18 +389,11 @@ class _ExcludedAlbumNameChips extends ConsumerWidget {
child: Chip(
label: Text(
album.name,
style: TextStyle(
fontSize: 12,
color: context.scaffoldBackgroundColor,
fontWeight: FontWeight.bold,
),
style: TextStyle(fontSize: 12, color: context.scaffoldBackgroundColor, fontWeight: FontWeight.bold),
),
backgroundColor: Colors.red[300],
deleteIconColor: context.scaffoldBackgroundColor,
deleteIcon: const Icon(
Icons.cancel_rounded,
size: 15,
),
deleteIcon: const Icon(Icons.cancel_rounded, size: 15),
onDeleted: removeSelection,
),
),
@ -478,10 +408,7 @@ class _SelectAllButton extends ConsumerWidget {
final List<LocalAlbum> filteredAlbums;
final List<LocalAlbum> selectedBackupAlbums;
const _SelectAllButton({
required this.filteredAlbums,
required this.selectedBackupAlbums,
});
const _SelectAllButton({required this.filteredAlbums, required this.selectedBackupAlbums});
@override
Widget build(BuildContext context, WidgetRef ref) {
@ -505,13 +432,9 @@ class _SelectAllButton extends ConsumerWidget {
icon: const Icon(Icons.select_all),
label: AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
child: Text(
"select_all".t(context: context),
),
),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12.0),
child: Text("select_all".t(context: context)),
),
style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12.0)),
),
),
const SizedBox(width: 8.0),
@ -528,9 +451,7 @@ class _SelectAllButton extends ConsumerWidget {
: null,
icon: const Icon(Icons.deselect),
label: Text('deselect_all'.t(context: context)),
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12.0),
),
style: OutlinedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12.0)),
),
),
],

View file

@ -16,9 +16,7 @@ class DriftUploadDetailPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final uploadItems = ref.watch(
driftBackupProvider.select((state) => state.uploadItems),
);
final uploadItems = ref.watch(driftBackupProvider.select((state) => state.uploadItems));
return Scaffold(
appBar: AppBar(
@ -36,26 +34,18 @@ class DriftUploadDetailPage extends ConsumerWidget {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.cloud_off_rounded,
size: 80,
color: context.colorScheme.onSurface.withValues(alpha: 0.3),
),
Icon(Icons.cloud_off_rounded, size: 80, color: context.colorScheme.onSurface.withValues(alpha: 0.3)),
const SizedBox(height: 16),
Text(
"no_uploads_in_progress".t(context: context),
style: context.textTheme.titleMedium?.copyWith(
color: context.colorScheme.onSurface.withValues(alpha: 0.6),
),
style: context.textTheme.titleMedium?.copyWith(color: context.colorScheme.onSurface.withValues(alpha: 0.6)),
),
],
),
);
}
Widget _buildUploadList(
Map<String, DriftUploadStatus> uploadItems,
) {
Widget _buildUploadList(Map<String, DriftUploadStatus> uploadItems) {
return ListView.separated(
addAutomaticKeepAlives: true,
padding: const EdgeInsets.all(16),
@ -68,10 +58,7 @@ class DriftUploadDetailPage extends ConsumerWidget {
);
}
Widget _buildUploadCard(
BuildContext context,
DriftUploadStatus item,
) {
Widget _buildUploadCard(BuildContext context, DriftUploadStatus item) {
final isCompleted = item.progress >= 1.0;
final double progressPercentage = (item.progress * 100).clamp(0, 100);
@ -79,19 +66,12 @@ class DriftUploadDetailPage extends ConsumerWidget {
elevation: 0,
color: item.isFailed != null ? context.colorScheme.errorContainer : context.colorScheme.surfaceContainer,
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(
Radius.circular(16),
),
side: BorderSide(
color: context.colorScheme.outline.withValues(alpha: 0.1),
width: 1,
),
borderRadius: const BorderRadius.all(Radius.circular(16)),
side: BorderSide(color: context.colorScheme.outline.withValues(alpha: 0.1), width: 1),
),
child: InkWell(
onTap: () => _showFileDetailDialog(context, item),
borderRadius: const BorderRadius.all(
Radius.circular(16),
),
borderRadius: const BorderRadius.all(Radius.circular(16)),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
@ -105,9 +85,7 @@ class DriftUploadDetailPage extends ConsumerWidget {
children: [
Text(
path.basename(item.filename),
style: context.textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.w600,
),
style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
@ -166,18 +144,11 @@ class DriftUploadDetailPage extends ConsumerWidget {
),
),
if (isCompleted)
Icon(
Icons.check_circle_rounded,
size: 28,
color: context.colorScheme.primary,
)
Icon(Icons.check_circle_rounded, size: 28, color: context.colorScheme.primary)
else
Text(
percentage.toStringAsFixed(0),
style: context.textTheme.labelSmall?.copyWith(
fontWeight: FontWeight.bold,
fontSize: 10,
),
style: context.textTheme.labelSmall?.copyWith(fontWeight: FontWeight.bold, fontSize: 10),
),
],
),
@ -192,10 +163,7 @@ class DriftUploadDetailPage extends ConsumerWidget {
);
}
Future<void> _showFileDetailDialog(
BuildContext context,
DriftUploadStatus item,
) async {
Future<void> _showFileDetailDialog(BuildContext context, DriftUploadStatus item) async {
showDialog(
context: context,
builder: (context) => FileDetailDialog(uploadStatus: item),
@ -206,10 +174,7 @@ class DriftUploadDetailPage extends ConsumerWidget {
class FileDetailDialog extends ConsumerWidget {
final DriftUploadStatus uploadStatus;
const FileDetailDialog({
super.key,
required this.uploadStatus,
});
const FileDetailDialog({super.key, required this.uploadStatus});
@override
Widget build(BuildContext context, WidgetRef ref) {
@ -217,29 +182,17 @@ class FileDetailDialog extends ConsumerWidget {
insetPadding: const EdgeInsets.all(20),
backgroundColor: context.colorScheme.surfaceContainerLow,
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(
Radius.circular(16),
),
side: BorderSide(
color: context.colorScheme.outline.withValues(alpha: 0.2),
width: 1,
),
borderRadius: const BorderRadius.all(Radius.circular(16)),
side: BorderSide(color: context.colorScheme.outline.withValues(alpha: 0.2), width: 1),
),
title: Row(
children: [
Icon(
Icons.info_outline,
color: context.primaryColor,
size: 24,
),
Icon(Icons.info_outline, color: context.primaryColor, size: 24),
const SizedBox(width: 8),
Expanded(
child: Text(
"details".t(context: context),
style: context.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
color: context.primaryColor,
),
style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600, color: context.primaryColor),
),
),
],
@ -250,10 +203,7 @@ class FileDetailDialog extends ConsumerWidget {
future: _getAssetDetails(ref, uploadStatus.taskId),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const SizedBox(
height: 200,
child: Center(child: CircularProgressIndicator()),
);
return const SizedBox(height: 200, child: Center(child: CircularProgressIndicator()));
}
final asset = snapshot.data;
@ -270,18 +220,11 @@ class FileDetailDialog extends ConsumerWidget {
width: 128,
height: 128,
decoration: BoxDecoration(
border: Border.all(
color: context.colorScheme.outline.withValues(alpha: 0.2),
width: 1,
),
border: Border.all(color: context.colorScheme.outline.withValues(alpha: 0.2), width: 1),
borderRadius: const BorderRadius.all(Radius.circular(12)),
),
child: asset != null
? Thumbnail(
asset: asset,
size: const Size(512, 512),
fit: BoxFit.cover,
)
? Thumbnail(asset: asset, size: const Size(512, 512), fit: BoxFit.cover)
: null,
),
),
@ -289,44 +232,14 @@ class FileDetailDialog extends ConsumerWidget {
const SizedBox(height: 24),
if (asset != null) ...[
_buildInfoSection(context, [
_buildInfoRow(
context,
"Filename",
path.basename(uploadStatus.filename),
),
_buildInfoRow(
context,
"Local ID",
asset.id,
),
_buildInfoRow(
context,
"File Size",
formatHumanReadableBytes(uploadStatus.fileSize, 2),
),
_buildInfoRow(context, "Filename", path.basename(uploadStatus.filename)),
_buildInfoRow(context, "Local ID", asset.id),
_buildInfoRow(context, "File Size", formatHumanReadableBytes(uploadStatus.fileSize, 2)),
if (asset.width != null) _buildInfoRow(context, "Width", "${asset.width}px"),
if (asset.height != null)
_buildInfoRow(
context,
"Height",
"${asset.height}px",
),
_buildInfoRow(
context,
"Created At",
asset.createdAt.toString(),
),
_buildInfoRow(
context,
"Updated At",
asset.updatedAt.toString(),
),
if (asset.checksum != null)
_buildInfoRow(
context,
"Checksum",
asset.checksum!,
),
if (asset.height != null) _buildInfoRow(context, "Height", "${asset.height}px"),
_buildInfoRow(context, "Created At", asset.createdAt.toString()),
_buildInfoRow(context, "Updated At", asset.updatedAt.toString()),
if (asset.checksum != null) _buildInfoRow(context, "Checksum", asset.checksum!),
]),
],
],
@ -340,39 +253,23 @@ class FileDetailDialog extends ConsumerWidget {
onPressed: () => Navigator.of(context).pop(),
child: Text(
"close".t(),
style: TextStyle(
fontWeight: FontWeight.w600,
color: context.primaryColor,
),
style: TextStyle(fontWeight: FontWeight.w600, color: context.primaryColor),
),
),
],
);
}
Widget _buildInfoSection(
BuildContext context,
List<Widget> children,
) {
Widget _buildInfoSection(BuildContext context, List<Widget> children) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: context.colorScheme.surfaceContainer,
borderRadius: const BorderRadius.all(
Radius.circular(12),
),
border: Border.all(
color: context.colorScheme.outline.withValues(alpha: 0.1),
width: 1,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
...children,
],
borderRadius: const BorderRadius.all(Radius.circular(12)),
border: Border.all(color: context.colorScheme.outline.withValues(alpha: 0.1), width: 1),
),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [...children]),
);
}
@ -405,10 +302,7 @@ class FileDetailDialog extends ConsumerWidget {
);
}
Future<LocalAsset?> _getAssetDetails(
WidgetRef ref,
String localAssetId,
) async {
Future<LocalAsset?> _getAssetDetails(WidgetRef ref, String localAssetId) async {
try {
final repository = ref.read(localAssetRepository);
return await repository.getById(localAssetId);

View file

@ -25,9 +25,7 @@ class FailedBackupStatusPage extends HookConsumerWidget {
context.maybePop(true);
},
splashRadius: 24,
icon: const Icon(
Icons.arrow_back_ios_rounded,
),
icon: const Icon(Icons.arrow_back_ios_rounded),
),
),
body: ListView.builder(
@ -37,19 +35,13 @@ class FailedBackupStatusPage extends HookConsumerWidget {
var errorAsset = errorBackupList.elementAt(index);
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 4,
),
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 4),
child: Card(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(15), // if you need this
),
side: BorderSide(
color: Colors.black12,
width: 1,
),
side: BorderSide(color: Colors.black12, width: 1),
),
elevation: 0,
child: Row(
@ -57,12 +49,7 @@ class FailedBackupStatusPage extends HookConsumerWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 100,
minHeight: 100,
maxWidth: 100,
maxHeight: 150,
),
constraints: const BoxConstraints(minWidth: 100, minHeight: 100, maxWidth: 100, maxHeight: 150),
child: ClipRRect(
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(15),
@ -71,11 +58,7 @@ class FailedBackupStatusPage extends HookConsumerWidget {
clipBehavior: Clip.hardEdge,
child: Image(
fit: BoxFit.cover,
image: ImmichLocalThumbnailProvider(
asset: errorAsset.asset,
height: 512,
width: 512,
),
image: ImmichLocalThumbnailProvider(asset: errorAsset.asset, height: 512, width: 512),
),
),
),
@ -91,20 +74,14 @@ class FailedBackupStatusPage extends HookConsumerWidget {
children: [
Text(
DateFormat.yMMMMd().format(
DateTime.parse(
errorAsset.fileCreatedAt.toString(),
).toLocal(),
DateTime.parse(errorAsset.fileCreatedAt.toString()).toLocal(),
),
style: TextStyle(
fontWeight: FontWeight.w600,
color: context.isDarkTheme ? Colors.white70 : Colors.grey[800],
),
),
Icon(
Icons.error,
color: Colors.red.withAlpha(200),
size: 18,
),
Icon(Icons.error, color: Colors.red.withAlpha(200), size: 18),
],
),
Padding(
@ -113,10 +90,7 @@ class FailedBackupStatusPage extends HookConsumerWidget {
errorAsset.fileName,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.bold,
color: context.primaryColor,
),
style: TextStyle(fontWeight: FontWeight.bold, color: context.primaryColor),
),
),
Text(