Merge branch 'main' into misc_tweaks

This commit is contained in:
Alex 2025-04-02 10:31:17 -05:00 committed by GitHub
commit d11fb479d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
336 changed files with 13896 additions and 4633 deletions

3
.gitattributes vendored
View File

@ -6,6 +6,9 @@ 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

View File

@ -13,7 +13,7 @@ jobs:
steps: steps:
- name: Generate a token - name: Generate a token
id: generate-token id: generate-token
uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1 uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # 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 }}

View File

@ -31,7 +31,7 @@ jobs:
steps: steps:
- name: Generate a token - name: Generate a token
id: generate-token id: generate-token
uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1 uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # 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 }}
@ -42,7 +42,7 @@ jobs:
token: ${{ steps.generate-token.outputs.token }} token: ${{ steps.generate-token.outputs.token }}
- name: Install uv - name: Install uv
uses: astral-sh/setup-uv@22695119d769bdb6f7032ad67b9bca0ef8c4a174 # v5 uses: astral-sh/setup-uv@0c5e2b8115b80b4c7c5ddf6ffdd634974642d182 # v5
- 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 }}"
@ -70,7 +70,7 @@ jobs:
steps: steps:
- name: Generate a token - name: Generate a token
id: generate-token id: generate-token
uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1 uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # 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 }}

View File

