Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fd0b41f30 | ||
|
|
c26b28f6a4 | ||
|
|
c72c82c401 | ||
|
|
fecf3809a6 | ||
|
|
619bd72de9 | ||
|
|
fd4a5f71b5 |
@@ -71,7 +71,7 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
|||||||
|
|
||||||
1. If you do not already have it, download the latest [`hwaccel.ml.yml`][hw-file] file and ensure it's in the same folder as the `docker-compose.yml`.
|
1. If you do not already have it, download the latest [`hwaccel.ml.yml`][hw-file] file and ensure it's in the same folder as the `docker-compose.yml`.
|
||||||
2. In the `docker-compose.yml` under `immich-machine-learning`, uncomment the `extends` section and change `cpu` to the appropriate backend.
|
2. In the `docker-compose.yml` under `immich-machine-learning`, uncomment the `extends` section and change `cpu` to the appropriate backend.
|
||||||
3. Still in `immich-machine-learning`, add one of -[armnn, cuda, rocm, openvino] to the `image` section's tag at the end of the line.
|
3. Still in `immich-machine-learning`, add one of -[armnn, cuda, rocm, openvino, rknn] to the `image` section's tag at the end of the line.
|
||||||
4. Redeploy the `immich-machine-learning` container with these updated settings.
|
4. Redeploy the `immich-machine-learning` container with these updated settings.
|
||||||
|
|
||||||
### Confirming Device Usage
|
### Confirming Device Usage
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ name: immich_remote_ml
|
|||||||
services:
|
services:
|
||||||
immich-machine-learning:
|
immich-machine-learning:
|
||||||
container_name: immich_machine_learning
|
container_name: immich_machine_learning
|
||||||
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino] to the image tag.
|
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
|
||||||
# Example tag: ${IMMICH_VERSION:-release}-cuda
|
# Example tag: ${IMMICH_VERSION:-release}-cuda
|
||||||
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
|
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
|
||||||
# extends:
|
# extends:
|
||||||
# file: hwaccel.ml.yml
|
# file: hwaccel.ml.yml
|
||||||
# service: # set to one of [armnn, cuda, rocm, openvino, openvino-wsl] for accelerated inference - use the `-wsl` version for WSL2 where applicable
|
# service: # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
|
||||||
volumes:
|
volumes:
|
||||||
- model-cache:/cache
|
- model-cache:/cache
|
||||||
restart: always
|
restart: always
|
||||||
|
|||||||
@@ -737,6 +737,11 @@ class SyncService {
|
|||||||
album.thumbnail.value = thumb;
|
album.thumbnail.value = thumb;
|
||||||
try {
|
try {
|
||||||
await _albumRepository.create(album);
|
await _albumRepository.create(album);
|
||||||
|
final int assetCount =
|
||||||
|
await _albumMediaRepository.getAssetCount(album.localId!);
|
||||||
|
await _eTagRepository.upsertAll([
|
||||||
|
ETag(id: album.eTagKeyAssetCount, assetCount: assetCount),
|
||||||
|
]);
|
||||||
_log.info("Added a new local album to DB: ${album.name}");
|
_log.info("Added a new local album to DB: ${album.name}");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_log.severe("Failed to add new local album ${album.name} to DB", e);
|
_log.severe("Failed to add new local album ${album.name} to DB", e);
|
||||||
|
|||||||
@@ -210,6 +210,9 @@ class LoginForm extends HookConsumerWidget {
|
|||||||
.getOAuthServerUrl(sanitizeUrl(serverEndpointController.text));
|
.getOAuthServerUrl(sanitizeUrl(serverEndpointController.text));
|
||||||
|
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
|
|
||||||
|
// Invalidate all api repository provider instance to take into account new access token
|
||||||
|
invalidateAllApiRepositoryProviders(ref);
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
log.severe('Error getting OAuth server Url: $error', stack);
|
log.severe('Error getting OAuth server Url: $error', stack);
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ select
|
|||||||
"exif" as "exifInfo"
|
"exif" as "exifInfo"
|
||||||
from
|
from
|
||||||
"assets"
|
"assets"
|
||||||
inner join "exif" on "assets"."id" = "exif"."assetId"
|
left join "exif" on "assets"."id" = "exif"."assetId"
|
||||||
inner join "albums_assets_assets" on "albums_assets_assets"."assetsId" = "assets"."id"
|
inner join "albums_assets_assets" on "albums_assets_assets"."assetsId" = "assets"."id"
|
||||||
where
|
where
|
||||||
"albums_assets_assets"."albumsId" = "albums"."id"
|
"albums_assets_assets"."albumsId" = "albums"."id"
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ const withAssets = (eb: ExpressionBuilder<DB, 'albums'>) => {
|
|||||||
eb
|
eb
|
||||||
.selectFrom('assets')
|
.selectFrom('assets')
|
||||||
.selectAll('assets')
|
.selectAll('assets')
|
||||||
.innerJoin('exif', 'assets.id', 'exif.assetId')
|
.leftJoin('exif', 'assets.id', 'exif.assetId')
|
||||||
.select((eb) => eb.table('exif').as('exifInfo'))
|
.select((eb) => eb.table('exif').as('exifInfo'))
|
||||||
.innerJoin('albums_assets_assets', 'albums_assets_assets.assetsId', 'assets.id')
|
.innerJoin('albums_assets_assets', 'albums_assets_assets.assetsId', 'assets.id')
|
||||||
.whereRef('albums_assets_assets.albumsId', '=', 'albums.id')
|
.whereRef('albums_assets_assets.albumsId', '=', 'albums.id')
|
||||||
|
|||||||
8
web/package-lock.json
generated
8
web/package-lock.json
generated
@@ -70,7 +70,7 @@
|
|||||||
"prettier-plugin-sort-json": "^4.1.1",
|
"prettier-plugin-sort-json": "^4.1.1",
|
||||||
"prettier-plugin-svelte": "^3.3.3",
|
"prettier-plugin-svelte": "^3.3.3",
|
||||||
"rollup-plugin-visualizer": "^5.14.0",
|
"rollup-plugin-visualizer": "^5.14.0",
|
||||||
"svelte": "^5.22.6",
|
"svelte": "^5.25.3",
|
||||||
"svelte-check": "^4.1.5",
|
"svelte-check": "^4.1.5",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"tslib": "^2.6.2",
|
"tslib": "^2.6.2",
|
||||||
@@ -8350,9 +8350,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/svelte": {
|
"node_modules/svelte": {
|
||||||
"version": "5.23.0",
|
"version": "5.25.3",
|
||||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.23.0.tgz",
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.25.3.tgz",
|
||||||
"integrity": "sha512-v0lL3NuKontiCxholEiAXCB+BYbndlKbwlDMK0DS86WgGELMJSpyqCSbJeMEMBDwOglnS7Ar2Rq0wwa/z2L8Vg==",
|
"integrity": "sha512-J9rcZ/xVJonAoESqVGHHZhrNdVbrCfkdB41BP6eiwHMoFShD9it3yZXApVYMHdGfCshBsZCKsajwJeBbS/M1zg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ampproject/remapping": "^2.3.0",
|
"@ampproject/remapping": "^2.3.0",
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
"prettier-plugin-sort-json": "^4.1.1",
|
"prettier-plugin-sort-json": "^4.1.1",
|
||||||
"prettier-plugin-svelte": "^3.3.3",
|
"prettier-plugin-svelte": "^3.3.3",
|
||||||
"rollup-plugin-visualizer": "^5.14.0",
|
"rollup-plugin-visualizer": "^5.14.0",
|
||||||
"svelte": "^5.22.6",
|
"svelte": "^5.25.3",
|
||||||
"svelte-check": "^4.1.5",
|
"svelte-check": "^4.1.5",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"tslib": "^2.6.2",
|
"tslib": "^2.6.2",
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { press, tap } from 'svelte-gestures';
|
|
||||||
|
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
import { ProjectionType } from '$lib/constants';
|
import { ProjectionType } from '$lib/constants';
|
||||||
import { getAssetThumbnailUrl, isSharedLink } from '$lib/utils';
|
import { getAssetThumbnailUrl, isSharedLink } from '$lib/utils';
|
||||||
@@ -103,10 +101,8 @@
|
|||||||
}
|
}
|
||||||
onClick?.($state.snapshot(asset));
|
onClick?.($state.snapshot(asset));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClick = (e: MouseEvent) => {
|
const handleClick = (e: MouseEvent) => {
|
||||||
if (isTouchDevice) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (e.ctrlKey || e.metaKey) {
|
if (e.ctrlKey || e.metaKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -126,6 +122,25 @@
|
|||||||
const onMouseLeave = () => {
|
const onMouseLeave = () => {
|
||||||
mouseOver = false;
|
mouseOver = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function longPress(element: HTMLElement, { onLongPress }: { onLongPress: () => void }) {
|
||||||
|
let timer: ReturnType<typeof setTimeout>;
|
||||||
|
const start = (event: TouchEvent) => {
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
onLongPress();
|
||||||
|
event.preventDefault();
|
||||||
|
}, 350);
|
||||||
|
};
|
||||||
|
const end = () => clearTimeout(timer);
|
||||||
|
element.addEventListener('touchstart', start);
|
||||||
|
element.addEventListener('touchend', end);
|
||||||
|
return {
|
||||||
|
destroy: () => {
|
||||||
|
element.removeEventListener('touchstart', start);
|
||||||
|
element.removeEventListener('touchend', end);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -146,9 +161,6 @@
|
|||||||
></canvas>
|
></canvas>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- svelte queries for all links on afterNavigate, leading to performance problems in asset-grid which updates
|
|
||||||
the navigation url on scroll. Replace this with button for now. -->
|
|
||||||
|
|
||||||
<!-- as of iOS17, there is a preference for long press speed, which is not available for mobile web.
|
<!-- as of iOS17, there is a preference for long press speed, which is not available for mobile web.
|
||||||
The defaults are as follows:
|
The defaults are as follows:
|
||||||
fast: 200ms
|
fast: 200ms
|
||||||
@@ -163,10 +175,7 @@
|
|||||||
class:cursor-pointer={!disabled}
|
class:cursor-pointer={!disabled}
|
||||||
onmouseenter={onMouseEnter}
|
onmouseenter={onMouseEnter}
|
||||||
onmouseleave={onMouseLeave}
|
onmouseleave={onMouseLeave}
|
||||||
use:press={() => ({ timeframe: 350, triggerBeforeFinished: true })}
|
use:longPress={{ onLongPress: () => onSelect?.($state.snapshot(asset)) }}
|
||||||
use:tap={() => ({ timeframe: 350 })}
|
|
||||||
onpress={(evt) => (evt.detail.pointerType === 'mouse' ? void 0 : onSelect?.($state.snapshot(asset)))}
|
|
||||||
ontap={(evt) => (evt.detail.pointerType === 'mouse' ? void 0 : callClickHandlers())}
|
|
||||||
onkeydown={(evt) => {
|
onkeydown={(evt) => {
|
||||||
if (evt.key === 'Enter') {
|
if (evt.key === 'Enter') {
|
||||||
callClickHandlers();
|
callClickHandlers();
|
||||||
|
|||||||
@@ -394,7 +394,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let album = $state(data.album);
|
let album = $derived(data.album);
|
||||||
let albumId = $derived(album.id);
|
let albumId = $derived(album.id);
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
@@ -404,6 +404,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
let assetStore = new AssetStore();
|
let assetStore = new AssetStore();
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (viewMode === AlbumPageViewMode.VIEW) {
|
if (viewMode === AlbumPageViewMode.VIEW) {
|
||||||
void assetStore.updateOptions({ albumId, order: albumOrder });
|
void assetStore.updateOptions({ albumId, order: albumOrder });
|
||||||
|
|||||||
Reference in New Issue
Block a user