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:
parent
7aab84f2d9
commit
ff3cde4dfb
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user