@ -384,7 +384,7 @@ jobs:
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Install uv - name: Install uv
uses: astral-sh/setup-uv@22695119d769bdb6f7032ad67b9bca0ef8c4a174 # v5 uses: astral-sh/setup-uv@0c5e2b8115b80b4c7c5ddf6ffdd634974642d182 # v5
- uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5 - uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5
# TODO: add caching when supported (https://github.com/actions/setup-python/pull/818) # TODO: add caching when supported (https://github.com/actions/setup-python/pull/818)
# with: # with:
@ -525,7 +525,7 @@ jobs:
- name: Generate new migrations - name: Generate new migrations
continue-on-error: true continue-on-error: true
run: npm run typeorm:migrations:generate ./src/migrations/TestMigration run: npm run migrations:generate TestMigration
- name: Find file changes - name: Find file changes
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20 uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20
@ -538,7 +538,7 @@ jobs:
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/migrations/*-TestMigration.ts cat ./src/*-TestMigration.ts
exit 1 exit 1
- name: Run SQL generation - name: Run SQL generation

View File

@ -39,6 +39,7 @@
], ],
"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"
} }
} }

View File

@ -104,7 +104,7 @@ For the mobile app, you can use `https://demo.immich.app` for the `Server Endpoi
| 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 | No | Yes | | Folder View | Yes | Yes |
## Translations ## Translations

View File

@ -1,39 +1,29 @@
import { FlatCompat } from '@eslint/eslintrc';
import js from '@eslint/js'; import js from '@eslint/js';
import typescriptEslint from '@typescript-eslint/eslint-plugin'; import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
import tsParser from '@typescript-eslint/parser'; import eslintPluginUnicorn from 'eslint-plugin-unicorn';
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 [ export default typescriptEslint.config([
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: tsParser, parser: typescriptEslint.parser,
ecmaVersion: 5, ecmaVersion: 5,
sourceType: 'module', sourceType: 'module',
@ -58,4 +48,4 @@ export default [
'object-shorthand': ['error', 'always'], 'object-shorthand': ['error', 'always'],
}, },
}, },
]; ]);

970
cli/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.57", "version": "2.2.61",
"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,9 +21,7 @@
"@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.13.10", "@types/node": "^22.13.14",
"@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",
@ -31,12 +29,13 @@
"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": "^56.0.1", "eslint-plugin-unicorn": "^57.0.0",
"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",

View File

Before

Width:  |  Height:  |  Size: 4.9 MiB

After

Width:  |  Height:  |  Size: 4.9 MiB

View File

@ -45,7 +45,7 @@ Some search examples:
</TabItem> </TabItem>
<TabItem value="Mobile" label="Mobile"> <TabItem value="Mobile" label="Mobile">
<img src={require('./img/moblie-smart-serach.webp').default} width="30%" title='Smart search on mobile' /> <img src={require('./img/mobile-smart-search.webp').default} width="30%" title='Smart search on mobile' />
</TabItem> </TabItem>
</Tabs> </Tabs>
@ -56,7 +56,20 @@ Navigating to `Administration > Settings > Machine Learning Settings > Smart Sea
### CLIP models ### CLIP models
More powerful models can be used for more accurate search results, but are slower and can require more server resources. Check the dropdowns below to see how they compare in memory usage, speed and quality by language. The default search model is fast, but there are many other options that can provide better search results. The tradeoff of using these models is that they're slower and/or use more memory (both when indexing images with background Smart Search jobs and when searching).
The first step of choosing the right model for you is to know which languages your users will search in.
If your users will only search in English, then the [CLIP][huggingface-clip] section is the first place to look. This is a curated list of the models that generally perform the best for their size class. The models here are ordered from higher to lower quality. This means that the top models will generally rank the most relevant results higher and have a higher capacity to understand descriptive, detailed, and/or niche queries. The models are also generally ordered from larger to smaller, so consider the impact on memory usage, job processing and search speed when deciding on one. The smaller models in this list are not too different in quality and many times faster.
[Multilingual models][huggingface-multilingual-clip] are also available so users can search in their native language. Use these models if you expect non-English searches to be common. They can be separated into two search patterns:
- `nllb` models expect the search query to be in the language specified in the user settings
- `xlm` and `siglip2` models understand search text regardless of the current language setting
`nllb` models tend to perform the best and are recommended when users primarily searches in their native, non-English language. `xlm` and `siglip2` models are more flexible and are recommended for mixed language search, where the same user might search in different languages at different times.
For more details, check the tables below to see how they compare in memory usage, speed and quality by language.
Once you've chosen a model, follow these steps: Once you've chosen a model, follow these steps:

View File

@ -1,3 +1,7 @@
---
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.

View File

@ -69,39 +69,4 @@ 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 or setup optional features below. Read the [Post Installation](/docs/install/post-install.mdx) steps and [upgrade instructions](/docs/install/upgrading.md).
### 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
[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

View File

@ -41,3 +41,9 @@ 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

View File

@ -67,10 +67,4 @@ Click "**Edit Rules**" and add the following firewall rules:
## Next Steps ## Next Steps
Read the [Post Installation](/docs/install/post-install.mdx) steps or setup optional features below. Read the [Post Installation](/docs/install/post-install.mdx) steps and [upgrade instructions](/docs/install/upgrading.md).
### 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

View File

@ -247,6 +247,10 @@ 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:

View File

@ -131,6 +131,10 @@ 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

View File

@ -0,0 +1,32 @@
---
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
```
[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
[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

View File

@ -1,2 +1,7 @@
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.
:::

View File

@ -1,4 +1,20 @@
[ [
{
"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", "label": "v1.130.3",
"url": "https://v1.130.3.archive.immich.app" "url": "https://v1.130.3.archive.immich.app"

View File

@ -1,39 +1,29 @@
import { FlatCompat } from '@eslint/eslintrc';
import js from '@eslint/js'; import js from '@eslint/js';
import typescriptEslint from '@typescript-eslint/eslint-plugin'; import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
import tsParser from '@typescript-eslint/parser'; import eslintPluginUnicorn from 'eslint-plugin-unicorn';
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 [ export default typescriptEslint.config([
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: tsParser, parser: typescriptEslint.parser,
ecmaVersion: 5, ecmaVersion: 5,
sourceType: 'module', sourceType: 'module',
@ -62,4 +52,4 @@ export default [
'object-shorthand': ['error', 'always'], 'object-shorthand': ['error', 'always'],
}, },
}, },
]; ]);

1361
e2e/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "immich-e2e", "name": "immich-e2e",
"version": "1.130.3", "version": "1.131.3",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",
@ -25,18 +25,16 @@
"@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.13.10", "@types/node": "^22.13.14",
"@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": "^56.0.1", "eslint-plugin-unicorn": "^57.0.0",
"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",
@ -49,6 +47,7 @@
"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"
}, },

View File

@ -1257,6 +1257,7 @@ 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 });
} }

View File

@ -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,7 +337,82 @@ 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 () => {

View File

@ -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="http://`); expect(resp.text).toContain(`<meta property="og:image" content="https://my.immich.app`);
}); });
}); });

View File

@ -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,

View File

@ -537,6 +537,7 @@ 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);

View File

@ -44,7 +44,7 @@ test.describe('Photo Viewer', () => {
const { x, y, width, height } = box!; const { x, y, width, height } = box!;
await page.mouse.move(x + width / 2, y + height / 2); await page.mouse.move(x + width / 2, y + height / 2);
await page.mouse.wheel(0, -1); await page.mouse.wheel(0, -1);
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('original'); 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 }) => {

View File

@ -987,6 +987,7 @@
"permanently_deleted_asset": "تم حذف الأصل بشكل نهائي", "permanently_deleted_asset": "تم حذف الأصل بشكل نهائي",
"permanently_deleted_assets_count": "تم حذف {count, plural, one {# محتوى} other {# المحتويات}} نهائيًا", "permanently_deleted_assets_count": "تم حذف {count, plural, one {# محتوى} other {# المحتويات}} نهائيًا",
"person": "شخص", "person": "شخص",
"person_birthdate": "تاريخ الميلاد {التاريخ}",
"person_hidden": "{name}{hidden, select, true { (مخفي)} other {}}", "person_hidden": "{name}{hidden, select, true { (مخفي)} other {}}",
"photo_shared_all_users": "يبدو أنك شاركت صورك مع جميع المستخدمين أو ليس لديك أي مستخدم للمشاركة معه.", "photo_shared_all_users": "يبدو أنك شاركت صورك مع جميع المستخدمين أو ليس لديك أي مستخدم للمشاركة معه.",
"photos": "الصور", "photos": "الصور",
@ -1078,6 +1079,8 @@
"remove_from_album": "إزالة من الألبوم", "remove_from_album": "إزالة من الألبوم",
"remove_from_favorites": "إزالة من المفضلة", "remove_from_favorites": "إزالة من المفضلة",
"remove_from_shared_link": "إزالة من الرابط المشترك", "remove_from_shared_link": "إزالة من الرابط المشترك",
"remove_memory": "إزالة الذاكرة",
"remove_photo_from_memory": "إزالة الصورة من هذه الذكرى",
"remove_url": "إزالة عنوان URL", "remove_url": "إزالة عنوان URL",
"remove_user": "إزالة المستخدم", "remove_user": "إزالة المستخدم",
"removed_api_key": "تم إزالة مفتاح API: {name}", "removed_api_key": "تم إزالة مفتاح API: {name}",
@ -1148,6 +1151,7 @@
"searching_locales": "جارٍ البحث في اللغات...", "searching_locales": "جارٍ البحث في اللغات...",
"second": "ثانية", "second": "ثانية",
"see_all_people": "عرض جميع الأشخاص", "see_all_people": "عرض جميع الأشخاص",
"select": "إختر",
"select_album_cover": "تحديد غلاف الألبوم", "select_album_cover": "تحديد غلاف الألبوم",
"select_all": "تحديد الكل", "select_all": "تحديد الكل",
"select_all_duplicates": "تحديد جميع النسخ المكررة", "select_all_duplicates": "تحديد جميع النسخ المكررة",

View File

@ -65,8 +65,13 @@
"forcing_refresh_library_files": "Forcing refresh of all library files", "forcing_refresh_library_files": "Forcing refresh of all library files",
"image_format": "Format", "image_format": "Format",
"image_format_description": "WebP produces smaller files than JPEG, but is slower to encode.", "image_format_description": "WebP produces smaller files than JPEG, but is slower to encode.",
"image_fullsize_enabled": "Enable full-size image generation",
"image_fullsize_enabled_description": "Generate full-size image for non-web-friendly formats. When \"Prefer embedded preview\" is enabled, embedded previews are used directly without conversion. Does not affect web-friendly formats like JPEG.",
"image_fullsize_quality_description": "Full-size image quality from 1-100. Higher is better, but produces larger files.",
"image_fullsize_title": "Full-size Image Settings",
"image_fullsize_description": "Full-size image with stripped metadata, used when zoomed in",
"image_prefer_embedded_preview": "Prefer embedded preview", "image_prefer_embedded_preview": "Prefer embedded preview",
"image_prefer_embedded_preview_setting_description": "Use embedded previews in RAW photos as the input to image processing when available. This can produce more accurate colors for some images, but the quality of the preview is camera-dependent and the image may have more compression artifacts.", "image_prefer_embedded_preview_setting_description": "Use embedded previews in RAW photos as the input to image processing and when available. This can produce more accurate colors for some images, but the quality of the preview is camera-dependent and the image may have more compression artifacts.",
"image_prefer_wide_gamut": "Prefer wide gamut", "image_prefer_wide_gamut": "Prefer wide gamut",
"image_prefer_wide_gamut_setting_description": "Use Display P3 for thumbnails. This better preserves the vibrance of images with wide colorspaces, but images may appear differently on old devices with an old browser version. sRGB images are kept as sRGB to avoid color shifts.", "image_prefer_wide_gamut_setting_description": "Use Display P3 for thumbnails. This better preserves the vibrance of images with wide colorspaces, but images may appear differently on old devices with an old browser version. sRGB images are kept as sRGB to avoid color shifts.",
"image_preview_description": "Medium-size image with stripped metadata, used when viewing a single asset and for machine learning", "image_preview_description": "Medium-size image with stripped metadata, used when viewing a single asset and for machine learning",
@ -859,6 +864,7 @@
"loop_videos": "Loop videos", "loop_videos": "Loop videos",
"loop_videos_description": "Enable to automatically loop a video in the detail viewer.", "loop_videos_description": "Enable to automatically loop a video in the detail viewer.",
"main_branch_warning": "Youre using a development version; we strongly recommend using a release version!", "main_branch_warning": "Youre using a development version; we strongly recommend using a release version!",
"main_menu": "Main menu",
"make": "Make", "make": "Make",
"manage_shared_links": "Manage shared links", "manage_shared_links": "Manage shared links",
"manage_sharing_with_partners": "Manage sharing with partners", "manage_sharing_with_partners": "Manage sharing with partners",

1
i18n/eu.json Normal file
View File

@ -0,0 +1 @@
{}

1
i18n/gl.json Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -50,6 +50,7 @@
"confirm_user_password_reset": "क्या आप वाकई {user} का पासवर्ड रीसेट करना चाहते हैं?", "confirm_user_password_reset": "क्या आप वाकई {user} का पासवर्ड रीसेट करना चाहते हैं?",
"create_job": "जॉब बनाएँ", "create_job": "जॉब बनाएँ",
"cron_expression": "क्रॉन अभिव्यक्ति", "cron_expression": "क्रॉन अभिव्यक्ति",
"cron_expression_description": "क्रॉन प्रारूप का उपयोग करके स्कैनिंग अंतराल सेट करें। अधिक जानकारी के लिए कृपया <link>क्रोनटैब गुरु</link> देखें",
"disable_login": "लॉगिन अक्षम करें", "disable_login": "लॉगिन अक्षम करें",
"duplicate_detection_job_description": "समान छवियों का पता लगाने के लिए संपत्तियों पर मशीन लर्निंग चलाएं। यह कार्यक्षमता स्मार्ट खोज पर निर्भर करती है", "duplicate_detection_job_description": "समान छवियों का पता लगाने के लिए संपत्तियों पर मशीन लर्निंग चलाएं। यह कार्यक्षमता स्मार्ट खोज पर निर्भर करती है",
"exclusion_pattern_description": "Exclusion पैटर्न आपको अपनी लाइब्रेरी को स्कैन करते समय फ़ाइलों और फ़ोल्डरों को अनदेखा करने देता है। यह उपयोगी है यदि आपके पास ऐसे फ़ोल्डर हैं जिनमें ऐसी फ़ाइलें हैं जिन्हें आप आयात नहीं करना चाहते हैं, जैसे RAW फ़ाइलें।", "exclusion_pattern_description": "Exclusion पैटर्न आपको अपनी लाइब्रेरी को स्कैन करते समय फ़ाइलों और फ़ोल्डरों को अनदेखा करने देता है। यह उपयोगी है यदि आपके पास ऐसे फ़ोल्डर हैं जिनमें ऐसी फ़ाइलें हैं जिन्हें आप आयात नहीं करना चाहते हैं, जैसे RAW फ़ाइलें।",
@ -61,11 +62,14 @@
"failed_job_command": "कार्य {job} के लिए आदेश {command} विफल", "failed_job_command": "कार्य {job} के लिए आदेश {command} विफल",
"force_delete_user_warning": "चेतावनी: इससे उपयोगकर्ता और सारा डेटा तुरंत हट जाएगा। इसे पूर्ववत नहीं किया जा सकता और फ़ाइलें पुनर्प्राप्त नहीं की जा सकतीं।", "force_delete_user_warning": "चेतावनी: इससे उपयोगकर्ता और सारा डेटा तुरंत हट जाएगा। इसे पूर्ववत नहीं किया जा सकता और फ़ाइलें पुनर्प्राप्त नहीं की जा सकतीं।",
"forcing_refresh_library_files": "सभी लाइब्रेरी फ़ाइलों को जबरन सामयिक करें", "forcing_refresh_library_files": "सभी लाइब्रेरी फ़ाइलों को जबरन सामयिक करें",
"image_format": "प्रारूप",
"image_format_description": "वेबपी, जेपीईजी की तुलना में छोटी फ़ाइलें बनाता है, लेकिन एनकोड करने में धीमा है।", "image_format_description": "वेबपी, जेपीईजी की तुलना में छोटी फ़ाइलें बनाता है, लेकिन एनकोड करने में धीमा है।",
"image_prefer_embedded_preview": "एम्बेडेड पूर्वावलोकन को प्राथमिकता दें", "image_prefer_embedded_preview": "एम्बेडेड पूर्वावलोकन को प्राथमिकता दें",
"image_prefer_embedded_preview_setting_description": "जब उपलब्ध हो तो RAW फ़ोटो में एम्बेडेड पूर्वावलोकन का उपयोग इमेज प्रोसेसिंग के इनपुट के रूप में करें। यह कुछ छवियों के लिए अधिक सटीक रंग उत्पन्न कर सकता है, लेकिन पूर्वावलोकन की गुणवत्ता कैमरे पर निर्भर करती है और छवि में अधिक संपीड़न कलाकृतियाँ हो सकती हैं।", "image_prefer_embedded_preview_setting_description": "जब उपलब्ध हो तो RAW फ़ोटो में एम्बेडेड पूर्वावलोकन का उपयोग इमेज प्रोसेसिंग के इनपुट के रूप में करें। यह कुछ छवियों के लिए अधिक सटीक रंग उत्पन्न कर सकता है, लेकिन पूर्वावलोकन की गुणवत्ता कैमरे पर निर्भर करती है और छवि में अधिक संपीड़न कलाकृतियाँ हो सकती हैं।",
"image_prefer_wide_gamut": "विस्तृत सरगम को प्राथमिकता दें", "image_prefer_wide_gamut": "विस्तृत सरगम को प्राथमिकता दें",
"image_prefer_wide_gamut_setting_description": "थंबनेल के लिए डिस्प्ले P3 का उपयोग करें। यह विस्तृत कलरस्पेस वाली छवियों की जीवंतता को बेहतर ढंग से संरक्षित करता है, लेकिन पुराने ब्राउज़र संस्करण वाले पुराने डिवाइस पर छवियां अलग-अलग दिखाई दे सकती हैं। रंग परिवर्तन से बचने के लिए sRGB छवियों को sRGB के रूप में रखा जाता है।", "image_prefer_wide_gamut_setting_description": "थंबनेल के लिए डिस्प्ले P3 का उपयोग करें। यह विस्तृत कलरस्पेस वाली छवियों की जीवंतता को बेहतर ढंग से संरक्षित करता है, लेकिन पुराने ब्राउज़र संस्करण वाले पुराने डिवाइस पर छवियां अलग-अलग दिखाई दे सकती हैं। रंग परिवर्तन से बचने के लिए sRGB छवियों को sRGB के रूप में रखा जाता है।",
"image_preview_description": "मेटाडेटा रहित मध्यम आकार की छवि, जिसका उपयोग एकल संपत्ति देखने और मशीन लर्निंग के लिए होता है",
"image_preview_title": "पूर्वदर्शन सेटिंग्स",
"image_quality": "गुणवत्ता", "image_quality": "गुणवत्ता",
"image_settings": "छवि सेटिंग्स", "image_settings": "छवि सेटिंग्स",
"image_settings_description": "उत्पन्न छवियों की गुणवत्ता और रिज़ॉल्यूशन प्रबंधित करें", "image_settings_description": "उत्पन्न छवियों की गुणवत्ता और रिज़ॉल्यूशन प्रबंधित करें",

View File

@ -35,7 +35,7 @@
"authentication_settings_disable_all": "Biztosan letiltod az összes bejelentkezési módot? A bejelentkezés teljesen le lesz tiltva.", "authentication_settings_disable_all": "Biztosan letiltod az összes bejelentkezési módot? A bejelentkezés teljesen le lesz tiltva.",
"authentication_settings_reenable": "Az újbóli engedélyezéshez használj egy<link>Szerver Parancsot</link>.", "authentication_settings_reenable": "Az újbóli engedélyezéshez használj egy<link>Szerver Parancsot</link>.",
"background_task_job": "Háttérfeladatok", "background_task_job": "Háttérfeladatok",
"backup_database": "Tartalék Adatbázis", "backup_database": "Adatbázis Biztonsági Mentése",
"backup_database_enable_description": "Adatbázis biztonsági mentések engedélyezése", "backup_database_enable_description": "Adatbázis biztonsági mentések engedélyezése",
"backup_keep_last_amount": "Megőrizendő korábbi biztonsági mentések száma", "backup_keep_last_amount": "Megőrizendő korábbi biztonsági mentések száma",
"backup_settings": "Biztonsági mentés beállításai", "backup_settings": "Biztonsági mentés beállításai",

View File

@ -7,7 +7,7 @@
"actions": "アクション", "actions": "アクション",
"active": "アクティブ", "active": "アクティブ",
"activity": "アクティビティ", "activity": "アクティビティ",
"activity_changed": "アクティビティは{enabled, select, true {有効化} other {無効化}}されました", "activity_changed": "アクティビティは{enabled, select, true {有効} other {無効}}になりました",
"add": "追加", "add": "追加",
"add_a_description": "説明を追加", "add_a_description": "説明を追加",
"add_a_location": "場所を追加", "add_a_location": "場所を追加",
@ -20,20 +20,28 @@
"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を追加",
"added_to_archive": "アーカイブに追加済", "added_to_archive": "アーカイブに追加済",
"added_to_favorites": "お気に入りに追加済", "added_to_favorites": "お気に入りに追加済",
"added_to_favorites_count": "{count, number} 枚の画像をお気に入りに追加済", "added_to_favorites_count": "{count, number} 枚の画像をお気に入りに追加済",
"admin": { "admin": {
"add_exclusion_pattern_description": "除外パターンを追加します。ワイルドカード「*」「**」「?」を使用できます。すべてのディレクトリで「Raw」と名前が付いたファイルを無視するには、「**/Raw/**」を使用します。また、「.tif」で終わるファイルをすべて無視するには、「**/*.tif」を使用します。さらに、絶対パスを無視するには「/path/to/ignore/**」を使用します。", "add_exclusion_pattern_description": "除外パターンを追加します。ワイルドカード「*」「**」「?」を使用できます。すべてのディレクトリで「Raw」と名前が付いたファイルを無視するには、「**/Raw/**」を使用します。また、「.tif」で終わるファイルをすべて無視するには、「**/*.tif」を使用します。さらに、絶対パスを無視するには「/path/to/ignore/**」を使用します。",
"asset_offline_description": "この外部ライブラリのアセットはディスク上に見つからなくなってゴミ箱に移動されました。ファイルがライブラリの中で移動された場合はタイムラインで新しい対応するアセットを確認してください。このアセットを復元するには以下のファイルパスがImmichからアクセスできるか確認してライブラリをスキャンしてください。",
"authentication_settings": "認証設定", "authentication_settings": "認証設定",
"authentication_settings_description": "認証設定の管理パスワード、OAuth、その他", "authentication_settings_description": "認証設定の管理パスワード、OAuth、その他",
"authentication_settings_disable_all": "本当に全てのログイン方法を無効にしますか? ログインは完全に無効になります。", "authentication_settings_disable_all": "本当に全てのログイン方法を無効にしますか? ログインは完全に無効になります。",
"authentication_settings_reenable": "再び有効にするには、<link>サーバーコマンド</link>を使用してください。", "authentication_settings_reenable": "再び有効にするには、<link>サーバーコマンド</link>を使用してください。",
"background_task_job": "バックグラウンドタスク", "background_task_job": "バックグラウンドタスク",
"backup_database": "データベースのバックアップ",
"backup_database_enable_description": "データベースのバックアップを有効にする",
"backup_keep_last_amount": "過去のバックアップの保持数",
"backup_settings": "バックアップ設定",
"backup_settings_description": "データベースのバックアップ設定の管理",
"check_all": "すべてを選択", "check_all": "すべてを選択",
"cleanup": "クリーンアップ",
"cleared_jobs": "{job}のジョブをクリアしました", "cleared_jobs": "{job}のジョブをクリアしました",
"config_set_by_file": "設定は現在 Config File で設定されている", "config_set_by_file": "設定は現在 Config File で設定されている",
"confirm_delete_library": "本当に {library} を削除しますか?", "confirm_delete_library": "本当に {library} を削除しますか?",
@ -41,6 +49,10 @@
"confirm_email_below": "確認のため、以下に \"{email}\" と入力してください", "confirm_email_below": "確認のため、以下に \"{email}\" と入力してください",
"confirm_reprocess_all_faces": "本当にすべての顔を再処理しますか? これにより名前が付けられた人物も消去されます。", "confirm_reprocess_all_faces": "本当にすべての顔を再処理しますか? これにより名前が付けられた人物も消去されます。",
"confirm_user_password_reset": "本当に {user} のパスワードをリセットしますか?", "confirm_user_password_reset": "本当に {user} のパスワードをリセットしますか?",
"create_job": "ジョブの作成",
"cron_expression": "Cron式",
"cron_expression_description": "cronのフォーマットを使ってスキャン間隔を設定します。詳しくは<link>Crontab Guru</link>などを参照してください",
"cron_expression_presets": "Cron式のプリセット",
"disable_login": "ログインを無効にする", "disable_login": "ログインを無効にする",
"duplicate_detection_job_description": "機械学習を用いて類似画像の検出を行います。(スマートサーチに依存)", "duplicate_detection_job_description": "機械学習を用いて類似画像の検出を行います。(スマートサーチに依存)",
"exclusion_pattern_description": "除外パターンを使用すると、ライブラリをスキャンする際にファイルやフォルダを無視することができます。RAWファイルなど、インポートしたくないファイルを含むフォルダがある場合に便利です。", "exclusion_pattern_description": "除外パターンを使用すると、ライブラリをスキャンする際にファイルやフォルダを無視することができます。RAWファイルなど、インポートしたくないファイルを含むフォルダがある場合に便利です。",
@ -52,15 +64,25 @@
"failed_job_command": "ジョブ {job}のコマンド {command}が失敗しました", "failed_job_command": "ジョブ {job}のコマンド {command}が失敗しました",
"force_delete_user_warning": "警告:この操作を行うと、ユーザーとすべてのアセットが直ちに削除されます。これは元に戻せず、ファイルも復元できません。", "force_delete_user_warning": "警告:この操作を行うと、ユーザーとすべてのアセットが直ちに削除されます。これは元に戻せず、ファイルも復元できません。",
"forcing_refresh_library_files": "すべてのライブラリファイルを強制更新", "forcing_refresh_library_files": "すべてのライブラリファイルを強制更新",
"image_format": "フォーマット",
"image_format_description": "WebPはJPEGよりもファイルサイズが小さいですが、エンコードに時間がかかります。", "image_format_description": "WebPはJPEGよりもファイルサイズが小さいですが、エンコードに時間がかかります。",
"image_prefer_embedded_preview": "埋め込みプレビューを優先", "image_prefer_embedded_preview": "埋め込みプレビューを優先",
"image_prefer_embedded_preview_setting_description": "RAW写真の埋め込みプレビューが利用可能な場合に画像処理の入力として使用します。これにより、いくつかの画像でより正確な色を得ることができますが、プレビューの品質はカメラによって異なり、画像により多くの圧縮アーティファクトが含まれる場合があります。", "image_prefer_embedded_preview_setting_description": "RAW写真の埋め込みプレビューが利用可能な場合に画像処理の入力として使用します。これにより、いくつかの画像でより正確な色を得ることができますが、プレビューの品質はカメラによって異なり、画像により多くの圧縮アーティファクトが含まれる場合があります。",
"image_prefer_wide_gamut": "広色域に対応させる", "image_prefer_wide_gamut": "広色域に対応させる",
"image_prefer_wide_gamut_setting_description": "サムネイルにはDisplay P3を使用します。これにより、広色域の画像の鮮やかさをよりよく保つことができますが、古いデバイスや古いブラウザバージョンでは画像が異なって見える場合があります。sRGBの画像は、色の変化を避けるためにsRGBのままにします。", "image_prefer_wide_gamut_setting_description": "サムネイルにはDisplay P3を使用します。これにより、広色域の画像の鮮やかさをよりよく保つことができますが、古いデバイスや古いブラウザバージョンでは画像が異なって見える場合があります。sRGBの画像は、色の変化を避けるためにsRGBのままにします。",
"image_preview_description": "単一のアセットを表示する時や機械学習に使われるメタデータを取り除いた中サイズの画像",
"image_preview_quality_description": "プレビューの画質は1〜100で設定できます。値が高いほど品質は良くなりますがファイルサイズが大きくなってアプリの応答性が低下するおそれがあります。低い値を設定すると機械学習の品質に影響を与えるおそれがあります。",
"image_preview_title": "プレビュー設定",
"image_quality": "品質", "image_quality": "品質",
"image_resolution": "解像度",
"image_resolution_description": "解像度を上げるとより精細に保存できますが、エンコードに時間がかかりファイルサイズが大きくなってアプリの応答性が低下するおそれがあります。",
"image_settings": "画像設定", "image_settings": "画像設定",
"image_settings_description": "生成される画像の品質と解像度の設定", "image_settings_description": "生成される画像の品質と解像度の設定",
"image_thumbnail_description": "メインのタイムラインのような写真グループで表示する際に使われるメタデータを取り除いた小さなサムネイル",
"image_thumbnail_quality_description": "サムネイルの画質を1〜100の間で設定できます。値が大きいほど良い品質ですがファイルサイズが大きくなりアプリの応答性が低下します。",
"image_thumbnail_title": "サムネイル設定",
"job_concurrency": "{job} の同時実行数", "job_concurrency": "{job} の同時実行数",
"job_created": "ジョブを作成しました",
"job_not_concurrency_safe": "このジョブは安全に同時実行できません。", "job_not_concurrency_safe": "このジョブは安全に同時実行できません。",
"job_settings": "ジョブ設定", "job_settings": "ジョブ設定",
"job_settings_description": "ジョブの同時実行を管理します", "job_settings_description": "ジョブの同時実行を管理します",
@ -75,7 +97,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": "変更されたファイルを自動的に監視",
@ -110,7 +132,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", "machine_learning_url_description": "機械学習サーバーのURL。複数のURLが設定された場合は1つずつサーバーが正常に応答するまで接続を試みます。応答のないサーバーはオンラインになるまで一時的に無視されます。",
"manage_concurrency": "同時実行数の管理", "manage_concurrency": "同時実行数の管理",
"manage_log_settings": "ログ設定を管理します", "manage_log_settings": "ログ設定を管理します",
"map_dark_style": "ダークモード", "map_dark_style": "ダークモード",
@ -126,8 +148,14 @@
"map_settings": "地図", "map_settings": "地図",
"map_settings_description": "地図設定", "map_settings_description": "地図設定",
"map_style_description": "マップテーマstyle.jsonの参照先URL", "map_style_description": "マップテーマstyle.jsonの参照先URL",
"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_description": "画像のEXIFデータとサイドカーファイルから顔をインポート",
"metadata_settings": "メタデータ設定",
"metadata_settings_description": "メタデータの設定を管理します",
"migration_job": "マイグレーション", "migration_job": "マイグレーション",
"migration_job_description": "アセットおよび顔のサムネイルを最新のフォルダ構造に移行します", "migration_job_description": "アセットおよび顔のサムネイルを最新のフォルダ構造に移行します",
"no_paths_added": "パスが追加されていません", "no_paths_added": "パスが追加されていません",
@ -182,6 +210,7 @@
"password_settings": "パスワード ログイン", "password_settings": "パスワード ログイン",
"password_settings_description": "パスワード ログイン設定を管理します", "password_settings_description": "パスワード ログイン設定を管理します",
"paths_validated_successfully": "すべてのパスが正常に検証されました", "paths_validated_successfully": "すべてのパスが正常に検証されました",
"person_cleanup_job": "人物のクリーンアップ",
"quota_size_gib": "割り当て容量 (GiB)", "quota_size_gib": "割り当て容量 (GiB)",
"refreshing_all_libraries": "すべてのライブラリを更新", "refreshing_all_libraries": "すべてのライブラリを更新",
"registration": "管理者登録", "registration": "管理者登録",
@ -192,9 +221,13 @@
"require_password_change_on_login": "初回ログイン時にパスワード変更を要求する", "require_password_change_on_login": "初回ログイン時にパスワード変更を要求する",
"reset_settings_to_default": "設定をデフォルトにリセットします", "reset_settings_to_default": "設定をデフォルトにリセットします",
"reset_settings_to_recent_saved": "前回の設定値に戻す", "reset_settings_to_recent_saved": "前回の設定値に戻す",
"scanning_library": "ライブラリのスキャン",
"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):// を含める)",
"server_public_users": "公開ユーザー",
"server_public_users_description": "共有アルバムにユーザーを追加するとすべてのユーザー (名前とメールアドレス) がリスト化されます。無効にするとユーザーリストは管理者のみ利用可能になります。",
"server_settings": "サーバー設定", "server_settings": "サーバー設定",
"server_settings_description": "サーバー設定を管理します", "server_settings_description": "サーバー設定を管理します",
"server_welcome_message": "ウェルカム メッセージ", "server_welcome_message": "ウェルカム メッセージ",
@ -210,7 +243,7 @@
"storage_template_hash_verification_enabled_description": "ハッシュ検証の有効化(よくわからなければ、有効にしてください)", "storage_template_hash_verification_enabled_description": "ハッシュ検証の有効化(よくわからなければ、有効にしてください)",
"storage_template_migration": "ストレージ テンプレート の移行", "storage_template_migration": "ストレージ テンプレート の移行",
"storage_template_migration_description": "現在の<link>{template}</link>を以前にアップロードされたアセットに適用", "storage_template_migration_description": "現在の<link>{template}</link>を以前にアップロードされたアセットに適用",
"storage_template_migration_info": "テンプレートの変更は新しいアセットにのみ適用されます。 以前にアップロードしたアセットにテンプレートを遡って適用するには、<link>{job}</link> を実行してください。", "storage_template_migration_info": "ストレージテンプレートは全ての拡張子を小文字に変換します。テンプレートの変更は新しいアセットにのみ適用されます。 以前にアップロードしたアセットにテンプレートを遡って適用するには、<link>{job}</link> を実行してください。",
"storage_template_migration_job": "ストレージテンプレート移行ジョブ", "storage_template_migration_job": "ストレージテンプレート移行ジョブ",
"storage_template_more_details": "この機能の詳細については、<template-link>ストレージテンプレート</template-link>とその<implications-link>影響</implications-link>を参照してください", "storage_template_more_details": "この機能の詳細については、<template-link>ストレージテンプレート</template-link>とその<implications-link>影響</implications-link>を参照してください",
"storage_template_onboarding_description": "この機能を有効にすると、ユーザー定義のテンプレートに基づいてファイルが自動で整理されます。 安定性の問題のため、この機能はデフォルトでオフになっています。 詳細については、<link>ドキュメント</link>を参照してください。", "storage_template_onboarding_description": "この機能を有効にすると、ユーザー定義のテンプレートに基づいてファイルが自動で整理されます。 安定性の問題のため、この機能はデフォルトでオフになっています。 詳細については、<link>ドキュメント</link>を参照してください。",
@ -219,6 +252,17 @@
"storage_template_settings_description": "アップロードしたアセットのフォルダ構造とファイル名を管理します", "storage_template_settings_description": "アップロードしたアセットのフォルダ構造とファイル名を管理します",
"storage_template_user_label": "<code>{label}</code>はユーザーのストレージラベルです", "storage_template_user_label": "<code>{label}</code>はユーザーのストレージラベルです",
"system_settings": "システム設定", "system_settings": "システム設定",
"tag_cleanup_job": "タグのクリーンアップ",
"template_email_available_tags": "テンプレートで次の変数を使えます: {tags}",
"template_email_if_empty": "テンプレートが空の場合はデフォルトのメールが使われます。",
"template_email_invite_album": "アルバム招待のテンプレート",
"template_email_preview": "プレビュー",
"template_email_settings": "メールテンプレート",
"template_email_settings_description": "通知のメールテンプレートのカスタムを管理します",
"template_email_update_album": "アルバム更新のテンプレート",
"template_email_welcome": "ウェルカムメールのテンプレート",
"template_settings": "通知テンプレート",
"template_settings_description": "通知のためのカスタムテンプレートを管理します。",
"theme_custom_css_settings": "カスタムCSS", "theme_custom_css_settings": "カスタムCSS",
"theme_custom_css_settings_description": "CSS を使って Immich のデザインをカスタマイズできます。", "theme_custom_css_settings_description": "CSS を使って Immich のデザインをカスタマイズできます。",
"theme_settings": "テーマ設定", "theme_settings": "テーマ設定",
@ -248,6 +292,8 @@
"transcoding_constant_rate_factor": "CRF値 (-crf)", "transcoding_constant_rate_factor": "CRF値 (-crf)",
"transcoding_constant_rate_factor_description": "出力動画の品質レベル。H.264の場合は23、HEVCの場合は28、VP9の場合は31、AV1の場合は35が一般的な値です。値が低いほど品質が良くなりますが、ファイルサイズが大きくなります。", "transcoding_constant_rate_factor_description": "出力動画の品質レベル。H.264の場合は23、HEVCの場合は28、VP9の場合は31、AV1の場合は35が一般的な値です。値が低いほど品質が良くなりますが、ファイルサイズが大きくなります。",
"transcoding_disabled_description": "動画をトランスコードしない設定にしますが、これにより一部のクライアントで再生ができなくなる可能性があります", "transcoding_disabled_description": "動画をトランスコードしない設定にしますが、これにより一部のクライアントで再生ができなくなる可能性があります",
"transcoding_encoding_options": "エンコードオプション",
"transcoding_encoding_options_description": "エンコードされた動画のコーデック、解像度、画質、その他オプションの設定します",
"transcoding_hardware_acceleration": "ハードウェアアクセラレーション", "transcoding_hardware_acceleration": "ハードウェアアクセラレーション",
"transcoding_hardware_acceleration_description": "より高速ですが、同じビットレートではより低品質になります(実験的)", "transcoding_hardware_acceleration_description": "より高速ですが、同じビットレートではより低品質になります(実験的)",
"transcoding_hardware_decoding": "ハードウェアデコード", "transcoding_hardware_decoding": "ハードウェアデコード",
@ -260,6 +306,8 @@
"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": "設定解像度を超える動画、または容認されていない形式の動画",
"transcoding_policy": "トランスコードポリシー",
"transcoding_policy_description": "動画がいつトランスコードされるかを設定します",
"transcoding_preferred_hardware_device": "推奨ハードウェアデバイス", "transcoding_preferred_hardware_device": "推奨ハードウェアデバイス",
"transcoding_preferred_hardware_device_description": "VAAPI と QSV のみに適用されます。 ハードウェアトランスコードに使用されるdriードを設定します。", "transcoding_preferred_hardware_device_description": "VAAPI と QSV のみに適用されます。 ハードウェアトランスコードに使用されるdriードを設定します。",
"transcoding_preset_preset": "プリセット (-preset)", "transcoding_preset_preset": "プリセット (-preset)",
@ -268,7 +316,7 @@
"transcoding_reference_frames_description": "特定のフレームを圧縮するときに参照するフレームの数。より高い値は圧縮効率を改善しますが、エンコードが遅くなります。\"0\" に設定すると、この値が自動的に設定されます。", "transcoding_reference_frames_description": "特定のフレームを圧縮するときに参照するフレームの数。より高い値は圧縮効率を改善しますが、エンコードが遅くなります。\"0\" に設定すると、この値が自動的に設定されます。",
"transcoding_required_description": "許容されていない動画形式のみ", "transcoding_required_description": "許容されていない動画形式のみ",
"transcoding_settings": "動画トランスコード設定", "transcoding_settings": "動画トランスコード設定",
"transcoding_settings_description": "動画ファイルの解像度とエンコード情報を管理します", "transcoding_settings_description": "トランスコードする動画とその処理方法を管理します",
"transcoding_target_resolution": "解像度", "transcoding_target_resolution": "解像度",
"transcoding_target_resolution_description": "解像度を高くすると細かなディテールを保持できますが、エンコードに時間がかかり、ファイルサイズが大きくなり、アプリの応答性が低下する可能性があります。", "transcoding_target_resolution_description": "解像度を高くすると細かなディテールを保持できますが、エンコードに時間がかかり、ファイルサイズが大きくなり、アプリの応答性が低下する可能性があります。",
"transcoding_temporal_aq": "適応的量子化(Temporal AQ)", "transcoding_temporal_aq": "適応的量子化(Temporal AQ)",
@ -290,6 +338,7 @@
"trash_settings_description": "ごみ箱の設定を管理します", "trash_settings_description": "ごみ箱の設定を管理します",
"untracked_files": "追跡されていないファイル", "untracked_files": "追跡されていないファイル",
"untracked_files_description": "これらのファイルはアプリケーションによって追跡されていません。これらは移動の失敗、アップロードの中断、またはバグにより取り残されたものである可能性があります", "untracked_files_description": "これらのファイルはアプリケーションによって追跡されていません。これらは移動の失敗、アップロードの中断、またはバグにより取り残されたものである可能性があります",
"user_cleanup_job": "ユーザーのクリーンアップ",
"user_delete_delay": "<b>{user}</b>のアカウントとアセットは{delay, plural, one {#日} other {#日}}後に完全に削除されるように予定されます。", "user_delete_delay": "<b>{user}</b>のアカウントとアセットは{delay, plural, one {#日} other {#日}}後に完全に削除されるように予定されます。",
"user_delete_delay_settings": "遅延削除", "user_delete_delay_settings": "遅延削除",
"user_delete_delay_settings_description": "削除実行後、ユーザーのアカウントとアセットが完全に削除されるまでの日数。 ユーザー削除ジョブは深夜に実行され、削除の準備ができているユーザーを確認します。 この設定への変更は、次回の実行時に反映されます。", "user_delete_delay_settings_description": "削除実行後、ユーザーのアカウントとアセットが完全に削除されるまでの日数。 ユーザー削除ジョブは深夜に実行され、削除の準備ができているユーザーを確認します。 この設定への変更は、次回の実行時に反映されます。",
@ -345,6 +394,7 @@
"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": "この値は一回のみ表示されます。 ウィンドウを閉じる前に必ずコピーしてください。",
@ -368,8 +418,9 @@
"asset_offline": "アセットはオフラインです", "asset_offline": "アセットはオフラインです",
"asset_offline_description": "このアセットはオフラインです。 Immichはファイルの場所にアクセスできません。 アセットが利用可能であることを確認しライブラリを再スキャンしてください。", "asset_offline_description": "このアセットはオフラインです。 Immichはファイルの場所にアクセスできません。 アセットが利用可能であることを確認しライブラリを再スキャンしてください。",
"asset_skipped": "スキップ済", "asset_skipped": "スキップ済",
"asset_skipped_in_trash": "ゴミ箱の中",
"asset_uploaded": "アップロード済", "asset_uploaded": "アップロード済",
"asset_uploading": "アップロード中...", "asset_uploading": "アップロード中",
"assets": "アセット", "assets": "アセット",
"assets_added_count": "{count, plural, one {#個} other {#個}}のアセットを追加しました", "assets_added_count": "{count, plural, one {#個} other {#個}}のアセットを追加しました",
"assets_added_to_album_count": "{count, plural, one {#個} other {#個}}のアセットをアルバムに追加しました", "assets_added_to_album_count": "{count, plural, one {#個} other {#個}}のアセットをアルバムに追加しました",
@ -378,7 +429,7 @@
"assets_moved_to_trash_count": "{count, plural, one {#個} other {#個}}のアセットをごみ箱に移動しました", "assets_moved_to_trash_count": "{count, plural, one {#個} other {#個}}のアセットをごみ箱に移動しました",
"assets_permanently_deleted_count": "{count, plural, one {#個} other {#個}}のアセットを完全に削除しました", "assets_permanently_deleted_count": "{count, plural, one {#個} other {#個}}のアセットを完全に削除しました",
"assets_removed_count": "{count, plural, one {#個} other {#個}}のアセットを削除しました", "assets_removed_count": "{count, plural, one {#個} other {#個}}のアセットを削除しました",
"assets_restore_confirmation": "ごみ箱のアセットをすべて復元してもよろしいですか? この操作を元に戻すことはできません!", "assets_restore_confirmation": "ごみ箱のアセットをすべて復元してもよろしいですか? この操作を元に戻すことはできません! オフラインのアセットはこの方法では復元できません。",
"assets_restored_count": "{count, plural, one {#個} other {#個}}のアセットを復元しました", "assets_restored_count": "{count, plural, one {#個} other {#個}}のアセットを復元しました",
"assets_trashed_count": "{count, plural, one {#個} other {#個}}のアセットをごみ箱に移動しました", "assets_trashed_count": "{count, plural, one {#個} other {#個}}のアセットをごみ箱に移動しました",
"assets_were_part_of_album_count": "{count, plural, one {個} other {個}}のアセットは既にアルバムの一部です", "assets_were_part_of_album_count": "{count, plural, one {個} other {個}}のアセットは既にアルバムの一部です",
@ -389,6 +440,7 @@
"birthdate_saved": "生年月日が正常に保存されました", "birthdate_saved": "生年月日が正常に保存されました",
"birthdate_set_description": "生年月日は、写真撮影時のこの人物の年齢を計算するために使用されます。", "birthdate_set_description": "生年月日は、写真撮影時のこの人物の年齢を計算するために使用されます。",
"blurred_background": "ぼやけた背景", "blurred_background": "ぼやけた背景",
"bugs_and_feature_requests": "バグと機能のリクエスト",
"build": "ビルド", "build": "ビルド",
"build_image": "ビルドイメージ", "build_image": "ビルドイメージ",
"bulk_delete_duplicates_confirmation": "本当に {count, plural, one {#個} other {#個}}の重複したアセットを一括削除しますか?これにより各重複中の最大のアセットが保持され、他の全ての重複が削除されます。この操作を元に戻すことはできません!", "bulk_delete_duplicates_confirmation": "本当に {count, plural, one {#個} other {#個}}の重複したアセットを一括削除しますか?これにより各重複中の最大のアセットが保持され、他の全ての重複が削除されます。この操作を元に戻すことはできません!",
@ -433,7 +485,9 @@
"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_password": "確認", "confirm_password": "確認",
"contain": "収める", "contain": "収める",
"context": "状況", "context": "状況",
@ -474,25 +528,33 @@
"date_range": "日付", "date_range": "日付",
"day": "ライトモード", "day": "ライトモード",
"deduplicate_all": "全て重複排除", "deduplicate_all": "全て重複排除",
"deduplication_criteria_1": "バイト単位の画像サイズ",
"deduplication_criteria_2": "EXIFデータ数",
"deduplication_info": "重複排除情報",
"deduplication_info_description": "アセットを自動的に選択して重複を一括で削除するには次のようにします:",
"default_locale": "デフォルトのロケール", "default_locale": "デフォルトのロケール",
"default_locale_description": "ブラウザのロケールに基づいて日付と数値をフォーマットします", "default_locale_description": "ブラウザのロケールに基づいて日付と数値をフォーマットします",
"delete": "削除", "delete": "削除",
"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": "リンクを削除",
"delete_others": "ほかを削除",
"delete_shared_link": "共有リンクを消す", "delete_shared_link": "共有リンクを消す",
"delete_tag": "タグを削除する", "delete_tag": "タグを削除する",
"delete_tag_confirmation_prompt": "本当に{tagName}タグを削除しますか?", "delete_tag_confirmation_prompt": "本当に{tagName}タグを削除しますか?",
"delete_user": "ユーザーを削除", "delete_user": "ユーザーを削除",
"deleted_shared_link": "共有リンクを削除", "deleted_shared_link": "共有リンクを削除",
"deletes_missing_assets": "ディスクからなくなったアセットを削除する",
"description": "概要欄", "description": "概要欄",
"details": "詳細", "details": "詳細",
"direction": "方向", "direction": "方向",
"disabled": "無効", "disabled": "無効",
"disallow_edits": "編集を許可しない", "disallow_edits": "編集を許可しない",
"discord": "Discord",
"discover": "探索", "discover": "探索",
"dismiss_all_errors": "全てのエラーを無視", "dismiss_all_errors": "全てのエラーを無視",
"dismiss_error": "エラーを無視", "dismiss_error": "エラーを無視",
@ -501,6 +563,7 @@
"display_original_photos": "オリジナルの写真を表示", "display_original_photos": "オリジナルの写真を表示",
"display_original_photos_setting_description": "オリジナルのアセットが Web 互換である場合は、アセットを表示するときにサムネイルではなく元の写真を優先して表示します。これにより写真の表示速度が遅くなる可能性があります。", "display_original_photos_setting_description": "オリジナルのアセットが Web 互換である場合は、アセットを表示するときにサムネイルではなく元の写真を優先して表示します。これにより写真の表示速度が遅くなる可能性があります。",
"do_not_show_again": "このメッセージを再び表示しない", "do_not_show_again": "このメッセージを再び表示しない",
"documentation": "ドキュメント",
"done": "完了", "done": "完了",
"download": "ダウンロード", "download": "ダウンロード",
"download_include_embedded_motion_videos": "埋め込まれた動画", "download_include_embedded_motion_videos": "埋め込まれた動画",
@ -543,6 +606,7 @@
"enabled": "有効", "enabled": "有効",
"end_date": "終了日", "end_date": "終了日",
"error": "エラー", "error": "エラー",
"error_delete_face": "アセットから顔の削除ができませんでした",
"error_loading_image": "画像の読み込みエラー", "error_loading_image": "画像の読み込みエラー",
"error_title": "エラー - 問題が発生しました", "error_title": "エラー - 問題が発生しました",
"errors": { "errors": {
@ -570,6 +634,7 @@
"failed_to_create_shared_link": "共有リンクを作成できませんでした", "failed_to_create_shared_link": "共有リンクを作成できませんでした",
"failed_to_edit_shared_link": "共有リンクを編集できませんでした", "failed_to_edit_shared_link": "共有リンクを編集できませんでした",
"failed_to_get_people": "人物を取得できませんでした", "failed_to_get_people": "人物を取得できませんでした",
"failed_to_keep_this_delete_others": "ほかのアセットを削除できませんでした",
"failed_to_load_asset": "アセットを読み込めませんでした", "failed_to_load_asset": "アセットを読み込めませんでした",
"failed_to_load_assets": "アセットを読み込めませんでした", "failed_to_load_assets": "アセットを読み込めませんでした",
"failed_to_load_people": "人物を読み込めませんでした", "failed_to_load_people": "人物を読み込めませんでした",
@ -621,6 +686,7 @@
"unable_to_get_comments_number": "コメント数を取得できません", "unable_to_get_comments_number": "コメント数を取得できません",
"unable_to_get_shared_link": "共有リンクの取得に失敗しました", "unable_to_get_shared_link": "共有リンクの取得に失敗しました",
"unable_to_hide_person": "人物を非表示にできません", "unable_to_hide_person": "人物を非表示にできません",
"unable_to_link_motion_video": "モーションビデオをリンクできません",
"unable_to_link_oauth_account": "OAuth アカウントをリンクできません", "unable_to_link_oauth_account": "OAuth アカウントをリンクできません",
"unable_to_load_album": "アルバムを読み込めません", "unable_to_load_album": "アルバムを読み込めません",
"unable_to_load_asset_activity": "アセットのアクティビティを読み込めません", "unable_to_load_asset_activity": "アセットのアクティビティを読み込めません",
@ -659,6 +725,7 @@
"unable_to_submit_job": "ジョブを送信できません", "unable_to_submit_job": "ジョブを送信できません",
"unable_to_trash_asset": "アセットをゴミ箱に移動できません", "unable_to_trash_asset": "アセットをゴミ箱に移動できません",
"unable_to_unlink_account": "アカウントのリンクを解除できません", "unable_to_unlink_account": "アカウントのリンクを解除できません",
"unable_to_unlink_motion_video": "モーションビデオのリンクを解除できません",
"unable_to_update_album_cover": "アルバムカバーを更新できません", "unable_to_update_album_cover": "アルバムカバーを更新できません",
"unable_to_update_album_info": "アルバム情報を更新できません", "unable_to_update_album_info": "アルバム情報を更新できません",
"unable_to_update_library": "ライブラリを更新できません", "unable_to_update_library": "ライブラリを更新できません",
@ -682,6 +749,7 @@
"external": "外部", "external": "外部",
"external_libraries": "外部ライブラリ", "external_libraries": "外部ライブラリ",
"face_unassigned": "未割り当て", "face_unassigned": "未割り当て",
"failed_to_load_assets": "アセットのロードに失敗しました",
"favorite": "お気に入り", "favorite": "お気に入り",
"favorite_or_unfavorite_photo": "写真をお気に入りまたはお気に入り解除", "favorite_or_unfavorite_photo": "写真をお気に入りまたはお気に入り解除",
"favorites": "お気に入り", "favorites": "お気に入り",
@ -702,10 +770,13 @@
"get_help": "助けを求める", "get_help": "助けを求める",
"getting_started": "はじめる", "getting_started": "はじめる",
"go_back": "戻る", "go_back": "戻る",
"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})さん",
@ -738,6 +809,7 @@
"include_shared_albums": "共有アルバムを含める", "include_shared_albums": "共有アルバムを含める",
"include_shared_partner_assets": "パートナーがシェアしたアセットを含める", "include_shared_partner_assets": "パートナーがシェアしたアセットを含める",
"individual_share": "1枚の共有", "individual_share": "1枚の共有",
"individual_shares": "個人の共有",
"info": "情報", "info": "情報",
"interval": { "interval": {
"day_at_onepm": "毎日午後1時", "day_at_onepm": "毎日午後1時",
@ -751,6 +823,8 @@
"jobs": "ジョブ", "jobs": "ジョブ",
"keep": "保持", "keep": "保持",
"keep_all": "全て保持", "keep_all": "全て保持",
"keep_this_delete_others": "これを残してほかを削除する",
"kept_this_deleted_others": "このアセットを残して{count, plural, other {#件のアセット}}を削除する",
"keyboard_shortcuts": "キーボードショートカット", "keyboard_shortcuts": "キーボードショートカット",
"language": "言語", "language": "言語",
"language_setting_description": "優先言語を選択してください", "language_setting_description": "優先言語を選択してください",
@ -758,12 +832,14 @@
"latest_version": "最新バージョン", "latest_version": "最新バージョン",
"latitude": "緯度", "latitude": "緯度",
"leave": "標高", "leave": "標高",
"lens_model": "レンズモデル",
"let_others_respond": "他のユーザーの返信を許可する", "let_others_respond": "他のユーザーの返信を許可する",
"level": "レベル", "level": "レベル",
"library": "ライブラリ", "library": "ライブラリ",
"library_options": "ライブラリ設定", "library_options": "ライブラリ設定",
"light": "ライトモード", "light": "ライトモード",
"like_deleted": "いいねが削除されました", "like_deleted": "いいねが削除されました",
"link_motion_video": "モーションビデオのリンク",
"link_options": "リンクのオプション", "link_options": "リンクのオプション",
"link_to_oauth": "OAuthへリンクする", "link_to_oauth": "OAuthへリンクする",
"linked_oauth_account": "リンクされたOAuthアカウント", "linked_oauth_account": "リンクされたOAuthアカウント",
@ -782,6 +858,7 @@
"look": "見た目", "look": "見た目",
"loop_videos": "動画をループ", "loop_videos": "動画をループ",
"loop_videos_description": "有効にすると詳細表示で自動的に動画がループします。", "loop_videos_description": "有効にすると詳細表示で自動的に動画がループします。",
"main_branch_warning": "開発版を使っているようです。リリース版の使用を強く推奨します!",
"make": "メーカー", "make": "メーカー",
"manage_shared_links": "共有済みのリンクを管理", "manage_shared_links": "共有済みのリンクを管理",
"manage_sharing_with_partners": "パートナーとの共有を管理します", "manage_sharing_with_partners": "パートナーとの共有を管理します",
@ -814,6 +891,7 @@
"month": "月", "month": "月",
"more": "もっと表示", "more": "もっと表示",
"moved_to_trash": "ゴミ箱に移動しました", "moved_to_trash": "ゴミ箱に移動しました",
"mute_memories": "メモリーのミュート",
"my_albums": "私のアルバム", "my_albums": "私のアルバム",
"name": "名前", "name": "名前",
"name_or_nickname": "名前またはニックネーム", "name_or_nickname": "名前またはニックネーム",
@ -843,7 +921,7 @@
"no_results": "結果がありません", "no_results": "結果がありません",
"no_results_description": "同義語やより一般的なキーワードを試してください", "no_results_description": "同義語やより一般的なキーワードを試してください",
"no_shared_albums_message": "アルバムを作成して写真や動画を共有しましょう", "no_shared_albums_message": "アルバムを作成して写真や動画を共有しましょう",
"not_in_any_album": "どのアルバムにも入っていません", "not_in_any_album": "どのアルバムにも入っていない",
"note_apply_storage_label_to_previously_uploaded assets": "注意: 以前にアップロードしたアセットにストレージラベルを適用するには以下を実行してください", "note_apply_storage_label_to_previously_uploaded assets": "注意: 以前にアップロードしたアセットにストレージラベルを適用するには以下を実行してください",
"note_unlimited_quota": "注: 容量を無制限にするには0を入力してください", "note_unlimited_quota": "注: 容量を無制限にするには0を入力してください",
"notes": "注意", "notes": "注意",
@ -851,6 +929,7 @@
"notifications": "通知", "notifications": "通知",
"notifications_setting_description": "通知を管理します", "notifications_setting_description": "通知を管理します",
"oauth": "OAuth", "oauth": "OAuth",
"official_immich_resources": "公式Immichリソース",
"offline": "オフライン", "offline": "オフライン",
"offline_paths": "オフラインのパス", "offline_paths": "オフラインのパス",
"offline_paths_description": "これらの結果は、外部ライブラリの一部ではないファイルを手動で削除したことが原因である可能性があります。", "offline_paths_description": "これらの結果は、外部ライブラリの一部ではないファイルを手動で削除したことが原因である可能性があります。",
@ -908,6 +987,7 @@
"permanently_deleted_asset": "アセットを完全に削除しました", "permanently_deleted_asset": "アセットを完全に削除しました",
"permanently_deleted_assets_count": "{count, plural, one {#個} other {#個}}のアセットを完全に削除しました", "permanently_deleted_assets_count": "{count, plural, one {#個} other {#個}}のアセットを完全に削除しました",
"person": "人物", "person": "人物",
"person_birthdate": "{date}生まれ",
"person_hidden": "{name}{hidden, select, true { (非表示)} other {}}", "person_hidden": "{name}{hidden, select, true { (非表示)} other {}}",
"photo_shared_all_users": "写真をすべてのユーザーと共有したか、共有するユーザーがいないようです。", "photo_shared_all_users": "写真をすべてのユーザーと共有したか、共有するユーザーがいないようです。",
"photos": "写真", "photos": "写真",
@ -917,6 +997,7 @@
"pick_a_location": "場所を選択", "pick_a_location": "場所を選択",
"place": "場所", "place": "場所",
"places": "撮影場所", "places": "撮影場所",
"places_count": "{count, plural, other {{count, number}箇所}}",
"play": "再生", "play": "再生",
"play_memories": "メモリーを再生", "play_memories": "メモリーを再生",
"play_motion_photo": "モーションビデオを再生", "play_motion_photo": "モーションビデオを再生",
@ -976,14 +1057,17 @@
"reassigned_assets_to_new_person": "{count, plural, one {#個} other {#個}}のアセットを新しい人物に割り当てました", "reassigned_assets_to_new_person": "{count, plural, one {#個} other {#個}}のアセットを新しい人物に割り当てました",
"reassing_hint": "選択されたアセットを既存の人物に割り当て", "reassing_hint": "選択されたアセットを既存の人物に割り当て",
"recent": "最近", "recent": "最近",
"recent-albums": "最近のアルバム",
"recent_searches": "最近の検索", "recent_searches": "最近の検索",
"refresh": "更新", "refresh": "更新",
"refresh_encoded_videos": "エンコードされた動画を更新", "refresh_encoded_videos": "エンコードされた動画を更新",
"refresh_faces": "顔認識を更新",
"refresh_metadata": "メタデータを更新", "refresh_metadata": "メタデータを更新",
"refresh_thumbnails": "サムネイルを更新", "refresh_thumbnails": "サムネイルを更新",
"refreshed": "更新済", "refreshed": "更新済",
"refreshes_every_file": "すべてのファイルを更新", "refreshes_every_file": "すべてのファイルを更新",
"refreshing_encoded_video": "エンコードされた動画を更新中", "refreshing_encoded_video": "エンコードされた動画を更新中",
"refreshing_faces": "顔認識を更新中",
"refreshing_metadata": "メタデータを更新中", "refreshing_metadata": "メタデータを更新中",
"regenerating_thumbnails": "サムネイルを再生成中", "regenerating_thumbnails": "サムネイルを再生成中",
"remove": "削除", "remove": "削除",
@ -995,11 +1079,16 @@
"remove_from_album": "アルバムから削除", "remove_from_album": "アルバムから削除",
"remove_from_favorites": "お気に入りから削除", "remove_from_favorites": "お気に入りから削除",
"remove_from_shared_link": "共有リンクから削除", "remove_from_shared_link": "共有リンクから削除",
"remove_memory": "メモリーの削除",
"remove_photo_from_memory": "メモリーから写真を削除",
"remove_url": "URLの削除",
"remove_user": "ユーザーを削除", "remove_user": "ユーザーを削除",
"removed_api_key": "削除されたAPI キー: {name}", "removed_api_key": "削除されたAPI キー: {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": "修復",
@ -1008,6 +1097,7 @@
"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": "人物の非表示設定をリセット",
@ -1030,22 +1120,29 @@
"saved_settings": "設定を保存しました", "saved_settings": "設定を保存しました",
"say_something": "何か書き込みましょう", "say_something": "何か書き込みましょう",
"scan_all_libraries": "全てのライブラリをスキャン", "scan_all_libraries": "全てのライブラリをスキャン",
"scan_library": "スキャン",
"scan_settings": "スキャン設定", "scan_settings": "スキャン設定",
"scanning_for_album": "アルバムをスキャン中…", "scanning_for_album": "アルバムをスキャン中…",
"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_people": "人物を検索", "search_people": "人物を検索",
"search_places": "場所を検索", "search_places": "場所を検索",
"search_rating": "レートで検索...",
"search_settings": "検索設定",
"search_state": "都道府県を検索…", "search_state": "都道府県を検索…",
"search_tags": "タグを検索...", "search_tags": "タグを検索...",
"search_timezone": "タイムゾーンを検索…", "search_timezone": "タイムゾーンを検索…",
@ -1054,6 +1151,7 @@
"searching_locales": "ロケールを検索…", "searching_locales": "ロケールを検索…",
"second": "秒", "second": "秒",
"see_all_people": "全ての人物を見る", "see_all_people": "全ての人物を見る",
"select": "選択",
"select_album_cover": "アルバムカバーを選択", "select_album_cover": "アルバムカバーを選択",
"select_all": "全て選択", "select_all": "全て選択",
"select_all_duplicates": "全ての重複を選択", "select_all_duplicates": "全ての重複を選択",
@ -1076,6 +1174,7 @@
"server_version": "サーバーバージョン", "server_version": "サーバーバージョン",
"set": "設定", "set": "設定",
"set_as_album_cover": "アルバムカバーとして設定", "set_as_album_cover": "アルバムカバーとして設定",
"set_as_featured_photo": "人物写真に設定",
"set_as_profile_picture": "プロフィール画像として設定", "set_as_profile_picture": "プロフィール画像として設定",
"set_date_of_birth": "生年月日を設定", "set_date_of_birth": "生年月日を設定",
"set_profile_picture": "プロフィール画像を設定", "set_profile_picture": "プロフィール画像を設定",
@ -1090,6 +1189,7 @@
"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": "共有",
@ -1112,6 +1212,8 @@
"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_supporter_badge": "サポーターバッジ", "show_supporter_badge": "サポーターバッジ",
"show_supporter_badge_description": "サポーターバッジを表示", "show_supporter_badge_description": "サポーターバッジを表示",
"shuffle": "ランダム", "shuffle": "ランダム",
@ -1121,6 +1223,8 @@
"sign_up": "登録", "sign_up": "登録",
"size": "サイズ", "size": "サイズ",
"skip_to_content": "コンテンツへスキップ", "skip_to_content": "コンテンツへスキップ",
"skip_to_folders": "フォルダへスキップ",
"skip_to_tags": "タグへスキップ",
"slideshow": "スライドショー", "slideshow": "スライドショー",
"slideshow_settings": "スライドショー設定", "slideshow_settings": "スライドショー設定",
"sort_albums_by": "この順序でアルバムをソート…", "sort_albums_by": "この順序でアルバムをソート…",
@ -1128,6 +1232,7 @@
"sort_items": "アイテムの数", "sort_items": "アイテムの数",
"sort_modified": "変更日", "sort_modified": "変更日",
"sort_oldest": "古い写真", "sort_oldest": "古い写真",
"sort_people_by_similarity": "似ている順に人物を並び替える",
"sort_recent": "最新の写真", "sort_recent": "最新の写真",
"sort_title": "タイトル", "sort_title": "タイトル",
"source": "ソース", "source": "ソース",
@ -1151,12 +1256,17 @@
"submit": "送信", "submit": "送信",
"suggestions": "ユーザーリスト", "suggestions": "ユーザーリスト",
"sunrise_on_the_beach": "海岸の日の出", "sunrise_on_the_beach": "海岸の日の出",
"support": "サポート",
"support_and_feedback": "サポートとフィードバック",
"support_third_party_description": "Immichのインストールはサードパーティーによってパッケージ化されています。遭遇した問題はそのパッケージに起因している可能性があるので以下のリンクを使って最初にそのパッケージに問題を提起してください。",
"swap_merge_direction": "統合する方向を入れ替え", "swap_merge_direction": "統合する方向を入れ替え",
"sync": "同期", "sync": "同期",
"tag": "タグ付けする", "tag": "タグ付けする",
"tag_assets": "アセットにタグ付けする", "tag_assets": "アセットにタグ付けする",
"tag_created": "タグ: {tag} を作成しました", "tag_created": "タグ: {tag} を作成しました",
"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": "タグ",
@ -1165,15 +1275,19 @@
"theme_selection": "テーマ選択", "theme_selection": "テーマ選択",
"theme_selection_description": "ブラウザのシステム設定に基づいてテーマを明色または暗色に自動的に設定します", "theme_selection_description": "ブラウザのシステム設定に基づいてテーマを明色または暗色に自動的に設定します",
"they_will_be_merged_together": "これらは一緒に統合されます", "they_will_be_merged_together": "これらは一緒に統合されます",
"third_party_resources": "サードパーティーリソース",
"time_based_memories": "時間によるメモリー", "time_based_memories": "時間によるメモリー",
"timeline": "タイムライン",
"timezone": "タイムゾーン", "timezone": "タイムゾーン",
"to_archive": "アーカイブ", "to_archive": "アーカイブ",
"to_change_password": "パスワードを変更", "to_change_password": "パスワードを変更",
"to_favorite": "お気に入り", "to_favorite": "お気に入り",
"to_login": "ログイン", "to_login": "ログイン",
"to_parent": "上位の階層へ",
"to_trash": "ゴミ箱", "to_trash": "ゴミ箱",
"toggle_settings": "設定をトグル", "toggle_settings": "設定をトグル",
"toggle_theme": "ダークテーマを切り替え", "toggle_theme": "ダークテーマを切り替え",
"total": "合計",
"total_usage": "総使用量", "total_usage": "総使用量",
"trash": "ゴミ箱", "trash": "ゴミ箱",
"trash_all": "全て削除", "trash_all": "全て削除",
@ -1187,10 +1301,13 @@
"unfavorite": "お気に入りから外す", "unfavorite": "お気に入りから外す",
"unhide_person": "人物の非表示を解除", "unhide_person": "人物の非表示を解除",
"unknown": "不明", "unknown": "不明",
"unknown_country": "不明な国",
"unknown_year": "不明な年", "unknown_year": "不明な年",
"unlimited": "無制限", "unlimited": "無制限",
"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": "無名の共有",
@ -1231,7 +1348,9 @@
"variables": "変数", "variables": "変数",
"version": "バージョン", "version": "バージョン",
"version_announcement_closing": "あなたの友人、Alex", "version_announcement_closing": "あなたの友人、Alex",
"version_announcement_message": "こんにちは、親愛なる皆様へ。アプリの新しいバージョンがありますので、構成の不整合を防ぐために<link>リリースノート</link>にアクセスし、<code>docker-compose.yml</code>、及び<code>.cnv</code>の設定が最新か確認してください。特に自動的にアプリの更新を制御するWatchTowerやその他システムを利用している場合に当てはまります。", "version_announcement_message": "こんにちは! 新しいバージョンのImmichがリリースされました。特にWatchTowerやImmichインスタンスを自動的に更新する仕組みを設けている場合は<link>リリースノート</link>をよく読んで設定が最新のものになっているか確認してください。",
"version_history": "バージョン履歴",
"version_history_item": "{date}に{version}をインストール",
"video": "動画", "video": "動画",
"video_hover_setting": "ホバー時にサムネイルで動画を再生", "video_hover_setting": "ホバー時にサムネイルで動画を再生",
"video_hover_setting_description": "マウスが項目の上にあるときに動画のサムネイルを再生します。無効時でも再生アイコンにカーソルを合わせると再生を開始できます。", "video_hover_setting_description": "マウスが項目の上にあるときに動画のサムネイルを再生します。無効時でも再生アイコンにカーソルを合わせると再生を開始できます。",
@ -1242,7 +1361,9 @@
"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_next_asset": "次のアセットを見る", "view_next_asset": "次のアセットを見る",
"view_previous_asset": "前のアセットを見る", "view_previous_asset": "前のアセットを見る",
"view_stack": "ビュースタック", "view_stack": "ビュースタック",
@ -1251,10 +1372,10 @@
"warning": "警告", "warning": "警告",
"week": "週", "week": "週",
"welcome": "ようこそ", "welcome": "ようこそ",
"welcome_to_immich": "immichにようこそ", "welcome_to_immich": "Immichにようこそ",
"year": "年", "year": "年",
"years_ago": "{years, plural, one {#年} other {#年}}前", "years_ago": "{years, plural, one {#年} other {#年}}前",
"yes": "はい", "yes": "はい",
"you_dont_have_any_shared_links": "共有リンクはありません", "you_dont_have_any_shared_links": "共有リンクはありません",
"zoom_image": "画像を拡大" "zoom_image": "画像を拡大"
} }

1
i18n/ka.json Normal file
View File

@ -0,0 +1 @@
{}

1
i18n/kk.json Normal file
View File

@ -0,0 +1 @@
{}

1
i18n/kn.json Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -41,6 +41,7 @@
"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} 라이브러리를 삭제하시겠습니까?",
@ -96,7 +97,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": "파일 변겅을 자동으로 감지",
@ -147,6 +148,8 @@
"map_settings": "지도", "map_settings": "지도",
"map_settings_description": "지도 설정 관리", "map_settings_description": "지도 설정 관리",
"map_style_description": "지도 테마 style.json URL", "map_style_description": "지도 테마 style.json URL",
"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": "얼굴 가져오기 활성화",
@ -240,7 +243,7 @@
"storage_template_hash_verification_enabled_description": "해시 검증을 활성화합니다. 이 설정의 결과를 확실히 이해하지 않는 한 비활성화하지 마세요.", "storage_template_hash_verification_enabled_description": "해시 검증을 활성화합니다. 이 설정의 결과를 확실히 이해하지 않는 한 비활성화하지 마세요.",
"storage_template_migration": "스토리지 템플릿 마이그레이션", "storage_template_migration": "스토리지 템플릿 마이그레이션",
"storage_template_migration_description": "이전에 업로드된 항목에 현재 <link>{template}</link> 적용", "storage_template_migration_description": "이전에 업로드된 항목에 현재 <link>{template}</link> 적용",
"storage_template_migration_info": "템플릿 변경 사항은 새 업로드 항목부터 적용됩니다. 기존 항목에도 적용하려면 <link>{job}</link>을 실행하세요.", "storage_template_migration_info": "저장소 템플릿은 모든 확장자를 소문자로 변환합니다. 템플릿 변경 사항은 새 자산에만 적용됩니다. 이전에 업로드한 자산에 템플릿을 적용하려면 <link>{job}</link>를 실행하세요.",
"storage_template_migration_job": "스토리지 템플릿 마이그레이션 작업", "storage_template_migration_job": "스토리지 템플릿 마이그레이션 작업",
"storage_template_more_details": "이 기능에 대한 자세한 내용은 <template-link>스토리지 템플릿</template-link> 및 <implications-link>설명</implications-link>을 참조하세요.", "storage_template_more_details": "이 기능에 대한 자세한 내용은 <template-link>스토리지 템플릿</template-link> 및 <implications-link>설명</implications-link>을 참조하세요.",
"storage_template_onboarding_description": "이 기능을 활성화하면 사용자 정의 템플릿을 사용하여 파일을 자동으로 정리할 수 있습니다. 안정성 문제로 인해 해당 기능은 기본적으로 비활성화되어 있습니다. 자세한 내용은 <link>문서</link>를 참조하세요.", "storage_template_onboarding_description": "이 기능을 활성화하면 사용자 정의 템플릿을 사용하여 파일을 자동으로 정리할 수 있습니다. 안정성 문제로 인해 해당 기능은 기본적으로 비활성화되어 있습니다. 자세한 내용은 <link>문서</link>를 참조하세요.",
@ -250,10 +253,16 @@
"storage_template_user_label": "사용자의 스토리지 레이블: <code>{label}</code>", "storage_template_user_label": "사용자의 스토리지 레이블: <code>{label}</code>",
"system_settings": "시스템 설정", "system_settings": "시스템 설정",
"tag_cleanup_job": "태그 정리", "tag_cleanup_job": "태그 정리",
"template_email_available_tags": "템플릿에서 다음 변수를 사용할 수 있습니다: {tags}",
"template_email_if_empty": "비어 있는 경우 기본 템플릿이 사용됩니다.", "template_email_if_empty": "비어 있는 경우 기본 템플릿이 사용됩니다.",
"template_email_invite_album": "앨범 템플릿 초대",
"template_email_preview": "미리보기", "template_email_preview": "미리보기",
"template_email_settings": "이메일 템플릿", "template_email_settings": "이메일 템플릿",
"template_email_settings_description": "사용자 정의 이메일 템플릿 관리", "template_email_settings_description": "사용자 정의 이메일 템플릿 관리",
"template_email_update_album": "앨범 템플릿 업데이트",
"template_email_welcome": "이메일 템플릿에 오신것을 환영합니다",
"template_settings": "알림 템플릿",
"template_settings_description": "알림을 위한 사용자 지정 템플릿을 관리합니다.",
"theme_custom_css_settings": "사용자 정의 CSS", "theme_custom_css_settings": "사용자 정의 CSS",
"theme_custom_css_settings_description": "Immich에 적용할 사용자 정의 CSS(Cascading Style Sheets) 설정", "theme_custom_css_settings_description": "Immich에 적용할 사용자 정의 CSS(Cascading Style Sheets) 설정",
"theme_settings": "테마 설정", "theme_settings": "테마 설정",
@ -278,11 +287,13 @@
"transcoding_audio_codec_description": "Opus는 가장 좋은 품질의 옵션이지만 기기 및 소프트웨어가 오래된 경우 호환되지 않을 수 있습니다.", "transcoding_audio_codec_description": "Opus는 가장 좋은 품질의 옵션이지만 기기 및 소프트웨어가 오래된 경우 호환되지 않을 수 있습니다.",
"transcoding_bitrate_description": "최대 비트레이트를 초과하는 동영상 또는 허용되지 않는 형식의 동영상", "transcoding_bitrate_description": "최대 비트레이트를 초과하는 동영상 또는 허용되지 않는 형식의 동영상",
"transcoding_codecs_learn_more": "여기에서 사용되는 용어에 대한 자세한 내용은 FFmpeg 문서의 <h264-link>H.264 코덱</h264-link>, <hevc-link>HEVC 코덱</hevc-link> 및 <vp9-link>VP9 코덱</vp9-link> 항목을 참조하세요.", "transcoding_codecs_learn_more": "여기에서 사용되는 용어에 대한 자세한 내용은 FFmpeg 문서의 <h264-link>H.264 코덱</h264-link>, <hevc-link>HEVC 코덱</hevc-link> 및 <vp9-link>VP9 코덱</vp9-link> 항목을 참조하세요.",
"transcoding_constant_quality_mode": "Constant quality mode", "transcoding_constant_quality_mode": "고정 품질 모드",
"transcoding_constant_quality_mode_description": "ICQ는 CQP보다 나은 성능을 보이나 일부 기기의 하드웨어 가속에서 지원되지 않을 수 있습니다. 이 옵션을 설정하면 품질 기반 인코딩 시 지정된 모드를 우선적으로 사용합니다. NVENC에서는 ICQ를 지원하지 않아 이 설정이 적용되지 않습니다.", "transcoding_constant_quality_mode_description": "ICQ는 CQP보다 나은 성능을 보이나 일부 기기의 하드웨어 가속에서 지원되지 않을 수 있습니다. 이 옵션을 설정하면 품질 기반 인코딩 시 지정된 모드를 우선적으로 사용합니다. NVENC에서는 ICQ를 지원하지 않아 이 설정이 적용되지 않습니다.",
"transcoding_constant_rate_factor": "Constant rate factor (-crf)", "transcoding_constant_rate_factor": "상수 비율 계수(-CRF)",
"transcoding_constant_rate_factor_description": "일반적으로 H.264는 23, HEVC는 28, VP9는 31, AV1는 35를 사용합니다. 값이 낮으면 품질이 향상되지만 파일 크기가 증가합니다.", "transcoding_constant_rate_factor_description": "일반적으로 H.264는 23, HEVC는 28, VP9는 31, AV1는 35를 사용합니다. 값이 낮으면 품질이 향상되지만 파일 크기가 증가합니다.",
"transcoding_disabled_description": "동영상을 트랜스코딩하지 않음. 일부 기기에서 재생이 불가능할 수 있습니다.", "transcoding_disabled_description": "동영상을 트랜스코딩하지 않음. 일부 기기에서 재생이 불가능할 수 있습니다.",
"transcoding_encoding_options": "인코딩 옵션",
"transcoding_encoding_options_description": "인코딩된 동영상의 코덱, 해상도, 품질 및 기타 옵션을 설정합니다",
"transcoding_hardware_acceleration": "하드웨어 가속", "transcoding_hardware_acceleration": "하드웨어 가속",
"transcoding_hardware_acceleration_description": "실험적인 기능입니다. 속도가 향상되지만 동일 비트레이트에서 품질이 상대적으로 낮을 수 있습니다.", "transcoding_hardware_acceleration_description": "실험적인 기능입니다. 속도가 향상되지만 동일 비트레이트에서 품질이 상대적으로 낮을 수 있습니다.",
"transcoding_hardware_decoding": "하드웨어 디코딩", "transcoding_hardware_decoding": "하드웨어 디코딩",
@ -295,6 +306,8 @@
"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": "목표 해상도보다 높은 동영상 또는 허용되지 않는 형식의 동영상",
"transcoding_policy": "트랜스코드 정책",
"transcoding_policy_description": "동영상 트랜스코딩 시기 설정하기",
"transcoding_preferred_hardware_device": "선호하는 하드웨어 기기", "transcoding_preferred_hardware_device": "선호하는 하드웨어 기기",
"transcoding_preferred_hardware_device_description": "하드웨어 트랜스코딩에 사용할 dri 노드를 설정합니다. (VAAPI와 QSV만 해당)", "transcoding_preferred_hardware_device_description": "하드웨어 트랜스코딩에 사용할 dri 노드를 설정합니다. (VAAPI와 QSV만 해당)",
"transcoding_preset_preset": "프리셋 (-preset)", "transcoding_preset_preset": "프리셋 (-preset)",
@ -303,10 +316,10 @@
"transcoding_reference_frames_description": "특정 프레임을 압축할 때 참조하는 프레임 수를 설정합니다. 값이 높으면 압축 효율이 향상되나 인코딩 속도가 저하됩니다. 0을 입력한 경우 자동으로 설정합니다.", "transcoding_reference_frames_description": "특정 프레임을 압축할 때 참조하는 프레임 수를 설정합니다. 값이 높으면 압축 효율이 향상되나 인코딩 속도가 저하됩니다. 0을 입력한 경우 자동으로 설정합니다.",
"transcoding_required_description": "허용된 형식이 아닌 동영상만", "transcoding_required_description": "허용된 형식이 아닌 동영상만",
"transcoding_settings": "동영상 트랜스코딩 설정", "transcoding_settings": "동영상 트랜스코딩 설정",
"transcoding_settings_description": "동영상 파일의 해상도 및 인코딩 정보 관리", "transcoding_settings_description": "트랜스코딩할 동영상과 처리 방법 관리하기",
"transcoding_target_resolution": "목표 해상도", "transcoding_target_resolution": "목표 해상도",
"transcoding_target_resolution_description": "높은 해상도를 선택한 경우 세부 묘사의 손실을 최소화할 수 있지만, 인코딩 시간과 파일 크기가 증가하여 앱의 반응 속도가 느려질 수 있습니다.", "transcoding_target_resolution_description": "높은 해상도를 선택한 경우 세부 묘사의 손실을 최소화할 수 있지만, 인코딩 시간과 파일 크기가 증가하여 앱의 반응 속도가 느려질 수 있습니다.",
"transcoding_temporal_aq": "Temporal AQ", "transcoding_temporal_aq": "일시적 AQ",
"transcoding_temporal_aq_description": "세부 묘사가 많고 움직임이 적은 장면의 품질이 향상됩니다. 오래된 기기와 호환되지 않을 수 있습니다. (NVENC만 해당)", "transcoding_temporal_aq_description": "세부 묘사가 많고 움직임이 적은 장면의 품질이 향상됩니다. 오래된 기기와 호환되지 않을 수 있습니다. (NVENC만 해당)",
"transcoding_threads": "스레드", "transcoding_threads": "스레드",
"transcoding_threads_description": "값이 높으면 인코딩 속도가 향상되지만 리소스 사용량이 증가합니다. 값은 CPU 코어 수보다 작아야 하며, 설정하지 않으려면 0을 입력합니다.", "transcoding_threads_description": "값이 높으면 인코딩 속도가 향상되지만 리소스 사용량이 증가합니다. 값은 CPU 코어 수보다 작아야 하며, 설정하지 않으려면 0을 입력합니다.",
@ -381,6 +394,7 @@
"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": "이 값은 한 번만 표시됩니다. 창을 닫기 전 반드시 복사해주세요.",
@ -471,7 +485,9 @@
"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_password": "비밀번호 확인", "confirm_password": "비밀번호 확인",
"contain": "맞춤", "contain": "맞춤",
"context": "내용", "context": "내용",
@ -512,15 +528,21 @@
"date_range": "날짜 범위", "date_range": "날짜 범위",
"day": "일", "day": "일",
"deduplicate_all": "모두 삭제", "deduplicate_all": "모두 삭제",
"deduplication_criteria_1": "이미지 크기(바이트)",
"deduplication_criteria_2": "EXIF 데이터 개수",
"deduplication_info": "중복 제거 정보",
"deduplication_info_description": "자산을 자동으로 미리 선택하고 일괄적으로 중복을 제거하려면 다음을 살펴보세요:",
"default_locale": "기본 로케일", "default_locale": "기본 로케일",
"default_locale_description": "브라우저 로케일에 따른 날짜 및 숫자 형식 지정", "default_locale_description": "브라우저 로케일에 따른 날짜 및 숫자 형식 지정",
"delete": "삭제", "delete": "삭제",
"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": "링크 삭제",
"delete_others": "다른 사람 삭제",
"delete_shared_link": "공유 링크 삭제", "delete_shared_link": "공유 링크 삭제",
"delete_tag": "태그 삭제", "delete_tag": "태그 삭제",
"delete_tag_confirmation_prompt": "{tagName} 태그를 삭제하시겠습니까?", "delete_tag_confirmation_prompt": "{tagName} 태그를 삭제하시겠습니까?",
@ -532,7 +554,7 @@
"direction": "방향", "direction": "방향",
"disabled": "비활성화됨", "disabled": "비활성화됨",
"disallow_edits": "뷰어로 설정", "disallow_edits": "뷰어로 설정",
"discord": "Discord", "discord": "디스코드",
"discover": "탐색", "discover": "탐색",
"dismiss_all_errors": "모든 오류 무시", "dismiss_all_errors": "모든 오류 무시",
"dismiss_error": "오류 무시", "dismiss_error": "오류 무시",
@ -579,11 +601,12 @@
"editor_crop_tool_h2_rotation": "회전", "editor_crop_tool_h2_rotation": "회전",
"email": "이메일", "email": "이메일",
"empty_trash": "휴지통 비우기", "empty_trash": "휴지통 비우기",
"empty_trash_confirmation": "휴지통을 비우시겠습니까? 휴지통에 있는 모든 항목이 Immich에서 영구적으로 삭제됩니다. 이 작업은 되돌릴 수 없습니다!", "empty_trash_confirmation": "휴지통을 비우시겠습니까? 휴지통에 있는 모든 항목이 Immich에서 영구적으로 삭제됩니다.\n이 작업은 되돌릴 수 없습니다!",
"enable": "활성화", "enable": "활성화",
"enabled": "활성화됨", "enabled": "활성화됨",
"end_date": "종료일", "end_date": "종료일",
"error": "오류", "error": "오류",
"error_delete_face": "에셋에서 얼굴 삭제 오류",
"error_loading_image": "이미지 로드 오류", "error_loading_image": "이미지 로드 오류",
"error_title": "오류 - 문제가 발생했습니다", "error_title": "오류 - 문제가 발생했습니다",
"errors": { "errors": {
@ -611,6 +634,7 @@
"failed_to_create_shared_link": "공유 링크를 생성하지 못했습니다.", "failed_to_create_shared_link": "공유 링크를 생성하지 못했습니다.",
"failed_to_edit_shared_link": "공유 링크를 수정하지 못했습니다.", "failed_to_edit_shared_link": "공유 링크를 수정하지 못했습니다.",
"failed_to_get_people": "인물 로드 실패", "failed_to_get_people": "인물 로드 실패",
"failed_to_keep_this_delete_others": "이 자산을 유지하고 다른 자산을 삭제하지 못했습니다",
"failed_to_load_asset": "항목 로드 실패", "failed_to_load_asset": "항목 로드 실패",
"failed_to_load_assets": "항목 로드 실패", "failed_to_load_assets": "항목 로드 실패",
"failed_to_load_people": "인물 로드 실패", "failed_to_load_people": "인물 로드 실패",
@ -725,6 +749,7 @@
"external": "외부", "external": "외부",
"external_libraries": "외부 라이브러리", "external_libraries": "외부 라이브러리",
"face_unassigned": "알 수 없음", "face_unassigned": "알 수 없음",
"failed_to_load_assets": "에셋 로드에 실패했습니다",
"favorite": "즐겨찾기", "favorite": "즐겨찾기",
"favorite_or_unfavorite_photo": "즐겨찾기 추가/제거", "favorite_or_unfavorite_photo": "즐겨찾기 추가/제거",
"favorites": "즐겨찾기", "favorites": "즐겨찾기",
@ -745,10 +770,13 @@
"get_help": "도움 요청", "get_help": "도움 요청",
"getting_started": "시작하기", "getting_started": "시작하기",
"go_back": "뒤로", "go_back": "뒤로",
"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})",
@ -781,6 +809,7 @@
"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": "매일 오후 1시", "day_at_onepm": "매일 오후 1시",
@ -794,6 +823,8 @@
"jobs": "작업", "jobs": "작업",
"keep": "유지", "keep": "유지",
"keep_all": "모두 유지", "keep_all": "모두 유지",
"keep_this_delete_others": "이 항목은 보관하고 다른 항목은 삭제",
"kept_this_deleted_others": "이 자산을 유지하고 {count, plural, one {# asset} other {# assets}}을 삭제했습니다",
"keyboard_shortcuts": "키보드 단축키", "keyboard_shortcuts": "키보드 단축키",
"language": "언어", "language": "언어",
"language_setting_description": "선호하는 언어 선택", "language_setting_description": "선호하는 언어 선택",
@ -801,6 +832,7 @@
"latest_version": "최신 버전", "latest_version": "최신 버전",
"latitude": "위도", "latitude": "위도",
"leave": "나가기", "leave": "나가기",
"lens_model": "카메라 렌즈 모델",
"let_others_respond": "다른 사용자의 반응 허용", "let_others_respond": "다른 사용자의 반응 허용",
"level": "레벨", "level": "레벨",
"library": "라이브러리", "library": "라이브러리",
@ -859,6 +891,7 @@
"month": "월", "month": "월",
"more": "더보기", "more": "더보기",
"moved_to_trash": "휴지통으로 이동되었습니다.", "moved_to_trash": "휴지통으로 이동되었습니다.",
"mute_memories": "추억 음소거",
"my_albums": "내 앨범", "my_albums": "내 앨범",
"name": "이름", "name": "이름",
"name_or_nickname": "이름 또는 닉네임", "name_or_nickname": "이름 또는 닉네임",
@ -954,6 +987,7 @@
"permanently_deleted_asset": "항목이 영구적으로 삭제되었습니다.", "permanently_deleted_asset": "항목이 영구적으로 삭제되었습니다.",
"permanently_deleted_assets_count": "항목 {count, plural, one {#개} other {#개}}가 영구적으로 삭제되었습니다.", "permanently_deleted_assets_count": "항목 {count, plural, one {#개} other {#개}}가 영구적으로 삭제되었습니다.",
"person": "인물", "person": "인물",
"person_birthdate": "{date} 출생",
"person_hidden": "{name}{hidden, select, true { (숨김)} other {}}", "person_hidden": "{name}{hidden, select, true { (숨김)} other {}}",
"photo_shared_all_users": "이미 모든 사용자와 사진을 공유 중이거나 다른 사용자가 없는 것 같습니다.", "photo_shared_all_users": "이미 모든 사용자와 사진을 공유 중이거나 다른 사용자가 없는 것 같습니다.",
"photos": "사진", "photos": "사진",
@ -963,6 +997,7 @@
"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": "모션 포토 재생", "play_motion_photo": "모션 포토 재생",
@ -1022,6 +1057,7 @@
"reassigned_assets_to_new_person": "항목 {count, plural, one {#개} other {#개}}가 새 인물에 할당되었습니다.", "reassigned_assets_to_new_person": "항목 {count, plural, one {#개} other {#개}}가 새 인물에 할당되었습니다.",
"reassing_hint": "기존 인물에 선택한 항목 할당", "reassing_hint": "기존 인물에 선택한 항목 할당",
"recent": "최근", "recent": "최근",
"recent-albums": "최근 앨범",
"recent_searches": "최근 검색", "recent_searches": "최근 검색",
"refresh": "새로고침", "refresh": "새로고침",
"refresh_encoded_videos": "동영상 재인코딩", "refresh_encoded_videos": "동영상 재인코딩",
@ -1043,11 +1079,16 @@
"remove_from_album": "앨범에서 제거", "remove_from_album": "앨범에서 제거",
"remove_from_favorites": "즐겨찾기에서 제거", "remove_from_favorites": "즐겨찾기에서 제거",
"remove_from_shared_link": "공유 링크에서 제거", "remove_from_shared_link": "공유 링크에서 제거",
"remove_memory": "추억 제거",
"remove_photo_from_memory": "이 추억에서 사진 제거",
"remove_url": "URL 제거",
"remove_user": "사용자 삭제", "remove_user": "사용자 삭제",
"removed_api_key": "API 키 삭제: {name}", "removed_api_key": "API 키 삭제: {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": "수리",
@ -1056,6 +1097,7 @@
"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": "인물 표시 여부 초기화",
@ -1092,12 +1134,14 @@
"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": "태그로 검색...",
@ -1107,6 +1151,7 @@
"searching_locales": "로케일 검색...", "searching_locales": "로케일 검색...",
"second": "초", "second": "초",
"see_all_people": "모든 인물 보기", "see_all_people": "모든 인물 보기",
"select": "선택",
"select_album_cover": "앨범 커버 변경", "select_album_cover": "앨범 커버 변경",
"select_all": "모두 선택", "select_all": "모두 선택",
"select_all_duplicates": "모두 선택", "select_all_duplicates": "모두 선택",
@ -1129,6 +1174,7 @@
"server_version": "서버 버전", "server_version": "서버 버전",
"set": "설정", "set": "설정",
"set_as_album_cover": "앨범 커버로 설정", "set_as_album_cover": "앨범 커버로 설정",
"set_as_featured_photo": "추천 사진으로 설정",
"set_as_profile_picture": "프로필 사진으로 설정", "set_as_profile_picture": "프로필 사진으로 설정",
"set_date_of_birth": "생년월일 설정", "set_date_of_birth": "생년월일 설정",
"set_profile_picture": "프로필 사진으로 설정", "set_profile_picture": "프로필 사진으로 설정",
@ -1143,6 +1189,7 @@
"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": "공유",
@ -1165,6 +1212,7 @@
"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": "서포터 배지 표시",
@ -1184,6 +1232,7 @@
"sort_items": "항목 수", "sort_items": "항목 수",
"sort_modified": "수정된 날짜", "sort_modified": "수정된 날짜",
"sort_oldest": "오래된 사진", "sort_oldest": "오래된 사진",
"sort_people_by_similarity": "유사성을 기준으로 사람 정렬",
"sort_recent": "최근 사진", "sort_recent": "최근 사진",
"sort_title": "제목", "sort_title": "제목",
"source": "소스", "source": "소스",
@ -1217,6 +1266,7 @@
"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": "태그",
@ -1237,6 +1287,7 @@
"to_trash": "삭제", "to_trash": "삭제",
"toggle_settings": "설정 변경", "toggle_settings": "설정 변경",
"toggle_theme": "다크 모드 사용", "toggle_theme": "다크 모드 사용",
"total": "합계",
"total_usage": "총 사용량", "total_usage": "총 사용량",
"trash": "휴지통", "trash": "휴지통",
"trash_all": "모두 삭제", "trash_all": "모두 삭제",
@ -1256,6 +1307,7 @@
"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": "이름 없는 공유",
@ -1287,6 +1339,7 @@
"user_purchase_settings_description": "구매 및 제품 키 관리", "user_purchase_settings_description": "구매 및 제품 키 관리",
"user_role_set": "{user}님에게 {role} 역할을 설정했습니다.", "user_role_set": "{user}님에게 {role} 역할을 설정했습니다.",
"user_usage_detail": "사용자 사용량 상세", "user_usage_detail": "사용자 사용량 상세",
"user_usage_stats": "계정 사용량 통계",
"user_usage_stats_description": "계정 사용량 통계 보기", "user_usage_stats_description": "계정 사용량 통계 보기",
"username": "계정명", "username": "계정명",
"users": "사용자", "users": "사용자",
@ -1308,7 +1361,9 @@
"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_next_asset": "다음 항목 보기", "view_next_asset": "다음 항목 보기",
"view_previous_asset": "이전 항목 보기", "view_previous_asset": "이전 항목 보기",
"view_stack": "스택 보기", "view_stack": "스택 보기",
@ -1323,4 +1378,4 @@
"yes": "네", "yes": "네",
"you_dont_have_any_shared_links": "생성한 공유 링크가 없습니다.", "you_dont_have_any_shared_links": "생성한 공유 링크가 없습니다.",
"zoom_image": "이미지 확대" "zoom_image": "이미지 확대"
} }

View File

@ -29,6 +29,7 @@
"added_to_favorites_count": "Pievienots {count, number} izlasei", "added_to_favorites_count": "Pievienots {count, number} izlasei",
"admin": { "admin": {
"add_exclusion_pattern_description": "Pievienojiet izlaišanas shēmas. Aizstājējzīmju izmantoša *, **, un ? tiek atbalstīta. Lai ignorētu visus failus jebkurā direktorijā ar nosaukumu “RAW”, izmantojiet “**/RAW/**”. Lai ignorētu visus failus, kas beidzas ar “. tif”, izmantojiet “**/*. tif”. Lai ignorētu absolūto ceļu, izmantojiet “/path/to/ignore/**”.", "add_exclusion_pattern_description": "Pievienojiet izlaišanas shēmas. Aizstājējzīmju izmantoša *, **, un ? tiek atbalstīta. Lai ignorētu visus failus jebkurā direktorijā ar nosaukumu “RAW”, izmantojiet “**/RAW/**”. Lai ignorētu visus failus, kas beidzas ar “. tif”, izmantojiet “**/*. tif”. Lai ignorētu absolūto ceļu, izmantojiet “/path/to/ignore/**”.",
"asset_offline_description": "Šis ārējās bibliotēkas resurss vairs nav atrodams diskā un ir pārvietots uz atkritumu grozu. Ja fails tika pārvietots bibliotēkas ietvaros, pārbaudiet, vai jūsu hronoloģijā ir jauns atbilstošais resurss. Lai atjaunotu šo resursu, pārliecinieties, vai Immich var piekļūt tālāk norādītajam faila ceļam un skenēt bibliotēku.",
"authentication_settings": "Autentifikācijas iestatījumi", "authentication_settings": "Autentifikācijas iestatījumi",
"authentication_settings_description": "Paroļu, OAuth un citu autentifikācijas iestatījumu pārvaldība", "authentication_settings_description": "Paroļu, OAuth un citu autentifikācijas iestatījumu pārvaldība",
"authentication_settings_disable_all": "Vai tiešām vēlaties atspējot visas pieteikšanās metodes? Pieteikšanās tiks pilnībā atspējota.", "authentication_settings_disable_all": "Vai tiešām vēlaties atspējot visas pieteikšanās metodes? Pieteikšanās tiks pilnībā atspējota.",
@ -316,6 +317,8 @@
"birthdate_set_description": "Dzimšanas datums tiek izmantots, lai aprēķinātu šīs personas vecumu fotogrāfijas uzņemšanas brīdī.", "birthdate_set_description": "Dzimšanas datums tiek izmantots, lai aprēķinātu šīs personas vecumu fotogrāfijas uzņemšanas brīdī.",
"blurred_background": "", "blurred_background": "",
"bugs_and_feature_requests": "Kļūdas un funkciju pieprasījumi", "bugs_and_feature_requests": "Kļūdas un funkciju pieprasījumi",
"build": "Būvējums",
"build_image": "Būvējuma attēls",
"camera": "", "camera": "",
"camera_brand": "", "camera_brand": "",
"camera_model": "", "camera_model": "",
@ -599,7 +602,7 @@
"model": "Modelis", "model": "Modelis",
"month": "Mēnesis", "month": "Mēnesis",
"more": "Vairāk", "more": "Vairāk",
"moved_to_trash": "", "moved_to_trash": "Pārvietots uz atkritni",
"my_albums": "Mani albumi", "my_albums": "Mani albumi",
"name": "Vārds", "name": "Vārds",
"name_or_nickname": "Vārds vai iesauka", "name_or_nickname": "Vārds vai iesauka",
@ -824,7 +827,7 @@
"sort_oldest": "Vecākā fotogrāfija", "sort_oldest": "Vecākā fotogrāfija",
"sort_recent": "Nesenākā fotogrāfija", "sort_recent": "Nesenākā fotogrāfija",
"sort_title": "Nosaukums", "sort_title": "Nosaukums",
"source": "Avots", "source": "Pirmkods",
"stack": "Apvienot kaudzē", "stack": "Apvienot kaudzē",
"stack_selected_photos": "", "stack_selected_photos": "",
"stacktrace": "", "stacktrace": "",
@ -893,6 +896,7 @@
"version": "Versija", "version": "Versija",
"version_announcement_message": "Sveiki! Ir pieejama jauna Immich versija. Lūdzu, veltiet laiku, lai izlasītu <link>laidiena piezīmes</link> un pārliecinātos, ka jūsu iestatījumi ir atjaunināti, lai novērstu jebkādu nepareizu konfigurāciju, jo īpaši, ja izmantojat WatchTower vai citu mehānismu, kas automātiski atjaunina jūsu Immich instanci.", "version_announcement_message": "Sveiki! Ir pieejama jauna Immich versija. Lūdzu, veltiet laiku, lai izlasītu <link>laidiena piezīmes</link> un pārliecinātos, ka jūsu iestatījumi ir atjaunināti, lai novērstu jebkādu nepareizu konfigurāciju, jo īpaši, ja izmantojat WatchTower vai citu mehānismu, kas automātiski atjaunina jūsu Immich instanci.",
"version_history": "Versiju vēsture", "version_history": "Versiju vēsture",
"version_history_item": "{version} uzstādīta {date}",
"video": "Videoklips", "video": "Videoklips",
"video_hover_setting_description": "", "video_hover_setting_description": "",
"videos": "Videoklipi", "videos": "Videoklipi",

1
i18n/pa.json Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -1079,6 +1079,8 @@
"remove_from_album": "Odstrániť z albumu", "remove_from_album": "Odstrániť z albumu",
"remove_from_favorites": "Odstrániť z obľúbených", "remove_from_favorites": "Odstrániť z obľúbených",
"remove_from_shared_link": "Odstrániť zo zdieľaného odkazu", "remove_from_shared_link": "Odstrániť zo zdieľaného odkazu",
"remove_memory": "Odstrániť spomienku",
"remove_photo_from_memory": "Odstrániť fotografiu z tejto spomienky",
"remove_url": "Odstrániť URL", "remove_url": "Odstrániť URL",
"remove_user": "Odstrániť používateľa", "remove_user": "Odstrániť používateľa",
"removed_api_key": "Odstrániť API kľúč: {name}", "removed_api_key": "Odstrániť API kľúč: {name}",

1
i18n/sq.json Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -246,7 +246,7 @@
"storage_template_migration_info": "Lagringsmallen kommer konvertera alla filändelser till gemena bokstäver. Ändringar gäller endast för nya resurser, för att retoaktivt tillämpa mallen på befintliga resurser kör <link>{job}</link>.", "storage_template_migration_info": "Lagringsmallen kommer konvertera alla filändelser till gemena bokstäver. Ändringar gäller endast för nya resurser, för att retoaktivt tillämpa mallen på befintliga resurser kör <link>{job}</link>.",
"storage_template_migration_job": "Lagringsmall migreringsjobb", "storage_template_migration_job": "Lagringsmall migreringsjobb",
"storage_template_more_details": "För mer information om den här funktionen se <template-link>Lagringsmall</template-link> och dess <implications-link>konsekvenser</implications-link>", "storage_template_more_details": "För mer information om den här funktionen se <template-link>Lagringsmall</template-link> och dess <implications-link>konsekvenser</implications-link>",
"storage_template_onboarding_description": "Vid aktivering organiserar denna funktion automatiskt filer baserat på en användardefinierad mall. På grunda av stabilitetsproblem är denna funktion avstängd som standard, för mer information se <link>dokumentation</link>.", "storage_template_onboarding_description": "Vid aktivering organiserar denna funktion automatiskt filer baserat på en användardefinierad mall. På grund av stabilitetsproblem är denna funktion avstängd som standard, för mer information se <link>dokumentation</link>.",
"storage_template_path_length": "Uppskattad längdbegränsning på sökväg: <b>{length, number}</b>/{limit, number}", "storage_template_path_length": "Uppskattad längdbegränsning på sökväg: <b>{length, number}</b>/{limit, number}",
"storage_template_settings": "Lagringsmall", "storage_template_settings": "Lagringsmall",
"storage_template_settings_description": "Hantera mappstruktur och filnamn för uppladdade resurser", "storage_template_settings_description": "Hantera mappstruktur och filnamn för uppladdade resurser",

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@
"added_to_favorites_count": "Додано {count, number} до обраного", "added_to_favorites_count": "Додано {count, number} до обраного",
"admin": { "admin": {
"add_exclusion_pattern_description": "Додайте шаблони виключень. Підстановка з використанням *, ** та ? підтримується. Для ігнорування всіх файлів у будь-якому каталозі з ім'ям «Raw», використовуйте \"**/Raw/**\". Для ігнорування всіх файлів, що закінчуються на \".tif\", використовуйте \"**/*.tif\". Для ігнорування абсолютного шляху використовуйте \"/path/to/ignore/**\".", "add_exclusion_pattern_description": "Додайте шаблони виключень. Підстановка з використанням *, ** та ? підтримується. Для ігнорування всіх файлів у будь-якому каталозі з ім'ям «Raw», використовуйте \"**/Raw/**\". Для ігнорування всіх файлів, що закінчуються на \".tif\", використовуйте \"**/*.tif\". Для ігнорування абсолютного шляху використовуйте \"/path/to/ignore/**\".",
"asset_offline_description": "Цей зовнішній бібліотечний актив більше не знайдено на диску і був переміщений до кошика. Якщо файл був переміщений у межах бібліотеки, перевірте свій таймлайн на наявність нового відповідного активу. Щоб відновити цей актив, переконайтеся, що шлях файлу нижче доступний для Immich, і проскануйте бібліотеку.", "asset_offline_description": "Цей зовнішній бібліотечний актив більше не знайдено на диску і був переміщений до смітника. Якщо файл був переміщений у межах бібліотеки, перевірте свій таймлайн на наявність нового відповідного активу. Щоб відновити цей актив, переконайтеся, що шлях файлу нижче доступний для Immich, і проскануйте бібліотеку.",
"authentication_settings": "Налаштування аутентифікації", "authentication_settings": "Налаштування аутентифікації",
"authentication_settings_description": "Управління паролями, OAuth та іншими налаштуваннями аутентифікації", "authentication_settings_description": "Управління паролями, OAuth та іншими налаштуваннями аутентифікації",
"authentication_settings_disable_all": "Ви впевнені, що хочете вимкнути всі методи входу? Вхід буде повністю вимкнений.", "authentication_settings_disable_all": "Ви впевнені, що хочете вимкнути всі методи входу? Вхід буде повністю вимкнений.",
@ -331,11 +331,11 @@
"transcoding_two_pass_encoding_setting_description": "Транскодування за двома проходами для отримання кращих закодованих відео. Коли ввімкнено максимальний бітрейт (необхідний для роботи з H.264 та HEVC), цей режим використовує діапазон бітрейту, заснований на максимальному бітрейті, і ігнорує CRF. Для VP9 можна використовувати CRF, якщо вимкнено максимальний бітрейт.", "transcoding_two_pass_encoding_setting_description": "Транскодування за двома проходами для отримання кращих закодованих відео. Коли ввімкнено максимальний бітрейт (необхідний для роботи з H.264 та HEVC), цей режим використовує діапазон бітрейту, заснований на максимальному бітрейті, і ігнорує CRF. Для VP9 можна використовувати CRF, якщо вимкнено максимальний бітрейт.",
"transcoding_video_codec": "Відеокодек", "transcoding_video_codec": "Відеокодек",
"transcoding_video_codec_description": "VP9 має високу ефективність і сумісність з вебом, але потребує більше часу на транскодування. HEVC працює схоже, але має меншу сумісність з вебом. H.264 має широку сумісність і швидко транскодується, але створює значно більші файли. AV1 - найефективніший кодек, але не підтримується на старіших пристроях.", "transcoding_video_codec_description": "VP9 має високу ефективність і сумісність з вебом, але потребує більше часу на транскодування. HEVC працює схоже, але має меншу сумісність з вебом. H.264 має широку сумісність і швидко транскодується, але створює значно більші файли. AV1 - найефективніший кодек, але не підтримується на старіших пристроях.",
"trash_enabled_description": "Увімкнення кошика", "trash_enabled_description": "Увімкнення смітника",
"trash_number_of_days": "Кількість днів", "trash_number_of_days": "Кількість днів",
"trash_number_of_days_description": "Кількість днів, щоб залишити ресурси в кошику перед остаточним їх видаленням", "trash_number_of_days_description": "Кількість днів, щоб залишити ресурси в смітнику перед остаточним їх видаленням",
"trash_settings": "Налаштування кошика", "trash_settings": "Налаштування смітника",
"trash_settings_description": "Керування налаштуваннями кошика", "trash_settings_description": "Керування налаштуваннями смітника",
"untracked_files": "Невідстежувані файли", "untracked_files": "Невідстежувані файли",
"untracked_files_description": "Ці файли не відстежуються програмою. Вони можуть бути результатом невдалого переміщення, перерваного завантаження або залишитися через помилку програми", "untracked_files_description": "Ці файли не відстежуються програмою. Вони можуть бути результатом невдалого переміщення, перерваного завантаження або залишитися через помилку програми",
"user_cleanup_job": "Очищення користувача", "user_cleanup_job": "Очищення користувача",
@ -426,12 +426,12 @@
"assets_added_to_album_count": "Додано {count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}} до альбому", "assets_added_to_album_count": "Додано {count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}} до альбому",
"assets_added_to_name_count": "Додано {count, plural, one {# елемент} other {# елементів}} до {hasName, select, true {<b>{name}</b>} other {нового альбому}}", "assets_added_to_name_count": "Додано {count, plural, one {# елемент} other {# елементів}} до {hasName, select, true {<b>{name}</b>} other {нового альбому}}",
"assets_count": "{count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}}", "assets_count": "{count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}}",
"assets_moved_to_trash_count": "Переміщено {count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}} у кошик", "assets_moved_to_trash_count": "Переміщено {count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}} у смітник",
"assets_permanently_deleted_count": "Остаточно видалено {count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}}", "assets_permanently_deleted_count": "Остаточно видалено {count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}}",
"assets_removed_count": "Вилучено {count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}}", "assets_removed_count": "Вилучено {count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}}",
"assets_restore_confirmation": "Ви впевнені, що хочете відновити всі свої активи з кошика? Цю дію не можна скасувати! Зверніть увагу, що будь-які офлайн-активи не можуть бути відновлені таким чином.", "assets_restore_confirmation": "Ви впевнені, що хочете відновити всі свої активи з смітника? Цю дію не можна скасувати! Зверніть увагу, що будь-які офлайн-активи не можуть бути відновлені таким чином.",
"assets_restored_count": "Відновлено {count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}}", "assets_restored_count": "Відновлено {count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}}",
"assets_trashed_count": "Поміщено в кошик {count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}}", "assets_trashed_count": "Поміщено в смітник {count, plural, one {# ресурс} few {# ресурси} other {# ресурсів}}",
"assets_were_part_of_album_count": "{count, plural, one {Ресурс був} few {Ресурси були} other {Ресурси були}} вже частиною альбому", "assets_were_part_of_album_count": "{count, plural, one {Ресурс був} few {Ресурси були} other {Ресурси були}} вже частиною альбому",
"authorized_devices": "Авторизовані пристрої", "authorized_devices": "Авторизовані пристрої",
"back": "Назад", "back": "Назад",
@ -445,7 +445,7 @@
"build_image": "Версія збірки", "build_image": "Версія збірки",
"bulk_delete_duplicates_confirmation": "Ви впевнені, що хочете масово видалити {count, plural, one {# дубльований ресурс} few {# дубльовані ресурси} other {# дубльованих ресурсів}}? Це дія залишить найбільший ресурс у кожній групі і остаточно видалить всі інші дублікати. Цю дію неможливо скасувати!", "bulk_delete_duplicates_confirmation": "Ви впевнені, що хочете масово видалити {count, plural, one {# дубльований ресурс} few {# дубльовані ресурси} other {# дубльованих ресурсів}}? Це дія залишить найбільший ресурс у кожній групі і остаточно видалить всі інші дублікати. Цю дію неможливо скасувати!",
"bulk_keep_duplicates_confirmation": "Ви впевнені, що хочете залишити {count, plural, one {# дубльований ресурс} few {# дубльовані ресурси} other {# дубльованих ресурсів}}? Це дозволить вирішити всі групи дублікатів без видалення чого-небудь.", "bulk_keep_duplicates_confirmation": "Ви впевнені, що хочете залишити {count, plural, one {# дубльований ресурс} few {# дубльовані ресурси} other {# дубльованих ресурсів}}? Це дозволить вирішити всі групи дублікатів без видалення чого-небудь.",
"bulk_trash_duplicates_confirmation": "Ви впевнені, що хочете викинути в кошик {count, plural, one {# дубльований ресурс} few {# дубльовані ресурси} other {# дубльованих ресурсів}} масово? Це залишить найбільший ресурс у кожній групі і викине в кошик всі інші дублікати.", "bulk_trash_duplicates_confirmation": "Ви впевнені, що хочете викинути в смітник {count, plural, one {# дубльований ресурс} few {# дубльовані ресурси} other {# дубльованих ресурсів}} масово? Це залишить найбільший ресурс у кожній групі і викине в смітник всі інші дублікати.",
"buy": "Придбайте Immich", "buy": "Придбайте Immich",
"camera": "Камера", "camera": "Камера",
"camera_brand": "Марка камери", "camera_brand": "Марка камери",
@ -600,8 +600,8 @@
"editor_crop_tool_h2_aspect_ratios": "Пропорції зображення", "editor_crop_tool_h2_aspect_ratios": "Пропорції зображення",
"editor_crop_tool_h2_rotation": "Орієнтація", "editor_crop_tool_h2_rotation": "Орієнтація",
"email": "Електронна пошта", "email": "Електронна пошта",
"empty_trash": "Очистити кошик", "empty_trash": "Очистити смітник",
"empty_trash_confirmation": "Ви впевнені, що хочете очистити кошик? Це остаточно видалить всі ресурси в кошику з Immich.\nЦю дію не можна скасувати!", "empty_trash_confirmation": "Ви впевнені, що хочете очистити смітник? Це остаточно видалить всі ресурси в смітнику з Immich.\nЦю дію не можна скасувати!",
"enable": "Увімкнути", "enable": "Увімкнути",
"enabled": "Увімкнено", "enabled": "Увімкнено",
"end_date": "Дата завершення", "end_date": "Дата завершення",
@ -680,7 +680,7 @@
"unable_to_download_files": "Неможливо завантажити файли", "unable_to_download_files": "Неможливо завантажити файли",
"unable_to_edit_exclusion_pattern": "Не вдалося редагувати шаблон виключення", "unable_to_edit_exclusion_pattern": "Не вдалося редагувати шаблон виключення",
"unable_to_edit_import_path": "Неможливо відредагувати шлях імпорту", "unable_to_edit_import_path": "Неможливо відредагувати шлях імпорту",
"unable_to_empty_trash": "Неможливо очистити кошик", "unable_to_empty_trash": "Неможливо очистити смітник",
"unable_to_enter_fullscreen": "Неможливо увійти в повноекранний режим", "unable_to_enter_fullscreen": "Неможливо увійти в повноекранний режим",
"unable_to_exit_fullscreen": "Неможливо вийти з повноекранного режиму", "unable_to_exit_fullscreen": "Неможливо вийти з повноекранного режиму",
"unable_to_get_comments_number": "Не вдалося отримати кількість коментарів", "unable_to_get_comments_number": "Не вдалося отримати кількість коментарів",
@ -710,7 +710,7 @@
"unable_to_reset_password": "Не вдається скинути пароль", "unable_to_reset_password": "Не вдається скинути пароль",
"unable_to_resolve_duplicate": "Не вдається вирішити дублікат", "unable_to_resolve_duplicate": "Не вдається вирішити дублікат",
"unable_to_restore_assets": "Неможливо відновити активи", "unable_to_restore_assets": "Неможливо відновити активи",
"unable_to_restore_trash": "Неможливо відновити сміття", "unable_to_restore_trash": "Не вдалося відновити вміст",
"unable_to_restore_user": "Не вдається відновити користувача", "unable_to_restore_user": "Не вдається відновити користувача",
"unable_to_save_album": "Не вдається зберегти альбом", "unable_to_save_album": "Не вдається зберегти альбом",
"unable_to_save_api_key": "Не вдається зберегти ключ API", "unable_to_save_api_key": "Не вдається зберегти ключ API",
@ -1289,7 +1289,7 @@
"toggle_theme": "Перемикання теми", "toggle_theme": "Перемикання теми",
"total": "Усього", "total": "Усього",
"total_usage": "Загальне використання", "total_usage": "Загальне використання",
"trash": "Кошик", "trash": "Смітник",
"trash_all": "Видалити все", "trash_all": "Видалити все",
"trash_count": "Видалити {count, number}", "trash_count": "Видалити {count, number}",
"trash_delete_asset": "Смітник/Видалити ресурс", "trash_delete_asset": "Смітник/Видалити ресурс",

