mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-03 19:17:11 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			256 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			256 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'package:auto_route/auto_route.dart';
 | 
						|
import 'package:easy_localization/easy_localization.dart';
 | 
						|
import 'package:flutter/material.dart';
 | 
						|
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
						|
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
 | 
						|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
 | 
						|
import 'package:immich_mobile/extensions/theme_extensions.dart';
 | 
						|
import 'package:immich_mobile/extensions/translate_extensions.dart';
 | 
						|
import 'package:immich_mobile/presentation/widgets/backup/backup_toggle_button.widget.dart';
 | 
						|
import 'package:immich_mobile/providers/background_sync.provider.dart';
 | 
						|
import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
 | 
						|
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
 | 
						|
import 'package:immich_mobile/providers/user.provider.dart';
 | 
						|
import 'package:immich_mobile/routing/router.dart';
 | 
						|
import 'package:immich_mobile/widgets/backup/backup_info_card.dart';
 | 
						|
 | 
						|
@RoutePage()
 | 
						|
class DriftBackupPage extends ConsumerStatefulWidget {
 | 
						|
  const DriftBackupPage({super.key});
 | 
						|
 | 
						|
  @override
 | 
						|
  ConsumerState<DriftBackupPage> createState() => _DriftBackupPageState();
 | 
						|
}
 | 
						|
 | 
						|
