Compare commits
7 Commits
29
...
feature/Ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f19cf206ba | ||
|
|
7ac30995a8 | ||
|
|
fe2ddc3644 | ||
|
|
ec0eb93036 | ||
|
|
d9a41b8ea0 | ||
|
|
f30fac971a | ||
|
|
fe26ccd1b7 |
@@ -1,10 +1,10 @@
|
|||||||
ARG BASEIMAGE=mcr.microsoft.com/devcontainers/typescript-node:22@sha256:b0b88ef6a5abf21194343d2c5b2829dddd9be1142f65f6a5e4390a51d5a70dd8
|
ARG BASEIMAGE=mcr.microsoft.com/devcontainers/typescript-node:22@sha256:9791f4aa527774bc370c6bd2f6705ce5a686f1e6f204badd8dfaacce28c631ae
|
||||||
FROM ${BASEIMAGE}
|
FROM ${BASEIMAGE}
|
||||||
|
|
||||||
# Flutter SDK
|
# Flutter SDK
|
||||||
# https://flutter.dev/docs/development/tools/sdk/releases?tab=linux
|
# https://flutter.dev/docs/development/tools/sdk/releases?tab=linux
|
||||||
ENV FLUTTER_CHANNEL="stable"
|
ENV FLUTTER_CHANNEL="stable"
|
||||||
ENV FLUTTER_VERSION="3.29.1"
|
ENV FLUTTER_VERSION="3.24.5"
|
||||||
ENV FLUTTER_HOME=/flutter
|
ENV FLUTTER_HOME=/flutter
|
||||||
ENV PATH=${PATH}:${FLUTTER_HOME}/bin
|
ENV PATH=${PATH}:${FLUTTER_HOME}/bin
|
||||||
|
|
||||||
|
|||||||
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -6,9 +6,6 @@ mobile/openapi/**/*.dart linguist-generated=true
|
|||||||
mobile/lib/**/*.g.dart -diff -merge
|
mobile/lib/**/*.g.dart -diff -merge
|
||||||
mobile/lib/**/*.g.dart linguist-generated=true
|
mobile/lib/**/*.g.dart linguist-generated=true
|
||||||
|
|
||||||
mobile/lib/**/*.drift.dart -diff -merge
|
|
||||||
mobile/lib/**/*.drift.dart linguist-generated=true
|
|
||||||
|
|
||||||
open-api/typescript-sdk/fetch-client.ts -diff -merge
|
open-api/typescript-sdk/fetch-client.ts -diff -merge
|
||||||
open-api/typescript-sdk/fetch-client.ts linguist-generated=true
|
open-api/typescript-sdk/fetch-client.ts linguist-generated=true
|
||||||
|
|
||||||
|
|||||||
1
.github/.nvmrc
vendored
1
.github/.nvmrc
vendored
@@ -1 +0,0 @@
|
|||||||
22.14.0
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
title: '[Feature] feature-name-goes-here'
|
title: "[Feature] feature-name-goes-here"
|
||||||
labels: ['feature']
|
labels: ["feature"]
|
||||||
|
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
@@ -13,7 +13,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: I have searched the existing feature requests, both open and closed, to make sure this is not a duplicate request.
|
label: I have searched the existing feature requests, both open and closed, to make sure this is not a duplicate request.
|
||||||
options:
|
options:
|
||||||
- label: 'Yes'
|
- label: "Yes"
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
|
|||||||
7
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
7
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -5,7 +5,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: I have searched the existing issues, both open and closed, to make sure this is not a duplicate report.
|
label: I have searched the existing issues, both open and closed, to make sure this is not a duplicate report.
|
||||||
options:
|
options:
|
||||||
- label: 'Yes'
|
- label: "Yes"
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
- type: markdown
|
- type: markdown
|
||||||
@@ -84,7 +84,7 @@ body:
|
|||||||
id: repro
|
id: repro
|
||||||
attributes:
|
attributes:
|
||||||
label: Reproduction steps
|
label: Reproduction steps
|
||||||
description: 'How do you trigger this bug? Please walk us through it step by step.'
|
description: "How do you trigger this bug? Please walk us through it step by step."
|
||||||
value: |
|
value: |
|
||||||
1.
|
1.
|
||||||
2.
|
2.
|
||||||
@@ -97,8 +97,7 @@ body:
|
|||||||
id: logs
|
id: logs
|
||||||
attributes:
|
attributes:
|
||||||
label: Relevant log output
|
label: Relevant log output
|
||||||
description:
|
description: Please copy and paste any relevant logs below. (code formatting is
|
||||||
Please copy and paste any relevant logs below. (code formatting is
|
|
||||||
enabled, no need for backticks)
|
enabled, no need for backticks)
|
||||||
render: shell
|
render: shell
|
||||||
validations:
|
validations:
|
||||||
|
|||||||
28
.github/package-lock.json
generated
vendored
28
.github/package-lock.json
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"name": ".github",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"devDependencies": {
|
|
||||||
"prettier": "^3.5.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/prettier": {
|
|
||||||
"version": "3.5.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
|
|
||||||
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"bin": {
|
|
||||||
"prettier": "bin/prettier.cjs"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
9
.github/package.json
vendored
9
.github/package.json
vendored
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"scripts": {
|
|
||||||
"format": "prettier --check .",
|
|
||||||
"format:fix": "prettier --write ."
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"prettier": "^3.5.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
4
.github/pull_request_template.md
vendored
4
.github/pull_request_template.md
vendored
@@ -32,5 +32,5 @@ The `/api/something` endpoint is now `/api/something-else`
|
|||||||
- [ ] I have confirmed that any new dependencies are strictly necessary.
|
- [ ] I have confirmed that any new dependencies are strictly necessary.
|
||||||
- [ ] I have written tests for new code (if applicable)
|
- [ ] I have written tests for new code (if applicable)
|
||||||
- [ ] I have followed naming conventions/patterns in the surrounding code
|
- [ ] I have followed naming conventions/patterns in the surrounding code
|
||||||
- [ ] All code in `src/services/` uses repositories implementations for database calls, filesystem operations, etc.
|
- [ ] All code in `src/services` uses repositories implementations for database calls, filesystem operations, etc.
|
||||||
- [ ] All code in `src/repositories/` is pretty basic/simple and does not have any immich specific logic (that belongs in `src/services/`)
|
- [ ] All code in `src/repositories/` is pretty basic/simple and does not have any immich specific logic (that belongs in `src/services`)
|
||||||
|
|||||||
12
.github/workflows/build-mobile.yml
vendored
12
.github/workflows/build-mobile.yml
vendored
@@ -22,9 +22,9 @@ jobs:
|
|||||||
should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
- id: found_paths
|
- id: found_paths
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
uses: dorny/paths-filter@v3
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
mobile:
|
mobile:
|
||||||
@@ -51,18 +51,18 @@ jobs:
|
|||||||
ref="${input_ref:-$github_ref}"
|
ref="${input_ref:-$github_ref}"
|
||||||
echo "ref=$ref" >> $GITHUB_OUTPUT
|
echo "ref=$ref" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{ steps.get-ref.outputs.ref }}
|
ref: ${{ steps.get-ref.outputs.ref }}
|
||||||
|
|
||||||
- uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4
|
- uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
java-version: '17'
|
java-version: '17'
|
||||||
cache: 'gradle'
|
cache: 'gradle'
|
||||||
|
|
||||||
- name: Setup Flutter SDK
|
- name: Setup Flutter SDK
|
||||||
uses: subosito/flutter-action@e938fdf56512cc96ef2f93601a5a40bde3801046 # v2
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
flutter-version-file: ./mobile/pubspec.yaml
|
flutter-version-file: ./mobile/pubspec.yaml
|
||||||
@@ -89,7 +89,7 @@ jobs:
|
|||||||
flutter build apk --release --split-per-abi --target-platform android-arm,android-arm64,android-x64
|
flutter build apk --release --split-per-abi --target-platform android-arm,android-arm64,android-x64
|
||||||
|
|
||||||
- name: Publish Android Artifact
|
- name: Publish Android Artifact
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-apk-signed
|
name: release-apk-signed
|
||||||
path: mobile/build/app/outputs/flutter-apk/*.apk
|
path: mobile/build/app/outputs/flutter-apk/*.apk
|
||||||
|
|||||||
2
.github/workflows/cache-cleanup.yml
vendored
2
.github/workflows/cache-cleanup.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Cleanup
|
- name: Cleanup
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
17
.github/workflows/cli.yml
vendored
17
.github/workflows/cli.yml
vendored
@@ -6,6 +6,7 @@ on:
|
|||||||
- 'cli/**'
|
- 'cli/**'
|
||||||
- '.github/workflows/cli.yml'
|
- '.github/workflows/cli.yml'
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
paths:
|
paths:
|
||||||
- 'cli/**'
|
- 'cli/**'
|
||||||
- '.github/workflows/cli.yml'
|
- '.github/workflows/cli.yml'
|
||||||
@@ -28,9 +29,9 @@ jobs:
|
|||||||
working-directory: ./cli
|
working-directory: ./cli
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
- uses: actions/checkout@v4
|
||||||
# Setup .npmrc file to publish to npm
|
# Setup .npmrc file to publish to npm
|
||||||
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './cli/.nvmrc'
|
node-version-file: './cli/.nvmrc'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
@@ -52,16 +53,16 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
|
uses: docker/setup-qemu-action@v3.5.0
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
|
uses: docker/setup-buildx-action@v3.10.0
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
uses: docker/login-action@v3
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
@@ -76,7 +77,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Generate docker image tags
|
- name: Generate docker image tags
|
||||||
id: metadata
|
id: metadata
|
||||||
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
flavor: |
|
flavor: |
|
||||||
latest=false
|
latest=false
|
||||||
@@ -87,7 +88,7 @@ jobs:
|
|||||||
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
|
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
|
||||||
|
|
||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
|
uses: docker/build-push-action@v6.15.0
|
||||||
with:
|
with:
|
||||||
file: cli/Dockerfile
|
file: cli/Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|||||||
63
.github/workflows/codeql-analysis.yml
vendored
63
.github/workflows/codeql-analysis.yml
vendored
@@ -9,14 +9,14 @@
|
|||||||
# the `language` matrix defined below to confirm you have the correct set of
|
# the `language` matrix defined below to confirm you have the correct set of
|
||||||
# supported CodeQL languages.
|
# supported CodeQL languages.
|
||||||
#
|
#
|
||||||
name: 'CodeQL'
|
name: "CodeQL"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ['main']
|
branches: [ "main" ]
|
||||||
pull_request:
|
pull_request:
|
||||||
# The branches below must be a subset of the branches above
|
# The branches below must be a subset of the branches above
|
||||||
branches: ['main']
|
branches: [ "main" ]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '20 13 * * 1'
|
- cron: '20 13 * * 1'
|
||||||
|
|
||||||
@@ -36,42 +36,43 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
language: ['javascript', 'python']
|
language: [ 'javascript', 'python' ]
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@45775bd8235c68ba998cffa5171334d58593da47 # v3
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
# By default, queries listed here will override any specified in a config file.
|
# By default, queries listed here will override any specified in a config file.
|
||||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
|
||||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||||
# queries: security-extended,security-and-quality
|
# queries: security-extended,security-and-quality
|
||||||
|
|
||||||
# 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@45775bd8235c68ba998cffa5171334d58593da47 # v3
|
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v3
|
||||||
|
|
||||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
|
|
||||||
# - run: |
|
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||||
# echo "Run, Build Application using script"
|
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||||
# ./location_of_script_within_repo/buildscript.sh
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
# - run: |
|
||||||
uses: github/codeql-action/analyze@45775bd8235c68ba998cffa5171334d58593da47 # v3
|
# echo "Run, Build Application using script"
|
||||||
with:
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
category: '/language:${{matrix.language}}'
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v3
|
||||||
|
with:
|
||||||
|
category: "/language:${{matrix.language}}"
|
||||||
|
|||||||
91
.github/workflows/docker.yml
vendored
91
.github/workflows/docker.yml
vendored
@@ -23,9 +23,9 @@ jobs:
|
|||||||
should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
- id: found_paths
|
- id: found_paths
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
uses: dorny/paths-filter@v3
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
server:
|
server:
|
||||||
@@ -49,10 +49,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn', '-rknn']
|
suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn']
|
||||||
steps:
|
steps:
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
@@ -77,7 +77,7 @@ jobs:
|
|||||||
suffix: ['']
|
suffix: ['']
|
||||||
steps:
|
steps:
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
@@ -120,26 +120,21 @@ jobs:
|
|||||||
device: cuda
|
device: cuda
|
||||||
suffix: -cuda
|
suffix: -cuda
|
||||||
|
|
||||||
- platform: linux/amd64
|
|
||||||
runner: mich
|
|
||||||
device: rocm
|
|
||||||
suffix: -rocm
|
|
||||||
|
|
||||||
- platform: linux/amd64
|
- platform: linux/amd64
|
||||||
runner: ubuntu-latest
|
runner: ubuntu-latest
|
||||||
device: openvino
|
device: openvino
|
||||||
suffix: -openvino
|
suffix: -openvino
|
||||||
|
|
||||||
|
- platforms: linux/amd64
|
||||||
|
runner: mich
|
||||||
|
device: rocm
|
||||||
|
suffix: -rocm
|
||||||
|
|
||||||
- platform: linux/arm64
|
- platform: linux/arm64
|
||||||
runner: ubuntu-24.04-arm
|
runner: ubuntu-24.04-arm
|
||||||
device: armnn
|
device: armnn
|
||||||
suffix: -armnn
|
suffix: -armnn
|
||||||
|
|
||||||
- platform: linux/arm64
|
|
||||||
runner: ubuntu-24.04-arm
|
|
||||||
device: rknn
|
|
||||||
suffix: -rknn
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Prepare
|
- name: Prepare
|
||||||
run: |
|
run: |
|
||||||
@@ -147,13 +142,13 @@ jobs:
|
|||||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
|
uses: docker/setup-buildx-action@v3.10.0
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
uses: docker/login-action@v3
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
@@ -180,7 +175,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
id: build
|
id: build
|
||||||
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
|
uses: docker/build-push-action@v6.15.0
|
||||||
with:
|
with:
|
||||||
context: ${{ env.context }}
|
context: ${{ env.context }}
|
||||||
file: ${{ env.file }}
|
file: ${{ env.file }}
|
||||||
@@ -205,7 +200,7 @@ jobs:
|
|||||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||||
|
|
||||||
- name: Upload digest
|
- name: Upload digest
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ml-digests-${{ matrix.device }}-${{ env.PLATFORM_PAIR }}
|
name: ml-digests-${{ matrix.device }}-${{ env.PLATFORM_PAIR }}
|
||||||
path: ${{ runner.temp }}/digests/*
|
path: ${{ runner.temp }}/digests/*
|
||||||
@@ -225,19 +220,15 @@ jobs:
|
|||||||
- device: cpu
|
- device: cpu
|
||||||
- device: cuda
|
- device: cuda
|
||||||
suffix: -cuda
|
suffix: -cuda
|
||||||
- device: rocm
|
|
||||||
suffix: -rocm
|
|
||||||
- device: openvino
|
- device: openvino
|
||||||
suffix: -openvino
|
suffix: -openvino
|
||||||
- device: armnn
|
- device: armnn
|
||||||
suffix: -armnn
|
suffix: -armnn
|
||||||
- device: rknn
|
|
||||||
suffix: -rknn
|
|
||||||
needs:
|
needs:
|
||||||
- build_and_push_ml
|
- build_and_push_ml
|
||||||
steps:
|
steps:
|
||||||
- name: Download digests
|
- name: Download digests
|
||||||
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: ${{ runner.temp }}/digests
|
path: ${{ runner.temp }}/digests
|
||||||
pattern: ml-digests-${{ matrix.device }}-*
|
pattern: ml-digests-${{ matrix.device }}-*
|
||||||
@@ -245,44 +236,43 @@ jobs:
|
|||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
if: ${{ github.event_name == 'release' }}
|
if: ${{ github.event_name == 'release' }}
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Login to GHCR
|
- name: Login to GHCR
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Generate docker image tags
|
- name: Generate docker image tags
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5
|
uses: docker/metadata-action@v5
|
||||||
env:
|
env:
|
||||||
DOCKER_METADATA_PR_HEAD_SHA: 'true'
|
DOCKER_METADATA_PR_HEAD_SHA: 'true'
|
||||||
with:
|
with:
|
||||||
flavor: |
|
flavor: |
|
||||||
# Disable latest tag
|
# Disable latest tag
|
||||||
latest=false
|
latest=false
|
||||||
suffix=${{ matrix.suffix }}
|
|
||||||
images: |
|
images: |
|
||||||
name=${{ env.GHCR_REPO }}
|
name=${{ env.GHCR_REPO }}
|
||||||
name=${{ env.DOCKER_REPO }},enable=${{ github.event_name == 'release' }}
|
name=${{ env.DOCKER_REPO }},enable=${{ github.event_name == 'release' }}
|
||||||
tags: |
|
tags: |
|
||||||
# Tag with branch name
|
# Tag with branch name
|
||||||
type=ref,event=branch
|
type=ref,event=branch,suffix=${{ matrix.suffix }}
|
||||||
# Tag with pr-number
|
# Tag with pr-number
|
||||||
type=ref,event=pr
|
type=ref,event=pr,suffix=${{ matrix.suffix }}
|
||||||
# Tag with long commit sha hash
|
# Tag with long commit sha hash
|
||||||
type=sha,format=long,prefix=commit-
|
type=sha,format=long,prefix=commit-,suffix=${{ matrix.suffix }}
|
||||||
# Tag with git tag on release
|
# Tag with git tag on release
|
||||||
type=ref,event=tag
|
type=ref,event=tag,suffix=${{ matrix.suffix }}
|
||||||
type=raw,value=release,enable=${{ github.event_name == 'release' }}
|
type=raw,value=release,enable=${{ github.event_name == 'release' }},suffix=${{ matrix.suffix }}
|
||||||
|
|
||||||
- name: Create manifest list and push
|
- name: Create manifest list and push
|
||||||
working-directory: ${{ runner.temp }}/digests
|
working-directory: ${{ runner.temp }}/digests
|
||||||
@@ -315,13 +305,13 @@ jobs:
|
|||||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
uses: docker/login-action@v3
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
@@ -348,7 +338,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
id: build
|
id: build
|
||||||
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
|
uses: docker/build-push-action@v6.15.0
|
||||||
with:
|
with:
|
||||||
context: ${{ env.context }}
|
context: ${{ env.context }}
|
||||||
file: ${{ env.file }}
|
file: ${{ env.file }}
|
||||||
@@ -373,7 +363,7 @@ jobs:
|
|||||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||||
|
|
||||||
- name: Upload digest
|
- name: Upload digest
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: server-digests-${{ env.PLATFORM_PAIR }}
|
name: server-digests-${{ env.PLATFORM_PAIR }}
|
||||||
path: ${{ runner.temp }}/digests/*
|
path: ${{ runner.temp }}/digests/*
|
||||||
@@ -391,7 +381,7 @@ jobs:
|
|||||||
- build_and_push_server
|
- build_and_push_server
|
||||||
steps:
|
steps:
|
||||||
- name: Download digests
|
- name: Download digests
|
||||||
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: ${{ runner.temp }}/digests
|
path: ${{ runner.temp }}/digests
|
||||||
pattern: server-digests-*
|
pattern: server-digests-*
|
||||||
@@ -399,44 +389,43 @@ jobs:
|
|||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
if: ${{ github.event_name == 'release' }}
|
if: ${{ github.event_name == 'release' }}
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Login to GHCR
|
- name: Login to GHCR
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Generate docker image tags
|
- name: Generate docker image tags
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5
|
uses: docker/metadata-action@v5
|
||||||
env:
|
env:
|
||||||
DOCKER_METADATA_PR_HEAD_SHA: 'true'
|
DOCKER_METADATA_PR_HEAD_SHA: 'true'
|
||||||
with:
|
with:
|
||||||
flavor: |
|
flavor: |
|
||||||
# Disable latest tag
|
# Disable latest tag
|
||||||
latest=false
|
latest=false
|
||||||
suffix=${{ matrix.suffix }}
|
|
||||||
images: |
|
images: |
|
||||||
name=${{ env.GHCR_REPO }}
|
name=${{ env.GHCR_REPO }}
|
||||||
name=${{ env.DOCKER_REPO }},enable=${{ github.event_name == 'release' }}
|
name=${{ env.DOCKER_REPO }},enable=${{ github.event_name == 'release' }}
|
||||||
tags: |
|
tags: |
|
||||||
# Tag with branch name
|
# Tag with branch name
|
||||||
type=ref,event=branch
|
type=ref,event=branch,suffix=${{ matrix.suffix }}
|
||||||
# Tag with pr-number
|
# Tag with pr-number
|
||||||
type=ref,event=pr
|
type=ref,event=pr,suffix=${{ matrix.suffix }}
|
||||||
# Tag with long commit sha hash
|
# Tag with long commit sha hash
|
||||||
type=sha,format=long,prefix=commit-
|
type=sha,format=long,prefix=commit-,suffix=${{ matrix.suffix }}
|
||||||
# Tag with git tag on release
|
# Tag with git tag on release
|
||||||
type=ref,event=tag
|
type=ref,event=tag,suffix=${{ matrix.suffix }}
|
||||||
type=raw,value=release,enable=${{ github.event_name == 'release' }}
|
type=raw,value=release,enable=${{ github.event_name == 'release' }},suffix=${{ matrix.suffix }}
|
||||||
|
|
||||||
- name: Create manifest list and push
|
- name: Create manifest list and push
|
||||||
working-directory: ${{ runner.temp }}/digests
|
working-directory: ${{ runner.temp }}/digests
|
||||||
|
|||||||
11
.github/workflows/docs-build.yml
vendored
11
.github/workflows/docs-build.yml
vendored
@@ -3,6 +3,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
|
||||||
@@ -17,9 +18,9 @@ jobs:
|
|||||||
should_run: ${{ steps.found_paths.outputs.docs == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
should_run: ${{ steps.found_paths.outputs.docs == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
- id: found_paths
|
- id: found_paths
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
uses: dorny/paths-filter@v3
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
docs:
|
docs:
|
||||||
@@ -41,10 +42,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './docs/.nvmrc'
|
node-version-file: './docs/.nvmrc'
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ jobs:
|
|||||||
run: npm run build
|
run: npm run build
|
||||||
|
|
||||||
- name: Upload build output
|
- name: Upload build output
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: docs-build-output
|
name: docs-build-output
|
||||||
path: docs/build/
|
path: docs/build/
|
||||||
|
|||||||
42
.github/workflows/docs-deploy.yml
vendored
42
.github/workflows/docs-deploy.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
name: Docs deploy
|
name: Docs deploy
|
||||||
on:
|
on:
|
||||||
workflow_run:
|
workflow_run:
|
||||||
workflows: ['Docs build']
|
workflows: ["Docs build"]
|
||||||
types:
|
types:
|
||||||
- completed
|
- completed
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
run: echo 'The triggering workflow did not succeed' && exit 1
|
run: echo 'The triggering workflow did not succeed' && exit 1
|
||||||
- name: Get artifact
|
- name: Get artifact
|
||||||
id: get-artifact
|
id: get-artifact
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
return { found: true, id: matchArtifact.id };
|
return { found: true, id: matchArtifact.id };
|
||||||
- name: Determine deploy parameters
|
- name: Determine deploy parameters
|
||||||
id: parameters
|
id: parameters
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const eventType = context.payload.workflow_run.event;
|
const eventType = context.payload.workflow_run.event;
|
||||||
@@ -98,11 +98,11 @@ jobs:
|
|||||||
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
|
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Load parameters
|
- name: Load parameters
|
||||||
id: parameters
|
id: parameters
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const json = `${{ needs.checks.outputs.parameters }}`;
|
const json = `${{ needs.checks.outputs.parameters }}`;
|
||||||
@@ -115,7 +115,7 @@ jobs:
|
|||||||
echo "Starting docs deployment for ${{ steps.parameters.outputs.event }} ${{ steps.parameters.outputs.name }}"
|
echo "Starting docs deployment for ${{ steps.parameters.outputs.event }} ${{ steps.parameters.outputs.name }}"
|
||||||
|
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
let artifact = ${{ needs.checks.outputs.artifact }};
|
let artifact = ${{ needs.checks.outputs.artifact }};
|
||||||
@@ -138,12 +138,12 @@ jobs:
|
|||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
|
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
|
||||||
uses: gruntwork-io/terragrunt-action@9559e51d05873b0ea467c42bbabcb5c067642ccc # v2
|
uses: gruntwork-io/terragrunt-action@v2
|
||||||
with:
|
with:
|
||||||
tg_version: '0.58.12'
|
tg_version: "0.58.12"
|
||||||
tofu_version: '1.7.1'
|
tofu_version: "1.7.1"
|
||||||
tg_dir: 'deployment/modules/cloudflare/docs'
|
tg_dir: "deployment/modules/cloudflare/docs"
|
||||||
tg_command: 'apply'
|
tg_command: "apply"
|
||||||
|
|
||||||
- name: Deploy Docs Subdomain Output
|
- name: Deploy Docs Subdomain Output
|
||||||
id: docs-output
|
id: docs-output
|
||||||
@@ -153,12 +153,12 @@ jobs:
|
|||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
|
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
|
||||||
uses: gruntwork-io/terragrunt-action@9559e51d05873b0ea467c42bbabcb5c067642ccc # v2
|
uses: gruntwork-io/terragrunt-action@v2
|
||||||
with:
|
with:
|
||||||
tg_version: '0.58.12'
|
tg_version: "0.58.12"
|
||||||
tofu_version: '1.7.1'
|
tofu_version: "1.7.1"
|
||||||
tg_dir: 'deployment/modules/cloudflare/docs'
|
tg_dir: "deployment/modules/cloudflare/docs"
|
||||||
tg_command: 'output -json'
|
tg_command: "output -json"
|
||||||
|
|
||||||
- name: Output Cleaning
|
- name: Output Cleaning
|
||||||
id: clean
|
id: clean
|
||||||
@@ -167,13 +167,13 @@ jobs:
|
|||||||
echo "output=$TG_OUT" >> $GITHUB_OUTPUT
|
echo "output=$TG_OUT" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Publish to Cloudflare Pages
|
- name: Publish to Cloudflare Pages
|
||||||
uses: cloudflare/pages-action@f0a1cd58cd66095dee69bfa18fa5efd1dde93bca # v1
|
uses: cloudflare/pages-action@v1
|
||||||
with:
|
with:
|
||||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN_PAGES_UPLOAD }}
|
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN_PAGES_UPLOAD }}
|
||||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
projectName: ${{ fromJson(steps.clean.outputs.output).pages_project_name.value }}
|
projectName: ${{ fromJson(steps.clean.outputs.output).pages_project_name.value }}
|
||||||
workingDirectory: 'docs'
|
workingDirectory: "docs"
|
||||||
directory: 'build'
|
directory: "build"
|
||||||
branch: ${{ steps.parameters.outputs.name }}
|
branch: ${{ steps.parameters.outputs.name }}
|
||||||
wranglerVersion: '3'
|
wranglerVersion: '3'
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ jobs:
|
|||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
|
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
|
||||||
uses: gruntwork-io/terragrunt-action@9559e51d05873b0ea467c42bbabcb5c067642ccc # v2
|
uses: gruntwork-io/terragrunt-action@v2
|
||||||
with:
|
with:
|
||||||
tg_version: '0.58.12'
|
tg_version: '0.58.12'
|
||||||
tofu_version: '1.7.1'
|
tofu_version: '1.7.1'
|
||||||
@@ -192,7 +192,7 @@ jobs:
|
|||||||
tg_command: 'apply'
|
tg_command: 'apply'
|
||||||
|
|
||||||
- name: Comment
|
- name: Comment
|
||||||
uses: actions-cool/maintain-one-comment@4b2dbf086015f892dcb5e8c1106f5fccd6c1476b # v3
|
uses: actions-cool/maintain-one-comment@v3
|
||||||
if: ${{ steps.parameters.outputs.event == 'pr' }}
|
if: ${{ steps.parameters.outputs.event == 'pr' }}
|
||||||
with:
|
with:
|
||||||
number: ${{ fromJson(needs.checks.outputs.parameters).pr_number }}
|
number: ${{ fromJson(needs.checks.outputs.parameters).pr_number }}
|
||||||
|
|||||||
18
.github/workflows/docs-destroy.yml
vendored
18
.github/workflows/docs-destroy.yml
vendored
@@ -9,24 +9,24 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Destroy Docs Subdomain
|
- name: Destroy Docs Subdomain
|
||||||
env:
|
env:
|
||||||
TF_VAR_prefix_name: 'pr-${{ github.event.number }}'
|
TF_VAR_prefix_name: "pr-${{ github.event.number }}"
|
||||||
TF_VAR_prefix_event_type: 'pr'
|
TF_VAR_prefix_event_type: "pr"
|
||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
|
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
|
||||||
uses: gruntwork-io/terragrunt-action@9559e51d05873b0ea467c42bbabcb5c067642ccc # v2
|
uses: gruntwork-io/terragrunt-action@v2
|
||||||
with:
|
with:
|
||||||
tg_version: '0.58.12'
|
tg_version: "0.58.12"
|
||||||
tofu_version: '1.7.1'
|
tofu_version: "1.7.1"
|
||||||
tg_dir: 'deployment/modules/cloudflare/docs'
|
tg_dir: "deployment/modules/cloudflare/docs"
|
||||||
tg_command: 'destroy -refresh=false'
|
tg_command: "destroy -refresh=false"
|
||||||
|
|
||||||
- name: Comment
|
- name: Comment
|
||||||
uses: actions-cool/maintain-one-comment@4b2dbf086015f892dcb5e8c1106f5fccd6c1476b # v3
|
uses: actions-cool/maintain-one-comment@v3
|
||||||
with:
|
with:
|
||||||
number: ${{ github.event.number }}
|
number: ${{ github.event.number }}
|
||||||
delete: true
|
delete: true
|
||||||
|
|||||||
11
.github/workflows/fix-format.yml
vendored
11
.github/workflows/fix-format.yml
vendored
@@ -13,19 +13,19 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Generate a token
|
- name: Generate a token
|
||||||
id: generate-token
|
id: generate-token
|
||||||
uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1
|
uses: actions/create-github-app-token@v1
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: 'Checkout'
|
- name: 'Checkout'
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.ref }}
|
ref: ${{ github.event.pull_request.head.ref }}
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
|
|
||||||
@@ -33,13 +33,13 @@ jobs:
|
|||||||
run: make install-all && make format-all
|
run: make install-all && make format-all
|
||||||
|
|
||||||
- name: Commit and push
|
- name: Commit and push
|
||||||
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9
|
uses: EndBug/add-and-commit@v9
|
||||||
with:
|
with:
|
||||||
default_author: github_actions
|
default_author: github_actions
|
||||||
message: 'chore: fix formatting'
|
message: 'chore: fix formatting'
|
||||||
|
|
||||||
- name: Remove label
|
- name: Remove label
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
uses: actions/github-script@v7
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
@@ -49,3 +49,4 @@ jobs:
|
|||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
name: 'fix:formatting'
|
name: 'fix:formatting'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
6
.github/workflows/pr-label-validation.yml
vendored
6
.github/workflows/pr-label-validation.yml
vendored
@@ -12,11 +12,11 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: Require PR to have a changelog label
|
- name: Require PR to have a changelog label
|
||||||
uses: mheap/github-action-required-labels@388fd6af37b34cdfe5a23b37060e763217e58b03 # v5
|
uses: mheap/github-action-required-labels@v5
|
||||||
with:
|
with:
|
||||||
mode: exactly
|
mode: exactly
|
||||||
count: 1
|
count: 1
|
||||||
use_regex: true
|
use_regex: true
|
||||||
labels: 'changelog:.*'
|
labels: "changelog:.*"
|
||||||
add_comment: true
|
add_comment: true
|
||||||
message: 'Label error. Requires {{errorString}} {{count}} of: {{ provided }}. Found: {{ applied }}. A maintainer will add the required label.'
|
message: "Label error. Requires {{errorString}} {{count}} of: {{ provided }}. Found: {{ applied }}. A maintainer will add the required label."
|
||||||
|
|||||||
6
.github/workflows/pr-labeler.yml
vendored
6
.github/workflows/pr-labeler.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
name: 'Pull Request Labeler'
|
name: "Pull Request Labeler"
|
||||||
on:
|
on:
|
||||||
- pull_request_target
|
- pull_request_target
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
labeler:
|
labeler:
|
||||||
@@ -9,4 +9,4 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5
|
- uses: actions/labeler@v5
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: PR Conventional Commit Validation
|
- name: PR Conventional Commit Validation
|
||||||
uses: ytanikin/PRConventionalCommits@b628c5a234cc32513014b7bfdd1e47b532124d98 # 1.3.0
|
uses: ytanikin/PRConventionalCommits@1.3.0
|
||||||
with:
|
with:
|
||||||
task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]'
|
task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]'
|
||||||
add_label: 'false'
|
add_label: 'false'
|
||||||
|
|||||||
18
.github/workflows/prepare-release.yml
vendored
18
.github/workflows/prepare-release.yml
vendored
@@ -31,25 +31,25 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Generate a token
|
- name: Generate a token
|
||||||
id: generate-token
|
id: generate-token
|
||||||
uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1
|
uses: actions/create-github-app-token@v1
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
- name: Install uv
|
- name: Install Poetry
|
||||||
uses: astral-sh/setup-uv@0c5e2b8115b80b4c7c5ddf6ffdd634974642d182 # v5
|
run: pipx install poetry
|
||||||
|
|
||||||
- name: Bump version
|
- name: Bump version
|
||||||
run: misc/release/pump-version.sh -s "${{ inputs.serverBump }}" -m "${{ inputs.mobileBump }}"
|
run: misc/release/pump-version.sh -s "${{ inputs.serverBump }}" -m "${{ inputs.mobileBump }}"
|
||||||
|
|
||||||
- name: Commit and tag
|
- name: Commit and tag
|
||||||
id: push-tag
|
id: push-tag
|
||||||
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9
|
uses: EndBug/add-and-commit@v9
|
||||||
with:
|
with:
|
||||||
default_author: github_actions
|
default_author: github_actions
|
||||||
message: 'chore: version ${{ env.IMMICH_VERSION }}'
|
message: 'chore: version ${{ env.IMMICH_VERSION }}'
|
||||||
@@ -70,23 +70,23 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Generate a token
|
- name: Generate a token
|
||||||
id: generate-token
|
id: generate-token
|
||||||
uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1
|
uses: actions/create-github-app-token@v1
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
- name: Download APK
|
- name: Download APK
|
||||||
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-apk-signed
|
name: release-apk-signed
|
||||||
|
|
||||||
- name: Create draft release
|
- name: Create draft release
|
||||||
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
tag_name: ${{ env.IMMICH_VERSION }}
|
tag_name: ${{ env.IMMICH_VERSION }}
|
||||||
|
|||||||
10
.github/workflows/preview-label.yaml
vendored
10
.github/workflows/preview-label.yaml
vendored
@@ -2,7 +2,7 @@ name: Preview label
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [labeled, closed]
|
types: [labeled]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
comment-status:
|
comment-status:
|
||||||
@@ -11,10 +11,10 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2
|
- uses: mshick/add-pr-comment@v2
|
||||||
with:
|
with:
|
||||||
message-id: 'preview-status'
|
message-id: "preview-status"
|
||||||
message: 'Deploying preview environment to https://pr-${{ github.event.pull_request.number }}.preview.internal.immich.cloud/'
|
message: "Deploying preview environment to https://pr-${{ github.event.pull_request.number }}.preview.internal.immich.cloud/"
|
||||||
|
|
||||||
remove-label:
|
remove-label:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -22,7 +22,7 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
|
- uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
github.rest.issues.removeLabel({
|
github.rest.issues.removeLabel({
|
||||||
|
|||||||
4
.github/workflows/sdk.yml
vendored
4
.github/workflows/sdk.yml
vendored
@@ -15,9 +15,9 @@ jobs:
|
|||||||
run:
|
run:
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
- uses: actions/checkout@v4
|
||||||
# Setup .npmrc file to publish to npm
|
# Setup .npmrc file to publish to npm
|
||||||
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './open-api/typescript-sdk/.nvmrc'
|
node-version-file: './open-api/typescript-sdk/.nvmrc'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|||||||
33
.github/workflows/static_analysis.yml
vendored
33
.github/workflows/static_analysis.yml
vendored
@@ -16,9 +16,9 @@ jobs:
|
|||||||
should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
- id: found_paths
|
- id: found_paths
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
uses: dorny/paths-filter@v3
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
mobile:
|
mobile:
|
||||||
@@ -38,10 +38,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Flutter SDK
|
- name: Setup Flutter SDK
|
||||||
uses: subosito/flutter-action@e938fdf56512cc96ef2f93601a5a40bde3801046 # v2
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
flutter-version-file: ./mobile/pubspec.yaml
|
flutter-version-file: ./mobile/pubspec.yaml
|
||||||
@@ -50,26 +50,6 @@ jobs:
|
|||||||
run: dart pub get
|
run: dart pub get
|
||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
|
|
||||||
- name: Run Build Runner
|
|
||||||
run: make build
|
|
||||||
working-directory: ./mobile
|
|
||||||
|
|
||||||
- name: Find file changes
|
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20
|
|
||||||
id: verify-changed-files
|
|
||||||
with:
|
|
||||||
files: |
|
|
||||||
mobile/**/*.g.dart
|
|
||||||
mobile/**/*.gr.dart
|
|
||||||
mobile/**/*.drift.dart
|
|
||||||
|
|
||||||
- name: Verify files have not changed
|
|
||||||
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
|
||||||
run: |
|
|
||||||
echo "ERROR: Generated files not up to date! Run make_build inside the mobile directory"
|
|
||||||
echo "Changed files: ${{ steps.verify-changed-files.outputs.changed_files }}"
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
- name: Run dart analyze
|
- name: Run dart analyze
|
||||||
run: dart analyze --fatal-infos
|
run: dart analyze --fatal-infos
|
||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
@@ -81,3 +61,8 @@ jobs:
|
|||||||
- name: Run dart custom_lint
|
- name: Run dart custom_lint
|
||||||
run: dart run custom_lint
|
run: dart run custom_lint
|
||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
|
|
||||||
|
# Enable after riverpod generator migration is completed
|
||||||
|
# - name: Run dart custom lint
|
||||||
|
# run: dart run custom_lint
|
||||||
|
# working-directory: ./mobile
|
||||||
|
|||||||
117
.github/workflows/test.yml
vendored
117
.github/workflows/test.yml
vendored
@@ -21,12 +21,11 @@ jobs:
|
|||||||
should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||||
should_run_e2e_web: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.web == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
should_run_e2e_web: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.web == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||||
should_run_e2e_server_cli: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.server == 'true' || steps.found_paths.outputs.cli == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
should_run_e2e_server_cli: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.server == 'true' || steps.found_paths.outputs.cli == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
||||||
should_run_.github: ${{ steps.found_paths.outputs['.github'] == 'true' || steps.should_force.outputs.should_force == 'true' }} # redundant to have should_force but if someone changes the trigger then this won't have to be changed
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
- id: found_paths
|
- id: found_paths
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
uses: dorny/paths-filter@v3
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
web:
|
web:
|
||||||
@@ -46,8 +45,6 @@ jobs:
|
|||||||
- 'machine-learning/**'
|
- 'machine-learning/**'
|
||||||
workflow:
|
workflow:
|
||||||
- '.github/workflows/test.yml'
|
- '.github/workflows/test.yml'
|
||||||
.github:
|
|
||||||
- '.github/**'
|
|
||||||
|
|
||||||
- name: Check if we should force jobs to run
|
- name: Check if we should force jobs to run
|
||||||
id: should_force
|
id: should_force
|
||||||
@@ -64,10 +61,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
|
|
||||||
@@ -101,10 +98,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './cli/.nvmrc'
|
node-version-file: './cli/.nvmrc'
|
||||||
|
|
||||||
@@ -142,10 +139,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './cli/.nvmrc'
|
node-version-file: './cli/.nvmrc'
|
||||||
|
|
||||||
@@ -176,10 +173,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './web/.nvmrc'
|
node-version-file: './web/.nvmrc'
|
||||||
|
|
||||||
@@ -221,10 +218,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './e2e/.nvmrc'
|
node-version-file: './e2e/.nvmrc'
|
||||||
|
|
||||||
@@ -260,10 +257,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
|
|
||||||
@@ -285,12 +282,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './e2e/.nvmrc'
|
node-version-file: './e2e/.nvmrc'
|
||||||
|
|
||||||
@@ -327,12 +324,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './e2e/.nvmrc'
|
node-version-file: './e2e/.nvmrc'
|
||||||
|
|
||||||
@@ -363,9 +360,9 @@ jobs:
|
|||||||
if: ${{ needs.pre-job.outputs.should_run_mobile == 'true' }}
|
if: ${{ needs.pre-job.outputs.should_run_mobile == 'true' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
- uses: actions/checkout@v4
|
||||||
- name: Setup Flutter SDK
|
- name: Setup Flutter SDK
|
||||||
uses: subosito/flutter-action@e938fdf56512cc96ef2f93601a5a40bde3801046 # v2
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
flutter-version-file: ./mobile/pubspec.yaml
|
flutter-version-file: ./mobile/pubspec.yaml
|
||||||
@@ -382,60 +379,34 @@ jobs:
|
|||||||
run:
|
run:
|
||||||
working-directory: ./machine-learning
|
working-directory: ./machine-learning
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install uv
|
- name: Install poetry
|
||||||
uses: astral-sh/setup-uv@0c5e2b8115b80b4c7c5ddf6ffdd634974642d182 # v5
|
run: pipx install poetry
|
||||||
- uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5
|
- uses: actions/setup-python@v5
|
||||||
# TODO: add caching when supported (https://github.com/actions/setup-python/pull/818)
|
with:
|
||||||
# with:
|
python-version: 3.11
|
||||||
# python-version: 3.11
|
cache: 'poetry'
|
||||||
# cache: 'uv'
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
uv sync --extra cpu
|
poetry install --with dev --with cpu
|
||||||
- name: Lint with ruff
|
- name: Lint with ruff
|
||||||
run: |
|
run: |
|
||||||
uv run ruff check --output-format=github immich_ml
|
poetry run ruff check --output-format=github app export
|
||||||
- name: Check black formatting
|
- name: Check black formatting
|
||||||
run: |
|
run: |
|
||||||
uv run black --check immich_ml
|
poetry run black --check app export
|
||||||
- name: Run mypy type checking
|
- name: Run mypy type checking
|
||||||
run: |
|
run: |
|
||||||
uv run mypy --strict immich_ml/
|
poetry run mypy --install-types --non-interactive --strict app/
|
||||||
- name: Run tests and coverage
|
- name: Run tests and coverage
|
||||||
run: |
|
run: |
|
||||||
uv run pytest --cov=immich_ml --cov-report term-missing
|
poetry run pytest app --cov=app --cov-report term-missing
|
||||||
|
|
||||||
github-files-formatting:
|
|
||||||
name: .github Files Formatting
|
|
||||||
needs: pre-job
|
|
||||||
if: ${{ needs.pre-job.outputs['should_run_.github'] == 'true' }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: ./.github
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
|
||||||
|
|
||||||
- name: Setup Node
|
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
|
||||||
with:
|
|
||||||
node-version-file: './.github/.nvmrc'
|
|
||||||
|
|
||||||
- name: Run npm install
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Run formatter
|
|
||||||
run: npm run format
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
|
|
||||||
shellcheck:
|
shellcheck:
|
||||||
name: ShellCheck
|
name: ShellCheck
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
- uses: actions/checkout@v4
|
||||||
- name: Run ShellCheck
|
- name: Run ShellCheck
|
||||||
uses: ludeeus/action-shellcheck@master
|
uses: ludeeus/action-shellcheck@master
|
||||||
with:
|
with:
|
||||||
@@ -449,10 +420,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
|
|
||||||
@@ -466,7 +437,7 @@ jobs:
|
|||||||
run: make open-api
|
run: make open-api
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20
|
uses: tj-actions/verify-changed-files@v20
|
||||||
id: verify-changed-files
|
id: verify-changed-files
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
@@ -504,10 +475,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
|
|
||||||
@@ -518,27 +489,27 @@ jobs:
|
|||||||
run: npm run build
|
run: npm run build
|
||||||
|
|
||||||
- name: Run existing migrations
|
- name: Run existing migrations
|
||||||
run: npm run migrations:run
|
run: npm run typeorm:migrations:run
|
||||||
|
|
||||||
- name: Test npm run schema:reset command works
|
- name: Test npm run schema:reset command works
|
||||||
run: npm run typeorm:schema:reset
|
run: npm run typeorm:schema:reset
|
||||||
|
|
||||||
- name: Generate new migrations
|
- name: Generate new migrations
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: npm run migrations:generate TestMigration
|
run: npm run typeorm:migrations:generate ./src/migrations/TestMigration
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20
|
uses: tj-actions/verify-changed-files@v20
|
||||||
id: verify-changed-files
|
id: verify-changed-files
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
server/src
|
server/src/migrations/
|
||||||
- name: Verify migration files have not changed
|
- name: Verify migration files have not changed
|
||||||
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
||||||
run: |
|
run: |
|
||||||
echo "ERROR: Generated migration files not up to date!"
|
echo "ERROR: Generated migration files not up to date!"
|
||||||
echo "Changed files: ${{ steps.verify-changed-files.outputs.changed_files }}"
|
echo "Changed files: ${{ steps.verify-changed-files.outputs.changed_files }}"
|
||||||
cat ./src/*-TestMigration.ts
|
cat ./src/migrations/*-TestMigration.ts
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
- name: Run SQL generation
|
- name: Run SQL generation
|
||||||
@@ -547,7 +518,7 @@ jobs:
|
|||||||
DB_URL: postgres://postgres:postgres@localhost:5432/immich
|
DB_URL: postgres://postgres:postgres@localhost:5432/immich
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20
|
uses: tj-actions/verify-changed-files@v20
|
||||||
id: verify-changed-sql-files
|
id: verify-changed-sql-files
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
|
|||||||
15
.github/workflows/weblate-lock.yml
vendored
15
.github/workflows/weblate-lock.yml
vendored
@@ -11,22 +11,15 @@ jobs:
|
|||||||
should_run: ${{ steps.found_paths.outputs.i18n == 'true' && github.head_ref != 'chore/translations'}}
|
should_run: ${{ steps.found_paths.outputs.i18n == 'true' && github.head_ref != 'chore/translations'}}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
- id: found_paths
|
- id: found_paths
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
uses: dorny/paths-filter@v3
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
i18n:
|
i18n:
|
||||||
- 'i18n/!(en)**\.json'
|
- 'i18n/!(en)**\.json'
|
||||||
- name: Debug
|
|
||||||
run: |
|
|
||||||
echo "Should run: ${{ steps.found_paths.outputs.i18n == 'true' && github.head_ref != 'chore/translations'}}"
|
|
||||||
echo "Found i18n paths: ${{ steps.found_paths.outputs.i18n }}"
|
|
||||||
echo "Head ref: ${{ github.head_ref }}"
|
|
||||||
|
|
||||||
enforce-lock:
|
enforce-lock:
|
||||||
name: Check Weblate Lock
|
name: Check Weblate Lock
|
||||||
needs: [pre-job]
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ needs.pre-job.outputs.should_run == 'true' }}
|
if: ${{ needs.pre-job.outputs.should_run == 'true' }}
|
||||||
steps:
|
steps:
|
||||||
@@ -36,7 +29,7 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- name: Find Pull Request
|
- name: Find Pull Request
|
||||||
uses: juliangruber/find-pull-request-action@48b6133aa6c826f267ebd33aa2d29470f9d9e7d0 # v1
|
uses: juliangruber/find-pull-request-action@v1
|
||||||
id: find-pr
|
id: find-pr
|
||||||
with:
|
with:
|
||||||
branch: chore/translations
|
branch: chore/translations
|
||||||
@@ -45,7 +38,7 @@ jobs:
|
|||||||
run: exit 1
|
run: exit 1
|
||||||
success-check-lock:
|
success-check-lock:
|
||||||
name: Weblate Lock Check Success
|
name: Weblate Lock Check Success
|
||||||
needs: [enforce-lock]
|
needs: [ enforce-lock ]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: always()
|
if: always()
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -39,7 +39,6 @@
|
|||||||
],
|
],
|
||||||
"explorer.fileNesting.enabled": true,
|
"explorer.fileNesting.enabled": true,
|
||||||
"explorer.fileNesting.patterns": {
|
"explorer.fileNesting.patterns": {
|
||||||
"*.ts": "${capture}.spec.ts,${capture}.mock.ts",
|
"*.ts": "${capture}.spec.ts,${capture}.mock.ts"
|
||||||
"*.dart": "${capture}.g.dart,${capture}.gr.dart,${capture}.drift.dart"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
10
Makefile
10
Makefile
@@ -39,7 +39,7 @@ attach-server:
|
|||||||
renovate:
|
renovate:
|
||||||
LOG_LEVEL=debug npx renovate --platform=local --repository-cache=reset
|
LOG_LEVEL=debug npx renovate --platform=local --repository-cache=reset
|
||||||
|
|
||||||
MODULES = e2e server web cli sdk docs .github
|
MODULES = e2e server web cli sdk docs
|
||||||
|
|
||||||
audit-%:
|
audit-%:
|
||||||
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) audit fix
|
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) audit fix
|
||||||
@@ -77,14 +77,14 @@ test-medium:
|
|||||||
test-medium-dev:
|
test-medium-dev:
|
||||||
docker exec -it immich_server /bin/sh -c "npm run test:medium"
|
docker exec -it immich_server /bin/sh -c "npm run test:medium"
|
||||||
|
|
||||||
build-all: $(foreach M,$(filter-out e2e .github,$(MODULES)),build-$M) ;
|
build-all: $(foreach M,$(filter-out e2e,$(MODULES)),build-$M) ;
|
||||||
install-all: $(foreach M,$(MODULES),install-$M) ;
|
install-all: $(foreach M,$(MODULES),install-$M) ;
|
||||||
check-all: $(foreach M,$(filter-out sdk cli docs .github,$(MODULES)),check-$M) ;
|
check-all: $(foreach M,$(filter-out sdk cli docs,$(MODULES)),check-$M) ;
|
||||||
lint-all: $(foreach M,$(filter-out sdk docs .github,$(MODULES)),lint-$M) ;
|
lint-all: $(foreach M,$(filter-out sdk docs,$(MODULES)),lint-$M) ;
|
||||||
format-all: $(foreach M,$(filter-out sdk,$(MODULES)),format-$M) ;
|
format-all: $(foreach M,$(filter-out sdk,$(MODULES)),format-$M) ;
|
||||||
audit-all: $(foreach M,$(MODULES),audit-$M) ;
|
audit-all: $(foreach M,$(MODULES),audit-$M) ;
|
||||||
hygiene-all: lint-all format-all check-all sql audit-all;
|
hygiene-all: lint-all format-all check-all sql audit-all;
|
||||||
test-all: $(foreach M,$(filter-out sdk docs .github,$(MODULES)),test-$M) ;
|
test-all: $(foreach M,$(filter-out sdk docs,$(MODULES)),test-$M) ;
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
|
find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
|
||||||
|
|||||||
@@ -61,7 +61,9 @@
|
|||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
|
|
||||||
Access the demo [here](https://demo.immich.app). For the mobile app, you can use `https://demo.immich.app` for the `Server Endpoint URL`.
|
Access the demo [here](https://demo.immich.app). The demo is running on a Free-tier Oracle VM in Amsterdam with a 2.4Ghz quad-core ARM64 CPU and 24GB RAM.
|
||||||
|
|
||||||
|
For the mobile app, you can use `https://demo.immich.app/api` for the `Server Endpoint URL`
|
||||||
|
|
||||||
### Login credentials
|
### Login credentials
|
||||||
|
|
||||||
@@ -102,7 +104,7 @@ Access the demo [here](https://demo.immich.app). For the mobile app, you can use
|
|||||||
| Read-only gallery | Yes | Yes |
|
| Read-only gallery | Yes | Yes |
|
||||||
| Stacked Photos | Yes | Yes |
|
| Stacked Photos | Yes | Yes |
|
||||||
| Tags | No | Yes |
|
| Tags | No | Yes |
|
||||||
| Folder View | Yes | Yes |
|
| Folder View | No | Yes |
|
||||||
|
|
||||||
## Translations
|
## Translations
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,39 @@
|
|||||||
|
import { FlatCompat } from '@eslint/eslintrc';
|
||||||
import js from '@eslint/js';
|
import js from '@eslint/js';
|
||||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
import typescriptEslint from '@typescript-eslint/eslint-plugin';
|
||||||
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
|
import tsParser from '@typescript-eslint/parser';
|
||||||
import globals from 'globals';
|
import globals from 'globals';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import typescriptEslint from 'typescript-eslint';
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
recommendedConfig: js.configs.recommended,
|
||||||
|
allConfig: js.configs.all,
|
||||||
|
});
|
||||||
|
|
||||||
export default typescriptEslint.config([
|
export default [
|
||||||
eslintPluginUnicorn.configs.recommended,
|
|
||||||
eslintPluginPrettierRecommended,
|
|
||||||
js.configs.recommended,
|
|
||||||
typescriptEslint.configs.recommended,
|
|
||||||
{
|
{
|
||||||
ignores: ['eslint.config.mjs', 'dist'],
|
ignores: ['eslint.config.mjs', 'dist'],
|
||||||
},
|
},
|
||||||
|
...compat.extends(
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:prettier/recommended',
|
||||||
|
'plugin:unicorn/recommended',
|
||||||
|
),
|
||||||
{
|
{
|
||||||
|
plugins: {
|
||||||
|
'@typescript-eslint': typescriptEslint,
|
||||||
|
},
|
||||||
|
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
globals: {
|
globals: {
|
||||||
...globals.node,
|
...globals.node,
|
||||||
},
|
},
|
||||||
|
|
||||||
parser: typescriptEslint.parser,
|
parser: tsParser,
|
||||||
ecmaVersion: 5,
|
ecmaVersion: 5,
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
|
|
||||||
@@ -48,4 +58,4 @@ export default typescriptEslint.config([
|
|||||||
'object-shorthand': ['error', 'always'],
|
'object-shorthand': ['error', 'always'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
];
|
||||||
|
|||||||
1035
cli/package-lock.json
generated
1035
cli/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.61",
|
"version": "2.2.52",
|
||||||
"description": "Command Line Interface (CLI) for Immich",
|
"description": "Command Line Interface (CLI) for Immich",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": "./dist/index.js",
|
"exports": "./dist/index.js",
|
||||||
@@ -21,7 +21,9 @@
|
|||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/micromatch": "^4.0.9",
|
"@types/micromatch": "^4.0.9",
|
||||||
"@types/mock-fs": "^4.13.1",
|
"@types/mock-fs": "^4.13.1",
|
||||||
"@types/node": "^22.14.0",
|
"@types/node": "^22.13.5",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
||||||
|
"@typescript-eslint/parser": "^8.15.0",
|
||||||
"@vitest/coverage-v8": "^3.0.0",
|
"@vitest/coverage-v8": "^3.0.0",
|
||||||
"byte-size": "^9.0.0",
|
"byte-size": "^9.0.0",
|
||||||
"cli-progress": "^3.12.0",
|
"cli-progress": "^3.12.0",
|
||||||
@@ -29,13 +31,12 @@
|
|||||||
"eslint": "^9.14.0",
|
"eslint": "^9.14.0",
|
||||||
"eslint-config-prettier": "^10.0.0",
|
"eslint-config-prettier": "^10.0.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-unicorn": "^57.0.0",
|
"eslint-plugin-unicorn": "^56.0.1",
|
||||||
"globals": "^16.0.0",
|
"globals": "^16.0.0",
|
||||||
"mock-fs": "^5.2.0",
|
"mock-fs": "^5.2.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"prettier-plugin-organize-imports": "^4.0.0",
|
"prettier-plugin-organize-imports": "^4.0.0",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"typescript-eslint": "^8.28.0",
|
|
||||||
"vite": "^6.0.0",
|
"vite": "^6.0.0",
|
||||||
"vite-tsconfig-paths": "^5.0.0",
|
"vite-tsconfig-paths": "^5.0.0",
|
||||||
"vitest": "^3.0.0",
|
"vitest": "^3.0.0",
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ services:
|
|||||||
context: ../
|
context: ../
|
||||||
dockerfile: server/Dockerfile
|
dockerfile: server/Dockerfile
|
||||||
target: dev
|
target: dev
|
||||||
restart: unless-stopped
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ../server:/usr/src/app
|
- ../server:/usr/src/app
|
||||||
- ../open-api:/usr/src/open-api
|
- ../open-api:/usr/src/open-api
|
||||||
@@ -95,12 +95,12 @@ services:
|
|||||||
image: immich-machine-learning-dev:latest
|
image: immich-machine-learning-dev:latest
|
||||||
# extends:
|
# extends:
|
||||||
# file: hwaccel.ml.yml
|
# file: hwaccel.ml.yml
|
||||||
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference
|
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl] for accelerated inference
|
||||||
build:
|
build:
|
||||||
context: ../machine-learning
|
context: ../machine-learning
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
args:
|
args:
|
||||||
- DEVICE=cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference
|
- DEVICE=cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl] for accelerated inference
|
||||||
ports:
|
ports:
|
||||||
- 3003:3003
|
- 3003:3003
|
||||||
volumes:
|
volumes:
|
||||||
@@ -116,7 +116,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:8-bookworm@sha256:42cba146593a5ea9a622002c1b7cba5da7be248650cbb64ecb9c6c33d29794b1
|
image: redis:6.2-alpine@sha256:148bb5411c184abd288d9aaed139c98123eeb8824c5d3fce03cf721db58066d8
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
|
|
||||||
|
|||||||
@@ -38,12 +38,12 @@ services:
|
|||||||
image: immich-machine-learning:latest
|
image: immich-machine-learning:latest
|
||||||
# extends:
|
# extends:
|
||||||
# file: hwaccel.ml.yml
|
# file: hwaccel.ml.yml
|
||||||
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference
|
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl] for accelerated inference
|
||||||
build:
|
build:
|
||||||
context: ../machine-learning
|
context: ../machine-learning
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
args:
|
args:
|
||||||
- DEVICE=cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference
|
- DEVICE=cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl] for accelerated inference
|
||||||
ports:
|
ports:
|
||||||
- 3003:3003
|
- 3003:3003
|
||||||
volumes:
|
volumes:
|
||||||
@@ -56,7 +56,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:8-bookworm@sha256:42cba146593a5ea9a622002c1b7cba5da7be248650cbb64ecb9c6c33d29794b1
|
image: redis:6.2-alpine@sha256:148bb5411c184abd288d9aaed139c98123eeb8824c5d3fce03cf721db58066d8
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
restart: always
|
||||||
@@ -77,12 +77,22 @@ services:
|
|||||||
- 5432:5432
|
- 5432:5432
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: >-
|
test: >-
|
||||||
pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1; Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1
|
pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1;
|
||||||
|
Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align
|
||||||
|
--command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')";
|
||||||
|
echo "checksum failure count is $$Chksum";
|
||||||
|
[ "$$Chksum" = '0' ] || exit 1
|
||||||
interval: 5m
|
interval: 5m
|
||||||
start_interval: 30s
|
start_interval: 30s
|
||||||
start_period: 5m
|
start_period: 5m
|
||||||
command: >-
|
command: >-
|
||||||
postgres -c shared_preload_libraries=vectors.so -c 'search_path="$$user", public, vectors' -c logging_collector=on -c max_wal_size=2GB -c shared_buffers=512MB -c wal_compression=on
|
postgres
|
||||||
|
-c shared_preload_libraries=vectors.so
|
||||||
|
-c 'search_path="$$user", public, vectors'
|
||||||
|
-c logging_collector=on
|
||||||
|
-c max_wal_size=2GB
|
||||||
|
-c shared_buffers=512MB
|
||||||
|
-c wal_compression=on
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
# set IMMICH_TELEMETRY_INCLUDE=all in .env to enable metrics
|
# set IMMICH_TELEMETRY_INCLUDE=all in .env to enable metrics
|
||||||
@@ -90,7 +100,7 @@ services:
|
|||||||
container_name: immich_prometheus
|
container_name: immich_prometheus
|
||||||
ports:
|
ports:
|
||||||
- 9090:9090
|
- 9090:9090
|
||||||
image: prom/prometheus@sha256:502ad90314c7485892ce696cb14a99fceab9fc27af29f4b427f41bd39701a199
|
image: prom/prometheus@sha256:6927e0919a144aa7616fd0137d4816816d42f6b816de3af269ab065250859a62
|
||||||
volumes:
|
volumes:
|
||||||
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
||||||
- prometheus-data:/prometheus
|
- prometheus-data:/prometheus
|
||||||
@@ -99,10 +109,10 @@ services:
|
|||||||
# add data source for http://immich-prometheus:9090 to get started
|
# add data source for http://immich-prometheus:9090 to get started
|
||||||
immich-grafana:
|
immich-grafana:
|
||||||
container_name: immich_grafana
|
container_name: immich_grafana
|
||||||
command: [ './run.sh', '-disable-reporting' ]
|
command: ['./run.sh', '-disable-reporting']
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
image: grafana/grafana:11.6.0-ubuntu@sha256:fd8fa48213c624e1a95122f1d93abbf1cf1cbe85fc73212c1e599dbd76c63ff8
|
image: grafana/grafana:11.5.2-ubuntu@sha256:8b5858c447e06fd7a89006b562ba7bba7c4d5813600c7982374c41852adefaeb
|
||||||
volumes:
|
volumes:
|
||||||
- grafana-data:/var/lib/grafana
|
- grafana-data:/var/lib/grafana
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ services:
|
|||||||
|
|
||||||
immich-machine-learning:
|
immich-machine-learning:
|
||||||
container_name: immich_machine_learning
|
container_name: immich_machine_learning
|
||||||
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
|
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino] to the image tag.
|
||||||
# Example tag: ${IMMICH_VERSION:-release}-cuda
|
# Example tag: ${IMMICH_VERSION:-release}-cuda
|
||||||
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
|
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
|
||||||
# extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/ml-hardware-acceleration
|
# extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/ml-hardware-acceleration
|
||||||
# file: hwaccel.ml.yml
|
# file: hwaccel.ml.yml
|
||||||
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
|
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl] for accelerated inference - use the `-wsl` version for WSL2 where applicable
|
||||||
volumes:
|
volumes:
|
||||||
- model-cache:/cache
|
- model-cache:/cache
|
||||||
env_file:
|
env_file:
|
||||||
@@ -49,7 +49,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:8-bookworm@sha256:42cba146593a5ea9a622002c1b7cba5da7be248650cbb64ecb9c6c33d29794b1
|
image: docker.io/redis:6.2-alpine@sha256:148bb5411c184abd288d9aaed139c98123eeb8824c5d3fce03cf721db58066d8
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
restart: always
|
||||||
@@ -67,12 +67,22 @@ services:
|
|||||||
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
|
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: >-
|
test: >-
|
||||||
pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1; Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1
|
pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1;
|
||||||
|
Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align
|
||||||
|
--command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')";
|
||||||
|
echo "checksum failure count is $$Chksum";
|
||||||
|
[ "$$Chksum" = '0' ] || exit 1
|
||||||
interval: 5m
|
interval: 5m
|
||||||
start_interval: 30s
|
start_interval: 30s
|
||||||
start_period: 5m
|
start_period: 5m
|
||||||
command: >-
|
command: >-
|
||||||
postgres -c shared_preload_libraries=vectors.so -c 'search_path="$$user", public, vectors' -c logging_collector=on -c max_wal_size=2GB -c shared_buffers=512MB -c wal_compression=on
|
postgres
|
||||||
|
-c shared_preload_libraries=vectors.so
|
||||||
|
-c 'search_path="$$user", public, vectors'
|
||||||
|
-c logging_collector=on
|
||||||
|
-c max_wal_size=2GB
|
||||||
|
-c shared_buffers=512MB
|
||||||
|
-c wal_compression=on
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
# The location where your uploaded files are stored
|
# The location where your uploaded files are stored
|
||||||
UPLOAD_LOCATION=./library
|
UPLOAD_LOCATION=./library
|
||||||
|
# The location where your database files are stored
|
||||||
# The location where your database files are stored. Network shares are not supported for the database
|
|
||||||
DB_DATA_LOCATION=./postgres
|
DB_DATA_LOCATION=./postgres
|
||||||
|
|
||||||
# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
|
# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
|
||||||
|
|||||||
@@ -14,13 +14,6 @@ services:
|
|||||||
- /lib/firmware/mali_csffw.bin:/lib/firmware/mali_csffw.bin:ro # Mali firmware for your chipset (not always required depending on the driver)
|
- /lib/firmware/mali_csffw.bin:/lib/firmware/mali_csffw.bin:ro # Mali firmware for your chipset (not always required depending on the driver)
|
||||||
- /usr/lib/libmali.so:/usr/lib/libmali.so:ro # Mali driver for your chipset (always required)
|
- /usr/lib/libmali.so:/usr/lib/libmali.so:ro # Mali driver for your chipset (always required)
|
||||||
|
|
||||||
rknn:
|
|
||||||
security_opt:
|
|
||||||
- systempaths=unconfined
|
|
||||||
- apparmor=unconfined
|
|
||||||
devices:
|
|
||||||
- /dev/dri:/dev/dri
|
|
||||||
|
|
||||||
cpu: {}
|
cpu: {}
|
||||||
|
|
||||||
cuda:
|
cuda:
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ See [Backup and Restore](/docs/administration/backup-and-restore.md).
|
|||||||
|
|
||||||
### Does Immich support reading existing face tag metadata?
|
### Does Immich support reading existing face tag metadata?
|
||||||
|
|
||||||
Yes, it creates new faces and persons from the imported asset metadata. For details see the [feature request #4348](https://github.com/immich-app/immich/discussions/4348) and [PR #6455](https://github.com/immich-app/immich/pull/6455).
|
No, it currently does not. There is an [open feature request on GitHub](https://github.com/immich-app/immich/discussions/4348).
|
||||||
|
|
||||||
### Does Immich support the filtering of NSFW images?
|
### Does Immich support the filtering of NSFW images?
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ No, this is not supported. Only models listed in the [Hugging Face][huggingface]
|
|||||||
|
|
||||||
### I want to be able to search in other languages besides English. How can I do that?
|
### I want to be able to search in other languages besides English. How can I do that?
|
||||||
|
|
||||||
You can change to a multilingual CLIP model. See [here](/docs/features/searching#clip-models) for instructions.
|
You can change to a multilingual CLIP model. See [here](/docs/features/searching#clip-model) for instructions.
|
||||||
|
|
||||||
### Does Immich support Facial Recognition for videos?
|
### Does Immich support Facial Recognition for videos?
|
||||||
|
|
||||||
|
|||||||
@@ -30,13 +30,6 @@ As mentioned above, you should make your own backup of these together with the a
|
|||||||
You can adjust the schedule and amount of kept backups in the [admin settings](http://my.immich.app/admin/system-settings?isOpen=backup).
|
You can adjust the schedule and amount of kept backups in the [admin settings](http://my.immich.app/admin/system-settings?isOpen=backup).
|
||||||
By default, Immich will keep the last 14 backups and create a new backup every day at 2:00 AM.
|
By default, Immich will keep the last 14 backups and create a new backup every day at 2:00 AM.
|
||||||
|
|
||||||
#### Trigger Backup
|
|
||||||
|
|
||||||
You are able to trigger a backup in the [admin job status page](http://my.immich.app/admin/jobs-status).
|
|
||||||
Visit the page, open the "Create job" modal from the top right, select "Backup Database" and click "Confirm".
|
|
||||||
A job will run and trigger a backup, you can verify this worked correctly by checking the logs or the backup folder.
|
|
||||||
This backup will count towards the last X backups that will be kept based on your settings.
|
|
||||||
|
|
||||||
#### Restoring
|
#### Restoring
|
||||||
|
|
||||||
We hope to make restoring simpler in future versions, for now you can find the backups in the `UPLOAD_LOCATION/backups` folder on your host.
|
We hope to make restoring simpler in future versions, for now you can find the backups in the `UPLOAD_LOCATION/backups` folder on your host.
|
||||||
@@ -60,7 +53,7 @@ docker compose create # Create Docker containers for Immich apps witho
|
|||||||
docker start immich_postgres # Start Postgres server
|
docker start immich_postgres # Start Postgres server
|
||||||
sleep 10 # Wait for Postgres server to start up
|
sleep 10 # Wait for Postgres server to start up
|
||||||
# Check the database user if you deviated from the default
|
# Check the database user if you deviated from the default
|
||||||
gunzip --stdout "/path/to/backup/dump.sql.gz" \
|
gunzip < "/path/to/backup/dump.sql.gz" \
|
||||||
| sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" \
|
| sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" \
|
||||||
| docker exec -i immich_postgres psql --dbname=postgres --username=<DB_USERNAME> # Restore Backup
|
| docker exec -i immich_postgres psql --dbname=postgres --username=<DB_USERNAME> # Restore Backup
|
||||||
docker compose up -d # Start remainder of Immich apps
|
docker compose up -d # Start remainder of Immich apps
|
||||||
@@ -83,8 +76,8 @@ docker compose create # Create Docker containers for
|
|||||||
docker start immich_postgres # Start Postgres server
|
docker start immich_postgres # Start Postgres server
|
||||||
sleep 10 # Wait for Postgres server to start up
|
sleep 10 # Wait for Postgres server to start up
|
||||||
docker exec -it immich_postgres bash # Enter the Docker shell and run the following command
|
docker exec -it immich_postgres bash # Enter the Docker shell and run the following command
|
||||||
# Check the database user if you deviated from the default. If your backup ends in `.gz`, replace `cat` with `gunzip --stdout`
|
# Check the database user if you deviated from the default. If your backup ends in `.gz`, replace `cat` with `gunzip`
|
||||||
cat "/dump.sql" | sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" | psql --dbname=postgres --username=<DB_USERNAME>
|
cat < "/dump.sql" | sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" | psql --dbname=postgres --username=<DB_USERNAME>
|
||||||
exit # Exit the Docker shell
|
exit # Exit the Docker shell
|
||||||
docker compose up -d # Start remainder of Immich apps
|
docker compose up -d # Start remainder of Immich apps
|
||||||
```
|
```
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 12 KiB |
@@ -11,7 +11,6 @@ The `immich-server` docker image comes preinstalled with an administrative CLI (
|
|||||||
| `enable-oauth-login` | Enable OAuth login |
|
| `enable-oauth-login` | Enable OAuth login |
|
||||||
| `disable-oauth-login` | Disable OAuth login |
|
| `disable-oauth-login` | Disable OAuth login |
|
||||||
| `list-users` | List Immich users |
|
| `list-users` | List Immich users |
|
||||||
| `version` | Print Immich version |
|
|
||||||
|
|
||||||
## How to run a command
|
## How to run a command
|
||||||
|
|
||||||
@@ -81,10 +80,3 @@ immich-admin list-users
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Print Immich Version
|
|
||||||
|
|
||||||
```
|
|
||||||
immich-admin version
|
|
||||||
v1.129.0
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Admin can send a welcome email if the Email option is set, you can learn here ho
|
|||||||
|
|
||||||
Admin can specify the storage quota for the user as the instance's admin; once the limit is reached, the user won't be able to upload to the instance anymore.
|
Admin can specify the storage quota for the user as the instance's admin; once the limit is reached, the user won't be able to upload to the instance anymore.
|
||||||
|
|
||||||
In order to select a storage quota, click on the pencil icon and enter the storage quota in GiB. You can choose an unlimited quota by leaving it empty (default).
|
In order to select a storage quota, click on the pencil icon and enter the storage quota in GiB. You can choose an unlimited quota using the value 0 (default).
|
||||||
|
|
||||||
:::tip
|
:::tip
|
||||||
The system administrator can see the usage quota percentage of all users in Server Stats page.
|
The system administrator can see the usage quota percentage of all users in Server Stats page.
|
||||||
|
|||||||
@@ -63,13 +63,6 @@ If you only want to do web development connected to an existing, remote backend,
|
|||||||
IMMICH_SERVER_URL=https://demo.immich.app/ npm run dev
|
IMMICH_SERVER_URL=https://demo.immich.app/ npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
If you're using PowerShell on Windows you may need to set the env var separately like so:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
$env:IMMICH_SERVER_URL = "https://demo.immich.app/"
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `@immich/ui`
|
#### `@immich/ui`
|
||||||
|
|
||||||
To see local changes to `@immich/ui` in Immich, do the following:
|
To see local changes to `@immich/ui` in Immich, do the following:
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ You begin by authenticating to your Immich server. For instance:
|
|||||||
immich login http://192.168.1.216:2283/api HFEJ38DNSDUEG
|
immich login http://192.168.1.216:2283/api HFEJ38DNSDUEG
|
||||||
```
|
```
|
||||||
|
|
||||||
This will store your credentials in a `auth.yml` file in the configuration directory which defaults to `~/.config/immich/`. The directory can be set with the `-d` option or the environment variable `IMMICH_CONFIG_DIR`. Please keep the file secure, either by performing the logout command after you are done, or deleting it manually.
|
This will store your credentials in a `auth.yml` file in the configuration directory which defaults to `~/.config/`. The directory can be set with the `-d` option or the environment variable `IMMICH_CONFIG_DIR`. Please keep the file secure, either by performing the logout command after you are done, or deleting it manually.
|
||||||
|
|
||||||
Once you are authenticated, you can upload assets to your Immich server.
|
Once you are authenticated, you can upload assets to your Immich server.
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 4.9 MiB After Width: | Height: | Size: 4.9 MiB |
@@ -37,7 +37,7 @@ To validate that Immich can reach your external library, start a shell inside th
|
|||||||
|
|
||||||
### Exclusion Patterns
|
### Exclusion Patterns
|
||||||
|
|
||||||
By default, all files in the import paths will be added to the library. If there are files that should not be added, exclusion patterns can be used to exclude them. Exclusion patterns are glob patterns are matched against the full file path. If a file matches an exclusion pattern, it will not be added to the library. Exclusion patterns can be added in the Scan Settings page for each library.
|
By default, all files in the import paths will be added to the library. If there are files that should not be added, exclusion patterns can be used to exclude them. Exclusion patterns are glob patterns are matched against the full file path. If a file matches an exclusion pattern, it will not be added to the library. Exclusion patterns can be added in the Scan Settings page for each library. Under the hood, Immich uses the [glob](https://www.npmjs.com/package/glob) package to match patterns, so please refer to [their documentation](https://github.com/isaacs/node-glob#glob-primer) to see what patterns are supported.
|
||||||
|
|
||||||
Some basic examples:
|
Some basic examples:
|
||||||
|
|
||||||
@@ -48,11 +48,7 @@ Some basic examples:
|
|||||||
|
|
||||||
Special characters such as @ should be escaped, for instance:
|
Special characters such as @ should be escaped, for instance:
|
||||||
|
|
||||||
- `**/\@eaDir/**` will exclude all files in any directory named `@eaDir`
|
- `**/\@eadir/**` will exclude all files in any directory named `@eadir`
|
||||||
|
|
||||||
:::info
|
|
||||||
Internally, Immich uses the [glob](https://www.npmjs.com/package/glob) package to process exclusion patterns, and sometimes those patterns are translated into [Postgres LIKE patterns](https://www.postgresql.org/docs/current/functions-matching.html). The intention is to support basic folder exclusions but we recommend against advanced usage since those can't reliably be translated to the Postgres syntax. Please refer to the [glob documentation](https://github.com/isaacs/node-glob#glob-primer) for a basic overview on glob patterns.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Automatic watching (EXPERIMENTAL)
|
### Automatic watching (EXPERIMENTAL)
|
||||||
|
|
||||||
@@ -95,7 +91,7 @@ The `immich-server` container will need access to the gallery. Modify your docke
|
|||||||
+ - /mnt/nas/christmas-trip:/mnt/media/christmas-trip:ro
|
+ - /mnt/nas/christmas-trip:/mnt/media/christmas-trip:ro
|
||||||
+ - /home/user/old-pics:/mnt/media/old-pics:ro
|
+ - /home/user/old-pics:/mnt/media/old-pics:ro
|
||||||
+ - /mnt/media/videos:/mnt/media/videos:ro
|
+ - /mnt/media/videos:/mnt/media/videos:ro
|
||||||
+ - /mnt/media/videos2:/mnt/media/videos2 # WARNING: Immich will be able to delete the files in this folder, as it does not end with :ro
|
+ - /mnt/media/videos2:/mnt/media/videos2 # the files in this folder can be deleted, as it does not end with :ro
|
||||||
+ - "C:/Users/user_name/Desktop/my media:/mnt/media/my-media:ro" # import path in Windows system.
|
+ - "C:/Users/user_name/Desktop/my media:/mnt/media/my-media:ro" # import path in Windows system.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
|||||||
- CUDA (NVIDIA GPUs with [compute capability](https://developer.nvidia.com/cuda-gpus) 5.2 or higher)
|
- CUDA (NVIDIA GPUs with [compute capability](https://developer.nvidia.com/cuda-gpus) 5.2 or higher)
|
||||||
- ROCm (AMD GPUs)
|
- ROCm (AMD GPUs)
|
||||||
- OpenVINO (Intel GPUs such as Iris Xe and Arc)
|
- OpenVINO (Intel GPUs such as Iris Xe and Arc)
|
||||||
- RKNN (Rockchip)
|
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
|
|
||||||
@@ -21,7 +20,6 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
|||||||
- Only Linux and Windows (through WSL2) servers are supported.
|
- Only Linux and Windows (through WSL2) servers are supported.
|
||||||
- ARM NN is only supported on devices with Mali GPUs. Other Arm devices are not supported.
|
- ARM NN is only supported on devices with Mali GPUs. Other Arm devices are not supported.
|
||||||
- Some models may not be compatible with certain backends. CUDA is the most reliable.
|
- Some models may not be compatible with certain backends. CUDA is the most reliable.
|
||||||
- Search latency isn't improved by ARM NN due to model compatibility issues preventing its use. However, smart search jobs do make use of ARM NN.
|
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
@@ -36,7 +34,6 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
|||||||
- The `hwaccel.ml.yml` file assumes the path to it is `/usr/lib/libmali.so`, so update accordingly if it is elsewhere
|
- The `hwaccel.ml.yml` file assumes the path to it is `/usr/lib/libmali.so`, so update accordingly if it is elsewhere
|
||||||
- The `hwaccel.ml.yml` file assumes an additional file `/lib/firmware/mali_csffw.bin`, so update accordingly if your device's driver does not require this file
|
- The `hwaccel.ml.yml` file assumes an additional file `/lib/firmware/mali_csffw.bin`, so update accordingly if your device's driver does not require this file
|
||||||
- Optional: Configure your `.env` file, see [environment variables](/docs/install/environment-variables) for ARM NN specific settings
|
- Optional: Configure your `.env` file, see [environment variables](/docs/install/environment-variables) for ARM NN specific settings
|
||||||
- In particular, the `MACHINE_LEARNING_ANN_FP16_TURBO` can significantly improve performance at the cost of very slightly lower accuracy
|
|
||||||
|
|
||||||
#### CUDA
|
#### CUDA
|
||||||
|
|
||||||
@@ -47,9 +44,7 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
|||||||
|
|
||||||
#### ROCm
|
#### ROCm
|
||||||
|
|
||||||
- The GPU must be supported by ROCm. If it isn't officially supported, you can attempt to use the `HSA_OVERRIDE_GFX_VERSION` environmental variable: `HSA_OVERRIDE_GFX_VERSION=<a supported version, e.g. 10.3.0>`. If this doesn't work, you might need to also set `HSA_USE_SVM=0`.
|
- The GPU must be supported by ROCm. If it isn't officially supported, you can attempt to use the `HSA_OVERRIDE_GFX_VERSION` environmental variable: `HSA_OVERRIDE_GFX_VERSION=<a supported version, e.g. 10.3.0>`.
|
||||||
- The ROCm image is quite large and requires at least 35GiB of free disk space. However, pulling later updates to the service through Docker will generally only amount to a few hundred megabytes as the rest will be cached.
|
|
||||||
- This backend is new and may experience some issues. For example, GPU power consumption can be higher than usual after running inference, even if the machine learning service is idle. In this case, it will only go back to normal after being idle for 5 minutes (configurable with the [MACHINE_LEARNING_MODEL_TTL](/docs/install/environment-variables) setting).
|
|
||||||
|
|
||||||
#### OpenVINO
|
#### OpenVINO
|
||||||
|
|
||||||
@@ -57,21 +52,11 @@ You do not need to redo any machine learning jobs after enabling hardware accele
|
|||||||
- Ensure the server's kernel version is new enough to use the device for hardware accceleration.
|
- Ensure the server's kernel version is new enough to use the device for hardware accceleration.
|
||||||
- Expect higher RAM usage when using OpenVINO compared to CPU processing.
|
- Expect higher RAM usage when using OpenVINO compared to CPU processing.
|
||||||
|
|
||||||
#### RKNN
|
|
||||||
|
|
||||||
- You must have a supported Rockchip SoC: only RK3566, RK3568, RK3576 and RK3588 are supported at this moment.
|
|
||||||
- Make sure you have the appropriate linux kernel driver installed
|
|
||||||
- This is usually pre-installed on the device vendor's Linux images
|
|
||||||
- RKNPU driver V0.9.8 or later must be available in the host server
|
|
||||||
- You may confirm this by running `cat /sys/kernel/debug/rknpu/version` to check the version
|
|
||||||
- Optional: Configure your `.env` file, see [environment variables](/docs/install/environment-variables) for RKNN specific settings
|
|
||||||
- In particular, setting `MACHINE_LEARNING_RKNN_THREADS` to 2 or 3 can _dramatically_ improve performance for RK3576 and RK3588 compared to the default of 1, at the expense of multiplying the amount of RAM each model uses by that amount.
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. If you do not already have it, download the latest [`hwaccel.ml.yml`][hw-file] file and ensure it's in the same folder as the `docker-compose.yml`.
|
1. If you do not already have it, download the latest [`hwaccel.ml.yml`][hw-file] file and ensure it's in the same folder as the `docker-compose.yml`.
|
||||||
2. In the `docker-compose.yml` under `immich-machine-learning`, uncomment the `extends` section and change `cpu` to the appropriate backend.
|
2. In the `docker-compose.yml` under `immich-machine-learning`, uncomment the `extends` section and change `cpu` to the appropriate backend.
|
||||||
3. Still in `immich-machine-learning`, add one of -[armnn, cuda, rocm, openvino, rknn] to the `image` section's tag at the end of the line.
|
3. Still in `immich-machine-learning`, add one of -[armnn, cuda, rocm, openvino] to the `image` section's tag at the end of the line.
|
||||||
4. Redeploy the `immich-machine-learning` container with these updated settings.
|
4. Redeploy the `immich-machine-learning` container with these updated settings.
|
||||||
|
|
||||||
### Confirming Device Usage
|
### Confirming Device Usage
|
||||||
@@ -147,12 +132,3 @@ Note that you should increase job concurrencies to increase overall utilization
|
|||||||
- If you encounter an error when a model is running, try a different model to see if the issue is model-specific.
|
- If you encounter an error when a model is running, try a different model to see if the issue is model-specific.
|
||||||
- You may want to increase concurrency past the default for higher utilization. However, keep in mind that this will also increase VRAM consumption.
|
- You may want to increase concurrency past the default for higher utilization. However, keep in mind that this will also increase VRAM consumption.
|
||||||
- Larger models benefit more from hardware acceleration, if you have the VRAM for them.
|
- Larger models benefit more from hardware acceleration, if you have the VRAM for them.
|
||||||
- Compared to ARM NN, RKNPU has:
|
|
||||||
- Wider model support (including for search, which ARM NN does not accelerate)
|
|
||||||
- Less heat generation
|
|
||||||
- Very slightly lower accuracy (RKNPU always uses FP16, while ARM NN by default uses higher precision FP32 unless `MACHINE_LEARNING_ANN_FP16_TURBO` is enabled)
|
|
||||||
- Varying speed (tested on RK3588):
|
|
||||||
- If `MACHINE_LEARNING_RKNN_THREADS` is at the default of 1, RKNPU will have substantially lower throughput for ML jobs than ARM NN in most cases, but similar latency (such as when searching)
|
|
||||||
- If `MACHINE_LEARNING_RKNN_THREADS` is set to 3, it will be somewhat faster than ARM NN at FP32, but somewhat slower than ARM NN if `MACHINE_LEARNING_ANN_FP16_TURBO` is enabled
|
|
||||||
- When other tasks also use the GPU (like transcoding), RKNPU has a significant advantage over ARM NN as it uses the otherwise idle NPU instead of competing for GPU usage
|
|
||||||
- Lower RAM usage if `MACHINE_LEARNING_RKNN_THREADS` is at the default of 1, but significantly higher if greater than 1 (which is necessary for it to fully utilize the NPU and hence be comparable in speed to ARM NN)
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ For the full list, refer to the [Immich source code](https://github.com/immich-a
|
|||||||
| `JPEG 2000` | `.jp2` | :white_check_mark: | |
|
| `JPEG 2000` | `.jp2` | :white_check_mark: | |
|
||||||
| `JPEG` | `.webp` `.jpg` `.jpe` `.insp` | :white_check_mark: | |
|
| `JPEG` | `.webp` `.jpg` `.jpe` `.insp` | :white_check_mark: | |
|
||||||
| `JPEG XL` | `.jxl` | :white_check_mark: | |
|
| `JPEG XL` | `.jxl` | :white_check_mark: | |
|
||||||
| `PNG` | `.png` | :white_check_mark: | |
|
| `PNG` | `.webp` | :white_check_mark: | |
|
||||||
| `PSD` | `.psd` | :white_check_mark: | Adobe Photoshop |
|
| `PSD` | `.psd` | :white_check_mark: | Adobe Photoshop |
|
||||||
| `RAW` | `.raw` | :white_check_mark: | |
|
| `RAW` | `.raw` | :white_check_mark: | |
|
||||||
| `RW2` | `.rw2` | :white_check_mark: | |
|
| `RW2` | `.rw2` | :white_check_mark: | |
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ name: immich_remote_ml
|
|||||||
services:
|
services:
|
||||||
immich-machine-learning:
|
immich-machine-learning:
|
||||||
container_name: immich_machine_learning
|
container_name: immich_machine_learning
|
||||||
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
|
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino] to the image tag.
|
||||||
# Example tag: ${IMMICH_VERSION:-release}-cuda
|
# Example tag: ${IMMICH_VERSION:-release}-cuda
|
||||||
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
|
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
|
||||||
# extends:
|
# extends:
|
||||||
# file: hwaccel.ml.yml
|
# file: hwaccel.ml.yml
|
||||||
# service: # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
|
# service: # set to one of [armnn, cuda, rocm, openvino, openvino-wsl] for accelerated inference - use the `-wsl` version for WSL2 where applicable
|
||||||
volumes:
|
volumes:
|
||||||
- model-cache:/cache
|
- model-cache:/cache
|
||||||
restart: always
|
restart: always
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
---
|
|
||||||
sidebar_position: 100
|
|
||||||
---
|
|
||||||
|
|
||||||
# Config File
|
# Config File
|
||||||
|
|
||||||
A config file can be provided as an alternative to the UI configuration.
|
A config file can be provided as an alternative to the UI configuration.
|
||||||
|
|||||||
@@ -69,7 +69,39 @@ If you get an error `can't set healthcheck.start_interval as feature require Doc
|
|||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
|
||||||
Read the [Post Installation](/docs/install/post-install.mdx) steps and [upgrade instructions](/docs/install/upgrading.md).
|
Read the [Post Installation](/docs/install/post-install.mdx) steps or setup optional features below.
|
||||||
|
|
||||||
|
### Setting up optional features
|
||||||
|
|
||||||
|
- [External Libraries](/docs/features/libraries.md): Adding your existing photo library to Immich
|
||||||
|
- [Hardware Transcoding](/docs/features/hardware-transcoding.md): Speeding up video transcoding
|
||||||
|
- [Hardware-Accelerated Machine Learning](/docs/features/ml-hardware-acceleration.md): Speeding up various machine learning tasks in Immich
|
||||||
|
|
||||||
|
### Upgrading
|
||||||
|
|
||||||
|
:::danger Read the release notes
|
||||||
|
Immich is currently under heavy development, which means you can expect [breaking changes][breaking] and bugs. Therefore, we recommend reading the release notes prior to updating and to take special care when using automated tools like [Watchtower][watchtower].
|
||||||
|
|
||||||
|
You can see versions that had breaking changes [here][breaking].
|
||||||
|
:::
|
||||||
|
|
||||||
|
If `IMMICH_VERSION` is set, it will need to be updated to the latest or desired version.
|
||||||
|
|
||||||
|
When a new version of Immich is [released][releases], the application can be upgraded and restarted with the following commands, run in the directory with the `docker-compose.yml` file:
|
||||||
|
|
||||||
|
```bash title="Upgrade and restart Immich"
|
||||||
|
docker compose pull && docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
To clean up disk space, the old version's obsolete container images can be deleted with the following command:
|
||||||
|
|
||||||
|
```bash title="Clean up unused Docker images"
|
||||||
|
docker image prune
|
||||||
|
```
|
||||||
|
|
||||||
[compose-file]: https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
|
[compose-file]: https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
|
||||||
[env-file]: https://github.com/immich-app/immich/releases/latest/download/example.env
|
[env-file]: https://github.com/immich-app/immich/releases/latest/download/example.env
|
||||||
|
[watchtower]: https://containrrr.dev/watchtower/
|
||||||
|
[breaking]: https://github.com/immich-app/immich/discussions?discussions_q=label%3Achangelog%3Abreaking-change+sort%3Adate_created
|
||||||
|
[container-auth]: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-to-the-container-registry
|
||||||
|
[releases]: https://github.com/immich-app/immich/releases
|
||||||
|
|||||||
@@ -170,8 +170,6 @@ Redis (Sentinel) URL example JSON before encoding:
|
|||||||
| `MACHINE_LEARNING_MAX_BATCH_SIZE__FACIAL_RECOGNITION` | Set the maximum number of faces that will be processed at once by the facial recognition model | None (`1` if using OpenVINO) | machine learning |
|
| `MACHINE_LEARNING_MAX_BATCH_SIZE__FACIAL_RECOGNITION` | Set the maximum number of faces that will be processed at once by the facial recognition model | None (`1` if using OpenVINO) | machine learning |
|
||||||
| `MACHINE_LEARNING_PING_TIMEOUT` | How long (ms) to wait for a PING response when checking if an ML server is available | `2000` | server |
|
| `MACHINE_LEARNING_PING_TIMEOUT` | How long (ms) to wait for a PING response when checking if an ML server is available | `2000` | server |
|
||||||
| `MACHINE_LEARNING_AVAILABILITY_BACKOFF_TIME` | How long to ignore ML servers that are offline before trying again | `30000` | server |
|
| `MACHINE_LEARNING_AVAILABILITY_BACKOFF_TIME` | How long to ignore ML servers that are offline before trying again | `30000` | server |
|
||||||
| `MACHINE_LEARNING_RKNN` | Enable RKNN hardware acceleration if supported | `True` | machine learning |
|
|
||||||
| `MACHINE_LEARNING_RKNN_THREADS` | How many threads of RKNN runtime should be spinned up while inferencing. | `1` | machine learning |
|
|
||||||
|
|
||||||
\*1: It is recommended to begin with this parameter when changing the concurrency levels of the machine learning service and then tune the other ones.
|
\*1: It is recommended to begin with this parameter when changing the concurrency levels of the machine learning service and then tune the other ones.
|
||||||
|
|
||||||
|
|||||||
@@ -41,9 +41,3 @@ A list of common steps to take after installing Immich include:
|
|||||||
## Step 7 - Setup Server Backups
|
## Step 7 - Setup Server Backups
|
||||||
|
|
||||||
<ServerBackup />
|
<ServerBackup />
|
||||||
|
|
||||||
## Setting up optional features
|
|
||||||
|
|
||||||
- [External Libraries](/docs/features/libraries.md): Adding your existing photo library to Immich
|
|
||||||
- [Hardware Transcoding](/docs/features/hardware-transcoding.md): Speeding up video transcoding
|
|
||||||
- [Hardware-Accelerated Machine Learning](/docs/features/ml-hardware-acceleration.md): Speeding up various machine learning tasks in Immich
|
|
||||||
|
|||||||
@@ -67,4 +67,10 @@ Click "**Edit Rules**" and add the following firewall rules:
|
|||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
|
||||||
Read the [Post Installation](/docs/install/post-install.mdx) steps and [upgrade instructions](/docs/install/upgrading.md).
|
Read the [Post Installation](/docs/install/post-install.mdx) steps or setup optional features below.
|
||||||
|
|
||||||
|
### Setting up optional features
|
||||||
|
|
||||||
|
- [External Libraries](/docs/features/libraries.md): Adding your existing photo library to Immich
|
||||||
|
- [Hardware Transcoding](/docs/features/hardware-transcoding.md): Speeding up video transcoding
|
||||||
|
- [Hardware-Accelerated Machine Learning](/docs/features/ml-hardware-acceleration.md): Speeding up various machine learning tasks in Immich
|
||||||
|
|||||||
@@ -247,10 +247,6 @@ Some examples are: `IMMICH_VERSION`, `UPLOAD_LOCATION`, `DB_DATA_LOCATION`, `TZ`
|
|||||||
|
|
||||||
## Updating the App
|
## Updating the App
|
||||||
|
|
||||||
:::danger
|
|
||||||
Make sure to read the general [upgrade instructions](/docs/install/upgrading.md).
|
|
||||||
:::
|
|
||||||
|
|
||||||
When updates become available, SCALE alerts and provides easy updates.
|
When updates become available, SCALE alerts and provides easy updates.
|
||||||
To update the app to the latest version:
|
To update the app to the latest version:
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ alt="Select Plugins > Compose.Manager > Add New Stack > Label it Immich"
|
|||||||
7. Paste the entire contents of the [Immich example.env](https://github.com/immich-app/immich/releases/latest/download/example.env) file into the Unraid editor, then **before saving** edit the following:
|
7. Paste the entire contents of the [Immich example.env](https://github.com/immich-app/immich/releases/latest/download/example.env) file into the Unraid editor, then **before saving** edit the following:
|
||||||
|
|
||||||
- `UPLOAD_LOCATION`: Create a folder in your Images Unraid share and place the **absolute** location here > For example my _"images"_ share has a folder within it called _"immich"_. If I browse to this directory in the terminal and type `pwd` the output is `/mnt/user/images/immich`. This is the exact value I need to enter as my `UPLOAD_LOCATION`
|
- `UPLOAD_LOCATION`: Create a folder in your Images Unraid share and place the **absolute** location here > For example my _"images"_ share has a folder within it called _"immich"_. If I browse to this directory in the terminal and type `pwd` the output is `/mnt/user/images/immich`. This is the exact value I need to enter as my `UPLOAD_LOCATION`
|
||||||
- `DB_DATA_LOCATION`: Change this to use an Unraid share (preferably a cache pool, e.g. `/mnt/user/appdata/postgresql/data`). This uses the `appdata` share. Do also create the `postgresql` folder, by running `mkdir /mnt/user/{share_location}/postgresql/data`. If left at default it will try to use Unraid's `/boot/config/plugins/compose.manager/projects/[stack_name]/postgres` folder which it doesn't have permissions to, resulting in this container continuously restarting.
|
- `DB_DATA_LOCATION`: Change this to use an Unraid share (preferably a cache pool, e.g. `/mnt/user/appdata`). If left at default it will try to use Unraid's `/boot/config/plugins/compose.manager/projects/[stack_name]/postgres` folder which it doesn't have permissions to, resulting in this container continuously restarting.
|
||||||
|
|
||||||
<img
|
<img
|
||||||
src={require('./img/unraid05.webp').default}
|
src={require('./img/unraid05.webp').default}
|
||||||
@@ -131,10 +131,6 @@ For more information on how to use the application once installed, please refer
|
|||||||
|
|
||||||
## Updating Steps
|
## Updating Steps
|
||||||
|
|
||||||
:::danger
|
|
||||||
Make sure to read the general [upgrade instructions](/docs/install/upgrading.md).
|
|
||||||
:::
|
|
||||||
|
|
||||||
Updating is extremely easy however it's important to be aware that containers managed via the Docker Compose Manager plugin do not integrate with Unraid's native dockerman UI, the label "_update ready_" will always be present on containers installed via the Docker Compose Manager.
|
Updating is extremely easy however it's important to be aware that containers managed via the Docker Compose Manager plugin do not integrate with Unraid's native dockerman UI, the label "_update ready_" will always be present on containers installed via the Docker Compose Manager.
|
||||||
|
|
||||||
<img
|
<img
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
---
|
|
||||||
sidebar_position: 95
|
|
||||||
---
|
|
||||||
|
|
||||||
# Upgrading
|
|
||||||
|
|
||||||
:::danger Read the release notes
|
|
||||||
Immich is currently under heavy development, which means you can expect [breaking changes][breaking] and bugs. You should read the release notes prior to updating and take special care when using automated tools like [Watchtower][watchtower].
|
|
||||||
|
|
||||||
You can see versions that had breaking changes [here][breaking].
|
|
||||||
:::
|
|
||||||
|
|
||||||
When a new version of Immich is [released][releases], you should read the release notes and account for any breaking changes noted (as mentioned above).
|
|
||||||
If you use `IMMICH_VERSION` in your `.env` file, it will need to be updated to the latest or desired version.
|
|
||||||
After that, the application can be upgraded and restarted with the following commands, run in the directory with the `docker-compose.yml` file:
|
|
||||||
|
|
||||||
```bash title="Upgrade and restart Immich"
|
|
||||||
docker compose pull && docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
To clean up disk space, the old version's obsolete container images can be deleted with the following command:
|
|
||||||
|
|
||||||
```bash title="Clean up unused Docker images"
|
|
||||||
docker image prune
|
|
||||||
```
|
|
||||||
|
|
||||||
[watchtower]: https://containrrr.dev/watchtower/
|
|
||||||
[breaking]: https://github.com/immich-app/immich/discussions?discussions_q=label%3Achangelog%3Abreaking-change+sort%3Adate_created
|
|
||||||
[releases]: https://github.com/immich-app/immich/releases
|
|
||||||
@@ -1,7 +1,2 @@
|
|||||||
Now that you have imported some pictures, you should setup server backups to preserve your memories.
|
Now that you have imported some pictures, you should setup server backups to preserve your memories.
|
||||||
You can do so by following our [backup guide](/docs/administration/backup-and-restore.md).
|
You can do so by following our [backup guide](/docs/administration/backup-and-restore.md).
|
||||||
|
|
||||||
:::danger
|
|
||||||
Immich is still under heavy development _and_ handles very important data.
|
|
||||||
It is essential that you set up good backups, and test them.
|
|
||||||
:::
|
|
||||||
|
|||||||
30
docs/package-lock.json
generated
30
docs/package-lock.json
generated
@@ -5308,9 +5308,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/autoprefixer": {
|
"node_modules/autoprefixer": {
|
||||||
"version": "10.4.21",
|
"version": "10.4.20",
|
||||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
|
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
|
||||||
"integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==",
|
"integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -5327,11 +5327,11 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"browserslist": "^4.24.4",
|
"browserslist": "^4.23.3",
|
||||||
"caniuse-lite": "^1.0.30001702",
|
"caniuse-lite": "^1.0.30001646",
|
||||||
"fraction.js": "^4.3.7",
|
"fraction.js": "^4.3.7",
|
||||||
"normalize-range": "^0.1.2",
|
"normalize-range": "^0.1.2",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.0.1",
|
||||||
"postcss-value-parser": "^4.2.0"
|
"postcss-value-parser": "^4.2.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -5781,9 +5781,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001706",
|
"version": "1.0.30001695",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz",
|
||||||
"integrity": "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==",
|
"integrity": "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -15734,9 +15734,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prettier": {
|
"node_modules/prettier": {
|
||||||
"version": "3.5.3",
|
"version": "3.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz",
|
||||||
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
|
"integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -18377,9 +18377,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "5.8.2",
|
"version": "5.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
|
||||||
"integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
|
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
export const discordPath =
|
export const discordPath =
|
||||||
'M81.15,0c-1.2376,2.1973-2.3489,4.4704-3.3591,6.794-9.5975-1.4396-19.3718-1.4396-28.9945,0-.985-2.3236-2.1216-4.5967-3.3591-6.794-9.0166,1.5407-17.8059,4.2431-26.1405,8.0568C2.779,32.5304-1.6914,56.3725.5312,79.8863c9.6732,7.1476,20.5083,12.603,32.0505,16.0884,2.6014-3.4854,4.8998-7.1981,6.8698-11.0623-3.738-1.3891-7.3497-3.1318-10.8098-5.1523.9092-.6567,1.7932-1.3386,2.6519-1.9953,20.281,9.547,43.7696,9.547,64.0758,0,.8587.7072,1.7427,1.3891,2.6519,1.9953-3.4601,2.0457-7.0718,3.7632-10.835,5.1776,1.97,3.8642,4.2683,7.5769,6.8698,11.0623,11.5419-3.4854,22.3769-8.9156,32.0509-16.0631,2.626-27.2771-4.496-50.9172-18.817-71.8548C98.9811,4.2684,90.1918,1.5659,81.1752.0505l-.0252-.0505ZM42.2802,65.4144c-6.2383,0-11.4159-5.6575-11.4159-12.6535s4.9755-12.6788,11.3907-12.6788,11.5169,5.708,11.4159,12.6788c-.101,6.9708-5.026,12.6535-11.3907,12.6535ZM84.3576,65.4144c-6.2637,0-11.3907-5.6575-11.3907-12.6535s4.9755-12.6788,11.3907-12.6788,11.4917,5.708,11.3906,12.6788c-.101,6.9708-5.026,12.6535-11.3906,12.6535Z';
|
'M 9.1367188 3.8691406 C 9.1217187 3.8691406 9.1067969 3.8700938 9.0917969 3.8710938 C 8.9647969 3.8810937 5.9534375 4.1403594 4.0234375 5.6933594 C 3.0154375 6.6253594 1 12.073203 1 16.783203 C 1 16.866203 1.0215 16.946531 1.0625 17.019531 C 2.4535 19.462531 6.2473281 20.102859 7.1113281 20.130859 L 7.1269531 20.130859 C 7.2799531 20.130859 7.4236719 20.057594 7.5136719 19.933594 L 8.3886719 18.732422 C 6.0296719 18.122422 4.8248594 17.086391 4.7558594 17.025391 C 4.5578594 16.850391 4.5378906 16.549563 4.7128906 16.351562 C 4.8068906 16.244563 4.9383125 16.189453 5.0703125 16.189453 C 5.1823125 16.189453 5.2957188 16.228594 5.3867188 16.308594 C 5.4157187 16.334594 7.6340469 18.216797 11.998047 18.216797 C 16.370047 18.216797 18.589328 16.325641 18.611328 16.306641 C 18.702328 16.227641 18.815734 16.189453 18.927734 16.189453 C 19.059734 16.189453 19.190156 16.243562 19.285156 16.351562 C 19.459156 16.549563 19.441141 16.851391 19.244141 17.025391 C 19.174141 17.087391 17.968375 18.120469 15.609375 18.730469 L 16.484375 19.933594 C 16.574375 20.057594 16.718094 20.130859 16.871094 20.130859 L 16.886719 20.130859 C 17.751719 20.103859 21.5465 19.463531 22.9375 17.019531 C 22.9785 16.947531 23 16.866203 23 16.783203 C 23 12.073203 20.984172 6.624875 19.951172 5.671875 C 18.047172 4.140875 15.036203 3.8820937 14.908203 3.8710938 C 14.895203 3.8700938 14.880188 3.8691406 14.867188 3.8691406 C 14.681188 3.8691406 14.510594 3.9793906 14.433594 4.1503906 C 14.427594 4.1623906 14.362062 4.3138281 14.289062 4.5488281 C 15.548063 4.7608281 17.094141 5.1895937 18.494141 6.0585938 C 18.718141 6.1975938 18.787437 6.4917969 18.648438 6.7167969 C 18.558438 6.8627969 18.402188 6.9433594 18.242188 6.9433594 C 18.156188 6.9433594 18.069234 6.9200937 17.990234 6.8710938 C 15.584234 5.3800938 12.578 5.3046875 12 5.3046875 C 11.422 5.3046875 8.4157187 5.3810469 6.0117188 6.8730469 C 5.9327188 6.9210469 5.8457656 6.9433594 5.7597656 6.9433594 C 5.5997656 6.9433594 5.4425625 6.86475 5.3515625 6.71875 C 5.2115625 6.49375 5.2818594 6.1985938 5.5058594 6.0585938 C 6.9058594 5.1905937 8.4528906 4.7627812 9.7128906 4.5507812 C 9.6388906 4.3147813 9.5714062 4.1643437 9.5664062 4.1523438 C 9.4894063 3.9813438 9.3217188 3.8691406 9.1367188 3.8691406 z M 12 7.3046875 C 12.296 7.3046875 14.950594 7.3403125 16.933594 8.5703125 C 17.326594 8.8143125 17.777234 8.9453125 18.240234 8.9453125 C 18.633234 8.9453125 19.010656 8.8555 19.347656 8.6875 C 19.964656 10.2405 20.690828 12.686219 20.923828 15.199219 C 20.883828 15.143219 20.840922 15.089109 20.794922 15.037109 C 20.324922 14.498109 19.644687 14.191406 18.929688 14.191406 C 18.332687 14.191406 17.754078 14.405437 17.330078 14.773438 C 17.257078 14.832437 15.505 16.21875 12 16.21875 C 8.496 16.21875 6.7450313 14.834687 6.7070312 14.804688 C 6.2540312 14.407687 5.6742656 14.189453 5.0722656 14.189453 C 4.3612656 14.189453 3.6838438 14.494391 3.2148438 15.025391 C 3.1658438 15.080391 3.1201719 15.138266 3.0761719 15.197266 C 3.3091719 12.686266 4.0344375 10.235594 4.6484375 8.6835938 C 4.9864375 8.8525938 5.3657656 8.9433594 5.7597656 8.9433594 C 6.2217656 8.9433594 6.6724531 8.8143125 7.0644531 8.5703125 C 9.0494531 7.3393125 11.704 7.3046875 12 7.3046875 z M 8.890625 10.044922 C 7.966625 10.044922 7.2167969 10.901031 7.2167969 11.957031 C 7.2167969 13.013031 7.965625 13.869141 8.890625 13.869141 C 9.815625 13.869141 10.564453 13.013031 10.564453 11.957031 C 10.564453 10.900031 9.815625 10.044922 8.890625 10.044922 z M 15.109375 10.044922 C 14.185375 10.044922 13.435547 10.901031 13.435547 11.957031 C 13.435547 13.013031 14.184375 13.869141 15.109375 13.869141 C 16.034375 13.869141 16.783203 13.013031 16.783203 11.957031 C 16.783203 10.900031 16.033375 10.044922 15.109375 10.044922 z';
|
||||||
export const discordViewBox = '0 0 126.644 96';
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import React, { useEffect, useState } from 'react';
|
|||||||
|
|
||||||
export default function VersionSwitcher(): JSX.Element {
|
export default function VersionSwitcher(): JSX.Element {
|
||||||
const [versions, setVersions] = useState([]);
|
const [versions, setVersions] = useState([]);
|
||||||
const [activeLabel, setLabel] = useState('Versions');
|
const [label, setLabel] = useState('Versions');
|
||||||
|
|
||||||
const windowSize = useWindowSize();
|
const windowSize = useWindowSize();
|
||||||
|
|
||||||
@@ -48,13 +48,12 @@ export default function VersionSwitcher(): JSX.Element {
|
|||||||
versions.length > 0 && (
|
versions.length > 0 && (
|
||||||
<DropdownNavbarItem
|
<DropdownNavbarItem
|
||||||
className="version-switcher-34ab39"
|
className="version-switcher-34ab39"
|
||||||
label={activeLabel}
|
label={label}
|
||||||
mobile={windowSize === 'mobile'}
|
mobile={windowSize === 'mobile'}
|
||||||
items={versions.map(({ label, url }) => ({
|
items={versions.map(({ label, url }) => ({
|
||||||
label,
|
label,
|
||||||
to: new URL(location.pathname + location.search + location.hash, url).href,
|
to: new URL(location.pathname + location.search + location.hash, url).href,
|
||||||
target: '_self',
|
target: '_self',
|
||||||
className: label === activeLabel ? 'dropdown__link--active menu__link--active' : '', // workaround because React Router `<NavLink>` only supports using URL path for checking if active: https://v5.reactrouter.com/web/api/NavLink/isactive-func
|
|
||||||
}))}
|
}))}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
import Layout from '@theme/Layout';
|
import Layout from '@theme/Layout';
|
||||||
import { discordPath, discordViewBox } from '@site/src/components/svg-paths';
|
import { useColorMode } from '@docusaurus/theme-common';
|
||||||
import ThemedImage from '@theme/ThemedImage';
|
import { discordPath } from '@site/src/components/svg-paths';
|
||||||
import Icon from '@mdi/react';
|
import Icon from '@mdi/react';
|
||||||
function HomepageHeader() {
|
function HomepageHeader() {
|
||||||
|
const { isDarkTheme } = useColorMode();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header>
|
<header>
|
||||||
<div className="top-[calc(12%)] md:top-[calc(30%)] h-screen w-full absolute -z-10">
|
<div className="top-[calc(12%)] md:top-[calc(30%)] h-screen w-full absolute -z-10">
|
||||||
@@ -12,8 +14,8 @@ function HomepageHeader() {
|
|||||||
<div className="w-full h-[120vh] absolute left-0 top-0 backdrop-blur-3xl bg-immich-bg/40 dark:bg-transparent"></div>
|
<div className="w-full h-[120vh] absolute left-0 top-0 backdrop-blur-3xl bg-immich-bg/40 dark:bg-transparent"></div>
|
||||||
</div>
|
</div>
|
||||||
<section className="text-center pt-12 sm:pt-24 bg-immich-bg/50 dark:bg-immich-dark-bg/80">
|
<section className="text-center pt-12 sm:pt-24 bg-immich-bg/50 dark:bg-immich-dark-bg/80">
|
||||||
<ThemedImage
|
<img
|
||||||
sources={{ dark: 'img/logomark-dark.svg', light: 'img/logomark-light.svg' }}
|
src={isDarkTheme ? 'img/logomark-dark.svg' : 'img/logomark-light.svg'}
|
||||||
className="h-[115px] w-[115px] mb-2 antialiased rounded-none"
|
className="h-[115px] w-[115px] mb-2 antialiased rounded-none"
|
||||||
alt="Immich logo"
|
alt="Immich logo"
|
||||||
/>
|
/>
|
||||||
@@ -33,6 +35,7 @@ function HomepageHeader() {
|
|||||||
sacrificing your privacy.
|
sacrificing your privacy.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col sm:flex-row place-items-center place-content-center mt-9 gap-4 ">
|
<div className="flex flex-col sm:flex-row place-items-center place-content-center mt-9 gap-4 ">
|
||||||
<Link
|
<Link
|
||||||
className="flex place-items-center place-content-center py-3 px-8 border bg-immich-primary dark:bg-immich-dark-primary rounded-xl no-underline hover:no-underline text-white hover:text-gray-50 dark:text-immich-dark-bg font-bold uppercase"
|
className="flex place-items-center place-content-center py-3 px-8 border bg-immich-primary dark:bg-immich-dark-primary rounded-xl no-underline hover:no-underline text-white hover:text-gray-50 dark:text-immich-dark-bg font-bold uppercase"
|
||||||
@@ -55,27 +58,27 @@ function HomepageHeader() {
|
|||||||
Buy Merch
|
Buy Merch
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="my-12 flex gap-1 font-medium place-items-center place-content-center text-immich-primary dark:text-immich-dark-primary">
|
<div className="my-12 flex gap-1 font-medium place-items-center place-content-center text-immich-primary dark:text-immich-dark-primary">
|
||||||
<Icon
|
<Icon path={discordPath} size={1} />
|
||||||
path={discordPath}
|
|
||||||
viewBox={discordViewBox} /* viewBox may show an error in your IDE but it is normal. */
|
|
||||||
size={1}
|
|
||||||
/>
|
|
||||||
<Link to="https://discord.immich.app/">Join our Discord</Link>
|
<Link to="https://discord.immich.app/">Join our Discord</Link>
|
||||||
</div>
|
</div>
|
||||||
<ThemedImage
|
<img
|
||||||
sources={{ dark: '/img/screenshot-dark.webp', light: '/img/screenshot-light.webp' }}
|
src={isDarkTheme ? '/img/screenshot-dark.webp' : '/img/screenshot-light.webp'}
|
||||||
alt="screenshots"
|
alt="screenshots"
|
||||||
className="w-[95%] lg:w-[85%] xl:w-[70%] 2xl:w-[60%] "
|
className="w-[95%] lg:w-[85%] xl:w-[70%] 2xl:w-[60%] "
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="mx-[25%] m-auto my-14 md:my-28">
|
<div className="mx-[25%] m-auto my-14 md:my-28">
|
||||||
<hr className="border bg-gray-500 dark:bg-gray-400" />
|
<hr className="border bg-gray-500 dark:bg-gray-400" />
|
||||||
</div>
|
</div>
|
||||||
<ThemedImage
|
|
||||||
sources={{ dark: 'img/logomark-dark.svg', light: 'img/logomark-light.svg' }}
|
<img
|
||||||
|
src={isDarkTheme ? 'img/logomark-dark.svg' : 'img/logomark-light.svg'}
|
||||||
className="h-[115px] w-[115px] mb-2 antialiased rounded-none"
|
className="h-[115px] w-[115px] mb-2 antialiased rounded-none"
|
||||||
alt="Immich logo"
|
alt="Immich logo"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p className="font-bold text-2xl md:text-5xl ">Download the mobile app</p>
|
<p className="font-bold text-2xl md:text-5xl ">Download the mobile app</p>
|
||||||
<p className="text-lg">
|
<p className="text-lg">
|
||||||
@@ -94,8 +97,9 @@ function HomepageHeader() {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ThemedImage
|
|
||||||
sources={{ dark: '/img/app-qr-code-dark.svg', light: '/img/app-qr-code-light.svg' }}
|
<img
|
||||||
|
src={isDarkTheme ? '/img/app-qr-code-dark.svg' : '/img/app-qr-code-light.svg'}
|
||||||
alt="app qr code"
|
alt="app qr code"
|
||||||
width={'150px'}
|
width={'150px'}
|
||||||
className="shadow-lg p-3 my-8 dark:bg-immich-dark-bg "
|
className="shadow-lg p-3 my-8 dark:bg-immich-dark-bg "
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
import Layout from '@theme/Layout';
|
import Layout from '@theme/Layout';
|
||||||
|
import { useColorMode } from '@docusaurus/theme-common';
|
||||||
function HomepageHeader() {
|
function HomepageHeader() {
|
||||||
|
const { isDarkTheme } = useColorMode();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header>
|
<header>
|
||||||
<section className="max-w-[900px] m-4 p-4 md:p-6 md:m-auto md:my-12 border border-red-400 rounded-2xl bg-slate-200 dark:bg-immich-dark-gray">
|
<section className="max-w-[900px] m-4 p-4 md:p-6 md:m-auto md:my-12 border border-red-400 rounded-2xl bg-slate-200 dark:bg-immich-dark-gray">
|
||||||
|
|||||||
@@ -242,13 +242,6 @@ const roadmap: Item[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const milestones: Item[] = [
|
const milestones: Item[] = [
|
||||||
{
|
|
||||||
icon: mdiStar,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: '60,000 Stars',
|
|
||||||
description: 'Reached 60K Stars on GitHub!',
|
|
||||||
getDateLabel: withLanguage(new Date(2025, 2, 4)),
|
|
||||||
},
|
|
||||||
withRelease({
|
withRelease({
|
||||||
icon: mdiLinkEdit,
|
icon: mdiLinkEdit,
|
||||||
iconColor: 'crimson',
|
iconColor: 'crimson',
|
||||||
|
|||||||
36
docs/static/archived-versions.json
vendored
36
docs/static/archived-versions.json
vendored
@@ -1,40 +1,4 @@
|
|||||||
[
|
[
|
||||||
{
|
|
||||||
"label": "v1.131.3",
|
|
||||||
"url": "https://v1.131.3.archive.immich.app"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "v1.131.2",
|
|
||||||
"url": "https://v1.131.2.archive.immich.app"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "v1.131.1",
|
|
||||||
"url": "https://v1.131.1.archive.immich.app"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "v1.131.0",
|
|
||||||
"url": "https://v1.131.0.archive.immich.app"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "v1.130.3",
|
|
||||||
"url": "https://v1.130.3.archive.immich.app"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "v1.130.2",
|
|
||||||
"url": "https://v1.130.2.archive.immich.app"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "v1.130.1",
|
|
||||||
"url": "https://v1.130.1.archive.immich.app"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "v1.130.0",
|
|
||||||
"url": "https://v1.130.0.archive.immich.app"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "v1.129.0",
|
|
||||||
"url": "https://v1.129.0.archive.immich.app"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"label": "v1.128.0",
|
"label": "v1.128.0",
|
||||||
"url": "https://v1.128.0.archive.immich.app"
|
"url": "https://v1.128.0.archive.immich.app"
|
||||||
|
|||||||
@@ -1,29 +1,39 @@
|
|||||||
|
import { FlatCompat } from '@eslint/eslintrc';
|
||||||
import js from '@eslint/js';
|
import js from '@eslint/js';
|
||||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
import typescriptEslint from '@typescript-eslint/eslint-plugin';
|
||||||
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
|
import tsParser from '@typescript-eslint/parser';
|
||||||
import globals from 'globals';
|
import globals from 'globals';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import typescriptEslint from 'typescript-eslint';
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
recommendedConfig: js.configs.recommended,
|
||||||
|
allConfig: js.configs.all,
|
||||||
|
});
|
||||||
|
|
||||||
export default typescriptEslint.config([
|
export default [
|
||||||
eslintPluginUnicorn.configs.recommended,
|
|
||||||
eslintPluginPrettierRecommended,
|
|
||||||
js.configs.recommended,
|
|
||||||
typescriptEslint.configs.recommended,
|
|
||||||
{
|
{
|
||||||
ignores: ['eslint.config.mjs'],
|
ignores: ['eslint.config.mjs'],
|
||||||
},
|
},
|
||||||
|
...compat.extends(
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:prettier/recommended',
|
||||||
|
'plugin:unicorn/recommended',
|
||||||
|
),
|
||||||
{
|
{
|
||||||
|
plugins: {
|
||||||
|
'@typescript-eslint': typescriptEslint,
|
||||||
|
},
|
||||||
|
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
globals: {
|
globals: {
|
||||||
...globals.node,
|
...globals.node,
|
||||||
},
|
},
|
||||||
|
|
||||||
parser: typescriptEslint.parser,
|
parser: tsParser,
|
||||||
ecmaVersion: 5,
|
ecmaVersion: 5,
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
|
|
||||||
@@ -52,4 +62,4 @@ export default typescriptEslint.config([
|
|||||||
'object-shorthand': ['error', 'always'],
|
'object-shorthand': ['error', 'always'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
];
|
||||||
|
|||||||
1507
e2e/package-lock.json
generated
1507
e2e/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.131.3",
|
"version": "1.128.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -25,16 +25,18 @@
|
|||||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||||
"@playwright/test": "^1.44.1",
|
"@playwright/test": "^1.44.1",
|
||||||
"@types/luxon": "^3.4.2",
|
"@types/luxon": "^3.4.2",
|
||||||
"@types/node": "^22.14.0",
|
"@types/node": "^22.13.5",
|
||||||
"@types/oidc-provider": "^8.5.1",
|
"@types/oidc-provider": "^8.5.1",
|
||||||
"@types/pg": "^8.11.0",
|
"@types/pg": "^8.11.0",
|
||||||
"@types/pngjs": "^6.0.4",
|
"@types/pngjs": "^6.0.4",
|
||||||
"@types/supertest": "^6.0.2",
|
"@types/supertest": "^6.0.2",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
||||||
|
"@typescript-eslint/parser": "^8.15.0",
|
||||||
"@vitest/coverage-v8": "^3.0.0",
|
"@vitest/coverage-v8": "^3.0.0",
|
||||||
"eslint": "^9.14.0",
|
"eslint": "^9.14.0",
|
||||||
"eslint-config-prettier": "^10.0.0",
|
"eslint-config-prettier": "^10.0.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-unicorn": "^57.0.0",
|
"eslint-plugin-unicorn": "^56.0.1",
|
||||||
"exiftool-vendored": "^28.3.1",
|
"exiftool-vendored": "^28.3.1",
|
||||||
"globals": "^16.0.0",
|
"globals": "^16.0.0",
|
||||||
"jose": "^5.6.3",
|
"jose": "^5.6.3",
|
||||||
@@ -47,7 +49,6 @@
|
|||||||
"socket.io-client": "^4.7.4",
|
"socket.io-client": "^4.7.4",
|
||||||
"supertest": "^7.0.0",
|
"supertest": "^7.0.0",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"typescript-eslint": "^8.28.0",
|
|
||||||
"utimes": "^5.2.1",
|
"utimes": "^5.2.1",
|
||||||
"vitest": "^3.0.0"
|
"vitest": "^3.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1141,7 +1141,7 @@ describe('/asset', () => {
|
|||||||
fNumber: 8,
|
fNumber: 8,
|
||||||
focalLength: 97,
|
focalLength: 97,
|
||||||
iso: 100,
|
iso: 100,
|
||||||
lensModel: 'Sony E PZ 18-105mm F4 G OSS',
|
lensModel: 'E PZ 18-105mm F4 G OSS',
|
||||||
fileSizeInByte: 25_001_984,
|
fileSizeInByte: 25_001_984,
|
||||||
dateTimeOriginal: '2016-09-27T10:51:44+00:00',
|
dateTimeOriginal: '2016-09-27T10:51:44+00:00',
|
||||||
orientation: '1',
|
orientation: '1',
|
||||||
@@ -1163,7 +1163,7 @@ describe('/asset', () => {
|
|||||||
fNumber: 22,
|
fNumber: 22,
|
||||||
focalLength: 25,
|
focalLength: 25,
|
||||||
iso: 100,
|
iso: 100,
|
||||||
lensModel: 'Zeiss Batis 25mm F2',
|
lensModel: 'E 25mm F2',
|
||||||
fileSizeInByte: 49_512_448,
|
fileSizeInByte: 49_512_448,
|
||||||
dateTimeOriginal: '2016-01-08T14:08:01+00:00',
|
dateTimeOriginal: '2016-01-08T14:08:01+00:00',
|
||||||
orientation: '1',
|
orientation: '1',
|
||||||
@@ -1234,7 +1234,7 @@ describe('/asset', () => {
|
|||||||
focalLength: 18.3,
|
focalLength: 18.3,
|
||||||
iso: 100,
|
iso: 100,
|
||||||
latitude: 36.613_24,
|
latitude: 36.613_24,
|
||||||
lensModel: '18.3mm F2.8',
|
lensModel: 'GR LENS 18.3mm F2.8',
|
||||||
longitude: -121.897_85,
|
longitude: -121.897_85,
|
||||||
make: 'RICOH IMAGING COMPANY, LTD.',
|
make: 'RICOH IMAGING COMPANY, LTD.',
|
||||||
model: 'RICOH GR III',
|
model: 'RICOH GR III',
|
||||||
@@ -1257,7 +1257,6 @@ describe('/asset', () => {
|
|||||||
|
|
||||||
for (const { id, status } of assets) {
|
for (const { id, status } of assets) {
|
||||||
expect(status).toBe(AssetMediaStatus.Created);
|
expect(status).toBe(AssetMediaStatus.Created);
|
||||||
// longer timeout as the thumbnail generation from full-size raw files can take a while
|
|
||||||
await utils.waitForWebsocketEvent({ event: 'assetUpload', id });
|
await utils.waitForWebsocketEvent({ event: 'assetUpload', id });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ describe('/libraries', () => {
|
|||||||
const library = await utils.createLibrary(admin.accessToken, {
|
const library = await utils.createLibrary(admin.accessToken, {
|
||||||
ownerId: admin.userId,
|
ownerId: admin.userId,
|
||||||
importPaths: [`${testAssetDirInternal}/temp`],
|
importPaths: [`${testAssetDirInternal}/temp`],
|
||||||
exclusionPatterns: ['**/directoryA/**'],
|
exclusionPatterns: ['**/directoryA'],
|
||||||
});
|
});
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
await utils.scan(admin.accessToken, library.id);
|
||||||
@@ -337,82 +337,7 @@ describe('/libraries', () => {
|
|||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
||||||
|
|
||||||
expect(assets.count).toBe(1);
|
expect(assets.count).toBe(1);
|
||||||
|
expect(assets.items[0].originalPath.includes('directoryB'));
|
||||||
expect(assets.items).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining('directoryB/assetB.png') }),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should scan external library with multiple exclusion patterns', async () => {
|
|
||||||
const library = await utils.createLibrary(admin.accessToken, {
|
|
||||||
ownerId: admin.userId,
|
|
||||||
importPaths: [`${testAssetDirInternal}/temp`],
|
|
||||||
exclusionPatterns: ['**/directoryA/**', '**/directoryB/**'],
|
|
||||||
});
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.count).toBe(0);
|
|
||||||
|
|
||||||
expect(assets.items).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove assets covered by a new exclusion pattern', async () => {
|
|
||||||
const library = await utils.createLibrary(admin.accessToken, {
|
|
||||||
ownerId: admin.userId,
|
|
||||||
importPaths: [`${testAssetDirInternal}/temp`],
|
|
||||||
});
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.count).toBe(2);
|
|
||||||
|
|
||||||
expect(assets.items).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining('directoryA/assetA.png') }),
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining('directoryB/assetB.png') }),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await utils.updateLibrary(admin.accessToken, library.id, {
|
|
||||||
exclusionPatterns: ['**/directoryA/**'],
|
|
||||||
});
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.count).toBe(1);
|
|
||||||
|
|
||||||
expect(assets.items).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining('directoryB/assetB.png') }),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await utils.updateLibrary(admin.accessToken, library.id, {
|
|
||||||
exclusionPatterns: ['**/directoryA/**', '**/directoryB/**'],
|
|
||||||
});
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.count).toBe(0);
|
|
||||||
|
|
||||||
expect(assets.items).toEqual([]);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should scan multiple import paths', async () => {
|
it('should scan multiple import paths', async () => {
|
||||||
@@ -529,133 +454,6 @@ describe('/libraries', () => {
|
|||||||
utils.removeImageFile(`${testAssetDir}/temp/folder${char}2/asset2.png`);
|
utils.removeImageFile(`${testAssetDir}/temp/folder${char}2/asset2.png`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should respect exclusion patterns when using multiple import paths', async () => {
|
|
||||||
// https://github.com/immich-app/immich/issues/17121
|
|
||||||
const library = await utils.createLibrary(admin.accessToken, {
|
|
||||||
ownerId: admin.userId,
|
|
||||||
importPaths: [`${testAssetDirInternal}/temp/exclusion/`, `${testAssetDirInternal}/temp/exclusion2/`],
|
|
||||||
});
|
|
||||||
|
|
||||||
const excludedFolder = `Raw`;
|
|
||||||
|
|
||||||
utils.createImageFile(`${testAssetDir}/temp/exclusion/asset1.png`);
|
|
||||||
utils.createImageFile(`${testAssetDir}/temp/exclusion/${excludedFolder}/asset2.png`);
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.items).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining(`/asset1.png`) }),
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining(`${excludedFolder}/asset2.png`) }),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.items).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining(`/asset1.png`) }),
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining(`${excludedFolder}/asset2.png`) }),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await utils.updateLibrary(admin.accessToken, library.id, { exclusionPatterns: [`**/${excludedFolder}/**`] });
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.items).toEqual([
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining(`/asset1.png`) }),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.items).toEqual([
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining(`/asset1.png`) }),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
utils.removeImageFile(`${testAssetDir}/temp/exclusion/asset1.png`);
|
|
||||||
utils.removeImageFile(`${testAssetDir}/temp/exclusion/${excludedFolder}/asset2.png`);
|
|
||||||
});
|
|
||||||
|
|
||||||
const annoyingExclusionPatterns = ['@', '#', '$', '%', '^', '&', '='];
|
|
||||||
|
|
||||||
it.each(annoyingExclusionPatterns)('should support exclusion patterns with %s', async (char) => {
|
|
||||||
const library = await utils.createLibrary(admin.accessToken, {
|
|
||||||
ownerId: admin.userId,
|
|
||||||
importPaths: [`${testAssetDirInternal}/temp/exclusion/`],
|
|
||||||
});
|
|
||||||
|
|
||||||
const excludedFolder = `${char}folder`;
|
|
||||||
|
|
||||||
utils.createImageFile(`${testAssetDir}/temp/exclusion/asset1.png`);
|
|
||||||
utils.createImageFile(`${testAssetDir}/temp/exclusion/${excludedFolder}/asset2.png`);
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.items).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining(`/asset1.png`) }),
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining(`${excludedFolder}/asset2.png`) }),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.items).toEqual(
|
|
||||||
expect.arrayContaining([
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining(`/asset1.png`) }),
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining(`${excludedFolder}/asset2.png`) }),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await utils.updateLibrary(admin.accessToken, library.id, { exclusionPatterns: [`**/${excludedFolder}/**`] });
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.items).toEqual([
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining(`/asset1.png`) }),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.items).toEqual([
|
|
||||||
expect.objectContaining({ originalPath: expect.stringContaining(`/asset1.png`) }),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
utils.removeImageFile(`${testAssetDir}/temp/exclusion/asset1.png`);
|
|
||||||
utils.removeImageFile(`${testAssetDir}/temp/exclusion/${excludedFolder}/asset2.png`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reimport a modified file', async () => {
|
it('should reimport a modified file', async () => {
|
||||||
const library = await utils.createLibrary(admin.accessToken, {
|
const library = await utils.createLibrary(admin.accessToken, {
|
||||||
ownerId: admin.userId,
|
ownerId: admin.userId,
|
||||||
@@ -692,7 +490,7 @@ describe('/libraries', () => {
|
|||||||
utils.removeImageFile(`${testAssetDir}/temp/reimport/asset.jpg`);
|
utils.removeImageFile(`${testAssetDir}/temp/reimport/asset.jpg`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not reimport a file with unchanged timestamp', async () => {
|
it('should not reimport unmodified files', async () => {
|
||||||
const library = await utils.createLibrary(admin.accessToken, {
|
const library = await utils.createLibrary(admin.accessToken, {
|
||||||
ownerId: admin.userId,
|
ownerId: admin.userId,
|
||||||
importPaths: [`${testAssetDirInternal}/temp/reimport`],
|
importPaths: [`${testAssetDirInternal}/temp/reimport`],
|
||||||
@@ -1135,8 +933,6 @@ describe('/libraries', () => {
|
|||||||
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
||||||
|
|
||||||
expect(assets.count).toBe(1);
|
|
||||||
|
|
||||||
utils.renameImageFile(`${testAssetDir}/temp/offline/offline.png`, `${testAssetDir}/temp/offline.png`);
|
utils.renameImageFile(`${testAssetDir}/temp/offline/offline.png`, `${testAssetDir}/temp/offline.png`);
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
await utils.scan(admin.accessToken, library.id);
|
||||||
@@ -1167,58 +963,6 @@ describe('/libraries', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set a trashed offline asset to online but keep it in trash', async () => {
|
|
||||||
utils.createImageFile(`${testAssetDir}/temp/offline/offline.png`);
|
|
||||||
|
|
||||||
const library = await utils.createLibrary(admin.accessToken, {
|
|
||||||
ownerId: admin.userId,
|
|
||||||
importPaths: [`${testAssetDirInternal}/temp/offline`],
|
|
||||||
});
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
|
|
||||||
expect(assets.count).toBe(1);
|
|
||||||
|
|
||||||
await utils.deleteAssets(admin.accessToken, [assets.items[0].id]);
|
|
||||||
|
|
||||||
{
|
|
||||||
const trashedAsset = await utils.getAssetInfo(admin.accessToken, assets.items[0].id);
|
|
||||||
|
|
||||||
expect(trashedAsset.isTrashed).toBe(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
utils.renameImageFile(`${testAssetDir}/temp/offline/offline.png`, `${testAssetDir}/temp/offline.png`);
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
const offlineAsset = await utils.getAssetInfo(admin.accessToken, assets.items[0].id);
|
|
||||||
expect(offlineAsset.isTrashed).toBe(true);
|
|
||||||
expect(offlineAsset.originalPath).toBe(`${testAssetDirInternal}/temp/offline/offline.png`);
|
|
||||||
expect(offlineAsset.isOffline).toBe(true);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id, withDeleted: true });
|
|
||||||
expect(assets.count).toBe(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
utils.renameImageFile(`${testAssetDir}/temp/offline.png`, `${testAssetDir}/temp/offline/offline.png`);
|
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
|
||||||
|
|
||||||
const backOnlineAsset = await utils.getAssetInfo(admin.accessToken, assets.items[0].id);
|
|
||||||
|
|
||||||
expect(backOnlineAsset.originalPath).toBe(`${testAssetDirInternal}/temp/offline/offline.png`);
|
|
||||||
expect(backOnlineAsset.isOffline).toBe(false);
|
|
||||||
expect(backOnlineAsset.isTrashed).toBe(true);
|
|
||||||
|
|
||||||
{
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id, withDeleted: true });
|
|
||||||
expect(assets.count).toBe(1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not set an offline asset to online if its file exists, is not covered by an exclusion pattern, but is outside of all import paths', async () => {
|
it('should not set an offline asset to online if its file exists, is not covered by an exclusion pattern, but is outside of all import paths', async () => {
|
||||||
utils.createImageFile(`${testAssetDir}/temp/offline/offline.png`);
|
utils.createImageFile(`${testAssetDir}/temp/offline/offline.png`);
|
||||||
|
|
||||||
@@ -1280,17 +1024,16 @@ describe('/libraries', () => {
|
|||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
await utils.scan(admin.accessToken, library.id);
|
||||||
|
|
||||||
{
|
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
||||||
const { assets: assetsBefore } = await utils.searchAssets(admin.accessToken, { libraryId: library.id });
|
|
||||||
expect(assetsBefore.count).toBe(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
utils.renameImageFile(`${testAssetDir}/temp/offline/offline.png`, `${testAssetDir}/temp/offline.png`);
|
utils.renameImageFile(`${testAssetDir}/temp/offline/offline.png`, `${testAssetDir}/temp/offline.png`);
|
||||||
|
|
||||||
await utils.scan(admin.accessToken, library.id);
|
await utils.scan(admin.accessToken, library.id);
|
||||||
|
|
||||||
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id, withDeleted: true });
|
{
|
||||||
expect(assets.count).toBe(1);
|
const { assets } = await utils.searchAssets(admin.accessToken, { libraryId: library.id, withDeleted: true });
|
||||||
|
expect(assets.count).toBe(1);
|
||||||
|
}
|
||||||
|
|
||||||
const offlineAsset = await utils.getAssetInfo(admin.accessToken, assets.items[0].id);
|
const offlineAsset = await utils.getAssetInfo(admin.accessToken, assets.items[0].id);
|
||||||
|
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ describe('/people', () => {
|
|||||||
expect(body).toMatchObject({
|
expect(body).toMatchObject({
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
name: 'New Person',
|
name: 'New Person',
|
||||||
birthDate: '1990-01-01',
|
birthDate: '1990-01-01T00:00:00.000Z',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ describe('/people', () => {
|
|||||||
.set('Authorization', `Bearer ${admin.accessToken}`)
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
.send({ birthDate: '1990-01-01' });
|
.send({ birthDate: '1990-01-01' });
|
||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
expect(body).toMatchObject({ birthDate: '1990-01-01' });
|
expect(body).toMatchObject({ birthDate: '1990-01-01T00:00:00.000Z' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should clear a date of birth', async () => {
|
it('should clear a date of birth', async () => {
|
||||||
|
|||||||
@@ -633,6 +633,7 @@ describe('/search', () => {
|
|||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
expect(body).toEqual([
|
expect(body).toEqual([
|
||||||
'Andalusia',
|
'Andalusia',
|
||||||
|
'Berlin',
|
||||||
'Glarus',
|
'Glarus',
|
||||||
'Greater Accra',
|
'Greater Accra',
|
||||||
'Havana',
|
'Havana',
|
||||||
@@ -641,7 +642,6 @@ describe('/search', () => {
|
|||||||
'Mississippi',
|
'Mississippi',
|
||||||
'New York',
|
'New York',
|
||||||
'Shanghai',
|
'Shanghai',
|
||||||
'State of Berlin',
|
|
||||||
'St.-Petersburg',
|
'St.-Petersburg',
|
||||||
'Tbilisi',
|
'Tbilisi',
|
||||||
'Tokyo',
|
'Tokyo',
|
||||||
@@ -657,6 +657,7 @@ describe('/search', () => {
|
|||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
expect(body).toEqual([
|
expect(body).toEqual([
|
||||||
'Andalusia',
|
'Andalusia',
|
||||||
|
'Berlin',
|
||||||
'Glarus',
|
'Glarus',
|
||||||
'Greater Accra',
|
'Greater Accra',
|
||||||
'Havana',
|
'Havana',
|
||||||
@@ -665,7 +666,6 @@ describe('/search', () => {
|
|||||||
'Mississippi',
|
'Mississippi',
|
||||||
'New York',
|
'New York',
|
||||||
'Shanghai',
|
'Shanghai',
|
||||||
'State of Berlin',
|
|
||||||
'St.-Petersburg',
|
'St.-Petersburg',
|
||||||
'Tbilisi',
|
'Tbilisi',
|
||||||
'Tokyo',
|
'Tokyo',
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ describe('/shared-links', () => {
|
|||||||
const resp = await request(shareUrl).get(`/${linkWithAssets.key}`);
|
const resp = await request(shareUrl).get(`/${linkWithAssets.key}`);
|
||||||
expect(resp.status).toBe(200);
|
expect(resp.status).toBe(200);
|
||||||
expect(resp.header['content-type']).toContain('text/html');
|
expect(resp.header['content-type']).toContain('text/html');
|
||||||
expect(resp.text).toContain(`<meta property="og:image" content="https://my.immich.app`);
|
expect(resp.text).toContain(`<meta property="og:image" content="http://`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -246,7 +246,15 @@ describe('/shared-links', () => {
|
|||||||
const { status, body } = await request(app).get('/shared-links/me').query({ key: linkWithMetadata.key });
|
const { status, body } = await request(app).get('/shared-links/me').query({ key: linkWithMetadata.key });
|
||||||
|
|
||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
expect(body.assets).toHaveLength(0);
|
expect(body.assets).toHaveLength(1);
|
||||||
|
expect(body.assets[0]).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
originalFileName: 'example.png',
|
||||||
|
localDateTime: expect.any(String),
|
||||||
|
fileCreatedAt: expect.any(String),
|
||||||
|
exifInfo: expect.any(Object),
|
||||||
|
}),
|
||||||
|
);
|
||||||
expect(body.album).toBeDefined();
|
expect(body.album).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const tests: Test[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: 'should support paths with an asterisk',
|
test: 'should support paths with an asterisk',
|
||||||
paths: [`/photos*/image1.jpg`],
|
paths: [`/photos\*/image1.jpg`],
|
||||||
files: {
|
files: {
|
||||||
'/photos*/image1.jpg': true,
|
'/photos*/image1.jpg': true,
|
||||||
'/photos*/image2.jpg': false,
|
'/photos*/image2.jpg': false,
|
||||||
@@ -40,7 +40,7 @@ const tests: Test[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: 'should support paths with a single quote',
|
test: 'should support paths with a single quote',
|
||||||
paths: [`/photos'/image1.jpg`],
|
paths: [`/photos\'/image1.jpg`],
|
||||||
files: {
|
files: {
|
||||||
"/photos'/image1.jpg": true,
|
"/photos'/image1.jpg": true,
|
||||||
"/photos'/image2.jpg": false,
|
"/photos'/image2.jpg": false,
|
||||||
@@ -49,7 +49,7 @@ const tests: Test[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: 'should support paths with a double quote',
|
test: 'should support paths with a double quote',
|
||||||
paths: [`/photos"/image1.jpg`],
|
paths: [`/photos\"/image1.jpg`],
|
||||||
files: {
|
files: {
|
||||||
'/photos"/image1.jpg': true,
|
'/photos"/image1.jpg': true,
|
||||||
'/photos"/image2.jpg': false,
|
'/photos"/image2.jpg': false,
|
||||||
@@ -67,7 +67,7 @@ const tests: Test[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: 'should support paths with an opening brace',
|
test: 'should support paths with an opening brace',
|
||||||
paths: [`/photos{/image1.jpg`],
|
paths: [`/photos\{/image1.jpg`],
|
||||||
files: {
|
files: {
|
||||||
'/photos{/image1.jpg': true,
|
'/photos{/image1.jpg': true,
|
||||||
'/photos{/image2.jpg': false,
|
'/photos{/image2.jpg': false,
|
||||||
@@ -76,7 +76,7 @@ const tests: Test[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: 'should support paths with a closing brace',
|
test: 'should support paths with a closing brace',
|
||||||
paths: [`/photos}/image1.jpg`],
|
paths: [`/photos\}/image1.jpg`],
|
||||||
files: {
|
files: {
|
||||||
'/photos}/image1.jpg': true,
|
'/photos}/image1.jpg': true,
|
||||||
'/photos}/image2.jpg': false,
|
'/photos}/image2.jpg': false,
|
||||||
|
|||||||
@@ -493,7 +493,7 @@ export const utils = {
|
|||||||
value: accessToken,
|
value: accessToken,
|
||||||
domain,
|
domain,
|
||||||
path: '/',
|
path: '/',
|
||||||
expires: 2_058_028_213,
|
expires: 1_742_402_728,
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
sameSite: 'Lax',
|
sameSite: 'Lax',
|
||||||
@@ -503,7 +503,7 @@ export const utils = {
|
|||||||
value: 'password',
|
value: 'password',
|
||||||
domain,
|
domain,
|
||||||
path: '/',
|
path: '/',
|
||||||
expires: 2_058_028_213,
|
expires: 1_742_402_728,
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
sameSite: 'Lax',
|
sameSite: 'Lax',
|
||||||
@@ -513,7 +513,7 @@ export const utils = {
|
|||||||
value: 'true',
|
value: 'true',
|
||||||
domain,
|
domain,
|
||||||
path: '/',
|
path: '/',
|
||||||
expires: 2_058_028_213,
|
expires: 1_742_402_728,
|
||||||
httpOnly: false,
|
httpOnly: false,
|
||||||
secure: false,
|
secure: false,
|
||||||
sameSite: 'Lax',
|
sameSite: 'Lax',
|
||||||
@@ -537,7 +537,6 @@ export const utils = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
waitForQueueFinish: (accessToken: string, queue: keyof AllJobStatusResponseDto, ms?: number) => {
|
waitForQueueFinish: (accessToken: string, queue: keyof AllJobStatusResponseDto, ms?: number) => {
|
||||||
// eslint-disable-next-line no-async-promise-executor
|
|
||||||
return new Promise<void>(async (resolve, reject) => {
|
return new Promise<void>(async (resolve, reject) => {
|
||||||
const timeout = setTimeout(() => reject(new Error('Timed out waiting for queue to empty')), ms || 10_000);
|
const timeout = setTimeout(() => reject(new Error('Timed out waiting for queue to empty')), ms || 10_000);
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ function imageLocator(page: Page) {
|
|||||||
test.describe('Photo Viewer', () => {
|
test.describe('Photo Viewer', () => {
|
||||||
let admin: LoginResponseDto;
|
let admin: LoginResponseDto;
|
||||||
let asset: AssetMediaResponseDto;
|
let asset: AssetMediaResponseDto;
|
||||||
let rawAsset: AssetMediaResponseDto;
|
|
||||||
|
|
||||||
test.beforeAll(async () => {
|
test.beforeAll(async () => {
|
||||||
utils.initSdk();
|
utils.initSdk();
|
||||||
await utils.resetDatabase();
|
await utils.resetDatabase();
|
||||||
admin = await utils.adminSetup();
|
admin = await utils.adminSetup();
|
||||||
asset = await utils.createAsset(admin.accessToken);
|
asset = await utils.createAsset(admin.accessToken);
|
||||||
rawAsset = await utils.createAsset(admin.accessToken, { assetData: { filename: 'test.arw' } });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test.beforeEach(async ({ context, page }) => {
|
test.beforeEach(async ({ context, page }) => {
|
||||||
@@ -38,7 +36,7 @@ test.describe('Photo Viewer', () => {
|
|||||||
await expect(page.getByTestId('loading-spinner')).toBeVisible();
|
await expect(page.getByTestId('loading-spinner')).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('loads original photo when zoomed', async ({ page }) => {
|
test('loads high resolution photo when zoomed', async ({ page }) => {
|
||||||
await page.goto(`/photos/${asset.id}`);
|
await page.goto(`/photos/${asset.id}`);
|
||||||
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('thumbnail');
|
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('thumbnail');
|
||||||
const box = await imageLocator(page).boundingBox();
|
const box = await imageLocator(page).boundingBox();
|
||||||
@@ -49,17 +47,6 @@ test.describe('Photo Viewer', () => {
|
|||||||
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('original');
|
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('original');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('loads fullsize image when zoomed and original is web-incompatible', async ({ page }) => {
|
|
||||||
await page.goto(`/photos/${rawAsset.id}`);
|
|
||||||
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('thumbnail');
|
|
||||||
const box = await imageLocator(page).boundingBox();
|
|
||||||
expect(box).toBeTruthy();
|
|
||||||
const { x, y, width, height } = box!;
|
|
||||||
await page.mouse.move(x + width / 2, y + height / 2);
|
|
||||||
await page.mouse.wheel(0, -1);
|
|
||||||
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('fullsize');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('reloads photo when checksum changes', async ({ page }) => {
|
test('reloads photo when checksum changes', async ({ page }) => {
|
||||||
await page.goto(`/photos/${asset.id}`);
|
await page.goto(`/photos/${asset.id}`);
|
||||||
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('thumbnail');
|
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('thumbnail');
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ test.describe('Shared Links', () => {
|
|||||||
await page.goto(`/share/${sharedLink.key}`);
|
await page.goto(`/share/${sharedLink.key}`);
|
||||||
await page.getByRole('heading', { name: 'Test Album' }).waitFor();
|
await page.getByRole('heading', { name: 'Test Album' }).waitFor();
|
||||||
await page.locator(`[data-asset-id="${asset.id}"]`).hover();
|
await page.locator(`[data-asset-id="${asset.id}"]`).hover();
|
||||||
await page.waitForSelector('[data-group] svg');
|
await page.waitForSelector('#asset-group-by-date svg');
|
||||||
await page.getByRole('checkbox').click();
|
await page.getByRole('checkbox').click();
|
||||||
await page.getByRole('button', { name: 'Download' }).click();
|
await page.getByRole('button', { name: 'Download' }).click();
|
||||||
await page.waitForEvent('download');
|
await page.getByText('DOWNLOADING', { exact: true }).waitFor();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('download all from shared link', async ({ page }) => {
|
test('download all from shared link', async ({ page }) => {
|
||||||
@@ -56,7 +56,6 @@ test.describe('Shared Links', () => {
|
|||||||
await page.getByRole('heading', { name: 'Test Album' }).waitFor();
|
await page.getByRole('heading', { name: 'Test Album' }).waitFor();
|
||||||
await page.getByRole('button', { name: 'Download' }).click();
|
await page.getByRole('button', { name: 'Download' }).click();
|
||||||
await page.getByText('DOWNLOADING', { exact: true }).waitFor();
|
await page.getByText('DOWNLOADING', { exact: true }).waitFor();
|
||||||
await page.waitForEvent('download');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('enter password for a shared link', async ({ page }) => {
|
test('enter password for a shared link', async ({ page }) => {
|
||||||
|
|||||||
18
i18n/af.json
18
i18n/af.json
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"about": "Oor",
|
"about": "Verfris",
|
||||||
"account": "Rekening",
|
"account": "Rekening",
|
||||||
"account_settings": "Rekeninginstellings",
|
"account_settings": "Rekeninginstellings",
|
||||||
"acknowledge": "Erken",
|
"acknowledge": "Erken",
|
||||||
@@ -56,16 +56,15 @@
|
|||||||
"duplicate_detection_job_description": "Begin masjienleer op bates om soortgelyke beelde op te spoor. Maak staat op Smart Search",
|
"duplicate_detection_job_description": "Begin masjienleer op bates om soortgelyke beelde op te spoor. Maak staat op Smart Search",
|
||||||
"exclusion_pattern_description": "Met uitsluitingspatrone kan jy lêers en vouers ignoreer wanneer jy jou biblioteek skandeer. Dit is nuttig as jy vouers het wat lêers bevat wat jy nie wil invoer nie, soos RAW-lêers.",
|
"exclusion_pattern_description": "Met uitsluitingspatrone kan jy lêers en vouers ignoreer wanneer jy jou biblioteek skandeer. Dit is nuttig as jy vouers het wat lêers bevat wat jy nie wil invoer nie, soos RAW-lêers.",
|
||||||
"external_library_created_at": "Eksterne biblioteek (geskep op {date})",
|
"external_library_created_at": "Eksterne biblioteek (geskep op {date})",
|
||||||
"external_library_management": "Eksterne Biblioteekbestuur",
|
"external_library_management": "Eksterne Biblioteek-opsies",
|
||||||
"face_detection": "Gesig deteksie",
|
"face_detection": "Gesigsopsporing",
|
||||||
"failed_job_command": "Opdrag {command} het misluk vir werk: {job}",
|
"failed_job_command": "Opdrag {command} het misluk vir werk: {job}",
|
||||||
"force_delete_user_warning": "WAARSKUWING: Dit sal onmiddellik die gebruiker en alle bates verwyder. Dit kan nie ontdoen word nie en die lêers kan nie herstel word nie.",
|
"force_delete_user_warning": "WAARSKUWING: Dit sal onmiddellik die gebruiker en alle bates verwyder. Dit kan nie ontdoen word nie en die lêers kan nie herstel word nie.",
|
||||||
"forcing_refresh_library_files": "Forseer herlaai van alle biblioteeklêers",
|
"forcing_refresh_library_files": "Forseer herlaai van alle biblioteeklêers",
|
||||||
"image_format": "Formaat",
|
"image_format": "Formaat",
|
||||||
"image_format_description": "WebP produseer kleiner lêers as JPEG, maar is stadiger om te enkodeer.",
|
"image_format_description": "WebP produseer kleiner lêers as JPEG, maar is stadiger om te enkodeer.",
|
||||||
"image_prefer_embedded_preview": "Verkies ingebedde voorskou",
|
"image_prefer_embedded_preview": "Verkies ingebedde voorskou",
|
||||||
"image_prefer_wide_gamut": "Verkies wide gamut",
|
"image_prefer_wide_gamut": "Verkies wye spektrum",
|
||||||
"image_prefer_wide_gamut_setting_description": "Gebruik Display P3 vir kleinkiekies. Dit behou die lewendheid van beelde met wye kleurruimtes beter, maar beelde kan anders verskyn op ou apparate met 'n ou blaaierweergawe. sRGB-beelde gebruik steeds sRGB om kleurverskuiwings te voorkom.",
|
|
||||||
"image_preview_description": "Mediumgrootte prent met gestroopte metadata, wat gebruik word wanneer 'n enkele bate bekyk word en vir masjienleer",
|
"image_preview_description": "Mediumgrootte prent met gestroopte metadata, wat gebruik word wanneer 'n enkele bate bekyk word en vir masjienleer",
|
||||||
"image_preview_quality_description": "Voorskou kwaliteit van 1-100. Hoër is beter, maar produseer groter lêers en kan app-reaksie verminder. Die stel van 'n lae waarde kan masjienleerkwaliteit beïnvloed.",
|
"image_preview_quality_description": "Voorskou kwaliteit van 1-100. Hoër is beter, maar produseer groter lêers en kan app-reaksie verminder. Die stel van 'n lae waarde kan masjienleerkwaliteit beïnvloed.",
|
||||||
"image_preview_title": "Voorskou Instellings",
|
"image_preview_title": "Voorskou Instellings",
|
||||||
@@ -73,14 +72,7 @@
|
|||||||
"image_resolution": "Resolusie",
|
"image_resolution": "Resolusie",
|
||||||
"image_resolution_description": "Hoër resolusies kan meer detail bewaar, maar neem langer om te enkodeer, het groter lêergroottes en kan app-reaksie verminder.",
|
"image_resolution_description": "Hoër resolusies kan meer detail bewaar, maar neem langer om te enkodeer, het groter lêergroottes en kan app-reaksie verminder.",
|
||||||
"image_settings": "Prent Instellings",
|
"image_settings": "Prent Instellings",
|
||||||
"image_settings_description": "Bestuur die kwaliteit en resolusie van gegenereerde beelde",
|
"image_settings_description": "Bestuur die kwaliteit en resolusie van gegenereerde beelde"
|
||||||
"image_thumbnail_description": "Klein kleinkiekies sonder metadata, gebruik om groepe foto's soos die tydlyn te bekyk",
|
|
||||||
"image_thumbnail_quality_description": "Kleinkiekiekwaliteit van 1-100. Hoër is beter, maar produseer groter lêers en kan die toepassing vertraag.",
|
|
||||||
"image_thumbnail_title": "Kleinkiekie-instellings",
|
|
||||||
"job_concurrency": "{job} gelyktydigheid",
|
|
||||||
"job_created": "Taak gemaak",
|
|
||||||
"job_not_concurrency_safe": "Hierdie taak kan nie gelyktydig uitgevoer word nie.",
|
|
||||||
"job_settings": "Agtergrondtaakinstellings"
|
|
||||||
},
|
},
|
||||||
"search_by_description": "Soek by beskrywing",
|
"search_by_description": "Soek by beskrywing",
|
||||||
"search_by_description_example": "Stapdag in Sapa"
|
"search_by_description_example": "Stapdag in Sapa"
|
||||||
|
|||||||
806
i18n/ar.json
806
i18n/ar.json
File diff suppressed because it is too large
Load Diff
48
i18n/bg.json
48
i18n/bg.json
@@ -20,7 +20,7 @@
|
|||||||
"add_partner": "Добавете партньор",
|
"add_partner": "Добавете партньор",
|
||||||
"add_path": "Добави път",
|
"add_path": "Добави път",
|
||||||
"add_photos": "Добавете снимки",
|
"add_photos": "Добавете снимки",
|
||||||
"add_to": "Добави към…",
|
"add_to": "Добави към...",
|
||||||
"add_to_album": "Добави към албум",
|
"add_to_album": "Добави към албум",
|
||||||
"add_to_shared_album": "Добави към споделен албум",
|
"add_to_shared_album": "Добави към споделен албум",
|
||||||
"add_url": "Добави URL",
|
"add_url": "Добави URL",
|
||||||
@@ -41,7 +41,6 @@
|
|||||||
"backup_settings": "Настройка на резервни копия",
|
"backup_settings": "Настройка на резервни копия",
|
||||||
"backup_settings_description": "Управление на настройките за резервно копие на базата данни",
|
"backup_settings_description": "Управление на настройките за резервно копие на базата данни",
|
||||||
"check_all": "Провери всичко",
|
"check_all": "Провери всичко",
|
||||||
"cleanup": "Почистване",
|
|
||||||
"cleared_jobs": "Изчистени задачи от тип: {job}",
|
"cleared_jobs": "Изчистени задачи от тип: {job}",
|
||||||
"config_set_by_file": "Конфигурацията е зададена от файл",
|
"config_set_by_file": "Конфигурацията е зададена от файл",
|
||||||
"confirm_delete_library": "Сигурни ли сте че искате да изтриете библиотеката - {library} ?",
|
"confirm_delete_library": "Сигурни ли сте че искате да изтриете библиотеката - {library} ?",
|
||||||
@@ -97,7 +96,7 @@
|
|||||||
"library_scanning_enable_description": "Включване на периодичното сканиране на библиотеката",
|
"library_scanning_enable_description": "Включване на периодичното сканиране на библиотеката",
|
||||||
"library_settings": "Външна библиотека",
|
"library_settings": "Външна библиотека",
|
||||||
"library_settings_description": "Управление на настройките за външна библиотека",
|
"library_settings_description": "Управление на настройките за външна библиотека",
|
||||||
"library_tasks_description": "Сканирайте външни библиотеки за нови и/или променени активи",
|
"library_tasks_description": "Извършване на задачи за библиотеката",
|
||||||
"library_watching_enable_description": "Наблюдаване за промяна на файловете във външната библиотека",
|
"library_watching_enable_description": "Наблюдаване за промяна на файловете във външната библиотека",
|
||||||
"library_watching_settings": "Наблюдаване на библиотеката (ЕКСПЕРИМЕНТАЛНО)",
|
"library_watching_settings": "Наблюдаване на библиотеката (ЕКСПЕРИМЕНТАЛНО)",
|
||||||
"library_watching_settings_description": "Автоматично наблюдавай за променени файлове",
|
"library_watching_settings_description": "Автоматично наблюдавай за променени файлове",
|
||||||
@@ -132,7 +131,7 @@
|
|||||||
"machine_learning_smart_search_description": "Семантично търсене на изображения с помощта на CLIP вграждания",
|
"machine_learning_smart_search_description": "Семантично търсене на изображения с помощта на CLIP вграждания",
|
||||||
"machine_learning_smart_search_enabled": "Включване на Интелигентно Търсене",
|
"machine_learning_smart_search_enabled": "Включване на Интелигентно Търсене",
|
||||||
"machine_learning_smart_search_enabled_description": "Ако е деактивирано, изображенията няма да бъдат кодирани за Интелигентно Търсене.",
|
"machine_learning_smart_search_enabled_description": "Ако е деактивирано, изображенията няма да бъдат кодирани за Интелигентно Търсене.",
|
||||||
"machine_learning_url_description": "URL на сървъра за машинно обучение. Ако са предоставени повече от един URL, всеки сървър ще бъде опитан един по един, докато един отговори успешно, в реда от първия до последния. Сървъри, които не отговорят, ще бъдат временно игнорирани, докато не се върнат онлайн.",
|
"machine_learning_url_description": "URL на сървъра за машинно обучение. Ако са предоставени повече от един URL, всеки сървър ще бъде опитан един по един, докато един не отговори успешно, в реда от първия до последния.",
|
||||||
"manage_concurrency": "Управление на паралелност",
|
"manage_concurrency": "Управление на паралелност",
|
||||||
"manage_log_settings": "Управление на настройките на записване",
|
"manage_log_settings": "Управление на настройките на записване",
|
||||||
"map_dark_style": "Тъмен стил",
|
"map_dark_style": "Тъмен стил",
|
||||||
@@ -148,8 +147,6 @@
|
|||||||
"map_settings": "Карта",
|
"map_settings": "Карта",
|
||||||
"map_settings_description": "Управление на настройките на картата",
|
"map_settings_description": "Управление на настройките на картата",
|
||||||
"map_style_description": "URL адрес към файл \"style.json\" за задаване на стил на картата",
|
"map_style_description": "URL адрес към файл \"style.json\" за задаване на стил на картата",
|
||||||
"memory_cleanup_job": "Почистване на паметта",
|
|
||||||
"memory_generate_job": "Генериране на паметта",
|
|
||||||
"metadata_extraction_job": "Извличане на метаданни",
|
"metadata_extraction_job": "Извличане на метаданни",
|
||||||
"metadata_extraction_job_description": "Извличане на метаданни от всеки от елемент, като GPS локация, лица и резолюция на файловете",
|
"metadata_extraction_job_description": "Извличане на метаданни от всеки от елемент, като GPS локация, лица и резолюция на файловете",
|
||||||
"metadata_faces_import_setting": "Включи импорт на лице",
|
"metadata_faces_import_setting": "Включи импорт на лице",
|
||||||
@@ -222,7 +219,7 @@
|
|||||||
"reset_settings_to_default": "Възстановяване на настройките по подразбиране",
|
"reset_settings_to_default": "Възстановяване на настройките по подразбиране",
|
||||||
"reset_settings_to_recent_saved": "Възстановяване на настройките до последните запазени настройки",
|
"reset_settings_to_recent_saved": "Възстановяване на настройките до последните запазени настройки",
|
||||||
"scanning_library": "Сканиране на библиотеката",
|
"scanning_library": "Сканиране на библиотеката",
|
||||||
"search_jobs": "Търсене на задачи…",
|
"search_jobs": "Търсене на задачи...",
|
||||||
"send_welcome_email": "Изпращане на имейл за добре дошли",
|
"send_welcome_email": "Изпращане на имейл за добре дошли",
|
||||||
"server_external_domain_settings": "Външен домейн",
|
"server_external_domain_settings": "Външен домейн",
|
||||||
"server_external_domain_settings_description": "Домейн за публични споделени връзки, включително http(s)://",
|
"server_external_domain_settings_description": "Домейн за публични споделени връзки, включително http(s)://",
|
||||||
@@ -302,7 +299,7 @@
|
|||||||
"transcoding_max_b_frames": "Максимални B-фрейма",
|
"transcoding_max_b_frames": "Максимални B-фрейма",
|
||||||
"transcoding_max_b_frames_description": "По-високите стойности подобряват ефективността на компресията, но забавят разкодирането. Може да не е съвместим с хардуерното ускорение на по-стари устройства. 0 деактивира B-фрейма, докато -1 задава тази стойност автоматично.",
|
"transcoding_max_b_frames_description": "По-високите стойности подобряват ефективността на компресията, но забавят разкодирането. Може да не е съвместим с хардуерното ускорение на по-стари устройства. 0 деактивира B-фрейма, докато -1 задава тази стойност автоматично.",
|
||||||
"transcoding_max_bitrate": "Максимален битрейт",
|
"transcoding_max_bitrate": "Максимален битрейт",
|
||||||
"transcoding_max_bitrate_description": "Задаването на максимален битрейт може да направи размерите на файловете по-предвидими при незначителни разлики за качеството. При 720p типичните стойности са 2600 kbit/s за VP9 или HEVC или 4500 kbit/s за H.264. Деактивирано, ако е зададено на 0.",
|
"transcoding_max_bitrate_description": "Задаването на максимален битрейт може да направи размерите на файловете по-предвидими при незначителни разлики за качеството. При 720p типичните стойности са 2600k за VP9 или HEVC или 4500k за H.264. Деактивирано, ако е зададено на 0.",
|
||||||
"transcoding_max_keyframe_interval": "Максимален интервал между ключовите кадри",
|
"transcoding_max_keyframe_interval": "Максимален интервал между ключовите кадри",
|
||||||
"transcoding_max_keyframe_interval_description": "Задава максималното разстояние между ключовите кадри. По-ниските стойности влошават ефективността на компресията, но подобряват времето за търсене и могат да подобрят качеството в сцени с бързо движение. 0 задава тази стойност автоматично.",
|
"transcoding_max_keyframe_interval_description": "Задава максималното разстояние между ключовите кадри. По-ниските стойности влошават ефективността на компресията, но подобряват времето за търсене и могат да подобрят качеството в сцени с бързо движение. 0 задава тази стойност автоматично.",
|
||||||
"transcoding_optimal_description": "Видеоклипове с по-висока от целевата разделителна способност или не в приетия формат",
|
"transcoding_optimal_description": "Видеоклипове с по-висока от целевата разделителна способност или не в приетия формат",
|
||||||
@@ -394,7 +391,6 @@
|
|||||||
"allow_edits": "Позволяване на редакции",
|
"allow_edits": "Позволяване на редакции",
|
||||||
"allow_public_user_to_download": "Позволете на публичен потребител да може да изтегля",
|
"allow_public_user_to_download": "Позволете на публичен потребител да може да изтегля",
|
||||||
"allow_public_user_to_upload": "Позволете на публичния потребител да може да качва",
|
"allow_public_user_to_upload": "Позволете на публичния потребител да може да качва",
|
||||||
"alt_text_qr_code": "Изображение на QR код",
|
|
||||||
"anti_clockwise": "Обратно на часовниковата стрелка",
|
"anti_clockwise": "Обратно на часовниковата стрелка",
|
||||||
"api_key": "API ключ",
|
"api_key": "API ключ",
|
||||||
"api_key_description": "Тази стойност ще бъде показана само веднъж. Моля, не забравяйте да го копирате, преди да затворите прозореца.",
|
"api_key_description": "Тази стойност ще бъде показана само веднъж. Моля, не забравяйте да го копирате, преди да затворите прозореца.",
|
||||||
@@ -410,17 +406,17 @@
|
|||||||
"are_these_the_same_person": "Това едно и също лице ли е?",
|
"are_these_the_same_person": "Това едно и също лице ли е?",
|
||||||
"are_you_sure_to_do_this": "Сигурни ли сте, че искате да направите това?",
|
"are_you_sure_to_do_this": "Сигурни ли сте, че искате да направите това?",
|
||||||
"asset_added_to_album": "Добавено в албум",
|
"asset_added_to_album": "Добавено в албум",
|
||||||
"asset_adding_to_album": "Добавяне в албум…",
|
"asset_adding_to_album": "Добавяне в албум...",
|
||||||
"asset_description_updated": "Описанието на елемента е обновено",
|
"asset_description_updated": "Описанието на елемента е обновено",
|
||||||
"asset_filename_is_offline": "Активът {filename} е офлайн",
|
"asset_filename_is_offline": "Активът {filename} е офлайн",
|
||||||
"asset_has_unassigned_faces": "Елементът има незададени лица",
|
"asset_has_unassigned_faces": "Елементът има незададени лица",
|
||||||
"asset_hashing": "Хеширане…",
|
"asset_hashing": "Хеширане...",
|
||||||
"asset_offline": "Елементът е офлайн",
|
"asset_offline": "Елементът е офлайн",
|
||||||
"asset_offline_description": "Този външен актив вече не се намира на диска. Моля, свържете се с администратора на Immich за помощ.",
|
"asset_offline_description": "Този външен актив вече не се намира на диска. Моля, свържете се с администратора на Immich за помощ.",
|
||||||
"asset_skipped": "Пропуснато",
|
"asset_skipped": "Пропуснато",
|
||||||
"asset_skipped_in_trash": "В кошчето",
|
"asset_skipped_in_trash": "В кошчето",
|
||||||
"asset_uploaded": "Качено",
|
"asset_uploaded": "Качено",
|
||||||
"asset_uploading": "Качване…",
|
"asset_uploading": "Качване...",
|
||||||
"assets": "Елементи",
|
"assets": "Елементи",
|
||||||
"assets_added_count": "Добавено {count, plural, one {# asset} other {# assets}}",
|
"assets_added_count": "Добавено {count, plural, one {# asset} other {# assets}}",
|
||||||
"assets_added_to_album_count": "Добавен(и) са {count, plural, one {# актив} other {# актива}} в албума",
|
"assets_added_to_album_count": "Добавен(и) са {count, plural, one {# актив} other {# актива}} в албума",
|
||||||
@@ -485,7 +481,6 @@
|
|||||||
"comments_are_disabled": "Коментарите са деактивирани",
|
"comments_are_disabled": "Коментарите са деактивирани",
|
||||||
"confirm": "Потвърди",
|
"confirm": "Потвърди",
|
||||||
"confirm_admin_password": "Потвърждаване на паролата на администратора",
|
"confirm_admin_password": "Потвърждаване на паролата на администратора",
|
||||||
"confirm_delete_face": "Сигурни ли сте, че искате да изтриете лицето на {name} от актива?",
|
|
||||||
"confirm_delete_shared_link": "Сигурни ли сте, че искате да изтриете тази споделена връзка?",
|
"confirm_delete_shared_link": "Сигурни ли сте, че искате да изтриете тази споделена връзка?",
|
||||||
"confirm_keep_this_delete_others": "Всички останали файлове в стека ще бъдат изтрити, с изключение на този файл. Сигурни ли сте, че искате да продължите?",
|
"confirm_keep_this_delete_others": "Всички останали файлове в стека ще бъдат изтрити, с изключение на този файл. Сигурни ли сте, че искате да продължите?",
|
||||||
"confirm_password": "Потвърдете паролата",
|
"confirm_password": "Потвърдете паролата",
|
||||||
@@ -538,7 +533,6 @@
|
|||||||
"delete_album": "Изтрий албум",
|
"delete_album": "Изтрий албум",
|
||||||
"delete_api_key_prompt": "Сигурни ли сте, че искате да изтриете този API ключ?",
|
"delete_api_key_prompt": "Сигурни ли сте, че искате да изтриете този API ключ?",
|
||||||
"delete_duplicates_confirmation": "Сигурни ли сте, че искате да изтриете окончателно тези дубликати?",
|
"delete_duplicates_confirmation": "Сигурни ли сте, че искате да изтриете окончателно тези дубликати?",
|
||||||
"delete_face": "Изтрий лице",
|
|
||||||
"delete_key": "Изтрий ключ",
|
"delete_key": "Изтрий ключ",
|
||||||
"delete_library": "Изтрий библиотека",
|
"delete_library": "Изтрий библиотека",
|
||||||
"delete_link": "Изтрий линк",
|
"delete_link": "Изтрий линк",
|
||||||
@@ -606,7 +600,6 @@
|
|||||||
"enabled": "Включено",
|
"enabled": "Включено",
|
||||||
"end_date": "Крайна дата",
|
"end_date": "Крайна дата",
|
||||||
"error": "Грешка",
|
"error": "Грешка",
|
||||||
"error_delete_face": "Грешка при изтриване на лице от актива",
|
|
||||||
"error_loading_image": "Грешка при зареждане на изображението",
|
"error_loading_image": "Грешка при зареждане на изображението",
|
||||||
"error_title": "Грешка - нещо се обърка",
|
"error_title": "Грешка - нещо се обърка",
|
||||||
"errors": {
|
"errors": {
|
||||||
@@ -773,10 +766,8 @@
|
|||||||
"go_to_folder": "Отиди в папката",
|
"go_to_folder": "Отиди в папката",
|
||||||
"go_to_search": "Преминаване към търсене",
|
"go_to_search": "Преминаване към търсене",
|
||||||
"group_albums_by": "Групирай албум по...",
|
"group_albums_by": "Групирай албум по...",
|
||||||
"group_country": "Групирай по държава",
|
|
||||||
"group_no": "Няма група",
|
"group_no": "Няма група",
|
||||||
"group_owner": "Групиране по собственик",
|
"group_owner": "Групиране по собственик",
|
||||||
"group_places_by": "Групирай места по…",
|
|
||||||
"group_year": "Групиране по година",
|
"group_year": "Групиране по година",
|
||||||
"has_quota": "Лимит",
|
"has_quota": "Лимит",
|
||||||
"hi_user": "Здравей, {name} {email}",
|
"hi_user": "Здравей, {name} {email}",
|
||||||
@@ -809,7 +800,6 @@
|
|||||||
"include_shared_albums": "Включване на споделени албуми",
|
"include_shared_albums": "Включване на споделени албуми",
|
||||||
"include_shared_partner_assets": "Включване на споделените с партньор елементи",
|
"include_shared_partner_assets": "Включване на споделените с партньор елементи",
|
||||||
"individual_share": "Индивидуално споделяне",
|
"individual_share": "Индивидуално споделяне",
|
||||||
"individual_shares": "Индивидуални споделяния",
|
|
||||||
"info": "Информация",
|
"info": "Информация",
|
||||||
"interval": {
|
"interval": {
|
||||||
"day_at_onepm": "Всеки ден в 13:00",
|
"day_at_onepm": "Всеки ден в 13:00",
|
||||||
@@ -832,7 +822,6 @@
|
|||||||
"latest_version": "Последна версия",
|
"latest_version": "Последна версия",
|
||||||
"latitude": "Ширина",
|
"latitude": "Ширина",
|
||||||
"leave": "Излез",
|
"leave": "Излез",
|
||||||
"lens_model": "Модел леща",
|
|
||||||
"let_others_respond": "Позволете на другите да отговорят",
|
"let_others_respond": "Позволете на другите да отговорят",
|
||||||
"level": "Ниво",
|
"level": "Ниво",
|
||||||
"library": "Библиотека",
|
"library": "Библиотека",
|
||||||
@@ -891,7 +880,6 @@
|
|||||||
"month": "Месец",
|
"month": "Месец",
|
||||||
"more": "Още",
|
"more": "Още",
|
||||||
"moved_to_trash": "Преместено в кошчето",
|
"moved_to_trash": "Преместено в кошчето",
|
||||||
"mute_memories": "Изключване на звука на спомените",
|
|
||||||
"my_albums": "Мои албуми",
|
"my_albums": "Мои албуми",
|
||||||
"name": "Име",
|
"name": "Име",
|
||||||
"name_or_nickname": "Име или прякор",
|
"name_or_nickname": "Име или прякор",
|
||||||
@@ -996,7 +984,6 @@
|
|||||||
"pick_a_location": "Избери локация",
|
"pick_a_location": "Избери локация",
|
||||||
"place": "Местоположение",
|
"place": "Местоположение",
|
||||||
"places": "Местоположения",
|
"places": "Местоположения",
|
||||||
"places_count": "{count, plural, one {{count, number} Място} other {{count, number} Места}}",
|
|
||||||
"play": "Възпроизвеждане",
|
"play": "Възпроизвеждане",
|
||||||
"play_memories": "Възпроизвеждане на спомени",
|
"play_memories": "Възпроизвеждане на спомени",
|
||||||
"play_motion_photo": "Възпроизведи Motion Photo",
|
"play_motion_photo": "Възпроизведи Motion Photo",
|
||||||
@@ -1080,12 +1067,10 @@
|
|||||||
"remove_from_shared_link": "Премахни от споделения линк",
|
"remove_from_shared_link": "Премахни от споделения линк",
|
||||||
"remove_url": "Премахни URL",
|
"remove_url": "Премахни URL",
|
||||||
"remove_user": "Премахни потребителя",
|
"remove_user": "Премахни потребителя",
|
||||||
"removed_api_key": "Премахат API ключ: {name}",
|
"removed_api_key": "Премахни API Key: {name}",
|
||||||
"removed_from_archive": "Премахни от архива",
|
"removed_from_archive": "Премахни от Архива",
|
||||||
"removed_from_favorites": "Премахнато от любими",
|
"removed_from_favorites": "Премахнато от Любими",
|
||||||
"removed_from_favorites_count": "{count, plural, other {Премахнати #}} от Любими",
|
"removed_from_favorites_count": "{count, plural, other {Премахнати #}} от Любими",
|
||||||
"removed_memory": "Премахнат спомен",
|
|
||||||
"removed_photo_from_memory": "Премахната снимка от спомен",
|
|
||||||
"removed_tagged_assets": "Премахнат е етикетът от {count, plural, one {# елемент} other {# елемента}}",
|
"removed_tagged_assets": "Премахнат е етикетът от {count, plural, one {# елемент} other {# елемента}}",
|
||||||
"rename": "Преименувай",
|
"rename": "Преименувай",
|
||||||
"repair": "Поправи",
|
"repair": "Поправи",
|
||||||
@@ -1094,7 +1079,6 @@
|
|||||||
"repository": "Хранилище",
|
"repository": "Хранилище",
|
||||||
"require_password": "Изискай парола",
|
"require_password": "Изискай парола",
|
||||||
"require_user_to_change_password_on_first_login": "Изисквай потребителят да промени паролата си при първото влизане",
|
"require_user_to_change_password_on_first_login": "Изисквай потребителят да промени паролата си при първото влизане",
|
||||||
"rescan": "Пресканиране",
|
|
||||||
"reset": "Нулиране",
|
"reset": "Нулиране",
|
||||||
"reset_password": "Нулиране на паролата",
|
"reset_password": "Нулиране на паролата",
|
||||||
"reset_people_visibility": "Нулиране на видимостта на хората",
|
"reset_people_visibility": "Нулиране на видимостта на хората",
|
||||||
@@ -1123,22 +1107,18 @@
|
|||||||
"search": "Търсене",
|
"search": "Търсене",
|
||||||
"search_albums": "Търси албуми",
|
"search_albums": "Търси албуми",
|
||||||
"search_by_context": "Търси по контекст",
|
"search_by_context": "Търси по контекст",
|
||||||
"search_by_description": "Търси по описание",
|
|
||||||
"search_by_description_example": "Разходка в Сапа",
|
|
||||||
"search_by_filename": "Търси по име на файла или разширение",
|
"search_by_filename": "Търси по име на файла или разширение",
|
||||||
"search_by_filename_example": "например IMG_1234.JPG или PNG",
|
"search_by_filename_example": "например IMG_1234.JPG или PNG",
|
||||||
"search_camera_make": "Търси производител на камерата...",
|
"search_camera_make": "Търси производител на камерата...",
|
||||||
"search_camera_model": "Търси модел на камерата...",
|
"search_camera_model": "Търси модел на камерата...",
|
||||||
"search_city": "Търси град...",
|
"search_city": "Търси град...",
|
||||||
"search_country": "Търси държава...",
|
"search_country": "Търси държава...",
|
||||||
"search_for": "Търси за",
|
|
||||||
"search_for_existing_person": "Търси съществуващ човек",
|
"search_for_existing_person": "Търси съществуващ човек",
|
||||||
"search_no_people": "Няма хора",
|
"search_no_people": "Няма хора",
|
||||||
"search_no_people_named": "Няма хора на име \"{name}\"",
|
"search_no_people_named": "Няма хора на име \"{name}\"",
|
||||||
"search_options": "Опции за търсене",
|
"search_options": "Опции за търсене",
|
||||||
"search_people": "Търсете на хора",
|
"search_people": "Търсете на хора",
|
||||||
"search_places": "Търсене на места",
|
"search_places": "Търсене на места",
|
||||||
"search_rating": "Търси по рейтинг…",
|
|
||||||
"search_settings": "Търсене на настройки",
|
"search_settings": "Търсене на настройки",
|
||||||
"search_state": "Търсене на щат...",
|
"search_state": "Търсене на щат...",
|
||||||
"search_tags": "Търсене на етикети...",
|
"search_tags": "Търсене на етикети...",
|
||||||
@@ -1185,7 +1165,6 @@
|
|||||||
"shared_from_partner": "Снимки от {partner}",
|
"shared_from_partner": "Снимки от {partner}",
|
||||||
"shared_link_options": "Опции за споделена връзка",
|
"shared_link_options": "Опции за споделена връзка",
|
||||||
"shared_links": "Споделени връзки",
|
"shared_links": "Споделени връзки",
|
||||||
"shared_links_description": "Сподели снимки и видеа с линк",
|
|
||||||
"shared_photos_and_videos_count": "{assetCount, plural, other {# споделени снимки и видеа.}}",
|
"shared_photos_and_videos_count": "{assetCount, plural, other {# споделени снимки и видеа.}}",
|
||||||
"shared_with_partner": "Споделено с {partner}",
|
"shared_with_partner": "Споделено с {partner}",
|
||||||
"sharing": "Споделени",
|
"sharing": "Споделени",
|
||||||
@@ -1208,7 +1187,6 @@
|
|||||||
"show_person_options": "Показване на опции за лица",
|
"show_person_options": "Показване на опции за лица",
|
||||||
"show_progress_bar": "Показване на прогрес бара",
|
"show_progress_bar": "Показване на прогрес бара",
|
||||||
"show_search_options": "Показване на опциите за търсене",
|
"show_search_options": "Показване на опциите за търсене",
|
||||||
"show_shared_links": "Покажи споделени линкове",
|
|
||||||
"show_slideshow_transition": "Покажи прехода на слайдшоуто",
|
"show_slideshow_transition": "Покажи прехода на слайдшоуто",
|
||||||
"show_supporter_badge": "Значка поддръжник",
|
"show_supporter_badge": "Значка поддръжник",
|
||||||
"show_supporter_badge_description": "Покажи значка поддръжник",
|
"show_supporter_badge_description": "Покажи значка поддръжник",
|
||||||
@@ -1262,7 +1240,6 @@
|
|||||||
"tag_created": "Създаден етикет: {tag}",
|
"tag_created": "Създаден етикет: {tag}",
|
||||||
"tag_feature_description": "Разглеждане на снимки и видеоклипове, групирани по теми с логически тагове",
|
"tag_feature_description": "Разглеждане на снимки и видеоклипове, групирани по теми с логически тагове",
|
||||||
"tag_not_found_question": "Не можете да намерите етикет? Създайте такъв <link>тук</link>",
|
"tag_not_found_question": "Не можете да намерите етикет? Създайте такъв <link>тук</link>",
|
||||||
"tag_people": "Отбележи Хора",
|
|
||||||
"tag_updated": "Актуализиран етикет: {tag}",
|
"tag_updated": "Актуализиран етикет: {tag}",
|
||||||
"tagged_assets": "Тагнати {count, plural, one {# елемент} other {# елементи}}",
|
"tagged_assets": "Тагнати {count, plural, one {# елемент} other {# елементи}}",
|
||||||
"tags": "Етикет",
|
"tags": "Етикет",
|
||||||
@@ -1297,13 +1274,11 @@
|
|||||||
"unfavorite": "Премахване от любимите",
|
"unfavorite": "Премахване от любимите",
|
||||||
"unhide_person": "Покажи отново човека",
|
"unhide_person": "Покажи отново човека",
|
||||||
"unknown": "Неизвестно",
|
"unknown": "Неизвестно",
|
||||||
"unknown_country": "Непозната Държава",
|
|
||||||
"unknown_year": "Неизвестна година",
|
"unknown_year": "Неизвестна година",
|
||||||
"unlimited": "Неограничено",
|
"unlimited": "Неограничено",
|
||||||
"unlink_motion_video": "Премахни връзката с видео",
|
"unlink_motion_video": "Премахни връзката с видео",
|
||||||
"unlink_oauth": "Премахни OAuth",
|
"unlink_oauth": "Премахни OAuth",
|
||||||
"unlinked_oauth_account": "Премахни OAuth акаунт",
|
"unlinked_oauth_account": "Премахни OAuth акаунт",
|
||||||
"unmute_memories": "Включване на звука на спомените",
|
|
||||||
"unnamed_album": "Албум без име",
|
"unnamed_album": "Албум без име",
|
||||||
"unnamed_album_delete_confirmation": "Сигурни ли сте, че искате да изтриете този албум?",
|
"unnamed_album_delete_confirmation": "Сигурни ли сте, че искате да изтриете този албум?",
|
||||||
"unnamed_share": "Споделяне без име",
|
"unnamed_share": "Споделяне без име",
|
||||||
@@ -1357,7 +1332,6 @@
|
|||||||
"view_all": "Преглед на всички",
|
"view_all": "Преглед на всички",
|
||||||
"view_all_users": "Преглед на всички потребители",
|
"view_all_users": "Преглед на всички потребители",
|
||||||
"view_in_timeline": "Покажи във времева линия",
|
"view_in_timeline": "Покажи във времева линия",
|
||||||
"view_link": "Преглед на връзката",
|
|
||||||
"view_links": "Преглед на връзките",
|
"view_links": "Преглед на връзките",
|
||||||
"view_name": "Прегледай",
|
"view_name": "Прегледай",
|
||||||
"view_next_asset": "Преглед на следващия файл",
|
"view_next_asset": "Преглед на следващия файл",
|
||||||
|
|||||||
30
i18n/bi.json
30
i18n/bi.json
@@ -1,22 +1,20 @@
|
|||||||
{
|
{
|
||||||
"about": "abaot",
|
"account": "",
|
||||||
"account": "Akaont",
|
"account_settings": "",
|
||||||
"account_settings": "Seting blo Akaont",
|
"acknowledge": "",
|
||||||
"acknowledge": "Akcept",
|
|
||||||
"action": "",
|
"action": "",
|
||||||
"actions": "",
|
"actions": "",
|
||||||
"active": "Stap Mekem",
|
"active": "",
|
||||||
"activity": "Wanem hemi Mekem",
|
"activity": "",
|
||||||
"activity_changed": "WAnem hemi Mekem hemi",
|
"add": "",
|
||||||
"add": "Ad",
|
"add_a_description": "",
|
||||||
"add_a_description": "Putem Description blo hem",
|
"add_a_location": "",
|
||||||
"add_a_location": "Putem place blo hem",
|
"add_a_name": "",
|
||||||
"add_a_name": "Putem nam blo hem",
|
"add_a_title": "",
|
||||||
"add_a_title": "Putem wan name blo hem",
|
"add_exclusion_pattern": "",
|
||||||
"add_exclusion_pattern": "Putem wan paten wae hemi karem aot",
|
"add_import_path": "",
|
||||||
"add_import_path": "Putem wan pat blo import",
|
"add_location": "",
|
||||||
"add_location": "Putem wan place blo hem",
|
"add_more_users": "",
|
||||||
"add_more_users": "Putem mor man",
|
|
||||||
"add_partner": "",
|
"add_partner": "",
|
||||||
"add_path": "",
|
"add_path": "",
|
||||||
"add_photos": "",
|
"add_photos": "",
|
||||||
|
|||||||
818
i18n/ca.json
818
i18n/ca.json
File diff suppressed because it is too large
Load Diff
832
i18n/cs.json
832
i18n/cs.json
File diff suppressed because it is too large
Load Diff
906
i18n/da.json
906
i18n/da.json
File diff suppressed because it is too large
Load Diff
814
i18n/de.json
814
i18n/de.json
File diff suppressed because it is too large
Load Diff
809
i18n/el.json
809
i18n/el.json
File diff suppressed because it is too large
Load Diff
821
i18n/en.json
821
i18n/en.json
File diff suppressed because it is too large
Load Diff
828
i18n/es.json
828
i18n/es.json
File diff suppressed because it is too large
Load Diff
44
i18n/et.json
44
i18n/et.json
@@ -41,7 +41,6 @@
|
|||||||
"backup_settings": "Varundamise seaded",
|
"backup_settings": "Varundamise seaded",
|
||||||
"backup_settings_description": "Halda andmebaasi varundamise seadeid",
|
"backup_settings_description": "Halda andmebaasi varundamise seadeid",
|
||||||
"check_all": "Märgi kõik",
|
"check_all": "Märgi kõik",
|
||||||
"cleanup": "Koristus",
|
|
||||||
"cleared_jobs": "Tööted eemaldatud: {job}",
|
"cleared_jobs": "Tööted eemaldatud: {job}",
|
||||||
"config_set_by_file": "Konfiguratsioon on määratud konfifaili abil",
|
"config_set_by_file": "Konfiguratsioon on määratud konfifaili abil",
|
||||||
"confirm_delete_library": "Kas oled kindel, et soovid kustutada {library} kogu?",
|
"confirm_delete_library": "Kas oled kindel, et soovid kustutada {library} kogu?",
|
||||||
@@ -66,11 +65,6 @@
|
|||||||
"forcing_refresh_library_files": "Kogu kõigi failide sundvärskendamine",
|
"forcing_refresh_library_files": "Kogu kõigi failide sundvärskendamine",
|
||||||
"image_format": "Formaat",
|
"image_format": "Formaat",
|
||||||
"image_format_description": "WebP failid on väiksemad kui JPEG, aga kodeerimine on aeglasem.",
|
"image_format_description": "WebP failid on väiksemad kui JPEG, aga kodeerimine on aeglasem.",
|
||||||
"image_fullsize_description": "Täismõõdus pilt ilma metaandmeteta, kasutatakse sisse suumimisel",
|
|
||||||
"image_fullsize_enabled": "Luba täismõõdus piltide genereerimine",
|
|
||||||
"image_fullsize_enabled_description": "Genereeri mitte-veebisõbralike formaatide jaoks täismõõdus pilt. Kui \"Eelista manustatud eelvaadet\" on lubatud, kasutatakse manustatud eelvaateid otse ilma teisendamiseta. Ei mõjuta veebisõbralikke formaate nagu JPEG.",
|
|
||||||
"image_fullsize_quality_description": "Täismõõdus pildi kvaliteet vahemikus 1-100. Kõrgem väärtus on parem, aga tulemuseks on suuremad failid.",
|
|
||||||
"image_fullsize_title": "Täismõõdus pildi seaded",
|
|
||||||
"image_prefer_embedded_preview": "Eelista manustatud eelvaadet",
|
"image_prefer_embedded_preview": "Eelista manustatud eelvaadet",
|
||||||
"image_prefer_embedded_preview_setting_description": "Kasuta pilditöötluse sisendina võimalusel RAW fotodesse manustatud eelvaateid. See võib mõnede piltide puhul anda tulemuseks täpsemad värvid, aga eelvaate kvaliteet sõltub konkreetsest kaamerast ning pildis võib olla rohkem tihendusmüra.",
|
"image_prefer_embedded_preview_setting_description": "Kasuta pilditöötluse sisendina võimalusel RAW fotodesse manustatud eelvaateid. See võib mõnede piltide puhul anda tulemuseks täpsemad värvid, aga eelvaate kvaliteet sõltub konkreetsest kaamerast ning pildis võib olla rohkem tihendusmüra.",
|
||||||
"image_prefer_wide_gamut": "Eelista laia värvigammat",
|
"image_prefer_wide_gamut": "Eelista laia värvigammat",
|
||||||
@@ -102,7 +96,7 @@
|
|||||||
"library_scanning_enable_description": "Luba kogu perioodiline skaneerimine",
|
"library_scanning_enable_description": "Luba kogu perioodiline skaneerimine",
|
||||||
"library_settings": "Väline kogu",
|
"library_settings": "Väline kogu",
|
||||||
"library_settings_description": "Halda välise kogu seadeid",
|
"library_settings_description": "Halda välise kogu seadeid",
|
||||||
"library_tasks_description": "Otsi välistest kogudest uusi ja muutunud üksuseid",
|
"library_tasks_description": "Soorita kogu toiminguid",
|
||||||
"library_watching_enable_description": "Jälgi välises kogus failide muudatusi",
|
"library_watching_enable_description": "Jälgi välises kogus failide muudatusi",
|
||||||
"library_watching_settings": "Kogu jälgimine (EKSPERIMENTAALNE)",
|
"library_watching_settings": "Kogu jälgimine (EKSPERIMENTAALNE)",
|
||||||
"library_watching_settings_description": "Jälgi automaatselt muutunud faile",
|
"library_watching_settings_description": "Jälgi automaatselt muutunud faile",
|
||||||
@@ -137,7 +131,7 @@
|
|||||||
"machine_learning_smart_search_description": "Otsi pilte semantiliselt CLIP-manuste abil",
|
"machine_learning_smart_search_description": "Otsi pilte semantiliselt CLIP-manuste abil",
|
||||||
"machine_learning_smart_search_enabled": "Luba nutiotsing",
|
"machine_learning_smart_search_enabled": "Luba nutiotsing",
|
||||||
"machine_learning_smart_search_enabled_description": "Kui keelatud, siis ei kodeerita pilte nutiotsingu jaoks.",
|
"machine_learning_smart_search_enabled_description": "Kui keelatud, siis ei kodeerita pilte nutiotsingu jaoks.",
|
||||||
"machine_learning_url_description": "Masinõppe serveri URL. Kui ette on antud rohkem kui üks URL, proovitakse neid järjest ükshaaval, kuni üks edukalt vastab. Servereid, mis ei vasta, ignoreeritakse ajutiselt, kuni ühendus taastub.",
|
"machine_learning_url_description": "Masinõppe serveri URL. Kui ette on antud rohkem kui üks URL, proovitakse neid järjest ükshaaval, kuni üks edukalt vastab.",
|
||||||
"manage_concurrency": "Halda samaaegsust",
|
"manage_concurrency": "Halda samaaegsust",
|
||||||
"manage_log_settings": "Halda logi seadeid",
|
"manage_log_settings": "Halda logi seadeid",
|
||||||
"map_dark_style": "Tume stiil",
|
"map_dark_style": "Tume stiil",
|
||||||
@@ -153,8 +147,6 @@
|
|||||||
"map_settings": "Kaart",
|
"map_settings": "Kaart",
|
||||||
"map_settings_description": "Halda kaardi seadeid",
|
"map_settings_description": "Halda kaardi seadeid",
|
||||||
"map_style_description": "Kaarditeema style.json URL",
|
"map_style_description": "Kaarditeema style.json URL",
|
||||||
"memory_cleanup_job": "Mälestuste korrastamine",
|
|
||||||
"memory_generate_job": "Mälestuste genereerimine",
|
|
||||||
"metadata_extraction_job": "Metaandmete eraldamine",
|
"metadata_extraction_job": "Metaandmete eraldamine",
|
||||||
"metadata_extraction_job_description": "Eralda igast üksusest metaandmed, nagu GPS-koordinaadid, näod ja resolutsioon",
|
"metadata_extraction_job_description": "Eralda igast üksusest metaandmed, nagu GPS-koordinaadid, näod ja resolutsioon",
|
||||||
"metadata_faces_import_setting": "Luba nägude import",
|
"metadata_faces_import_setting": "Luba nägude import",
|
||||||
@@ -248,7 +240,7 @@
|
|||||||
"storage_template_hash_verification_enabled_description": "Lülitab sisse räsi kontrolli; ära lülita seda välja, kui sa ei ole tagajärgedest teadlik",
|
"storage_template_hash_verification_enabled_description": "Lülitab sisse räsi kontrolli; ära lülita seda välja, kui sa ei ole tagajärgedest teadlik",
|
||||||
"storage_template_migration": "Talletusmalli migreerimine",
|
"storage_template_migration": "Talletusmalli migreerimine",
|
||||||
"storage_template_migration_description": "Rakenda praegune <link>{template}</link> varem üleslaaditud üksustele",
|
"storage_template_migration_description": "Rakenda praegune <link>{template}</link> varem üleslaaditud üksustele",
|
||||||
"storage_template_migration_info": "Talletusmall teeb kõik faililaiendid väiketähtedeks. Malli muudatused rakenduvad ainult uutele üksustele. Et rakendada malli tagasiulatuvalt varem üleslaaditud üksustele, käivita <link>{job}</link>.",
|
"storage_template_migration_info": "Malli muudatused rakenduvad ainult uutele üksustele. Et rakendada malli tagasiulatuvalt varem üleslaaditud üksustele, käivita <link>{job}</link>.",
|
||||||
"storage_template_migration_job": "Talletusmallide migreerimise tööde",
|
"storage_template_migration_job": "Talletusmallide migreerimise tööde",
|
||||||
"storage_template_more_details": "Et selle funktsiooni kohta rohkem teada saada, loe <template-link>talletusmallide</template-link> ja nende <implications-link>tagajärgede</implications-link> kohta",
|
"storage_template_more_details": "Et selle funktsiooni kohta rohkem teada saada, loe <template-link>talletusmallide</template-link> ja nende <implications-link>tagajärgede</implications-link> kohta",
|
||||||
"storage_template_onboarding_description": "Kui sisse lülitatud, võimaldab see faile kasutaja määratud malli alusel automaatselt organiseerida. Stabiilsusprobleemide tõttu on see funktsioon vaikimisi välja lülitatud. Rohkem infot leiad <link>dokumentatsioonist</link>.",
|
"storage_template_onboarding_description": "Kui sisse lülitatud, võimaldab see faile kasutaja määratud malli alusel automaatselt organiseerida. Stabiilsusprobleemide tõttu on see funktsioon vaikimisi välja lülitatud. Rohkem infot leiad <link>dokumentatsioonist</link>.",
|
||||||
@@ -307,7 +299,7 @@
|
|||||||
"transcoding_max_b_frames": "Maksimaalne B-kaadrite arv",
|
"transcoding_max_b_frames": "Maksimaalne B-kaadrite arv",
|
||||||
"transcoding_max_b_frames_description": "Kõrgemad väärtused parandavad pakkimise efektiivsust, aga aeglustavad kodeerimist. See valik ei pruugi olla ühilduv riistvaralise kiirendusega vanematel seadmetel. 0 lülitab B-kaadrid välja, -1 määrab väärtuse automaatselt.",
|
"transcoding_max_b_frames_description": "Kõrgemad väärtused parandavad pakkimise efektiivsust, aga aeglustavad kodeerimist. See valik ei pruugi olla ühilduv riistvaralise kiirendusega vanematel seadmetel. 0 lülitab B-kaadrid välja, -1 määrab väärtuse automaatselt.",
|
||||||
"transcoding_max_bitrate": "Maksimaalne bitisagedus",
|
"transcoding_max_bitrate": "Maksimaalne bitisagedus",
|
||||||
"transcoding_max_bitrate_description": "Maksimaalse bitisageduse määramine teeb failisuurused ennustatavamaks, väikese kvaliteedikao hinnaga. 720p resolutsiooni puhul on tüüpilised väärtused 2600 kbit/s (VP9 ja HEVC) või 4500 kbit/s (H.264). Väärtus 0 eemaldab piirangu.",
|
"transcoding_max_bitrate_description": "Maksimaalse bitisageduse määramine teeb failisuurused ennustatavamaks, väikese kvaliteedikao hinnaga. 720p resolutsiooni puhul on tüüpilised väärtused 2600k (VP9 ja HEVC) või 4500k (H.264). Väärtus 0 eemaldab piirangu.",
|
||||||
"transcoding_max_keyframe_interval": "Maksimaalne võtmekaadri intervall",
|
"transcoding_max_keyframe_interval": "Maksimaalne võtmekaadri intervall",
|
||||||
"transcoding_max_keyframe_interval_description": "Määrab maksimaalse kauguse võtmekaadrite vahel. Madalamad väärtused vähendavad pakkimise efektiivsust, aga parandavad otsimiskiirust ning võivad tõsta kiire liikumisega stseenide kvaliteeti. 0 määrab väärtuse automaatselt.",
|
"transcoding_max_keyframe_interval_description": "Määrab maksimaalse kauguse võtmekaadrite vahel. Madalamad väärtused vähendavad pakkimise efektiivsust, aga parandavad otsimiskiirust ning võivad tõsta kiire liikumisega stseenide kvaliteeti. 0 määrab väärtuse automaatselt.",
|
||||||
"transcoding_optimal_description": "Kõrgema kui lubatud resolutsiooniga või mittelubatud formaadis videod",
|
"transcoding_optimal_description": "Kõrgema kui lubatud resolutsiooniga või mittelubatud formaadis videod",
|
||||||
@@ -399,7 +391,6 @@
|
|||||||
"allow_edits": "Luba muutmine",
|
"allow_edits": "Luba muutmine",
|
||||||
"allow_public_user_to_download": "Luba avalikul kasutajal alla laadida",
|
"allow_public_user_to_download": "Luba avalikul kasutajal alla laadida",
|
||||||
"allow_public_user_to_upload": "Luba avalikul kasutajal üles laadida",
|
"allow_public_user_to_upload": "Luba avalikul kasutajal üles laadida",
|
||||||
"alt_text_qr_code": "QR kood",
|
|
||||||
"anti_clockwise": "Vastupäeva",
|
"anti_clockwise": "Vastupäeva",
|
||||||
"api_key": "API võti",
|
"api_key": "API võti",
|
||||||
"api_key_description": "Seda väärtust kuvatakse ainult üks kord. Kopeeri see enne akna sulgemist.",
|
"api_key_description": "Seda väärtust kuvatakse ainult üks kord. Kopeeri see enne akna sulgemist.",
|
||||||
@@ -440,7 +431,7 @@
|
|||||||
"assets_were_part_of_album_count": "{count, plural, one {Üksus oli} other {Üksused olid}} juba osa albumist",
|
"assets_were_part_of_album_count": "{count, plural, one {Üksus oli} other {Üksused olid}} juba osa albumist",
|
||||||
"authorized_devices": "Autoriseeritud seadmed",
|
"authorized_devices": "Autoriseeritud seadmed",
|
||||||
"back": "Tagasi",
|
"back": "Tagasi",
|
||||||
"back_close_deselect": "Tagasi, sulge või tühista valik",
|
"back_close_deselect": "Tagasi, sulge, või tühista valik",
|
||||||
"backward": "Tagasi",
|
"backward": "Tagasi",
|
||||||
"birthdate_saved": "Sünnikuupäev salvestatud",
|
"birthdate_saved": "Sünnikuupäev salvestatud",
|
||||||
"birthdate_set_description": "Sünnikuupäeva kasutatakse isiku vanuse arvutamiseks foto tegemise hetkel.",
|
"birthdate_set_description": "Sünnikuupäeva kasutatakse isiku vanuse arvutamiseks foto tegemise hetkel.",
|
||||||
@@ -490,7 +481,6 @@
|
|||||||
"comments_are_disabled": "Kommentaarid on keelatud",
|
"comments_are_disabled": "Kommentaarid on keelatud",
|
||||||
"confirm": "Kinnita",
|
"confirm": "Kinnita",
|
||||||
"confirm_admin_password": "Kinnita administraatori parool",
|
"confirm_admin_password": "Kinnita administraatori parool",
|
||||||
"confirm_delete_face": "Kas oled kindel, et soovid isiku {name} näo üksuselt kustutada?",
|
|
||||||
"confirm_delete_shared_link": "Kas oled kindel, et soovid selle jagatud lingi kustutada?",
|
"confirm_delete_shared_link": "Kas oled kindel, et soovid selle jagatud lingi kustutada?",
|
||||||
"confirm_keep_this_delete_others": "Kõik muud üksused selles virnas kustutatakse. Kas oled kindel, et soovid jätkata?",
|
"confirm_keep_this_delete_others": "Kõik muud üksused selles virnas kustutatakse. Kas oled kindel, et soovid jätkata?",
|
||||||
"confirm_password": "Kinnita parool",
|
"confirm_password": "Kinnita parool",
|
||||||
@@ -543,7 +533,6 @@
|
|||||||
"delete_album": "Kustuta album",
|
"delete_album": "Kustuta album",
|
||||||
"delete_api_key_prompt": "Kas oled kindel, et soovid selle API võtme kustutada?",
|
"delete_api_key_prompt": "Kas oled kindel, et soovid selle API võtme kustutada?",
|
||||||
"delete_duplicates_confirmation": "Kas oled kindel, et soovid need duplikaadid jäädavalt kustutada?",
|
"delete_duplicates_confirmation": "Kas oled kindel, et soovid need duplikaadid jäädavalt kustutada?",
|
||||||
"delete_face": "Kustuta nägu",
|
|
||||||
"delete_key": "Kustuta võti",
|
"delete_key": "Kustuta võti",
|
||||||
"delete_library": "Kustuta kogu",
|
"delete_library": "Kustuta kogu",
|
||||||
"delete_link": "Kustuta link",
|
"delete_link": "Kustuta link",
|
||||||
@@ -611,7 +600,6 @@
|
|||||||
"enabled": "Lubatud",
|
"enabled": "Lubatud",
|
||||||
"end_date": "Lõppkuupäev",
|
"end_date": "Lõppkuupäev",
|
||||||
"error": "Viga",
|
"error": "Viga",
|
||||||
"error_delete_face": "Viga näo kustutamisel",
|
|
||||||
"error_loading_image": "Viga pildi laadimisel",
|
"error_loading_image": "Viga pildi laadimisel",
|
||||||
"error_title": "Viga - midagi läks valesti",
|
"error_title": "Viga - midagi läks valesti",
|
||||||
"errors": {
|
"errors": {
|
||||||
@@ -730,7 +718,6 @@
|
|||||||
"unable_to_submit_job": "Tööte edastamine ebaõnnestus",
|
"unable_to_submit_job": "Tööte edastamine ebaõnnestus",
|
||||||
"unable_to_trash_asset": "Üksuse prügikasti liigutamine ebaõnnestus",
|
"unable_to_trash_asset": "Üksuse prügikasti liigutamine ebaõnnestus",
|
||||||
"unable_to_unlink_account": "Konto lahtiühendamine ebaõnnestus",
|
"unable_to_unlink_account": "Konto lahtiühendamine ebaõnnestus",
|
||||||
"unable_to_unlink_motion_video": "Liikuva video linkimise tühistamine ebaõnnestus",
|
|
||||||
"unable_to_update_album_cover": "Albumi kaanepildi muutmine ebaõnnestus",
|
"unable_to_update_album_cover": "Albumi kaanepildi muutmine ebaõnnestus",
|
||||||
"unable_to_update_album_info": "Albumi info muutmine ebaõnnestus",
|
"unable_to_update_album_info": "Albumi info muutmine ebaõnnestus",
|
||||||
"unable_to_update_library": "Kogu uuendamine ebaõnnestus",
|
"unable_to_update_library": "Kogu uuendamine ebaõnnestus",
|
||||||
@@ -747,7 +734,6 @@
|
|||||||
"expired": "Aegunud",
|
"expired": "Aegunud",
|
||||||
"expires_date": "Aegub {date}",
|
"expires_date": "Aegub {date}",
|
||||||
"explore": "Avasta",
|
"explore": "Avasta",
|
||||||
"explorer": "Brauser",
|
|
||||||
"export": "Ekspordi",
|
"export": "Ekspordi",
|
||||||
"export_as_json": "Ekspordi JSON-formaati",
|
"export_as_json": "Ekspordi JSON-formaati",
|
||||||
"extension": "Laiend",
|
"extension": "Laiend",
|
||||||
@@ -756,7 +742,6 @@
|
|||||||
"face_unassigned": "Seostamata",
|
"face_unassigned": "Seostamata",
|
||||||
"failed_to_load_assets": "Üksuste laadimine ebaõnnestus",
|
"failed_to_load_assets": "Üksuste laadimine ebaõnnestus",
|
||||||
"favorite": "Lemmik",
|
"favorite": "Lemmik",
|
||||||
"favorite_or_unfavorite_photo": "Lisa foto lemmikutesse või eemalda lemmikutest",
|
|
||||||
"favorites": "Lemmikud",
|
"favorites": "Lemmikud",
|
||||||
"feature_photo_updated": "Esiletõstetud foto muudetud",
|
"feature_photo_updated": "Esiletõstetud foto muudetud",
|
||||||
"features": "Funktsioonid",
|
"features": "Funktsioonid",
|
||||||
@@ -814,7 +799,6 @@
|
|||||||
"include_shared_albums": "Kaasa jagatud albumid",
|
"include_shared_albums": "Kaasa jagatud albumid",
|
||||||
"include_shared_partner_assets": "Kaasa partneri jagatud üksused",
|
"include_shared_partner_assets": "Kaasa partneri jagatud üksused",
|
||||||
"individual_share": "Jagatud üksus",
|
"individual_share": "Jagatud üksus",
|
||||||
"individual_shares": "Jagatud üksused",
|
|
||||||
"info": "Info",
|
"info": "Info",
|
||||||
"interval": {
|
"interval": {
|
||||||
"day_at_onepm": "Iga päev kell 13",
|
"day_at_onepm": "Iga päev kell 13",
|
||||||
@@ -844,7 +828,6 @@
|
|||||||
"library_options": "Kogu seaded",
|
"library_options": "Kogu seaded",
|
||||||
"light": "Hele",
|
"light": "Hele",
|
||||||
"like_deleted": "Meeldimine kustutatud",
|
"like_deleted": "Meeldimine kustutatud",
|
||||||
"link_motion_video": "Lingi liikuv video",
|
|
||||||
"link_options": "Lingi valikud",
|
"link_options": "Lingi valikud",
|
||||||
"link_to_oauth": "Ühenda OAuth",
|
"link_to_oauth": "Ühenda OAuth",
|
||||||
"linked_oauth_account": "OAuth konto ühendatud",
|
"linked_oauth_account": "OAuth konto ühendatud",
|
||||||
@@ -864,7 +847,6 @@
|
|||||||
"loop_videos": "Taasesita videod",
|
"loop_videos": "Taasesita videod",
|
||||||
"loop_videos_description": "Lülita sisse, et detailvaates videot automaatselt taasesitada.",
|
"loop_videos_description": "Lülita sisse, et detailvaates videot automaatselt taasesitada.",
|
||||||
"main_branch_warning": "Sa kasutad arendusversiooni; soovitame tungivalt kasutada väljalaskeversiooni!",
|
"main_branch_warning": "Sa kasutad arendusversiooni; soovitame tungivalt kasutada väljalaskeversiooni!",
|
||||||
"main_menu": "Peamenüü",
|
|
||||||
"make": "Mark",
|
"make": "Mark",
|
||||||
"manage_shared_links": "Halda jagatud linke",
|
"manage_shared_links": "Halda jagatud linke",
|
||||||
"manage_sharing_with_partners": "Halda partneritega jagamist",
|
"manage_sharing_with_partners": "Halda partneritega jagamist",
|
||||||
@@ -897,7 +879,6 @@
|
|||||||
"month": "Kuu",
|
"month": "Kuu",
|
||||||
"more": "Rohkem",
|
"more": "Rohkem",
|
||||||
"moved_to_trash": "Liigutatud prügikasti",
|
"moved_to_trash": "Liigutatud prügikasti",
|
||||||
"mute_memories": "Vaigista mälestused",
|
|
||||||
"my_albums": "Minu albumid",
|
"my_albums": "Minu albumid",
|
||||||
"name": "Nimi",
|
"name": "Nimi",
|
||||||
"name_or_nickname": "Nimi või hüüdnimi",
|
"name_or_nickname": "Nimi või hüüdnimi",
|
||||||
@@ -993,7 +974,6 @@
|
|||||||
"permanently_deleted_asset": "Üksus jäädavalt kustutatud",
|
"permanently_deleted_asset": "Üksus jäädavalt kustutatud",
|
||||||
"permanently_deleted_assets_count": "{count, plural, one {# üksus} other {# üksust}} jäädavalt kustutatud",
|
"permanently_deleted_assets_count": "{count, plural, one {# üksus} other {# üksust}} jäädavalt kustutatud",
|
||||||
"person": "Isik",
|
"person": "Isik",
|
||||||
"person_birthdate": "Sündinud {date}",
|
|
||||||
"person_hidden": "{name}{hidden, select, true { (peidetud)} other {}}",
|
"person_hidden": "{name}{hidden, select, true { (peidetud)} other {}}",
|
||||||
"photo_shared_all_users": "Paistab, et oled oma fotosid kõigi kasutajatega jaganud, või pole ühtegi kasutajat, kellega jagada.",
|
"photo_shared_all_users": "Paistab, et oled oma fotosid kõigi kasutajatega jaganud, või pole ühtegi kasutajat, kellega jagada.",
|
||||||
"photos": "Fotod",
|
"photos": "Fotod",
|
||||||
@@ -1085,16 +1065,12 @@
|
|||||||
"remove_from_album": "Eemalda albumist",
|
"remove_from_album": "Eemalda albumist",
|
||||||
"remove_from_favorites": "Eemalda lemmikutest",
|
"remove_from_favorites": "Eemalda lemmikutest",
|
||||||
"remove_from_shared_link": "Eemalda jagatud lingist",
|
"remove_from_shared_link": "Eemalda jagatud lingist",
|
||||||
"remove_memory": "Eemalda mälestus",
|
|
||||||
"remove_photo_from_memory": "Eemalda foto sellest mälestusest",
|
|
||||||
"remove_url": "Eemalda URL",
|
"remove_url": "Eemalda URL",
|
||||||
"remove_user": "Eemalda kasutaja",
|
"remove_user": "Eemalda kasutaja",
|
||||||
"removed_api_key": "API võti eemaldatud: {name}",
|
"removed_api_key": "API võti eemaldatud: {name}",
|
||||||
"removed_from_archive": "Arhiivist eemaldatud",
|
"removed_from_archive": "Arhiivist eemaldatud",
|
||||||
"removed_from_favorites": "Lemmikutest eemaldatud",
|
"removed_from_favorites": "Lemmikutest eemaldatud",
|
||||||
"removed_from_favorites_count": "{count, plural, other {# eemaldatud}} lemmikutest",
|
"removed_from_favorites_count": "{count, plural, other {# eemaldatud}} lemmikutest",
|
||||||
"removed_memory": "Mäletus eemaldatud",
|
|
||||||
"removed_photo_from_memory": "Foto mälestustest eemaldatud",
|
|
||||||
"removed_tagged_assets": "Silt eemaldatud {count, plural, one {# üksuselt} other {# üksuselt}}",
|
"removed_tagged_assets": "Silt eemaldatud {count, plural, one {# üksuselt} other {# üksuselt}}",
|
||||||
"rename": "Nimeta ümber",
|
"rename": "Nimeta ümber",
|
||||||
"repair": "Parandus",
|
"repair": "Parandus",
|
||||||
@@ -1103,7 +1079,6 @@
|
|||||||
"repository": "Koodihoidla",
|
"repository": "Koodihoidla",
|
||||||
"require_password": "Nõua parooli",
|
"require_password": "Nõua parooli",
|
||||||
"require_user_to_change_password_on_first_login": "Nõua kasutajalt esmakordsel sisenemisel parooli muutmist",
|
"require_user_to_change_password_on_first_login": "Nõua kasutajalt esmakordsel sisenemisel parooli muutmist",
|
||||||
"rescan": "Skaneeri uuesti",
|
|
||||||
"reset": "Lähtesta",
|
"reset": "Lähtesta",
|
||||||
"reset_password": "Lähtesta parool",
|
"reset_password": "Lähtesta parool",
|
||||||
"reset_people_visibility": "Lähtesta isikute nähtavus",
|
"reset_people_visibility": "Lähtesta isikute nähtavus",
|
||||||
@@ -1147,7 +1122,6 @@
|
|||||||
"search_options": "Otsingu valikud",
|
"search_options": "Otsingu valikud",
|
||||||
"search_people": "Otsi inimesi",
|
"search_people": "Otsi inimesi",
|
||||||
"search_places": "Otsi kohti",
|
"search_places": "Otsi kohti",
|
||||||
"search_rating": "Otsi hinnangu järgi...",
|
|
||||||
"search_settings": "Otsi seadeid",
|
"search_settings": "Otsi seadeid",
|
||||||
"search_state": "Otsi osariiki...",
|
"search_state": "Otsi osariiki...",
|
||||||
"search_tags": "Otsi silte...",
|
"search_tags": "Otsi silte...",
|
||||||
@@ -1157,7 +1131,6 @@
|
|||||||
"searching_locales": "Lokaatide otsimine...",
|
"searching_locales": "Lokaatide otsimine...",
|
||||||
"second": "Sekund",
|
"second": "Sekund",
|
||||||
"see_all_people": "Vaata kõiki isikuid",
|
"see_all_people": "Vaata kõiki isikuid",
|
||||||
"select": "Vali",
|
|
||||||
"select_album_cover": "Vali albumi kaanepilt",
|
"select_album_cover": "Vali albumi kaanepilt",
|
||||||
"select_all": "Vali kõik",
|
"select_all": "Vali kõik",
|
||||||
"select_all_duplicates": "Vali kõik duplikaadid",
|
"select_all_duplicates": "Vali kõik duplikaadid",
|
||||||
@@ -1252,7 +1225,7 @@
|
|||||||
"start_date": "Alguskuupäev",
|
"start_date": "Alguskuupäev",
|
||||||
"state": "Osariik",
|
"state": "Osariik",
|
||||||
"status": "Staatus",
|
"status": "Staatus",
|
||||||
"stop_motion_photo": "Peata liikuv foto",
|
"stop_motion_photo": "Peata liikuv pilt",
|
||||||
"stop_photo_sharing": "Lõpeta oma fotode jagamine?",
|
"stop_photo_sharing": "Lõpeta oma fotode jagamine?",
|
||||||
"stop_photo_sharing_description": "{partner} ei pääse rohkem su fotodele ligi.",
|
"stop_photo_sharing_description": "{partner} ei pääse rohkem su fotodele ligi.",
|
||||||
"stop_sharing_photos_with_user": "Lõpeta oma fotode selle kasutajaga jagamine",
|
"stop_sharing_photos_with_user": "Lõpeta oma fotode selle kasutajaga jagamine",
|
||||||
@@ -1272,7 +1245,6 @@
|
|||||||
"tag_created": "Lisatud silt: {tag}",
|
"tag_created": "Lisatud silt: {tag}",
|
||||||
"tag_feature_description": "Fotode ja videote lehitsemine siltide kaupa grupeeritult",
|
"tag_feature_description": "Fotode ja videote lehitsemine siltide kaupa grupeeritult",
|
||||||
"tag_not_found_question": "Ei leia silti? <link>Lisa uus silt.</link>",
|
"tag_not_found_question": "Ei leia silti? <link>Lisa uus silt.</link>",
|
||||||
"tag_people": "Sildista inimesi",
|
|
||||||
"tag_updated": "Muudetud silt: {tag}",
|
"tag_updated": "Muudetud silt: {tag}",
|
||||||
"tagged_assets": "{count, plural, one {# üksus} other {# üksust}} sildistatud",
|
"tagged_assets": "{count, plural, one {# üksus} other {# üksust}} sildistatud",
|
||||||
"tags": "Sildid",
|
"tags": "Sildid",
|
||||||
@@ -1310,13 +1282,10 @@
|
|||||||
"unknown_country": "Tundmatu riik",
|
"unknown_country": "Tundmatu riik",
|
||||||
"unknown_year": "Teadmata aasta",
|
"unknown_year": "Teadmata aasta",
|
||||||
"unlimited": "Piiramatu",
|
"unlimited": "Piiramatu",
|
||||||
"unlink_motion_video": "Tühista liikuva video linkimine",
|
|
||||||
"unlink_oauth": "Eemalda OAuth ühendus",
|
"unlink_oauth": "Eemalda OAuth ühendus",
|
||||||
"unlinked_oauth_account": "OAuth ühendus eemaldatud",
|
"unlinked_oauth_account": "OAuth ühendus eemaldatud",
|
||||||
"unmute_memories": "Tühista mälestuste vaigistamine",
|
|
||||||
"unnamed_album": "Nimetu album",
|
"unnamed_album": "Nimetu album",
|
||||||
"unnamed_album_delete_confirmation": "Kas oled kindel, et soovid selle albumi kustutada?",
|
"unnamed_album_delete_confirmation": "Kas oled kindel, et soovid selle albumi kustutada?",
|
||||||
"unnamed_share": "Nimetu jagamine",
|
|
||||||
"unsaved_change": "Salvestamata muudatus",
|
"unsaved_change": "Salvestamata muudatus",
|
||||||
"unselect_all": "Ära vali ühtegi",
|
"unselect_all": "Ära vali ühtegi",
|
||||||
"unselect_all_duplicates": "Ära vali duplikaate",
|
"unselect_all_duplicates": "Ära vali duplikaate",
|
||||||
@@ -1367,7 +1336,6 @@
|
|||||||
"view_all": "Vaata kõiki",
|
"view_all": "Vaata kõiki",
|
||||||
"view_all_users": "Vaata kõiki kasutajaid",
|
"view_all_users": "Vaata kõiki kasutajaid",
|
||||||
"view_in_timeline": "Vaata ajajoonel",
|
"view_in_timeline": "Vaata ajajoonel",
|
||||||
"view_link": "Vaata linki",
|
|
||||||
"view_links": "Vaata linke",
|
"view_links": "Vaata linke",
|
||||||
"view_name": "Vaade",
|
"view_name": "Vaade",
|
||||||
"view_next_asset": "Vaata järgmist üksust",
|
"view_next_asset": "Vaata järgmist üksust",
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@@ -254,7 +254,7 @@
|
|||||||
"transcoding_max_b_frames": "بیشترین B-frames",
|
"transcoding_max_b_frames": "بیشترین B-frames",
|
||||||
"transcoding_max_b_frames_description": "مقادیر بالاتر کارایی فشرده سازی را بهبود میبخشند، اما کدگذاری را کند میکنند. ممکن است با شتاب دهی سختافزاری در دستگاههای قدیمی سازگار نباشد. مقدار( 0 ) B-frames را غیرفعال میکند، در حالی که مقدار ( 1 ) این مقدار را به صورت خودکار تنظیم میکند.",
|
"transcoding_max_b_frames_description": "مقادیر بالاتر کارایی فشرده سازی را بهبود میبخشند، اما کدگذاری را کند میکنند. ممکن است با شتاب دهی سختافزاری در دستگاههای قدیمی سازگار نباشد. مقدار( 0 ) B-frames را غیرفعال میکند، در حالی که مقدار ( 1 ) این مقدار را به صورت خودکار تنظیم میکند.",
|
||||||
"transcoding_max_bitrate": "بیشترین بیت ریت",
|
"transcoding_max_bitrate": "بیشترین بیت ریت",
|
||||||
"transcoding_max_bitrate_description": "تنظیم حداکثر بیتریت میتواند اندازه فایلها را در حدی قابل پیشبینیتر کند، هرچند که هزینه کمی برای کیفیت دارد. در وضوح 720p، مقادیر معمول 2600 kbit/s برای VP9 یا HEVC و 4500 kbit/s برای H.264 است. اگر به 0 تنظیم شود، غیرفعال میشود.",
|
"transcoding_max_bitrate_description": "تنظیم حداکثر بیتریت میتواند اندازه فایلها را در حدی قابل پیشبینیتر کند، هرچند که هزینه کمی برای کیفیت دارد. در وضوح 720p، مقادیر معمول 2600k برای VP9 یا HEVC و 4500k برای H.264 است. اگر به 0 تنظیم شود، غیرفعال میشود.",
|
||||||
"transcoding_max_keyframe_interval": "حداکثر فاصله کلید فریم",
|
"transcoding_max_keyframe_interval": "حداکثر فاصله کلید فریم",
|
||||||
"transcoding_max_keyframe_interval_description": "حداکثر فاصله فریم بین کلیدفریمها را تنظیم میکند. مقادیر پایینتر کارایی فشردهسازی را کاهش میدهند، اما زمان جستجو را بهبود میبخشند و ممکن است کیفیت را در صحنههای با حرکت سریع بهبود دهند. مقدار 0 این مقدار را بهطور خودکار تنظیم میکند.",
|
"transcoding_max_keyframe_interval_description": "حداکثر فاصله فریم بین کلیدفریمها را تنظیم میکند. مقادیر پایینتر کارایی فشردهسازی را کاهش میدهند، اما زمان جستجو را بهبود میبخشند و ممکن است کیفیت را در صحنههای با حرکت سریع بهبود دهند. مقدار 0 این مقدار را بهطور خودکار تنظیم میکند.",
|
||||||
"transcoding_optimal_description": "ویدیوهایی که از رزولوشن هدف بالاتر هستند یا در قالب پذیرفته شده نیستند",
|
"transcoding_optimal_description": "ویدیوهایی که از رزولوشن هدف بالاتر هستند یا در قالب پذیرفته شده نیستند",
|
||||||
|
|||||||
794
i18n/fi.json
794
i18n/fi.json
File diff suppressed because it is too large
Load Diff
814
i18n/fr.json
814
i18n/fr.json
File diff suppressed because it is too large
Load Diff
816
i18n/he.json
816
i18n/he.json
File diff suppressed because it is too large
Load Diff
804
i18n/hi.json
804
i18n/hi.json
File diff suppressed because it is too large
Load Diff
@@ -288,7 +288,7 @@
|
|||||||
"transcoding_max_b_frames": "Maksimalni B-frameovi",
|
"transcoding_max_b_frames": "Maksimalni B-frameovi",
|
||||||
"transcoding_max_b_frames_description": "Više vrijednosti poboljšavaju učinkovitost kompresije, ali usporavaju kodiranje. Možda nije kompatibilan s hardverskim ubrzanjem na starijim uređajima. 0 onemogućuje B-frameove, dok -1 automatski postavlja ovu vrijednost.",
|
"transcoding_max_b_frames_description": "Više vrijednosti poboljšavaju učinkovitost kompresije, ali usporavaju kodiranje. Možda nije kompatibilan s hardverskim ubrzanjem na starijim uređajima. 0 onemogućuje B-frameove, dok -1 automatski postavlja ovu vrijednost.",
|
||||||
"transcoding_max_bitrate": "Maksimalne brzina prijenosa (bitrate)",
|
"transcoding_max_bitrate": "Maksimalne brzina prijenosa (bitrate)",
|
||||||
"transcoding_max_bitrate_description": "Postavljanje maksimalne brzine prijenosa može učiniti veličine datoteka predvidljivijima uz manji trošak za kvalitetu. Pri 720p, tipične vrijednosti su 2600 kbit/s za VP9 ili HEVC ili 4500 kbit/s za H.264. Onemogućeno ako je postavljeno na 0.",
|
"transcoding_max_bitrate_description": "Postavljanje maksimalne brzine prijenosa može učiniti veličine datoteka predvidljivijima uz manji trošak za kvalitetu. Pri 720p, tipične vrijednosti su 2600k za VP9 ili HEVC ili 4500k za H.264. Onemogućeno ako je postavljeno na 0.",
|
||||||
"transcoding_max_keyframe_interval": "Maksimalni interval ključnih sličica",
|
"transcoding_max_keyframe_interval": "Maksimalni interval ključnih sličica",
|
||||||
"transcoding_max_keyframe_interval_description": "Postavlja maksimalnu udaljenost slika između ključnih kadrova. Niže vrijednosti pogoršavaju učinkovitost kompresije, ali poboljšavaju vrijeme traženja i mogu poboljšati kvalitetu u scenama s brzim kretanjem. 0 automatski postavlja ovu vrijednost.",
|
"transcoding_max_keyframe_interval_description": "Postavlja maksimalnu udaljenost slika između ključnih kadrova. Niže vrijednosti pogoršavaju učinkovitost kompresije, ali poboljšavaju vrijeme traženja i mogu poboljšati kvalitetu u scenama s brzim kretanjem. 0 automatski postavlja ovu vrijednost.",
|
||||||
"transcoding_optimal_description": "Videozapisi koji su veći od ciljne rezolucije ili nisu u prihvatljivom formatu",
|
"transcoding_optimal_description": "Videozapisi koji su veći od ciljne rezolucije ili nisu u prihvatljivom formatu",
|
||||||
@@ -468,7 +468,6 @@
|
|||||||
"comments_are_disabled": "Komentari onemogućeni",
|
"comments_are_disabled": "Komentari onemogućeni",
|
||||||
"confirm": "Potvrdi",
|
"confirm": "Potvrdi",
|
||||||
"confirm_admin_password": "Potvrdite lozinku administratora",
|
"confirm_admin_password": "Potvrdite lozinku administratora",
|
||||||
"confirm_delete_face": "Jeste li sigurni da želite izbrisati lice {name} iz knjižnice materijala.",
|
|
||||||
"confirm_delete_shared_link": "Jeste li sigurni da želite izbrisati ovu zajedničku vezu?",
|
"confirm_delete_shared_link": "Jeste li sigurni da želite izbrisati ovu zajedničku vezu?",
|
||||||
"confirm_keep_this_delete_others": "Sva druga sredstva u nizu bit će izbrisana osim ovog sredstva. Jeste li sigurni da želite nastaviti?",
|
"confirm_keep_this_delete_others": "Sva druga sredstva u nizu bit će izbrisana osim ovog sredstva. Jeste li sigurni da želite nastaviti?",
|
||||||
"confirm_password": "Potvrdite lozinku",
|
"confirm_password": "Potvrdite lozinku",
|
||||||
|
|||||||
819
i18n/hu.json
819
i18n/hu.json
File diff suppressed because it is too large
Load Diff
808
i18n/id.json
808
i18n/id.json
File diff suppressed because it is too large
Load Diff
846
i18n/it.json
846
i18n/it.json
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user