merge main

This commit is contained in:
martabal 2024-01-19 23:30:59 +01:00
commit 690b5e7f06
No known key found for this signature in database
GPG Key ID: C00196E3148A52BD
24 changed files with 161 additions and 136 deletions

View File

@ -7,11 +7,7 @@ Immich uses the [OpenAPI](https://swagger.io/specification/) standard to generat
OpenAPI is used to generate the client (Typescript, Dart) SDK. `openapi-generator-cli` can be installed [here](https://openapi-generator.tech/docs/installation/). The generated SDK is based on the `immich-openapi-specs.json` file, which is autogenerated by the server **when running in development mode**. The `immich-openapi-specs.json` file can be modified with `@nestjs/swagger` decorators used or referenced by controller endpoints. See the [NestJS OpenAPI docs](https://docs.nestjs.com/openapi/types-and-parameters) for more info. When you add a new endpoint or modify an existing one, you must run the server in development mode and run the command below to update the client SDK. OpenAPI is used to generate the client (Typescript, Dart) SDK. `openapi-generator-cli` can be installed [here](https://openapi-generator.tech/docs/installation/). The generated SDK is based on the `immich-openapi-specs.json` file, which is autogenerated by the server **when running in development mode**. The `immich-openapi-specs.json` file can be modified with `@nestjs/swagger` decorators used or referenced by controller endpoints. See the [NestJS OpenAPI docs](https://docs.nestjs.com/openapi/types-and-parameters) for more info. When you add a new endpoint or modify an existing one, you must run the server in development mode and run the command below to update the client SDK.
```bash ```bash
npm run api:generate # Run from the `server/` directory make open-api
``` ```
You can find the generated client SDK in the `web/src/api` for Typescript SDK and `mobile/openapi` for Dart SDK. You can find the generated client SDK in the `open-api/typescript-sdk/client` for Typescript SDK and `mobile/openapi` for Dart SDK.
:::tip
This can also be run via `make open-api` from the project root directory (not in the `server` folder)
:::

View File

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "machine-learning" name = "machine-learning"
version = "1.93.1" version = "1.93.2"
description = "" description = ""
authors = ["Hau Tran <alex.tran1502@gmail.com>"] authors = ["Hau Tran <alex.tran1502@gmail.com>"]
readme = "README.md" readme = "README.md"

View File

@ -62,7 +62,7 @@ fi
if [ "$CURRENT_SERVER" != "$NEXT_SERVER" ]; then if [ "$CURRENT_SERVER" != "$NEXT_SERVER" ]; then
echo "Pumping Server: $CURRENT_SERVER => $NEXT_SERVER" echo "Pumping Server: $CURRENT_SERVER => $NEXT_SERVER"
npm --prefix server version $SERVER_PUMP npm --prefix server version $SERVER_PUMP
npm --prefix server run api:generate make open-api
poetry --directory machine-learning version $SERVER_PUMP poetry --directory machine-learning version $SERVER_PUMP
fi fi

View File

@ -35,8 +35,8 @@ platform :android do
task: 'bundle', task: 'bundle',
build_type: 'Release', build_type: 'Release',
properties: { properties: {
"android.injected.version.code" => 118, "android.injected.version.code" => 119,
"android.injected.version.name" => "1.93.1", "android.injected.version.name" => "1.93.2",
} }
) )
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab') upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')

View File

@ -19,7 +19,7 @@ platform :ios do
desc "iOS Beta" desc "iOS Beta"
lane :beta do lane :beta do
increment_version_number( increment_version_number(
version_number: "1.93.1" version_number: "1.93.2"
) )
increment_build_number( increment_build_number(
build_number: latest_testflight_build_number + 1, build_number: latest_testflight_build_number + 1,

View File

@ -197,7 +197,7 @@ class ControlBottomAppBar extends ConsumerWidget {
label: "control_bottom_app_bar_edit_location".tr(), label: "control_bottom_app_bar_edit_location".tr(),
onPressed: enabled ? onEditLocation : null, onPressed: enabled ? onEditLocation : null,
), ),
if (!hasLocal && if (!selectionAssetState.hasLocal &&
selectionAssetState.selectedCount > 1 && selectionAssetState.selectedCount > 1 &&
onStack != null) onStack != null)
ControlBoxButton( ControlBoxButton(
@ -211,7 +211,7 @@ class ControlBottomAppBar extends ConsumerWidget {
label: 'album_viewer_appbar_share_remove'.tr(), label: 'album_viewer_appbar_share_remove'.tr(),
onPressed: enabled ? onRemoveFromAlbum : null, onPressed: enabled ? onRemoveFromAlbum : null,
), ),
if (hasLocal) if (selectionAssetState.hasLocal)
ControlBoxButton( ControlBoxButton(
iconData: Icons.backup_outlined, iconData: Icons.backup_outlined,
label: "Upload", label: "Upload",

View File

@ -3,7 +3,7 @@ Immich API
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 1.93.0 - API version: 1.93.2
- Build package: org.openapitools.codegen.languages.DartClientCodegen - Build package: org.openapitools.codegen.languages.DartClientCodegen
## Requirements ## Requirements

View File

@ -2,7 +2,7 @@ name: immich_mobile
description: Immich - selfhosted backup media file on mobile phone description: Immich - selfhosted backup media file on mobile phone
publish_to: "none" publish_to: "none"
version: 1.93.1+118 version: 1.93.2+119
isar_version: &isar_version 3.1.0+1 isar_version: &isar_version 3.1.0+1
environment: environment:

View File

@ -6221,7 +6221,7 @@
"info": { "info": {
"title": "Immich", "title": "Immich",
"description": "Immich API", "description": "Immich API",
"version": "1.93.1", "version": "1.93.2",
"contact": {} "contact": {}
}, },
"tags": [], "tags": [],

View File

@ -4,7 +4,7 @@
* Immich * Immich
* Immich API * Immich API
* *
* The version of the OpenAPI document: 1.93.0 * The version of the OpenAPI document: 1.93.2
* *
* *
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@ -4,7 +4,7 @@
* Immich * Immich
* Immich API * Immich API
* *
* The version of the OpenAPI document: 1.93.0 * The version of the OpenAPI document: 1.93.2
* *
* *
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@ -4,7 +4,7 @@
* Immich * Immich
* Immich API * Immich API
* *
* The version of the OpenAPI document: 1.93.0 * The version of the OpenAPI document: 1.93.2
* *
* *
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@ -4,7 +4,7 @@
* Immich * Immich
* Immich API * Immich API
* *
* The version of the OpenAPI document: 1.93.0 * The version of the OpenAPI document: 1.93.2
* *
* *
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@ -4,7 +4,7 @@
* Immich * Immich
* Immich API * Immich API
* *
* The version of the OpenAPI document: 1.93.0 * The version of the OpenAPI document: 1.93.2
* *
* *
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@ -1,12 +1,12 @@
{ {
"name": "immich", "name": "immich",
"version": "1.93.1", "version": "1.93.2",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "immich", "name": "immich",
"version": "1.93.1", "version": "1.93.2",
"license": "UNLICENSED", "license": "UNLICENSED",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.22.11", "@babel/runtime": "^7.22.11",

View File

@ -1,6 +1,6 @@
{ {
"name": "immich", "name": "immich",
"version": "1.93.1", "version": "1.93.2",
"description": "", "description": "",
"author": "", "author": "",
"private": true, "private": true,

View File

@ -1014,8 +1014,6 @@ describe(PersonService.name, () => {
oldPersonId: personStub.mergePerson.id, oldPersonId: personStub.mergePerson.id,
}); });
expect(personMock.update).not.toHaveBeenCalled();
expect(accessMock.person.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['person-1'])); expect(accessMock.person.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['person-1']));
}); });
@ -1040,7 +1038,6 @@ describe(PersonService.name, () => {
name: personStub.primaryPerson.name, name: personStub.primaryPerson.name,
}); });
expect(personMock.delete).toHaveBeenCalledWith([personStub.primaryPerson]);
expect(accessMock.person.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['person-1'])); expect(accessMock.person.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['person-1']));
}); });

