You've already forked immich
mirror of
https://github.com/immich-app/immich.git
synced 2025-07-17 15:47:54 +02:00
feat(mobile): add support for material themes (#11560)
* feat(mobile): add support for material themes Added support for custom theming and updated all elements accordingly. * fix(mobile): Restored immich brand colors to default theme * fix(mobile): make ListTile titles bold in settings main page * feat(mobile): update bottom nav and appbar colors * small tweaks --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
@ -57,6 +57,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
||||
? 'assets/immich-text-dark.png'
|
||||
: 'assets/immich-text-light.png',
|
||||
height: 16,
|
||||
color: context.primaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -88,7 +89,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
||||
|
||||
buildSettingButton() {
|
||||
return buildActionButton(
|
||||
Icons.settings_rounded,
|
||||
Icons.settings_outlined,
|
||||
"profile_drawer_settings",
|
||||
() => context.pushRoute(const SettingsRoute()),
|
||||
);
|
||||
@ -146,9 +147,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: context.isDarkTheme
|
||||
? context.scaffoldBackgroundColor
|
||||
: const Color.fromARGB(255, 225, 229, 240),
|
||||
color: context.colorScheme.surface,
|
||||
),
|
||||
child: ListTile(
|
||||
minLeadingWidth: 50,
|
||||
@ -171,10 +170,10 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: LinearProgressIndicator(
|
||||
minHeight: 5.0,
|
||||
minHeight: 10.0,
|
||||
value: percentage,
|
||||
backgroundColor: Colors.grey,
|
||||
color: theme.primaryColor,
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.circular(10.0)),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
@ -248,7 +247,6 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
||||
right: horizontalPadding,
|
||||
bottom: isHorizontal ? 20 : 100,
|
||||
),
|
||||
backgroundColor: theme.cardColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
|
@ -2,6 +2,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/extensions/theme_extensions.dart';
|
||||
import 'package:immich_mobile/providers/upload_profile_image.provider.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
@ -79,9 +80,7 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: context.isDarkTheme
|
||||
? context.scaffoldBackgroundColor
|
||||
: const Color.fromARGB(255, 225, 229, 240),
|
||||
color: context.colorScheme.surface,
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(10),
|
||||
topRight: Radius.circular(10),
|
||||
@ -99,9 +98,7 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
|
||||
bottom: -5,
|
||||
right: -8,
|
||||
child: Material(
|
||||
color: context.isDarkTheme
|
||||
? Colors.blueGrey[800]
|
||||
: Colors.white,
|
||||
color: context.colorScheme.surfaceContainerHighest,
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(50.0),
|
||||
@ -129,7 +126,7 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
|
||||
subtitle: Text(
|
||||
authState.userEmail,
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
color: context.textTheme.bodySmall?.color?.withAlpha(200),
|
||||
color: context.colorScheme.onSurfaceSecondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -2,6 +2,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/extensions/theme_extensions.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_info.model.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
@ -42,9 +43,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
||||
padding: const EdgeInsets.only(left: 10.0, right: 10.0, bottom: 10.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context.isDarkTheme
|
||||
? context.scaffoldBackgroundColor
|
||||
: const Color.fromARGB(255, 225, 229, 240),
|
||||
color: context.colorScheme.surface,
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(10),
|
||||
bottomRight: Radius.circular(10),
|
||||
@ -71,10 +70,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Divider(
|
||||
color: Color.fromARGB(101, 201, 201, 201),
|
||||
thickness: 1,
|
||||
),
|
||||
child: Divider(thickness: 1),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@ -100,8 +96,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
||||
"${appInfo.value["version"]} build.${appInfo.value["buildNumber"]}",
|
||||
style: TextStyle(
|
||||
fontSize: contentFontSize,
|
||||
color: context.textTheme.labelSmall?.color
|
||||
?.withOpacity(0.5),
|
||||
color: context.colorScheme.onSurfaceSecondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@ -111,10 +106,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Divider(
|
||||
color: Color.fromARGB(101, 201, 201, 201),
|
||||
thickness: 1,
|
||||
),
|
||||
child: Divider(thickness: 1),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@ -142,8 +134,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
||||
: "--",
|
||||
style: TextStyle(
|
||||
fontSize: contentFontSize,
|
||||
color: context.textTheme.labelSmall?.color
|
||||
?.withOpacity(0.5),
|
||||
color: context.colorScheme.onSurfaceSecondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@ -153,10 +144,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Divider(
|
||||
color: Color.fromARGB(101, 201, 201, 201),
|
||||
thickness: 1,
|
||||
),
|
||||
child: Divider(thickness: 1),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@ -197,8 +185,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
||||
getServerUrl() ?? '--',
|
||||
style: TextStyle(
|
||||
fontSize: contentFontSize,
|
||||
color: context.textTheme.labelSmall?.color
|
||||
?.withOpacity(0.5),
|
||||
color: context.colorScheme.onSurfaceSecondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
@ -211,10 +198,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Divider(
|
||||
color: Color.fromARGB(101, 201, 201, 201),
|
||||
thickness: 1,
|
||||
),
|
||||
child: Divider(thickness: 1),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@ -255,8 +239,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
||||
: "--",
|
||||
style: TextStyle(
|
||||
fontSize: contentFontSize,
|
||||
color: context.textTheme.labelSmall?.color
|
||||
?.withOpacity(0.5),
|
||||
color: context.colorScheme.onSurfaceSecondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
|
@ -47,7 +47,7 @@ class ConfirmDialog extends StatelessWidget {
|
||||
child: Text(
|
||||
ok,
|
||||
style: TextStyle(
|
||||
color: Colors.red[400],
|
||||
color: context.colorScheme.error,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
|
@ -111,7 +111,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
|
||||
|
||||
buildBackupIndicator() {
|
||||
final indicatorIcon = getBackupBadgeIcon();
|
||||
final badgeBackground = isDarkTheme ? Colors.blueGrey[800] : Colors.white;
|
||||
final badgeBackground = context.colorScheme.surfaceContainer;
|
||||
|
||||
return InkWell(
|
||||
onTap: () => context.pushRoute(const BackupControllerRoute()),
|
||||
@ -123,7 +123,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
|
||||
decoration: BoxDecoration(
|
||||
color: badgeBackground,
|
||||
border: Border.all(
|
||||
color: isDarkTheme ? Colors.black : Colors.grey,
|
||||
color: context.colorScheme.outline.withOpacity(.3),
|
||||
),
|
||||
borderRadius: BorderRadius.circular(widgetSize / 2),
|
||||
),
|
||||
|
@ -21,6 +21,7 @@ class ImmichTitleText extends StatelessWidget {
|
||||
),
|
||||
width: fontSize * 4,
|
||||
filterQuality: FilterQuality.high,
|
||||
color: context.primaryColor,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -51,9 +51,9 @@ class ImmichToast {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
color: context.isDarkTheme ? Colors.grey[900] : Colors.grey[50],
|
||||
color: context.colorScheme.surfaceContainer,
|
||||
border: Border.all(
|
||||
color: Colors.black12,
|
||||
color: context.colorScheme.outline.withOpacity(.5),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
|
Reference in New Issue
Block a user