chore: bump line length to 120 (#20191)

This commit is contained in:
shenlong
2025-07-25 08:07:22 +05:30
committed by GitHub
parent 977c9b96ba
commit ad65e9011a
517 changed files with 4520 additions and 9514 deletions
@@ -21,8 +21,7 @@ class AlbumAdditionalSharedUserSelectionPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final AsyncValue<List<UserDto>> suggestedShareUsers =
ref.watch(otherUsersProvider);
final AsyncValue<List<UserDto>> suggestedShareUsers = ref.watch(otherUsersProvider);
final sharedUsersList = useState<Set<UserDto>>({});
addNewUsersHandler() {
@@ -138,8 +137,7 @@ class AlbumAdditionalSharedUserSelectionPage extends HookConsumerWidget {
),
actions: [
TextButton(
onPressed:
sharedUsersList.value.isEmpty ? null : addNewUsersHandler,
onPressed: sharedUsersList.value.isEmpty ? null : addNewUsersHandler,
child: const Text(
"add",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
@@ -65,10 +65,8 @@ class AlbumAssetSelectionPage extends HookConsumerWidget {
if (selected.value.isNotEmpty || canDeselect)
TextButton(
onPressed: () {
var payload =
AssetSelectionPageResult(selectedAssets: selected.value);
AutoRouter.of(context)
.popForced<AssetSelectionPageResult>(payload);
var payload = AssetSelectionPageResult(selectedAssets: selected.value);
AutoRouter.of(context).popForced<AssetSelectionPageResult>(payload);
},
child: Text(
canDeselect ? "done" : "add",
+3 -7
View File
@@ -42,16 +42,12 @@ class AlbumDateRange extends ConsumerWidget {
@pragma('vm:prefer-inline')
String _getDateRangeText(DateTime startDate, DateTime endDate) {
if (startDate.day == endDate.day &&
startDate.month == endDate.month &&
startDate.year == endDate.year) {
if (startDate.day == endDate.day && startDate.month == endDate.month && startDate.year == endDate.year) {
return DateFormat.yMMMd().format(startDate);
}
final String startDateText = (startDate.year == endDate.year
? DateFormat.MMMd()
: DateFormat.yMMMd())
.format(startDate);
final String startDateText =
(startDate.year == endDate.year ? DateFormat.MMMd() : DateFormat.yMMMd()).format(startDate);
final String endDateText = DateFormat.yMMMd().format(endDate);
return "$startDateText - $endDateText";
}
+10 -25
View File
@@ -7,8 +7,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.dart'
as entity;
import 'package:immich_mobile/infrastructure/entities/user.entity.dart' as entity;
import 'package:immich_mobile/providers/album/album.provider.dart';
import 'package:immich_mobile/providers/album/current_album.provider.dart';
import 'package:immich_mobile/providers/auth.provider.dart';
@@ -28,8 +27,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
return const SizedBox();
}
final sharedUsers =
useState(album.sharedUsers.map((u) => u.toDto()).toList());
final sharedUsers = useState(album.sharedUsers.map((u) => u.toDto()).toList());
final owner = album.owner.value;
final userId = ref.watch(authProvider).userId;
final activityEnabled = useState(album.activityEnabled);
@@ -50,8 +48,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
isProcessing.value = true;
try {
final isSuccess =
await ref.read(albumProvider.notifier).leaveAlbum(album);
final isSuccess = await ref.read(albumProvider.notifier).leaveAlbum(album);
if (isSuccess) {
context.navigateTo(
@@ -99,8 +96,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
actions = [
ListTile(
leading: const Icon(Icons.person_remove_rounded),
title: const Text("shared_album_section_people_action_remove_user")
.tr(),
title: const Text("shared_album_section_people_action_remove_user").tr(),
onTap: () => removeUserFromAlbum(user),
),
];
@@ -126,9 +122,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
buildOwnerInfo() {
return ListTile(
leading: owner != null
? UserCircleAvatar(user: owner.toDto())
: const SizedBox(),
leading: owner != null ? UserCircleAvatar(user: owner.toDto()) : const SizedBox(),
title: Text(
album.owner.value?.name ?? "",
style: const TextStyle(
@@ -170,12 +164,8 @@ class AlbumOptionsPage extends HookConsumerWidget {
color: context.colorScheme.onSurfaceSecondary,
),
),
trailing: userId == user.id || isOwner
? const Icon(Icons.more_horiz_rounded)
: const SizedBox(),
onTap: userId == user.id || isOwner
? () => handleUserClick(user)
: null,
trailing: userId == user.id || isOwner ? const Icon(Icons.more_horiz_rounded) : const SizedBox(),
onTap: userId == user.id || isOwner ? () => handleUserClick(user) : null,
);
},
);
@@ -204,20 +194,15 @@ class AlbumOptionsPage extends HookConsumerWidget {
value: activityEnabled.value,
onChanged: (bool value) async {
activityEnabled.value = value;
if (await ref
.read(albumProvider.notifier)
.setActivitystatus(album, value)) {
if (await ref.read(albumProvider.notifier).setActivitystatus(album, value)) {
album.activityEnabled = value;
}
},
activeColor: activityEnabled.value
? context.primaryColor
: context.themeData.disabledColor,
activeColor: activityEnabled.value ? context.primaryColor : context.themeData.disabledColor,
dense: true,
title: Text(
"comments_and_likes",
style: context.textTheme.titleMedium
?.copyWith(fontWeight: FontWeight.w500),
style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w500),
).tr(),
subtitle: Text(
"let_others_respond",
+3 -7
View File
@@ -48,8 +48,7 @@ class AlbumViewer extends HookConsumerWidget {
);
Future<bool> onRemoveFromAlbumPressed(Iterable<Asset> assets) async {
final bool isSuccess =
await ref.read(albumProvider.notifier).removeAsset(album, assets);
final bool isSuccess = await ref.read(albumProvider.notifier).removeAsset(album, assets);
if (!isSuccess) {
ImmichToast.show(
@@ -65,8 +64,7 @@ class AlbumViewer extends HookConsumerWidget {
/// Find out if the assets in album exist on the device
/// If they exist, add to selected asset state to show they are already selected.
void onAddPhotosPressed() async {
AssetSelectionPageResult? returnPayload =
await context.pushRoute<AssetSelectionPageResult?>(
AssetSelectionPageResult? returnPayload = await context.pushRoute<AssetSelectionPageResult?>(
AlbumAssetSelectionRoute(
existingAssets: album.assets,
canDeselect: false,
@@ -77,9 +75,7 @@ class AlbumViewer extends HookConsumerWidget {
// Check if there is new assets add
isProcessing.value = true;
await ref
.watch(albumProvider.notifier)
.addAssets(album, returnPayload.selectedAssets);
await ref.watch(albumProvider.notifier).addAssets(album, returnPayload.selectedAssets);
isProcessing.value = false;
}
+14 -31
View File
@@ -26,8 +26,7 @@ class AlbumsPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final albums =
ref.watch(albumProvider).where((album) => album.isRemote).toList();
final albums = ref.watch(albumProvider).where((album) => album.isRemote).toList();
final albumSortOption = ref.watch(albumSortByOptionsProvider);
final albumSortIsReverse = ref.watch(albumSortOrderProvider);
final sorted = albumSortOption.sortFn(albums, albumSortIsReverse);
@@ -131,8 +130,7 @@ class AlbumsPage extends HookConsumerWidget {
)
: null,
controller: searchController,
onChanged: (_) =>
onSearch(searchController.text, filterMode.value),
onChanged: (_) => onSearch(searchController.text, filterMode.value),
focusNode: searchFocusNode,
onTapOutside: (_) => searchFocusNode.unfocus(),
),
@@ -180,9 +178,7 @@ class AlbumsPage extends HookConsumerWidget {
const SortButton(),
IconButton(
icon: Icon(
isGrid.value
? Icons.view_list_outlined
: Icons.grid_view_outlined,
isGrid.value ? Icons.view_list_outlined : Icons.grid_view_outlined,
size: 24,
),
onPressed: toggleViewMode,
@@ -196,8 +192,7 @@ class AlbumsPage extends HookConsumerWidget {
? GridView.builder(
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
gridDelegate:
const SliverGridDelegateWithMaxCrossAxisExtent(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 250,
mainAxisSpacing: 12,
crossAxisSpacing: 12,
@@ -244,10 +239,8 @@ class AlbumsPage extends HookConsumerWidget {
},
) : 'owned'.t(context: context)}',
overflow: TextOverflow.ellipsis,
style:
context.textTheme.bodyMedium?.copyWith(
color: context
.colorScheme.onSurfaceSecondary,
style: context.textTheme.bodyMedium?.copyWith(
color: context.colorScheme.onSurfaceSecondary,
),
)
: null,
@@ -316,9 +309,7 @@ class QuickFilterButton extends StatelessWidget {
child: Text(
label,
style: TextStyle(
color: isSelected
? context.colorScheme.onPrimary
: context.colorScheme.onSurface,
color: isSelected ? context.colorScheme.onPrimary : context.colorScheme.onSurface,
fontSize: 14,
),
),
@@ -356,28 +347,22 @@ class SortButton extends ConsumerWidget {
? albumSortIsReverse
? Icon(
Icons.keyboard_arrow_down,
color: albumSortOption == mode
? context.colorScheme.onPrimary
: context.colorScheme.onSurface,
color:
albumSortOption == mode ? context.colorScheme.onPrimary : context.colorScheme.onSurface,
)
: Icon(
Icons.keyboard_arrow_up_rounded,
color: albumSortOption == mode
? context.colorScheme.onPrimary
: context.colorScheme.onSurface,
color:
albumSortOption == mode ? context.colorScheme.onPrimary : context.colorScheme.onSurface,
)
: const Icon(Icons.abc, color: Colors.transparent),
onPressed: () {
final selected = albumSortOption == mode;
// Switch direction
if (selected) {
ref
.read(albumSortOrderProvider.notifier)
.changeSortDirection(!albumSortIsReverse);
ref.read(albumSortOrderProvider.notifier).changeSortDirection(!albumSortIsReverse);
} else {
ref
.read(albumSortByOptionsProvider.notifier)
.changeSortMode(mode);
ref.read(albumSortByOptionsProvider.notifier).changeSortMode(mode);
}
},
style: ButtonStyle(
@@ -385,9 +370,7 @@ class SortButton extends ConsumerWidget {
const EdgeInsets.fromLTRB(16, 16, 32, 16),
),
backgroundColor: WidgetStateProperty.all(
albumSortOption == mode
? context.colorScheme.primary
: Colors.transparent,
albumSortOption == mode ? context.colorScheme.primary : Colors.transparent,
),
shape: WidgetStateProperty.all(
const RoundedRectangleBorder(
@@ -19,9 +19,7 @@ class AlbumPreviewPage extends HookConsumerWidget {
final assets = useState<List<Asset>>([]);
getAssetsInAlbum() async {
assets.value = await ref
.read(albumMediaRepositoryProvider)
.getAssets(album.localId!);
assets.value = await ref.read(albumMediaRepositoryProvider).getAssets(album.localId!);
}
useEffect(
@@ -19,8 +19,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final selectedBackupAlbums = ref.watch(backupProvider).selectedBackupAlbums;
final excludedBackupAlbums = ref.watch(backupProvider).excludedBackupAlbums;
final enableSyncUploadAlbum =
useAppSettingsState(AppSettingsEnum.syncAlbums);
final enableSyncUploadAlbum = useAppSettingsState(AppSettingsEnum.syncAlbums);
final isDarkTheme = context.isDarkTheme;
final albums = ref.watch(backupProvider).availableAlbums;
@@ -85,8 +84,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
buildSelectedAlbumNameChip() {
return selectedBackupAlbums.map((album) {
void removeSelection() =>
ref.read(backupProvider.notifier).removeAlbumForBackup(album);
void removeSelection() => ref.read(backupProvider.notifier).removeAlbumForBackup(album);
return Padding(
padding: const EdgeInsets.only(right: 8.0),
@@ -117,9 +115,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
buildExcludedAlbumNameChip() {
return excludedBackupAlbums.map((album) {
void removeSelection() {
ref
.watch(backupProvider.notifier)
.removeExcludedAlbumForBackup(album);
ref.watch(backupProvider.notifier).removeExcludedAlbumForBackup(album);
}
return GestureDetector(
@@ -215,11 +211,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
title: Text(
"backup_album_selection_page_albums_device".tr(
namedArgs: {
'count': ref
.watch(backupProvider)
.availableAlbums
.length
.toString(),
'count': ref.watch(backupProvider).availableAlbums.length.toString(),
},
),
style: context.textTheme.titleSmall,
@@ -30,11 +30,8 @@ class BackupControllerPage extends HookConsumerWidget {
final hasAnyAlbum = backupState.selectedBackupAlbums.isNotEmpty;
final didGetBackupInfo = useState(false);
bool hasExclusiveAccess =
backupState.backupProgress != BackUpProgressEnum.inBackground;
bool shouldBackup = backupState.allUniqueAssets.length -
backupState.selectedAlbumsBackupAssetsIds.length ==
0 ||
bool hasExclusiveAccess = backupState.backupProgress != BackUpProgressEnum.inBackground;
bool shouldBackup = backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length == 0 ||
!hasExclusiveAccess
? false
: true;
@@ -48,9 +45,7 @@ class BackupControllerPage extends HookConsumerWidget {
ref.watch(iOSBackgroundSettingsProvider.notifier).refresh();
}
ref
.watch(websocketProvider.notifier)
.stopListenToEvent('on_upload_success');
ref.watch(websocketProvider.notifier).stopListenToEvent('on_upload_success');
return () {
WakelockPlus.disable();
@@ -61,8 +56,7 @@ class BackupControllerPage extends HookConsumerWidget {
useEffect(
() {
if (backupState.backupProgress == BackUpProgressEnum.idle &&
!didGetBackupInfo.value) {
if (backupState.backupProgress == BackUpProgressEnum.idle && !didGetBackupInfo.value) {
ref.watch(backupProvider.notifier).getBackupInfo();
didGetBackupInfo.value = true;
}
@@ -183,9 +177,7 @@ class BackupControllerPage extends HookConsumerWidget {
onPressed: () async {
await context.pushRoute(const BackupAlbumSelectionRoute());
// waited until returning from selection
await ref
.read(backupProvider.notifier)
.backupAlbumSelectionDone();
await ref.read(backupProvider.notifier).backupAlbumSelectionDone();
// waited until backup albums are stored in DB
ref.read(albumProvider.notifier).refreshDeviceAlbums();
},
@@ -203,8 +195,7 @@ class BackupControllerPage extends HookConsumerWidget {
void startBackup() {
ref.watch(errorBackupListProvider.notifier).empty();
if (ref.watch(backupProvider).backupProgress !=
BackUpProgressEnum.inBackground) {
if (ref.watch(backupProvider).backupProgress != BackUpProgressEnum.inBackground) {
ref.watch(backupProvider.notifier).startBackupProcess();
}
}
@@ -216,8 +207,7 @@ class BackupControllerPage extends HookConsumerWidget {
),
child: Container(
child: backupState.backupProgress == BackUpProgressEnum.inProgress ||
backupState.backupProgress ==
BackUpProgressEnum.manualInProgress
backupState.backupProgress == BackUpProgressEnum.manualInProgress
? ElevatedButton(
style: ElevatedButton.styleFrom(
foregroundColor: Colors.grey[50],
@@ -225,8 +215,7 @@ class BackupControllerPage extends HookConsumerWidget {
// padding: const EdgeInsets.all(14),
),
onPressed: () {
if (backupState.backupProgress ==
BackUpProgressEnum.manualInProgress) {
if (backupState.backupProgress == BackUpProgressEnum.manualInProgress) {
ref.read(manualUploadProvider.notifier).cancelBackup();
} else {
ref.read(backupProvider.notifier).cancelBackup();
+5 -12
View File
@@ -39,9 +39,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
return;
}
await ref
.read(driftBackupProvider.notifier)
.getBackupStatus(currentUser.id);
await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
await ref.read(driftBackupProvider.notifier).backup(currentUser.id);
}
@@ -224,9 +222,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
if (currentUser == null) {
return;
}
ref
.read(driftBackupProvider.notifier)
.getBackupStatus(currentUser.id);
ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
},
child: const Text(
"select",
@@ -245,8 +241,7 @@ class _TotalCard extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final totalCount =
ref.watch(driftBackupProvider.select((p) => p.totalCount));
final totalCount = ref.watch(driftBackupProvider.select((p) => p.totalCount));
return BackupInfoCard(
title: "total".tr(),
@@ -261,8 +256,7 @@ class _BackupCard extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final backupCount =
ref.watch(driftBackupProvider.select((p) => p.backupCount));
final backupCount = ref.watch(driftBackupProvider.select((p) => p.backupCount));
return BackupInfoCard(
title: "backup_controller_page_backup".tr(),
@@ -277,8 +271,7 @@ class _RemainderCard extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final remainderCount =
ref.watch(driftBackupProvider.select((p) => p.remainderCount));
final remainderCount = ref.watch(driftBackupProvider.select((p) => p.remainderCount));
return BackupInfoCard(
title: "backup_controller_page_remainder".tr(),
subtitle: "backup_controller_page_remainder_sub".tr(),
@@ -21,12 +21,10 @@ class DriftBackupAlbumSelectionPage extends ConsumerStatefulWidget {
const DriftBackupAlbumSelectionPage({super.key});
@override
ConsumerState<DriftBackupAlbumSelectionPage> createState() =>
_DriftBackupAlbumSelectionPageState();
ConsumerState<DriftBackupAlbumSelectionPage> createState() => _DriftBackupAlbumSelectionPageState();
}
class _DriftBackupAlbumSelectionPageState
extends ConsumerState<DriftBackupAlbumSelectionPage> {
class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbumSelectionPage> {
String _searchQuery = '';
bool _isSearchMode = false;
int _initialTotalAssetCount = 0;
@@ -42,13 +40,10 @@ class _DriftBackupAlbumSelectionPageState
_searchController = TextEditingController();
_searchFocusNode = FocusNode();
_enableSyncUploadAlbum.value = ref
.read(appSettingsServiceProvider)
.getSetting(AppSettingsEnum.syncAlbums);
_enableSyncUploadAlbum.value = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.syncAlbums);
ref.read(backupAlbumProvider.notifier).getAll();
_initialTotalAssetCount =
ref.read(driftBackupProvider.select((p) => p.totalCount));
_initialTotalAssetCount = ref.read(driftBackupProvider.select((p) => p.totalCount));
}
@override
@@ -69,12 +64,8 @@ class _DriftBackupAlbumSelectionPageState
return album.name.toLowerCase().contains(_searchQuery.toLowerCase());
}).toList();
final selectedBackupAlbums = albums
.where((album) => album.backupSelection == BackupSelection.selected)
.toList();
final excludedBackupAlbums = albums
.where((album) => album.backupSelection == BackupSelection.excluded)
.toList();
final selectedBackupAlbums = albums.where((album) => album.backupSelection == BackupSelection.selected).toList();
final excludedBackupAlbums = albums.where((album) => album.backupSelection == BackupSelection.excluded).toList();
handleSyncAlbumToggle(bool isEnable) async {
if (isEnable) {
@@ -98,16 +89,11 @@ class _DriftBackupAlbumSelectionPageState
return;
}
await ref
.read(driftBackupProvider.notifier)
.getBackupStatus(currentUser.id);
final currentTotalAssetCount =
ref.read(driftBackupProvider.select((p) => p.totalCount));
await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
final currentTotalAssetCount = ref.read(driftBackupProvider.select((p) => p.totalCount));
if (currentTotalAssetCount != _initialTotalAssetCount) {
final isBackupEnabled = ref
.read(appSettingsServiceProvider)
.getSetting(AppSettingsEnum.enableBackup);
final isBackupEnabled = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup);
if (!isBackupEnabled) {
return;
@@ -132,8 +118,7 @@ class _DriftBackupAlbumSelectionPageState
autofocus: true,
controller: _searchController,
focusNode: _searchFocusNode,
onChanged: (value) =>
setState(() => _searchQuery = value.trim()),
onChanged: (value) => setState(() => _searchQuery = value.trim()),
)
: const Text(
"backup_album_selection_page_select_albums",
@@ -195,8 +180,7 @@ class _DriftBackupAlbumSelectionPageState
SettingsSwitchListTile(
valueNotifier: _enableSyncUploadAlbum,
title: "sync_albums".t(context: context),
subtitle: "sync_upload_album_setting_subtitle"
.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,
@@ -238,8 +222,7 @@ class _DriftBackupAlbumSelectionPageState
builder: (BuildContext context) {
return AlertDialog(
shape: const RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(10)),
borderRadius: BorderRadius.all(Radius.circular(10)),
),
elevation: 5,
title: Text(
@@ -428,8 +411,7 @@ class _SelectedAlbumNameChips extends ConsumerWidget {
),
),
backgroundColor: context.primaryColor,
deleteIconColor:
context.isDarkTheme ? Colors.black : Colors.white,
deleteIconColor: context.isDarkTheme ? Colors.black : Colors.white,
deleteIcon: const Icon(
Icons.cancel_rounded,
size: 15,
@@ -504,9 +486,7 @@ class _SelectAllButton extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final canSelectAll = filteredAlbums
.where((album) => album.backupSelection != BackupSelection.selected)
.isNotEmpty;
final canSelectAll = filteredAlbums.where((album) => album.backupSelection != BackupSelection.selected).isNotEmpty;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
@@ -518,9 +498,7 @@ class _SelectAllButton extends ConsumerWidget {
? () {
for (final album in filteredAlbums) {
if (album.backupSelection != BackupSelection.selected) {
ref
.read(backupAlbumProvider.notifier)
.selectAlbum(album);
ref.read(backupAlbumProvider.notifier).selectAlbum(album);
}
}
}
@@ -544,9 +522,7 @@ class _SelectAllButton extends ConsumerWidget {
? () {
for (final album in filteredAlbums) {
if (album.backupSelection == BackupSelection.selected) {
ref
.read(backupAlbumProvider.notifier)
.deselectAlbum(album);
ref.read(backupAlbumProvider.notifier).deselectAlbum(album);
}
}
}
@@ -27,9 +27,7 @@ class DriftUploadDetailPage extends ConsumerWidget {
elevation: 0,
scrolledUnderElevation: 1,
),
body: uploadItems.isEmpty
? _buildEmptyState(context)
: _buildUploadList(uploadItems),
body: uploadItems.isEmpty ? _buildEmptyState(context) : _buildUploadList(uploadItems),
);
}
@@ -79,9 +77,7 @@ class DriftUploadDetailPage extends ConsumerWidget {
return Card(
elevation: 0,
color: item.isFailed != null
? context.colorScheme.errorContainer
: context.colorScheme.surfaceContainer,
color: item.isFailed != null ? context.colorScheme.errorContainer : context.colorScheme.surfaceContainer,
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(
Radius.circular(16),
@@ -119,8 +115,7 @@ class DriftUploadDetailPage extends ConsumerWidget {
Text(
'Tap for more details',
style: context.textTheme.bodySmall?.copyWith(
color: context.colorScheme.onSurface
.withValues(alpha: 0.6),
color: context.colorScheme.onSurface.withValues(alpha: 0.6),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
@@ -163,13 +158,10 @@ class DriftUploadDetailPage extends ConsumerWidget {
tween: Tween<double>(begin: 0.0, end: progress),
duration: const Duration(milliseconds: 300),
builder: (context, value, _) => CircularProgressIndicator(
backgroundColor:
context.colorScheme.outline.withValues(alpha: 0.2),
backgroundColor: context.colorScheme.outline.withValues(alpha: 0.2),
strokeWidth: 3,
value: value,
color: isCompleted
? context.colorScheme.primary
: context.colorScheme.secondary,
color: isCompleted ? context.colorScheme.primary : context.colorScheme.secondary,
),
),
),
@@ -279,12 +271,10 @@ class FileDetailDialog extends ConsumerWidget {
height: 128,
decoration: BoxDecoration(
border: Border.all(
color: context.colorScheme.outline
.withValues(alpha: 0.2),
color: context.colorScheme.outline.withValues(alpha: 0.2),
width: 1,
),
borderRadius:
const BorderRadius.all(Radius.circular(12)),
borderRadius: const BorderRadius.all(Radius.circular(12)),
),
child: asset != null
? Thumbnail(
@@ -314,8 +304,7 @@ class FileDetailDialog extends ConsumerWidget {
"File Size",
formatHumanReadableBytes(uploadStatus.fileSize, 2),
),
if (asset.width != null)
_buildInfoRow(context, "Width", "${asset.width}px"),
if (asset.width != null) _buildInfoRow(context, "Width", "${asset.width}px"),
if (asset.height != null)
_buildInfoRow(
context,
@@ -97,9 +97,7 @@ class FailedBackupStatusPage extends HookConsumerWidget {
),
style: TextStyle(
fontWeight: FontWeight.w600,
color: context.isDarkTheme
? Colors.white70
: Colors.grey[800],
color: context.isDarkTheme ? Colors.white70 : Colors.grey[800],
),
),
Icon(
@@ -125,9 +123,7 @@ class FailedBackupStatusPage extends HookConsumerWidget {
errorAsset.errorMessage,
style: TextStyle(
fontWeight: FontWeight.w500,
color: context.isDarkTheme
? Colors.white70
: Colors.grey[800],
color: context.isDarkTheme ? Colors.white70 : Colors.grey[800],
),
),
],
+6 -14
View File
@@ -27,10 +27,8 @@ class ActivitiesPage extends HookConsumerWidget {
final asset = ref.watch(currentAssetProvider);
final user = ref.watch(currentUserProvider);
final activityNotifier = ref
.read(albumActivityProvider(album.remoteId!, asset?.remoteId).notifier);
final activities =
ref.watch(albumActivityProvider(album.remoteId!, asset?.remoteId));
final activityNotifier = ref.read(albumActivityProvider(album.remoteId!, asset?.remoteId).notifier);
final activities = ref.watch(albumActivityProvider(album.remoteId!, asset?.remoteId));
final listViewScrollController = useScrollController();
@@ -49,10 +47,7 @@ class ActivitiesPage extends HookConsumerWidget {
body: activities.widgetWhen(
onData: (data) {
final liked = data.firstWhereOrNull(
(a) =>
a.type == ActivityType.like &&
a.user.id == user?.id &&
a.assetId == asset?.remoteId,
(a) => a.type == ActivityType.like && a.user.id == user?.id && a.assetId == asset?.remoteId,
);
return SafeArea(
@@ -71,18 +66,15 @@ class ActivitiesPage extends HookConsumerWidget {
}
final activity = data[index];
final canDelete = activity.user.id == user?.id ||
album.ownerId == user?.id;
final canDelete = activity.user.id == user?.id || album.ownerId == user?.id;
return Padding(
padding: const EdgeInsets.all(5),
child: DismissibleActivity(
activity.id,
ActivityTile(activity),
onDismiss: canDelete
? (activityId) async => await activityNotifier
.removeActivity(activity.id)
: null,
onDismiss:
canDelete ? (activityId) async => await activityNotifier.removeActivity(activity.id) : null,
),
);
},
@@ -130,10 +130,8 @@ class AppLogDetailPage extends HookConsumerWidget {
child: ListView(
children: [
buildTextWithCopyButton("MESSAGE", logMessage.message),
if (logMessage.error != null)
buildTextWithCopyButton("DETAILS", logMessage.error.toString()),
if (logMessage.logger != null)
buildLogContext1(logMessage.logger.toString()),
if (logMessage.error != null) buildTextWithCopyButton("DETAILS", logMessage.error.toString()),
if (logMessage.logger != null) buildLogContext1(logMessage.logger.toString()),
if (logMessage.stack != null)
buildTextWithCopyButton(
"STACK TRACE",
@@ -61,9 +61,7 @@ class _ChangeExperiencePageState extends ConsumerState<ChangeExperiencePage> {
ref.read(websocketProvider.notifier).stopListenToOldEvents();
ref.read(websocketProvider.notifier).startListeningToBetaEvents();
final permission = await ref
.read(galleryPermissionNotifier.notifier)
.requestGalleryPermission();
final permission = await ref.read(galleryPermissionNotifier.notifier).requestGalleryPermission();
if (permission.isGranted) {
await ref.read(backgroundSyncProvider).syncLocal(full: true);
@@ -138,9 +136,7 @@ class _ChangeExperiencePageState extends ConsumerState<ChangeExperiencePage> {
child: ElevatedButton(
onPressed: () {
context.replaceRoute(
widget.switchingToBeta
? const TabShellRoute()
: const TabControllerRoute(),
widget.switchingToBeta ? const TabShellRoute() : const TabControllerRoute(),
);
},
child: const Text("Continue"),
+6 -14
View File
@@ -27,8 +27,7 @@ class CreateAlbumPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final albumTitleController =
useTextEditingController.fromValue(TextEditingValue.empty);
final albumTitleController = useTextEditingController.fromValue(TextEditingValue.empty);
final albumTitleTextFieldFocusNode = useFocusNode();
final albumDescriptionTextFieldFocusNode = useFocusNode();
final isAlbumTitleTextFieldFocus = useState(false);
@@ -45,15 +44,12 @@ class CreateAlbumPage extends HookConsumerWidget {
if (albumTitleController.text.isEmpty) {
albumTitleController.text = 'create_album_page_untitled'.tr();
isAlbumTitleEmpty.value = false;
ref
.watch(albumTitleProvider.notifier)
.setAlbumTitle('create_album_page_untitled'.tr());
ref.watch(albumTitleProvider.notifier).setAlbumTitle('create_album_page_untitled'.tr());
}
}
onSelectPhotosButtonPressed() async {
AssetSelectionPageResult? selectedAsset =
await context.pushRoute<AssetSelectionPageResult?>(
AssetSelectionPageResult? selectedAsset = await context.pushRoute<AssetSelectionPageResult?>(
AlbumAssetSelectionRoute(
existingAssets: selectedAssets.value,
canDeselect: true,
@@ -118,8 +114,7 @@ class CreateAlbumPage extends HookConsumerWidget {
child: FilledButton.icon(
style: FilledButton.styleFrom(
alignment: Alignment.centerLeft,
padding:
const EdgeInsets.symmetric(vertical: 24, horizontal: 16),
padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 16),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10),
@@ -230,15 +225,12 @@ class CreateAlbumPage extends HookConsumerWidget {
).tr(),
actions: [
TextButton(
onPressed:
albumTitleController.text.isNotEmpty ? createAlbum : null,
onPressed: albumTitleController.text.isNotEmpty ? createAlbum : null,
child: Text(
'create'.tr(),
style: TextStyle(
fontWeight: FontWeight.bold,
color: albumTitleController.text.isNotEmpty
? context.primaryColor
: context.themeData.disabledColor,
color: albumTitleController.text.isNotEmpty ? context.primaryColor : context.themeData.disabledColor,
),
),
),
+2 -4
View File
@@ -34,8 +34,7 @@ class DownloadPanel extends ConsumerWidget {
duration: const Duration(milliseconds: 300),
child: showProgress
? ConstrainedBox(
constraints:
BoxConstraints.loose(Size(context.width - 32, 300)),
constraints: BoxConstraints.loose(Size(context.width - 32, 300)),
child: ListView.builder(
shrinkWrap: true,
itemCount: tasks.length,
@@ -122,8 +121,7 @@ class DownloadTaskTile extends StatelessWidget {
child: LinearProgressIndicator(
minHeight: 8.0,
value: progress,
borderRadius:
const BorderRadius.all(Radius.circular(10.0)),
borderRadius: const BorderRadius.all(Radius.circular(10.0)),
),
),
const SizedBox(width: 8),
@@ -267,8 +267,7 @@ class GalleryViewerPage extends HookConsumerWidget {
PhotoViewGalleryPageOptions buildVideo(BuildContext context, Asset asset) {
return PhotoViewGalleryPageOptions.customChild(
onDragStart: (_, details, __, ___) =>
localPosition.value = details.localPosition,
onDragStart: (_, details, __, ___) => localPosition.value = details.localPosition,
onDragUpdate: (_, details, __) => handleSwipeUpDown(details),
heroAttributes: _getHeroAttributes(asset),
filterQuality: FilterQuality.high,
@@ -304,8 +303,7 @@ class GalleryViewerPage extends HookConsumerWidget {
final stackId = newAsset.stackId;
if (stackId != null && currentIndex.value == index) {
final stackElements =
ref.read(assetStackStateProvider(newAsset.stackId!));
final stackElements = ref.read(assetStackStateProvider(newAsset.stackId!));
if (stackIndex.value < stackElements.length) {
newAsset = stackElements.elementAt(stackIndex.value);
}
@@ -319,8 +317,7 @@ class GalleryViewerPage extends HookConsumerWidget {
return PopScope(
// Change immersive mode back to normal "edgeToEdge" mode
onPopInvokedWithResult: (didPop, _) =>
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge),
onPopInvokedWithResult: (didPop, _) => SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge),
child: Scaffold(
backgroundColor: Colors.black,
body: Stack(
@@ -335,8 +332,7 @@ class GalleryViewerPage extends HookConsumerWidget {
if (asset.isImage && !ref.read(isPlayingMotionVideoProvider)) {
isZoomed.value = state != PhotoViewScaleState.initial;
ref.read(showControlsProvider.notifier).show =
!isZoomed.value;
ref.read(showControlsProvider.notifier).show = !isZoomed.value;
}
},
gaplessPlayback: true,
@@ -454,9 +450,7 @@ class GalleryViewerPage extends HookConsumerWidget {
@pragma('vm:prefer-inline')
PhotoViewHeroAttributes _getHeroAttributes(Asset asset) {
return PhotoViewHeroAttributes(
tag: asset.isInDb
? asset.id + heroOffset
: '${asset.remoteId}-$heroOffset',
tag: asset.isInDb ? asset.id + heroOffset : '${asset.remoteId}-$heroOffset',
transitionOnUserGestures: true,
);
}
@@ -40,8 +40,7 @@ class LargeLeadingTile extends StatelessWidget {
child: Container(
decoration: BoxDecoration(
color: selected
? selectedTileColor ??
Theme.of(context).primaryColor.withAlpha(30)
? selectedTileColor ?? Theme.of(context).primaryColor.withAlpha(30)
: tileColor ?? Colors.transparent,
borderRadius: BorderRadius.circular(borderRadius),
),
@@ -87,11 +87,9 @@ class NativeVideoViewerPage extends HookConsumerWidget {
// Use a network URL for the video player controller
final serverEndpoint = Store.get(StoreKey.serverEndpoint);
final isOriginalVideo = ref
.read(appSettingsServiceProvider)
.getSetting<bool>(AppSettingsEnum.loadOriginalVideo);
final String postfixUrl =
isOriginalVideo ? 'original' : 'video/playback';
final isOriginalVideo =
ref.read(appSettingsServiceProvider).getSetting<bool>(AppSettingsEnum.loadOriginalVideo);
final String postfixUrl = isOriginalVideo ? 'original' : 'video/playback';
final String videoUrl = asset.livePhotoVideoId != null
? '$serverEndpoint/assets/${asset.livePhotoVideoId}/$postfixUrl'
: '$serverEndpoint/assets/${asset.remoteId}/$postfixUrl';
@@ -119,8 +117,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
}
try {
aspectRatio.value =
await ref.read(assetServiceProvider).getAspectRatio(asset);
aspectRatio.value = await ref.read(assetServiceProvider).getAspectRatio(asset);
} catch (error) {
log.severe(
'Error getting aspect ratio for asset ${asset.fileName}: $error',
@@ -135,8 +132,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
}
final videoPlayback = ref.read(videoPlaybackValueProvider);
if ((isBuffering.value ||
videoPlayback.state == VideoPlaybackState.initializing) &&
if ((isBuffering.value || videoPlayback.state == VideoPlaybackState.initializing) &&
videoPlayback.state != VideoPlaybackState.buffering) {
ref.read(videoPlaybackValueProvider.notifier).value =
videoPlayback.copyWith(state: VideoPlaybackState.buffering);
@@ -195,8 +191,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
return;
}
final videoPlayback =
VideoPlaybackValue.fromNativeController(videoController);
final videoPlayback = VideoPlaybackValue.fromNativeController(videoController);
ref.read(videoPlaybackValueProvider.notifier).value = videoPlayback;
isVideoReady.value = true;
@@ -215,8 +210,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
return;
}
final videoPlayback =
VideoPlaybackValue.fromNativeController(videoController);
final videoPlayback = VideoPlaybackValue.fromNativeController(videoController);
if (videoPlayback.state == VideoPlaybackState.playing) {
// Sync with the controls playing
WakelockPlus.enable();
@@ -225,8 +219,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
WakelockPlus.disable();
}
ref.read(videoPlaybackValueProvider.notifier).status =
videoPlayback.state;
ref.read(videoPlaybackValueProvider.notifier).status = videoPlayback.state;
}
void onPlaybackPositionChanged() {
@@ -245,8 +238,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
return;
}
ref.read(videoPlaybackValueProvider.notifier).position =
Duration(seconds: playbackInfo.position);
ref.read(videoPlaybackValueProvider.notifier).position = Duration(seconds: playbackInfo.position);
// Check if the video is buffering
if (playbackInfo.status == PlaybackStatus.playing) {
@@ -265,18 +257,14 @@ class NativeVideoViewerPage extends HookConsumerWidget {
}
if (videoController.playbackInfo?.status == PlaybackStatus.stopped &&
!ref
.read(appSettingsServiceProvider)
.getSetting<bool>(AppSettingsEnum.loopVideo)) {
!ref.read(appSettingsServiceProvider).getSetting<bool>(AppSettingsEnum.loopVideo)) {
ref.read(isPlayingMotionVideoProvider.notifier).playing = false;
}
}
void removeListeners(NativeVideoPlayerController controller) {
controller.onPlaybackPositionChanged
.removeListener(onPlaybackPositionChanged);
controller.onPlaybackStatusChanged
.removeListener(onPlaybackStatusChanged);
controller.onPlaybackPositionChanged.removeListener(onPlaybackPositionChanged);
controller.onPlaybackStatusChanged.removeListener(onPlaybackStatusChanged);
controller.onPlaybackReady.removeListener(onPlaybackReady);
controller.onPlaybackEnded.removeListener(onPlaybackEnded);
}
@@ -301,9 +289,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
nc.loadVideoSource(source).catchError((error) {
log.severe('Error loading video source: $error');
});
final loopVideo = ref
.read(appSettingsServiceProvider)
.getSetting<bool>(AppSettingsEnum.loopVideo);
final loopVideo = ref.read(appSettingsServiceProvider).getSetting<bool>(AppSettingsEnum.loopVideo);
nc.setLoop(loopVideo);
controller.value = nc;
@@ -397,8 +383,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
children: [
// This remains under the video to avoid flickering
// For motion videos, this is the image portion of the asset
if (!isVideoReady.value || asset.isMotionPhoto)
Center(key: ValueKey(asset.id), child: image),
if (!isVideoReady.value || asset.isMotionPhoto) Center(key: ValueKey(asset.id), child: image),
if (aspectRatio.value != null && !isCasting)
Visibility.maintain(
key: ValueKey(asset),
+1 -2
View File
@@ -129,8 +129,7 @@ class _TabletLayout extends HookWidget {
const _TabletLayout();
@override
Widget build(BuildContext context) {
final selectedSection =
useState<SettingSection>(SettingSection.values.first);
final selectedSection = useState<SettingSection>(SettingSection.values.first);
return Row(
mainAxisAlignment: MainAxisAlignment.start,
@@ -74,9 +74,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
if (context.router.current.name == SplashScreenRoute.name) {
context.replaceRoute(
Store.isBetaTimelineEnabled
? const TabShellRoute()
: const TabControllerRoute(),
Store.isBetaTimelineEnabled ? const TabShellRoute() : const TabControllerRoute(),
);
}
@@ -84,8 +82,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
return;
}
final hasPermission =
await ref.read(galleryPermissionNotifier.notifier).hasPermission;
final hasPermission = await ref.read(galleryPermissionNotifier.notifier).hasPermission;
if (hasPermission) {
// Resume backup (if enable) then navigate
ref.watch(backupProvider.notifier).resumeBackup();
@@ -20,8 +20,7 @@ class TabControllerPage extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final isRefreshingAssets = ref.watch(assetProvider);
final isRefreshingRemoteAlbums = ref.watch(isRefreshingRemoteAlbumProvider);
final isScreenLandscape =
MediaQuery.orientationOf(context) == Orientation.landscape;
final isScreenLandscape = MediaQuery.orientationOf(context) == Orientation.landscape;
Widget buildIcon({required Widget icon, required bool isProcessing}) {
if (!isProcessing) return icon;
@@ -118,8 +117,7 @@ class TabControllerPage extends HookConsumerWidget {
Widget bottomNavigationBar(TabsRouter tabsRouter) {
return NavigationBar(
selectedIndex: tabsRouter.activeIndex,
onDestinationSelected: (index) =>
onNavigationSelected(tabsRouter, index),
onDestinationSelected: (index) => onNavigationSelected(tabsRouter, index),
destinations: navigationDestinations,
);
}
@@ -135,8 +133,7 @@ class TabControllerPage extends HookConsumerWidget {
),
)
.toList(),
onDestinationSelected: (index) =>
onNavigationSelected(tabsRouter, index),
onDestinationSelected: (index) => onNavigationSelected(tabsRouter, index),
selectedIndex: tabsRouter.activeIndex,
labelType: NavigationRailLabelType.all,
groupAlignment: 0.0,
@@ -160,8 +157,7 @@ class TabControllerPage extends HookConsumerWidget {
final tabsRouter = AutoTabsRouter.of(context);
return PopScope(
canPop: tabsRouter.activeIndex == 0,
onPopInvokedWithResult: (didPop, _) =>
!didPop ? tabsRouter.setActiveIndex(0) : null,
onPopInvokedWithResult: (didPop, _) => !didPop ? tabsRouter.setActiveIndex(0) : null,
child: Scaffold(
resizeToAvoidBottomInset: false,
body: isScreenLandscape
@@ -173,9 +169,7 @@ class TabControllerPage extends HookConsumerWidget {
],
)
: child,
bottomNavigationBar: multiselectEnabled || isScreenLandscape
? null
: bottomNavigationBar(tabsRouter),
bottomNavigationBar: multiselectEnabled || isScreenLandscape ? null : bottomNavigationBar(tabsRouter),
),
);
},
+6 -14
View File
@@ -33,9 +33,7 @@ class _TabShellPageState extends ConsumerState<TabShellPage> {
WidgetsBinding.instance.addPostFrameCallback((_) async {
ref.read(websocketProvider.notifier).connect();
final isEnableBackup = ref
.read(appSettingsServiceProvider)
.getSetting(AppSettingsEnum.enableBackup);
final isEnableBackup = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup);
await runNewSync(ref, full: true).then((_) async {
if (isEnableBackup) {
@@ -44,9 +42,7 @@ class _TabShellPageState extends ConsumerState<TabShellPage> {
return;
}
await ref
.read(driftBackupProvider.notifier)
.handleBackupResume(currentUser.id);
await ref.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id);
}
});
});
@@ -110,8 +106,7 @@ class _TabShellPageState extends ConsumerState<TabShellPage> {
),
)
.toList(),
onDestinationSelected: (index) =>
_onNavigationSelected(tabsRouter, index, ref),
onDestinationSelected: (index) => _onNavigationSelected(tabsRouter, index, ref),
selectedIndex: tabsRouter.activeIndex,
labelType: NavigationRailLabelType.all,
groupAlignment: 0.0,
@@ -134,8 +129,7 @@ class _TabShellPageState extends ConsumerState<TabShellPage> {
final tabsRouter = AutoTabsRouter.of(context);
return PopScope(
canPop: tabsRouter.activeIndex == 0,
onPopInvokedWithResult: (didPop, _) =>
!didPop ? tabsRouter.setActiveIndex(0) : null,
onPopInvokedWithResult: (didPop, _) => !didPop ? tabsRouter.setActiveIndex(0) : null,
child: Scaffold(
resizeToAvoidBottomInset: false,
body: isScreenLandscape
@@ -191,8 +185,7 @@ class _BottomNavigationBar extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final isScreenLandscape = context.orientation == Orientation.landscape;
final isMultiselectEnabled =
ref.watch(multiSelectProvider.select((s) => s.isEnabled));
final isMultiselectEnabled = ref.watch(multiSelectProvider.select((s) => s.isEnabled));
if (isScreenLandscape || isMultiselectEnabled) {
return const SizedBox.shrink();
@@ -200,8 +193,7 @@ class _BottomNavigationBar extends ConsumerWidget {
return NavigationBar(
selectedIndex: tabsRouter.activeIndex,
onDestinationSelected: (index) =>
_onNavigationSelected(tabsRouter, index, ref),
onDestinationSelected: (index) => _onNavigationSelected(tabsRouter, index, ref),
destinations: destinations,
);
}
+1 -3
View File
@@ -187,9 +187,7 @@ class _AspectRatioButton extends StatelessWidget {
'7:5' => Icons.crop_7_5_rounded,
_ => Icons.crop_free_rounded,
},
color: aspectRatio.value == ratio
? context.primaryColor
: context.themeData.iconTheme.color,
color: aspectRatio.value == ratio ? context.primaryColor : context.themeData.iconTheme.color,
),
onPressed: () {
cropController.crop = const Rect.fromLTRB(0.1, 0.1, 0.9, 0.9);
+3 -8
View File
@@ -40,9 +40,7 @@ class EditImagePage extends ConsumerWidget {
image.image.resolve(const ImageConfiguration()).addListener(
ImageStreamListener(
(ImageInfo info, bool _) {
info.image
.toByteData(format: ImageByteFormat.png)
.then((byteData) {
info.image.toByteData(format: ImageByteFormat.png).then((byteData) {
if (byteData != null) {
completer.complete(byteData.buffer.asUint8List());
} else {
@@ -50,8 +48,7 @@ class EditImagePage extends ConsumerWidget {
}
});
},
onError: (exception, stackTrace) =>
completer.completeError(exception),
onError: (exception, stackTrace) => completer.completeError(exception),
),
);
return completer.future;
@@ -103,9 +100,7 @@ class EditImagePage extends ConsumerWidget {
),
actions: <Widget>[
TextButton(
onPressed: isEdited
? () => _saveEditedImage(context, asset, image, ref)
: null,
onPressed: isEdited ? () => _saveEditedImage(context, asset, image, ref) : null,
child: Text(
"save_to_gallery".tr(),
style: TextStyle(
+5 -13
View File
@@ -34,18 +34,14 @@ class FilterImagePage extends HookWidget {
ColorFilter filter,
) {
final completer = Completer<ui.Image>();
final size =
Size(inputImage.width.toDouble(), inputImage.height.toDouble());
final size = Size(inputImage.width.toDouble(), inputImage.height.toDouble());
final recorder = ui.PictureRecorder();
final canvas = Canvas(recorder);
final paint = Paint()..colorFilter = filter;
canvas.drawImage(inputImage, Offset.zero, paint);
recorder
.endRecording()
.toImage(size.width.round(), size.height.round())
.then((image) {
recorder.endRecording().toImage(size.width.round(), size.height.round()).then((image) {
completer.complete(image);
});
@@ -67,8 +63,7 @@ class FilterImagePage extends HookWidget {
final uiImage = await completer.future;
final filteredUiImage = await createFilteredImage(uiImage, filter);
final byteData =
await filteredUiImage.toByteData(format: ui.ImageByteFormat.png);
final byteData = await filteredUiImage.toByteData(format: ui.ImageByteFormat.png);
final pngBytes = byteData!.buffer.asUint8List();
return Image.memory(pngBytes, fit: BoxFit.contain);
@@ -87,8 +82,7 @@ class FilterImagePage extends HookWidget {
size: 24,
),
onPressed: () async {
final filteredImage =
await applyFilterAndConvert(colorFilter.value);
final filteredImage = await applyFilterAndConvert(colorFilter.value);
context.pushRoute(
EditImageRoute(
asset: asset,
@@ -165,9 +159,7 @@ class _FilterButton extends StatelessWidget {
borderRadius: const BorderRadius.all(
Radius.circular(10),
),
border: isSelected
? Border.all(color: context.primaryColor, width: 3)
: null,
border: isSelected ? Border.all(color: context.primaryColor, width: 3) : null,
),
child: ClipRRect(
borderRadius: const BorderRadius.all(
@@ -21,9 +21,7 @@ RecursiveFolder? _findFolderInStructure(
RecursiveFolder targetFolder,
) {
for (final folder in rootFolder.subfolders) {
if (targetFolder.path == '/' &&
folder.path.isEmpty &&
folder.name == targetFolder.name) {
if (targetFolder.path == '/' && folder.path.isEmpty && folder.name == targetFolder.name) {
return folder;
}
@@ -54,9 +52,7 @@ class FolderPage extends HookConsumerWidget {
useEffect(
() {
if (folder == null) {
ref
.read(folderStructureProvider.notifier)
.fetchFolders(sortOrder.value);
ref.read(folderStructureProvider.notifier).fetchFolders(sortOrder.value);
}
return null;
},
@@ -67,8 +63,7 @@ class FolderPage extends HookConsumerWidget {
useEffect(
() {
if (folder != null && folderState.hasValue) {
final updatedFolder =
_findFolderInStructure(folderState.value!, folder!);
final updatedFolder = _findFolderInStructure(folderState.value!, folder!);
if (updatedFolder != null) {
currentFolder.value = updatedFolder;
}
@@ -79,8 +74,7 @@ class FolderPage extends HookConsumerWidget {
);
void onToggleSortOrder() {
final newOrder =
sortOrder.value == SortOrder.asc ? SortOrder.desc : SortOrder.asc;
final newOrder = sortOrder.value == SortOrder.asc ? SortOrder.desc : SortOrder.asc;
ref.read(folderStructureProvider.notifier).fetchFolders(newOrder);
@@ -151,9 +145,7 @@ class FolderContent extends HookConsumerWidget {
useEffect(
() {
if (folder == null) return;
ref
.read(folderRenderListProvider(folder!).notifier)
.fetchAssets(sortOrder);
ref.read(folderRenderListProvider(folder!).notifier).fetchAssets(sortOrder);
return null;
},
[folder],
@@ -211,13 +203,10 @@ class FolderContent extends HookConsumerWidget {
),
)
: null,
onTap: () =>
context.pushRoute(FolderRoute(folder: subfolder)),
onTap: () => context.pushRoute(FolderRoute(folder: subfolder)),
),
),
if (!list.isEmpty &&
list.allAssets != null &&
list.allAssets!.isNotEmpty)
if (!list.isEmpty && list.allAssets != null && list.allAssets!.isNotEmpty)
...list.allAssets!.map(
(asset) => LargeLeadingTile(
onTap: () {
+3 -7
View File
@@ -25,8 +25,7 @@ class LibraryPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
context.locale;
final trashEnabled =
ref.watch(serverInfoProvider.select((v) => v.serverFeatures.trash));
final trashEnabled = ref.watch(serverInfoProvider.select((v) => v.serverFeatures.trash));
return Scaffold(
appBar: const ImmichAppBar(),
@@ -388,8 +387,7 @@ class PlacesCollectionCard extends StatelessWidget {
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(20)),
color:
context.colorScheme.secondaryContainer.withAlpha(100),
color: context.colorScheme.secondaryContainer.withAlpha(100),
),
child: IgnorePointer(
child: MapThumbnail(
@@ -399,9 +397,7 @@ class PlacesCollectionCard extends StatelessWidget {
-157.91959,
),
showAttribution: false,
themeMode: context.isDarkTheme
? ThemeMode.dark
: ThemeMode.light,
themeMode: context.isDarkTheme ? ThemeMode.dark : ThemeMode.light,
),
),
),
@@ -54,8 +54,7 @@ class LocalAlbumsPage extends HookConsumerWidget {
color: context.colorScheme.onSurfaceSecondary,
),
),
onTap: () => context
.pushRoute(AlbumViewerRoute(albumId: albums[index].id)),
onTap: () => context.pushRoute(AlbumViewerRoute(albumId: albums[index].id)),
),
);
},
@@ -23,11 +23,10 @@ class PinAuthPage extends HookConsumerWidget {
final isBetaTimeline = Store.isBetaTimelineEnabled;
Future<void> registerBiometric(String pinCode) async {
final isRegistered =
await ref.read(localAuthProvider.notifier).registerBiometric(
context,
pinCode,
);
final isRegistered = await ref.read(localAuthProvider.notifier).registerBiometric(
context,
pinCode,
);
if (isRegistered) {
context.showSnackBar(
@@ -101,8 +100,7 @@ class PinAuthPage extends HookConsumerWidget {
autoFocus: true,
onSuccess: (_) {
if (isBetaTimeline) {
context
.replaceRoute(const DriftLockedFolderRoute());
context.replaceRoute(const DriftLockedFolderRoute());
} else {
context.replaceRoute(const LockedRoute());
}
@@ -63,10 +63,8 @@ class DriftPartnerPage extends HookConsumerWidget {
builder: (BuildContext context) {
return ConfirmDialog(
title: "stop_photo_sharing",
content: "partner_page_stop_sharing_content"
.tr(namedArgs: {'partner': partner.name}),
onOk: () =>
ref.read(partnerUsersProvider.notifier).removePartner(partner),
content: "partner_page_stop_sharing_content".tr(namedArgs: {'partner': partner.name}),
onOk: () => ref.read(partnerUsersProvider.notifier).removePartner(partner),
);
},
);
@@ -53,8 +53,7 @@ class PartnerPage extends HookConsumerWidget {
},
);
if (selectedUser != null) {
final ok =
await ref.read(partnerServiceProvider).addPartner(selectedUser);
final ok = await ref.read(partnerServiceProvider).addPartner(selectedUser);
if (ok) {
ref.invalidate(partnerSharedByProvider);
} else {
@@ -73,8 +72,7 @@ class PartnerPage extends HookConsumerWidget {
builder: (BuildContext context) {
return ConfirmDialog(
title: "stop_photo_sharing",
content: "partner_page_stop_sharing_content"
.tr(namedArgs: {'partner': u.name}),
content: "partner_page_stop_sharing_content".tr(namedArgs: {'partner': u.name}),
onOk: () => ref.read(partnerServiceProvider).removePartner(u),
);
},
@@ -149,8 +147,7 @@ class PartnerPage extends HookConsumerWidget {
centerTitle: false,
actions: [
IconButton(
onPressed:
availableUsers.whenOrNull(data: (data) => addNewUsersHandler),
onPressed: availableUsers.whenOrNull(data: (data) => addNewUsersHandler),
icon: const Icon(Icons.person_add),
tooltip: "add_partner".tr(),
),
@@ -38,9 +38,8 @@ class PartnerDetailPage extends HookConsumerWidget {
if (toggleInProcess) return;
toggleInProcess = true;
try {
final ok = await ref
.read(partnerSharedWithProvider.notifier)
.updatePartner(partner, inTimeline: !inTimeline.value);
final ok =
await ref.read(partnerSharedWithProvider.notifier).updatePartner(partner, inTimeline: !inTimeline.value);
if (ok) {
inTimeline.value = !inTimeline.value;
final action = inTimeline.value ? "shown on" : "hidden from";
@@ -66,9 +66,7 @@ class PeopleCollectionPage extends HookConsumerWidget {
data: (people) {
if (search.value != null) {
people = people.where((person) {
return person.name
.toLowerCase()
.contains(search.value!.toLowerCase());
return person.name.toLowerCase().contains(search.value!.toLowerCase());
}).toList();
}
return GridView.builder(
@@ -107,8 +105,7 @@ class PeopleCollectionPage extends HookConsumerWidget {
),
const SizedBox(height: 12),
GestureDetector(
onTap: () =>
showNameEditModel(person.id, person.name),
onTap: () => showNameEditModel(person.id, person.name),
child: person.name.isEmpty
? Text(
'add_a_name'.tr(),
@@ -124,8 +121,7 @@ class PeopleCollectionPage extends HookConsumerWidget {
child: Text(
person.name,
overflow: TextOverflow.ellipsis,
style:
context.textTheme.titleSmall?.copyWith(
style: context.textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.w500,
),
),
@@ -59,8 +59,7 @@ class PlacesCollectionPage extends HookConsumerWidget {
height: 200,
width: context.width,
child: MapThumbnail(
onTap: (_, __) => context
.pushRoute(MapRoute(initialLocation: currentLocation)),
onTap: (_, __) => context.pushRoute(MapRoute(initialLocation: currentLocation)),
zoom: 8,
centre: currentLocation ??
const LatLng(
@@ -68,8 +67,7 @@ class PlacesCollectionPage extends HookConsumerWidget {
-157.91959,
),
showAttribution: false,
themeMode:
context.isDarkTheme ? ThemeMode.dark : ThemeMode.light,
themeMode: context.isDarkTheme ? ThemeMode.dark : ThemeMode.light,
),
),
),
@@ -77,9 +75,7 @@ class PlacesCollectionPage extends HookConsumerWidget {
data: (places) {
if (search.value != null) {
places = places.where((place) {
return place.label
.toLowerCase()
.contains(search.value!.toLowerCase());
return place.label.toLowerCase().contains(search.value!.toLowerCase());
}).toList();
}
return ListView.builder(
@@ -110,8 +106,7 @@ class PlaceTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
final thumbnailUrl =
'${Store.get(StoreKey.serverEndpoint)}/assets/$id/thumbnail';
final thumbnailUrl = '${Store.get(StoreKey.serverEndpoint)}/assets/$id/thumbnail';
void navigateToPlace() {
context.pushRoute(
@@ -152,8 +147,7 @@ class PlaceTile extends StatelessWidget {
fit: BoxFit.cover,
imageUrl: thumbnailUrl,
httpHeaders: ApiService.getRequestHeaders(),
errorWidget: (context, url, error) =>
const Icon(Icons.image_not_supported_outlined),
errorWidget: (context, url, error) => const Icon(Icons.image_not_supported_outlined),
),
),
);
@@ -58,8 +58,7 @@ class SharedLinkPage extends HookConsumerWidget {
child: Icon(
Icons.link_off,
size: 100,
color:
context.themeData.iconTheme.color?.withValues(alpha: 0.5),
color: context.themeData.iconTheme.color?.withValues(alpha: 0.5),
),
),
),
@@ -86,8 +85,7 @@ class SharedLinkPage extends HookConsumerWidget {
if (constraints.maxWidth > 600) {
// Two column
return GridView.builder(
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisExtent: 180,
),
@@ -121,8 +119,7 @@ class SharedLinkPage extends HookConsumerWidget {
body: SafeArea(
child: sharedLinks.widgetWhen(
onError: (error, stackTrace) => buildNoShares(),
onData: (links) =>
links.isNotEmpty ? buildSharesList(links) : buildNoShares(),
onData: (links) => links.isNotEmpty ? buildSharesList(links) : buildNoShares(),
),
),
);
@@ -31,11 +31,9 @@ class SharedLinkEditPage extends HookConsumerWidget {
const padding = 20.0;
final themeData = context.themeData;
final colorScheme = context.colorScheme;
final descriptionController =
useTextEditingController(text: existingLink?.description ?? "");
final descriptionController = useTextEditingController(text: existingLink?.description ?? "");
final descriptionFocusNode = useFocusNode();
final passwordController =
useTextEditingController(text: existingLink?.password ?? "");
final passwordController = useTextEditingController(text: existingLink?.password ?? "");
final showMetadata = useState(existingLink?.showMetadata ?? true);
final allowDownload = useState(existingLink?.allowDownload ?? true);
final allowUpload = useState(existingLink?.allowUpload ?? false);
@@ -155,15 +153,12 @@ class SharedLinkEditPage extends HookConsumerWidget {
Widget buildShowMetaButton() {
return SwitchListTile.adaptive(
value: showMetadata.value,
onChanged: newShareLink.value.isEmpty
? (value) => showMetadata.value = value
: null,
onChanged: newShareLink.value.isEmpty ? (value) => showMetadata.value = value : null,
activeColor: colorScheme.primary,
dense: true,
title: Text(
"show_metadata",
style: themeData.textTheme.labelLarge
?.copyWith(fontWeight: FontWeight.bold),
style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
).tr(),
);
}
@@ -171,15 +166,12 @@ class SharedLinkEditPage extends HookConsumerWidget {
Widget buildAllowDownloadButton() {
return SwitchListTile.adaptive(
value: allowDownload.value,
onChanged: newShareLink.value.isEmpty
? (value) => allowDownload.value = value
: null,
onChanged: newShareLink.value.isEmpty ? (value) => allowDownload.value = value : null,
activeColor: colorScheme.primary,
dense: true,
title: Text(
"allow_public_user_to_download",
style: themeData.textTheme.labelLarge
?.copyWith(fontWeight: FontWeight.bold),
style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
).tr(),
);
}
@@ -187,15 +179,12 @@ class SharedLinkEditPage extends HookConsumerWidget {
Widget buildAllowUploadButton() {
return SwitchListTile.adaptive(
value: allowUpload.value,
onChanged: newShareLink.value.isEmpty
? (value) => allowUpload.value = value
: null,
onChanged: newShareLink.value.isEmpty ? (value) => allowUpload.value = value : null,
activeColor: colorScheme.primary,
dense: true,
title: Text(
"allow_public_user_to_upload",
style: themeData.textTheme.labelLarge
?.copyWith(fontWeight: FontWeight.bold),
style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
).tr(),
);
}
@@ -203,15 +192,12 @@ class SharedLinkEditPage extends HookConsumerWidget {
Widget buildEditExpiryButton() {
return SwitchListTile.adaptive(
value: editExpiry.value,
onChanged: newShareLink.value.isEmpty
? (value) => editExpiry.value = value
: null,
onChanged: newShareLink.value.isEmpty ? (value) => editExpiry.value = value : null,
activeColor: colorScheme.primary,
dense: true,
title: Text(
"change_expiration_time",
style: themeData.textTheme.labelLarge
?.copyWith(fontWeight: FontWeight.bold),
style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
).tr(),
);
}
@@ -229,8 +215,7 @@ class SharedLinkEditPage extends HookConsumerWidget {
enableFilter: false,
width: context.width - 40,
initialSelection: expiryAfter.value,
enabled: newShareLink.value.isEmpty &&
(existingLink == null || editExpiry.value),
enabled: newShareLink.value.isEmpty && (existingLink == null || editExpiry.value),
onSelected: (value) {
expiryAfter.value = value!;
},
@@ -241,8 +226,7 @@ class SharedLinkEditPage extends HookConsumerWidget {
),
DropdownMenuEntry(
value: 30,
label: "shared_link_edit_expire_after_option_minutes"
.tr(namedArgs: {'count': "30"}),
label: "shared_link_edit_expire_after_option_minutes".tr(namedArgs: {'count': "30"}),
),
DropdownMenuEntry(
value: 60,
@@ -250,8 +234,7 @@ class SharedLinkEditPage extends HookConsumerWidget {
),
DropdownMenuEntry(
value: 60 * 6,
label: "shared_link_edit_expire_after_option_hours"
.tr(namedArgs: {'count': "6"}),
label: "shared_link_edit_expire_after_option_hours".tr(namedArgs: {'count': "6"}),
),
DropdownMenuEntry(
value: 60 * 24,
@@ -259,23 +242,19 @@ class SharedLinkEditPage extends HookConsumerWidget {
),
DropdownMenuEntry(
value: 60 * 24 * 7,
label: "shared_link_edit_expire_after_option_days"
.tr(namedArgs: {'count': "7"}),
label: "shared_link_edit_expire_after_option_days".tr(namedArgs: {'count': "7"}),
),
DropdownMenuEntry(
value: 60 * 24 * 30,
label: "shared_link_edit_expire_after_option_days"
.tr(namedArgs: {'count': "30"}),
label: "shared_link_edit_expire_after_option_days".tr(namedArgs: {'count': "30"}),
),
DropdownMenuEntry(
value: 60 * 24 * 30 * 3,
label: "shared_link_edit_expire_after_option_months"
.tr(namedArgs: {'count': "3"}),
label: "shared_link_edit_expire_after_option_months".tr(namedArgs: {'count': "3"}),
),
DropdownMenuEntry(
value: 60 * 24 * 30 * 12,
label: "shared_link_edit_expire_after_option_year"
.tr(namedArgs: {'count': "1"}),
label: "shared_link_edit_expire_after_option_year".tr(namedArgs: {'count': "1"}),
),
],
);
@@ -346,27 +325,21 @@ class SharedLinkEditPage extends HookConsumerWidget {
}
Future<void> handleNewLink() async {
final newLink =
await ref.read(sharedLinkServiceProvider).createSharedLink(
albumId: albumId,
assetIds: assetsList,
showMeta: showMetadata.value,
allowDownload: allowDownload.value,
allowUpload: allowUpload.value,
description: descriptionController.text.isEmpty
? null
: descriptionController.text,
password: passwordController.text.isEmpty
? null
: passwordController.text,
expiresAt: expiryAfter.value == 0 ? null : calculateExpiry(),
);
final newLink = await ref.read(sharedLinkServiceProvider).createSharedLink(
albumId: albumId,
assetIds: assetsList,
showMeta: showMetadata.value,
allowDownload: allowDownload.value,
allowUpload: allowUpload.value,
description: descriptionController.text.isEmpty ? null : descriptionController.text,
password: passwordController.text.isEmpty ? null : passwordController.text,
expiresAt: expiryAfter.value == 0 ? null : calculateExpiry(),
);
ref.invalidate(sharedLinksStateProvider);
final externalDomain = ref.read(
serverInfoProvider.select((s) => s.serverConfig.externalDomain),
);
var serverUrl =
externalDomain.isNotEmpty ? externalDomain : getServerUrl();
var serverUrl = externalDomain.isNotEmpty ? externalDomain : getServerUrl();
if (serverUrl != null && !serverUrl.endsWith('/')) {
serverUrl += '/';
}
@@ -472,8 +445,7 @@ class SharedLinkEditPage extends HookConsumerWidget {
child: buildAllowDownloadButton(),
),
Padding(
padding:
const EdgeInsets.only(left: padding, right: 20, bottom: 20),
padding: const EdgeInsets.only(left: padding, right: 20, bottom: 20),
child: buildAllowUploadButton(),
),
if (existingLink != null)
@@ -502,12 +474,9 @@ class SharedLinkEditPage extends HookConsumerWidget {
bottom: padding,
),
child: ElevatedButton(
onPressed:
existingLink != null ? handleEditLink : handleNewLink,
onPressed: existingLink != null ? handleEditLink : handleNewLink,
child: Text(
existingLink != null
? "shared_link_edit_submit_button"
: "create_link",
existingLink != null ? "shared_link_edit_submit_button" : "create_link",
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
+10 -24
View File
@@ -24,8 +24,7 @@ class TrashPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final trashRenderList = ref.watch(trashTimelineProvider);
final trashDays =
ref.watch(serverInfoProvider.select((v) => v.serverConfig.trashDays));
final trashDays = ref.watch(serverInfoProvider.select((v) => v.serverConfig.trashDays));
final selectionEnabledHook = useState(false);
final selection = useState(<Asset>{});
final processing = useProcessingOverlay();
@@ -68,16 +67,13 @@ class TrashPage extends HookConsumerWidget {
processing.value = true;
try {
if (selection.value.isNotEmpty) {
final isRemoved = await ref
.read(assetProvider.notifier)
.deleteAssets(selection.value, force: true);
final isRemoved = await ref.read(assetProvider.notifier).deleteAssets(selection.value, force: true);
if (isRemoved) {
if (context.mounted) {
ImmichToast.show(
context: context,
msg: 'assets_deleted_permanently'
.tr(namedArgs: {'count': "${selection.value.length}"}),
msg: 'assets_deleted_permanently'.tr(namedArgs: {'count': "${selection.value.length}"}),
gravity: ToastGravity.BOTTOM,
);
}
@@ -110,15 +106,12 @@ class TrashPage extends HookConsumerWidget {
processing.value = true;
try {
if (selection.value.isNotEmpty) {
final result = await ref
.read(trashProvider.notifier)
.restoreAssets(selection.value);
final result = await ref.read(trashProvider.notifier).restoreAssets(selection.value);
if (result && context.mounted) {
ImmichToast.show(
context: context,
msg: 'assets_restored_successfully'
.tr(namedArgs: {'count': "${selection.value.length}"}),
msg: 'assets_restored_successfully'.tr(namedArgs: {'count': "${selection.value.length}"}),
gravity: ToastGravity.BOTTOM,
);
}
@@ -131,9 +124,7 @@ class TrashPage extends HookConsumerWidget {
String getAppBarTitle(String count) {
if (selectionEnabledHook.value) {
return selection.value.isNotEmpty
? "${selection.value.length}"
: "trash_page_select_assets_btn".tr();
return selection.value.isNotEmpty ? "${selection.value.length}" : "trash_page_select_assets_btn".tr();
}
return 'trash_page_title'.tr(namedArgs: {'count': count});
}
@@ -147,9 +138,8 @@ class TrashPage extends HookConsumerWidget {
selectionEnabledHook.value = false;
selection.value = {};
},
icon: !selectionEnabledHook.value
? const Icon(Icons.arrow_back_ios_rounded)
: const Icon(Icons.close_rounded),
icon:
!selectionEnabledHook.value ? const Icon(Icons.arrow_back_ios_rounded) : const Icon(Icons.close_rounded),
),
centerTitle: !selectionEnabledHook.value,
automaticallyImplyLeading: false,
@@ -192,9 +182,7 @@ class TrashPage extends HookConsumerWidget {
color: Colors.red[400],
),
label: Text(
selection.value.isEmpty
? 'trash_page_delete_all'.tr()
: 'delete'.tr(),
selection.value.isEmpty ? 'trash_page_delete_all'.tr() : 'delete'.tr(),
style: TextStyle(
fontSize: 14,
color: Colors.red[400],
@@ -212,9 +200,7 @@ class TrashPage extends HookConsumerWidget {
Icons.history_rounded,
),
label: Text(
selection.value.isEmpty
? 'trash_page_restore_all'.tr()
: 'restore'.tr(),
selection.value.isEmpty ? 'trash_page_restore_all'.tr() : 'restore'.tr(),
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
@@ -33,10 +33,8 @@ class PermissionOnboardingPage extends HookConsumerWidget {
).tr(),
const SizedBox(height: 18),
ElevatedButton(
onPressed: () => ref
.read(galleryPermissionNotifier.notifier)
.requestGalleryPermission()
.then((permission) async {
onPressed: () =>
ref.read(galleryPermissionNotifier.notifier).requestGalleryPermission().then((permission) async {
if (permission.isGranted) {
// If permission is limited, we will show the limited
// permission page
@@ -139,12 +137,8 @@ class PermissionOnboardingPage extends HookConsumerWidget {
final Widget child = switch (permission) {
PermissionStatus.limited => buildPermissionLimited(),
PermissionStatus.denied => buildRequestPermission(),
PermissionStatus.granted ||
PermissionStatus.provisional =>
buildPermissionGranted(),
PermissionStatus.restricted ||
PermissionStatus.permanentlyDenied =>
buildPermissionDenied()
PermissionStatus.granted || PermissionStatus.provisional => buildPermissionGranted(),
PermissionStatus.restricted || PermissionStatus.permanentlyDenied => buildPermissionDenied()
};
return Scaffold(
+11 -22
View File
@@ -40,8 +40,7 @@ class MemoryPage extends HookConsumerWidget {
final currentAsset = useState<Asset?>(null);
/// The list of all of the asset page controllers
final memoryAssetPageControllers =
List.generate(memories.length, (i) => usePageController());
final memoryAssetPageControllers = List.generate(memories.length, (i) => usePageController());
/// The main vertically scrolling page controller with each list of memories
final memoryPageController = usePageController(initialPage: memoryIndex);
@@ -73,19 +72,16 @@ class MemoryPage extends HookConsumerWidget {
// Wait for the next frame to ensure the page is built
SchedulerBinding.instance.addPostFrameCallback((_) {
final previousIndex = currentMemoryIndex.value - 1;
final previousMemoryController =
memoryAssetPageControllers[previousIndex];
final previousMemoryController = memoryAssetPageControllers[previousIndex];
// Ensure the controller is attached
if (previousMemoryController.hasClients) {
previousMemoryController
.jumpToPage(memories[previousIndex].assets.length - 1);
previousMemoryController.jumpToPage(memories[previousIndex].assets.length - 1);
} else {
// Wait for the next frame until it is attached
SchedulerBinding.instance.addPostFrameCallback((_) {
if (previousMemoryController.hasClients) {
previousMemoryController
.jumpToPage(memories[previousIndex].assets.length - 1);
previousMemoryController.jumpToPage(memories[previousIndex].assets.length - 1);
}
});
}
@@ -96,8 +92,7 @@ class MemoryPage extends HookConsumerWidget {
toNextAsset(int currentAssetIndex) {
if (currentAssetIndex + 1 < currentMemory.value.assets.length) {
// Go to the next asset
PageController controller =
memoryAssetPageControllers[currentMemoryIndex.value];
PageController controller = memoryAssetPageControllers[currentMemoryIndex.value];
controller.nextPage(
curve: Curves.easeInOut,
@@ -112,8 +107,7 @@ class MemoryPage extends HookConsumerWidget {
toPreviousAsset(int currentAssetIndex) {
if (currentAssetIndex > 0) {
// Go to the previous asset
PageController controller =
memoryAssetPageControllers[currentMemoryIndex.value];
PageController controller = memoryAssetPageControllers[currentMemoryIndex.value];
controller.previousPage(
curve: Curves.easeInOut,
@@ -126,8 +120,7 @@ class MemoryPage extends HookConsumerWidget {
}
updateProgressText() {
assetProgress.value =
"${currentAssetPage.value + 1}|${currentMemory.value.assets.length}";
assetProgress.value = "${currentAssetPage.value + 1}|${currentMemory.value.assets.length}";
}
/// Downloads and caches the image for the asset at this [currentMemory]'s index
@@ -180,8 +173,7 @@ class MemoryPage extends HookConsumerWidget {
// Precache the next page right away if we are on the first page
if (currentAssetPage.value == 0) {
Future.delayed(const Duration(milliseconds: 200))
.then((_) => precacheAsset(1));
Future.delayed(const Duration(milliseconds: 200)).then((_) => precacheAsset(1));
}
Future<void> onAssetChanged(int otherIndex) async {
@@ -212,12 +204,10 @@ class MemoryPage extends HookConsumerWidget {
// maxScrollExtend contains the sum of horizontal pixels of all assets for depth = 1
// or sum of vertical pixels of all memories for depth = 0
if (notification is ScrollUpdateNotification) {
final isEpiloguePage =
(memoryPageController.page?.floor() ?? 0) >= memories.length;
final isEpiloguePage = (memoryPageController.page?.floor() ?? 0) >= memories.length;
final offset = notification.metrics.pixels;
if (isEpiloguePage &&
(offset > notification.metrics.maxScrollExtent + 150)) {
if (isEpiloguePage && (offset > notification.metrics.maxScrollExtent + 150)) {
context.maybePop();
return true;
}
@@ -358,8 +348,7 @@ class MemoryPage extends HookConsumerWidget {
),
),
),
if (currentAsset.value != null &&
currentAsset.value!.isVideo)
if (currentAsset.value != null && currentAsset.value!.isVideo)
Positioned(
bottom: 24,
right: 32,
+2 -6
View File
@@ -106,9 +106,7 @@ class PhotosPage extends HookConsumerWidget {
return Stack(
children: [
MultiselectGrid(
topWidget: (currentUser != null && currentUser.memoryEnabled)
? const MemoryLane()
: const SizedBox(),
topWidget: (currentUser != null && currentUser.memoryEnabled) ? const MemoryLane() : const SizedBox(),
renderListProvider: timelineUsers.length > 1
? multiUsersTimelineProvider(timelineUsers)
: singleUserTimelineProvider(currentUser?.id),
@@ -120,9 +118,7 @@ class PhotosPage extends HookConsumerWidget {
),
AnimatedPositioned(
duration: const Duration(milliseconds: 300),
top: ref.watch(multiselectProvider)
? -(kToolbarHeight + context.padding.top)
: 0,
top: ref.watch(multiselectProvider) ? -(kToolbarHeight + context.padding.top) : 0,
left: 0,
right: 0,
child: Container(
+1 -3
View File
@@ -28,9 +28,7 @@ class AllPeoplePage extends HookConsumerWidget {
body: curatedPeople.widgetWhen(
onData: (people) => ExploreGrid(
isPeople: true,
curatedContent: people
.map((e) => SearchCuratedContent(label: e.name, id: e.id))
.toList(),
curatedContent: people.map((e) => SearchCuratedContent(label: e.name, id: e.id)).toList(),
),
),
);
+1 -2
View File
@@ -13,8 +13,7 @@ class AllPlacesPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
AsyncValue<List<SearchCuratedContent>> places =
ref.watch(getAllPlacesProvider);
AsyncValue<List<SearchCuratedContent>> places = ref.watch(getAllPlacesProvider);
return Scaffold(
appBar: AppBar(
+10 -20
View File
@@ -48,8 +48,7 @@ class MapPage extends HookConsumerWidget {
final layerDebouncer = useDebouncer(interval: const Duration(seconds: 1));
final isLoading = useProcessingOverlay();
final scrollController = useScrollController();
final markerDebouncer =
useDebouncer(interval: const Duration(milliseconds: 800));
final markerDebouncer = useDebouncer(interval: const Duration(milliseconds: 800));
final selectedAssets = useValueNotifier<Set<Asset>>({});
const mapZoomToAssetLevel = 12.0;
@@ -64,8 +63,7 @@ class MapPage extends HookConsumerWidget {
final bounds = await mapController.value!.getVisibleRegion();
final inBounds = markers.value
.where(
(m) =>
bounds.contains(LatLng(m.latLng.latitude, m.latLng.longitude)),
(m) => bounds.contains(LatLng(m.latLng.latitude, m.latLng.longitude)),
)
.toList();
// Notify bottom sheet to update asset grid only when there are new assets
@@ -101,8 +99,7 @@ class MapPage extends HookConsumerWidget {
useEffect(
() {
final currentAssetLink =
ref.read(currentAssetProvider.notifier).ref.keepAlive();
final currentAssetLink = ref.read(currentAssetProvider.notifier).ref.keepAlive();
loadMarkers();
return currentAssetLink.close;
@@ -128,8 +125,7 @@ class MapPage extends HookConsumerWidget {
MapMarker marker, {
bool shouldAnimate = true,
}) async {
final assetPoint =
await mapController.value!.toScreenLocation(marker.latLng);
final assetPoint = await mapController.value!.toScreenLocation(marker.latLng);
selectedMarker.value = _AssetMarkerMeta(
point: assetPoint,
marker: marker,
@@ -144,11 +140,9 @@ class MapPage extends HookConsumerWidget {
if (mapController.value == null) {
return;
}
final latlngBound =
await mapController.value!.getBoundsFromPoint(point, 50);
final latlngBound = await mapController.value!.getBoundsFromPoint(point, 50);
final marker = markersInBounds.value.firstWhereOrNull(
(m) =>
latlngBound.contains(LatLng(m.latLng.latitude, m.latLng.longitude)),
(m) => latlngBound.contains(LatLng(m.latLng.latitude, m.latLng.longitude)),
);
if (marker != null) {
@@ -211,16 +205,14 @@ class MapPage extends HookConsumerWidget {
}
void onBottomSheetScrolled(String assetRemoteId) {
final assetMarker = markersInBounds.value
.firstWhereOrNull((m) => m.assetRemoteId == assetRemoteId);
final assetMarker = markersInBounds.value.firstWhereOrNull((m) => m.assetRemoteId == assetRemoteId);
if (assetMarker != null) {
updateAssetMarkerPosition(assetMarker);
}
}
void onZoomToAsset(String assetRemoteId) {
final assetMarker = markersInBounds.value
.firstWhereOrNull((m) => m.assetRemoteId == assetRemoteId);
final assetMarker = markersInBounds.value.firstWhereOrNull((m) => m.assetRemoteId == assetRemoteId);
if (mapController.value != null && assetMarker != null) {
// Offset the latitude a little to show the marker just above the viewports center
final offset = context.isMobile ? 0.02 : 0;
@@ -236,8 +228,7 @@ class MapPage extends HookConsumerWidget {
}
void onZoomToLocation() async {
final (location, error) =
await MapUtils.checkPermAndGetLocation(context: context);
final (location, error) = await MapUtils.checkPermAndGetLocation(context: context);
if (error != null) {
if (error == LocationPermission.unableToDetermine && context.mounted) {
ImmichToast.show(
@@ -360,8 +351,7 @@ class _AssetMarkerMeta {
});
@override
String toString() =>
'_AssetMarkerMeta(point: $point, marker: $marker, shouldAnimate: $shouldAnimate)';
String toString() => '_AssetMarkerMeta(point: $point, marker: $marker, shouldAnimate: $shouldAnimate)';
}
class _MapWithMarker extends StatelessWidget {
@@ -35,8 +35,7 @@ class MapLocationPickerPage extends HookConsumerWidget {
selectedLatLng.value = centre;
controller.value?.animateCamera(CameraUpdate.newLatLng(centre));
if (marker.value != null) {
await controller.value
?.updateSymbol(marker.value!, SymbolOptions(geometry: centre));
await controller.value?.updateSymbol(marker.value!, SymbolOptions(geometry: centre));
}
}
@@ -45,15 +44,13 @@ class MapLocationPickerPage extends HookConsumerWidget {
}
Future<void> getCurrentLocation() async {
var (currentLocation, _) =
await MapUtils.checkPermAndGetLocation(context: context);
var (currentLocation, _) = await MapUtils.checkPermAndGetLocation(context: context);
if (currentLocation == null) {
return;
}
var currentLatLng =
LatLng(currentLocation.latitude, currentLocation.longitude);
var currentLatLng = LatLng(currentLocation.latitude, currentLocation.longitude);
selectedLatLng.value = currentLatLng;
controller.value?.animateCamera(CameraUpdate.newLatLng(currentLatLng));
}
@@ -75,11 +72,9 @@ class MapLocationPickerPage extends HookConsumerWidget {
),
),
child: MapLibreMap(
initialCameraPosition:
CameraPosition(target: initialLatLng, zoom: 12),
initialCameraPosition: CameraPosition(target: initialLatLng, zoom: 12),
styleString: style,
onMapCreated: (mapController) =>
controller.value = mapController,
onMapCreated: (mapController) => controller.value = mapController,
onStyleLoadedCallback: onStyleLoaded,
onMapClick: onMapClick,
dragEnabled: false,
@@ -165,8 +160,7 @@ class _BottomBar extends StatelessWidget {
children: [
ElevatedButton(
onPressed: onUseLocation,
child:
const Text("map_location_picker_page_use_location").tr(),
child: const Text("map_location_picker_page_use_location").tr(),
),
ElevatedButton(
onPressed: onGetCurrentLocation,
+14 -38
View File
@@ -48,8 +48,7 @@ class SearchPage extends HookConsumerWidget {
isFavorite: false,
),
mediaType: prefilter?.mediaType ?? AssetType.other,
language:
"${context.locale.languageCode}-${context.locale.countryCode}",
language: "${context.locale.languageCode}-${context.locale.countryCode}",
),
);
@@ -87,9 +86,7 @@ class SearchPage extends HookConsumerWidget {
isSearching.value = true;
ref.watch(paginatedSearchProvider.notifier).clear();
final hasResult = await ref
.watch(paginatedSearchProvider.notifier)
.search(filter.value);
final hasResult = await ref.watch(paginatedSearchProvider.notifier).search(filter.value);
if (!hasResult) {
context.showSnackBar(
@@ -103,9 +100,7 @@ class SearchPage extends HookConsumerWidget {
loadMoreSearchResult() async {
isSearching.value = true;
final hasResult = await ref
.watch(paginatedSearchProvider.notifier)
.search(filter.value);
final hasResult = await ref.watch(paginatedSearchProvider.notifier).search(filter.value);
if (!hasResult) {
context.showSnackBar(
@@ -416,8 +411,7 @@ class SearchPage extends HookConsumerWidget {
),
);
if (value) {
filterText
.add('search_filter_display_option_not_in_album'.tr());
filterText.add('search_filter_display_option_not_in_album'.tr());
}
break;
case DisplayOption.archive:
@@ -563,9 +557,7 @@ class SearchPage extends HookConsumerWidget {
'search_by_context'.tr(),
style: context.textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.w500,
color: textSearchType.value == TextSearchType.context
? context.colorScheme.primary
: null,
color: textSearchType.value == TextSearchType.context ? context.colorScheme.primary : null,
),
),
selectedColor: context.colorScheme.primary,
@@ -583,9 +575,7 @@ class SearchPage extends HookConsumerWidget {
'search_filter_filename'.tr(),
style: context.textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.w500,
color: textSearchType.value == TextSearchType.filename
? context.colorScheme.primary
: null,
color: textSearchType.value == TextSearchType.filename ? context.colorScheme.primary : null,
),
),
selectedColor: context.colorScheme.primary,
@@ -603,15 +593,11 @@ class SearchPage extends HookConsumerWidget {
'search_by_description'.tr(),
style: context.textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.w500,
color:
textSearchType.value == TextSearchType.description
? context.colorScheme.primary
: null,
color: textSearchType.value == TextSearchType.description ? context.colorScheme.primary : null,
),
),
selectedColor: context.colorScheme.primary,
selected:
textSearchType.value == TextSearchType.description,
selected: textSearchType.value == TextSearchType.description,
),
onPressed: () {
textSearchType.value = TextSearchType.description;
@@ -645,9 +631,7 @@ class SearchPage extends HookConsumerWidget {
hintText: searchHintText.value,
key: const Key('search_text_field'),
controller: textSearchController,
contentPadding: prefilter != null
? const EdgeInsets.only(left: 24)
: const EdgeInsets.all(8),
contentPadding: prefilter != null ? const EdgeInsets.only(left: 24) : const EdgeInsets.all(8),
prefixIcon: prefilter != null
? null
: Icon(
@@ -744,17 +728,13 @@ class SearchResultGrid extends StatelessWidget {
padding: const EdgeInsets.only(top: 8.0),
child: NotificationListener<ScrollEndNotification>(
onNotification: (notification) {
final isBottomSheetNotification = notification.context
?.findAncestorWidgetOfExactType<
DraggableScrollableSheet>() !=
null;
final isBottomSheetNotification =
notification.context?.findAncestorWidgetOfExactType<DraggableScrollableSheet>() != null;
final metrics = notification.metrics;
final isVerticalScroll = metrics.axis == Axis.vertical;
if (metrics.pixels >= metrics.maxScrollExtent &&
isVerticalScroll &&
!isBottomSheetNotification) {
if (metrics.pixels >= metrics.maxScrollExtent && isVerticalScroll && !isBottomSheetNotification) {
onScrollEnd();
}
@@ -770,9 +750,7 @@ class SearchResultGrid extends StatelessWidget {
dragScrollLabelEnabled: false,
emptyIndicator: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: !isSearching
? const SearchEmptyContent()
: const SizedBox.shrink(),
child: !isSearching ? const SearchEmptyContent() : const SizedBox.shrink(),
),
),
),
@@ -794,9 +772,7 @@ class SearchEmptyContent extends StatelessWidget {
const SizedBox(height: 40),
Center(
child: Image.asset(
context.isDarkTheme
? 'assets/polaroid-dark.png'
: 'assets/polaroid-light.png',
context.isDarkTheme ? 'assets/polaroid-dark.png' : 'assets/polaroid-light.png',
height: 125,
),
),
@@ -38,9 +38,7 @@ class ShareIntentPage extends HookConsumerWidget {
void upload() async {
for (final attachment in candidates) {
await ref
.read(shareIntentUploadProvider.notifier)
.upload(attachment.file);
await ref.read(shareIntentUploadProvider.notifier).upload(attachment.file);
}
isUploaded.value = true;
@@ -76,9 +74,7 @@ class ShareIntentPage extends HookConsumerWidget {
leading: IconButton(
onPressed: () {
context.navigateTo(
Store.isBetaTimelineEnabled
? const TabShellRoute()
: const TabControllerRoute(),
Store.isBetaTimelineEnabled ? const TabShellRoute() : const TabControllerRoute(),
);
},
icon: const Icon(Icons.arrow_back),
@@ -170,9 +166,7 @@ class ShareIntentPage extends HookConsumerWidget {
height: 48,
child: ElevatedButton(
onPressed: isUploaded.value ? null : upload,
child: isUploaded.value
? UploadingText(candidates: candidates)
: const Text('upload').tr(),
child: isUploaded.value ? UploadingText(candidates: candidates) : const Text('upload').tr(),
),
),
),