setting page tune

This commit is contained in:
Alex Tran
2026-01-18 22:45:43 -06:00
parent b65ce3f55d
commit fed1fd7c23
14 changed files with 82 additions and 97 deletions

View File

@@ -603,7 +603,7 @@
"backup_album_selection_page_select_albums": "Select albums",
"backup_album_selection_page_selection_info": "Selection Info",
"backup_album_selection_page_total_assets": "Total unique assets",
"backup_albums_sync": "Backup albums synchronization",
"backup_albums_sync": "Backup Albums Synchronization",
"backup_all": "All",
"backup_background_service_backup_failed_message": "Failed to backup assets. Retrying…",
"backup_background_service_complete_notification": "Asset backup complete",
@@ -2257,7 +2257,7 @@
"url": "URL",
"usage": "Usage",
"use_biometric": "Use biometric",
"use_current_connection": "use current connection",
"use_current_connection": "Use current connection",
"use_custom_date_range": "Use custom date range instead",
"user": "User",
"user_has_been_deleted": "This user has been deleted.",

View File

@@ -64,4 +64,12 @@ extension ContextHelper on BuildContext {
// Show SnackBars from the current context
void showSnackBar(SnackBar snackBar) => ScaffoldMessenger.of(this).showSnackBar(snackBar);
// Text style token
TextStyle get textTokenSettingTitle => textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w500, height: 1.5);
TextStyle get textTokenSettingSubtitle =>
textTheme.bodyMedium!.copyWith(color: textTheme.bodyMedium!.color!.withAlpha(215));
TextStyle get textTokenSettingGroupTitle => textTheme.bodyMedium!.copyWith(color: colorScheme.onSurfaceVariant);
}

View File

@@ -18,6 +18,7 @@ class SyncStatusPage extends StatelessWidget {
splashRadius: 24,
icon: const Icon(Icons.arrow_back_ios_rounded),
),
centerTitle: false,
),
body: const SyncStatusAndActions(),
);

View File

@@ -61,7 +61,11 @@ ThemeData getThemeData({required ColorScheme colorScheme, required Locale locale
),
),
chipTheme: const ChipThemeData(side: BorderSide.none),
sliderTheme: const SliderThemeData(thumbShape: RoundSliderThumbShape(enabledThumbRadius: 7), trackHeight: 2.0),
sliderTheme: const SliderThemeData(
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 7),
trackHeight: 2.0,
year2023: false,
),
bottomNavigationBarTheme: const BottomNavigationBarThemeData(type: BottomNavigationBarType.fixed),
popupMenuTheme: const PopupMenuThemeData(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),

View File

