mirror of
https://github.com/immich-app/immich.git
synced 2024-12-25 10:43:13 +02:00
Enable swiping between assets (#381)
Enable swiping between assets (#381) Co-authored-by: Alex <alex.tran1502@gmail.com> Co-authored-by: Malte Kiefer <59220985+MalteKiefer@users.noreply.github.com> Co-authored-by: Matthias Rupp <matthias.rupp@posteo.de>
This commit is contained in:
parent
e8d1f89a47
commit
8c184dc4d4
2
mobile/.gitignore
vendored
2
mobile/.gitignore
vendored
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
# Flutter/Dart/Pub related
|
# Flutter/Dart/Pub related
|
||||||
**/doc/api/
|
**/doc/api/
|
||||||
**/ios/Flutter/.last_build_id
|
**/ios/
|
||||||
.dart_tool/
|
.dart_tool/
|
||||||
.flutter-plugins
|
.flutter-plugins
|
||||||
.flutter-plugins-dependencies
|
.flutter-plugins-dependencies
|
||||||
|
@ -17,7 +17,6 @@ import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
|||||||
import 'package:immich_mobile/shared/providers/websocket.provider.dart';
|
import 'package:immich_mobile/shared/providers/websocket.provider.dart';
|
||||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||||
import 'package:immich_mobile/shared/views/version_announcement_overlay.dart';
|
import 'package:immich_mobile/shared/views/version_announcement_overlay.dart';
|
||||||
|
|
||||||
import 'constants/hive_box.dart';
|
import 'constants/hive_box.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
|
@ -20,7 +20,9 @@ class AlbumNotifier extends StateNotifier<List<AlbumResponseDto>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<AlbumResponseDto?> createAlbum(
|
Future<AlbumResponseDto?> createAlbum(
|
||||||
String albumTitle, Set<AssetResponseDto> assets) async {
|
String albumTitle,
|
||||||
|
Set<AssetResponseDto> assets,
|
||||||
|
) async {
|
||||||
AlbumResponseDto? album =
|
AlbumResponseDto? album =
|
||||||
await _albumService.createAlbum(albumTitle, assets, []);
|
await _albumService.createAlbum(albumTitle, assets, []);
|
||||||
|
|
||||||
|
@ -12,8 +12,13 @@ import 'package:openapi/api.dart';
|
|||||||
|
|
||||||
class AlbumViewerThumbnail extends HookConsumerWidget {
|
class AlbumViewerThumbnail extends HookConsumerWidget {
|
||||||
final AssetResponseDto asset;
|
final AssetResponseDto asset;
|
||||||
|
final List<AssetResponseDto> assetList;
|
||||||
|
|
||||||
const AlbumViewerThumbnail({Key? key, required this.asset}) : super(key: key);
|
const AlbumViewerThumbnail({
|
||||||
|
Key? key,
|
||||||
|
required this.asset,
|
||||||
|
required this.assetList,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@ -28,25 +33,13 @@ class AlbumViewerThumbnail extends HookConsumerWidget {
|
|||||||
ref.watch(assetSelectionProvider).isMultiselectEnable;
|
ref.watch(assetSelectionProvider).isMultiselectEnable;
|
||||||
|
|
||||||
_viewAsset() {
|
_viewAsset() {
|
||||||
if (asset.type == AssetTypeEnum.IMAGE) {
|
AutoRouter.of(context).push(
|
||||||
AutoRouter.of(context).push(
|
GalleryViewerRoute(
|
||||||
ImageViewerRoute(
|
asset: asset,
|
||||||
imageUrl:
|
assetList: assetList,
|
||||||
'${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}&isThumb=false',
|
thumbnailRequestUrl: thumbnailRequestUrl,
|
||||||
heroTag: asset.id,
|
),
|
||||||
thumbnailUrl: thumbnailRequestUrl,
|
);
|
||||||
asset: asset,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
AutoRouter.of(context).push(
|
|
||||||
VideoViewerRoute(
|
|
||||||
videoUrl:
|
|
||||||
'${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}',
|
|
||||||
asset: asset,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BoxBorder drawBorderColor() {
|
BoxBorder drawBorderColor() {
|
||||||
|
@ -29,9 +29,7 @@ class AlbumViewerPage extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
FocusNode titleFocusNode = useFocusNode();
|
FocusNode titleFocusNode = useFocusNode();
|
||||||
ScrollController scrollController = useScrollController();
|
ScrollController scrollController = useScrollController();
|
||||||
|
var albumInfo = ref.watch(sharedAlbumDetailProvider(albumId));
|
||||||
AsyncValue<AlbumResponseDto?> albumInfo =
|
|
||||||
ref.watch(sharedAlbumDetailProvider(albumId));
|
|
||||||
|
|
||||||
final userId = ref.watch(authenticationProvider).userId;
|
final userId = ref.watch(authenticationProvider).userId;
|
||||||
|
|
||||||
@ -200,7 +198,10 @@ class AlbumViewerPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(BuildContext context, int index) {
|
(BuildContext context, int index) {
|
||||||
return AlbumViewerThumbnail(asset: albumInfo.assets[index]);
|
return AlbumViewerThumbnail(
|
||||||
|
asset: albumInfo.assets[index],
|
||||||
|
assetList: albumInfo.assets,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
childCount: albumInfo.assets.length,
|
childCount: albumInfo.assets.length,
|
||||||
),
|
),
|
||||||
|
@ -15,7 +15,6 @@ class _RemotePhotoViewState extends State<RemotePhotoView> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool allowMoving = _status == _RemoteImageStatus.full;
|
bool allowMoving = _status == _RemoteImageStatus.full;
|
||||||
|
|
||||||
return PhotoView(
|
return PhotoView(
|
||||||
imageProvider: _imageProvider,
|
imageProvider: _imageProvider,
|
||||||
minScale: PhotoViewComputedScale.contained,
|
minScale: PhotoViewComputedScale.contained,
|
||||||
@ -32,8 +31,9 @@ class _RemotePhotoViewState extends State<RemotePhotoView> {
|
|||||||
PhotoViewControllerValue controllerValue,
|
PhotoViewControllerValue controllerValue,
|
||||||
) {
|
) {
|
||||||
// Disable swipe events when zoomed in
|
// Disable swipe events when zoomed in
|
||||||
if (_zoomedIn) return;
|
if (_zoomedIn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (controllerValue.position.dy > swipeThreshold) {
|
if (controllerValue.position.dy > swipeThreshold) {
|
||||||
widget.onSwipeDown();
|
widget.onSwipeDown();
|
||||||
} else if (controllerValue.position.dy < -swipeThreshold) {
|
} else if (controllerValue.position.dy < -swipeThreshold) {
|
||||||
@ -42,7 +42,14 @@ class _RemotePhotoViewState extends State<RemotePhotoView> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _scaleStateChanged(PhotoViewScaleState state) {
|
void _scaleStateChanged(PhotoViewScaleState state) {
|
||||||
_zoomedIn = state == PhotoViewScaleState.zoomedIn;
|
// _onScaleListener;
|
||||||
|
_zoomedIn = state != PhotoViewScaleState.initial;
|
||||||
|
if (_zoomedIn) {
|
||||||
|
widget.isZoomedListener.value = true;
|
||||||
|
} else {
|
||||||
|
widget.isZoomedListener.value = false;
|
||||||
|
}
|
||||||
|
widget.isZoomedFunction();
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedNetworkImageProvider _authorizedImageProvider(String url) {
|
CachedNetworkImageProvider _authorizedImageProvider(String url) {
|
||||||
@ -107,6 +114,8 @@ class RemotePhotoView extends StatefulWidget {
|
|||||||
required this.thumbnailUrl,
|
required this.thumbnailUrl,
|
||||||
required this.imageUrl,
|
required this.imageUrl,
|
||||||
required this.authToken,
|
required this.authToken,
|
||||||
|
required this.isZoomedFunction,
|
||||||
|
required this.isZoomedListener,
|
||||||
required this.onSwipeDown,
|
required this.onSwipeDown,
|
||||||
required this.onSwipeUp,
|
required this.onSwipeUp,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -117,6 +126,9 @@ class RemotePhotoView extends StatefulWidget {
|
|||||||
|
|
||||||
final void Function() onSwipeDown;
|
final void Function() onSwipeDown;
|
||||||
final void Function() onSwipeUp;
|
final void Function() onSwipeUp;
|
||||||
|
final void Function() isZoomedFunction;
|
||||||
|
|
||||||
|
final ValueNotifier<bool> isZoomedListener;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() {
|
State<StatefulWidget> createState() {
|
||||||
|
134
mobile/lib/modules/asset_viewer/views/gallery_viewer.dart
Normal file
134
mobile/lib/modules/asset_viewer/views/gallery_viewer.dart
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:flutter_swipe_detector/flutter_swipe_detector.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/constants/hive_box.dart';
|
||||||
|
import 'package:immich_mobile/modules/asset_viewer/providers/image_viewer_page_state.provider.dart';
|
||||||
|
import 'package:immich_mobile/modules/asset_viewer/ui/exif_bottom_sheet.dart';
|
||||||
|
import 'package:immich_mobile/modules/asset_viewer/ui/top_control_app_bar.dart';
|
||||||
|
import 'package:immich_mobile/modules/asset_viewer/views/image_viewer_page.dart';
|
||||||
|
import 'package:immich_mobile/modules/asset_viewer/views/video_viewer_page.dart';
|
||||||
|
import 'package:immich_mobile/modules/home/services/asset.service.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class GalleryViewerPage extends HookConsumerWidget {
|
||||||
|
late List<AssetResponseDto> assetList;
|
||||||
|
final AssetResponseDto asset;
|
||||||
|
final String thumbnailRequestUrl;
|
||||||
|
|
||||||
|
GalleryViewerPage({
|
||||||
|
Key? key,
|
||||||
|
required this.assetList,
|
||||||
|
required this.asset,
|
||||||
|
required this.thumbnailRequestUrl,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
AssetResponseDto? assetDetail;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final Box<dynamic> box = Hive.box(userInfoBox);
|
||||||
|
|
||||||
|
int indexOfAsset = assetList.indexOf(asset);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState(int index) {
|
||||||
|
indexOfAsset = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageController controller =
|
||||||
|
PageController(initialPage: assetList.indexOf(asset));
|
||||||
|
|
||||||
|
getAssetExif() async {
|
||||||
|
assetDetail = await ref
|
||||||
|
.watch(assetServiceProvider)
|
||||||
|
.getAssetById(assetList[indexOfAsset].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showInfo() {
|
||||||
|
showModalBottomSheet(
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
barrierColor: Colors.transparent,
|
||||||
|
isScrollControlled: false,
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return ExifBottomSheet(assetDetail: assetDetail!);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final isZoomed = useState<bool>(false);
|
||||||
|
ValueNotifier<bool> isZoomedListener = ValueNotifier<bool>(false);
|
||||||
|
|
||||||
|
//make isZoomed listener call instead
|
||||||
|
void isZoomedMethod() {
|
||||||
|
if (isZoomedListener.value) {
|
||||||
|
isZoomed.value = true;
|
||||||
|
} else {
|
||||||
|
isZoomed.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
appBar: TopControlAppBar(
|
||||||
|
asset: assetList[indexOfAsset],
|
||||||
|
onMoreInfoPressed: () {
|
||||||
|
showInfo();
|
||||||
|
},
|
||||||
|
onDownloadPressed: () {
|
||||||
|
ref
|
||||||
|
.watch(imageViewerStateProvider.notifier)
|
||||||
|
.downloadAsset(assetList[indexOfAsset], context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: PageView.builder(
|
||||||
|
controller: controller,
|
||||||
|
pageSnapping: true,
|
||||||
|
physics: isZoomed.value
|
||||||
|
? const NeverScrollableScrollPhysics()
|
||||||
|
: const BouncingScrollPhysics(),
|
||||||
|
itemCount: assetList.length,
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
initState(index);
|
||||||
|
getAssetExif();
|
||||||
|
if (assetList[index].type == AssetTypeEnum.IMAGE) {
|
||||||
|
return ImageViewerPage(
|
||||||
|
thumbnailUrl:
|
||||||
|
'${box.get(serverEndpointKey)}/asset/thumbnail/${assetList[index].id}',
|
||||||
|
imageUrl:
|
||||||
|
'${box.get(serverEndpointKey)}/asset/file?aid=${assetList[index].deviceAssetId}&did=${assetList[index].deviceId}&isThumb=false',
|
||||||
|
authToken: 'Bearer ${box.get(accessTokenKey)}',
|
||||||
|
isZoomedFunction: isZoomedMethod,
|
||||||
|
isZoomedListener: isZoomedListener,
|
||||||
|
asset: assetList[index],
|
||||||
|
heroTag: assetList[index].id,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return SwipeDetector(
|
||||||
|
onSwipeDown: (_) {
|
||||||
|
AutoRouter.of(context).pop();
|
||||||
|
},
|
||||||
|
onSwipeUp: (_) {
|
||||||
|
showInfo();
|
||||||
|
},
|
||||||
|
child: Hero(
|
||||||
|
tag: assetList[index].id,
|
||||||
|
child: VideoViewerPage(
|
||||||
|
asset: assetList[index],
|
||||||
|
videoUrl:
|
||||||
|
'${box.get(serverEndpointKey)}/asset/file?aid=${assetList[index].deviceAssetId}&did=${assetList[index].deviceId}',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,12 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hive/hive.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/hive_box.dart';
|
|
||||||
import 'package:immich_mobile/modules/asset_viewer/models/image_viewer_page_state.model.dart';
|
import 'package:immich_mobile/modules/asset_viewer/models/image_viewer_page_state.model.dart';
|
||||||
import 'package:immich_mobile/modules/asset_viewer/providers/image_viewer_page_state.provider.dart';
|
import 'package:immich_mobile/modules/asset_viewer/providers/image_viewer_page_state.provider.dart';
|
||||||
import 'package:immich_mobile/modules/asset_viewer/ui/download_loading_indicator.dart';
|
import 'package:immich_mobile/modules/asset_viewer/ui/download_loading_indicator.dart';
|
||||||
import 'package:immich_mobile/modules/asset_viewer/ui/exif_bottom_sheet.dart';
|
import 'package:immich_mobile/modules/asset_viewer/ui/exif_bottom_sheet.dart';
|
||||||
import 'package:immich_mobile/modules/asset_viewer/ui/remote_photo_view.dart';
|
import 'package:immich_mobile/modules/asset_viewer/ui/remote_photo_view.dart';
|
||||||
import 'package:immich_mobile/modules/asset_viewer/ui/top_control_app_bar.dart';
|
|
||||||
import 'package:immich_mobile/modules/home/services/asset.service.dart';
|
import 'package:immich_mobile/modules/home/services/asset.service.dart';
|
||||||
import 'package:openapi/api.dart';
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
@ -19,8 +16,9 @@ class ImageViewerPage extends HookConsumerWidget {
|
|||||||
final String heroTag;
|
final String heroTag;
|
||||||
final String thumbnailUrl;
|
final String thumbnailUrl;
|
||||||
final AssetResponseDto asset;
|
final AssetResponseDto asset;
|
||||||
|
final String authToken;
|
||||||
AssetResponseDto? assetDetail;
|
final ValueNotifier<bool> isZoomedListener;
|
||||||
|
final void Function() isZoomedFunction;
|
||||||
|
|
||||||
ImageViewerPage({
|
ImageViewerPage({
|
||||||
Key? key,
|
Key? key,
|
||||||
@ -28,31 +26,22 @@ class ImageViewerPage extends HookConsumerWidget {
|
|||||||
required this.heroTag,
|
required this.heroTag,
|
||||||
required this.thumbnailUrl,
|
required this.thumbnailUrl,
|
||||||
required this.asset,
|
required this.asset,
|
||||||
|
required this.authToken,
|
||||||
|
required this.isZoomedFunction,
|
||||||
|
required this.isZoomedListener,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
AssetResponseDto? assetDetail;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final downloadAssetStatus =
|
final downloadAssetStatus =
|
||||||
ref.watch(imageViewerStateProvider).downloadAssetStatus;
|
ref.watch(imageViewerStateProvider).downloadAssetStatus;
|
||||||
var box = Hive.box(userInfoBox);
|
|
||||||
|
|
||||||
getAssetExif() async {
|
getAssetExif() async {
|
||||||
assetDetail =
|
assetDetail =
|
||||||
await ref.watch(assetServiceProvider).getAssetById(asset.id);
|
await ref.watch(assetServiceProvider).getAssetById(asset.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
showInfo() {
|
|
||||||
showModalBottomSheet(
|
|
||||||
backgroundColor: Colors.black,
|
|
||||||
barrierColor: Colors.transparent,
|
|
||||||
isScrollControlled: false,
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return ExifBottomSheet(assetDetail: assetDetail!);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() {
|
() {
|
||||||
getAssetExif();
|
getAssetExif();
|
||||||
@ -61,39 +50,39 @@ class ImageViewerPage extends HookConsumerWidget {
|
|||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
return Scaffold(
|
showInfo() {
|
||||||
backgroundColor: Colors.black,
|
showModalBottomSheet(
|
||||||
appBar: TopControlAppBar(
|
backgroundColor: Colors.black,
|
||||||
asset: asset,
|
barrierColor: Colors.transparent,
|
||||||
onMoreInfoPressed: showInfo,
|
isScrollControlled: false,
|
||||||
onDownloadPressed: () {
|
context: context,
|
||||||
ref
|
builder: (context) {
|
||||||
.watch(imageViewerStateProvider.notifier)
|
return ExifBottomSheet(assetDetail: assetDetail ?? asset);
|
||||||
.downloadAsset(asset, context);
|
|
||||||
},
|
},
|
||||||
),
|
);
|
||||||
body: SafeArea(
|
}
|
||||||
child: Stack(
|
|
||||||
children: [
|
return Stack(
|
||||||
Center(
|
children: [
|
||||||
child: Hero(
|
Center(
|
||||||
tag: heroTag,
|
child: Hero(
|
||||||
child: RemotePhotoView(
|
tag: heroTag,
|
||||||
thumbnailUrl: thumbnailUrl,
|
child: RemotePhotoView(
|
||||||
imageUrl: imageUrl,
|
thumbnailUrl: thumbnailUrl,
|
||||||
authToken: "Bearer ${box.get(accessTokenKey)}",
|
imageUrl: imageUrl,
|
||||||
onSwipeDown: () => AutoRouter.of(context).pop(),
|
authToken: authToken,
|
||||||
onSwipeUp: () => showInfo(),
|
isZoomedFunction: isZoomedFunction,
|
||||||
),
|
isZoomedListener: isZoomedListener,
|
||||||
),
|
onSwipeDown: () => AutoRouter.of(context).pop(),
|
||||||
|
onSwipeUp: () => showInfo(),
|
||||||
),
|
),
|
||||||
if (downloadAssetStatus == DownloadAssetStatus.loading)
|
),
|
||||||
const Center(
|
|
||||||
child: DownloadLoadingIndicator(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
if (downloadAssetStatus == DownloadAssetStatus.loading)
|
||||||
|
const Center(
|
||||||
|
child: DownloadLoadingIndicator(),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
||||||
import 'package:flutter_swipe_detector/flutter_swipe_detector.dart';
|
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/hive_box.dart';
|
import 'package:immich_mobile/constants/hive_box.dart';
|
||||||
@ -9,9 +6,6 @@ import 'package:chewie/chewie.dart';
|
|||||||
import 'package:immich_mobile/modules/asset_viewer/models/image_viewer_page_state.model.dart';
|
import 'package:immich_mobile/modules/asset_viewer/models/image_viewer_page_state.model.dart';
|
||||||
import 'package:immich_mobile/modules/asset_viewer/providers/image_viewer_page_state.provider.dart';
|
import 'package:immich_mobile/modules/asset_viewer/providers/image_viewer_page_state.provider.dart';
|
||||||
import 'package:immich_mobile/modules/asset_viewer/ui/download_loading_indicator.dart';
|
import 'package:immich_mobile/modules/asset_viewer/ui/download_loading_indicator.dart';
|
||||||
import 'package:immich_mobile/modules/asset_viewer/ui/exif_bottom_sheet.dart';
|
|
||||||
import 'package:immich_mobile/modules/asset_viewer/ui/top_control_app_bar.dart';
|
|
||||||
import 'package:immich_mobile/modules/home/services/asset.service.dart';
|
|
||||||
import 'package:openapi/api.dart';
|
import 'package:openapi/api.dart';
|
||||||
import 'package:video_player/video_player.dart';
|
import 'package:video_player/video_player.dart';
|
||||||
|
|
||||||
@ -31,66 +25,17 @@ class VideoViewerPage extends HookConsumerWidget {
|
|||||||
|
|
||||||
String jwtToken = Hive.box(userInfoBox).get(accessTokenKey);
|
String jwtToken = Hive.box(userInfoBox).get(accessTokenKey);
|
||||||
|
|
||||||
void showInfo() {
|
return Stack(
|
||||||
showModalBottomSheet(
|
children: [
|
||||||
backgroundColor: Colors.black,
|
VideoThumbnailPlayer(
|
||||||
barrierColor: Colors.transparent,
|
url: videoUrl,
|
||||||
isScrollControlled: false,
|
jwtToken: jwtToken,
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return ExifBottomSheet(assetDetail: assetDetail!);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAssetExif() async {
|
|
||||||
assetDetail =
|
|
||||||
await ref.watch(assetServiceProvider).getAssetById(asset.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(
|
|
||||||
() {
|
|
||||||
getAssetExif();
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: Colors.black,
|
|
||||||
appBar: TopControlAppBar(
|
|
||||||
asset: asset,
|
|
||||||
onMoreInfoPressed: () {
|
|
||||||
showInfo();
|
|
||||||
},
|
|
||||||
onDownloadPressed: () {
|
|
||||||
ref
|
|
||||||
.watch(imageViewerStateProvider.notifier)
|
|
||||||
.downloadAsset(asset, context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
body: SwipeDetector(
|
|
||||||
onSwipeDown: (_) {
|
|
||||||
AutoRouter.of(context).pop();
|
|
||||||
},
|
|
||||||
onSwipeUp: (_) {
|
|
||||||
showInfo();
|
|
||||||
},
|
|
||||||
child: SafeArea(
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
VideoThumbnailPlayer(
|
|
||||||
url: videoUrl,
|
|
||||||
jwtToken: jwtToken,
|
|
||||||
),
|
|
||||||
if (downloadAssetStatus == DownloadAssetStatus.loading)
|
|
||||||
const Center(
|
|
||||||
child: DownloadLoadingIndicator(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
if (downloadAssetStatus == DownloadAssetStatus.loading)
|
||||||
|
const Center(
|
||||||
|
child: DownloadLoadingIndicator(),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,10 +79,13 @@ class _VideoThumbnailPlayerState extends State<VideoThumbnailPlayer> {
|
|||||||
_createChewieController() {
|
_createChewieController() {
|
||||||
chewieController = ChewieController(
|
chewieController = ChewieController(
|
||||||
showOptions: true,
|
showOptions: true,
|
||||||
showControlsOnInitialize: false,
|
showControlsOnInitialize: true,
|
||||||
videoPlayerController: videoPlayerController,
|
videoPlayerController: videoPlayerController,
|
||||||
autoPlay: true,
|
autoPlay: true,
|
||||||
autoInitialize: false,
|
autoInitialize: true,
|
||||||
|
allowFullScreen: true,
|
||||||
|
showControls: true,
|
||||||
|
hideControlsTimer: const Duration(seconds: 5),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,11 +105,13 @@ class _VideoThumbnailPlayerState extends State<VideoThumbnailPlayer> {
|
|||||||
controller: chewieController!,
|
controller: chewieController!,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: const SizedBox(
|
: const Center(
|
||||||
width: 75,
|
child: SizedBox(
|
||||||
height: 75,
|
width: 75,
|
||||||
child: CircularProgressIndicator.adaptive(
|
height: 75,
|
||||||
strokeWidth: 2,
|
child: CircularProgressIndicator.adaptive(
|
||||||
|
strokeWidth: 2,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -162,6 +162,10 @@ class BackupNotifier extends StateNotifier<BackUpState> {
|
|||||||
onlyAll: true,
|
onlyAll: true,
|
||||||
type: RequestType.common,
|
type: RequestType.common,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (list.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
AssetPathEntity albumHasAllAssets = list.first;
|
AssetPathEntity albumHasAllAssets = list.first;
|
||||||
|
|
||||||
backupAlbumInfoBox.put(
|
backupAlbumInfoBox.put(
|
||||||
|
@ -3,10 +3,18 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:immich_mobile/modules/home/ui/thumbnail_image.dart';
|
import 'package:immich_mobile/modules/home/ui/thumbnail_image.dart';
|
||||||
import 'package:openapi/api.dart';
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
class ImageGrid extends ConsumerWidget {
|
class ImageGrid extends ConsumerWidget {
|
||||||
final List<AssetResponseDto> assetGroup;
|
final List<AssetResponseDto> assetGroup;
|
||||||
|
final List<AssetResponseDto> sortedAssetGroup;
|
||||||
|
|
||||||
const ImageGrid({Key? key, required this.assetGroup}) : super(key: key);
|
ImageGrid({
|
||||||
|
Key? key,
|
||||||
|
required this.assetGroup,
|
||||||
|
required this.sortedAssetGroup,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
List<AssetResponseDto> imageSortedList = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@ -19,12 +27,14 @@ class ImageGrid extends ConsumerWidget {
|
|||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(BuildContext context, int index) {
|
(BuildContext context, int index) {
|
||||||
var assetType = assetGroup[index].type;
|
var assetType = assetGroup[index].type;
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {},
|
onTap: () {},
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
ThumbnailImage(asset: assetGroup[index]),
|
ThumbnailImage(
|
||||||
|
asset: assetGroup[index],
|
||||||
|
assetList: sortedAssetGroup,
|
||||||
|
),
|
||||||
if (assetType != AssetTypeEnum.IMAGE)
|
if (assetType != AssetTypeEnum.IMAGE)
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 5,
|
top: 5,
|
||||||
|
@ -13,8 +13,10 @@ import 'package:openapi/api.dart';
|
|||||||
|
|
||||||
class ThumbnailImage extends HookConsumerWidget {
|
class ThumbnailImage extends HookConsumerWidget {
|
||||||
final AssetResponseDto asset;
|
final AssetResponseDto asset;
|
||||||
|
final List<AssetResponseDto> assetList;
|
||||||
|
|
||||||
const ThumbnailImage({Key? key, required this.asset}) : super(key: key);
|
const ThumbnailImage({Key? key, required this.asset, required this.assetList})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@ -60,29 +62,17 @@ class ThumbnailImage extends HookConsumerWidget {
|
|||||||
.watch(homePageStateProvider.notifier)
|
.watch(homePageStateProvider.notifier)
|
||||||
.addSingleSelectedItem(asset);
|
.addSingleSelectedItem(asset);
|
||||||
} else {
|
} else {
|
||||||
if (asset.type == AssetTypeEnum.IMAGE) {
|
AutoRouter.of(context).push(
|
||||||
AutoRouter.of(context).push(
|
GalleryViewerRoute(
|
||||||
ImageViewerRoute(
|
assetList: assetList,
|
||||||
imageUrl:
|
thumbnailRequestUrl: thumbnailRequestUrl,
|
||||||
'${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}&isThumb=false',
|
asset: asset,
|
||||||
heroTag: asset.id,
|
),
|
||||||
thumbnailUrl: thumbnailRequestUrl,
|
);
|
||||||
asset: asset,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
AutoRouter.of(context).push(
|
|
||||||
VideoViewerRoute(
|
|
||||||
videoUrl:
|
|
||||||
'${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}',
|
|
||||||
asset: asset,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
// Enable multi selecte function
|
// Enable multi select function
|
||||||
ref.watch(homePageStateProvider.notifier).enableMultiSelect({asset});
|
ref.watch(homePageStateProvider.notifier).enableMultiSelect({asset});
|
||||||
HapticFeedback.heavyImpact();
|
HapticFeedback.heavyImpact();
|
||||||
},
|
},
|
||||||
|
@ -10,9 +10,11 @@ import 'package:immich_mobile/modules/home/ui/image_grid.dart';
|
|||||||
import 'package:immich_mobile/modules/home/ui/immich_sliver_appbar.dart';
|
import 'package:immich_mobile/modules/home/ui/immich_sliver_appbar.dart';
|
||||||
import 'package:immich_mobile/modules/home/ui/monthly_title_text.dart';
|
import 'package:immich_mobile/modules/home/ui/monthly_title_text.dart';
|
||||||
import 'package:immich_mobile/modules/home/ui/profile_drawer.dart';
|
import 'package:immich_mobile/modules/home/ui/profile_drawer.dart';
|
||||||
|
|
||||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||||
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
||||||
import 'package:immich_mobile/shared/providers/websocket.provider.dart';
|
import 'package:immich_mobile/shared/providers/websocket.provider.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
class HomePage extends HookConsumerWidget {
|
class HomePage extends HookConsumerWidget {
|
||||||
const HomePage({Key? key}) : super(key: key);
|
const HomePage({Key? key}) : super(key: key);
|
||||||
@ -25,6 +27,13 @@ class HomePage extends HookConsumerWidget {
|
|||||||
var isMultiSelectEnable =
|
var isMultiSelectEnable =
|
||||||
ref.watch(homePageStateProvider).isMultiSelectEnable;
|
ref.watch(homePageStateProvider).isMultiSelectEnable;
|
||||||
var homePageState = ref.watch(homePageStateProvider);
|
var homePageState = ref.watch(homePageStateProvider);
|
||||||
|
List<AssetResponseDto> sortedAssetList = [];
|
||||||
|
// set sorted List
|
||||||
|
for (var group in assetGroupByDateTime.values) {
|
||||||
|
for (var value in group) {
|
||||||
|
sortedAssetList.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() {
|
() {
|
||||||
@ -73,7 +82,10 @@ class HomePage extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
imageGridGroup.add(
|
imageGridGroup.add(
|
||||||
ImageGrid(assetGroup: immichAssetList),
|
ImageGrid(
|
||||||
|
assetGroup: immichAssetList,
|
||||||
|
sortedAssetGroup: sortedAssetList,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
lastMonth = currentMonth;
|
lastMonth = currentMonth;
|
||||||
|
@ -11,6 +11,7 @@ import 'package:immich_mobile/modules/home/ui/monthly_title_text.dart';
|
|||||||
import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart';
|
import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart';
|
||||||
import 'package:immich_mobile/modules/search/providers/search_result_page.provider.dart';
|
import 'package:immich_mobile/modules/search/providers/search_result_page.provider.dart';
|
||||||
import 'package:immich_mobile/modules/search/ui/search_suggestion_list.dart';
|
import 'package:immich_mobile/modules/search/ui/search_suggestion_list.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
class SearchResultPage extends HookConsumerWidget {
|
class SearchResultPage extends HookConsumerWidget {
|
||||||
const SearchResultPage({Key? key, required this.searchTerm})
|
const SearchResultPage({Key? key, required this.searchTerm})
|
||||||
@ -27,7 +28,9 @@ class SearchResultPage extends HookConsumerWidget {
|
|||||||
|
|
||||||
final List<Widget> imageGridGroup = [];
|
final List<Widget> imageGridGroup = [];
|
||||||
|
|
||||||
late FocusNode searchFocusNode;
|
FocusNode? searchFocusNode;
|
||||||
|
|
||||||
|
List<AssetResponseDto> sortedAssetList = [];
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() {
|
() {
|
||||||
@ -37,14 +40,14 @@ class SearchResultPage extends HookConsumerWidget {
|
|||||||
Duration.zero,
|
Duration.zero,
|
||||||
() => ref.read(searchResultPageProvider.notifier).search(searchTerm),
|
() => ref.read(searchResultPageProvider.notifier).search(searchTerm),
|
||||||
);
|
);
|
||||||
return () => searchFocusNode.dispose();
|
return () => searchFocusNode?.dispose();
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
_onSearchSubmitted(String newSearchTerm) {
|
_onSearchSubmitted(String newSearchTerm) {
|
||||||
debugPrint("Re-Search with $newSearchTerm");
|
debugPrint("Re-Search with $newSearchTerm");
|
||||||
searchFocusNode.unfocus();
|
searchFocusNode?.unfocus();
|
||||||
isNewSearch.value = false;
|
isNewSearch.value = false;
|
||||||
currentSearchTerm.value = newSearchTerm;
|
currentSearchTerm.value = newSearchTerm;
|
||||||
ref.watch(searchResultPageProvider.notifier).search(newSearchTerm);
|
ref.watch(searchResultPageProvider.notifier).search(newSearchTerm);
|
||||||
@ -58,7 +61,7 @@ class SearchResultPage extends HookConsumerWidget {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
searchTermController.clear();
|
searchTermController.clear();
|
||||||
ref.watch(searchPageStateProvider.notifier).setSearchTerm("");
|
ref.watch(searchPageStateProvider.notifier).setSearchTerm("");
|
||||||
searchFocusNode.requestFocus();
|
searchFocusNode?.requestFocus();
|
||||||
},
|
},
|
||||||
textInputAction: TextInputAction.search,
|
textInputAction: TextInputAction.search,
|
||||||
onSubmitted: (searchTerm) {
|
onSubmitted: (searchTerm) {
|
||||||
@ -131,7 +134,12 @@ class SearchResultPage extends HookConsumerWidget {
|
|||||||
if (searchResultPageState.isSuccess) {
|
if (searchResultPageState.isSuccess) {
|
||||||
if (searchResultPageState.searchResult.isNotEmpty) {
|
if (searchResultPageState.searchResult.isNotEmpty) {
|
||||||
int? lastMonth;
|
int? lastMonth;
|
||||||
|
// set sorted List
|
||||||
|
for (var group in assetGroupByDateTime.values) {
|
||||||
|
for (var value in group) {
|
||||||
|
sortedAssetList.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
assetGroupByDateTime.forEach((dateGroup, immichAssetList) {
|
assetGroupByDateTime.forEach((dateGroup, immichAssetList) {
|
||||||
DateTime parseDateGroup = DateTime.parse(dateGroup);
|
DateTime parseDateGroup = DateTime.parse(dateGroup);
|
||||||
int currentMonth = parseDateGroup.month;
|
int currentMonth = parseDateGroup.month;
|
||||||
@ -154,7 +162,10 @@ class SearchResultPage extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
imageGridGroup.add(
|
imageGridGroup.add(
|
||||||
ImageGrid(assetGroup: immichAssetList),
|
ImageGrid(
|
||||||
|
assetGroup: immichAssetList,
|
||||||
|
sortedAssetGroup: sortedAssetList,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
lastMonth = currentMonth;
|
lastMonth = currentMonth;
|
||||||
@ -193,7 +204,7 @@ class SearchResultPage extends HookConsumerWidget {
|
|||||||
title: GestureDetector(
|
title: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
isNewSearch.value = true;
|
isNewSearch.value = true;
|
||||||
searchFocusNode.requestFocus();
|
searchFocusNode?.requestFocus();
|
||||||
},
|
},
|
||||||
child: isNewSearch.value ? _buildTextField() : _buildChip(),
|
child: isNewSearch.value ? _buildTextField() : _buildChip(),
|
||||||
),
|
),
|
||||||
@ -201,7 +212,10 @@ class SearchResultPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
body: GestureDetector(
|
body: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
searchFocusNode.unfocus();
|
if (searchFocusNode != null) {
|
||||||
|
searchFocusNode?.unfocus();
|
||||||
|
}
|
||||||
|
|
||||||
ref.watch(searchPageStateProvider.notifier).disableSearch();
|
ref.watch(searchPageStateProvider.notifier).disableSearch();
|
||||||
},
|
},
|
||||||
child: Stack(
|
child: Stack(
|
||||||
|
@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/modules/album/views/library_page.dart';
|
import 'package:immich_mobile/modules/album/views/library_page.dart';
|
||||||
|
import 'package:immich_mobile/modules/asset_viewer/views/gallery_viewer.dart';
|
||||||
import 'package:immich_mobile/modules/backup/views/album_preview_page.dart';
|
import 'package:immich_mobile/modules/backup/views/album_preview_page.dart';
|
||||||
import 'package:immich_mobile/modules/backup/views/backup_album_selection_page.dart';
|
import 'package:immich_mobile/modules/backup/views/backup_album_selection_page.dart';
|
||||||
import 'package:immich_mobile/modules/backup/views/failed_backup_status_page.dart';
|
import 'package:immich_mobile/modules/backup/views/failed_backup_status_page.dart';
|
||||||
@ -47,6 +48,7 @@ part 'router.gr.dart';
|
|||||||
],
|
],
|
||||||
transitionsBuilder: TransitionsBuilders.fadeIn,
|
transitionsBuilder: TransitionsBuilders.fadeIn,
|
||||||
),
|
),
|
||||||
|
AutoRoute(page: GalleryViewerPage, guards: [AuthGuard]),
|
||||||
AutoRoute(page: ImageViewerPage, guards: [AuthGuard]),
|
AutoRoute(page: ImageViewerPage, guards: [AuthGuard]),
|
||||||
AutoRoute(page: VideoViewerPage, guards: [AuthGuard]),
|
AutoRoute(page: VideoViewerPage, guards: [AuthGuard]),
|
||||||
AutoRoute(page: BackupControllerPage, guards: [AuthGuard]),
|
AutoRoute(page: BackupControllerPage, guards: [AuthGuard]),
|
||||||
@ -78,6 +80,7 @@ part 'router.gr.dart';
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
class AppRouter extends _$AppRouter {
|
class AppRouter extends _$AppRouter {
|
||||||
|
// ignore: unused_field
|
||||||
final ApiService _apiService;
|
final ApiService _apiService;
|
||||||
|
|
||||||
AppRouter(this._apiService) : super(authGuard: AuthGuard(_apiService));
|
AppRouter(this._apiService) : super(authGuard: AuthGuard(_apiService));
|
||||||
|
@ -41,6 +41,16 @@ class _$AppRouter extends RootStackRouter {
|
|||||||
opaque: true,
|
opaque: true,
|
||||||
barrierDismissible: false);
|
barrierDismissible: false);
|
||||||
},
|
},
|
||||||
|
GalleryViewerRoute.name: (routeData) {
|
||||||
|
final args = routeData.argsAs<GalleryViewerRouteArgs>();
|
||||||
|
return MaterialPageX<dynamic>(
|
||||||
|
routeData: routeData,
|
||||||
|
child: GalleryViewerPage(
|
||||||
|
key: args.key,
|
||||||
|
assetList: args.assetList,
|
||||||
|
asset: args.asset,
|
||||||
|
thumbnailRequestUrl: args.thumbnailRequestUrl));
|
||||||
|
},
|
||||||
ImageViewerRoute.name: (routeData) {
|
ImageViewerRoute.name: (routeData) {
|
||||||
final args = routeData.argsAs<ImageViewerRouteArgs>();
|
final args = routeData.argsAs<ImageViewerRouteArgs>();
|
||||||
return MaterialPageX<dynamic>(
|
return MaterialPageX<dynamic>(
|
||||||
@ -50,7 +60,10 @@ class _$AppRouter extends RootStackRouter {
|
|||||||
imageUrl: args.imageUrl,
|
imageUrl: args.imageUrl,
|
||||||
heroTag: args.heroTag,
|
heroTag: args.heroTag,
|
||||||
thumbnailUrl: args.thumbnailUrl,
|
thumbnailUrl: args.thumbnailUrl,
|
||||||
asset: args.asset));
|
asset: args.asset,
|
||||||
|
authToken: args.authToken,
|
||||||
|
isZoomedFunction: args.isZoomedFunction,
|
||||||
|
isZoomedListener: args.isZoomedListener));
|
||||||
},
|
},
|
||||||
VideoViewerRoute.name: (routeData) {
|
VideoViewerRoute.name: (routeData) {
|
||||||
final args = routeData.argsAs<VideoViewerRouteArgs>();
|
final args = routeData.argsAs<VideoViewerRouteArgs>();
|
||||||
@ -174,6 +187,8 @@ class _$AppRouter extends RootStackRouter {
|
|||||||
parent: TabControllerRoute.name,
|
parent: TabControllerRoute.name,
|
||||||
guards: [authGuard])
|
guards: [authGuard])
|
||||||
]),
|
]),
|
||||||
|
RouteConfig(GalleryViewerRoute.name,
|
||||||
|
path: '/gallery-viewer-page', guards: [authGuard]),
|
||||||
RouteConfig(ImageViewerRoute.name,
|
RouteConfig(ImageViewerRoute.name,
|
||||||
path: '/image-viewer-page', guards: [authGuard]),
|
path: '/image-viewer-page', guards: [authGuard]),
|
||||||
RouteConfig(VideoViewerRoute.name,
|
RouteConfig(VideoViewerRoute.name,
|
||||||
@ -237,6 +252,46 @@ class TabControllerRoute extends PageRouteInfo<void> {
|
|||||||
static const String name = 'TabControllerRoute';
|
static const String name = 'TabControllerRoute';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// generated route for
|
||||||
|
/// [GalleryViewerPage]
|
||||||
|
class GalleryViewerRoute extends PageRouteInfo<GalleryViewerRouteArgs> {
|
||||||
|
GalleryViewerRoute(
|
||||||
|
{Key? key,
|
||||||
|
required List<AssetResponseDto> assetList,
|
||||||
|
required AssetResponseDto asset,
|
||||||
|
required String thumbnailRequestUrl})
|
||||||
|
: super(GalleryViewerRoute.name,
|
||||||
|
path: '/gallery-viewer-page',
|
||||||
|
args: GalleryViewerRouteArgs(
|
||||||
|
key: key,
|
||||||
|
assetList: assetList,
|
||||||
|
asset: asset,
|
||||||
|
thumbnailRequestUrl: thumbnailRequestUrl));
|
||||||
|
|
||||||
|
static const String name = 'GalleryViewerRoute';
|
||||||
|
}
|
||||||
|
|
||||||
|
class GalleryViewerRouteArgs {
|
||||||
|
const GalleryViewerRouteArgs(
|
||||||
|
{this.key,
|
||||||
|
required this.assetList,
|
||||||
|
required this.asset,
|
||||||
|
required this.thumbnailRequestUrl});
|
||||||
|
|
||||||
|
final Key? key;
|
||||||
|
|
||||||
|
final List<AssetResponseDto> assetList;
|
||||||
|
|
||||||
|
final AssetResponseDto asset;
|
||||||
|
|
||||||
|
final String thumbnailRequestUrl;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'GalleryViewerRouteArgs{key: $key, assetList: $assetList, asset: $asset, thumbnailRequestUrl: $thumbnailRequestUrl}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [ImageViewerPage]
|
/// [ImageViewerPage]
|
||||||
class ImageViewerRoute extends PageRouteInfo<ImageViewerRouteArgs> {
|
class ImageViewerRoute extends PageRouteInfo<ImageViewerRouteArgs> {
|
||||||
@ -245,7 +300,10 @@ class ImageViewerRoute extends PageRouteInfo<ImageViewerRouteArgs> {
|
|||||||
required String imageUrl,
|
required String imageUrl,
|
||||||
required String heroTag,
|
required String heroTag,
|
||||||
required String thumbnailUrl,
|
required String thumbnailUrl,
|
||||||
required AssetResponseDto asset})
|
required AssetResponseDto asset,
|
||||||
|
required String authToken,
|
||||||
|
required void Function() isZoomedFunction,
|
||||||
|
required ValueNotifier<bool> isZoomedListener})
|
||||||
: super(ImageViewerRoute.name,
|
: super(ImageViewerRoute.name,
|
||||||
path: '/image-viewer-page',
|
path: '/image-viewer-page',
|
||||||
args: ImageViewerRouteArgs(
|
args: ImageViewerRouteArgs(
|
||||||
@ -253,7 +311,10 @@ class ImageViewerRoute extends PageRouteInfo<ImageViewerRouteArgs> {
|
|||||||
imageUrl: imageUrl,
|
imageUrl: imageUrl,
|
||||||
heroTag: heroTag,
|
heroTag: heroTag,
|
||||||
thumbnailUrl: thumbnailUrl,
|
thumbnailUrl: thumbnailUrl,
|
||||||
asset: asset));
|
asset: asset,
|
||||||
|
authToken: authToken,
|
||||||
|
isZoomedFunction: isZoomedFunction,
|
||||||
|
isZoomedListener: isZoomedListener));
|
||||||
|
|
||||||
static const String name = 'ImageViewerRoute';
|
static const String name = 'ImageViewerRoute';
|
||||||
}
|
}
|
||||||
@ -264,7 +325,10 @@ class ImageViewerRouteArgs {
|
|||||||
required this.imageUrl,
|
required this.imageUrl,
|
||||||
required this.heroTag,
|
required this.heroTag,
|
||||||
required this.thumbnailUrl,
|
required this.thumbnailUrl,
|
||||||
required this.asset});
|
required this.asset,
|
||||||
|
required this.authToken,
|
||||||
|
required this.isZoomedFunction,
|
||||||
|
required this.isZoomedListener});
|
||||||
|
|
||||||
final Key? key;
|
final Key? key;
|
||||||
|
|
||||||
@ -276,9 +340,15 @@ class ImageViewerRouteArgs {
|
|||||||
|
|
||||||
final AssetResponseDto asset;
|
final AssetResponseDto asset;
|
||||||
|
|
||||||
|
final String authToken;
|
||||||
|
|
||||||
|
final void Function() isZoomedFunction;
|
||||||
|
|
||||||
|
final ValueNotifier<bool> isZoomedListener;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'ImageViewerRouteArgs{key: $key, imageUrl: $imageUrl, heroTag: $heroTag, thumbnailUrl: $thumbnailUrl, asset: $asset}';
|
return 'ImageViewerRouteArgs{key: $key, imageUrl: $imageUrl, heroTag: $heroTag, thumbnailUrl: $thumbnailUrl, asset: $asset, authToken: $authToken, isZoomedFunction: $isZoomedFunction, isZoomedListener: $isZoomedListener}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user