Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(web) : User removal from option menu on the top in shared album #12959

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
78 changes: 71 additions & 7 deletions web/src/lib/components/album-page/album-options.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
<script lang="ts">
import Icon from '$lib/components/elements/icon.svelte';
import { updateAlbumInfo, type AlbumResponseDto, type UserResponseDto, AssetOrder } from '@immich/sdk';
import { mdiArrowDownThin, mdiArrowUpThin, mdiPlus } from '@mdi/js';
import {
getMyUser,
updateAlbumInfo,
removeUserFromAlbum,
type AlbumResponseDto,
type UserResponseDto,
AssetOrder
} from '@immich/sdk';
import { mdiArrowDownThin, mdiArrowUpThin, mdiPlus, mdiDotsVertical } from '@mdi/js';
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
import UserAvatar from '$lib/components/shared-components/user-avatar.svelte';
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
Expand All @@ -10,14 +17,22 @@
import { handleError } from '$lib/utils/handle-error';
import { findKey } from 'lodash-es';
import { t } from 'svelte-i18n';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
import ConfirmDialog from '$lib/components/shared-components/dialog/confirm-dialog.svelte';
import { notificationController, NotificationType } from '../shared-components/notification/notification';
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { onMount } from 'svelte';
export let album: AlbumResponseDto;
export let order: AssetOrder | undefined;
export let user: UserResponseDto;
export let onChangeOrder: (order: AssetOrder) => void;
export let onClose: () => void;
export let onToggleEnabledActivity: () => void;
export let onShowSelectSharedUser: () => void;
export let onRemove: (userId: string) => void;
let currentUser: UserResponseDto | null = null;
let selectedRemoveUser: UserResponseDto | null = null;
const options: Record<AssetOrder, RenderedOption> = {
[AssetOrder.Asc]: { icon: mdiArrowUpThin, title: $t('oldest_first') },
Expand All @@ -26,11 +41,20 @@
$: selectedOption = order ? options[order] : options[AssetOrder.Desc];
const handleToggle = async (returnedOption: RenderedOption) => {
// Fetch the current user when the component mounts
onMount(async (): Promise<void> => {
try {
currentUser = await getMyUser();
} catch (error) {
handleError(error, $t('errors.unable_to_refresh_user'));
}
});
const handleToggle = async (returnedOption: RenderedOption): Promise<void> => {
if (selectedOption === returnedOption) {
return;
}
let order = AssetOrder.Desc;
let order: AssetOrder = AssetOrder.Desc;
order = findKey(options, (option) => option === returnedOption) as AssetOrder;
try {
Expand All @@ -45,6 +69,28 @@
handleError(error, $t('errors.unable_to_save_album'));
}
};
const handleMenuRemove = (user: UserResponseDto): void => {
selectedRemoveUser = user;
};
const handleRemoveUser = async (): Promise<void> => {
if (!selectedRemoveUser) {
return;
}
try {
await removeUserFromAlbum({ id: album.id, userId: selectedRemoveUser.id });
onRemove(selectedRemoveUser.id);
notificationController.show({
type: NotificationType.Info,
message: $t('album_user_removed', { values: { user: selectedRemoveUser.name } }),
});
} catch (error) {
handleError(error, $t('errors.unable_to_remove_album_users'));
} finally {
selectedRemoveUser = null;
}
};
</script>

<FullScreenModal title={$t('options')} {onClose}>
Expand Down Expand Up @@ -77,22 +123,40 @@
</div>
<div>{$t('invite_people')}</div>
</button>
{#if currentUser}
<div class="flex items-center gap-2 py-2 mt-2">
<div>
<UserAvatar {user} size="md" />
<UserAvatar user={currentUser} size="md" />
</div>
<div class="w-full">{user.name}</div>
<div class="w-full">{currentUser.name}</div>
<div>{$t('owner')}</div>
</div>
{/if}

{#each album.albumUsers as { user } (user.id)}
<div class="flex items-center gap-2 py-2">
<div>
<UserAvatar {user} size="md" />
</div>
<div class="w-full">{user.name}</div>
{#if user.id !== album.ownerId} <!-- Allow deletion for non-owners -->
<ButtonContextMenu icon={mdiDotsVertical} size="20" title={$t('options')}>
<MenuOption onClick={() => handleMenuRemove(user)} text={$t('remove')} />
</ButtonContextMenu>
{/if}
</div>
{/each}
</div>
</div>
</div>
</FullScreenModal>

{#if selectedRemoveUser}
<ConfirmDialog
title={$t('album_remove_user')}
prompt={$t('album_remove_user_confirmation', { values: { user: selectedRemoveUser.name } })}
confirmText={$t('remove_user')}
onConfirm={handleRemoveUser}
onCancel={() => (selectedRemoveUser = null)}
/>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,7 @@
albumOrder = order;
await setModeToView();
}}
onRemove={handleRemoveUser}
onClose={() => (viewMode = ViewMode.VIEW)}
onToggleEnabledActivity={handleToggleEnableActivity}
onShowSelectSharedUser={() => (viewMode = ViewMode.SELECT_USERS)}
Expand Down
Loading