1
0
forked from Cutlery/immich

Compare commits

...

291 Commits

Author SHA1 Message Date
mertalev 388e132fca use class provider directly 2024-03-22 23:00:29 -04:00
mertalev 43e0a59f93 set max 2024-03-22 21:44:17 -04:00
mertalev da34bd714e search, kysely extension 2024-03-22 21:40:32 -04:00
mertalev 77da10e3ab wip
wip

use prisma for paginated queries

remove migration file

redundant spread

simplified extend

use bigint for comparison

handle deleted assets in extension

Squashed commit of the following:

commit 64aac239f0
Author: Alex <alex.tran1502@gmail.com>
Date:   Thu Mar 21 18:00:22 2024 -0500

    chore: consolidate readme files (#8171)

commit d6823b128c
Author: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Date:   Thu Mar 21 23:59:21 2024 +0100

    fix(server): validation events actually throwing an error (#8172)

    * fix validation events

    * add e2e test

commit 508f32c08a
Author: martin <74269598+martabal@users.noreply.github.com>
Date:   Thu Mar 21 21:01:08 2024 +0100

    feat(web): improvements to slideshow (#8032)

    * feat: improvements to slideshow

    * feat: pause video with slideshow bar

    * pr feedback

    * fix: remove dispatch

    * fix: simplify

    * pr feedback

    * pr feedback

    ---------

    Co-authored-by: Alex Tran <alex.tran1502@gmail.com>

commit 8ed6ed4d2b
Author: Ethan Margaillan <ethan.margaillan@gmail.com>
Date:   Thu Mar 21 19:39:33 2024 +0100

    feat(web): rework context menus: add icons and reorder items (#8090)

commit 1abb0bdae8
Author: Fynn Petersen-Frey <10599762+fyfrey@users.noreply.github.com>
Date:   Thu Mar 21 17:51:03 2024 +0100

    feat(mobile): faster image loader (#8140)

    Co-authored-by: Alex Tran <alex.tran1502@gmail.com>

commit 5ef6215546
Author: martyfuhry <martyfuhry@gmail.com>
Date:   Thu Mar 21 12:31:18 2024 -0400

    chore(mobile): Bump to Flutter 3.19.0 (#7167)

    * Bump to Flutter 3.19.0

    * Ran pub upgrade --major-versions and removed isar_version alias

    Wrong http version

    * Updated share_plus to fix android build

    * Updates github actions to 3.19.0

    * upgrade to 3.19.3

    * upgrade to 3.19.3

    ---------

    Co-authored-by: Alex Tran <alex.tran1502@gmail.com>

commit 95fb9c4365
Author: waclaw66 <waclaw66@seznam.cz>
Date:   Thu Mar 21 18:23:06 2024 +0200

    fix(mobile): spacing fixes of #8087 (#8163)

    fix(mobile): spacing fix of https://github.com/immich-app/immich/pull/8087

commit fa0a5107c2
Author: aviv926 <51673860+aviv926@users.noreply.github.com>
Date:   Thu Mar 21 17:05:45 2024 +0200

    fix(docs): Immich quota claim note (#8151)

    * Add a note about immich_quota_claim.

    * Fix

    * PR feedback

    * npm run format:fix

    * use ¹

commit dc3c329431
Author: Jason Rasmussen <jrasm91@gmail.com>
Date:   Thu Mar 21 09:36:10 2024 -0500

    chore: remove unused type (#8157)

commit 2a9f2b4515
Author: Jason Rasmussen <jrasm91@gmail.com>
Date:   Thu Mar 21 09:08:29 2024 -0500

    refactor: app modules, main.ts (#8156)

commit 793049388b
Author: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
Date:   Thu Mar 21 14:44:54 2024 +0100

    refactor(web): cleanup notification components (#8150)

    * refactor(web): cleanup notification components

    * use counter for ID

commit 382b63954c
Author: Jason Rasmussen <jrasm91@gmail.com>
Date:   Thu Mar 21 08:07:47 2024 -0500

    refactor: asset v1, app.utils (#8152)

commit 87ccba7f9d
Author: Ben Basten <45583362+ben-basten@users.noreply.github.com>
Date:   Thu Mar 21 12:24:19 2024 +0000

    feat(web): keyboard access for search dropdown, combobox fixes (#8079)

    * feat(web): keyboard access for search dropdown

    Also: fixing cosmetic issue with combobox component.

    * fix: revert changing required field

    * fix: create new focusChange action

    * fix: combobox usability improvements

    * handle escape key on the clear button
    * move focus to input when clear button is clicked
    * leave the dropdown closed if the user has already closed the dropdown and tabs over to the clear button
    * activate the combobox if a user tabs backwards onto the clear button

    * rename focusChange to focusOutside

    * small fixes

    * do not activate combobox on backwards tabbing
    * simplify classes in "No results" option
    * prevent dropdown option from being preselected when clear button is
      clicked

    * fix: remove unused event dispatcher interface

commit e21c96c0ef
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Thu Mar 21 07:14:44 2024 -0500

    chore(deps): update redis:6.2-alpine docker digest to 3fcb624 (#8137)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 4de0b2f44e
Author: Ethan Margaillan <ethan.margaillan@gmail.com>
Date:   Thu Mar 21 13:14:13 2024 +0100

    feat(web): add ctrl+a / ctrl+d shortcuts to select / deselect all assets (#8105)

    * feat(web): use ctrl+a / ctrl+d to select / deselect all assets

    * fix(web): use shortcutList for ctrl+a / ctrl+d

    * fix(web): remove useless get()

    * feat(web): asset interaction store can now select many assets at once

commit b588a87d4a
Author: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Date:   Thu Mar 21 12:59:49 2024 +0100

    chore(server): rename domain `repositories` -> `interfaces` (#8147)

    rename domain repositories

commit 44ed1f0919
Author: Alex <alex.tran1502@gmail.com>
Date:   Thu Mar 21 00:18:38 2024 -0500

    fix(web): asset-grid padding/margin left fix (#8125)

    use media query for grid padding/margin size

commit 16d0df796c
Author: Jason Rasmussen <jrasm91@gmail.com>
Date:   Wed Mar 20 22:15:09 2024 -0500

    refactor: infra folder (#8138)

commit 9fd5d2ad9c
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Wed Mar 20 22:59:15 2024 -0400

    fix(deps): update machine-learning (#8057)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 28ad004b01
Author: Kirill <44521162+kirilldem@users.noreply.github.com>
Date:   Thu Mar 21 03:58:52 2024 +0100

    Update remote-machine-learning.md (#8038)

    * Update remote-machine-learning.md

    provide an example to use cuda or another container

    * Update docs/docs/guides/remote-machine-learning.md

    Co-authored-by: aviv926 <51673860+aviv926@users.noreply.github.com>

    * Update docs/docs/guides/remote-machine-learning.md

    ---------

    Co-authored-by: Mert <101130780+mertalev@users.noreply.github.com>
    Co-authored-by: aviv926 <51673860+aviv926@users.noreply.github.com>

commit ef4a492cb1
Author: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Date:   Thu Mar 21 00:07:30 2024 +0100

    chore(server): move services (#8133)

    move services

commit 6d9e7694b1
Author: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Date:   Wed Mar 20 23:53:07 2024 +0100

    chore(server): move dtos (#8131)

    move dtos

commit 0c13c63bb6
Author: Jason Rasmussen <jrasm91@gmail.com>
Date:   Wed Mar 20 16:46:59 2024 -0500

    refactor: infra/domain module (#8130)

commit 907eb869bc
Author: Jason Rasmussen <jrasm91@gmail.com>
Date:   Wed Mar 20 16:22:47 2024 -0500

    chore: move apps and test utils (#8129)

commit c1402eee8e
Author: Jason Rasmussen <jrasm91@gmail.com>
Date:   Wed Mar 20 16:02:51 2024 -0500

    chore: migrate database files (#8126)

commit 84f7ca855a
Author: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Date:   Wed Mar 20 21:42:58 2024 +0100

    chore(server): move domain interfaces (#8124)

    move domain interfaces

commit 2dcce03352
Author: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Date:   Wed Mar 20 21:25:33 2024 +0100

    chore(server): move commands (#8121)

    move commands

commit 96a22ec3c1
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Wed Mar 20 16:21:27 2024 -0400

    chore(deps): update base-image to v20240319 (major) (#8115)

    chore(deps): update base-image to v20240319

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 4b29bccc7c
Author: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Date:   Wed Mar 20 21:20:38 2024 +0100

    chore(server): move cores (#8120)

    move cores

commit 40e079a247
Author: Jason Rasmussen <jrasm91@gmail.com>
Date:   Wed Mar 20 15:15:01 2024 -0500

    chore: move controllers and middleware (#8119)

commit 81f0265095
Author: Jason Rasmussen <jrasm91@gmail.com>
Date:   Wed Mar 20 15:04:03 2024 -0500

    chore: organize config, validation, decorators (#8118)

    * refactor: validation

    * refactor: utilities

    * refactor: config

commit 92cc647cf6
Author: Jason Rasmussen <jrasm91@gmail.com>
Date:   Wed Mar 20 14:50:01 2024 -0500

    chore: renovate grouping (#8113)

commit 048d437b0b
Author: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
Date:   Wed Mar 20 20:40:41 2024 +0100

    fix(web): prevent duplicate time bucket loads (#8091)

commit ec9a6bca14
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Wed Mar 20 15:38:58 2024 -0400

    chore(deps): update dependency socket.io-client to v4.7.5 (#8111)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit bd5952b943
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Wed Mar 20 15:35:07 2024 -0400

    chore(deps): update vitest monorepo to v1.4.0 (#8112)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 3f0d54c752
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Wed Mar 20 15:34:12 2024 -0400

    fix(deps): update server (#8067)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit dab4595a4e
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Wed Mar 20 14:09:10 2024 -0500

    chore(deps): update redis:6.2-alpine docker digest to fd35357 (#8001)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 6d9ca82b19
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Wed Mar 20 14:08:01 2024 -0500

    chore(deps): update web (#8066)

    * chore(deps): update web

    * fix: linting

    ---------

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>

commit 373a03e819
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Wed Mar 20 14:06:58 2024 -0500

    chore(deps): update dependency @types/node to v20.11.28 (#8110)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit d97b0259fa
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Wed Mar 20 14:38:48 2024 -0400

    chore(deps): update node.js to bf77dc2 (#8063)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 2267ca1949
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Wed Mar 20 14:38:28 2024 -0400

    chore(deps): update node.js to 8765147 (#8058)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 29be53e70d
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Wed Mar 20 14:37:22 2024 -0400

    chore(deps): update prom/prometheus docker digest to 5ccad47 (#8071)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 851fe4a49f
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Wed Mar 20 14:33:41 2024 -0400

    chore(deps): update dependency @types/node to v20.11.28 (#8064)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 30f499cf2e
Author: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Date:   Wed Mar 20 19:32:04 2024 +0100

    chore(server): use absolute import paths (#8080)

    update server to use absolute import paths

commit 591a641d8d
Author: Alex <alex.tran1502@gmail.com>
Date:   Wed Mar 20 10:00:35 2024 -0500

    chore: post release tasks

commit 5b314ffd46
Author: Alex The Bot <alex.tran1502@gmail.com>
Date:   Wed Mar 20 14:50:57 2024 +0000

    Version v1.99.0

commit 0b078c9f99
Author: Alex <alex.tran1502@gmail.com>
Date:   Wed Mar 20 09:46:31 2024 -0500

    fix(web): Share button visible when viewing album has only shared link (#8100)

commit 0d5584ecbb
Author: Alex <alex.tran1502@gmail.com>
Date:   Wed Mar 20 09:28:19 2024 -0500

    fix(web): shift-select again (#8098)

commit 5e090646ba
Author: waclaw66 <waclaw66@seznam.cz>
Date:   Wed Mar 20 16:26:09 2024 +0200

    fix(mobile): missing "Add name" translation (#8087)

    fix(mobile): missing "Add name" translation, positioning

commit c4e910dd3d
Author: Mert <101130780+mertalev@users.noreply.github.com>
Date:   Wed Mar 20 10:20:46 2024 -0400

    docs(server): add documentation for prometheus metrics (#8084)

    * add monitoring doc

    * wording

    * indent

    * note instead of tip

    * Update docs/docs/features/monitoring.md

    Co-authored-by: bo0tzz <git@bo0tzz.me>

    * Update docs/docs/features/monitoring.md

    Co-authored-by: bo0tzz <git@bo0tzz.me>

    ---------

    Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
    Co-authored-by: bo0tzz <git@bo0tzz.me>

commit 5a2394af7c
Author: Alex <alex.tran1502@gmail.com>
Date:   Wed Mar 20 09:16:20 2024 -0500

    fix(web): shift-select (#8093)

    * fix(web): shift-select

    * remove unused code

    * proper fix

commit 48e32269f4
Author: Alex <alex.tran1502@gmail.com>
Date:   Wed Mar 20 09:16:00 2024 -0500

    chore: add prometheus.yml to release artifact (#8096)

commit dd9d90d21e
Author: Zack Pollard <zackpollard@ymail.com>
Date:   Wed Mar 20 06:31:52 2024 -0600

    test: temporarily disable flaky audit e2e test until #7436 is fixed (#8089)

commit 0544c687b9
Author: Ethan Margaillan <ethan.margaillan@gmail.com>
Date:   Wed Mar 20 13:29:30 2024 +0100

    fix(web): missing margin on people page (#8081)

commit e810aae212
Author: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
Date:   Wed Mar 20 13:24:08 2024 +0100

    fix(web): show search page errors and use feature flag (#8088)

commit 9c6a26de9f
Author: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
Date:   Wed Mar 20 05:41:31 2024 +0100

    chore(web): add asset store unit tests (#8077)

    chore(web): asset store unit tests

commit e6f2bb9f89
Author: Jonathan Jogenfors <jonathan@jogenfors.se>
Date:   Wed Mar 20 05:40:28 2024 +0100

    fix(server): use extension in originalFileName for libraries (#8083)

    * use file base

    * fix: test

    * fix: e2e-job tests

    ---------

    Co-authored-by: Alex Tran <alex.tran1502@gmail.com>

commit f908bd4a64
Author: Ethan Margaillan <ethan.margaillan@gmail.com>
Date:   Wed Mar 20 05:28:13 2024 +0100

    fix(web): prevent drag-n-drop upload overlay from showing when not dragging files (#8082)

commit 7395b03b1f
Author: Thariq Shanavas <thariqshanavas@gmail.com>
Date:   Tue Mar 19 22:12:36 2024 -0600

    fix(docs) minor security warning raised by Borg (#8075)

    * Fix minor borg security warning

    * Update template-backup-script.md

    * removed one unnecessary step

    * Clarified optional steps

    * Update template-backup-script.md

commit 63b4fc6f65
Author: Alex <alex.tran1502@gmail.com>
Date:   Tue Mar 19 23:07:26 2024 -0500

    chore(mobile): svg logo (#8074)

    * chore(mobile): anti-aliasing logo

    * use svg

    * adjust height

    * better sizing

commit f392fe7702
Author: Mert <101130780+mertalev@users.noreply.github.com>
Date:   Tue Mar 19 23:23:57 2024 -0400

    fix(server): "view all" for cities only showing 12 cities (#8035)

    * view all cities

    * increase limit

    * rename endpoint

    * optimize query

    * remove pagination

    * update sql

    * linting

    * revert sort by count in explore page for now

    * fix query

    * fix

    * update sql

    * move to search, add partner support

    * update sql

    * pr feedback

    * euphemism

    * parameters as separate variable

    * move comment

    * update sql

    * linting

commit 2daed747cd
Author: Mert <101130780+mertalev@users.noreply.github.com>
Date:   Tue Mar 19 22:42:10 2024 -0400

    chore(server): change `save` -> `update` in asset repository (#8055)

    * `save` -> `update`

    * change return type

    * include relations

    * fix tests

    * remove when mocks

    * fix

    * stricter typing

    * simpler type

commit 9e4bab7494
Author: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
Date:   Tue Mar 19 14:31:56 2024 +0000

    feat(mobile): drag to select assets (#8004)

    fear(mobile): drag to select assets

    Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
    Co-authored-by: Alex <alex.tran1502@gmail.com>

commit 9274c0701b
Author: waclaw66 <waclaw66@seznam.cz>
Date:   Tue Mar 19 16:22:44 2024 +0200

    fix(mobile): do not show hidden people (#8072)

    * fix(mobile): do not show hidden people

    * dart format fix

commit 0bc773fd00
Author: Alex <alex.tran1502@gmail.com>
Date:   Tue Mar 19 08:40:14 2024 -0500

    refactor(mobile): backup album selection (#8053)

    * feat(mobile): include album with 0 assets as album option for backup

    * Show icon instead of thumbnail

    * Handle backupProgress state transition correctly to always load the backup info

    * remove todo comment

commit c6d2408517
Author: Ben Basten <45583362+ben-basten@users.noreply.github.com>
Date:   Tue Mar 19 12:56:41 2024 +0000

    feat(web): combobox accessibility improvements (#8007)

    * bump skip link z index, to prevent overlap with the search box

    * combobox refactor initial commit

    * pull label into the combobox component

    * feat(web): combobox accessibility improvements

    * fix: replace crypto.randomUUID, fix border UI bug, simpler focus handling (#2)

    * fix: handle changes in the selected option

    * fix: better escape key handling in search bar

    * fix: remove broken tailwind classes

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

    * fix: remove custom "outclick" handler logic

    * fix: use focusout instead of custom key handlers to detect focus change

    * fix: move escape key handling to the window

    Also add escape key handling to the input box, to make sure that the "recent searches" dropdown gets closed too.

    * fix: better input event handling

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

    * fix: highlighting selected dropdown element

    ---------

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

commit 033f83a55a
Author: Jan <17313367+JW-CH@users.noreply.github.com>
Date:   Tue Mar 19 13:47:33 2024 +0100

    fix(docs): update authelia OIDC link (#8070)

commit 51841d627c
Author: Alex <alex.tran1502@gmail.com>
Date:   Mon Mar 18 22:39:49 2024 -0500

    fix(web): load panorama in shared link (#8060)

    * fix(web): load panorama in shared link

    * remove console log

commit 50924f0b3d
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Mon Mar 18 19:49:31 2024 -0400

    chore(deps): update dependency @types/node to v20.11.27 (#8012)

    * chore(deps): update dependency @types/node to v20.11.27

    * fixes

    * fixes

    ---------

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
    Co-authored-by: Marty Fuhry <martyfuhry@gmail.com>

commit 4aae1da841
Author: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Date:   Mon Mar 18 22:56:39 2024 +0100

    fix(web): repair page typo (#8051)

    fix typo

commit 1a2554548a
Author: bo0tzz <git@bo0tzz.me>
Date:   Mon Mar 18 22:54:30 2024 +0100

    chore: Simplify install script (#8048)

    * chore: Simplify install script

    The default .env file now contains a set UPLOAD_LOCATION already

    * fix: Remove leftover line

commit 40262c30cb
Author: Jason Rasmussen <jrasm91@gmail.com>
Date:   Mon Mar 18 15:59:53 2024 -0500

    refactor(server): library service (#8050)

    * refactor: library service

    * chore: open api

    * fix: checks

commit 761e7fdd2d
Author: Alex <alex.tran1502@gmail.com>
Date:   Mon Mar 18 14:46:52 2024 -0500

    feat(server): memory includes partners assets on timeline (#7993)

    * feat(server): memory includes partners assets on timeline

    * remove unsued code, generate sql

    * fix test

    * add test

commit cd8a124b25
Author: aviv926 <51673860+aviv926@users.noreply.github.com>
Date:   Mon Mar 18 16:00:11 2024 +0200

    feat(docs): User management new options (#8029)

    * User Management

    * Add photo

commit 148428a564
Author: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Date:   Sun Mar 17 20:16:02 2024 +0100

    feat(server): use nestjs events to validate config (#7986)

    * use events for config validation

    * chore: better types

    * add unit tests

    ---------

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

commit 14da671bf9
Author: Tyler Brockett <tylerbrockett@users.noreply.github.com>
Date:   Sun Mar 17 11:41:55 2024 -0700

    fix(docs): add microservices to IMMICH_CONFIG_FILE env var documentation (#8017)

commit e8f0f82db0
Author: Davide <22103897+dvdblg@users.noreply.github.com>
Date:   Sun Mar 17 18:48:59 2024 +0100

    feat(ml): add cache_dir option to OpenVINO EP (#8018)

    * add cache_dir option to OpenVINO EP

    * update provider options test to include cache_dir

    * use forward slash instead of string concatenation

    * fix cache_dir placement in provider options assertion

commit b8278404a0
Author: Alex <alex.tran1502@gmail.com>
Date:   Sun Mar 17 10:46:42 2024 -0500

    chore(docs): update readme (#8021)

commit 45671b0b8b
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Mar 16 15:34:49 2024 -0500

    chore(deps): update typescript-eslint monorepo to v7.2.0 (#8008)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

refactor
2024-03-21 21:08:28 -04:00
Alex 64aac239f0 chore: consolidate readme files (#8171) 2024-03-21 18:00:22 -05:00
Daniel Dietzler d6823b128c fix(server): validation events actually throwing an error (#8172)
* fix validation events

* add e2e test
2024-03-21 17:59:21 -05:00
martin 508f32c08a feat(web): improvements to slideshow (#8032)
* feat: improvements to slideshow

* feat: pause video with slideshow bar

* pr feedback

* fix: remove dispatch

* fix: simplify

* pr feedback

* pr feedback

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-21 15:01:08 -05:00
Ethan Margaillan 8ed6ed4d2b feat(web): rework context menus: add icons and reorder items (#8090) 2024-03-21 13:39:33 -05:00
Fynn Petersen-Frey 1abb0bdae8 feat(mobile): faster image loader (#8140)
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-21 11:51:03 -05:00
martyfuhry 5ef6215546 chore(mobile): Bump to Flutter 3.19.0 (#7167)
* Bump to Flutter 3.19.0

* Ran pub upgrade --major-versions and removed isar_version alias

Wrong http version

* Updated share_plus to fix android build

* Updates github actions to 3.19.0

* upgrade to 3.19.3

* upgrade to 3.19.3

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-21 11:31:18 -05:00
waclaw66 95fb9c4365 fix(mobile): spacing fixes of #8087 (#8163)
fix(mobile): spacing fix of https://github.com/immich-app/immich/pull/8087
2024-03-21 11:23:06 -05:00
aviv926 fa0a5107c2 fix(docs): Immich quota claim note (#8151)
* Add a note about immich_quota_claim.

* Fix

* PR feedback

* npm run format:fix

* use ¹
2024-03-21 15:05:45 +00:00
Jason Rasmussen dc3c329431 chore: remove unused type (#8157) 2024-03-21 14:36:10 +00:00
Jason Rasmussen 2a9f2b4515 refactor: app modules, main.ts (#8156) 2024-03-21 10:08:29 -04:00
Michel Heusschen 793049388b refactor(web): cleanup notification components (#8150)
* refactor(web): cleanup notification components

* use counter for ID
2024-03-21 09:44:54 -04:00
Jason Rasmussen 382b63954c refactor: asset v1, app.utils (#8152) 2024-03-21 09:07:47 -04:00
Ben Basten 87ccba7f9d feat(web): keyboard access for search dropdown, combobox fixes (#8079)
* feat(web): keyboard access for search dropdown

Also: fixing cosmetic issue with combobox component.

* fix: revert changing required field

* fix: create new focusChange action

* fix: combobox usability improvements

* handle escape key on the clear button
* move focus to input when clear button is clicked
* leave the dropdown closed if the user has already closed the dropdown and tabs over to the clear button
* activate the combobox if a user tabs backwards onto the clear button

* rename focusChange to focusOutside

* small fixes

* do not activate combobox on backwards tabbing
* simplify classes in "No results" option
* prevent dropdown option from being preselected when clear button is
  clicked

* fix: remove unused event dispatcher interface
2024-03-21 08:24:19 -04:00
renovate[bot] e21c96c0ef chore(deps): update redis:6.2-alpine docker digest to 3fcb624 (#8137)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-21 07:14:44 -05:00
Ethan Margaillan 4de0b2f44e feat(web): add ctrl+a / ctrl+d shortcuts to select / deselect all assets (#8105)
* feat(web): use ctrl+a / ctrl+d to select / deselect all assets

* fix(web): use shortcutList for ctrl+a / ctrl+d

* fix(web): remove useless get()

* feat(web): asset interaction store can now select many assets at once
2024-03-21 07:14:13 -05:00
Daniel Dietzler b588a87d4a chore(server): rename domain repositories -> interfaces (#8147)
rename domain repositories
2024-03-21 06:59:49 -05:00
Alex 44ed1f0919 fix(web): asset-grid padding/margin left fix (#8125)
use media query for grid padding/margin size
2024-03-21 00:18:38 -05:00
Jason Rasmussen 16d0df796c refactor: infra folder (#8138) 2024-03-20 23:15:09 -04:00
renovate[bot] 9fd5d2ad9c fix(deps): update machine-learning (#8057)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-20 22:59:15 -04:00
Kirill 28ad004b01 Update remote-machine-learning.md (#8038)
* Update remote-machine-learning.md

provide an example to use cuda or another container

* Update docs/docs/guides/remote-machine-learning.md

Co-authored-by: aviv926 <51673860+aviv926@users.noreply.github.com>

* Update docs/docs/guides/remote-machine-learning.md

---------

Co-authored-by: Mert <101130780+mertalev@users.noreply.github.com>
Co-authored-by: aviv926 <51673860+aviv926@users.noreply.github.com>
2024-03-20 22:58:52 -04:00
Daniel Dietzler ef4a492cb1 chore(server): move services (#8133)
move services
2024-03-20 18:07:30 -05:00
Daniel Dietzler 6d9e7694b1 chore(server): move dtos (#8131)
move dtos
2024-03-20 23:53:07 +01:00
Jason Rasmussen 0c13c63bb6 refactor: infra/domain module (#8130) 2024-03-20 16:46:59 -05:00
Jason Rasmussen 907eb869bc chore: move apps and test utils (#8129) 2024-03-20 17:22:47 -04:00
Jason Rasmussen c1402eee8e chore: migrate database files (#8126) 2024-03-20 21:02:51 +00:00
Daniel Dietzler 84f7ca855a chore(server): move domain interfaces (#8124)
move domain interfaces
2024-03-20 16:42:58 -04:00
Daniel Dietzler 2dcce03352 chore(server): move commands (#8121)
move commands
2024-03-20 20:25:33 +00:00
renovate[bot] 96a22ec3c1 chore(deps): update base-image to v20240319 (major) (#8115)
chore(deps): update base-image to v20240319

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-20 16:21:27 -04:00
Daniel Dietzler 4b29bccc7c chore(server): move cores (#8120)
move cores
2024-03-20 20:20:38 +00:00
Jason Rasmussen 40e079a247 chore: move controllers and middleware (#8119) 2024-03-20 16:15:01 -04:00
Jason Rasmussen 81f0265095 chore: organize config, validation, decorators (#8118)
* refactor: validation

* refactor: utilities

* refactor: config
2024-03-20 16:04:03 -04:00
Jason Rasmussen 92cc647cf6 chore: renovate grouping (#8113) 2024-03-20 15:50:01 -04:00
Michel Heusschen 048d437b0b fix(web): prevent duplicate time bucket loads (#8091) 2024-03-20 15:40:41 -04:00
renovate[bot] ec9a6bca14 chore(deps): update dependency socket.io-client to v4.7.5 (#8111)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-20 15:38:58 -04:00
renovate[bot] bd5952b943 chore(deps): update vitest monorepo to v1.4.0 (#8112)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-20 15:35:07 -04:00
renovate[bot] 3f0d54c752 fix(deps): update server (#8067)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-20 15:34:12 -04:00
renovate[bot] dab4595a4e chore(deps): update redis:6.2-alpine docker digest to fd35357 (#8001)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-20 14:09:10 -05:00
renovate[bot] 6d9ca82b19 chore(deps): update web (#8066)
* chore(deps): update web

* fix: linting

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-03-20 14:08:01 -05:00
renovate[bot] 373a03e819 chore(deps): update dependency @types/node to v20.11.28 (#8110)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-20 14:06:58 -05:00
renovate[bot] d97b0259fa chore(deps): update node.js to bf77dc2 (#8063)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-20 14:38:48 -04:00
renovate[bot] 2267ca1949 chore(deps): update node.js to 8765147 (#8058)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-20 14:38:28 -04:00
renovate[bot] 29be53e70d chore(deps): update prom/prometheus docker digest to 5ccad47 (#8071)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-20 14:37:22 -04:00
renovate[bot] 851fe4a49f chore(deps): update dependency @types/node to v20.11.28 (#8064)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-20 14:33:41 -04:00
Daniel Dietzler 30f499cf2e chore(server): use absolute import paths (#8080)
update server to use absolute import paths
2024-03-20 14:32:04 -04:00
Alex 591a641d8d chore: post release tasks 2024-03-20 10:00:35 -05:00
Alex The Bot 5b314ffd46 Version v1.99.0 2024-03-20 14:50:57 +00:00
Alex 0b078c9f99 fix(web): Share button visible when viewing album has only shared link (#8100) 2024-03-20 14:46:31 +00:00
Alex 0d5584ecbb fix(web): shift-select again (#8098) 2024-03-20 14:28:19 +00:00
waclaw66 5e090646ba fix(mobile): missing "Add name" translation (#8087)
fix(mobile): missing "Add name" translation, positioning
2024-03-20 14:26:09 +00:00
Mert c4e910dd3d docs(server): add documentation for prometheus metrics (#8084)
* add monitoring doc

* wording

* indent

* note instead of tip

* Update docs/docs/features/monitoring.md

Co-authored-by: bo0tzz <git@bo0tzz.me>

* Update docs/docs/features/monitoring.md

Co-authored-by: bo0tzz <git@bo0tzz.me>

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
Co-authored-by: bo0tzz <git@bo0tzz.me>
2024-03-20 09:20:46 -05:00
Alex 5a2394af7c fix(web): shift-select (#8093)
* fix(web): shift-select

* remove unused code

* proper fix
2024-03-20 09:16:20 -05:00
Alex 48e32269f4 chore: add prometheus.yml to release artifact (#8096) 2024-03-20 09:16:00 -05:00
Zack Pollard dd9d90d21e test: temporarily disable flaky audit e2e test until #7436 is fixed (#8089) 2024-03-20 07:31:52 -05:00
Ethan Margaillan 0544c687b9 fix(web): missing margin on people page (#8081) 2024-03-20 07:29:30 -05:00
Michel Heusschen e810aae212 fix(web): show search page errors and use feature flag (#8088) 2024-03-20 07:24:08 -05:00
Michel Heusschen 9c6a26de9f chore(web): add asset store unit tests (#8077)
chore(web): asset store unit tests
2024-03-19 23:41:31 -05:00
Jonathan Jogenfors e6f2bb9f89 fix(server): use extension in originalFileName for libraries (#8083)
* use file base

* fix: test

* fix: e2e-job tests

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-19 23:40:28 -05:00
Ethan Margaillan f908bd4a64 fix(web): prevent drag-n-drop upload overlay from showing when not dragging files (#8082) 2024-03-19 23:28:13 -05:00
Thariq Shanavas 7395b03b1f fix(docs) minor security warning raised by Borg (#8075)
* Fix minor borg security warning

* Update template-backup-script.md

* removed one unnecessary step

* Clarified optional steps

* Update template-backup-script.md
2024-03-19 23:12:36 -05:00
Alex 63b4fc6f65 chore(mobile): svg logo (#8074)
* chore(mobile): anti-aliasing logo

* use svg

* adjust height

* better sizing
2024-03-19 23:07:26 -05:00
Mert f392fe7702 fix(server): "view all" for cities only showing 12 cities (#8035)
* view all cities

* increase limit

* rename endpoint

* optimize query

* remove pagination

* update sql

* linting

* revert sort by count in explore page for now

* fix query

* fix

* update sql

* move to search, add partner support

* update sql

* pr feedback

* euphemism

* parameters as separate variable

* move comment

* update sql

* linting
2024-03-20 03:23:57 +00:00
Mert 2daed747cd chore(server): change save -> update in asset repository (#8055)
* `save` -> `update`

* change return type

* include relations

* fix tests

* remove when mocks

* fix

* stricter typing

* simpler type
2024-03-19 22:42:10 -04:00
shenlong 9e4bab7494 feat(mobile): drag to select assets (#8004)
fear(mobile): drag to select assets

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: Alex <alex.tran1502@gmail.com>
2024-03-19 14:31:56 +00:00
waclaw66 9274c0701b fix(mobile): do not show hidden people (#8072)
* fix(mobile): do not show hidden people

* dart format fix
2024-03-19 09:22:44 -05:00
Alex 0bc773fd00 refactor(mobile): backup album selection (#8053)
* feat(mobile): include album with 0 assets as album option for backup

* Show icon instead of thumbnail

* Handle backupProgress state transition correctly to always load the backup info

* remove todo comment
2024-03-19 08:40:14 -05:00
Ben Basten c6d2408517 feat(web): combobox accessibility improvements (#8007)
* bump skip link z index, to prevent overlap with the search box

* combobox refactor initial commit

* pull label into the combobox component

* feat(web): combobox accessibility improvements

* fix: replace crypto.randomUUID, fix border UI bug, simpler focus handling (#2)

* fix: handle changes in the selected option

* fix: better escape key handling in search bar

* fix: remove broken tailwind classes

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

* fix: remove custom "outclick" handler logic

* fix: use focusout instead of custom key handlers to detect focus change

* fix: move escape key handling to the window

Also add escape key handling to the input box, to make sure that the "recent searches" dropdown gets closed too.

* fix: better input event handling

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

* fix: highlighting selected dropdown element

---------

Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
2024-03-19 07:56:41 -05:00
Jan 033f83a55a fix(docs): update authelia OIDC link (#8070) 2024-03-19 07:47:33 -05:00
Alex 51841d627c fix(web): load panorama in shared link (#8060)
* fix(web): load panorama in shared link

* remove console log
2024-03-18 22:39:49 -05:00
renovate[bot] 50924f0b3d chore(deps): update dependency @types/node to v20.11.27 (#8012)
* chore(deps): update dependency @types/node to v20.11.27

* fixes

* fixes

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
Co-authored-by: Marty Fuhry <martyfuhry@gmail.com>
2024-03-18 19:49:31 -04:00
Daniel Dietzler 4aae1da841 fix(web): repair page typo (#8051)
fix typo
2024-03-18 21:56:39 +00:00
bo0tzz 1a2554548a chore: Simplify install script (#8048)
* chore: Simplify install script

The default .env file now contains a set UPLOAD_LOCATION already

* fix: Remove leftover line
2024-03-18 16:54:30 -05:00
Jason Rasmussen 40262c30cb refactor(server): library service (#8050)
* refactor: library service

* chore: open api

* fix: checks
2024-03-18 16:59:53 -04:00
Alex 761e7fdd2d feat(server): memory includes partners assets on timeline (#7993)
* feat(server): memory includes partners assets on timeline

* remove unsued code, generate sql

* fix test

* add test
2024-03-18 14:46:52 -05:00
aviv926 cd8a124b25 feat(docs): User management new options (#8029)
* User Management

* Add photo
2024-03-18 09:00:11 -05:00
Daniel Dietzler 148428a564 feat(server): use nestjs events to validate config (#7986)
* use events for config validation

* chore: better types

* add unit tests

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-03-17 20:16:02 +01:00
Tyler Brockett 14da671bf9 fix(docs): add microservices to IMMICH_CONFIG_FILE env var documentation (#8017) 2024-03-17 13:41:55 -05:00
Davide e8f0f82db0 feat(ml): add cache_dir option to OpenVINO EP (#8018)
* add cache_dir option to OpenVINO EP

* update provider options test to include cache_dir

* use forward slash instead of string concatenation

* fix cache_dir placement in provider options assertion
2024-03-17 13:48:59 -04:00
Alex b8278404a0 chore(docs): update readme (#8021) 2024-03-17 10:46:42 -05:00
renovate[bot] 45671b0b8b chore(deps): update typescript-eslint monorepo to v7.2.0 (#8008)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-16 15:34:49 -05:00
Michel Heusschen 321525ead5 fix(web): updating asset store after remove (#7999) 2024-03-16 09:22:15 -04:00
DeclanE 1d24e20d22 feat(doc) Updated feature-panel.png with the new logo (#7995)
* Updated feature-panel-withnewlogo

* Updated with new Feature Panel image from docs.
2024-03-16 00:59:58 -05:00
Mert 3a045b33ca chore(deps): update onnxruntime-openvino (#7854) 2024-03-16 00:04:45 -04:00
Mert a9438a9c2d fix(server): prevent feedback loop during library scan (#7944)
* prevent feedback loop

* add nesting

* made nesting less ugly

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-15 22:01:58 +00:00
renovate[bot] eea0a98090 chore(deps): update machine-learning (#7890) 2024-03-15 17:19:28 -04:00
Alex a491240aeb fix(doc): logo size on small screen (#7992) 2024-03-15 15:59:25 -05:00
renovate[bot] 8c24a994e1 fix(deps): update exiftool (#7879)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-15 15:40:32 -05:00
sevtdy 64f53e674c feat(web): add millisecond options to storage template settings (#7942)
* feat(web): add millisecond options storage template settings

* fix(web): fix test

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-15 20:13:08 +00:00
Aegeontis 54fdf33fd9 Make mobile app a "media management app" to get rid of android prompt (#7851)
Make mobile app a "media management app"
2024-03-15 15:11:28 -05:00
Michel Heusschen 997e9c5877 refactor(web): list navigation with keyboard (#7987) 2024-03-15 15:00:53 -05:00
Michel Heusschen e21c586cc5 fix(web): logo invisible on share page (#7990) 2024-03-15 14:53:58 -05:00
renovate[bot] abedfd1015 chore(deps): pin prom/prometheus docker tag to bc1794e (#7874)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-15 12:57:36 -04:00
Jason Rasmussen 2a0e1c0d3c refactor: global validation pipe (#7985)
* refactor: global validation pipe

* chore: formatting
2024-03-15 12:51:08 -04:00
Michel Heusschen 5a6b71dda3 perf(web): batch asset store changes (#7974)
* perf(web): batch asset store changes

* update external calls to assetstore
2024-03-15 12:11:29 -04:00
Michel Heusschen a3dfa27a53 chore(web): remove unused AssetSelectionViewer (#7981) 2024-03-15 12:04:54 -04:00
Michel Heusschen cfb14ca80b fix(web): minor album card issues (#7975)
* fix(web): minor album card issues

* fix album grid gap
2024-03-15 12:03:54 -04:00
DeclanE 0f79c4ff46 feat(server): added support for SVG files (#7960)
* Added SVG Support

* Removed comment

* Server Test fixes

* Sorted the mimetypes

* Reverted mimetypes.assettype

* Lint

* fix test

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-15 16:02:31 +00:00
Michel Heusschen 029dd99ae0 fix(web): improve focus and shortcuts (#7983)
* fix(web): improve focus and shortcuts

* fix shiftKeyIsDown
2024-03-15 12:01:35 -04:00
Daniel Dietzler a46366d336 chore(server): introduce proper job status (#7932)
* introduce proper job status

* fix condition for onDone jobs

* fix tests
2024-03-15 09:16:54 -04:00
Jason Rasmussen 07e8f79563 refactor: library e2e (#7969) 2024-03-15 09:16:08 -04:00
Alex 9ed7de50e7 feat(doc): new logo and screenshots (#7961)
* feat(doc): new logo and screenshots

* remove unused logo

* logo with text

* feature panel

* remove logo explaination
2024-03-14 22:15:20 -05:00
Michel Heusschen eed8e6b67a fix(web): keyboard shortcut handling (#7946)
* fix(web): keyboard shortcut handling

* drop executeShortcuts in favor of action

* fix merge

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-03-14 23:16:55 +00:00
Jason Rasmussen 12fb90c232 refactor(cli): simplify (#7962)
* refactor(cli): yup

* fix missing return for authenticate

---------

Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
2024-03-14 19:09:28 -04:00
Sam Holton cda45f9bfb feat(web): randomize password on reest (#7943)
* feat(web): randomize password on reest

* prettier

* chore: clean up

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-03-14 21:33:39 +00:00
Sam Holton ab4b8eca15 feat(web): preload assets in photo-viewer (#7920)
* feat(web): preload assets in photo-viewer

* PR feedback

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-14 16:12:32 -05:00
martyfuhry 582cdcab82 feat(mobile): Remote thumbnails and images use an on-disk image cache (#7929)
* Fixes remote full / thumbnail provider

* Adds image cache manager to both remote image providers

format

format

Fix typo in equals

remove unused import

renames image loader

* Adds height and width to the image cache for thumbs

format

* Uses a separate remote and thumbnail cache

format

* Fixes key name

* Changes uri to string, fixes comment

* Chunk events are optional and remote thumbnails don't report chunk events

* better exception handling

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-14 15:29:09 -05:00
Jason Rasmussen 5a589babcb chore(cli): use lockfile v3 (#7958) 2024-03-14 16:19:07 -04:00
Jason Rasmussen 0b8edb7671 chore: remove unused dep (#7957) 2024-03-14 16:18:55 -04:00
Ben 9bd79ffc00 feat(mobile): Adds file upload progress stats (#7760)
* feat(mobile): Adds file upload progress stats: current upload file size uploaded, current file size and formatted bytes per second upload speed. Closes #7379

* chore(mobile): Fix stan issues

* chore(mobile): Remove non-'en-US' translations, as I saw on another PR review (just looking around) that localisation is done via Localizely and this was the instruction (to only provide the en-US localisation).

* fix(mobile): Provide boundary checks to ensure overflow issues are accounted for on erroneous upload speed calculation, sometimes the numbers received back from the upload handler can be a bit wild.

* fix(mobile): Some heuristic bug fixing. Whilst thinking what could trigger overflow issues or 'zero' readouts, left over values from the previous file may do that. So adding the last upload sent bytes to the values to be reset may help! The time isn't necessary, as the period/cycle is inconsequential in this circumstance, well it should be anyway.

* fix(mobile): Actually, in combination to the last commit, some more heuristic bug fixing. I was thinking it would be advantageous not to reset the update time, as it would trigger a quicker first upload speed calculation. However, I realised that could also cause the calculation to be incorrect on the first cycle as the period wouldn't align. Not really sure if it would be a big deal, but I'm taking wild guesses in the dark here. Again, some purely heuristic debugging as I can't re-produce the underlying issue. This is mainly just ensuring that the state is fully reset and is a known state at the beginning of each file as a common strategy to reduce issues.

* refactor(mobile): Move the UI for the file progress to underneath the progress bar, it makes more sense there than in the file information table which contains only static information pertaining to the file itself. Switching to a monospace font to keep the UI from jumping around as the numbers change.

* refactor(mobile): In order to have the UI always present an 'active' upload speed (as per the discussion on PR #7760), this stores the 'upload speeds' (capped at the latest 10) in a list and calculates the current upload speed as the average over them. This way the UI can always display a 'constant' upload speed during uploading, instead of starting a fresh when each file starts uploading. Limiting it to the 10 latest keeps the average somewhat recent and ensures some level of sensible memory allocation.
2024-03-14 15:15:22 -05:00
martin c04dfdf38b refactor(web): albums list (1) (#7660)
* refactor: albums list

* fix: rename filename

* chore: fix merge

* pr feedback

* chore: fix merge

* pr feedback

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-14 14:05:57 -05:00
Jason Rasmussen 2080aeee4d chore(cli): clean up files (#7955) 2024-03-14 13:09:27 -04:00
martin 31f7e1aca3 feat(server, web): album orders (#7819)
* feat: album orders

* fix: tests

* pr feedback

* pr feedback

* pr feedback

* fix: tests

* add comment

* pr feedback

* fix: rendering issue

* wording

* fix: order value doesn't change

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-14 11:45:03 -05:00
bo0tzz 1c4637cb43 chore(ci): Clean up docker buildx workaround (#7949)
Co-authored-by: Alex <alex.tran1502@gmail.com>
2024-03-14 10:16:33 -05:00
aviv926 559565d6a7 chore(web): Sharing -> Partner Sharing (#7952) 2024-03-14 10:16:20 -05:00
Jonathan Jogenfors ba38713fbc fix(server): queue library asset refresh in batches (#7914)
* add debug logs

* scan assets in batches

* Cleanup

* don't normalize

* Removing extra log

* remove unneeded code

* change log levels
2024-03-14 14:43:05 +01:00
thielepaul 428b7b0c4e fix(mobile): make elements scrollable to avoid overflow in landscale (#7933)
fix(mobile): make elements scrollable to avoid overflow in landscape
2024-03-14 12:28:18 +00:00
dependabot[bot] 2f78bff97c chore(deps): bump docker/setup-buildx-action from 3.1.0 to 3.2.0 (#7948)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v3.1.0...v3.2.0)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-14 07:55:55 -04:00
dependabot[bot] a85b147b3a chore(deps): bump docker/build-push-action from 5.2.0 to 5.3.0 (#7947)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5.2.0...v5.3.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-14 07:55:46 -04:00
Mert ee8e8a0c0f perf(server): optimize getByIds query (#7918)
* clean up usage

* i'm not updating all these tests

* update tests

* add indices

* add indices to entities

remove index from person entity

add to face entity

fix

* simplify query

* update sql

* missing await

* remove synchronize false
2024-03-14 01:58:09 -04:00
Mert d67cc00e4e feat(server): lower library scan memory usage (#7939)
* use trie

* update tests

* formatting

* pr feedback

* linting
2024-03-14 01:52:30 -04:00
Alex 63d252b603 fix(web): FullScreenContainer logo (#7938) 2024-03-14 02:00:22 +00:00
mmomjian bd88a241ff docs: Update backup script example (#7734)
* Update backup script example

* Update template-backup-script.md

* Update template-backup-script.md

* Update template-backup-script.md

* Update template-backup-script.md

* Update template-backup-script.md

* Update template-backup-script.md
2024-03-13 13:08:01 -05:00
Alex 76432341ed feat(mobile): update logo (#7919)
* App Icon

* In App Icon

* runner

* ios icon

* ios is done

* splash

* Notification Icon

* Immich text

* Immich text

* actually update andoir icon

* adaptive icon

* adaptive icon
2024-03-13 12:14:59 -05:00
Alex ff2f4f8ed8 feat(web): update logo (#7798)
* feat(web): update logo

* favicon

* no text logo on small screen

* correct break point
2024-03-13 12:14:45 -05:00
Kokul Shanmugharajah 29c3a826c5 feat(server): Update XMP sidecar search to look for both photo.ext.xmp and photo.xmp (#7813)
* Add support for photo.xmp sidecars

* format

* Add comment

* Proper handling

* Handle mocking better

* Address PR feedback

* Add test coverage if both xmp files exist

* Update server/src/domain/metadata/metadata.service.ts

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

* Update server/src/domain/metadata/metadata.service.ts

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

* Update server/src/domain/metadata/metadata.service.ts

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

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-03-13 12:14:26 -05:00
Andrew Rowson 37e5b91dc2 fix(server): ml gunicorn listen on ipv4 and ipv6 by default (#7930) 2024-03-13 12:13:56 -05:00
renovate[bot] d67a6b7293 fix(deps): update server (#7898)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-13 12:54:46 -04:00
Daniel Dietzler 054df27929 fix(web): url state of nested accordions (#7928)
* fix url state of nested accordions

* Use existing method to update state

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

---------

Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
2024-03-13 11:15:51 -04:00
DeclanE 2b1def4e7c fix(blog/docs): Fix Milestone linking for "multi select" and "View Exif" fix(docs): Update "zoodyy" to "yfrey" (#7926)
Fix Milestone linking for "multi select" and "View Exif" on Blog; update "zoodyy" to "yfrey" in Docs
2024-03-13 09:41:15 -05:00
martyfuhry 08d64f1c25 chore(mobile): Removes analysis options for openapi directory (#7309)
* Removes analysis options for openapi directory

* Updates the generate open api script to remove the analysis_options.yaml file from the mobile/openapi directory
2024-03-13 09:27:52 -04:00
DeclanE a7efd66ae9 fix(web): Enhance Notification Handling for Duplicate Assets (#7858)
* Duplicate reporting in upload panel file-uploader.ts

* Update upload-panel.svelte

* Reimplement Error reporting upload-panel.svelte

* Update upload-panel.svelte

* Run Prettier again

* Update web/src/lib/components/shared-components/upload-panel.svelte

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

* Ran Prettier

* Update web/src/lib/components/shared-components/upload-panel.svelte

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

* Run Prettier final

* Update web/src/lib/components/shared-components/upload-panel.svelte

Removed odd "``;"

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

---------

Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-13 01:37:56 +00:00
natedawg 92804fe4b2 fix(web): Remove excess spacing on #asset-grid and search bar (#7910)
* fix(web): Remove excess left-margin on #asset-grid

* fix(web): Remove excess left-padding on search bar

---------

Co-authored-by: natedawg <nate@natedawg.net>
2024-03-12 21:03:37 -04:00
Michel Heusschen b07ed3f615 fix(web): correctly use button and link elements (#7907) 2024-03-12 15:30:19 -04:00
renovate[bot] 67b209808f fix(deps): update web (#7872)
* fix(deps): update web

* update types to follow map types

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
2024-03-12 15:28:29 -04:00
Michel Heusschen 82aabc63f5 fix(web): prevent combobox options from disappearing (#7733) 2024-03-12 14:21:42 -05:00
Jason Rasmussen 17d7d9364f chore: publish sdk on release (#7895)
* chore: publish sdk on release

* fix: runtime dep

* chore: sync versions

* chore: update readme

* fix: use Node16 module resolution
2024-03-12 12:01:12 -04:00
ztz 779f5d9b3d feat(web): dark color-scheme css for dark mode (#7812)
* feat(web): dark color-scheme css for dark mode

* use dark classes instead of adding data property

* fix code format

* fix typo

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-12 15:48:23 +00:00
renovate[bot] 83198ef595 chore(deps): update grafana/grafana docker tag to v10.4.0 (#7875)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-12 10:32:19 -05:00
DeclanE 412c9bc76d feat(web): Implemented device last seen date and time with user locale support (#7863)
* Implemented last seen date and time with user locale support

* Run Prettier

* Prettier and Linter

* Updated last seen to be in line with suggestions

* Reworked datestamp
2024-03-12 10:31:46 -05:00
bo0tzz 72f9295490 feat(server): YAML config file support (#7894)
* test(server): Load config from yaml

* docs: YAML config support

* feat(server): YAML config file support

* fix format

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-12 16:29:49 +01:00
renovate[bot] 1683bb75e1 fix(deps): update server (#7880) 2024-03-12 11:28:45 -04:00
Ben Basten 727a8cd715 feat(mobile): add labels to app bar buttons (#7865) 2024-03-12 10:12:11 -05:00
shenlong 7489db9481 refactor(mobile): app settings (#7749)
* refactor(mobile): app settings

* Font size

* refactor(mobile): backup settings ui (#7771)

* refactor: SettingsButtonListTile

* refactor: Backup settings to App settings

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>

* fix: invalidate appsettingsprovider on timeline setting change

* styling

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-12 14:56:08 +00:00
dependabot[bot] 4733de25af chore(deps): bump softprops/action-gh-release from 1 to 2 (#7844)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 09:31:09 -04:00
Michel Heusschen c24b6cf617 refactor(web): sidebar menu links (#7891) 2024-03-12 09:11:16 -04:00
bo0tzz 6bfa1fceec chore(cli): Version 2.1.0 (#7893) 2024-03-12 12:11:40 +00:00
Michel Heusschen 41504b9a2c fix(web): asset viewer navigation buttons (#7888) 2024-03-12 08:09:11 -04:00
renovate[bot] 3cd232f571 chore(deps): update base-image to v20240312 (major) (#7892)
chore(deps): update base-image to v20240312

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-12 08:07:56 -04:00
Michel Heusschen 1b8844cb4a fix(web): asset upload progress (#7882) 2024-03-12 07:19:38 -04:00
Mert a097e903c9 feat(server): OpenTelemetry integration (#7356)
* wip

* span class decorator

fix typing

* improvements

* noisy postgres logs

formatting

* add source

* strict string comparison

Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>

* remove debug code

* execution time histogram

* remove prometheus stuff

remove prometheus data

* disable by default

disable nestjs-otel stuff by default

update imports

* re-add postgres instrumentation

formatting

formatting

* refactor: execution time histogram

* decorator alias

* formatting

* keep original method order in filesystem repo

* linting

* enable otel sdk in e2e

* actually enable otel sdk in e2e

* share exclude paths

* formatting

* fix rebase

* more buckets

* add example setup

* add envs

fix

actual fix

* linting

* update comments

* update docker env

* use more specific env

---------

Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-03-12 05:19:12 +00:00
Slavik def82a7354 docs: config-file.md update config to current (v1.98) state (#7808)
* docs: config-file.md update config to current (v1.98) state

* fix format

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-12 03:46:42 +00:00
DeclanE a94e45260e fix: Hide play bar when there's only one image in memory (#7764)
* fix: Hide play bar when there's only one image in memory

This commit introduces a fixto hide the play bar at the top of the memory viewer when there's only one image in the memory. Previously, the play bar was displayed regardless of the number of images, leading to unnecessary UI elements for single-image memories.

* Update web/src/lib/components/memory-page/memory-viewer.svelte

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

---------

Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-12 03:36:34 +00:00
Dhrumil Shah bbed14a9ff feat(server): Add OAuth auto-redirect enable/disable CLI commands (#7841)
* Rebase

* format fix

* docs format

* Change to enable/disable oauth master

* spell change for oauth

* Fix filename
2024-03-11 23:32:00 -04:00
Mert d09980f646 chore(cli): clarify use of concurrency option (#7840)
* add <number>

* add e2e tests

* add test with number
2024-03-11 23:30:13 -04:00
Slavik e732cb68a7 docs: backup-and-restore.md: fix broken link (#7806)
backup-and-restore.md: fix broken link
2024-03-11 22:27:31 -05:00
renovate[bot] 4b4ebe4f80 fix(deps): update machine-learning (#7871)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-11 23:26:43 -04:00
Nicholas Flamy 7b5ff397b3 Fix trash permanent delete dialog (#7805)
* Fix Outdated Info for Deletion

* Undo Flutter Updating Dependencies
2024-03-11 22:25:55 -05:00
renovate[bot] 4b6206b32d chore(deps): update server (#7869)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-11 23:22:55 -04:00
renovate[bot] faab3aab0a fix(deps): update docs (#7870)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-11 23:21:29 -04:00
martyfuhry a1130b3e27 fix(mobile): Fixes local thumbnail image provider key (#7766)
* Fixes large and small image cache

* Fixes local thumb provider key

format

* format

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-12 03:04:52 +00:00
martyfuhry de28f83d0d fix(mobile): Fixes immersive mode not ending for memory lane (#7767)
Fixes immersive mode not ending for memory lane
2024-03-11 22:02:28 -05:00
Michel Heusschen b7e5407822 fix(web): small fixes for empty placeholder (#7859) 2024-03-11 21:18:47 -04:00
renovate[bot] 4023c665cc chore(deps): update dependency @types/node to v20.11.25 (#7860)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-11 21:17:09 -04:00
renovate[bot] 7aa75d5643 chore(deps): update dependency typescript to v5.4.2 (#7861)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-11 21:16:42 -04:00
renovate[bot] cfece31649 chore(deps): update @immich/cli (#7866)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-11 21:16:22 -04:00
renovate[bot] a326f7c833 chore(deps): update open-api (#7867)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-11 21:15:57 -04:00
Ben McCann 078da36f20 fix(server): serve static directory only if it exists (#7857)
* fix(server): serve static directory only if it exists

* update

* refactor: web root

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-03-11 13:06:04 -04:00
Tejpal Sahota 6c8fad4cac docs: Update external-library.md (#7850)
Although it is written clearly directly below, showing an example of what to change for both containers makes it very clear for people who just skim the code sections.
2024-03-11 17:02:55 +00:00
markeeisner 8c3ff65402 docs: Add guide for album sync python script (#7736)
* Add guide for album sync python script

* Add newline for formatting test

* Run prettier

* fix hardcoded url and extension

* brevity

Co-authored-by: Mert <101130780+mertalev@users.noreply.github.com>

* more brevity with copy and paste facepalm

Co-authored-by: Mert <101130780+mertalev@users.noreply.github.com>

* grammar fix

Co-authored-by: Mert <101130780+mertalev@users.noreply.github.com>

---------

Co-authored-by: Mert <101130780+mertalev@users.noreply.github.com>
2024-03-11 11:55:21 -05:00
Sam Holton b33cb5fe3f feat(web): add preference for thumbnail playback on hover (#7831)
* feat(web): add preference for thumbnail playback on hover

* pr feedback, add user settings behavior setting

* user settings consistency

* rename appearance to app settings

* collapse single trash setting into app settings
2024-03-11 12:45:01 -04:00
Jason Rasmussen 84453d2e34 fix: immich logo links (#7856) 2024-03-11 11:25:05 -05:00
Alex d069ad5be4 Update and rename Immich-logo-inline-dark.svg to immich-logo-inline-dark.svg 2024-03-11 11:23:03 -05:00
Alex f1fa88a67e Rename Immich-logo-inline-light.png to immich-logo-inline-light.png 2024-03-11 11:22:52 -05:00
Alex 6aa4f2e67e Update and rename Immich-logo-inline-light.svg to immich-logo-inline-light.svg 2024-03-11 11:22:41 -05:00
Alex 053e8509a5 Rename Immich-logo-stacked-dark.png to immich-logo-stacked-dark.png 2024-03-11 11:22:25 -05:00
Alex d865e98e6f Update and rename Immich-logo-stacked-dark.svg to immich-logo-stacked-dark.svg 2024-03-11 11:22:10 -05:00
Alex 70d196dbdb Rename Immich-logo-stacked-light.png to immich-logo-stacked-light.png 2024-03-11 11:21:41 -05:00
Alex ea2755a559 Update and rename Immich-logo-stacked-light.svg to immich-logo-stacked-light.svg 2024-03-11 11:21:24 -05:00
Alex 932dd3c885 Rename Immich-logo-inline-dark.png to immich-logo-inline-dark.png 2024-03-11 11:21:05 -05:00
Alex 2de9a92fba chore: update readme with new logo and add design materials (#7852)
* chore: readme logo

* design material
2024-03-11 11:16:57 -05:00
Jason Rasmussen a41ffb5131 feat(web): empty external library placeholder (#7848) 2024-03-11 10:29:21 -05:00
Alex ae34e4f59f chore: post release tasks 2024-03-11 09:48:25 -05:00
Mert 8dc62bd29a fix(server): face search results not always sorted (#7839)
* order by

* update sql
2024-03-11 09:19:20 -05:00
Alex The Bot 4027cba4eb Version v1.98.2 2024-03-11 14:17:12 +00:00
Mert 5bd597f14b fix(server): external library sync not working for large libraries (#7759) 2024-03-10 22:30:57 -04:00
Ghazi Tounsi 49d9051879 fix(mobile): archive desc sorting (#7822)
desc sort
2024-03-10 21:15:34 -05:00
DeclanE e5978981f3 Fix: Disable 'As profile picture' option for videos in context menu a… (#7830)
* Fix: Disable 'As profile picture' option for videos in context menu asset-viewer-nav-bar.svelte

This commit modifies the context menu behavior to disable the "As profile picture" option when interacting with video assets. Previously, the option was available for all asset types, including videos, which could lead to confusion when this displayed an error.

With this change, the "As profile picture" option is conditionally rendered based on the asset type. If the asset is a video, the option is not displayed in the context menu.

This adjustment enhances the web experience by preventing users from attempting to set a video as their profile picture, which is not supported by the system.

Fixes: #7724

* Switched to check if photo instead of video
2024-03-10 18:32:27 -04:00
Sam Holton d257cdcbbf feat(web): add sticky date headers for asset-date-group (#7824)
* feat(web): add sticky date headers for asset-date-group

* use existing classes
2024-03-10 15:32:05 -04:00
Daniel Dietzler 60c521101a chore(server): type checks for e2e (#7800)
type checks for e2e
2024-03-09 23:18:25 +00:00
Daniel Dietzler 11e7533a4d chore(server): user e2e: wait for user delete event (#7799)
* wait for user delete event

* fix update event names

* add test for hard deletion of user
2024-03-10 00:10:24 +01:00
Daniel Dietzler ec8fb0be83 chore(server): remove unused storage repository variable from microservices app service (#7797)
remove unused storage repository from microservices app service
2024-03-09 16:06:31 -05:00
Alex a6cd4b8427 chore(server): openapi (#7794)
* chore(server): openapi

* openapi
2024-03-09 14:01:52 -06:00
renovate[bot] 3bdd2612ce chore(deps): update typescript-eslint monorepo to v7.1.1 (#7790)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-09 13:33:11 -05:00
Jason Rasmussen 30b0b2474e refactor: asset e2e (#7769) 2024-03-09 12:51:58 -05:00
martin 8eb9dad989 fix: update e2e (#7710)
* fix: update e2e

* update package.json

* fix: version
2024-03-08 23:16:36 -05:00
Fynn Petersen-Frey 3f1d37e556 feat(server): hardware HDR tonemapping for RKMPP (#7655)
* feat(server): hardware HDR tonemapping for RKMPP

* review feedback
2024-03-08 21:17:26 -05:00
Ben McCann ba55e867e0 perf: precompress and cache assets (#7757)
* perf: precompress and cache assets

* fix cache header

* use startswith

---------

Co-authored-by: mertalev <101130780+mertalev@users.noreply.github.com>
2024-03-08 21:15:38 -05:00
Alex 4fdb0835c9 chore: post release tasks 2024-03-08 19:08:33 -06:00
Alex The Bot 430561d692 Version v1.98.1 2024-03-08 23:44:13 +00:00
Alex e8fb529026 fix(server): getAllAssets doesn't return all assets (#7752)
* fix(server): getAllAssets doesn't return all assets

* try reverting

* fix: archive and remove unused method

* update sql

* remove unused code

* linting
2024-03-08 17:16:32 -06:00
Sam Holton 7a4ae7d142 feat(server,web): add force delete to immediately remove user (#7681)
* feat(server,web): add force delete to immediately remove user

* update wording on force delete confirmation

* fix force delete css

* PR feedback

* cleanup user service delete for force

* adding user status column

* some cleanup and tests

* more test fixes

* run npm run sql:generate

* chore: cleanup and websocket

* chore: linting

* userRepository.restore

* removed bad color class from delete-confirm-dialoge

* additional confirmation for user force delete

* shorten confirmation message

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-03-08 17:49:39 -05:00
Andrew Roberts 9cb0a1ffbf fix(web): modal password reset modal in dark mode (#7748)
* Fixed dark mode password reset success

* Fixed prettier issue
2024-03-08 14:05:15 -05:00
Michel Heusschen fa32c6660c fix(web): album state after removing assets (#7745)
* fix(web): album state after removing assets

* refresh album on remove + simplify AlbumSummary
2024-03-08 14:03:37 -05:00
DeclanE fe8c6b17a6 chore: rename "Library" to "External Library" in system settings (#7744)
* Change "Library" > "External Library" under system settings

This is intended to assist with any confusion regarding standard libraries

* Changed key from "library" to "external-library"

* Updated "Encode Clip" to "Smart Search"
2024-03-08 16:49:44 +00:00
Jason Rasmussen 89f6190fb0 refactor: search e2e (#7732) 2024-03-08 11:20:54 -05:00
Michel Heusschen ffdd504008 refactor(web): admin and user signup forms (#7739) 2024-03-08 08:45:41 -05:00
dependabot[bot] 46597aac97 chore(deps): bump docker/build-push-action from 5.1.0 to 5.2.0 (#7737)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.1.0 to 5.2.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5.1.0...v5.2.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-08 08:41:39 -05:00
mmomjian 9b27a09131 docs: Update DB queries (#7730) 2024-03-07 23:28:51 -05:00
Jason Rasmussen a50f125dd1 refactor: api validators (boolean and date) (#7709)
* refactor: api validators (boolean and date)

* chore: open api

* revert: time bucket change
2024-03-07 22:59:02 -05:00
Alex 753842745d Localizely: Translations update (#7715)
chore(mobile): translation update
2024-03-07 20:56:05 -06:00
martyfuhry 21caa06fa2 fix(mobile): Fixes large and small image cache (#7726)
Fixes large and small image cache
2024-03-07 20:55:50 -06:00
aviv926 7a7475ed67 docs: Update External Libraries Guide (#7723) 2024-03-07 18:49:30 -05:00
Sam Holton dbb6a8dc2a fix(server): remove shared links during user delete (#7696)
* fix(server): remove shared links during user delete

* add delete cascade for shared links
2024-03-07 17:21:23 -05:00
Jonathan Jogenfors a5a27594b8 docs: admin-only library settings (#7716)
* document admin-only library settings

* renew library guide
2024-03-07 21:27:02 +00:00
Jason Rasmussen 661409bac7 feat(server): create a person with optional values (#7706)
* feat: create person dto

* chore: open api

* fix: e2e

* fix: web usage
2024-03-07 15:34:57 -05:00
Jonathan Jogenfors f1a8e385e9 deps(server): CVE-2024-28176 (#7717)
bumpety bump
2024-03-07 15:34:10 -05:00
renovate[bot] a623556762 chore(deps): update dependency @playwright/test to v1.42.1 (#7684)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-07 15:31:45 -05:00
Alex The Bot 7dc5e0cc4f Version v1.98.0 2024-03-07 19:22:14 +00:00
Alex Tran ba5d5256b1 Revert "Version v1.98.0"
This reverts commit 9b1a379fa6.
2024-03-07 12:04:54 -06:00
Alex Tran 307ffc990d fix(server): admin access to edit library 2024-03-07 12:03:21 -06:00
Alex The Bot 9b1a379fa6 Version v1.98.0 2024-03-07 17:40:40 +00:00
Jonathan Jogenfors 4cb0f37918 chore(server): Move library watcher to microservices (#7533)
* move watcher init to micro

* document watcher recovery

* chore: fix lint

* add try lock

* use global library watch lock

* fix: ensure lock stays on

* fix: mocks

* unit test for library watch lock

* move statement to correct test

* fix: correct return type of try lock

* fix: tests

* add library teardown

* add chokidar error handler

* make event strings an enum

* wait for event refactor

* refactor event type mocks

* expect correct error

* don't release lock in teardown

* chore: lint

* use enum

* fix mock

* fix lint

* fix watcher await

* remove await

* simplify typing

* remove async

* Revert "remove async"

This reverts commit 84ab5abac487532c79a7d770869b08fbba1294bf.

* can now change watch settings at runtime

* fix lint

* only watch libraries if enabled

---------

Co-authored-by: mertalev <101130780+mertalev@users.noreply.github.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-07 11:36:53 -06:00
Alex 3278dcbcbe fix(web): save filename search in search filter box (#7704) 2024-03-07 10:16:47 -06:00
Jason Rasmussen b733a29430 refactor: e2e (#7703)
* refactor: e2e

* fix: submodule check

* chore: extend startup timeout
2024-03-07 10:14:36 -05:00
Michel Heusschen 2dcd0e516f fix(server): add extension to filename migration (#7697) 2024-03-07 09:33:56 -05:00
Alex e823b39579 fix(server): access face count when the value is undefined (#7694) 2024-03-06 23:21:10 -05:00
Alex cd058fdafa chore(mobile,web): use originalFilename (#7692)
* chore(mobile,web): use originalFilename

* web

* remove unused code
2024-03-06 23:20:04 -05:00
Alex 1eea547aa2 chore(server): search filename using originalFileName (#7691) 2024-03-06 22:36:08 -05:00
martyfuhry 4323d18387 fix(mobile): Refactors exif bottom sheet to use widgets and fixes slow sliding up exif bottom sheet (#7671)
* Refactors exif bottom sheet to use widgets and fixes slow sliding up experience

format

* Refactors exif bottom sheet to use widgets and fixes slow sliding up experience

format

* Fixes people

* removes wrong exif bottom sheet

format

format

* Moved more widgets out of exit bottom sheet

format

* small styling

---------

Co-authored-by: Marty Fuhry <marty@fuhry.farm>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-07 03:27:33 +00:00
Mert 1ec5d612fa perf(server): use queries to refresh library assets (#7685)
* use queries instead of js

* missing await

* add mock methods

* fix test

* update sql

* linting
2024-03-06 21:23:10 -06:00
renovate[bot] fcb990665c chore(deps): update base-image to v20240305 (major) (#7682)
chore(deps): update base-image to v20240305

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-06 22:22:55 -05:00
Mert ffaa08e7ea chore(server): lower default max recognition distance for facial recognition (#7689)
lower default to 0.5
2024-03-06 22:20:38 -05:00
Michel Heusschen 5dd11ca17a fix(web): consistent modal escape behavior (#7677)
* fix(web): consistent modal escape behavior

* make onClose optional
2024-03-06 22:18:53 -05:00
Alex 3da2b05428 chore(server): save original file name with extension (#7679)
* chore(server): save original file name with extension

* extract extension

* update e2e test

* update e2e test

* download archive

* fix download archive appending name

* pr feedback

* remove unused code

* test

* unit test

* remove unused code

* migration

* noops

* pr feedback

* Update server/src/domain/download/download.service.ts

Co-authored-by: Mert <101130780+mertalev@users.noreply.github.com>

---------

Co-authored-by: Mert <101130780+mertalev@users.noreply.github.com>
2024-03-07 02:34:55 +00:00
Mert f88343019d perf(web): optimize response sizes for initial page load (#7594) 2024-03-06 12:05:53 -05:00
Emanuel Bennici ba12d92af3 feat(mobile): Add people list to exit bottom sheet (#6717)
* feat(mobile): Define constants as 'const'

* feat(mobile): Add people list to asset bottom sheet

Add a list of people per asset in the exif bottom sheet, like on the
web.

Currently the list of people is loaded by making a request each time to
the server. This is the MVP approach.
In the future, the people information can be synced like we're doing
with the assets.

* styling

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-06 11:15:54 -05:00
Michel Heusschen 52a52f9f40 fix(web): date input on chrome (#7669) 2024-03-06 05:47:15 -06:00
Sam Holton 9125999d1a feat(server,web): make user deletion delay configurable (#7663)
* feat(server,web): make user deletion delay configurable

* alphabetical order

* add min for user.deleteDelay in SettingInputField

* make config.user.deleteDelay SettingInputField min consistent format

* fix e2e test

* update description on user delete delay
2024-03-05 23:45:40 -06:00
Alex 52dfe5fc92 fix(server): stack info in asset response for mobile (#7346)
* fix(server): stack info in asset response for mobile

* fix(server): getAllAssets - do not filter by stack ID

* tet(server): GET /assets stack e2e

* chore(server): fix checks

* stack asset height

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2024-03-06 05:44:56 +00:00
renovate[bot] 4c0bb2308c fix(deps): update machine-learning (#7634)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-06 00:24:33 -05:00
martyfuhry 4ef4cc8016 refactor(mobile): Refactor video player page and gallery bottom app bar (#7625)
* Fixes double video auto initialize issue and placeholder for video controller

* WIP unravel stack index

* Refactors video player controller

format

fixing video

format

Working

format

* Fixes hide on pause

* Got hiding when tapped working

* Hides controls when video starts and fixes placeholder for memory card

Remove prints

* Fixes show controls with microtask

* fix LivePhotos not playing

* removes unused function callbacks and moves wakelock

* Update motion video

* Fixing motion photo playing

* Renames to isPlayingVideo

* Fixes playing video on change

* pause on dispose

* fixing issues with sync between controls

* Adds gallery app bar

* Switches to memoized

* Fixes pause

* Revert "Switches to memoized"

This reverts commit 234e6741dea05aa0b967dde746f1d625f15bed94.

* uses stateful widget

* Fixes double video play by using provider and new chewie video player

wip

format

Fixes motion photos

format

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-05 21:42:22 -06:00
Alex 2f53f6a62c feat(web): search by filename (#7624)
* Toggle to search by filename

* wild card search and pr feedback

* Pr feedback

* naming

* placeholder

* Create index

* pr feedback

* pr feedback

* Update web/src/lib/components/shared-components/search-bar/search-text-section.svelte

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

* pr feedback

* pr feedback

* pr feedback

* pr feedback

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-03-05 17:08:35 -06:00
Jonathan Jogenfors ae46188753 chore(deps): bump sanitize-html, fixing CVE-2024-21501 (#7662)
* bump sanitize-html

* bump better
2024-03-05 17:35:52 -05:00
renovate[bot] 51f6b8f23b chore(deps): update dependency @types/cookie-parser to v1.4.7 (#7661)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-05 17:31:26 -05:00
Jonathan Jogenfors 5d377e5b0f chore(server): eslint await-thenable (#7545)
* await-thenable

* fix library watchers

* moar eslint

* fix test

* fix typo

* try to remove check void return

* fix checksVoidReturn

* move to domain utils

* remove eslint ignores

* chore: cleanup types

* chore: use logger

* fix: e2e

---------

Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-03-05 17:23:06 -05:00
Jason Rasmussen 972d5a3411 feat(server): deterministic download order (#7658) 2024-03-05 15:04:43 -06:00
renovate[bot] 8df63b7c94 fix(deps): update dependency archiver to v7 (#7622)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-05 12:26:54 -05:00
renovate[bot] ee3b2a0cf5 chore(deps): update server (#7652)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-05 12:16:41 -05:00
Jason Rasmussen 8988d3f886 chore: download e2e (#7651) 2024-03-05 12:07:46 -05:00
bo0tzz 4dc0fc45e7 feat(cli): Use well-known endpoint to resolve API (#6733)
* feat(cli): use immich-well-known

* chore: e2e test

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-03-05 12:06:24 -05:00
renovate[bot] 1c93ef1916 chore(deps): update dependency svelte-check to v3.6.6 (#7650)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-05 17:01:12 +00:00
renovate[bot] 9bf1d87e35 chore(deps): update dependency @types/node to v20.11.24 (#7649)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-05 16:30:51 +00:00
renovate[bot] 31b823058d chore(deps): update dependency @types/node to v20.11.24 (#7645)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-05 11:29:04 -05:00
Jason Rasmussen 9a2e0e8962 chore(cli): remove unused packages (#7648) 2024-03-05 16:18:53 +00:00
renovate[bot] e0ae936496 chore(deps): update dependency @types/node to v20.11.24 (#7646)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-05 15:58:40 +00:00
Alex 0675389aae Revert "fix(web): prevent duplicate calls to time bucket endpoint" (#7644)
Revert "fix(web): prevent duplicate calls to time bucket endpoint (#7563)"

This reverts commit 8b02f18e99.
2024-03-05 09:44:33 -06:00
Michel Heusschen facd0bc3a4 Revert "perf(web): optimize date groups" (#7638)
Revert "perf(web): optimize date groups (#7593)"

This reverts commit 762c4684f8.
2024-03-05 09:43:24 -06:00
renovate[bot] 967019d9e0 chore(deps): update dependency @types/node to v20.11.23 (#7641)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-05 07:57:22 -05:00
renovate[bot] e5da735918 chore(deps): update @immich/cli (#7640)
chore(deps): update dependency @types/node to v20.11.23

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-05 07:57:03 -05:00
waclaw66 9b3f60ffde fix(web): prettify album download filename (#7637)
fix(server): pretify download filename
2024-03-05 07:56:12 -05:00
renovate[bot] a5d19bc945 fix(deps): update server (#7635)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-05 03:48:00 +00:00
renovate[bot] 9995647d63 chore(deps): update dependency prettier-plugin-svelte to v3.2.2 (#7633)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-04 22:43:55 -05:00
Nicholas Flamy 70881bc97f Update truenas.md with permission info. (#7606)
* Update truenas.md with permission info.

This is very important information about permissions on datasets used by immich.

* Update truenas.md

* Update truenas.md with proper formatting
2024-03-05 02:51:20 +00:00
renovate[bot] dbf0ddf3a7 chore(deps): update @immich/cli (#7629)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-04 21:36:53 -05:00
renovate[bot] 2e62e3a0ca chore(deps): update dependency @types/node to v20.11.22 (#7630)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-04 21:36:01 -05:00
martin 6ab404597c fix(server): incorrect number of assets for a person (#7602)
* fix: incorrect number of assets

* fix: tests

* pr feedback

* fix: e2e test

* fix: e2e test

* fix: e2e test

* feat: more tests
2024-03-04 18:11:54 -05:00
renovate[bot] 5bc13c49a4 chore(deps): update dependency @types/node to v20.11.22 (#7610)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-04 17:42:26 -05:00
martin 935ddf3fbd fix(server, web): prevent reload when liking an asset (#7589)
pr feedback
2024-03-04 17:41:10 -05:00
Sam Holton 87c3d886ff feat(web): use lib/utils/copyToClipboard for share link (#7603) 2024-03-04 17:39:58 -05:00
Robert Vollmer de71d8e0a3 fix(server): regular version check (#7620)
`dt.diffNow()` equals `dt.diff(DateTime.now())`, so it returns a
negative number when `dt` is in the past (which it always is in this
case).

Therefore we could only get over the condition during startup (when
`this.releaseVersionCheckedAt` isn't set yet), effectively breaking
update notifications while the server is running.
2024-03-04 08:42:22 -06:00
Sam Holton 7ef202c8b2 feat(server, web): add checkbox to create user screen for shouldChang… (#7598)
feat(server, web): add checkbox to create user screen for shouldChangePassword
2024-03-03 23:40:03 -06:00
DawidPietrykowski e8b001f62f feat: preloading of machine learning models (#7540) 2024-03-03 19:48:56 -05:00
Mert 762c4684f8 perf(web): optimize date groups (#7593)
* optimize date groups

* remove `.values()`

* remove console.log

* remove if condition

* remove console.log

* remove outdated comment

* revert dynamic import
2024-03-03 16:12:52 -06:00
Mert 2fa10a254c feat(web): improve alt text (#7596)
* alt text

* memory lane alt text

* revert sql generator change

* use getAltText

* oops

* handle large number of people in asset

* nit

* add aria-label to search button

* update api

* fixed tests

* fixed typing

* fixed spacing

* fix displaying null
2024-03-03 16:42:17 -05:00
martin 07c926bb12 fix: bump version pipeline (#7586)
* fix: bump version pipeline

* pr feedback
2024-03-03 15:17:21 -06:00
renovate[bot] 3d410ff7dc chore(deps): update dependency @playwright/test to v1.42.0 (#7601)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-03 15:16:03 -06:00
Sam Holton 2bb7b3e60f feat(web): add share link on asset-viewer (#7595)
* feat(web): add share link on asset-viewer

* PR feedback: move download to context, make share first button
2024-03-03 15:15:35 -06:00
Sam Holton 29a4389aac feat(web): show user quota on server stats page (#7591) 2024-03-03 15:47:00 -05:00
martin 8ce18b3403 feat(machine-learning): support cuda 12 (#7569)
* feat: support cuda12

* fix: group optional

* move to cuda 12

* pr feedback
2024-03-02 23:36:16 -05:00
renovate[bot] fd3503e77d chore(deps): update dependency @types/pg to v8.11.2 (#7585)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-02 18:08:41 -05:00
martin ebe7a14c14 fix(server): prevent leaking isFavorite and isArchived info (#7580)
* fix: prevent leaking favorites info

* add e2e test

* fix: e2e test

* fix: isArchived

* fix: keep old version
2024-03-02 18:01:24 -05:00
Sam Holton f03381a5b1 feat(server): allow oauth claim to set 0 for no quota (#7581)
* feat(server): allow oauth claim to set 0 for no quota

* PR feedback to remove extra objects from user.stub.ts
2024-03-02 14:18:56 -06:00
martin 8d44afe915 feat(web): ascending order for slideshow (#7502)
* feat: ascending order for slideshow

* feat: use dropdown

* rename

* fix: size

* pr feedback

* fix: hide text on small screen

* Wording

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2024-03-02 09:50:02 -06:00
martin db455060f0 fix(web): show history search box only when needed (#7544)
show history search box only when needed
2024-03-02 09:38:34 -06:00
Ignacy Kajdan b63b42d3d7 docs: fix the database name env variable (#7576) 2024-03-02 08:58:07 -05:00
Michel Heusschen a4e6c43823 perf(web): asset delete (#7555)
* perf(web): asset delete

* update asset delete on search page

* don't use arrow function in class
2024-03-01 19:49:31 -05:00
Sam Holton 7303fab9d9 feat(server/web): add oauth defaultStorageQuota and storageQuotaClaim (#7548)
* feat(server/web): add oauth defaultStorageQuota and storageQuotaClaim

* feat(server/web): fix format and use domain.util constants

* address some pr feedback

* simplify oauth storage quota logic

* adding tests and pr feedback

* chore: cleanup

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
2024-03-01 19:46:07 -05:00
Mert 8b02f18e99 fix(web): prevent duplicate calls to time bucket endpoint (#7563) 2024-03-01 14:16:07 -05:00
1271 changed files with 31470 additions and 25045 deletions
+1 -1
View File
@@ -45,7 +45,7 @@ jobs:
uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: "3.16.9"
flutter-version: "3.19.3"
cache: true
- name: Create the Keystore
+2 -2
View File
@@ -58,7 +58,7 @@ jobs:
uses: docker/setup-qemu-action@v3.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.1.0
uses: docker/setup-buildx-action@v3.2.0
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
@@ -87,7 +87,7 @@ jobs:
type=raw,value=latest,enable=${{ github.event_name == 'workflow_dispatch' }}
- name: Build and push image
uses: docker/build-push-action@v5.1.0
uses: docker/build-push-action@v5.3.0
with:
file: cli/Dockerfile
platforms: linux/amd64,linux/arm64
-26
View File
@@ -1,26 +0,0 @@
name: Update Immich SDK
on:
workflow_dispatch:
push:
branches: ["main"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
update-sdk-repos:
runs-on: ubuntu-latest
if: ${{ !github.event.pull_request.head.repo.fork }}
steps:
- uses: actions/github-script@v7
with:
github-token: ${{ secrets.GH_TOKEN }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: 'immich-app',
repo: 'immich-sdk-typescript-axios',
workflow_id: 'build.yml',
ref: 'main'
})
+2 -8
View File
@@ -66,13 +66,7 @@ jobs:
uses: docker/setup-qemu-action@v3.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.1.0
# Workaround to fix error:
# failed to push: failed to copy: io: read/write on closed pipe
# See https://github.com/docker/build-push-action/issues/761
with:
driver-opts: |
image=moby/buildkit:v0.10.6
uses: docker/setup-buildx-action@v3.2.0
- name: Login to Docker Hub
# Only push to Docker Hub when making a release
@@ -121,7 +115,7 @@ jobs:
fi
- name: Build and push image
uses: docker/build-push-action@v5.1.0
uses: docker/build-push-action@v5.3.0
with:
context: ${{ matrix.context }}
file: ${{ matrix.file }}
+8 -7
View File
@@ -4,16 +4,16 @@ on:
workflow_dispatch:
inputs:
serverBump:
description: "Bump server version"
description: 'Bump server version'
required: true
default: "false"
default: 'false'
type: choice
options:
- "false"
- 'false'
- minor
- patch
mobileBump:
description: "Bump mobile build number"
description: 'Bump mobile build number'
required: false
type: boolean
@@ -46,8 +46,8 @@ jobs:
with:
author_name: Alex The Bot
author_email: alex.tran1502@gmail.com
default_author: user_info
message: "Version ${{ env.IMMICH_VERSION }}"
default_author: user_info
message: 'Version ${{ env.IMMICH_VERSION }}'
tag: ${{ env.IMMICH_VERSION }}
push: true
@@ -74,7 +74,7 @@ jobs:
name: release-apk-signed
- name: Create draft release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
with:
draft: true
tag_name: ${{ env.IMMICH_VERSION }}
@@ -85,4 +85,5 @@ jobs:
docker/example.env
docker/hwaccel.ml.yml
docker/hwaccel.transcoding.yml
docker/prometheus.yml
*.apk
+31
View File
@@ -0,0 +1,31 @@
name: Update Immich SDK
on:
release:
types: [published]
permissions:
packages: write
jobs:
publish:
name: Publish `@immich/sdk`
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./open-api/typescript-sdk
steps:
- uses: actions/checkout@v4
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- name: Install deps
run: npm ci
- name: Build
run: npm run build
- name: Publish
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: "3.16.9"
flutter-version: "3.19.3"
- name: Install dependencies
run: dart pub get
+9 -26
View File
@@ -10,23 +10,6 @@ concurrency:
cancel-in-progress: true
jobs:
server-e2e-api:
name: Server (e2e-api)
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./server
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run npm install
run: npm ci
- name: Run e2e tests
run: npm run e2e:api
server-e2e-jobs:
name: Server (e2e-jobs)
runs-on: ubuntu-latest
@@ -108,17 +91,13 @@ jobs:
with:
node-version: 20
- name: Run setup typescript-sdk
- name: Setup typescript-sdk
run: npm ci && npm run build
working-directory: ./open-api/typescript-sdk
- name: Run npm install (cli)
- name: Install deps
run: npm ci
- name: Run npm install (server)
run: npm ci
working-directory: ./server
- name: Run linter
run: npm run lint
if: ${{ !cancelled() }}
@@ -213,6 +192,10 @@ jobs:
run: npm run format
if: ${{ !cancelled() }}
- name: Run tsc
run: npm run check
if: ${{ !cancelled() }}
- name: Install Playwright Browsers
run: npx playwright install --with-deps chromium
if: ${{ !cancelled() }}
@@ -346,14 +329,14 @@ jobs:
- name: Generate new migrations
continue-on-error: true
run: npm run typeorm:migrations:generate ./src/infra/migrations/TestMigration
run: npm run typeorm:migrations:generate ./src/migrations/TestMigration
- name: Find file changes
uses: tj-actions/verify-changed-files@v19
id: verify-changed-files
with:
files: |
server/src/infra/migrations/
server/src/migrations/
- name: Verify migration files have not changed
if: steps.verify-changed-files.outputs.files_changed == 'true'
run: |
@@ -371,7 +354,7 @@ jobs:
id: verify-changed-sql-files
with:
files: |
server/src/infra/sql
server/src/queries
- name: Verify SQL files have not changed
if: steps.verify-changed-sql-files.outputs.files_changed == 'true'
+34
View File
@@ -0,0 +1,34 @@
{
"editor.formatOnSave": true,
"[javascript][typescript][css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2,
"editor.formatOnSave": true
},
"[svelte]": {
"editor.defaultFormatter": "svelte.svelte-vscode",
"editor.tabSize": 2
},
"svelte.enable-ts-plugin": true,
"eslint.validate": [
"javascript",
"svelte"
],
"typescript.preferences.importModuleSpecifier": "non-relative",
"[dart]": {
"editor.formatOnSave": true,
"editor.selectionHighlight": false,
"editor.suggest.snippetsPreventQuickSuggestions": false,
"editor.suggestSelection": "first",
"editor.tabCompletion": "onlySnippets",
"editor.wordBasedSuggestions": "off",
"editor.defaultFormatter": "Dart-Code.dart-code"
},
"cSpell.words": [
"immich"
],
"explorer.fileNesting.enabled": true,
"explorer.fileNesting.patterns": {
"*.ts": "${capture}.spec.ts,${capture}.mock.ts"
}
}
-3
View File
@@ -19,9 +19,6 @@ pull-stage:
server-e2e-jobs:
docker compose -f ./server/e2e/docker-compose.server-e2e.yml up --renew-anon-volumes --abort-on-container-exit --exit-code-from immich-server --remove-orphans --build
server-e2e-api:
npm run e2e:api --prefix server
.PHONY: e2e
e2e:
docker compose -f ./e2e/docker-compose.yml up --build -V --remove-orphans
+13 -13
View File
@@ -9,26 +9,26 @@
</p>
<p align="center">
<img src="design/immich-logo.svg" width="150" title="Login With Custom URL">
<img src="design/immich-logo-stacked-light.svg" width="300" title="Login With Custom URL">
</p>
<h3 align="center">Immich - High performance self-hosted photo and video backup solution</h3>
<h3 align="center">High performance self-hosted photo and video management solution</h3>
<br/>
<a href="https://immich.app">
<img src="design/immich-screenshots.png" title="Main Screenshot">
</a>
<br/>
<p align="center">
<a href="README_ca_ES.md">Català</a>
<a href="README_es_ES.md">Español</a>
<a href="README_fr_FR.md">Français</a>
<a href="README_it_IT.md">Italiano</a>
<a href="README_ja_JP.md">日本語</a>
<a href="README_ko_KR.md">한국어</a>
<a href="README_de_DE.md">Deutsch</a>
<a href="README_nl_NL.md">Nederlands</a>
<a href="README_tr_TR.md">Türkçe</a>
<a href="README_zh_CN.md">中文</a>
<a href="README_ru_RU.md">Русский</a>
<a href="readme_i18n/README_ca_ES.md">Català</a>
<a href="readme_i18n/README_es_ES.md">Español</a>
<a href="readme_i18n/README_fr_FR.md">Français</a>
<a href="readme_i18n/README_it_IT.md">Italiano</a>
<a href="readme_i18n/README_ja_JP.md">日本語</a>
<a href="readme_i18n/README_ko_KR.md">한국어</a>
<a href="readme_i18n/README_de_DE.md">Deutsch</a>
<a href="readme_i18n/README_nl_NL.md">Nederlands</a>
<a href="readme_i18n/README_tr_TR.md">Türkçe</a>
<a href="readme_i18n/README_zh_CN.md">中文</a>
<a href="readme_i18n/README_ru_RU.md">Русский</a>
</p>
## Disclaimer
+2 -1
View File
@@ -19,8 +19,9 @@ module.exports = {
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-floating-promises': 'error',
'unicorn/prefer-module': 'off',
'unicorn/prevent-abbreviations': 'off',
'unicorn/no-process-exit': 'off',
curly: 2,
'prettier/prettier': 0,
'unicorn/prevent-abbreviations': 'error',
},
};
+7 -3
View File
@@ -1,11 +1,15 @@
**/*.spec.js
coverage/**
src/**
upload/**
.editorconfig
.eslintignore
.eslintrc.js
.eslintrc.cjs
.gitignore
.prettierignore
.prettierrc
Dockerfile
package-lock.json
testSetup.js
tsconfig.json
tsconfig.build.json
vite.config.ts
vitest.config.ts
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:20-alpine3.19@sha256:c0a3badbd8a0a760de903e00cedbca94588e609299820557e72cba2a53dbaa2c as core
FROM node:20-alpine3.19@sha256:bf77dc26e48ea95fca9d1aceb5acfa69d2e546b765ec2abfb502975f1a2d4def as core
WORKDIR /usr/src/open-api/typescript-sdk
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
+439 -5303
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@immich/cli",
"version": "2.0.8",
"version": "2.1.0",
"description": "Command Line Interface (CLI) for Immich",
"type": "module",
"exports": "./dist/index.js",
@@ -14,7 +14,6 @@
],
"devDependencies": {
"@immich/sdk": "file:../open-api/typescript-sdk",
"@testcontainers/postgresql": "^10.7.1",
"@types/byte-size": "^8.1.0",
"@types/cli-progress": "^3.11.0",
"@types/lodash-es": "^4.17.12",
@@ -36,6 +35,7 @@
"prettier-plugin-organize-imports": "^3.2.4",
"typescript": "^5.3.3",
"vite": "^5.0.12",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^1.2.2",
"yaml": "^2.3.1"
},
@@ -1,4 +1,12 @@
import { AssetBulkUploadCheckResult } from '@immich/sdk';
import {
AssetBulkUploadCheckResult,
addAssetsToAlbum,
checkBulkUpload,
createAlbum,
defaults,
getAllAlbums,
getSupportedMediaTypes,
} from '@immich/sdk';
import byteSize from 'byte-size';
import cliProgress from 'cli-progress';
import { chunk, zip } from 'lodash-es';
@@ -7,9 +15,8 @@ import fs, { createReadStream } from 'node:fs';
import { access, constants, stat, unlink } from 'node:fs/promises';
import os from 'node:os';
import { basename } from 'node:path';
import { ImmichApi } from 'src/services/api.service';
import { CrawlService } from '../services/crawl.service';
import { BaseCommand } from './base-command';
import { CrawlService } from 'src/services/crawl.service';
import { BaseOptions, authenticate } from 'src/utils';
const zipDefined = zip as <T, U>(a: T[], b: U[]) => [T, U][];
@@ -66,8 +73,8 @@ class Asset {
assetData: new File([await fs.openAsBlob(this.path)], basename(this.path)),
deviceAssetId: this.deviceAssetId,
deviceId: 'CLI',
fileCreatedAt: this.fileCreatedAt,
fileModifiedAt: this.fileModifiedAt,
fileCreatedAt: this.fileCreatedAt.toISOString(),
fileModifiedAt: this.fileModifiedAt.toISOString(),
isFavorite: String(false),
};
const formData = new FormData();
@@ -106,7 +113,7 @@ class Asset {
}
}
export class UploadOptionsDto {
class UploadOptionsDto {
recursive? = false;
exclusionPatterns?: string[] = [];
dryRun? = false;
@@ -118,11 +125,13 @@ export class UploadOptionsDto {
concurrency? = 4;
}
export class UploadCommand extends BaseCommand {
api!: ImmichApi;
export const upload = (paths: string[], baseOptions: BaseOptions, uploadOptions: UploadOptionsDto) =>
new UploadCommand().run(paths, baseOptions, uploadOptions);
public async run(paths: string[], options: UploadOptionsDto): Promise<void> {
this.api = await this.connect();
// TODO refactor this
class UploadCommand {
public async run(paths: string[], baseOptions: BaseOptions, options: UploadOptionsDto): Promise<void> {
await authenticate(baseOptions);
console.log('Crawling for assets...');
const files = await this.getFiles(paths, options);
@@ -264,7 +273,7 @@ export class UploadCommand extends BaseCommand {
}
public async getAlbums(): Promise<Map<string, string>> {
const existingAlbums = await this.api.getAllAlbums();
const existingAlbums = await getAllAlbums({});
const albumMapping = new Map<string, string>();
for (const album of existingAlbums) {
@@ -313,7 +322,7 @@ export class UploadCommand extends BaseCommand {
try {
for (const albumNames of chunk(newAlbums, options.concurrency)) {
const newAlbumIds = await Promise.all(
albumNames.map((albumName: string) => this.api.createAlbum({ albumName }).then((r) => r.id)),
albumNames.map((albumName: string) => createAlbum({ createAlbumDto: { albumName } }).then((r) => r.id)),
);
for (const [albumName, albumId] of zipDefined(albumNames, newAlbumIds)) {
@@ -348,7 +357,7 @@ export class UploadCommand extends BaseCommand {
try {
for (const [albumId, assets] of albumToAssets.entries()) {
for (const assetBatch of chunk(assets, Math.min(1000 * (options.concurrency ?? 4), 65_000))) {
await this.api.addAssetsToAlbum(albumId, { ids: assetBatch });
await addAssetsToAlbum({ id: albumId, bulkIdsDto: { ids: assetBatch } });
albumUpdateProgress.increment(assetBatch.length);
}
}
@@ -404,17 +413,18 @@ export class UploadCommand extends BaseCommand {
const assetBulkUploadCheckDto = {
assets: zipDefined(assetsToCheck, checksums).map(([asset, checksum]) => ({ id: asset.path, checksum })),
};
const checkResponse = await this.api.checkBulkUpload(assetBulkUploadCheckDto);
const checkResponse = await checkBulkUpload({ assetBulkUploadCheckDto });
return checkResponse.results;
}
private async uploadAssets(assets: Asset[]): Promise<string[]> {
const fileRequests = await Promise.all(assets.map((asset) => asset.getUploadFormData()));
return Promise.all(fileRequests.map((request) => this.uploadAsset(request).then((response) => response.id)));
const results = await Promise.all(fileRequests.map((request) => this.uploadAsset(request)));
return results.map((response) => response.id);
}
private async crawl(paths: string[], options: UploadOptionsDto): Promise<string[]> {
const formatResponse = await this.api.getSupportedMediaTypes();
const formatResponse = await getSupportedMediaTypes();
const crawlService = new CrawlService(formatResponse.image, formatResponse.video);
return crawlService.crawl({
@@ -426,14 +436,12 @@ export class UploadCommand extends BaseCommand {
}
private async uploadAsset(data: FormData): Promise<{ id: string }> {
const url = this.api.instanceUrl + '/asset/upload';
const { baseUrl, headers } = defaults;
const response = await fetch(url, {
const response = await fetch(`${baseUrl}/asset/upload`, {
method: 'post',
redirect: 'error',
headers: {
'x-api-key': this.api.apiKey,
},
headers: headers as Record<string, string>,
body: data,
});
if (response.status !== 200 && response.status !== 201) {
+48
View File
@@ -0,0 +1,48 @@
import { getMyUserInfo } from '@immich/sdk';
import { existsSync } from 'node:fs';
import { mkdir, unlink } from 'node:fs/promises';
import { BaseOptions, connect, getAuthFilePath, logError, withError, writeAuthFile } from 'src/utils';
export const login = async (instanceUrl: string, apiKey: string, options: BaseOptions) => {
console.log(`Logging in to ${instanceUrl}`);
const { configDirectory: configDir } = options;
await connect(instanceUrl, apiKey);
const [error, userInfo] = await withError(getMyUserInfo());
if (error) {
logError(error, 'Failed to load user info');
process.exit(1);
}
console.log(`Logged in as ${userInfo.email}`);
if (!existsSync(configDir)) {
// Create config folder if it doesn't exist
const created = await mkdir(configDir, { recursive: true });
if (!created) {
console.log(`Failed to create config folder: ${configDir}`);
return;
}
}
await writeAuthFile(configDir, { instanceUrl, apiKey });
console.log(`Wrote auth info to ${getAuthFilePath(configDir)}`);
};
export const logout = async (options: BaseOptions) => {
console.log('Logging out...');
const { configDirectory: configDir } = options;
const authFile = getAuthFilePath(configDir);
if (existsSync(authFile)) {
await unlink(authFile);
console.log(`Removed auth file: ${authFile}`);
}
console.log('Successfully logged out');
};
-20
View File
@@ -1,20 +0,0 @@
import { ServerVersionResponseDto, UserResponseDto } from '@immich/sdk';
import { ImmichApi } from 'src/services/api.service';
import { SessionService } from '../services/session.service';
export abstract class BaseCommand {
protected sessionService!: SessionService;
protected user!: UserResponseDto;
protected serverVersion!: ServerVersionResponseDto;
constructor(options: { configDirectory?: string }) {
if (!options.configDirectory) {
throw new Error('Config directory is required');
}
this.sessionService = new SessionService(options.configDirectory);
}
public async connect(): Promise<ImmichApi> {
return await this.sessionService.connect();
}
}
-7
View File
@@ -1,7 +0,0 @@
import { BaseCommand } from './base-command';
export class LoginCommand extends BaseCommand {
public async run(instanceUrl: string, apiKey: string): Promise<void> {
await this.sessionService.login(instanceUrl, apiKey);
}
}
-8
View File
@@ -1,8 +0,0 @@
import { BaseCommand } from './base-command';
export class LogoutCommand extends BaseCommand {
public static readonly description = 'Logout and remove persisted credentials';
public async run(): Promise<void> {
await this.sessionService.logout();
}
}
-17
View File
@@ -1,17 +0,0 @@
import { BaseCommand } from './base-command';
export class ServerInfoCommand extends BaseCommand {
public async run() {
const api = await this.connect();
const versionInfo = await api.getServerVersion();
const mediaTypes = await api.getSupportedMediaTypes();
const statistics = await api.getAssetStatistics();
console.log(`Server Version: ${versionInfo.major}.${versionInfo.minor}.${versionInfo.patch}`);
console.log(`Image Types: ${mediaTypes.image.map((extension) => extension.replace('.', ''))}`);
console.log(`Video Types: ${mediaTypes.video.map((extension) => extension.replace('.', ''))}`);
console.log(
`Statistics:\n Images: ${statistics.images}\n Videos: ${statistics.videos}\n Total: ${statistics.total}`,
);
}
}
+15
View File
@@ -0,0 +1,15 @@
import { getAssetStatistics, getServerVersion, getSupportedMediaTypes } from '@immich/sdk';
import { BaseOptions, authenticate } from 'src/utils';
export const serverInfo = async (options: BaseOptions) => {
await authenticate(options);
const versionInfo = await getServerVersion();
const mediaTypes = await getSupportedMediaTypes();
const stats = await getAssetStatistics({});
console.log(`Server Version: ${versionInfo.major}.${versionInfo.minor}.${versionInfo.patch}`);
console.log(`Image Types: ${mediaTypes.image.map((extension) => extension.replace('.', ''))}`);
console.log(`Video Types: ${mediaTypes.video.map((extension) => extension.replace('.', ''))}`);
console.log(`Statistics:\n Images: ${stats.images}\n Videos: ${stats.videos}\n Total: ${stats.total}`);
};
+28 -35
View File
@@ -2,11 +2,10 @@
import { Command, Option } from 'commander';
import os from 'node:os';
import path from 'node:path';
import { upload } from 'src/commands/asset';
import { login, logout } from 'src/commands/auth';
import { serverInfo } from 'src/commands/server-info';
import { version } from '../package.json';
import { LoginCommand } from './commands/login.command';
import { LogoutCommand } from './commands/logout.command';
import { ServerInfoCommand } from './commands/server-info.command';
import { UploadCommand } from './commands/upload.command';
const defaultConfigDirectory = path.join(os.homedir(), '.config/immich/');
@@ -18,14 +17,34 @@ const program = new Command()
new Option('-d, --config-directory <directory>', 'Configuration directory where auth.yml will be stored')
.env('IMMICH_CONFIG_DIR')
.default(defaultConfigDirectory),
);
)
.addOption(new Option('-u, --url [url]', 'Immich server URL').env('IMMICH_INSTANCE_URL'))
.addOption(new Option('-k, --key [apiKey]', 'Immich API key').env('IMMICH_API_KEY'));
program
.command('login')
.alias('login-key')
.description('Login using an API key')
.argument('url', 'Immich server URL')
.argument('key', 'Immich API key')
.action((url, key) => login(url, key, program.opts()));
program
.command('logout')
.description('Remove stored credentials')
.action(() => logout(program.opts()));
program
.command('server-info')
.description('Display server information')
.action(() => serverInfo(program.opts()));
program
.command('upload')
.description('Upload assets')
.usage('[options] [paths...]')
.usage('[paths...] [options]')
.addOption(new Option('-r, --recursive', 'Recursive').env('IMMICH_RECURSIVE').default(false))
.addOption(new Option('-i, --ignore [paths...]', 'Paths to ignore').env('IMMICH_IGNORE_PATHS'))
.addOption(new Option('-i, --ignore [paths...]', 'Paths to ignore').env('IMMICH_IGNORE_PATHS').default([]))
.addOption(new Option('-h, --skip-hash', "Don't hash files before upload").env('IMMICH_SKIP_HASH').default(false))
.addOption(new Option('-H, --include-hidden', 'Include hidden folders').env('IMMICH_INCLUDE_HIDDEN').default(false))
.addOption(
@@ -44,38 +63,12 @@ program
.default(false),
)
.addOption(
new Option('-c, --concurrency', 'Number of assets to upload at the same time')
new Option('-c, --concurrency <number>', 'Number of assets to upload at the same time')
.env('IMMICH_UPLOAD_CONCURRENCY')
.default(4),
)
.addOption(new Option('--delete', 'Delete local assets after upload').env('IMMICH_DELETE_ASSETS'))
.argument('[paths...]', 'One or more paths to assets to be uploaded')
.action(async (paths, options) => {
options.exclusionPatterns = options.ignore;
await new UploadCommand(program.opts()).run(paths, options);
});
program
.command('server-info')
.description('Display server information')
.action(async () => {
await new ServerInfoCommand(program.opts()).run();
});
program
.command('login-key')
.description('Login using an API key')
.argument('url')
.argument('key')
.action(async (url, key) => {
await new LoginCommand(program.opts()).run(url, key);
});
program
.command('logout')
.description('Remove stored credentials')
.action(async () => {
await new LogoutCommand(program.opts()).run();
});
.action((paths, options) => upload(paths, program.opts(), options));
program.parse(process.argv);
-106
View File
@@ -1,106 +0,0 @@
import {
ApiKeyCreateDto,
AssetBulkUploadCheckDto,
BulkIdsDto,
CreateAlbumDto,
CreateAssetDto,
LoginCredentialDto,
SignUpDto,
addAssetsToAlbum,
checkBulkUpload,
createAlbum,
createApiKey,
getAllAlbums,
getAllAssets,
getAssetStatistics,
getMyUserInfo,
getServerVersion,
getSupportedMediaTypes,
login,
pingServer,
signUpAdmin,
uploadFile,
} from '@immich/sdk';
/**
* Wraps the underlying API to abstract away the options and make API calls mockable for testing.
*/
export class ImmichApi {
private readonly options;
constructor(
public instanceUrl: string,
public apiKey: string,
) {
this.options = {
baseUrl: instanceUrl,
headers: {
'x-api-key': apiKey,
},
};
}
setApiKey(apiKey: string) {
this.apiKey = apiKey;
if (!this.options.headers) {
throw new Error('missing headers');
}
this.options.headers['x-api-key'] = apiKey;
}
addAssetsToAlbum(id: string, bulkIdsDto: BulkIdsDto) {
return addAssetsToAlbum({ id, bulkIdsDto }, this.options);
}
checkBulkUpload(assetBulkUploadCheckDto: AssetBulkUploadCheckDto) {
return checkBulkUpload({ assetBulkUploadCheckDto }, this.options);
}
createAlbum(createAlbumDto: CreateAlbumDto) {
return createAlbum({ createAlbumDto }, this.options);
}
createApiKey(apiKeyCreateDto: ApiKeyCreateDto, options: { headers: { Authorization: string } }) {
return createApiKey({ apiKeyCreateDto }, { ...this.options, ...options });
}
getAllAlbums() {
return getAllAlbums({}, this.options);
}
getAllAssets() {
return getAllAssets({}, this.options);
}
getAssetStatistics() {
return getAssetStatistics({}, this.options);
}
getMyUserInfo() {
return getMyUserInfo(this.options);
}
getServerVersion() {
return getServerVersion(this.options);
}
getSupportedMediaTypes() {
return getSupportedMediaTypes(this.options);
}
login(loginCredentialDto: LoginCredentialDto) {
return login({ loginCredentialDto }, this.options);
}
pingServer() {
return pingServer(this.options);
}
signUpAdmin(signUpDto: SignUpDto) {
return signUpAdmin({ signUpDto }, this.options);
}
uploadFile(createAssetDto: CreateAssetDto) {
return uploadFile({ createAssetDto }, this.options);
}
}
-135
View File
@@ -1,135 +0,0 @@
import fs from 'node:fs';
import path from 'node:path';
import yaml from 'yaml';
import { SessionService } from './session.service';
const TEST_CONFIG_DIR = '/tmp/immich/';
const TEST_AUTH_FILE = path.join(TEST_CONFIG_DIR, 'auth.yml');
const TEST_IMMICH_INSTANCE_URL = 'https://test/api';
const TEST_IMMICH_API_KEY = 'pNussssKSYo5WasdgalvKJ1n9kdvaasdfbluPg';
const spyOnConsole = () => vi.spyOn(console, 'log').mockImplementation(() => {});
const createTestAuthFile = async (contents: string) => {
if (!fs.existsSync(TEST_CONFIG_DIR)) {
// Create config folder if it doesn't exist
const created = await fs.promises.mkdir(TEST_CONFIG_DIR, { recursive: true });
if (!created) {
throw new Error(`Failed to create config folder ${TEST_CONFIG_DIR}`);
}
}
fs.writeFileSync(TEST_AUTH_FILE, contents);
};
const readTestAuthFile = async (): Promise<string> => {
return await fs.promises.readFile(TEST_AUTH_FILE, 'utf8');
};
const deleteAuthFile = () => {
try {
fs.unlinkSync(TEST_AUTH_FILE);
} catch (error: any) {
if (error.code !== 'ENOENT') {
throw error;
}
}
};
const mocks = vi.hoisted(() => {
return {
getMyUserInfo: vi.fn(() => Promise.resolve({ email: 'admin@example.com' })),
pingServer: vi.fn(() => Promise.resolve({ res: 'pong' })),
};
});
vi.mock('./api.service', async (importOriginal) => {
const module = await importOriginal<typeof import('./api.service')>();
// @ts-expect-error this is only a partial implementation of the return value
module.ImmichApi.prototype.getMyUserInfo = mocks.getMyUserInfo;
module.ImmichApi.prototype.pingServer = mocks.pingServer;
return module;
});
describe('SessionService', () => {
let sessionService: SessionService;
beforeEach(() => {
deleteAuthFile();
sessionService = new SessionService(TEST_CONFIG_DIR);
});
afterEach(() => {
deleteAuthFile();
});
it('should connect to immich', async () => {
await createTestAuthFile(
JSON.stringify({
apiKey: TEST_IMMICH_API_KEY,
instanceUrl: TEST_IMMICH_INSTANCE_URL,
}),
);
await sessionService.connect();
expect(mocks.pingServer).toHaveBeenCalledTimes(1);
});
it('should error if no auth file exists', async () => {
await sessionService.connect().catch((error) => {
expect(error.message).toEqual('No auth file exist. Please login first');
});
});
it('should error if auth file is missing instance URl', async () => {
await createTestAuthFile(
JSON.stringify({
apiKey: TEST_IMMICH_API_KEY,
}),
);
await sessionService.connect().catch((error) => {
expect(error.message).toEqual(`Instance URL missing in auth config file ${TEST_AUTH_FILE}`);
});
});
it('should error if auth file is missing api key', async () => {
await createTestAuthFile(
JSON.stringify({
instanceUrl: TEST_IMMICH_INSTANCE_URL,
}),
);
await expect(sessionService.connect()).rejects.toThrow(`API key missing in auth config file ${TEST_AUTH_FILE}`);
});
it('should create auth file when logged in', async () => {
await sessionService.login(TEST_IMMICH_INSTANCE_URL, TEST_IMMICH_API_KEY);
const data: string = await readTestAuthFile();
const authConfig = yaml.parse(data);
expect(authConfig.instanceUrl).toBe(TEST_IMMICH_INSTANCE_URL);
expect(authConfig.apiKey).toBe(TEST_IMMICH_API_KEY);
});
it('should delete auth file when logging out', async () => {
const consoleSpy = spyOnConsole();
await createTestAuthFile(
JSON.stringify({
apiKey: TEST_IMMICH_API_KEY,
instanceUrl: TEST_IMMICH_INSTANCE_URL,
}),
);
await sessionService.logout();
await fs.promises.access(TEST_AUTH_FILE, fs.constants.F_OK).catch((error) => {
expect(error.message).toContain('ENOENT');
});
expect(consoleSpy.mock.calls).toEqual([
['Logging out...'],
[`Removed auth file ${TEST_AUTH_FILE}`],
['Successfully logged out'],
]);
});
});
-101
View File
@@ -1,101 +0,0 @@
import { existsSync } from 'node:fs';
import { access, constants, mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
import path from 'node:path';
import yaml from 'yaml';
import { ImmichApi } from './api.service';
class LoginError extends Error {
constructor(message: string) {
super(message);
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}
export class SessionService {
readonly configDirectory!: string;
readonly authPath!: string;
constructor(configDirectory: string) {
this.configDirectory = configDirectory;
this.authPath = path.join(configDirectory, '/auth.yml');
}
async connect(): Promise<ImmichApi> {
let instanceUrl = process.env.IMMICH_INSTANCE_URL;
let apiKey = process.env.IMMICH_API_KEY;
if (!instanceUrl || !apiKey) {
await access(this.authPath, constants.F_OK).catch((error) => {
if (error.code === 'ENOENT') {
throw new LoginError('No auth file exist. Please login first');
}
});
const data: string = await readFile(this.authPath, 'utf8');
const parsedConfig = yaml.parse(data);
instanceUrl = parsedConfig.instanceUrl;
apiKey = parsedConfig.apiKey;
if (!instanceUrl) {
throw new LoginError(`Instance URL missing in auth config file ${this.authPath}`);
}
if (!apiKey) {
throw new LoginError(`API key missing in auth config file ${this.authPath}`);
}
}
const api = new ImmichApi(instanceUrl, apiKey);
const pingResponse = await api.pingServer().catch((error) => {
throw new Error(`Failed to connect to server ${instanceUrl}: ${error.message}`, error);
});
if (pingResponse.res !== 'pong') {
throw new Error(`Could not parse response. Is Immich listening on ${instanceUrl}?`);
}
return api;
}
async login(instanceUrl: string, apiKey: string): Promise<ImmichApi> {
console.log('Logging in...');
const api = new ImmichApi(instanceUrl, apiKey);
// Check if server and api key are valid
const userInfo = await api.getMyUserInfo().catch((error) => {
throw new LoginError(`Failed to connect to server ${instanceUrl}: ${error.message}`);
});
console.log(`Logged in as ${userInfo.email}`);
if (!existsSync(this.configDirectory)) {
// Create config folder if it doesn't exist
const created = await mkdir(this.configDirectory, { recursive: true });
if (!created) {
throw new Error(`Failed to create config folder ${this.configDirectory}`);
}
}
await writeFile(this.authPath, yaml.stringify({ instanceUrl, apiKey }), { mode: 0o600 });
console.log('Wrote auth info to ' + this.authPath);
return api;
}
async logout(): Promise<void> {
console.log('Logging out...');
if (existsSync(this.authPath)) {
await unlink(this.authPath);
console.log('Removed auth file ' + this.authPath);
}
console.log('Successfully logged out');
}
}
+89
View File
@@ -0,0 +1,89 @@
import { defaults, getMyUserInfo, isHttpError } from '@immich/sdk';
import { readFile, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import yaml from 'yaml';
export interface BaseOptions {
configDirectory: string;
apiKey?: string;
instanceUrl?: string;
}
export interface AuthDto {
instanceUrl: string;
apiKey: string;
}
export const authenticate = async (options: BaseOptions): Promise<void> => {
const { configDirectory: configDir, instanceUrl, apiKey } = options;
// provided in command
if (instanceUrl && apiKey) {
await connect(instanceUrl, apiKey);
return;
}
// fallback to file
const config = await readAuthFile(configDir);
await connect(config.instanceUrl, config.apiKey);
};
export const connect = async (instanceUrl: string, apiKey: string): Promise<void> => {
const wellKnownUrl = new URL('.well-known/immich', instanceUrl);
try {
const wellKnown = await fetch(wellKnownUrl).then((response) => response.json());
const endpoint = new URL(wellKnown.api.endpoint, instanceUrl).toString();
if (endpoint !== instanceUrl) {
console.debug(`Discovered API at ${endpoint}`);
}
instanceUrl = endpoint;
} catch {
// noop
}
defaults.baseUrl = instanceUrl;
defaults.headers = { 'x-api-key': apiKey };
const [error] = await withError(getMyUserInfo());
if (isHttpError(error)) {
logError(error, 'Failed to connect to server');
process.exit(1);
}
};
export const logError = (error: unknown, message: string) => {
if (isHttpError(error)) {
console.error(`${message}: ${error.status}`);
console.error(JSON.stringify(error.data, undefined, 2));
} else {
console.error(`${message} - ${error}`);
}
};
export const getAuthFilePath = (dir: string) => join(dir, 'auth.yml');
export const readAuthFile = async (dir: string) => {
try {
const data = await readFile(getAuthFilePath(dir));
// TODO add class-transform/validation
return yaml.parse(data.toString()) as AuthDto;
} catch (error: Error | any) {
if (error.code === 'ENOENT' || error.code === 'ENOTDIR') {
console.log('No auth file exists. Please login first.');
process.exit(1);
}
throw error;
}
};
export const writeAuthFile = async (dir: string, auth: AuthDto) =>
writeFile(getAuthFilePath(dir), yaml.stringify(auth), { mode: 0o600 });
export const withError = async <T>(promise: Promise<T>): Promise<[Error, undefined] | [undefined, T]> => {
try {
const result = await promise;
return [undefined, result];
} catch (error: Error | any) {
return [error, undefined];
}
};
-12
View File
@@ -15,19 +15,7 @@
"incremental": true,
"skipLibCheck": true,
"esModuleInterop": true,
"rootDirs": ["src", "../server/src"],
"baseUrl": "./",
"paths": {
"@test": ["../server/test"],
"@test/*": ["../server/test/*"],
"@test-utils": ["../server/src/test-utils/utils"],
"@app/immich": ["../server/src/immich"],
"@app/immich/*": ["../server/src/immich/*"],
"@app/infra": ["../server/src/infra"],
"@app/infra/*": ["../server/src/infra/*"],
"@app/domain": ["../server/src/domain"],
"@app/domain/*": ["../server/src/domain/*"]
},
"types": ["vitest/globals"]
},
"exclude": ["dist", "node_modules"]
+2
View File
@@ -1,4 +1,5 @@
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
export default defineConfig({
build: {
@@ -14,4 +15,5 @@ export default defineConfig({
// bundle everything except for Node built-ins
noExternal: /^(?!node:).*$/,
},
plugins: [tsconfigPaths()],
});
Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

+63
View File
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 28.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Router_Medium_x5F_Black_00000159464448132936669960000002337362428709113490_"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 792 266.25"
style="enable-background:new 0 0 792 266.25;" xml:space="preserve">
<style type="text/css">
.st0{fill:#ACCBFA;}
.st1{fill:#FA2921;}
.st2{fill:#ED79B5;}
.st3{fill:#FFB400;}
.st4{fill:#1E83F7;}
.st5{fill:#18C249;}
</style>
<g>
<path class="st0" d="M268.73,63.18c6.34,0,11.52,5.18,11.52,11.35c0,6.34-5.18,11.35-11.52,11.35s-11.69-5.01-11.69-11.35
C257.04,68.36,262.39,63.18,268.73,63.18z M258.88,122.45c0-3.01-0.67-7.85-0.67-10.68c0-6.01,4.67-10.68,10.52-10.68
c5.84,0,10.52,4.67,10.52,10.68c0,2.84-0.83,7.68-0.83,10.68v38.73c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.67,10.68-10.52,10.68
c-5.84,0-10.52-4.67-10.52-10.68c0-2.84,0.67-7.68,0.67-10.68V122.45z"/>
<path class="st0" d="M394.28,171.87c0-2.84,0.83-7.68,0.83-10.68V132.3c0-10.18-5.34-16.86-14.52-16.86c-6.01,0-11.35,3-14.86,8.85
c0.33,1.84,0.5,3.67,0.5,5.68v31.22c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.67,10.68-10.68,10.68c-5.51,0-10.35-4.67-10.35-10.68
c0-2.84,0.83-7.68,0.83-10.68V131.8c0-3.17-0.5-6.01-1.67-8.51c-2.17-4.84-6.51-7.85-12.52-7.85c-6.18,0-11.19,3.17-14.86,8.85
v36.9c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.84,10.68-10.52,10.68c-5.84,0-10.52-4.67-10.52-10.68c0-2.84,0.67-7.68,0.67-10.68
v-38.57c0-3.01-1.5-8.35-1.5-10.85c0-6.01,4.34-10.68,10.18-10.68c5.51,0,8.68,3.67,9.68,8.51c5.01-6.68,12.02-10.85,21.2-10.85
c10.85,0,18.7,5.18,23.54,13.52c5.51-8.68,13.52-13.52,23.54-13.52c16.86,0,29.72,12.19,29.72,31.72v30.72
c0,3.01,0.67,7.85,0.67,10.68c0,6.01-4.51,10.68-10.52,10.68C399.12,182.55,394.28,177.88,394.28,171.87z"/>
<path class="st0" d="M528.5,171.87c0-2.84,0.83-7.68,0.83-10.68V132.3c0-10.18-5.34-16.86-14.52-16.86c-6.01,0-11.35,3-14.86,8.85
c0.33,1.84,0.5,3.67,0.5,5.68v31.22c0,3.01,0.84,7.85,0.84,10.68c0,6.01-4.67,10.68-10.68,10.68c-5.51,0-10.35-4.67-10.35-10.68
c0-2.84,0.84-7.68,0.84-10.68V131.8c0-3.17-0.5-6.01-1.67-8.51c-2.17-4.84-6.51-7.85-12.52-7.85c-6.18,0-11.19,3.17-14.86,8.85
v36.9c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.84,10.68-10.52,10.68c-5.84,0-10.52-4.67-10.52-10.68c0-2.84,0.67-7.68,0.67-10.68
v-38.57c0-3.01-1.5-8.35-1.5-10.85c0-6.01,4.34-10.68,10.18-10.68c5.51,0,8.68,3.67,9.68,8.51c5.01-6.68,12.02-10.85,21.2-10.85
c10.85,0,18.7,5.18,23.54,13.52c5.51-8.68,13.52-13.52,23.54-13.52c16.86,0,29.72,12.19,29.72,31.72v30.72
c0,3.01,0.67,7.85,0.67,10.68c0,6.01-4.51,10.68-10.52,10.68C533.35,182.55,528.5,177.88,528.5,171.87z"/>
<path class="st0" d="M576.92,63.18c6.34,0,11.52,5.18,11.52,11.35c0,6.34-5.18,11.35-11.52,11.35s-11.69-5.01-11.69-11.35
C565.23,68.36,570.57,63.18,576.92,63.18z M567.07,122.45c0-3.01-0.67-7.85-0.67-10.68c0-6.01,4.67-10.68,10.52-10.68
s10.52,4.67,10.52,10.68c0,2.84-0.84,7.68-0.84,10.68v38.73c0,3.01,0.84,7.85,0.84,10.68c0,6.01-4.67,10.68-10.52,10.68
s-10.52-4.67-10.52-10.68c0-2.84,0.67-7.68,0.67-10.68V122.45z"/>
<path class="st0" d="M601.79,141.31c0-23.54,14.69-42.57,39.07-42.57c12.86,0,24.71,5.84,30.05,14.53c2,3.17,2.34,5.01,2.34,6.51
c0,5.18-4.01,9.52-9.85,9.52c-3.84,0-7.34-2.17-8.85-6.01c-2.34-5.18-6.85-8.18-13.69-8.18c-12.86,0-20.03,11.52-20.03,26.04
c0,14.69,7.51,26.04,20.53,26.04c7.01,0,12.02-2.5,14.36-7.68c1.67-3.51,4.84-6.51,9.18-6.51c6.01,0,9.68,4.17,9.68,9.35
c0,2.5-1,5.51-3.17,8.35c-5.51,7.35-15.86,13.19-30.05,13.19C616.32,183.89,601.79,165.19,601.79,141.31z"/>
<path class="st0" d="M737.69,171.87c0-2.84,0.67-7.68,0.67-10.68v-28.55c0-10.18-5.68-17.2-15.36-17.2
c-6.68,0-12.35,3.17-16.03,8.35v37.4c0,3.01,0.67,7.85,0.67,10.68c0,6.01-4.67,10.68-10.52,10.68s-10.52-4.67-10.52-10.68
c0-2.84,0.84-7.68,0.84-10.68v-80.8c0-3.01-0.84-7.85-0.84-10.68c0-6.01,4.84-10.68,10.52-10.68c5.84,0,10.52,4.67,10.52,10.68
c0,2.84-0.67,7.68-0.67,10.68v27.21c5.01-5.51,12.19-8.85,21.37-8.85c17.2,0,29.55,12.86,29.55,31.22v31.22
c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.84,10.68-10.52,10.68C742.36,182.55,737.69,177.88,737.69,171.87z"/>
</g>
<g>
<path class="st1" d="M114.82,96.21c11.92,10.55,21.52,21.86,27.7,32.52c10.62-18.99,17.71-41.55,17.8-55.92c0-0.1,0-0.19,0-0.28
c0-21.26-21.21-29.54-39.48-29.54s-39.48,8.28-39.48,29.54c0,0.29,0,0.68,0,1.15C91.54,78.2,103.61,86.29,114.82,96.21z"/>
<path class="st2" d="M49.8,154.19c7.45-8.29,18.88-17.27,31.77-24.86c13.72-8.07,27.44-13.71,39.49-16.3
c-14.78-15.96-34.04-29.68-47.68-34.21c-0.1-0.03-0.18-0.06-0.27-0.09c-20.22-6.57-34.65,11.05-40.3,28.42s-4.33,40.11,15.89,46.68
C48.99,153.93,49.35,154.05,49.8,154.19z"/>
<path class="st3" d="M209.07,106.86c-5.65-17.38-20.07-34.99-40.3-28.42c-0.28,0.09-0.65,0.21-1.09,0.35
c-1.16,11.08-5.12,25.07-11.09,38.79c-6.35,14.6-14.14,27.23-22.36,36.39c21.34,4.23,44.99,4,58.68-0.35
c0.1-0.03,0.19-0.06,0.27-0.09C213.4,146.97,214.71,124.24,209.07,106.86z"/>
<path class="st4" d="M102.8,171.18c-3.44-15.54-4.56-30.34-3.3-42.59c-19.75,9.12-38.75,23.2-47.27,34.78
c-0.06,0.08-0.11,0.16-0.16,0.23c-12.5,17.2-0.2,36.37,14.58,47.11s36.81,16.51,49.31-0.69c0.17-0.24,0.4-0.55,0.68-0.93
C111.05,199.44,106.04,185.79,102.8,171.18z"/>
<path class="st5" d="M189.48,162.49c-10.9,2.33-25.42,2.88-40.32,1.44c-15.84-1.53-30.26-5.03-41.52-10.02
c2.57,21.6,10.09,44.02,18.47,55.7c0.06,0.08,0.11,0.16,0.16,0.23c12.5,17.2,34.52,11.43,49.31,0.69
c14.78-10.74,27.08-29.9,14.58-47.11C189.99,163.18,189.76,162.86,189.48,162.49z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

+62
View File
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 28.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Router_Medium_x5F_White" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 792 266.25" style="enable-background:new 0 0 792 266.25;" xml:space="preserve">
<style type="text/css">
.st0{fill:#4251B0;}
.st1{fill:#FA2921;}
.st2{fill:#ED79B5;}
.st3{fill:#FFB400;}
.st4{fill:#1E83F7;}
.st5{fill:#18C249;}
</style>
<g>
<path class="st0" d="M268.73,63.18c6.34,0,11.52,5.18,11.52,11.35c0,6.34-5.18,11.35-11.52,11.35s-11.69-5.01-11.69-11.35
C257.04,68.36,262.39,63.18,268.73,63.18z M258.88,122.45c0-3.01-0.67-7.85-0.67-10.68c0-6.01,4.67-10.68,10.52-10.68
c5.84,0,10.52,4.67,10.52,10.68c0,2.84-0.83,7.68-0.83,10.68v38.73c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.67,10.68-10.52,10.68
c-5.84,0-10.52-4.67-10.52-10.68c0-2.84,0.67-7.68,0.67-10.68V122.45z"/>
<path class="st0" d="M394.28,171.87c0-2.84,0.83-7.68,0.83-10.68V132.3c0-10.18-5.34-16.86-14.52-16.86c-6.01,0-11.35,3-14.86,8.85
c0.33,1.84,0.5,3.67,0.5,5.68v31.22c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.67,10.68-10.68,10.68c-5.51,0-10.35-4.67-10.35-10.68
c0-2.84,0.83-7.68,0.83-10.68V131.8c0-3.17-0.5-6.01-1.67-8.51c-2.17-4.84-6.51-7.85-12.52-7.85c-6.18,0-11.19,3.17-14.86,8.85
v36.9c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.84,10.68-10.52,10.68c-5.84,0-10.52-4.67-10.52-10.68c0-2.84,0.67-7.68,0.67-10.68
v-38.57c0-3.01-1.5-8.35-1.5-10.85c0-6.01,4.34-10.68,10.18-10.68c5.51,0,8.68,3.67,9.68,8.51c5.01-6.68,12.02-10.85,21.2-10.85
c10.85,0,18.7,5.18,23.54,13.52c5.51-8.68,13.52-13.52,23.54-13.52c16.86,0,29.72,12.19,29.72,31.72v30.72
c0,3.01,0.67,7.85,0.67,10.68c0,6.01-4.51,10.68-10.52,10.68C399.12,182.55,394.28,177.88,394.28,171.87z"/>
<path class="st0" d="M528.5,171.87c0-2.84,0.83-7.68,0.83-10.68V132.3c0-10.18-5.34-16.86-14.52-16.86c-6.01,0-11.35,3-14.86,8.85
c0.33,1.84,0.5,3.67,0.5,5.68v31.22c0,3.01,0.84,7.85,0.84,10.68c0,6.01-4.67,10.68-10.68,10.68c-5.51,0-10.35-4.67-10.35-10.68
c0-2.84,0.84-7.68,0.84-10.68V131.8c0-3.17-0.5-6.01-1.67-8.51c-2.17-4.84-6.51-7.85-12.52-7.85c-6.18,0-11.19,3.17-14.86,8.85
v36.9c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.84,10.68-10.52,10.68c-5.84,0-10.52-4.67-10.52-10.68c0-2.84,0.67-7.68,0.67-10.68
v-38.57c0-3.01-1.5-8.35-1.5-10.85c0-6.01,4.34-10.68,10.18-10.68c5.51,0,8.68,3.67,9.68,8.51c5.01-6.68,12.02-10.85,21.2-10.85
c10.85,0,18.7,5.18,23.54,13.52c5.51-8.68,13.52-13.52,23.54-13.52c16.86,0,29.72,12.19,29.72,31.72v30.72
c0,3.01,0.67,7.85,0.67,10.68c0,6.01-4.51,10.68-10.52,10.68C533.35,182.55,528.5,177.88,528.5,171.87z"/>
<path class="st0" d="M576.92,63.18c6.34,0,11.52,5.18,11.52,11.35c0,6.34-5.18,11.35-11.52,11.35s-11.69-5.01-11.69-11.35
C565.23,68.36,570.57,63.18,576.92,63.18z M567.07,122.45c0-3.01-0.67-7.85-0.67-10.68c0-6.01,4.67-10.68,10.52-10.68
s10.52,4.67,10.52,10.68c0,2.84-0.84,7.68-0.84,10.68v38.73c0,3.01,0.84,7.85,0.84,10.68c0,6.01-4.67,10.68-10.52,10.68
s-10.52-4.67-10.52-10.68c0-2.84,0.67-7.68,0.67-10.68V122.45z"/>
<path class="st0" d="M601.79,141.31c0-23.54,14.69-42.57,39.07-42.57c12.86,0,24.71,5.84,30.05,14.53c2,3.17,2.34,5.01,2.34,6.51
c0,5.18-4.01,9.52-9.85,9.52c-3.84,0-7.34-2.17-8.85-6.01c-2.34-5.18-6.85-8.18-13.69-8.18c-12.86,0-20.03,11.52-20.03,26.04
c0,14.69,7.51,26.04,20.53,26.04c7.01,0,12.02-2.5,14.36-7.68c1.67-3.51,4.84-6.51,9.18-6.51c6.01,0,9.68,4.17,9.68,9.35
c0,2.5-1,5.51-3.17,8.35c-5.51,7.35-15.86,13.19-30.05,13.19C616.32,183.89,601.79,165.19,601.79,141.31z"/>
<path class="st0" d="M737.69,171.87c0-2.84,0.67-7.68,0.67-10.68v-28.55c0-10.18-5.68-17.2-15.36-17.2
c-6.68,0-12.35,3.17-16.03,8.35v37.4c0,3.01,0.67,7.85,0.67,10.68c0,6.01-4.67,10.68-10.52,10.68s-10.52-4.67-10.52-10.68
c0-2.84,0.84-7.68,0.84-10.68v-80.8c0-3.01-0.84-7.85-0.84-10.68c0-6.01,4.84-10.68,10.52-10.68c5.84,0,10.52,4.67,10.52,10.68
c0,2.84-0.67,7.68-0.67,10.68v27.21c5.01-5.51,12.19-8.85,21.37-8.85c17.2,0,29.55,12.86,29.55,31.22v31.22
c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.84,10.68-10.52,10.68C742.36,182.55,737.69,177.88,737.69,171.87z"/>
</g>
<g>
<path class="st1" d="M114.82,96.21c11.92,10.55,21.52,21.86,27.7,32.52c10.62-18.99,17.71-41.55,17.8-55.92c0-0.1,0-0.19,0-0.28
c0-21.26-21.21-29.54-39.48-29.54s-39.48,8.28-39.48,29.54c0,0.29,0,0.68,0,1.15C91.54,78.2,103.61,86.29,114.82,96.21z"/>
<path class="st2" d="M49.8,154.19c7.45-8.29,18.88-17.27,31.77-24.86c13.72-8.07,27.44-13.71,39.49-16.3
c-14.78-15.96-34.04-29.68-47.68-34.21c-0.1-0.03-0.18-0.06-0.27-0.09c-20.22-6.57-34.65,11.05-40.3,28.42s-4.33,40.11,15.89,46.68
C48.99,153.93,49.35,154.05,49.8,154.19z"/>
<path class="st3" d="M209.07,106.86c-5.65-17.38-20.07-34.99-40.3-28.42c-0.28,0.09-0.65,0.21-1.09,0.35
c-1.16,11.08-5.12,25.07-11.09,38.79c-6.35,14.6-14.14,27.23-22.36,36.39c21.34,4.23,44.99,4,58.68-0.35
c0.1-0.03,0.19-0.06,0.27-0.09C213.4,146.97,214.71,124.24,209.07,106.86z"/>
<path class="st4" d="M102.8,171.18c-3.44-15.54-4.56-30.34-3.3-42.59c-19.75,9.12-38.75,23.2-47.27,34.78
c-0.06,0.08-0.11,0.16-0.16,0.23c-12.5,17.2-0.2,36.37,14.58,47.11s36.81,16.51,49.31-0.69c0.17-0.24,0.4-0.55,0.68-0.93
C111.05,199.44,106.04,185.79,102.8,171.18z"/>
<path class="st5" d="M189.48,162.49c-10.9,2.33-25.42,2.88-40.32,1.44c-15.84-1.53-30.26-5.03-41.52-10.02
c2.57,21.6,10.09,44.02,18.47,55.7c0.06,0.08,0.11,0.16,0.16,0.23c12.5,17.2,34.52,11.43,49.31,0.69
c14.78-10.74,27.08-29.9,14.58-47.11C189.99,163.18,189.76,162.86,189.48,162.49z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

+66
View File
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 28.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Router_Medium_x5F_Black_00000037681990313894948460000012967653829507626171_"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 792 792"
style="enable-background:new 0 0 792 792;" xml:space="preserve">
<style type="text/css">
.st0{fill:#ACCBFA;}
.st1{fill:#FA2921;}
.st2{fill:#ED79B5;}
.st3{fill:#FFB400;}
.st4{fill:#1E83F7;}
.st5{fill:#18C249;}
</style>
<g>
<path class="st0" d="M110.16,537.4c7.85,0,14.25,6.4,14.25,14.04c0,7.85-6.4,14.04-14.25,14.04s-14.45-6.19-14.45-14.04
C95.71,543.8,102.32,537.4,110.16,537.4z M97.98,610.7c0-3.72-0.83-9.71-0.83-13.22c0-7.43,5.78-13.22,13.01-13.22
s13.01,5.78,13.01,13.22c0,3.51-1.03,9.5-1.03,13.22v47.9c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.78,13.22-13.01,13.22
s-13.01-5.78-13.01-13.22c0-3.51,0.83-9.5,0.83-13.22V610.7z"/>
<path class="st0" d="M265.44,671.82c0-3.51,1.03-9.5,1.03-13.22v-35.72c0-12.6-6.61-20.85-17.96-20.85
c-7.43,0-14.04,3.72-18.38,10.94c0.41,2.27,0.62,4.54,0.62,7.02v38.61c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.78,13.22-13.22,13.22
c-6.81,0-12.8-5.78-12.8-13.22c0-3.51,1.03-9.5,1.03-13.22v-36.34c0-3.92-0.62-7.43-2.06-10.53c-2.69-5.99-8.05-9.71-15.49-9.71
c-7.64,0-13.83,3.92-18.38,10.94v45.63c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.99,13.22-13.01,13.22c-7.23,0-13.01-5.78-13.01-13.22
c0-3.51,0.83-9.5,0.83-13.22v-47.7c0-3.72-1.86-10.32-1.86-13.42c0-7.43,5.37-13.22,12.6-13.22c6.81,0,10.74,4.54,11.98,10.53
c6.19-8.26,14.87-13.42,26.22-13.42c13.42,0,23.13,6.4,29.11,16.73c6.81-10.74,16.73-16.73,29.11-16.73
c20.86,0,36.75,15.07,36.75,39.23v37.99c0,3.72,0.83,9.71,0.83,13.22c0,7.43-5.57,13.22-13.01,13.22
C271.43,685.04,265.44,679.26,265.44,671.82z"/>
<path class="st0" d="M431.45,671.82c0-3.51,1.03-9.5,1.03-13.22v-35.72c0-12.6-6.61-20.85-17.96-20.85
c-7.43,0-14.04,3.72-18.38,10.94c0.41,2.27,0.62,4.54,0.62,7.02v38.61c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.78,13.22-13.22,13.22
c-6.82,0-12.8-5.78-12.8-13.22c0-3.51,1.03-9.5,1.03-13.22v-36.34c0-3.92-0.62-7.43-2.06-10.53c-2.68-5.99-8.05-9.71-15.49-9.71
c-7.64,0-13.83,3.92-18.38,10.94v45.63c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.99,13.22-13.01,13.22c-7.23,0-13.01-5.78-13.01-13.22
c0-3.51,0.83-9.5,0.83-13.22v-47.7c0-3.72-1.86-10.32-1.86-13.42c0-7.43,5.37-13.22,12.6-13.22c6.82,0,10.74,4.54,11.98,10.53
c6.2-8.26,14.87-13.42,26.22-13.42c13.42,0,23.13,6.4,29.11,16.73c6.81-10.74,16.72-16.73,29.11-16.73
c20.86,0,36.75,15.07,36.75,39.23v37.99c0,3.72,0.83,9.71,0.83,13.22c0,7.43-5.57,13.22-13.01,13.22
C437.44,685.04,431.45,679.26,431.45,671.82z"/>
<path class="st0" d="M491.33,537.4c7.85,0,14.25,6.4,14.25,14.04c0,7.85-6.4,14.04-14.25,14.04s-14.45-6.19-14.45-14.04
C476.87,543.8,483.48,537.4,491.33,537.4z M479.15,610.7c0-3.72-0.83-9.71-0.83-13.22c0-7.43,5.78-13.22,13.01-13.22
s13.01,5.78,13.01,13.22c0,3.51-1.03,9.5-1.03,13.22v47.9c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.78,13.22-13.01,13.22
s-13.01-5.78-13.01-13.22c0-3.51,0.83-9.5,0.83-13.22V610.7z"/>
<path class="st0" d="M522.09,634.04c0-29.11,18.17-52.65,48.32-52.65c15.9,0,30.56,7.23,37.17,17.97c2.48,3.92,2.89,6.19,2.89,8.05
c0,6.4-4.96,11.77-12.18,11.77c-4.75,0-9.08-2.68-10.94-7.43c-2.89-6.4-8.47-10.12-16.93-10.12c-15.9,0-24.78,14.25-24.78,32.21
c0,18.17,9.29,32.21,25.4,32.21c8.67,0,14.87-3.1,17.76-9.5c2.06-4.34,5.99-8.05,11.36-8.05c7.43,0,11.98,5.16,11.98,11.56
c0,3.1-1.24,6.81-3.92,10.32c-6.82,9.09-19.62,16.31-37.17,16.31C540.06,686.69,522.09,663.56,522.09,634.04z"/>
<path class="st0" d="M690.17,671.82c0-3.51,0.83-9.5,0.83-13.22v-35.3c0-12.6-7.02-21.27-19-21.27c-8.26,0-15.28,3.92-19.82,10.32
v46.25c0,3.72,0.83,9.71,0.83,13.22c0,7.43-5.78,13.22-13.01,13.22s-13.01-5.78-13.01-13.22c0-3.51,1.03-9.5,1.03-13.22v-99.94
c0-3.72-1.03-9.71-1.03-13.22c0-7.43,5.99-13.22,13.01-13.22c7.23,0,13.01,5.78,13.01,13.22c0,3.51-0.83,9.5-0.83,13.22v33.66
c6.2-6.81,15.07-10.94,26.43-10.94c21.27,0,36.55,15.9,36.55,38.61v38.61c0,3.72,1.03,9.71,1.03,13.22
c0,7.43-5.99,13.22-13.01,13.22C695.95,685.04,690.17,679.26,690.17,671.82z"/>
</g>
<g>
<path class="st1" d="M376.76,216.42c28.32,25.07,51.15,51.95,65.83,77.27c25.23-45.12,42.08-98.73,42.3-132.88
c0-0.24,0-0.46,0-0.66c0-50.53-50.41-70.2-93.82-70.2s-93.82,19.66-93.82,70.2c0,0.69,0,1.62,0,2.73
C321.44,173.62,350.14,192.84,376.76,216.42z"/>
<path class="st2" d="M222.27,354.21c17.7-19.69,44.85-41.04,75.5-59.08c32.6-19.19,65.21-32.59,93.83-38.73
c-35.11-37.94-80.89-70.53-113.31-81.29c-0.23-0.07-0.44-0.14-0.63-0.21c-48.06-15.61-82.34,26.25-95.75,67.54
c-13.42,41.29-10.29,95.31,37.77,110.92C220.33,353.58,221.21,353.86,222.27,354.21z"/>
<path class="st3" d="M600.73,241.74c-13.42-41.29-47.69-83.15-95.75-67.54c-0.66,0.21-1.54,0.5-2.6,0.84
c-2.75,26.34-12.16,59.57-26.36,92.17c-15.09,34.68-33.6,64.69-53.14,86.48c50.7,10.05,106.9,9.52,139.45-0.83
c0.23-0.07,0.44-0.14,0.63-0.21C611.02,337.05,614.15,283.03,600.73,241.74z"/>
<path class="st4" d="M348.22,394.58c-8.17-36.93-10.84-72.09-7.84-101.2c-46.93,21.67-92.08,55.14-112.33,82.64
c-0.14,0.19-0.27,0.37-0.39,0.54c-29.7,40.88-0.48,86.42,34.64,111.94s87.46,39.24,117.16-1.64c0.41-0.56,0.95-1.31,1.6-2.21
C367.81,461.72,355.9,429.3,348.22,394.58z"/>
<path class="st5" d="M554.19,373.91c-25.9,5.53-60.41,6.84-95.81,3.42c-37.65-3.64-71.91-11.96-98.67-23.82
c6.11,51.33,23.99,104.61,43.89,132.37c0.14,0.19,0.27,0.37,0.39,0.54c29.7,40.88,82.04,27.16,117.16,1.64S585.5,417,555.8,376.12
C555.39,375.56,554.85,374.81,554.19,373.91z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

+66
View File
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 28.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Router_Medium_x5F_White_00000062189486027058041470000012691761407447023025_"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 792 792"
style="enable-background:new 0 0 792 792;" xml:space="preserve">
<style type="text/css">
.st0{fill:#4251B0;}
.st1{fill:#FA2921;}
.st2{fill:#ED79B5;}
.st3{fill:#FFB400;}
.st4{fill:#1E83F7;}
.st5{fill:#18C249;}
</style>
<g>
<path class="st0" d="M110.16,537.4c7.85,0,14.25,6.4,14.25,14.04c0,7.85-6.4,14.04-14.25,14.04s-14.45-6.19-14.45-14.04
C95.71,543.8,102.32,537.4,110.16,537.4z M97.98,610.7c0-3.72-0.83-9.71-0.83-13.22c0-7.43,5.78-13.22,13.01-13.22
s13.01,5.78,13.01,13.22c0,3.51-1.03,9.5-1.03,13.22v47.9c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.78,13.22-13.01,13.22
s-13.01-5.78-13.01-13.22c0-3.51,0.83-9.5,0.83-13.22V610.7z"/>
<path class="st0" d="M265.44,671.82c0-3.51,1.03-9.5,1.03-13.22v-35.72c0-12.6-6.61-20.85-17.96-20.85
c-7.43,0-14.04,3.72-18.38,10.94c0.41,2.27,0.62,4.54,0.62,7.02v38.61c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.78,13.22-13.22,13.22
c-6.81,0-12.8-5.78-12.8-13.22c0-3.51,1.03-9.5,1.03-13.22v-36.34c0-3.92-0.62-7.43-2.06-10.53c-2.69-5.99-8.05-9.71-15.49-9.71
c-7.64,0-13.83,3.92-18.38,10.94v45.63c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.99,13.22-13.01,13.22c-7.23,0-13.01-5.78-13.01-13.22
c0-3.51,0.83-9.5,0.83-13.22v-47.7c0-3.72-1.86-10.32-1.86-13.42c0-7.43,5.37-13.22,12.6-13.22c6.81,0,10.74,4.54,11.98,10.53
c6.19-8.26,14.87-13.42,26.22-13.42c13.42,0,23.13,6.4,29.11,16.73c6.81-10.74,16.73-16.73,29.11-16.73
c20.86,0,36.75,15.07,36.75,39.23v37.99c0,3.72,0.83,9.71,0.83,13.22c0,7.43-5.57,13.22-13.01,13.22
C271.43,685.04,265.44,679.26,265.44,671.82z"/>
<path class="st0" d="M431.45,671.82c0-3.51,1.03-9.5,1.03-13.22v-35.72c0-12.6-6.61-20.85-17.96-20.85
c-7.43,0-14.04,3.72-18.38,10.94c0.41,2.27,0.62,4.54,0.62,7.02v38.61c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.78,13.22-13.22,13.22
c-6.82,0-12.8-5.78-12.8-13.22c0-3.51,1.03-9.5,1.03-13.22v-36.34c0-3.92-0.62-7.43-2.06-10.53c-2.68-5.99-8.05-9.71-15.49-9.71
c-7.64,0-13.83,3.92-18.38,10.94v45.63c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.99,13.22-13.01,13.22c-7.23,0-13.01-5.78-13.01-13.22
c0-3.51,0.83-9.5,0.83-13.22v-47.7c0-3.72-1.86-10.32-1.86-13.42c0-7.43,5.37-13.22,12.6-13.22c6.82,0,10.74,4.54,11.98,10.53
c6.2-8.26,14.87-13.42,26.22-13.42c13.42,0,23.13,6.4,29.11,16.73c6.81-10.74,16.72-16.73,29.11-16.73
c20.86,0,36.75,15.07,36.75,39.23v37.99c0,3.72,0.83,9.71,0.83,13.22c0,7.43-5.57,13.22-13.01,13.22
C437.44,685.04,431.45,679.26,431.45,671.82z"/>
<path class="st0" d="M491.33,537.4c7.85,0,14.25,6.4,14.25,14.04c0,7.85-6.4,14.04-14.25,14.04s-14.45-6.19-14.45-14.04
C476.87,543.8,483.48,537.4,491.33,537.4z M479.15,610.7c0-3.72-0.83-9.71-0.83-13.22c0-7.43,5.78-13.22,13.01-13.22
s13.01,5.78,13.01,13.22c0,3.51-1.03,9.5-1.03,13.22v47.9c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.78,13.22-13.01,13.22
s-13.01-5.78-13.01-13.22c0-3.51,0.83-9.5,0.83-13.22V610.7z"/>
<path class="st0" d="M522.09,634.04c0-29.11,18.17-52.65,48.32-52.65c15.9,0,30.56,7.23,37.17,17.97c2.48,3.92,2.89,6.19,2.89,8.05
c0,6.4-4.96,11.77-12.18,11.77c-4.75,0-9.08-2.68-10.94-7.43c-2.89-6.4-8.47-10.12-16.93-10.12c-15.9,0-24.78,14.25-24.78,32.21
c0,18.17,9.29,32.21,25.4,32.21c8.67,0,14.87-3.1,17.76-9.5c2.06-4.34,5.99-8.05,11.36-8.05c7.43,0,11.98,5.16,11.98,11.56
c0,3.1-1.24,6.81-3.92,10.32c-6.82,9.09-19.62,16.31-37.17,16.31C540.06,686.69,522.09,663.56,522.09,634.04z"/>
<path class="st0" d="M690.17,671.82c0-3.51,0.83-9.5,0.83-13.22v-35.3c0-12.6-7.02-21.27-19-21.27c-8.26,0-15.28,3.92-19.82,10.32
v46.25c0,3.72,0.83,9.71,0.83,13.22c0,7.43-5.78,13.22-13.01,13.22s-13.01-5.78-13.01-13.22c0-3.51,1.03-9.5,1.03-13.22v-99.94
c0-3.72-1.03-9.71-1.03-13.22c0-7.43,5.99-13.22,13.01-13.22c7.23,0,13.01,5.78,13.01,13.22c0,3.51-0.83,9.5-0.83,13.22v33.66
c6.2-6.81,15.07-10.94,26.43-10.94c21.27,0,36.55,15.9,36.55,38.61v38.61c0,3.72,1.03,9.71,1.03,13.22
c0,7.43-5.99,13.22-13.01,13.22C695.95,685.04,690.17,679.26,690.17,671.82z"/>
</g>
<g>
<path class="st1" d="M376.76,216.42c28.32,25.07,51.15,51.95,65.83,77.27c25.23-45.12,42.08-98.73,42.3-132.88
c0-0.24,0-0.46,0-0.66c0-50.53-50.41-70.2-93.82-70.2s-93.82,19.66-93.82,70.2c0,0.69,0,1.62,0,2.73
C321.44,173.62,350.14,192.84,376.76,216.42z"/>
<path class="st2" d="M222.27,354.21c17.7-19.69,44.85-41.04,75.5-59.08c32.6-19.19,65.21-32.59,93.83-38.73
c-35.11-37.94-80.89-70.53-113.31-81.29c-0.23-0.07-0.44-0.14-0.63-0.21c-48.06-15.61-82.34,26.25-95.75,67.54
c-13.42,41.29-10.29,95.31,37.77,110.92C220.33,353.58,221.21,353.86,222.27,354.21z"/>
<path class="st3" d="M600.73,241.74c-13.42-41.29-47.69-83.15-95.75-67.54c-0.66,0.21-1.54,0.5-2.6,0.84
c-2.75,26.34-12.16,59.57-26.36,92.17c-15.09,34.68-33.6,64.69-53.14,86.48c50.7,10.05,106.9,9.52,139.45-0.83
c0.23-0.07,0.44-0.14,0.63-0.21C611.02,337.05,614.15,283.03,600.73,241.74z"/>
<path class="st4" d="M348.22,394.58c-8.17-36.93-10.84-72.09-7.84-101.2c-46.93,21.67-92.08,55.14-112.33,82.64
c-0.14,0.19-0.27,0.37-0.39,0.54c-29.7,40.88-0.48,86.42,34.64,111.94s87.46,39.24,117.16-1.64c0.41-0.56,0.95-1.31,1.6-2.21
C367.81,461.72,355.9,429.3,348.22,394.58z"/>
<path class="st5" d="M554.19,373.91c-25.9,5.53-60.41,6.84-95.81,3.42c-37.65-3.64-71.91-11.96-98.67-23.82
c6.11,51.33,23.99,104.61,43.89,132.37c0.14,0.19,0.27,0.37,0.39,0.54c29.7,40.88,82.04,27.16,117.16,1.64S585.5,417,555.8,376.12
C555.39,375.56,554.85,374.81,554.19,373.91z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

+25 -94
View File
@@ -1,98 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="svg2781" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 564.2 553.5"
style="enable-background:new 0 0 564.2 553.5;" xml:space="preserve">
<!-- Generator: Adobe Illustrator 28.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Flower" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 792 792" style="enable-background:new 0 0 792 792;" xml:space="preserve">
<style type="text/css">
.st0{fill:#4081EF;stroke:#512D8C;stroke-miterlimit:10;}
.st1{fill:#31A452;stroke:#512D8C;stroke-miterlimit:10;}
.st2{fill:#DE7FB3;stroke:#512D8C;stroke-miterlimit:10;}
.st3{fill:#FFB800;stroke:#512D8C;stroke-miterlimit:10;}
.st4{fill:#E64132;stroke:#512D8C;stroke-miterlimit:10;}
.st5{fill:#F2F5FB;stroke:#512D8C;stroke-miterlimit:10;}
.st0{fill:#FA2921;}
.st1{fill:#ED79B5;}
.st2{fill:#FFB400;}
.st3{fill:#1E83F7;}
.st4{fill:#18C249;}
</style>
<path class="st0" d="M210.5,549.6c-2.2-0.2-5.5-1-9.7-2.2c-52.4-15.7-99-46.5-133.8-88.5c-8.8-10.7-17.2-22.4-19.4-27.5
c-8.1-18.1-6.3-38.7,4.8-55.4c5-7.5,13.2-15,20.5-18.7c1.2-0.6,54.1-20,55.8-20.4c0.5-0.1,0.5,0.2-0.3,2.1c-0.7,1.7-1,3.1-1.1,5.5
l-0.1,3.2l2.8,5.8c8.7,17.9,19.2,32.7,33.2,46.4c6.3,6.2,7.8,7.6,13.8,12.3c22.7,18.1,52,30.7,79.9,34.3c2.5,0.3,5,0.8,5.7,1
c2.8,0.9,7.7-0.8,11-3.7l1.8-1.6l-0.2,4.8c-0.1,2.7-0.6,15.4-1,28.3c-0.6,20.3-0.8,24-1.5,27.5c-3.9,20.7-18.6,37.5-38.4,44.1
c-4.6,1.5-8,2.2-13.1,2.7C216.6,550.1,215.3,550,210.5,549.6z"/>
<path class="st1" d="M339.8,549.4c-4-0.4-9.4-1.6-13.2-2.9c-3.4-1.2-10-4.4-12.5-6.1c-10.9-7.4-19-17.9-23.1-30
c-2.2-6.7-2.3-7.5-3.3-36.9c-0.5-14.9-0.9-27.9-0.9-28.9l0-1.9l2.3,1.8c2.6,2,6.6,3.4,8.5,3.1c0.6-0.1,3-0.5,5.3-0.8
c37.7-5.3,71.2-22.2,97.4-49.1c12.2-12.5,21.4-25.5,29.9-42.4l3.5-7l0-3.6c0-3.1-0.1-3.8-1-5.7c-0.5-1.2-0.9-2.1-0.9-2.2
c0.2-0.2,55.3,20.1,56.9,20.9c2.6,1.3,6.6,4.1,9.9,7c9.2,7.7,16.1,19.4,18.8,31.8c0.7,3.1,0.8,4.8,0.8,11.3c0,8.6-0.5,11.7-2.9,18.7
c-1.7,5-2.9,7.2-7.1,13.1c-7.6,11-15.3,20.5-25.2,31.2c-32.8,35.4-76.5,62.5-123.4,76.3C351.6,549.6,347.2,550.1,339.8,549.4z"/>
<path class="st2" d="M255.6,438c-25.9-4.2-50.7-14.9-71.7-31c-5.2-4-8.7-7.1-14.1-12.4c-12.7-12.5-21.9-24.9-30.5-41.4
c-2.3-4.4-2.4-4.7-2.4-7.1c0-8.8,8.5-15.2,16.9-12.7c5.6,1.7,9.6,6.8,9.7,12.2c0,2.6-0.8,4.6-2.6,6.2c-1.2,1.1-3.2,1.9-4.6,1.9
c-1.2,0-3.3-0.8-4.3-1.6c-2.1-1.8-2-1,0.4,3.2c19.3,33.8,52.3,59.1,90,69.1c5.7,1.5,11.5,2.7,11.8,2.4c0.1-0.1-0.4-0.8-1.3-1.6
c-5.1-4.5-2.3-11.7,5-12.8c5.4-0.8,11.4,2.7,13.9,8c0.8,1.7,1,2.5,1,5.3s-0.1,3.5-1,5.3c-2,4.3-6.8,7.9-10.3,7.8
C260.6,438.7,257.9,438.3,255.6,438z"/>
<path class="st0" d="M297.6,438.2c-3.4-1.3-6.4-4.3-7.8-8.1c-1.1-2.9-0.9-7.3,0.5-10.2c2.6-5.3,8.7-8.5,14.4-7.5
c2.9,0.5,4.7,1.9,6,4.3c0.8,1.6,1,2.2,0.8,3.6c-0.3,2.2-0.9,3.3-2.7,4.8c-0.8,0.7-1.4,1.4-1.3,1.5c0.5,0.5,13.4-2.7,21.3-5.4
c33.6-11.3,62.5-35.1,80.4-66.1c2.5-4.4,2.6-5,0.5-3.2c-2.8,2.4-7,1.9-9.6-1c-4-4.6-0.7-13.8,6.1-16.9c2-0.9,2.7-1,5.5-1
c2.9,0,3.5,0.1,5.6,1.1c4.4,2.1,7.4,6.4,7.8,11c0.2,2.2,0.1,2.3-2.2,6.9c-23,45.9-67,78.1-117.2,85.9
C300.2,438.8,299.4,438.9,297.6,438.2z"/>
<path class="st1" d="M211.1,398.5c-4.7-0.9-8.7-2.7-12.9-5.9c-10.8-8.1-13.5-22.3-6.6-33.7c0.7-1.2,1.1-2.2,1-2.4
c-0.2-0.2-1.2-0.6-2.3-1.1c-7.6-3-13-10.6-13.5-19.1c-0.5-7.4,3.1-15,9-19.4c1-0.7,2.2-1.5,2.6-1.8c0.8-0.4,68.9-22.7,69.4-22.7
c0.2,0,0.7,0.7,1.2,1.5c0.5,0.8,1.6,2.3,2.4,3.3c1.2,1.4,1.5,1.9,1.2,2.3c-0.2,0.3-6.9,9.5-14.8,20.5
c-15.9,21.9-15.5,21.3-13.4,23.4c1.3,1.3,2.9,1.4,4.4,0.3c0.6-0.4,7.5-9.7,15.5-20.7c11.2-15.4,14.6-19.9,15-19.7
c0.9,0.4,5.5,1.9,6.6,2.1l1,0.2l0,35.3c0,39.7,0,38.8-2.5,44c-2.6,5.3-7.2,9.3-12.7,11.2c-3.7,1.3-6.8,1.6-10.2,1
c-5.5-0.9-9.8-3.2-13.7-7.4l-2.2-2.4l-0.6,0.9c-3,4.3-8.6,8.1-14,9.5C218.2,398.6,213.2,398.9,211.1,398.5z"/>
<path class="st3" d="M342.9,398.5c-5.5-0.9-9.9-3.2-14.3-7.6l-3.2-3.2l-0.7,1c-2.3,3.3-6.8,6.5-11.1,7.9c-3.7,1.2-9.2,1.4-12.6,0.3
c-7.1-2.1-12.7-7.4-15.2-14.3l-0.9-2.6v-37.1v-37.1l1.8-0.4c1-0.2,2.7-0.8,3.9-1.2c1.1-0.5,2.1-0.8,2.2-0.7c0.1,0.1,6.5,9,14.4,19.9
c7.8,10.9,14.7,20.1,15.2,20.5c2.2,1.9,5.4,0.4,5.4-2.6c0-1.4-1-2.9-13.8-20.5c-7.6-10.5-14.2-19.6-14.7-20.4l-0.9-1.3l1.4-1.7
c0.8-0.9,1.9-2.5,2.5-3.4l1-1.6l34.4,11.2c18.9,6.2,35.1,11.6,35.9,12.1c6.8,4,11.1,11.3,11.1,19.1c0,4.1-0.5,6.4-2.4,10.2
c-2,4.1-5.5,7.6-9.6,9.7c-1.6,0.8-3.2,1.5-3.4,1.5c-1,0-0.9,0.7,0.3,2.6c2.8,4.3,4,8.5,3.9,13.7c0,8.1-3.7,15.2-10.6,20.3
C356.4,397.6,349.5,399.5,342.9,398.5z"/>
<path class="st2" d="M53.9,341.9c-0.5-0.1-2.3-0.4-3.9-0.7c-15.6-2.6-30.4-12.6-38.8-26.2c-3.5-5.7-6.4-13.2-7.8-19.9
c-1.2-6.1-0.8-28.1,0.8-43.1c4.5-43,19-84.3,42.2-120.7c6.5-10.2,14.9-21.5,18.2-24.6c17.8-16.6,43.1-20.5,64.8-10
c4.3,2.1,8.8,5.1,12.7,8.6c2.8,2.4,5.8,6.1,20.9,25.5c9.7,12.5,17.8,22.8,17.9,23c0.2,0.2-0.9,0.4-3.2,0.4c-2.5,0-4.1,0.2-5.7,0.7
c-2.1,0.7-2.6,1.1-7.9,6.3c-8.2,8.1-14.4,15.3-20.3,23.9c-15.5,22.2-25.4,47.7-28.8,74.8c-2.2,16.9-1.6,37.5,1.6,52.3
c0.3,1.4,0.5,2.8,0.4,3c-0.1,0.2,0.2,1.3,0.8,2.4c1.1,2.4,4.3,5.7,6.5,6.8l1.5,0.8l-1.2,0.4c-0.7,0.2-13.1,3.8-27.6,8
c-16.4,4.7-27.7,7.8-29.8,8.1C64.1,342.1,56.1,342.3,53.9,341.9z"/>
<path class="st3" d="M494.7,341.7c-2.1-0.3-33.8-9.1-56.5-15.8l-2.5-0.7l1.6-0.8c3.4-1.7,7.2-6.6,7.3-9.6c0-0.7,0.4-3.3,0.8-5.8
c3.9-22.7,3.1-46.1-2.5-68.4c-6.4-25.5-18.6-49.2-35.8-69.1c-4.6-5.3-14.8-15.4-16.4-16.1c-2.4-1.1-5.1-1.6-8-1.4l-2.7,0.2l1.2-1.5
c0.7-0.8,8.5-10.8,17.5-22.3c8.9-11.5,17.2-21.8,18.5-23.1c2.6-2.7,7-6.2,10.3-8.2c19.3-11.6,43-11.1,61.6,1.2
c5.4,3.6,8.2,6.2,12.3,11.7c26.4,34.5,44,73.7,52.3,116.2c3.4,17.6,4.9,33.3,5,52.4c0,13-0.2,14.8-2.5,21.8
C547.8,328.6,521.7,345.2,494.7,341.7z"/>
<path class="st4" d="M133.9,318.5c-2-0.5-4.6-1.9-6-3.3c-2.5-2.4-3.1-3.5-3.7-7.3c-4.4-27.3-2.2-54,6.7-79.3
c5.3-15.1,13.5-30.5,23-43.1c5.8-7.8,16.6-19.5,19-20.7c4.7-2.4,11.3-1.2,15.2,2.7c5.4,5.4,5.2,13.9-0.3,19.1
c-4.3,4-9.4,4.4-12.6,0.9c-1.7-1.9-2.2-3.9-1.7-6.4c0.2-1.1,0.3-2,0.2-2.2c-0.3-0.3-3.6,3.3-8.3,9.1c-17.6,21.8-28.5,48-31.9,76.5
c-1.1,9.3-1,26.4,0.1,34.6c0.3,1.8,0.8,1.9,1.4,0.1c0.9-2.6,4-4.7,6.8-4.7c3,0,5.9,2.2,7.5,5.7c0.6,1.3,0.8,2.3,0.8,5.2
c0,3.3-0.1,3.8-1.1,5.7c-1.4,2.7-4.6,5.7-7.1,6.6C139.4,318.6,135.8,318.9,133.9,318.5z"/>
<path class="st1" d="M422.6,318.5c-3.7-0.6-7.7-3.6-9.4-7.1c-3.8-7.5,0.1-16.9,6.9-16.9c3.1,0,5.8,2,6.9,5.2
c0.4,1.2,0.5,1.3,0.7,0.7c1.3-3.7,1.7-26.4,0.6-35.7c-3.6-29.6-14.5-55.3-33-77.9c-5.5-6.7-8.4-9.4-7.1-6.6c0.7,1.4,0.5,4.3-0.3,5.9
c-0.9,1.7-3.2,3.5-5,3.8c-3.2,0.6-7.9-1.6-10.2-4.8c-6.5-8.8-0.5-21.2,10.4-21.4c4.6-0.1,5.2,0.3,11.2,6.4
c12.1,12.3,21.1,24.9,28.8,40.3c13.2,26.3,18.6,54.9,16.1,84.5c-0.5,5.6-2,15.7-2.6,17.1c-1.3,2.8-4.8,5.5-8.4,6.5
C425.9,318.9,425.1,318.9,422.6,318.5z"/>
<path class="st0" d="M178.2,307.2c-6-1.3-12.2-6.2-14.9-11.7c-3.4-7-3.1-15.1,0.9-21.6c0.7-1.2,1.2-2.3,1.1-2.4
c-0.1-0.1-1.1-0.6-2.1-1c-3.9-1.5-8.1-4.8-10.7-8.3c-4.6-6.2-6.1-14.6-3.9-22.1c2.9-10.3,9.4-16.8,19.1-19.3c2.8-0.7,9-0.8,11.7,0
c1.1,0.3,2.2,0.5,2.4,0.5c0.2,0,0.3-0.7,0.3-1.5c0-2.9,0.8-5.8,2.4-9.2c5.2-10.8,18.1-15.5,29-10.5c2.7,1.2,6.2,3.8,7.8,5.8
c0.7,0.8,10.3,14,21.5,29.4l20.3,27.9l-1.5,1.8c-0.8,1-1.9,2.6-2.5,3.5c-0.6,1-1.2,1.7-1.5,1.6c-4.5-1.7-46.7-15-47.7-15
c-1.9,0-3.1,1.3-3.1,3.2c0,1,0.2,1.7,0.8,2.3c0.6,0.6,7.8,3.1,24.5,8.5l23.7,7.7l-0.1,4.3l-0.1,4.3L223,295.9
c-18,5.9-33.9,10.9-35.2,11.2C184.7,307.8,181.2,307.8,178.2,307.2z"/>
<path class="st4" d="M372.5,306.8c-1.8-0.5-17.5-5.6-35-11.3l-31.8-10.4l1-4.3v-4.3l22.6-7.7c15-4.9,24-8,24.6-8.5
c0.7-0.6,0.9-1.1,0.9-2.2c0-2-1.2-3.3-3.1-3.3c-0.9,0-10.5,2.9-24.7,7.5c-12.8,4.1-23.4,7.5-23.6,7.5c-0.1,0-0.7-0.8-1.3-1.9
c-0.6-1-1.6-2.5-2.2-3.2c-0.7-0.7-1.2-1.5-1.2-1.6c0-0.2,9.6-13.5,21.4-29.6c18.9-26,21.6-29.6,23.6-31.1c5.7-4.4,13.1-5.8,19.7-3.9
c9,2.7,16.1,11.6,16.1,20.3c0,2.3-0.1,2.3,3.1,1.5c4.7-1.1,11.5-0.5,16,1.5c4.6,2,9,6,11.5,10.2c2.1,3.6,3.9,9.4,4.2,13.2
c0.3,5.2-1.1,10.7-4,15.3c-2.6,4.1-7.8,8.3-12.1,9.8c-0.9,0.3-1.7,0.8-1.7,1c0,0.2,0.4,1,0.9,1.7c2.4,3.6,3.6,7.7,3.5,12.7
c0,5.8-2.1,10.7-6.4,15.1c-4,4.1-8.9,6.3-14.9,6.5C376.3,307.7,375.3,307.6,372.5,306.8z"/>
<path class="st5" d="M276.2,298.9c-6.1-1.6-11.4-6.8-13.2-12.9c-0.7-2.4-0.7-7.5,0-9.9c1.7-5.8,6.6-10.8,12.3-12.5
c2.7-0.8,7.2-0.9,10-0.2c6.2,1.6,11.6,7.1,13.2,13.3c1.6,6-0.3,12.6-5,17.3C288.9,298.6,282.2,300.5,276.2,298.9z"/>
<path class="st2" d="M248.3,229.8c-13.3-18.3-21.2-29.6-22-31.1c-1.4-3-1.9-5.5-1.9-9.4c0-14.1,13.1-24.4,27.1-21.4
c1.4,0.3,2.6,0.5,2.7,0.5s0.3-1.3,0.4-2.8c0.8-10.7,8.4-19.6,18.9-22.4c3.9-1,10.6-1,14.5,0c8.9,2.3,15.9,9.3,18.2,18.2
c0.4,1.5,0.7,3.7,0.7,4.9c0,1.2,0.1,2.1,0.3,2.1s1.5-0.3,3-0.6c7.4-1.6,15.2,0.7,20.5,6c4.3,4.3,6.6,9.6,6.6,15.6
c0,4-0.6,6.5-2.4,10c-0.6,1.2-10.4,15-21.7,30.7c-17.8,24.5-20.8,28.5-21.4,28.3c-0.4-0.1-1.9-0.6-3.4-1.1c-1.5-0.5-2.9-0.9-3.3-0.9
c-0.7,0-0.7-0.8-0.3-25.5v-25.5l-1.4-0.9c-1-1.1-2.5-1.5-3.8-0.9c-2,0.8-2-0.5-1.8,27.2v25.8h-1.2c-0.5-0.2-2.4,0.3-4,0.9
s-3.1,1.1-3.2,1.1C269.2,258.5,259.8,245.6,248.3,229.8z"/>
<path class="st3" d="M210.9,164.8c-4.1-0.9-7.7-3.6-9.6-7.4c-1.4-2.8-1.7-7.3-0.5-10.3c1.7-4.5,3.9-6.1,15.6-11.2
c15.8-7,31.4-11.1,49.2-12.9c7.3-0.8,23.2-0.8,30.6,0c17.4,1.8,33.3,6,49.1,13c7.3,3.2,12.5,6.1,13.6,7.5c4.3,5.6,3.8,12.7-1.1,17.6
c-5.1,5.1-12.9,5.4-18.1,0.7c-2-1.8-3-3.5-3.4-5.6c-0.7-4,2.9-8.1,7.3-8.2c1.4,0,1.5-0.1,1.1-0.5c-0.3-0.3-2.2-1.2-4.3-2.1
c-33.2-14.5-70.5-16.4-105-5.4c-7.5,2.4-19,7.2-18.6,7.7c0.1,0.2,0.8,0.3,1.6,0.3c5.6,0,9.1,6.2,6.1,10.8
C221.6,163.3,215.9,165.9,210.9,164.8z"/>
<path class="st4" d="M174.7,123.4c-8.9-13.1-16.8-25.1-17.5-26.6c-1.6-3.3-3.6-9.2-4.4-13c-2.6-12.5-0.9-25.8,5-37.5
c4.2-8.3,11.2-16.3,18.6-21.3c5-3.4,6.1-3.9,12.8-6.3c23.1-8.2,47.2-13.1,73.4-15c7.5-0.6,28.5-0.6,36.3,0
c25.5,1.8,50.6,6.9,73,14.8c6.4,2.2,8.2,3.1,13.1,6.5c9.8,6.6,18.1,17.5,22,29.2c2.2,6.5,2.7,10,2.7,17.9c0,7.9-0.5,11.3-2.7,17.9
c-2.3,6.8-3.7,9.1-20.3,33.6l-16.1,23.8l-0.4-2.2c-0.2-1.2-0.9-3-1.4-4c-1-1.8-4.4-5.6-4.7-5.2c-0.1,0.1-1.2-0.4-2.4-1.1
c-9.1-5.2-21.9-10.5-33.2-13.9c-37-11-77.2-8.8-113,6.1c-4.9,2.1-17.7,8.4-19.2,9.5c-2.2,1.6-5.1,6.8-5.1,9c0,0.4-0.1,1-0.3,1.2
C191,147,184.7,138,174.7,123.4z"/>
<g id="Flower_00000077325900055813483940000000694823054982625702_">
<path class="st0" d="M375.48,267.63c38.64,34.21,69.78,70.87,89.82,105.42c34.42-61.56,57.42-134.71,57.71-181.3
c0-0.33,0-0.63,0-0.91c0-68.94-68.77-95.77-128.01-95.77s-128.01,26.83-128.01,95.77c0,0.94,0,2.2,0,3.72
C300.01,209.24,339.15,235.47,375.48,267.63z"/>
<path class="st1" d="M164.7,455.63c24.15-26.87,61.2-55.99,103.01-80.61c44.48-26.18,88.97-44.47,128.02-52.84
c-47.91-51.76-110.37-96.24-154.6-110.91c-0.31-0.1-0.6-0.19-0.86-0.28c-65.57-21.3-112.34,35.81-130.64,92.15
c-18.3,56.34-14.04,130.04,51.53,151.34C162.05,454.77,163.25,455.16,164.7,455.63z"/>
<path class="st2" d="M681.07,302.19c-18.3-56.34-65.07-113.45-130.64-92.15c-0.9,0.29-2.1,0.68-3.54,1.15
c-3.75,35.93-16.6,81.27-35.96,125.76c-20.59,47.32-45.84,88.27-72.51,118c69.18,13.72,145.86,12.98,190.26-1.14
c0.31-0.1,0.6-0.2,0.86-0.28C695.11,432.22,699.37,358.52,681.07,302.19z"/>
<path class="st3" d="M336.54,510.71c-11.15-50.39-14.8-98.36-10.7-138.08c-64.03,29.57-125.63,75.23-153.26,112.76
c-0.19,0.26-0.37,0.51-0.53,0.73c-40.52,55.78-0.66,117.91,47.27,152.72c47.92,34.82,119.33,53.54,159.86-2.24
c0.56-0.76,1.3-1.78,2.19-3.01C363.28,602.32,347.02,558.08,336.54,510.71z"/>
<path class="st4" d="M617.57,482.52c-35.33,7.54-82.42,9.33-130.72,4.66c-51.37-4.96-98.11-16.32-134.63-32.5
c8.33,70.03,32.73,142.73,59.88,180.6c0.19,0.26,0.37,0.51,0.53,0.73c40.52,55.78,111.93,37.06,159.86,2.24
c47.92-34.82,87.79-96.95,47.27-152.72C619.2,484.77,618.46,483.75,617.57,482.52z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 540 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 570 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

+24 -1
View File
@@ -99,7 +99,7 @@ services:
redis:
container_name: immich_redis
image: redis:6.2-alpine@sha256:51d6c56749a4243096327e3fb964a48ed92254357108449cb6e23999c37773c5
image: redis:6.2-alpine@sha256:3fcb624d83a9c478357f16dc173c58ded325ccc5fd2a4375f3916c04cc579f70
database:
container_name: immich_postgres
@@ -114,6 +114,29 @@ services:
- ${UPLOAD_LOCATION}/postgres:/var/lib/postgresql/data
ports:
- 5432:5432
# set IMMICH_METRICS=true in .env to enable metrics
# immich-prometheus:
# container_name: immich_prometheus
# ports:
# - 9090:9090
# image: prom/prometheus
# volumes:
# - ./prometheus.yml:/etc/prometheus/prometheus.yml
# - prometheus-data:/prometheus
# first login uses admin/admin
# add data source for http://immich-prometheus:9090 to get started
# immich-grafana:
# container_name: immich_grafana
# command: ['./run.sh', '-disable-reporting']
# ports:
# - 3000:3000
# image: grafana/grafana:10.3.3-ubuntu
# volumes:
# - grafana-data:/var/lib/grafana
volumes:
model-cache:
prometheus-data:
grafana-data:
+24 -1
View File
@@ -56,7 +56,7 @@ services:
redis:
container_name: immich_redis
image: redis:6.2-alpine@sha256:51d6c56749a4243096327e3fb964a48ed92254357108449cb6e23999c37773c5
image: redis:6.2-alpine@sha256:3fcb624d83a9c478357f16dc173c58ded325ccc5fd2a4375f3916c04cc579f70
restart: always
database:
@@ -73,5 +73,28 @@ services:
ports:
- 5432:5432
# set IMMICH_METRICS=true in .env to enable metrics
immich-prometheus:
container_name: immich_prometheus
ports:
- 9090:9090
image: prom/prometheus@sha256:5ccad477d0057e62a7cd1981ffcc43785ac10c5a35522dc207466ff7e7ec845f
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
# first login uses admin/admin
# add data source for http://immich-prometheus:9090 to get started
immich-grafana:
container_name: immich_grafana
command: ['./run.sh', '-disable-reporting']
ports:
- 3000:3000
image: grafana/grafana:10.4.0-ubuntu@sha256:c1f582b7cc4c1b9805d187b5600ce7879550a12ef6d29571da133c3d3fc67a9c
volumes:
- grafana-data:/var/lib/grafana
volumes:
model-cache:
prometheus-data:
grafana-data:
+6 -2
View File
@@ -1,9 +1,9 @@
version: "3.8"
# Configurations for hardware-accelerated transcoding
# Configurations for hardware-accelerated transcoding
# If using Unraid or another platform that doesn't allow multiple Compose files,
# you can inline the config for a backend by copying its contents
# you can inline the config for a backend by copying its contents
# into the immich-microservices service in the docker-compose.yml file.
# See https://immich.app/docs/features/hardware-transcoding for more info on using hardware transcoding.
@@ -38,6 +38,10 @@ services:
- /dev/dri:/dev/dri
- /dev/dma_heap:/dev/dma_heap
- /dev/mpp_service:/dev/mpp_service
#- /dev/mali0:/dev/mali0 # only required to enable OpenCL-accelerated HDR -> SDR tonemapping
volumes:
#- /etc/OpenCL:/etc/OpenCL:ro # only required to enable OpenCL-accelerated HDR -> SDR tonemapping
#- /usr/lib/aarch64-linux-gnu/libmali.so.1:/usr/lib/aarch64-linux-gnu/libmali.so.1:ro # only required to enable OpenCL-accelerated HDR -> SDR tonemapping
vaapi:
devices:
+12
View File
@@ -0,0 +1,12 @@
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: immich_server
static_configs:
- targets: ['immich-server:8081']
- job_name: immich_microservices
static_configs:
- targets: ['immich-microservices:8081']
@@ -101,7 +101,7 @@ Some storage locations are impacted by the Storage Template. See below for more
<TabItem value="Storage Template Off (Default)." label="Storage Template Off (Default)." default>
:::note
`UPLOAD_LOCATION/library` folder is not used by default on new machines running version 1.92.0. These are if the system administrator activated the storage template engine, for [more info](https://github.com/immich-app/immich/releases#:~:text=the%20partner%E2%80%99s%20assets.-,Hardening%20storage%20template,-We%20have%20further).
`UPLOAD_LOCATION/library` folder is not used by default on new machines running version 1.92.0. These are if the system administrator activated the storage template engine, for [more info](https://github.com/immich-app/immich/releases/tag/v1.92.0#:~:text=the%20partner%E2%80%99s%20assets.-,Hardening%20storage%20template).
:::
**1. User-Specific Folders:**
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

+10 -2
View File
@@ -11,7 +11,7 @@ Unable to set `app.immich:/` as a valid redirect URI? See [Mobile Redirect URI](
Immich supports 3rd party authentication via [OpenID Connect][oidc] (OIDC), an identity layer built on top of OAuth2. OIDC is supported by most identity providers, including:
- [Authentik](https://goauthentik.io/integrations/sources/oauth/#openid-connect)
- [Authelia](https://www.authelia.com/configuration/identity-providers/open-id-connect/)
- [Authelia](https://www.authelia.com/configuration/identity-providers/openid-connect/clients/)
- [Okta](https://www.okta.com/openid-connect/)
- [Google](https://developers.google.com/identity/openid-connect/openid-connect)
@@ -67,12 +67,20 @@ Once you have a new OAuth client application configured, Immich can be configure
| Client Secret | string | (required) | Required. Client Secret (previous step) |
| Scope | string | openid email profile | Full list of scopes to send with the request (space delimited) |
| Signing Algorithm | string | RS256 | The algorithm used to sign the id token (examples: RS256, HS256) |
| Storage Label Claim | string | preferred_username | Claim mapping for the user's storage label**¹** |
| Storage Quota Claim | string | immich_quota | Claim mapping for the user's storage**¹** |
| Default Storage Quota (GiB) | number | 0 | Default quota for user without storage quota claim (Enter 0 for unlimited quota) |
| Button Text | string | Login with OAuth | Text for the OAuth button on the web |
| Auto Register | boolean | true | When true, will automatically register a user the first time they sign in |
| Storage Claim | string | preferred_username | Claim mapping for the user's storage label |
| [Auto Launch](#auto-launch) | boolean | false | When true, will skip the login page and automatically start the OAuth login process |
| [Mobile Redirect URI Override](#mobile-redirect-uri) | URL | (empty) | Http(s) alternative mobile redirect URI |
:::note Claim Options [1]
Claim is only used on user creation and not synchronized after that.
:::
:::info
The Issuer URL should look something like the following, and return a valid json document.
+17 -1
View File
@@ -8,6 +8,8 @@ The `immich-server` docker image comes preinstalled with an administrative CLI (
| `reset-admin-password` | Reset the password for the admin user |
| `disable-password-login` | Disable password login |
| `enable-password-login` | Enable password login |
| `enable-oauth-login` | Enable OAuth login |
| `disable-oauth-login` | Disable OAuth login |
| `list-users` | List Immich users |
## How to run a command
@@ -36,13 +38,27 @@ immich-admin disable-password-login
Password login has been disabled.
```
Enabled Password Login
Enable Password Login
```
immich-admin enable-password-login
Password login has been enabled.
```
Enable OAuth login
```
immich-admin enable-oauth-login
OAuth login has been enabled.
```
Disable OAuth login
```
immich-admin disable-oauth-login
OAuth login has been disabled.
```
List Users
```
+49 -4
View File
@@ -13,12 +13,57 @@ Immich supports multiple users, each with their own library.
<UserCreate />
## Delete a User
## Set Storage Quota For User
If you need to remove a user from Immich, head to "Administration", where users can be scheduled for deletion. The user account will immediately become disabled and their library and all associated data will be removed after 7 days.
Admin can specify the storage quota for the user as the instance's admin; once the limit is reached, the user won't be able to upload to the instance anymore.
In order to select a storage quota, click on the pencil icon and enter the storage quota in GiB. You can choose an unlimited quota using the value 0 (default).
:::tip
The system administrator can see the usage quota percentage of all users in Server Stats page.
:::
:::info
External libraries don't take up space from the storage quota.
:::
<img src={require('./img/user-quota-size.png').default} width="40%" title="Set Quota Size" />
## Set Storage Label For User
The admin can add a custom label for each user, so instead of `upload/{userId}/your-template` it will be `upload/{custom_user_label}/your-template`.
To apply a storage template, go to the Administration page -> click on the pencil button next to the user.
:::note
To apply the Storage Label to previously uploaded assets, run the Storage Migration Job.
:::
<img src={require('./img/user-storage-label.png').default} width="40%" title="Delete User" />
## Password Reset
To reset a user's password, click the pencil icon to edit a user, then click "Reset Password". The user's password will be reset to "password" and they have to change it next time the sign in.
To reset a user's password, click the pencil icon to edit a user, then click "Reset Password". The user's password will be reset to random password and they have to change it next time the sign in.
![Reset Password](./img/user-management-update.png)
<img src={require('./img/user-management-update.png').default} width="40%" title="Reset Password" />
## Delete a User
If you need to remove a user from Immich, head to "Administration", where users can be scheduled for deletion. The user account will immediately become disabled and their library and all associated data will be removed after 7 days by default.
<img src={require('./img/delete-user.webp').default} width="40%" title="Delete User" />
### Delete Delay
You can customize the time of the deletion of the users from the Administration -> Settings -> User Settings.
:::info user deletion job
The user deletion job runs at midnight to check for users that are ready for deletion. Changes to this setting will be evaluated at the next execution.
:::
<img src={require('./img/customize-delete-user.png').default} width="80%" title="Customize Delete User" />
### Immediately Remove User
You can choose to delete a user immediately by checking the box
`Queue user and assets for immediate deletion` in the deletion process, this will immediately remove the user and all assets.
This cannot be undone and the files cannot be recovered.
<img src={require('./img/immediately-remove-user.png').default} width="40%" title="Customize Delete User" />
+3 -3
View File
@@ -1,14 +1,14 @@
# Database Migrations
After making any changes in the `server/src/infra/entities`, a database migration need to run in order to register the changes in the database. Follow the steps below to create a new migration.
After making any changes in the `server/src/entities`, a database migration need to run in order to register the changes in the database. Follow the steps below to create a new migration.
1. Run the command
```bash
npm run typeorm:migrations:generate ./src/infra/<migration-name>
npm run typeorm:migrations:generate <migration-name>
```
2. Check if the migration file makes sense.
3. Move the migration file to folder `./server/src/infra/migrations` in your code editor.
3. Move the migration file to folder `./server/src/migrations` in your code editor.
The server will automatically detect `*.ts` file changes and restart. Part of the server start-up process includes running any new migrations, so it will be applied immediately.
+1 -1
View File
@@ -10,7 +10,7 @@ If foreground backup is enabled: whenever the app is opened or resumed, it will
## Background backup
Background backup is available thanks to the contribution effort of [@zoodyy](https://github.com/zoodyy) and [@martyfuhry](https://github.com/martyfuhry).
Background backup is available thanks to the contribution effort of [@fyfrey](https://github.com/fyfrey) and [@martyfuhry](https://github.com/martyfuhry).
If background backup is enabled. The app will periodically check if there are any new photos or videos in the selected album(s) to be uploaded to the cloud. If there are, it will upload them to the cloud in the background.
@@ -42,6 +42,18 @@ You do not need to redo any transcoding jobs after enabling hardware acceleratio
- If you have an 11th gen CPU or older, then you may need to follow [these][jellyfin-lp] instructions as Low-Power mode is required
- Additionally, if the server specifically has an 11th gen CPU and is running kernel 5.15 (shipped with Ubuntu 22.04 LTS), then you will need to upgrade this kernel (from [Jellyfin docs][jellyfin-kernel-bug])
#### RKMPP
For RKMPP to work:
- You must have a supported Rockchip ARM SoC.
- Only RK3588 supports hardware tonemapping, other SoCs use slower software tonemapping while still using hardware encoding.
- Tonemapping requires `/usr/lib/aarch64-linux-gnu/libmali.so.1` to be present on your host system. Install [`libmali-valhall-g610-g6p0-gbm`][libmali-rockchip] and modify the [`hwaccel.transcoding.yml`][hw-file] file:
- under `rkmpp` uncomment the 3 lines required for OpenCL tonemapping by removing the `#` symbol at the beginning of each line
- `- /dev/mali0:/dev/mali0`
- `- /etc/OpenCL:/etc/OpenCL:ro`
- `- /usr/lib/aarch64-linux-gnu/libmali.so.1:/usr/lib/aarch64-linux-gnu/libmali.so.1:ro`
## Setup
#### Basic Setup
@@ -106,3 +118,4 @@ Once this is done, you can continue to step 3 of "Basic Setup".
[nvcr]: https://github.com/NVIDIA/nvidia-container-runtime/
[jellyfin-lp]: https://jellyfin.org/docs/general/administration/hardware-acceleration/intel/#configure-and-verify-lp-mode-on-linux
[jellyfin-kernel-bug]: https://jellyfin.org/docs/general/administration/hardware-acceleration/intel/#known-issues-and-limitations
[libmali-rockchip]: https://github.com/tsukumijima/libmali-rockchip/releases
+16 -34
View File
@@ -38,7 +38,7 @@ Note: Either a manual or scheduled library scan must have been performed to iden
In all above scan methods, Immich will check if any files are missing. This can happen if files are deleted, or if they are on a storage location that is currently unavailable, like a network drive that is not mounted, or a USB drive that has been unplugged. In order to prevent accidental deletion of assets, Immich will not immediately delete an asset from the library if the file is missing. Instead, the asset will be internally marked as offline and will still be visible in the main timeline. If the file is moved back to its original location and the library is scanned again, the asset will be restored.
Finally, files can be deleted from Immich via the `Remove Offline Files` job. This job can be found by the three dots menu for the associated external storage that was configured under user account settings > libraries (the same location described at [create external libraries](#create-external-libraries)). When this job is run, any assets marked as offline will then be removed from Immich. Run this job whenever files have been deleted from the file system and you want to remove them from Immich.
Finally, files can be deleted from Immich via the `Remove Offline Files` job. This job can be found by the three dots menu for the associated external storage that was configured under Administration > Libraries (the same location described at [create external libraries](#create-external-libraries)). When this job is run, any assets marked as offline will then be removed from Immich. Run this job whenever files have been deleted from the file system and you want to remove them from Immich.
### Import Paths
@@ -50,8 +50,6 @@ If the import paths are edited in a way that an external file is no longer in an
Sometimes, an external library will not scan correctly. This can happen if immich_server or immich_microservices can't access the files. Here are some things to check:
- Is the external path set correctly? Each import path must be contained in the external path.
- Make sure the external path does not contain spaces
- In the docker-compose file, are the volumes mounted correctly?
- Are the volumes identical between the `server` and `microservices` container?
- Are the import paths set correctly, and do they match the path set in docker-compose file?
@@ -61,18 +59,6 @@ Sometimes, an external library will not scan correctly. This can happen if immic
To validate that Immich can reach your external library, start a shell inside the container. Run `docker exec -it immich_microservices /bin/bash` to a bash shell. If your import path is `/data/import/photos`, check it with `ls /data/import/photos`. Do the same check for the `immich_server` container. If you cannot access this directory in both the `microservices` and `server` containers, Immich won't be able to import files.
### Security Considerations
:::caution
Please read and understand this section before setting external paths, as there are important security considerations.
:::
For security purposes, each Immich user is disallowed to add external files by default. This is to prevent devastating [path traversal attacks](https://owasp.org/www-community/attacks/Path_Traversal). An admin can allow individual users to use external path feature via the `external path` setting found in the admin panel. Without the external path restriction, a user can add any image or video file on the Immich host filesystem to be imported into Immich, potentially allowing sensitive data to be accessed. If you are running Immich as root in your Docker setup (which is the default), all external file reads are done with root privileges. This is particularly dangerous if the Immich host is a shared server.
With the `external path` set, a user is restricted to accessing external files to files or directories within that path. The Immich admin should still be careful not set the external path too generously. For example, `user1` wants to read their photos in to `/home/user1`. A lazy admin sets that user's external path to `/home/` since it "gets the job done". However, that user will then be able to read all photos in `/home/user2/private-photos`, too! Please set the external path as specific as possible. If multiple folders must be added, do this using the docker volume mount feature described below.
### Exclusion Patterns
By default, all files in the import paths will be added to the library. If there are files that should not be added, exclusion patterns can be used to exclude them. Exclusion patterns are glob patterns are matched against the full file path. If a file matches an exclusion pattern, it will not be added to the library. Exclusion patterns can be added in the Scan Settings page for each library. Under the hood, Immich uses the [glob](https://www.npmjs.com/package/glob) package to match patterns, so please refer to [their documentation](https://github.com/isaacs/node-glob#glob-primer) to see what patterns are supported.
@@ -90,6 +76,16 @@ This feature - currently hidden in the config file - is considered experimental
If your photos are on a network drive, automatic file watching likely won't work. In that case, you will have to rely on a periodic library refresh to pull in your changes.
#### Troubleshooting
If you encounter an `ENOSPC` error, you need to increase your file watcher limit. In sysctl, this key is called `fs.inotify.max_user_watched` and has a default value of 8192. Increase this number to a suitable value greater than the number of files you will be watching. Note that Immich has to watch all files in your import paths including any ignored files.
```
ERROR [LibraryService] Library watcher for library c69faf55-f96d-4aa0-b83b-2d80cbc27d98 encountered error: Error: ENOSPC: System limit for number of file watchers reached, watch '/media/photo.jpg'
```
In rare cases, the library watcher can hang, preventing Immich from starting up. In this case, disable the library watcher in the configuration file. If the watcher is enabled from within Immich, the app must be started without the microservices. Disable the microservices in the docker compose file, start Immich, disable the library watcher in the admin settings, close Immich, re-enable the microservices, and then Immich can be started normally.
### Nightly job
There is an automatic job that's run once a day and refreshes all modified files in all libraries as well as cleans up any libraries stuck in deletion.
@@ -135,27 +131,13 @@ The `ro` flag at the end only gives read-only access to the volumes. While Immic
_Remember to bring the container `docker compose down/up` to register the changes. Make sure you can see the mounted path in the container._
:::
### Set External Path
Only an admin can do this.
- Navigate to `Administration > Users` page on the web.
- Click on the user edit button.
- Set `/mnt/media` to be the external path. This folder will only contain the three folders that we want to import, so nothing else can be accessed.
:::note
Spaces in the internal path aren't currently supported.
You must import it as:
`..:/mnt/media/my-media:ro`
instead of
`..:/mnt/media/my media:ro`
:::
### Create External Libraries
- Click on your user name in the top right corner -> Account Settings
- Click on Libraries
These actions must be performed by the Immich administrator.
- Click on Administration -> Libraries
- Click on Create External Library
- Select which user owns the library, this can not be changed later
- Click the drop-down menu on the newly created library
- Click on Rename Library and rename it to "Christmas Trip"
- Click Edit Import Paths
@@ -166,7 +148,7 @@ NOTE: We have to use the `/mnt/media/christmas-trip` path and not the `/mnt/nas/
Next, we'll add an exclusion pattern to filter out raw files.
- Click the drop-down menu on the newly christmas library
- Click the drop-down menu on the newly-created Christmas library
- Click on Manage
- Click on Scan Settings
- Click on Add Exclusion Pattern
+113
View File
@@ -0,0 +1,113 @@
# Monitoring
## Overview
Immich provides a variety of performance metrics to allow for local monitoring and insights. This integration is primarily in the form of Prometheus metrics. However, exporting traces is also possible due to the use of OpenTelemetry instrumentation.
:::note
This is an opt-in feature intended for you to monitor immich's performance. This data isn't sent anywhere beyond what you've configured.
:::
## Prometheus
Prometheus is a tool that collects metrics from a number of sources you configure. It operates in a "pull" strategy - that is, it periodically requests metrics from each defined source. This means that the source doesn't send anything until it's requested. It also means that the source -- immich, in this case -- has to expose an endpoint for Prometheus to target when it requests metrics.
### Metrics
These metrics come in a variety of forms:
- Counters, which can only increase. Example: the number of times an endpoint has been called.
- Gauges, which can increase or decrease within a certain range. Example: CPU utilization.
- Histograms, where each observation is assigned to a certain number of "buckets". Example: response time, where each bucket is a number of milliseconds. This one is a bit more complicated.
- Buckets in this case are _cumulative_; that is, an observation is placed not only into the smallest bucket that contains it, but also to all buckets larger than this. For example, if a histogram has three buckets for 1ms, 5ms and 10ms, an observation of 3ms will be bucketed into both 5ms and 10ms.
The metrics in immich are grouped into API (endpoint calls and response times), host (memory and CPU utilization), and IO (internal database queries, image processing, and so on). Each group of metrics can be enabled or disabled independently.
### Configuration
Immich will not expose an endpoint for metrics by default. To enable this endpoint, you can add the `IMMICH_METRICS=true` environmental variable to your `.env` file. Note that only the server and microservices containers currently use this variable.
:::note
`IMMICH_METRICS` is equivalent to enabling the following three environmental variables: `IMMICH_API_METRICS`, `IMMICH_HOST_METRICS`, and `IMMICH_IO_METRICS`. If you would like to only expose certain kinds of metrics, you can set only those environmental variables to `true`. Explicitly setting the environmental variable for a metric group overrides `IMMICH_METRICS` for that group.
:::
The next step is to configure a new or existing Prometheus instance to scrape this endpoint. The following steps assume that you do not have an existing Prometheus instance, but the steps will be similar either way.
You can start by defining a Prometheus service in the Compose file:
```yaml
immich-prometheus:
container_name: immich_prometheus
ports:
# this exposes the default port for Prometheus so you can interact with it
- 9090:9090
image: prom/prometheus
volumes:
# the Prometheus configuration file - a barebones one is provided to get started
- ./prometheus.yml:/etc/prometheus/prometheus.yml
# a named volume defined in the bottom of the Compose file; it can also be a mounted folder
- prometheus-data:/prometheus
```
You will also need to add `prometheus-data` to the list of volumes in the bottom of the Compose file:
```yaml
volumes:
model-cache:
prometheus-data:
```
The last piece is the [configuration file][prom-file]. This file defines (among other things) the sources Prometheus should target. Download it and place it in the same folder as the Compose file.
:::tip
The provided file is just a starting point. There are a ton of ways to configure Prometheus, so feel free to experiment!
:::
After bringing down the containers with `docker compose down` and back up with `docker compose up -d`, a Prometheus instance will now collect metrics from the immich server and microservices containers. Note that we didn't need to expose any new ports for these containers - the communication is handled in the internal Docker network.
:::note
To see exactly what metrics are made available, you can additionally add `8081:8081` to the server container's ports and `8082:8081` to the microservices container's ports. Visiting the `/metrics` endpoint for these services will show the same raw data that Prometheus collects.
:::
### Usage
So after setting up Prometheus, how do you actually view the metrics? The simplest way is to use Prometheus directly. Visiting Prometheus will show you a web UI where you can search for and visualize metrics. You can also view the status of your data sources and configure settings, but this is beyond the scope of this guide.
## Grafana
For a dedicated tool with nice presentation, you can use Grafana instead. This connects to Prometheus (and possibly other sources) for sophisticated data visualization.
Setting up Grafana is similar to Prometheus. You can add a service for it:
```yaml
immich-grafana:
container_name: immich_grafana
command: ['./run.sh', '-disable-reporting'] # this is to disable Grafana's telemetry
ports:
- 3000:3000
image: grafana/grafana
volumes:
# stores your pretty dashboards and panels
- grafana-data:/var/lib/grafana
```
And add another volume for it:
```yaml
volumes:
model-cache:
prometheus-data:
grafana-data:
```
After bringing down the services and back up again, you can now visit Grafana to view your metrics. On the first login, enter `admin` for both username and password and update your password. You can then go to the settings and add a data source with `http://immich-prometheus:9090` to point Grafana to your Prometheus instance.
### Usage
You can make your first dashboard to get started. Don't forget to save it frequently, or you'll lose all your progress!
You can then make a new panel, specifying Prometheus as the data source for it.
-- TODO: add images and more details here
[prom-file]: https://github.com/immich-app/immich/releases/latest/download/prometheus.yml
+130
View File
@@ -0,0 +1,130 @@
# API Album Sync (Python Script)
This is an example of a python script for syncing an album to a local folder. This was used for a digital photoframe so the displayed photos could be managed from the immich web or app UI.
The script is copied below in it's current form. A repository is hosted [here](https://git.orenit.solutions/open/immichalbumpull).
:::danger
This guide uses a generated API key. This key gives the same access to your immich instance as the user it is attached to, so be careful how the config file is stored and transferred.
:::
### Prerequisites
- Python 3.7+
- [requests library](https://pypi.org/project/requests/)
### Installing
Copy the contents of 'pull.py' (shown below) to your chosen location or clone the repository:
```bash
git clone https://git.orenit.solutions/open/immichalbumpull
```
Edit or create the 'config.ini' file in the same directory as the script with the necessary details:
```ini title='config.ini'
[immich]
# URL of target immich instance
url = https://photo.example.com
# API key from Account Settings -> API Keys
apikey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Full local path to target directory
destination = /home/photo/photos
# immich album name
album = Photoframe
```
### Usage
Run the script directly:
```bash
./pull.py
```
Or from cron (every 5 minutes):
```bash
*/5 * * * * /usr/bin/python /home/user/immichalbumpull/pull.py
```
### Python Script
```python title='pull.py'
#!/usr/bin/env python
import requests
import configparser
import os
import shutil
# Read config file
config = configparser.ConfigParser()
config.read('config.ini')
url = config['immich']['url']
apikey = config['immich']['apikey']
photodir = config['immich']['destination']
albumname = config['immich']['album']
headers = {
'Accept': 'application/json',
'x-api-key': apikey
}
# Set up the directory for the downloaded images
os.makedirs(photodir, exist_ok=True)
# Get the list of albums from the API
response = requests.get(url + "/api/album", headers=headers)
# Parse the JSON response
data = response.json()
# Find the chosen album id
for item in data:
if item['albumName'] == albumname:
albumid = item['id']
# Get the list of photos from the API using the albumid
response = requests.get(url + "/api/album/" + albumid, headers=headers)
# Parse the JSON response and extract the URLs of the images
data = response.json()
image_urls = data['assets']
# Download each image from the URL and save it to the directory
headers = {
'Accept': 'application/octet-stream',
'x-api-key': apikey
}
photolist = []
for id in image_urls:
# Query asset info endpoint for correct extension
assetinfourl = url + "/api/asset/" + str(id['id'])
response = requests.get(assetinfourl, headers=headers)
assetinfo = response.json()
ext = os.path.splitext(assetinfo['originalFileName'])
asseturl = url + "/api/download/asset/" + str(id['id'])
response = requests.post(asseturl, headers=headers, stream=True)
# Build current photo list for deletions below
photo = os.path.basename(asseturl) + ext[1]
photolist.append(photo)
photofullpath = photodir + '/' + os.path.basename(asseturl) + ext[1]
# Only download file if it doesn't already exist
if not os.path.exists(photofullpath):
with open(photofullpath, 'wb') as f:
for chunk in response.iter_content(1024):
f.write(chunk)
# Delete old photos removed from album
for filename in os.listdir(photodir):
if filename not in photolist:
os.unlink(os.path.join(photodir, filename))
```
+5 -1
View File
@@ -13,7 +13,7 @@ Run `docker exec -it immich_postgres psql immich <DB_USERNAME>` to connect to th
## Assets
:::note
The `"originalFileName"` column is the name of the uploaded file _without_ the extension.
The `"originalFileName"` column is the name of the file at time of upload, including the extension.
:::
```sql title="Find by original filename"
@@ -40,6 +40,10 @@ SELECT * FROM "assets" where "livePhotoVideoId" IS NOT NULL;
SELECT "assets".* FROM "exif" LEFT JOIN "assets" ON "assets"."id" = "exif"."assetId" WHERE "exif"."assetId" IS NULL;
```
```sql title="size < 100,000 bytes, smallest to largest"
SELECT * FROM "assets" JOIN "exif" ON "assets"."id" = "exif"."assetId" WHERE "exif"."fileSizeInByte" < 100000 ORDER BY "exif"."fileSizeInByte" ASC;
```
```sql title="Without thumbnails"
SELECT * FROM "assets" WHERE "assets"."resizePath" IS NULL OR "assets"."webpPath" IS NULL;
```
+18 -29
View File
@@ -14,6 +14,12 @@ Edit `docker-compose.yml` to add two new mount points under `volumes:`
- ${EXTERNAL_PATH}:/usr/src/app/external
```
```
immich-microservices:
volumes:
- ${EXTERNAL_PATH}:/usr/src/app/external
```
Be sure to add exactly the same line to both `immich-server:` and `immich-microservices:`.
Edit `.env` to define `EXTERNAL_PATH`, substituting in the correct path for your computer:
@@ -28,6 +34,10 @@ On my computer, for example, I use this path:
EXTERNAL_PATH=/home/tenino/photos
```
:::info EXTERNAL_PATH design
The design choice to put the EXTERNAL_PATH into .env rather than put two copies of the absolute path in the yml file in order to make everything easier, so if you have two copies of the same path that have to be kept in sync, then someday later when you move the data, update only one of the paths, without everything will break mysteriously.
:::
Restart Immich.
```
@@ -35,47 +45,26 @@ docker compose down
docker compose up -d
```
# Set the External Path
# Create the library
In the Immich web UI:
- click the **Administration** link in the upper right corner.
<img src={require('./img/administration-link.png').default} width="50%" title="Administration link" />
- Select the **Users** tab
<img src={require('./img/users-tab.png').default} width="50%" title="Users tab" />
- Select the **External Libraries** tab
<img src={require('./img/external-libraries.png').default} width="50%" title="External Libraries tab" />
- Select the **pencil** next to your user ID
<img src={require('./img/pencil.png').default} width="50%" title="Pencil" />
- Click the **Create Library** button
<img src={require('./img/create-external-library.png').default} width="50%" title="Create Library button" />
- Fill in the **External Path** field with `/usr/src/app/external`
<img src={require('./img/external-path.png').default} width="50%" title="External Path field" />
Notice this matches the path _inside the container_ where we mounted your photos.
The purpose of the external path field is for administrators who have multiple users
on their Immich instance. It lets you prevent other authorized users from
navigating to your external library.
# Import the library
In the Immich web UI:
- Click your user avatar in the upper-right corner (circle with your initials)
<img src={require('./img/user-avatar.png').default} width="50%" title="User avatar" />
- Click **Account Settings**
<img src={require('./img/account-settings.png').default} width="50%" title="Account Settings button" />
- Click to expand **Libraries**
<img src={require('./img/libraries-dropdown.png').default} width="50%" title="Libraries dropdown" />
- Click the **Create External Library** button
<img src={require('./img/create-external-library-button.png').default} width="50%" title="Create External Library button" />
- In the dialog, select which user should own the new library
<img src={require('./img/library-owner.png').default} width="50%" title="Library owner diaglog" />
- Click the three-dots menu and select **Edit Import Paths**
<img src={require('./img/edit-import-paths.png').default} width="50%" title="Edit Import Paths menu option" />
- Click \*_Add path_
- Click Add path
<img src={require('./img/add-path-button.png').default} width="50%" title="Add Path button" />
- Enter **/usr/src/app/external** as the path and click Add
Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

@@ -16,7 +16,12 @@ version: '3.8'
services:
immich-machine-learning:
container_name: immich_machine_learning
# For hardware acceleration, add one of -[armnn, cuda, openvino] to the image tag.
# Example tag: ${IMMICH_VERSION:-release}-cuda
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
# extends:
# file: hwaccel.ml.yml
# service: # set to one of [armnn, cuda, openvino, openvino-wsl] for accelerated inference - use the `-wsl` version for WSL2 where applicable
volumes:
- model-cache:/cache
restart: always
+15 -16
View File
@@ -9,8 +9,8 @@ The database is saved to your Immich upload folder in the `database-backup` subd
### Prerequisites
- Borg needs to be installed on your server as well as the remote machine. You can find instructions to install Borg [here](https://borgbackup.readthedocs.io/en/latest/installation.html).
- To run this sript as a non-root user, you should [add your username to the docker group](https://docs.docker.com/engine/install/linux-postinstall/).
- To run this script non-interactively, set up [passwordless ssh](https://www.redhat.com/sysadmin/passwordless-ssh) to your remote machine from your server.
- (Optional) To run this sript as a non-root user, you should [add your username to the docker group](https://docs.docker.com/engine/install/linux-postinstall/).
- To run this script non-interactively, set up [passwordless ssh](https://www.redhat.com/sysadmin/passwordless-ssh) to your remote machine from your server. If you skipped the previous step, make sure this step is done from your root account.
To initialize the borg repository, run the following commands once.
@@ -19,19 +19,16 @@ UPLOAD_LOCATION="/path/to/immich/directory" # Immich database location, as
BACKUP_PATH="/path/to/local/backup/directory"
mkdir "$UPLOAD_LOCATION/database-backup"
mkdir "$BACKUP_PATH/immich-borg"
borg init --encryption=none "$BACKUP_PATH/immich-borg"
## Remote set up
REMOTE_HOST="remote_host@IP"
REMOTE_BACKUP_PATH="/path/to/remote/backup/directory"
ssh "$REMOTE_HOST" "mkdir $REMOTE_BACKUP_PATH/immich-borg"
ssh "$REMOTE_HOST" "borg init --encryption=none $REMOTE_BACKUP_PATH/immich-borg"
borg init --encryption=none "$REMOTE_HOST:$REMOTE_BACKUP_PATH/immich-borg"
```
Edit the following script as necessary and add it to your crontab. Note that this script assumes there are no spaces in your paths. If there are spaces, enclose the paths in double quotes.
Edit the following script as necessary and add it to your crontab. Note that this script assumes there are no `:`, `@`, or `"` characters in your paths. If these characters exist, you will need to escape and/or rename the paths.
```bash title='Borg backup template'
#!/bin/sh
@@ -46,18 +43,20 @@ REMOTE_BACKUP_PATH="/path/to/remote/backup/directory"
### Local
# Backup Immich database
docker exec -t immich_postgres pg_dumpall -c -U postgres | /usr/bin/gzip > $UPLOAD_LOCATION/database-backup/immich-database.sql.gz
docker exec -t immich_postgres pg_dumpall -c -U postgres > "$UPLOAD_LOCATION"/database-backup/immich-database.sql
# For deduplicating backup programs such as Borg or Restic, compressing the content can increase backup size by making it harder to deduplicate. If you are using a different program or still prefer to compress, you can use the following command instead:
# docker exec -t immich_postgres pg_dumpall -c -U postgres | /usr/bin/gzip --rsyncable > "$UPLOAD_LOCATION"/database-backup/immich-database.sql.gz
### Append to local Borg repository
borg create $BACKUP_PATH/immich-borg::{now} $UPLOAD_LOCATION --exclude $UPLOAD_LOCATION/thumbs/ --exclude $UPLOAD_LOCATION/encoded-video/
borg prune --keep-weekly=4 --keep-monthly=3 $BACKUP_PATH/immich-borg
borg compact $BACKUP_PATH/immich-borg
borg create "$BACKUP_PATH/immich-borg::{now}" "$UPLOAD_LOCATION" --exclude "$UPLOAD_LOCATION"/thumbs/ --exclude "$UPLOAD_LOCATION"/encoded-video/
borg prune --keep-weekly=4 --keep-monthly=3 "$BACKUP_PATH"/immich-borg
borg compact "$BACKUP_PATH"/immich-borg
### Append to remote Borg repository
borg create $REMOTE_HOST:$REMOTE_BACKUP_PATH/immich-borg::{now} $UPLOAD_LOCATION --exclude $UPLOAD_LOCATION/thumbs/ --exclude $UPLOAD_LOCATION/encoded-video/
borg prune --keep-weekly=4 --keep-monthly=3 $REMOTE_HOST:$REMOTE_BACKUP_PATH/immich-borg
borg compact $REMOTE_HOST:$REMOTE_BACKUP_PATH/immich-borg
borg create "$REMOTE_HOST:$REMOTE_BACKUP_PATH/immich-borg::{now}" "$UPLOAD_LOCATION" --exclude "$UPLOAD_LOCATION"/thumbs/ --exclude "$UPLOAD_LOCATION"/encoded-video/
borg prune --keep-weekly=4 --keep-monthly=3 "$REMOTE_HOST:$REMOTE_BACKUP_PATH"/immich-borg
borg compact "$REMOTE_HOST:$REMOTE_BACKUP_PATH"/immich-borg
```
### Restoring
@@ -67,7 +66,7 @@ To restore from a backup, use the `borg mount` command.
```bash title='Restore from local backup'
BACKUP_PATH="/path/to/local/backup/directory"
mkdir /tmp/immich-mountpoint
borg mount $BACKUP_PATH/immich-borg /tmp/immich-mountpoint
borg mount "$BACKUP_PATH"/immich-borg /tmp/immich-mountpoint
cd /tmp/immich-mountpoint
```
@@ -75,7 +74,7 @@ cd /tmp/immich-mountpoint
REMOTE_HOST="remote_host@IP"
REMOTE_BACKUP_PATH="/path/to/remote/backup/directory"
mkdir /tmp/immich-mountpoint
borg mount $REMOTE_HOST:$REMOTE_BACKUP_PATH/immich-borg /tmp/immich-mountpoint
borg mount "$REMOTE_HOST:$REMOTE_BACKUP_PATH"/immich-borg /tmp/immich-mountpoint
cd /tmp/immich-mountpoint
```
+27 -8
View File
@@ -4,7 +4,7 @@ A config file can be provided as an alternative to the UI configuration.
### Step 1 - Create a new config file
In JSON format, create a new config file (e.g. `immich.config`) and put it in a location that can be accessed by Immich.
In JSON format, create a new config file (e.g. `immich.json`) and put it in a location that can be accessed by Immich.
The default configuration looks like this:
```json
@@ -14,7 +14,9 @@ The default configuration looks like this:
"threads": 0,
"preset": "ultrafast",
"targetVideoCodec": "h264",
"acceptedVideoCodecs": ["h264"],
"targetAudioCodec": "aac",
"acceptedAudioCodecs": ["aac", "mp3", "libopus"],
"targetResolution": "720",
"maxBitrate": "0",
"bframes": -1,
@@ -24,6 +26,7 @@ The default configuration looks like this:
"temporalAQ": false,
"cqMode": "auto",
"twoPass": false,
"preferredHwDevice": "auto",
"transcode": "required",
"tonemap": "hable",
"accel": "disabled"
@@ -38,7 +41,7 @@ The default configuration looks like this:
"metadataExtraction": {
"concurrency": 5
},
"recognizeFaces": {
"faceDetection": {
"concurrency": 2
},
"search": {
@@ -50,9 +53,6 @@ The default configuration looks like this:
"library": {
"concurrency": 5
},
"storageTemplateMigration": {
"concurrency": 5
},
"migration": {
"concurrency": 5
},
@@ -95,18 +95,23 @@ The default configuration looks like this:
"issuerUrl": "",
"clientId": "",
"clientSecret": "",
"mobileOverrideEnabled": false,
"mobileRedirectUri": "",
"scope": "openid email profile",
"signingAlgorithm": "RS256",
"storageLabelClaim": "preferred_username",
"storageQuotaClaim": "immich_quota",
"defaultStorageQuota": 0,
"buttonText": "Login with OAuth",
"autoRegister": true,
"autoLaunch": false
"autoLaunch": false,
"mobileOverrideEnabled": false,
"mobileRedirectUri": ""
},
"passwordLogin": {
"enabled": true
},
"storageTemplate": {
"enabled": false,
"hashVerificationEnabled": true,
"template": "{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}"
},
"thumbnail": {
@@ -125,6 +130,9 @@ The default configuration looks like this:
"theme": {
"customCss": ""
},
"user": {
"deleteDelay": 7
},
"library": {
"scan": {
"enabled": true,
@@ -135,6 +143,13 @@ The default configuration looks like this:
"usePolling": false,
"interval": 10000
}
},
"server": {
"externalDomain": "",
"loginPageMessage": ""
},
"user": {
"deleteDelay": 7
}
}
```
@@ -148,3 +163,7 @@ So you can just grab it from there, paste it into a file and you're pretty much
In your `.env` file, set the variable `IMMICH_CONFIG_FILE` to the path of your config.
For more information, refer to the [Environment Variables](/docs/install/environment-variables.md) section.
:::tip
YAML-formatted config files are also supported.
:::
+14 -12
View File
@@ -36,7 +36,7 @@ These environment variables are used by the `docker-compose.yml` file and do **N
| `NODE_ENV` | Environment (production, development) | `production` | server, microservices, machine learning, web |
| `LOG_LEVEL` | Log Level (verbose, debug, log, warn, error) | `log` | server, microservices |
| `IMMICH_MEDIA_LOCATION` | Media Location | `./upload` | server, microservices |
| `IMMICH_CONFIG_FILE` | Path to config file | | server |
| `IMMICH_CONFIG_FILE` | Path to config file | | server, microservices |
| `IMMICH_WEB_ROOT` | Path of root index.html | `/usr/src/app/www` | server |
| `IMMICH_REVERSE_GEOCODING_ROOT` | Path of reverse geocoding dump directory | `/usr/src/resources` | microservices |
@@ -67,7 +67,7 @@ These environment variables are used by the `docker-compose.yml` file and do **N
| `DB_PORT` | Database Port | `5432` | server, microservices |
| `DB_USERNAME` | Database User | `postgres` | server, microservices |
| `DB_PASSWORD` | Database Password | `postgres` | server, microservices |
| `DB_DATABASE` | Database Name | `immich` | server, microservices |
| `DB_DATABASE_NAME` | Database Name | `immich` | server, microservices |
| `DB_VECTOR_EXTENSION`<sup>\*1</sup> | Database Vector Extension (one of [`pgvector`, `pgvecto.rs`]) | `pgvecto.rs` | server, microservices |
\*1: This setting cannot be changed after the server has successfully started up
@@ -124,16 +124,18 @@ Redis (Sentinel) URL example JSON before encoding:
## Machine Learning
| Variable | Description | Default | Services |
| :----------------------------------------------- | :----------------------------------------------------------------- | :-----------------: | :--------------- |
| `MACHINE_LEARNING_MODEL_TTL` | Inactivity time (s) before a model is unloaded (disabled if \<= 0) | `300` | machine learning |
| `MACHINE_LEARNING_MODEL_TTL_POLL_S` | Interval (s) between checks for the model TTL (disabled if \<= 0) | `10` | machine learning |
| `MACHINE_LEARNING_CACHE_FOLDER` | Directory where models are downloaded | `/cache` | machine learning |
| `MACHINE_LEARNING_REQUEST_THREADS`<sup>\*1</sup> | Thread count of the request thread pool (disabled if \<= 0) | number of CPU cores | machine learning |
| `MACHINE_LEARNING_MODEL_INTER_OP_THREADS` | Number of parallel model operations | `1` | machine learning |
| `MACHINE_LEARNING_MODEL_INTRA_OP_THREADS` | Number of threads for each model operation | `2` | machine learning |
| `MACHINE_LEARNING_WORKERS`<sup>\*2</sup> | Number of worker processes to spawn | `1` | machine learning |
| `MACHINE_LEARNING_WORKER_TIMEOUT` | Maximum time (s) of unresponsiveness before a worker is killed | `120` | machine learning |
| Variable | Description | Default | Services |
| :----------------------------------------------- | :------------------------------------------------------------------- | :-----------------: | :--------------- |
| `MACHINE_LEARNING_MODEL_TTL` | Inactivity time (s) before a model is unloaded (disabled if \<= 0) | `300` | machine learning |
| `MACHINE_LEARNING_MODEL_TTL_POLL_S` | Interval (s) between checks for the model TTL (disabled if \<= 0) | `10` | machine learning |
| `MACHINE_LEARNING_CACHE_FOLDER` | Directory where models are downloaded | `/cache` | machine learning |
| `MACHINE_LEARNING_REQUEST_THREADS`<sup>\*1</sup> | Thread count of the request thread pool (disabled if \<= 0) | number of CPU cores | machine learning |
| `MACHINE_LEARNING_MODEL_INTER_OP_THREADS` | Number of parallel model operations | `1` | machine learning |
| `MACHINE_LEARNING_MODEL_INTRA_OP_THREADS` | Number of threads for each model operation | `2` | machine learning |
| `MACHINE_LEARNING_WORKERS`<sup>\*2</sup> | Number of worker processes to spawn | `1` | machine learning |
| `MACHINE_LEARNING_WORKER_TIMEOUT` | Maximum time (s) of unresponsiveness before a worker is killed | `120` | machine learning |
| `MACHINE_LEARNING_PRELOAD__CLIP` | Name of a CLIP model to be preloaded and kept in cache | | machine learning |
| `MACHINE_LEARNING_PRELOAD__FACIAL_RECOGNITION` | Name of a facial recognition model to be preloaded and kept in cache | | machine learning |
\*1: It is recommended to begin with this parameter when changing the concurrency levels of the machine learning service and then tune the other ones.
+4
View File
@@ -28,6 +28,10 @@ Or before beginning app installation, [create the datasets](https://www.truenas.
Immich requires seven datasets: **library**, **pgBackup**, **pgData**, **profile**, **thumbs**, **uploads**, and **video**.
You can organize these as one parent with seven child datasets, for example `mnt/tank/immich/library`, `mnt/tank/immich/pgBackup`, and so on.
:::info Permissions
The **pgData** dataset must be owned by the user `netdata` (UID 999) for postgres to start. The other datasets must be owned by the user `root` (UID 0) or a group that includes the user `root` (UID 0) for immich to have the necessary permissions.
:::
## Installing the Immich Application
To install the **Immich** application, go to **Apps**, click **Discover Apps**, either begin typing Immich into the search field or scroll down to locate the **Immich** application widget.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 758 KiB

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