refactor(mobile): build context extensions (#4923)

* refactor: move all extensions to separate package

* refactor(mobile): add BuildContext extension

* refactor(mobile): use theme getters from context

* refactor(mobile): use media query size from context

* refactor(mobile): use auto router methods from context

* refactor(mobile): use navigator methods from context

---------

Co-authored-by: shalong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
shenlong
2023-11-09 16:19:53 +00:00
committed by GitHub
parent a147dee4b6
commit bffc2cdf60
106 changed files with 660 additions and 628 deletions
@@ -1,8 +1,8 @@
import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/modules/backup/models/backup_state.model.dart';
import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
import 'package:immich_mobile/modules/backup/providers/manual_upload.provider.dart';
@@ -22,9 +22,8 @@ class ImmichAppBarDialog extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
BackUpState backupState = ref.watch(backupProvider);
final theme = Theme.of(context);
bool isDarkTheme = theme.brightness == Brightness.dark;
bool isHorizontal = MediaQuery.of(context).size.width > 600;
final theme = context.themeData;
bool isHorizontal = !context.isMobile;
final horizontalPadding = isHorizontal ? 100.0 : 20.0;
final user = ref.watch(currentUserProvider);
@@ -40,7 +39,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
return Row(
children: [
InkWell(
onTap: () => Navigator.of(context).pop(),
onTap: () => context.pop(),
child: const Icon(
Icons.close,
size: 20,
@@ -54,7 +53,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
style: TextStyle(
fontFamily: 'SnowburstOne',
fontWeight: FontWeight.bold,
color: Theme.of(context).primaryColor,
color: context.primaryColor,
fontSize: 15,
),
),
@@ -90,7 +89,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
return buildActionButton(
Icons.settings_rounded,
"profile_drawer_settings",
() => AutoRouter.of(context).push(const SettingsRoute()),
() => context.autoPush(const SettingsRoute()),
);
}
@@ -98,7 +97,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
return buildActionButton(
Icons.assignment_outlined,
"profile_drawer_app_logs",
() => AutoRouter.of(context).push(const AppLogRoute()),
() => context.autoPush(const AppLogRoute()),
);
}
@@ -121,7 +120,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
ref.watch(backupProvider.notifier).cancelBackup();
ref.watch(assetProvider.notifier).clearAllAsset();
ref.watch(websocketProvider.notifier).disconnect();
AutoRouter.of(context).replace(const LoginRoute());
context.autoReplace(const LoginRoute());
},
);
},
@@ -136,8 +135,8 @@ class ImmichAppBarDialog extends HookConsumerWidget {
child: Container(
padding: const EdgeInsets.symmetric(vertical: 4),
decoration: BoxDecoration(
color: isDarkTheme
? Theme.of(context).scaffoldBackgroundColor
color: context.isDarkTheme
? context.scaffoldBackgroundColor
: const Color.fromARGB(255, 225, 229, 240),
),
child: ListTile(
@@ -191,7 +190,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
children: [
InkWell(
onTap: () {
Navigator.of(context).pop();
context.pop();
launchUrl(
Uri.parse('https://immich.app'),
mode: LaunchMode.externalApplication,
@@ -199,7 +198,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
},
child: Text(
"profile_drawer_documentation",
style: Theme.of(context).textTheme.bodySmall,
style: context.textTheme.bodySmall,
).tr(),
),
const SizedBox(
@@ -211,7 +210,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
),
InkWell(
onTap: () {
Navigator.of(context).pop();
context.pop();
launchUrl(
Uri.parse('https://github.com/immich-app/immich'),
mode: LaunchMode.externalApplication,
@@ -219,7 +218,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
},
child: Text(
"profile_drawer_github",
style: Theme.of(context).textTheme.bodySmall,
style: context.textTheme.bodySmall,
).tr(),
),
],
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:image_picker/image_picker.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/modules/home/providers/upload_profile_image.provider.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
@@ -18,7 +19,6 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
AuthenticationState authState = ref.watch(authenticationProvider);
final uploadProfileImageStatus =
ref.watch(uploadProfileImageProvider).status;
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
final user = Store.tryGet(StoreKey.currentUser);
buildUserProfileImage() {
@@ -91,8 +91,8 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Theme.of(context).brightness == Brightness.dark
? Theme.of(context).scaffoldBackgroundColor
color: context.isDarkTheme
? context.scaffoldBackgroundColor
: const Color.fromARGB(255, 225, 229, 240),
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(10),
@@ -111,7 +111,9 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
bottom: -5,
right: -8,
child: Material(
color: isDarkMode ? Colors.blueGrey[800] : Colors.white,
color: context.isDarkTheme
? Colors.blueGrey[800]
: Colors.white,
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
@@ -120,7 +122,7 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
padding: const EdgeInsets.all(5.0),
child: Icon(
Icons.camera_alt_outlined,
color: Theme.of(context).primaryColor,
color: context.primaryColor,
size: 14,
),
),
@@ -132,16 +134,16 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
title: Text(
"${authState.firstName} ${authState.lastName}",
style: TextStyle(
color: Theme.of(context).primaryColor,
color: context.primaryColor,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
subtitle: Text(
authState.userEmail,
style: Theme.of(context).textTheme.labelMedium?.copyWith(
fontSize: 12,
),
style: context.textTheme.labelMedium?.copyWith(
fontSize: 12,
),
),
),
),
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/shared/models/server_info/server_info.model.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
@@ -39,8 +40,8 @@ class AppBarServerInfo extends HookConsumerWidget {
padding: const EdgeInsets.only(left: 10.0, right: 10.0, bottom: 10.0),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).brightness == Brightness.dark
? Theme.of(context).scaffoldBackgroundColor
color: context.isDarkTheme
? context.scaffoldBackgroundColor
: const Color.fromARGB(255, 225, 229, 240),
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(10),
@@ -61,7 +62,7 @@ class AppBarServerInfo extends HookConsumerWidget {
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 11,
color: Theme.of(context).primaryColor,
color: context.primaryColor,
fontWeight: FontWeight.w600,
),
),
@@ -83,7 +84,7 @@ class AppBarServerInfo extends HookConsumerWidget {
"server_info_box_app_version".tr(),
style: TextStyle(
fontSize: 11,
color: Theme.of(context).textTheme.labelSmall?.color,
color: context.textTheme.labelSmall?.color,
fontWeight: FontWeight.bold,
),
),
@@ -97,10 +98,7 @@ class AppBarServerInfo extends HookConsumerWidget {
"${appInfo.value["version"]} build.${appInfo.value["buildNumber"]}",
style: TextStyle(
fontSize: 11,
color: Theme.of(context)
.textTheme
.labelSmall
?.color
color: context.textTheme.labelSmall?.color
?.withOpacity(0.5),
fontWeight: FontWeight.bold,
),
@@ -126,7 +124,7 @@ class AppBarServerInfo extends HookConsumerWidget {
"server_info_box_server_version".tr(),
style: TextStyle(
fontSize: 11,
color: Theme.of(context).textTheme.labelSmall?.color,
color: context.textTheme.labelSmall?.color,
fontWeight: FontWeight.bold,
),
),
@@ -142,10 +140,7 @@ class AppBarServerInfo extends HookConsumerWidget {
: "?",
style: TextStyle(
fontSize: 11,
color: Theme.of(context)
.textTheme
.labelSmall
?.color
color: context.textTheme.labelSmall?.color
?.withOpacity(0.5),
fontWeight: FontWeight.bold,
),
@@ -171,7 +166,7 @@ class AppBarServerInfo extends HookConsumerWidget {
"server_info_box_server_url".tr(),
style: TextStyle(
fontSize: 11,
color: Theme.of(context).textTheme.labelSmall?.color,
color: context.textTheme.labelSmall?.color,
fontWeight: FontWeight.bold,
),
),
@@ -185,14 +180,12 @@ class AppBarServerInfo extends HookConsumerWidget {
child: Tooltip(
verticalOffset: 0,
decoration: BoxDecoration(
color:
Theme.of(context).primaryColor.withOpacity(0.9),
color: context.primaryColor.withOpacity(0.9),
borderRadius: BorderRadius.circular(10),
),
textStyle: TextStyle(
color: Theme.of(context).brightness == Brightness.dark
? Colors.black
: Colors.white,
color:
context.isDarkTheme ? Colors.black : Colors.white,
fontWeight: FontWeight.bold,
),
message: getServerUrl() ?? '--',
@@ -202,10 +195,7 @@ class AppBarServerInfo extends HookConsumerWidget {
getServerUrl() ?? '--',
style: TextStyle(
fontSize: 11,
color: Theme.of(context)
.textTheme
.labelSmall
?.color
color: context.textTheme.labelSmall?.color
?.withOpacity(0.5),
fontWeight: FontWeight.bold,
overflow: TextOverflow.ellipsis,
+4 -3
View File
@@ -1,6 +1,7 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
class ConfirmDialog extends ConsumerWidget {
final Function onOk;
@@ -26,11 +27,11 @@ class ConfirmDialog extends ConsumerWidget {
content: Text(content).tr(),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(false),
onPressed: () => context.pop(false),
child: Text(
cancel,
style: TextStyle(
color: Theme.of(context).primaryColor,
color: context.primaryColor,
fontWeight: FontWeight.bold,
),
).tr(),
@@ -38,7 +39,7 @@ class ConfirmDialog extends ConsumerWidget {
TextButton(
onPressed: () {
onOk();
Navigator.of(context).pop(true);
context.pop(true);
},
child: Text(
ok,
+8 -8
View File
@@ -1,6 +1,6 @@
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';
@@ -28,7 +28,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
final ServerInfo serverInfoState = ref.watch(serverInfoProvider);
AuthenticationState authState = ref.watch(authenticationProvider);
final user = Store.tryGet(StoreKey.currentUser);
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
final isDarkTheme = context.isDarkTheme;
const widgetSize = 30.0;
buildProfileIndicator() {
@@ -70,7 +70,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
}
getBackupBadgeIcon() {
final iconColor = isDarkMode ? Colors.white : Colors.black;
final iconColor = isDarkTheme ? Colors.white : Colors.black;
if (isEnableAutoBackup) {
if (backupState.backupProgress == BackUpProgressEnum.inProgress) {
@@ -104,10 +104,10 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
buildBackupIndicator() {
final indicatorIcon = getBackupBadgeIcon();
final badgeBackground = isDarkMode ? Colors.blueGrey[800] : Colors.white;
final badgeBackground = isDarkTheme ? Colors.blueGrey[800] : Colors.white;
return InkWell(
onTap: () => AutoRouter.of(context).push(const BackupControllerRoute()),
onTap: () => context.autoPush(const BackupControllerRoute()),
borderRadius: BorderRadius.circular(12),
child: Badge(
label: Container(
@@ -116,7 +116,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
decoration: BoxDecoration(
color: badgeBackground,
border: Border.all(
color: isDarkMode ? Colors.black : Colors.grey,
color: isDarkTheme ? Colors.black : Colors.grey,
),
borderRadius: BorderRadius.circular(widgetSize / 2),
),
@@ -129,14 +129,14 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
child: Icon(
Icons.backup_rounded,
size: widgetSize,
color: Theme.of(context).primaryColor,
color: context.primaryColor,
),
),
);
}
return AppBar(
backgroundColor: Theme.of(context).appBarTheme.backgroundColor,
backgroundColor: context.themeData.appBarTheme.backgroundColor,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5),
+3 -2
View File
@@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/utils/image_url_builder.dart';
@@ -86,7 +87,7 @@ class ImmichImage extends StatelessWidget {
}
return Icon(
Icons.image_not_supported_outlined,
color: Theme.of(context).primaryColor,
color: context.primaryColor,
);
},
);
@@ -137,7 +138,7 @@ class ImmichImage extends StatelessWidget {
}
return Icon(
Icons.image_not_supported_outlined,
color: Theme.of(context).primaryColor,
color: context.primaryColor,
);
},
);
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
class ImmichLoadingIndicator extends StatelessWidget {
final double? borderRadius;
@@ -14,7 +15,7 @@ class ImmichLoadingIndicator extends StatelessWidget {
height: 60,
width: 60,
decoration: BoxDecoration(
color: Theme.of(context).primaryColor.withAlpha(200),
color: context.primaryColor.withAlpha(200),
borderRadius: BorderRadius.circular(borderRadius ?? 10),
),
padding: const EdgeInsets.all(15),
+2 -2
View File
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
class ImmichTitleText extends StatelessWidget {
final double fontSize;
@@ -18,9 +19,8 @@ class ImmichTitleText extends StatelessWidget {
fontFamily: 'SnowburstOne',
fontWeight: FontWeight.bold,
fontSize: fontSize,
color: color ?? Theme.of(context).primaryColor,
color: color ?? context.primaryColor,
),
);
}
}
+4 -4
View File
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
enum ToastType { info, success, error }
@@ -11,14 +12,13 @@ class ImmichToast {
ToastGravity gravity = ToastGravity.TOP,
int durationInSecond = 3,
}) {
final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
final fToast = FToast();
fToast.init(context);
Color getColor(ToastType type, BuildContext context) {
switch (type) {
case ToastType.info:
return Theme.of(context).primaryColor;
return context.primaryColor;
case ToastType.success:
return const Color.fromARGB(255, 78, 140, 124);
case ToastType.error:
@@ -31,7 +31,7 @@ class ImmichToast {
case ToastType.info:
return Icon(
Icons.info_outline_rounded,
color: Theme.of(context).primaryColor,
color: context.primaryColor,
);
case ToastType.success:
return const Icon(
@@ -51,7 +51,7 @@ class ImmichToast {
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: isDarkTheme ? Colors.grey[900] : Colors.grey[50],
color: context.isDarkTheme ? Colors.grey[900] : Colors.grey[50],
border: Border.all(
color: Colors.black12,
width: 1,
+2 -1
View File
@@ -1,5 +1,6 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/models/user.dart';
@@ -10,7 +11,7 @@ Widget userAvatar(BuildContext context, User u, {double? radius}) {
final lastNameFirstLetter = u.lastName.isNotEmpty ? u.lastName[0] : "";
return CircleAvatar(
radius: radius,
backgroundColor: Theme.of(context).primaryColor.withAlpha(50),
backgroundColor: context.primaryColor.withAlpha(50),
foregroundImage: CachedNetworkImageProvider(
url,
headers: {"Authorization": "Bearer ${Store.get(StoreKey.accessToken)}"},
+3 -4
View File
@@ -3,6 +3,7 @@ import 'dart:math';
import 'package:cached_network_image/cached_network_image.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/models/user.dart';
import 'package:immich_mobile/shared/ui/transparent_image.dart';
@@ -45,15 +46,13 @@ class UserCircleAvatar extends ConsumerWidget {
user.firstName[0].toUpperCase(),
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context).brightness == Brightness.dark
? Colors.black
: Colors.white,
color: context.isDarkTheme ? Colors.black : Colors.white,
),
);
return CircleAvatar(
backgroundColor: useRandomBackgroundColor
? randomColors[Random().nextInt(randomColors.length)]
: Theme.of(context).primaryColor,
: context.primaryColor,
radius: radius,
child: user.profileImagePath == ""
? textIcon