feat(mobile): editors can update album title & description (#31959)

feat(mobile): editors can update album title & description (#31954)


(cherry picked from commit cc916979502390640e186e421f84f3ce7414c884)

Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
immich-push-o-matic[bot]
2026-09-30 21:26:59 +00:00
committed by GitHub
co-authored by shenlong shenlong-tanwen
parent f4b47bf350
commit c263b0d4d2
2 changed files with 40 additions and 33 deletions
@@ -4,6 +4,7 @@ enum ServerCapability {
// Feature Support
cloudIdMetadata(SemVer(major: 2, minor: 4, patch: 0)),
bulkCloudIdMetadata(SemVer(major: 2, minor: 5, patch: 0)),
albumEditorUpdate(SemVer(major: 2, minor: 6, patch: 2)),
// Sync
syncV2(SemVer(major: 3, minor: 0, patch: 0)),
@@ -6,6 +6,7 @@ import 'package:flutter/services.dart';
import 'package:hooks_riverpod/hooks_riverpod.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/server_capability.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/album/pending_uploads_banner.widget.dart';
@@ -16,6 +17,7 @@ import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/remote_album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/providers/server_info.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
@@ -187,6 +189,9 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
Widget build(BuildContext context) {
final user = ref.watch(currentUserProvider);
final isOwner = user != null ? user.id == _album.ownerId : false;
final editorCanUpdate = ref.watch(
serverInfoProvider.select((state) => state.serverVersion.supports(.albumEditorUpdate)),
);
return ProviderScope(
overrides: [
@@ -199,19 +204,30 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
],
child: Timeline(
topSliverWidget: PendingUploadsBanner(albumId: _album.id),
appBar: RemoteAlbumSliverAppBar(
kebabMenu: _AlbumKebabMenu(
album: _album,
onDeleteAlbum: () => deleteAlbum(context),
onAddUsers: () => addUsers(context),
onAddPhotos: () => addAssets(context),
onToggleAlbumOrder: () => toggleAlbumOrder(),
onEditAlbum: () => showEditTitleAndDescription(context),
onCreateSharedLink: () => unawaited(context.pushRoute(SharedLinkEditRoute(albumId: _album.id))),
onShowOptions: () => context.pushRoute(AlbumOptionsRoute(album: _album)),
),
onEditTitle: isOwner ? () => showEditTitleAndDescription(context) : null,
onActivity: () => showActivity(context),
appBar: FutureBuilder<bool>(
future: ref
.watch(remoteAlbumServiceProvider)
.getUserRole(_album.id, user?.id ?? '')
.then((role) => role == AlbumUserRole.editor),
builder: (_, snapshot) {
final isEditor = snapshot.data ?? false;
final canEdit = isOwner || (isEditor && editorCanUpdate);
return RemoteAlbumSliverAppBar(
kebabMenu: _AlbumKebabMenu(
album: _album,
onDeleteAlbum: () => deleteAlbum(context),
onAddUsers: () => addUsers(context),
onAddPhotos: isOwner || isEditor ? () => addAssets(context) : null,
onToggleAlbumOrder: () => toggleAlbumOrder(),
onEditAlbum: canEdit ? () => showEditTitleAndDescription(context) : null,
onCreateSharedLink: () => unawaited(context.pushRoute(SharedLinkEditRoute(albumId: _album.id))),
onShowOptions: () => context.pushRoute(AlbumOptionsRoute(album: _album)),
),
onEditTitle: canEdit ? () => showEditTitleAndDescription(context) : null,
onActivity: () => showActivity(context),
);
},
),
bottomSheet: RemoteAlbumBottomSheet(album: _album),
),
@@ -419,26 +435,16 @@ class _AlbumKebabMenu extends ConsumerWidget {
final user = ref.watch(currentUserProvider);
final isOwner = user != null && user.id == album.ownerId;
return FutureBuilder<bool>(
future: ref
.watch(remoteAlbumServiceProvider)
.getUserRole(album.id, user?.id ?? '')
.then((role) => role == AlbumUserRole.editor),
builder: (context, snapshot) {
final canAddPhotos = snapshot.data ?? false;
return RemoteAlbumOption(
iconColor: iconColor,
iconShadows: iconShadows,
onDeleteAlbum: isOwner ? onDeleteAlbum : null,
onAddUsers: isOwner ? onAddUsers : null,
onAddPhotos: isOwner || canAddPhotos ? onAddPhotos : null,
onToggleAlbumOrder: isOwner ? onToggleAlbumOrder : null,
onEditAlbum: isOwner ? onEditAlbum : null,
onCreateSharedLink: isOwner ? onCreateSharedLink : null,
onShowOptions: onShowOptions,
);
},
return RemoteAlbumOption(
iconColor: iconColor,
iconShadows: iconShadows,
onDeleteAlbum: isOwner ? onDeleteAlbum : null,
onAddUsers: isOwner ? onAddUsers : null,
onAddPhotos: onAddPhotos,
onToggleAlbumOrder: isOwner ? onToggleAlbumOrder : null,
onEditAlbum: onEditAlbum,
onCreateSharedLink: isOwner ? onCreateSharedLink : null,
onShowOptions: onShowOptions,
);
}
}