@@ -27,9 +27,12 @@ class DriftBackupSettings extends ConsumerWidget {
settings: [
Padding(
padding: const EdgeInsets.only(left: 16.0),
child: Text(
"network_requirements".t(context: context).toUpperCase(),
style: context.textTheme.labelSmall?.copyWith(color: context.colorScheme.onSurface.withValues(alpha: 0.7)),
child: Row(
children: [
Icon(Icons.cell_tower, color: context.colorScheme.onSurface.withValues(alpha: 0.7), size: 20),
const SizedBox(width: 8),
Text("network_requirements".t(context: context), style: context.textTokenSettingGroupTitle),
],
),
),
const _UseWifiForUploadVideosButton(),
@@ -38,11 +41,16 @@ class DriftBackupSettings extends ConsumerWidget {
const Divider(),
Padding(
padding: const EdgeInsets.only(left: 16.0),
child: Text(
"background_options".t(context: context).toUpperCase(),
style: context.textTheme.labelSmall?.copyWith(
color: context.colorScheme.onSurface.withValues(alpha: 0.7),
),
child: Row(
children: [
Icon(
Icons.charging_station_rounded,
color: context.colorScheme.onSurface.withValues(alpha: 0.7),
size: 20,
),
const SizedBox(width: 8),
Text("background_options".t(context: context), style: context.textTokenSettingGroupTitle),
],
),
),
const _BackupOnlyWhenChargingButton(),
@@ -51,9 +59,12 @@ class DriftBackupSettings extends ConsumerWidget {
const Divider(),
Padding(
padding: const EdgeInsets.only(left: 16.0),
child: Text(
"backup_albums_sync".t(context: context).toUpperCase(),
style: context.textTheme.labelSmall?.copyWith(color: context.colorScheme.onSurface.withValues(alpha: 0.7)),
child: Row(
children: [
Icon(Icons.sync, color: context.colorScheme.onSurface.withValues(alpha: 0.7), size: 20),
const SizedBox(width: 8),
Text("backup_albums_sync".t(context: context), style: context.textTokenSettingGroupTitle),
],
),
),
const _AlbumSyncActionButton(),
@@ -116,13 +127,10 @@ class _AlbumSyncActionButtonState extends ConsumerState<_AlbumSyncActionButton>
return Column(
children: [
ListTile(
title: Text(
"sync_albums".t(context: context),
style: context.textTheme.titleMedium?.copyWith(color: context.primaryColor),
),
title: Text("sync_albums".t(context: context), style: context.textTokenSettingTitle),
subtitle: Text(
"sync_upload_album_setting_subtitle".t(context: context),
style: context.textTheme.labelLarge,
style: context.textTokenSettingSubtitle,
),
trailing: Switch(
value: albumSyncEnable,
@@ -147,16 +155,11 @@ class _AlbumSyncActionButtonState extends ConsumerState<_AlbumSyncActionButton>
contentPadding: const EdgeInsets.only(left: 32, right: 16),
title: Text(
"organize_into_albums".t(context: context),
style: context.textTheme.titleSmall?.copyWith(
color: context.colorScheme.onSurface,
fontWeight: FontWeight.normal,
),
style: context.textTokenSettingTitle,
),
subtitle: Text(
"organize_into_albums_description".t(context: context),
style: context.textTheme.bodyMedium?.copyWith(
color: context.colorScheme.onSurface.withValues(alpha: 0.7),
),
style: context.textTokenSettingSubtitle,
),
trailing: isAlbumSyncInProgress
? const SizedBox(
@@ -223,11 +226,8 @@ class _SettingsSwitchTileState extends ConsumerState<_SettingsSwitchTile> {
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(
widget.titleKey.t(context: context),
style: context.textTheme.titleMedium?.copyWith(color: context.primaryColor),
),
subtitle: Text(widget.subtitleKey.t(context: context), style: context.textTheme.labelLarge),
title: Text(widget.titleKey.t(context: context), style: context.textTokenSettingTitle),
subtitle: Text(widget.subtitleKey.t(context: context), style: context.textTokenSettingSubtitle),
trailing: StreamBuilder(
stream: valueStream,
initialData: Store.tryGet(widget.appSettingsEnum.storeKey) ?? widget.appSettingsEnum.defaultValue,
@@ -354,7 +354,7 @@ class _BackupDelaySliderState extends ConsumerState<_BackupDelaySlider> {
'backup_controller_page_background_delay'.tr(
namedArgs: {'duration': formatBackupDelaySliderValue(currentValue)},
),
style: context.textTheme.titleMedium?.copyWith(color: context.primaryColor),
style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500),
),
),
Slider(

View File

@@ -36,12 +36,12 @@ class EntityCountTile extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Icon(icon, color: context.primaryColor),
Icon(icon, color: context.primaryColor, size: 18),
const SizedBox(width: 8),
Flexible(
child: Text(
label,
style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 16),
style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.w500),
),
),
],
@@ -50,7 +50,7 @@ class EntityCountTile extends StatelessWidget {
const Spacer(),
RichText(
text: TextSpan(
style: const TextStyle(fontSize: 18, fontFamily: 'GoogleSansCode', fontWeight: FontWeight.w600),
style: const TextStyle(fontSize: 16, fontFamily: 'GoogleSansCode'),
children: [
TextSpan(
text: zeroPadding(count, maxDigits),

View File

@@ -116,11 +116,8 @@ class SyncStatusAndActions extends HookConsumerWidget {
const SizedBox(height: 24),
_SectionHeaderText(text: "jobs".t(context: context)),
ListTile(
title: Text(
"sync_local".t(context: context),
style: const TextStyle(fontWeight: FontWeight.w500),
),
subtitle: Text("tap_to_run_job".t(context: context)),
title: Text("sync_local".t(context: context), style: context.textTokenSettingTitle),
subtitle: Text("tap_to_run_job".t(context: context), style: context.textTokenSettingSubtitle),
leading: const Icon(Icons.sync),
trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).localSyncStatus),
onTap: () {
@@ -128,11 +125,8 @@ class SyncStatusAndActions extends HookConsumerWidget {
},
),
ListTile(
title: Text(
"sync_remote".t(context: context),
style: const TextStyle(fontWeight: FontWeight.w500),
),
subtitle: Text("tap_to_run_job".t(context: context)),
title: Text("sync_remote".t(context: context), style: context.textTokenSettingTitle),
subtitle: Text("tap_to_run_job".t(context: context), style: context.textTokenSettingSubtitle),
leading: const Icon(Icons.cloud_sync),
trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).remoteSyncStatus),
onTap: () {
@@ -140,12 +134,9 @@ class SyncStatusAndActions extends HookConsumerWidget {
},
),
ListTile(
title: Text(
"hash_asset".t(context: context),
style: const TextStyle(fontWeight: FontWeight.w500),
),
title: Text("hash_asset".t(context: context), style: context.textTokenSettingTitle),
leading: const Icon(Icons.tag),
subtitle: Text("tap_to_run_job".t(context: context)),
subtitle: Text("tap_to_run_job".t(context: context), style: context.textTokenSettingSubtitle),
trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).hashJobStatus),
onTap: () {
ref.read(backgroundSyncProvider).hashAssets();
@@ -211,13 +202,7 @@ class _SectionHeaderText extends StatelessWidget {
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 16.0),
child: Text(
text.toUpperCase(),
style: context.textTheme.labelLarge?.copyWith(
fontWeight: FontWeight.w500,
color: context.colorScheme.onSurface.withAlpha(200),
),
),
child: Text(text, style: context.textTokenSettingGroupTitle),
);
}
}

View File

@@ -57,7 +57,7 @@ class BetaTimelineListTile extends ConsumerWidget {
return Padding(
padding: const EdgeInsets.only(left: 4.0),
child: ListTile(
title: Text("new_timeline".t(context: context)),
title: Text("new_timeline".t(context: context), style: context.textTokenSettingTitle),
trailing: Switch.adaptive(
value: betaTimelineValue,
onChanged: onSwitchChanged,

View File

@@ -214,10 +214,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
borderRadius: const BorderRadius.all(Radius.circular(12)),
border: Border.all(color: context.primaryColor.withValues(alpha: 0.25)),
),
child: Text(
'free_up_space_description'.t(context: context),
style: context.textTheme.labelLarge?.copyWith(fontSize: 15),
),
child: Text('free_up_space_description'.t(context: context), style: context.textTheme.bodyMedium),
),
),
@@ -256,7 +253,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
content: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text('cutoff_date_description'.t(context: context), style: context.textTheme.labelLarge),
Text('cutoff_date_description'.t(context: context), style: context.textTokenSettingSubtitle),
const SizedBox(height: 16),
GridView.count(
shrinkWrap: true,
@@ -352,7 +349,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
content: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text('cleanup_filter_description'.t(context: context), style: context.textTheme.labelLarge),
Text('cleanup_filter_description'.t(context: context), style: context.textTokenSettingSubtitle),
const SizedBox(height: 16),
SegmentedButton<AssetFilterType>(
segments: [
@@ -381,10 +378,10 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
const SizedBox(height: 16),
SwitchListTile(
contentPadding: EdgeInsets.zero,
title: Text('keep_favorites'.t(context: context), style: context.textTheme.titleSmall),
title: Text('keep_favorites'.t(context: context), style: context.textTokenSettingTitle),
subtitle: Text(
'keep_favorites_description'.t(context: context),
style: context.textTheme.labelLarge,
style: context.textTokenSettingSubtitle,
),
value: state.keepFavorites,
onChanged: (value) {
@@ -435,10 +432,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
: null,
content: Column(
children: [
Text(
'cleanup_step3_description'.t(context: context),
style: context.textTheme.labelLarge?.copyWith(fontSize: 15),
),
Text('cleanup_step3_description'.t(context: context), style: context.textTokenSettingSubtitle),
if (CurrentPlatform.isIOS) ...[
const SizedBox(height: 12),
Container(

View File

@@ -117,7 +117,7 @@ class EndpointInputState extends ConsumerState<EndpointInput> {
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: validateUrl,
keyboardType: TextInputType.url,
style: const TextStyle(fontFamily: 'GoogleSansCode', fontWeight: FontWeight.w600, fontSize: 14),
style: const TextStyle(fontFamily: 'GoogleSansCode', fontSize: 14),
decoration: InputDecoration(
hintText: 'http(s)://immich.domain.com',
contentPadding: const EdgeInsets.all(16),

View File

@@ -1,12 +1,12 @@
import 'dart:convert';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/widgets/settings/networking_settings/endpoint_input.dart';
@@ -103,7 +103,7 @@ class ExternalNetworkPreference extends HookConsumerWidget {
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 24),
child: Text("external_network_sheet_info".tr(), style: context.textTheme.bodyMedium),
child: Text("external_network_sheet_info".t(context: context), style: context.textTheme.bodyMedium),
),
const SizedBox(height: 4),
Divider(color: context.colorScheme.surfaceContainerHighest),
@@ -135,7 +135,7 @@ class ExternalNetworkPreference extends HookConsumerWidget {
height: 48,
child: OutlinedButton.icon(
icon: const Icon(Icons.add),
label: Text('add_endpoint'.tr().toUpperCase()),
label: Text('add_endpoint'.t(context: context)),
onPressed: enabled
? () {
entries.value = [

View File

@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/providers/auth.provider.dart';
import 'package:immich_mobile/providers/network.provider.dart';
@@ -167,13 +168,12 @@ class LocalNetworkPreference extends HookConsumerWidget {
enabled: enabled,
contentPadding: const EdgeInsets.only(left: 24, right: 8),
leading: const Icon(Icons.lan_rounded),
title: Text("server_endpoint".tr()),
title: Text("server_endpoint".t(context: context)),
subtitle: localEndpointText.value.isEmpty
? const Text("http://local-ip:2283")
: Text(
localEndpointText.value,
style: context.textTheme.labelLarge?.copyWith(
fontWeight: FontWeight.bold,
color: enabled ? context.primaryColor : context.colorScheme.onSurface.withAlpha(100),
fontFamily: 'GoogleSansCode',
),
@@ -190,7 +190,7 @@ class LocalNetworkPreference extends HookConsumerWidget {
height: 48,
child: OutlinedButton.icon(
icon: const Icon(Icons.wifi_find_rounded),
label: Text('use_current_connection'.tr().toUpperCase()),
label: Text('use_current_connection'.t(context: context)),
onPressed: enabled ? autofillCurrentNetwork : null,
),
),

View File

@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/providers/network.provider.dart';
import 'package:immich_mobile/services/app_settings.service.dart';
@@ -90,7 +91,7 @@ class NetworkingSettings extends HookConsumerWidget {
Padding(
padding: const EdgeInsets.only(top: 8, left: 16, bottom: 8),
child: NetworkPreferenceTitle(
title: "current_server_address".tr().toUpperCase(),
title: "current_server_address".t(context: context),
icon: (currentEndpoint?.startsWith('https') ?? false) ? Icons.https_outlined : Icons.http_outlined,
),
),
@@ -108,12 +109,7 @@ class NetworkingSettings extends HookConsumerWidget {
: const Icon(Icons.circle_outlined),
title: Text(
currentEndpoint ?? "--",
style: TextStyle(
fontSize: 16,
fontFamily: 'GoogleSansCode',
fontWeight: FontWeight.bold,
color: context.primaryColor,
),
style: TextStyle(fontSize: 14, fontFamily: 'GoogleSansCode', color: context.primaryColor),
),
),
),
@@ -130,12 +126,18 @@ class NetworkingSettings extends HookConsumerWidget {
),
Padding(
padding: const EdgeInsets.only(top: 8, left: 16, bottom: 16),
child: NetworkPreferenceTitle(title: "local_network".tr().toUpperCase(), icon: Icons.home_outlined),
child: NetworkPreferenceTitle(
title: "local_network".t(context: context),
icon: Icons.home_outlined,
),
),
LocalNetworkPreference(enabled: featureEnabled.value),
Padding(
padding: const EdgeInsets.only(top: 32, left: 16, bottom: 16),
child: NetworkPreferenceTitle(title: "external_network".tr().toUpperCase(), icon: Icons.dns_outlined),
child: NetworkPreferenceTitle(
title: "external_network".t(context: context),
icon: Icons.dns_outlined,
),
),
ExternalNetworkPreference(enabled: featureEnabled.value),
],
@@ -155,13 +157,7 @@ class NetworkPreferenceTitle extends StatelessWidget {
children: [
Icon(icon, color: context.colorScheme.onSurface.withAlpha(150)),
const SizedBox(width: 8),
Text(
title,
style: context.textTheme.displaySmall?.copyWith(
color: context.colorScheme.onSurface.withAlpha(200),
fontWeight: FontWeight.w500,
),
),
Text(title, style: context.textTokenSettingGroupTitle),
],
);
}

View File

@@ -36,10 +36,7 @@ class SettingsCard extends StatelessWidget {
padding: const EdgeInsets.all(16.0),
child: Icon(icon, color: context.primaryColor),
),
title: Text(
title,
style: context.textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w600, color: context.primaryColor),
),
title: Text(title, style: context.textTheme.titleMedium!.copyWith(color: context.primaryColor)),
subtitle: Text(subtitle),
onTap: () => context.pushRoute(settingRoute),
),