mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-03-27 17:34:44 +01:00
Material 3 theme
This commit is contained in:
parent
9682f81f39
commit
93d966ad08
63 changed files with 1588 additions and 1810 deletions
69
app/lib/color_schemes.g.dart
Normal file
69
app/lib/color_schemes.g.dart
Normal file
|
@ -0,0 +1,69 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
const lightColorScheme = ColorScheme(
|
||||
brightness: Brightness.light,
|
||||
primary: Color(0xFF0061A4),
|
||||
onPrimary: Color(0xFFFFFFFF),
|
||||
primaryContainer: Color(0xFFD1E4FF),
|
||||
onPrimaryContainer: Color(0xFF001D36),
|
||||
secondary: Color(0xFF535F70),
|
||||
onSecondary: Color(0xFFFFFFFF),
|
||||
secondaryContainer: Color(0xFFD7E3F7),
|
||||
onSecondaryContainer: Color(0xFF101C2B),
|
||||
tertiary: Color(0xFF6B5778),
|
||||
onTertiary: Color(0xFFFFFFFF),
|
||||
tertiaryContainer: Color(0xFFF2DAFF),
|
||||
onTertiaryContainer: Color(0xFF251431),
|
||||
error: Color(0xFFBA1A1A),
|
||||
errorContainer: Color(0xFFFFDAD6),
|
||||
onError: Color(0xFFFFFFFF),
|
||||
onErrorContainer: Color(0xFF410002),
|
||||
background: Color(0xFFFDFCFF),
|
||||
onBackground: Color(0xFF1A1C1E),
|
||||
surface: Color(0xFFFDFCFF),
|
||||
onSurface: Color(0xFF1A1C1E),
|
||||
surfaceVariant: Color(0xFFDFE2EB),
|
||||
onSurfaceVariant: Color(0xFF43474E),
|
||||
outline: Color(0xFF73777F),
|
||||
onInverseSurface: Color(0xFFF1F0F4),
|
||||
inverseSurface: Color(0xFF2F3033),
|
||||
inversePrimary: Color(0xFF9ECAFF),
|
||||
shadow: Color(0xFF000000),
|
||||
surfaceTint: Color(0xFF0061A4),
|
||||
// outlineVariant: Color(0xFFC3C7CF),
|
||||
// scrim: Color(0xFF000000),
|
||||
);
|
||||
|
||||
const darkColorScheme = ColorScheme(
|
||||
brightness: Brightness.dark,
|
||||
primary: Color(0xFF9ECAFF),
|
||||
onPrimary: Color(0xFF003258),
|
||||
primaryContainer: Color(0xFF00497D),
|
||||
onPrimaryContainer: Color(0xFFD1E4FF),
|
||||
secondary: Color(0xFFBBC7DB),
|
||||
onSecondary: Color(0xFF253140),
|
||||
secondaryContainer: Color(0xFF3B4858),
|
||||
onSecondaryContainer: Color(0xFFD7E3F7),
|
||||
tertiary: Color(0xFFD6BEE4),
|
||||
onTertiary: Color(0xFF3B2948),
|
||||
tertiaryContainer: Color(0xFF523F5F),
|
||||
onTertiaryContainer: Color(0xFFF2DAFF),
|
||||
error: Color(0xFFFFB4AB),
|
||||
errorContainer: Color(0xFF93000A),
|
||||
onError: Color(0xFF690005),
|
||||
onErrorContainer: Color(0xFFFFDAD6),
|
||||
background: Color(0xFF1A1C1E),
|
||||
onBackground: Color(0xFFE2E2E6),
|
||||
surface: Color(0xFF1A1C1E),
|
||||
onSurface: Color(0xFFE2E2E6),
|
||||
surfaceVariant: Color(0xFF43474E),
|
||||
onSurfaceVariant: Color(0xFFC3C7CF),
|
||||
outline: Color(0xFF8D9199),
|
||||
onInverseSurface: Color(0xFF1A1C1E),
|
||||
inverseSurface: Color(0xFFE2E2E6),
|
||||
inversePrimary: Color(0xFF0061A4),
|
||||
shadow: Color(0xFF000000),
|
||||
surfaceTint: Color(0xFF9ECAFF),
|
||||
// outlineVariant: Color(0xFF43474E),
|
||||
// scrim: Color(0xFF000000),
|
||||
);
|
148
app/lib/material3.dart
Normal file
148
app/lib/material3.dart
Normal file
|
@ -0,0 +1,148 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class M3 extends ThemeExtension<M3> {
|
||||
const M3({
|
||||
required this.checkbox,
|
||||
required this.filterChip,
|
||||
required this.listTile,
|
||||
});
|
||||
|
||||
static M3 of(BuildContext context) => Theme.of(context).extension<M3>()!;
|
||||
|
||||
@override
|
||||
M3 copyWith({
|
||||
M3Checkbox? checkbox,
|
||||
M3FilterChip? filterChip,
|
||||
M3ListTile? listTile,
|
||||
}) =>
|
||||
M3(
|
||||
checkbox: checkbox ?? this.checkbox,
|
||||
filterChip: filterChip ?? this.filterChip,
|
||||
listTile: listTile ?? this.listTile,
|
||||
);
|
||||
|
||||
@override
|
||||
M3 lerp(ThemeExtension<M3>? other, double t) {
|
||||
if (other is! M3) {
|
||||
return this;
|
||||
}
|
||||
return M3(
|
||||
checkbox: checkbox.lerp(other.checkbox, t),
|
||||
filterChip: filterChip.lerp(other.filterChip, t),
|
||||
listTile: listTile.lerp(other.listTile, t),
|
||||
);
|
||||
}
|
||||
|
||||
final M3Checkbox checkbox;
|
||||
final M3FilterChip filterChip;
|
||||
final M3ListTile listTile;
|
||||
}
|
||||
|
||||
class M3Checkbox {
|
||||
const M3Checkbox({
|
||||
required this.disabled,
|
||||
});
|
||||
|
||||
M3Checkbox lerp(M3Checkbox? other, double t) {
|
||||
if (other is! M3Checkbox) {
|
||||
return this;
|
||||
}
|
||||
return M3Checkbox(
|
||||
disabled: disabled.lerp(other.disabled, t),
|
||||
);
|
||||
}
|
||||
|
||||
final M3CheckboxDisabled disabled;
|
||||
}
|
||||
|
||||
class M3CheckboxDisabled {
|
||||
const M3CheckboxDisabled({
|
||||
required this.container,
|
||||
});
|
||||
|
||||
M3CheckboxDisabled lerp(M3CheckboxDisabled? other, double t) {
|
||||
if (other is! M3CheckboxDisabled) {
|
||||
return this;
|
||||
}
|
||||
return M3CheckboxDisabled(
|
||||
container: Color.lerp(container, other.container, t)!,
|
||||
);
|
||||
}
|
||||
|
||||
final Color container;
|
||||
}
|
||||
|
||||
class M3FilterChip {
|
||||
const M3FilterChip({
|
||||
required this.disabled,
|
||||
});
|
||||
|
||||
M3FilterChip lerp(M3FilterChip? other, double t) {
|
||||
if (other is! M3FilterChip) {
|
||||
return this;
|
||||
}
|
||||
return M3FilterChip(
|
||||
disabled: disabled.lerp(other.disabled, t),
|
||||
);
|
||||
}
|
||||
|
||||
final M3FilterChipDisabled disabled;
|
||||
}
|
||||
|
||||
class M3FilterChipDisabled {
|
||||
const M3FilterChipDisabled({
|
||||
required this.containerSelected,
|
||||
required this.labelText,
|
||||
});
|
||||
|
||||
M3FilterChipDisabled lerp(M3FilterChipDisabled? other, double t) {
|
||||
if (other is! M3FilterChipDisabled) {
|
||||
return this;
|
||||
}
|
||||
return M3FilterChipDisabled(
|
||||
containerSelected:
|
||||
Color.lerp(containerSelected, other.containerSelected, t)!,
|
||||
labelText: Color.lerp(labelText, other.labelText, t)!,
|
||||
);
|
||||
}
|
||||
|
||||
final Color containerSelected;
|
||||
final Color labelText;
|
||||
}
|
||||
|
||||
class M3ListTile {
|
||||
const M3ListTile({
|
||||
required this.enabled,
|
||||
});
|
||||
|
||||
M3ListTile lerp(M3ListTile? other, double t) {
|
||||
if (other is! M3ListTile) {
|
||||
return this;
|
||||
}
|
||||
return M3ListTile(
|
||||
enabled: enabled.lerp(other.enabled, t),
|
||||
);
|
||||
}
|
||||
|
||||
final M3ListTileEnabled enabled;
|
||||
}
|
||||
|
||||
class M3ListTileEnabled {
|
||||
const M3ListTileEnabled({
|
||||
required this.headline,
|
||||
required this.supportingText,
|
||||
});
|
||||
|
||||
M3ListTileEnabled lerp(M3ListTileEnabled? other, double t) {
|
||||
if (other is! M3ListTileEnabled) {
|
||||
return this;
|
||||
}
|
||||
return M3ListTileEnabled(
|
||||
headline: Color.lerp(headline, other.headline, t)!,
|
||||
supportingText: Color.lerp(supportingText, other.supportingText, t)!,
|
||||
);
|
||||
}
|
||||
|
||||
final Color headline;
|
||||
final Color supportingText;
|
||||
}
|
|
@ -1,213 +1,196 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:nc_photos/color_schemes.g.dart';
|
||||
import 'package:nc_photos/material3.dart';
|
||||
import 'package:nc_photos/pref.dart';
|
||||
|
||||
class AppTheme extends StatelessWidget {
|
||||
const AppTheme({
|
||||
Key? key,
|
||||
required this.child,
|
||||
this.brightnessOverride,
|
||||
}) : super(key: key);
|
||||
extension ThemeExtension on ThemeData {
|
||||
double get widthLimitedContentMaxWidth => 550.0;
|
||||
|
||||
factory AppTheme.light({
|
||||
Key? key,
|
||||
required Widget child,
|
||||
}) =>
|
||||
AppTheme(
|
||||
key: key,
|
||||
brightnessOverride: Brightness.light,
|
||||
child: child,
|
||||
);
|
||||
Color get listPlaceholderBackgroundColor =>
|
||||
colorScheme.secondaryContainer.withOpacity(.6);
|
||||
|
||||
factory AppTheme.dark({
|
||||
Key? key,
|
||||
required Widget child,
|
||||
}) =>
|
||||
AppTheme(
|
||||
key: key,
|
||||
brightnessOverride: Brightness.dark,
|
||||
child: child,
|
||||
);
|
||||
Color get listPlaceholderForegroundColor =>
|
||||
colorScheme.onSecondaryContainer.withOpacity(.7);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Theme(
|
||||
data: _buildThemeData(context),
|
||||
child: DefaultTextStyle(
|
||||
style: _buildTextStyle(context),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
Color get homeNavigationBarBackgroundColor =>
|
||||
elevate(colorScheme.surface, 2).withOpacity(.77);
|
||||
|
||||
Color get onDarkSurface {
|
||||
return brightness == Brightness.light
|
||||
? colorScheme.onInverseSurface
|
||||
: colorScheme.onSurface;
|
||||
}
|
||||
|
||||
static ThemeData buildThemeData(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return theme.brightness == Brightness.light
|
||||
? buildLightThemeData()
|
||||
: buildDarkThemeData();
|
||||
}
|
||||
|
||||
static AppBarTheme getContextualAppBarTheme(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
if (theme.brightness == Brightness.light) {
|
||||
return theme.appBarTheme.copyWith(
|
||||
backgroundColor: Colors.grey[800],
|
||||
foregroundColor: Colors.white.withOpacity(.87),
|
||||
);
|
||||
} else {
|
||||
return theme.appBarTheme.copyWith(
|
||||
backgroundColor: Colors.grey[200],
|
||||
foregroundColor: Colors.black87,
|
||||
);
|
||||
/// Apply surface tint to [color] based on the [elevation] level
|
||||
///
|
||||
/// This function is a temporary workaround for widgets not yet fully
|
||||
/// supported Material 3
|
||||
Color elevate(Color color, int elevation) {
|
||||
final double tintOpacity;
|
||||
switch (elevation) {
|
||||
case 1:
|
||||
tintOpacity = 0.05;
|
||||
break;
|
||||
case 2:
|
||||
tintOpacity = 0.08;
|
||||
break;
|
||||
case 3:
|
||||
tintOpacity = 0.11;
|
||||
break;
|
||||
case 4:
|
||||
tintOpacity = 0.12;
|
||||
break;
|
||||
case 5:
|
||||
default:
|
||||
tintOpacity = 0.14;
|
||||
break;
|
||||
}
|
||||
return Color.lerp(color, colorScheme.surfaceTint, tintOpacity)!;
|
||||
}
|
||||
}
|
||||
|
||||
static Color getSelectionOverlayColor(BuildContext context) {
|
||||
return Theme.of(context).brightness == Brightness.light
|
||||
? primarySwatchLight[100]!.withOpacity(0.7)
|
||||
: primarySwatchDark[700]!.withOpacity(0.7);
|
||||
ThemeData buildTheme(Brightness brightness) {
|
||||
return (brightness == Brightness.light)
|
||||
? buildLightTheme()
|
||||
: buildDarkTheme();
|
||||
}
|
||||
|
||||
ThemeData buildLightTheme() {
|
||||
final theme = _applyColorScheme(lightColorScheme);
|
||||
return theme;
|
||||
}
|
||||
|
||||
ThemeData buildDarkTheme() {
|
||||
final ThemeData theme;
|
||||
if (Pref().isUseBlackInDarkThemeOr(false)) {
|
||||
theme = _applyColorScheme(darkColorScheme.copyWith(
|
||||
background: Colors.black,
|
||||
surface: Colors.grey[900],
|
||||
));
|
||||
} else {
|
||||
theme = _applyColorScheme(darkColorScheme);
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
|
||||
static Color getOverscrollIndicatorColor(BuildContext context) {
|
||||
return Theme.of(context).brightness == Brightness.light
|
||||
? Colors.grey[800]!
|
||||
: Colors.grey[200]!;
|
||||
}
|
||||
|
||||
static Color getRootPickerContentBoxColor(BuildContext context) {
|
||||
return Colors.blue[200]!;
|
||||
}
|
||||
|
||||
static Color getPrimaryTextColor(BuildContext context) {
|
||||
return Theme.of(context).brightness == Brightness.light
|
||||
? primaryTextColorLight
|
||||
: primaryTextColorDark;
|
||||
}
|
||||
|
||||
static Color getSecondaryTextColor(BuildContext context) {
|
||||
return Theme.of(context).brightness == Brightness.light
|
||||
? Colors.black.withOpacity(.6)
|
||||
: Colors.white60;
|
||||
}
|
||||
|
||||
static Color getPrimaryTextColorInverse(BuildContext context) =>
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? primaryTextColorDark
|
||||
: primaryTextColorLight;
|
||||
|
||||
static Color getAppBarDarkModeSwitchColor(BuildContext context) {
|
||||
return Colors.black87;
|
||||
}
|
||||
|
||||
static Color getAppBarDarkModeSwitchTrackColor(BuildContext context) {
|
||||
return Colors.white.withOpacity(.5);
|
||||
}
|
||||
|
||||
static Color getListItemBackgroundColor(BuildContext context) {
|
||||
return Theme.of(context).brightness == Brightness.light
|
||||
? Colors.black26
|
||||
: Colors.white12;
|
||||
}
|
||||
|
||||
static Color getUnfocusedIconColor(BuildContext context) {
|
||||
return Theme.of(context).brightness == Brightness.light
|
||||
? unfocusedIconColorLight
|
||||
: unfocusedIconColorDark;
|
||||
}
|
||||
|
||||
static ThemeData buildLightThemeData() {
|
||||
final theme = ThemeData(
|
||||
brightness: Brightness.light,
|
||||
primarySwatch: AppTheme.primarySwatchLight,
|
||||
);
|
||||
final appBarTheme = theme.appBarTheme.copyWith(
|
||||
backgroundColor: theme.scaffoldBackgroundColor,
|
||||
foregroundColor: theme.colorScheme.onSurface,
|
||||
);
|
||||
return theme.copyWith(appBarTheme: appBarTheme);
|
||||
}
|
||||
|
||||
static ThemeData buildDarkThemeData() {
|
||||
final Color background;
|
||||
final Color popup;
|
||||
if (Pref().isUseBlackInDarkThemeOr(false)) {
|
||||
background = Colors.black;
|
||||
popup = Colors.grey[900]!;
|
||||
} else {
|
||||
// in the material spec, black is suggested to be 0x121212, but the one
|
||||
// used in flutter by default is 0x303030, why?
|
||||
background = Colors.grey[850]!;
|
||||
popup = Colors.grey[800]!;
|
||||
}
|
||||
|
||||
final theme = ThemeData(
|
||||
brightness: Brightness.dark,
|
||||
primarySwatch: AppTheme.primarySwatchDark,
|
||||
scaffoldBackgroundColor: background,
|
||||
dialogBackgroundColor: popup,
|
||||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||||
backgroundColor: background,
|
||||
),
|
||||
popupMenuTheme: PopupMenuThemeData(
|
||||
color: popup,
|
||||
),
|
||||
checkboxTheme: CheckboxThemeData(
|
||||
fillColor: _CheckboxDarkColorProperty(),
|
||||
),
|
||||
);
|
||||
final appBarTheme = theme.appBarTheme.copyWith(
|
||||
backgroundColor: background,
|
||||
foregroundColor: theme.colorScheme.onSurface,
|
||||
);
|
||||
return theme.copyWith(appBarTheme: appBarTheme);
|
||||
}
|
||||
|
||||
ThemeData _buildThemeData(BuildContext context) {
|
||||
return (brightnessOverride ?? Theme.of(context).brightness) ==
|
||||
Brightness.light
|
||||
? buildLightThemeData()
|
||||
: buildDarkThemeData();
|
||||
}
|
||||
|
||||
TextStyle _buildTextStyle(BuildContext context) {
|
||||
return (brightnessOverride ?? Theme.of(context).brightness) ==
|
||||
Brightness.light
|
||||
? const TextStyle(color: AppTheme.primaryTextColorLight)
|
||||
: TextStyle(color: AppTheme.primaryTextColorDark);
|
||||
}
|
||||
|
||||
static const primarySwatchLight = Colors.blue;
|
||||
static const primarySwatchDark = Colors.cyan;
|
||||
|
||||
static const primaryTextColorLight = Colors.black87;
|
||||
static final primaryTextColorDark = Colors.white.withOpacity(.87);
|
||||
|
||||
static const unfocusedIconColorLight = Colors.black54;
|
||||
static const unfocusedIconColorDark = Colors.white70;
|
||||
|
||||
static const widthLimitedContentMaxWidth = 550.0;
|
||||
|
||||
/// Make a TextButton look like a default FlatButton. See
|
||||
/// https://flutter.dev/go/material-button-migration-guide
|
||||
static final flatButtonStyle = TextButton.styleFrom(
|
||||
primary: Colors.black87,
|
||||
minimumSize: const Size(88, 36),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(2.0)),
|
||||
ThemeData buildDarkModeSwitchTheme(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return theme.copyWith(
|
||||
switchTheme: SwitchThemeData(
|
||||
trackColor: MaterialStateProperty.all(theme.colorScheme.surfaceVariant),
|
||||
thumbColor: MaterialStateProperty.all(Colors.black87),
|
||||
),
|
||||
);
|
||||
|
||||
final Widget child;
|
||||
final Brightness? brightnessOverride;
|
||||
}
|
||||
|
||||
class _CheckboxDarkColorProperty implements MaterialStateProperty<Color?> {
|
||||
@override
|
||||
resolve(Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return Colors.cyanAccent[400];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
ThemeData _applyColorScheme(ColorScheme colorScheme) {
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: colorScheme.brightness,
|
||||
colorScheme: colorScheme,
|
||||
scaffoldBackgroundColor: colorScheme.background,
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: colorScheme.background,
|
||||
foregroundColor: colorScheme.onSurface,
|
||||
),
|
||||
listTileTheme: ListTileThemeData(
|
||||
iconColor: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
iconTheme: IconThemeData(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
// remove after dialog supports m3
|
||||
dialogBackgroundColor:
|
||||
Color.lerp(colorScheme.surface, colorScheme.surfaceTint, 0.11),
|
||||
popupMenuTheme: PopupMenuThemeData(
|
||||
// remove after menu supports m3
|
||||
color: Color.lerp(colorScheme.surface, colorScheme.surfaceTint, 0.08),
|
||||
),
|
||||
navigationBarTheme: const NavigationBarThemeData(
|
||||
// default for Material 3
|
||||
height: 80,
|
||||
),
|
||||
// remove after checkbox supports m3
|
||||
// see: https://m3.material.io/components/checkbox/specs
|
||||
checkboxTheme: CheckboxThemeData(
|
||||
fillColor: MaterialStateProperty.resolveWith((states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
return colorScheme.onSurface;
|
||||
} else {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return colorScheme.primary;
|
||||
} else {
|
||||
return Colors.transparent;
|
||||
}
|
||||
}
|
||||
}),
|
||||
checkColor: MaterialStateProperty.all(colorScheme.onPrimary),
|
||||
),
|
||||
// remove after checkbox supports m3
|
||||
// see: https://m3.material.io/components/switch/specs
|
||||
// the color here is slightly modified to work better with the M2 switch
|
||||
switchTheme: SwitchThemeData(
|
||||
trackColor: MaterialStateProperty.resolveWith((states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return colorScheme.onSurface.withOpacity(.12);
|
||||
} else {
|
||||
return colorScheme.surfaceVariant.withOpacity(.12);
|
||||
}
|
||||
} else {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
// return colorScheme.primary;
|
||||
return colorScheme.primaryContainer;
|
||||
} else {
|
||||
return colorScheme.surfaceVariant;
|
||||
}
|
||||
}
|
||||
}),
|
||||
thumbColor: MaterialStateProperty.resolveWith((states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
// return colorScheme.surface;
|
||||
return colorScheme.onSurface.withOpacity(.38);
|
||||
} else {
|
||||
return colorScheme.onSurface.withOpacity(.38);
|
||||
}
|
||||
} else {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
// return colorScheme.onPrimary;
|
||||
return colorScheme.primary;
|
||||
} else {
|
||||
return colorScheme.outline;
|
||||
}
|
||||
}
|
||||
}),
|
||||
),
|
||||
snackBarTheme: SnackBarThemeData(
|
||||
backgroundColor: colorScheme.inverseSurface,
|
||||
contentTextStyle: TextStyle(
|
||||
color: colorScheme.onInverseSurface,
|
||||
),
|
||||
actionTextColor: colorScheme.inversePrimary,
|
||||
),
|
||||
extensions: [
|
||||
M3(
|
||||
checkbox: M3Checkbox(
|
||||
disabled: M3CheckboxDisabled(
|
||||
container: colorScheme.onSurface.withOpacity(.38),
|
||||
),
|
||||
),
|
||||
filterChip: M3FilterChip(
|
||||
disabled: M3FilterChipDisabled(
|
||||
containerSelected: colorScheme.onSurface.withOpacity(.12),
|
||||
labelText: colorScheme.onSurface.withOpacity(.38),
|
||||
),
|
||||
),
|
||||
listTile: M3ListTile(
|
||||
enabled: M3ListTileEnabled(
|
||||
headline: colorScheme.onSurface,
|
||||
supportingText: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
|
||||
class AboutGeocodingDialog extends StatelessWidget {
|
||||
const AboutGeocodingDialog({
|
||||
|
@ -9,21 +8,19 @@ class AboutGeocodingDialog extends StatelessWidget {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: AlertDialog(
|
||||
title: Text(L10n.global().gpsPlaceAboutDialogTitle),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(L10n.global().gpsPlaceAboutDialogContent),
|
||||
const SizedBox(height: 16),
|
||||
const Divider(height: 16),
|
||||
const Text(
|
||||
"Based on GeoNames Gazetteer data by GeoNames, licensed under CC BY 4.0",
|
||||
),
|
||||
],
|
||||
),
|
||||
return AlertDialog(
|
||||
title: Text(L10n.global().gpsPlaceAboutDialogTitle),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(L10n.global().gpsPlaceAboutDialogContent),
|
||||
const SizedBox(height: 16),
|
||||
const Divider(height: 16),
|
||||
const Text(
|
||||
"Based on GeoNames Gazetteer data by GeoNames, licensed under CC BY 4.0",
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import 'package:nc_photos/exception_util.dart' as exception_util;
|
|||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/widget/home.dart';
|
||||
import 'package:nc_photos/widget/settings.dart';
|
||||
import 'package:nc_photos/widget/sign_in.dart';
|
||||
|
@ -49,10 +48,7 @@ class _AccountPickerDialogState extends State<AccountPickerDialog> {
|
|||
title: Text(label ?? a.url),
|
||||
subtitle: label == null ? Text(a.username2) : null,
|
||||
trailing: IconButton(
|
||||
icon: Icon(
|
||||
Icons.close,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
icon: const Icon(Icons.close),
|
||||
tooltip: L10n.global().deleteTooltip,
|
||||
onPressed: () => _onRemoveItemPressed(a),
|
||||
),
|
||||
|
@ -69,43 +65,35 @@ class _AccountPickerDialogState extends State<AccountPickerDialog> {
|
|||
},
|
||||
child: Tooltip(
|
||||
message: L10n.global().addServerTooltip,
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
child: const Center(
|
||||
child: Icon(Icons.add),
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
final accountLabel = AccountPref.of(widget.account).getAccountLabel();
|
||||
return AppTheme(
|
||||
child: SimpleDialog(
|
||||
title: ListTile(
|
||||
dense: true,
|
||||
title: Text(
|
||||
accountLabel ?? widget.account.url,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
subtitle: accountLabel == null
|
||||
? Text(
|
||||
widget.account.username2,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
)
|
||||
: null,
|
||||
trailing: IconButton(
|
||||
icon: Icon(
|
||||
Icons.settings_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
tooltip: L10n.global().settingsMenuLabel,
|
||||
onPressed: _onEditPressed,
|
||||
),
|
||||
return SimpleDialog(
|
||||
title: ListTile(
|
||||
dense: true,
|
||||
title: Text(
|
||||
accountLabel ?? widget.account.url,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
subtitle: accountLabel == null
|
||||
? Text(
|
||||
widget.account.username2,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
)
|
||||
: null,
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.settings_outlined),
|
||||
tooltip: L10n.global().settingsMenuLabel,
|
||||
onPressed: _onEditPressed,
|
||||
),
|
||||
titlePadding: const EdgeInsetsDirectional.fromSTEB(8, 16, 8, 0),
|
||||
contentPadding: const EdgeInsetsDirectional.fromSTEB(0, 12, 0, 8),
|
||||
children: otherAccountOptions + addAccountOptions,
|
||||
),
|
||||
titlePadding: const EdgeInsetsDirectional.fromSTEB(8, 16, 8, 0),
|
||||
contentPadding: const EdgeInsetsDirectional.fromSTEB(0, 12, 0, 8),
|
||||
children: otherAccountOptions + addAccountOptions,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ import 'package:nc_photos/pref.dart';
|
|||
import 'package:nc_photos/session_storage.dart';
|
||||
import 'package:nc_photos/share_handler.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/ls_single_file.dart';
|
||||
import 'package:nc_photos/use_case/preprocess_album.dart';
|
||||
import 'package:nc_photos/use_case/remove_from_album.dart';
|
||||
|
@ -111,20 +110,18 @@ class _AlbumBrowserState extends State<AlbumBrowser>
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) {
|
||||
if (isEditMode) {
|
||||
return Form(
|
||||
key: _editFormKey,
|
||||
child: _buildContent(context),
|
||||
);
|
||||
} else {
|
||||
return _buildContent(context);
|
||||
}
|
||||
},
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) {
|
||||
if (isEditMode) {
|
||||
return Form(
|
||||
key: _editFormKey,
|
||||
child: _buildContent(context),
|
||||
);
|
||||
} else {
|
||||
return _buildContent(context);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -253,17 +250,7 @@ class _AlbumBrowserState extends State<AlbumBrowser>
|
|||
child: content,
|
||||
);
|
||||
}
|
||||
return buildItemStreamListOuter(
|
||||
context,
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
child: content,
|
||||
),
|
||||
);
|
||||
return buildItemStreamListOuter(context, child: content);
|
||||
}
|
||||
|
||||
Widget _buildAppBar(BuildContext context) {
|
||||
|
|
|
@ -6,7 +6,6 @@ import 'package:nc_photos/api/api.dart';
|
|||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/cache_manager_util.dart';
|
||||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
|
||||
class AlbumBrowserAppBar extends StatelessWidget {
|
||||
const AlbumBrowserAppBar({
|
||||
|
@ -26,9 +25,8 @@ class AlbumBrowserAppBar extends StatelessWidget {
|
|||
background: _getAppBarCover(context, account, coverPreviewUrl),
|
||||
title: Text(
|
||||
album.name,
|
||||
style: TextStyle(
|
||||
color: AppTheme.getPrimaryTextColor(context),
|
||||
),
|
||||
style:
|
||||
TextStyle(color: Theme.of(context).appBarTheme.foregroundColor),
|
||||
),
|
||||
),
|
||||
actions: actions,
|
||||
|
@ -95,9 +93,9 @@ class _AlbumBrowserEditAppBarState extends State<AlbumBrowserEditAppBar> {
|
|||
onSaved: (_) {
|
||||
widget.onAlbumNameSaved?.call(_controller.text);
|
||||
},
|
||||
style: TextStyle(
|
||||
color: AppTheme.getPrimaryTextColor(context),
|
||||
),
|
||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||
color: Theme.of(context).appBarTheme.foregroundColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
leading: IconButton(
|
||||
|
|
|
@ -8,7 +8,6 @@ import 'package:nc_photos/entity/file_descriptor.dart';
|
|||
import 'package:nc_photos/iterable_extension.dart';
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/widget/dir_picker.dart';
|
||||
|
||||
class AlbumDirPickerArguments {
|
||||
|
@ -45,10 +44,8 @@ class AlbumDirPicker extends StatefulWidget {
|
|||
class _AlbumDirPickerState extends State<AlbumDirPicker> {
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: _buildContent(context),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
|
||||
class AlbumGridItem extends StatelessWidget {
|
||||
const AlbumGridItem({
|
||||
|
@ -40,23 +39,18 @@ class AlbumGridItem extends StatelessWidget {
|
|||
const SizedBox(height: 8),
|
||||
Text(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.bodyText1!.copyWith(
|
||||
color: AppTheme.getPrimaryTextColor(context),
|
||||
),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
textAlign: TextAlign.start,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
const SizedBox(height: 2),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
subtitle ?? "",
|
||||
style: Theme.of(context).textTheme.bodyText2!.copyWith(
|
||||
fontSize: 10,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
textAlign: TextAlign.start,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
@ -65,10 +59,7 @@ class AlbumGridItem extends StatelessWidget {
|
|||
if (subtitle2?.isNotEmpty == true)
|
||||
Text(
|
||||
subtitle2!,
|
||||
style: Theme.of(context).textTheme.bodyText2!.copyWith(
|
||||
fontSize: 10,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
textAlign: TextAlign.end,
|
||||
maxLines: 1,
|
||||
),
|
||||
|
|
|
@ -20,7 +20,6 @@ import 'package:nc_photos/exception_util.dart' as exception_util;
|
|||
import 'package:nc_photos/iterable_extension.dart';
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/create_album.dart';
|
||||
import 'package:nc_photos/use_case/preprocess_album.dart';
|
||||
import 'package:nc_photos/use_case/update_album_with_actual_items.dart';
|
||||
|
@ -74,17 +73,14 @@ class _AlbumImporterState extends State<AlbumImporter> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body:
|
||||
BlocListener<ListImportableAlbumBloc, ListImportableAlbumBlocState>(
|
||||
return Scaffold(
|
||||
body: BlocListener<ListImportableAlbumBloc, ListImportableAlbumBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child:
|
||||
BlocBuilder<ListImportableAlbumBloc, ListImportableAlbumBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListImportableAlbumBloc,
|
||||
ListImportableAlbumBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -59,15 +59,13 @@ class _AlbumPickerState extends State<AlbumPicker>
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: BlocListener<ListAlbumBloc, ListAlbumBlocState>(
|
||||
return Scaffold(
|
||||
body: BlocListener<ListAlbumBloc, ListAlbumBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListAlbumBloc, ListAlbumBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListAlbumBloc, ListAlbumBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -125,11 +123,11 @@ class _AlbumPickerState extends State<AlbumPicker>
|
|||
cover: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Container(
|
||||
color: AppTheme.getListItemBackgroundColor(context),
|
||||
color: Theme.of(context).listPlaceholderBackgroundColor,
|
||||
constraints: const BoxConstraints.expand(),
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: Colors.white.withOpacity(.8),
|
||||
color: Theme.of(context).listPlaceholderForegroundColor,
|
||||
size: 88,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -22,7 +22,6 @@ import 'package:nc_photos/exception_util.dart' as exception_util;
|
|||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/string_extension.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/create_share.dart';
|
||||
import 'package:nc_photos/use_case/remove_share.dart';
|
||||
import 'package:nc_photos/widget/empty_list_indicator.dart';
|
||||
|
@ -73,17 +72,15 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: BlocListener<ListAlbumShareOutlierBloc,
|
||||
return Scaffold(
|
||||
body: BlocListener<ListAlbumShareOutlierBloc,
|
||||
ListAlbumShareOutlierBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListAlbumShareOutlierBloc,
|
||||
ListAlbumShareOutlierBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListAlbumShareOutlierBloc,
|
||||
ListAlbumShareOutlierBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -112,23 +109,16 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
} else {
|
||||
return Stack(
|
||||
children: [
|
||||
Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) => _buildItem(context, _items[index]),
|
||||
childCount: _items.length,
|
||||
),
|
||||
CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) => _buildItem(context, _items[index]),
|
||||
childCount: _items.length,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (state is ListAlbumShareOutlierBlocLoading)
|
||||
const Align(
|
||||
|
@ -264,20 +254,11 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
}
|
||||
|
||||
Widget _buildFileThumbnail(File file) {
|
||||
final Widget child;
|
||||
if (file_util.isAlbumFile(widget.account, file)) {
|
||||
return SizedBox(
|
||||
width: 56,
|
||||
height: 56,
|
||||
child: Icon(
|
||||
Icons.photo_album,
|
||||
size: 32,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
);
|
||||
child = const Icon(Icons.photo_album, size: 32);
|
||||
} else {
|
||||
return CachedNetworkImage(
|
||||
width: 56,
|
||||
height: 56,
|
||||
child = CachedNetworkImage(
|
||||
cacheManager: ThumbnailCacheManager.inst,
|
||||
imageUrl: api_util.getFilePreviewUrl(widget.account, file,
|
||||
width: k.photoThumbSize, height: k.photoThumbSize),
|
||||
|
@ -287,13 +268,15 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
fadeInDuration: const Duration(),
|
||||
filterQuality: FilterQuality.high,
|
||||
imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
|
||||
errorWidget: (context, url, error) => Icon(
|
||||
Icons.image_not_supported,
|
||||
size: 32,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
errorWidget: (context, url, error) =>
|
||||
const Icon(Icons.image_not_supported, size: 32),
|
||||
);
|
||||
}
|
||||
return SizedBox(
|
||||
width: 56,
|
||||
height: 56,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
String _buildFilename(File file) {
|
||||
|
@ -309,34 +292,26 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
}) {
|
||||
return IconButton(
|
||||
onPressed: onPressed,
|
||||
icon: Icon(
|
||||
Icons.handyman_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
icon: const Icon(Icons.handyman_outlined),
|
||||
tooltip: L10n.global().fixTooltip,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildProcessingIcon(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
return const Padding(
|
||||
padding: EdgeInsets.all(12),
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFixedIcon(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Icon(
|
||||
Icons.check,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
return const Padding(
|
||||
padding: EdgeInsets.all(12),
|
||||
child: Icon(Icons.check),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
71
app/lib/widget/app_bar_title_container.dart
Normal file
71
app/lib/widget/app_bar_title_container.dart
Normal file
|
@ -0,0 +1,71 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:nc_photos/material3.dart';
|
||||
|
||||
/// App bar title with optional subtitle and leading icon
|
||||
class AppBarTitleContainer extends StatelessWidget {
|
||||
const AppBarTitleContainer({
|
||||
super.key,
|
||||
required this.title,
|
||||
this.subtitle,
|
||||
this.icon,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
if (icon != null) ...[
|
||||
SizedBox(
|
||||
height: 40,
|
||||
width: 40,
|
||||
child: Center(
|
||||
child: IconTheme(
|
||||
data: IconThemeData(
|
||||
size: 24,
|
||||
color: Theme.of(context).appBarTheme.foregroundColor,
|
||||
),
|
||||
child: icon!,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
],
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
DefaultTextStyle(
|
||||
style: subtitle == null
|
||||
? Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||
color: Theme.of(context).appBarTheme.foregroundColor,
|
||||
)
|
||||
: Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||
color: Theme.of(context).appBarTheme.foregroundColor,
|
||||
),
|
||||
maxLines: 1,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.clip,
|
||||
child: title,
|
||||
),
|
||||
if (subtitle != null)
|
||||
DefaultTextStyle(
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: M3.of(context).listTile.enabled.supportingText,
|
||||
),
|
||||
maxLines: 1,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.clip,
|
||||
child: subtitle!,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
final Widget title;
|
||||
final Widget? subtitle;
|
||||
final Widget? icon;
|
||||
}
|
|
@ -18,7 +18,6 @@ import 'package:nc_photos/language_util.dart' as language_util;
|
|||
import 'package:nc_photos/object_extension.dart';
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/inflate_file_descriptor.dart';
|
||||
import 'package:nc_photos/use_case/update_property.dart';
|
||||
import 'package:nc_photos/widget/builder/photo_list_item_builder.dart';
|
||||
|
@ -71,15 +70,13 @@ class _ArchiveBrowserState extends State<ArchiveBrowser>
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: BlocListener<ScanAccountDirBloc, ScanAccountDirBlocState>(
|
||||
return Scaffold(
|
||||
body: BlocListener<ScanAccountDirBloc, ScanAccountDirBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ScanAccountDirBloc, ScanAccountDirBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ScanAccountDirBloc, ScanAccountDirBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -134,20 +131,13 @@ class _ArchiveBrowserState extends State<ArchiveBrowser>
|
|||
children: [
|
||||
buildItemStreamListOuter(
|
||||
context,
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (state is ScanAccountDirBlocLoading ||
|
||||
|
|
|
@ -79,7 +79,7 @@ class AlbumGridItemBuilder {
|
|||
} catch (_) {
|
||||
cover = Icon(
|
||||
Icons.panorama,
|
||||
color: Colors.white.withOpacity(.8),
|
||||
color: Theme.of(context).listPlaceholderForegroundColor,
|
||||
size: 88,
|
||||
);
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ class AlbumGridItemBuilder {
|
|||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Container(
|
||||
color: AppTheme.getListItemBackgroundColor(context),
|
||||
color: Theme.of(context).listPlaceholderBackgroundColor,
|
||||
constraints: const BoxConstraints.expand(),
|
||||
child: cover,
|
||||
),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
|
||||
class ChangelogArguments {
|
||||
const ChangelogArguments(this.fromVersion);
|
||||
|
@ -30,11 +29,9 @@ class Changelog extends StatelessWidget {
|
|||
);
|
||||
|
||||
@override
|
||||
build(BuildContext context) => AppTheme(
|
||||
child: Scaffold(
|
||||
appBar: _buildAppBar(),
|
||||
body: Builder(builder: (context) => _buildContent(context)),
|
||||
),
|
||||
build(BuildContext context) => Scaffold(
|
||||
appBar: _buildAppBar(),
|
||||
body: Builder(builder: (context) => _buildContent(context)),
|
||||
);
|
||||
|
||||
AppBar _buildAppBar() => AppBar(
|
||||
|
|
|
@ -38,21 +38,20 @@ class CollectionListSmall extends StatelessWidget {
|
|||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Colors.black.withOpacity(0),
|
||||
Colors.black.withOpacity(.55),
|
||||
Colors.black.withOpacity(.5),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
color: Colors.black.withOpacity(.55),
|
||||
color: Colors.black.withOpacity(.5),
|
||||
constraints: const BoxConstraints(minWidth: double.infinity),
|
||||
padding: const EdgeInsets.fromLTRB(8, 0, 8, 4),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
color: AppTheme.primaryTextColorDark,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||
color: Theme.of(context).onDarkSurface,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
@ -80,7 +79,7 @@ class CollectionListSmall extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
return Container(
|
||||
color: AppTheme.getListItemBackgroundColor(context),
|
||||
color: Theme.of(context).listPlaceholderBackgroundColor,
|
||||
constraints: const BoxConstraints.expand(),
|
||||
child: content,
|
||||
);
|
||||
|
|
|
@ -18,7 +18,6 @@ import 'package:nc_photos/mobile/self_signed_cert_manager.dart';
|
|||
import 'package:nc_photos/platform/features.dart' as features;
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/string_extension.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/url_launcher_util.dart';
|
||||
import 'package:nc_photos/use_case/ls_single_file.dart';
|
||||
|
||||
|
@ -61,14 +60,11 @@ class _ConnectState extends State<Connect> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body:
|
||||
BlocListener<AppPasswordExchangeBloc, AppPasswordExchangeBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: Builder(builder: (context) => _buildContent(context)),
|
||||
),
|
||||
return Scaffold(
|
||||
body: BlocListener<AppPasswordExchangeBloc, AppPasswordExchangeBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: Builder(builder: (context) => _buildContent(context)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ import 'package:nc_photos/entity/file_descriptor.dart';
|
|||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/material3.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:path/path.dart' as path_lib;
|
||||
|
||||
class DirPicker extends StatefulWidget {
|
||||
|
@ -106,6 +106,7 @@ class DirPickerState extends State<DirPicker> {
|
|||
// needed to prevent background color overflowing the parent bound, see:
|
||||
// https://github.com/flutter/flutter/issues/86584
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: ListView.separated(
|
||||
key: Key(_currentPath),
|
||||
itemBuilder: (context, index) {
|
||||
|
@ -142,27 +143,38 @@ class DirPickerState extends State<DirPicker> {
|
|||
final pickState = _isItemPicked(item);
|
||||
|
||||
IconData? iconData;
|
||||
Color? iconColor;
|
||||
if (canPick) {
|
||||
switch (pickState) {
|
||||
case _PickState.picked:
|
||||
iconData = widget.isMultipleSelections
|
||||
? Icons.check_box
|
||||
: Icons.radio_button_checked;
|
||||
iconColor = CheckboxTheme.of(context)
|
||||
.fillColor!
|
||||
.resolve({MaterialState.selected});
|
||||
break;
|
||||
|
||||
case _PickState.childPicked:
|
||||
iconData = widget.isMultipleSelections
|
||||
? Icons.indeterminate_check_box
|
||||
: Icons.remove_circle_outline;
|
||||
iconColor = CheckboxTheme.of(context)
|
||||
.fillColor!
|
||||
.resolve({MaterialState.selected});
|
||||
break;
|
||||
|
||||
case _PickState.notPicked:
|
||||
default:
|
||||
iconData = widget.isMultipleSelections
|
||||
? Icons.check_box_outline_blank
|
||||
: Icons.radio_button_unchecked;
|
||||
iconColor = Theme.of(context).colorScheme.onSurface;
|
||||
break;
|
||||
}
|
||||
} else if (item.isE2ee) {
|
||||
iconData = Icons.lock_outlined;
|
||||
iconColor = M3.of(context).checkbox.disabled.container;
|
||||
}
|
||||
|
||||
return ListTile(
|
||||
|
@ -177,6 +189,7 @@ class DirPickerState extends State<DirPicker> {
|
|||
child: Icon(
|
||||
iconData,
|
||||
key: ValueKey(pickState),
|
||||
color: iconColor,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
|
@ -188,15 +201,15 @@ class DirPickerState extends State<DirPicker> {
|
|||
},
|
||||
)
|
||||
: IconButton(
|
||||
icon: Icon(iconData),
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
icon: Icon(iconData, color: iconColor),
|
||||
onPressed: null,
|
||||
),
|
||||
title: Text(item.file.filename),
|
||||
trailing: item.children?.isNotEmpty == true
|
||||
? const Icon(Icons.arrow_forward_ios)
|
||||
: null,
|
||||
textColor: item.isE2ee ? AppTheme.getUnfocusedIconColor(context) : null,
|
||||
textColor:
|
||||
item.isE2ee ? M3.of(context).checkbox.disabled.container : null,
|
||||
onTap: item.children?.isNotEmpty == true
|
||||
? () {
|
||||
try {
|
||||
|
|
|
@ -26,7 +26,6 @@ import 'package:nc_photos/or_null.dart';
|
|||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/share_handler.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/preprocess_album.dart';
|
||||
import 'package:nc_photos/use_case/remove.dart';
|
||||
import 'package:nc_photos/use_case/update_album.dart';
|
||||
|
@ -106,20 +105,18 @@ class _DynamicAlbumBrowserState extends State<DynamicAlbumBrowser>
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) {
|
||||
if (isEditMode) {
|
||||
return Form(
|
||||
key: _editFormKey,
|
||||
child: _buildContent(context),
|
||||
);
|
||||
} else {
|
||||
return _buildContent(context);
|
||||
}
|
||||
},
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) {
|
||||
if (isEditMode) {
|
||||
return Form(
|
||||
key: _editFormKey,
|
||||
child: _buildContent(context),
|
||||
);
|
||||
} else {
|
||||
return _buildContent(context);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -214,26 +211,19 @@ class _DynamicAlbumBrowserState extends State<DynamicAlbumBrowser>
|
|||
}
|
||||
return buildItemStreamListOuter(
|
||||
context,
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
SliverIgnorePointer(
|
||||
ignoring: isEditMode,
|
||||
sliver: SliverOpacity(
|
||||
opacity: isEditMode ? .25 : 1,
|
||||
sliver: buildItemStreamList(
|
||||
maxCrossAxisExtent: thumbSize.toDouble(),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
SliverIgnorePointer(
|
||||
ignoring: isEditMode,
|
||||
sliver: SliverOpacity(
|
||||
opacity: isEditMode ? .25 : 1,
|
||||
sliver: buildItemStreamList(
|
||||
maxCrossAxisExtent: thumbSize.toDouble(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import 'package:nc_photos/platform/k.dart' as platform_k;
|
|||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/share_handler.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/widget/empty_list_indicator.dart';
|
||||
import 'package:nc_photos/widget/handler/delete_local_selection_handler.dart';
|
||||
import 'package:nc_photos/widget/local_file_viewer.dart';
|
||||
|
@ -81,15 +80,13 @@ class _EnhancedPhotoBrowserState extends State<EnhancedPhotoBrowser>
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: BlocListener<ScanLocalDirBloc, ScanLocalDirBlocState>(
|
||||
return Scaffold(
|
||||
body: BlocListener<ScanLocalDirBloc, ScanLocalDirBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ScanLocalDirBloc, ScanLocalDirBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ScanLocalDirBloc, ScanLocalDirBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -159,20 +156,13 @@ class _EnhancedPhotoBrowserState extends State<EnhancedPhotoBrowser>
|
|||
children: [
|
||||
buildItemStreamListOuter(
|
||||
context,
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (state is ScanLocalDirBlocLoading || _buildItemQueue.isProcessing)
|
||||
|
|
|
@ -69,35 +69,35 @@ class _HomeState extends State<Home> with TickerProviderStateMixin {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
bottomNavigationBar: _buildBottomNavigationBar(context),
|
||||
body: Builder(builder: (context) => _buildContent(context)),
|
||||
extendBody: true,
|
||||
resizeToAvoidBottomInset: false,
|
||||
),
|
||||
return Scaffold(
|
||||
bottomNavigationBar: _buildBottomNavigationBar(context),
|
||||
body: Builder(builder: (context) => _buildContent(context)),
|
||||
extendBody: true,
|
||||
resizeToAvoidBottomInset: false,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBottomNavigationBar(BuildContext context) {
|
||||
return BottomNavigationBar(
|
||||
items: <BottomNavigationBarItem>[
|
||||
BottomNavigationBarItem(
|
||||
return NavigationBar(
|
||||
destinations: [
|
||||
NavigationDestination(
|
||||
icon: const Icon(Icons.photo_outlined),
|
||||
selectedIcon: const Icon(Icons.photo),
|
||||
label: L10n.global().photosTabLabel,
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
NavigationDestination(
|
||||
icon: const Icon(Icons.search),
|
||||
label: L10n.global().searchTooltip,
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
NavigationDestination(
|
||||
icon: const Icon(Icons.grid_view_outlined),
|
||||
selectedIcon: const Icon(Icons.grid_view_sharp),
|
||||
label: L10n.global().collectionsTooltip,
|
||||
),
|
||||
],
|
||||
currentIndex: _nextPage,
|
||||
onTap: _onTapNavItem,
|
||||
backgroundColor: Theme.of(context).bottomAppBarColor.withOpacity(.8),
|
||||
selectedIndex: _nextPage,
|
||||
onDestinationSelected: _onTapNavItem,
|
||||
backgroundColor: Theme.of(context).homeNavigationBarBackgroundColor,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import 'package:nc_photos/object_extension.dart';
|
|||
import 'package:nc_photos/platform/features.dart' as features;
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/remove_album.dart';
|
||||
import 'package:nc_photos/use_case/unimport_shared_album.dart';
|
||||
import 'package:nc_photos/widget/album_browser_util.dart' as album_browser_util;
|
||||
|
@ -115,35 +114,27 @@ class _HomeAlbumsState extends State<HomeAlbums>
|
|||
children: [
|
||||
buildItemStreamListOuter(
|
||||
context,
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
_onRefreshPressed();
|
||||
await _waitRefresh();
|
||||
},
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
sliver: buildItemStreamList(
|
||||
maxCrossAxisExtent: 256,
|
||||
mainAxisSpacing: 6,
|
||||
),
|
||||
),
|
||||
child: RefreshIndicator(
|
||||
backgroundColor: Colors.grey[100],
|
||||
onRefresh: () async {
|
||||
_onRefreshPressed();
|
||||
await _waitRefresh();
|
||||
},
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
sliver: buildItemStreamList(
|
||||
maxCrossAxisExtent: 256,
|
||||
mainAxisSpacing: 6,
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: _calcBottomAppBarExtent(context),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: _calcBottomAppBarExtent(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -499,7 +490,8 @@ class _HomeAlbumsState extends State<HomeAlbums>
|
|||
}
|
||||
}
|
||||
|
||||
double _calcBottomAppBarExtent(BuildContext context) => kToolbarHeight;
|
||||
double _calcBottomAppBarExtent(BuildContext context) =>
|
||||
NavigationBarTheme.of(context).height!;
|
||||
|
||||
late final _bloc = ListAlbumBloc.of(widget.account);
|
||||
late final _accountPrefUpdatedEventListener =
|
||||
|
@ -556,7 +548,7 @@ class _ButtonListItem extends _ListItem {
|
|||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: AppTheme.getListItemBackgroundColor(context),
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
|
@ -564,19 +556,18 @@ class _ButtonListItem extends _ListItem {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
color: AppTheme.getPrimaryTextColor(context),
|
||||
size: 24,
|
||||
),
|
||||
Icon(icon),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(label),
|
||||
child: Text(
|
||||
label,
|
||||
style: Theme.of(context).textTheme.labelLarge,
|
||||
),
|
||||
),
|
||||
if (isShowIndicator)
|
||||
const Icon(
|
||||
Icon(
|
||||
Icons.circle,
|
||||
color: Colors.red,
|
||||
color: Theme.of(context).colorScheme.tertiary,
|
||||
size: 8,
|
||||
),
|
||||
],
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:nc_photos/pref.dart';
|
|||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/url_launcher_util.dart';
|
||||
import 'package:nc_photos/widget/account_picker_dialog.dart';
|
||||
import 'package:nc_photos/widget/app_bar_title_container.dart';
|
||||
import 'package:nc_photos/widget/settings.dart';
|
||||
|
||||
/// AppBar for home screens
|
||||
|
@ -34,46 +35,18 @@ class HomeSliverAppBar extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Row(
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
if (account.scheme == "http")
|
||||
const Icon(
|
||||
Icons.no_encryption_outlined,
|
||||
color: Colors.orange,
|
||||
)
|
||||
else
|
||||
Icon(
|
||||
Icons.https,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
accountLabel ?? account.address,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
if (accountLabel == null)
|
||||
Text(
|
||||
account.username2,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
child: AppBarTitleContainer(
|
||||
title: Text(accountLabel ?? account.address),
|
||||
subtitle: accountLabel == null ? Text(account.username2) : null,
|
||||
icon: account.scheme == "http"
|
||||
? Icon(
|
||||
Icons.no_encryption_outlined,
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
)
|
||||
: Icon(
|
||||
Icons.https,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
floating: true,
|
||||
|
@ -81,18 +54,8 @@ class HomeSliverAppBar extends StatelessWidget {
|
|||
actions: (actions ?? []) +
|
||||
[
|
||||
if (!Pref().isFollowSystemThemeOr(false))
|
||||
Switch(
|
||||
value: Theme.of(context).brightness == Brightness.dark,
|
||||
_DarkModeSwitch(
|
||||
onChanged: _onDarkModeChanged,
|
||||
activeColor: AppTheme.getAppBarDarkModeSwitchColor(context),
|
||||
inactiveThumbColor:
|
||||
AppTheme.getAppBarDarkModeSwitchColor(context),
|
||||
activeTrackColor:
|
||||
AppTheme.getAppBarDarkModeSwitchTrackColor(context),
|
||||
activeThumbImage:
|
||||
const AssetImage("assets/ic_dark_mode_switch_24dp.png"),
|
||||
inactiveThumbImage:
|
||||
const AssetImage("assets/ic_dark_mode_switch_24dp.png"),
|
||||
),
|
||||
PopupMenuButton<int>(
|
||||
tooltip: MaterialLocalizations.of(context).moreButtonTooltip,
|
||||
|
@ -144,3 +107,26 @@ class HomeSliverAppBar extends StatelessWidget {
|
|||
static const _menuValueAbout = -1;
|
||||
static const _menuValueHelp = -2;
|
||||
}
|
||||
|
||||
class _DarkModeSwitch extends StatelessWidget {
|
||||
const _DarkModeSwitch({
|
||||
this.onChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Theme(
|
||||
data: buildDarkModeSwitchTheme(context),
|
||||
child: Switch(
|
||||
value: Theme.of(context).brightness == Brightness.dark,
|
||||
onChanged: onChanged,
|
||||
activeThumbImage:
|
||||
const AssetImage("assets/ic_dark_mode_switch_24dp.png"),
|
||||
inactiveThumbImage:
|
||||
const AssetImage("assets/ic_dark_mode_switch_24dp.png"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final ValueChanged<bool>? onChanged;
|
||||
}
|
||||
|
|
|
@ -155,56 +155,49 @@ class _HomePhotosState extends State<HomePhotos>
|
|||
children: [
|
||||
buildItemStreamListOuter(
|
||||
context,
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
child: DraggableScrollbar.semicircle(
|
||||
controller: _scrollController,
|
||||
overrideMaxScrollExtent: scrollExtent,
|
||||
// status bar + app bar
|
||||
topOffset: _calcAppBarExtent(context),
|
||||
bottomOffset: _calcBottomAppBarExtent(context),
|
||||
labelTextBuilder: (_) => _buildScrollLabel(context),
|
||||
labelPadding: const EdgeInsets.symmetric(horizontal: 40),
|
||||
enabled: _isScrollbarVisible,
|
||||
heightScrollThumb: 60,
|
||||
child: ScrollConfiguration(
|
||||
behavior: ScrollConfiguration.of(context)
|
||||
.copyWith(scrollbars: false),
|
||||
child: RefreshIndicator(
|
||||
backgroundColor: Colors.grey[100],
|
||||
onRefresh: () async {
|
||||
_onRefreshSelected();
|
||||
await _waitRefresh();
|
||||
},
|
||||
child: CustomScrollView(
|
||||
controller: _scrollController,
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
_web?.buildContent(context),
|
||||
if (AccountPref.of(widget.account)
|
||||
.isEnableMemoryAlbumOr(true) &&
|
||||
_smartAlbums.isNotEmpty)
|
||||
_buildSmartAlbumList(context),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
onMaxExtentChanged: (value) {
|
||||
setState(() {
|
||||
_itemListMaxExtent = value;
|
||||
});
|
||||
},
|
||||
isEnableVisibilityCallback: true,
|
||||
child: DraggableScrollbar.semicircle(
|
||||
controller: _scrollController,
|
||||
overrideMaxScrollExtent: scrollExtent,
|
||||
// status bar + app bar
|
||||
topOffset: _calcAppBarExtent(context),
|
||||
bottomOffset: _calcBottomAppBarExtent(context),
|
||||
labelTextBuilder: (_) => _buildScrollLabel(context),
|
||||
labelPadding: const EdgeInsets.symmetric(horizontal: 40),
|
||||
backgroundColor: Theme.of(context).colorScheme.inverseSurface,
|
||||
enabled: _isScrollbarVisible,
|
||||
heightScrollThumb: 60,
|
||||
child: ScrollConfiguration(
|
||||
behavior:
|
||||
ScrollConfiguration.of(context).copyWith(scrollbars: false),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
_onRefreshSelected();
|
||||
await _waitRefresh();
|
||||
},
|
||||
child: CustomScrollView(
|
||||
controller: _scrollController,
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
_web?.buildContent(context),
|
||||
if (AccountPref.of(widget.account)
|
||||
.isEnableMemoryAlbumOr(true) &&
|
||||
_smartAlbums.isNotEmpty)
|
||||
_buildSmartAlbumList(context),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
onMaxExtentChanged: (value) {
|
||||
setState(() {
|
||||
_itemListMaxExtent = value;
|
||||
});
|
||||
},
|
||||
isEnableVisibilityCallback: true,
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: _calcBottomAppBarExtent(context),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: _calcBottomAppBarExtent(context),
|
||||
),
|
||||
),
|
||||
].whereType<Widget>().toList(),
|
||||
),
|
||||
),
|
||||
].whereType<Widget>().toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -368,10 +361,10 @@ class _HomePhotosState extends State<HomePhotos>
|
|||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Text(
|
||||
text,
|
||||
style: const TextStyle(
|
||||
color: AppTheme.primaryTextColorLight,
|
||||
fontSize: 16,
|
||||
),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
.copyWith(color: Theme.of(context).colorScheme.onInverseSurface),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
|
@ -684,7 +677,8 @@ class _HomePhotosState extends State<HomePhotos>
|
|||
double _calcAppBarExtent(BuildContext context) =>
|
||||
MediaQuery.of(context).padding.top + kToolbarHeight;
|
||||
|
||||
double _calcBottomAppBarExtent(BuildContext context) => kToolbarHeight;
|
||||
double _calcBottomAppBarExtent(BuildContext context) =>
|
||||
NavigationBarTheme.of(context).height!;
|
||||
|
||||
Primitive<bool> get _hasFiredMetadataTask {
|
||||
final name = bloc_util.getInstNameForRootAwareAccount(
|
||||
|
@ -1025,7 +1019,9 @@ class _SmartAlbumItem extends StatelessWidget {
|
|||
padding: const EdgeInsets.all(4),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(color: AppTheme.primaryTextColorDark),
|
||||
style: Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||
color: Theme.of(context).onDarkSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -74,14 +74,7 @@ class _HomeSearchState extends State<HomeSearch>
|
|||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<SearchBloc, SearchBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
child: _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -330,7 +323,7 @@ class _HomeSearchState extends State<HomeSearch>
|
|||
return Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: ColoredBox(
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
child: SingleChildScrollView(
|
||||
child: HomeSearchSuggestion(
|
||||
account: widget.account,
|
||||
|
@ -559,7 +552,8 @@ class _HomeSearchState extends State<HomeSearch>
|
|||
}
|
||||
}
|
||||
|
||||
double _calcBottomAppBarExtent(BuildContext context) => kToolbarHeight;
|
||||
double _calcBottomAppBarExtent(BuildContext context) =>
|
||||
NavigationBarTheme.of(context).height!;
|
||||
|
||||
bool _isShowLanding(SearchBlocState state) => state is SearchBlocInit;
|
||||
|
||||
|
@ -648,21 +642,18 @@ class _FilterBubbleList extends StatelessWidget {
|
|||
}
|
||||
|
||||
Widget _buildBubble(BuildContext context, String label) {
|
||||
return Container(
|
||||
height: 28,
|
||||
decoration: BoxDecoration(
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(14)),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppTheme.getPrimaryTextColorInverse(context),
|
||||
),
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: FilterChip(
|
||||
elevation: 1,
|
||||
pressElevation: 1,
|
||||
showCheckmark: false,
|
||||
visualDensity: VisualDensity.compact,
|
||||
selected: true,
|
||||
selectedColor:
|
||||
Theme.of(context).elevate(Theme.of(context).colorScheme.surface, 5),
|
||||
label: Text(label),
|
||||
onSelected: (_) {},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -807,7 +798,7 @@ class _FilterDropdownState<T> extends State<_FilterDropdown<T>> {
|
|||
child: Text(
|
||||
widget.label,
|
||||
style: TextStyle(
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -9,8 +9,8 @@ import 'package:nc_photos/entity/person.dart';
|
|||
import 'package:nc_photos/entity/tag.dart';
|
||||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/object_extension.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/list_location_group.dart';
|
||||
import 'package:nc_photos/widget/album_browser_util.dart' as album_browser_util;
|
||||
import 'package:nc_photos/widget/page_visibility_mixin.dart';
|
||||
|
@ -58,11 +58,14 @@ class _HomeSearchSuggestionState extends State<HomeSearchSuggestion>
|
|||
BlocBuilder<HomeSearchSuggestionBloc, HomeSearchSuggestionBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
data: Theme.of(context).run((t) {
|
||||
return t.copyWith(
|
||||
listTileTheme: ListTileThemeData(
|
||||
iconColor: t.colorScheme.onBackground,
|
||||
textColor: t.colorScheme.onBackground,
|
||||
),
|
||||
);
|
||||
}),
|
||||
child: _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -12,6 +12,7 @@ import 'package:nc_photos/di_container.dart';
|
|||
import 'package:nc_photos/entity/file_descriptor.dart';
|
||||
import 'package:nc_photos/help_utils.dart' as help_util;
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/material3.dart';
|
||||
import 'package:nc_photos/object_extension.dart';
|
||||
import 'package:nc_photos/pixel_image_provider.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
|
@ -84,7 +85,8 @@ class _ImageEditorState extends State<ImageEditor> {
|
|||
}
|
||||
|
||||
@override
|
||||
build(BuildContext context) => AppTheme(
|
||||
build(BuildContext context) => Theme(
|
||||
data: buildDarkTheme(),
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: _buildContent,
|
||||
|
@ -184,8 +186,7 @@ class _ImageEditorState extends State<ImageEditor> {
|
|||
|
||||
Widget _buildAppBar(BuildContext context) => AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
foregroundColor: Colors.white.withOpacity(.87),
|
||||
elevation: 0,
|
||||
leading: BackButton(onPressed: () => _onBackButton(context)),
|
||||
title: Text(L10n.global().imageEditTitle),
|
||||
actions: [
|
||||
|
@ -359,7 +360,9 @@ class _ToolButton extends StatelessWidget {
|
|||
onTap: onPressed,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected ? Colors.white24 : null,
|
||||
color: isSelected
|
||||
? Theme.of(context).colorScheme.secondaryContainer
|
||||
: null,
|
||||
// borderRadius: const BorderRadius.all(Radius.circular(24)),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
|
@ -370,8 +373,8 @@ class _ToolButton extends StatelessWidget {
|
|||
Icon(
|
||||
icon,
|
||||
color: isSelected
|
||||
? Colors.white
|
||||
: AppTheme.unfocusedIconColorDark,
|
||||
? Theme.of(context).colorScheme.onSecondaryContainer
|
||||
: M3.of(context).filterChip.disabled.labelText,
|
||||
size: 18,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
|
@ -379,8 +382,8 @@ class _ToolButton extends StatelessWidget {
|
|||
label,
|
||||
style: TextStyle(
|
||||
color: isSelected
|
||||
? Colors.white
|
||||
: AppTheme.unfocusedIconColorDark,
|
||||
? Theme.of(context).colorScheme.onSecondaryContainer
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -3,7 +3,6 @@ import 'package:nc_photos/app_localizations.dart';
|
|||
import 'package:nc_photos/double_extension.dart';
|
||||
import 'package:nc_photos/iterable_extension.dart';
|
||||
import 'package:nc_photos/object_extension.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/widget/image_editor/toolbar_button.dart';
|
||||
import 'package:nc_photos/widget/stateful_slider.dart';
|
||||
import 'package:nc_photos_plugin/nc_photos_plugin.dart';
|
||||
|
@ -186,41 +185,39 @@ class _ColorToolbarState extends State<ColorToolbar> {
|
|||
required double initialValue,
|
||||
ValueChanged<double>? onChangeEnd,
|
||||
}) {
|
||||
return AppTheme.dark(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Stack(
|
||||
children: [
|
||||
Align(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: Text(min.toStringAsFixedTruncated(1)),
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Stack(
|
||||
children: [
|
||||
Align(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: Text(min.toStringAsFixedTruncated(1)),
|
||||
),
|
||||
if (min < 0 && max > 0)
|
||||
const Align(
|
||||
alignment: AlignmentDirectional.center,
|
||||
child: Text("0"),
|
||||
),
|
||||
if (min < 0 && max > 0)
|
||||
const Align(
|
||||
alignment: AlignmentDirectional.center,
|
||||
child: Text("0"),
|
||||
),
|
||||
Align(
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
child: Text(max.toStringAsFixedTruncated(1)),
|
||||
),
|
||||
],
|
||||
),
|
||||
Align(
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
child: Text(max.toStringAsFixedTruncated(1)),
|
||||
),
|
||||
],
|
||||
),
|
||||
StatefulSlider(
|
||||
key: key,
|
||||
initialValue: initialValue.toDouble(),
|
||||
min: min.toDouble(),
|
||||
max: max.toDouble(),
|
||||
onChangeEnd: onChangeEnd,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
StatefulSlider(
|
||||
key: key,
|
||||
initialValue: initialValue.toDouble(),
|
||||
min: min.toDouble(),
|
||||
max: max.toDouble(),
|
||||
onChangeEnd: onChangeEnd,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/material3.dart';
|
||||
|
||||
/// Button in the image editor toolbar
|
||||
///
|
||||
|
@ -19,9 +19,19 @@ class ToolbarButton extends StatelessWidget {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
final color = !isSelected && isActivated
|
||||
? Colors.white12
|
||||
: AppTheme.primarySwatchDark[500]!.withOpacity(0.7);
|
||||
final Color backgroundColor, foregroundColor;
|
||||
if (isSelected) {
|
||||
backgroundColor = Theme.of(context).colorScheme.secondaryContainer;
|
||||
foregroundColor = Theme.of(context).colorScheme.onSecondaryContainer;
|
||||
} else {
|
||||
if (isActivated) {
|
||||
backgroundColor = M3.of(context).filterChip.disabled.containerSelected;
|
||||
foregroundColor = Theme.of(context).colorScheme.onSurface;
|
||||
} else {
|
||||
backgroundColor = Theme.of(context).colorScheme.secondaryContainer;
|
||||
foregroundColor = M3.of(context).filterChip.disabled.labelText;
|
||||
}
|
||||
}
|
||||
return InkWell(
|
||||
onTap: onPressed,
|
||||
child: Padding(
|
||||
|
@ -41,7 +51,7 @@ class ToolbarButton extends StatelessWidget {
|
|||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(32),
|
||||
color: color,
|
||||
color: backgroundColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -49,9 +59,7 @@ class ToolbarButton extends StatelessWidget {
|
|||
child: Icon(
|
||||
icon,
|
||||
size: 32,
|
||||
color: isSelected
|
||||
? Colors.white
|
||||
: AppTheme.unfocusedIconColorDark,
|
||||
color: foregroundColor,
|
||||
),
|
||||
),
|
||||
if (isActivated && activationOrder! >= 0)
|
||||
|
@ -63,9 +71,7 @@ class ToolbarButton extends StatelessWidget {
|
|||
(activationOrder! + 1).toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: isSelected
|
||||
? Colors.white
|
||||
: AppTheme.unfocusedIconColorDark,
|
||||
color: foregroundColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -79,8 +85,9 @@ class ToolbarButton extends StatelessWidget {
|
|||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color:
|
||||
isSelected ? Colors.white : AppTheme.unfocusedIconColorDark,
|
||||
color: isSelected
|
||||
? Theme.of(context).colorScheme.onSurface
|
||||
: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/widget/image_editor/toolbar_button.dart';
|
||||
import 'package:nc_photos_plugin/nc_photos_plugin.dart';
|
||||
|
||||
|
@ -263,7 +262,7 @@ class _OrientationButton extends StatelessWidget {
|
|||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
? AppTheme.primarySwatchDark[500]!.withOpacity(0.7)
|
||||
? Theme.of(context).colorScheme.secondaryContainer
|
||||
: null,
|
||||
// borderRadius: const BorderRadius.all(Radius.circular(24)),
|
||||
),
|
||||
|
@ -274,8 +273,8 @@ class _OrientationButton extends StatelessWidget {
|
|||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isSelected
|
||||
? Colors.white
|
||||
: AppTheme.unfocusedIconColorDark,
|
||||
? Theme.of(context).colorScheme.onSecondaryContainer
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -82,7 +82,8 @@ class _ImageEnhancerState extends State<ImageEnhancer> {
|
|||
}
|
||||
|
||||
@override
|
||||
build(BuildContext context) => AppTheme.dark(
|
||||
build(BuildContext context) => Theme(
|
||||
data: buildDarkTheme(),
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: _buildContent,
|
||||
|
@ -131,8 +132,7 @@ class _ImageEnhancerState extends State<ImageEnhancer> {
|
|||
|
||||
Widget _buildAppBar(BuildContext context) => AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
foregroundColor: Colors.white.withOpacity(.87),
|
||||
elevation: 0,
|
||||
title: Text(L10n.global().enhanceTooltip),
|
||||
actions: [
|
||||
TextButton(
|
||||
|
@ -361,47 +361,39 @@ class _ImageEnhancerState extends State<ImageEnhancer> {
|
|||
var current = .8;
|
||||
final iteration = await showDialog<int>(
|
||||
context: context,
|
||||
builder: (context) => AppTheme(
|
||||
child: AlertDialog(
|
||||
title: Text(L10n.global().enhanceLowLightParamBrightnessLabel),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.brightness_low,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(L10n.global().enhanceLowLightParamBrightnessLabel),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
const Icon(Icons.brightness_low),
|
||||
Expanded(
|
||||
child: StatefulSlider(
|
||||
initialValue: current,
|
||||
onChangeEnd: (value) {
|
||||
current = value;
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: StatefulSlider(
|
||||
initialValue: current,
|
||||
onChangeEnd: (value) {
|
||||
current = value;
|
||||
},
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.brightness_high,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
final iteration = (current * 10).round().clamp(1, 10);
|
||||
Navigator.of(context).pop(iteration);
|
||||
},
|
||||
child: Text(L10n.global().enhanceButtonLabel),
|
||||
),
|
||||
const Icon(Icons.brightness_high),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
final iteration = (current * 10).round().clamp(1, 10);
|
||||
Navigator.of(context).pop(iteration);
|
||||
},
|
||||
child: Text(L10n.global().enhanceButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
_log.info("[_getZeroDceArgs] iteration: $iteration");
|
||||
|
@ -413,48 +405,39 @@ class _ImageEnhancerState extends State<ImageEnhancer> {
|
|||
var current = .5;
|
||||
final radius = await showDialog<int>(
|
||||
context: context,
|
||||
builder: (context) => AppTheme(
|
||||
child: AlertDialog(
|
||||
title: Text(L10n.global().enhancePortraitBlurParamBlurLabel),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.circle,
|
||||
size: 20,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(L10n.global().enhancePortraitBlurParamBlurLabel),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
const Icon(Icons.circle, size: 20),
|
||||
Expanded(
|
||||
child: StatefulSlider(
|
||||
initialValue: current,
|
||||
onChangeEnd: (value) {
|
||||
current = value;
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: StatefulSlider(
|
||||
initialValue: current,
|
||||
onChangeEnd: (value) {
|
||||
current = value;
|
||||
},
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.blur_on,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
final radius = (current * 25).round().clamp(1, 25);
|
||||
Navigator.of(context).pop(radius);
|
||||
},
|
||||
child: Text(L10n.global().enhanceButtonLabel),
|
||||
),
|
||||
const Icon(Icons.blur_on),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
final radius = (current * 25).round().clamp(1, 25);
|
||||
Navigator.of(context).pop(radius);
|
||||
},
|
||||
child: Text(L10n.global().enhanceButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
_log.info("[_getDeepLab3PortraitArgs] radius: $radius");
|
||||
|
@ -483,47 +466,38 @@ class _ImageEnhancerState extends State<ImageEnhancer> {
|
|||
var current = 1.0;
|
||||
final weight = await showDialog<double>(
|
||||
context: context,
|
||||
builder: (context) => AppTheme(
|
||||
child: AlertDialog(
|
||||
title: Text(L10n.global().enhanceGenericParamWeightLabel),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.water_drop,
|
||||
size: 20,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(L10n.global().enhanceGenericParamWeightLabel),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
const Icon(Icons.water_drop, size: 20),
|
||||
Expanded(
|
||||
child: StatefulSlider(
|
||||
initialValue: current,
|
||||
onChangeEnd: (value) {
|
||||
current = value;
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: StatefulSlider(
|
||||
initialValue: current,
|
||||
onChangeEnd: (value) {
|
||||
current = value;
|
||||
},
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.water_drop_outlined,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(current);
|
||||
},
|
||||
child: Text(L10n.global().enhanceButtonLabel),
|
||||
),
|
||||
const Icon(Icons.water_drop_outlined),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(current);
|
||||
},
|
||||
child: Text(L10n.global().enhanceButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
_log.info("[_getDeepLab3ColorPopArgs] weight: $weight");
|
||||
|
@ -635,14 +609,17 @@ class _ListChild extends StatelessWidget {
|
|||
child: InkWell(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
color: isSelected ? Colors.white24 : null,
|
||||
color: isSelected
|
||||
? Theme.of(context).colorScheme.secondaryContainer
|
||||
: null,
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
color:
|
||||
isSelected ? Colors.white : AppTheme.unfocusedIconColorDark,
|
||||
color: isSelected
|
||||
? Theme.of(context).colorScheme.onSecondaryContainer
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -889,106 +866,95 @@ class _StylePicker extends StatefulWidget {
|
|||
class _StylePickerState extends State<_StylePicker> {
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: AlertDialog(
|
||||
title: Text(L10n.global().enhanceStyleTransferStyleDialogTitle),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (_selected != null) ...[
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: SizedBox(
|
||||
width: 128,
|
||||
height: 128,
|
||||
child: Image(
|
||||
return AlertDialog(
|
||||
title: Text(L10n.global().enhanceStyleTransferStyleDialogTitle),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (_selected != null) ...[
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: SizedBox(
|
||||
width: 128,
|
||||
height: 128,
|
||||
child: Image(
|
||||
image: ResizeImage.resizeIfNeeded(
|
||||
128, null, ContentUriImage(_getSelectedUri())),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
Wrap(
|
||||
runSpacing: 8,
|
||||
spacing: 8,
|
||||
children: [
|
||||
..._bundledStyles.mapIndexed((i, e) => _buildItem(
|
||||
i,
|
||||
Image(
|
||||
image: ResizeImage.resizeIfNeeded(
|
||||
_thumbSize, null, ContentUriImage(e)),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
)),
|
||||
if (_customUri != null)
|
||||
_buildItem(
|
||||
_bundledStyles.length,
|
||||
Image(
|
||||
image: ResizeImage.resizeIfNeeded(
|
||||
128, null, ContentUriImage(_getSelectedUri())),
|
||||
_thumbSize, null, ContentUriImage(_customUri!)),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: _onCustomTap,
|
||||
child: SizedBox(
|
||||
width: _thumbSize.toDouble(),
|
||||
height: _thumbSize.toDouble(),
|
||||
child: const Icon(Icons.file_open_outlined),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
Wrap(
|
||||
runSpacing: 8,
|
||||
spacing: 8,
|
||||
children: [
|
||||
..._bundledStyles.mapIndexed((i, e) => _buildItem(
|
||||
i,
|
||||
Image(
|
||||
image: ResizeImage.resizeIfNeeded(
|
||||
_thumbSize, null, ContentUriImage(e)),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
)),
|
||||
if (_customUri != null)
|
||||
_buildItem(
|
||||
_bundledStyles.length,
|
||||
Image(
|
||||
image: ResizeImage.resizeIfNeeded(
|
||||
_thumbSize, null, ContentUriImage(_customUri!)),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: _onCustomTap,
|
||||
child: SizedBox(
|
||||
width: _thumbSize.toDouble(),
|
||||
height: _thumbSize.toDouble(),
|
||||
child: const Icon(
|
||||
Icons.file_open_outlined,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
const Icon(Icons.auto_fix_normal),
|
||||
Expanded(
|
||||
child: StatefulSlider(
|
||||
initialValue: _weight,
|
||||
min: .01,
|
||||
onChangeEnd: (value) {
|
||||
_weight = value;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.auto_fix_normal,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
Expanded(
|
||||
child: StatefulSlider(
|
||||
initialValue: _weight,
|
||||
min: .01,
|
||||
onChangeEnd: (value) {
|
||||
_weight = value;
|
||||
},
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.auto_fix_high,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
if (_selected == null) {
|
||||
SnackBarManager().showSnackBar(SnackBar(
|
||||
content: Text(L10n.global()
|
||||
.enhanceStyleTransferNoStyleSelectedNotification),
|
||||
duration: k.snackBarDurationNormal,
|
||||
));
|
||||
} else {
|
||||
final result = _StylePickerResult(_getSelectedUri(), _weight);
|
||||
Navigator.of(context).pop(result);
|
||||
}
|
||||
},
|
||||
child: Text(L10n.global().enhanceButtonLabel),
|
||||
),
|
||||
const Icon(Icons.auto_fix_high),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
if (_selected == null) {
|
||||
SnackBarManager().showSnackBar(SnackBar(
|
||||
content: Text(L10n.global()
|
||||
.enhanceStyleTransferNoStyleSelectedNotification),
|
||||
duration: k.snackBarDurationNormal,
|
||||
));
|
||||
} else {
|
||||
final result = _StylePickerResult(_getSelectedUri(), _weight);
|
||||
Navigator.of(context).pop(result);
|
||||
}
|
||||
},
|
||||
child: Text(L10n.global().enhanceButtonLabel),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,8 @@ class LocalFileViewer extends StatefulWidget {
|
|||
class _LocalFileViewerState extends State<LocalFileViewer> {
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
return Theme(
|
||||
data: buildDarkTheme(),
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: _buildContent,
|
||||
|
@ -108,8 +109,7 @@ class _LocalFileViewerState extends State<LocalFileViewer> {
|
|||
),
|
||||
AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
foregroundColor: Colors.white.withOpacity(.87),
|
||||
elevation: 0,
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.share),
|
||||
|
|
|
@ -82,8 +82,8 @@ class _MyAppState extends State<MyApp>
|
|||
}
|
||||
return MaterialApp(
|
||||
onGenerateTitle: (context) => AppLocalizations.of(context)!.appTitle,
|
||||
theme: AppTheme.buildLightThemeData(),
|
||||
darkTheme: AppTheme.buildDarkThemeData(),
|
||||
theme: buildLightTheme(),
|
||||
darkTheme: buildDarkTheme(),
|
||||
themeMode: themeMode,
|
||||
initialRoute: Splash.routeName,
|
||||
onGenerateRoute: _onGenerateRoute,
|
||||
|
|
|
@ -58,15 +58,13 @@ class _PeopleBrowserState extends State<PeopleBrowser> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: BlocListener<ListPersonBloc, ListPersonBlocState>(
|
||||
return Scaffold(
|
||||
body: BlocListener<ListPersonBloc, ListPersonBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListPersonBloc, ListPersonBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListPersonBloc, ListPersonBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -89,32 +87,25 @@ class _PeopleBrowserState extends State<PeopleBrowser> {
|
|||
Widget _buildContent(BuildContext context, ListPersonBlocState state) {
|
||||
return Stack(
|
||||
children: [
|
||||
Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
if (state is ListPersonBlocLoading)
|
||||
const SliverToBoxAdapter(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: LinearProgressIndicator(),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
if (state is ListPersonBlocLoading)
|
||||
const SliverToBoxAdapter(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: LinearProgressIndicator(),
|
||||
),
|
||||
),
|
||||
SliverStaggeredGrid.extentBuilder(
|
||||
maxCrossAxisExtent: 160,
|
||||
mainAxisSpacing: 2,
|
||||
crossAxisSpacing: 2,
|
||||
itemCount: _items.length,
|
||||
itemBuilder: _buildItem,
|
||||
staggeredTileBuilder: (_) => const StaggeredTile.count(1, 1),
|
||||
),
|
||||
],
|
||||
),
|
||||
SliverStaggeredGrid.extentBuilder(
|
||||
maxCrossAxisExtent: 160,
|
||||
mainAxisSpacing: 2,
|
||||
crossAxisSpacing: 2,
|
||||
itemCount: _items.length,
|
||||
itemBuilder: _buildItem,
|
||||
staggeredTileBuilder: (_) => const StaggeredTile.count(1, 1),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
@ -213,9 +204,9 @@ class _PersonListItem extends _ListItem {
|
|||
account: account,
|
||||
label: name,
|
||||
coverUrl: faceUrl,
|
||||
fallbackBuilder: (_) => Icon(
|
||||
fallbackBuilder: (context) => Icon(
|
||||
Icons.person,
|
||||
color: Colors.white.withOpacity(.8),
|
||||
color: Theme.of(context).listPlaceholderForegroundColor,
|
||||
),
|
||||
onTap: onTap,
|
||||
);
|
||||
|
|
|
@ -29,6 +29,7 @@ import 'package:nc_photos/share_handler.dart';
|
|||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/throttler.dart';
|
||||
import 'package:nc_photos/widget/app_bar_title_container.dart';
|
||||
import 'package:nc_photos/widget/builder/photo_list_item_builder.dart';
|
||||
import 'package:nc_photos/widget/handler/add_selection_to_album_handler.dart';
|
||||
import 'package:nc_photos/widget/handler/archive_selection_handler.dart';
|
||||
|
@ -103,15 +104,13 @@ class _PersonBrowserState extends State<PersonBrowser>
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: BlocListener<ListFaceFileBloc, ListFaceFileBlocState>(
|
||||
return Scaffold(
|
||||
body: BlocListener<ListFaceFileBloc, ListFaceFileBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListFaceFileBloc, ListFaceFileBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListFaceFileBloc, ListFaceFileBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -137,28 +136,20 @@ class _PersonBrowserState extends State<PersonBrowser>
|
|||
Widget _buildContent(BuildContext context, ListFaceFileBlocState state) {
|
||||
return buildItemStreamListOuter(
|
||||
context,
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context, state),
|
||||
if (state is ListFaceFileBlocLoading || _buildItemQueue.isProcessing)
|
||||
const SliverToBoxAdapter(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: LinearProgressIndicator(),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context, state),
|
||||
if (state is ListFaceFileBlocLoading ||
|
||||
_buildItemQueue.isProcessing)
|
||||
const SliverToBoxAdapter(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: LinearProgressIndicator(),
|
||||
),
|
||||
),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -175,43 +166,12 @@ class _PersonBrowserState extends State<PersonBrowser>
|
|||
return SliverAppBar(
|
||||
floating: true,
|
||||
titleSpacing: 0,
|
||||
title: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 40,
|
||||
width: 40,
|
||||
child: _buildFaceImage(context),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
widget.person.name,
|
||||
style: TextStyle(
|
||||
color: AppTheme.getPrimaryTextColor(context),
|
||||
),
|
||||
maxLines: 1,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.clip,
|
||||
),
|
||||
if (state is! ListFaceFileBlocLoading &&
|
||||
!_buildItemQueue.isProcessing)
|
||||
Text(
|
||||
L10n.global().personPhotoCountText(_backingFiles.length),
|
||||
style: TextStyle(
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
title: AppBarTitleContainer(
|
||||
icon: _buildFaceImage(context),
|
||||
title: Text(widget.person.name),
|
||||
subtitle:
|
||||
Text(L10n.global().personPhotoCountText(_backingFiles.length)),
|
||||
),
|
||||
// ),
|
||||
actions: [
|
||||
ZoomMenuButton(
|
||||
initialZoom: _thumbZoomLevel,
|
||||
|
@ -254,7 +214,7 @@ class _PersonBrowserState extends State<PersonBrowser>
|
|||
} catch (_) {
|
||||
cover = Icon(
|
||||
Icons.person,
|
||||
color: Colors.white.withOpacity(.8),
|
||||
color: Theme.of(context).listPlaceholderForegroundColor,
|
||||
size: 24,
|
||||
);
|
||||
}
|
||||
|
@ -262,7 +222,7 @@ class _PersonBrowserState extends State<PersonBrowser>
|
|||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(64),
|
||||
child: Container(
|
||||
color: AppTheme.getListItemBackgroundColor(context),
|
||||
color: Theme.of(context).listPlaceholderBackgroundColor,
|
||||
constraints: const BoxConstraints.expand(),
|
||||
child: cover,
|
||||
),
|
||||
|
|
|
@ -171,7 +171,7 @@ class PhotoListLocalImageItem extends PhotoListLocalFileItem {
|
|||
Container(
|
||||
// arbitrary size here
|
||||
constraints: BoxConstraints.tight(const Size(128, 128)),
|
||||
color: AppTheme.getListItemBackgroundColor(context),
|
||||
color: Theme.of(context).listPlaceholderBackgroundColor,
|
||||
child: Image(
|
||||
image: ResizeImage.resizeIfNeeded(
|
||||
k.photoThumbSize, null, provider),
|
||||
|
@ -182,7 +182,7 @@ class PhotoListLocalImageItem extends PhotoListLocalFileItem {
|
|||
child: Icon(
|
||||
Icons.image_not_supported,
|
||||
size: 64,
|
||||
color: Colors.white.withOpacity(.8),
|
||||
color: Theme.of(context).listPlaceholderForegroundColor,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -223,7 +223,7 @@ class PhotoListImage extends StatelessWidget {
|
|||
child: Icon(
|
||||
Icons.image_not_supported,
|
||||
size: 64,
|
||||
color: Colors.white.withOpacity(.8),
|
||||
color: Theme.of(context).listPlaceholderForegroundColor,
|
||||
),
|
||||
);
|
||||
Widget child;
|
||||
|
@ -263,7 +263,7 @@ class PhotoListImage extends StatelessWidget {
|
|||
Container(
|
||||
// arbitrary size here
|
||||
constraints: BoxConstraints.tight(const Size(128, 128)),
|
||||
color: AppTheme.getListItemBackgroundColor(context),
|
||||
color: Theme.of(context).listPlaceholderBackgroundColor,
|
||||
child: child,
|
||||
),
|
||||
if (isGif)
|
||||
|
@ -325,7 +325,7 @@ class PhotoListVideo extends StatelessWidget {
|
|||
Container(
|
||||
// arbitrary size here
|
||||
constraints: BoxConstraints.tight(const Size(128, 128)),
|
||||
color: AppTheme.getListItemBackgroundColor(context),
|
||||
color: Theme.of(context).listPlaceholderBackgroundColor,
|
||||
child: CachedNetworkImage(
|
||||
cacheManager: ThumbnailCacheManager.inst,
|
||||
imageUrl: previewUrl,
|
||||
|
@ -341,7 +341,7 @@ class PhotoListVideo extends StatelessWidget {
|
|||
child: Icon(
|
||||
Icons.image_not_supported,
|
||||
size: 64,
|
||||
color: Colors.white.withOpacity(.8),
|
||||
color: Theme.of(context).listPlaceholderForegroundColor,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -458,10 +458,7 @@ class PhotoListDate extends StatelessWidget {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
subtitle,
|
||||
style: Theme.of(context).textTheme.caption!.copyWith(
|
||||
color: AppTheme.getPrimaryTextColor(context),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -20,8 +20,8 @@ import 'package:nc_photos/object_extension.dart';
|
|||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/share_handler.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/widget/about_geocoding_dialog.dart';
|
||||
import 'package:nc_photos/widget/app_bar_title_container.dart';
|
||||
import 'package:nc_photos/widget/builder/photo_list_item_builder.dart';
|
||||
import 'package:nc_photos/widget/handler/add_selection_to_album_handler.dart';
|
||||
import 'package:nc_photos/widget/handler/archive_selection_handler.dart';
|
||||
|
@ -91,15 +91,13 @@ class _PlaceBrowserState extends State<PlaceBrowser>
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: BlocListener<ListLocationFileBloc, ListLocationFileBlocState>(
|
||||
return Scaffold(
|
||||
body: BlocListener<ListLocationFileBloc, ListLocationFileBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListLocationFileBloc, ListLocationFileBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListLocationFileBloc, ListLocationFileBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -125,28 +123,21 @@ class _PlaceBrowserState extends State<PlaceBrowser>
|
|||
Widget _buildContent(BuildContext context, ListLocationFileBlocState state) {
|
||||
return buildItemStreamListOuter(
|
||||
context,
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context, state),
|
||||
if (state is ListLocationFileBlocLoading ||
|
||||
_buildItemQueue.isProcessing)
|
||||
const SliverToBoxAdapter(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: LinearProgressIndicator(),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context, state),
|
||||
if (state is ListLocationFileBlocLoading ||
|
||||
_buildItemQueue.isProcessing)
|
||||
const SliverToBoxAdapter(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: LinearProgressIndicator(),
|
||||
),
|
||||
),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -164,29 +155,14 @@ class _PlaceBrowserState extends State<PlaceBrowser>
|
|||
return SliverAppBar(
|
||||
floating: true,
|
||||
titleSpacing: 0,
|
||||
title: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
widget.place ?? location_util.alpha2CodeToName(widget.countryCode)!,
|
||||
style: TextStyle(
|
||||
color: AppTheme.getPrimaryTextColor(context),
|
||||
),
|
||||
maxLines: 1,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.clip,
|
||||
),
|
||||
if (state is! ListLocationFileBlocLoading &&
|
||||
!_buildItemQueue.isProcessing)
|
||||
Text(
|
||||
L10n.global().personPhotoCountText(_backingFiles.length),
|
||||
style: TextStyle(
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
title: AppBarTitleContainer(
|
||||
title: Text(
|
||||
widget.place ?? location_util.alpha2CodeToName(widget.countryCode)!,
|
||||
),
|
||||
subtitle: (state is! ListLocationFileBlocLoading &&
|
||||
!_buildItemQueue.isProcessing)
|
||||
? Text(L10n.global().personPhotoCountText(_backingFiles.length))
|
||||
: null,
|
||||
),
|
||||
actions: [
|
||||
ZoomMenuButton(
|
||||
|
|
|
@ -63,15 +63,13 @@ class _PlacesBrowserState extends State<PlacesBrowser> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: BlocListener<ListLocationBloc, ListLocationBlocState>(
|
||||
return Scaffold(
|
||||
body: BlocListener<ListLocationBloc, ListLocationBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListLocationBloc, ListLocationBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListLocationBloc, ListLocationBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -94,49 +92,41 @@ class _PlacesBrowserState extends State<PlacesBrowser> {
|
|||
Widget _buildContent(BuildContext context, ListLocationBlocState state) {
|
||||
return Stack(
|
||||
children: [
|
||||
Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
if (state is ListLocationBlocLoading)
|
||||
const SliverToBoxAdapter(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: LinearProgressIndicator(),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: 48,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
itemCount: _countryItems.length,
|
||||
itemBuilder: (context, i) =>
|
||||
_countryItems[i].buildWidget(context),
|
||||
separatorBuilder: (_, __) => const SizedBox(width: 8),
|
||||
),
|
||||
),
|
||||
),
|
||||
CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
if (state is ListLocationBlocLoading)
|
||||
const SliverToBoxAdapter(
|
||||
child: SizedBox(height: 8),
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: LinearProgressIndicator(),
|
||||
),
|
||||
),
|
||||
SliverStaggeredGrid.extentBuilder(
|
||||
maxCrossAxisExtent: 160,
|
||||
mainAxisSpacing: 2,
|
||||
crossAxisSpacing: 2,
|
||||
itemCount: _placeItems.length,
|
||||
itemBuilder: (context, i) =>
|
||||
_placeItems[i].buildWidget(context),
|
||||
staggeredTileBuilder: (_) => const StaggeredTile.count(1, 1),
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: 48,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
itemCount: _countryItems.length,
|
||||
itemBuilder: (context, i) =>
|
||||
_countryItems[i].buildWidget(context),
|
||||
separatorBuilder: (_, __) => const SizedBox(width: 8),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SliverToBoxAdapter(
|
||||
child: SizedBox(height: 8),
|
||||
),
|
||||
SliverStaggeredGrid.extentBuilder(
|
||||
maxCrossAxisExtent: 160,
|
||||
mainAxisSpacing: 2,
|
||||
crossAxisSpacing: 2,
|
||||
itemCount: _placeItems.length,
|
||||
itemBuilder: (context, i) => _placeItems[i].buildWidget(context),
|
||||
staggeredTileBuilder: (_) => const StaggeredTile.count(1, 1),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
@ -265,9 +255,9 @@ class _PlaceItem {
|
|||
account: account,
|
||||
label: place,
|
||||
coverUrl: thumbUrl,
|
||||
fallbackBuilder: (_) => Icon(
|
||||
fallbackBuilder: (context) => Icon(
|
||||
Icons.location_on,
|
||||
color: Colors.white.withOpacity(.8),
|
||||
color: Theme.of(context).listPlaceholderForegroundColor,
|
||||
),
|
||||
onTap: onTap,
|
||||
);
|
||||
|
@ -303,12 +293,9 @@ class _CountryItem {
|
|||
},
|
||||
fadeInDuration: const Duration(),
|
||||
filterQuality: FilterQuality.high,
|
||||
errorWidget: (_, __, ___) => Padding(
|
||||
padding: const EdgeInsetsDirectional.fromSTEB(8, 8, 0, 8),
|
||||
child: Icon(
|
||||
Icons.location_on,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
errorWidget: (_, __, ___) => const Padding(
|
||||
padding: EdgeInsetsDirectional.fromSTEB(8, 8, 0, 8),
|
||||
child: Icon(Icons.location_on),
|
||||
),
|
||||
imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
|
||||
),
|
||||
|
@ -321,7 +308,7 @@ class _CountryItem {
|
|||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: AppTheme.getListItemBackgroundColor(context),
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
|
|
|
@ -56,12 +56,11 @@ class _ResultViewerState extends State<ResultViewer> {
|
|||
@override
|
||||
build(BuildContext context) {
|
||||
if (_file == null) {
|
||||
return AppTheme(
|
||||
return Theme(
|
||||
data: buildDarkTheme(),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.black,
|
||||
shadowColor: Colors.black,
|
||||
foregroundColor: Colors.white.withOpacity(.87),
|
||||
elevation: 0,
|
||||
),
|
||||
body: Container(
|
||||
|
|
|
@ -10,7 +10,6 @@ import 'package:nc_photos/entity/file_descriptor.dart';
|
|||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/ls_single_file.dart';
|
||||
import 'package:nc_photos/widget/dir_picker.dart';
|
||||
import 'package:nc_photos/widget/processing_dialog.dart';
|
||||
|
@ -75,10 +74,8 @@ class _RootPickerState extends State<RootPicker> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: _buildContent(context),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -57,14 +57,7 @@ class _SearchLandingState extends State<SearchLanding> {
|
|||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<SearchLandingBloc, SearchLandingBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
child: _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -319,7 +312,7 @@ class _LandingPersonItem {
|
|||
onTap: onTap,
|
||||
fallbackBuilder: (_) => Icon(
|
||||
Icons.person,
|
||||
color: Colors.white.withOpacity(.8),
|
||||
color: Theme.of(context).listPlaceholderForegroundColor,
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -344,7 +337,7 @@ class _LandingLocationItem {
|
|||
onTap: onTap,
|
||||
fallbackBuilder: (_) => Icon(
|
||||
Icons.location_on,
|
||||
color: Colors.white.withOpacity(.8),
|
||||
color: Theme.of(context).listPlaceholderForegroundColor,
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -384,9 +377,7 @@ class _LandingItemWidget extends StatelessWidget {
|
|||
width: 88,
|
||||
child: Text(
|
||||
label + "\n",
|
||||
style: Theme.of(context).textTheme.bodyText1!.copyWith(
|
||||
color: AppTheme.getPrimaryTextColor(context),
|
||||
),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
@ -408,7 +399,7 @@ class _LandingItemWidget extends StatelessWidget {
|
|||
Widget _buildCoverImage(BuildContext context) {
|
||||
Widget cover;
|
||||
Widget buildPlaceholder() => Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: fallbackBuilder(context),
|
||||
);
|
||||
try {
|
||||
|
@ -436,7 +427,7 @@ class _LandingItemWidget extends StatelessWidget {
|
|||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(128),
|
||||
child: Container(
|
||||
color: AppTheme.getListItemBackgroundColor(context),
|
||||
color: Theme.of(context).listPlaceholderBackgroundColor,
|
||||
constraints: const BoxConstraints.expand(),
|
||||
child: cover,
|
||||
),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/theme.dart';
|
||||
|
||||
// Overlay a check mark if an item is selected
|
||||
class Selectable extends StatelessWidget {
|
||||
|
@ -23,7 +22,7 @@ class Selectable extends StatelessWidget {
|
|||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppTheme.getSelectionOverlayColor(context),
|
||||
color: Theme.of(context).colorScheme.primaryContainer,
|
||||
borderRadius: borderRadius,
|
||||
),
|
||||
),
|
||||
|
@ -44,12 +43,12 @@ class Selectable extends StatelessWidget {
|
|||
Icon(
|
||||
Icons.circle,
|
||||
size: iconSize,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: Theme.of(context).colorScheme.primaryContainer,
|
||||
),
|
||||
Icon(
|
||||
Icons.check_circle_outlined,
|
||||
size: iconSize,
|
||||
color: Colors.white,
|
||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
|
||||
class SelectionAppBar extends StatelessWidget {
|
||||
const SelectionAppBar({
|
||||
|
@ -12,20 +11,15 @@ class SelectionAppBar extends StatelessWidget {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
appBarTheme: AppTheme.getContextualAppBarTheme(context),
|
||||
),
|
||||
child: SliverAppBar(
|
||||
pinned: true,
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
tooltip: MaterialLocalizations.of(context).closeButtonTooltip,
|
||||
onPressed: onClosePressed,
|
||||
),
|
||||
title: Text(L10n.global().selectionAppBarTitle(count)),
|
||||
actions: actions,
|
||||
return SliverAppBar(
|
||||
pinned: true,
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
tooltip: MaterialLocalizations.of(context).closeButtonTooltip,
|
||||
onPressed: onClosePressed,
|
||||
),
|
||||
title: Text(L10n.global().selectionAppBarTitle(count)),
|
||||
actions: actions,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import 'package:nc_photos/platform/notification.dart';
|
|||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/service.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/url_launcher_util.dart';
|
||||
import 'package:nc_photos/widget/fancy_option_picker.dart';
|
||||
import 'package:nc_photos/widget/gps_map.dart';
|
||||
|
@ -83,11 +82,9 @@ class _SettingsState extends State<Settings> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -104,11 +101,8 @@ class _SettingsState extends State<Settings> {
|
|||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
ListTile(
|
||||
leading: ListTileCenterLeading(
|
||||
child: Icon(
|
||||
Icons.translate_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
leading: const ListTileCenterLeading(
|
||||
child: Icon(Icons.translate_outlined),
|
||||
),
|
||||
title: Text(L10n.global().settingsLanguageTitle),
|
||||
subtitle: Text(language_util.getSelectedLanguage().nativeName),
|
||||
|
@ -133,39 +127,27 @@ class _SettingsState extends State<Settings> {
|
|||
),
|
||||
_buildSubSettings(
|
||||
context,
|
||||
leading: Icon(
|
||||
Icons.manage_accounts_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
leading: const Icon(Icons.manage_accounts_outlined),
|
||||
label: L10n.global().settingsAccountTitle,
|
||||
builder: () => AccountSettingsWidget(account: widget.account),
|
||||
),
|
||||
_buildSubSettings(
|
||||
context,
|
||||
leading: Icon(
|
||||
Icons.image_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
leading: const Icon(Icons.image_outlined),
|
||||
label: L10n.global().photosTabLabel,
|
||||
description: L10n.global().settingsPhotosDescription,
|
||||
builder: () => _PhotosSettings(account: widget.account),
|
||||
),
|
||||
_buildSubSettings(
|
||||
context,
|
||||
leading: Icon(
|
||||
Icons.photo_album_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
leading: const Icon(Icons.photo_album_outlined),
|
||||
label: L10n.global().settingsAlbumTitle,
|
||||
description: L10n.global().settingsAlbumDescription,
|
||||
builder: () => _AlbumSettings(),
|
||||
),
|
||||
_buildSubSettings(
|
||||
context,
|
||||
leading: Icon(
|
||||
Icons.view_carousel_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
leading: const Icon(Icons.view_carousel_outlined),
|
||||
label: L10n.global().settingsViewerTitle,
|
||||
description: L10n.global().settingsViewerDescription,
|
||||
builder: () => _ViewerSettings(),
|
||||
|
@ -173,40 +155,28 @@ class _SettingsState extends State<Settings> {
|
|||
if (features.isSupportEnhancement)
|
||||
_buildSubSettings(
|
||||
context,
|
||||
leading: Icon(
|
||||
Icons.auto_fix_high_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
leading: const Icon(Icons.auto_fix_high_outlined),
|
||||
label: L10n.global().settingsImageEditTitle,
|
||||
description: L10n.global().settingsImageEditDescription,
|
||||
builder: () => const EnhancementSettings(),
|
||||
),
|
||||
_buildSubSettings(
|
||||
context,
|
||||
leading: Icon(
|
||||
Icons.palette_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
leading: const Icon(Icons.palette_outlined),
|
||||
label: L10n.global().settingsThemeTitle,
|
||||
description: L10n.global().settingsThemeDescription,
|
||||
builder: () => _ThemeSettings(),
|
||||
),
|
||||
_buildSubSettings(
|
||||
context,
|
||||
leading: Icon(
|
||||
Icons.emoji_symbols_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
leading: const Icon(Icons.emoji_symbols_outlined),
|
||||
label: L10n.global().settingsMiscellaneousTitle,
|
||||
builder: () => const _MiscSettings(),
|
||||
),
|
||||
if (_enabledExperiments.isNotEmpty)
|
||||
_buildSubSettings(
|
||||
context,
|
||||
leading: Icon(
|
||||
Icons.science_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
leading: const Icon(Icons.science_outlined),
|
||||
label: L10n.global().settingsExperimentalTitle,
|
||||
description: L10n.global().settingsExperimentalDescription,
|
||||
builder: () => _ExperimentalSettings(),
|
||||
|
@ -214,10 +184,7 @@ class _SettingsState extends State<Settings> {
|
|||
if (_isShowDevSettings)
|
||||
_buildSubSettings(
|
||||
context,
|
||||
leading: Icon(
|
||||
Icons.code_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
leading: const Icon(Icons.code_outlined),
|
||||
label: "Developer options",
|
||||
builder: () => _DevSettings(),
|
||||
),
|
||||
|
@ -332,26 +299,23 @@ class _SettingsState extends State<Settings> {
|
|||
if (value) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AppTheme(
|
||||
child: AlertDialog(
|
||||
title: Text(L10n.global().exifSupportConfirmationDialogTitle),
|
||||
content: Text(L10n.global().exifSupportDetails),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child:
|
||||
Text(MaterialLocalizations.of(context).cancelButtonLabel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
child: Text(L10n.global().enableButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(L10n.global().exifSupportConfirmationDialogTitle),
|
||||
content: Text(L10n.global().exifSupportDetails),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
child: Text(L10n.global().enableButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
).then((value) {
|
||||
if (value == true) {
|
||||
|
@ -389,18 +353,16 @@ class _SettingsState extends State<Settings> {
|
|||
if (value) {
|
||||
final result = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AppTheme(
|
||||
child: AlertDialog(
|
||||
content: Text(L10n.global().captureLogDetails),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
child: Text(L10n.global().enableButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
builder: (context) => AlertDialog(
|
||||
content: Text(L10n.global().captureLogDetails),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
child: Text(L10n.global().enableButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (result == true) {
|
||||
|
@ -514,11 +476,9 @@ class _AccountSettingsState extends State<AccountSettingsWidget> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -823,11 +783,9 @@ class _PhotosSettingsState extends State<_PhotosSettings> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -869,24 +827,22 @@ class _PhotosSettingsState extends State<_PhotosSettings> {
|
|||
var memoriesRange = _memoriesRange;
|
||||
final result = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (_) => AppTheme(
|
||||
child: AlertDialog(
|
||||
content: _MemoriesRangeSlider(
|
||||
initialRange: _memoriesRange,
|
||||
onChanged: (value) {
|
||||
memoriesRange = value;
|
||||
},
|
||||
),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 0),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
child: Text(L10n.global().applyButtonLabel),
|
||||
),
|
||||
],
|
||||
builder: (_) => AlertDialog(
|
||||
content: _MemoriesRangeSlider(
|
||||
initialRange: _memoriesRange,
|
||||
onChanged: (value) {
|
||||
memoriesRange = value;
|
||||
},
|
||||
),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 0),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
child: Text(L10n.global().applyButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (result != true || memoriesRange == _memoriesRange) {
|
||||
|
@ -1004,11 +960,9 @@ class _ViewerSettingsState extends State<_ViewerSettings> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1060,55 +1014,46 @@ class _ViewerSettingsState extends State<_ViewerSettings> {
|
|||
await ScreenBrightness().setScreenBrightness(brightness);
|
||||
final value = await showDialog<int>(
|
||||
context: context,
|
||||
builder: (_) => AppTheme(
|
||||
child: AlertDialog(
|
||||
title: Text(L10n.global().settingsScreenBrightnessTitle),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(L10n.global().settingsScreenBrightnessDescription),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.brightness_low,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
builder: (_) => AlertDialog(
|
||||
title: Text(L10n.global().settingsScreenBrightnessTitle),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(L10n.global().settingsScreenBrightnessDescription),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
const Icon(Icons.brightness_low),
|
||||
Expanded(
|
||||
child: StatefulSlider(
|
||||
initialValue: brightness,
|
||||
min: 0.01,
|
||||
onChangeEnd: (value) async {
|
||||
brightness = value;
|
||||
try {
|
||||
await ScreenBrightness().setScreenBrightness(value);
|
||||
} catch (e, stackTrace) {
|
||||
_log.severe("Failed while setScreenBrightness", e,
|
||||
stackTrace);
|
||||
}
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: StatefulSlider(
|
||||
initialValue: brightness,
|
||||
min: 0.01,
|
||||
onChangeEnd: (value) async {
|
||||
brightness = value;
|
||||
try {
|
||||
await ScreenBrightness()
|
||||
.setScreenBrightness(value);
|
||||
} catch (e, stackTrace) {
|
||||
_log.severe("Failed while setScreenBrightness", e,
|
||||
stackTrace);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.brightness_high,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop((brightness * 100).round());
|
||||
},
|
||||
child: Text(MaterialLocalizations.of(context).okButtonLabel),
|
||||
),
|
||||
const Icon(Icons.brightness_high),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop((brightness * 100).round());
|
||||
},
|
||||
child: Text(MaterialLocalizations.of(context).okButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -1218,11 +1163,9 @@ class _AlbumSettingsState extends State<_AlbumSettings> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1299,11 +1242,9 @@ class _EnhancementSettingsState extends State<EnhancementSettings> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1346,34 +1287,32 @@ class _EnhancementSettingsState extends State<EnhancementSettings> {
|
|||
var height = _maxHeight;
|
||||
final result = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (_) => AppTheme(
|
||||
child: AlertDialog(
|
||||
title: Text(L10n.global().settingsEnhanceMaxResolutionTitle2),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(L10n.global().settingsEnhanceMaxResolutionDescription),
|
||||
const SizedBox(height: 16),
|
||||
_EnhanceResolutionSlider(
|
||||
initialWidth: _maxWidth,
|
||||
initialHeight: _maxHeight,
|
||||
onChanged: (value) {
|
||||
width = value.item1;
|
||||
height = value.item2;
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
builder: (_) => AlertDialog(
|
||||
title: Text(L10n.global().settingsEnhanceMaxResolutionTitle2),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(L10n.global().settingsEnhanceMaxResolutionDescription),
|
||||
const SizedBox(height: 16),
|
||||
_EnhanceResolutionSlider(
|
||||
initialWidth: _maxWidth,
|
||||
initialHeight: _maxHeight,
|
||||
onChanged: (value) {
|
||||
width = value.item1;
|
||||
height = value.item2;
|
||||
},
|
||||
child: Text(MaterialLocalizations.of(context).okButtonLabel),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
child: Text(MaterialLocalizations.of(context).okButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (result != true || (width == _maxWidth && height == _maxHeight)) {
|
||||
|
@ -1538,11 +1477,9 @@ class _ThemeSettingsState extends State<_ThemeSettings> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1645,11 +1582,9 @@ class _MiscSettingsState extends State<_MiscSettings> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1735,11 +1670,9 @@ class _ExperimentalSettingsState extends State<_ExperimentalSettings> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1799,11 +1732,9 @@ class _DevSettings extends StatefulWidget {
|
|||
class _DevSettingsState extends State<_DevSettings> {
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1883,9 +1814,9 @@ Widget _buildCaption(BuildContext context, String label) {
|
|||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
style: Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
|||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/widget/home.dart';
|
||||
import 'package:nc_photos/widget/sign_in.dart';
|
||||
import 'package:page_view_indicators/circle_page_indicator.dart';
|
||||
|
@ -23,11 +22,9 @@ class Setup extends StatefulWidget {
|
|||
class _SetupState extends State<Setup> {
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
appBar: _buildAppBar(context),
|
||||
body: Builder(builder: (context) => _buildContent(context)),
|
||||
),
|
||||
return Scaffold(
|
||||
appBar: _buildAppBar(context),
|
||||
body: Builder(builder: (context) => _buildContent(context)),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import 'package:nc_photos/entity/sharee.dart';
|
|||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/share_album_with_user.dart';
|
||||
import 'package:nc_photos/use_case/unshare_album_with_user.dart';
|
||||
import 'package:nc_photos/widget/album_share_outlier_browser.dart';
|
||||
|
@ -62,15 +61,13 @@ class _ShareAlbumDialogState extends State<ShareAlbumDialog> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: DialogScaffold(
|
||||
canPop: _processingSharee.isEmpty,
|
||||
body: BlocListener<ListShareeBloc, ListShareeBlocState>(
|
||||
bloc: _shareeBloc,
|
||||
listener: _onShareeStateChange,
|
||||
child: Builder(
|
||||
builder: _buildContent,
|
||||
),
|
||||
return DialogScaffold(
|
||||
canPop: _processingSharee.isEmpty,
|
||||
body: BlocListener<ListShareeBloc, ListShareeBlocState>(
|
||||
bloc: _shareeBloc,
|
||||
listener: _onShareeStateChange,
|
||||
child: Builder(
|
||||
builder: _buildContent,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -90,14 +87,12 @@ class _ShareAlbumDialogState extends State<ShareAlbumDialog> {
|
|||
final isProcessing = _processingSharee.any((s) => s == share.shareWith);
|
||||
final Widget trailing;
|
||||
if (isProcessing) {
|
||||
trailing = Padding(
|
||||
padding: const EdgeInsetsDirectional.only(end: 12),
|
||||
trailing = const Padding(
|
||||
padding: EdgeInsetsDirectional.only(end: 12),
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
|
@ -263,7 +258,6 @@ class _ShareAlbumDialogState extends State<ShareAlbumDialog> {
|
|||
action: hasFailure
|
||||
? SnackBarAction(
|
||||
label: L10n.global().fixButtonLabel,
|
||||
textColor: Theme.of(context).colorScheme.secondaryVariant,
|
||||
onPressed: _onFixPressed,
|
||||
)
|
||||
: null,
|
||||
|
@ -303,7 +297,6 @@ class _ShareAlbumDialogState extends State<ShareAlbumDialog> {
|
|||
action: hasFailure
|
||||
? SnackBarAction(
|
||||
label: L10n.global().fixButtonLabel,
|
||||
textColor: Theme.of(context).colorScheme.secondaryVariant,
|
||||
onPressed: _onFixPressed,
|
||||
)
|
||||
: null,
|
||||
|
|
|
@ -8,7 +8,6 @@ import 'package:nc_photos/entity/file_util.dart' as file_util;
|
|||
import 'package:nc_photos/iterable_extension.dart';
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/widget/dir_picker.dart';
|
||||
|
||||
class ShareFolderPickerArguments {
|
||||
|
@ -49,10 +48,8 @@ class ShareFolderPicker extends StatefulWidget {
|
|||
class _ShareFolderPickerState extends State<ShareFolderPicker> {
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: _buildContent(context),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ import 'package:nc_photos/exception_util.dart' as exception_util;
|
|||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/remove.dart';
|
||||
import 'package:nc_photos/use_case/remove_share.dart';
|
||||
import 'package:nc_photos/widget/list_tile_center_leading.dart';
|
||||
|
@ -67,10 +66,8 @@ class SharedFileViewer extends StatefulWidget {
|
|||
class _SharedFileViewerState extends State<SharedFileViewer> {
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: _buildContent(context),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ import 'package:nc_photos/object_extension.dart';
|
|||
import 'package:nc_photos/or_null.dart';
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/import_potential_shared_album.dart';
|
||||
import 'package:nc_photos/widget/album_browser_util.dart' as album_browser_util;
|
||||
import 'package:nc_photos/widget/empty_list_indicator.dart';
|
||||
|
@ -82,15 +81,13 @@ class _SharingBrowserState extends State<SharingBrowser> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: BlocListener<ListSharingBloc, ListSharingBlocState>(
|
||||
return Scaffold(
|
||||
body: BlocListener<ListSharingBloc, ListSharingBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListSharingBloc, ListSharingBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListSharingBloc, ListSharingBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -117,26 +114,19 @@ class _SharingBrowserState extends State<SharingBrowser> {
|
|||
} else {
|
||||
return Stack(
|
||||
children: [
|
||||
Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
title: Text(L10n.global().collectionSharingLabel),
|
||||
floating: true,
|
||||
CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
title: Text(L10n.global().collectionSharingLabel),
|
||||
floating: true,
|
||||
),
|
||||
SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) => _buildItem(context, _items[index]),
|
||||
childCount: _items.length,
|
||||
),
|
||||
SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) => _buildItem(context, _items[index]),
|
||||
childCount: _items.length,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (state is ListSharingBlocLoading)
|
||||
const Align(
|
||||
|
@ -172,14 +162,10 @@ class _SharingBrowserState extends State<SharingBrowser> {
|
|||
final firstItem = shares.first as ListSharingFile;
|
||||
return _ListTile(
|
||||
leading: shares.first.share.itemType == ShareItemType.folder
|
||||
? SizedBox(
|
||||
? const SizedBox(
|
||||
height: _leadingSize,
|
||||
width: _leadingSize,
|
||||
child: Icon(
|
||||
Icons.folder,
|
||||
size: 32,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
child: Icon(Icons.folder, size: 32),
|
||||
)
|
||||
: CachedNetworkImage(
|
||||
width: _leadingSize,
|
||||
|
@ -195,11 +181,8 @@ class _SharingBrowserState extends State<SharingBrowser> {
|
|||
fadeInDuration: const Duration(),
|
||||
filterQuality: FilterQuality.high,
|
||||
imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
|
||||
errorWidget: (context, url, error) => Icon(
|
||||
Icons.folder,
|
||||
size: 32,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
errorWidget: (context, url, error) =>
|
||||
const Icon(Icons.folder, size: 32),
|
||||
),
|
||||
label: shares.first.share.filename,
|
||||
description: shares.first.share.uidOwner == widget.account.userId
|
||||
|
@ -207,10 +190,7 @@ class _SharingBrowserState extends State<SharingBrowser> {
|
|||
: L10n.global().fileLastSharedByOthersDescription(
|
||||
shares.first.share.displaynameOwner, dateStr),
|
||||
trailing: (shares.any((element) => element.share.url?.isNotEmpty == true))
|
||||
? Icon(
|
||||
Icons.link,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
)
|
||||
? const Icon(Icons.link)
|
||||
: null,
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(SharedFileViewer.routeName,
|
||||
|
@ -231,14 +211,10 @@ class _SharingBrowserState extends State<SharingBrowser> {
|
|||
final cover = firstItem.album.coverProvider.getCover(firstItem.album);
|
||||
return _ListTile(
|
||||
leading: cover == null
|
||||
? SizedBox(
|
||||
? const SizedBox(
|
||||
height: _leadingSize,
|
||||
width: _leadingSize,
|
||||
child: Icon(
|
||||
Icons.photo_album,
|
||||
size: 32,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
child: Icon(Icons.photo_album, size: 32),
|
||||
)
|
||||
: CachedNetworkImage(
|
||||
width: _leadingSize,
|
||||
|
@ -253,21 +229,15 @@ class _SharingBrowserState extends State<SharingBrowser> {
|
|||
fadeInDuration: const Duration(),
|
||||
filterQuality: FilterQuality.high,
|
||||
imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
|
||||
errorWidget: (context, url, error) => Icon(
|
||||
Icons.photo_album,
|
||||
size: 32,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
errorWidget: (context, url, error) =>
|
||||
const Icon(Icons.photo_album, size: 32),
|
||||
),
|
||||
label: firstItem.album.name,
|
||||
description: shares.first.share.uidOwner == widget.account.userId
|
||||
? L10n.global().fileLastSharedDescription(dateStr)
|
||||
: L10n.global().albumLastSharedByOthersDescription(
|
||||
shares.first.share.displaynameOwner, dateStr),
|
||||
trailing: Icon(
|
||||
Icons.photo_album_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
trailing: const Icon(Icons.photo_album_outlined),
|
||||
onTap: () =>
|
||||
_onAlbumShareItemTap(context, shares.first as ListSharingAlbum),
|
||||
);
|
||||
|
|
|
@ -34,10 +34,8 @@ class SignIn extends StatefulWidget {
|
|||
class _SignInState extends State<SignIn> {
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(builder: (context) => _buildContent(context)),
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(builder: (context) => _buildContent(context)),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -84,16 +82,20 @@ class _SignInState extends State<SignIn> {
|
|||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: AppTheme.widthLimitedContentMaxWidth),
|
||||
constraints: BoxConstraints(
|
||||
maxWidth:
|
||||
Theme.of(context).widthLimitedContentMaxWidth,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
child: _buildForm(context),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: AppTheme.widthLimitedContentMaxWidth),
|
||||
constraints: BoxConstraints(
|
||||
maxWidth:
|
||||
Theme.of(context).widthLimitedContentMaxWidth,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
|
@ -119,8 +121,10 @@ class _SignInState extends State<SignIn> {
|
|||
),
|
||||
if (!platform_k.isWeb) Expanded(child: Container()),
|
||||
Container(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: AppTheme.widthLimitedContentMaxWidth),
|
||||
constraints: BoxConstraints(
|
||||
maxWidth:
|
||||
Theme.of(context).widthLimitedContentMaxWidth,
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
|
|
@ -95,7 +95,8 @@ class _SlideshowViewerState extends State<SlideshowViewer>
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
return Theme(
|
||||
data: buildDarkTheme(),
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: _buildContent,
|
||||
|
@ -162,8 +163,7 @@ class _SlideshowViewerState extends State<SlideshowViewer>
|
|||
),
|
||||
AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
foregroundColor: Colors.white.withOpacity(.87),
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
tooltip: MaterialLocalizations.of(context).closeButtonTooltip,
|
||||
|
|
|
@ -16,7 +16,6 @@ import 'package:nc_photos/flutter_util.dart' as flutter_util;
|
|||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/object_extension.dart';
|
||||
import 'package:nc_photos/share_handler.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/preprocess_album.dart';
|
||||
import 'package:nc_photos/widget/album_browser_mixin.dart';
|
||||
import 'package:nc_photos/widget/handler/add_selection_to_album_handler.dart';
|
||||
|
@ -76,11 +75,9 @@ class _SmartAlbumBrowserState extends State<SmartAlbumBrowser>
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
return Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => _buildContent(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -120,20 +117,13 @@ class _SmartAlbumBrowserState extends State<SmartAlbumBrowser>
|
|||
} else {
|
||||
return buildItemStreamListOuter(
|
||||
context,
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import 'package:nc_photos/k.dart' as k;
|
|||
import 'package:nc_photos/mobile/android/activity.dart';
|
||||
import 'package:nc_photos/platform/k.dart' as platform_k;
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/compat/v29.dart';
|
||||
import 'package:nc_photos/use_case/compat/v46.dart';
|
||||
import 'package:nc_photos/use_case/compat/v55.dart';
|
||||
|
@ -58,12 +57,10 @@ class _SplashState extends State<Splash> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: WillPopScope(
|
||||
onWillPop: () => Future.value(false),
|
||||
child: Builder(builder: (context) => _buildContent(context)),
|
||||
),
|
||||
return Scaffold(
|
||||
body: WillPopScope(
|
||||
onWillPop: () => Future.value(false),
|
||||
child: Builder(builder: (context) => _buildContent(context)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ import 'package:nc_photos/object_extension.dart';
|
|||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/share_handler.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/throttler.dart';
|
||||
import 'package:nc_photos/widget/app_bar_title_container.dart';
|
||||
import 'package:nc_photos/widget/builder/photo_list_item_builder.dart';
|
||||
import 'package:nc_photos/widget/handler/add_selection_to_album_handler.dart';
|
||||
import 'package:nc_photos/widget/handler/archive_selection_handler.dart';
|
||||
|
@ -96,15 +96,13 @@ class _TagBrowserState extends State<TagBrowser>
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: BlocListener<ListTagFileBloc, ListTagFileBlocState>(
|
||||
return Scaffold(
|
||||
body: BlocListener<ListTagFileBloc, ListTagFileBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListTagFileBloc, ListTagFileBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<ListTagFileBloc, ListTagFileBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -130,27 +128,20 @@ class _TagBrowserState extends State<TagBrowser>
|
|||
Widget _buildContent(BuildContext context, ListTagFileBlocState state) {
|
||||
return buildItemStreamListOuter(
|
||||
context,
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context, state),
|
||||
if (state is ListTagFileBlocLoading || _buildItemQueue.isProcessing)
|
||||
const SliverToBoxAdapter(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: LinearProgressIndicator(),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context, state),
|
||||
if (state is ListTagFileBlocLoading || _buildItemQueue.isProcessing)
|
||||
const SliverToBoxAdapter(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: LinearProgressIndicator(),
|
||||
),
|
||||
),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -167,45 +158,14 @@ class _TagBrowserState extends State<TagBrowser>
|
|||
return SliverAppBar(
|
||||
floating: true,
|
||||
titleSpacing: 0,
|
||||
title: Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
width: 40,
|
||||
child: Center(
|
||||
child: Icon(Icons.local_offer_outlined, size: 24),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
widget.tag.displayName,
|
||||
style: TextStyle(
|
||||
color: AppTheme.getPrimaryTextColor(context),
|
||||
),
|
||||
maxLines: 1,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.clip,
|
||||
),
|
||||
if (state is! ListTagFileBlocLoading &&
|
||||
!_buildItemQueue.isProcessing)
|
||||
Text(
|
||||
L10n.global().personPhotoCountText(_backingFiles.length),
|
||||
style: TextStyle(
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
title: AppBarTitleContainer(
|
||||
icon: const Icon(Icons.local_offer_outlined),
|
||||
title: Text(widget.tag.displayName),
|
||||
subtitle:
|
||||
(state is! ListTagFileBlocLoading && !_buildItemQueue.isProcessing)
|
||||
? Text(L10n.global().personPhotoCountText(_backingFiles.length))
|
||||
: null,
|
||||
),
|
||||
// ),
|
||||
actions: [
|
||||
ZoomMenuButton(
|
||||
initialZoom: _thumbZoomLevel,
|
||||
|
|
|
@ -11,7 +11,6 @@ import 'package:nc_photos/entity/tag.dart';
|
|||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/widget/dialog_scaffold.dart';
|
||||
|
||||
class TagPickerDialog extends StatefulWidget {
|
||||
|
@ -35,13 +34,11 @@ class _TagPickerDialogState extends State<TagPickerDialog> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: DialogScaffold(
|
||||
body: BlocListener<ListTagBloc, ListTagBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: _onStateChange,
|
||||
child: Builder(builder: _buildContent),
|
||||
),
|
||||
return DialogScaffold(
|
||||
body: BlocListener<ListTagBloc, ListTagBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: _onStateChange,
|
||||
child: Builder(builder: _buildContent),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import 'package:nc_photos/language_util.dart' as language_util;
|
|||
import 'package:nc_photos/object_extension.dart';
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/inflate_file_descriptor.dart';
|
||||
import 'package:nc_photos/use_case/restore_trashbin.dart';
|
||||
import 'package:nc_photos/widget/builder/photo_list_item_builder.dart';
|
||||
|
@ -73,15 +72,13 @@ class _TrashbinBrowserState extends State<TrashbinBrowser>
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Scaffold(
|
||||
body: BlocListener<LsTrashbinBloc, LsTrashbinBlocState>(
|
||||
return Scaffold(
|
||||
body: BlocListener<LsTrashbinBloc, LsTrashbinBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<LsTrashbinBloc, LsTrashbinBlocState>(
|
||||
bloc: _bloc,
|
||||
listener: (context, state) => _onStateChange(context, state),
|
||||
child: BlocBuilder<LsTrashbinBloc, LsTrashbinBlocState>(
|
||||
bloc: _bloc,
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
builder: (context, state) => _buildContent(context, state),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -138,20 +135,13 @@ class _TrashbinBrowserState extends State<TrashbinBrowser>
|
|||
children: [
|
||||
buildItemStreamListOuter(
|
||||
context,
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||
secondary: AppTheme.getOverscrollIndicatorColor(context),
|
||||
),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
_buildAppBar(context),
|
||||
buildItemStreamList(
|
||||
maxCrossAxisExtent: _thumbSize.toDouble(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (state is LsTrashbinBlocLoading || _buildItemQueue.isProcessing)
|
||||
|
|
|
@ -60,7 +60,8 @@ class TrashbinViewer extends StatefulWidget {
|
|||
class _TrashbinViewerState extends State<TrashbinViewer> {
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
return Theme(
|
||||
data: buildDarkTheme(),
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: _buildContent,
|
||||
|
@ -120,8 +121,7 @@ class _TrashbinViewerState extends State<TrashbinViewer> {
|
|||
),
|
||||
AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
foregroundColor: Colors.white.withOpacity(.87),
|
||||
elevation: 0,
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.restore_outlined),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/material3.dart';
|
||||
|
||||
/// A [ListTile]-like widget with unbounded height
|
||||
class UnboundedListTile extends StatelessWidget {
|
||||
|
@ -28,14 +28,16 @@ class UnboundedListTile extends StatelessWidget {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
DefaultTextStyle(
|
||||
style: Theme.of(context).textTheme.subtitle1!,
|
||||
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
|
||||
color: M3.of(context).listTile.enabled.headline,
|
||||
),
|
||||
child: title,
|
||||
),
|
||||
if (subtitle != null)
|
||||
DefaultTextStyle(
|
||||
style: TextStyle(
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: M3.of(context).listTile.enabled.supportingText,
|
||||
),
|
||||
child: subtitle!,
|
||||
),
|
||||
],
|
||||
|
|
|
@ -180,10 +180,9 @@ class _VideoViewerState extends State<VideoViewer>
|
|||
valueListenable: _controller,
|
||||
builder: (context, VideoPlayerValue value, child) => Text(
|
||||
_durationToString(value.position),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.white.withOpacity(.87),
|
||||
),
|
||||
style: Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
|
@ -192,10 +191,12 @@ class _VideoViewerState extends State<VideoViewer>
|
|||
_controller,
|
||||
allowScrubbing: true,
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
colors: const VideoProgressColors(
|
||||
backgroundColor: Colors.white24,
|
||||
bufferedColor: Colors.white38,
|
||||
playedColor: Colors.white,
|
||||
colors: VideoProgressColors(
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.surface,
|
||||
bufferedColor:
|
||||
Theme.of(context).colorScheme.surfaceVariant,
|
||||
playedColor: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -203,10 +204,9 @@ class _VideoViewerState extends State<VideoViewer>
|
|||
if (_controller.value.duration != Duration.zero)
|
||||
Text(
|
||||
_durationToString(_controller.value.duration),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.white.withOpacity(.87),
|
||||
),
|
||||
style: Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Tooltip(
|
||||
|
@ -222,8 +222,7 @@ class _VideoViewerState extends State<VideoViewer>
|
|||
child: Icon(
|
||||
_controller.value.volume == 0
|
||||
? Icons.volume_mute_outlined
|
||||
: Icons.volume_up_outlined,
|
||||
color: Colors.white.withOpacity(.87),
|
||||
: Icons.volume_up,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -104,16 +104,18 @@ class _ViewerState extends State<Viewer>
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
final originalBrightness = Theme.of(context).brightness;
|
||||
return Theme(
|
||||
data: buildDarkTheme(),
|
||||
child: Scaffold(
|
||||
body: Builder(
|
||||
builder: _buildContent,
|
||||
builder: (context) => _buildContent(context, originalBrightness),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildContent(BuildContext context) {
|
||||
Widget _buildContent(BuildContext context, Brightness originalBrightness) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
|
@ -131,7 +133,8 @@ class _ViewerState extends State<Viewer>
|
|||
),
|
||||
HorizontalPageViewer(
|
||||
pageCount: _streamFilesView.length,
|
||||
pageBuilder: _buildPage,
|
||||
pageBuilder: (context, i) =>
|
||||
_buildPage(context, i, originalBrightness),
|
||||
initialPage: widget.startIndex,
|
||||
controller: _viewerController,
|
||||
viewportFraction: _viewportFraction,
|
||||
|
@ -174,8 +177,7 @@ class _ViewerState extends State<Viewer>
|
|||
),
|
||||
AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
foregroundColor: Colors.white.withOpacity(.87),
|
||||
elevation: 0,
|
||||
actions: [
|
||||
if (!_isDetailPaneActive && _canOpenDetailPane()) ...[
|
||||
(_pageStates[index]?.favoriteOverride ??
|
||||
|
@ -222,45 +224,30 @@ class _ViewerState extends State<Viewer>
|
|||
child: ViewerBottomAppBar(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.share_outlined,
|
||||
color: Colors.white.withOpacity(.87),
|
||||
),
|
||||
icon: const Icon(Icons.share_outlined),
|
||||
tooltip: L10n.global().shareTooltip,
|
||||
onPressed: () => _onSharePressed(context),
|
||||
),
|
||||
if (features.isSupportEnhancement &&
|
||||
ImageEnhancer.isSupportedFormat(file)) ...[
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.tune_outlined,
|
||||
color: Colors.white.withOpacity(.87),
|
||||
),
|
||||
icon: const Icon(Icons.tune_outlined),
|
||||
tooltip: L10n.global().editTooltip,
|
||||
onPressed: () => _onEditPressed(context),
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.auto_fix_high_outlined,
|
||||
color: Colors.white.withOpacity(.87),
|
||||
),
|
||||
icon: const Icon(Icons.auto_fix_high_outlined),
|
||||
tooltip: L10n.global().enhanceTooltip,
|
||||
onPressed: () => _onEnhancePressed(context),
|
||||
),
|
||||
],
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.download_outlined,
|
||||
color: Colors.white.withOpacity(.87),
|
||||
),
|
||||
icon: const Icon(Icons.download_outlined),
|
||||
tooltip: L10n.global().downloadTooltip,
|
||||
onPressed: _onDownloadPressed,
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.delete_outlined,
|
||||
color: Colors.white.withOpacity(.87),
|
||||
),
|
||||
icon: const Icon(Icons.delete_outlined),
|
||||
tooltip: L10n.global().deleteTooltip,
|
||||
onPressed: () => _onDeletePressed(context),
|
||||
),
|
||||
|
@ -271,7 +258,8 @@ class _ViewerState extends State<Viewer>
|
|||
);
|
||||
}
|
||||
|
||||
Widget _buildPage(BuildContext context, int index) {
|
||||
Widget _buildPage(
|
||||
BuildContext context, int index, Brightness originalBrightness) {
|
||||
if (_pageStates[index] == null) {
|
||||
_onCreateNewPage(context, index);
|
||||
} else if (!_pageStates[index]!.scrollController.hasClients) {
|
||||
|
@ -310,31 +298,42 @@ class _ViewerState extends State<Viewer>
|
|||
});
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
alignment: Alignment.topLeft,
|
||||
constraints: BoxConstraints(
|
||||
minHeight: MediaQuery.of(context).size.height),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(4)),
|
||||
),
|
||||
margin:
|
||||
EdgeInsets.only(top: _calcDetailPaneOffset(index)),
|
||||
// this visibility widget avoids loading the detail pane
|
||||
// until it's actually opened, otherwise swiping between
|
||||
// photos will slow down severely
|
||||
child: Visibility(
|
||||
visible: _isShowDetailPane,
|
||||
child: ViewerDetailPane(
|
||||
account: widget.account,
|
||||
fd: _streamFilesView[index],
|
||||
album: widget.album,
|
||||
onRemoveFromAlbumPressed: _onRemoveFromAlbumPressed,
|
||||
onArchivePressed: _onArchivePressed,
|
||||
onUnarchivePressed: _onUnarchivePressed,
|
||||
onSlideshowPressed: _onSlideshowPressed,
|
||||
),
|
||||
child: Theme(
|
||||
data: buildTheme(originalBrightness),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return Container(
|
||||
alignment: Alignment.topLeft,
|
||||
constraints: BoxConstraints(
|
||||
minHeight: MediaQuery.of(context).size.height,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(4),
|
||||
),
|
||||
),
|
||||
margin: EdgeInsets.only(
|
||||
top: _calcDetailPaneOffset(index),
|
||||
),
|
||||
// this visibility widget avoids loading the detail pane
|
||||
// until it's actually opened, otherwise swiping between
|
||||
// photos will slow down severely
|
||||
child: Visibility(
|
||||
visible: _isShowDetailPane,
|
||||
child: ViewerDetailPane(
|
||||
account: widget.account,
|
||||
fd: _streamFilesView[index],
|
||||
album: widget.album,
|
||||
onRemoveFromAlbumPressed:
|
||||
_onRemoveFromAlbumPressed,
|
||||
onArchivePressed: _onArchivePressed,
|
||||
onUnarchivePressed: _onUnarchivePressed,
|
||||
onSlideshowPressed: _onSlideshowPressed,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -185,11 +185,8 @@ class _ViewerDetailPaneState extends State<ViewerDetailPane> {
|
|||
),
|
||||
],
|
||||
ListTile(
|
||||
leading: ListTileCenterLeading(
|
||||
child: Icon(
|
||||
Icons.image_outlined,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
leading: const ListTileCenterLeading(
|
||||
child: Icon(Icons.image_outlined),
|
||||
),
|
||||
title: Text(path_lib.basenameWithoutExtension(widget.fd.fdPath)),
|
||||
subtitle: Text(widget.fd.strippedPath),
|
||||
|
@ -197,10 +194,9 @@ class _ViewerDetailPaneState extends State<ViewerDetailPane> {
|
|||
if (_file != null) ...[
|
||||
if (!_file!.isOwned(widget.account.userId))
|
||||
ListTile(
|
||||
leading: ListTileCenterLeading(
|
||||
leading: const ListTileCenterLeading(
|
||||
child: Icon(
|
||||
Icons.share_outlined,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
),
|
||||
title:
|
||||
|
@ -209,38 +205,22 @@ class _ViewerDetailPaneState extends State<ViewerDetailPane> {
|
|||
),
|
||||
if (_tags.isNotEmpty)
|
||||
ListTile(
|
||||
leading: Icon(
|
||||
Icons.local_offer_outlined,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
leading: const Icon(Icons.local_offer_outlined),
|
||||
title: SizedBox(
|
||||
height: 40,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: _tags.length,
|
||||
itemBuilder: (context, index) => Center(
|
||||
child: Wrap(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 4),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
_tags[index],
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppTheme.getPrimaryTextColorInverse(
|
||||
context),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
itemBuilder: (context, index) => FilterChip(
|
||||
elevation: 1,
|
||||
pressElevation: 1,
|
||||
showCheckmark: false,
|
||||
visualDensity: VisualDensity.compact,
|
||||
selected: true,
|
||||
selectedColor: Theme.of(context)
|
||||
.elevate(Theme.of(context).colorScheme.surface, 5),
|
||||
label: Text(_tags[index]),
|
||||
onSelected: (_) {},
|
||||
),
|
||||
separatorBuilder: (context, index) =>
|
||||
const SizedBox(width: 8),
|
||||
|
@ -249,28 +229,17 @@ class _ViewerDetailPaneState extends State<ViewerDetailPane> {
|
|||
),
|
||||
],
|
||||
ListTile(
|
||||
leading: Icon(
|
||||
Icons.calendar_today_outlined,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
leading: const Icon(Icons.calendar_today_outlined),
|
||||
title: Text("$dateStr $timeStr"),
|
||||
trailing: _file == null
|
||||
? null
|
||||
: Icon(
|
||||
Icons.edit_outlined,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
trailing: _file == null ? null : const Icon(Icons.edit_outlined),
|
||||
onTap: _file == null ? null : () => _onDateTimeTap(context),
|
||||
),
|
||||
if (_file != null) ...[
|
||||
if (_file!.metadata?.imageWidth != null &&
|
||||
_file!.metadata?.imageHeight != null)
|
||||
ListTile(
|
||||
leading: ListTileCenterLeading(
|
||||
child: Icon(
|
||||
Icons.aspect_ratio,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
leading: const ListTileCenterLeading(
|
||||
child: Icon(Icons.aspect_ratio),
|
||||
),
|
||||
title: Text(
|
||||
"${_file!.metadata!.imageWidth} x ${_file!.metadata!.imageHeight}"),
|
||||
|
@ -278,19 +247,13 @@ class _ViewerDetailPaneState extends State<ViewerDetailPane> {
|
|||
)
|
||||
else
|
||||
ListTile(
|
||||
leading: Icon(
|
||||
Icons.aspect_ratio,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
leading: const Icon(Icons.aspect_ratio),
|
||||
title: Text(_byteSizeToString(_file!.contentLength ?? 0)),
|
||||
),
|
||||
if (_model != null)
|
||||
ListTile(
|
||||
leading: ListTileCenterLeading(
|
||||
child: Icon(
|
||||
Icons.camera_outlined,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
leading: const ListTileCenterLeading(
|
||||
child: Icon(Icons.camera_outlined),
|
||||
),
|
||||
title: Text(_model!),
|
||||
subtitle: _buildCameraSubtitle()
|
||||
|
@ -298,18 +261,12 @@ class _ViewerDetailPaneState extends State<ViewerDetailPane> {
|
|||
),
|
||||
if (_location?.name != null)
|
||||
ListTile(
|
||||
leading: ListTileCenterLeading(
|
||||
child: Icon(
|
||||
Icons.location_on_outlined,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
leading: const ListTileCenterLeading(
|
||||
child: Icon(Icons.location_on_outlined),
|
||||
),
|
||||
title: Text(L10n.global().gpsPlaceText(_location!.name!)),
|
||||
subtitle: _location!.toSubtitle()?.run((obj) => Text(obj)),
|
||||
trailing: Icon(
|
||||
Icons.info_outline,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
trailing: const Icon(Icons.info_outline),
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
|
@ -556,6 +513,10 @@ class _DetailPaneButton extends StatelessWidget {
|
|||
build(BuildContext context) {
|
||||
return TextButton(
|
||||
onPressed: onPressed,
|
||||
style: ButtonStyle(
|
||||
foregroundColor:
|
||||
MaterialStateProperty.all(Theme.of(context).colorScheme.onSurface),
|
||||
),
|
||||
child: SizedBox(
|
||||
width: 96,
|
||||
height: 96,
|
||||
|
@ -563,18 +524,12 @@ class _DetailPaneButton extends StatelessWidget {
|
|||
padding: const EdgeInsets.fromLTRB(8, 16, 8, 0),
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
Icon(icon),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
label,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
|
||||
class ZoomMenuButton extends StatelessWidget {
|
||||
const ZoomMenuButton({
|
||||
|
@ -67,19 +66,17 @@ class _PopupMenuZoomState extends State<_PopupMenuZoom> {
|
|||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
child: Slider(
|
||||
value: _value.toDouble(),
|
||||
min: widget.minValue.toDouble(),
|
||||
max: widget.maxValue.toDouble(),
|
||||
divisions: (widget.maxValue - widget.minValue).round(),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_value = value.round();
|
||||
});
|
||||
widget.onChanged?.call(_value);
|
||||
},
|
||||
),
|
||||
return Slider(
|
||||
value: _value.toDouble(),
|
||||
min: widget.minValue.toDouble(),
|
||||
max: widget.maxValue.toDouble(),
|
||||
divisions: (widget.maxValue - widget.minValue).round(),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_value = value.round();
|
||||
});
|
||||
widget.onChanged?.call(_value);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue