mirror of
https://github.com/immich-app/immich.git
synced 2025-11-03 02:57:10 -05:00
refactor: bottom sheet action button (#20964)
* fix: incorrect archive action shown in asset viewer' * Refactor * use enums syntax and add tests
This commit is contained in:
parent
cd6d8fcdfe
commit
ec01db5c8b
@ -44,6 +44,7 @@ class LikeActivityActionButton extends ConsumerWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return BaseActionButton(
|
return BaseActionButton(
|
||||||
|
maxWidth: 60,
|
||||||
iconData: liked != null ? Icons.favorite : Icons.favorite_border,
|
iconData: liked != null ? Icons.favorite : Icons.favorite_border,
|
||||||
label: "like".t(context: context),
|
label: "like".t(context: context),
|
||||||
onPressed: () => onTap(liked),
|
onPressed: () => onTap(liked),
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/delete_action_
|
|||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_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/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/share_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/unarchive_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/upload_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart';
|
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.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';
|
||||||
@ -31,6 +32,7 @@ class ViewerBottomBar extends ConsumerWidget {
|
|||||||
int opacity = ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity));
|
int opacity = ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity));
|
||||||
final showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls));
|
final showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls));
|
||||||
final isInLockedView = ref.watch(inLockedViewProvider);
|
final isInLockedView = ref.watch(inLockedViewProvider);
|
||||||
|
final isArchived = asset is RemoteAsset && asset.visibility == AssetVisibility.archive;
|
||||||
|
|
||||||
if (!showControls) {
|
if (!showControls) {
|
||||||
opacity = 0;
|
opacity = 0;
|
||||||
@ -40,10 +42,15 @@ class ViewerBottomBar extends ConsumerWidget {
|
|||||||
const ShareActionButton(source: ActionSource.viewer),
|
const ShareActionButton(source: ActionSource.viewer),
|
||||||
if (asset.isLocalOnly) const UploadActionButton(source: ActionSource.viewer),
|
if (asset.isLocalOnly) const UploadActionButton(source: ActionSource.viewer),
|
||||||
if (asset.type == AssetType.image) const EditImageActionButton(),
|
if (asset.type == AssetType.image) const EditImageActionButton(),
|
||||||
if (asset.hasRemote && isOwner) const ArchiveActionButton(source: ActionSource.viewer),
|
if (isOwner) ...[
|
||||||
asset.isLocalOnly
|
if (asset.hasRemote && isOwner && isArchived)
|
||||||
? const DeleteLocalActionButton(source: ActionSource.viewer)
|
const UnArchiveActionButton(source: ActionSource.viewer)
|
||||||
: const DeleteActionButton(source: ActionSource.viewer, showConfirmation: true),
|
else
|
||||||
|
const ArchiveActionButton(source: ActionSource.viewer),
|
||||||
|
asset.isLocalOnly
|
||||||
|
? const DeleteLocalActionButton(source: ActionSource.viewer)
|
||||||
|
: const DeleteActionButton(source: ActionSource.viewer, showConfirmation: true),
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
return IgnorePointer(
|
return IgnorePointer(
|
||||||
|
|||||||
@ -6,18 +6,6 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|||||||
import 'package:immich_mobile/domain/models/exif.model.dart';
|
import 'package:immich_mobile/domain/models/exif.model.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/archive_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/delete_local_action_button.widget.dart';
|
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permanent_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/like_activity_action_button.widget.dart';
|
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/move_to_lock_folder_action_button.widget.dart';
|
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/remove_from_album_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/share_link_action_button.widget.dart';
|
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_button.widget.dart';
|
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart';
|
|
||||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_sheet/sheet_location_details.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_sheet/sheet_location_details.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_sheet/sheet_people_details.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_sheet/sheet_people_details.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
|
||||||
@ -26,6 +14,8 @@ import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asse
|
|||||||
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/routes.provider.dart';
|
import 'package:immich_mobile/providers/routes.provider.dart';
|
||||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
|
import 'package:immich_mobile/utils/action_button.utils.dart';
|
||||||
import 'package:immich_mobile/utils/bytes_units.dart';
|
import 'package:immich_mobile/utils/bytes_units.dart';
|
||||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||||
|
|
||||||
@ -45,34 +35,25 @@ class AssetDetailBottomSheet extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash));
|
final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash));
|
||||||
|
final isOwner = asset is RemoteAsset && asset.ownerId == ref.watch(currentUserProvider)?.id;
|
||||||
final isInLockedView = ref.watch(inLockedViewProvider);
|
final isInLockedView = ref.watch(inLockedViewProvider);
|
||||||
final currentAlbum = ref.watch(currentRemoteAlbumProvider);
|
final currentAlbum = ref.watch(currentRemoteAlbumProvider);
|
||||||
|
final isArchived = asset is RemoteAsset && asset.visibility == AssetVisibility.archive;
|
||||||
|
|
||||||
final actions = <Widget>[
|
final buttonContext = ActionButtonContext(
|
||||||
const ShareActionButton(source: ActionSource.viewer),
|
asset: asset,
|
||||||
if (currentAlbum != null && currentAlbum.isActivityEnabled && currentAlbum.isShared)
|
isOwner: isOwner,
|
||||||
const LikeActivityActionButton(),
|
isArchived: isArchived,
|
||||||
if (asset.hasRemote) ...[
|
isTrashEnabled: isTrashEnable,
|
||||||
const ShareLinkActionButton(source: ActionSource.viewer),
|
isInLockedView: isInLockedView,
|
||||||
const ArchiveActionButton(source: ActionSource.viewer),
|
currentAlbum: currentAlbum,
|
||||||
if (!asset.hasLocal) const DownloadActionButton(source: ActionSource.viewer),
|
source: ActionSource.viewer,
|
||||||
isTrashEnable
|
);
|
||||||
? const TrashActionButton(source: ActionSource.viewer)
|
|
||||||
: const DeletePermanentActionButton(source: ActionSource.viewer),
|
|
||||||
const DeleteActionButton(source: ActionSource.viewer),
|
|
||||||
const MoveToLockFolderActionButton(source: ActionSource.viewer),
|
|
||||||
],
|
|
||||||
if (asset.storage == AssetState.local) ...[
|
|
||||||
const DeleteLocalActionButton(source: ActionSource.viewer),
|
|
||||||
const UploadActionButton(source: ActionSource.timeline),
|
|
||||||
],
|
|
||||||
if (currentAlbum != null) RemoveFromAlbumActionButton(albumId: currentAlbum.id, source: ActionSource.viewer),
|
|
||||||
];
|
|
||||||
|
|
||||||
final lockedViewActions = <Widget>[];
|
final actions = ActionButtonBuilder.build(buttonContext);
|
||||||
|
|
||||||
return BaseBottomSheet(
|
return BaseBottomSheet(
|
||||||
actions: isInLockedView ? lockedViewActions : actions,
|
actions: actions,
|
||||||
slivers: const [_AssetDetailBottomSheet()],
|
slivers: const [_AssetDetailBottomSheet()],
|
||||||
controller: controller,
|
controller: controller,
|
||||||
initialChildSize: initialChildSize,
|
initialChildSize: initialChildSize,
|
||||||
|
|||||||
@ -69,10 +69,8 @@ class _BaseDraggableScrollableSheetState extends ConsumerState<BaseBottomSheet>
|
|||||||
shouldCloseOnMinExtent: widget.shouldCloseOnMinExtent,
|
shouldCloseOnMinExtent: widget.shouldCloseOnMinExtent,
|
||||||
builder: (BuildContext context, ScrollController scrollController) {
|
builder: (BuildContext context, ScrollController scrollController) {
|
||||||
return Card(
|
return Card(
|
||||||
color: widget.backgroundColor ?? context.colorScheme.surface,
|
color: widget.backgroundColor ?? context.colorScheme.surfaceContainer,
|
||||||
borderOnForeground: false,
|
elevation: 3.0,
|
||||||
clipBehavior: Clip.antiAlias,
|
|
||||||
elevation: 6.0,
|
|
||||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(18))),
|
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(18))),
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 0),
|
margin: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
|
|||||||
160
mobile/lib/utils/action_button.utils.dart
Normal file
160
mobile/lib/utils/action_button.utils.dart
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:immich_mobile/constants/enums.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/archive_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/delete_local_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permanent_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/like_activity_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/move_to_lock_folder_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/remove_from_album_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/remove_from_lock_folder_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/share_link_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/unarchive_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
|
||||||
|
class ActionButtonContext {
|
||||||
|
final BaseAsset asset;
|
||||||
|
final bool isOwner;
|
||||||
|
final bool isArchived;
|
||||||
|
final bool isTrashEnabled;
|
||||||
|
final bool isInLockedView;
|
||||||
|
final RemoteAlbum? currentAlbum;
|
||||||
|
final ActionSource source;
|
||||||
|
|
||||||
|
const ActionButtonContext({
|
||||||
|
required this.asset,
|
||||||
|
required this.isOwner,
|
||||||
|
required this.isArchived,
|
||||||
|
required this.isTrashEnabled,
|
||||||
|
required this.isInLockedView,
|
||||||
|
required this.currentAlbum,
|
||||||
|
required this.source,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ActionButtonType {
|
||||||
|
share,
|
||||||
|
shareLink,
|
||||||
|
archive,
|
||||||
|
unarchive,
|
||||||
|
download,
|
||||||
|
trash,
|
||||||
|
deletePermanent,
|
||||||
|
delete,
|
||||||
|
moveToLockFolder,
|
||||||
|
removeFromLockFolder,
|
||||||
|
deleteLocal,
|
||||||
|
upload,
|
||||||
|
removeFromAlbum,
|
||||||
|
likeActivity;
|
||||||
|
|
||||||
|
bool shouldShow(ActionButtonContext context) {
|
||||||
|
return switch (this) {
|
||||||
|
ActionButtonType.share => true,
|
||||||
|
ActionButtonType.shareLink =>
|
||||||
|
!context.isInLockedView && //
|
||||||
|
context.asset.hasRemote,
|
||||||
|
ActionButtonType.archive =>
|
||||||
|
context.isOwner && //
|
||||||
|
!context.isInLockedView && //
|
||||||
|
context.asset.hasRemote && //
|
||||||
|
!context.isArchived,
|
||||||
|
ActionButtonType.unarchive =>
|
||||||
|
context.isOwner && //
|
||||||
|
!context.isInLockedView && //
|
||||||
|
context.asset.hasRemote && //
|
||||||
|
context.isArchived,
|
||||||
|
ActionButtonType.download =>
|
||||||
|
!context.isInLockedView && //
|
||||||
|
context.asset.hasRemote && //
|
||||||
|
!context.asset.hasLocal,
|
||||||
|
ActionButtonType.trash =>
|
||||||
|
context.isOwner && //
|
||||||
|
!context.isInLockedView && //
|
||||||
|
context.asset.hasRemote && //
|
||||||
|
context.isTrashEnabled,
|
||||||
|
ActionButtonType.deletePermanent =>
|
||||||
|
context.isOwner && //
|
||||||
|
context.asset.hasRemote && //
|
||||||
|
!context.isTrashEnabled ||
|
||||||
|
context.isInLockedView,
|
||||||
|
ActionButtonType.delete =>
|
||||||
|
context.isOwner && //
|
||||||
|
!context.isInLockedView && //
|
||||||
|
context.asset.hasRemote,
|
||||||
|
ActionButtonType.moveToLockFolder =>
|
||||||
|
context.isOwner && //
|
||||||
|
!context.isInLockedView && //
|
||||||
|
context.asset.hasRemote,
|
||||||
|
ActionButtonType.removeFromLockFolder =>
|
||||||
|
context.isOwner && //
|
||||||
|
context.isInLockedView && //
|
||||||
|
context.asset.hasRemote,
|
||||||
|
ActionButtonType.deleteLocal =>
|
||||||
|
!context.isInLockedView && //
|
||||||
|
context.asset.storage == AssetState.local,
|
||||||
|
ActionButtonType.upload =>
|
||||||
|
!context.isInLockedView && //
|
||||||
|
context.asset.storage == AssetState.local,
|
||||||
|
ActionButtonType.removeFromAlbum =>
|
||||||
|
context.isOwner && //
|
||||||
|
!context.isInLockedView && //
|
||||||
|
context.currentAlbum != null,
|
||||||
|
ActionButtonType.likeActivity =>
|
||||||
|
!context.isInLockedView &&
|
||||||
|
context.currentAlbum != null &&
|
||||||
|
context.currentAlbum!.isActivityEnabled &&
|
||||||
|
context.currentAlbum!.isShared,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildButton(ActionButtonContext context) {
|
||||||
|
return switch (this) {
|
||||||
|
ActionButtonType.share => ShareActionButton(source: context.source),
|
||||||
|
ActionButtonType.shareLink => ShareLinkActionButton(source: context.source),
|
||||||
|
ActionButtonType.archive => ArchiveActionButton(source: context.source),
|
||||||
|
ActionButtonType.unarchive => UnArchiveActionButton(source: context.source),
|
||||||
|
ActionButtonType.download => DownloadActionButton(source: context.source),
|
||||||
|
ActionButtonType.trash => TrashActionButton(source: context.source),
|
||||||
|
ActionButtonType.deletePermanent => DeletePermanentActionButton(source: context.source),
|
||||||
|
ActionButtonType.delete => DeleteActionButton(source: context.source),
|
||||||
|
ActionButtonType.moveToLockFolder => MoveToLockFolderActionButton(source: context.source),
|
||||||
|
ActionButtonType.removeFromLockFolder => RemoveFromLockFolderActionButton(source: context.source),
|
||||||
|
ActionButtonType.deleteLocal => DeleteLocalActionButton(source: context.source),
|
||||||
|
ActionButtonType.upload => UploadActionButton(source: context.source),
|
||||||
|
ActionButtonType.removeFromAlbum => RemoveFromAlbumActionButton(
|
||||||
|
albumId: context.currentAlbum!.id,
|
||||||
|
source: context.source,
|
||||||
|
),
|
||||||
|
ActionButtonType.likeActivity => const LikeActivityActionButton(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ActionButtonBuilder {
|
||||||
|
static const List<ActionButtonType> _actionTypes = [
|
||||||
|
ActionButtonType.share,
|
||||||
|
ActionButtonType.shareLink,
|
||||||
|
ActionButtonType.likeActivity,
|
||||||
|
ActionButtonType.archive,
|
||||||
|
ActionButtonType.unarchive,
|
||||||
|
ActionButtonType.download,
|
||||||
|
ActionButtonType.trash,
|
||||||
|
ActionButtonType.deletePermanent,
|
||||||
|
ActionButtonType.delete,
|
||||||
|
ActionButtonType.moveToLockFolder,
|
||||||
|
ActionButtonType.removeFromLockFolder,
|
||||||
|
ActionButtonType.deleteLocal,
|
||||||
|
ActionButtonType.upload,
|
||||||
|
ActionButtonType.removeFromAlbum,
|
||||||
|
];
|
||||||
|
|
||||||
|
static List<Widget> build(ActionButtonContext context) {
|
||||||
|
return _actionTypes.where((type) => type.shouldShow(context)).map((type) => type.buildButton(context)).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
717
mobile/test/utils/action_button_utils_test.dart
Normal file
717
mobile/test/utils/action_button_utils_test.dart
Normal file
@ -0,0 +1,717 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:immich_mobile/constants/enums.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/utils/action_button.utils.dart';
|
||||||
|
|
||||||
|
LocalAsset createLocalAsset({
|
||||||
|
String? remoteId,
|
||||||
|
String name = 'test.jpg',
|
||||||
|
String? checksum = 'test-checksum',
|
||||||
|
AssetType type = AssetType.image,
|
||||||
|
DateTime? createdAt,
|
||||||
|
DateTime? updatedAt,
|
||||||
|
bool isFavorite = false,
|
||||||
|
}) {
|
||||||
|
return LocalAsset(
|
||||||
|
id: 'local-id',
|
||||||
|
remoteId: remoteId,
|
||||||
|
name: name,
|
||||||
|
checksum: checksum,
|
||||||
|
type: type,
|
||||||
|
createdAt: createdAt ?? DateTime.now(),
|
||||||
|
updatedAt: updatedAt ?? DateTime.now(),
|
||||||
|
isFavorite: isFavorite,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteAsset createRemoteAsset({
|
||||||
|
String? localId,
|
||||||
|
String name = 'test.jpg',
|
||||||
|
String checksum = 'test-checksum',
|
||||||
|
AssetType type = AssetType.image,
|
||||||
|
DateTime? createdAt,
|
||||||
|
DateTime? updatedAt,
|
||||||
|
bool isFavorite = false,
|
||||||
|
}) {
|
||||||
|
return RemoteAsset(
|
||||||
|
id: 'remote-id',
|
||||||
|
localId: localId,
|
||||||
|
name: name,
|
||||||
|
checksum: checksum,
|
||||||
|
type: type,
|
||||||
|
ownerId: 'owner-id',
|
||||||
|
createdAt: createdAt ?? DateTime.now(),
|
||||||
|
updatedAt: updatedAt ?? DateTime.now(),
|
||||||
|
isFavorite: isFavorite,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteAlbum createRemoteAlbum({
|
||||||
|
String id = 'test-album-id',
|
||||||
|
String name = 'Test Album',
|
||||||
|
bool isActivityEnabled = false,
|
||||||
|
bool isShared = false,
|
||||||
|
}) {
|
||||||
|
return RemoteAlbum(
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
ownerId: 'owner-id',
|
||||||
|
description: 'Test Description',
|
||||||
|
createdAt: DateTime.now(),
|
||||||
|
updatedAt: DateTime.now(),
|
||||||
|
isActivityEnabled: isActivityEnabled,
|
||||||
|
isShared: isShared,
|
||||||
|
order: AlbumAssetOrder.asc,
|
||||||
|
assetCount: 0,
|
||||||
|
ownerName: 'Test Owner',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('ActionButtonContext', () {
|
||||||
|
test('should create context with all required parameters', () {
|
||||||
|
final asset = createLocalAsset();
|
||||||
|
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: asset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(context.asset, isA<BaseAsset>());
|
||||||
|
expect(context.isOwner, isTrue);
|
||||||
|
expect(context.isArchived, isFalse);
|
||||||
|
expect(context.isTrashEnabled, isTrue);
|
||||||
|
expect(context.isInLockedView, isFalse);
|
||||||
|
expect(context.currentAlbum, isNull);
|
||||||
|
expect(context.source, ActionSource.timeline);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('ActionButtonType.shouldShow', () {
|
||||||
|
late BaseAsset mergedAsset;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
mergedAsset = createLocalAsset(remoteId: 'remote-id');
|
||||||
|
});
|
||||||
|
|
||||||
|
group('share button', () {
|
||||||
|
test('should show when not in locked view', () {
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: mergedAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.share.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should show when in locked view', () {
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: mergedAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: true,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.share.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('shareLink button', () {
|
||||||
|
test('should show when not in locked view and asset has remote', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.shareLink.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when in locked view', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: true,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.shareLink.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when asset has no remote', () {
|
||||||
|
final localAsset = createLocalAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: localAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.shareLink.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('archive button', () {
|
||||||
|
test('should show when owner, not locked, has remote, and not archived', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.archive.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when not owner', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: false,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.archive.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when in locked view', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: true,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.archive.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when asset has no remote', () {
|
||||||
|
final localAsset = createLocalAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: localAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.archive.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when already archived', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: true,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.archive.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('unarchive button', () {
|
||||||
|
test('should show when owner, not locked, has remote, and is archived', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: true,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.unarchive.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when not archived', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.unarchive.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when not owner', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: false,
|
||||||
|
isArchived: true,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.unarchive.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('download button', () {
|
||||||
|
test('should show when not locked, has remote, and no local copy', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.download.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when has local copy', () {
|
||||||
|
final mergedAsset = createLocalAsset(remoteId: 'remote-id');
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: mergedAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.download.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when in locked view', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: true,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.download.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('trash button', () {
|
||||||
|
test('should show when owner, not locked, has remote, and trash enabled', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.trash.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when trash disabled', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: false,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.trash.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('deletePermanent button', () {
|
||||||
|
test('should show when owner, not locked, has remote, and trash disabled', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: false,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.deletePermanent.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when trash enabled', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.deletePermanent.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('delete button', () {
|
||||||
|
test('should show when owner, not locked, and has remote', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.delete.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('moveToLockFolder button', () {
|
||||||
|
test('should show when owner, not locked, and has remote', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.moveToLockFolder.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('deleteLocal button', () {
|
||||||
|
test('should show when not locked and asset is local only', () {
|
||||||
|
final localAsset = createLocalAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: localAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.deleteLocal.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when asset is not local only', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.deleteLocal.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('upload button', () {
|
||||||
|
test('should show when not locked and asset is local only', () {
|
||||||
|
final localAsset = createLocalAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: localAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.upload.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('removeFromAlbum button', () {
|
||||||
|
test('should show when owner, not locked, and has current album', () {
|
||||||
|
final album = createRemoteAlbum();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: mergedAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: album,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.removeFromAlbum.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when no current album', () {
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: mergedAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.removeFromAlbum.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('likeActivity button', () {
|
||||||
|
test('should show when not locked, has album, activity enabled, and shared', () {
|
||||||
|
final album = createRemoteAlbum(isActivityEnabled: true, isShared: true);
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: mergedAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: album,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.likeActivity.shouldShow(context), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when activity not enabled', () {
|
||||||
|
final album = createRemoteAlbum(isActivityEnabled: false, isShared: true);
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: mergedAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: album,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.likeActivity.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when album not shared', () {
|
||||||
|
final album = createRemoteAlbum(isActivityEnabled: true, isShared: false);
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: mergedAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: album,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.likeActivity.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show when no album', () {
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: mergedAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ActionButtonType.likeActivity.shouldShow(context), isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('ActionButtonType.buildButton', () {
|
||||||
|
late BaseAsset asset;
|
||||||
|
late ActionButtonContext context;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
asset = createLocalAsset(remoteId: 'remote-id');
|
||||||
|
context = ActionButtonContext(
|
||||||
|
asset: asset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should build correct widget for each button type', () {
|
||||||
|
for (final buttonType in ActionButtonType.values) {
|
||||||
|
if (buttonType == ActionButtonType.removeFromAlbum) {
|
||||||
|
final album = createRemoteAlbum();
|
||||||
|
final contextWithAlbum = ActionButtonContext(
|
||||||
|
asset: asset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: album,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
final widget = buttonType.buildButton(contextWithAlbum);
|
||||||
|
expect(widget, isA<Widget>());
|
||||||
|
} else {
|
||||||
|
final widget = buttonType.buildButton(context);
|
||||||
|
expect(widget, isA<Widget>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('ActionButtonBuilder', () {
|
||||||
|
test('should return buttons that should show', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
final widgets = ActionButtonBuilder.build(context);
|
||||||
|
|
||||||
|
expect(widgets, isNotEmpty);
|
||||||
|
expect(widgets.length, greaterThan(0));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should include album-specific buttons when album is present', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
final album = createRemoteAlbum(isActivityEnabled: true, isShared: true);
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: album,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
final widgets = ActionButtonBuilder.build(context);
|
||||||
|
|
||||||
|
expect(widgets, isNotEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should only include local buttons for local assets', () {
|
||||||
|
final localAsset = createLocalAsset();
|
||||||
|
final context = ActionButtonContext(
|
||||||
|
asset: localAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
final widgets = ActionButtonBuilder.build(context);
|
||||||
|
|
||||||
|
expect(widgets, isNotEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should respect archived state', () {
|
||||||
|
final remoteAsset = createRemoteAsset();
|
||||||
|
|
||||||
|
final archivedContext = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: true,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
final archivedWidgets = ActionButtonBuilder.build(archivedContext);
|
||||||
|
|
||||||
|
final nonArchivedContext = ActionButtonContext(
|
||||||
|
asset: remoteAsset,
|
||||||
|
isOwner: true,
|
||||||
|
isArchived: false,
|
||||||
|
isTrashEnabled: true,
|
||||||
|
isInLockedView: false,
|
||||||
|
currentAlbum: null,
|
||||||
|
source: ActionSource.timeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
final nonArchivedWidgets = ActionButtonBuilder.build(nonArchivedContext);
|
||||||
|
|
||||||
|
expect(archivedWidgets, isNotEmpty);
|
||||||
|
expect(nonArchivedWidgets, isNotEmpty);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user