Compare commits

..

19 Commits

Author SHA1 Message Date
Alex The Bot
4ebb9974ff Version v1.93.3 2024-01-20 16:03:18 +00:00
Alex Tran
144822ddc4 chore: recap post date 2024-01-19 19:44:01 -06:00
Kiel Hurley
1efcb00a65 fix(web): Use correct unit for user quota (#6518)
Use correct unit

Already uses GiB when converting to/from bytes
2024-01-19 19:35:56 -06:00
Guillermo
732f289336 fix(web): better button placement within the user management table (#6520)
fix(web): better button placement within table
2024-01-19 18:49:14 -05:00
martin
aa02ccb731 fix(web): album description (#6512)
fix: album description
2024-01-19 15:30:00 -06:00
martin
68d4f1b946 fix(web): delete user (#6514)
fix: delete user
2024-01-19 15:22:00 -06:00
Alex The Bot
3dddc6b449 Version v1.93.2 2024-01-19 18:29:04 +00:00
Alex
88ac3c2016 fix(web): better invite shared user to album layout (#6511)
* fix(web): better invite to album design

* rounded corner

* use icon

* padding
2024-01-19 12:27:29 -06:00
martin
17eaeb695e feat: smart merge (#6508)
* pr feedback

* fix: tests

* update assets statistics

* pr feedback

* pr feedback

* fix: linter

* pr feedback

* fix: don't limit the smart merge

* pr feedback

* fix: server code

* remove slider

* fix: tests

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-01-19 17:52:26 +00:00
shenlong
f80f867976 fix(mobile): stack button not in bottom app bar (#6497)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2024-01-19 17:40:10 +00:00
martin
d15c443d9b fix(web): user list when sharing an album (#6500)
fix: user list when sharing an album

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-01-19 17:38:44 +00:00
Alex
07b874edda fix(web): revert smart merge (#6504)
* revert smart merge

* fix test

* fix test

* Remove Slider file
2024-01-19 11:34:20 -06:00
Jason Rasmussen
df27460f1c fix: open api pump (#6502) 2024-01-19 11:09:18 -06:00
Alex The Bot
d5af357992 Version v1.93.1 2024-01-19 15:01:17 +00:00
Jason Rasmussen
dacca4cdf1 fix(web): slider (#6485) 2024-01-19 08:57:15 -06:00
Mert
b4d1470586 fix(web): prevent layout change from scrollbar in admin setings (#6482)
stable scrollbar
2024-01-19 03:30:48 +00:00
Alex Tran
20c284407c chore: post release openapi update 2024-01-18 21:21:28 -06:00
Alex Tran
1af5fcfcde chore: post release openapi update 2024-01-18 21:19:39 -06:00
Alex
7e1b1eae41 chore: post release tasks 2024-01-18 21:15:58 -06:00
35 changed files with 204 additions and 172 deletions

2
.gitignore vendored
View File

@@ -16,3 +16,5 @@ mobile/*.jks
mobile/libisar.dylib
open-api/typescript-sdk/build
mobile/android/fastlane/report.xml
mobile/ios/fastlane/report.xml

View File

@@ -2,6 +2,7 @@
title: Immich Recap 2023
authors: [alextran]
tags: [update, recap-2023]
date: 2023-12-30T00:00
---
Hi everyone,

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.
```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.
:::tip
This can also be run via `make open-api` from the project root directory (not in the `server` folder)
:::
You can find the generated client SDK in the `open-api/typescript-sdk/client` for Typescript SDK and `mobile/openapi` for Dart SDK.

View File

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

View File

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

View File

@@ -35,8 +35,8 @@ platform :android do
task: 'bundle',
build_type: 'Release',
properties: {
"android.injected.version.code" => 118,
"android.injected.version.name" => "1.93.0",
"android.injected.version.code" => 119,
"android.injected.version.name" => "1.93.3",
}
)
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

@@ -5,17 +5,17 @@
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000217">
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000253">
</testcase>
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="66.694734">
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="74.926686">
</testcase>
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="27.6926">
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="28.933555">
</testcase>

View File

@@ -179,4 +179,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 599d8aeb73728400c15364e734525722250a5382
COCOAPODS: 1.11.3
COCOAPODS: 1.12.1

View File

@@ -379,7 +379,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 131;
CURRENT_PROJECT_VERSION = 134;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -515,7 +515,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 131;
CURRENT_PROJECT_VERSION = 134;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -543,7 +543,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 131;
CURRENT_PROJECT_VERSION = 134;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;

View File

@@ -54,11 +54,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.91.0</string>
<string>1.93.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>131</string>
<string>134</string>
<key>FLTEnableImpeller</key>
<true />
<key>ITSAppUsesNonExemptEncryption</key>

View File

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

View File

@@ -5,32 +5,32 @@
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000273">
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.00026">
</testcase>
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="0.162117">
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="0.172341">
</testcase>
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="3.645923">
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="6.491104">
</testcase>
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="0.158953">
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="0.217405">
</testcase>
<testcase classname="fastlane.lanes" name="4: build_app" time="114.023733">
<testcase classname="fastlane.lanes" name="4: build_app" time="138.23059">
</testcase>
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="97.572612">
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="70.463048">
</testcase>

View File

@@ -197,7 +197,7 @@ class ControlBottomAppBar extends ConsumerWidget {
label: "control_bottom_app_bar_edit_location".tr(),
onPressed: enabled ? onEditLocation : null,
),
if (!hasLocal &&
if (!selectionAssetState.hasLocal &&
selectionAssetState.selectedCount > 1 &&
onStack != null)
ControlBoxButton(
@@ -211,7 +211,7 @@ class ControlBottomAppBar extends ConsumerWidget {
label: 'album_viewer_appbar_share_remove'.tr(),
onPressed: enabled ? onRemoveFromAlbum : null,
),
if (hasLocal)
if (selectionAssetState.hasLocal)
ControlBoxButton(
iconData: Icons.backup_outlined,
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:
- API version: 1.92.1
- API version: 1.93.3
- Build package: org.openapitools.codegen.languages.DartClientCodegen
## Requirements

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -132,4 +132,8 @@ input:focus-visible {
display: none;
scrollbar-width: none;
}
.scrollbar-stable {
scrollbar-gutter: stable both-edges;
}
}

View File

@@ -2,7 +2,6 @@
import { quintOut } from 'svelte/easing';
import { fly } from 'svelte/transition';
import { createEventDispatcher } from 'svelte';
import Slider from '$lib/components/elements/slider.svelte';
export let title: string;
export let subtitle = '';
@@ -11,22 +10,88 @@
export let isEdited = false;
const dispatch = createEventDispatcher<{ toggle: boolean }>();
const onToggle = (event: Event) => dispatch('toggle', (event.target as HTMLInputElement).checked);
</script>
<Slider bind:checked {disabled} on:toggle={() => dispatch('toggle', checked)}>
<div class="flex h-[26px] place-items-center gap-1">
<label class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm" for={title}>
{title}
</label>
{#if isEdited}
<div
transition:fly={{ x: 10, duration: 200, easing: quintOut }}
class="rounded-full bg-orange-100 px-2 text-[10px] text-orange-900"
>
Unsaved change
</div>
{/if}
<div class="flex place-items-center justify-between">
<div>
<div class="flex h-[26px] place-items-center gap-1">
<label class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm" for={title}>
{title}
</label>
{#if isEdited}
<div
transition:fly={{ x: 10, duration: 200, easing: quintOut }}
class="rounded-full bg-orange-100 px-2 text-[10px] text-orange-900"
>
Unsaved change
</div>
{/if}
</div>
<p class="text-sm dark:text-immich-dark-fg">{subtitle}</p>
</div>
<p class="text-sm dark:text-immich-dark-fg">{subtitle}</p>
</Slider>
<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>
<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 Button from '../elements/buttons/button.svelte';
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';
export let album: AlbumResponseDto;
@@ -60,28 +60,25 @@
</span>
</svelte:fragment>
<div class="immich-scrollbar max-h-[300px] overflow-y-auto">
{#if selectedUsers.length > 0}
<div class="mb-2 flex place-items-center gap-4 overflow-x-auto px-5 py-2">
<p class="font-medium">To</p>
{#if selectedUsers.length > 0}
<div class="mb-2 flex flex-wrap place-items-center gap-4 overflow-x-auto px-5 py-2 sticky">
<p class="font-medium">To</p>
{#each selectedUsers as user}
{#key user.id}
<button
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"
>
<UserAvatar {user} size="sm" />
<p class="text-xs font-medium">{user.name}</p>
</button>
{/key}
{/each}
<div class="flex place-content-end mr-0 ml-auto p-5">
<Button size="sm" rounded="lg" on:click={() => dispatch('select', selectedUsers)}>Add</Button>
</div>
</div>
{/if}
{#each selectedUsers as user}
{#key user.id}
<button
on:click={() => handleUnselect(user)}
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" />
<p class="text-xs font-medium">{user.name}</p>
</button>
{/key}
{/each}
</div>
{/if}
<div class="immich-scrollbar max-h-[500px] overflow-y-auto">
{#if users.length > 0}
<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"
>
{#if selectedUsers.includes(user)}
<span
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"
></span
<div
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"
>
<Icon path={mdiCheck} size={24} />
</div>
{:else}
<UserAvatar {user} size="md" />
{/if}
@@ -118,7 +116,20 @@
{/if}
</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 />
<div id="shared-buttons" class="my-4 flex place-content-center place-items-center justify-around">
<button
class="flex flex-col place-content-center place-items-center gap-2 hover:cursor-pointer"

View File

@@ -172,12 +172,12 @@
</div>
{#if innerHeight}
<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"
>
{#each reactions as reaction, index (reaction.id)}
{#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">
<UserAvatar user={reaction.user} size="sm" />
</div>
@@ -215,7 +215,7 @@
{#if (index != reactions.length - 1 && !shouldGroup(reactions[index].createdAt, reactions[index + 1].createdAt)) || index === reactions.length - 1}
<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)}
>
{timeSince(luxon.DateTime.fromISO(reaction.createdAt))}
@@ -223,7 +223,7 @@
{/if}
{:else if reaction.type === 'like'}
<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="w-full" title={`${reaction.user.name} (${reaction.user.email})`}>
@@ -260,7 +260,7 @@
</div>
{#if (index != reactions.length - 1 && isTenMinutesApart(reactions[index].createdAt, reactions[index + 1].createdAt)) || index === reactions.length - 1}
<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)}
>
{timeSince(luxon.DateTime.fromISO(reaction.createdAt))}
@@ -274,7 +274,7 @@
</div>
<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>
<UserAvatar {user} size="md" showTitle={false} />

View File

@@ -741,7 +741,7 @@
<div
transition:fly={{ duration: 150 }}
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"
>
<ActivityViewer

View File

@@ -1,75 +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>
<div class="flex place-items-center justify-between">
<slot name="leading" />
<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>
<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

@@ -121,7 +121,7 @@
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="quotaSize">Quota Size (GB)</label>
<label class="immich-form-label" for="quotaSize">Quota Size (GiB)</label>
<input class="immich-form-input" id="quotaSize" name="quotaSize" type="number" min="0" />
</div>

View File

@@ -102,7 +102,7 @@
</div>
<div class="m-4 flex flex-col gap-2">
<label class="immich-form-label" for="quotaSize">Quota Size (GB)</label>
<label class="immich-form-label" for="quotaSize">Quota Size (GiB)</label>
<input class="immich-form-input" id="quotaSize" name="quotaSize" type="number" min="0" bind:value={quotaSize} />
<p>Note: Enter 0 for unlimited quota</p>
</div>

View File

@@ -42,7 +42,7 @@
</div>
{/if}
<div class="{scrollbarClass} absolute {hasTitleClass} w-full overflow-y-auto">
<div class="{scrollbarClass} scrollbar-stable absolute {hasTitleClass} w-full overflow-y-auto">
<slot />
</div>
</section>

View File

@@ -100,6 +100,7 @@
let reactions: ActivityResponseDto[] = [];
let globalWidth: number;
let assetGridWidth: number;
let textarea: HTMLTextAreaElement;
const assetStore = new AssetStore({ albumId: album.id });
const assetInteractionStore = createAssetInteractionStore();
@@ -122,7 +123,13 @@
$: showActivityStatus =
album.sharedUsers.length > 0 && !$showAssetViewer && (album.isActivityEnabled || $numberOfComments > 0);
afterNavigate(({ from }) => {
$: {
if (textarea) {
textarea.value = album.description;
autoGrowHeight();
}
}
$: afterNavigate(({ from }) => {
assetViewingStore.showAssetViewer(false);
let url: string | undefined = from?.url?.pathname;
@@ -142,6 +149,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 () => {
try {
const { data } = await api.albumApi.updateAlbumInfo({
@@ -636,7 +650,12 @@
disabled={!isOwned}
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>
{/if}
</section>
@@ -680,7 +699,7 @@
<div
transition:fly={{ duration: 150 }}
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"
>
<ActivityViewer
@@ -753,3 +772,15 @@
{/if}
<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}
<DeleteConfirmDialog
user={selectedUser}
on:succes={onUserDeleteSuccess}
on:success={onUserDeleteSuccess}
on:fail={onUserDeleteFail}
on:cancel={() => (shouldShowDeleteConfirmDialog = false)}
/>
@@ -212,7 +212,7 @@
</div>
</td>
<td class="w-4/12 lg:w-3/12 xl:w-2/12 text-ellipsis break-all px-4 text-sm">
<td class="w-4/12 lg:w-3/12 xl:w-2/12 text-ellipsis break-all text-sm">
{#if !isDeleted(immichUser)}
<button
on:click={() => editUserHandler(immichUser)}