#68 settings: show/hide motion photo icon on thumbnails
This commit is contained in:
parent
466d150e49
commit
db863d68e3
9 changed files with 69 additions and 31 deletions
|
@ -652,6 +652,8 @@
|
|||
"@settingsSectionThumbnails": {},
|
||||
"settingsThumbnailShowLocationIcon": "Show location icon",
|
||||
"@settingsThumbnailShowLocationIcon": {},
|
||||
"settingsThumbnailShowMotionPhotoIcon": "Show motion photo icon",
|
||||
"@settingsThumbnailShowMotionPhotoIcon": {},
|
||||
"settingsThumbnailShowRawIcon": "Show raw icon",
|
||||
"@settingsThumbnailShowRawIcon": {},
|
||||
"settingsThumbnailShowVideoDuration": "Show video duration",
|
||||
|
|
|
@ -314,6 +314,7 @@
|
|||
|
||||
"settingsSectionThumbnails": "섬네일",
|
||||
"settingsThumbnailShowLocationIcon": "위치 아이콘 표시",
|
||||
"settingsThumbnailShowMotionPhotoIcon": "모션 포토 아이콘 표시",
|
||||
"settingsThumbnailShowRawIcon": "Raw 아이콘 표시",
|
||||
"settingsThumbnailShowVideoDuration": "동영상 길이 표시",
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ class SettingsDefaults {
|
|||
EntrySetAction.delete,
|
||||
];
|
||||
static const showThumbnailLocation = true;
|
||||
static const showThumbnailMotionPhoto = true;
|
||||
static const showThumbnailRaw = true;
|
||||
static const showThumbnailVideoDuration = true;
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ class Settings extends ChangeNotifier {
|
|||
static const collectionSortFactorKey = 'collection_sort_factor';
|
||||
static const collectionSelectionQuickActionsKey = 'collection_selection_quick_actions';
|
||||
static const showThumbnailLocationKey = 'show_thumbnail_location';
|
||||
static const showThumbnailMotionPhotoKey = 'show_thumbnail_motion_photo';
|
||||
static const showThumbnailRawKey = 'show_thumbnail_raw';
|
||||
static const showThumbnailVideoDurationKey = 'show_thumbnail_video_duration';
|
||||
|
||||
|
@ -241,6 +242,10 @@ class Settings extends ChangeNotifier {
|
|||
|
||||
set showThumbnailLocation(bool newValue) => setAndNotify(showThumbnailLocationKey, newValue);
|
||||
|
||||
bool get showThumbnailMotionPhoto => getBoolOrDefault(showThumbnailMotionPhotoKey, SettingsDefaults.showThumbnailMotionPhoto);
|
||||
|
||||
set showThumbnailMotionPhoto(bool newValue) => setAndNotify(showThumbnailMotionPhotoKey, newValue);
|
||||
|
||||
bool get showThumbnailRaw => getBoolOrDefault(showThumbnailRawKey, SettingsDefaults.showThumbnailRaw);
|
||||
|
||||
set showThumbnailRaw(bool newValue) => setAndNotify(showThumbnailRawKey, newValue);
|
||||
|
@ -494,6 +499,7 @@ class Settings extends ChangeNotifier {
|
|||
case isCrashlyticsEnabledKey:
|
||||
case mustBackTwiceToExitKey:
|
||||
case showThumbnailLocationKey:
|
||||
case showThumbnailMotionPhotoKey:
|
||||
case showThumbnailRawKey:
|
||||
case showThumbnailVideoDurationKey:
|
||||
case showOverlayMinimapKey:
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:aves/model/selection.dart';
|
||||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/widgets/common/grid/theme.dart';
|
||||
import 'package:aves/widgets/common/identity/aves_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
@ -31,7 +30,6 @@ class GridItemSelectionOverlay<T> extends StatelessWidget {
|
|||
? OverlayIcon(
|
||||
key: ValueKey(isSelected),
|
||||
icon: isSelected ? AIcons.selected : AIcons.unselected,
|
||||
size: context.select<GridThemeData, double>((t) => t.iconSize),
|
||||
)
|
||||
: const SizedBox.shrink();
|
||||
child = AnimatedSwitcher(
|
||||
|
|
|
@ -28,6 +28,7 @@ class GridTheme extends StatelessWidget {
|
|||
fontSize: fontSize,
|
||||
highlightBorderWidth: highlightBorderWidth,
|
||||
showLocation: showLocation ?? settings.showThumbnailLocation,
|
||||
showMotionPhoto: settings.showThumbnailMotionPhoto,
|
||||
showRaw: settings.showThumbnailRaw,
|
||||
showVideoDuration: settings.showThumbnailVideoDuration,
|
||||
);
|
||||
|
@ -39,13 +40,14 @@ class GridTheme extends StatelessWidget {
|
|||
|
||||
class GridThemeData {
|
||||
final double iconSize, fontSize, highlightBorderWidth;
|
||||
final bool showLocation, showRaw, showVideoDuration;
|
||||
final bool showLocation, showMotionPhoto, showRaw, showVideoDuration;
|
||||
|
||||
const GridThemeData({
|
||||
required this.iconSize,
|
||||
required this.fontSize,
|
||||
required this.highlightBorderWidth,
|
||||
required this.showLocation,
|
||||
required this.showMotionPhoto,
|
||||
required this.showRaw,
|
||||
required this.showVideoDuration,
|
||||
});
|
||||
|
|
|
@ -24,7 +24,6 @@ class VideoIcon extends StatelessWidget {
|
|||
final showDuration = gridTheme.showVideoDuration;
|
||||
Widget child = OverlayIcon(
|
||||
icon: entry.is360 ? AIcons.threeSixty : AIcons.videoThumb,
|
||||
size: gridTheme.iconSize,
|
||||
text: showDuration ? entry.durationText : null,
|
||||
iconScale: entry.is360 && showDuration ? .9 : 1,
|
||||
);
|
||||
|
@ -44,12 +43,13 @@ class VideoIcon extends StatelessWidget {
|
|||
class AnimatedImageIcon extends StatelessWidget {
|
||||
const AnimatedImageIcon({Key? key}) : super(key: key);
|
||||
|
||||
static const scale = .8;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return OverlayIcon(
|
||||
return const OverlayIcon(
|
||||
icon: AIcons.animated,
|
||||
size: context.select<GridThemeData, double>((t) => t.iconSize),
|
||||
iconScale: .8,
|
||||
iconScale: scale,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -59,9 +59,8 @@ class GeotiffIcon extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return OverlayIcon(
|
||||
return const OverlayIcon(
|
||||
icon: AIcons.geo,
|
||||
size: context.select<GridThemeData, double>((t) => t.iconSize),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -71,9 +70,8 @@ class SphericalImageIcon extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return OverlayIcon(
|
||||
return const OverlayIcon(
|
||||
icon: AIcons.threeSixty,
|
||||
size: context.select<GridThemeData, double>((t) => t.iconSize),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -83,9 +81,8 @@ class GpsIcon extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return OverlayIcon(
|
||||
return const OverlayIcon(
|
||||
icon: AIcons.location,
|
||||
size: context.select<GridThemeData, double>((t) => t.iconSize),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -95,9 +92,22 @@ class RawIcon extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return OverlayIcon(
|
||||
return const OverlayIcon(
|
||||
icon: AIcons.raw,
|
||||
size: context.select<GridThemeData, double>((t) => t.iconSize),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MotionPhotoIcon extends StatelessWidget {
|
||||
const MotionPhotoIcon({Key? key}) : super(key: key);
|
||||
|
||||
static const scale = .8;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const OverlayIcon(
|
||||
icon: AIcons.motionPhoto,
|
||||
iconScale: scale,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +115,8 @@ class RawIcon extends StatelessWidget {
|
|||
class MultiPageIcon extends StatelessWidget {
|
||||
final AvesEntry entry;
|
||||
|
||||
static const scale = .8;
|
||||
|
||||
const MultiPageIcon({
|
||||
Key? key,
|
||||
required this.entry,
|
||||
|
@ -112,27 +124,19 @@ class MultiPageIcon extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
IconData icon;
|
||||
String? text;
|
||||
if (entry.isMotionPhoto) {
|
||||
icon = AIcons.motionPhoto;
|
||||
} else {
|
||||
if (entry.isBurst) {
|
||||
text = '${entry.burstEntries?.length}';
|
||||
}
|
||||
icon = AIcons.multiPage;
|
||||
}
|
||||
final gridTheme = context.watch<GridThemeData>();
|
||||
final child = OverlayIcon(
|
||||
icon: icon,
|
||||
size: gridTheme.iconSize,
|
||||
iconScale: .8,
|
||||
icon: AIcons.multiPage,
|
||||
iconScale: scale,
|
||||
text: text,
|
||||
);
|
||||
return DefaultTextStyle(
|
||||
style: TextStyle(
|
||||
color: Colors.grey.shade200,
|
||||
fontSize: gridTheme.fontSize,
|
||||
fontSize: context.select<GridThemeData, double>((t) => t.fontSize),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
|
@ -141,20 +145,19 @@ class MultiPageIcon extends StatelessWidget {
|
|||
|
||||
class OverlayIcon extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final double size;
|
||||
final String? text;
|
||||
final double iconScale;
|
||||
|
||||
const OverlayIcon({
|
||||
Key? key,
|
||||
required this.icon,
|
||||
required this.size,
|
||||
this.iconScale = 1,
|
||||
this.text,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final size = context.select<GridThemeData, double>((t) => t.iconSize);
|
||||
final iconChild = Icon(icon, size: size);
|
||||
final iconBox = SizedBox(
|
||||
width: size,
|
||||
|
|
|
@ -31,7 +31,10 @@ class ThumbnailEntryOverlay extends StatelessWidget {
|
|||
if (entry.isGeotiff) const GeotiffIcon(),
|
||||
if (entry.is360) const SphericalImageIcon(),
|
||||
],
|
||||
if (entry.isMultiPage) MultiPageIcon(entry: entry),
|
||||
if (entry.isMultiPage) ...[
|
||||
if (entry.isMotionPhoto && context.select<GridThemeData, bool>((t) => t.showMotionPhoto)) const MotionPhotoIcon(),
|
||||
if (!entry.isMotionPhoto) MultiPageIcon(entry: entry),
|
||||
],
|
||||
];
|
||||
if (children.isEmpty) return const SizedBox.shrink();
|
||||
if (children.length == 1) return children.first;
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:aves/theme/icons.dart';
|
|||
import 'package:aves/utils/color_utils.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
|
||||
import 'package:aves/widgets/common/identity/aves_icons.dart';
|
||||
import 'package:aves/widgets/settings/common/tile_leading.dart';
|
||||
import 'package:aves/widgets/settings/thumbnails/selection_actions_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -20,6 +21,7 @@ class ThumbnailsSection extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final currentShowThumbnailLocation = context.select<Settings, bool>((s) => s.showThumbnailLocation);
|
||||
final currentShowThumbnailMotionPhoto = context.select<Settings, bool>((s) => s.showThumbnailMotionPhoto);
|
||||
final currentShowThumbnailRaw = context.select<Settings, bool>((s) => s.showThumbnailRaw);
|
||||
final currentShowThumbnailVideoDuration = context.select<Settings, bool>((s) => s.showThumbnailVideoDuration);
|
||||
|
||||
|
@ -53,6 +55,26 @@ class ThumbnailsSection extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: currentShowThumbnailMotionPhoto,
|
||||
onChanged: (v) => settings.showThumbnailMotionPhoto = v,
|
||||
title: Row(
|
||||
children: [
|
||||
Expanded(child: Text(context.l10n.settingsThumbnailShowMotionPhotoIcon)),
|
||||
AnimatedOpacity(
|
||||
opacity: opacityFor(currentShowThumbnailMotionPhoto),
|
||||
duration: Durations.toggleableTransitionAnimation,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: iconSize * (1 - MotionPhotoIcon.scale) / 2),
|
||||
child: Icon(
|
||||
AIcons.motionPhoto,
|
||||
size: iconSize * MotionPhotoIcon.scale,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: currentShowThumbnailRaw,
|
||||
onChanged: (v) => settings.showThumbnailRaw = v,
|
||||
|
|
Loading…
Reference in a new issue