Merge branch 'main' into feat/show-archived-assets-for-a-person
This commit is contained in:
@@ -102,6 +102,7 @@
|
||||
onSelect={() => (config.ffmpeg.acceptedVideoCodecs = [config.ffmpeg.targetVideoCodec])}
|
||||
/>
|
||||
|
||||
<!-- PCM is excluded here since it's a bad choice for users storage-wise -->
|
||||
<SettingSelect
|
||||
label={$t('admin.transcoding_audio_codec')}
|
||||
{disabled}
|
||||
@@ -145,6 +146,7 @@
|
||||
{ value: AudioCodec.Aac, text: 'AAC' },
|
||||
{ value: AudioCodec.Mp3, text: 'MP3' },
|
||||
{ value: AudioCodec.Libopus, text: 'Opus' },
|
||||
{ value: AudioCodec.PcmS16Le, text: 'PCM (16 bit)' },
|
||||
]}
|
||||
isEdited={!isEqual(sortBy(config.ffmpeg.acceptedAudioCodecs), sortBy(savedConfig.ffmpeg.acceptedAudioCodecs))}
|
||||
/>
|
||||
|
||||
@@ -25,11 +25,12 @@
|
||||
plugins,
|
||||
container,
|
||||
panorama,
|
||||
touchmoveTwoFingers: true,
|
||||
touchmoveTwoFingers: false,
|
||||
mousewheelCtrlKey: false,
|
||||
navbar,
|
||||
maxFov: 180,
|
||||
fisheye: true,
|
||||
minFov: 10,
|
||||
maxFov: 120,
|
||||
fisheye: false,
|
||||
});
|
||||
|
||||
if (originalImageUrl && !$alwaysLoadOriginalFile) {
|
||||
|
||||
@@ -15,9 +15,8 @@
|
||||
type AssetFaceResponseDto,
|
||||
type PersonResponseDto,
|
||||
} from '@immich/sdk';
|
||||
import { mdiAccountOff } from '@mdi/js';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { mdiArrowLeftThin, mdiMinus, mdiRestart } from '@mdi/js';
|
||||
import { mdiAccountOff, mdiArrowLeftThin, mdiPencil, mdiRestart } from '@mdi/js';
|
||||
import { onMount } from 'svelte';
|
||||
import { linear } from 'svelte/easing';
|
||||
import { fly } from 'svelte/transition';
|
||||
@@ -297,7 +296,7 @@
|
||||
{:else}
|
||||
<CircleIconButton
|
||||
color="primary"
|
||||
icon={mdiMinus}
|
||||
icon={mdiPencil}
|
||||
title={$t('select_new_face')}
|
||||
size="18"
|
||||
padding="1"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
export let onClose: () => void;
|
||||
export let onSubmit: () => void;
|
||||
export let onCancel: () => void;
|
||||
export let oauthEnabled = false;
|
||||
|
||||
let error: string;
|
||||
let success: string;
|
||||
@@ -90,12 +91,17 @@
|
||||
|
||||
<div class="my-4 flex flex-col gap-2">
|
||||
<label class="immich-form-label" for="password">{$t('password')}</label>
|
||||
<PasswordField id="password" bind:password autocomplete="new-password" />
|
||||
<PasswordField id="password" bind:password autocomplete="new-password" required={!oauthEnabled} />
|
||||
</div>
|
||||
|
||||
<div class="my-4 flex flex-col gap-2">
|
||||
<label class="immich-form-label" for="confirmPassword">{$t('confirm_password')}</label>
|
||||
<PasswordField id="confirmPassword" bind:password={confirmPassword} autocomplete="new-password" />
|
||||
<PasswordField
|
||||
id="confirmPassword"
|
||||
bind:password={confirmPassword}
|
||||
autocomplete="new-password"
|
||||
required={!oauthEnabled}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="my-4 flex place-items-center justify-between gap-2">
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import { mdiImageAlbum, mdiShareVariantOutline } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
import type { OnAddToAlbum } from '$lib/utils/actions';
|
||||
|
||||
export let shared = false;
|
||||
export let onAddToAlbum: OnAddToAlbum = () => {};
|
||||
|
||||
let showAlbumPicker = false;
|
||||
|
||||
@@ -21,13 +23,19 @@
|
||||
showAlbumPicker = false;
|
||||
|
||||
const assetIds = [...getAssets()].map((asset) => asset.id);
|
||||
await addAssetsToNewAlbum(albumName, assetIds);
|
||||
const album = await addAssetsToNewAlbum(albumName, assetIds);
|
||||
if (!album) {
|
||||
return;
|
||||
}
|
||||
|
||||
onAddToAlbum(assetIds, album.id);
|
||||
};
|
||||
|
||||
const handleAddToAlbum = async (album: AlbumResponseDto) => {
|
||||
showAlbumPicker = false;
|
||||
const assetIds = [...getAssets()].map((asset) => asset.id);
|
||||
await addAssetsToAlbum(album.id, assetIds);
|
||||
onAddToAlbum(assetIds, album.id);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
import { type ServerAboutResponseDto, type ServerVersionHistoryResponseDto } from '@immich/sdk';
|
||||
import { DateTime } from 'luxon';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { mdiAlert } from '@mdi/js';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
|
||||
export let onClose: () => void;
|
||||
|
||||
@@ -152,6 +154,15 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if info.sourceRef === 'main' && info.repository === 'immich-app/immich'}
|
||||
<div class="col-span-full p-4 flex gap-1">
|
||||
<Icon path={mdiAlert} size="2em" color="#ffcc4d" />
|
||||
<p class="immich-form-label text-sm" id="main-warning">
|
||||
{$t('main_branch_warning')}
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="col-span-full">
|
||||
<label class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm" for="version-history"
|
||||
>{$t('version_history')}</label
|
||||
|
||||
@@ -10,11 +10,14 @@
|
||||
type ServerAboutResponseDto,
|
||||
type ServerVersionHistoryResponseDto,
|
||||
} from '@immich/sdk';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { mdiAlert } from '@mdi/js';
|
||||
|
||||
const { serverVersion, connected } = websocketStore;
|
||||
|
||||
let isOpen = false;
|
||||
|
||||
$: isMain = info?.sourceRef === 'main' && info.repository === 'immich-app/immich';
|
||||
$: version = $serverVersion ? `v${$serverVersion.major}.${$serverVersion.minor}.${$serverVersion.patch}` : null;
|
||||
|
||||
let info: ServerAboutResponseDto;
|
||||
@@ -47,7 +50,13 @@
|
||||
|
||||
<div class="flex justify-between justify-items-center">
|
||||
{#if $connected && version}
|
||||
<button type="button" on:click={() => (isOpen = true)} class="dark:text-immich-gray">{version}</button>
|
||||
<button type="button" on:click={() => (isOpen = true)} class="dark:text-immich-gray flex gap-1">
|
||||
{#if isMain}
|
||||
<Icon path={mdiAlert} size="1.5em" color="#ffcc4d" /> {info.sourceRef}
|
||||
{:else}
|
||||
{version}
|
||||
{/if}
|
||||
</button>
|
||||
{:else}
|
||||
<p class="text-red-500">{$t('unknown')}</p>
|
||||
{/if}
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
"transcoding_hardware_acceleration": "Hardware Acceleration",
|
||||
"transcoding_hardware_acceleration_description": "Experimental; much faster, but will have lower quality at the same bitrate",
|
||||
"transcoding_hardware_decoding": "Hardware decoding",
|
||||
"transcoding_hardware_decoding_setting_description": "Applies only to NVENC, QSV and RKMPP. Enables end-to-end acceleration instead of only accelerating encoding. May not work on all videos.",
|
||||
"transcoding_hardware_decoding_setting_description": "Enables end-to-end acceleration instead of only accelerating encoding. May not work on all videos.",
|
||||
"transcoding_hevc_codec": "HEVC codec",
|
||||
"transcoding_max_b_frames": "Maximum B-frames",
|
||||
"transcoding_max_b_frames_description": "Higher values improve compression efficiency, but slow down encoding. May not be compatible with hardware acceleration on older devices. 0 disables B-frames, while -1 sets this value automatically.",
|
||||
@@ -816,6 +816,7 @@
|
||||
"look": "Look",
|
||||
"loop_videos": "Loop videos",
|
||||
"loop_videos_description": "Enable to automatically loop a video in the detail viewer.",
|
||||
"main_branch_warning": "You're running a build from the main branch. We strongly recommend using a release version!",
|
||||
"make": "Make",
|
||||
"manage_shared_links": "Manage shared links",
|
||||
"manage_sharing_with_partners": "Manage sharing with partners",
|
||||
|
||||
@@ -8,6 +8,7 @@ export type OnDelete = (assetIds: string[]) => void;
|
||||
export type OnRestore = (ids: string[]) => void;
|
||||
export type OnLink = (assets: { still: AssetResponseDto; motion: AssetResponseDto }) => void;
|
||||
export type OnUnlink = (assets: { still: AssetResponseDto; motion: AssetResponseDto }) => void;
|
||||
export type OnAddToAlbum = (ids: string[], albumId: string) => void;
|
||||
export type OnArchive = (ids: string[], isArchived: boolean) => void;
|
||||
export type OnFavorite = (ids: string[], favorite: boolean) => void;
|
||||
export type OnStack = (ids: string[]) => void;
|
||||
|
||||
+2
-2
@@ -205,7 +205,7 @@
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await updatePerson({ id: person.id, personUpdateDto: { featureFaceAssetId: asset.id } });
|
||||
person = await updatePerson({ id: person.id, personUpdateDto: { featureFaceAssetId: asset.id } });
|
||||
notificationController.show({ message: $t('feature_photo_updated'), type: NotificationType.Info });
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_set_feature_photo'));
|
||||
@@ -256,7 +256,7 @@
|
||||
try {
|
||||
isEditingName = false;
|
||||
|
||||
await updatePerson({ id: person.id, personUpdateDto: { name: personName } });
|
||||
person = await updatePerson({ id: person.id, personUpdateDto: { name: personName } });
|
||||
|
||||
notificationController.show({
|
||||
message: $t('change_name_successfully'),
|
||||
|
||||
@@ -216,6 +216,11 @@
|
||||
|
||||
const triggerAssetUpdate = () => (searchResultAssets = searchResultAssets);
|
||||
|
||||
const onAddToAlbum = (assetIds: string[]) => {
|
||||
const assetIdSet = new Set(assetIds);
|
||||
searchResultAssets = searchResultAssets.filter((a: AssetResponseDto) => !assetIdSet.has(a.id));
|
||||
};
|
||||
|
||||
function getObjectKeys<T extends object>(obj: T): (keyof T)[] {
|
||||
return Object.keys(obj) as (keyof T)[];
|
||||
}
|
||||
@@ -230,8 +235,8 @@
|
||||
<CreateSharedLink />
|
||||
<CircleIconButton title={$t('select_all')} icon={mdiSelectAll} on:click={handleSelectAll} />
|
||||
<ButtonContextMenu icon={mdiPlus} title={$t('add_to')}>
|
||||
<AddToAlbum />
|
||||
<AddToAlbum shared />
|
||||
<AddToAlbum {onAddToAlbum} />
|
||||
<AddToAlbum shared {onAddToAlbum} />
|
||||
</ButtonContextMenu>
|
||||
<FavoriteAction removeFavorite={isAllFavorite} onFavorite={triggerAssetUpdate} />
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
notificationController,
|
||||
} from '$lib/components/shared-components/notification/notification';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { serverConfig } from '$lib/stores/server-config.store';
|
||||
import { serverConfig, featureFlags } from '$lib/stores/server-config.store';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { websocketEvents } from '$lib/stores/websocket';
|
||||
import { copyToClipboard } from '$lib/utils';
|
||||
@@ -113,6 +113,7 @@
|
||||
onSubmit={onUserCreated}
|
||||
onCancel={() => (shouldShowCreateUserForm = false)}
|
||||
onClose={() => (shouldShowCreateUserForm = false)}
|
||||
oauthEnabled={$featureFlags.oauth}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user