feat: toggle in options modal

pull/24319/head
idubnori 2025-12-01 21:31:08 +09:00
parent fa43fae2a5
commit d9e7f8e7cf
3 changed files with 59 additions and 19 deletions

View File

@ -0,0 +1,19 @@
import { PersistedLocalStorage } from '$lib/utils/persisted';
class AlbumSettingsManager {
#showAssetOwners = new PersistedLocalStorage<boolean>('album-show-asset-owners', false);
get showAssetOwners() {
return this.#showAssetOwners.current;
}
setShowAssetOwners(value: boolean) {
this.#showAssetOwners.current = value;
}
toggleShowAssetOwners() {
this.#showAssetOwners.current = !this.#showAssetOwners.current;
}
}
export const albumSettingsManager = new AlbumSettingsManager();

View File

@ -4,6 +4,7 @@
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
import UserAvatar from '$lib/components/shared-components/user-avatar.svelte';
import type { RenderedOption } from '$lib/elements/Dropdown.svelte';
import { albumSettingsManager } from '$lib/managers/album-settings-manager.svelte';
import { handleError } from '$lib/utils/handle-error';
import {
AlbumUserRole,
@ -24,12 +25,26 @@
album: AlbumResponseDto;
order: AssetOrder | undefined;
user: UserResponseDto;
showAlbumUsers?: boolean;
onClose: (
result?: { action: 'changeOrder'; order: AssetOrder } | { action: 'shareUser' } | { action: 'refreshAlbum' },
result?:
| { action: 'changeOrder'; order: AssetOrder }
| { action: 'shareUser' }
| { action: 'refreshAlbum'; showAlbumUsers?: boolean },
) => void;
}
let { album, order, user, onClose }: Props = $props();
let { album, order, user, showAlbumUsers = $bindable(false), onClose }: Props = $props();
// managerから読み込んで初期値を設定
if (showAlbumUsers === false) {
showAlbumUsers = albumSettingsManager.showAssetOwners;
}
const handleToggleShowAlbumUsers = () => {
showAlbumUsers = !showAlbumUsers;
albumSettingsManager.setShowAssetOwners(showAlbumUsers);
};
const options: Record<AssetOrder, RenderedOption> = {
[AssetOrder.Asc]: { icon: mdiArrowUpThin, title: $t('oldest_first') },
@ -86,7 +101,7 @@
try {
await removeUserFromAlbum({ id: album.id, userId: user.id });
onClose({ action: 'refreshAlbum' });
onClose({ action: 'refreshAlbum', showAlbumUsers });
toastManager.success($t('album_user_removed', { values: { user: user.name } }));
} catch (error) {
handleError(error, $t('errors.unable_to_remove_album_users'));
@ -99,7 +114,7 @@
const message = $t('user_role_set', {
values: { user: user.name, role: role == AlbumUserRole.Viewer ? $t('role_viewer') : $t('role_editor') },
});
onClose({ action: 'refreshAlbum' });
onClose({ action: 'refreshAlbum', showAlbumUsers });
toastManager.success(message);
} catch (error) {
handleError(error, $t('errors.unable_to_change_album_user_role'));
@ -107,7 +122,7 @@
};
</script>
<Modal title={$t('options')} onClose={() => onClose({ action: 'refreshAlbum' })} size="small">
<Modal title={$t('options')} onClose={() => onClose({ action: 'refreshAlbum', showAlbumUsers })} size="small">
<ModalBody>
<div class="items-center justify-center">
<div class="py-2">
@ -127,6 +142,14 @@
checked={album.isActivityEnabled}
onToggle={handleToggleActivity}
/>
{#if album?.shared && album.albumUsers.some(({ role }) => role === AlbumUserRole.Editor)}
<SettingSwitch
title={$t('show_asset_owners')}
subtitle={$t('display_who_uploaded_each_asset')}
checked={showAlbumUsers}
onToggle={handleToggleShowAlbumUsers}
/>
{/if}
</div>
</div>
<div class="py-2">

View File

@ -30,6 +30,7 @@
import Timeline from '$lib/components/timeline/Timeline.svelte';
import { AlbumPageViewMode, AppRoute } from '$lib/constants';
import { activityManager } from '$lib/managers/activity-manager.svelte';
import { albumSettingsManager } from '$lib/managers/album-settings-manager.svelte';
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
@ -66,7 +67,6 @@
} from '@immich/sdk';
import { Button, Icon, IconButton, modalManager, toastManager } from '@immich/ui';
import {
mdiAccountEyeOutline,
mdiArrowLeft,
mdiCogOutline,
mdiDeleteOutline,
@ -101,7 +101,7 @@
let isCreatingSharedAlbum = $state(false);
let isShowActivity = $state(false);
let albumOrder: AssetOrder | undefined = $state(data.album.order);
let showAlbumUsers = $state(false);
let showAlbumUsers = $state(albumSettingsManager.showAssetOwners);
const assetInteraction = new AssetInteraction();
const timelineInteraction = new AssetInteraction();
@ -394,7 +394,12 @@
};
const handleOptions = async () => {
const result = await modalManager.show(AlbumOptionsModal, { album, order: albumOrder, user: $user });
const result = await modalManager.show(AlbumOptionsModal, {
album,
order: albumOrder,
user: $user,
showAlbumUsers,
});
if (!result) {
return;
@ -410,6 +415,10 @@
break;
}
case 'refreshAlbum': {
// if (result.showAlbumUsers !== undefined) {
// showAlbumUsers = result.showAlbumUsers;
// albumSettingsManager.setShowAssetOwners(result.showAlbumUsers);
// }
await refreshAlbum();
break;
}
@ -605,17 +614,6 @@
{#snippet trailing()}
<CastButton />
{#if containsEditors}
<IconButton
variant="ghost"
shape="round"
color="secondary"
aria-label="view asset owners"
icon={mdiAccountEyeOutline}
onclick={() => (showAlbumUsers = !showAlbumUsers)}
/>
{/if}
{#if isEditor}
<IconButton
variant="ghost"