Compare commits

..

20 Commits

Author SHA1 Message Date
renovate[bot] f8ec3e9dbd chore(deps): update machine-learning 2026-05-18 17:31:37 +00:00
shenlong 9cffcc9f4e refactor: migrate network config (#28471) 2026-05-18 16:22:42 +00:00
shenlong 40925f0a06 refactor: immich form and text input (#28479)
refacotr: immich form

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-05-18 16:21:36 +00:00
Oliver Roed Schøler 0544d22902 feat: Selectable metadata in duplicates utility with diffing (#26328) 2026-05-18 17:49:51 +02:00
Jason Rasmussen 3d075f2bf8 feat: workflows & plugins (#26727)
feat: plugins

chore: better types

feat: plugins
2026-05-18 11:09:33 -04:00
Luis Nachtigall 7384799f19 fix(mobile): asset viewer stuck on spinner after rotation (#28019) 2026-05-18 20:32:51 +05:30
Alex 4a7f06e8fd feat: upload and add local asset directly to album (#28123)
* feat: manually upload local assets to album

* feat: manually upload local assets to album

* refactor

* Upload status

* pr feedback
2026-05-18 20:31:22 +05:30
Lauritz Tieste 8f662fc459 refactor: enhance shared link UI and functionality (#26464)
* feat(shared-link): enhance shared link UI and functionality with new expiry options and improved layout

* rebase & cleanup

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-05-18 20:29:56 +05:30
Benjamin Nguyen 24b1dae9f2 feat(mobile): "Add Tags" asset multiselect option (#26269)
* add bulk_tag_assets_action_button to general_bottom_sheet.widget

include create tag tile in 'Add Tags' action modal

* follow provider -> svc -> repo pattern for tags

* rebase and cleanup

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-05-18 20:29:09 +05:30
Lauritz Tieste 3a3469a5f9 feat(ui): add ImmichURLInput (#27105)
feat(ui): implement shared URL input configuration and update input fields
2026-05-18 20:28:57 +05:30
Adam Gastineau 7993619ed2 fix(ios): respect status bar scroll to top in timeline views (#28469)
* fix(ios): respect status bar scroll to top in library views

* Make sure to wrap all loading states in Scaffold
2026-05-18 20:28:01 +05:30
shenlong 4d1f6f869b chore: cleanup mobile mise config (#28473)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-05-18 19:18:52 +05:30
Yaros 3eb03f7934 chore: update readmes to match main (#28458) 2026-05-17 13:08:27 -05:00
Alex 03ed3daa31 chore: improve mobile slideshow (#28460) 2026-05-17 10:54:21 -05:00
Min Idzelis 02581e81a7 fix(web): work around Chrome HDR image seam lines during zoom (#27715)
Change-Id: Ic5a5b1a476c2af93b465ef23dabc601a6a6a6964

Co-authored-by: Alex <alex.tran1502@gmail.com>
2026-05-16 02:15:24 +00:00
Santo Shakil 3ab3d5cf43 fix(mobile): don't force-unwrap nil localizedTitle in ios getAlbums (#28452)
crashes on ios 26 when a PHAssetCollection returns nil for
localizedTitle. fall back to localIdentifier. ref #28428
2026-05-15 18:12:28 -05:00
Ben Beckford 0ef04d9baa feat(mobile): slideshow view (#28421)
* feat(mobile): slideshow view

* move slideshow settings to metadata store

* remove watch in initState

* wrap progress bar in safearea

* show slideshow button on remote albums

* fix crash on unknown assets

* always show slideshow option

* add zoom effect

* add padding to slideshow settings

* chore: styling tweak

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
2026-05-15 18:12:04 -05:00
Santo Shakil df016f9228 fix(mobile): mounted check in ThumbnailTile hero flight listener (#28451)
When the user pops back from the asset viewer mid-flight, the hero
animation can fire its status listener after _ThumbnailTileState has
been disposed. setState then throws a null check on State._element.

Guard the listener with `if (!mounted) return;` — same pattern as
#28300 in the album sync action.
2026-05-15 21:41:04 +00:00
Santo Shakil 17779c1e74 fix(mobile): cronet thumbnail buffer overflow regression from #28439 (#28450)
The hybrid added in onReadCompleted reuses Cronet's ByteBuffer between
reads to save a JNI wrap call when no grow is needed. That reuse breaks
advance() — Cronet's position() is cumulative across reads, so the same
K bytes get counted on every subsequent iteration. b.offset overshoots
b.capacity, the reuse branch keeps firing on a now-empty buffer, and
request.read() throws the original IllegalArgumentException again.

Always pass a fresh wrap from wrapRemaining() so byteBuffer.position()
reflects only this iteration's bytes. Same shape as the original PR
had before the broken optimization was layered on top.
2026-05-15 17:25:31 -04:00
Santo Shakil 01d6a244d8 fix(mobile): cronet buffer overflow on compressed thumbnails (#28439)
CronetImageFetcher sized the response buffer from Content-Length, which is
the compressed wire size. Cronet auto-decompresses gzip/br responses and
writes decompressed bytes into the buffer, exceeding it and throwing
IllegalArgumentException: ByteBuffer is already full on the next read. Use
the growable path; Content-Length becomes an initial alloc hint only,
capped at 128 MB so an untrusted server can't overflow Int.MAX_VALUE or
OOM us upfront. Reuse Cronet's ByteBuffer between reads when no grow is
needed.
2026-05-15 14:48:23 -04:00
242 changed files with 9841 additions and 9195 deletions
@@ -16,7 +16,7 @@ services:
- ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
- /etc/localtime:/etc/localtime:ro
- pnpm_store_server:/buildcache/pnpm-store
- ../packages/plugins:/build/corePlugin
- ../packages/plugin-core:/build/plugins/immich-plugin-core
immich-web:
env_file: !reset []
immich-machine-learning:
+10 -14
View File
@@ -62,9 +62,6 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
defaults:
run:
working-directory: ./server
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
@@ -84,7 +81,7 @@ jobs:
github_token: ${{ steps.token.outputs.token }}
- name: Run ci-unit
run: mise run ci-unit
run: mise run //server:ci-unit
cli-unit-tests:
name: Unit Test CLI
@@ -380,7 +377,7 @@ jobs:
cache-dependency-path: '**/pnpm-lock.yaml'
- name: Setup packages
run: pnpm --filter "@immich/*" install --frozen-lockfile && pnpm --filter "@immich/*" build
run: pnpm --filter @immich/sdk --filter @immich/cli install --frozen-lockfile && pnpm --filter @immich/sdk --filter @immich/cli build
- name: Run setup web
run: pnpm install --frozen-lockfile && pnpm exec svelte-kit sync
@@ -678,7 +675,6 @@ jobs:
- name: Install server dependencies
run: SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm --filter immich install --frozen-lockfile
- name: Run API generation
run: mise //:open-api
working-directory: open-api
@@ -717,9 +713,6 @@ jobs:
--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
ports:
- 5432:5432
defaults:
run:
working-directory: ./server
steps:
- id: token
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
@@ -741,18 +734,21 @@ jobs:
- name: Install server dependencies
run: SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm install --frozen-lockfile
- name: Build plugins
run: mise //:plugins
- name: Build the app
run: pnpm build
run: mise //server:build
- name: Run existing migrations
run: pnpm migrations:run
run: pnpm --filter immich migrations:run
- name: Test npm run schema:reset command works
run: pnpm schema:reset
run: pnpm --filter immich schema:reset
- name: Generate new migrations
continue-on-error: true
run: pnpm migrations:generate src/TestMigration
run: pnpm --filter migrations:generate src/TestMigration
- name: Find file changes
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
@@ -768,7 +764,7 @@ jobs:
run: |
echo "ERROR: Generated migration files not up to date!"
echo "Changed files: ${CHANGED_FILES}"
cat ./src/*-TestMigration.ts
cat ./server/src/*-TestMigration.ts
exit 1
- name: Run SQL generation
+1 -1
View File
@@ -74,7 +74,7 @@ services:
- ${UPLOAD_LOCATION}/photos:/data
- /etc/localtime:/etc/localtime:ro
- pnpm_store_server:/buildcache/pnpm-store
- ../packages/plugins:/build/corePlugin
- ../packages/plugin-core:/build/plugins/immich-plugin-core
env_file:
- .env
environment:
+1 -1
View File
@@ -18,7 +18,7 @@ make e2e
Before you can run the tests, you need to run the following commands _once_:
- `pnpm install`
- `pnpm --filter "@immich/*" build`
- `pnpm --filter @immich/sdk --filter @immich/cli build`
- `mise //:open-api`
Once the test environment is running, the e2e tests can be run via:
+26 -8
View File
@@ -22,13 +22,12 @@
"add_birthday": "Add a birthday",
"add_endpoint": "Add endpoint",
"add_exclusion_pattern": "Add exclusion pattern",
"add_filter": "Add filter",
"add_filter_description": "Click to add a filter condition",
"add_location": "Add location",
"add_more_users": "Add more users",
"add_partner": "Add partner",
"add_path": "Add path",
"add_photos": "Add photos",
"add_step": "Add step",
"add_tag": "Add tag",
"add_to": "Add to…",
"add_to_album": "Add to album",
@@ -42,7 +41,6 @@
"add_to_shared_album": "Add to shared album",
"add_upload_to_stack": "Add upload to stack",
"add_url": "Add URL",
"add_workflow_step": "Add workflow step",
"added_to_archive": "Added to archive",
"added_to_favorites": "Added to favorites",
"added_to_favorites_count": "Added {count, number} to favorites",
@@ -733,6 +731,7 @@
"cannot_update_the_description": "Cannot update the description",
"cast": "Cast",
"cast_description": "Configure available cast destinations",
"change": "Change",
"change_date": "Change date",
"change_description": "Change description",
"change_display_order": "Change display order",
@@ -761,6 +760,7 @@
"check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.",
"check_logs": "Check Logs",
"checksum": "Checksum",
"choose": "Choose",
"choose_matching_people_to_merge": "Choose matching people to merge",
"city": "City",
"cleanup_confirm_description": "Immich found {count} assets (created before {date}) safely backed up to the server. Remove the local copies from this device?",
@@ -778,6 +778,7 @@
"clear": "Clear",
"clear_all": "Clear all",
"clear_all_recent_searches": "Clear all recent searches",
"clear_failed_count": "Clear failed ({count})",
"clear_file_cache": "Clear File Cache",
"clear_message": "Clear message",
"clear_value": "Clear value",
@@ -809,6 +810,7 @@
"comments_are_disabled": "Comments are disabled",
"common_create_new_album": "Create new album",
"completed": "Completed",
"configuration": "Configuration",
"confirm": "Confirm",
"confirm_admin_password": "Confirm Admin Password",
"confirm_delete_face": "Are you sure you want to delete {name} face from the asset?",
@@ -823,6 +825,7 @@
"contain": "Contain",
"context": "Context",
"continue": "Continue",
"control_bottom_app_bar_add_tags": "Add Tags",
"control_bottom_app_bar_create_new_album": "Create new album",
"control_bottom_app_bar_delete_from_immich": "Delete from Immich",
"control_bottom_app_bar_delete_from_local": "Delete from device",
@@ -894,6 +897,7 @@
"date_of_birth": "Date of birth",
"date_of_birth_saved": "Date of birth saved successfully",
"date_range": "Date range",
"date_time_original": "Date/Time Original",
"day": "Day",
"days": "Days",
"deduplicate_all": "Deduplicate All",
@@ -1074,6 +1078,7 @@
"failed_to_remove_product_key": "Failed to remove product key",
"failed_to_reset_pin_code": "Failed to reset PIN code",
"failed_to_stack_assets": "Failed to stack assets",
"failed_to_tag_assets": "Failed to tag assets",
"failed_to_unstack_assets": "Failed to un-stack assets",
"failed_to_update_notification_status": "Failed to update notification status",
"incorrect_email_or_password": "Incorrect email or password",
@@ -1193,11 +1198,13 @@
"export_as_json": "Export as JSON",
"export_database": "Export Database",
"export_database_description": "Export the SQLite database",
"exposure_time": "Exposure Time",
"extension": "Extension",
"external": "External",
"external_libraries": "External Libraries",
"external_network": "External network",
"external_network_sheet_info": "When not on the preferred Wi-Fi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom",
"f_number": "F-Number",
"face_unassigned": "Unassigned",
"failed": "Failed",
"failed_count": "Failed: {count}",
@@ -1215,7 +1222,6 @@
"features_setting_description": "Manage the app features",
"file_name_or_extension": "File name or extension",
"file_name_text": "File name",
"file_name_with_value": "File name: {file_name}",
"file_size": "File size",
"filename": "Filename",
"filetype": "Filetype",
@@ -1228,6 +1234,7 @@
"find_them_fast": "Find them fast by name with search",
"first": "First",
"fix_incorrect_match": "Fix incorrect match",
"focal_length": "Focal Length",
"folder": "Folder",
"folder_not_found": "Folder not found",
"folders": "Folders",
@@ -1348,6 +1355,7 @@
"ios_debug_info_no_sync_yet": "No background sync job has run yet",
"ios_debug_info_processes_queued": "{count, plural, one {{count} background process queued} other {{count} background processes queued}}",
"ios_debug_info_processing_ran_at": "Processing ran {dateTime}",
"iso": "ISO",
"items_count": "{count, plural, one {# item} other {# items}}",
"jobs": "Jobs",
"json_editor": "JSON editor",
@@ -1580,6 +1588,7 @@
"mobile_app": "Mobile App",
"mobile_app_download_onboarding_note": "Download the companion mobile app using the following options",
"model": "Model",
"modify_date": "Modify Date",
"month": "Month",
"more": "More",
"motion": "Motion",
@@ -1628,7 +1637,6 @@
"next": "Next",
"next_memory": "Next memory",
"no": "No",
"no_actions_added": "No actions added yet",
"no_albums_found": "No albums found",
"no_albums_message": "Create an album to organize your photos and videos",
"no_albums_with_name_yet": "It looks like you do not have any albums with this name yet.",
@@ -1645,7 +1653,6 @@
"no_exif_info_available": "No exif info available",
"no_explore_results_message": "Upload more photos to explore your collection.",
"no_favorites_message": "Add favorites to quickly find your best pictures and videos",
"no_filters_added": "No filters added yet",
"no_libraries_message": "Create an external library to view your photos and videos",
"no_local_assets_found": "No local assets found with this checksum",
"no_location_set": "No location set",
@@ -1658,6 +1665,7 @@
"no_results": "No results",
"no_results_description": "Try a synonym or more general keyword",
"no_shared_albums_message": "Create an album to share photos and videos with people in your network",
"no_steps": "No steps added yet",
"no_uploads_in_progress": "No uploads in progress",
"none": "None",
"not_allowed": "Not allowed",
@@ -1703,6 +1711,7 @@
"organize_into_albums": "Organize into albums",
"organize_into_albums_description": "Put existing photos into albums using current sync settings",
"organize_your_library": "Organize your library",
"orientation": "Orientation",
"original": "original",
"other": "Other",
"other_devices": "Other devices",
@@ -1794,6 +1803,8 @@
"play_original_video_setting_description": "Prefer playback of original videos rather than transcoded videos. If original asset is not compatible it may not playback correctly.",
"play_transcoded_video": "Play transcoded video",
"please_auth_to_access": "Please authenticate to access",
"plugin_method_filter_type": "Filter",
"plugin_method_filter_type_description": "This method can filter events and conditionally prevent subsequent steps from running",
"port": "Port",
"preferences_settings_subtitle": "Manage the app's preferences",
"preferences_settings_title": "Preferences",
@@ -1815,6 +1826,7 @@
"profile_drawer_readonly_mode": "Read-only mode enabled. Long-press the user avatar icon to exit.",
"profile_image_of_user": "Profile image of {user}",
"profile_picture_set": "Profile picture set.",
"projection_type": "Projection Type",
"public_album": "Public album",
"public_share": "Public Share",
"purchase_account_info": "Supporter",
@@ -2184,7 +2196,9 @@
"show_in_timeline": "Show in timeline",
"show_in_timeline_setting_description": "Show photos and videos from this user in your timeline",
"show_keyboard_shortcuts": "Show keyboard shortcuts",
"show_less": "Show less",
"show_metadata": "Show metadata",
"show_more_fields": "{count, plural, one {Show # more field} other {Show # more fields}}",
"show_or_hide_info": "Show or hide info",
"show_password": "Show password",
"show_person_options": "Show person options",
@@ -2236,6 +2250,10 @@
"start_date_before_end_date": "Start date must be before end date",
"state": "State",
"status": "Status",
"step_delete": "Delete step",
"step_delete_confirm": "Are you sure you want to delete this step?",
"step_details": "Step details",
"steps": "Steps",
"stop_casting": "Stop casting",
"stop_motion_photo": "Stop Motion Photo",
"stop_photo_sharing": "Stop sharing your photos?",
@@ -2329,7 +2347,7 @@
"trash_page_title": "Trash ({count})",
"trashed_items_will_be_permanently_deleted_after": "Trashed items will be permanently deleted after {days, plural, one {# day} other {# days}}.",
"trigger": "Trigger",
"trigger_asset_uploaded": "Asset Uploaded",
"trigger_asset_uploaded": "Asset Upload",
"trigger_asset_uploaded_description": "Triggered when a new asset is uploaded",
"trigger_description": "An event that kicks off the workflow",
"trigger_person_recognized": "Person Recognized",
@@ -2369,7 +2387,6 @@
"unsupported_field_type": "Unsupported field type",
"unsupported_file_type": "File {file} can't be uploaded because its file type {type} is not supported.",
"untagged": "Untagged",
"untitled_workflow": "Untitled workflow",
"up_next": "Up next",
"update_location_action_prompt": "Update the location of {count} selected assets with:",
"updated_at": "Updated",
@@ -2461,6 +2478,7 @@
"welcome_to_immich": "Welcome to Immich",
"width": "Width",
"wifi_name": "Wi-Fi Name",
"workflow": "Workflow",
"workflow_delete_prompt": "Are you sure you want to delete this workflow?",
"workflow_deleted": "Workflow deleted",
"workflow_description": "Workflow description",
+4 -4
View File
@@ -1,8 +1,8 @@
ARG DEVICE=cpu
FROM python:3.11-bookworm@sha256:970c99f886b839fc8829289040c1845dadaf2cae46b37acc7710333158ec29b4 AS builder-cpu
FROM python:3.11-bookworm@sha256:99f4240b31e5b9cf1e792420390b0d531022af3922b3d15681e7b818ca63fe37 AS builder-cpu
FROM python:3.13-slim-trixie@sha256:d168b8d9eb761f4d3fe305ebd04aeb7e7f2de0297cec5fb2f8f6403244621664 AS builder-openvino
FROM python:3.13-slim-trixie@sha256:dc1546eefcbe8caaa1f004f16ab76b204b5e1dbd58ff81b899f21cd40541232f AS builder-openvino
FROM builder-cpu AS builder-cuda
@@ -39,12 +39,12 @@ RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --frozen --extra ${DEVICE} --no-dev --no-editable --no-install-project --compile-bytecode --no-progress --active --link-mode copy
FROM python:3.11-slim-bookworm@sha256:9c6f90801e6b68e772b7c0ca74260cbf7af9f320acec894e26fccdaccfbe3b47 AS prod-cpu
FROM python:3.11-slim-bookworm@sha256:cd67330292a51e2963156f74ff340455d66b2172e9190e99f40dff9357471177 AS prod-cpu
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2 \
MACHINE_LEARNING_MODEL_ARENA=false
FROM python:3.13-slim-trixie@sha256:d168b8d9eb761f4d3fe305ebd04aeb7e7f2de0297cec5fb2f8f6403244621664 AS prod-openvino
FROM python:3.13-slim-trixie@sha256:dc1546eefcbe8caaa1f004f16ab76b204b5e1dbd58ff81b899f21cd40541232f AS prod-openvino
RUN apt-get update && \
apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \
+400 -354
View File
@@ -2,11 +2,14 @@ version = 1
revision = 3
requires-python = ">=3.11, <4.0"
resolution-markers = [
"python_full_version >= '3.13' and sys_platform == 'darwin'",
"python_full_version >= '3.15' and sys_platform == 'darwin'",
"python_full_version >= '3.13' and python_full_version < '3.15' and sys_platform == 'darwin'",
"python_full_version == '3.12.*' and sys_platform == 'darwin'",
"python_full_version >= '3.13' and platform_machine == 'aarch64' and sys_platform == 'linux'",
"python_full_version >= '3.15' and platform_machine == 'aarch64' and sys_platform == 'linux'",
"python_full_version >= '3.13' and python_full_version < '3.15' and platform_machine == 'aarch64' and sys_platform == 'linux'",
"python_full_version == '3.12.*' and platform_machine == 'aarch64' and sys_platform == 'linux'",
"(python_full_version >= '3.13' and platform_machine != 'aarch64' and sys_platform == 'linux') or (python_full_version >= '3.13' and sys_platform != 'darwin' and sys_platform != 'linux')",
"(python_full_version >= '3.15' and platform_machine != 'aarch64' and sys_platform == 'linux') or (python_full_version >= '3.15' and sys_platform != 'darwin' and sys_platform != 'linux')",
"(python_full_version >= '3.13' and python_full_version < '3.15' and platform_machine != 'aarch64' and sys_platform == 'linux') or (python_full_version >= '3.13' and python_full_version < '3.15' and sys_platform != 'darwin' and sys_platform != 'linux')",
"(python_full_version == '3.12.*' and platform_machine != 'aarch64' and sys_platform == 'linux') or (python_full_version == '3.12.*' and sys_platform != 'darwin' and sys_platform != 'linux')",
"python_full_version < '3.12' and sys_platform == 'darwin'",
"python_full_version < '3.12' and platform_machine == 'aarch64' and sys_platform == 'linux'",
@@ -76,6 +79,46 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/bf/cd/d6d9bb1dadf73e7af02d18225cbd2c93f8552e13130484f1c8dcfece292b/anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee", size = 85481, upload-time = "2023-12-16T17:06:55.989Z" },
]
[[package]]
name = "ast-serialize"
version = "0.5.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/81/9d/09e27731bd5864a9ce04e3244074e674bb8936bf62b45e0357248717adac/ast_serialize-0.5.0.tar.gz", hash = "sha256:5880091bfe6f4f986f22866375c2e884843e7a0b6343ae41aeea659613d879b6", size = 61157, upload-time = "2026-05-17T17:48:29.429Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c0/9a/13dde51ba9e15f8b97957ab7cb0120d0e381524d651c6bd630b9c359227f/ast_serialize-0.5.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8f5c14f169eb0972c0c21bada5358b23d6047c76583b005234f865b11f1fa00a", size = 1183520, upload-time = "2026-05-17T17:47:30.831Z" },
{ url = "https://files.pythonhosted.org/packages/37/de/5a7f0a9fe68944f536632a5af84676739c7d2582be42deb082634bf3a754/ast_serialize-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7d1a2de9de5be04652f0ed60738356ef94f66db37924a9499fffe98dc491aa0b", size = 1175779, upload-time = "2026-05-17T17:47:32.551Z" },
{ url = "https://files.pythonhosted.org/packages/9c/81/0bb853e76e4f6e9a1855d569003c59e19ffac45f7079d91505d1bb212f92/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be5173fb66f9b49026d9d5a2ff0fc7c7009077107c0eb285b2d60fdf1fe10bd1", size = 1233750, upload-time = "2026-05-17T17:47:34.731Z" },
{ url = "https://files.pythonhosted.org/packages/e5/d3/4cf705beeccc08754d0bbda99aefff26110e209b9a07ac8a6b60eec48531/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8015cd071ac1339924ee2b8098c93e00e155f30a16f40ec9816fcf84f4753f6", size = 1235942, upload-time = "2026-05-17T17:47:36.287Z" },
{ url = "https://files.pythonhosted.org/packages/26/c8/ee097e437ea27dd2b8b227865c875492b585650a5802a22d82b304c8201b/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5499e8797edff2a9186aa313ed382c6b422e798e9332d9953badcee6e69a88f2", size = 1442517, upload-time = "2026-05-17T17:47:38.17Z" },
{ url = "https://files.pythonhosted.org/packages/ff/bd/68063442838f1ba68ec72b5436430bc75b3bb17a1a3c3063f09b0c05ae2b/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6848f2a093fb5548751a9a09bff8fcd229e2bbeb0e3331f391b6ae6d26cd9903", size = 1254081, upload-time = "2026-05-17T17:47:39.826Z" },
{ url = "https://files.pythonhosted.org/packages/50/e2/1e520793bc6a4e4524a6ab022391e827825eaa0c3811828bfdc6852eca26/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:832d4c998e0b091fd60a6d6bceee535483c4d490de9ba85003af835225719261", size = 1259910, upload-time = "2026-05-17T17:47:41.369Z" },
{ url = "https://files.pythonhosted.org/packages/4e/e1/49b60f467979979cfe6913b43948ff25bca971ad0591d181812f163a988e/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:16db7c62ec0b8efe1d7afd283a388d8f74f2605d56032e5a37747d2de8dba027", size = 1250678, upload-time = "2026-05-17T17:47:43.702Z" },
{ url = "https://files.pythonhosted.org/packages/74/ba/66ab9555de6275677566f6574e5ef6c29cb185ea866f643bc06f8280a8ee/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:baf5eb061eb5bccade4128ad42da33787d72f6013809cd1b590376ece8b3c937", size = 1301603, upload-time = "2026-05-17T17:47:46.256Z" },
{ url = "https://files.pythonhosted.org/packages/66/42/6aca9b9abc710014b2be9059689e5dd1679339e78f567ffb4d255a9e2050/ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:104e4a35bd7c124173c41760ef9aaea17ddb3f86c65cb643671d59afbe3ee94c", size = 1410332, upload-time = "2026-05-17T17:47:47.899Z" },
{ url = "https://files.pythonhosted.org/packages/47/68/2f76594432a22581ecf878b5e75a9b8601c24b2241cf0bbeb1e21fcf370c/ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:36be371028fc1675acb38a331bde160dbab7ff907fdf00b67eb6911aa106951b", size = 1509979, upload-time = "2026-05-17T17:47:50.942Z" },
{ url = "https://files.pythonhosted.org/packages/40/ac/a93c9b58292653f6c595752f677a08e608f903b710594909e9231a389b3b/ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:061ee58bdb52341c8201a6df41182a977736bae3b7ded87ca7176ca25a8a47ab", size = 1505002, upload-time = "2026-05-17T17:47:54.093Z" },
{ url = "https://files.pythonhosted.org/packages/14/2e/b278f68c497ee2f1d1576cbbef8db5281cd4a5f2db040537592ac9c8862e/ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b15219e9cdc9f53f6f4cb51c009203507228226148c05c5e8fe451c28b435eb3", size = 1456231, upload-time = "2026-05-17T17:47:56.311Z" },
{ url = "https://files.pythonhosted.org/packages/0b/43/419be1c566a4c504cd8fd60ce2f84e790f295495c0f327cfaeadf3d51012/ast_serialize-0.5.0-cp314-cp314t-win32.whl", hash = "sha256:842d1c004bb466c7df036f95fabef789570541922b10976b12f5592a69cf0b38", size = 1058668, upload-time = "2026-05-17T17:47:58.305Z" },
{ url = "https://files.pythonhosted.org/packages/03/6f/c9d4d549295ed05111aeb8853232d1afd9d0a179fddb01eeffbb3a4a6842/ast_serialize-0.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b0c06d760909b095cc466356dfccd05a1c7233a6ca191c020dca2c6a6f16c24c", size = 1101075, upload-time = "2026-05-17T17:48:00.35Z" },
{ url = "https://files.pythonhosted.org/packages/d0/8e/d00c5ab30c58222e07d62956fca86c59d91b9ad32997e633c38b526623a3/ast_serialize-0.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:787baedb0262cc49e8ce37cc15c00ae818e46a165a3b36f5e21ed174998104cb", size = 1075347, upload-time = "2026-05-17T17:48:01.753Z" },
{ url = "https://files.pythonhosted.org/packages/e0/9e/dc2530acb3a60dc6e46d65abf27d1d9f86721694757906a148d90a6860de/ast_serialize-0.5.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:0668aa9459cfa8c9c49ddd2163ebcf43088ba045ef7492af6fe22e0098303101", size = 1191380, upload-time = "2026-05-17T17:48:03.738Z" },
{ url = "https://files.pythonhosted.org/packages/26/0a/bd3d18a582f273d6c843d16bb9e22e9e16365ff7991e92f18f798e9f1224/ast_serialize-0.5.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:bf683d6363edf2b39eed6b6d4fe22d34b6203867a67e27134d9e2a2680c4bc4a", size = 1183879, upload-time = "2026-05-17T17:48:05.463Z" },
{ url = "https://files.pythonhosted.org/packages/40/ae/1f919100f8620887af58fcc381c61a1f218cdf89c6e155f87b213e61010a/ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc22cf0c9be65e71cf88fda130af60d61eb4a79370ad4cfe7900d48a4aa2211", size = 1244529, upload-time = "2026-05-17T17:48:07.008Z" },
{ url = "https://files.pythonhosted.org/packages/c6/ca/6376559dcce707cdbc1d0d9a13c8d3baaaa501e949ce0ebdc4230cd881aa/ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f66173891548c9f2726bf27957b41cabce12fa679dc6da505ddbde4d4b3b31cf", size = 1240560, upload-time = "2026-05-17T17:48:08.46Z" },
{ url = "https://files.pythonhosted.org/packages/35/b2/a620e206b5aeb7efbf2710336df57d457cffbb3991076bbcc1147ef9abd4/ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e42d729ef2be96a14efbad355093284739e3670ece3e534f82cc8832790911d9", size = 1451172, upload-time = "2026-05-17T17:48:09.922Z" },
{ url = "https://files.pythonhosted.org/packages/fa/e0/4ad5c04c24a40481b2935ce9a0ccdb6023dc8b667167d06ae530cc3512f2/ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b725026bafa801dbd7310eb13a75f0a2e370e7e51b2cb225f9d21fcfadf919ee", size = 1265072, upload-time = "2026-05-17T17:48:11.469Z" },
{ url = "https://files.pythonhosted.org/packages/b2/71/4d1d479aa56d0101c40e17720c3d6ac2af7269ea0487a80b18e7bfd1a5b7/ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b54f60c1d78767a53b67eaa663f0dfac3afe606aa07f1301572f588b73d64809", size = 1270488, upload-time = "2026-05-17T17:48:13.575Z" },
{ url = "https://files.pythonhosted.org/packages/6d/4f/0de1bbe06f6edef9fde4ed12ca8e7b3ec7e6e2bd4e672c5af487f7957665/ast_serialize-0.5.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:27d51654fc240a1e87e742d353d98eb45b75f62f129086b3596ab53df2ac2a43", size = 1260702, upload-time = "2026-05-17T17:48:15.141Z" },
{ url = "https://files.pythonhosted.org/packages/75/61/e00872439cfdddcc3c1b6cdaa6e5d904ba8e26a18807c67c4e14409d0ca8/ast_serialize-0.5.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c36237c46dd1674542f2109740ea5ea485a169bf1431939ada0434e17934", size = 1311182, upload-time = "2026-05-17T17:48:16.779Z" },
{ url = "https://files.pythonhosted.org/packages/76/8e/699a5b955f7926956c95e9e1d74132acad73c2fe7a426f94da89123c20aa/ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1943db345233cc7194a470f13afa9c59772c0b123dea0c9414c4d4ca54369759", size = 1421410, upload-time = "2026-05-17T17:48:18.527Z" },
{ url = "https://files.pythonhosted.org/packages/a9/ae/d5b7626874478997adc7a29ab28accf21e596fb590c944290401dfd0b29e/ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:df1c00022cbbcb064bfaa505aa9c9295362443ce5dacb459d1331d3da353f887", size = 1516587, upload-time = "2026-05-17T17:48:20.133Z" },
{ url = "https://files.pythonhosted.org/packages/0c/ce/b59e02a82d9c4244d64cde502e0b00e83e38816abe19155ceb5437402c7f/ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:cae65289fc456fde04af979a2be09302ef5d8ab92ef23e596d6746dc267ada27", size = 1515171, upload-time = "2026-05-17T17:48:21.921Z" },
{ url = "https://files.pythonhosted.org/packages/8b/38/d8d90042747d05aa08d4efcf1c99035a5f670a6bf4c214d31644392afbca/ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:239a4c354e8d676e9d94631d1d4a64edc6b266f86ff3a5a80aedd344f342c01d", size = 1464668, upload-time = "2026-05-17T17:48:23.544Z" },
{ url = "https://files.pythonhosted.org/packages/dd/51/5b840c4df7334104cecffa28f23904fe81ca89ca223d2450e288de39fd3c/ast_serialize-0.5.0-cp39-abi3-win32.whl", hash = "sha256:143a4ef63285a075871908fda3672dc21864b83a8ec3ee12304aa3e4c5387b9a", size = 1068311, upload-time = "2026-05-17T17:48:25.027Z" },
{ url = "https://files.pythonhosted.org/packages/41/11/ca5672c7d491825bc4cd6702dea106a6b60d928707712ec257c7833ae476/ast_serialize-0.5.0-cp39-abi3-win_amd64.whl", hash = "sha256:cf25572c526add400f26a4750dc6ce0c3bb93fc1f75e7ae0cad4ce4f2cd5c590", size = 1108931, upload-time = "2026-05-17T17:48:26.591Z" },
{ url = "https://files.pythonhosted.org/packages/45/19/cc8bd127d28a43da249aa955cfd164cf8fd534e79e42cea96c4854d72fd0/ast_serialize-0.5.0-cp39-abi3-win_arm64.whl", hash = "sha256:92a31c9c20d25a076edaeec76b128a3535d74a24f340b9a8a7e96c9b86dc9642", size = 1081181, upload-time = "2026-05-17T17:48:28.122Z" },
]
[[package]]
name = "bidict"
version = "0.23.1"
@@ -511,7 +554,7 @@ sdist = { url = "https://files.pythonhosted.org/packages/0a/d2/deb3296d08097fedd
[[package]]
name = "fastapi"
version = "0.136.0"
version = "0.136.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "annotated-doc" },
@@ -520,9 +563,9 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "typing-inspection" },
]
sdist = { url = "https://files.pythonhosted.org/packages/4e/d9/e66315807e41e69e7f6a1b42a162dada2f249c5f06ad3f1a95f84ab336ef/fastapi-0.136.0.tar.gz", hash = "sha256:cf08e067cc66e106e102d9ba659463abfac245200752f8a5b7b1e813de4ff73e", size = 396607, upload-time = "2026-04-16T11:47:13.623Z" }
sdist = { url = "https://files.pythonhosted.org/packages/5d/45/c130091c2dfa061bbfe3150f2a5091ef1adf149f2a8d2ae769ecaf6e99a2/fastapi-0.136.1.tar.gz", hash = "sha256:7af665ad7acfa0a3baf8983d393b6b471b9da10ede59c60045f49fbc89a0fa7f", size = 397448, upload-time = "2026-04-23T16:49:44.046Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/26/a3/0bd5f0cdb0bbc92650e8dc457e9250358411ee5d1b65e42b6632387daf81/fastapi-0.136.0-py3-none-any.whl", hash = "sha256:8793d44ec7378e2be07f8a013cf7f7aa47d6327d0dfe9804862688ec4541a6b4", size = 117556, upload-time = "2026-04-16T11:47:11.922Z" },
{ url = "https://files.pythonhosted.org/packages/5a/ff/2e4eca3ade2c22fe1dea7043b8ee9dabe47753349eb1b56a202de8af6349/fastapi-0.136.1-py3-none-any.whl", hash = "sha256:a6e9d7eeada96c93a4d69cb03836b44fa34e2854accb7244a1ece36cd4781c3f", size = 117683, upload-time = "2026-04-23T16:49:42.437Z" },
]
[[package]]
@@ -874,7 +917,7 @@ wheels = [
[[package]]
name = "huggingface-hub"
version = "1.13.0"
version = "1.15.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "filelock" },
@@ -887,9 +930,9 @@ dependencies = [
{ name = "typer" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/89/ff/ec7ed2eb43bd7ce8bb2233d109cc235c3e807ffe5e469dc09db261fac05e/huggingface_hub-1.13.0.tar.gz", hash = "sha256:f6df2dac5abe82ce2fe05873d10d5ff47bc677d616a2f521f4ee26db9415d9d0", size = 781788, upload-time = "2026-04-30T11:57:33.858Z" }
sdist = { url = "https://files.pythonhosted.org/packages/bb/b6/e22bd20a25299c34b8c5922c1545a6320825b13906eb0f7298edfd034a0b/huggingface_hub-1.15.0.tar.gz", hash = "sha256:28abfdddda3927fd4de6a63cf26ab012498a2c24dae52baf150c5c6edf98a1d5", size = 784100, upload-time = "2026-05-15T11:42:52.149Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/93/db/4b1cdae9460ae1f3ca020cd767f013430ce23eb1d9c890ae3a0609b38d26/huggingface_hub-1.13.0-py3-none-any.whl", hash = "sha256:e942cb50d6a08dd5306688b1ac05bda157fd2fcc88b63dae405f7bd0d3234005", size = 660643, upload-time = "2026-04-30T11:57:31.802Z" },
{ url = "https://files.pythonhosted.org/packages/6e/11/0b64cc9024329b76d7547c19a67604a61d21d3ba678a69d1b220c29d5112/huggingface_hub-1.15.0-py3-none-any.whl", hash = "sha256:a4a59af04cbc41a3fe3fec429b171ef994ef8c971eda10136746f408dd4e3744", size = 663602, upload-time = "2026-05-15T11:42:50.487Z" },
]
[[package]]
@@ -1178,80 +1221,80 @@ wheels = [
[[package]]
name = "librt"
version = "0.9.0"
version = "0.11.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/eb/6b/3d5c13fb3e3c4f43206c8f9dfed13778c2ed4f000bacaa0b7ce3c402a265/librt-0.9.0.tar.gz", hash = "sha256:a0951822531e7aee6e0dfb556b30d5ee36bbe234faf60c20a16c01be3530869d", size = 184368, upload-time = "2026-04-09T16:06:26.173Z" }
sdist = { url = "https://files.pythonhosted.org/packages/40/08/9e7f6b5d2b5bed6ad055cdd5925f192bb403a51280f86b56554d9d0699a2/librt-0.11.0.tar.gz", hash = "sha256:075dc3ef4458a278e0195cbf6ac9d38808d9b906c5a6c7f7f79c3888276a3fb1", size = 200139, upload-time = "2026-05-10T18:17:25.138Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e2/1e/2ec7afcebcf3efea593d13aee18bbcfdd3a243043d848ebf385055e9f636/librt-0.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:90904fac73c478f4b83f4ed96c99c8208b75e6f9a8a1910548f69a00f1eaa671", size = 67155, upload-time = "2026-04-09T16:04:42.933Z" },
{ url = "https://files.pythonhosted.org/packages/18/77/72b85afd4435268338ad4ec6231b3da8c77363f212a0227c1ff3b45e4d35/librt-0.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:789fff71757facc0738e8d89e3b84e4f0251c1c975e85e81b152cdaca927cc2d", size = 69916, upload-time = "2026-04-09T16:04:44.042Z" },
{ url = "https://files.pythonhosted.org/packages/27/fb/948ea0204fbe2e78add6d46b48330e58d39897e425560674aee302dca81c/librt-0.9.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1bf465d1e5b0a27713862441f6467b5ab76385f4ecf8f1f3a44f8aa3c695b4b6", size = 199635, upload-time = "2026-04-09T16:04:45.5Z" },
{ url = "https://files.pythonhosted.org/packages/ac/cd/894a29e251b296a27957856804cfd21e93c194aa131de8bb8032021be07e/librt-0.9.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f819e0c6413e259a17a7c0d49f97f405abadd3c2a316a3b46c6440b7dbbedbb1", size = 211051, upload-time = "2026-04-09T16:04:47.016Z" },
{ url = "https://files.pythonhosted.org/packages/18/8f/dcaed0bc084a35f3721ff2d081158db569d2c57ea07d35623ddaca5cfc8e/librt-0.9.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e0785c2fb4a81e1aece366aa3e2e039f4a4d7d21aaaded5227d7f3c703427882", size = 224031, upload-time = "2026-04-09T16:04:48.207Z" },
{ url = "https://files.pythonhosted.org/packages/03/44/88f6c1ed1132cd418601cc041fbd92fed28b3a09f39de81978e0822d13ff/librt-0.9.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:80b25c7b570a86c03b5da69e665809deb39265476e8e21d96a9328f9762f9990", size = 218069, upload-time = "2026-04-09T16:04:50.025Z" },
{ url = "https://files.pythonhosted.org/packages/a3/90/7d02e981c2db12188d82b4410ff3e35bfdb844b26aecd02233626f46af2b/librt-0.9.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d4d16b608a1c43d7e33142099a75cd93af482dadce0bf82421e91cad077157f4", size = 224857, upload-time = "2026-04-09T16:04:51.684Z" },
{ url = "https://files.pythonhosted.org/packages/ef/c3/c77e706b7215ca32e928d47535cf13dbc3d25f096f84ddf8fbc06693e229/librt-0.9.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:194fc1a32e1e21fe809d38b5faea66cc65eaa00217c8901fbdb99866938adbdb", size = 219865, upload-time = "2026-04-09T16:04:52.949Z" },
{ url = "https://files.pythonhosted.org/packages/52/d1/32b0c1a0eb8461c70c11656c46a29f760b7c7edf3c36d6f102470c17170f/librt-0.9.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8c6bc1384d9738781cfd41d09ad7f6e8af13cfea2c75ece6bd6d2566cdea2076", size = 218451, upload-time = "2026-04-09T16:04:54.174Z" },
{ url = "https://files.pythonhosted.org/packages/74/d1/adfd0f9c44761b1d49b1bec66173389834c33ee2bd3c7fd2e2367f1942d4/librt-0.9.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:15cb151e52a044f06e54ac7f7b47adbfc89b5c8e2b63e1175a9d587c43e8942a", size = 241300, upload-time = "2026-04-09T16:04:55.452Z" },
{ url = "https://files.pythonhosted.org/packages/09/b0/9074b64407712f0003c27f5b1d7655d1438979155f049720e8a1abd9b1a1/librt-0.9.0-cp311-cp311-win32.whl", hash = "sha256:f100bfe2acf8a3689af9d0cc660d89f17286c9c795f9f18f7b62dd1a6b247ae6", size = 55668, upload-time = "2026-04-09T16:04:56.689Z" },
{ url = "https://files.pythonhosted.org/packages/24/19/40b77b77ce80b9389fb03971431b09b6b913911c38d412059e0b3e2a9ef2/librt-0.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:0b73e4266307e51c95e09c0750b7ec383c561d2e97d58e473f6f6a209952fbb8", size = 62976, upload-time = "2026-04-09T16:04:57.733Z" },
{ url = "https://files.pythonhosted.org/packages/70/9d/9fa7a64041e29035cb8c575af5f0e3840be1b97b4c4d9061e0713f171849/librt-0.9.0-cp311-cp311-win_arm64.whl", hash = "sha256:bc5518873822d2faa8ebdd2c1a4d7c8ef47b01a058495ab7924cb65bdbf5fc9a", size = 53502, upload-time = "2026-04-09T16:04:58.806Z" },
{ url = "https://files.pythonhosted.org/packages/bf/90/89ddba8e1c20b0922783cd93ed8e64f34dc05ab59c38a9c7e313632e20ff/librt-0.9.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9b3e3bc363f71bda1639a4ee593cb78f7fbfeacc73411ec0d4c92f00730010a4", size = 68332, upload-time = "2026-04-09T16:05:00.09Z" },
{ url = "https://files.pythonhosted.org/packages/a8/40/7aa4da1fb08bdeeb540cb07bfc8207cb32c5c41642f2594dbd0098a0662d/librt-0.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0a09c2f5869649101738653a9b7ab70cf045a1105ac66cbb8f4055e61df78f2d", size = 70581, upload-time = "2026-04-09T16:05:01.213Z" },
{ url = "https://files.pythonhosted.org/packages/48/ac/73a2187e1031041e93b7e3a25aae37aa6f13b838c550f7e0f06f66766212/librt-0.9.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5ca8e133d799c948db2ab1afc081c333a825b5540475164726dcbf73537e5c2f", size = 203984, upload-time = "2026-04-09T16:05:02.542Z" },
{ url = "https://files.pythonhosted.org/packages/5e/3d/23460d571e9cbddb405b017681df04c142fb1b04cbfce77c54b08e28b108/librt-0.9.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:603138ee838ee1583f1b960b62d5d0007845c5c423feb68e44648b1359014e27", size = 215762, upload-time = "2026-04-09T16:05:04.127Z" },
{ url = "https://files.pythonhosted.org/packages/de/1e/42dc7f8ab63e65b20640d058e63e97fd3e482c1edbda3570d813b4d0b927/librt-0.9.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f4003f70c56a5addd6aa0897f200dd59afd3bf7bcd5b3cce46dd21f925743bc2", size = 230288, upload-time = "2026-04-09T16:05:05.883Z" },
{ url = "https://files.pythonhosted.org/packages/dc/08/ca812b6d8259ad9ece703397f8ad5c03af5b5fedfce64279693d3ce4087c/librt-0.9.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:78042f6facfd98ecb25e9829c7e37cce23363d9d7c83bc5f72702c5059eb082b", size = 224103, upload-time = "2026-04-09T16:05:07.148Z" },
{ url = "https://files.pythonhosted.org/packages/b6/3f/620490fb2fa66ffd44e7f900254bc110ebec8dac6c1b7514d64662570e6f/librt-0.9.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a361c9434a64d70a7dbb771d1de302c0cc9f13c0bffe1cf7e642152814b35265", size = 232122, upload-time = "2026-04-09T16:05:08.386Z" },
{ url = "https://files.pythonhosted.org/packages/e9/83/12864700a1b6a8be458cf5d05db209b0d8e94ae281e7ec261dbe616597b4/librt-0.9.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:dd2c7e082b0b92e1baa4da28163a808672485617bc855cc22a2fd06978fa9084", size = 225045, upload-time = "2026-04-09T16:05:09.707Z" },
{ url = "https://files.pythonhosted.org/packages/fd/1b/845d339c29dc7dbc87a2e992a1ba8d28d25d0e0372f9a0a2ecebde298186/librt-0.9.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7e6274fd33fc5b2a14d41c9119629d3ff395849d8bcbc80cf637d9e8d2034da8", size = 227372, upload-time = "2026-04-09T16:05:10.942Z" },
{ url = "https://files.pythonhosted.org/packages/8d/fe/277985610269d926a64c606f761d58d3db67b956dbbf40024921e95e7fcb/librt-0.9.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5093043afb226ecfa1400120d1ebd4442b4f99977783e4f4f7248879009b227f", size = 248224, upload-time = "2026-04-09T16:05:12.254Z" },
{ url = "https://files.pythonhosted.org/packages/92/1b/ee486d244b8de6b8b5dbaefabe6bfdd4a72e08f6353edf7d16d27114da8d/librt-0.9.0-cp312-cp312-win32.whl", hash = "sha256:9edcc35d1cae9fd5320171b1a838c7da8a5c968af31e82ecc3dff30b4be0957f", size = 55986, upload-time = "2026-04-09T16:05:13.529Z" },
{ url = "https://files.pythonhosted.org/packages/89/7a/ba1737012308c17dc6d5516143b5dce9a2c7ba3474afd54e11f44a4d1ef3/librt-0.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:3cc2917258e131ae5f958a4d872e07555b51cb7466a43433218061c74ef33745", size = 63260, upload-time = "2026-04-09T16:05:14.68Z" },
{ url = "https://files.pythonhosted.org/packages/36/e4/01752c113da15127f18f7bf11142f5640038f062407a611c059d0036c6aa/librt-0.9.0-cp312-cp312-win_arm64.whl", hash = "sha256:90e6d5420fc8a300518d4d2288154ff45005e920425c22cbbfe8330f3f754bd9", size = 53694, upload-time = "2026-04-09T16:05:16.095Z" },
{ url = "https://files.pythonhosted.org/packages/5f/d7/1b3e26fffde1452d82f5666164858a81c26ebe808e7ae8c9c88628981540/librt-0.9.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f29b68cd9714531672db62cc54f6e8ff981900f824d13fa0e00749189e13778e", size = 68367, upload-time = "2026-04-09T16:05:17.243Z" },
{ url = "https://files.pythonhosted.org/packages/a5/5b/c61b043ad2e091fbe1f2d35d14795e545d0b56b03edaa390fa1dcee3d160/librt-0.9.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7d5c8a5929ac325729f6119802070b561f4db793dffc45e9ac750992a4ed4d22", size = 70595, upload-time = "2026-04-09T16:05:18.471Z" },
{ url = "https://files.pythonhosted.org/packages/a3/22/2448471196d8a73370aa2f23445455dc42712c21404081fcd7a03b9e0749/librt-0.9.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:756775d25ec8345b837ab52effee3ad2f3b2dfd6bbee3e3f029c517bd5d8f05a", size = 204354, upload-time = "2026-04-09T16:05:19.593Z" },
{ url = "https://files.pythonhosted.org/packages/ac/5e/39fc4b153c78cfd2c8a2dcb32700f2d41d2312aa1050513183be4540930d/librt-0.9.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b8f5d00b49818f4e2b1667db994488b045835e0ac16fe2f924f3871bd2b8ac5", size = 216238, upload-time = "2026-04-09T16:05:20.868Z" },
{ url = "https://files.pythonhosted.org/packages/d7/42/bc2d02d0fa7badfa63aa8d6dcd8793a9f7ef5a94396801684a51ed8d8287/librt-0.9.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c81aef782380f0f13ead670aae01825eb653b44b046aa0e5ebbb79f76ed4aa11", size = 230589, upload-time = "2026-04-09T16:05:22.305Z" },
{ url = "https://files.pythonhosted.org/packages/c8/7b/e2d95cc513866373692aa5edf98080d5602dd07cabfb9e5d2f70df2f25f7/librt-0.9.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66b58fed90a545328e80d575467244de3741e088c1af928f0b489ebec3ef3858", size = 224610, upload-time = "2026-04-09T16:05:23.647Z" },
{ url = "https://files.pythonhosted.org/packages/31/d5/6cec4607e998eaba57564d06a1295c21b0a0c8de76e4e74d699e627bd98c/librt-0.9.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e78fb7419e07d98c2af4b8567b72b3eaf8cb05caad642e9963465569c8b2d87e", size = 232558, upload-time = "2026-04-09T16:05:25.025Z" },
{ url = "https://files.pythonhosted.org/packages/95/8c/27f1d8d3aaf079d3eb26439bf0b32f1482340c3552e324f7db9dca858671/librt-0.9.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c3786f0f4490a5cd87f1ed6cefae833ad6b1060d52044ce0434a2e85893afd0", size = 225521, upload-time = "2026-04-09T16:05:26.311Z" },
{ url = "https://files.pythonhosted.org/packages/6b/d8/1e0d43b1c329b416017619469b3c3801a25a6a4ef4a1c68332aeaa6f72ca/librt-0.9.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:8494cfc61e03542f2d381e71804990b3931175a29b9278fdb4a5459948778dc2", size = 227789, upload-time = "2026-04-09T16:05:27.624Z" },
{ url = "https://files.pythonhosted.org/packages/2c/b4/d3d842e88610fcd4c8eec7067b0c23ef2d7d3bff31496eded6a83b0f99be/librt-0.9.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:07cf11f769831186eeac424376e6189f20ace4f7263e2134bdb9757340d84d4d", size = 248616, upload-time = "2026-04-09T16:05:29.181Z" },
{ url = "https://files.pythonhosted.org/packages/ec/28/527df8ad0d1eb6c8bdfa82fc190f1f7c4cca5a1b6d7b36aeabf95b52d74d/librt-0.9.0-cp313-cp313-win32.whl", hash = "sha256:850d6d03177e52700af605fd60db7f37dcb89782049a149674d1a9649c2138fd", size = 56039, upload-time = "2026-04-09T16:05:30.709Z" },
{ url = "https://files.pythonhosted.org/packages/f3/a7/413652ad0d92273ee5e30c000fc494b361171177c83e57c060ecd3c21538/librt-0.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:a5af136bfba820d592f86c67affcef9b3ff4d4360ac3255e341e964489b48519", size = 63264, upload-time = "2026-04-09T16:05:31.881Z" },
{ url = "https://files.pythonhosted.org/packages/a4/0a/92c244309b774e290ddb15e93363846ae7aa753d9586b8aad511c5e6145b/librt-0.9.0-cp313-cp313-win_arm64.whl", hash = "sha256:4c4d0440a3a8e31d962340c3e1cc3fc9ee7febd34c8d8f770d06adb947779ea5", size = 53728, upload-time = "2026-04-09T16:05:33.31Z" },
{ url = "https://files.pythonhosted.org/packages/cd/c1/184e539543f06ea2912f4b92a5ffaede4f9b392689e3f00acbf8134bee92/librt-0.9.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:3f05d145df35dca5056a8bc3838e940efebd893a54b3e19b2dda39ceaa299bcb", size = 67830, upload-time = "2026-04-09T16:05:34.517Z" },
{ url = "https://files.pythonhosted.org/packages/f3/ad/23399bdcb7afca819acacdef31b37ee59de261bd66b503a7995c03c4b0dc/librt-0.9.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1c587494461ebd42229d0f1739f3aa34237dd9980623ecf1be8d3bcba79f4499", size = 70280, upload-time = "2026-04-09T16:05:35.649Z" },
{ url = "https://files.pythonhosted.org/packages/9f/0b/4542dc5a2b8772dbf92cafb9194701230157e73c14b017b6961a23598b03/librt-0.9.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b0a2040f801406b93657a70b72fa12311063a319fee72ce98e1524da7200171f", size = 201925, upload-time = "2026-04-09T16:05:36.739Z" },
{ url = "https://files.pythonhosted.org/packages/31/d4/8ee7358b08fd0cfce051ef96695380f09b3c2c11b77c9bfbc367c921cce5/librt-0.9.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f38bc489037eca88d6ebefc9c4d41a4e07c8e8b4de5188a9e6d290273ad7ebb1", size = 212381, upload-time = "2026-04-09T16:05:38.043Z" },
{ url = "https://files.pythonhosted.org/packages/f2/94/a2025fe442abedf8b038038dab3dba942009ad42b38ea064a1a9e6094241/librt-0.9.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3fd278f5e6bf7c75ccd6d12344eb686cc020712683363b66f46ac79d37c799f", size = 227065, upload-time = "2026-04-09T16:05:39.394Z" },
{ url = "https://files.pythonhosted.org/packages/7c/e9/b9fcf6afa909f957cfbbf918802f9dada1bd5d3c1da43d722fd6a310dc3f/librt-0.9.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fcbdf2a9ca24e87bbebb47f1fe34e531ef06f104f98c9ccfc953a3f3344c567a", size = 221333, upload-time = "2026-04-09T16:05:40.999Z" },
{ url = "https://files.pythonhosted.org/packages/ac/7c/ba54cd6aa6a3c8cd12757a6870e0c79a64b1e6327f5248dcff98423f4d43/librt-0.9.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e306d956cfa027fe041585f02a1602c32bfa6bb8ebea4899d373383295a6c62f", size = 229051, upload-time = "2026-04-09T16:05:42.605Z" },
{ url = "https://files.pythonhosted.org/packages/4b/4b/8cfdbad314c8677a0148bf0b70591d6d18587f9884d930276098a235461b/librt-0.9.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:465814ab157986acb9dfa5ccd7df944be5eefc0d08d31ec6e8d88bc71251d845", size = 222492, upload-time = "2026-04-09T16:05:43.842Z" },
{ url = "https://files.pythonhosted.org/packages/1f/d1/2eda69563a1a88706808decdce035e4b32755dbfbb0d05e1a65db9547ed1/librt-0.9.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:703f4ae36d6240bfe24f542bac784c7e4194ec49c3ba5a994d02891649e2d85b", size = 223849, upload-time = "2026-04-09T16:05:45.054Z" },
{ url = "https://files.pythonhosted.org/packages/04/44/b2ed37df6be5b3d42cfe36318e0598e80843d5c6308dd63d0bf4e0ce5028/librt-0.9.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3be322a15ee5e70b93b7a59cfd074614f22cc8c9ff18bd27f474e79137ea8d3b", size = 245001, upload-time = "2026-04-09T16:05:46.34Z" },
{ url = "https://files.pythonhosted.org/packages/47/e7/617e412426df89169dd2a9ed0cc8752d5763336252c65dbf945199915119/librt-0.9.0-cp314-cp314-win32.whl", hash = "sha256:b8da9f8035bb417770b1e1610526d87ad4fc58a2804dc4d79c53f6d2cf5a6eb9", size = 51799, upload-time = "2026-04-09T16:05:47.738Z" },
{ url = "https://files.pythonhosted.org/packages/24/ed/c22ca4db0ca3cbc285e4d9206108746beda561a9792289c3c31281d7e9df/librt-0.9.0-cp314-cp314-win_amd64.whl", hash = "sha256:b8bd70d5d816566a580d193326912f4a76ec2d28a97dc4cd4cc831c0af8e330e", size = 59165, upload-time = "2026-04-09T16:05:49.198Z" },
{ url = "https://files.pythonhosted.org/packages/24/56/875398fafa4cbc8f15b89366fc3287304ddd3314d861f182a4b87595ace0/librt-0.9.0-cp314-cp314-win_arm64.whl", hash = "sha256:fc5758e2b7a56532dc33e3c544d78cbaa9ecf0a0f2a2da2df882c1d6b99a317f", size = 49292, upload-time = "2026-04-09T16:05:50.362Z" },
{ url = "https://files.pythonhosted.org/packages/4c/61/bc448ecbf9b2d69c5cff88fe41496b19ab2a1cbda0065e47d4d0d51c0867/librt-0.9.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:f24b90b0e0c8cc9491fb1693ae91fe17cb7963153a1946395acdbdd5818429a4", size = 70175, upload-time = "2026-04-09T16:05:51.564Z" },
{ url = "https://files.pythonhosted.org/packages/60/f2/c47bb71069a73e2f04e70acbd196c1e5cc411578ac99039a224b98920fd4/librt-0.9.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3fe56e80badb66fdcde06bef81bbaa5bfcf6fbd7aefb86222d9e369c38c6b228", size = 72951, upload-time = "2026-04-09T16:05:52.699Z" },
{ url = "https://files.pythonhosted.org/packages/29/19/0549df59060631732df758e8886d92088da5fdbedb35b80e4643664e8412/librt-0.9.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:527b5b820b47a09e09829051452bb0d1dd2122261254e2a6f674d12f1d793d54", size = 225864, upload-time = "2026-04-09T16:05:53.895Z" },
{ url = "https://files.pythonhosted.org/packages/9d/f8/3b144396d302ac08e50f89e64452c38db84bc7b23f6c60479c5d3abd303c/librt-0.9.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d429bdd4ac0ab17c8e4a8af0ed2a7440b16eba474909ab357131018fe8c7e71", size = 241155, upload-time = "2026-04-09T16:05:55.191Z" },
{ url = "https://files.pythonhosted.org/packages/7a/ce/ee67ec14581de4043e61d05786d2aed6c9b5338816b7859bcf07455c6a9f/librt-0.9.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7202bdcac47d3a708271c4304a474a8605a4a9a4a709e954bf2d3241140aa938", size = 252235, upload-time = "2026-04-09T16:05:56.549Z" },
{ url = "https://files.pythonhosted.org/packages/8a/fa/0ead15daa2b293a54101550b08d4bafe387b7d4a9fc6d2b985602bae69b6/librt-0.9.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0d620e74897f8c2613b3c4e2e9c1e422eb46d2ddd07df540784d44117836af3", size = 244963, upload-time = "2026-04-09T16:05:57.858Z" },
{ url = "https://files.pythonhosted.org/packages/29/68/9fbf9a9aa704ba87689e40017e720aced8d9a4d2b46b82451d8142f91ec9/librt-0.9.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d69fc39e627908f4c03297d5a88d9284b73f4d90b424461e32e8c2485e21c283", size = 257364, upload-time = "2026-04-09T16:05:59.686Z" },
{ url = "https://files.pythonhosted.org/packages/1a/8d/9d60869f1b6716c762e45f66ed945b1e5dd649f7377684c3b176ae424648/librt-0.9.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:c2640e23d2b7c98796f123ffd95cf2022c7777aa8a4a3b98b36c570d37e85eee", size = 247661, upload-time = "2026-04-09T16:06:00.938Z" },
{ url = "https://files.pythonhosted.org/packages/70/ff/a5c365093962310bfdb4f6af256f191085078ffb529b3f0cbebb5b33ebe2/librt-0.9.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:451daa98463b7695b0a30aa56bf637831ea559e7b8101ac2ef6382e8eb15e29c", size = 248238, upload-time = "2026-04-09T16:06:02.537Z" },
{ url = "https://files.pythonhosted.org/packages/a0/3c/2d34365177f412c9e19c0a29f969d70f5343f27634b76b765a54d8b27705/librt-0.9.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:928bd06eca2c2bbf4349e5b817f837509b0604342e65a502de1d50a7570afd15", size = 269457, upload-time = "2026-04-09T16:06:03.833Z" },
{ url = "https://files.pythonhosted.org/packages/bc/cd/de45b239ea3bdf626f982a00c14bfcf2e12d261c510ba7db62c5969a27cd/librt-0.9.0-cp314-cp314t-win32.whl", hash = "sha256:a9c63e04d003bc0fb6a03b348018b9a3002f98268200e22cc80f146beac5dc40", size = 52453, upload-time = "2026-04-09T16:06:05.229Z" },
{ url = "https://files.pythonhosted.org/packages/7f/f9/bfb32ae428aa75c0c533915622176f0a17d6da7b72b5a3c6363685914f70/librt-0.9.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f162af66a2ed3f7d1d161a82ca584efd15acd9c1cff190a373458c32f7d42118", size = 60044, upload-time = "2026-04-09T16:06:06.398Z" },
{ url = "https://files.pythonhosted.org/packages/aa/47/7d70414bcdbb3bc1f458a8d10558f00bbfdb24e5a11740fc8197e12c3255/librt-0.9.0-cp314-cp314t-win_arm64.whl", hash = "sha256:a4b25c6c25cac5d0d9d6d6da855195b254e0021e513e0249f0e3b444dc6e0e61", size = 50009, upload-time = "2026-04-09T16:06:07.995Z" },
{ url = "https://files.pythonhosted.org/packages/fe/87/2bf31fe17587b29e3f93ec31421e2b1e1c3e349b8bf6c7c313dbad1d5340/librt-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:93d95bd45b7d58343d8b90d904450a545144eec19a002511163426f8ab1fae29", size = 141092, upload-time = "2026-05-10T18:15:34.795Z" },
{ url = "https://files.pythonhosted.org/packages/cf/08/5c5bf772920b7ebac6e32bc91a643e0ab3870199c0b542356d3baa83970a/librt-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ee278c769a713638cdacd4c0436d72156e75df3ebc0166ab2b9dc43acc386c9", size = 142035, upload-time = "2026-05-10T18:15:36.242Z" },
{ url = "https://files.pythonhosted.org/packages/06/20/662a03d254e5b000d838e8b345d83303ddb768c080fd488e40634c0fa66b/librt-0.11.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f230cb1cbc9faaa616f9a678f530ebcf186e414b6bcbd88b960e4ba1b92428d5", size = 475022, upload-time = "2026-05-10T18:15:37.56Z" },
{ url = "https://files.pythonhosted.org/packages/de/f3/aa81523e45184c6ec23dc7f63263362ec55f80a09d424c012359ecbe7e35/librt-0.11.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5d63c855d86938d9de93e265c9bd8c705b51ec494de5738340ee93767a686e4b", size = 467273, upload-time = "2026-05-10T18:15:39.182Z" },
{ url = "https://files.pythonhosted.org/packages/6b/6f/59c74b560ca8853834d5501d589c8a2519f4184f273a085ffd0f37a1cc47/librt-0.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f028be9e96a08d31df3479ac80d99be374d17f3b78e4796b3fd3c913d4e89", size = 497083, upload-time = "2026-05-10T18:15:40.634Z" },
{ url = "https://files.pythonhosted.org/packages/fe/7b/5aa4d2c9600a719401160bf7055417df0b2a47439b9d88286ce45e56b65f/librt-0.11.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:258d73a0aa66a055e65b2e4d1b8cdb23b9d132c5bb915d9547d804fcaed116cc", size = 489139, upload-time = "2026-05-10T18:15:41.934Z" },
{ url = "https://files.pythonhosted.org/packages/d6/31/9143803d7da6856a69153785768c4936864430eec0fd9461c3ea527d9922/librt-0.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0827efe7854718f04aaddf6496e96960a956e676fe1d0f04eb41511fd8ad06d5", size = 508442, upload-time = "2026-05-10T18:15:43.206Z" },
{ url = "https://files.pythonhosted.org/packages/2f/5a/bce08184488426bda4ccc2c4964ac048c8f68ae89bd7120082eef4233cfd/librt-0.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7753e57d6e12d019c0d8786f1c09c709f4c3fcc57c3887b24e36e6c06ec938b7", size = 514230, upload-time = "2026-05-10T18:15:44.761Z" },
{ url = "https://files.pythonhosted.org/packages/89/8c/bb5e213d254b7505a0e658da199d8ab719086632ce09eef311ab27976523/librt-0.11.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:11bd19822431cc21af9f27374e7ae2e58103c7d98bda823536a6c47f6bb2bb3d", size = 494231, upload-time = "2026-05-10T18:15:46.308Z" },
{ url = "https://files.pythonhosted.org/packages/9d/fb/541cdad5b1ab1300398c74c4c9a497b88e5074c21b1244c8f49731d3a284/librt-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:22bdf239b219d3993761a148ffa134b19e52e9989c84f845d5d7b71d70a17412", size = 537585, upload-time = "2026-05-10T18:15:47.629Z" },
{ url = "https://files.pythonhosted.org/packages/8f/f2/464bb69295c320cb06bddb4f14a4ec67934ee14b2bffb12b19fb7ab287ba/librt-0.11.0-cp311-cp311-win32.whl", hash = "sha256:46c60b61e308eb535fbd6fa622b1ee1bb2815691c1ad9c98bf7b84952ec3bc8d", size = 100509, upload-time = "2026-05-10T18:15:49.157Z" },
{ url = "https://files.pythonhosted.org/packages/6d/e7/a17ee1788f9e4fbf548c19f4afa07c92089b9e24fef6cb2410863781ef4c/librt-0.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:902e546ff044f579ff1c953ff5fce97b636fe9e3943996b2177710c6ef076f73", size = 118628, upload-time = "2026-05-10T18:15:50.345Z" },
{ url = "https://files.pythonhosted.org/packages/cc/c7/6c766214f9f9903bcfcfbef97d807af8d8f5aa3502d247858ab17582d212/librt-0.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:65ac3bc20f78aa0ee5ae84baa68917f89fef4af63e941084dd019a0d0e749f0c", size = 103122, upload-time = "2026-05-10T18:15:52.068Z" },
{ url = "https://files.pythonhosted.org/packages/8b/d0/07c77e067f0838949b43bd89232c29d72efebb9d2801a9750184eb706b71/librt-0.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b87504f1690a23b9a2cca841191a04f83895d4fc2dd04df91d82b1a04ca2ad46", size = 144147, upload-time = "2026-05-10T18:15:53.227Z" },
{ url = "https://files.pythonhosted.org/packages/7a/24/8493538fa4f62f982686398a5b8f68008138a75086abdea19ade64bf4255/librt-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40071fc5fe0ce8daa6de616702314a01e1250711682b0523d6ab8d4525910cb3", size = 143614, upload-time = "2026-05-10T18:15:54.657Z" },
{ url = "https://files.pythonhosted.org/packages/ff/1e/f8bad050810d9171f34a1648ed910e56814c2ba61639f2bd53c6377ae24b/librt-0.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:137e79445c896a0ea7b265f52d23954e05b64222ee1af69e2cb34219067cbb67", size = 485538, upload-time = "2026-05-10T18:15:56.117Z" },
{ url = "https://files.pythonhosted.org/packages/c0/fe/3594ebfbaf03084ba4b120c9ba5c3183fd938a48725e9bbe6ff0a5159ad8/librt-0.11.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:cca6644054e78746d8d4ef238681f9c34ff8b584fe6b988ecebb8db3b15e622a", size = 479623, upload-time = "2026-05-10T18:15:57.544Z" },
{ url = "https://files.pythonhosted.org/packages/b0/da/5d1876984b3746c85dbd219dbfcb73c85f54ee263fd32e5b2a632ec14571/librt-0.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5b0eea49f5562861ee8d757a32ef7d559c1d35be2aaaa1ec28941d74c9ffc8a", size = 513082, upload-time = "2026-05-10T18:15:58.805Z" },
{ url = "https://files.pythonhosted.org/packages/19/6e/55bdf5d5ca00c3e18430690bf2c953d8d3ffd3c337418173d33dec985dc9/librt-0.11.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0d1029d7e1ae1a7e647ed6fb5df8c4ce2dffefb7a9f5fd1376a4554d96dac09f", size = 508105, upload-time = "2026-05-10T18:16:00.2Z" },
{ url = "https://files.pythonhosted.org/packages/07/10/f1f23a7c595ee90ece4d35c851e5d104b1311a887ed1b4ac4c35bbd13da8/librt-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bc3ce6b33c5828d9e80592011a5c584cb2ce86edbc4088405f70da47dc1d1b3b", size = 522268, upload-time = "2026-05-10T18:16:01.708Z" },
{ url = "https://files.pythonhosted.org/packages/b6/02/5720f5697a7f54b78b3aefbe20df3a48cedcff1276618c4aa481177942ed/librt-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:936c5995f3514a42111f20099397d8177c79b4d7e70961e396c6f5a0a3566766", size = 527348, upload-time = "2026-05-10T18:16:03.496Z" },
{ url = "https://files.pythonhosted.org/packages/50/db/b4a47c6f91db4ff76348a0b3dd0cc65e090a078b765a810a62ff9434c3d3/librt-0.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9bc0ca6ad9381cbe8e4aa6e5726e4c80c78115a6e9723c599ed1d73e092bc49d", size = 516294, upload-time = "2026-05-10T18:16:05.173Z" },
{ url = "https://files.pythonhosted.org/packages/9e/58/9384b2f4eb1ed1d273d40948a7c5c4b2360213b402ef3be4641c06299f9c/librt-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:070aa8c26c0a74774317a72df8851facc7f0f012a5b406557ac56992d92e1ec8", size = 553608, upload-time = "2026-05-10T18:16:06.839Z" },
{ url = "https://files.pythonhosted.org/packages/21/7b/5aa8848a7c6a9278c79375146da1812e695754ceec5f005e6043461a7315/librt-0.11.0-cp312-cp312-win32.whl", hash = "sha256:6bf14feb84b05ae945277395451998c89c54d0def4070eb5c08de544930b245a", size = 101879, upload-time = "2026-05-10T18:16:08.103Z" },
{ url = "https://files.pythonhosted.org/packages/37/33/8a745436944947575b584231750a41417de1a38cf6a2e9251d1065651c09/librt-0.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:75672f0bc524ede266287d532d7923dbce94c7514ad07627bac3d0c6d92cc4d9", size = 119831, upload-time = "2026-05-10T18:16:09.174Z" },
{ url = "https://files.pythonhosted.org/packages/59/67/a6739ac96e28b7855808bdb0370e250606104a859750d209e5a0716fe7ab/librt-0.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c", size = 103470, upload-time = "2026-05-10T18:16:10.369Z" },
{ url = "https://files.pythonhosted.org/packages/82/61/e59168d4d0bf2bf90f4f0caf7a001bfc60254c3af4586013b04dc3ef517b/librt-0.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:78dc31f7fdfe9c9d0eb0e8f42d139db230e826415bbcabd9f0e9faaaee909894", size = 144119, upload-time = "2026-05-10T18:16:11.771Z" },
{ url = "https://files.pythonhosted.org/packages/61/fd/caa1d60b12f7dd79ccea23054e06eeaebe266a5f52c40a6b651069200ce5/librt-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fa475675db22290c3158e1d42326d0f5a65f04f44a0e68c3630a25b53560fb9c", size = 143565, upload-time = "2026-05-10T18:16:13.334Z" },
{ url = "https://files.pythonhosted.org/packages/b8/a9/dc744f5c2b4978d48db970be29f22716d3413d28b14ad99740817315cf2c/librt-0.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:621db29691044bdeda22e789e482e1b0f3a985d90e3426c9c6d17606416205ea", size = 485395, upload-time = "2026-05-10T18:16:14.729Z" },
{ url = "https://files.pythonhosted.org/packages/8f/21/7f8e97a1e4dae952a5a95948f6f8507a173bc1e669f54340bba6ca1ca31b/librt-0.11.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a9010e2ed5b3a9e158c5fd966b3ab7e834bb3d3aacc8f66c91dd4b57a3799230", size = 479383, upload-time = "2026-05-10T18:16:16.321Z" },
{ url = "https://files.pythonhosted.org/packages/a6/6d/d8ee9c114bebf2c50e29ec2aa940826fccb62a645c3e4c18760987d0e16d/librt-0.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c39513d8b7477a2e1ed8c43fc21c524e8d5a0f8d4e8b7b074dbdbe7820a08e2", size = 513010, upload-time = "2026-05-10T18:16:17.647Z" },
{ url = "https://files.pythonhosted.org/packages/f0/43/0b5708af2bd30a46400e72ba6bdaa8f066f15fb9a688527e34220e8d6c06/librt-0.11.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7aef3cf1d5af86e770ab04bfd993dfc4ae8b8c17f66fb77dd4a7d50de7bbb1a3", size = 508433, upload-time = "2026-05-10T18:16:19.309Z" },
{ url = "https://files.pythonhosted.org/packages/4a/50/356187247d09013490481033183b3532b58acf8028bcb34b2b56a375c9b2/librt-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:557183ddc36babe46b27dd60facbd5adb4492181a5be887587d57cda6e092f21", size = 522595, upload-time = "2026-05-10T18:16:20.642Z" },
{ url = "https://files.pythonhosted.org/packages/40/e7/c6ac4240899c7f3248079d5a9900debe0dadb3fdeaf856684c987105ba47/librt-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83d3e1f72bd42f6c5c0b7daec530c3f829bd02db42c70b8ddf0c2d90a2459930", size = 527255, upload-time = "2026-05-10T18:16:22.352Z" },
{ url = "https://files.pythonhosted.org/packages/eb/b5/a81322dbeedeeaf9c1ee6f001734d28a09d8383ac9e6779bc24bbd0743c6/librt-0.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4ce1f21fbe589bc1afd7872dece84fb0e1144f794a288e58a10d2c54a55c43be", size = 516847, upload-time = "2026-05-10T18:16:23.627Z" },
{ url = "https://files.pythonhosted.org/packages/ae/66/6e6323787d592b55204a42595ff1102da5115601b53a7e9ddebc889a6da5/librt-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b09f7044ea2b64c9da42fd3d335666518cfd1c6e8a182c95da73d0214b41e", size = 553920, upload-time = "2026-05-10T18:16:25.025Z" },
{ url = "https://files.pythonhosted.org/packages/9c/21/623f8ca230857102066d9ca8c6c1734995908c4d0d1bee7bb2ef0021cb33/librt-0.11.0-cp313-cp313-win32.whl", hash = "sha256:78fddc31cd4d3caa897ad5d31f856b1faadc9474021ad6cb182b9018793e254e", size = 101898, upload-time = "2026-05-10T18:16:26.649Z" },
{ url = "https://files.pythonhosted.org/packages/b3/1d/b4ebd44dd723f768469007515cb92251e0ae286c94c140f374801140fa74/librt-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ca8aa88751a775870b764e93bad5135385f563cb8dcee399abf034ea4d3cb47", size = 119812, upload-time = "2026-05-10T18:16:27.859Z" },
{ url = "https://files.pythonhosted.org/packages/3b/e4/b2f4ca7965ca373b491cdb4bc25cdb30c1649ca81a8782056a83850292a9/librt-0.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:96f044bb325fd9cf1a723015638c219e9143f0dfbc0ca54c565df2b7fc748b44", size = 103448, upload-time = "2026-05-10T18:16:29.066Z" },
{ url = "https://files.pythonhosted.org/packages/29/eb/dbce197da4e227779e56b5735f2decc3eb36e55a1cdbf1bd65d6639d76c1/librt-0.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4a017a95e5837dc15a8c5661d60e05daa96b90908b1aa6b7acdf443cd25c8ebd", size = 143345, upload-time = "2026-05-10T18:16:30.674Z" },
{ url = "https://files.pythonhosted.org/packages/76/a3/254bebd0c11c8ba684018efb8006ff22e466abce445215cca6c778e7d9de/librt-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b1ecbd9819deccc39b7542bf4d2a740d8a620694d39989e58661d3763458f8d4", size = 143131, upload-time = "2026-05-10T18:16:32.037Z" },
{ url = "https://files.pythonhosted.org/packages/f1/3f/f77d6122d21ac7bf6ae8a7dfced1bd2a7ac545d3273ebdcaf8042f6d619f/librt-0.11.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7da327dacd7be8f8ec36547373550744a3cc0e536d54665cd83f8bcd961200e8", size = 477024, upload-time = "2026-05-10T18:16:33.493Z" },
{ url = "https://files.pythonhosted.org/packages/ac/0a/2c996dadebaa7d9bbbd43ef2d4f3e66b6da545f838a41694ef6172cebec8/librt-0.11.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0dc56b1f8d06e60db362cc3fdae206681817f86ce4725d34511473487f12a34b", size = 474221, upload-time = "2026-05-10T18:16:34.864Z" },
{ url = "https://files.pythonhosted.org/packages/0a/7e/f5d92af8486b8272c23b3e686b46ff72d89c8169585eb61eef01a2ac7147/librt-0.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05fb8fb2ab90e21c8d12ea240d744ad514da9baf381ebfa70d91d20d21713175", size = 505174, upload-time = "2026-05-10T18:16:36.705Z" },
{ url = "https://files.pythonhosted.org/packages/af/1a/cb0734fe86398eb33193ab753b7326255c74cac5eb09e76b9b16536e7adb/librt-0.11.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cae74872be221df4374d10fec61f93ed1513b9546ea84f2c0bf73ab3e9bd0b03", size = 497216, upload-time = "2026-05-10T18:16:38.418Z" },
{ url = "https://files.pythonhosted.org/packages/18/06/094820f91558b66e29943c0ec41c9914f460f48dd51fc503c3101e10842d/librt-0.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:32bcc918c0148eb7e3d57385125bac7e5f9e4359d05f07448b09f6f778c2f31c", size = 513921, upload-time = "2026-05-10T18:16:39.848Z" },
{ url = "https://files.pythonhosted.org/packages/0b/c2/00de9018871a282f530cacb457d5ec0428f6ac7e6fedde9aff7468d9fb04/librt-0.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f9743fc99135d5f78d2454435615f6dec0473ca507c26ce9d92b10b562a280d3", size = 520850, upload-time = "2026-05-10T18:16:41.471Z" },
{ url = "https://files.pythonhosted.org/packages/51/9d/64631832348fd1834fb3a61b996434edddaaf25a31d03b0a76273159d2cf/librt-0.11.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5ba067f4aadae8fda802d91d2124c90c42195ff32d9161d3549e6d05cfe26f96", size = 504237, upload-time = "2026-05-10T18:16:43.15Z" },
{ url = "https://files.pythonhosted.org/packages/a5/ec/ae5525eb16edc827a044e7bb8777a455ff95d4bca9379e7e6bddd7383647/librt-0.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:de3bf945454d032f9e390b85c4072e0a0570bf825421c8be0e71209fa65e1abe", size = 546261, upload-time = "2026-05-10T18:16:44.408Z" },
{ url = "https://files.pythonhosted.org/packages/5a/09/adce371f27ca039411da9659f7430fcc2ba6cd0c7b3e4467a0f091be7fa9/librt-0.11.0-cp314-cp314-win32.whl", hash = "sha256:d2277a05f6dcb9fd13db9566aac4fabd68c3ea1ea46ee5567d4eef8efa495a2f", size = 96965, upload-time = "2026-05-10T18:16:46.039Z" },
{ url = "https://files.pythonhosted.org/packages/d6/ee/8ac720d98548f173c7ce2e632a7ca94673f74cacd5c8162a84af5b35958a/librt-0.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:ab73e8db5e3f564d812c1f5c3a175930a5f9bc96ccb5e3b22a34d7858b401cf7", size = 115151, upload-time = "2026-05-10T18:16:47.133Z" },
{ url = "https://files.pythonhosted.org/packages/94/20/c900cf14efeb09b6bef2b2dff20779f73464b97fd58d1c6bccc379588ae3/librt-0.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aea3caa317752e3a466fa8af45d91ee0ea8c7fdd96e42b0a8dd9b76a7931eba1", size = 98850, upload-time = "2026-05-10T18:16:48.597Z" },
{ url = "https://files.pythonhosted.org/packages/0c/71/944bfe4b64e12abffcd3c15e1cce07f72f3d55655083786285f4dedeb532/librt-0.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d1b36540d7aaf9b9101b3a6f376c8d8e9f7a9aec93ed05918f2c69d493ffef72", size = 151138, upload-time = "2026-05-10T18:16:49.839Z" },
{ url = "https://files.pythonhosted.org/packages/b6/10/99e64a5c86989357fda078c8143c533389585f6473b7439172dd8f3b3b2d/librt-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:efbb343ab2ce3540f4ecbe6315d677ed70f37cd9a72b1e58066c918ca83acbaa", size = 151976, upload-time = "2026-05-10T18:16:51.062Z" },
{ url = "https://files.pythonhosted.org/packages/21/31/5072ad880946d83e5ea4147d6d018c78eefce85b77819b19bdd0ee229435/librt-0.11.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0dd688aab3f7914d3e6e5e3554978e0383312fb8e771d84be008a35b9ee548", size = 557927, upload-time = "2026-05-10T18:16:52.632Z" },
{ url = "https://files.pythonhosted.org/packages/5e/8d/70b5fb7cfbab60edbe7381614ab985da58e144fbf465c86d44c95f43cdca/librt-0.11.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f5fb36b8c6c63fdcbb1d526d94c0d1331610d43f4118cc1beb4efef4f3faacb2", size = 539698, upload-time = "2026-05-10T18:16:53.934Z" },
{ url = "https://files.pythonhosted.org/packages/fa/a3/ba3495a0b3edbd24a4cae0d1d3c64f39a9fc45d06e812101289b50c1a619/librt-0.11.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a9a237d13addb93715b6fee74023d5ee3469b53fce527626c0e088aa585805f", size = 577162, upload-time = "2026-05-10T18:16:55.589Z" },
{ url = "https://files.pythonhosted.org/packages/f7/db/36e25fb81f99937ff1b96612a1dc9fd66f039cb9cc3aee12c01fac31aab9/librt-0.11.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5ddd17bd87b2c56ddd60e546a7984a2e64c4e8eab92fb4cf3830a48ad5469d51", size = 566494, upload-time = "2026-05-10T18:16:56.975Z" },
{ url = "https://files.pythonhosted.org/packages/33/0d/3f622b47f0b013eeb9cf4cc07ae9bfe378d832a4eec998b2b209fe84244d/librt-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd43992b4473d42f12ff9e68326079f0696d9d4e6000e8f39a0238d482ba6ee2", size = 596858, upload-time = "2026-05-10T18:16:58.374Z" },
{ url = "https://files.pythonhosted.org/packages/a9/02/71b90bc93039c46a2000651f6ad60122b114c8f54c4ad306e0e96f5b75ad/librt-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f8e3e8056dd674e279741485e2e512d6e9a751c7455809d0114e6ebf8d781085", size = 590318, upload-time = "2026-05-10T18:16:59.676Z" },
{ url = "https://files.pythonhosted.org/packages/04/04/418cb3f75621e2b761fb1ab0f017f4d70a1a72a6e7c74ee4f7e8d198c2f3/librt-0.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c1f708d8ae9c56cf38a903c44297243d2ec83fd82b396b977e0144a3e76217e3", size = 575115, upload-time = "2026-05-10T18:17:01.007Z" },
{ url = "https://files.pythonhosted.org/packages/cc/2c/5a2183ac58dd911f26b5d7e7d7d8f1d87fcecdddd99d6c12169a258ff62c/librt-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0add982e0e7b9fc14cf4b33789d5f13f66581889b88c2f58099f6ce8f92617bd", size = 617918, upload-time = "2026-05-10T18:17:02.682Z" },
{ url = "https://files.pythonhosted.org/packages/15/1f/dc6771a52592a4451be6effa200cbfc9cec61e4393d3033d81a9d307961d/librt-0.11.0-cp314-cp314t-win32.whl", hash = "sha256:2b481d846ac894c4e8403c5fd0e87c5d11d6499e404b474602508a224ff531c8", size = 103562, upload-time = "2026-05-10T18:17:03.99Z" },
{ url = "https://files.pythonhosted.org/packages/62/4a/7d1415567027286a75ba1093ec4aca11f073e0f559c530cf3e0a757ad55c/librt-0.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:28edb433edde181112a908c78907af28f964eabc15f4dd16c9d66c834302677c", size = 124327, upload-time = "2026-05-10T18:17:05.465Z" },
{ url = "https://files.pythonhosted.org/packages/ce/62/b40b382fa0c66fee1478073eb8db352a4a6beda4a1adccf1df911d8c289c/librt-0.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dee008f20b542e3cd162ba338a7f9ec0f6d23d395f66fe8aeeec3c9d067ea253", size = 102572, upload-time = "2026-05-10T18:17:06.809Z" },
]
[[package]]
name = "locust"
version = "2.43.4"
version = "2.44.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "configargparse" },
@@ -1271,9 +1314,9 @@ dependencies = [
{ name = "typing-extensions", marker = "python_full_version < '3.12'" },
{ name = "werkzeug" },
]
sdist = { url = "https://files.pythonhosted.org/packages/52/be/6df1c778f673e1e2d785f262d20a4e130fdb8e51242466d7ae434b66a587/locust-2.43.4.tar.gz", hash = "sha256:4ace60f07f5fa9bf08d1b64da25915707befca19a790897eed6372656824deee", size = 1434321, upload-time = "2026-04-01T20:43:04.322Z" }
sdist = { url = "https://files.pythonhosted.org/packages/16/03/0fb9e22848c8bda302fd0adb1a8e31e46df1f44abc89ca134cff053c3128/locust-2.44.0.tar.gz", hash = "sha256:338a9fd5389b30df96439baba8299193b5efc1f129763cd9bc6108354fb52547", size = 1436312, upload-time = "2026-05-11T20:42:10.277Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c5/2c/a90d0b6fc476eb0f8e5a705f49e410563450b9b087688cc93a50eab54d63/locust-2.43.4-py3-none-any.whl", hash = "sha256:a4f40403e9f665e0dcb94991d9a8f19317d0d36afe88400833c5fab99ba942ed", size = 1454332, upload-time = "2026-04-01T20:43:02.767Z" },
{ url = "https://files.pythonhosted.org/packages/76/15/e14290a81e92f84c4d8fad0bfcfcf0c2cbbf0b27bf67d7ec593e101dcb90/locust-2.44.0-py3-none-any.whl", hash = "sha256:5dd69aae3dfca8e25c2565e5c4491b21984b41877406b8172ea96cfa9d76c0e5", size = 1457147, upload-time = "2026-05-11T20:42:07.684Z" },
]
[[package]]
@@ -1490,52 +1533,53 @@ wheels = [
[[package]]
name = "mypy"
version = "1.20.1"
version = "2.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "ast-serialize" },
{ name = "librt", marker = "platform_python_implementation != 'PyPy'" },
{ name = "mypy-extensions" },
{ name = "pathspec" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0b/3d/5b373635b3146264eb7a68d09e5ca11c305bbb058dfffbb47c47daf4f632/mypy-1.20.1.tar.gz", hash = "sha256:6fc3f4ecd52de81648fed1945498bf42fa2993ddfad67c9056df36ae5757f804", size = 3815892, upload-time = "2026-04-13T02:46:51.474Z" }
sdist = { url = "https://files.pythonhosted.org/packages/82/15/cca9d88503549ed6fedeaa1d448cdddd542ee8a490232d732e278036fbf2/mypy-2.1.0.tar.gz", hash = "sha256:81e76ad12c2d804512e9b13240d1588316531bfba07558286078bfbce9613633", size = 3898359, upload-time = "2026-05-11T18:37:36.237Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/82/0d/555ab7453cc4a4a8643b7f21c842b1a84c36b15392061ae7b052ee119320/mypy-1.20.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c01eb9bac2c6a962d00f9d23421cd2913840e65bba365167d057bd0b4171a92e", size = 14336012, upload-time = "2026-04-13T02:45:39.935Z" },
{ url = "https://files.pythonhosted.org/packages/57/26/85a28893f7db8a16ebb41d1e9dfcb4475844d06a88480b6639e32a74d6ef/mypy-1.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:55d12ddbd8a9cac5b276878bd534fa39fff5bf543dc6ae18f25d30c8d7d27fca", size = 13224636, upload-time = "2026-04-13T02:45:49.659Z" },
{ url = "https://files.pythonhosted.org/packages/93/41/bd4cd3c2caeb6c448b669222b8cfcbdee4a03b89431527b56fca9e56b6f3/mypy-1.20.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0aa322c1468b6cdfc927a44ce130f79bb44bcd34eb4a009eb9f96571fd80955", size = 13663471, upload-time = "2026-04-13T02:46:20.276Z" },
{ url = "https://files.pythonhosted.org/packages/3e/56/7ee8c471e10402d64b6517ae10434541baca053cffd81090e4097d5609d4/mypy-1.20.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3f8bc95899cf676b6e2285779a08a998cc3a7b26f1026752df9d2741df3c79e8", size = 14532344, upload-time = "2026-04-13T02:46:44.205Z" },
{ url = "https://files.pythonhosted.org/packages/b5/95/b37d1fa859a433f6156742e12f62b0bb75af658544fb6dada9363918743a/mypy-1.20.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:47c2b90191a870a04041e910277494b0d92f0711be9e524d45c074fe60c00b65", size = 14776670, upload-time = "2026-04-13T02:45:52.481Z" },
{ url = "https://files.pythonhosted.org/packages/03/77/b302e4cb0b80d2bdf6bf4fce5864bb4cbfa461f7099cea544eaf2457df78/mypy-1.20.1-cp311-cp311-win_amd64.whl", hash = "sha256:9857dc8d2ec1a392ffbda518075beb00ac58859979c79f9e6bdcb7277082c2f2", size = 10816524, upload-time = "2026-04-13T02:45:37.711Z" },
{ url = "https://files.pythonhosted.org/packages/7f/21/d969d7a68eb964993ebcc6170d5ecaf0cf65830c58ac3344562e16dc42a9/mypy-1.20.1-cp311-cp311-win_arm64.whl", hash = "sha256:09d8df92bb25b6065ab91b178da843dda67b33eb819321679a6e98a907ce0e10", size = 9750419, upload-time = "2026-04-13T02:45:08.542Z" },
{ url = "https://files.pythonhosted.org/packages/69/1b/75a7c825a02781ca10bc2f2f12fba2af5202f6d6005aad8d2d1f264d8d78/mypy-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:36ee2b9c6599c230fea89bbd79f401f9f9f8e9fcf0c777827789b19b7da90f51", size = 14494077, upload-time = "2026-04-13T02:45:55.085Z" },
{ url = "https://files.pythonhosted.org/packages/b0/54/5e5a569ea5c2b4d48b729fb32aa936eeb4246e4fc3e6f5b3d36a2dfbefb9/mypy-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fba3fb0968a7b48806b0c90f38d39296f10766885a94c83bd21399de1e14eb28", size = 13319495, upload-time = "2026-04-13T02:45:29.674Z" },
{ url = "https://files.pythonhosted.org/packages/6f/a4/a1945b19f33e91721b59deee3abb484f2fa5922adc33bb166daf5325d76d/mypy-1.20.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef1415a637cd3627d6304dfbeddbadd21079dafc2a8a753c477ce4fc0c2af54f", size = 13696948, upload-time = "2026-04-13T02:46:15.006Z" },
{ url = "https://files.pythonhosted.org/packages/b2/c6/75e969781c2359b2f9c15b061f28ec6d67c8b61865ceda176e85c8e7f2de/mypy-1.20.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef3461b1ad5cd446e540016e90b5984657edda39f982f4cc45ca317b628f5a37", size = 14706744, upload-time = "2026-04-13T02:46:00.482Z" },
{ url = "https://files.pythonhosted.org/packages/a8/6e/b221b1de981fc4262fe3e0bf9ec272d292dfe42394a689c2d49765c144c4/mypy-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:542dd63c9e1339b6092eb25bd515f3a32a1453aee8c9521d2ddb17dacd840237", size = 14949035, upload-time = "2026-04-13T02:45:06.021Z" },
{ url = "https://files.pythonhosted.org/packages/ca/4b/298ba2de0aafc0da3ff2288da06884aae7ba6489bc247c933f87847c41b3/mypy-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:1d55c7cd8ca22e31f93af2a01160a9e95465b5878de23dba7e48116052f20a8d", size = 10883216, upload-time = "2026-04-13T02:45:47.232Z" },
{ url = "https://files.pythonhosted.org/packages/c7/f9/5e25b8f0b8cb92f080bfed9c21d3279b2a0b6a601cdca369a039ba84789d/mypy-1.20.1-cp312-cp312-win_arm64.whl", hash = "sha256:f5b84a79070586e0d353ee07b719d9d0a4aa7c8ee90c0ea97747e98cbe193019", size = 9814299, upload-time = "2026-04-13T02:45:21.934Z" },
{ url = "https://files.pythonhosted.org/packages/21/e8/ef0991aa24c8f225df10b034f3c2681213cb54cf247623c6dec9a5744e70/mypy-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f3886c03e40afefd327bd70b3f634b39ea82e87f314edaa4d0cce4b927ddcc1", size = 14500739, upload-time = "2026-04-13T02:46:05.442Z" },
{ url = "https://files.pythonhosted.org/packages/23/73/416ebec3047636ed89fa871dc8c54bf05e9e20aa9499da59790d7adb312d/mypy-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e860eb3904f9764e83bafd70c8250bdffdc7dde6b82f486e8156348bf7ceb184", size = 13314735, upload-time = "2026-04-13T02:46:47.154Z" },
{ url = "https://files.pythonhosted.org/packages/10/1e/1505022d9c9ac2e014a384eb17638fb37bf8e9d0a833ea60605b66f8f7ba/mypy-1.20.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4b5aac6e785719da51a84f5d09e9e843d473170a9045b1ea7ea1af86225df4b", size = 13704356, upload-time = "2026-04-13T02:45:19.773Z" },
{ url = "https://files.pythonhosted.org/packages/98/91/275b01f5eba5c467a3318ec214dd865abb66e9c811231c8587287b92876a/mypy-1.20.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f37b6cd0fe2ad3a20f05ace48ca3523fc52ff86940e34937b439613b6854472e", size = 14696420, upload-time = "2026-04-13T02:45:24.205Z" },
{ url = "https://files.pythonhosted.org/packages/a1/57/b3779e134e1b7250d05f874252780d0a88c068bc054bcff99ca20a3a2986/mypy-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4bbb0f6b54ce7cc350ef4a770650d15fa70edd99ad5267e227133eda9c94218", size = 14936093, upload-time = "2026-04-13T02:45:32.087Z" },
{ url = "https://files.pythonhosted.org/packages/be/33/81b64991b0f3f278c3b55c335888794af190b2d59031a5ad1401bcb69f1e/mypy-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:c3dc20f8ec76eecd77148cdd2f1542ed496e51e185713bf488a414f862deb8f2", size = 10889659, upload-time = "2026-04-13T02:46:02.926Z" },
{ url = "https://files.pythonhosted.org/packages/1b/fd/7adcb8053572edf5ef8f3db59599dfeeee3be9cc4c8c97e2d28f66f42ac5/mypy-1.20.1-cp313-cp313-win_arm64.whl", hash = "sha256:a9d62bbac5d6d46718e2b0330b25e6264463ed832722b8f7d4440ff1be3ca895", size = 9815515, upload-time = "2026-04-13T02:46:32.103Z" },
{ url = "https://files.pythonhosted.org/packages/40/cd/db831e84c81d57d4886d99feee14e372f64bbec6a9cb1a88a19e243f2ef5/mypy-1.20.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:12927b9c0ed794daedcf1dab055b6c613d9d5659ac511e8d936d96f19c087d12", size = 14483064, upload-time = "2026-04-13T02:45:26.901Z" },
{ url = "https://files.pythonhosted.org/packages/d5/82/74e62e7097fa67da328ac8ece8de09133448c04d20ddeaeba251a3000f01/mypy-1.20.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:752507dd481e958b2c08fc966d3806c962af5a9433b5bf8f3bdd7175c20e34fe", size = 13335694, upload-time = "2026-04-13T02:46:12.514Z" },
{ url = "https://files.pythonhosted.org/packages/74/c4/97e9a0abe4f3cdbbf4d079cb87a03b786efeccf5bf2b89fe4f96939ab2e6/mypy-1.20.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c614655b5a065e56274c6cbbe405f7cf7e96c0654db7ba39bc680238837f7b08", size = 13726365, upload-time = "2026-04-13T02:45:17.422Z" },
{ url = "https://files.pythonhosted.org/packages/d7/aa/a19d884a8d28fcd3c065776323029f204dbc774e70ec9c85eba228b680de/mypy-1.20.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2c3f6221a76f34d5100c6d35b3ef6b947054123c3f8d6938a4ba00b1308aa572", size = 14693472, upload-time = "2026-04-13T02:46:41.253Z" },
{ url = "https://files.pythonhosted.org/packages/84/44/cc9324bd21cf786592b44bf3b5d224b3923c1230ec9898d508d00241d465/mypy-1.20.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4bdfc06303ac06500af71ea0cdbe995c502b3c9ba32f3f8313523c137a25d1b6", size = 14919266, upload-time = "2026-04-13T02:46:28.37Z" },
{ url = "https://files.pythonhosted.org/packages/6e/dc/779abb25a8c63e8f44bf5a336217fa92790fa17e0c40e0c725d10cb01bbd/mypy-1.20.1-cp314-cp314-win_amd64.whl", hash = "sha256:0131edd7eba289973d1ba1003d1a37c426b85cdef76650cd02da6420898a5eb3", size = 11049713, upload-time = "2026-04-13T02:45:57.673Z" },
{ url = "https://files.pythonhosted.org/packages/28/08/4172be2ad7de9119b5a92ca36abbf641afdc5cb1ef4ae0c3a8182f29674f/mypy-1.20.1-cp314-cp314-win_arm64.whl", hash = "sha256:33f02904feb2c07e1fdf7909026206396c9deeb9e6f34d466b4cfedb0aadbbe4", size = 9999819, upload-time = "2026-04-13T02:46:35.039Z" },
{ url = "https://files.pythonhosted.org/packages/2d/af/af9e46b0c8eabbce9fc04a477564170f47a1c22b308822282a59b7ff315f/mypy-1.20.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:168472149dd8cc505c98cefd21ad77e4257ed6022cd5ed2fe2999bed56977a5a", size = 15547508, upload-time = "2026-04-13T02:46:25.588Z" },
{ url = "https://files.pythonhosted.org/packages/a7/cd/39c9e4ad6ba33e069e5837d772a9e6c304b4a5452a14a975d52b36444650/mypy-1.20.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:eb674600309a8f22790cca883a97c90299f948183ebb210fbef6bcee07cb1986", size = 14399557, upload-time = "2026-04-13T02:46:10.021Z" },
{ url = "https://files.pythonhosted.org/packages/83/c1/3fd71bdc118ffc502bf57559c909927bb7e011f327f7bb8e0488e98a5870/mypy-1.20.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef2b2e4cc464ba9795459f2586923abd58a0055487cbe558cb538ea6e6bc142a", size = 15045789, upload-time = "2026-04-13T02:45:10.81Z" },
{ url = "https://files.pythonhosted.org/packages/8e/73/6f07ff8b57a7d7b3e6e5bf34685d17632382395c8bb53364ec331661f83e/mypy-1.20.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dee461d396dd46b3f0ed5a098dbc9b8860c81c46ad44fa071afcfbc149f167c9", size = 15850795, upload-time = "2026-04-13T02:45:03.349Z" },
{ url = "https://files.pythonhosted.org/packages/ec/e2/f7dffec1c7767078f9e9adf0c786d1fe0ff30964a77eb213c09b8b58cb76/mypy-1.20.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e364926308b3e66f1361f81a566fc1b2f8cd47fc8525e8136d4058a65a4b4f02", size = 16088539, upload-time = "2026-04-13T02:46:17.841Z" },
{ url = "https://files.pythonhosted.org/packages/1a/76/e0dee71035316e75a69d73aec2f03c39c21c967b97e277fd0ef8fd6aec66/mypy-1.20.1-cp314-cp314t-win_amd64.whl", hash = "sha256:a0c17fbd746d38c70cbc42647cfd884f845a9708a4b160a8b4f7e70d41f4d7fa", size = 12575567, upload-time = "2026-04-13T02:45:34.795Z" },
{ url = "https://files.pythonhosted.org/packages/22/a8/7ed43c9d9c3d1468f86605e323a5d97e411a448790a00f07e779f3211a46/mypy-1.20.1-cp314-cp314t-win_arm64.whl", hash = "sha256:db2cb89654626a912efda69c0d5c1d22d948265e2069010d3dde3abf751c7d08", size = 10378823, upload-time = "2026-04-13T02:45:13.35Z" },
{ url = "https://files.pythonhosted.org/packages/d8/28/926bd972388e65a39ee98e188ccf67e81beb3aacfd5d6b310051772d974b/mypy-1.20.1-py3-none-any.whl", hash = "sha256:1aae28507f253fe82d883790d1c0a0d35798a810117c88184097fe8881052f06", size = 2636553, upload-time = "2026-04-13T02:46:30.45Z" },
{ url = "https://files.pythonhosted.org/packages/0a/a1/639f3024794a2a15899cb90707fe02e044c4412794c39c5769fd3df2e2ef/mypy-2.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a683016b16fe2f572dc04c72be7ee0504ac1605a265d0200f5cea695fb788f41", size = 14691685, upload-time = "2026-05-11T18:33:27.973Z" },
{ url = "https://files.pythonhosted.org/packages/3b/08/9a585dea4325f20d8b80dc78623fa50d1fd2173b710f6237afd6ba6ab39b/mypy-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a293c534adb55271fef24a26da04b855540a8c13cc07bc5917b9fd2c394f2ca", size = 13555165, upload-time = "2026-05-11T18:32:16.107Z" },
{ url = "https://files.pythonhosted.org/packages/81/dc/7c42cc9c6cb01e8eb09961f1f738741d3e9c7e9d5c5b30ec69222625cd5f/mypy-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7406f4d048e71e576f5356d317e5b0a9e666dfd966bd99f9d14ca06e1a341538", size = 13994376, upload-time = "2026-05-11T18:32:39.256Z" },
{ url = "https://files.pythonhosted.org/packages/d4/fa/285946c33bce716e082c11dfeee9ee196eaf1f5042efb3581a31f9f205e4/mypy-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e0210d626fc8b31ccc90233754c7bc90e1f43205e85d96387f7db1285b55c398", size = 14864618, upload-time = "2026-05-11T18:34:49.765Z" },
{ url = "https://files.pythonhosted.org/packages/2b/83/82397f48af6c27e295d57979ded8490c9829040152cf7571b2f026aeb9a0/mypy-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3712c20deed54e814eaaa825603bada8ea1c390670a397c95b98405347acc563", size = 15102063, upload-time = "2026-05-11T18:34:05.855Z" },
{ url = "https://files.pythonhosted.org/packages/40/68/b02dec39057b88eb03dc0aa854732e26e8361f34f9d0e20c7614967d1eba/mypy-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fcaa0e479066e31f7cceb6a3bea39cb22b2ff51a6b2f24f193d19179ba17c389", size = 11060564, upload-time = "2026-05-11T18:35:36.494Z" },
{ url = "https://files.pythonhosted.org/packages/cf/a8/ea3dcbef31f99b634f2ee23bb0321cbc8c1b388b76a861eb849f13c347dc/mypy-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:0b1a5260c95aa443083f9ed3592662941951bca3d4ca224a5dc517c38b7cf666", size = 9966983, upload-time = "2026-05-11T18:37:14.139Z" },
{ url = "https://files.pythonhosted.org/packages/95/b1/55861beb5c339b44f9a2ba92df9e2cb1eeb4ae1eee674cdf7772c797778b/mypy-2.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:244358bf1c0da7722230bce60683d52e8e9fd030554926f15b747a84efb5b3af", size = 14874381, upload-time = "2026-05-11T18:37:31.784Z" },
{ url = "https://files.pythonhosted.org/packages/0b/b3/b7f770114b7d0ac92d0f76e8d93c2780844a70488a90e91821927850da86/mypy-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4ec7c57657493c7a75534df2751c8ae2cda383c16ecc55d2106c54476b1b16f6", size = 13665501, upload-time = "2026-05-11T18:34:23.063Z" },
{ url = "https://files.pythonhosted.org/packages/b6/f3/8ae2037967e2126689a0c11d99e2b707134a565191e92c60ca2572aec60a/mypy-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8161b6ff4392410023224f0969d17db93e1e154bc3e4ba62598e720723ae211", size = 14045750, upload-time = "2026-05-11T18:31:48.151Z" },
{ url = "https://files.pythonhosted.org/packages/a0/32/615eb5911859e43d054941b0d0a7d06cfa2870eba86529cf385b052b111c/mypy-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf03e12003084a67395184d3eb8cbd6a489dc3655b5664b28c210a9e2403ab0b", size = 15061630, upload-time = "2026-05-11T18:37:06.898Z" },
{ url = "https://files.pythonhosted.org/packages/d4/03/4eafbfff8bfab1b87082741eae6e6a624028c984e6708b73bce2a8570c9d/mypy-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:20509760fd791c51579d573153407d226385ec1f8bcce55d730b354f3336bc22", size = 15288831, upload-time = "2026-05-11T18:31:18.07Z" },
{ url = "https://files.pythonhosted.org/packages/99/ee/919661478e5891a3c96e549c036e467e64563ab85995b10c53c8358e16a3/mypy-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:6753d0c1fdd6b1a23b9e4f283ce80b2153b724adcb2653b20b85a8a28ac6436b", size = 11135228, upload-time = "2026-05-11T18:34:31.23Z" },
{ url = "https://files.pythonhosted.org/packages/24/0a/6a12b9782ca0831a553192f351679f4548abc9d19a7cc93bb7feb02084c7/mypy-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:98ebb6589bb3b6d0c6f0c459d53ca55b8091fbc13d277c4041c885392e8195e8", size = 10040684, upload-time = "2026-05-11T18:36:48.199Z" },
{ url = "https://files.pythonhosted.org/packages/6e/dd/c7191469c777f07689c032a8f7326e393ea34c92d6d76eb7ce5ba57ea66d/mypy-2.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35aac3bb114e03888f535d5eb51b8bafbb3266586b599da1940f9b1be3ec5bd5", size = 14852174, upload-time = "2026-05-11T18:31:38.929Z" },
{ url = "https://files.pythonhosted.org/packages/55/8c/aed55408879043d72bb9135f4d0d19a02b886dd569631e113e3d2706cb8d/mypy-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8de55a8c861f2a49331f807be98d90caeceeef520bde13d43a160207f8af613e", size = 13651542, upload-time = "2026-05-11T18:36:04.636Z" },
{ url = "https://files.pythonhosted.org/packages/3a/8e/f371a824b1f1fa8ea6e3dbb8703d232977d572be2329554a3bc4d960302f/mypy-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5fdf2941a07434af755837d9880f7d7d25f1dacb1af9dcd4b9b66f2220a3024e", size = 14033929, upload-time = "2026-05-11T18:35:55.742Z" },
{ url = "https://files.pythonhosted.org/packages/94/21/f54be870d6dd53a82c674407e0f8eed7174b05ec78d42e5abd7b42e84fd5/mypy-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e195b817c13f02352a9c124301f9f30f078405444679b6753c1b96b6eed37285", size = 15039200, upload-time = "2026-05-11T18:33:10.281Z" },
{ url = "https://files.pythonhosted.org/packages/17/99/bf21748626a40ce59fd29a39386ab46afec88b7bd2f0fa6c3a97c995523f/mypy-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5431d42af987ebd92ba2f71d45c85ed41d8e6ca9f5fd209a69f68f707d2469e5", size = 15272690, upload-time = "2026-05-11T18:32:07.205Z" },
{ url = "https://files.pythonhosted.org/packages/d6/d7/9e90d2cf47100bea550ed2bc7b0d4de3a62181d84d5e37da0003e8462637/mypy-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:767fe8c66dc3e01e19e1737d4c38ebefead16125e1b8e58ad421903b376f5c65", size = 11147435, upload-time = "2026-05-11T18:33:56.477Z" },
{ url = "https://files.pythonhosted.org/packages/ec/46/e5c449e858798e35ffc90946282a27c62a77be743fe17480e4977374eb91/mypy-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:ecfe70d43775ab99562ab128ce49854a362044c9f894961f68f898c23cb7429d", size = 10035052, upload-time = "2026-05-11T18:32:30.049Z" },
{ url = "https://files.pythonhosted.org/packages/b0/ca/b279a672e874aedd5498ae25f722dacc8aa86bbffb939b3f97cbb1cf6686/mypy-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7354c5a7f69d9345c3d6e69921d57088eea3ddeeb6b20d34c1b3855b02c36ec2", size = 14848422, upload-time = "2026-05-11T18:35:45.984Z" },
{ url = "https://files.pythonhosted.org/packages/27/e6/3efe56c631d959b9b4454e208b0ac4b7f4f58b404c89f8bec7b49efdfc21/mypy-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:49890d4f76ac9e06ec117f9e09f3174da70a620a0c300953d8595c926e80947f", size = 13677374, upload-time = "2026-05-11T18:36:57.188Z" },
{ url = "https://files.pythonhosted.org/packages/84/7f/8107ea87a44fd1f1b59882442f033c9c3488c127201b1d1d15f1cbd6022e/mypy-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:761be68e023ef5d94678772396a8af1220030f80837a3afd8d0aef3b419666f4", size = 14055743, upload-time = "2026-05-11T18:35:18.361Z" },
{ url = "https://files.pythonhosted.org/packages/51/4d/b6d34db183133b83761b9199a82d31557cdbb70a380d8c3b3438e11882a3/mypy-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c90345fc182dc363b891350457ec69c35140858538f38b4540845afcc32b1aef", size = 15020937, upload-time = "2026-05-11T18:34:59.618Z" },
{ url = "https://files.pythonhosted.org/packages/ff/d7/f08360c691d758acb02f45022c34d98b92892f4ea756644e1000d4b9f3d8/mypy-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b84802e7b5a6daf1f5e15bc9fcd7ddae77be13981ffab037f1c67bb84d67d135", size = 15253371, upload-time = "2026-05-11T18:36:41.081Z" },
{ url = "https://files.pythonhosted.org/packages/67/1b/09460a13719530a19bce27bd3bc8449e83569dd2ba7faf51c9c3c30c0b61/mypy-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:022c771234936ceac541ebaf836fe9e2abeb3f5e09aff21588fe543ff006fe21", size = 11326429, upload-time = "2026-05-11T18:34:13.526Z" },
{ url = "https://files.pythonhosted.org/packages/40/62/75dbf0f82f7b6680340efc614af29dd0b3c17b8a4f1cd09b8bd2fd6bc814/mypy-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:498207db725cec88829a6a5c2fc771205fd043719ef98bc49aba8fb9fc4e6d57", size = 10218799, upload-time = "2026-05-11T18:32:23.491Z" },
{ url = "https://files.pythonhosted.org/packages/b2/66/caca04ed7d972fb6eb6dd1ccd6df1de5c38fae8c5b3dc1c4e8e0d85ee6b9/mypy-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7d5e5cad0efeba72b93cd17490cc0d69c5ac9ca132994fe3fb0314808aeeb83e", size = 15923458, upload-time = "2026-05-11T18:35:28.64Z" },
{ url = "https://files.pythonhosted.org/packages/ed/52/2d90cbe49d014b13ed7ff337930c30bad35893fe38a1e4641e756bb62191/mypy-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ff715050c127d724fd260a2e666e7747fdd83511c0c47d449d98238970aef780", size = 14757697, upload-time = "2026-05-11T18:36:14.208Z" },
{ url = "https://files.pythonhosted.org/packages/ac/37/d98f4a14e081b238992d0ed96b6d39c7cc0148c9699eb71eaa68629665ea/mypy-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82208da9e09414d520e912d3e462d454854bed0810b71540bb016dcbca7308fd", size = 15405638, upload-time = "2026-05-11T18:33:48.249Z" },
{ url = "https://files.pythonhosted.org/packages/a3/c2/15c46613b24a84fad2aea1248bf9619b99c2767ae9071fe224c179a0b7d4/mypy-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e79ebc1b904b84f0310dff7469655a9c36c7a68bddb37bdd42b67a332df61d08", size = 16215852, upload-time = "2026-05-11T18:32:50.296Z" },
{ url = "https://files.pythonhosted.org/packages/5c/90/9c16a57f482c76d25f6379762b56bbf65c711d8158cf271fb2802cfb0640/mypy-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e583edc957cfb0deb142079162ae826f58449b116c1d442f2d91c69d9fced081", size = 16452695, upload-time = "2026-05-11T18:33:38.182Z" },
{ url = "https://files.pythonhosted.org/packages/0f/4c/215a4eeb63cacc5f17f516691ea7285d11e249802b942476bff15922a314/mypy-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b33b6cd332695bba180d55e717a79d3038e479a2c49cc5eb3d53603409b9a5d7", size = 12866622, upload-time = "2026-05-11T18:34:39.945Z" },
{ url = "https://files.pythonhosted.org/packages/4b/50/1043e1db5f455ffe4c9ab22747cd8ca2bc492b1e4f4e21b130a44ee2b217/mypy-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:4f910fe825376a7b66ef7ca8c98e5a149e8cd64c19ae71d84047a74ee060d4e6", size = 10610798, upload-time = "2026-05-11T18:36:31.444Z" },
{ url = "https://files.pythonhosted.org/packages/0d/2a/13ca1f292f6db1b98ff495ef3467736b331621c5917cad984b7043e7348d/mypy-2.1.0-py3-none-any.whl", hash = "sha256:a663814603a5c563fb87a4f96fb473eeb30d1f5a4885afcf44f9db000a366289", size = 2693302, upload-time = "2026-05-11T18:31:29.246Z" },
]
[[package]]
@@ -1687,82 +1731,79 @@ wheels = [
[[package]]
name = "onnxruntime"
version = "1.24.4"
version = "1.26.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "flatbuffers" },
{ name = "numpy" },
{ name = "packaging" },
{ name = "protobuf" },
{ name = "sympy" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/60/69/6c40720201012c6af9aa7d4ecdd620e521bd806dc6269d636fdd5c5aeebe/onnxruntime-1.24.4-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0bdfce8e9a6497cec584aab407b71bf697dac5e1b7b7974adc50bf7533bdb3a2", size = 17332131, upload-time = "2026-03-17T22:05:49.005Z" },
{ url = "https://files.pythonhosted.org/packages/38/e9/8c901c150ce0c368da38638f44152fb411059c0c7364b497c9e5c957321a/onnxruntime-1.24.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:046ff290045a387676941a02a8ae5c3ebec6b4f551ae228711968c4a69d8f6b7", size = 15152472, upload-time = "2026-03-17T22:03:26.176Z" },
{ url = "https://files.pythonhosted.org/packages/d5/b6/7a4df417cdd01e8f067a509e123ac8b31af450a719fa7ed81787dd6057ec/onnxruntime-1.24.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e54ad52e61d2d4618dcff8fa1480ac66b24ee2eab73331322db1049f11ccf330", size = 17222993, upload-time = "2026-03-17T22:04:34.485Z" },
{ url = "https://files.pythonhosted.org/packages/dd/59/8febe015f391aa1757fa5ba82c759ea4b6c14ef970132efb5e316665ba61/onnxruntime-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b43b63eb24a2bc8fc77a09be67587a570967a412cccb837b6245ccb546691153", size = 12594863, upload-time = "2026-03-17T22:05:38.749Z" },
{ url = "https://files.pythonhosted.org/packages/32/84/4155fcd362e8873eb6ce305acfeeadacd9e0e59415adac474bea3d9281bb/onnxruntime-1.24.4-cp311-cp311-win_arm64.whl", hash = "sha256:e26478356dba25631fb3f20112e345f8e8bf62c499bb497e8a559f7d69cf7e7b", size = 12259895, upload-time = "2026-03-17T22:05:28.812Z" },
{ url = "https://files.pythonhosted.org/packages/d7/38/31db1b232b4ba960065a90c1506ad7a56995cd8482033184e97fadca17cc/onnxruntime-1.24.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:cad1c2b3f455c55678ab2a8caa51fb420c25e6e3cf10f4c23653cdabedc8de78", size = 17341875, upload-time = "2026-03-17T22:05:51.669Z" },
{ url = "https://files.pythonhosted.org/packages/aa/60/c4d1c8043eb42f8a9aa9e931c8c293d289c48ff463267130eca97d13357f/onnxruntime-1.24.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1a5c5a544b22f90859c88617ecb30e161ee3349fcc73878854f43d77f00558b5", size = 15172485, upload-time = "2026-03-17T22:03:32.182Z" },
{ url = "https://files.pythonhosted.org/packages/6d/ab/5b68110e0460d73fad814d5bd11c7b1ddcce5c37b10177eb264d6a36e331/onnxruntime-1.24.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d640eb9f3782689b55cfa715094474cd5662f2f137be6a6f847a594b6e9705c", size = 17244912, upload-time = "2026-03-17T22:04:37.251Z" },
{ url = "https://files.pythonhosted.org/packages/8b/f4/6b89e297b93704345f0f3f8c62229bee323ef25682a3f9b4f89a39324950/onnxruntime-1.24.4-cp312-cp312-win_amd64.whl", hash = "sha256:535b29475ca42b593c45fbb2152fbf1cdf3f287315bf650e6a724a0a1d065cdb", size = 12596856, upload-time = "2026-03-17T22:05:41.224Z" },
{ url = "https://files.pythonhosted.org/packages/43/06/8b8ec6e9e6a474fcd5d772453f627ad4549dfe3ab8c0bf70af5afcde551b/onnxruntime-1.24.4-cp312-cp312-win_arm64.whl", hash = "sha256:e6214096e14b7b52e3bee1903dc12dc7ca09cb65e26664668a4620cc5e6f9a90", size = 12270275, upload-time = "2026-03-17T22:05:31.132Z" },
{ url = "https://files.pythonhosted.org/packages/e9/f0/8a21ec0a97e40abb7d8da1e8b20fb9e1af509cc6d191f6faa75f73622fb2/onnxruntime-1.24.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e99a48078baaefa2b50fe5836c319499f71f13f76ed32d0211f39109147a49e0", size = 17341922, upload-time = "2026-03-17T22:03:56.364Z" },
{ url = "https://files.pythonhosted.org/packages/8b/25/d7908de8e08cee9abfa15b8aa82349b79733ae5865162a3609c11598805d/onnxruntime-1.24.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4aaed1e5e1aaacf2343c838a30a7c3ade78f13eeb16817411f929d04040a13", size = 15172290, upload-time = "2026-03-17T22:03:37.124Z" },
{ url = "https://files.pythonhosted.org/packages/7f/72/105ec27a78c5aa0154a7c0cd8c41c19a97799c3b12fc30392928997e3be3/onnxruntime-1.24.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e30c972bc02e072911aabb6891453ec73795386c0af2b761b65444b8a4c4745f", size = 17244738, upload-time = "2026-03-17T22:04:40.625Z" },
{ url = "https://files.pythonhosted.org/packages/05/fb/a592736d968c2f58e12de4d52088dda8e0e724b26ad5c0487263adb45875/onnxruntime-1.24.4-cp313-cp313-win_amd64.whl", hash = "sha256:3b6ba8b0181a3aa88edab00eb01424ffc06f42e71095a91186c2249415fcff93", size = 12597435, upload-time = "2026-03-17T22:05:43.826Z" },
{ url = "https://files.pythonhosted.org/packages/ad/04/ae2479e9841b64bd2eb44f8a64756c62593f896514369a11243b1b86ca5c/onnxruntime-1.24.4-cp313-cp313-win_arm64.whl", hash = "sha256:71d6a5c1821d6e8586a024000ece458db8f2fc0ecd050435d45794827ce81e19", size = 12269852, upload-time = "2026-03-17T22:05:33.353Z" },
{ url = "https://files.pythonhosted.org/packages/b4/af/a479a536c4398ffaf49fbbe755f45d5b8726bdb4335ab31b537f3d7149b8/onnxruntime-1.24.4-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1700f559c8086d06b2a4d5de51e62cb4ff5e2631822f71a36db8c72383db71ee", size = 15176861, upload-time = "2026-03-17T22:03:40.143Z" },
{ url = "https://files.pythonhosted.org/packages/be/13/19f5da70c346a76037da2c2851ecbf1266e61d7f0dcdb887c667210d4608/onnxruntime-1.24.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c74e268dc808e61e63784d43f9ddcdaf50a776c2819e8bd1d1b11ef64bf7e36", size = 17247454, upload-time = "2026-03-17T22:04:46.643Z" },
{ url = "https://files.pythonhosted.org/packages/89/db/b30dbbd6037847b205ab75d962bc349bf1e46d02a65b30d7047a6893ffd6/onnxruntime-1.24.4-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:fbff2a248940e3398ae78374c5a839e49a2f39079b488bc64439fa0ec327a3e4", size = 17343300, upload-time = "2026-03-17T22:03:59.223Z" },
{ url = "https://files.pythonhosted.org/packages/61/88/1746c0e7959961475b84c776d35601a21d445f463c93b1433a409ec3e188/onnxruntime-1.24.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e2b7969e72d8cb53ffc88ab6d49dd5e75c1c663bda7be7eb0ece192f127343d1", size = 15175936, upload-time = "2026-03-17T22:03:43.671Z" },
{ url = "https://files.pythonhosted.org/packages/5f/ba/4699cde04a52cece66cbebc85bd8335a0d3b9ad485abc9a2e15946a1349d/onnxruntime-1.24.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14ed1f197fab812b695a5eaddb536c635e58a2fbbe50a517c78f082cc6ce9177", size = 17246432, upload-time = "2026-03-17T22:04:49.58Z" },
{ url = "https://files.pythonhosted.org/packages/ef/60/4590910841bb28bd3b4b388a9efbedf4e2d2cca99ddf0c863642b4e87814/onnxruntime-1.24.4-cp314-cp314-win_amd64.whl", hash = "sha256:311e309f573bf3c12aa5723e23823077f83d5e412a18499d4485c7eb41040858", size = 12903276, upload-time = "2026-03-17T22:05:46.349Z" },
{ url = "https://files.pythonhosted.org/packages/7f/6f/60e2c0acea1e1ac09b3e794b5a19c166eebf91c0b860b3e6db8e74983fda/onnxruntime-1.24.4-cp314-cp314-win_arm64.whl", hash = "sha256:3f0b910e86b759a4732663ec61fd57ac42ee1b0066f68299de164220b660546d", size = 12594365, upload-time = "2026-03-17T22:05:35.795Z" },
{ url = "https://files.pythonhosted.org/packages/cf/68/0c05d10f8f6c40fe0912ebec0d5a33884aaa2af2053507e864dab0883208/onnxruntime-1.24.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa12ddc54c9c4594073abcaa265cd9681e95fb89dae982a6f508a794ca42e661", size = 15176889, upload-time = "2026-03-17T22:03:48.021Z" },
{ url = "https://files.pythonhosted.org/packages/6c/1d/1666dc64e78d8587d168fec4e3b7922b92eb286a2ddeebcf6acb55c7dc82/onnxruntime-1.24.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1cc6a518255f012134bc791975a6294806be9a3b20c4a54cca25194c90cf731", size = 17247021, upload-time = "2026-03-17T22:04:52.377Z" },
{ url = "https://files.pythonhosted.org/packages/d4/81/29a9eb470994a75eb7b3ccf32be314d7c66675a00ac7b50294816cc2db27/onnxruntime-1.26.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:ee1109ef4ef27cad90e823399e61e03b3c6c7bfe0fb820b4baf3678c15be8b3c", size = 18005108, upload-time = "2026-05-08T19:08:11.728Z" },
{ url = "https://files.pythonhosted.org/packages/66/c7/73efa6c8a4000c38fcc14947d84f234a17e5d66f203b37b7f1ad4a7b46eb/onnxruntime-1.26.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35c7c7b0ac2e02001d28fab6c9fc24e9abc5e6faa35e6e19c63cecf1406ba89f", size = 16043752, upload-time = "2026-05-08T19:07:10.707Z" },
{ url = "https://files.pythonhosted.org/packages/b6/3f/8de630f595daf6ce884d4dd95afd2a60e70ec6572e52bfee3aa2229befab/onnxruntime-1.26.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11a8df4dcfe9ad5ff0bd71a7571dbed019fabc7594676c89fe8b86ea029c246f", size = 18176043, upload-time = "2026-05-08T19:07:33.735Z" },
{ url = "https://files.pythonhosted.org/packages/9c/21/9f041de20787cd85498bd48e0ec4d098bf2a6c486e25b24b8dae1bf492b2/onnxruntime-1.26.0-cp311-cp311-win_amd64.whl", hash = "sha256:e6456718125fd777c673f3b78d4a9ab58d6adea641e9afae85ee6444f0e0e9a9", size = 13023165, upload-time = "2026-05-08T19:08:00.633Z" },
{ url = "https://files.pythonhosted.org/packages/0e/82/3b9fe0ead2557cc3adf74c74c141bd1c7c4c6a9548c610af37df199f4512/onnxruntime-1.26.0-cp311-cp311-win_arm64.whl", hash = "sha256:cd920e45b730e4a87833e2910d8ca375aaca9da6ccc09e24bce463b3356d637f", size = 12789514, upload-time = "2026-05-08T19:07:49.433Z" },
{ url = "https://files.pythonhosted.org/packages/81/b1/d111b1df656761f980d9e298a60039a9cb66036b1d039e777537743d0ac3/onnxruntime-1.26.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:05b028781b322ad74b57ce5b50aa5280bb1fe96ceec334628ade681e0b24c1ac", size = 18016624, upload-time = "2026-05-12T00:41:01.735Z" },
{ url = "https://files.pythonhosted.org/packages/f6/a0/3f9d896a0385a36bd04345d6d0b802821a5782adde562e7e135f6bb71c73/onnxruntime-1.26.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91f2bb870a4b9224eba0a6728c1fa7a9e552b8e59e1083c51fbbc3d013f2b5c0", size = 16052692, upload-time = "2026-05-08T19:07:13.829Z" },
{ url = "https://files.pythonhosted.org/packages/7c/43/2a4e04f8dbeffad19bbcced4bcd4289bf478921518437404d6b92bdf213b/onnxruntime-1.26.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b6dd70599005bd1bf29779f04a91978b92b5e719c11a20068a8f8e535f725b6", size = 18185439, upload-time = "2026-05-08T19:07:36.299Z" },
{ url = "https://files.pythonhosted.org/packages/44/fc/026d0a7162b9c2153dac292baea9e027c42304dc1d9dc6f8ff5b4cfbaedd/onnxruntime-1.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:a26374dc7fbcaae593601086b242120e13f2310558df0991da6dd8b8fac00414", size = 13026427, upload-time = "2026-05-08T19:08:03.503Z" },
{ url = "https://files.pythonhosted.org/packages/3e/27/1dcf88e45e4c69db5f7b106f2dacc3801ba98994e082ca03e1dfdf7bfe57/onnxruntime-1.26.0-cp312-cp312-win_arm64.whl", hash = "sha256:54a8053410fd31fd66469bd754fcfe8a4df9f7eb44756b4b5479bf50c842d948", size = 12796647, upload-time = "2026-05-08T19:07:52.108Z" },
{ url = "https://files.pythonhosted.org/packages/cf/a2/c801242685e0ce48a4ca51dfafbb588765e0446397e123be53ba5598f3f5/onnxruntime-1.26.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:ccce19c5f771b8268902f77d9fed9e88f9499465d6780808faa6611a789d33f0", size = 18016563, upload-time = "2026-05-08T19:07:28.081Z" },
{ url = "https://files.pythonhosted.org/packages/e2/64/0492c0b1db04e29b2630c87cfa36f9d6872b1ca8614b90c5cad58fac7d76/onnxruntime-1.26.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdbed8cf3b672b66acb032f33a253bc27f42bce6ece48ae3fab4fa483a5e96e0", size = 16052634, upload-time = "2026-05-08T19:07:16.885Z" },
{ url = "https://files.pythonhosted.org/packages/3d/26/4d09ddc755a84fc8d5e192991626b0e0680e8f6c5d58f4f1d05c42bc48cf/onnxruntime-1.26.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c07af6fc6d5557835f2b6ee7a96d8b3235d0c57a8e230efdedaee106a8a3cbc6", size = 18185632, upload-time = "2026-05-08T19:07:38.756Z" },
{ url = "https://files.pythonhosted.org/packages/77/89/3e52249aa08fa301e217ecba07b5246a8338fa2b401e109326e3fc5be0f9/onnxruntime-1.26.0-cp313-cp313-win_amd64.whl", hash = "sha256:61bec80655efa460591c2bc655392d57d2650ce85533a6b9b3b7a790d7ea7916", size = 13026751, upload-time = "2026-05-08T19:08:06.2Z" },
{ url = "https://files.pythonhosted.org/packages/06/b3/c1c8782b14af6797c303de132d6eef26a9fb80dfacd3750ce57911d11c6b/onnxruntime-1.26.0-cp313-cp313-win_arm64.whl", hash = "sha256:a6677545ff451e3539a02746d2f207d8c5baa4a0a818886bb9d6a6eb9511ee89", size = 12796807, upload-time = "2026-05-08T19:07:54.879Z" },
{ url = "https://files.pythonhosted.org/packages/c3/f5/47b0676408abec652c14b84d7173e389837832d850c24f87184277313e8d/onnxruntime-1.26.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e016edc15d3c19f36807e1c6b10be5b27807688c32720f91b5ae480a95215d0", size = 16057265, upload-time = "2026-05-08T19:07:19.603Z" },
{ url = "https://files.pythonhosted.org/packages/3b/45/33ab6deeef010ca844c877dd618cebc079590bbe52d2a3678e7223b1b908/onnxruntime-1.26.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f5fc48a91a046a6a5c9b147f83fb41d65d24d24923373b222cdd248f0f4f4aac", size = 18197590, upload-time = "2026-05-08T19:07:41.422Z" },
{ url = "https://files.pythonhosted.org/packages/40/89/17546c1c20f6bfc3ae41c22152378a26edfea918af3129e2139dcd7c99f3/onnxruntime-1.26.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:33a791f31432a3af1a96db5e54818b37aba5e5eefc2e6af5794c10a9118a9993", size = 18019724, upload-time = "2026-05-08T19:07:30.723Z" },
{ url = "https://files.pythonhosted.org/packages/bb/24/89457a35f6af29538a76647f2c18c3a28277e6c19234c847e7b4b7c19860/onnxruntime-1.26.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e90c00732c4553618103149d93f688e8c3063017938f8983e21a71d9f3b6d22e", size = 16054821, upload-time = "2026-05-08T19:07:22.348Z" },
{ url = "https://files.pythonhosted.org/packages/12/f9/15b2e1815cf570d238e0135529f80d2dce64e8e8818a1489cae83823c5c6/onnxruntime-1.26.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01498e80ba8988428d08c2d51b1338f89e3de2a93e6ffe555f79c68f26a5c06b", size = 18185815, upload-time = "2026-05-08T19:07:44.179Z" },
{ url = "https://files.pythonhosted.org/packages/d7/65/2e11055faf015e4b07f45b513fa49b391baf2e19d92d77d73ebee13c1004/onnxruntime-1.26.0-cp314-cp314-win_amd64.whl", hash = "sha256:7ead61450d8405167c87dd3a31d8da1d576b490a57dab1aa8b82a7da6825f5aa", size = 13349887, upload-time = "2026-05-08T19:08:08.671Z" },
{ url = "https://files.pythonhosted.org/packages/19/e4/0f9d1a5718b1781c610c1e354765a3820597081754277a6a9a2b50705702/onnxruntime-1.26.0-cp314-cp314-win_arm64.whl", hash = "sha256:31d71a53490e46910877d0902b5ad99c69a5955e5c7ea6c82863519410e1ba7c", size = 13140121, upload-time = "2026-05-08T19:07:57.804Z" },
{ url = "https://files.pythonhosted.org/packages/1c/42/3b8e635f067d06d9f45bede470b8d539d101a4166c272213158dfd08b6ce/onnxruntime-1.26.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d7b6d258fb78fdfcf049795bcfaa74dcb90ae7baa277afd21e6fd28b83f2c496", size = 16057240, upload-time = "2026-05-08T19:07:25.163Z" },
{ url = "https://files.pythonhosted.org/packages/93/99/f2be40a31b908d96b861ae0ce98582fa376c18a7f816b9d5eb4cd6aa0a4c/onnxruntime-1.26.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4eefd386a45202aefb7a5132b94f32df9d506c9edcc7faf2fc60d65183f4b183", size = 18197382, upload-time = "2026-05-08T19:07:46.965Z" },
]
[[package]]
name = "onnxruntime-gpu"
version = "1.24.4"
version = "1.26.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "flatbuffers" },
{ name = "numpy" },
{ name = "packaging" },
{ name = "protobuf" },
{ name = "sympy" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/9f/13/e080d758f2b60f71abe518c707135fb121d6a3019e0761ead89b5283ac3d/onnxruntime_gpu-1.24.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2a698659271c28220b3f56fe9b63f70eae3b3c36afa544201bf750b929a36dc", size = 252761835, upload-time = "2026-03-17T22:03:45.584Z" },
{ url = "https://files.pythonhosted.org/packages/d2/07/036825cbe30f91ea8574a18a759beccd0ea31b7b71e17f6a9ee9304b51d2/onnxruntime_gpu-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:1a799a16e5f1ff4d6a9e5f72d750849ab0fe534da8d323ae4a5d8d8bb7daeca8", size = 207193563, upload-time = "2026-03-17T21:58:28.097Z" },
{ url = "https://files.pythonhosted.org/packages/d0/2c/5b3fd4748cf7ed291eae541a37e426efc20ea04cb6e6a05768304ab0aa41/onnxruntime_gpu-1.24.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb0e38f0c1ef3b76ae0081c8e51eed20dd8925aa916f0fc6f9b8b17d05610e99", size = 252765531, upload-time = "2026-03-17T22:03:57.528Z" },
{ url = "https://files.pythonhosted.org/packages/f2/86/70cecfdab1e963cc7f8c11e72040dfcd5cff85b1de2de74deba9611e0059/onnxruntime_gpu-1.24.4-cp312-cp312-win_amd64.whl", hash = "sha256:da5c1e327d8e119a831be2790e69f93cf6daab9145ed0aca7577f412a620f709", size = 207197978, upload-time = "2026-03-17T21:58:38.43Z" },
{ url = "https://files.pythonhosted.org/packages/be/4e/56d11203d7a35e7d6a5ea735f5fecb8673537038c07323e8d3090a896547/onnxruntime_gpu-1.24.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bbdaa73f9055fb2a177425edbed651a1843a6239f9d5430e284f4e5f65440a33", size = 252763446, upload-time = "2026-03-17T22:04:09.515Z" },
{ url = "https://files.pythonhosted.org/packages/fa/bc/35f3a37226d7a28c84b8b456f52237ccd39eb7111114bcf9ac340178e1ec/onnxruntime_gpu-1.24.4-cp313-cp313-win_amd64.whl", hash = "sha256:6be8bf2048777c517fca33eb61e114969fa326619feaa789d8c75f24337ea762", size = 207198775, upload-time = "2026-03-17T21:58:48.768Z" },
{ url = "https://files.pythonhosted.org/packages/37/83/0c851882051b38f245f44b4a51d6232b95b8cd5d334b2c1260f2d796834f/onnxruntime_gpu-1.24.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e4b348a078ced73fc577d21b83992fd2187edd10c233729c8d01b000b8543525", size = 252774594, upload-time = "2026-03-17T22:04:24.957Z" },
{ url = "https://files.pythonhosted.org/packages/3e/5b/82b27f766b64f97c9a98b772dc07b608e900bd2faafdfa176b86d20be7f8/onnxruntime_gpu-1.24.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:af9dd7ef92d94c75e5523cf070e180f3d8cdbb2fc007dcea97ba71b03e3b96d6", size = 252765395, upload-time = "2026-03-17T22:04:37.305Z" },
{ url = "https://files.pythonhosted.org/packages/5d/95/fa8c48e03790c979167d08164b34a8442c7074bca4c7253b4455497025de/onnxruntime_gpu-1.24.4-cp314-cp314-win_amd64.whl", hash = "sha256:4dde3d2f1039060c42b12fd446fc0da5b836cc65dceb4020ca60a04cffa1d90d", size = 209597109, upload-time = "2026-03-17T21:58:58.136Z" },
{ url = "https://files.pythonhosted.org/packages/1a/98/7707edefcecf69d6c45b83a83f13ac58257017b4eaf58772668d302f849f/onnxruntime_gpu-1.24.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:097c6f53e99ee35f21d0fdba76ca283b92465a0e364c6f0209cb9653c424e2a4", size = 252776951, upload-time = "2026-03-17T22:04:49.715Z" },
{ url = "https://files.pythonhosted.org/packages/dc/0f/696b4f94a282952239ffed39db78cb17a00ad993acd929cfac010a09759b/onnxruntime_gpu-1.26.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4fa231294c2643911d2a7d16469c4808b0bdcdc4b5f4063d3a53744ce25b683a", size = 276956564, upload-time = "2026-05-08T19:15:35.133Z" },
{ url = "https://files.pythonhosted.org/packages/ef/26/a417b7a1cdbbf56a389bfcd399255be23f30e5721e3e519472fe8dde9c99/onnxruntime_gpu-1.26.0-cp311-cp311-win_amd64.whl", hash = "sha256:cc5329aad02d9745cc3ae9cdb185bfa1aad242a7bf89b8c471280002ec40f98a", size = 226539455, upload-time = "2026-05-08T19:09:24.631Z" },
{ url = "https://files.pythonhosted.org/packages/94/fd/59bee7cffaa435da44fefdeb63e29c61de4dbfa4b279852f59cd02c042ae/onnxruntime_gpu-1.26.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3c01119ed4d9449d60367fa8ccffcd02bd3fe736754284e4b198d131f54edad6", size = 276971796, upload-time = "2026-05-08T19:15:46.192Z" },
{ url = "https://files.pythonhosted.org/packages/a4/e4/9b378a5466ea0bed65e5beb8e09254973c580a6522810a38afbcc45e5105/onnxruntime_gpu-1.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:5f49c44689894650990e4c8a857d2edafc276fbd79bba57ceb224bd18d25d491", size = 226548963, upload-time = "2026-05-08T19:09:34.925Z" },
{ url = "https://files.pythonhosted.org/packages/dd/97/fe8979f44b9275654b42f7bb556e30789b71a1b22998c83b540df2b1b774/onnxruntime_gpu-1.26.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cfda2fad535595bfc3e570eb588092717711dcb2957656d814695e0c9ceb1508", size = 276974871, upload-time = "2026-05-08T19:15:58.052Z" },
{ url = "https://files.pythonhosted.org/packages/67/3f/59f1777a394625ecc9a85636de57dc47c25dbb5f888da050f1463955a0ce/onnxruntime_gpu-1.26.0-cp313-cp313-win_amd64.whl", hash = "sha256:6ab9f9c741d2e239b2e321ab0d389c04329d4ab7f11e3b92dd3aa7db1c59dee4", size = 226548083, upload-time = "2026-05-08T19:09:44.408Z" },
{ url = "https://files.pythonhosted.org/packages/89/96/360328e3c463f7ea08e853c4239c397e83363dd0204de71a710dc1a544bd/onnxruntime_gpu-1.26.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bcf6f347cad9f88a9a625c2b352cf9de927528aedb627ebbc089a201f1990b94", size = 276992052, upload-time = "2026-05-08T19:16:09.892Z" },
{ url = "https://files.pythonhosted.org/packages/fd/c8/aa2dc0e79bba577f37d5448bcb32fea79977e07506684d8138c19a0f1077/onnxruntime_gpu-1.26.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e6e4fb1ec9ae1cf456534d9115f106ab2a1ae96fa513b4ed0f4795302b4a2c6", size = 276978254, upload-time = "2026-05-08T19:16:22.096Z" },
{ url = "https://files.pythonhosted.org/packages/41/e7/923298431e669567d7ccc2a4c898b6534a47641a051569fd97165fe6d9b8/onnxruntime_gpu-1.26.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e592439b0183d303c2374517b5b392599a3d50b2dc9de949b9b15731ac921c9", size = 229142768, upload-time = "2026-05-08T19:09:54.589Z" },
{ url = "https://files.pythonhosted.org/packages/97/91/93ffe5431d154989f5e04864a25a97eea480997d771232bcbbc538188241/onnxruntime_gpu-1.26.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:56dc7b73954ff4bdc71f5b8ab306b6f61be5d007881b6ef423a609e2b9cd088b", size = 276991545, upload-time = "2026-05-08T19:16:33.347Z" },
]
[[package]]
name = "onnxruntime-migraphx"
version = "1.24.2"
version = "1.25.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "flatbuffers" },
{ name = "numpy" },
{ name = "packaging" },
{ name = "protobuf" },
{ name = "sympy" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/dd/da/ca7ebc1a8d1193c97ceb9a05fad50f675eb955dc51beb7eb9ba89c8e7db0/onnxruntime_migraphx-1.24.2-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:a2b434fb8880cac2b268950bdf279f33741d29c1f1c5461d27af835e8e288043", size = 20339710, upload-time = "2026-02-21T07:25:13.17Z" },
{ url = "https://files.pythonhosted.org/packages/fa/2e/8c83ec45a9365b4256495ca55eea30da7f03b02177b6da423c7da1ff5f6a/onnxruntime_migraphx-1.24.2-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:ec814818da952bda3062e26f56c88bb713c00491ef91f86716c8d7346f9bc31b", size = 20341883, upload-time = "2026-02-21T07:25:17.86Z" },
{ url = "https://files.pythonhosted.org/packages/9f/52/4776ac68dbc46ca02c9a14cc9e5c496017f47a18cedf606cc38f4911b96a/onnxruntime_migraphx-1.24.2-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:20e497538362170af639b03a40249d7ed61b873ac354f20d732b90252206e320", size = 20342422, upload-time = "2026-02-21T07:25:22.526Z" },
{ url = "https://files.pythonhosted.org/packages/76/44/db9035204a3363f9c0a4822c68e9a7520c13ef8d261f96b89b1375106dab/onnxruntime_migraphx-1.24.2-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:9d7f1b1a2b9651143a2080b4f42ee99eead02023de1855d1b8a02199a9c179aa", size = 20343783, upload-time = "2026-02-21T07:25:29.155Z" },
{ url = "https://files.pythonhosted.org/packages/a5/3c/8c142017df701c38c4f5d6cae0294a2891bdd0f719eaff42e87564ac1480/onnxruntime_migraphx-1.25.0-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:c7f28ddb8eef13fd5e9002d5162bfe848abfd02dcf13ab6a6b8c00380c014f33", size = 21467402, upload-time = "2026-04-21T05:23:52.026Z" },
{ url = "https://files.pythonhosted.org/packages/1c/0d/21730262547fae9557cb3fc85d891d600158c92399f68e4a760aed59bffc/onnxruntime_migraphx-1.25.0-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:5c1dac156f98a9a20556bbc1e1c69d5ca1f78bad14d4953aa2b3cb2711507166", size = 21477899, upload-time = "2026-04-21T05:24:31.072Z" },
{ url = "https://files.pythonhosted.org/packages/09/b5/39764a6c87e9f97c0891f194100883192a0ce88725aba6215d499cd714b8/onnxruntime_migraphx-1.25.0-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:d778d88bfdd8818817618ff3e4d973ed861428f61ba7c8b841690c699cb29ed4", size = 21477896, upload-time = "2026-04-21T05:25:11.969Z" },
{ url = "https://files.pythonhosted.org/packages/35/97/f8d8f3141c606e14a23e52a035c123524f5b714e15a1f9425a940906dfce/onnxruntime_migraphx-1.25.0-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:5558a05f4cc1975c9974090337bbc460aae72b29ae20afb42bec93b74df0eae8", size = 21478521, upload-time = "2026-04-21T05:25:52.121Z" },
]
[[package]]
@@ -1822,70 +1863,70 @@ wheels = [
[[package]]
name = "orjson"
version = "3.11.8"
version = "3.11.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/9d/1b/2024d06792d0779f9dbc51531b61c24f76c75b9f4ce05e6f3377a1814cea/orjson-3.11.8.tar.gz", hash = "sha256:96163d9cdc5a202703e9ad1b9ae757d5f0ca62f4fa0cc93d1f27b0e180cc404e", size = 5603832, upload-time = "2026-03-31T16:16:27.878Z" }
sdist = { url = "https://files.pythonhosted.org/packages/7e/0c/964746fcafbd16f8ff53219ad9f6b412b34f345c75f384ad434ceaadb538/orjson-3.11.9.tar.gz", hash = "sha256:4fef17e1f8722c11587a6ef18e35902450221da0028e65dbaaa543619e68e48f", size = 5599163, upload-time = "2026-05-06T15:11:08.309Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/67/41/5aa7fa3b0f4dc6b47dcafc3cea909299c37e40e9972feabc8b6a74e2730d/orjson-3.11.8-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:003646067cc48b7fcab2ae0c562491c9b5d2cbd43f1e5f16d98fd118c5522d34", size = 229229, upload-time = "2026-03-31T16:14:50.424Z" },
{ url = "https://files.pythonhosted.org/packages/0a/d7/57e7f2458e0a2c41694f39fc830030a13053a84f837a5b73423dca1f0938/orjson-3.11.8-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:ed193ce51d77a3830cad399a529cd4ef029968761f43ddc549e1bc62b40d88f8", size = 128871, upload-time = "2026-03-31T16:14:51.888Z" },
{ url = "https://files.pythonhosted.org/packages/53/4a/e0fdb9430983e6c46e0299559275025075568aad5d21dd606faee3703924/orjson-3.11.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30491bc4f862aa15744b9738517454f1e46e56c972a2be87d70d727d5b2a8f8", size = 132104, upload-time = "2026-03-31T16:14:53.142Z" },
{ url = "https://files.pythonhosted.org/packages/08/4a/2025a60ff3f5c8522060cda46612d9b1efa653de66ed2908591d8d82f22d/orjson-3.11.8-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eda5b8b6be91d3f26efb7dc6e5e68ee805bc5617f65a328587b35255f138bf4", size = 130483, upload-time = "2026-03-31T16:14:54.605Z" },
{ url = "https://files.pythonhosted.org/packages/2d/3c/b9cde05bdc7b2385c66014e0620627da638d3d04e4954416ab48c31196c5/orjson-3.11.8-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee8db7bfb6fe03581bbab54d7c4124a6dd6a7f4273a38f7267197890f094675f", size = 135481, upload-time = "2026-03-31T16:14:55.901Z" },
{ url = "https://files.pythonhosted.org/packages/ff/f2/a8238e7734de7cb589fed319857a8025d509c89dc52fdcc88f39c6d03d5a/orjson-3.11.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d8b5231de76c528a46b57010bbd83fb51e056aa0220a372fd5065e978406f1c", size = 146819, upload-time = "2026-03-31T16:14:57.548Z" },
{ url = "https://files.pythonhosted.org/packages/db/10/dbf1e2a3cafea673b1b4350e371877b759060d6018a998643b7040e5de48/orjson-3.11.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:58a4a208a6fbfdb7a7327b8f201c6014f189f721fd55d047cafc4157af1bc62a", size = 132846, upload-time = "2026-03-31T16:14:58.91Z" },
{ url = "https://files.pythonhosted.org/packages/f8/fc/55e667ec9c85694038fcff00573d221b085d50777368ee3d77f38668bf3c/orjson-3.11.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f8952d6d2505c003e8f0224ff7858d341fa4e33fef82b91c4ff0ef070f2393c", size = 133580, upload-time = "2026-03-31T16:15:00.519Z" },
{ url = "https://files.pythonhosted.org/packages/7e/a6/c08c589a9aad0cb46c4831d17de212a2b6901f9d976814321ff8e69e8785/orjson-3.11.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0022bb50f90da04b009ce32c512dc1885910daa7cb10b7b0cba4505b16db82a8", size = 142042, upload-time = "2026-03-31T16:15:01.906Z" },
{ url = "https://files.pythonhosted.org/packages/5c/cc/2f78ea241d52b717d2efc38878615fe80425bf2beb6e68c984dde257a766/orjson-3.11.8-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ff51f9d657d1afb6f410cb435792ce4e1fe427aab23d2fcd727a2876e21d4cb6", size = 423845, upload-time = "2026-03-31T16:15:03.703Z" },
{ url = "https://files.pythonhosted.org/packages/70/07/c17dcf05dd8045457538428a983bf1f1127928df5bf328cb24d2b7cddacb/orjson-3.11.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6dbe9a97bdb4d8d9d5367b52a7c32549bba70b2739c58ef74a6964a6d05ae054", size = 147729, upload-time = "2026-03-31T16:15:05.203Z" },
{ url = "https://files.pythonhosted.org/packages/90/6c/0fb6e8a24e682e0958d71711ae6f39110e4b9cd8cab1357e2a89cb8e1951/orjson-3.11.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5c370674ebabe16c6ccac33ff80c62bf8a6e59439f5e9d40c1f5ab8fd2215b7", size = 136425, upload-time = "2026-03-31T16:15:07.052Z" },
{ url = "https://files.pythonhosted.org/packages/b2/35/4d3cc3a3d616035beb51b24a09bb872942dc452cf2df0c1d11ab35046d9f/orjson-3.11.8-cp311-cp311-win32.whl", hash = "sha256:0e32f7154299f42ae66f13488963269e5eccb8d588a65bc839ed986919fc9fac", size = 131870, upload-time = "2026-03-31T16:15:08.678Z" },
{ url = "https://files.pythonhosted.org/packages/13/26/9fe70f81d16b702f8c3a775e8731b50ad91d22dacd14c7599b60a0941cd1/orjson-3.11.8-cp311-cp311-win_amd64.whl", hash = "sha256:25e0c672a2e32348d2eb33057b41e754091f2835f87222e4675b796b92264f06", size = 127440, upload-time = "2026-03-31T16:15:09.994Z" },
{ url = "https://files.pythonhosted.org/packages/e8/c6/b038339f4145efd2859c1ca53097a52c0bb9cbdd24f947ebe146da1ad067/orjson-3.11.8-cp311-cp311-win_arm64.whl", hash = "sha256:9185589c1f2a944c17e26c9925dcdbc2df061cc4a145395c57f0c51f9b5dbfcd", size = 127399, upload-time = "2026-03-31T16:15:11.412Z" },
{ url = "https://files.pythonhosted.org/packages/01/f6/8d58b32ab32d9215973a1688aebd098252ee8af1766c0e4e36e7831f0295/orjson-3.11.8-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1cd0b77e77c95758f8e1100139844e99f3ccc87e71e6fc8e1c027e55807c549f", size = 229233, upload-time = "2026-03-31T16:15:12.762Z" },
{ url = "https://files.pythonhosted.org/packages/a9/8b/2ffe35e71f6b92622e8ea4607bf33ecf7dfb51b3619dcfabfd36cbe2d0a5/orjson-3.11.8-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:6a3d159d5ffa0e3961f353c4b036540996bf8b9697ccc38261c0eac1fd3347a6", size = 128772, upload-time = "2026-03-31T16:15:14.237Z" },
{ url = "https://files.pythonhosted.org/packages/27/d2/1f8682ae50d5c6897a563cb96bc106da8c9cb5b7b6e81a52e4cc086679b9/orjson-3.11.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76070a76e9c5ae661e2d9848f216980d8d533e0f8143e6ed462807b242e3c5e8", size = 131946, upload-time = "2026-03-31T16:15:15.607Z" },
{ url = "https://files.pythonhosted.org/packages/52/4b/5500f76f0eece84226e0689cb48dcde081104c2fa6e2483d17ca13685ffb/orjson-3.11.8-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:54153d21520a71a4c82a0dbb4523e468941d549d221dc173de0f019678cf3813", size = 130368, upload-time = "2026-03-31T16:15:17.066Z" },
{ url = "https://files.pythonhosted.org/packages/da/4e/58b927e08fbe9840e6c920d9e299b051ea667463b1f39a56e668669f8508/orjson-3.11.8-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:469ac2125611b7c5741a0b3798cd9e5786cbad6345f9f400c77212be89563bec", size = 135540, upload-time = "2026-03-31T16:15:18.404Z" },
{ url = "https://files.pythonhosted.org/packages/56/7c/ba7cb871cba1bcd5cd02ee34f98d894c6cea96353ad87466e5aef2429c60/orjson-3.11.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14778ffd0f6896aa613951a7fbf4690229aa7a543cb2bfbe9f358e08aafa9546", size = 146877, upload-time = "2026-03-31T16:15:19.833Z" },
{ url = "https://files.pythonhosted.org/packages/0b/5d/eb9c25fc1386696c6a342cd361c306452c75e0b55e86ad602dd4827a7fd7/orjson-3.11.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea56a955056a6d6c550cf18b3348656a9d9a4f02e2d0c02cabf3c73f1055d506", size = 132837, upload-time = "2026-03-31T16:15:21.282Z" },
{ url = "https://files.pythonhosted.org/packages/37/87/5ddeb7fc1fbd9004aeccab08426f34c81a5b4c25c7061281862b015fce2b/orjson-3.11.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53a0f57e59a530d18a142f4d4ba6dfc708dc5fdedce45e98ff06b44930a2a48f", size = 133624, upload-time = "2026-03-31T16:15:22.641Z" },
{ url = "https://files.pythonhosted.org/packages/22/09/90048793db94ee4b2fcec4ac8e5ddb077367637d6650be896b3494b79bb7/orjson-3.11.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b48e274f8824567d74e2158199e269597edf00823a1b12b63d48462bbf5123e", size = 141904, upload-time = "2026-03-31T16:15:24.435Z" },
{ url = "https://files.pythonhosted.org/packages/c0/cf/eb284847487821a5d415e54149a6449ba9bfc5872ce63ab7be41b8ec401c/orjson-3.11.8-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3f262401086a3960586af06c054609365e98407151f5ea24a62893a40d80dbbb", size = 423742, upload-time = "2026-03-31T16:15:26.155Z" },
{ url = "https://files.pythonhosted.org/packages/44/09/e12423d327071c851c13e76936f144a96adacfc037394dec35ac3fc8d1e8/orjson-3.11.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8e8c6218b614badf8e229b697865df4301afa74b791b6c9ade01d19a9953a942", size = 147806, upload-time = "2026-03-31T16:15:27.909Z" },
{ url = "https://files.pythonhosted.org/packages/b3/6d/37c2589ba864e582ffe7611643314785c6afb1f83c701654ef05daa8fcc7/orjson-3.11.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:093d489fa039ddade2db541097dbb484999fcc65fc2b0ff9819141e2ab364f25", size = 136485, upload-time = "2026-03-31T16:15:29.749Z" },
{ url = "https://files.pythonhosted.org/packages/be/c9/135194a02ab76b04ed9a10f68624b7ebd238bbe55548878b11ff15a0f352/orjson-3.11.8-cp312-cp312-win32.whl", hash = "sha256:e0950ed1bcb9893f4293fd5c5a7ee10934fbf82c4101c70be360db23ce24b7d2", size = 131966, upload-time = "2026-03-31T16:15:31.687Z" },
{ url = "https://files.pythonhosted.org/packages/ed/9a/9796f8fbe3cf30ce9cb696748dbb535e5c87be4bf4fe2e9ca498ef1fa8cf/orjson-3.11.8-cp312-cp312-win_amd64.whl", hash = "sha256:3cf17c141617b88ced4536b2135c552490f07799f6ad565948ea07bef0dcb9a6", size = 127441, upload-time = "2026-03-31T16:15:33.333Z" },
{ url = "https://files.pythonhosted.org/packages/cc/47/5aaf54524a7a4a0dd09dd778f3fa65dd2108290615b652e23d944152bc8e/orjson-3.11.8-cp312-cp312-win_arm64.whl", hash = "sha256:48854463b0572cc87dac7d981aa72ed8bf6deedc0511853dc76b8bbd5482d36d", size = 127364, upload-time = "2026-03-31T16:15:34.748Z" },
{ url = "https://files.pythonhosted.org/packages/66/7f/95fba509bb2305fab0073558f1e8c3a2ec4b2afe58ed9fcb7d3b8beafe94/orjson-3.11.8-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3f23426851d98478c8970da5991f84784a76682213cd50eb73a1da56b95239dc", size = 229180, upload-time = "2026-03-31T16:15:36.426Z" },
{ url = "https://files.pythonhosted.org/packages/f6/9d/b237215c743ca073697d759b5503abd2cb8a0d7b9c9e21f524bcf176ab66/orjson-3.11.8-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:ebaed4cef74a045b83e23537b52ef19a367c7e3f536751e355a2a394f8648559", size = 128754, upload-time = "2026-03-31T16:15:38.049Z" },
{ url = "https://files.pythonhosted.org/packages/42/3d/27d65b6d11e63f133781425f132807aef793ed25075fec686fc8e46dd528/orjson-3.11.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97c8f5d3b62380b70c36ffacb2a356b7c6becec86099b177f73851ba095ef623", size = 131877, upload-time = "2026-03-31T16:15:39.484Z" },
{ url = "https://files.pythonhosted.org/packages/dd/cc/faee30cd8f00421999e40ef0eba7332e3a625ce91a58200a2f52c7fef235/orjson-3.11.8-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:436c4922968a619fb7fef1ccd4b8b3a76c13b67d607073914d675026e911a65c", size = 130361, upload-time = "2026-03-31T16:15:41.274Z" },
{ url = "https://files.pythonhosted.org/packages/5c/bb/a6c55896197f97b6d4b4e7c7fd77e7235517c34f5d6ad5aadd43c54c6d7c/orjson-3.11.8-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ab359aff0436d80bfe8a23b46b5fea69f1e18aaf1760a709b4787f1318b317f", size = 135521, upload-time = "2026-03-31T16:15:42.758Z" },
{ url = "https://files.pythonhosted.org/packages/9c/7c/ca3a3525aa32ff636ebb1778e77e3587b016ab2edb1b618b36ba96f8f2c0/orjson-3.11.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f89b6d0b3a8d81e1929d3ab3d92bbc225688bd80a770c49432543928fe09ac55", size = 146862, upload-time = "2026-03-31T16:15:44.341Z" },
{ url = "https://files.pythonhosted.org/packages/3c/0c/18a9d7f18b5edd37344d1fd5be17e94dc652c67826ab749c6e5948a78112/orjson-3.11.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29c009e7a2ca9ad0ed1376ce20dd692146a5d9fe4310848904b6b4fee5c5c137", size = 132847, upload-time = "2026-03-31T16:15:46.368Z" },
{ url = "https://files.pythonhosted.org/packages/23/91/7e722f352ad67ca573cee44de2a58fb810d0f4eb4e33276c6a557979fd8a/orjson-3.11.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:705b895b781b3e395c067129d8551655642dfe9437273211d5404e87ac752b53", size = 133637, upload-time = "2026-03-31T16:15:48.123Z" },
{ url = "https://files.pythonhosted.org/packages/af/04/32845ce13ac5bd1046ddb02ac9432ba856cc35f6d74dde95864fe0ad5523/orjson-3.11.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:88006eda83858a9fdf73985ce3804e885c2befb2f506c9a3723cdeb5a2880e3e", size = 141906, upload-time = "2026-03-31T16:15:49.626Z" },
{ url = "https://files.pythonhosted.org/packages/02/5e/c551387ddf2d7106d9039369862245c85738b828844d13b99ccb8d61fd06/orjson-3.11.8-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:55120759e61309af7fcf9e961c6f6af3dde5921cdb3ee863ef63fd9db126cae6", size = 423722, upload-time = "2026-03-31T16:15:51.176Z" },
{ url = "https://files.pythonhosted.org/packages/00/a3/ecfe62434096f8a794d4976728cb59bcfc4a643977f21c2040545d37eb4c/orjson-3.11.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:98bdc6cb889d19bed01de46e67574a2eab61f5cc6b768ed50e8ac68e9d6ffab6", size = 147801, upload-time = "2026-03-31T16:15:52.939Z" },
{ url = "https://files.pythonhosted.org/packages/18/6d/0dce10b9f6643fdc59d99333871a38fa5a769d8e2fc34a18e5d2bfdee900/orjson-3.11.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:708c95f925a43ab9f34625e45dcdadf09ec8a6e7b664a938f2f8d5650f6c090b", size = 136460, upload-time = "2026-03-31T16:15:54.431Z" },
{ url = "https://files.pythonhosted.org/packages/01/d6/6dde4f31842d87099238f1f07b459d24edc1a774d20687187443ab044191/orjson-3.11.8-cp313-cp313-win32.whl", hash = "sha256:01c4e5a6695dc09098f2e6468a251bc4671c50922d4d745aff1a0a33a0cf5b8d", size = 131956, upload-time = "2026-03-31T16:15:56.081Z" },
{ url = "https://files.pythonhosted.org/packages/c1/f9/4e494a56e013db957fb77186b818b916d4695b8fa2aa612364974160e91b/orjson-3.11.8-cp313-cp313-win_amd64.whl", hash = "sha256:c154a35dd1330707450bb4d4e7dd1f17fa6f42267a40c1e8a1daa5e13719b4b8", size = 127410, upload-time = "2026-03-31T16:15:57.54Z" },
{ url = "https://files.pythonhosted.org/packages/57/7f/803203d00d6edb6e9e7eef421d4e1adbb5ea973e40b3533f3cfd9aeb374e/orjson-3.11.8-cp313-cp313-win_arm64.whl", hash = "sha256:4861bde57f4d253ab041e374f44023460e60e71efaa121f3c5f0ed457c3a701e", size = 127338, upload-time = "2026-03-31T16:15:59.106Z" },
{ url = "https://files.pythonhosted.org/packages/6d/35/b01910c3d6b85dc882442afe5060cbf719c7d1fc85749294beda23d17873/orjson-3.11.8-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ec795530a73c269a55130498842aaa762e4a939f6ce481a7e986eeaa790e9da4", size = 229171, upload-time = "2026-03-31T16:16:00.651Z" },
{ url = "https://files.pythonhosted.org/packages/c2/56/c9ec97bd11240abef39b9e5d99a15462809c45f677420fd148a6c5e6295e/orjson-3.11.8-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c492a0e011c0f9066e9ceaa896fbc5b068c54d365fea5f3444b697ee01bc8625", size = 128746, upload-time = "2026-03-31T16:16:02.673Z" },
{ url = "https://files.pythonhosted.org/packages/3b/e4/66d4f30a90de45e2f0cbd9623588e8ae71eef7679dbe2ae954ed6d66a41f/orjson-3.11.8-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:883206d55b1bd5f5679ad5e6ddd3d1a5e3cac5190482927fdb8c78fb699193b5", size = 131867, upload-time = "2026-03-31T16:16:04.342Z" },
{ url = "https://files.pythonhosted.org/packages/19/30/2a645fc9286b928675e43fa2a3a16fb7b6764aa78cc719dc82141e00f30b/orjson-3.11.8-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5774c1fdcc98b2259800b683b19599c133baeb11d60033e2095fd9d4667b82db", size = 124664, upload-time = "2026-03-31T16:16:05.837Z" },
{ url = "https://files.pythonhosted.org/packages/db/44/77b9a86d84a28d52ba3316d77737f6514e17118119ade3f91b639e859029/orjson-3.11.8-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7381c83dd3d4a6347e6635950aa448f54e7b8406a27c7ecb4a37e9f1ae08b", size = 129701, upload-time = "2026-03-31T16:16:07.407Z" },
{ url = "https://files.pythonhosted.org/packages/b3/ea/eff3d9bfe47e9bc6969c9181c58d9f71237f923f9c86a2d2f490cd898c82/orjson-3.11.8-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14439063aebcb92401c11afc68ee4e407258d2752e62d748b6942dad20d2a70d", size = 141202, upload-time = "2026-03-31T16:16:09.48Z" },
{ url = "https://files.pythonhosted.org/packages/52/c8/90d4b4c60c84d62068d0cf9e4d8f0a4e05e76971d133ac0c60d818d4db20/orjson-3.11.8-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa72e71977bff96567b0f500fc5bfd2fdf915f34052c782a4c6ebbdaa97aa858", size = 127194, upload-time = "2026-03-31T16:16:11.02Z" },
{ url = "https://files.pythonhosted.org/packages/8d/c7/ea9e08d1f0ba981adffb629811148b44774d935171e7b3d780ae43c4c254/orjson-3.11.8-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7679bc2f01bb0d219758f1a5f87bb7c8a81c0a186824a393b366876b4948e14f", size = 133639, upload-time = "2026-03-31T16:16:13.434Z" },
{ url = "https://files.pythonhosted.org/packages/6c/8c/ddbbfd6ba59453c8fc7fe1d0e5983895864e264c37481b2a791db635f046/orjson-3.11.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:14f7b8fcb35ef403b42fa5ecfa4ed032332a91f3dc7368fbce4184d59e1eae0d", size = 141914, upload-time = "2026-03-31T16:16:14.955Z" },
{ url = "https://files.pythonhosted.org/packages/4e/31/dbfbefec9df060d34ef4962cd0afcb6fa7a9ec65884cb78f04a7859526c3/orjson-3.11.8-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:c2bdf7b2facc80b5e34f48a2d557727d5c5c57a8a450de122ae81fa26a81c1bc", size = 423800, upload-time = "2026-03-31T16:16:16.594Z" },
{ url = "https://files.pythonhosted.org/packages/87/cf/f74e9ae9803d4ab46b163494adba636c6d7ea955af5cc23b8aaa94cfd528/orjson-3.11.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ccd7ba1b0605813a0715171d39ec4c314cb97a9c85893c2c5c0c3a3729df38bf", size = 147837, upload-time = "2026-03-31T16:16:18.585Z" },
{ url = "https://files.pythonhosted.org/packages/64/e6/9214f017b5db85e84e68602792f742e5dc5249e963503d1b356bee611e01/orjson-3.11.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cdbc8c9c02463fef4d3c53a9ba3336d05496ec8e1f1c53326a1e4acc11f5c600", size = 136441, upload-time = "2026-03-31T16:16:20.151Z" },
{ url = "https://files.pythonhosted.org/packages/24/dd/3590348818f58f837a75fb969b04cdf187ae197e14d60b5e5a794a38b79d/orjson-3.11.8-cp314-cp314-win32.whl", hash = "sha256:0b57f67710a8cd459e4e54eb96d5f77f3624eba0c661ba19a525807e42eccade", size = 131983, upload-time = "2026-03-31T16:16:21.823Z" },
{ url = "https://files.pythonhosted.org/packages/3f/0f/b6cb692116e05d058f31ceee819c70f097fa9167c82f67fabe7516289abc/orjson-3.11.8-cp314-cp314-win_amd64.whl", hash = "sha256:735e2262363dcbe05c35e3a8869898022af78f89dde9e256924dc02e99fe69ca", size = 127396, upload-time = "2026-03-31T16:16:23.685Z" },
{ url = "https://files.pythonhosted.org/packages/c0/d1/facb5b5051fabb0ef9d26c6544d87ef19a939a9a001198655d0d891062dd/orjson-3.11.8-cp314-cp314-win_arm64.whl", hash = "sha256:6ccdea2c213cf9f3d9490cbd5d427693c870753df41e6cb375bd79bcbafc8817", size = 127330, upload-time = "2026-03-31T16:16:25.496Z" },
{ url = "https://files.pythonhosted.org/packages/1e/51/3fb9e65ae76ee97bd611869a503fa3fc0a6e81dd8b737cf3003f682df7ff/orjson-3.11.9-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f01c4818b3fc9b0da8e096722a84318071eaa118df35f6ed2344da0e73a5444f", size = 228522, upload-time = "2026-05-06T15:09:35.362Z" },
{ url = "https://files.pythonhosted.org/packages/16/fa/9d54b07cb3f3b0bfd57841478e42d7a0ece4a9f49f9907eecf5a45461687/orjson-3.11.9-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:3ebca4179031ee716ed076ffadc29428e900512f6fccee8614c9983157fcf19c", size = 128463, upload-time = "2026-05-06T15:09:37.063Z" },
{ url = "https://files.pythonhosted.org/packages/88/b1/6ceafc2eefd0a553e3be77ce6c49d107e772485d9568629376171c50e634/orjson-3.11.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48ee05097750de0ff69ed5b7bbcf0732182fd57a24043dcc2a1da780a5ead3a5", size = 132306, upload-time = "2026-05-06T15:09:38.299Z" },
{ url = "https://files.pythonhosted.org/packages/ea/76/f11311285324a40aab1e3031385c50b635a7cd0734fdaf60c7e89a696f60/orjson-3.11.9-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6082706765a95a6680d812e1daf1c0cfe8adec7831b3ff3b625693f3b461b1c", size = 127988, upload-time = "2026-05-06T15:09:39.597Z" },
{ url = "https://files.pythonhosted.org/packages/9e/85/0ef63bcf1337f44031ce9b91b1919563f62a37527b3ea4368bb15a22e5d7/orjson-3.11.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:277fefe9d76ee17eb14debf399e3533d4d63b5f677a4d3719eb763536af1f4bd", size = 135188, upload-time = "2026-05-06T15:09:40.957Z" },
{ url = "https://files.pythonhosted.org/packages/05/94/b0d27090ea8a2095db3c2bd1b1c96f96f19bbb494d7fef33130e846e613d/orjson-3.11.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03db380e3780fa0015ed776a90f20e8e20bb11dde13b216ce19e5718e3dfba62", size = 145937, upload-time = "2026-05-06T15:09:42.249Z" },
{ url = "https://files.pythonhosted.org/packages/09/eb/75d50c29c05b8054013e221e598820a365c8e64065312e75e202ed880709/orjson-3.11.9-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33d7d766701847dc6729846362dc27895d2f2d2251264f9d10e7cb9878194877", size = 132758, upload-time = "2026-05-06T15:09:43.945Z" },
{ url = "https://files.pythonhosted.org/packages/49/bd/360686f39348aa88827cb6fbf7dc606fd41c831a35235e1abf1db8e3a9e6/orjson-3.11.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:147302878da387104b66bb4a8b0227d1d487e976ce41a8501916161072ed87b1", size = 133971, upload-time = "2026-05-06T15:09:45.239Z" },
{ url = "https://files.pythonhosted.org/packages/0e/30/3178eb16f3221aeef068b6f1f1ebe05f656ea5c6dffe9f6c917329fe17a3/orjson-3.11.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3513550321f8c8c811a7c3297b8a630e82dc08e4c10216d07703c997776236cd", size = 141685, upload-time = "2026-05-06T15:09:46.858Z" },
{ url = "https://files.pythonhosted.org/packages/5f/f1/ff2f19ed0225f9680fafa42febca3570dd59444ebf190980738d376214c2/orjson-3.11.9-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:c5d001196b89fa9cf0a4ab79766cd835b991a166e4b621ba95089edc50c429ff", size = 415167, upload-time = "2026-05-06T15:09:48.312Z" },
{ url = "https://files.pythonhosted.org/packages/9b/61/863bddf0da6e9e586765414debd54b4e58db05f560902b6d00658cb88636/orjson-3.11.9-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:16969c9d369c98eb084889c6e4d2d39b77c7eb38ceccf8da2a9fff62ae908980", size = 147913, upload-time = "2026-05-06T15:09:49.733Z" },
{ url = "https://files.pythonhosted.org/packages/b6/8a/4081492586d75b073d60c5271a8d0f05a0955cabf1e34c8473f6fcd84235/orjson-3.11.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:63e0efbc991250c0b3143488fa57d95affcabbfc63c99c48d625dd37779aafe2", size = 136959, upload-time = "2026-05-06T15:09:51.311Z" },
{ url = "https://files.pythonhosted.org/packages/0d/bd/70b6ab193594d7abb875320c0a7c8335e846f28968c432c31042409c3c8d/orjson-3.11.9-cp311-cp311-win32.whl", hash = "sha256:14ed654580c1ed2bc217352ec82f91b047aef82951aa71c7f64e0dcb03c0e180", size = 131533, upload-time = "2026-05-06T15:09:52.637Z" },
{ url = "https://files.pythonhosted.org/packages/3f/17/1a1a228183d62d1b77e2c30d210f47dd4768b310ebe1607c63e3c0e3a71e/orjson-3.11.9-cp311-cp311-win_amd64.whl", hash = "sha256:57ea77fb70a448ce87d18fca050193202a3da5e54598f6501ca5476fb66cfe02", size = 127106, upload-time = "2026-05-06T15:09:54.204Z" },
{ url = "https://files.pythonhosted.org/packages/b8/95/285de5fa296d09681ee9c546cd4a8aeb773b701cf343dc125994f4d52953/orjson-3.11.9-cp311-cp311-win_arm64.whl", hash = "sha256:19b72ed11572a2ee51a67a903afbe5af504f84ed6f529c0fe44b0ab3fb5cc697", size = 126848, upload-time = "2026-05-06T15:09:55.551Z" },
{ url = "https://files.pythonhosted.org/packages/16/6d/11867a3ffa3a3608d84a4de51ef4dd0896d6b5cc9132fbe1daf593e677bc/orjson-3.11.9-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9ef6fe90aadef185c7b128859f40beb24720b4ecea95379fc9000931179c3a49", size = 228515, upload-time = "2026-05-06T15:09:57.265Z" },
{ url = "https://files.pythonhosted.org/packages/24/75/05912954c8b288f34fcf5cd4b9b071cb4f6e77b9961e175e56ebb258089f/orjson-3.11.9-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:e5c9b8f28e726e97d97696c826bc7bea5d71cecd63576dba92924a32c1961291", size = 128409, upload-time = "2026-05-06T15:09:59.063Z" },
{ url = "https://files.pythonhosted.org/packages/ab/86/1c3a47df3bc8191ea9ac51603bbb872a95167a364320c269f2557911f406/orjson-3.11.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a473dbb4162108b27901492546f83c76fdcea3d0eadff00ae7a07e18dcce09", size = 132106, upload-time = "2026-05-06T15:10:00.798Z" },
{ url = "https://files.pythonhosted.org/packages/d7/cf/b33b5f3e695ae7d63feef9d915c37cc3b8f465493dcd4f8e0b4c697a2366/orjson-3.11.9-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:011382e2a60fda9d46f1cdee31068cfc52ffe952b587d683ec0463002802a0f4", size = 127864, upload-time = "2026-05-06T15:10:02.15Z" },
{ url = "https://files.pythonhosted.org/packages/31/6a/6cf69385a58208024fcb8c014e2141b8ce838aba6492b589f8acfff97fab/orjson-3.11.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c2d3dc759490128c5c1711a53eeaa8ee1d437fd0038ffd2b6008abf46db3f882", size = 135213, upload-time = "2026-05-06T15:10:03.515Z" },
{ url = "https://files.pythonhosted.org/packages/e8/f8/0b1bd3e8f2efcdd376af5c8cfd79eaf13f018080c0089c80ebd724e3c7fb/orjson-3.11.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8ea516b3726d190e1b4297e6f4e7a8650347ae053868a18163b4dd3641d1fff", size = 145994, upload-time = "2026-05-06T15:10:05.083Z" },
{ url = "https://files.pythonhosted.org/packages/f3/59/dab79f61044c529d2c81aecdc589b1f833a1c8dec11ba3b1c2498a02ca7e/orjson-3.11.9-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:380cdce7ba24989af81d0a7013d0aaec5d0e2a21734c0e2681b1bc4f141957fe", size = 132744, upload-time = "2026-05-06T15:10:06.853Z" },
{ url = "https://files.pythonhosted.org/packages/0e/a4/82b7a2fe5d8a67a59ed831b24d59a3d46ea7d207b66e1602d376541d94a6/orjson-3.11.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be4fa4f0af7fa18951f7ab3fc2148e223af211bf03f59e1c6034ec3f97f21d61", size = 134014, upload-time = "2026-05-06T15:10:08.213Z" },
{ url = "https://files.pythonhosted.org/packages/50/c7/375e83a76851b73b2e39f3bcf0e5a19e2b89bad13e5bca97d0b293d27f24/orjson-3.11.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a8f5f8bc7ce7d59f08d9f99fa510c06496164a24cb5f3d34537dbd9ca30132e2", size = 141509, upload-time = "2026-05-06T15:10:09.595Z" },
{ url = "https://files.pythonhosted.org/packages/7f/7c/49d5d82a3d3097f641f094f552131f1e2723b0b8cb0fa2874ab65ecfffa6/orjson-3.11.9-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:4d7fde5501b944f83b3e665e1b31343ff6e154b15560a16b7130ea1e594a4206", size = 415127, upload-time = "2026-05-06T15:10:11.049Z" },
{ url = "https://files.pythonhosted.org/packages/3a/dc/7446c538590d55f455647e5f3c61fc33f7108714e7afcffa6a2a033f8350/orjson-3.11.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cde1a448023ba7d5bb4c01c5afb48894380b5e4956e0627266526587ef4e535f", size = 148025, upload-time = "2026-05-06T15:10:12.842Z" },
{ url = "https://files.pythonhosted.org/packages/df/e5/4d2d8af06f788329b4f78f8cc3679bb395392fcaa1e4d8d3c33e85308fa4/orjson-3.11.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:71e63adb0e1f1ed5d9e168f50a91ceb93ae6420731d222dc7da5c69409aa47aa", size = 136943, upload-time = "2026-05-06T15:10:14.405Z" },
{ url = "https://files.pythonhosted.org/packages/06/69/850264ccf6d80f6b174620d30a87f65c9b1490aba33fe6b62798e618cad3/orjson-3.11.9-cp312-cp312-win32.whl", hash = "sha256:2d057a602cdd19a0ad680417527c45b6961a095081c0f46fe0e03e304aac6470", size = 131606, upload-time = "2026-05-06T15:10:15.791Z" },
{ url = "https://files.pythonhosted.org/packages/b9/d5/973a43fc9c55e20f2051e9830997649f669be0cb3ca52192087c0143f118/orjson-3.11.9-cp312-cp312-win_amd64.whl", hash = "sha256:59e403b1cc5a676da8eaf31f6254801b7341b3e29efa85f92b48d272637e77be", size = 127101, upload-time = "2026-05-06T15:10:17.129Z" },
{ url = "https://files.pythonhosted.org/packages/fe/ae/495470f0e4a18f73fa10b7f6b84b464ec4cc5291c4e0c7c2a6c400bef006/orjson-3.11.9-cp312-cp312-win_arm64.whl", hash = "sha256:9af678d6488357948f1f84c6cd1c1d397c014e1ae2f98ae082a44eb48f602624", size = 126736, upload-time = "2026-05-06T15:10:18.645Z" },
{ url = "https://files.pythonhosted.org/packages/32/33/93fcc25907235c344ae73122f8a4e01d2d393ef062b4af7d2e2487a32c37/orjson-3.11.9-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4bab1b2d6141fe7b32ae71dac905666ece4f94936efbfb13d55bb7739a3a6021", size = 228458, upload-time = "2026-05-06T15:10:20.079Z" },
{ url = "https://files.pythonhosted.org/packages/8f/27/b1e6dadb3c080313c03fdd8067b85e6a0460c7d8d6a1c3984ef77b904e4d/orjson-3.11.9-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:844417969855fc7a41be124aafe83dc424592a7f77cd4501900c67307122b92c", size = 128368, upload-time = "2026-05-06T15:10:21.549Z" },
{ url = "https://files.pythonhosted.org/packages/21/0f/c9ede0bf052f6b4051e64a7d4fa91b725cccf8321a6a786e86eb03519f00/orjson-3.11.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffe02797b5e9f3a9d8292ddcd289b474ad13e81ad83cd1891a240811f1d2cb81", size = 132070, upload-time = "2026-05-06T15:10:23.371Z" },
{ url = "https://files.pythonhosted.org/packages/fd/26/d398e28048dc18205bbe812f2c88cb9b40313db2470778e25964796458fe/orjson-3.11.9-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e4eed3b200023042814d2fc8a5d2e880f13b52e1ed2485e83da4f3962f7dc1a", size = 127892, upload-time = "2026-05-06T15:10:24.714Z" },
{ url = "https://files.pythonhosted.org/packages/66/60/52b0054c4c700d5aa7fc5b7ca96917400d8f061307778578e67a10e25852/orjson-3.11.9-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aff7da9952a5ad1cef8e68017724d96c7b9a66e99e91d6252e1b133d67a7b10", size = 135217, upload-time = "2026-05-06T15:10:26.084Z" },
{ url = "https://files.pythonhosted.org/packages/d5/97/1e3dc2b2a28b7b2528f403d2fc1d79ec5f39af3bc143ab65d3ec26426385/orjson-3.11.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d4e98d6f3b8afed8bc8cd9718ec0cdf46661826beefb53fe8eafb37f2bf0362", size = 145980, upload-time = "2026-05-06T15:10:28.062Z" },
{ url = "https://files.pythonhosted.org/packages/fc/39/31fbfe7850f2de32dee7e7e5c09f26d403ab01e440ac96001c6b01ad3c99/orjson-3.11.9-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a81d52442a7c99b3662333235b3adf96a1715864658b35bb797212be7bddb97", size = 132738, upload-time = "2026-05-06T15:10:29.727Z" },
{ url = "https://files.pythonhosted.org/packages/a1/08/dca0082dd2a194acb93e5457e73455388e2e2ca464a2672449a9ddbb679d/orjson-3.11.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e39364e726a8fff737309aff059ff67d8a8c8d5b677be7bb49a8b3e84b7e218", size = 134033, upload-time = "2026-05-06T15:10:31.152Z" },
{ url = "https://files.pythonhosted.org/packages/11/d4/5bdb0626801230139987385554c5d4c42255218ac906525bf4347f22cd95/orjson-3.11.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4fd66214623f1b17501df9f0543bef0b833979ab5b6ded1e1d123222866aa8c9", size = 141492, upload-time = "2026-05-06T15:10:32.641Z" },
{ url = "https://files.pythonhosted.org/packages/fa/88/a21fb53b3ede6703aede6dce4710ed4111e5b201cfa6bbff5e544f9d47d7/orjson-3.11.9-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8ecc30f10465fa1e0ce13fd01d9e22c316e5053a719a8d915d4545a09a5ff677", size = 415087, upload-time = "2026-05-06T15:10:34.438Z" },
{ url = "https://files.pythonhosted.org/packages/3d/57/1b30daf70f0d8180e9a73cefbfbdd99e4bf19eb020466502b01fba7e0e50/orjson-3.11.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:97db4c94a7db398a5bd636273324f0b3fd58b350bbbac8bb380ceb825a9b40f4", size = 148031, upload-time = "2026-05-06T15:10:36.358Z" },
{ url = "https://files.pythonhosted.org/packages/04/83/45fbb6d962e260807f99441db9613cee868ceda4baceda59b3720a563f97/orjson-3.11.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f78cf8fec5bd627f4082b8dfeac7871b43d7f3274904492a43dab39f18a19a0", size = 136915, upload-time = "2026-05-06T15:10:38.013Z" },
{ url = "https://files.pythonhosted.org/packages/5f/cc/2d10025f9056d376e4127ec05a5808b218d46f035fdc08178a5411b34250/orjson-3.11.9-cp313-cp313-win32.whl", hash = "sha256:d4087e5c0209a0a8efe4de3303c234b9c44d1174161dcd851e8eea07c7560b32", size = 131613, upload-time = "2026-05-06T15:10:39.569Z" },
{ url = "https://files.pythonhosted.org/packages/67/bd/2775ff28bfe883b9aa1ff348300542eb2ef1ee18d8ae0e3a49846817a865/orjson-3.11.9-cp313-cp313-win_amd64.whl", hash = "sha256:051b102c93b4f634e89f3866b07b9a9a98915ada541f4ec30f177067b2694979", size = 127086, upload-time = "2026-05-06T15:10:41.262Z" },
{ url = "https://files.pythonhosted.org/packages/91/2b/d26799e580939e32a7da9a39531bc9e58e15ca32ffaa6a8cb3e9bb0d22cd/orjson-3.11.9-cp313-cp313-win_arm64.whl", hash = "sha256:cce9127885941bd28f080cecf1f1d288336b7e0d812c345b08be88b572796254", size = 126696, upload-time = "2026-05-06T15:10:42.651Z" },
{ url = "https://files.pythonhosted.org/packages/8e/eb/5da01e356015aee6ecfa1187ced87aef51364e306f5e695dd52719bf0e78/orjson-3.11.9-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b6ef1979adc4bc243523f1a2ba91418030a8e29b0a99cbe7e0e2d6807d4dce6e", size = 228465, upload-time = "2026-05-06T15:10:44.097Z" },
{ url = "https://files.pythonhosted.org/packages/64/62/3e0e0c14c957133bcd855395c62b55ed4e3b0af23ffea11b032cb1dcbdb1/orjson-3.11.9-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:f36b7f32c7c0db4a719f1fc5824db4a9c6f8bd1a354debb91faf26ebf3a4c71e", size = 128364, upload-time = "2026-05-06T15:10:45.839Z" },
{ url = "https://files.pythonhosted.org/packages/5a/5a/07d8aa117211a8ed7630bda80c8c0b14d04e0f8dcf99bcf49656e4a710eb/orjson-3.11.9-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08f4d8ebb44925c794e535b2bebc507cebf32209df81de22ae285fb0d8d66de0", size = 132063, upload-time = "2026-05-06T15:10:47.267Z" },
{ url = "https://files.pythonhosted.org/packages/d6/ec/4acaf21483e18aa945be74a474c74b434f284b549f275a0a39b9f98956e9/orjson-3.11.9-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6cc7923789694fd58f001cbcac7e47abc13af4d560ebbfcf3b41a8b1a0748124", size = 122356, upload-time = "2026-05-06T15:10:48.765Z" },
{ url = "https://files.pythonhosted.org/packages/13/d8/5f0555e7638801323b7a75850f92e7dfa891bc84fe27a1ba4449170d1200/orjson-3.11.9-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea5c46eb2d3af39e806b986f4b09d5c2706a1f5afde3cbf7544ce6616127173c", size = 129592, upload-time = "2026-05-06T15:10:50.13Z" },
{ url = "https://files.pythonhosted.org/packages/b6/30/ed9860412a3603ceb3c5955bfd72d28b9d0e7ba6ed81add14f83d7114236/orjson-3.11.9-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f5d89a2ed90731df3be64bab0aa44f78bff39fdc9d71c291f4a8023aa46425b7", size = 140491, upload-time = "2026-05-06T15:10:51.582Z" },
{ url = "https://files.pythonhosted.org/packages/d0/17/adc514dea7ac7c505527febf884934b815d34f0c7b8693c1a8b39c5c4a57/orjson-3.11.9-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25e4aed0312d292c09f61af25bba34e0b2c88546041472b09088c39a4d828af1", size = 127309, upload-time = "2026-05-06T15:10:53.329Z" },
{ url = "https://files.pythonhosted.org/packages/76/3e/c0b690253f0b82d86e99949af13533363acfb5432ecb5d53dd5b3bce9c34/orjson-3.11.9-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaea64f3f467d22e70eeed68bdccb3bc4f83f650446c4a03c59f2cba28a108db", size = 134030, upload-time = "2026-05-06T15:10:54.988Z" },
{ url = "https://files.pythonhosted.org/packages/c1/7a/bc82a0bb25e9faaf92dc4d9ef002732efc09737706af83e346788641d4a7/orjson-3.11.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a028425d1b440c5d92a6be1e1a020739dfe67ea87d96c6dbe828c1b30041728b", size = 141482, upload-time = "2026-05-06T15:10:56.663Z" },
{ url = "https://files.pythonhosted.org/packages/01/55/e69188b939f77d5d32a9833745ace31ea5ccae3ab613a1ec185d3cd2c4fb/orjson-3.11.9-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:5b192c6cf397e4455b11523c5cf2b18ed084c1bbd61b6c0926344d2129481972", size = 415178, upload-time = "2026-05-06T15:10:58.446Z" },
{ url = "https://files.pythonhosted.org/packages/2e/1a/b8a5a7ac527e80b9cb11d51e3f6689b709279183264b9ec5c7bc680bb8b5/orjson-3.11.9-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ea407d4ccf5891d667d045fecae97a7a1e5e87b3b97f97ae1803c2e741130be0", size = 148089, upload-time = "2026-05-06T15:11:00.441Z" },
{ url = "https://files.pythonhosted.org/packages/97/4e/00503f64204bf859b37213a63927028f30fb6268cd8677fb0a5ad48155e1/orjson-3.11.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5f63aaf97afd9f6dec5b1a68e1b8da12bfccb4cb9a9a65c3e0b6c847849e7586", size = 136921, upload-time = "2026-05-06T15:11:02.176Z" },
{ url = "https://files.pythonhosted.org/packages/0d/ba/a23b82a0a8d0ed7bed4e5f5035aae751cad4ff6a1e8d2ecd14d8860f5929/orjson-3.11.9-cp314-cp314-win32.whl", hash = "sha256:e30ab17845bb9fa54ccf67fa4f9f5282652d54faa6d17452f47d0f369d038673", size = 131638, upload-time = "2026-05-06T15:11:03.696Z" },
{ url = "https://files.pythonhosted.org/packages/f3/c3/0c6798456bade745c75c452342dabacce5798196483e77e643be1f53877d/orjson-3.11.9-cp314-cp314-win_amd64.whl", hash = "sha256:32ef5f4283a3be81913947d19608eacb7c6608026851123790cd9cc8982af34b", size = 127078, upload-time = "2026-05-06T15:11:05.123Z" },
{ url = "https://files.pythonhosted.org/packages/16/21/5a3f1e8913103b703a436a5664238e5b965ec392b555fe68943ea3691e6b/orjson-3.11.9-cp314-cp314-win_arm64.whl", hash = "sha256:eebdbdeef0094e4f5aefa20dcd4eb2368ab5e7a3b4edea27f1e7b2892e009cf9", size = 126687, upload-time = "2026-05-06T15:11:06.602Z" },
]
[[package]]
@@ -2080,7 +2121,7 @@ wheels = [
[[package]]
name = "pydantic"
version = "2.12.5"
version = "2.13.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "annotated-types" },
@@ -2088,120 +2129,125 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "typing-inspection" },
]
sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" }
sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" },
{ url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" },
]
[[package]]
name = "pydantic-core"
version = "2.41.5"
version = "2.46.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" }
sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z" },
{ url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z" },
{ url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z" },
{ url = "https://files.pythonhosted.org/packages/6e/6a/30d94a9674a7fe4f4744052ed6c5e083424510be1e93da5bc47569d11810/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", size = 2063890, upload-time = "2025-11-04T13:39:36.053Z" },
{ url = "https://files.pythonhosted.org/packages/50/be/76e5d46203fcb2750e542f32e6c371ffa9b8ad17364cf94bb0818dbfb50c/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", size = 2229740, upload-time = "2025-11-04T13:39:37.753Z" },
{ url = "https://files.pythonhosted.org/packages/d3/ee/fed784df0144793489f87db310a6bbf8118d7b630ed07aa180d6067e653a/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", size = 2350021, upload-time = "2025-11-04T13:39:40.94Z" },
{ url = "https://files.pythonhosted.org/packages/c8/be/8fed28dd0a180dca19e72c233cbf58efa36df055e5b9d90d64fd1740b828/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", size = 2066378, upload-time = "2025-11-04T13:39:42.523Z" },
{ url = "https://files.pythonhosted.org/packages/b0/3b/698cf8ae1d536a010e05121b4958b1257f0b5522085e335360e53a6b1c8b/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", size = 2175761, upload-time = "2025-11-04T13:39:44.553Z" },
{ url = "https://files.pythonhosted.org/packages/b8/ba/15d537423939553116dea94ce02f9c31be0fa9d0b806d427e0308ec17145/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", size = 2146303, upload-time = "2025-11-04T13:39:46.238Z" },
{ url = "https://files.pythonhosted.org/packages/58/7f/0de669bf37d206723795f9c90c82966726a2ab06c336deba4735b55af431/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", size = 2340355, upload-time = "2025-11-04T13:39:48.002Z" },
{ url = "https://files.pythonhosted.org/packages/e5/de/e7482c435b83d7e3c3ee5ee4451f6e8973cff0eb6007d2872ce6383f6398/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", size = 2319875, upload-time = "2025-11-04T13:39:49.705Z" },
{ url = "https://files.pythonhosted.org/packages/fe/e6/8c9e81bb6dd7560e33b9053351c29f30c8194b72f2d6932888581f503482/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", size = 1987549, upload-time = "2025-11-04T13:39:51.842Z" },
{ url = "https://files.pythonhosted.org/packages/11/66/f14d1d978ea94d1bc21fc98fcf570f9542fe55bfcc40269d4e1a21c19bf7/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", size = 2011305, upload-time = "2025-11-04T13:39:53.485Z" },
{ url = "https://files.pythonhosted.org/packages/56/d8/0e271434e8efd03186c5386671328154ee349ff0354d83c74f5caaf096ed/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", size = 1972902, upload-time = "2025-11-04T13:39:56.488Z" },
{ url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" },
{ url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" },
{ url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" },
{ url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" },
{ url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" },
{ url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" },
{ url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" },
{ url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" },
{ url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" },
{ url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" },
{ url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" },
{ url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" },
{ url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" },
{ url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" },
{ url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" },
{ url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" },
{ url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" },
{ url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" },
{ url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" },
{ url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" },
{ url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" },
{ url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" },
{ url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" },
{ url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" },
{ url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" },
{ url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" },
{ url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" },
{ url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" },
{ url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" },
{ url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" },
{ url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" },
{ url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" },
{ url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" },
{ url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" },
{ url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" },
{ url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" },
{ url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" },
{ url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" },
{ url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" },
{ url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" },
{ url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" },
{ url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" },
{ url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" },
{ url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" },
{ url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" },
{ url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" },
{ url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" },
{ url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" },
{ url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" },
{ url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" },
{ url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" },
{ url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" },
{ url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" },
{ url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" },
{ url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" },
{ url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" },
{ url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z" },
{ url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z" },
{ url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z" },
{ url = "https://files.pythonhosted.org/packages/2e/1b/687711069de7efa6af934e74f601e2a4307365e8fdc404703afc453eab26/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", size = 2138905, upload-time = "2025-11-04T13:42:47.156Z" },
{ url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" },
{ url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" },
{ url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" },
{ url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" },
{ url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z" },
{ url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z" },
{ url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z" },
{ url = "https://files.pythonhosted.org/packages/83/d9/8412d7f06f616bbc053d30cb4e5f76786af3221462ad5eee1f202021eb4e/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", size = 2174762, upload-time = "2025-11-04T13:43:34.744Z" },
{ url = "https://files.pythonhosted.org/packages/55/4c/162d906b8e3ba3a99354e20faa1b49a85206c47de97a639510a0e673f5da/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", size = 2143141, upload-time = "2025-11-04T13:43:37.701Z" },
{ url = "https://files.pythonhosted.org/packages/1f/f2/f11dd73284122713f5f89fc940f370d035fa8e1e078d446b3313955157fe/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", size = 2330317, upload-time = "2025-11-04T13:43:40.406Z" },
{ url = "https://files.pythonhosted.org/packages/88/9d/b06ca6acfe4abb296110fb1273a4d848a0bfb2ff65f3ee92127b3244e16b/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", size = 2316992, upload-time = "2025-11-04T13:43:43.602Z" },
{ url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" },
{ url = "https://files.pythonhosted.org/packages/5c/fa/6d7708d2cfc1a832acb6aeb0cd16e801902df8a0f583bb3b4b527fde022e/pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594", size = 2111872, upload-time = "2026-05-06T13:40:27.596Z" },
{ url = "https://files.pythonhosted.org/packages/ae/6f/aa064a3e74b5745afbdf250594f38e7ead05e2d651bcb35994b9417a0d4d/pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c", size = 1948255, upload-time = "2026-05-06T13:39:12.574Z" },
{ url = "https://files.pythonhosted.org/packages/43/3a/41114a9f7569b84b4d84e7a018c57c56347dac30c0d4a872946ec4e36c46/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826", size = 1972827, upload-time = "2026-05-06T13:38:19.841Z" },
{ url = "https://files.pythonhosted.org/packages/ef/25/1ab42e8048fe551934d9884e8d64daa7e990ad386f310a15981aeb6a5b08/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04", size = 2041051, upload-time = "2026-05-06T13:38:10.447Z" },
{ url = "https://files.pythonhosted.org/packages/94/c2/1a934597ddf08da410385b3b7aae91956a5a76c635effef456074fad7e88/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e", size = 2221314, upload-time = "2026-05-06T13:40:13.089Z" },
{ url = "https://files.pythonhosted.org/packages/02/6d/9e8ad178c9c4df27ad3c8f25d1fe2a7ab0d2ba0559fad4aee5d3d1f16771/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3", size = 2285146, upload-time = "2026-05-06T13:38:59.224Z" },
{ url = "https://files.pythonhosted.org/packages/80/50/540cd3aeefc041beb111125c4bff779831a2111fc6b15a9138cda277d32c/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4", size = 2089685, upload-time = "2026-05-06T13:38:17.762Z" },
{ url = "https://files.pythonhosted.org/packages/6b/a4/b440ad35f05f6a38f89fa0f149accb3f0e02be94ca5e15f3c449a61b4bc9/pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398", size = 2115420, upload-time = "2026-05-06T13:37:58.195Z" },
{ url = "https://files.pythonhosted.org/packages/99/61/de4f55db8dfd57bfdfa9a12ec90fe1b57c4f41062f7ca86f08586b3e0ac0/pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3", size = 2165122, upload-time = "2026-05-06T13:37:01.167Z" },
{ url = "https://files.pythonhosted.org/packages/f7/52/7c529d7bdb2d1068bd52f51fe32572c8301f9a4febf1948f10639f1436f5/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848", size = 2182573, upload-time = "2026-05-06T13:38:45.04Z" },
{ url = "https://files.pythonhosted.org/packages/37/b3/7c40325848ba78247f2812dcf9c7274e38cd801820ca6dd9fe63bcfb0eb4/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3", size = 2317139, upload-time = "2026-05-06T13:37:15.539Z" },
{ url = "https://files.pythonhosted.org/packages/d9/37/f913f81a657c865b75da6c0dbed79876073c2a43b5bd9edbe8da785e4d49/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109", size = 2360433, upload-time = "2026-05-06T13:37:30.099Z" },
{ url = "https://files.pythonhosted.org/packages/c4/67/6acaa1be2567f9256b056d8477158cac7240813956ce86e49deae8e173b4/pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda", size = 1985513, upload-time = "2026-05-06T13:38:15.669Z" },
{ url = "https://files.pythonhosted.org/packages/aa/e6/c505f83dfeda9a2e5c995cfd872949e4d05e12f7feb3dca72f633daefa94/pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33", size = 2071114, upload-time = "2026-05-06T13:40:35.416Z" },
{ url = "https://files.pythonhosted.org/packages/0f/da/7a263a96d965d9d0df5e8de8a475f33495451117035b09acb110288c381f/pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d", size = 2044298, upload-time = "2026-05-06T13:38:29.754Z" },
{ url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" },
{ url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" },
{ url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" },
{ url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" },
{ url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" },
{ url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" },
{ url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" },
{ url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" },
{ url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" },
{ url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" },
{ url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" },
{ url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" },
{ url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" },
{ url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" },
{ url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" },
{ url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" },
{ url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" },
{ url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" },
{ url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" },
{ url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" },
{ url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" },
{ url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" },
{ url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" },
{ url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" },
{ url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" },
{ url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" },
{ url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" },
{ url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" },
{ url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" },
{ url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" },
{ url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" },
{ url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" },
{ url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" },
{ url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" },
{ url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" },
{ url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" },
{ url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" },
{ url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" },
{ url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" },
{ url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" },
{ url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" },
{ url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" },
{ url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" },
{ url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" },
{ url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" },
{ url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" },
{ url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" },
{ url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" },
{ url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" },
{ url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" },
{ url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" },
{ url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" },
{ url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" },
{ url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" },
{ url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" },
{ url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" },
{ url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" },
{ url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" },
{ url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" },
{ url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" },
{ url = "https://files.pythonhosted.org/packages/ee/a4/73995fd4ebbb46ba0ee51e6fa049b8f02c40daebb762208feda8a6b7894d/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c", size = 2111589, upload-time = "2026-05-06T13:37:10.817Z" },
{ url = "https://files.pythonhosted.org/packages/fb/7f/f37d3a5e8bfcc2e403f5c57a730f2d815693fb42119e8ea48b3789335af1/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b", size = 1944552, upload-time = "2026-05-06T13:36:56.717Z" },
{ url = "https://files.pythonhosted.org/packages/15/3c/d7eb777b3ff43e8433a4efb39a17aa8fd98a4ee8561a24a67ef5db07b2d6/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b", size = 1982984, upload-time = "2026-05-06T13:39:06.207Z" },
{ url = "https://files.pythonhosted.org/packages/63/87/70b9f40170a81afd55ca26c9b2acb25c20d64bcfbf888fafecb3ba077d4c/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea", size = 2138417, upload-time = "2026-05-06T13:39:45.476Z" },
{ url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" },
{ url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" },
{ url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" },
{ url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" },
{ url = "https://files.pythonhosted.org/packages/11/cb/428de0385b6c8d44b716feba566abfacfbd23ee3c4439faa789a1456242f/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0", size = 2112782, upload-time = "2026-05-06T13:37:04.016Z" },
{ url = "https://files.pythonhosted.org/packages/0b/b5/6a17bdadd0fc1f170adfd05a20d37c832f52b117b4d9131da1f41bb097ce/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7", size = 1952146, upload-time = "2026-05-06T13:39:43.092Z" },
{ url = "https://files.pythonhosted.org/packages/2a/dc/03734d80e362cd43ef65428e9de77c730ce7f2f11c60d2b1e1b39f0fbf99/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2", size = 2134492, upload-time = "2026-05-06T13:36:58.124Z" },
{ url = "https://files.pythonhosted.org/packages/de/df/5e5ffc085ed07cc22d298134d3d911c63e91f6a0eb91fe646750a3209910/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9", size = 2156604, upload-time = "2026-05-06T13:37:49.88Z" },
{ url = "https://files.pythonhosted.org/packages/81/44/6e112a4253e56f5705467cbab7ab5e91ee7398ba3d56d358635958893d3e/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf", size = 2183828, upload-time = "2026-05-06T13:37:43.053Z" },
{ url = "https://files.pythonhosted.org/packages/ac/ad/5565071e937d8e752842ac241463944c9eb14c87e2d269f2658a5bd05e98/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30", size = 2310000, upload-time = "2026-05-06T13:37:56.694Z" },
{ url = "https://files.pythonhosted.org/packages/4f/c3/66883a5cec183e7fba4d024b4cbbe61851a63750ef606b0afecc46d1f2bf/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc", size = 2361286, upload-time = "2026-05-06T13:40:05.667Z" },
{ url = "https://files.pythonhosted.org/packages/4b/2d/69abac8f838090bbecd5df894befb2c2619e7996a98ddb949db9f3b93225/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983", size = 2193071, upload-time = "2026-05-06T13:38:08.682Z" },
]
[[package]]
name = "pydantic-settings"
version = "2.13.1"
version = "2.14.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic" },
{ name = "python-dotenv" },
{ name = "typing-inspection" },
]
sdist = { url = "https://files.pythonhosted.org/packages/52/6d/fffca34caecc4a3f97bda81b2098da5e8ab7efc9a66e819074a11955d87e/pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025", size = 223826, upload-time = "2026-02-19T13:45:08.055Z" }
sdist = { url = "https://files.pythonhosted.org/packages/07/60/1d1e59c9c90d54591469ada7d268251f71c24bdb765f1a8a832cee8c6653/pydantic_settings-2.14.1.tar.gz", hash = "sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa", size = 235551, upload-time = "2026-05-08T13:40:06.542Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/00/4b/ccc026168948fec4f7555b9164c724cf4125eac006e176541483d2c959be/pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237", size = 58929, upload-time = "2026-02-19T13:45:06.034Z" },
{ url = "https://files.pythonhosted.org/packages/ae/8d/f1af3832f5e6eb13ba94ee809e72b8ecb5eef226d27ee0bef7d963d943c7/pydantic_settings-2.14.1-py3-none-any.whl", hash = "sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de", size = 60964, upload-time = "2026-05-08T13:40:04.958Z" },
]
[[package]]
@@ -2312,11 +2358,11 @@ wheels = [
[[package]]
name = "python-multipart"
version = "0.0.27"
version = "0.0.29"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/69/9b/f23807317a113dc36e74e75eb265a02dd1a4d9082abc3c1064acd22997c4/python_multipart-0.0.27.tar.gz", hash = "sha256:9870a6a8c5a20a5bf4f07c017bd1489006ff8836cff097b6933355ee2b49b602", size = 44043, upload-time = "2026-04-27T10:51:26.649Z" }
sdist = { url = "https://files.pythonhosted.org/packages/4e/fe/70bd71a6738b09a0bdf6480ca6436b167469ca4578b2a0efbe390b4b0e70/python_multipart-0.0.29.tar.gz", hash = "sha256:643e93849196645e2dbdd81a0f8829a23123ad7f797a84a364c6fb3563f18904", size = 45678, upload-time = "2026-05-17T17:29:47.654Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/99/78/4126abcbdbd3c559d43e0db7f7b9173fc6befe45d39a2856cc0b8ec2a5a6/python_multipart-0.0.27-py3-none-any.whl", hash = "sha256:6fccfad17a27334bd0193681b369f476eda3409f17381a2d65aa7df3f7275645", size = 29254, upload-time = "2026-04-27T10:51:24.997Z" },
{ url = "https://files.pythonhosted.org/packages/8f/cb/769cfc37177252872a45a71f3fbdde9d51b471a3f3c14bfe95dde3407386/python_multipart-0.0.29-py3-none-any.whl", hash = "sha256:2ddcc971cef266225f54f552d8fa10bcfbb1f14446caec199060daac59ff2d69", size = 29640, upload-time = "2026-05-17T17:29:45.69Z" },
]
[[package]]
@@ -2577,27 +2623,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.15.10"
version = "0.15.13"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e7/d9/aa3f7d59a10ef6b14fe3431706f854dbf03c5976be614a9796d36326810c/ruff-0.15.10.tar.gz", hash = "sha256:d1f86e67ebfdef88e00faefa1552b5e510e1d35f3be7d423dc7e84e63788c94e", size = 4631728, upload-time = "2026-04-09T14:06:09.884Z" }
sdist = { url = "https://files.pythonhosted.org/packages/24/21/a7d5c126d5b557715ef81098f3db2fe20f622a039ff2e626af28d674ab80/ruff-0.15.13.tar.gz", hash = "sha256:f9d89f17f7ba7fb2ed42921f0df75da797a9a5d71bc39049e2c687cf2baf44b7", size = 4678180, upload-time = "2026-05-14T13:44:37.869Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/eb/00/a1c2fdc9939b2c03691edbda290afcd297f1f389196172826b03d6b6a595/ruff-0.15.10-py3-none-linux_armv6l.whl", hash = "sha256:0744e31482f8f7d0d10a11fcbf897af272fefdfcb10f5af907b18c2813ff4d5f", size = 10563362, upload-time = "2026-04-09T14:06:21.189Z" },
{ url = "https://files.pythonhosted.org/packages/5c/15/006990029aea0bebe9d33c73c3e28c80c391ebdba408d1b08496f00d422d/ruff-0.15.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b1e7c16ea0ff5a53b7c2df52d947e685973049be1cdfe2b59a9c43601897b22e", size = 10951122, upload-time = "2026-04-09T14:06:02.236Z" },
{ url = "https://files.pythonhosted.org/packages/f2/c0/4ac978fe874d0618c7da647862afe697b281c2806f13ce904ad652fa87e4/ruff-0.15.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:93cc06a19e5155b4441dd72808fdf84290d84ad8a39ca3b0f994363ade4cebb1", size = 10314005, upload-time = "2026-04-09T14:06:00.026Z" },
{ url = "https://files.pythonhosted.org/packages/da/73/c209138a5c98c0d321266372fc4e33ad43d506d7e5dd817dd89b60a8548f/ruff-0.15.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83e1dd04312997c99ea6965df66a14fb4f03ba978564574ffc68b0d61fd3989e", size = 10643450, upload-time = "2026-04-09T14:05:42.137Z" },
{ url = "https://files.pythonhosted.org/packages/ec/76/0deec355d8ec10709653635b1f90856735302cb8e149acfdf6f82a5feb70/ruff-0.15.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8154d43684e4333360fedd11aaa40b1b08a4e37d8ffa9d95fee6fa5b37b6fab1", size = 10379597, upload-time = "2026-04-09T14:05:49.984Z" },
{ url = "https://files.pythonhosted.org/packages/dc/be/86bba8fc8798c081e28a4b3bb6d143ccad3fd5f6f024f02002b8f08a9fa3/ruff-0.15.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ab88715f3a6deb6bde6c227f3a123410bec7b855c3ae331b4c006189e895cef", size = 11146645, upload-time = "2026-04-09T14:06:12.246Z" },
{ url = "https://files.pythonhosted.org/packages/a8/89/140025e65911b281c57be1d385ba1d932c2366ca88ae6663685aed8d4881/ruff-0.15.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a768ff5969b4f44c349d48edf4ab4f91eddb27fd9d77799598e130fb628aa158", size = 12030289, upload-time = "2026-04-09T14:06:04.776Z" },
{ url = "https://files.pythonhosted.org/packages/88/de/ddacca9545a5e01332567db01d44bd8cf725f2db3b3d61a80550b48308ea/ruff-0.15.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ee3ef42dab7078bda5ff6a1bcba8539e9857deb447132ad5566a038674540d0", size = 11496266, upload-time = "2026-04-09T14:05:55.485Z" },
{ url = "https://files.pythonhosted.org/packages/bc/bb/7ddb00a83760ff4a83c4e2fc231fd63937cc7317c10c82f583302e0f6586/ruff-0.15.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51cb8cc943e891ba99989dd92d61e29b1d231e14811db9be6440ecf25d5c1609", size = 11256418, upload-time = "2026-04-09T14:05:57.69Z" },
{ url = "https://files.pythonhosted.org/packages/dc/8d/55de0d35aacf6cd50b6ee91ee0f291672080021896543776f4170fc5c454/ruff-0.15.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:e59c9bdc056a320fb9ea1700a8d591718b8faf78af065484e801258d3a76bc3f", size = 11288416, upload-time = "2026-04-09T14:05:44.695Z" },
{ url = "https://files.pythonhosted.org/packages/68/cf/9438b1a27426ec46a80e0a718093c7f958ef72f43eb3111862949ead3cc1/ruff-0.15.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:136c00ca2f47b0018b073f28cb5c1506642a830ea941a60354b0e8bc8076b151", size = 10621053, upload-time = "2026-04-09T14:05:52.782Z" },
{ url = "https://files.pythonhosted.org/packages/4c/50/e29be6e2c135e9cd4cb15fbade49d6a2717e009dff3766dd080fcb82e251/ruff-0.15.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b80a2f3c9c8a950d6237f2ca12b206bccff626139be9fa005f14feb881a1ae8", size = 10378302, upload-time = "2026-04-09T14:06:14.361Z" },
{ url = "https://files.pythonhosted.org/packages/18/2f/e0b36a6f99c51bb89f3a30239bc7bf97e87a37ae80aa2d6542d6e5150364/ruff-0.15.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e3e53c588164dc025b671c9df2462429d60357ea91af7e92e9d56c565a9f1b07", size = 10850074, upload-time = "2026-04-09T14:06:16.581Z" },
{ url = "https://files.pythonhosted.org/packages/11/08/874da392558ce087a0f9b709dc6ec0d60cbc694c1c772dab8d5f31efe8cb/ruff-0.15.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b0c52744cf9f143a393e284125d2576140b68264a93c6716464e129a3e9adb48", size = 11358051, upload-time = "2026-04-09T14:06:18.948Z" },
{ url = "https://files.pythonhosted.org/packages/e4/46/602938f030adfa043e67112b73821024dc79f3ab4df5474c25fa4c1d2d14/ruff-0.15.10-py3-none-win32.whl", hash = "sha256:d4272e87e801e9a27a2e8df7b21011c909d9ddd82f4f3281d269b6ba19789ca5", size = 10588964, upload-time = "2026-04-09T14:06:07.14Z" },
{ url = "https://files.pythonhosted.org/packages/25/b6/261225b875d7a13b33a6d02508c39c28450b2041bb01d0f7f1a83d569512/ruff-0.15.10-py3-none-win_amd64.whl", hash = "sha256:28cb32d53203242d403d819fd6983152489b12e4a3ae44993543d6fe62ab42ed", size = 11745044, upload-time = "2026-04-09T14:05:39.473Z" },
{ url = "https://files.pythonhosted.org/packages/58/ed/dea90a65b7d9e69888890fb14c90d7f51bf0c1e82ad800aeb0160e4bacfd/ruff-0.15.10-py3-none-win_arm64.whl", hash = "sha256:601d1610a9e1f1c2165a4f561eeaa2e2ea1e97f3287c5aa258d3dab8b57c6188", size = 11035607, upload-time = "2026-04-09T14:05:47.593Z" },
{ url = "https://files.pythonhosted.org/packages/c6/61/11d458dc6ac22504fd8e237b29dfd40504c7fbbcc8930402cfe51a8e63ed/ruff-0.15.13-py3-none-linux_armv6l.whl", hash = "sha256:444b580fc72fd6887e650acd3e575e18cdc79dbcf42fb4030b491057921f61f8", size = 10738279, upload-time = "2026-05-14T13:44:18.7Z" },
{ url = "https://files.pythonhosted.org/packages/86/ca/caa871ee7be718c45256fada4e16a218ee3e33f0c4a46b729a60a24912e6/ruff-0.15.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6590d009e7cb7ebf36f83dbdd44a3fa48a0994ff6f1cdc1b08006abe58f98dc7", size = 11124798, upload-time = "2026-05-14T13:44:06.427Z" },
{ url = "https://files.pythonhosted.org/packages/d3/19/43f5f2e568dddde567fc41f8471f9432c09563e19d3e617a48cfa52f8f0a/ruff-0.15.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1c26d2f66163deeb6e08d8b39fbbe983ce3c71cea06a6d7591cfd1421793c629", size = 10460761, upload-time = "2026-05-14T13:44:04.375Z" },
{ url = "https://files.pythonhosted.org/packages/99/df/cf938cd6de3003178f03ad7c1ea2a6c099468c03a35037985070b37e76be/ruff-0.15.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbd6f94b434f896308e4d57fb7bfde0d02b99f7a64b3bdab0fdfa6a864203a5", size = 10804451, upload-time = "2026-05-14T13:44:25.221Z" },
{ url = "https://files.pythonhosted.org/packages/c7/7d/5d0973129b154ded2225729169d7068f26b467760b146493fde138415f23/ruff-0.15.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf3259f3be4d181bda591da5db2571aed6853c6a048157756448020bc6c5cd22", size = 10534285, upload-time = "2026-05-14T13:44:08.888Z" },
{ url = "https://files.pythonhosted.org/packages/1f/e3/6b999bbc66cd51e5f073842bc2a3995e99c5e0e72e16b15e7261f7abf57a/ruff-0.15.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae9c17e5eb4430c154e76abc25d79a318190f5a997f38fb6b114416c5319ffc9", size = 11312063, upload-time = "2026-05-14T13:44:11.274Z" },
{ url = "https://files.pythonhosted.org/packages/af/5a/642639e9f5db04f1e97fbd6e091c6fd20725bdf072fb114d00eefb9e6eb8/ruff-0.15.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e2e39bff6c341f4b577a21b801326fab0b11847f48fcaa83f00a113c9b3cb55", size = 12183079, upload-time = "2026-05-14T13:44:01.634Z" },
{ url = "https://files.pythonhosted.org/packages/19/4c/7585735f6b53b0f12de13618b2f7d250a844f018822efc899df2e7b8295f/ruff-0.15.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e8d9a8e08013542e94d3220bc5b62cc3e5ef87c5f74bff367d3fac14fab013e6", size = 11440833, upload-time = "2026-05-14T13:43:59.043Z" },
{ url = "https://files.pythonhosted.org/packages/e8/31/bf1a0803d077e679cfeee5f2f67290a0fa79c7385b5d9a8c17b9db2c48f0/ruff-0.15.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc411dfebe5eebe55ce041c6ae080eb7668955e866daa2fbb16692a784f1c4ca", size = 11434486, upload-time = "2026-05-14T13:44:27.761Z" },
{ url = "https://files.pythonhosted.org/packages/e1/4e/62c9b999875d4f14db80f277c030578f5e249c9852d65b7ac7ad0b43c041/ruff-0.15.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:768494eb08b9cee54e2fd27969966f74db5a57f6eaa7a90fcb3306af34dfc4bd", size = 11385189, upload-time = "2026-05-14T13:44:13.704Z" },
{ url = "https://files.pythonhosted.org/packages/fc/89/7e959047a104df3eb12863447c110140191fc5b6c4f379ea2e803fcdb0e4/ruff-0.15.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:fb75f9a3a7e42ffe117d734494e6c5e5cb3565d66e12612cb63d0e572a41a5b6", size = 10781380, upload-time = "2026-05-14T13:43:56.734Z" },
{ url = "https://files.pythonhosted.org/packages/ff/52/5fd18f3b88cab63e88aa11516b3b4e1e5f720e5c330f8dbe5c26210f41f8/ruff-0.15.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8cb74dd33bb2f6613faf7fc03b660053b5ac4f80e706d5788c6335e2a8048d51", size = 10540605, upload-time = "2026-05-14T13:44:20.748Z" },
{ url = "https://files.pythonhosted.org/packages/e8/e0/9e35f338990d3e41a82875ff7053ffe97541dae81c9d02143177f381d572/ruff-0.15.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:7ef823f817fcd191dc934e984be9cf4094f808effa16f2542ad8e821ba02bbf2", size = 11036554, upload-time = "2026-05-14T13:44:16.256Z" },
{ url = "https://files.pythonhosted.org/packages/c2/13/070fb048c24080fba188f66371e2a92785be257ad02242066dc7255ac6e9/ruff-0.15.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f345a13937bd7f09f6f5d19fa0721b0c103e00e7f62bc67089a8e5e037719e0b", size = 11528133, upload-time = "2026-05-14T13:44:22.808Z" },
{ url = "https://files.pythonhosted.org/packages/6b/8c/b1e1666aef7fc6555094d73ae6cd981701781ae85b97ceefc0eebd0b4668/ruff-0.15.13-py3-none-win32.whl", hash = "sha256:4044f94208b3b05ba0fc4a4abd0558cf4d6459bd18325eead7fd8cc66f909b41", size = 10721455, upload-time = "2026-05-14T13:44:35.697Z" },
{ url = "https://files.pythonhosted.org/packages/ab/a6/870a3e8a50590bb92be184ad928c2922f088b00d9dc5c5ec7b924ee08c22/ruff-0.15.13-py3-none-win_amd64.whl", hash = "sha256:7064884d442b7d477b4e7473d12da7f08851d2b1982763c5d3f388a19468a1a4", size = 11900409, upload-time = "2026-05-14T13:44:30.389Z" },
{ url = "https://files.pythonhosted.org/packages/9b/36/9c015cd052fca743dae8cb2aeb16b551444787467db42ceab0fc968865af/ruff-0.15.13-py3-none-win_arm64.whl", hash = "sha256:2471da9bd1068c8c064b5fd9c0c4b6dddffd6369cb1cd68b29993b1709ff1b21", size = 11179336, upload-time = "2026-05-14T13:44:33.026Z" },
]
[[package]]
@@ -2974,41 +3020,41 @@ wheels = [
[[package]]
name = "types-pyyaml"
version = "6.0.12.20260408"
version = "6.0.12.20260518"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/74/73/b759b1e413c31034cc01ecdfb96b38115d0ab4db55a752a3929f0cd449fd/types_pyyaml-6.0.12.20260408.tar.gz", hash = "sha256:92a73f2b8d7f39ef392a38131f76b970f8c66e4c42b3125ae872b7c93b556307", size = 17735, upload-time = "2026-04-08T04:30:50.974Z" }
sdist = { url = "https://files.pythonhosted.org/packages/b8/83/4a1afc3fbfcf5b8d46fc390cd95ed6b0dc9010a265f4e9f46314efffa37a/types_pyyaml-6.0.12.20260518.tar.gz", hash = "sha256:d917f83fb38462550338c1297faedd860b3ec83912b96b1e3d73255f7473e466", size = 17850, upload-time = "2026-05-18T06:01:58.675Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/1c/f0/c391068b86abb708882c6d75a08cd7d25b2c7227dab527b3a3685a3c635b/types_pyyaml-6.0.12.20260408-py3-none-any.whl", hash = "sha256:fbc42037d12159d9c801ebfcc79ebd28335a7c13b08a4cfbc6916df78fee9384", size = 20339, upload-time = "2026-04-08T04:30:50.113Z" },
{ url = "https://files.pythonhosted.org/packages/06/a2/c01db32be2ae7d6a1689972f3c492b149ee4e164b12fdfd9f64b50888215/types_pyyaml-6.0.12.20260518-py3-none-any.whl", hash = "sha256:d2150f75a231c9fe9c7463bd29487d93e60bac90400287351384bc2284eba7cd", size = 20312, upload-time = "2026-05-18T06:01:57.368Z" },
]
[[package]]
name = "types-requests"
version = "2.33.0.20260408"
version = "2.33.0.20260518"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/69/6a/749dc53a54a3f35842c1f8197b3ca6b54af6d7458a1bfc75f6629b6da666/types_requests-2.33.0.20260408.tar.gz", hash = "sha256:95b9a86376807a216b2fb412b47617b202091c3ea7c078f47cc358d5528ccb7b", size = 23882, upload-time = "2026-04-08T04:34:49.33Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e0/01/c5a19253fe1ac159159ddf9a3a07cec8bb5e486ec4d9002ad2821da0e5d2/types_requests-2.33.0.20260518.tar.gz", hash = "sha256:df7bd3bfe0ca8402dfb841e7d9be714bb5578203283d66d7dc4ef69343449a5e", size = 24752, upload-time = "2026-05-18T06:07:37.966Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/90/b8/78fd6c037de4788c040fdd323b3369804400351b7827473920f6c1d03c10/types_requests-2.33.0.20260408-py3-none-any.whl", hash = "sha256:81f31d5ea4acb39f03be7bc8bed569ba6d5a9c5d97e89f45ac43d819b68ca50f", size = 20739, upload-time = "2026-04-08T04:34:48.325Z" },
{ url = "https://files.pythonhosted.org/packages/1c/bc/b139710a3b6018f7fb2b9508b35c8af564e61bf2bf4fa619d088f3e16f85/types_requests-2.33.0.20260518-py3-none-any.whl", hash = "sha256:626d697d1adaaff76e2044dc8c5c051d8f21abc157bdfe204a75558076fe0bf0", size = 21391, upload-time = "2026-05-18T06:07:37.044Z" },
]
[[package]]
name = "types-setuptools"
version = "82.0.0.20260408"
version = "82.0.0.20260518"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c3/12/3464b410c50420dd4674fa5fe9d3880711c1dbe1a06f5fe4960ee9067b9e/types_setuptools-82.0.0.20260408.tar.gz", hash = "sha256:036c68caf7e672a699f5ebbf914708d40644c14e05298bc49f7272be91cf43d3", size = 44861, upload-time = "2026-04-08T04:29:33.292Z" }
sdist = { url = "https://files.pythonhosted.org/packages/38/bc/73c2c27e047e42f114ac50fb3bdef986c56cbdb68096f8690eeafb839a93/types_setuptools-82.0.0.20260518.tar.gz", hash = "sha256:3b743cfe63d0981ea4c15b90710fc1ed41e3464a537d51e705be514e891c1d07", size = 44999, upload-time = "2026-05-18T06:02:55.642Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3d/e1/46a4fc3ef03aabf5d18bac9df5cf37c6b02c3bddf3e05c3533f4b4588331/types_setuptools-82.0.0.20260408-py3-none-any.whl", hash = "sha256:ece0a215cdfa6463a65fd6f68bd940f39e455729300ddfe61cab1147ed1d2462", size = 68428, upload-time = "2026-04-08T04:29:32.175Z" },
{ url = "https://files.pythonhosted.org/packages/32/8f/d5e2d493f09a7a98c95619edda1cb37cee377626c0a869d53274c26f2858/types_setuptools-82.0.0.20260518-py3-none-any.whl", hash = "sha256:31c04a62b57a653a5021caf191be0f10f70df890f813b51f02bab3969d300f20", size = 68444, upload-time = "2026-05-18T06:02:54.582Z" },
]
[[package]]
name = "types-simplejson"
version = "3.20.0.20260408"
version = "3.20.0.20260518"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/9f/36/e319fd0f6d906dbf7c2c03eef17db77ef461197a75b253fccd9c7c695d3e/types_simplejson-3.20.0.20260408.tar.gz", hash = "sha256:0b0e1bf61e70f81dfe6ef4c2b9c02e39403848c0652df334e7a430c3a26c06b3", size = 10693, upload-time = "2026-04-08T04:28:07.8Z" }
sdist = { url = "https://files.pythonhosted.org/packages/a5/e4/f8ecdc3529688ad058b0496f67a1bdfbd2576c3669e1c478b6347b12cb7e/types_simplejson-3.20.0.20260518.tar.gz", hash = "sha256:298c5b2fc2df3eb128d2077abd5bd1f5b0419dcf72fdf0551b2af2f03b1ff2b3", size = 10777, upload-time = "2026-05-18T06:04:39.57Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/22/c0/01a5a4c3948c2269cf9d727e5e66a8b404e03beb4f9522680a3f71097011/types_simplejson-3.20.0.20260408-py3-none-any.whl", hash = "sha256:f9e542199cb159ed34ad54b6ceb3dc9af890c256b810ad1bd7c69c61db7d2236", size = 10415, upload-time = "2026-04-08T04:28:06.984Z" },
{ url = "https://files.pythonhosted.org/packages/a6/41/16937326596bec6283a51cc901c701a964019569b861ac5f88128bc98b43/types_simplejson-3.20.0.20260518-py3-none-any.whl", hash = "sha256:f4792dbc1ab049fcaee5d99ca950bd6468ea462fe79af25fe8ca08b6bee313ac", size = 10421, upload-time = "2026-05-18T06:04:38.706Z" },
]
[[package]]
@@ -3052,15 +3098,15 @@ wheels = [
[[package]]
name = "uvicorn"
version = "0.44.0"
version = "0.47.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
{ name = "h11" },
]
sdist = { url = "https://files.pythonhosted.org/packages/5e/da/6eee1ff8b6cbeed47eeb5229749168e81eb4b7b999a1a15a7176e51410c9/uvicorn-0.44.0.tar.gz", hash = "sha256:6c942071b68f07e178264b9152f1f16dfac5da85880c4ce06366a96d70d4f31e", size = 86947, upload-time = "2026-04-06T09:23:22.826Z" }
sdist = { url = "https://files.pythonhosted.org/packages/f6/b1/8e7077a8641086aea449e1b5752a570f1b5906c64e0a33cd6d93b63a066b/uvicorn-0.47.0.tar.gz", hash = "sha256:7c9a0ea1a9414106bbab7324609c162d8fa0cdcdcb703060987269d77c7bb533", size = 90582, upload-time = "2026-05-14T18:16:54.455Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/23/a5bbd9600dd607411fa644c06ff4951bec3a4d82c4b852374024359c19c0/uvicorn-0.44.0-py3-none-any.whl", hash = "sha256:ce937c99a2cc70279556967274414c087888e8cec9f9c94644dfca11bd3ced89", size = 69425, upload-time = "2026-04-06T09:23:21.524Z" },
{ url = "https://files.pythonhosted.org/packages/15/41/ac2dfdbc1f60c7af4f994c7a335cfa7040c01642b605d65f611cecc2a1e4/uvicorn-0.47.0-py3-none-any.whl", hash = "sha256:2c5715bc12d1892d84752049f400cd1c3cb018514967fdfeb97640443a6a9432", size = 71301, upload-time = "2026-05-14T18:16:51.762Z" },
]
[package.optional-dependencies]
+19 -1
View File
@@ -2,7 +2,7 @@ experimental_monorepo_root = true
[monorepo]
config_roots = [
"packages/plugins",
"packages/plugin-core",
"server",
"packages/cli",
"deployment",
@@ -22,12 +22,22 @@ terragrunt = "1.0.3"
opentofu = "1.11.6"
java = "21.0.2"
"npm:oazapfts" = "7.5.0"
"github:extism/cli" = "1.6.3"
"github:webassembly/binaryen" = "version_124"
"github:extism/js-pdk" = "1.6.0"
[tools."github:CQLabs/homebrew-dcm"]
version = "1.37.0"
bin = "dcm"
postinstall = "chmod +x \"$MISE_TOOL_INSTALL_PATH/dcm\" || true"
[tools."github:CQLabs/homebrew-dcm".platforms]
linux-x64 = { asset_pattern = "dcm-linux-x64-release.zip" }
linux-arm64 = { asset_pattern = "dcm-linux-arm-release.zip" }
macos-x64 = { asset_pattern = "dcm-macos-x64-release.zip" }
macos-arm64 = { asset_pattern = "dcm-macos-arm-release.zip" }
windows-x64 = { asset_pattern = "dcm-windows-release.zip" }
[tools."github:jellyfin/jellyfin-ffmpeg"]
version = "7.1.3-6"
@@ -41,6 +51,12 @@ macos-arm64 = { asset_pattern = "jellyfin-ffmpeg_*_portable_macarm64-gpl.tar.xz"
experimental = true
pin = true
[tasks.plugins]
run = [
"pnpm --filter @immich/plugin-sdk --filter @immich/plugin-core install --frozen-lockfile",
"pnpm --filter @immich/plugin-sdk --filter @immich/plugin-core build"
]
[tasks.open-api-typescript]
run = [
"oazapfts --optimistic --argumentStyle=object --useEnumType --allSchemas open-api/immich-openapi-specs.json packages/sdk/src/fetch-client.ts",
@@ -55,6 +71,8 @@ run = "bash ./bin/generate-dart-sdk.sh"
[tasks.open-api]
env = { SHARP_IGNORE_GLOBAL_LIBVIPS = true }
run = [
{ task = "//:plugins" },
{ task = "//server:build" },
{ task = "//server:install" },
{ task = "//server:build" },
{ task = "//server:sync-open-api" },
@@ -23,6 +23,8 @@ import java.io.IOException
import java.nio.ByteBuffer
import java.util.concurrent.ConcurrentHashMap
private const val MAX_PREALLOC_BYTES = 128 * 1024 * 1024
private class RemoteRequest(val cancellationSignal: CancellationSignal)
class RemoteImagesImpl(context: Context) : RemoteImageApi {
@@ -228,7 +230,6 @@ private class CronetImageFetcher : ImageFetcher {
private val onComplete: () -> Unit,
) : UrlRequest.Callback() {
private var buffer: NativeByteBuffer? = null
private var wrapped: ByteBuffer? = null
private var error: Exception? = null
override fun onRedirectReceived(request: UrlRequest, info: UrlResponseInfo, newUrl: String) {
@@ -242,15 +243,16 @@ private class CronetImageFetcher : ImageFetcher {
}
try {
// Content-Length is a size hint only. With Content-Encoding (gzip/br/...),
// Cronet auto-decompresses and writes decompressed bytes to our buffer, which
// may exceed the wire/compressed Content-Length. Always use the growable
// buffer path so we can't overflow.
val contentLength = info.allHeaders["content-length"]?.firstOrNull()?.toIntOrNull() ?: 0
if (contentLength > 0) {
buffer = NativeByteBuffer(contentLength + 1)
wrapped = NativeBuffer.wrap(buffer!!.pointer, contentLength + 1)
request.read(wrapped)
} else {
buffer = NativeByteBuffer(INITIAL_BUFFER_SIZE)
request.read(buffer!!.wrapRemaining())
}
// Cap the up-front alloc: Content-Length is untrusted and can be huge or near
// Int.MAX_VALUE (overflowing `+1`). For larger responses the grow path takes over.
val initialSize = if (contentLength in 1..MAX_PREALLOC_BYTES) contentLength + 1 else INITIAL_BUFFER_SIZE
buffer = NativeByteBuffer(initialSize)
request.read(buffer!!.wrapRemaining())
} catch (e: Exception) {
error = e
return request.cancel()
@@ -263,14 +265,14 @@ private class CronetImageFetcher : ImageFetcher {
byteBuffer: ByteBuffer
) {
try {
val buf = if (wrapped == null) {
buffer!!.run {
advance(byteBuffer.position())
ensureHeadroom()
wrapRemaining()
}
} else {
wrapped
// Always pass a fresh wrap so byteBuffer.position() represents only the
// bytes Cronet wrote in this iteration. Reusing the caller-supplied
// ByteBuffer breaks advance(): Cronet's position keeps accumulating
// across reads, which would double-count previous iterations' bytes.
val buf = buffer!!.run {
advance(byteBuffer.position())
ensureHeadroom()
wrapRemaining()
}
request.read(buf)
} catch (e: Exception) {
@@ -280,7 +282,6 @@ private class CronetImageFetcher : ImageFetcher {
}
override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) {
wrapped?.let { buffer!!.advance(it.position()) }
onSuccess(buffer!!)
onComplete()
}
+1 -1
View File
@@ -110,7 +110,7 @@ class NativeSyncApiImpl: ImmichPlugin, NativeSyncApi, FlutterPlugin {
var domainAlbum = PlatformAlbum(
id: album.localIdentifier,
name: album.localizedTitle!,
name: album.localizedTitle ?? album.localIdentifier,
updatedAt: nil,
isCloud: isCloud,
assetCount: Int64(assets.count)
+4
View File
@@ -18,3 +18,7 @@ enum CleanupStep { selectDate, scan, delete }
enum AssetKeepType { none, photosOnly, videosOnly }
enum AssetDateAggregation { start, end }
enum SlideshowLook { contain, cover, blurredBackground }
enum SlideshowDirection { forward, backward, shuffle }
@@ -4,6 +4,7 @@ import 'package:immich_mobile/domain/models/config/map_config.dart';
import 'package:immich_mobile/domain/models/config/theme_config.dart';
import 'package:immich_mobile/domain/models/config/timeline_config.dart';
import 'package:immich_mobile/domain/models/config/viewer_config.dart';
import 'package:immich_mobile/domain/models/config/slideshow_config.dart';
class AppConfig {
final ThemeConfig theme;
@@ -12,6 +13,7 @@ class AppConfig {
final TimelineConfig timeline;
final ImageConfig image;
final ViewerConfig viewer;
final SlideshowConfig slideshow;
const AppConfig({
this.theme = const .new(),
@@ -20,6 +22,7 @@ class AppConfig {
this.timeline = const .new(),
this.image = const .new(),
this.viewer = const .new(),
this.slideshow = const .new(),
});
AppConfig copyWith({
@@ -29,6 +32,7 @@ class AppConfig {
TimelineConfig? timeline,
ImageConfig? image,
ViewerConfig? viewer,
SlideshowConfig? slideshow,
}) => .new(
theme: theme ?? this.theme,
cleanup: cleanup ?? this.cleanup,
@@ -36,6 +40,7 @@ class AppConfig {
timeline: timeline ?? this.timeline,
image: image ?? this.image,
viewer: viewer ?? this.viewer,
slideshow: slideshow ?? this.slideshow,
);
@override
@@ -47,12 +52,13 @@ class AppConfig {
other.map == map &&
other.timeline == timeline &&
other.image == image &&
other.viewer == viewer);
other.viewer == viewer &&
other.slideshow == slideshow);
@override
int get hashCode => Object.hash(theme, cleanup, map, timeline, image, viewer);
int get hashCode => Object.hash(theme, cleanup, map, timeline, image, viewer, slideshow);
@override
String toString() =>
'AppConfig(theme: $theme, cleanup: $cleanup, map: $map, timeline: $timeline, image: $image, viewer: $viewer)';
'AppConfig(theme: $theme, cleanup: $cleanup, map: $map, timeline: $timeline, image: $image, viewer: $viewer, slideshow: $slideshow)';
}
@@ -0,0 +1,54 @@
import 'package:flutter/foundation.dart';
class NetworkConfig {
final bool autoEndpointSwitching;
final String? preferredWifiName;
final String? localEndpoint;
final List<String> externalEndpointList;
final Map<String, String> customHeaders;
const NetworkConfig({
this.autoEndpointSwitching = false,
this.preferredWifiName,
this.localEndpoint,
this.externalEndpointList = const [],
this.customHeaders = const {},
});
NetworkConfig copyWith({
bool? autoEndpointSwitching,
String? preferredWifiName,
String? localEndpoint,
List<String>? externalEndpointList,
Map<String, String>? customHeaders,
}) => NetworkConfig(
autoEndpointSwitching: autoEndpointSwitching ?? this.autoEndpointSwitching,
preferredWifiName: preferredWifiName ?? this.preferredWifiName,
localEndpoint: localEndpoint ?? this.localEndpoint,
externalEndpointList: externalEndpointList ?? this.externalEndpointList,
customHeaders: customHeaders ?? this.customHeaders,
);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is NetworkConfig &&
other.autoEndpointSwitching == autoEndpointSwitching &&
other.preferredWifiName == preferredWifiName &&
other.localEndpoint == localEndpoint &&
listEquals(other.externalEndpointList, externalEndpointList) &&
mapEquals(other.customHeaders, customHeaders));
@override
int get hashCode => Object.hash(
autoEndpointSwitching,
preferredWifiName,
localEndpoint,
Object.hashAll(externalEndpointList),
Object.hashAllUnordered(customHeaders.entries.map((e) => Object.hash(e.key, e.value))),
);
@override
String toString() =>
'NetworkConfig(autoEndpointSwitching: $autoEndpointSwitching, preferredWifiName: $preferredWifiName, localEndpoint: $localEndpoint, externalEndpointList: $externalEndpointList, customHeaders: $customHeaders)';
}
@@ -0,0 +1,48 @@
import 'package:immich_mobile/constants/enums.dart';
class SlideshowConfig {
final bool transition;
final bool repeat;
final int duration;
final SlideshowLook look;
final SlideshowDirection direction;
const SlideshowConfig({
this.transition = true,
this.repeat = true,
this.duration = 5,
this.look = SlideshowLook.contain,
this.direction = SlideshowDirection.forward,
});
SlideshowConfig copyWith({
bool? transition,
bool? repeat,
int? duration,
SlideshowLook? look,
SlideshowDirection? direction,
}) => SlideshowConfig(
transition: transition ?? this.transition,
repeat: repeat ?? this.repeat,
duration: duration ?? this.duration,
look: look ?? this.look,
direction: direction ?? this.direction,
);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is SlideshowConfig &&
other.transition == transition &&
other.repeat == repeat &&
other.duration == duration &&
other.look == look &&
other.direction == direction);
@override
int get hashCode => Object.hash(transition, repeat, duration, look, direction);
@override
String toString() =>
'SlideshowConfig(transition: $transition, repeat: $repeat, duration: $duration, look: $look, direction: $direction)';
}
@@ -1,18 +1,22 @@
import 'package:immich_mobile/domain/models/config/network_config.dart';
import 'package:immich_mobile/domain/models/log.model.dart';
class SystemConfig {
final LogLevel logLevel;
final NetworkConfig network;
const SystemConfig({this.logLevel = .info});
const SystemConfig({this.logLevel = .info, this.network = const .new()});
SystemConfig copyWith({LogLevel? logLevel}) => SystemConfig(logLevel: logLevel ?? this.logLevel);
SystemConfig copyWith({LogLevel? logLevel, NetworkConfig? network}) =>
SystemConfig(logLevel: logLevel ?? this.logLevel, network: network ?? this.network);
@override
bool operator ==(Object other) => identical(this, other) || (other is SystemConfig && other.logLevel == logLevel);
bool operator ==(Object other) =>
identical(this, other) || (other is SystemConfig && other.logLevel == logLevel && other.network == network);
@override
int get hashCode => logLevel.hashCode;
int get hashCode => Object.hash(logLevel, network);
@override
String toString() => 'SystemConfig(logLevel: $logLevel)';
String toString() => 'SystemConfig(logLevel: $logLevel, network: $network)';
}
+71 -1
View File
@@ -34,6 +34,23 @@ enum MetadataKey<T extends Object> {
viewerAutoPlayVideo<bool>(.appConfig, 'viewer.autoPlayVideo', true),
viewerTapToNavigate<bool>(.appConfig, 'viewer.tapToNavigate', false),
// Network
networkAutoEndpointSwitching<bool>(.systemConfig, 'network.autoEndpointSwitching', false),
networkPreferredWifiName<String>(.systemConfig, 'network.preferredWifiName', ''),
networkLocalEndpoint<String>(.systemConfig, 'network.localEndpoint', ''),
networkExternalEndpointList<List<String>>(
.systemConfig,
'network.externalEndpointList',
[],
_ListCodec(_PrimitiveCodec.string),
),
networkCustomHeaders<Map<String, String>>(
.systemConfig,
'network.customHeaders',
{},
_MapCodec(_PrimitiveCodec.string, _PrimitiveCodec.string),
),
// Timeline
timelineTilesPerRow<int>(.appConfig, 'timeline.tilesPerRow', 4),
timelineGroupAssetsBy<GroupAssetsBy>(
@@ -64,7 +81,19 @@ enum MetadataKey<T extends Object> {
),
cleanupKeepAlbumIds<List<String>>(.appConfig, 'cleanup.keepAlbumIds', [], _ListCodec(_PrimitiveCodec.string)),
cleanupCutoffDaysAgo<int>(.appConfig, 'cleanup.cutoffDaysAgo', -1),
cleanupDefaultsInitialized<bool>(.appConfig, 'cleanup.defaultsInitialized', false);
cleanupDefaultsInitialized<bool>(.appConfig, 'cleanup.defaultsInitialized', false),
// Slideshow
slideshowTransition<bool>(.appConfig, 'slideshow.transition', true),
slideshowRepeat<bool>(.appConfig, 'slideshow.repeat', true),
slideshowDuration<int>(.appConfig, 'slideshow.duration', 5),
slideshowLook<SlideshowLook>(.appConfig, 'slideshow.look', SlideshowLook.contain, _EnumCodec(SlideshowLook.values)),
slideshowDirection<SlideshowDirection>(
.appConfig,
'slideshow.direction',
SlideshowDirection.forward,
_EnumCodec(SlideshowDirection.values),
);
final MetadataDomain domain;
final String name;
@@ -131,6 +160,47 @@ final class _DateTimeCodec extends _MetadataCodec<DateTime> {
DateTime? decode(String raw) => DateTime.tryParse(raw);
}
final class _MapCodec<K extends Object, V extends Object> extends _MetadataCodec<Map<K, V>> {
final _MetadataCodec<K> _keyCodec;
final _MetadataCodec<V> _valueCodec;
const _MapCodec(this._keyCodec, this._valueCodec);
@override
String encode(Map<K, V> value) {
final entries = <String, String>{};
value.forEach((k, v) => entries[_keyCodec.encode(k)] = _valueCodec.encode(v));
return jsonEncode(entries);
}
@override
Map<K, V>? decode(String raw) {
try {
final decoded = jsonDecode(raw);
if (decoded is! Map) {
return null;
}
final result = <K, V>{};
for (final entry in decoded.entries) {
final rawKey = entry.key;
final rawValue = entry.value;
if (rawKey is! String || rawValue is! String) {
return null;
}
final k = _keyCodec.decode(rawKey);
final v = _valueCodec.decode(rawValue);
if (k == null || v == null) {
return null;
}
result[k] = v;
}
return result;
} on FormatException {
return null;
}
}
}
final class _ListCodec<T extends Object> extends _MetadataCodec<List<T>> {
final _MetadataCodec<T> _elementCodec;
+5 -7
View File
@@ -15,15 +15,8 @@ enum StoreKey<T> {
advancedTroubleshooting<bool>._(114),
selectedAlbumSortReverse<bool>._(123),
enableHapticFeedback<bool>._(126),
customHeaders<String>._(127),
syncAlbums<bool>._(131),
// Auto endpoint switching
autoEndpointSwitching<bool>._(132),
preferredWifiName<String>._(133),
localEndpoint<String>._(134),
externalEndpointList<String>._(135),
manageLocalMediaAndroid<bool>._(137),
// Read-only Mode settings
readonlyModeEnabled<bool>._(138),
@@ -36,6 +29,11 @@ enum StoreKey<T> {
syncMigrationStatus<String>._(1013),
// Legacy keys that have been migrated to the new metadata store
legacyAutoEndpointSwitching<bool>._(132),
legacyPreferredWifiName<String>._(133),
legacyLocalEndpoint<String>._(134),
legacyExternalEndpointList<String>._(135),
legacyCustomHeaders<String>._(127),
legacyLoopVideo<bool>._(117),
legacyLoadOriginalVideo<bool>._(136),
legacyAutoPlayVideo<bool>._(139),
@@ -9,12 +9,47 @@ import 'package:immich_mobile/infrastructure/repositories/remote_album.repositor
import 'package:immich_mobile/models/albums/album_search.model.dart';
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
import 'package:immich_mobile/services/foreground_upload.service.dart';
import 'package:logging/logging.dart';
/// Categorizes a heterogeneous asset selection into the candidates that can
/// be added to an album immediately (already on the server) and the local-only
/// candidates that must be uploaded first.
class AlbumAssetCandidates {
final List<String> remoteAssetIds;
final List<LocalAsset> localAssetsToUpload;
const AlbumAssetCandidates({required this.remoteAssetIds, required this.localAssetsToUpload});
}
class RemoteAlbumService {
static final _logger = Logger('RemoteAlbumService');
final DriftRemoteAlbumRepository _repository;
final DriftAlbumApiRepository _albumApiRepository;
final ForegroundUploadService _uploadService;
const RemoteAlbumService(this._repository, this._albumApiRepository);
const RemoteAlbumService(this._repository, this._albumApiRepository, this._uploadService);
/// Categorizes a heterogeneous asset selection into already-on-server IDs
/// and local assets that still need to be uploaded.
static AlbumAssetCandidates categorizeCandidates(Iterable<BaseAsset> assets) {
final remoteIds = <String>[];
final localToUpload = <LocalAsset>[];
for (final asset in assets) {
if (asset is RemoteAsset) {
remoteIds.add(asset.id);
} else if (asset is LocalAsset) {
final remoteId = asset.remoteId;
if (remoteId != null) {
remoteIds.add(remoteId);
} else {
localToUpload.add(asset);
}
}
}
return AlbumAssetCandidates(remoteAssetIds: remoteIds, localAssetsToUpload: localToUpload);
}
Stream<RemoteAlbum?> watchAlbum(String albumId) {
return _repository.watchAlbum(albumId);
@@ -148,6 +183,122 @@ class RemoteAlbumService {
return album.added.length;
}
/// !TODO The name here is not clear as we have addAssets method above,
/// which is only add remote assets to album, for the next PR, we will allow
/// adding local assets from album from the timeline as well with this flow.
/// So saving that for the next refactor
Future<int> addAssetsToAlbum({
required String albumId,
required UserDto uploader,
required AlbumAssetCandidates candidates,
UploadCallbacks uploadCallbacks = const UploadCallbacks(),
}) async {
int addedCount = 0;
if (candidates.remoteAssetIds.isNotEmpty) {
addedCount += await addAssets(albumId: albumId, assetIds: candidates.remoteAssetIds);
}
if (candidates.localAssetsToUpload.isNotEmpty) {
addedCount += await _uploadAndAddLocals(albumId, uploader, candidates.localAssetsToUpload, uploadCallbacks);
}
return addedCount;
}
/// Creates an album, seeding it with already-remote asset IDs, then uploads
/// local-only assets and links each one as it finishes.
Future<RemoteAlbum> createAlbumWithAssets({
required String title,
required UserDto owner,
String? description,
AlbumAssetCandidates candidates = const AlbumAssetCandidates(remoteAssetIds: [], localAssetsToUpload: []),
UploadCallbacks uploadCallbacks = const UploadCallbacks(),
}) async {
final album = await createAlbum(
title: title,
owner: owner,
description: description,
assetIds: candidates.remoteAssetIds,
);
if (candidates.localAssetsToUpload.isNotEmpty) {
await _uploadAndAddLocals(album.id, owner, candidates.localAssetsToUpload, uploadCallbacks);
}
return album;
}
Future<int> _uploadAndAddLocals(
String albumId,
UserDto uploader,
List<LocalAsset> localAssets,
UploadCallbacks userCallbacks,
) async {
int addedCount = 0;
final pendingAdds = <Future<void>>[];
final localById = {for (final a in localAssets) a.id: a};
final wrappedCallbacks = UploadCallbacks(
onProgress: (localId, filename, bytes, totalBytes) => _runUploadCallback(
'Upload progress callback failed for $localId',
() => userCallbacks.onProgress?.call(localId, filename, bytes, totalBytes),
),
onICloudProgress: (localId, progress) => _runUploadCallback(
'iCloud progress callback failed for $localId',
() => userCallbacks.onICloudProgress?.call(localId, progress),
),
onError: (localId, errorMessage) => _runUploadCallback(
'Upload error callback failed for $localId',
() => userCallbacks.onError?.call(localId, errorMessage),
),
onSuccess: (localId, remoteId) {
_runUploadCallback(
'Upload success callback failed for $localId',
() => userCallbacks.onSuccess?.call(localId, remoteId),
);
final source = localById[localId];
if (source == null) {
_logger.warning('Upload success for $localId but source LocalAsset missing; skipping album link');
return;
}
pendingAdds.add(
_linkUploadedAssetToAlbum(albumId, remoteId, uploader, source)
.then<void>((added) {
addedCount += added;
})
.catchError((Object error, StackTrace stack) {
_logger.warning('Failed to add uploaded asset $remoteId to album $albumId', error, stack);
}),
);
},
);
await _uploadService.uploadManual(localAssets, callbacks: wrappedCallbacks);
await Future.wait(pendingAdds);
return addedCount;
}
void _runUploadCallback(String message, void Function() callback) {
try {
callback();
} catch (error, stack) {
_logger.warning(message, error, stack);
}
}
/// Links a freshly-uploaded asset to an album, ensuring the local DB
/// reflects the change without waiting for the next sync. We call the API
/// (server is the source of truth), then upsert a placeholder
/// `remote_asset_entity` row from the local source so the FK-protected
/// junction insert succeeds. Sync overwrites the placeholder later with
/// the authoritative server data.
Future<int> _linkUploadedAssetToAlbum(String albumId, String remoteId, UserDto uploader, LocalAsset source) async {
final result = await _albumApiRepository.addAssets(albumId, [remoteId]);
if (result.added.isEmpty) {
return 0;
}
await _repository.upsertRemoteAssetStub(remoteId: remoteId, ownerId: uploader.id, source: source);
await _repository.addAssets(albumId, result.added);
return result.added.length;
}
Future<void> deleteAlbum(String albumId) async {
await _albumApiRepository.deleteAlbum(albumId);
@@ -0,0 +1,31 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/tag.model.dart';
import 'package:immich_mobile/infrastructure/repositories/tags_api.repository.dart';
final tagServiceProvider = Provider<TagService>((ref) => TagService(ref.watch(tagsApiRepositoryProvider)));
class TagService {
final TagsApiRepository _repository;
const TagService(this._repository);
Future<int> bulkTagAssets(List<String> assetIds, List<String> tagIds) async {
return _repository.bulkTagAssets(assetIds, tagIds);
}
Future<Set<Tag>> getAllTags() async {
final dtos = await _repository.getAllTags();
if (dtos == null) {
return {};
}
return dtos.map((dto) => Tag.fromDto(dto)).toSet();
}
Future<List<Tag>> upsertTags(List<String> tags) async {
final dtos = await _repository.upsertTags(tags);
if (dtos == null) {
return [];
}
return dtos.map((dto) => Tag.fromDto(dto)).toList();
}
}
@@ -4,6 +4,8 @@ extension StringExtension on String {
String capitalize() {
return split(" ").map((str) => str.isEmpty ? str : str[0].toUpperCase() + str.substring(1)).join(" ");
}
String? get nullIfEmpty => isEmpty ? null : this;
}
extension DurationExtension on String {
@@ -2,6 +2,7 @@ import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/models/config/app_config.dart';
import 'package:immich_mobile/domain/models/config/system_config.dart';
import 'package:immich_mobile/domain/models/metadata_key.dart';
import 'package:immich_mobile/extensions/string_extensions.dart';
import 'package:immich_mobile/infrastructure/entities/metadata.entity.drift.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
@@ -139,9 +140,25 @@ extension<T extends Object> on MetadataDomain<T> {
autoPlayVideo: repo._read(.viewerAutoPlayVideo),
tapToNavigate: repo._read(.viewerTapToNavigate),
),
slideshow: .new(
transition: repo._read(.slideshowTransition),
repeat: repo._read(.slideshowRepeat),
duration: repo._read(.slideshowDuration),
look: repo._read(.slideshowLook),
direction: repo._read(.slideshowDirection),
),
);
case .systemConfig:
repo._systemConfig = .new(logLevel: repo._read(.logLevel));
repo._systemConfig = .new(
logLevel: repo._read(.logLevel),
network: .new(
autoEndpointSwitching: repo._read(.networkAutoEndpointSwitching),
preferredWifiName: repo._read(.networkPreferredWifiName).nullIfEmpty,
localEndpoint: repo._read(.networkLocalEndpoint).nullIfEmpty,
externalEndpointList: repo._read(.networkExternalEndpointList),
customHeaders: repo._read(.networkCustomHeaders),
),
);
}
}
}
@@ -10,6 +10,7 @@ import 'package:immich_mobile/infrastructure/entities/remote_album.entity.drift.
import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
enum SortRemoteAlbumsBy { id, updatedAt }
@@ -159,7 +160,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
createdAt: Value(album.createdAt),
updatedAt: Value(album.updatedAt),
description: Value(album.description),
thumbnailAssetId: Value(album.thumbnailAssetId),
thumbnailAssetId: Value(album.thumbnailAssetId ?? (assetIds.isNotEmpty ? assetIds.first : null)),
isActivityEnabled: Value(album.isActivityEnabled),
order: Value(album.order),
);
@@ -274,17 +275,59 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
}
Future<int> addAssets(String albumId, List<String> assetIds) async {
if (assetIds.isEmpty) {
return 0;
}
final albumAssets = assetIds.map(
(assetId) => RemoteAlbumAssetEntityCompanion(albumId: Value(albumId), assetId: Value(assetId)),
);
await _db.batch((batch) {
batch.insertAll(_db.remoteAlbumAssetEntity, albumAssets);
await _db.transaction(() async {
await _db.batch((batch) {
batch.insertAll(_db.remoteAlbumAssetEntity, albumAssets);
});
final album = _db.update(_db.remoteAlbumEntity)
..where((row) => row.id.equals(albumId) & row.thumbnailAssetId.isNull());
await album.write(RemoteAlbumEntityCompanion(thumbnailAssetId: Value(assetIds.first)));
});
return assetIds.length;
}
/// Inserts a placeholder `remote_asset_entity` row from a freshly-uploaded
/// local asset. Skips silently if a row with the same id or
/// (owner_id, checksum) already exists — sync will overwrite with the
/// authoritative server data once the AssetUploadReadyV1 event is processed.
Future<void> upsertRemoteAssetStub({
required String remoteId,
required String ownerId,
required LocalAsset source,
}) async {
await _db
.into(_db.remoteAssetEntity)
.insert(
RemoteAssetEntityCompanion(
id: Value(remoteId),
ownerId: Value(ownerId),
checksum: Value(source.checksum ?? remoteId),
name: Value(source.name),
type: Value(source.type),
createdAt: Value(source.createdAt),
updatedAt: Value(source.updatedAt),
width: Value(source.width),
height: Value(source.height),
durationMs: Value(source.durationMs),
isFavorite: Value(source.isFavorite),
visibility: const Value(AssetVisibility.timeline),
isEdited: Value(source.isEdited),
),
mode: InsertMode.insertOrIgnore,
);
}
Future<void> addUsers(String albumId, List<String> userIds) {
final albumUsers = userIds.map(
(assetId) => RemoteAlbumUserEntityCompanion(
@@ -197,16 +197,6 @@ class SyncStreamRepository extends DriftDatabaseRepository {
try {
await _db.batch((batch) {
for (final asset in data) {
// Avoid SqliteException(2067) when server re-issues a new id for
// the same (ownerId, checksum). #22522 #27186
_enqueueRemoteAssetDedupe(
batch,
id: asset.id,
ownerId: asset.ownerId,
checksum: asset.checksum,
libraryId: asset.libraryId,
);
final companion = RemoteAssetEntityCompanion(
name: Value(asset.originalFileName),
type: Value(asset.type.toAssetType()),
@@ -246,15 +236,6 @@ class SyncStreamRepository extends DriftDatabaseRepository {
try {
await _db.batch((batch) {
for (final asset in data) {
// See updateAssetsV1 for why this dedupe is required. #22522 #27186
_enqueueRemoteAssetDedupe(
batch,
id: asset.id,
ownerId: asset.ownerId,
checksum: asset.checksum,
libraryId: asset.libraryId,
);
final companion = RemoteAssetEntityCompanion(
name: Value(asset.originalFileName),
type: Value(asset.type.toAssetType()),
@@ -290,39 +271,6 @@ class SyncStreamRepository extends DriftDatabaseRepository {
}
}
/// Queues a DELETE that prunes any stale remote_asset row matching the
/// partial UNIQUE index for the incoming asset:
/// - libraryId IS NULL -> (owner_id, checksum)
/// - libraryId NOT NULL -> (owner_id, library_id, checksum)
/// The current id is excluded so a same-id update does not delete itself.
void _enqueueRemoteAssetDedupe(
Batch batch, {
required String id,
required String ownerId,
required String checksum,
required String? libraryId,
}) {
if (libraryId == null) {
batch.deleteWhere(
_db.remoteAssetEntity,
(row) =>
row.ownerId.equals(ownerId) &
row.checksum.equals(checksum) &
row.libraryId.isNull() &
row.id.equals(id).not(),
);
} else {
batch.deleteWhere(
_db.remoteAssetEntity,
(row) =>
row.ownerId.equals(ownerId) &
row.checksum.equals(checksum) &
row.libraryId.equals(libraryId) &
row.id.equals(id).not(),
);
}
}
Future<void> updateAssetsExifV1(Iterable<SyncAssetExifV1> data, {String debugLabel = 'user'}) async {
try {
await _db.batch((batch) {
@@ -14,4 +14,13 @@ class TagsApiRepository extends ApiRepository {
Future<List<TagResponseDto>?> getAllTags() async {
return await _api.getAllTags();
}
Future<int> bulkTagAssets(List<String> assetIds, List<String> tagIds) async {
final response = await _api.bulkTagAssets(TagBulkAssetsDto(assetIds: assetIds, tagIds: tagIds));
return response?.count ?? 0;
}
Future<List<TagResponseDto>?> upsertTags(List<String> tags) async {
return _api.upsertTags(TagUpsertDto(tags: tags));
}
}
@@ -1,14 +1,12 @@
import 'dart:convert';
import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/domain/models/metadata_key.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/providers/api.provider.dart';
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
class SettingsHeader {
String key = "";
@@ -24,17 +22,14 @@ class HeaderSettingsPage extends HookConsumerWidget {
final headers = useState<List<SettingsHeader>>([]);
final setInitialHeaders = useState(false);
var headersStr = Store.get(StoreKey.customHeaders, "");
final storedHeaders = ref.read(metadataProvider).systemConfig.network.customHeaders;
if (!setInitialHeaders.value) {
if (headersStr.isNotEmpty) {
var customHeaders = jsonDecode(headersStr) as Map;
customHeaders.forEach((k, v) {
final header = SettingsHeader();
header.key = k;
header.value = v;
headers.value.add(header);
});
}
storedHeaders.forEach((k, v) {
final header = SettingsHeader();
header.key = k;
header.value = v;
headers.value.add(header);
});
// add first one to help the user
if (headers.value.isEmpty) {
@@ -88,8 +83,8 @@ class HeaderSettingsPage extends HookConsumerWidget {
}
saveHeaders(WidgetRef ref, List<SettingsHeader> headers) async {
final headersMap = {};
for (var header in headers) {
final headersMap = <String, String>{};
for (final header in headers) {
final key = header.key.trim();
final value = header.value.trim();
@@ -99,8 +94,7 @@ class HeaderSettingsPage extends HookConsumerWidget {
headersMap[key] = value;
}
var encoded = jsonEncode(headersMap);
await Store.put(StoreKey.customHeaders, encoded);
await ref.read(metadataProvider).write(MetadataKey.networkCustomHeaders, headersMap);
await ref.read(apiServiceProvider).updateHeaders();
}
}
@@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/models/shared_link/shared_link.model.dart';
import 'package:immich_mobile/providers/shared_link.provider.dart';
import 'package:immich_mobile/widgets/shared_link/shared_link_item.dart';
@@ -28,71 +27,41 @@ class SharedLinkPage extends HookConsumerWidget {
}, []);
Widget buildNoShares() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 16.0, top: 16.0),
child: const Text(
"shared_link_manage_links",
style: TextStyle(fontSize: 14, color: Colors.grey, fontWeight: FontWeight.bold),
).tr(),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: const Text("you_dont_have_any_shared_links", style: TextStyle(fontSize: 14)).tr(),
),
),
Expanded(
child: Center(
child: Icon(Icons.link_off, size: 100, color: context.themeData.iconTheme.color?.withValues(alpha: 0.5)),
),
),
],
return Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.link_off, size: 100, color: Theme.of(context).colorScheme.onSurface.withAlpha(128)),
const SizedBox(height: 20),
const Text("you_dont_have_any_shared_links", style: TextStyle(fontSize: 14)).tr(),
],
),
);
}
Widget buildSharesList(List<SharedLink> links) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 16.0, top: 16.0, bottom: 30.0),
child: Text(
"shared_link_manage_links",
style: context.textTheme.labelLarge?.copyWith(color: context.textTheme.labelLarge?.color?.withAlpha(200)),
).tr(),
),
Expanded(
child: LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 600) {
// Two column
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisExtent: 180,
),
itemCount: links.length,
itemBuilder: (context, index) {
return SharedLinkItem(links.elementAt(index));
},
);
}
// Single column
return ListView.builder(
itemCount: links.length,
itemBuilder: (context, index) {
return SharedLinkItem(links.elementAt(index));
},
);
},
),
),
],
return LayoutBuilder(
builder: (context, constraints) => constraints.maxWidth > 600
? GridView.builder(
key: const PageStorageKey('shared-links-grid'),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisExtent: 180,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
padding: const EdgeInsets.all(12),
itemCount: links.length,
itemBuilder: (context, index) => SharedLinkItem(links[index]),
)
: ListView.separated(
key: const PageStorageKey('shared-links-list'),
padding: const EdgeInsets.symmetric(vertical: 8),
itemCount: links.length,
itemBuilder: (context, index) => SharedLinkItem(links[index]),
separatorBuilder: (context, index) => const Divider(height: 1),
),
);
}
@@ -6,15 +6,20 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/models/shared_link/shared_link.model.dart';
import 'package:immich_mobile/providers/server_info.provider.dart';
import 'package:immich_mobile/providers/shared_link.provider.dart';
import 'package:immich_mobile/services/shared_link.service.dart';
import 'package:immich_mobile/utils/url_helper.dart';
import 'package:immich_mobile/widgets/common/confirm_dialog.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
import 'package:share_plus/share_plus.dart';
@RoutePage()
class SharedLinkEditPage extends HookConsumerWidget {
static const int maxFutureDate = 365 * 2;
final SharedLink? existingLink;
final List<String>? assetsList;
final String? albumId;
@@ -23,71 +28,82 @@ class SharedLinkEditPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
const padding = 20.0;
final themeData = context.themeData;
final colorScheme = context.colorScheme;
final externalDomain = ref.watch(serverInfoProvider.select((s) => s.serverConfig.externalDomain));
final displayServerUrl = externalDomain.isNotEmpty ? externalDomain : getServerUrl();
final expiryPresets = <(Duration, String)>[
(Duration.zero, context.t.never),
(const Duration(minutes: 30), context.t.shared_link_edit_expire_after_option_minutes(count: 30)),
(const Duration(hours: 1), context.t.shared_link_edit_expire_after_option_hour),
(const Duration(hours: 6), context.t.shared_link_edit_expire_after_option_hours(count: 6)),
(const Duration(days: 1), context.t.shared_link_edit_expire_after_option_day),
(const Duration(days: 7), context.t.shared_link_edit_expire_after_option_days(count: 7)),
(const Duration(days: 30), context.t.shared_link_edit_expire_after_option_days(count: 30)),
(const Duration(days: 90), context.t.shared_link_edit_expire_after_option_months(count: 3)),
(const Duration(days: 365), context.t.shared_link_edit_expire_after_option_year(count: 1)),
];
final descriptionController = useTextEditingController(text: existingLink?.description ?? "");
final descriptionFocusNode = useFocusNode();
final passwordController = useTextEditingController(text: existingLink?.password ?? "");
final slugController = useTextEditingController(text: existingLink?.slug ?? "");
final slugFocusNode = useFocusNode();
useListenable(slugController);
final showMetadata = useState(existingLink?.showMetadata ?? true);
final allowDownload = useState(existingLink?.allowDownload ?? true);
final allowUpload = useState(existingLink?.allowUpload ?? false);
final editExpiry = useState(false);
final expiryAfter = useState(0);
final expiryAfter = useState<DateTime?>(existingLink?.expiresAt?.toLocal());
final selectedPresetIndex = useState<int?>(existingLink?.expiresAt == null ? 0 : null);
final newShareLink = useState("");
Widget buildSharedLinkRow({required String leading, required String content}) {
return Row(
children: [
Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Text(
content,
style: TextStyle(color: colorScheme.primary, fontWeight: FontWeight.bold),
),
),
),
const SizedBox(width: 8),
Text(leading, style: const TextStyle(fontWeight: FontWeight.bold)),
],
);
}
Widget buildLinkTitle() {
if (existingLink != null) {
if (existingLink!.type == SharedLinkSource.album) {
return Row(
children: [
const Text('public_album', style: TextStyle(fontWeight: FontWeight.bold)).tr(),
const Text(" | ", style: TextStyle(fontWeight: FontWeight.bold)),
Text(
existingLink!.title,
style: TextStyle(color: colorScheme.primary, fontWeight: FontWeight.bold),
),
],
);
return buildSharedLinkRow(leading: context.t.public_album, content: existingLink!.title);
}
if (existingLink!.type == SharedLinkSource.individual) {
return Row(
children: [
const Text('shared_link_individual_shared', style: TextStyle(fontWeight: FontWeight.bold)).tr(),
const Text(" | ", style: TextStyle(fontWeight: FontWeight.bold)),
Expanded(
child: Text(
existingLink!.description ?? "--",
style: TextStyle(color: colorScheme.primary, fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
),
),
],
return buildSharedLinkRow(
leading: context.t.shared_link_individual_shared,
content: existingLink!.description ?? "--",
);
}
}
return const Text("create_link_to_share_description", style: TextStyle(fontWeight: FontWeight.bold)).tr();
return Text(context.t.create_link_to_share_description, style: const TextStyle(fontWeight: FontWeight.bold));
}
Widget buildDescriptionField() {
return TextField(
controller: descriptionController,
enabled: newShareLink.value.isEmpty,
focusNode: descriptionFocusNode,
textInputAction: TextInputAction.done,
autofocus: false,
decoration: InputDecoration(
labelText: 'description'.tr(),
labelStyle: TextStyle(fontWeight: FontWeight.bold, color: colorScheme.primary),
labelText: context.t.description,
labelStyle: const TextStyle(fontWeight: FontWeight.bold),
floatingLabelBehavior: FloatingLabelBehavior.always,
border: const OutlineInputBorder(),
hintText: 'shared_link_edit_description_hint'.tr(),
hintText: context.t.shared_link_edit_description_hint,
hintStyle: const TextStyle(fontWeight: FontWeight.normal, fontSize: 14),
disabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey.withValues(alpha: 0.5))),
),
onTapOutside: (_) => descriptionFocusNode.unfocus(),
);
@@ -96,16 +112,14 @@ class SharedLinkEditPage extends HookConsumerWidget {
Widget buildPasswordField() {
return TextField(
controller: passwordController,
enabled: newShareLink.value.isEmpty,
autofocus: false,
decoration: InputDecoration(
labelText: 'password'.tr(),
labelStyle: TextStyle(fontWeight: FontWeight.bold, color: colorScheme.primary),
labelText: context.t.password,
labelStyle: const TextStyle(fontWeight: FontWeight.bold),
floatingLabelBehavior: FloatingLabelBehavior.always,
border: const OutlineInputBorder(),
hintText: 'shared_link_edit_password_hint'.tr(),
hintText: context.t.shared_link_edit_password_hint,
hintStyle: const TextStyle(fontWeight: FontWeight.normal, fontSize: 14),
disabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey.withValues(alpha: 0.5))),
),
);
}
@@ -113,18 +127,16 @@ class SharedLinkEditPage extends HookConsumerWidget {
Widget buildSlugField() {
return TextField(
controller: slugController,
enabled: newShareLink.value.isEmpty,
focusNode: slugFocusNode,
textInputAction: TextInputAction.done,
autofocus: false,
decoration: InputDecoration(
labelText: 'custom_url'.tr(),
labelStyle: TextStyle(fontWeight: FontWeight.bold, color: colorScheme.primary),
floatingLabelBehavior: FloatingLabelBehavior.always,
labelText: slugController.text.isNotEmpty ? context.t.custom_url : null,
labelStyle: const TextStyle(fontWeight: FontWeight.bold),
border: const OutlineInputBorder(),
hintText: 'custom_url'.tr(),
hintStyle: const TextStyle(fontWeight: FontWeight.normal, fontSize: 14),
disabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey.withValues(alpha: 0.5))),
hintText: context.t.custom_url,
prefixText: slugController.text.isNotEmpty ? '/s/' : null,
prefixStyle: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
),
onTapOutside: (_) => slugFocusNode.unfocus(),
);
@@ -133,145 +145,182 @@ class SharedLinkEditPage extends HookConsumerWidget {
Widget buildShowMetaButton() {
return SwitchListTile.adaptive(
value: showMetadata.value,
onChanged: newShareLink.value.isEmpty ? (value) => showMetadata.value = value : null,
activeThumbColor: colorScheme.primary,
onChanged: (value) => showMetadata.value = value,
dense: true,
title: Text("show_metadata", style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold)).tr(),
title: Text(
context.t.show_metadata,
style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
),
);
}
Widget buildAllowDownloadButton() {
return SwitchListTile.adaptive(
value: allowDownload.value,
onChanged: newShareLink.value.isEmpty ? (value) => allowDownload.value = value : null,
activeThumbColor: colorScheme.primary,
onChanged: (value) => allowDownload.value = value,
dense: true,
title: Text(
"allow_public_user_to_download",
context.t.allow_public_user_to_download,
style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
).tr(),
),
);
}
Widget buildAllowUploadButton() {
return SwitchListTile.adaptive(
value: allowUpload.value,
onChanged: newShareLink.value.isEmpty ? (value) => allowUpload.value = value : null,
activeThumbColor: colorScheme.primary,
onChanged: (value) => allowUpload.value = value,
dense: true,
title: Text(
"allow_public_user_to_upload",
context.t.allow_public_user_to_upload,
style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
).tr(),
),
);
}
Widget buildEditExpiryButton() {
return SwitchListTile.adaptive(
value: editExpiry.value,
onChanged: newShareLink.value.isEmpty ? (value) => editExpiry.value = value : null,
activeThumbColor: colorScheme.primary,
dense: true,
title: Text(
"change_expiration_time",
style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
).tr(),
String formatDateTime(DateTime dateTime) => DateFormat.yMMMd(context.locale.toString()).add_Hm().format(dateTime);
DateTime? getExpiresAtFromPreset(Duration preset) => preset == Duration.zero ? null : DateTime.now().add(preset);
Future<void> selectDate() async {
final today = DateTime.now();
final safeInitialDate = expiryAfter.value ?? today.add(const Duration(days: 7));
final initialDate = safeInitialDate.isBefore(today) ? today : safeInitialDate;
final selectedDate = await showDatePicker(
context: context,
initialDate: initialDate,
firstDate: today,
lastDate: today.add(const Duration(days: maxFutureDate)),
);
if (selectedDate != null && context.mounted) {
final isToday =
selectedDate.year == today.year && selectedDate.month == today.month && selectedDate.day == today.day;
final initialTime = isToday ? TimeOfDay.fromDateTime(today) : const TimeOfDay(hour: 12, minute: 0);
final selectedTime = await showTimePicker(context: context, initialTime: initialTime);
if (selectedTime != null) {
final now = DateTime.now();
var finalDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
if (finalDateTime.isBefore(now) && isToday) {
finalDateTime = now;
}
selectedPresetIndex.value = null;
expiryAfter.value = finalDateTime;
}
}
}
Widget buildExpiryAfterButton() {
return DropdownMenu(
label: Text(
"expire_after",
style: TextStyle(fontWeight: FontWeight.bold, color: colorScheme.primary),
).tr(),
enableSearch: false,
enableFilter: false,
width: context.width - 40,
initialSelection: expiryAfter.value,
enabled: newShareLink.value.isEmpty && (existingLink == null || editExpiry.value),
onSelected: (value) {
expiryAfter.value = value!;
},
dropdownMenuEntries: [
DropdownMenuEntry(value: 0, label: "never".tr()),
DropdownMenuEntry(
value: 30,
label: "shared_link_edit_expire_after_option_minutes".tr(namedArgs: {'count': "30"}),
),
DropdownMenuEntry(value: 60, label: "shared_link_edit_expire_after_option_hour".tr()),
DropdownMenuEntry(
value: 60 * 6,
label: "shared_link_edit_expire_after_option_hours".tr(namedArgs: {'count': "6"}),
),
DropdownMenuEntry(value: 60 * 24, label: "shared_link_edit_expire_after_option_day".tr()),
DropdownMenuEntry(
value: 60 * 24 * 7,
label: "shared_link_edit_expire_after_option_days".tr(namedArgs: {'count': "7"}),
),
DropdownMenuEntry(
value: 60 * 24 * 30,
label: "shared_link_edit_expire_after_option_days".tr(namedArgs: {'count': "30"}),
),
DropdownMenuEntry(
value: 60 * 24 * 30 * 3,
label: "shared_link_edit_expire_after_option_months".tr(namedArgs: {'count': "3"}),
),
DropdownMenuEntry(
value: 60 * 24 * 30 * 12,
label: "shared_link_edit_expire_after_option_year".tr(namedArgs: {'count': "1"}),
),
],
);
}
void copyLinkToClipboard() {
Clipboard.setData(ClipboardData(text: newShareLink.value)).then((_) {
context.scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(
"shared_link_clipboard_copied_massage",
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
).tr(),
duration: const Duration(seconds: 2),
),
);
});
}
Widget buildNewLinkField() {
return Column(
return ExpansionTile(
title: Text(
context.t.expire_after,
style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
),
subtitle: Text(
expiryAfter.value == null ? context.t.shared_link_expires_never : formatDateTime(expiryAfter.value!),
style: TextStyle(color: themeData.colorScheme.primary),
),
children: [
const Padding(padding: EdgeInsets.only(top: 20, bottom: 20), child: Divider()),
TextFormField(
readOnly: true,
initialValue: newShareLink.value,
decoration: InputDecoration(
border: const OutlineInputBorder(),
enabledBorder: themeData.inputDecorationTheme.focusedBorder,
suffixIcon: IconButton(onPressed: copyLinkToClipboard, icon: const Icon(Icons.copy)),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: Align(
alignment: Alignment.bottomRight,
child: ElevatedButton(
onPressed: () {
context.maybePop();
},
child: const Text("done", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)).tr(),
),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Wrap(
spacing: 8,
runSpacing: 8,
children: List.generate(expiryPresets.length, (index) {
final preset = expiryPresets[index];
return ChoiceChip(
label: Text(preset.$2),
selected: selectedPresetIndex.value == index,
onSelected: (_) {
selectedPresetIndex.value = index;
expiryAfter.value = getExpiresAtFromPreset(preset.$1);
},
);
}),
),
if (expiryAfter.value != null) ...[
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: OutlinedButton.icon(
onPressed: selectDate,
icon: const Icon(Icons.edit_calendar),
label: Text(context.t.edit_date_and_time),
),
),
],
],
),
),
],
);
}
DateTime calculateExpiry() {
return DateTime.now().add(Duration(minutes: expiryAfter.value));
Future<void> copyToClipboard(String link) async {
await Clipboard.setData(ClipboardData(text: link));
if (!context.mounted) {
return;
}
context.scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(
context.t.shared_link_clipboard_copied_massage,
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
),
duration: const Duration(seconds: 2),
),
);
}
Widget buildLinkCopyField(String link) {
return TextFormField(
readOnly: true,
onTap: () => copyToClipboard(link),
initialValue: link,
decoration: InputDecoration(
border: const OutlineInputBorder(),
enabledBorder: themeData.inputDecorationTheme.focusedBorder,
suffixIcon: IconButton(onPressed: () => Share.share(link), icon: const Icon(Icons.share)),
),
);
}
Widget buildNewLinkReadyScreen() {
return Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.add_link, size: 100, color: themeData.colorScheme.primary),
const SizedBox(height: 20),
buildLinkCopyField(newShareLink.value),
const SizedBox(height: 20),
ElevatedButton.icon(
onPressed: () => context.maybePop(),
icon: const Icon(Icons.check),
label: Text(context.t.done, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
),
],
),
);
}
DateTime? calculateExpiry() => expiryAfter.value;
Future<void> handleNewLink() async {
final newLink = await ref
.read(sharedLinkServiceProvider)
@@ -284,30 +333,30 @@ class SharedLinkEditPage extends HookConsumerWidget {
description: descriptionController.text.isEmpty ? null : descriptionController.text,
password: passwordController.text.isEmpty ? null : passwordController.text,
slug: slugController.text.isEmpty ? null : slugController.text,
expiresAt: expiryAfter.value == 0 ? null : calculateExpiry(),
expiresAt: calculateExpiry()?.toUtc(),
);
if (!context.mounted) {
return;
}
ref.invalidate(sharedLinksStateProvider);
await ref.read(serverInfoProvider.notifier).getServerConfig();
if (!context.mounted) {
return;
}
final externalDomain = ref.read(serverInfoProvider.select((s) => s.serverConfig.externalDomain));
var serverUrl = externalDomain.isNotEmpty ? externalDomain : getServerUrl();
if (serverUrl != null && !serverUrl.endsWith('/')) {
serverUrl += '/';
}
final serverUrl = externalDomain.isNotEmpty ? externalDomain : getServerUrl();
if (newLink != null && serverUrl != null) {
final hasSlug = newLink.slug?.isNotEmpty == true;
final urlPath = hasSlug ? newLink.slug : newLink.key;
final basePath = hasSlug ? 's' : 'share';
newShareLink.value = "$serverUrl$basePath/$urlPath";
copyLinkToClipboard();
} else if (newLink == null) {
if (newLink != null) {
newShareLink.value = buildSharedLinkUrl(baseUrl: serverUrl, slug: newLink.slug, key: newLink.key) ?? '';
await copyToClipboard(newShareLink.value);
} else {
ImmichToast.show(
context: context,
gravity: ToastGravity.BOTTOM,
toastType: ToastType.error,
msg: 'shared_link_create_error'.tr(),
msg: context.t.shared_link_create_error,
);
}
}
@@ -348,8 +397,9 @@ class SharedLinkEditPage extends HookConsumerWidget {
slug = existingLink!.slug;
}
if (editExpiry.value) {
expiry = expiryAfter.value == 0 ? null : calculateExpiry();
final newExpiry = expiryAfter.value;
if (newExpiry?.toUtc() != existingLink!.expiresAt?.toUtc()) {
expiry = newExpiry;
changeExpiry = true;
}
@@ -363,69 +413,115 @@ class SharedLinkEditPage extends HookConsumerWidget {
description: desc,
password: password,
slug: slug,
expiresAt: expiry,
expiresAt: expiry?.toUtc(),
changeExpiry: changeExpiry,
);
if (!context.mounted) {
return;
}
ref.invalidate(sharedLinksStateProvider);
await context.maybePop();
}
Future<void> handleDeleteLink() async {
return showDialog(
context: context,
builder: (BuildContext context) => ConfirmDialog(
title: "delete_shared_link_dialog_title",
content: "confirm_delete_shared_link",
onOk: () async {
await ref.read(sharedLinkServiceProvider).deleteSharedLink(existingLink!.id);
ref.invalidate(sharedLinksStateProvider);
if (context.mounted) {
await context.maybePop();
}
},
),
);
}
return Scaffold(
appBar: AppBar(
title: Text(existingLink == null ? "create_link_to_share" : "edit_link").tr(),
title: Text(existingLink == null ? context.t.create_link_to_share : context.t.edit_link),
elevation: 0,
leading: const CloseButton(),
centerTitle: false,
),
body: SafeArea(
child: ListView(
children: [
Padding(padding: const EdgeInsets.all(padding), child: buildLinkTitle()),
Padding(padding: const EdgeInsets.all(padding), child: buildDescriptionField()),
Padding(padding: const EdgeInsets.all(padding), child: buildPasswordField()),
Padding(padding: const EdgeInsets.all(padding), child: buildSlugField()),
Padding(
padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding),
child: buildShowMetaButton(),
),
Padding(
padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding),
child: buildAllowDownloadButton(),
),
Padding(
padding: const EdgeInsets.only(left: padding, right: 20, bottom: 20),
child: buildAllowUploadButton(),
),
if (existingLink != null)
Padding(
padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding),
child: buildEditExpiryButton(),
),
Padding(
padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding),
child: buildExpiryAfterButton(),
),
if (newShareLink.value.isEmpty)
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(right: padding + 10, bottom: padding),
child: ElevatedButton(
onPressed: existingLink != null ? handleEditLink : handleNewLink,
child: Text(
existingLink != null ? "shared_link_edit_submit_button" : "create_link",
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
).tr(),
),
child: newShareLink.value.isEmpty
? Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: ListView(
children: [
const SizedBox(height: 20),
buildLinkTitle(),
if (existingLink != null)
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 16),
buildLinkCopyField(
buildSharedLinkUrl(
baseUrl: displayServerUrl,
slug: existingLink!.slug,
key: existingLink!.key,
) ??
'',
),
const SizedBox(height: 24),
const Divider(),
],
),
const SizedBox(height: 24),
buildDescriptionField(),
const SizedBox(height: 16),
buildPasswordField(),
const SizedBox(height: 16),
buildSlugField(),
const SizedBox(height: 16),
buildShowMetaButton(),
const SizedBox(height: 16),
buildAllowDownloadButton(),
const SizedBox(height: 16),
buildAllowUploadButton(),
const SizedBox(height: 16),
buildExpiryAfterButton(),
const SizedBox(height: 24),
Align(
alignment: Alignment.centerRight,
child: Row(
mainAxisSize: MainAxisSize.min,
spacing: 8,
children: [
if (existingLink != null)
OutlinedButton.icon(
style: OutlinedButton.styleFrom(
foregroundColor: themeData.colorScheme.error,
side: BorderSide(color: themeData.colorScheme.error),
),
onPressed: handleDeleteLink,
icon: const Icon(Icons.delete_outline),
label: Text(
context.t.delete,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
),
ElevatedButton.icon(
icon: const Icon(Icons.check),
onPressed: existingLink != null ? handleEditLink : handleNewLink,
label: Text(
existingLink != null ? context.t.shared_link_edit_submit_button : context.t.create_link,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
),
],
),
),
const SizedBox(height: 40),
],
),
),
if (newShareLink.value.isNotEmpty)
Padding(
padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding),
child: buildNewLinkField(),
),
],
),
)
: Center(child: buildNewLinkReadyScreen()),
),
);
}
@@ -37,6 +37,7 @@ class _DriftAlbumsPageState extends ConsumerState<DriftAlbumsPage> {
final scrollView = CustomScrollView(
controller: _scrollController,
physics: const AlwaysScrollableScrollPhysics(),
slivers: [
ImmichSliverAppBar(
snap: false,
@@ -5,7 +5,6 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
@RoutePage()
class DriftAssetSelectionTimelinePage extends ConsumerWidget {
@@ -22,17 +21,13 @@ class DriftAssetSelectionTimelinePage extends ConsumerWidget {
),
),
timelineServiceProvider.overrideWith((ref) {
final user = ref.watch(currentUserProvider);
if (user == null) {
throw Exception('User must be logged in to access asset selection timeline');
}
final timelineService = ref.watch(timelineFactoryProvider).remoteAssets(user.id);
final timelineUsers = ref.watch(timelineUsersProvider).valueOrNull ?? [];
final timelineService = ref.watch(timelineFactoryProvider).main(timelineUsers);
ref.onDispose(timelineService.dispose);
return timelineService;
}),
],
child: const Timeline(),
child: const Timeline(showStorageIndicator: true),
);
}
}
@@ -179,17 +179,14 @@ class _DriftCreateAlbumPageState extends ConsumerState<DriftCreateAlbumPage> {
}
final album = await ref
.watch(remoteAlbumProvider.notifier)
.createAlbum(
.read(remoteAlbumProvider.notifier)
.createAlbumWithAssets(
title: title,
description: albumDescriptionController.text.trim(),
assetIds: selectedAssets.map((asset) {
final remoteAsset = asset as RemoteAsset;
return remoteAsset.id;
}).toList(),
assets: selectedAssets,
);
if (album != null) {
if (album != null && context.mounted) {
unawaited(context.replaceRoute(RemoteAlbumRoute(album: album)));
}
}
@@ -8,6 +8,7 @@ import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/album/pending_uploads_banner.widget.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart';
import 'package:immich_mobile/presentation/widgets/remote_album/drift_album_option.widget.dart';
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
@@ -39,7 +40,8 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
}
Future<void> addAssets(BuildContext context) async {
final albumAssets = await ref.read(remoteAlbumProvider.notifier).getAssets(_album.id);
final notifier = ref.read(remoteAlbumProvider.notifier);
final albumAssets = await notifier.getAssets(_album.id);
final newAssets = await context.pushRoute<Set<BaseAsset>>(
DriftAssetSelectionTimelineRoute(lockedSelectionAssets: albumAssets.toSet()),
@@ -49,17 +51,9 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
return;
}
final added = await ref
.read(remoteAlbumProvider.notifier)
.addAssets(
_album.id,
newAssets.map((asset) {
final remoteAsset = asset as RemoteAsset;
return remoteAsset.id;
}).toList(),
);
final added = await notifier.addAssetsToAlbum(_album.id, newAssets);
if (added > 0) {
if (added > 0 && context.mounted) {
ImmichToast.show(
context: context,
msg: "assets_added_to_album_count".t(context: context, args: {'count': added.toString()}),
@@ -186,6 +180,7 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
currentRemoteAlbumScopedProvider.overrideWithValue(_album),
],
child: Timeline(
topSliverWidget: PendingUploadsBanner(albumId: _album.id),
appBar: RemoteAlbumSliverAppBar(
icon: Icons.photo_album_outlined,
kebabMenu: _AlbumKebabMenu(
@@ -0,0 +1,376 @@
import 'dart:async';
import 'dart:math';
import 'dart:ui';
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/config/slideshow_config.dart';
import 'package:immich_mobile/domain/services/timeline.service.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/scroll_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/pages/common/settings.page.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/video_viewer.widget.dart';
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/video_player_provider.dart';
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';
import 'package:immich_mobile/widgets/photo_view/photo_view.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
@RoutePage()
class DriftSlideshowPage extends ConsumerStatefulWidget {
final TimelineService timeline;
const DriftSlideshowPage({super.key, required this.timeline});
@override
ConsumerState<DriftSlideshowPage> createState() => _DriftSlideshowPageState();
}
class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> {
late SlideshowConfig _config;
late final PageController _pageController;
late final Stopwatch _stopwatch;
late Timer _timer;
late int _index;
late int _nextIndex;
bool _paused = false;
bool _showAppBar = false;
@override
initState() {
super.initState();
_config = ref.read(appConfigProvider.select((s) => s.slideshow));
final asset = ref.read(assetViewerProvider).currentAsset;
_index = asset == null ? 0 : widget.timeline.getIndex(asset.heroTag) ?? 0;
_pageController = PageController(initialPage: _index);
_stopwatch = Stopwatch();
_createTimer();
_updateNextIndex();
ref.listenManual(appConfigProvider.select((s) => s.slideshow), _onConfigChanged);
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
unawaited(WakelockPlus.enable());
}
@override
dispose() {
_timer.cancel();
_stopwatch.stop();
_pageController.dispose();
unawaited(WakelockPlus.disable());
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
super.dispose();
}
void _play() {
final asset = widget.timeline.getAssetSafe(_index)!;
if (asset.isImage) {
_createTimer();
} else if (ref.read(videoPlayerProvider(asset.heroTag)).status == VideoPlaybackStatus.paused) {
ref.read(videoPlayerProvider(asset.heroTag).notifier).play();
} else {
_nextPage();
}
_updateNextIndex();
setState(() {
_paused = false;
});
}
void _pause() {
_timer.cancel();
_stopwatch.stop();
final asset = widget.timeline.getAssetSafe(_index)!;
if (!asset.isImage) {
ref.read(videoPlayerProvider(asset.heroTag).notifier).pause();
}
setState(() {
_paused = true;
});
}
void _onConfigChanged(SlideshowConfig? previous, SlideshowConfig next) {
if (_config == next) {
return;
}
final durationChanged = _config.duration != next.duration;
_config = next;
_updateNextIndex();
final asset = widget.timeline.getAssetSafe(_index);
if (durationChanged && !_paused && asset?.isImage == true) {
_timer.cancel();
_createTimer();
}
setState(() {});
}
void _updateNextIndex() {
_nextIndex = switch (_config.direction) {
SlideshowDirection.forward => _index + 1,
SlideshowDirection.backward => _index - 1,
SlideshowDirection.shuffle => widget.timeline.getIndex(widget.timeline.getRandomAsset().heroTag)!,
};
if (!widget.timeline.hasRange(_nextIndex, 1)) {
widget.timeline.preloadAssets(_nextIndex);
}
}
void _nextPage() async {
if (_nextIndex < 0 || _nextIndex >= widget.timeline.totalAssets) {
if (_config.repeat) {
final wrapped = _config.direction == SlideshowDirection.forward ? 0 : widget.timeline.totalAssets - 1;
await widget.timeline.preloadAssets(wrapped);
_pageController.jumpToPage(wrapped);
} else {
setState(() {
_paused = true;
});
}
return;
}
if (!widget.timeline.hasRange(_nextIndex, 1)) {
await widget.timeline.preloadAssets(_nextIndex);
}
if (_config.direction == SlideshowDirection.shuffle || !_config.transition) {
_pageController.jumpToPage(_nextIndex);
} else {
unawaited(_pageController.animateToPage(_nextIndex, duration: Durations.long2, curve: Curves.easeIn));
}
}
void _createTimer() {
_timer = Timer(Duration(milliseconds: _config.duration * 1000 - _stopwatch.elapsedMilliseconds), () {
_stopwatch.stop();
_stopwatch.reset();
_nextPage();
});
_stopwatch.start();
}
void _pageChanged(int page) {
final asset = widget.timeline.getAssetSafe(page)!;
setState(() {
_index = page;
if (!asset.isImage) {
_paused = false;
}
});
_timer.cancel();
_stopwatch.stop();
_stopwatch.reset();
if (!_paused && asset.isImage) {
_createTimer();
}
_updateNextIndex();
}
void _onTapUp() async {
await SystemChrome.setEnabledSystemUIMode(_showAppBar ? SystemUiMode.immersive : SystemUiMode.edgeToEdge);
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
_showAppBar = !_showAppBar;
});
});
}
Widget _getProgressBar(BuildContext context) {
final asset = widget.timeline.getAssetSafe(_index);
if (asset == null) {
return Container();
}
if (asset.isImage) {
final elapsed = _stopwatch.elapsedMilliseconds;
final duration = _config.duration * 1000;
return TweenAnimationBuilder(
key: Key(_index.toString()),
tween: Tween<double>(begin: elapsed / duration.toDouble(), end: _paused ? elapsed / duration.toDouble() : 1.0),
duration: Duration(milliseconds: _paused ? 1 : max(duration - elapsed, 1)),
builder: (context, value, _) => LinearProgressIndicator(
color: context.colorScheme.primary,
borderRadius: const BorderRadius.all(Radius.zero),
minHeight: 5,
value: value,
),
);
} else {
return LinearProgressIndicator(
color: context.colorScheme.primary,
borderRadius: const BorderRadius.all(Radius.zero),
minHeight: 5,
value:
ref.watch(videoPlayerProvider(asset.heroTag).select((s) => s.position)).inMilliseconds /
asset.duration.inMilliseconds,
);
}
}
Widget _getBlur(BuildContext context, int index) {
final asset = widget.timeline.getAssetSafe(index);
if (asset == null) {
return Container();
}
return ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 30, sigmaY: 30),
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: getFullImageProvider(asset, size: Size(context.width, context.height)),
fit: BoxFit.cover,
),
),
child: Container(color: Colors.black.withValues(alpha: 0.2)),
),
);
}
Widget _getPhotoView(BuildContext context, int index) {
final asset = widget.timeline.getAssetSafe(index);
if (asset == null) {
return const Center(child: ImmichLoadingIndicator());
}
final scale = _config.look == SlideshowLook.cover
? PhotoViewComputedScale.covered
: PhotoViewComputedScale.contained;
final isCurrent = _index == index;
final imageProvider = getFullImageProvider(asset, size: context.sizeData);
if (asset.isImage) {
final zoomOut = index % 2 == 1;
final elapsed = _stopwatch.elapsedMilliseconds;
final duration = _config.duration * 1000;
final progress = zoomOut ? 1.0 - elapsed / duration.toDouble() : elapsed / duration.toDouble();
return TweenAnimationBuilder(
tween: Tween<double>(
begin: progress,
end: _paused
? progress
: zoomOut
? 0.0
: 1.0,
),
duration: Duration(milliseconds: _paused ? 1 : max(duration - elapsed, 1)),
builder: (context, value, _) => PhotoView(
imageProvider: imageProvider,
index: index,
disableScaleGestures: true,
gaplessPlayback: true,
filterQuality: FilterQuality.high,
initialScale: scale * (1.0 + value / 10.0),
controller: PhotoViewController(),
onTapUp: (_, _, _) => _onTapUp(),
),
);
} else {
final status = ref.watch(videoPlayerProvider(asset.heroTag).select((s) => s.status));
final position = ref.read(videoPlayerProvider(asset.heroTag)).position;
if (status == VideoPlaybackStatus.completed && isCurrent && position.inMicroseconds > 0) {
_nextPage();
} else if (status == VideoPlaybackStatus.playing) {
ref.read(videoPlayerProvider(asset.heroTag).notifier).setLoop(false);
}
return PhotoView.customChild(
onTapUp: (_, _, _) => _onTapUp(),
disableScaleGestures: true,
filterQuality: FilterQuality.high,
initialScale: scale,
child: NativeVideoViewer(
asset: asset,
isCurrent: isCurrent,
image: Image(image: imageProvider, fit: BoxFit.contain, alignment: Alignment.center),
),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size(AppBar().preferredSize.width, AppBar().preferredSize.height + 5),
child: IgnorePointer(
ignoring: !_showAppBar,
child: AnimatedOpacity(
opacity: _showAppBar ? 1.0 : 0.0,
duration: Durations.short2,
child: Column(
children: [
AppBar(
backgroundColor: context.scaffoldBackgroundColor,
title: Text("slideshow".t(context: context)),
actions: [
IconButton(
onPressed: _paused ? _play : _pause,
icon: Icon(_paused ? Icons.play_arrow : Icons.pause),
),
IconButton(
onPressed: () {
_pause();
context.pushRoute(SettingsSubRoute(section: SettingSection.assetViewer));
},
icon: const Icon(Icons.settings),
),
],
),
_getProgressBar(context),
],
),
),
),
),
extendBody: true,
extendBodyBehindAppBar: true,
backgroundColor: Colors.black,
body: PhotoViewGestureDetectorScope(
axis: Axis.horizontal,
child: PageView.builder(
controller: _pageController,
physics: const FastClampingScrollPhysics(),
itemCount: widget.timeline.totalAssets,
onPageChanged: _pageChanged,
itemBuilder: (context, index) => Stack(
children: [
if (_config.look == SlideshowLook.blurredBackground) _getBlur(context, index),
_getPhotoView(context, index),
],
),
),
),
);
}
}
@@ -186,7 +186,7 @@ class DriftSearchPage extends HookConsumerWidget {
expanded: true,
onSearch: handleApply,
onClear: handleClear,
child: TagPicker(onSelect: handleOnSelect, filter: (filter.value.tagIds ?? []).toSet()),
child: TagPicker(onSelectExistingTag: handleOnSelect, filter: (filter.value.tagIds ?? []).toSet()),
),
),
);
@@ -50,10 +50,13 @@ class BaseActionButton extends ConsumerWidget {
final iconColor = this.iconColor;
return MenuItemButton(
style: MenuItemButton.styleFrom(alignment: Alignment.centerLeft, padding: const EdgeInsets.all(16)),
leadingIcon: Icon(iconData, color: iconColor),
style: MenuItemButton.styleFrom(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
),
leadingIcon: Icon(iconData, color: iconColor, size: 20),
onPressed: onPressed,
child: Text(label, style: TextStyle(fontSize: 16, color: iconColor)),
child: Text(label, style: TextStyle(fontSize: 15, color: iconColor)),
);
}
@@ -0,0 +1,46 @@
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
class BulkTagAssetsActionButton extends ConsumerWidget {
final ActionSource source;
const BulkTagAssetsActionButton({super.key, required this.source});
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
final result = await ref.read(actionProvider.notifier).tagAssets(source, context);
if (result == null) {
return;
}
ref.read(multiSelectProvider.notifier).reset();
if (!context.mounted) {
return;
}
ImmichToast.show(
context: context,
msg: result.success
? 'tagged_assets'.t(context: context, args: {'count': result.count.toString()})
: 'errors.failed_to_tag_assets'.t(context: context),
gravity: ToastGravity.BOTTOM,
toastType: result.success ? ToastType.success : ToastType.error,
);
}
@override
Widget build(BuildContext context, WidgetRef ref) {
return BaseActionButton(
iconData: Icons.sell_outlined,
label: "control_bottom_app_bar_add_tags".t(context: context),
onPressed: () => _onTap(context, ref),
);
}
}
@@ -0,0 +1,34 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/routing/router.dart';
class SlideshowActionButton extends ConsumerWidget {
final bool iconOnly;
final bool menuItem;
const SlideshowActionButton({super.key, this.iconOnly = false, this.menuItem = false});
void _onTap(BuildContext context, WidgetRef ref) {
if (!context.mounted) {
return;
}
context.pushRoute(DriftSlideshowRoute(timeline: ref.read(timelineServiceProvider)));
}
@override
Widget build(BuildContext context, WidgetRef ref) {
return BaseActionButton(
iconData: Icons.slideshow,
label: "slideshow".t(context: context),
iconOnly: iconOnly,
menuItem: menuItem,
onPressed: () => _onTap(context, ref),
maxWidth: 100,
);
}
}
@@ -0,0 +1,252 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
import 'package:immich_mobile/providers/album/pending_album_uploads.provider.dart';
/// Pinned banner sliver that surfaces in-flight album uploads directly under
/// the album app bar. Renders nothing while the queue is empty. Tapping the
/// banner opens a bottom sheet with per-asset progress.
class PendingUploadsBanner extends ConsumerWidget {
static const double _height = 52;
final String albumId;
const PendingUploadsBanner({super.key, required this.albumId});
@override
Widget build(BuildContext context, WidgetRef ref) {
final pending = ref.watch(pendingAlbumUploadsProvider(albumId));
if (pending.isEmpty) {
return const SliverToBoxAdapter(child: SizedBox.shrink());
}
final hasFailures = pending.any((p) => p.failed);
final clamped = pending.map((p) => p.progress.clamp(0.0, 1.0)).toList(growable: false);
final overallProgress = clamped.isEmpty ? 0.0 : clamped.reduce((a, b) => a + b) / clamped.length;
final isIndeterminate = overallProgress <= 0.0;
return SliverPersistentHeader(
pinned: true,
delegate: _PendingUploadsBannerDelegate(
height: _height,
child: _PendingUploadsBannerContent(
albumId: albumId,
previewAsset: pending.first.asset,
count: pending.length,
overallProgress: overallProgress,
isIndeterminate: isIndeterminate,
hasFailures: hasFailures,
),
),
);
}
static void _openSheet(BuildContext context, String albumId) {
showModalBottomSheet(
context: context,
showDragHandle: true,
builder: (_) => _PendingUploadsSheet(albumId: albumId),
);
}
}
class _PendingUploadsBannerDelegate extends SliverPersistentHeaderDelegate {
final double height;
final Widget child;
const _PendingUploadsBannerDelegate({required this.height, required this.child});
@override
double get minExtent => height;
@override
double get maxExtent => height;
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) => child;
@override
bool shouldRebuild(covariant _PendingUploadsBannerDelegate oldDelegate) =>
height != oldDelegate.height || child != oldDelegate.child;
}
class _PendingUploadsBannerContent extends StatelessWidget {
final String albumId;
final BaseAsset previewAsset;
final int count;
final double overallProgress;
final bool isIndeterminate;
final bool hasFailures;
const _PendingUploadsBannerContent({
required this.albumId,
required this.previewAsset,
required this.count,
required this.overallProgress,
required this.isIndeterminate,
required this.hasFailures,
});
@override
Widget build(BuildContext context) {
final percentLabel = isIndeterminate ? '' : ' · ${(overallProgress * 100).toInt()}%';
return Material(
color: hasFailures ? context.colorScheme.errorContainer : context.colorScheme.surfaceContainerHigh,
child: InkWell(
onTap: () => PendingUploadsBanner._openSheet(context, albumId),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(4)),
child: SizedBox(width: 32, height: 32, child: Thumbnail.fromAsset(asset: previewAsset)),
),
const SizedBox(width: 12),
Expanded(
child: Text(
'${'uploading'.t(context: context)} $count$percentLabel',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w500),
),
),
if (hasFailures)
Padding(
padding: const EdgeInsets.only(left: 8),
child: Icon(Icons.error_outline, color: context.colorScheme.error, size: 20),
),
Icon(Icons.chevron_right_rounded, color: context.colorScheme.onSurfaceVariant),
],
),
),
),
SizedBox(
height: 3,
child: LinearProgressIndicator(
value: isIndeterminate ? null : overallProgress,
backgroundColor: context.colorScheme.surfaceContainerHighest,
valueColor: AlwaysStoppedAnimation<Color>(
hasFailures ? context.colorScheme.error : context.colorScheme.primary,
),
),
),
],
),
),
);
}
}
class _PendingUploadsSheet extends ConsumerWidget {
final String albumId;
const _PendingUploadsSheet({required this.albumId});
@override
Widget build(BuildContext context, WidgetRef ref) {
final pending = ref.watch(pendingAlbumUploadsProvider(albumId));
// Auto-dismiss when the queue empties.
if (pending.isEmpty) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (Navigator.of(context).canPop()) {
Navigator.of(context).pop();
}
});
return const SizedBox.shrink();
}
final failedCount = pending.where((p) => p.failed).length;
return SafeArea(
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Row(
children: [
Expanded(
child: Text(
'${'uploading'.t(context: context)} (${pending.length})',
style: context.textTheme.titleMedium,
),
),
if (failedCount > 0)
TextButton.icon(
onPressed: () => ref.read(pendingAlbumUploadsProvider(albumId).notifier).clearFailed(),
icon: const Icon(Icons.clear_rounded, size: 18),
label: Text('clear_failed_count'.t(context: context, args: {'count': failedCount})),
style: TextButton.styleFrom(foregroundColor: context.colorScheme.error),
),
],
),
),
SizedBox(
height: 96,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: pending.length,
separatorBuilder: (_, __) => const SizedBox(width: 8),
itemBuilder: (_, index) => _PendingUploadTile(entry: pending[index]),
),
),
],
),
),
);
}
}
class _PendingUploadTile extends StatelessWidget {
final PendingAlbumUpload entry;
const _PendingUploadTile({required this.entry});
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: SizedBox(
width: 96,
height: 96,
child: Stack(
fit: StackFit.expand,
children: [
Thumbnail.fromAsset(asset: entry.asset),
Positioned.fill(
child: ColoredBox(
color: entry.failed ? Colors.red.withValues(alpha: 0.6) : Colors.black54,
child: Center(
child: entry.failed
? const Icon(Icons.error_outline, color: Colors.white, size: 28)
: SizedBox(
width: 32,
height: 32,
child: CircularProgressIndicator(
value: entry.progress > 0 ? entry.progress : null,
strokeWidth: 2.5,
backgroundColor: Colors.white24,
valueColor: const AlwaysStoppedAnimation<Color>(Colors.white),
),
),
),
),
),
],
),
),
);
}
}
@@ -56,10 +56,13 @@ class _AssetPageState extends ConsumerState<AssetPage> {
_DragIntent _dragIntent = _DragIntent.none;
Drag? _drag;
BaseAsset? _asset;
@override
void initState() {
super.initState();
_eventSubscription = EventStream.shared.listen(_onEvent);
_asset = ref.read(timelineServiceProvider).getAssetSafe(widget.index);
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted || !_scrollController.hasClients) {
return;
@@ -71,6 +74,14 @@ class _AssetPageState extends ConsumerState<AssetPage> {
});
}
@override
void didUpdateWidget(AssetPage oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.index != widget.index) {
_asset = ref.read(timelineServiceProvider).getAssetSafe(widget.index);
}
}
@override
void dispose() {
_scrollController.dispose();
@@ -383,7 +394,7 @@ class _AssetPageState extends ConsumerState<AssetPage> {
final stackIndex = ref.watch(assetViewerProvider.select((s) => s.stackIndex));
final isPlayingMotionVideo = ref.watch(isPlayingMotionVideoProvider);
final asset = ref.read(timelineServiceProvider).getAssetSafe(widget.index);
final asset = _asset;
if (asset == null) {
return const Center(child: ImmichLoadingIndicator());
}
@@ -8,6 +8,7 @@ import 'package:immich_mobile/domain/models/setting.model.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/bulk_tag_assets_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart';
@@ -26,6 +27,7 @@ import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.d
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/setting.provider.dart';
import 'package:immich_mobile/providers/infrastructure/user_metadata.provider.dart';
import 'package:immich_mobile/providers/server_info.provider.dart';
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
@@ -57,6 +59,9 @@ class _GeneralBottomSheetState extends ConsumerState<GeneralBottomSheet> {
final multiselect = ref.watch(multiSelectProvider);
final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash));
final advancedTroubleshooting = ref.watch(settingsProvider.notifier).get(Setting.advancedTroubleshooting);
final tagsEnabled = ref.watch(
userMetadataPreferencesProvider.select((value) => value.valueOrNull?.tagsEnabled ?? false),
);
Future<void> addAssetsToAlbum(RemoteAlbum album) async {
final selectedAssets = multiselect.selectedAssets;
@@ -114,6 +119,7 @@ class _GeneralBottomSheetState extends ConsumerState<GeneralBottomSheet> {
: const DeletePermanentActionButton(source: ActionSource.timeline),
const FavoriteActionButton(source: ActionSource.timeline),
const ArchiveActionButton(source: ActionSource.timeline),
if (tagsEnabled) const BulkTagAssetsActionButton(source: ActionSource.timeline),
const EditDateTimeActionButton(source: ActionSource.timeline),
const EditLocationActionButton(source: ActionSource.timeline),
const MoveToLockFolderActionButton(source: ActionSource.timeline),
@@ -120,6 +120,9 @@ class _ThumbnailTileState extends ConsumerState<ThumbnailTile> {
},
flightShuttleBuilder: (context, animation, direction, from, to) {
void animationStatusListener(AnimationStatus status) {
if (!mounted) {
return;
}
final heroInFlight = status == AnimationStatus.forward || status == AnimationStatus.reverse;
if (_hideIndicators != heroInFlight) {
setState(() => _hideIndicators = heroInFlight);
@@ -242,7 +242,11 @@ class _AssetTileWidget extends ConsumerWidget {
return false;
}
return lockSelectionAssets.contains(asset);
// Iterate with `==` instead of `Set.contains` because `RemoteAsset.hashCode`
// includes `localId` while `==` does not — so the same server asset can
// hash to a different bucket when its `localId` differs (e.g., album-fetched
// copy has localId=null, merged-timeline copy has it populated).
return lockSelectionAssets.any((a) => a == asset);
}
@override
@@ -64,36 +64,32 @@ class Timeline extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
floatingActionButton: const DownloadStatusFloatingButton(),
body: LayoutBuilder(
builder: (_, constraints) => ProviderScope(
overrides: [
timelineArgsProvider.overrideWith(
(ref) => TimelineArgs(
maxWidth: constraints.maxWidth,
maxHeight: constraints.maxHeight,
columnCount: ref.watch(appConfigProvider.select((config) => config.timeline.tilesPerRow)),
showStorageIndicator: showStorageIndicator,
withStack: withStack,
groupBy: groupBy,
),
return LayoutBuilder(
builder: (_, constraints) => ProviderScope(
overrides: [
timelineArgsProvider.overrideWith(
(ref) => TimelineArgs(
maxWidth: constraints.maxWidth,
maxHeight: constraints.maxHeight,
columnCount: ref.watch(appConfigProvider.select((config) => config.timeline.tilesPerRow)),
showStorageIndicator: showStorageIndicator,
withStack: withStack,
groupBy: groupBy,
),
if (readOnly) readonlyModeProvider.overrideWith(() => _AlwaysReadOnlyNotifier()),
],
child: _SliverTimeline(
topSliverWidget: topSliverWidget,
topSliverWidgetHeight: topSliverWidgetHeight,
bottomSliverWidget: bottomSliverWidget,
appBar: appBar,
bottomSheet: bottomSheet,
withScrubber: withScrubber,
persistentBottomBar: persistentBottomBar,
snapToMonth: snapToMonth,
maxWidth: constraints.maxWidth,
loadingWidget: loadingWidget,
),
if (readOnly) readonlyModeProvider.overrideWith(() => _AlwaysReadOnlyNotifier()),
],
child: _SliverTimeline(
topSliverWidget: topSliverWidget,
topSliverWidgetHeight: topSliverWidgetHeight,
bottomSliverWidget: bottomSliverWidget,
appBar: appBar,
bottomSheet: bottomSheet,
withScrubber: withScrubber,
persistentBottomBar: persistentBottomBar,
snapToMonth: snapToMonth,
maxWidth: constraints.maxWidth,
loadingWidget: loadingWidget,
),
),
);
@@ -379,121 +375,126 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> {
ref.read(multiSelectProvider.notifier).reset();
}
},
child: asyncSegments.widgetWhen(
onLoading: widget.loadingWidget != null ? () => widget.loadingWidget! : null,
onData: (segments) {
final childCount = (segments.lastOrNull?.lastIndex ?? -1) + 1;
final double appBarExpandedHeight = widget.appBar != null && widget.appBar is MesmerizingSliverAppBar
? 200
: 0;
final topPadding = context.padding.top + (widget.appBar == null ? 0 : kToolbarHeight) + 10;
child: PrimaryScrollController(
controller: _scrollController,
child: Scaffold(
resizeToAvoidBottomInset: false,
floatingActionButton: const DownloadStatusFloatingButton(),
body: asyncSegments.widgetWhen(
onLoading: widget.loadingWidget != null ? () => widget.loadingWidget! : null,
onData: (segments) {
final childCount = (segments.lastOrNull?.lastIndex ?? -1) + 1;
final double appBarExpandedHeight = widget.appBar != null && widget.appBar is MesmerizingSliverAppBar
? 200
: 0;
final topPadding = context.padding.top + (widget.appBar == null ? 0 : kToolbarHeight) + 10;
const bottomSheetOpenModifier = 120.0;
final contentBottomPadding = context.padding.bottom + (isMultiSelectEnabled ? bottomSheetOpenModifier : 0);
final scrubberBottomPadding = contentBottomPadding + kScrubberThumbHeight;
const bottomSheetOpenModifier = 120.0;
final contentBottomPadding =
context.padding.bottom + (isMultiSelectEnabled ? bottomSheetOpenModifier : 0);
final scrubberBottomPadding = contentBottomPadding + kScrubberThumbHeight;
final grid = CustomScrollView(
primary: true,
physics: _scrollPhysics,
cacheExtent: maxHeight * 2,
slivers: [
if (isSelectionMode) const SelectionSliverAppBar() else if (widget.appBar != null) widget.appBar!,
if (widget.topSliverWidget != null) widget.topSliverWidget!,
_SliverSegmentedList(
segments: segments,
delegate: SliverChildBuilderDelegate(
(ctx, index) {
if (index >= childCount) {
return null;
}
final segment = segments.findByIndex(index);
return segment?.builder(ctx, index) ?? const SizedBox.shrink();
},
childCount: childCount,
addAutomaticKeepAlives: false,
// We add repaint boundary around tiles, so skip the auto boundaries
addRepaintBoundaries: false,
),
),
if (widget.bottomSliverWidget != null) widget.bottomSliverWidget!,
SliverPadding(padding: EdgeInsets.only(bottom: contentBottomPadding)),
],
);
final grid = CustomScrollView(
primary: true,
physics: _scrollPhysics,
cacheExtent: maxHeight * 2,
slivers: [
if (isSelectionMode) const SelectionSliverAppBar() else if (widget.appBar != null) widget.appBar!,
if (widget.topSliverWidget != null) widget.topSliverWidget!,
_SliverSegmentedList(
segments: segments,
delegate: SliverChildBuilderDelegate(
(ctx, index) {
if (index >= childCount) {
return null;
}
final segment = segments.findByIndex(index);
return segment?.builder(ctx, index) ?? const SizedBox.shrink();
},
childCount: childCount,
addAutomaticKeepAlives: false,
// We add repaint boundary around tiles, so skip the auto boundaries
addRepaintBoundaries: false,
),
),
if (widget.bottomSliverWidget != null) widget.bottomSliverWidget!,
SliverPadding(padding: EdgeInsets.only(bottom: contentBottomPadding)),
],
);
final Widget timeline;
if (widget.withScrubber) {
timeline = Scrubber(
snapToMonth: widget.snapToMonth,
layoutSegments: segments,
timelineHeight: maxHeight,
topPadding: topPadding,
bottomPadding: scrubberBottomPadding,
monthSegmentSnappingOffset: widget.topSliverWidgetHeight ?? 0 + appBarExpandedHeight,
hasAppBar: widget.appBar != null,
child: grid,
);
} else {
timeline = grid;
}
final Widget timeline;
if (widget.withScrubber) {
timeline = Scrubber(
snapToMonth: widget.snapToMonth,
layoutSegments: segments,
timelineHeight: maxHeight,
topPadding: topPadding,
bottomPadding: scrubberBottomPadding,
monthSegmentSnappingOffset: widget.topSliverWidgetHeight ?? 0 + appBarExpandedHeight,
hasAppBar: widget.appBar != null,
child: grid,
);
} else {
timeline = grid;
}
return PrimaryScrollController(
controller: _scrollController,
child: RawGestureDetector(
gestures: {
CustomScaleGestureRecognizer: GestureRecognizerFactoryWithHandlers<CustomScaleGestureRecognizer>(
() => CustomScaleGestureRecognizer(),
(CustomScaleGestureRecognizer scale) {
scale.onStart = (details) {
_baseScaleFactor = _scaleFactor;
};
return RawGestureDetector(
gestures: {
CustomScaleGestureRecognizer: GestureRecognizerFactoryWithHandlers<CustomScaleGestureRecognizer>(
() => CustomScaleGestureRecognizer(),
(CustomScaleGestureRecognizer scale) {
scale.onStart = (details) {
_baseScaleFactor = _scaleFactor;
};
scale.onUpdate = (details) {
final newScaleFactor = math.max(math.min(5.0, _baseScaleFactor * details.scale), 1.0);
final newPerRow = 7 - newScaleFactor.toInt();
scale.onUpdate = (details) {
final newScaleFactor = math.max(math.min(5.0, _baseScaleFactor * details.scale), 1.0);
final newPerRow = 7 - newScaleFactor.toInt();
if (newPerRow != _perRow) {
final targetAssetIndex = _getCurrentAssetIndex(segments);
setState(() {
_scaleFactor = newScaleFactor;
_perRow = newPerRow;
_restoreAssetIndex = targetAssetIndex;
});
if (newPerRow != _perRow) {
final targetAssetIndex = _getCurrentAssetIndex(segments);
setState(() {
_scaleFactor = newScaleFactor;
_perRow = newPerRow;
_restoreAssetIndex = targetAssetIndex;
});
ref.read(metadataProvider).write(MetadataKey.timelineTilesPerRow, _perRow);
}
};
},
),
},
child: TimelineDragRegion(
onStart: !isReadonlyModeEnabled ? _setDragStartIndex : null,
onAssetEnter: _handleDragAssetEnter,
onEnd: !isReadonlyModeEnabled ? _stopDrag : null,
onScroll: _dragScroll,
onScrollStart: () {
// Minimize the bottom sheet when drag selection starts
ref.read(timelineStateProvider.notifier).setScrolling(true);
ref.read(metadataProvider).write(MetadataKey.timelineTilesPerRow, _perRow);
}
};
},
),
},
child: Stack(
clipBehavior: Clip.none,
children: [
timeline,
if (isBottomWidgetVisible)
Positioned(
top: MediaQuery.paddingOf(context).top,
left: 25,
child: const SizedBox(
height: kToolbarHeight,
child: Center(child: _MultiSelectStatusButton()),
child: TimelineDragRegion(
onStart: !isReadonlyModeEnabled ? _setDragStartIndex : null,
onAssetEnter: _handleDragAssetEnter,
onEnd: !isReadonlyModeEnabled ? _stopDrag : null,
onScroll: _dragScroll,
onScrollStart: () {
// Minimize the bottom sheet when drag selection starts
ref.read(timelineStateProvider.notifier).setScrolling(true);
},
child: Stack(
clipBehavior: Clip.none,
children: [
timeline,
if (isBottomWidgetVisible)
Positioned(
top: MediaQuery.paddingOf(context).top,
left: 25,
child: const SizedBox(
height: kToolbarHeight,
child: Center(child: _MultiSelectStatusButton()),
),
),
),
if (isBottomWidgetVisible) widget.bottomSheet!,
],
if (isBottomWidgetVisible) widget.bottomSheet!,
],
),
),
),
),
);
},
);
},
),
),
),
);
}
@@ -0,0 +1,81 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
class PendingAlbumUpload {
final LocalAsset asset;
final double progress;
final bool failed;
const PendingAlbumUpload({required this.asset, this.progress = 0.0, this.failed = false});
PendingAlbumUpload copyWith({double? progress, bool? failed}) =>
PendingAlbumUpload(asset: asset, progress: progress ?? this.progress, failed: failed ?? this.failed);
}
class AlbumPendingUploadsNotifier extends AutoDisposeFamilyNotifier<List<PendingAlbumUpload>, String> {
KeepAliveLink? _keepAliveLink;
@override
List<PendingAlbumUpload> build(String albumId) {
ref.onDispose(() {
_keepAliveLink?.close();
_keepAliveLink = null;
});
return const [];
}
void enqueue(Iterable<LocalAsset> assets) {
if (assets.isEmpty) {
return;
}
final existingIds = state.map((e) => e.asset.id).toSet();
final additions = assets.where((a) => !existingIds.contains(a.id)).map((a) => PendingAlbumUpload(asset: a));
state = [...state, ...additions];
_syncKeepAlive();
}
void updateProgress(String localAssetId, double progress) {
state = [
for (final entry in state)
if (entry.asset.id == localAssetId) entry.copyWith(progress: progress, failed: false) else entry,
];
_syncKeepAlive();
}
void markFailed(String localAssetId) {
state = [
for (final entry in state)
if (entry.asset.id == localAssetId) entry.copyWith(failed: true) else entry,
];
_syncKeepAlive();
}
void markAllFailed() {
state = [for (final entry in state) entry.copyWith(failed: true)];
_syncKeepAlive();
}
void remove(String localAssetId) {
state = state.where((e) => e.asset.id != localAssetId).toList();
_syncKeepAlive();
}
void clearFailed() {
state = state.where((e) => !e.failed).toList();
_syncKeepAlive();
}
void _syncKeepAlive() {
if (state.isEmpty) {
_keepAliveLink?.close();
_keepAliveLink = null;
} else {
_keepAliveLink ??= ref.keepAlive();
}
}
}
final pendingAlbumUploadsProvider = NotifierProvider.autoDispose
.family<AlbumPendingUploadsNotifier, List<PendingAlbumUpload>, String>(AlbumPendingUploadsNotifier.new);
+10 -5
View File
@@ -1,6 +1,9 @@
import 'dart:convert';
import 'package:flutter_udid/flutter_udid.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/constants.dart';
import 'package:immich_mobile/domain/models/metadata_key.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/domain/services/user.service.dart';
@@ -8,6 +11,7 @@ import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/models/auth/auth_state.model.dart';
import 'package:immich_mobile/models/auth/login_response.model.dart';
import 'package:immich_mobile/providers/api.provider.dart';
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
import 'package:immich_mobile/services/api.service.dart';
import 'package:immich_mobile/services/auth.service.dart';
@@ -126,7 +130,8 @@ class AuthNotifier extends StateNotifier<AuthState> {
await _apiService.updateHeaders();
final serverEndpoint = Store.get(StoreKey.serverEndpoint);
final customHeaders = Store.tryGet(StoreKey.customHeaders);
final headerMap = _ref.read(metadataProvider).systemConfig.network.customHeaders;
final customHeaders = headerMap.isEmpty ? null : jsonEncode(headerMap);
await _widgetService.writeCredentials(serverEndpoint, accessToken, customHeaders);
// Get the deviceid from the store if it exists, otherwise generate a new one
@@ -174,19 +179,19 @@ class AuthNotifier extends StateNotifier<AuthState> {
}
Future<void> saveWifiName(String wifiName) async {
await Store.put(StoreKey.preferredWifiName, wifiName);
await _ref.read(metadataProvider).write(MetadataKey.networkPreferredWifiName, wifiName);
}
Future<void> saveLocalEndpoint(String url) async {
await Store.put(StoreKey.localEndpoint, url);
await _ref.read(metadataProvider).write(MetadataKey.networkLocalEndpoint, url);
}
String? getSavedWifiName() {
return Store.tryGet(StoreKey.preferredWifiName);
return _ref.read(metadataProvider).systemConfig.network.preferredWifiName;
}
String? getSavedLocalEndpoint() {
return Store.tryGet(StoreKey.localEndpoint);
return _ref.read(metadataProvider).systemConfig.network.localEndpoint;
}
/// Returns the current server endpoint (with /api) URL from the store
@@ -13,6 +13,7 @@ import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart'
import 'package:immich_mobile/providers/backup/asset_upload_progress.provider.dart';
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
import 'package:immich_mobile/providers/infrastructure/asset_viewer/asset.provider.dart' show assetExifProvider;
import 'package:immich_mobile/providers/infrastructure/tag.provider.dart';
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
import 'package:immich_mobile/providers/websocket.provider.dart';
@@ -353,6 +354,23 @@ class ActionNotifier extends Notifier<void> {
}
}
Future<ActionResult?> tagAssets(ActionSource source, BuildContext context) async {
final ids = _getOwnedRemoteIdsForSource(source);
try {
final count = await _service.tagAssets(ids, context);
if (count == null) {
return null;
}
ref.invalidate(tagProvider);
return ActionResult(count: count, success: true);
} catch (error, stack) {
_logger.severe('Failed to tag assets', error, stack);
ref.invalidate(tagProvider);
return ActionResult(count: ids.length, success: false, error: error.toString());
}
}
Future<ActionResult> removeFromAlbum(ActionSource source, String albumId) async {
final ids = _getRemoteIdsForSource(source);
try {
@@ -9,6 +9,7 @@ import 'package:immich_mobile/infrastructure/repositories/remote_album.repositor
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
import 'package:immich_mobile/providers/infrastructure/remote_album.provider.dart';
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
import 'package:immich_mobile/services/foreground_upload.service.dart';
final localAlbumRepository = Provider<DriftLocalAlbumRepository>(
(ref) => DriftLocalAlbumRepository(ref.watch(driftProvider)),
@@ -33,7 +34,11 @@ final remoteAlbumRepository = Provider<DriftRemoteAlbumRepository>(
);
final remoteAlbumServiceProvider = Provider<RemoteAlbumService>(
(ref) => RemoteAlbumService(ref.watch(remoteAlbumRepository), ref.watch(driftAlbumApiRepositoryProvider)),
(ref) => RemoteAlbumService(
ref.watch(remoteAlbumRepository),
ref.watch(driftAlbumApiRepositoryProvider),
ref.watch(foregroundUploadServiceProvider),
),
dependencies: [remoteAlbumRepository],
);
@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:collection/collection.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart';
@@ -6,8 +8,10 @@ import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/domain/services/remote_album.service.dart';
import 'package:immich_mobile/models/albums/album_search.model.dart';
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
import 'package:immich_mobile/providers/album/pending_album_uploads.provider.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
import 'package:immich_mobile/services/foreground_upload.service.dart';
import 'package:logging/logging.dart';
class RemoteAlbumState {
@@ -105,6 +109,46 @@ class RemoteAlbumNotifier extends Notifier<RemoteAlbumState> {
}
}
/// Creates an album from a heterogeneous asset selection. Already-remote
/// assets seed the album immediately; local-only assets are uploaded in the
/// background and linked one-by-one as each upload completes.
Future<RemoteAlbum?> createAlbumWithAssets({
required String title,
String? description,
Iterable<BaseAsset> assets = const [],
}) async {
try {
final currentUser = ref.read(currentUserProvider);
if (currentUser == null) {
throw Exception('User not logged in');
}
final candidates = RemoteAlbumService.categorizeCandidates(assets);
final album = await _remoteAlbumService.createAlbum(
title: title,
owner: currentUser,
description: description,
assetIds: candidates.remoteAssetIds,
);
state = state.copyWith(albums: [...state.albums, album]);
if (candidates.localAssetsToUpload.isNotEmpty) {
unawaited(
addAssetsToAlbum(
album.id,
candidates.localAssetsToUpload,
).then<void>((_) {}).catchError((Object _, StackTrace _) {}),
);
}
return album;
} catch (error, stack) {
_logger.severe('Failed to create album with assets', error, stack);
rethrow;
}
}
Future<RemoteAlbum?> updateAlbum(
String albumId, {
String? name,
@@ -155,8 +199,65 @@ class RemoteAlbumNotifier extends Notifier<RemoteAlbumState> {
return _remoteAlbumService.getAssets(albumId);
}
Future<int> addAssets(String albumId, List<String> assetIds) {
return _remoteAlbumService.addAssets(albumId: albumId, assetIds: assetIds);
Future<int> addAssets(String albumId, List<String> assetIds) async {
final added = await _remoteAlbumService.addAssets(albumId: albumId, assetIds: assetIds);
if (added > 0) {
await _refreshAlbumInState(albumId);
}
return added;
}
/// Adds a heterogeneous asset selection to an album. Already-remote assets
/// are linked immediately; local-only assets are queued in
/// [pendingAlbumUploadsProvider] (so the album page can show them with
/// progress indicators), uploaded, and linked one-by-one as each finishes.
Future<int> addAssetsToAlbum(String albumId, Iterable<BaseAsset> assets) async {
final currentUser = ref.read(currentUserProvider);
if (currentUser == null) {
throw Exception('User not logged in');
}
final candidates = RemoteAlbumService.categorizeCandidates(assets);
final pendingNotifier = ref.read(pendingAlbumUploadsProvider(albumId).notifier);
pendingNotifier.enqueue(candidates.localAssetsToUpload);
try {
final added = await _remoteAlbumService.addAssetsToAlbum(
albumId: albumId,
uploader: currentUser,
candidates: candidates,
uploadCallbacks: UploadCallbacks(
onProgress: (localAssetId, _, bytes, totalBytes) {
final progress = totalBytes > 0 ? bytes / totalBytes : 0.0;
pendingNotifier.updateProgress(localAssetId, progress);
},
onSuccess: (localAssetId, _) => pendingNotifier.remove(localAssetId),
onError: (localAssetId, _) => pendingNotifier.markFailed(localAssetId),
),
);
if (added > 0) {
await _refreshAlbumInState(albumId);
}
return added;
} catch (error, stack) {
if (candidates.localAssetsToUpload.isNotEmpty) {
pendingNotifier.markAllFailed();
}
_logger.severe('Failed to add assets to album $albumId', error, stack);
rethrow;
}
}
/// Re-reads a single album from the local DB and replaces it in [state] so
/// that views bound to the album list (counts, thumbnails) reflect the
/// latest junction-table changes without a full `refresh()`.
Future<void> _refreshAlbumInState(String albumId) async {
final updated = await _remoteAlbumService.get(albumId);
if (updated == null) {
return;
}
state = state.copyWith(albums: state.albums.map((album) => album.id == albumId ? updated : album).toList());
}
Future<void> addUsers(String albumId, List<String> userIds) {
@@ -1,16 +1,22 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/tag.model.dart';
import 'package:immich_mobile/infrastructure/repositories/tags_api.repository.dart';
import 'package:immich_mobile/domain/services/tag.service.dart';
class TagNotifier extends AsyncNotifier<Set<Tag>> {
@override
Future<Set<Tag>> build() async {
final repo = ref.read(tagsApiRepositoryProvider);
final allTags = await repo.getAllTags();
if (allTags == null) {
return {};
}
return allTags.map((t) => Tag.fromDto(t)).toSet();
return ref.watch(tagServiceProvider).getAllTags();
}
Future<int> bulkTagAssets(List<String> assetIds, List<String> tagIds) async {
return ref.read(tagServiceProvider).bulkTagAssets(assetIds, tagIds);
}
Future<List<Tag>> upsertTags(List<String> tags) async {
final upsertedTags = await ref.read(tagServiceProvider).upsertTags(tags);
state = AsyncValue.data({...?state.valueOrNull, ...upsertedTags});
return upsertedTags;
}
}
+13 -19
View File
@@ -1,46 +1,40 @@
import 'dart:convert';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
final authRepositoryProvider = Provider<AuthRepository>((ref) => AuthRepository(ref.watch(driftProvider)));
final authRepositoryProvider = Provider<AuthRepository>(
(ref) => AuthRepository(ref.watch(driftProvider), ref.watch(metadataProvider)),
);
class AuthRepository {
final Drift _drift;
final MetadataRepository _metadata;
const AuthRepository(this._drift);
const AuthRepository(this._drift, this._metadata);
Future<void> clearLocalData() async {
await SyncStreamRepository(_drift).reset();
}
bool getEndpointSwitchingFeature() {
return Store.tryGet(StoreKey.autoEndpointSwitching) ?? false;
return _metadata.systemConfig.network.autoEndpointSwitching;
}
String? getPreferredWifiName() {
return Store.tryGet(StoreKey.preferredWifiName);
return _metadata.systemConfig.network.preferredWifiName;
}
String? getLocalEndpoint() {
return Store.tryGet(StoreKey.localEndpoint);
return _metadata.systemConfig.network.localEndpoint;
}
List<AuxilaryEndpoint> getExternalEndpointList() {
final jsonString = Store.tryGet(StoreKey.externalEndpointList);
if (jsonString == null) {
return [];
}
final List<dynamic> jsonList = jsonDecode(jsonString);
final endpointList = jsonList.map((e) => AuxilaryEndpoint.fromJson(e)).toList();
return endpointList;
return _metadata.systemConfig.network.externalEndpointList
.map((url) => AuxilaryEndpoint(url: url, status: .valid))
.toList();
}
}
+2
View File
@@ -60,6 +60,7 @@ import 'package:immich_mobile/presentation/pages/drift_place_detail.page.dart';
import 'package:immich_mobile/presentation/pages/drift_recently_taken.page.dart';
import 'package:immich_mobile/presentation/pages/drift_recently_added.page.dart';
import 'package:immich_mobile/presentation/pages/drift_remote_album.page.dart';
import 'package:immich_mobile/presentation/pages/drift_slideshow.page.dart';
import 'package:immich_mobile/presentation/pages/drift_trash.page.dart';
import 'package:immich_mobile/presentation/pages/drift_user_selection.page.dart';
import 'package:immich_mobile/presentation/pages/drift_video.page.dart';
@@ -189,6 +190,7 @@ class AppRouter extends RootStackRouter {
AutoRoute(page: AssetTroubleshootRoute.page, guards: [_authGuard, _duplicateGuard]),
AutoRoute(page: DownloadInfoRoute.page, guards: [_authGuard, _duplicateGuard]),
AutoRoute(page: CleanupPreviewRoute.page, guards: [_authGuard, _duplicateGuard]),
AutoRoute(page: DriftSlideshowRoute.page, guards: [_authGuard, _duplicateGuard]),
// required to handle all deeplinks in deep_link.service.dart
// auto_route_library#1722
RedirectRoute(path: '*', redirectTo: '/'),
+47
View File
@@ -1095,6 +1095,53 @@ class DriftSearchRoute extends PageRouteInfo<void> {
);
}
/// generated route for
/// [DriftSlideshowPage]
class DriftSlideshowRoute extends PageRouteInfo<DriftSlideshowRouteArgs> {
DriftSlideshowRoute({
Key? key,
required TimelineService timeline,
List<PageRouteInfo>? children,
}) : super(
DriftSlideshowRoute.name,
args: DriftSlideshowRouteArgs(key: key, timeline: timeline),
initialChildren: children,
);
static const String name = 'DriftSlideshowRoute';
static PageInfo page = PageInfo(
name,
builder: (data) {
final args = data.argsAs<DriftSlideshowRouteArgs>();
return DriftSlideshowPage(key: args.key, timeline: args.timeline);
},
);
}
class DriftSlideshowRouteArgs {
const DriftSlideshowRouteArgs({this.key, required this.timeline});
final Key? key;
final TimelineService timeline;
@override
String toString() {
return 'DriftSlideshowRouteArgs{key: $key, timeline: $timeline}';
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! DriftSlideshowRouteArgs) return false;
return key == other.key && timeline == other.timeline;
}
@override
int get hashCode => key.hashCode ^ timeline.hashCode;
}
/// generated route for
/// [DriftTrashPage]
class DriftTrashRoute extends PageRouteInfo<void> {
+25
View File
@@ -7,6 +7,7 @@ import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/asset_edit.model.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/domain/services/tag.service.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/extensions/platform_extensions.dart';
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
@@ -23,6 +24,7 @@ import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/utils/timezone.dart';
import 'package:immich_mobile/widgets/common/date_time_picker.dart';
import 'package:immich_mobile/widgets/common/location_picker.dart';
import 'package:immich_mobile/widgets/common/tag_picker.dart';
import 'package:maplibre_gl/maplibre_gl.dart' as maplibre;
final actionServiceProvider = Provider<ActionService>(
@@ -35,6 +37,7 @@ final actionServiceProvider = Provider<ActionService>(
ref.watch(trashedLocalAssetRepository),
ref.watch(assetMediaRepositoryProvider),
ref.watch(downloadRepositoryProvider),
ref.watch(tagServiceProvider),
),
);
@@ -47,6 +50,7 @@ class ActionService {
final DriftTrashedLocalAssetRepository _trashedLocalAssetRepository;
final AssetMediaRepository _assetMediaRepository;
final DownloadRepository _downloadRepository;
final TagService _tagService;
const ActionService(
this._assetApiRepository,
@@ -57,6 +61,7 @@ class ActionService {
this._trashedLocalAssetRepository,
this._assetMediaRepository,
this._downloadRepository,
this._tagService,
);
Future<void> shareLink(List<String> remoteIds, BuildContext context) async {
@@ -234,6 +239,26 @@ class ActionService {
return true;
}
Future<int?> tagAssets(List<String> remoteIds, BuildContext context) async {
final tagResults = await showTagPickerModal(context: context);
if (tagResults == null) {
// user cancelled
return null;
}
final selectedTagIds = Set<String>.from(tagResults.$1);
final selectedNewTagValues = tagResults.$2;
if (selectedNewTagValues.isNotEmpty) {
final upsertedTags = await _tagService.upsertTags(selectedNewTagValues.toList());
selectedTagIds.addAll(upsertedTags.map((t) => t.id));
}
if (selectedTagIds.isEmpty) {
return 0;
}
return _tagService.bulkTagAssets(remoteIds, selectedTagIds.toList());
}
Future<void> stack(String userId, List<String> remoteIds) async {
final stack = await _assetApiRepository.stack(remoteIds);
await _remoteAssetRepository.stack(userId, stack);
+8 -17
View File
@@ -5,8 +5,8 @@ import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/utils/debug_print.dart';
import 'package:immich_mobile/utils/url_helper.dart';
import 'package:logging/logging.dart';
@@ -177,30 +177,21 @@ class ApiService {
if (serverEndpoint != null && serverEndpoint.isNotEmpty) {
urls.add(serverEndpoint);
}
final localEndpoint = Store.tryGet(StoreKey.localEndpoint);
if (localEndpoint != null && localEndpoint.isNotEmpty) {
final network = MetadataRepository.instance.systemConfig.network;
final localEndpoint = network.localEndpoint;
if (localEndpoint != null) {
urls.add(localEndpoint);
}
final externalJson = Store.tryGet(StoreKey.externalEndpointList);
if (externalJson != null) {
final List<dynamic> list = jsonDecode(externalJson);
for (final entry in list) {
final url = AuxilaryEndpoint.fromJson(entry).url;
if (url.isNotEmpty) {
urls.add(url);
}
for (final url in network.externalEndpointList) {
if (url.isNotEmpty) {
urls.add(url);
}
}
return urls;
}
static Map<String, String> getRequestHeaders() {
var customHeadersStr = Store.get(StoreKey.customHeaders, "");
if (customHeadersStr.isEmpty) {
return const {};
}
return (jsonDecode(customHeadersStr) as Map).cast<String, String>();
return MetadataRepository.instance.systemConfig.network.customHeaders;
}
ApiClient get apiClient => _apiClient;
@@ -8,7 +8,6 @@ enum AppSettingsEnum<T> {
selectedAlbumSortReverse<bool>(StoreKey.selectedAlbumSortReverse, null, true),
enableHapticFeedback<bool>(StoreKey.enableHapticFeedback, null, true),
syncAlbums<bool>(StoreKey.syncAlbums, null, false),
autoEndpointSwitching<bool>(StoreKey.autoEndpointSwitching, null, false),
enableBackup<bool>(StoreKey.enableBackup, null, false),
useCellularForUploadVideos<bool>(StoreKey.useWifiForUploadVideos, null, false),
useCellularForUploadPhotos<bool>(StoreKey.useWifiForUploadPhotos, null, false),
-4
View File
@@ -123,10 +123,6 @@ class AuthService {
_authRepository.clearLocalData(),
Store.delete(StoreKey.currentUser),
Store.delete(StoreKey.accessToken),
Store.delete(StoreKey.autoEndpointSwitching),
Store.delete(StoreKey.preferredWifiName),
Store.delete(StoreKey.localEndpoint),
Store.delete(StoreKey.externalEndpointList),
]);
}
@@ -27,6 +27,7 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/set_profile_pi
import 'package:immich_mobile/presentation/widgets/action_buttons/share_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/share_link_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/similar_photos_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/slideshow_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/unarchive_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action_button.widget.dart';
@@ -73,6 +74,7 @@ enum ActionButtonType {
similarPhotos,
setProfilePicture,
viewInTimeline,
slideshow,
download,
upload,
openInBrowser,
@@ -179,6 +181,7 @@ enum ActionButtonType {
context.timelineOrigin != TimelineOrigin.localAlbum &&
context.isOwner,
ActionButtonType.cast => context.isCasting || context.asset.hasRemote,
ActionButtonType.slideshow => true,
};
}
@@ -200,6 +203,7 @@ enum ActionButtonType {
iconOnly: iconOnly,
menuItem: menuItem,
),
ActionButtonType.slideshow => SlideshowActionButton(iconOnly: iconOnly, menuItem: menuItem),
ActionButtonType.archive => ArchiveActionButton(source: context.source, iconOnly: iconOnly, menuItem: menuItem),
ActionButtonType.unarchive => UnArchiveActionButton(
source: context.source,
+105 -4
View File
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'package:drift/drift.dart';
import 'package:flutter/material.dart';
@@ -12,7 +13,7 @@ import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/infrastructure/entities/metadata.entity.drift.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
import 'package:immich_mobile/services/api.service.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
const int targetVersion = 26;
@@ -37,12 +38,35 @@ Future<void> _migrateTo25() async {
return;
}
final serverUrls = ApiService.getServerUrls();
if (serverUrls.isEmpty) {
final urls = <String>[];
final serverEndpoint = Store.tryGet(StoreKey.serverEndpoint);
if (serverEndpoint != null && serverEndpoint.isNotEmpty) {
urls.add(serverEndpoint);
}
final localEndpoint = Store.tryGet(StoreKey.legacyLocalEndpoint);
if (localEndpoint != null && localEndpoint.isNotEmpty) {
urls.add(localEndpoint);
}
final externalJson = Store.tryGet(StoreKey.legacyExternalEndpointList);
if (externalJson != null) {
final List<dynamic> list = jsonDecode(externalJson);
for (final entry in list) {
final url = AuxilaryEndpoint.fromJson(entry).url;
if (url.isNotEmpty) {
urls.add(url);
}
}
}
if (urls.isEmpty) {
return;
}
await NetworkRepository.setHeaders(ApiService.getRequestHeaders(), serverUrls, token: accessToken);
final customHeadersStr = Store.get(StoreKey.legacyCustomHeaders, "");
final headers = customHeadersStr.isEmpty
? const <String, String>{}
: (jsonDecode(customHeadersStr) as Map).cast<String, String>();
await NetworkRepository.setHeaders(headers, urls, token: accessToken);
}
Future<void> _migrateTo26(Drift drift) async {
@@ -96,9 +120,76 @@ Future<void> _migrateTo26(Drift drift) async {
await migrator.migrateBool(StoreKey.legacyLoadOriginalVideo, MetadataKey.viewerLoadOriginalVideo);
await migrator.migrateBool(StoreKey.legacyAutoPlayVideo, MetadataKey.viewerAutoPlayVideo);
await migrator.migrateBool(StoreKey.legacyTapToNavigate, MetadataKey.viewerTapToNavigate);
// Network
await migrator.migrateBool(StoreKey.legacyAutoEndpointSwitching, MetadataKey.networkAutoEndpointSwitching);
await migrator.migrateString(StoreKey.legacyPreferredWifiName, MetadataKey.networkPreferredWifiName);
await migrator.migrateString(StoreKey.legacyLocalEndpoint, MetadataKey.networkLocalEndpoint);
await _migrateExternalEndpointList(drift, migrator);
await _migrateCustomHeaders(drift, migrator);
await migrator.complete();
}
Future<void> _migrateExternalEndpointList(Drift drift, _StoreMigrator migrator) async {
final raw = await migrator.readLegacyStoreString(StoreKey.legacyExternalEndpointList.id);
if (raw == null) {
return;
}
final urls = <String>[];
try {
final decoded = jsonDecode(raw);
if (decoded is List) {
for (final entry in decoded) {
final url = AuxilaryEndpoint.fromJson(entry).url;
if (url.isNotEmpty) {
urls.add(url);
}
}
}
} on FormatException {
// ignore invalid entries
}
await drift.metadataEntity.insertOnConflictUpdate(
MetadataEntityCompanion.insert(
key: MetadataKey.networkExternalEndpointList.key,
value: MetadataKey.networkExternalEndpointList.encode(urls),
updatedAt: Value(DateTime.now()),
),
);
await migrator.deleteLegacyStoreRows([StoreKey.legacyExternalEndpointList.id]);
}
Future<void> _migrateCustomHeaders(Drift drift, _StoreMigrator migrator) async {
final raw = await migrator.readLegacyStoreString(StoreKey.legacyCustomHeaders.id);
if (raw == null) {
return;
}
final headers = <String, String>{};
try {
final decoded = jsonDecode(raw);
if (decoded is Map) {
decoded.forEach((key, value) {
if (key is String && value is String) {
headers[key] = value;
}
});
}
} on FormatException {
// ignore invalid entries
}
await drift.metadataEntity.insertOnConflictUpdate(
MetadataEntityCompanion.insert(
key: MetadataKey.networkCustomHeaders.key,
value: MetadataKey.networkCustomHeaders.encode(headers),
updatedAt: Value(DateTime.now()),
),
);
await migrator.deleteLegacyStoreRows([StoreKey.legacyCustomHeaders.id]);
}
class _StoreMigrator {
final Drift _db;
final Map<MetadataKey<Object>, Object> _cache = {};
@@ -153,6 +244,16 @@ class _StoreMigrator {
_migratedStoreIds.add(legacyKey.id);
}
Future<void> migrateString(StoreKey<String> legacyKey, MetadataKey<String> newKey) async {
final value = await readLegacyStoreString(legacyKey.id);
if (value == null) {
return;
}
_cache[newKey] = value;
_migratedStoreIds.add(legacyKey.id);
}
Future<void> complete() async {
await _db.batch((batch) {
for (final entry in _cache.entries) {
+11
View File
@@ -24,6 +24,17 @@ String? getServerUrl() {
);
}
String? buildSharedLinkUrl({required String? baseUrl, required String key, String? slug}) {
if (baseUrl == null || baseUrl.isEmpty) {
return null;
}
final normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl : '$baseUrl/';
final path = (slug != null && slug.isNotEmpty) ? 's/$slug' : 'share/$key';
return '$normalizedBaseUrl$path';
}
/// Converts a Unicode URL to its ASCII-compatible encoding (Punycode).
///
/// This is especially useful for internationalized domain names (IDNs),
@@ -18,6 +18,7 @@ import 'package:immich_mobile/providers/infrastructure/current_album.provider.da
import 'package:immich_mobile/providers/infrastructure/remote_album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/widgets/album/remote_album_shared_user_icons.dart';
class RemoteAlbumSliverAppBar extends ConsumerStatefulWidget {
@@ -89,6 +90,10 @@ class _MesmerizingSliverAppBarState extends ConsumerState<RemoteAlbumSliverAppBa
onPressed: () => context.maybePop(),
),
actions: [
IconButton(
onPressed: () => context.pushRoute(DriftSlideshowRoute(timeline: ref.read(timelineServiceProvider))),
icon: Icon(Icons.slideshow_outlined, color: actionIconColor, shadows: actionIconShadows),
),
if (currentAlbum.isActivityEnabled && currentAlbum.isShared)
IconButton(
icon: Icon(Icons.chat_outlined, color: actionIconColor, shadows: actionIconShadows),
+113 -6
View File
@@ -8,12 +8,78 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/providers/infrastructure/tag.provider.dart';
import 'package:immich_mobile/widgets/common/search_field.dart';
class TagPicker extends HookConsumerWidget {
const TagPicker({super.key, required this.onSelect, required this.filter});
String _trimSlashes(String s) => s.replaceAll(RegExp(r'^/+|/+$'), '');
Future<(Set<String>, Set<String>)?> showTagPickerModal({required BuildContext context, Set<String>? initialSelection}) {
return showDialog<(Set<String>, Set<String>)?>(
context: context,
builder: (context) => _TagPickerModal(initialSelection: initialSelection),
);
}
class _TagPickerModal extends HookConsumerWidget {
final Set<String>? initialSelection;
const _TagPickerModal({this.initialSelection});
@override
Widget build(BuildContext context, WidgetRef ref) {
final selectedTagIds = useState<Set<String>>(initialSelection ?? {});
final newTagValues = useState<Set<String>>({});
void onSelectExistingTag(Iterable<Tag> tags) {
selectedTagIds.value = tags.map((tag) => tag.id).toSet();
}
void onSelectNewTag(Set<String> tags) {
newTagValues.value = tags;
}
return AlertDialog(
contentPadding: const EdgeInsets.symmetric(vertical: 16, horizontal: 0),
actions: [
TextButton(
onPressed: () => context.pop(),
child: Text(
"cancel",
style: context.textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w600,
color: context.colorScheme.error,
),
).tr(),
),
TextButton(
onPressed: () => context.pop((selectedTagIds.value, newTagValues.value)),
child: Text(
"action_common_update",
style: context.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w600, color: context.primaryColor),
).tr(),
),
],
content: SizedBox(
width: MediaQuery.of(context).size.width * 0.8,
height: MediaQuery.of(context).size.height * 0.6,
child: TagPicker(
onSelectExistingTag: onSelectExistingTag,
filter: selectedTagIds.value,
onSelectNewTag: onSelectNewTag,
),
),
);
}
}
class TagPicker extends HookConsumerWidget {
const TagPicker({super.key, required this.onSelectExistingTag, required this.filter, this.onSelectNewTag});
final Function(Iterable<Tag>) onSelect;
final Set<String> filter;
/// Callback when existing tags are selected/deselected.
final Function(Iterable<Tag>) onSelectExistingTag;
/// If not null, shows a tile to create a new tag with user's filter input.
final Function(Set<String>)? onSelectNewTag;
@override
Widget build(BuildContext context, WidgetRef ref) {
final formFocus = useFocusNode();
@@ -21,6 +87,7 @@ class TagPicker extends HookConsumerWidget {
final tags = ref.watch(tagProvider);
final selectedTagIds = useState<Set<String>>(filter);
final borderRadius = const BorderRadius.all(Radius.circular(10));
final selectedNewTagValues = useState<Set<String>>({});
return Column(
children: [
@@ -41,13 +108,53 @@ class TagPicker extends HookConsumerWidget {
Expanded(
child: tags.widgetWhen(
onData: (tags) {
final trimmedQuery = _trimSlashes(searchQuery.value);
final queryResult = tags
.where((t) => t.value.toLowerCase().contains(searchQuery.value.toLowerCase()))
.where((t) => t.value.toLowerCase().contains(trimmedQuery.toLowerCase()))
.toList();
final showCreateTile =
(onSelectNewTag != null) &&
trimmedQuery.isNotEmpty &&
!tags.any((t) => t.value.toLowerCase() == trimmedQuery.toLowerCase());
final isCreateSelected = selectedNewTagValues.value.contains(trimmedQuery);
return ListView.builder(
itemCount: queryResult.length,
itemCount: queryResult.length + (showCreateTile ? 1 : 0),
padding: const EdgeInsets.all(8),
itemBuilder: (context, index) {
if (showCreateTile && index == queryResult.length) {
// Create new tag tile
return Padding(
padding: const EdgeInsets.only(bottom: 2.0),
child: Container(
decoration: BoxDecoration(
color: isCreateSelected ? context.primaryColor : context.primaryColor.withAlpha(25),
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
child: ListTile(
title: Text(
trimmedQuery,
style: context.textTheme.bodyLarge?.copyWith(
color: isCreateSelected ? context.colorScheme.onPrimary : context.colorScheme.onSurface,
),
),
trailing: Icon(
Icons.add,
color: isCreateSelected ? context.colorScheme.onPrimary : context.colorScheme.onSurface,
),
onTap: () {
final newSelectedNewTagValues = {...selectedNewTagValues.value};
if (isCreateSelected) {
newSelectedNewTagValues.remove(trimmedQuery);
} else {
newSelectedNewTagValues.add(trimmedQuery);
}
selectedNewTagValues.value = newSelectedNewTagValues;
onSelectNewTag!.call(newSelectedNewTagValues);
},
),
),
);
}
final tag = queryResult[index];
final isSelected = selectedTagIds.value.any((id) => id == tag.id);
@@ -73,7 +180,7 @@ class TagPicker extends HookConsumerWidget {
newSelected.add(tag.id);
}
selectedTagIds.value = newSelected;
onSelect(tags.where((t) => newSelected.contains(t.id)));
onSelectExistingTag(tags.where((t) => newSelected.contains(t.id)));
},
),
),
+10 -13
View File
@@ -397,19 +397,16 @@ class LoginForm extends HookConsumerWidget {
mainAxisSize: MainAxisSize.max,
children: [
ImmichForm(
onSubmit: getServerAuthSettings,
submitText: 'next'.t(context: context),
submitIcon: Icons.arrow_forward_rounded,
onSubmit: getServerAuthSettings,
child: ImmichTextInput(
builder: (_, form) => ImmichURLInput(
controller: serverEndpointController,
label: 'login_form_endpoint_url'.t(context: context),
hintText: 'login_form_endpoint_hint'.t(context: context),
validator: _validateUrl,
keyboardAction: TextInputAction.next,
keyboardType: TextInputType.url,
autofillHints: const [AutofillHints.url],
autoCorrect: false,
onSubmit: (ctx, _) => ImmichForm.of(ctx).submit(),
keyboardAction: .next,
onSubmit: (_) => form.submit(),
),
),
ImmichTextButton(
@@ -437,10 +434,10 @@ class LoginForm extends HookConsumerWidget {
),
if (isPasswordLoginEnable.value)
ImmichForm(
onSubmit: login,
submitText: 'login'.t(context: context),
submitIcon: Icons.login_rounded,
onSubmit: login,
child: Column(
builder: (context, form) => Column(
spacing: ImmichSpacing.md,
children: [
ImmichTextInput(
@@ -451,7 +448,7 @@ class LoginForm extends HookConsumerWidget {
keyboardAction: TextInputAction.next,
keyboardType: TextInputType.emailAddress,
autofillHints: const [AutofillHints.email],
onSubmit: (_, _) => passwordFocusNode.requestFocus(),
onSubmit: (_) => passwordFocusNode.requestFocus(),
),
ImmichPasswordInput(
controller: passwordController,
@@ -459,17 +456,17 @@ class LoginForm extends HookConsumerWidget {
label: 'password'.t(context: context),
hintText: 'login_form_password_hint'.t(context: context),
keyboardAction: TextInputAction.go,
onSubmit: (ctx, _) => ImmichForm.of(ctx).submit(),
onSubmit: (_) => form.submit(),
),
],
),
),
if (isOauthEnable.value)
ImmichForm(
onSubmit: oAuthLogin,
submitText: oAuthButtonLabel.value,
submitIcon: Icons.pin_outlined,
onSubmit: oAuthLogin,
child: isPasswordLoginEnable.value
builder: (context, _) => isPasswordLoginEnable.value
? Padding(
padding: const EdgeInsets.only(left: 18.0, right: 18.0, top: 12.0),
child: Divider(color: context.isDarkTheme ? Colors.white : Colors.black, height: 5),
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:immich_mobile/widgets/settings/asset_viewer_settings/image_viewer_quality_setting.dart';
import 'package:immich_mobile/widgets/settings/asset_viewer_settings/image_viewer_tap_to_navigate_setting.dart';
import 'package:immich_mobile/widgets/settings/asset_viewer_settings/video_viewer_settings.dart';
import 'package:immich_mobile/widgets/settings/asset_viewer_settings/slideshow_settings.dart';
import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart';
class AssetViewerSettings extends StatelessWidget {
@@ -13,6 +14,7 @@ class AssetViewerSettings extends StatelessWidget {
const ImageViewerQualitySetting(),
const ImageViewerTapToNavigateSetting(),
const VideoViewerSettings(),
const SlideshowSettings(),
];
return SettingsSubPageScaffold(settings: assetViewerSetting, showDivider: true);
@@ -0,0 +1,123 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
import 'package:immich_mobile/widgets/settings/setting_group_title.dart';
import 'package:immich_mobile/widgets/settings/settings_radio_list_tile.dart';
import 'package:immich_mobile/widgets/settings/settings_slider_list_tile.dart';
import 'package:immich_mobile/widgets/settings/settings_sub_title.dart';
import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart';
class SlideshowSettings extends HookConsumerWidget {
const SlideshowSettings({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final slideshow = ref.read(appConfigProvider).slideshow;
final useTransition = useState(slideshow.transition);
final useRepeat = useState(slideshow.repeat);
final useDuration = useState(slideshow.duration);
final useLook = useState(slideshow.look);
final useDirection = useState(slideshow.direction);
useValueChanged<bool, void>(useTransition.value, (_, __) {
ref.read(metadataProvider).write(.slideshowTransition, useTransition.value);
});
useValueChanged<bool, void>(useRepeat.value, (_, __) {
ref.read(metadataProvider).write(.slideshowRepeat, useRepeat.value);
});
useValueChanged<int, void>(useDuration.value, (_, __) {
ref.read(metadataProvider).write(.slideshowDuration, useDuration.value);
});
useValueChanged<SlideshowLook, void>(useLook.value, (_, __) {
ref.read(metadataProvider).write(.slideshowLook, useLook.value);
});
useValueChanged<SlideshowDirection, void>(useDirection.value, (_, __) {
ref.read(metadataProvider).write(.slideshowDirection, useDirection.value);
});
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SettingGroupTitle(
title: 'slideshow'.t(context: context),
icon: Icons.slideshow_outlined,
),
SettingsSwitchListTile(
valueNotifier: useTransition,
title: "show_slideshow_transition".t(context: context),
enabled: useDirection.value != SlideshowDirection.shuffle,
),
SettingsSwitchListTile(
valueNotifier: useRepeat,
title: "slideshow_repeat".t(context: context),
subtitle: "slideshow_repeat_description".t(context: context),
),
SettingsSliderListTile(
valueNotifier: useDuration,
text: "duration".t(context: context),
minValue: 5,
noDivisons: 5,
maxValue: 30,
),
Padding(
padding: const EdgeInsets.only(top: 20),
child: SettingsSubTitle(title: 'look'.t(context: context)),
),
SettingsRadioListTile(
groups: [
SettingsRadioGroup(
title: 'contain'.t(context: context),
value: SlideshowLook.contain,
),
SettingsRadioGroup(
title: 'cover'.t(context: context),
value: SlideshowLook.cover,
),
SettingsRadioGroup(
title: 'blurred_background'.t(context: context),
value: SlideshowLook.blurredBackground,
),
],
groupBy: useLook.value,
onRadioChanged: (value) {
if (value != null) {
useLook.value = value;
}
},
),
Padding(
padding: const EdgeInsets.only(top: 20),
child: SettingsSubTitle(title: 'direction'.t(context: context)),
),
Padding(
padding: const EdgeInsets.only(bottom: 32),
child: SettingsRadioListTile(
groups: [
SettingsRadioGroup(
title: 'forward'.t(context: context),
value: SlideshowDirection.forward,
),
SettingsRadioGroup(
title: 'backward'.t(context: context),
value: SlideshowDirection.backward,
),
SettingsRadioGroup(
title: 'shuffle'.t(context: context),
value: SlideshowDirection.shuffle,
),
],
groupBy: useDirection.value,
onRadioChanged: (value) {
if (value != null) {
useDirection.value = value;
}
},
),
),
],
);
}
}
@@ -1,10 +1,10 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/providers/auth.provider.dart';
import 'package:immich_mobile/widgets/settings/networking_settings/networking_settings.dart';
import 'package:immich_ui/immich_ui.dart';
class EndpointInput extends StatefulHookConsumerWidget {
const EndpointInput({
@@ -111,28 +111,12 @@ class EndpointInputState extends ConsumerState<EndpointInput> {
status: auxCheckStatus,
enabled: widget.enabled,
),
subtitle: TextFormField(
subtitle: ImmichURLInput(
enabled: widget.enabled,
onTapOutside: (_) => focusNode.unfocus(),
autovalidateMode: AutovalidateMode.onUserInteraction,
autovalidateMode: .onUserInteraction,
validator: validateUrl,
keyboardType: TextInputType.url,
style: const TextStyle(fontFamily: 'GoogleSansCode', fontSize: 14),
decoration: InputDecoration(
hintText: 'http(s)://immich.domain.com',
contentPadding: const EdgeInsets.all(16),
filled: true,
fillColor: context.colorScheme.surfaceContainer,
border: const OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(16))),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red[300]!),
borderRadius: const BorderRadius.all(Radius.circular(16)),
),
disabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: context.isDarkTheme ? Colors.grey[900]! : Colors.grey[300]!),
borderRadius: const BorderRadius.all(Radius.circular(16)),
),
),
keyboardAction: .next,
hintText: 'http(s)://immich.domain.com',
controller: controller,
focusNode: focusNode,
),
@@ -1,13 +1,11 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/domain/models/metadata_key.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
import 'package:immich_mobile/widgets/settings/networking_settings/endpoint_input.dart';
class ExternalNetworkPreference extends HookConsumerWidget {
@@ -23,11 +21,12 @@ class ExternalNetworkPreference extends HookConsumerWidget {
saveEndpointList() {
canSave.value = entries.value.every((e) => e.status == AuxCheckStatus.valid);
final endpointList = entries.value.where((url) => url.status == AuxCheckStatus.valid).toList();
final urls = entries.value
.where((e) => e.status == AuxCheckStatus.valid && e.url.isNotEmpty)
.map((e) => e.url)
.toList();
final jsonString = jsonEncode(endpointList);
Store.put(StoreKey.externalEndpointList, jsonString);
ref.read(metadataProvider).write(MetadataKey.networkExternalEndpointList, urls);
}
updateValidationStatus(String url, int index, AuxCheckStatus status) {
@@ -69,14 +68,13 @@ class ExternalNetworkPreference extends HookConsumerWidget {
}
useEffect(() {
final jsonString = Store.tryGet(StoreKey.externalEndpointList);
final urls = ref.read(metadataProvider).systemConfig.network.externalEndpointList;
if (jsonString == null) {
if (urls.isEmpty) {
return null;
}
final List<dynamic> jsonList = jsonDecode(jsonString);
entries.value = jsonList.map((e) => AuxilaryEndpoint.fromJson(e)).toList();
entries.value = urls.map((url) => AuxilaryEndpoint(url: url, status: .valid)).toList();
return null;
}, const []);
@@ -8,24 +8,29 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/providers/auth.provider.dart';
import 'package:immich_mobile/providers/network.provider.dart';
import 'package:immich_ui/immich_ui.dart';
class LocalNetworkPreference extends HookConsumerWidget {
const LocalNetworkPreference({super.key, required this.enabled});
final bool enabled;
Future<String?> _showEditDialog(BuildContext context, String title, String hintText, String initialValue) {
Future<String?> _showEditDialog(
BuildContext context,
String title,
String hintText,
String initialValue, {
bool isUrlField = false,
}) {
final controller = TextEditingController(text: initialValue);
return showDialog<String>(
context: context,
builder: (context) => AlertDialog(
title: Text(title),
content: TextField(
controller: controller,
autofocus: true,
decoration: InputDecoration(border: const OutlineInputBorder(), hintText: hintText),
),
content: isUrlField
? ImmichURLInput(controller: controller, autofocus: true, keyboardAction: .done, hintText: hintText)
: ImmichTextInput(controller: controller, autofocus: true, keyboardAction: .done, hintText: hintText),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
@@ -81,6 +86,7 @@ class LocalNetworkPreference extends HookConsumerWidget {
"server_endpoint".tr(),
"http://local-ip:2283",
localEndpointText.value,
isUrlField: true,
);
if (localEndpoint != null) {
@@ -1,13 +1,12 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
import 'package:immich_mobile/providers/network.provider.dart';
import 'package:immich_mobile/services/app_settings.service.dart';
import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart';
import 'package:immich_mobile/utils/url_helper.dart';
import 'package:immich_mobile/widgets/settings/networking_settings/external_network_preference.dart';
import 'package:immich_mobile/widgets/settings/networking_settings/local_network_preference.dart';
@@ -20,7 +19,10 @@ class NetworkingSettings extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final currentEndpoint = getServerUrl();
final featureEnabled = useAppSettingsState(AppSettingsEnum.autoEndpointSwitching);
final featureEnabled = useState(ref.read(systemConfigProvider).network.autoEndpointSwitching);
useValueChanged<bool, void>(featureEnabled.value, (_, __) {
ref.read(metadataProvider).write(.networkAutoEndpointSwitching, featureEnabled.value);
});
Future<void> checkWifiReadPermission() async {
final [hasLocationInUse, hasLocationAlways] = await Future.wait([
@@ -1,201 +1,140 @@
import 'dart:math' as math;
import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/models/shared_link/shared_link.model.dart';
import 'package:immich_mobile/providers/server_info.provider.dart';
import 'package:immich_mobile/providers/shared_link.provider.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/utils/debug_print.dart';
import 'package:immich_mobile/utils/image_url_builder.dart';
import 'package:immich_mobile/utils/url_helper.dart';
import 'package:immich_mobile/widgets/common/confirm_dialog.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
import 'package:immich_mobile/widgets/search/thumbnail_with_info.dart';
import 'package:immich_mobile/utils/debug_print.dart';
class SharedLinkItem extends ConsumerWidget {
final SharedLink sharedLink;
const SharedLinkItem(this.sharedLink, {super.key});
bool isExpired() {
if (sharedLink.expiresAt != null) {
return DateTime.now().isAfter(sharedLink.expiresAt!);
}
return false;
}
bool isExpired() => sharedLink.expiresAt?.isBefore(DateTime.now()) ?? false;
Widget buildExpiryDuration(BuildContext context) {
var expiresText = context.t.shared_link_expires_never;
IconData expiryIcon = Icons.schedule;
Widget getExpiryDuration(bool isDarkMode) {
var expiresText = "shared_link_expires_never".tr();
if (sharedLink.expiresAt != null) {
if (isExpired()) {
return Text("expired", style: TextStyle(color: Colors.red[300])).tr();
expiresText = context.t.expired;
expiryIcon = Icons.timer_off_outlined;
}
final difference = sharedLink.expiresAt!.difference(DateTime.now());
dPrint(() => "Difference: $difference");
if (difference.inDays > 0) {
var dayDifference = difference.inDays;
if (difference.inHours % 24 > 12) {
dayDifference += 1;
}
expiresText = "shared_link_expires_days".tr(namedArgs: {'count': dayDifference.toString()});
expiresText = context.t.shared_link_expires_days(count: dayDifference);
} else if (difference.inHours > 0) {
expiresText = "shared_link_expires_hours".tr(namedArgs: {'count': difference.inHours.toString()});
expiresText = context.t.shared_link_expires_hours(count: difference.inHours);
} else if (difference.inMinutes > 0) {
expiresText = "shared_link_expires_minutes".tr(namedArgs: {'count': difference.inMinutes.toString()});
expiresText = context.t.shared_link_expires_minutes(count: difference.inMinutes);
} else if (difference.inSeconds > 0) {
expiresText = "shared_link_expires_seconds".tr(namedArgs: {'count': difference.inSeconds.toString()});
expiresText = context.t.shared_link_expires_seconds(count: difference.inSeconds);
}
}
return Text(expiresText, style: TextStyle(color: isDarkMode ? Colors.grey[400] : Colors.grey[600]));
return Row(
children: [
Icon(expiryIcon, size: 12, color: isExpired() ? context.colorScheme.error : context.colorScheme.onSurface),
const SizedBox(width: 4),
Text(
expiresText,
style: TextStyle(color: isExpired() ? context.colorScheme.error : context.colorScheme.onSurface),
),
],
);
}
@override
Widget build(BuildContext context, WidgetRef ref) {
final colorScheme = context.colorScheme;
final isDarkMode = colorScheme.brightness == Brightness.dark;
final thumbnailUrl = sharedLink.thumbAssetId != null ? getThumbnailUrlForRemoteId(sharedLink.thumbAssetId!) : null;
final imageSize = math.min(context.width / 4, 100.0);
void copyShareLinkToClipboard() {
Future<void> copyShareLinkToClipboard() async {
final externalDomain = ref.read(serverInfoProvider.select((s) => s.serverConfig.externalDomain));
var serverUrl = externalDomain.isNotEmpty ? externalDomain : getServerUrl();
if (serverUrl != null && !serverUrl.endsWith('/')) {
serverUrl += '/';
}
if (serverUrl == null) {
final serverUrl = externalDomain.isNotEmpty ? externalDomain : getServerUrl();
final shareUrl = buildSharedLinkUrl(baseUrl: serverUrl, slug: sharedLink.slug, key: sharedLink.key);
if (shareUrl == null) {
ImmichToast.show(
context: context,
gravity: ToastGravity.BOTTOM,
toastType: ToastType.error,
msg: "shared_link_error_server_url_fetch".tr(),
msg: context.t.shared_link_error_server_url_fetch,
);
return;
}
final hasSlug = sharedLink.slug?.isNotEmpty == true;
final urlPath = hasSlug ? sharedLink.slug : sharedLink.key;
final basePath = hasSlug ? 's' : 'share';
Clipboard.setData(ClipboardData(text: "$serverUrl$basePath/$urlPath")).then((_) {
context.scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(
"shared_link_clipboard_copied_massage",
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
).tr(),
duration: const Duration(seconds: 2),
await Clipboard.setData(ClipboardData(text: shareUrl));
if (!context.mounted) {
return;
}
context.scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(
context.t.shared_link_clipboard_copied_massage,
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
),
);
});
}
Future<void> deleteShareLink() async {
return showDialog(
context: context,
builder: (BuildContext context) {
return ConfirmDialog(
title: "delete_shared_link_dialog_title",
content: "confirm_delete_shared_link",
onOk: () => ref.read(sharedLinksStateProvider.notifier).deleteLink(sharedLink.id),
);
},
duration: const Duration(seconds: 2),
),
);
}
Widget buildThumbnail() {
if (thumbnailUrl == null) {
return Container(
height: imageSize * 1.2,
width: imageSize,
decoration: BoxDecoration(color: isDarkMode ? Colors.grey[800] : Colors.grey[200]),
child: Center(
child: Icon(Icons.image_not_supported_outlined, color: isDarkMode ? Colors.grey[100] : Colors.grey[700]),
),
);
}
return SizedBox(
height: imageSize * 1.2,
width: imageSize,
child: Padding(
padding: const EdgeInsets.only(right: 4.0),
child: ThumbnailWithInfo(
imageUrl: thumbnailUrl,
key: key,
textInfo: '',
noImageIcon: Icons.image_not_supported_outlined,
onTap: () {},
),
),
child: thumbnailUrl == null
? const Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
child: Icon(Icons.image_not_supported_outlined),
)
: ThumbnailWithInfo(
imageUrl: thumbnailUrl,
key: key,
textInfo: '',
noImageIcon: Icons.image_not_supported_outlined,
onTap: () => context.pushRoute(SharedLinkEditRoute(existingLink: sharedLink)),
),
);
}
Widget buildInfoChip(String labelText) {
return Padding(
padding: const EdgeInsets.only(right: 10),
child: Chip(
backgroundColor: colorScheme.primary,
label: Text(
labelText,
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.black : Colors.white,
),
),
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(25))),
return Card.outlined(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
child: Text(labelText, style: const TextStyle(fontSize: 11)),
),
);
}
Widget buildBottomInfo() {
Widget buildShareParameterInfos() {
return Row(
spacing: 4,
children: [
if (sharedLink.allowUpload) buildInfoChip("upload".tr()),
if (sharedLink.allowDownload) buildInfoChip("download".tr()),
if (sharedLink.showMetadata) buildInfoChip("shared_link_info_chip_metadata".tr()),
],
);
}
Widget buildSharedLinkActions() {
const actionIconSize = 20.0;
return Row(
children: [
IconButton(
splashRadius: 25,
constraints: const BoxConstraints(),
iconSize: actionIconSize,
icon: const Icon(Icons.delete_outline),
style: const ButtonStyle(
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // the '2023' part
),
onPressed: deleteShareLink,
),
IconButton(
splashRadius: 25,
constraints: const BoxConstraints(),
iconSize: actionIconSize,
icon: const Icon(Icons.edit_outlined),
style: const ButtonStyle(
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // the '2023' part
),
onPressed: () => context.pushRoute(SharedLinkEditRoute(existingLink: sharedLink)),
),
IconButton(
splashRadius: 25,
constraints: const BoxConstraints(),
iconSize: actionIconSize,
icon: const Icon(Icons.copy_outlined),
style: const ButtonStyle(
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // the '2023' part
),
onPressed: copyShareLinkToClipboard,
),
if (sharedLink.allowUpload) buildInfoChip(context.t.upload),
if (sharedLink.allowDownload) buildInfoChip(context.t.download),
if (sharedLink.showMetadata) buildInfoChip(context.t.shared_link_info_chip_metadata),
],
);
}
@@ -204,69 +143,64 @@ class SharedLinkItem extends ConsumerWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
getExpiryDuration(isDarkMode),
Padding(
padding: const EdgeInsets.only(top: 5),
child: Tooltip(
verticalOffset: 0,
decoration: BoxDecoration(
color: colorScheme.primary.withValues(alpha: 0.9),
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
textStyle: TextStyle(color: isDarkMode ? Colors.black : Colors.white, fontWeight: FontWeight.bold),
message: sharedLink.title,
preferBelow: false,
triggerMode: TooltipTriggerMode.tap,
child: Text(
sharedLink.title,
style: TextStyle(
color: colorScheme.primary,
fontWeight: FontWeight.bold,
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(height: 5),
Text(
sharedLink.title,
style: TextStyle(
color: Theme.of(context).colorScheme.primary,
fontWeight: FontWeight.bold,
overflow: TextOverflow.ellipsis,
),
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Tooltip(
verticalOffset: 0,
decoration: BoxDecoration(
color: colorScheme.primary.withValues(alpha: 0.9),
borderRadius: const BorderRadius.all(Radius.circular(10)),
),
textStyle: TextStyle(color: isDarkMode ? Colors.black : Colors.white, fontWeight: FontWeight.bold),
message: sharedLink.description ?? "",
preferBelow: false,
triggerMode: TooltipTriggerMode.tap,
child: Text(sharedLink.description ?? "", overflow: TextOverflow.ellipsis),
),
),
Padding(padding: const EdgeInsets.only(right: 15), child: buildSharedLinkActions()),
],
),
buildBottomInfo(),
if (sharedLink.description?.isNotEmpty ?? false)
Text(sharedLink.description!, overflow: TextOverflow.ellipsis),
buildExpiryDuration(context),
buildShareParameterInfos(),
],
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(padding: const EdgeInsets.only(left: 15), child: buildThumbnail()),
Expanded(
child: Padding(padding: const EdgeInsets.only(left: 15), child: buildSharedLinkDetails()),
),
],
return Dismissible(
key: ValueKey(sharedLink.id),
direction: DismissDirection.endToStart,
background: Container(
color: Theme.of(context).colorScheme.error,
alignment: Alignment.centerRight,
padding: const EdgeInsets.only(right: 20),
child: Icon(Icons.delete, color: Theme.of(context).colorScheme.onError),
),
confirmDismiss: (_) async {
final confirmed = await showDialog<bool>(
context: context,
builder: (BuildContext context) => ConfirmDialog(
title: "delete_shared_link_dialog_title",
content: "confirm_delete_shared_link",
onOk: () {},
),
);
if (confirmed == true) {
await ref.read(sharedLinksStateProvider.notifier).deleteLink(sharedLink.id);
return true;
}
return false;
},
child: InkWell(
onTap: () => context.pushRoute(SharedLinkEditRoute(existingLink: sharedLink)),
onLongPress: copyShareLinkToClipboard,
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildThumbnail(),
const SizedBox(width: 12),
Expanded(child: buildSharedLinkDetails()),
],
),
),
const Padding(padding: EdgeInsets.all(20), child: Divider(height: 0)),
],
),
);
}
}
-8
View File
@@ -1,11 +1,3 @@
[tools]
flutter = "3.41.9"
[tools."github:CQLabs/homebrew-dcm"]
version = "1.30.0"
bin = "dcm"
postinstall = "chmod +x $MISE_TOOL_INSTALL_PATH/dcm"
[tasks."codegen:dart"]
alias = "codegen"
description = "Execute build_runner to auto-generate dart code"
+12 -16
View File
@@ -205,8 +205,8 @@ Class | Method | HTTP request | Description
*PeopleApi* | [**updatePeople**](doc//PeopleApi.md#updatepeople) | **PUT** /people | Update people
*PeopleApi* | [**updatePerson**](doc//PeopleApi.md#updateperson) | **PUT** /people/{id} | Update person
*PluginsApi* | [**getPlugin**](doc//PluginsApi.md#getplugin) | **GET** /plugins/{id} | Retrieve a plugin
*PluginsApi* | [**getPluginTriggers**](doc//PluginsApi.md#getplugintriggers) | **GET** /plugins/triggers | List all plugin triggers
*PluginsApi* | [**getPlugins**](doc//PluginsApi.md#getplugins) | **GET** /plugins | List all plugins
*PluginsApi* | [**searchPluginMethods**](doc//PluginsApi.md#searchpluginmethods) | **GET** /plugins/methods | Retrieve plugin methods
*PluginsApi* | [**searchPlugins**](doc//PluginsApi.md#searchplugins) | **GET** /plugins | List all plugins
*QueuesApi* | [**emptyQueue**](doc//QueuesApi.md#emptyqueue) | **DELETE** /queues/{name}/jobs | Empty a queue
*QueuesApi* | [**getQueue**](doc//QueuesApi.md#getqueue) | **GET** /queues/{name} | Retrieve a queue
*QueuesApi* | [**getQueueJobs**](doc//QueuesApi.md#getqueuejobs) | **GET** /queues/{name}/jobs | Retrieve queue jobs
@@ -314,7 +314,9 @@ Class | Method | HTTP request | Description
*WorkflowsApi* | [**createWorkflow**](doc//WorkflowsApi.md#createworkflow) | **POST** /workflows | Create a workflow
*WorkflowsApi* | [**deleteWorkflow**](doc//WorkflowsApi.md#deleteworkflow) | **DELETE** /workflows/{id} | Delete a workflow
*WorkflowsApi* | [**getWorkflow**](doc//WorkflowsApi.md#getworkflow) | **GET** /workflows/{id} | Retrieve a workflow
*WorkflowsApi* | [**getWorkflows**](doc//WorkflowsApi.md#getworkflows) | **GET** /workflows | List all workflows
*WorkflowsApi* | [**getWorkflowForShare**](doc//WorkflowsApi.md#getworkflowforshare) | **GET** /workflows/{id}/share | Retrieve a workflow
*WorkflowsApi* | [**getWorkflowTriggers**](doc//WorkflowsApi.md#getworkflowtriggers) | **GET** /workflows/triggers | List all workflow triggers
*WorkflowsApi* | [**searchWorkflows**](doc//WorkflowsApi.md#searchworkflows) | **GET** /workflows | List all workflows
*WorkflowsApi* | [**updateWorkflow**](doc//WorkflowsApi.md#updateworkflow) | **PUT** /workflows/{id} | Update a workflow
@@ -487,16 +489,8 @@ Class | Method | HTTP request | Description
- [PinCodeResetDto](doc//PinCodeResetDto.md)
- [PinCodeSetupDto](doc//PinCodeSetupDto.md)
- [PlacesResponseDto](doc//PlacesResponseDto.md)
- [PluginActionResponseDto](doc//PluginActionResponseDto.md)
- [PluginContextType](doc//PluginContextType.md)
- [PluginFilterResponseDto](doc//PluginFilterResponseDto.md)
- [PluginJsonSchema](doc//PluginJsonSchema.md)
- [PluginJsonSchemaProperty](doc//PluginJsonSchemaProperty.md)
- [PluginJsonSchemaPropertyAdditionalProperties](doc//PluginJsonSchemaPropertyAdditionalProperties.md)
- [PluginJsonSchemaType](doc//PluginJsonSchemaType.md)
- [PluginMethodResponseDto](doc//PluginMethodResponseDto.md)
- [PluginResponseDto](doc//PluginResponseDto.md)
- [PluginTriggerResponseDto](doc//PluginTriggerResponseDto.md)
- [PluginTriggerType](doc//PluginTriggerType.md)
- [PurchaseResponse](doc//PurchaseResponse.md)
- [PurchaseUpdate](doc//PurchaseUpdate.md)
- [QueueCommand](doc//QueueCommand.md)
@@ -669,12 +663,14 @@ Class | Method | HTTP request | Description
- [VersionCheckStateResponseDto](doc//VersionCheckStateResponseDto.md)
- [VideoCodec](doc//VideoCodec.md)
- [VideoContainer](doc//VideoContainer.md)
- [WorkflowActionItemDto](doc//WorkflowActionItemDto.md)
- [WorkflowActionResponseDto](doc//WorkflowActionResponseDto.md)
- [WorkflowCreateDto](doc//WorkflowCreateDto.md)
- [WorkflowFilterItemDto](doc//WorkflowFilterItemDto.md)
- [WorkflowFilterResponseDto](doc//WorkflowFilterResponseDto.md)
- [WorkflowResponseDto](doc//WorkflowResponseDto.md)
- [WorkflowShareResponseDto](doc//WorkflowShareResponseDto.md)
- [WorkflowShareStepDto](doc//WorkflowShareStepDto.md)
- [WorkflowStepDto](doc//WorkflowStepDto.md)
- [WorkflowTrigger](doc//WorkflowTrigger.md)
- [WorkflowTriggerResponseDto](doc//WorkflowTriggerResponseDto.md)
- [WorkflowType](doc//WorkflowType.md)
- [WorkflowUpdateDto](doc//WorkflowUpdateDto.md)
+7 -13
View File
@@ -235,16 +235,8 @@ part 'model/pin_code_change_dto.dart';
part 'model/pin_code_reset_dto.dart';
part 'model/pin_code_setup_dto.dart';
part 'model/places_response_dto.dart';
part 'model/plugin_action_response_dto.dart';
part 'model/plugin_context_type.dart';
part 'model/plugin_filter_response_dto.dart';
part 'model/plugin_json_schema.dart';
part 'model/plugin_json_schema_property.dart';
part 'model/plugin_json_schema_property_additional_properties.dart';
part 'model/plugin_json_schema_type.dart';
part 'model/plugin_method_response_dto.dart';
part 'model/plugin_response_dto.dart';
part 'model/plugin_trigger_response_dto.dart';
part 'model/plugin_trigger_type.dart';
part 'model/purchase_response.dart';
part 'model/purchase_update.dart';
part 'model/queue_command.dart';
@@ -417,12 +409,14 @@ part 'model/validate_library_response_dto.dart';
part 'model/version_check_state_response_dto.dart';
part 'model/video_codec.dart';
part 'model/video_container.dart';
part 'model/workflow_action_item_dto.dart';
part 'model/workflow_action_response_dto.dart';
part 'model/workflow_create_dto.dart';
part 'model/workflow_filter_item_dto.dart';
part 'model/workflow_filter_response_dto.dart';
part 'model/workflow_response_dto.dart';
part 'model/workflow_share_response_dto.dart';
part 'model/workflow_share_step_dto.dart';
part 'model/workflow_step_dto.dart';
part 'model/workflow_trigger.dart';
part 'model/workflow_trigger_response_dto.dart';
part 'model/workflow_type.dart';
part 'model/workflow_update_dto.dart';
+144 -13
View File
@@ -73,14 +73,40 @@ class PluginsApi {
return null;
}
/// List all plugin triggers
/// Retrieve plugin methods
///
/// Retrieve a list of all available plugin triggers.
/// Retrieve a list of plugin methods
///
/// Note: This method returns the HTTP [Response].
Future<Response> getPluginTriggersWithHttpInfo() async {
///
/// Parameters:
///
/// * [String] description:
///
/// * [bool] enabled:
/// Whether the plugin method is enabled
///
/// * [String] id:
/// Plugin method ID
///
/// * [String] name:
///
/// * [String] pluginName:
/// Plugin name
///
/// * [String] pluginVersion:
/// Plugin version
///
/// * [String] title:
///
/// * [WorkflowTrigger] trigger:
/// Workflow trigger
///
/// * [WorkflowType] type:
/// Workflow types
Future<Response> searchPluginMethodsWithHttpInfo({ String? description, bool? enabled, String? id, String? name, String? pluginName, String? pluginVersion, String? title, WorkflowTrigger? trigger, WorkflowType? type, }) async {
// ignore: prefer_const_declarations
final apiPath = r'/plugins/triggers';
final apiPath = r'/plugins/methods';
// ignore: prefer_final_locals
Object? postBody;
@@ -89,6 +115,34 @@ class PluginsApi {
final headerParams = <String, String>{};
final formParams = <String, String>{};
if (description != null) {
queryParams.addAll(_queryParams('', 'description', description));
}
if (enabled != null) {
queryParams.addAll(_queryParams('', 'enabled', enabled));
}
if (id != null) {
queryParams.addAll(_queryParams('', 'id', id));
}
if (name != null) {
queryParams.addAll(_queryParams('', 'name', name));
}
if (pluginName != null) {
queryParams.addAll(_queryParams('', 'pluginName', pluginName));
}
if (pluginVersion != null) {
queryParams.addAll(_queryParams('', 'pluginVersion', pluginVersion));
}
if (title != null) {
queryParams.addAll(_queryParams('', 'title', title));
}
if (trigger != null) {
queryParams.addAll(_queryParams('', 'trigger', trigger));
}
if (type != null) {
queryParams.addAll(_queryParams('', 'type', type));
}
const contentTypes = <String>[];
@@ -103,11 +157,37 @@ class PluginsApi {
);
}
/// List all plugin triggers
/// Retrieve plugin methods
///
/// Retrieve a list of all available plugin triggers.
Future<List<PluginTriggerResponseDto>?> getPluginTriggers() async {
final response = await getPluginTriggersWithHttpInfo();
/// Retrieve a list of plugin methods
///
/// Parameters:
///
/// * [String] description:
///
/// * [bool] enabled:
/// Whether the plugin method is enabled
///
/// * [String] id:
/// Plugin method ID
///
/// * [String] name:
///
/// * [String] pluginName:
/// Plugin name
///
/// * [String] pluginVersion:
/// Plugin version
///
/// * [String] title:
///
/// * [WorkflowTrigger] trigger:
/// Workflow trigger
///
/// * [WorkflowType] type:
/// Workflow types
Future<List<PluginMethodResponseDto>?> searchPluginMethods({ String? description, bool? enabled, String? id, String? name, String? pluginName, String? pluginVersion, String? title, WorkflowTrigger? trigger, WorkflowType? type, }) async {
final response = await searchPluginMethodsWithHttpInfo( description: description, enabled: enabled, id: id, name: name, pluginName: pluginName, pluginVersion: pluginVersion, title: title, trigger: trigger, type: type, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@@ -116,8 +196,8 @@ class PluginsApi {
// 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<PluginTriggerResponseDto>') as List)
.cast<PluginTriggerResponseDto>()
return (await apiClient.deserializeAsync(responseBody, 'List<PluginMethodResponseDto>') as List)
.cast<PluginMethodResponseDto>()
.toList(growable: false);
}
@@ -129,7 +209,23 @@ class PluginsApi {
/// Retrieve a list of plugins available to the authenticated user.
///
/// Note: This method returns the HTTP [Response].
Future<Response> getPluginsWithHttpInfo() async {
///
/// Parameters:
///
/// * [String] description:
///
/// * [bool] enabled:
/// Whether the plugin is enabled
///
/// * [String] id:
/// Plugin ID
///
/// * [String] name:
///
/// * [String] title:
///
/// * [String] version:
Future<Response> searchPluginsWithHttpInfo({ String? description, bool? enabled, String? id, String? name, String? title, String? version, }) async {
// ignore: prefer_const_declarations
final apiPath = r'/plugins';
@@ -140,6 +236,25 @@ class PluginsApi {
final headerParams = <String, String>{};
final formParams = <String, String>{};
if (description != null) {
queryParams.addAll(_queryParams('', 'description', description));
}
if (enabled != null) {
queryParams.addAll(_queryParams('', 'enabled', enabled));
}
if (id != null) {
queryParams.addAll(_queryParams('', 'id', id));
}
if (name != null) {
queryParams.addAll(_queryParams('', 'name', name));
}
if (title != null) {
queryParams.addAll(_queryParams('', 'title', title));
}
if (version != null) {
queryParams.addAll(_queryParams('', 'version', version));
}
const contentTypes = <String>[];
@@ -157,8 +272,24 @@ class PluginsApi {
/// List all plugins
///
/// Retrieve a list of plugins available to the authenticated user.
Future<List<PluginResponseDto>?> getPlugins() async {
final response = await getPluginsWithHttpInfo();
///
/// Parameters:
///
/// * [String] description:
///
/// * [bool] enabled:
/// Whether the plugin is enabled
///
/// * [String] id:
/// Plugin ID
///
/// * [String] name:
///
/// * [String] title:
///
/// * [String] version:
Future<List<PluginResponseDto>?> searchPlugins({ String? description, bool? enabled, String? id, String? name, String? title, String? version, }) async {
final response = await searchPluginsWithHttpInfo( description: description, enabled: enabled, id: id, name: name, title: title, version: version, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
+164 -6
View File
@@ -178,14 +178,19 @@ class WorkflowsApi {
return null;
}
/// List all workflows
/// Retrieve a workflow
///
/// Retrieve a list of workflows available to the authenticated user.
/// Retrieve a workflow details without ids, default values, etc.
///
/// Note: This method returns the HTTP [Response].
Future<Response> getWorkflowsWithHttpInfo() async {
///
/// Parameters:
///
/// * [String] id (required):
Future<Response> getWorkflowForShareWithHttpInfo(String id,) async {
// ignore: prefer_const_declarations
final apiPath = r'/workflows';
final apiPath = r'/workflows/{id}/share'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
@@ -208,11 +213,164 @@ class WorkflowsApi {
);
}
/// Retrieve a workflow
///
/// Retrieve a workflow details without ids, default values, etc.
///
/// Parameters:
///
/// * [String] id (required):
Future<WorkflowShareResponseDto?> getWorkflowForShare(String id,) async {
final response = await getWorkflowForShareWithHttpInfo(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) {
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'WorkflowShareResponseDto',) as WorkflowShareResponseDto;
}
return null;
}
/// List all workflow triggers
///
/// Retrieve a list of all available workflow triggers.
///
/// Note: This method returns the HTTP [Response].
Future<Response> getWorkflowTriggersWithHttpInfo() async {
// ignore: prefer_const_declarations
final apiPath = r'/workflows/triggers';
// ignore: prefer_final_locals
Object? postBody;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>[];
return apiClient.invokeAPI(
apiPath,
'GET',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// List all workflow triggers
///
/// Retrieve a list of all available workflow triggers.
Future<List<WorkflowTriggerResponseDto>?> getWorkflowTriggers() async {
final response = await getWorkflowTriggersWithHttpInfo();
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<WorkflowTriggerResponseDto>') as List)
.cast<WorkflowTriggerResponseDto>()
.toList(growable: false);
}
return null;
}
/// List all workflows
///
/// Retrieve a list of workflows available to the authenticated user.
Future<List<WorkflowResponseDto>?> getWorkflows() async {
final response = await getWorkflowsWithHttpInfo();
///
/// Note: This method returns the HTTP [Response].
///
/// Parameters:
///
/// * [String] description:
/// Workflow description
///
/// * [bool] enabled:
/// Workflow enabled
///
/// * [String] id:
/// Workflow ID
///
/// * [String] name:
/// Workflow name
///
/// * [WorkflowTrigger] trigger:
/// Workflow trigger type
Future<Response> searchWorkflowsWithHttpInfo({ String? description, bool? enabled, String? id, String? name, WorkflowTrigger? trigger, }) async {
// ignore: prefer_const_declarations
final apiPath = r'/workflows';
// ignore: prefer_final_locals
Object? postBody;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
if (description != null) {
queryParams.addAll(_queryParams('', 'description', description));
}
if (enabled != null) {
queryParams.addAll(_queryParams('', 'enabled', enabled));
}
if (id != null) {
queryParams.addAll(_queryParams('', 'id', id));
}
if (name != null) {
queryParams.addAll(_queryParams('', 'name', name));
}
if (trigger != null) {
queryParams.addAll(_queryParams('', 'trigger', trigger));
}
const contentTypes = <String>[];
return apiClient.invokeAPI(
apiPath,
'GET',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// List all workflows
///
/// Retrieve a list of workflows available to the authenticated user.
///
/// Parameters:
///
/// * [String] description:
/// Workflow description
///
/// * [bool] enabled:
/// Workflow enabled
///
/// * [String] id:
/// Workflow ID
///
/// * [String] name:
/// Workflow name
///
/// * [WorkflowTrigger] trigger:
/// Workflow trigger type
Future<List<WorkflowResponseDto>?> searchWorkflows({ String? description, bool? enabled, String? id, String? name, WorkflowTrigger? trigger, }) async {
final response = await searchWorkflowsWithHttpInfo( description: description, enabled: enabled, id: id, name: name, trigger: trigger, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
+14 -26
View File
@@ -516,26 +516,10 @@ class ApiClient {
return PinCodeSetupDto.fromJson(value);
case 'PlacesResponseDto':
return PlacesResponseDto.fromJson(value);
case 'PluginActionResponseDto':
return PluginActionResponseDto.fromJson(value);
case 'PluginContextType':
return PluginContextTypeTypeTransformer().decode(value);
case 'PluginFilterResponseDto':
return PluginFilterResponseDto.fromJson(value);
case 'PluginJsonSchema':
return PluginJsonSchema.fromJson(value);
case 'PluginJsonSchemaProperty':
return PluginJsonSchemaProperty.fromJson(value);
case 'PluginJsonSchemaPropertyAdditionalProperties':
return PluginJsonSchemaPropertyAdditionalProperties.fromJson(value);
case 'PluginJsonSchemaType':
return PluginJsonSchemaTypeTypeTransformer().decode(value);
case 'PluginMethodResponseDto':
return PluginMethodResponseDto.fromJson(value);
case 'PluginResponseDto':
return PluginResponseDto.fromJson(value);
case 'PluginTriggerResponseDto':
return PluginTriggerResponseDto.fromJson(value);
case 'PluginTriggerType':
return PluginTriggerTypeTypeTransformer().decode(value);
case 'PurchaseResponse':
return PurchaseResponse.fromJson(value);
case 'PurchaseUpdate':
@@ -880,18 +864,22 @@ class ApiClient {
return VideoCodecTypeTransformer().decode(value);
case 'VideoContainer':
return VideoContainerTypeTransformer().decode(value);
case 'WorkflowActionItemDto':
return WorkflowActionItemDto.fromJson(value);
case 'WorkflowActionResponseDto':
return WorkflowActionResponseDto.fromJson(value);
case 'WorkflowCreateDto':
return WorkflowCreateDto.fromJson(value);
case 'WorkflowFilterItemDto':
return WorkflowFilterItemDto.fromJson(value);
case 'WorkflowFilterResponseDto':
return WorkflowFilterResponseDto.fromJson(value);
case 'WorkflowResponseDto':
return WorkflowResponseDto.fromJson(value);
case 'WorkflowShareResponseDto':
return WorkflowShareResponseDto.fromJson(value);
case 'WorkflowShareStepDto':
return WorkflowShareStepDto.fromJson(value);
case 'WorkflowStepDto':
return WorkflowStepDto.fromJson(value);
case 'WorkflowTrigger':
return WorkflowTriggerTypeTransformer().decode(value);
case 'WorkflowTriggerResponseDto':
return WorkflowTriggerResponseDto.fromJson(value);
case 'WorkflowType':
return WorkflowTypeTypeTransformer().decode(value);
case 'WorkflowUpdateDto':
return WorkflowUpdateDto.fromJson(value);
default:
+6 -9
View File
@@ -142,15 +142,6 @@ String parameterToString(dynamic value) {
if (value is Permission) {
return PermissionTypeTransformer().encode(value).toString();
}
if (value is PluginContextType) {
return PluginContextTypeTypeTransformer().encode(value).toString();
}
if (value is PluginJsonSchemaType) {
return PluginJsonSchemaTypeTypeTransformer().encode(value).toString();
}
if (value is PluginTriggerType) {
return PluginTriggerTypeTypeTransformer().encode(value).toString();
}
if (value is QueueCommand) {
return QueueCommandTypeTransformer().encode(value).toString();
}
@@ -208,6 +199,12 @@ String parameterToString(dynamic value) {
if (value is VideoContainer) {
return VideoContainerTypeTransformer().encode(value).toString();
}
if (value is WorkflowTrigger) {
return WorkflowTriggerTypeTransformer().encode(value).toString();
}
if (value is WorkflowType) {
return WorkflowTypeTypeTransformer().encode(value).toString();
}
return value.toString();
}
+3 -3
View File
@@ -77,7 +77,7 @@ class JobName {
static const versionCheck = JobName._(r'VersionCheck');
static const ocrQueueAll = JobName._(r'OcrQueueAll');
static const ocr = JobName._(r'Ocr');
static const workflowRun = JobName._(r'WorkflowRun');
static const workflowAssetCreate = JobName._(r'WorkflowAssetCreate');
/// List of all possible values in this [enum][JobName].
static const values = <JobName>[
@@ -135,7 +135,7 @@ class JobName {
versionCheck,
ocrQueueAll,
ocr,
workflowRun,
workflowAssetCreate,
];
static JobName? fromJson(dynamic value) => JobNameTypeTransformer().decode(value);
@@ -228,7 +228,7 @@ class JobNameTypeTransformer {
case r'VersionCheck': return JobName.versionCheck;
case r'OcrQueueAll': return JobName.ocrQueueAll;
case r'Ocr': return JobName.ocr;
case r'WorkflowRun': return JobName.workflowRun;
case r'WorkflowAssetCreate': return JobName.workflowAssetCreate;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
-158
View File
@@ -1,158 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class PluginActionResponseDto {
/// Returns a new [PluginActionResponseDto] instance.
PluginActionResponseDto({
required this.description,
required this.id,
required this.methodName,
required this.pluginId,
required this.schema,
this.supportedContexts = const [],
required this.title,
});
/// Action description
String description;
/// Action ID
String id;
/// Method name
String methodName;
/// Plugin ID
String pluginId;
/// Action schema
PluginJsonSchema? schema;
/// Supported contexts
List<PluginContextType> supportedContexts;
/// Action title
String title;
@override
bool operator ==(Object other) => identical(this, other) || other is PluginActionResponseDto &&
other.description == description &&
other.id == id &&
other.methodName == methodName &&
other.pluginId == pluginId &&
other.schema == schema &&
_deepEquality.equals(other.supportedContexts, supportedContexts) &&
other.title == title;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(description.hashCode) +
(id.hashCode) +
(methodName.hashCode) +
(pluginId.hashCode) +
(schema == null ? 0 : schema!.hashCode) +
(supportedContexts.hashCode) +
(title.hashCode);
@override
String toString() => 'PluginActionResponseDto[description=$description, id=$id, methodName=$methodName, pluginId=$pluginId, schema=$schema, supportedContexts=$supportedContexts, title=$title]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'description'] = this.description;
json[r'id'] = this.id;
json[r'methodName'] = this.methodName;
json[r'pluginId'] = this.pluginId;
if (this.schema != null) {
json[r'schema'] = this.schema;
} else {
// json[r'schema'] = null;
}
json[r'supportedContexts'] = this.supportedContexts;
json[r'title'] = this.title;
return json;
}
/// Returns a new [PluginActionResponseDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static PluginActionResponseDto? fromJson(dynamic value) {
upgradeDto(value, "PluginActionResponseDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return PluginActionResponseDto(
description: mapValueOfType<String>(json, r'description')!,
id: mapValueOfType<String>(json, r'id')!,
methodName: mapValueOfType<String>(json, r'methodName')!,
pluginId: mapValueOfType<String>(json, r'pluginId')!,
schema: PluginJsonSchema.fromJson(json[r'schema']),
supportedContexts: PluginContextType.listFromJson(json[r'supportedContexts']),
title: mapValueOfType<String>(json, r'title')!,
);
}
return null;
}
static List<PluginActionResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <PluginActionResponseDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = PluginActionResponseDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, PluginActionResponseDto> mapFromJson(dynamic json) {
final map = <String, PluginActionResponseDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = PluginActionResponseDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of PluginActionResponseDto-objects as value to a dart map
static Map<String, List<PluginActionResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<PluginActionResponseDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = PluginActionResponseDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'description',
'id',
'methodName',
'pluginId',
'schema',
'supportedContexts',
'title',
};
}
-88
View File
@@ -1,88 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
/// Plugin context
class PluginContextType {
/// Instantiate a new enum with the provided [value].
const PluginContextType._(this.value);
/// The underlying value of this enum member.
final String value;
@override
String toString() => value;
String toJson() => value;
static const asset = PluginContextType._(r'asset');
static const album = PluginContextType._(r'album');
static const person = PluginContextType._(r'person');
/// List of all possible values in this [enum][PluginContextType].
static const values = <PluginContextType>[
asset,
album,
person,
];
static PluginContextType? fromJson(dynamic value) => PluginContextTypeTypeTransformer().decode(value);
static List<PluginContextType> listFromJson(dynamic json, {bool growable = false,}) {
final result = <PluginContextType>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = PluginContextType.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
}
/// Transformation class that can [encode] an instance of [PluginContextType] to String,
/// and [decode] dynamic data back to [PluginContextType].
class PluginContextTypeTypeTransformer {
factory PluginContextTypeTypeTransformer() => _instance ??= const PluginContextTypeTypeTransformer._();
const PluginContextTypeTypeTransformer._();
String encode(PluginContextType data) => data.value;
/// Decodes a [dynamic value][data] to a PluginContextType.
///
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
///
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
/// and users are still using an old app with the old code.
PluginContextType? decode(dynamic data, {bool allowNull = true}) {
if (data != null) {
switch (data) {
case r'asset': return PluginContextType.asset;
case r'album': return PluginContextType.album;
case r'person': return PluginContextType.person;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
}
}
}
return null;
}
/// Singleton [PluginContextTypeTypeTransformer] instance.
static PluginContextTypeTypeTransformer? _instance;
}
-158
View File
@@ -1,158 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class PluginFilterResponseDto {
/// Returns a new [PluginFilterResponseDto] instance.
PluginFilterResponseDto({
required this.description,
required this.id,
required this.methodName,
required this.pluginId,
required this.schema,
this.supportedContexts = const [],
required this.title,
});
/// Filter description
String description;
/// Filter ID
String id;
/// Method name
String methodName;
/// Plugin ID
String pluginId;
/// Filter schema
PluginJsonSchema? schema;
/// Supported contexts
List<PluginContextType> supportedContexts;
/// Filter title
String title;
@override
bool operator ==(Object other) => identical(this, other) || other is PluginFilterResponseDto &&
other.description == description &&
other.id == id &&
other.methodName == methodName &&
other.pluginId == pluginId &&
other.schema == schema &&
_deepEquality.equals(other.supportedContexts, supportedContexts) &&
other.title == title;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(description.hashCode) +
(id.hashCode) +
(methodName.hashCode) +
(pluginId.hashCode) +
(schema == null ? 0 : schema!.hashCode) +
(supportedContexts.hashCode) +
(title.hashCode);
@override
String toString() => 'PluginFilterResponseDto[description=$description, id=$id, methodName=$methodName, pluginId=$pluginId, schema=$schema, supportedContexts=$supportedContexts, title=$title]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'description'] = this.description;
json[r'id'] = this.id;
json[r'methodName'] = this.methodName;
json[r'pluginId'] = this.pluginId;
if (this.schema != null) {
json[r'schema'] = this.schema;
} else {
// json[r'schema'] = null;
}
json[r'supportedContexts'] = this.supportedContexts;
json[r'title'] = this.title;
return json;
}
/// Returns a new [PluginFilterResponseDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static PluginFilterResponseDto? fromJson(dynamic value) {
upgradeDto(value, "PluginFilterResponseDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return PluginFilterResponseDto(
description: mapValueOfType<String>(json, r'description')!,
id: mapValueOfType<String>(json, r'id')!,
methodName: mapValueOfType<String>(json, r'methodName')!,
pluginId: mapValueOfType<String>(json, r'pluginId')!,
schema: PluginJsonSchema.fromJson(json[r'schema']),
supportedContexts: PluginContextType.listFromJson(json[r'supportedContexts']),
title: mapValueOfType<String>(json, r'title')!,
);
}
return null;
}
static List<PluginFilterResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <PluginFilterResponseDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = PluginFilterResponseDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, PluginFilterResponseDto> mapFromJson(dynamic json) {
final map = <String, PluginFilterResponseDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = PluginFilterResponseDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of PluginFilterResponseDto-objects as value to a dart map
static Map<String, List<PluginFilterResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<PluginFilterResponseDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = PluginFilterResponseDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'description',
'id',
'methodName',
'pluginId',
'schema',
'supportedContexts',
'title',
};
}
-158
View File
@@ -1,158 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class PluginJsonSchema {
/// Returns a new [PluginJsonSchema] instance.
PluginJsonSchema({
this.additionalProperties,
this.description,
this.properties = const {},
this.required_ = const [],
this.type,
});
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
bool? additionalProperties;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? description;
Map<String, PluginJsonSchemaProperty> properties;
List<String> required_;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
PluginJsonSchemaType? type;
@override
bool operator ==(Object other) => identical(this, other) || other is PluginJsonSchema &&
other.additionalProperties == additionalProperties &&
other.description == description &&
_deepEquality.equals(other.properties, properties) &&
_deepEquality.equals(other.required_, required_) &&
other.type == type;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(additionalProperties == null ? 0 : additionalProperties!.hashCode) +
(description == null ? 0 : description!.hashCode) +
(properties.hashCode) +
(required_.hashCode) +
(type == null ? 0 : type!.hashCode);
@override
String toString() => 'PluginJsonSchema[additionalProperties=$additionalProperties, description=$description, properties=$properties, required_=$required_, type=$type]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
if (this.additionalProperties != null) {
json[r'additionalProperties'] = this.additionalProperties;
} else {
// json[r'additionalProperties'] = null;
}
if (this.description != null) {
json[r'description'] = this.description;
} else {
// json[r'description'] = null;
}
json[r'properties'] = this.properties;
json[r'required'] = this.required_;
if (this.type != null) {
json[r'type'] = this.type;
} else {
// json[r'type'] = null;
}
return json;
}
/// Returns a new [PluginJsonSchema] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static PluginJsonSchema? fromJson(dynamic value) {
upgradeDto(value, "PluginJsonSchema");
if (value is Map) {
final json = value.cast<String, dynamic>();
return PluginJsonSchema(
additionalProperties: mapValueOfType<bool>(json, r'additionalProperties'),
description: mapValueOfType<String>(json, r'description'),
properties: PluginJsonSchemaProperty.mapFromJson(json[r'properties']),
required_: json[r'required'] is Iterable
? (json[r'required'] as Iterable).cast<String>().toList(growable: false)
: const [],
type: PluginJsonSchemaType.fromJson(json[r'type']),
);
}
return null;
}
static List<PluginJsonSchema> listFromJson(dynamic json, {bool growable = false,}) {
final result = <PluginJsonSchema>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = PluginJsonSchema.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, PluginJsonSchema> mapFromJson(dynamic json) {
final map = <String, PluginJsonSchema>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = PluginJsonSchema.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of PluginJsonSchema-objects as value to a dart map
static Map<String, List<PluginJsonSchema>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<PluginJsonSchema>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = PluginJsonSchema.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
};
}
-195
View File
@@ -1,195 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class PluginJsonSchemaProperty {
/// Returns a new [PluginJsonSchemaProperty] instance.
PluginJsonSchemaProperty({
this.additionalProperties,
this.default_,
this.description,
this.enum_ = const [],
this.items,
this.properties = const {},
this.required_ = const [],
this.type,
});
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
PluginJsonSchemaPropertyAdditionalProperties? additionalProperties;
Object? default_;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? description;
List<String> enum_;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
PluginJsonSchemaProperty? items;
Map<String, PluginJsonSchemaProperty> properties;
List<String> required_;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
PluginJsonSchemaType? type;
@override
bool operator ==(Object other) => identical(this, other) || other is PluginJsonSchemaProperty &&
other.additionalProperties == additionalProperties &&
other.default_ == default_ &&
other.description == description &&
_deepEquality.equals(other.enum_, enum_) &&
other.items == items &&
_deepEquality.equals(other.properties, properties) &&
_deepEquality.equals(other.required_, required_) &&
other.type == type;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(additionalProperties == null ? 0 : additionalProperties!.hashCode) +
(default_ == null ? 0 : default_!.hashCode) +
(description == null ? 0 : description!.hashCode) +
(enum_.hashCode) +
(items == null ? 0 : items!.hashCode) +
(properties.hashCode) +
(required_.hashCode) +
(type == null ? 0 : type!.hashCode);
@override
String toString() => 'PluginJsonSchemaProperty[additionalProperties=$additionalProperties, default_=$default_, description=$description, enum_=$enum_, items=$items, properties=$properties, required_=$required_, type=$type]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
if (this.additionalProperties != null) {
json[r'additionalProperties'] = this.additionalProperties;
} else {
// json[r'additionalProperties'] = null;
}
if (this.default_ != null) {
json[r'default'] = this.default_;
} else {
// json[r'default'] = null;
}
if (this.description != null) {
json[r'description'] = this.description;
} else {
// json[r'description'] = null;
}
json[r'enum'] = this.enum_;
if (this.items != null) {
json[r'items'] = this.items;
} else {
// json[r'items'] = null;
}
json[r'properties'] = this.properties;
json[r'required'] = this.required_;
if (this.type != null) {
json[r'type'] = this.type;
} else {
// json[r'type'] = null;
}
return json;
}
/// Returns a new [PluginJsonSchemaProperty] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static PluginJsonSchemaProperty? fromJson(dynamic value) {
upgradeDto(value, "PluginJsonSchemaProperty");
if (value is Map) {
final json = value.cast<String, dynamic>();
return PluginJsonSchemaProperty(
additionalProperties: PluginJsonSchemaPropertyAdditionalProperties.fromJson(json[r'additionalProperties']),
default_: mapValueOfType<Object>(json, r'default'),
description: mapValueOfType<String>(json, r'description'),
enum_: json[r'enum'] is Iterable
? (json[r'enum'] as Iterable).cast<String>().toList(growable: false)
: const [],
items: PluginJsonSchemaProperty.fromJson(json[r'items']),
properties: PluginJsonSchemaProperty.mapFromJson(json[r'properties']),
required_: json[r'required'] is Iterable
? (json[r'required'] as Iterable).cast<String>().toList(growable: false)
: const [],
type: PluginJsonSchemaType.fromJson(json[r'type']),
);
}
return null;
}
static List<PluginJsonSchemaProperty> listFromJson(dynamic json, {bool growable = false,}) {
final result = <PluginJsonSchemaProperty>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = PluginJsonSchemaProperty.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, PluginJsonSchemaProperty> mapFromJson(dynamic json) {
final map = <String, PluginJsonSchemaProperty>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = PluginJsonSchemaProperty.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of PluginJsonSchemaProperty-objects as value to a dart map
static Map<String, List<PluginJsonSchemaProperty>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<PluginJsonSchemaProperty>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = PluginJsonSchemaProperty.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
};
}
@@ -1,195 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class PluginJsonSchemaPropertyAdditionalProperties {
/// Returns a new [PluginJsonSchemaPropertyAdditionalProperties] instance.
PluginJsonSchemaPropertyAdditionalProperties({
this.additionalProperties,
this.default_,
this.description,
this.enum_ = const [],
this.items,
this.properties = const {},
this.required_ = const [],
this.type,
});
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
PluginJsonSchemaPropertyAdditionalProperties? additionalProperties;
Object? default_;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? description;
List<String> enum_;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
PluginJsonSchemaProperty? items;
Map<String, PluginJsonSchemaProperty> properties;
List<String> required_;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
PluginJsonSchemaType? type;
@override
bool operator ==(Object other) => identical(this, other) || other is PluginJsonSchemaPropertyAdditionalProperties &&
other.additionalProperties == additionalProperties &&
other.default_ == default_ &&
other.description == description &&
_deepEquality.equals(other.enum_, enum_) &&
other.items == items &&
_deepEquality.equals(other.properties, properties) &&
_deepEquality.equals(other.required_, required_) &&
other.type == type;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(additionalProperties == null ? 0 : additionalProperties!.hashCode) +
(default_ == null ? 0 : default_!.hashCode) +
(description == null ? 0 : description!.hashCode) +
(enum_.hashCode) +
(items == null ? 0 : items!.hashCode) +
(properties.hashCode) +
(required_.hashCode) +
(type == null ? 0 : type!.hashCode);
@override
String toString() => 'PluginJsonSchemaPropertyAdditionalProperties[additionalProperties=$additionalProperties, default_=$default_, description=$description, enum_=$enum_, items=$items, properties=$properties, required_=$required_, type=$type]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
if (this.additionalProperties != null) {
json[r'additionalProperties'] = this.additionalProperties;
} else {
// json[r'additionalProperties'] = null;
}
if (this.default_ != null) {
json[r'default'] = this.default_;
} else {
// json[r'default'] = null;
}
if (this.description != null) {
json[r'description'] = this.description;
} else {
// json[r'description'] = null;
}
json[r'enum'] = this.enum_;
if (this.items != null) {
json[r'items'] = this.items;
} else {
// json[r'items'] = null;
}
json[r'properties'] = this.properties;
json[r'required'] = this.required_;
if (this.type != null) {
json[r'type'] = this.type;
} else {
// json[r'type'] = null;
}
return json;
}
/// Returns a new [PluginJsonSchemaPropertyAdditionalProperties] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static PluginJsonSchemaPropertyAdditionalProperties? fromJson(dynamic value) {
upgradeDto(value, "PluginJsonSchemaPropertyAdditionalProperties");
if (value is Map) {
final json = value.cast<String, dynamic>();
return PluginJsonSchemaPropertyAdditionalProperties(
additionalProperties: PluginJsonSchemaPropertyAdditionalProperties.fromJson(json[r'additionalProperties']),
default_: mapValueOfType<Object>(json, r'default'),
description: mapValueOfType<String>(json, r'description'),
enum_: json[r'enum'] is Iterable
? (json[r'enum'] as Iterable).cast<String>().toList(growable: false)
: const [],
items: PluginJsonSchemaProperty.fromJson(json[r'items']),
properties: PluginJsonSchemaProperty.mapFromJson(json[r'properties']),
required_: json[r'required'] is Iterable
? (json[r'required'] as Iterable).cast<String>().toList(growable: false)
: const [],
type: PluginJsonSchemaType.fromJson(json[r'type']),
);
}
return null;
}
static List<PluginJsonSchemaPropertyAdditionalProperties> listFromJson(dynamic json, {bool growable = false,}) {
final result = <PluginJsonSchemaPropertyAdditionalProperties>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = PluginJsonSchemaPropertyAdditionalProperties.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, PluginJsonSchemaPropertyAdditionalProperties> mapFromJson(dynamic json) {
final map = <String, PluginJsonSchemaPropertyAdditionalProperties>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = PluginJsonSchemaPropertyAdditionalProperties.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of PluginJsonSchemaPropertyAdditionalProperties-objects as value to a dart map
static Map<String, List<PluginJsonSchemaPropertyAdditionalProperties>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<PluginJsonSchemaPropertyAdditionalProperties>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = PluginJsonSchemaPropertyAdditionalProperties.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
};
}
-100
View File
@@ -1,100 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class PluginJsonSchemaType {
/// Instantiate a new enum with the provided [value].
const PluginJsonSchemaType._(this.value);
/// The underlying value of this enum member.
final String value;
@override
String toString() => value;
String toJson() => value;
static const string = PluginJsonSchemaType._(r'string');
static const number = PluginJsonSchemaType._(r'number');
static const integer = PluginJsonSchemaType._(r'integer');
static const boolean = PluginJsonSchemaType._(r'boolean');
static const object = PluginJsonSchemaType._(r'object');
static const array = PluginJsonSchemaType._(r'array');
static const null_ = PluginJsonSchemaType._(r'null');
/// List of all possible values in this [enum][PluginJsonSchemaType].
static const values = <PluginJsonSchemaType>[
string,
number,
integer,
boolean,
object,
array,
null_,
];
static PluginJsonSchemaType? fromJson(dynamic value) => PluginJsonSchemaTypeTypeTransformer().decode(value);
static List<PluginJsonSchemaType> listFromJson(dynamic json, {bool growable = false,}) {
final result = <PluginJsonSchemaType>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = PluginJsonSchemaType.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
}
/// Transformation class that can [encode] an instance of [PluginJsonSchemaType] to String,
/// and [decode] dynamic data back to [PluginJsonSchemaType].
class PluginJsonSchemaTypeTypeTransformer {
factory PluginJsonSchemaTypeTypeTransformer() => _instance ??= const PluginJsonSchemaTypeTypeTransformer._();
const PluginJsonSchemaTypeTypeTransformer._();
String encode(PluginJsonSchemaType data) => data.value;
/// Decodes a [dynamic value][data] to a PluginJsonSchemaType.
///
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
///
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
/// and users are still using an old app with the old code.
PluginJsonSchemaType? decode(dynamic data, {bool allowNull = true}) {
if (data != null) {
switch (data) {
case r'string': return PluginJsonSchemaType.string;
case r'number': return PluginJsonSchemaType.number;
case r'integer': return PluginJsonSchemaType.integer;
case r'boolean': return PluginJsonSchemaType.boolean;
case r'object': return PluginJsonSchemaType.object;
case r'array': return PluginJsonSchemaType.array;
case r'null': return PluginJsonSchemaType.null_;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
}
}
}
return null;
}
/// Singleton [PluginJsonSchemaTypeTypeTransformer] instance.
static PluginJsonSchemaTypeTypeTransformer? _instance;
}
+172
View File
@@ -0,0 +1,172 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class PluginMethodResponseDto {
/// Returns a new [PluginMethodResponseDto] instance.
PluginMethodResponseDto({
required this.description,
required this.hostFunctions,
required this.key,
required this.name,
this.schema,
required this.title,
this.types = const [],
this.uiHints = const [],
});
/// Description
String description;
bool hostFunctions;
/// Key
String key;
/// Name
String name;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
Object? schema;
/// Title
String title;
/// Workflow types
List<WorkflowType> types;
/// Ui hints
List<String> uiHints;
@override
bool operator ==(Object other) => identical(this, other) || other is PluginMethodResponseDto &&
other.description == description &&
other.hostFunctions == hostFunctions &&
other.key == key &&
other.name == name &&
other.schema == schema &&
other.title == title &&
_deepEquality.equals(other.types, types) &&
_deepEquality.equals(other.uiHints, uiHints);
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(description.hashCode) +
(hostFunctions.hashCode) +
(key.hashCode) +
(name.hashCode) +
(schema == null ? 0 : schema!.hashCode) +
(title.hashCode) +
(types.hashCode) +
(uiHints.hashCode);
@override
String toString() => 'PluginMethodResponseDto[description=$description, hostFunctions=$hostFunctions, key=$key, name=$name, schema=$schema, title=$title, types=$types, uiHints=$uiHints]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'description'] = this.description;
json[r'hostFunctions'] = this.hostFunctions;
json[r'key'] = this.key;
json[r'name'] = this.name;
if (this.schema != null) {
json[r'schema'] = this.schema;
} else {
// json[r'schema'] = null;
}
json[r'title'] = this.title;
json[r'types'] = this.types;
json[r'uiHints'] = this.uiHints;
return json;
}
/// Returns a new [PluginMethodResponseDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static PluginMethodResponseDto? fromJson(dynamic value) {
upgradeDto(value, "PluginMethodResponseDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return PluginMethodResponseDto(
description: mapValueOfType<String>(json, r'description')!,
hostFunctions: mapValueOfType<bool>(json, r'hostFunctions')!,
key: mapValueOfType<String>(json, r'key')!,
name: mapValueOfType<String>(json, r'name')!,
schema: mapValueOfType<Object>(json, r'schema'),
title: mapValueOfType<String>(json, r'title')!,
types: WorkflowType.listFromJson(json[r'types']),
uiHints: json[r'uiHints'] is Iterable
? (json[r'uiHints'] as Iterable).cast<String>().toList(growable: false)
: const [],
);
}
return null;
}
static List<PluginMethodResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <PluginMethodResponseDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = PluginMethodResponseDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, PluginMethodResponseDto> mapFromJson(dynamic json) {
final map = <String, PluginMethodResponseDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = PluginMethodResponseDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of PluginMethodResponseDto-objects as value to a dart map
static Map<String, List<PluginMethodResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<PluginMethodResponseDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = PluginMethodResponseDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'description',
'hostFunctions',
'key',
'name',
'title',
'types',
'uiHints',
};
}
+10 -19
View File
@@ -13,21 +13,17 @@ part of openapi.api;
class PluginResponseDto {
/// Returns a new [PluginResponseDto] instance.
PluginResponseDto({
this.actions = const [],
required this.author,
required this.createdAt,
required this.description,
this.filters = const [],
required this.id,
this.methods = const [],
required this.name,
required this.title,
required this.updatedAt,
required this.version,
});
/// Plugin actions
List<PluginActionResponseDto> actions;
/// Plugin author
String author;
@@ -37,12 +33,12 @@ class PluginResponseDto {
/// Plugin description
String description;
/// Plugin filters
List<PluginFilterResponseDto> filters;
/// Plugin ID
String id;
/// Plugin methods
List<PluginMethodResponseDto> methods;
/// Plugin name
String name;
@@ -57,12 +53,11 @@ class PluginResponseDto {
@override
bool operator ==(Object other) => identical(this, other) || other is PluginResponseDto &&
_deepEquality.equals(other.actions, actions) &&
other.author == author &&
other.createdAt == createdAt &&
other.description == description &&
_deepEquality.equals(other.filters, filters) &&
other.id == id &&
_deepEquality.equals(other.methods, methods) &&
other.name == name &&
other.title == title &&
other.updatedAt == updatedAt &&
@@ -71,28 +66,26 @@ class PluginResponseDto {
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(actions.hashCode) +
(author.hashCode) +
(createdAt.hashCode) +
(description.hashCode) +
(filters.hashCode) +
(id.hashCode) +
(methods.hashCode) +
(name.hashCode) +
(title.hashCode) +
(updatedAt.hashCode) +
(version.hashCode);
@override
String toString() => 'PluginResponseDto[actions=$actions, author=$author, createdAt=$createdAt, description=$description, filters=$filters, id=$id, name=$name, title=$title, updatedAt=$updatedAt, version=$version]';
String toString() => 'PluginResponseDto[author=$author, createdAt=$createdAt, description=$description, id=$id, methods=$methods, name=$name, title=$title, updatedAt=$updatedAt, version=$version]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'actions'] = this.actions;
json[r'author'] = this.author;
json[r'createdAt'] = this.createdAt;
json[r'description'] = this.description;
json[r'filters'] = this.filters;
json[r'id'] = this.id;
json[r'methods'] = this.methods;
json[r'name'] = this.name;
json[r'title'] = this.title;
json[r'updatedAt'] = this.updatedAt;
@@ -109,12 +102,11 @@ class PluginResponseDto {
final json = value.cast<String, dynamic>();
return PluginResponseDto(
actions: PluginActionResponseDto.listFromJson(json[r'actions']),
author: mapValueOfType<String>(json, r'author')!,
createdAt: mapValueOfType<String>(json, r'createdAt')!,
description: mapValueOfType<String>(json, r'description')!,
filters: PluginFilterResponseDto.listFromJson(json[r'filters']),
id: mapValueOfType<String>(json, r'id')!,
methods: PluginMethodResponseDto.listFromJson(json[r'methods']),
name: mapValueOfType<String>(json, r'name')!,
title: mapValueOfType<String>(json, r'title')!,
updatedAt: mapValueOfType<String>(json, r'updatedAt')!,
@@ -166,12 +158,11 @@ class PluginResponseDto {
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'actions',
'author',
'createdAt',
'description',
'filters',
'id',
'methods',
'name',
'title',
'updatedAt',
-107
View File
@@ -1,107 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class PluginTriggerResponseDto {
/// Returns a new [PluginTriggerResponseDto] instance.
PluginTriggerResponseDto({
required this.contextType,
required this.type,
});
PluginContextType contextType;
PluginTriggerType type;
@override
bool operator ==(Object other) => identical(this, other) || other is PluginTriggerResponseDto &&
other.contextType == contextType &&
other.type == type;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(contextType.hashCode) +
(type.hashCode);
@override
String toString() => 'PluginTriggerResponseDto[contextType=$contextType, type=$type]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'contextType'] = this.contextType;
json[r'type'] = this.type;
return json;
}
/// Returns a new [PluginTriggerResponseDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static PluginTriggerResponseDto? fromJson(dynamic value) {
upgradeDto(value, "PluginTriggerResponseDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return PluginTriggerResponseDto(
contextType: PluginContextType.fromJson(json[r'contextType'])!,
type: PluginTriggerType.fromJson(json[r'type'])!,
);
}
return null;
}
static List<PluginTriggerResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <PluginTriggerResponseDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = PluginTriggerResponseDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, PluginTriggerResponseDto> mapFromJson(dynamic json) {
final map = <String, PluginTriggerResponseDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = PluginTriggerResponseDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of PluginTriggerResponseDto-objects as value to a dart map
static Map<String, List<PluginTriggerResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<PluginTriggerResponseDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = PluginTriggerResponseDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'contextType',
'type',
};
}
-107
View File
@@ -1,107 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class WorkflowActionItemDto {
/// Returns a new [WorkflowActionItemDto] instance.
WorkflowActionItemDto({
this.actionConfig = const {},
required this.pluginActionId,
});
Map<String, Object> actionConfig;
/// Plugin action ID
String pluginActionId;
@override
bool operator ==(Object other) => identical(this, other) || other is WorkflowActionItemDto &&
_deepEquality.equals(other.actionConfig, actionConfig) &&
other.pluginActionId == pluginActionId;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(actionConfig.hashCode) +
(pluginActionId.hashCode);
@override
String toString() => 'WorkflowActionItemDto[actionConfig=$actionConfig, pluginActionId=$pluginActionId]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'actionConfig'] = this.actionConfig;
json[r'pluginActionId'] = this.pluginActionId;
return json;
}
/// Returns a new [WorkflowActionItemDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static WorkflowActionItemDto? fromJson(dynamic value) {
upgradeDto(value, "WorkflowActionItemDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return WorkflowActionItemDto(
actionConfig: mapCastOfType<String, Object>(json, r'actionConfig') ?? const {},
pluginActionId: mapValueOfType<String>(json, r'pluginActionId')!,
);
}
return null;
}
static List<WorkflowActionItemDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <WorkflowActionItemDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = WorkflowActionItemDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, WorkflowActionItemDto> mapFromJson(dynamic json) {
final map = <String, WorkflowActionItemDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = WorkflowActionItemDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of WorkflowActionItemDto-objects as value to a dart map
static Map<String, List<WorkflowActionItemDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<WorkflowActionItemDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = WorkflowActionItemDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'pluginActionId',
};
}
-142
View File
@@ -1,142 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class WorkflowActionResponseDto {
/// Returns a new [WorkflowActionResponseDto] instance.
WorkflowActionResponseDto({
required this.actionConfig,
required this.id,
required this.order,
required this.pluginActionId,
required this.workflowId,
});
Map<String, Object>? actionConfig;
/// Action ID
String id;
/// Action order
///
/// Minimum value: -9007199254740991
/// Maximum value: 9007199254740991
int order;
/// Plugin action ID
String pluginActionId;
/// Workflow ID
String workflowId;
@override
bool operator ==(Object other) => identical(this, other) || other is WorkflowActionResponseDto &&
_deepEquality.equals(other.actionConfig, actionConfig) &&
other.id == id &&
other.order == order &&
other.pluginActionId == pluginActionId &&
other.workflowId == workflowId;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(actionConfig == null ? 0 : actionConfig!.hashCode) +
(id.hashCode) +
(order.hashCode) +
(pluginActionId.hashCode) +
(workflowId.hashCode);
@override
String toString() => 'WorkflowActionResponseDto[actionConfig=$actionConfig, id=$id, order=$order, pluginActionId=$pluginActionId, workflowId=$workflowId]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
if (this.actionConfig != null) {
json[r'actionConfig'] = this.actionConfig;
} else {
// json[r'actionConfig'] = null;
}
json[r'id'] = this.id;
json[r'order'] = this.order;
json[r'pluginActionId'] = this.pluginActionId;
json[r'workflowId'] = this.workflowId;
return json;
}
/// Returns a new [WorkflowActionResponseDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static WorkflowActionResponseDto? fromJson(dynamic value) {
upgradeDto(value, "WorkflowActionResponseDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return WorkflowActionResponseDto(
actionConfig: mapCastOfType<String, Object>(json, r'actionConfig'),
id: mapValueOfType<String>(json, r'id')!,
order: mapValueOfType<int>(json, r'order')!,
pluginActionId: mapValueOfType<String>(json, r'pluginActionId')!,
workflowId: mapValueOfType<String>(json, r'workflowId')!,
);
}
return null;
}
static List<WorkflowActionResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <WorkflowActionResponseDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = WorkflowActionResponseDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, WorkflowActionResponseDto> mapFromJson(dynamic json) {
final map = <String, WorkflowActionResponseDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = WorkflowActionResponseDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of WorkflowActionResponseDto-objects as value to a dart map
static Map<String, List<WorkflowActionResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<WorkflowActionResponseDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = WorkflowActionResponseDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'actionConfig',
'id',
'order',
'pluginActionId',
'workflowId',
};
}
+23 -37
View File
@@ -13,24 +13,14 @@ part of openapi.api;
class WorkflowCreateDto {
/// Returns a new [WorkflowCreateDto] instance.
WorkflowCreateDto({
this.actions = const [],
this.description,
this.enabled,
this.filters = const [],
required this.name,
required this.triggerType,
this.name,
this.steps = const [],
required this.trigger,
});
/// Workflow actions
List<WorkflowActionItemDto> actions;
/// Workflow description
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? description;
/// Workflow enabled
@@ -42,39 +32,35 @@ class WorkflowCreateDto {
///
bool? enabled;
/// Workflow filters
List<WorkflowFilterItemDto> filters;
/// Workflow name
String name;
String? name;
PluginTriggerType triggerType;
List<WorkflowStepDto> steps;
WorkflowTrigger trigger;
@override
bool operator ==(Object other) => identical(this, other) || other is WorkflowCreateDto &&
_deepEquality.equals(other.actions, actions) &&
other.description == description &&
other.enabled == enabled &&
_deepEquality.equals(other.filters, filters) &&
other.name == name &&
other.triggerType == triggerType;
_deepEquality.equals(other.steps, steps) &&
other.trigger == trigger;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(actions.hashCode) +
(description == null ? 0 : description!.hashCode) +
(enabled == null ? 0 : enabled!.hashCode) +
(filters.hashCode) +
(name.hashCode) +
(triggerType.hashCode);
(name == null ? 0 : name!.hashCode) +
(steps.hashCode) +
(trigger.hashCode);
@override
String toString() => 'WorkflowCreateDto[actions=$actions, description=$description, enabled=$enabled, filters=$filters, name=$name, triggerType=$triggerType]';
String toString() => 'WorkflowCreateDto[description=$description, enabled=$enabled, name=$name, steps=$steps, trigger=$trigger]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'actions'] = this.actions;
if (this.description != null) {
json[r'description'] = this.description;
} else {
@@ -85,9 +71,13 @@ class WorkflowCreateDto {
} else {
// json[r'enabled'] = null;
}
json[r'filters'] = this.filters;
if (this.name != null) {
json[r'name'] = this.name;
json[r'triggerType'] = this.triggerType;
} else {
// json[r'name'] = null;
}
json[r'steps'] = this.steps;
json[r'trigger'] = this.trigger;
return json;
}
@@ -100,12 +90,11 @@ class WorkflowCreateDto {
final json = value.cast<String, dynamic>();
return WorkflowCreateDto(
actions: WorkflowActionItemDto.listFromJson(json[r'actions']),
description: mapValueOfType<String>(json, r'description'),
enabled: mapValueOfType<bool>(json, r'enabled'),
filters: WorkflowFilterItemDto.listFromJson(json[r'filters']),
name: mapValueOfType<String>(json, r'name')!,
triggerType: PluginTriggerType.fromJson(json[r'triggerType'])!,
name: mapValueOfType<String>(json, r'name'),
steps: WorkflowStepDto.listFromJson(json[r'steps']),
trigger: WorkflowTrigger.fromJson(json[r'trigger'])!,
);
}
return null;
@@ -153,10 +142,7 @@ class WorkflowCreateDto {
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'actions',
'filters',
'name',
'triggerType',
'trigger',
};
}
-107
View File
@@ -1,107 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class WorkflowFilterItemDto {
/// Returns a new [WorkflowFilterItemDto] instance.
WorkflowFilterItemDto({
this.filterConfig = const {},
required this.pluginFilterId,
});
Map<String, Object> filterConfig;
/// Plugin filter ID
String pluginFilterId;
@override
bool operator ==(Object other) => identical(this, other) || other is WorkflowFilterItemDto &&
_deepEquality.equals(other.filterConfig, filterConfig) &&
other.pluginFilterId == pluginFilterId;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(filterConfig.hashCode) +
(pluginFilterId.hashCode);
@override
String toString() => 'WorkflowFilterItemDto[filterConfig=$filterConfig, pluginFilterId=$pluginFilterId]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'filterConfig'] = this.filterConfig;
json[r'pluginFilterId'] = this.pluginFilterId;
return json;
}
/// Returns a new [WorkflowFilterItemDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static WorkflowFilterItemDto? fromJson(dynamic value) {
upgradeDto(value, "WorkflowFilterItemDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return WorkflowFilterItemDto(
filterConfig: mapCastOfType<String, Object>(json, r'filterConfig') ?? const {},
pluginFilterId: mapValueOfType<String>(json, r'pluginFilterId')!,
);
}
return null;
}
static List<WorkflowFilterItemDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <WorkflowFilterItemDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = WorkflowFilterItemDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, WorkflowFilterItemDto> mapFromJson(dynamic json) {
final map = <String, WorkflowFilterItemDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = WorkflowFilterItemDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of WorkflowFilterItemDto-objects as value to a dart map
static Map<String, List<WorkflowFilterItemDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<WorkflowFilterItemDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = WorkflowFilterItemDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'pluginFilterId',
};
}
-142
View File
@@ -1,142 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class WorkflowFilterResponseDto {
/// Returns a new [WorkflowFilterResponseDto] instance.
WorkflowFilterResponseDto({
required this.filterConfig,
required this.id,
required this.order,
required this.pluginFilterId,
required this.workflowId,
});
Map<String, Object>? filterConfig;
/// Filter ID
String id;
/// Filter order
///
/// Minimum value: -9007199254740991
/// Maximum value: 9007199254740991
int order;
/// Plugin filter ID
String pluginFilterId;
/// Workflow ID
String workflowId;
@override
bool operator ==(Object other) => identical(this, other) || other is WorkflowFilterResponseDto &&
_deepEquality.equals(other.filterConfig, filterConfig) &&
other.id == id &&
other.order == order &&
other.pluginFilterId == pluginFilterId &&
other.workflowId == workflowId;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(filterConfig == null ? 0 : filterConfig!.hashCode) +
(id.hashCode) +
(order.hashCode) +
(pluginFilterId.hashCode) +
(workflowId.hashCode);
@override
String toString() => 'WorkflowFilterResponseDto[filterConfig=$filterConfig, id=$id, order=$order, pluginFilterId=$pluginFilterId, workflowId=$workflowId]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
if (this.filterConfig != null) {
json[r'filterConfig'] = this.filterConfig;
} else {
// json[r'filterConfig'] = null;
}
json[r'id'] = this.id;
json[r'order'] = this.order;
json[r'pluginFilterId'] = this.pluginFilterId;
json[r'workflowId'] = this.workflowId;
return json;
}
/// Returns a new [WorkflowFilterResponseDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static WorkflowFilterResponseDto? fromJson(dynamic value) {
upgradeDto(value, "WorkflowFilterResponseDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return WorkflowFilterResponseDto(
filterConfig: mapCastOfType<String, Object>(json, r'filterConfig'),
id: mapValueOfType<String>(json, r'id')!,
order: mapValueOfType<int>(json, r'order')!,
pluginFilterId: mapValueOfType<String>(json, r'pluginFilterId')!,
workflowId: mapValueOfType<String>(json, r'workflowId')!,
);
}
return null;
}
static List<WorkflowFilterResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <WorkflowFilterResponseDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = WorkflowFilterResponseDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, WorkflowFilterResponseDto> mapFromJson(dynamic json) {
final map = <String, WorkflowFilterResponseDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = WorkflowFilterResponseDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of WorkflowFilterResponseDto-objects as value to a dart map
static Map<String, List<WorkflowFilterResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<WorkflowFilterResponseDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = WorkflowFilterResponseDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'filterConfig',
'id',
'order',
'pluginFilterId',
'workflowId',
};
}
+32 -37
View File
@@ -13,86 +13,83 @@ part of openapi.api;
class WorkflowResponseDto {
/// Returns a new [WorkflowResponseDto] instance.
WorkflowResponseDto({
this.actions = const [],
required this.createdAt,
required this.description,
required this.enabled,
this.filters = const [],
required this.id,
required this.name,
required this.ownerId,
required this.triggerType,
this.steps = const [],
required this.trigger,
required this.updatedAt,
});
/// Workflow actions
List<WorkflowActionResponseDto> actions;
/// Creation date
String createdAt;
/// Workflow description
String description;
String? description;
/// Workflow enabled
bool enabled;
/// Workflow filters
List<WorkflowFilterResponseDto> filters;
/// Workflow ID
String id;
/// Workflow name
String? name;
/// Owner user ID
String ownerId;
/// Workflow steps
List<WorkflowStepDto> steps;
PluginTriggerType triggerType;
WorkflowTrigger trigger;
/// Update date
String updatedAt;
@override
bool operator ==(Object other) => identical(this, other) || other is WorkflowResponseDto &&
_deepEquality.equals(other.actions, actions) &&
other.createdAt == createdAt &&
other.description == description &&
other.enabled == enabled &&
_deepEquality.equals(other.filters, filters) &&
other.id == id &&
other.name == name &&
other.ownerId == ownerId &&
other.triggerType == triggerType;
_deepEquality.equals(other.steps, steps) &&
other.trigger == trigger &&
other.updatedAt == updatedAt;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(actions.hashCode) +
(createdAt.hashCode) +
(description.hashCode) +
(description == null ? 0 : description!.hashCode) +
(enabled.hashCode) +
(filters.hashCode) +
(id.hashCode) +
(name == null ? 0 : name!.hashCode) +
(ownerId.hashCode) +
(triggerType.hashCode);
(steps.hashCode) +
(trigger.hashCode) +
(updatedAt.hashCode);
@override
String toString() => 'WorkflowResponseDto[actions=$actions, createdAt=$createdAt, description=$description, enabled=$enabled, filters=$filters, id=$id, name=$name, ownerId=$ownerId, triggerType=$triggerType]';
String toString() => 'WorkflowResponseDto[createdAt=$createdAt, description=$description, enabled=$enabled, id=$id, name=$name, steps=$steps, trigger=$trigger, updatedAt=$updatedAt]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'actions'] = this.actions;
json[r'createdAt'] = this.createdAt;
if (this.description != null) {
json[r'description'] = this.description;
} else {
// json[r'description'] = null;
}
json[r'enabled'] = this.enabled;
json[r'filters'] = this.filters;
json[r'id'] = this.id;
if (this.name != null) {
json[r'name'] = this.name;
} else {
// json[r'name'] = null;
}
json[r'ownerId'] = this.ownerId;
json[r'triggerType'] = this.triggerType;
json[r'steps'] = this.steps;
json[r'trigger'] = this.trigger;
json[r'updatedAt'] = this.updatedAt;
return json;
}
@@ -105,15 +102,14 @@ class WorkflowResponseDto {
final json = value.cast<String, dynamic>();
return WorkflowResponseDto(
actions: WorkflowActionResponseDto.listFromJson(json[r'actions']),
createdAt: mapValueOfType<String>(json, r'createdAt')!,
description: mapValueOfType<String>(json, r'description')!,
description: mapValueOfType<String>(json, r'description'),
enabled: mapValueOfType<bool>(json, r'enabled')!,
filters: WorkflowFilterResponseDto.listFromJson(json[r'filters']),
id: mapValueOfType<String>(json, r'id')!,
name: mapValueOfType<String>(json, r'name'),
ownerId: mapValueOfType<String>(json, r'ownerId')!,
triggerType: PluginTriggerType.fromJson(json[r'triggerType'])!,
steps: WorkflowStepDto.listFromJson(json[r'steps']),
trigger: WorkflowTrigger.fromJson(json[r'trigger'])!,
updatedAt: mapValueOfType<String>(json, r'updatedAt')!,
);
}
return null;
@@ -161,15 +157,14 @@ class WorkflowResponseDto {
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'actions',
'createdAt',
'description',
'enabled',
'filters',
'id',
'name',
'ownerId',
'triggerType',
'steps',
'trigger',
'updatedAt',
};
}
+134
View File
@@ -0,0 +1,134 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class WorkflowShareResponseDto {
/// Returns a new [WorkflowShareResponseDto] instance.
WorkflowShareResponseDto({
required this.description,
required this.name,
this.steps = const [],
required this.trigger,
});
/// Workflow description
String? description;
/// Workflow name
String? name;
/// Workflow steps
List<WorkflowShareStepDto> steps;
WorkflowTrigger trigger;
@override
bool operator ==(Object other) => identical(this, other) || other is WorkflowShareResponseDto &&
other.description == description &&
other.name == name &&
_deepEquality.equals(other.steps, steps) &&
other.trigger == trigger;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(description == null ? 0 : description!.hashCode) +
(name == null ? 0 : name!.hashCode) +
(steps.hashCode) +
(trigger.hashCode);
@override
String toString() => 'WorkflowShareResponseDto[description=$description, name=$name, steps=$steps, trigger=$trigger]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
if (this.description != null) {
json[r'description'] = this.description;
} else {
// json[r'description'] = null;
}
if (this.name != null) {
json[r'name'] = this.name;
} else {
// json[r'name'] = null;
}
json[r'steps'] = this.steps;
json[r'trigger'] = this.trigger;
return json;
}
/// Returns a new [WorkflowShareResponseDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static WorkflowShareResponseDto? fromJson(dynamic value) {
upgradeDto(value, "WorkflowShareResponseDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return WorkflowShareResponseDto(
description: mapValueOfType<String>(json, r'description'),
name: mapValueOfType<String>(json, r'name'),
steps: WorkflowShareStepDto.listFromJson(json[r'steps']),
trigger: WorkflowTrigger.fromJson(json[r'trigger'])!,
);
}
return null;
}
static List<WorkflowShareResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <WorkflowShareResponseDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = WorkflowShareResponseDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, WorkflowShareResponseDto> mapFromJson(dynamic json) {
final map = <String, WorkflowShareResponseDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = WorkflowShareResponseDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of WorkflowShareResponseDto-objects as value to a dart map
static Map<String, List<WorkflowShareResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<WorkflowShareResponseDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = WorkflowShareResponseDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'description',
'name',
'steps',
'trigger',
};
}
+131
View File
@@ -0,0 +1,131 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class WorkflowShareStepDto {
/// Returns a new [WorkflowShareStepDto] instance.
WorkflowShareStepDto({
this.config = const {},
this.enabled,
required this.method,
});
/// Step configuration
Map<String, Object>? config;
/// Step is enabled
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
bool? enabled;
/// Step plugin method
String method;
@override
bool operator ==(Object other) => identical(this, other) || other is WorkflowShareStepDto &&
_deepEquality.equals(other.config, config) &&
other.enabled == enabled &&
other.method == method;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(config == null ? 0 : config!.hashCode) +
(enabled == null ? 0 : enabled!.hashCode) +
(method.hashCode);
@override
String toString() => 'WorkflowShareStepDto[config=$config, enabled=$enabled, method=$method]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
if (this.config != null) {
json[r'config'] = this.config;
} else {
// json[r'config'] = null;
}
if (this.enabled != null) {
json[r'enabled'] = this.enabled;
} else {
// json[r'enabled'] = null;
}
json[r'method'] = this.method;
return json;
}
/// Returns a new [WorkflowShareStepDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static WorkflowShareStepDto? fromJson(dynamic value) {
upgradeDto(value, "WorkflowShareStepDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return WorkflowShareStepDto(
config: mapCastOfType<String, Object>(json, r'config'),
enabled: mapValueOfType<bool>(json, r'enabled'),
method: mapValueOfType<String>(json, r'method')!,
);
}
return null;
}
static List<WorkflowShareStepDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <WorkflowShareStepDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = WorkflowShareStepDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, WorkflowShareStepDto> mapFromJson(dynamic json) {
final map = <String, WorkflowShareStepDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = WorkflowShareStepDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of WorkflowShareStepDto-objects as value to a dart map
static Map<String, List<WorkflowShareStepDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<WorkflowShareStepDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = WorkflowShareStepDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'config',
'method',
};
}
+131
View File
@@ -0,0 +1,131 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class WorkflowStepDto {
/// Returns a new [WorkflowStepDto] instance.
WorkflowStepDto({
this.config = const {},
this.enabled,
required this.method,
});
/// Step configuration
Map<String, Object>? config;
/// Step is enabled
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
bool? enabled;
/// Step plugin method
String method;
@override
bool operator ==(Object other) => identical(this, other) || other is WorkflowStepDto &&
_deepEquality.equals(other.config, config) &&
other.enabled == enabled &&
other.method == method;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(config == null ? 0 : config!.hashCode) +
(enabled == null ? 0 : enabled!.hashCode) +
(method.hashCode);
@override
String toString() => 'WorkflowStepDto[config=$config, enabled=$enabled, method=$method]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
if (this.config != null) {
json[r'config'] = this.config;
} else {
// json[r'config'] = null;
}
if (this.enabled != null) {
json[r'enabled'] = this.enabled;
} else {
// json[r'enabled'] = null;
}
json[r'method'] = this.method;
return json;
}
/// Returns a new [WorkflowStepDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static WorkflowStepDto? fromJson(dynamic value) {
upgradeDto(value, "WorkflowStepDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return WorkflowStepDto(
config: mapCastOfType<String, Object>(json, r'config'),
enabled: mapValueOfType<bool>(json, r'enabled'),
method: mapValueOfType<String>(json, r'method')!,
);
}
return null;
}
static List<WorkflowStepDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <WorkflowStepDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = WorkflowStepDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, WorkflowStepDto> mapFromJson(dynamic json) {
final map = <String, WorkflowStepDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = WorkflowStepDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of WorkflowStepDto-objects as value to a dart map
static Map<String, List<WorkflowStepDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<WorkflowStepDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = WorkflowStepDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'config',
'method',
};
}
@@ -11,9 +11,9 @@
part of openapi.api;
/// Plugin trigger type
class PluginTriggerType {
class WorkflowTrigger {
/// Instantiate a new enum with the provided [value].
const PluginTriggerType._(this.value);
const WorkflowTrigger._(this.value);
/// The underlying value of this enum member.
final String value;
@@ -23,22 +23,22 @@ class PluginTriggerType {
String toJson() => value;
static const assetCreate = PluginTriggerType._(r'AssetCreate');
static const personRecognized = PluginTriggerType._(r'PersonRecognized');
static const assetCreate = WorkflowTrigger._(r'AssetCreate');
static const personRecognized = WorkflowTrigger._(r'PersonRecognized');
/// List of all possible values in this [enum][PluginTriggerType].
static const values = <PluginTriggerType>[
/// List of all possible values in this [enum][WorkflowTrigger].
static const values = <WorkflowTrigger>[
assetCreate,
personRecognized,
];
static PluginTriggerType? fromJson(dynamic value) => PluginTriggerTypeTypeTransformer().decode(value);
static WorkflowTrigger? fromJson(dynamic value) => WorkflowTriggerTypeTransformer().decode(value);
static List<PluginTriggerType> listFromJson(dynamic json, {bool growable = false,}) {
final result = <PluginTriggerType>[];
static List<WorkflowTrigger> listFromJson(dynamic json, {bool growable = false,}) {
final result = <WorkflowTrigger>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = PluginTriggerType.fromJson(row);
final value = WorkflowTrigger.fromJson(row);
if (value != null) {
result.add(value);
}
@@ -48,16 +48,16 @@ class PluginTriggerType {
}
}
/// Transformation class that can [encode] an instance of [PluginTriggerType] to String,
/// and [decode] dynamic data back to [PluginTriggerType].
class PluginTriggerTypeTypeTransformer {
factory PluginTriggerTypeTypeTransformer() => _instance ??= const PluginTriggerTypeTypeTransformer._();
/// Transformation class that can [encode] an instance of [WorkflowTrigger] to String,
/// and [decode] dynamic data back to [WorkflowTrigger].
class WorkflowTriggerTypeTransformer {
factory WorkflowTriggerTypeTransformer() => _instance ??= const WorkflowTriggerTypeTransformer._();
const PluginTriggerTypeTypeTransformer._();
const WorkflowTriggerTypeTransformer._();
String encode(PluginTriggerType data) => data.value;
String encode(WorkflowTrigger data) => data.value;
/// Decodes a [dynamic value][data] to a PluginTriggerType.
/// Decodes a [dynamic value][data] to a WorkflowTrigger.
///
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
@@ -65,11 +65,11 @@ class PluginTriggerTypeTypeTransformer {
///
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
/// and users are still using an old app with the old code.
PluginTriggerType? decode(dynamic data, {bool allowNull = true}) {
WorkflowTrigger? decode(dynamic data, {bool allowNull = true}) {
if (data != null) {
switch (data) {
case r'AssetCreate': return PluginTriggerType.assetCreate;
case r'PersonRecognized': return PluginTriggerType.personRecognized;
case r'AssetCreate': return WorkflowTrigger.assetCreate;
case r'PersonRecognized': return WorkflowTrigger.personRecognized;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
@@ -79,7 +79,7 @@ class PluginTriggerTypeTypeTransformer {
return null;
}
/// Singleton [PluginTriggerTypeTypeTransformer] instance.
static PluginTriggerTypeTypeTransformer? _instance;
/// Singleton [WorkflowTriggerTypeTransformer] instance.
static WorkflowTriggerTypeTransformer? _instance;
}
@@ -0,0 +1,108 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class WorkflowTriggerResponseDto {
/// Returns a new [WorkflowTriggerResponseDto] instance.
WorkflowTriggerResponseDto({
required this.trigger,
this.types = const [],
});
WorkflowTrigger trigger;
/// Workflow types
List<WorkflowType> types;
@override
bool operator ==(Object other) => identical(this, other) || other is WorkflowTriggerResponseDto &&
other.trigger == trigger &&
_deepEquality.equals(other.types, types);
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(trigger.hashCode) +
(types.hashCode);
@override
String toString() => 'WorkflowTriggerResponseDto[trigger=$trigger, types=$types]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'trigger'] = this.trigger;
json[r'types'] = this.types;
return json;
}
/// Returns a new [WorkflowTriggerResponseDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static WorkflowTriggerResponseDto? fromJson(dynamic value) {
upgradeDto(value, "WorkflowTriggerResponseDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return WorkflowTriggerResponseDto(
trigger: WorkflowTrigger.fromJson(json[r'trigger'])!,
types: WorkflowType.listFromJson(json[r'types']),
);
}
return null;
}
static List<WorkflowTriggerResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <WorkflowTriggerResponseDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = WorkflowTriggerResponseDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, WorkflowTriggerResponseDto> mapFromJson(dynamic json) {
final map = <String, WorkflowTriggerResponseDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = WorkflowTriggerResponseDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of WorkflowTriggerResponseDto-objects as value to a dart map
static Map<String, List<WorkflowTriggerResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<WorkflowTriggerResponseDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = WorkflowTriggerResponseDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'trigger',
'types',
};
}
+85
View File
@@ -0,0 +1,85 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
/// Workflow type
class WorkflowType {
/// Instantiate a new enum with the provided [value].
const WorkflowType._(this.value);
/// The underlying value of this enum member.
final String value;
@override
String toString() => value;
String toJson() => value;
static const assetV1 = WorkflowType._(r'AssetV1');
static const assetPersonV1 = WorkflowType._(r'AssetPersonV1');
/// List of all possible values in this [enum][WorkflowType].
static const values = <WorkflowType>[
assetV1,
assetPersonV1,
];
static WorkflowType? fromJson(dynamic value) => WorkflowTypeTypeTransformer().decode(value);
static List<WorkflowType> listFromJson(dynamic json, {bool growable = false,}) {
final result = <WorkflowType>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = WorkflowType.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
}
/// Transformation class that can [encode] an instance of [WorkflowType] to String,
/// and [decode] dynamic data back to [WorkflowType].
class WorkflowTypeTypeTransformer {
factory WorkflowTypeTypeTransformer() => _instance ??= const WorkflowTypeTypeTransformer._();
const WorkflowTypeTypeTransformer._();
String encode(WorkflowType data) => data.value;
/// Decodes a [dynamic value][data] to a WorkflowType.
///
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
///
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
/// and users are still using an old app with the old code.
WorkflowType? decode(dynamic data, {bool allowNull = true}) {
if (data != null) {
switch (data) {
case r'AssetV1': return WorkflowType.assetV1;
case r'AssetPersonV1': return WorkflowType.assetPersonV1;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
}
}
}
return null;
}
/// Singleton [WorkflowTypeTypeTransformer] instance.
static WorkflowTypeTypeTransformer? _instance;
}
+16 -37
View File
@@ -13,24 +13,14 @@ part of openapi.api;
class WorkflowUpdateDto {
/// Returns a new [WorkflowUpdateDto] instance.
WorkflowUpdateDto({
this.actions = const [],
this.description,
this.enabled,
this.filters = const [],
this.name,
this.triggerType,
this.steps = const [],
this.trigger,
});
/// Workflow actions
List<WorkflowActionItemDto> actions;
/// Workflow description
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? description;
/// Workflow enabled
@@ -42,51 +32,41 @@ class WorkflowUpdateDto {
///
bool? enabled;
/// Workflow filters
List<WorkflowFilterItemDto> filters;
/// Workflow name
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? name;
List<WorkflowStepDto> steps;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
PluginTriggerType? triggerType;
WorkflowTrigger? trigger;
@override
bool operator ==(Object other) => identical(this, other) || other is WorkflowUpdateDto &&
_deepEquality.equals(other.actions, actions) &&
other.description == description &&
other.enabled == enabled &&
_deepEquality.equals(other.filters, filters) &&
other.name == name &&
other.triggerType == triggerType;
_deepEquality.equals(other.steps, steps) &&
other.trigger == trigger;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(actions.hashCode) +
(description == null ? 0 : description!.hashCode) +
(enabled == null ? 0 : enabled!.hashCode) +
(filters.hashCode) +
(name == null ? 0 : name!.hashCode) +
(triggerType == null ? 0 : triggerType!.hashCode);
(steps.hashCode) +
(trigger == null ? 0 : trigger!.hashCode);
@override
String toString() => 'WorkflowUpdateDto[actions=$actions, description=$description, enabled=$enabled, filters=$filters, name=$name, triggerType=$triggerType]';
String toString() => 'WorkflowUpdateDto[description=$description, enabled=$enabled, name=$name, steps=$steps, trigger=$trigger]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'actions'] = this.actions;
if (this.description != null) {
json[r'description'] = this.description;
} else {
@@ -97,16 +77,16 @@ class WorkflowUpdateDto {
} else {
// json[r'enabled'] = null;
}
json[r'filters'] = this.filters;
if (this.name != null) {
json[r'name'] = this.name;
} else {
// json[r'name'] = null;
}
if (this.triggerType != null) {
json[r'triggerType'] = this.triggerType;
json[r'steps'] = this.steps;
if (this.trigger != null) {
json[r'trigger'] = this.trigger;
} else {
// json[r'triggerType'] = null;
// json[r'trigger'] = null;
}
return json;
}
@@ -120,12 +100,11 @@ class WorkflowUpdateDto {
final json = value.cast<String, dynamic>();
return WorkflowUpdateDto(
actions: WorkflowActionItemDto.listFromJson(json[r'actions']),
description: mapValueOfType<String>(json, r'description'),
enabled: mapValueOfType<bool>(json, r'enabled'),
filters: WorkflowFilterItemDto.listFromJson(json[r'filters']),
name: mapValueOfType<String>(json, r'name'),
triggerType: PluginTriggerType.fromJson(json[r'triggerType']),
steps: WorkflowStepDto.listFromJson(json[r'steps']),
trigger: WorkflowTrigger.fromJson(json[r'trigger']),
);
}
return null;
+1
View File
@@ -5,6 +5,7 @@ export 'src/components/icon_button.dart';
export 'src/components/password_input.dart';
export 'src/components/text_button.dart';
export 'src/components/text_input.dart';
export 'src/components/url_input.dart';
export 'src/constants.dart';
export 'src/theme.dart';
export 'src/translation.dart';

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