#24 viewer: added option to show/hide info on overlay

This commit is contained in:
Thibault Deckers 2021-01-12 12:54:53 +09:00
parent 80d7de43ed
commit 6ea9923a92
4 changed files with 113 additions and 75 deletions

View file

@ -47,6 +47,7 @@ class Settings extends ChangeNotifier {
// viewer // viewer
static const showOverlayMinimapKey = 'show_overlay_minimap'; static const showOverlayMinimapKey = 'show_overlay_minimap';
static const showOverlayInfoKey = 'show_overlay_info';
static const showOverlayShootingDetailsKey = 'show_overlay_shooting_details'; static const showOverlayShootingDetailsKey = 'show_overlay_shooting_details';
// info // info
@ -166,6 +167,10 @@ class Settings extends ChangeNotifier {
set showOverlayMinimap(bool newValue) => setAndNotify(showOverlayMinimapKey, newValue); set showOverlayMinimap(bool newValue) => setAndNotify(showOverlayMinimapKey, newValue);
bool get showOverlayInfo => getBoolOrDefault(showOverlayInfoKey, true);
set showOverlayInfo(bool newValue) => setAndNotify(showOverlayInfoKey, newValue);
bool get showOverlayShootingDetails => getBoolOrDefault(showOverlayShootingDetailsKey, true); bool get showOverlayShootingDetails => getBoolOrDefault(showOverlayShootingDetailsKey, true);
set showOverlayShootingDetails(bool newValue) => setAndNotify(showOverlayShootingDetailsKey, newValue); set showOverlayShootingDetails(bool newValue) => setAndNotify(showOverlayShootingDetailsKey, newValue);

View file

@ -5,18 +5,25 @@ import 'package:flutter/material.dart';
final _filter = ImageFilter.blur(sigmaX: 4, sigmaY: 4); final _filter = ImageFilter.blur(sigmaX: 4, sigmaY: 4);
class BlurredRect extends StatelessWidget { class BlurredRect extends StatelessWidget {
final bool enabled;
final Widget child; final Widget child;
const BlurredRect({Key key, this.child}) : super(key: key); const BlurredRect({
Key key,
this.enabled = true,
this.child,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ClipRect( return enabled
? ClipRect(
child: BackdropFilter( child: BackdropFilter(
filter: _filter, filter: _filter,
child: child, child: child,
), ),
); )
: child;
} }
} }

View file

@ -25,12 +25,20 @@ class _SettingsPageState extends State<SettingsPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context);
return MediaQueryDataProvider( return MediaQueryDataProvider(
child: Scaffold( child: Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('Settings'), title: Text('Settings'),
), ),
body: SafeArea( body: Theme(
data: theme.copyWith(
textTheme: theme.textTheme.copyWith(
// dense style font for tile subtitles, without modifying title font
bodyText2: TextStyle(fontSize: 12),
),
),
child: SafeArea(
child: Consumer<Settings>( child: Consumer<Settings>(
builder: (context, settings, child) => AnimationLimiter( builder: (context, settings, child) => AnimationLimiter(
child: ListView( child: ListView(
@ -58,6 +66,7 @@ class _SettingsPageState extends State<SettingsPage> {
), ),
), ),
), ),
),
); );
} }
@ -188,9 +197,15 @@ class _SettingsPageState extends State<SettingsPage> {
onChanged: (v) => settings.showOverlayMinimap = v, onChanged: (v) => settings.showOverlayMinimap = v,
title: Text('Show minimap'), title: Text('Show minimap'),
), ),
SwitchListTile(
value: settings.showOverlayInfo,
onChanged: (v) => settings.showOverlayInfo = v,
title: Text('Show information'),
subtitle: Text('Show title, date, location, etc.'),
),
SwitchListTile( SwitchListTile(
value: settings.showOverlayShootingDetails, value: settings.showOverlayShootingDetails,
onChanged: (v) => settings.showOverlayShootingDetails = v, onChanged: settings.showOverlayInfo ? (v) => settings.showOverlayShootingDetails = v : null,
title: Text('Show shooting details'), title: Text('Show shooting details'),
), ),
], ],

View file

@ -51,6 +51,8 @@ class _ViewerBottomOverlayState extends State<ViewerBottomOverlay> {
return index < entries.length ? entries[index] : null; return index < entries.length ? entries[index] : null;
} }
MultiPageController get multiPageController => widget.multiPageController;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -71,7 +73,9 @@ class _ViewerBottomOverlayState extends State<ViewerBottomOverlay> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final hasEdgeContent = settings.showOverlayInfo || multiPageController != null;
return BlurredRect( return BlurredRect(
enabled: hasEdgeContent,
child: Selector<MediaQueryData, Tuple3<double, EdgeInsets, EdgeInsets>>( child: Selector<MediaQueryData, Tuple3<double, EdgeInsets, EdgeInsets>>(
selector: (c, mq) => Tuple3(mq.size.width, mq.viewInsets, mq.viewPadding), selector: (c, mq) => Tuple3(mq.size.width, mq.viewInsets, mq.viewPadding),
builder: (c, mq, child) { builder: (c, mq, child) {
@ -84,7 +88,7 @@ class _ViewerBottomOverlayState extends State<ViewerBottomOverlay> {
final availableWidth = mqWidth - viewPadding.horizontal; final availableWidth = mqWidth - viewPadding.horizontal;
return Container( return Container(
color: kOverlayBackgroundColor, color: hasEdgeContent ? kOverlayBackgroundColor: Colors.transparent,
padding: viewInsets + viewPadding.copyWith(top: 0), padding: viewInsets + viewPadding.copyWith(top: 0),
child: FutureBuilder<OverlayMetadata>( child: FutureBuilder<OverlayMetadata>(
future: _detailLoader, future: _detailLoader,
@ -100,7 +104,7 @@ class _ViewerBottomOverlayState extends State<ViewerBottomOverlay> {
details: _lastDetails, details: _lastDetails,
position: widget.showPosition ? '${widget.index + 1}/${widget.entries.length}' : null, position: widget.showPosition ? '${widget.index + 1}/${widget.entries.length}' : null,
availableWidth: availableWidth, availableWidth: availableWidth,
multiPageController: widget.multiPageController, multiPageController: multiPageController,
); );
}, },
), ),
@ -136,8 +140,6 @@ class _BottomOverlayContent extends AnimatedWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final infoMaxWidth = availableWidth - infoPadding.horizontal;
return DefaultTextStyle( return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2.copyWith( style: Theme.of(context).textTheme.bodyText2.copyWith(
shadows: [Constants.embossShadow], shadows: [Constants.embossShadow],
@ -150,12 +152,42 @@ class _BottomOverlayContent extends AnimatedWidget {
child: Selector<MediaQueryData, Orientation>( child: Selector<MediaQueryData, Orientation>(
selector: (c, mq) => mq.orientation, selector: (c, mq) => mq.orientation,
builder: (c, orientation, child) { builder: (c, orientation, child) {
Widget infoColumn;
if (settings.showOverlayInfo) {
infoColumn = _buildInfoColumn(orientation);
}
if (multiPageController != null) {
infoColumn = Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MultiPageOverlay(
entry: entry,
controller: multiPageController,
availableWidth: availableWidth,
),
if (infoColumn != null) infoColumn,
],
);
}
return infoColumn ?? SizedBox();
},
),
),
);
}
Widget _buildInfoColumn(Orientation orientation) {
final infoMaxWidth = availableWidth - infoPadding.horizontal;
final twoColumns = orientation == Orientation.landscape && infoMaxWidth / 2 > _subRowMinWidth; final twoColumns = orientation == Orientation.landscape && infoMaxWidth / 2 > _subRowMinWidth;
final subRowWidth = twoColumns ? min(_subRowMinWidth, infoMaxWidth / 2) : infoMaxWidth; final subRowWidth = twoColumns ? min(_subRowMinWidth, infoMaxWidth / 2) : infoMaxWidth;
final positionTitle = _PositionTitleRow(entry: entry, collectionPosition: position, multiPageController: multiPageController); final positionTitle = _PositionTitleRow(entry: entry, collectionPosition: position, multiPageController: multiPageController);
final hasShootingDetails = details != null && !details.isEmpty && settings.showOverlayShootingDetails; final hasShootingDetails = details != null && !details.isEmpty && settings.showOverlayShootingDetails;
Widget infoColumn = Padding( return Padding(
padding: infoPadding, padding: infoPadding,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@ -192,27 +224,6 @@ class _BottomOverlayContent extends AnimatedWidget {
], ],
), ),
); );
if (multiPageController != null) {
infoColumn = Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MultiPageOverlay(
entry: entry,
controller: multiPageController,
availableWidth: availableWidth,
),
infoColumn,
],
);
}
return infoColumn;
},
),
),
);
} }
Widget _buildSoloLocationRow() => AnimatedSwitcher( Widget _buildSoloLocationRow() => AnimatedSwitcher(