mirror of
https://github.com/immich-app/immich.git
synced 2024-11-28 09:33:27 +02:00
refactor(mobile): immich loading overlay (#5320)
* refactor: dcm fixes * refactor: ImmichLoadingOverlay to custom hook * chore: dart fixes * pr changes * fix: process overlay add / remove in postframecallback --------- Co-authored-by: shalong-tanwen <139912620+shalong-tanwen@users.noreply.github.com> Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
parent
513f252a0c
commit
527d602a9f
@ -49,7 +49,6 @@ dart_code_metrics:
|
||||
# Common
|
||||
- avoid-accessing-collections-by-constant-index
|
||||
- avoid-accessing-other-classes-private-members
|
||||
- avoid-async-call-in-sync-function
|
||||
- avoid-cascade-after-if-null
|
||||
- avoid-collapsible-if
|
||||
- avoid-collection-methods-with-unrelated-types
|
||||
|
@ -45,7 +45,7 @@ class ImmichTestHelper {
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [dbProvider.overrideWithValue(db)],
|
||||
child: app.getMainWidget(),
|
||||
child: const app.MainWidget(),
|
||||
),
|
||||
);
|
||||
// Post run tasks
|
||||
|
@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Color immichBackgroundColor = const Color(0xFFf6f8fe);
|
||||
Color immichDarkBackgroundColor = const Color.fromARGB(255, 0, 0, 0);
|
||||
Color immichDarkThemePrimaryColor = const Color.fromARGB(255, 173, 203, 250);
|
||||
const Color immichBackgroundColor = Color(0xFFf6f8fe);
|
||||
const Color immichDarkBackgroundColor = Color.fromARGB(255, 0, 0, 0);
|
||||
const Color immichDarkThemePrimaryColor = Color.fromARGB(255, 173, 203, 250);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
@ -7,6 +8,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:timezone/data/latest.dart';
|
||||
import 'package:immich_mobile/constants/locales.dart';
|
||||
import 'package:immich_mobile/modules/backup/background_service/background.service.dart';
|
||||
@ -28,7 +30,6 @@ import 'package:immich_mobile/shared/providers/app_state.provider.dart';
|
||||
import 'package:immich_mobile/shared/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/shared/services/immich_logger.service.dart';
|
||||
import 'package:immich_mobile/shared/services/local_notification.service.dart';
|
||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||
import 'package:immich_mobile/utils/http_ssl_cert_override.dart';
|
||||
import 'package:immich_mobile/utils/immich_app_theme.dart';
|
||||
import 'package:immich_mobile/utils/migration.dart';
|
||||
@ -43,10 +44,11 @@ void main() async {
|
||||
await initApp();
|
||||
await migrateDatabaseIfNeeded(db);
|
||||
HttpOverrides.global = HttpSSLCertOverride();
|
||||
|
||||
runApp(
|
||||
ProviderScope(
|
||||
overrides: [dbProvider.overrideWithValue(db)],
|
||||
child: getMainWidget(),
|
||||
child: const MainWidget(),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -108,16 +110,6 @@ Future<Isar> loadDb() async {
|
||||
return db;
|
||||
}
|
||||
|
||||
Widget getMainWidget() {
|
||||
return EasyLocalization(
|
||||
supportedLocales: locales,
|
||||
path: translationsPath,
|
||||
useFallbackTranslations: true,
|
||||
fallbackLocale: locales.first,
|
||||
child: const ImmichApp(),
|
||||
);
|
||||
}
|
||||
|
||||
class ImmichApp extends ConsumerStatefulWidget {
|
||||
const ImmichApp({super.key});
|
||||
|
||||
@ -167,10 +159,9 @@ class ImmichAppState extends ConsumerState<ImmichApp>
|
||||
// Android 8 does not support transparent app bars
|
||||
final info = await DeviceInfoPlugin().androidInfo;
|
||||
if (info.version.sdkInt <= 26) {
|
||||
overlayStyle =
|
||||
MediaQuery.of(context).platformBrightness == Brightness.light
|
||||
? SystemUiOverlayStyle.light
|
||||
: SystemUiOverlayStyle.dark;
|
||||
overlayStyle = context.isDarkTheme
|
||||
? SystemUiOverlayStyle.dark
|
||||
: SystemUiOverlayStyle.light;
|
||||
}
|
||||
}
|
||||
SystemChrome.setSystemUIOverlayStyle(overlayStyle);
|
||||
@ -202,22 +193,33 @@ class ImmichAppState extends ConsumerState<ImmichApp>
|
||||
supportedLocales: context.supportedLocales,
|
||||
locale: context.locale,
|
||||
debugShowCheckedModeBanner: false,
|
||||
home: Stack(
|
||||
children: [
|
||||
MaterialApp.router(
|
||||
title: 'Immich',
|
||||
debugShowCheckedModeBanner: false,
|
||||
themeMode: ref.watch(immichThemeProvider),
|
||||
darkTheme: immichDarkTheme,
|
||||
theme: immichLightTheme,
|
||||
routeInformationParser: router.defaultRouteParser(),
|
||||
routerDelegate: router.delegate(
|
||||
navigatorObservers: () => [TabNavigationObserver(ref: ref)],
|
||||
),
|
||||
),
|
||||
const ImmichLoadingOverlay(),
|
||||
],
|
||||
home: MaterialApp.router(
|
||||
title: 'Immich',
|
||||
debugShowCheckedModeBanner: false,
|
||||
themeMode: ref.watch(immichThemeProvider),
|
||||
darkTheme: immichDarkTheme,
|
||||
theme: immichLightTheme,
|
||||
routeInformationParser: router.defaultRouteParser(),
|
||||
routerDelegate: router.delegate(
|
||||
navigatorObservers: () => [TabNavigationObserver(ref: ref)],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ignore: prefer-single-widget-per-file
|
||||
class MainWidget extends StatelessWidget {
|
||||
const MainWidget({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return EasyLocalization(
|
||||
supportedLocales: locales,
|
||||
path: translationsPath,
|
||||
useFallbackTranslations: true,
|
||||
fallbackLocale: locales.first,
|
||||
child: const ImmichApp(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final newAlbumTitle = ref.watch(albumViewerProvider).editTitleText;
|
||||
final isEditAlbum = ref.watch(albumViewerProvider).isEditAlbum;
|
||||
final isProcessing = useProcessingOverlay();
|
||||
final comments = album.shared
|
||||
? ref.watch(
|
||||
activityStatisticsStateProvider(
|
||||
@ -52,7 +53,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
: 0;
|
||||
|
||||
deleteAlbum() async {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
final bool success;
|
||||
if (album.shared) {
|
||||
@ -74,7 +75,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
);
|
||||
}
|
||||
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
Future<void> showConfirmationDialog() async {
|
||||
@ -122,7 +123,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
}
|
||||
|
||||
void onLeaveAlbumPressed() async {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
bool isSuccess =
|
||||
await ref.watch(sharedAlbumProvider.notifier).leaveAlbum(album);
|
||||
@ -140,11 +141,11 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
);
|
||||
}
|
||||
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
void onRemoveFromAlbumPressed() async {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
bool isSuccess =
|
||||
await ref.watch(sharedAlbumProvider.notifier).removeAssetFromAlbum(
|
||||
@ -167,7 +168,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
);
|
||||
}
|
||||
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
void handleShareAssets(
|
||||
@ -198,9 +199,9 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
}
|
||||
|
||||
void onShareAssetsTo() async {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
handleShareAssets(ref, context, selected);
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
buildBottomSheetActions() {
|
||||
|
@ -24,6 +24,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
||||
final owner = album.owner.value;
|
||||
final userId = ref.watch(authenticationProvider).userId;
|
||||
final activityEnabled = useState(album.activityEnabled);
|
||||
final isProcessing = useProcessingOverlay();
|
||||
final isOwner = owner?.id == userId;
|
||||
|
||||
void showErrorMessage() {
|
||||
@ -37,7 +38,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
void leaveAlbum() async {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
try {
|
||||
final isSuccess =
|
||||
@ -54,11 +55,11 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
||||
showErrorMessage();
|
||||
}
|
||||
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
void removeUserFromAlbum(User user) async {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
try {
|
||||
await ref
|
||||
@ -71,7 +72,7 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
context.pop();
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
void handleUserClick(User user) {
|
||||
|
@ -33,6 +33,7 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
final userId = ref.watch(authenticationProvider).userId;
|
||||
final selection = useState<Set<Asset>>({});
|
||||
final multiSelectEnabled = useState(false);
|
||||
final isProcessing = useProcessingOverlay();
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
@ -75,24 +76,21 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
),
|
||||
);
|
||||
|
||||
if (returnPayload != null) {
|
||||
if (returnPayload != null && returnPayload.selectedAssets.isNotEmpty) {
|
||||
// Check if there is new assets add
|
||||
if (returnPayload.selectedAssets.isNotEmpty) {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
var addAssetsResult =
|
||||
await ref.watch(albumServiceProvider).addAdditionalAssetToAlbum(
|
||||
returnPayload.selectedAssets,
|
||||
albumInfo,
|
||||
);
|
||||
var addAssetsResult =
|
||||
await ref.watch(albumServiceProvider).addAdditionalAssetToAlbum(
|
||||
returnPayload.selectedAssets,
|
||||
albumInfo,
|
||||
);
|
||||
|
||||
if (addAssetsResult != null &&
|
||||
addAssetsResult.successfullyAdded > 0) {
|
||||
ref.invalidate(albumDetailProvider(albumId));
|
||||
}
|
||||
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
if (addAssetsResult != null && addAssetsResult.successfullyAdded > 0) {
|
||||
ref.invalidate(albumDetailProvider(albumId));
|
||||
}
|
||||
|
||||
isProcessing.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +100,7 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
if (sharedUserIds != null) {
|
||||
ImmichLoadingOverlayController.appLoader.show();
|
||||
isProcessing.value = true;
|
||||
|
||||
var isSuccess = await ref
|
||||
.watch(albumServiceProvider)
|
||||
@ -112,7 +110,7 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
ref.invalidate(albumDetailProvider(album.id));
|
||||
}
|
||||
|
||||
ImmichLoadingOverlayController.appLoader.hide();
|
||||
isProcessing.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ import 'package:immich_mobile/shared/providers/websocket.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_app_bar.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_toast.dart';
|
||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||
import 'package:immich_mobile/utils/selection_handlers.dart';
|
||||
|
||||
class HomePage extends HookConsumerWidget {
|
||||
@ -50,7 +51,7 @@ class HomePage extends HookConsumerWidget {
|
||||
|
||||
final tipOneOpacity = useState(0.0);
|
||||
final refreshCount = useState(0);
|
||||
final processing = useState(false);
|
||||
final processing = useProcessingOverlay();
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
@ -212,10 +213,10 @@ class HomePage extends HookConsumerWidget {
|
||||
processing.value = true;
|
||||
selectionEnabledHook.value = false;
|
||||
try {
|
||||
ref.read(manualUploadProvider.notifier).uploadAssets(
|
||||
context,
|
||||
selection.value.where((a) => a.storage == AssetState.local),
|
||||
);
|
||||
ref.read(manualUploadProvider.notifier).uploadAssets(
|
||||
context,
|
||||
selection.value.where((a) => a.storage == AssetState.local),
|
||||
);
|
||||
} finally {
|
||||
processing.value = false;
|
||||
}
|
||||
@ -323,16 +324,12 @@ class HomePage extends HookConsumerWidget {
|
||||
} else {
|
||||
refreshCount.value++;
|
||||
// set counter back to 0 if user does not request refresh again
|
||||
Timer(const Duration(seconds: 4), () {
|
||||
refreshCount.value = 0;
|
||||
});
|
||||
Timer(const Duration(seconds: 4), () => refreshCount.value = 0);
|
||||
}
|
||||
}
|
||||
|
||||
buildLoadingIndicator() {
|
||||
Timer(const Duration(seconds: 2), () {
|
||||
tipOneOpacity.value = 1;
|
||||
});
|
||||
Timer(const Duration(seconds: 2), () => tipOneOpacity.value = 1);
|
||||
|
||||
return Center(
|
||||
child: Column(
|
||||
@ -415,7 +412,6 @@ class HomePage extends HookConsumerWidget {
|
||||
selectionAssetState: selectionAssetState.value,
|
||||
onStack: onStack,
|
||||
),
|
||||
if (processing.value) const Center(child: ImmichLoadingIndicator()),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -12,8 +12,8 @@ import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/confirm_dialog.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_toast.dart';
|
||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||
|
||||
class TrashPage extends HookConsumerWidget {
|
||||
const TrashPage({super.key});
|
||||
@ -25,7 +25,7 @@ class TrashPage extends HookConsumerWidget {
|
||||
ref.watch(serverInfoProvider.select((v) => v.serverConfig.trashDays));
|
||||
final selectionEnabledHook = useState(false);
|
||||
final selection = useState(<Asset>{});
|
||||
final processing = useState(false);
|
||||
final processing = useProcessingOverlay();
|
||||
|
||||
void selectionListener(
|
||||
bool multiselect,
|
||||
@ -261,8 +261,6 @@ class TrashPage extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
if (selectionEnabledHook.value) buildBottomBar(),
|
||||
if (processing.value)
|
||||
const Center(child: ImmichLoadingIndicator()),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -21,7 +21,7 @@ class ImmichLoadingIndicator extends StatelessWidget {
|
||||
padding: const EdgeInsets.all(15),
|
||||
child: const CircularProgressIndicator(
|
||||
color: Colors.white,
|
||||
strokeWidth: 2,
|
||||
strokeWidth: 3,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1,41 +1,64 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
|
||||
class ImmichLoadingOverlay extends StatelessWidget {
|
||||
const ImmichLoadingOverlay({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
final _loadingEntry = OverlayEntry(
|
||||
builder: (context) => SizedBox.square(
|
||||
dimension: double.infinity,
|
||||
child: DecoratedBox(
|
||||
decoration:
|
||||
BoxDecoration(color: context.colorScheme.surface.withAlpha(200)),
|
||||
child: const Center(child: ImmichLoadingIndicator()),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
ValueNotifier<bool> useProcessingOverlay() {
|
||||
return use(const _LoadingOverlay());
|
||||
}
|
||||
|
||||
class _LoadingOverlay extends Hook<ValueNotifier<bool>> {
|
||||
const _LoadingOverlay();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ValueListenableBuilder<bool>(
|
||||
valueListenable:
|
||||
ImmichLoadingOverlayController.appLoader.loaderShowingNotifier,
|
||||
builder: (context, shouldShow, child) {
|
||||
return shouldShow
|
||||
? const Scaffold(
|
||||
backgroundColor: Colors.black54,
|
||||
body: Center(
|
||||
child: ImmichLoadingIndicator(),
|
||||
),
|
||||
)
|
||||
: const SizedBox();
|
||||
},
|
||||
);
|
||||
}
|
||||
_LoadingOverlayState createState() => _LoadingOverlayState();
|
||||
}
|
||||
|
||||
class ImmichLoadingOverlayController {
|
||||
static final ImmichLoadingOverlayController appLoader =
|
||||
ImmichLoadingOverlayController();
|
||||
ValueNotifier<bool> loaderShowingNotifier = ValueNotifier(false);
|
||||
ValueNotifier<String> loaderTextNotifier = ValueNotifier('error message');
|
||||
class _LoadingOverlayState
|
||||
extends HookState<ValueNotifier<bool>, _LoadingOverlay> {
|
||||
late final _isProcessing = ValueNotifier(false)..addListener(_listener);
|
||||
OverlayEntry? overlayEntry;
|
||||
|
||||
void show() {
|
||||
loaderShowingNotifier.value = true;
|
||||
void _listener() {
|
||||
setState(() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (_isProcessing.value) {
|
||||
overlayEntry?.remove();
|
||||
overlayEntry = _loadingEntry;
|
||||
Overlay.of(context).insert(_loadingEntry);
|
||||
} else {
|
||||
overlayEntry?.remove();
|
||||
overlayEntry = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void hide() {
|
||||
loaderShowingNotifier.value = false;
|
||||
@override
|
||||
ValueNotifier<bool> build(BuildContext context) {
|
||||
return _isProcessing;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_isProcessing.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Object? get debugValue => _isProcessing.value;
|
||||
|
||||
@override
|
||||
String get debugLabel => 'useProcessingOverlay<>';
|
||||
}
|
||||
|
@ -48,8 +48,8 @@ ThemeData immichLightTheme = ThemeData(
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
),
|
||||
appBarTheme: AppBarTheme(
|
||||
titleTextStyle: const TextStyle(
|
||||
appBarTheme: const AppBarTheme(
|
||||
titleTextStyle: TextStyle(
|
||||
fontFamily: 'Overpass',
|
||||
color: Colors.indigo,
|
||||
fontWeight: FontWeight.bold,
|
||||
@ -61,7 +61,7 @@ ThemeData immichLightTheme = ThemeData(
|
||||
scrolledUnderElevation: 0,
|
||||
centerTitle: true,
|
||||
),
|
||||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
backgroundColor: immichBackgroundColor,
|
||||
selectedItemColor: Colors.indigo,
|
||||
@ -69,7 +69,7 @@ ThemeData immichLightTheme = ThemeData(
|
||||
cardTheme: const CardTheme(
|
||||
surfaceTintColor: Colors.transparent,
|
||||
),
|
||||
drawerTheme: DrawerThemeData(
|
||||
drawerTheme: const DrawerThemeData(
|
||||
backgroundColor: immichBackgroundColor,
|
||||
),
|
||||
textTheme: const TextTheme(
|
||||
@ -162,7 +162,7 @@ ThemeData immichDarkTheme = ThemeData(
|
||||
hintColor: Colors.grey[600],
|
||||
fontFamily: 'Overpass',
|
||||
snackBarTheme: SnackBarThemeData(
|
||||
contentTextStyle: TextStyle(
|
||||
contentTextStyle: const TextStyle(
|
||||
fontFamily: 'Overpass',
|
||||
color: immichDarkThemePrimaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
@ -174,35 +174,35 @@ ThemeData immichDarkTheme = ThemeData(
|
||||
foregroundColor: immichDarkThemePrimaryColor,
|
||||
),
|
||||
),
|
||||
appBarTheme: AppBarTheme(
|
||||
appBarTheme: const AppBarTheme(
|
||||
titleTextStyle: TextStyle(
|
||||
fontFamily: 'Overpass',
|
||||
color: immichDarkThemePrimaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
),
|
||||
backgroundColor: const Color.fromARGB(255, 32, 33, 35),
|
||||
backgroundColor: Color.fromARGB(255, 32, 33, 35),
|
||||
foregroundColor: immichDarkThemePrimaryColor,
|
||||
elevation: 0,
|
||||
scrolledUnderElevation: 0,
|
||||
centerTitle: true,
|
||||
),
|
||||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
backgroundColor: const Color.fromARGB(255, 35, 36, 37),
|
||||
backgroundColor: Color.fromARGB(255, 35, 36, 37),
|
||||
selectedItemColor: immichDarkThemePrimaryColor,
|
||||
),
|
||||
drawerTheme: DrawerThemeData(
|
||||
backgroundColor: immichDarkBackgroundColor,
|
||||
scrimColor: Colors.white.withOpacity(0.1),
|
||||
),
|
||||
textTheme: TextTheme(
|
||||
displayLarge: const TextStyle(
|
||||
textTheme: const TextTheme(
|
||||
displayLarge: TextStyle(
|
||||
fontSize: 26,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color.fromARGB(255, 255, 255, 255),
|
||||
),
|
||||
displayMedium: const TextStyle(
|
||||
displayMedium: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color.fromARGB(255, 255, 255, 255),
|
||||
@ -212,15 +212,15 @@ ThemeData immichDarkTheme = ThemeData(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: immichDarkThemePrimaryColor,
|
||||
),
|
||||
titleSmall: const TextStyle(
|
||||
titleSmall: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
titleMedium: const TextStyle(
|
||||
titleMedium: TextStyle(
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
titleLarge: const TextStyle(
|
||||
titleLarge: TextStyle(
|
||||
fontSize: 26.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
@ -258,7 +258,7 @@ ThemeData immichDarkTheme = ThemeData(
|
||||
dialogTheme: const DialogTheme(
|
||||
surfaceTintColor: Colors.transparent,
|
||||
),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
inputDecorationTheme: const InputDecorationTheme(
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: immichDarkThemePrimaryColor,
|
||||
@ -267,12 +267,12 @@ ThemeData immichDarkTheme = ThemeData(
|
||||
labelStyle: TextStyle(
|
||||
color: immichDarkThemePrimaryColor,
|
||||
),
|
||||
hintStyle: const TextStyle(
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
textSelectionTheme: TextSelectionThemeData(
|
||||
textSelectionTheme: const TextSelectionThemeData(
|
||||
cursorColor: immichDarkThemePrimaryColor,
|
||||
),
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user