mirror of
https://github.com/immich-app/immich.git
synced 2024-11-28 09:33:27 +02:00
Add mobile dark mode and user setting (#468)
* styling light and dark theme * Icon topbar * Fixed app bar title dark theme * Fixed issue with getting thumbnail for things * Refactor sharing page * Refactor scroll thumb * Refactor chip in auto backup indiation button * Refactor sharing page * Added theme toggle * Up version for testflight build * Refactor backup controller page * Refactor album selection page * refactor album pages * Refactor gradient color profile header * Added theme switcher * Register app theme correctly * Added locale to the app * Added translation key * Styling for bottomsheet colors * up server version * Fixed font size * Fixed overlapsed sliverappbar on photos screen
This commit is contained in:
parent
30f069a5db
commit
c1b22125fd
@ -30,8 +30,8 @@ platform :android do
|
||||
task: 'bundle',
|
||||
build_type: 'Release',
|
||||
properties: {
|
||||
"android.injected.version.code" => 32,
|
||||
"android.injected.version.name" => "1.22.0",
|
||||
"android.injected.version.code" => 33,
|
||||
"android.injected.version.name" => "1.23.0",
|
||||
}
|
||||
)
|
||||
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
||||
|
@ -48,7 +48,7 @@
|
||||
"control_bottom_app_bar_delete": "Delete",
|
||||
"create_shared_album_page_share": "Share",
|
||||
"create_shared_album_page_create": "Create",
|
||||
"create_shared_album_page_share_add_assets": "ADD ASSETS",
|
||||
"create_shared_album_page_share_add_assets": "ADD PHOTOS",
|
||||
"create_shared_album_page_share_select_photos": "Select Photos",
|
||||
"daily_title_text_date": "E, MMM dd",
|
||||
"daily_title_text_date_year": "E, MMM dd, yyyy",
|
||||
@ -113,5 +113,14 @@
|
||||
"library_page_new_album": "New album",
|
||||
"create_album_page_untitled": "Untitled",
|
||||
"share_dialog_preparing": "Preparing...",
|
||||
"control_bottom_app_bar_share": "Share"
|
||||
"control_bottom_app_bar_share": "Share",
|
||||
"setting_pages_app_bar_settings": "Settings",
|
||||
"theme_setting_theme_title": "Theme",
|
||||
"theme_setting_theme_subtitle": "Choose the app's theme setting",
|
||||
"theme_setting_system_theme_switch": "Automatic (Follow system setting)",
|
||||
"theme_setting_dark_mode_switch": "Dark mode",
|
||||
"theme_setting_image_viewer_quality_title": "Image viewer quality",
|
||||
"theme_setting_image_viewer_quality_subtitle": "Adjust the quality of the detail image viewer",
|
||||
"theme_setting_three_stage_loading_title": "Enable three-stage loading",
|
||||
"theme_setting_three_stage_loading_subtitle": "The three-stage loading delivers the best quality image in exchange for a slower loading speed"
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ platform :ios do
|
||||
desc "iOS Beta"
|
||||
lane :beta do
|
||||
increment_version_number(
|
||||
version_number: "1.22.0"
|
||||
version_number: "1.23.0"
|
||||
)
|
||||
increment_build_number(
|
||||
build_number: latest_testflight_build_number + 1,
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
const immichBackgroundColor = Color(0xFFf6f8fe);
|
||||
Color immichBackgroundColor = const Color(0xFFf6f8fe);
|
||||
Color immichDarkBackgroundColor = const Color.fromARGB(255, 0, 0, 0);
|
||||
Color immichDarkThemePrimaryColor = const Color.fromARGB(255, 173, 203, 250);
|
||||
|
@ -7,7 +7,6 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/immich_colors.dart';
|
||||
import 'package:immich_mobile/modules/backup/models/hive_backup_albums.model.dart';
|
||||
import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
|
||||
import 'package:immich_mobile/modules/login/models/hive_saved_login_info.model.dart';
|
||||
@ -19,8 +18,10 @@ import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||
import 'package:immich_mobile/shared/providers/release_info.provider.dart';
|
||||
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/shared/providers/websocket.provider.dart';
|
||||
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
|
||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||
import 'package:immich_mobile/shared/views/version_announcement_overlay.dart';
|
||||
import 'package:immich_mobile/utils/immich_app_theme.dart';
|
||||
import 'constants/hive_box.dart';
|
||||
|
||||
void main() async {
|
||||
@ -50,8 +51,11 @@ void main() async {
|
||||
Locale('da', 'DK'),
|
||||
Locale('de', 'DE'),
|
||||
Locale('es', 'ES'),
|
||||
Locale('fi', 'FI'),
|
||||
Locale('fr', 'FR'),
|
||||
Locale('it', 'IT'),
|
||||
Locale('ja', 'JP'),
|
||||
Locale('pl', 'PL')
|
||||
];
|
||||
|
||||
if (kReleaseMode && Platform.isAndroid) {
|
||||
@ -130,7 +134,6 @@ class ImmichAppState extends ConsumerState<ImmichApp>
|
||||
@override
|
||||
initState() {
|
||||
super.initState();
|
||||
|
||||
initApp().then((_) => debugPrint("App Init Completed"));
|
||||
}
|
||||
|
||||
@ -155,23 +158,9 @@ class ImmichAppState extends ConsumerState<ImmichApp>
|
||||
MaterialApp.router(
|
||||
title: 'Immich',
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: Brightness.light,
|
||||
primarySwatch: Colors.indigo,
|
||||
fontFamily: 'WorkSans',
|
||||
snackBarTheme: const SnackBarThemeData(
|
||||
contentTextStyle: TextStyle(fontFamily: 'WorkSans'),
|
||||
),
|
||||
scaffoldBackgroundColor: immichBackgroundColor,
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: immichBackgroundColor,
|
||||
foregroundColor: Colors.indigo,
|
||||
elevation: 1,
|
||||
centerTitle: true,
|
||||
systemOverlayStyle: SystemUiOverlayStyle.dark,
|
||||
),
|
||||
),
|
||||
themeMode: ref.watch(immichThemeProvider),
|
||||
darkTheme: immichDarkTheme,
|
||||
theme: immichLightTheme,
|
||||
routeInformationParser: router.defaultRouteParser(),
|
||||
routerDelegate: router.delegate(
|
||||
navigatorObservers: () => [TabNavigationObserver(ref: ref)],
|
||||
|
@ -14,6 +14,8 @@ class AlbumActionOutlinedButton extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: OutlinedButton.icon(
|
||||
@ -22,19 +24,23 @@ class AlbumActionOutlinedButton extends StatelessWidget {
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(25),
|
||||
),
|
||||
side: const BorderSide(
|
||||
side: BorderSide(
|
||||
width: 1,
|
||||
color: Color.fromARGB(255, 215, 215, 215),
|
||||
color: isDarkTheme
|
||||
? const Color.fromARGB(255, 63, 63, 63)
|
||||
: const Color.fromARGB(255, 206, 206, 206),
|
||||
),
|
||||
),
|
||||
icon: Icon(iconData, size: 15),
|
||||
icon: Icon(
|
||||
iconData,
|
||||
size: 15,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
label: Text(
|
||||
labelText,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black87,
|
||||
),
|
||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
onPressed: onPressed,
|
||||
),
|
||||
|
@ -52,7 +52,6 @@ class AlbumThumbnailCard extends StatelessWidget {
|
||||
album.albumName,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -65,14 +64,14 @@ class AlbumThumbnailCard extends StatelessWidget {
|
||||
? 'album_thumbnail_card_item'
|
||||
: 'album_thumbnail_card_items',
|
||||
style: const TextStyle(
|
||||
fontSize: 10,
|
||||
fontSize: 12,
|
||||
),
|
||||
).tr(args: ['${album.assetCount}']),
|
||||
if (album.shared)
|
||||
const Text(
|
||||
'album_thumbnail_card_shared',
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontSize: 12,
|
||||
),
|
||||
).tr()
|
||||
],
|
||||
|
@ -19,6 +19,8 @@ class AlbumTitleTextField extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
return TextField(
|
||||
onChanged: (v) {
|
||||
if (v.isEmpty) {
|
||||
@ -51,7 +53,10 @@ class AlbumTitleTextField extends ConsumerWidget {
|
||||
albumTitleController.clear();
|
||||
isAlbumTitleEmpty.value = true;
|
||||
},
|
||||
icon: const Icon(Icons.cancel_rounded),
|
||||
icon: Icon(
|
||||
Icons.cancel_rounded,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
splashRadius: 10,
|
||||
)
|
||||
: null,
|
||||
@ -65,7 +70,9 @@ class AlbumTitleTextField extends ConsumerWidget {
|
||||
),
|
||||
hintText: 'share_add_title'.tr(),
|
||||
focusColor: Colors.grey[300],
|
||||
fillColor: Colors.grey[200],
|
||||
fillColor: isDarkTheme
|
||||
? const Color.fromARGB(255, 32, 33, 35)
|
||||
: Colors.grey[200],
|
||||
filled: isAlbumTitleTextFieldFocus.value,
|
||||
),
|
||||
);
|
||||
|
@ -150,7 +150,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget {
|
||||
|
||||
void _buildBottomSheet() {
|
||||
showModalBottomSheet(
|
||||
backgroundColor: immichBackgroundColor,
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
isScrollControlled: false,
|
||||
context: context,
|
||||
builder: (context) {
|
||||
|
@ -18,6 +18,7 @@ class AlbumViewerEditableTitle extends HookConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final titleTextEditController =
|
||||
useTextEditingController(text: albumInfo.albumName);
|
||||
final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
void onFocusModeChange() {
|
||||
if (!titleFocusNode.hasFocus && titleTextEditController.text.isEmpty) {
|
||||
@ -65,7 +66,10 @@ class AlbumViewerEditableTitle extends HookConsumerWidget {
|
||||
onPressed: () {
|
||||
titleTextEditController.clear();
|
||||
},
|
||||
icon: const Icon(Icons.cancel_rounded),
|
||||
icon: Icon(
|
||||
Icons.cancel_rounded,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
splashRadius: 10,
|
||||
)
|
||||
: null,
|
||||
@ -78,7 +82,9 @@ class AlbumViewerEditableTitle extends HookConsumerWidget {
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
focusColor: Colors.grey[300],
|
||||
fillColor: Colors.grey[200],
|
||||
fillColor: isDarkTheme
|
||||
? const Color.fromARGB(255, 32, 33, 35)
|
||||
: Colors.grey[200],
|
||||
filled: titleFocusNode.hasFocus,
|
||||
hintText: 'share_add_title'.tr(),
|
||||
),
|
||||
|
@ -35,13 +35,7 @@ class SharingSliverAppBar extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 4.0),
|
||||
child: TextButton.icon(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all(
|
||||
Theme.of(context).primaryColor.withAlpha(20),
|
||||
),
|
||||
// foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
),
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
AutoRouter.of(context)
|
||||
.push(CreateAlbumRoute(isSharedAlbum: true));
|
||||
@ -52,8 +46,12 @@ class SharingSliverAppBar extends StatelessWidget {
|
||||
),
|
||||
label: const Text(
|
||||
"sharing_silver_appbar_create_shared_album",
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 11,
|
||||
// color: Theme.of(context).primaryColor,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
@ -61,13 +59,7 @@ class SharingSliverAppBar extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 4.0),
|
||||
child: TextButton.icon(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all(
|
||||
Theme.of(context).primaryColor.withAlpha(20),
|
||||
),
|
||||
// foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
),
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: null,
|
||||
icon: const Icon(
|
||||
Icons.swap_horizontal_circle_outlined,
|
||||
@ -75,8 +67,11 @@ class SharingSliverAppBar extends StatelessWidget {
|
||||
),
|
||||
label: const Text(
|
||||
"sharing_silver_appbar_share_partner",
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 11,
|
||||
),
|
||||
maxLines: 1,
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
|
@ -3,7 +3,6 @@ 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/constants/immich_colors.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/draggable_scrollbar.dart';
|
||||
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
|
||||
import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart';
|
||||
@ -242,7 +241,7 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
titleFocusNode.unfocus();
|
||||
},
|
||||
child: DraggableScrollbar.semicircle(
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
backgroundColor: Theme.of(context).hintColor,
|
||||
controller: scrollController,
|
||||
heightScrollThumb: 48.0,
|
||||
child: CustomScrollView(
|
||||
@ -255,7 +254,7 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
minHeight: 50,
|
||||
maxHeight: 50,
|
||||
child: Container(
|
||||
color: immichBackgroundColor,
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
child: _buildControlButton(albumInfo),
|
||||
),
|
||||
),
|
||||
|
@ -43,7 +43,7 @@ class AssetSelectionPage extends HookConsumerWidget {
|
||||
return Stack(
|
||||
children: [
|
||||
DraggableScrollbar.semicircle(
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
backgroundColor: Theme.of(context).hintColor,
|
||||
controller: scrollController,
|
||||
heightScrollThumb: 48.0,
|
||||
child: CustomScrollView(
|
||||
|
@ -27,6 +27,7 @@ class CreateAlbumPage extends HookConsumerWidget {
|
||||
final isAlbumTitleEmpty = useState(true);
|
||||
final selectedAssets =
|
||||
ref.watch(assetSelectionProvider).selectedNewAssetsForAlbum;
|
||||
final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
_showSelectUserPage() {
|
||||
AutoRouter.of(context).push(const SelectUserForSharingRoute());
|
||||
@ -75,9 +76,12 @@ class CreateAlbumPage extends HookConsumerWidget {
|
||||
return SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 200, left: 18),
|
||||
child: const Text(
|
||||
child: Text(
|
||||
'create_shared_album_page_share_add_assets',
|
||||
style: TextStyle(fontSize: 12),
|
||||
style: Theme.of(context).textTheme.headline2?.copyWith(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
);
|
||||
@ -96,24 +100,28 @@ class CreateAlbumPage extends HookConsumerWidget {
|
||||
alignment: Alignment.centerLeft,
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 22, horizontal: 16),
|
||||
side: const BorderSide(
|
||||
color: Color.fromARGB(255, 206, 206, 206),
|
||||
side: BorderSide(
|
||||
color: isDarkTheme
|
||||
? const Color.fromARGB(255, 63, 63, 63)
|
||||
: const Color.fromARGB(255, 206, 206, 206),
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
),
|
||||
onPressed: _onSelectPhotosButtonPressed,
|
||||
icon: const Icon(Icons.add_rounded),
|
||||
icon: Icon(
|
||||
Icons.add_rounded,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
label: Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Text(
|
||||
'create_shared_album_page_share_select_photos',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.grey[700],
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: Theme.of(context).textTheme.labelLarge?.copyWith(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
@ -190,6 +198,7 @@ class CreateAlbumPage extends HookConsumerWidget {
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
centerTitle: false,
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
leading: IconButton(
|
||||
onPressed: () {
|
||||
ref.watch(assetSelectionProvider.notifier).removeAll();
|
||||
@ -197,9 +206,11 @@ class CreateAlbumPage extends HookConsumerWidget {
|
||||
},
|
||||
icon: const Icon(Icons.close_rounded),
|
||||
),
|
||||
title: const Text(
|
||||
title: Text(
|
||||
'share_create_album',
|
||||
style: TextStyle(color: Colors.black),
|
||||
style: Theme.of(context).textTheme.headline2?.copyWith(
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
).tr(),
|
||||
actions: [
|
||||
if (isSharedAlbum)
|
||||
@ -209,8 +220,9 @@ class CreateAlbumPage extends HookConsumerWidget {
|
||||
: null,
|
||||
child: Text(
|
||||
'create_shared_album_page_share'.tr(),
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -234,9 +246,9 @@ class CreateAlbumPage extends HookConsumerWidget {
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
elevation: 5,
|
||||
automaticallyImplyLeading: false,
|
||||
// leading: Container(),
|
||||
pinned: true,
|
||||
floating: false,
|
||||
bottom: PreferredSize(
|
||||
|
@ -23,7 +23,7 @@ class LibraryPage extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
Widget _buildAppBar() {
|
||||
return SliverAppBar(
|
||||
return const SliverAppBar(
|
||||
centerTitle: true,
|
||||
floating: true,
|
||||
pinned: false,
|
||||
@ -35,7 +35,6 @@ class LibraryPage extends HookConsumerWidget {
|
||||
fontFamily: 'SnowburstOne',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 22,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -72,7 +71,6 @@ class LibraryPage extends HookConsumerWidget {
|
||||
child: const Text(
|
||||
'library_page_new_album',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
|
@ -136,9 +136,9 @@ class SelectUserForSharingPage extends HookConsumerWidget {
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(
|
||||
title: Text(
|
||||
'share_invite',
|
||||
style: TextStyle(color: Colors.black),
|
||||
style: TextStyle(color: Theme.of(context).primaryColor),
|
||||
).tr(),
|
||||
elevation: 0,
|
||||
centerTitle: false,
|
||||
@ -150,11 +150,18 @@ class SelectUserForSharingPage extends HookConsumerWidget {
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
primary: Theme.of(context).primaryColor,
|
||||
),
|
||||
onPressed:
|
||||
sharedUsersList.value.isEmpty ? null : _createSharedAlbum,
|
||||
child: const Text(
|
||||
"share_create_album",
|
||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
// color: Theme.of(context).primaryColor,
|
||||
),
|
||||
).tr(),
|
||||
)
|
||||
],
|
||||
|
@ -61,11 +61,9 @@ class SharingPage extends HookConsumerWidget {
|
||||
sharedAlbums[index].albumName,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.grey.shade800,
|
||||
),
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
AutoRouter.of(context)
|
||||
@ -87,7 +85,7 @@ class SharingPage extends HookConsumerWidget {
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10), // if you need this
|
||||
side: const BorderSide(
|
||||
color: Colors.black12,
|
||||
color: Colors.grey,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
@ -97,30 +95,26 @@ class SharingPage extends HookConsumerWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 5.0, bottom: 5),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(left: 5.0, bottom: 5),
|
||||
child: Icon(
|
||||
Icons.offline_share_outlined,
|
||||
size: 50,
|
||||
color: Theme.of(context).primaryColor.withAlpha(200),
|
||||
// color: Theme.of(context).primaryColor,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
'sharing_page_empty_list',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: Theme.of(context).textTheme.headline3,
|
||||
).tr(),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
'sharing_page_description',
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey[700]),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
).tr(),
|
||||
),
|
||||
],
|
||||
|
@ -11,7 +11,8 @@ import 'package:immich_mobile/modules/asset_viewer/ui/top_control_app_bar.dart';
|
||||
import 'package:immich_mobile/modules/asset_viewer/views/image_viewer_page.dart';
|
||||
import 'package:immich_mobile/modules/asset_viewer/views/video_viewer_page.dart';
|
||||
import 'package:immich_mobile/modules/home/services/asset.service.dart';
|
||||
import 'package:immich_mobile/shared/services/app_settings.service.dart';
|
||||
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
|
||||
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
|
@ -24,6 +24,7 @@ class AlbumInfoCard extends HookConsumerWidget {
|
||||
ref.watch(backupProvider).selectedBackupAlbums.contains(albumInfo);
|
||||
final bool isExcluded =
|
||||
ref.watch(backupProvider).excludedBackupAlbums.contains(albumInfo);
|
||||
final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
ColorFilter selectedFilter = ColorFilter.mode(
|
||||
Theme.of(context).primaryColor.withAlpha(100),
|
||||
@ -39,11 +40,11 @@ class AlbumInfoCard extends HookConsumerWidget {
|
||||
return Chip(
|
||||
visualDensity: VisualDensity.compact,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
|
||||
label: const Text(
|
||||
label: Text(
|
||||
"album_info_card_backup_album_included",
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.white,
|
||||
color: isDarkTheme ? Colors.black : Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
@ -53,11 +54,11 @@ class AlbumInfoCard extends HookConsumerWidget {
|
||||
return Chip(
|
||||
visualDensity: VisualDensity.compact,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
|
||||
label: const Text(
|
||||
label: Text(
|
||||
"album_info_card_backup_album_excluded",
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.white,
|
||||
color: isDarkTheme ? Colors.black : Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
@ -141,8 +142,10 @@ class AlbumInfoCard extends HookConsumerWidget {
|
||||
margin: const EdgeInsets.all(1),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12), // if you need this
|
||||
side: const BorderSide(
|
||||
color: Color(0xFFC9C9C9),
|
||||
side: BorderSide(
|
||||
color: isDarkTheme
|
||||
? const Color.fromARGB(255, 37, 35, 35)
|
||||
: const Color(0xFFC9C9C9),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
@ -219,8 +222,9 @@ class AlbumInfoCard extends HookConsumerWidget {
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
AutoRouter.of(context)
|
||||
.push(AlbumPreviewRoute(album: albumInfo));
|
||||
AutoRouter.of(context).push(
|
||||
AlbumPreviewRoute(album: albumInfo),
|
||||
);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.image_outlined,
|
||||
|
@ -35,7 +35,7 @@ class BackupInfoCard extends StatelessWidget {
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
subtitle,
|
||||
style: const TextStyle(color: Color(0xFF808080), fontSize: 12),
|
||||
style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
),
|
||||
trailing: Column(
|
||||
|
@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/immich_colors.dart';
|
||||
import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
|
||||
import 'package:immich_mobile/modules/backup/ui/album_info_card.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
|
||||
@ -16,6 +17,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
||||
final availableAlbums = ref.watch(backupProvider).availableAlbums;
|
||||
final selectedBackupAlbums = ref.watch(backupProvider).selectedBackupAlbums;
|
||||
final excludedBackupAlbums = ref.watch(backupProvider).excludedBackupAlbums;
|
||||
final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
@ -81,14 +83,16 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
||||
),
|
||||
label: Text(
|
||||
album.name,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.white,
|
||||
color: Theme.of(context).brightness == Brightness.dark
|
||||
? Colors.black
|
||||
: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
deleteIconColor: Colors.white,
|
||||
deleteIconColor: isDarkTheme ? Colors.black : Colors.white,
|
||||
deleteIcon: const Icon(
|
||||
Icons.cancel_rounded,
|
||||
size: 15,
|
||||
@ -119,14 +123,15 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
||||
),
|
||||
label: Text(
|
||||
album.name,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.white,
|
||||
color: isDarkTheme ? Colors.black : immichBackgroundColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
backgroundColor: Colors.red[300],
|
||||
deleteIconColor: Colors.white,
|
||||
deleteIconColor:
|
||||
isDarkTheme ? Colors.black : immichBackgroundColor,
|
||||
deleteIcon: const Icon(
|
||||
Icons.cancel_rounded,
|
||||
size: 15,
|
||||
@ -154,11 +159,16 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
||||
physics: const ClampingScrollPhysics(),
|
||||
children: [
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
horizontal: 16.0,
|
||||
),
|
||||
child: const Text(
|
||||
"backup_album_selection_page_selection_info",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
// Selected Album Chips
|
||||
@ -178,9 +188,11 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
||||
child: Card(
|
||||
margin: const EdgeInsets.all(0),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5), // if you need this
|
||||
side: const BorderSide(
|
||||
color: Color.fromARGB(255, 235, 235, 235),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
side: BorderSide(
|
||||
color: isDarkTheme
|
||||
? const Color.fromARGB(255, 0, 0, 0)
|
||||
: const Color.fromARGB(255, 235, 235, 235),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
@ -190,12 +202,11 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
||||
children: [
|
||||
ListTile(
|
||||
visualDensity: VisualDensity.compact,
|
||||
title: Text(
|
||||
title: const Text(
|
||||
"backup_album_selection_page_total_assets",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
color: Colors.grey[700],
|
||||
),
|
||||
).tr(),
|
||||
trailing: Text(
|
||||
@ -257,11 +268,10 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: [
|
||||
Text(
|
||||
const Text(
|
||||
'backup_album_selection_page_assets_scatter',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey[700],
|
||||
),
|
||||
).tr(),
|
||||
],
|
||||
|
@ -82,7 +82,7 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
);
|
||||
}
|
||||
|
||||
ListTile _buildBackupController() {
|
||||
ListTile _buildAutoBackupController() {
|
||||
var backUpOption = authenticationState.deviceInfo.isAutoBackup
|
||||
? "backup_controller_page_status_on".tr()
|
||||
: "backup_controller_page_status_off".tr();
|
||||
@ -114,13 +114,7 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
).tr(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: OutlinedButton(
|
||||
style: OutlinedButton.styleFrom(
|
||||
side: const BorderSide(
|
||||
width: 1,
|
||||
color: Color.fromARGB(255, 220, 220, 220),
|
||||
),
|
||||
),
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
if (isAutoBackup) {
|
||||
ref
|
||||
@ -134,7 +128,10 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
},
|
||||
child: Text(
|
||||
backupBtnText,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -232,33 +229,24 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
children: [
|
||||
const Text(
|
||||
"backup_controller_page_to_backup",
|
||||
style: TextStyle(color: Color(0xFF808080), fontSize: 12),
|
||||
style: TextStyle(fontSize: 12),
|
||||
).tr(),
|
||||
_buildSelectedAlbumName(),
|
||||
_buildExcludedAlbumName()
|
||||
],
|
||||
),
|
||||
),
|
||||
trailing: OutlinedButton(
|
||||
style: OutlinedButton.styleFrom(
|
||||
enableFeedback: true,
|
||||
side: const BorderSide(
|
||||
width: 1,
|
||||
color: Color.fromARGB(255, 220, 220, 220),
|
||||
),
|
||||
),
|
||||
trailing: ElevatedButton(
|
||||
onPressed: () {
|
||||
AutoRouter.of(context).push(const BackupAlbumSelectionRoute());
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 16.0,
|
||||
child: const Text(
|
||||
"backup_controller_page_select",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
child: const Text(
|
||||
"backup_controller_page_select",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
).tr(),
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -324,14 +312,14 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Table(
|
||||
border: TableBorder.all(
|
||||
color: Colors.black12,
|
||||
color: Theme.of(context).primaryColorLight,
|
||||
width: 1,
|
||||
),
|
||||
children: [
|
||||
TableRow(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[100],
|
||||
),
|
||||
decoration: const BoxDecoration(
|
||||
// color: Colors.grey[100],
|
||||
),
|
||||
children: [
|
||||
TableCell(
|
||||
verticalAlignment: TableCellVerticalAlignment.middle,
|
||||
@ -355,9 +343,9 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
],
|
||||
),
|
||||
TableRow(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[200],
|
||||
),
|
||||
decoration: const BoxDecoration(
|
||||
// color: Colors.grey[200],
|
||||
),
|
||||
children: [
|
||||
TableCell(
|
||||
verticalAlignment: TableCellVerticalAlignment.middle,
|
||||
@ -384,9 +372,9 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
],
|
||||
),
|
||||
TableRow(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[100],
|
||||
),
|
||||
decoration: const BoxDecoration(
|
||||
// color: Colors.grey[100],
|
||||
),
|
||||
children: [
|
||||
TableCell(
|
||||
child: Padding(
|
||||
@ -463,7 +451,7 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
"${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length}",
|
||||
),
|
||||
const Divider(),
|
||||
_buildBackupController(),
|
||||
_buildAutoBackupController(),
|
||||
const Divider(),
|
||||
_buildStorageInformation(),
|
||||
const Divider(),
|
||||
@ -479,7 +467,7 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.red[300],
|
||||
onPrimary: Colors.grey[50],
|
||||
padding: const EdgeInsets.all(14),
|
||||
// padding: const EdgeInsets.all(14),
|
||||
),
|
||||
onPressed: () {
|
||||
ref.read(backupProvider.notifier).cancelBackup();
|
||||
@ -493,11 +481,6 @@ class BackupControllerPage extends HookConsumerWidget {
|
||||
).tr(),
|
||||
)
|
||||
: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Theme.of(context).primaryColor,
|
||||
onPrimary: Colors.grey[50],
|
||||
padding: const EdgeInsets.all(14),
|
||||
),
|
||||
onPressed: shouldBackup ? startBackup : null,
|
||||
child: const Text(
|
||||
"backup_controller_page_start_backup",
|
||||
|
@ -1,11 +1,9 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/delete_diaglog.dart';
|
||||
|
||||
import '../../../shared/providers/asset.provider.dart';
|
||||
import '../providers/home_page_state.provider.dart';
|
||||
|
||||
class ControlBottomAppBar extends ConsumerWidget {
|
||||
const ControlBottomAppBar({Key? key}) : super(key: key);
|
||||
|
||||
@ -19,10 +17,10 @@ class ControlBottomAppBar extends ConsumerWidget {
|
||||
height: MediaQuery.of(context).size.height * 0.15,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(15),
|
||||
topRight: Radius.circular(15),
|
||||
topLeft: Radius.circular(8),
|
||||
topRight: Radius.circular(8),
|
||||
),
|
||||
color: Colors.grey[300]?.withOpacity(0.98),
|
||||
color: Theme.of(context).scaffoldBackgroundColor.withOpacity(0.95),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
|
@ -86,7 +86,6 @@ class DailyTitleText extends ConsumerWidget {
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
|
@ -14,32 +14,22 @@ class DisableMultiSelectButton extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Positioned(
|
||||
top: 0,
|
||||
top: 10,
|
||||
left: 0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 16.0, top: 46),
|
||||
child: Material(
|
||||
elevation: 20,
|
||||
borderRadius: BorderRadius.circular(35),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(35),
|
||||
color: Colors.grey[100],
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||
child: TextButton.icon(
|
||||
onPressed: () {
|
||||
onPressed();
|
||||
},
|
||||
icon: const Icon(Icons.close_rounded),
|
||||
label: Text(
|
||||
'$selectedItemCount',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
onPressed();
|
||||
},
|
||||
icon: const Icon(Icons.close_rounded),
|
||||
label: Text(
|
||||
'$selectedItemCount',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -30,6 +30,7 @@ class ImmichSliverAppBar extends ConsumerWidget {
|
||||
floating: true,
|
||||
pinned: false,
|
||||
snap: false,
|
||||
backgroundColor: Theme.of(context).appBarTheme.backgroundColor,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(5)),
|
||||
),
|
||||
@ -57,7 +58,7 @@ class ImmichSliverAppBar extends ConsumerWidget {
|
||||
child: GestureDetector(
|
||||
onTap: () => Scaffold.of(context).openDrawer(),
|
||||
child: Material(
|
||||
color: Colors.grey[200],
|
||||
// color: Colors.grey[200],
|
||||
elevation: 1,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(50.0),
|
||||
@ -77,13 +78,12 @@ class ImmichSliverAppBar extends ConsumerWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
title: Text(
|
||||
title: const Text(
|
||||
'IMMICH',
|
||||
style: TextStyle(
|
||||
fontFamily: 'SnowburstOne',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 22,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
@ -112,12 +112,13 @@ class ImmichSliverAppBar extends ConsumerWidget {
|
||||
? const Icon(Icons.backup_rounded)
|
||||
: Badge(
|
||||
padding: const EdgeInsets.all(4),
|
||||
elevation: 2,
|
||||
elevation: 3,
|
||||
position: BadgePosition.bottomEnd(bottom: -4, end: -4),
|
||||
badgeColor: Colors.white,
|
||||
badgeContent: const Icon(
|
||||
Icons.cloud_off_rounded,
|
||||
size: 8,
|
||||
color: Colors.indigo,
|
||||
),
|
||||
child: const Icon(Icons.backup_rounded),
|
||||
),
|
||||
|
@ -22,7 +22,7 @@ class MonthlyTitleText extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 26,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).primaryColor,
|
||||
color: Theme.of(context).textTheme.headline1?.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -22,17 +22,16 @@ class ProfileDrawer extends HookConsumerWidget {
|
||||
height: double.infinity,
|
||||
child: Icon(
|
||||
Icons.logout_rounded,
|
||||
color: Colors.grey[700],
|
||||
color: Theme.of(context).textTheme.labelMedium?.color,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
"profile_drawer_sign_out",
|
||||
style: TextStyle(
|
||||
color: Colors.grey[700],
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
).tr(),
|
||||
onTap: () async {
|
||||
bool res = await ref.watch(authenticationProvider.notifier).logout();
|
||||
@ -54,17 +53,16 @@ class ProfileDrawer extends HookConsumerWidget {
|
||||
height: double.infinity,
|
||||
child: Icon(
|
||||
Icons.settings_rounded,
|
||||
color: Colors.grey[700],
|
||||
color: Theme.of(context).textTheme.labelMedium?.color,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
"profile_drawer_settings",
|
||||
style: TextStyle(
|
||||
color: Colors.grey[700],
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
).tr(),
|
||||
onTap: () {
|
||||
AutoRouter.of(context).push(const SettingsRoute());
|
||||
|
@ -23,6 +23,7 @@ class ProfileDrawerHeader extends HookConsumerWidget {
|
||||
final uploadProfileImageStatus =
|
||||
ref.watch(uploadProfileImageProvider).status;
|
||||
var dummmy = Random().nextInt(1024);
|
||||
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
_buildUserProfileImage() {
|
||||
if (authState.profileImagePath.isEmpty) {
|
||||
@ -104,13 +105,19 @@ class ProfileDrawerHeader extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return DrawerHeader(
|
||||
decoration: const BoxDecoration(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Color.fromARGB(255, 216, 219, 238),
|
||||
Color.fromARGB(255, 242, 242, 242),
|
||||
Colors.white,
|
||||
],
|
||||
colors: isDarkMode
|
||||
? [
|
||||
const Color.fromARGB(255, 22, 25, 48),
|
||||
const Color.fromARGB(255, 13, 13, 13),
|
||||
const Color.fromARGB(255, 0, 0, 0),
|
||||
]
|
||||
: [
|
||||
const Color.fromARGB(255, 216, 219, 238),
|
||||
const Color.fromARGB(255, 242, 242, 242),
|
||||
Colors.white,
|
||||
],
|
||||
begin: Alignment.centerRight,
|
||||
end: Alignment.centerLeft,
|
||||
),
|
||||
@ -129,8 +136,8 @@ class ProfileDrawerHeader extends HookConsumerWidget {
|
||||
child: GestureDetector(
|
||||
onTap: _pickUserProfileImage,
|
||||
child: Material(
|
||||
color: Colors.grey[50],
|
||||
elevation: 2,
|
||||
color: Colors.grey[100],
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(50.0),
|
||||
),
|
||||
@ -157,7 +164,7 @@ class ProfileDrawerHeader extends HookConsumerWidget {
|
||||
),
|
||||
Text(
|
||||
authState.userEmail,
|
||||
style: TextStyle(color: Colors.grey[800], fontSize: 12),
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
)
|
||||
],
|
||||
),
|
||||
|
@ -38,7 +38,7 @@ class ServerInfoBox extends HookConsumerWidget {
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Card(
|
||||
elevation: 0,
|
||||
color: Colors.grey[100],
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5), // if you need this
|
||||
side: const BorderSide(
|
||||
@ -65,7 +65,10 @@ class ServerInfoBox extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
const Divider(
|
||||
color: Color.fromARGB(101, 201, 201, 201),
|
||||
thickness: 1,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
@ -87,7 +90,10 @@ class ServerInfoBox extends HookConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(),
|
||||
const Divider(
|
||||
color: Color.fromARGB(101, 201, 201, 201),
|
||||
thickness: 1,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
@ -117,9 +117,9 @@ class HomePage extends HookConsumerWidget {
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 50.0),
|
||||
padding: const EdgeInsets.only(top: 60.0, bottom: 30.0),
|
||||
child: DraggableScrollbar.semicircle(
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
backgroundColor: Theme.of(context).hintColor,
|
||||
controller: scrollController,
|
||||
heightScrollThumb: 48.0,
|
||||
child: CustomScrollView(
|
||||
|
@ -26,7 +26,7 @@ class ThumbnailWithInfo extends StatelessWidget {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 2,
|
||||
width: MediaQuery.of(context).size.width / 3,
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
@ -58,7 +58,7 @@ class ThumbnailWithInfo extends StatelessWidget {
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -29,6 +29,8 @@ class SearchPage extends HookConsumerWidget {
|
||||
AsyncValue<List<CuratedObjectsResponseDto>> curatedObjects =
|
||||
ref.watch(getCuratedObjectProvider);
|
||||
|
||||
double imageSize = MediaQuery.of(context).size.width / 3;
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
searchFocusNode = FocusNode();
|
||||
@ -46,15 +48,15 @@ class SearchPage extends HookConsumerWidget {
|
||||
|
||||
_buildPlaces() {
|
||||
return curatedLocation.when(
|
||||
loading: () => const SizedBox(
|
||||
height: 200,
|
||||
child: Center(child: ImmichLoadingIndicator()),
|
||||
loading: () => SizedBox(
|
||||
height: imageSize,
|
||||
child: const Center(child: ImmichLoadingIndicator()),
|
||||
),
|
||||
error: (err, stack) => Text('Error: $err'),
|
||||
data: (curatedLocations) {
|
||||
return curatedLocations.isNotEmpty
|
||||
? SizedBox(
|
||||
height: MediaQuery.of(context).size.width / 2,
|
||||
height: imageSize,
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.only(left: 16),
|
||||
scrollDirection: Axis.horizontal,
|
||||
@ -76,7 +78,7 @@ class SearchPage extends HookConsumerWidget {
|
||||
),
|
||||
)
|
||||
: SizedBox(
|
||||
height: MediaQuery.of(context).size.width / 2,
|
||||
height: imageSize,
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.only(left: 16),
|
||||
scrollDirection: Axis.horizontal,
|
||||
@ -105,7 +107,7 @@ class SearchPage extends HookConsumerWidget {
|
||||
data: (objects) {
|
||||
return objects.isNotEmpty
|
||||
? SizedBox(
|
||||
height: MediaQuery.of(context).size.width / 2,
|
||||
height: imageSize,
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.only(left: 16),
|
||||
scrollDirection: Axis.horizontal,
|
||||
@ -113,7 +115,7 @@ class SearchPage extends HookConsumerWidget {
|
||||
itemBuilder: ((context, index) {
|
||||
var curatedObjectInfo = objects[index];
|
||||
var thumbnailRequestUrl =
|
||||
'${box.get(serverEndpointKey)}/asset/file?aid=${curatedObjectInfo.deviceAssetId}&did=${curatedObjectInfo.deviceId}&isThumb=true';
|
||||
'${box.get(serverEndpointKey)}/asset/thumbnail/${curatedObjectInfo.id}';
|
||||
|
||||
return ThumbnailWithInfo(
|
||||
imageUrl: thumbnailRequestUrl,
|
||||
@ -131,7 +133,8 @@ class SearchPage extends HookConsumerWidget {
|
||||
),
|
||||
)
|
||||
: SizedBox(
|
||||
height: MediaQuery.of(context).size.width / 2,
|
||||
// height: imageSize,
|
||||
width: imageSize,
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.only(left: 16),
|
||||
scrollDirection: Axis.horizontal,
|
||||
@ -163,12 +166,13 @@ class SearchPage extends HookConsumerWidget {
|
||||
child: Stack(
|
||||
children: [
|
||||
ListView(
|
||||
shrinkWrap: true,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: const Text(
|
||||
"search_page_places",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
|
||||
).tr(),
|
||||
),
|
||||
_buildPlaces(),
|
||||
@ -176,7 +180,7 @@ class SearchPage extends HookConsumerWidget {
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: const Text(
|
||||
"search_page_things",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
|
||||
).tr(),
|
||||
),
|
||||
_buildThings()
|
||||
|
@ -172,7 +172,7 @@ class SearchResultPage extends HookConsumerWidget {
|
||||
});
|
||||
|
||||
return DraggableScrollbar.semicircle(
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
backgroundColor: Theme.of(context).hintColor,
|
||||
controller: scrollController,
|
||||
heightScrollThumb: 48.0,
|
||||
child: CustomScrollView(
|
||||
|
@ -0,0 +1,4 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
|
||||
|
||||
final appSettingsServiceProvider = Provider((ref) => AppSettingsService());
|
@ -5,7 +5,7 @@ import 'package:immich_mobile/constants/hive_box.dart';
|
||||
|
||||
enum AppSettingsEnum {
|
||||
threeStageLoading, // true, false,
|
||||
themeMode, // "light","dark"
|
||||
themeMode, // "light","dark","system"
|
||||
}
|
||||
|
||||
class AppSettingsService {
|
||||
@ -61,8 +61,8 @@ class AppSettingsService {
|
||||
|
||||
// Default value of themeMode is "light"
|
||||
if (settingType == AppSettingsEnum.themeMode) {
|
||||
hiveBox.put(settingKey, "light");
|
||||
return "light";
|
||||
hiveBox.put(settingKey, "system");
|
||||
return "system";
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,5 +75,3 @@ class AppSettingsService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final appSettingsServiceProvider = Provider((ref) => AppSettingsService());
|
@ -1,3 +1,4 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/modules/settings/ui/image_viewer_quality_setting/three_stage_loading.dart';
|
||||
|
||||
@ -8,20 +9,21 @@ class ImageViewerQualitySetting extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const ExpansionTile(
|
||||
title: Text(
|
||||
'Image viewer quality',
|
||||
return ExpansionTile(
|
||||
textColor: Theme.of(context).primaryColor,
|
||||
title: const Text(
|
||||
'theme_setting_image_viewer_quality_title',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
'Adjust the quality of the detail image viewer',
|
||||
).tr(),
|
||||
subtitle: const Text(
|
||||
'theme_setting_image_viewer_quality_subtitle',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
children: [
|
||||
).tr(),
|
||||
children: const [
|
||||
ThreeStageLoading(),
|
||||
],
|
||||
);
|
||||
|
@ -1,7 +1,9 @@
|
||||
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/shared/services/app_settings.service.dart';
|
||||
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
|
||||
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
|
||||
|
||||
class ThreeStageLoading extends HookConsumerWidget {
|
||||
const ThreeStageLoading({
|
||||
@ -35,18 +37,18 @@ class ThreeStageLoading extends HookConsumerWidget {
|
||||
|
||||
return SwitchListTile.adaptive(
|
||||
title: const Text(
|
||||
"Enable three stage loading",
|
||||
"theme_setting_three_stage_loading_title",
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
).tr(),
|
||||
subtitle: const Text(
|
||||
"The three-stage loading delivers the best quality image in exchange for a slower loading speed",
|
||||
"theme_setting_three_stage_loading_subtitle",
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
).tr(),
|
||||
value: isEnable.value,
|
||||
onChanged: onSwitchChanged,
|
||||
);
|
||||
|
107
mobile/lib/modules/settings/ui/theme_setting/theme_setting.dart
Normal file
107
mobile/lib/modules/settings/ui/theme_setting/theme_setting.dart
Normal file
@ -0,0 +1,107 @@
|
||||
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/modules/settings/providers/app_settings.provider.dart';
|
||||
import 'package:immich_mobile/modules/settings/ui/image_viewer_quality_setting/three_stage_loading.dart';
|
||||
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
|
||||
import 'package:immich_mobile/utils/immich_app_theme.dart';
|
||||
|
||||
class ThemeSetting extends HookConsumerWidget {
|
||||
const ThemeSetting({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final currentTheme = useState<ThemeMode>(ThemeMode.system);
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
currentTheme.value = ref.read(immichThemeProvider);
|
||||
return null;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return ExpansionTile(
|
||||
textColor: Theme.of(context).primaryColor,
|
||||
title: const Text(
|
||||
'theme_setting_theme_title',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
subtitle: const Text(
|
||||
'theme_setting_theme_subtitle',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
),
|
||||
).tr(),
|
||||
children: [
|
||||
SwitchListTile.adaptive(
|
||||
activeColor: Theme.of(context).primaryColor,
|
||||
title: const Text(
|
||||
'theme_setting_system_theme_switch',
|
||||
style: TextStyle(
|
||||
fontSize: 12.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
value: currentTheme.value == ThemeMode.system,
|
||||
onChanged: (bool isSystem) {
|
||||
var currentSystemBrightness =
|
||||
MediaQuery.of(context).platformBrightness;
|
||||
|
||||
if (isSystem) {
|
||||
currentTheme.value = ThemeMode.system;
|
||||
ref.watch(immichThemeProvider.notifier).state = ThemeMode.system;
|
||||
ref
|
||||
.watch(appSettingsServiceProvider)
|
||||
.setSetting(AppSettingsEnum.themeMode, "system");
|
||||
} else {
|
||||
if (currentSystemBrightness == Brightness.light) {
|
||||
currentTheme.value = ThemeMode.light;
|
||||
ref.watch(immichThemeProvider.notifier).state = ThemeMode.light;
|
||||
ref
|
||||
.watch(appSettingsServiceProvider)
|
||||
.setSetting(AppSettingsEnum.themeMode, "light");
|
||||
} else if (currentSystemBrightness == Brightness.dark) {
|
||||
currentTheme.value = ThemeMode.dark;
|
||||
ref.watch(immichThemeProvider.notifier).state = ThemeMode.dark;
|
||||
ref
|
||||
.watch(appSettingsServiceProvider)
|
||||
.setSetting(AppSettingsEnum.themeMode, "dark");
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
if (currentTheme.value != ThemeMode.system)
|
||||
SwitchListTile.adaptive(
|
||||
activeColor: Theme.of(context).primaryColor,
|
||||
title: const Text(
|
||||
'theme_setting_dark_mode_switch',
|
||||
style: TextStyle(
|
||||
fontSize: 12.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
value: ref.watch(immichThemeProvider) == ThemeMode.dark,
|
||||
onChanged: (bool isDark) {
|
||||
if (isDark) {
|
||||
ref.watch(immichThemeProvider.notifier).state = ThemeMode.dark;
|
||||
ref
|
||||
.watch(appSettingsServiceProvider)
|
||||
.setSetting(AppSettingsEnum.themeMode, "dark");
|
||||
} else {
|
||||
ref.watch(immichThemeProvider.notifier).state = ThemeMode.light;
|
||||
ref
|
||||
.watch(appSettingsServiceProvider)
|
||||
.setSetting(AppSettingsEnum.themeMode, "light");
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/modules/settings/ui/image_viewer_quality_setting/image_viewer_quality_setting.dart';
|
||||
import 'package:immich_mobile/modules/settings/ui/theme_setting/theme_setting.dart';
|
||||
|
||||
class SettingsPage extends HookConsumerWidget {
|
||||
const SettingsPage({Key? key}) : super(key: key);
|
||||
@ -20,12 +22,12 @@ class SettingsPage extends HookConsumerWidget {
|
||||
automaticallyImplyLeading: false,
|
||||
centerTitle: false,
|
||||
title: const Text(
|
||||
'Settings',
|
||||
'setting_pages_app_bar_settings',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
@ -33,10 +35,7 @@ class SettingsPage extends HookConsumerWidget {
|
||||
context: context,
|
||||
tiles: [
|
||||
const ImageViewerQualitySetting(),
|
||||
const SettingListTile(
|
||||
title: 'Theme',
|
||||
subtitle: 'Choose between light and dark theme',
|
||||
),
|
||||
const ThemeSetting(),
|
||||
],
|
||||
).toList(),
|
||||
],
|
||||
@ -44,38 +43,3 @@ class SettingsPage extends HookConsumerWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SettingListTile extends StatelessWidget {
|
||||
const SettingListTile({
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
final String title;
|
||||
final String subtitle;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
dense: true,
|
||||
title: Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
subtitle,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
trailing: const Icon(
|
||||
Icons.keyboard_arrow_right_rounded,
|
||||
size: 24,
|
||||
),
|
||||
onTap: () {},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/hive_box.dart';
|
||||
import 'package:immich_mobile/constants/immich_colors.dart';
|
||||
import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
|
||||
import 'package:immich_mobile/modules/login/models/hive_saved_login_info.model.dart';
|
||||
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
|
||||
@ -49,7 +48,6 @@ class SplashScreenPage extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: immichBackgroundColor,
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
@ -2,7 +2,6 @@ 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/constants/immich_colors.dart';
|
||||
import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
|
||||
@ -36,8 +35,6 @@ class TabControllerPage extends ConsumerWidget {
|
||||
bottomNavigationBar: isMultiSelectEnable
|
||||
? null
|
||||
: BottomNavigationBar(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
backgroundColor: immichBackgroundColor,
|
||||
selectedLabelStyle: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
|
133
mobile/lib/utils/immich_app_theme.dart
Normal file
133
mobile/lib/utils/immich_app_theme.dart
Normal file
@ -0,0 +1,133 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/immich_colors.dart';
|
||||
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
|
||||
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
|
||||
|
||||
final immichThemeProvider = StateProvider<ThemeMode>((ref) {
|
||||
var themeMode = ref
|
||||
.watch(appSettingsServiceProvider)
|
||||
.getSetting(AppSettingsEnum.themeMode);
|
||||
|
||||
debugPrint("Current themeMode $themeMode");
|
||||
|
||||
if (themeMode == "light") {
|
||||
return ThemeMode.light;
|
||||
} else if (themeMode == "dark") {
|
||||
return ThemeMode.dark;
|
||||
} else {
|
||||
return ThemeMode.system;
|
||||
}
|
||||
});
|
||||
|
||||
ThemeData immichDarkTheme = ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: Brightness.dark,
|
||||
primarySwatch: Colors.indigo,
|
||||
primaryColor: immichDarkThemePrimaryColor,
|
||||
scaffoldBackgroundColor: immichDarkBackgroundColor,
|
||||
hintColor: Colors.grey[600],
|
||||
fontFamily: 'WorkSans',
|
||||
snackBarTheme: const SnackBarThemeData(
|
||||
contentTextStyle: TextStyle(fontFamily: 'WorkSans'),
|
||||
),
|
||||
appBarTheme: AppBarTheme(
|
||||
titleTextStyle: TextStyle(
|
||||
fontFamily: 'WorkSans',
|
||||
color: immichDarkThemePrimaryColor,
|
||||
),
|
||||
backgroundColor: const Color.fromARGB(255, 32, 33, 35),
|
||||
foregroundColor: immichDarkThemePrimaryColor,
|
||||
elevation: 1,
|
||||
centerTitle: true,
|
||||
systemOverlayStyle: SystemUiOverlayStyle.light,
|
||||
),
|
||||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
backgroundColor: const Color.fromARGB(255, 35, 36, 37),
|
||||
selectedItemColor: immichDarkThemePrimaryColor,
|
||||
),
|
||||
drawerTheme: DrawerThemeData(
|
||||
backgroundColor: immichDarkBackgroundColor,
|
||||
scrimColor: Colors.white.withOpacity(0.1),
|
||||
),
|
||||
textTheme: TextTheme(
|
||||
headline1: const TextStyle(
|
||||
fontSize: 26,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color.fromARGB(255, 255, 255, 255),
|
||||
),
|
||||
headline2: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color.fromARGB(255, 148, 151, 155),
|
||||
),
|
||||
headline3: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: immichDarkThemePrimaryColor,
|
||||
),
|
||||
),
|
||||
cardColor: Colors.grey[900],
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
onPrimary: Colors.black87,
|
||||
primary: immichDarkThemePrimaryColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
ThemeData immichLightTheme = ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: Brightness.light,
|
||||
primarySwatch: Colors.indigo,
|
||||
hintColor: Colors.indigo,
|
||||
fontFamily: 'WorkSans',
|
||||
scaffoldBackgroundColor: immichBackgroundColor,
|
||||
snackBarTheme: const SnackBarThemeData(
|
||||
contentTextStyle: TextStyle(fontFamily: 'WorkSans'),
|
||||
),
|
||||
appBarTheme: AppBarTheme(
|
||||
titleTextStyle: const TextStyle(
|
||||
fontFamily: 'WorkSans',
|
||||
color: Colors.indigo,
|
||||
),
|
||||
backgroundColor: immichBackgroundColor,
|
||||
foregroundColor: Colors.indigo,
|
||||
elevation: 1,
|
||||
centerTitle: true,
|
||||
systemOverlayStyle: SystemUiOverlayStyle.dark,
|
||||
),
|
||||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
backgroundColor: immichBackgroundColor,
|
||||
selectedItemColor: Colors.indigo,
|
||||
),
|
||||
drawerTheme: DrawerThemeData(
|
||||
backgroundColor: immichBackgroundColor,
|
||||
),
|
||||
textTheme: const TextTheme(
|
||||
headline1: TextStyle(
|
||||
fontSize: 26,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.indigo,
|
||||
),
|
||||
headline2: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black87,
|
||||
),
|
||||
headline3: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.indigo,
|
||||
),
|
||||
),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.indigo,
|
||||
onPrimary: Colors.white,
|
||||
),
|
||||
),
|
||||
);
|
@ -2,7 +2,7 @@ name: immich_mobile
|
||||
description: Immich - selfhosted backup media file on mobile phone
|
||||
|
||||
publish_to: "none"
|
||||
version: 1.22.0+32
|
||||
version: 1.23.0+33
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.0 <3.0.0"
|
||||
|
@ -10,7 +10,7 @@ export interface IServerVersion {
|
||||
|
||||
export const serverVersion: IServerVersion = {
|
||||
major: 1,
|
||||
minor: 22,
|
||||
minor: 23,
|
||||
patch: 0,
|
||||
build: 0,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user