View File

@ -2,7 +2,6 @@
import { quintOut } from 'svelte/easing'; import { quintOut } from 'svelte/easing';
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
import Slider from '$lib/components/elements/slider.svelte';
export let title: string; export let title: string;
export let subtitle = ''; export let subtitle = '';
@ -11,6 +10,7 @@
export let isEdited = false; export let isEdited = false;
const dispatch = createEventDispatcher<{ toggle: boolean }>(); const dispatch = createEventDispatcher<{ toggle: boolean }>();
const onToggle = (event: Event) => dispatch('toggle', (event.target as HTMLInputElement).checked);
</script> </script>
<div class="flex place-items-center justify-between"> <div class="flex place-items-center justify-between">
@ -31,5 +31,67 @@
<p class="text-sm dark:text-immich-dark-fg">{subtitle}</p> <p class="text-sm dark:text-immich-dark-fg">{subtitle}</p>
</div> </div>
<Slider bind:checked {disabled} on:toggle={() => dispatch('toggle', checked)} />
<label class="relative inline-block h-[10px] w-[36px] flex-none">
<input
class="disabled::cursor-not-allowed h-0 w-0 opacity-0"
type="checkbox"
bind:checked
on:click={onToggle}
{disabled}
/>
{#if disabled}
<span class="slider slider-disabled cursor-not-allowed" />
{:else}
<span class="slider slider-enabled cursor-pointer" />
{/if}
</label>
</div> </div>
<style>
.slider {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 34px;
}
input:disabled {
cursor: not-allowed;
}
.slider:before {
position: absolute;
content: '';
height: 20px;
width: 20px;
left: 0px;
right: 0px;
bottom: -4px;
background-color: gray;
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 50%;
}
input:checked + .slider:before {
-webkit-transform: translateX(18px);
-ms-transform: translateX(18px);
transform: translateX(18px);
background-color: #4250af;
}
input:checked + .slider-disabled {
background-color: gray;
}
input:checked + .slider-enabled {
background-color: #adcbfa;
}
</style>

View File

@ -7,7 +7,7 @@
import ImmichLogo from '../shared-components/immich-logo.svelte'; import ImmichLogo from '../shared-components/immich-logo.svelte';
import Button from '../elements/buttons/button.svelte'; import Button from '../elements/buttons/button.svelte';
import { AppRoute } from '$lib/constants'; import { AppRoute } from '$lib/constants';
import { mdiLink, mdiShareCircle } from '@mdi/js'; import { mdiCheck, mdiLink, mdiShareCircle } from '@mdi/js';
import Icon from '$lib/components/elements/icon.svelte'; import Icon from '$lib/components/elements/icon.svelte';
export let album: AlbumResponseDto; export let album: AlbumResponseDto;
@ -60,28 +60,25 @@
</span> </span>
</svelte:fragment> </svelte:fragment>
<div class="immich-scrollbar max-h-[300px] overflow-y-auto"> {#if selectedUsers.length > 0}
{#if selectedUsers.length > 0} <div class="mb-2 flex flex-wrap place-items-center gap-4 overflow-x-auto px-5 py-2 sticky">
<div class="mb-2 flex place-items-center gap-4 overflow-x-auto px-5 py-2"> <p class="font-medium">To</p>
<p class="font-medium">To</p>
{#each selectedUsers as user} {#each selectedUsers as user}
{#key user.id} {#key user.id}
<button <button
on:click={() => handleUnselect(user)} on:click={() => handleUnselect(user)}
class="flex place-items-center gap-1 rounded-full border border-gray-400 p-1 transition-colors hover:bg-gray-200 dark:hover:bg-gray-700" class="flex place-items-center gap-1 rounded-full border border-gray-500 p-2 transition-colors hover:bg-gray-200 dark:hover:bg-gray-700"
> >
<UserAvatar {user} size="sm" /> <UserAvatar {user} size="sm" />
<p class="text-xs font-medium">{user.name}</p> <p class="text-xs font-medium">{user.name}</p>
</button> </button>
{/key} {/key}
{/each} {/each}
<div class="flex place-content-end mr-0 ml-auto p-5"> </div>
<Button size="sm" rounded="lg" on:click={() => dispatch('select', selectedUsers)}>Add</Button> {/if}
</div>
</div>
{/if}
<div class="immich-scrollbar max-h-[500px] overflow-y-auto">
{#if users.length > 0} {#if users.length > 0}
<p class="px-5 text-xs font-medium">SUGGESTIONS</p> <p class="px-5 text-xs font-medium">SUGGESTIONS</p>
@ -92,10 +89,11 @@
class="flex w-full place-items-center gap-4 px-5 py-4 transition-all hover:bg-gray-200 dark:hover:bg-gray-700" class="flex w-full place-items-center gap-4 px-5 py-4 transition-all hover:bg-gray-200 dark:hover:bg-gray-700"
> >
{#if selectedUsers.includes(user)} {#if selectedUsers.includes(user)}
<span <div
class="flex h-12 w-12 place-content-center place-items-center rounded-full border bg-immich-primary text-3xl text-white dark:border-immich-dark-gray dark:bg-immich-dark-primary dark:text-immich-dark-bg" class="flex h-10 w-10 items-center justify-center rounded-full border bg-immich-primary text-3xl text-white dark:border-immich-dark-gray dark:bg-immich-dark-primary dark:text-immich-dark-bg"
>✓</span
> >
<Icon path={mdiCheck} size={24} />
</div>
{:else} {:else}
<UserAvatar {user} size="md" /> <UserAvatar {user} size="md" />
{/if} {/if}
@ -118,7 +116,20 @@
{/if} {/if}
</div> </div>
{#if users.length > 0}
<div class="p-3">
<Button
size="sm"
fullwidth
rounded="full"
disabled={!selectedUsers.length}
on:click={() => dispatch('select', selectedUsers)}>Add</Button
>
</div>
{/if}
<hr /> <hr />
<div id="shared-buttons" class="my-4 flex place-content-center place-items-center justify-around"> <div id="shared-buttons" class="my-4 flex place-content-center place-items-center justify-around">
<button <button
class="flex flex-col place-content-center place-items-center gap-2 hover:cursor-pointer" class="flex flex-col place-content-center place-items-center gap-2 hover:cursor-pointer"

View File

@ -172,12 +172,12 @@
</div> </div>
{#if innerHeight} {#if innerHeight}
<div <div
class="overflow-y-auto immich-scrollbar relative w-full" class="overflow-y-auto immich-scrollbar relative w-full px-2"
style="height: {divHeight}px;padding-bottom: {chatHeight}px" style="height: {divHeight}px;padding-bottom: {chatHeight}px"
> >
{#each reactions as reaction, index (reaction.id)} {#each reactions as reaction, index (reaction.id)}
{#if reaction.type === 'comment'} {#if reaction.type === 'comment'}
<div class="flex dark:bg-gray-800 bg-gray-200 p-3 mx-2 mt-3 rounded-lg gap-4 justify-start"> <div class="flex dark:bg-gray-800 bg-gray-200 py-3 pl-3 mt-3 rounded-lg gap-4 justify-start">
<div class="flex items-center"> <div class="flex items-center">
<UserAvatar user={reaction.user} size="sm" /> <UserAvatar user={reaction.user} size="sm" />
</div> </div>
@ -215,7 +215,7 @@
{#if (index != reactions.length - 1 && !shouldGroup(reactions[index].createdAt, reactions[index + 1].createdAt)) || index === reactions.length - 1} {#if (index != reactions.length - 1 && !shouldGroup(reactions[index].createdAt, reactions[index + 1].createdAt)) || index === reactions.length - 1}
<div <div
class=" px-2 text-right w-full text-sm text-gray-500 dark:text-gray-300" class="pt-1 px-2 text-right w-full text-sm text-gray-500 dark:text-gray-300"
title={new Date(reaction.createdAt).toLocaleDateString(undefined, timeOptions)} title={new Date(reaction.createdAt).toLocaleDateString(undefined, timeOptions)}
> >
{timeSince(luxon.DateTime.fromISO(reaction.createdAt))} {timeSince(luxon.DateTime.fromISO(reaction.createdAt))}
@ -223,7 +223,7 @@
{/if} {/if}
{:else if reaction.type === 'like'} {:else if reaction.type === 'like'}
<div class="relative"> <div class="relative">
<div class="flex p-3 mx-2 mt-3 rounded-full gap-4 items-center text-sm"> <div class="flex py-3 pl-3 mt-3 gap-4 items-center text-sm">
<div class="text-red-600"><Icon path={mdiHeart} size={20} /></div> <div class="text-red-600"><Icon path={mdiHeart} size={20} /></div>
<div class="w-full" title={`${reaction.user.name} (${reaction.user.email})`}> <div class="w-full" title={`${reaction.user.name} (${reaction.user.email})`}>
@ -260,7 +260,7 @@
</div> </div>
{#if (index != reactions.length - 1 && isTenMinutesApart(reactions[index].createdAt, reactions[index + 1].createdAt)) || index === reactions.length - 1} {#if (index != reactions.length - 1 && isTenMinutesApart(reactions[index].createdAt, reactions[index + 1].createdAt)) || index === reactions.length - 1}
<div <div
class=" px-2 text-right w-full text-sm text-gray-500 dark:text-gray-300" class="pt-1 px-2 text-right w-full text-sm text-gray-500 dark:text-gray-300"
title={new Date(reaction.createdAt).toLocaleDateString(navigator.language, timeOptions)} title={new Date(reaction.createdAt).toLocaleDateString(navigator.language, timeOptions)}
> >
{timeSince(luxon.DateTime.fromISO(reaction.createdAt))} {timeSince(luxon.DateTime.fromISO(reaction.createdAt))}
@ -274,7 +274,7 @@
</div> </div>
<div class="absolute w-full bottom-0"> <div class="absolute w-full bottom-0">
<div class="flex items-center justify-center p-2 mr-2" bind:clientHeight={chatHeight}> <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 class="flex p-2 gap-4 h-fit bg-gray-200 text-immich-dark-gray rounded-3xl w-full">
<div> <div>
<UserAvatar {user} size="md" showTitle={false} /> <UserAvatar {user} size="md" showTitle={false} />

View File

@ -741,7 +741,7 @@
<div <div
transition:fly={{ duration: 150 }} transition:fly={{ duration: 150 }}
id="activity-panel" id="activity-panel"
class="z-[1002] row-start-1 row-span-5 w-[360px] md:w-[460px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-l-immich-dark-gray dark:bg-immich-dark-bg pl-4" class="z-[1002] row-start-1 row-span-5 w-[360px] md:w-[460px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-l-immich-dark-gray dark:bg-immich-dark-bg"
translate="yes" translate="yes"
> >
<ActivityViewer <ActivityViewer

View File

@ -1,72 +0,0 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
export let checked = false;
export let disabled = false;
const dispatch = createEventDispatcher<{ toggle: boolean }>();
const onToggle = (event: Event) => dispatch('toggle', (event.target as HTMLInputElement).checked);
</script>
<label class="relative inline-block h-[10px] w-[36px] flex-none">
<input
class="disabled::cursor-not-allowed h-0 w-0 opacity-0"
type="checkbox"
bind:checked
on:click={onToggle}
{disabled}
/>
{#if disabled}
<span class="slider slider-disabled cursor-not-allowed" />
{:else}
<span class="slider slider-enabled cursor-pointer" />
{/if}
</label>
<style>
.slider {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 34px;
}
input:disabled {
cursor: not-allowed;
}
.slider:before {
position: absolute;
content: '';
height: 20px;
width: 20px;
left: 0px;
right: 0px;
bottom: -4px;
background-color: gray;
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 50%;
}
input:checked + .slider:before {
-webkit-transform: translateX(18px);
-ms-transform: translateX(18px);
transform: translateX(18px);
background-color: #4250af;
}
input:checked + .slider-disabled {
background-color: gray;
}
input:checked + .slider-enabled {
background-color: #adcbfa;
}
</style>

View File

@ -100,6 +100,7 @@
let reactions: ActivityResponseDto[] = []; let reactions: ActivityResponseDto[] = [];
let globalWidth: number; let globalWidth: number;
let assetGridWidth: number; let assetGridWidth: number;
let textarea: HTMLTextAreaElement;
const assetStore = new AssetStore({ albumId: album.id }); const assetStore = new AssetStore({ albumId: album.id });
const assetInteractionStore = createAssetInteractionStore(); const assetInteractionStore = createAssetInteractionStore();
@ -120,7 +121,13 @@
$: showActivityStatus = $: showActivityStatus =
album.sharedUsers.length > 0 && !$showAssetViewer && (album.isActivityEnabled || $numberOfComments > 0); album.sharedUsers.length > 0 && !$showAssetViewer && (album.isActivityEnabled || $numberOfComments > 0);
afterNavigate(({ from }) => { $: {
if (textarea) {
textarea.value = album.description;
autoGrowHeight();
}
}
$: afterNavigate(({ from }) => {
assetViewingStore.showAssetViewer(false); assetViewingStore.showAssetViewer(false);
let url: string | undefined = from?.url?.pathname; let url: string | undefined = from?.url?.pathname;
@ -140,6 +147,13 @@
} }
}); });
const autoGrowHeight = () => {
// little hack so that the height of the text area is correctly initialized
textarea.scrollHeight;
textarea.style.height = '5px';
textarea.style.height = `${textarea.scrollHeight}px`;
};
const handleToggleEnableActivity = async () => { const handleToggleEnableActivity = async () => {
try { try {
const { data } = await api.albumApi.updateAlbumInfo({ const { data } = await api.albumApi.updateAlbumInfo({
@ -634,7 +648,12 @@
disabled={!isOwned} disabled={!isOwned}
title="Edit description" title="Edit description"
> >
{album.description || 'Add description'} <textarea
class="w-full bg-transparent resize-none overflow-hidden outline-none"
bind:this={textarea}
bind:value={album.description}
placeholder="Add description"
/>
</button> </button>
{/if} {/if}
</section> </section>
@ -678,7 +697,7 @@
<div <div
transition:fly={{ duration: 150 }} transition:fly={{ duration: 150 }}
id="activity-panel" id="activity-panel"
class="z-[2] w-[360px] md:w-[460px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-l-immich-dark-gray dark:bg-immich-dark-bg pl-4" class="z-[2] w-[360px] md:w-[460px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-l-immich-dark-gray dark:bg-immich-dark-bg"
translate="yes" translate="yes"
> >
<ActivityViewer <ActivityViewer
@ -751,3 +770,15 @@
{/if} {/if}
<UpdatePanel {assetStore} /> <UpdatePanel {assetStore} />
<style>
::placeholder {
color: rgb(60, 60, 60);
opacity: 0.6;
}
::-ms-input-placeholder {
/* Edge 12 -18 */
color: white;
}
</style>

View File

@ -130,7 +130,7 @@
{#if shouldShowDeleteConfirmDialog} {#if shouldShowDeleteConfirmDialog}
<DeleteConfirmDialog <DeleteConfirmDialog
user={selectedUser} user={selectedUser}
on:succes={onUserDeleteSuccess} on:success={onUserDeleteSuccess}
on:fail={onUserDeleteFail} on:fail={onUserDeleteFail}
on:cancel={() => (shouldShowDeleteConfirmDialog = false)} on:cancel={() => (shouldShowDeleteConfirmDialog = false)}
/> />