View File

@ -54,7 +54,7 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
RUN apt-get update && apt-get install -y --no-install-recommends g++ RUN apt-get update && apt-get install -y --no-install-recommends g++
COPY --from=ghcr.io/astral-sh/uv:latest@sha256:57da96c4557243fc0a732817854084e81af9393f64dc7d172f39c16465b5e2ba /uv /uvx /bin/ COPY --from=ghcr.io/astral-sh/uv:latest@sha256:fb91e82e8643382d5bce074ba0d167677d678faff4bd518dac670476d19b159c /uv /uvx /bin/
RUN --mount=type=cache,target=/root/.cache/uv \ RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
@ -67,7 +67,7 @@ FROM python:3.11-slim-bookworm@sha256:7029b00486ac40bed03e36775b864d3f3d39dcbdf1
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2 ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2
FROM prod-cpu AS prod-openvino FROM python:3.11-slim-bookworm@sha256:7029b00486ac40bed03e36775b864d3f3d39dcbdf19cd45e6a52d541e6c178f0 AS prod-openvino
RUN apt-get update && \ RUN apt-get update && \
apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \ apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \
@ -82,6 +82,8 @@ RUN apt-get update && \
FROM nvidia/cuda:12.2.2-runtime-ubuntu22.04@sha256:94c1577b2cd9dd6c0312dc04dff9cb2fdce2b268018abc3d7c2dbcacf1155000 AS prod-cuda FROM nvidia/cuda:12.2.2-runtime-ubuntu22.04@sha256:94c1577b2cd9dd6c0312dc04dff9cb2fdce2b268018abc3d7c2dbcacf1155000 AS prod-cuda
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2
RUN apt-get update && \ RUN apt-get update && \
apt-get install --no-install-recommends -yqq libcudnn9-cuda-12 && \ apt-get install --no-install-recommends -yqq libcudnn9-cuda-12 && \
apt-get clean && \ apt-get clean && \
@ -140,7 +142,6 @@ ENV TRANSFORMERS_CACHE=/cache \
PYTHONPATH=/usr/src \ PYTHONPATH=/usr/src \
DEVICE=${DEVICE} \ DEVICE=${DEVICE} \
VIRTUAL_ENV=/opt/venv \ VIRTUAL_ENV=/opt/venv \
LD_BIND_NOW=1 \
MACHINE_LEARNING_CACHE_FOLDER=/cache MACHINE_LEARNING_CACHE_FOLDER=/cache
# prevent core dumps # prevent core dumps
@ -149,6 +150,7 @@ RUN echo "hard core 0" >> /etc/security/limits.conf && \
echo 'ulimit -S -c 0 > /dev/null 2>&1' >> /etc/profile echo 'ulimit -S -c 0 > /dev/null 2>&1' >> /etc/profile
COPY --from=builder /opt/venv /opt/venv COPY --from=builder /opt/venv /opt/venv
COPY scripts/healthcheck.py .
COPY immich_ml immich_ml COPY immich_ml immich_ml
ARG BUILD_ID ARG BUILD_ID

