mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
fix(mobile): stack row blocking gestures and not showing up (#21854)
This commit is contained in:
parent
28e9892ed3
commit
9ae42106cc
6 changed files with 121 additions and 86 deletions
|
|
@ -3,7 +3,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.provider.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart';
|
||||
|
||||
class AssetStackRow extends ConsumerWidget {
|
||||
|
|
@ -11,27 +11,25 @@ class AssetStackRow extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
int opacity = ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity));
|
||||
final showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls));
|
||||
|
||||
if (!showControls) {
|
||||
opacity = 0;
|
||||
final asset = ref.watch(assetViewerProvider.select((state) => state.currentAsset));
|
||||
if (asset == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final asset = ref.watch(assetViewerProvider.select((s) => s.currentAsset));
|
||||
final stackChildren = ref.watch(stackChildrenNotifier(asset)).valueOrNull;
|
||||
if (stackChildren == null || stackChildren.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls));
|
||||
final opacity = showControls ? ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity)) : 0;
|
||||
|
||||
return IgnorePointer(
|
||||
ignoring: opacity < 255,
|
||||
child: AnimatedOpacity(
|
||||
opacity: opacity / 255,
|
||||
duration: Durations.short2,
|
||||
child: ref
|
||||
.watch(stackChildrenNotifier(asset))
|
||||
.when(
|
||||
data: (state) => SizedBox.square(dimension: 80, child: _StackList(stack: state)),
|
||||
error: (_, __) => const SizedBox.shrink(),
|
||||
loading: () => const SizedBox.shrink(),
|
||||
),
|
||||
child: _StackList(stack: stackChildren),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -44,58 +42,77 @@ class _StackList extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.only(left: 5, right: 5, bottom: 30),
|
||||
itemCount: stack.length,
|
||||
itemBuilder: (ctx, index) {
|
||||
final asset = stack[index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 5),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
ref.read(assetViewerProvider.notifier).setStackIndex(index);
|
||||
ref.read(currentAssetNotifier.notifier).setAsset(asset);
|
||||
},
|
||||
child: Container(
|
||||
height: 60,
|
||||
width: 60,
|
||||
decoration: index == ref.watch(assetViewerProvider.select((s) => s.stackIndex))
|
||||
? const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.all(Radius.circular(6)),
|
||||
border: Border.fromBorderSide(BorderSide(color: Colors.white, width: 2)),
|
||||
)
|
||||
: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.all(Radius.circular(6)),
|
||||
border: null,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Image(
|
||||
fit: BoxFit.cover,
|
||||
image: getThumbnailImageProvider(remoteId: asset.id, size: const Size.square(60)),
|
||||
),
|
||||
if (asset.isVideo)
|
||||
const Icon(
|
||||
Icons.play_circle_outline_rounded,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
shadows: [
|
||||
Shadow(blurRadius: 5.0, color: Color.fromRGBO(0, 0, 0, 0.6), offset: Offset(0.0, 0.0)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
return Center(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 10.0, right: 10.0, bottom: 20.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 5.0,
|
||||
children: List.generate(stack.length, (i) {
|
||||
final asset = stack[i];
|
||||
return _StackItem(key: ValueKey(asset.heroTag), asset: asset, index: i);
|
||||
}),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _StackItem extends ConsumerStatefulWidget {
|
||||
final RemoteAsset asset;
|
||||
final int index;
|
||||
|
||||
const _StackItem({super.key, required this.asset, required this.index});
|
||||
|
||||
@override
|
||||
ConsumerState<_StackItem> createState() => _StackItemState();
|
||||
}
|
||||
|
||||
class _StackItemState extends ConsumerState<_StackItem> {
|
||||
void _onTap() {
|
||||
ref.read(currentAssetNotifier.notifier).setAsset(widget.asset);
|
||||
ref.read(assetViewerProvider.notifier).setStackIndex(widget.index);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const playIcon = Center(
|
||||
child: Icon(
|
||||
Icons.play_circle_outline_rounded,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
shadows: [Shadow(blurRadius: 5.0, color: Color.fromRGBO(0, 0, 0, 0.6), offset: Offset(0.0, 0.0))],
|
||||
),
|
||||
);
|
||||
const selectedDecoration = BoxDecoration(
|
||||
border: Border.fromBorderSide(BorderSide(color: Colors.white, width: 2)),
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
);
|
||||
const unselectedDecoration = BoxDecoration(
|
||||
border: Border.fromBorderSide(BorderSide(color: Colors.grey, width: 0.5)),
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
);
|
||||
|
||||
Widget thumbnail = Thumbnail.fromAsset(asset: widget.asset, size: const Size(60, 40));
|
||||
if (widget.asset.isVideo) {
|
||||
thumbnail = Stack(children: [thumbnail, playIcon]);
|
||||
}
|
||||
thumbnail = ClipRRect(borderRadius: const BorderRadius.all(Radius.circular(10)), child: thumbnail);
|
||||
final isSelected = ref.watch(assetViewerProvider.select((s) => s.stackIndex == widget.index));
|
||||
return SizedBox(
|
||||
width: 60,
|
||||
height: 40,
|
||||
child: GestureDetector(
|
||||
onTap: _onTap,
|
||||
child: DecoratedBox(
|
||||
decoration: isSelected ? selectedDecoration : unselectedDecoration,
|
||||
position: DecorationPosition.foreground,
|
||||
child: thumbnail,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue