mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-03 19:29:32 -05:00 
			
		
		
		
	* refactor: autoroutex pushroute * refactor: autoroutex popRoute * refactor: autoroutex navigate and replace * chore: add doc comments for extension methods * refactor: Add LoggerMixin and refactor Album activities to use mixin * refactor: Activity page * chore: activity user from user constructor * fix: update current asset after build method * refactor: tests with similar structure as lib * chore: remove avoid-declaring-call-method rule from dcm analysis * test: fix proper expect order * test: activity_statistics_provider_test * test: activity_provider_test * test: use proper matchers * test: activity_text_field_test & dismissible_activity_test added * test: add http mock to return transparent image * test: download isar core libs during test * test: add widget tags to widget test cases * test: activity_tile_test * build: currentAlbumProvider to generator * movie add / remove like to activity input tile * test: activities_page_test.dart * chore: better error logs * chore: dismissibleactivity as statelesswidget --------- Co-authored-by: shalong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
		
			
				
	
	
		
			189 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'package:auto_route/auto_route.dart';
 | 
						|
import 'package:flutter/material.dart';
 | 
						|
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
						|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
 | 
						|
import 'package:immich_mobile/shared/models/store.dart';
 | 
						|
import 'package:immich_mobile/shared/ui/app_bar_dialog/app_bar_dialog.dart';
 | 
						|
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
 | 
						|
 | 
						|
import 'package:immich_mobile/routing/router.dart';
 | 
						|
import 'package:immich_mobile/modules/backup/models/backup_state.model.dart';
 | 
						|
import 'package:immich_mobile/shared/models/server_info/server_info.model.dart';
 | 
						|
import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
 | 
						|
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
 | 
						|
 | 
						|
class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
 | 
						|
  @override
 | 
						|
  Size get preferredSize => const Size.fromHeight(kToolbarHeight);
 | 
						|
  final Widget? action;
 | 
						|
 | 
						|
  const ImmichAppBar({super.key, this.action});
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context, WidgetRef ref) {
 | 
						|
    final BackUpState backupState = ref.watch(backupProvider);
 | 
						|
    final bool isEnableAutoBackup =
 | 
						|
        backupState.backgroundBackup || backupState.autoBackup;
 | 
						|
    final ServerInfo serverInfoState = ref.watch(serverInfoProvider);
 | 
						|
    final user = Store.tryGet(StoreKey.currentUser);
 | 
						|
    final isDarkTheme = context.isDarkTheme;
 | 
						|
    const widgetSize = 30.0;
 | 
						|
 | 
						|
    buildProfileIndicator() {
 | 
						|
      return InkWell(
 | 
						|
        onTap: () => showDialog(
 | 
						|
          context: context,
 | 
						|
          useRootNavigator: false,
 | 
						|
          builder: (ctx) => const ImmichAppBarDialog(),
 | 
						|
        ),
 | 
						|
        borderRadius: BorderRadius.circular(12),
 | 
						|
        child: Badge(
 | 
						|
          label: Container(
 | 
						|
            decoration: BoxDecoration(
 | 
						|
              color: Colors.black,
 | 
						|
              borderRadius: BorderRadius.circular(widgetSize / 2),
 | 
						|
            ),
 | 
						|
            child: const Icon(
 | 
						|
              Icons.info,
 | 
						|
              color: Color.fromARGB(255, 243, 188, 106),
 | 
						|
              size: widgetSize / 2,
 | 
						|
            ),
 | 
						|
          ),
 | 
						|
          backgroundColor: Colors.transparent,
 | 
						|
          alignment: Alignment.bottomRight,
 | 
						|
          isLabelVisible: serverInfoState.isVersionMismatch ||
 | 
						|
              ((user?.isAdmin ?? false) &&
 | 
						|
                  serverInfoState.isNewReleaseAvailable),
 | 
						|
          offset: const Offset(2, 2),
 | 
						|
          child: user == null
 | 
						|
              ? const Icon(
 | 
						|
                  Icons.face_outlined,
 | 
						|
                  size: widgetSize,
 | 
						|
                )
 | 
						|
              : UserCircleAvatar(
 | 
						|
                  radius: 15,
 | 
						|
                  size: 27,
 | 
						|
                  user: user,
 | 
						|
                ),
 | 
						|
        ),
 | 
						|
      );
 | 
						|
    }
 | 
						|
 | 
						|
    getBackupBadgeIcon() {
 | 
						|
      final iconColor = isDarkTheme ? Colors.white : Colors.black;
 | 
						|
 | 
						|
      if (isEnableAutoBackup) {
 | 
						|
        if (backupState.backupProgress == BackUpProgressEnum.inProgress) {
 | 
						|
          return Container(
 | 
						|
            padding: const EdgeInsets.all(3.5),
 | 
						|
            child: CircularProgressIndicator(
 | 
						|
              strokeWidth: 2,
 | 
						|
              strokeCap: StrokeCap.round,
 | 
						|
              valueColor: AlwaysStoppedAnimation<Color>(iconColor),
 | 
						|
            ),
 | 
						|
          );
 | 
						|
        } else if (backupState.backupProgress !=
 | 
						|
                BackUpProgressEnum.inBackground &&
 | 
						|
            backupState.backupProgress != BackUpProgressEnum.manualInProgress) {
 | 
						|
          return Icon(
 | 
						|
            Icons.check_outlined,
 | 
						|
            size: 9,
 | 
						|
            color: iconColor,
 | 
						|
          );
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (!isEnableAutoBackup) {
 | 
						|
        return Icon(
 | 
						|
          Icons.cloud_off_rounded,
 | 
						|
          size: 9,
 | 
						|
          color: iconColor,
 | 
						|
        );
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    buildBackupIndicator() {
 | 
						|
      final indicatorIcon = getBackupBadgeIcon();
 | 
						|
      final badgeBackground = isDarkTheme ? Colors.blueGrey[800] : Colors.white;
 | 
						|
 | 
						|
      return InkWell(
 | 
						|
        onTap: () => context.pushRoute(const BackupControllerRoute()),
 | 
						|
        borderRadius: BorderRadius.circular(12),
 | 
						|
        child: Badge(
 | 
						|
          label: Container(
 | 
						|
            width: widgetSize / 2,
 | 
						|
            height: widgetSize / 2,
 | 
						|
            decoration: BoxDecoration(
 | 
						|
              color: badgeBackground,
 | 
						|
              border: Border.all(
 | 
						|
                color: isDarkTheme ? Colors.black : Colors.grey,
 | 
						|
              ),
 | 
						|
              borderRadius: BorderRadius.circular(widgetSize / 2),
 | 
						|
            ),
 | 
						|
            child: indicatorIcon,
 | 
						|
          ),
 | 
						|
          backgroundColor: Colors.transparent,
 | 
						|
          alignment: Alignment.bottomRight,
 | 
						|
          isLabelVisible: indicatorIcon != null,
 | 
						|
          offset: const Offset(2, 2),
 | 
						|
          child: Icon(
 | 
						|
            Icons.backup_rounded,
 | 
						|
            size: widgetSize,
 | 
						|
            color: context.primaryColor,
 | 
						|
          ),
 | 
						|
        ),
 | 
						|
      );
 | 
						|
    }
 | 
						|
 | 
						|
    return AppBar(
 | 
						|
      backgroundColor: context.themeData.appBarTheme.backgroundColor,
 | 
						|
      shape: const RoundedRectangleBorder(
 | 
						|
        borderRadius: BorderRadius.all(
 | 
						|
          Radius.circular(5),
 | 
						|
        ),
 | 
						|
      ),
 | 
						|
      automaticallyImplyLeading: false,
 | 
						|
      centerTitle: false,
 | 
						|
      title: Builder(
 | 
						|
        builder: (BuildContext context) {
 | 
						|
          return Row(
 | 
						|
            children: [
 | 
						|
              Container(
 | 
						|
                padding: const EdgeInsets.only(top: 3),
 | 
						|
                width: 28,
 | 
						|
                height: 28,
 | 
						|
                child: Image.asset(
 | 
						|
                  'assets/immich-logo.png',
 | 
						|
                ),
 | 
						|
              ),
 | 
						|
              Container(
 | 
						|
                margin: const EdgeInsets.only(left: 10),
 | 
						|
                child: const Text(
 | 
						|
                  'IMMICH',
 | 
						|
                  style: TextStyle(
 | 
						|
                    fontFamily: 'SnowburstOne',
 | 
						|
                    fontWeight: FontWeight.bold,
 | 
						|
                    fontSize: 24,
 | 
						|
                  ),
 | 
						|
                ),
 | 
						|
              ),
 | 
						|
            ],
 | 
						|
          );
 | 
						|
        },
 | 
						|
      ),
 | 
						|
      actions: [
 | 
						|
        if (action != null)
 | 
						|
          Padding(padding: const EdgeInsets.only(right: 20), child: action!),
 | 
						|
        Padding(
 | 
						|
          padding: const EdgeInsets.only(right: 20),
 | 
						|
          child: buildBackupIndicator(),
 | 
						|
        ),
 | 
						|
        Padding(
 | 
						|
          padding: const EdgeInsets.only(right: 20),
 | 
						|
          child: buildProfileIndicator(),
 | 
						|
        ),
 | 
						|
      ],
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |