mirror of
https://github.com/KevinMidboe/immich.git
synced 2026-01-08 10:15:49 +00: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:
@@ -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(),
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user