class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
 | 
						|
  @override
 | 
						|
  void initState() {
 | 
						|
    super.initState();
 | 
						|
    final currentUser = ref.read(currentUserProvider);
 | 
						|
    if (currentUser == null) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> startBackup() async {
 | 
						|
    final currentUser = ref.read(currentUserProvider);
 | 
						|
    if (currentUser == null) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    await ref.read(backgroundSyncProvider).syncRemote();
 | 
						|
    await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
 | 
						|
    await ref.read(driftBackupProvider.notifier).startBackup(currentUser.id);
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> stopBackup() async {
 | 
						|
    await ref.read(driftBackupProvider.notifier).cancel();
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    final selectedAlbum = ref
 | 
						|
        .watch(backupAlbumProvider)
 | 
						|
        .where((album) => album.backupSelection == BackupSelection.selected)
 | 
						|
        .toList();
 | 
						|
 | 
						|
    return Scaffold(
 | 
						|
      appBar: AppBar(
 | 
						|
        elevation: 0,
 | 
						|
        title: Text("backup_controller_page_backup".t()),
 | 
						|
        leading: IconButton(
 | 
						|
          onPressed: () {
 | 
						|
            context.maybePop(true);
 | 
						|
          },
 | 
						|
          splashRadius: 24,
 | 
						|
          icon: const Icon(Icons.arrow_back_ios_rounded),
 | 
						|
        ),
 | 
						|
        actions: [
 | 
						|
          IconButton(
 | 
						|
            onPressed: () {
 | 
						|
              context.pushRoute(const DriftBackupOptionsRoute());
 | 
						|
            },
 | 
						|
            icon: const Icon(Icons.settings_outlined),
 | 
						|
            tooltip: "backup_options".t(context: context),
 | 
						|
          ),
 | 
						|
        ],
 | 
						|
      ),
 | 
						|
      body: Stack(
 | 
						|
        children: [
 | 
						|
          Padding(
 | 
						|
            padding: const EdgeInsets.only(left: 16.0, right: 16, bottom: 32),
 | 
						|
            child: ListView(
 | 
						|
              children: [
 | 
						|
                const SizedBox(height: 8),
 | 
						|
                const _BackupAlbumSelectionCard(),
 | 
						|
                if (selectedAlbum.isNotEmpty) ...[
 | 
						|
                  const _TotalCard(),
 | 
						|
                  const _BackupCard(),
 | 
						|
                  const _RemainderCard(),
 | 
						|
                  const Divider(),
 | 
						|
                  BackupToggleButton(onStart: () async => await startBackup(), onStop: () async => await stopBackup()),
 | 
						|
                  TextButton.icon(
 | 
						|
                    icon: const Icon(Icons.info_outline_rounded),
 | 
						|
                    onPressed: () => context.pushRoute(const DriftUploadDetailRoute()),
 | 
						|
                    label: Text("view_details".t(context: context)),
 | 
						|
                  ),
 | 
						|
                ],
 | 
						|
              ],
 | 
						|
            ),
 | 
						|
          ),
 | 
						|
        ],
 | 
						|
      ),
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class _BackupAlbumSelectionCard extends ConsumerWidget {
 | 
						|
  const _BackupAlbumSelectionCard();
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context, WidgetRef ref) {
 | 
						|
    Widget buildSelectedAlbumName() {
 | 
						|
      String text = "backup_controller_page_backup_selected".tr();
 | 
						|
      final albums = ref
 | 
						|
          .watch(backupAlbumProvider)
 | 
						|
          .where((album) => album.backupSelection == BackupSelection.selected)
 | 
						|
          .toList();
 | 
						|
 | 
						|
      if (albums.isNotEmpty) {
 | 
						|
        for (var album in albums) {
 | 
						|
          if (album.name == "Recent" || album.name == "Recents") {
 | 
						|
            text += "${album.name} (${'all'.tr()}), ";
 | 
						|
          } else {
 | 
						|
            text += "${album.name}, ";
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        return Padding(
 | 
						|
          padding: const EdgeInsets.only(top: 8.0),
 | 
						|
          child: Text(
 | 
						|
            text.trim().substring(0, text.length - 2),
 | 
						|
            style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
 | 
						|
          ),
 | 
						|
        );
 | 
						|
      } else {
 | 
						|
        return Padding(
 | 
						|
          padding: const EdgeInsets.only(top: 8.0),
 | 
						|
          child: Text(
 | 
						|
            "backup_controller_page_none_selected".tr(),
 | 
						|
            style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor),
 | 
						|
          ),
 | 
						|
        );
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Widget buildExcludedAlbumName() {
 | 
						|
      String text = "backup_controller_page_excluded".tr();
 | 
						|
      final albums = ref
 | 
						|
          .watch(backupAlbumProvider)
 | 
						|
          .where((album) => album.backupSelection == BackupSelection.excluded)
 | 
						|
          .toList();
 | 
						|
 | 
						|
      if (albums.isNotEmpty) {
 | 
						|
        for (var album in albums) {
 | 
						|
          text += "${album.name}, ";
 | 
						|
        }
 | 
						|
 | 
						|
        return Padding(
 | 
						|
          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]),
 | 
						|
          ),
 | 
						|
        );
 | 
						|
      } else {
 | 
						|
        return const SizedBox();
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return Card(
 | 
						|
      shape: RoundedRectangleBorder(
 | 
						|
        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(),
 | 
						|
        subtitle: Padding(
 | 
						|
          padding: const EdgeInsets.only(top: 8.0),
 | 
						|
          child: Column(
 | 
						|
            crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
            children: [
 | 
						|
              Text(
 | 
						|
                "backup_controller_page_to_backup",
 | 
						|
                style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary),
 | 
						|
              ).tr(),
 | 
						|
              buildSelectedAlbumName(),
 | 
						|
              buildExcludedAlbumName(),
 | 
						|
            ],
 | 
						|
          ),
 | 
						|
        ),
 | 
						|
        trailing: ElevatedButton(
 | 
						|
          onPressed: () async {
 | 
						|
            await context.pushRoute(const DriftBackupAlbumSelectionRoute());
 | 
						|
            final currentUser = ref.read(currentUserProvider);
 | 
						|
            if (currentUser == null) {
 | 
						|
              return;
 | 
						|
            }
 | 
						|
            ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
 | 
						|
          },
 | 
						|
          child: const Text("select", style: TextStyle(fontWeight: FontWeight.bold)).tr(),
 | 
						|
        ),
 | 
						|
      ),
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class _TotalCard extends ConsumerWidget {
 | 
						|
  const _TotalCard();
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context, WidgetRef ref) {
 | 
						|
    final totalCount = ref.watch(driftBackupProvider.select((p) => p.totalCount));
 | 
						|
 | 
						|
    return BackupInfoCard(
 | 
						|
      title: "total".tr(),
 | 
						|
      subtitle: "backup_controller_page_total_sub".tr(),
 | 
						|
      info: totalCount.toString(),
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class _BackupCard extends ConsumerWidget {
 | 
						|
  const _BackupCard();
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context, WidgetRef ref) {
 | 
						|
    final backupCount = ref.watch(driftBackupProvider.select((p) => p.backupCount));
 | 
						|
 | 
						|
    return BackupInfoCard(
 | 
						|
      title: "backup_controller_page_backup".tr(),
 | 
						|
      subtitle: "backup_controller_page_backup_sub".tr(),
 | 
						|
      info: backupCount.toString(),
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class _RemainderCard extends ConsumerWidget {
 | 
						|
  const _RemainderCard();
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context, WidgetRef ref) {
 | 
						|
    final remainderCount = ref.watch(driftBackupProvider.select((p) => p.remainderCount));
 | 
						|
    return BackupInfoCard(
 | 
						|
      title: "backup_controller_page_remainder".tr(),
 | 
						|
      subtitle: "backup_controller_page_remainder_sub".tr(),
 | 
						|
      info: remainderCount.toString(),
 | 
						|
      onTap: () => context.pushRoute(const DriftBackupAssetDetailRoute()),
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |