1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-25 10:43:13 +02:00

feat(mobile): Fullscreen image effects (#1529)

* fullscreen image effects

* toggles app bar instead of hides on tap

* edgeToEdge mode to render beneath navbar on android

* fixed appbar size

* fixed safearea for video and added opacity to appbar in gallery

* wrapped in black container to fix artifact on iOS

* changed to black

* added scaffold back woops
This commit is contained in:
martyfuhry 2023-02-03 11:26:05 -05:00 committed by GitHub
parent 7aab84f2d9
commit ff3cde4dfb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 41 deletions

View File

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_displaymode/flutter_displaymode.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
@ -155,6 +156,8 @@ class ImmichAppState extends ConsumerState<ImmichApp>
var router = ref.watch(appRouterProvider);
ref.watch(releaseInfoProvider.notifier).checkGithubReleaseInfo();
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
return MaterialApp(
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,

View File

@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/shared/models/asset.dart';
class TopControlAppBar extends HookConsumerWidget with PreferredSizeWidget {
class TopControlAppBar extends HookConsumerWidget {
const TopControlAppBar({
Key? key,
required this.asset,
@ -31,7 +31,6 @@ class TopControlAppBar extends HookConsumerWidget with PreferredSizeWidget {
return AppBar(
foregroundColor: Colors.grey[100],
toolbarHeight: 60,
backgroundColor: Colors.transparent,
leading: IconButton(
onPressed: () {
@ -120,7 +119,4 @@ class TopControlAppBar extends HookConsumerWidget with PreferredSizeWidget {
],
);
}
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}

View File

@ -48,6 +48,7 @@ class GalleryViewerPage extends HookConsumerWidget {
final isLoadPreview = useState(AppSettingsEnum.loadPreview.defaultValue);
final isLoadOriginal = useState(AppSettingsEnum.loadOriginal.defaultValue);
final isZoomed = useState<bool>(false);
final showAppBar = useState<bool>(true);
final indexOfAsset = useState(assetList.indexOf(asset));
final isPlayingMotionVideo = useState(false);
late Offset localPosition;
@ -227,36 +228,50 @@ class GalleryViewerPage extends HookConsumerWidget {
}
}
buildAppBar() {
return AnimatedOpacity(
duration: const Duration(milliseconds: 100),
opacity: (showAppBar.value || !isZoomed.value) ? 1.0 : 0.0,
child: Container(
color: Colors.black.withOpacity(0.4),
child: TopControlAppBar(
isPlayingMotionVideo: isPlayingMotionVideo.value,
asset: assetList[indexOfAsset.value],
onMoreInfoPressed: () {
showInfo();
},
onDownloadPressed: assetList[indexOfAsset.value].isLocal
? null
: () {
ref.watch(imageViewerStateProvider.notifier).downloadAsset(
assetList[indexOfAsset.value].remote!,
context,
);
},
onSharePressed: () {
ref
.watch(imageViewerStateProvider.notifier)
.shareAsset(assetList[indexOfAsset.value], context);
},
onToggleMotionVideo: (() {
isPlayingMotionVideo.value = !isPlayingMotionVideo.value;
}),
onDeletePressed: () => handleDelete((assetList[indexOfAsset.value])),
onAddToAlbumPressed: () => addToAlbum(assetList[indexOfAsset.value]),
),
),
);
}
return Scaffold(
backgroundColor: Colors.black,
appBar: TopControlAppBar(
isPlayingMotionVideo: isPlayingMotionVideo.value,
asset: assetList[indexOfAsset.value],
onMoreInfoPressed: () {
showInfo();
},
onDownloadPressed: assetList[indexOfAsset.value].isLocal
? null
: () {
ref.watch(imageViewerStateProvider.notifier).downloadAsset(
assetList[indexOfAsset.value].remote!,
context,
);
},
onSharePressed: () {
ref
.watch(imageViewerStateProvider.notifier)
.shareAsset(assetList[indexOfAsset.value], context);
},
onToggleMotionVideo: (() {
isPlayingMotionVideo.value = !isPlayingMotionVideo.value;
}),
onDeletePressed: () => handleDelete((assetList[indexOfAsset.value])),
onAddToAlbumPressed: () => addToAlbum(assetList[indexOfAsset.value]),
),
body: SafeArea(
child: PhotoViewGallery.builder(
scaleStateChangedCallback: (state) => isZoomed.value = state != PhotoViewScaleState.initial,
body: Stack(
children: [
PhotoViewGallery.builder(
scaleStateChangedCallback: (state) {
isZoomed.value = state != PhotoViewScaleState.initial;
showAppBar.value = !isZoomed.value;
},
pageController: controller,
scrollPhysics: isZoomed.value
? const NeverScrollableScrollPhysics() // Don't allow paging while scrolled in
@ -327,6 +342,7 @@ class GalleryViewerPage extends HookConsumerWidget {
return PhotoViewGalleryPageOptions(
onDragStart: (_, details, __) => localPosition = details.localPosition,
onDragUpdate: (_, details, __) => handleSwipeUpDown(details),
onTapDown: (_, __, ___) => showAppBar.value = !showAppBar.value,
imageProvider: provider,
heroAttributes: PhotoViewHeroAttributes(tag: assetList[index].id),
minScale: PhotoViewComputedScale.contained,
@ -335,20 +351,32 @@ class GalleryViewerPage extends HookConsumerWidget {
return PhotoViewGalleryPageOptions.customChild(
onDragStart: (_, details, __) => localPosition = details.localPosition,
onDragUpdate: (_, details, __) => handleSwipeUpDown(details),
onTapDown: (_, __, ___) => showAppBar.value = !showAppBar.value,
heroAttributes: PhotoViewHeroAttributes(tag: assetList[index].id),
child: VideoViewerPage(
asset: assetList[index],
isMotionVideo: isPlayingMotionVideo.value,
onVideoEnded: () {
if (isPlayingMotionVideo.value) {
isPlayingMotionVideo.value = false;
}
},
maxScale: 1.0,
minScale: 1.0,
child: SafeArea(
child: VideoViewerPage(
asset: assetList[index],
isMotionVideo: isPlayingMotionVideo.value,
onVideoEnded: () {
if (isPlayingMotionVideo.value) {
isPlayingMotionVideo.value = false;
}
},
),
),
);
}
},
),
Positioned(
top: 0,
left: 0,
right: 0,
child: buildAppBar(),
),
],
),
);
}