Compare commits

...

418 Commits

Author SHA1 Message Date
Alex
536fda04f2 Up version for release 2022-10-04 15:29:47 -05:00
Alex
2094204877 Up version for release 2022-10-04 15:29:37 -05:00
Alex
ab375cca1a Up Version for release 2022-10-04 15:21:58 -05:00
Alex
479f706f8a fix(mobile): Fix error parsing datetime prevent the timeline to be displayed (#784) 2022-10-04 15:19:29 -05:00
Deepesh Bhardwaj
4342285507 Updated jpeg thumbnail path (#780) 2022-10-04 09:46:06 -05:00
Jonas Janz
8bb656cb17 add docker volumes to services (#766)
* add docker volumes to services

this change adds the volume definitions for
/usr/src/app/upload
/usr/src/app/.reverse-geocoding-dump

to the `immich-server` docker-compose files
as /usr/src/app/upload should always be a volume for the containers
I also added it to the `Dockerfile`

Signed-off-by: PixelJonas <5434875+PixelJonas@users.noreply.github.com>

* remove geocoding-dump volume from docker-compose

Signed-off-by: PixelJonas <5434875+PixelJonas@users.noreply.github.com>
2022-10-01 16:01:27 -05:00
Alex
3f1f835df3 Update readme for beta release invitation links 2022-09-29 15:13:18 -05:00
Matthias Rupp
87ca031335 Fix bug with missing year and add date to drag handle (#761) 2022-09-29 10:19:55 -05:00
Alex Tran
96b9e37461 Up version for release 2022-09-28 16:28:14 -05:00
Alex Tran
0d3a2fe844 Added generated geocoding files to gitignore 2022-09-28 15:44:43 -05:00
Johannes Zellner
848781aef5 Provide a sensible dumpDirectory for the local-reverse-geocoder module (#759)
Fixes #758
2022-09-28 15:43:34 -05:00
Matthias Rupp
28bf497a0b feat(mobile): Improve timeline performance on mobile - experimental (#710) 2022-09-28 11:30:38 -05:00
Alex Tran
8ede738396 Up mobile version 2022-09-28 06:22:12 -05:00
Alex Tran
40c2b6a563 Update readme 2022-09-28 05:59:23 -05:00
Alex Tran
3581cf7305 Pump server version 2022-09-28 05:53:50 -05:00
Zack Pollard
c33775b944 feat(server): missing exif extract nightly task (#754)
* fix: nightly reverse geocoding task checking for mapbox

* refactor: remove file size from image processor and queue data

* feat: add missing exif nightly job

* Remove filesize requirement in assetUploadedProcessorName queue insertion

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2022-09-28 05:41:50 -05:00
Alex
b0cd2522e0 feat(server): support .NEF file (#746) 2022-09-23 19:09:45 -05:00
Alex
c3979f6e31 fix(machine-learning) Remove unsused database config (#745) 2022-09-23 19:00:47 -05:00
Alex
103df4d9f3 fix(web) navigating forward button get in the way of video control bar (#744)
* fix(web) navigating forward button get in the way of video control bar

* Remove unsued style
2022-09-23 18:22:06 -05:00
Zack Pollard
040e02cfc5 fix(server): handle missing reverse geocoding admin zones (#742) 2022-09-23 10:14:42 -05:00
Zack Pollard
f377b64065 feat(server) Remove mapbox and use local reverse geocoding (#738)
* feat: local reverse geocoding implementation, removes mapbox

* Disable non-null tslintrule

* Disable non-null tslintrule

* Remove tsignore

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2022-09-22 21:50:05 -05:00
Alex
e5459b68ff fix(server,web,mobile): Incorrectly record and show timestamp and time zone of the asset (#706)
Implemented a mechanism to extract the correct time zone from the GPS coordinate if presented in the file's EXIF, and to convert the timestamp to the correct UTC time so that the time will show correctly based on the mobile/web local time zone.
2022-09-22 15:58:17 -05:00
Alex Tran
fc194021a4 Pump server version 2022-09-22 11:38:50 -05:00
bo0tzz
39f8ca3bf1 Only run scheduled geocoding task once per day (#730) 2022-09-21 07:17:59 -05:00
Alex
7a807f7216 Update README.md 2022-09-19 16:04:22 -05:00
Alex
bedfb51b1c Add demo URL 2022-09-19 16:00:51 -05:00
Alex
b2afb95c19 Create codeql-analysis.yml 2022-09-19 14:03:49 -05:00
Alex
10239161fd fix(mobile): app crash when there is no object detection result on search page (#725)
* fix(mobile): app crash when there is no data for object detection

* Up version for release

* Up version for release
2022-09-19 11:03:51 -05:00
Alex
242f10952d fix(server): query only image (#724) 2022-09-19 10:48:44 -05:00
Alex Tran
e997bd371b Up server version 2022-09-18 21:44:55 -05:00
Alex
400167f4ef fix(server): sanitization error that crash the server (#721) 2022-09-18 21:44:13 -05:00
Alex
572f6d833d Up mobile version and update deprecated api 2022-09-18 16:11:30 -05:00
Alex
2e06be5155 Up mobile version and update deprecated api 2022-09-18 16:11:24 -05:00
Alex Tran
62121470a8 Up server version 2022-09-18 15:37:10 -05:00
Alex
e3ccc3ee6b feat(server): sanitized path for asset creation process to avoid security risk (#717)
* feat(server): sanitized path for asset creation process to avoid security risk

* Sanitize resize path
2022-09-18 15:16:53 -05:00
Alex
ece94f6bdc fix(server): correct user permission to update user info (#716) 2022-09-18 09:27:06 -05:00
Jamie Slome
03fc0703c0 Create SECURITY.md (#712) 2022-09-17 13:07:12 -05:00
Alex
0d13b25f56 feat(web): Update to latest version of SvelteKit (#705) 2022-09-16 23:13:22 -05:00
Alex
75c2067836 feat(web) Remove fetching fonts from GoogleFonts (#703) 2022-09-16 17:23:31 -05:00
Alex
824da6a07b Up server version 2022-09-16 16:55:04 -05:00
Alex
2c2ea24dc4 test(web) Add tests for asset repository (#680)
* Added back tests for asset repository

* Added more tests

* Added asset count test
2022-09-16 16:47:45 -05:00
Alex
47b73a5b64 fix(mobile): Fixed iOS 16 overflow cache and memory leaked in gallery viewer. (#700) 2022-09-16 16:46:23 -05:00
bo0tzz
6b3f8e548d Merge pull request #699 from JaCoB1123/patch-1
Fix spelling of Proxmox in Readme
2022-09-15 23:07:00 +02:00
Jan Bader
0ea483f901 Fix spelling of Proxmox in Readme 2022-09-15 23:05:15 +02:00
Jonas Janz
97aed8ef23 fix(nginx): revert nginx image to support arm/v7 (#692) 2022-09-14 13:36:29 -05:00
Alex
0ee3fe9157 Update install.sh to use latest released tag 2022-09-14 11:07:37 -05:00
Alex
434770155f Up version for release 2022-09-14 10:27:34 -05:00
Alex
7e8bf94543 fix/cache read write error ios16 (#691)
* Fix(mobile) cache read/write issue, cannot load image on ios16

* Update
2022-09-14 10:18:25 -05:00
Zack Pollard
8d8944705c Merge pull request #690 from beune/fix-typo
Fix typo
2022-09-14 13:16:47 +01:00
Pim Beune
7c9c1a5169 Fix typo 2022-09-14 13:53:34 +02:00
Jonas Janz
1a6c16d8ea breaking(setup): use non-root image for immich-proxy (#651)
* feat(nginx): use non-root container for immich-proxy

Signed-off-by: PixelJonas <5434875+PixelJonas@users.noreply.github.com>

* re-add test env

* feat(nginx): add correct port for staging

* add the new port to the default docker-compose.yml

Signed-off-by: PixelJonas <5434875+PixelJonas@users.noreply.github.com>
2022-09-13 21:50:10 -05:00
Alex
ccf792f9d3 fix(server): mismatch createdAt value in table and table (#688) 2022-09-13 20:12:42 -05:00
Fynn Petersen-Frey
789bc8563c fix Android BackgroundServiceStartNotAllowedException (#687) 2022-09-13 20:12:31 -05:00
Manuel
99a50f70dd readme: add app store links (#689) 2022-09-13 18:23:27 -05:00
Alex Tran
9bef411056 Up server version: 2022-09-13 12:14:36 -05:00
Alex
e79e92c60f Added Log level to background service (#685) 2022-09-13 12:09:57 -05:00
Alex
858ad43d3b fix(server): harden inserting process, self-healing timestamp info on bad timestamp (#682)
* fix(server): harden inserting process, self-healing timestamp info
2022-09-12 23:35:44 -05:00
Alex
5761765ea7 fix(server): remove album thumbnail when the asset is deleted from the database (#681) 2022-09-12 22:06:52 -05:00
Thanh Pham
6abc733763 fix(web): datetime display and add TZ into environment (#618)
* fix(web): timezone

* doc(): update readme.md

* feat(web): keep using UTC timezone in default

* chore(): update doc and remove debug code

* chore(): update readme.md

* Move timezone into to .env.example

* Run prettier check

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2022-09-12 14:40:18 -05:00
Alex Tran
4271e24e59 Up version for release 2022-09-11 16:05:53 -05:00
Alex
9e4ed2214b fix(web): incorrect shared album count (#677) 2022-09-11 10:07:04 -05:00
Alex
011332e509 fix(mobile) memory leaked causes app to crash when swiping (#673)
* Dispose image provider when swiping away from the asset
2022-09-11 09:56:26 -05:00
Alex
5403ef4d84 Fix(mobile) oversize play button (#672) 2022-09-11 00:25:04 -05:00
Alex Tran
31739aca02 Up version for release 2022-09-10 11:58:59 -05:00
Thanh Pham
8f2e7b6f65 fix(server): loop on checksum generation (#662) 2022-09-10 11:52:39 -05:00
Brett Profitt
4ed647c43d fix(install): Fix checking for docker compose. (#663) 2022-09-10 11:48:50 -05:00
Alex
f88ff4fb5c fix(mobile): background backup not working in release mode (#664) 2022-09-10 11:46:51 -05:00
Alex Tran
cc4881d633 Up version for release 2022-09-09 23:23:37 -05:00
Alex
d856b35afc feat(web) add scrollbar with timeline information (#658)
- Implement a scrollbar with a timeline similar to Google Photos
- The scrollbar can also be dragged
2022-09-09 15:55:20 -05:00
Jaime Baez
b6d025da09 Fix Notification components possible memory leaks (#650)
Dispose subscriptions and timeouts when
the components are removed from the DOM
2022-09-09 07:40:35 -05:00
Jaime Baez
cc79ff1ca3 Merge pull request #642 from immich-app/add/ci-web-checks
Add web test / check commands and workflow to run in CI
2022-09-08 19:12:39 +02:00
Jaime Baez
131aa2b6be Add command to test/check code in dev-setup docs 2022-09-08 17:54:45 +02:00
Jaime Baez
02a6b73122 Add web-unit-test workflow to run in CI 2022-09-08 17:44:13 +02:00
Jaime Baez
d87366c095 Add dev-setup documentation 2022-09-08 17:41:24 +02:00
Jaime Baez
4f7a3afbfc Fix web lint issues 2022-09-08 17:30:49 +02:00
Jaime Baez
6725954b70 Add web check / lint npm commands
`svelte-check` returns some "hints" that can be ignored since some
are not true and others are not relevant.
2022-09-08 17:17:15 +02:00
Fynn Petersen-Frey
4fe535e5e8 improve Android background service reliability (#603)
This change greatly reduces the chance that a backup is not performed
when a new photo/video is made.
Instead of combining the change trigger and additonal constraints (wifi
or charging) into a single worker, these aspects are now separated.
Thus, it is now reliably possible to take pictures while the wifi
constraint is not satisfied and upload them hours/days later once
connected to wifi without taking a new photo.
As a positive side effect, this simplifies the error/retry handling
by directly leveraging Android's WorkManager without workarounds.
The separation also allows to notify the currently running BackupWorker
that new assets were added while backing up other assets to also upload
those newly added assets.
Further, a new tiny service checks if the app is killed, to reschedule
the content change worker and allow to detect the first new photo.
Bonus: The home screen now shows backup as enabled if background backup
is active.

* use separate worker/task for listening on changed/added assets
* use separate worker/task for performing the backup
* content observer worker enqueues backup worker on each new asset
* wifi/charging constraints only apply to backup worker
* backupworker is notified of assets added while running to re-run
* new service to catch app being killed to workaround WorkManager issue
2022-09-08 08:36:08 -05:00
Jaime Baez
aed94bfc4c Format web code with prettier
Added `.md` and `.json` to .prettierignore
2022-09-08 12:53:09 +02:00
Jaime Baez
de996c0a81 Merge pull request #612 from immich-app/add/web-ui-tests-setup
Add web UI components tests setup

@alextran1502 I'll get this merged so I can add CI checks for the web as well. Let me know if you have any questions 😃
2022-09-08 11:24:08 +02:00
Jaime Baez
1a39aa4da5 Merge pull request #633 from immich-app/fix/server-lint-errors
Add all server checks to CI - fix lint issues
2022-09-08 11:12:31 +02:00
Jaime Baez
1f4ba73da7 Add all server checks to CI - fix lint issues
CI will now run linter, type-checks and tests for the server.

All the lint issues have been fixed.
2022-09-08 11:07:27 +02:00
Alex Tran
836b174d33 Better styling for count info 2022-09-07 21:19:24 -05:00
Alex Tran
853a65aef1 Up version for release 2022-09-07 15:26:29 -05:00
Alex
566039b93f feat(web): add asset and album count info (#623)
* Get asset and album count

* Generate APIs

* Added asset count for each type

* Added api on the web

* Added info button for asset and album count to trigger getting info on hover

* Remove websocket event from photo page
2022-09-07 15:16:18 -05:00
bo0tzz
18a7ff8726 Remove empty translations (#620) 2022-09-07 14:41:44 -05:00
Thanh Pham
6ffdf167fe fix(web): detail panel overflow-x (#615) 2022-09-07 13:20:44 -05:00
Jaime Baez
6b702b13e4 Rename albums BLoC (.bloc.ts convention)
By convention now it's `album.bloc.ts`
2022-09-07 16:04:50 +02:00
Jaime Baez
f476bd985b Add AlbumCard UI tests
- add libraries for component UI testing
- implement AlbumCard UI tests
2022-09-07 16:00:57 +02:00
Alex
92c4f0598b fix(mobile): search page crashes the app on some Android models (#610) 2022-09-07 06:45:26 -05:00
Alex
a337402124 fix(web): stop showing version announcement on first run of a new web instance (#609) 2022-09-07 06:38:29 -05:00
dependabot[bot]
209e6332b3 Bump actions/checkout from 2 to 3 (#604)
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-07 06:08:44 -05:00
Jaime Baez
645bd8a109 Add web test setup (#597)
* Extract logic from Albums page

- move "albums" page logic to `albums-bloc`
- add types to AlbumCard custom events

* Implement some album-bloc unit-tests

- add libraries for testing
- add album factory
- changes in albums-bloc API

* Add rest of albums-bloc test

Cleanup and remove console logs

* Refactor `isShowContextMenu` writable to derived
2022-09-07 05:20:19 -05:00
Daniel Weaver
9a471d80f7 Update README.md (#599)
Adding a note to the installation section about reverse proxies being a cause for issues when uploading large files.
2022-09-06 16:05:38 -05:00
Alex Tran
de0c59efe7 Added mobile change log 37 2022-09-06 10:03:55 -05:00
Alex Tran
c19d26f4f3 Update some mobile UI with Material 3 theme 2022-09-06 09:37:04 -05:00
Alex Tran
2edfc75c8a Fixed sliverappbar icon color to conform with theming 2022-09-06 08:18:07 -05:00
Matthias Rupp
4c977d2c1f fix(mobile): cache related crash (#593) 2022-09-06 08:10:52 -05:00
Alex
1425f2ec78 Up server version 2022-09-05 23:44:42 -05:00
Alex
b081eda76f fix(server): change the createdAt and modifiedAt to the correct type in database (#591)
* Added migration files

* Remove type casting in sql query
2022-09-05 20:51:01 -05:00
Thanh Pham
7f6837c751 hotfix(server): skip exif extraction on duplicate file (#590)
* fix(server): skip exif extraction on duplicate file

* fix(server): typo

* chore(server): remvoe un-use code
2022-09-05 20:02:50 -05:00
Thanh Pham
a467936e73 feat(server): de-duplication (#557)
* feat(server): remove un-used deviceAssetId cols.

* feat(server): return 409 if asset is duplicated

* feat(server): replace old unique constaint

* feat(server): strip deviceId in file path

* feat(server): skip duplicate asset

* chore(server): revert changes

* fix(server): asset test spec

* fix(server): checksum generation for uploaded assets

* fix(server): make sure generation queue run after migraion

* feat(server): remove temp file

* chore(server): remove dead code
2022-09-05 14:45:38 -05:00
Alex Tran
2677ddccaa Up version for release 2022-09-05 14:32:05 -05:00
bo0tzz
564ace3ddf Use runtime env var for login page message to lower web container startup time (#577)
* Use runtime env var for loginPageMessage

* Rename VITE_LOGIN_PAGE_MESSAGE to PUBLIC_LOGIN_PAGE_MESSAGE in .env.example

* Move docker image `npm run build` step into Dockerfile

* Remove comment from web Dockerfile
2022-09-05 09:51:45 -05:00
Thanh Pham
a81ef7497c feat(server): support 3gpp format (#582)
* feat(server): support 3gpp format

* feat(web): add 3gp ext

* Support 3gp video format.

video/3gpp mimetype added to supported video format.

* feat(mobile): add tif ext

Co-authored-by: Alexandre Bouijoux <alexandre@bouijoux.fr>
2022-09-05 08:53:13 -05:00
Matthias Rupp
caa7b07398 Show all albums an asset appears in on the asset viewer page (#575)
* Add route to query albums for a specific asset

* Update API and add to detail-panel

* Fix tests

* Refactor API endpoint

* Added alt attribute to img tag

Co-authored-by: Alex <alex.tran1502@gmail.com>
2022-09-05 08:50:20 -05:00
Alex
6976a7241e Fixed upload asset to album in asset selection (#579)
* Fixed error uploading a file from album

* Fixed album selection mode show viewing asset stage

* Navigate back after uploading asset to album
2022-09-05 00:18:53 -05:00
Alex Tran
172eda3ce5 Fixed readme 2022-09-04 21:08:13 -05:00
Alex
552340add7 Feature - Implemented virtual scroll on web (#573)
This PR implemented a virtual scroll on the web, as seen in this article.

[Building the Google Photos Web UI](https://medium.com/google-design/google-photos-45b714dfbed1)
2022-09-04 08:34:39 -05:00
SirBogner
bd92dde117 Update localizely.yml (#574) 2022-09-04 08:27:05 -05:00
Alex
617c54ab81 [Localizely] Translations update (#576) 2022-09-04 08:26:11 -05:00
Thanh Pham
c76f7804ab feat(server): generate checksum for previous uploaded assets (#558)
* feat(server): generate checksum for previous uploaded assets

* fix(server): typo
2022-09-02 08:32:21 -05:00
Damian Gomez
0799aa2c72 Italia language for Mobile App (#559)
Co-authored-by: Damian Gomez <damian.gomez@elitedivision.it>
2022-09-01 08:48:13 -05:00
Thanh Pham
b80dca74ef feat(server): calculate sha1 checksum (#525)
* feat(server): override multer storage

* feat(server): calc sha1 of uploaded file

* feat(server): add checksum into asset

* chore(server): add package-lock for mkdirp package

* fix(server): free hash stream

* chore(server): rollback this changes, not refactor here

* refactor(server): re-arrange import statement

* fix(server): make sure hash done before callback

* refactor(server): replace varchar to char for checksum, reserve pixelChecksum for future

* refactor(server): remove pixelChecksum

* refactor(server): convert checksum from string to bytea

* feat(server): add index to checksum

* refactor(): rollback package.json changes

* feat(server): remove uploaded file when progress fail

* feat(server): calculate hash in sequence
2022-08-31 09:27:17 -05:00
Thanh Pham
f5f00e0f6c fix(web): file uploading error in album page (#550)
* feat(web): show upload error notification

* fix(web): album upload issue
2022-08-31 08:12:31 -05:00
Fynn Petersen-Frey
75d2d82d05 ask user to disable battery optimizations when turning on background backup (#554)
* ask user to disable battery optimizations when turning on background backup

* remove obsolete texts/translations

* add button link to dontkillmyapp
2022-08-31 08:08:40 -05:00
Fynn Petersen-Frey
5172242f88 fix: persist WiFi + charging settings of background backup (#553) 2022-08-30 09:09:19 -05:00
Matthias Rupp
25e68cf826 Better caching for mobile (#521)
* Use custom caches in all modules

* Cache Settings

* Fix wrong key

* Create custom cache repository based on hive

* Show cache usage in settings

* Show cache sizes

* Change settings ranges and default value

* Handle cache clear by operating system

* Resolve review comments
2022-08-29 22:44:43 -05:00
be bright
e527685ebf Added korean translation for mobile app (#549)
* Added korean translation for mobile app

* Added locale to info.plist

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2022-08-29 08:54:40 -05:00
Thanh Pham
e745cb5e4b fix(server): parse all img formats and enrich metadata (#547)
* fix(server): use file path instead buffer to reduce memory usage

fix undefined exif data

* fix(server): parse all img formats

* feat(server): enrich metadata

* Format oneliner condition

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2022-08-28 15:43:31 -05:00
Thanh Pham
dfaa4969da Server - Fixed - Use file path instead buffer to reduce memory usage on EXIF extraction (#545)
fix undefined exif data
2022-08-28 11:09:24 -05:00
Alex
f980a2f27a Add asset repository and refactor asset service (#540)
* build endpoint to get asset count by month

* Added asset repository

* Added create asset

* get asset by device ID

* Added test for existing methods

* Refactor additional endpoint

* Refactor database api to get curated locations and curated objects

* Refactor get search properties

* Fixed cookies parsing for websocket

* Added API to get asset count by time group

* Remove unused code
2022-08-26 22:53:37 -07:00
Alex
6b7c97c02a Added release notes 2022-08-26 13:43:05 -07:00
Alex
fdd9f37abd Added error handling for layout.server.ts to avoid unaccessible to previous deploy instance due to changes in SvelteKit project 2022-08-26 11:30:45 -07:00
Alex
a09bba454c Pump version for release 2022-08-26 10:57:12 -07:00
Alex
4be9aa091b Added error handling notification (#536) 2022-08-26 10:36:41 -07:00
Alex
33b810de74 Removed upload button on sharing and album page 2022-08-26 10:05:15 -07:00
Alex
44ccb1eec1 Added timeout option for notification component 2022-08-26 10:01:47 -07:00
Alex
bef38c670c Reference CLI in limit upload message 2022-08-26 09:42:48 -07:00
Alex
025d7bf192 Merge branch 'main' of github.com:immich-app/immich 2022-08-26 09:42:17 -07:00
Alex
5ad2d62039 Added limit on total of file upload on web (#535) 2022-08-26 09:39:28 -07:00
Alex
a128833e68 Added limit on total of file upload on web 2022-08-26 09:36:54 -07:00
Alex
87f7b0849a Added migration down for change exif file type 2022-08-26 09:13:11 -07:00
Alex
4596a8ee01 Change fileSizeInByte to bigint from int to handle large size (#534) 2022-08-26 09:07:59 -07:00
Alex
f9b1b12b10 Implement notification box for web (#533)
* Added test button

* styling notification box

* Added auto dismission and animation to each notificaiont list

* Remove test button
2022-08-25 23:04:23 -07:00
Alex
68b1655e7f Show the first two letter of user first and last name when profile image not existed (#532)
* Added user first name and last name abbreviation to Circle Avatar:

* Remove unsued code
2022-08-25 15:52:11 -07:00
Alex
658b64df74 Added page navigation progress indicator 2022-08-25 13:02:36 -07:00
Alex
e344503834 Fixed navigating with keyboard skip assets (#531)
* Cleaned up event listner
2022-08-24 22:18:28 -07:00
Alex
bf2760ffef Fixed mobile timeline crash when date group cannot be parsed (#530)
* Handle error when datetime is incorrect

* Added better debug message
2022-08-24 21:31:20 -07:00
Alex
db2ed2d881 Migrate SvelteKit to the latest version 431 (#526) 2022-08-24 21:10:48 -07:00
Thanh Pham
fb0fa742f5 fix(web): buffering for video player (#520)
* fix(web): buffering for video player

* chore(): missing file -_-

* refactor(web): using URL builder

* chore(): add semicolon

* fix(web): video player

* remove deadcode

Co-authored-by: Alex <alex.tran1502@gmail.com>
2022-08-23 20:21:41 -07:00
Thanh Pham
3b55cdc0be refactor(server): move constant into common package (#522)
* refactor(server): move constant into common package

* refactor(server): re-arrange import statement in microservice module

* refactor(server): move app.config into common package

* fix(server): e2e testing
2022-08-23 07:34:21 -07:00
Alex
0efcc99f3e Added Dutch locale 2022-08-22 12:52:24 -07:00
Nick Pieper
7a85164a1e Added dutch translation for Immich (#519)
* Create nl-NL.json with dutch translation

* Add nl-NL to localizely.yml
2022-08-22 12:50:56 -07:00
Thanh Pham
ba2cda8955 feat(server): support tiff uploading (#513)
* feat(server): suport tiff uploading

* remove unused variable

Co-authored-by: Alex <alex.tran1502@gmail.com>
2022-08-22 12:49:17 -07:00
Alex
9048be4c8e Added Code of conduct 2022-08-21 12:43:56 -07:00
Alex
83716ae1bc Added changelog note 2022-08-21 12:30:15 -07:00
Alex
5cd4d2d158 Added condition to show notification setting on android only 2022-08-21 11:04:01 -07:00
Alex
13bb6d469b Pump version for release 2022-08-21 09:56:52 -07:00
Matthias Rupp
8e4c4c34e4 Use CachedNetworkImage and separate cache for thumbnails on library page (#509)
* Use CachedNetworkImage and separate cache for thumbnails on library page

* Use caching for shared albums as well

* Introduce cache service
2022-08-21 09:41:36 -07:00
Fynn Petersen-Frey
3125d04f32 show notifications on background backup errors (#496)
* show notifications on background backup errors

* settings page to configure (background backup error) notifications

* persist time since failed background backup

* fix darkmode slider color
2022-08-21 09:29:24 -07:00
Alex
c436c57cc9 Fixed immich-machine-learning container not starting correctly in production 2022-08-20 23:04:10 -07:00
Thanh Pham
7f9f825589 fix(server): correct media info (#508)
* fix(server): correct media info

* fix(server): video metadata
2022-08-20 22:58:47 -07:00
Alex
da9aed5c11 Fixed e2e container stage 2022-08-20 22:37:55 -07:00
Alex
10ef3509dd Fixed machine-learning container cannot start prod 2022-08-20 22:27:25 -07:00
Alex
3dc538f9e6 Fixed machine-learning container cannot start prod 2022-08-20 22:26:47 -07:00
Thanh Pham
1e29ff322d build(server): minimal container (#506)
* build(server): update Dockerfile

* build(server): fix dockerfile

* build(machine-learning): multiple build stages

* build(server): update Dockerfile
2022-08-20 21:19:02 -07:00
Thanh Pham
9c30d58b10 feat(server): preserve caption fields and extract mediainfo for video (#505)
* feat(server): preserve caption fields and extract mediainfo for video

* Fixed Geocoding missing info leads to fail EXIF extraction for the whole file

Co-authored-by: Alex <alex.tran1502@gmail.com>
2022-08-20 16:31:37 -07:00
Matthias Rupp
013a0f8324 Customization options for asset grid (#498)
* Add settings options for number of assets per row and storage indicator

* Add attributes to enum to avoid duplicate code

* Also apply customizations to albums

* Minor Refactorings

* Three stage loading i18n fix
2022-08-20 14:19:40 -07:00
Alex
07b58f46f9 Merge branch 'main' of github.com:alextran1501/immich 2022-08-20 08:01:59 -07:00
Alex
566e118a19 Added pt-BR translation locale to mobile app 2022-08-20 08:01:52 -07:00
Oton
0e18c88534 pt-BR Translation: Translation into Portuguese Brazil. (#500) 2022-08-20 08:01:25 -07:00
Alex
068d06b9ee Add x-adobe-dng to support file type (#504) 2022-08-20 07:50:58 -07:00
Thanh Pham
0cf7606ec9 fix(server): remove albumThumbnailAssetId when album is empty (#495) 2022-08-19 11:47:14 -07:00
Alex
25338ce02f Fixed issue with filename is blank on iOS causing update to fail 2022-08-18 16:27:08 -05:00
Alex Tran
4805d86a7c pump version 2022-08-18 15:01:45 -05:00
Fynn Petersen-Frey
33b1410d82 upload new photos in background with a service (#382)
* properly done background backup service

* new concurrency/locking management with heartbeat

fix communication erros with Kotlin plugin on start/stop service methods

better error handling for BackgroundService public methods

Add default notification message when service is running

* configurable WiFi & charging requirement for service

* use translations in background service
2022-08-18 09:41:59 -05:00
r3nor
f35ebec7c6 Readme redistribution and reorganisation (#485)
* redistribute and organize readme

* Fix typos

* Change developers to development

* Remove mobile app emoji

* Multiple changes

- Removed the .env example inbody to link to the .env.example file; this way it won't be needed to change the readme if the .env file changes and the readme gets shorter.
- Redistributed the steps:
  - Inline instead of tables
  - bullets in steps
- Fix wording
2022-08-18 08:31:00 -05:00
Thanh Pham
3aa6ee0320 feat: remove webp on asset deleted as well (#489)
* fix(server): remove webp file on asset deleted

* chore(server): job not fail when file not found
2022-08-18 08:25:03 -05:00
Thanh Pham
cdb0aa00d8 feat(server, microservices): add bull prefix (#490) 2022-08-18 08:24:07 -05:00
Alex
9de7b8d3a7 Create github-repo-stats.yml 2022-08-16 22:56:20 -05:00
Max
4a28a46612 fix spelling mistakes (#479) 2022-08-16 13:50:45 -05:00
Malte Kiefer
16561d15ff Added German translation for the settings view (#478)
* added translation for the settings view

* added translation for the settings view
2022-08-16 11:00:48 -05:00
Alex
9642ad2820 Fixed Websocket not getting correct data on mobile 2022-08-15 23:43:12 -05:00
Alex
e2169a26c2 Remove padding bottom on photos page mobile 2022-08-15 23:11:54 -05:00
Alex
f697922f32 Remove hardcode UIsystemLight in info.plist (#475) 2022-08-15 23:10:51 -05:00
Alex Tran
1390d01763 Up version 2022-08-15 19:13:51 -05:00
Alex
86f780871c Fixed different lettercases in email create different user (#470)
* Fixed different lettercases in email create different user

* Fixed test
2022-08-15 19:11:08 -05:00
Alex
c1b22125fd Add mobile dark mode and user setting (#468)
* styling light and dark theme

* Icon topbar

* Fixed app bar title dark theme

* Fixed issue with getting thumbnail for things

* Refactor sharing page

* Refactor scroll thumb

* Refactor chip in auto  backup indiation button

* Refactor sharing page

* Added theme toggle

* Up version for testflight build

* Refactor backup controller page

* Refactor album selection page

* refactor album pages

* Refactor gradient color profile header

* Added theme switcher

* Register app theme correctly

* Added locale to the app

* Added translation key

* Styling for bottomsheet colors

* up server version

* Fixed font size

* Fixed overlapsed sliverappbar on photos screen
2022-08-15 18:53:30 -05:00
Alex
30f069a5db Add settings screen on mobile (#463)
* Refactor profile drawer to sub component

* Added setting page, routing with some options

* Added setting service

* Implement three stage settings

* get app setting for three stage loading
2022-08-13 15:51:09 -05:00
bo0tzz
2bf6cd9241 Fix redirect to login page after password change (#461)
* Fix redirect to login page after password change

Copied from the similar fix in #414

* Fix typo in change-password form

* Remove misplaced text from user management page
2022-08-13 09:54:29 -05:00
Alex Tran
87d2a954a3 Fixed error handling with catch block 2022-08-12 22:29:24 -05:00
Alex
a388c5a642 Fixed webp upload on web (#460) 2022-08-12 21:52:30 -05:00
Alex Tran
4b34f017ca cosmetic change 2022-08-12 21:19:54 -05:00
Alex Tran
5c1d1dd5a1 Added version note for f-droid 2022-08-12 20:10:00 -05:00
Alex Tran
1580d27c23 Up version 2022-08-12 20:06:45 -05:00
Alex
4b9187928c Edit user on the web (#458)
* Added dispatch event for edit user

* Fixed import location

* solve merge conflict

* Fixed issue not admin user can access admin page

* Implemented edit user and password reset
2022-08-12 14:25:19 -05:00
Alex Tran
5b7236f6ad Temporary remove bug tests 2022-08-11 23:17:09 -05:00
Alex Tran
6fb439b580 Fixed merge conflict 2022-08-11 13:46:42 -05:00
Alex Tran
a8334b5c27 Fixed test again 2022-08-11 13:46:11 -05:00
Alex Tran
e1cac93945 Fixed test 2022-08-11 09:29:53 -05:00
R0GGER
081f9f5bce typo (#456) 2022-08-11 08:33:44 -05:00
Alex Tran
25ccc5660d Merge branch 'main' of github.com:immich-app/immich 2022-08-11 08:27:48 -05:00
Alex Tran
b6d3e578f2 Added test and github action for unit tests 2022-08-11 08:27:44 -05:00
Matthias Rupp
52377c2dcf Fix sharing on iPad (#453) 2022-08-11 08:13:33 -05:00
Alex
5c78f707fe Modify Album API endpoint to return a count attribute instead of a full assets array (#454)
* Change API to return assets count and change web behavior accordingly

* Refactor assets.length

* Explicitly declare type of assetCount so Dart SDK understand it

* Finished refactoring on mobile
2022-08-10 22:48:25 -05:00
Alex Tran
bd5ed1b684 Merge branch 'main' of github.com:immich-app/immich 2022-08-09 19:12:32 -05:00
Alex Tran
e89339b813 Up server version 2022-08-09 19:12:21 -05:00
Alex
0b69feda40 Fixed checkbox render performance (#448) 2022-08-09 19:10:55 -05:00
Alex
339f7f776f Fixed setting high refresh rate crash ios release build 2022-08-08 23:43:48 -05:00
Alex Tran
7e6ccbad21 Up server version 2022-08-08 22:55:35 -05:00
Alex Tran
aac53e5cdc Up version for release 2022-08-08 22:39:32 -05:00
Alex Tran
cbec75a175 Rewording delete caution message 2022-08-08 22:13:36 -05:00
Alex
bf04d9eb39 Feature - Delete asset on the web (#436)
* Added selection mechanism to photos page

* Added control app bar

* Refactor AlbumAppBar into ControlAppBar

* Added addtional micro interactions when in multi selection mode

* Implemented delete selected asset and rerender
2022-08-08 22:06:11 -05:00
Malte Kiefer
3058c894b1 updated German translation (#444) 2022-08-08 21:21:02 -05:00
Matthias Rupp
e57e279fe1 Share assets from mobile to other apps (#435)
* Share unique assets

* Style share preparing dialog

* Share assets from multiselect

* Fix i18n

* Use navigator like in delete dialog

* Center bottom-bar buttons
2022-08-08 10:46:12 -05:00
dependabot[bot]
f43c58fc6d Bump docker/build-push-action from 3.1.0 to 3.1.1 (#441)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.1.0...v3.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-08 08:22:14 -05:00
Matthias Rupp
dea304ac39 Fix/album title (#440)
* Fix album title overflow

* i18n

* More i18n
2022-08-08 08:11:56 -05:00
Matthias Rupp
b46e834220 Mobile performance improvements (#417)
* First performance tweaks (caching and rendering improvemetns)

* Revert asset response caching

* 3-step image loading in asset viewer

* Prevent panning and zooming until full-scale version is loaded

* Loading indicator

* Adapt to gallery PR

* Cleanup

* Dart format

* Fix exif sheet

* Disable three stage loading until settings are available
2022-08-07 19:43:09 -05:00
Alex Tran
46f4905259 Up server version 2022-08-07 18:42:21 -05:00
Alex
28c7736ecd Fix error in logout procedure and guard for each route (#439) 2022-08-07 18:36:34 -05:00
Alex Tran
f881981c44 Fix typo in Readme 2022-08-07 08:22:03 -05:00
Alex
953d18e795 Remove serverEndpoint completely and fix upload path (#434) 2022-08-07 08:12:31 -05:00
Alex
b45024a97e Update README.md 2022-08-07 00:17:12 -05:00
Alex Tran
3dcdfa0166 Up android build version 2022-08-06 23:45:31 -05:00
Alex
2079583866 Update installation method and documentation (#424)
* Add installation script

* Populate instsall.sh

* format

* Get IP address on both macos and linux

* Update mobile version

* Remove test folder

* Added sed command for ios

* Added sed command for ios

* Fixed ios command

* Fixed ios command

* Added friendly debug message

* Update README

* Update Readme with new installation instruction

* Update message on instsallation script
2022-08-06 23:42:50 -05:00
Alex
b68358766b Remove VITE_SERVER_ENDPOINT dependency (#428)
* Move backend api to its own instance

* Remove external fetch hook

* Added endpoint for album

* Added endpoint for admin page

* Make request directly to immich-server

* Refactor unsued code
2022-08-06 18:14:54 -05:00
Alex Tran
cf2b9eddfa Pump version 1.20 2022-08-03 15:43:42 -05:00
Stevenson Chittumuri
8c184dc4d4 Enable swiping between assets (#381)
Enable swiping between assets (#381)

Co-authored-by: Alex <alex.tran1502@gmail.com>
Co-authored-by: Malte Kiefer <59220985+MalteKiefer@users.noreply.github.com>
Co-authored-by: Matthias Rupp <matthias.rupp@posteo.de>
2022-08-03 15:36:12 -05:00
Alex
e8d1f89a47 Implement album feature on mobile (#420)
* Refactor sharing to album

* Added library page in the bottom navigation bar

* Refactor SharedAlbumService to album service

* Refactor apiProvider to its file

* Added image grid

* render album thumbnail

* Using the wrap to render thumbnail and album info better

* Navigate to album viewer

* After deletion, navigate to the respective page of the shared and non-shared album

* Correctly remove album in local state

* Refactor create album page

* Implemented create non-shared album
2022-08-03 00:04:34 -05:00
Alex
0e85b0fd8f Remove print statement 2022-07-31 22:26:09 -05:00
Alex Tran
f7dc916e80 Fixed problem with Recent (isAll) album is both in exclude and include album list at the same time 2022-07-31 21:56:41 -05:00
Alex
03e7a254a2 Fixed logging out not redirect correctly in reverse proxy (#414)
* Remove check due to logout always success

* Added console log

* Remove console.log

* Up server version
2022-07-31 16:53:07 -05:00
Matthias Rupp
0ac9fe5a54 Load low- and high quality thumbnail in the same img tag to avoid flickering (#413) 2022-07-31 15:56:03 -05:00
Malte Kiefer
dc61fd925f fixed some German translations (#399) 2022-07-30 07:41:39 -05:00
Alex Tran
2aea08726f Update donation info 2022-07-29 13:42:39 -05:00
Alex Tran
746bec908b Update donation info 2022-07-29 13:41:29 -05:00
Alex Tran
8102e3b3f5 Fixed github action to conform with the move to org 2022-07-29 12:54:40 -05:00
Alex Tran
1ba998aa68 Added changlog for Fdroid release 2022-07-27 13:17:36 -05:00
Alex Tran
2de34f70ce Update readme 2022-07-27 13:09:52 -05:00
Alex Tran
8b9fd67d6f Remove AxiosError import due to production build error 2022-07-27 13:01:49 -05:00
Alex
97238a1621 Up version for release 2022-07-27 11:39:19 -05:00
Alex
ef4136d327 [WEB] Select album thumbnail (#383)
* Added context menu for album opionts

* choose asset for album thumbnail

* Refactor UpdateAlbumDto to accept albumThumbnailAssetId

* implemented changing album cover on web

* Fixed api change on mobile app
2022-07-27 11:16:02 -05:00
Alex
6dbca8d478 Added Japanese/Polish/Finish and fix Italian/Spanish translation 2022-07-27 11:14:21 -05:00
Alex
a305db9e6f [Localizely] Translations update (#384) 2022-07-27 11:07:37 -05:00
Alex Tran
59c1ea3097 Added 2-stage loading for album's thumbnail 2022-07-26 22:06:06 -05:00
Alex
03457f5d32 [WEB] Upload asset directly to album (#379)
* Added stores to get album assetId

* Upload assets and add to album

* Added comments

* resolve conflict when add assets from upload directly

* Filtered out duplicate asset before adding to the album
2022-07-26 20:53:25 -05:00
Alex
2336a6159c [WEB] Load thumbnail with native source property for faster load time (#378) 2022-07-26 15:13:08 -05:00
Alex Tran
e4c4b53fcd Added imageName as searchable text on database 2022-07-26 13:43:12 -05:00
Alex
83cbf51704 Use cookies for client requests (#377)
* Use cookie for frontend request

* Remove api helper to use SDK

* Added error handling to status box

* Remove additional places that check for session.user

* Refactor sending password

* prettier clean up

* remove deadcode

* Move all authentication requests to the client

* refactor upload panel to only fetch assets after the upload panel disappear

* Added keydown to remove focus on title change on album viewer
2022-07-26 12:28:07 -05:00
Alex Tran
2ebb755f00 Fixed corner radius for message board 2022-07-24 23:45:05 -05:00
Alex Tran
ec1c3a86f5 Added messages when there is no album or shared album 2022-07-24 23:30:30 -05:00
Alex
969f770df0 Delete album on web (#373)
* Show context menu

* Show context menu at the correct location

* Implement delete album button

* Delete album within album viewer
2022-07-24 22:47:12 -05:00
Alex Tran
9c3f848fa8 Use Webp for album thumbnail 2022-07-24 08:51:00 -05:00
Alex Tran
1ea6425cd1 Handle unhandled promises that lead to unable to login 2022-07-24 08:41:06 -05:00
Alex
052db5d748 Remove/Add asset in ablum on web (#371)
* Added interaction to select multiple thumbnail

* Fixed stutter transition

* Return AlbumResponseDto after removing an asset from album

* Render correctly when an array of thumbnail is updated

* Fixed wording

* Added native dialog for removing users from album

* Fixed rendering incorrect profile image on share user select dialog
2022-07-23 23:23:14 -05:00
bo0tzz
a35460cb84 Bump tfjs version to 3.19.0 for arm64 support (#368)
* Add linux/arm64 to machine-learning container build

* Bump tfjs version to 3.19.0

* Fix tfjs dependency error
2022-07-23 14:15:55 -05:00
Alex
ae93bbe2a7 Docker login only with branch from the repository (#370) 2022-07-23 13:48:53 -05:00
Alex
3b97c7729b Implement mechanism to remove and add shared user in album on web (#369)
* AFixed overlay issue of modal

* Added modal with existing user

* Added custom scrollbar to all pages

* Fixed Document is not define when access document DOM node in browswer

* Added context menu

* Added api to remove user from album

* Handle user leave album

* Added share button to non-shared album

* Added padding to album viewer:

* Fixed margin top of asset selection page

* Fixed issue cannot push to dockerhub
2022-07-23 13:08:49 -05:00
bo0tzz
6021124688 Move docker login step to after build (#367) 2022-07-23 11:05:13 -05:00
Alex
1d34976dd0 Implement album creation on web (#365)
* Added album creation button functionality

* Added input for album title

* Added select photos button

* Added page to select assets

* Show photo selection timeline

* Implemented update album name mechanism:

* Added selection mechanism

* Added selection mechanism with existing assets in album

* Refactored and added comments

* Refactored and added comments - 2

* Refactor album app bar

* Added modal for select user

* Implemented choose users

* Added additional share user button

* Added rule to show add users button
2022-07-22 09:44:22 -05:00
dependabot[bot]
02bde51caf Bump docker/build-push-action from 3.0.0 to 3.1.0 (#363)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.0.0...v3.1.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>
2022-07-20 20:49:11 -05:00
Matthias Rupp
bef1e2e3db Api logout route (#361)
* Add logout route that deletes http only cookies

* Rebuild API
2022-07-19 13:49:58 -05:00
Alex
be3e3e5d7e Added Cookie Authentication (#360)
* Added Cookie Authentication

* Fixed issue with bearer is in lower case

* Fixed bearer to Bearer to conform with standard
2022-07-18 14:14:25 -05:00
Alex
c028c7db4e dev/add detail viewer to album (#358)
* Rename asset viewer folder

* Refactor AssetViewer to be able to user with different component

* Refactor AssetViewer to be able to user with different component

* Added viewer for album and sharing
2022-07-18 00:22:39 -05:00
Alex Tran
c129023821 Remove console.log 2022-07-17 15:10:04 -05:00
Alex Tran
cbdb8fa51f Update get user info controller to avoid conflict with /count 2022-07-17 15:09:26 -05:00
Alex
c6ecfb679a Added sharing page to web (#355)
* Added shared album

* Added list tile

* Show info of shared album owner
2022-07-16 23:52:00 -05:00
Alex
5d03e9bda8 Fix test instance cannot clear database after each test" (#354)
* Update test

* Fixed test cannot initialize database

* Added a separate network to test containers group to run test while in development mode
2022-07-16 23:43:31 -05:00
Alex Tran
d8b26c6da8 Update bug report template 2022-07-16 10:54:00 -05:00
Alex
2e61cf3183 Update README.md
Fixed incorrect info about microservices container
2022-07-16 07:15:22 -05:00
Alex Tran
45e2335b86 Allow manually run test workflow 2022-07-16 00:48:35 -05:00
Alex Tran
2bbc44c5ab Fixed test 2022-07-16 00:45:58 -05:00
Alex Tran
012428416d Remove console.log 2022-07-15 23:27:23 -05:00
Alex
7134f93eb8 Add ablum feature to web (#352)
* Added album page

* Refactor sidebar

* Added album assets count info

* Added album viewer page

* Refactor album sorting

* Fixed incorrectly showing selected asset in album selection

* Improve fetching speed with prefetch

* Refactor to use ImmichThubmnail component for all

* Update to the latest version of Svelte

* Implement fixed app bar in album viewer

* Added shared user avatar

* Correctly get all owned albums, including shared
2022-07-15 23:18:17 -05:00
Jaime Baez
1887b5a860 Add email validation in the API when creating new users (#350)
* Refactor user.service - add user-repository

* Add email validation for creating users
2022-07-15 14:30:56 -05:00
Jaime Baez
ef17668871 Update Spanish translations (#348)
- add missing translations
- remove extra white spaces
- spelling and other corrections
2022-07-14 13:59:07 -05:00
Alex
e9909b179a Up version for release 2022-07-14 11:39:06 -05:00
Alex
09f8bdef6d Up version for release 2022-07-14 11:32:07 -05:00
Alex
2a9b09f359 Added DA,ES,FR,IT (#347)
* Added DA,ES,FR,IT

* Update French translation
2022-07-14 10:20:23 -05:00
Alex
1f6a3ccac7 Added local code in localizely config file 2022-07-14 08:39:43 -05:00
Eidenz
1f40fc1de9 Add missing translation tag for search_no_objects (#344)
* feat(mobile) added french translations

* fix(mobile) added missing translation tag for search_no_objects (EN,DE,FR)

* fix(mobile) renamed search_no_objects to search_page_no_objects
2022-07-13 20:46:28 -05:00
Eidenz
20b94ef0bb feat(mobile) added french translations (#343) 2022-07-13 11:35:02 -05:00
Alex Tran
72c334e5e0 Pump build number 2022-07-13 10:12:03 -05:00
Alex Tran
e7f35822af Pump version number 2022-07-13 10:04:25 -05:00
Alex Tran
bd2152d568 Pump build number 2022-07-13 09:56:34 -05:00
Alex
b1d7ef03e2 Pump version for release (#339)
* Remove unncessesary line

* Pump version for release
2022-07-13 09:51:41 -05:00
Alex Tran
aa74417d11 Fixed web production build 2022-07-13 08:35:52 -05:00
Alex Tran
229b009b7f Remove Axios import in web hook.ts 2022-07-13 08:25:43 -05:00
Fynn Petersen-Frey
bece6253d5 Improve Docker setup and reduce memory usage of production containers (#338) 2022-07-13 07:42:00 -05:00
Alex
ae7e582ec8 Refactor mobile to use OpenApi generated SDK (#336) 2022-07-13 07:23:48 -05:00
Fynn Petersen-Frey
d69470e207 Add extended redis & DB port configuration via environment variables (#330)
* Add database port configuration via env variable

Add redis connection configuration via env variables

* Add redis connection configuration via env variables
2022-07-12 22:21:11 -05:00
Alex
c60e852226 fix 331 (#335)
* fix #331 - Video with no date information in EXIF upload via web caused mobile client not able to render other assets
2022-07-12 16:34:43 -05:00
Zack Pollard
a205478a29 Remove advice regarding running immich-server with scaling (#334) 2022-07-11 11:40:25 -05:00
Alex
22d30522e1 [Localizely] Translations update (#324) 2022-07-10 22:31:29 -05:00
Matthias Rupp
19b1fad274 Add message to login screen (useful for demo instances) (#329)
* Add message for demo instances to login screen

* Rename env variable

* Added key into

* Add styling to conform with Immich color scheme

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2022-07-10 22:31:17 -05:00
Alex
9a6dfacf9b Refactor web to use OpenAPI SDK (#326)
* Refactor main index page

* Refactor admin page

* Refactor Auth endpoint

* Refactor directory to prep for monorepo

* Fixed refactoring path

* Resolved file path in vite

* Refactor photo index page

* Refactor thumbnail

* Fixed test

* Refactor Video Viewer component

* Refactor download file

* Refactor navigation bar

* Refactor upload file check

* Simplify Upload Asset signature

* PR feedback
2022-07-10 21:41:45 -05:00
Alex
7f236c5b18 Add OpenAPI Specs and Response DTOs (#320)
* Added swagger bearer auth method authentication accordingly

* Update Auth endpoint

* Added additional api information for authentication

* Added Swagger CLI pluggin

* Added DTO for /user endpoint

* Added /device-info reponse DTOs

* Implement server version

* Added DTOs for /server-info

* Added DTOs for /assets

* Added album to Swagger group

* Added generated specs file

* Add Client API generator for web

* Remove incorrectly placed node_modules

* Created class to handle access token

* Remove password and hash when getting all user

* PR feedback

* Fixed video from CLI doesn't get metadata extracted

* Fixed issue with TSConfig to work with generated openAPI

* PR feedback

* Remove console.log
2022-07-08 21:26:50 -05:00
Matthias Rupp
25985c732d Merge pull request #323 from alextran1502/fix/localizely_format
Change localizely format to json
2022-07-08 15:56:49 +02:00
Matthias
9ce50b7e3d Change localizely format to json 2022-07-08 15:53:20 +02:00
Matthias Rupp
f5e93a8179 Add translation keys for upload info section (#319) 2022-07-07 17:25:02 -05:00
Matthias Rupp
2b5cef156c Internationalization (German) of the mobile app. (#246)
* Add i18n framework to mobile app and write simple translation generator

* Replace all texts in login_form with i18n keys

* Localization of sharing section

* Localization of asset viewer section

* Use JSON as base translation format

* Add check for missing/unused translation keys

* Add localizely

* Remove i18n directory in favour of localizely

* Backup Translation

* More translations

* Translate home page

* Translation of search page

* Translate new server version announcement

* Reformat code

* Fix typo in german translation

* Update englisch translations

* Change translation keys to match dart filenames

* Add /api to translated endpoint_urls

* Update localizely.yml

* Add languages to ios plist

* Remove unused keys

* Added script to check outdated key in other translations

* Add download key to localizely.yml

Co-authored-by: Alex <alex.tran1502@gmail.com>
2022-07-07 13:40:54 -05:00
Alex
f3032f74a4 Added changelog for Fdroid 2022-07-06 22:35:07 -05:00
Alex
58ec7553ea Add information for uploading asset and error indication with error message for each failed upload. (#315)
* Added info box

* Fixed upload endpoint doesn't report error status code

* Added chip to show update error

* Added chip to show failed upload

* Add duplication check for upload

* Better duplication-checking placement

* Remove check for duplicated asset

* Added failed backup status route

* added page

* Display error card with thumbnail

* Improved styling

* Set thumbnail with better quality

* Remove force upload error
2022-07-06 16:12:55 -05:00
Alex
357f7d1c31 Added schedule job to perform reverse geocoding if key is added after backing up assets (#305) 2022-07-04 15:16:39 -05:00
Zack Pollard
e6d30d72fa Fix typeorm migrations (#297)
* fix: remove config parameter from typeorm cli and update config

the config parameter is no longer supported since version 0.3
the config now needs to export a DataSource object to work with the 0.3 cli

* fix: update all typeorm entities and migrations to be aligned with database structure

* Fixed test-util import databaseConfig

* Fixed column mismatch in raw query with new migration

* Remove dist build directory when starting dev server

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2022-07-04 14:20:43 -05:00
Jaime Baez
355038a91a Use npm ci for installing pacakages (#304) 2022-07-04 13:47:25 -05:00
Alex
97d9b80baa Added creation date for video from ffmpeg.prob (#303) 2022-07-04 13:44:43 -05:00
Alex Tran
b6814fad57 Up version for hotfix 2022-07-03 20:55:30 -05:00
Alex
7586c65103 Fix cannot query shared album on mobile (#298) 2022-07-03 20:52:03 -05:00
Alex
633170d743 Fixed inconnect image grouping with the same date but different year (#296) 2022-07-03 18:00:56 -05:00
Alex Tran
c5be7827c3 Remove 2284 to avoid confusion since 443 is not exposed from internal proxy 2022-07-03 11:37:26 -05:00
Alex Tran
e84c705e31 Added changelog to Fdroid 2022-07-03 10:49:37 -05:00
Alex Tran
36162509e0 Up version for release 2022-07-03 10:39:09 -05:00
Alex
76bf1c0379 Remove thumbnail generation on mobile app (#292)
* Remove thumbnail generation on mobile

* Remove tconditions for missing thumbnail on the backend

* Remove console.log

* Refactor queue systems

* Convert queue and processor name to constant

* Added corresponding interface to job queue
2022-07-02 21:06:36 -05:00
Alex
32b847c26e Fixed event propagation trigger navigating twice (#293) 2022-07-01 20:49:41 -05:00
Alex
a45d6fdf57 Fix server crash on bad file operation and other optimizations (#291)
* Fixed issue with generating thumbnail for video with 0 length cause undefined file and crash the server
* Added all file error handling operation
* Temporarily disabled WebSocket on the web because receiving a new upload event doesn't put the new file in the correct place. 
* Cosmetic fixed on the info panel
2022-07-01 12:00:12 -05:00
Zack Pollard
c071e64a7e infra: switch port to 3003 for machine learning container (#290)
* infra: switch port to 3003 for machine learning container

fixes #289

* Changed port of machine-learning-endpoint to match with new port

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2022-07-01 10:20:04 -05:00
Alex
663f12851e Fixed filename duplication when upload from web (#288)
* Fixed filename duplication when upload from web

* Fixed cosmetic of detail panel view
2022-06-30 20:43:33 -05:00
xpwmaosldk
c4ef523564 Optimize mobile - Avoid creating unnecessary widgets (#268)
* Avoid creating unnecessary widgets

* more flexible null handling and runtime errors prevention
2022-06-30 20:08:49 -05:00
Alex
992f792c0a Fixed admin is forced to change password on mobile app (#287)
* Fixed issues

* Upversion and add changed log
2022-06-30 13:59:02 -05:00
Alex Tran
97611fa057 Fixed issue with unexposed Nginx port on release image 2022-06-30 00:26:54 -05:00
Alex Tran
32240777c3 fixed release build directory for Github action 2022-06-30 00:10:01 -05:00
Alex Tran
6065ff8caa Update readme with new discord invitation link 2022-06-29 23:50:24 -05:00
Alex Tran
8db073941d Up server version for release 2022-06-29 21:54:57 -05:00
Alex
5e281b44e9 Add Podman Support (#278) 2022-06-29 21:49:35 -05:00
Zack Pollard
142ede350e feat: create immich-nginx container to remove default nginx config setup (#280)
* feat: create immich-proxy container to remove default nginx config setup

* infra: make production docker-compose point at release builds for stability

* Fixed nginx config file was overriden by default.conf in nginx container; Fixed docker-compose.dev; Added additional tag 'release' for tagging after release build in Github Action

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2022-06-29 21:24:55 -05:00
Alex
a2e1d4caa2 Update server dependencies and fixed Typeorm API changes in new version (#276)
* Fixed dependencies

* Adapt typeorm API to be compatible with new version

* Fixed typeorm API in tests

* Remove console.log
2022-06-29 13:39:58 -05:00
Alex
5f00d8b9c6 Added mechanism of required password change of new user's first login (#272)
* Deprecate login scenarios that support pre-web era

* refactor and simplify setup

* Added user info to change password form

* change isFistLogin column to shouldChangePassword

* Implemented change user password

* Implement the change password page for mobile

* Change label

* Added changes log and up minor version

* Fixed typo in the release note

* Up server version
2022-06-27 15:13:07 -05:00
bo0tzz
2e85e18020 Use APP_UPLOAD_LOCATION constant for diskInfo (#271) 2022-06-27 09:14:32 -05:00
Alex
40a8115101 Fix backup not resuming after closed and reopen (#266)
* Fixed app not resuming backup after closing and reopening the app

* Fixed cosmetic effect of backup button doesn't change state right away after pressing start backup

* Fixed grammar

* Fixed deep copy problem that cause incorrect asset count when backing up

* Format code
2022-06-25 15:12:47 -05:00
xpwmaosldk
d02b97e1c1 Add service provider (#250)
* optimize android side gradle settings

* android minsdk back to 21

* remove unused package, update linter and fix lint error

* clean code of 'shared module' with offical dart style guide

* restore uploadProfileImage method in UserService

* add service provider

* fix searchFocusNode init error
2022-06-25 13:46:51 -05:00
Alex Tran
485b152beb Improved info panel on web 2022-06-25 13:28:36 -05:00
Jaime Baez
c918f5b001 Set TypeScript to strict mode and fix issues related to server types (#261)
* Fix lint issues and some other TS issues

- set TypeScript in strict mode
- add npm commands to lint / check code
- fix all lint issues
- fix some TS issues
- rename User reponse DTO to make it consistent with the other ones
- override Express/User interface to use UserResponseDto interface
 This is for when the accessing the `user` from a Express Request,
 like in `asset-upload-config`

* Fix the rest of TS issues

- fix all the remaining TypeScript errors
- add missing `@types/mapbox__mapbox-sdk` package

* Move global.d.ts to server `src` folder

* Update AssetReponseDto duration type

This is now of type `string` that defaults to '0:00:00.00000' if not set
which is what the mobile app currently expects

* Set context when logging error in asset.service

Use `ServeFile` as the context for logging an error when
asset.resizePath is not set

* Fix wrong AppController merge conflict resolution

`redirectToWebpage` was removed in main as is no longer used.
2022-06-25 12:53:06 -05:00
Jaime Baez
cca2f7d178 Fix web container port mapping (#264)
Vite uses port 3000 to do Websocket connection. If it doesn't mange to
connect it enters in an endless loop refreshing the page.
2022-06-25 12:30:38 -05:00
Matthias Rupp
baf533de35 Delete assets from server if local deletion fails (#260)
* Delete assets from server if local deletion fails

* Remove commented line
2022-06-24 10:02:09 -05:00
Alex
dfc0d6eee7 Update readme with additional image 2022-06-24 07:28:56 -05:00
Alex Tran
7948cb8110 remove redirect from previous implementation of web routing 2022-06-24 06:33:11 -05:00
Alex
568436f188 Up minor version for release 2022-06-23 22:38:26 -05:00
Alex
04b59318f9 Up patch version 2022-06-23 22:21:02 -05:00
Zack Pollard
1a3d05ffc3 chore: improve default setup (#234)
* chore: remove UPLOAD_LOCATION as it isn't used in the server

* docker: remove network in docker compose as docker creates one by default

* nginx: update reverse proxy to put web at root and api at /api

* docker: remove unneeded exposed ports and docker network

Align dev setup with prod, but with ports exposed for direct connection
Most communication between services happens on the internal network, so we don't need to expose all these services.
With the nginx changes, the api and web panel are both server through the reverse proxy on / for web and /api for the API.
The only service that should expose ports is nginx as that is the entrypoint to the application.

* chore: remove CORS now we serve the api on /api in the default setup

* docs: update README.md to include /api

* Fixed docket-compose file for dev environment and websocket on web and mobile

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2022-06-23 22:18:50 -05:00
Alex
2f2db74d73 Remove expose PostgreSQL port on production docker-compose file 2022-06-23 13:17:31 -05:00
xpwmaosldk
ef097d15dd Clean code of shared folder (#249)
* optimize android side gradle settings

* android minsdk back to 21

* remove unused package, update linter and fix lint error

* clean code of 'shared module' with offical dart style guide

* restore uploadProfileImage method in UserService
2022-06-22 23:14:14 -05:00
xpwmaosldk
caaa474c23 Optimize android's Gradle settings and clean up mobile source code (#240)
* optimize android side gradle settings

* android minsdk back to 21

* remove unused package, update linter and fix lint error
2022-06-22 00:23:35 -05:00
Alex
63bebd92e0 Added image tagging and object detection after generaing jpeg thumbnail 2022-06-21 18:00:30 -05:00
Alex
ad36b8b10f Added f-droid metadata for build 19 2022-06-20 18:51:42 -05:00
Alex
18c22d2a6c Fix #197 app logged off when closed (#239)
* Fixed issue with app logging off after closing

* Change version to reflect minor change
2022-06-20 18:10:23 -05:00
Alex
73024edba9 Update mobile version for CI build 2022-06-20 13:33:25 -05:00
Alex
a360c0a3d7 Update mobile version for CI build 2022-06-20 13:33:19 -05:00
Matthias Rupp
34657f820f Allow zooming in image viewer (#227)
* Allow zooming in image viewer

* Use thumbnailProvider as initial provider

* Set maximum zoom level to 100%

* Implement custom swipe listener in remote_photo_view

* Dart format

* Disable swipe gestures when zoomed in (prevents panning)
2022-06-20 13:29:42 -05:00
Alex Tran
8840911f22 Use polling as primary connection for socket io 2022-06-19 18:21:11 -05:00
Alex Tran
4aa66f4156 Fixed issue socket-io cannot be connected in production build on web 2022-06-19 09:33:10 -05:00
Alex Tran
799a1c99f2 Remove debugging console.log 2022-06-19 09:13:39 -05:00
Alex Tran
c4247bfea3 Fixed issue socket-io cannot be connected in production build on web 2022-06-19 09:12:43 -05:00
Alex
1e3464fe47 Feature - Add upload functionality on Web (#231)
* Added file selector

* Extract metadata to upload files to the web

* Added request for uploading

* Generate jpeg/Webp thumbnail for asset uploaded without thumbnail data

* Added generating thumbnail for video and WebSocket broadcast after thumbnail is generated

* Added video length extraction

* Added Uploading Panel

* Added upload progress store and styling the uploaded asset

* Added condition to only show upload panel when there is upload in progress

* Remove asset from the upload list after successfully uploading

* Added WebSocket to listen to upload event on the web

* Added mechanism to check for existing assets before uploading on the web

* Added test workflow

* Update readme
2022-06-19 08:16:35 -05:00
Alex
b7603fd150 Update mobile changelog 2022-06-18 11:00:35 -05:00
Jaime Baez
517a3363d6 Refactor API for albums feature (#155)
* Rename "shared" to "album"

Prepare moving "SharedAlbums" to "Albums"

* Update server album API endpoints

* Update mobile app album endpoints

Also add `putRequest` to mobile network.service

* Add GET album collection filter

- allow to filter by owner = 'mine' | 'their'
- make sharedWithUserIds no longer required when creating an album

* Rename remaining variables to "album"

* Add ParseMeUUIDPipe to validate uuid or `me`

* Add album params validation

* Update todo in mobile album service.

* Setup e2e testing

* Add user e2e tests

* Rename database host env variable to DB_HOST

* Add some `Album` e2e tests

Also fix issues found with the tests

* Force push (try to recover DB_HOST env)

* Rename db host env variable to `DB_HOSTNAME`

* Remove unnecessary `initDb` from test-utils

The current database.config is running the migrations:
`migrationsRun: true`

* Remove `initDb` usage from album e2e test

* Update GET albums filter to `shared`

- add filter by all / shared / not shared
- add response DTOs
- add GET albums e2e tests

* Update album e2e tests for user.service changes

* Update mobile app to use album response DTOs

* Refactor album-service DB into album-registry

- DB logic refactored into album-repository making it easier to test
- add some album-service unit tests
- add `clearMocks` to jest configuration

* Finish implementing album.service unit tests

* Rename response DTO

Make them consistent with rest of the project naming

* Update debug log messages in mobile network service

* Rename table `shared_albums` to `albums`

* Rename table `asset_shared_album`

* Rename Albums `sharedAssets` to `assets`

* Update tests to match updated "delete" response

* Fixed asset cannot be compared in Set by adding Equatable package

* Remove hero effect to fixed janky animation

Co-authored-by: Alex <alex.tran1502@gmail.com>
2022-06-18 10:56:36 -05:00
Alex
3511b69fc8 Up Minor Version 2022-06-18 09:56:56 -05:00
Zack Pollard
e6efc61b3b fix: out of memory error when uploading large assets on slow internet (#224) 2022-06-18 07:36:58 -05:00
Alex Tran
360c1d9a15 Update Readme 2022-06-14 09:41:06 -05:00
Jaime Baez
e3449f9c8f Fix 500 error on login with email not in DB (#212)
* Fix 500 error on login with email not in DB

* Fix type declarations in ServerInfoDto
2022-06-12 18:29:10 -05:00
Alex
a8e723d722 Fixed ENABLE_MAPBOX value is ignored (#223) 2022-06-12 18:19:53 -05:00
Alex Tran
d116234523 Update Readme with discord tag and new logo panel 2022-06-11 23:42:28 -05:00
Alex
dce2bc7508 Added account info panel with sign out button (#219) 2022-06-11 23:17:20 -05:00
Matthias Rupp
2bf764f560 Input validation for email and server endpoint in mobile app (#211) 2022-06-11 22:12:20 -05:00
Alex Tran
587b77e70b Fixex announcement web not close after acknowledgement 2022-06-11 19:58:16 -05:00
Alex Tran
53cd9fd8bf Fixed Github Aaction build release 2022-06-11 17:47:01 -05:00
Alex
a8220172f8 WIP refactor container and queuing system (#206)
* refactor microservices to machine-learning

* Update tGithub issue template with correct task syntax

* Added microservices container

* Communicate between service based on queue system

* added dependency

* Fixed problem with having to import BullQueue into the individual service

* Added todo

* refactor server into monorepo with microservices

* refactor database and entity to library

* added simple migration

* Move migrations and database config to library

* Migration works in library

* Cosmetic change in logging message

* added user dto

* Fixed issue with testing not able to find the shared library

* Clean up library mapping path

* Added webp generator to microservices

* Update Github Action build latest

* Fixed issue NPM cannot install due to conflict witl Bull Queue

* format project with prettier

* Modified docker-compose file

* Add GH Action for Staging build:

* Fixed GH action job name

* Modified GH Action to only build & push latest when pushing to main

* Added Test 2e2 Github Action

* Added Test 2e2 Github Action

* Implemented microservice to extract exif

* Added cronjob to scan and generate webp thumbnail  at midnight

* Refactor to ireduce hit time to database when running microservices

* Added error handling to asset services that handle read file from disk

* Added video transcoding queue to process one video at a time

* Fixed loading spinner on web while loading covering the info panel

* Add mechanism to show new release announcement to web and mobile app (#209)

* Added changelog page

* Fixed issues based on PR comments

* Fixed issue with video transcoding run on the server

* Change entry point content for backward combatibility when starting up server

* Added announcement box

* Added error handling to failed silently when the app version checking is not able to make the request to GITHUB

* Added new version announcement overlay

* Update message

* Added messages

* Added logic to check and show announcement

* Add method to handle saving new version

* Added button to dimiss the acknowledge message

* Up version for deployment to the app store
2022-06-11 16:12:06 -05:00
Alex
397f8c70b4 Fixed NPM build dependency conflict for server 2022-06-07 08:08:22 -05:00
Matthias Rupp
68ff5377b0 Minor improvements to the detail-panel component (#205)
* Fix roudning behavior in details panel

* Add lat,lon-popup to map in details

* Refactor map code in detail-panel to avoid duplicate code
2022-06-06 16:40:12 -05:00
Jaime Baez
b359dc3cb6 Fix user e2e tests (#194)
* WIP fix user e2e tests

The e2e tests still don't seem to work due to migrations not running.

Changes:
- update user.e2e tests to use new `userService.createUser` method
- fix server `typeorm` command to use ORM config
- update make test-e2e to re-create database volume every time
- add User DTO
- update auth.service and user.service to use User DTO
- update CreateUserDto making optional properties that are optional

* Fix migrations
- add missing `.ts` extension to migrations path
- update user e2e test for the new returned User resource
2022-06-06 11:16:03 -05:00
Zack Pollard
5b036067ed Fix sidebar layout (#204)
* fix: sidebar margins with more than one item incorrect

* fix: api url in sidebar shouldn't overflow the sidebar width
2022-06-05 21:12:12 -05:00
Alex
b9f38162d5 Implemented status box on the side bar (#201) 2022-06-05 05:15:39 -05:00
Alex
ab6909bfbd 20 video conversion for web view (#200)
* Added job for video conversion every 1 minute

* Handle get video as mp4 on the web

* Auto play video on web on hovered

* Added video player

* Added animation and video duration to thumbnail player

* Fixed issue with video not playing on hover

* Added animation when loading thumbnail
2022-06-04 18:34:11 -05:00
Alex
53c3c916a6 View assets detail and download operation (#198)
* Fixed not displaying default user profile picture

* Added buttons to close viewer and micro-interaction for navigating assets left, right

* Add additional buttons to the control bar

* Display EXIF info

* Added map to detail info

* Handle user input keyboard

* Fixed incorrect file name when downloading multiple files

* Implemented download panel
2022-06-03 11:04:30 -05:00
Alex
6924aa5eb1 Update font size of 'create shared album' button to keep the text on one line 2022-05-29 18:15:16 -05:00
Alex
a3b45d62b6 175 Fixed issue back button android return to login page (#193)
* Back button is no longer return to login page

* Update to material 3

* Update to material 3

* Up version for deployment

* Added F-droid changelog
2022-05-29 17:32:30 -05:00
Alex Tran
b34de624ce Added changelog for F-droid 2022-05-29 09:11:22 -05:00
Alex Tran
7886c42742 Update Fastlane iOS build version + speicify database container to restart always 2022-05-29 08:42:27 -05:00
Alex
d476b15312 Implemented user profile upload and show on web/mobile (#191)
* Update mobile dependencies

* Added image picker

* Added mechanism to upload profile image

* Added image type to send to web

* Added styling for circle avatar

* Fixxed issue with sharp cannot resize image properly

* Finished displaying and uploading user profile

* Added user profile to web
2022-05-28 22:35:45 -05:00
Alex Tran
bdf38e7668 Added endpoint for getting user profile image 2022-05-27 22:24:58 -05:00
Alex Tran
e33566a04a Upload profile picture and convert into webp 2022-05-27 22:15:35 -05:00
Alex
c28251b8b4 [WEB] View large images on web (#189)
* Added selection icon to thumbnail

* Added micro-interaction and video file indication

* Added page to add page

* Added image viewer

* navigate assets

* Added separate component for viewing the video file

* Added FFmpeg modules

* Added correct content-type header for serving image file

* Added loading spinner
2022-05-27 14:02:06 -05:00
Alex Tran
337db1c508 fixed typo for bug template 2022-05-26 15:12:08 -05:00
Alex Tran
ad2a1ba901 Update and add issue templates 2022-05-26 15:10:50 -05:00
Alex Tran
fa6f6f8e9f Fixed default DB_HOSTNAME to be the correct database container 2022-05-24 08:49:38 -05:00
Pavle Portic
a44043a4e5 Add ability to pass redis hostname as env var (#174)
* Add ability to pass redis hostname as env var

* Read postgres host from env var in microservices

* Update .env.example with postgres and redis hostname vars
2022-05-23 17:23:02 -05:00
shruuub
87b15c60c0 Fix typos and grammar, plus change Linux to Unix (#180)
Fixed Readme typo
2022-05-23 11:58:00 -05:00
Alex
2c83e52c15 Added dependency in docker-compose (#173)
* Added dependency in docker-compose
* downgrade sharp version to 0.28
2022-05-22 10:15:38 -05:00
Alex
55c5027539 Add webp thumbnail conversion task to optimize performance of fast scrolling (#172)
* Update readme

* Added webp to table and entity

* Added cronjob and sharp dependencies

* Added conversion of webp every 5 minutes and endpoint will now server webp image if exist
2022-05-22 06:56:36 -05:00
Alex
ce06af0c9b Fixed lodash library not invoking in production build (#171)
* Added staging docker-compose file
* Use lodash-es and remove hydration option on photos page fixed the problem
2022-05-22 04:48:38 -05:00
Alex Tran
baaf7ad153 disable hydration 2022-05-21 23:50:54 -05:00
Alex Tran
4a25e7dc22 remove footer to fix error when reloading the page 2022-05-21 23:36:58 -05:00
Alex Tran
f90563d18c not prerender photos page 2022-05-21 23:28:02 -05:00
Alex Tran
8352ecd3b9 Update readme 2022-05-21 18:53:30 -05:00
Alex Tran
69b34a4364 Update readme 2022-05-21 18:49:23 -05:00
Alex
6023c3c624 Show assets on web (#168)
* Implemented lazy loading thumbnail
* Display assets as date-time grouping
* Update Readme
* Modify GitHub action to run from the latest update
2022-05-21 16:50:56 -05:00
Alex Tran
171e7ffa77 Update readme 2022-05-21 08:30:27 -05:00
Alex Tran
d9f918005a Added python3 to prod target of web Dockerfile 2022-05-21 02:34:39 -05:00
Alex Tran
e8ade4866b Added python3 to docker image of web 2022-05-21 02:30:00 -05:00
Alex Tran
bbfa789a4e update readme 2022-05-21 02:25:15 -05:00
Alex
a779c3803c Add web interface with admin functionality (#167) 2022-05-21 02:23:55 -05:00
Jaime Baez
79dea504b0 Add e2e testing setup (#163)
* Setup e2e testing

* Add user e2e tests

* Rename database host env variable to DB_HOST

* Force push (try to recover DB_HOST env)

* Rename db host env variable to `DB_HOSTNAME`

* Remove unnecessary `initDb` from test-utils

The current database.config is running the migrations:
`migrationsRun: true`
2022-05-19 18:30:47 -05:00
Migelo
4900fecd10 fix immich-server service name in README (#166) 2022-05-18 06:26:37 -04:00
Alex
adfaab7eb2 Update to flutter 3 (#162) 2022-05-14 09:25:19 -05:00
Alex
c5adbea6e1 Fixed incorrect microservices URLs after updating dockerfiles (#159) 2022-05-11 06:18:11 -05:00
Alex
bb89fa4aab Modify docker-compose to be compatible with k8s (#149)
* Modify docker-compose file using a hyphen for services instead of underscore

* Change URL in Nginx setting
2022-05-08 07:07:58 -05:00
Alex
43d639104d Bug/fixed permission not requested android 10 (#150)
* Added  android:requestLegacyExternalStorage=true to manifest

* Up pubspec version code for android build
2022-05-08 06:47:38 -05:00
Alex
a1792a7d94 Pump docker-compose container version 2022-05-06 07:47:19 -05:00
Alex
373b6918f8 Feature #120 #89 selective backup in app (#137) 2022-05-06 07:22:23 -05:00
dependabot[bot]
f1396761b0 Bump docker/setup-buildx-action from 1.6.0 to 2.0.0 (#141)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 1.6.0 to 2.0.0.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v1.6.0...v2.0.0)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  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>
2022-05-06 07:21:33 -05:00
dependabot[bot]
335bb0707c Bump docker/build-push-action from 2.10.0 to 3.0.0 (#142)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 2.10.0 to 3.0.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v2.10.0...v3.0.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  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>
2022-05-06 07:21:21 -05:00
dependabot[bot]
7a51e0dd4d Bump docker/login-action from 1 to 2 (#143)
Bumps [docker/login-action](https://github.com/docker/login-action) from 1 to 2.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: docker/login-action
  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>
2022-05-06 07:21:11 -05:00
dependabot[bot]
5b42899dde Bump docker/setup-qemu-action from 1.2.0 to 2.0.0 (#140)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 1.2.0 to 2.0.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v1.2.0...v2.0.0)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  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>
2022-05-06 07:20:50 -05:00
Alex
229357df2b Appbar on homepage is fixed so the cursor won't be overlapping when scrolling 2022-04-30 17:03:45 -05:00
Alex
8d5626620b Refactor homepage widget 2022-04-30 10:55:27 -05:00
Alex
2c4243b3d0 Deploy 1.8.0_12-dev (#132)
* Update 1.8.0_12
* Update readme
2022-04-29 13:10:42 -05:00
Alex
38e0178c81 Implemented editable album title (#130)
* Replace static title text with a text edit field
* Implement endpoint for updating album info
* Implement changing title
* Only the owner can change the title
2022-04-28 23:46:37 -05:00
Alex
c5c7a134dd Update docker-compose file for faster and cleaner build; update ios version for deployment to test flight 2022-04-24 21:43:45 -05:00
Alex
da9eb61532 Implemented remembering login data with radio button (#126) 2022-04-24 21:33:10 -05:00
Alex
c1ccf026f0 Fixed typo in readme 2022-04-23 21:47:53 -05:00
Alex
4309104925 118 - Implement shared album feature (#124)
* New features 
  - Share album. Users can now create albums to share with existing people on the network.
  - Owner can delete the album.
  - Owner can invite the additional users to the album.
  - Shared users and the owner can add additional assets to the album.
* In the asset viewer, the user can swipe up to see detailed information and swip down to dismiss.
* Several UI enhancements.
2022-04-23 21:08:45 -05:00
Alex Tran
a3b84b3ca7 Update readme 2022-04-05 17:29:02 -05:00
Alex Tran
f6630163b1 update readme 2022-04-05 17:27:37 -05:00
Chiogros
aebeb37fb0 Legacy CPUs architecture alternative tip. (#93) 2022-04-05 17:26:42 -05:00
Alex
b74ad69288 Fixed duplicated filename on upload 2022-04-05 14:57:54 -05:00
Alex Tran
b6579cd38e Fixed incorrect image name when push to dockerhub 2022-04-05 11:43:09 -05:00
Alex Tran
46a2032b9a Update release workflow 2022-04-05 11:08:30 -05:00
Alex Tran
0eb548f115 Update readme 2022-04-05 11:04:53 -05:00
887 changed files with 75405 additions and 11682 deletions

1
.github/FUNDING.yml vendored
View File

@@ -1,3 +1,4 @@
# These are supported funding model platforms
github: alextran1502
custom: https://www.buymeacoffee.com/altran1502

View File

@@ -1,15 +1,29 @@
---
name: Bug report
about: Create a report to help us improve
title: "[BUG]"
labels: bug
title: '[BUG] <title>'
labels: bug, need triage
assignees: ''
---
<!--
Note: Please search to see if an issue already exists for the bug you encountered.
-->
**Describe the bug**
A clear and concise description of what the bug is.
**Task List**
*Please complete the task list below. We need this information to help us reproduce the bug or point out problems in your setup. You are not providing enough info may delay our effort to help you.*
- [ ] I have read thoroughly the README setup and installation instructions.
- [ ] I have included my `docker-compose` file.
- [ ] I have included my redacted `.env` file.
- [ ] I have included information on my machine, and environment.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
@@ -23,13 +37,10 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Version [e.g. 22]
**System**
- Phone OS [iOS, Android]: `<version>`
- Server Version: `<version>`
- Mobile App Version: `<version>`
**Additional context**
Add any other context about the problem here.

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1 @@
blank_issues_enabled: false

View File

@@ -0,0 +1,32 @@
name: Feature Request
description: Request a feature that you would like for the app
title: "[Feature]: "
labels: ["feature", "need triage"]
assignees:
- ""
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this feature request!
- type: textarea
id: feature-detail
attributes:
label: Feature detail
placeholder: Describe the feature you would like to see for the app
validations:
required: true
- type: dropdown
id: platform
attributes:
label: Platform
description: Choose the platform for the feature
options:
- Web
- Mobile App
- Server
validations:
required: true

View File

@@ -4,61 +4,117 @@ on:
workflow_dispatch:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build_and_push_server_latest:
# This image include both the server and microservices - the two containers can be slitted into separated
# service with its coressponding entry file.
build_and_push_server_monorepo_latest:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: "main" # branch
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v1.2.0
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1.6.0
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push Immich
uses: docker/build-push-action@v2.10.0
- name: Build and push Immich Mono Repo
uses: docker/build-push-action@v3.1.1
with:
context: ./server
file: ./server/Dockerfile
platforms: linux/arm/v7,linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
push: true
tags: |
altran1502/immich-server:latest
build_and_push_microservice_latest:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: "main" # branch
- name: Set up QEMU
uses: docker/setup-qemu-action@v1.2.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1.6.0
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Microservices
uses: docker/build-push-action@v2.10.0
with:
context: ./microservices
file: ./microservices/Dockerfile
platforms: linux/arm/v7,linux/amd64
push: ${{ github.event_name != 'pull_request' }}
tags: |
altran1502/immich-microservices:latest
build_and_push_machine_learning_latest:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Machine Learning
uses: docker/build-push-action@v3.1.1
with:
context: ./machine-learning
file: ./machine-learning/Dockerfile
platforms: linux/arm/v7,linux/amd64,linux/arm64
push: true
tags: |
altran1502/immich-machine-learning:latest
build_and_push_web_latest:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Web
uses: docker/build-push-action@v3.1.1
with:
context: ./web
file: ./web/Dockerfile
platforms: linux/arm/v7,linux/amd64,linux/arm64
target: prod
push: true
tags: |
altran1502/immich-web:latest
build_and_push_nginx_latest:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Proxy
uses: docker/build-push-action@v3.1.1
with:
context: ./nginx
file: ./nginx/Dockerfile
platforms: linux/arm/v7,linux/amd64,linux/arm64
push: true
tags: |
altran1502/immich-proxy:latest

View File

@@ -0,0 +1,126 @@
name: Build and Push Docker Image - Staging
on:
workflow_dispatch:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
# This image include both the server and microservices - the two containers can be slitted into separated
# service with its coressponding entry file.
build_and_push_server_monorepo_staging:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
if: ${{ github.repository == 'immich-app/immich' }}
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push Immich Mono Repo
uses: docker/build-push-action@v3.1.1
with:
context: ./server
file: ./server/Dockerfile
platforms: linux/arm/v7,linux/amd64,linux/arm64
push: ${{ github.event_name == 'pull_request' && github.repository == 'immich-app/immich' }}
tags: |
altran1502/immich-server:staging
build_and_push_machine_learning_staging:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
if: ${{ github.repository == 'immich-app/immich' }}
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Machine Learning
uses: docker/build-push-action@v3.1.1
with:
context: ./machine-learning
file: ./machine-learning/Dockerfile
platforms: linux/arm/v7,linux/amd64,linux/arm64
push: ${{ github.event_name == 'pull_request' && github.repository == 'immich-app/immich' }}
tags: |
altran1502/immich-machine-learning:staging
build_and_push_web_staging:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
if: ${{ github.repository == 'immich-app/immich' }}
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Web
uses: docker/build-push-action@v3.1.1
with:
context: ./web
file: ./web/Dockerfile
platforms: linux/arm/v7,linux/amd64,linux/arm64
target: prod
push: ${{ github.event_name == 'pull_request' && github.repository == 'immich-app/immich' }}
tags: |
altran1502/immich-web:staging
build_and_push_nginx_staging:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
if: ${{ github.repository == 'immich-app/immich' }}
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Proxy
uses: docker/build-push-action@v3.1.1
with:
context: ./nginx
file: ./nginx/Dockerfile
platforms: linux/arm/v7,linux/amd64,linux/arm64
push: ${{ github.event_name == 'pull_request' && github.repository == 'immich-app/immich' }}
tags: |
altran1502/immich-proxy:staging

View File

@@ -1,4 +1,4 @@
name: Build Server - Release
name: Build and push Docker image - Release
on:
workflow_dispatch:
@@ -6,90 +6,153 @@ on:
types: [published]
jobs:
build_and_push_server_release:
build_and_push_server_monorepo_release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: "main"
ref: "main"
fetch-depth: 0
- name: Docker meta
id: meta
uses: docker/metadata-action@v3
with:
images: altran1502/immich-server
- name: 'Get Previous tag'
- name: "Get Previous tag"
id: previoustag
uses: "WyriHaximus/github-action-get-previous-tag@v1"
with:
fallback: latest
fallback: latest
- name: Set up QEMU
uses: docker/setup-qemu-action@v1.2.0
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1.6.0
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push immich-server release
uses: docker/build-push-action@v2.10.0
uses: docker/build-push-action@v3.1.1
with:
context: ./server
file: ./server/Dockerfile
platforms: linux/arm/v7,linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.previoustag.outputs.tag }}
labels: ${{ steps.meta.outputs.labels }}
tags: |
altran1502/immich-server:${{ steps.previoustag.outputs.tag }}
altran1502/immich-server:release
build_and_push_microservice_release:
build_and_push_machine_learning_release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: "main"
fetch-depth: 0
- name: Docker meta
id: meta
uses: docker/metadata-action@v3
with:
images: altran1502/immich-microservices
- name: 'Get Previous tag'
- name: "Get Previous tag"
id: previoustag
uses: "WyriHaximus/github-action-get-previous-tag@v1"
with:
fallback: latest
fallback: latest
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Machine Learning
uses: docker/build-push-action@v3.1.1
with:
context: ./machine-learning
file: ./machine-learning/Dockerfile
platforms: linux/arm/v7,linux/amd64,linux/arm64
push: true
tags: |
altran1502/immich-machine-learning:${{ steps.previoustag.outputs.tag }}
altran1502/immich-machine-learning:release
build_and_push_web_release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: "main"
fetch-depth: 0
- name: "Get Previous tag"
id: previoustag
uses: "WyriHaximus/github-action-get-previous-tag@v1"
with:
fallback: latest
- name: Set up QEMU
uses: docker/setup-qemu-action@v1.2.0
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1.6.0
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push immich-microservices release
uses: docker/build-push-action@v2.10.0
- name: Build and push immich-web release
uses: docker/build-push-action@v3.1.1
with:
context: ./microservices
file: ./microservices/Dockerfile
platforms: linux/arm/v7,linux/amd64
context: ./web
file: ./web/Dockerfile
platforms: linux/arm/v7,linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.previoustag.outputs.tag }}
labels: ${{ steps.meta.outputs.labels }}
target: prod
tags: |
altran1502/immich-web:${{ steps.previoustag.outputs.tag }}
altran1502/immich-web:release
build_and_push_nginx_release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: "main"
fetch-depth: 0
- name: "Get Previous tag"
id: previoustag
uses: "WyriHaximus/github-action-get-previous-tag@v1"
with:
fallback: latest
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push immich-proxy release
uses: docker/build-push-action@v3.1.1
with:
context: ./nginx
file: ./nginx/Dockerfile
platforms: linux/arm/v7,linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: |
altran1502/immich-proxy:release
altran1502/immich-proxy:${{ steps.previoustag.outputs.tag }}

74
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,74 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '20 13 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript', 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

19
.github/workflows/github-repo-stats.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: github-repo-stats
on:
schedule:
# Run this once per day, towards the end of the day for keeping the most
# recent data point most meaningful (hours are interpreted in UTC).
- cron: "0 23 * * *"
workflow_dispatch: # Allow for running this manually.
jobs:
j1:
name: github-repo-stats
runs-on: ubuntu-latest
steps:
- name: run-ghrs
# Use latest release.
uses: jgehrcke/github-repo-stats@RELEASE
with:
ghtoken: ${{ secrets.GHRS_GITHUB_API_TOKEN }}

41
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Test
on:
workflow_dispatch:
pull_request:
push:
branches: [main]
jobs:
e2e-tests:
name: Run end-to-end test suites
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Run Immich Server 2E2 Test
run: docker-compose -f ./docker/docker-compose.test.yml --env-file ./docker/.env.test up --abort-on-container-exit --exit-code-from immich-server-test
server-unit-tests:
name: Run server unit test suites and checks
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Run tests
run: cd server && npm ci && npm run check:all
web-unit-tests:
name: Run web unit test suites and checks
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Run tests
run: cd web && npm ci && npm run check:all

134
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,134 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation
in our community a harassment-free experience for everyone, regardless
of age, body size, visible or invisible disability, ethnicity, sex
characteristics, gender identity and expression, level of experience,
education, socio-economic status, nationality, personal appearance,
race, religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open,
welcoming, diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for
our community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our
mistakes, and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or
political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in
a professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our
standards of acceptable behavior and will take appropriate and fair
corrective action in response to any behavior that they deem
inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit,
or reject comments, commits, code, wiki edits, issues, and other
contributions that are not aligned to this Code of Conduct, and will
communicate reasons for moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also
applies when an individual is officially representing the community in
public spaces. Examples of representing our community include using an
official e-mail address, posting via an official social media account,
or acting as an appointed representative at an online or offline
event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior
may be reported to the community leaders responsible for enforcement
at our Discord channel. All complaints
will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and
security of the reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in
determining the consequences for any action they deem in violation of
this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior
deemed unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders,
providing clarity around the nature of the violation and an
explanation of why the behavior was inappropriate. A public apology
may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued
behavior. No interaction with the people involved, including
unsolicited interaction with those enforcing the Code of Conduct, for
a specified period of time. This includes avoiding interactions in
community spaces as well as external channels like social
media. Violating these terms may lead to a temporary or permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards,
including sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or
public communication with the community for a specified period of
time. No public or private interaction with the people involved,
including unsolicited interaction with those enforcing the Code of
Conduct, is allowed during this period. Violating these terms may lead
to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of
community standards, including sustained inappropriate behavior,
harassment of an individual, or aggression toward or disparagement of
classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction
within the community.
## Attribution
This Code of Conduct is adapted from the [Contributor
Covenant][homepage], version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of
conduct enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the
FAQ at https://www.contributor-covenant.org/faq. Translations are
available at https://www.contributor-covenant.org/translations.

View File

@@ -1,14 +1,29 @@
dev:
docker-compose -f ./docker/docker-compose.dev.yml up --remove-orphans
rm -rf ./server/dist && docker-compose -f ./docker/docker-compose.dev.yml up --remove-orphans
dev-new:
rm -rf ./server/dist && docker compose -f ./docker/docker-compose.dev.yml up --remove-orphans
dev-update:
docker-compose -f ./docker/docker-compose.dev.yml up --build -V --remove-orphans
rm -rf ./server/dist && docker-compose -f ./docker/docker-compose.dev.yml up --build -V --remove-orphans
dev-scale:
docker-compose -f ./docker/docker-compose.dev.yml up --build -V --scale immich_server=3 --remove-orphans
rm -rf ./server/dist && docker-compose -f ./docker/docker-compose.dev.yml up --build -V --scale immich-server=3 --remove-orphans
stage:
docker-compose -f ./docker/docker-compose.staging.yml up --build -V --remove-orphans
pull-stage:
docker-compose -f ./docker/docker-compose.staging.yml pull
test-e2e:
docker-compose -f ./docker/docker-compose.test.yml --env-file ./docker/.env.test -p immich-test-e2e up --renew-anon-volumes --abort-on-container-exit --exit-code-from immich-server-test --remove-orphans --build
prod:
docker-compose -f ./docker/docker-compose.yml up --build -V --remove-orphans
prod-scale:
docker-compose -f ./docker/docker-compose.yml up --build -V --scale immich_server=3 --scale immich_microservices=3 --remove-orphans
docker-compose -f ./docker/docker-compose.yml up --build -V --scale immich-server=3 --scale immich-microservices=3 --remove-orphans
api:
cd ./server && npm run api:generate

9
NOTES.md Normal file
View File

@@ -0,0 +1,9 @@
# TODO
Server scenario with web
[ ] 1 user exist without admin right -> make admin on first check
[ ] 2 users exist without admin right -> ask user to choose which account will be the admin
[ X ] No users exist -> prompt signup form for Admin

View File

@@ -6,7 +6,7 @@
[ ] Up version in [docker/docker-compose.gpu.yml](/docker/docker-compose.gpu.yml) for `immich_server` service
[ ] Up version in [docker/docker-compose.dev.yml](/docker/docker-compose.gpu.yml) for `immich_server` service
[ ] Up version in [docker/docker-compose.dev.yml](/docker/docker-compose.dev.yml) for `immich_server` service
[ ] Up version in [server/src/constants/server_version.constant.ts](/server/src/constants/server_version.constant.ts)

320
README.md
View File

@@ -1,3 +1,9 @@
<h1 align="center"> Immich </h1>
<p align="center"> <b>High performance self-hosted photo and video backup solution.</b> </p>
<p align="center">
<img src="design/feature-panel.png" title="Immich Logo">
</p>
<p align="center">
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-green.svg?color=3F51B5&style=for-the-badge&label=License&logoColor=000000&labelColor=ececec" alt="License: MIT"></a>
<a href="https://github.com/alextran1502/immich"><img src="https://img.shields.io/github/stars/alextran1502/immich.svg?style=for-the-badge&logo=github&color=3F51B5&label=Stars&logoColor=000000&labelColor=ececec" alt="Star on Github"></a>
@@ -8,141 +14,259 @@
<img src="https://img.shields.io/teamcity/http/immichci.little-home.net/s/Immich_BuildAndPublishIOSToTestFlight.svg?style=for-the-badge&label=iOS&logo=teamcity&logoColor=000000&labelColor=ececec" alt="iOS Build"/>
</a>
<a href="https://actions-badge.atrox.dev/alextran1502/immich/goto?ref=main">
<img alt="Build Status" src="https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Falextran1502%2Fimmich%2Fbadge%3Fref%3Dmain&style=for-the-badge&label=Server Docker&logo=docker&labelColor=ececec" />
<img alt="Build Status" src="https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Falextran1502%2Fimmich%2Fbadge%3Fref%3Dmain&style=for-the-badge&label=Github Action&logo=github&labelColor=ececec&logoColor=000000" />
</a>
<a href="https://discord.gg/D8JsnBEuKb">
<img src="https://img.shields.io/discord/979116623879368755.svg?label=Immich%20Discord&logo=Discord&style=for-the-badge&logoColor=000000&labelColor=ececec" atl="Immich Discord"/>
</a>
<br/>
<br/>
<br/>
<br/>
<p align="center">
<img src="design/immich-logo.svg" width="200" title="Immich Logo">
</p>
<br/>
</p>
# Immich
## Demo
Self-hosted photo and video backup solution directly from your mobile phone.
You can access the web demo at https://demo.immich.app
![](https://media.giphy.com/media/y8ZeaAigGmNvlSoKhU/giphy.gif)
For the mobile app, you can use https://demo.immich.app/api for the `Server Endpoint URL`
Loading ~4000 images/videos
## Screenshots
```
The credential
email: demo@immich.app
password: demo
```
<p align="left">
<img src="design/nsc1.png" width="150" title="Login With Custom URL">
<img src="design/nsc2.png" width="150" title="Backup Setting Info">
<img src="design/nsc3.png" width="150" title="Multiple select">
<img src="design/nsc4.jpeg" width="150" title="Curated Search Info">
<img src="design/nsc6.png" width="150" title="EXIF Info">
```
Spec: Free-tier Oracle VM - Amsterdam - 2.4Ghz quad-core ARM64 CPU, 24GB RAM
```
## Content
- [Features](#features)
- [Screenshots](#screenshots)
- [Installation](#installation)
- [Update](#update)
- [Mobile App](#mobile-app)
- [App Beta Invitation links](#App-Beta-release-channel)
- [Development](#development)
- [Support](#support)
- [Known Issues](#known-issues)
# Features
> ⚠️ WARNING: **NOT READY FOR PRODUCTION! DO NOT USE TO STORE YOUR ASSETS**. This project is under heavy development, there will be continuous functions, features and api changes.
| Features | Mobile | Web |
| - | - | - |
| Upload and view videos and photos | Yes | Yes
| Auto backup when the app is opened | Yes | N/A
| Selective album(s) for backup | Yes | N/A
| Download photos and videos to local device | Yes | Yes
| Multi-user support | Yes | Yes
| Album | Yes | Yes
| Shared Albums | Yes | Yes
| Quick navigation with draggable scrollbar | Yes | Yes
| Support RAW (HEIC, HEIF, DNG, Apple ProRaw) | Yes | Yes
| Metadata view (EXIF, map) | Yes | Yes
| Search by metadata, objects and image tags | Yes | No
| Administrative functions (user management) | N/A | Yes
| Background backup | Android | N/A
| Virtual scroll | N/A | Yes
<br/>
# Screenshots
### Mobile
| | | | | |
| - | - | - | - | - |
| <img src="design/login-screen.png" width="150" title="Login With Custom URL"> <p align="center"> Login with custom URL </p> | <img src="design/backup-screen.png" width="150" title="Backup Setting Info"> <p align="center"> Backup Settings </p> | <img src="design/selective-backup-screen.png" width="150" title="Backup Setting Info"> <p align="center"> Backup selection </p> | <img src="design/home-screen.jpeg" width="150" title="Home Screen"> <p align="center"> Home Screen </p> | <img src="design/search-screen.jpeg" width="150" title="Curated Search Info"> <p align="center"> Curated search </p> |
| <img src="design/shared-albums.png" width="150" title="Shared Albums"> <p align="center"> Shared albums </p> | <img src="design/nsc6.png" width="150" title="EXIF Info"> <p align="center"> EXIF info </p> | <img src="https://media.giphy.com/media/y8ZeaAigGmNvlSoKhU/giphy.gif" width="150" title="Loading ~4000 images/videos"> <p align="center"> Loading ~4000 images/videos </p> |
### Web
| Home Dashboard | Image view |
| - | - |
|<img src="design/web-home.jpeg" width="100%" title="Home Dashboard"> | <img src="design/web-detail.jpeg" width="100%" title="Detail">|
<br/>
# Project Details
## 💾 System Requirements
- **OS**: Preferred unix-based operating system (Ubuntu, Debian, MacOS...etc).
- **RAM**: At least 2GB, preferred 4GB.
- **Core**: At least 2 cores, preferred 4 cores.
## 🔩 Technology Stack
There are several services that compose Immich:
1. **NestJs** - Backend of the application
2. **SvelteKit** - Web frontend of the application
3. **PostgreSQL** - Main database of the application
4. **Redis** - For sharing websocket instance between docker instances and background tasks message queue.
5. **Nginx** - Load balancing and optimized file uploading.
6. **TensorFlow** - Object Detection (COCO SSD) and Image Classification (ImageNet).
<br/>
# Installation
NOTE: When using a reverse proxy in front of Immich (such as NGINX), the reverse proxy might require extra configuration to allow large files to be uploaded (such as client_max_body_size in the case of NGINX).
## Testing One-step installation (not recommended for production)
> ⚠️ *This installation method is for evaluating Immich before futher customization to meet the users' needs.*
*Applicable system: Ubuntu, Debian, MacOS*
- In the shell, from the directory of your choice, run the following command:
```bash
curl -o- https://raw.githubusercontent.com/immich-app/immich/main/install.sh | bash
```
This script will download the `docker-compose.yml` file and the `.env` file, then populate the necessary information, and finally run the `docker-compose up` or `docker compose up` (based on your docker's version) command.
The web application will be available at `http://<machine-ip-address>:2283`, and the server URL for the mobile app will be `http://<machine-ip-address>:2283/api`.
The directory which is used to store the backup file is `./immich-app/immich-data`.
<br/>
## Custom installation (Recommended)
### Step 1 - Download necessary files
- Create a directory called `immich-app` and cd into it.
- Get `docker-compose.yml`
```bash
wget https://raw.githubusercontent.com/immich-app/immich/main/docker/docker-compose.yml
```
- Get `.env`
```bash
wget -O .env https://raw.githubusercontent.com/immich-app/immich/main/docker/.env.example
```
### Step 2 - Populate .env file with custom information
<a href="https://github.com/immich-app/immich/blob/main/docker/.env.example" target="_blank"><b>See the example <code>.env</code> file</b></a>
* Populate custom database information if necessary.
* Populate `UPLOAD_LOCATION` as prefered location for storing backup assets.
* Populate a secret value for `JWT_SECRET`, you can use this command: `openssl rand -base64 128`
### Step 3 - Start the containers
- Run `docker-compose up` or `docker compose up` (based on your docker's version)
### Step 4 - Register admin user
- Navigate to the web at `http://<machine-ip-address>:2283` and follow the prompts to register admin user.
<p align="center">
<img src="design/admin-registration-form.png" width="300" title="Admin Registration">
</p>
# Note
- You can add and manage users from the administration page.
<p align="center">
<img src="design/admin-interface.png" width="500" title="Admin User Management">
</p>
**!! NOT READY FOR PRODUCTION! DO NOT USE TO STORE YOUR ASSETS !!**
### Step 5 - Access the mobile app
This project is under heavy development, there will be continous functions, features and api changes.
- Login the mobile app with the server endpoint URL at `http://<machine-ip-address>:2283/api`
<p align="center">
<img src="design/login-screen.jpeg" width="250" title="Example login screen">
</p>
# Features
<br/>
- Upload and view assets(videos/images).
- Multi-user supported.
- Quick navigation with drag scroll bar.
- Auto Backup.
- Support HEIC/HEIF Backup.
- Extract and display EXIF info.
- Real-time render from multi-device upload event.
- Image Tagging/Classification based on ImageNet dataset
- Object detection based on COCO SSD.
- Search assets based on tags and exif data (lens, make, model, orientation)
- Upload assets from your local computer/server using [immich cli tools](https://www.npmjs.com/package/immich)
- [Optional] Reverse geocoding using Mapbox (Generous free-tier of 100,000 search/month)
- Show asset's location information on map (OpenStreetMap).
- Show curated places on the search page
- Show curated objects on the search page
## Update
If you have installed, you can update the application by navigate to the directory that contains the `docker-compose.yml` file and run the following command:
```bash
docker-compose pull && docker-compose up -d
```
# Mobile app
| F-Droid | Google Play | iOS |
| - | - | - |
| <a href="https://f-droid.org/packages/app.alextran.immich"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" alt="Get it on F-Droid" height="80"></a> | <p align="left"> <a href="https://play.google.com/store/apps/details?id=app.alextran.immich"><img src="design/google-play-qr-code.png" width="200" title="Google Play Store"></a> <p/> | <p align="left"> <a href="https://apps.apple.com/us/app/immich/id1613945652"><img src="design/ios-qr-code.png" width="200" title="Apple App Store"></a> <p/> |
> *The Play/App Store version might be lagging behind the latest release due to the review process.*
# App Beta release channel
You can opt-in to join app beta release channel by following the links below:
* Android: Invitation link from [web](https://play.google.com/store/apps/details?id=app.alextran.immich) or from [mobile](https://play.google.com/store/apps/details?id=app.alextran.immich)
* iOS: [TestFlight invitation link](https://testflight.apple.com/join/1vYsAa8P)
<br/>
# Development
You can use docker compose for development, there are several services that compose Immich
1. NestJs
2. PostgreSQL
3. Redis
4. Nginx
5. TensorFlow
## Populate .env file
Navigate to `docker` directory and run
```
cp .env.example .env
```
Then populate the value in there.
Notice that if set `ENABLE_MAPBOX` to `true`, you will have to provide `MAPBOX_KEY` for the server to run.
Pay attention to the key `UPLOAD_LOCATION`, this directory must exist and is owned by the user that run the `docker-compose` command below.
To start, run
The development environment can be started from the root of the project after populating the `.env` file with the command:
```bash
docker-compose -f ./docker/docker-compose.yml up --build -V
```
make dev # required Makefile installed on the system.
```
The server will be running at `http://your-ip:2283` through `Nginx`
All servers and web container are hot reload for quick feedback loop.
## Register User
Use the command below on your terminal to create user as we don't have user interface for this function yet.
## Note for developers
### 1 - OpenAPI
OpenAPI is used to generate the client (Typescript, Dart) SDK. `openapi-generator-cli` can be installed [here](https://openapi-generator.tech/docs/installation/). When you add a new or modify an existing endpoint, you must run the generate command below to update the client SDK.
```bash
curl --location --request POST 'http://your-server-ip:2283/auth/signUp' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "testuser@email.com",
"password": "password"
}'
npm run api:generate # Run from server directory
```
You can find the generated client SDK in the [`web/src/api`](web/src/api) for Typescript SDK and [`mobile/openapi`](mobile/openapi) for Dart SDK.
## Run mobile app
### Android
Download `apk` in release tab and run on your phone. You can follow this guide on how to do that
- [Run APK on Android](https://www.lifewire.com/install-apk-on-android-4177185)
### iOS
You can download the app from Apple AppStore [here](https://apps.apple.com/us/app/immich/id1613945652):
<p align="left">
<img src="design/ios-qr-code.png" width="250" title="Apple App Store">
<p/>
<br/>
# Support
If you like the app, find it helpful, and want to support me to offset the cost of publishing to AppStores, you can sponsor the project with [**Github Sponsore**](https://github.com/sponsors/alextran1502).
If you like the app, find it helpful, and want to support me to offset the cost of publishing to AppStores, you can sponsor the project with [**one time**](https://github.com/sponsors/alextran1502?frequency=one-time&sponsor=alextran1502) or monthly donation from [**Github Sponsor**](https://github.com/sponsors/alextran1502).
This is also a meaningful way to give me motivation and encounragment to continue working on the app.
You can also donate using crypto currency with the following addresses:
Cheer! 🎉
<p align="" style="display: flex; place-items: center; gap: 15px" title="Bitcoin(BTC)"><img src="design/bitcoin.png" width="25" title="Bitcoin"> <b>Bitcoin</b>: <code>1FvEp6P6NM8EZEkpGUFAN2LqJ1gxusNxZX</code></p>
# Known Issue
<p align="" style="display: flex; place-items: center; gap: 15px" title="Cardano(ADA)"> <img src="design/cardano.png" width="30" title="Cardano"> <b>Cardano</b>: <code>addr1qyy567vqhqrr3p7vpszr5p264gw89sqcwts2z8wqy4yek87cdmy79zazyjp7tmwhkluhk3krvslkzfvg0h43tytp3f5q49nycc</code> </p>
TensorFlow doesn't run with older CPU architecture, it requires CPU with AVX and AVX2 instruction set. If you encounter the error `illegal instruction core dump` when running the docker-compose command above, check for your CPU flags with the command and make sure you see `AVX` and `AVX2`. Otherwise, switch to a different VM/desktop with different architecture.
This is also a meaningful way to give me motivation and encouragement to continue working on the app.
Cheers! 🎉
<br/>
# Known Issues
## TensorFlow Build Issue
*This is a known issue for incorrect Proxmox setup*
TensorFlow doesn't run with older CPU architecture, it requires a CPU with AVX and AVX2 instruction set. If you encounter the error `illegal instruction core dump` when running the docker-compose command above, check for your CPU flags with the command and make sure you see `AVX` and `AVX2`:
```bash
more /proc/cpuinfo | grep flags
```
If you are running virtualization in Promox, the VM doesn't have the flag enable.
```
If you are running virtualization in Proxmox, the VM doesn't have the flag enabled.
You need to change the CPU type from `kvm64` to `host` under VMs hardware tab.
`Hardware > Processors > Edit > Advanced > Type (dropdown menu) > host`

5
SECURITY.md Normal file
View File

@@ -0,0 +1,5 @@
# Security Policy
## Reporting a Vulnerability
Please report security issues to `alex.tran1502@gmail.com`

BIN
design/admin-interface.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

BIN
design/backup-screen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

BIN
design/bitcoin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
design/cardano.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
design/feature-panel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

BIN
design/home-screen.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

BIN
design/login-screen.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
design/login-screen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 303 KiB

BIN
design/search-screen.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 KiB

BIN
design/shared-albums.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

BIN
design/web-admin.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
design/web-detail.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

BIN
design/web-home.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

32
dev-setup.md Normal file
View File

@@ -0,0 +1,32 @@
# Development Setup
## Lint / format extensions
Setting these in the IDE give a better developer experience auto-formatting code on save and providing instant feedback on lint issues.
### VSCode
Install Prettier, ESLint and Svelte extensions.
in User `settings.json` (`cmd + shift + p` and search for Open User Settings JSON) add the following:
```json
{
"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"]
}
```
## Running tests / checks
In both server and web:
`npm run check:all`

View File

@@ -1,15 +1,66 @@
###################################################################################
# Database
###################################################################################
DB_HOSTNAME=immich_postgres
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_DATABASE_NAME=
DB_DATABASE_NAME=immich
# Optional Database settings:
# DB_PORT=5432
###################################################################################
# Redis
###################################################################################
REDIS_HOSTNAME=immich_redis
# Optional Redis settings:
# REDIS_PORT=6379
# REDIS_DBINDEX=0
# REDIS_PASSWORD=
# REDIS_SOCKET=
###################################################################################
# Upload File Config
###################################################################################
UPLOAD_LOCATION=absolute_location_on_your_machine_where_you_want_to_store_the_backup
# JWT SECRET
JWT_SECRET=
###################################################################################
# Log message level - [simple|verbose]
###################################################################################
# MAPBOX
## ENABLE_MAPBOX is either true of false -> if true, you have to provide MAPBOX_KEY
ENABLE_MAPBOX=
MAPBOX_KEY=
LOG_LEVEL=simple
###################################################################################
# JWT SECRET
###################################################################################
JWT_SECRET=randomstringthatissolongandpowerfulthatnoonecanguess
###################################################################################
# Reverse Geocoding
####################################################################################
# DISABLE_REVERSE_GEOCODING=false
# Reverse geocoding is done locally which has a small impact on memory usage
# This memory usage can be altered by changing the REVERSE_GEOCODING_PRECISION variable
# This ranges from 0-3 with 3 being the most precise
# 3 - Cities > 500 population: ~200MB RAM
# 2 - Cities > 1000 population: ~150MB RAM
# 1 - Cities > 5000 population: ~80MB RAM
# 0 - Cities > 15000 population: ~40MB RAM
# REVERSE_GEOCODING_PRECISION=3
####################################################################################
# WEB - Optional
####################################################################################
# Custom message on the login page, should be written in HTML form.
# For example PUBLIC_LOGIN_PAGE_MESSAGE="This is a demo instance of Immich.<br><br>Email: <i>demo@demo.de</i><br>Password: <i>demo</i>"
PUBLIC_LOGIN_PAGE_MESSAGE=

22
docker/.env.test Normal file
View File

@@ -0,0 +1,22 @@
# Database
DB_HOSTNAME=immich-database-test
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_DATABASE_NAME=e2e_test
# Redis
REDIS_HOSTNAME=immich_redis_test
# Upload File Config
UPLOAD_LOCATION=./upload
# JWT SECRET
JWT_SECRET=randomstringthatissolongandpowerfulthatnoonecanguess
# MAPBOX
## ENABLE_MAPBOX is either true of false -> if true, you have to provide MAPBOX_KEY
ENABLE_MAPBOX=false
# WEB
MAPBOX_KEY=
VITE_SERVER_ENDPOINT=http://localhost:2283/api

View File

@@ -1,14 +1,13 @@
version: "3.8"
services:
immich_server:
image: immich-server-dev:1.6.0
immich-server:
image: immich-server-dev:latest
build:
context: ../server
dockerfile: Dockerfile
command: npm run start:dev
expose:
- "3000"
target: builder
command: npm run start:dev immich
volumes:
- ../server:/usr/src/app
- ${UPLOAD_LOCATION}:/usr/src/app/upload
@@ -20,19 +19,16 @@ services:
depends_on:
- redis
- database
networks:
- immich_network
immich_microservices:
image: immich-microservices-dev:1.6.0
immich-machine-learning:
image: immich-machine-learning-dev:latest
build:
context: ../microservices
context: ../machine-learning
dockerfile: Dockerfile
target: builder
command: npm run start:dev
expose:
- "3001"
volumes:
- ../microservices:/usr/src/app
- ../machine-learning:/usr/src/app
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- /usr/src/app/node_modules
env_file:
@@ -41,15 +37,48 @@ services:
- NODE_ENV=development
depends_on:
- database
networks:
- immich_network
immich-microservices:
image: immich-microservices:latest
build:
context: ../server
dockerfile: Dockerfile
target: builder
command: npm run start:dev microservices
volumes:
- ../server:/usr/src/app
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- /usr/src/app/node_modules
env_file:
- .env
environment:
- NODE_ENV=development
depends_on:
- database
- immich-server
immich-web:
image: immich-web-dev:1.9.0
build:
context: ../web
dockerfile: Dockerfile
target: dev
command: npm run dev --host
env_file:
- .env
ports:
- 3000:3000
- 24678:24678
volumes:
- ../web:/usr/src/app
- /usr/src/app/node_modules
restart: always
depends_on:
- immich-server
redis:
container_name: immich_redis
image: redis:6.2
networks:
- immich_network
database:
container_name: immich_postgres
@@ -65,25 +94,20 @@ services:
- pgdata:/var/lib/postgresql/data
ports:
- 5432:5432
networks:
- immich_network
nginx:
container_name: proxy_nginx
image: nginx:latest
volumes:
- ./settings/nginx-conf:/etc/nginx/conf.d
immich-proxy:
container_name: immich_proxy
image: immich-proxy-dev:latest
build:
context: ../nginx
dockerfile: Dockerfile
ports:
- 2283:80
- 2284:443
- 2283:8080
logging:
driver: none
networks:
- immich_network
depends_on:
- immich_server
- immich-server
restart: always
networks:
immich_network:
volumes:
pgdata:

View File

@@ -1,92 +0,0 @@
version: "3.8"
services:
immich_server:
image: immich-server-dev:1.6.0
build:
context: ../server
dockerfile: Dockerfile
command: npm run start:dev
expose:
- "3000"
volumes:
- ../server:/usr/src/app
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- /usr/src/app/node_modules
env_file:
- .env
depends_on:
- redis
- database
networks:
- immich_network
immich_microservices:
image: immich-microservices-dev:1.6.0
build:
context: ../microservices
dockerfile: Dockerfile
command: npm run start:dev
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [ gpu ]
expose:
- "3001"
volumes:
- ../microservices:/usr/src/app
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- /usr/src/app/node_modules
env_file:
- .env
depends_on:
- database
- immich_server
networks:
- immich_network
redis:
container_name: immich_redis
image: redis:6.2
networks:
- immich_network
database:
container_name: immich_postgres
image: postgres:14
env_file:
- .env
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
PG_DATA: /var/lib/postgresql/data
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- 5432:5432
networks:
- immich_network
nginx:
container_name: proxy_nginx
image: nginx:latest
volumes:
- ./settings/nginx-conf:/etc/nginx/conf.d
ports:
- 2283:80
- 2284:443
logging:
driver: none
networks:
- immich_network
depends_on:
- immich_server
networks:
immich_network:
volumes:
pgdata:

View File

@@ -0,0 +1,83 @@
version: "3.8"
services:
immich-server:
image: altran1502/immich-server:staging
entrypoint: ["/bin/sh", "./start-server.sh"]
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
env_file:
- .env
environment:
- NODE_ENV=production
depends_on:
- redis
- database
restart: always
immich-microservices:
image: altran1502/immich-server:staging
entrypoint: ["/bin/sh", "./start-microservices.sh"]
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
env_file:
- .env
environment:
- NODE_ENV=production
depends_on:
- redis
- database
restart: always
immich-machine-learning:
image: altran1502/immich-machine-learning:staging
entrypoint: ["/bin/sh", "./entrypoint.sh"]
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
env_file:
- .env
environment:
- NODE_ENV=production
depends_on:
- database
restart: always
immich-web:
image: altran1502/immich-web:staging
entrypoint: ["/bin/sh", "./entrypoint.sh"]
env_file:
- .env
restart: always
redis:
container_name: immich_redis
image: redis:6.2
restart: always
database:
container_name: immich_postgres
image: postgres:14
env_file:
- .env
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
PG_DATA: /var/lib/postgresql/data
volumes:
- pgdata:/var/lib/postgresql/data
restart: always
immich-proxy:
container_name: immich_proxy
image: altran1502/immich-proxy:staging
ports:
- 2283:8080
logging:
driver: none
depends_on:
- immich-server
restart: always
volumes:
pgdata:

View File

@@ -0,0 +1,46 @@
version: "3.8"
services:
immich-server-test:
image: immich-server-test
build:
context: ../server
dockerfile: Dockerfile
target: builder
command: npm run test:e2e
expose:
- "3000"
volumes:
- ../server:/usr/src/app
- /usr/src/app/node_modules
env_file:
- .env.test
environment:
- NODE_ENV=development
depends_on:
- immich-redis-test
- immich-database-test
networks:
- immich-test-network
immich-redis-test:
container_name: immich-redis-test
image: redis:6.2
networks:
- immich-test-network
immich-database-test:
container_name: immich-database-test
image: postgres:14
env_file:
- .env.test
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
PG_DATA: /var/lib/postgresql/data
volumes:
- /var/lib/postgresql/data
networks:
- immich-test-network
networks:
immich-test-network:

View File

@@ -1,14 +1,9 @@
version: "3.8"
services:
immich_server:
image: immich-server:1.6.0
build:
context: ../server
dockerfile: Dockerfile
entrypoint: ["/bin/sh", "./entrypoint.sh"]
expose:
- "3000"
immich-server:
image: altran1502/immich-server:release
entrypoint: ["/bin/sh", "./start-server.sh"]
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
env_file:
@@ -18,18 +13,25 @@ services:
depends_on:
- redis
- database
networks:
- immich_network
restart: unless-stopped
restart: always
immich_microservices:
image: immich-microservices:1.6.0
build:
context: ../microservices
dockerfile: Dockerfile
immich-microservices:
image: altran1502/immich-server:release
entrypoint: ["/bin/sh", "./start-microservices.sh"]
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
env_file:
- .env
environment:
- NODE_ENV=production
depends_on:
- redis
- database
restart: always
immich-machine-learning:
image: altran1502/immich-machine-learning:release
entrypoint: ["/bin/sh", "./entrypoint.sh"]
expose:
- "3001"
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
env_file:
@@ -38,15 +40,19 @@ services:
- NODE_ENV=production
depends_on:
- database
networks:
- immich_network
restart: unless-stopped
restart: always
immich-web:
image: altran1502/immich-web:release
entrypoint: ["/bin/sh", "./entrypoint.sh"]
env_file:
- .env
restart: always
redis:
container_name: immich_redis
image: redis:6.2
networks:
- immich_network
restart: always
database:
container_name: immich_postgres
@@ -60,27 +66,18 @@ services:
PG_DATA: /var/lib/postgresql/data
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- 5432:5432
networks:
- immich_network
restart: always
nginx:
container_name: proxy_nginx
image: nginx:latest
volumes:
- ./settings/nginx-conf:/etc/nginx/conf.d
immich-proxy:
container_name: immich_proxy
image: altran1502/immich-proxy:release
ports:
- 2283:80
- 2284:443
- 2283:8080
logging:
driver: none
networks:
- immich_network
depends_on:
- immich_server
- immich-server
restart: always
networks:
immich_network:
volumes:
pgdata:
pgdata:

View File

@@ -1,35 +0,0 @@
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# events {
# worker_connections 1000;
# }
server {
client_max_body_size 50000M;
listen 80;
access_log off;
location / {
proxy_buffering off;
proxy_buffer_size 16k;
proxy_busy_buffers_size 24k;
proxy_buffers 64 4k;
proxy_force_ranges on;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_pass http://immich_server:3000;
}
}

91
install.sh Executable file
View File

@@ -0,0 +1,91 @@
echo "Starting Immich installation..."
ip_address=$(hostname -I | awk '{print $1}')
release_version=$(curl --silent "https://api.github.com/repos/immich-app/immich/releases/latest" |
grep '"tag_name":' |
sed -E 's/.*"([^"]+)".*/\1/')
RED='\033[0;31m'
GREEN='\032[0;31m'
NC='\033[0m' # No Color
get_release_version() {
curl --silent "https://api.github.com/repos/immich-app/immich/releases/latest" | # Get latest release from GitHub api
grep '"tag_name":' | # Get tag line
sed -E 's/.*"([^"]+)".*/\1/' # Pluck JSON value
}
create_immich_directory() {
echo "Creating Immich directory..."
mkdir -p ./immich-app/immich-data
}
download_docker_compose_file() {
echo "Downloading docker-compose.yml..."
curl -L https://raw.githubusercontent.com/immich-app/immich/$release_version/docker/docker-compose.yml -o ./immich-app/docker-compose.yml >/dev/null 2>&1
}
download_dot_env_file() {
echo "Downloading .env file..."
curl -L https://raw.githubusercontent.com/immich-app/immich/$release_version/docker/.env.example -o ./immich-app/.env >/dev/null 2>&1
}
populate_upload_location() {
echo "Populating default UPLOAD_LOCATION value..."
cd ./immich-app/immich-data
upload_location=$(pwd)
# Replace value of UPLOAD_LOCATION in .env with upload_location path
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' "s|UPLOAD_LOCATION=.*|UPLOAD_LOCATION=$upload_location|" ../.env
else
sed -i "s|UPLOAD_LOCATION=.*|UPLOAD_LOCATION=$upload_location|" ../.env
fi
cd ..
}
start_docker_compose() {
echo "Starting Immich's docker containers"
if docker compose &>/dev/null; then
docker_bin="docker compose"
elif docker-compose &>/dev/null; then
docker_bin="docker-compose"
else
echo 'Cannot find `docker compose` or `docker-compose`.'
exit 1
fi
if $docker_bin up --remove-orphans -d; then
show_friendly_message
exit 0
else
echo "Could not start. Check for errors above."
exit 1
fi
}
show_friendly_message() {
echo "Succesfully deployed Immich!"
echo "You can access the website at http://$ip_address:2283 and the server URL for the mobile app is http://$ip_address:2283/api"
echo "The backup (or upload) location is $upload_location"
echo "---------------------------------------------------"
echo "If you want to configure custom information of the server, including the database, Redis information, or the backup (or upload) location, etc.
1. First bring down the containers with the command 'docker-compose down' in the immich-app directory,
2. Then change the information that fits your needs in the '.env' file,
3. Finally, bring the containers back up with the command 'docker-compose up --remove-orphans -d' in the immich-app directory"
}
# MAIN
create_immich_directory
download_docker_compose_file
download_dot_env_file
populate_upload_location
start_docker_compose

35
localizely.yml Normal file
View File

@@ -0,0 +1,35 @@
config_version: 1.0
project_id: ead34689-ec52-41d9-b675-09bc85a6cbd7
file_type: json
upload:
files:
- file: mobile/assets/i18n/en-US.json
locale_code: en-US
- file: mobile/assets/i18n/de-DE.json
locale_code: de-DE
- file: mobile/assets/i18n/fr-FR.json
locale_code: fr-FR
- file: mobile/assets/i18n/it-IT.json
locale_code: it-IT
- file: mobile/assets/i18n/nl-NL.json
locale_code: nl-NL
- file: mobile/assets/i18n/ko-KR.json
locale_code: ko-KR
- file: mobile/assets/i18n/da-DK.json
locale_code: da-DK
download:
files:
- file: mobile/assets/i18n/en-US.json
locale_code: en-US
- file: mobile/assets/i18n/de-DE.json
locale_code: de-DE
- file: mobile/assets/i18n/fr-FR.json
locale_code: fr-FR
- file: mobile/assets/i18n/it-IT.json
locale_code: it-IT
- file: mobile/assets/i18n/nl-NL.json
locale_code: nl-NL
- file: mobile/assets/i18n/ko-KR.json
locale_code: ko-KR
- file: mobile/assets/i18n/da-DK.json
locale_code: da-DK

View File

@@ -32,4 +32,6 @@ lerna-debug.log*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/extensions.json
upload/

View File

@@ -0,0 +1,42 @@
# Build stage
FROM node:16-bullseye-slim as builder
ARG DEBIAN_FRONTEND=noninteractive
WORKDIR /usr/src/app
COPY package.json package-lock.json ./
RUN apt-get update
RUN apt-get install gcc g++ make cmake python3 python3-pip ffmpeg -y
RUN npm ci
RUN npm rebuild @tensorflow/tfjs-node --build-from-source
COPY . .
RUN npm run build
# Prod stage
FROM node:16-bullseye-slim
ARG DEBIAN_FRONTEND=noninteractive
WORKDIR /usr/src/app
COPY package.json package-lock.json ./
COPY entrypoint.sh ./
RUN mkdir -p /usr/src/app/dist \
&& mkdir -p /usr/src/app/node_modules \
&& apt-get update \
&& apt-get install -y ffmpeg \
&& rm -rf /var/cache/apt/lists
COPY --from=builder /usr/src/app/node_modules ./node_modules
COPY --from=builder /usr/src/app/dist ./dist
RUN npm prune --production
# CMD [ "node", "dist/main" ]

View File

@@ -0,0 +1,3 @@
# npm run typeorm migration:run
# npm run start:prod
node dist/main.js

File diff suppressed because it is too large Load Diff

View File

@@ -25,20 +25,17 @@
"@nestjs/core": "^8.0.0",
"@nestjs/mapped-types": "^1.0.1",
"@nestjs/platform-express": "^8.0.0",
"@nestjs/typeorm": "^8.0.3",
"@tensorflow-models/coco-ssd": "^2.2.2",
"@tensorflow-models/mobilenet": "^2.1.0",
"@tensorflow/tfjs": "^3.15.0",
"@tensorflow/tfjs-converter": "^3.15.0",
"@tensorflow/tfjs-core": "^3.15.0",
"@tensorflow/tfjs-node": "^3.15.0",
"@tensorflow/tfjs-node-gpu": "^3.15.0",
"@tensorflow/tfjs": "^3.19.0",
"@tensorflow/tfjs-converter": "^3.19.0",
"@tensorflow/tfjs-core": "^3.19.0",
"@tensorflow/tfjs-node": "^3.19.0",
"@tensorflow/tfjs-node-gpu": "^3.19.0",
"@trpc/server": "^9.20.3",
"pg": "^8.7.3",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0",
"typeorm": "^0.2.45"
"rxjs": "^7.2.0"
},
"devDependencies": {
"@nestjs/cli": "^8.2.4",

View File

@@ -1,15 +1,9 @@
import { Module } from '@nestjs/common';
import { ImageClassifierModule } from './image-classifier/image-classifier.module';
import { databaseConfig } from './config/database.config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ObjectDetectionModule } from './object-detection/object-detection.module';
@Module({
imports: [
TypeOrmModule.forRoot(databaseConfig),
ImageClassifierModule,
ObjectDetectionModule,
],
imports: [ImageClassifierModule, ObjectDetectionModule],
controllers: [],
providers: [],
})

View File

@@ -5,9 +5,9 @@ import { ImageClassifierService } from './image-classifier.service';
export class ImageClassifierController {
constructor(
private readonly imageClassifierService: ImageClassifierService,
) {}
) { }
@Post('/tagImage')
@Post('/tag-image')
async tagImage(@Body('thumbnailPath') thumbnailPath: string) {
return await this.imageClassifierService.tagImage(thumbnailPath);
}

View File

@@ -5,17 +5,17 @@ import { Logger } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3001, () => {
await app.listen(3003, () => {
if (process.env.NODE_ENV == 'development') {
Logger.log(
'Running Immich Microservices in DEVELOPMENT environment',
'Running Immich Machine Learning in DEVELOPMENT environment',
'IMMICH MICROSERVICES',
);
}
if (process.env.NODE_ENV == 'production') {
Logger.log(
'Running Immich Microservices in PRODUCTION environment',
'Running Immich Machine Learning in PRODUCTION environment',
'IMMICH MICROSERVICES',
);
}

View File

@@ -1,13 +1,14 @@
import { Body, Controller, Post } from '@nestjs/common';
import { ObjectDetectionService } from './object-detection.service';
import { Logger } from '@nestjs/common';
@Controller('object-detection')
export class ObjectDetectionController {
constructor(
private readonly objectDetectionService: ObjectDetectionService,
) {}
) { }
@Post('/detectObject')
@Post('/detect-object')
async detectObject(@Body('thumbnailPath') thumbnailPath: string) {
return await this.objectDetectionService.detectObject(thumbnailPath);
}

View File

@@ -1 +0,0 @@
devenv/

View File

@@ -1,3 +0,0 @@
__pycache__/
devenv/
app/upload

View File

@@ -1,25 +0,0 @@
## GPU Build
# FROM tensorflow/tensorflow:latest-gpu as gpu
# WORKDIR /code
# COPY ./requirements.txt /code/requirements.txt
# RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
# COPY ./app /code/app
## CPU BUILD
FROM python:3.8 as cpu
RUN apt-get update
RUN apt-get install ffmpeg libsm6 libxext6 -y
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./app /code/app

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

View File

@@ -1,37 +0,0 @@
from tensorflow.keras.applications import InceptionV3
from tensorflow.keras.applications.inception_v3 import preprocess_input, decode_predictions
from tensorflow.keras.preprocessing import image
import numpy as np
from PIL import Image
import cv2
IMG_SIZE = 299
PREDICTION_MODEL = InceptionV3(weights='imagenet')
def classify_image(image_path: str):
img_path = f'./app/{image_path}'
# img = image.load_img(img_path, target_size=(IMG_SIZE, IMG_SIZE))
target_image = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
resized_target_image = cv2.resize(target_image, (IMG_SIZE, IMG_SIZE))
x = image.img_to_array(resized_target_image)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
preds = PREDICTION_MODEL.predict(x)
result = decode_predictions(preds, top=3)[0]
payload = []
for _, value, _ in result:
payload.append(value)
return payload
def warm_up():
img_path = f'./app/test.png'
img = image.load_img(img_path, target_size=(IMG_SIZE, IMG_SIZE))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
PREDICTION_MODEL.predict(x)

File diff suppressed because it is too large Load Diff

View File

@@ -1,46 +0,0 @@
from pydantic import BaseModel
from fastapi import FastAPI
from .object_detection import object_detection
from .image_classifier import image_classifier
from tf2_yolov4.anchors import YOLOV4_ANCHORS
from tf2_yolov4.model import YOLOv4
HEIGHT, WIDTH = (640, 960)
# Warm up model
image_classifier.warm_up()
app = FastAPI()
class TagImagePayload(BaseModel):
thumbnail_path: str
@app.post("/tagImage")
async def post_root(payload: TagImagePayload):
image_path = payload.thumbnail_path
if image_path[0] == '.':
image_path = image_path[2:]
return image_classifier.classify_image(image_path=image_path)
@app.get("/")
async def test():
object_detection.run_detection()
# image = tf.io.read_file("./app/cars.jpg")
# image = tf.image.decode_image(image)
# image = tf.image.resize(image, (HEIGHT, WIDTH))
# images = tf.expand_dims(image, axis=0) / 255.0
# model = YOLOv4(
# (HEIGHT, WIDTH, 3),
# 80,
# YOLOV4_ANCHORS,
# "darknet",
# )

View File

@@ -1,4 +0,0 @@
def run_detection():
print("run detection")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 KiB

View File

@@ -1,8 +0,0 @@
opencv-python==4.5.5.64
fastapi>=0.68.0,<0.69.0
pydantic>=1.8.0,<2.0.0
uvicorn>=0.15.0,<0.16.0
tensorflow==2.8.0
numpy==1.22.2
pillow==9.0.1
tf2_yolov4==0.1.0

View File

@@ -1,16 +0,0 @@
FROM node:16-bullseye-slim
ARG DEBIAN_FRONTEND=noninteractive
WORKDIR /usr/src/app
COPY package.json package-lock.json ./
RUN apt-get update
RUN apt-get install gcc g++ make cmake python3 python3-pip ffmpeg -y
RUN npm install
COPY . .
RUN npm run build

View File

@@ -1,2 +0,0 @@
# npm run typeorm migration:run
npm run build && npm run start:prod

View File

@@ -1,11 +0,0 @@
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
export const databaseConfig: TypeOrmModuleOptions = {
type: 'postgres',
host: 'immich_postgres',
port: 5432,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE_NAME,
synchronize: false,
};

View File

@@ -1,25 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
// End to End test
describe('AppController (e2e)', () => {
let app: INestApplication;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('/ (GET)', () => {
return request(app.getHttpServer())
.get('/')
.expect(200)
.expect('Hello World!');
});
});

2
mobile/.gitignore vendored
View File

@@ -24,7 +24,7 @@
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
**/ios/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies

View File

@@ -1,10 +1,45 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
# This file should be version controlled.
version:
revision: 77d935af4db863f6abd0b9c31c7e6df2a13de57b
revision: cd41fdd495f6944ecd3506c21e94c6567b073278
channel: stable
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
base_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
- platform: android
create_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
base_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
- platform: ios
create_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
base_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
- platform: linux
create_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
base_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
- platform: macos
create_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
base_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
- platform: web
create_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
base_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
- platform: windows
create_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
base_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

View File

@@ -21,9 +21,18 @@ linter:
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
use_build_context_synchronously: false
require_trailing_commas: true
unrelated_type_equality_checks: true
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
analyzer:
exclude:
- openapi/
- openapi/test/
- lib/generated_plugin_registrant.dart

View File

@@ -11,3 +11,6 @@ GeneratedPluginRegistrant.java
key.properties
**/*.keystore
**/*.jks
# Fastlane
/fastlane/report.xml

View File

@@ -51,7 +51,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "app.alextran.immich"
minSdkVersion 21
minSdkVersion 23
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
@@ -80,5 +80,8 @@ flutter {
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "androidx.work:work-runtime-ktx:$work_version"
implementation "androidx.concurrent:concurrent-futures:$concurrent_version"
implementation "com.google.guava:guava:$guava_version"
}

View File

@@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="app.alextran.immich">
<application android:label="Immich" android:name="${applicationName}" android:usesCleartextTraffic="true" android:icon="@mipmap/ic_launcher">
<application android:label="Immich" android:name="${applicationName}" android:usesCleartextTraffic="true" android:icon="@mipmap/ic_launcher" android:requestLegacyExternalStorage="true">
<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
@@ -12,6 +12,7 @@
</intent-filter>
</activity>
<service android:name=".AppClearedService" android:stopWithTask="false" />
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data android:name="flutterEmbedding" android:value="2" />
@@ -23,4 +24,11 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
</queries>
</manifest>

View File

@@ -1,20 +0,0 @@
// Generated file.
// If you wish to remove Flutter's multidex support, delete this entire file.
package io.flutter.app;
import android.content.Context;
import androidx.annotation.CallSuper;
import androidx.multidex.MultiDex;
/**
* Extension of {@link io.flutter.app.FlutterApplication}, adding multidex support.
*/
public class FlutterMultiDexApplication extends FlutterApplication {
@Override
@CallSuper
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}

View File

@@ -1,6 +0,0 @@
package com.example.immich_mobile
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}

View File

@@ -0,0 +1,25 @@
package app.alextran.immich
import android.app.Service
import android.content.Intent
import android.os.IBinder
/**
* Catches the event when either the system or the user kills the app
* (does not apply on force close!)
*/
class AppClearedService() : Service() {
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
return START_NOT_STICKY;
}
override fun onTaskRemoved(rootIntent: Intent) {
ContentObserverWorker.workManagerAppClearedWorkaround(applicationContext)
stopSelf();
}
}

View File

@@ -0,0 +1,75 @@
package app.alextran.immich
import android.content.Context
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
/**
* Android plugin for Dart `BackgroundService`
*
* Receives messages/method calls from the foreground Dart side to manage
* the background service, e.g. start (enqueue), stop (cancel)
*/
class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
private var methodChannel: MethodChannel? = null
private var context: Context? = null
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
onAttachedToEngine(binding.applicationContext, binding.binaryMessenger)
}
private fun onAttachedToEngine(ctx: Context, messenger: BinaryMessenger) {
context = ctx
methodChannel = MethodChannel(messenger, "immich/foregroundChannel")
methodChannel?.setMethodCallHandler(this)
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
onDetachedFromEngine()
}
private fun onDetachedFromEngine() {
methodChannel?.setMethodCallHandler(null)
methodChannel = null
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
val ctx = context!!
when(call.method) {
"enable" -> {
val args = call.arguments<ArrayList<*>>()!!
ctx.getSharedPreferences(BackupWorker.SHARED_PREF_NAME, Context.MODE_PRIVATE)
.edit()
.putLong(BackupWorker.SHARED_PREF_CALLBACK_KEY, args.get(0) as Long)
.putString(BackupWorker.SHARED_PREF_NOTIFICATION_TITLE, args.get(1) as String)
.apply()
ContentObserverWorker.enable(ctx, immediate = args.get(2) as Boolean)
result.success(true)
}
"configure" -> {
val args = call.arguments<ArrayList<*>>()!!
val requireUnmeteredNetwork = args.get(0) as Boolean
val requireCharging = args.get(1) as Boolean
ContentObserverWorker.configureWork(ctx, requireUnmeteredNetwork, requireCharging)
result.success(true)
}
"disable" -> {
ContentObserverWorker.disable(ctx)
BackupWorker.stopWork(ctx)
result.success(true)
}
"isEnabled" -> {
result.success(ContentObserverWorker.isEnabled(ctx))
}
"isIgnoringBatteryOptimizations" -> {
result.success(BackupWorker.isIgnoringBatteryOptimizations(ctx))
}
else -> result.notImplemented()
}
}
}
private const val TAG = "BackgroundServicePlugin"

View File

@@ -0,0 +1,328 @@
package app.alextran.immich
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.os.PowerManager
import android.os.SystemClock
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.concurrent.futures.ResolvableFuture
import androidx.work.BackoffPolicy
import androidx.work.Constraints
import androidx.work.ForegroundInfo
import androidx.work.ListenableWorker
import androidx.work.NetworkType
import androidx.work.WorkerParameters
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.WorkInfo
import com.google.common.util.concurrent.ListenableFuture
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.dart.DartExecutor
import io.flutter.embedding.engine.loader.FlutterLoader
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.view.FlutterCallbackInformation
import java.util.concurrent.TimeUnit
/**
* Worker executed by Android WorkManager to perform backup in background
*
* Starts the Dart runtime/engine and calls `_nativeEntry` function in
* `background.service.dart` to run the actual backup logic.
* Called by Android WorkManager when all constraints for the work are met,
* i.e. battery is not low and optionally Wifi and charging are active.
*/
class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ctx, params), MethodChannel.MethodCallHandler {
private val resolvableFuture = ResolvableFuture.create<Result>()
private var engine: FlutterEngine? = null
private lateinit var backgroundChannel: MethodChannel
private val notificationManager = ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
private val isIgnoringBatteryOptimizations = isIgnoringBatteryOptimizations(applicationContext)
private var timeBackupStarted: Long = 0L
override fun startWork(): ListenableFuture<ListenableWorker.Result> {
Log.d(TAG, "startWork")
val ctx = applicationContext
if (!flutterLoader.initialized()) {
flutterLoader.startInitialization(ctx)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create a Notification channel if necessary
createChannel()
}
val title = ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE)
.getString(SHARED_PREF_NOTIFICATION_TITLE, NOTIFICATION_DEFAULT_TITLE)!!
if (isIgnoringBatteryOptimizations) {
// normal background services can only up to 10 minutes
// foreground services are allowed to run indefinitely
// requires battery optimizations to be disabled (either manually by the user
// or by the system learning that immich is important to the user)
setForegroundAsync(createForegroundInfo(title))
} else {
showBackgroundInfo(title)
}
engine = FlutterEngine(ctx)
flutterLoader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) {
runDart()
}
return resolvableFuture
}
/**
* Starts the Dart runtime/engine and calls `_nativeEntry` function in
* `background.service.dart` to run the actual backup logic.
*/
private fun runDart() {
val callbackDispatcherHandle = applicationContext.getSharedPreferences(
SHARED_PREF_NAME, Context.MODE_PRIVATE).getLong(SHARED_PREF_CALLBACK_KEY, 0L)
val callbackInformation = FlutterCallbackInformation.lookupCallbackInformation(callbackDispatcherHandle)
val appBundlePath = flutterLoader.findAppBundlePath()
engine?.let { engine ->
backgroundChannel = MethodChannel(engine.dartExecutor, "immich/backgroundChannel")
backgroundChannel.setMethodCallHandler(this@BackupWorker)
engine.dartExecutor.executeDartCallback(
DartExecutor.DartCallback(
applicationContext.assets,
appBundlePath,
callbackInformation
)
)
}
}
override fun onStopped() {
Log.d(TAG, "onStopped")
// called when the system has to stop this worker because constraints are
// no longer met or the system needs resources for more important tasks
Handler(Looper.getMainLooper()).postAtFrontOfQueue {
backgroundChannel.invokeMethod("systemStop", null)
}
// cannot await/get(block) on resolvableFuture as its already cancelled (would throw CancellationException)
// instead, wait for 5 seconds until forcefully stopping backup work
Handler(Looper.getMainLooper()).postDelayed({
stopEngine(null)
}, 5000)
}
private fun stopEngine(result: Result?) {
if (result != null) {
Log.d(TAG, "stopEngine result=${result}")
resolvableFuture.set(result)
}
engine?.destroy()
engine = null
clearBackgroundNotification()
}
override fun onMethodCall(call: MethodCall, r: MethodChannel.Result) {
when (call.method) {
"initialized" -> {
timeBackupStarted = SystemClock.uptimeMillis()
backgroundChannel.invokeMethod(
"onAssetsChanged",
null,
object : MethodChannel.Result {
override fun notImplemented() {
stopEngine(Result.failure())
}
override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) {
stopEngine(Result.failure())
}
override fun success(receivedResult: Any?) {
val success = receivedResult as Boolean
stopEngine(if(success) Result.success() else Result.retry())
}
}
)
}
"updateNotification" -> {
val args = call.arguments<ArrayList<*>>()!!
val title = args.get(0) as String
val content = args.get(1) as String
if (isIgnoringBatteryOptimizations) {
setForegroundAsync(createForegroundInfo(title, content))
} else {
showBackgroundInfo(title, content)
}
}
"showError" -> {
val args = call.arguments<ArrayList<*>>()!!
val title = args.get(0) as String
val content = args.get(1) as String
val individualTag = args.get(2) as String?
showError(title, content, individualTag)
}
"clearErrorNotifications" -> clearErrorNotifications()
"hasContentChanged" -> {
val lastChange = applicationContext
.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE)
.getLong(SHARED_PREF_LAST_CHANGE, timeBackupStarted)
val hasContentChanged = lastChange > timeBackupStarted;
timeBackupStarted = SystemClock.uptimeMillis()
r.success(hasContentChanged)
}
else -> r.notImplemented()
}
}
private fun showError(title: String, content: String, individualTag: String?) {
val notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL_ERROR_ID)
.setContentTitle(title)
.setTicker(title)
.setContentText(content)
.setSmallIcon(R.mipmap.ic_launcher)
.setOnlyAlertOnce(true)
.build()
notificationManager.notify(individualTag, NOTIFICATION_ERROR_ID, notification)
}
private fun clearErrorNotifications() {
notificationManager.cancel(NOTIFICATION_ERROR_ID)
}
private fun showBackgroundInfo(title: String = NOTIFICATION_DEFAULT_TITLE, content: String? = null) {
val notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL_ID)
.setContentTitle(title)
.setTicker(title)
.setContentText(content)
.setSmallIcon(R.mipmap.ic_launcher)
.setOnlyAlertOnce(true)
.setOngoing(true)
.build()
notificationManager.notify(NOTIFICATION_ID, notification)
}
private fun clearBackgroundNotification() {
notificationManager.cancel(NOTIFICATION_ID)
}
private fun createForegroundInfo(title: String = NOTIFICATION_DEFAULT_TITLE, content: String? = null): ForegroundInfo {
val notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL_ID)
.setContentTitle(title)
.setTicker(title)
.setContentText(content)
.setSmallIcon(R.mipmap.ic_launcher)
.setOngoing(true)
.build()
return ForegroundInfo(NOTIFICATION_ID, notification)
}
@RequiresApi(Build.VERSION_CODES.O)
private fun createChannel() {
val foreground = NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)
notificationManager.createNotificationChannel(foreground)
val error = NotificationChannel(NOTIFICATION_CHANNEL_ERROR_ID, NOTIFICATION_CHANNEL_ERROR_ID, NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(error)
}
companion object {
const val SHARED_PREF_NAME = "immichBackgroundService"
const val SHARED_PREF_CALLBACK_KEY = "callbackDispatcherHandle"
const val SHARED_PREF_NOTIFICATION_TITLE = "notificationTitle"
const val SHARED_PREF_LAST_CHANGE = "lastChange"
private const val TASK_NAME_BACKUP = "immich/BackupWorker"
private const val NOTIFICATION_CHANNEL_ID = "immich/backgroundService"
private const val NOTIFICATION_CHANNEL_ERROR_ID = "immich/backgroundServiceError"
private const val NOTIFICATION_DEFAULT_TITLE = "Immich"
private const val NOTIFICATION_ID = 1
private const val NOTIFICATION_ERROR_ID = 2
private const val ONE_MINUTE = 60000L
/**
* Enqueues the BackupWorker to run once the constraints are met
*/
fun enqueueBackupWorker(context: Context,
requireWifi: Boolean = false,
requireCharging: Boolean = false,
delayMilliseconds: Long = 0L) {
val workRequest = buildWorkRequest(requireWifi, requireCharging, delayMilliseconds)
WorkManager.getInstance(context).enqueueUniqueWork(TASK_NAME_BACKUP, ExistingWorkPolicy.KEEP, workRequest)
Log.d(TAG, "enqueueBackupWorker: BackupWorker enqueued")
}
/**
* Updates the constraints of an already enqueued BackupWorker
*/
fun updateBackupWorker(context: Context,
requireWifi: Boolean = false,
requireCharging: Boolean = false) {
try {
val wm = WorkManager.getInstance(context)
val workInfoFuture = wm.getWorkInfosForUniqueWork(TASK_NAME_BACKUP)
val workInfoList = workInfoFuture.get(1000, TimeUnit.MILLISECONDS)
if (workInfoList != null) {
for (workInfo in workInfoList) {
if (workInfo.getState() == WorkInfo.State.ENQUEUED) {
val workRequest = buildWorkRequest(requireWifi, requireCharging)
wm.enqueueUniqueWork(TASK_NAME_BACKUP, ExistingWorkPolicy.REPLACE, workRequest)
Log.d(TAG, "updateBackupWorker updated BackupWorker constraints")
return
}
}
}
Log.d(TAG, "updateBackupWorker: BackupWorker not enqueued")
} catch (e: Exception) {
Log.d(TAG, "updateBackupWorker failed: ${e}")
}
}
/**
* Stops the currently running worker (if any) and removes it from the work queue
*/
fun stopWork(context: Context) {
WorkManager.getInstance(context).cancelUniqueWork(TASK_NAME_BACKUP)
Log.d(TAG, "stopWork: BackupWorker cancelled")
}
/**
* Returns `true` if the app is ignoring battery optimizations
*/
fun isIgnoringBatteryOptimizations(ctx: Context): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val pwrm = ctx.getSystemService(Context.POWER_SERVICE) as PowerManager
val name = ctx.packageName
return pwrm.isIgnoringBatteryOptimizations(name)
}
return true
}
private fun buildWorkRequest(requireWifi: Boolean = false,
requireCharging: Boolean = false,
delayMilliseconds: Long = 0L): OneTimeWorkRequest {
val constraints = Constraints.Builder()
.setRequiredNetworkType(if (requireWifi) NetworkType.UNMETERED else NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(requireCharging)
.build();
val work = OneTimeWorkRequest.Builder(BackupWorker::class.java)
.setConstraints(constraints)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, ONE_MINUTE, TimeUnit.MILLISECONDS)
.setInitialDelay(delayMilliseconds, TimeUnit.MILLISECONDS)
.build()
return work
}
private val flutterLoader = FlutterLoader()
}
}
private const val TAG = "BackupWorker"

View File

@@ -0,0 +1,137 @@
package app.alextran.immich
import android.content.Context
import android.os.SystemClock
import android.provider.MediaStore
import android.util.Log
import androidx.work.Constraints
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.Operation
import java.util.concurrent.TimeUnit
/**
* Worker executed by Android WorkManager observing content changes (new photos/videos)
*
* Immediately enqueues the BackupWorker when running.
* As this work is not triggered periodically, but on content change, the
* worker enqueues itself again after each run.
*/
class ContentObserverWorker(ctx: Context, params: WorkerParameters) : Worker(ctx, params) {
override fun doWork(): Result {
if (!isEnabled(applicationContext)) {
return Result.failure()
}
if (getTriggeredContentUris().size > 0) {
startBackupWorker(applicationContext, delayMilliseconds = 0)
}
enqueueObserverWorker(applicationContext, ExistingWorkPolicy.REPLACE)
return Result.success()
}
companion object {
const val SHARED_PREF_SERVICE_ENABLED = "serviceEnabled"
const val SHARED_PREF_REQUIRE_WIFI = "requireWifi"
const val SHARED_PREF_REQUIRE_CHARGING = "requireCharging"
private const val TASK_NAME_OBSERVER = "immich/ContentObserver"
/**
* Enqueues the `ContentObserverWorker`.
*
* @param context Android Context
*/
fun enable(context: Context, immediate: Boolean = false) {
// migration to remove any old active background task
WorkManager.getInstance(context).cancelUniqueWork("immich/photoListener")
enqueueObserverWorker(context, ExistingWorkPolicy.KEEP)
Log.d(TAG, "enabled ContentObserverWorker")
if (immediate) {
startBackupWorker(context, delayMilliseconds = 5000)
}
}
/**
* Configures the `BackupWorker` to run when all constraints are met.
*
* @param context Android Context
* @param requireWifi if true, task only runs if connected to wifi
* @param requireCharging if true, task only runs if device is charging
*/
fun configureWork(context: Context,
requireWifi: Boolean = false,
requireCharging: Boolean = false) {
context.getSharedPreferences(BackupWorker.SHARED_PREF_NAME, Context.MODE_PRIVATE)
.edit()
.putBoolean(SHARED_PREF_SERVICE_ENABLED, true)
.putBoolean(SHARED_PREF_REQUIRE_WIFI, requireWifi)
.putBoolean(SHARED_PREF_REQUIRE_CHARGING, requireCharging)
.apply()
BackupWorker.updateBackupWorker(context, requireWifi, requireCharging)
}
/**
* Stops the currently running worker (if any) and removes it from the work queue
*/
fun disable(context: Context) {
context.getSharedPreferences(BackupWorker.SHARED_PREF_NAME, Context.MODE_PRIVATE)
.edit().putBoolean(SHARED_PREF_SERVICE_ENABLED, false).apply()
WorkManager.getInstance(context).cancelUniqueWork(TASK_NAME_OBSERVER)
Log.d(TAG, "disabled ContentObserverWorker")
}
/**
* Return true if the user has enabled the background backup service
*/
fun isEnabled(ctx: Context): Boolean {
return ctx.getSharedPreferences(BackupWorker.SHARED_PREF_NAME, Context.MODE_PRIVATE)
.getBoolean(SHARED_PREF_SERVICE_ENABLED, false)
}
/**
* Enqueue and replace the worker without the content trigger but with a short delay
*/
fun workManagerAppClearedWorkaround(context: Context) {
val work = OneTimeWorkRequest.Builder(ContentObserverWorker::class.java)
.setInitialDelay(500, TimeUnit.MILLISECONDS)
.build()
WorkManager
.getInstance(context)
.enqueueUniqueWork(TASK_NAME_OBSERVER, ExistingWorkPolicy.REPLACE, work)
.getResult()
.get()
Log.d(TAG, "workManagerAppClearedWorkaround")
}
private fun enqueueObserverWorker(context: Context, policy: ExistingWorkPolicy) {
val constraints = Constraints.Builder()
.addContentUriTrigger(MediaStore.Images.Media.INTERNAL_CONTENT_URI, true)
.addContentUriTrigger(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true)
.addContentUriTrigger(MediaStore.Video.Media.INTERNAL_CONTENT_URI, true)
.addContentUriTrigger(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true)
.setTriggerContentUpdateDelay(5000, TimeUnit.MILLISECONDS)
.build()
val work = OneTimeWorkRequest.Builder(ContentObserverWorker::class.java)
.setConstraints(constraints)
.build()
WorkManager.getInstance(context).enqueueUniqueWork(TASK_NAME_OBSERVER, policy, work)
}
private fun startBackupWorker(context: Context, delayMilliseconds: Long) {
val sp = context.getSharedPreferences(BackupWorker.SHARED_PREF_NAME, Context.MODE_PRIVATE)
val requireWifi = sp.getBoolean(SHARED_PREF_REQUIRE_WIFI, true)
val requireCharging = sp.getBoolean(SHARED_PREF_REQUIRE_CHARGING, false)
BackupWorker.enqueueBackupWorker(context, requireWifi, requireCharging, delayMilliseconds)
sp.edit().putLong(BackupWorker.SHARED_PREF_LAST_CHANGE, SystemClock.uptimeMillis()).apply()
}
}
}
private const val TAG = "ContentObserverWorker"

View File

@@ -1,6 +1,25 @@
package app.alextran.immich
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import android.os.Bundle
import android.content.Intent
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
flutterEngine.getPlugins().add(BackgroundServicePlugin())
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
try {
startService(Intent(getBaseContext(), AppClearedService::class.java));
} catch (e: Exception) {
// startService must not be called when app is in background (crashes app)
// there is nothing we can do
}
}
}

View File

@@ -1,12 +1,15 @@
buildscript {
ext.kotlin_version = '1.6.10'
ext.work_version = '2.7.1'
ext.concurrent_version = '1.1.0'
ext.guava_version = '31.0.1-android'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
classpath 'com.android.tools.build:gradle:7.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

View File

@@ -1,2 +1,2 @@
json_key_file("/Users/alex/Documents/immich-fastlane-googleplaystore-key.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one
package_name("app.alextran.immich") # e.g. com.krausefx.app
json_key_file("/Users/alex/Documents/immich-play-store-key.json")
package_name("app.alextran.immich")

View File

@@ -16,10 +16,30 @@
default_platform(:android)
platform :android do
desc "Update AAB to PlayStore"
desc "Build Android and Release Testing"
lane :beta do
upload_to_play_store(track: 'beta', aab: '../build/app/outputs/bundle/release/app-release.aab')
gradle(
task: 'bundle',
build_type: 'Release',
properties: {
"android.injected.version.code" => 47,
"android.injected.version.name" => "1.30.2",
}
)
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab', track: 'beta')
end
desc "Build and Release Android"
lane :release do
gradle(
task: 'bundle',
build_type: 'Release',
properties: {
"android.injected.version.code" => 48,
"android.injected.version.name" => "1.30.2",
}
)
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
end
end

View File

@@ -21,7 +21,15 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do
[bundle exec] fastlane android beta
```
Update AAB to PlayStore
Build Android and Release Testing
### android release
```sh
[bundle exec] fastlane android release
```
Build and Release Android
----

View File

@@ -0,0 +1,7 @@
* New features
- Share album. Users can now create albums to share with existing people on the network.
- Owner can delete the album.
- Owner can invite the additional users to the album.
- Shared users and the owner can add additional assets to the album.
* In the asset viewer, the user can swipe up to see detailed information and swip down to dismiss.
* Several UI enhancements.

View File

@@ -0,0 +1 @@
* Album name is now editable

View File

@@ -0,0 +1,2 @@
* New Feature - Selection backup. User can now select a combination of albums to be included or excluded during the backup process, and only unique photos, and videos that are not overlapping between the two groups will be backup.
* Bug fix - Show correct count of backup and remainder assets.

View File

@@ -0,0 +1 @@
* Hotfix: Permission is being requested now when open backup screen on Android10

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