mirror of
https://github.com/immich-app/immich.git
synced 2026-04-12 20:22:10 -04:00
We are generally looking to move away from hooks as they are hard to reason about and have weird bugs. In particular, the timer did not properly capture the ref of the callback, and so it would execute on old state. A standard stateful widget does not have this problem, and is easier to organise. Co-authored-by: Alex <alex.tran1502@gmail.com>
88 lines
3.9 KiB
Dart
88 lines
3.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
import 'package:immich_mobile/constants/enums.dart';
|
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
|
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_action_button.widget.dart';
|
|
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart';
|
|
import 'package:immich_mobile/presentation/widgets/action_buttons/edit_image_action_button.widget.dart';
|
|
import 'package:immich_mobile/presentation/widgets/action_buttons/share_action_button.widget.dart';
|
|
import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart';
|
|
import 'package:immich_mobile/presentation/widgets/action_buttons/add_action_button.widget.dart';
|
|
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
|
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
|
|
import 'package:immich_mobile/providers/routes.provider.dart';
|
|
import 'package:immich_mobile/providers/user.provider.dart';
|
|
import 'package:immich_mobile/widgets/asset_viewer/video_controls.dart';
|
|
|
|
class ViewerBottomBar extends ConsumerWidget {
|
|
const ViewerBottomBar({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final asset = ref.watch(assetViewerProvider.select((s) => s.currentAsset));
|
|
if (asset == null) {
|
|
return const SizedBox.shrink();
|
|
}
|
|
|
|
final isReadonlyModeEnabled = ref.watch(readonlyModeProvider);
|
|
final user = ref.watch(currentUserProvider);
|
|
final isOwner = asset is RemoteAsset && asset.ownerId == user?.id;
|
|
final showingDetails = ref.watch(assetViewerProvider.select((s) => s.showingDetails));
|
|
final isInLockedView = ref.watch(inLockedViewProvider);
|
|
|
|
final originalTheme = context.themeData;
|
|
|
|
final actions = <Widget>[
|
|
const ShareActionButton(source: ActionSource.viewer),
|
|
|
|
if (!isInLockedView) ...[
|
|
if (asset.isLocalOnly) const UploadActionButton(source: ActionSource.viewer),
|
|
if (asset.type == AssetType.image) const EditImageActionButton(),
|
|
if (asset.hasRemote) AddActionButton(originalTheme: originalTheme),
|
|
|
|
if (isOwner) ...[
|
|
asset.isLocalOnly
|
|
? const DeleteLocalActionButton(source: ActionSource.viewer)
|
|
: const DeleteActionButton(source: ActionSource.viewer, showConfirmation: true),
|
|
],
|
|
],
|
|
];
|
|
|
|
return AnimatedSwitcher(
|
|
duration: Durations.short4,
|
|
child: showingDetails
|
|
? const SizedBox.shrink()
|
|
: Theme(
|
|
data: context.themeData.copyWith(
|
|
iconTheme: const IconThemeData(size: 22, color: Colors.white),
|
|
textTheme: context.themeData.textTheme.copyWith(
|
|
labelLarge: context.themeData.textTheme.labelLarge?.copyWith(color: Colors.white),
|
|
),
|
|
),
|
|
child: Container(
|
|
decoration: const BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.bottomCenter,
|
|
end: Alignment.topCenter,
|
|
colors: [Colors.black45, Colors.black12, Colors.transparent],
|
|
stops: [0.0, 0.7, 1.0],
|
|
),
|
|
),
|
|
child: SafeArea(
|
|
top: false,
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
if (asset.isVideo) VideoControls(videoPlayerName: asset.heroTag),
|
|
if (!isReadonlyModeEnabled)
|
|
Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: actions),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|