View File

@ -10,6 +10,7 @@ from tokenizers import Encoding, Tokenizer
from immich_ml.config import log from immich_ml.config import log
from immich_ml.models.base import InferenceModel from immich_ml.models.base import InferenceModel
from immich_ml.models.constants import WEBLATE_TO_FLORES200
from immich_ml.models.transforms import clean_text, serialize_np_array from immich_ml.models.transforms import clean_text, serialize_np_array
from immich_ml.schemas import ModelSession, ModelTask, ModelType from immich_ml.schemas import ModelSession, ModelTask, ModelType
@ -18,8 +19,9 @@ class BaseCLIPTextualEncoder(InferenceModel):
depends = [] depends = []
identity = (ModelType.TEXTUAL, ModelTask.SEARCH) identity = (ModelType.TEXTUAL, ModelTask.SEARCH)
def _predict(self, inputs: str, **kwargs: Any) -> str: def _predict(self, inputs: str, language: str | None = None, **kwargs: Any) -> str:
res: NDArray[np.float32] = self.session.run(None, self.tokenize(inputs))[0][0] tokens = self.tokenize(inputs, language=language)
res: NDArray[np.float32] = self.session.run(None, tokens)[0][0]
return serialize_np_array(res) return serialize_np_array(res)
def _load(self) -> ModelSession: def _load(self) -> ModelSession:
@ -28,6 +30,7 @@ class BaseCLIPTextualEncoder(InferenceModel):
self.tokenizer = self._load_tokenizer() self.tokenizer = self._load_tokenizer()
tokenizer_kwargs: dict[str, Any] | None = self.text_cfg.get("tokenizer_kwargs") tokenizer_kwargs: dict[str, Any] | None = self.text_cfg.get("tokenizer_kwargs")
self.canonicalize = tokenizer_kwargs is not None and tokenizer_kwargs.get("clean") == "canonicalize" self.canonicalize = tokenizer_kwargs is not None and tokenizer_kwargs.get("clean") == "canonicalize"
self.is_nllb = self.model_name.startswith("nllb")
log.debug(f"Loaded tokenizer for CLIP model '{self.model_name}'") log.debug(f"Loaded tokenizer for CLIP model '{self.model_name}'")
return session return session
@ -37,7 +40,7 @@ class BaseCLIPTextualEncoder(InferenceModel):
pass pass
@abstractmethod @abstractmethod
def tokenize(self, text: str) -> dict[str, NDArray[np.int32]]: def tokenize(self, text: str, language: str | None = None) -> dict[str, NDArray[np.int32]]:
pass pass
@property @property
@ -92,14 +95,23 @@ class OpenClipTextualEncoder(BaseCLIPTextualEncoder):
return tokenizer return tokenizer
def tokenize(self, text: str) -> dict[str, NDArray[np.int32]]: def tokenize(self, text: str, language: str | None = None) -> dict[str, NDArray[np.int32]]:
text = clean_text(text, canonicalize=self.canonicalize) text = clean_text(text, canonicalize=self.canonicalize)
if self.is_nllb and language is not None:
flores_code = WEBLATE_TO_FLORES200.get(language)
if flores_code is None:
no_country = language.split("-")[0]
flores_code = WEBLATE_TO_FLORES200.get(no_country)
if flores_code is None:
log.warning(f"Language '{language}' not found, defaulting to 'en'")
flores_code = "eng_Latn"
text = f"{flores_code}{text}"
tokens: Encoding = self.tokenizer.encode(text) tokens: Encoding = self.tokenizer.encode(text)
return {"text": np.array([tokens.ids], dtype=np.int32)} return {"text": np.array([tokens.ids], dtype=np.int32)}
class MClipTextualEncoder(OpenClipTextualEncoder): class MClipTextualEncoder(OpenClipTextualEncoder):
def tokenize(self, text: str) -> dict[str, NDArray[np.int32]]: def tokenize(self, text: str, language: str | None = None) -> dict[str, NDArray[np.int32]]:
text = clean_text(text, canonicalize=self.canonicalize) text = clean_text(text, canonicalize=self.canonicalize)
tokens: Encoding = self.tokenizer.encode(text) tokens: Encoding = self.tokenizer.encode(text)
return { return {

View File

@ -86,6 +86,66 @@ RKNN_SUPPORTED_SOCS = ["rk3566", "rk3568", "rk3576", "rk3588"]
RKNN_COREMASK_SUPPORTED_SOCS = ["rk3576", "rk3588"] RKNN_COREMASK_SUPPORTED_SOCS = ["rk3576", "rk3588"]
WEBLATE_TO_FLORES200 = {
"af": "afr_Latn",
"ar": "arb_Arab",
"az": "azj_Latn",
"be": "bel_Cyrl",
"bg": "bul_Cyrl",
"ca": "cat_Latn",
"cs": "ces_Latn",
"da": "dan_Latn",
"de": "deu_Latn",
"el": "ell_Grek",
"en": "eng_Latn",
"es": "spa_Latn",
"et": "est_Latn",
"fa": "pes_Arab",
"fi": "fin_Latn",
"fr": "fra_Latn",
"he": "heb_Hebr",
"hi": "hin_Deva",
"hr": "hrv_Latn",
"hu": "hun_Latn",
"hy": "hye_Armn",
"id": "ind_Latn",
"it": "ita_Latn",
"ja": "jpn_Hira",
"kmr": "kmr_Latn",
"ko": "kor_Hang",
"lb": "ltz_Latn",
"lt": "lit_Latn",
"lv": "lav_Latn",
"mfa": "zsm_Latn",
"mk": "mkd_Cyrl",
"mn": "khk_Cyrl",
"mr": "mar_Deva",
"ms": "zsm_Latn",
"nb-NO": "nob_Latn",
"nn": "nno_Latn",
"nl": "nld_Latn",
"pl": "pol_Latn",
"pt-BR": "por_Latn",
"pt": "por_Latn",
"ro": "ron_Latn",
"ru": "rus_Cyrl",
"sk": "slk_Latn",
"sl": "slv_Latn",
"sr-Cyrl": "srp_Cyrl",
"sv": "swe_Latn",
"ta": "tam_Taml",
"te": "tel_Telu",
"th": "tha_Thai",
"tr": "tur_Latn",
"uk": "ukr_Cyrl",
"ur": "urd_Arab",
"vi": "vie_Latn",
"zh-CN": "zho_Hans",
"zh-Hans": "zho_Hans",
"zh-TW": "zho_Hant",
}
def get_model_source(model_name: str) -> ModelSource | None: def get_model_source(model_name: str) -> ModelSource | None:
cleaned_name = clean_name(model_name) cleaned_name = clean_name(model_name)

View File

@ -494,6 +494,88 @@ class TestCLIP:
assert np.allclose(tokens["text"], np.array([mock_ids], dtype=np.int32), atol=0) assert np.allclose(tokens["text"], np.array([mock_ids], dtype=np.int32), atol=0)
mock_tokenizer.encode.assert_called_once_with("test search query") mock_tokenizer.encode.assert_called_once_with("test search query")
def test_openclip_tokenizer_adds_flores_token_for_nllb(
self,
mocker: MockerFixture,
clip_model_cfg: dict[str, Any],
clip_tokenizer_cfg: Callable[[Path], dict[str, Any]],
) -> None:
mocker.patch.object(OpenClipTextualEncoder, "download")
mocker.patch.object(OpenClipTextualEncoder, "model_cfg", clip_model_cfg)
mocker.patch.object(OpenClipTextualEncoder, "tokenizer_cfg", clip_tokenizer_cfg)
mocker.patch.object(InferenceModel, "_make_session", autospec=True).return_value
mock_tokenizer = mocker.patch("immich_ml.models.clip.textual.Tokenizer.from_file", autospec=True).return_value
mock_ids = [randint(0, 50000) for _ in range(77)]
mock_tokenizer.encode.return_value = SimpleNamespace(ids=mock_ids)
clip_encoder = OpenClipTextualEncoder("nllb-clip-base-siglip__mrl", cache_dir="test_cache")
clip_encoder._load()
clip_encoder.tokenize("test search query", language="de")
mock_tokenizer.encode.assert_called_once_with("deu_Latntest search query")
def test_openclip_tokenizer_removes_country_code_from_language_for_nllb_if_not_found(
self,
mocker: MockerFixture,
clip_model_cfg: dict[str, Any],
clip_tokenizer_cfg: Callable[[Path], dict[str, Any]],
) -> None:
mocker.patch.object(OpenClipTextualEncoder, "download")
mocker.patch.object(OpenClipTextualEncoder, "model_cfg", clip_model_cfg)
mocker.patch.object(OpenClipTextualEncoder, "tokenizer_cfg", clip_tokenizer_cfg)
mocker.patch.object(InferenceModel, "_make_session", autospec=True).return_value
mock_tokenizer = mocker.patch("immich_ml.models.clip.textual.Tokenizer.from_file", autospec=True).return_value
mock_ids = [randint(0, 50000) for _ in range(77)]
mock_tokenizer.encode.return_value = SimpleNamespace(ids=mock_ids)
clip_encoder = OpenClipTextualEncoder("nllb-clip-base-siglip__mrl", cache_dir="test_cache")
clip_encoder._load()
clip_encoder.tokenize("test search query", language="de-CH")
mock_tokenizer.encode.assert_called_once_with("deu_Latntest search query")
def test_openclip_tokenizer_falls_back_to_english_for_nllb_if_language_code_not_found(
self,
mocker: MockerFixture,
clip_model_cfg: dict[str, Any],
clip_tokenizer_cfg: Callable[[Path], dict[str, Any]],
warning: mock.Mock,
) -> None:
mocker.patch.object(OpenClipTextualEncoder, "download")
mocker.patch.object(OpenClipTextualEncoder, "model_cfg", clip_model_cfg)
mocker.patch.object(OpenClipTextualEncoder, "tokenizer_cfg", clip_tokenizer_cfg)
mocker.patch.object(InferenceModel, "_make_session", autospec=True).return_value
mock_tokenizer = mocker.patch("immich_ml.models.clip.textual.Tokenizer.from_file", autospec=True).return_value
mock_ids = [randint(0, 50000) for _ in range(77)]
mock_tokenizer.encode.return_value = SimpleNamespace(ids=mock_ids)
clip_encoder = OpenClipTextualEncoder("nllb-clip-base-siglip__mrl", cache_dir="test_cache")
clip_encoder._load()
clip_encoder.tokenize("test search query", language="unknown")
mock_tokenizer.encode.assert_called_once_with("eng_Latntest search query")
warning.assert_called_once_with("Language 'unknown' not found, defaulting to 'en'")
def test_openclip_tokenizer_does_not_add_flores_token_for_non_nllb_model(
self,
mocker: MockerFixture,
clip_model_cfg: dict[str, Any],
clip_tokenizer_cfg: Callable[[Path], dict[str, Any]],
) -> None:
mocker.patch.object(OpenClipTextualEncoder, "download")
mocker.patch.object(OpenClipTextualEncoder, "model_cfg", clip_model_cfg)
mocker.patch.object(OpenClipTextualEncoder, "tokenizer_cfg", clip_tokenizer_cfg)
mocker.patch.object(InferenceModel, "_make_session", autospec=True).return_value
mock_tokenizer = mocker.patch("immich_ml.models.clip.textual.Tokenizer.from_file", autospec=True).return_value
mock_ids = [randint(0, 50000) for _ in range(77)]
mock_tokenizer.encode.return_value = SimpleNamespace(ids=mock_ids)
clip_encoder = OpenClipTextualEncoder("ViT-B-32__openai", cache_dir="test_cache")
clip_encoder._load()
clip_encoder.tokenize("test search query", language="de")
mock_tokenizer.encode.assert_called_once_with("test search query")
def test_mclip_tokenizer( def test_mclip_tokenizer(
self, self,
mocker: MockerFixture, mocker: MockerFixture,

309
machine-learning/uv.lock generated
View File

@ -508,16 +508,16 @@ wheels = [
[[package]] [[package]]
name = "fastapi" name = "fastapi"
version = "0.115.11" version = "0.115.12"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "pydantic" }, { name = "pydantic" },
{ name = "starlette" }, { name = "starlette" },
{ name = "typing-extensions" }, { name = "typing-extensions" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/b5/28/c5d26e5860df807241909a961a37d45e10533acef95fc368066c7dd186cd/fastapi-0.115.11.tar.gz", hash = "sha256:cc81f03f688678b92600a65a5e618b93592c65005db37157147204d8924bf94f", size = 294441 } sdist = { url = "https://files.pythonhosted.org/packages/f4/55/ae499352d82338331ca1e28c7f4a63bfd09479b16395dce38cf50a39e2c2/fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681", size = 295236 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/b3/5d/4d8bbb94f0dbc22732350c06965e40740f4a92ca560e90bb566f4f73af41/fastapi-0.115.11-py3-none-any.whl", hash = "sha256:32e1541b7b74602e4ef4a0260ecaf3aadf9d4f19590bba3e1bf2ac4666aa2c64", size = 94926 }, { url = "https://files.pythonhosted.org/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164 },
] ]
[[package]] [[package]]
@ -1583,62 +1583,64 @@ wheels = [
[[package]] [[package]]
name = "orjson" name = "orjson"
version = "3.10.15" version = "3.10.16"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ae/f9/5dea21763eeff8c1590076918a446ea3d6140743e0e36f58f369928ed0f4/orjson-3.10.15.tar.gz", hash = "sha256:05ca7fe452a2e9d8d9d706a2984c95b9c2ebc5db417ce0b7a49b91d50642a23e", size = 5282482 } sdist = { url = "https://files.pythonhosted.org/packages/98/c7/03913cc4332174071950acf5b0735463e3f63760c80585ef369270c2b372/orjson-3.10.16.tar.gz", hash = "sha256:d2aaa5c495e11d17b9b93205f5fa196737ee3202f000aaebf028dc9a73750f10", size = 5410415 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/52/09/e5ff18ad009e6f97eb7edc5f67ef98b3ce0c189da9c3eaca1f9587cd4c61/orjson-3.10.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:552c883d03ad185f720d0c09583ebde257e41b9521b74ff40e08b7dec4559c04", size = 249532 }, { url = "https://files.pythonhosted.org/packages/9d/a6/22cb9b03baf167bc2d659c9e74d7580147f36e6a155e633801badfd5a74d/orjson-3.10.16-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4cb473b8e79154fa778fb56d2d73763d977be3dcc140587e07dbc545bbfc38f8", size = 249179 },
{ url = "https://files.pythonhosted.org/packages/bd/b8/a75883301fe332bd433d9b0ded7d2bb706ccac679602c3516984f8814fb5/orjson-3.10.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e3e8d438d02e4854f70bfdc03a6bcdb697358dbaa6bcd19cbe24d24ece1f8", size = 125229 }, { url = "https://files.pythonhosted.org/packages/d7/ce/3e68cc33020a6ebd8f359b8628b69d2132cd84fea68155c33057e502ee51/orjson-3.10.16-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:622a8e85eeec1948690409a19ca1c7d9fd8ff116f4861d261e6ae2094fe59a00", size = 138510 },
{ url = "https://files.pythonhosted.org/packages/83/4b/22f053e7a364cc9c685be203b1e40fc5f2b3f164a9b2284547504eec682e/orjson-3.10.15-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c2c79fa308e6edb0ffab0a31fd75a7841bf2a79a20ef08a3c6e3b26814c8ca8", size = 150148 }, { url = "https://files.pythonhosted.org/packages/dc/12/63bee7764ce12052f7c1a1393ce7f26dc392c93081eb8754dd3dce9b7c6b/orjson-3.10.16-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c682d852d0ce77613993dc967e90e151899fe2d8e71c20e9be164080f468e370", size = 132373 },
{ url = "https://files.pythonhosted.org/packages/63/64/1b54fc75ca328b57dd810541a4035fe48c12a161d466e3cf5b11a8c25649/orjson-3.10.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cb85490aa6bf98abd20607ab5c8324c0acb48d6da7863a51be48505646c814", size = 139748 }, { url = "https://files.pythonhosted.org/packages/b3/d5/2998c2f319adcd572f2b03ba2083e8176863d1055d8d713683ddcf927b71/orjson-3.10.16-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c520ae736acd2e32df193bcff73491e64c936f3e44a2916b548da048a48b46b", size = 136774 },
{ url = "https://files.pythonhosted.org/packages/5e/ff/ff0c5da781807bb0a5acd789d9a7fbcb57f7b0c6e1916595da1f5ce69f3c/orjson-3.10.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763dadac05e4e9d2bc14938a45a2d0560549561287d41c465d3c58aec818b164", size = 154559 }, { url = "https://files.pythonhosted.org/packages/00/03/88c236ae307bd0604623204d4a835e15fbf9c75b8535c8f13ef45abd413f/orjson-3.10.16-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:134f87c76bfae00f2094d85cfab261b289b76d78c6da8a7a3b3c09d362fd1e06", size = 138030 },
{ url = "https://files.pythonhosted.org/packages/4e/9a/11e2974383384ace8495810d4a2ebef5f55aacfc97b333b65e789c9d362d/orjson-3.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a330b9b4734f09a623f74a7490db713695e13b67c959713b78369f26b3dee6bf", size = 130349 }, { url = "https://files.pythonhosted.org/packages/66/ba/3e256ddfeb364f98fd6ac65774844090d356158b2d1de8998db2bf984503/orjson-3.10.16-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b59afde79563e2cf37cfe62ee3b71c063fd5546c8e662d7fcfc2a3d5031a5c4c", size = 142677 },
{ url = "https://files.pythonhosted.org/packages/2d/c4/dd9583aea6aefee1b64d3aed13f51d2aadb014028bc929fe52936ec5091f/orjson-3.10.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a61a4622b7ff861f019974f73d8165be1bd9a0855e1cad18ee167acacabeb061", size = 138514 }, { url = "https://files.pythonhosted.org/packages/2c/71/73a1214bd27baa2ea5184fff4aa6193a114dfb0aa5663dad48fe63e8cd29/orjson-3.10.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:113602f8241daaff05d6fad25bd481d54c42d8d72ef4c831bb3ab682a54d9e15", size = 132798 },
{ url = "https://files.pythonhosted.org/packages/53/3e/dcf1729230654f5c5594fc752de1f43dcf67e055ac0d300c8cdb1309269a/orjson-3.10.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acd271247691574416b3228db667b84775c497b245fa275c6ab90dc1ffbbd2b3", size = 130940 }, { url = "https://files.pythonhosted.org/packages/53/ac/0b2f41c0a1e8c095439d0fab3b33103cf41a39be8e6aa2c56298a6034259/orjson-3.10.16-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4fc0077d101f8fab4031e6554fc17b4c2ad8fdbc56ee64a727f3c95b379e31da", size = 135450 },
{ url = "https://files.pythonhosted.org/packages/e8/2b/b9759fe704789937705c8a56a03f6c03e50dff7df87d65cba9a20fec5282/orjson-3.10.15-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4759b109c37f635aa5c5cc93a1b26927bfde24b254bcc0e1149a9fada253d2d", size = 414713 }, { url = "https://files.pythonhosted.org/packages/d9/ca/7524c7b0bc815d426ca134dab54cad519802287b808a3846b047a5b2b7a3/orjson-3.10.16-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:9c6bf6ff180cd69e93f3f50380224218cfab79953a868ea3908430bcfaf9cb5e", size = 412356 },
{ url = "https://files.pythonhosted.org/packages/a7/6b/b9dfdbd4b6e20a59238319eb203ae07c3f6abf07eef909169b7a37ae3bba/orjson-3.10.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e992fd5cfb8b9f00bfad2fd7a05a4299db2bbe92e6440d9dd2fab27655b3182", size = 141028 }, { url = "https://files.pythonhosted.org/packages/05/1d/3ae2367c255276bf16ff7e1b210dd0af18bc8da20c4e4295755fc7de1268/orjson-3.10.16-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5673eadfa952f95a7cd76418ff189df11b0a9c34b1995dff43a6fdbce5d63bf4", size = 152769 },
{ url = "https://files.pythonhosted.org/packages/7c/b5/40f5bbea619c7caf75eb4d652a9821875a8ed04acc45fe3d3ef054ca69fb/orjson-3.10.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f95fb363d79366af56c3f26b71df40b9a583b07bbaaf5b317407c4d58497852e", size = 129715 }, { url = "https://files.pythonhosted.org/packages/d3/2d/8eb10b6b1d30bb69c35feb15e5ba5ac82466cf743d562e3e8047540efd2f/orjson-3.10.16-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5fe638a423d852b0ae1e1a79895851696cb0d9fa0946fdbfd5da5072d9bb9551", size = 137223 },
{ url = "https://files.pythonhosted.org/packages/38/60/2272514061cbdf4d672edbca6e59c7e01cd1c706e881427d88f3c3e79761/orjson-3.10.15-cp310-cp310-win32.whl", hash = "sha256:f9875f5fea7492da8ec2444839dcc439b0ef298978f311103d0b7dfd775898ab", size = 142473 }, { url = "https://files.pythonhosted.org/packages/47/42/f043717930cb2de5fbebe47f308f101bed9ec2b3580b1f99c8284b2f5fe8/orjson-3.10.16-cp310-cp310-win32.whl", hash = "sha256:33af58f479b3c6435ab8f8b57999874b4b40c804c7a36b5cc6b54d8f28e1d3dd", size = 141734 },
{ url = "https://files.pythonhosted.org/packages/11/5d/be1490ff7eafe7fef890eb4527cf5bcd8cfd6117f3efe42a3249ec847b60/orjson-3.10.15-cp310-cp310-win_amd64.whl", hash = "sha256:17085a6aa91e1cd70ca8533989a18b5433e15d29c574582f76f821737c8d5806", size = 133564 }, { url = "https://files.pythonhosted.org/packages/67/99/795ad7282b425b9fddcfb8a31bded5dcf84dba78ecb1e7ae716e84e794da/orjson-3.10.16-cp310-cp310-win_amd64.whl", hash = "sha256:0338356b3f56d71293c583350af26f053017071836b07e064e92819ecf1aa055", size = 133779 },
{ url = "https://files.pythonhosted.org/packages/7a/a2/21b25ce4a2c71dbb90948ee81bd7a42b4fbfc63162e57faf83157d5540ae/orjson-3.10.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c4cc83960ab79a4031f3119cc4b1a1c627a3dc09df125b27c4201dff2af7eaa6", size = 249533 }, { url = "https://files.pythonhosted.org/packages/97/29/43f91a5512b5d2535594438eb41c5357865fd5e64dec745d90a588820c75/orjson-3.10.16-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44fcbe1a1884f8bc9e2e863168b0f84230c3d634afe41c678637d2728ea8e739", size = 249180 },
{ url = "https://files.pythonhosted.org/packages/b2/85/2076fc12d8225698a51278009726750c9c65c846eda741e77e1761cfef33/orjson-3.10.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ddbeef2481d895ab8be5185f2432c334d6dec1f5d1933a9c83014d188e102cef", size = 125230 }, { url = "https://files.pythonhosted.org/packages/0c/36/2a72d55e266473c19a86d97b7363bb8bf558ab450f75205689a287d5ce61/orjson-3.10.16-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78177bf0a9d0192e0b34c3d78bcff7fe21d1b5d84aeb5ebdfe0dbe637b885225", size = 138510 },
{ url = "https://files.pythonhosted.org/packages/06/df/a85a7955f11274191eccf559e8481b2be74a7c6d43075d0a9506aa80284d/orjson-3.10.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e590a0477b23ecd5b0ac865b1b907b01b3c5535f5e8a8f6ab0e503efb896334", size = 150148 }, { url = "https://files.pythonhosted.org/packages/bb/ad/f86d6f55c1a68b57ff6ea7966bce5f4e5163f2e526ddb7db9fc3c2c8d1c4/orjson-3.10.16-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12824073a010a754bb27330cad21d6e9b98374f497f391b8707752b96f72e741", size = 132373 },
{ url = "https://files.pythonhosted.org/packages/37/b3/94c55625a29b8767c0eed194cb000b3787e3c23b4cdd13be17bae6ccbb4b/orjson-3.10.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6be38bd103d2fd9bdfa31c2720b23b5d47c6796bcb1d1b598e3924441b4298d", size = 139749 }, { url = "https://files.pythonhosted.org/packages/5e/8b/d18f2711493a809f3082a88fda89342bc8e16767743b909cd3c34989fba3/orjson-3.10.16-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddd41007e56284e9867864aa2f29f3136bb1dd19a49ca43c0b4eda22a579cf53", size = 136773 },
{ url = "https://files.pythonhosted.org/packages/53/ba/c608b1e719971e8ddac2379f290404c2e914cf8e976369bae3cad88768b1/orjson-3.10.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff4f6edb1578960ed628a3b998fa54d78d9bb3e2eb2cfc5c2a09732431c678d0", size = 154558 }, { url = "https://files.pythonhosted.org/packages/a1/dc/ce025f002f8e0749e3f057c4d773a4d4de32b7b4c1fc5a50b429e7532586/orjson-3.10.16-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0877c4d35de639645de83666458ca1f12560d9fa7aa9b25d8bb8f52f61627d14", size = 138029 },
{ url = "https://files.pythonhosted.org/packages/b2/c4/c1fb835bb23ad788a39aa9ebb8821d51b1c03588d9a9e4ca7de5b354fdd5/orjson-3.10.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0482b21d0462eddd67e7fce10b89e0b6ac56570424662b685a0d6fccf581e13", size = 130349 }, { url = "https://files.pythonhosted.org/packages/0e/1b/cf9df85852b91160029d9f26014230366a2b4deb8cc51fabe68e250a8c1a/orjson-3.10.16-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9a09a539e9cc3beead3e7107093b4ac176d015bec64f811afb5965fce077a03c", size = 142677 },
{ url = "https://files.pythonhosted.org/packages/78/14/bb2b48b26ab3c570b284eb2157d98c1ef331a8397f6c8bd983b270467f5c/orjson-3.10.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bb5cc3527036ae3d98b65e37b7986a918955f85332c1ee07f9d3f82f3a6899b5", size = 138513 }, { url = "https://files.pythonhosted.org/packages/92/18/5b1e1e995bffad49dc4311a0bdfd874bc6f135fd20f0e1f671adc2c9910e/orjson-3.10.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31b98bc9b40610fec971d9a4d67bb2ed02eec0a8ae35f8ccd2086320c28526ca", size = 132800 },
{ url = "https://files.pythonhosted.org/packages/4a/97/d5b353a5fe532e92c46467aa37e637f81af8468aa894cd77d2ec8a12f99e/orjson-3.10.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d569c1c462912acdd119ccbf719cf7102ea2c67dd03b99edcb1a3048651ac96b", size = 130942 }, { url = "https://files.pythonhosted.org/packages/d6/eb/467f25b580e942fcca1344adef40633b7f05ac44a65a63fc913f9a805d58/orjson-3.10.16-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0ce243f5a8739f3a18830bc62dc2e05b69a7545bafd3e3249f86668b2bcd8e50", size = 135451 },
{ url = "https://files.pythonhosted.org/packages/b5/5d/a067bec55293cca48fea8b9928cfa84c623be0cce8141d47690e64a6ca12/orjson-3.10.15-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:1e6d33efab6b71d67f22bf2962895d3dc6f82a6273a965fab762e64fa90dc399", size = 414717 }, { url = "https://files.pythonhosted.org/packages/8d/4b/9d10888038975cb375982e9339d9495bac382d5c976c500b8d6f2c8e2e4e/orjson-3.10.16-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:64792c0025bae049b3074c6abe0cf06f23c8e9f5a445f4bab31dc5ca23dbf9e1", size = 412358 },
{ url = "https://files.pythonhosted.org/packages/6f/9a/1485b8b05c6b4c4db172c438cf5db5dcfd10e72a9bc23c151a1137e763e0/orjson-3.10.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c33be3795e299f565681d69852ac8c1bc5c84863c0b0030b2b3468843be90388", size = 141033 }, { url = "https://files.pythonhosted.org/packages/3b/e2/cfbcfcc4fbe619e0ca9bdbbfccb2d62b540bbfe41e0ee77d44a628594f59/orjson-3.10.16-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea53f7e68eec718b8e17e942f7ca56c6bd43562eb19db3f22d90d75e13f0431d", size = 152772 },
{ url = "https://files.pythonhosted.org/packages/f8/d2/fc67523656e43a0c7eaeae9007c8b02e86076b15d591e9be11554d3d3138/orjson-3.10.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eea80037b9fae5339b214f59308ef0589fc06dc870578b7cce6d71eb2096764c", size = 129720 }, { url = "https://files.pythonhosted.org/packages/b9/d6/627a1b00569be46173007c11dde3da4618c9bfe18409325b0e3e2a82fe29/orjson-3.10.16-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a741ba1a9488c92227711bde8c8c2b63d7d3816883268c808fbeada00400c164", size = 137225 },
{ url = "https://files.pythonhosted.org/packages/79/42/f58c7bd4e5b54da2ce2ef0331a39ccbbaa7699b7f70206fbf06737c9ed7d/orjson-3.10.15-cp311-cp311-win32.whl", hash = "sha256:d5ac11b659fd798228a7adba3e37c010e0152b78b1982897020a8e019a94882e", size = 142473 }, { url = "https://files.pythonhosted.org/packages/0a/7b/a73c67b505021af845b9f05c7c848793258ea141fa2058b52dd9b067c2b4/orjson-3.10.16-cp311-cp311-win32.whl", hash = "sha256:c7ed2c61bb8226384c3fdf1fb01c51b47b03e3f4536c985078cccc2fd19f1619", size = 141733 },
{ url = "https://files.pythonhosted.org/packages/00/f8/bb60a4644287a544ec81df1699d5b965776bc9848d9029d9f9b3402ac8bb/orjson-3.10.15-cp311-cp311-win_amd64.whl", hash = "sha256:cf45e0214c593660339ef63e875f32ddd5aa3b4adc15e662cdb80dc49e194f8e", size = 133570 }, { url = "https://files.pythonhosted.org/packages/f4/22/5e8217c48d68c0adbfb181e749d6a733761074e598b083c69a1383d18147/orjson-3.10.16-cp311-cp311-win_amd64.whl", hash = "sha256:cd67d8b3e0e56222a2e7b7f7da9031e30ecd1fe251c023340b9f12caca85ab60", size = 133784 },
{ url = "https://files.pythonhosted.org/packages/66/85/22fe737188905a71afcc4bf7cc4c79cd7f5bbe9ed1fe0aac4ce4c33edc30/orjson-3.10.15-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9d11c0714fc85bfcf36ada1179400862da3288fc785c30e8297844c867d7505a", size = 249504 }, { url = "https://files.pythonhosted.org/packages/5d/15/67ce9d4c959c83f112542222ea3b9209c1d424231d71d74c4890ea0acd2b/orjson-3.10.16-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6d3444abbfa71ba21bb042caa4b062535b122248259fdb9deea567969140abca", size = 249325 },
{ url = "https://files.pythonhosted.org/packages/48/b7/2622b29f3afebe938a0a9037e184660379797d5fd5234e5998345d7a5b43/orjson-3.10.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dba5a1e85d554e3897fa9fe6fbcff2ed32d55008973ec9a2b992bd9a65d2352d", size = 125080 }, { url = "https://files.pythonhosted.org/packages/da/2c/1426b06f30a1b9ada74b6f512c1ddf9d2760f53f61cdb59efeb9ad342133/orjson-3.10.16-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:30245c08d818fdcaa48b7d5b81499b8cae09acabb216fe61ca619876b128e184", size = 133621 },
{ url = "https://files.pythonhosted.org/packages/ce/8f/0b72a48f4403d0b88b2a41450c535b3e8989e8a2d7800659a967efc7c115/orjson-3.10.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7723ad949a0ea502df656948ddd8b392780a5beaa4c3b5f97e525191b102fff0", size = 150121 }, { url = "https://files.pythonhosted.org/packages/9e/88/18d26130954bc73bee3be10f95371ea1dfb8679e0e2c46b0f6d8c6289402/orjson-3.10.16-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0ba1d0baa71bf7579a4ccdcf503e6f3098ef9542106a0eca82395898c8a500a", size = 138270 },
{ url = "https://files.pythonhosted.org/packages/06/ec/acb1a20cd49edb2000be5a0404cd43e3c8aad219f376ac8c60b870518c03/orjson-3.10.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6fd9bc64421e9fe9bd88039e7ce8e58d4fead67ca88e3a4014b143cec7684fd4", size = 139796 }, { url = "https://files.pythonhosted.org/packages/4f/f9/6d8b64fcd58fae072e80ee7981be8ba0d7c26ace954e5cd1d027fc80518f/orjson-3.10.16-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb0beefa5ef3af8845f3a69ff2a4aa62529b5acec1cfe5f8a6b4141033fd46ef", size = 132346 },
{ url = "https://files.pythonhosted.org/packages/33/e1/f7840a2ea852114b23a52a1c0b2bea0a1ea22236efbcdb876402d799c423/orjson-3.10.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dadba0e7b6594216c214ef7894c4bd5f08d7c0135f4dd0145600be4fbcc16767", size = 154636 }, { url = "https://files.pythonhosted.org/packages/16/3f/2513fd5bc786f40cd12af569c23cae6381aeddbefeed2a98f0a666eb5d0d/orjson-3.10.16-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6daa0e1c9bf2e030e93c98394de94506f2a4d12e1e9dadd7c53d5e44d0f9628e", size = 136845 },
{ url = "https://files.pythonhosted.org/packages/fa/da/31543337febd043b8fa80a3b67de627669b88c7b128d9ad4cc2ece005b7a/orjson-3.10.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48f59114fe318f33bbaee8ebeda696d8ccc94c9e90bc27dbe72153094e26f41", size = 130621 }, { url = "https://files.pythonhosted.org/packages/6d/42/b0e7b36720f5ab722b48e8ccf06514d4f769358dd73c51abd8728ef58d0b/orjson-3.10.16-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9da9019afb21e02410ef600e56666652b73eb3e4d213a0ec919ff391a7dd52aa", size = 138078 },
{ url = "https://files.pythonhosted.org/packages/ed/78/66115dc9afbc22496530d2139f2f4455698be444c7c2475cb48f657cefc9/orjson-3.10.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:035fb83585e0f15e076759b6fedaf0abb460d1765b6a36f48018a52858443514", size = 138516 }, { url = "https://files.pythonhosted.org/packages/a3/a8/d220afb8a439604be74fc755dbc740bded5ed14745ca536b304ed32eb18a/orjson-3.10.16-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:daeb3a1ee17b69981d3aae30c3b4e786b0f8c9e6c71f2b48f1aef934f63f38f4", size = 142712 },
{ url = "https://files.pythonhosted.org/packages/22/84/cd4f5fb5427ffcf823140957a47503076184cb1ce15bcc1165125c26c46c/orjson-3.10.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d13b7fe322d75bf84464b075eafd8e7dd9eae05649aa2a5354cfa32f43c59f17", size = 130762 }, { url = "https://files.pythonhosted.org/packages/8c/88/7e41e9883c00f84f92fe357a8371edae816d9d7ef39c67b5106960c20389/orjson-3.10.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80fed80eaf0e20a31942ae5d0728849862446512769692474be5e6b73123a23b", size = 133136 },
{ url = "https://files.pythonhosted.org/packages/93/1f/67596b711ba9f56dd75d73b60089c5c92057f1130bb3a25a0f53fb9a583b/orjson-3.10.15-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7066b74f9f259849629e0d04db6609db4cf5b973248f455ba5d3bd58a4daaa5b", size = 414700 }, { url = "https://files.pythonhosted.org/packages/e9/ca/61116095307ad0be828ea26093febaf59e38596d84a9c8d765c3c5e4934f/orjson-3.10.16-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73390ed838f03764540a7bdc4071fe0123914c2cc02fb6abf35182d5fd1b7a42", size = 135258 },
{ url = "https://files.pythonhosted.org/packages/7c/0c/6a3b3271b46443d90efb713c3e4fe83fa8cd71cda0d11a0f69a03f437c6e/orjson-3.10.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88dc3f65a026bd3175eb157fea994fca6ac7c4c8579fc5a86fc2114ad05705b7", size = 141077 }, { url = "https://files.pythonhosted.org/packages/dc/1b/09493cf7d801505f094c9295f79c98c1e0af2ac01c7ed8d25b30fcb19ada/orjson-3.10.16-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a22bba012a0c94ec02a7768953020ab0d3e2b884760f859176343a36c01adf87", size = 412326 },
{ url = "https://files.pythonhosted.org/packages/3b/9b/33c58e0bfc788995eccd0d525ecd6b84b40d7ed182dd0751cd4c1322ac62/orjson-3.10.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b342567e5465bd99faa559507fe45e33fc76b9fb868a63f1642c6bc0735ad02a", size = 129898 }, { url = "https://files.pythonhosted.org/packages/ea/02/125d7bbd7f7a500190ddc8ae5d2d3c39d87ed3ed28f5b37cfe76962c678d/orjson-3.10.16-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5385bbfdbc90ff5b2635b7e6bebf259652db00a92b5e3c45b616df75b9058e88", size = 152800 },
{ url = "https://files.pythonhosted.org/packages/01/c1/d577ecd2e9fa393366a1ea0a9267f6510d86e6c4bb1cdfb9877104cac44c/orjson-3.10.15-cp312-cp312-win32.whl", hash = "sha256:0a4f27ea5617828e6b58922fdbec67b0aa4bb844e2d363b9244c47fa2180e665", size = 142566 }, { url = "https://files.pythonhosted.org/packages/f9/09/7658a9e3e793d5b3b00598023e0fb6935d0e7bbb8ff72311c5415a8ce677/orjson-3.10.16-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:02c6279016346e774dd92625d46c6c40db687b8a0d685aadb91e26e46cc33e1e", size = 137516 },
{ url = "https://files.pythonhosted.org/packages/ed/eb/a85317ee1732d1034b92d56f89f1de4d7bf7904f5c8fb9dcdd5b1c83917f/orjson-3.10.15-cp312-cp312-win_amd64.whl", hash = "sha256:ef5b87e7aa9545ddadd2309efe6824bd3dd64ac101c15dae0f2f597911d46eaa", size = 133732 }, { url = "https://files.pythonhosted.org/packages/29/87/32b7a4831e909d347278101a48d4cf9f3f25901b2295e7709df1651f65a1/orjson-3.10.16-cp312-cp312-win32.whl", hash = "sha256:7ca55097a11426db80f79378e873a8c51f4dde9ffc22de44850f9696b7eb0e8c", size = 141759 },
{ url = "https://files.pythonhosted.org/packages/06/10/fe7d60b8da538e8d3d3721f08c1b7bff0491e8fa4dd3bf11a17e34f4730e/orjson-3.10.15-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bae0e6ec2b7ba6895198cd981b7cca95d1487d0147c8ed751e5632ad16f031a6", size = 249399 }, { url = "https://files.pythonhosted.org/packages/35/ce/81a27e7b439b807bd393585271364cdddf50dc281fc57c4feef7ccb186a6/orjson-3.10.16-cp312-cp312-win_amd64.whl", hash = "sha256:86d127efdd3f9bf5f04809b70faca1e6836556ea3cc46e662b44dab3fe71f3d6", size = 133944 },
{ url = "https://files.pythonhosted.org/packages/6b/83/52c356fd3a61abd829ae7e4366a6fe8e8863c825a60d7ac5156067516edf/orjson-3.10.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f93ce145b2db1252dd86af37d4165b6faa83072b46e3995ecc95d4b2301b725a", size = 125044 }, { url = "https://files.pythonhosted.org/packages/87/b9/ff6aa28b8c86af9526160905593a2fe8d004ac7a5e592ee0b0ff71017511/orjson-3.10.16-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:148a97f7de811ba14bc6dbc4a433e0341ffd2cc285065199fb5f6a98013744bd", size = 249289 },
{ url = "https://files.pythonhosted.org/packages/55/b2/d06d5901408e7ded1a74c7c20d70e3a127057a6d21355f50c90c0f337913/orjson-3.10.15-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c203f6f969210128af3acae0ef9ea6aab9782939f45f6fe02d05958fe761ef9", size = 150066 }, { url = "https://files.pythonhosted.org/packages/6c/81/6d92a586149b52684ab8fd70f3623c91d0e6a692f30fd8c728916ab2263c/orjson-3.10.16-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:1d960c1bf0e734ea36d0adc880076de3846aaec45ffad29b78c7f1b7962516b8", size = 133640 },
{ url = "https://files.pythonhosted.org/packages/75/8c/60c3106e08dc593a861755781c7c675a566445cc39558677d505878d879f/orjson-3.10.15-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8918719572d662e18b8af66aef699d8c21072e54b6c82a3f8f6404c1f5ccd5e0", size = 139737 }, { url = "https://files.pythonhosted.org/packages/c2/88/b72443f4793d2e16039ab85d0026677932b15ab968595fb7149750d74134/orjson-3.10.16-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a318cd184d1269f68634464b12871386808dc8b7c27de8565234d25975a7a137", size = 138286 },
{ url = "https://files.pythonhosted.org/packages/6a/8c/ae00d7d0ab8a4490b1efeb01ad4ab2f1982e69cc82490bf8093407718ff5/orjson-3.10.15-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f71eae9651465dff70aa80db92586ad5b92df46a9373ee55252109bb6b703307", size = 154804 }, { url = "https://files.pythonhosted.org/packages/c3/3c/72a22d4b28c076c4016d5a52bd644a8e4d849d3bb0373d9e377f9e3b2250/orjson-3.10.16-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df23f8df3ef9223d1d6748bea63fca55aae7da30a875700809c500a05975522b", size = 132307 },
{ url = "https://files.pythonhosted.org/packages/22/86/65dc69bd88b6dd254535310e97bc518aa50a39ef9c5a2a5d518e7a223710/orjson-3.10.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e117eb299a35f2634e25ed120c37c641398826c2f5a3d3cc39f5993b96171b9e", size = 130583 }, { url = "https://files.pythonhosted.org/packages/8a/a2/f1259561bdb6ad7061ff1b95dab082fe32758c4bc143ba8d3d70831f0a06/orjson-3.10.16-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b94dda8dd6d1378f1037d7f3f6b21db769ef911c4567cbaa962bb6dc5021cf90", size = 136739 },
{ url = "https://files.pythonhosted.org/packages/bb/00/6fe01ededb05d52be42fabb13d93a36e51f1fd9be173bd95707d11a8a860/orjson-3.10.15-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13242f12d295e83c2955756a574ddd6741c81e5b99f2bef8ed8d53e47a01e4b7", size = 138465 }, { url = "https://files.pythonhosted.org/packages/3d/af/c7583c4b34f33d8b8b90cfaab010ff18dd64e7074cc1e117a5f1eff20dcf/orjson-3.10.16-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f12970a26666a8775346003fd94347d03ccb98ab8aa063036818381acf5f523e", size = 138076 },
{ url = "https://files.pythonhosted.org/packages/db/2f/4cc151c4b471b0cdc8cb29d3eadbce5007eb0475d26fa26ed123dca93b33/orjson-3.10.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7946922ada8f3e0b7b958cc3eb22cfcf6c0df83d1fe5521b4a100103e3fa84c8", size = 130742 }, { url = "https://files.pythonhosted.org/packages/d7/59/d7fc7fbdd3d4a64c2eae4fc7341a5aa39cf9549bd5e2d7f6d3c07f8b715b/orjson-3.10.16-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15a1431a245d856bd56e4d29ea0023eb4d2c8f71efe914beb3dee8ab3f0cd7fb", size = 142643 },
{ url = "https://files.pythonhosted.org/packages/9f/13/8a6109e4b477c518498ca37963d9c0eb1508b259725553fb53d53b20e2ea/orjson-3.10.15-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b7155eb1623347f0f22c38c9abdd738b287e39b9982e1da227503387b81b34ca", size = 414669 }, { url = "https://files.pythonhosted.org/packages/92/0e/3bd8f2197d27601f16b4464ae948826da2bcf128af31230a9dbbad7ceb57/orjson-3.10.16-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c83655cfc247f399a222567d146524674a7b217af7ef8289c0ff53cfe8db09f0", size = 133168 },
{ url = "https://files.pythonhosted.org/packages/22/7b/1d229d6d24644ed4d0a803de1b0e2df832032d5beda7346831c78191b5b2/orjson-3.10.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:208beedfa807c922da4e81061dafa9c8489c6328934ca2a562efa707e049e561", size = 141043 }, { url = "https://files.pythonhosted.org/packages/af/a8/351fd87b664b02f899f9144d2c3dc848b33ac04a5df05234cbfb9e2a7540/orjson-3.10.16-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fa59ae64cb6ddde8f09bdbf7baf933c4cd05734ad84dcf4e43b887eb24e37652", size = 135271 },
{ url = "https://files.pythonhosted.org/packages/cc/d3/6dc91156cf12ed86bed383bcb942d84d23304a1e57b7ab030bf60ea130d6/orjson-3.10.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eca81f83b1b8c07449e1d6ff7074e82e3fd6777e588f1a6632127f286a968825", size = 129826 }, { url = "https://files.pythonhosted.org/packages/ba/b0/a6d42a7d412d867c60c0337d95123517dd5a9370deea705ea1be0f89389e/orjson-3.10.16-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ca5426e5aacc2e9507d341bc169d8af9c3cbe88f4cd4c1cf2f87e8564730eb56", size = 412444 },
{ url = "https://files.pythonhosted.org/packages/b3/38/c47c25b86f6996f1343be721b6ea4367bc1c8bc0fc3f6bbcd995d18cb19d/orjson-3.10.15-cp313-cp313-win32.whl", hash = "sha256:c03cd6eea1bd3b949d0d007c8d57049aa2b39bd49f58b4b2af571a5d3833d890", size = 142542 }, { url = "https://files.pythonhosted.org/packages/79/ec/7572cd4e20863f60996f3f10bc0a6da64a6fd9c35954189a914cec0b7377/orjson-3.10.16-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6fd5da4edf98a400946cd3a195680de56f1e7575109b9acb9493331047157430", size = 152737 },
{ url = "https://files.pythonhosted.org/packages/27/f1/1d7ec15b20f8ce9300bc850de1e059132b88990e46cd0ccac29cbf11e4f9/orjson-3.10.15-cp313-cp313-win_amd64.whl", hash = "sha256:fd56a26a04f6ba5fb2045b0acc487a63162a958ed837648c5781e1fe3316cfbf", size = 133444 }, { url = "https://files.pythonhosted.org/packages/a9/19/ceb9e8fed5403b2e76a8ac15f581b9d25780a3be3c9b3aa54b7777a210d5/orjson-3.10.16-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:980ecc7a53e567169282a5e0ff078393bac78320d44238da4e246d71a4e0e8f5", size = 137482 },
{ url = "https://files.pythonhosted.org/packages/1b/78/a78bb810f3786579dbbbd94768284cbe8f2fd65167cd7020260679665c17/orjson-3.10.16-cp313-cp313-win32.whl", hash = "sha256:28f79944dd006ac540a6465ebd5f8f45dfdf0948ff998eac7a908275b4c1add6", size = 141714 },
{ url = "https://files.pythonhosted.org/packages/81/9c/b66ce9245ff319df2c3278acd351a3f6145ef34b4a2d7f4b0f739368370f/orjson-3.10.16-cp313-cp313-win_amd64.whl", hash = "sha256:fe0a145e96d51971407cb8ba947e63ead2aa915db59d6631a355f5f2150b56b7", size = 133954 },
] ]
[[package]] [[package]]
@ -1787,91 +1789,104 @@ wheels = [
[[package]] [[package]]
name = "pydantic" name = "pydantic"
version = "2.10.6" version = "2.11.1"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "annotated-types" }, { name = "annotated-types" },
{ name = "pydantic-core" }, { name = "pydantic-core" },
{ name = "typing-extensions" }, { name = "typing-extensions" },
{ name = "typing-inspection" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/b7/ae/d5220c5c52b158b1de7ca89fc5edb72f304a70a4c540c84c8844bf4008de/pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236", size = 761681 } sdist = { url = "https://files.pythonhosted.org/packages/93/a3/698b87a4d4d303d7c5f62ea5fbf7a79cab236ccfbd0a17847b7f77f8163e/pydantic-2.11.1.tar.gz", hash = "sha256:442557d2910e75c991c39f4b4ab18963d57b9b55122c8b2a9cd176d8c29ce968", size = 782817 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", size = 431696 }, { url = "https://files.pythonhosted.org/packages/cc/12/f9221a949f2419e2e23847303c002476c26fbcfd62dc7f3d25d0bec5ca99/pydantic-2.11.1-py3-none-any.whl", hash = "sha256:5b6c415eee9f8123a14d859be0c84363fec6b1feb6b688d6435801230b56e0b8", size = 442648 },
] ]
[[package]] [[package]]
name = "pydantic-core" name = "pydantic-core"
version = "2.27.2" version = "2.33.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "typing-extensions" }, { name = "typing-extensions" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 } sdist = { url = "https://files.pythonhosted.org/packages/b9/05/91ce14dfd5a3a99555fce436318cc0fd1f08c4daa32b3248ad63669ea8b4/pydantic_core-2.33.0.tar.gz", hash = "sha256:40eb8af662ba409c3cbf4a8150ad32ae73514cd7cb1f1a2113af39763dd616b3", size = 434080 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/3a/bc/fed5f74b5d802cf9a03e83f60f18864e90e3aed7223adaca5ffb7a8d8d64/pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa", size = 1895938 }, { url = "https://files.pythonhosted.org/packages/29/43/0649ad07e66b36a3fb21442b425bd0348ac162c5e686b36471f363201535/pydantic_core-2.33.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:71dffba8fe9ddff628c68f3abd845e91b028361d43c5f8e7b3f8b91d7d85413e", size = 2042968 },
{ url = "https://files.pythonhosted.org/packages/71/2a/185aff24ce844e39abb8dd680f4e959f0006944f4a8a0ea372d9f9ae2e53/pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c", size = 1815684 }, { url = "https://files.pythonhosted.org/packages/a0/a6/975fea4774a459e495cb4be288efd8b041ac756a0a763f0b976d0861334b/pydantic_core-2.33.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:abaeec1be6ed535a5d7ffc2e6c390083c425832b20efd621562fbb5bff6dc518", size = 1860347 },
{ url = "https://files.pythonhosted.org/packages/c3/43/fafabd3d94d159d4f1ed62e383e264f146a17dd4d48453319fd782e7979e/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a", size = 1829169 }, { url = "https://files.pythonhosted.org/packages/aa/49/7858dadad305101a077ec4d0c606b6425a2b134ea8d858458a6d287fd871/pydantic_core-2.33.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:759871f00e26ad3709efc773ac37b4d571de065f9dfb1778012908bcc36b3a73", size = 1910060 },
{ url = "https://files.pythonhosted.org/packages/a2/d1/f2dfe1a2a637ce6800b799aa086d079998959f6f1215eb4497966efd2274/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5", size = 1867227 }, { url = "https://files.pythonhosted.org/packages/8d/4f/6522527911d9c5fe6d76b084d8b388d5c84b09d113247b39f91937500b34/pydantic_core-2.33.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dcfebee69cd5e1c0b76a17e17e347c84b00acebb8dd8edb22d4a03e88e82a207", size = 1997129 },
{ url = "https://files.pythonhosted.org/packages/7d/39/e06fcbcc1c785daa3160ccf6c1c38fea31f5754b756e34b65f74e99780b5/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c", size = 2037695 }, { url = "https://files.pythonhosted.org/packages/75/d0/06f396da053e3d73001ea4787e56b4d7132a87c0b5e2e15a041e808c35cd/pydantic_core-2.33.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b1262b912435a501fa04cd213720609e2cefa723a07c92017d18693e69bf00b", size = 2140389 },
{ url = "https://files.pythonhosted.org/packages/7a/67/61291ee98e07f0650eb756d44998214231f50751ba7e13f4f325d95249ab/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7", size = 2741662 }, { url = "https://files.pythonhosted.org/packages/f5/6b/b9ff5b69cd4ef007cf665463f3be2e481dc7eb26c4a55b2f57a94308c31a/pydantic_core-2.33.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4726f1f3f42d6a25678c67da3f0b10f148f5655813c5aca54b0d1742ba821b8f", size = 2754237 },
{ url = "https://files.pythonhosted.org/packages/32/90/3b15e31b88ca39e9e626630b4c4a1f5a0dfd09076366f4219429e6786076/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a", size = 1993370 }, { url = "https://files.pythonhosted.org/packages/53/80/b4879de375cdf3718d05fcb60c9aa1f119d28e261dafa51b6a69c78f7178/pydantic_core-2.33.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e790954b5093dff1e3a9a2523fddc4e79722d6f07993b4cd5547825c3cbf97b5", size = 2007433 },
{ url = "https://files.pythonhosted.org/packages/ff/83/c06d333ee3a67e2e13e07794995c1535565132940715931c1c43bfc85b11/pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236", size = 1996813 }, { url = "https://files.pythonhosted.org/packages/46/24/54054713dc0af98a94eab37e0f4294dfd5cd8f70b2ca9dcdccd15709fd7e/pydantic_core-2.33.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:34e7fb3abe375b5c4e64fab75733d605dda0f59827752debc99c17cb2d5f3276", size = 2123980 },
{ url = "https://files.pythonhosted.org/packages/7c/f7/89be1c8deb6e22618a74f0ca0d933fdcb8baa254753b26b25ad3acff8f74/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962", size = 2005287 }, { url = "https://files.pythonhosted.org/packages/3a/4c/257c1cb89e14cfa6e95ebcb91b308eb1dd2b348340ff76a6e6fcfa9969e1/pydantic_core-2.33.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ecb158fb9b9091b515213bed3061eb7deb1d3b4e02327c27a0ea714ff46b0760", size = 2087433 },
{ url = "https://files.pythonhosted.org/packages/b7/7d/8eb3e23206c00ef7feee17b83a4ffa0a623eb1a9d382e56e4aa46fd15ff2/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9", size = 2128414 }, { url = "https://files.pythonhosted.org/packages/0c/62/927df8a39ad78ef7b82c5446e01dec9bb0043e1ad71d8f426062f5f014db/pydantic_core-2.33.0-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:4d9149e7528af8bbd76cc055967e6e04617dcb2a2afdaa3dea899406c5521faa", size = 2260242 },
{ url = "https://files.pythonhosted.org/packages/4e/99/fe80f3ff8dd71a3ea15763878d464476e6cb0a2db95ff1c5c554133b6b83/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af", size = 2155301 }, { url = "https://files.pythonhosted.org/packages/74/f2/389414f7c77a100954e84d6f52a82bd1788ae69db72364376d8a73b38765/pydantic_core-2.33.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e81a295adccf73477220e15ff79235ca9dcbcee4be459eb9d4ce9a2763b8386c", size = 2258227 },
{ url = "https://files.pythonhosted.org/packages/2b/a3/e50460b9a5789ca1451b70d4f52546fa9e2b420ba3bfa6100105c0559238/pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4", size = 1816685 }, { url = "https://files.pythonhosted.org/packages/53/99/94516313e15d906a1264bb40faf24a01a4af4e2ca8a7c10dd173b6513c5a/pydantic_core-2.33.0-cp310-cp310-win32.whl", hash = "sha256:f22dab23cdbce2005f26a8f0c71698457861f97fc6318c75814a50c75e87d025", size = 1925523 },
{ url = "https://files.pythonhosted.org/packages/57/4c/a8838731cb0f2c2a39d3535376466de6049034d7b239c0202a64aaa05533/pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31", size = 1982876 }, { url = "https://files.pythonhosted.org/packages/7d/67/cc789611c6035a0b71305a1ec6ba196256ced76eba8375f316f840a70456/pydantic_core-2.33.0-cp310-cp310-win_amd64.whl", hash = "sha256:9cb2390355ba084c1ad49485d18449b4242da344dea3e0fe10babd1f0db7dcfc", size = 1951872 },
{ url = "https://files.pythonhosted.org/packages/c2/89/f3450af9d09d44eea1f2c369f49e8f181d742f28220f88cc4dfaae91ea6e/pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc", size = 1893421 }, { url = "https://files.pythonhosted.org/packages/f0/93/9e97af2619b4026596487a79133e425c7d3c374f0a7f100f3d76bcdf9c83/pydantic_core-2.33.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a608a75846804271cf9c83e40bbb4dab2ac614d33c6fd5b0c6187f53f5c593ef", size = 2042784 },
{ url = "https://files.pythonhosted.org/packages/9e/e3/71fe85af2021f3f386da42d291412e5baf6ce7716bd7101ea49c810eda90/pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7", size = 1814998 }, { url = "https://files.pythonhosted.org/packages/42/b4/0bba8412fd242729feeb80e7152e24f0e1a1c19f4121ca3d4a307f4e6222/pydantic_core-2.33.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e1c69aa459f5609dec2fa0652d495353accf3eda5bdb18782bc5a2ae45c9273a", size = 1858179 },
{ url = "https://files.pythonhosted.org/packages/a6/3c/724039e0d848fd69dbf5806894e26479577316c6f0f112bacaf67aa889ac/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15", size = 1826167 }, { url = "https://files.pythonhosted.org/packages/69/1f/c1c40305d929bd08af863df64b0a26203b70b352a1962d86f3bcd52950fe/pydantic_core-2.33.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9ec80eb5a5f45a2211793f1c4aeddff0c3761d1c70d684965c1807e923a588b", size = 1909396 },
{ url = "https://files.pythonhosted.org/packages/2b/5b/1b29e8c1fb5f3199a9a57c1452004ff39f494bbe9bdbe9a81e18172e40d3/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306", size = 1865071 }, { url = "https://files.pythonhosted.org/packages/0f/99/d2e727375c329c1e652b5d450fbb9d56e8c3933a397e4bd46e67c68c2cd5/pydantic_core-2.33.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e925819a98318d17251776bd3d6aa9f3ff77b965762155bdad15d1a9265c4cfd", size = 1998264 },
{ url = "https://files.pythonhosted.org/packages/89/6c/3985203863d76bb7d7266e36970d7e3b6385148c18a68cc8915fd8c84d57/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99", size = 2036244 }, { url = "https://files.pythonhosted.org/packages/9c/2e/3119a33931278d96ecc2e9e1b9d50c240636cfeb0c49951746ae34e4de74/pydantic_core-2.33.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5bf68bb859799e9cec3d9dd8323c40c00a254aabb56fe08f907e437005932f2b", size = 2140588 },
{ url = "https://files.pythonhosted.org/packages/0e/41/f15316858a246b5d723f7d7f599f79e37493b2e84bfc789e58d88c209f8a/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459", size = 2737470 }, { url = "https://files.pythonhosted.org/packages/35/bd/9267bd1ba55f17c80ef6cb7e07b3890b4acbe8eb6014f3102092d53d9300/pydantic_core-2.33.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1b2ea72dea0825949a045fa4071f6d5b3d7620d2a208335207793cf29c5a182d", size = 2746296 },
{ url = "https://files.pythonhosted.org/packages/a8/7c/b860618c25678bbd6d1d99dbdfdf0510ccb50790099b963ff78a124b754f/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048", size = 1992291 }, { url = "https://files.pythonhosted.org/packages/6f/ed/ef37de6478a412ee627cbebd73e7b72a680f45bfacce9ff1199de6e17e88/pydantic_core-2.33.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1583539533160186ac546b49f5cde9ffc928062c96920f58bd95de32ffd7bffd", size = 2005555 },
{ url = "https://files.pythonhosted.org/packages/bf/73/42c3742a391eccbeab39f15213ecda3104ae8682ba3c0c28069fbcb8c10d/pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d", size = 1994613 }, { url = "https://files.pythonhosted.org/packages/dd/84/72c8d1439585d8ee7bc35eb8f88a04a4d302ee4018871f1f85ae1b0c6625/pydantic_core-2.33.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:23c3e77bf8a7317612e5c26a3b084c7edeb9552d645742a54a5867635b4f2453", size = 2124452 },
{ url = "https://files.pythonhosted.org/packages/94/7a/941e89096d1175d56f59340f3a8ebaf20762fef222c298ea96d36a6328c5/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b", size = 2002355 }, { url = "https://files.pythonhosted.org/packages/a7/8f/cb13de30c6a3e303423751a529a3d1271c2effee4b98cf3e397a66ae8498/pydantic_core-2.33.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a7a7f2a3f628d2f7ef11cb6188bcf0b9e1558151d511b974dfea10a49afe192b", size = 2087001 },
{ url = "https://files.pythonhosted.org/packages/6e/95/2359937a73d49e336a5a19848713555605d4d8d6940c3ec6c6c0ca4dcf25/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474", size = 2126661 }, { url = "https://files.pythonhosted.org/packages/83/d0/e93dc8884bf288a63fedeb8040ac8f29cb71ca52e755f48e5170bb63e55b/pydantic_core-2.33.0-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:f1fb026c575e16f673c61c7b86144517705865173f3d0907040ac30c4f9f5915", size = 2261663 },
{ url = "https://files.pythonhosted.org/packages/2b/4c/ca02b7bdb6012a1adef21a50625b14f43ed4d11f1fc237f9d7490aa5078c/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6", size = 2153261 }, { url = "https://files.pythonhosted.org/packages/4c/ba/4b7739c95efa0b542ee45fd872c8f6b1884ab808cf04ce7ac6621b6df76e/pydantic_core-2.33.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:635702b2fed997e0ac256b2cfbdb4dd0bf7c56b5d8fba8ef03489c03b3eb40e2", size = 2257786 },
{ url = "https://files.pythonhosted.org/packages/72/9d/a241db83f973049a1092a079272ffe2e3e82e98561ef6214ab53fe53b1c7/pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", size = 1812361 }, { url = "https://files.pythonhosted.org/packages/cc/98/73cbca1d2360c27752cfa2fcdcf14d96230e92d7d48ecd50499865c56bf7/pydantic_core-2.33.0-cp311-cp311-win32.whl", hash = "sha256:07b4ced28fccae3f00626eaa0c4001aa9ec140a29501770a88dbbb0966019a86", size = 1925697 },
{ url = "https://files.pythonhosted.org/packages/e8/ef/013f07248041b74abd48a385e2110aa3a9bbfef0fbd97d4e6d07d2f5b89a/pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", size = 1982484 }, { url = "https://files.pythonhosted.org/packages/9a/26/d85a40edeca5d8830ffc33667d6fef329fd0f4bc0c5181b8b0e206cfe488/pydantic_core-2.33.0-cp311-cp311-win_amd64.whl", hash = "sha256:4927564be53239a87770a5f86bdc272b8d1fbb87ab7783ad70255b4ab01aa25b", size = 1949859 },
{ url = "https://files.pythonhosted.org/packages/10/1c/16b3a3e3398fd29dca77cea0a1d998d6bde3902fa2706985191e2313cc76/pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", size = 1867102 }, { url = "https://files.pythonhosted.org/packages/7e/0b/5a381605f0b9870465b805f2c86c06b0a7c191668ebe4117777306c2c1e5/pydantic_core-2.33.0-cp311-cp311-win_arm64.whl", hash = "sha256:69297418ad644d521ea3e1aa2e14a2a422726167e9ad22b89e8f1130d68e1e9a", size = 1907978 },
{ url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127 }, { url = "https://files.pythonhosted.org/packages/a9/c4/c9381323cbdc1bb26d352bc184422ce77c4bc2f2312b782761093a59fafc/pydantic_core-2.33.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6c32a40712e3662bebe524abe8abb757f2fa2000028d64cc5a1006016c06af43", size = 2025127 },
{ url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340 }, { url = "https://files.pythonhosted.org/packages/6f/bd/af35278080716ecab8f57e84515c7dc535ed95d1c7f52c1c6f7b313a9dab/pydantic_core-2.33.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ec86b5baa36f0a0bfb37db86c7d52652f8e8aa076ab745ef7725784183c3fdd", size = 1851687 },
{ url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900 }, { url = "https://files.pythonhosted.org/packages/12/e4/a01461225809c3533c23bd1916b1e8c2e21727f0fea60ab1acbffc4e2fca/pydantic_core-2.33.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4deac83a8cc1d09e40683be0bc6d1fa4cde8df0a9bf0cda5693f9b0569ac01b6", size = 1892232 },
{ url = "https://files.pythonhosted.org/packages/f6/31/4240bc96025035500c18adc149aa6ffdf1a0062a4b525c932065ceb4d868/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", size = 1869177 }, { url = "https://files.pythonhosted.org/packages/51/17/3d53d62a328fb0a49911c2962036b9e7a4f781b7d15e9093c26299e5f76d/pydantic_core-2.33.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:175ab598fb457a9aee63206a1993874badf3ed9a456e0654273e56f00747bbd6", size = 1977896 },
{ url = "https://files.pythonhosted.org/packages/fa/20/02fbaadb7808be578317015c462655c317a77a7c8f0ef274bc016a784c54/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", size = 2038046 }, { url = "https://files.pythonhosted.org/packages/30/98/01f9d86e02ec4a38f4b02086acf067f2c776b845d43f901bd1ee1c21bc4b/pydantic_core-2.33.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f36afd0d56a6c42cf4e8465b6441cf546ed69d3a4ec92724cc9c8c61bd6ecf4", size = 2127717 },
{ url = "https://files.pythonhosted.org/packages/06/86/7f306b904e6c9eccf0668248b3f272090e49c275bc488a7b88b0823444a4/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", size = 2685386 }, { url = "https://files.pythonhosted.org/packages/3c/43/6f381575c61b7c58b0fd0b92134c5a1897deea4cdfc3d47567b3ff460a4e/pydantic_core-2.33.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a98257451164666afafc7cbf5fb00d613e33f7e7ebb322fbcd99345695a9a61", size = 2680287 },
{ url = "https://files.pythonhosted.org/packages/8d/f0/49129b27c43396581a635d8710dae54a791b17dfc50c70164866bbf865e3/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", size = 1997060 }, { url = "https://files.pythonhosted.org/packages/01/42/c0d10d1451d161a9a0da9bbef023b8005aa26e9993a8cc24dc9e3aa96c93/pydantic_core-2.33.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecc6d02d69b54a2eb83ebcc6f29df04957f734bcf309d346b4f83354d8376862", size = 2008276 },
{ url = "https://files.pythonhosted.org/packages/0d/0f/943b4af7cd416c477fd40b187036c4f89b416a33d3cc0ab7b82708a667aa/pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", size = 2004870 }, { url = "https://files.pythonhosted.org/packages/20/ca/e08df9dba546905c70bae44ced9f3bea25432e34448d95618d41968f40b7/pydantic_core-2.33.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a69b7596c6603afd049ce7f3835bcf57dd3892fc7279f0ddf987bebed8caa5a", size = 2115305 },
{ url = "https://files.pythonhosted.org/packages/35/40/aea70b5b1a63911c53a4c8117c0a828d6790483f858041f47bab0b779f44/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", size = 1999822 }, { url = "https://files.pythonhosted.org/packages/03/1f/9b01d990730a98833113581a78e595fd40ed4c20f9693f5a658fb5f91eff/pydantic_core-2.33.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ea30239c148b6ef41364c6f51d103c2988965b643d62e10b233b5efdca8c0099", size = 2068999 },
{ url = "https://files.pythonhosted.org/packages/f2/b3/807b94fd337d58effc5498fd1a7a4d9d59af4133e83e32ae39a96fddec9d/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", size = 2130364 }, { url = "https://files.pythonhosted.org/packages/20/18/fe752476a709191148e8b1e1139147841ea5d2b22adcde6ee6abb6c8e7cf/pydantic_core-2.33.0-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:abfa44cf2f7f7d7a199be6c6ec141c9024063205545aa09304349781b9a125e6", size = 2241488 },
{ url = "https://files.pythonhosted.org/packages/fc/df/791c827cd4ee6efd59248dca9369fb35e80a9484462c33c6649a8d02b565/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", size = 2158303 }, { url = "https://files.pythonhosted.org/packages/81/22/14738ad0a0bf484b928c9e52004f5e0b81dd8dabbdf23b843717b37a71d1/pydantic_core-2.33.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:20d4275f3c4659d92048c70797e5fdc396c6e4446caf517ba5cad2db60cd39d3", size = 2248430 },
{ url = "https://files.pythonhosted.org/packages/9b/67/4e197c300976af185b7cef4c02203e175fb127e414125916bf1128b639a9/pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", size = 1834064 }, { url = "https://files.pythonhosted.org/packages/e8/27/be7571e215ac8d321712f2433c445b03dbcd645366a18f67b334df8912bc/pydantic_core-2.33.0-cp312-cp312-win32.whl", hash = "sha256:918f2013d7eadea1d88d1a35fd4a1e16aaf90343eb446f91cb091ce7f9b431a2", size = 1908353 },
{ url = "https://files.pythonhosted.org/packages/1f/ea/cd7209a889163b8dcca139fe32b9687dd05249161a3edda62860430457a5/pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", size = 1989046 }, { url = "https://files.pythonhosted.org/packages/be/3a/be78f28732f93128bd0e3944bdd4b3970b389a1fbd44907c97291c8dcdec/pydantic_core-2.33.0-cp312-cp312-win_amd64.whl", hash = "sha256:aec79acc183865bad120b0190afac467c20b15289050648b876b07777e67ea48", size = 1955956 },
{ url = "https://files.pythonhosted.org/packages/bc/49/c54baab2f4658c26ac633d798dab66b4c3a9bbf47cff5284e9c182f4137a/pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", size = 1885092 }, { url = "https://files.pythonhosted.org/packages/21/26/b8911ac74faa994694b76ee6a22875cc7a4abea3c381fdba4edc6c6bef84/pydantic_core-2.33.0-cp312-cp312-win_arm64.whl", hash = "sha256:5461934e895968655225dfa8b3be79e7e927e95d4bd6c2d40edd2fa7052e71b6", size = 1903259 },
{ url = "https://files.pythonhosted.org/packages/41/b1/9bc383f48f8002f99104e3acff6cba1231b29ef76cfa45d1506a5cad1f84/pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", size = 1892709 }, { url = "https://files.pythonhosted.org/packages/79/20/de2ad03ce8f5b3accf2196ea9b44f31b0cd16ac6e8cfc6b21976ed45ec35/pydantic_core-2.33.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f00e8b59e1fc8f09d05594aa7d2b726f1b277ca6155fc84c0396db1b373c4555", size = 2032214 },
{ url = "https://files.pythonhosted.org/packages/10/6c/e62b8657b834f3eb2961b49ec8e301eb99946245e70bf42c8817350cbefc/pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", size = 1811273 }, { url = "https://files.pythonhosted.org/packages/f9/af/6817dfda9aac4958d8b516cbb94af507eb171c997ea66453d4d162ae8948/pydantic_core-2.33.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a73be93ecef45786d7d95b0c5e9b294faf35629d03d5b145b09b81258c7cd6d", size = 1852338 },
{ url = "https://files.pythonhosted.org/packages/ba/15/52cfe49c8c986e081b863b102d6b859d9defc63446b642ccbbb3742bf371/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", size = 1823027 }, { url = "https://files.pythonhosted.org/packages/44/f3/49193a312d9c49314f2b953fb55740b7c530710977cabe7183b8ef111b7f/pydantic_core-2.33.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff48a55be9da6930254565ff5238d71d5e9cd8c5487a191cb85df3bdb8c77365", size = 1896913 },
{ url = "https://files.pythonhosted.org/packages/b1/1c/b6f402cfc18ec0024120602bdbcebc7bdd5b856528c013bd4d13865ca473/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", size = 1868888 }, { url = "https://files.pythonhosted.org/packages/06/e0/c746677825b2e29a2fa02122a8991c83cdd5b4c5f638f0664d4e35edd4b2/pydantic_core-2.33.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a4ea04195638dcd8c53dadb545d70badba51735b1594810e9768c2c0b4a5da", size = 1986046 },
{ url = "https://files.pythonhosted.org/packages/bd/7b/8cb75b66ac37bc2975a3b7de99f3c6f355fcc4d89820b61dffa8f1e81677/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", size = 2037738 }, { url = "https://files.pythonhosted.org/packages/11/ec/44914e7ff78cef16afb5e5273d480c136725acd73d894affdbe2a1bbaad5/pydantic_core-2.33.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41d698dcbe12b60661f0632b543dbb119e6ba088103b364ff65e951610cb7ce0", size = 2128097 },
{ url = "https://files.pythonhosted.org/packages/c8/f1/786d8fe78970a06f61df22cba58e365ce304bf9b9f46cc71c8c424e0c334/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", size = 2685138 }, { url = "https://files.pythonhosted.org/packages/fe/f5/c6247d424d01f605ed2e3802f338691cae17137cee6484dce9f1ac0b872b/pydantic_core-2.33.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae62032ef513fe6281ef0009e30838a01057b832dc265da32c10469622613885", size = 2681062 },
{ url = "https://files.pythonhosted.org/packages/a6/74/d12b2cd841d8724dc8ffb13fc5cef86566a53ed358103150209ecd5d1999/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", size = 1997025 }, { url = "https://files.pythonhosted.org/packages/f0/85/114a2113b126fdd7cf9a9443b1b1fe1b572e5bd259d50ba9d5d3e1927fa9/pydantic_core-2.33.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f225f3a3995dbbc26affc191d0443c6c4aa71b83358fd4c2b7d63e2f6f0336f9", size = 2007487 },
{ url = "https://files.pythonhosted.org/packages/a0/6e/940bcd631bc4d9a06c9539b51f070b66e8f370ed0933f392db6ff350d873/pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", size = 2004633 }, { url = "https://files.pythonhosted.org/packages/e6/40/3c05ed28d225c7a9acd2b34c5c8010c279683a870219b97e9f164a5a8af0/pydantic_core-2.33.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5bdd36b362f419c78d09630cbaebc64913f66f62bda6d42d5fbb08da8cc4f181", size = 2121382 },
{ url = "https://files.pythonhosted.org/packages/50/cc/a46b34f1708d82498c227d5d80ce615b2dd502ddcfd8376fc14a36655af1/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", size = 1999404 }, { url = "https://files.pythonhosted.org/packages/8a/22/e70c086f41eebd323e6baa92cc906c3f38ddce7486007eb2bdb3b11c8f64/pydantic_core-2.33.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:2a0147c0bef783fd9abc9f016d66edb6cac466dc54a17ec5f5ada08ff65caf5d", size = 2072473 },
{ url = "https://files.pythonhosted.org/packages/ca/2d/c365cfa930ed23bc58c41463bae347d1005537dc8db79e998af8ba28d35e/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", size = 2130130 }, { url = "https://files.pythonhosted.org/packages/3e/84/d1614dedd8fe5114f6a0e348bcd1535f97d76c038d6102f271433cd1361d/pydantic_core-2.33.0-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:c860773a0f205926172c6644c394e02c25421dc9a456deff16f64c0e299487d3", size = 2249468 },
{ url = "https://files.pythonhosted.org/packages/f4/d7/eb64d015c350b7cdb371145b54d96c919d4db516817f31cd1c650cae3b21/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", size = 2157946 }, { url = "https://files.pythonhosted.org/packages/b0/c0/787061eef44135e00fddb4b56b387a06c303bfd3884a6df9bea5cb730230/pydantic_core-2.33.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:138d31e3f90087f42aa6286fb640f3c7a8eb7bdae829418265e7e7474bd2574b", size = 2254716 },
{ url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 }, { url = "https://files.pythonhosted.org/packages/ae/e2/27262eb04963201e89f9c280f1e10c493a7a37bc877e023f31aa72d2f911/pydantic_core-2.33.0-cp313-cp313-win32.whl", hash = "sha256:d20cbb9d3e95114325780f3cfe990f3ecae24de7a2d75f978783878cce2ad585", size = 1916450 },
{ url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 }, { url = "https://files.pythonhosted.org/packages/13/8d/25ff96f1e89b19e0b70b3cd607c9ea7ca27e1dcb810a9cd4255ed6abf869/pydantic_core-2.33.0-cp313-cp313-win_amd64.whl", hash = "sha256:ca1103d70306489e3d006b0f79db8ca5dd3c977f6f13b2c59ff745249431a606", size = 1956092 },
{ url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 }, { url = "https://files.pythonhosted.org/packages/1b/64/66a2efeff657b04323ffcd7b898cb0354d36dae3a561049e092134a83e9c/pydantic_core-2.33.0-cp313-cp313-win_arm64.whl", hash = "sha256:6291797cad239285275558e0a27872da735b05c75d5237bbade8736f80e4c225", size = 1908367 },
{ url = "https://files.pythonhosted.org/packages/46/72/af70981a341500419e67d5cb45abe552a7c74b66326ac8877588488da1ac/pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e", size = 1891159 }, { url = "https://files.pythonhosted.org/packages/52/54/295e38769133363d7ec4a5863a4d579f331728c71a6644ff1024ee529315/pydantic_core-2.33.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7b79af799630af263eca9ec87db519426d8c9b3be35016eddad1832bac812d87", size = 1813331 },
{ url = "https://files.pythonhosted.org/packages/ad/3d/c5913cccdef93e0a6a95c2d057d2c2cba347815c845cda79ddd3c0f5e17d/pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8", size = 1768331 }, { url = "https://files.pythonhosted.org/packages/4c/9c/0c8ea02db8d682aa1ef48938abae833c1d69bdfa6e5ec13b21734b01ae70/pydantic_core-2.33.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eabf946a4739b5237f4f56d77fa6668263bc466d06a8036c055587c130a46f7b", size = 1986653 },
{ url = "https://files.pythonhosted.org/packages/f6/f0/a3ae8fbee269e4934f14e2e0e00928f9346c5943174f2811193113e58252/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3", size = 1822467 }, { url = "https://files.pythonhosted.org/packages/8e/4f/3fb47d6cbc08c7e00f92300e64ba655428c05c56b8ab6723bd290bae6458/pydantic_core-2.33.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8a1d581e8cdbb857b0e0e81df98603376c1a5c34dc5e54039dcc00f043df81e7", size = 1931234 },
{ url = "https://files.pythonhosted.org/packages/d7/7a/7bbf241a04e9f9ea24cd5874354a83526d639b02674648af3f350554276c/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f", size = 1979797 }, { url = "https://files.pythonhosted.org/packages/44/77/85e173b715e1a277ce934f28d877d82492df13e564fa68a01c96f36a47ad/pydantic_core-2.33.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e2762c568596332fdab56b07060c8ab8362c56cf2a339ee54e491cd503612c50", size = 2040129 },
{ url = "https://files.pythonhosted.org/packages/4f/5f/4784c6107731f89e0005a92ecb8a2efeafdb55eb992b8e9d0a2be5199335/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133", size = 1987839 }, { url = "https://files.pythonhosted.org/packages/33/e7/33da5f8a94bbe2191cfcd15bd6d16ecd113e67da1b8c78d3cc3478112dab/pydantic_core-2.33.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5bf637300ff35d4f59c006fff201c510b2b5e745b07125458a5389af3c0dff8c", size = 1872656 },
{ url = "https://files.pythonhosted.org/packages/6d/a7/61246562b651dff00de86a5f01b6e4befb518df314c54dec187a78d81c84/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc", size = 1998861 }, { url = "https://files.pythonhosted.org/packages/b4/7a/9600f222bea840e5b9ba1f17c0acc79b669b24542a78c42c6a10712c0aae/pydantic_core-2.33.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c151ce3d59ed56ebd7ce9ce5986a409a85db697d25fc232f8e81f195aa39a1", size = 1903731 },
{ url = "https://files.pythonhosted.org/packages/86/aa/837821ecf0c022bbb74ca132e117c358321e72e7f9702d1b6a03758545e2/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50", size = 2116582 }, { url = "https://files.pythonhosted.org/packages/81/d2/94c7ca4e24c5dcfb74df92e0836c189e9eb6814cf62d2f26a75ea0a906db/pydantic_core-2.33.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ee65f0cc652261744fd07f2c6e6901c914aa6c5ff4dcfaf1136bc394d0dd26b", size = 2083966 },
{ url = "https://files.pythonhosted.org/packages/81/b0/5e74656e95623cbaa0a6278d16cf15e10a51f6002e3ec126541e95c29ea3/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9", size = 2151985 }, { url = "https://files.pythonhosted.org/packages/b8/74/a0259989d220e8865ed6866a6d40539e40fa8f507e587e35d2414cc081f8/pydantic_core-2.33.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:024d136ae44d233e6322027bbf356712b3940bee816e6c948ce4b90f18471b3d", size = 2118951 },
{ url = "https://files.pythonhosted.org/packages/63/37/3e32eeb2a451fddaa3898e2163746b0cffbbdbb4740d38372db0490d67f3/pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151", size = 2004715 }, { url = "https://files.pythonhosted.org/packages/13/4c/87405ed04d6d07597920b657f082a8e8e58bf3034178bb9044b4d57a91e2/pydantic_core-2.33.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e37f10f6d4bc67c58fbd727108ae1d8b92b397355e68519f1e4a7babb1473442", size = 2079632 },
{ url = "https://files.pythonhosted.org/packages/5a/4c/bcb02970ef91d4cd6de7c6893101302637da456bc8b52c18ea0d047b55ce/pydantic_core-2.33.0-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:502ed542e0d958bd12e7c3e9a015bce57deaf50eaa8c2e1c439b512cb9db1e3a", size = 2250541 },
{ url = "https://files.pythonhosted.org/packages/a3/2b/dbe5450c4cd904be5da736dcc7f2357b828199e29e38de19fc81f988b288/pydantic_core-2.33.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:715c62af74c236bf386825c0fdfa08d092ab0f191eb5b4580d11c3189af9d330", size = 2255685 },
{ url = "https://files.pythonhosted.org/packages/ca/a6/ca1d35f695d81f639c5617fc9efb44caad21a9463383fa45364b3044175a/pydantic_core-2.33.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bccc06fa0372151f37f6b69834181aa9eb57cf8665ed36405fb45fbf6cac3bae", size = 2082395 },
{ url = "https://files.pythonhosted.org/packages/2b/b2/553e42762e7b08771fca41c0230c1ac276f9e79e78f57628e1b7d328551d/pydantic_core-2.33.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5d8dc9f63a26f7259b57f46a7aab5af86b2ad6fbe48487500bb1f4b27e051e4c", size = 2041207 },
{ url = "https://files.pythonhosted.org/packages/85/81/a91a57bbf3efe53525ab75f65944b8950e6ef84fe3b9a26c1ec173363263/pydantic_core-2.33.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:30369e54d6d0113d2aa5aee7a90d17f225c13d87902ace8fcd7bbf99b19124db", size = 1873736 },
{ url = "https://files.pythonhosted.org/packages/9c/d2/5ab52e9f551cdcbc1ee99a0b3ef595f56d031f66f88e5ca6726c49f9ce65/pydantic_core-2.33.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3eb479354c62067afa62f53bb387827bee2f75c9c79ef25eef6ab84d4b1ae3b", size = 1903794 },
{ url = "https://files.pythonhosted.org/packages/2f/5f/a81742d3f3821b16f1265f057d6e0b68a3ab13a814fe4bffac536a1f26fd/pydantic_core-2.33.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0310524c833d91403c960b8a3cf9f46c282eadd6afd276c8c5edc617bd705dc9", size = 2083457 },
{ url = "https://files.pythonhosted.org/packages/b5/2f/e872005bc0fc47f9c036b67b12349a8522d32e3bda928e82d676e2a594d1/pydantic_core-2.33.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eddb18a00bbb855325db27b4c2a89a4ba491cd6a0bd6d852b225172a1f54b36c", size = 2119537 },
{ url = "https://files.pythonhosted.org/packages/d3/13/183f13ce647202eaf3dada9e42cdfc59cbb95faedd44d25f22b931115c7f/pydantic_core-2.33.0-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:ade5dbcf8d9ef8f4b28e682d0b29f3008df9842bb5ac48ac2c17bc55771cc976", size = 2080069 },
{ url = "https://files.pythonhosted.org/packages/23/8b/b6be91243da44a26558d9c3a9007043b3750334136c6550551e8092d6d96/pydantic_core-2.33.0-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:2c0afd34f928383e3fd25740f2050dbac9d077e7ba5adbaa2227f4d4f3c8da5c", size = 2251618 },
{ url = "https://files.pythonhosted.org/packages/aa/c5/fbcf1977035b834f63eb542e74cd6c807177f383386175b468f0865bcac4/pydantic_core-2.33.0-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7da333f21cd9df51d5731513a6d39319892947604924ddf2e24a4612975fb936", size = 2255374 },
{ url = "https://files.pythonhosted.org/packages/2f/f8/66f328e411f1c9574b13c2c28ab01f308b53688bbbe6ca8fb981e6cabc42/pydantic_core-2.33.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:4b6d77c75a57f041c5ee915ff0b0bb58eabb78728b69ed967bc5b780e8f701b8", size = 2082099 },
] ]
[[package]] [[package]]
@ -1933,14 +1948,14 @@ wheels = [
[[package]] [[package]]
name = "pytest-asyncio" name = "pytest-asyncio"
version = "0.25.3" version = "0.26.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "pytest" }, { name = "pytest" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/f2/a8/ecbc8ede70921dd2f544ab1cadd3ff3bf842af27f87bbdea774c7baa1d38/pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a", size = 54239 } sdist = { url = "https://files.pythonhosted.org/packages/8e/c4/453c52c659521066969523e87d85d54139bbd17b78f09532fb8eb8cdb58e/pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f", size = 54156 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/67/17/3493c5624e48fd97156ebaec380dcaafee9506d7e2c46218ceebbb57d7de/pytest_asyncio-0.25.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3", size = 19467 }, { url = "https://files.pythonhosted.org/packages/20/7f/338843f449ace853647ace35870874f69a764d251872ed1b4de9f234822c/pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0", size = 19694 },
] ]
[[package]] [[package]]
@ -2444,23 +2459,23 @@ wheels = [
[[package]] [[package]]
name = "types-pyyaml" name = "types-pyyaml"
version = "6.0.12.20241230" version = "6.0.12.20250402"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/9a/f9/4d566925bcf9396136c0a2e5dc7e230ff08d86fa011a69888dd184469d80/types_pyyaml-6.0.12.20241230.tar.gz", hash = "sha256:7f07622dbd34bb9c8b264fe860a17e0efcad00d50b5f27e93984909d9363498c", size = 17078 } sdist = { url = "https://files.pythonhosted.org/packages/2d/68/609eed7402f87c9874af39d35942744e39646d1ea9011765ec87b01b2a3c/types_pyyaml-6.0.12.20250402.tar.gz", hash = "sha256:d7c13c3e6d335b6af4b0122a01ff1d270aba84ab96d1a1a1063ecba3e13ec075", size = 17282 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/e8/c1/48474fbead512b70ccdb4f81ba5eb4a58f69d100ba19f17c92c0c4f50ae6/types_PyYAML-6.0.12.20241230-py3-none-any.whl", hash = "sha256:fa4d32565219b68e6dee5f67534c722e53c00d1cfc09c435ef04d7353e1e96e6", size = 20029 }, { url = "https://files.pythonhosted.org/packages/ed/56/1fe61db05685fbb512c07ea9323f06ea727125951f1eb4dff110b3311da3/types_pyyaml-6.0.12.20250402-py3-none-any.whl", hash = "sha256:652348fa9e7a203d4b0d21066dfb00760d3cbd5a15ebb7cf8d33c88a49546681", size = 20329 },
] ]
[[package]] [[package]]
name = "types-requests" name = "types-requests"
version = "2.32.0.20250306" version = "2.32.0.20250328"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "urllib3" }, { name = "urllib3" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/09/1a/beaeff79ef9efd186566ba5f0d95b44ae21f6d31e9413bcfbef3489b6ae3/types_requests-2.32.0.20250306.tar.gz", hash = "sha256:0962352694ec5b2f95fda877ee60a159abdf84a0fc6fdace599f20acb41a03d1", size = 23012 } sdist = { url = "https://files.pythonhosted.org/packages/00/7d/eb174f74e3f5634eaacb38031bbe467dfe2e545bc255e5c90096ec46bc46/types_requests-2.32.0.20250328.tar.gz", hash = "sha256:c9e67228ea103bd811c96984fac36ed2ae8da87a36a633964a21f199d60baf32", size = 22995 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/99/26/645d89f56004aa0ba3b96fec27793e3c7e62b40982ee069e52568922b6db/types_requests-2.32.0.20250306-py3-none-any.whl", hash = "sha256:25f2cbb5c8710b2022f8bbee7b2b66f319ef14aeea2f35d80f18c9dbf3b60a0b", size = 20673 }, { url = "https://files.pythonhosted.org/packages/cc/15/3700282a9d4ea3b37044264d3e4d1b1f0095a4ebf860a99914fd544e3be3/types_requests-2.32.0.20250328-py3-none-any.whl", hash = "sha256:72ff80f84b15eb3aa7a8e2625fffb6a93f2ad5a0c20215fc1dcfa61117bcb2a2", size = 20663 },
] ]
[[package]] [[package]]
@ -2477,20 +2492,20 @@ wheels = [
[[package]] [[package]]
name = "types-simplejson" name = "types-simplejson"
version = "3.20.0.20250318" version = "3.20.0.20250326"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b7/bb/c19c0863ce03b950a2e6319e668a3e3f51c977368d6a1da529893e794162/types_simplejson-3.20.0.20250318.tar.gz", hash = "sha256:5ada2caa2f76826a90b97985f7b0caf55088a23ed4eb9c39fc1f5cb00b985e09", size = 9966 } sdist = { url = "https://files.pythonhosted.org/packages/af/14/e26fc55e1ea56f9ea470917d3e2f8240e6d043ca914181021d04115ae0f7/types_simplejson-3.20.0.20250326.tar.gz", hash = "sha256:b2689bc91e0e672d7a5a947b4cb546b76ae7ddc2899c6678e72a10bf96cd97d2", size = 10489 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/02/5a/adb04301014b18324ec88d5fcfe0ffc262ffc68c443cfe79e32b6cc68a35/types_simplejson-3.20.0.20250318-py3-none-any.whl", hash = "sha256:e8c9cdb06b566b6ca1c7bf3d4c97fbd69a6f6a5aea760ef127f31e638a094c26", size = 10336 }, { url = "https://files.pythonhosted.org/packages/76/bf/d3f3a5ba47fd18115e8446d39f025b85905d2008677c29ee4d03b4cddd57/types_simplejson-3.20.0.20250326-py3-none-any.whl", hash = "sha256:db1ddea7b8f7623b27a137578f22fc6c618db8c83ccfb1828ca0d2f0ec11efa7", size = 10462 },
] ]
[[package]] [[package]]
name = "types-ujson" name = "types-ujson"
version = "5.10.0.20240515" version = "5.10.0.20250326"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/12/49/abb4bcb9f2258f785edbf236b517c3e7ba8a503a8cbce6b5895930586cc0/types-ujson-5.10.0.20240515.tar.gz", hash = "sha256:ceae7127f0dafe4af5dd0ecf98ee13e9d75951ef963b5c5a9b7ea92e0d71f0d7", size = 3571 } sdist = { url = "https://files.pythonhosted.org/packages/cc/5c/c974451c4babdb4ae3588925487edde492d59a8403010b4642a554d09954/types_ujson-5.10.0.20250326.tar.gz", hash = "sha256:5469e05f2c31ecb3c4c0267cc8fe41bcd116826fbb4ded69801a645c687dd014", size = 8340 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/3f/1f/9d018cee3d09ab44a5211f0b5ed9b0422ad9a8c226bf3967f5884498d8f0/types_ujson-5.10.0.20240515-py3-none-any.whl", hash = "sha256:02bafc36b3a93d2511757a64ff88bd505e0a57fba08183a9150fbcfcb2015310", size = 2757 }, { url = "https://files.pythonhosted.org/packages/3e/c9/8a73a5f8fa6e70fc02eed506d5ac0ae9ceafbd2b8c9ad34a7de0f29900d6/types_ujson-5.10.0.20250326-py3-none-any.whl", hash = "sha256:acc0913f569def62ef6a892c8a47703f65d05669a3252391a97765cf207dca5b", size = 7644 },
] ]
[[package]] [[package]]
@ -2502,6 +2517,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
] ]
[[package]]
name = "typing-inspection"
version = "0.4.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125 },
]
[[package]] [[package]]
name = "urllib3" name = "urllib3"
version = "2.1.0" version = "2.1.0"

