Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58ae77ec92 | ||
|
|
4794a1a092 | ||
|
|
6abcfaef99 | ||
|
|
f6903696cb | ||
|
|
724a081bb5 | ||
|
|
4e332db2fb | ||
|
|
0712183a18 | ||
|
|
d004c03990 | ||
|
|
fff651f8a5 | ||
|
|
e2720e85bb | ||
|
|
5fdc8c9481 | ||
|
|
a3404cf420 | ||
|
|
5268dc4ee2 | ||
|
|
ef060e97b6 | ||
|
|
a9851df8d1 | ||
|
|
099a1e4210 | ||
|
|
79d760ccd7 | ||
|
|
369d3dfa38 | ||
|
|
93e53f6d74 | ||
|
|
d8f0a69dc8 | ||
|
|
09d9fa9755 | ||
|
|
118dc8cf5a | ||
|
|
9557395991 | ||
|
|
a5d63d6953 | ||
|
|
5ee4a43e74 | ||
|
|
c3aeb6c497 | ||
|
|
d22fb2d5db | ||
|
|
c4df96bd72 | ||
|
|
40e7b58ba4 | ||
|
|
4743a085f1 | ||
|
|
911c877e72 | ||
|
|
806000e671 |
@@ -4,7 +4,7 @@ FROM ${BASEIMAGE}
|
||||
# Flutter SDK
|
||||
# https://flutter.dev/docs/development/tools/sdk/releases?tab=linux
|
||||
ENV FLUTTER_CHANNEL="stable"
|
||||
ENV FLUTTER_VERSION="3.29.1"
|
||||
ENV FLUTTER_VERSION="3.29.3"
|
||||
ENV FLUTTER_HOME=/flutter
|
||||
ENV PATH=${PATH}:${FLUTTER_HOME}/bin
|
||||
|
||||
|
||||
2
.github/.nvmrc
vendored
2
.github/.nvmrc
vendored
@@ -1 +1 @@
|
||||
22.15.1
|
||||
22.16.0
|
||||
|
||||
@@ -14,7 +14,6 @@ body:
|
||||
label: I have searched the existing feature requests, both open and closed, to make sure this is not a duplicate request.
|
||||
options:
|
||||
- label: 'Yes'
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: feature
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -6,7 +6,6 @@ body:
|
||||
label: I have searched the existing issues, both open and closed, to make sure this is not a duplicate report.
|
||||
options:
|
||||
- label: 'Yes'
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
@@ -50,7 +50,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
|
||||
uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
|
||||
uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
@@ -76,6 +76,6 @@ jobs:
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
|
||||
uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
||||
with:
|
||||
category: '/language:${{matrix.language}}'
|
||||
|
||||
2
.github/workflows/pr-label-validation.yml
vendored
2
.github/workflows/pr-label-validation.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Require PR to have a changelog label
|
||||
uses: mheap/github-action-required-labels@388fd6af37b34cdfe5a23b37060e763217e58b03 # v5.5.0
|
||||
uses: mheap/github-action-required-labels@fb29a14a076b0f74099f6198f77750e8fc236016 # v5.5.0
|
||||
with:
|
||||
mode: exactly
|
||||
count: 1
|
||||
|
||||
2
.github/workflows/static_analysis.yml
vendored
2
.github/workflows/static_analysis.yml
vendored
@@ -118,7 +118,7 @@ jobs:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
|
||||
uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
category: zizmor
|
||||
|
||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -648,7 +648,7 @@ jobs:
|
||||
contents: read
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:14bec5d02e8704081eafd566029204a4eb6bb75f3056cfb34e81c5ab1657a490
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:1076bb152a3000df23911fdec83f14ea83f0dd0c42bc7d4e14b854e9bda1b0c9
|
||||
env:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_USER: postgres
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@
|
||||
.DS_Store
|
||||
.vscode/*
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
|
||||
docker/upload
|
||||
|
||||
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"esbenp.prettier-vscode",
|
||||
"svelte.svelte-vscode",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"dart-code.flutter",
|
||||
"dart-code.dart-code",
|
||||
"dcmdev.dcm-vscode-extension"
|
||||
]
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
22.15.1
|
||||
22.16.0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:22.15.0-alpine3.20@sha256:686b8892b69879ef5bfd6047589666933508f9a5451c67320df3070ba0e9807b AS core
|
||||
FROM node:22.16.0-alpine3.20@sha256:2289fb1fba0f4633b08ec47b94a89c7e20b829fc5679f9b7b298eaa2f1ed8b7e AS core
|
||||
|
||||
WORKDIR /usr/src/open-api/typescript-sdk
|
||||
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
|
||||
|
||||
1107
cli/package-lock.json
generated
1107
cli/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@immich/cli",
|
||||
"version": "2.2.67",
|
||||
"version": "2.2.68",
|
||||
"description": "Command Line Interface (CLI) for Immich",
|
||||
"type": "module",
|
||||
"exports": "./dist/index.js",
|
||||
@@ -21,7 +21,7 @@
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/micromatch": "^4.0.9",
|
||||
"@types/mock-fs": "^4.13.1",
|
||||
"@types/node": "^22.15.18",
|
||||
"@types/node": "^22.15.21",
|
||||
"@vitest/coverage-v8": "^3.0.0",
|
||||
"byte-size": "^9.0.0",
|
||||
"cli-progress": "^3.12.0",
|
||||
@@ -69,6 +69,6 @@
|
||||
"micromatch": "^4.0.8"
|
||||
},
|
||||
"volta": {
|
||||
"node": "22.15.1"
|
||||
"node": "22.16.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ name: immich-dev
|
||||
services:
|
||||
immich-server:
|
||||
container_name: immich_server
|
||||
command: ['/usr/src/app/bin/immich-dev']
|
||||
command: [ '/usr/src/app/bin/immich-dev' ]
|
||||
image: immich-server-dev:latest
|
||||
# extends:
|
||||
# file: hwaccel.transcoding.yml
|
||||
@@ -48,7 +48,7 @@ services:
|
||||
IMMICH_THIRD_PARTY_SOURCE_URL: https://github.com/immich-app/immich/
|
||||
IMMICH_THIRD_PARTY_BUG_FEATURE_URL: https://github.com/immich-app/immich/issues
|
||||
IMMICH_THIRD_PARTY_DOCUMENTATION_URL: https://immich.app/docs
|
||||
IMMICH_THIRD_PARTY_SUPPORT_URL: https://immich.app/docs/third-party
|
||||
IMMICH_THIRD_PARTY_SUPPORT_URL: https://immich.app/docs/community-guides
|
||||
ulimits:
|
||||
nofile:
|
||||
soft: 1048576
|
||||
@@ -70,7 +70,7 @@ services:
|
||||
# user: 0:0
|
||||
build:
|
||||
context: ../web
|
||||
command: ['/usr/src/app/bin/immich-web']
|
||||
command: [ '/usr/src/app/bin/immich-web' ]
|
||||
env_file:
|
||||
- .env
|
||||
ports:
|
||||
@@ -122,7 +122,7 @@ services:
|
||||
|
||||
database:
|
||||
container_name: immich_postgres
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0-pgvectors0.2.0
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0-pgvectors0.2.0@sha256:fa4f6e0971f454cd95fec5a9aaed2ed93d8f46725cc6bc61e0698e97dba96da1
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
@@ -134,7 +134,6 @@ services:
|
||||
- ${UPLOAD_LOCATION}/postgres:/var/lib/postgresql/data
|
||||
ports:
|
||||
- 5432:5432
|
||||
|
||||
# set IMMICH_TELEMETRY_INCLUDE=all in .env to enable metrics
|
||||
# immich-prometheus:
|
||||
# container_name: immich_prometheus
|
||||
|
||||
@@ -63,7 +63,7 @@ services:
|
||||
|
||||
database:
|
||||
container_name: immich_postgres
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0-pgvectors0.2.0
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0-pgvectors0.2.0@sha256:fa4f6e0971f454cd95fec5a9aaed2ed93d8f46725cc6bc61e0698e97dba96da1
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
|
||||
@@ -56,7 +56,7 @@ services:
|
||||
|
||||
database:
|
||||
container_name: immich_postgres
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0-pgvectors0.2.0
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0-pgvectors0.2.0@sha256:fa4f6e0971f454cd95fec5a9aaed2ed93d8f46725cc6bc61e0698e97dba96da1
|
||||
environment:
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
POSTGRES_USER: ${DB_USERNAME}
|
||||
|
||||
@@ -1 +1 @@
|
||||
22.15.1
|
||||
22.16.0
|
||||
|
||||
@@ -115,32 +115,72 @@ Note: Activating the license is not required.
|
||||
|
||||
### VSCode
|
||||
|
||||
Install `Flutter`, `DCM`, `Prettier`, `ESLint` and `Svelte` extensions.
|
||||
Install `Flutter`, `DCM`, `Prettier`, `ESLint` and `Svelte` extensions. These extensions are listed in the `extensions.json` file under `.vscode/` and should appear as workspace recommendations.
|
||||
|
||||
in User `settings.json` (`cmd + shift + p` and search for `Open User Settings JSON`) add the following:
|
||||
Here are the settings we use, they should be active as workspace settings (`settings.json`):
|
||||
|
||||
```json title="settings.json"
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"[javascript][typescript][css]": {
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.tabSize": 2,
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[svelte]": {
|
||||
"editor.defaultFormatter": "svelte.svelte-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.tabSize": 2
|
||||
},
|
||||
"svelte.enable-ts-plugin": true,
|
||||
"eslint.validate": ["javascript", "svelte"],
|
||||
"[dart]": {
|
||||
"editor.defaultFormatter": "Dart-Code.dart-code",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.selectionHighlight": false,
|
||||
"editor.suggest.snippetsPreventQuickSuggestions": false,
|
||||
"editor.suggestSelection": "first",
|
||||
"editor.tabCompletion": "onlySnippets",
|
||||
"editor.wordBasedSuggestions": "off",
|
||||
"editor.defaultFormatter": "Dart-Code.dart-code"
|
||||
}
|
||||
"editor.wordBasedSuggestions": "off"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": "explicit",
|
||||
"source.removeUnusedImports": "explicit"
|
||||
},
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.tabSize": 2
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.tabSize": 2
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.tabSize": 2
|
||||
},
|
||||
"[svelte]": {
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": "explicit",
|
||||
"source.removeUnusedImports": "explicit"
|
||||
},
|
||||
"editor.defaultFormatter": "svelte.svelte-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.tabSize": 2
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": "explicit",
|
||||
"source.removeUnusedImports": "explicit"
|
||||
},
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.tabSize": 2
|
||||
},
|
||||
"cSpell.words": ["immich"],
|
||||
"editor.formatOnSave": true,
|
||||
"eslint.validate": ["javascript", "svelte"],
|
||||
"explorer.fileNesting.enabled": true,
|
||||
"explorer.fileNesting.patterns": {
|
||||
"*.dart": "${capture}.g.dart,${capture}.gr.dart,${capture}.drift.dart",
|
||||
"*.ts": "${capture}.spec.ts,${capture}.mock.ts"
|
||||
},
|
||||
"svelte.enable-ts-plugin": true,
|
||||
"typescript.preferences.importModuleSpecifier": "non-relative"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -57,6 +57,6 @@
|
||||
"node": ">=20"
|
||||
},
|
||||
"volta": {
|
||||
"node": "22.15.1"
|
||||
"node": "22.16.0"
|
||||
}
|
||||
}
|
||||
|
||||
4
docs/static/archived-versions.json
vendored
4
docs/static/archived-versions.json
vendored
@@ -1,4 +1,8 @@
|
||||
[
|
||||
{
|
||||
"label": "v1.134.0",
|
||||
"url": "https://v1.134.0.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v1.133.1",
|
||||
"url": "https://v1.133.1.archive.immich.app"
|
||||
|
||||
@@ -1 +1 @@
|
||||
22.15.1
|
||||
22.16.0
|
||||
|
||||
@@ -37,7 +37,7 @@ services:
|
||||
image: redis:6.2-alpine@sha256:3211c33a618c457e5d241922c975dbc4f446d0bdb2dc75694f5573ef8e2d01fa
|
||||
|
||||
database:
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:e6d1209c1c13791c6f9fbf726c41865e3320dfe2445a6b4ffb03e25f904b3b37
|
||||
command: -c fsync=off -c shared_preload_libraries=vchord.so -c config_file=/var/lib/postgresql/data/postgresql.conf
|
||||
environment:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
|
||||
1096
e2e/package-lock.json
generated
1096
e2e/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich-e2e",
|
||||
"version": "1.133.1",
|
||||
"version": "1.134.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
@@ -25,7 +25,7 @@
|
||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||
"@playwright/test": "^1.44.1",
|
||||
"@types/luxon": "^3.4.2",
|
||||
"@types/node": "^22.15.18",
|
||||
"@types/node": "^22.15.21",
|
||||
"@types/oidc-provider": "^8.5.1",
|
||||
"@types/pg": "^8.15.1",
|
||||
"@types/pngjs": "^6.0.4",
|
||||
@@ -52,6 +52,6 @@
|
||||
"vitest": "^3.0.0"
|
||||
},
|
||||
"volta": {
|
||||
"node": "22.15.1"
|
||||
"node": "22.16.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import { AssetMediaResponseDto, AssetVisibility, LoginResponseDto, SharedLinkType } from '@immich/sdk';
|
||||
import {
|
||||
AssetMediaResponseDto,
|
||||
AssetVisibility,
|
||||
LoginResponseDto,
|
||||
SharedLinkType,
|
||||
TimeBucketAssetResponseDto,
|
||||
} from '@immich/sdk';
|
||||
import { DateTime } from 'luxon';
|
||||
import { createUserDto } from 'src/fixtures';
|
||||
import { errorDto } from 'src/responses';
|
||||
@@ -19,7 +25,8 @@ describe('/timeline', () => {
|
||||
let user: LoginResponseDto;
|
||||
let timeBucketUser: LoginResponseDto;
|
||||
|
||||
let userAssets: AssetMediaResponseDto[];
|
||||
let user1Assets: AssetMediaResponseDto[];
|
||||
let user2Assets: AssetMediaResponseDto[];
|
||||
|
||||
beforeAll(async () => {
|
||||
await utils.resetDatabase();
|
||||
@@ -29,7 +36,7 @@ describe('/timeline', () => {
|
||||
utils.userSetup(admin.accessToken, createUserDto.create('time-bucket')),
|
||||
]);
|
||||
|
||||
userAssets = await Promise.all([
|
||||
user1Assets = await Promise.all([
|
||||
utils.createAsset(user.accessToken),
|
||||
utils.createAsset(user.accessToken),
|
||||
utils.createAsset(user.accessToken, {
|
||||
@@ -42,12 +49,15 @@ describe('/timeline', () => {
|
||||
utils.createAsset(user.accessToken),
|
||||
]);
|
||||
|
||||
await Promise.all([
|
||||
user2Assets = await Promise.all([
|
||||
utils.createAsset(timeBucketUser.accessToken, { fileCreatedAt: new Date('1970-01-01').toISOString() }),
|
||||
utils.createAsset(timeBucketUser.accessToken, { fileCreatedAt: new Date('1970-02-10').toISOString() }),
|
||||
utils.createAsset(timeBucketUser.accessToken, { fileCreatedAt: new Date('1970-02-11').toISOString() }),
|
||||
utils.createAsset(timeBucketUser.accessToken, { fileCreatedAt: new Date('1970-02-11').toISOString() }),
|
||||
utils.createAsset(timeBucketUser.accessToken, { fileCreatedAt: new Date('1970-02-12').toISOString() }),
|
||||
]);
|
||||
|
||||
await utils.deleteAssets(timeBucketUser.accessToken, [user2Assets[4].id]);
|
||||
});
|
||||
|
||||
describe('GET /timeline/buckets', () => {
|
||||
@@ -74,7 +84,7 @@ describe('/timeline', () => {
|
||||
it('should not allow access for unrelated shared links', async () => {
|
||||
const sharedLink = await utils.createSharedLink(user.accessToken, {
|
||||
type: SharedLinkType.Individual,
|
||||
assetIds: userAssets.map(({ id }) => id),
|
||||
assetIds: user1Assets.map(({ id }) => id),
|
||||
});
|
||||
|
||||
const { status, body } = await request(app).get('/timeline/buckets').query({ key: sharedLink.key });
|
||||
@@ -202,5 +212,17 @@ describe('/timeline', () => {
|
||||
thumbhash: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('should return time bucket in trash', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.get('/timeline/bucket')
|
||||
.set('Authorization', `Bearer ${timeBucketUser.accessToken}`)
|
||||
.query({ timeBucket: '1970-02-01T00:00:00.000Z', isTrashed: true });
|
||||
|
||||
expect(status).toBe(200);
|
||||
|
||||
const timeBucket: TimeBucketAssetResponseDto = body;
|
||||
expect(timeBucket.isTrashed).toEqual([true]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -301,10 +301,9 @@
|
||||
"transcoding_encoding_options": "Encoding Options",
|
||||
"transcoding_encoding_options_description": "Set codecs, resolution, quality and other options for the encoded videos",
|
||||
"transcoding_hardware_acceleration": "Hardware Acceleration",
|
||||
"transcoding_hardware_acceleration_description": "Experimental; much faster, but will have lower quality at the same bitrate",
|
||||
"transcoding_hardware_acceleration_description": "Experimental: faster transcoding but may reduce quality at same bitrate",
|
||||
"transcoding_hardware_decoding": "Hardware decoding",
|
||||
"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.",
|
||||
"transcoding_max_bitrate": "Maximum bitrate",
|
||||
@@ -662,6 +661,8 @@
|
||||
"confirm_keep_this_delete_others": "All other assets in the stack will be deleted except for this asset. Are you sure you want to continue?",
|
||||
"confirm_new_pin_code": "Confirm new PIN code",
|
||||
"confirm_password": "Confirm password",
|
||||
"confirm_tag_face": "Do you want to tag this face as {name}?",
|
||||
"confirm_tag_face_unnamed": "Do you want to tag this face?",
|
||||
"connected_to": "Connected to",
|
||||
"contain": "Contain",
|
||||
"context": "Context",
|
||||
@@ -840,6 +841,7 @@
|
||||
"error_delete_face": "Error deleting face from asset",
|
||||
"error_loading_image": "Error loading image",
|
||||
"error_saving_image": "Error: {error}",
|
||||
"error_tag_face_bounding_box": "Error tagging face - cannot get bounding box coordinates",
|
||||
"error_title": "Error - Something went wrong",
|
||||
"errors": {
|
||||
"cannot_navigate_next_asset": "Cannot navigate to the next asset",
|
||||
@@ -978,7 +980,6 @@
|
||||
"exif_bottom_sheet_location": "LOCATION",
|
||||
"exif_bottom_sheet_people": "PEOPLE",
|
||||
"exif_bottom_sheet_person_add_person": "Add name",
|
||||
"exif_bottom_sheet_person_age": "Age {age}",
|
||||
"exif_bottom_sheet_person_age_months": "Age {months} months",
|
||||
"exif_bottom_sheet_person_age_year_months": "Age 1 year, {months} months",
|
||||
"exif_bottom_sheet_person_age_years": "Age {years}",
|
||||
@@ -1942,6 +1943,7 @@
|
||||
"view_previous_asset": "View previous asset",
|
||||
"view_qr_code": "View QR code",
|
||||
"view_stack": "View Stack",
|
||||
"view_user": "View User",
|
||||
"viewer_remove_from_stack": "Remove from Stack",
|
||||
"viewer_stack_use_as_main_asset": "Use as Main Asset",
|
||||
"viewer_unstack": "Un-Stack",
|
||||
|
||||
@@ -35,8 +35,8 @@ platform :android do
|
||||
task: 'bundle',
|
||||
build_type: 'Release',
|
||||
properties: {
|
||||
"android.injected.version.code" => 199,
|
||||
"android.injected.version.name" => "1.133.1",
|
||||
"android.injected.version.code" => 200,
|
||||
"android.injected.version.name" => "1.134.0",
|
||||
}
|
||||
)
|
||||
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')
|
||||
|
||||
@@ -543,7 +543,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 205;
|
||||
CURRENT_PROJECT_VERSION = 207;
|
||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -687,7 +687,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 205;
|
||||
CURRENT_PROJECT_VERSION = 207;
|
||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -717,7 +717,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 205;
|
||||
CURRENT_PROJECT_VERSION = 207;
|
||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -750,7 +750,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 205;
|
||||
CURRENT_PROJECT_VERSION = 207;
|
||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
@@ -794,7 +794,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 205;
|
||||
CURRENT_PROJECT_VERSION = 207;
|
||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
@@ -835,7 +835,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 205;
|
||||
CURRENT_PROJECT_VERSION = 207;
|
||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.132.3</string>
|
||||
<string>1.133.1</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
@@ -93,7 +93,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>205</string>
|
||||
<string>207</string>
|
||||
<key>FLTEnableImpeller</key>
|
||||
<true />
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
|
||||
@@ -22,7 +22,7 @@ platform :ios do
|
||||
path: "./Runner.xcodeproj",
|
||||
)
|
||||
increment_version_number(
|
||||
version_number: "1.133.1"
|
||||
version_number: "1.134.0"
|
||||
)
|
||||
increment_build_number(
|
||||
build_number: latest_testflight_build_number + 1,
|
||||
|
||||
@@ -13,6 +13,7 @@ const Map<String, Locale> locales = {
|
||||
'Czech (cs)': Locale('cs'),
|
||||
'Danish (da)': Locale('da'),
|
||||
'Dutch (nl)': Locale('nl'),
|
||||
'Estonian (et)': Locale('et'),
|
||||
'Finnish (fi)': Locale('fi'),
|
||||
'French (fr)': Locale('fr'),
|
||||
'Galician (gl)': Locale('gl'),
|
||||
|
||||
@@ -169,7 +169,7 @@ class PhotoViewCoreState extends State<PhotoViewCore>
|
||||
scale: newScale,
|
||||
position: widget.enablePanAlways
|
||||
? delta
|
||||
: clampPosition(position: delta * details.scale),
|
||||
: clampPosition(position: delta, scale: details.scale),
|
||||
rotation:
|
||||
widget.enableRotation ? _rotationBefore! + details.rotation : null,
|
||||
rotationFocusPoint: widget.enableRotation ? details.focalPoint : null,
|
||||
|
||||
5
mobile/openapi/README.md
generated
5
mobile/openapi/README.md
generated
@@ -3,7 +3,7 @@ Immich API
|
||||
|
||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: 1.133.1
|
||||
- API version: 1.134.0
|
||||
- Generator version: 7.8.0
|
||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||
|
||||
@@ -192,6 +192,7 @@ Class | Method | HTTP request | Description
|
||||
*ServerApi* | [**getStorage**](doc//ServerApi.md#getstorage) | **GET** /server/storage |
|
||||
*ServerApi* | [**getSupportedMediaTypes**](doc//ServerApi.md#getsupportedmediatypes) | **GET** /server/media-types |
|
||||
*ServerApi* | [**getTheme**](doc//ServerApi.md#gettheme) | **GET** /server/theme |
|
||||
*ServerApi* | [**getVersionCheck**](doc//ServerApi.md#getversioncheck) | **GET** /server/version-check |
|
||||
*ServerApi* | [**getVersionHistory**](doc//ServerApi.md#getversionhistory) | **GET** /server/version-history |
|
||||
*ServerApi* | [**pingServer**](doc//ServerApi.md#pingserver) | **GET** /server/ping |
|
||||
*ServerApi* | [**setServerLicense**](doc//ServerApi.md#setserverlicense) | **PUT** /server/license |
|
||||
@@ -226,6 +227,7 @@ Class | Method | HTTP request | Description
|
||||
*SystemConfigApi* | [**updateConfig**](doc//SystemConfigApi.md#updateconfig) | **PUT** /system-config |
|
||||
*SystemMetadataApi* | [**getAdminOnboarding**](doc//SystemMetadataApi.md#getadminonboarding) | **GET** /system-metadata/admin-onboarding |
|
||||
*SystemMetadataApi* | [**getReverseGeocodingState**](doc//SystemMetadataApi.md#getreversegeocodingstate) | **GET** /system-metadata/reverse-geocoding-state |
|
||||
*SystemMetadataApi* | [**getVersionCheckState**](doc//SystemMetadataApi.md#getversioncheckstate) | **GET** /system-metadata/version-check-state |
|
||||
*SystemMetadataApi* | [**updateAdminOnboarding**](doc//SystemMetadataApi.md#updateadminonboarding) | **POST** /system-metadata/admin-onboarding |
|
||||
*TagsApi* | [**bulkTagAssets**](doc//TagsApi.md#bulktagassets) | **PUT** /tags/assets |
|
||||
*TagsApi* | [**createTag**](doc//TagsApi.md#createtag) | **POST** /tags |
|
||||
@@ -525,6 +527,7 @@ Class | Method | HTTP request | Description
|
||||
- [ValidateLibraryDto](doc//ValidateLibraryDto.md)
|
||||
- [ValidateLibraryImportPathResponseDto](doc//ValidateLibraryImportPathResponseDto.md)
|
||||
- [ValidateLibraryResponseDto](doc//ValidateLibraryResponseDto.md)
|
||||
- [VersionCheckStateResponseDto](doc//VersionCheckStateResponseDto.md)
|
||||
- [VideoCodec](doc//VideoCodec.md)
|
||||
- [VideoContainer](doc//VideoContainer.md)
|
||||
|
||||
|
||||
1
mobile/openapi/lib/api.dart
generated
1
mobile/openapi/lib/api.dart
generated
@@ -320,6 +320,7 @@ part 'model/validate_access_token_response_dto.dart';
|
||||
part 'model/validate_library_dto.dart';
|
||||
part 'model/validate_library_import_path_response_dto.dart';
|
||||
part 'model/validate_library_response_dto.dart';
|
||||
part 'model/version_check_state_response_dto.dart';
|
||||
part 'model/video_codec.dart';
|
||||
part 'model/video_container.dart';
|
||||
|
||||
|
||||
41
mobile/openapi/lib/api/server_api.dart
generated
41
mobile/openapi/lib/api/server_api.dart
generated
@@ -418,6 +418,47 @@ class ServerApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /server/version-check' operation and returns the [Response].
|
||||
Future<Response> getVersionCheckWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/server/version-check';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
apiPath,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
Future<VersionCheckStateResponseDto?> getVersionCheck() async {
|
||||
final response = await getVersionCheckWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'VersionCheckStateResponseDto',) as VersionCheckStateResponseDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /server/version-history' operation and returns the [Response].
|
||||
Future<Response> getVersionHistoryWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
|
||||
41
mobile/openapi/lib/api/system_metadata_api.dart
generated
41
mobile/openapi/lib/api/system_metadata_api.dart
generated
@@ -98,6 +98,47 @@ class SystemMetadataApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /system-metadata/version-check-state' operation and returns the [Response].
|
||||
Future<Response> getVersionCheckStateWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/system-metadata/version-check-state';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
apiPath,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
Future<VersionCheckStateResponseDto?> getVersionCheckState() async {
|
||||
final response = await getVersionCheckStateWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'VersionCheckStateResponseDto',) as VersionCheckStateResponseDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'POST /system-metadata/admin-onboarding' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
|
||||
2
mobile/openapi/lib/api_client.dart
generated
2
mobile/openapi/lib/api_client.dart
generated
@@ -696,6 +696,8 @@ class ApiClient {
|
||||
return ValidateLibraryImportPathResponseDto.fromJson(value);
|
||||
case 'ValidateLibraryResponseDto':
|
||||
return ValidateLibraryResponseDto.fromJson(value);
|
||||
case 'VersionCheckStateResponseDto':
|
||||
return VersionCheckStateResponseDto.fromJson(value);
|
||||
case 'VideoCodec':
|
||||
return VideoCodecTypeTransformer().decode(value);
|
||||
case 'VideoContainer':
|
||||
|
||||
115
mobile/openapi/lib/model/version_check_state_response_dto.dart
generated
Normal file
115
mobile/openapi/lib/model/version_check_state_response_dto.dart
generated
Normal file
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class VersionCheckStateResponseDto {
|
||||
/// Returns a new [VersionCheckStateResponseDto] instance.
|
||||
VersionCheckStateResponseDto({
|
||||
required this.checkedAt,
|
||||
required this.releaseVersion,
|
||||
});
|
||||
|
||||
String? checkedAt;
|
||||
|
||||
String? releaseVersion;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is VersionCheckStateResponseDto &&
|
||||
other.checkedAt == checkedAt &&
|
||||
other.releaseVersion == releaseVersion;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(checkedAt == null ? 0 : checkedAt!.hashCode) +
|
||||
(releaseVersion == null ? 0 : releaseVersion!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'VersionCheckStateResponseDto[checkedAt=$checkedAt, releaseVersion=$releaseVersion]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
if (this.checkedAt != null) {
|
||||
json[r'checkedAt'] = this.checkedAt;
|
||||
} else {
|
||||
// json[r'checkedAt'] = null;
|
||||
}
|
||||
if (this.releaseVersion != null) {
|
||||
json[r'releaseVersion'] = this.releaseVersion;
|
||||
} else {
|
||||
// json[r'releaseVersion'] = null;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [VersionCheckStateResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static VersionCheckStateResponseDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "VersionCheckStateResponseDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return VersionCheckStateResponseDto(
|
||||
checkedAt: mapValueOfType<String>(json, r'checkedAt'),
|
||||
releaseVersion: mapValueOfType<String>(json, r'releaseVersion'),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<VersionCheckStateResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <VersionCheckStateResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = VersionCheckStateResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, VersionCheckStateResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, VersionCheckStateResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = VersionCheckStateResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of VersionCheckStateResponseDto-objects as value to a dart map
|
||||
static Map<String, List<VersionCheckStateResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<VersionCheckStateResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = VersionCheckStateResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'checkedAt',
|
||||
'releaseVersion',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ name: immich_mobile
|
||||
description: Immich - selfhosted backup media file on mobile phone
|
||||
|
||||
publish_to: 'none'
|
||||
version: 1.133.1+199
|
||||
version: 1.134.0+200
|
||||
|
||||
environment:
|
||||
sdk: '>=3.3.0 <4.0.0'
|
||||
|
||||
@@ -5563,6 +5563,38 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/server/version-check": {
|
||||
"get": {
|
||||
"operationId": "getVersionCheck",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/VersionCheckStateResponseDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Server"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/server/version-history": {
|
||||
"get": {
|
||||
"operationId": "getVersionHistory",
|
||||
@@ -6846,6 +6878,38 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/system-metadata/version-check-state": {
|
||||
"get": {
|
||||
"operationId": "getVersionCheckState",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/VersionCheckStateResponseDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"System Metadata"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/tags": {
|
||||
"get": {
|
||||
"operationId": "getAllTags",
|
||||
@@ -8132,7 +8196,7 @@
|
||||
"info": {
|
||||
"title": "Immich",
|
||||
"description": "Immich API",
|
||||
"version": "1.133.1",
|
||||
"version": "1.134.0",
|
||||
"contact": {}
|
||||
},
|
||||
"tags": [],
|
||||
@@ -14939,6 +15003,23 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"VersionCheckStateResponseDto": {
|
||||
"properties": {
|
||||
"checkedAt": {
|
||||
"nullable": true,
|
||||
"type": "string"
|
||||
},
|
||||
"releaseVersion": {
|
||||
"nullable": true,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"checkedAt",
|
||||
"releaseVersion"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"VideoCodec": {
|
||||
"enum": [
|
||||
"h264",
|
||||
|
||||
@@ -1 +1 @@
|
||||
22.15.1
|
||||
22.16.0
|
||||
|
||||
12
open-api/typescript-sdk/package-lock.json
generated
12
open-api/typescript-sdk/package-lock.json
generated
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.133.1",
|
||||
"version": "1.134.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.133.1",
|
||||
"version": "1.134.0",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"@oazapfts/runtime": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.15.18",
|
||||
"@types/node": "^22.15.21",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
@@ -23,9 +23,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.15.19",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.19.tgz",
|
||||
"integrity": "sha512-3vMNr4TzNQyjHcRZadojpRaD9Ofr6LsonZAoQ+HMUa/9ORTPoxVIw0e0mpqWpdjj8xybyCM+oKOUH2vwFu/oEw==",
|
||||
"version": "22.15.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz",
|
||||
"integrity": "sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@immich/sdk",
|
||||
"version": "1.133.1",
|
||||
"version": "1.134.0",
|
||||
"description": "Auto-generated TypeScript SDK for the Immich API",
|
||||
"type": "module",
|
||||
"main": "./build/index.js",
|
||||
@@ -19,7 +19,7 @@
|
||||
"@oazapfts/runtime": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.15.18",
|
||||
"@types/node": "^22.15.21",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"repository": {
|
||||
@@ -28,6 +28,6 @@
|
||||
"directory": "open-api/typescript-sdk"
|
||||
},
|
||||
"volta": {
|
||||
"node": "22.15.1"
|
||||
"node": "22.16.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Immich
|
||||
* 1.133.1
|
||||
* 1.134.0
|
||||
* DO NOT MODIFY - This file has been generated using oazapfts.
|
||||
* See https://www.npmjs.com/package/oazapfts
|
||||
*/
|
||||
@@ -1076,6 +1076,10 @@ export type ServerVersionResponseDto = {
|
||||
minor: number;
|
||||
patch: number;
|
||||
};
|
||||
export type VersionCheckStateResponseDto = {
|
||||
checkedAt: string | null;
|
||||
releaseVersion: string | null;
|
||||
};
|
||||
export type ServerVersionHistoryResponseDto = {
|
||||
createdAt: string;
|
||||
id: string;
|
||||
@@ -2947,6 +2951,14 @@ export function getServerVersion(opts?: Oazapfts.RequestOpts) {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function getVersionCheck(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: VersionCheckStateResponseDto;
|
||||
}>("/server/version-check", {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function getVersionHistory(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
@@ -3284,6 +3296,14 @@ export function getReverseGeocodingState(opts?: Oazapfts.RequestOpts) {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function getVersionCheckState(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: VersionCheckStateResponseDto;
|
||||
}>("/system-metadata/version-check-state", {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function getAllTags(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
|
||||
@@ -1 +1 @@
|
||||
22.15.1
|
||||
22.16.0
|
||||
|
||||
@@ -26,7 +26,7 @@ COPY --from=dev /usr/src/app/node_modules/@img ./node_modules/@img
|
||||
COPY --from=dev /usr/src/app/node_modules/exiftool-vendored.pl ./node_modules/exiftool-vendored.pl
|
||||
|
||||
# web build
|
||||
FROM node:22.15.0-alpine3.20@sha256:686b8892b69879ef5bfd6047589666933508f9a5451c67320df3070ba0e9807b AS web
|
||||
FROM node:22.16.0-alpine3.20@sha256:2289fb1fba0f4633b08ec47b94a89c7e20b829fc5679f9b7b298eaa2f1ed8b7e AS web
|
||||
|
||||
WORKDIR /usr/src/open-api/typescript-sdk
|
||||
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
|
||||
|
||||
529
server/package-lock.json
generated
529
server/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "immich",
|
||||
"version": "1.133.1",
|
||||
"version": "1.134.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "immich",
|
||||
"version": "1.133.1",
|
||||
"version": "1.134.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
@@ -64,7 +64,7 @@
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"sanitize-html": "^2.14.0",
|
||||
"semver": "^7.6.2",
|
||||
"sharp": "^0.34.0",
|
||||
"sharp": "^0.34.2",
|
||||
"sirv": "^3.0.0",
|
||||
"tailwindcss-preset-email": "^1.3.2",
|
||||
"thumbhash": "^0.1.1",
|
||||
@@ -92,7 +92,7 @@
|
||||
"@types/lodash": "^4.14.197",
|
||||
"@types/mock-fs": "^4.13.1",
|
||||
"@types/multer": "^1.4.7",
|
||||
"@types/node": "^22.15.18",
|
||||
"@types/node": "^22.15.21",
|
||||
"@types/nodemailer": "^6.4.14",
|
||||
"@types/picomatch": "^4.0.0",
|
||||
"@types/pngjs": "^6.0.5",
|
||||
@@ -661,12 +661,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz",
|
||||
"integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
|
||||
"version": "7.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.3.tgz",
|
||||
"integrity": "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.27.1"
|
||||
"@babel/types": "^7.27.3"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
@@ -717,9 +717,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
|
||||
"integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
|
||||
"version": "7.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz",
|
||||
"integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.27.1",
|
||||
@@ -966,9 +966,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/core": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz",
|
||||
"integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==",
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz",
|
||||
"integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -1016,13 +1016,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "9.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz",
|
||||
"integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==",
|
||||
"version": "9.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz",
|
||||
"integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://eslint.org/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/object-schema": {
|
||||
@@ -1036,13 +1039,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/plugin-kit": {
|
||||
"version": "0.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz",
|
||||
"integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==",
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz",
|
||||
"integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@eslint/core": "^0.13.0",
|
||||
"@eslint/core": "^0.14.0",
|
||||
"levn": "^0.4.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1185,9 +1188,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-darwin-arm64": {
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.1.tgz",
|
||||
"integrity": "sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==",
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.2.tgz",
|
||||
"integrity": "sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1207,9 +1210,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-darwin-x64": {
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.1.tgz",
|
||||
"integrity": "sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==",
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.2.tgz",
|
||||
"integrity": "sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1373,9 +1376,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-arm": {
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.1.tgz",
|
||||
"integrity": "sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==",
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.2.tgz",
|
||||
"integrity": "sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -1395,9 +1398,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-arm64": {
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.1.tgz",
|
||||
"integrity": "sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==",
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.2.tgz",
|
||||
"integrity": "sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1417,9 +1420,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-s390x": {
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.1.tgz",
|
||||
"integrity": "sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==",
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.2.tgz",
|
||||
"integrity": "sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -1439,9 +1442,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-x64": {
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.1.tgz",
|
||||
"integrity": "sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==",
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.2.tgz",
|
||||
"integrity": "sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1461,9 +1464,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linuxmusl-arm64": {
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.1.tgz",
|
||||
"integrity": "sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==",
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.2.tgz",
|
||||
"integrity": "sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1483,9 +1486,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linuxmusl-x64": {
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.1.tgz",
|
||||
"integrity": "sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==",
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.2.tgz",
|
||||
"integrity": "sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1505,16 +1508,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-wasm32": {
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.1.tgz",
|
||||
"integrity": "sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==",
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.2.tgz",
|
||||
"integrity": "sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==",
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/runtime": "^1.4.0"
|
||||
"@emnapi/runtime": "^1.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
@@ -1523,10 +1526,29 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-win32-arm64": {
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.2.tgz",
|
||||
"integrity": "sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-win32-ia32": {
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.1.tgz",
|
||||
"integrity": "sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==",
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.2.tgz",
|
||||
"integrity": "sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -1543,9 +1565,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-win32-x64": {
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.1.tgz",
|
||||
"integrity": "sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==",
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.2.tgz",
|
||||
"integrity": "sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -2118,28 +2140,6 @@
|
||||
"integrity": "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@modelcontextprotocol/sdk": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.1.tgz",
|
||||
"integrity": "sha512-9LfmxKTb1v+vUS1/emSk1f5ePmTLkb9Le9AxOB5T0XM59EUumwcS45z05h7aiZx3GI0Bl7mjb3FMEglYj+acuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"content-type": "^1.0.5",
|
||||
"cors": "^2.8.5",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"eventsource": "^3.0.2",
|
||||
"express": "^5.0.1",
|
||||
"express-rate-limit": "^7.5.0",
|
||||
"pkce-challenge": "^5.0.0",
|
||||
"raw-body": "^3.0.0",
|
||||
"zod": "^3.23.8",
|
||||
"zod-to-json-schema": "^3.24.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz",
|
||||
@@ -4867,9 +4867,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@swc/core": {
|
||||
"version": "1.11.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.24.tgz",
|
||||
"integrity": "sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg==",
|
||||
"version": "1.11.29",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.29.tgz",
|
||||
"integrity": "sha512-g4mThMIpWbNhV8G2rWp5a5/Igv8/2UFRJx2yImrLGMgrDDYZIopqZ/z0jZxDgqNA1QDx93rpwNF7jGsxVWcMlA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
@@ -4885,16 +4885,16 @@
|
||||
"url": "https://opencollective.com/swc"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-darwin-arm64": "1.11.24",
|
||||
"@swc/core-darwin-x64": "1.11.24",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.11.24",
|
||||
"@swc/core-linux-arm64-gnu": "1.11.24",
|
||||
"@swc/core-linux-arm64-musl": "1.11.24",
|
||||
"@swc/core-linux-x64-gnu": "1.11.24",
|
||||
"@swc/core-linux-x64-musl": "1.11.24",
|
||||
"@swc/core-win32-arm64-msvc": "1.11.24",
|
||||
"@swc/core-win32-ia32-msvc": "1.11.24",
|
||||
"@swc/core-win32-x64-msvc": "1.11.24"
|
||||
"@swc/core-darwin-arm64": "1.11.29",
|
||||
"@swc/core-darwin-x64": "1.11.29",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.11.29",
|
||||
"@swc/core-linux-arm64-gnu": "1.11.29",
|
||||
"@swc/core-linux-arm64-musl": "1.11.29",
|
||||
"@swc/core-linux-x64-gnu": "1.11.29",
|
||||
"@swc/core-linux-x64-musl": "1.11.29",
|
||||
"@swc/core-win32-arm64-msvc": "1.11.29",
|
||||
"@swc/core-win32-ia32-msvc": "1.11.29",
|
||||
"@swc/core-win32-x64-msvc": "1.11.29"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/helpers": ">=0.5.17"
|
||||
@@ -4906,9 +4906,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-arm64": {
|
||||
"version": "1.11.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.24.tgz",
|
||||
"integrity": "sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA==",
|
||||
"version": "1.11.29",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.29.tgz",
|
||||
"integrity": "sha512-whsCX7URzbuS5aET58c75Dloby3Gtj/ITk2vc4WW6pSDQKSPDuONsIcZ7B2ng8oz0K6ttbi4p3H/PNPQLJ4maQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4923,9 +4923,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-x64": {
|
||||
"version": "1.11.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.24.tgz",
|
||||
"integrity": "sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ==",
|
||||
"version": "1.11.29",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.29.tgz",
|
||||
"integrity": "sha512-S3eTo/KYFk+76cWJRgX30hylN5XkSmjYtCBnM4jPLYn7L6zWYEPajsFLmruQEiTEDUg0gBEWLMNyUeghtswouw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -4940,9 +4940,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm-gnueabihf": {
|
||||
"version": "1.11.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.24.tgz",
|
||||
"integrity": "sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw==",
|
||||
"version": "1.11.29",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.29.tgz",
|
||||
"integrity": "sha512-o9gdshbzkUMG6azldHdmKklcfrcMx+a23d/2qHQHPDLUPAN+Trd+sDQUYArK5Fcm7TlpG4sczz95ghN0DMkM7g==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -4957,9 +4957,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-gnu": {
|
||||
"version": "1.11.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.24.tgz",
|
||||
"integrity": "sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg==",
|
||||
"version": "1.11.29",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.29.tgz",
|
||||
"integrity": "sha512-sLoaciOgUKQF1KX9T6hPGzvhOQaJn+3DHy4LOHeXhQqvBgr+7QcZ+hl4uixPKTzxk6hy6Hb0QOvQEdBAAR1gXw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4974,9 +4974,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-musl": {
|
||||
"version": "1.11.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.24.tgz",
|
||||
"integrity": "sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw==",
|
||||
"version": "1.11.29",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.29.tgz",
|
||||
"integrity": "sha512-PwjB10BC0N+Ce7RU/L23eYch6lXFHz7r3NFavIcwDNa/AAqywfxyxh13OeRy+P0cg7NDpWEETWspXeI4Ek8otw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4991,9 +4991,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-gnu": {
|
||||
"version": "1.11.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.24.tgz",
|
||||
"integrity": "sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg==",
|
||||
"version": "1.11.29",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.29.tgz",
|
||||
"integrity": "sha512-i62vBVoPaVe9A3mc6gJG07n0/e7FVeAvdD9uzZTtGLiuIfVfIBta8EMquzvf+POLycSk79Z6lRhGPZPJPYiQaA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -5008,9 +5008,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-musl": {
|
||||
"version": "1.11.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.24.tgz",
|
||||
"integrity": "sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw==",
|
||||
"version": "1.11.29",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.29.tgz",
|
||||
"integrity": "sha512-YER0XU1xqFdK0hKkfSVX1YIyCvMDI7K07GIpefPvcfyNGs38AXKhb2byySDjbVxkdl4dycaxxhRyhQ2gKSlsFQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -5025,9 +5025,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-arm64-msvc": {
|
||||
"version": "1.11.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.24.tgz",
|
||||
"integrity": "sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ==",
|
||||
"version": "1.11.29",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.29.tgz",
|
||||
"integrity": "sha512-po+WHw+k9g6FAg5IJ+sMwtA/fIUL3zPQ4m/uJgONBATCVnDDkyW6dBA49uHNVtSEvjvhuD8DVWdFP847YTcITw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -5042,9 +5042,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-ia32-msvc": {
|
||||
"version": "1.11.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.24.tgz",
|
||||
"integrity": "sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ==",
|
||||
"version": "1.11.29",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.29.tgz",
|
||||
"integrity": "sha512-h+NjOrbqdRBYr5ItmStmQt6x3tnhqgwbj9YxdGPepbTDamFv7vFnhZR0YfB3jz3UKJ8H3uGJ65Zw1VsC+xpFkg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -5059,9 +5059,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-x64-msvc": {
|
||||
"version": "1.11.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.24.tgz",
|
||||
"integrity": "sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w==",
|
||||
"version": "1.11.29",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.29.tgz",
|
||||
"integrity": "sha512-Q8cs2BDV9wqDvqobkXOYdC+pLUSEpX/KvI0Dgfun1F+LzuLotRFuDhrvkU9ETJA6OnD2+Fn/ieHgloiKA/Mn/g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -5104,23 +5104,23 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@testcontainers/postgresql": {
|
||||
"version": "10.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@testcontainers/postgresql/-/postgresql-10.26.0.tgz",
|
||||
"integrity": "sha512-xc5ahJ7HcYayMuyl5lmAdx/9CddBpbdmaSWhPtxRWel3t3EoMGR/7tk8uynTq+mZeYHZFXaudy/x3etsWwM2mQ==",
|
||||
"version": "10.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@testcontainers/postgresql/-/postgresql-10.27.0.tgz",
|
||||
"integrity": "sha512-xJMhH68GVl1wE+FifIgKElZqArBeagat4qFh0etN/bvR3FC0mdHWKkzzAToNficSNXxutN5UarYlSSt0YLMMbQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"testcontainers": "^10.26.0"
|
||||
"testcontainers": "^10.27.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@testcontainers/redis": {
|
||||
"version": "10.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@testcontainers/redis/-/redis-10.26.0.tgz",
|
||||
"integrity": "sha512-eDX421zhoePqbVpNMhyxw7IAK65VdIp0rrxdREfZm6epkVSv8lRlWtLoet7Hxm3Jak+sfLH5TvVDML7cLxfcAg==",
|
||||
"version": "10.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@testcontainers/redis/-/redis-10.27.0.tgz",
|
||||
"integrity": "sha512-jxiGM9kcUFU+2EnoeLQX8WniCVyxPoKhQml+SqnLbTxZ7S59Ih7Ccur/U/CDRhJ/9cTAkdZzURzuuMqY2u8UjA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"testcontainers": "^10.26.0"
|
||||
"testcontainers": "^10.27.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tokenizer/inflate": {
|
||||
@@ -5244,13 +5244,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/compression": {
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz",
|
||||
"integrity": "sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==",
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.8.0.tgz",
|
||||
"integrity": "sha512-g4vmPIwbTii9dX1HVioHbOolubEaf4re4vDxuzpKrzz9uI7uarBExi9begX0cXyIB85jXZ5X2A/v8rsHZxSAPw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/express": "*"
|
||||
"@types/express": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/connect": {
|
||||
@@ -5341,9 +5342,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/express": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
|
||||
"integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
|
||||
"version": "4.17.22",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.22.tgz",
|
||||
"integrity": "sha512-eZUmSnhRX9YRSkplpz0N+k6NljUUn5l3EWZIKZvYzhvMphEuNiyyy1viH/ejgt66JWgALwC/gtSUAeQKtSwW/w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -5415,9 +5416,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.17.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz",
|
||||
"integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==",
|
||||
"version": "4.17.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz",
|
||||
"integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -5480,9 +5481,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.15.19",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.19.tgz",
|
||||
"integrity": "sha512-3vMNr4TzNQyjHcRZadojpRaD9Ofr6LsonZAoQ+HMUa/9ORTPoxVIw0e0mpqWpdjj8xybyCM+oKOUH2vwFu/oEw==",
|
||||
"version": "22.15.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz",
|
||||
"integrity": "sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
@@ -5576,9 +5577,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "19.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.4.tgz",
|
||||
"integrity": "sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==",
|
||||
"version": "19.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.5.tgz",
|
||||
"integrity": "sha512-piErsCVVbpMMT2r7wbawdZsq4xMvIAhQuac2gedQHysu1TZYEigE6pnFfgZT+/jQnrRuF5r+SHzuehFjfRjr4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -5951,9 +5952,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/coverage-v8": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.3.tgz",
|
||||
"integrity": "sha512-cj76U5gXCl3g88KSnf80kof6+6w+K4BjOflCl7t6yRJPDuCrHtVu0SgNYOUARJOL5TI8RScDbm5x4s1/P9bvpw==",
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.4.tgz",
|
||||
"integrity": "sha512-G4p6OtioySL+hPV7Y6JHlhpsODbJzt1ndwHAFkyk6vVjpK03PFsKnauZIzcd0PrK4zAbc5lc+jeZ+eNGiMA+iw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -5974,8 +5975,8 @@
|
||||
"url": "https://opencollective.com/vitest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vitest/browser": "3.1.3",
|
||||
"vitest": "3.1.3"
|
||||
"@vitest/browser": "3.1.4",
|
||||
"vitest": "3.1.4"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vitest/browser": {
|
||||
@@ -5984,14 +5985,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/expect": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.3.tgz",
|
||||
"integrity": "sha512-7FTQQuuLKmN1Ig/h+h/GO+44Q1IlglPlR2es4ab7Yvfx+Uk5xsv+Ykk+MEt/M2Yn/xGmzaLKxGw2lgy2bwuYqg==",
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.4.tgz",
|
||||
"integrity": "sha512-xkD/ljeliyaClDYqHPNCiJ0plY5YIcM0OlRiZizLhlPmpXWpxnGMyTZXOHFhFeG7w9P5PBeL4IdtJ/HeQwTbQA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/spy": "3.1.3",
|
||||
"@vitest/utils": "3.1.3",
|
||||
"@vitest/spy": "3.1.4",
|
||||
"@vitest/utils": "3.1.4",
|
||||
"chai": "^5.2.0",
|
||||
"tinyrainbow": "^2.0.0"
|
||||
},
|
||||
@@ -6000,13 +6001,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/mocker": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.3.tgz",
|
||||
"integrity": "sha512-PJbLjonJK82uCWHjzgBJZuR7zmAOrSvKk1QBxrennDIgtH4uK0TB1PvYmc0XBCigxxtiAVPfWtAdy4lpz8SQGQ==",
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.4.tgz",
|
||||
"integrity": "sha512-8IJ3CvwtSw/EFXqWFL8aCMu+YyYXG2WUSrQbViOZkWTKTVicVwZ/YiEZDSqD00kX+v/+W+OnxhNWoeVKorHygA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/spy": "3.1.3",
|
||||
"@vitest/spy": "3.1.4",
|
||||
"estree-walker": "^3.0.3",
|
||||
"magic-string": "^0.30.17"
|
||||
},
|
||||
@@ -6037,9 +6038,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/pretty-format": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.3.tgz",
|
||||
"integrity": "sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA==",
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.4.tgz",
|
||||
"integrity": "sha512-cqv9H9GvAEoTaoq+cYqUTCGscUjKqlJZC7PRwY5FMySVj5J+xOm1KQcCiYHJOEzOKRUhLH4R2pTwvFlWCEScsg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -6050,13 +6051,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/runner": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.3.tgz",
|
||||
"integrity": "sha512-Tae+ogtlNfFei5DggOsSUvkIaSuVywujMj6HzR97AHK6XK8i3BuVyIifWAm/sE3a15lF5RH9yQIrbXYuo0IFyA==",
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.4.tgz",
|
||||
"integrity": "sha512-djTeF1/vt985I/wpKVFBMWUlk/I7mb5hmD5oP8K9ACRmVXgKTae3TUOtXAEBfslNKPzUQvnKhNd34nnRSYgLNQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/utils": "3.1.3",
|
||||
"@vitest/utils": "3.1.4",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
"funding": {
|
||||
@@ -6064,13 +6065,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/snapshot": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.3.tgz",
|
||||
"integrity": "sha512-XVa5OPNTYUsyqG9skuUkFzAeFnEzDp8hQu7kZ0N25B1+6KjGm4hWLtURyBbsIAOekfWQ7Wuz/N/XXzgYO3deWQ==",
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.4.tgz",
|
||||
"integrity": "sha512-JPHf68DvuO7vilmvwdPr9TS0SuuIzHvxeaCkxYcCD4jTk67XwL45ZhEHFKIuCm8CYstgI6LZ4XbwD6ANrwMpFg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/pretty-format": "3.1.3",
|
||||
"@vitest/pretty-format": "3.1.4",
|
||||
"magic-string": "^0.30.17",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
@@ -6079,9 +6080,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/spy": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.3.tgz",
|
||||
"integrity": "sha512-x6w+ctOEmEXdWaa6TO4ilb7l9DxPR5bwEb6hILKuxfU1NqWT2mpJD9NJN7t3OTfxmVlOMrvtoFJGdgyzZ605lQ==",
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.4.tgz",
|
||||
"integrity": "sha512-Xg1bXhu+vtPXIodYN369M86K8shGLouNjoVI78g8iAq2rFoHFdajNvJJ5A/9bPMFcfQqdaCpOgWKEoMQg/s0Yg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -6092,13 +6093,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/utils": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.3.tgz",
|
||||
"integrity": "sha512-2Ltrpht4OmHO9+c/nmHtF09HWiyWdworqnHIwjfvDyWjuwKbdkcS9AnhsDn+8E2RM4x++foD1/tNuLPVvWG1Rg==",
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.4.tgz",
|
||||
"integrity": "sha512-yriMuO1cfFhmiGc8ataN51+9ooHRuURdfAZfwFd3usWynjzpLslZdYnRegTv32qdgtJTsj15FoeZe2g15fY1gg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/pretty-format": "3.1.3",
|
||||
"@vitest/pretty-format": "3.1.4",
|
||||
"loupe": "^3.1.3",
|
||||
"tinyrainbow": "^2.0.0"
|
||||
},
|
||||
@@ -7104,9 +7105,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/bullmq": {
|
||||
"version": "5.52.2",
|
||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.52.2.tgz",
|
||||
"integrity": "sha512-fK/dKIv8ymyys4K+zeNEPA+yuYWzRPmBWUmwIMz8DvYekadl8VG19yUx94Na0n0cLAi+spdn3a/+ufkYK7CBUg==",
|
||||
"version": "5.53.0",
|
||||
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.53.0.tgz",
|
||||
"integrity": "sha512-AbzcwR+9GdgrenolOC9kApF+TkUKZpUCMiFbXgRYw9ivWhOfLCqKeajIptM7NdwhY7cpXgv+QpbweUuQZUxkyA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cron-parser": "^4.9.0",
|
||||
@@ -8393,9 +8394,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
|
||||
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
|
||||
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -8971,9 +8972,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "9.26.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.26.0.tgz",
|
||||
"integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==",
|
||||
"version": "9.27.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz",
|
||||
"integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8981,14 +8982,13 @@
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
"@eslint/config-array": "^0.20.0",
|
||||
"@eslint/config-helpers": "^0.2.1",
|
||||
"@eslint/core": "^0.13.0",
|
||||
"@eslint/core": "^0.14.0",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "9.26.0",
|
||||
"@eslint/plugin-kit": "^0.2.8",
|
||||
"@eslint/js": "9.27.0",
|
||||
"@eslint/plugin-kit": "^0.3.1",
|
||||
"@humanfs/node": "^0.16.6",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@humanwhocodes/retry": "^0.4.2",
|
||||
"@modelcontextprotocol/sdk": "^1.8.0",
|
||||
"@types/estree": "^1.0.6",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"ajv": "^6.12.4",
|
||||
@@ -9012,8 +9012,7 @@
|
||||
"lodash.merge": "^4.6.2",
|
||||
"minimatch": "^3.1.2",
|
||||
"natural-compare": "^1.4.0",
|
||||
"optionator": "^0.9.3",
|
||||
"zod": "^3.24.2"
|
||||
"optionator": "^0.9.3"
|
||||
},
|
||||
"bin": {
|
||||
"eslint": "bin/eslint.js"
|
||||
@@ -9288,29 +9287,6 @@
|
||||
"node": ">=0.8.x"
|
||||
}
|
||||
},
|
||||
"node_modules/eventsource": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz",
|
||||
"integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eventsource-parser": "^3.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eventsource-parser": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz",
|
||||
"integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/exiftool-vendored": {
|
||||
"version": "28.8.0",
|
||||
"resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-28.8.0.tgz",
|
||||
@@ -9397,22 +9373,6 @@
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/express-rate-limit": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz",
|
||||
"integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/express-rate-limit"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"express": "^4.11 || 5 || ^5.0.0-beta.1"
|
||||
}
|
||||
},
|
||||
"node_modules/express/node_modules/cookie": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
|
||||
@@ -13503,16 +13463,6 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/pkce-challenge": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz",
|
||||
"integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pluralize": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
|
||||
@@ -15012,15 +14962,15 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sharp": {
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.1.tgz",
|
||||
"integrity": "sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==",
|
||||
"version": "0.34.2",
|
||||
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.2.tgz",
|
||||
"integrity": "sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"color": "^4.2.3",
|
||||
"detect-libc": "^2.0.3",
|
||||
"semver": "^7.7.1"
|
||||
"detect-libc": "^2.0.4",
|
||||
"semver": "^7.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
@@ -15029,8 +14979,8 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-darwin-arm64": "0.34.1",
|
||||
"@img/sharp-darwin-x64": "0.34.1",
|
||||
"@img/sharp-darwin-arm64": "0.34.2",
|
||||
"@img/sharp-darwin-x64": "0.34.2",
|
||||
"@img/sharp-libvips-darwin-arm64": "1.1.0",
|
||||
"@img/sharp-libvips-darwin-x64": "1.1.0",
|
||||
"@img/sharp-libvips-linux-arm": "1.1.0",
|
||||
@@ -15040,15 +14990,16 @@
|
||||
"@img/sharp-libvips-linux-x64": "1.1.0",
|
||||
"@img/sharp-libvips-linuxmusl-arm64": "1.1.0",
|
||||
"@img/sharp-libvips-linuxmusl-x64": "1.1.0",
|
||||
"@img/sharp-linux-arm": "0.34.1",
|
||||
"@img/sharp-linux-arm64": "0.34.1",
|
||||
"@img/sharp-linux-s390x": "0.34.1",
|
||||
"@img/sharp-linux-x64": "0.34.1",
|
||||
"@img/sharp-linuxmusl-arm64": "0.34.1",
|
||||
"@img/sharp-linuxmusl-x64": "0.34.1",
|
||||
"@img/sharp-wasm32": "0.34.1",
|
||||
"@img/sharp-win32-ia32": "0.34.1",
|
||||
"@img/sharp-win32-x64": "0.34.1"
|
||||
"@img/sharp-linux-arm": "0.34.2",
|
||||
"@img/sharp-linux-arm64": "0.34.2",
|
||||
"@img/sharp-linux-s390x": "0.34.2",
|
||||
"@img/sharp-linux-x64": "0.34.2",
|
||||
"@img/sharp-linuxmusl-arm64": "0.34.2",
|
||||
"@img/sharp-linuxmusl-x64": "0.34.2",
|
||||
"@img/sharp-wasm32": "0.34.2",
|
||||
"@img/sharp-win32-arm64": "0.34.2",
|
||||
"@img/sharp-win32-ia32": "0.34.2",
|
||||
"@img/sharp-win32-x64": "0.34.2"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
@@ -15489,9 +15440,9 @@
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/sql-formatter": {
|
||||
"version": "15.6.1",
|
||||
"resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.6.1.tgz",
|
||||
"integrity": "sha512-uoKbRLVbjzwa8ouY4lI9YM387zRxDv9Gg5kZBzu2iNls2wVBlDLshhudCstczddRvj7J+xOpHTTWX6Z0lRgYGA==",
|
||||
"version": "15.6.2",
|
||||
"resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.6.2.tgz",
|
||||
"integrity": "sha512-ZjqOfJGuB97UeHzTJoTbadlM0h9ynehtSTHNUbGfXR4HZ4rCIoD2oIW91W+A5oE76k8hl0Uz5GD8Sx3Pt9Xa3w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -16477,9 +16428,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/testcontainers": {
|
||||
"version": "10.26.0",
|
||||
"resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.26.0.tgz",
|
||||
"integrity": "sha512-4Iv3KB23pZcnxnXg4eIlOpXuvx4aHexxLY6URiciRQrc3Dao09NsVoYGxD8sV9heKUZ107mecalDITx4NZHo7A==",
|
||||
"version": "10.27.0",
|
||||
"resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.27.0.tgz",
|
||||
"integrity": "sha512-Y1A2OerjRKUDZ00tAbn1hHHHVeEH+jRgg7a41AF6mLUZPlBIkL8stSQkEzziFp1IK3Id9hPKu7Iq7rIpavkYaw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -16497,7 +16448,7 @@
|
||||
"ssh-remote-port-forward": "^1.0.4",
|
||||
"tar-fs": "^3.0.7",
|
||||
"tmp": "^0.2.3",
|
||||
"undici": "^5.28.5"
|
||||
"undici": "^5.29.0"
|
||||
}
|
||||
},
|
||||
"node_modules/testcontainers/node_modules/tmp": {
|
||||
@@ -17519,9 +17470,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite-node": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.3.tgz",
|
||||
"integrity": "sha512-uHV4plJ2IxCl4u1up1FQRrqclylKAogbtBfOTwcuJ28xFi+89PZ57BRh+naIRvH70HPwxy5QHYzg1OrEaC7AbA==",
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.4.tgz",
|
||||
"integrity": "sha512-6enNwYnpyDo4hEgytbmc6mYWHXDHYEn0D1/rw4Q+tnHUGtKTJsn8T1YkX6Q18wI5LCrS8CTYlBaiCqxOy2kvUA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -17649,19 +17600,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vitest": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.3.tgz",
|
||||
"integrity": "sha512-188iM4hAHQ0km23TN/adso1q5hhwKqUpv+Sd6p5sOuh6FhQnRNW3IsiIpvxqahtBabsJ2SLZgmGSpcYK4wQYJw==",
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.4.tgz",
|
||||
"integrity": "sha512-Ta56rT7uWxCSJXlBtKgIlApJnT6e6IGmTYxYcmxjJ4ujuZDI59GUQgVDObXXJujOmPDBYXHK1qmaGtneu6TNIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/expect": "3.1.3",
|
||||
"@vitest/mocker": "3.1.3",
|
||||
"@vitest/pretty-format": "^3.1.3",
|
||||
"@vitest/runner": "3.1.3",
|
||||
"@vitest/snapshot": "3.1.3",
|
||||
"@vitest/spy": "3.1.3",
|
||||
"@vitest/utils": "3.1.3",
|
||||
"@vitest/expect": "3.1.4",
|
||||
"@vitest/mocker": "3.1.4",
|
||||
"@vitest/pretty-format": "^3.1.4",
|
||||
"@vitest/runner": "3.1.4",
|
||||
"@vitest/snapshot": "3.1.4",
|
||||
"@vitest/spy": "3.1.4",
|
||||
"@vitest/utils": "3.1.4",
|
||||
"chai": "^5.2.0",
|
||||
"debug": "^4.4.0",
|
||||
"expect-type": "^1.2.1",
|
||||
@@ -17674,7 +17625,7 @@
|
||||
"tinypool": "^1.0.2",
|
||||
"tinyrainbow": "^2.0.0",
|
||||
"vite": "^5.0.0 || ^6.0.0",
|
||||
"vite-node": "3.1.3",
|
||||
"vite-node": "3.1.4",
|
||||
"why-is-node-running": "^2.3.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -17690,8 +17641,8 @@
|
||||
"@edge-runtime/vm": "*",
|
||||
"@types/debug": "^4.1.12",
|
||||
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
|
||||
"@vitest/browser": "3.1.3",
|
||||
"@vitest/ui": "3.1.3",
|
||||
"@vitest/browser": "3.1.4",
|
||||
"@vitest/ui": "3.1.4",
|
||||
"happy-dom": "*",
|
||||
"jsdom": "*"
|
||||
},
|
||||
@@ -18267,26 +18218,6 @@
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.24.4",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz",
|
||||
"integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
},
|
||||
"node_modules/zod-to-json-schema": {
|
||||
"version": "3.24.5",
|
||||
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz",
|
||||
"integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"zod": "^3.24.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich",
|
||||
"version": "1.133.1",
|
||||
"version": "1.134.0",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
@@ -90,7 +90,7 @@
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"sanitize-html": "^2.14.0",
|
||||
"semver": "^7.6.2",
|
||||
"sharp": "^0.34.0",
|
||||
"sharp": "^0.34.2",
|
||||
"sirv": "^3.0.0",
|
||||
"tailwindcss-preset-email": "^1.3.2",
|
||||
"thumbhash": "^0.1.1",
|
||||
@@ -118,7 +118,7 @@
|
||||
"@types/lodash": "^4.14.197",
|
||||
"@types/mock-fs": "^4.13.1",
|
||||
"@types/multer": "^1.4.7",
|
||||
"@types/node": "^22.15.18",
|
||||
"@types/node": "^22.15.21",
|
||||
"@types/nodemailer": "^6.4.14",
|
||||
"@types/picomatch": "^4.0.0",
|
||||
"@types/pngjs": "^6.0.5",
|
||||
@@ -155,9 +155,9 @@
|
||||
"vitest": "^3.0.0"
|
||||
},
|
||||
"volta": {
|
||||
"node": "22.15.1"
|
||||
"node": "22.16.0"
|
||||
},
|
||||
"overrides": {
|
||||
"sharp": "^0.34.0"
|
||||
"sharp": "^0.34.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ServerController } from 'src/controllers/server.controller';
|
||||
import { ServerService } from 'src/services/server.service';
|
||||
import { SystemMetadataService } from 'src/services/system-metadata.service';
|
||||
import { VersionService } from 'src/services/version.service';
|
||||
import request from 'supertest';
|
||||
import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils';
|
||||
@@ -7,11 +8,13 @@ import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils'
|
||||
describe(ServerController.name, () => {
|
||||
let ctx: ControllerContext;
|
||||
const serverService = mockBaseService(ServerService);
|
||||
const systemMetadataService = mockBaseService(SystemMetadataService);
|
||||
const versionService = mockBaseService(VersionService);
|
||||
|
||||
beforeAll(async () => {
|
||||
ctx = await controllerSetup(ServerController, [
|
||||
{ provide: ServerService, useValue: serverService },
|
||||
{ provide: SystemMetadataService, useValue: systemMetadataService },
|
||||
{ provide: VersionService, useValue: versionService },
|
||||
]);
|
||||
return () => ctx.close();
|
||||
|
||||
@@ -13,8 +13,10 @@ import {
|
||||
ServerVersionHistoryResponseDto,
|
||||
ServerVersionResponseDto,
|
||||
} from 'src/dtos/server.dto';
|
||||
import { VersionCheckStateResponseDto } from 'src/dtos/system-metadata.dto';
|
||||
import { Authenticated } from 'src/middleware/auth.guard';
|
||||
import { ServerService } from 'src/services/server.service';
|
||||
import { SystemMetadataService } from 'src/services/system-metadata.service';
|
||||
import { VersionService } from 'src/services/version.service';
|
||||
|
||||
@ApiTags('Server')
|
||||
@@ -22,6 +24,7 @@ import { VersionService } from 'src/services/version.service';
|
||||
export class ServerController {
|
||||
constructor(
|
||||
private service: ServerService,
|
||||
private systemMetadataService: SystemMetadataService,
|
||||
private versionService: VersionService,
|
||||
) {}
|
||||
|
||||
@@ -96,4 +99,10 @@ export class ServerController {
|
||||
getServerLicense(): Promise<LicenseResponseDto> {
|
||||
return this.service.getLicense();
|
||||
}
|
||||
|
||||
@Get('version-check')
|
||||
@Authenticated()
|
||||
getVersionCheck(): Promise<VersionCheckStateResponseDto> {
|
||||
return this.systemMetadataService.getVersionCheckState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { Body, Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AdminOnboardingUpdateDto, ReverseGeocodingStateResponseDto } from 'src/dtos/system-metadata.dto';
|
||||
import {
|
||||
AdminOnboardingUpdateDto,
|
||||
ReverseGeocodingStateResponseDto,
|
||||
VersionCheckStateResponseDto,
|
||||
} from 'src/dtos/system-metadata.dto';
|
||||
import { Permission } from 'src/enum';
|
||||
import { Authenticated } from 'src/middleware/auth.guard';
|
||||
import { SystemMetadataService } from 'src/services/system-metadata.service';
|
||||
@@ -28,4 +32,10 @@ export class SystemMetadataController {
|
||||
getReverseGeocodingState(): Promise<ReverseGeocodingStateResponseDto> {
|
||||
return this.service.getReverseGeocodingState();
|
||||
}
|
||||
|
||||
@Get('version-check-state')
|
||||
@Authenticated({ permission: Permission.SYSTEM_METADATA_READ, admin: true })
|
||||
getVersionCheckState(): Promise<VersionCheckStateResponseDto> {
|
||||
return this.service.getVersionCheckState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,3 +13,8 @@ export class ReverseGeocodingStateResponseDto {
|
||||
lastUpdate!: string | null;
|
||||
lastImportFileName!: string | null;
|
||||
}
|
||||
|
||||
export class VersionCheckStateResponseDto {
|
||||
checkedAt!: string | null;
|
||||
releaseVersion!: string | null;
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ with
|
||||
"assets"."visibility",
|
||||
"assets"."isFavorite",
|
||||
assets.type = 'IMAGE' as "isImage",
|
||||
assets."deletedAt" is null as "isTrashed",
|
||||
assets."deletedAt" is not null as "isTrashed",
|
||||
"assets"."livePhotoVideoId",
|
||||
"assets"."localDateTime",
|
||||
"assets"."ownerId",
|
||||
|
||||
@@ -15,6 +15,7 @@ select
|
||||
inner join "memories_assets_assets" on "assets"."id" = "memories_assets_assets"."assetsId"
|
||||
where
|
||||
"memories_assets_assets"."memoriesId" = "memories"."id"
|
||||
and "assets"."visibility" = 'timeline'
|
||||
and "assets"."deletedAt" is null
|
||||
order by
|
||||
"assets"."fileCreatedAt" asc
|
||||
@@ -43,6 +44,7 @@ select
|
||||
inner join "memories_assets_assets" on "assets"."id" = "memories_assets_assets"."assetsId"
|
||||
where
|
||||
"memories_assets_assets"."memoriesId" = "memories"."id"
|
||||
and "assets"."visibility" = 'timeline'
|
||||
and "assets"."deletedAt" is null
|
||||
order by
|
||||
"assets"."fileCreatedAt" asc
|
||||
@@ -79,6 +81,7 @@ select
|
||||
inner join "memories_assets_assets" on "assets"."id" = "memories_assets_assets"."assetsId"
|
||||
where
|
||||
"memories_assets_assets"."memoriesId" = "memories"."id"
|
||||
and "assets"."visibility" = 'timeline'
|
||||
and "assets"."deletedAt" is null
|
||||
order by
|
||||
"assets"."fileCreatedAt" asc
|
||||
@@ -111,6 +114,7 @@ select
|
||||
inner join "memories_assets_assets" on "assets"."id" = "memories_assets_assets"."assetsId"
|
||||
where
|
||||
"memories_assets_assets"."memoriesId" = "memories"."id"
|
||||
and "assets"."visibility" = 'timeline'
|
||||
and "assets"."deletedAt" is null
|
||||
order by
|
||||
"assets"."fileCreatedAt" asc
|
||||
|
||||
@@ -595,7 +595,7 @@ export class AssetRepository {
|
||||
'assets.visibility',
|
||||
'assets.isFavorite',
|
||||
sql`assets.type = 'IMAGE'`.as('isImage'),
|
||||
sql`assets."deletedAt" is null`.as('isTrashed'),
|
||||
sql`assets."deletedAt" is not null`.as('isTrashed'),
|
||||
'assets.livePhotoVideoId',
|
||||
'assets.localDateTime',
|
||||
'assets.ownerId',
|
||||
|
||||
@@ -118,7 +118,7 @@ export class DatabaseRepository {
|
||||
this.logger.log(`Creating ${EXTENSION_NAMES[extension]} extension`);
|
||||
await sql`CREATE EXTENSION IF NOT EXISTS ${sql.raw(extension)} CASCADE`.execute(this.db);
|
||||
if (extension === DatabaseExtension.VECTORCHORD) {
|
||||
const dbName = sql.table(await this.getDatabaseName());
|
||||
const dbName = sql.id(await this.getDatabaseName());
|
||||
await sql`ALTER DATABASE ${dbName} SET vchordrq.prewarm_dim = '512,640,768,1024,1152,1536'`.execute(this.db);
|
||||
await sql`SET vchordrq.prewarm_dim = '512,640,768,1024,1152,1536'`.execute(this.db);
|
||||
await sql`ALTER DATABASE ${dbName} SET vchordrq.probes = 1`.execute(this.db);
|
||||
@@ -247,7 +247,10 @@ export class DatabaseRepository {
|
||||
return;
|
||||
}
|
||||
const dimSize = await this.getDimensionSize(table);
|
||||
await sql`DROP INDEX IF EXISTS ${sql.raw(indexName)}`.execute(this.db);
|
||||
await this.db.schema.dropIndex(indexName).ifExists().execute();
|
||||
if (table === 'smart_search') {
|
||||
await this.db.schema.alterTable(table).dropConstraint('dim_size_constraint').ifExists().execute();
|
||||
}
|
||||
await this.db.transaction().execute(async (tx) => {
|
||||
if (!rows.some((row) => row.columnName === 'embedding')) {
|
||||
this.logger.warn(`Column 'embedding' does not exist in table '${table}', truncating and adding column.`);
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Insertable, Kysely, Updateable } from 'kysely';
|
||||
import { Insertable, Kysely, sql, Updateable } from 'kysely';
|
||||
import { jsonArrayFrom } from 'kysely/helpers/postgres';
|
||||
import { DateTime } from 'luxon';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB, Memories } from 'src/db';
|
||||
import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { MemorySearchDto } from 'src/dtos/memory.dto';
|
||||
import { AssetVisibility } from 'src/enum';
|
||||
import { IBulkAsset } from 'src/types';
|
||||
|
||||
@Injectable()
|
||||
export class MemoryRepository implements IBulkAsset {
|
||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||
|
||||
cleanup() {
|
||||
async cleanup() {
|
||||
await this.db
|
||||
.deleteFrom('memories_assets_assets')
|
||||
.using('assets')
|
||||
.whereRef('memories_assets_assets.assetsId', '=', 'assets.id')
|
||||
.where('assets.visibility', '!=', AssetVisibility.TIMELINE)
|
||||
.execute();
|
||||
|
||||
return this.db
|
||||
.deleteFrom('memories')
|
||||
.where('createdAt', '<', DateTime.now().minus({ days: 30 }).toJSDate())
|
||||
@@ -36,6 +44,7 @@ export class MemoryRepository implements IBulkAsset {
|
||||
.innerJoin('memories_assets_assets', 'assets.id', 'memories_assets_assets.assetsId')
|
||||
.whereRef('memories_assets_assets.memoriesId', '=', 'memories.id')
|
||||
.orderBy('assets.fileCreatedAt', 'asc')
|
||||
.where('assets.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
|
||||
.where('assets.deletedAt', 'is', null),
|
||||
).as('assets'),
|
||||
)
|
||||
@@ -138,6 +147,7 @@ export class MemoryRepository implements IBulkAsset {
|
||||
.innerJoin('memories_assets_assets', 'assets.id', 'memories_assets_assets.assetsId')
|
||||
.whereRef('memories_assets_assets.memoriesId', '=', 'memories.id')
|
||||
.orderBy('assets.fileCreatedAt', 'asc')
|
||||
.where('assets.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
|
||||
.where('assets.deletedAt', 'is', null),
|
||||
).as('assets'),
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
AdminOnboardingResponseDto,
|
||||
AdminOnboardingUpdateDto,
|
||||
ReverseGeocodingStateResponseDto,
|
||||
VersionCheckStateResponseDto,
|
||||
} from 'src/dtos/system-metadata.dto';
|
||||
import { SystemMetadataKey } from 'src/enum';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
@@ -24,4 +25,9 @@ export class SystemMetadataService extends BaseService {
|
||||
const value = await this.systemMetadataRepository.get(SystemMetadataKey.REVERSE_GEOCODING_STATE);
|
||||
return { lastUpdate: null, lastImportFileName: null, ...value };
|
||||
}
|
||||
|
||||
async getVersionCheckState(): Promise<VersionCheckStateResponseDto> {
|
||||
const value = await this.systemMetadataRepository.get(SystemMetadataKey.VERSION_CHECK_STATE);
|
||||
return { checkedAt: null, releaseVersion: null, ...value };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
22.15.1
|
||||
22.16.0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:22.15.0-alpine3.20@sha256:686b8892b69879ef5bfd6047589666933508f9a5451c67320df3070ba0e9807b
|
||||
FROM node:22.16.0-alpine3.20@sha256:2289fb1fba0f4633b08ec47b94a89c7e20b829fc5679f9b7b298eaa2f1ed8b7e
|
||||
|
||||
RUN apk add --no-cache tini
|
||||
USER node
|
||||
|
||||
1018
web/package-lock.json
generated
1018
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich-web",
|
||||
"version": "1.133.1",
|
||||
"version": "1.134.0",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
@@ -28,7 +28,7 @@
|
||||
"dependencies": {
|
||||
"@formatjs/icu-messageformat-parser": "^2.9.8",
|
||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||
"@immich/ui": "^0.22.2",
|
||||
"@immich/ui": "^0.22.4",
|
||||
"@mapbox/mapbox-gl-rtl-text": "0.2.3",
|
||||
"@mdi/js": "^7.4.47",
|
||||
"@photo-sphere-viewer/core": "^5.11.5",
|
||||
@@ -80,7 +80,7 @@
|
||||
"dotenv": "^16.4.7",
|
||||
"eslint": "^9.18.0",
|
||||
"eslint-config-prettier": "^10.0.0",
|
||||
"eslint-p": "^0.22.0",
|
||||
"eslint-p": "^0.23.0",
|
||||
"eslint-plugin-svelte": "^3.0.0",
|
||||
"eslint-plugin-unicorn": "^57.0.0",
|
||||
"factory.ts": "^1.4.1",
|
||||
@@ -101,6 +101,6 @@
|
||||
"vitest": "^3.0.0"
|
||||
},
|
||||
"volta": {
|
||||
"node": "22.15.1"
|
||||
"node": "22.16.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
|
||||
const deleteAsset = async () => {
|
||||
try {
|
||||
preAction({ type: AssetAction.DELETE, asset: toTimelineAsset(asset) });
|
||||
await deleteAssets({ assetBulkDeleteDto: { ids: [asset.id], force: true } });
|
||||
onAction({ type: AssetAction.DELETE, asset: toTimelineAsset(asset) });
|
||||
|
||||
|
||||
@@ -279,12 +279,17 @@
|
||||
const data = getFaceCroppedCoordinates();
|
||||
if (!data) {
|
||||
notificationController.show({
|
||||
message: 'Error tagging face - cannot get bounding box coordinates',
|
||||
message: $t('error_tag_face_bounding_box'),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const isConfirmed = await modalManager.showDialog({ prompt: `Do you want to tag this face as ${person.name}?` });
|
||||
const isConfirmed = await modalManager.showDialog({
|
||||
prompt: person.name
|
||||
? $t('confirm_tag_face', { values: { name: person.name } })
|
||||
: $t('confirm_tag_face_unnamed'),
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import ProgressBar from '$lib/components/shared-components/progress-bar/progress-bar.svelte';
|
||||
import SlideshowSettings from '$lib/components/slideshow-settings.svelte';
|
||||
import { ProgressBarStatus } from '$lib/constants';
|
||||
import { modalManager } from '$lib/managers/modal-manager.svelte';
|
||||
import { SlideshowNavigation, slideshowStore } from '$lib/stores/slideshow.store';
|
||||
import { IconButton } from '@immich/ui';
|
||||
import { mdiChevronLeft, mdiChevronRight, mdiClose, mdiCog, mdiFullscreen, mdiPause, mdiPlay } from '@mdi/js';
|
||||
@@ -31,7 +32,6 @@
|
||||
|
||||
let progressBarStatus: ProgressBarStatus | undefined = $state();
|
||||
let progressBar = $state<ReturnType<typeof ProgressBar>>();
|
||||
let showSettings = $state(false);
|
||||
let showControls = $state(true);
|
||||
let timer: NodeJS.Timeout;
|
||||
let isOverControls = $state(false);
|
||||
@@ -99,11 +99,11 @@
|
||||
onNext();
|
||||
};
|
||||
|
||||
const onSettingToggled = async () => {
|
||||
showSettings = !showSettings;
|
||||
if (document.fullscreenElement && showSettings) {
|
||||
const onShowSettings = async () => {
|
||||
if (document.fullscreenElement) {
|
||||
await document.exitFullscreen();
|
||||
}
|
||||
await modalManager.show(SlideshowSettings, {});
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
shape="round"
|
||||
color="secondary"
|
||||
icon={mdiCog}
|
||||
onclick={onSettingToggled}
|
||||
onclick={onShowSettings}
|
||||
aria-label={$t('slideshow_settings')}
|
||||
class="text-white"
|
||||
/>
|
||||
@@ -185,9 +185,6 @@
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{#if showSettings}
|
||||
<SlideshowSettings onClose={() => (showSettings = false)} />
|
||||
{/if}
|
||||
|
||||
<ProgressBar
|
||||
autoplay
|
||||
|
||||
@@ -104,8 +104,10 @@
|
||||
|
||||
const handleClick = (e: MouseEvent) => {
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
window.open(currentUrlReplaceAssetId(asset.id), '_blank');
|
||||
return;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
callClickHandlers();
|
||||
@@ -249,19 +251,6 @@
|
||||
>
|
||||
<!-- icon overlay -->
|
||||
<div>
|
||||
{#if !usingMobileDevice && mouseOver && !disableLinkMouseOver}
|
||||
<!-- lazy show the url on mouse over-->
|
||||
<a
|
||||
class="absolute w-full top-0 bottom-0"
|
||||
style:cursor="unset"
|
||||
href={currentUrlReplaceAssetId(asset.id)}
|
||||
onclick={(evt) => evt.preventDefault()}
|
||||
tabindex={-1}
|
||||
aria-label="Thumbnail URL"
|
||||
>
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
<!-- Gradient overlay on hover -->
|
||||
{#if !usingMobileDevice && !disabled}
|
||||
<div
|
||||
@@ -320,6 +309,20 @@
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- lazy show the url on mouse over-->
|
||||
{#if !usingMobileDevice && mouseOver && !disableLinkMouseOver}
|
||||
<a
|
||||
class="absolute w-full top-0 bottom-0"
|
||||
style:cursor="unset"
|
||||
href={currentUrlReplaceAssetId(asset.id)}
|
||||
onclick={(evt) => evt.preventDefault()}
|
||||
tabindex={-1}
|
||||
aria-label="Thumbnail URL"
|
||||
>
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
<ImageThumbnail
|
||||
class={imageClass}
|
||||
{brokenAssetClass}
|
||||
@@ -336,7 +339,7 @@
|
||||
url={getAssetPlaybackUrl({ id: asset.id, cacheKey: asset.thumbhash })}
|
||||
enablePlayback={mouseOver && $playVideoThumbnailOnHover}
|
||||
curve={selected}
|
||||
durationInSeconds={timeToSeconds(asset.duration!)}
|
||||
durationInSeconds={asset.duration ? timeToSeconds(asset.duration) : 0}
|
||||
playbackOnIconHover={!$playVideoThumbnailOnHover}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -55,35 +55,6 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="absolute end-0 top-0 z-1 flex place-items-center gap-1 text-xs font-medium text-white">
|
||||
{#if showTime}
|
||||
<span class="pt-2">
|
||||
{#if remainingSeconds < 60}
|
||||
{Duration.fromObject({ seconds: remainingSeconds }).toFormat('m:ss')}
|
||||
{:else if remainingSeconds < 3600}
|
||||
{Duration.fromObject({ seconds: remainingSeconds }).toFormat('mm:ss')}
|
||||
{:else}
|
||||
{Duration.fromObject({ seconds: remainingSeconds }).toFormat('h:mm:ss')}
|
||||
{/if}
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<span class="pe-2 pt-2" onmouseenter={onMouseEnter} onmouseleave={onMouseLeave}>
|
||||
{#if enablePlayback}
|
||||
{#if loading}
|
||||
<LoadingSpinner />
|
||||
{:else if error}
|
||||
<Icon path={mdiAlertCircleOutline} size="24" class="text-red-600" />
|
||||
{:else}
|
||||
<Icon path={pauseIcon} size="24" />
|
||||
{/if}
|
||||
{:else}
|
||||
<Icon path={playIcon} size="24" />
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{#if enablePlayback}
|
||||
<video
|
||||
bind:this={player}
|
||||
@@ -114,3 +85,32 @@
|
||||
}}
|
||||
></video>
|
||||
{/if}
|
||||
|
||||
<div class="absolute end-0 top-0 flex place-items-center gap-1 text-xs font-medium text-white">
|
||||
{#if showTime}
|
||||
<span class="pt-2">
|
||||
{#if remainingSeconds < 60}
|
||||
{Duration.fromObject({ seconds: remainingSeconds }).toFormat('m:ss')}
|
||||
{:else if remainingSeconds < 3600}
|
||||
{Duration.fromObject({ seconds: remainingSeconds }).toFormat('mm:ss')}
|
||||
{:else}
|
||||
{Duration.fromObject({ seconds: remainingSeconds }).toFormat('h:mm:ss')}
|
||||
{/if}
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<span class="pe-2 pt-2" onmouseenter={onMouseEnter} onmouseleave={onMouseLeave}>
|
||||
{#if enablePlayback}
|
||||
{#if loading}
|
||||
<LoadingSpinner />
|
||||
{:else if error}
|
||||
<Icon path={mdiAlertCircleOutline} size="24" class="text-red-600" />
|
||||
{:else}
|
||||
<Icon path={pauseIcon} size="24" />
|
||||
{/if}
|
||||
{:else}
|
||||
<Icon path={playIcon} size="24" />
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -47,7 +47,10 @@
|
||||
{#if canScrollLeft || canScrollRight}
|
||||
<div class="sticky start-0 z-1">
|
||||
{#if canScrollLeft}
|
||||
<div class="absolute start-4 top-24" transition:fade={{ duration: 200 }}>
|
||||
<div
|
||||
class="absolute start-4 max-md:top-[75px] top-[108px] -translate-y-1/2"
|
||||
transition:fade={{ duration: 200 }}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-full border border-gray-500 bg-gray-100 p-2 text-gray-500 opacity-50 hover:opacity-100"
|
||||
@@ -60,7 +63,10 @@
|
||||
</div>
|
||||
{/if}
|
||||
{#if canScrollRight}
|
||||
<div class="absolute end-4 top-24 z-1" transition:fade={{ duration: 200 }}>
|
||||
<div
|
||||
class="absolute end-4 max-md:top-[75px] top-[108px] -translate-y-1/2 z-1"
|
||||
transition:fade={{ duration: 200 }}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-full border border-gray-500 bg-gray-100 p-2 text-gray-500 opacity-50 hover:opacity-100"
|
||||
@@ -77,7 +83,7 @@
|
||||
<div class="inline-block" use:resizeObserver={({ width }) => (innerWidth = width)}>
|
||||
{#each memoryStore.memories as memory (memory.id)}
|
||||
<a
|
||||
class="memory-card relative me-2 md:me-4 last:me-0 inline-block aspect-3/4 md:aspect-4/3 max-md:h-[150px] xl:aspect-video h-[215px] rounded-xl"
|
||||
class="memory-card relative me-2 md:me-4 last:me-0 inline-block aspect-3/4 md:aspect-4/3 max-md:h-[150px] xl:aspect-video h-[216px] rounded-xl"
|
||||
href="{AppRoute.MEMORY}?{QueryParameter.ID}={memory.assets[0].id}"
|
||||
>
|
||||
<img
|
||||
|
||||
@@ -6,9 +6,13 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { modalManager } from '$lib/managers/modal-manager.svelte';
|
||||
import AvatarEditModal from '$lib/modals/AvatarEditModal.svelte';
|
||||
import HelpAndFeedbackModal from '$lib/modals/HelpAndFeedbackModal.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { userInteraction } from '$lib/stores/user.svelte';
|
||||
import { getAboutInfo, type ServerAboutResponseDto } from '@immich/sdk';
|
||||
import { Button } from '@immich/ui';
|
||||
import { mdiCog, mdiLogout, mdiPencil, mdiWrench } from '@mdi/js';
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { fade } from 'svelte/transition';
|
||||
import UserAvatar from '../user-avatar.svelte';
|
||||
@@ -19,6 +23,12 @@
|
||||
}
|
||||
|
||||
let { onLogout, onClose = () => {} }: Props = $props();
|
||||
|
||||
let info: ServerAboutResponseDto | undefined = $state();
|
||||
|
||||
onMount(async () => {
|
||||
info = userInteraction.aboutInfo ?? (await getAboutInfo());
|
||||
});
|
||||
</script>
|
||||
|
||||
<div
|
||||
@@ -29,7 +39,7 @@
|
||||
use:focusTrap
|
||||
>
|
||||
<div
|
||||
class="mx-4 mt-4 flex flex-col items-center justify-center gap-4 rounded-3xl bg-white p-4 dark:bg-immich-dark-primary/10"
|
||||
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" />
|
||||
@@ -91,13 +101,25 @@
|
||||
</div>
|
||||
|
||||
<div class="mb-4 flex flex-col">
|
||||
<Button
|
||||
class="m-1 mx-4 rounded-none rounded-b-3xl bg-white p-3 dark:bg-immich-dark-primary/10"
|
||||
onclick={onLogout}
|
||||
leadingIcon={mdiLogout}
|
||||
variant="ghost"
|
||||
color="secondary">{$t('sign_out')}</Button
|
||||
>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-full place-content-center place-items-center gap-2 py-3 font-medium text-gray-500 hover:bg-immich-primary/10 dark:text-gray-300"
|
||||
onclick={onLogout}
|
||||
>
|
||||
<Icon path={mdiLogout} size={24} />
|
||||
{$t('sign_out')}</button
|
||||
class="text-center mt-4 underline text-xs text-immich-primary dark:text-immich-dark-primary"
|
||||
onclick={async () => {
|
||||
onClose();
|
||||
if (info) {
|
||||
await modalManager.show(HelpAndFeedbackModal, { info });
|
||||
}
|
||||
}}
|
||||
>
|
||||
{$t('support_and_feedback')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,18 +12,13 @@
|
||||
import SearchBar from '$lib/components/shared-components/search-bar/search-bar.svelte';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { modalManager } from '$lib/managers/modal-manager.svelte';
|
||||
import HelpAndFeedbackModal from '$lib/modals/HelpAndFeedbackModal.svelte';
|
||||
import { mobileDevice } from '$lib/stores/mobile-device.svelte';
|
||||
import { notificationManager } from '$lib/stores/notification-manager.svelte';
|
||||
import { featureFlags } from '$lib/stores/server-config.store';
|
||||
import { sidebarStore } from '$lib/stores/sidebar.svelte';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { userInteraction } from '$lib/stores/user.svelte';
|
||||
import { getAboutInfo, type ServerAboutResponseDto } from '@immich/sdk';
|
||||
import { Button, IconButton } from '@immich/ui';
|
||||
import { mdiBellBadge, mdiBellOutline, mdiHelpCircleOutline, mdiMagnify, mdiMenu, mdiTrayArrowUp } from '@mdi/js';
|
||||
import { onMount } from 'svelte';
|
||||
import { mdiBellBadge, mdiBellOutline, mdiMagnify, mdiMenu, mdiTrayArrowUp } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
import ThemeButton from '../theme-button.svelte';
|
||||
import UserAvatar from '../user-avatar.svelte';
|
||||
@@ -42,17 +37,11 @@
|
||||
let shouldShowNotificationPanel = $state(false);
|
||||
let innerWidth: number = $state(0);
|
||||
const hasUnreadNotifications = $derived(notificationManager.notifications.length > 0);
|
||||
|
||||
let info: ServerAboutResponseDto | undefined = $state();
|
||||
|
||||
onMount(async () => {
|
||||
info = userInteraction.aboutInfo ?? (await getAboutInfo());
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:window bind:innerWidth />
|
||||
|
||||
<nav id="dashboard-navbar" class="max-md:h-(--navbar-height-md) h-(--navbar-height) w-dvw text-sm overflow-hidden">
|
||||
<nav id="dashboard-navbar" class="max-md:h-(--navbar-height-md) h-(--navbar-height) w-dvw text-sm">
|
||||
<SkipLink text={$t('skip_to_content')} />
|
||||
<div
|
||||
class="grid h-full grid-cols-[--spacing(32)_auto] items-center py-2 sidebar:grid-cols-[--spacing(64)_auto] {noBorder
|
||||
@@ -130,18 +119,6 @@
|
||||
|
||||
<ThemeButton padding="2" />
|
||||
|
||||
<div>
|
||||
<IconButton
|
||||
shape="round"
|
||||
color="secondary"
|
||||
variant="ghost"
|
||||
size="medium"
|
||||
icon={mdiHelpCircleOutline}
|
||||
onclick={() => info && modalManager.show(HelpAndFeedbackModal, { info })}
|
||||
aria-label={$t('support_and_feedback')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
use:clickOutside={{
|
||||
onOutclick: () => (shouldShowNotificationPanel = false),
|
||||
|
||||
@@ -214,7 +214,7 @@
|
||||
]}
|
||||
/>
|
||||
|
||||
<div class="w-full relative" use:focusOutside={{ onFocusOut }} tabindex="-1">
|
||||
<div class="w-full relative z-auto" use:focusOutside={{ onFocusOut }} tabindex="-1">
|
||||
<form
|
||||
draggable="false"
|
||||
autocomplete="off"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { searchStore } from '$lib/stores/search.svelte';
|
||||
import { mdiMagnify, mdiClose } from '@mdi/js';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { mdiClose, mdiMagnify } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import { fly } from 'svelte/transition';
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
@@ -95,7 +95,7 @@
|
||||
{#if isOpen && isSearchSuggestions}
|
||||
<div
|
||||
transition:fly={{ y: 25, duration: 150 }}
|
||||
class="absolute w-full rounded-b-3xl border-2 border-t-0 border-gray-200 bg-white pb-5 shadow-2xl transition-all dark:border-gray-700 dark:bg-immich-dark-gray dark:text-gray-300"
|
||||
class="absolute w-full rounded-b-3xl border-2 border-t-0 border-gray-200 bg-white pb-5 shadow-2xl transition-all dark:border-gray-700 dark:bg-immich-dark-gray dark:text-gray-300 z-1"
|
||||
>
|
||||
<div class="flex items-center justify-between px-5 pt-5 text-xs">
|
||||
<p class="py-2" aria-hidden={true}>{$t('recent_searches').toUpperCase()}</p>
|
||||
|
||||
@@ -60,9 +60,7 @@
|
||||
{disabled}
|
||||
onCheckedChange={() => handleCheckboxChange(option.value)}
|
||||
/>
|
||||
<Label label={option.text} for="{option.value}-checkbox">
|
||||
{option.text}
|
||||
</Label>
|
||||
<Label label={option.text} for="{option.value}-checkbox" />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -21,6 +21,7 @@ import { navigate } from '$lib/utils/navigation';
|
||||
import {
|
||||
addAssetsToAlbum as addAssets,
|
||||
AssetVisibility,
|
||||
bulkTagAssets,
|
||||
createStack,
|
||||
deleteAssets,
|
||||
deleteStacks,
|
||||
@@ -28,7 +29,6 @@ import {
|
||||
getBaseUrl,
|
||||
getDownloadInfo,
|
||||
getStack,
|
||||
tagAssets as tagAllAssets,
|
||||
untagAssets,
|
||||
updateAsset,
|
||||
updateAssets,
|
||||
@@ -83,9 +83,7 @@ export const tagAssets = async ({
|
||||
tagIds: string[];
|
||||
showNotification?: boolean;
|
||||
}) => {
|
||||
for (const tagId of tagIds) {
|
||||
await tagAllAssets({ id: tagId, bulkIdsDto: { ids: assetIds } });
|
||||
}
|
||||
await bulkTagAssets({ tagBulkAssetsDto: { tagIds, assetIds } });
|
||||
|
||||
if (showNotification) {
|
||||
const $t = await getFormatter();
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
import { modalManager } from '$lib/managers/modal-manager.svelte';
|
||||
import UserCreateModal from '$lib/modals/UserCreateModal.svelte';
|
||||
import UserDeleteConfirmModal from '$lib/modals/UserDeleteConfirmModal.svelte';
|
||||
import UserEditModal from '$lib/modals/UserEditModal.svelte';
|
||||
import UserRestoreConfirmModal from '$lib/modals/UserRestoreConfirmModal.svelte';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { serverConfig } from '$lib/stores/server-config.store';
|
||||
@@ -18,8 +17,8 @@
|
||||
import { websocketEvents } from '$lib/stores/websocket';
|
||||
import { getByteUnitString } from '$lib/utils/byte-units';
|
||||
import { UserStatus, searchUsersAdmin, type UserAdminResponseDto } from '@immich/sdk';
|
||||
import { Button, HStack, IconButton, Link, Text } from '@immich/ui';
|
||||
import { mdiDeleteRestore, mdiInfinity, mdiPencilOutline, mdiPlusBoxOutline, mdiTrashCanOutline } from '@mdi/js';
|
||||
import { Button, HStack, IconButton, Text } from '@immich/ui';
|
||||
import { mdiDeleteRestore, mdiEyeOutline, mdiInfinity, mdiPlusBoxOutline, mdiTrashCanOutline } from '@mdi/js';
|
||||
import { DateTime } from 'luxon';
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
@@ -63,13 +62,6 @@
|
||||
await refresh();
|
||||
};
|
||||
|
||||
const handleEdit = async (dto: UserAdminResponseDto) => {
|
||||
const result = await modalManager.show(UserEditModal, { user: dto });
|
||||
if (result) {
|
||||
await refresh();
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = async (user: UserAdminResponseDto) => {
|
||||
const result = await modalManager.show(UserDeleteConfirmModal, { user });
|
||||
if (result) {
|
||||
@@ -116,9 +108,9 @@
|
||||
? 'bg-red-300 dark:bg-red-900'
|
||||
: 'even:bg-subtle/20 odd:bg-subtle/80'}"
|
||||
>
|
||||
<td class="w-8/12 sm:w-5/12 lg:w-6/12 xl:w-4/12 2xl:w-5/12 text-ellipsis break-all px-2 text-sm"
|
||||
><Link href="{AppRoute.ADMIN_USERS}/{immichUser.id}">{immichUser.email}</Link></td
|
||||
>
|
||||
<td class="w-8/12 sm:w-5/12 lg:w-6/12 xl:w-4/12 2xl:w-5/12 text-ellipsis break-all px-2 text-sm">
|
||||
{immichUser.email}
|
||||
</td>
|
||||
<td class="hidden sm:block w-3/12 text-ellipsis break-all px-2 text-sm">{immichUser.name}</td>
|
||||
<td class="hidden xl:block w-3/12 2xl:w-2/12 text-ellipsis break-all px-2 text-sm">
|
||||
<div class="container mx-auto flex flex-wrap justify-center">
|
||||
@@ -136,10 +128,10 @@
|
||||
<IconButton
|
||||
shape="round"
|
||||
size="medium"
|
||||
icon={mdiPencilOutline}
|
||||
title={$t('edit_user')}
|
||||
onclick={() => handleEdit(immichUser)}
|
||||
aria-label={$t('edit_user')}
|
||||
icon={mdiEyeOutline}
|
||||
title={$t('view_user')}
|
||||
href={`${AppRoute.ADMIN_USERS}/${immichUser.id}`}
|
||||
aria-label={$t('view_user')}
|
||||
/>
|
||||
{#if immichUser.id !== $user.id}
|
||||
<IconButton
|
||||
|
||||
Reference in New Issue
Block a user