Compare commits

...

66 Commits

Author SHA1 Message Date
Alex The Bot
1f4993350a Version v1.60.0 2023-06-04 15:45:06 +00:00
Michel Heusschen
f9b1d1edaf fix(server): better metadata extraction for images (#2653) 2023-06-03 21:55:30 -05:00
Michel Heusschen
cab5477656 fix(web+server): showing assets without thumbnail (#2652)
* fix(web+server): showing assets without thumbnail

* missed change
2023-06-03 21:41:27 -05:00
Mert
b8de668f5f feat(ml): env variables for tags, faces and eager startup (#2626)
* env variables for tags, faces and eager startup

* chore(server,ml): remove object detection job and endpoint (#2627)

* removed object detection job

* removed object detection endpoint

* env variables for tags, faces and eager startup

* download without caching models if not eager

* simplified `get_cached_model`

* re-added env for clip text model
2023-06-02 21:42:47 -05:00
Jason Rasmussen
c5234731d6 fix(server): add executable permission to start scripts (#2650) 2023-06-02 14:04:26 -05:00
Michel Heusschen
ef86a77946 refactor(server): remove invalid exif coordinates (#2651) 2023-06-02 14:04:07 -05:00
Michel Heusschen
1b301984dd fix(server): handle invalid coordinates (#2648) 2023-06-02 11:29:12 -05:00
Michel Heusschen
9807f76aff chore(web): improve type checking (#2644)
* fix(web): use id instead of assetId

* chore(web): improve type checking

* fix test jobs

* improve type checking and resolve errors
2023-06-02 08:55:08 -05:00
Michel Heusschen
47673dd773 fix(web): use id instead of assetId (#2643) 2023-06-02 08:50:35 -05:00
Jason Rasmussen
a9fb1d435a refactor(server): use UUID dto in asset controller (#2641)
* refactor: assetId => id

* chore: open api

* chore: remove unused dto

* fix(web): assetId => id

* fix: web test
2023-06-01 21:19:25 -05:00
Jason Rasmussen
422ad20641 refactor(server): use swagger (#2639) 2023-06-02 02:12:22 +00:00
Jason Rasmussen
3ea2fe1c48 refactor(server): shared links (#2632)
* refactor: rename share => shared-link

* refactor: shared link crud methods

* chore: open api
2023-06-01 21:09:57 -05:00
Jason Rasmussen
038e064e60 refactor(server): handle download (#2637) 2023-06-01 21:03:15 -05:00
Jason Rasmussen
800f010383 refactor(server): app init (#2638) 2023-06-01 20:54:16 -05:00
Jason Rasmussen
4350f9363d feat(server): use base64 shared links (#2633)
* feat(server): use base64 shared links

* fix: handle array values
2023-06-01 15:56:37 -05:00
Jason Rasmussen
76a1629e75 test(server): job service (#2634) 2023-06-01 16:07:45 -04:00
Jason Rasmussen
2493dfaba3 feat(server): dynamic job concurrency (#2622)
* feat(server): dynamic job concurrency

* styling and add setting info to top of the job list

* regenerate api

* remove DETECT_OBJECT job

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2023-06-01 05:32:51 -05:00
Jason Rasmussen
656dc08406 refactor(server): tags (#2589)
* refactor: tags

* chore: open api

* chore: unused import

* feat: add/remove/get tag assets

* chore: open api

* chore: finish tag tests for add/remove assets
2023-05-31 20:51:28 -05:00
Mert
631f13cf2f chore(server,ml): remove object detection job and endpoint (#2627)
* removed object detection job

* removed object detection endpoint
2023-05-31 20:49:51 -05:00
Jason Rasmussen
9730bf0acc fix(server): without queries (#2621) 2023-05-31 10:00:37 -05:00
Stormrover
9f2b5ea86e Allow docker image version pinning (#2617)
* Allow docker image version pinning

* Updating docker-compose documentation.

* Fixing formatting

* Added Optional to documentation.
2023-05-30 20:53:24 -05:00
Sergey Kondrikov
5702442783 fix: remove mbtree files (#2620) 2023-05-30 20:52:57 -05:00
Jason Rasmussen
74c2f446e9 fix: missing faces job (#2618) 2023-05-30 13:51:53 -05:00
Alex The Bot
da1710bcd2 Version v1.59.1 2023-05-30 17:56:47 +00:00
Jason Rasmussen
2dfd56b49b fix: reload assets from typesense results (#2615)
* fix: reload assets from typesense results

* chore: coverage
2023-05-30 12:55:06 -05:00
Alex The Bot
6538e599dd Version v1.59.0 2023-05-30 15:27:35 +00:00
Michel Heusschen
789e3e3924 refactor(server): use date type for entities (#2602) 2023-05-30 08:15:56 -05:00
Michel Heusschen
3d505e425d fix(web): show icons for empty album (#2604) 2023-05-29 13:58:09 -05:00
Manuel Taberna
e7122d7a72 feat(web): add zoom to photo viewer (#2577)
* feat(web): add zoom to photo viewer

* reduce asset viewer next/prev button div width

* add wrap to block statement
2023-05-29 09:12:58 -05:00
Michel Heusschen
94d0705607 refactor(server): change asset entity to date type (#2599)
* refactor(server): change asset entity to date type

* lower coverage threshold
2023-05-29 09:05:14 -05:00
Jason Rasmussen
caba462703 fix(server): library folder missing on new install (#2597) 2023-05-28 20:48:07 -05:00
Jason Rasmussen
ffe397247e refactor(server): auth decorator (#2588) 2023-05-28 11:30:01 -05:00
Michel Heusschen
e7ad622c02 refactor(web): user avatar (#2585)
* refactor(web): user avatar

* change user settings link

* update package lock json

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2023-05-28 08:10:55 -05:00
Jason Rasmussen
bca4626708 feat(server): return asset checksum (#2582)
* feat: return asset checksum

* chore: generate open api

* chore: coverage

* feat(server): support base64 hashes in bulk upload check:

* chore: generate open api
2023-05-27 20:56:17 -05:00
Michel Heusschen
7f0ad8e2d2 fix(web+mobile): consistent filename handling (#2534) 2023-05-27 20:53:29 -05:00
Sergey Kondrikov
6c6c5ef651 chore(web): generate API functions with a single argument (#2568) 2023-05-27 20:52:22 -05:00
Alex The Bot
a460940430 Version v1.58.0 2023-05-27 21:56:06 +00:00
Alex
fc2455be80 fix(server): missing metadata extraction job (#2586)
* fix(server): missing metadata extraction job

* format

* fix test

* fix test

* Added source to upload

* fix test

* OK! CODE COVERAGE
2023-05-27 16:49:57 -05:00
Michel Heusschen
fd4357cf23 fix(server): exif time extraction (#2583) 2023-05-27 16:24:07 -05:00
Jason Rasmussen
e41e0df27e fix(server): invalid exif date string (#2580) 2023-05-26 21:13:09 -05:00
Michel Heusschen
f370dc3929 fix(web): small style issues (#2578) 2023-05-26 14:44:06 -05:00
Jason Rasmussen
1c2d83e2c7 refactor(server): job handlers (#2572)
* refactor(server): job handlers

* chore: remove comment

* chore: add comments for
2023-05-26 14:43:24 -05:00
Jason Rasmussen
d6756f3d81 feat(web): improved action bar actions (#2553)
* feat(web): improved action bar actions

* Update web/src/lib/components/photos-page/actions/delete-assets.svelte

Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>

* update archive and favorite actions

* feat: add un archive/favorite on associated pages

* fix favorite action + use isAllArchived for photos

* remove unneeded unarchive check

---------

Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
2023-05-26 08:11:10 -05:00
Fynn Petersen-Frey
71ef7685c5 chore(mobile): update isar (#2571) 2023-05-26 08:09:44 -05:00
Jason Rasmussen
b7516f31c6 refactor(server): delete album (#2570) 2023-05-26 08:04:09 -05:00
Jason Rasmussen
065fb166c2 refactor(server): bull jobs (#2569)
* refactor(server): bull jobs

* chore: add comment

* chore: metadata test coverage

* fix typo

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2023-05-26 07:52:52 -05:00
Jason Rasmussen
4cc6e3b966 refactor(server): update album (#2562)
* refactor: update album

* fix: remove unnecessary decorator
2023-05-25 14:37:19 -05:00
Michel Heusschen
1c293a2759 fix(web): back button on person page (#2566) 2023-05-25 11:48:36 -05:00
Michel Heusschen
062e2eca6f feat(web+server): map date filters + small changes (#2565) 2023-05-25 11:47:52 -05:00
Fynn Petersen-Frey
bcc2c34eef feat(mobile): partner sharing (#2541)
* feat(mobile): partner sharing

* getAllAssets for other users

* i18n

* fix tests

* try to fix web tests

* shared with/by confusion

* error logging

* guard against outdated server version
2023-05-24 22:52:43 -05:00
Jason Rasmussen
1613ae9185 feat(web): show assets without thumbs (#2561)
* feat(web): show assets without thumbnails

* chore: open api
2023-05-24 21:13:02 -05:00
Jason Rasmussen
d827a6182b refactor: create album (#2555) 2023-05-24 21:10:45 -05:00
Jason Rasmussen
83df14d379 feat: disk stats for library folder (#2560) 2023-05-24 21:05:31 -05:00
Alex Phillips
7c1dae918d feat(server): xmp sidecar metadata (#2466)
* initial commit for XMP sidecar support

* Added support for 'missing' metadata files to include those without sidecar files, now detects sidecar files in the filesystem for media already ingested but the sidecar was created afterwards

* didn't mean to commit default log level during testing

* new sidecar logic for video metadata as well

* Added xml mimetype for sidecars only

* don't need capture group for this regex

* wrong default value reverted

* simplified the move here - keep it in the same try catch since the outcome is to move the media back anyway

* simplified setter logic

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>

* simplified logic per suggestions

* sidecar is now its own queue with a discover and sync, updated UI for the new job queueing

* queue a sidecar job for every asset based on discovery or sync, though the logic is almost identical aside from linking the sidecar

* now queue sidecar jobs for each assset, though logic is mostly the same between discovery and sync

* simplified logic of filename extraction and asset instantiation

* not sure how that got deleted..

* updated code per suggestions and comments in the PR

* stat was not being used, removed the variable set

* better type checking, using in-scope variables for exif getter instead of passing in every time

* removed commented out test

* ran and resolved all lints, formats, checks, and tests

* resolved suggested change in PR

* made getExifProperty more dynamic with multiple possible args for fallbacks, fixed typo, used generic in function  for better type checking

* better error handling and moving files back to positions on move or save failure

* regenerated api

* format fixes

* Added XMP documentation

* documentation typo

* Merged in main

* missed merge conflict

* more changes due to a merge

* Resolving conflicts

* added icon for sidecar jobs

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2023-05-24 20:59:30 -05:00
Jonathan Jogenfors
1b54c4f8e7 feat(server): Add support for client-side hashing (#2072)
* Modify controller DTOs

* Can check duplicates on server side

* Remove deviceassetid and deviceid

* Remove device ids from file uploader

* Add db migration for removed device ids

* Don't sanitize checksum

* Convert asset checksum to string

* Make checksum not optional for asset

* Use enums when rejecting duplicates

* Cleanup

* Return of the device id, but optional

* Don't use deviceId for upload folder

* Use checksum in thumb path

* Only use asset id in thumb path

* Openapi generation

* Put deviceAssetId back in asset response dto

* Add missing checksum in test fixture

* Add another missing checksum in test fixture

* Cleanup asset repository

* Add back previous /exists endpoint

* Require checksum to not be null

* Correctly set deviceId in db

* Remove index

* Fix compilation errors

* Make device id nullabel in asset response dto

* Reduce PR scope

* Revert asset service

* Reorder imports

* Reorder imports

* Reduce PR scope

* Reduce PR scope

* Reduce PR scope

* Reduce PR scope

* Reduce PR scope

* Update openapi

* Reduce PR scope

* refactor: asset bulk upload check

* chore: regenreate open-api

* chore: fix tests

* chore: tests

* update migrations and regenerate api

* Feat: use checksum in web file uploader

* Change to wasm-crypto

* Use crypto api for checksumming in web uploader

* Minor cleanup of file upload

* feat(web): pause and resume jobs

* Make device asset id not nullable again

* Cleanup

* Device id not nullable in response dto

* Update API specs

* Bump api specs

* Remove old TODO comment

* Remove NOT NULL constraint on checksum index

* Fix requested pubspec changes

* Remove unneeded import

* Update server/apps/immich/src/api-v1/asset/asset.service.ts

Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>

* Update server/apps/immich/src/api-v1/asset/asset-repository.ts

Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>

* Remove unneeded check

* Update server/apps/immich/src/api-v1/asset/asset-repository.ts

Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>

* Remove hashing in the web uploader

* Cleanup file uploader

* Remove varchar from asset entity fields

* Return 200 from bulk upload check

* Put device asset id back into asset repository

* Merge migrations

* Revert pubspec lock

* Update openapi specs

* Merge upstream changes

* Fix failing asset service tests

* Fix formatting issue

* Cleanup migrations

* Remove newline from pubspec

* Revert newline

* Checkout main version

* Revert again

* Only return AssetCheck

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
2023-05-24 16:08:21 -05:00
Jason Rasmussen
49b74e9091 refactor(server): album controller (#2539)
* refactor: album controller/service

* chore: open-api

* fix: tests
2023-05-24 09:30:13 -05:00
Jason Rasmussen
a1f1e5bc37 fix(server): reverse geocoding delete dump logic (#2551) 2023-05-23 20:36:36 -05:00
Jason Rasmussen
2dc8a93685 feat(web): use user layout on admin pages (#2550) 2023-05-23 19:02:12 -05:00
Jason Rasmussen
c2145cbe11 fix: hide album context menu (#2543) 2023-05-23 15:40:32 -05:00
Jason Rasmussen
50a792a81a refactor(server): use cascades for keys and tokens (#2544) 2023-05-23 15:40:04 -05:00
Jason Rasmussen
e2bd7e1e08 feat(web): job tile icons (#2546) 2023-05-23 15:04:24 -05:00
Thomas
11a5a990d0 docker: use default entrypoint and command where applicable (#2529)
A default entrypoint and command make it just a bit easier to use the images as
there is no longer a need for an explicit entrypoint. The exception is the
server image, which still requires the shell script to be specified.
2023-05-23 09:02:47 -05:00
Alex The Bot
ecc894ac82 Version v1.57.1 2023-05-23 09:21:22 +00:00
Michel Heusschen
50b649cd3e fix(web): small fixes for album selection modal (#2527) 2023-05-23 04:15:48 -05:00
Michel Heusschen
99b018cd49 fix(web): loading leaflet in production builds (#2526) 2023-05-23 04:14:00 -05:00
Alex
6aa2800275 chore: post release tasks 2023-05-22 22:43:06 -05:00
475 changed files with 14148 additions and 6488 deletions

View File

@@ -96,7 +96,11 @@ jobs:
if: ${{ !cancelled() }}
- name: Run svelte checks
run: npm run check
run: npm run check:svelte
if: ${{ !cancelled() }}
- name: Run tsc
run: npm run check:typescript
if: ${{ !cancelled() }}
- name: Run unit tests & coverage

View File

@@ -3,8 +3,8 @@ version: "3.8"
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:release
entrypoint: ["/bin/sh", "./start-server.sh"]
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
command: ["start-server.sh"]
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
env_file:
@@ -17,8 +17,8 @@ services:
immich-microservices:
container_name: immich_microservices
image: ghcr.io/immich-app/immich-server:release
entrypoint: ["/bin/sh", "./start-microservices.sh"]
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
command: ["start-microservices.sh"]
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
env_file:
@@ -31,7 +31,7 @@ services:
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:release
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- model-cache:/cache
@@ -41,8 +41,7 @@ services:
immich-web:
container_name: immich_web
image: ghcr.io/immich-app/immich-web:release
entrypoint: ["/bin/sh", "./entrypoint.sh"]
image: ghcr.io/immich-app/immich-web:${IMMICH_VERSION:-release}
env_file:
- .env
restart: always
@@ -80,7 +79,7 @@ services:
immich-proxy:
container_name: immich_proxy
image: ghcr.io/immich-app/immich-proxy:release
image: ghcr.io/immich-app/immich-proxy:${IMMICH_VERSION:-release}
environment:
# Make sure these values get passed through from the env file
- IMMICH_SERVER_URL

View File

@@ -105,3 +105,12 @@ IMMICH_MACHINE_LEARNING_URL=http://immich-machine-learning:3003
####################################################################################
#IMMICH_API_URL_EXTERNAL=http://localhost:3001
###################################################################################
# Immich Version - Optional
#
# This allows all immich docker images to be pinned to a specific version. By default,
# the version is "release" but could be a specific version, like "v1.59.0".
###################################################################################
#IMMICH_VERSION=

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -0,0 +1,13 @@
# XMP Sidecars
Immich can ingest XMP sidecars on file upload (via the CLI) as well as detect new sidecars that are placed in the filesystem for existing images.
<img src={require('./img/xmp-sidecars.png').default} title='XMP sidecars' />
XMP sidecars are external XML files that contain metadata related to media files. Many applications read and write these files either exclusively or in addition to the metadata written to image files. They can be a powerful tool for editing and storing metadata of a media file without modifying the mdia file itself. When Immich receives or detects an XMP sidecar for a media file, it will attempt to extract the metadata from both the sidecar as well as the media file. It will prioritize the metadata for fields in the sidecar but will fall back and use the metadata in the media file if necessary.
When importing files via the CLI bulk uploader, Immich will automatically detect XMP sidecar files as files that exist next to the original media file and have the exact same name with an additional `.xmp` file extension (i.e., `PXL_20230401_203352928.MP.jpg` and `PXL_20230401_203352928.MP.jpg.xmp`).
There are 2 administrator jobs associated with sidecar files: `SYNC` and `DISCOVER`. The sync job will re-scan all media with existing sidecar files and queue them for a metadata refresh. This is a great use case when third-party applications are used to modify the metadata of media. The discover job will attempt to scan the filesystem for new sidecar files for all media that does not currently have a sidecar file associated with it.
<img src={require('./img/sidecar-jobs.png').default} title='Sidecar Administrator Jobs' />

View File

@@ -136,6 +136,15 @@ IMMICH_MACHINE_LEARNING_URL=http://immich-machine-learning:3003
####################################################################################
#IMMICH_API_URL_EXTERNAL=http://localhost:3001
###################################################################################
# Immich Version - Optional
#
# This allows all immich docker images to be pinned to a specific version. By default,
# the version is "release" but could be a specific version, like "v1.59.0".
###################################################################################
#IMMICH_VERSION=
```
</details>
@@ -159,6 +168,8 @@ For more information on how to use the application, please refer to the [Post In
### Step 4 - Upgrading
If `IMMICH_VERSION` is set, it will need to be updated to the latest or desired version.
When a new version of Immich is [released](https://github.com/immich-app/immich/releases), the application can be upgraded with the following commands, run in the directory with the `docker-compose.yml` file:
```bash title="Upgrade Immich"

View File

@@ -22,13 +22,18 @@ class ClipRequestBody(BaseModel):
classification_model = os.getenv(
"MACHINE_LEARNING_CLASSIFICATION_MODEL", "microsoft/resnet-50"
)
object_model = os.getenv("MACHINE_LEARNING_OBJECT_MODEL", "hustvl/yolos-tiny")
clip_image_model = os.getenv("MACHINE_LEARNING_CLIP_IMAGE_MODEL", "clip-ViT-B-32")
clip_text_model = os.getenv("MACHINE_LEARNING_CLIP_TEXT_MODEL", "clip-ViT-B-32")
facial_recognition_model = os.getenv(
"MACHINE_LEARNING_FACIAL_RECOGNITION_MODEL", "buffalo_l"
)
min_face_score = float(os.getenv("MACHINE_LEARNING_MIN_FACE_SCORE", 0.7))
min_tag_score = float(os.getenv("MACHINE_LEARNING_MIN_TAG_SCORE", 0.9))
eager_startup = (
os.getenv("MACHINE_LEARNING_EAGER_STARTUP", "true") == "true"
) # loads all models at startup
cache_folder = os.getenv("MACHINE_LEARNING_CACHE_FOLDER", "/cache")
_model_cache = {}
@@ -38,12 +43,19 @@ app = FastAPI()
@app.on_event("startup")
async def startup_event():
models = [
(classification_model, "image-classification"),
(clip_image_model, "clip"),
(clip_text_model, "clip"),
(facial_recognition_model, "facial-recognition"),
]
# Get all models
_get_model(object_model, "object-detection")
_get_model(classification_model, "image-classification")
_get_model(clip_image_model)
_get_model(clip_text_model)
_get_model(facial_recognition_model, "facial-recognition")
for model_name, model_type in models:
if eager_startup:
get_cached_model(model_name, model_type)
else:
_get_model(model_name, model_type)
@app.get("/")
@@ -56,37 +68,30 @@ def ping():
return "pong"
@app.post("/object-detection/detect-object", status_code=200)
def object_detection(payload: MlRequestBody):
model = _get_model(object_model, "object-detection")
assetPath = payload.thumbnailPath
return run_engine(model, assetPath)
@app.post("/image-classifier/tag-image", status_code=200)
def image_classification(payload: MlRequestBody):
model = _get_model(classification_model, "image-classification")
model = get_cached_model(classification_model, "image-classification")
assetPath = payload.thumbnailPath
return run_engine(model, assetPath)
@app.post("/sentence-transformer/encode-image", status_code=200)
def clip_encode_image(payload: MlRequestBody):
model = _get_model(clip_image_model)
model = get_cached_model(clip_image_model, "clip")
assetPath = payload.thumbnailPath
return model.encode(Image.open(assetPath)).tolist()
@app.post("/sentence-transformer/encode-text", status_code=200)
def clip_encode_text(payload: ClipRequestBody):
model = _get_model(clip_text_model)
model = get_cached_model(clip_text_model, "clip")
text = payload.text
return model.encode(text).tolist()
@app.post("/facial-recognition/detect-faces", status_code=200)
def facial_recognition(payload: MlRequestBody):
model = _get_model(facial_recognition_model, "facial-recognition")
model = get_cached_model(facial_recognition_model, "facial-recognition")
assetPath = payload.thumbnailPath
img = cv.imread(assetPath)
height, width, _ = img.shape
@@ -94,7 +99,7 @@ def facial_recognition(payload: MlRequestBody):
faces = model.get(img)
for face in faces:
if face.det_score < 0.7:
if face.det_score < min_face_score:
continue
x1, y1, x2, y2 = face.bbox
@@ -121,7 +126,7 @@ def run_engine(engine, path):
for index, pred in enumerate(predictions):
tags = pred["label"].split(", ")
if pred["score"] > 0.9:
if pred["score"] > min_tag_score:
result = [*result, *tags]
if len(result) > 1:
@@ -130,26 +135,32 @@ def run_engine(engine, path):
return result
def _get_model(model, task=None):
def get_cached_model(model, task):
global _model_cache
key = "|".join([model, str(task)])
if key not in _model_cache:
if task:
if task == "facial-recognition":
face_model = FaceAnalysis(
name=model,
root=cache_folder,
allowed_modules=["detection", "recognition"],
)
face_model.prepare(ctx_id=0, det_size=(640, 640))
_model_cache[key] = face_model
else:
_model_cache[key] = pipeline(model=model, task=task)
else:
_model_cache[key] = SentenceTransformer(model, cache_folder=cache_folder)
model = _get_model(model, task)
_model_cache[key] = model
return _model_cache[key]
def _get_model(model, task):
match task:
case "facial-recognition":
model = FaceAnalysis(
name=model,
root=cache_folder,
allowed_modules=["detection", "recognition"],
)
model.prepare(ctx_id=0, det_size=(640, 640))
case "clip":
model = SentenceTransformer(model, cache_folder=cache_folder)
case _:
model = pipeline(model=model, task=task)
return model
if __name__ == "__main__":
host = os.getenv("MACHINE_LEARNING_HOST", "0.0.0.0")
port = int(os.getenv("MACHINE_LEARNING_PORT", 3003))

5
mobile/.gitignore vendored
View File

@@ -49,3 +49,8 @@ app.*.map.json
# Fastlane
ios/fastlane/report.xml
# Isar
default.isar
default.isar.lock
libisar.so

View File

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

View File

@@ -0,0 +1 @@
* Remove Hive box

View File

@@ -5,19 +5,17 @@
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.00032">
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000296">
</testcase>
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="29.247439">
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="64.042552">
</testcase>
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="22.794249">
<failure message="/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/actions/actions_helper.rb:67:in `execute_action&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/runner.rb:255:in `block in execute_action&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/runner.rb:229:in `chdir&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/runner.rb:229:in `execute_action&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/runner.rb:157:in `trigger_action_by_name&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/fast_file.rb:159:in `method_missing&apos;&#10;Fastfile:42:in `block (2 levels) in parsing_binding&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/lane.rb:33:in `call&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/runner.rb:49:in `block in execute&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/runner.rb:45:in `chdir&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/runner.rb:45:in `execute&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/lane_manager.rb:47:in `cruise_lane&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/command_line_handler.rb:36:in `handle&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/commands_generator.rb:110:in `block (2 levels) in run&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/commander-4.6.0/lib/commander/command.rb:187:in `call&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/commander-4.6.0/lib/commander/command.rb:157:in `run&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/commander-4.6.0/lib/commander/runner.rb:444:in `run_active_command&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:124:in `run!&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/commander-4.6.0/lib/commander/delegates.rb:18:in `run!&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/commands_generator.rb:354:in `run&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/commands_generator.rb:43:in `start&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/fastlane/lib/fastlane/cli_tools_distributor.rb:123:in `take_off&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/gems/fastlane-2.212.2/bin/fastlane:23:in `&lt;top (required)&gt;&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/bin/fastlane:25:in `load&apos;&#10;/usr/local/Cellar/fastlane/2.212.2/libexec/bin/fastlane:25:in `&lt;main&gt;&apos;&#10;&#10;Google Api Error: Invalid request - APK specifies a version code that has already been used." />
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="29.676557">
</testcase>

View File

@@ -257,6 +257,15 @@
"sharing_page_empty_list": "EMPTY LIST",
"sharing_silver_appbar_create_shared_album": "Create shared album",
"sharing_silver_appbar_share_partner": "Share with partner",
"partner_page_title": "Partner",
"partner_page_no_more_users": "No more users to add",
"partner_page_empty_message": "Your photos are not yet shared with any partner.",
"partner_page_shared_to_title": "Shared to",
"partner_page_select_partner": "Select partner",
"partner_page_add_partner": "Add partner",
"partner_page_partner_add_failed": "Failed to add partner",
"partner_page_stop_sharing_title": "Stop sharing your photos?",
"partner_page_stop_sharing_content": "{} will no longer be able to access your photos.",
"tab_controller_nav_library": "Library",
"tab_controller_nav_photos": "Photos",
"tab_controller_nav_search": "Search",

View File

@@ -379,7 +379,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 95;
CURRENT_PROJECT_VERSION = 97;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -515,7 +515,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 95;
CURRENT_PROJECT_VERSION = 97;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -543,7 +543,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 95;
CURRENT_PROJECT_VERSION = 97;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;

View File

@@ -45,11 +45,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.55.0</string>
<string>1.57.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>95</string>
<string>97</string>
<key>FLTEnableImpeller</key>
<true />
<key>ITSAppUsesNonExemptEncryption</key>

View File

@@ -19,7 +19,7 @@ platform :ios do
desc "iOS Beta"
lane :beta do
increment_version_number(
version_number: "1.57.0"
version_number: "1.60.0"
)
increment_build_number(
build_number: latest_testflight_build_number + 1,

View File

@@ -5,29 +5,32 @@
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000282">
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000407">
</testcase>
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="2.815995">
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="2.988375">
</testcase>
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="30.927419">
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="45.42439">
</testcase>
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="1.464698">
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="2.381359">
</testcase>
<testcase classname="fastlane.lanes" name="4: build_app" time="66.988561">
<testcase classname="fastlane.lanes" name="4: build_app" time="94.653021">
<failure message="/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/actions/actions_helper.rb:67:in `execute_action&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/runner.rb:255:in `block in execute_action&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/runner.rb:229:in `chdir&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/runner.rb:229:in `execute_action&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/runner.rb:157:in `trigger_action_by_name&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/fast_file.rb:159:in `method_missing&apos;&#10;Fastfile:27:in `block (2 levels) in parsing_binding&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/lane.rb:33:in `call&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/runner.rb:49:in `block in execute&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/runner.rb:45:in `chdir&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/runner.rb:45:in `execute&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/lane_manager.rb:47:in `cruise_lane&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/command_line_handler.rb:36:in `handle&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/commands_generator.rb:110:in `block (2 levels) in run&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/commander-4.6.0/lib/commander/command.rb:187:in `call&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/commander-4.6.0/lib/commander/command.rb:157:in `run&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/commander-4.6.0/lib/commander/runner.rb:444:in `run_active_command&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:124:in `run!&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/commander-4.6.0/lib/commander/delegates.rb:18:in `run!&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/commands_generator.rb:354:in `run&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/commands_generator.rb:43:in `start&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/fastlane/lib/fastlane/cli_tools_distributor.rb:123:in `take_off&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/gems/fastlane-2.212.1/bin/fastlane:23:in `&lt;top (required)&gt;&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/bin/fastlane:25:in `load&apos;&#10;/usr/local/Cellar/fastlane/2.212.1/libexec/bin/fastlane:25:in `&lt;main&gt;&apos;&#10;&#10;Error packaging up the application" />
</testcase>
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="58.237354">
</testcase>

View File

@@ -20,6 +20,7 @@ import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/routing/tab_navigation_observer.dart';
import 'package:immich_mobile/shared/models/album.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/models/etag.dart';
import 'package:immich_mobile/shared/models/exif_info.dart';
import 'package:immich_mobile/shared/models/logger_message.model.dart';
import 'package:immich_mobile/shared/models/store.dart';
@@ -89,6 +90,7 @@ Future<Isar> loadDb() async {
BackupAlbumSchema,
DuplicatedAssetSchema,
LoggerMessageSchema,
ETagSchema,
],
directory: dir.path,
maxSizeMiB: 256,

View File

@@ -8,6 +8,7 @@ import 'package:immich_mobile/shared/models/album.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/providers/db.provider.dart';
import 'package:immich_mobile/shared/providers/user.provider.dart';
import 'package:isar/isar.dart';
class SharedAlbumNotifier extends StateNotifier<List<Album>> {
@@ -73,7 +74,9 @@ final sharedAlbumProvider =
});
final sharedAlbumDetailProvider =
StreamProvider.autoDispose.family<Album, int>((ref, albumId) async* {
StreamProvider.family<Album, int>((ref, albumId) async* {
final user = ref.watch(currentUserProvider);
if (user == null) return;
final AlbumService sharedAlbumService = ref.watch(albumServiceProvider);
await for (final a in sharedAlbumService.watchAlbum(albumId)) {

View File

@@ -2,8 +2,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/services/user.service.dart';
final suggestedSharedUsersProvider =
FutureProvider.autoDispose<List<User>>((ref) {
final otherUsersProvider = FutureProvider.autoDispose<List<User>>((ref) {
UserService userService = ref.watch(userServiceProvider);
return userService.getUsersInDb();

View File

@@ -1,85 +0,0 @@
import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:immich_mobile/routing/router.dart';
class SharingSliverAppBar extends StatelessWidget {
const SharingSliverAppBar({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return SliverAppBar(
centerTitle: true,
floating: false,
pinned: true,
snap: false,
automaticallyImplyLeading: false,
title: Text(
'IMMICH',
style: TextStyle(
fontFamily: 'SnowburstOne',
fontWeight: FontWeight.bold,
fontSize: 22,
color: Theme.of(context).primaryColor,
),
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(50.0),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(right: 4.0),
child: ElevatedButton.icon(
onPressed: () {
AutoRouter.of(context)
.push(CreateAlbumRoute(isSharedAlbum: true));
},
icon: const Icon(
Icons.photo_album_outlined,
size: 20,
),
label: const Text(
"sharing_silver_appbar_create_shared_album",
maxLines: 1,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 11,
// color: Theme.of(context).primaryColor,
),
).tr(),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 4.0),
child: ElevatedButton.icon(
onPressed: null,
icon: const Icon(
Icons.swap_horizontal_circle_outlined,
size: 20,
),
label: const Text(
"sharing_silver_appbar_share_partner",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 11,
),
maxLines: 1,
).tr(),
),
),
)
],
),
),
),
);
}
}

View File

@@ -8,6 +8,7 @@ import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structu
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/providers/asset.provider.dart';
import 'package:immich_mobile/shared/providers/user.provider.dart';
class AssetSelectionPage extends HookConsumerWidget {
const AssetSelectionPage({
@@ -21,7 +22,8 @@ class AssetSelectionPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final renderList = ref.watch(remoteAssetsProvider);
final currentUser = ref.watch(currentUserProvider);
final renderList = ref.watch(remoteAssetsProvider(currentUser?.isarId));
final selected = useState<Set<Asset>>(existingAssets);
final selectionEnabledHook = useState(true);

View File

@@ -17,7 +17,7 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final AsyncValue<List<User>> suggestedShareUsers =
ref.watch(suggestedSharedUsersProvider);
ref.watch(otherUsersProvider);
final sharedUsersList = useState<Set<User>>({});
addNewUsersHandler() {

View File

@@ -20,8 +20,7 @@ class SelectUserForSharingPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final sharedUsersList = useState<Set<User>>({});
AsyncValue<List<User>> suggestedShareUsers =
ref.watch(suggestedSharedUsersProvider);
final suggestedShareUsers = ref.watch(otherUsersProvider);
createSharedAlbum() async {
var newAlbum =

View File

@@ -5,10 +5,11 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
import 'package:immich_mobile/modules/album/ui/album_thumbnail_card.dart';
import 'package:immich_mobile/modules/album/ui/sharing_sliver_appbar.dart';
import 'package:immich_mobile/modules/partner/providers/partner.provider.dart';
import 'package:immich_mobile/modules/partner/ui/partner_list.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/models/album.dart';
import 'package:immich_mobile/shared/models/store.dart' as store;
import 'package:immich_mobile/shared/providers/user.provider.dart';
import 'package:immich_mobile/shared/ui/immich_image.dart';
class SharingPage extends HookConsumerWidget {
@@ -17,7 +18,8 @@ class SharingPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final List<Album> sharedAlbums = ref.watch(sharedAlbumProvider);
final userId = store.Store.get(store.StoreKey.currentUser).id;
final userId = ref.watch(currentUserProvider)?.id;
final partner = ref.watch(partnerSharedWithProvider);
var isDarkMode = Theme.of(context).brightness == Brightness.dark;
useEffect(
@@ -63,8 +65,7 @@ class SharingPage extends HookConsumerWidget {
final isOwner = album.ownerId == userId;
return ListTile(
contentPadding:
const EdgeInsets.symmetric(vertical: 12, horizontal: 12),
contentPadding: const EdgeInsets.symmetric(horizontal: 12),
leading: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: ImmichImage(
@@ -93,7 +94,8 @@ class SharingPage extends HookConsumerWidget {
)
: album.ownerName != null
? Text(
'album_thumbnail_shared_by'.tr(args: [album.ownerName!]),
'album_thumbnail_shared_by'
.tr(args: [album.ownerName!]),
style: const TextStyle(
fontSize: 12.0,
),
@@ -110,6 +112,75 @@ class SharingPage extends HookConsumerWidget {
);
}
buildTopBottons() {
return Padding(
padding: const EdgeInsets.only(
left: 12.0,
right: 12.0,
bottom: 12.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: ElevatedButton.icon(
onPressed: () {
AutoRouter.of(context)
.push(CreateAlbumRoute(isSharedAlbum: true));
},
icon: const Icon(
Icons.photo_album_outlined,
size: 20,
),
label: const Text(
"sharing_silver_appbar_create_shared_album",
maxLines: 1,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 11,
),
).tr(),
),
),
const SizedBox(width: 12.0),
Expanded(
child: ElevatedButton.icon(
onPressed: () =>
AutoRouter.of(context).push(const PartnerRoute()),
icon: const Icon(
Icons.swap_horizontal_circle_outlined,
size: 20,
),
label: const Text(
"sharing_silver_appbar_share_partner",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 11,
),
maxLines: 1,
).tr(),
),
)
],
),
);
}
AppBar buildAppBar() {
return AppBar(
centerTitle: true,
automaticallyImplyLeading: false,
title: const Text(
'IMMICH',
style: TextStyle(
fontFamily: 'SnowburstOne',
fontWeight: FontWeight.bold,
fontSize: 22,
),
),
);
}
buildEmptyListIndication() {
return SliverToBoxAdapter(
child: Padding(
@@ -123,7 +194,6 @@ class SharingPage extends HookConsumerWidget {
width: 0.5,
),
),
// color: Colors.transparent,
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
@@ -160,11 +230,27 @@ class SharingPage extends HookConsumerWidget {
}
return Scaffold(
appBar: buildAppBar(),
body: CustomScrollView(
slivers: [
const SharingSliverAppBar(),
SliverToBoxAdapter(child: buildTopBottons()),
if (partner.isNotEmpty)
SliverPadding(
padding: const EdgeInsets.only(left: 12, right: 12, bottom: 4),
sliver: SliverToBoxAdapter(
child: const Text(
"partner_page_title",
style: TextStyle(fontWeight: FontWeight.bold),
).tr(),
),
),
if (partner.isNotEmpty) PartnerList(partner: partner),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
padding: EdgeInsets.only(
left: 12,
right: 12,
top: partner.isEmpty ? 0 : 16,
),
sliver: SliverToBoxAdapter(
child: const Text(
"sharing_page_album",

View File

@@ -3,16 +3,18 @@ import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structu
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/providers/db.provider.dart';
import 'package:immich_mobile/shared/providers/user.provider.dart';
import 'package:isar/isar.dart';
final archiveProvider = StreamProvider<RenderList>((ref) async* {
final user = ref.watch(currentUserProvider);
if (user == null) return;
final query = ref
.watch(dbProvider)
.assets
.filter()
.ownerIdEqualTo(Store.get(StoreKey.currentUser).isarId)
.ownerIdEqualTo(user.isarId)
.isArchivedEqualTo(true)
.sortByFileCreatedAt();
final settings = ref.watch(appSettingsServiceProvider);

View File

@@ -4,9 +4,9 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/asset_viewer/providers/asset_description.provider.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/providers/user.provider.dart';
import 'package:immich_mobile/shared/ui/immich_toast.dart';
import 'package:logging/logging.dart';
import 'package:immich_mobile/shared/models/store.dart' as store;
class DescriptionInput extends HookConsumerWidget {
DescriptionInput({
@@ -25,9 +25,10 @@ class DescriptionInput extends HookConsumerWidget {
final focusNode = useFocusNode();
final isFocus = useState(false);
final isTextEmpty = useState(controller.text.isEmpty);
final descriptionProvider = ref.watch(assetDescriptionProvider(asset).notifier);
final descriptionProvider =
ref.watch(assetDescriptionProvider(asset).notifier);
final description = ref.watch(assetDescriptionProvider(asset));
final owner = store.Store.get(store.StoreKey.currentUser);
final owner = ref.watch(currentUserProvider);
final hasError = useState(false);
controller.text = description;
@@ -67,7 +68,7 @@ class DescriptionInput extends HookConsumerWidget {
}
return TextField(
enabled: owner.isarId == asset.ownerId,
enabled: owner?.isarId == asset.ownerId,
focusNode: focusNode,
onTap: () => isFocus.value = true,
onChanged: (value) {

View File

@@ -7,7 +7,7 @@ part of 'backup_album.model.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetBackupAlbumCollection on Isar {
IsarCollection<BackupAlbum> get backupAlbums => this.collection();
@@ -45,7 +45,7 @@ const BackupAlbumSchema = CollectionSchema(
getId: _backupAlbumGetId,
getLinks: _backupAlbumGetLinks,
attach: _backupAlbumAttach,
version: '3.0.5',
version: '3.1.0+1',
);
int _backupAlbumEstimateSize(

View File

@@ -7,7 +7,7 @@ part of 'duplicated_asset.model.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetDuplicatedAssetCollection on Isar {
IsarCollection<DuplicatedAsset> get duplicatedAssets => this.collection();
@@ -34,7 +34,7 @@ const DuplicatedAssetSchema = CollectionSchema(
getId: _duplicatedAssetGetId,
getLinks: _duplicatedAssetGetLinks,
attach: _duplicatedAssetAttach,
version: '3.0.5',
version: '3.1.0+1',
);
int _duplicatedAssetEstimateSize(

View File

@@ -219,8 +219,6 @@ class BackupService {
if (file != null) {
String originalFileName = await entity.titleAsync;
String fileNameWithoutPath =
originalFileName.toString().split(".")[0];
var fileExtension = p.extension(file.path);
var mimeType = FileHelper.getMimeType(file.path);
var fileStream = file.openRead();
@@ -228,7 +226,7 @@ class BackupService {
"assetData",
fileStream,
file.lengthSync(),
filename: fileNameWithoutPath,
filename: originalFileName,
contentType: MediaType(
mimeType["type"],
mimeType["subType"],
@@ -334,14 +332,13 @@ class BackupService {
var motionFile = File(validPath);
var fileStream = motionFile.openRead();
String originalFileName = await entity.titleAsync;
String fileNameWithoutPath = originalFileName.toString().split(".")[0];
var mimeType = FileHelper.getMimeType(validPath);
return http.MultipartFile(
"livePhotoData",
fileStream,
motionFile.lengthSync(),
filename: fileNameWithoutPath,
filename: originalFileName,
contentType: MediaType(
mimeType["type"],
mimeType["subType"],

View File

@@ -3,16 +3,18 @@ import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structu
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/providers/db.provider.dart';
import 'package:immich_mobile/shared/providers/user.provider.dart';
import 'package:isar/isar.dart';
final favoriteAssetsProvider = StreamProvider<RenderList>((ref) async* {
final user = ref.watch(currentUserProvider);
if (user == null) return;
final query = ref
.watch(dbProvider)
.assets
.filter()
.ownerIdEqualTo(Store.get(StoreKey.currentUser).isarId)
.ownerIdEqualTo(user.isarId)
.isFavoriteEqualTo(true)
.sortByFileCreatedAt();
final settings = ref.watch(appSettingsServiceProvider);

View File

@@ -1,47 +1,16 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/shared/ui/confirm_dialog.dart';
class DeleteDialog extends ConsumerWidget {
class DeleteDialog extends ConfirmDialog {
final Function onDelete;
const DeleteDialog({Key? key, required this.onDelete}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return AlertDialog(
// backgroundColor: Colors.grey[200],
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
title: const Text("delete_dialog_title").tr(),
content: const Text("delete_dialog_alert").tr(),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
"delete_dialog_cancel",
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
),
).tr(),
),
TextButton(
onPressed: () {
onDelete();
Navigator.of(context).pop();
},
child: Text(
"delete_dialog_ok",
style: TextStyle(
color: Colors.red[400],
fontWeight: FontWeight.bold,
),
).tr(),
),
],
);
}
const DeleteDialog({Key? key, required this.onDelete})
: super(
key: key,
title: "delete_dialog_title",
content: "delete_dialog_alert",
cancel: "delete_dialog_cancel",
ok: "delete_dialog_ok",
onOk: onDelete,
);
}

View File

@@ -20,6 +20,7 @@ import 'package:immich_mobile/shared/models/album.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/providers/asset.provider.dart';
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
import 'package:immich_mobile/shared/providers/user.provider.dart';
import 'package:immich_mobile/shared/providers/websocket.provider.dart';
import 'package:immich_mobile/shared/services/share.service.dart';
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
@@ -38,6 +39,7 @@ class HomePage extends HookConsumerWidget {
final albums = ref.watch(albumProvider).where((a) => a.isRemote).toList();
final sharedAlbums = ref.watch(sharedAlbumProvider);
final albumService = ref.watch(albumServiceProvider);
final currentUser = ref.watch(currentUserProvider);
final tipOneOpacity = useState(0.0);
final refreshCount = useState(0);
@@ -300,7 +302,7 @@ class HomePage extends HookConsumerWidget {
bottom: false,
child: Stack(
children: [
ref.watch(assetsProvider).when(
ref.watch(assetsProvider(currentUser?.isarId)).when(
data: (data) => data.isEmpty
? buildLoadingIndicator()
: ImmichAssetGrid(

View File

@@ -0,0 +1,50 @@
import 'dart:async';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/album/providers/suggested_shared_users.provider.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/providers/db.provider.dart';
import 'package:isar/isar.dart';
class PartnerSharedWithNotifier extends StateNotifier<List<User>> {
PartnerSharedWithNotifier(Isar db) : super([]) {
final query = db.users.filter().isPartnerSharedWithEqualTo(true);
query.findAll().then((partners) => state = partners);
query.watch().listen((partners) => state = partners);
}
}
final partnerSharedWithProvider =
StateNotifierProvider<PartnerSharedWithNotifier, List<User>>((ref) {
return PartnerSharedWithNotifier(ref.watch(dbProvider));
});
class PartnerSharedByNotifier extends StateNotifier<List<User>> {
PartnerSharedByNotifier(Isar db) : super([]) {
final query = db.users.filter().isPartnerSharedByEqualTo(true);
query.findAll().then((partners) => state = partners);
streamSub = query.watch().listen((partners) => state = partners);
}
late final StreamSubscription<List<User>> streamSub;
@override
void dispose() {
streamSub.cancel();
super.dispose();
}
}
final partnerSharedByProvider =
StateNotifierProvider<PartnerSharedByNotifier, List<User>>((ref) {
return PartnerSharedByNotifier(ref.watch(dbProvider));
});
final partnerAvailableProvider =
FutureProvider.autoDispose<List<User>>((ref) async {
final otherUsers = await ref.watch(otherUsersProvider.future);
final currentPartners = ref.watch(partnerSharedByProvider);
final available = Set<User>.of(otherUsers);
available.removeAll(currentPartners);
return available.toList();
});

View File

@@ -0,0 +1,72 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/providers/api.provider.dart';
import 'package:immich_mobile/shared/providers/db.provider.dart';
import 'package:immich_mobile/shared/services/api.service.dart';
import 'package:isar/isar.dart';
import 'package:logging/logging.dart';
final partnerServiceProvider = Provider(
(ref) => PartnerService(
ref.watch(apiServiceProvider),
ref.watch(dbProvider),
),
);
enum PartnerDirection {
sharedWith("shared-with"),
sharedBy("shared-by");
const PartnerDirection(
this._value,
);
final String _value;
}
class PartnerService {
final ApiService _apiService;
final Isar _db;
final Logger _log = Logger("PartnerService");
PartnerService(this._apiService, this._db);
Future<List<User>?> getPartners(PartnerDirection direction) async {
try {
final userDtos =
await _apiService.partnerApi.getPartners(direction._value);
if (userDtos != null) {
return userDtos.map((u) => User.fromDto(u)).toList();
}
} catch (e) {
_log.warning("failed to get partners for direction $direction:\n$e");
}
return null;
}
Future<bool> removePartner(User partner) async {
try {
await _apiService.partnerApi.removePartner(partner.id);
partner.isPartnerSharedBy = false;
await _db.writeTxn(() => _db.users.put(partner));
} catch (e) {
_log.warning("failed to remove partner ${partner.id}:\n$e");
return false;
}
return true;
}
Future<bool> addPartner(User partner) async {
try {
final dto = await _apiService.partnerApi.createPartner(partner.id);
if (dto != null) {
partner.isPartnerSharedBy = true;
await _db.writeTxn(() => _db.users.put(partner));
return true;
}
} catch (e) {
_log.warning("failed to add partner ${partner.id}:\n$e");
}
return false;
}
}

View File

@@ -0,0 +1,30 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/ui/user_avatar.dart';
class PartnerList extends HookConsumerWidget {
const PartnerList({Key? key, required this.partner}) : super(key: key);
final List<User> partner;
@override
Widget build(BuildContext context, WidgetRef ref) {
return SliverList(
delegate:
SliverChildBuilderDelegate(listEntry, childCount: partner.length),
);
}
Widget listEntry(BuildContext context, int index) {
final User p = partner[index];
return ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 12.0),
leading: userAvatar(context, p, radius: 30),
title: Text("${p.firstName} ${p.lastName}"),
onTap: () => AutoRouter.of(context).push(PartnerDetailRoute(partner: p)),
);
}
}

View File

@@ -0,0 +1,40 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/providers/asset.provider.dart';
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
class PartnerDetailPage extends HookConsumerWidget {
const PartnerDetailPage({Key? key, required this.partner}) : super(key: key);
final User partner;
@override
Widget build(BuildContext context, WidgetRef ref) {
final assets = ref.watch(assetsProvider(partner.isarId));
return Scaffold(
appBar: AppBar(
title: Text("${partner.firstName} ${partner.lastName}"),
elevation: 0,
centerTitle: false,
),
body: assets.when(
data: (renderList) => renderList.isEmpty
? Padding(
padding: const EdgeInsets.all(16),
child: Text(
"It seems ${partner.firstName} does not have any photos...\n"
"Or your server version does not match the app version."),
)
: ImmichAssetGrid(
renderList: renderList,
onRefresh: () => ref.read(assetProvider.notifier).getAllAsset(),
),
error: (e, _) => Text("Error loading partners:\n$e"),
loading: () => const Center(child: ImmichLoadingIndicator()),
),
);
}
}

View File

@@ -0,0 +1,160 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/partner/providers/partner.provider.dart';
import 'package:immich_mobile/modules/partner/services/partner.service.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/ui/confirm_dialog.dart';
import 'package:immich_mobile/shared/ui/immich_toast.dart';
import 'package:immich_mobile/shared/ui/user_avatar.dart';
class PartnerPage extends HookConsumerWidget {
const PartnerPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final List<User> partners = ref.watch(partnerSharedByProvider);
final availableUsers = ref.watch(partnerAvailableProvider);
addNewUsersHandler() async {
final users = availableUsers.value;
if (users == null || users.isEmpty) {
ImmichToast.show(
context: context,
msg: "partner_page_no_more_users".tr(),
);
return;
}
final selectedUser = await showDialog<User>(
context: context,
builder: (context) {
return SimpleDialog(
title: const Text("partner_page_select_partner").tr(),
children: [
for (User u in users)
SimpleDialogOption(
onPressed: () => Navigator.pop(context, u),
child: Row(
children: [
Padding(
padding: const EdgeInsets.only(right: 8),
child: userAvatar(context, u),
),
Text("${u.firstName} ${u.lastName}"),
],
),
)
],
);
},
);
if (selectedUser != null) {
final ok =
await ref.read(partnerServiceProvider).addPartner(selectedUser);
if (ok) {
ref.invalidate(partnerSharedByProvider);
} else {
ImmichToast.show(
context: context,
msg: "partner_page_partner_add_failed".tr(),
toastType: ToastType.error,
);
}
}
}
onDeleteUser(User u) {
return showDialog(
context: context,
builder: (BuildContext context) {
return ConfirmDialog(
title: "partner_page_stop_sharing_title",
content:
"partner_page_stop_sharing_content".tr(args: [u.firstName]),
onOk: () => ref.read(partnerServiceProvider).removePartner(u),
);
},
);
}
buildUserList(List<User> users) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 16.0, top: 16.0),
child: const Text(
"partner_page_shared_to_title",
style: TextStyle(
fontSize: 14,
color: Colors.grey,
fontWeight: FontWeight.bold,
),
).tr(),
),
if (users.isNotEmpty)
ListView.builder(
shrinkWrap: true,
itemCount: users.length,
itemBuilder: ((context, index) {
return ListTile(
leading: userAvatar(context, users[index]),
title: Text(
users[index].email,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
trailing: IconButton(
icon: const Icon(Icons.person_remove),
onPressed: () => onDeleteUser(users[index]),
),
);
}),
),
if (users.isEmpty)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: const Text(
"partner_page_empty_message",
style: TextStyle(fontSize: 14),
).tr(),
),
ElevatedButton.icon(
onPressed: availableUsers.whenOrNull(
data: (data) => addNewUsersHandler,
),
icon: const Icon(Icons.person_add),
label: const Text("partner_page_add_partner").tr(),
),
],
),
),
],
);
}
return Scaffold(
appBar: AppBar(
title: const Text("partner_page_title").tr(),
elevation: 0,
centerTitle: false,
actions: [
IconButton(
onPressed:
availableUsers.whenOrNull(data: (data) => addNewUsersHandler),
icon: const Icon(Icons.person_add),
tooltip: "partner_page_add_partner".tr(),
)
],
),
body: buildUserList(partners),
);
}
}

View File

@@ -6,6 +6,8 @@ import 'package:immich_mobile/modules/album/views/album_viewer_page.dart';
import 'package:immich_mobile/modules/album/views/asset_selection_page.dart';
import 'package:immich_mobile/modules/album/views/create_album_page.dart';
import 'package:immich_mobile/modules/album/views/library_page.dart';
import 'package:immich_mobile/modules/partner/views/partner_detail_page.dart';
import 'package:immich_mobile/modules/partner/views/partner_page.dart';
import 'package:immich_mobile/modules/album/views/select_additional_user_for_sharing_page.dart';
import 'package:immich_mobile/modules/album/views/select_user_for_sharing_page.dart';
import 'package:immich_mobile/modules/album/views/sharing_page.dart';
@@ -35,6 +37,7 @@ import 'package:immich_mobile/routing/duplicate_guard.dart';
import 'package:immich_mobile/routing/gallery_permission_guard.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/models/album.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/models/logger_message.model.dart';
import 'package:immich_mobile/shared/providers/api.provider.dart';
import 'package:immich_mobile/shared/services/api.service.dart';
@@ -136,6 +139,8 @@ part 'router.gr.dart';
DuplicateGuard,
],
),
AutoRoute(page: PartnerPage, guards: [AuthGuard, DuplicateGuard]),
AutoRoute(page: PartnerDetailPage, guards: [AuthGuard, DuplicateGuard])
],
)
class AppRouter extends _$AppRouter {

View File

@@ -256,6 +256,22 @@ class _$AppRouter extends RootStackRouter {
child: const ArchivePage(),
);
},
PartnerRoute.name: (routeData) {
return MaterialPageX<dynamic>(
routeData: routeData,
child: const PartnerPage(),
);
},
PartnerDetailRoute.name: (routeData) {
final args = routeData.argsAs<PartnerDetailRouteArgs>();
return MaterialPageX<dynamic>(
routeData: routeData,
child: PartnerDetailPage(
key: args.key,
partner: args.partner,
),
);
},
HomeRoute.name: (routeData) {
return MaterialPageX<dynamic>(
routeData: routeData,
@@ -523,6 +539,22 @@ class _$AppRouter extends RootStackRouter {
duplicateGuard,
],
),
RouteConfig(
PartnerRoute.name,
path: '/partner-page',
guards: [
authGuard,
duplicateGuard,
],
),
RouteConfig(
PartnerDetailRoute.name,
path: '/partner-detail-page',
guards: [
authGuard,
duplicateGuard,
],
),
];
}
@@ -1113,6 +1145,52 @@ class ArchiveRoute extends PageRouteInfo<void> {
static const String name = 'ArchiveRoute';
}
/// generated route for
/// [PartnerPage]
class PartnerRoute extends PageRouteInfo<void> {
const PartnerRoute()
: super(
PartnerRoute.name,
path: '/partner-page',
);
static const String name = 'PartnerRoute';
}
/// generated route for
/// [PartnerDetailPage]
class PartnerDetailRoute extends PageRouteInfo<PartnerDetailRouteArgs> {
PartnerDetailRoute({
Key? key,
required User partner,
}) : super(
PartnerDetailRoute.name,
path: '/partner-detail-page',
args: PartnerDetailRouteArgs(
key: key,
partner: partner,
),
);
static const String name = 'PartnerDetailRoute';
}
class PartnerDetailRouteArgs {
const PartnerDetailRouteArgs({
this.key,
required this.partner,
});
final Key? key;
final User partner;
@override
String toString() {
return 'PartnerDetailRouteArgs{key: $key, partner: $partner}';
}
}
/// generated route for
/// [HomePage]
class HomeRoute extends PageRouteInfo<void> {

View File

@@ -87,8 +87,8 @@ class Album {
remoteId == other.remoteId &&
localId == other.localId &&
name == other.name &&
createdAt == other.createdAt &&
modifiedAt == other.modifiedAt &&
createdAt.isAtSameMomentAs(other.createdAt) &&
modifiedAt.isAtSameMomentAs(other.modifiedAt) &&
shared == other.shared &&
owner.value == other.owner.value &&
thumbnail.value == other.thumbnail.value &&
@@ -128,8 +128,8 @@ class Album {
final Album a = Album(
remoteId: dto.id,
name: dto.albumName,
createdAt: DateTime.parse(dto.createdAt),
modifiedAt: DateTime.parse(dto.updatedAt),
createdAt: dto.createdAt,
modifiedAt: dto.updatedAt,
shared: dto.shared,
);
a.owner.value = await db.users.getById(dto.ownerId);

View File

@@ -7,7 +7,7 @@ part of 'album.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetAlbumCollection on Isar {
IsarCollection<Album> get albums => this.collection();
@@ -111,7 +111,7 @@ const AlbumSchema = CollectionSchema(
getId: _albumGetId,
getLinks: _albumGetLinks,
attach: _albumAttach,
version: '3.0.5',
version: '3.1.0+1',
);
int _albumEstimateSize(

View File

@@ -15,9 +15,9 @@ class Asset {
Asset.remote(AssetResponseDto remote)
: remoteId = remote.id,
isLocal = false,
fileCreatedAt = DateTime.parse(remote.fileCreatedAt),
fileModifiedAt = DateTime.parse(remote.fileModifiedAt),
updatedAt = DateTime.parse(remote.updatedAt),
fileCreatedAt = remote.fileCreatedAt,
fileModifiedAt = remote.fileModifiedAt,
updatedAt = remote.updatedAt,
durationInSeconds = remote.duration.toDuration()?.inSeconds ?? 0,
type = remote.type.toAssetType(),
fileName = p.basename(remote.originalPath),
@@ -179,9 +179,9 @@ class Asset {
localId == other.localId &&
deviceId == other.deviceId &&
ownerId == other.ownerId &&
fileCreatedAt == other.fileCreatedAt &&
fileModifiedAt == other.fileModifiedAt &&
updatedAt == other.updatedAt &&
fileCreatedAt.isAtSameMomentAs(other.fileCreatedAt) &&
fileModifiedAt.isAtSameMomentAs(other.fileModifiedAt) &&
updatedAt.isAtSameMomentAs(other.updatedAt) &&
durationInSeconds == other.durationInSeconds &&
type == other.type &&
width == other.width &&

View File

@@ -7,7 +7,7 @@ part of 'asset.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetAssetCollection on Isar {
IsarCollection<Asset> get assets => this.collection();
@@ -142,7 +142,7 @@ const AssetSchema = CollectionSchema(
getId: _assetGetId,
getLinks: _assetGetLinks,
attach: _assetAttach,
version: '3.0.5',
version: '3.1.0+1',
);
int _assetEstimateSize(

View File

@@ -0,0 +1,13 @@
import 'package:immich_mobile/utils/hash.dart';
import 'package:isar/isar.dart';
part 'etag.g.dart';
@Collection(inheritance: false)
class ETag {
ETag({required this.id, this.value});
Id get isarId => fastHash(id);
@Index(unique: true, replace: true, type: IndexType.hash)
String id;
String? value;
}

View File

@@ -0,0 +1,724 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'etag.dart';
// **************************************************************************
// IsarCollectionGenerator
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetETagCollection on Isar {
IsarCollection<ETag> get eTags => this.collection();
}
const ETagSchema = CollectionSchema(
name: r'ETag',
id: -644290296585643859,
properties: {
r'id': PropertySchema(
id: 0,
name: r'id',
type: IsarType.string,
),
r'value': PropertySchema(
id: 1,
name: r'value',
type: IsarType.string,
)
},
estimateSize: _eTagEstimateSize,
serialize: _eTagSerialize,
deserialize: _eTagDeserialize,
deserializeProp: _eTagDeserializeProp,
idName: r'isarId',
indexes: {
r'id': IndexSchema(
id: -3268401673993471357,
name: r'id',
unique: true,
replace: true,
properties: [
IndexPropertySchema(
name: r'id',
type: IndexType.hash,
caseSensitive: true,
)
],
)
},
links: {},
embeddedSchemas: {},
getId: _eTagGetId,
getLinks: _eTagGetLinks,
attach: _eTagAttach,
version: '3.1.0+1',
);
int _eTagEstimateSize(
ETag object,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
var bytesCount = offsets.last;
bytesCount += 3 + object.id.length * 3;
{
final value = object.value;
if (value != null) {
bytesCount += 3 + value.length * 3;
}
}
return bytesCount;
}
void _eTagSerialize(
ETag object,
IsarWriter writer,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
writer.writeString(offsets[0], object.id);
writer.writeString(offsets[1], object.value);
}
ETag _eTagDeserialize(
Id id,
IsarReader reader,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
final object = ETag(
id: reader.readString(offsets[0]),
value: reader.readStringOrNull(offsets[1]),
);
return object;
}
P _eTagDeserializeProp<P>(
IsarReader reader,
int propertyId,
int offset,
Map<Type, List<int>> allOffsets,
) {
switch (propertyId) {
case 0:
return (reader.readString(offset)) as P;
case 1:
return (reader.readStringOrNull(offset)) as P;
default:
throw IsarError('Unknown property with id $propertyId');
}
}
Id _eTagGetId(ETag object) {
return object.isarId;
}
List<IsarLinkBase<dynamic>> _eTagGetLinks(ETag object) {
return [];
}
void _eTagAttach(IsarCollection<dynamic> col, Id id, ETag object) {}
extension ETagByIndex on IsarCollection<ETag> {
Future<ETag?> getById(String id) {
return getByIndex(r'id', [id]);
}
ETag? getByIdSync(String id) {
return getByIndexSync(r'id', [id]);
}
Future<bool> deleteById(String id) {
return deleteByIndex(r'id', [id]);
}
bool deleteByIdSync(String id) {
return deleteByIndexSync(r'id', [id]);
}
Future<List<ETag?>> getAllById(List<String> idValues) {
final values = idValues.map((e) => [e]).toList();
return getAllByIndex(r'id', values);
}
List<ETag?> getAllByIdSync(List<String> idValues) {
final values = idValues.map((e) => [e]).toList();
return getAllByIndexSync(r'id', values);
}
Future<int> deleteAllById(List<String> idValues) {
final values = idValues.map((e) => [e]).toList();
return deleteAllByIndex(r'id', values);
}
int deleteAllByIdSync(List<String> idValues) {
final values = idValues.map((e) => [e]).toList();
return deleteAllByIndexSync(r'id', values);
}
Future<Id> putById(ETag object) {
return putByIndex(r'id', object);
}
Id putByIdSync(ETag object, {bool saveLinks = true}) {
return putByIndexSync(r'id', object, saveLinks: saveLinks);
}
Future<List<Id>> putAllById(List<ETag> objects) {
return putAllByIndex(r'id', objects);
}
List<Id> putAllByIdSync(List<ETag> objects, {bool saveLinks = true}) {
return putAllByIndexSync(r'id', objects, saveLinks: saveLinks);
}
}
extension ETagQueryWhereSort on QueryBuilder<ETag, ETag, QWhere> {
QueryBuilder<ETag, ETag, QAfterWhere> anyIsarId() {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(const IdWhereClause.any());
});
}
}
extension ETagQueryWhere on QueryBuilder<ETag, ETag, QWhereClause> {
QueryBuilder<ETag, ETag, QAfterWhereClause> isarIdEqualTo(Id isarId) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IdWhereClause.between(
lower: isarId,
upper: isarId,
));
});
}
QueryBuilder<ETag, ETag, QAfterWhereClause> isarIdNotEqualTo(Id isarId) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query
.addWhereClause(
IdWhereClause.lessThan(upper: isarId, includeUpper: false),
)
.addWhereClause(
IdWhereClause.greaterThan(lower: isarId, includeLower: false),
);
} else {
return query
.addWhereClause(
IdWhereClause.greaterThan(lower: isarId, includeLower: false),
)
.addWhereClause(
IdWhereClause.lessThan(upper: isarId, includeUpper: false),
);
}
});
}
QueryBuilder<ETag, ETag, QAfterWhereClause> isarIdGreaterThan(Id isarId,
{bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.greaterThan(lower: isarId, includeLower: include),
);
});
}
QueryBuilder<ETag, ETag, QAfterWhereClause> isarIdLessThan(Id isarId,
{bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.lessThan(upper: isarId, includeUpper: include),
);
});
}
QueryBuilder<ETag, ETag, QAfterWhereClause> isarIdBetween(
Id lowerIsarId,
Id upperIsarId, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IdWhereClause.between(
lower: lowerIsarId,
includeLower: includeLower,
upper: upperIsarId,
includeUpper: includeUpper,
));
});
}
QueryBuilder<ETag, ETag, QAfterWhereClause> idEqualTo(String id) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IndexWhereClause.equalTo(
indexName: r'id',
value: [id],
));
});
}
QueryBuilder<ETag, ETag, QAfterWhereClause> idNotEqualTo(String id) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query
.addWhereClause(IndexWhereClause.between(
indexName: r'id',
lower: [],
upper: [id],
includeUpper: false,
))
.addWhereClause(IndexWhereClause.between(
indexName: r'id',
lower: [id],
includeLower: false,
upper: [],
));
} else {
return query
.addWhereClause(IndexWhereClause.between(
indexName: r'id',
lower: [id],
includeLower: false,
upper: [],
))
.addWhereClause(IndexWhereClause.between(
indexName: r'id',
lower: [],
upper: [id],
includeUpper: false,
));
}
});
}
}
extension ETagQueryFilter on QueryBuilder<ETag, ETag, QFilterCondition> {
QueryBuilder<ETag, ETag, QAfterFilterCondition> idEqualTo(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'id',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> idGreaterThan(
String value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
include: include,
property: r'id',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> idLessThan(
String value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.lessThan(
include: include,
property: r'id',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> idBetween(
String lower,
String upper, {
bool includeLower = true,
bool includeUpper = true,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.between(
property: r'id',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> idStartsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.startsWith(
property: r'id',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> idEndsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.endsWith(
property: r'id',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> idContains(String value,
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.contains(
property: r'id',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> idMatches(String pattern,
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.matches(
property: r'id',
wildcard: pattern,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> idIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'id',
value: '',
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> idIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
property: r'id',
value: '',
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> isarIdEqualTo(Id value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'isarId',
value: value,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> isarIdGreaterThan(
Id value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
include: include,
property: r'isarId',
value: value,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> isarIdLessThan(
Id value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.lessThan(
include: include,
property: r'isarId',
value: value,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> isarIdBetween(
Id lower,
Id upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.between(
property: r'isarId',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> valueIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNull(
property: r'value',
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> valueIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNotNull(
property: r'value',
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> valueEqualTo(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'value',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> valueGreaterThan(
String? value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
include: include,
property: r'value',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> valueLessThan(
String? value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.lessThan(
include: include,
property: r'value',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> valueBetween(
String? lower,
String? upper, {
bool includeLower = true,
bool includeUpper = true,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.between(
property: r'value',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> valueStartsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.startsWith(
property: r'value',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> valueEndsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.endsWith(
property: r'value',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> valueContains(String value,
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.contains(
property: r'value',
value: value,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> valueMatches(String pattern,
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.matches(
property: r'value',
wildcard: pattern,
caseSensitive: caseSensitive,
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> valueIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'value',
value: '',
));
});
}
QueryBuilder<ETag, ETag, QAfterFilterCondition> valueIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
property: r'value',
value: '',
));
});
}
}
extension ETagQueryObject on QueryBuilder<ETag, ETag, QFilterCondition> {}
extension ETagQueryLinks on QueryBuilder<ETag, ETag, QFilterCondition> {}
extension ETagQuerySortBy on QueryBuilder<ETag, ETag, QSortBy> {
QueryBuilder<ETag, ETag, QAfterSortBy> sortById() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'id', Sort.asc);
});
}
QueryBuilder<ETag, ETag, QAfterSortBy> sortByIdDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'id', Sort.desc);
});
}
QueryBuilder<ETag, ETag, QAfterSortBy> sortByValue() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'value', Sort.asc);
});
}
QueryBuilder<ETag, ETag, QAfterSortBy> sortByValueDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'value', Sort.desc);
});
}
}
extension ETagQuerySortThenBy on QueryBuilder<ETag, ETag, QSortThenBy> {
QueryBuilder<ETag, ETag, QAfterSortBy> thenById() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'id', Sort.asc);
});
}
QueryBuilder<ETag, ETag, QAfterSortBy> thenByIdDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'id', Sort.desc);
});
}
QueryBuilder<ETag, ETag, QAfterSortBy> thenByIsarId() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isarId', Sort.asc);
});
}
QueryBuilder<ETag, ETag, QAfterSortBy> thenByIsarIdDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isarId', Sort.desc);
});
}
QueryBuilder<ETag, ETag, QAfterSortBy> thenByValue() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'value', Sort.asc);
});
}
QueryBuilder<ETag, ETag, QAfterSortBy> thenByValueDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'value', Sort.desc);
});
}
}
extension ETagQueryWhereDistinct on QueryBuilder<ETag, ETag, QDistinct> {
QueryBuilder<ETag, ETag, QDistinct> distinctById(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'id', caseSensitive: caseSensitive);
});
}
QueryBuilder<ETag, ETag, QDistinct> distinctByValue(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'value', caseSensitive: caseSensitive);
});
}
}
extension ETagQueryProperty on QueryBuilder<ETag, ETag, QQueryProperty> {
QueryBuilder<ETag, int, QQueryOperations> isarIdProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'isarId');
});
}
QueryBuilder<ETag, String, QQueryOperations> idProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'id');
});
}
QueryBuilder<ETag, String?, QQueryOperations> valueProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'value');
});
}
}

View File

@@ -7,7 +7,7 @@ part of 'exif_info.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetExifInfoCollection on Isar {
IsarCollection<ExifInfo> get exifInfos => this.collection();
@@ -99,7 +99,7 @@ const ExifInfoSchema = CollectionSchema(
getId: _exifInfoGetId,
getLinks: _exifInfoGetLinks,
attach: _exifInfoAttach,
version: '3.0.5',
version: '3.1.0+1',
);
int _exifInfoEstimateSize(

View File

@@ -7,7 +7,7 @@ part of 'logger_message.model.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetLoggerMessageCollection on Isar {
IsarCollection<LoggerMessage> get loggerMessages => this.collection();
@@ -55,7 +55,7 @@ const LoggerMessageSchema = CollectionSchema(
getId: _loggerMessageGetId,
getLinks: _loggerMessageGetLinks,
attach: _loggerMessageAttach,
version: '3.0.5',
version: '3.1.0+1',
);
int _loggerMessageEstimateSize(

View File

@@ -7,7 +7,7 @@ part of 'store.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetStoreValueCollection on Isar {
IsarCollection<StoreValue> get storeValues => this.collection();
@@ -39,7 +39,7 @@ const StoreValueSchema = CollectionSchema(
getId: _storeValueGetId,
getLinks: _storeValueGetLinks,
attach: _storeValueAttach,
version: '3.0.5',
version: '3.1.0+1',
);
int _storeValueEstimateSize(

View File

@@ -14,18 +14,20 @@ class User {
required this.firstName,
required this.lastName,
required this.isAdmin,
this.isPartnerSharedBy = false,
this.isPartnerSharedWith = false,
});
Id get isarId => fastHash(id);
User.fromDto(UserResponseDto dto)
: id = dto.id,
updatedAt = dto.updatedAt != null
? DateTime.parse(dto.updatedAt!).toUtc()
: DateTime.now().toUtc(),
updatedAt = dto.updatedAt,
email = dto.email,
firstName = dto.firstName,
lastName = dto.lastName,
isPartnerSharedBy = false,
isPartnerSharedWith = false,
isAdmin = dto.isAdmin;
@Index(unique: true, replace: false, type: IndexType.hash)
@@ -34,6 +36,8 @@ class User {
String email;
String firstName;
String lastName;
bool isPartnerSharedBy;
bool isPartnerSharedWith;
bool isAdmin;
@Backlink(to: 'owner')
final IsarLinks<Album> albums = IsarLinks<Album>();
@@ -44,10 +48,12 @@ class User {
bool operator ==(other) {
if (other is! User) return false;
return id == other.id &&
updatedAt == other.updatedAt &&
updatedAt.isAtSameMomentAs(other.updatedAt) &&
email == other.email &&
firstName == other.firstName &&
lastName == other.lastName &&
isPartnerSharedBy == other.isPartnerSharedBy &&
isPartnerSharedWith == other.isPartnerSharedWith &&
isAdmin == other.isAdmin;
}
@@ -59,5 +65,7 @@ class User {
email.hashCode ^
firstName.hashCode ^
lastName.hashCode ^
isPartnerSharedBy.hashCode ^
isPartnerSharedWith.hashCode ^
isAdmin.hashCode;
}

View File

@@ -7,7 +7,7 @@ part of 'user.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetUserCollection on Isar {
IsarCollection<User> get users => this.collection();
@@ -37,13 +37,23 @@ const UserSchema = CollectionSchema(
name: r'isAdmin',
type: IsarType.bool,
),
r'lastName': PropertySchema(
r'isPartnerSharedBy': PropertySchema(
id: 4,
name: r'isPartnerSharedBy',
type: IsarType.bool,
),
r'isPartnerSharedWith': PropertySchema(
id: 5,
name: r'isPartnerSharedWith',
type: IsarType.bool,
),
r'lastName': PropertySchema(
id: 6,
name: r'lastName',
type: IsarType.string,
),
r'updatedAt': PropertySchema(
id: 5,
id: 7,
name: r'updatedAt',
type: IsarType.dateTime,
)
@@ -88,7 +98,7 @@ const UserSchema = CollectionSchema(
getId: _userGetId,
getLinks: _userGetLinks,
attach: _userAttach,
version: '3.0.5',
version: '3.1.0+1',
);
int _userEstimateSize(
@@ -114,8 +124,10 @@ void _userSerialize(
writer.writeString(offsets[1], object.firstName);
writer.writeString(offsets[2], object.id);
writer.writeBool(offsets[3], object.isAdmin);
writer.writeString(offsets[4], object.lastName);
writer.writeDateTime(offsets[5], object.updatedAt);
writer.writeBool(offsets[4], object.isPartnerSharedBy);
writer.writeBool(offsets[5], object.isPartnerSharedWith);
writer.writeString(offsets[6], object.lastName);
writer.writeDateTime(offsets[7], object.updatedAt);
}
User _userDeserialize(
@@ -129,8 +141,10 @@ User _userDeserialize(
firstName: reader.readString(offsets[1]),
id: reader.readString(offsets[2]),
isAdmin: reader.readBool(offsets[3]),
lastName: reader.readString(offsets[4]),
updatedAt: reader.readDateTime(offsets[5]),
isPartnerSharedBy: reader.readBoolOrNull(offsets[4]) ?? false,
isPartnerSharedWith: reader.readBoolOrNull(offsets[5]) ?? false,
lastName: reader.readString(offsets[6]),
updatedAt: reader.readDateTime(offsets[7]),
);
return object;
}
@@ -151,8 +165,12 @@ P _userDeserializeProp<P>(
case 3:
return (reader.readBool(offset)) as P;
case 4:
return (reader.readString(offset)) as P;
return (reader.readBoolOrNull(offset) ?? false) as P;
case 5:
return (reader.readBoolOrNull(offset) ?? false) as P;
case 6:
return (reader.readString(offset)) as P;
case 7:
return (reader.readDateTime(offset)) as P;
default:
throw IsarError('Unknown property with id $propertyId');
@@ -741,6 +759,26 @@ extension UserQueryFilter on QueryBuilder<User, User, QFilterCondition> {
});
}
QueryBuilder<User, User, QAfterFilterCondition> isPartnerSharedByEqualTo(
bool value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'isPartnerSharedBy',
value: value,
));
});
}
QueryBuilder<User, User, QAfterFilterCondition> isPartnerSharedWithEqualTo(
bool value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'isPartnerSharedWith',
value: value,
));
});
}
QueryBuilder<User, User, QAfterFilterCondition> isarIdEqualTo(Id value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
@@ -1140,6 +1178,30 @@ extension UserQuerySortBy on QueryBuilder<User, User, QSortBy> {
});
}
QueryBuilder<User, User, QAfterSortBy> sortByIsPartnerSharedBy() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isPartnerSharedBy', Sort.asc);
});
}
QueryBuilder<User, User, QAfterSortBy> sortByIsPartnerSharedByDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isPartnerSharedBy', Sort.desc);
});
}
QueryBuilder<User, User, QAfterSortBy> sortByIsPartnerSharedWith() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isPartnerSharedWith', Sort.asc);
});
}
QueryBuilder<User, User, QAfterSortBy> sortByIsPartnerSharedWithDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isPartnerSharedWith', Sort.desc);
});
}
QueryBuilder<User, User, QAfterSortBy> sortByLastName() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'lastName', Sort.asc);
@@ -1214,6 +1276,30 @@ extension UserQuerySortThenBy on QueryBuilder<User, User, QSortThenBy> {
});
}
QueryBuilder<User, User, QAfterSortBy> thenByIsPartnerSharedBy() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isPartnerSharedBy', Sort.asc);
});
}
QueryBuilder<User, User, QAfterSortBy> thenByIsPartnerSharedByDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isPartnerSharedBy', Sort.desc);
});
}
QueryBuilder<User, User, QAfterSortBy> thenByIsPartnerSharedWith() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isPartnerSharedWith', Sort.asc);
});
}
QueryBuilder<User, User, QAfterSortBy> thenByIsPartnerSharedWithDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isPartnerSharedWith', Sort.desc);
});
}
QueryBuilder<User, User, QAfterSortBy> thenByIsarId() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isarId', Sort.asc);
@@ -1279,6 +1365,18 @@ extension UserQueryWhereDistinct on QueryBuilder<User, User, QDistinct> {
});
}
QueryBuilder<User, User, QDistinct> distinctByIsPartnerSharedBy() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'isPartnerSharedBy');
});
}
QueryBuilder<User, User, QDistinct> distinctByIsPartnerSharedWith() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'isPartnerSharedWith');
});
}
QueryBuilder<User, User, QDistinct> distinctByLastName(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
@@ -1324,6 +1422,18 @@ extension UserQueryProperty on QueryBuilder<User, User, QQueryProperty> {
});
}
QueryBuilder<User, bool, QQueryOperations> isPartnerSharedByProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'isPartnerSharedBy');
});
}
QueryBuilder<User, bool, QQueryOperations> isPartnerSharedWithProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'isPartnerSharedWith');
});
}
QueryBuilder<User, String, QQueryOperations> lastNameProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'lastName');