View File

@ -36,6 +36,8 @@ analyzer:
exclude: exclude:
- openapi/** - openapi/**
- lib/generated_plugin_registrant.dart - lib/generated_plugin_registrant.dart
- lib/**/*.g.dart
- lib/**/*.drift.dart
plugins: plugins:
- custom_lint - custom_lint

View File

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

24
mobile/build.yaml Normal file
View File

@ -0,0 +1,24 @@
targets:
$default:
builders:
#drift @DriftDatabase()
drift_dev:
# Disable default builder to use modular builder instead
enabled: false
drift_dev:analyzer:
enabled: true
options: &drift_options
store_date_time_values_as_text: true
named_parameters: true
write_from_json_string_constructor: false
data_class_to_companions: false
# Required for make-migrations
databases:
main: lib/infrastructure/repositories/db.repository.dart
generate_for: &drift_generate_for
- lib/infrastructure/entities/*.dart
- lib/infrastructure/repositories/db.repository.dart
drift_dev:modular:
enabled: true
options: *drift_options
generate_for: *drift_generate_for

View File

@ -0,0 +1 @@
{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":true},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"user_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_admin","getter_name":"isAdmin","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_admin\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_admin\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"email","getter_name":"email","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"profile_image_path","getter_name":"profileImagePath","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"quota_size_in_bytes","getter_name":"quotaSizeInBytes","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"quota_usage_in_bytes","getter_name":"quotaUsageInBytes","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":1,"references":[0],"type":"table","data":{"name":"user_metadata_entity","was_declared_in_moor":false,"columns":[{"name":"user_id","getter_name":"userId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"preferences","getter_name":"preferences","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"userPreferenceConverter","dart_type_name":"UserPreferences"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["user_id"]}},{"id":2,"references":[0],"type":"table","data":{"name":"partner_entity","was_declared_in_moor":false,"columns":[{"name":"shared_by_id","getter_name":"sharedById","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"shared_with_id","getter_name":"sharedWithId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"in_timeline","getter_name":"inTimeline","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"in_timeline\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"in_timeline\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["shared_by_id","shared_with_id"]}}]}

View File

@ -201,41 +201,41 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/wakelock_plus/ios" :path: ".symlinks/plugins/wakelock_plus/ios"
SPEC CHECKSUMS: SPEC CHECKSUMS:
background_downloader: 3ca0e156ad83a9fc1c8300f5f7c38e94e2d0bf51 background_downloader: b42a56120f5348bff70e74222f0e9e6f7f1a1537
connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342 device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49 file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086 flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100
flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29 flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
flutter_udid: b2417673f287ee62817a1de3d1643f47b9f508ab flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
flutter_web_auth_2: 06d500582775790a0d4c323222fcb6d7990f9603 flutter_web_auth_2: 5c8d9dcd7848b5a9efb086d24e7a9adcae979c80
fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
geolocator_apple: 9bcea1918ff7f0062d98345d238ae12718acfbc1 geolocator_apple: 1560c3c875af2a412242c7a923e15d0d401966ff
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573 integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
isar_flutter_libs: fdf730ca925d05687f36d7f1d355e482529ed097 isar_flutter_libs: bc909e72c3d756c2759f14c8776c13b5b0556e26
MapLibre: 0ebfa9329d313cec8bf0a5ba5a336a1dc903785e MapLibre: 0ebfa9329d313cec8bf0a5ba5a336a1dc903785e
maplibre_gl: be7b98f1c3ed75bf77f321eec04df359d0ff6f62 maplibre_gl: eab61cca6e1cfa9187249bacd3f08b51e8cd8ae9
native_video_player: d12af78a1a4a8cf09775a5177d5b392def6fd23c native_video_player: b65c58951ede2f93d103a25366bdebca95081265
network_info_plus: 6613d9d7cdeb0e6f366ed4dbe4b3c51c52d567a9 network_info_plus: cf61925ab5205dce05a4f0895989afdb6aade5fc
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
photo_manager: ff695c7a1dd5bc379974953a2b5c0a293f7c4c8a photo_manager: d2fbcc0f2d82458700ee6256a15018210a81d413
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868 SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
share_handler_ios: 6dd3a4ac5ca0d955274aec712ba0ecdcaf583e7c share_handler_ios: e2244e990f826b2c8eaa291ac3831569438ba0fb
share_handler_ios_models: fc638c9b4330dc7f082586c92aee9dfa0b87b871 share_handler_ios_models: fc638c9b4330dc7f082586c92aee9dfa0b87b871
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56 wakelock_plus: 04623e3f525556020ebd4034310f20fe7fda8b49
PODFILE CHECKSUM: 03b7eead4ee77b9e778179eeb0f3b5513617451c PODFILE CHECKSUM: 03b7eead4ee77b9e778179eeb0f3b5513617451c
COCOAPODS: 1.15.2 COCOAPODS: 1.16.2

View File

@ -541,7 +541,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 199; CURRENT_PROJECT_VERSION = 200;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@ -685,7 +685,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 199; CURRENT_PROJECT_VERSION = 200;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@ -715,7 +715,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 199; CURRENT_PROJECT_VERSION = 200;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@ -748,7 +748,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 199; CURRENT_PROJECT_VERSION = 200;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
@ -791,7 +791,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 199; CURRENT_PROJECT_VERSION = 200;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
@ -831,7 +831,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 199; CURRENT_PROJECT_VERSION = 200;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;

View File

@ -78,7 +78,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.130.3</string> <string>1.131.0</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>
@ -93,7 +93,7 @@
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>199</string> <string>200</string>
<key>FLTEnableImpeller</key> <key>FLTEnableImpeller</key>
<true/> <true/>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>

View File

@ -19,7 +19,7 @@ platform :ios do
desc "iOS Release" desc "iOS Release"
lane :release do lane :release do
increment_version_number( increment_version_number(
version_number: "1.130.3" version_number: "1.131.3"
) )
increment_build_number( increment_build_number(
build_number: latest_testflight_build_number + 1, build_number: latest_testflight_build_number + 1,

View File

@ -1,32 +1,4 @@
import 'dart:ui'; import 'package:immich_mobile/domain/models/user_metadata.model.dart';
enum AvatarColor {
// do not change this order or reuse indices for other purposes, adding is OK
primary,
pink,
red,
yellow,
blue,
green,
purple,
orange,
gray,
amber;
Color toColor({bool isDarkTheme = false}) => switch (this) {
AvatarColor.primary =>
isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF),
AvatarColor.pink => const Color.fromARGB(255, 244, 114, 182),
AvatarColor.red => const Color.fromARGB(255, 239, 68, 68),
AvatarColor.yellow => const Color.fromARGB(255, 234, 179, 8),
AvatarColor.blue => const Color.fromARGB(255, 59, 130, 246),
AvatarColor.green => const Color.fromARGB(255, 22, 163, 74),
AvatarColor.purple => const Color.fromARGB(255, 147, 51, 234),
AvatarColor.orange => const Color.fromARGB(255, 234, 88, 12),
AvatarColor.gray => const Color.fromARGB(255, 75, 85, 99),
AvatarColor.amber => const Color.fromARGB(255, 217, 119, 6),
};
}
// TODO: Rename to User once Isar is removed // TODO: Rename to User once Isar is removed
class UserDto { class UserDto {

View File

@ -0,0 +1,105 @@
import 'dart:ui';
enum AvatarColor {
// do not change this order or reuse indices for other purposes, adding is OK
primary("primary"),
pink("pink"),
red("red"),
yellow("yellow"),
blue("blue"),
green("green"),
purple("purple"),
orange("orange"),
gray("gray"),
amber("amber");
final String value;
const AvatarColor(this.value);
Color toColor({bool isDarkTheme = false}) => switch (this) {
AvatarColor.primary =>
isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF),
AvatarColor.pink => const Color.fromARGB(255, 244, 114, 182),
AvatarColor.red => const Color.fromARGB(255, 239, 68, 68),
AvatarColor.yellow => const Color.fromARGB(255, 234, 179, 8),
AvatarColor.blue => const Color.fromARGB(255, 59, 130, 246),
AvatarColor.green => const Color.fromARGB(255, 22, 163, 74),
AvatarColor.purple => const Color.fromARGB(255, 147, 51, 234),
AvatarColor.orange => const Color.fromARGB(255, 234, 88, 12),
AvatarColor.gray => const Color.fromARGB(255, 75, 85, 99),
AvatarColor.amber => const Color.fromARGB(255, 217, 119, 6),
};
}
class UserPreferences {
final bool foldersEnabled;
final bool memoriesEnabled;
final bool peopleEnabled;
final bool ratingsEnabled;
final bool sharedLinksEnabled;
final bool tagsEnabled;
final AvatarColor userAvatarColor;
final bool showSupportBadge;
const UserPreferences({
this.foldersEnabled = false,
this.memoriesEnabled = true,
this.peopleEnabled = true,
this.ratingsEnabled = false,
this.sharedLinksEnabled = true,
this.tagsEnabled = false,
this.userAvatarColor = AvatarColor.primary,
this.showSupportBadge = true,
});
UserPreferences copyWith({
bool? foldersEnabled,
bool? memoriesEnabled,
bool? peopleEnabled,
bool? ratingsEnabled,
bool? sharedLinksEnabled,
bool? tagsEnabled,
AvatarColor? userAvatarColor,
bool? showSupportBadge,
}) {
return UserPreferences(
foldersEnabled: foldersEnabled ?? this.foldersEnabled,
memoriesEnabled: memoriesEnabled ?? this.memoriesEnabled,
peopleEnabled: peopleEnabled ?? this.peopleEnabled,
ratingsEnabled: ratingsEnabled ?? this.ratingsEnabled,
sharedLinksEnabled: sharedLinksEnabled ?? this.sharedLinksEnabled,
tagsEnabled: tagsEnabled ?? this.tagsEnabled,
userAvatarColor: userAvatarColor ?? this.userAvatarColor,
showSupportBadge: showSupportBadge ?? this.showSupportBadge,
);
}
Map<String, Object?> toMap() {
final preferences = <String, Object?>{};
preferences["folders-Enabled"] = foldersEnabled;
preferences["memories-Enabled"] = memoriesEnabled;
preferences["people-Enabled"] = peopleEnabled;
preferences["ratings-Enabled"] = ratingsEnabled;
preferences["sharedLinks-Enabled"] = sharedLinksEnabled;
preferences["tags-Enabled"] = tagsEnabled;
preferences["avatar-Color"] = userAvatarColor.value;
preferences["purchase-ShowSupportBadge"] = showSupportBadge;
return preferences;
}
factory UserPreferences.fromMap(Map<String, Object?> map) {
return UserPreferences(
foldersEnabled: map["folders-Enabled"] as bool? ?? false,
memoriesEnabled: map["memories-Enabled"] as bool? ?? true,
peopleEnabled: map["people-Enabled"] as bool? ?? true,
ratingsEnabled: map["ratings-Enabled"] as bool? ?? false,
sharedLinksEnabled: map["sharedLinks-Enabled"] as bool? ?? true,
tagsEnabled: map["tags-Enabled"] as bool? ?? false,
userAvatarColor: AvatarColor.values.firstWhere(
(e) => e.value == map["avatar-Color"] as String?,
orElse: () => AvatarColor.primary,
),
showSupportBadge: map["purchase-ShowSupportBadge"] as bool? ?? true,
);
}
}

View File

@ -0,0 +1,18 @@
import 'package:drift/drift.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
class PartnerEntity extends Table with DriftDefaultsMixin {
const PartnerEntity();
BlobColumn get sharedById =>
blob().references(UserEntity, #id, onDelete: KeyAction.cascade)();
BlobColumn get sharedWithId =>
blob().references(UserEntity, #id, onDelete: KeyAction.cascade)();
BoolColumn get inTimeline => boolean().withDefault(const Constant(false))();
@override
Set<Column> get primaryKey => {sharedById, sharedWithId};
}

View File

@ -0,0 +1,610 @@
// dart format width=80
// ignore_for_file: type=lint
import 'package:drift/drift.dart' as i0;
import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart'
as i1;
import 'dart:typed_data' as i2;
import 'package:immich_mobile/infrastructure/entities/partner.entity.dart'
as i3;
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4;
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'
as i5;
import 'package:drift/internal/modular.dart' as i6;
typedef $$PartnerEntityTableCreateCompanionBuilder = i1.PartnerEntityCompanion
Function({
required i2.Uint8List sharedById,
required i2.Uint8List sharedWithId,
i0.Value<bool> inTimeline,
});
typedef $$PartnerEntityTableUpdateCompanionBuilder = i1.PartnerEntityCompanion
Function({
i0.Value<i2.Uint8List> sharedById,
i0.Value<i2.Uint8List> sharedWithId,
i0.Value<bool> inTimeline,
});
final class $$PartnerEntityTableReferences extends i0.BaseReferences<
i0.GeneratedDatabase, i1.$PartnerEntityTable, i1.PartnerEntityData> {
$$PartnerEntityTableReferences(
super.$_db, super.$_table, super.$_typedResult);
static i5.$UserEntityTable _sharedByIdTable(i0.GeneratedDatabase db) =>
i6.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity')
.createAlias(i0.$_aliasNameGenerator(
i6.ReadDatabaseContainer(db)
.resultSet<i1.$PartnerEntityTable>('partner_entity')
.sharedById,
i6.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity')
.id));
i5.$$UserEntityTableProcessedTableManager get sharedById {
final $_column = $_itemColumn<i2.Uint8List>('shared_by_id')!;
final manager = i5
.$$UserEntityTableTableManager(
$_db,
i6.ReadDatabaseContainer($_db)
.resultSet<i5.$UserEntityTable>('user_entity'))
.filter((f) => f.id.sqlEquals($_column));
final item = $_typedResult.readTableOrNull(_sharedByIdTable($_db));
if (item == null) return manager;
return i0.ProcessedTableManager(
manager.$state.copyWith(prefetchedData: [item]));
}
static i5.$UserEntityTable _sharedWithIdTable(i0.GeneratedDatabase db) =>
i6.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity')
.createAlias(i0.$_aliasNameGenerator(
i6.ReadDatabaseContainer(db)
.resultSet<i1.$PartnerEntityTable>('partner_entity')
.sharedWithId,
i6.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity')
.id));
i5.$$UserEntityTableProcessedTableManager get sharedWithId {
final $_column = $_itemColumn<i2.Uint8List>('shared_with_id')!;
final manager = i5
.$$UserEntityTableTableManager(
$_db,
i6.ReadDatabaseContainer($_db)
.resultSet<i5.$UserEntityTable>('user_entity'))
.filter((f) => f.id.sqlEquals($_column));
final item = $_typedResult.readTableOrNull(_sharedWithIdTable($_db));
if (item == null) return manager;
return i0.ProcessedTableManager(
manager.$state.copyWith(prefetchedData: [item]));
}
}
class $$PartnerEntityTableFilterComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$PartnerEntityTable> {
$$PartnerEntityTableFilterComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.ColumnFilters<bool> get inTimeline => $composableBuilder(
column: $table.inTimeline, builder: (column) => i0.ColumnFilters(column));
i5.$$UserEntityTableFilterComposer get sharedById {
final i5.$$UserEntityTableFilterComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.sharedById,
referencedTable: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableFilterComposer(
$db: $db,
$table: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
));
return composer;
}
i5.$$UserEntityTableFilterComposer get sharedWithId {
final i5.$$UserEntityTableFilterComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.sharedWithId,
referencedTable: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableFilterComposer(
$db: $db,
$table: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
));
return composer;
}
}
class $$PartnerEntityTableOrderingComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$PartnerEntityTable> {
$$PartnerEntityTableOrderingComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.ColumnOrderings<bool> get inTimeline => $composableBuilder(
column: $table.inTimeline,
builder: (column) => i0.ColumnOrderings(column));
i5.$$UserEntityTableOrderingComposer get sharedById {
final i5.$$UserEntityTableOrderingComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.sharedById,
referencedTable: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableOrderingComposer(
$db: $db,
$table: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
));
return composer;
}
i5.$$UserEntityTableOrderingComposer get sharedWithId {
final i5.$$UserEntityTableOrderingComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.sharedWithId,
referencedTable: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableOrderingComposer(
$db: $db,
$table: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
));
return composer;
}
}
class $$PartnerEntityTableAnnotationComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$PartnerEntityTable> {
$$PartnerEntityTableAnnotationComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.GeneratedColumn<bool> get inTimeline => $composableBuilder(
column: $table.inTimeline, builder: (column) => column);
i5.$$UserEntityTableAnnotationComposer get sharedById {
final i5.$$UserEntityTableAnnotationComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.sharedById,
referencedTable: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableAnnotationComposer(
$db: $db,
$table: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
));
return composer;
}
i5.$$UserEntityTableAnnotationComposer get sharedWithId {
final i5.$$UserEntityTableAnnotationComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.sharedWithId,
referencedTable: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableAnnotationComposer(
$db: $db,
$table: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
));
return composer;
}
}
class $$PartnerEntityTableTableManager extends i0.RootTableManager<
i0.GeneratedDatabase,
i1.$PartnerEntityTable,
i1.PartnerEntityData,
i1.$$PartnerEntityTableFilterComposer,
i1.$$PartnerEntityTableOrderingComposer,
i1.$$PartnerEntityTableAnnotationComposer,
$$PartnerEntityTableCreateCompanionBuilder,
$$PartnerEntityTableUpdateCompanionBuilder,
(i1.PartnerEntityData, i1.$$PartnerEntityTableReferences),
i1.PartnerEntityData,
i0.PrefetchHooks Function({bool sharedById, bool sharedWithId})> {
$$PartnerEntityTableTableManager(
i0.GeneratedDatabase db, i1.$PartnerEntityTable table)
: super(i0.TableManagerState(
db: db,
table: table,
createFilteringComposer: () =>
i1.$$PartnerEntityTableFilterComposer($db: db, $table: table),
createOrderingComposer: () =>
i1.$$PartnerEntityTableOrderingComposer($db: db, $table: table),
createComputedFieldComposer: () =>
i1.$$PartnerEntityTableAnnotationComposer($db: db, $table: table),
updateCompanionCallback: ({
i0.Value<i2.Uint8List> sharedById = const i0.Value.absent(),
i0.Value<i2.Uint8List> sharedWithId = const i0.Value.absent(),
i0.Value<bool> inTimeline = const i0.Value.absent(),
}) =>
i1.PartnerEntityCompanion(
sharedById: sharedById,
sharedWithId: sharedWithId,
inTimeline: inTimeline,
),
createCompanionCallback: ({
required i2.Uint8List sharedById,
required i2.Uint8List sharedWithId,
i0.Value<bool> inTimeline = const i0.Value.absent(),
}) =>
i1.PartnerEntityCompanion.insert(
sharedById: sharedById,
sharedWithId: sharedWithId,
inTimeline: inTimeline,
),
withReferenceMapper: (p0) => p0
.map((e) => (
e.readTable(table),
i1.$$PartnerEntityTableReferences(db, table, e)
))
.toList(),
prefetchHooksCallback: ({sharedById = false, sharedWithId = false}) {
return i0.PrefetchHooks(
db: db,
explicitlyWatchedTables: [],
addJoins: <
T extends i0.TableManagerState<
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic>>(state) {
if (sharedById) {
state = state.withJoin(
currentTable: table,
currentColumn: table.sharedById,
referencedTable:
i1.$$PartnerEntityTableReferences._sharedByIdTable(db),
referencedColumn: i1.$$PartnerEntityTableReferences
._sharedByIdTable(db)
.id,
) as T;
}
if (sharedWithId) {
state = state.withJoin(
currentTable: table,
currentColumn: table.sharedWithId,
referencedTable: i1.$$PartnerEntityTableReferences
._sharedWithIdTable(db),
referencedColumn: i1.$$PartnerEntityTableReferences
._sharedWithIdTable(db)
.id,
) as T;
}
return state;
},
getPrefetchedDataCallback: (items) async {
return [];
},
);
},
));
}
typedef $$PartnerEntityTableProcessedTableManager = i0.ProcessedTableManager<
i0.GeneratedDatabase,
i1.$PartnerEntityTable,
i1.PartnerEntityData,
i1.$$PartnerEntityTableFilterComposer,
i1.$$PartnerEntityTableOrderingComposer,
i1.$$PartnerEntityTableAnnotationComposer,
$$PartnerEntityTableCreateCompanionBuilder,
$$PartnerEntityTableUpdateCompanionBuilder,
(i1.PartnerEntityData, i1.$$PartnerEntityTableReferences),
i1.PartnerEntityData,
i0.PrefetchHooks Function({bool sharedById, bool sharedWithId})>;
class $PartnerEntityTable extends i3.PartnerEntity
with i0.TableInfo<$PartnerEntityTable, i1.PartnerEntityData> {
@override
final i0.GeneratedDatabase attachedDatabase;
final String? _alias;
$PartnerEntityTable(this.attachedDatabase, [this._alias]);
static const i0.VerificationMeta _sharedByIdMeta =
const i0.VerificationMeta('sharedById');
@override
late final i0.GeneratedColumn<i2.Uint8List> sharedById =
i0.GeneratedColumn<i2.Uint8List>('shared_by_id', aliasedName, false,
type: i0.DriftSqlType.blob,
requiredDuringInsert: true,
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
'REFERENCES user_entity (id) ON DELETE CASCADE'));
static const i0.VerificationMeta _sharedWithIdMeta =
const i0.VerificationMeta('sharedWithId');
@override
late final i0.GeneratedColumn<i2.Uint8List> sharedWithId =
i0.GeneratedColumn<i2.Uint8List>('shared_with_id', aliasedName, false,
type: i0.DriftSqlType.blob,
requiredDuringInsert: true,
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
'REFERENCES user_entity (id) ON DELETE CASCADE'));
static const i0.VerificationMeta _inTimelineMeta =
const i0.VerificationMeta('inTimeline');
@override
late final i0.GeneratedColumn<bool> inTimeline = i0.GeneratedColumn<bool>(
'in_timeline', aliasedName, false,
type: i0.DriftSqlType.bool,
requiredDuringInsert: false,
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
'CHECK ("in_timeline" IN (0, 1))'),
defaultValue: const i4.Constant(false));
@override
List<i0.GeneratedColumn> get $columns =>
[sharedById, sharedWithId, inTimeline];
@override
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => $name;
static const String $name = 'partner_entity';
@override
i0.VerificationContext validateIntegrity(
i0.Insertable<i1.PartnerEntityData> instance,
{bool isInserting = false}) {
final context = i0.VerificationContext();
final data = instance.toColumns(true);
if (data.containsKey('shared_by_id')) {
context.handle(
_sharedByIdMeta,
sharedById.isAcceptableOrUnknown(
data['shared_by_id']!, _sharedByIdMeta));
} else if (isInserting) {
context.missing(_sharedByIdMeta);
}
if (data.containsKey('shared_with_id')) {
context.handle(
_sharedWithIdMeta,
sharedWithId.isAcceptableOrUnknown(
data['shared_with_id']!, _sharedWithIdMeta));
} else if (isInserting) {
context.missing(_sharedWithIdMeta);
}
if (data.containsKey('in_timeline')) {
context.handle(
_inTimelineMeta,
inTimeline.isAcceptableOrUnknown(
data['in_timeline']!, _inTimelineMeta));
}
return context;
}
@override
Set<i0.GeneratedColumn> get $primaryKey => {sharedById, sharedWithId};
@override
i1.PartnerEntityData map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return i1.PartnerEntityData(
sharedById: attachedDatabase.typeMapping
.read(i0.DriftSqlType.blob, data['${effectivePrefix}shared_by_id'])!,
sharedWithId: attachedDatabase.typeMapping.read(
i0.DriftSqlType.blob, data['${effectivePrefix}shared_with_id'])!,
inTimeline: attachedDatabase.typeMapping
.read(i0.DriftSqlType.bool, data['${effectivePrefix}in_timeline'])!,
);
}
@override
$PartnerEntityTable createAlias(String alias) {
return $PartnerEntityTable(attachedDatabase, alias);
}
@override
bool get withoutRowId => true;
@override
bool get isStrict => true;
}
class PartnerEntityData extends i0.DataClass
implements i0.Insertable<i1.PartnerEntityData> {
final i2.Uint8List sharedById;
final i2.Uint8List sharedWithId;
final bool inTimeline;
const PartnerEntityData(
{required this.sharedById,
required this.sharedWithId,
required this.inTimeline});
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
map['shared_by_id'] = i0.Variable<i2.Uint8List>(sharedById);
map['shared_with_id'] = i0.Variable<i2.Uint8List>(sharedWithId);
map['in_timeline'] = i0.Variable<bool>(inTimeline);
return map;
}
factory PartnerEntityData.fromJson(Map<String, dynamic> json,
{i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return PartnerEntityData(
sharedById: serializer.fromJson<i2.Uint8List>(json['sharedById']),
sharedWithId: serializer.fromJson<i2.Uint8List>(json['sharedWithId']),
inTimeline: serializer.fromJson<bool>(json['inTimeline']),
);
}
@override
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'sharedById': serializer.toJson<i2.Uint8List>(sharedById),
'sharedWithId': serializer.toJson<i2.Uint8List>(sharedWithId),
'inTimeline': serializer.toJson<bool>(inTimeline),
};
}
i1.PartnerEntityData copyWith(
{i2.Uint8List? sharedById,
i2.Uint8List? sharedWithId,
bool? inTimeline}) =>
i1.PartnerEntityData(
sharedById: sharedById ?? this.sharedById,
sharedWithId: sharedWithId ?? this.sharedWithId,
inTimeline: inTimeline ?? this.inTimeline,
);
PartnerEntityData copyWithCompanion(i1.PartnerEntityCompanion data) {
return PartnerEntityData(
sharedById:
data.sharedById.present ? data.sharedById.value : this.sharedById,
sharedWithId: data.sharedWithId.present
? data.sharedWithId.value
: this.sharedWithId,
inTimeline:
data.inTimeline.present ? data.inTimeline.value : this.inTimeline,
);
}
@override
String toString() {
return (StringBuffer('PartnerEntityData(')
..write('sharedById: $sharedById, ')
..write('sharedWithId: $sharedWithId, ')
..write('inTimeline: $inTimeline')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(i0.$driftBlobEquality.hash(sharedById),
i0.$driftBlobEquality.hash(sharedWithId), inTimeline);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is i1.PartnerEntityData &&
i0.$driftBlobEquality.equals(other.sharedById, this.sharedById) &&
i0.$driftBlobEquality.equals(other.sharedWithId, this.sharedWithId) &&
other.inTimeline == this.inTimeline);
}
class PartnerEntityCompanion extends i0.UpdateCompanion<i1.PartnerEntityData> {
final i0.Value<i2.Uint8List> sharedById;
final i0.Value<i2.Uint8List> sharedWithId;
final i0.Value<bool> inTimeline;
const PartnerEntityCompanion({
this.sharedById = const i0.Value.absent(),
this.sharedWithId = const i0.Value.absent(),
this.inTimeline = const i0.Value.absent(),
});
PartnerEntityCompanion.insert({
required i2.Uint8List sharedById,
required i2.Uint8List sharedWithId,
this.inTimeline = const i0.Value.absent(),
}) : sharedById = i0.Value(sharedById),
sharedWithId = i0.Value(sharedWithId);
static i0.Insertable<i1.PartnerEntityData> custom({
i0.Expression<i2.Uint8List>? sharedById,
i0.Expression<i2.Uint8List>? sharedWithId,
i0.Expression<bool>? inTimeline,
}) {
return i0.RawValuesInsertable({
if (sharedById != null) 'shared_by_id': sharedById,
if (sharedWithId != null) 'shared_with_id': sharedWithId,
if (inTimeline != null) 'in_timeline': inTimeline,
});
}
i1.PartnerEntityCompanion copyWith(
{i0.Value<i2.Uint8List>? sharedById,
i0.Value<i2.Uint8List>? sharedWithId,
i0.Value<bool>? inTimeline}) {
return i1.PartnerEntityCompanion(
sharedById: sharedById ?? this.sharedById,
sharedWithId: sharedWithId ?? this.sharedWithId,
inTimeline: inTimeline ?? this.inTimeline,
);
}
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
if (sharedById.present) {
map['shared_by_id'] = i0.Variable<i2.Uint8List>(sharedById.value);
}
if (sharedWithId.present) {
map['shared_with_id'] = i0.Variable<i2.Uint8List>(sharedWithId.value);
}
if (inTimeline.present) {
map['in_timeline'] = i0.Variable<bool>(inTimeline.value);
}
return map;
}
@override
String toString() {
return (StringBuffer('PartnerEntityCompanion(')
..write('sharedById: $sharedById, ')
..write('sharedWithId: $sharedWithId, ')
..write('inTimeline: $inTimeline')
..write(')'))
.toString();
}
}

View File

@ -1,4 +1,7 @@
import 'package:drift/drift.dart' hide Index;
import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
import 'package:immich_mobile/utils/hash.dart'; import 'package:immich_mobile/utils/hash.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
@ -71,3 +74,20 @@ class User {
quotaSizeInBytes: quotaSizeInBytes, quotaSizeInBytes: quotaSizeInBytes,
); );
} }
class UserEntity extends Table with DriftDefaultsMixin {
const UserEntity();
BlobColumn get id => blob()();
TextColumn get name => text()();
BoolColumn get isAdmin => boolean().withDefault(const Constant(false))();
TextColumn get email => text()();
TextColumn get profileImagePath => text().nullable()();
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
// Quota
IntColumn get quotaSizeInBytes => integer().nullable()();
IntColumn get quotaUsageInBytes => integer().withDefault(const Constant(0))();
@override
Set<Column> get primaryKey => {id};
}

View File

@ -0,0 +1,656 @@
// dart format width=80
// ignore_for_file: type=lint
import 'package:drift/drift.dart' as i0;
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'
as i1;
import 'dart:typed_data' as i2;
import 'package:immich_mobile/infrastructure/entities/user.entity.dart' as i3;
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4;
typedef $$UserEntityTableCreateCompanionBuilder = i1.UserEntityCompanion
Function({
required i2.Uint8List id,
required String name,
i0.Value<bool> isAdmin,
required String email,
i0.Value<String?> profileImagePath,
i0.Value<DateTime> updatedAt,
i0.Value<int?> quotaSizeInBytes,
i0.Value<int> quotaUsageInBytes,
});
typedef $$UserEntityTableUpdateCompanionBuilder = i1.UserEntityCompanion
Function({
i0.Value<i2.Uint8List> id,
i0.Value<String> name,
i0.Value<bool> isAdmin,
i0.Value<String> email,
i0.Value<String?> profileImagePath,
i0.Value<DateTime> updatedAt,
i0.Value<int?> quotaSizeInBytes,
i0.Value<int> quotaUsageInBytes,
});
class $$UserEntityTableFilterComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$UserEntityTable> {
$$UserEntityTableFilterComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.ColumnFilters<i2.Uint8List> get id => $composableBuilder(
column: $table.id, builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<String> get name => $composableBuilder(
column: $table.name, builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<bool> get isAdmin => $composableBuilder(
column: $table.isAdmin, builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<String> get email => $composableBuilder(
column: $table.email, builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<String> get profileImagePath => $composableBuilder(
column: $table.profileImagePath,
builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<DateTime> get updatedAt => $composableBuilder(
column: $table.updatedAt, builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<int> get quotaSizeInBytes => $composableBuilder(
column: $table.quotaSizeInBytes,
builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<int> get quotaUsageInBytes => $composableBuilder(
column: $table.quotaUsageInBytes,
builder: (column) => i0.ColumnFilters(column));
}
class $$UserEntityTableOrderingComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$UserEntityTable> {
$$UserEntityTableOrderingComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.ColumnOrderings<i2.Uint8List> get id => $composableBuilder(
column: $table.id, builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<String> get name => $composableBuilder(
column: $table.name, builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<bool> get isAdmin => $composableBuilder(
column: $table.isAdmin, builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<String> get email => $composableBuilder(
column: $table.email, builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<String> get profileImagePath => $composableBuilder(
column: $table.profileImagePath,
builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<DateTime> get updatedAt => $composableBuilder(
column: $table.updatedAt,
builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<int> get quotaSizeInBytes => $composableBuilder(
column: $table.quotaSizeInBytes,
builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<int> get quotaUsageInBytes => $composableBuilder(
column: $table.quotaUsageInBytes,
builder: (column) => i0.ColumnOrderings(column));
}
class $$UserEntityTableAnnotationComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$UserEntityTable> {
$$UserEntityTableAnnotationComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.GeneratedColumn<i2.Uint8List> get id =>
$composableBuilder(column: $table.id, builder: (column) => column);
i0.GeneratedColumn<String> get name =>
$composableBuilder(column: $table.name, builder: (column) => column);
i0.GeneratedColumn<bool> get isAdmin =>
$composableBuilder(column: $table.isAdmin, builder: (column) => column);
i0.GeneratedColumn<String> get email =>
$composableBuilder(column: $table.email, builder: (column) => column);
i0.GeneratedColumn<String> get profileImagePath => $composableBuilder(
column: $table.profileImagePath, builder: (column) => column);
i0.GeneratedColumn<DateTime> get updatedAt =>
$composableBuilder(column: $table.updatedAt, builder: (column) => column);
i0.GeneratedColumn<int> get quotaSizeInBytes => $composableBuilder(
column: $table.quotaSizeInBytes, builder: (column) => column);
i0.GeneratedColumn<int> get quotaUsageInBytes => $composableBuilder(
column: $table.quotaUsageInBytes, builder: (column) => column);
}
class $$UserEntityTableTableManager extends i0.RootTableManager<
i0.GeneratedDatabase,
i1.$UserEntityTable,
i1.UserEntityData,
i1.$$UserEntityTableFilterComposer,
i1.$$UserEntityTableOrderingComposer,
i1.$$UserEntityTableAnnotationComposer,
$$UserEntityTableCreateCompanionBuilder,
$$UserEntityTableUpdateCompanionBuilder,
(
i1.UserEntityData,
i0.BaseReferences<i0.GeneratedDatabase, i1.$UserEntityTable,
i1.UserEntityData>
),
i1.UserEntityData,
i0.PrefetchHooks Function()> {
$$UserEntityTableTableManager(
i0.GeneratedDatabase db, i1.$UserEntityTable table)
: super(i0.TableManagerState(
db: db,
table: table,
createFilteringComposer: () =>
i1.$$UserEntityTableFilterComposer($db: db, $table: table),
createOrderingComposer: () =>
i1.$$UserEntityTableOrderingComposer($db: db, $table: table),
createComputedFieldComposer: () =>
i1.$$UserEntityTableAnnotationComposer($db: db, $table: table),
updateCompanionCallback: ({
i0.Value<i2.Uint8List> id = const i0.Value.absent(),
i0.Value<String> name = const i0.Value.absent(),
i0.Value<bool> isAdmin = const i0.Value.absent(),
i0.Value<String> email = const i0.Value.absent(),
i0.Value<String?> profileImagePath = const i0.Value.absent(),
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
i0.Value<int?> quotaSizeInBytes = const i0.Value.absent(),
i0.Value<int> quotaUsageInBytes = const i0.Value.absent(),
}) =>
i1.UserEntityCompanion(
id: id,
name: name,
isAdmin: isAdmin,
email: email,
profileImagePath: profileImagePath,
updatedAt: updatedAt,
quotaSizeInBytes: quotaSizeInBytes,
quotaUsageInBytes: quotaUsageInBytes,
),
createCompanionCallback: ({
required i2.Uint8List id,
required String name,
i0.Value<bool> isAdmin = const i0.Value.absent(),
required String email,
i0.Value<String?> profileImagePath = const i0.Value.absent(),
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
i0.Value<int?> quotaSizeInBytes = const i0.Value.absent(),
i0.Value<int> quotaUsageInBytes = const i0.Value.absent(),
}) =>
i1.UserEntityCompanion.insert(
id: id,
name: name,
isAdmin: isAdmin,
email: email,
profileImagePath: profileImagePath,
updatedAt: updatedAt,
quotaSizeInBytes: quotaSizeInBytes,
quotaUsageInBytes: quotaUsageInBytes,
),
withReferenceMapper: (p0) => p0
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e)))
.toList(),
prefetchHooksCallback: null,
));
}
typedef $$UserEntityTableProcessedTableManager = i0.ProcessedTableManager<
i0.GeneratedDatabase,
i1.$UserEntityTable,
i1.UserEntityData,
i1.$$UserEntityTableFilterComposer,
i1.$$UserEntityTableOrderingComposer,
i1.$$UserEntityTableAnnotationComposer,
$$UserEntityTableCreateCompanionBuilder,
$$UserEntityTableUpdateCompanionBuilder,
(
i1.UserEntityData,
i0.BaseReferences<i0.GeneratedDatabase, i1.$UserEntityTable,
i1.UserEntityData>
),
i1.UserEntityData,
i0.PrefetchHooks Function()>;
class $UserEntityTable extends i3.UserEntity
with i0.TableInfo<$UserEntityTable, i1.UserEntityData> {
@override
final i0.GeneratedDatabase attachedDatabase;
final String? _alias;
$UserEntityTable(this.attachedDatabase, [this._alias]);
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
@override
late final i0.GeneratedColumn<i2.Uint8List> id =
i0.GeneratedColumn<i2.Uint8List>('id', aliasedName, false,
type: i0.DriftSqlType.blob, requiredDuringInsert: true);
static const i0.VerificationMeta _nameMeta =
const i0.VerificationMeta('name');
@override
late final i0.GeneratedColumn<String> name = i0.GeneratedColumn<String>(
'name', aliasedName, false,
type: i0.DriftSqlType.string, requiredDuringInsert: true);
static const i0.VerificationMeta _isAdminMeta =
const i0.VerificationMeta('isAdmin');
@override
late final i0.GeneratedColumn<bool> isAdmin = i0.GeneratedColumn<bool>(
'is_admin', aliasedName, false,
type: i0.DriftSqlType.bool,
requiredDuringInsert: false,
defaultConstraints:
i0.GeneratedColumn.constraintIsAlways('CHECK ("is_admin" IN (0, 1))'),
defaultValue: const i4.Constant(false));
static const i0.VerificationMeta _emailMeta =
const i0.VerificationMeta('email');
@override
late final i0.GeneratedColumn<String> email = i0.GeneratedColumn<String>(
'email', aliasedName, false,
type: i0.DriftSqlType.string, requiredDuringInsert: true);
static const i0.VerificationMeta _profileImagePathMeta =
const i0.VerificationMeta('profileImagePath');
@override
late final i0.GeneratedColumn<String> profileImagePath =
i0.GeneratedColumn<String>('profile_image_path', aliasedName, true,
type: i0.DriftSqlType.string, requiredDuringInsert: false);
static const i0.VerificationMeta _updatedAtMeta =
const i0.VerificationMeta('updatedAt');
@override
late final i0.GeneratedColumn<DateTime> updatedAt =
i0.GeneratedColumn<DateTime>('updated_at', aliasedName, false,
type: i0.DriftSqlType.dateTime,
requiredDuringInsert: false,
defaultValue: i4.currentDateAndTime);
static const i0.VerificationMeta _quotaSizeInBytesMeta =
const i0.VerificationMeta('quotaSizeInBytes');
@override
late final i0.GeneratedColumn<int> quotaSizeInBytes = i0.GeneratedColumn<int>(
'quota_size_in_bytes', aliasedName, true,
type: i0.DriftSqlType.int, requiredDuringInsert: false);
static const i0.VerificationMeta _quotaUsageInBytesMeta =
const i0.VerificationMeta('quotaUsageInBytes');
@override
late final i0.GeneratedColumn<int> quotaUsageInBytes =
i0.GeneratedColumn<int>('quota_usage_in_bytes', aliasedName, false,
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
defaultValue: const i4.Constant(0));
@override
List<i0.GeneratedColumn> get $columns => [
id,
name,
isAdmin,
email,
profileImagePath,
updatedAt,
quotaSizeInBytes,
quotaUsageInBytes
];
@override
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => $name;
static const String $name = 'user_entity';
@override
i0.VerificationContext validateIntegrity(
i0.Insertable<i1.UserEntityData> instance,
{bool isInserting = false}) {
final context = i0.VerificationContext();
final data = instance.toColumns(true);
if (data.containsKey('id')) {
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
} else if (isInserting) {
context.missing(_idMeta);
}
if (data.containsKey('name')) {
context.handle(
_nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta));
} else if (isInserting) {
context.missing(_nameMeta);
}
if (data.containsKey('is_admin')) {
context.handle(_isAdminMeta,
isAdmin.isAcceptableOrUnknown(data['is_admin']!, _isAdminMeta));
}
if (data.containsKey('email')) {
context.handle(
_emailMeta, email.isAcceptableOrUnknown(data['email']!, _emailMeta));
} else if (isInserting) {
context.missing(_emailMeta);
}
if (data.containsKey('profile_image_path')) {
context.handle(
_profileImagePathMeta,
profileImagePath.isAcceptableOrUnknown(
data['profile_image_path']!, _profileImagePathMeta));
}
if (data.containsKey('updated_at')) {
context.handle(_updatedAtMeta,
updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta));
}
if (data.containsKey('quota_size_in_bytes')) {
context.handle(
_quotaSizeInBytesMeta,
quotaSizeInBytes.isAcceptableOrUnknown(
data['quota_size_in_bytes']!, _quotaSizeInBytesMeta));
}
if (data.containsKey('quota_usage_in_bytes')) {
context.handle(
_quotaUsageInBytesMeta,
quotaUsageInBytes.isAcceptableOrUnknown(
data['quota_usage_in_bytes']!, _quotaUsageInBytesMeta));
}
return context;
}
@override
Set<i0.GeneratedColumn> get $primaryKey => {id};
@override
i1.UserEntityData map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return i1.UserEntityData(
id: attachedDatabase.typeMapping
.read(i0.DriftSqlType.blob, data['${effectivePrefix}id'])!,
name: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}name'])!,
isAdmin: attachedDatabase.typeMapping
.read(i0.DriftSqlType.bool, data['${effectivePrefix}is_admin'])!,
email: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}email'])!,
profileImagePath: attachedDatabase.typeMapping.read(
i0.DriftSqlType.string, data['${effectivePrefix}profile_image_path']),
updatedAt: attachedDatabase.typeMapping.read(
i0.DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!,
quotaSizeInBytes: attachedDatabase.typeMapping.read(
i0.DriftSqlType.int, data['${effectivePrefix}quota_size_in_bytes']),
quotaUsageInBytes: attachedDatabase.typeMapping.read(
i0.DriftSqlType.int, data['${effectivePrefix}quota_usage_in_bytes'])!,
);
}
@override
$UserEntityTable createAlias(String alias) {
return $UserEntityTable(attachedDatabase, alias);
}
@override
bool get withoutRowId => true;
@override
bool get isStrict => true;
}
class UserEntityData extends i0.DataClass
implements i0.Insertable<i1.UserEntityData> {
final i2.Uint8List id;
final String name;
final bool isAdmin;
final String email;
final String? profileImagePath;
final DateTime updatedAt;
final int? quotaSizeInBytes;
final int quotaUsageInBytes;
const UserEntityData(
{required this.id,
required this.name,
required this.isAdmin,
required this.email,
this.profileImagePath,
required this.updatedAt,
this.quotaSizeInBytes,
required this.quotaUsageInBytes});
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
map['id'] = i0.Variable<i2.Uint8List>(id);
map['name'] = i0.Variable<String>(name);
map['is_admin'] = i0.Variable<bool>(isAdmin);
map['email'] = i0.Variable<String>(email);
if (!nullToAbsent || profileImagePath != null) {
map['profile_image_path'] = i0.Variable<String>(profileImagePath);
}
map['updated_at'] = i0.Variable<DateTime>(updatedAt);
if (!nullToAbsent || quotaSizeInBytes != null) {
map['quota_size_in_bytes'] = i0.Variable<int>(quotaSizeInBytes);
}
map['quota_usage_in_bytes'] = i0.Variable<int>(quotaUsageInBytes);
return map;
}
factory UserEntityData.fromJson(Map<String, dynamic> json,
{i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return UserEntityData(
id: serializer.fromJson<i2.Uint8List>(json['id']),
name: serializer.fromJson<String>(json['name']),
isAdmin: serializer.fromJson<bool>(json['isAdmin']),
email: serializer.fromJson<String>(json['email']),
profileImagePath: serializer.fromJson<String?>(json['profileImagePath']),
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
quotaSizeInBytes: serializer.fromJson<int?>(json['quotaSizeInBytes']),
quotaUsageInBytes: serializer.fromJson<int>(json['quotaUsageInBytes']),
);
}
@override
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<i2.Uint8List>(id),
'name': serializer.toJson<String>(name),
'isAdmin': serializer.toJson<bool>(isAdmin),
'email': serializer.toJson<String>(email),
'profileImagePath': serializer.toJson<String?>(profileImagePath),
'updatedAt': serializer.toJson<DateTime>(updatedAt),
'quotaSizeInBytes': serializer.toJson<int?>(quotaSizeInBytes),
'quotaUsageInBytes': serializer.toJson<int>(quotaUsageInBytes),
};
}
i1.UserEntityData copyWith(
{i2.Uint8List? id,
String? name,
bool? isAdmin,
String? email,
i0.Value<String?> profileImagePath = const i0.Value.absent(),
DateTime? updatedAt,
i0.Value<int?> quotaSizeInBytes = const i0.Value.absent(),
int? quotaUsageInBytes}) =>
i1.UserEntityData(
id: id ?? this.id,
name: name ?? this.name,
isAdmin: isAdmin ?? this.isAdmin,
email: email ?? this.email,
profileImagePath: profileImagePath.present
? profileImagePath.value
: this.profileImagePath,
updatedAt: updatedAt ?? this.updatedAt,
quotaSizeInBytes: quotaSizeInBytes.present
? quotaSizeInBytes.value
: this.quotaSizeInBytes,
quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes,
);
UserEntityData copyWithCompanion(i1.UserEntityCompanion data) {
return UserEntityData(
id: data.id.present ? data.id.value : this.id,
name: data.name.present ? data.name.value : this.name,
isAdmin: data.isAdmin.present ? data.isAdmin.value : this.isAdmin,
email: data.email.present ? data.email.value : this.email,
profileImagePath: data.profileImagePath.present
? data.profileImagePath.value
: this.profileImagePath,
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
quotaSizeInBytes: data.quotaSizeInBytes.present
? data.quotaSizeInBytes.value
: this.quotaSizeInBytes,
quotaUsageInBytes: data.quotaUsageInBytes.present
? data.quotaUsageInBytes.value
: this.quotaUsageInBytes,
);
}
@override
String toString() {
return (StringBuffer('UserEntityData(')
..write('id: $id, ')
..write('name: $name, ')
..write('isAdmin: $isAdmin, ')
..write('email: $email, ')
..write('profileImagePath: $profileImagePath, ')
..write('updatedAt: $updatedAt, ')
..write('quotaSizeInBytes: $quotaSizeInBytes, ')
..write('quotaUsageInBytes: $quotaUsageInBytes')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(i0.$driftBlobEquality.hash(id), name, isAdmin,
email, profileImagePath, updatedAt, quotaSizeInBytes, quotaUsageInBytes);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is i1.UserEntityData &&
i0.$driftBlobEquality.equals(other.id, this.id) &&
other.name == this.name &&
other.isAdmin == this.isAdmin &&
other.email == this.email &&
other.profileImagePath == this.profileImagePath &&
other.updatedAt == this.updatedAt &&
other.quotaSizeInBytes == this.quotaSizeInBytes &&
other.quotaUsageInBytes == this.quotaUsageInBytes);
}
class UserEntityCompanion extends i0.UpdateCompanion<i1.UserEntityData> {
final i0.Value<i2.Uint8List> id;
final i0.Value<String> name;
final i0.Value<bool> isAdmin;
final i0.Value<String> email;
final i0.Value<String?> profileImagePath;
final i0.Value<DateTime> updatedAt;
final i0.Value<int?> quotaSizeInBytes;
final i0.Value<int> quotaUsageInBytes;
const UserEntityCompanion({
this.id = const i0.Value.absent(),
this.name = const i0.Value.absent(),
this.isAdmin = const i0.Value.absent(),
this.email = const i0.Value.absent(),
this.profileImagePath = const i0.Value.absent(),
this.updatedAt = const i0.Value.absent(),
this.quotaSizeInBytes = const i0.Value.absent(),
this.quotaUsageInBytes = const i0.Value.absent(),
});
UserEntityCompanion.insert({
required i2.Uint8List id,
required String name,
this.isAdmin = const i0.Value.absent(),
required String email,
this.profileImagePath = const i0.Value.absent(),
this.updatedAt = const i0.Value.absent(),
this.quotaSizeInBytes = const i0.Value.absent(),
this.quotaUsageInBytes = const i0.Value.absent(),
}) : id = i0.Value(id),
name = i0.Value(name),
email = i0.Value(email);
static i0.Insertable<i1.UserEntityData> custom({
i0.Expression<i2.Uint8List>? id,
i0.Expression<String>? name,
i0.Expression<bool>? isAdmin,
i0.Expression<String>? email,
i0.Expression<String>? profileImagePath,
i0.Expression<DateTime>? updatedAt,
i0.Expression<int>? quotaSizeInBytes,
i0.Expression<int>? quotaUsageInBytes,
}) {
return i0.RawValuesInsertable({
if (id != null) 'id': id,
if (name != null) 'name': name,
if (isAdmin != null) 'is_admin': isAdmin,
if (email != null) 'email': email,
if (profileImagePath != null) 'profile_image_path': profileImagePath,
if (updatedAt != null) 'updated_at': updatedAt,
if (quotaSizeInBytes != null) 'quota_size_in_bytes': quotaSizeInBytes,
if (quotaUsageInBytes != null) 'quota_usage_in_bytes': quotaUsageInBytes,
});
}
i1.UserEntityCompanion copyWith(
{i0.Value<i2.Uint8List>? id,
i0.Value<String>? name,
i0.Value<bool>? isAdmin,
i0.Value<String>? email,
i0.Value<String?>? profileImagePath,
i0.Value<DateTime>? updatedAt,
i0.Value<int?>? quotaSizeInBytes,
i0.Value<int>? quotaUsageInBytes}) {
return i1.UserEntityCompanion(
id: id ?? this.id,
name: name ?? this.name,
isAdmin: isAdmin ?? this.isAdmin,
email: email ?? this.email,
profileImagePath: profileImagePath ?? this.profileImagePath,
updatedAt: updatedAt ?? this.updatedAt,
quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes,
quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes,
);
}
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
if (id.present) {
map['id'] = i0.Variable<i2.Uint8List>(id.value);
}
if (name.present) {
map['name'] = i0.Variable<String>(name.value);
}
if (isAdmin.present) {
map['is_admin'] = i0.Variable<bool>(isAdmin.value);
}
if (email.present) {
map['email'] = i0.Variable<String>(email.value);
}
if (profileImagePath.present) {
map['profile_image_path'] = i0.Variable<String>(profileImagePath.value);
}
if (updatedAt.present) {
map['updated_at'] = i0.Variable<DateTime>(updatedAt.value);
}
if (quotaSizeInBytes.present) {
map['quota_size_in_bytes'] = i0.Variable<int>(quotaSizeInBytes.value);
}
if (quotaUsageInBytes.present) {
map['quota_usage_in_bytes'] = i0.Variable<int>(quotaUsageInBytes.value);
}
return map;
}
@override
String toString() {
return (StringBuffer('UserEntityCompanion(')
..write('id: $id, ')
..write('name: $name, ')
..write('isAdmin: $isAdmin, ')
..write('email: $email, ')
..write('profileImagePath: $profileImagePath, ')
..write('updatedAt: $updatedAt, ')
..write('quotaSizeInBytes: $quotaSizeInBytes, ')
..write('quotaUsageInBytes: $quotaUsageInBytes')
..write(')'))
.toString();
}
}

View File

@ -0,0 +1,21 @@
import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
class UserMetadataEntity extends Table with DriftDefaultsMixin {
const UserMetadataEntity();
BlobColumn get userId =>
blob().references(UserEntity, #id, onDelete: KeyAction.cascade)();
TextColumn get preferences => text().map(userPreferenceConverter)();
@override
Set<Column> get primaryKey => {userId};
}
final JsonTypeConverter2<UserPreferences, String, Object?>
userPreferenceConverter = TypeConverter.json2(
fromJson: (json) => UserPreferences.fromMap(json as Map<String, Object?>),
toJson: (pref) => pref.toMap(),
);

View File

@ -0,0 +1,468 @@
// dart format width=80
// ignore_for_file: type=lint
import 'package:drift/drift.dart' as i0;
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart'
as i1;
import 'dart:typed_data' as i2;
import 'package:immich_mobile/domain/models/user_metadata.model.dart' as i3;
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.dart'
as i4;
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'
as i5;
import 'package:drift/internal/modular.dart' as i6;
typedef $$UserMetadataEntityTableCreateCompanionBuilder
= i1.UserMetadataEntityCompanion Function({
required i2.Uint8List userId,
required i3.UserPreferences preferences,
});
typedef $$UserMetadataEntityTableUpdateCompanionBuilder
= i1.UserMetadataEntityCompanion Function({
i0.Value<i2.Uint8List> userId,
i0.Value<i3.UserPreferences> preferences,
});
final class $$UserMetadataEntityTableReferences extends i0.BaseReferences<
i0.GeneratedDatabase,
i1.$UserMetadataEntityTable,
i1.UserMetadataEntityData> {
$$UserMetadataEntityTableReferences(
super.$_db, super.$_table, super.$_typedResult);
static i5.$UserEntityTable _userIdTable(i0.GeneratedDatabase db) =>
i6.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity')
.createAlias(i0.$_aliasNameGenerator(
i6.ReadDatabaseContainer(db)
.resultSet<i1.$UserMetadataEntityTable>(
'user_metadata_entity')
.userId,
i6.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity')
.id));
i5.$$UserEntityTableProcessedTableManager get userId {
final $_column = $_itemColumn<i2.Uint8List>('user_id')!;
final manager = i5
.$$UserEntityTableTableManager(
$_db,
i6.ReadDatabaseContainer($_db)
.resultSet<i5.$UserEntityTable>('user_entity'))
.filter((f) => f.id.sqlEquals($_column));
final item = $_typedResult.readTableOrNull(_userIdTable($_db));
if (item == null) return manager;
return i0.ProcessedTableManager(
manager.$state.copyWith(prefetchedData: [item]));
}
}
class $$UserMetadataEntityTableFilterComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$UserMetadataEntityTable> {
$$UserMetadataEntityTableFilterComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.ColumnWithTypeConverterFilters<i3.UserPreferences, i3.UserPreferences,
String>
get preferences => $composableBuilder(
column: $table.preferences,
builder: (column) => i0.ColumnWithTypeConverterFilters(column));
i5.$$UserEntityTableFilterComposer get userId {
final i5.$$UserEntityTableFilterComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.userId,
referencedTable: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableFilterComposer(
$db: $db,
$table: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
));
return composer;
}
}
class $$UserMetadataEntityTableOrderingComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$UserMetadataEntityTable> {
$$UserMetadataEntityTableOrderingComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.ColumnOrderings<String> get preferences => $composableBuilder(
column: $table.preferences,
builder: (column) => i0.ColumnOrderings(column));
i5.$$UserEntityTableOrderingComposer get userId {
final i5.$$UserEntityTableOrderingComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.userId,
referencedTable: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableOrderingComposer(
$db: $db,
$table: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
));
return composer;
}
}
class $$UserMetadataEntityTableAnnotationComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$UserMetadataEntityTable> {
$$UserMetadataEntityTableAnnotationComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.GeneratedColumnWithTypeConverter<i3.UserPreferences, String>
get preferences => $composableBuilder(
column: $table.preferences, builder: (column) => column);
i5.$$UserEntityTableAnnotationComposer get userId {
final i5.$$UserEntityTableAnnotationComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.userId,
referencedTable: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableAnnotationComposer(
$db: $db,
$table: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
));
return composer;
}
}
class $$UserMetadataEntityTableTableManager extends i0.RootTableManager<
i0.GeneratedDatabase,
i1.$UserMetadataEntityTable,
i1.UserMetadataEntityData,
i1.$$UserMetadataEntityTableFilterComposer,
i1.$$UserMetadataEntityTableOrderingComposer,
i1.$$UserMetadataEntityTableAnnotationComposer,
$$UserMetadataEntityTableCreateCompanionBuilder,
$$UserMetadataEntityTableUpdateCompanionBuilder,
(i1.UserMetadataEntityData, i1.$$UserMetadataEntityTableReferences),
i1.UserMetadataEntityData,
i0.PrefetchHooks Function({bool userId})> {
$$UserMetadataEntityTableTableManager(
i0.GeneratedDatabase db, i1.$UserMetadataEntityTable table)
: super(i0.TableManagerState(
db: db,
table: table,
createFilteringComposer: () => i1
.$$UserMetadataEntityTableFilterComposer($db: db, $table: table),
createOrderingComposer: () =>
i1.$$UserMetadataEntityTableOrderingComposer(
$db: db, $table: table),
createComputedFieldComposer: () =>
i1.$$UserMetadataEntityTableAnnotationComposer(
$db: db, $table: table),
updateCompanionCallback: ({
i0.Value<i2.Uint8List> userId = const i0.Value.absent(),
i0.Value<i3.UserPreferences> preferences = const i0.Value.absent(),
}) =>
i1.UserMetadataEntityCompanion(
userId: userId,
preferences: preferences,
),
createCompanionCallback: ({
required i2.Uint8List userId,
required i3.UserPreferences preferences,
}) =>
i1.UserMetadataEntityCompanion.insert(
userId: userId,
preferences: preferences,
),
withReferenceMapper: (p0) => p0
.map((e) => (
e.readTable(table),
i1.$$UserMetadataEntityTableReferences(db, table, e)
))
.toList(),
prefetchHooksCallback: ({userId = false}) {
return i0.PrefetchHooks(
db: db,
explicitlyWatchedTables: [],
addJoins: <
T extends i0.TableManagerState<
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic,
dynamic>>(state) {
if (userId) {
state = state.withJoin(
currentTable: table,
currentColumn: table.userId,
referencedTable:
i1.$$UserMetadataEntityTableReferences._userIdTable(db),
referencedColumn: i1.$$UserMetadataEntityTableReferences
._userIdTable(db)
.id,
) as T;
}
return state;
},
getPrefetchedDataCallback: (items) async {
return [];
},
);
},
));
}
typedef $$UserMetadataEntityTableProcessedTableManager
= i0.ProcessedTableManager<
i0.GeneratedDatabase,
i1.$UserMetadataEntityTable,
i1.UserMetadataEntityData,
i1.$$UserMetadataEntityTableFilterComposer,
i1.$$UserMetadataEntityTableOrderingComposer,
i1.$$UserMetadataEntityTableAnnotationComposer,
$$UserMetadataEntityTableCreateCompanionBuilder,
$$UserMetadataEntityTableUpdateCompanionBuilder,
(i1.UserMetadataEntityData, i1.$$UserMetadataEntityTableReferences),
i1.UserMetadataEntityData,
i0.PrefetchHooks Function({bool userId})>;
class $UserMetadataEntityTable extends i4.UserMetadataEntity
with i0.TableInfo<$UserMetadataEntityTable, i1.UserMetadataEntityData> {
@override
final i0.GeneratedDatabase attachedDatabase;
final String? _alias;
$UserMetadataEntityTable(this.attachedDatabase, [this._alias]);
static const i0.VerificationMeta _userIdMeta =
const i0.VerificationMeta('userId');
@override
late final i0.GeneratedColumn<i2.Uint8List> userId =
i0.GeneratedColumn<i2.Uint8List>('user_id', aliasedName, false,
type: i0.DriftSqlType.blob,
requiredDuringInsert: true,
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
'REFERENCES user_entity (id) ON DELETE CASCADE'));
@override
late final i0.GeneratedColumnWithTypeConverter<i3.UserPreferences, String>
preferences = i0.GeneratedColumn<String>(
'preferences', aliasedName, false,
type: i0.DriftSqlType.string, requiredDuringInsert: true)
.withConverter<i3.UserPreferences>(
i1.$UserMetadataEntityTable.$converterpreferences);
@override
List<i0.GeneratedColumn> get $columns => [userId, preferences];
@override
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => $name;
static const String $name = 'user_metadata_entity';
@override
i0.VerificationContext validateIntegrity(
i0.Insertable<i1.UserMetadataEntityData> instance,
{bool isInserting = false}) {
final context = i0.VerificationContext();
final data = instance.toColumns(true);
if (data.containsKey('user_id')) {
context.handle(_userIdMeta,
userId.isAcceptableOrUnknown(data['user_id']!, _userIdMeta));
} else if (isInserting) {
context.missing(_userIdMeta);
}
return context;
}
@override
Set<i0.GeneratedColumn> get $primaryKey => {userId};
@override
i1.UserMetadataEntityData map(Map<String, dynamic> data,
{String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return i1.UserMetadataEntityData(
userId: attachedDatabase.typeMapping
.read(i0.DriftSqlType.blob, data['${effectivePrefix}user_id'])!,
preferences: i1.$UserMetadataEntityTable.$converterpreferences.fromSql(
attachedDatabase.typeMapping.read(
i0.DriftSqlType.string, data['${effectivePrefix}preferences'])!),
);
}
@override
$UserMetadataEntityTable createAlias(String alias) {
return $UserMetadataEntityTable(attachedDatabase, alias);
}
static i0.JsonTypeConverter2<i3.UserPreferences, String, Object?>
$converterpreferences = i4.userPreferenceConverter;
@override
bool get withoutRowId => true;
@override
bool get isStrict => true;
}
class UserMetadataEntityData extends i0.DataClass
implements i0.Insertable<i1.UserMetadataEntityData> {
final i2.Uint8List userId;
final i3.UserPreferences preferences;
const UserMetadataEntityData(
{required this.userId, required this.preferences});
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
map['user_id'] = i0.Variable<i2.Uint8List>(userId);
{
map['preferences'] = i0.Variable<String>(
i1.$UserMetadataEntityTable.$converterpreferences.toSql(preferences));
}
return map;
}
factory UserMetadataEntityData.fromJson(Map<String, dynamic> json,
{i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return UserMetadataEntityData(
userId: serializer.fromJson<i2.Uint8List>(json['userId']),
preferences: i1.$UserMetadataEntityTable.$converterpreferences
.fromJson(serializer.fromJson<Object?>(json['preferences'])),
);
}
@override
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'userId': serializer.toJson<i2.Uint8List>(userId),
'preferences': serializer.toJson<Object?>(i1
.$UserMetadataEntityTable.$converterpreferences
.toJson(preferences)),
};
}
i1.UserMetadataEntityData copyWith(
{i2.Uint8List? userId, i3.UserPreferences? preferences}) =>
i1.UserMetadataEntityData(
userId: userId ?? this.userId,
preferences: preferences ?? this.preferences,
);
UserMetadataEntityData copyWithCompanion(
i1.UserMetadataEntityCompanion data) {
return UserMetadataEntityData(
userId: data.userId.present ? data.userId.value : this.userId,
preferences:
data.preferences.present ? data.preferences.value : this.preferences,
);
}
@override
String toString() {
return (StringBuffer('UserMetadataEntityData(')
..write('userId: $userId, ')
..write('preferences: $preferences')
..write(')'))
.toString();
}
@override
int get hashCode =>
Object.hash(i0.$driftBlobEquality.hash(userId), preferences);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is i1.UserMetadataEntityData &&
i0.$driftBlobEquality.equals(other.userId, this.userId) &&
other.preferences == this.preferences);
}
class UserMetadataEntityCompanion
extends i0.UpdateCompanion<i1.UserMetadataEntityData> {
final i0.Value<i2.Uint8List> userId;
final i0.Value<i3.UserPreferences> preferences;
const UserMetadataEntityCompanion({
this.userId = const i0.Value.absent(),
this.preferences = const i0.Value.absent(),
});
UserMetadataEntityCompanion.insert({
required i2.Uint8List userId,
required i3.UserPreferences preferences,
}) : userId = i0.Value(userId),
preferences = i0.Value(preferences);
static i0.Insertable<i1.UserMetadataEntityData> custom({
i0.Expression<i2.Uint8List>? userId,
i0.Expression<String>? preferences,
}) {
return i0.RawValuesInsertable({
if (userId != null) 'user_id': userId,
if (preferences != null) 'preferences': preferences,
});
}
i1.UserMetadataEntityCompanion copyWith(
{i0.Value<i2.Uint8List>? userId,
i0.Value<i3.UserPreferences>? preferences}) {
return i1.UserMetadataEntityCompanion(
userId: userId ?? this.userId,
preferences: preferences ?? this.preferences,
);
}
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
if (userId.present) {
map['user_id'] = i0.Variable<i2.Uint8List>(userId.value);
}
if (preferences.present) {
map['preferences'] = i0.Variable<String>(i1
.$UserMetadataEntityTable.$converterpreferences
.toSql(preferences.value));
}
return map;
}
@override
String toString() {
return (StringBuffer('UserMetadataEntityCompanion(')
..write('userId: $userId, ')
..write('preferences: $preferences')
..write(')'))
.toString();
}
}

View File

@ -1,8 +1,15 @@
import 'dart:async'; import 'dart:async';
import 'package:drift/drift.dart';
import 'package:drift_flutter/drift_flutter.dart';
import 'package:immich_mobile/domain/interfaces/db.interface.dart'; import 'package:immich_mobile/domain/interfaces/db.interface.dart';
import 'package:immich_mobile/infrastructure/entities/partner.entity.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'db.repository.drift.dart';
// #zoneTxn is the symbol used by Isar to mark a transaction within the current zone // #zoneTxn is the symbol used by Isar to mark a transaction within the current zone
// ref: isar/isar_common.dart // ref: isar/isar_common.dart
const Symbol _kzoneTxn = #zoneTxn; const Symbol _kzoneTxn = #zoneTxn;
@ -17,3 +24,35 @@ class IsarDatabaseRepository implements IDatabaseRepository {
Future<T> transaction<T>(Future<T> Function() callback) => Future<T> transaction<T>(Future<T> Function() callback) =>
Zone.current[_kzoneTxn] == null ? _db.writeTxn(callback) : callback(); Zone.current[_kzoneTxn] == null ? _db.writeTxn(callback) : callback();
} }
@DriftDatabase(tables: [UserEntity, UserMetadataEntity, PartnerEntity])
class Drift extends $Drift implements IDatabaseRepository {
Drift([QueryExecutor? executor])
: super(
executor ??
driftDatabase(
name: 'immich',
native: const DriftNativeOptions(shareAcrossIsolates: true),
),
);
@override
int get schemaVersion => 1;
@override
MigrationStrategy get migration => MigrationStrategy(
beforeOpen: (details) async {
await customStatement('PRAGMA journal_mode = WAL');
await customStatement('PRAGMA foreign_keys = ON');
},
);
}
class DriftDatabaseRepository implements IDatabaseRepository {
final Drift _db;
const DriftDatabaseRepository(this._db);
@override
Future<T> transaction<T>(Future<T> Function() callback) =>
_db.transaction(callback);
}

View File

@ -0,0 +1,67 @@
// dart format width=80
// ignore_for_file: type=lint
import 'package:drift/drift.dart' as i0;
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'
as i1;
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart'
as i2;
import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart'
as i3;
abstract class $Drift extends i0.GeneratedDatabase {
$Drift(i0.QueryExecutor e) : super(e);
$DriftManager get managers => $DriftManager(this);
late final i1.$UserEntityTable userEntity = i1.$UserEntityTable(this);
late final i2.$UserMetadataEntityTable userMetadataEntity =
i2.$UserMetadataEntityTable(this);
late final i3.$PartnerEntityTable partnerEntity =
i3.$PartnerEntityTable(this);
@override
Iterable<i0.TableInfo<i0.Table, Object?>> get allTables =>
allSchemaEntities.whereType<i0.TableInfo<i0.Table, Object?>>();
@override
List<i0.DatabaseSchemaEntity> get allSchemaEntities =>
[userEntity, userMetadataEntity, partnerEntity];
@override
i0.StreamQueryUpdateRules get streamUpdateRules =>
const i0.StreamQueryUpdateRules(
[
i0.WritePropagation(
on: i0.TableUpdateQuery.onTableName('user_entity',
limitUpdateKind: i0.UpdateKind.delete),
result: [
i0.TableUpdate('user_metadata_entity',
kind: i0.UpdateKind.delete),
],
),
i0.WritePropagation(
on: i0.TableUpdateQuery.onTableName('user_entity',
limitUpdateKind: i0.UpdateKind.delete),
result: [
i0.TableUpdate('partner_entity', kind: i0.UpdateKind.delete),
],
),
i0.WritePropagation(
on: i0.TableUpdateQuery.onTableName('user_entity',
limitUpdateKind: i0.UpdateKind.delete),
result: [
i0.TableUpdate('partner_entity', kind: i0.UpdateKind.delete),
],
),
],
);
@override
i0.DriftDatabaseOptions get options =>
const i0.DriftDatabaseOptions(storeDateTimeAsText: true);
}
class $DriftManager {
final $Drift _db;
$DriftManager(this._db);
i1.$$UserEntityTableTableManager get userEntity =>
i1.$$UserEntityTableTableManager(_db, _db.userEntity);
i2.$$UserMetadataEntityTableTableManager get userMetadataEntity =>
i2.$$UserMetadataEntityTableTableManager(_db, _db.userMetadataEntity);
i3.$$PartnerEntityTableTableManager get partnerEntity =>
i3.$$PartnerEntityTableTableManager(_db, _db.partnerEntity);
}

View File

@ -0,0 +1,9 @@
import 'package:drift/drift.dart';
mixin DriftDefaultsMixin on Table {
@override
bool get isStrict => true;
@override
bool get withoutRowId => true;
}

View File

@ -1,6 +1,7 @@
import 'package:immich_mobile/domain/models/exif.model.dart'; import 'package:immich_mobile/domain/models/exif.model.dart';
import 'package:openapi/api.dart'; import 'package:openapi/api.dart';
// TODO: Move to repository once all classes are refactored
abstract final class ExifDtoConverter { abstract final class ExifDtoConverter {
static ExifInfo fromDto(ExifResponseDto dto) { static ExifInfo fromDto(ExifResponseDto dto) {
return ExifInfo( return ExifInfo(

View File

@ -1,6 +1,8 @@
import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
import 'package:openapi/api.dart'; import 'package:openapi/api.dart';
// TODO: Move to repository once all classes are refactored
abstract final class UserConverter { abstract final class UserConverter {
/// Base user dto used where the complete user object is not required /// Base user dto used where the complete user object is not required
static UserDto fromSimpleUserDto(UserResponseDto dto) => UserDto( static UserDto fromSimpleUserDto(UserResponseDto dto) => UserDto(

View File

@ -236,6 +236,7 @@ class SearchFilter {
String? context; String? context;
String? filename; String? filename;
String? description; String? description;
String? language;
Set<Person> people; Set<Person> people;
SearchLocationFilter location; SearchLocationFilter location;
SearchCameraFilter camera; SearchCameraFilter camera;
@ -249,6 +250,7 @@ class SearchFilter {
this.context, this.context,
this.filename, this.filename,
this.description, this.description,
this.language,
required this.people, required this.people,
required this.location, required this.location,
required this.camera, required this.camera,
@ -279,6 +281,7 @@ class SearchFilter {
String? context, String? context,
String? filename, String? filename,
String? description, String? description,
String? language,
Set<Person>? people, Set<Person>? people,
SearchLocationFilter? location, SearchLocationFilter? location,
SearchCameraFilter? camera, SearchCameraFilter? camera,
@ -290,6 +293,7 @@ class SearchFilter {
context: context ?? this.context, context: context ?? this.context,
filename: filename ?? this.filename, filename: filename ?? this.filename,
description: description ?? this.description, description: description ?? this.description,
language: language ?? this.language,
people: people ?? this.people, people: people ?? this.people,
location: location ?? this.location, location: location ?? this.location,
camera: camera ?? this.camera, camera: camera ?? this.camera,
@ -301,7 +305,7 @@ class SearchFilter {
@override @override
String toString() { String toString() {
return 'SearchFilter(context: $context, filename: $filename, description: $description, people: $people, location: $location, camera: $camera, date: $date, display: $display, mediaType: $mediaType)'; return 'SearchFilter(context: $context, filename: $filename, description: $description, language: $language, people: $people, location: $location, camera: $camera, date: $date, display: $display, mediaType: $mediaType)';
} }
@override @override
@ -311,6 +315,7 @@ class SearchFilter {
return other.context == context && return other.context == context &&
other.filename == filename && other.filename == filename &&
other.description == description && other.description == description &&
other.language == language &&
other.people == people && other.people == people &&
other.location == location && other.location == location &&
other.camera == camera && other.camera == camera &&
@ -324,6 +329,7 @@ class SearchFilter {
return context.hashCode ^ return context.hashCode ^
filename.hashCode ^ filename.hashCode ^
description.hashCode ^ description.hashCode ^
language.hashCode ^
people.hashCode ^ people.hashCode ^
location.hashCode ^ location.hashCode ^
camera.hashCode ^ camera.hashCode ^

View File

@ -263,10 +263,6 @@ class GalleryViewerPage extends HookConsumerWidget {
PhotoViewGalleryPageOptions buildAsset(BuildContext context, int index) { PhotoViewGalleryPageOptions buildAsset(BuildContext context, int index) {
var newAsset = loadAsset(index); var newAsset = loadAsset(index);
WidgetsBinding.instance.addPostFrameCallback((_) {
ref.read(currentAssetProvider.notifier).set(newAsset);
});
final stackId = newAsset.stackId; final stackId = newAsset.stackId;
if (stackId != null && currentIndex.value == index) { if (stackId != null && currentIndex.value == index) {
final stackElements = final stackElements =

View File

@ -44,6 +44,10 @@ class NativeVideoViewerPage extends HookConsumerWidget {
final lastVideoPosition = useRef(-1); final lastVideoPosition = useRef(-1);
final isBuffering = useRef(false); final isBuffering = useRef(false);
// Used to track whether the video should play when the app
// is brought back to the foreground
final shouldPlayOnForeground = useRef(true);
// When a video is opened through the timeline, `isCurrent` will immediately be true. // When a video is opened through the timeline, `isCurrent` will immediately be true.
// When swiping from video A to video B, `isCurrent` will initially be true for video A and false for video B. // When swiping from video A to video B, `isCurrent` will initially be true for video A and false for video B.
// If the swipe is completed, `isCurrent` will be true for video B after a delay. // If the swipe is completed, `isCurrent` will be true for video B after a delay.
@ -368,6 +372,20 @@ class NativeVideoViewerPage extends HookConsumerWidget {
const [], const [],
); );
useOnAppLifecycleStateChange((_, state) async {
if (state == AppLifecycleState.resumed && shouldPlayOnForeground.value) {
controller.value?.play();
} else if (state == AppLifecycleState.paused) {
final videoPlaying = await controller.value?.isPlaying();
if (videoPlaying ?? true) {
shouldPlayOnForeground.value = true;
controller.value?.pause();
} else {
shouldPlayOnForeground.value = false;
}
}
});
return Stack( return Stack(
children: [ children: [
// This remains under the video to avoid flickering // This remains under the video to avoid flickering

View File

@ -48,6 +48,8 @@ class SearchPage extends HookConsumerWidget {
isFavorite: false, isFavorite: false,
), ),
mediaType: prefilter?.mediaType ?? AssetType.other, mediaType: prefilter?.mediaType ?? AssetType.other,
language:
"${context.locale.languageCode}-${context.locale.countryCode}",
), ),
); );

View File

@ -71,8 +71,13 @@ class AssetRepository extends DatabaseRepository implements IAssetRepository {
Future<List<Asset>> getAllByRemoteId( Future<List<Asset>> getAllByRemoteId(
Iterable<String> ids, { Iterable<String> ids, {
AssetState? state, AssetState? state,
}) => }) async {
_getAllByRemoteIdImpl(ids, state).findAll(); if (ids.isEmpty) {
return [];
}
return _getAllByRemoteIdImpl(ids, state).findAll();
}
QueryBuilder<Asset, Asset, QAfterFilterCondition> _getAllByRemoteIdImpl( QueryBuilder<Asset, Asset, QAfterFilterCondition> _getAllByRemoteIdImpl(
Iterable<String> ids, Iterable<String> ids,

View File

@ -1,5 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -389,10 +388,7 @@ class AssetService {
} }
Future<double> getAspectRatio(Asset asset) async { Future<double> getAspectRatio(Asset asset) async {
// platform_manager always returns 0 for orientation on iOS, so only prefer it on Android if (asset.isRemote) {
if (asset.isLocal && Platform.isAndroid) {
await asset.localAsync;
} else if (asset.isRemote) {
asset = await loadExif(asset); asset = await loadExif(asset);
} else if (asset.isLocal) { } else if (asset.isLocal) {
await asset.localAsync; await asset.localAsync;

View File

@ -60,6 +60,7 @@ class SearchService {
response = await _apiService.searchApi.searchSmart( response = await _apiService.searchApi.searchSmart(
SmartSearchDto( SmartSearchDto(
query: filter.context!, query: filter.context!,
language: filter.language,
country: filter.location.country, country: filter.location.country,
state: filter.location.state, state: filter.location.state,
city: filter.location.city, city: filter.location.city,

View File

@ -95,6 +95,11 @@ class BottomGalleryBar extends ConsumerWidget {
totalAssets.value -= 1; totalAssets.value -= 1;
} }
if (isDeleted) {
ref
.read(currentAssetProvider.notifier)
.set(renderList.loadAsset(assetIndex.value));
}
return isDeleted; return isDeleted;
} }

View File

@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/services/api.service.dart'; import 'package:immich_mobile/services/api.service.dart';

View File

@ -14,3 +14,6 @@ create_splash:
build_release_android: build_release_android:
flutter build appbundle flutter build appbundle
migrations:
dart run drift_dev make-migrations

View File

@ -3,7 +3,7 @@ Immich API
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 1.130.3 - API version: 1.131.3
- Generator version: 7.8.0 - Generator version: 7.8.0
- Build package: org.openapitools.codegen.languages.DartClientCodegen - Build package: org.openapitools.codegen.languages.DartClientCodegen
@ -438,6 +438,7 @@ Class | Method | HTTP request | Description
- [SystemConfigDto](doc//SystemConfigDto.md) - [SystemConfigDto](doc//SystemConfigDto.md)
- [SystemConfigFFmpegDto](doc//SystemConfigFFmpegDto.md) - [SystemConfigFFmpegDto](doc//SystemConfigFFmpegDto.md)
- [SystemConfigFacesDto](doc//SystemConfigFacesDto.md) - [SystemConfigFacesDto](doc//SystemConfigFacesDto.md)
- [SystemConfigGeneratedFullsizeImageDto](doc//SystemConfigGeneratedFullsizeImageDto.md)
- [SystemConfigGeneratedImageDto](doc//SystemConfigGeneratedImageDto.md) - [SystemConfigGeneratedImageDto](doc//SystemConfigGeneratedImageDto.md)
- [SystemConfigImageDto](doc//SystemConfigImageDto.md) - [SystemConfigImageDto](doc//SystemConfigImageDto.md)
- [SystemConfigJobDto](doc//SystemConfigJobDto.md) - [SystemConfigJobDto](doc//SystemConfigJobDto.md)

View File

@ -245,6 +245,7 @@ part 'model/system_config_backups_dto.dart';
part 'model/system_config_dto.dart'; part 'model/system_config_dto.dart';
part 'model/system_config_f_fmpeg_dto.dart'; part 'model/system_config_f_fmpeg_dto.dart';
part 'model/system_config_faces_dto.dart'; part 'model/system_config_faces_dto.dart';
part 'model/system_config_generated_fullsize_image_dto.dart';
part 'model/system_config_generated_image_dto.dart'; part 'model/system_config_generated_image_dto.dart';
part 'model/system_config_image_dto.dart'; part 'model/system_config_image_dto.dart';
part 'model/system_config_job_dto.dart'; part 'model/system_config_job_dto.dart';

View File

@ -546,6 +546,8 @@ class ApiClient {
return SystemConfigFFmpegDto.fromJson(value); return SystemConfigFFmpegDto.fromJson(value);
case 'SystemConfigFacesDto': case 'SystemConfigFacesDto':
return SystemConfigFacesDto.fromJson(value); return SystemConfigFacesDto.fromJson(value);
case 'SystemConfigGeneratedFullsizeImageDto':
return SystemConfigGeneratedFullsizeImageDto.fromJson(value);
case 'SystemConfigGeneratedImageDto': case 'SystemConfigGeneratedImageDto':
return SystemConfigGeneratedImageDto.fromJson(value); return SystemConfigGeneratedImageDto.fromJson(value);
case 'SystemConfigImageDto': case 'SystemConfigImageDto':

View File

@ -23,11 +23,13 @@ class AssetMediaSize {
String toJson() => value; String toJson() => value;
static const fullsize = AssetMediaSize._(r'fullsize');
static const preview = AssetMediaSize._(r'preview'); static const preview = AssetMediaSize._(r'preview');
static const thumbnail = AssetMediaSize._(r'thumbnail'); static const thumbnail = AssetMediaSize._(r'thumbnail');
/// List of all possible values in this [enum][AssetMediaSize]. /// List of all possible values in this [enum][AssetMediaSize].
static const values = <AssetMediaSize>[ static const values = <AssetMediaSize>[
fullsize,
preview, preview,
thumbnail, thumbnail,
]; ];
@ -68,6 +70,7 @@ class AssetMediaSizeTypeTransformer {
AssetMediaSize? decode(dynamic data, {bool allowNull = true}) { AssetMediaSize? decode(dynamic data, {bool allowNull = true}) {
if (data != null) { if (data != null) {
switch (data) { switch (data) {
case r'fullsize': return AssetMediaSize.fullsize;
case r'preview': return AssetMediaSize.preview; case r'preview': return AssetMediaSize.preview;
case r'thumbnail': return AssetMediaSize.thumbnail; case r'thumbnail': return AssetMediaSize.thumbnail;
default: default:

View File

@ -24,6 +24,7 @@ class PathType {
String toJson() => value; String toJson() => value;
static const original = PathType._(r'original'); static const original = PathType._(r'original');
static const fullsize = PathType._(r'fullsize');
static const preview = PathType._(r'preview'); static const preview = PathType._(r'preview');
static const thumbnail = PathType._(r'thumbnail'); static const thumbnail = PathType._(r'thumbnail');
static const encodedVideo = PathType._(r'encoded_video'); static const encodedVideo = PathType._(r'encoded_video');
@ -34,6 +35,7 @@ class PathType {
/// List of all possible values in this [enum][PathType]. /// List of all possible values in this [enum][PathType].
static const values = <PathType>[ static const values = <PathType>[
original, original,
fullsize,
preview, preview,
thumbnail, thumbnail,
encodedVideo, encodedVideo,
@ -79,6 +81,7 @@ class PathTypeTypeTransformer {
if (data != null) { if (data != null) {
switch (data) { switch (data) {
case r'original': return PathType.original; case r'original': return PathType.original;
case r'fullsize': return PathType.fullsize;
case r'preview': return PathType.preview; case r'preview': return PathType.preview;
case r'thumbnail': return PathType.thumbnail; case r'thumbnail': return PathType.thumbnail;
case r'encoded_video': return PathType.encodedVideo; case r'encoded_video': return PathType.encodedVideo;

View File

@ -25,6 +25,7 @@ class SmartSearchDto {
this.isNotInAlbum, this.isNotInAlbum,
this.isOffline, this.isOffline,
this.isVisible, this.isVisible,
this.language,
this.lensModel, this.lensModel,
this.libraryId, this.libraryId,
this.make, this.make,
@ -132,6 +133,14 @@ class SmartSearchDto {
/// ///
bool? isVisible; bool? isVisible;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? language;
String? lensModel; String? lensModel;
String? libraryId; String? libraryId;
@ -271,6 +280,7 @@ class SmartSearchDto {
other.isNotInAlbum == isNotInAlbum && other.isNotInAlbum == isNotInAlbum &&
other.isOffline == isOffline && other.isOffline == isOffline &&
other.isVisible == isVisible && other.isVisible == isVisible &&
other.language == language &&
other.lensModel == lensModel && other.lensModel == lensModel &&
other.libraryId == libraryId && other.libraryId == libraryId &&
other.make == make && other.make == make &&
@ -308,6 +318,7 @@ class SmartSearchDto {
(isNotInAlbum == null ? 0 : isNotInAlbum!.hashCode) + (isNotInAlbum == null ? 0 : isNotInAlbum!.hashCode) +
(isOffline == null ? 0 : isOffline!.hashCode) + (isOffline == null ? 0 : isOffline!.hashCode) +
(isVisible == null ? 0 : isVisible!.hashCode) + (isVisible == null ? 0 : isVisible!.hashCode) +
(language == null ? 0 : language!.hashCode) +
(lensModel == null ? 0 : lensModel!.hashCode) + (lensModel == null ? 0 : lensModel!.hashCode) +
(libraryId == null ? 0 : libraryId!.hashCode) + (libraryId == null ? 0 : libraryId!.hashCode) +
(make == null ? 0 : make!.hashCode) + (make == null ? 0 : make!.hashCode) +
@ -331,7 +342,7 @@ class SmartSearchDto {
(withExif == null ? 0 : withExif!.hashCode); (withExif == null ? 0 : withExif!.hashCode);
@override @override
String toString() => 'SmartSearchDto[city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isArchived=$isArchived, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, page=$page, personIds=$personIds, query=$query, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif]'; String toString() => 'SmartSearchDto[city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isArchived=$isArchived, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isVisible=$isVisible, language=$language, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, page=$page, personIds=$personIds, query=$query, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@ -395,6 +406,11 @@ class SmartSearchDto {
} else { } else {
// json[r'isVisible'] = null; // json[r'isVisible'] = null;
} }
if (this.language != null) {
json[r'language'] = this.language;
} else {
// json[r'language'] = null;
}
if (this.lensModel != null) { if (this.lensModel != null) {
json[r'lensModel'] = this.lensModel; json[r'lensModel'] = this.lensModel;
} else { } else {
@ -508,6 +524,7 @@ class SmartSearchDto {
isNotInAlbum: mapValueOfType<bool>(json, r'isNotInAlbum'), isNotInAlbum: mapValueOfType<bool>(json, r'isNotInAlbum'),
isOffline: mapValueOfType<bool>(json, r'isOffline'), isOffline: mapValueOfType<bool>(json, r'isOffline'),
isVisible: mapValueOfType<bool>(json, r'isVisible'), isVisible: mapValueOfType<bool>(json, r'isVisible'),
language: mapValueOfType<String>(json, r'language'),
lensModel: mapValueOfType<String>(json, r'lensModel'), lensModel: mapValueOfType<String>(json, r'lensModel'),
libraryId: mapValueOfType<String>(json, r'libraryId'), libraryId: mapValueOfType<String>(json, r'libraryId'),
make: mapValueOfType<String>(json, r'make'), make: mapValueOfType<String>(json, r'make'),

View File

@ -0,0 +1,117 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class SystemConfigGeneratedFullsizeImageDto {
/// Returns a new [SystemConfigGeneratedFullsizeImageDto] instance.
SystemConfigGeneratedFullsizeImageDto({
required this.enabled,
required this.format,
required this.quality,
});
bool enabled;
ImageFormat format;
/// Minimum value: 1
/// Maximum value: 100
int quality;
@override
bool operator ==(Object other) => identical(this, other) || other is SystemConfigGeneratedFullsizeImageDto &&
other.enabled == enabled &&
other.format == format &&
other.quality == quality;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(enabled.hashCode) +
(format.hashCode) +
(quality.hashCode);
@override
String toString() => 'SystemConfigGeneratedFullsizeImageDto[enabled=$enabled, format=$format, quality=$quality]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'enabled'] = this.enabled;
json[r'format'] = this.format;
json[r'quality'] = this.quality;
return json;
}
/// Returns a new [SystemConfigGeneratedFullsizeImageDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static SystemConfigGeneratedFullsizeImageDto? fromJson(dynamic value) {
upgradeDto(value, "SystemConfigGeneratedFullsizeImageDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return SystemConfigGeneratedFullsizeImageDto(
enabled: mapValueOfType<bool>(json, r'enabled')!,
format: ImageFormat.fromJson(json[r'format'])!,
quality: mapValueOfType<int>(json, r'quality')!,
);
}
return null;
}
static List<SystemConfigGeneratedFullsizeImageDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <SystemConfigGeneratedFullsizeImageDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = SystemConfigGeneratedFullsizeImageDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, SystemConfigGeneratedFullsizeImageDto> mapFromJson(dynamic json) {
final map = <String, SystemConfigGeneratedFullsizeImageDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = SystemConfigGeneratedFullsizeImageDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of SystemConfigGeneratedFullsizeImageDto-objects as value to a dart map
static Map<String, List<SystemConfigGeneratedFullsizeImageDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<SystemConfigGeneratedFullsizeImageDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = SystemConfigGeneratedFullsizeImageDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'enabled',
'format',
'quality',
};
}

View File

@ -15,6 +15,7 @@ class SystemConfigImageDto {
SystemConfigImageDto({ SystemConfigImageDto({
required this.colorspace, required this.colorspace,
required this.extractEmbedded, required this.extractEmbedded,
required this.fullsize,
required this.preview, required this.preview,
required this.thumbnail, required this.thumbnail,
}); });
@ -23,6 +24,8 @@ class SystemConfigImageDto {
bool extractEmbedded; bool extractEmbedded;
SystemConfigGeneratedFullsizeImageDto fullsize;
SystemConfigGeneratedImageDto preview; SystemConfigGeneratedImageDto preview;
SystemConfigGeneratedImageDto thumbnail; SystemConfigGeneratedImageDto thumbnail;
@ -31,6 +34,7 @@ class SystemConfigImageDto {
bool operator ==(Object other) => identical(this, other) || other is SystemConfigImageDto && bool operator ==(Object other) => identical(this, other) || other is SystemConfigImageDto &&
other.colorspace == colorspace && other.colorspace == colorspace &&
other.extractEmbedded == extractEmbedded && other.extractEmbedded == extractEmbedded &&
other.fullsize == fullsize &&
other.preview == preview && other.preview == preview &&
other.thumbnail == thumbnail; other.thumbnail == thumbnail;
@ -39,16 +43,18 @@ class SystemConfigImageDto {
// ignore: unnecessary_parenthesis // ignore: unnecessary_parenthesis
(colorspace.hashCode) + (colorspace.hashCode) +
(extractEmbedded.hashCode) + (extractEmbedded.hashCode) +
(fullsize.hashCode) +
(preview.hashCode) + (preview.hashCode) +
(thumbnail.hashCode); (thumbnail.hashCode);
@override @override
String toString() => 'SystemConfigImageDto[colorspace=$colorspace, extractEmbedded=$extractEmbedded, preview=$preview, thumbnail=$thumbnail]'; String toString() => 'SystemConfigImageDto[colorspace=$colorspace, extractEmbedded=$extractEmbedded, fullsize=$fullsize, preview=$preview, thumbnail=$thumbnail]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
json[r'colorspace'] = this.colorspace; json[r'colorspace'] = this.colorspace;
json[r'extractEmbedded'] = this.extractEmbedded; json[r'extractEmbedded'] = this.extractEmbedded;
json[r'fullsize'] = this.fullsize;
json[r'preview'] = this.preview; json[r'preview'] = this.preview;
json[r'thumbnail'] = this.thumbnail; json[r'thumbnail'] = this.thumbnail;
return json; return json;
@ -65,6 +71,7 @@ class SystemConfigImageDto {
return SystemConfigImageDto( return SystemConfigImageDto(
colorspace: Colorspace.fromJson(json[r'colorspace'])!, colorspace: Colorspace.fromJson(json[r'colorspace'])!,
extractEmbedded: mapValueOfType<bool>(json, r'extractEmbedded')!, extractEmbedded: mapValueOfType<bool>(json, r'extractEmbedded')!,
fullsize: SystemConfigGeneratedFullsizeImageDto.fromJson(json[r'fullsize'])!,
preview: SystemConfigGeneratedImageDto.fromJson(json[r'preview'])!, preview: SystemConfigGeneratedImageDto.fromJson(json[r'preview'])!,
thumbnail: SystemConfigGeneratedImageDto.fromJson(json[r'thumbnail'])!, thumbnail: SystemConfigGeneratedImageDto.fromJson(json[r'thumbnail'])!,
); );
@ -116,6 +123,7 @@ class SystemConfigImageDto {
static const requiredKeys = <String>{ static const requiredKeys = <String>{
'colorspace', 'colorspace',
'extractEmbedded', 'extractEmbedded',
'fullsize',
'preview', 'preview',
'thumbnail', 'thumbnail',
}; };

View File

@ -206,6 +206,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.4.0"
charcode:
dependency: transitive
description:
name: charcode
sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a
url: "https://pub.dev"
source: hosted
version: "1.4.0"
checked_yaml: checked_yaml:
dependency: transitive dependency: transitive
description: description:
@ -382,6 +390,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.0.2" version: "7.0.2"
drift:
dependency: "direct main"
description:
name: drift
sha256: "14a61af39d4584faf1d73b5b35e4b758a43008cf4c0fdb0576ec8e7032c0d9a5"
url: "https://pub.dev"
source: hosted
version: "2.26.0"
drift_dev:
dependency: "direct dev"
description:
name: drift_dev
sha256: "0d3f8b33b76cf1c6a82ee34d9511c40957549c4674b8f1688609e6d6c7306588"
url: "https://pub.dev"
source: hosted
version: "2.26.0"
drift_flutter:
dependency: "direct main"
description:
name: drift_flutter
sha256: "0cadbf3b8733409a6cf61d18ba2e94e149df81df7de26f48ae0695b48fd71922"
url: "https://pub.dev"
source: hosted
version: "0.2.4"
dynamic_color: dynamic_color:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1288,6 +1320,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.0" version: "1.5.0"
recase:
dependency: transitive
description:
name: recase
sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213
url: "https://pub.dev"
source: hosted
version: "4.1.0"
riverpod: riverpod:
dependency: transitive dependency: transitive
description: description:
@ -1549,6 +1589,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.4.0"
sqlite3:
dependency: transitive
description:
name: sqlite3
sha256: "310af39c40dd0bb2058538333c9d9840a2725ae0b9f77e4fd09ad6696aa8f66e"
url: "https://pub.dev"
source: hosted
version: "2.7.5"
sqlite3_flutter_libs:
dependency: transitive
description:
name: sqlite3_flutter_libs
sha256: "7adb4cc96dc08648a5eb1d80a7619070796ca6db03901ff2b6dcb15ee30468f3"
url: "https://pub.dev"
source: hosted
version: "0.5.31"
sqlparser:
dependency: transitive
description:
name: sqlparser
sha256: "27dd0a9f0c02e22ac0eb42a23df9ea079ce69b52bb4a3b478d64e0ef34a263ee"
url: "https://pub.dev"
source: hosted
version: "0.41.0"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:

View File

@ -2,7 +2,7 @@ name: immich_mobile
description: Immich - selfhosted backup media file on mobile phone description: Immich - selfhosted backup media file on mobile phone
publish_to: 'none' publish_to: 'none'
version: 1.130.3+191 version: 1.131.3+193
environment: environment:
sdk: '>=3.3.0 <4.0.0' sdk: '>=3.3.0 <4.0.0'
@ -73,6 +73,9 @@ dependencies:
isar_flutter_libs: # contains Isar Core isar_flutter_libs: # contains Isar Core
version: *isar_version version: *isar_version
hosted: https://pub.isar-community.dev/ hosted: https://pub.isar-community.dev/
# DB
drift: ^2.23.1
drift_flutter: ^0.2.4
dependency_overrides: dependency_overrides:
analyzer: ^6.0.0 analyzer: ^6.0.0
@ -99,6 +102,8 @@ dev_dependencies:
immich_mobile_immich_lint: immich_mobile_immich_lint:
path: './immich_lint' path: './immich_lint'
fake_async: ^1.3.1 fake_async: ^1.3.1
# Drift generator
drift_dev: ^2.23.1
flutter: flutter:
uses-material-design: true uses-material-design: true

View File

@ -1,4 +1,5 @@
import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
abstract final class UserStub { abstract final class UserStub {
const UserStub._(); const UserStub._();

View File

@ -7656,7 +7656,7 @@
"info": { "info": {
"title": "Immich", "title": "Immich",
"description": "Immich API", "description": "Immich API",
"version": "1.130.3", "version": "1.131.3",
"contact": {} "contact": {}
}, },
"tags": [], "tags": [],
@ -8660,6 +8660,7 @@
}, },
"AssetMediaSize": { "AssetMediaSize": {
"enum": [ "enum": [
"fullsize",
"preview", "preview",
"thumbnail" "thumbnail"
], ],
@ -10442,6 +10443,7 @@
"PathType": { "PathType": {
"enum": [ "enum": [
"original", "original",
"fullsize",
"preview", "preview",
"thumbnail", "thumbnail",
"encoded_video", "encoded_video",
@ -11853,6 +11855,9 @@
"isVisible": { "isVisible": {
"type": "boolean" "type": "boolean"
}, },
"language": {
"type": "string"
},
"lensModel": { "lensModel": {
"nullable": true, "nullable": true,
"type": "string" "type": "string"
@ -12612,6 +12617,31 @@
], ],
"type": "object" "type": "object"
}, },
"SystemConfigGeneratedFullsizeImageDto": {
"properties": {
"enabled": {
"type": "boolean"
},
"format": {
"allOf": [
{
"$ref": "#/components/schemas/ImageFormat"
}
]
},
"quality": {
"maximum": 100,
"minimum": 1,
"type": "integer"
}
},
"required": [
"enabled",
"format",
"quality"
],
"type": "object"
},
"SystemConfigGeneratedImageDto": { "SystemConfigGeneratedImageDto": {
"properties": { "properties": {
"format": { "format": {
@ -12650,6 +12680,9 @@
"extractEmbedded": { "extractEmbedded": {
"type": "boolean" "type": "boolean"
}, },
"fullsize": {
"$ref": "#/components/schemas/SystemConfigGeneratedFullsizeImageDto"
},
"preview": { "preview": {
"$ref": "#/components/schemas/SystemConfigGeneratedImageDto" "$ref": "#/components/schemas/SystemConfigGeneratedImageDto"
}, },
@ -12660,6 +12693,7 @@
"required": [ "required": [
"colorspace", "colorspace",
"extractEmbedded", "extractEmbedded",
"fullsize",
"preview", "preview",
"thumbnail" "thumbnail"
], ],

View File

@ -1,18 +1,18 @@
{ {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.130.3", "version": "1.131.3",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.130.3", "version": "1.131.3",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"@oazapfts/runtime": "^1.0.2" "@oazapfts/runtime": "^1.0.2"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.13.10", "@types/node": "^22.13.14",
"typescript": "^5.3.3" "typescript": "^5.3.3"
} }
}, },
@ -23,9 +23,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "22.13.10", "version": "22.13.15",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.15.tgz",
"integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", "integrity": "sha512-imAbQEEbVni6i6h6Bd5xkCRwLqFc8hihCsi2GbtDoAtUcAFQ6Zs4pFXTZUUbroTkXdImczWM9AI8eZUuybXE3w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.130.3", "version": "1.131.3",
"description": "Auto-generated TypeScript SDK for the Immich API", "description": "Auto-generated TypeScript SDK for the Immich API",
"type": "module", "type": "module",
"main": "./build/index.js", "main": "./build/index.js",
@ -19,7 +19,7 @@
"@oazapfts/runtime": "^1.0.2" "@oazapfts/runtime": "^1.0.2"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.13.10", "@types/node": "^22.13.14",
"typescript": "^5.3.3" "typescript": "^5.3.3"
}, },
"repository": { "repository": {

View File

@ -1,6 +1,6 @@
/** /**
* Immich * Immich
* 1.130.3 * 1.131.3
* DO NOT MODIFY - This file has been generated using oazapfts. * DO NOT MODIFY - This file has been generated using oazapfts.
* See https://www.npmjs.com/package/oazapfts * See https://www.npmjs.com/package/oazapfts
*/ */
@ -924,6 +924,7 @@ export type SmartSearchDto = {
isNotInAlbum?: boolean; isNotInAlbum?: boolean;
isOffline?: boolean; isOffline?: boolean;
isVisible?: boolean; isVisible?: boolean;
language?: string;
lensModel?: string | null; lensModel?: string | null;
libraryId?: string | null; libraryId?: string | null;
make?: string; make?: string;
@ -1178,6 +1179,11 @@ export type SystemConfigFFmpegDto = {
transcode: TranscodePolicy; transcode: TranscodePolicy;
twoPass: boolean; twoPass: boolean;
}; };
export type SystemConfigGeneratedFullsizeImageDto = {
enabled: boolean;
format: ImageFormat;
quality: number;
};
export type SystemConfigGeneratedImageDto = { export type SystemConfigGeneratedImageDto = {
format: ImageFormat; format: ImageFormat;
quality: number; quality: number;
@ -1186,6 +1192,7 @@ export type SystemConfigGeneratedImageDto = {
export type SystemConfigImageDto = { export type SystemConfigImageDto = {
colorspace: Colorspace; colorspace: Colorspace;
extractEmbedded: boolean; extractEmbedded: boolean;
fullsize: SystemConfigGeneratedFullsizeImageDto;
preview: SystemConfigGeneratedImageDto; preview: SystemConfigGeneratedImageDto;
thumbnail: SystemConfigGeneratedImageDto; thumbnail: SystemConfigGeneratedImageDto;
}; };
@ -3572,6 +3579,7 @@ export enum AssetJobName {
TranscodeVideo = "transcode-video" TranscodeVideo = "transcode-video"
} }
export enum AssetMediaSize { export enum AssetMediaSize {
Fullsize = "fullsize",
Preview = "preview", Preview = "preview",
Thumbnail = "thumbnail" Thumbnail = "thumbnail"
} }
@ -3621,6 +3629,7 @@ export enum PathEntityType {
} }
export enum PathType { export enum PathType {
Original = "original", Original = "original",
Fullsize = "fullsize",
Preview = "preview", Preview = "preview",
Thumbnail = "thumbnail", Thumbnail = "thumbnail",
EncodedVideo = "encoded_video", EncodedVideo = "encoded_video",

View File

@ -1,39 +1,29 @@
import { FlatCompat } from '@eslint/eslintrc';
import js from '@eslint/js'; import js from '@eslint/js';
import typescriptEslint from '@typescript-eslint/eslint-plugin'; import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
import tsParser from '@typescript-eslint/parser'; import eslintPluginUnicorn from 'eslint-plugin-unicorn';
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 [ export default typescriptEslint.config([
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: tsParser, parser: typescriptEslint.parser,
ecmaVersion: 5, ecmaVersion: 5,
sourceType: 'module', sourceType: 'module',
@ -77,6 +67,14 @@ export default [
], ],
}, },
], ],
'@typescript-eslint/no-unused-vars': [
'warn',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
}, },
}, },
]; ]);

1183
server/package-lock.json generated

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