Compare commits
97 Commits
fix/map-pa
...
pnpm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
345e14921c | ||
|
|
3751f8bc57 | ||
|
|
88b8afb8d6 | ||
|
|
2e13543d5d | ||
|
|
bcfc967d77 | ||
|
|
7d0e8f50f7 | ||
|
|
c759233d8c | ||
|
|
bfe32c2bb9 | ||
|
|
6c7b2e4b5c | ||
|
|
7edbeb2ed6 | ||
|
|
4e59a55c1d | ||
|
|
c2d7337d12 | ||
|
|
c1b82bed9b | ||
|
|
9ca31abae9 | ||
|
|
ebcf133bea | ||
|
|
1923f1a887 | ||
|
|
ce14324c97 | ||
|
|
6a309129b7 | ||
|
|
bcb1bf4692 | ||
|
|
7f89999abe | ||
|
|
813186e618 | ||
|
|
20d9204ada | ||
|
|
3a9e79a452 | ||
|
|
03966146fe | ||
|
|
ecc58a8971 | ||
|
|
c705a7b280 | ||
|
|
ef278b4fb0 | ||
|
|
4cd633dc68 | ||
|
|
a18c6fa910 | ||
|
|
90aa0dc14d | ||
|
|
ce8c80dad0 | ||
|
|
81eb98d4e5 | ||
|
|
2b03802e9c | ||
|
|
484311e9bb | ||
|
|
366539bc4c | ||
|
|
69b1331026 | ||
|
|
af30d97668 | ||
|
|
9b047d30e4 | ||
|
|
6a5597b36b | ||
|
|
c10b795e99 | ||
|
|
b606d4fe73 | ||
|
|
4c2ad44303 | ||
|
|
698d3004b4 | ||
|
|
fe4d6edbdc | ||
|
|
798debfde3 | ||
|
|
6563fa608a | ||
|
|
1a90fc8e58 | ||
|
|
c707f9cef4 | ||
|
|
6fda863c08 | ||
|
|
373b654156 | ||
|
|
a5d84ba552 | ||
|
|
1dc8fa2979 | ||
|
|
0426699f13 | ||
|
|
8154ec29df | ||
|
|
3024cd343b | ||
|
|
0b44d4b6f2 | ||
|
|
a04c6ed80d | ||
|
|
1c50e19894 | ||
|
|
e61d7f2616 | ||
|
|
a6b0869714 | ||
|
|
9c25b8ba7d | ||
|
|
3c72f489d8 | ||
|
|
1f2c779b36 | ||
|
|
5c74f634b7 | ||
|
|
ecc99bfd16 | ||
|
|
ff4d70e351 | ||
|
|
42c2389eb5 | ||
|
|
33c9f88ba4 | ||
|
|
11c469907f | ||
|
|
7c43e6c3c8 | ||
|
|
00aa385972 | ||
|
|
a5ed453929 | ||
|
|
dd8969cb7d | ||
|
|
bce4f93c90 | ||
|
|
a4c0dc5007 | ||
|
|
d233a7d97a | ||
|
|
5cdbb65d28 | ||
|
|
3434544864 | ||
|
|
269bf4b344 | ||
|
|
f9435a538b | ||
|
|
10e2ec2841 | ||
|
|
fe91b44ab9 | ||
|
|
747a72120e | ||
|
|
910661e75c | ||
|
|
c8a135a7ae | ||
|
|
08d1cf5bde | ||
|
|
3e62497fd0 | ||
|
|
a1bc862a32 | ||
|
|
75bf3aa1be | ||
|
|
38e68d16f9 | ||
|
|
caf11fbb96 | ||
|
|
f99c6feac5 | ||
|
|
5122512f19 | ||
|
|
49ed212af8 | ||
|
|
e29103b69f | ||
|
|
14b771d7c7 | ||
|
|
07aa51638c |
@@ -55,7 +55,7 @@
|
|||||||
"userEnvProbe": "loginInteractiveShell",
|
"userEnvProbe": "loginInteractiveShell",
|
||||||
"remoteEnv": {
|
"remoteEnv": {
|
||||||
// The location where your uploaded files are stored
|
// The location where your uploaded files are stored
|
||||||
"UPLOAD_LOCATION": "${localEnv:UPLOAD_LOCATION:upload-devcontainer-volume}",
|
"UPLOAD_LOCATION": "${localEnv:UPLOAD_LOCATION:./library}",
|
||||||
// Connection secret for postgres. You should change it to a random password
|
// Connection secret for postgres. You should change it to a random password
|
||||||
// Please use only the characters `A-Za-z0-9`, without special characters or spaces
|
// Please use only the characters `A-Za-z0-9`, without special characters or spaces
|
||||||
"DB_PASSWORD": "${localEnv:DB_PASSWORD:postgres}",
|
"DB_PASSWORD": "${localEnv:DB_PASSWORD:postgres}",
|
||||||
|
|||||||
@@ -51,14 +51,19 @@ fix_permissions() {
|
|||||||
|
|
||||||
run_cmd sudo find "${IMMICH_WORKSPACE}/server/upload" -not -path "${IMMICH_WORKSPACE}/server/upload/postgres/*" -not -path "${IMMICH_WORKSPACE}/server/upload/postgres" -exec chown node {} +
|
run_cmd sudo find "${IMMICH_WORKSPACE}/server/upload" -not -path "${IMMICH_WORKSPACE}/server/upload/postgres/*" -not -path "${IMMICH_WORKSPACE}/server/upload/postgres" -exec chown node {} +
|
||||||
|
|
||||||
run_cmd sudo chown node -R "${IMMICH_WORKSPACE}/.vscode" \
|
# Change ownership for directories that exist
|
||||||
|
for dir in "${IMMICH_WORKSPACE}/.vscode" \
|
||||||
"${IMMICH_WORKSPACE}/cli/node_modules" \
|
"${IMMICH_WORKSPACE}/cli/node_modules" \
|
||||||
"${IMMICH_WORKSPACE}/e2e/node_modules" \
|
"${IMMICH_WORKSPACE}/e2e/node_modules" \
|
||||||
"${IMMICH_WORKSPACE}/open-api/typescript-sdk/node_modules" \
|
"${IMMICH_WORKSPACE}/open-api/typescript-sdk/node_modules" \
|
||||||
"${IMMICH_WORKSPACE}/server/node_modules" \
|
"${IMMICH_WORKSPACE}/server/node_modules" \
|
||||||
"${IMMICH_WORKSPACE}/server/dist" \
|
"${IMMICH_WORKSPACE}/server/dist" \
|
||||||
"${IMMICH_WORKSPACE}/web/node_modules" \
|
"${IMMICH_WORKSPACE}/web/node_modules" \
|
||||||
"${IMMICH_WORKSPACE}/web/dist"
|
"${IMMICH_WORKSPACE}/web/dist"; do
|
||||||
|
if [ -d "$dir" ]; then
|
||||||
|
run_cmd sudo chown node -R "$dir"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
log ""
|
log ""
|
||||||
}
|
}
|
||||||
@@ -68,10 +73,10 @@ install_dependencies() {
|
|||||||
log "Installing dependencies"
|
log "Installing dependencies"
|
||||||
(
|
(
|
||||||
cd "${IMMICH_WORKSPACE}" || exit 1
|
cd "${IMMICH_WORKSPACE}" || exit 1
|
||||||
run_cmd make install-server
|
run_cmd make ci-server
|
||||||
run_cmd make install-sdk
|
run_cmd make ci-sdk
|
||||||
run_cmd make build-sdk
|
run_cmd make build-sdk
|
||||||
run_cmd make install-web
|
run_cmd make ci-web
|
||||||
)
|
)
|
||||||
log ""
|
log ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ services:
|
|||||||
build:
|
build:
|
||||||
target: dev-container-server
|
target: dev-container-server
|
||||||
env_file: !reset []
|
env_file: !reset []
|
||||||
|
hostname: immich-dev
|
||||||
environment:
|
environment:
|
||||||
- IMMICH_SERVER_URL=http://127.0.0.1:2283/
|
- IMMICH_SERVER_URL=http://127.0.0.1:2283/
|
||||||
volumes: !override
|
volumes: !override
|
||||||
@@ -12,8 +13,8 @@ services:
|
|||||||
- open_api_node_modules:/workspaces/immich/open-api/typescript-sdk/node_modules
|
- open_api_node_modules:/workspaces/immich/open-api/typescript-sdk/node_modules
|
||||||
- server_node_modules:/workspaces/immich/server/node_modules
|
- server_node_modules:/workspaces/immich/server/node_modules
|
||||||
- web_node_modules:/workspaces/immich/web/node_modules
|
- web_node_modules:/workspaces/immich/web/node_modules
|
||||||
- ${UPLOAD_LOCATION-./Library}/photos:/workspaces/immich/server/upload
|
- ${UPLOAD_LOCATION:-upload1-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/workspaces/immich/server/upload
|
||||||
- ${UPLOAD_LOCATION-./Library}/photos/upload:/workspaces/immich/server/upload/upload
|
- ${UPLOAD_LOCATION:-upload2-devcontainer-volume}${UPLOAD_LOCATION:+/photos/upload}:/workspaces/immich/server/upload/upload
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
|
||||||
immich-web:
|
immich-web:
|
||||||
@@ -29,8 +30,9 @@ services:
|
|||||||
POSTGRES_USER: ${DB_USERNAME-postgres}
|
POSTGRES_USER: ${DB_USERNAME-postgres}
|
||||||
POSTGRES_DB: ${DB_DATABASE_NAME-immich}
|
POSTGRES_DB: ${DB_DATABASE_NAME-immich}
|
||||||
POSTGRES_INITDB_ARGS: '--data-checksums'
|
POSTGRES_INITDB_ARGS: '--data-checksums'
|
||||||
|
POSTGRES_HOST_AUTH_METHOD: md5
|
||||||
volumes:
|
volumes:
|
||||||
- ${UPLOAD_LOCATION-./Library}/postgres:/var/lib/postgresql/data
|
- ${UPLOAD_LOCATION:-postgres-devcontainer-volume}${UPLOAD_LOCATION:+/postgres}:/var/lib/postgresql/data
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
env_file: !reset []
|
env_file: !reset []
|
||||||
@@ -42,4 +44,6 @@ volumes:
|
|||||||
open_api_node_modules:
|
open_api_node_modules:
|
||||||
server_node_modules:
|
server_node_modules:
|
||||||
web_node_modules:
|
web_node_modules:
|
||||||
upload-devcontainer-volume:
|
upload1-devcontainer-volume:
|
||||||
|
upload2-devcontainer-volume:
|
||||||
|
postgres-devcontainer-volume:
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ design/
|
|||||||
docker/
|
docker/
|
||||||
!docker/scripts
|
!docker/scripts
|
||||||
docs/
|
docs/
|
||||||
|
!docs/package.json
|
||||||
|
!docs/package-lock.json
|
||||||
e2e/
|
e2e/
|
||||||
|
!e2e/package.json
|
||||||
|
!e2e/package-lock.json
|
||||||
fastlane/
|
fastlane/
|
||||||
machine-learning/
|
machine-learning/
|
||||||
misc/
|
misc/
|
||||||
|
|||||||
14
.github/workflows/cli.yml
vendored
14
.github/workflows/cli.yml
vendored
@@ -33,18 +33,22 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
# Setup .npmrc file to publish to npm
|
# Setup .npmrc file to publish to npm
|
||||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './cli/.nvmrc'
|
node-version-file: './cli/.nvmrc'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Prepare SDK
|
- name: Prepare SDK
|
||||||
run: npm ci --prefix ../open-api/typescript-sdk/
|
run: pnpm install --frozen-lockfile
|
||||||
- name: Build SDK
|
- name: Build SDK
|
||||||
run: npm run build --prefix ../open-api/typescript-sdk/
|
run: pnpm --dir ../open-api/typescript-sdk/ build
|
||||||
- run: npm ci
|
- run: pnpm build
|
||||||
- run: npm run build
|
- run: pnpm publish
|
||||||
- run: npm publish
|
|
||||||
if: ${{ github.event_name == 'release' }}
|
if: ${{ github.event_name == 'release' }}
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|||||||
2
.github/workflows/docs-build.yml
vendored
2
.github/workflows/docs-build.yml
vendored
@@ -57,6 +57,8 @@ jobs:
|
|||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './docs/.nvmrc'
|
node-version-file: './docs/.nvmrc'
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: '**/package-lock.json'
|
||||||
|
|
||||||
- name: Run npm install
|
- name: Run npm install
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|||||||
4
.github/workflows/fix-format.yml
vendored
4
.github/workflows/fix-format.yml
vendored
@@ -28,10 +28,14 @@ jobs:
|
|||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
persist-credentials: true
|
persist-credentials: true
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Fix formatting
|
- name: Fix formatting
|
||||||
run: make install-all && make format-all
|
run: make install-all && make format-all
|
||||||
|
|||||||
10
.github/workflows/sdk.yml
vendored
10
.github/workflows/sdk.yml
vendored
@@ -20,16 +20,20 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
# Setup .npmrc file to publish to npm
|
# Setup .npmrc file to publish to npm
|
||||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './open-api/typescript-sdk/.nvmrc'
|
node-version-file: './open-api/typescript-sdk/.nvmrc'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
cache: 'pnpm'
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
- name: Build
|
- name: Build
|
||||||
run: npm run build
|
run: pnpm build
|
||||||
- name: Publish
|
- name: Publish
|
||||||
run: npm publish
|
run: pnpm publish
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|||||||
166
.github/workflows/test.yml
vendored
166
.github/workflows/test.yml
vendored
@@ -80,28 +80,32 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Run npm install
|
- name: Run pnpm install
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: npm run lint
|
run: pnpm lint
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run formatter
|
- name: Run formatter
|
||||||
run: npm run format
|
run: pnpm format
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
run: npm run check
|
run: pnpm check
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run small tests & coverage
|
- name: Run small tests & coverage
|
||||||
run: npm test
|
run: pnpm test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
cli-unit-tests:
|
cli-unit-tests:
|
||||||
@@ -121,32 +125,36 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './cli/.nvmrc'
|
node-version-file: './cli/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Setup typescript-sdk
|
- name: Setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
|
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: npm run lint
|
run: pnpm lint
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run formatter
|
- name: Run formatter
|
||||||
run: npm run format
|
run: pnpm format
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
run: npm run check
|
run: pnpm check
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run unit tests & coverage
|
- name: Run unit tests & coverage
|
||||||
run: npm run test
|
run: pnpm test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
cli-unit-tests-win:
|
cli-unit-tests-win:
|
||||||
@@ -166,25 +174,29 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './cli/.nvmrc'
|
node-version-file: './cli/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Setup typescript-sdk
|
- name: Setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
|
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
# Skip linter & formatter in Windows test.
|
# Skip linter & formatter in Windows test.
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
run: npm run check
|
run: pnpm check
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run unit tests & coverage
|
- name: Run unit tests & coverage
|
||||||
run: npm run test
|
run: pnpm test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
web-lint:
|
web-lint:
|
||||||
@@ -204,28 +216,32 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './web/.nvmrc'
|
node-version-file: './web/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Run setup typescript-sdk
|
- name: Run setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
|
|
||||||
- name: Run npm install
|
- name: Run pnpm install
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: npm run lint:p
|
run: pnpm lint:p
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run formatter
|
- name: Run formatter
|
||||||
run: npm run format
|
run: pnpm format
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run svelte checks
|
- name: Run svelte checks
|
||||||
run: npm run check:svelte
|
run: pnpm check:svelte
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
web-unit-tests:
|
web-unit-tests:
|
||||||
@@ -245,24 +261,28 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './web/.nvmrc'
|
node-version-file: './web/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Run setup typescript-sdk
|
- name: Run setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
|
|
||||||
- name: Run npm install
|
- name: Run pnpm install
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
run: npm run check:typescript
|
run: pnpm run check:typescript
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run unit tests & coverage
|
- name: Run unit tests & coverage
|
||||||
run: npm run test
|
run: pnpm run test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
i18n-tests:
|
i18n-tests:
|
||||||
@@ -278,16 +298,20 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './web/.nvmrc'
|
node-version-file: './web/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm --prefix=web ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Format
|
- name: Format
|
||||||
run: npm --prefix=web run format:i18n
|
run: pnpm --dir=web format:i18n
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||||
@@ -322,30 +346,34 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './e2e/.nvmrc'
|
node-version-file: './e2e/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Run setup typescript-sdk
|
- name: Run setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm run build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: npm run lint
|
run: pnpm lint
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run formatter
|
- name: Run formatter
|
||||||
run: npm run format
|
run: pnpm format
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
run: npm run check
|
run: pnpm check
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
server-medium-tests:
|
server-medium-tests:
|
||||||
@@ -365,16 +393,20 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Run npm install
|
- name: Run pnpm install
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Run medium tests
|
- name: Run medium tests
|
||||||
run: npm run test:medium
|
run: pnpm test:medium
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
e2e-tests-server-cli:
|
e2e-tests-server-cli:
|
||||||
@@ -398,23 +430,27 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './e2e/.nvmrc'
|
node-version-file: './e2e/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Run setup typescript-sdk
|
- name: Run setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run setup cli
|
- name: Run setup cli
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./cli
|
working-directory: ./cli
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Docker build
|
- name: Docker build
|
||||||
@@ -422,7 +458,7 @@ jobs:
|
|||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run e2e tests (api & cli)
|
- name: Run e2e tests (api & cli)
|
||||||
run: npm run test
|
run: pnpm test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
e2e-tests-web:
|
e2e-tests-web:
|
||||||
@@ -446,22 +482,26 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './e2e/.nvmrc'
|
node-version-file: './e2e/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Run setup typescript-sdk
|
- name: Run setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Install Playwright Browsers
|
- name: Install Playwright Browsers
|
||||||
run: npx playwright install --with-deps chromium
|
run: npx playwright install chromium --only-shell
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Docker build
|
- name: Docker build
|
||||||
@@ -564,16 +604,20 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './.github/.nvmrc'
|
node-version-file: './.github/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Run npm install
|
- name: Run pnpm install
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Run formatter
|
- name: Run formatter
|
||||||
run: npm run format
|
run: pnpm format
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
shellcheck:
|
shellcheck:
|
||||||
@@ -605,16 +649,20 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Install server dependencies
|
- name: Install server dependencies
|
||||||
run: npm --prefix=server ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build the app
|
- name: Build the app
|
||||||
run: npm --prefix=server run build
|
run: pnpm --dir=server build
|
||||||
|
|
||||||
- name: Run API generation
|
- name: Run API generation
|
||||||
run: make open-api
|
run: make open-api
|
||||||
@@ -644,7 +692,7 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.1
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3
|
||||||
env:
|
env:
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
@@ -666,26 +714,30 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Install server dependencies
|
- name: Install server dependencies
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build the app
|
- name: Build the app
|
||||||
run: npm run build
|
run: pnpm build
|
||||||
|
|
||||||
- name: Run existing migrations
|
- name: Run existing migrations
|
||||||
run: npm run migrations:run
|
run: pnpm migrations:run
|
||||||
|
|
||||||
- name: Test npm run schema:reset command works
|
- name: Test pnpm schema:reset command works
|
||||||
run: npm run schema:reset
|
run: pnpm schema:reset
|
||||||
|
|
||||||
- name: Generate new migrations
|
- name: Generate new migrations
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: npm run migrations:generate src/TestMigration
|
run: pnpm migrations:generate src/TestMigration
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||||
@@ -704,7 +756,7 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
- name: Run SQL generation
|
- name: Run SQL generation
|
||||||
run: npm run sync:sql
|
run: pnpm sync:sql
|
||||||
env:
|
env:
|
||||||
DB_URL: postgres://postgres:postgres@localhost:5432/immich
|
DB_URL: postgres://postgres:postgres@localhost:5432/immich
|
||||||
|
|
||||||
|
|||||||
33
Makefile
33
Makefile
@@ -34,7 +34,7 @@ open-api-typescript:
|
|||||||
cd ./open-api && bash ./bin/generate-open-api.sh typescript
|
cd ./open-api && bash ./bin/generate-open-api.sh typescript
|
||||||
|
|
||||||
sql:
|
sql:
|
||||||
npm --prefix server run sync:sql
|
pnpm --dir server run sync:sql
|
||||||
|
|
||||||
attach-server:
|
attach-server:
|
||||||
docker exec -it docker_immich-server_1 sh
|
docker exec -it docker_immich-server_1 sh
|
||||||
@@ -45,28 +45,30 @@ renovate:
|
|||||||
MODULES = e2e server web cli sdk docs .github
|
MODULES = e2e server web cli sdk docs .github
|
||||||
|
|
||||||
audit-%:
|
audit-%:
|
||||||
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) audit fix
|
pnpm --dir $(subst sdk,open-api/typescript-sdk,$*) audit fix
|
||||||
install-%:
|
install-%:
|
||||||
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) i
|
pnpm --dir $(subst sdk,open-api/typescript-sdk,$*) i
|
||||||
|
ci-%:
|
||||||
|
pnpm --dir $(subst sdk,open-api/typescript-sdk,$*) install --frozen-lockfile
|
||||||
build-cli: build-sdk
|
build-cli: build-sdk
|
||||||
build-web: build-sdk
|
build-web: build-sdk
|
||||||
build-%: install-%
|
build-%: install-%
|
||||||
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) run build
|
pnpm --dir $(subst sdk,open-api/typescript-sdk,$*) build
|
||||||
format-%:
|
format-%:
|
||||||
npm --prefix $* run format:fix
|
pnpm --dir $* format:fix
|
||||||
lint-%:
|
lint-%:
|
||||||
npm --prefix $* run lint:fix
|
pnpm --dir $* lint:fix
|
||||||
check-%:
|
check-%:
|
||||||
npm --prefix $* run check
|
pnpm --dir $* check
|
||||||
check-web:
|
check-web:
|
||||||
npm --prefix web run check:typescript
|
pnpm --dir web check:typescript
|
||||||
npm --prefix web run check:svelte
|
pnpm --dir web check:svelte
|
||||||
test-%:
|
test-%:
|
||||||
npm --prefix $* run test
|
pnpm --dir $* test
|
||||||
test-e2e:
|
test-e2e:
|
||||||
docker compose -f ./e2e/docker-compose.yml build
|
docker compose -f ./e2e/docker-compose.yml build
|
||||||
npm --prefix e2e run test
|
pnpm --dir e2e test
|
||||||
npm --prefix e2e run test:web
|
pnpm --dir e2e test:web
|
||||||
test-medium:
|
test-medium:
|
||||||
docker run \
|
docker run \
|
||||||
--rm \
|
--rm \
|
||||||
@@ -76,12 +78,13 @@ test-medium:
|
|||||||
-v ./server/tsconfig.json:/usr/src/app/tsconfig.json \
|
-v ./server/tsconfig.json:/usr/src/app/tsconfig.json \
|
||||||
-e NODE_ENV=development \
|
-e NODE_ENV=development \
|
||||||
immich-server:latest \
|
immich-server:latest \
|
||||||
-c "npm ci && npm run test:medium -- --run"
|
-c "pnpm install --frozen-lockfile && pnpm test:medium -- --run"
|
||||||
test-medium-dev:
|
test-medium-dev:
|
||||||
docker exec -it immich_server /bin/sh -c "npm run test:medium"
|
docker exec -it immich_server /bin/sh -c "pnpm test:medium"
|
||||||
|
|
||||||
build-all: $(foreach M,$(filter-out e2e .github,$(MODULES)),build-$M) ;
|
build-all: $(foreach M,$(filter-out e2e .github,$(MODULES)),build-$M) ;
|
||||||
install-all: $(foreach M,$(MODULES),install-$M) ;
|
install-all: $(foreach M,$(filter-out .github,$(MODULES)),install-$M) ;
|
||||||
|
ci-all: $(foreach M,$(filter-out .github,$(MODULES)),ci-$M) ;
|
||||||
check-all: $(foreach M,$(filter-out sdk cli docs .github,$(MODULES)),check-$M) ;
|
check-all: $(foreach M,$(filter-out sdk cli docs .github,$(MODULES)),check-$M) ;
|
||||||
lint-all: $(foreach M,$(filter-out sdk docs .github,$(MODULES)),lint-$M) ;
|
lint-all: $(foreach M,$(filter-out sdk docs .github,$(MODULES)),lint-$M) ;
|
||||||
format-all: $(foreach M,$(filter-out sdk,$(MODULES)),format-$M) ;
|
format-all: $(foreach M,$(filter-out sdk,$(MODULES)),format-$M) ;
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ upload/**
|
|||||||
.prettierignore
|
.prettierignore
|
||||||
.prettierrc
|
.prettierrc
|
||||||
Dockerfile
|
Dockerfile
|
||||||
package-lock.json
|
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
vite.config.ts
|
vite.config.ts
|
||||||
vitest.config.ts
|
vitest.config.ts
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ FROM node:22.16.0-alpine3.20@sha256:2289fb1fba0f4633b08ec47b94a89c7e20b829fc5679
|
|||||||
|
|
||||||
WORKDIR /usr/src/open-api/typescript-sdk
|
WORKDIR /usr/src/open-api/typescript-sdk
|
||||||
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
|
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
|
||||||
RUN npm ci
|
RUN pnpm install --frozen-lockfile
|
||||||
COPY open-api/typescript-sdk/ ./
|
COPY open-api/typescript-sdk/ ./
|
||||||
RUN npm run build
|
RUN pnpm build
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
COPY cli/package.json cli/package-lock.json ./
|
COPY cli/package.json pnpm-lock.yaml ./
|
||||||
RUN npm ci
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
COPY cli .
|
COPY cli .
|
||||||
RUN npm run build
|
RUN pnpm build
|
||||||
|
|
||||||
WORKDIR /import
|
WORKDIR /import
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ Please see the [Immich CLI documentation](https://immich.app/docs/features/comma
|
|||||||
|
|
||||||
Before building the CLI, you must build the immich server and the open-api client. To build the server run the following in the server folder:
|
Before building the CLI, you must build the immich server and the open-api client. To build the server run the following in the server folder:
|
||||||
|
|
||||||
$ npm install
|
$ pnpm install
|
||||||
$ npm run build
|
$ pnpm build
|
||||||
|
|
||||||
Then, to build the open-api client run the following in the open-api folder:
|
Then, to build the open-api client run the following in the open-api folder:
|
||||||
|
|
||||||
@@ -15,8 +15,8 @@ Then, to build the open-api client run the following in the open-api folder:
|
|||||||
|
|
||||||
To run the Immich CLI from source, run the following in the cli folder:
|
To run the Immich CLI from source, run the following in the cli folder:
|
||||||
|
|
||||||
$ npm install
|
$ pnpm install
|
||||||
$ npm run build
|
$ pnpm build
|
||||||
$ ts-node .
|
$ ts-node .
|
||||||
|
|
||||||
You'll need ts-node, the easiest way to install it is to use npm:
|
You'll need ts-node, the easiest way to install it is to use npm:
|
||||||
@@ -25,6 +25,6 @@ You'll need ts-node, the easiest way to install it is to use npm:
|
|||||||
|
|
||||||
You can also build and install the CLI using
|
You can also build and install the CLI using
|
||||||
|
|
||||||
$ npm run build
|
$ pnpm build
|
||||||
$ npm install -g .
|
$ pnpm install -g .
|
||||||
****
|
****
|
||||||
|
|||||||
4517
cli/package-lock.json
generated
4517
cli/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.69",
|
"version": "2.2.72",
|
||||||
"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",
|
||||||
@@ -15,13 +15,13 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.1.0",
|
"@eslint/eslintrc": "^3.1.0",
|
||||||
"@eslint/js": "^9.8.0",
|
"@eslint/js": "^9.8.0",
|
||||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
"@immich/sdk": "workspace:^",
|
||||||
"@types/byte-size": "^8.1.0",
|
"@types/byte-size": "^8.1.0",
|
||||||
"@types/cli-progress": "^3.11.0",
|
"@types/cli-progress": "^3.11.0",
|
||||||
"@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.15.31",
|
"@types/node": "^22.15.32",
|
||||||
"@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",
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ name: immich-dev
|
|||||||
services:
|
services:
|
||||||
immich-server:
|
immich-server:
|
||||||
container_name: immich_server
|
container_name: immich_server
|
||||||
command: [ '/usr/src/app/bin/immich-dev' ]
|
command: ['/usr/src/app/bin/immich-dev']
|
||||||
image: immich-server-dev:latest
|
image: immich-server-dev:latest
|
||||||
# extends:
|
# extends:
|
||||||
# file: hwaccel.transcoding.yml
|
# file: hwaccel.transcoding.yml
|
||||||
@@ -70,7 +70,7 @@ services:
|
|||||||
# user: 0:0
|
# user: 0:0
|
||||||
build:
|
build:
|
||||||
context: ../web
|
context: ../web
|
||||||
command: [ '/usr/src/app/bin/immich-web' ]
|
command: ['/usr/src/app/bin/immich-web']
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
ports:
|
ports:
|
||||||
@@ -122,7 +122,7 @@ services:
|
|||||||
|
|
||||||
database:
|
database:
|
||||||
container_name: immich_postgres
|
container_name: immich_postgres
|
||||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.1-pgvectors0.2.0
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:5f6a838e4e44c8e0e019d0ebfe3ee8952b69afc2809b2c25f7b0119641978e91
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ services:
|
|||||||
|
|
||||||
database:
|
database:
|
||||||
container_name: immich_postgres
|
container_name: immich_postgres
|
||||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.1-pgvectors0.2.0
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:5f6a838e4e44c8e0e019d0ebfe3ee8952b69afc2809b2c25f7b0119641978e91
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
@@ -91,10 +91,10 @@ services:
|
|||||||
# add data source for http://immich-prometheus:9090 to get started
|
# add data source for http://immich-prometheus:9090 to get started
|
||||||
immich-grafana:
|
immich-grafana:
|
||||||
container_name: immich_grafana
|
container_name: immich_grafana
|
||||||
command: [ './run.sh', '-disable-reporting' ]
|
command: ['./run.sh', '-disable-reporting']
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
image: grafana/grafana:12.0.1-ubuntu@sha256:65575bb9c761335e2ff30e364f21d38632e3b2e75f5f81d83cc92f44b9bbc055
|
image: grafana/grafana:12.0.2-ubuntu@sha256:0512d81cdeaaff0e370a9aa66027b465d1f1f04379c3a9c801a905fabbdbc7a5
|
||||||
volumes:
|
volumes:
|
||||||
- grafana-data:/var/lib/grafana
|
- grafana-data:/var/lib/grafana
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ services:
|
|||||||
|
|
||||||
database:
|
database:
|
||||||
container_name: immich_postgres
|
container_name: immich_postgres
|
||||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.1-pgvectors0.2.0
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:5f6a838e4e44c8e0e019d0ebfe3ee8952b69afc2809b2c25f7b0119641978e91
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
POSTGRES_USER: ${DB_USERNAME}
|
POSTGRES_USER: ${DB_USERNAME}
|
||||||
|
|||||||
@@ -64,7 +64,13 @@ COMMIT;
|
|||||||
|
|
||||||
### Updating VectorChord
|
### Updating VectorChord
|
||||||
|
|
||||||
When installing a new version of VectorChord, you will need to manually update the extension by connecting to the Immich database and running `ALTER EXTENSION vchord UPDATE;`.
|
When installing a new version of VectorChord, you will need to manually update the extension and reindex by connecting to the Immich database and running:
|
||||||
|
|
||||||
|
```
|
||||||
|
ALTER EXTENSION vchord UPDATE;
|
||||||
|
REINDEX INDEX face_index;
|
||||||
|
REINDEX INDEX clip_index;
|
||||||
|
```
|
||||||
|
|
||||||
## Migrating to VectorChord
|
## Migrating to VectorChord
|
||||||
|
|
||||||
@@ -76,6 +82,8 @@ Support for pgvecto.rs will be dropped in a later release, hence we recommend al
|
|||||||
|
|
||||||
The easiest option is to have both extensions installed during the migration:
|
The easiest option is to have both extensions installed during the migration:
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Migration steps (automatic)</summary>
|
||||||
1. Ensure you still have pgvecto.rs installed
|
1. Ensure you still have pgvecto.rs installed
|
||||||
2. Install `pgvector` (`>= 0.7.0, < 1.0.0`). The easiest way to do this is on Debian/Ubuntu by adding the [PostgreSQL Apt repository][pg-apt] and then running `apt install postgresql-NN-pgvector`, where `NN` is your Postgres version (e.g., `16`)
|
2. Install `pgvector` (`>= 0.7.0, < 1.0.0`). The easiest way to do this is on Debian/Ubuntu by adding the [PostgreSQL Apt repository][pg-apt] and then running `apt install postgresql-NN-pgvector`, where `NN` is your Postgres version (e.g., `16`)
|
||||||
3. [Install VectorChord][vchord-install]
|
3. [Install VectorChord][vchord-install]
|
||||||
@@ -89,8 +97,12 @@ The easiest option is to have both extensions installed during the migration:
|
|||||||
11. Restart the Postgres database
|
11. Restart the Postgres database
|
||||||
12. Uninstall pgvecto.rs (e.g. `apt-get purge vectors-pg14` on Debian-based environments, replacing `pg14` as appropriate). `pgvector` must remain installed as it provides the data types used by `vchord`
|
12. Uninstall pgvecto.rs (e.g. `apt-get purge vectors-pg14` on Debian-based environments, replacing `pg14` as appropriate). `pgvector` must remain installed as it provides the data types used by `vchord`
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
If it is not possible to have both VectorChord and pgvecto.rs installed at the same time, you can perform the migration with more manual steps:
|
If it is not possible to have both VectorChord and pgvecto.rs installed at the same time, you can perform the migration with more manual steps:
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Migration steps (manual)</summary>
|
||||||
1. While pgvecto.rs is still installed, run the following SQL command using psql or your choice of database client. Take note of the number outputted by this command as you will need it later
|
1. While pgvecto.rs is still installed, run the following SQL command using psql or your choice of database client. Take note of the number outputted by this command as you will need it later
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
@@ -123,14 +135,20 @@ ALTER TABLE face_search ALTER COLUMN embedding SET DATA TYPE vector(512);
|
|||||||
|
|
||||||
5. Start Immich and let it create new indices using VectorChord
|
5. Start Immich and let it create new indices using VectorChord
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
### Migrating from pgvector
|
### Migrating from pgvector
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Migration steps</summary>
|
||||||
1. Ensure you have at least 0.7.0 of pgvector installed. If it is below that, please upgrade it and run the SQL command `ALTER EXTENSION vector UPDATE;` using psql or your choice of database client
|
1. Ensure you have at least 0.7.0 of pgvector installed. If it is below that, please upgrade it and run the SQL command `ALTER EXTENSION vector UPDATE;` using psql or your choice of database client
|
||||||
2. Follow the Prerequisites to install VectorChord
|
2. Follow the Prerequisites to install VectorChord
|
||||||
3. If Immich does not have superuser permissions, run the SQL command `CREATE EXTENSION vchord CASCADE;`
|
3. If Immich does not have superuser permissions, run the SQL command `CREATE EXTENSION vchord CASCADE;`
|
||||||
4. Remove the `DB_VECTOR_EXTENSION=pgvector` environmental variable as it will make Immich still use pgvector if set
|
4. Remove the `DB_VECTOR_EXTENSION=pgvector` environmental variable as it will make Immich still use pgvector if set
|
||||||
5. Start Immich and let it create new indices using VectorChord
|
5. Start Immich and let it create new indices using VectorChord
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
Note that VectorChord itself uses pgvector types, so you should not uninstall pgvector after following these steps.
|
Note that VectorChord itself uses pgvector types, so you should not uninstall pgvector after following these steps.
|
||||||
|
|
||||||
[vchord-install]: https://docs.vectorchord.ai/vectorchord/getting-started/installation.html
|
[vchord-install]: https://docs.vectorchord.ai/vectorchord/getting-started/installation.html
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ alt="Dot Env Example"
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
- Change the default `DB_PASSWORD`, and add custom database connection information if necessary.
|
- Change the default `DB_PASSWORD`, and add custom database connection information if necessary.
|
||||||
- Change `DB_DATA_LOCATION` to a folder where the database will be saved to disk.
|
- Change `DB_DATA_LOCATION` to a folder (absolute path) where the database will be saved to disk.
|
||||||
- Change `UPLOAD_LOCATION` to a folder where media (uploaded and generated) will be stored.
|
- Change `UPLOAD_LOCATION` to a folder (absolute path) where media (uploaded and generated) will be stored.
|
||||||
|
|
||||||
11. Click on "**Deploy the stack**".
|
11. Click on "**Deploy the stack**".
|
||||||
|
|
||||||
|
|||||||
12
docs/static/archived-versions.json
vendored
12
docs/static/archived-versions.json
vendored
@@ -1,4 +1,16 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"label": "v1.135.3",
|
||||||
|
"url": "https://v1.135.3.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.135.2",
|
||||||
|
"url": "https://v1.135.2.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.135.1",
|
||||||
|
"url": "https://v1.135.1.archive.immich.app"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "v1.135.0",
|
"label": "v1.135.0",
|
||||||
"url": "https://v1.135.0.archive.immich.app"
|
"url": "https://v1.135.0.archive.immich.app"
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ services:
|
|||||||
image: redis:6.2-alpine@sha256:3211c33a618c457e5d241922c975dbc4f446d0bdb2dc75694f5573ef8e2d01fa
|
image: redis:6.2-alpine@sha256:3211c33a618c457e5d241922c975dbc4f446d0bdb2dc75694f5573ef8e2d01fa
|
||||||
|
|
||||||
database:
|
database:
|
||||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:9c704fb49ce27549df00f1b096cc93f8b0c959ef087507704d74954808f78a82
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:3aef84a0a4fabbda17ef115c3019ba0c914ec73e9f6e59203674322d858b8eea
|
||||||
command: -c fsync=off -c shared_preload_libraries=vchord.so -c config_file=/var/lib/postgresql/data/postgresql.conf
|
command: -c fsync=off -c shared_preload_libraries=vchord.so -c config_file=/var/lib/postgresql/data/postgresql.conf
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
|
|||||||
6874
e2e/package-lock.json
generated
6874
e2e/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.135.0",
|
"version": "1.135.3",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -21,11 +21,11 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.1.0",
|
"@eslint/eslintrc": "^3.1.0",
|
||||||
"@eslint/js": "^9.8.0",
|
"@eslint/js": "^9.8.0",
|
||||||
"@immich/cli": "file:../cli",
|
"@immich/cli": "workspace:^",
|
||||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
"@immich/sdk": "workspace:^",
|
||||||
"@playwright/test": "^1.44.1",
|
"@playwright/test": "^1.44.1",
|
||||||
"@types/luxon": "^3.4.2",
|
"@types/luxon": "^3.4.2",
|
||||||
"@types/node": "^22.15.31",
|
"@types/node": "^22.15.32",
|
||||||
"@types/oidc-provider": "^9.0.0",
|
"@types/oidc-provider": "^9.0.0",
|
||||||
"@types/pg": "^8.15.1",
|
"@types/pg": "^8.15.1",
|
||||||
"@types/pngjs": "^6.0.4",
|
"@types/pngjs": "^6.0.4",
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ describe('/people', () => {
|
|||||||
let nameAlicePerson: PersonResponseDto;
|
let nameAlicePerson: PersonResponseDto;
|
||||||
let nameBobPerson: PersonResponseDto;
|
let nameBobPerson: PersonResponseDto;
|
||||||
let nameCharliePerson: PersonResponseDto;
|
let nameCharliePerson: PersonResponseDto;
|
||||||
let nameNullPerson: PersonResponseDto;
|
let nameNullPerson4Assets: PersonResponseDto;
|
||||||
|
let nameNullPerson3Assets: PersonResponseDto;
|
||||||
|
let nameNullPerson1Asset: PersonResponseDto;
|
||||||
|
let nameBillPersonFavourite: PersonResponseDto;
|
||||||
|
let nameFreddyPersonFavourite: PersonResponseDto;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await utils.resetDatabase();
|
await utils.resetDatabase();
|
||||||
@@ -27,7 +31,11 @@ describe('/people', () => {
|
|||||||
nameCharliePerson,
|
nameCharliePerson,
|
||||||
nameBobPerson,
|
nameBobPerson,
|
||||||
nameAlicePerson,
|
nameAlicePerson,
|
||||||
nameNullPerson,
|
nameNullPerson4Assets,
|
||||||
|
nameNullPerson3Assets,
|
||||||
|
nameNullPerson1Asset,
|
||||||
|
nameBillPersonFavourite,
|
||||||
|
nameFreddyPersonFavourite,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
utils.createPerson(admin.accessToken, {
|
utils.createPerson(admin.accessToken, {
|
||||||
name: 'visible_person',
|
name: 'visible_person',
|
||||||
@@ -52,11 +60,26 @@ describe('/people', () => {
|
|||||||
utils.createPerson(admin.accessToken, {
|
utils.createPerson(admin.accessToken, {
|
||||||
name: '',
|
name: '',
|
||||||
}),
|
}),
|
||||||
|
utils.createPerson(admin.accessToken, {
|
||||||
|
name: '',
|
||||||
|
}),
|
||||||
|
utils.createPerson(admin.accessToken, {
|
||||||
|
name: '',
|
||||||
|
}),
|
||||||
|
utils.createPerson(admin.accessToken, {
|
||||||
|
name: 'Bill',
|
||||||
|
isFavorite: true,
|
||||||
|
}),
|
||||||
|
utils.createPerson(admin.accessToken, {
|
||||||
|
name: 'Freddy',
|
||||||
|
isFavorite: true,
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const asset1 = await utils.createAsset(admin.accessToken);
|
const asset1 = await utils.createAsset(admin.accessToken);
|
||||||
const asset2 = await utils.createAsset(admin.accessToken);
|
const asset2 = await utils.createAsset(admin.accessToken);
|
||||||
const asset3 = await utils.createAsset(admin.accessToken);
|
const asset3 = await utils.createAsset(admin.accessToken);
|
||||||
|
const asset4 = await utils.createAsset(admin.accessToken);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
utils.createFace({ assetId: asset1.id, personId: visiblePerson.id }),
|
utils.createFace({ assetId: asset1.id, personId: visiblePerson.id }),
|
||||||
@@ -64,15 +87,27 @@ describe('/people', () => {
|
|||||||
utils.createFace({ assetId: asset1.id, personId: multipleAssetsPerson.id }),
|
utils.createFace({ assetId: asset1.id, personId: multipleAssetsPerson.id }),
|
||||||
utils.createFace({ assetId: asset1.id, personId: multipleAssetsPerson.id }),
|
utils.createFace({ assetId: asset1.id, personId: multipleAssetsPerson.id }),
|
||||||
utils.createFace({ assetId: asset2.id, personId: multipleAssetsPerson.id }),
|
utils.createFace({ assetId: asset2.id, personId: multipleAssetsPerson.id }),
|
||||||
utils.createFace({ assetId: asset3.id, personId: multipleAssetsPerson.id }),
|
utils.createFace({ assetId: asset3.id, personId: multipleAssetsPerson.id }), // 4 assets
|
||||||
// Named persons
|
// Named persons
|
||||||
utils.createFace({ assetId: asset1.id, personId: nameCharliePerson.id }), // 1 asset
|
utils.createFace({ assetId: asset1.id, personId: nameCharliePerson.id }), // 1 asset
|
||||||
utils.createFace({ assetId: asset1.id, personId: nameBobPerson.id }),
|
utils.createFace({ assetId: asset1.id, personId: nameBobPerson.id }),
|
||||||
utils.createFace({ assetId: asset2.id, personId: nameBobPerson.id }), // 2 assets
|
utils.createFace({ assetId: asset2.id, personId: nameBobPerson.id }), // 2 assets
|
||||||
utils.createFace({ assetId: asset1.id, personId: nameAlicePerson.id }), // 1 asset
|
utils.createFace({ assetId: asset1.id, personId: nameAlicePerson.id }), // 1 asset
|
||||||
// Null-named person
|
// Null-named person 4 assets
|
||||||
utils.createFace({ assetId: asset1.id, personId: nameNullPerson.id }),
|
utils.createFace({ assetId: asset1.id, personId: nameNullPerson4Assets.id }),
|
||||||
utils.createFace({ assetId: asset2.id, personId: nameNullPerson.id }), // 2 assets
|
utils.createFace({ assetId: asset2.id, personId: nameNullPerson4Assets.id }),
|
||||||
|
utils.createFace({ assetId: asset3.id, personId: nameNullPerson4Assets.id }),
|
||||||
|
utils.createFace({ assetId: asset4.id, personId: nameNullPerson4Assets.id }), // 4 assets
|
||||||
|
// Null-named person 3 assets
|
||||||
|
utils.createFace({ assetId: asset1.id, personId: nameNullPerson3Assets.id }),
|
||||||
|
utils.createFace({ assetId: asset2.id, personId: nameNullPerson3Assets.id }),
|
||||||
|
utils.createFace({ assetId: asset3.id, personId: nameNullPerson3Assets.id }), // 3 assets
|
||||||
|
// Null-named person 1 asset
|
||||||
|
utils.createFace({ assetId: asset3.id, personId: nameNullPerson1Asset.id }),
|
||||||
|
// Favourite People
|
||||||
|
utils.createFace({ assetId: asset1.id, personId: nameFreddyPersonFavourite.id }),
|
||||||
|
utils.createFace({ assetId: asset2.id, personId: nameFreddyPersonFavourite.id }),
|
||||||
|
utils.createFace({ assetId: asset1.id, personId: nameBillPersonFavourite.id }),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -87,15 +122,19 @@ describe('/people', () => {
|
|||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
expect(body).toEqual({
|
expect(body).toEqual({
|
||||||
hasNextPage: false,
|
hasNextPage: false,
|
||||||
total: 7,
|
total: 11,
|
||||||
hidden: 1,
|
hidden: 1,
|
||||||
people: [
|
people: [
|
||||||
|
expect.objectContaining({ name: 'Freddy' }),
|
||||||
|
expect.objectContaining({ name: 'Bill' }),
|
||||||
expect.objectContaining({ name: 'multiple_assets_person' }),
|
expect.objectContaining({ name: 'multiple_assets_person' }),
|
||||||
expect.objectContaining({ name: 'Bob' }),
|
expect.objectContaining({ name: 'Bob' }),
|
||||||
expect.objectContaining({ name: 'Alice' }),
|
expect.objectContaining({ name: 'Alice' }),
|
||||||
expect.objectContaining({ name: 'Charlie' }),
|
expect.objectContaining({ name: 'Charlie' }),
|
||||||
expect.objectContaining({ name: 'visible_person' }),
|
expect.objectContaining({ name: 'visible_person' }),
|
||||||
expect.objectContaining({ name: 'hidden_person' }),
|
expect.objectContaining({ id: nameNullPerson4Assets.id, name: '' }),
|
||||||
|
expect.objectContaining({ id: nameNullPerson3Assets.id, name: '' }),
|
||||||
|
expect.objectContaining({ name: 'hidden_person' }), // Should really be before the null names
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -105,17 +144,21 @@ describe('/people', () => {
|
|||||||
|
|
||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
expect(body.hasNextPage).toBe(false);
|
expect(body.hasNextPage).toBe(false);
|
||||||
expect(body.total).toBe(7); // All persons
|
expect(body.total).toBe(11); // All persons
|
||||||
expect(body.hidden).toBe(1); // 'hidden_person'
|
expect(body.hidden).toBe(1); // 'hidden_person'
|
||||||
|
|
||||||
const people = body.people as PersonResponseDto[];
|
const people = body.people as PersonResponseDto[];
|
||||||
|
|
||||||
expect(people.map((p) => p.id)).toEqual([
|
expect(people.map((p) => p.id)).toEqual([
|
||||||
|
nameFreddyPersonFavourite.id, // name: 'Freddy', count: 2
|
||||||
|
nameBillPersonFavourite.id, // name: 'Bill', count: 1
|
||||||
multipleAssetsPerson.id, // name: 'multiple_assets_person', count: 3
|
multipleAssetsPerson.id, // name: 'multiple_assets_person', count: 3
|
||||||
nameBobPerson.id, // name: 'Bob', count: 2
|
nameBobPerson.id, // name: 'Bob', count: 2
|
||||||
nameAlicePerson.id, // name: 'Alice', count: 1
|
nameAlicePerson.id, // name: 'Alice', count: 1
|
||||||
nameCharliePerson.id, // name: 'Charlie', count: 1
|
nameCharliePerson.id, // name: 'Charlie', count: 1
|
||||||
visiblePerson.id, // name: 'visible_person', count: 1
|
visiblePerson.id, // name: 'visible_person', count: 1
|
||||||
|
nameNullPerson4Assets.id, // name: '', count: 4
|
||||||
|
nameNullPerson3Assets.id, // name: '', count: 3
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(people.some((p) => p.id === hiddenPerson.id)).toBe(false);
|
expect(people.some((p) => p.id === hiddenPerson.id)).toBe(false);
|
||||||
@@ -127,14 +170,18 @@ describe('/people', () => {
|
|||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
expect(body).toEqual({
|
expect(body).toEqual({
|
||||||
hasNextPage: false,
|
hasNextPage: false,
|
||||||
total: 7,
|
total: 11,
|
||||||
hidden: 1,
|
hidden: 1,
|
||||||
people: [
|
people: [
|
||||||
|
expect.objectContaining({ name: 'Freddy' }),
|
||||||
|
expect.objectContaining({ name: 'Bill' }),
|
||||||
expect.objectContaining({ name: 'multiple_assets_person' }),
|
expect.objectContaining({ name: 'multiple_assets_person' }),
|
||||||
expect.objectContaining({ name: 'Bob' }),
|
expect.objectContaining({ name: 'Bob' }),
|
||||||
expect.objectContaining({ name: 'Alice' }),
|
expect.objectContaining({ name: 'Alice' }),
|
||||||
expect.objectContaining({ name: 'Charlie' }),
|
expect.objectContaining({ name: 'Charlie' }),
|
||||||
expect.objectContaining({ name: 'visible_person' }),
|
expect.objectContaining({ name: 'visible_person' }),
|
||||||
|
expect.objectContaining({ id: nameNullPerson4Assets.id, name: '' }),
|
||||||
|
expect.objectContaining({ id: nameNullPerson3Assets.id, name: '' }),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -148,9 +195,9 @@ describe('/people', () => {
|
|||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
expect(body).toEqual({
|
expect(body).toEqual({
|
||||||
hasNextPage: true,
|
hasNextPage: true,
|
||||||
total: 7,
|
total: 11,
|
||||||
hidden: 1,
|
hidden: 1,
|
||||||
people: [expect.objectContaining({ name: 'visible_person' })],
|
people: [expect.objectContaining({ name: 'Alice' })],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -119,6 +119,16 @@ describe('/shared-links', () => {
|
|||||||
expect(resp.header['content-type']).toContain('text/html');
|
expect(resp.header['content-type']).toContain('text/html');
|
||||||
expect(resp.text).toContain(`<meta property="og:image" content="https://my.immich.app`);
|
expect(resp.text).toContain(`<meta property="og:image" content="https://my.immich.app`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return 404 for an invalid shared link', async () => {
|
||||||
|
const resp = await request(shareUrl).get(`/invalid-key`);
|
||||||
|
expect(resp.status).toBe(404);
|
||||||
|
expect(resp.header['content-type']).toContain('text/html');
|
||||||
|
expect(resp.text).not.toContain(`og:type`);
|
||||||
|
expect(resp.text).not.toContain(`og:title`);
|
||||||
|
expect(resp.text).not.toContain(`og:description`);
|
||||||
|
expect(resp.text).not.toContain(`og:image`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('GET /shared-links', () => {
|
describe('GET /shared-links', () => {
|
||||||
|
|||||||
@@ -464,7 +464,6 @@
|
|||||||
"assets": "Assets",
|
"assets": "Assets",
|
||||||
"assets_added_count": "Added {count, plural, one {# asset} other {# assets}}",
|
"assets_added_count": "Added {count, plural, one {# asset} other {# assets}}",
|
||||||
"assets_added_to_album_count": "Added {count, plural, one {# asset} other {# assets}} to the album",
|
"assets_added_to_album_count": "Added {count, plural, one {# asset} other {# assets}} to the album",
|
||||||
"assets_added_to_name_count": "Added {count, plural, one {# asset} other {# assets}} to {hasName, select, true {<b>{name}</b>} other {new album}}",
|
|
||||||
"assets_cannot_be_added_to_album_count": "{count, plural, one {Asset} other {Assets}} cannot be added to the album",
|
"assets_cannot_be_added_to_album_count": "{count, plural, one {Asset} other {Assets}} cannot be added to the album",
|
||||||
"assets_count": "{count, plural, one {# asset} other {# assets}}",
|
"assets_count": "{count, plural, one {# asset} other {# assets}}",
|
||||||
"assets_deleted_permanently": "{count} asset(s) deleted permanently",
|
"assets_deleted_permanently": "{count} asset(s) deleted permanently",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
ARG DEVICE=cpu
|
ARG DEVICE=cpu
|
||||||
|
|
||||||
FROM python:3.11-bookworm@sha256:d2621a9f74d31a8a60af19f97b09cc3ac54382c8680b6544018713a12ef6c048 AS builder-cpu
|
FROM python:3.11-bookworm@sha256:ce3b954c9285a7a145cba620bae03db836ab890b6b9e0d05a3ca522ea00dfbc9 AS builder-cpu
|
||||||
|
|
||||||
FROM builder-cpu AS builder-openvino
|
FROM builder-cpu AS builder-openvino
|
||||||
|
|
||||||
@@ -59,7 +59,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:4faec156e35a5f345d57804d8858c6ba1cf6352ce5f4bffc11b7fdebdef46a38 /uv /uvx /bin/
|
COPY --from=ghcr.io/astral-sh/uv:latest@sha256:cda0fdc9b6066975ba4c791597870d18bc3a441dfc18ab24c5e888c16e15780c /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 \
|
||||||
@@ -68,11 +68,11 @@ RUN if [ "$DEVICE" = "rocm" ]; then \
|
|||||||
uv pip install /opt/onnxruntime_rocm-*.whl; \
|
uv pip install /opt/onnxruntime_rocm-*.whl; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
FROM python:3.11-slim-bookworm@sha256:7a3ed1226224bcc1fe5443262363d42f48cf832a540c1836ba8ccbeaadf8637c AS prod-cpu
|
FROM python:3.11-slim-bookworm@sha256:9e1912aab0a30bbd9488eb79063f68f42a68ab0946cbe98fecf197fe5b085506 AS prod-cpu
|
||||||
|
|
||||||
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2
|
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2
|
||||||
|
|
||||||
FROM python:3.11-slim-bookworm@sha256:7a3ed1226224bcc1fe5443262363d42f48cf832a540c1836ba8ccbeaadf8637c AS prod-openvino
|
FROM python:3.11-slim-bookworm@sha256:9e1912aab0a30bbd9488eb79063f68f42a68ab0946cbe98fecf197fe5b085506 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 && \
|
||||||
|
|||||||
@@ -244,7 +244,6 @@ async def load(model: InferenceModel) -> InferenceModel:
|
|||||||
|
|
||||||
async def idle_shutdown_task() -> None:
|
async def idle_shutdown_task() -> None:
|
||||||
while True:
|
while True:
|
||||||
log.debug("Checking for inactivity...")
|
|
||||||
if (
|
if (
|
||||||
last_called is not None
|
last_called is not None
|
||||||
and not active_requests
|
and not active_requests
|
||||||
|
|||||||
141
machine-learning/uv.lock
generated
141
machine-learning/uv.lock
generated
@@ -517,16 +517,16 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastapi"
|
name = "fastapi"
|
||||||
version = "0.115.12"
|
version = "0.115.13"
|
||||||
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/f4/55/ae499352d82338331ca1e28c7f4a63bfd09479b16395dce38cf50a39e2c2/fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681", size = 295236, upload-time = "2025-03-23T22:55:43.822Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/20/64/ec0788201b5554e2a87c49af26b77a4d132f807a0fa9675257ac92c6aa0e/fastapi-0.115.13.tar.gz", hash = "sha256:55d1d25c2e1e0a0a50aceb1c8705cd932def273c102bff0b1c1da88b3c6eb307", size = 295680, upload-time = "2025-06-17T11:49:45.575Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164, upload-time = "2025-03-23T22:55:42.101Z" },
|
{ url = "https://files.pythonhosted.org/packages/59/4a/e17764385382062b0edbb35a26b7cf76d71e27e456546277a42ba6545c6e/fastapi-0.115.13-py3-none-any.whl", hash = "sha256:0a0cab59afa7bab22f5eb347f8c9864b681558c278395e94035a741fc10cd865", size = 95315, upload-time = "2025-06-17T11:49:44.106Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -900,7 +900,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "huggingface-hub"
|
name = "huggingface-hub"
|
||||||
version = "0.32.4"
|
version = "0.33.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "filelock" },
|
{ name = "filelock" },
|
||||||
@@ -912,9 +912,9 @@ dependencies = [
|
|||||||
{ name = "tqdm" },
|
{ name = "tqdm" },
|
||||||
{ name = "typing-extensions" },
|
{ name = "typing-extensions" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/60/c8/4f7d270285c46324fd66f62159eb16739aa5696f422dba57678a8c6b78e9/huggingface_hub-0.32.4.tar.gz", hash = "sha256:f61d45cd338736f59fb0e97550b74c24ee771bcc92c05ae0766b9116abe720be", size = 424494, upload-time = "2025-06-03T09:59:46.105Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/91/8a/1362d565fefabaa4185cf3ae842a98dbc5b35146f5694f7080f043a6952f/huggingface_hub-0.33.0.tar.gz", hash = "sha256:aa31f70d29439d00ff7a33837c03f1f9dd83971ce4e29ad664d63ffb17d3bb97", size = 426179, upload-time = "2025-06-11T17:08:07.913Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/67/8b/222140f3cfb6f17b0dd8c4b9a0b36bd4ebefe9fb0098ba35d6960abcda0f/huggingface_hub-0.32.4-py3-none-any.whl", hash = "sha256:37abf8826b38d971f60d3625229221c36e53fe58060286db9baf619cfbf39767", size = 512101, upload-time = "2025-06-03T09:59:44.099Z" },
|
{ url = "https://files.pythonhosted.org/packages/33/fb/53587a89fbc00799e4179796f51b3ad713c5de6bb680b2becb6d37c94649/huggingface_hub-0.33.0-py3-none-any.whl", hash = "sha256:e8668875b40c68f9929150d99727d39e5ebb8a05a98e4191b908dc7ded9074b3", size = 514799, upload-time = "2025-06-11T17:08:05.757Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1225,7 +1225,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "locust"
|
name = "locust"
|
||||||
version = "2.37.9"
|
version = "2.37.11"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "configargparse" },
|
{ name = "configargparse" },
|
||||||
@@ -1245,14 +1245,14 @@ dependencies = [
|
|||||||
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
||||||
{ name = "werkzeug" },
|
{ name = "werkzeug" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/90/05/2bfdf19756c6a12f6f9513f75340ecf0595d83cab4d9fc91162225908e3d/locust-2.37.9.tar.gz", hash = "sha256:e43673b594ec5ecde4f9ba6e0d5c66c00d7c0ae93591951abe83e8d186c67175", size = 2252507, upload-time = "2025-06-05T09:26:58.186Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/4f/19/66cdab585f7d4385be615d3792402fc75a1bed7519e5283adbe7133dbc78/locust-2.37.11.tar.gz", hash = "sha256:89c79bc599aa57160bd41dd3876e35d8b9dee5abded78e35008d01fd8f1640ed", size = 2252602, upload-time = "2025-06-23T08:22:23.922Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/33/1c/0ece4176231c578e819d970ec08d124492833e50aafd171c582bcc414446/locust-2.37.9-py3-none-any.whl", hash = "sha256:e17da439f3a252d1fb6d4c34daf00d7e8b87e99d833a32e8a79f4f8ebb07767d", size = 2269084, upload-time = "2025-06-05T09:26:56.257Z" },
|
{ url = "https://files.pythonhosted.org/packages/3a/2d/e5ae05911521bf84113be349d51b16d54589e986837d2d518f63434ea3ec/locust-2.37.11-py3-none-any.whl", hash = "sha256:b826f95fbfd5d9a32df6ab1b74672b88e65bbc33ec99fdc10af98079952ad517", size = 2269179, upload-time = "2025-06-23T08:22:21.067Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "locust-cloud"
|
name = "locust-cloud"
|
||||||
version = "1.23.1"
|
version = "1.24.2"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "configargparse" },
|
{ name = "configargparse" },
|
||||||
@@ -1262,9 +1262,9 @@ dependencies = [
|
|||||||
{ name = "python-socketio", extra = ["client"] },
|
{ name = "python-socketio", extra = ["client"] },
|
||||||
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/bd/7c/d9cbbd051490aeedfbd6ddda8ad48f77dd848ee490f6ebd166d20db5911e/locust_cloud-1.23.1.tar.gz", hash = "sha256:a09161752b8c9a9205e97cef5223ee3ad967bc2d91c52d61952aaa3da6802a55", size = 450937, upload-time = "2025-06-05T06:07:53.773Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/d9/77/bda24167a2b763ba5d3cad1f3fa2a938f5273e51a61bffdbc8dc2e3ba24d/locust_cloud-1.24.2.tar.gz", hash = "sha256:a2656537ff367e6d4d4673477ba9e81ed73a8423a71573cd2512248740eded77", size = 451122, upload-time = "2025-06-23T11:08:00.558Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/7e/01/5af43edee540e38ba0ee0a2e3beb72c50073e0f646bb543a8b34650315e3/locust_cloud-1.23.1-py3-none-any.whl", hash = "sha256:11677895c6ed6d0beef1b425a6f04f10ea2cfcaeaefbf00a97fb3c9134296e54", size = 408323, upload-time = "2025-06-05T06:07:51.947Z" },
|
{ url = "https://files.pythonhosted.org/packages/f4/38/8cda8aa1c6dfe5c5abbf69a9b10c03585c37eff64ca92733a291806052ac/locust_cloud-1.24.2-py3-none-any.whl", hash = "sha256:64a5e6f2bf0a1a012d9805291d44fb57e57535c2b5c0fa5bc87ba0d7cce9ef9c", size = 408594, upload-time = "2025-06-23T11:07:59.092Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1415,7 +1415,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mypy"
|
name = "mypy"
|
||||||
version = "1.16.0"
|
version = "1.16.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "mypy-extensions" },
|
{ name = "mypy-extensions" },
|
||||||
@@ -1423,33 +1423,33 @@ dependencies = [
|
|||||||
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
||||||
{ name = "typing-extensions" },
|
{ name = "typing-extensions" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/d4/38/13c2f1abae94d5ea0354e146b95a1be9b2137a0d506728e0da037c4276f6/mypy-1.16.0.tar.gz", hash = "sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab", size = 3323139, upload-time = "2025-05-29T13:46:12.532Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/64/5e/a0485f0608a3d67029d3d73cec209278b025e3493a3acfda3ef3a88540fd/mypy-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7909541fef256527e5ee9c0a7e2aeed78b6cda72ba44298d1334fe7881b05c5c", size = 10967416, upload-time = "2025-05-29T13:34:17.783Z" },
|
{ url = "https://files.pythonhosted.org/packages/8e/12/2bf23a80fcef5edb75de9a1e295d778e0f46ea89eb8b115818b663eff42b/mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a", size = 10958644, upload-time = "2025-06-16T16:51:11.649Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/4b/53/5837c221f74c0d53a4bfc3003296f8179c3a2a7f336d7de7bbafbe96b688/mypy-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e71d6f0090c2256c713ed3d52711d01859c82608b5d68d4fa01a3fe30df95571", size = 10087654, upload-time = "2025-05-29T13:32:37.878Z" },
|
{ url = "https://files.pythonhosted.org/packages/08/50/bfe47b3b278eacf348291742fd5e6613bbc4b3434b72ce9361896417cfe5/mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72", size = 10087033, upload-time = "2025-06-16T16:35:30.089Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/29/59/5fd2400352c3093bed4c09017fe671d26bc5bb7e6ef2d4bf85f2a2488104/mypy-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:936ccfdd749af4766be824268bfe22d1db9eb2f34a3ea1d00ffbe5b5265f5491", size = 11875192, upload-time = "2025-05-29T13:34:54.281Z" },
|
{ url = "https://files.pythonhosted.org/packages/21/de/40307c12fe25675a0776aaa2cdd2879cf30d99eec91b898de00228dc3ab5/mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea", size = 11875645, upload-time = "2025-06-16T16:35:48.49Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ad/3e/4bfec74663a64c2012f3e278dbc29ffe82b121bc551758590d1b6449ec0c/mypy-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4086883a73166631307fdd330c4a9080ce24913d4f4c5ec596c601b3a4bdd777", size = 12612939, upload-time = "2025-05-29T13:33:14.766Z" },
|
{ url = "https://files.pythonhosted.org/packages/a6/d8/85bdb59e4a98b7a31495bd8f1a4445d8ffc86cde4ab1f8c11d247c11aedc/mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574", size = 12616986, upload-time = "2025-06-16T16:48:39.526Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/88/1f/fecbe3dcba4bf2ca34c26ca016383a9676711907f8db4da8354925cbb08f/mypy-1.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:feec38097f71797da0231997e0de3a58108c51845399669ebc532c815f93866b", size = 12874719, upload-time = "2025-05-29T13:21:52.09Z" },
|
{ url = "https://files.pythonhosted.org/packages/0e/d0/bb25731158fa8f8ee9e068d3e94fcceb4971fedf1424248496292512afe9/mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d", size = 12878632, upload-time = "2025-06-16T16:36:08.195Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f3/51/c2d280601cd816c43dfa512a759270d5a5ef638d7ac9bea9134c8305a12f/mypy-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:09a8da6a0ee9a9770b8ff61b39c0bb07971cda90e7297f4213741b48a0cc8d93", size = 9487053, upload-time = "2025-05-29T13:33:29.797Z" },
|
{ url = "https://files.pythonhosted.org/packages/2d/11/822a9beb7a2b825c0cb06132ca0a5183f8327a5e23ef89717c9474ba0bc6/mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6", size = 9484391, upload-time = "2025-06-16T16:37:56.151Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/24/c4/ff2f79db7075c274fe85b5fff8797d29c6b61b8854c39e3b7feb556aa377/mypy-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab", size = 10884498, upload-time = "2025-05-29T13:18:54.066Z" },
|
{ url = "https://files.pythonhosted.org/packages/9a/61/ec1245aa1c325cb7a6c0f8570a2eee3bfc40fa90d19b1267f8e50b5c8645/mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc", size = 10890557, upload-time = "2025-06-16T16:37:21.421Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/02/07/12198e83006235f10f6a7808917376b5d6240a2fd5dce740fe5d2ebf3247/mypy-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2", size = 10011755, upload-time = "2025-05-29T13:34:00.851Z" },
|
{ url = "https://files.pythonhosted.org/packages/6b/bb/6eccc0ba0aa0c7a87df24e73f0ad34170514abd8162eb0c75fd7128171fb/mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782", size = 10012921, upload-time = "2025-06-16T16:51:28.659Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f1/9b/5fd5801a72b5d6fb6ec0105ea1d0e01ab2d4971893076e558d4b6d6b5f80/mypy-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff", size = 11800138, upload-time = "2025-05-29T13:32:55.082Z" },
|
{ url = "https://files.pythonhosted.org/packages/5f/80/b337a12e2006715f99f529e732c5f6a8c143bb58c92bb142d5ab380963a5/mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507", size = 11802887, upload-time = "2025-06-16T16:50:53.627Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/2e/81/a117441ea5dfc3746431e51d78a4aca569c677aa225bca2cc05a7c239b61/mypy-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666", size = 12533156, upload-time = "2025-05-29T13:19:12.963Z" },
|
{ url = "https://files.pythonhosted.org/packages/d9/59/f7af072d09793d581a745a25737c7c0a945760036b16aeb620f658a017af/mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca", size = 12531658, upload-time = "2025-06-16T16:33:55.002Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/3f/38/88ec57c6c86014d3f06251e00f397b5a7daa6888884d0abf187e4f5f587f/mypy-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c", size = 12742426, upload-time = "2025-05-29T13:20:22.72Z" },
|
{ url = "https://files.pythonhosted.org/packages/82/c4/607672f2d6c0254b94a646cfc45ad589dd71b04aa1f3d642b840f7cce06c/mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4", size = 12732486, upload-time = "2025-06-16T16:37:03.301Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/bd/53/7e9d528433d56e6f6f77ccf24af6ce570986c2d98a5839e4c2009ef47283/mypy-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b", size = 9478319, upload-time = "2025-05-29T13:21:17.582Z" },
|
{ url = "https://files.pythonhosted.org/packages/b6/5e/136555ec1d80df877a707cebf9081bd3a9f397dedc1ab9750518d87489ec/mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6", size = 9479482, upload-time = "2025-06-16T16:47:37.48Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/70/cf/158e5055e60ca2be23aec54a3010f89dcffd788732634b344fc9cb1e85a0/mypy-1.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13", size = 11062927, upload-time = "2025-05-29T13:35:52.328Z" },
|
{ url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/94/34/cfff7a56be1609f5d10ef386342ce3494158e4d506516890142007e6472c/mypy-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090", size = 10083082, upload-time = "2025-05-29T13:35:33.378Z" },
|
{ url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b3/7f/7242062ec6288c33d8ad89574df87c3903d394870e5e6ba1699317a65075/mypy-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1", size = 11828306, upload-time = "2025-05-29T13:21:02.164Z" },
|
{ url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6f/5f/b392f7b4f659f5b619ce5994c5c43caab3d80df2296ae54fa888b3d17f5a/mypy-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8", size = 12702764, upload-time = "2025-05-29T13:20:42.826Z" },
|
{ url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9b/c0/7646ef3a00fa39ac9bc0938626d9ff29d19d733011be929cfea59d82d136/mypy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730", size = 12896233, upload-time = "2025-05-29T13:18:37.446Z" },
|
{ url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6d/38/52f4b808b3fef7f0ef840ee8ff6ce5b5d77381e65425758d515cdd4f5bb5/mypy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec", size = 9565547, upload-time = "2025-05-29T13:20:02.836Z" },
|
{ url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/97/9c/ca03bdbefbaa03b264b9318a98950a9c683e06472226b55472f96ebbc53d/mypy-1.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a9e056237c89f1587a3be1a3a70a06a698d25e2479b9a2f57325ddaaffc3567b", size = 11059753, upload-time = "2025-05-29T13:18:18.167Z" },
|
{ url = "https://files.pythonhosted.org/packages/28/e3/96964af4a75a949e67df4b95318fe2b7427ac8189bbc3ef28f92a1c5bc56/mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438", size = 11063480, upload-time = "2025-06-16T16:47:56.205Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/36/92/79a969b8302cfe316027c88f7dc6fee70129490a370b3f6eb11d777749d0/mypy-1.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b07e107affb9ee6ce1f342c07f51552d126c32cd62955f59a7db94a51ad12c0", size = 10073338, upload-time = "2025-05-29T13:19:48.079Z" },
|
{ url = "https://files.pythonhosted.org/packages/f5/4d/cd1a42b8e5be278fab7010fb289d9307a63e07153f0ae1510a3d7b703193/mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536", size = 10090538, upload-time = "2025-06-16T16:46:43.92Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/14/9b/a943f09319167da0552d5cd722104096a9c99270719b1afeea60d11610aa/mypy-1.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6fb60cbd85dc65d4d63d37cb5c86f4e3a301ec605f606ae3a9173e5cf34997b", size = 11827764, upload-time = "2025-05-29T13:46:04.47Z" },
|
{ url = "https://files.pythonhosted.org/packages/c9/4f/c3c6b4b66374b5f68bab07c8cabd63a049ff69796b844bc759a0ca99bb2a/mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f", size = 11836839, upload-time = "2025-06-16T16:36:28.039Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ec/64/ff75e71c65a0cb6ee737287c7913ea155845a556c64144c65b811afdb9c7/mypy-1.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7e32297a437cc915599e0578fa6bc68ae6a8dc059c9e009c628e1c47f91495d", size = 12701356, upload-time = "2025-05-29T13:35:13.553Z" },
|
{ url = "https://files.pythonhosted.org/packages/b4/7e/81ca3b074021ad9775e5cb97ebe0089c0f13684b066a750b7dc208438403/mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359", size = 12715634, upload-time = "2025-06-16T16:50:34.441Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/0a/ad/0e93c18987a1182c350f7a5fab70550852f9fabe30ecb63bfbe51b602074/mypy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:afe420c9380ccec31e744e8baff0d406c846683681025db3531b32db56962d52", size = 12900745, upload-time = "2025-05-29T13:17:24.409Z" },
|
{ url = "https://files.pythonhosted.org/packages/e9/95/bdd40c8be346fa4c70edb4081d727a54d0a05382d84966869738cfa8a497/mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be", size = 12895584, upload-time = "2025-06-16T16:34:54.857Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/28/5d/036c278d7a013e97e33f08c047fe5583ab4f1fc47c9a49f985f1cdd2a2d7/mypy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:55f9076c6ce55dd3f8cd0c6fff26a008ca8e5131b89d5ba6d86bd3f47e736eeb", size = 9572200, upload-time = "2025-05-29T13:33:44.92Z" },
|
{ url = "https://files.pythonhosted.org/packages/5a/fd/d486a0827a1c597b3b48b1bdef47228a6e9ee8102ab8c28f944cb83b65dc/mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee", size = 9573886, upload-time = "2025-06-16T16:36:43.589Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/99/a3/6ed10530dec8e0fdc890d81361260c9ef1f5e5c217ad8c9b21ecb2b8366b/mypy-1.16.0-py3-none-any.whl", hash = "sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031", size = 2265773, upload-time = "2025-05-29T13:35:18.762Z" },
|
{ url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1834,7 +1834,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pydantic"
|
name = "pydantic"
|
||||||
version = "2.11.5"
|
version = "2.11.7"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "annotated-types" },
|
{ name = "annotated-types" },
|
||||||
@@ -1842,9 +1842,9 @@ dependencies = [
|
|||||||
{ name = "typing-extensions" },
|
{ name = "typing-extensions" },
|
||||||
{ name = "typing-inspection" },
|
{ name = "typing-inspection" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/f0/86/8ce9040065e8f924d642c58e4a344e33163a07f6b57f836d0d734e0ad3fb/pydantic-2.11.5.tar.gz", hash = "sha256:7f853db3d0ce78ce8bbb148c401c2cdd6431b3473c0cdff2755c7690952a7b7a", size = 787102, upload-time = "2025-05-22T21:18:08.761Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/b5/69/831ed22b38ff9b4b64b66569f0e5b7b97cf3638346eb95a2147fdb49ad5f/pydantic-2.11.5-py3-none-any.whl", hash = "sha256:f9c26ba06f9747749ca1e5c94d6a85cb84254577553c8785576fd38fa64dc0f7", size = 444229, upload-time = "2025-05-22T21:18:06.329Z" },
|
{ url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1977,7 +1977,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "8.4.0"
|
version = "8.4.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||||
@@ -1988,9 +1988,9 @@ dependencies = [
|
|||||||
{ name = "pygments" },
|
{ name = "pygments" },
|
||||||
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/fb/aa/405082ce2749be5398045152251ac69c0f3578c7077efc53431303af97ce/pytest-8.4.0.tar.gz", hash = "sha256:14d920b48472ea0dbf68e45b96cd1ffda4705f33307dcc86c676c1b5104838a6", size = 1515232, upload-time = "2025-06-02T17:36:30.03Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/2f/de/afa024cbe022b1b318a3d224125aa24939e99b4ff6f22e0ba639a2eaee47/pytest-8.4.0-py3-none-any.whl", hash = "sha256:f40f825768ad76c0977cbacdf1fd37c6f7a468e460ea6a0636078f8972d4517e", size = 363797, upload-time = "2025-06-02T17:36:27.859Z" },
|
{ url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2007,15 +2007,16 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest-cov"
|
name = "pytest-cov"
|
||||||
version = "6.1.1"
|
version = "6.2.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "coverage", extra = ["toml"] },
|
{ name = "coverage", extra = ["toml"] },
|
||||||
|
{ name = "pluggy" },
|
||||||
{ name = "pytest" },
|
{ name = "pytest" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/25/69/5f1e57f6c5a39f81411b550027bf72842c4567ff5fd572bed1edc9e4b5d9/pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a", size = 66857, upload-time = "2025-04-05T14:07:51.592Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/18/99/668cade231f434aaa59bbfbf49469068d2ddd945000621d3d165d2e7dd7b/pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", size = 69432, upload-time = "2025-06-12T10:47:47.684Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/28/d0/def53b4a790cfb21483016430ed828f64830dd981ebe1089971cd10cab25/pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde", size = 23841, upload-time = "2025-04-05T14:07:49.641Z" },
|
{ url = "https://files.pythonhosted.org/packages/bc/16/4ea354101abb1287856baa4af2732be351c7bee728065aed451b678153fd/pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5", size = 24644, upload-time = "2025-06-12T10:47:45.932Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2303,27 +2304,27 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff"
|
name = "ruff"
|
||||||
version = "0.11.13"
|
version = "0.12.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ed/da/9c6f995903b4d9474b39da91d2d626659af3ff1eeb43e9ae7c119349dba6/ruff-0.11.13.tar.gz", hash = "sha256:26fa247dc68d1d4e72c179e08889a25ac0c7ba4d78aecfc835d49cbfd60bf514", size = 4282054, upload-time = "2025-06-05T21:00:15.721Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/24/90/5255432602c0b196a0da6720f6f76b93eb50baef46d3c9b0025e2f9acbf3/ruff-0.12.0.tar.gz", hash = "sha256:4d047db3662418d4a848a3fdbfaf17488b34b62f527ed6f10cb8afd78135bc5c", size = 4376101, upload-time = "2025-06-17T15:19:26.217Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/7d/ce/a11d381192966e0b4290842cc8d4fac7dc9214ddf627c11c1afff87da29b/ruff-0.11.13-py3-none-linux_armv6l.whl", hash = "sha256:4bdfbf1240533f40042ec00c9e09a3aade6f8c10b6414cf11b519488d2635d46", size = 10292516, upload-time = "2025-06-05T20:59:32.944Z" },
|
{ url = "https://files.pythonhosted.org/packages/e6/fd/b46bb20e14b11ff49dbc74c61de352e0dc07fb650189513631f6fb5fc69f/ruff-0.12.0-py3-none-linux_armv6l.whl", hash = "sha256:5652a9ecdb308a1754d96a68827755f28d5dfb416b06f60fd9e13f26191a8848", size = 10311554, upload-time = "2025-06-17T15:18:45.792Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/78/db/87c3b59b0d4e753e40b6a3b4a2642dfd1dcaefbff121ddc64d6c8b47ba00/ruff-0.11.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aef9c9ed1b5ca28bb15c7eac83b8670cf3b20b478195bd49c8d756ba0a36cf48", size = 11106083, upload-time = "2025-06-05T20:59:37.03Z" },
|
{ url = "https://files.pythonhosted.org/packages/e7/d3/021dde5a988fa3e25d2468d1dadeea0ae89dc4bc67d0140c6e68818a12a1/ruff-0.12.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:05ed0c914fabc602fc1f3b42c53aa219e5736cb030cdd85640c32dbc73da74a6", size = 11118435, upload-time = "2025-06-17T15:18:49.064Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/77/79/d8cec175856ff810a19825d09ce700265f905c643c69f45d2b737e4a470a/ruff-0.11.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53b15a9dfdce029c842e9a5aebc3855e9ab7771395979ff85b7c1dedb53ddc2b", size = 10436024, upload-time = "2025-06-05T20:59:39.741Z" },
|
{ url = "https://files.pythonhosted.org/packages/07/a2/01a5acf495265c667686ec418f19fd5c32bcc326d4c79ac28824aecd6a32/ruff-0.12.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:07a7aa9b69ac3fcfda3c507916d5d1bca10821fe3797d46bad10f2c6de1edda0", size = 10466010, upload-time = "2025-06-17T15:18:51.341Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8b/5b/f6d94f2980fa1ee854b41568368a2e1252681b9238ab2895e133d303538f/ruff-0.11.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab153241400789138d13f362c43f7edecc0edfffce2afa6a68434000ecd8f69a", size = 10646324, upload-time = "2025-06-05T20:59:42.185Z" },
|
{ url = "https://files.pythonhosted.org/packages/4c/57/7caf31dd947d72e7aa06c60ecb19c135cad871a0a8a251723088132ce801/ruff-0.12.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7731c3eec50af71597243bace7ec6104616ca56dda2b99c89935fe926bdcd48", size = 10661366, upload-time = "2025-06-17T15:18:53.29Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6c/9c/b4c2acf24ea4426016d511dfdc787f4ce1ceb835f3c5fbdbcb32b1c63bda/ruff-0.11.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c51f93029d54a910d3d24f7dd0bb909e31b6cd989a5e4ac513f4eb41629f0dc", size = 10174416, upload-time = "2025-06-05T20:59:44.319Z" },
|
{ url = "https://files.pythonhosted.org/packages/e9/ba/aa393b972a782b4bc9ea121e0e358a18981980856190d7d2b6187f63e03a/ruff-0.12.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:952d0630eae628250ab1c70a7fffb641b03e6b4a2d3f3ec6c1d19b4ab6c6c807", size = 10173492, upload-time = "2025-06-17T15:18:55.262Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f3/10/e2e62f77c65ede8cd032c2ca39c41f48feabedb6e282bfd6073d81bb671d/ruff-0.11.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1808b3ed53e1a777c2ef733aca9051dc9bf7c99b26ece15cb59a0320fbdbd629", size = 11724197, upload-time = "2025-06-05T20:59:46.935Z" },
|
{ url = "https://files.pythonhosted.org/packages/d7/50/9349ee777614bc3062fc6b038503a59b2034d09dd259daf8192f56c06720/ruff-0.12.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c021f04ea06966b02614d442e94071781c424ab8e02ec7af2f037b4c1e01cc82", size = 11761739, upload-time = "2025-06-17T15:18:58.906Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/bb/f0/466fe8469b85c561e081d798c45f8a1d21e0b4a5ef795a1d7f1a9a9ec182/ruff-0.11.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d28ce58b5ecf0f43c1b71edffabe6ed7f245d5336b17805803312ec9bc665933", size = 12511615, upload-time = "2025-06-05T20:59:49.534Z" },
|
{ url = "https://files.pythonhosted.org/packages/04/8f/ad459de67c70ec112e2ba7206841c8f4eb340a03ee6a5cabc159fe558b8e/ruff-0.12.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d235618283718ee2fe14db07f954f9b2423700919dc688eacf3f8797a11315c", size = 12537098, upload-time = "2025-06-17T15:19:01.316Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/17/0e/cefe778b46dbd0cbcb03a839946c8f80a06f7968eb298aa4d1a4293f3448/ruff-0.11.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55e4bc3a77842da33c16d55b32c6cac1ec5fb0fbec9c8c513bdce76c4f922165", size = 12117080, upload-time = "2025-06-05T20:59:51.654Z" },
|
{ url = "https://files.pythonhosted.org/packages/ed/50/15ad9c80ebd3c4819f5bd8883e57329f538704ed57bac680d95cb6627527/ruff-0.12.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0758038f81beec8cc52ca22de9685b8ae7f7cc18c013ec2050012862cc9165", size = 12154122, upload-time = "2025-06-17T15:19:03.727Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/5d/2c/caaeda564cbe103bed145ea557cb86795b18651b0f6b3ff6a10e84e5a33f/ruff-0.11.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:633bf2c6f35678c56ec73189ba6fa19ff1c5e4807a78bf60ef487b9dd272cc71", size = 11326315, upload-time = "2025-06-05T20:59:54.469Z" },
|
{ url = "https://files.pythonhosted.org/packages/76/e6/79b91e41bc8cc3e78ee95c87093c6cacfa275c786e53c9b11b9358026b3d/ruff-0.12.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:139b3d28027987b78fc8d6cfb61165447bdf3740e650b7c480744873688808c2", size = 11363374, upload-time = "2025-06-17T15:19:05.875Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/75/f0/782e7d681d660eda8c536962920c41309e6dd4ebcea9a2714ed5127d44bd/ruff-0.11.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ffbc82d70424b275b089166310448051afdc6e914fdab90e08df66c43bb5ca9", size = 11555640, upload-time = "2025-06-05T20:59:56.986Z" },
|
{ url = "https://files.pythonhosted.org/packages/db/c3/82b292ff8a561850934549aa9dc39e2c4e783ab3c21debe55a495ddf7827/ruff-0.12.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68853e8517b17bba004152aebd9dd77d5213e503a5f2789395b25f26acac0da4", size = 11587647, upload-time = "2025-06-17T15:19:08.246Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/5d/d4/3d580c616316c7f07fb3c99dbecfe01fbaea7b6fd9a82b801e72e5de742a/ruff-0.11.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a9ddd3ec62a9a89578c85842b836e4ac832d4a2e0bfaad3b02243f930ceafcc", size = 10507364, upload-time = "2025-06-05T20:59:59.154Z" },
|
{ url = "https://files.pythonhosted.org/packages/2b/42/d5760d742669f285909de1bbf50289baccb647b53e99b8a3b4f7ce1b2001/ruff-0.12.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3a9512af224b9ac4757f7010843771da6b2b0935a9e5e76bb407caa901a1a514", size = 10527284, upload-time = "2025-06-17T15:19:10.37Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/5a/dc/195e6f17d7b3ea6b12dc4f3e9de575db7983db187c378d44606e5d503319/ruff-0.11.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d237a496e0778d719efb05058c64d28b757c77824e04ffe8796c7436e26712b7", size = 10141462, upload-time = "2025-06-05T21:00:01.481Z" },
|
{ url = "https://files.pythonhosted.org/packages/19/f6/fcee9935f25a8a8bba4adbae62495c39ef281256693962c2159e8b284c5f/ruff-0.12.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b08df3d96db798e5beb488d4df03011874aff919a97dcc2dd8539bb2be5d6a88", size = 10158609, upload-time = "2025-06-17T15:19:12.286Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f4/8e/39a094af6967faa57ecdeacb91bedfb232474ff8c3d20f16a5514e6b3534/ruff-0.11.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26816a218ca6ef02142343fd24c70f7cd8c5aa6c203bca284407adf675984432", size = 11121028, upload-time = "2025-06-05T21:00:04.06Z" },
|
{ url = "https://files.pythonhosted.org/packages/37/fb/057febf0eea07b9384787bfe197e8b3384aa05faa0d6bd844b94ceb29945/ruff-0.12.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6a315992297a7435a66259073681bb0d8647a826b7a6de45c6934b2ca3a9ed51", size = 11141462, upload-time = "2025-06-17T15:19:15.195Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/5a/c0/b0b508193b0e8a1654ec683ebab18d309861f8bd64e3a2f9648b80d392cb/ruff-0.11.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:51c3f95abd9331dc5b87c47ac7f376db5616041173826dfd556cfe3d4977f492", size = 11602992, upload-time = "2025-06-05T21:00:06.249Z" },
|
{ url = "https://files.pythonhosted.org/packages/10/7c/1be8571011585914b9d23c95b15d07eec2d2303e94a03df58294bc9274d4/ruff-0.12.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1e55e44e770e061f55a7dbc6e9aed47feea07731d809a3710feda2262d2d4d8a", size = 11641616, upload-time = "2025-06-17T15:19:17.6Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7c/91/263e33ab93ab09ca06ce4f8f8547a858cc198072f873ebc9be7466790bae/ruff-0.11.13-py3-none-win32.whl", hash = "sha256:96c27935418e4e8e77a26bb05962817f28b8ef3843a6c6cc49d8783b5507f250", size = 10474944, upload-time = "2025-06-05T21:00:08.459Z" },
|
{ url = "https://files.pythonhosted.org/packages/6a/ef/b960ab4818f90ff59e571d03c3f992828d4683561095e80f9ef31f3d58b7/ruff-0.12.0-py3-none-win32.whl", hash = "sha256:7162a4c816f8d1555eb195c46ae0bd819834d2a3f18f98cc63819a7b46f474fb", size = 10525289, upload-time = "2025-06-17T15:19:19.688Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/46/f4/7c27734ac2073aae8efb0119cae6931b6fb48017adf048fdf85c19337afc/ruff-0.11.13-py3-none-win_amd64.whl", hash = "sha256:29c3189895a8a6a657b7af4e97d330c8a3afd2c9c8f46c81e2fc5a31866517e3", size = 11548669, upload-time = "2025-06-05T21:00:11.147Z" },
|
{ url = "https://files.pythonhosted.org/packages/34/93/8b16034d493ef958a500f17cda3496c63a537ce9d5a6479feec9558f1695/ruff-0.12.0-py3-none-win_amd64.whl", hash = "sha256:d00b7a157b8fb6d3827b49d3324da34a1e3f93492c1f97b08e222ad7e9b291e0", size = 11598311, upload-time = "2025-06-17T15:19:21.785Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ec/bf/b273dd11673fed8a6bd46032c0ea2a04b2ac9bfa9c628756a5856ba113b0/ruff-0.11.13-py3-none-win_arm64.whl", hash = "sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b", size = 10683928, upload-time = "2025-06-05T21:00:13.758Z" },
|
{ url = "https://files.pythonhosted.org/packages/d0/33/4d3e79e4a84533d6cd526bfb42c020a23256ae5e4265d858bd1287831f7d/ruff-0.12.0-py3-none-win_arm64.whl", hash = "sha256:8cd24580405ad8c1cc64d61725bca091d6b6da7eb3d36f72cc605467069d7e8b", size = 10724946, upload-time = "2025-06-17T15:19:23.952Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2558,14 +2559,14 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "types-requests"
|
name = "types-requests"
|
||||||
version = "2.32.0.20250602"
|
version = "2.32.4.20250611"
|
||||||
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/48/b0/5321e6eeba5d59e4347fcf9bf06a5052f085c3aa0f4876230566d6a4dc97/types_requests-2.32.0.20250602.tar.gz", hash = "sha256:ee603aeefec42051195ae62ca7667cd909a2f8128fdf8aad9e8a5219ecfab3bf", size = 23042, upload-time = "2025-06-02T03:15:02.958Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/6d/7f/73b3a04a53b0fd2a911d4ec517940ecd6600630b559e4505cc7b68beb5a0/types_requests-2.32.4.20250611.tar.gz", hash = "sha256:741c8777ed6425830bf51e54d6abe245f79b4dcb9019f1622b773463946bf826", size = 23118, upload-time = "2025-06-11T03:11:41.272Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/da/18/9b782980e575c6581d5c0c1c99f4c6f89a1d7173dad072ee96b2756c02e6/types_requests-2.32.0.20250602-py3-none-any.whl", hash = "sha256:f4f335f87779b47ce10b8b8597b409130299f6971ead27fead4fe7ba6ea3e726", size = 20638, upload-time = "2025-06-02T03:15:01.959Z" },
|
{ url = "https://files.pythonhosted.org/packages/3d/ea/0be9258c5a4fa1ba2300111aa5a0767ee6d18eb3fd20e91616c12082284d/types_requests-2.32.4.20250611-py3-none-any.whl", hash = "sha256:ad2fe5d3b0cb3c2c902c8815a70e7fb2302c4b8c1f77bdcd738192cdb3878072", size = 20643, upload-time = "2025-06-11T03:11:40.186Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -90,6 +90,35 @@
|
|||||||
<data android:mimeType="video/*" />
|
<data android:mimeType="video/*" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- immich:// URL scheme handling -->
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data android:scheme="immich" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- my.immich.app deep link -->
|
||||||
|
<intent-filter android:autoVerify="true">
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data android:scheme="https" />
|
||||||
|
|
||||||
|
<data
|
||||||
|
android:host="my.immich.app"
|
||||||
|
android:path="/" />
|
||||||
|
<data
|
||||||
|
android:host="my.immich.app"
|
||||||
|
android:pathPrefix="/albums/" />
|
||||||
|
<data
|
||||||
|
android:host="my.immich.app"
|
||||||
|
android:pathPrefix="/memories/" />
|
||||||
|
<data
|
||||||
|
android:host="my.immich.app"
|
||||||
|
android:pathPrefix="/photos/" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ platform :android do
|
|||||||
task: 'bundle',
|
task: 'bundle',
|
||||||
build_type: 'Release',
|
build_type: 'Release',
|
||||||
properties: {
|
properties: {
|
||||||
"android.injected.version.code" => 201,
|
"android.injected.version.code" => 204,
|
||||||
"android.injected.version.name" => "1.135.0",
|
"android.injected.version.name" => "1.135.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')
|
||||||
|
|||||||
@@ -346,6 +346,7 @@
|
|||||||
};
|
};
|
||||||
F0B57D372DF764BD00DC5BCC = {
|
F0B57D372DF764BD00DC5BCC = {
|
||||||
CreatedOnToolsVersion = 16.4;
|
CreatedOnToolsVersion = 16.4;
|
||||||
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
FAC6F88F2D287C890078CB2F = {
|
FAC6F88F2D287C890078CB2F = {
|
||||||
CreatedOnToolsVersion = 16.0;
|
CreatedOnToolsVersion = 16.0;
|
||||||
@@ -648,7 +649,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 = 208;
|
CURRENT_PROJECT_VERSION = 210;
|
||||||
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;
|
||||||
@@ -792,7 +793,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 = 208;
|
CURRENT_PROJECT_VERSION = 210;
|
||||||
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;
|
||||||
@@ -822,7 +823,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 = 208;
|
CURRENT_PROJECT_VERSION = 210;
|
||||||
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;
|
||||||
@@ -856,7 +857,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 210;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
@@ -864,7 +865,7 @@
|
|||||||
INFOPLIST_FILE = WidgetExtension/Info.plist;
|
INFOPLIST_FILE = WidgetExtension/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Widget;
|
INFOPLIST_KEY_CFBundleDisplayName = Widget;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
|
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -899,7 +900,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 210;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
@@ -907,7 +908,7 @@
|
|||||||
INFOPLIST_FILE = WidgetExtension/Info.plist;
|
INFOPLIST_FILE = WidgetExtension/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Widget;
|
INFOPLIST_KEY_CFBundleDisplayName = Widget;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
|
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -939,7 +940,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 210;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
@@ -947,7 +948,7 @@
|
|||||||
INFOPLIST_FILE = WidgetExtension/Info.plist;
|
INFOPLIST_FILE = WidgetExtension/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Widget;
|
INFOPLIST_KEY_CFBundleDisplayName = Widget;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
|
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -978,7 +979,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 = 208;
|
CURRENT_PROJECT_VERSION = 210;
|
||||||
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;
|
||||||
@@ -1022,7 +1023,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 = 208;
|
CURRENT_PROJECT_VERSION = 210;
|
||||||
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;
|
||||||
@@ -1063,7 +1064,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 = 208;
|
CURRENT_PROJECT_VERSION = 210;
|
||||||
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;
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.134.0</string>
|
<string>1.135.1</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
@@ -86,14 +86,26 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleTypeRole</key>
|
<key>CFBundleTypeRole</key>
|
||||||
<string>Editor</string>
|
<string>Editor</string>
|
||||||
|
<key>CFBundleURLName</key>
|
||||||
|
<string>Share Extension</string>
|
||||||
<key>CFBundleURLSchemes</key>
|
<key>CFBundleURLSchemes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Editor</string>
|
||||||
|
<key>CFBundleURLName</key>
|
||||||
|
<string>Deep Link</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>immich</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>208</string>
|
<string>210</string>
|
||||||
<key>FLTEnableImpeller</key>
|
<key>FLTEnableImpeller</key>
|
||||||
<true />
|
<true />
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
@@ -115,11 +127,13 @@
|
|||||||
</dict>
|
</dict>
|
||||||
<key>NSBonjourServices</key>
|
<key>NSBonjourServices</key>
|
||||||
<array>
|
<array>
|
||||||
<string>_googlecast._tcp</string>
|
<string>_googlecast._tcp</string>
|
||||||
<string>_CC1AD845._googlecast._tcp</string>
|
<string>_CC1AD845._googlecast._tcp</string>
|
||||||
</array>
|
</array>
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>NSCameraUsageDescription</key>
|
||||||
<string>We need to access the camera to let you take beautiful video using this app</string>
|
<string>We need to access the camera to let you take beautiful video using this app</string>
|
||||||
|
<key>NSFaceIDUsageDescription</key>
|
||||||
|
<string>We need to use FaceID to allow access to your locked folder</string>
|
||||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||||
<string>We require this permission to access the local WiFi name for background upload mechanism</string>
|
<string>We require this permission to access the local WiFi name for background upload mechanism</string>
|
||||||
<key>NSLocationUsageDescription</key>
|
<key>NSLocationUsageDescription</key>
|
||||||
@@ -166,7 +180,8 @@
|
|||||||
<true />
|
<true />
|
||||||
<key>io.flutter.embedded_views_preview</key>
|
<key>io.flutter.embedded_views_preview</key>
|
||||||
<true />
|
<true />
|
||||||
<key>NSFaceIDUsageDescription</key>
|
<key>NSLocalNetworkUsageDescription</key>
|
||||||
<string>We need to use FaceID to allow access to your locked folder</string>
|
<string>We need local network permission to connect to the local server using IP address and
|
||||||
|
allow the casting feature to work</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
@@ -2,6 +2,10 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>com.apple.developer.associated-domains</key>
|
||||||
|
<array>
|
||||||
|
<string>applinks:my.immich.app</string>
|
||||||
|
</array>
|
||||||
<key>com.apple.developer.networking.wifi-info</key>
|
<key>com.apple.developer.networking.wifi-info</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>aps-environment</key>
|
<key>aps-environment</key>
|
||||||
<string>development</string>
|
<string>development</string>
|
||||||
|
<key>com.apple.developer.associated-domains</key>
|
||||||
|
<array>
|
||||||
|
<string>applinks:my.immich.app</string>
|
||||||
|
</array>
|
||||||
<key>com.apple.developer.networking.wifi-info</key>
|
<key>com.apple.developer.networking.wifi-info</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
|
|||||||
@@ -24,27 +24,11 @@ struct ImageEntry: TimelineEntry {
|
|||||||
struct ImmichWidgetView: View {
|
struct ImmichWidgetView: View {
|
||||||
var entry: ImageEntry
|
var entry: ImageEntry
|
||||||
|
|
||||||
func getErrorText(_ error: WidgetError?) -> String {
|
|
||||||
switch error {
|
|
||||||
case .noLogin:
|
|
||||||
return "Login to Immich"
|
|
||||||
|
|
||||||
case .fetchFailed:
|
|
||||||
return "Unable to connect to your Immich instance"
|
|
||||||
|
|
||||||
case .albumNotFound:
|
|
||||||
return "Album not found"
|
|
||||||
|
|
||||||
default:
|
|
||||||
return "An unknown error occured"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if entry.image == nil {
|
if entry.image == nil {
|
||||||
VStack {
|
VStack {
|
||||||
Image("LaunchImage")
|
Image("LaunchImage")
|
||||||
Text(getErrorText(entry.error))
|
Text(entry.error?.errorDescription ?? "")
|
||||||
.minimumScaleFactor(0.25)
|
.minimumScaleFactor(0.25)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
|
|||||||
@@ -8,6 +8,32 @@ enum WidgetError: Error {
|
|||||||
case unknown
|
case unknown
|
||||||
case albumNotFound
|
case albumNotFound
|
||||||
case unableToResize
|
case unableToResize
|
||||||
|
case invalidImage
|
||||||
|
case invalidURL
|
||||||
|
}
|
||||||
|
|
||||||
|
extension WidgetError: LocalizedError {
|
||||||
|
public var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .noLogin:
|
||||||
|
return "Login to Immich"
|
||||||
|
|
||||||
|
case .fetchFailed:
|
||||||
|
return "Unable to connect to your Immich instance"
|
||||||
|
|
||||||
|
case .albumNotFound:
|
||||||
|
return "Album not found"
|
||||||
|
|
||||||
|
case .invalidURL:
|
||||||
|
return "An invalid URL was used"
|
||||||
|
|
||||||
|
case .invalidImage:
|
||||||
|
return "An invalid image was received"
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "An unknown error occured"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AssetType: String, Codable {
|
enum AssetType: String, Codable {
|
||||||
@@ -146,7 +172,7 @@ class ImmichAPI {
|
|||||||
return try JSONDecoder().decode([MemoryResult].self, from: data)
|
return try JSONDecoder().decode([MemoryResult].self, from: data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchImage(asset: SearchResult) async throws -> UIImage {
|
func fetchImage(asset: SearchResult) async throws(WidgetError) -> UIImage {
|
||||||
let thumbnailParams = [URLQueryItem(name: "size", value: "preview")]
|
let thumbnailParams = [URLQueryItem(name: "size", value: "preview")]
|
||||||
let assetEndpoint = "/assets/" + asset.id + "/thumbnail"
|
let assetEndpoint = "/assets/" + asset.id + "/thumbnail"
|
||||||
|
|
||||||
@@ -157,16 +183,24 @@ class ImmichAPI {
|
|||||||
params: thumbnailParams
|
params: thumbnailParams
|
||||||
)
|
)
|
||||||
else {
|
else {
|
||||||
throw URLError(.badURL)
|
throw .invalidURL
|
||||||
}
|
}
|
||||||
|
|
||||||
let (data, _) = try await URLSession.shared.data(from: fetchURL)
|
guard let imageSource = CGImageSourceCreateWithURL(fetchURL as CFURL, nil) else {
|
||||||
|
throw .invalidURL
|
||||||
guard let img = UIImage(data: data) else {
|
|
||||||
throw URLError(.badServerResponse)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return img
|
let decodeOptions: [NSString: Any] = [
|
||||||
|
kCGImageSourceCreateThumbnailFromImageAlways: true,
|
||||||
|
kCGImageSourceThumbnailMaxPixelSize: 400,
|
||||||
|
kCGImageSourceCreateThumbnailWithTransform: true
|
||||||
|
]
|
||||||
|
|
||||||
|
guard let thumbnail = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, decodeOptions as CFDictionary) else {
|
||||||
|
throw .fetchFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
return UIImage(cgImage: thumbnail)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchAlbums() async throws -> [Album] {
|
func fetchAlbums() async throws -> [Album] {
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ struct RandomConfigurationAppIntent: WidgetConfigurationIntent {
|
|||||||
"Choose an album to show images from"
|
"Choose an album to show images from"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Parameter(title: "Album", default: NO_ALBUM)
|
@Parameter(title: "Album")
|
||||||
var album: Album?
|
var album: Album?
|
||||||
|
|
||||||
@Parameter(title: "Show Album Name", default: false)
|
@Parameter(title: "Show Album Name", default: false)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ platform :ios do
|
|||||||
path: "./Runner.xcodeproj",
|
path: "./Runner.xcodeproj",
|
||||||
)
|
)
|
||||||
increment_version_number(
|
increment_version_number(
|
||||||
version_number: "1.135.0"
|
version_number: "1.135.3"
|
||||||
)
|
)
|
||||||
increment_build_number(
|
increment_build_number(
|
||||||
build_number: latest_testflight_build_number + 1,
|
build_number: latest_testflight_build_number + 1,
|
||||||
|
|||||||
@@ -10,3 +10,5 @@ enum TextSearchType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum AssetVisibilityEnum { timeline, hidden, archive, locked }
|
enum AssetVisibilityEnum { timeline, hidden, archive, locked }
|
||||||
|
|
||||||
|
enum SortUserBy { id }
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const Map<String, Locale> locales = {
|
|||||||
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'SIMPLIFIED'),
|
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'SIMPLIFIED'),
|
||||||
'Chinese Traditional (zh_TW)':
|
'Chinese Traditional (zh_TW)':
|
||||||
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'),
|
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'),
|
||||||
|
'Croatian (hr)': Locale('hr'),
|
||||||
'Czech (cs)': Locale('cs'),
|
'Czech (cs)': Locale('cs'),
|
||||||
'Danish (da)': Locale('da'),
|
'Danish (da)': Locale('da'),
|
||||||
'Dutch (nl)': Locale('nl'),
|
'Dutch (nl)': Locale('nl'),
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
import 'dart:typed_data';
|
|
||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
abstract interface class IAssetMediaRepository {
|
|
||||||
Future<Uint8List?> getThumbnail(
|
|
||||||
String id, {
|
|
||||||
int quality = 80,
|
|
||||||
Size size = const Size.square(256),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/device_asset.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IDeviceAssetRepository implements IDatabaseRepository {
|
|
||||||
Future<bool> updateAll(List<DeviceAsset> assetHash);
|
|
||||||
|
|
||||||
Future<List<DeviceAsset>> getByIds(List<String> localIds);
|
|
||||||
|
|
||||||
Future<void> deleteIds(List<String> ids);
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/exif.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IExifInfoRepository implements IDatabaseRepository {
|
|
||||||
Future<ExifInfo?> get(int assetId);
|
|
||||||
|
|
||||||
Future<ExifInfo> update(ExifInfo exifInfo);
|
|
||||||
|
|
||||||
Future<List<ExifInfo>> updateAll(List<ExifInfo> exifInfos);
|
|
||||||
|
|
||||||
Future<void> delete(int assetId);
|
|
||||||
|
|
||||||
Future<void> deleteAll();
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/local_album.model.dart';
|
|
||||||
|
|
||||||
abstract interface class ILocalAlbumRepository implements IDatabaseRepository {
|
|
||||||
Future<List<LocalAlbum>> getAll({Set<SortLocalAlbumsBy> sortBy = const {}});
|
|
||||||
|
|
||||||
Future<List<LocalAsset>> getAssets(String albumId);
|
|
||||||
|
|
||||||
Future<List<String>> getAssetIds(String albumId);
|
|
||||||
|
|
||||||
Future<void> upsert(
|
|
||||||
LocalAlbum album, {
|
|
||||||
Iterable<LocalAsset> toUpsert = const [],
|
|
||||||
Iterable<String> toDelete = const [],
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<void> updateAll(Iterable<LocalAlbum> albums);
|
|
||||||
|
|
||||||
Future<void> delete(String albumId);
|
|
||||||
|
|
||||||
Future<void> processDelta({
|
|
||||||
required List<LocalAsset> updates,
|
|
||||||
required List<String> deletes,
|
|
||||||
required Map<String, List<String>> assetAlbums,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<void> syncDeletes(String albumId, Iterable<String> assetIdsToKeep);
|
|
||||||
|
|
||||||
Future<List<LocalAsset>> getAssetsToHash(String albumId);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum SortLocalAlbumsBy { id, backupSelection, isIosSharedAlbum }
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|
||||||
|
|
||||||
abstract interface class ILocalAssetRepository implements IDatabaseRepository {
|
|
||||||
Future<void> updateHashes(Iterable<LocalAsset> hashes);
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/log.model.dart';
|
|
||||||
|
|
||||||
abstract interface class ILogRepository implements IDatabaseRepository {
|
|
||||||
Future<bool> insert(LogMessage log);
|
|
||||||
|
|
||||||
Future<bool> insertAll(Iterable<LogMessage> logs);
|
|
||||||
|
|
||||||
Future<List<LogMessage>> getAll();
|
|
||||||
|
|
||||||
Future<bool> deleteAll();
|
|
||||||
|
|
||||||
/// Truncates the logs to the most recent [limit]. Defaults to recent 250 logs
|
|
||||||
Future<void> truncate({int limit = 250});
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IStorageRepository {
|
|
||||||
Future<File?> getFileForAsset(LocalAsset asset);
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IStoreRepository implements IDatabaseRepository {
|
|
||||||
Future<bool> insert<T>(StoreKey<T> key, T value);
|
|
||||||
|
|
||||||
Future<T?> tryGet<T>(StoreKey<T> key);
|
|
||||||
|
|
||||||
Future<List<StoreDto<Object>>> getAll();
|
|
||||||
|
|
||||||
Stream<T?> watch<T>(StoreKey<T> key);
|
|
||||||
|
|
||||||
Stream<StoreDto<Object>> watchAll();
|
|
||||||
|
|
||||||
Future<bool> update<T>(StoreKey<T> key, T value);
|
|
||||||
|
|
||||||
Future<void> delete<T>(StoreKey<T> key);
|
|
||||||
|
|
||||||
Future<void> deleteAll();
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import 'package:http/http.dart' as http;
|
|
||||||
import 'package:immich_mobile/domain/models/sync_event.model.dart';
|
|
||||||
|
|
||||||
abstract interface class ISyncApiRepository {
|
|
||||||
Future<void> ack(List<String> data);
|
|
||||||
|
|
||||||
Future<void> streamChanges(
|
|
||||||
Function(List<SyncEvent>, Function() abort) onData, {
|
|
||||||
int batchSize,
|
|
||||||
http.Client? httpClient,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
|
||||||
import 'package:openapi/api.dart';
|
|
||||||
|
|
||||||
abstract interface class ISyncStreamRepository implements IDatabaseRepository {
|
|
||||||
Future<void> updateUsersV1(Iterable<SyncUserV1> data);
|
|
||||||
Future<void> deleteUsersV1(Iterable<SyncUserDeleteV1> data);
|
|
||||||
|
|
||||||
Future<void> updatePartnerV1(Iterable<SyncPartnerV1> data);
|
|
||||||
Future<void> deletePartnerV1(Iterable<SyncPartnerDeleteV1> data);
|
|
||||||
|
|
||||||
Future<void> updateAssetsV1(Iterable<SyncAssetV1> data);
|
|
||||||
Future<void> deleteAssetsV1(Iterable<SyncAssetDeleteV1> data);
|
|
||||||
Future<void> updateAssetsExifV1(Iterable<SyncAssetExifV1> data);
|
|
||||||
|
|
||||||
Future<void> updatePartnerAssetsV1(Iterable<SyncAssetV1> data);
|
|
||||||
Future<void> deletePartnerAssetsV1(Iterable<SyncAssetDeleteV1> data);
|
|
||||||
Future<void> updatePartnerAssetsExifV1(Iterable<SyncAssetExifV1> data);
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
|
||||||
|
|
||||||
abstract interface class ITimelineRepository implements IDatabaseRepository {
|
|
||||||
Stream<List<Bucket>> watchMainBucket(
|
|
||||||
List<String> timelineUsers, {
|
|
||||||
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<List<BaseAsset>> getMainBucketAssets(
|
|
||||||
List<String> timelineUsers, {
|
|
||||||
required int offset,
|
|
||||||
required int count,
|
|
||||||
});
|
|
||||||
|
|
||||||
Stream<List<Bucket>> watchLocalBucket(
|
|
||||||
String albumId, {
|
|
||||||
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<List<BaseAsset>> getLocalBucketAssets(
|
|
||||||
String albumId, {
|
|
||||||
required int offset,
|
|
||||||
required int count,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IUserRepository implements IDatabaseRepository {
|
|
||||||
Future<bool> insert(UserDto user);
|
|
||||||
|
|
||||||
Future<UserDto?> getByUserId(String id);
|
|
||||||
|
|
||||||
Future<List<UserDto?>> getByUserIds(List<String> ids);
|
|
||||||
|
|
||||||
Future<List<UserDto>> getAll({SortUserBy? sortBy});
|
|
||||||
|
|
||||||
Future<bool> updateAll(List<UserDto> users);
|
|
||||||
|
|
||||||
Future<UserDto> update(UserDto user);
|
|
||||||
|
|
||||||
Future<void> delete(List<String> ids);
|
|
||||||
|
|
||||||
Future<void> deleteAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
enum SortUserBy { id }
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import 'dart:typed_data';
|
|
||||||
|
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IUserApiRepository {
|
|
||||||
Future<UserDto?> getMyUser();
|
|
||||||
|
|
||||||
Future<List<UserDto>> getAll();
|
|
||||||
|
|
||||||
/// Saves the [data] in the server and uses it as the current users profile image
|
|
||||||
Future<String> createProfileImage({
|
|
||||||
required String name,
|
|
||||||
required Uint8List data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,5 @@
|
|||||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
abstract interface class IPersonApiRepository {
|
|
||||||
Future<List<Person>> getAll();
|
|
||||||
Future<Person> update(String id, {String? name});
|
|
||||||
}
|
|
||||||
|
|
||||||
class Person {
|
class Person {
|
||||||
Person({
|
Person({
|
||||||
required this.id,
|
required this.id,
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:immich_mobile/constants/constants.dart';
|
import 'package:immich_mobile/constants/constants.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/local_album.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/interfaces/local_asset.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/interfaces/storage.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
||||||
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
||||||
import 'package:immich_mobile/presentation/pages/dev/dev_logger.dart';
|
import 'package:immich_mobile/presentation/pages/dev/dev_logger.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
@@ -12,16 +12,16 @@ import 'package:logging/logging.dart';
|
|||||||
class HashService {
|
class HashService {
|
||||||
final int batchSizeLimit;
|
final int batchSizeLimit;
|
||||||
final int batchFileLimit;
|
final int batchFileLimit;
|
||||||
final ILocalAlbumRepository _localAlbumRepository;
|
final DriftLocalAlbumRepository _localAlbumRepository;
|
||||||
final ILocalAssetRepository _localAssetRepository;
|
final DriftLocalAssetRepository _localAssetRepository;
|
||||||
final IStorageRepository _storageRepository;
|
final StorageRepository _storageRepository;
|
||||||
final NativeSyncApi _nativeSyncApi;
|
final NativeSyncApi _nativeSyncApi;
|
||||||
final _log = Logger('HashService');
|
final _log = Logger('HashService');
|
||||||
|
|
||||||
HashService({
|
HashService({
|
||||||
required ILocalAlbumRepository localAlbumRepository,
|
required DriftLocalAlbumRepository localAlbumRepository,
|
||||||
required ILocalAssetRepository localAssetRepository,
|
required DriftLocalAssetRepository localAssetRepository,
|
||||||
required IStorageRepository storageRepository,
|
required StorageRepository storageRepository,
|
||||||
required NativeSyncApi nativeSyncApi,
|
required NativeSyncApi nativeSyncApi,
|
||||||
this.batchSizeLimit = kBatchHashSizeLimit,
|
this.batchSizeLimit = kBatchHashSizeLimit,
|
||||||
this.batchFileLimit = kBatchHashFileLimit,
|
this.batchFileLimit = kBatchHashFileLimit,
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/local_album.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/local_album.model.dart';
|
import 'package:immich_mobile/domain/models/local_album.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
import 'package:immich_mobile/domain/services/store.service.dart';
|
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||||
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
||||||
import 'package:immich_mobile/presentation/pages/dev/dev_logger.dart';
|
import 'package:immich_mobile/presentation/pages/dev/dev_logger.dart';
|
||||||
import 'package:immich_mobile/utils/diff.dart';
|
import 'package:immich_mobile/utils/diff.dart';
|
||||||
@@ -14,14 +14,14 @@ import 'package:logging/logging.dart';
|
|||||||
import 'package:platform/platform.dart';
|
import 'package:platform/platform.dart';
|
||||||
|
|
||||||
class LocalSyncService {
|
class LocalSyncService {
|
||||||
final ILocalAlbumRepository _localAlbumRepository;
|
final DriftLocalAlbumRepository _localAlbumRepository;
|
||||||
final NativeSyncApi _nativeSyncApi;
|
final NativeSyncApi _nativeSyncApi;
|
||||||
final Platform _platform;
|
final Platform _platform;
|
||||||
final StoreService _storeService;
|
final StoreService _storeService;
|
||||||
final Logger _log = Logger("DeviceSyncService");
|
final Logger _log = Logger("DeviceSyncService");
|
||||||
|
|
||||||
LocalSyncService({
|
LocalSyncService({
|
||||||
required ILocalAlbumRepository localAlbumRepository,
|
required DriftLocalAlbumRepository localAlbumRepository,
|
||||||
required NativeSyncApi nativeSyncApi,
|
required NativeSyncApi nativeSyncApi,
|
||||||
required StoreService storeService,
|
required StoreService storeService,
|
||||||
Platform? platform,
|
Platform? platform,
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:immich_mobile/constants/constants.dart';
|
import 'package:immich_mobile/constants/constants.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/log.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/interfaces/store.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/log.model.dart';
|
import 'package:immich_mobile/domain/models/log.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/log.repository.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/store.repository.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
/// Service responsible for handling application logging.
|
/// Service responsible for handling application logging.
|
||||||
@@ -14,8 +14,8 @@ import 'package:logging/logging.dart';
|
|||||||
/// writes them to a persistent [ILogRepository], and manages log levels
|
/// writes them to a persistent [ILogRepository], and manages log levels
|
||||||
/// via [IStoreRepository]
|
/// via [IStoreRepository]
|
||||||
class LogService {
|
class LogService {
|
||||||
final ILogRepository _logRepository;
|
final IsarLogRepository _logRepository;
|
||||||
final IStoreRepository _storeRepository;
|
final IsarStoreRepository _storeRepository;
|
||||||
|
|
||||||
final List<LogMessage> _msgBuffer = [];
|
final List<LogMessage> _msgBuffer = [];
|
||||||
|
|
||||||
@@ -37,8 +37,8 @@ class LogService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<LogService> init({
|
static Future<LogService> init({
|
||||||
required ILogRepository logRepository,
|
required IsarLogRepository logRepository,
|
||||||
required IStoreRepository storeRepository,
|
required IsarStoreRepository storeRepository,
|
||||||
bool shouldBuffer = true,
|
bool shouldBuffer = true,
|
||||||
}) async {
|
}) async {
|
||||||
_instance ??= await create(
|
_instance ??= await create(
|
||||||
@@ -50,8 +50,8 @@ class LogService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<LogService> create({
|
static Future<LogService> create({
|
||||||
required ILogRepository logRepository,
|
required IsarLogRepository logRepository,
|
||||||
required IStoreRepository storeRepository,
|
required IsarStoreRepository storeRepository,
|
||||||
bool shouldBuffer = true,
|
bool shouldBuffer = true,
|
||||||
}) async {
|
}) async {
|
||||||
final instance = LogService._(logRepository, storeRepository, shouldBuffer);
|
final instance = LogService._(logRepository, storeRepository, shouldBuffer);
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:immich_mobile/domain/interfaces/store.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/store.repository.dart';
|
||||||
|
|
||||||
/// Provides access to a persistent key-value store with an in-memory cache.
|
/// Provides access to a persistent key-value store with an in-memory cache.
|
||||||
/// Listens for repository changes to keep the cache updated.
|
/// Listens for repository changes to keep the cache updated.
|
||||||
class StoreService {
|
class StoreService {
|
||||||
final IStoreRepository _storeRepository;
|
final IsarStoreRepository _storeRepository;
|
||||||
|
|
||||||
/// In-memory cache. Keys are [StoreKey.id]
|
/// In-memory cache. Keys are [StoreKey.id]
|
||||||
final Map<int, Object?> _cache = {};
|
final Map<int, Object?> _cache = {};
|
||||||
late final StreamSubscription<StoreDto> _storeUpdateSubscription;
|
late final StreamSubscription<StoreDto> _storeUpdateSubscription;
|
||||||
|
|
||||||
StoreService._({required IStoreRepository storeRepository})
|
StoreService._({required IsarStoreRepository storeRepository})
|
||||||
: _storeRepository = storeRepository;
|
: _storeRepository = storeRepository;
|
||||||
|
|
||||||
// TODO: Temporary typedef to make minimal changes. Remove this and make the presentation layer access store through a provider
|
// TODO: Temporary typedef to make minimal changes. Remove this and make the presentation layer access store through a provider
|
||||||
@@ -26,14 +26,14 @@ class StoreService {
|
|||||||
|
|
||||||
// TODO: Replace the implementation with the one from create after removing the typedef
|
// TODO: Replace the implementation with the one from create after removing the typedef
|
||||||
static Future<StoreService> init({
|
static Future<StoreService> init({
|
||||||
required IStoreRepository storeRepository,
|
required IsarStoreRepository storeRepository,
|
||||||
}) async {
|
}) async {
|
||||||
_instance ??= await create(storeRepository: storeRepository);
|
_instance ??= await create(storeRepository: storeRepository);
|
||||||
return _instance!;
|
return _instance!;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<StoreService> create({
|
static Future<StoreService> create({
|
||||||
required IStoreRepository storeRepository,
|
required IsarStoreRepository storeRepository,
|
||||||
}) async {
|
}) async {
|
||||||
final instance = StoreService._(storeRepository: storeRepository);
|
final instance = StoreService._(storeRepository: storeRepository);
|
||||||
await instance._populateCache();
|
await instance._populateCache();
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:immich_mobile/domain/interfaces/sync_api.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/interfaces/sync_stream.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/sync_event.model.dart';
|
import 'package:immich_mobile/domain/models/sync_event.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/sync_api.repository.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:openapi/api.dart';
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
class SyncStreamService {
|
class SyncStreamService {
|
||||||
final Logger _logger = Logger('SyncStreamService');
|
final Logger _logger = Logger('SyncStreamService');
|
||||||
|
|
||||||
final ISyncApiRepository _syncApiRepository;
|
final SyncApiRepository _syncApiRepository;
|
||||||
final ISyncStreamRepository _syncStreamRepository;
|
final SyncStreamRepository _syncStreamRepository;
|
||||||
final bool Function()? _cancelChecker;
|
final bool Function()? _cancelChecker;
|
||||||
|
|
||||||
SyncStreamService({
|
SyncStreamService({
|
||||||
required ISyncApiRepository syncApiRepository,
|
required SyncApiRepository syncApiRepository,
|
||||||
required ISyncStreamRepository syncStreamRepository,
|
required SyncStreamRepository syncStreamRepository,
|
||||||
bool Function()? cancelChecker,
|
bool Function()? cancelChecker,
|
||||||
}) : _syncApiRepository = syncApiRepository,
|
}) : _syncApiRepository = syncApiRepository,
|
||||||
_syncStreamRepository = syncStreamRepository,
|
_syncStreamRepository = syncStreamRepository,
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import 'dart:math' as math;
|
|||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:immich_mobile/constants/constants.dart';
|
import 'package:immich_mobile/constants/constants.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/timeline.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/setting.model.dart';
|
import 'package:immich_mobile/domain/models/setting.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||||
import 'package:immich_mobile/domain/services/setting.service.dart';
|
import 'package:immich_mobile/domain/services/setting.service.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
||||||
import 'package:immich_mobile/utils/async_mutex.dart';
|
import 'package:immich_mobile/utils/async_mutex.dart';
|
||||||
|
|
||||||
typedef TimelineAssetSource = Future<List<BaseAsset>> Function(
|
typedef TimelineAssetSource = Future<List<BaseAsset>> Function(
|
||||||
@@ -18,11 +18,11 @@ typedef TimelineAssetSource = Future<List<BaseAsset>> Function(
|
|||||||
typedef TimelineBucketSource = Stream<List<Bucket>> Function();
|
typedef TimelineBucketSource = Stream<List<Bucket>> Function();
|
||||||
|
|
||||||
class TimelineFactory {
|
class TimelineFactory {
|
||||||
final ITimelineRepository _timelineRepository;
|
final DriftTimelineRepository _timelineRepository;
|
||||||
final SettingsService _settingsService;
|
final SettingsService _settingsService;
|
||||||
|
|
||||||
const TimelineFactory({
|
const TimelineFactory({
|
||||||
required ITimelineRepository timelineRepository,
|
required DriftTimelineRepository timelineRepository,
|
||||||
required SettingsService settingsService,
|
required SettingsService settingsService,
|
||||||
}) : _timelineRepository = timelineRepository,
|
}) : _timelineRepository = timelineRepository,
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:immich_mobile/domain/interfaces/user.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/interfaces/user_api.interface.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/services/store.service.dart';
|
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/user_api.repository.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
class UserService {
|
class UserService {
|
||||||
final Logger _log = Logger("UserService");
|
final Logger _log = Logger("UserService");
|
||||||
final IUserRepository _userRepository;
|
final IsarUserRepository _isarUserRepository;
|
||||||
final IUserApiRepository _userApiRepository;
|
final UserApiRepository _userApiRepository;
|
||||||
final StoreService _storeService;
|
final StoreService _storeService;
|
||||||
|
|
||||||
UserService({
|
UserService({
|
||||||
required IUserRepository userRepository,
|
required IsarUserRepository isarUserRepository,
|
||||||
required IUserApiRepository userApiRepository,
|
required UserApiRepository userApiRepository,
|
||||||
required StoreService storeService,
|
required StoreService storeService,
|
||||||
}) : _userRepository = userRepository,
|
}) : _isarUserRepository = isarUserRepository,
|
||||||
_userApiRepository = userApiRepository,
|
_userApiRepository = userApiRepository,
|
||||||
_storeService = storeService;
|
_storeService = storeService;
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ class UserService {
|
|||||||
final user = await _userApiRepository.getMyUser();
|
final user = await _userApiRepository.getMyUser();
|
||||||
if (user == null) return null;
|
if (user == null) return null;
|
||||||
await _storeService.put(StoreKey.currentUser, user);
|
await _storeService.put(StoreKey.currentUser, user);
|
||||||
await _userRepository.update(user);
|
await _isarUserRepository.update(user);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ class UserService {
|
|||||||
);
|
);
|
||||||
final updatedUser = getMyUser().copyWith(profileImagePath: path);
|
final updatedUser = getMyUser().copyWith(profileImagePath: path);
|
||||||
await _storeService.put(StoreKey.currentUser, updatedUser);
|
await _storeService.put(StoreKey.currentUser, updatedUser);
|
||||||
await _userRepository.update(updatedUser);
|
await _isarUserRepository.update(updatedUser);
|
||||||
return path;
|
return path;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_log.warning("Failed to upload profile image", e);
|
_log.warning("Failed to upload profile image", e);
|
||||||
@@ -59,10 +59,10 @@ class UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<UserDto>> getAll() async {
|
Future<List<UserDto>> getAll() async {
|
||||||
return await _userRepository.getAll();
|
return await _isarUserRepository.getAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteAll() {
|
Future<void> deleteAll() {
|
||||||
return _userRepository.deleteAll();
|
return _isarUserRepository.deleteAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:immich_mobile/domain/interfaces/asset_media.interface.dart';
|
|
||||||
import 'package:photo_manager/photo_manager.dart';
|
import 'package:photo_manager/photo_manager.dart';
|
||||||
|
|
||||||
class AssetMediaRepository implements IAssetMediaRepository {
|
class AssetMediaRepository {
|
||||||
const AssetMediaRepository();
|
const AssetMediaRepository();
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Uint8List?> getThumbnail(
|
Future<Uint8List?> getThumbnail(
|
||||||
String id, {
|
String id, {
|
||||||
int quality = 80,
|
int quality = 80,
|
||||||
|
|||||||
@@ -1,23 +1,19 @@
|
|||||||
import 'package:immich_mobile/domain/interfaces/device_asset.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/device_asset.model.dart';
|
import 'package:immich_mobile/domain/models/device_asset.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/device_asset.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/device_asset.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
class IsarDeviceAssetRepository extends IsarDatabaseRepository
|
class IsarDeviceAssetRepository extends IsarDatabaseRepository {
|
||||||
implements IDeviceAssetRepository {
|
|
||||||
final Isar _db;
|
final Isar _db;
|
||||||
|
|
||||||
const IsarDeviceAssetRepository(this._db) : super(_db);
|
const IsarDeviceAssetRepository(this._db) : super(_db);
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> deleteIds(List<String> ids) {
|
Future<void> deleteIds(List<String> ids) {
|
||||||
return transaction(() async {
|
return transaction(() async {
|
||||||
await _db.deviceAssetEntitys.deleteAllByAssetId(ids.toList());
|
await _db.deviceAssetEntitys.deleteAllByAssetId(ids.toList());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<DeviceAsset>> getByIds(List<String> localIds) {
|
Future<List<DeviceAsset>> getByIds(List<String> localIds) {
|
||||||
return _db.deviceAssetEntitys
|
return _db.deviceAssetEntitys
|
||||||
.where()
|
.where()
|
||||||
@@ -26,7 +22,6 @@ class IsarDeviceAssetRepository extends IsarDatabaseRepository
|
|||||||
.then((value) => value.map((e) => e.toModel()).toList());
|
.then((value) => value.map((e) => e.toModel()).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> updateAll(List<DeviceAsset> assetHash) {
|
Future<bool> updateAll(List<DeviceAsset> assetHash) {
|
||||||
return transaction(() async {
|
return transaction(() async {
|
||||||
await _db.deviceAssetEntitys
|
await _db.deviceAssetEntitys
|
||||||
|
|||||||
@@ -1,36 +1,30 @@
|
|||||||
import 'package:immich_mobile/domain/interfaces/exif.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/exif.model.dart';
|
import 'package:immich_mobile/domain/models/exif.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/exif.entity.dart'
|
import 'package:immich_mobile/infrastructure/entities/exif.entity.dart'
|
||||||
as entity;
|
as entity;
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
class IsarExifRepository extends IsarDatabaseRepository
|
class IsarExifRepository extends IsarDatabaseRepository {
|
||||||
implements IExifInfoRepository {
|
|
||||||
final Isar _db;
|
final Isar _db;
|
||||||
|
|
||||||
const IsarExifRepository(this._db) : super(_db);
|
const IsarExifRepository(this._db) : super(_db);
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> delete(int assetId) async {
|
Future<void> delete(int assetId) async {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
await _db.exifInfos.delete(assetId);
|
await _db.exifInfos.delete(assetId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> deleteAll() async {
|
Future<void> deleteAll() async {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
await _db.exifInfos.clear();
|
await _db.exifInfos.clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<ExifInfo?> get(int assetId) async {
|
Future<ExifInfo?> get(int assetId) async {
|
||||||
return (await _db.exifInfos.get(assetId))?.toDto();
|
return (await _db.exifInfos.get(assetId))?.toDto();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<ExifInfo> update(ExifInfo exifInfo) {
|
Future<ExifInfo> update(ExifInfo exifInfo) {
|
||||||
return transaction(() async {
|
return transaction(() async {
|
||||||
await _db.exifInfos.put(entity.ExifInfo.fromDto(exifInfo));
|
await _db.exifInfos.put(entity.ExifInfo.fromDto(exifInfo));
|
||||||
@@ -38,7 +32,6 @@ class IsarExifRepository extends IsarDatabaseRepository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<ExifInfo>> updateAll(List<ExifInfo> exifInfos) {
|
Future<List<ExifInfo>> updateAll(List<ExifInfo> exifInfos) {
|
||||||
return transaction(() async {
|
return transaction(() async {
|
||||||
await _db.exifInfos.putAll(
|
await _db.exifInfos.putAll(
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/local_album.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/local_album.model.dart';
|
import 'package:immich_mobile/domain/models/local_album.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart';
|
||||||
@@ -8,15 +7,15 @@ import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.d
|
|||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
import 'package:platform/platform.dart';
|
import 'package:platform/platform.dart';
|
||||||
|
|
||||||
class DriftLocalAlbumRepository extends DriftDatabaseRepository
|
enum SortLocalAlbumsBy { id, backupSelection, isIosSharedAlbum }
|
||||||
implements ILocalAlbumRepository {
|
|
||||||
|
class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
||||||
final Drift _db;
|
final Drift _db;
|
||||||
final Platform _platform;
|
final Platform _platform;
|
||||||
const DriftLocalAlbumRepository(this._db, {Platform? platform})
|
const DriftLocalAlbumRepository(this._db, {Platform? platform})
|
||||||
: _platform = platform ?? const LocalPlatform(),
|
: _platform = platform ?? const LocalPlatform(),
|
||||||
super(_db);
|
super(_db);
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<LocalAlbum>> getAll({Set<SortLocalAlbumsBy> sortBy = const {}}) {
|
Future<List<LocalAlbum>> getAll({Set<SortLocalAlbumsBy> sortBy = const {}}) {
|
||||||
final assetCount = _db.localAlbumAssetEntity.assetId.count();
|
final assetCount = _db.localAlbumAssetEntity.assetId.count();
|
||||||
|
|
||||||
@@ -56,7 +55,6 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository
|
|||||||
.get();
|
.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> delete(String albumId) => transaction(() async {
|
Future<void> delete(String albumId) => transaction(() async {
|
||||||
// Remove all assets that are only in this particular album
|
// Remove all assets that are only in this particular album
|
||||||
// We cannot remove all assets in the album because they might be in other albums in iOS
|
// We cannot remove all assets in the album because they might be in other albums in iOS
|
||||||
@@ -72,7 +70,6 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository
|
|||||||
.delete();
|
.delete();
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> syncDeletes(
|
Future<void> syncDeletes(
|
||||||
String albumId,
|
String albumId,
|
||||||
Iterable<String> assetIdsToKeep,
|
Iterable<String> assetIdsToKeep,
|
||||||
@@ -101,7 +98,6 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository
|
|||||||
await deleteSmt.go();
|
await deleteSmt.go();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> upsert(
|
Future<void> upsert(
|
||||||
LocalAlbum localAlbum, {
|
LocalAlbum localAlbum, {
|
||||||
Iterable<LocalAsset> toUpsert = const [],
|
Iterable<LocalAsset> toUpsert = const [],
|
||||||
@@ -134,7 +130,6 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> updateAll(Iterable<LocalAlbum> albums) {
|
Future<void> updateAll(Iterable<LocalAlbum> albums) {
|
||||||
return _db.transaction(() async {
|
return _db.transaction(() async {
|
||||||
await _db.localAlbumEntity
|
await _db.localAlbumEntity
|
||||||
@@ -185,7 +180,6 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<LocalAsset>> getAssets(String albumId) {
|
Future<List<LocalAsset>> getAssets(String albumId) {
|
||||||
final query = _db.localAlbumAssetEntity.select().join(
|
final query = _db.localAlbumAssetEntity.select().join(
|
||||||
[
|
[
|
||||||
@@ -202,7 +196,6 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository
|
|||||||
.get();
|
.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<String>> getAssetIds(String albumId) {
|
Future<List<String>> getAssetIds(String albumId) {
|
||||||
final query = _db.localAlbumAssetEntity.selectOnly()
|
final query = _db.localAlbumAssetEntity.selectOnly()
|
||||||
..addColumns([_db.localAlbumAssetEntity.assetId])
|
..addColumns([_db.localAlbumAssetEntity.assetId])
|
||||||
@@ -212,7 +205,6 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository
|
|||||||
.get();
|
.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> processDelta({
|
Future<void> processDelta({
|
||||||
required List<LocalAsset> updates,
|
required List<LocalAsset> updates,
|
||||||
required List<String> deletes,
|
required List<String> deletes,
|
||||||
@@ -253,7 +245,6 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<LocalAsset>> getAssetsToHash(String albumId) {
|
Future<List<LocalAsset>> getAssetsToHash(String albumId) {
|
||||||
final query = _db.localAlbumAssetEntity.select().join(
|
final query = _db.localAlbumAssetEntity.select().join(
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/local_asset.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
|
|
||||||
class DriftLocalAssetRepository extends DriftDatabaseRepository
|
class DriftLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
implements ILocalAssetRepository {
|
|
||||||
final Drift _db;
|
final Drift _db;
|
||||||
const DriftLocalAssetRepository(this._db) : super(_db);
|
const DriftLocalAssetRepository(this._db) : super(_db);
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> updateHashes(Iterable<LocalAsset> hashes) {
|
Future<void> updateHashes(Iterable<LocalAsset> hashes) {
|
||||||
if (hashes.isEmpty) {
|
if (hashes.isEmpty) {
|
||||||
return Future.value();
|
return Future.value();
|
||||||
|
|||||||
@@ -1,28 +1,23 @@
|
|||||||
import 'package:immich_mobile/domain/interfaces/log.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/log.model.dart';
|
import 'package:immich_mobile/domain/models/log.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/log.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/log.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
class IsarLogRepository extends IsarDatabaseRepository
|
class IsarLogRepository extends IsarDatabaseRepository {
|
||||||
implements ILogRepository {
|
|
||||||
final Isar _db;
|
final Isar _db;
|
||||||
const IsarLogRepository(super.db) : _db = db;
|
const IsarLogRepository(super.db) : _db = db;
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> deleteAll() async {
|
Future<bool> deleteAll() async {
|
||||||
await transaction(() async => await _db.loggerMessages.clear());
|
await transaction(() async => await _db.loggerMessages.clear());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<LogMessage>> getAll() async {
|
Future<List<LogMessage>> getAll() async {
|
||||||
final logs =
|
final logs =
|
||||||
await _db.loggerMessages.where().sortByCreatedAtDesc().findAll();
|
await _db.loggerMessages.where().sortByCreatedAtDesc().findAll();
|
||||||
return logs.map((l) => l.toDto()).toList();
|
return logs.map((l) => l.toDto()).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> insert(LogMessage log) async {
|
Future<bool> insert(LogMessage log) async {
|
||||||
final logEntity = LoggerMessage.fromDto(log);
|
final logEntity = LoggerMessage.fromDto(log);
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
@@ -31,7 +26,6 @@ class IsarLogRepository extends IsarDatabaseRepository
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> insertAll(Iterable<LogMessage> logs) async {
|
Future<bool> insertAll(Iterable<LogMessage> logs) async {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
final logEntities =
|
final logEntities =
|
||||||
@@ -41,7 +35,6 @@ class IsarLogRepository extends IsarDatabaseRepository
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> truncate({int limit = 250}) async {
|
Future<void> truncate({int limit = 250}) async {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
final count = await _db.loggerMessages.count();
|
final count = await _db.loggerMessages.count();
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:immich_mobile/domain/interfaces/storage.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:photo_manager/photo_manager.dart';
|
import 'package:photo_manager/photo_manager.dart';
|
||||||
|
|
||||||
class StorageRepository implements IStorageRepository {
|
class StorageRepository {
|
||||||
final _log = Logger('StorageRepository');
|
final _log = Logger('StorageRepository');
|
||||||
|
|
||||||
@override
|
|
||||||
Future<File?> getFileForAsset(LocalAsset asset) async {
|
Future<File?> getFileForAsset(LocalAsset asset) async {
|
||||||
File? file;
|
File? file;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import 'package:immich_mobile/domain/interfaces/store.interface.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/infrastructure/entities/store.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/store.entity.dart';
|
||||||
@@ -6,14 +5,12 @@ import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
|||||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
class IsarStoreRepository extends IsarDatabaseRepository
|
class IsarStoreRepository extends IsarDatabaseRepository {
|
||||||
implements IStoreRepository {
|
|
||||||
final Isar _db;
|
final Isar _db;
|
||||||
final validStoreKeys = StoreKey.values.map((e) => e.id).toSet();
|
final validStoreKeys = StoreKey.values.map((e) => e.id).toSet();
|
||||||
|
|
||||||
IsarStoreRepository(super.db) : _db = db;
|
IsarStoreRepository(super.db) : _db = db;
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> deleteAll() async {
|
Future<bool> deleteAll() async {
|
||||||
return await transaction(() async {
|
return await transaction(() async {
|
||||||
await _db.storeValues.clear();
|
await _db.storeValues.clear();
|
||||||
@@ -21,7 +18,6 @@ class IsarStoreRepository extends IsarDatabaseRepository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Stream<StoreDto<Object>> watchAll() {
|
Stream<StoreDto<Object>> watchAll() {
|
||||||
return _db.storeValues
|
return _db.storeValues
|
||||||
.filter()
|
.filter()
|
||||||
@@ -34,12 +30,10 @@ class IsarStoreRepository extends IsarDatabaseRepository
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> delete<T>(StoreKey<T> key) async {
|
Future<void> delete<T>(StoreKey<T> key) async {
|
||||||
return await transaction(() async => await _db.storeValues.delete(key.id));
|
return await transaction(() async => await _db.storeValues.delete(key.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> insert<T>(StoreKey<T> key, T value) async {
|
Future<bool> insert<T>(StoreKey<T> key, T value) async {
|
||||||
return await transaction(() async {
|
return await transaction(() async {
|
||||||
await _db.storeValues.put(await _fromValue(key, value));
|
await _db.storeValues.put(await _fromValue(key, value));
|
||||||
@@ -47,7 +41,6 @@ class IsarStoreRepository extends IsarDatabaseRepository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<T?> tryGet<T>(StoreKey<T> key) async {
|
Future<T?> tryGet<T>(StoreKey<T> key) async {
|
||||||
final entity = (await _db.storeValues.get(key.id));
|
final entity = (await _db.storeValues.get(key.id));
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
@@ -56,7 +49,6 @@ class IsarStoreRepository extends IsarDatabaseRepository
|
|||||||
return await _toValue(key, entity);
|
return await _toValue(key, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> update<T>(StoreKey<T> key, T value) async {
|
Future<bool> update<T>(StoreKey<T> key, T value) async {
|
||||||
return await transaction(() async {
|
return await transaction(() async {
|
||||||
await _db.storeValues.put(await _fromValue(key, value));
|
await _db.storeValues.put(await _fromValue(key, value));
|
||||||
@@ -64,7 +56,6 @@ class IsarStoreRepository extends IsarDatabaseRepository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Stream<T?> watch<T>(StoreKey<T> key) async* {
|
Stream<T?> watch<T>(StoreKey<T> key) async* {
|
||||||
yield* _db.storeValues
|
yield* _db.storeValues
|
||||||
.watchObject(key.id, fireImmediately: true)
|
.watchObject(key.id, fireImmediately: true)
|
||||||
@@ -109,7 +100,6 @@ class IsarStoreRepository extends IsarDatabaseRepository
|
|||||||
return StoreValue(key.id, intValue: intValue, strValue: strValue);
|
return StoreValue(key.id, intValue: intValue, strValue: strValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<StoreDto<Object>>> getAll() async {
|
Future<List<StoreDto<Object>>> getAll() async {
|
||||||
final entities = await _db.storeValues
|
final entities = await _db.storeValues
|
||||||
.filter()
|
.filter()
|
||||||
|
|||||||
@@ -3,24 +3,21 @@ import 'dart:convert';
|
|||||||
|
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:immich_mobile/constants/constants.dart';
|
import 'package:immich_mobile/constants/constants.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/sync_api.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/sync_event.model.dart';
|
import 'package:immich_mobile/domain/models/sync_event.model.dart';
|
||||||
import 'package:immich_mobile/presentation/pages/dev/dev_logger.dart';
|
import 'package:immich_mobile/presentation/pages/dev/dev_logger.dart';
|
||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:openapi/api.dart';
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
class SyncApiRepository implements ISyncApiRepository {
|
class SyncApiRepository {
|
||||||
final Logger _logger = Logger('SyncApiRepository');
|
final Logger _logger = Logger('SyncApiRepository');
|
||||||
final ApiService _api;
|
final ApiService _api;
|
||||||
SyncApiRepository(this._api);
|
SyncApiRepository(this._api);
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> ack(List<String> data) {
|
Future<void> ack(List<String> data) {
|
||||||
return _api.syncApi.sendSyncAck(SyncAckSetDto(acks: data));
|
return _api.syncApi.sendSyncAck(SyncAckSetDto(acks: data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> streamChanges(
|
Future<void> streamChanges(
|
||||||
Function(List<SyncEvent>, Function() abort) onData, {
|
Function(List<SyncEvent>, Function() abort) onData, {
|
||||||
int batchSize = kSyncEventBatchSize,
|
int batchSize = kSyncEventBatchSize,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/sync_stream.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart';
|
||||||
@@ -10,14 +9,12 @@ import 'package:logging/logging.dart';
|
|||||||
import 'package:openapi/api.dart' as api show AssetVisibility;
|
import 'package:openapi/api.dart' as api show AssetVisibility;
|
||||||
import 'package:openapi/api.dart' hide AssetVisibility;
|
import 'package:openapi/api.dart' hide AssetVisibility;
|
||||||
|
|
||||||
class DriftSyncStreamRepository extends DriftDatabaseRepository
|
class SyncStreamRepository extends DriftDatabaseRepository {
|
||||||
implements ISyncStreamRepository {
|
|
||||||
final Logger _logger = Logger('DriftSyncStreamRepository');
|
final Logger _logger = Logger('DriftSyncStreamRepository');
|
||||||
final Drift _db;
|
final Drift _db;
|
||||||
|
|
||||||
DriftSyncStreamRepository(super.db) : _db = db;
|
SyncStreamRepository(super.db) : _db = db;
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> deleteUsersV1(Iterable<SyncUserDeleteV1> data) async {
|
Future<void> deleteUsersV1(Iterable<SyncUserDeleteV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
@@ -34,7 +31,6 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> updateUsersV1(Iterable<SyncUserV1> data) async {
|
Future<void> updateUsersV1(Iterable<SyncUserV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
@@ -57,7 +53,6 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> deletePartnerV1(Iterable<SyncPartnerDeleteV1> data) async {
|
Future<void> deletePartnerV1(Iterable<SyncPartnerDeleteV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
@@ -77,7 +72,6 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> updatePartnerV1(Iterable<SyncPartnerV1> data) async {
|
Future<void> updatePartnerV1(Iterable<SyncPartnerV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _db.batch((batch) {
|
await _db.batch((batch) {
|
||||||
@@ -101,7 +95,6 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> deleteAssetsV1(Iterable<SyncAssetDeleteV1> data) async {
|
Future<void> deleteAssetsV1(Iterable<SyncAssetDeleteV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _deleteAssetsV1(data);
|
await _deleteAssetsV1(data);
|
||||||
@@ -111,7 +104,6 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> updateAssetsV1(Iterable<SyncAssetV1> data) async {
|
Future<void> updateAssetsV1(Iterable<SyncAssetV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _updateAssetsV1(data);
|
await _updateAssetsV1(data);
|
||||||
@@ -121,7 +113,6 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> deletePartnerAssetsV1(Iterable<SyncAssetDeleteV1> data) async {
|
Future<void> deletePartnerAssetsV1(Iterable<SyncAssetDeleteV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _deleteAssetsV1(data);
|
await _deleteAssetsV1(data);
|
||||||
@@ -131,7 +122,6 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> updatePartnerAssetsV1(Iterable<SyncAssetV1> data) async {
|
Future<void> updatePartnerAssetsV1(Iterable<SyncAssetV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _updateAssetsV1(data);
|
await _updateAssetsV1(data);
|
||||||
@@ -141,7 +131,6 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> updateAssetsExifV1(Iterable<SyncAssetExifV1> data) async {
|
Future<void> updateAssetsExifV1(Iterable<SyncAssetExifV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _updateAssetExifV1(data);
|
await _updateAssetExifV1(data);
|
||||||
@@ -151,7 +140,6 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> updatePartnerAssetsExifV1(Iterable<SyncAssetExifV1> data) async {
|
Future<void> updatePartnerAssetsExifV1(Iterable<SyncAssetExifV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _updateAssetExifV1(data);
|
await _updateAssetExifV1(data);
|
||||||
|
|||||||
@@ -3,15 +3,13 @@ import 'dart:async';
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:immich_mobile/constants/constants.dart';
|
import 'package:immich_mobile/constants/constants.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/timeline.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
import 'package:stream_transform/stream_transform.dart';
|
import 'package:stream_transform/stream_transform.dart';
|
||||||
|
|
||||||
class DriftTimelineRepository extends DriftDatabaseRepository
|
class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
implements ITimelineRepository {
|
|
||||||
final Drift _db;
|
final Drift _db;
|
||||||
|
|
||||||
const DriftTimelineRepository(super._db) : _db = _db;
|
const DriftTimelineRepository(super._db) : _db = _db;
|
||||||
@@ -28,7 +26,6 @@ class DriftTimelineRepository extends DriftDatabaseRepository
|
|||||||
return buckets;
|
return buckets;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Stream<List<Bucket>> watchMainBucket(
|
Stream<List<Bucket>> watchMainBucket(
|
||||||
List<String> userIds, {
|
List<String> userIds, {
|
||||||
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
||||||
@@ -49,7 +46,6 @@ class DriftTimelineRepository extends DriftDatabaseRepository
|
|||||||
.throttle(const Duration(seconds: 3), trailing: true);
|
.throttle(const Duration(seconds: 3), trailing: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<BaseAsset>> getMainBucketAssets(
|
Future<List<BaseAsset>> getMainBucketAssets(
|
||||||
List<String> userIds, {
|
List<String> userIds, {
|
||||||
required int offset,
|
required int offset,
|
||||||
@@ -90,7 +86,6 @@ class DriftTimelineRepository extends DriftDatabaseRepository
|
|||||||
.get();
|
.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Stream<List<Bucket>> watchLocalBucket(
|
Stream<List<Bucket>> watchLocalBucket(
|
||||||
String albumId, {
|
String albumId, {
|
||||||
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
||||||
@@ -124,7 +119,6 @@ class DriftTimelineRepository extends DriftDatabaseRepository
|
|||||||
}).watch();
|
}).watch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<BaseAsset>> getLocalBucketAssets(
|
Future<List<BaseAsset>> getLocalBucketAssets(
|
||||||
String albumId, {
|
String albumId, {
|
||||||
required int offset,
|
required int offset,
|
||||||
|
|||||||
@@ -1,30 +1,26 @@
|
|||||||
import 'package:immich_mobile/domain/interfaces/user.interface.dart';
|
import 'package:immich_mobile/constants/enums.dart';
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/user.entity.dart'
|
import 'package:immich_mobile/infrastructure/entities/user.entity.dart'
|
||||||
as entity;
|
as entity;
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
class IsarUserRepository extends IsarDatabaseRepository
|
class IsarUserRepository extends IsarDatabaseRepository {
|
||||||
implements IUserRepository {
|
|
||||||
final Isar _db;
|
final Isar _db;
|
||||||
const IsarUserRepository(super.db) : _db = db;
|
const IsarUserRepository(super.db) : _db = db;
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> delete(List<String> ids) async {
|
Future<void> delete(List<String> ids) async {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
await _db.users.deleteAllById(ids);
|
await _db.users.deleteAllById(ids);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> deleteAll() async {
|
Future<void> deleteAll() async {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
await _db.users.clear();
|
await _db.users.clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<UserDto>> getAll({SortUserBy? sortBy}) async {
|
Future<List<UserDto>> getAll({SortUserBy? sortBy}) async {
|
||||||
return (await _db.users
|
return (await _db.users
|
||||||
.where()
|
.where()
|
||||||
@@ -39,17 +35,14 @@ class IsarUserRepository extends IsarDatabaseRepository
|
|||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<UserDto?> getByUserId(String id) async {
|
Future<UserDto?> getByUserId(String id) async {
|
||||||
return (await _db.users.getById(id))?.toDto();
|
return (await _db.users.getById(id))?.toDto();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<UserDto?>> getByUserIds(List<String> ids) async {
|
Future<List<UserDto?>> getByUserIds(List<String> ids) async {
|
||||||
return (await _db.users.getAllById(ids)).map((u) => u?.toDto()).toList();
|
return (await _db.users.getAllById(ids)).map((u) => u?.toDto()).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> insert(UserDto user) async {
|
Future<bool> insert(UserDto user) async {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
await _db.users.put(entity.User.fromDto(user));
|
await _db.users.put(entity.User.fromDto(user));
|
||||||
@@ -57,7 +50,6 @@ class IsarUserRepository extends IsarDatabaseRepository
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<UserDto> update(UserDto user) async {
|
Future<UserDto> update(UserDto user) async {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
await _db.users.put(entity.User.fromDto(user));
|
await _db.users.put(entity.User.fromDto(user));
|
||||||
@@ -65,7 +57,6 @@ class IsarUserRepository extends IsarDatabaseRepository
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> updateAll(List<UserDto> users) async {
|
Future<bool> updateAll(List<UserDto> users) async {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
await _db.users.putAll(users.map(entity.User.fromDto).toList());
|
await _db.users.putAll(users.map(entity.User.fromDto).toList());
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/user_api.interface.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/api.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/api.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/utils/user.converter.dart';
|
import 'package:immich_mobile/infrastructure/utils/user.converter.dart';
|
||||||
import 'package:openapi/api.dart';
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
class UserApiRepository extends ApiRepository implements IUserApiRepository {
|
class UserApiRepository extends ApiRepository {
|
||||||
final UsersApi _api;
|
final UsersApi _api;
|
||||||
const UserApiRepository(this._api);
|
const UserApiRepository(this._api);
|
||||||
|
|
||||||
@override
|
|
||||||
Future<UserDto?> getMyUser() async {
|
Future<UserDto?> getMyUser() async {
|
||||||
final (adminDto, preferenceDto) =
|
final (adminDto, preferenceDto) =
|
||||||
await (_api.getMyUser(), _api.getMyPreferences()).wait;
|
await (_api.getMyUser(), _api.getMyPreferences()).wait;
|
||||||
@@ -20,7 +18,6 @@ class UserApiRepository extends ApiRepository implements IUserApiRepository {
|
|||||||
return UserConverter.fromAdminDto(adminDto, preferenceDto);
|
return UserConverter.fromAdminDto(adminDto, preferenceDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String> createProfileImage({
|
Future<String> createProfileImage({
|
||||||
required String name,
|
required String name,
|
||||||
required Uint8List data,
|
required Uint8List data,
|
||||||
@@ -33,7 +30,6 @@ class UserApiRepository extends ApiRepository implements IUserApiRepository {
|
|||||||
return res.profileImagePath;
|
return res.profileImagePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<UserDto>> getAll() async {
|
Future<List<UserDto>> getAll() async {
|
||||||
final dto = await checkNull(_api.searchUsers());
|
final dto = await checkNull(_api.searchUsers());
|
||||||
return dto.map(UserConverter.fromSimpleUserDto).toList();
|
return dto.map(UserConverter.fromSimpleUserDto).toList();
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
import 'package:immich_mobile/models/activities/activity.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IActivityApiRepository {
|
|
||||||
Future<List<Activity>> getAll(
|
|
||||||
String albumId, {
|
|
||||||
String? assetId,
|
|
||||||
});
|
|
||||||
Future<Activity> create(
|
|
||||||
String albumId,
|
|
||||||
ActivityType type, {
|
|
||||||
String? assetId,
|
|
||||||
String? comment,
|
|
||||||
});
|
|
||||||
Future<void> delete(String id);
|
|
||||||
Future<ActivityStats> getStats(String albumId, {String? assetId});
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
|
||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
|
||||||
import 'package:immich_mobile/interfaces/database.interface.dart';
|
|
||||||
import 'package:immich_mobile/models/albums/album_search.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IAlbumRepository implements IDatabaseRepository {
|
|
||||||
Future<Album> create(Album album);
|
|
||||||
|
|
||||||
Future<Album?> get(int id);
|
|
||||||
|
|
||||||
Future<Album?> getByName(
|
|
||||||
String name, {
|
|
||||||
bool? shared,
|
|
||||||
bool? remote,
|
|
||||||
bool? owner,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<List<Album>> getAll({
|
|
||||||
bool? shared,
|
|
||||||
bool? remote,
|
|
||||||
int? ownerId,
|
|
||||||
AlbumSort? sortBy,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<Album> update(Album album);
|
|
||||||
|
|
||||||
Future<void> delete(int albumId);
|
|
||||||
|
|
||||||
Future<void> deleteAllLocal();
|
|
||||||
|
|
||||||
Future<int> count({bool? local});
|
|
||||||
|
|
||||||
Future<void> addUsers(Album album, List<UserDto> users);
|
|
||||||
|
|
||||||
Future<void> removeUsers(Album album, List<UserDto> users);
|
|
||||||
|
|
||||||
Future<void> addAssets(Album album, List<Asset> assets);
|
|
||||||
|
|
||||||
Future<void> removeAssets(Album album, List<Asset> assets);
|
|
||||||
|
|
||||||
Future<Album> recalculateMetadata(Album album);
|
|
||||||
|
|
||||||
Future<List<Album>> search(String searchTerm, QuickFilterMode filterMode);
|
|
||||||
|
|
||||||
Stream<List<Album>> watchRemoteAlbums();
|
|
||||||
|
|
||||||
Stream<List<Album>> watchLocalAlbums();
|
|
||||||
|
|
||||||
Stream<Album?> watchAlbum(int id);
|
|
||||||
|
|
||||||
Future<void> clearTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AlbumSort { remoteId, localId }
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
|
||||||
|
|
||||||
abstract interface class IAlbumApiRepository {
|
|
||||||
Future<Album> get(String id);
|
|
||||||
|
|
||||||
Future<List<Album>> getAll({bool? shared});
|
|
||||||
|
|
||||||
Future<Album> create(
|
|
||||||
String name, {
|
|
||||||
required Iterable<String> assetIds,
|
|
||||||
Iterable<String> sharedUserIds = const [],
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<Album> update(
|
|
||||||
String albumId, {
|
|
||||||
String? name,
|
|
||||||
String? thumbnailAssetId,
|
|
||||||
String? description,
|
|
||||||
bool? activityEnabled,
|
|
||||||
SortOrder? sortOrder,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<void> delete(String albumId);
|
|
||||||
|
|
||||||
Future<({List<String> added, List<String> duplicates})> addAssets(
|
|
||||||
String albumId,
|
|
||||||
Iterable<String> assetIds,
|
|
||||||
);
|
|
||||||
|
|
||||||
Future<({List<String> removed, List<String> failed})> removeAssets(
|
|
||||||
String albumId,
|
|
||||||
Iterable<String> assetIds,
|
|
||||||
);
|
|
||||||
|
|
||||||
Future<Album> addUsers(
|
|
||||||
String albumId,
|
|
||||||
Iterable<String> userIds,
|
|
||||||
);
|
|
||||||
|
|
||||||
Future<void> removeUser(String albumId, {required String userId});
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
|
||||||
|
|
||||||
abstract interface class IAlbumMediaRepository {
|
|
||||||
Future<List<Album>> getAll();
|
|
||||||
|
|
||||||
Future<List<String>> getAssetIds(String albumId);
|
|
||||||
|
|
||||||
Future<int> getAssetCount(String albumId);
|
|
||||||
|
|
||||||
Future<List<Asset>> getAssets(
|
|
||||||
String albumId, {
|
|
||||||
int start = 0,
|
|
||||||
int end = 0x7fffffffffffffff,
|
|
||||||
DateTime? modifiedFrom,
|
|
||||||
DateTime? modifiedUntil,
|
|
||||||
bool orderByModificationDate = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<Album> get(String id);
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
|
||||||
import 'package:immich_mobile/interfaces/database.interface.dart';
|
|
||||||
|
|
||||||
abstract interface class IAssetRepository implements IDatabaseRepository {
|
|
||||||
Future<Asset?> getByRemoteId(String id);
|
|
||||||
|
|
||||||
Future<Asset?> getByOwnerIdChecksum(int ownerId, String checksum);
|
|
||||||
|
|
||||||
Future<List<Asset>> getAllByRemoteId(
|
|
||||||
Iterable<String> ids, {
|
|
||||||
AssetState? state,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<List<Asset?>> getAllByOwnerIdChecksum(
|
|
||||||
List<int> ids,
|
|
||||||
List<String> checksums,
|
|
||||||
);
|
|
||||||
|
|
||||||
Future<List<Asset>> getAll({
|
|
||||||
required String ownerId,
|
|
||||||
AssetState? state,
|
|
||||||
AssetSort? sortBy,
|
|
||||||
int? limit,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<List<Asset>> getAllLocal();
|
|
||||||
|
|
||||||
Future<List<Asset>> getByAlbum(
|
|
||||||
Album album, {
|
|
||||||
Iterable<String> notOwnedBy = const [],
|
|
||||||
String? ownerId,
|
|
||||||
AssetState? state,
|
|
||||||
AssetSort? sortBy,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<Asset> update(Asset asset);
|
|
||||||
|
|
||||||
Future<List<Asset>> updateAll(List<Asset> assets);
|
|
||||||
|
|
||||||
Future<void> deleteAllByRemoteId(List<String> ids, {AssetState? state});
|
|
||||||
|
|
||||||
Future<void> deleteByIds(List<int> ids);
|
|
||||||
|
|
||||||
Future<List<Asset>> getMatches({
|
|
||||||
required List<Asset> assets,
|
|
||||||
required String ownerId,
|
|
||||||
AssetState? state,
|
|
||||||
int limit = 100,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<void> upsertDuplicatedAssets(Iterable<String> duplicatedAssets);
|
|
||||||
|
|
||||||
Future<List<String>> getAllDuplicatedAssetIds();
|
|
||||||
|
|
||||||
Future<List<Asset>> getStackAssets(String stackId);
|
|
||||||
|
|
||||||
Future<void> clearTable();
|
|
||||||
|
|
||||||
Stream<Asset?> watchAsset(int id, {bool fireImmediately = false});
|
|
||||||
|
|
||||||
Future<List<Asset>> getTrashAssets(String userId);
|
|
||||||
|
|
||||||
Future<List<Asset>> getRecentlyTakenAssets(String userId);
|
|
||||||
Future<List<Asset>> getMotionAssets(String userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AssetSort { checksum, ownerIdChecksum }
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
|
||||||
|
|
||||||
abstract interface class IAssetApiRepository {
|
|
||||||
// Future<Asset> get(String id);
|
|
||||||
|
|
||||||
// Future<List<Asset>> getAll();
|
|
||||||
|
|
||||||
// Future<Asset> create(Asset asset);
|
|
||||||
|
|
||||||
Future<Asset> update(
|
|
||||||
String id, {
|
|
||||||
String? description,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Future<void> delete(String id);
|
|
||||||
|
|
||||||
Future<List<Asset>> search({List<String> personIds = const []});
|
|
||||||
|
|
||||||
Future<void> updateVisibility(
|
|
||||||
List<String> list,
|
|
||||||
AssetVisibilityEnum visibility,
|
|
||||||
);
|
|
||||||
|
|
||||||
Future<String?> getAssetMIMEType(String id);
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
|
||||||
|
|
||||||
abstract interface class IAssetMediaRepository {
|
|
||||||
Future<List<String>> deleteAll(List<String> ids);
|
|
||||||
|
|
||||||
Future<Asset?> get(String id);
|
|
||||||
|
|
||||||
/// Obtaining the correct original filename of the asset
|
|
||||||
Future<String?> getOriginalFilename(String id);
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import 'package:immich_mobile/interfaces/database.interface.dart';
|
|
||||||
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IAuthRepository implements IDatabaseRepository {
|
|
||||||
Future<void> clearLocalData();
|
|
||||||
String getAccessToken();
|
|
||||||
bool getEndpointSwitchingFeature();
|
|
||||||
String? getPreferredWifiName();
|
|
||||||
String? getLocalEndpoint();
|
|
||||||
List<AuxilaryEndpoint> getExternalEndpointList();
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import 'package:immich_mobile/models/auth/login_response.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IAuthApiRepository {
|
|
||||||
Future<LoginResponse> login(String email, String password);
|
|
||||||
|
|
||||||
Future<void> logout();
|
|
||||||
|
|
||||||
Future<void> changePassword(String newPassword);
|
|
||||||
|
|
||||||
Future<bool> unlockPinCode(String pinCode);
|
|
||||||
Future<void> lockPinCode();
|
|
||||||
|
|
||||||
Future<void> setupPinCode(String pinCode);
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import 'package:immich_mobile/entities/backup_album.entity.dart';
|
|
||||||
import 'package:immich_mobile/interfaces/database.interface.dart';
|
|
||||||
|
|
||||||
abstract interface class IBackupAlbumRepository implements IDatabaseRepository {
|
|
||||||
Future<List<BackupAlbum>> getAll({BackupAlbumSort? sort});
|
|
||||||
|
|
||||||
Future<List<String>> getIdsBySelection(BackupSelection backup);
|
|
||||||
|
|
||||||
Future<List<BackupAlbum>> getAllBySelection(BackupSelection backup);
|
|
||||||
|
|
||||||
Future<void> updateAll(List<BackupAlbum> backupAlbums);
|
|
||||||
|
|
||||||
Future<void> deleteAll(List<int> ids);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum BackupAlbumSort { id }
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import 'package:immich_mobile/models/auth/biometric_status.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IBiometricRepository {
|
|
||||||
Future<BiometricStatus> getStatus();
|
|
||||||
Future<bool> authenticate(String? message);
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
|
||||||
import 'package:immich_mobile/models/cast/cast_manager_state.dart';
|
|
||||||
|
|
||||||
abstract interface class ICastDestinationService {
|
|
||||||
Future<bool> initialize();
|
|
||||||
CastDestinationType getType();
|
|
||||||
|
|
||||||
void Function(bool)? onConnectionState;
|
|
||||||
|
|
||||||
void Function(Duration)? onCurrentTime;
|
|
||||||
void Function(Duration)? onDuration;
|
|
||||||
|
|
||||||
void Function(String)? onReceiverName;
|
|
||||||
void Function(CastState)? onCastState;
|
|
||||||
|
|
||||||
Future<void> connect(dynamic device);
|
|
||||||
|
|
||||||
void loadMedia(Asset asset, bool reload);
|
|
||||||
|
|
||||||
void play();
|
|
||||||
void pause();
|
|
||||||
void seekTo(Duration position);
|
|
||||||
void stop();
|
|
||||||
Future<void> disconnect();
|
|
||||||
|
|
||||||
Future<List<(String, CastDestinationType, dynamic)>> getDevices();
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import 'package:background_downloader/background_downloader.dart';
|
|
||||||
|
|
||||||
abstract interface class IDownloadRepository {
|
|
||||||
void Function(TaskStatusUpdate)? onImageDownloadStatus;
|
|
||||||
void Function(TaskStatusUpdate)? onVideoDownloadStatus;
|
|
||||||
void Function(TaskStatusUpdate)? onLivePhotoDownloadStatus;
|
|
||||||
void Function(TaskProgressUpdate)? onTaskProgress;
|
|
||||||
|
|
||||||
Future<List<TaskRecord>> getLiveVideoTasks();
|
|
||||||
Future<List<bool>> downloadAll(List<DownloadTask> tasks);
|
|
||||||
|
|
||||||
Future<bool> cancel(String id);
|
|
||||||
Future<void> deleteAllTrackingRecords();
|
|
||||||
Future<void> deleteRecordsWithIds(List<String> id);
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import 'package:immich_mobile/entities/etag.entity.dart';
|
|
||||||
import 'package:immich_mobile/interfaces/database.interface.dart';
|
|
||||||
|
|
||||||
abstract interface class IETagRepository implements IDatabaseRepository {
|
|
||||||
Future<ETag?> get(String id);
|
|
||||||
|
|
||||||
Future<ETag?> getById(String id);
|
|
||||||
|
|
||||||
Future<List<String>> getAllIds();
|
|
||||||
|
|
||||||
Future<void> upsertAll(List<ETag> etags);
|
|
||||||
|
|
||||||
Future<void> deleteByIds(List<String> ids);
|
|
||||||
|
|
||||||
Future<void> clearTable();
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import 'dart:io';
|
|
||||||
import 'dart:typed_data';
|
|
||||||
|
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
|
||||||
|
|
||||||
abstract interface class IFileMediaRepository {
|
|
||||||
Future<Asset?> saveImage(
|
|
||||||
Uint8List data, {
|
|
||||||
required String title,
|
|
||||||
String? relativePath,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<Asset?> saveImageWithFile(
|
|
||||||
String filePath, {
|
|
||||||
String? title,
|
|
||||||
String? relativePath,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<Asset?> saveVideo(
|
|
||||||
File file, {
|
|
||||||
required String title,
|
|
||||||
String? relativePath,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<Asset?> saveLivePhoto({
|
|
||||||
required File image,
|
|
||||||
required File video,
|
|
||||||
required String title,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<void> clearFileCache();
|
|
||||||
|
|
||||||
Future<void> enableBackgroundAccess();
|
|
||||||
|
|
||||||
Future<void> requestExtendedPermissions();
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
|
||||||
|
|
||||||
abstract interface class IFolderApiRepository {
|
|
||||||
Future<List<String>> getAllUniquePaths();
|
|
||||||
Future<List<Asset>> getAssetsForPath(String? path);
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
abstract interface class ILocalFilesManager {
|
|
||||||
Future<bool> moveToTrash(List<String> mediaUrls);
|
|
||||||
Future<bool> restoreFromTrash(String fileName, int type);
|
|
||||||
Future<bool> requestManageMediaPermission();
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
abstract interface class INetworkRepository {
|
|
||||||
Future<String?> getWifiName();
|
|
||||||
Future<String?> getWifiIp();
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
|
||||||
|
|
||||||
abstract class IPartnerRepository {
|
|
||||||
Future<List<UserDto>> getSharedWith();
|
|
||||||
Future<List<UserDto>> getSharedBy();
|
|
||||||
Stream<List<UserDto>> watchSharedWith();
|
|
||||||
Stream<List<UserDto>> watchSharedBy();
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IPartnerApiRepository {
|
|
||||||
Future<List<UserDto>> getAll(Direction direction);
|
|
||||||
Future<UserDto> create(String id);
|
|
||||||
Future<UserDto> update(String id, {required bool inTimeline});
|
|
||||||
Future<void> delete(String id);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Direction {
|
|
||||||
sharedWithMe,
|
|
||||||
sharedByMe,
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
abstract interface class ISecureStorageRepository {
|
|
||||||
Future<String?> read(String key);
|
|
||||||
Future<void> write(String key, String value);
|
|
||||||
Future<void> delete(String key);
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import 'package:immich_mobile/models/sessions/session_create_response.model.dart';
|
|
||||||
|
|
||||||
abstract interface class ISessionAPIRepository {
|
|
||||||
Future<SessionCreateResponse> createSession(
|
|
||||||
String deviceName,
|
|
||||||
String deviceOS, {
|
|
||||||
int? duration,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import 'package:immich_mobile/models/upload/share_intent_attachment.model.dart';
|
|
||||||
|
|
||||||
abstract interface class IShareHandlerRepository {
|
|
||||||
void Function(List<ShareIntentAttachment>)? onSharedMedia;
|
|
||||||
|
|
||||||
Future<void> init();
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
|
||||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
|
||||||
|
|
||||||
abstract class ITimelineRepository {
|
|
||||||
Future<List<String>> getTimelineUserIds(String id);
|
|
||||||
|
|
||||||
Stream<List<String>> watchTimelineUsers(String id);
|
|
||||||
|
|
||||||
Stream<RenderList> watchArchiveTimeline(String userId);
|
|
||||||
Stream<RenderList> watchFavoriteTimeline(String userId);
|
|
||||||
Stream<RenderList> watchTrashTimeline(String userId);
|
|
||||||
Stream<RenderList> watchAlbumTimeline(
|
|
||||||
Album album,
|
|
||||||
GroupAssetsBy groupAssetsBy,
|
|
||||||
);
|
|
||||||
Stream<RenderList> watchAllVideosTimeline(String userId);
|
|
||||||
|
|
||||||
Stream<RenderList> watchHomeTimeline(
|
|
||||||
String userId,
|
|
||||||
GroupAssetsBy groupAssetsBy,
|
|
||||||
);
|
|
||||||
Stream<RenderList> watchMultiUsersTimeline(
|
|
||||||
List<String> userIds,
|
|
||||||
GroupAssetsBy groupAssetsBy,
|
|
||||||
);
|
|
||||||
|
|
||||||
Future<RenderList> getTimelineFromAssets(
|
|
||||||
List<Asset> assets,
|
|
||||||
GroupAssetsBy getGroupByOption,
|
|
||||||
);
|
|
||||||
|
|
||||||
Stream<RenderList> watchAssetSelectionTimeline(String userId);
|
|
||||||
|
|
||||||
Stream<RenderList> watchLockedTimeline(
|
|
||||||
String userId,
|
|
||||||
GroupAssetsBy groupAssetsBy,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user