View File

@@ -3,6 +3,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/album/services/album.service.dart';
import 'package:immich_mobile/shared/models/exif_info.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/providers/db.provider.dart';
import 'package:immich_mobile/shared/services/asset.service.dart';
import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart';
@@ -10,6 +11,7 @@ import 'package:immich_mobile/modules/settings/providers/app_settings.provider.d
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/services/sync.service.dart';
import 'package:immich_mobile/shared/services/user.service.dart';
import 'package:immich_mobile/utils/db.dart';
import 'package:isar/isar.dart';
import 'package:logging/logging.dart';
@@ -23,6 +25,7 @@ class AssetsState {}
class AssetNotifier extends StateNotifier<AssetsState> {
final AssetService _assetService;
final AlbumService _albumService;
final UserService _userService;
final SyncService _syncService;
final Isar _db;
final log = Logger('AssetNotifier');
@@ -32,6 +35,7 @@ class AssetNotifier extends StateNotifier<AssetsState> {
AssetNotifier(
this._assetService,
this._albumService,
this._userService,
this._syncService,
this._db,
) : super(AssetsState());
@@ -51,6 +55,12 @@ class AssetNotifier extends StateNotifier<AssetsState> {
final bool newRemote = await _assetService.refreshRemoteAssets();
final bool newLocal = await _albumService.refreshDeviceAlbums();
debugPrint("newRemote: $newRemote, newLocal: $newLocal");
await _userService.refreshUsers();
final List<User> partners =
await _db.users.filter().isPartnerSharedWithEqualTo(true).findAll();
for (User u in partners) {
await _assetService.refreshRemoteAssets(u);
}
log.info("Load assets: ${stopwatch.elapsedMilliseconds}ms");
} finally {
_getAllAssetInProgress = false;
@@ -147,6 +157,7 @@ final assetProvider = StateNotifierProvider<AssetNotifier, AssetsState>((ref) {
return AssetNotifier(
ref.watch(assetServiceProvider),
ref.watch(albumServiceProvider),
ref.watch(userServiceProvider),
ref.watch(syncServiceProvider),
ref.watch(dbProvider),
);
@@ -161,12 +172,14 @@ final assetDetailProvider =
}
});
final assetsProvider = StreamProvider.autoDispose<RenderList>((ref) async* {
final assetsProvider =
StreamProvider.family<RenderList, int?>((ref, userId) async* {
if (userId == null) return;
final query = ref
.watch(dbProvider)
.assets
.filter()
.ownerIdEqualTo(Store.get(StoreKey.currentUser).isarId)
.ownerIdEqualTo(userId)
.isArchivedEqualTo(false)
.sortByFileCreatedAtDesc();
final settings = ref.watch(appSettingsServiceProvider);
@@ -179,14 +192,15 @@ final assetsProvider = StreamProvider.autoDispose<RenderList>((ref) async* {
});
final remoteAssetsProvider =
StreamProvider.autoDispose<RenderList>((ref) async* {
StreamProvider.family<RenderList, int?>((ref, userId) async* {
if (userId == null) return;
final query = ref
.watch(dbProvider)
.assets
.where()
.remoteIdIsNotNull()
.filter()
.ownerIdEqualTo(Store.get(StoreKey.currentUser).isarId)
.ownerIdEqualTo(userId)
.sortByFileCreatedAt();
final settings = ref.watch(appSettingsServiceProvider);
final groupBy =

View File

@@ -0,0 +1,26 @@
import 'dart:async';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/models/user.dart';
class CurrentUserProvider extends StateNotifier<User?> {
CurrentUserProvider() : super(null) {
state = Store.tryGet(StoreKey.currentUser);
streamSub =
Store.watch(StoreKey.currentUser).listen((user) => state = user);
}
late final StreamSubscription<User?> streamSub;
@override
void dispose() {
streamSub.cancel();
super.dispose();
}
}
final currentUserProvider =
StateNotifierProvider<CurrentUserProvider, User?>((ref) {
return CurrentUserProvider();
});

View File

@@ -16,6 +16,7 @@ class ApiService {
late AssetApi assetApi;
late SearchApi searchApi;
late ServerInfoApi serverInfoApi;
late PartnerApi partnerApi;
ApiService() {
final endpoint = Store.tryGet(StoreKey.serverEndpoint);
@@ -37,6 +38,7 @@ class ApiService {
assetApi = AssetApi(_apiClient);
serverInfoApi = ServerInfoApi(_apiClient);
searchApi = SearchApi(_apiClient);
partnerApi = PartnerApi(_apiClient);
}
Future<String> resolveAndSetEndpoint(String serverUrl) async {

View File

@@ -3,8 +3,10 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/models/etag.dart';
import 'package:immich_mobile/shared/models/exif_info.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/providers/api.provider.dart';
import 'package:immich_mobile/shared/providers/db.provider.dart';
import 'package:immich_mobile/shared/services/api.service.dart';
@@ -36,37 +38,47 @@ class AssetService {
/// Checks the server for updated assets and updates the local database if
/// required. Returns `true` if there were any changes.
Future<bool> refreshRemoteAssets() async {
Future<bool> refreshRemoteAssets([User? user]) async {
user ??= Store.get(StoreKey.currentUser);
final Stopwatch sw = Stopwatch()..start();
final int numOwnedRemoteAssets = await _db.assets
.where()
.remoteIdIsNotNull()
.filter()
.ownerIdEqualTo(Store.get(StoreKey.currentUser).isarId)
.ownerIdEqualTo(user!.isarId)
.count();
final bool changes = await _syncService.syncRemoteAssetsToDb(
() async => (await _getRemoteAssets(hasCache: numOwnedRemoteAssets > 0))
?.map(Asset.remote)
.toList(),
user,
() async => (await _getRemoteAssets(
hasCache: numOwnedRemoteAssets > 0,
user: user!,
)),
);
debugPrint("refreshRemoteAssets full took ${sw.elapsedMilliseconds}ms");
return changes;
}
/// Returns `null` if the server state did not change, else list of assets
Future<List<AssetResponseDto>?> _getRemoteAssets({
Future<List<Asset>?> _getRemoteAssets({
required bool hasCache,
required User user,
}) async {
try {
final etag = hasCache ? Store.tryGet(StoreKey.assetETag) : null;
final etag = hasCache ? _db.eTags.getByIdSync(user.id)?.value : null;
final (List<AssetResponseDto>? assets, String? newETag) =
await _apiService.assetApi.getAllAssetsWithETag(eTag: etag);
await _apiService.assetApi
.getAllAssetsWithETag(eTag: etag, userId: user.id);
if (assets == null) {
return null;
} else if (assets.isNotEmpty && assets.first.ownerId != user.id) {
log.warning("Make sure that server and app versions match!"
" The server returned assets for user ${assets.first.ownerId}"
" while requesting assets of user ${user.id}");
return null;
} else if (newETag != etag) {
Store.put(StoreKey.assetETag, newETag);
_db.writeTxn(() => _db.eTags.put(ETag(id: user.id, value: newETag)));
}
return assets;
return assets.map(Asset.remote).toList();
} catch (e, stack) {
log.severe('Error while getting remote assets', e, stack);
return null;

View File

@@ -40,7 +40,9 @@ class SyncService {
dbUsers,
compare: (User a, User b) => a.id.compareTo(b.id),
both: (User a, User b) {
if (!a.updatedAt.isAtSameMomentAs(b.updatedAt)) {
if (!a.updatedAt.isAtSameMomentAs(b.updatedAt) ||
a.isPartnerSharedBy != b.isPartnerSharedBy ||
a.isPartnerSharedWith != b.isPartnerSharedWith) {
toUpsert.add(a);
return true;
}
@@ -61,9 +63,10 @@ class SyncService {
/// Syncs remote assets owned by the logged-in user to the DB
/// Returns `true` if there were any changes
Future<bool> syncRemoteAssetsToDb(
User user,
FutureOr<List<Asset>?> Function() loadAssets,
) =>
_lock.run(() => _syncRemoteAssetsToDb(loadAssets));
_lock.run(() => _syncRemoteAssetsToDb(user, loadAssets));
/// Syncs remote albums to the database
/// returns `true` if there were any changes
@@ -149,13 +152,13 @@ class SyncService {
/// Syncs remote assets to the databas
/// returns `true` if there were any changes
Future<bool> _syncRemoteAssetsToDb(
User user,
FutureOr<List<Asset>?> Function() loadAssets,
) async {
final List<Asset>? remote = await loadAssets();
if (remote == null) {
return false;
}
final User user = Store.get(StoreKey.currentUser);
final List<Asset> inDb = await _db.assets
.filter()
.ownerIdEqualTo(user.isarId)
@@ -276,7 +279,7 @@ class SyncService {
album.name = dto.albumName;
album.shared = dto.shared;
album.modifiedAt = DateTime.parse(dto.updatedAt);
album.modifiedAt = dto.updatedAt;
if (album.thumbnail.value?.remoteId != dto.albumThumbnailAssetId) {
album.thumbnail.value = await _db.assets
.where()
@@ -349,10 +352,19 @@ class SyncService {
);
} else if (album.shared) {
final User user = Store.get(StoreKey.currentUser);
// delete assets in DB unless they belong to this user or are part of some other shared album
deleteCandidates.addAll(
await album.assets.filter().not().ownerIdEqualTo(user.isarId).findAll(),
);
// delete assets in DB unless they belong to this user or are part of some other shared album or belong to a partner
final userIds = await _db.users
.filter()
.isPartnerSharedWithEqualTo(true)
.isarIdProperty()
.findAll();
userIds.add(user.isarId);
final orphanedAssets = await album.assets
.filter()
.not()
.anyOf(userIds, (q, int id) => q.ownerIdEqualTo(id))
.findAll();
deleteCandidates.addAll(orphanedAssets);
}
try {
final bool ok = await _db.writeTxn(() => _db.albums.delete(album.id));
@@ -701,5 +713,5 @@ bool _hasAlbumResponseDtoChanged(AlbumResponseDto dto, Album a) {
dto.albumThumbnailAssetId != a.thumbnail.value?.remoteId ||
dto.shared != a.shared ||
dto.sharedUsers.length != a.sharedUsers.length ||
!DateTime.parse(dto.updatedAt).isAtSameMomentAs(a.modifiedAt);
!dto.updatedAt.isAtSameMomentAs(a.modifiedAt);
}

View File

@@ -1,16 +1,19 @@
import 'package:flutter/material.dart';
import 'package:collection/collection.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:http/http.dart';
import 'package:http_parser/http_parser.dart';
import 'package:image_picker/image_picker.dart';
import 'package:immich_mobile/modules/partner/services/partner.service.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/providers/api.provider.dart';
import 'package:immich_mobile/shared/providers/db.provider.dart';
import 'package:immich_mobile/shared/services/api.service.dart';
import 'package:immich_mobile/shared/services/sync.service.dart';
import 'package:immich_mobile/utils/diff.dart';
import 'package:immich_mobile/utils/files_helper.dart';
import 'package:isar/isar.dart';
import 'package:logging/logging.dart';
import 'package:openapi/api.dart';
final userServiceProvider = Provider(
@@ -18,6 +21,7 @@ final userServiceProvider = Provider(
ref.watch(apiServiceProvider),
ref.watch(dbProvider),
ref.watch(syncServiceProvider),
ref.watch(partnerServiceProvider),
),
);
@@ -25,15 +29,22 @@ class UserService {
final ApiService _apiService;
final Isar _db;
final SyncService _syncService;
final PartnerService _partnerService;
final Logger _log = Logger("UserService");
UserService(this._apiService, this._db, this._syncService);
UserService(
this._apiService,
this._db,
this._syncService,
this._partnerService,
);
Future<List<User>?> _getAllUsers({required bool isAll}) async {
try {
final dto = await _apiService.userApi.getAllUsers(isAll);
return dto?.map(User.fromDto).toList();
} catch (e) {
debugPrint("Error [getAllUsersInfo] ${e.toString()}");
_log.warning("Failed get all users:\n$e");
return null;
}
}
@@ -62,16 +73,45 @@ class UserService {
),
);
} catch (e) {
debugPrint("Error [uploadProfileImage] ${e.toString()}");
_log.warning("Failed to upload profile image:\n$e");
return null;
}
}
Future<bool> refreshUsers() async {
final List<User>? users = await _getAllUsers(isAll: true);
if (users == null) {
final List<User>? sharedBy =
await _partnerService.getPartners(PartnerDirection.sharedBy);
final List<User>? sharedWith =
await _partnerService.getPartners(PartnerDirection.sharedWith);
if (users == null || sharedBy == null || sharedWith == null) {
_log.warning("Failed to refresh users");
return false;
}
users.sortBy((u) => u.id);
sharedBy.sortBy((u) => u.id);
sharedWith.sortBy((u) => u.id);
diffSortedListsSync(
users,
sharedBy,
compare: (User a, User b) => a.id.compareTo(b.id),
both: (User a, User b) => a.isPartnerSharedBy = true,
onlyFirst: (_) {},
onlySecond: (_) {},
);
diffSortedListsSync(
users,
sharedWith,
compare: (User a, User b) => a.id.compareTo(b.id),
both: (User a, User b) => a.isPartnerSharedWith = true,
onlyFirst: (_) {},
onlySecond: (_) {},
);
return _syncService.syncUsersFromServer(users);
}
}

View File

@@ -0,0 +1,54 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
class ConfirmDialog extends ConsumerWidget {
final Function onOk;
final String title;
final String content;
final String cancel;
final String ok;
const ConfirmDialog({
Key? key,
required this.onOk,
required this.title,
required this.content,
this.cancel = "delete_dialog_cancel",
this.ok = "backup_controller_page_background_battery_info_ok",
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
title: Text(title).tr(),
content: Text(content).tr(),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(
cancel,
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
),
).tr(),
),
TextButton(
onPressed: () {
onOk();
Navigator.of(context).pop();
},
child: Text(
ok,
style: TextStyle(
color: Colors.red[400],
fontWeight: FontWeight.bold,
),
).tr(),
),
],
);
}
}

View File

@@ -0,0 +1,21 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/models/user.dart';
Widget userAvatar(BuildContext context, User u, {double? radius}) {
final url =
"${Store.get(StoreKey.serverEndpoint)}/user/profile-image/${u.id}";
return CircleAvatar(
radius: radius,
backgroundColor: Theme.of(context).primaryColor.withAlpha(50),
foregroundImage: CachedNetworkImageProvider(
url,
headers: {"Authorization": "Bearer ${Store.get(StoreKey.accessToken)}"},
cacheKey: "user-${u.id}-profile",
),
// silence errors if user has no profile image, use initials as fallback
onForegroundImageError: (exception, stackTrace) {},
child: Text((u.firstName[0] + u.lastName[0]).toUpperCase()),
);
}

View File

@@ -1,7 +1,9 @@
import 'package:immich_mobile/shared/models/album.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/models/etag.dart';
import 'package:immich_mobile/shared/models/exif_info.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:isar/isar.dart';
Future<void> clearAssetsAndAlbums(Isar db) async {
@@ -10,5 +12,7 @@ Future<void> clearAssetsAndAlbums(Isar db) async {
await db.assets.clear();
await db.exifInfos.clear();
await db.albums.clear();
await db.eTags.clear();
await db.users.clear();
});
}

View File

@@ -14,9 +14,11 @@ extension WithETag on AssetApi {
/// ETag of data already cached on the client
Future<(List<AssetResponseDto>? assets, String? eTag)> getAllAssetsWithETag({
String? eTag,
String? userId,
}) async {
final response = await getAllAssetsWithHttpInfo(
ifNoneMatch: eTag,
userId: userId,
);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));

View File

@@ -17,10 +17,16 @@ doc/AlbumCountResponseDto.md
doc/AlbumResponseDto.md
doc/AllJobStatusResponseDto.md
doc/AssetApi.md
doc/AssetBulkUploadCheckDto.md
doc/AssetBulkUploadCheckItem.md
doc/AssetBulkUploadCheckResponseDto.md
doc/AssetBulkUploadCheckResult.md
doc/AssetCountByTimeBucket.md
doc/AssetCountByTimeBucketResponseDto.md
doc/AssetCountByUserIdResponseDto.md
doc/AssetFileUploadResponseDto.md
doc/AssetIdsDto.md
doc/AssetIdsResponseDto.md
doc/AssetResponseDto.md
doc/AssetTypeEnum.md
doc/AuthDeviceResponseDto.md
@@ -51,6 +57,7 @@ doc/JobCommand.md
doc/JobCommandDto.md
doc/JobCountsDto.md
doc/JobName.md
doc/JobSettingsDto.md
doc/JobStatusDto.md
doc/LoginCredentialDto.md
doc/LoginResponseDto.md
@@ -89,6 +96,7 @@ doc/SmartInfoResponseDto.md
doc/SystemConfigApi.md
doc/SystemConfigDto.md
doc/SystemConfigFFmpegDto.md
doc/SystemConfigJobDto.md
doc/SystemConfigOAuthDto.md
doc/SystemConfigPasswordLoginDto.md
doc/SystemConfigStorageTemplateDto.md
@@ -142,10 +150,16 @@ lib/model/api_key_create_dto.dart
lib/model/api_key_create_response_dto.dart
lib/model/api_key_response_dto.dart
lib/model/api_key_update_dto.dart
lib/model/asset_bulk_upload_check_dto.dart
lib/model/asset_bulk_upload_check_item.dart
lib/model/asset_bulk_upload_check_response_dto.dart
lib/model/asset_bulk_upload_check_result.dart
lib/model/asset_count_by_time_bucket.dart
lib/model/asset_count_by_time_bucket_response_dto.dart
lib/model/asset_count_by_user_id_response_dto.dart
lib/model/asset_file_upload_response_dto.dart
lib/model/asset_ids_dto.dart
lib/model/asset_ids_response_dto.dart
lib/model/asset_response_dto.dart
lib/model/asset_type_enum.dart
lib/model/auth_device_response_dto.dart
@@ -174,6 +188,7 @@ lib/model/job_command.dart
lib/model/job_command_dto.dart
lib/model/job_counts_dto.dart
lib/model/job_name.dart
lib/model/job_settings_dto.dart
lib/model/job_status_dto.dart
lib/model/login_credential_dto.dart
lib/model/login_response_dto.dart
@@ -205,6 +220,7 @@ lib/model/sign_up_dto.dart
lib/model/smart_info_response_dto.dart
lib/model/system_config_dto.dart
lib/model/system_config_f_fmpeg_dto.dart
lib/model/system_config_job_dto.dart
lib/model/system_config_o_auth_dto.dart
lib/model/system_config_password_login_dto.dart
lib/model/system_config_storage_template_dto.dart
@@ -236,10 +252,16 @@ test/api_key_create_response_dto_test.dart
test/api_key_response_dto_test.dart
test/api_key_update_dto_test.dart
test/asset_api_test.dart
test/asset_bulk_upload_check_dto_test.dart
test/asset_bulk_upload_check_item_test.dart
test/asset_bulk_upload_check_response_dto_test.dart
test/asset_bulk_upload_check_result_test.dart
test/asset_count_by_time_bucket_response_dto_test.dart
test/asset_count_by_time_bucket_test.dart
test/asset_count_by_user_id_response_dto_test.dart
test/asset_file_upload_response_dto_test.dart
test/asset_ids_dto_test.dart
test/asset_ids_response_dto_test.dart
test/asset_response_dto_test.dart
test/asset_type_enum_test.dart
test/auth_device_response_dto_test.dart
@@ -270,6 +292,7 @@ test/job_command_dto_test.dart
test/job_command_test.dart
test/job_counts_dto_test.dart
test/job_name_test.dart
test/job_settings_dto_test.dart
test/job_status_dto_test.dart
test/login_credential_dto_test.dart
test/login_response_dto_test.dart
@@ -308,6 +331,7 @@ test/smart_info_response_dto_test.dart
test/system_config_api_test.dart
test/system_config_dto_test.dart
test/system_config_f_fmpeg_dto_test.dart
test/system_config_job_dto_test.dart
test/system_config_o_auth_dto_test.dart
test/system_config_password_login_dto_test.dart
test/system_config_storage_template_dto_test.dart

View File

@@ -3,7 +3,7 @@ Immich API
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 1.57.0
- API version: 1.60.0
- Build package: org.openapitools.codegen.languages.DartClientCodegen
## Requirements
@@ -77,42 +77,43 @@ Class | Method | HTTP request | Description
*APIKeyApi* | [**getKey**](doc//APIKeyApi.md#getkey) | **GET** /api-key/{id} |
*APIKeyApi* | [**getKeys**](doc//APIKeyApi.md#getkeys) | **GET** /api-key |
*APIKeyApi* | [**updateKey**](doc//APIKeyApi.md#updatekey) | **PUT** /api-key/{id} |
*AlbumApi* | [**addAssetsToAlbum**](doc//AlbumApi.md#addassetstoalbum) | **PUT** /album/{albumId}/assets |
*AlbumApi* | [**addUsersToAlbum**](doc//AlbumApi.md#adduserstoalbum) | **PUT** /album/{albumId}/users |
*AlbumApi* | [**addAssetsToAlbum**](doc//AlbumApi.md#addassetstoalbum) | **PUT** /album/{id}/assets |
*AlbumApi* | [**addUsersToAlbum**](doc//AlbumApi.md#adduserstoalbum) | **PUT** /album/{id}/users |
*AlbumApi* | [**createAlbum**](doc//AlbumApi.md#createalbum) | **POST** /album |
*AlbumApi* | [**createAlbumSharedLink**](doc//AlbumApi.md#createalbumsharedlink) | **POST** /album/create-shared-link |
*AlbumApi* | [**deleteAlbum**](doc//AlbumApi.md#deletealbum) | **DELETE** /album/{albumId} |
*AlbumApi* | [**downloadArchive**](doc//AlbumApi.md#downloadarchive) | **GET** /album/{albumId}/download |
*AlbumApi* | [**deleteAlbum**](doc//AlbumApi.md#deletealbum) | **DELETE** /album/{id} |
*AlbumApi* | [**downloadArchive**](doc//AlbumApi.md#downloadarchive) | **GET** /album/{id}/download |
*AlbumApi* | [**getAlbumCountByUserId**](doc//AlbumApi.md#getalbumcountbyuserid) | **GET** /album/count-by-user-id |
*AlbumApi* | [**getAlbumInfo**](doc//AlbumApi.md#getalbuminfo) | **GET** /album/{albumId} |
*AlbumApi* | [**getAlbumInfo**](doc//AlbumApi.md#getalbuminfo) | **GET** /album/{id} |
*AlbumApi* | [**getAllAlbums**](doc//AlbumApi.md#getallalbums) | **GET** /album |
*AlbumApi* | [**removeAssetFromAlbum**](doc//AlbumApi.md#removeassetfromalbum) | **DELETE** /album/{albumId}/assets |
*AlbumApi* | [**removeUserFromAlbum**](doc//AlbumApi.md#removeuserfromalbum) | **DELETE** /album/{albumId}/user/{userId} |
*AlbumApi* | [**updateAlbumInfo**](doc//AlbumApi.md#updatealbuminfo) | **PATCH** /album/{albumId} |
*AlbumApi* | [**removeAssetFromAlbum**](doc//AlbumApi.md#removeassetfromalbum) | **DELETE** /album/{id}/assets |
*AlbumApi* | [**removeUserFromAlbum**](doc//AlbumApi.md#removeuserfromalbum) | **DELETE** /album/{id}/user/{userId} |
*AlbumApi* | [**updateAlbumInfo**](doc//AlbumApi.md#updatealbuminfo) | **PATCH** /album/{id} |
*AssetApi* | [**addAssetsToSharedLink**](doc//AssetApi.md#addassetstosharedlink) | **PATCH** /asset/shared-link/add |
*AssetApi* | [**bulkUploadCheck**](doc//AssetApi.md#bulkuploadcheck) | **POST** /asset/bulk-upload-check |
*AssetApi* | [**checkDuplicateAsset**](doc//AssetApi.md#checkduplicateasset) | **POST** /asset/check |
*AssetApi* | [**checkExistingAssets**](doc//AssetApi.md#checkexistingassets) | **POST** /asset/exist |
*AssetApi* | [**createAssetsSharedLink**](doc//AssetApi.md#createassetssharedlink) | **POST** /asset/shared-link |
*AssetApi* | [**deleteAsset**](doc//AssetApi.md#deleteasset) | **DELETE** /asset |
*AssetApi* | [**downloadFile**](doc//AssetApi.md#downloadfile) | **GET** /asset/download/{assetId} |
*AssetApi* | [**downloadFile**](doc//AssetApi.md#downloadfile) | **GET** /asset/download/{id} |
*AssetApi* | [**downloadFiles**](doc//AssetApi.md#downloadfiles) | **POST** /asset/download-files |
*AssetApi* | [**downloadLibrary**](doc//AssetApi.md#downloadlibrary) | **GET** /asset/download-library |
*AssetApi* | [**getAllAssets**](doc//AssetApi.md#getallassets) | **GET** /asset |
*AssetApi* | [**getArchivedAssetCountByUserId**](doc//AssetApi.md#getarchivedassetcountbyuserid) | **GET** /asset/stat/archive |
*AssetApi* | [**getAssetById**](doc//AssetApi.md#getassetbyid) | **GET** /asset/assetById/{assetId} |
*AssetApi* | [**getAssetById**](doc//AssetApi.md#getassetbyid) | **GET** /asset/assetById/{id} |
*AssetApi* | [**getAssetByTimeBucket**](doc//AssetApi.md#getassetbytimebucket) | **POST** /asset/time-bucket |
*AssetApi* | [**getAssetCountByTimeBucket**](doc//AssetApi.md#getassetcountbytimebucket) | **POST** /asset/count-by-time-bucket |
*AssetApi* | [**getAssetCountByUserId**](doc//AssetApi.md#getassetcountbyuserid) | **GET** /asset/count-by-user-id |
*AssetApi* | [**getAssetSearchTerms**](doc//AssetApi.md#getassetsearchterms) | **GET** /asset/search-terms |
*AssetApi* | [**getAssetThumbnail**](doc//AssetApi.md#getassetthumbnail) | **GET** /asset/thumbnail/{assetId} |
*AssetApi* | [**getAssetThumbnail**](doc//AssetApi.md#getassetthumbnail) | **GET** /asset/thumbnail/{id} |
*AssetApi* | [**getCuratedLocations**](doc//AssetApi.md#getcuratedlocations) | **GET** /asset/curated-locations |
*AssetApi* | [**getCuratedObjects**](doc//AssetApi.md#getcuratedobjects) | **GET** /asset/curated-objects |
*AssetApi* | [**getMapMarkers**](doc//AssetApi.md#getmapmarkers) | **GET** /asset/map-marker |
*AssetApi* | [**getUserAssetsByDeviceId**](doc//AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} |
*AssetApi* | [**removeAssetsFromSharedLink**](doc//AssetApi.md#removeassetsfromsharedlink) | **PATCH** /asset/shared-link/remove |
*AssetApi* | [**searchAsset**](doc//AssetApi.md#searchasset) | **POST** /asset/search |
*AssetApi* | [**serveFile**](doc//AssetApi.md#servefile) | **GET** /asset/file/{assetId} |
*AssetApi* | [**updateAsset**](doc//AssetApi.md#updateasset) | **PUT** /asset/{assetId} |
*AssetApi* | [**serveFile**](doc//AssetApi.md#servefile) | **GET** /asset/file/{id} |
*AssetApi* | [**updateAsset**](doc//AssetApi.md#updateasset) | **PUT** /asset/{id} |
*AssetApi* | [**uploadFile**](doc//AssetApi.md#uploadfile) | **POST** /asset/upload |
*AuthenticationApi* | [**adminSignUp**](doc//AuthenticationApi.md#adminsignup) | **POST** /auth/admin-sign-up |
*AuthenticationApi* | [**changePassword**](doc//AuthenticationApi.md#changepassword) | **POST** /auth/change-password |
@@ -144,20 +145,23 @@ Class | Method | HTTP request | Description
*ServerInfoApi* | [**getServerVersion**](doc//ServerInfoApi.md#getserverversion) | **GET** /server-info/version |
*ServerInfoApi* | [**getStats**](doc//ServerInfoApi.md#getstats) | **GET** /server-info/stats |
*ServerInfoApi* | [**pingServer**](doc//ServerInfoApi.md#pingserver) | **GET** /server-info/ping |
*ShareApi* | [**editSharedLink**](doc//ShareApi.md#editsharedlink) | **PATCH** /share/{id} |
*ShareApi* | [**getAllSharedLinks**](doc//ShareApi.md#getallsharedlinks) | **GET** /share |
*ShareApi* | [**getMySharedLink**](doc//ShareApi.md#getmysharedlink) | **GET** /share/me |
*ShareApi* | [**getSharedLinkById**](doc//ShareApi.md#getsharedlinkbyid) | **GET** /share/{id} |
*ShareApi* | [**removeSharedLink**](doc//ShareApi.md#removesharedlink) | **DELETE** /share/{id} |
*ShareApi* | [**updateSharedLink**](doc//ShareApi.md#updatesharedlink) | **PATCH** /share/{id} |
*SystemConfigApi* | [**getConfig**](doc//SystemConfigApi.md#getconfig) | **GET** /system-config |
*SystemConfigApi* | [**getDefaults**](doc//SystemConfigApi.md#getdefaults) | **GET** /system-config/defaults |
*SystemConfigApi* | [**getStorageTemplateOptions**](doc//SystemConfigApi.md#getstoragetemplateoptions) | **GET** /system-config/storage-template-options |
*SystemConfigApi* | [**updateConfig**](doc//SystemConfigApi.md#updateconfig) | **PUT** /system-config |
*TagApi* | [**create**](doc//TagApi.md#create) | **POST** /tag |
*TagApi* | [**delete**](doc//TagApi.md#delete) | **DELETE** /tag/{id} |
*TagApi* | [**findAll**](doc//TagApi.md#findall) | **GET** /tag |
*TagApi* | [**findOne**](doc//TagApi.md#findone) | **GET** /tag/{id} |
*TagApi* | [**update**](doc//TagApi.md#update) | **PATCH** /tag/{id} |
*TagApi* | [**createTag**](doc//TagApi.md#createtag) | **POST** /tag |
*TagApi* | [**deleteTag**](doc//TagApi.md#deletetag) | **DELETE** /tag/{id} |
*TagApi* | [**getAllTags**](doc//TagApi.md#getalltags) | **GET** /tag |
*TagApi* | [**getTagAssets**](doc//TagApi.md#gettagassets) | **GET** /tag/{id}/assets |
*TagApi* | [**getTagById**](doc//TagApi.md#gettagbyid) | **GET** /tag/{id} |
*TagApi* | [**tagAssets**](doc//TagApi.md#tagassets) | **PUT** /tag/{id}/assets |
*TagApi* | [**untagAssets**](doc//TagApi.md#untagassets) | **DELETE** /tag/{id}/assets |
*TagApi* | [**updateTag**](doc//TagApi.md#updatetag) | **PATCH** /tag/{id} |
*UserApi* | [**createProfileImage**](doc//UserApi.md#createprofileimage) | **POST** /user/profile-image |
*UserApi* | [**createUser**](doc//UserApi.md#createuser) | **POST** /user |
*UserApi* | [**deleteUser**](doc//UserApi.md#deleteuser) | **DELETE** /user/{userId} |
@@ -183,10 +187,16 @@ Class | Method | HTTP request | Description
- [AlbumCountResponseDto](doc//AlbumCountResponseDto.md)
- [AlbumResponseDto](doc//AlbumResponseDto.md)
- [AllJobStatusResponseDto](doc//AllJobStatusResponseDto.md)
- [AssetBulkUploadCheckDto](doc//AssetBulkUploadCheckDto.md)
- [AssetBulkUploadCheckItem](doc//AssetBulkUploadCheckItem.md)
- [AssetBulkUploadCheckResponseDto](doc//AssetBulkUploadCheckResponseDto.md)
- [AssetBulkUploadCheckResult](doc//AssetBulkUploadCheckResult.md)
- [AssetCountByTimeBucket](doc//AssetCountByTimeBucket.md)
- [AssetCountByTimeBucketResponseDto](doc//AssetCountByTimeBucketResponseDto.md)
- [AssetCountByUserIdResponseDto](doc//AssetCountByUserIdResponseDto.md)
- [AssetFileUploadResponseDto](doc//AssetFileUploadResponseDto.md)
- [AssetIdsDto](doc//AssetIdsDto.md)
- [AssetIdsResponseDto](doc//AssetIdsResponseDto.md)
- [AssetResponseDto](doc//AssetResponseDto.md)
- [AssetTypeEnum](doc//AssetTypeEnum.md)
- [AuthDeviceResponseDto](doc//AuthDeviceResponseDto.md)
@@ -215,6 +225,7 @@ Class | Method | HTTP request | Description
- [JobCommandDto](doc//JobCommandDto.md)
- [JobCountsDto](doc//JobCountsDto.md)
- [JobName](doc//JobName.md)
- [JobSettingsDto](doc//JobSettingsDto.md)
- [JobStatusDto](doc//JobStatusDto.md)
- [LoginCredentialDto](doc//LoginCredentialDto.md)
- [LoginResponseDto](doc//LoginResponseDto.md)
@@ -246,6 +257,7 @@ Class | Method | HTTP request | Description
- [SmartInfoResponseDto](doc//SmartInfoResponseDto.md)
- [SystemConfigDto](doc//SystemConfigDto.md)
- [SystemConfigFFmpegDto](doc//SystemConfigFFmpegDto.md)
- [SystemConfigJobDto](doc//SystemConfigJobDto.md)
- [SystemConfigOAuthDto](doc//SystemConfigOAuthDto.md)
- [SystemConfigPasswordLoginDto](doc//SystemConfigPasswordLoginDto.md)
- [SystemConfigStorageTemplateDto](doc//SystemConfigStorageTemplateDto.md)

View File

@@ -10,8 +10,8 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**id** | **String** | |
**name** | **String** | |
**createdAt** | **String** | |
**updatedAt** | **String** | |
**createdAt** | [**DateTime**](DateTime.md) | |
**updatedAt** | [**DateTime**](DateTime.md) | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -12,7 +12,7 @@ Name | Type | Description | Notes
**email** | **String** | |
**firstName** | **String** | |
**lastName** | **String** | |
**createdAt** | **String** | |
**createdAt** | [**DateTime**](DateTime.md) | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -9,22 +9,22 @@ All URIs are relative to */api*
Method | HTTP request | Description
------------- | ------------- | -------------
[**addAssetsToAlbum**](AlbumApi.md#addassetstoalbum) | **PUT** /album/{albumId}/assets |
[**addUsersToAlbum**](AlbumApi.md#adduserstoalbum) | **PUT** /album/{albumId}/users |
[**addAssetsToAlbum**](AlbumApi.md#addassetstoalbum) | **PUT** /album/{id}/assets |
[**addUsersToAlbum**](AlbumApi.md#adduserstoalbum) | **PUT** /album/{id}/users |
[**createAlbum**](AlbumApi.md#createalbum) | **POST** /album |
[**createAlbumSharedLink**](AlbumApi.md#createalbumsharedlink) | **POST** /album/create-shared-link |
[**deleteAlbum**](AlbumApi.md#deletealbum) | **DELETE** /album/{albumId} |
[**downloadArchive**](AlbumApi.md#downloadarchive) | **GET** /album/{albumId}/download |
[**deleteAlbum**](AlbumApi.md#deletealbum) | **DELETE** /album/{id} |
[**downloadArchive**](AlbumApi.md#downloadarchive) | **GET** /album/{id}/download |
[**getAlbumCountByUserId**](AlbumApi.md#getalbumcountbyuserid) | **GET** /album/count-by-user-id |
[**getAlbumInfo**](AlbumApi.md#getalbuminfo) | **GET** /album/{albumId} |
[**getAlbumInfo**](AlbumApi.md#getalbuminfo) | **GET** /album/{id} |
[**getAllAlbums**](AlbumApi.md#getallalbums) | **GET** /album |
[**removeAssetFromAlbum**](AlbumApi.md#removeassetfromalbum) | **DELETE** /album/{albumId}/assets |
[**removeUserFromAlbum**](AlbumApi.md#removeuserfromalbum) | **DELETE** /album/{albumId}/user/{userId} |
[**updateAlbumInfo**](AlbumApi.md#updatealbuminfo) | **PATCH** /album/{albumId} |
[**removeAssetFromAlbum**](AlbumApi.md#removeassetfromalbum) | **DELETE** /album/{id}/assets |
[**removeUserFromAlbum**](AlbumApi.md#removeuserfromalbum) | **DELETE** /album/{id}/user/{userId} |
[**updateAlbumInfo**](AlbumApi.md#updatealbuminfo) | **PATCH** /album/{id} |
# **addAssetsToAlbum**
> AddAssetsResponseDto addAssetsToAlbum(albumId, addAssetsDto, key)
> AddAssetsResponseDto addAssetsToAlbum(id, addAssetsDto, key)
@@ -47,12 +47,12 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AlbumApi();
final albumId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final addAssetsDto = AddAssetsDto(); // AddAssetsDto |
final key = key_example; // String |
try {
final result = api_instance.addAssetsToAlbum(albumId, addAssetsDto, key);
final result = api_instance.addAssetsToAlbum(id, addAssetsDto, key);
print(result);
} catch (e) {
print('Exception when calling AlbumApi->addAssetsToAlbum: $e\n');
@@ -63,7 +63,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**albumId** | **String**| |
**id** | **String**| |
**addAssetsDto** | [**AddAssetsDto**](AddAssetsDto.md)| |
**key** | **String**| | [optional]
@@ -83,7 +83,7 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **addUsersToAlbum**
> AlbumResponseDto addUsersToAlbum(albumId, addUsersDto)
> AlbumResponseDto addUsersToAlbum(id, addUsersDto)
@@ -106,11 +106,11 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AlbumApi();
final albumId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final addUsersDto = AddUsersDto(); // AddUsersDto |
try {
final result = api_instance.addUsersToAlbum(albumId, addUsersDto);
final result = api_instance.addUsersToAlbum(id, addUsersDto);
print(result);
} catch (e) {
print('Exception when calling AlbumApi->addUsersToAlbum: $e\n');
@@ -121,7 +121,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**albumId** | **String**| |
**id** | **String**| |
**addUsersDto** | [**AddUsersDto**](AddUsersDto.md)| |
### Return type
@@ -250,7 +250,7 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **deleteAlbum**
> deleteAlbum(albumId)
> deleteAlbum(id)
@@ -273,10 +273,10 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AlbumApi();
final albumId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
try {
api_instance.deleteAlbum(albumId);
api_instance.deleteAlbum(id);
} catch (e) {
print('Exception when calling AlbumApi->deleteAlbum: $e\n');
}
@@ -286,7 +286,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**albumId** | **String**| |
**id** | **String**| |
### Return type
@@ -304,7 +304,7 @@ void (empty response body)
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **downloadArchive**
> MultipartFile downloadArchive(albumId, name, skip, key)
> MultipartFile downloadArchive(id, name, skip, key)
@@ -327,13 +327,13 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AlbumApi();
final albumId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final name = name_example; // String |
final skip = 8.14; // num |
final key = key_example; // String |
try {
final result = api_instance.downloadArchive(albumId, name, skip, key);
final result = api_instance.downloadArchive(id, name, skip, key);
print(result);
} catch (e) {
print('Exception when calling AlbumApi->downloadArchive: $e\n');
@@ -344,7 +344,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**albumId** | **String**| |
**id** | **String**| |
**name** | **String**| | [optional]
**skip** | **num**| | [optional]
**key** | **String**| | [optional]
@@ -416,7 +416,7 @@ This endpoint does not need any parameter.
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **getAlbumInfo**
> AlbumResponseDto getAlbumInfo(albumId, key)
> AlbumResponseDto getAlbumInfo(id, key)
@@ -439,11 +439,11 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AlbumApi();
final albumId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final key = key_example; // String |
try {
final result = api_instance.getAlbumInfo(albumId, key);
final result = api_instance.getAlbumInfo(id, key);
print(result);
} catch (e) {
print('Exception when calling AlbumApi->getAlbumInfo: $e\n');
@@ -454,7 +454,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**albumId** | **String**| |
**id** | **String**| |
**key** | **String**| | [optional]
### Return type
@@ -530,7 +530,7 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **removeAssetFromAlbum**
> AlbumResponseDto removeAssetFromAlbum(albumId, removeAssetsDto)
> AlbumResponseDto removeAssetFromAlbum(id, removeAssetsDto)
@@ -553,11 +553,11 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AlbumApi();
final albumId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final removeAssetsDto = RemoveAssetsDto(); // RemoveAssetsDto |
try {
final result = api_instance.removeAssetFromAlbum(albumId, removeAssetsDto);
final result = api_instance.removeAssetFromAlbum(id, removeAssetsDto);
print(result);
} catch (e) {
print('Exception when calling AlbumApi->removeAssetFromAlbum: $e\n');
@@ -568,7 +568,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**albumId** | **String**| |
**id** | **String**| |
**removeAssetsDto** | [**RemoveAssetsDto**](RemoveAssetsDto.md)| |
### Return type
@@ -587,7 +587,7 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **removeUserFromAlbum**
> removeUserFromAlbum(albumId, userId)
> removeUserFromAlbum(id, userId)
@@ -610,11 +610,11 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AlbumApi();
final albumId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final userId = userId_example; // String |
try {
api_instance.removeUserFromAlbum(albumId, userId);
api_instance.removeUserFromAlbum(id, userId);
} catch (e) {
print('Exception when calling AlbumApi->removeUserFromAlbum: $e\n');
}
@@ -624,7 +624,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**albumId** | **String**| |
**id** | **String**| |
**userId** | **String**| |
### Return type
@@ -643,7 +643,7 @@ void (empty response body)
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **updateAlbumInfo**
> AlbumResponseDto updateAlbumInfo(albumId, updateAlbumDto)
> AlbumResponseDto updateAlbumInfo(id, updateAlbumDto)
@@ -666,11 +666,11 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AlbumApi();
final albumId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final updateAlbumDto = UpdateAlbumDto(); // UpdateAlbumDto |
try {
final result = api_instance.updateAlbumInfo(albumId, updateAlbumDto);
final result = api_instance.updateAlbumInfo(id, updateAlbumDto);
print(result);
} catch (e) {
print('Exception when calling AlbumApi->updateAlbumInfo: $e\n');
@@ -681,7 +681,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**albumId** | **String**| |
**id** | **String**| |
**updateAlbumDto** | [**UpdateAlbumDto**](UpdateAlbumDto.md)| |
### Return type

View File

@@ -12,8 +12,8 @@ Name | Type | Description | Notes
**id** | **String** | |
**ownerId** | **String** | |
**albumName** | **String** | |
**createdAt** | **String** | |
**updatedAt** | **String** | |
**createdAt** | [**DateTime**](DateTime.md) | |
**updatedAt** | [**DateTime**](DateTime.md) | |
**albumThumbnailAssetId** | **String** | |
**shared** | **bool** | |
**sharedUsers** | [**List<UserResponseDto>**](UserResponseDto.md) | | [default to const []]

View File

@@ -8,15 +8,16 @@ import 'package:openapi/api.dart';
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**thumbnailGenerationQueue** | [**JobStatusDto**](JobStatusDto.md) | |
**metadataExtractionQueue** | [**JobStatusDto**](JobStatusDto.md) | |
**videoConversionQueue** | [**JobStatusDto**](JobStatusDto.md) | |
**objectTaggingQueue** | [**JobStatusDto**](JobStatusDto.md) | |
**clipEncodingQueue** | [**JobStatusDto**](JobStatusDto.md) | |
**storageTemplateMigrationQueue** | [**JobStatusDto**](JobStatusDto.md) | |
**backgroundTaskQueue** | [**JobStatusDto**](JobStatusDto.md) | |
**searchQueue** | [**JobStatusDto**](JobStatusDto.md) | |
**recognizeFacesQueue** | [**JobStatusDto**](JobStatusDto.md) | |
**thumbnailGeneration** | [**JobStatusDto**](JobStatusDto.md) | |
**metadataExtraction** | [**JobStatusDto**](JobStatusDto.md) | |
**videoConversion** | [**JobStatusDto**](JobStatusDto.md) | |
**objectTagging** | [**JobStatusDto**](JobStatusDto.md) | |
**clipEncoding** | [**JobStatusDto**](JobStatusDto.md) | |
**storageTemplateMigration** | [**JobStatusDto**](JobStatusDto.md) | |
**backgroundTask** | [**JobStatusDto**](JobStatusDto.md) | |
**search** | [**JobStatusDto**](JobStatusDto.md) | |
**recognizeFaces** | [**JobStatusDto**](JobStatusDto.md) | |
**sidecar** | [**JobStatusDto**](JobStatusDto.md) | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -10,29 +10,30 @@ All URIs are relative to */api*
Method | HTTP request | Description
------------- | ------------- | -------------
[**addAssetsToSharedLink**](AssetApi.md#addassetstosharedlink) | **PATCH** /asset/shared-link/add |
[**bulkUploadCheck**](AssetApi.md#bulkuploadcheck) | **POST** /asset/bulk-upload-check |
[**checkDuplicateAsset**](AssetApi.md#checkduplicateasset) | **POST** /asset/check |
[**checkExistingAssets**](AssetApi.md#checkexistingassets) | **POST** /asset/exist |
[**createAssetsSharedLink**](AssetApi.md#createassetssharedlink) | **POST** /asset/shared-link |
[**deleteAsset**](AssetApi.md#deleteasset) | **DELETE** /asset |
[**downloadFile**](AssetApi.md#downloadfile) | **GET** /asset/download/{assetId} |
[**downloadFile**](AssetApi.md#downloadfile) | **GET** /asset/download/{id} |
[**downloadFiles**](AssetApi.md#downloadfiles) | **POST** /asset/download-files |
[**downloadLibrary**](AssetApi.md#downloadlibrary) | **GET** /asset/download-library |
[**getAllAssets**](AssetApi.md#getallassets) | **GET** /asset |
[**getArchivedAssetCountByUserId**](AssetApi.md#getarchivedassetcountbyuserid) | **GET** /asset/stat/archive |
[**getAssetById**](AssetApi.md#getassetbyid) | **GET** /asset/assetById/{assetId} |
[**getAssetById**](AssetApi.md#getassetbyid) | **GET** /asset/assetById/{id} |
[**getAssetByTimeBucket**](AssetApi.md#getassetbytimebucket) | **POST** /asset/time-bucket |
[**getAssetCountByTimeBucket**](AssetApi.md#getassetcountbytimebucket) | **POST** /asset/count-by-time-bucket |
[**getAssetCountByUserId**](AssetApi.md#getassetcountbyuserid) | **GET** /asset/count-by-user-id |
[**getAssetSearchTerms**](AssetApi.md#getassetsearchterms) | **GET** /asset/search-terms |
[**getAssetThumbnail**](AssetApi.md#getassetthumbnail) | **GET** /asset/thumbnail/{assetId} |
[**getAssetThumbnail**](AssetApi.md#getassetthumbnail) | **GET** /asset/thumbnail/{id} |
[**getCuratedLocations**](AssetApi.md#getcuratedlocations) | **GET** /asset/curated-locations |
[**getCuratedObjects**](AssetApi.md#getcuratedobjects) | **GET** /asset/curated-objects |
[**getMapMarkers**](AssetApi.md#getmapmarkers) | **GET** /asset/map-marker |
[**getUserAssetsByDeviceId**](AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} |
[**removeAssetsFromSharedLink**](AssetApi.md#removeassetsfromsharedlink) | **PATCH** /asset/shared-link/remove |
[**searchAsset**](AssetApi.md#searchasset) | **POST** /asset/search |
[**serveFile**](AssetApi.md#servefile) | **GET** /asset/file/{assetId} |
[**updateAsset**](AssetApi.md#updateasset) | **PUT** /asset/{assetId} |
[**serveFile**](AssetApi.md#servefile) | **GET** /asset/file/{id} |
[**updateAsset**](AssetApi.md#updateasset) | **PUT** /asset/{id} |
[**uploadFile**](AssetApi.md#uploadfile) | **POST** /asset/upload |
@@ -93,6 +94,63 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **bulkUploadCheck**
> AssetBulkUploadCheckResponseDto bulkUploadCheck(assetBulkUploadCheckDto)
Checks if assets exist by checksums
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AssetApi();
final assetBulkUploadCheckDto = AssetBulkUploadCheckDto(); // AssetBulkUploadCheckDto |
try {
final result = api_instance.bulkUploadCheck(assetBulkUploadCheckDto);
print(result);
} catch (e) {
print('Exception when calling AssetApi->bulkUploadCheck: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**assetBulkUploadCheckDto** | [**AssetBulkUploadCheckDto**](AssetBulkUploadCheckDto.md)| |
### Return type
[**AssetBulkUploadCheckResponseDto**](AssetBulkUploadCheckResponseDto.md)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **checkDuplicateAsset**
> CheckDuplicateAssetResponseDto checkDuplicateAsset(checkDuplicateAssetDto, key)
@@ -320,7 +378,7 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **downloadFile**
> MultipartFile downloadFile(assetId, key)
> MultipartFile downloadFile(id, key)
@@ -343,11 +401,11 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AssetApi();
final assetId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final key = key_example; // String |
try {
final result = api_instance.downloadFile(assetId, key);
final result = api_instance.downloadFile(id, key);
print(result);
} catch (e) {
print('Exception when calling AssetApi->downloadFile: $e\n');
@@ -358,7 +416,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**assetId** | **String**| |
**id** | **String**| |
**key** | **String**| | [optional]
### Return type
@@ -495,7 +553,7 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **getAllAssets**
> List<AssetResponseDto> getAllAssets(isFavorite, isArchived, skip, ifNoneMatch)
> List<AssetResponseDto> getAllAssets(userId, isFavorite, isArchived, withoutThumbs, skip, ifNoneMatch)
@@ -520,13 +578,15 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AssetApi();
final userId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final isFavorite = true; // bool |
final isArchived = true; // bool |
final withoutThumbs = true; // bool | Include assets without thumbnails
final skip = 8.14; // num |
final ifNoneMatch = ifNoneMatch_example; // String | ETag of data already cached on the client
try {
final result = api_instance.getAllAssets(isFavorite, isArchived, skip, ifNoneMatch);
final result = api_instance.getAllAssets(userId, isFavorite, isArchived, withoutThumbs, skip, ifNoneMatch);
print(result);
} catch (e) {
print('Exception when calling AssetApi->getAllAssets: $e\n');
@@ -537,8 +597,10 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**userId** | **String**| | [optional]
**isFavorite** | **bool**| | [optional]
**isArchived** | **bool**| | [optional]
**withoutThumbs** | **bool**| Include assets without thumbnails | [optional]
**skip** | **num**| | [optional]
**ifNoneMatch** | **String**| ETag of data already cached on the client | [optional]
@@ -609,7 +671,7 @@ This endpoint does not need any parameter.
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **getAssetById**
> AssetResponseDto getAssetById(assetId, key)
> AssetResponseDto getAssetById(id, key)
@@ -634,11 +696,11 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AssetApi();
final assetId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final key = key_example; // String |
try {
final result = api_instance.getAssetById(assetId, key);
final result = api_instance.getAssetById(id, key);
print(result);
} catch (e) {
print('Exception when calling AssetApi->getAssetById: $e\n');
@@ -649,7 +711,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**assetId** | **String**| |
**id** | **String**| |
**key** | **String**| | [optional]
### Return type
@@ -880,7 +942,7 @@ This endpoint does not need any parameter.
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **getAssetThumbnail**
> MultipartFile getAssetThumbnail(assetId, format, key)
> MultipartFile getAssetThumbnail(id, format, key)
@@ -903,12 +965,12 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AssetApi();
final assetId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final format = ; // ThumbnailFormat |
final key = key_example; // String |
try {
final result = api_instance.getAssetThumbnail(assetId, format, key);
final result = api_instance.getAssetThumbnail(id, format, key);
print(result);
} catch (e) {
print('Exception when calling AssetApi->getAssetThumbnail: $e\n');
@@ -919,7 +981,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**assetId** | **String**| |
**id** | **String**| |
**format** | [**ThumbnailFormat**](.md)| | [optional]
**key** | **String**| | [optional]
@@ -1041,7 +1103,7 @@ This endpoint does not need any parameter.
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **getMapMarkers**
> List<MapMarkerResponseDto> getMapMarkers(isFavorite)
> List<MapMarkerResponseDto> getMapMarkers(isFavorite, fileCreatedAfter, fileCreatedBefore)
@@ -1065,9 +1127,11 @@ import 'package:openapi/api.dart';
final api_instance = AssetApi();
final isFavorite = true; // bool |
final fileCreatedAfter = 2013-10-20T19:20:30+01:00; // DateTime |
final fileCreatedBefore = 2013-10-20T19:20:30+01:00; // DateTime |
try {
final result = api_instance.getMapMarkers(isFavorite);
final result = api_instance.getMapMarkers(isFavorite, fileCreatedAfter, fileCreatedBefore);
print(result);
} catch (e) {
print('Exception when calling AssetApi->getMapMarkers: $e\n');
@@ -1079,6 +1143,8 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**isFavorite** | **bool**| | [optional]
**fileCreatedAfter** | **DateTime**| | [optional]
**fileCreatedBefore** | **DateTime**| | [optional]
### Return type
@@ -1265,7 +1331,7 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **serveFile**
> MultipartFile serveFile(assetId, isThumb, isWeb, key)
> MultipartFile serveFile(id, isThumb, isWeb, key)
@@ -1288,13 +1354,13 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AssetApi();
final assetId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final isThumb = true; // bool |
final isWeb = true; // bool |
final key = key_example; // String |
try {
final result = api_instance.serveFile(assetId, isThumb, isWeb, key);
final result = api_instance.serveFile(id, isThumb, isWeb, key);
print(result);
} catch (e) {
print('Exception when calling AssetApi->serveFile: $e\n');
@@ -1305,7 +1371,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**assetId** | **String**| |
**id** | **String**| |
**isThumb** | **bool**| | [optional]
**isWeb** | **bool**| | [optional]
**key** | **String**| | [optional]
@@ -1326,7 +1392,7 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **updateAsset**
> AssetResponseDto updateAsset(assetId, updateAssetDto)
> AssetResponseDto updateAsset(id, updateAssetDto)
@@ -1351,11 +1417,11 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = AssetApi();
final assetId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final updateAssetDto = UpdateAssetDto(); // UpdateAssetDto |
try {
final result = api_instance.updateAsset(assetId, updateAssetDto);
final result = api_instance.updateAsset(id, updateAssetDto);
print(result);
} catch (e) {
print('Exception when calling AssetApi->updateAsset: $e\n');
@@ -1366,7 +1432,7 @@ try {
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**assetId** | **String**| |
**id** | **String**| |
**updateAssetDto** | [**UpdateAssetDto**](UpdateAssetDto.md)| |
### Return type
@@ -1385,7 +1451,7 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **uploadFile**
> AssetFileUploadResponseDto uploadFile(assetType, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, isFavorite, fileExtension, key, livePhotoData, isArchived, isVisible, duration)
> AssetFileUploadResponseDto uploadFile(assetType, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, isFavorite, fileExtension, key, livePhotoData, sidecarData, isArchived, isVisible, duration)
@@ -1412,18 +1478,19 @@ final assetType = ; // AssetTypeEnum |
final assetData = BINARY_DATA_HERE; // MultipartFile |
final deviceAssetId = deviceAssetId_example; // String |
final deviceId = deviceId_example; // String |
final fileCreatedAt = fileCreatedAt_example; // String |
final fileModifiedAt = fileModifiedAt_example; // String |
final fileCreatedAt = 2013-10-20T19:20:30+01:00; // DateTime |
final fileModifiedAt = 2013-10-20T19:20:30+01:00; // DateTime |
final isFavorite = true; // bool |
final fileExtension = fileExtension_example; // String |
final key = key_example; // String |
final livePhotoData = BINARY_DATA_HERE; // MultipartFile |
final sidecarData = BINARY_DATA_HERE; // MultipartFile |
final isArchived = true; // bool |
final isVisible = true; // bool |
final duration = duration_example; // String |
try {
final result = api_instance.uploadFile(assetType, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, isFavorite, fileExtension, key, livePhotoData, isArchived, isVisible, duration);
final result = api_instance.uploadFile(assetType, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, isFavorite, fileExtension, key, livePhotoData, sidecarData, isArchived, isVisible, duration);
print(result);
} catch (e) {
print('Exception when calling AssetApi->uploadFile: $e\n');
@@ -1438,12 +1505,13 @@ Name | Type | Description | Notes
**assetData** | **MultipartFile**| |
**deviceAssetId** | **String**| |
**deviceId** | **String**| |
**fileCreatedAt** | **String**| |
**fileModifiedAt** | **String**| |
**fileCreatedAt** | **DateTime**| |
**fileModifiedAt** | **DateTime**| |
**isFavorite** | **bool**| |
**fileExtension** | **String**| |
**key** | **String**| | [optional]
**livePhotoData** | **MultipartFile**| | [optional]
**sidecarData** | **MultipartFile**| | [optional]
**isArchived** | **bool**| | [optional]
**isVisible** | **bool**| | [optional]
**duration** | **String**| | [optional]

View File

@@ -0,0 +1,15 @@
# openapi.model.AssetBulkUploadCheckDto
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**assets** | [**List<AssetBulkUploadCheckItem>**](AssetBulkUploadCheckItem.md) | | [default to const []]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,16 @@
# openapi.model.AssetBulkUploadCheckItem
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**id** | **String** | |
**checksum** | **String** | base64 or hex encoded sha1 hash |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,15 @@
# openapi.model.AssetBulkUploadCheckResponseDto
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**results** | [**List<AssetBulkUploadCheckResult>**](AssetBulkUploadCheckResult.md) | | [default to const []]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,18 @@
# openapi.model.AssetBulkUploadCheckResult
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**id** | **String** | |
**action** | **String** | |
**reason** | **String** | | [optional]
**assetId** | **String** | | [optional]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

15
mobile/openapi/doc/AssetIdsDto.md generated Normal file
View File

@@ -0,0 +1,15 @@
# openapi.model.AssetIdsDto
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**assetIds** | **List<String>** | | [default to const []]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,17 @@
# openapi.model.AssetIdsResponseDto
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**assetId** | **String** | |
**success** | **bool** | |
**error** | **String** | | [optional]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -15,21 +15,20 @@ Name | Type | Description | Notes
**deviceId** | **String** | |
**originalPath** | **String** | |
**originalFileName** | **String** | |
**resizePath** | **String** | |
**fileCreatedAt** | **String** | |
**fileModifiedAt** | **String** | |
**updatedAt** | **String** | |
**resized** | **bool** | |
**fileCreatedAt** | [**DateTime**](DateTime.md) | |
**fileModifiedAt** | [**DateTime**](DateTime.md) | |
**updatedAt** | [**DateTime**](DateTime.md) | |
**isFavorite** | **bool** | |
**isArchived** | **bool** | |
**mimeType** | **String** | |
**duration** | **String** | |
**webpPath** | **String** | |
**encodedVideoPath** | **String** | | [optional]
**exifInfo** | [**ExifResponseDto**](ExifResponseDto.md) | | [optional]
**smartInfo** | [**SmartInfoResponseDto**](SmartInfoResponseDto.md) | | [optional]
**livePhotoVideoId** | **String** | | [optional]
**tags** | [**List<TagResponseDto>**](TagResponseDto.md) | | [optional] [default to const []]
**people** | [**List<PersonResponseDto>**](PersonResponseDto.md) | | [optional] [default to const []]
**checksum** | **String** | base64 encoded sha1 hash |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -9,7 +9,7 @@ import 'package:openapi/api.dart';
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**assetIds** | **List<String>** | | [default to const []]
**expiresAt** | **String** | | [optional]
**expiresAt** | [**DateTime**](DateTime.md) | | [optional]
**allowUpload** | **bool** | | [optional]
**allowDownload** | **bool** | | [optional]
**showExif** | **bool** | | [optional]

View File

@@ -9,7 +9,7 @@ import 'package:openapi/api.dart';
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**description** | **String** | | [optional]
**expiresAt** | **String** | | [optional]
**expiresAt** | [**DateTime**](DateTime.md) | | [optional]
**allowUpload** | **bool** | | [optional]
**allowDownload** | **bool** | | [optional]
**showExif** | **bool** | | [optional]

View File

@@ -10,6 +10,7 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**timeBucket** | **List<String>** | | [default to const []]
**userId** | **String** | | [optional]
**withoutThumbs** | **bool** | Include assets without thumbnails | [optional]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -10,6 +10,7 @@ Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**timeGroup** | [**TimeGroupEnum**](TimeGroupEnum.md) | |
**userId** | **String** | | [optional]
**withoutThumbs** | **bool** | Include assets without thumbnails | [optional]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

15
mobile/openapi/doc/JobSettingsDto.md generated Normal file
View File

@@ -0,0 +1,15 @@
# openapi.model.JobSettingsDto
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**concurrency** | **int** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -9,70 +9,13 @@ All URIs are relative to */api*
Method | HTTP request | Description
------------- | ------------- | -------------
[**editSharedLink**](ShareApi.md#editsharedlink) | **PATCH** /share/{id} |
[**getAllSharedLinks**](ShareApi.md#getallsharedlinks) | **GET** /share |
[**getMySharedLink**](ShareApi.md#getmysharedlink) | **GET** /share/me |
[**getSharedLinkById**](ShareApi.md#getsharedlinkbyid) | **GET** /share/{id} |
[**removeSharedLink**](ShareApi.md#removesharedlink) | **DELETE** /share/{id} |
[**updateSharedLink**](ShareApi.md#updatesharedlink) | **PATCH** /share/{id} |
# **editSharedLink**
> SharedLinkResponseDto editSharedLink(id, editSharedLinkDto)
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = ShareApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final editSharedLinkDto = EditSharedLinkDto(); // EditSharedLinkDto |
try {
final result = api_instance.editSharedLink(id, editSharedLinkDto);
print(result);
} catch (e) {
print('Exception when calling ShareApi->editSharedLink: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **String**| |
**editSharedLinkDto** | [**EditSharedLinkDto**](EditSharedLinkDto.md)| |
### Return type
[**SharedLinkResponseDto**](SharedLinkResponseDto.md)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **getAllSharedLinks**
> List<SharedLinkResponseDto> getAllSharedLinks()
@@ -288,3 +231,60 @@ void (empty response body)
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **updateSharedLink**
> SharedLinkResponseDto updateSharedLink(id, editSharedLinkDto)
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = ShareApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final editSharedLinkDto = EditSharedLinkDto(); // EditSharedLinkDto |
try {
final result = api_instance.updateSharedLink(id, editSharedLinkDto);
print(result);
} catch (e) {
print('Exception when calling ShareApi->updateSharedLink: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **String**| |
**editSharedLinkDto** | [**EditSharedLinkDto**](EditSharedLinkDto.md)| |
### Return type
[**SharedLinkResponseDto**](SharedLinkResponseDto.md)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

View File

@@ -13,8 +13,8 @@ Name | Type | Description | Notes
**description** | **String** | | [optional]
**userId** | **String** | |
**key** | **String** | |
**createdAt** | **String** | |
**expiresAt** | **String** | |
**createdAt** | [**DateTime**](DateTime.md) | |
**expiresAt** | [**DateTime**](DateTime.md) | |
**assets** | [**List<AssetResponseDto>**](AssetResponseDto.md) | | [default to const []]
**album** | [**AlbumResponseDto**](AlbumResponseDto.md) | | [optional]
**allowUpload** | **bool** | |

View File

@@ -12,6 +12,7 @@ Name | Type | Description | Notes
**oauth** | [**SystemConfigOAuthDto**](SystemConfigOAuthDto.md) | |
**passwordLogin** | [**SystemConfigPasswordLoginDto**](SystemConfigPasswordLoginDto.md) | |
**storageTemplate** | [**SystemConfigStorageTemplateDto**](SystemConfigStorageTemplateDto.md) | |
**job** | [**SystemConfigJobDto**](SystemConfigJobDto.md) | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

24
mobile/openapi/doc/SystemConfigJobDto.md generated Normal file
View File

@@ -0,0 +1,24 @@
# openapi.model.SystemConfigJobDto
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**thumbnailGeneration** | [**JobSettingsDto**](JobSettingsDto.md) | |
**metadataExtraction** | [**JobSettingsDto**](JobSettingsDto.md) | |
**videoConversion** | [**JobSettingsDto**](JobSettingsDto.md) | |
**objectTagging** | [**JobSettingsDto**](JobSettingsDto.md) | |
**clipEncoding** | [**JobSettingsDto**](JobSettingsDto.md) | |
**storageTemplateMigration** | [**JobSettingsDto**](JobSettingsDto.md) | |
**backgroundTask** | [**JobSettingsDto**](JobSettingsDto.md) | |
**search** | [**JobSettingsDto**](JobSettingsDto.md) | |
**recognizeFaces** | [**JobSettingsDto**](JobSettingsDto.md) | |
**sidecar** | [**JobSettingsDto**](JobSettingsDto.md) | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -9,15 +9,18 @@ All URIs are relative to */api*
Method | HTTP request | Description
------------- | ------------- | -------------
[**create**](TagApi.md#create) | **POST** /tag |
[**delete**](TagApi.md#delete) | **DELETE** /tag/{id} |
[**findAll**](TagApi.md#findall) | **GET** /tag |
[**findOne**](TagApi.md#findone) | **GET** /tag/{id} |
[**update**](TagApi.md#update) | **PATCH** /tag/{id} |
[**createTag**](TagApi.md#createtag) | **POST** /tag |
[**deleteTag**](TagApi.md#deletetag) | **DELETE** /tag/{id} |
[**getAllTags**](TagApi.md#getalltags) | **GET** /tag |
[**getTagAssets**](TagApi.md#gettagassets) | **GET** /tag/{id}/assets |
[**getTagById**](TagApi.md#gettagbyid) | **GET** /tag/{id} |
[**tagAssets**](TagApi.md#tagassets) | **PUT** /tag/{id}/assets |
[**untagAssets**](TagApi.md#untagassets) | **DELETE** /tag/{id}/assets |
[**updateTag**](TagApi.md#updatetag) | **PATCH** /tag/{id} |
# **create**
> TagResponseDto create(createTagDto)
# **createTag**
> TagResponseDto createTag(createTagDto)
@@ -43,10 +46,10 @@ final api_instance = TagApi();
final createTagDto = CreateTagDto(); // CreateTagDto |
try {
final result = api_instance.create(createTagDto);
final result = api_instance.createTag(createTagDto);
print(result);
} catch (e) {
print('Exception when calling TagApi->create: $e\n');
print('Exception when calling TagApi->createTag: $e\n');
}
```
@@ -71,8 +74,8 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **delete**
> delete(id)
# **deleteTag**
> deleteTag(id)
@@ -98,9 +101,9 @@ final api_instance = TagApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
try {
api_instance.delete(id);
api_instance.deleteTag(id);
} catch (e) {
print('Exception when calling TagApi->delete: $e\n');
print('Exception when calling TagApi->deleteTag: $e\n');
}
```
@@ -125,8 +128,8 @@ void (empty response body)
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **findAll**
> List<TagResponseDto> findAll()
# **getAllTags**
> List<TagResponseDto> getAllTags()
@@ -151,10 +154,10 @@ import 'package:openapi/api.dart';
final api_instance = TagApi();
try {
final result = api_instance.findAll();
final result = api_instance.getAllTags();
print(result);
} catch (e) {
print('Exception when calling TagApi->findAll: $e\n');
print('Exception when calling TagApi->getAllTags: $e\n');
}
```
@@ -176,8 +179,8 @@ This endpoint does not need any parameter.
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **findOne**
> TagResponseDto findOne(id)
# **getTagAssets**
> List<AssetResponseDto> getTagAssets(id)
@@ -203,10 +206,65 @@ final api_instance = TagApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
try {
final result = api_instance.findOne(id);
final result = api_instance.getTagAssets(id);
print(result);
} catch (e) {
print('Exception when calling TagApi->findOne: $e\n');
print('Exception when calling TagApi->getTagAssets: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **String**| |
### Return type
[**List<AssetResponseDto>**](AssetResponseDto.md)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **getTagById**
> TagResponseDto getTagById(id)
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = TagApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
try {
final result = api_instance.getTagById(id);
print(result);
} catch (e) {
print('Exception when calling TagApi->getTagById: $e\n');
}
```
@@ -231,8 +289,122 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **update**
> TagResponseDto update(id, updateTagDto)
# **tagAssets**
> List<AssetIdsResponseDto> tagAssets(id, assetIdsDto)
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = TagApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final assetIdsDto = AssetIdsDto(); // AssetIdsDto |
try {
final result = api_instance.tagAssets(id, assetIdsDto);
print(result);
} catch (e) {
print('Exception when calling TagApi->tagAssets: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **String**| |
**assetIdsDto** | [**AssetIdsDto**](AssetIdsDto.md)| |
### Return type
[**List<AssetIdsResponseDto>**](AssetIdsResponseDto.md)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **untagAssets**
> List<AssetIdsResponseDto> untagAssets(id, assetIdsDto)
### Example
```dart
import 'package:openapi/api.dart';
// TODO Configure API key authorization: cookie
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
// TODO Configure API key authorization: api_key
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
// TODO Configure HTTP Bearer authorization: bearer
// Case 1. Use String Token
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
// Case 2. Use Function which generate token.
// String yourTokenGeneratorFunction() { ... }
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
final api_instance = TagApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final assetIdsDto = AssetIdsDto(); // AssetIdsDto |
try {
final result = api_instance.untagAssets(id, assetIdsDto);
print(result);
} catch (e) {
print('Exception when calling TagApi->untagAssets: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **String**| |
**assetIdsDto** | [**AssetIdsDto**](AssetIdsDto.md)| |
### Return type
[**List<AssetIdsResponseDto>**](AssetIdsResponseDto.md)
### Authorization
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **updateTag**
> TagResponseDto updateTag(id, updateTagDto)
@@ -259,10 +431,10 @@ final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
final updateTagDto = UpdateTagDto(); // UpdateTagDto |
try {
final result = api_instance.update(id, updateTagDto);
final result = api_instance.updateTag(id, updateTagDto);
print(result);
} catch (e) {
print('Exception when calling TagApi->update: $e\n');
print('Exception when calling TagApi->updateTag: $e\n');
}
```

View File

@@ -8,11 +8,10 @@ import 'package:openapi/api.dart';
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**id** | **String** | |
**type** | [**TagTypeEnum**](TagTypeEnum.md) | |
**id** | **String** | |
**name** | **String** | |
**userId** | **String** | |
**renameTagId** | **String** | | [optional]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -9,7 +9,6 @@ import 'package:openapi/api.dart';
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **String** | | [optional]
**renameTagId** | **String** | | [optional]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -13,12 +13,12 @@ Name | Type | Description | Notes
**firstName** | **String** | |
**lastName** | **String** | |
**storageLabel** | **String** | |
**createdAt** | **String** | |
**profileImagePath** | **String** | |
**shouldChangePassword** | **bool** | |
**isAdmin** | **bool** | |
**deletedAt** | [**DateTime**](DateTime.md) | | [optional]
**updatedAt** | **String** | | [optional]
**createdAt** | [**DateTime**](DateTime.md) | |
**deletedAt** | [**DateTime**](DateTime.md) | |
**updatedAt** | [**DateTime**](DateTime.md) | |
**oauthId** | **String** | |
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -54,10 +54,16 @@ part 'model/admin_signup_response_dto.dart';
part 'model/album_count_response_dto.dart';
part 'model/album_response_dto.dart';
part 'model/all_job_status_response_dto.dart';
part 'model/asset_bulk_upload_check_dto.dart';
part 'model/asset_bulk_upload_check_item.dart';
part 'model/asset_bulk_upload_check_response_dto.dart';
part 'model/asset_bulk_upload_check_result.dart';
part 'model/asset_count_by_time_bucket.dart';
part 'model/asset_count_by_time_bucket_response_dto.dart';
part 'model/asset_count_by_user_id_response_dto.dart';
part 'model/asset_file_upload_response_dto.dart';
part 'model/asset_ids_dto.dart';
part 'model/asset_ids_response_dto.dart';
part 'model/asset_response_dto.dart';
part 'model/asset_type_enum.dart';
part 'model/auth_device_response_dto.dart';
@@ -86,6 +92,7 @@ part 'model/job_command.dart';
part 'model/job_command_dto.dart';
part 'model/job_counts_dto.dart';
part 'model/job_name.dart';
part 'model/job_settings_dto.dart';
part 'model/job_status_dto.dart';
part 'model/login_credential_dto.dart';
part 'model/login_response_dto.dart';
@@ -117,6 +124,7 @@ part 'model/sign_up_dto.dart';
part 'model/smart_info_response_dto.dart';
part 'model/system_config_dto.dart';
part 'model/system_config_f_fmpeg_dto.dart';
part 'model/system_config_job_dto.dart';
part 'model/system_config_o_auth_dto.dart';
part 'model/system_config_password_login_dto.dart';
part 'model/system_config_storage_template_dto.dart';

View File

@@ -16,18 +16,18 @@ class AlbumApi {
final ApiClient apiClient;
/// Performs an HTTP 'PUT /album/{albumId}/assets' operation and returns the [Response].
/// Performs an HTTP 'PUT /album/{id}/assets' operation and returns the [Response].
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [AddAssetsDto] addAssetsDto (required):
///
/// * [String] key:
Future<Response> addAssetsToAlbumWithHttpInfo(String albumId, AddAssetsDto addAssetsDto, { String? key, }) async {
Future<Response> addAssetsToAlbumWithHttpInfo(String id, AddAssetsDto addAssetsDto, { String? key, }) async {
// ignore: prefer_const_declarations
final path = r'/album/{albumId}/assets'
.replaceAll('{albumId}', albumId);
final path = r'/album/{id}/assets'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody = addAssetsDto;
@@ -56,13 +56,13 @@ class AlbumApi {
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [AddAssetsDto] addAssetsDto (required):
///
/// * [String] key:
Future<AddAssetsResponseDto?> addAssetsToAlbum(String albumId, AddAssetsDto addAssetsDto, { String? key, }) async {
final response = await addAssetsToAlbumWithHttpInfo(albumId, addAssetsDto, key: key, );
Future<AddAssetsResponseDto?> addAssetsToAlbum(String id, AddAssetsDto addAssetsDto, { String? key, }) async {
final response = await addAssetsToAlbumWithHttpInfo(id, addAssetsDto, key: key, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -76,16 +76,16 @@ class AlbumApi {
return null;
}
/// Performs an HTTP 'PUT /album/{albumId}/users' operation and returns the [Response].
/// Performs an HTTP 'PUT /album/{id}/users' operation and returns the [Response].
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [AddUsersDto] addUsersDto (required):
Future<Response> addUsersToAlbumWithHttpInfo(String albumId, AddUsersDto addUsersDto,) async {
Future<Response> addUsersToAlbumWithHttpInfo(String id, AddUsersDto addUsersDto,) async {
// ignore: prefer_const_declarations
final path = r'/album/{albumId}/users'
.replaceAll('{albumId}', albumId);
final path = r'/album/{id}/users'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody = addUsersDto;
@@ -110,11 +110,11 @@ class AlbumApi {
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [AddUsersDto] addUsersDto (required):
Future<AlbumResponseDto?> addUsersToAlbum(String albumId, AddUsersDto addUsersDto,) async {
final response = await addUsersToAlbumWithHttpInfo(albumId, addUsersDto,);
Future<AlbumResponseDto?> addUsersToAlbum(String id, AddUsersDto addUsersDto,) async {
final response = await addUsersToAlbumWithHttpInfo(id, addUsersDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -222,14 +222,14 @@ class AlbumApi {
return null;
}
/// Performs an HTTP 'DELETE /album/{albumId}' operation and returns the [Response].
/// Performs an HTTP 'DELETE /album/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] albumId (required):
Future<Response> deleteAlbumWithHttpInfo(String albumId,) async {
/// * [String] id (required):
Future<Response> deleteAlbumWithHttpInfo(String id,) async {
// ignore: prefer_const_declarations
final path = r'/album/{albumId}'
.replaceAll('{albumId}', albumId);
final path = r'/album/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
@@ -254,28 +254,28 @@ class AlbumApi {
/// Parameters:
///
/// * [String] albumId (required):
Future<void> deleteAlbum(String albumId,) async {
final response = await deleteAlbumWithHttpInfo(albumId,);
/// * [String] id (required):
Future<void> deleteAlbum(String id,) async {
final response = await deleteAlbumWithHttpInfo(id,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
}
/// Performs an HTTP 'GET /album/{albumId}/download' operation and returns the [Response].
/// Performs an HTTP 'GET /album/{id}/download' operation and returns the [Response].
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [String] name:
///
/// * [num] skip:
///
/// * [String] key:
Future<Response> downloadArchiveWithHttpInfo(String albumId, { String? name, num? skip, String? key, }) async {
Future<Response> downloadArchiveWithHttpInfo(String id, { String? name, num? skip, String? key, }) async {
// ignore: prefer_const_declarations
final path = r'/album/{albumId}/download'
.replaceAll('{albumId}', albumId);
final path = r'/album/{id}/download'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
@@ -310,15 +310,15 @@ class AlbumApi {
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [String] name:
///
/// * [num] skip:
///
/// * [String] key:
Future<MultipartFile?> downloadArchive(String albumId, { String? name, num? skip, String? key, }) async {
final response = await downloadArchiveWithHttpInfo(albumId, name: name, skip: skip, key: key, );
Future<MultipartFile?> downloadArchive(String id, { String? name, num? skip, String? key, }) async {
final response = await downloadArchiveWithHttpInfo(id, name: name, skip: skip, key: key, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -373,16 +373,16 @@ class AlbumApi {
return null;
}
/// Performs an HTTP 'GET /album/{albumId}' operation and returns the [Response].
/// Performs an HTTP 'GET /album/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [String] key:
Future<Response> getAlbumInfoWithHttpInfo(String albumId, { String? key, }) async {
Future<Response> getAlbumInfoWithHttpInfo(String id, { String? key, }) async {
// ignore: prefer_const_declarations
final path = r'/album/{albumId}'
.replaceAll('{albumId}', albumId);
final path = r'/album/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
@@ -411,11 +411,11 @@ class AlbumApi {
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [String] key:
Future<AlbumResponseDto?> getAlbumInfo(String albumId, { String? key, }) async {
final response = await getAlbumInfoWithHttpInfo(albumId, key: key, );
Future<AlbumResponseDto?> getAlbumInfo(String id, { String? key, }) async {
final response = await getAlbumInfoWithHttpInfo(id, key: key, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -492,16 +492,16 @@ class AlbumApi {
return null;
}
/// Performs an HTTP 'DELETE /album/{albumId}/assets' operation and returns the [Response].
/// Performs an HTTP 'DELETE /album/{id}/assets' operation and returns the [Response].
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [RemoveAssetsDto] removeAssetsDto (required):
Future<Response> removeAssetFromAlbumWithHttpInfo(String albumId, RemoveAssetsDto removeAssetsDto,) async {
Future<Response> removeAssetFromAlbumWithHttpInfo(String id, RemoveAssetsDto removeAssetsDto,) async {
// ignore: prefer_const_declarations
final path = r'/album/{albumId}/assets'
.replaceAll('{albumId}', albumId);
final path = r'/album/{id}/assets'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody = removeAssetsDto;
@@ -526,11 +526,11 @@ class AlbumApi {
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [RemoveAssetsDto] removeAssetsDto (required):
Future<AlbumResponseDto?> removeAssetFromAlbum(String albumId, RemoveAssetsDto removeAssetsDto,) async {
final response = await removeAssetFromAlbumWithHttpInfo(albumId, removeAssetsDto,);
Future<AlbumResponseDto?> removeAssetFromAlbum(String id, RemoveAssetsDto removeAssetsDto,) async {
final response = await removeAssetFromAlbumWithHttpInfo(id, removeAssetsDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -544,16 +544,16 @@ class AlbumApi {
return null;
}
/// Performs an HTTP 'DELETE /album/{albumId}/user/{userId}' operation and returns the [Response].
/// Performs an HTTP 'DELETE /album/{id}/user/{userId}' operation and returns the [Response].
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [String] userId (required):
Future<Response> removeUserFromAlbumWithHttpInfo(String albumId, String userId,) async {
Future<Response> removeUserFromAlbumWithHttpInfo(String id, String userId,) async {
// ignore: prefer_const_declarations
final path = r'/album/{albumId}/user/{userId}'
.replaceAll('{albumId}', albumId)
final path = r'/album/{id}/user/{userId}'
.replaceAll('{id}', id)
.replaceAll('{userId}', userId);
// ignore: prefer_final_locals
@@ -579,26 +579,26 @@ class AlbumApi {
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [String] userId (required):
Future<void> removeUserFromAlbum(String albumId, String userId,) async {
final response = await removeUserFromAlbumWithHttpInfo(albumId, userId,);
Future<void> removeUserFromAlbum(String id, String userId,) async {
final response = await removeUserFromAlbumWithHttpInfo(id, userId,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
}
/// Performs an HTTP 'PATCH /album/{albumId}' operation and returns the [Response].
/// Performs an HTTP 'PATCH /album/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [UpdateAlbumDto] updateAlbumDto (required):
Future<Response> updateAlbumInfoWithHttpInfo(String albumId, UpdateAlbumDto updateAlbumDto,) async {
Future<Response> updateAlbumInfoWithHttpInfo(String id, UpdateAlbumDto updateAlbumDto,) async {
// ignore: prefer_const_declarations
final path = r'/album/{albumId}'
.replaceAll('{albumId}', albumId);
final path = r'/album/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody = updateAlbumDto;
@@ -623,11 +623,11 @@ class AlbumApi {
/// Parameters:
///
/// * [String] albumId (required):
/// * [String] id (required):
///
/// * [UpdateAlbumDto] updateAlbumDto (required):
Future<AlbumResponseDto?> updateAlbumInfo(String albumId, UpdateAlbumDto updateAlbumDto,) async {
final response = await updateAlbumInfoWithHttpInfo(albumId, updateAlbumDto,);
Future<AlbumResponseDto?> updateAlbumInfo(String id, UpdateAlbumDto updateAlbumDto,) async {
final response = await updateAlbumInfoWithHttpInfo(id, updateAlbumDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}

View File

@@ -71,6 +71,58 @@ class AssetApi {
return null;
}
/// Checks if assets exist by checksums
///
/// Note: This method returns the HTTP [Response].
///
/// Parameters:
///
/// * [AssetBulkUploadCheckDto] assetBulkUploadCheckDto (required):
Future<Response> bulkUploadCheckWithHttpInfo(AssetBulkUploadCheckDto assetBulkUploadCheckDto,) async {
// ignore: prefer_const_declarations
final path = r'/asset/bulk-upload-check';
// ignore: prefer_final_locals
Object? postBody = assetBulkUploadCheckDto;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/json'];
return apiClient.invokeAPI(
path,
'POST',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Checks if assets exist by checksums
///
/// Parameters:
///
/// * [AssetBulkUploadCheckDto] assetBulkUploadCheckDto (required):
Future<AssetBulkUploadCheckResponseDto?> bulkUploadCheck(AssetBulkUploadCheckDto assetBulkUploadCheckDto,) async {
final response = await bulkUploadCheckWithHttpInfo(assetBulkUploadCheckDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'AssetBulkUploadCheckResponseDto',) as AssetBulkUploadCheckResponseDto;
}
return null;
}
/// Check duplicated asset before uploading - for Web upload used
///
/// Note: This method returns the HTTP [Response].
@@ -280,16 +332,16 @@ class AssetApi {
return null;
}
/// Performs an HTTP 'GET /asset/download/{assetId}' operation and returns the [Response].
/// Performs an HTTP 'GET /asset/download/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] assetId (required):
/// * [String] id (required):
///
/// * [String] key:
Future<Response> downloadFileWithHttpInfo(String assetId, { String? key, }) async {
Future<Response> downloadFileWithHttpInfo(String id, { String? key, }) async {
// ignore: prefer_const_declarations
final path = r'/asset/download/{assetId}'
.replaceAll('{assetId}', assetId);
final path = r'/asset/download/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
@@ -318,11 +370,11 @@ class AssetApi {
/// Parameters:
///
/// * [String] assetId (required):
/// * [String] id (required):
///
/// * [String] key:
Future<MultipartFile?> downloadFile(String assetId, { String? key, }) async {
final response = await downloadFileWithHttpInfo(assetId, key: key, );
Future<MultipartFile?> downloadFile(String id, { String? key, }) async {
final response = await downloadFileWithHttpInfo(id, key: key, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -467,15 +519,20 @@ class AssetApi {
///
/// Parameters:
///
/// * [String] userId:
///
/// * [bool] isFavorite:
///
/// * [bool] isArchived:
///
/// * [bool] withoutThumbs:
/// Include assets without thumbnails
///
/// * [num] skip:
///
/// * [String] ifNoneMatch:
/// ETag of data already cached on the client
Future<Response> getAllAssetsWithHttpInfo({ bool? isFavorite, bool? isArchived, num? skip, String? ifNoneMatch, }) async {
Future<Response> getAllAssetsWithHttpInfo({ String? userId, bool? isFavorite, bool? isArchived, bool? withoutThumbs, num? skip, String? ifNoneMatch, }) async {
// ignore: prefer_const_declarations
final path = r'/asset';
@@ -486,12 +543,18 @@ class AssetApi {
final headerParams = <String, String>{};
final formParams = <String, String>{};
if (userId != null) {
queryParams.addAll(_queryParams('', 'userId', userId));
}
if (isFavorite != null) {
queryParams.addAll(_queryParams('', 'isFavorite', isFavorite));
}
if (isArchived != null) {
queryParams.addAll(_queryParams('', 'isArchived', isArchived));
}
if (withoutThumbs != null) {
queryParams.addAll(_queryParams('', 'withoutThumbs', withoutThumbs));
}
if (skip != null) {
queryParams.addAll(_queryParams('', 'skip', skip));
}
@@ -518,16 +581,21 @@ class AssetApi {
///
/// Parameters:
///
/// * [String] userId:
///
/// * [bool] isFavorite:
///
/// * [bool] isArchived:
///
/// * [bool] withoutThumbs:
/// Include assets without thumbnails
///
/// * [num] skip:
///
/// * [String] ifNoneMatch:
/// ETag of data already cached on the client
Future<List<AssetResponseDto>?> getAllAssets({ bool? isFavorite, bool? isArchived, num? skip, String? ifNoneMatch, }) async {
final response = await getAllAssetsWithHttpInfo( isFavorite: isFavorite, isArchived: isArchived, skip: skip, ifNoneMatch: ifNoneMatch, );
Future<List<AssetResponseDto>?> getAllAssets({ String? userId, bool? isFavorite, bool? isArchived, bool? withoutThumbs, num? skip, String? ifNoneMatch, }) async {
final response = await getAllAssetsWithHttpInfo( userId: userId, isFavorite: isFavorite, isArchived: isArchived, withoutThumbs: withoutThumbs, skip: skip, ifNoneMatch: ifNoneMatch, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -591,13 +659,13 @@ class AssetApi {
///
/// Parameters:
///
/// * [String] assetId (required):
/// * [String] id (required):
///
/// * [String] key:
Future<Response> getAssetByIdWithHttpInfo(String assetId, { String? key, }) async {
Future<Response> getAssetByIdWithHttpInfo(String id, { String? key, }) async {
// ignore: prefer_const_declarations
final path = r'/asset/assetById/{assetId}'
.replaceAll('{assetId}', assetId);
final path = r'/asset/assetById/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
@@ -628,11 +696,11 @@ class AssetApi {
///
/// Parameters:
///
/// * [String] assetId (required):
/// * [String] id (required):
///
/// * [String] key:
Future<AssetResponseDto?> getAssetById(String assetId, { String? key, }) async {
final response = await getAssetByIdWithHttpInfo(assetId, key: key, );
Future<AssetResponseDto?> getAssetById(String id, { String? key, }) async {
final response = await getAssetByIdWithHttpInfo(id, key: key, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -828,18 +896,18 @@ class AssetApi {
return null;
}
/// Performs an HTTP 'GET /asset/thumbnail/{assetId}' operation and returns the [Response].
/// Performs an HTTP 'GET /asset/thumbnail/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] assetId (required):
/// * [String] id (required):
///
/// * [ThumbnailFormat] format:
///
/// * [String] key:
Future<Response> getAssetThumbnailWithHttpInfo(String assetId, { ThumbnailFormat? format, String? key, }) async {
Future<Response> getAssetThumbnailWithHttpInfo(String id, { ThumbnailFormat? format, String? key, }) async {
// ignore: prefer_const_declarations
final path = r'/asset/thumbnail/{assetId}'
.replaceAll('{assetId}', assetId);
final path = r'/asset/thumbnail/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
@@ -871,13 +939,13 @@ class AssetApi {
/// Parameters:
///
/// * [String] assetId (required):
/// * [String] id (required):
///
/// * [ThumbnailFormat] format:
///
/// * [String] key:
Future<MultipartFile?> getAssetThumbnail(String assetId, { ThumbnailFormat? format, String? key, }) async {
final response = await getAssetThumbnailWithHttpInfo(assetId, format: format, key: key, );
Future<MultipartFile?> getAssetThumbnail(String id, { ThumbnailFormat? format, String? key, }) async {
final response = await getAssetThumbnailWithHttpInfo(id, format: format, key: key, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -983,7 +1051,11 @@ class AssetApi {
/// Parameters:
///
/// * [bool] isFavorite:
Future<Response> getMapMarkersWithHttpInfo({ bool? isFavorite, }) async {
///
/// * [DateTime] fileCreatedAfter:
///
/// * [DateTime] fileCreatedBefore:
Future<Response> getMapMarkersWithHttpInfo({ bool? isFavorite, DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, }) async {
// ignore: prefer_const_declarations
final path = r'/asset/map-marker';
@@ -997,6 +1069,12 @@ class AssetApi {
if (isFavorite != null) {
queryParams.addAll(_queryParams('', 'isFavorite', isFavorite));
}
if (fileCreatedAfter != null) {
queryParams.addAll(_queryParams('', 'fileCreatedAfter', fileCreatedAfter));
}
if (fileCreatedBefore != null) {
queryParams.addAll(_queryParams('', 'fileCreatedBefore', fileCreatedBefore));
}
const contentTypes = <String>[];
@@ -1015,8 +1093,12 @@ class AssetApi {
/// Parameters:
///
/// * [bool] isFavorite:
Future<List<MapMarkerResponseDto>?> getMapMarkers({ bool? isFavorite, }) async {
final response = await getMapMarkersWithHttpInfo( isFavorite: isFavorite, );
///
/// * [DateTime] fileCreatedAfter:
///
/// * [DateTime] fileCreatedBefore:
Future<List<MapMarkerResponseDto>?> getMapMarkers({ bool? isFavorite, DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, }) async {
final response = await getMapMarkersWithHttpInfo( isFavorite: isFavorite, fileCreatedAfter: fileCreatedAfter, fileCreatedBefore: fileCreatedBefore, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -1194,20 +1276,20 @@ class AssetApi {
return null;
}
/// Performs an HTTP 'GET /asset/file/{assetId}' operation and returns the [Response].
/// Performs an HTTP 'GET /asset/file/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] assetId (required):
/// * [String] id (required):
///
/// * [bool] isThumb:
///
/// * [bool] isWeb:
///
/// * [String] key:
Future<Response> serveFileWithHttpInfo(String assetId, { bool? isThumb, bool? isWeb, String? key, }) async {
Future<Response> serveFileWithHttpInfo(String id, { bool? isThumb, bool? isWeb, String? key, }) async {
// ignore: prefer_const_declarations
final path = r'/asset/file/{assetId}'
.replaceAll('{assetId}', assetId);
final path = r'/asset/file/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
@@ -1242,15 +1324,15 @@ class AssetApi {
/// Parameters:
///
/// * [String] assetId (required):
/// * [String] id (required):
///
/// * [bool] isThumb:
///
/// * [bool] isWeb:
///
/// * [String] key:
Future<MultipartFile?> serveFile(String assetId, { bool? isThumb, bool? isWeb, String? key, }) async {
final response = await serveFileWithHttpInfo(assetId, isThumb: isThumb, isWeb: isWeb, key: key, );
Future<MultipartFile?> serveFile(String id, { bool? isThumb, bool? isWeb, String? key, }) async {
final response = await serveFileWithHttpInfo(id, isThumb: isThumb, isWeb: isWeb, key: key, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -1270,13 +1352,13 @@ class AssetApi {
///
/// Parameters:
///
/// * [String] assetId (required):
/// * [String] id (required):
///
/// * [UpdateAssetDto] updateAssetDto (required):
Future<Response> updateAssetWithHttpInfo(String assetId, UpdateAssetDto updateAssetDto,) async {
Future<Response> updateAssetWithHttpInfo(String id, UpdateAssetDto updateAssetDto,) async {
// ignore: prefer_const_declarations
final path = r'/asset/{assetId}'
.replaceAll('{assetId}', assetId);
final path = r'/asset/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody = updateAssetDto;
@@ -1303,11 +1385,11 @@ class AssetApi {
///
/// Parameters:
///
/// * [String] assetId (required):
/// * [String] id (required):
///
/// * [UpdateAssetDto] updateAssetDto (required):
Future<AssetResponseDto?> updateAsset(String assetId, UpdateAssetDto updateAssetDto,) async {
final response = await updateAssetWithHttpInfo(assetId, updateAssetDto,);
Future<AssetResponseDto?> updateAsset(String id, UpdateAssetDto updateAssetDto,) async {
final response = await updateAssetWithHttpInfo(id, updateAssetDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -1332,9 +1414,9 @@ class AssetApi {
///
/// * [String] deviceId (required):
///
/// * [String] fileCreatedAt (required):
/// * [DateTime] fileCreatedAt (required):
///
/// * [String] fileModifiedAt (required):
/// * [DateTime] fileModifiedAt (required):
///
/// * [bool] isFavorite (required):
///
@@ -1344,12 +1426,14 @@ class AssetApi {
///
/// * [MultipartFile] livePhotoData:
///
/// * [MultipartFile] sidecarData:
///
/// * [bool] isArchived:
///
/// * [bool] isVisible:
///
/// * [String] duration:
Future<Response> uploadFileWithHttpInfo(AssetTypeEnum assetType, MultipartFile assetData, String deviceAssetId, String deviceId, String fileCreatedAt, String fileModifiedAt, bool isFavorite, String fileExtension, { String? key, MultipartFile? livePhotoData, bool? isArchived, bool? isVisible, String? duration, }) async {
Future<Response> uploadFileWithHttpInfo(AssetTypeEnum assetType, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, bool isFavorite, String fileExtension, { String? key, MultipartFile? livePhotoData, MultipartFile? sidecarData, bool? isArchived, bool? isVisible, String? duration, }) async {
// ignore: prefer_const_declarations
final path = r'/asset/upload';
@@ -1382,6 +1466,11 @@ class AssetApi {
mp.fields[r'livePhotoData'] = livePhotoData.field;
mp.files.add(livePhotoData);
}
if (sidecarData != null) {
hasFields = true;
mp.fields[r'sidecarData'] = sidecarData.field;
mp.files.add(sidecarData);
}
if (deviceAssetId != null) {
hasFields = true;
mp.fields[r'deviceAssetId'] = parameterToString(deviceAssetId);
@@ -1443,9 +1532,9 @@ class AssetApi {
///
/// * [String] deviceId (required):
///
/// * [String] fileCreatedAt (required):
/// * [DateTime] fileCreatedAt (required):
///
/// * [String] fileModifiedAt (required):
/// * [DateTime] fileModifiedAt (required):
///
/// * [bool] isFavorite (required):
///
@@ -1455,13 +1544,15 @@ class AssetApi {
///
/// * [MultipartFile] livePhotoData:
///
/// * [MultipartFile] sidecarData:
///
/// * [bool] isArchived:
///
/// * [bool] isVisible:
///
/// * [String] duration:
Future<AssetFileUploadResponseDto?> uploadFile(AssetTypeEnum assetType, MultipartFile assetData, String deviceAssetId, String deviceId, String fileCreatedAt, String fileModifiedAt, bool isFavorite, String fileExtension, { String? key, MultipartFile? livePhotoData, bool? isArchived, bool? isVisible, String? duration, }) async {
final response = await uploadFileWithHttpInfo(assetType, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, isFavorite, fileExtension, key: key, livePhotoData: livePhotoData, isArchived: isArchived, isVisible: isVisible, duration: duration, );
Future<AssetFileUploadResponseDto?> uploadFile(AssetTypeEnum assetType, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, bool isFavorite, String fileExtension, { String? key, MultipartFile? livePhotoData, MultipartFile? sidecarData, bool? isArchived, bool? isVisible, String? duration, }) async {
final response = await uploadFileWithHttpInfo(assetType, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, isFavorite, fileExtension, key: key, livePhotoData: livePhotoData, sidecarData: sidecarData, isArchived: isArchived, isVisible: isVisible, duration: duration, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}

View File

@@ -16,58 +16,6 @@ class ShareApi {
final ApiClient apiClient;
/// Performs an HTTP 'PATCH /share/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
///
/// * [EditSharedLinkDto] editSharedLinkDto (required):
Future<Response> editSharedLinkWithHttpInfo(String id, EditSharedLinkDto editSharedLinkDto,) async {
// ignore: prefer_const_declarations
final path = r'/share/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody = editSharedLinkDto;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/json'];
return apiClient.invokeAPI(
path,
'PATCH',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [String] id (required):
///
/// * [EditSharedLinkDto] editSharedLinkDto (required):
Future<SharedLinkResponseDto?> editSharedLink(String id, EditSharedLinkDto editSharedLinkDto,) async {
final response = await editSharedLinkWithHttpInfo(id, editSharedLinkDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'SharedLinkResponseDto',) as SharedLinkResponseDto;
}
return null;
}
/// Performs an HTTP 'GET /share' operation and returns the [Response].
Future<Response> getAllSharedLinksWithHttpInfo() async {
// ignore: prefer_const_declarations
@@ -250,4 +198,56 @@ class ShareApi {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
}
/// Performs an HTTP 'PATCH /share/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
///
/// * [EditSharedLinkDto] editSharedLinkDto (required):
Future<Response> updateSharedLinkWithHttpInfo(String id, EditSharedLinkDto editSharedLinkDto,) async {
// ignore: prefer_const_declarations
final path = r'/share/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody = editSharedLinkDto;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/json'];
return apiClient.invokeAPI(
path,
'PATCH',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [String] id (required):
///
/// * [EditSharedLinkDto] editSharedLinkDto (required):
Future<SharedLinkResponseDto?> updateSharedLink(String id, EditSharedLinkDto editSharedLinkDto,) async {
final response = await updateSharedLinkWithHttpInfo(id, editSharedLinkDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'SharedLinkResponseDto',) as SharedLinkResponseDto;
}
return null;
}
}

View File

@@ -20,7 +20,7 @@ class TagApi {
/// Parameters:
///
/// * [CreateTagDto] createTagDto (required):
Future<Response> createWithHttpInfo(CreateTagDto createTagDto,) async {
Future<Response> createTagWithHttpInfo(CreateTagDto createTagDto,) async {
// ignore: prefer_const_declarations
final path = r'/tag';
@@ -48,8 +48,8 @@ class TagApi {
/// Parameters:
///
/// * [CreateTagDto] createTagDto (required):
Future<TagResponseDto?> create(CreateTagDto createTagDto,) async {
final response = await createWithHttpInfo(createTagDto,);
Future<TagResponseDto?> createTag(CreateTagDto createTagDto,) async {
final response = await createTagWithHttpInfo(createTagDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -67,7 +67,7 @@ class TagApi {
/// Parameters:
///
/// * [String] id (required):
Future<Response> deleteWithHttpInfo(String id,) async {
Future<Response> deleteTagWithHttpInfo(String id,) async {
// ignore: prefer_const_declarations
final path = r'/tag/{id}'
.replaceAll('{id}', id);
@@ -96,15 +96,15 @@ class TagApi {
/// Parameters:
///
/// * [String] id (required):
Future<void> delete(String id,) async {
final response = await deleteWithHttpInfo(id,);
Future<void> deleteTag(String id,) async {
final response = await deleteTagWithHttpInfo(id,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
}
/// Performs an HTTP 'GET /tag' operation and returns the [Response].
Future<Response> findAllWithHttpInfo() async {
Future<Response> getAllTagsWithHttpInfo() async {
// ignore: prefer_const_declarations
final path = r'/tag';
@@ -129,8 +129,8 @@ class TagApi {
);
}
Future<List<TagResponseDto>?> findAll() async {
final response = await findAllWithHttpInfo();
Future<List<TagResponseDto>?> getAllTags() async {
final response = await getAllTagsWithHttpInfo();
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -147,11 +147,62 @@ class TagApi {
return null;
}
/// Performs an HTTP 'GET /tag/{id}/assets' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
Future<Response> getTagAssetsWithHttpInfo(String id,) async {
// ignore: prefer_const_declarations
final path = r'/tag/{id}/assets'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>[];
return apiClient.invokeAPI(
path,
'GET',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [String] id (required):
Future<List<AssetResponseDto>?> getTagAssets(String id,) async {
final response = await getTagAssetsWithHttpInfo(id,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
final responseBody = await _decodeBodyBytes(response);
return (await apiClient.deserializeAsync(responseBody, 'List<AssetResponseDto>') as List)
.cast<AssetResponseDto>()
.toList();
}
return null;
}
/// Performs an HTTP 'GET /tag/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
Future<Response> findOneWithHttpInfo(String id,) async {
Future<Response> getTagByIdWithHttpInfo(String id,) async {
// ignore: prefer_const_declarations
final path = r'/tag/{id}'
.replaceAll('{id}', id);
@@ -180,8 +231,8 @@ class TagApi {
/// Parameters:
///
/// * [String] id (required):
Future<TagResponseDto?> findOne(String id,) async {
final response = await findOneWithHttpInfo(id,);
Future<TagResponseDto?> getTagById(String id,) async {
final response = await getTagByIdWithHttpInfo(id,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -195,13 +246,123 @@ class TagApi {
return null;
}
/// Performs an HTTP 'PUT /tag/{id}/assets' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
///
/// * [AssetIdsDto] assetIdsDto (required):
Future<Response> tagAssetsWithHttpInfo(String id, AssetIdsDto assetIdsDto,) async {
// ignore: prefer_const_declarations
final path = r'/tag/{id}/assets'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody = assetIdsDto;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/json'];
return apiClient.invokeAPI(
path,
'PUT',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [String] id (required):
///
/// * [AssetIdsDto] assetIdsDto (required):
Future<List<AssetIdsResponseDto>?> tagAssets(String id, AssetIdsDto assetIdsDto,) async {
final response = await tagAssetsWithHttpInfo(id, assetIdsDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
final responseBody = await _decodeBodyBytes(response);
return (await apiClient.deserializeAsync(responseBody, 'List<AssetIdsResponseDto>') as List)
.cast<AssetIdsResponseDto>()
.toList();
}
return null;
}
/// Performs an HTTP 'DELETE /tag/{id}/assets' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
///
/// * [AssetIdsDto] assetIdsDto (required):
Future<Response> untagAssetsWithHttpInfo(String id, AssetIdsDto assetIdsDto,) async {
// ignore: prefer_const_declarations
final path = r'/tag/{id}/assets'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody = assetIdsDto;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/json'];
return apiClient.invokeAPI(
path,
'DELETE',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [String] id (required):
///
/// * [AssetIdsDto] assetIdsDto (required):
Future<List<AssetIdsResponseDto>?> untagAssets(String id, AssetIdsDto assetIdsDto,) async {
final response = await untagAssetsWithHttpInfo(id, assetIdsDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
final responseBody = await _decodeBodyBytes(response);
return (await apiClient.deserializeAsync(responseBody, 'List<AssetIdsResponseDto>') as List)
.cast<AssetIdsResponseDto>()
.toList();
}
return null;
}
/// Performs an HTTP 'PATCH /tag/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
///
/// * [UpdateTagDto] updateTagDto (required):
Future<Response> updateWithHttpInfo(String id, UpdateTagDto updateTagDto,) async {
Future<Response> updateTagWithHttpInfo(String id, UpdateTagDto updateTagDto,) async {
// ignore: prefer_const_declarations
final path = r'/tag/{id}'
.replaceAll('{id}', id);
@@ -232,8 +393,8 @@ class TagApi {
/// * [String] id (required):
///
/// * [UpdateTagDto] updateTagDto (required):
Future<TagResponseDto?> update(String id, UpdateTagDto updateTagDto,) async {
final response = await updateWithHttpInfo(id, updateTagDto,);
Future<TagResponseDto?> updateTag(String id, UpdateTagDto updateTagDto,) async {
final response = await updateTagWithHttpInfo(id, updateTagDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}

View File

@@ -203,6 +203,14 @@ class ApiClient {
return AlbumResponseDto.fromJson(value);
case 'AllJobStatusResponseDto':
return AllJobStatusResponseDto.fromJson(value);
case 'AssetBulkUploadCheckDto':
return AssetBulkUploadCheckDto.fromJson(value);
case 'AssetBulkUploadCheckItem':
return AssetBulkUploadCheckItem.fromJson(value);
case 'AssetBulkUploadCheckResponseDto':
return AssetBulkUploadCheckResponseDto.fromJson(value);
case 'AssetBulkUploadCheckResult':
return AssetBulkUploadCheckResult.fromJson(value);
case 'AssetCountByTimeBucket':
return AssetCountByTimeBucket.fromJson(value);
case 'AssetCountByTimeBucketResponseDto':
@@ -211,6 +219,10 @@ class ApiClient {
return AssetCountByUserIdResponseDto.fromJson(value);
case 'AssetFileUploadResponseDto':
return AssetFileUploadResponseDto.fromJson(value);
case 'AssetIdsDto':
return AssetIdsDto.fromJson(value);
case 'AssetIdsResponseDto':
return AssetIdsResponseDto.fromJson(value);
case 'AssetResponseDto':
return AssetResponseDto.fromJson(value);
case 'AssetTypeEnum':
@@ -267,6 +279,8 @@ class ApiClient {
return JobCountsDto.fromJson(value);
case 'JobName':
return JobNameTypeTransformer().decode(value);
case 'JobSettingsDto':
return JobSettingsDto.fromJson(value);
case 'JobStatusDto':
return JobStatusDto.fromJson(value);
case 'LoginCredentialDto':
@@ -329,6 +343,8 @@ class ApiClient {
return SystemConfigDto.fromJson(value);
case 'SystemConfigFFmpegDto':
return SystemConfigFFmpegDto.fromJson(value);
case 'SystemConfigJobDto':
return SystemConfigJobDto.fromJson(value);
case 'SystemConfigOAuthDto':
return SystemConfigOAuthDto.fromJson(value);
case 'SystemConfigPasswordLoginDto':

View File

@@ -28,7 +28,7 @@ class AdminSignupResponseDto {
String lastName;
String createdAt;
DateTime createdAt;
@override
bool operator ==(Object other) => identical(this, other) || other is AdminSignupResponseDto &&
@@ -56,7 +56,7 @@ class AdminSignupResponseDto {
json[r'email'] = this.email;
json[r'firstName'] = this.firstName;
json[r'lastName'] = this.lastName;
json[r'createdAt'] = this.createdAt;
json[r'createdAt'] = this.createdAt.toUtc().toIso8601String();
return json;
}
@@ -83,7 +83,7 @@ class AdminSignupResponseDto {
email: mapValueOfType<String>(json, r'email')!,
firstName: mapValueOfType<String>(json, r'firstName')!,
lastName: mapValueOfType<String>(json, r'lastName')!,
createdAt: mapValueOfType<String>(json, r'createdAt')!,
createdAt: mapDateTime(json, r'createdAt', '')!,
);
}
return null;

View File

@@ -34,9 +34,9 @@ class AlbumResponseDto {
String albumName;
String createdAt;
DateTime createdAt;
String updatedAt;
DateTime updatedAt;
String? albumThumbnailAssetId;
@@ -86,8 +86,8 @@ class AlbumResponseDto {
json[r'id'] = this.id;
json[r'ownerId'] = this.ownerId;
json[r'albumName'] = this.albumName;
json[r'createdAt'] = this.createdAt;
json[r'updatedAt'] = this.updatedAt;
json[r'createdAt'] = this.createdAt.toUtc().toIso8601String();
json[r'updatedAt'] = this.updatedAt.toUtc().toIso8601String();
if (this.albumThumbnailAssetId != null) {
json[r'albumThumbnailAssetId'] = this.albumThumbnailAssetId;
} else {
@@ -123,8 +123,8 @@ class AlbumResponseDto {
id: mapValueOfType<String>(json, r'id')!,
ownerId: mapValueOfType<String>(json, r'ownerId')!,
albumName: mapValueOfType<String>(json, r'albumName')!,
createdAt: mapValueOfType<String>(json, r'createdAt')!,
updatedAt: mapValueOfType<String>(json, r'updatedAt')!,
createdAt: mapDateTime(json, r'createdAt', '')!,
updatedAt: mapDateTime(json, r'updatedAt', '')!,
albumThumbnailAssetId: mapValueOfType<String>(json, r'albumThumbnailAssetId'),
shared: mapValueOfType<bool>(json, r'shared')!,
sharedUsers: UserResponseDto.listFromJson(json[r'sharedUsers']),

View File

@@ -13,74 +13,80 @@ part of openapi.api;
class AllJobStatusResponseDto {
/// Returns a new [AllJobStatusResponseDto] instance.
AllJobStatusResponseDto({
required this.thumbnailGenerationQueue,
required this.metadataExtractionQueue,
required this.videoConversionQueue,
required this.objectTaggingQueue,
required this.clipEncodingQueue,
required this.storageTemplateMigrationQueue,
required this.backgroundTaskQueue,
required this.searchQueue,
required this.recognizeFacesQueue,
required this.thumbnailGeneration,
required this.metadataExtraction,
required this.videoConversion,
required this.objectTagging,
required this.clipEncoding,
required this.storageTemplateMigration,
required this.backgroundTask,
required this.search,
required this.recognizeFaces,
required this.sidecar,
});
JobStatusDto thumbnailGenerationQueue;
JobStatusDto thumbnailGeneration;
JobStatusDto metadataExtractionQueue;
JobStatusDto metadataExtraction;
JobStatusDto videoConversionQueue;
JobStatusDto videoConversion;
JobStatusDto objectTaggingQueue;
JobStatusDto objectTagging;
JobStatusDto clipEncodingQueue;
JobStatusDto clipEncoding;
JobStatusDto storageTemplateMigrationQueue;
JobStatusDto storageTemplateMigration;
JobStatusDto backgroundTaskQueue;
JobStatusDto backgroundTask;
JobStatusDto searchQueue;
JobStatusDto search;
JobStatusDto recognizeFacesQueue;
JobStatusDto recognizeFaces;
JobStatusDto sidecar;
@override
bool operator ==(Object other) => identical(this, other) || other is AllJobStatusResponseDto &&
other.thumbnailGenerationQueue == thumbnailGenerationQueue &&
other.metadataExtractionQueue == metadataExtractionQueue &&
other.videoConversionQueue == videoConversionQueue &&
other.objectTaggingQueue == objectTaggingQueue &&
other.clipEncodingQueue == clipEncodingQueue &&
other.storageTemplateMigrationQueue == storageTemplateMigrationQueue &&
other.backgroundTaskQueue == backgroundTaskQueue &&
other.searchQueue == searchQueue &&
other.recognizeFacesQueue == recognizeFacesQueue;
other.thumbnailGeneration == thumbnailGeneration &&
other.metadataExtraction == metadataExtraction &&
other.videoConversion == videoConversion &&
other.objectTagging == objectTagging &&
other.clipEncoding == clipEncoding &&
other.storageTemplateMigration == storageTemplateMigration &&
other.backgroundTask == backgroundTask &&
other.search == search &&
other.recognizeFaces == recognizeFaces &&
other.sidecar == sidecar;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(thumbnailGenerationQueue.hashCode) +
(metadataExtractionQueue.hashCode) +
(videoConversionQueue.hashCode) +
(objectTaggingQueue.hashCode) +
(clipEncodingQueue.hashCode) +
(storageTemplateMigrationQueue.hashCode) +
(backgroundTaskQueue.hashCode) +
(searchQueue.hashCode) +
(recognizeFacesQueue.hashCode);
(thumbnailGeneration.hashCode) +
(metadataExtraction.hashCode) +
(videoConversion.hashCode) +
(objectTagging.hashCode) +
(clipEncoding.hashCode) +
(storageTemplateMigration.hashCode) +
(backgroundTask.hashCode) +
(search.hashCode) +
(recognizeFaces.hashCode) +
(sidecar.hashCode);
@override
String toString() => 'AllJobStatusResponseDto[thumbnailGenerationQueue=$thumbnailGenerationQueue, metadataExtractionQueue=$metadataExtractionQueue, videoConversionQueue=$videoConversionQueue, objectTaggingQueue=$objectTaggingQueue, clipEncodingQueue=$clipEncodingQueue, storageTemplateMigrationQueue=$storageTemplateMigrationQueue, backgroundTaskQueue=$backgroundTaskQueue, searchQueue=$searchQueue, recognizeFacesQueue=$recognizeFacesQueue]';
String toString() => 'AllJobStatusResponseDto[thumbnailGeneration=$thumbnailGeneration, metadataExtraction=$metadataExtraction, videoConversion=$videoConversion, objectTagging=$objectTagging, clipEncoding=$clipEncoding, storageTemplateMigration=$storageTemplateMigration, backgroundTask=$backgroundTask, search=$search, recognizeFaces=$recognizeFaces, sidecar=$sidecar]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'thumbnail-generation-queue'] = this.thumbnailGenerationQueue;
json[r'metadata-extraction-queue'] = this.metadataExtractionQueue;
json[r'video-conversion-queue'] = this.videoConversionQueue;
json[r'object-tagging-queue'] = this.objectTaggingQueue;
json[r'clip-encoding-queue'] = this.clipEncodingQueue;
json[r'storage-template-migration-queue'] = this.storageTemplateMigrationQueue;
json[r'background-task-queue'] = this.backgroundTaskQueue;
json[r'search-queue'] = this.searchQueue;
json[r'recognize-faces-queue'] = this.recognizeFacesQueue;
json[r'thumbnailGeneration'] = this.thumbnailGeneration;
json[r'metadataExtraction'] = this.metadataExtraction;
json[r'videoConversion'] = this.videoConversion;
json[r'objectTagging'] = this.objectTagging;
json[r'clipEncoding'] = this.clipEncoding;
json[r'storageTemplateMigration'] = this.storageTemplateMigration;
json[r'backgroundTask'] = this.backgroundTask;
json[r'search'] = this.search;
json[r'recognizeFaces'] = this.recognizeFaces;
json[r'sidecar'] = this.sidecar;
return json;
}
@@ -103,15 +109,16 @@ class AllJobStatusResponseDto {
}());
return AllJobStatusResponseDto(
thumbnailGenerationQueue: JobStatusDto.fromJson(json[r'thumbnail-generation-queue'])!,
metadataExtractionQueue: JobStatusDto.fromJson(json[r'metadata-extraction-queue'])!,
videoConversionQueue: JobStatusDto.fromJson(json[r'video-conversion-queue'])!,
objectTaggingQueue: JobStatusDto.fromJson(json[r'object-tagging-queue'])!,
clipEncodingQueue: JobStatusDto.fromJson(json[r'clip-encoding-queue'])!,
storageTemplateMigrationQueue: JobStatusDto.fromJson(json[r'storage-template-migration-queue'])!,
backgroundTaskQueue: JobStatusDto.fromJson(json[r'background-task-queue'])!,
searchQueue: JobStatusDto.fromJson(json[r'search-queue'])!,
recognizeFacesQueue: JobStatusDto.fromJson(json[r'recognize-faces-queue'])!,
thumbnailGeneration: JobStatusDto.fromJson(json[r'thumbnailGeneration'])!,
metadataExtraction: JobStatusDto.fromJson(json[r'metadataExtraction'])!,
videoConversion: JobStatusDto.fromJson(json[r'videoConversion'])!,
objectTagging: JobStatusDto.fromJson(json[r'objectTagging'])!,
clipEncoding: JobStatusDto.fromJson(json[r'clipEncoding'])!,
storageTemplateMigration: JobStatusDto.fromJson(json[r'storageTemplateMigration'])!,
backgroundTask: JobStatusDto.fromJson(json[r'backgroundTask'])!,
search: JobStatusDto.fromJson(json[r'search'])!,
recognizeFaces: JobStatusDto.fromJson(json[r'recognizeFaces'])!,
sidecar: JobStatusDto.fromJson(json[r'sidecar'])!,
);
}
return null;
@@ -159,15 +166,16 @@ class AllJobStatusResponseDto {
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'thumbnail-generation-queue',
'metadata-extraction-queue',
'video-conversion-queue',
'object-tagging-queue',
'clip-encoding-queue',
'storage-template-migration-queue',
'background-task-queue',
'search-queue',
'recognize-faces-queue',
'thumbnailGeneration',
'metadataExtraction',
'videoConversion',
'objectTagging',
'clipEncoding',
'storageTemplateMigration',
'backgroundTask',
'search',
'recognizeFaces',
'sidecar',
};
}

View File

@@ -23,9 +23,9 @@ class APIKeyResponseDto {
String name;
String createdAt;
DateTime createdAt;
String updatedAt;
DateTime updatedAt;
@override
bool operator ==(Object other) => identical(this, other) || other is APIKeyResponseDto &&
@@ -49,8 +49,8 @@ class APIKeyResponseDto {
final json = <String, dynamic>{};
json[r'id'] = this.id;
json[r'name'] = this.name;
json[r'createdAt'] = this.createdAt;
json[r'updatedAt'] = this.updatedAt;
json[r'createdAt'] = this.createdAt.toUtc().toIso8601String();
json[r'updatedAt'] = this.updatedAt.toUtc().toIso8601String();
return json;
}
@@ -75,8 +75,8 @@ class APIKeyResponseDto {
return APIKeyResponseDto(
id: mapValueOfType<String>(json, r'id')!,
name: mapValueOfType<String>(json, r'name')!,
createdAt: mapValueOfType<String>(json, r'createdAt')!,
updatedAt: mapValueOfType<String>(json, r'updatedAt')!,
createdAt: mapDateTime(json, r'createdAt', '')!,
updatedAt: mapDateTime(json, r'updatedAt', '')!,
);
}
return null;

Some files were not shown because too many files have changed in this diff Show More