mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
refactor: auth manager (#27638)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import OnEvents from '$lib/components/OnEvents.svelte';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import VersionAnnouncementModal from '$lib/modals/VersionAnnouncementModal.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import type { ReleaseEvent } from '$lib/types';
|
||||
import { getReleaseType, semverToName } from '$lib/utils';
|
||||
import { modalManager } from '@immich/ui';
|
||||
@@ -12,7 +12,7 @@
|
||||
}>();
|
||||
|
||||
const onReleaseEvent = async (release: ReleaseEvent) => {
|
||||
if (!release.isAvailable || !$user.isAdmin) {
|
||||
if (!release.isAvailable || !authManager.user.isAdmin) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
|
||||
import SettingButtonsRow from '$lib/components/shared-components/settings/SystemConfigButtonRow.svelte';
|
||||
import { SettingInputFieldType } from '$lib/constants';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
import { systemConfigManager } from '$lib/managers/system-config-manager.svelte';
|
||||
import { handleSystemConfigSave } from '$lib/services/system-config.service';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { sendTestEmailAdmin } from '@immich/sdk';
|
||||
import { Button, toastManager } from '@immich/ui';
|
||||
@@ -45,7 +45,9 @@
|
||||
},
|
||||
});
|
||||
|
||||
toastManager.primary($t('admin.notification_email_test_email_sent', { values: { email: $user.email } }));
|
||||
toastManager.primary(
|
||||
$t('admin.notification_email_test_email_sent', { values: { email: authManager.user.email } }),
|
||||
);
|
||||
|
||||
if (!disabled) {
|
||||
await handleSystemConfigSave({ notifications: configToEdit.notifications });
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
|
||||
import { SettingInputFieldType } from '$lib/constants';
|
||||
import FormatMessage from '$lib/elements/FormatMessage.svelte';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
import { systemConfigManager } from '$lib/managers/system-config-manager.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { handleSystemConfigSave } from '$lib/services/system-config.service';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { getStorageTemplateOptions, type SystemConfigTemplateStorageOptionDto } from '@immich/sdk';
|
||||
import { Heading, Link, LoadingSpinner, Text } from '@immich/ui';
|
||||
import handlebar from 'handlebars';
|
||||
@@ -177,7 +177,10 @@
|
||||
<p class="text-sm">
|
||||
<FormatMessage
|
||||
key="admin.storage_template_path_length"
|
||||
values={{ length: parsedTemplate().length + $user.id.length + 'UPLOAD_LOCATION'.length, limit: 260 }}
|
||||
values={{
|
||||
length: parsedTemplate().length + authManager.user.id.length + 'UPLOAD_LOCATION'.length,
|
||||
limit: 260,
|
||||
}}
|
||||
>
|
||||
{#snippet children({ message })}
|
||||
<span class="font-semibold text-primary">{message}</span>
|
||||
@@ -186,7 +189,10 @@
|
||||
</p>
|
||||
|
||||
<p class="text-sm">
|
||||
<FormatMessage key="admin.storage_template_user_label" values={{ label: $user.storageLabel || $user.id }}>
|
||||
<FormatMessage
|
||||
key="admin.storage_template_user_label"
|
||||
values={{ label: authManager.user.storageLabel || authManager.user.id }}
|
||||
>
|
||||
{#snippet children({ message })}
|
||||
<code class="text-primary">{message}</code>
|
||||
{/snippet}
|
||||
@@ -195,7 +201,7 @@
|
||||
|
||||
<p class="p-4 py-2 mt-2 text-xs bg-gray-200 rounded-lg dark:bg-gray-700 dark:text-immich-dark-fg">
|
||||
<span class="text-immich-fg/25 dark:text-immich-dark-fg/50"
|
||||
>UPLOAD_LOCATION/library/{$user.storageLabel || $user.id}</span
|
||||
>UPLOAD_LOCATION/library/{authManager.user.storageLabel || authManager.user.id}</span
|
||||
>/{parsedTemplate()}.jpg
|
||||
</p>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import AlbumCover from '$lib/components/album-page/album-cover.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { getContextMenuPositionFromEvent, type ContextMenuPosition } from '$lib/utils/context-menu';
|
||||
import { getShortDateRange } from '$lib/utils/date-time';
|
||||
import type { AlbumResponseDto } from '@immich/sdk';
|
||||
@@ -85,7 +85,7 @@
|
||||
{/if}
|
||||
|
||||
{#if showOwner}
|
||||
{#if $user.id === album.ownerId}
|
||||
{#if authManager.user.id === album.ownerId}
|
||||
<p>{$t('owned')}</p>
|
||||
{:else if album.owner}
|
||||
<p>{$t('shared_by_user', { values: { user: album.owner.name } })}</p>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import OnEvents from '$lib/components/OnEvents.svelte';
|
||||
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
|
||||
import RightClickContextMenu from '$lib/components/shared-components/context-menu/right-click-context-menu.svelte';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import AlbumEditModal from '$lib/modals/AlbumEditModal.svelte';
|
||||
import AlbumOptionsModal from '$lib/modals/AlbumOptionsModal.svelte';
|
||||
import { handleDeleteAlbum, handleDownloadAlbum } from '$lib/services/album.service';
|
||||
@@ -16,7 +17,6 @@
|
||||
SortOrder,
|
||||
type AlbumViewSettings,
|
||||
} from '$lib/stores/preferences.store';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { getSelectedAlbumGroupOption, sortAlbums, stringToSortOrder, type AlbumGroup } from '$lib/utils/album-utils';
|
||||
import type { ContextMenuPosition } from '$lib/utils/context-menu';
|
||||
import { normalizeSearchString } from '$lib/utils/string-utils';
|
||||
@@ -97,7 +97,7 @@
|
||||
|
||||
/** Group by owner */
|
||||
[AlbumGroupBy.Owner]: (order, albums): AlbumGroup[] => {
|
||||
const currentUserId = $user.id;
|
||||
const currentUserId = authManager.user.id;
|
||||
const groupedByOwnerIds = groupBy(albums, 'ownerId');
|
||||
|
||||
const sortSign = order === SortOrder.Desc ? -1 : 1;
|
||||
@@ -130,7 +130,7 @@
|
||||
return sharedAlbums;
|
||||
}
|
||||
default: {
|
||||
const nonOwnedAlbums = sharedAlbums.filter((album) => album.ownerId !== $user.id);
|
||||
const nonOwnedAlbums = sharedAlbums.filter((album) => album.ownerId !== authManager.user.id);
|
||||
return nonOwnedAlbums.length > 0 ? ownedAlbums.concat(nonOwnedAlbums) : ownedAlbums;
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,7 @@
|
||||
albumGroupIds = groupedAlbums.map(({ id }) => id);
|
||||
});
|
||||
|
||||
let showFullContextMenu = $derived(allowEdit && selectedAlbum && selectedAlbum.ownerId === $user.id);
|
||||
let showFullContextMenu = $derived(allowEdit && selectedAlbum && selectedAlbum.ownerId === authManager.user.id);
|
||||
|
||||
onMount(async () => {
|
||||
if (allowEdit) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { dateFormats } from '$lib/constants';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import type { ContextMenuPosition } from '$lib/utils/context-menu';
|
||||
import type { AlbumResponseDto } from '@immich/sdk';
|
||||
import { Icon } from '@immich/ui';
|
||||
@@ -43,7 +43,7 @@
|
||||
icon={mdiShareVariantOutline}
|
||||
size="16"
|
||||
class="inline ms-1 opacity-70"
|
||||
title={album.ownerId === $user.id
|
||||
title={album.ownerId === authManager.user.id
|
||||
? $t('shared_by_you')
|
||||
: $t('shared_by_user', { values: { user: album.owner.name } })}
|
||||
/>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { shortcuts } from '$lib/actions/shortcut';
|
||||
import type { OnAction } from '$lib/components/asset-viewer/actions/action';
|
||||
import { AssetAction } from '$lib/constants';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
||||
import { updateAsset, type AssetResponseDto } from '@immich/sdk';
|
||||
@@ -42,7 +42,7 @@
|
||||
</script>
|
||||
|
||||
<svelte:document
|
||||
use:shortcuts={$preferences?.ratings.enabled
|
||||
use:shortcuts={authManager.authenticated && authManager.preferences.ratings.enabled
|
||||
? [
|
||||
{ shortcut: { key: '0' }, onShortcut: () => rateAsset(null) },
|
||||
...[1, 2, 3, 4, 5].map((rating) => ({
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
|
||||
import { activityManager } from '$lib/managers/activity-manager.svelte';
|
||||
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { getAssetMediaUrl } from '$lib/utils';
|
||||
import { getAssetType } from '$lib/utils/asset-utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { isTenMinutesApart } from '$lib/utils/timesince';
|
||||
import { ReactionType, type ActivityResponseDto, type AssetTypeEnum, type UserResponseDto } from '@immich/sdk';
|
||||
import { ReactionType, type ActivityResponseDto, type AssetTypeEnum } from '@immich/sdk';
|
||||
import { Icon, IconButton, LoadingSpinner, Textarea, toastManager } from '@immich/ui';
|
||||
import { mdiClose, mdiDeleteOutline, mdiDotsVertical, mdiSend, mdiThumbUp } from '@mdi/js';
|
||||
import * as luxon from 'luxon';
|
||||
@@ -39,7 +40,6 @@
|
||||
};
|
||||
|
||||
interface Props {
|
||||
user: UserResponseDto;
|
||||
assetId?: string | undefined;
|
||||
albumId: string;
|
||||
assetType?: AssetTypeEnum | undefined;
|
||||
@@ -47,7 +47,7 @@
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
let { user, assetId = undefined, albumId, assetType = undefined, albumOwnerId, disabled }: Props = $props();
|
||||
let { assetId = undefined, albumId, assetType = undefined, albumOwnerId, disabled }: Props = $props();
|
||||
|
||||
let innerHeight: number = $state(0);
|
||||
let activityHeight: number = $state(0);
|
||||
@@ -147,7 +147,7 @@
|
||||
/>
|
||||
</a>
|
||||
{/if}
|
||||
{#if reaction.user.id === user.id || albumOwnerId === user.id}
|
||||
{#if reaction.user.id === authManager.user.id || albumOwnerId === authManager.user.id}
|
||||
<div class="me-4">
|
||||
<ButtonContextMenu
|
||||
icon={mdiDotsVertical}
|
||||
@@ -200,7 +200,7 @@
|
||||
/>
|
||||
</a>
|
||||
{/if}
|
||||
{#if reaction.user.id === user.id || albumOwnerId === user.id}
|
||||
{#if reaction.user.id === authManager.user.id || albumOwnerId === authManager.user.id}
|
||||
<div class="me-4">
|
||||
<ButtonContextMenu
|
||||
icon={mdiDotsVertical}
|
||||
@@ -238,7 +238,7 @@
|
||||
<div class="flex items-center justify-center p-2" bind:clientHeight={chatHeight}>
|
||||
<div class="flex p-2 gap-4 h-fit bg-gray-200 text-immich-dark-gray rounded-3xl w-full">
|
||||
<div>
|
||||
<UserAvatar {user} size="md" noTitle />
|
||||
<UserAvatar user={authManager.user} size="md" noTitle />
|
||||
</div>
|
||||
<form class="flex w-full items-center max-h-56 gap-1" {onsubmit}>
|
||||
<Textarea
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getResizeObserverMock } from '$lib/__mocks__/resize-observer.mock';
|
||||
import { preferences as preferencesStore, resetSavedUser, user as userStore } from '$lib/stores/user.store';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { renderWithTooltips } from '$tests/helpers';
|
||||
import { assetFactory } from '@test-data/factories/asset-factory';
|
||||
import { preferencesFactory } from '@test-data/factories/preferences-factory';
|
||||
@@ -36,7 +36,7 @@ describe('AssetViewerNavBar component', () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
resetSavedUser();
|
||||
authManager.reset();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
@@ -44,8 +44,8 @@ describe('AssetViewerNavBar component', () => {
|
||||
});
|
||||
|
||||
it('shows back button', () => {
|
||||
const prefs = preferencesFactory.build({ cast: { gCastEnabled: false } });
|
||||
preferencesStore.set(prefs);
|
||||
const preferences = preferencesFactory.build({ cast: { gCastEnabled: false } });
|
||||
authManager.setPreferences(preferences);
|
||||
|
||||
const asset = assetFactory.build({ isTrashed: false });
|
||||
const { getByLabelText } = renderWithTooltips(AssetViewerNavBar, { asset, ...additionalProps });
|
||||
@@ -57,10 +57,10 @@ describe('AssetViewerNavBar component', () => {
|
||||
const ownerId = 'id-of-the-user';
|
||||
const user = userAdminFactory.build({ id: ownerId });
|
||||
const asset = assetFactory.build({ ownerId, isTrashed: false });
|
||||
userStore.set(user);
|
||||
authManager.setUser(user);
|
||||
|
||||
const prefs = preferencesFactory.build({ cast: { gCastEnabled: false } });
|
||||
preferencesStore.set(prefs);
|
||||
const preferences = preferencesFactory.build({ cast: { gCastEnabled: false } });
|
||||
authManager.setPreferences(preferences);
|
||||
|
||||
const { getByLabelText } = renderWithTooltips(AssetViewerNavBar, { asset, ...additionalProps });
|
||||
expect(getByLabelText('delete')).toBeInTheDocument();
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
import KeepThisDeleteOthersAction from '$lib/components/asset-viewer/actions/keep-this-delete-others.svelte';
|
||||
import RatingAction from '$lib/components/asset-viewer/actions/rating-action.svelte';
|
||||
import RemoveAssetFromStack from '$lib/components/asset-viewer/actions/remove-asset-from-stack.svelte';
|
||||
import RemoveFromAlbumAction from '$lib/components/timeline/actions/RemoveFromAlbumAction.svelte';
|
||||
import RestoreAction from '$lib/components/asset-viewer/actions/restore-action.svelte';
|
||||
import SetAlbumCoverAction from '$lib/components/asset-viewer/actions/set-album-cover-action.svelte';
|
||||
import SetFeaturedPhotoAction from '$lib/components/asset-viewer/actions/set-person-featured-action.svelte';
|
||||
@@ -19,13 +18,14 @@
|
||||
import LoadingDots from '$lib/components/LoadingDots.svelte';
|
||||
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
|
||||
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
|
||||
import RemoveFromAlbumAction from '$lib/components/timeline/actions/RemoveFromAlbumAction.svelte';
|
||||
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
import { languageManager } from '$lib/managers/language-manager.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { getGlobalActions } from '$lib/services/app.service';
|
||||
import { getAssetActions } from '$lib/services/asset.service';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { getSharedLink, withoutIcons } from '$lib/utils';
|
||||
import type { OnUndoDelete } from '$lib/utils/actions';
|
||||
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
||||
@@ -81,8 +81,8 @@
|
||||
setPlayOriginalVideo,
|
||||
}: Props = $props();
|
||||
|
||||
const isOwner = $derived($user && asset.ownerId === $user?.id);
|
||||
const isAlbumOwner = $derived($user && album?.ownerId === $user?.id);
|
||||
const isOwner = $derived(authManager.authenticated && asset.ownerId === authManager.user.id);
|
||||
const isAlbumOwner = $derived(authManager.authenticated && album?.ownerId === authManager.user.id);
|
||||
const isLocked = $derived(asset.visibility === AssetVisibility.Locked);
|
||||
const smartSearchEnabled = $derived(featureFlagsManager.value.smartSearch);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { getAnimateMock } from '$lib/__mocks__/animate.mock';
|
||||
import { getResizeObserverMock } from '$lib/__mocks__/resize-observer.mock';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
|
||||
import { preferences as preferencesStore, resetSavedUser, user as userStore } from '$lib/stores/user.store';
|
||||
import { renderWithTooltips } from '$tests/helpers';
|
||||
import { updateAsset } from '@immich/sdk';
|
||||
import { assetFactory } from '@test-data/factories/asset-factory';
|
||||
@@ -43,7 +43,7 @@ describe('AssetViewer', () => {
|
||||
|
||||
afterEach(() => {
|
||||
slideshowStore.slideshowState.set(SlideshowState.None);
|
||||
resetSavedUser();
|
||||
authManager.reset();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
@@ -56,8 +56,9 @@ describe('AssetViewer', () => {
|
||||
const user = userAdminFactory.build({ id: ownerId });
|
||||
const asset = assetFactory.build({ ownerId, isFavorite: false, isTrashed: false });
|
||||
|
||||
userStore.set(user);
|
||||
preferencesStore.set(preferencesFactory.build({ cast: { gCastEnabled: false } }));
|
||||
authManager.setUser(user);
|
||||
authManager.setPreferences(preferencesFactory.build({ cast: { gCastEnabled: false } }));
|
||||
|
||||
vi.mocked(updateAsset).mockResolvedValue({ ...asset, isFavorite: true });
|
||||
|
||||
const { getByLabelText, queryByLabelText } = renderWithTooltips(AssetViewer, {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
import { ocrManager } from '$lib/stores/ocr.svelte';
|
||||
import { alwaysLoadOriginalVideo } from '$lib/stores/preferences.store';
|
||||
import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { getSharedLink, handlePromiseError } from '$lib/utils';
|
||||
import type { OnUndoDelete } from '$lib/utils/actions';
|
||||
import { navigateToAsset } from '$lib/utils/asset-utils';
|
||||
@@ -629,7 +628,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if isShared && album && assetViewerManager.isShowActivityPanel && $user}
|
||||
{#if isShared && album && assetViewerManager.isShowActivityPanel && authManager.authenticated}
|
||||
<div
|
||||
transition:fly={{ duration: 150 }}
|
||||
id="activity-panel"
|
||||
@@ -637,7 +636,6 @@
|
||||
translate="yes"
|
||||
>
|
||||
<ActivityViewer
|
||||
user={$user}
|
||||
disabled={!album.isActivityEnabled}
|
||||
assetType={asset.type}
|
||||
albumOwnerId={album.ownerId}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import StarRating, { type Rating } from '$lib/elements/StarRating.svelte';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import { handlePromiseError } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updateAsset, type AssetResponseDto } from '@immich/sdk';
|
||||
@@ -25,7 +24,7 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if !authManager.isSharedLink && $preferences?.ratings.enabled}
|
||||
{#if !authManager.isSharedLink && authManager.authenticated && authManager.preferences.ratings.enabled}
|
||||
<section class="px-4 pt-4">
|
||||
<StarRating {rating} readOnly={!isOwner} onRating={(rating) => handlePromiseError(handleChangeRating(rating))} />
|
||||
</section>
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
import { Route } from '$lib/route';
|
||||
import { boundingBoxesArray } from '$lib/stores/people.store';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { preferences, user } from '$lib/stores/user.store';
|
||||
import { getAssetMediaUrl, getPeopleThumbnailUrl } from '$lib/utils';
|
||||
import { delay, getDimensions } from '$lib/utils/asset-utils';
|
||||
import { getByteUnitString } from '$lib/utils/byte-units';
|
||||
@@ -56,7 +55,7 @@
|
||||
let { asset, currentAlbum = null }: Props = $props();
|
||||
|
||||
let showEditFaces = $state(false);
|
||||
let isOwner = $derived($user?.id === asset.ownerId);
|
||||
let isOwner = $derived(authManager.authenticated && authManager.user.id === asset.ownerId);
|
||||
let people = $derived(asset.people || []);
|
||||
let unassignedFaces = $derived(asset.unassignedFaces || []);
|
||||
let showingHiddenPeople = $state(false);
|
||||
@@ -164,7 +163,7 @@
|
||||
</div>
|
||||
<div class="border border-t-0 border-red-400 bg-red-100 px-4 py-3 text-red-700">
|
||||
<p>
|
||||
{#if $user?.isAdmin}
|
||||
{#if authManager.authenticated && authManager.user.isAdmin}
|
||||
{$t('admin.asset_offline_description')}
|
||||
{:else}
|
||||
{$t('asset_offline_description')}
|
||||
@@ -563,7 +562,7 @@
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
{#if $preferences?.tags?.enabled}
|
||||
{#if authManager.authenticated && authManager.preferences.tags.enabled}
|
||||
<section class="relative px-2 pb-12 dark:bg-immich-dark-bg dark:text-immich-dark-fg">
|
||||
<DetailPanelTags {asset} {isOwner} />
|
||||
</section>
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
import { Route } from '$lib/route';
|
||||
import { getAssetBulkActions } from '$lib/services/asset.service';
|
||||
import { locale, videoViewerMuted, videoViewerVolume } from '$lib/stores/preferences.store';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import { getAssetMediaUrl, handlePromiseError, memoryLaneTitle } from '$lib/utils';
|
||||
import { fromISODateTimeUTC, toTimelineAsset } from '$lib/utils/timeline-util';
|
||||
import { AssetMediaSize, AssetTypeEnum, getAssetInfo } from '@immich/sdk';
|
||||
@@ -104,7 +103,8 @@
|
||||
});
|
||||
} else {
|
||||
progressBarController = new Tween<number>(0, {
|
||||
duration: (from: number, to: number) => (to ? $preferences.memories.duration * 1000 * (to - from) : 0),
|
||||
duration: (from: number, to: number) =>
|
||||
to ? authManager.preferences.memories.duration * 1000 * (to - from) : 0,
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -362,7 +362,7 @@
|
||||
unarchive={assetMultiSelectManager.isAllArchived}
|
||||
onArchive={handleDeleteOrArchiveAssets}
|
||||
/>
|
||||
{#if $preferences.tags.enabled && assetMultiSelectManager.isAllUserOwned}
|
||||
{#if authManager.preferences.tags.enabled && assetMultiSelectManager.isAllUserOwned}
|
||||
<TagAction menuItem />
|
||||
{/if}
|
||||
<DeleteAssets menuItem onAssetDelete={handleDeleteOrArchiveAssets} />
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { serverConfigManager } from '$lib/managers/server-config-manager.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { OnboardingRole } from '$lib/types';
|
||||
import { Logo } from '@immich/ui';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
let userRole = $derived(
|
||||
$user.isAdmin && !serverConfigManager.value.isOnboarded ? OnboardingRole.SERVER : OnboardingRole.USER,
|
||||
authManager.user.isAdmin && !serverConfigManager.value.isOnboarded ? OnboardingRole.SERVER : OnboardingRole.USER,
|
||||
);
|
||||
</script>
|
||||
|
||||
<div class="gap-4">
|
||||
<Logo variant="icon" size="giant" class="mb-2" />
|
||||
<p class="font-medium mb-6 text-6xl text-primary">
|
||||
{$t('onboarding_welcome_user', { values: { user: $user.name } })}
|
||||
{$t('onboarding_welcome_user', { values: { user: authManager.user.name } })}
|
||||
</p>
|
||||
<p class="text-3xl pb-6 font-light">
|
||||
{userRole == OnboardingRole.SERVER
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import StorageTemplateSettings from '$lib/components/admin-settings/StorageTemplateSettings.svelte';
|
||||
import FormatMessage from '$lib/elements/FormatMessage.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { Link } from '@immich/ui';
|
||||
</script>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</FormatMessage>
|
||||
</p>
|
||||
|
||||
{#if $user}
|
||||
{#if authManager.authenticated}
|
||||
<StorageTemplateSettings minified duration={0} saveOnClose />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
<script lang="ts">
|
||||
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updateMyPreferences } from '@immich/sdk';
|
||||
import { onDestroy } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
let gCastEnabled = $state($preferences?.cast?.gCastEnabled ?? false);
|
||||
let gCastEnabled = $state(authManager.authenticated ? authManager.preferences.cast.gCastEnabled : false);
|
||||
|
||||
onDestroy(async () => {
|
||||
try {
|
||||
const data = await updateMyPreferences({
|
||||
userPreferencesUpdateDto: {
|
||||
cast: { gCastEnabled },
|
||||
},
|
||||
});
|
||||
|
||||
$preferences = { ...data };
|
||||
const response = await updateMyPreferences({ userPreferencesUpdateDto: { cast: { gCastEnabled } } });
|
||||
authManager.setPreferences(response);
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_update_settings'));
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
|
||||
import ThemeButton from '$lib/components/shared-components/theme-button.svelte';
|
||||
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { setSharedLink } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { navigate } from '$lib/utils/navigation';
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
let { sharedLink, passwordRequired, key, slug, meta } = $state(data);
|
||||
let { title, description } = $state(meta);
|
||||
let isOwned = $derived($user ? $user.id === sharedLink?.userId : false);
|
||||
let isOwned = $derived(authManager.authenticated && authManager.user.id === sharedLink?.userId);
|
||||
let password = $state('');
|
||||
|
||||
const handlePasswordSubmit = async () => {
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
import Timeline from '$lib/components/timeline/Timeline.svelte';
|
||||
import Portal from '$lib/elements/Portal.svelte';
|
||||
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||
import { getAssetBulkActions } from '$lib/services/asset.service';
|
||||
import { mapSettings } from '$lib/stores/preferences.store';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import {
|
||||
updateStackedAssetInTimeline,
|
||||
updateUnstackedAssetInTimeline,
|
||||
@@ -158,7 +158,7 @@
|
||||
unarchive={assetMultiSelectManager.isAllArchived}
|
||||
onArchive={(ids, visibility) => timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
|
||||
/>
|
||||
{#if $preferences.tags.enabled}
|
||||
{#if authManager.preferences.tags.enabled}
|
||||
<TagAction menuItem />
|
||||
{/if}
|
||||
<DeleteAssets
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
import { focusTrap } from '$lib/actions/focus-trap';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import AvatarEditModal from '$lib/modals/AvatarEditModal.svelte';
|
||||
import HelpAndFeedbackModal from '$lib/modals/HelpAndFeedbackModal.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { userInteraction } from '$lib/stores/user.svelte';
|
||||
import { getAboutInfo, type ServerAboutResponseDto } from '@immich/sdk';
|
||||
import { Button, Icon, IconButton, modalManager } from '@immich/ui';
|
||||
@@ -39,7 +39,7 @@
|
||||
class="mx-4 mt-4 flex flex-col items-center justify-center gap-4 rounded-t-3xl bg-white p-4 dark:bg-immich-dark-primary/10"
|
||||
>
|
||||
<div class="relative">
|
||||
<UserAvatar user={$user} size="xl" />
|
||||
<UserAvatar user={authManager.user} size="xl" />
|
||||
<div class="absolute bottom-0 end-0 rounded-full w-6 h-6">
|
||||
<IconButton
|
||||
color="primary"
|
||||
@@ -56,9 +56,9 @@
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-center text-lg font-medium text-primary">
|
||||
{$user.name}
|
||||
{authManager.user.name}
|
||||
</p>
|
||||
<p class="text-sm text-gray-500 dark:text-immich-dark-fg">{$user.email}</p>
|
||||
<p class="text-sm text-gray-500 dark:text-immich-dark-fg">{authManager.user.email}</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-1">
|
||||
@@ -76,7 +76,7 @@
|
||||
{$t('account_settings')}
|
||||
</div>
|
||||
</Button>
|
||||
{#if $user.isAdmin}
|
||||
{#if authManager.user.isAdmin}
|
||||
<Button
|
||||
href={Route.systemSettings()}
|
||||
onclick={onClose}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
import { mediaQueryManager } from '$lib/stores/media-query-manager.svelte';
|
||||
import { notificationManager } from '$lib/stores/notification-manager.svelte';
|
||||
import { sidebarStore } from '$lib/stores/sidebar.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { ActionButton, Button, IconButton, Logo } from '@immich/ui';
|
||||
import { mdiBellBadge, mdiBellOutline, mdiMagnify, mdiMenu, mdiTrayArrowUp } from '@mdi/js';
|
||||
import { onMount } from 'svelte';
|
||||
@@ -171,10 +170,10 @@
|
||||
type="button"
|
||||
class="flex ps-2"
|
||||
onclick={() => (shouldShowAccountInfoPanel = !shouldShowAccountInfoPanel)}
|
||||
title={`${$user.name} (${$user.email})`}
|
||||
title="{authManager.user.name} ({authManager.user.email})"
|
||||
>
|
||||
{#key $user}
|
||||
<UserAvatar user={$user} size="md" noTitle interactive />
|
||||
{#key authManager.user}
|
||||
<UserAvatar user={authManager.user} size="md" noTitle interactive />
|
||||
{/key}
|
||||
</button>
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { setSupportBadgeVisibility } from '$lib/utils/purchase-utils';
|
||||
import { Button, Icon } from '@immich/ui';
|
||||
import { mdiPartyPopper } from '@mdi/js';
|
||||
@@ -22,7 +22,7 @@
|
||||
<SettingSwitch
|
||||
title={$t('show_supporter_badge')}
|
||||
subtitle={$t('show_supporter_badge_description')}
|
||||
bind:checked={$preferences.purchase.showSupportBadge}
|
||||
bind:checked={authManager.preferences.purchase.showSupportBadge}
|
||||
onToggle={setSupportBadgeVisibility}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import Combobox, { type ComboBoxOption } from '$lib/components/shared-components/combobox.svelte';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { getAllTags, type TagResponseDto } from '@immich/sdk';
|
||||
import { Checkbox, Label, Text } from '@immich/ui';
|
||||
import { onMount } from 'svelte';
|
||||
@@ -40,7 +40,7 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if $preferences?.tags?.enabled}
|
||||
{#if authManager.authenticated && authManager.preferences.tags.enabled}
|
||||
<div id="location-selection">
|
||||
<form autocomplete="off" id="create-tag-form">
|
||||
<div class="mb-4 flex flex-col">
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import PurchaseModal from '$lib/modals/PurchaseModal.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import { getAccountAge } from '$lib/utils/auth';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { getButtonVisibility } from '$lib/utils/purchase-utils';
|
||||
@@ -50,7 +49,8 @@
|
||||
},
|
||||
});
|
||||
|
||||
preferences.set(response);
|
||||
authManager.setPreferences(response);
|
||||
|
||||
showBuyButton = getButtonVisibility();
|
||||
showMessage = false;
|
||||
} catch (error) {
|
||||
@@ -70,7 +70,7 @@
|
||||
</script>
|
||||
|
||||
<div class="license-status ps-4 text-sm">
|
||||
{#if authManager.isPurchased && $preferences.purchase.showSupportBadge}
|
||||
{#if authManager.isPurchased && authManager.preferences.purchase.showSupportBadge}
|
||||
<button
|
||||
onclick={() => goto(Route.userSettings({ isOpen: OpenQueryParam.PURCHASE_SETTINGS }))}
|
||||
class="w-full mt-2"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { releaseManager } from '$lib/managers/release-manager.svelte';
|
||||
import ServerAboutModal from '$lib/modals/ServerAboutModal.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { userInteraction } from '$lib/stores/user.svelte';
|
||||
import { websocketStore } from '$lib/stores/websocket';
|
||||
import type { ReleaseEvent } from '$lib/types';
|
||||
@@ -40,7 +40,7 @@
|
||||
);
|
||||
|
||||
const getReleaseInfo = (release?: ReleaseEvent) => {
|
||||
if (!release || !release?.isAvailable || !$user.isAdmin) {
|
||||
if (!release || !release?.isAvailable || !authManager.user.isAdmin) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { userInteraction } from '$lib/stores/user.svelte';
|
||||
import { requestServerInfo } from '$lib/utils/auth';
|
||||
import { getByteUnitString } from '$lib/utils/byte-units';
|
||||
@@ -8,9 +8,17 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
let hasQuota = $derived($user?.quotaSizeInBytes !== null);
|
||||
let availableBytes = $derived((hasQuota ? $user?.quotaSizeInBytes : userInteraction.serverInfo?.diskSizeRaw) || 0);
|
||||
let usedBytes = $derived((hasQuota ? $user?.quotaUsageInBytes : userInteraction.serverInfo?.diskUseRaw) || 0);
|
||||
let hasQuota = $derived(authManager.user.quotaSizeInBytes !== null);
|
||||
let availableBytes = $derived(
|
||||
(hasQuota && authManager.authenticated
|
||||
? authManager.user.quotaSizeInBytes
|
||||
: userInteraction.serverInfo?.diskSizeRaw) || 0,
|
||||
);
|
||||
let usedBytes = $derived(
|
||||
(hasQuota && authManager.authenticated
|
||||
? authManager.user.quotaUsageInBytes
|
||||
: userInteraction.serverInfo?.diskUseRaw) || 0,
|
||||
);
|
||||
|
||||
const thresholds = [
|
||||
{ from: 0.8, className: 'bg-warning' },
|
||||
@@ -18,7 +26,7 @@
|
||||
];
|
||||
|
||||
onMount(async () => {
|
||||
if (userInteraction.serverInfo && $user) {
|
||||
if (userInteraction.serverInfo && authManager.authenticated) {
|
||||
return;
|
||||
}
|
||||
await requestServerInfo();
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
import BottomInfo from '$lib/components/shared-components/side-bar/bottom-info.svelte';
|
||||
import RecentAlbums from '$lib/components/shared-components/side-bar/recent-albums.svelte';
|
||||
import Sidebar from '$lib/components/sidebar/sidebar.svelte';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { recentAlbumsDropdown } from '$lib/stores/preferences.store';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import { NavbarGroup, NavbarItem } from '@immich/ui';
|
||||
import {
|
||||
mdiAccount,
|
||||
@@ -47,11 +47,11 @@
|
||||
<NavbarItem title={$t('map')} href={Route.map()} icon={mdiMapOutline} activeIcon={mdiMap} />
|
||||
{/if}
|
||||
|
||||
{#if $preferences.people.enabled && $preferences.people.sidebarWeb}
|
||||
{#if authManager.preferences.people.enabled && authManager.preferences.people.sidebarWeb}
|
||||
<NavbarItem title={$t('people')} href={Route.people()} icon={mdiAccountOutline} activeIcon={mdiAccount} />
|
||||
{/if}
|
||||
|
||||
{#if $preferences.sharedLinks.enabled && $preferences.sharedLinks.sidebarWeb}
|
||||
{#if authManager.preferences.sharedLinks.enabled && authManager.preferences.sharedLinks.sidebarWeb}
|
||||
<NavbarItem title={$t('shared_links')} href={Route.sharedLinks()} icon={mdiLink} />
|
||||
{/if}
|
||||
|
||||
@@ -79,11 +79,11 @@
|
||||
{/snippet}
|
||||
</NavbarItem>
|
||||
|
||||
{#if $preferences.tags.enabled && $preferences.tags.sidebarWeb}
|
||||
{#if authManager.preferences.tags.enabled && authManager.preferences.tags.sidebarWeb}
|
||||
<NavbarItem title={$t('tags')} href={Route.tags()} icon={{ icon: mdiTagMultipleOutline, flipped: true }} />
|
||||
{/if}
|
||||
|
||||
{#if $preferences.folders.enabled && $preferences.folders.sidebarWeb}
|
||||
{#if authManager.preferences.folders.enabled && authManager.preferences.folders.sidebarWeb}
|
||||
<NavbarItem title={$t('folders')} href={Route.folders()} icon={{ icon: mdiFolderOutline, flipped: true }} />
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import AssetUpdateDescriptionConfirmModal from '$lib/modals/AssetUpdateDescriptionConfirmModal.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { getOwnedAssetsWithWarning } from '$lib/utils/asset-utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updateAssets } from '@immich/sdk';
|
||||
@@ -19,7 +19,7 @@
|
||||
const handleUpdateDescription = async () => {
|
||||
const description = await modalManager.show(AssetUpdateDescriptionConfirmModal);
|
||||
if (description) {
|
||||
const ids = getOwnedAssetsWithWarning(assetMultiSelectManager.assets, $user);
|
||||
const ids = getOwnedAssetsWithWarning(assetMultiSelectManager.assets, authManager.user);
|
||||
|
||||
try {
|
||||
await updateAssets({ assetBulkUpdateDto: { ids, description } });
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
|
||||
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import GeolocationPointPickerModal from '$lib/modals/GeolocationPointPickerModal.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { getOwnedAssetsWithWarning } from '$lib/utils/asset-utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updateAssets } from '@immich/sdk';
|
||||
@@ -22,7 +22,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const ids = getOwnedAssetsWithWarning(assetMultiSelectManager.assets, $user);
|
||||
const ids = getOwnedAssetsWithWarning(assetMultiSelectManager.assets, authManager.user);
|
||||
|
||||
try {
|
||||
await updateAssets({ assetBulkUpdateDto: { ids, latitude: point.lat, longitude: point.lng } });
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import SettingInputField from '$lib/components/shared-components/settings/setting-input-field.svelte';
|
||||
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
|
||||
import { SettingInputFieldType } from '$lib/constants';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { ByteUnit, convertFromBytes, convertToBytes } from '$lib/utils/byte-units';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updateMyPreferences } from '@immich/sdk';
|
||||
@@ -10,12 +10,12 @@
|
||||
import { t } from 'svelte-i18n';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
let archiveSize = $state(convertFromBytes($preferences?.download?.archiveSize || 4, ByteUnit.GiB));
|
||||
let includeEmbeddedVideos = $state($preferences?.download?.includeEmbeddedVideos || false);
|
||||
let archiveSize = $state(convertFromBytes(authManager.preferences.download.archiveSize || 4, ByteUnit.GiB));
|
||||
let includeEmbeddedVideos = $state(authManager.preferences.download.includeEmbeddedVideos || false);
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
const newPreferences = await updateMyPreferences({
|
||||
const response = await updateMyPreferences({
|
||||
userPreferencesUpdateDto: {
|
||||
download: {
|
||||
archiveSize: Math.floor(convertToBytes(archiveSize, ByteUnit.GiB)),
|
||||
@@ -23,7 +23,8 @@
|
||||
},
|
||||
},
|
||||
});
|
||||
$preferences = newPreferences;
|
||||
|
||||
authManager.setPreferences(response);
|
||||
|
||||
toastManager.primary($t('saved_settings'));
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import SettingAccordion from '$lib/components/shared-components/settings/setting-accordion.svelte';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { AssetOrder, updateMyPreferences } from '@immich/sdk';
|
||||
import { Button, Field, NumberInput, Select, Switch, toastManager } from '@immich/ui';
|
||||
@@ -8,37 +8,37 @@
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
// Albums
|
||||
let defaultAssetOrder = $state($preferences?.albums?.defaultAssetOrder ?? AssetOrder.Desc);
|
||||
let defaultAssetOrder = $state(authManager.preferences.albums?.defaultAssetOrder ?? AssetOrder.Desc);
|
||||
|
||||
// Folders
|
||||
let foldersEnabled = $state($preferences?.folders?.enabled ?? false);
|
||||
let foldersSidebar = $state($preferences?.folders?.sidebarWeb ?? false);
|
||||
let foldersEnabled = $state(authManager.preferences.folders?.enabled ?? false);
|
||||
let foldersSidebar = $state(authManager.preferences.folders?.sidebarWeb ?? false);
|
||||
|
||||
// Memories
|
||||
let memoriesEnabled = $state($preferences?.memories?.enabled ?? true);
|
||||
let memoriesDuration = $state($preferences?.memories?.duration ?? 5);
|
||||
let memoriesEnabled = $state(authManager.preferences.memories?.enabled ?? true);
|
||||
let memoriesDuration = $state(authManager.preferences.memories?.duration ?? 5);
|
||||
|
||||
// People
|
||||
let peopleEnabled = $state($preferences?.people?.enabled ?? false);
|
||||
let peopleSidebar = $state($preferences?.people?.sidebarWeb ?? false);
|
||||
let peopleEnabled = $state(authManager.preferences.people?.enabled ?? false);
|
||||
let peopleSidebar = $state(authManager.preferences.people?.sidebarWeb ?? false);
|
||||
|
||||
// Ratings
|
||||
let ratingsEnabled = $state($preferences?.ratings?.enabled ?? false);
|
||||
let ratingsEnabled = $state(authManager.preferences.ratings?.enabled ?? false);
|
||||
|
||||
// Shared links
|
||||
let sharedLinksEnabled = $state($preferences?.sharedLinks?.enabled ?? true);
|
||||
let sharedLinkSidebar = $state($preferences?.sharedLinks?.sidebarWeb ?? false);
|
||||
let sharedLinksEnabled = $state(authManager.preferences.sharedLinks?.enabled ?? true);
|
||||
let sharedLinkSidebar = $state(authManager.preferences.sharedLinks?.sidebarWeb ?? false);
|
||||
|
||||
// Tags
|
||||
let tagsEnabled = $state($preferences?.tags?.enabled ?? false);
|
||||
let tagsSidebar = $state($preferences?.tags?.sidebarWeb ?? false);
|
||||
let tagsEnabled = $state(authManager.preferences.tags?.enabled ?? false);
|
||||
let tagsSidebar = $state(authManager.preferences.tags?.sidebarWeb ?? false);
|
||||
|
||||
// Cast
|
||||
let gCastEnabled = $state($preferences?.cast?.gCastEnabled ?? false);
|
||||
let gCastEnabled = $state(authManager.preferences.cast?.gCastEnabled ?? false);
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
const data = await updateMyPreferences({
|
||||
const response = await updateMyPreferences({
|
||||
userPreferencesUpdateDto: {
|
||||
albums: { defaultAssetOrder },
|
||||
folders: { enabled: foldersEnabled, sidebarWeb: foldersSidebar },
|
||||
@@ -51,8 +51,7 @@
|
||||
},
|
||||
});
|
||||
|
||||
$preferences = { ...data };
|
||||
|
||||
authManager.setPreferences(response);
|
||||
toastManager.primary($t('saved_settings'));
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_update_settings'));
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updateMyPreferences } from '@immich/sdk';
|
||||
import { Button, Field, Switch, toastManager } from '@immich/ui';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
let emailNotificationsEnabled = $state($preferences?.emailNotifications?.enabled ?? true);
|
||||
let albumInviteNotificationEnabled = $state($preferences?.emailNotifications?.albumInvite ?? true);
|
||||
let albumUpdateNotificationEnabled = $state($preferences?.emailNotifications?.albumUpdate ?? true);
|
||||
let emailNotificationsEnabled = $state(authManager.preferences.emailNotifications?.enabled ?? true);
|
||||
let albumInviteNotificationEnabled = $state(authManager.preferences.emailNotifications?.albumInvite ?? true);
|
||||
let albumUpdateNotificationEnabled = $state(authManager.preferences.emailNotifications?.albumUpdate ?? true);
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
const data = await updateMyPreferences({
|
||||
const response = await updateMyPreferences({
|
||||
userPreferencesUpdateDto: {
|
||||
emailNotifications: {
|
||||
enabled: emailNotificationsEnabled,
|
||||
@@ -22,10 +22,7 @@
|
||||
},
|
||||
});
|
||||
|
||||
$preferences.emailNotifications.enabled = data.emailNotifications.enabled;
|
||||
$preferences.emailNotifications.albumInvite = data.emailNotifications.albumInvite;
|
||||
$preferences.emailNotifications.albumUpdate = data.emailNotifications.albumUpdate;
|
||||
|
||||
authManager.setPreferences(response);
|
||||
toastManager.primary($t('saved_settings'));
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_update_settings'));
|
||||
|
||||
@@ -1,27 +1,22 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
import { oauth } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { type UserAdminResponseDto } from '@immich/sdk';
|
||||
import { Button, LoadingSpinner, toastManager } from '@immich/ui';
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
interface Props {
|
||||
user: UserAdminResponseDto;
|
||||
}
|
||||
|
||||
let { user = $bindable() }: Props = $props();
|
||||
|
||||
let loading = $state(true);
|
||||
|
||||
onMount(async () => {
|
||||
if (oauth.isCallback(globalThis.location)) {
|
||||
try {
|
||||
loading = true;
|
||||
user = await oauth.link(globalThis.location);
|
||||
const response = await oauth.link(globalThis.location);
|
||||
authManager.setUser(response);
|
||||
toastManager.primary($t('linked_oauth_account'));
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_link_oauth_account'));
|
||||
@@ -35,7 +30,8 @@
|
||||
|
||||
const handleUnlink = async () => {
|
||||
try {
|
||||
user = await oauth.unlink();
|
||||
const response = await oauth.unlink();
|
||||
authManager.setUser(response);
|
||||
toastManager.primary($t('unlinked_oauth_account'));
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_unlink_account'));
|
||||
@@ -51,7 +47,7 @@
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
{:else if featureFlagsManager.value.oauth}
|
||||
{#if user.oauthId}
|
||||
{#if authManager.user.oauthId}
|
||||
<Button shape="round" size="small" onclick={() => handleUnlink()}>{$t('unlink_oauth')}</Button>
|
||||
{:else}
|
||||
<Button shape="round" size="small" onclick={() => oauth.authorize(globalThis.location)}
|
||||
|
||||
@@ -24,12 +24,6 @@
|
||||
inTimeline: boolean;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
user: UserResponseDto;
|
||||
}
|
||||
|
||||
let { user }: Props = $props();
|
||||
|
||||
let partners: Array<PartnerSharing> = $state([]);
|
||||
|
||||
onMount(async () => {
|
||||
@@ -95,7 +89,7 @@
|
||||
};
|
||||
|
||||
const handleCreatePartners = async () => {
|
||||
const users = await modalManager.show(PartnerSelectionModal, { user });
|
||||
const users = await modalManager.show(PartnerSelectionModal, {});
|
||||
|
||||
if (!users) {
|
||||
return;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updateMyUser } from '@immich/sdk';
|
||||
import { Button, Field, Input, toastManager } from '@immich/ui';
|
||||
@@ -8,7 +8,7 @@
|
||||
import { createBubbler, preventDefault } from 'svelte/legacy';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
let editedUser = $state(cloneDeep($user));
|
||||
let editedUser = $state(cloneDeep(authManager.user));
|
||||
const bubble = createBubbler();
|
||||
|
||||
const handleSaveProfile = async () => {
|
||||
@@ -21,7 +21,7 @@
|
||||
});
|
||||
|
||||
Object.assign(editedUser, data);
|
||||
$user = data;
|
||||
authManager.setUser(data);
|
||||
|
||||
toastManager.primary($t('saved_profile'));
|
||||
} catch (error) {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import { dateFormats } from '$lib/constants';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { preferences, user } from '$lib/stores/user.store';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { setSupportBadgeVisibility } from '$lib/utils/purchase-utils';
|
||||
import {
|
||||
@@ -30,12 +29,12 @@
|
||||
const serverInfo = await getAboutInfo();
|
||||
isServerProduct = serverInfo.licensed;
|
||||
|
||||
const userInfo = await getMyUser();
|
||||
if (userInfo.license) {
|
||||
$user = { ...$user, license: userInfo.license };
|
||||
const response = await getMyUser();
|
||||
if (response.license) {
|
||||
authManager.setUser(response);
|
||||
}
|
||||
|
||||
if (isServerProduct && $user.isAdmin) {
|
||||
if (isServerProduct && authManager.user.isAdmin) {
|
||||
serverPurchaseInfo = await getServerPurchaseInfo();
|
||||
}
|
||||
};
|
||||
@@ -111,7 +110,7 @@
|
||||
<SettingSwitch
|
||||
title={$t('show_supporter_badge')}
|
||||
subtitle={$t('show_supporter_badge_description')}
|
||||
bind:checked={$preferences.purchase.showSupportBadge}
|
||||
bind:checked={authManager.preferences.purchase.showSupportBadge}
|
||||
onToggle={setSupportBadgeVisibility}
|
||||
/>
|
||||
</div>
|
||||
@@ -128,7 +127,7 @@
|
||||
{$t('purchase_server_title')}
|
||||
</p>
|
||||
|
||||
{#if $user.isAdmin && serverPurchaseInfo?.activatedAt}
|
||||
{#if authManager.user.isAdmin && serverPurchaseInfo?.activatedAt}
|
||||
<p class="dark:text-white text-sm mt-1 col-start-2">
|
||||
{$t('purchase_activated_time', {
|
||||
values: {
|
||||
@@ -142,7 +141,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if $user.isAdmin}
|
||||
{#if authManager.user.isAdmin}
|
||||
<div class="text-right mt-4">
|
||||
<Button shape="round" size="small" color="danger" onclick={removeServerProductKey}
|
||||
>{$t('purchase_button_remove_key')}</Button
|
||||
@@ -159,11 +158,11 @@
|
||||
<p class="text-primary font-semibold text-lg">
|
||||
{$t('purchase_individual_title')}
|
||||
</p>
|
||||
{#if $user.license?.activatedAt}
|
||||
{#if authManager.user.license?.activatedAt}
|
||||
<p class="dark:text-white text-sm mt-1 col-start-2">
|
||||
{$t('purchase_activated_time', {
|
||||
values: {
|
||||
date: new Date($user.license?.activatedAt).toLocaleString($locale, dateFormats.settings),
|
||||
date: new Date(authManager.user.license?.activatedAt).toLocaleString($locale, dateFormats.settings),
|
||||
},
|
||||
})}
|
||||
</p>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
import UserUsageStatistic from '$lib/components/user-settings-page/user-usage-statistic.svelte';
|
||||
import { OpenQueryParam, QueryParameter } from '$lib/constants';
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { oauth } from '$lib/utils';
|
||||
import { type ApiKeyResponseDto, type SessionResponseDto } from '@immich/sdk';
|
||||
import {
|
||||
@@ -120,7 +119,7 @@
|
||||
subtitle={$t('manage_your_oauth_connection')}
|
||||
isOpen={oauthOpen || undefined}
|
||||
>
|
||||
<OAuthSettings user={$user} />
|
||||
<OAuthSettings />
|
||||
</SettingAccordion>
|
||||
{/if}
|
||||
|
||||
@@ -139,7 +138,7 @@
|
||||
title={$t('partner_sharing')}
|
||||
subtitle={$t('manage_sharing_with_partners')}
|
||||
>
|
||||
<PartnerSettings user={$user} />
|
||||
<PartnerSettings />
|
||||
</SettingAccordion>
|
||||
|
||||
<SettingAccordion
|
||||
|
||||
Reference in New Issue
Block a user