mirror of
https://github.com/immich-app/immich.git
synced 2025-12-15 09:13:11 +03:00
Compare commits
1 Commits
revert-sve
...
feat/kb-sh
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
539f9d64e8 |
@@ -24,6 +24,67 @@ enum AddToMenuItem { album, archive, unarchive, lockedFolder }
|
|||||||
class AddActionButton extends ConsumerStatefulWidget {
|
class AddActionButton extends ConsumerStatefulWidget {
|
||||||
const AddActionButton({super.key});
|
const AddActionButton({super.key});
|
||||||
|
|
||||||
|
static void openAlbumSelector(BuildContext context, WidgetRef ref) {
|
||||||
|
final currentAsset = ref.read(currentAssetNotifier);
|
||||||
|
if (currentAsset == null) {
|
||||||
|
ImmichToast.show(context: context, msg: "Cannot load asset information.", toastType: ToastType.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Widget> slivers = [
|
||||||
|
AlbumSelector(onAlbumSelected: (album) => addCurrentAssetToAlbum(context, ref, album)),
|
||||||
|
];
|
||||||
|
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
builder: (_) {
|
||||||
|
return BaseBottomSheet(
|
||||||
|
actions: const [],
|
||||||
|
slivers: slivers,
|
||||||
|
initialChildSize: 0.6,
|
||||||
|
minChildSize: 0.3,
|
||||||
|
maxChildSize: 0.95,
|
||||||
|
expand: false,
|
||||||
|
backgroundColor: context.isDarkTheme ? Colors.black : Colors.white,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> addCurrentAssetToAlbum(BuildContext context, WidgetRef ref, RemoteAlbum album) async {
|
||||||
|
final latest = ref.read(currentAssetNotifier);
|
||||||
|
|
||||||
|
if (latest == null) {
|
||||||
|
ImmichToast.show(context: context, msg: "Cannot load asset information.", toastType: ToastType.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final addedCount = await ref.read(remoteAlbumProvider.notifier).addAssets(album.id, [latest.remoteId!]);
|
||||||
|
|
||||||
|
if (!context.mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addedCount == 0) {
|
||||||
|
ImmichToast.show(
|
||||||
|
context: context,
|
||||||
|
msg: 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {'album': album.name}),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ImmichToast.show(
|
||||||
|
context: context,
|
||||||
|
msg: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context.mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await Navigator.of(context).maybePop();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<AddActionButton> createState() => _AddActionButtonState();
|
ConsumerState<AddActionButton> createState() => _AddActionButtonState();
|
||||||
}
|
}
|
||||||
@@ -32,7 +93,7 @@ class _AddActionButtonState extends ConsumerState<AddActionButton> {
|
|||||||
void _handleMenuSelection(AddToMenuItem selected) {
|
void _handleMenuSelection(AddToMenuItem selected) {
|
||||||
switch (selected) {
|
switch (selected) {
|
||||||
case AddToMenuItem.album:
|
case AddToMenuItem.album:
|
||||||
_openAlbumSelector();
|
AddActionButton.openAlbumSelector(context, ref);
|
||||||
break;
|
break;
|
||||||
case AddToMenuItem.archive:
|
case AddToMenuItem.archive:
|
||||||
performArchiveAction(context, ref, source: ActionSource.viewer);
|
performArchiveAction(context, ref, source: ActionSource.viewer);
|
||||||
@@ -100,65 +161,6 @@ class _AddActionButtonState extends ConsumerState<AddActionButton> {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
void _openAlbumSelector() {
|
|
||||||
final currentAsset = ref.read(currentAssetNotifier);
|
|
||||||
if (currentAsset == null) {
|
|
||||||
ImmichToast.show(context: context, msg: "Cannot load asset information.", toastType: ToastType.error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<Widget> slivers = [AlbumSelector(onAlbumSelected: (album) => _addCurrentAssetToAlbum(album))];
|
|
||||||
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
builder: (_) {
|
|
||||||
return BaseBottomSheet(
|
|
||||||
actions: const [],
|
|
||||||
slivers: slivers,
|
|
||||||
initialChildSize: 0.6,
|
|
||||||
minChildSize: 0.3,
|
|
||||||
maxChildSize: 0.95,
|
|
||||||
expand: false,
|
|
||||||
backgroundColor: context.isDarkTheme ? Colors.black : Colors.white,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _addCurrentAssetToAlbum(RemoteAlbum album) async {
|
|
||||||
final latest = ref.read(currentAssetNotifier);
|
|
||||||
|
|
||||||
if (latest == null) {
|
|
||||||
ImmichToast.show(context: context, msg: "Cannot load asset information.", toastType: ToastType.error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final addedCount = await ref.read(remoteAlbumProvider.notifier).addAssets(album.id, [latest.remoteId!]);
|
|
||||||
|
|
||||||
if (!context.mounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addedCount == 0) {
|
|
||||||
ImmichToast.show(
|
|
||||||
context: context,
|
|
||||||
msg: 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {'album': album.name}),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ImmichToast.show(
|
|
||||||
context: context,
|
|
||||||
msg: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!context.mounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await Navigator.of(context).maybePop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final asset = ref.watch(currentAssetNotifier);
|
final asset = ref.watch(currentAssetNotifier);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class DeleteActionButton extends ConsumerWidget {
|
|||||||
final bool showConfirmation;
|
final bool showConfirmation;
|
||||||
const DeleteActionButton({super.key, required this.source, this.showConfirmation = false});
|
const DeleteActionButton({super.key, required this.source, this.showConfirmation = false});
|
||||||
|
|
||||||
void _onTap(BuildContext context, WidgetRef ref) async {
|
static void deleteAsset(BuildContext context, WidgetRef ref, bool showConfirmation, ActionSource source) async {
|
||||||
if (!context.mounted) {
|
if (!context.mounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ class DeleteActionButton extends ConsumerWidget {
|
|||||||
maxWidth: 110.0,
|
maxWidth: 110.0,
|
||||||
iconData: Icons.delete_sweep_outlined,
|
iconData: Icons.delete_sweep_outlined,
|
||||||
label: "delete".t(context: context),
|
label: "delete".t(context: context),
|
||||||
onPressed: () => _onTap(context, ref),
|
onPressed: () => deleteAsset(context, ref, showConfirmation, source),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,12 @@ class DownloadActionButton extends ConsumerWidget {
|
|||||||
final bool menuItem;
|
final bool menuItem;
|
||||||
const DownloadActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
|
const DownloadActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
|
||||||
|
|
||||||
void _onTap(BuildContext context, WidgetRef ref, BackgroundSyncManager backgroundSyncManager) async {
|
static void onDownload(
|
||||||
|
BuildContext context,
|
||||||
|
WidgetRef ref,
|
||||||
|
ActionSource source,
|
||||||
|
BackgroundSyncManager backgroundSyncManager,
|
||||||
|
) async {
|
||||||
if (!context.mounted) {
|
if (!context.mounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -41,7 +46,7 @@ class DownloadActionButton extends ConsumerWidget {
|
|||||||
label: "download".t(context: context),
|
label: "download".t(context: context),
|
||||||
iconOnly: iconOnly,
|
iconOnly: iconOnly,
|
||||||
menuItem: menuItem,
|
menuItem: menuItem,
|
||||||
onPressed: () => _onTap(context, ref, backgroundManager),
|
onPressed: () => onDownload(context, ref, source, backgroundManager),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class FavoriteActionButton extends ConsumerWidget {
|
|||||||
|
|
||||||
const FavoriteActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
|
const FavoriteActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
|
||||||
|
|
||||||
void _onTap(BuildContext context, WidgetRef ref) async {
|
static void favoriteAsset(BuildContext context, WidgetRef ref, ActionSource source) async {
|
||||||
if (!context.mounted) {
|
if (!context.mounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ class FavoriteActionButton extends ConsumerWidget {
|
|||||||
label: "favorite".t(context: context),
|
label: "favorite".t(context: context),
|
||||||
iconOnly: iconOnly,
|
iconOnly: iconOnly,
|
||||||
menuItem: menuItem,
|
menuItem: menuItem,
|
||||||
onPressed: () => _onTap(context, ref),
|
onPressed: () => favoriteAsset(context, ref, source),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/constants/enums.dart';
|
||||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/events.model.dart';
|
import 'package:immich_mobile/domain/models/events.model.dart';
|
||||||
@@ -13,6 +14,9 @@ import 'package:immich_mobile/domain/utils/event_stream.dart';
|
|||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/scroll_extensions.dart';
|
import 'package:immich_mobile/extensions/scroll_extensions.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/add_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/download_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/download_status_floating_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/download_status_floating_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/activities_bottom_sheet.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/asset_viewer/activities_bottom_sheet.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.provider.dart';
|
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.provider.dart';
|
||||||
@@ -27,11 +31,14 @@ import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart'
|
|||||||
import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/video_player_controls_provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/video_player_controls_provider.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||||
import 'package:immich_mobile/providers/cast.provider.dart';
|
import 'package:immich_mobile/providers/cast.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';
|
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';
|
||||||
import 'package:immich_mobile/widgets/photo_view/photo_view.dart';
|
import 'package:immich_mobile/widgets/photo_view/photo_view.dart';
|
||||||
import 'package:immich_mobile/widgets/photo_view/photo_view_gallery.dart';
|
import 'package:immich_mobile/widgets/photo_view/photo_view_gallery.dart';
|
||||||
@@ -622,6 +629,70 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
|||||||
ref.read(currentAssetNotifier.notifier).dispose();
|
ref.read(currentAssetNotifier.notifier).dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyEventResult handleKeyEvent(KeyDownEvent event) {
|
||||||
|
final asset = ref.watch(currentAssetNotifier);
|
||||||
|
final user = ref.watch(currentUserProvider);
|
||||||
|
final isOwner = asset is RemoteAsset && asset.ownerId == user?.id;
|
||||||
|
// Arrow Left
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.arrowLeft) {
|
||||||
|
final prevIndex = (pageController.page?.round() ?? 0) - 1;
|
||||||
|
if (prevIndex >= 0) {
|
||||||
|
pageController.animateToPage(prevIndex, duration: Durations.short4, curve: Curves.ease);
|
||||||
|
}
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arrow Right
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.arrowRight) {
|
||||||
|
final nextIndex = (pageController.page?.round() ?? 0) + 1;
|
||||||
|
if (nextIndex < totalAssets) {
|
||||||
|
pageController.animateToPage(nextIndex, duration: Durations.short4, curve: Curves.ease);
|
||||||
|
}
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key F - Favorite / Unfavorite
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.keyF) {
|
||||||
|
if (asset == null || !asset.hasRemote || !isOwner) return KeyEventResult.ignored;
|
||||||
|
if (asset.isFavorite) {
|
||||||
|
ref.read(actionProvider.notifier).unFavorite(ActionSource.viewer);
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
} else {
|
||||||
|
ref.read(actionProvider.notifier).favorite(ActionSource.viewer);
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shift + D - Download
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.keyD &&
|
||||||
|
(HardwareKeyboard.instance.logicalKeysPressed.contains(LogicalKeyboardKey.shiftLeft) ||
|
||||||
|
HardwareKeyboard.instance.logicalKeysPressed.contains(LogicalKeyboardKey.shiftRight))) {
|
||||||
|
if (asset == null || !asset.isRemoteOnly) return KeyEventResult.ignored;
|
||||||
|
final backgroundManager = ref.watch(backgroundSyncProvider);
|
||||||
|
DownloadActionButton.onDownload(context, ref, ActionSource.viewer, backgroundManager);
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key L - Add to Album
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.keyL) {
|
||||||
|
AddActionButton.openAlbumSelector(context, ref);
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete Key - Delete Asset
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.delete) {
|
||||||
|
if (asset == null || !asset.hasRemote || !isOwner) return KeyEventResult.ignored;
|
||||||
|
if (asset.isLocalOnly) {
|
||||||
|
ref.read(actionProvider.notifier).deleteLocal(ActionSource.viewer, context);
|
||||||
|
} else {
|
||||||
|
DeleteActionButton.deleteAsset(context, ref, true, ActionSource.viewer);
|
||||||
|
}
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KeyEventResult.ignored;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Rebuild the widget when the asset viewer state changes
|
// Rebuild the widget when the asset viewer state changes
|
||||||
@@ -658,46 +729,55 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
|||||||
// TODO: Add a custom scrum builder once the fix lands on stable
|
// TODO: Add a custom scrum builder once the fix lands on stable
|
||||||
return PopScope(
|
return PopScope(
|
||||||
onPopInvokedWithResult: _onPop,
|
onPopInvokedWithResult: _onPop,
|
||||||
child: Scaffold(
|
child: Focus(
|
||||||
backgroundColor: backgroundColor,
|
autofocus: true,
|
||||||
appBar: const ViewerTopAppBar(),
|
onKeyEvent: (node, event) {
|
||||||
extendBody: true,
|
if (event is KeyDownEvent) {
|
||||||
extendBodyBehindAppBar: true,
|
return handleKeyEvent(event);
|
||||||
floatingActionButton: IgnorePointer(
|
}
|
||||||
ignoring: !showingControls,
|
return KeyEventResult.ignored;
|
||||||
child: AnimatedOpacity(
|
},
|
||||||
opacity: showingControls ? 1.0 : 0.0,
|
child: Scaffold(
|
||||||
duration: Durations.short2,
|
backgroundColor: backgroundColor,
|
||||||
child: const DownloadStatusFloatingButton(),
|
appBar: const ViewerTopAppBar(),
|
||||||
),
|
extendBody: true,
|
||||||
),
|
extendBodyBehindAppBar: true,
|
||||||
body: Stack(
|
floatingActionButton: IgnorePointer(
|
||||||
children: [
|
ignoring: !showingControls,
|
||||||
PhotoViewGallery.builder(
|
child: AnimatedOpacity(
|
||||||
gaplessPlayback: true,
|
opacity: showingControls ? 1.0 : 0.0,
|
||||||
loadingBuilder: _placeholderBuilder,
|
duration: Durations.short2,
|
||||||
pageController: pageController,
|
child: const DownloadStatusFloatingButton(),
|
||||||
scrollPhysics: CurrentPlatform.isIOS
|
|
||||||
? const FastScrollPhysics() // Use bouncing physics for iOS
|
|
||||||
: const FastClampingScrollPhysics(), // Use heavy physics for Android
|
|
||||||
itemCount: totalAssets,
|
|
||||||
onPageChanged: _onPageChanged,
|
|
||||||
onPageBuild: _onPageBuild,
|
|
||||||
scaleStateChangedCallback: _onScaleStateChanged,
|
|
||||||
builder: _assetBuilder,
|
|
||||||
backgroundDecoration: BoxDecoration(color: backgroundColor),
|
|
||||||
enablePanAlways: true,
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
body: Stack(
|
||||||
bottomNavigationBar: showingBottomSheet
|
children: [
|
||||||
? const SizedBox.shrink()
|
PhotoViewGallery.builder(
|
||||||
: const Column(
|
gaplessPlayback: true,
|
||||||
mainAxisSize: MainAxisSize.min,
|
loadingBuilder: _placeholderBuilder,
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
pageController: pageController,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
scrollPhysics: CurrentPlatform.isIOS
|
||||||
children: [AssetStackRow(), ViewerBottomBar()],
|
? const FastScrollPhysics() // Use bouncing physics for iOS
|
||||||
|
: const FastClampingScrollPhysics(), // Use heavy physics for Android
|
||||||
|
itemCount: totalAssets,
|
||||||
|
onPageChanged: _onPageChanged,
|
||||||
|
onPageBuild: _onPageBuild,
|
||||||
|
scaleStateChangedCallback: _onScaleStateChanged,
|
||||||
|
builder: _assetBuilder,
|
||||||
|
backgroundDecoration: BoxDecoration(color: backgroundColor),
|
||||||
|
enablePanAlways: true,
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
bottomNavigationBar: showingBottomSheet
|
||||||
|
? const SizedBox.shrink()
|
||||||
|
: const Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [AssetStackRow(), ViewerBottomBar()],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user