Compare commits

...
Sign in to create a new pull request.

581 commits

Author SHA1 Message Date
Michael Mayer
8990d48381 Develop: Upgrade base image from 231127-mantic to 231206-mantic
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-12-06 17:10:53 +01:00
Michael Mayer
9c6fae98d3 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-12-06 17:10:16 +01:00
graciousgrey
55d5e7a732 Videos: Add file info for .mxf files #3935 2023-12-06 12:02:13 +01:00
graciousgrey
3507f5ef55 Add support for .mxf files #3935 2023-12-06 11:59:53 +01:00
Brandon Richardson
3d962e2382 Backend: Expose prometheus-style metrics endpoint
Expose a new API which can be scraped by prometheus to gather useful
metrics from an instance. The new endpoint exposes photoprism build
version information, golang version, edition and various count metrics.
2023-12-06 08:13:24 +01:00
Michael Mayer
0935d9fab0 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-12-04 11:52:16 +01:00
Michael Mayer
d36e5a3850 Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-12-04 11:51:56 +01:00
Michael Mayer
fb4d99625d Setup: Simplify mariadb service config in docker-compose.yml files #3928
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-12-04 11:07:55 +01:00
Daniel Black
cd014f02c5
Mariadb docker-compose simplification (#3928)
* Docker: mariadb container don't need command: mariadbd

The #3443 compatibility missed an important simplification,
the mariadbd/mysqld was never needed on the command.

Remove this from the simple cases.

Signed-off-by: Daniel Black <daniel@mariadb.org>

* Docker: mariadb - bump latest to 11.2

Latest GA MariaDB is currently 11.2

Signed-off-by: Daniel Black <daniel@mariadb.org>

* Docker: mariadb - eol for 10.7/10.8 - 10.11 is lts

As the 10.7 and 10.8 where short term releases and are now end of life,
remove those and replace with 10.11, a LTS version.

Signed-off-by: Daniel Black <daniel@mariadb.org>

---------

Signed-off-by: Daniel Black <daniel@mariadb.org>
2023-12-04 11:04:03 +01:00
Michael Mayer
1d7655584c Setup: Update Podman Compose example config
https://www.reddit.com/r/photoprism/comments/188hn3u/comment/kbxaiz9/
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-12-04 11:00:02 +01:00
Michael Mayer
13160c1640 Setup: Fix typo in Linux package install guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-12-04 10:01:58 +01:00
Michael Mayer
07d74e68f9 Setup: Improve Linux package install guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-12-04 09:33:38 +01:00
Michael Mayer
37f647a8f9 Setup: Improve docs for binary installation packages #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-29 13:45:55 +01:00
Michael Mayer
111fd0ebbe Setup: Improve docs for binary installation packages #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-29 13:32:48 +01:00
Michael Mayer
7801e603f9 Setup: Update docs for binary installation packages #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-29 13:12:19 +01:00
Michael Mayer
4ffc548287 Docs: Update badges in README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-28 14:03:47 +01:00
Michael Mayer
200b0e1f1d Docs: Update badges in README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-28 14:02:06 +01:00
Michael Mayer
e4f287bbb8
Windows: Update install.bat 2023-11-27 21:59:55 +01:00
Michael Mayer
ab491c3032 2FA: Add generator for random 16-digit app passwords #808
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-27 19:43:53 +01:00
Michael Mayer
f48ff16ef5 Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-27 18:21:42 +01:00
Michael Mayer
51178ea209 Develop: Upgrade base image from 231120-mantic to 231127-mantic
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-27 18:19:08 +01:00
Michael Mayer
5bc61b496f Cards View: Refactor generateLensInfo() to fix rendering bug #3918
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-27 15:41:48 +01:00
Michael Mayer
eb63cb8324 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-26 16:32:30 +01:00
Michael Mayer
6ba87a52d8 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-23 17:24:41 +01:00
graciousgrey
59456c57be Tests: Add unit test #3885 2023-11-21 17:47:29 +01:00
graciousgrey
292eaf6ee0 Tests: Add unit tests #3896 2023-11-21 17:08:18 +01:00
graciousgrey
5d06770ab6 Tests: Update photo fixtures 2023-11-21 17:07:39 +01:00
Michael Mayer
63d071a219 Develop: Upgrade base image from 231108-mantic to 231120-mantic #3885
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-20 18:59:58 +01:00
Michael Mayer
82c70772d2 Develop: Update Ubuntu base image Dockerfiles #3885
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-20 14:35:13 +01:00
Michael Mayer
f714c1d759 Develop: Update Ubuntu base image Dockerfiles #3885
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-20 14:32:15 +01:00
graciousgrey
2d7a951c1a Update SPONSORS.md 2023-11-20 12:29:09 +01:00
Michael Mayer
eb19a4a893 Search: Add filter to find pictures by resolution range in MP #3896
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-20 11:47:23 +01:00
Michael Mayer
717e616700 Vectors: Use RSVG instead of imagemagick to convert SVG to PNG #3885
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-20 11:43:54 +01:00
Michael Mayer
ac588057da Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-20 11:40:05 +01:00
Alex Spurling
d32bc4cc6c
FFmpeg: Seek input not output video (#3893)
This improves performance when converting video to images as we no longer
have to decode and then discard the first x seconds of video.
2023-11-19 15:55:33 +01:00
Michael Mayer
052fe82126 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-16 15:34:08 +01:00
Michael Mayer
8b5d547773 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-14 18:43:50 +01:00
Michael Mayer
e686b82cde Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-14 18:43:31 +01:00
Michael Mayer
d06a182ac0 JPEG: Reduce log level for reporting invalid color metadata #3843
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-09 10:38:05 +01:00
Michael Mayer
be10bacb40 Setup: Update Linux package install guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-09 10:13:22 +01:00
Michael Mayer
0af4eefde1 Setup: Update Linux package install guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-09 10:07:06 +01:00
Michael Mayer
a2757c194b Setup: Update Linux package install guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-09 10:03:06 +01:00
Michael Mayer
79a60b8971 Setup: Update Linux package install guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-09 09:46:49 +01:00
Michael Mayer
797853d461 Setup: Update Linux package install guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-09 09:23:05 +01:00
Michael Mayer
b65e9137c6 Setup: Update Linux package install guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-09 09:21:22 +01:00
Michael Mayer
b5e6a126d8 Setup: Update Linux package install guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-09 09:05:08 +01:00
Michael Mayer
23a096b431 Setup: Update Linux package install guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-09 09:05:00 +01:00
Michael Mayer
29b9b6fc76 Setup: Update Linux package install guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-09 08:58:52 +01:00
Michael Mayer
1b41e89cbd Develop: Upgrade base image from 231103-mantic to 231108-mantic
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-08 15:53:39 +01:00
Michael Mayer
a41fb2c05a Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-08 15:52:49 +01:00
Michael Mayer
a76a8bdb10 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-08 15:52:16 +01:00
Michael Mayer
adafb34433 Setup: Update Linux package config examples #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-08 11:47:12 +01:00
Michael Mayer
c9287f6f29 Setup: Update Linux package config examples #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-08 11:44:39 +01:00
Michael Mayer
c8d1b2e57b Setup: Update Linux package install guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-08 11:39:09 +01:00
Michael Mayer
380c521098 Setup: Update Linux package example config #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-08 11:35:30 +01:00
Michael Mayer
bb6175f78c Setup: Update Linux package example config #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-08 11:20:24 +01:00
Michael Mayer
b98e14f880 Setup: Update Linux package installation guide #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-08 11:11:03 +01:00
Michael Mayer
1f112629ab Setup: Update Linux package config file examples #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-08 11:00:38 +01:00
Michael Mayer
fdfbdc4ff7 Setup: Add Linux package config file examples #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-07 17:02:06 +01:00
graciousgrey
3a24d06a00 Translations: Update translations.json 2023-11-06 12:34:45 +01:00
Theresa Gresch
4609edb6ee
Merge pull request #3870 from photoprismci/weblate-photoprism-frontend
Weblate: Update translations
2023-11-06 12:30:07 +01:00
Weblate
36618c3a73 Weblate: Update frontend translations 2023-11-06 12:27:32 +01:00
Michael Mayer
539e18d984 Setup: Update tar.gz target in Makefile #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-03 15:05:51 +01:00
Michael Mayer
e97c96c509 Setup: Upgrade develop base image to 231103-mantic #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-03 13:18:48 +01:00
Michael Mayer
e85f349ea6 Setup: Prepare build scripts to provide .deb and .rpm packages #3861
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-03 13:05:12 +01:00
Michael Mayer
602097635f Setup: Update docs for Linux installation packages
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-02 14:54:40 +01:00
Michael Mayer
a247cc08f1 Docker: Update README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-02 12:11:58 +01:00
Michael Mayer
c2de3aa0ec HEIC: Improve build-libheif.sh and install-libheif.sh scripts #3852
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-02 11:24:39 +01:00
Michael Mayer
d93e4c8ccd Docker: Update README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-02 10:58:07 +01:00
Michael Mayer
4ffbbe9f84 UX: Improve copy to clipboard event handler in photo edit dialog
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-01 13:20:27 +01:00
Michael Mayer
fe182d78f4 Metadata: Add tests to pkg/txt/file_title_test.go
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-01 12:04:37 +01:00
Michael Mayer
7ec6b7e66f UX: Add click handler to copy filename and hash to clipboard from dialog
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-01 11:47:32 +01:00
Michael Mayer
8eee3597ef Setup: Improve Getting Started section in README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-01 10:52:27 +01:00
Michael Mayer
4d2ff59a40 Setup: Shorten Getting Started section in README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-01 10:43:21 +01:00
Michael Mayer
5611678835 Setup: Update Getting Started section in README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-01 10:41:25 +01:00
Michael Mayer
b053dced4a Docker: Update README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-01 09:35:25 +01:00
Michael Mayer
540c45c7c6 Docker: Update README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-01 09:27:59 +01:00
Michael Mayer
47c6ee070c Docker: Update README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-01 09:19:13 +01:00
Michael Mayer
afe3c13414 Docker: Fix links in README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-11-01 09:08:54 +01:00
Michael Mayer
e6b03f33f6
Update README.md 2023-11-01 09:01:31 +01:00
Michael Mayer
47e9b20929 Setup: Update docs for Linux installation packages
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-31 17:01:33 +01:00
Michael Mayer
227efd581d Setup: Update docs for Linux installation packages
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-31 16:21:27 +01:00
Michael Mayer
d0ea838b37 Thumbnails: Add panic handler for unexpected image encoding errors #3858
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-31 14:37:47 +01:00
Michael Mayer
eae09353f2 Search: Improve cards view ISO info #3816
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-31 14:26:38 +01:00
Michael Mayer
86f16790ea JPEG: Read files with invalid color data from the beginning #3843
Using a ReadSeeker is necessary to read images with invalid color
metadata from the beginning in order to avoid decoding errors.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-31 14:24:31 +01:00
Michael Mayer
29be637d62 Metadata: Update pkg/txt/specialwords.go
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-31 14:06:52 +01:00
Michael Mayer
78e6dd88d8 JPEG: Fix regression when handling files with EOF error #3855
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-31 13:13:18 +01:00
Michael Mayer
b07609c213 HEIC: Add iPhone 15 Pro file samples and update related tests #3852
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-31 12:39:36 +01:00
Michael Mayer
948417f97e Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-31 11:39:11 +01:00
Michael Mayer
6123ddf4af Metadata: Update pkg/txt/specialwords.go
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-31 11:38:57 +01:00
Michael Mayer
34fa0306ba Frontend: Update deps in package.json and package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-29 16:38:10 +01:00
Michael Mayer
597dd1e554 Backend: Update google/uuid in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-29 16:37:50 +01:00
Michael Mayer
e5e25e4e7e Develop: Upgrade base image from 231026-mantic to 231029-mantic #3852
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-29 16:37:02 +01:00
Michael Mayer
f2cc300a06 HEIC: Upgrade libheif from v1.13.0 to v1.17.1 #3852
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-29 16:11:09 +01:00
Michael Mayer
632c23ca47 HEIF: Update dist/build-libheif.sh script
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-28 14:29:49 +02:00
Michael Mayer
f28adc84e6 Develop: Update build deps in base image Dockerfiles
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-28 14:18:23 +02:00
Michael Mayer
ae585ba475 Setup: Update docs for Linux installation packages
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-27 10:07:32 +02:00
Michael Mayer
4d568d79e9 Setup: Update docs for Linux installation packages
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-27 09:17:42 +02:00
Michael Mayer
9b930a7910 Setup: Update docs for Linux installation packages
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-27 09:11:19 +02:00
Michael Mayer
3ef8540018 Setup: Update docs for Linux installation packages
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 16:12:05 +02:00
Michael Mayer
b88eccda0f Frontend: Update translations.pot and *.po files
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 13:38:20 +02:00
Michael Mayer
40bdbbf00f Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 13:37:49 +02:00
graciousgrey
46642b3ac0 Tests: Add unit tests for search 2023-10-26 12:52:39 +02:00
graciousgrey
313948b103 Tests: Add altitude to photo fixtures 2023-10-26 12:28:41 +02:00
Michael Mayer
fcc3971394 Develop: Upgrade default base image to Ubuntu 23.10 (Mantic Minotaur)
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 12:22:52 +02:00
Michael Mayer
cdf9e76a13 ARMv7: Update ubuntu base image tag in Makefile
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 12:07:15 +02:00
Michael Mayer
72da01722b Scripts: Update comment in build-libheif.sh
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 12:00:13 +02:00
Michael Mayer
5c41ffb3ab Scripts: Add inline usage information to install-libheif.sh
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 11:51:24 +02:00
Michael Mayer
42a8a9f8b7 ARMv7: Upgrade docker base images from Ubuntu 23.04 to 23.10
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 11:43:51 +02:00
Michael Mayer
0323c8ecd6 Scripts: Fix mantic base image support in install-nodejs.sh
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 11:42:47 +02:00
Michael Mayer
dcbe798772 Develop: Add mantic to install-jxl.sh and install-mariadb.sh scripts
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 11:26:27 +02:00
Michael Mayer
b8fb87a9cf Develop: Add mantic docker image build targets to Makefile
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 11:21:07 +02:00
Michael Mayer
a1aab20897 Develop: Add base image Dockerfiles for Ubuntu 23.10 (Mantic Minotaur)
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 11:16:25 +02:00
Michael Mayer
c034f092c3 Setup: Update docs for Linux installation packages
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 10:02:38 +02:00
Michael Mayer
a52ce4f9b1 Setup: Update captions in pkg/linux/README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 09:48:05 +02:00
Michael Mayer
f76013c99e Setup: Add docs for packages at https://dl.photoprism.app/pkg/linux/
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 09:40:12 +02:00
Michael Mayer
19efee9b6d Config: Change position of "http-cache-public" command flag
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 09:04:34 +02:00
Michael Mayer
5ca40cb94c CI: Update Makefiles
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-26 08:23:46 +02:00
Michael Mayer
1e7b6c6251 Make: Add pkg-amd64 and pkg-arm64 build targets
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-24 17:15:48 +02:00
graciousgrey
c40bf9a32a Translations: Update translations.json 2023-10-24 10:33:47 +02:00
Theresa Gresch
8e3cb872ad
Merge pull request #3842 from photoprismci/weblate-photoprism-frontend
Weblate: Update translations
2023-10-24 09:44:10 +02:00
Weblate
c962d1bcb2 Weblate: Update frontend translations 2023-10-24 00:02:03 +02:00
Michael Mayer
ef1a92ab80 Search: Update photo_test.js #3816
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-23 17:18:17 +02:00
Michael Mayer
bc4d543d3f Search: Improve cards view camera information #3816
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-23 17:16:57 +02:00
Carlos Abraham Pérez Marrero
50d6d6d44e
PWA: Fix app manifest logo icon sizes (#3838)
Logo icon 77.png does not exists so a warning is shown on Chrome Dev Tools when inspecting the PWA manifest
2023-10-23 11:29:39 +02:00
Michael Mayer
9abea5b55f Metadata: Ignore "SubSecModifyDate" in Exiftool JSON files #3780
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-21 17:32:42 +02:00
Michael Mayer
c2b56346b6 Search: Remove obsolete "fmin" and "fmax" filters #3818
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-21 16:33:00 +02:00
Michael Mayer
09f8a58404 Library: Stack sidecar files with vendor specific naming schemes #2983
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-21 15:02:16 +02:00
Michael Mayer
95e1260234 Frontend: Update @vvo/tzdb from v6.108.0 to v6.109.0 in package.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-21 12:05:10 +02:00
Michael Mayer
15377b1e98 Metadata: Update json_motion_test.go after upgrading photoprism/go-tz.v2
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-21 11:54:08 +02:00
Michael Mayer
a6c64a4cb1 Backend: Update photoprism/go-tz.v2 in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-21 11:48:42 +02:00
Michael Mayer
0a3a24ea33 Frontend: Update translations.pot and *.po files
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-21 03:34:47 +02:00
Michael Mayer
b6fdbb6986 Frontend: Update membership information on upgrade page
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-21 03:31:33 +02:00
Michael Mayer
67bd054f7b Metadata: Improve handling of local time values #3780
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-21 02:31:27 +02:00
Michael Mayer
60efc86649 Metadata: Use UTC offset if actual time zone is unknown #3780
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-21 00:11:11 +02:00
Michael Mayer
54f281a425 FS: Improve matching of related media files #2983
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-20 16:02:52 +02:00
Michael Mayer
a912383ede Backend: Regenerate assets/locales/el/default.po
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-20 12:56:49 +02:00
Michael Mayer
7e7764807a Frontend: Regenerate translations.pot and *.po files
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-20 12:56:24 +02:00
Michael Mayer
cca124e093 Search: Refactor GPS altitude range filter #3800
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-20 12:54:55 +02:00
Gilbert32
132237e47b
Search: Add altitude range filter (#3800)
* Add Altitude filters using IntRange

* Rename Altitude test
2023-10-20 12:23:20 +02:00
graciousgrey
f32d62cfe1 Update sponsors.md 2023-10-20 11:14:03 +02:00
Michael Mayer
29e4a5375b Frontend: Update deps in package.json and package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-20 10:44:34 +02:00
Michael Mayer
ff3bcaff30 Develop: Upgrade base image from 231015-lunar to 231020-lunar
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-20 10:29:13 +02:00
Michael Mayer
67562d9d90 Dockerfiles: Change "apt-get upgrade" to "apt-get dist-upgrade"
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-20 10:09:13 +02:00
Michael Mayer
027aca2994 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-20 10:03:52 +02:00
Lukas
8524fcc149
Adds Galaxy S10 to cameraModels (#3828) 2023-10-17 13:28:44 +02:00
graciousgrey
326ea3475a Translations: Update translations.json 2023-10-17 11:21:47 +02:00
Theresa Gresch
67b415dbc7
Merge pull request #3830 from photoprismci/weblate-photoprism-frontend
Weblate: Update translations
2023-10-17 11:11:24 +02:00
Weblate
afb01a8515 Weblate: Update frontend translations 2023-10-17 11:07:30 +02:00
graciousgrey
2570b2d482 Translations: Update translations.json 2023-10-17 09:41:53 +02:00
Theresa Gresch
cecff7374d
Merge pull request #3826 from photoprismci/weblate-photoprism-backend
Weblate: Update translations
2023-10-17 09:28:08 +02:00
Weblate
4a814f05d5 Weblate: Update backend translations 2023-10-16 18:35:40 +02:00
Theresa Gresch
5465324693
Merge pull request #3825 from photoprismci/weblate-photoprism-frontend
Weblate: Update translations
2023-10-16 17:36:01 +02:00
Weblate
6d0f3db196 Weblate: Update frontend translations 2023-10-16 17:33:08 +02:00
Cathie Integra
102348549d
Weblate: Update frontend translations (#3824)
Co-authored-by: Weblate <noreply@weblate.org>
2023-10-16 07:19:20 +02:00
Michael Mayer
029f57d1e6 Frontend: Update sidebar navigation
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-15 11:12:34 +02:00
Michael Mayer
2fed4b549c Index: Refactor optimization worker logs and queries #3124 #3742
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-15 11:02:15 +02:00
Michael Mayer
05e29170bf Backend: Refactor SQL batch size limit #3124 #3742
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-15 09:46:04 +02:00
Michael Mayer
b67043955d Config: Add trace log for performance measurement #3810
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-15 09:31:57 +02:00
Michael Mayer
c8287e462f Backend: Refactor queries for compatibility with SQLite #3124 #3742
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-15 09:31:10 +02:00
Michael Mayer
0a03071982 SQL: Refactor client config count queries #3742 #3810
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-15 08:42:24 +02:00
Michael Mayer
d71beeb903 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-15 08:11:16 +02:00
Michael Mayer
fd924f3b4c Develop: Upgrade base images to 231015
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-15 08:10:49 +02:00
Michael Mayer
afd77a6a30 HTTPS: Skip default certificate creation if TLS is disabled #3819 #3823
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-14 18:55:09 +02:00
Michael Mayer
c5dc0af24c Scripts: Add dist/remove-wait-online.sh
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-14 17:28:32 +02:00
Michael Mayer
8dc222d584 Scripts: Add dist/remove-snap.sh
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-14 17:05:37 +02:00
Michael Mayer
89bbba06ce Docker: Add "darktable" upgrade option for PHOTOPRISM_INIT #3741
Please note that this is a temporary solution that will only work with
Ubuntu 23.04 base images.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-14 14:04:38 +02:00
Michael Mayer
ef402ea2e7 HTTPS: Skip certificate creation if default TLS is disabled #3819 #3823
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-14 13:39:08 +02:00
Michael Mayer
297b3adcc2 Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-13 16:45:32 +02:00
Michael Mayer
01cb95ae74 Frontend: Update model/photo.js #2040 #3077 #3816
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-13 16:45:32 +02:00
Michael Mayer
bebf45a246 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-13 16:45:32 +02:00
graciousgrey
17b473d867 Tests: Add unit tests #3818 2023-10-13 14:02:20 +02:00
graciousgrey
170c6bb3dc Tests: Update fixtures 2023-10-13 14:00:08 +02:00
Michael Mayer
2e70152f9f Frontend: Update translations.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-13 12:52:46 +02:00
Michael Mayer
c86bbdce0c Frontend: Update deps in package.json and package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-13 12:52:29 +02:00
Cathie Integra
0a44f4f528
Weblate: Update frontend translations (#3820)
Co-authored-by: Weblate <noreply@weblate.org>
2023-10-13 12:49:31 +02:00
Michael Mayer
b7bbc59fca Upgrade: Improve error handling and messages #3813
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-13 12:43:20 +02:00
Michael Mayer
544eea50f2 Frontend: Update photo_test.js #2040 #3077 #3816
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-13 11:41:13 +02:00
Michael Mayer
09ad17d10a Cards View: Improve camera and lens information #2040 #3077 #3816
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-13 11:35:43 +02:00
Michael Mayer
57b1bb4b7d Cards View: Remove ISO number from video details #3816
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-12 16:25:08 +02:00
Michael Mayer
d28b672796 Cards View: Improve ISO number, focal len, exp. and aperture info #3816
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-12 16:20:59 +02:00
Michael Mayer
8975c781c5 Live Photos: Default to MP4 for Google HVC1 Motion Photos Playback #3814
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-12 15:20:54 +02:00
Michael Mayer
6a452bcf43 Search: Add Filters for ISO, FNumber and Focal Length Range #3818
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-12 14:53:40 +02:00
Michael Mayer
bac10302da Cards View: Add ISO, FNumber, Exposure and Focal Length #3816
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-12 11:46:03 +02:00
Michael Mayer
63f708417d ARMv7: Add install-libheif.sh to docker/develop/armv7/Dockerfile
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-11 11:55:06 +02:00
Michael Mayer
c6f462488b ARMv7: Update Ubuntu base image in docker/photoprism/armv7/Dockerfile
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-11 11:52:20 +02:00
Michael Mayer
666e6c6a6c ARMv7: Add docker-compose.armv7.yml 2023-10-11 11:46:12 +02:00
Michael Mayer
f692380dc6 ARMv7: Update docker/photoprism/armv7/Dockerfile
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-11 11:44:03 +02:00
Michael Mayer
22aee3b6c0 ARMv7: Update docker/develop/armv7/Dockerfile 2023-10-11 11:24:21 +02:00
Michael Mayer
f8efcdbd36 Backend: Update go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-11 10:59:50 +02:00
Michael Mayer
a470b908a4 Frontend: Update translations.pot and .po files
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-11 10:59:21 +02:00
Michael Mayer
aa9e598392 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-11 10:58:44 +02:00
Michael Mayer
ae5d8ae6d4 Develop: Upgrade base image from 231005-lunar to 231011-lunar
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-11 10:31:01 +02:00
Michael Mayer
2f8a8b6ab7 Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-11 10:19:32 +02:00
Michael Mayer
f087658ed0 Docs: Fix section header starts in options.yml #3812
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-11 10:10:30 +02:00
Michael Mayer
2f9792e541 PWA: Set orientation to any in generated manifest.json #3413
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-10 20:43:44 +02:00
Michael Mayer
f4dfc02a85 Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-10 17:03:24 +02:00
Michael Mayer
beb6d409ff Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-10 17:02:58 +02:00
Michael Mayer
0470899016 Metadata: Add additional camera make and model mappings #3802
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-10 16:52:00 +02:00
Michael Mayer
3d1f93f94e Albums: Redirect to matching collection if access was denied
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-10 15:16:35 +02:00
Michael Mayer
c74ad81f77 Albums: Redirect to overview if access to an album is denied
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-10 14:39:53 +02:00
Michael Mayer
4d8bf12c0b Commands: Remove unstable assertion from index_test.go
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-10 14:39:04 +02:00
Michael Mayer
3c0f1f37ad Share: Ensure that shares are always loaded in the user entity model
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-10 14:32:04 +02:00
Michael Mayer
e6b1a28bcf Metadata: Hide irrelevant values from supported data fields report
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-10 13:38:09 +02:00
graciousgrey
eb44d637f3 Tests: Add acceptance tests 2023-10-09 17:00:11 +02:00
Michael Mayer
fb419e26b7 Settings: Enable delete feature by default #3801
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-08 15:42:23 +02:00
Michael Mayer
80dd926f2d Share: Improve query validation in the search and albums API
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-07 17:33:04 +02:00
Michael Mayer
0f321b10bc Logs: Update log levels and messages
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-07 16:00:23 +02:00
Michael Mayer
ede4b3b897 Config: Refactor authentication settings #782
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-07 11:09:27 +02:00
Michael Mayer
f3fb28bdc2 Frontend: Update translations.json #3793
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-06 10:28:53 +02:00
Cathie Integra
98eba527eb
Weblate: Update frontend translations (#3794)
Co-authored-by: Weblate <noreply@weblate.org>
2023-10-06 10:28:10 +02:00
Michael Mayer
dd87d2a6f8 Settings: Prevent new users from disabling video preview images #3793
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-06 10:23:40 +02:00
Michael Mayer
10a58f2097 Metadata: Improve camera make and model string normalization #2040
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-06 09:51:40 +02:00
Michael Mayer
57c2aad29a Merge branch 'preview' into develop 2023-10-06 09:24:36 +02:00
Michael Mayer
61e7de69a4 Metadata: Improve camera make and model string normalization #2040
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-06 09:24:12 +02:00
Raymond
63515f84d7
Map VP09 to codec vp9 (#3792) 2023-10-06 04:09:07 +02:00
Michael Mayer
b0ef310b96 Metadata: Improve camera make string normalization #2040
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-06 03:33:03 +02:00
Michael Mayer
c78d12b56d Search: Limit result file types when sorting by similarity #2040
This also attempts to improve the (undocumented) randomly sorted
search results.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-06 02:57:07 +02:00
Michael Mayer
9b3efe6872 Search: Update number of expected results in filter tests #2040
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-06 02:34:21 +02:00
Michael Mayer
604849e92c Search: Include RAW files in results by default #2040
With these changes the size and type of the RAW file as well as other
details can be displayed in the Cards View. This also improves the
indexing of camera and lens metadata.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-06 02:22:48 +02:00
Michael Mayer
b45b20aa53 CI: Improve system architecture detection in build scripts
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-05 23:18:54 +02:00
Michael Mayer
1e11d8986e Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-05 22:25:20 +02:00
Michael Mayer
eb1a0150a3 Frontend: Update translations.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-05 22:22:02 +02:00
Cathie Integra
478bf67eb6
Weblate: Update frontend translations (#3791)
Co-authored-by: Weblate <noreply@weblate.org>
2023-10-05 22:21:03 +02:00
Michael Mayer
df8fa5693d Develop: Upgrade base image from 231003-lunar to 231005-lunar
Upgrades Go from v1.21.1 to v1.21.2.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-05 22:19:26 +02:00
Michael Mayer
8d7afaa476 Docs: Update screenshot URL in README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-05 21:38:37 +02:00
Michael Mayer
7106b25da1 Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-05 16:48:56 +02:00
Michael Mayer
0e26ffb064 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-05 16:48:36 +02:00
Michael Mayer
a0904c4008 Docs: Update pkg/live/README.md and pkg/video/README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-05 09:37:25 +02:00
Michael Mayer
4453d0ca8d Frontend: Update translations.pot and translations.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-04 17:48:59 +02:00
Michael Mayer
59ddf7e310 Demo: Shorten info text in upload dialog
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-04 17:48:24 +02:00
Michael Mayer
fd19bc0a5c Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-04 13:03:47 +02:00
Michael Mayer
f0ee301b28 Frontend: Update translations.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-04 13:00:43 +02:00
Cathie Integra
ffd2dd41a8
Weblate: Update frontend translations (#3787)
Co-authored-by: Weblate <noreply@weblate.org>
2023-10-04 12:59:58 +02:00
Michael Mayer
7354ea20a9 Demo: Update info text in upload dialog and translations.pot
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-04 12:49:56 +02:00
Michael Mayer
00c2dfc9f3 Frontend: Update translations.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-03 20:18:41 +02:00
Cathie Integra
ab8c71cb66
Weblate: Update frontend translations (#3786)
Co-authored-by: Weblate <noreply@weblate.org>
2023-10-03 20:18:08 +02:00
Michael Mayer
12ae011ba9 Upload: Only pre-select manually managed albums in upload dialog #3784
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-03 16:15:17 +02:00
Michael Mayer
7c86148d0a Upload: Pre-select current album when using mobile nav menu #3784
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-03 16:08:22 +02:00
Michael Mayer
dca3258112 Frontend: Update translations.pot
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-03 14:40:41 +02:00
Michael Mayer
20d50e62b8 Estimates: Show icon next to estimated metadata values in photo dialog
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-03 14:38:15 +02:00
Michael Mayer
37a2392d70 Demo: Limit number of files a user can upload
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-03 13:20:46 +02:00
Michael Mayer
71aed413e9 Demo: Update translations.pot and README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-03 12:47:44 +02:00
Michael Mayer
d3aea39a26 Demo: Remind users not to upload private or offensive content
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-03 12:43:31 +02:00
Michael Mayer
5e0ad1f4fd Develop: Upgrade base image from 230923-lunar to 231003-lunar
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-03 12:05:28 +02:00
Michael Mayer
d843cf0783 Frontend: Update deps in package.json and package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-03 11:48:57 +02:00
Michael Mayer
2f38402d9c Frontend: Update translations.json and package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-03 11:38:36 +02:00
Michael Mayer
edc408369a Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-10-03 11:38:08 +02:00
Ame Neko
8c6ce1f81b
Frontend: Fix duplicate string in zh translation (#3778) 2023-09-30 19:59:14 +02:00
Michael Mayer
ab3262a634
UX: Update cleanup icon in index.vue 2023-09-24 19:35:06 +02:00
Michael Mayer
cfe1ff3299 Config: Change "web server" to "Web server" in the docs for consistency
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-24 18:05:49 +02:00
Michael Mayer
9cfd9c0b66 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-24 17:32:09 +02:00
Michael Mayer
654a9b4130 Frontend: Add checks if variables are defined in photo.js #2040
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-24 17:31:52 +02:00
Michael Mayer
26ca084699 Videos: Cache embedded media to allow streaming and transcoding #3764
This is a follow-up improvement for the following feature requests that
have already shipped with our stable release:

- Live Photos: Add support for Samsung Motion Photos #439
- Live Photos: Add support for Google Camera Motion Photos #1739

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-24 17:13:06 +02:00
Michael Mayer
20407452f0 UX: Prefer original media files for cards view details #2040
This also adds camera lens information to the cards view details.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-24 14:11:52 +02:00
Michael Mayer
e59851350b Video: Update README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-23 17:00:40 +02:00
Michael Mayer
c38ab232fc Video: Update README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-23 16:57:14 +02:00
Michael Mayer
8b6de380d0 Develop: Upgrade base image from 230915-lunar to 230923-lunar
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-23 14:51:48 +02:00
Michael Mayer
63e672a5c9 Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-23 14:32:12 +02:00
Michael Mayer
50abd9b632 Index: Improve detection of embedded videos #439 #1739 #2788
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-23 13:37:42 +02:00
Michael Mayer
9e1d9702ae Frontend: Improve formatting of video codec names #439 #1739 #2788
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-23 12:42:54 +02:00
Michael Mayer
e5166f7120 Frontend: Update package-lock.json and translations.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-23 11:30:22 +02:00
Michael Mayer
2339197311 Live Photos: Add support for playing videos embedded in HEIC images #439
Related Issues:
- Samsung: Initial support for Motion Photos (#439)
- Google: Initial support for Motion Photos (#1739)
- Metadata: Flag Samsung/Google Motion Photos as Live Photos (#2788)

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-23 11:27:20 +02:00
Cathie Integra
04c19dd282
Weblate: Update frontend translations (#3760)
Co-authored-by: Weblate <noreply@weblate.org>
2023-09-23 08:59:07 +02:00
Michael Mayer
529103462c Index: Add native support for MP4 and Samsung/Google Motion Photos #439
Related Issues:
- Samsung: Initial support for Motion Photos (#439)
- Google: Initial support for Motion Photos (#1739)
- Metadata: Flag Samsung/Google Motion Photos as Live Photos (#2788)

Related Pull Requests:
- Live Photos: Add Support for Samsung Motion Photos (#3588)
- Samsung: Improved support for Motion Photos (#3660)
- Google: Initial support for Motion Photos (#3709)
- Google: Add support for Motion Photos (#3722)

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-22 23:59:56 +02:00
Michael Mayer
31a2cff5b6 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-22 23:33:21 +02:00
graciousgrey
4ece10b5af Tests: Improve acceptance tests 2023-09-21 20:00:56 +02:00
graciousgrey
3788a82d91 Docs: Update search form docs 2023-09-21 18:37:33 +02:00
Michael Mayer
1fab43f84b Frontend: Update deps in package.json and package-lock.json #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-21 03:13:53 +02:00
Michael Mayer
b378d14b80 Frontend: Update translations.json with latest UI translations #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-21 00:05:23 +02:00
Cathie Integra
7f24c9a4b4
Weblate: Update frontend translations (#3752)
Co-authored-by: Weblate <noreply@weblate.org>
2023-09-21 00:04:06 +02:00
Michael Mayer
bf9b21fef8 Places: Remove "map-control" class from cluster control #1187
Resolves right-to-left language layout issues.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-21 00:02:51 +02:00
Michael Mayer
5b912bb123 Frontend: Update translations.pot and translations.json #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 23:56:37 +02:00
Michael Mayer
cf0da6327f Places: Improve routing when browsing pictures in a cluster #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 23:51:57 +02:00
Michael Mayer
a865300666 Places: Add support for "label" and "category" search filters #1187
This also improves the documentation of existing search filters.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 22:07:30 +02:00
graciousgrey
0f1106eb3b Tests: Add unit tests 2023-09-20 21:48:55 +02:00
Michael Mayer
2843342d00 Logs: Reduce severity from error to warning when indexer is busy
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 21:11:51 +02:00
Michael Mayer
ce4cb6bd47 Frontend: Update deps in package-lock.json #3701
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 20:51:36 +02:00
Michael Mayer
1aff53ed3e Frontend: Update translations.json #3701
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 20:49:51 +02:00
Cathie Integra
9c30d1e789
Weblate: Update frontend translations (#3751)
Co-authored-by: Weblate <noreply@weblate.org>
2023-09-20 20:48:51 +02:00
Michael Mayer
d9a9db9c71 Archive: Change toolbar button text from "Delete" to "Delete All" #3701
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 20:37:32 +02:00
Cathie Integra
1c6b100b1f
Weblate: Update frontend translations (#3750)
Co-authored-by: Weblate <noreply@weblate.org>
2023-09-20 19:59:50 +02:00
Michael Mayer
7906dd8ce7 Places: Update translations and search toolbar tooltips #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 19:28:34 +02:00
Cathie Integra
83500af344
Weblate: Update frontend translations (#3749)
Co-authored-by: Weblate <noreply@weblate.org>
2023-09-20 19:07:04 +02:00
Michael Mayer
267430bf78 Places: Update assertion in search_photos_test.go #3558
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 18:39:39 +02:00
Michael Mayer
33bf0cede6 Places: Support sub-km distances when searching for locations #3558
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 18:37:41 +02:00
Michael Mayer
d7e21f449f Places: Change position of map style control #2106
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 18:09:29 +02:00
Michael Mayer
5e2f07ab56 Places: Change preview toolbar button icons and add tooltips #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 18:08:39 +02:00
Michael Mayer
c7d054960e Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 17:42:52 +02:00
Michael Mayer
295fe0e6fa Search: improve radius approximation for "lat" and "lng" filters #3558
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 17:42:38 +02:00
Michael Mayer
c2e38f942b Library: Trim "~" at the beginning and end of path names #3695
On Unix-like OS, this is a placeholder for the user's home directory.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 17:31:01 +02:00
Michael Mayer
8957462672 Library: Allow "#" at the beginning of path names #3695
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 17:13:25 +02:00
Michael Mayer
4d1003846c Search: Refactor "lat", "lng", and "dist" filters #1187 #3558
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 16:56:38 +02:00
Michael Mayer
d5a1526291 Places: Improve cluster control styles for mobile devices #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 13:44:40 +02:00
Michael Mayer
58b66e3954 Labels: Disable "More than 20 labels found" notification #3608
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 12:23:51 +02:00
Michael Mayer
dfd706b405 People: Disable "More than 20 people found" notification #3608
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 12:23:30 +02:00
Michael Mayer
8dbbe1c4f9 Albums: Disable "More than 20 albums found" notification #3608
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 12:23:07 +02:00
Michael Mayer
90e72bb486 Frontend: Update translations.json #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 12:13:35 +02:00
Michael Mayer
61a9ad0a19 Frontend: Update translations.pot #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 12:13:02 +02:00
Michael Mayer
06d8816a7f Search: Improve location search filters and related docs #1187 #3558
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 12:10:49 +02:00
Michael Mayer
ca20be57ce CSS: Rename maps.css to places.css for consistency #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 12:03:06 +02:00
Michael Mayer
67472eccfe Search: Disable "More than %{n} pictures found" notification #1187
It can be misleading, since the count refers to files, not pictures.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 12:02:26 +02:00
Michael Mayer
dcbb0cbfe9 Frontend: Update deps in package-lock.json #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 11:59:46 +02:00
Michael Mayer
6e282cc6b3 Places: Hide photo count notification in embedded mode #1187 #3657
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 04:02:46 +02:00
Michael Mayer
85506f9373 Places: Improve parsing and querying of GPS boundaries #1187 #3657
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-20 03:18:30 +02:00
Michael Mayer
b65362b35a Library: Explicitly escape "#" characters in path names #3695
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 23:55:56 +02:00
Michael Mayer
43655ba591 Index: Update photos in batches to be compatible with SQLite #3742
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 23:24:50 +02:00
Michael Mayer
9eb12c7183 Places: Increase size of "open in tab" button icon #1187 #3657
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 23:03:43 +02:00
Michael Mayer
cfd6149a6d Txt: Add Float32() test #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 22:07:15 +02:00
Michael Mayer
a92653d4f2 Places: Refactor cluster view overlay and backend API #1187 #3657
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 22:03:40 +02:00
Michael Mayer
405d56237e Places: Fix position of map search control #2106
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 13:13:52 +02:00
Michael Mayer
9c21f31db1 Places: Add map style and scale controls #2106
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 12:41:33 +02:00
Michael Mayer
5bc504491a SQLite: Improve inline code comments #3742
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 10:32:09 +02:00
Michael Mayer
728af5d8dc Places: Improve code comments #1187 #3657
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 10:31:40 +02:00
Michael Mayer
3299ace3e6 Places: Also update map markers on idle #1187 #3657
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 09:56:01 +02:00
Michael Mayer
edc97a68ad Library: Display checkboxes in a single row on large screens #3699
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 09:47:18 +02:00
Michael Mayer
139562e393 SQLite: Improve logging to confirm where the error is triggered #3742
see also https://github.com/photoprism/photoprism/discussions/3665

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 09:12:15 +02:00
Michael Mayer
09e09f4d23 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 09:00:51 +02:00
Michael Mayer
b93baa8ed0 Places: Refactor rendering of photos and clusters on the map #1187 #3657
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-19 08:41:37 +02:00
Michael Mayer
9fa7563f0c Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-18 15:13:03 +02:00
Michael Mayer
2bc8e8cc18 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-18 15:12:40 +02:00
graciousgrey
e737083822 Tests: Add unit tests 2023-09-15 16:26:16 +02:00
Michael Mayer
a39fed36e7 Develop: Upgrade base image from 230912-lunar to 230915-lunar
Includes WebP related security fixes and TestCafe v3.2.0.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-15 13:41:23 +02:00
Michael Mayer
27a551bbd2 OIDC: Upgrade Keycloak from 20.0 to 22.0 in the dev environment #782
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-15 13:40:28 +02:00
Michael Mayer
c7d361d61a Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-15 13:38:50 +02:00
Michael Mayer
c709567ee7 CI: Update install-nodejs.sh script
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-15 12:50:02 +02:00
Michael Mayer
e1776f7ed5 Develop: Add build-all target to Makefile
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-15 11:11:58 +02:00
Michael Mayer
cf364ac27a Docker: Fix Dockerfile link in README.md
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-15 11:11:09 +02:00
Michael Mayer
3cb4b69dac Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-15 11:10:47 +02:00
graciousgrey
001466b9fa Tests: Improve acceptance tests 2023-09-13 11:46:08 +02:00
graciousgrey
59207846bd Tests: Add unit test #3414 2023-09-12 14:35:51 +02:00
graciousgrey
f12c558f67 Tests: Refactor unit tests 2023-09-12 14:04:52 +02:00
Michael Mayer
ee97436539 UX: Adjust mosaic view layout to make better use of the available space
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-12 11:03:44 +02:00
Michael Mayer
586c224d15 Develop: Upgrade base image from 230911-lunar to 230912-lunar #3719
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-12 11:00:17 +02:00
Michael Mayer
5ae21dcddb Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-12 10:04:54 +02:00
Michael Mayer
a8595066e4 Docker: Expand supported user and group ID ranges #3719
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-12 10:00:00 +02:00
Michael Mayer
096b306420 Auth: Reduce bcrypt cost for faster login on small devices #3718
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-12 09:36:23 +02:00
graciousgrey
311288312e Tests: Add unit tests #3658 2023-09-11 17:09:54 +02:00
Michael Mayer
7cb1dcbd22 Frontend: Update deps in package.json and package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-11 12:17:15 +02:00
Michael Mayer
ab61322365 Frontend: Revert selected card color in default theme
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-11 12:14:13 +02:00
Michael Mayer
2159038c73 Develop: Upgrade base image from 230811-lunar to 230911-lunar
Includes new Go and NodeJS versions with bug fixes.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-11 11:18:05 +02:00
Michael Mayer
18efd74aab Develop: Update install-nodejs.sh script
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-11 11:09:15 +02:00
Michael Mayer
304c8e3ae6 Icons: Improve UI contrast by changing color from black to dim gray
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-11 10:43:40 +02:00
Michael Mayer
202da83f04 Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-11 10:17:32 +02:00
Michael Mayer
516eec932e Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-11 10:16:50 +02:00
Michael Mayer
63695ab801 Albums: Update frame/collage.go #3658
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-09 12:30:51 +02:00
Michael Mayer
12608a7a31 Albums: Downsize share preview image from 1600x900 to 1200x675 #3658
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-09 10:40:25 +02:00
graciousgrey
dbcaf775a8 Tests: Add acceptance test 2023-09-08 18:32:18 +02:00
Michael Mayer
71986e1565 Frontend: Update translations.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-08 17:37:43 +02:00
Michael Mayer
0ce71a9b80 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-08 17:37:30 +02:00
Michael Mayer
a30cbb19b7 Albums: Regenerate share preview after one hour and after changes #3658
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-08 17:36:56 +02:00
Cathie Integra
6463fe03be
Weblate: Update frontend translations (#3714)
Co-authored-by: Weblate <noreply@weblate.org>
2023-09-07 15:47:05 +02:00
graciousgrey
3c141ddf20 Tests: Adapt acceptance test #3701 2023-09-07 15:20:17 +02:00
Michael Mayer
d575807929 Docs: Update SPONSORS.md file
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-06 13:36:29 +02:00
Michael Mayer
207a99fab4 Docs: Update SPONSORS.md file
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-06 13:35:38 +02:00
altoing
132284eb0f
Scripts: Update install-gpu.sh (#3710) 2023-09-06 12:11:41 +02:00
Michael Mayer
4154649c76 FFmpeg: Remove deprecated "-vsync vfr" command flag #3659
See issue comments for details. This also introduces a package constant
for the default ffmpeg command name and updates the tests.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-06 11:27:24 +02:00
Michael Mayer
7197d6b651 Search: Group stacked files with same diff when sorting by similarity.
Diff is a perceptual differential hash. Grouping by photo ID should
prevent stacks of related files from being split in search results.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-04 12:28:41 +02:00
Michael Mayer
5d26bada42 Frontend: Update assertions in photo_test.js
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-04 06:36:09 +02:00
Michael Mayer
dd11d68236 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-04 06:35:34 +02:00
Michael Mayer
806f1be526 Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-04 06:35:17 +02:00
Michael Mayer
0890c547af Videos: Reduce horizontal margin of player in non-fullscreen mode
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-04 06:30:19 +02:00
Michael Mayer
93408db052 Videos: Increase margin of player in non-fullscreen mode
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-04 06:05:46 +02:00
Michael Mayer
fa3d3c326c Frontend: Update translations.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-03 17:32:40 +02:00
Cathie Integra
36119a5011
Weblate: Update frontend translations (#3700)
Co-authored-by: Weblate <noreply@weblate.org>
2023-09-03 17:31:51 +02:00
Michael Mayer
adf19db33b Live Photos: Change icon in cards view from movie to "play circle" #439
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-03 17:27:55 +02:00
Michael Mayer
4d47a5bef5 UX: Improve theme colors for better contrast
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-03 17:26:30 +02:00
Michael Mayer
c0ee909971 Index: Set appearance of video files based on their primary image #3559
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-03 16:44:30 +02:00
Michael Mayer
0e4ce95ff1 Library: Add option to run index and cache cleanup from the UI #3699
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-03 16:02:42 +02:00
Michael Mayer
ec1e3f0fb6 Frontend: Update translations.pot #272
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-03 15:48:22 +02:00
Michael Mayer
b92dd1af99 Frontend: Update translations.pot #272
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-03 15:45:55 +02:00
Michael Mayer
386bf823d7 Archive: Show number of archived pictures and improve "delete all" #272
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-03 15:44:00 +02:00
Michael Mayer
a59885cede FS: Refactor file extensions lookup table #1927
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-03 15:38:57 +02:00
Michael Mayer
6fbf73a8bd Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-03 15:33:57 +02:00
Michael Mayer
ff4b8c8cf6 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-01 20:31:05 +02:00
Michael Mayer
20d20c7fa9 Search: Allow searching for favorite:false to find other pictures
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-09-01 20:30:54 +02:00
graciousgrey
afe2190797 Tests: Add unit tests 2023-08-30 16:30:06 +02:00
Michael Mayer
ba612f6619 Frontend: Update translations.json 2023-08-24 11:32:48 +02:00
Cathie Integra
4fffc8e2d6
Weblate: Update frontend translations (#3662)
Co-authored-by: Weblate <noreply@weblate.org>
2023-08-24 10:04:48 +02:00
graciousgrey
27e8537640 Tests: Update acceptance test #3644 2023-08-22 13:06:00 +02:00
Michael Mayer
fd55b9046c Live Photos: Refactor Support for Samsung Motion Photos #439 #3588
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-22 10:48:37 +02:00
Gokce Dilek
44759d6673
Live Photos: Add Support for Samsung Motion Photos #439 #3588
* Save mp4 files generated from samsung motion photos
* Parse exiftool payload to identify videos
* Detect embedded video file type
* Extract embedded video in RelatedFiles
2023-08-22 10:21:37 +02:00
Michael Mayer
1507525ba4 People: Fix merging and renaming in connection with deleted names #3414
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-21 15:04:14 +02:00
Michael Mayer
2e367870a9 Albums: Fix generation of site URL when opening a share link #3658
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-21 11:29:41 +02:00
Michael Mayer
5c7f8d1726 Albums: Delay redirect when opening share link #3658
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-21 11:11:53 +02:00
Michael Mayer
51fc883459 Albums: Only pre-select manually manage albums in upload dialog #3644
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-21 10:44:54 +02:00
Michael Mayer
dc4eca6fd2 Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-21 10:29:50 +02:00
Michael Mayer
e4346adf13 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-21 10:29:37 +02:00
Michael Mayer
7020389a75 Albums: Fix album preview image URL in auth_share.go #3658
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-21 10:29:22 +02:00
Michael Mayer
e30c2e5f1b Upload: Pre-select current album in dialog #3644
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-21 10:10:15 +02:00
Reuben Dowle
fbd6ad2a95
Places: Fix clusters showing in the wrong location (#3657) 2023-08-21 09:34:10 +02:00
graciousgrey
80c10bb35c Tests: Add unit tests 2023-08-18 17:48:14 +02:00
Michael Mayer
a3f27c8d67 UX: Set accent color for HTML progress bar on splash screen
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-18 11:09:09 +02:00
Michael Mayer
f15ca1d7e5 Videos: Improve code comments in index_mediafile.go #926 #3588 #3559
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-18 10:08:21 +02:00
Michael Mayer
3c1b673f17 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-18 09:26:38 +02:00
Michael Mayer
d7f70c2a0c Forms: Update notes in search_photos.go and search_photos_geo.go #3639
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-18 09:26:10 +02:00
Michael Mayer
c6bb28f60d Videos: Refactor File.UpdateVideoInfos() method #926 #3588 #3559
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-18 09:12:38 +02:00
Michael Mayer
69f15924ab Videos: Improve code comments in index_mediafile.go #926 #3588 #3559
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-18 08:57:22 +02:00
graciousgrey
32c0d0ae66 Commands: Improve search filter documentation 2023-08-18 08:53:53 +02:00
Reuben Dowle
fc7269480c
Places: Fix cluster update callback function (#3648)
* Places: Avoid concurrently calculating markers

* Places: Ignore duplicated cluster IDs
2023-08-18 08:19:46 +02:00
Michael Mayer
5deedbf47c Places: Show 4 previews for clusters >= 10 pictures #1187 #2596 #3636
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-17 15:10:39 +02:00
Michael Mayer
736d1a9090 Places: Skip cluster update if nothing has changed #1187 #2596 #3636
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-17 14:20:22 +02:00
Michael Mayer
9b282e4ce0 Places: Improve code comments #1187 #2596 #3636
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-17 11:42:36 +02:00
Michael Mayer
ae52117557 Places: Also update clusters on 'resize' and 'idle' #1187 #2596 #3636
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-17 11:38:20 +02:00
Michael Mayer
09f324a1d9 Places: Don't also update clusters on 'move' #1187 #2596 #3636
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-16 20:42:48 +02:00
Michael Mayer
a0f16b60b5 Places: Also update clusters on 'move' #1187 #2596 #3636
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-16 20:34:50 +02:00
Michael Mayer
c7dae2383f Places: Reduce radius of photo cluster markers #1187 #2596 #3636
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-16 19:09:17 +02:00
Michael Mayer
730cbeaf2c Places: Remove paint from clusters layer #1187 #2596 #3636
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-16 14:53:05 +02:00
Michael Mayer
b85c2a2dab Places: Attach moveend handler before calling search() #1187 #2596 #3636
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-16 14:17:34 +02:00
Michael Mayer
874371b046 Places: Refactor rendering of clusters on the map #1187 #2596 #3636
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-16 13:34:13 +02:00
Reuben Dowle
f1c7378fbf
Places: Fix markers not updating correctly (#3636) 2023-08-16 12:56:38 +02:00
Michael Mayer
be0fdc1774 Search: Add "scan:false" filter to find photos that are not scans #3589
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-16 10:34:55 +02:00
Michael Mayer
cb9d601dfa Frontend: Update deps in package.json and package-lock.json #1187 #2596
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-16 10:32:15 +02:00
Michael Mayer
5b4b57e3bf Config: Improve docs and tests for Unix socket support #2337 #3595
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-16 10:14:19 +02:00
Michael Mayer
91cc358fc5 Clean: Shorten error log sanitization function name #439 #3588
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-15 17:05:55 +02:00
Michael Mayer
3212724aae Live Photos: Update cards.vue #3559
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-15 15:19:12 +02:00
Michael Mayer
3581aafc29 Entities: Update file_test.go #3559
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-15 15:17:09 +02:00
Michael Mayer
3f6cb27497 Live Photos: Show correct image and video dimensions #3559
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-15 14:51:32 +02:00
Michael Mayer
5822a26b8c Metadata: Add test for mov video JSON files #3559
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-15 14:19:08 +02:00
Michael Mayer
8ed9f3f409 WebDAV: Improve service discovery tests #3579
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-15 13:01:50 +02:00
Michael Mayer
a287830d1f Videos: Allow setting a lower TTL for caching video content #3631
Adds the new "--http-video-maxage SECONDS" config option.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-15 11:06:43 +02:00
Michael Mayer
5da5ee72a7 Frontend: Reformat cards.vue and mosaic.vue #1187
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-15 09:15:17 +02:00
Michael Mayer
7f13218229 Logs: Add LogError() func to sanitize error messages #439 #3588
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-15 08:12:52 +02:00
Michael Mayer
cc7c3e3a64 Places: Refactor Cluster View Styles #1187 #2596
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-14 15:24:47 +02:00
Michael Mayer
11beec835c Media: Move CreateExifToolJson() out of RelatedFiles() method #439 #3588
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-14 13:09:45 +02:00
Michael Mayer
cb66022925 Index: Refactor JSON sidecar creation #439 #3588
A JSON sidecar should now exist in the MediaFile.RelatedFiles() method
so that the information can subsequently be used to extract an embedded
video from the media file, if necessary.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-14 12:51:22 +02:00
Michael Mayer
c82a4b2287 HTTP: Refactor Unix socket support #2337 #3595
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-14 10:43:05 +02:00
graciousgrey
68fea5954d Update SPONSORS.md 2023-08-14 10:09:13 +02:00
Silver Bullet
2bf50082f5
Backend: Support listening on Unix Socket #2337 #3595
When HTTP listening address starts with unix: and contains /, listen
at given path instead of a TCP socket.

TLS or AutoTLS will not work since there is no TLS layer when using
the unix domain socket.
2023-08-14 10:00:35 +02:00
Michael Mayer
77b5996640 Frontend: Refactor styles and add Chrome theme
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-14 09:52:51 +02:00
graciousgrey
71c30e4218 Tests: Add unit tests 2023-08-11 14:48:28 +02:00
Michael Mayer
34066da2de Backend: Update deps in go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-11 14:30:59 +02:00
Michael Mayer
104f87ea6d Fronend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-11 14:30:36 +02:00
Michael Mayer
7d8325ef6b Develop: Upgrade base image from 230720-lunar to 230811-lunar
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-11 14:30:18 +02:00
Michael Mayer
4e05270385 CI: Update Go install script to fix latest version query
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-11 14:15:13 +02:00
graciousgrey
e6679e6c50 Tests: Add unit tests 2023-08-09 15:56:16 +02:00
graciousgrey
b194188e91 Tests: Add class for testing 2023-08-09 13:35:53 +02:00
graciousgrey
26ad621bd5 Tests: Add acceptance test #272 2023-08-08 13:57:31 +02:00
graciousgrey
b32e3cd244 Tests: Add unit test 2023-08-08 13:40:12 +02:00
graciousgrey
f9ea868582 Tests: Add unit tests 2023-08-08 13:01:48 +02:00
graciousgrey
470694e774 Tests: Add unit tests 2023-08-07 16:27:45 +02:00
Michael Mayer
16c78767b2 Metadata: Parse Caption and Caption-Abstract as Description #3567
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-07 14:56:47 +02:00
graciousgrey
eece27a0ae Tests: Add unit tests 2023-08-07 14:46:32 +02:00
graciousgrey
9f17d64ea3 Tests: Add unit tests 2023-08-07 14:46:32 +02:00
Michael Mayer
54326361b5 Frontend: Update translations.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-07 14:46:15 +02:00
Michael Mayer
eecce8c743 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-07 14:46:00 +02:00
Sönke Joppien
2a83345d11
Mention that translations should be added through Weblate (#3606)
* Mention translations in contributing section

* Mention Weblate
2023-08-07 14:44:53 +02:00
Sönke Joppien
65a5dd2cb4
Update German translation (#3605)
* Update German translation

* Update "Feature Request" to "Verbesserungsvorschlag"
2023-08-05 18:59:21 +02:00
graciousgrey
a3f253c9de Tests: Add unit tests 2023-08-04 17:34:28 +02:00
graciousgrey
a3bb4a2f0e Tests: Add unit tests 2023-08-04 16:23:08 +02:00
graciousgrey
63daf10bf9 Tests: Add unit tests 2023-08-02 16:44:12 +02:00
graciousgrey
5ba00e74e5 Tests: Add RefID to session fixtures 2023-08-02 16:42:17 +02:00
graciousgrey
ca40954796 Tests: Add unit tests for wildcard search #2050 2023-08-02 16:00:57 +02:00
Michael Mayer
82dac4b7db Metadata: Change order of titles source fields #3567
This is a workaround to avoid character encoding issues, see:
- https://github.com/photoprism/photoprism/discussions/3567
- https://exiftool.org/TagNames/IPTC.html

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-01 15:12:06 +02:00
Michael Mayer
3c7b1b29a7 Backend: Update tidwall/gjson in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-01 14:28:25 +02:00
Michael Mayer
098d39f9dc Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-08-01 14:28:05 +02:00
Reuben Dowle
a58318f304
UX: Don't process all features for clusters exceeding 100 photos. (#3577)
* Performance: Don't process all features when creating cluster marker..

Fixes performance issues with large numbers of photos

* Performance: Only update markers after final render, rather than repeatedly during zoom, pan, etc

* UX: Spread out photos used to generate cluster marker.

This gives a slightly more representative view of cluster than taking the first
couple of photos which are often all very similar.
2023-08-01 14:06:09 +02:00
Michael Mayer
31578a3806 UX: Revert outer padding of moasic view from pa-1 to pa-2 #3572
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-29 13:02:31 +02:00
Michael Mayer
36bac7ab48 Faces: Add POST REST endpoint to manually create new file markers #1548
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-27 19:13:00 +02:00
graciousgrey
83473f6f93 Tests: Adapt acceptance test to changes #2596 2023-07-27 17:30:11 +02:00
graciousgrey
098255c741 Tests: Add unit tests #2596 2023-07-27 16:09:23 +02:00
graciousgrey
40b1f1f5cd Tests: Update testcafe config 2023-07-27 12:58:23 +02:00
Michael Mayer
bc18507a14 Setup: Update stack config file for Portainer #1696
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-26 18:01:11 +02:00
Michael Mayer
ec09145fef Setup: Update stack config and env file for Portainer #1696
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-26 17:42:32 +02:00
Michael Mayer
348442d355 Setup: Add stack config and env file for Portainer #1696
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-26 17:19:56 +02:00
graciousgrey
6b8a75f29f Tests: Add unit tests 2023-07-26 16:38:48 +02:00
graciousgrey
b59b954d1f Tests: Add unit tests 2023-07-26 16:38:48 +02:00
Michael Mayer
2c33a34ac3 Metadata: Update list of special words in txt package
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-26 12:20:49 +02:00
Michael Mayer
6c1df15f34 Backend: Run "make fmt" #3566
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-25 19:15:09 +02:00
Gokce Dilek
1df12bd5c9
Albums: Refresh updated timestamp when photos are added (#3566)
Related Issue:
- #3080
2023-07-25 19:10:01 +02:00
graciousgrey
ff25b5f755 Tests: Add unit tests 2023-07-25 18:42:18 +02:00
graciousgrey
1fcef1bec4 Tests: Update test command in makefile 2023-07-24 17:09:38 +02:00
Michael Mayer
97e9ad9c1e UX: Restore 4px border radius for thumbnails in edit dialog #3572
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-24 16:26:11 +02:00
graciousgrey
8f165c653f Tests: Add acceptance test 2023-07-24 16:25:52 +02:00
Michael Mayer
fd0ef7825e UX: Add 4px border radius for thumbnails in mosaic view #3572
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-24 16:14:26 +02:00
graciousgrey
c9d1413ddb Tests: Add more unit tests #3512 2023-07-24 15:02:38 +02:00
Michael Mayer
ef1487ddd2 Frontend: Update translations.pot #3572
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-24 14:54:43 +02:00
Michael Mayer
22bb6634af UX: Use less padding in mosaic view in favor of larger thumbnails #3572
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-24 14:52:38 +02:00
graciousgrey
33b08f15e5 Tests: Add unit tests 2023-07-24 14:02:18 +02:00
graciousgrey
69d302248c Tests: Add unit tests 2023-07-24 13:38:02 +02:00
Heiko Mathes
60d280430e
Places: Add Cluster View (#2596)
* enable clustering on all zoom levels

* add latmin, latmax, lngmin and lngmax to search api

* open prefiltered search when clicking a cluster on the map

* start moving places pictures to overlay

* update scrollbar hide todo comment

* add todo comments for cluster view

* start implementing possitbility to close cluster view via back button

* move selected cluster to single query param

* improve back-navigation of cluster-view

* remove outdated comment

* start showing preview-images in clusters

* cleanup some cluster-code in places

* use rounded squares instead of circles so more from the image can be seen

* try improving map visibility by adding borders

* add counter bubble to places view

* remove obsolete comment

* remove console.log

* add todo comment to fix search on cluster-view open

* fix closing a cluster resetting the places-filter

* prevent old cluster markers from being visible while zooming

* prevent cluster-previews from being smaller than single-image-previews

* make cluster-preview-images fill the whole available area and scale them to their bounding box

* increase clusterRadius to reduce likelyhood of clusters colliding on the map

* update obsolete todo comment

* try making cluster view look less broken for small clusters. elements in photo-view use block-relative percentages based on viewport-relative media queries

* remove seemingly unrequired code

* fix cluster view after "pages"-components moved to "page" (singular)
2023-07-24 10:12:22 +02:00
Michael Mayer
ea8ee0938c UX: Trim Lat / Lng and split values with regex #3568 #3571
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-24 08:40:27 +02:00
Michael Mayer
2a002eca78 API: Remove unnecessary log message from batch delete handler #272
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-23 18:32:02 +02:00
Michael Mayer
6b9aeda48f Themes: Darken "Mint" clipboard menu colors
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-23 18:00:22 +02:00
Michael Mayer
ad3da85ecb UX: Add Delete All button to archive page toolbar #272
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-23 17:57:48 +02:00
Michael Mayer
90eac1966b Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-23 16:11:40 +02:00
Michael Mayer
bf0ad09557 UX: Refactor pasting lat / lng in a single operation #3568
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-23 16:07:02 +02:00
Reuben Dowle
ce13135743
Frontend: Allow paste of lat/lng in single operation (#3568)
This speeds up the workflow when pasting location found in external mapping application
2023-07-23 15:48:43 +02:00
Alex Kirk
5ca3329e2d
XMP: Add support for reading fstop:favorite flag (#1873)
* Add support for fstop:favorite in XMP files
* Incorporate suggestions
2023-07-23 15:43:32 +02:00
Michael Mayer
062495b6f2 Albums: Refresh UpdateAt after adding entries #3080 #3566
This requires adding unit tests and checking if there are other
situations where the content of an album is changed by the user
and therefore updating the timestamp would be appropriate.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-23 14:26:14 +02:00
Michael Mayer
20df14e9d1 Frontend: Add "Mint" theme and move default styles to themes/default.css
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-21 09:55:57 +02:00
graciousgrey
b5b13b0fbb Tests: Add unit tests 2023-07-20 20:06:27 +02:00
graciousgrey
4727f769d2 Tests: Add unit tests 2023-07-20 20:02:02 +02:00
graciousgrey
0817f1876d Tests: Add unit tests 2023-07-20 20:02:02 +02:00
graciousgrey
e1364f288c Tests: Add unit tests 2023-07-20 20:02:02 +02:00
Michael Mayer
74f6954a90 UX: Add click handler to open image in labels tab #3532
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-20 17:16:27 +02:00
Michael Mayer
7c70ac0126 UX: Improve tab styles and layout in photo editing dialog #3532
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-20 15:35:35 +02:00
Reuben Dowle
3d828a7df0
Frontend: Show thumbnail in the Labels tab of the edit dialog (#3532) 2023-07-20 09:17:46 +02:00
Michael Mayer
84a4c3c57e Frontend: Update deps in package.json and package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-20 09:03:02 +02:00
Michael Mayer
70ad541c01 Develop: Update install-go-tools.sh #3555
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-20 08:36:01 +02:00
Michael Mayer
68b40babfa Develop: Upgrade base image from 230715-lunar to 230720-lunar #3555
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-20 08:30:17 +02:00
Gokce Dilek
0d243d5ea4
Develop: Add Delve to install-go-tools.sh script (#3555) 2023-07-20 08:22:57 +02:00
Michael Mayer
73fa7bbe86 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-19 00:21:07 +02:00
Michael Mayer
3e2f215786 Video: Update cloud docker-compose.yml config example #3466 #3498 #3549
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-19 00:15:51 +02:00
Michael Mayer
63cebc7409 Video: Update docker-compose.yml config examples #3466 #3498 #3549
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-19 00:12:23 +02:00
Michael Mayer
4931889b5e Auth: Improve privilege level change detection #3512
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-18 23:35:10 +02:00
Michael Mayer
08070978cf Videos: Don't skip transcoding QuickTime files, only MP4 AVC #3525
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-18 21:23:56 +02:00
Michael Mayer
3b7b551cca Media: Add test for creating thumbs from broken JPEG #2721
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-18 17:23:39 +02:00
Michael Mayer
19b4490232 Video: Update docker-compose.yml config examples #3466 #3498 #3549
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-18 16:53:07 +02:00
Michael Mayer
7b9b2ae0c6 Auth: Delete user sessions after a permission level change #3512
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-18 16:38:10 +02:00
Michael Mayer
44603857fa Config: Shorten video transcoding flag descriptions #3466 #3498 #3549
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-18 16:20:25 +02:00
Michael Mayer
3cf1c699df Video: Refactor FFmpeg Transcoding Size Limit #3466 #3498 #3549
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-18 15:15:04 +02:00
Michael Mayer
8c0955dd41 Develop: Remove exif-read-tool from install-go-tools.sh script
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-15 15:29:14 +02:00
Michael Mayer
101d8d7baf Frontend: Update translations.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-15 15:25:51 +02:00
Michael Mayer
cc5ff21b4a Video: Add transcoding libs and improve error handling #3466
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-15 15:17:41 +02:00
Michael Mayer
5e645b9bfd Frontend: Update deps in package.json and package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-15 12:30:46 +02:00
Ikko Eltociear Ashimine
47e619a828
Frontend: Fix typo in cards.vue (#3545)
mutliple -> multiple
2023-07-15 12:21:32 +02:00
Michael Mayer
7dc02e4288 Develop: Upgrade base image from 230712-lunar to 230715-lunar #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-15 12:20:27 +02:00
Michael Mayer
651782eb4d Security: Add PHOTOPRISM_DEFAULT_TLS config option #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-15 12:01:06 +02:00
graciousgrey
5fb9e95217 Tests: Add unit test #3493 2023-07-14 11:51:28 +02:00
Michael Mayer
0e93bd8aa2 Auth: Ensure clipboard is cleared on logout and privilege change #3512
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-14 09:14:57 +02:00
Michael Mayer
781bb0b04f Frontend: Update deps in package-lock.json 2023-07-14 08:02:34 +02:00
Michael Mayer
40a018532a Config: Update install.bat Windows batch script #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 14:08:40 +02:00
Michael Mayer
f225191659 Config: Update uninstall.bat Windows batch script #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 14:07:08 +02:00
Michael Mayer
7e680a67cb Config: Download update.bat in windows batch script examples #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 14:05:14 +02:00
Michael Mayer
d574abff33 Config: Improve windows batch script examples #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 14:01:58 +02:00
Michael Mayer
00acfb5e45 Config: Increase wait time in install.bat file example #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 13:57:22 +02:00
Michael Mayer
5176380a56 Config: Add "@echo off" to windows batch file examples #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 13:55:42 +02:00
Michael Mayer
bc0593637a Config: Update windows (un)install.bat examples #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 13:53:35 +02:00
Michael Mayer
131ccbab15 Config: Update windows uninstall.bat example #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 13:45:41 +02:00
Michael Mayer
89842c8442 Config: Update windows install.bat example #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 13:44:51 +02:00
Michael Mayer
c172e06c04 Config: Update windows install.bat example #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 13:30:57 +02:00
Michael Mayer
09bd901272 Config: Update windows batch file examples #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 13:27:01 +02:00
Michael Mayer
38e8e1b7ca Config: Update docker/windows/install.bat example #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 13:11:32 +02:00
Michael Mayer
b9a7cb4fec Config: Update docker/windows/install.bat example #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 12:51:58 +02:00
Michael Mayer
14b415dcba Config: Add PHOTOPRISM_DISABLE_TLS to docker-compose.yml examples #3509
This commit also adds example batch files for Windows users.

Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-07-13 12:50:03 +02:00
Michael Mayer
945737b01e Backend: Update deps in go.mod and go.sum 2023-07-12 18:18:55 +00:00
Michael Mayer
dbc2887447 Develop: Update base image from 230628 tp 230712 2023-07-12 15:57:08 +02:00
Michael Mayer
91c006a63c Backend: Update go.mod 2023-07-12 15:51:30 +02:00
Michael Mayer
bd27ad08e7 Frontend: Update translations.json and package-lock.json 2023-07-12 15:50:51 +02:00
Cathie Integra
ff5f3ddeb1
Weblate: Update frontend translations (#3538)
Co-authored-by: Weblate <noreply@weblate.org>
2023-07-10 18:18:45 +02:00
Michael Mayer
c3fd96adf7
Update CODE_OF_CONDUCT.md 2023-07-05 12:59:07 +02:00
Michael Mayer
11e7d3f0d1 JPEG: Refactor error correction for broken files #2463 #2721 #3363
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-29 19:28:56 +02:00
Michael Mayer
e5db48b300 Search: Update geo filter form notes #3493
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-29 18:40:24 +02:00
Michael Mayer
5041b7f211 Search: Enhance "geo" filter to find pictures without coordinates #3493
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-29 18:35:02 +02:00
Michael Mayer
2f21b4fec5 Auth: Refactor login page footer #98
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-29 18:12:45 +02:00
Michael Mayer
1c9dad9cdd Backend: Update deps in go.mod
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-29 13:27:52 +02:00
Michael Mayer
da8e5a9af0 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-29 13:27:35 +02:00
Luca Carlon
9a699f234d
Metadata: When parsing dates from exiftool, remap year 0 to 1 (#2508)
Year 0 is frequently used in exiftool but is not accepted in the Go time
package. time package uses year 1 for "zero" dates instead. Therefore,
remap year 0 from exiftool to year 1.
2023-06-29 10:36:16 +02:00
Daniel Albers
da61515c4a
JPEG: Automatically fix files with missing EOI marker (#2721) 2023-06-29 10:34:51 +02:00
Michael Mayer
03f92bc0db Config: Fix expected return value in config_ffmpeg_test.go #3510
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-29 10:17:04 +02:00
Lukas
19ac83dd20
Config: Downscale videos based on largest dimension (#3510)
* Adds resolution limit

* Fixes 2 video filters and makes the env variable work

* Adds FFMPEG_RESOLUTION to all the docker-compose files

* Makes the resolution based on the longer side

* Fixes failing test
2023-06-29 10:07:47 +02:00
Michael Mayer
2dc9e142ef Init: Shorten install-https.sh script #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-28 17:10:07 +02:00
Michael Mayer
6ebbab9b17 Develop: Upgrade base image from 230607-lunar to 230628-lunar #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-28 17:05:41 +02:00
Michael Mayer
8e43186454 Config: Generate default HTTPS/TLS certificate on first startup #3509
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-28 16:50:04 +02:00
Michael Mayer
a6d3eee331 Config: Fix FFmpegResolution() func and related test #3498
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-28 16:45:53 +02:00
graciousgrey
9b3917dd00 Tests: Add unit tests 2023-06-28 16:12:11 +02:00
graciousgrey
19699c49c0 Tests: Add unit tests 2023-06-28 16:07:06 +02:00
Lukas
83d10ea00e
Config: Add video transcoding resolution option (#3498)
* Adds resolution limit

* Fixes 2 video filters and makes the env variable work

* Adds FFMPEG_RESOLUTION to all the docker-compose files
2023-06-28 15:22:52 +02:00
Bur0k
08ba1e1c05 Switched general YYYYMMDD Filter to a WhatsApp specific [IMG,VID]-YYYYMMDD-WA* Filter 2023-06-27 22:00:07 +02:00
Bur0k
37c40c9b3d Accept YYYYMMDD format in filenames (e.g. WhatsApp) 2023-06-27 22:00:07 +02:00
Michael Mayer
7910994166
Update README.md 2023-06-27 20:30:03 +02:00
Michael Mayer
111d0a2ae6 Tests: Reorder imports in fileinfo_test.go
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-27 20:25:50 +02:00
Michael Mayer
b4dffec0a3 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-27 19:47:54 +02:00
graciousgrey
5f103681fb Tests: Add unit tests 2023-06-27 19:27:34 +02:00
graciousgrey
29462bce13 Tests: Add unit tests 2023-06-27 19:20:11 +02:00
graciousgrey
e1ddaa7c0b Tests: Add unit tests 2023-06-27 18:41:36 +02:00
graciousgrey
f53619b004 Tests: Improve acceptance tests 2023-06-26 17:17:38 +02:00
graciousgrey
1e55e5b1d9 Tests: Add unit tests for pkg/clean 2023-06-26 15:57:56 +02:00
graciousgrey
186d1f26e7 Tests: Add unit tests for internal/entity 2023-06-26 15:55:05 +02:00
graciousgrey
43e98cc687 Tests: Add unit tests for pkg/authn 2023-06-26 15:54:23 +02:00
Michael Mayer
accb17bec9 Auth: Update invalid role log message in user entity
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-26 11:46:32 +02:00
graciousgrey
17242fb079 Tests: Add unit tests #3482 2023-06-23 18:38:54 +02:00
graciousgrey
749d4b6d7e Tests: Add unit tests #3482 2023-06-23 18:38:22 +02:00
Michael Mayer
bae5eace8f Frontend: Update translations.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-20 13:21:59 +02:00
Weblate
0818d5995c Weblate: Update frontend translations 2023-06-20 13:21:25 +02:00
Michael Mayer
96e0981c31 Backend: Update deps in go.mod and go.sum
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-20 13:19:54 +02:00
Michael Mayer
ee6e6c66e3 Frontend: Update deps in package-lock.json
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-20 13:19:40 +02:00
Michael Mayer
31f9b88495 UX: Improve video player size, background and error handling #1307 #3372
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-20 13:19:25 +02:00
Michael Mayer
87b6d72477 CLI: Improve length check in "photoprism passwd" command #3482
Signed-off-by: Michael Mayer <michael@photoprism.app>
2023-06-19 17:24:02 +02:00
Michael Mayer
054a0764c5 Revert "Videos: Play videos in full size (work in progress)"
This reverts commit df0d93b1e4.
2023-06-19 15:47:13 +02:00
627 changed files with 45938 additions and 23805 deletions

View file

@ -2,7 +2,7 @@
**By using the software and services we provide, you agree to our [Terms of Service](https://www.photoprism.app/terms), including our [Privacy Policy](https://www.photoprism.app/privacy) and the following Code of Conduct. It explains the "dos and donts" when interacting with our team and other community members.**
*Last Updated: May 13, 2023*
*Last Updated: July 5, 2023*
## Rules
@ -18,7 +18,7 @@ Because we want our Code of Conduct to be easy to understand and implement, we h
Not everyone has experience with Open Source communities and intuitively knows what is acceptable. In that case, the following guidelines and examples are meant to provide a quick overview and help you avoid the most common pitfalls:
(a) Do not [feel entitled](https://www.reddit.com/r/photoprism/comments/13emwf0/did_you_guys_really_nerf_hardware_transcoding/) to free software, support, or advice, especially if you are not a contributor, [member](https://link.photoprism.app/membership), or paying customer. Don't expect contributors to report to you and [meet deadlines](https://docs.photoprism.app/developer-guide/code-quality/#go-slow-before-you-go-fast) as if they work for you or owe you something, even if you donated a small amount. We also ask that you do not use GitHub Issues or other development tools to start general discussions, get technical support, or express personal opinions.
(a) Do not [feel entitled](https://www.reddit.com/r/photoprism/comments/13emwf0/did_you_guys_really_nerf_hardware_transcoding/) to free software, support, or advice, especially if you are not a contributor, [member](https://link.photoprism.app/membership), or business customer. Don't expect contributors to [give status reports](https://docs.photoprism.app/developer-guide/code-quality/#go-slow-before-you-go-fast) as if they work for you or owe you something, even if you have donated a small amount. We also ask that you do not use GitHub Issues or other development tools to start general discussions, get technical support, or express personal opinions.
(b) Honor **Rule &#35;2**, [read the docs](https://docs.photoprism.app) and [determine the cause of your problem](https://docs.photoprism.app/getting-started/troubleshooting/) before opening invalid bug reports, starting a public "shitstorm", or insulting other community members in our chat rooms. Aside from being annoying for everyone, it also keeps our team from working on features and enhancements that users like you are waiting for.

View file

@ -14,7 +14,7 @@ Feel free to [contact us](https://www.photoprism.app/contact) with anything that
You can also contribute by…
* answering questions in the [Community Chat](https://link.photoprism.app/chat), on [Reddit](https://link.photoprism.app/reddit) and in [GitHub Discussions](https://link.photoprism.app/discussions)
* helping us [translate](https://docs.photoprism.app/developer-guide/translations-weblate/) the Web UI
* helping us [translate](https://docs.photoprism.app/developer-guide/translations-weblate/) the Web UI on [Weblate](https://translate.photoprism.app/)
* [conducting research](https://github.com/photoprism/photoprism/issues?q=is%3Aopen+is%3Aissue+label%3Aresearch) and [improving the documentation](https://github.com/photoprism/photoprism/issues?q=is%3Aopen+is%3Aissue+label%3Adocs)
* publishing tutorials, blog posts, and podcasts
* voting for us on pages like:

View file

@ -1,7 +1,9 @@
# Ubuntu 23.04 (Lunar Lobster)
FROM photoprism/develop:230607-lunar
# Ubuntu 23.10 (Mantic Minotaur)
FROM photoprism/develop:231206-mantic
## Alternative Environments:
# FROM photoprism/develop:armv7 # ARMv7 (32bit)
# FROM photoprism/develop:lunar # Ubuntu 23.04 (Lunar Lobster)
# FROM photoprism/develop:jammy # Ubuntu 22.04 LTS (Jammy Jellyfish)
# FROM photoprism/develop:impish # Ubuntu 21.10 (Impish Indri)
# FROM photoprism/develop:bookworm # Debian 12 (Bookworm)
@ -13,4 +15,4 @@ WORKDIR "/go/src/github.com/photoprism/photoprism"
# Copy source to image.
COPY . .
COPY --chown=root:root /scripts/dist/ /scripts/
COPY --chown=root:root /scripts/dist/ /scripts/

113
Makefile
View file

@ -22,7 +22,7 @@ BUILD_ARCH ?= $(shell scripts/dist/arch.sh)
JS_BUILD_PATH ?= $(shell realpath "./assets/static/build")
# Install parameters.
INSTALL_PATH ?= $(BUILD_PATH)/photoprism-$(BUILD_TAG)-$(shell echo $(BUILD_OS) | tr '[:upper:]' '[:lower:]')-$(BUILD_ARCH)
INSTALL_PATH ?= $(BUILD_PATH)/photoprism-ce_$(BUILD_TAG)-$(shell echo $(BUILD_OS) | tr '[:upper:]' '[:lower:]')-$(BUILD_ARCH)
DESTDIR ?= $(INSTALL_PATH)
DESTUID ?= 1000
DESTGID ?= 1000
@ -54,6 +54,7 @@ all: dep build-js
dep: dep-tensorflow dep-js
biuld: build
build: build-go
build-all: build-go build-js
pull: docker-pull
test: test-js test-go
test-go: reset-sqlite run-test-go
@ -107,19 +108,23 @@ clean:
[ ! -d "$(JS_BUILD_PATH)" ] || rm -rf --preserve-root $(JS_BUILD_PATH)
tar.gz:
$(info Creating tar.gz archives from the directories in "$(BUILD_PATH)"...)
find "$(BUILD_PATH)" -maxdepth 1 -mindepth 1 -type d -exec tar --exclude='.[^/]*' -C {} -czf {}.tar.gz . \;
find "$(BUILD_PATH)" -maxdepth 1 -mindepth 1 -type d -name "photoprism*" -exec tar --exclude='.[^/]*' -C {} -czf {}.tar.gz . \;
pkg: pkg-amd64 pkg-arm64
pkg-amd64:
docker run --rm -u $(UID) --platform=amd64 --pull=always -v ".:/go/src/github.com/photoprism/photoprism" --entrypoint "" photoprism/develop:jammy make all install tar.gz
pkg-arm64:
docker run --rm -u $(UID) --platform=arm64 --pull=always -v ".:/go/src/github.com/photoprism/photoprism" --entrypoint "" photoprism/develop:jammy make all install tar.gz
install:
$(info Installing in "$(DESTDIR)"...)
@[ ! -d "$(DESTDIR)" ] || (echo "ERROR: Install path '$(DESTDIR)' already exists!"; exit 1)
mkdir --mode=$(INSTALL_MODE) -p $(DESTDIR)
env TMPDIR="$(BUILD_PATH)" ./scripts/dist/install-tensorflow.sh $(DESTDIR)
rm -rf --preserve-root $(DESTDIR)/include
(cd $(DESTDIR) && mkdir -p bin lib assets config config/examples)
(cd $(DESTDIR) && mkdir -p bin lib assets)
./scripts/build.sh prod "$(DESTDIR)/bin/$(BINARY_NAME)"
rsync -r -l --safe-links --exclude-from=assets/.buildignore --chmod=a+r,u+rw ./assets/ $(DESTDIR)/assets
wget -O $(DESTDIR)/assets/static/img/wallpaper/welcome.jpg https://cdn.photoprism.app/wallpaper/welcome.jpg
wget -O $(DESTDIR)/assets/static/img/preview.jpg https://cdn.photoprism.app/img/preview.jpg
cp internal/config/testdata/*.yml $(DESTDIR)/config/examples
chown -R $(INSTALL_USER) $(DESTDIR)
chmod -R $(INSTALL_MODE) $(DESTDIR)
chmod -R $(INSTALL_MODE_BIN) $(DESTDIR)/bin $(DESTDIR)/lib
@ -141,9 +146,9 @@ acceptance-sqlite-restart:
rm -rf storage/acceptance/originals/2011
rm -rf storage/acceptance/originals/2013
rm -rf storage/acceptance/originals/2017
./photoprism -p -c "./storage/acceptance/config-sqlite" --test start -d
./photoprism --auth-mode="public" -c "./storage/acceptance/config-sqlite" --test start -d
acceptance-sqlite-stop:
./photoprism -p -c "./storage/acceptance/config-sqlite" --test stop
./photoprism --auth-mode="public" -c "./storage/acceptance/config-sqlite" --test stop
acceptance-auth-sqlite-restart:
cp -f storage/acceptance/backup.db storage/acceptance/index.db
cp -f storage/acceptance/config-sqlite/settingsBackup.yml storage/acceptance/config-sqlite/settings.yml
@ -316,7 +321,7 @@ docker-develop: docker-develop-latest
docker-develop-all: docker-develop-latest docker-develop-other
docker-develop-latest: docker-develop-ubuntu
docker-develop-debian: docker-develop-bookworm docker-develop-bookworm-slim
docker-develop-ubuntu: docker-develop-lunar docker-develop-lunar-slim
docker-develop-ubuntu: docker-develop-mantic docker-develop-mantic-slim
docker-develop-other: docker-develop-debian docker-develop-bullseye docker-develop-bullseye-slim docker-develop-buster
docker-develop-bookworm:
docker pull --platform=amd64 debian:bookworm-slim
@ -334,8 +339,9 @@ docker-develop-bullseye-slim:
docker pull --platform=amd64 debian:bullseye-slim
docker pull --platform=arm64 debian:bullseye-slim
scripts/docker/buildx-multi.sh develop linux/amd64,linux/arm64 bullseye-slim /bullseye-slim
develop-armv7: docker-develop-armv7
docker-develop-armv7:
docker pull --platform=arm ubuntu:jammy
docker pull --platform=arm ubuntu:mantic
scripts/docker/buildx.sh develop linux/arm armv7 /armv7
docker-develop-buster:
docker pull --platform=amd64 golang:1-buster
@ -356,13 +362,21 @@ docker-develop-jammy-slim:
docker-develop-lunar:
docker pull --platform=amd64 ubuntu:lunar
docker pull --platform=arm64 ubuntu:lunar
scripts/docker/buildx-multi.sh develop linux/amd64,linux/arm64 lunar /lunar "-t photoprism/develop:latest -t photoprism/develop:ubuntu"
scripts/docker/buildx-multi.sh develop linux/amd64,linux/arm64 lunar /lunar
docker-develop-lunar-slim:
docker pull --platform=amd64 ubuntu:lunar
docker pull --platform=arm64 ubuntu:lunar
scripts/docker/buildx-multi.sh develop linux/amd64,linux/arm64 lunar-slim /lunar-slim
docker-develop-mantic:
docker pull --platform=amd64 ubuntu:mantic
docker pull --platform=arm64 ubuntu:mantic
scripts/docker/buildx-multi.sh develop linux/amd64,linux/arm64 mantic /mantic "-t photoprism/develop:latest -t photoprism/develop:ubuntu"
docker-develop-mantic-slim:
docker pull --platform=amd64 ubuntu:mantic
docker pull --platform=arm64 ubuntu:mantic
scripts/docker/buildx-multi.sh develop linux/amd64,linux/arm64 mantic-slim /mantic-slim
unstable: docker-unstable
docker-unstable: docker-unstable-lunar
docker-unstable: docker-unstable-mantic
docker-unstable-jammy:
docker pull --platform=amd64 photoprism/develop:jammy
docker pull --platform=amd64 photoprism/develop:jammy-slim
@ -371,13 +385,17 @@ docker-unstable-lunar:
docker pull --platform=amd64 photoprism/develop:lunar
docker pull --platform=amd64 photoprism/develop:lunar-slim
scripts/docker/buildx-multi.sh photoprism linux/amd64 unstable-ce /lunar
docker-unstable-mantic:
docker pull --platform=amd64 photoprism/develop:mantic
docker pull --platform=amd64 photoprism/develop:mantic-slim
scripts/docker/buildx-multi.sh photoprism linux/amd64 unstable-ce /mantic
preview: docker-preview-ce
docker-preview: docker-preview-ce
docker-preview-all: docker-preview-latest docker-preview-other
docker-preview-ce: docker-preview-lunar
docker-preview-ce: docker-preview-mantic
docker-preview-latest: docker-preview-ubuntu
docker-preview-debian: docker-preview-bookworm
docker-preview-ubuntu: docker-preview-lunar
docker-preview-ubuntu: docker-preview-mantic
docker-preview-other: docker-preview-debian docker-preview-bullseye
docker-preview-arm: docker-preview-arm64 docker-preview-armv7
docker-preview-bookworm:
@ -388,7 +406,7 @@ docker-preview-bookworm:
scripts/docker/buildx-multi.sh photoprism linux/amd64,linux/arm64 preview-bookworm /bookworm "-t photoprism/photoprism:preview-ce-debian"
docker-preview-armv7:
docker pull --platform=arm photoprism/develop:armv7
docker pull --platform=arm ubuntu:jammy
docker pull --platform=arm ubuntu:mantic
scripts/docker/buildx.sh photoprism linux/arm preview-armv7 /armv7
docker-preview-arm64:
docker pull --platform=arm64 photoprism/develop:lunar
@ -406,6 +424,12 @@ docker-preview-buster:
docker pull --platform=amd64 debian:buster-slim
docker pull --platform=arm64 debian:buster-slim
scripts/docker/buildx-multi.sh photoprism linux/amd64,linux/arm64 preview-buster /buster
docker-preview-impish:
docker pull --platform=amd64 photoprism/develop:impish
docker pull --platform=arm64 photoprism/develop:impish
docker pull --platform=amd64 ubuntu:impish
docker pull --platform=arm64 ubuntu:impish
scripts/docker/buildx-multi.sh photoprism linux/amd64,linux/arm64 preview-impish /impish
docker-preview-jammy:
docker pull --platform=amd64 photoprism/develop:jammy
docker pull --platform=amd64 photoprism/develop:jammy-slim
@ -418,18 +442,18 @@ docker-preview-lunar:
docker pull --platform=arm64 photoprism/develop:lunar
docker pull --platform=arm64 photoprism/develop:lunar-slim
scripts/docker/buildx-multi.sh photoprism linux/amd64,linux/arm64 preview-ce /lunar
docker-preview-impish:
docker pull --platform=amd64 photoprism/develop:impish
docker pull --platform=arm64 photoprism/develop:impish
docker pull --platform=amd64 ubuntu:impish
docker pull --platform=arm64 ubuntu:impish
scripts/docker/buildx-multi.sh photoprism linux/amd64,linux/arm64 preview-impish /impish
docker-preview-mantic:
docker pull --platform=amd64 photoprism/develop:mantic
docker pull --platform=amd64 photoprism/develop:mantic-slim
docker pull --platform=arm64 photoprism/develop:mantic
docker pull --platform=arm64 photoprism/develop:mantic-slim
scripts/docker/buildx-multi.sh photoprism linux/amd64,linux/arm64 preview-ce /mantic
release: docker-release
docker-release: docker-release-latest
docker-release-all: docker-release-latest docker-release-other
docker-release-latest: docker-release-ubuntu
docker-release-debian: docker-release-bookworm
docker-release-ubuntu: docker-release-lunar
docker-release-ubuntu: docker-release-mantic
docker-release-other: docker-release-debian docker-release-bullseye
docker-release-arm: docker-release-arm64 docker-release-armv7
docker-release-bookworm:
@ -440,7 +464,7 @@ docker-release-bookworm:
scripts/docker/buildx-multi.sh photoprism linux/amd64,linux/arm64 ce-bookworm /bookworm "-t photoprism/photoprism:ce-debian"
docker-release-armv7:
docker pull --platform=arm photoprism/develop:armv7
docker pull --platform=arm ubuntu:jammy
docker pull --platform=arm ubuntu:mantic
scripts/docker/buildx.sh photoprism linux/arm armv7 /armv7
docker-release-arm64:
docker pull --platform=arm64 photoprism/develop:lunar
@ -458,6 +482,12 @@ docker-release-buster:
docker pull --platform=amd64 debian:buster-slim
docker pull --platform=arm64 debian:buster-slim
scripts/docker/buildx-multi.sh photoprism linux/amd64,linux/arm64 ce-buster /buster
docker-release-impish:
docker pull --platform=amd64 photoprism/develop:impish
docker pull --platform=arm64 photoprism/develop:impish
docker pull --platform=amd64 ubuntu:impish
docker pull --platform=arm64 ubuntu:impish
scripts/docker/buildx-multi.sh photoprism linux/amd64,linux/arm64 ce-impish /impish
docker-release-jammy:
docker pull --platform=amd64 photoprism/develop:jammy
docker pull --platform=amd64 photoprism/develop:jammy-slim
@ -470,12 +500,12 @@ docker-release-lunar:
docker pull --platform=arm64 photoprism/develop:lunar
docker pull --platform=arm64 photoprism/develop:lunar-slim
scripts/docker/buildx-multi.sh photoprism linux/amd64,linux/arm64 ce /lunar
docker-release-impish:
docker pull --platform=amd64 photoprism/develop:impish
docker pull --platform=arm64 photoprism/develop:impish
docker pull --platform=amd64 ubuntu:impish
docker pull --platform=arm64 ubuntu:impish
scripts/docker/buildx-multi.sh photoprism linux/amd64,linux/arm64 ce-impish /impish
docker-release-mantic:
docker pull --platform=amd64 photoprism/develop:mantic
docker pull --platform=amd64 photoprism/develop:mantic-slim
docker pull --platform=arm64 photoprism/develop:mantic
docker pull --platform=arm64 photoprism/develop:mantic-slim
scripts/docker/buildx-multi.sh photoprism linux/amd64,linux/arm64 ce /mantic
start-local:
$(DOCKER_COMPOSE) -f docker-compose.local.yml up -d --wait
stop-local:
@ -502,8 +532,8 @@ terminal-latest:
$(DOCKER_COMPOSE) -f docker-compose.latest.yml exec photoprism-latest bash
logs-latest:
$(DOCKER_COMPOSE) -f docker-compose.latest.yml logs -f photoprism-latest
docker-local: docker-local-lunar
docker-local-all: docker-local-lunar docker-local-jammy docker-local-bookworm docker-local-bullseye docker-local-buster
docker-local: docker-local-mantic
docker-local-all: docker-local-mantic docker-local-lunar docker-local-jammy docker-local-bookworm docker-local-bullseye docker-local-buster
docker-local-bookworm:
docker pull photoprism/develop:bookworm
docker pull photoprism/develop:bookworm-slim
@ -516,6 +546,10 @@ docker-local-buster:
docker pull photoprism/develop:buster
docker pull debian:buster-slim
scripts/docker/build.sh photoprism ce-buster /buster "-t photoprism/photoprism:local"
docker-local-impish:
docker pull photoprism/develop:impish
docker pull ubuntu:impish
scripts/docker/build.sh photoprism ce-impish /impish "-t photoprism/photoprism:local"
docker-local-jammy:
docker pull photoprism/develop:jammy
docker pull ubuntu:jammy
@ -524,12 +558,12 @@ docker-local-lunar:
docker pull photoprism/develop:lunar
docker pull ubuntu:lunar
scripts/docker/build.sh photoprism ce-lunar /lunar "-t photoprism/photoprism:local"
docker-local-impish:
docker pull photoprism/develop:impish
docker pull ubuntu:impish
scripts/docker/build.sh photoprism ce-impish /impish "-t photoprism/photoprism:local"
docker-local-develop: docker-local-develop-lunar
docker-local-develop-all: docker-local-develop-lunar docker-local-develop-jammy docker-local-develop-bookworm docker-local-develop-bullseye docker-local-develop-buster docker-local-develop-impish
docker-local-mantic:
docker pull photoprism/develop:mantic
docker pull ubuntu:mantic
scripts/docker/build.sh photoprism ce-mantic /mantic "-t photoprism/photoprism:local"
docker-local-develop: docker-local-develop-mantic
docker-local-develop-all: docker-local-develop-mantic docker-local-develop-lunar docker-local-develop-jammy docker-local-develop-bookworm docker-local-develop-bullseye docker-local-develop-buster docker-local-develop-impish
docker-local-develop-bookworm:
docker pull debian:bookworm-slim
scripts/docker/build.sh develop bookworm /bookworm
@ -539,15 +573,18 @@ docker-local-develop-bullseye:
docker-local-develop-buster:
docker pull golang:1-buster
scripts/docker/build.sh develop buster /buster
docker-local-develop-impish:
docker pull ubuntu:impish
scripts/docker/build.sh develop impish /impish
docker-local-develop-jammy:
docker pull ubuntu:jammy
scripts/docker/build.sh develop jammy /jammy
docker-local-develop-lunar:
docker pull ubuntu:lunar
scripts/docker/build.sh develop lunar /lunar
docker-local-develop-impish:
docker pull ubuntu:impish
scripts/docker/build.sh develop impish /impish
docker-local-develop-mantic:
docker pull ubuntu:mantic
scripts/docker/build.sh develop mantic /mantic
docker-ddns:
docker pull golang:alpine
scripts/docker/buildx-multi.sh ddns linux/amd64,linux/arm64 $(BUILD_DATE)

View file

@ -2,20 +2,19 @@ PhotoPrism: Browse Your Life in Pictures
========================================
[![License: AGPL](https://img.shields.io/badge/license-AGPL-blue.svg)](https://docs.photoprism.app/license/agpl/)
[![GitHub contributors](https://img.shields.io/github/contributors/photoprism/photoprism.svg)](https://www.photoprism.app/about/team)
[![Documentation](https://img.shields.io/badge/read-the%20docs-4aa087.svg)](https://docs.photoprism.app/)
[![Community Chat](https://img.shields.io/badge/chat-on%20gitter-4aa087.svg)](https://link.photoprism.app/chat)
[![GitHub Discussions](https://img.shields.io/badge/ask-%20on%20github-4d6a91.svg)](https://link.photoprism.app/discussions)
[![Twitter](https://img.shields.io/badge/follow-@photoprism_app-00acee.svg)](https://link.photoprism.app/twitter)
[![Reddit](https://img.shields.io/badge/join-/r/photoprism-EC5800.svg)](https://link.photoprism.app/reddit)
[![Bluesky Social](https://dl.photoprism.app/img/badges/badge-follow-photoprism-bsky-social.svg)](https://photoprism.bsky.social/)
[![Mastodon](https://dl.photoprism.app/img/badges/badge-floss-social.svg)](https://floss.social/@photoprism)
PhotoPrism® is an AI-Powered Photos App for the [Decentralized Web](https://en.wikipedia.org/wiki/Decentralized_web).
It makes use of the latest technologies to tag and find pictures automatically without getting in your way.
You can run it at home, on a private server, or in the cloud.
![](https://dl.photoprism.app/img/ui/desktop-1000px.jpg)
![](https://dl.photoprism.app/img/ui/search-cards-view.jpg)
To get a first impression, you are welcome to play with our [public demo](https://try.photoprism.app/). Be careful not to upload any private pictures.
To get a first impression, you are welcome to play with our [public demo](https://try.photoprism.app/). Please be careful not to upload any private, unlawful or offensive pictures.
## Feature Overview ##
@ -39,20 +38,12 @@ Being completely [**self-funded and independent**](https://link.photoprism.app/m
## Getting Started ##
<img align="right" width="25%" src="https://www.photoprism.app/user/pages/01.home/03._screenshots/iphone-maps-hybrid-540px.png">
Step-by-step installation instructions for our self-hosted [community edition](https://www.photoprism.app/get) can be found
on [docs.photoprism.app](https://docs.photoprism.app/getting-started/) -
all you need is a Web browser and [Docker](https://docs.docker.com/get-docker/) to run the server.
It is available for Mac, Linux, and Windows.
Step-by-step [installation instructions](https://docs.photoprism.app/getting-started/) for our self-hosted [community edition](https://link.photoprism.app/personal-editions) can be found on [docs.photoprism.app](https://docs.photoprism.app/getting-started/) - all you need is a Web browser and [Docker](https://docs.docker.com/get-docker/) to run the server. It is available for Mac, Linux, and Windows.
The [stable version](https://docs.photoprism.app/release-notes/) and development
preview have been built into a single [multi-arch image](https://link.photoprism.app/docker-hub) for 64-bit AMD, Intel,
and ARM processors. That means, [Raspberry Pi](https://docs.photoprism.app/getting-started/raspberry-pi/) 3 / 4 owners can pull
from the same repository, enjoy the exact same functionality, and can follow the regular
[installation instructions](https://docs.photoprism.app/getting-started/docker-compose/)
after going through a short list of [requirements](https://docs.photoprism.app/getting-started/raspberry-pi/).
The [stable releases](https://docs.photoprism.app/release-notes/) and [development preview](https://docs.photoprism.app/getting-started/updates/#development-preview) are available as a [multi-arch image](https://link.photoprism.app/docker-hub) for 64-bit AMD, Intel, and ARM processors.
That means, [Raspberry Pi](https://docs.photoprism.app/getting-started/raspberry-pi/) and Apple Silicon users enjoy the exact same functionality and can follow the same [installation steps](https://docs.photoprism.app/getting-started/docker-compose/).
Existing users are advised to update their `docker-compose.yml` config based on our examples
available at [dl.photoprism.app/docker](https://dl.photoprism.app/docker/).
See our [Getting Started FAQ](https://docs.photoprism.app/getting-started/faq/#how-can-i-install-photoprism-without-docker) for alternative installation methods, for example using the [*tar.gz* packages](https://dl.photoprism.app/pkg/linux/README.html) we provide.
## Support Our Mission 💎 ##
@ -83,9 +74,8 @@ Please also leave [a star](https://github.com/photoprism/photoprism/stargazers)
## Getting Support ##
Visit [docs.photoprism.app/user-guide](https://docs.photoprism.app/user-guide/) to learn how to [sync](https://docs.photoprism.app/user-guide/sync/webdav/), [organize](https://docs.photoprism.app/user-guide/library/), and [share](https://docs.photoprism.app/user-guide/share/) your pictures. If you need help installing our software at home, you can [join us on Reddit](https://link.photoprism.app/reddit), ask in our [Community Chat](https://link.photoprism.app/chat), or post your question in [GitHub Discussions](https://link.photoprism.app/discussions).
Common problems can be quickly diagnosed and solved using the [Troubleshooting Checklists](https://docs.photoprism.app/getting-started/troubleshooting/) in [Getting Started](https://docs.photoprism.app/getting-started/). Eligible [members](https://link.photoprism.app/membership) are also welcome to [email us for technical support](https://www.photoprism.app/contact) and personalized advice.
Visit [docs.photoprism.app/user-guide](https://docs.photoprism.app/user-guide/) to learn how to [sync](https://docs.photoprism.app/user-guide/sync/webdav/), [organize](https://docs.photoprism.app/user-guide/library/), and [share](https://docs.photoprism.app/user-guide/share/) your pictures. If you need help installing our software at home, you are welcome to post your question in [GitHub Discussions](https://link.photoprism.app/discussions) or ask in our [Community Chat](https://link.photoprism.app/chat).
Common problems can be quickly diagnosed and solved using our [Troubleshooting Checklists](https://docs.photoprism.app/getting-started/troubleshooting/). Eligible [members](https://link.photoprism.app/membership) are also welcome to email us for technical support and advice.
## Upcoming Features and Enhancements ##
@ -113,7 +103,7 @@ Feel free to contact us at [hello@photoprism.app](mailto:hello@photoprism.app) w
## Every Contribution Makes a Difference ##
We welcome [contributions](CONTRIBUTING.md) of any kind, including blog posts, tutorials, testing, writing documentation, and pull requests. Our [Developer Guide](https://docs.photoprism.app/developer-guide/) contains all the information necessary for you to get started.
We welcome [contributions](CONTRIBUTING.md) of any kind, including blog posts, tutorials, translations, testing, writing documentation, and pull requests. Our [Developer Guide](https://docs.photoprism.app/developer-guide/) contains all the information necessary for you to get started.
----

View file

@ -20,6 +20,10 @@ You are [welcome to contact us](https://www.photoprism.app/contact) for change r
**Vitold Romanovski** (May 2023)
**Aaron C. de Bruyn** (September 2023)
[**Patrick Kvaksrud**](https://github.com/Kvaksrud) (October 2023)
## Gold Sponsors ##
[**Simen Eriksen**](https://github.com/dennorske) (GitHub Sponsors, December 2019)
@ -68,6 +72,10 @@ You are [welcome to contact us](https://www.photoprism.app/contact) for change r
[**Yongho Lee**](https://github.com/lyh16) (Patreon, May 2023)
**Albert R** (Patreon, August 2023)
**Peter Galbavy** (Patreon, November 2023)
## Infrastructure Sponsors ##
Our project infrastructure is provided by the following companies:

View file

@ -0,0 +1,70 @@
[{
"SourceFile": "beach_sand.jpg",
"ExifToolVersion": 12.56,
"FileName": "beach_sand.jpg",
"Directory": ".",
"FileSize": 105321,
"FileModifyDate": "2023:06:20 04:43:41+00:00",
"FileAccessDate": "2023:08:06 16:38:50+00:00",
"FileInodeChangeDate": "2023:08:04 05:10:37+00:00",
"FilePermissions": 100644,
"FileType": "JPEG",
"FileTypeExtension": "JPG",
"MIMEType": "image/jpeg",
"JFIFVersion": "1 2",
"ExifByteOrder": "MM",
"Make": "Apple",
"Model": "iPhone SE",
"XResolution": 72,
"YResolution": 72,
"ResolutionUnit": 2,
"Software": "10.2.1",
"ModifyDate": "2017:02:15 14:13:40",
"YCbCrPositioning": 1,
"ExposureTime": 0.0004940711462,
"ExposureProgram": 2,
"ISO": 25,
"ExifVersion": "0231",
"DateTimeOriginal": "2017:02:15 14:13:40",
"CreateDate": "2017:02:15 14:13:40",
"ComponentsConfiguration": "1 2 3 0",
"ApertureValue": 2.19999999733148,
"MeteringMode": 5,
"Flash": 16,
"FocalLength": 4.2,
"SubSecTimeOriginal": 249,
"SubSecTimeDigitized": 249,
"FlashpixVersion": "0100",
"ColorSpace": 65535,
"SensingMethod": 2,
"ExposureMode": 0,
"WhiteBalance": 0,
"SceneCaptureType": 0,
"LensModel": "iPhone SE back camera 4.15mm f/2.2",
"GPSVersionID": "2 3 0 0",
"GPSLatitudeRef": "S",
"GPSLongitudeRef": "E",
"GPSAltitudeRef": 1,
"CurrentIPTCDigest": "804bedc723e0e6cd3a41d0a44b074d19",
"DocumentNotes": "https://flickr.com/e/Rl7qi7oH%2BSEGDuwWBbZYaBQMEB5oNfPvQ6m3aMrPQ64%3D",
"ApplicationRecordVersion": 4,
"ImageWidth": 640,
"ImageHeight": 480,
"EncodingProcess": 2,
"BitsPerSample": 8,
"ColorComponents": 3,
"YCbCrSubSampling": "2 2",
"Aperture": 2.19999999733148,
"ImageSize": "640 480",
"Megapixels": 0.3072,
"ShutterSpeed": 0.0004940711462,
"SubSecCreateDate": "2017:02:15 14:13:40.249",
"SubSecDateTimeOriginal": "2017:02:15 14:13:40.249",
"GPSAltitude": -1.990417522,
"GPSLatitude": -29.2824777777778,
"GPSLongitude": 31.4436361111111,
"FocalLength35efl": 4.2,
"GPSPosition": "-29.2824777777778 31.4436361111111",
"LightValue": 15.2580006188259,
"LensID": "iPhone SE back camera 4.15mm f/2.2"
}]

Binary file not shown.

View file

@ -0,0 +1,153 @@
[{
"SourceFile": "iphone_15_pro.heic",
"ExifToolVersion": 12.40,
"FileName": "iphone_15_pro.heic",
"Directory": ".",
"FileSize": 886825,
"FileModifyDate": "2023:10:31 11:48:48+01:00",
"FileAccessDate": "2023:10:31 11:51:22+01:00",
"FileInodeChangeDate": "2023:10:31 11:50:11+01:00",
"FilePermissions": 100664,
"FileType": "HEIC",
"FileTypeExtension": "HEIC",
"MIMEType": "image/heic",
"MajorBrand": "heic",
"MinorVersion": "0.0.0",
"CompatibleBrands": ["mif1","MiHE","MiPr","miaf","MiHB","heic"],
"HandlerType": "pict",
"PrimaryItemReference": 49,
"MetaImageSize": "0 1287 4032 3024",
"XMPToolkit": "XMP Core 6.0.0",
"HDRGainMapHeadroom": 3.847906,
"HDRGainMapVersion": 131072,
"ExifByteOrder": "MM",
"Make": "Apple",
"Model": "iPhone 15 Pro",
"Orientation": 6,
"XResolution": 72,
"YResolution": 72,
"ResolutionUnit": 2,
"Software": 17.1,
"ModifyDate": "2023:10:31 11:44:43",
"HostComputer": "iPhone 15 Pro",
"ExposureTime": 0.01666666667,
"FNumber": 2.2,
"ExposureProgram": 2,
"ISO": 400,
"ExifVersion": "0232",
"DateTimeOriginal": "2023:10:31 11:44:43",
"CreateDate": "2023:10:31 11:44:43",
"OffsetTime": "+01:00",
"OffsetTimeOriginal": "+01:00",
"OffsetTimeDigitized": "+01:00",
"ShutterSpeedValue": 0.0165679999782223,
"ApertureValue": 2.20000000038133,
"BrightnessValue": 2.15000162,
"ExposureCompensation": 0,
"MeteringMode": 5,
"Flash": 16,
"FocalLength": 2.22,
"SubjectArea": "2015 1511 2323 1330",
"RunTimeFlags": 1,
"RunTimeValue": 154455128730208,
"RunTimeScale": 1000000000,
"RunTimeEpoch": 0,
"AccelerationVector": "-0.004213878416 -1.002046108 -0.01470538881",
"Warning": "[minor] Bad format (16) for MakerNotes entry 10",
"SubSecTimeOriginal": 432,
"SubSecTimeDigitized": 432,
"ColorSpace": 65535,
"ExifImageWidth": 4032,
"ExifImageHeight": 3024,
"SensingMethod": 2,
"SceneType": 1,
"ExposureMode": 0,
"WhiteBalance": 0,
"FocalLengthIn35mmFormat": 14,
"LensInfo": "2.22 9 1.779999971 2.8",
"LensMake": "Apple",
"LensModel": "iPhone 15 Pro back triple camera 2.22mm f/2.2",
"CompositeImage": 2,
"GPSLatitudeRef": "N",
"GPSLongitudeRef": "E",
"GPSAltitudeRef": 0,
"GPSTimeStamp": "10:44:43",
"GPSSpeedRef": "K",
"GPSSpeed": 0,
"GPSImgDirectionRef": "T",
"GPSImgDirection": 101.3112946,
"GPSDestBearingRef": "T",
"GPSDestBearing": 101.3112946,
"GPSDateStamp": "2023:10:31",
"GPSHPositioningError": 14.275587,
"ProfileCMMType": "appl",
"ProfileVersion": 1024,
"ProfileClass": "mntr",
"ColorSpaceData": "RGB ",
"ProfileConnectionSpace": "XYZ ",
"ProfileDateTime": "2022:01:01 00:00:00",
"ProfileFileSignature": "acsp",
"PrimaryPlatform": "APPL",
"CMMFlags": 0,
"DeviceManufacturer": "APPL",
"DeviceModel": "",
"DeviceAttributes": "0 0",
"RenderingIntent": 0,
"ConnectionSpaceIlluminant": "0.9642 1 0.82491",
"ProfileCreator": "appl",
"ProfileID": "236 253 163 142 56 133 71 195 109 180 189 79 122 218 24 47",
"ProfileDescription": "Display P3",
"ProfileCopyright": "Copyright Apple Inc., 2022",
"MediaWhitePoint": "0.96419 1 0.82489",
"RedMatrixColumn": "0.51512 0.2412 -0.00105",
"GreenMatrixColumn": "0.29198 0.69225 0.04189",
"BlueMatrixColumn": "0.1571 0.06657 0.78407",
"RedTRC": "(Binary data 32 bytes, use -b option to extract)",
"ChromaticAdaptation": "1.04788 0.02292 -0.0502 0.02959 0.99048 -0.01706 -0.00923 0.01508 0.75168",
"BlueTRC": "(Binary data 32 bytes, use -b option to extract)",
"GreenTRC": "(Binary data 32 bytes, use -b option to extract)",
"HEVCConfigurationVersion": 1,
"GeneralProfileSpace": 0,
"GeneralTierFlag": 0,
"GeneralProfileIDC": 3,
"GenProfileCompatibilityFlags": 1879048192,
"ConstraintIndicatorFlags": "176 0 0 0 0 0",
"GeneralLevelIDC": 90,
"MinSpatialSegmentationIDC": 0,
"ParallelismType": 0,
"ChromaFormat": 1,
"BitDepthLuma": 8,
"BitDepthChroma": 8,
"AverageFrameRate": 0,
"ConstantFrameRate": 0,
"NumTemporalLayers": 1,
"TemporalIDNested": 0,
"ImageWidth": 4032,
"ImageHeight": 3024,
"ImageSpatialExtent": "4032 3024",
"Rotation": 270,
"ImagePixelDepth": 8,
"AuxiliaryImageType": "urn:com:apple:photo:2020:aux:hdrgainmap",
"MediaDataSize": 882139,
"MediaDataOffset": 4686,
"RunTimeSincePowerUp": 154455.128730208,
"Aperture": 2.2,
"ImageSize": "4032 3024",
"Megapixels": 12.192768,
"ScaleFactor35efl": 6.30630630630631,
"ShutterSpeed": 0.01666666667,
"SubSecCreateDate": "2023:10:31 11:44:43.432+01:00",
"SubSecDateTimeOriginal": "2023:10:31 11:44:43.432+01:00",
"SubSecModifyDate": "2023:10:31 11:44:43+01:00",
"GPSAltitude": 50.15664187,
"GPSDateTime": "2023:10:31 10:44:43Z",
"GPSLatitude": 52.4596055555556,
"GPSLongitude": 13.3218416666667,
"CircleOfConfusion": "0.00476447847114884",
"FOV": 104.250120754113,
"FocalLength35efl": 14,
"GPSPosition": "52.4596055555556 13.3218416666667",
"HyperfocalDistance": 0.470184057236731,
"LightValue": 6.18189764281985,
"LensID": "iPhone 15 Pro back triple camera 2.22mm f/2.2"
}]

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 MiB

View file

@ -0,0 +1,82 @@
[{
"SourceFile": "/go/src/github.com/photoprism/photoprism/storage/import/samsung-motion-photo.jpg",
"ExifToolVersion": 12.56,
"FileName": "samsung-motion-photo.jpg",
"Directory": "/go/src/github.com/photoprism/photoprism/storage/import",
"FileSize": 7221645,
"FileModifyDate": "2023:07:27 02:03:13+00:00",
"FileAccessDate": "2023:08:13 17:11:04+00:00",
"FileInodeChangeDate": "2023:08:13 17:11:02+00:00",
"FilePermissions": 100644,
"FileType": "JPEG",
"FileTypeExtension": "JPG",
"MIMEType": "image/jpeg",
"ExifByteOrder": "II",
"Make": "samsung",
"Model": "SM-G973F",
"Orientation": 1,
"XResolution": 72,
"YResolution": 72,
"ResolutionUnit": 2,
"Software": "G973FXXU4CTC9",
"ModifyDate": "2020:04:23 18:33:41",
"YCbCrPositioning": 1,
"ExposureTime": 0.0007575757576,
"FNumber": 2.4,
"ExposureProgram": 2,
"ISO": 50,
"ExifVersion": "0220",
"DateTimeOriginal": "2020:04:23 18:33:41",
"CreateDate": "2020:04:23 18:33:41",
"ShutterSpeedValue": 0.999475026346474,
"ApertureValue": 2.39495740923786,
"BrightnessValue": 22.58,
"ExposureCompensation": 0,
"MaxApertureValue": 2.39495740923786,
"MeteringMode": 2,
"Flash": 0,
"FocalLength": 4.32,
"ColorSpace": 1,
"ExifImageWidth": 4032,
"ExifImageHeight": 3024,
"ExposureMode": 0,
"WhiteBalance": 0,
"DigitalZoomRatio": 1,
"FocalLengthIn35mmFormat": 26,
"SceneCaptureType": 0,
"ImageUniqueID": "L12XLLD01VM",
"GPSLatitudeRef": "N",
"GPSLongitudeRef": "W",
"Compression": 6,
"ThumbnailOffset": 888,
"ThumbnailLength": 50555,
"XMPToolkit": "Adobe XMP Core 5.1.0-jc003",
"MicroVideo": 1,
"MicroVideoVersion": 1,
"MicroVideoOffset": 4535831,
"MicroVideoPresentationTimestampUs": -1,
"ImageWidth": 4032,
"ImageHeight": 3024,
"EncodingProcess": 0,
"BitsPerSample": 8,
"ColorComponents": 3,
"YCbCrSubSampling": "2 2",
"TimeStamp": "2020:04:23 17:33:41.809+00:00",
"MCCData": 234,
"EmbeddedVideoType": "MotionPhoto_Data",
"EmbeddedVideoFile": "(Binary data 4535775 bytes, use -b option to extract)",
"Aperture": 2.4,
"ImageSize": "4032 3024",
"Megapixels": 12.192768,
"ScaleFactor35efl": 6.01851851851852,
"ShutterSpeed": 0.0007575757576,
"ThumbnailImage": "(Binary data 50555 bytes, use -b option to extract)",
"GPSLatitude": 51.5049828,
"GPSLongitude": -0.0787347997222222,
"CircleOfConfusion": "0.00499230176602706",
"FOV": 69.3903656740024,
"FocalLength35efl": 26,
"GPSPosition": "51.5049828 -0.0787347997222222",
"HyperfocalDistance": 1.55759815100044,
"LightValue": 13.8923910258672
}]

View file

@ -2,16 +2,16 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-02-09 12:51+0000\n"
"PO-Revision-Date: 2023-02-09 13:13+0000\n"
"Last-Translator: Anonymous <noreply@weblate.org>\n"
"POT-Creation-Date: 2023-03-09 13:14+0000\n"
"PO-Revision-Date: 2023-10-16 16:35+0000\n"
"Last-Translator: dtsolakis <dtsola@eranet.gr>\n"
"Language-Team: none\n"
"Language: el\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.15.2\n"
"X-Generator: Weblate 5.0.2\n"
#: messages.go:94
msgid "Something went wrong, try again"
@ -19,7 +19,7 @@ msgstr "Κάτι πήγε στραβά, δοκιμάστε ξανά"
#: messages.go:95
msgid "Unable to do that"
msgstr "Δεν είναι δυνατόν να το κάνετε αυτό"
msgstr "Αυτό δεν είναι εφικτό"
#: messages.go:96
msgid "Changes could not be saved"
@ -334,7 +334,7 @@ msgstr "Επεξεργασία μεταφόρτωσης..."
#: messages.go:172
msgid "Upload has been processed"
msgstr "%s έχει αποκατασταθεί"
msgstr "Η φόρτωση έχει ολοκληρωθεί"
#: messages.go:173
msgid "Selection approved"

View file

@ -1,8 +1,8 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: ci@photoprism.app\n"
"POT-Creation-Date: 2023-02-09 12:51+0000\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-03-09 13:14+0000\n"
"PO-Revision-Date: 2023-06-07 08:37+0000\n"
"Last-Translator: leosamuele221 <leosamuele221@gmail.com>\n"
"Language-Team: Italian <https://translate.photoprism.app/projects/photoprism/"

View file

@ -1,8 +1,8 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: ci@photoprism.app\n"
"POT-Creation-Date: 2023-02-09 12:51+0000\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-03-09 13:14+0000\n"
"PO-Revision-Date: 2023-06-07 08:37+0000\n"
"Last-Translator: Admin <hello@photoprism.app>\n"
"Language-Team: Slovak <https://translate.photoprism.app/projects/photoprism/"

BIN
assets/static/img/404.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

View file

@ -26,8 +26,8 @@
<div class="splash-logo">
{{template "logo.gohtml" .}}
</div>
<progress id="progress" class="html-progress" max="100"></progress>
<progress id="progress" class="html-progress" max="100" style="accent-color: #c8c2e8; color-scheme: dark;"></progress>
</div>
</div>
<div id="busy-overlay"><div class="splash-center"><progress id="busy-progress" class="html-progress" max="100"></progress></div></div>
<div id="busy-overlay"><div class="splash-center"><progress id="busy-progress" class="html-progress" max="100" style="accent-color: #c8c2e8; color-scheme: dark;"></progress></div></div>

128
docker-compose.armv7.yml Normal file
View file

@ -0,0 +1,128 @@
version: '3.5'
## FOR ARMv7 TEST AND DEVELOPMENT ONLY, DO NOT USE IN PRODUCTION ##
## Setup: https://docs.photoprism.app/developer-guide/setup/ ##
services:
## App Server
photoprism:
build: .
image: photoprism/photoprism:develop
platform: "arm"
depends_on:
- mariadb
- dummy-webdav
security_opt:
- seccomp:unconfined
- apparmor:unconfined
ports:
- "2342:2342" # Default HTTP port (host:container)
- "2343:2343" # Acceptance Test HTTP port (host:container)
shm_size: "2gb"
environment:
PHOTOPRISM_ADMIN_PASSWORD: "photoprism" # The initial admin password (min 4 characters)
PHOTOPRISM_UID: ${UID:-1000}
PHOTOPRISM_GID: ${GID:-1000}
PHOTOPRISM_SITE_URL: "http://localhost:2342/"
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
PHOTOPRISM_SITE_CAPTION: "Browse Your Life"
PHOTOPRISM_SITE_DESCRIPTION: "AI-powered app for browsing, organizing & sharing your photo collection."
PHOTOPRISM_SITE_AUTHOR: "@photoprism_app"
PHOTOPRISM_DEBUG: "true"
PHOTOPRISM_READONLY: "false"
PHOTOPRISM_PUBLIC: "true"
PHOTOPRISM_EXPERIMENTAL: "true"
PHOTOPRISM_SERVER_MODE: "debug"
PHOTOPRISM_HTTP_HOST: "0.0.0.0"
PHOTOPRISM_HTTP_PORT: 2342
PHOTOPRISM_HTTP_COMPRESSION: "gzip" # Improves transfer speed and bandwidth utilization (none or gzip)
PHOTOPRISM_DATABASE_DRIVER: "mysql"
PHOTOPRISM_DATABASE_SERVER: "mariadb:4001"
PHOTOPRISM_DATABASE_NAME: "photoprism"
PHOTOPRISM_DATABASE_USER: "root"
PHOTOPRISM_DATABASE_PASSWORD: "photoprism"
PHOTOPRISM_TEST_DRIVER: "sqlite"
PHOTOPRISM_TEST_DSN: ".test.db"
PHOTOPRISM_TEST_DSN_MYSQL8: "root:photoprism@tcp(mysql:4001)/photoprism?charset=utf8mb4,utf8&collation=utf8mb4_unicode_ci&parseTime=true"
PHOTOPRISM_ASSETS_PATH: "/go/src/github.com/photoprism/photoprism/assets"
PHOTOPRISM_STORAGE_PATH: "/go/src/github.com/photoprism/photoprism/storage"
PHOTOPRISM_ORIGINALS_PATH: "/go/src/github.com/photoprism/photoprism/storage/originals"
PHOTOPRISM_IMPORT_PATH: "/go/src/github.com/photoprism/photoprism/storage/import"
PHOTOPRISM_DISABLE_CHOWN: "false" # Disables storage permission updates on startup
PHOTOPRISM_DISABLE_BACKUPS: "false" # Don't backup photo and album metadata to YAML files
PHOTOPRISM_DISABLE_WEBDAV: "false" # Disables built-in WebDAV server
PHOTOPRISM_DISABLE_SETTINGS: "false" # Disables Settings in Web UI
PHOTOPRISM_DISABLE_PLACES: "false" # Disables reverse geocoding and maps
PHOTOPRISM_DISABLE_EXIFTOOL: "false" # Don't create ExifTool JSON files for improved metadata extraction
PHOTOPRISM_DISABLE_TENSORFLOW: "false" # Don't use TensorFlow for image classification
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive (requires TensorFlow)
PHOTOPRISM_UPLOAD_NSFW: "false" # Allows uploads that may be offensive
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Enables Darktable presets and disables concurrent RAW conversion
PHOTOPRISM_THUMB_FILTER: "lanczos" # Resample filter, best to worst: blackman, lanczos, cubic, linear
PHOTOPRISM_THUMB_UNCACHED: "true" # Enables on-demand thumbnail rendering (high memory and cpu usage)
PHOTOPRISM_THUMB_SIZE: 2048 # Pre-rendered thumbnail size limit (default 2048, min 720, max 7680)
# PHOTOPRISM_THUMB_SIZE: 4096 # Retina 4K, DCI 4K (requires more storage); 7680 for 8K Ultra HD
PHOTOPRISM_THUMB_SIZE_UNCACHED: 7680 # On-demand rendering size limit (default 7680, min 720, max 7680)
PHOTOPRISM_JPEG_SIZE: 7680 # Size limit for converted image files in pixels (720-30000)
PHOTOPRISM_JPEG_QUALITY: 92 # Set to 95 for high-quality thumbnails (25-100)
TF_CPP_MIN_LOG_LEVEL: 0 # Show TensorFlow log messages for development
## Enable TensorFlow AVX2 support for modern Intel CPUs (requires starting the container as root):
# PHOTOPRISM_INIT: "tensorflow-amd64-avx2"
## Hardware video transcoding config (optional):
# PHOTOPRISM_FFMPEG_BUFFERS: "64" # FFmpeg capture buffers (default: 32)
# PHOTOPRISM_FFMPEG_BITRATE: "32" # FFmpeg encoding bitrate limit in Mbit/s (default: 50)
# PHOTOPRISM_FFMPEG_ENCODER: "h264_v4l2m2m" # Use Video4Linux for AVC transcoding (default: libx264)
# PHOTOPRISM_FFMPEG_ENCODER: "h264_qsv" # Use Intel Quick Sync Video for AVC transcoding (default: libx264)
# PHOTOPRISM_INIT: "intel-graphics tensorflow-amd64-avx2" # Enable TensorFlow AVX2 & Intel Graphics support
# PHOTOPRISM_INIT: "install-updates" # Installs general operating system updates
## Hardware devices for video transcoding and machine learning (optional):
# devices:
# - "/dev/video11:/dev/video11" # Video4Linux (h264_v4l2m2m)
# - "/dev/dri/renderD128:/dev/dri/renderD128" # Intel GPU
# - "/dev/dri/card0:/dev/dri/card0"
working_dir: "/go/src/github.com/photoprism/photoprism"
volumes:
- ".:/go/src/github.com/photoprism/photoprism"
- "go-mod:/go/pkg/mod"
## MariaDB Database Server
## Docs: https://mariadb.com/docs/reference/
## Release Notes: https://mariadb.com/kb/en/changes-improvements-in-mariadb-1011/
mariadb:
image: mariadb:10.11
security_opt: # see https://github.com/MariaDB/mariadb-docker/issues/434#issuecomment-1136151239
- seccomp:unconfined
- apparmor:unconfined
command: --port=4001 --innodb-strict-mode=1 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
expose:
- "4001"
ports:
- "4001:4001" # database port (host:container)
volumes:
- "./scripts/sql/mariadb-init.sql:/docker-entrypoint-initdb.d/init.sql"
environment:
MARIADB_AUTO_UPGRADE: "1"
MARIADB_INITDB_SKIP_TZINFO: "1"
MARIADB_DATABASE: "photoprism"
MARIADB_USER: "photoprism"
MARIADB_PASSWORD: "photoprism"
MARIADB_ROOT_PASSWORD: "photoprism"
## Dummy WebDAV Server
dummy-webdav:
image: photoprism/dummy-webdav:231015
container_name: dummy-webdav
environment:
WEBDAV_USERNAME: admin
WEBDAV_PASSWORD: photoprism
## Create named volume for Go module cache
volumes:
go-mod:
driver: local
## Create shared "photoprism-develop" network for connecting with services in other docker-compose.yml files
networks:
default:
name: shared
driver: bridge

View file

@ -22,7 +22,7 @@ services:
PHOTOPRISM_ADMIN_USER: "admin" # admin login username
PHOTOPRISM_ADMIN_PASSWORD: "photoprism" # initial admin password (8-72 characters)
PHOTOPRISM_AUTH_MODE: "public" # authentication mode (public, password)
PHOTOPRISM_SITE_URL: "http://photoprism.me:2342/"
PHOTOPRISM_SITE_URL: "http://localhost:2342/"
PHOTOPRISM_SITE_CAPTION: "AI-Powered Photos App"
PHOTOPRISM_SITE_DESCRIPTION: "Open-Source Photo Management"
PHOTOPRISM_SITE_AUTHOR: "@photoprism_app"
@ -150,7 +150,7 @@ services:
security_opt: # see https://github.com/MariaDB/mariadb-docker/issues/434#issuecomment-1136151239
- seccomp:unconfined
- apparmor:unconfined
command: mariadbd --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
command: --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
expose:
- "4001" # database port (internal)
volumes:
@ -165,11 +165,11 @@ services:
## Dummy OpenID Connect Provider
dummy-oidc:
image: photoprism/dummy-oidc:220405
image: photoprism/dummy-oidc:231015
## Dummy WebDAV Server
dummy-webdav:
image: photoprism/dummy-webdav:20211109
image: photoprism/dummy-webdav:231015
environment:
WEBDAV_USERNAME: admin
WEBDAV_PASSWORD: photoprism

View file

@ -4,15 +4,15 @@ version: '3.5'
## Setup: https://docs.photoprism.app/developer-guide/setup/ ##
services:
## MariaDB 11.0 Database Server
## MariaDB 11.2 Database Server
## Docs: https://mariadb.com/docs/reference/
## Release Notes: https://mariadb.com/kb/en/mariadb-11-0-0-release-notes/
mariadb-11-0:
image: mariadb:11.0-rc
## Release Notes: https://mariadb.com/kb/en/release-notes-mariadb-11-2-series/
mariadb-11-2:
image: mariadb:11.2
security_opt: # see https://github.com/MariaDB/mariadb-docker/issues/434#issuecomment-1136151239
- seccomp:unconfined
- apparmor:unconfined
command: mariadbd --port=4001 --innodb-strict-mode=1 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
command: --port=4001 --innodb-strict-mode=1 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
expose:
- "4001"
ports:
@ -27,14 +27,14 @@ services:
MARIADB_PASSWORD: "photoprism"
MARIADB_ROOT_PASSWORD: "photoprism"
## MariaDB 10.8 Database Server
## Docs: https://mariadb.com/kb/en/release-notes-mariadb-108-series/
mariadb-10-8:
image: mariadb:10.8
## MariaDB 10.11 Database Server
## Docs: https://mariadb.com/kb/en/release-notes-mariadb-1011-series/
mariadb-10-11:
image: mariadb:10.11
security_opt: # see https://github.com/MariaDB/mariadb-docker/issues/434#issuecomment-1136151239
- seccomp:unconfined
- apparmor:unconfined
command: mariadbd --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
command: --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
expose:
- "4001"
ports:
@ -49,28 +49,12 @@ services:
MARIADB_PASSWORD: "photoprism"
MARIADB_ROOT_PASSWORD: "photoprism"
## MariaDB 10.7 Database Server
mariadb-10-7:
image: mariadb:10.7
command: mysqld --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
expose:
- "4001" # database port (internal)
volumes:
- "./scripts/sql/mariadb-init.sql:/docker-entrypoint-initdb.d/init.sql"
environment:
MARIADB_AUTO_UPGRADE: "1"
MARIADB_INITDB_SKIP_TZINFO: "1"
MARIADB_DATABASE: "photoprism"
MARIADB_USER: "photoprism"
MARIADB_PASSWORD: "photoprism"
MARIADB_ROOT_PASSWORD: "photoprism"
## MariaDB 10.5.5 Database Server
## Affected by MDEV-25362: Incorrect name resolution for subqueries in ON expressions
## see https://jira.mariadb.org/browse/MDEV-25362
mariadb-10-5-5:
image: mariadb:10.5.5
command: mysqld --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
command: --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
expose:
- "4001" # database port (internal)
volumes:
@ -85,7 +69,7 @@ services:
## Docs: https://mariadb.com/docs/reference/cs10.3/
mariadb-10-3:
image: mariadb:10.3
command: mysqld --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
command: --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
expose:
- "4001" # database port (internal)
volumes:
@ -100,7 +84,7 @@ services:
## Docs: https://mariadb.com/docs/reference/cs10.2/
mariadb-10-2:
image: mariadb:10.2
command: mysqld --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
command: --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
expose:
- "4001" # database port (internal)
volumes:
@ -114,7 +98,7 @@ services:
## MariaDB 10.1 Database Server
mariadb-10-1:
image: mariadb:10.1
command: mysqld --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
command: --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
expose:
- "4001" # database port (internal)
volumes:

View file

@ -8,7 +8,7 @@ services:
## Docs: https://dev.mysql.com/doc/refman/8.0/en/
mysql:
image: mysql:8
command: mysqld --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
command: --port=4001 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
expose:
- "4001" # database port (internal)
environment:

View file

@ -30,7 +30,7 @@ services:
PHOTOPRISM_ADMIN_USER: "admin" # admin login username
PHOTOPRISM_ADMIN_PASSWORD: "photoprism" # initial admin password (8-72 characters)
PHOTOPRISM_AUTH_MODE: "password" # authentication mode (public, password)
PHOTOPRISM_SITE_URL: "http://photoprism.me:2342/"
PHOTOPRISM_SITE_URL: "http://localhost:2342/"
PHOTOPRISM_SITE_CAPTION: "AI-Powered Photos App"
PHOTOPRISM_SITE_DESCRIPTION: "Open-Source Photo Management"
PHOTOPRISM_SITE_AUTHOR: "@photoprism_app"
@ -83,7 +83,7 @@ services:
## Dummy WebDAV Server
dummy-webdav:
image: photoprism/dummy-webdav:20211109
image: photoprism/dummy-webdav:231015
environment:
WEBDAV_USERNAME: admin
WEBDAV_PASSWORD: photoprism

View file

@ -62,7 +62,7 @@ services:
PHOTOPRISM_OIDC_CLIENT: "photoprism-develop"
PHOTOPRISM_OIDC_SECRET: "9d8351a0-ca01-4556-9c37-85eb634869b9"
## Site Information
PHOTOPRISM_SITE_URL: "http://photoprism.me:2342/" # server URL in the format "http(s)://domain.name(:port)/(path)"
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # server URL in the format "http(s)://domain.name(:port)/(path)"
PHOTOPRISM_SITE_CAPTION: "AI-Powered Photos App"
PHOTOPRISM_SITE_DESCRIPTION: "Tags and finds pictures without getting in your way!"
PHOTOPRISM_SITE_AUTHOR: "@photoprism_app"
@ -103,13 +103,13 @@ services:
PHOTOPRISM_JPEG_SIZE: 7680 # size limit for converted image files in pixels (720-30000)
PHOTOPRISM_JPEG_QUALITY: 85 # a higher value increases the quality and file size of JPEG images and thumbnails (25-100)
TF_CPP_MIN_LOG_LEVEL: 0 # show TensorFlow log messages for development
## Video Transcoding (https://docs.photoprism.app/getting-started/advanced/transcoding/):
# PHOTOPRISM_FFMPEG_ENCODER: "software" # H.264/AVC encoder (software, intel, nvidia, apple, raspberry, or vaapi)
# PHOTOPRISM_FFMPEG_SIZE: "1920" # video size limit in pixels (720-7680) (default: 3840)
# PHOTOPRISM_FFMPEG_BITRATE: "32" # video bitrate limit in Mbit/s (default: 50)
# LIBVA_DRIVER_NAME: "i965" # For Intel architectures Haswell and older which do not support QSV yet but use VAAPI instead
## Run/install on first startup (options: update https gpu tensorflow davfs clitools clean):
PHOTOPRISM_INIT: "https tensorflow"
## Hardware Video Transcoding (optional):
# PHOTOPRISM_FFMPEG_ENCODER: "nvidia" # FFmpeg encoder ("software", "intel", "nvidia", "apple", "raspberry", "vaapi") Intel: "intel" for Broadwell or later and "vaapi" for Haswell or earlier
# PHOTOPRISM_FFMPEG_ENCODER: "intel" # FFmpeg encoder ("software", "intel", "nvidia", "apple", "raspberry", "vaapi") Intel: "intel" for Broadwell or later and "vaapi" for Haswell or earlier`
# PHOTOPRISM_FFMPEG_BITRATE: "32" # FFmpeg encoding bitrate limit in Mbit/s (default: 50)
# LIBVA_DRIVER_NAME: "i965" # For Intel architectures Haswell and older which do not support QSV yet but use VAAPI instead
## Share hardware devices with FFmpeg and TensorFlow (optional):
# devices:
# - "/dev/dri:/dev/dri" # Intel QSV (Broadwell and later) or VAAPI (Haswell and earlier)
@ -133,7 +133,7 @@ services:
security_opt: # see https://github.com/MariaDB/mariadb-docker/issues/434#issuecomment-1136151239
- seccomp:unconfined
- apparmor:unconfined
command: mariadbd --port=4001 --innodb-strict-mode=1 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
command: --port=4001 --innodb-strict-mode=1 --innodb-buffer-pool-size=256M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
expose:
- "4001"
ports:
@ -165,7 +165,7 @@ services:
## Login: user / photoprism
## Admin: admin / photoprism
keycloak:
image: quay.io/keycloak/keycloak:20.0
image: quay.io/keycloak/keycloak:22.0
command: "start-dev" # development mode, do not use this in production!
container_name: keycloak
links:
@ -211,7 +211,7 @@ services:
## Dummy OpenID Connect Provider
dummy-oidc:
image: photoprism/dummy-oidc:220405
image: photoprism/dummy-oidc:231015
container_name: dummy-oidc
labels:
- "traefik.enable=true"
@ -224,7 +224,7 @@ services:
## Dummy WebDAV Server
dummy-webdav:
image: photoprism/dummy-webdav:220405
image: photoprism/dummy-webdav:231015
container_name: dummy-webdav
environment:
WEBDAV_USERNAME: admin

View file

@ -1,64 +1,21 @@
# Dockerfiles and Docker Compose Examples
# Dockerfiles for Development and Production
[**Dockerfiles**](https://docs.docker.com/engine/reference/builder/) are text documents that contain all commands a user
could call in a terminal to assemble an application image.
[**Dockerfiles**](https://docs.docker.com/engine/reference/builder/) are text documents that contain all commands a user could call in a terminal to assemble an application image.
[**Docker Compose**](https://docs.docker.com/compose/) uses [human-friendly YAML files](https://docs.photoprism.app/developer-guide/technologies/yaml/)
to configure all application services so you can easily start them with a single command.
[**Docker Compose**](https://docs.docker.com/compose/) uses [human-friendly YAML files](https://docs.photoprism.app/developer-guide/technologies/yaml/) to configure all application services so you can easily start them with a single command.
## Why are we using Docker? ##
See our [Getting Started FAQ](https://docs.photoprism.app/getting-started/faq/#how-can-i-install-photoprism-without-docker) for alternative installation methods, for example using the [*tar.gz* packages](https://github.com/photoprism/photoprism/blob/develop/setup/pkg/linux/README.md) we provide for download at [dl.photoprism.app/pkg/linux/](https://dl.photoprism.app/pkg/linux/README.html).
Containers are nothing new; [Solaris Zones](https://en.wikipedia.org/wiki/Solaris_Containers) have been around for
about 15 years, first released publicly in 2004. The chroot system call was introduced during
[development of Version 7 Unix in 1979](https://en.wikipedia.org/wiki/Chroot). It is used ever since for hosting
applications exposed to the public Internet.
## What are the benefits of using Docker? ##
Modern Linux containers are an incremental enhancement. A main advantage of Docker is that application images
can be easily made available to users via Internet. It provides a common standard across most operating
systems and devices, which saves our team a lot of time that we can then spend [more effectively](https://docs.photoprism.app/developer-guide/issues/#effectiveness-efficiency), for example,
providing support and developing one of the many features that users are waiting for.
**(1) Docker uses standard features of the Linux kernel.** Containers are nothing new; [Solaris Zones](https://en.wikipedia.org/wiki/Solaris_Containers) were released about 20 years ago and the chroot system call was introduced during [development of Version 7 Unix in 1979](https://en.wikipedia.org/wiki/Chroot). It is used ever since for hosting applications exposed to the public Internet. Modern Linux containers are an incremental improvement of this, based on standard functionality that is part of the kernel.
Human-readable and versioned Dockerfiles as part of our public source code also help avoid "works for me" moments and
other unwelcome surprises by enabling teams to have the exact same environment everywhere in
[development](https://github.com/photoprism/photoprism/blob/develop/docker/develop/bookworm/Dockerfile), staging,
and [production](https://github.com/photoprism/photoprism/blob/develop/docker/photoprism/bookworm/Dockerfile).
**(2) Docker saves time through simplified deployment and testing.** A main advantage of Docker is that application images can be [easily made available](https://hub.docker.com/r/photoprism/photoprism) to users via Internet. It provides a common standard across most operating systems and devices, which saves our team a lot of time that we can then spend [more effectively](https://docs.photoprism.app/developer-guide/code-quality/#effectiveness-efficiency), for example, providing support and developing one of the many features that users are waiting for.
Last but not least, virtually all file format parsers have vulnerabilities that just haven't been discovered yet.
This is a known risk that can affect you even if your computer is not directly connected to the Internet.
Running apps in a container with limited host access is an easy way to improve security without
compromising performance and usability.
**(3) Dockerfiles are part of the source code repository.** [Human-readable](https://docs.docker.com/engine/reference/builder/) and [versioned Dockerfiles](https://github.com/photoprism/photoprism/tree/develop/docker) that are part of our public source code help avoid "works for me" moments and other unwelcome surprises by enabling us to have the exact [same environment](http://localhost:8000/developer-guide/setup/) everywhere in [development](https://github.com/photoprism/photoprism/tree/develop/docker/develop), [staging, and production](https://github.com/photoprism/photoprism/tree/develop/docker/photoprism).
## What about Virtual Machines? ##
**(4) Running applications in containers is more secure.** Last but not least, virtually all file format parsers have vulnerabilities that just haven't been discovered yet. This is a known risk that can affect you even if your computer is not directly connected to the Internet. Running apps in a container with limited host access is an easy way to improve security without compromising performance and usability.
A virtual machine running its own operating system provides more security, but typically has side effects
such as lower performance and more difficult handling. You can also run Docker in a VM to get the best of
both worlds. It's essentially what happens when you run dockerized applications on [virtual cloud servers](https://docs.photoprism.app/getting-started/cloud/digitalocean/)
and operating systems other than Linux.
## Why not use virtual machines instead? ##
## Alternatives ##
### Building From Source ###
You can build and install PhotoPrism from the publicly available [source code](https://docs.photoprism.app/developer-guide/setup/):
```bash
git clone https://github.com/photoprism/photoprism.git
cd photoprism
make all install DESTDIR=/opt/photoprism
```
Missing build dependencies must be installed manually as shown in our human-readable and versioned
[Dockerfile](https://github.com/photoprism/photoprism/blob/develop/docker/develop/Dockerfile). You often don't
need to use the exact same versions, so it's possible to replace packages with what is available in your environment.
Please note that we do not have the resources to provide private users with dependencies and
[TensorFlow libraries](https://dl.photoprism.app/tensorflow/) for their personal environments. We recommend giving
Docker a try if you use Linux as it saves developers a lot of time when building, testing, and deploying complex
applications like PhotoPrism. It also effectively helps avoid "works for me" moments and missing dependencies.
### Installation Packages ###
An [unofficial port](https://docs.photoprism.app/getting-started/freebsd/) is available for FreeBSD / FreeNAS users.
You are invited to contribute by [building and testing standalone packages](https://docs.photoprism.app/developer-guide/) for Linux distributions and other operating systems.
Updates are [released several times a month](https://docs.photoprism.app/release-notes/), so maintaining the long list of dependencies for additional environments would currently consume too many of [our resources](https://link.photoprism.app/membership).
A virtual machine with a dedicated operating system environment provides even more security, but usually has side effects such as lower performance and more difficult handling. Using a VM, however, doesn't prevent you from running containerized apps to get the best of both worlds. This is essentially what happens when you install Docker on [virtual cloud servers](https://docs.photoprism.app/getting-started/cloud/digitalocean/) and operating systems other than Linux.

View file

@ -1,5 +1,5 @@
#### Base Image: Ubuntu 22.04 LTS (Jammy Jellyfish)
FROM ubuntu:jammy
#### Base Image: Ubuntu 23.10 (Mantic Minotaur)
FROM ubuntu:mantic
# Copyright © 2018 - 2023 PhotoPrism UG. All rights reserved.
#
@ -9,7 +9,7 @@ FROM ubuntu:jammy
# Add Open Container Initiative (OCI) annotations.
# See: https://github.com/opencontainers/image-spec/blob/main/annotations.md
LABEL org.opencontainers.image.title="PhotoPrism® Build Image (ARMv7)"
LABEL org.opencontainers.image.description="Ubuntu 22.04 LTS (Jammy Jellyfish)"
LABEL org.opencontainers.image.description="Ubuntu 23.10 (Mantic Minotaur)"
LABEL org.opencontainers.image.url="https://hub.docker.com/repository/docker/photoprism/develop"
LABEL org.opencontainers.image.source="https://github.com/photoprism/photoprism"
LABEL org.opencontainers.image.documentation="https://docs.photoprism.app/developer-guide/setup/"
@ -48,19 +48,19 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/80forceyes && \
echo 'APT::Get::Fix-Missing "true";' > /etc/apt/apt.conf.d/80fixmissing && \
echo 'force-confold' > /etc/dpkg/dpkg.cfg.d/force-confold && \
apt-get update && apt-get -qq upgrade && apt-get -qq install --no-install-recommends \
apt-get update && apt-get -qq dist-upgrade && apt-get -qq install --no-install-recommends \
apt-utils gpg pkg-config software-properties-common ca-certificates avahi-utils \
build-essential gcc g++ sudo bash make nano lsof lshw git jq \
autoconf automake cmake libtool libjpeg8 libjpeg8-dev \
autoconf automake cmake libtool libjpeg-dev libpng-dev libwebp-dev \
zip unzip wget curl rsync sqlite3 chrpath gettext libc6-dev \
libssl-dev libxft-dev libfreetype6 libfreetype6-dev libfontconfig1 \
libfontconfig1-dev libhdf5-serial-dev libpng-dev libzmq3-dev \
libfontconfig1-dev libhdf5-serial-dev libzmq3-dev \
libx264-dev libx265-dev libde265-dev libaom-dev libnss3 libxtst6 librsvg2-bin tzdata \
exiftool ffmpeg libavcodec-extra \
&& \
/scripts/install-nodejs.sh && \
/scripts/install-tensorflow.sh && \
/scripts/install-libheif.sh && \
/scripts/install-tensorflow.sh && \
/scripts/install-go.sh && \
/scripts/install-go-tools.sh && \
echo 'alias ll="ls -alh"' >> /etc/skel/.bashrc && \
@ -79,14 +79,14 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
/photoprism/storage/cache && \
/scripts/cleanup.sh
# download models and testdata
# Download models and testdata.
RUN mkdir /tmp/photoprism && \
wget "https://dl.photoprism.app/tensorflow/nsfw.zip?${BUILD_TAG}" -O /tmp/photoprism/nsfw.zip && \
wget "https://dl.photoprism.app/tensorflow/nasnet.zip?${BUILD_TAG}" -O /tmp/photoprism/nasnet.zip && \
wget "https://dl.photoprism.app/tensorflow/facenet.zip?${BUILD_TAG}" -O /tmp/photoprism/facenet.zip && \
wget "https://dl.photoprism.app/qa/testdata.zip?${BUILD_TAG}" -O /tmp/photoprism/testdata.zip
# set up project directory
# Default working directory.
WORKDIR "/go/src/github.com/photoprism/photoprism"
# Expose the following container ports:
@ -103,3 +103,4 @@ ENTRYPOINT ["/scripts/entrypoint.sh"]
# Keep container running.
CMD ["tail", "-f", "/dev/null"]

View file

@ -43,7 +43,7 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/80forceyes && \
echo 'APT::Get::Fix-Missing "true";' > /etc/apt/apt.conf.d/80fixmissing && \
echo 'force-confold' > /etc/dpkg/dpkg.cfg.d/force-confold && \
apt-get update && apt-get -qq upgrade && \
apt-get update && apt-get -qq dist-upgrade && \
apt-get -qq install \
libc6 ca-certificates sudo bash tzdata \
gpg zip unzip wget curl rsync make nano \

View file

@ -49,7 +49,7 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/80forceyes && \
echo 'APT::Get::Fix-Missing "true";' > /etc/apt/apt.conf.d/80fixmissing && \
echo 'force-confold' > /etc/dpkg/dpkg.cfg.d/force-confold && \
apt-get update && apt-get -qq upgrade && \
apt-get update && apt-get -qq dist-upgrade && \
apt-get -qq install \
libc6 ca-certificates sudo bash tzdata \
gpg zip unzip wget curl rsync make nano \

View file

@ -42,7 +42,7 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/80forceyes && \
echo 'APT::Get::Fix-Missing "true";' > /etc/apt/apt.conf.d/80fixmissing && \
echo 'force-confold' > /etc/dpkg/dpkg.cfg.d/force-confold && \
apt-get update && apt-get -qq upgrade && \
apt-get update && apt-get -qq dist-upgrade && \
apt-get -qq install \
libc6 ca-certificates bash sudo nano avahi-utils jq lsof lshw \
exiftool sqlite3 tzdata gpg make zip unzip wget curl rsync \

View file

@ -48,7 +48,7 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/80forceyes && \
echo 'APT::Get::Fix-Missing "true";' > /etc/apt/apt.conf.d/80fixmissing && \
echo 'force-confold' > /etc/dpkg/dpkg.cfg.d/force-confold && \
apt-get update && apt-get -qq upgrade && \
apt-get update && apt-get -qq dist-upgrade && \
apt-get -qq install \
libc6 ca-certificates bash sudo nano avahi-utils jq lsof lshw \
exiftool sqlite3 tzdata gpg make zip unzip wget curl rsync \
@ -58,11 +58,11 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
apt-get -qq install \
apt-utils pkg-config software-properties-common \
build-essential gcc g++ git gettext davfs2 chrpath apache2-utils \
autoconf automake cmake libtool libjpeg8-dev \
libx264-dev libx265-dev libaom-dev libvpx-dev libwebm-dev libpng-dev libxft-dev \
autoconf automake cmake libtool libjpeg-dev libpng-dev libwebp-dev \
libx264-dev libx265-dev libaom-dev libvpx-dev libwebm-dev libxft-dev \
libc6-dev libhdf5-serial-dev libzmq3-dev libssl-dev libnss3 \
libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev fonts-roboto \
librsvg2-bin ghostscript gsfonts \
librsvg2-bin ghostscript gsfonts pdf2svg ps2eps \
&& \
/scripts/install-nodejs.sh && \
/scripts/install-mariadb.sh mariadb-client && \

View file

@ -42,12 +42,12 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/80forceyes && \
echo 'APT::Get::Fix-Missing "true";' > /etc/apt/apt.conf.d/80fixmissing && \
echo 'force-confold' > /etc/dpkg/dpkg.cfg.d/force-confold && \
apt-get update && apt-get -qq upgrade && \
apt-get update && apt-get -qq dist-upgrade && \
apt-get -qq install \
libc6 ca-certificates bash sudo nano avahi-utils jq lsof lshw \
exiftool sqlite3 tzdata gpg make zip unzip wget curl rsync \
imagemagick libvips-dev rawtherapee ffmpeg libavcodec-extra x264 x265 libde265-dev \
libaom3 libvpx7 libwebm1 libjpeg8 libmatroska7 libdvdread8 libebml5 libgav1-bin libatomic1 \
libc6 ca-certificates bash sudo nano avahi-utils jq lsof lshw libebml5 libgav1-bin libatomic1 \
exiftool sqlite3 tzdata gpg make zip unzip wget curl rsync imagemagick libvips-dev rawtherapee \
ffmpeg libffmpeg-nvenc-dev libswscale-dev libavfilter-extra libavformat-extra libavcodec-extra \
x264 x265 libde265-dev libaom3 libvpx7 libwebm1 libjpeg8 libmatroska7 libdvdread8 \
&& \
/scripts/install-mariadb.sh mariadb-client && \
/scripts/install-darktable.sh && \
@ -75,4 +75,4 @@ WORKDIR /photoprism
EXPOSE 2342 2442 2443
# Keep container running.
CMD ["tail", "-f", "/dev/null"]
CMD ["tail", "-f", "/dev/null"]

View file

@ -48,21 +48,21 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/80forceyes && \
echo 'APT::Get::Fix-Missing "true";' > /etc/apt/apt.conf.d/80fixmissing && \
echo 'force-confold' > /etc/dpkg/dpkg.cfg.d/force-confold && \
apt-get update && apt-get -qq upgrade && \
apt-get update && apt-get -qq dist-upgrade && \
apt-get -qq install \
libc6 ca-certificates bash sudo nano avahi-utils jq lsof lshw \
exiftool sqlite3 tzdata gpg make zip unzip wget curl rsync \
imagemagick libvips-dev rawtherapee ffmpeg libavcodec-extra x264 x265 libde265-dev \
libaom3 libvpx7 libwebm1 libjpeg8 libmatroska7 libdvdread8 libebml5 libgav1-bin libatomic1 \
libc6 ca-certificates bash sudo nano avahi-utils jq lsof lshw libebml5 libgav1-bin libatomic1 \
exiftool sqlite3 tzdata gpg make zip unzip wget curl rsync imagemagick libvips-dev rawtherapee \
ffmpeg libffmpeg-nvenc-dev libswscale-dev libavfilter-extra libavformat-extra libavcodec-extra \
x264 x265 libde265-dev libaom3 libvpx7 libwebm1 libjpeg8 libmatroska7 libdvdread8 \
&& \
apt-get -qq install \
apt-utils pkg-config software-properties-common \
build-essential gcc g++ git gettext davfs2 chrpath apache2-utils \
autoconf automake cmake libtool libjpeg8-dev \
libx264-dev libx265-dev libaom-dev libvpx-dev libwebm-dev libpng-dev libxft-dev \
autoconf automake cmake libtool libjpeg-dev libpng-dev libwebp-dev \
libx264-dev libx265-dev libaom-dev libvpx-dev libwebm-dev libxft-dev \
libc6-dev libhdf5-serial-dev libzmq3-dev libssl-dev libnss3 \
libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev fonts-roboto \
librsvg2-bin ghostscript gsfonts \
librsvg2-bin ghostscript gsfonts pdf2svg ps2eps \
&& \
/scripts/install-nodejs.sh && \
/scripts/install-mariadb.sh mariadb-client && \

View file

@ -0,0 +1,78 @@
#### Base Image: Ubuntu 23.10 (Mantic Minotaur)
FROM ubuntu:mantic
# Copyright © 2018 - 2023 PhotoPrism UG. All rights reserved.
#
# Questions? Email us at hello@photoprism.app or visit our website to learn
# more about our team, products and services: https://www.photoprism.app/
# Add Open Container Initiative (OCI) annotations.
# See: https://github.com/opencontainers/image-spec/blob/main/annotations.md
LABEL org.opencontainers.image.title="PhotoPrism® Base Image (Ubuntu 23.10)"
LABEL org.opencontainers.image.description="Ubuntu 23.10 (Mantic Minotaur)"
LABEL org.opencontainers.image.url="https://hub.docker.com/repository/docker/photoprism/develop"
LABEL org.opencontainers.image.source="https://github.com/photoprism/photoprism"
LABEL org.opencontainers.image.documentation="https://docs.photoprism.app/developer-guide/setup/"
LABEL org.opencontainers.image.authors="PhotoPrism UG <hello@photoprism.app>"
LABEL org.opencontainers.image.vendor="PhotoPrism UG"
# Declare build parameters.
ARG TARGETARCH
ARG BUILD_TAG
# Set environment variables, see https://docs.photoprism.app/getting-started/config-options/.
ENV PHOTOPRISM_ARCH=$TARGETARCH \
DOCKER_TAG=$BUILD_TAG \
DOCKER_ENV="prod" \
PS1="\u@$DOCKER_TAG:\w\$ " \
PATH="/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/scripts:/opt/photoprism/bin" \
LD_LIBRARY_PATH="/usr/local/lib:/usr/lib" \
TMPDIR="/tmp" \
DEBIAN_FRONTEND="noninteractive" \
TF_CPP_MIN_LOG_LEVEL="2" \
PROG="photoprism"
# Copy scripts and package sources config.
COPY --chown=root:root --chmod=755 /scripts/dist/ /scripts/
# Update base image and add dependencies.
RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
echo 'APT::Install-Recommends "false";' > /etc/apt/apt.conf.d/80recommends && \
echo 'APT::Install-Suggests "false";' > /etc/apt/apt.conf.d/80suggests && \
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/80forceyes && \
echo 'APT::Get::Fix-Missing "true";' > /etc/apt/apt.conf.d/80fixmissing && \
echo 'force-confold' > /etc/dpkg/dpkg.cfg.d/force-confold && \
apt-get update && apt-get -qq dist-upgrade && \
apt-get -qq install \
libc6 ca-certificates bash sudo nano avahi-utils jq lsof lshw libebml5 libgav1-bin libatomic1 \
exiftool sqlite3 tzdata gpg make zip unzip wget curl rsync imagemagick libvips-dev rawtherapee \
ffmpeg libffmpeg-nvenc-dev libswscale-dev libavfilter-extra libavformat-extra libavcodec-extra \
x264 x265 libde265-dev libaom3 libvpx7 libwebm1 libjpeg8 libmatroska7 libdvdread8 \
&& \
/scripts/install-mariadb.sh mariadb-client && \
/scripts/install-darktable.sh && \
/scripts/install-libheif.sh && \
echo 'alias ll="ls -alh"' >> /etc/skel/.bashrc && \
echo 'export PS1="\u@$DOCKER_TAG:\w\$ "' >> /etc/skel/.bashrc && \
echo "ALL ALL=(ALL) NOPASSWD:SETENV: /scripts/entrypoint-init.sh" >> /etc/sudoers.d/init && \
cp /etc/skel/.bashrc /root/.bashrc && \
/scripts/create-users.sh && \
install -d -m 0777 -o 1000 -g 1000 \
/photoprism/originals \
/photoprism/import \
/photoprism/storage \
/photoprism/storage/sidecar \
/photoprism/storage/albums \
/photoprism/storage/backups \
/photoprism/storage/config \
/photoprism/storage/cache && \
/scripts/cleanup.sh
# Default working directory.
WORKDIR /photoprism
# Expose HTTP and HTTPS ports.
EXPOSE 2342 2442 2443
# Keep container running.
CMD ["tail", "-f", "/dev/null"]

View file

@ -0,0 +1,115 @@
#### Base Image: Ubuntu 23.10 (Mantic Minotaur)
FROM ubuntu:mantic
# Copyright © 2018 - 2023 PhotoPrism UG. All rights reserved.
#
# Questions? Email us at hello@photoprism.app or visit our website to learn
# more about our team, products and services: https://www.photoprism.app/
# Add Open Container Initiative (OCI) annotations.
# See: https://github.com/opencontainers/image-spec/blob/main/annotations.md
LABEL org.opencontainers.image.title="PhotoPrism® Build Image (Ubuntu 23.10)"
LABEL org.opencontainers.image.description="Ubuntu 23.10 (Mantic Minotaur)"
LABEL org.opencontainers.image.url="https://hub.docker.com/repository/docker/photoprism/develop"
LABEL org.opencontainers.image.source="https://github.com/photoprism/photoprism"
LABEL org.opencontainers.image.documentation="https://docs.photoprism.app/developer-guide/setup/"
LABEL org.opencontainers.image.authors="PhotoPrism UG <hello@photoprism.app>"
LABEL org.opencontainers.image.vendor="PhotoPrism UG"
# Declare build parameters.
ARG TARGETARCH
ARG BUILD_TAG
# Set environment variables, see https://docs.photoprism.app/getting-started/config-options/.
ENV PHOTOPRISM_ARCH=$TARGETARCH \
DOCKER_TAG=$BUILD_TAG \
DOCKER_ENV="develop" \
NODE_ENV="production" \
PS1="\u@$DOCKER_TAG:\w\$ " \
PATH="/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/scripts:/usr/local/go/bin:/go/bin:/opt/photoprism/bin" \
LD_LIBRARY_PATH="/usr/local/lib:/usr/lib" \
DEBIAN_FRONTEND="noninteractive" \
TMPDIR="/tmp" \
TF_CPP_MIN_LOG_LEVEL="0" \
GOPATH="/go" \
GOBIN="/usr/local/bin" \
GO111MODULE="on" \
CGO_CFLAGS="-g -O2 -Wno-return-local-addr" \
PROG="photoprism"
# Copy scripts and package sources config.
COPY --chown=root:root --chmod=755 /scripts/dist/ /scripts/
COPY --chown=root:root --chmod=644 /.my.cnf /etc/my.cnf
# Update base image and add dependencies.
RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
echo 'APT::Install-Recommends "false";' > /etc/apt/apt.conf.d/80recommends && \
echo 'APT::Install-Suggests "false";' > /etc/apt/apt.conf.d/80suggests && \
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/80forceyes && \
echo 'APT::Get::Fix-Missing "true";' > /etc/apt/apt.conf.d/80fixmissing && \
echo 'force-confold' > /etc/dpkg/dpkg.cfg.d/force-confold && \
apt-get update && apt-get -qq dist-upgrade && \
apt-get -qq install \
libc6 ca-certificates bash sudo nano avahi-utils jq lsof lshw libebml5 libgav1-bin libatomic1 \
exiftool sqlite3 tzdata gpg make zip unzip wget curl rsync imagemagick libvips-dev rawtherapee \
ffmpeg libffmpeg-nvenc-dev libswscale-dev libavfilter-extra libavformat-extra libavcodec-extra \
x264 x265 libde265-dev libaom3 libvpx7 libwebm1 libjpeg8 libmatroska7 libdvdread8 \
&& \
apt-get -qq install \
apt-utils pkg-config software-properties-common \
build-essential gcc g++ git gettext davfs2 chrpath apache2-utils \
autoconf automake cmake libtool libjpeg-dev libpng-dev libwebp-dev \
libx264-dev libx265-dev libaom-dev libvpx-dev libwebm-dev libxft-dev \
libc6-dev libhdf5-serial-dev libzmq3-dev libssl-dev libnss3 \
libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev fonts-roboto \
librsvg2-bin ghostscript gsfonts pdf2svg ps2eps \
&& \
/scripts/install-nodejs.sh && \
/scripts/install-mariadb.sh mariadb-client && \
/scripts/install-tensorflow.sh && \
/scripts/install-darktable.sh && \
/scripts/install-libheif.sh && \
/scripts/install-chrome.sh && \
/scripts/install-go.sh && \
/scripts/install-go-tools.sh && \
echo 'alias go=richgo ll="ls -alh"' >> /etc/skel/.bashrc && \
echo 'export PS1="\u@$DOCKER_TAG:\w\$ "' >> /etc/skel/.bashrc && \
echo "ALL ALL=(ALL) NOPASSWD:SETENV: ALL" >> /etc/sudoers.d/all && \
cp /etc/skel/.bashrc /root/.bashrc && \
cp /scripts/convert/policy.xml /etc/ImageMagick-6/policy.xml && \
/scripts/create-users.sh && \
install -d -m 0777 -o 1000 -g 1000 \
/photoprism/originals \
/photoprism/import \
/photoprism/storage \
/photoprism/storage/sidecar \
/photoprism/storage/albums \
/photoprism/storage/backups \
/photoprism/storage/config \
/photoprism/storage/cache && \
/scripts/cleanup.sh
# Download models and testdata.
RUN mkdir /tmp/photoprism && \
wget "https://dl.photoprism.app/tensorflow/nsfw.zip?${BUILD_TAG}" -O /tmp/photoprism/nsfw.zip && \
wget "https://dl.photoprism.app/tensorflow/nasnet.zip?${BUILD_TAG}" -O /tmp/photoprism/nasnet.zip && \
wget "https://dl.photoprism.app/tensorflow/facenet.zip?${BUILD_TAG}" -O /tmp/photoprism/facenet.zip && \
wget "https://dl.photoprism.app/qa/testdata.zip?${BUILD_TAG}" -O /tmp/photoprism/testdata.zip
# Default working directory.
WORKDIR "/go/src/github.com/photoprism/photoprism"
# Expose the following container ports:
# - 2342 (HTTP)
# - 2343 (Acceptance Tests)
# - 2442 (HTTP)
# - 2443 (HTTPS)
# - 9515 (Chromedriver)
# - 40000 (Go Debugger)
EXPOSE 2342 2343 2442 2443 9515 40000
# Declare container entrypoint script.
ENTRYPOINT ["/scripts/entrypoint.sh"]
# Keep container running.
CMD ["tail", "-f", "/dev/null"]

View file

@ -8,9 +8,10 @@ FROM photoprism/develop:armv7 as build
# Declare build parameters.
ARG TARGETARCH
ARG TARGETPLATFORM
ARG BUILD_TAG
# Copy source to image.
# Copy project files.
WORKDIR "/go/src/github.com/photoprism/photoprism"
COPY . .
@ -18,18 +19,19 @@ COPY . .
RUN make all install DESTDIR=/opt/photoprism
################################################## PRODUCTION STAGE ####################################################
#### Base Image: Ubuntu 22.04 LTS (Jammy Jellyfish)
FROM ubuntu:jammy
#### Base Image: Ubuntu 23.10 (Mantic Minotaur)
FROM ubuntu:mantic
# Add Open Container Initiative (OCI) annotations.
# See: https://github.com/opencontainers/image-spec/blob/main/annotations.md
LABEL org.opencontainers.image.title="PhotoPrism® (ARMv7)"
LABEL org.opencontainers.image.description="Ubuntu 22.04 LTS (Jammy Jellyfish)"
LABEL org.opencontainers.image.description="Ubuntu 23.10 (Mantic Minotaur)"
LABEL org.opencontainers.image.url="https://hub.docker.com/r/photoprism/photoprism"
LABEL org.opencontainers.image.source="https://github.com/photoprism/photoprism"
LABEL org.opencontainers.image.documentation="https://docs.photoprism.app/getting-started/"
LABEL org.opencontainers.image.authors="PhotoPrism UG <hello@photoprism.app>"
LABEL org.opencontainers.image.vendor="PhotoPrism UG"
LABEL org.opencontainers.image.ref.name="photoprism"
# Declare build parameters.
ARG TARGETARCH
@ -59,7 +61,7 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_UPLOAD_NSFW="true" \
PHOTOPRISM_DETECT_NSFW="false" \
PHOTOPRISM_EXPERIMENTAL="false" \
PHOTOPRISM_SITE_URL="http://photoprism.me:2342/" \
PHOTOPRISM_SITE_URL="http://localhost:2342/" \
PHOTOPRISM_SITE_CAPTION="AI-Powered Photos App" \
PHOTOPRISM_SITE_DESCRIPTION="" \
PHOTOPRISM_SITE_AUTHOR="" \
@ -89,7 +91,8 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_WORKERS=0 \
PHOTOPRISM_WAKEUP_INTERVAL=900 \
PHOTOPRISM_AUTO_INDEX=300 \
PHOTOPRISM_AUTO_IMPORT=300
PHOTOPRISM_AUTO_IMPORT=300 \
PHOTOPRISM_INIT="https"
# Copy dist files, scripts, and debian backports sources list.
COPY --from=build --chown=root:root --chmod=755 /opt/photoprism/ /opt/photoprism
@ -102,7 +105,7 @@ RUN echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/80forceyes && \
echo 'APT::Get::Fix-Missing "true";' > /etc/apt/apt.conf.d/80fixmissing && \
echo 'force-confold' > /etc/dpkg/dpkg.cfg.d/force-confold && \
apt-get update && apt-get -qq upgrade && \
apt-get update && apt-get -qq dist-upgrade && \
apt-get -qq install --no-install-recommends \
libc6 ca-certificates bash sudo nano avahi-utils jq lsof lshw \
exiftool mariadb-client sqlite3 tzdata gpg make zip unzip wget curl rsync \

View file

@ -56,7 +56,7 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_UPLOAD_NSFW="true" \
PHOTOPRISM_DETECT_NSFW="false" \
PHOTOPRISM_EXPERIMENTAL="false" \
PHOTOPRISM_SITE_URL="http://photoprism.me:2342/" \
PHOTOPRISM_SITE_URL="http://localhost:2342/" \
PHOTOPRISM_SITE_CAPTION="AI-Powered Photos App" \
PHOTOPRISM_SITE_DESCRIPTION="" \
PHOTOPRISM_SITE_AUTHOR="" \
@ -86,14 +86,15 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_WORKERS=0 \
PHOTOPRISM_WAKEUP_INTERVAL=900 \
PHOTOPRISM_AUTO_INDEX=300 \
PHOTOPRISM_AUTO_IMPORT=300
PHOTOPRISM_AUTO_IMPORT=300 \
PHOTOPRISM_INIT="https"
# Copy scripts.
COPY --chown=root:root --chmod=755 /scripts/dist/ /scripts/
# Update pre-installed packages.
RUN apt-get update && \
apt-get -qq upgrade && \
apt-get -qq dist-upgrade && \
/scripts/cleanup.sh
# Default working directory.

View file

@ -56,7 +56,7 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_UPLOAD_NSFW="true" \
PHOTOPRISM_DETECT_NSFW="false" \
PHOTOPRISM_EXPERIMENTAL="false" \
PHOTOPRISM_SITE_URL="http://photoprism.me:2342/" \
PHOTOPRISM_SITE_URL="http://localhost:2342/" \
PHOTOPRISM_SITE_CAPTION="AI-Powered Photos App" \
PHOTOPRISM_SITE_DESCRIPTION="" \
PHOTOPRISM_SITE_AUTHOR="" \
@ -86,7 +86,8 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_WORKERS=0 \
PHOTOPRISM_WAKEUP_INTERVAL=900 \
PHOTOPRISM_AUTO_INDEX=300 \
PHOTOPRISM_AUTO_IMPORT=300
PHOTOPRISM_AUTO_IMPORT=300 \
PHOTOPRISM_INIT="https"
# Copy scripts.
COPY --chown=root:root --chmod=755 /scripts/dist/ /scripts/

View file

@ -59,7 +59,7 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_UPLOAD_NSFW="true" \
PHOTOPRISM_DETECT_NSFW="false" \
PHOTOPRISM_EXPERIMENTAL="false" \
PHOTOPRISM_SITE_URL="http://photoprism.me:2342/" \
PHOTOPRISM_SITE_URL="http://localhost:2342/" \
PHOTOPRISM_SITE_CAPTION="AI-Powered Photos App" \
PHOTOPRISM_SITE_DESCRIPTION="" \
PHOTOPRISM_SITE_AUTHOR="" \
@ -89,7 +89,8 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_WORKERS=0 \
PHOTOPRISM_WAKEUP_INTERVAL=900 \
PHOTOPRISM_AUTO_INDEX=300 \
PHOTOPRISM_AUTO_IMPORT=300
PHOTOPRISM_AUTO_IMPORT=300 \
PHOTOPRISM_INIT="https"
# Copy dist files, scripts, and debian backports sources list.
COPY --from=build --chown=root:root --chmod=755 /opt/photoprism/ /opt/photoprism

View file

@ -59,7 +59,7 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_UPLOAD_NSFW="true" \
PHOTOPRISM_DETECT_NSFW="false" \
PHOTOPRISM_EXPERIMENTAL="false" \
PHOTOPRISM_SITE_URL="http://photoprism.me:2342/" \
PHOTOPRISM_SITE_URL="http://localhost:2342/" \
PHOTOPRISM_SITE_CAPTION="AI-Powered Photos App" \
PHOTOPRISM_SITE_DESCRIPTION="" \
PHOTOPRISM_SITE_AUTHOR="" \
@ -89,7 +89,8 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_WORKERS=0 \
PHOTOPRISM_WAKEUP_INTERVAL=900 \
PHOTOPRISM_AUTO_INDEX=300 \
PHOTOPRISM_AUTO_IMPORT=300
PHOTOPRISM_AUTO_IMPORT=300 \
PHOTOPRISM_INIT="https"
# Copy dist files and scripts.
COPY --from=build --chown=root:root --chmod=755 /opt/photoprism/ /opt/photoprism

View file

@ -57,7 +57,7 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_UPLOAD_NSFW="true" \
PHOTOPRISM_DETECT_NSFW="false" \
PHOTOPRISM_EXPERIMENTAL="false" \
PHOTOPRISM_SITE_URL="http://photoprism.me:2342/" \
PHOTOPRISM_SITE_URL="http://localhost:2342/" \
PHOTOPRISM_SITE_CAPTION="AI-Powered Photos App" \
PHOTOPRISM_SITE_DESCRIPTION="" \
PHOTOPRISM_SITE_AUTHOR="" \
@ -87,14 +87,15 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_WORKERS=0 \
PHOTOPRISM_WAKEUP_INTERVAL=900 \
PHOTOPRISM_AUTO_INDEX=300 \
PHOTOPRISM_AUTO_IMPORT=300
PHOTOPRISM_AUTO_IMPORT=300 \
PHOTOPRISM_INIT="https"
# Copy scripts.
COPY --chown=root:root --chmod=755 /scripts/dist/ /scripts/
# Update pre-installed packages.
RUN apt-get update && \
apt-get -qq upgrade && \
apt-get -qq dist-upgrade && \
/scripts/cleanup.sh
# Default working directory.

View file

@ -57,7 +57,7 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_UPLOAD_NSFW="true" \
PHOTOPRISM_DETECT_NSFW="false" \
PHOTOPRISM_EXPERIMENTAL="false" \
PHOTOPRISM_SITE_URL="http://photoprism.me:2342/" \
PHOTOPRISM_SITE_URL="http://localhost:2342/" \
PHOTOPRISM_SITE_CAPTION="AI-Powered Photos App" \
PHOTOPRISM_SITE_DESCRIPTION="" \
PHOTOPRISM_SITE_AUTHOR="" \
@ -87,14 +87,15 @@ ENV PHOTOPRISM_ARCH=$TARGETARCH \
PHOTOPRISM_WORKERS=0 \
PHOTOPRISM_WAKEUP_INTERVAL=900 \
PHOTOPRISM_AUTO_INDEX=300 \
PHOTOPRISM_AUTO_IMPORT=300
PHOTOPRISM_AUTO_IMPORT=300 \
PHOTOPRISM_INIT="https"
# Copy scripts.
COPY --chown=root:root --chmod=755 /scripts/dist/ /scripts/
# Update pre-installed packages.
RUN apt-get update && \
apt-get -qq upgrade && \
apt-get -qq dist-upgrade && \
/scripts/cleanup.sh
# Default working directory.

View file

@ -0,0 +1,114 @@
##################################################### BUILD STAGE ######################################################
FROM photoprism/develop:mantic as build
# Copyright © 2018 - 2023 PhotoPrism UG. All rights reserved.
#
# Questions? Email us at hello@photoprism.app or visit our website to learn
# more about our team, products and services: https://www.photoprism.app/
# Declare build parameters.
ARG TARGETARCH
ARG TARGETPLATFORM
ARG BUILD_TAG
# Copy source to image.
WORKDIR "/go/src/github.com/photoprism/photoprism"
COPY . .
# Build app.
RUN make all install DESTDIR=/opt/photoprism
################################################## PRODUCTION STAGE ####################################################
#### Base Image: Ubuntu 23.10 (Mantic Minotaur)
FROM photoprism/develop:mantic-slim
# Add Open Container Initiative (OCI) annotations.
# See: https://github.com/opencontainers/image-spec/blob/main/annotations.md
LABEL org.opencontainers.image.title="PhotoPrism® (Ubuntu 23.10)"
LABEL org.opencontainers.image.description="Ubuntu 23.10 (Mantic Minotaur)"
LABEL org.opencontainers.image.url="https://hub.docker.com/r/photoprism/photoprism"
LABEL org.opencontainers.image.source="https://github.com/photoprism/photoprism"
LABEL org.opencontainers.image.documentation="https://docs.photoprism.app/getting-started/"
LABEL org.opencontainers.image.authors="PhotoPrism UG <hello@photoprism.app>"
LABEL org.opencontainers.image.vendor="PhotoPrism UG"
# Declare build parameters.
ARG TARGETARCH
ARG BUILD_TAG
# Set environment variables, see https://docs.photoprism.app/getting-started/config-options/.
ENV PHOTOPRISM_ARCH=$TARGETARCH \
DOCKER_TAG=$BUILD_TAG \
DOCKER_ENV="prod" \
TMPDIR="/tmp" \
DEBIAN_FRONTEND="noninteractive" \
TF_CPP_MIN_LOG_LEVEL="2" \
PROG="photoprism" \
PHOTOPRISM_ASSETS_PATH="/opt/photoprism/assets" \
PHOTOPRISM_IMPORT_PATH="/photoprism/import" \
PHOTOPRISM_ORIGINALS_PATH="/photoprism/originals" \
PHOTOPRISM_STORAGE_PATH="/photoprism/storage" \
PHOTOPRISM_BACKUP_PATH="/photoprism/storage/backups" \
PHOTOPRISM_LOG_FILENAME="/photoprism/storage/photoprism.log" \
PHOTOPRISM_PID_FILENAME="/photoprism/storage/photoprism.pid" \
PHOTOPRISM_DEBUG="false" \
PHOTOPRISM_PUBLIC="false" \
PHOTOPRISM_READONLY="false" \
PHOTOPRISM_UPLOAD_NSFW="true" \
PHOTOPRISM_DETECT_NSFW="false" \
PHOTOPRISM_EXPERIMENTAL="false" \
PHOTOPRISM_SITE_URL="http://localhost:2342/" \
PHOTOPRISM_SITE_CAPTION="AI-Powered Photos App" \
PHOTOPRISM_SITE_DESCRIPTION="" \
PHOTOPRISM_SITE_AUTHOR="" \
PHOTOPRISM_HTTP_HOST="0.0.0.0" \
PHOTOPRISM_HTTP_PORT=2342 \
PHOTOPRISM_DATABASE_DRIVER="sqlite" \
PHOTOPRISM_DATABASE_SERVER="" \
PHOTOPRISM_DATABASE_NAME="photoprism" \
PHOTOPRISM_DATABASE_USER="photoprism" \
PHOTOPRISM_DATABASE_PASSWORD="" \
PHOTOPRISM_DISABLE_CHOWN="false" \
PHOTOPRISM_DISABLE_WEBDAV="false" \
PHOTOPRISM_DISABLE_SETTINGS="false" \
PHOTOPRISM_DISABLE_BACKUPS="false" \
PHOTOPRISM_DISABLE_EXIFTOOL="false" \
PHOTOPRISM_DISABLE_PLACES="false" \
PHOTOPRISM_DISABLE_TENSORFLOW="false" \
PHOTOPRISM_DISABLE_FACES="false" \
PHOTOPRISM_DISABLE_CLASSIFICATION="false" \
PHOTOPRISM_RAW_PRESETS="false" \
PHOTOPRISM_THUMB_FILTER="lanczos" \
PHOTOPRISM_THUMB_UNCACHED="false" \
PHOTOPRISM_THUMB_SIZE=2048 \
PHOTOPRISM_THUMB_SIZE_UNCACHED=7680 \
PHOTOPRISM_JPEG_SIZE=7680 \
PHOTOPRISM_JPEG_QUALITY=85 \
PHOTOPRISM_WORKERS=0 \
PHOTOPRISM_WAKEUP_INTERVAL=900 \
PHOTOPRISM_AUTO_INDEX=300 \
PHOTOPRISM_AUTO_IMPORT=300 \
PHOTOPRISM_INIT="https"
# Copy scripts.
COPY --chown=root:root --chmod=755 /scripts/dist/ /scripts/
# Update pre-installed packages.
RUN apt-get update && \
apt-get -qq dist-upgrade && \
/scripts/cleanup.sh
# Default working directory.
WORKDIR /photoprism
# Expose HTTP(S) ports.
EXPOSE 2342 2443
# Copy app files.
COPY --from=build --chown=root:root --chmod=755 /opt/photoprism/ /opt/photoprism
# Declare container entrypoint script.
ENTRYPOINT ["/scripts/entrypoint.sh"]
# Start app.
CMD ["/opt/photoprism/bin/photoprism", "start"]

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "photoprism",
"version": "1.0.0",
"version": "1",
"description": "AI-Powered Photos App",
"author": "PhotoPrism UG",
"license": "AGPL-3.0",
@ -20,45 +20,45 @@
"gettext-compile": "gettext-compile --output src/locales/translations.json src/locales/*.po"
},
"dependencies": {
"@babel/cli": "^7.21.5",
"@babel/core": "^7.21.8",
"@babel/eslint-parser": "^7.21.8",
"@babel/cli": "^7.23.0",
"@babel/core": "^7.23.2",
"@babel/eslint-parser": "^7.22.15",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-object-rest-spread": "^7.20.7",
"@babel/plugin-transform-runtime": "^7.21.4",
"@babel/preset-env": "^7.21.5",
"@babel/register": "^7.21.0",
"@babel/runtime": "^7.21.5",
"@babel/plugin-transform-runtime": "^7.23.2",
"@babel/preset-env": "^7.23.2",
"@babel/register": "^7.22.15",
"@babel/runtime": "^7.23.2",
"@lcdp/offline-plugin": "^5.1.1",
"@vvo/tzdb": "^6.107.0",
"axios": "^1.4.0",
"axios-mock-adapter": "^1.21.4",
"babel-loader": "^9.1.2",
"@vvo/tzdb": "^6.109.0",
"axios": "^1.6.0",
"axios-mock-adapter": "^1.22.0",
"babel-loader": "^9.1.3",
"babel-plugin-istanbul": "^6.1.1",
"browserslist": "^4.21.5",
"chai": "^4.3.7",
"browserslist": "^4.22.1",
"chai": "^4.3.10",
"cheerio": "1.0.0-rc.10",
"chrome-finder": "^1.0.7",
"core-js": "^3.30.2",
"core-js": "^3.33.1",
"cross-env": "^7.0.3",
"css-loader": "^6.7.3",
"cssnano": "^5.1.14",
"css-loader": "^6.8.1",
"cssnano": "^6.0.1",
"easygettext": "^2.17.0",
"eslint": "^8.40.0",
"eslint-config-prettier": "^8.8.0",
"eslint-config-standard": "^17.0.0",
"eslint": "^8.51.0",
"eslint-config-prettier": "^9.0.0",
"eslint-config-standard": "^17.1.0",
"eslint-formatter-pretty": "^5.0.0",
"eslint-plugin-html": "^7.1.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier-vue": "^4.2.0",
"eslint-plugin-prettier-vue": "^5.0.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-vue": "^9.13.0",
"eslint-plugin-vue": "^9.17.0",
"eslint-webpack-plugin": "^4.0.1",
"eventsource-polyfill": "^0.9.6",
"file-loader": "^6.2.0",
"file-saver": "^2.0.5",
"hls.js": "^1.2.9",
"hls.js": "^1.4.12",
"i": "^0.3.7",
"karma": "^6.4.2",
"karma-chrome-launcher": "^3.2.0",
@ -67,31 +67,31 @@
"karma-mocha": "^2.0.1",
"karma-verbose-reporter": "^0.0.8",
"karma-webpack": "^5.0.0",
"luxon": "^3.3.0",
"maplibre-gl": "^2.4.0",
"luxon": "^3.4.3",
"maplibre-gl": "^3.5.1",
"memoize-one": "^6.0.0",
"mini-css-extract-plugin": "^2.7.2",
"mini-css-extract-plugin": "^2.7.6",
"minimist": ">=1.2.5",
"mocha": "^10.2.0",
"node-storage-shim": "^2.0.1",
"photoswipe": "^4.1.3",
"postcss": "^8.4.20",
"postcss": "^8.4.31",
"postcss-import": "^15.1.0",
"postcss-loader": "^7.0.2",
"postcss-preset-env": "^7.8.3",
"postcss-loader": "^7.3.3",
"postcss-preset-env": "^9.2.0",
"postcss-reporter": "^7.0.5",
"postcss-url": "^10.1.3",
"prettier": "^2.8.8",
"prettier": "^3.0.3",
"pubsub-js": "^1.9.4",
"regenerator-runtime": "^0.13.11",
"regenerator-runtime": "^0.14.0",
"resolve-url-loader": "^5.0.0",
"sass": "^1.62.1",
"sass-loader": "^13.2.0",
"sass": "^1.69.4",
"sass-loader": "^13.3.2",
"server": "^1.0.38",
"sockette": "^2.0.6",
"style-loader": "^3.3.1",
"style-loader": "^3.3.3",
"svg-url-loader": "^8.0.0",
"tar": "^6.1.13",
"tar": "^6.2.0",
"url-loader": "^4.1.1",
"util": "^0.12.5",
"vue": "^2.7.14",
@ -106,17 +106,17 @@
"vue-template-compiler": "^2.7.13",
"vue2-filters": "^0.14.0",
"vuetify": "^1.5.24",
"webpack": "^5.83.0",
"webpack-bundle-analyzer": "^4.8.0",
"webpack-cli": "^5.1.1",
"webpack-hot-middleware": "^2.25.3",
"webpack": "^5.89.0",
"webpack-bundle-analyzer": "^4.9.1",
"webpack-cli": "^5.1.4",
"webpack-hot-middleware": "^2.25.4",
"webpack-manifest-plugin": "^5.0.0",
"webpack-md5-hash": "^0.0.6",
"webpack-merge": "^5.8.0"
"webpack-merge": "^5.10.0"
},
"engines": {
"node": ">= 16.0.0",
"npm": ">= 8.0.0",
"node": ">= 18.0.0",
"npm": ">= 9.0.0",
"yarn": "please use npm"
},
"browserslist": ">0.25% and last 2 years"

View file

@ -164,9 +164,9 @@ export default [
},
{
name: "moment",
path: "/moments/:uid/:slug",
path: "/moments/:album/:slug",
component: AlbumPhotos,
meta: { collName: "Moments", collRoute: "moments", auth: true },
meta: { collectionTitle: "Moments", collectionRoute: "moments", auth: true },
},
{
name: "albums",
@ -177,9 +177,9 @@ export default [
},
{
name: "album",
path: "/albums/:uid/:slug",
path: "/albums/:album/:slug",
component: AlbumPhotos,
meta: { collName: "Albums", collRoute: "albums", auth: true },
meta: { collectionTitle: "Albums", collectionRoute: "albums", auth: true },
},
{
name: "calendar",
@ -190,9 +190,9 @@ export default [
},
{
name: "month",
path: "/calendar/:uid/:slug",
path: "/calendar/:album/:slug",
component: AlbumPhotos,
meta: { collName: "Calendar", collRoute: "calendar", auth: true },
meta: { collectionTitle: "Calendar", collectionRoute: "calendar", auth: true },
},
{
name: "folders",
@ -203,9 +203,9 @@ export default [
},
{
name: "folder",
path: "/folders/:uid/:slug",
path: "/folders/:album/:slug",
component: AlbumPhotos,
meta: { collName: "Folders", collRoute: "folders", auth: true },
meta: { collectionTitle: "Folders", collectionRoute: "folders", auth: true },
},
{
name: "unsorted",
@ -263,16 +263,25 @@ export default [
meta: { title: $gettext("Places"), auth: true },
},
{
name: "places_query",
path: "/places/:q",
name: "places_view",
path: "/places/view/:s",
component: Places,
meta: { title: $gettext("Places"), auth: true },
},
{
name: "places_scope",
path: "/places/:s/:q",
component: Places,
name: "places_browse",
path: "/places/browse",
component: Photos,
meta: { title: $gettext("Places"), auth: true },
beforeEnter: (to, from, next) => {
if (session.loginRequired()) {
next({ name: "login" });
} else if (config.deny("photos", "search")) {
next({ name: "albums" });
} else {
next();
}
},
},
{
name: "states",
@ -283,9 +292,9 @@ export default [
},
{
name: "state",
path: "/states/:uid/:slug",
path: "/states/:album/:slug",
component: AlbumPhotos,
meta: { collName: "Places", collRoute: "states", auth: true },
meta: { collectionTitle: "Places", collectionRoute: "states", auth: true },
},
{
name: "files",

View file

@ -327,6 +327,12 @@ export default class Config {
case "files":
this.values.count.files += data.count;
break;
case "hidden":
this.values.count.hidden += data.count;
break;
case "archived":
this.values.count.archived += data.count;
break;
case "favorites":
this.values.count.favorites += data.count;
break;

View file

@ -84,11 +84,14 @@ export default class Session {
this.config.progress(80);
this.redeemToken(shared.token).finally(() => {
this.config.progress(99);
if (shared.uri) {
window.location = shared.uri;
} else {
window.location = this.config.baseUri + "/";
}
// Redirect URL.
const location = shared.uri ? shared.uri : this.config.baseUri + "/";
// Redirect to URL after one second.
setTimeout(() => {
window.location = location;
}, 1000);
});
} else {
this.config.progress(80);
@ -100,7 +103,7 @@ export default class Session {
}
useSessionStorage() {
this.deleteId();
this.reset();
this.storage.setItem(this.storage_key, "true");
this.storage = window.sessionStorage;
}
@ -112,7 +115,7 @@ export default class Session {
applyId(id) {
if (!id) {
this.deleteId();
this.reset();
return false;
}
@ -146,8 +149,6 @@ export default class Session {
this.storage.removeItem("session_id");
delete Api.defaults.headers.common[SessionHeader];
this.deleteAll();
}
setResp(resp) {
@ -272,9 +273,17 @@ export default class Session {
this.storage.removeItem("user");
}
deleteAll() {
deleteClipboard() {
this.storage.removeItem("clipboard");
this.storage.removeItem("photo_clipboard");
this.storage.removeItem("album_clipboard");
}
reset() {
this.deleteId();
this.deleteData();
this.deleteUser();
this.deleteClipboard();
}
sendClientInfo() {
@ -303,16 +312,20 @@ export default class Session {
}
login(username, password, token) {
this.deleteId();
this.reset();
return Api.post("session", { username, password, token }).then((resp) => {
const reload = this.config.getLanguage() !== resp.data?.config?.settings?.ui?.language;
this.setResp(resp);
this.sendClientInfo();
this.onLogin();
return Promise.resolve(reload);
});
}
onLogin() {
this.sendClientInfo();
}
refresh() {
// Refresh session information.
if (this.config.isPublic()) {
@ -330,7 +343,7 @@ export default class Session {
return Promise.resolve();
})
.catch(() => {
this.deleteId();
this.reset();
if (!this.isLogin()) {
window.location.reload();
}
@ -354,7 +367,7 @@ export default class Session {
}
onLogout(noRedirect) {
this.deleteId();
this.reset();
if (noRedirect !== true && !this.isLogin()) {
window.location = this.config.baseUri + "/";
}

View file

@ -153,6 +153,14 @@ export default class Util {
return s.replace(/\w\S*/g, (w) => w.replace(/^\w/, (c) => c.toUpperCase()));
}
static ucFirst(s) {
if (!s || s === "") {
return "";
}
return s.charAt(0).toUpperCase() + s.slice(1);
}
static generateToken() {
return (Math.random() + 1).toString(36).substring(6);
}
@ -171,6 +179,7 @@ export default class Util {
return "Unprocessed Sensor Data (RAW)";
case "mov":
case "qt":
case "qt ":
return "Apple QuickTime";
case "bmp":
return "Bitmap";
@ -193,8 +202,9 @@ export default class Util {
return "AOMedia Video 1 (AV1)";
case "avifs":
return "AVIF Image Sequence";
case "hevc":
case "hvc":
case "hevc":
case "hev1":
case "hvc1":
return "High Efficiency Video Coding (HEVC) / H.265";
case "m4v":
@ -235,6 +245,31 @@ export default class Util {
}
}
static formatCodec(codec) {
if (!codec) {
return "";
}
switch (codec) {
case "webp":
case "extended webp":
return "WebP";
case "webm":
return "WebM";
case "av1c":
case "av01":
return "AV1";
case "avc1":
return "AVC";
case "hvc":
case "hev1":
case "hvc1":
return "HEVC";
default:
return codec.toUpperCase();
}
}
static codecName(value) {
if (!value || typeof value !== "string") {
return "";
@ -245,16 +280,19 @@ export default class Util {
return "Unprocessed Sensor Data (RAW)";
case "mov":
case "qt":
case "qt ":
return "Apple QuickTime (MOV)";
case "avc":
case "avc1":
return "Advanced Video Coding (AVC) / H.264";
case "hevc":
case "hvc":
case "hevc":
case "hev1":
case "hvc1":
return "High Efficiency Video Coding (HEVC) / H.265";
case "vvc":
return "Versatile Video Coding (VVC) / H.266";
case "av1c":
case "av01":
return "AOMedia Video 1 (AV1)";
case "gif":
@ -263,6 +301,8 @@ export default class Util {
return "Matroska Multimedia Container (MKV)";
case "webp":
return "Google WebP";
case "extended webp":
return "Extended WebP";
case "webm":
return "Google WebM";
case "mpeg":

View file

@ -5,8 +5,8 @@
<v-toolbar flat :dense="$vuetify.breakpoint.smAndDown" class="page-toolbar" color="secondary">
<v-toolbar-title :title="album.Title">
<span class="hidden-xs-only">
<router-link :to="{ name: collRoute }">
{{ T(collName) }}
<router-link :to="{ name: collectionRoute }">
{{ T(collectionTitle) }}
</router-link>
<v-icon>{{ navIcon }}</v-icon>
</span>
@ -33,10 +33,12 @@
<v-icon>get_app</v-icon>
</v-btn>
<v-btn v-if="settings.view === 'cards'" icon class="action-view-list" :title="$gettext('Toggle View')" @click.stop="setView('list')">
<v-btn v-if="settings.view === 'cards'" icon class="action-view-list" :title="$gettext('Toggle View')"
@click.stop="setView('list')">
<v-icon>view_list</v-icon>
</v-btn>
<v-btn v-else-if="settings.view === 'list'" icon class="action-view-mosaic" :title="$gettext('Toggle View')" @click.stop="setView('mosaic')">
<v-btn v-else-if="settings.view === 'list'" icon class="action-view-mosaic" :title="$gettext('Toggle View')"
@click.stop="setView('mosaic')">
<v-icon>view_comfy</v-icon>
</v-btn>
<v-btn v-else icon class="action-view-cards" :title="$gettext('Toggle View')" @click.stop="setView('cards')">
@ -68,7 +70,8 @@
<p-share-dialog :show="dialog.share" :model="album" @upload="webdavUpload"
@close="dialog.share = false"></p-share-dialog>
<p-share-upload-dialog :show="dialog.upload" :items="{albums: album.getId()}" :model="album" @cancel="dialog.upload = false"
<p-share-upload-dialog :show="dialog.upload" :items="{albums: album.getId()}" :model="album"
@cancel="dialog.upload = false"
@confirm="dialog.upload = false"></p-share-upload-dialog>
<p-album-edit-dialog :show="dialog.edit" :album="album" @close="dialog.edit = false"></p-album-edit-dialog>
</v-form>
@ -77,34 +80,40 @@
import Event from "pubsub-js";
import Notify from "common/notify";
import download from "common/download";
import { T } from "common/vm";
import {T} from "common/vm";
export default {
name: 'PAlbumToolbar',
props: {
album: {
type: Object,
default: () => {},
default: () => {
},
},
filter: {
type: Object,
default: () => {},
default: () => {
},
},
updateFilter: {
type: Function,
default: () => {},
default: () => {
},
},
updateQuery: {
type: Function,
default: () => {},
default: () => {
},
},
settings: {
type: Object,
default: () => {},
default: () => {
},
},
refresh: {
type: Function,
default: () => {},
default: () => {
},
},
},
data() {
@ -125,8 +134,8 @@ export default {
experimental: this.$config.get("experimental"),
isFullScreen: !!document.fullscreenElement,
categories: this.$config.albumCategories(),
collName: this.$route.meta && this.$route.meta.collName ? this.$route.meta.collName : this.$gettext("Albums"),
collRoute: this.$route.meta && this.$route.meta.collRoute ? this.$route.meta.collRoute : "albums",
collectionTitle: this.$route.meta?.collectionTitle ? this.$route.meta.collectionTitle : this.$gettext("Albums"),
collectionRoute: this.$route.meta?.collectionRoute ? this.$route.meta.collectionRoute : "albums",
navIcon: this.$rtl ? 'navigate_before' : 'navigate_next',
searchExpanded: false,
options: {
@ -167,7 +176,12 @@ export default {
this.dialog.upload = true;
},
showUpload() {
Event.publish("dialog.upload");
// Pre-select manually managed albums in upload dialog.
if(this.album.Type === "album") {
Event.publish("dialog.upload", {albums: [this.album]});
} else {
Event.publish("dialog.upload", {albums: []});
}
},
expand() {
this.searchExpanded = !this.searchExpanded;

View file

@ -1,28 +1,23 @@
<template>
<div class="auth-footer">
<footer v-if="sponsor">
<footer>
<v-layout wrap align-top pa-0 ma-0>
<v-flex xs12 sm6 class="pa-0 body-2 text-selectable text-xs-center white--text text-sm-left">
{{ $config.getAbout() }}
{{ about }}
</v-flex>
<v-flex v-if="config.legalInfo" xs12 sm6 class="pa-0 body-2 text-xs-center text-sm-right white--text">
<a v-if="config.legalUrl" :href="config.legalUrl" target="_blank" class="text-link"
:style="`color: ${colors.link}!important`">{{ config.legalInfo }}</a>
<span v-else>{{ config.legalInfo }}</span>
<v-flex v-if="legalInfo" xs12 sm6 class="pa-0 body-2 text-xs-center text-sm-right white--text">
<a v-if="legalUrl" :href="legalUrl" target="_blank" class="text-link"
:style="`color: ${colors.link}!important`">{{ legalInfo }}</a>
<span v-else>{{ legalInfo }}</span>
</v-flex>
<v-flex v-else xs12 class="pa-0 body-2 text-selectable text-xs-center white--text text-sm-right sm6">
<strong>{{ config.siteCaption ? config.siteCaption : config.siteTitle }}</strong>
<v-flex v-else-if="caption" xs12 sm6
class="pa-0 body-2 text-selectable text-xs-center text-sm-right white--text">
<strong>{{ caption }}</strong>
</v-flex>
</v-layout>
</footer>
<footer v-else>
<v-layout wrap align-top pa-0 ma-0>
<v-flex xs12 sm6 class="pa-0 body-2 text-xs-center text-sm-left white--text text-selectable">
<strong>{{ config.siteTitle }}</strong> {{ config.siteCaption }}
</v-flex>
<v-flex xs12 sm6 class="pa-0 body-2 text-selectable text-xs-center text-sm-right">
<router-link to="/about" class="text-link"><span class="white--text">Made with in Berlin</span></router-link>
<v-flex v-else xs12 sm6 class="pa-0 body-2 text-selectable text-xs-center text-sm-right white--text">
<router-link to="/about" class="text-link"><span class="white--text">Made with in Berlin</span>
</router-link>
</v-flex>
</v-layout>
</footer>
@ -46,9 +41,14 @@ export default {
},
},
data() {
const config = this.$config;
return {
sponsor: this.$config.isSponsor(),
config: this.$config.values,
about: config.getAbout(),
sponsor: config.isSponsor(),
caption: config.values.siteCaption ? config.values.siteCaption : config.values.siteTitle,
legalUrl: config.values.legalUrl,
legalInfo: config.values.legalInfo,
config: config.values,
rtl: this.$rtl,
};
},

View file

@ -33,6 +33,7 @@ import PPhotoToolbar from "component/photo/toolbar.vue";
import PPhotoCards from "component/photo/cards.vue";
import PPhotoMosaic from "component/photo/mosaic.vue";
import PPhotoList from "component/photo/list.vue";
import PPhotoPreview from "component/photo/preview.vue";
import PPhotoClipboard from "component/photo/clipboard.vue";
import PAlbumClipboard from "component/album/clipboard.vue";
import PAlbumToolbar from "component/album/toolbar.vue";
@ -59,6 +60,7 @@ components.install = (Vue) => {
Vue.component("PPhotoCards", PPhotoCards);
Vue.component("PPhotoMosaic", PPhotoMosaic);
Vue.component("PPhotoList", PPhotoList);
Vue.component("PPhotoPreview", PPhotoPreview);
Vue.component("PPhotoClipboard", PPhotoClipboard);
Vue.component("PAlbumClipboard", PAlbumClipboard);
Vue.component("PAlbumToolbar", PAlbumToolbar);

View file

@ -65,7 +65,7 @@
</v-list>
</v-toolbar>
<v-list class="pt-3 p-flex-menu">
<v-list class="pt-3 p-flex-menu navigation-menu">
<v-list-tile v-if="isMini && !isRestricted" class="nav-expand" @click.stop="toggleIsMini()">
<v-list-tile-action :title="$gettext('Expand')">
<v-icon v-if="!rtl">chevron_right</v-icon>
@ -165,6 +165,8 @@
<v-list-tile-content>
<v-list-tile-title :class="`p-flex-menuitem menu-item ${rtl ? '--rtl' : ''}`">
<translate>Archive</translate>
<span v-show="config.count.archived > 0"
:class="`nav-count ${rtl ? '--rtl' : ''}`">{{ config.count.archived | abbreviateCount }}</span>
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
@ -522,6 +524,18 @@
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile v-show="featMembership" :to="{ name: 'upgrade' }" class="nav-membership" @click.stop="">
<v-list-tile-action :title="$gettext('Support Our Mission')">
<v-icon>diamond</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>
<translate key="Support Our Mission">Support Our Mission</translate>
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
<v-list class="p-user-box">
@ -539,7 +553,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile v-show="auth && !isPublic && $config.feature('account')" class="p-profile" @click.stop="onAccount">
<v-list-tile v-show="auth && !isPublic" class="p-profile" @click.stop="onAccountSettings">
<v-list-tile-avatar size="36">
<img :src="userAvatarURL" :alt="accountInfo" :title="accountInfo">
</v-list-tile-avatar>
@ -664,7 +678,7 @@
<span v-else>{{ config.legalInfo }}</span>
</div>
<p-reload-dialog :show="reload.dialog" @close="reload.dialog = false"></p-reload-dialog>
<p-upload-dialog :show="upload.dialog" @cancel="upload.dialog = false"
<p-upload-dialog :show="upload.dialog" :data="upload.data" @cancel="upload.dialog = false"
@confirm="upload.dialog = false"></p-upload-dialog>
<p-photo-edit-dialog :show="edit.dialog" :selection="edit.selection" :index="edit.index" :album="edit.album"
@close="edit.dialog = false"></p-photo-edit-dialog>
@ -673,6 +687,7 @@
<script>
import Event from "pubsub-js";
import Album from "model/album";
export default {
name: "PNavigation",
@ -702,6 +717,7 @@ export default {
const isReadOnly = this.$config.get("readonly");
const isRestricted = this.$config.deny("photos", "access_library");
const isSuperAdmin = this.$session.isSuperAdmin();
const tier = this.$config.getTier();
return {
canSearchPlaces: this.$config.allow("places", "search"),
@ -715,7 +731,8 @@ export default {
appIcon: this.$config.getIcon(),
indexing: false,
drawer: null,
featUpgrade: this.$config.getTier() < 8 && isSuperAdmin && !isPublic && !isDemo,
featUpgrade: tier < 6 && isSuperAdmin && !isPublic && !isDemo,
featMembership: tier < 3 && isSuperAdmin && !isPublic && !isDemo,
isRestricted: isRestricted,
isMini: localStorage.getItem('last_navigation_mode') !== 'false' || isRestricted,
isDemo: isDemo,
@ -734,6 +751,7 @@ export default {
},
upload: {
dialog: false,
data: {},
},
edit: {
dialog: false,
@ -777,7 +795,14 @@ export default {
this.subscriptions.push(Event.subscribe('index', this.onIndex));
this.subscriptions.push(Event.subscribe('import', this.onIndex));
this.subscriptions.push(Event.subscribe("dialog.reload", () => this.reload.dialog = true));
this.subscriptions.push(Event.subscribe("dialog.upload", () => this.upload.dialog = true));
this.subscriptions.push(Event.subscribe("dialog.upload", (ev, data) => {
if(data) {
this.upload.data = data;
} else {
this.upload.data = {};
}
this.upload.dialog = true;
}));
this.subscriptions.push(Event.subscribe("dialog.edit", (ev, data) => {
if (!this.edit.dialog) {
this.edit.dialog = true;
@ -807,7 +832,18 @@ export default {
},
openUpload() {
if (this.auth && !this.isReadOnly && this.$config.feature('upload')) {
this.upload.dialog = true;
if (this.$route.name === 'album' && this.$route.params?.album) {
return new Album().find(this.$route.params?.album).then(m => {
this.upload.dialog = true;
this.upload.data = {albums: [m]};
}).catch(() => {
this.upload.dialog = true;
this.upload.data = {albums: []};
});
} else {
this.upload.dialog = true;
this.upload.data = {albums: []};
}
} else {
this.goHome();
}
@ -827,8 +863,12 @@ export default {
this.isMini = !this.isMini;
localStorage.setItem('last_navigation_mode', `${this.isMini}`);
},
onAccount: function () {
this.$router.push({name: "settings_account"});
onAccountSettings: function () {
if (this.$config.feature('account')) {
this.$router.push({name: "settings_account"});
} else {
this.$router.push({name: "settings"});
}
},
onInfo() {
if (this.isSponsor && this.config.legalUrl) {

View file

@ -31,7 +31,7 @@
ref="items"
:key="photo.ID"
:data-index="index"
class="flex xs12 sm6 md4 lg3 xlg2 xxxl1 d-flex"
class="flex xs12 sm6 md4 lg3 xlg2 ul1 d-flex"
>
<div v-if="index < firstVisibleElementIndex || index > lastVisibileElementIndex"
:data-uid="photo.UID"
@ -92,7 +92,7 @@
>
<v-layout v-if="photo.Type === 'live' || photo.Type === 'animated'" class="live-player">
<video :id="'live-player-' + photo.ID" :key="photo.ID" width="500" height="500" preload="none"
loop muted playsinline>
loop muted playsinline>
<source :src="photo.videoUrl()">
</video>
</v-layout>
@ -203,6 +203,11 @@
<i>movie</i>
{{ photo.getVideoInfo() }}
</button>
<button v-else-if="photo.Type === 'live'" :title="$gettext('Live')"
@click.exact="openPhoto(index)">
<i>play_circle</i>
{{ photo.getVideoInfo() }}
</button>
<button v-else-if="photo.Type === 'animated'" :title="$gettext('Animated')+' GIF'"
@click.exact="openPhoto(index)">
<i>gif_box</i>
@ -218,6 +223,11 @@
<i>photo_camera</i>
{{ photo.getPhotoInfo() }}
</button>
<button v-if="photo.LensID > 1 || photo.FocalLength" :title="$gettext('Lens')" class="action-lens-edit"
:data-uid="photo.UID" @click.exact="editPhoto(index)">
<i>camera</i>
{{ photo.getLensInfo() }}
</button>
<template v-if="filter.order === 'name' && $config.feature('download')">
<br>
<button :title="$gettext('Name')"
@ -457,7 +467,7 @@ export default {
/**
* updating the clipboard does not rerender this component. Because of that
* there can be scenarios where the select-icon is missing after a change,
* for example when selecting mutliple elements at once. We therefore
* for example when selecting multiple elements at once. We therefore
* force an update to fix that.
*/
this.$forceUpdate();

View file

@ -163,6 +163,10 @@ import Photo from "model/photo";
export default {
name: 'PPhotoClipboard',
props: {
context: {
type: String,
default: 'photos',
},
selection: {
type: Array,
default: () => [],
@ -175,10 +179,6 @@ export default {
type: Object,
default: () => {},
},
context: {
type: String,
default: '',
},
},
data() {
const features = this.$config.settings().features;

View file

@ -1,6 +1,6 @@
<template>
<v-container grid-list-xs fluid class="pa-2 p-photos p-photo-mosaic">
<template v-if="photos.length === 0">
<div v-if="photos.length === 0" class="pa-0">
<v-alert
:value="true"
color="secondary-dark"
@ -24,7 +24,7 @@
</template>
</p>
</v-alert>
</template>
</div>
<v-layout row wrap class="search-results photo-results mosaic-view" :class="{'select-results': selectMode}">
<div
v-for="(photo, index) in photos"
@ -60,7 +60,7 @@
@mouseleave="pauseLive(photo)">
<v-layout v-if="photo.Type === 'live' || photo.Type === 'animated'" class="live-player">
<video :id="'live-player-' + photo.ID" :key="photo.ID" width="224" height="224" preload="none"
loop muted playsinline>
loop muted playsinline>
<source :src="photo.videoUrl()">
</video>
</v-layout>

View file

@ -0,0 +1,49 @@
<template>
<div class="p-photo-preview pa-0 ma-0 elevation-0 v-card v-sheet v-sheet--tile no-transition" :title="title">
<div class="v-responsive v-image card darken-1 elevation-0 clickable" @click.prevent.stop="openPhoto">
<div class="v-responsive__sizer" style="padding-bottom: 100%;"></div>
<div class="v-image__image v-image__image--cover" :style="cover"></div>
<div class="v-responsive__content"></div>
</div>
</div>
</template>
<script>
import Photo from "model/photo";
import Thumb from "model/thumb";
export default {
name: 'PPhotoPreview',
props: {
model: {
type: Object,
default: () => new Photo(false),
},
},
data() {
return {
url: this.model.thumbnailUrl('tile_500'),
title: this.model.Title ? this.model.Title : '',
};
},
computed: {
cover() {
return `background-image: url('${this.url}'); background-position: center center;`;
},
},
watch: {
model() {
this.url = this.model.thumbnailUrl('tile_500');
this.title = this.model.Title ? this.model.Title : '';
},
},
methods: {
openPhoto() {
if (!this.$viewer || !this.model) {
return;
}
this.$viewer.show(Thumb.fromFiles([this.model]), 0);
},
},
};
</script>

View file

@ -1,46 +1,68 @@
<template>
<v-form ref="form" lazy-validation
dense autocomplete="off" class="p-photo-toolbar" accept-charset="UTF-8"
:class="{'embedded': embedded}"
@submit.prevent="updateQuery()">
<v-toolbar flat :dense="$vuetify.breakpoint.smAndDown" class="page-toolbar" color="secondary">
<v-text-field :value="filter.q"
class="input-search background-inherit elevation-0"
solo hide-details clearable overflow single-line
validate-on-blur
autocorrect="off"
autocapitalize="none"
browser-autocomplete="off"
:label="$gettext('Search')"
prepend-inner-icon="search"
color="secondary-dark"
@change="(v) => {updateFilter({'q': v})}"
@keyup.enter.native="(e) => updateQuery({'q': e.target.value})"
@click:clear="() => {updateQuery({'q': ''})}"
></v-text-field>
<v-toolbar flat :dense="$vuetify.breakpoint.smAndDown" :height="embedded ? 45 : undefined"
class="page-toolbar" color="secondary">
<template v-if="!embedded">
<v-text-field :value="filter.q"
class="input-search background-inherit elevation-0"
solo hide-details clearable overflow single-line validate-on-blur
autocorrect="off"
autocapitalize="none"
browser-autocomplete="off"
:label="$gettext('Search')"
prepend-inner-icon="search"
color="secondary-dark"
@change="(v) => {updateFilter({'q': v})}"
@keyup.enter.native="(e) => updateQuery({'q': e.target.value})"
@click:clear="() => {updateQuery({'q': ''})}"
></v-text-field>
<v-btn icon class="hidden-xs-only action-reload" :title="$gettext('Reload')" @click.stop="refresh()">
<v-icon>refresh</v-icon>
</v-btn>
<v-btn v-if="filter.latlng" icon :title="$gettext('Show more')" class="action-clear-location" @click.stop="clearLocation()">
<v-icon>location_off</v-icon>
</v-btn>
<v-btn v-if="settings.view === 'cards'" icon :title="$gettext('Toggle View')" @click.stop="setView('list')">
<v-icon>view_list</v-icon>
</v-btn>
<v-btn v-else-if="settings.view === 'list'" icon :title="$gettext('Toggle View')" @click.stop="setView('mosaic')">
<v-icon>view_comfy</v-icon>
</v-btn>
<v-btn v-else icon :title="$gettext('Toggle View')" @click.stop="setView('cards')">
<v-icon>view_column</v-icon>
</v-btn>
<v-btn icon class="hidden-xs-only action-reload" :title="$gettext('Reload')" @click.stop="refresh()">
<v-icon>refresh</v-icon>
</v-btn>
<v-btn v-if="!$config.values.readonly && $config.feature('upload')" icon class="hidden-sm-and-down action-upload"
:title="$gettext('Upload')" @click.stop="showUpload()">
<v-icon>cloud_upload</v-icon>
</v-btn>
<v-btn v-if="settings.view === 'cards'" icon :title="$gettext('Toggle View')" @click.stop="setView('list')">
<v-icon>view_list</v-icon>
</v-btn>
<v-btn v-else-if="settings.view === 'list'" icon :title="$gettext('Toggle View')"
@click.stop="setView('mosaic')">
<v-icon>view_comfy</v-icon>
</v-btn>
<v-btn v-else icon :title="$gettext('Toggle View')" @click.stop="setView('cards')">
<v-icon>view_column</v-icon>
</v-btn>
<v-btn icon class="p-expand-search" :title="$gettext('Expand Search')"
@click.stop="searchExpanded = !searchExpanded">
<v-icon>{{ searchExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}</v-icon>
</v-btn>
<v-btn v-if="canDelete && context === 'archive' && config.count.archived > 0" icon
class="hidden-sm-and-down action-delete-all"
:title="$gettext('Delete All')" @click.stop="deleteAll()">
<v-icon>delete_sweep</v-icon>
</v-btn>
<v-btn v-else-if="canUpload" icon class="hidden-sm-and-down action-upload"
:title="$gettext('Upload')" @click.stop="showUpload()">
<v-icon>cloud_upload</v-icon>
</v-btn>
<v-btn icon class="p-expand-search" :title="$gettext('Expand Search')"
@click.stop="searchExpanded = !searchExpanded">
<v-icon>{{ searchExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}</v-icon>
</v-btn>
</template>
<template v-else>
<v-spacer></v-spacer>
<v-btn v-if="canAccessLibrary" icon :title="$gettext('Browse')" class="action-browse" @click.stop="onBrowse">
<v-icon size="20">tab</v-icon>
</v-btn>
<v-btn v-if="onClose !== undefined" icon :title="$gettext('Close')" class="action-close" @click.stop="onClose">
<v-icon>close</v-icon>
</v-btn>
</template>
</v-toolbar>
<v-card v-show="searchExpanded"
@ -166,41 +188,77 @@
</v-layout>
</v-card-text>
</v-card>
<p-photo-delete-dialog
:show="dialog.delete"
:text="$gettext('Are you sure you want to delete all archived pictures?')"
:action="$gettext('Delete All')"
@cancel="dialog.delete = false" @confirm="batchDelete">
</p-photo-delete-dialog>
</v-form>
</template>
<script>
import Event from "pubsub-js";
import * as options from "options/options";
import Api from "common/api";
import Notify from "common/notify";
export default {
name: 'PPhotoToolbar',
props: {
context: {
type: String,
default: 'photos',
},
filter: {
type: Object,
default: () => {},
default: () => {
},
},
staticFilter: {
type: Object,
default: () => {
},
},
updateFilter: {
type: Function,
default: () => {},
default: () => {
},
},
updateQuery: {
type: Function,
default: () => {},
default: () => {
},
},
settings: {
type: Object,
default: () => {},
default: () => {
},
},
refresh: {
type: Function,
default: () => {},
default: () => {
},
},
onClose: {
type: Function,
default: undefined,
},
embedded: {
type: Boolean,
default: false
},
},
data() {
const features = this.$config.settings().features;
const readonly = this.$config.get("readonly");
return {
experimental: this.$config.get("experimental"),
isFullScreen: !!document.fullscreenElement,
config: this.$config.values,
readonly: readonly,
canUpload: !readonly && !this.embedded && this.$config.allow("files", "upload") && features.upload,
canDelete: !readonly && !this.embedded && this.$config.allow("photos", "delete") && features.delete,
canAccessLibrary: this.$config.allow("photos", "access_library"),
searchExpanded: false,
all: {
countries: [{ID: "", Name: this.$gettext("All Countries")}],
@ -229,6 +287,9 @@ export default {
{value: 'similar', text: this.$gettext('Visual Similarity')},
],
},
dialog: {
delete: false,
},
};
},
computed: {
@ -262,7 +323,37 @@ export default {
},
showUpload() {
Event.publish("dialog.upload");
}
},
deleteAll() {
if (!this.canDelete) {
return;
}
this.dialog.delete = true;
},
clearLocation() {
this.$router.push({ name: "browse" });
},
onBrowse() {
const route = {name: 'places_browse', query: this.staticFilter};
const routeUrl = this.$router.resolve(route).href;
if (routeUrl) {
window.open(routeUrl, '_blank');
}
},
batchDelete() {
if (!this.canDelete) {
return;
}
this.dialog.delete = false;
Api.post("batch/photos/delete", {"all": true}).then(() => this.onDeleted());
},
onDeleted() {
Notify.success(this.$gettext("Permanently deleted"));
this.$clipboard.clear();
},
},
};
</script>

View file

@ -0,0 +1,102 @@
export default class MapStyleControl {
constructor(styles, defaultStyle, setStyle) {
this.styles = styles || MapStyleControl.DEFAULT_STYLES;
this.defaultStyle = defaultStyle || MapStyleControl.DEFAULT_STYLE;
this.setStyle = setStyle;
this.onDocumentClick = this.onDocumentClick.bind(this);
}
getDefaultPosition() {
return "top-right";
}
onAdd(map) {
this.map = map;
this.controlContainer = document.createElement("div");
this.controlContainer.classList.add("maplibregl-ctrl");
this.controlContainer.classList.add("maplibregl-ctrl-group");
this.mapStyleContainer = document.createElement("div");
this.styleButton = document.createElement("button");
this.styleButton.type = "button";
this.mapStyleContainer.classList.add("maplibregl-style-list");
for (const style of this.styles) {
const styleElement = document.createElement("button");
styleElement.type = "button";
styleElement.innerText = style.title;
styleElement.classList.add(style.style, "_");
styleElement.dataset.style = JSON.stringify(style.style);
styleElement.addEventListener("click", (event) => {
const srcElement = event.srcElement;
if (srcElement.classList.contains("active")) {
this.mapStyleContainer.style.display = "none";
this.styleButton.style.display = "block";
return;
}
// Set new map style.
if (typeof this.setStyle === "function") {
this.setStyle(JSON.parse(srcElement.dataset.style));
}
/*
this.mapStyleContainer.style.display = "none";
this.styleButton.style.display = "block";
const elms = this.mapStyleContainer.getElementsByClassName("active");
while (elms[0]) {
elms[0].classList.remove("active");
}
srcElement.classList.add("active");
*/
});
if (style.style === this.defaultStyle) {
styleElement.classList.add("active");
}
this.mapStyleContainer.appendChild(styleElement);
}
this.styleButton.classList.add("maplibregl-ctrl-icon");
this.styleButton.classList.add("maplibregl-style-switcher");
this.styleButton.addEventListener("click", () => {
this.styleButton.style.display = "none";
this.mapStyleContainer.style.display = "block";
});
document.addEventListener("click", this.onDocumentClick);
this.controlContainer.appendChild(this.styleButton);
this.controlContainer.appendChild(this.mapStyleContainer);
return this.controlContainer;
}
onRemove() {
if (
!this.controlContainer ||
!this.controlContainer.parentNode ||
!this.map ||
!this.styleButton
) {
return;
}
this.styleButton.removeEventListener("click", this.onDocumentClick);
this.controlContainer.parentNode.removeChild(this.controlContainer);
document.removeEventListener("click", this.onDocumentClick);
this.map = undefined;
}
onDocumentClick(event) {
if (
this.controlContainer &&
!this.controlContainer.contains(event.target) &&
this.mapStyleContainer &&
this.styleButton
) {
this.mapStyleContainer.style.display = "none";
this.styleButton.style.display = "block";
}
}
}
MapStyleControl.DEFAULT_STYLE = "default";
MapStyleControl.DEFAULT_STYLES = [
{
title: "Default",
style: "default",
},
];

View file

@ -1,8 +1,8 @@
<template>
<div class="video-wrapper" :style="style">
<video :key="source" ref="video" class="video-player" :height="height" :width="width" :autoplay="autoplay"
:style="style" :poster="poster" :loop="loop" preload="auto" controls playsinline @click.stop
@keydown.esc.stop.prevent="$emit('close')">
:style="style" :poster="poster" :loop="loop" preload="auto" controls playsinline
@click.stop @keydown.esc.stop.prevent="$emit('close')">
<source :src="source">
</video>
</div>
@ -85,8 +85,7 @@ export default {
return this.$el.getElementsByTagName('video')[0];
},
updateStyle() {
// this.style = `width: ${this.width.toString()}px; height: ${this.height.toString()}px`;
this.style = `width:100%; height: 100%`;
this.style = `width: ${this.width.toString()}px; height: ${this.height.toString()}px`;
this.$el.style.cssText = this.style;
},
render() {

View file

@ -38,7 +38,7 @@ Additional information can be found in our Developer Guide:
@import url("viewer.css");
@import url("tables.css");
@import url("results.css");
@import url("maps.css");
@import url("places.css");
@import url("labels.css");
@import url("files.css");
@import url("pages.css");
@ -68,7 +68,7 @@ main {
z-index: 1;
}
/* Page Overlay */
/* Loading Animations */
#busy-overlay {
display: none;

View file

@ -1,32 +1,49 @@
/* Layout Breakpoints */
@media (min-width: 1750px) {
/* Extra Large (XL) */
.flex.xlg2 {
flex-basis: 16.666666666666664%;
flex-grow: 0;
max-width: 16.666666666666664%;
}
.flex.xlg10 {
flex-basis: 83.333333333333332%;
flex-grow: 0;
max-width: 83.333333333333332%;
}
}
@media (min-width: 2400px) {
/* Extra Extra Large (XXL) */
.flex.xxl1 {
flex-basis: 8.333333333333332%;
flex-grow: 0;
max-width: 8.333333333333332%;
}
.flex.xxl11 {
flex-basis: 91.66666666666667%;
flex-grow: 0;
max-width: 91.66666666666667%;
}
}
@media (min-width: 2550px) {
.flex.xxxl1 {
@media (min-width: 2800px) {
/* Ultra Large (UL) */
.flex.ul1 {
flex-basis: 8.333333333333332%;
flex-grow: 0;
max-width: 8.333333333333332%;
}
.flex.ul11 {
flex-basis: 91.66666666666667%;
flex-grow: 0;
max-width: 91.66666666666667%;
}
}
/* Layout Widths */
.width-sm, .width-md, .width-lg {
margin-left: auto;
margin-right: auto;
@ -95,6 +112,13 @@
border-radius: 6px;
}
.ra-2,
.ra-2 > a,
.rounded-2,
.rounded-2 > a {
border-radius: 2px !important;
}
.ra-3,
.ra-3 > a,
.rounded-3,
@ -137,6 +161,13 @@
border-radius: 10px !important;
}
.ra-24,
.ra-24 > a,
.rounded-24,
.rounded-24 > a {
border-radius: 24px !important;
}
#photoprism div.v-dialog.v-dialog--fullscreen > div.v-card {
border-radius: 0;
}
@ -150,6 +181,30 @@
border-radius: 5px 5px 0 0;
}
/* Responsive Layout Styles */
@media only screen and (min-width: 960px) {
.pa-1-md-and-up {
padding: 4px!important;
}
.pa-2-md-and-up {
padding: 8px!important;
}
.pa-3-md-and-up {
padding: 16px!important;
}
.pa-3-md-and-up {
padding: 24px!important;
}
.ra-4-table-md-and-up table.v-table {
border-radius: 4px !important;
}
}
/* Page Footer */
footer {

View file

@ -1,3 +1,4 @@
/* Event Logs */
#photoprism .p-logs {
color: white;

View file

@ -1,26 +0,0 @@
#photoprism .map-control {
position: absolute;
background: transparent;
bottom: 35px;
right: 30px;
z-index: 2;
}
#photoprism.is-rtl .map-control {
right: auto;
left: 30px;
}
#photoprism #map .marker {
box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12) !important;
background-color: rgba(0, 0, 0, 0.3);
border-color: #fff;
color: rgba(0, 0, 0, 0.87);
display: block;
border-radius: 50%;
cursor: pointer;
}
#photoprism .maplibregl-ctrl-attrib-inner a {
color: #333 !important;
}

View file

@ -1,3 +1,5 @@
/* App Navigation */
#p-navigation {
z-index: 10;
}
@ -120,6 +122,12 @@ nav .v-list__tile__title.title {
overflow: hidden;
}
#photoprism .p-photo-toolbar.embedded {
position: sticky;
top: 0;
z-index: 1;
}
.p-user-box {
width: 100%;
padding: 0;
@ -307,4 +315,4 @@ nav .v-list__tile__title.title {
#photoprism #mobile-menu .menu-action:hover a i{
fill: #ffffff;
color: #ffffff;
}
}

148
frontend/src/css/places.css Normal file
View file

@ -0,0 +1,148 @@
/* Maps & Places */
#photoprism .map-control {
position: absolute;
background: transparent;
top: 10px;
left: 10px;
z-index: 2;
}
#photoprism.is-rtl .map-control {
left: auto;
right: 10px;
}
#photoprism .map-control .map-control-search {
overflow: hidden;
border-radius: 24px;
}
#photoprism #map .marker {
box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12) !important;
background-color: rgba(23, 23, 23, 0.23);
color: rgba(0, 0, 0, 0.87);
display: block;
border-radius: 50%;
cursor: pointer;
border: 1px solid #ffffff99;
}
#photoprism #map .cluster-marker {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 1px;
overflow: hidden;
/* background-color: #ffffff99; */
width: 100%;
height: 100%
}
#photoprism #map .counter-bubble {
border-radius: 100%;
position: absolute;
width: 24px;
height: 24px;
font-size: 12px;
display: flex;
color: #ffffff;
top: -5px;
right: -5px;
align-items: center;
justify-content: center;
box-shadow: 0px 3px 1px -2px rgb(0 0 0 / 20%), 0px 2px 2px 0px rgb(0 0 0 / 14%), 0px 1px 5px 0px rgb(0 0 0 / 12%);
}
#photoprism #map .cluster-marker > div {
width: 100%;
height: 100%;
background-size: cover;
}
#photoprism .maplibregl-ctrl-attrib-inner a {
color: #333 !important;
}
#photoprism .maplibregl-style-list {
display: none;
}
#photoprism .maplibregl-ctrl-group .maplibregl-style-list button {
background: none;
border: none;
cursor: pointer;
display: block;
font-size: 14px;
padding: 8px 8px 6px;
text-align: right;
width: 100%;
height: auto;
color: #000000;
}
#photoprism .maplibregl-style-list button.active {
font-weight: bold;
}
#photoprism .maplibregl-style-list button:hover {
background-color: rgba(0, 0, 0, 0.05);
}
#photoprism .maplibregl-style-list button + button {
border-top: 1px solid #ddd;
}
#photoprism .maplibregl-style-switcher {
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iNTQuODQ5cHgiIGhlaWdodD0iNTQuODQ5cHgiIHZpZXdCb3g9IjAgMCA1NC44NDkgNTQuODQ5IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1NC44NDkgNTQuODQ5OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PGc+PGc+PGc+PHBhdGggZD0iTTU0LjQ5NywzOS42MTRsLTEwLjM2My00LjQ5bC0xNC45MTcsNS45NjhjLTAuNTM3LDAuMjE0LTEuMTY1LDAuMzE5LTEuNzkzLDAuMzE5Yy0wLjYyNywwLTEuMjU0LTAuMTA0LTEuNzktMC4zMThsLTE0LjkyMS01Ljk2OEwwLjM1MSwzOS42MTRjLTAuNDcyLDAuMjAzLTAuNDY3LDAuNTI0LDAuMDEsMC43MTZMMjYuNTYsNTAuODFjMC40NzcsMC4xOTEsMS4yNTEsMC4xOTEsMS43MjksMEw1NC40ODgsNDAuMzNDNTQuOTY0LDQwLjEzOSw1NC45NjksMzkuODE3LDU0LjQ5NywzOS42MTR6Ii8+PHBhdGggZD0iTTU0LjQ5NywyNy41MTJsLTEwLjM2NC00LjQ5MWwtMTQuOTE2LDUuOTY2Yy0wLjUzNiwwLjIxNS0xLjE2NSwwLjMyMS0xLjc5MiwwLjMyMWMtMC42MjgsMC0xLjI1Ni0wLjEwNi0xLjc5My0wLjMyMWwtMTQuOTE4LTUuOTY2TDAuMzUxLDI3LjUxMmMtMC40NzIsMC4yMDMtMC40NjcsMC41MjMsMC4wMSwwLjcxNkwyNi41NiwzOC43MDZjMC40NzcsMC4xOSwxLjI1MSwwLjE5LDEuNzI5LDBsMjYuMTk5LTEwLjQ3OUM1NC45NjQsMjguMDM2LDU0Ljk2OSwyNy43MTYsNTQuNDk3LDI3LjUxMnoiLz48cGF0aCBkPSJNMC4zNjEsMTYuMTI1bDEzLjY2Miw1LjQ2NWwxMi41MzcsNS4wMTVjMC40NzcsMC4xOTEsMS4yNTEsMC4xOTEsMS43MjksMGwxMi41NDEtNS4wMTZsMTMuNjU4LTUuNDYzYzAuNDc3LTAuMTkxLDAuNDgtMC41MTEsMC4wMS0wLjcxNkwyOC4yNzcsNC4wNDhjLTAuNDcxLTAuMjA0LTEuMjM2LTAuMjA0LTEuNzA4LDBMMC4zNTEsMTUuNDFDLTAuMTIxLDE1LjYxNC0wLjExNiwxNS45MzUsMC4zNjEsMTYuMTI1eiIvPjwvZz48L2c+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjwvc3ZnPg==);
background-position: center;
background-repeat: no-repeat;
background-size: 70%;
}
#photoprism .cluster-control {
background: #2f3031;
position: absolute;
top: auto;
z-index: 2;
bottom: 0;
margin: 0;
padding: 0;
left: 4px;
right: 4px;
border-top-left-radius: 16px;
border-top-right-radius: 16px;
max-height: 90vh;
overflow: hidden;
box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
transition: all 650ms cubic-bezier(0.32, 1, 0.23, 1) 0ms;
}
#photoprism .cluster-control-container {
min-height: 40vh;
}
#photoprism .cluster-control .p-photos {
position: absolute;
top: 45px;
bottom: 0;
left: 0;
right: 0;
overflow: auto;
}
@media only screen and (min-height: 1500px) {
#photoprism .cluster-control-container {
min-height: 45vh;
}
}
@media only screen and (max-width: 599px) {
#photoprism .cluster-control {
left: 0;
right: 0;
}
#photoprism .cluster-control-container {
min-height: 66vh;
}
}

View file

@ -198,112 +198,128 @@ body.chrome #photoprism .search-results .result {
}
#photoprism .list-view {
box-shadow: 0 0 0 0 rgba(0,0,0,.2),0 0 0 0 rgba(0,0,0,.14),0 0 0 0 rgba(0,0,0,.12) !important;
box-shadow: 0 0 0 0 rgba(0, 0, 0, .2), 0 0 0 0 rgba(0, 0, 0, .14), 0 0 0 0 rgba(0, 0, 0, .12) !important;
}
#photoprism .cards-view .result,
#photoprism .mosaic-view .result
{
-webkit-transition-duration: 15ms !important;
-moz-transition-duration: 15ms !important;
-o-transition-duration: 15ms !important;
transition-duration: 15ms !important;
margin: 4px !important;
box-shadow: 0 0 0 0 rgba(0, 0, 0, .2), 0 0 0 0 rgba(0, 0, 0, .14), 0 0 0 0 rgba(0, 0, 0, .12) !important;
border-radius: 6px;
#photoprism .mosaic-view .result {
transition: none;
box-shadow: none !important;
}
#photoprism .cards-view .result {
margin: 2px !important;
}
#photoprism .mosaic-view .result {
margin: 0 !important;
}
#photoprism .search-results .image-container {
aspect-ratio: 1;
contain: layout paint style size;
aspect-ratio: 1;
contain: layout paint style size;
}
#photoprism .cards-view .result .image,
#photoprism .list-view .result .image,
#photoprism .mosaic-view .result.image
{
position: relative;
user-select: none;
aspect-ratio: 1;
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
overflow: hidden;
#photoprism .mosaic-view .result.image {
position: relative;
user-select: none;
aspect-ratio: 1;
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
overflow: hidden;
}
#photoprism .cards-view .result .image button,
#photoprism .list-view .result .image button,
#photoprism .mosaic-view .result.image button {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
width: 28px;
height: 28px;
padding: 0;
transition: background-color .3s cubic-bezier(.25,.8,.5,1);
position: absolute;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
width: 28px;
height: 28px;
padding: 0;
transition: background-color .3s cubic-bezier(.25, .8, .5, 1);
}
#photoprism .cards-view .result .image button {
width: 36px;
height: 36px;
width: 36px;
height: 36px;
}
#photoprism .list-view .result .image button {
width: 44px;
height: 44px;
width: 44px;
height: 44px;
}
#photoprism .cards-view .result .image button:hover,
#photoprism .list-view .result .image button:hover,
#photoprism .mosaic-view .result.image button:hover {
background-color: rgba(255, 255, 255, 0.12);
background-color: rgba(255, 255, 255, 0.12);
}
#photoprism .mosaic-view .result.image i,
#photoprism .list-view .result .image i,
#photoprism .cards-view .result .image i {
color: #e2e2e2;
font-size: 24px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
font-family: Material Icons;
font-style: normal;
font-weight: 400;
text-transform: none;
line-height: 1;
white-space: nowrap;
color: #e2e2e2;
font-size: 24px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
font-family: Material Icons;
font-style: normal;
font-weight: 400;
text-transform: none;
line-height: 1;
white-space: nowrap;
}
#photoprism .cards-view .result .caption {
hyphens: auto;
word-break: break-word;
hyphens: auto;
word-break: break-word;
}
#photoprism .cards-view .result .card-details i {
font-size: 14px;
display: inline-block;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
font-family: Material Icons;
font-style: normal;
font-weight: 400;
text-transform: none;
line-height: 1;
vertical-align: text-bottom;
white-space: nowrap;
font-size: 14px;
display: inline-block;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
font-family: Material Icons;
font-style: normal;
font-weight: 400;
text-transform: none;
line-height: 1;
vertical-align: text-bottom;
white-space: nowrap;
}
#photoprism .cards-view .result.placeholder .card-details i {
width: 14px;
width: 14px;
}
#photoprism .cards-view .result.is-selected {
margin: 7px !important;
}
#photoprism .cards-view .result.is-selected,
#photoprism .mosaic-view .result.is-selected {
margin: 1px !important;
box-shadow: 0 6px 6px -3px rgba(0, 0, 0, .2), 0 10px 14px 1px rgba(0, 0, 0, .14), 0 4px 18px 3px rgba(0, 0, 0, .12) !important;
margin: 9px !important;
}
#photoprism .list-view .result.is-selected .image {
margin: 2px !important;
}
#photoprism .cards-view .result.is-selected .card-details {
padding-left: 14px !important;
padding-right: 14px !important;
}
#photoprism .cards-view .result.is-selected .card-details .caption {
font-size: 0.85em !important;
text-overflow: ellipsis;
}
#photoprism .cards-view .input-select,
@ -515,28 +531,27 @@ body.chrome #photoprism .search-results .result {
/* old browser support */
@supports not (aspect-ratio: 1) {
/* elements with aspect-ratio 1 and without margin */
#photoprism .search-results .image-container,
#photoprism .cards-view .result .image,
#photoprism .list-view .result .image,
#photoprism .list-view .result.image,
#photoprism .mosaic-view .result.is-selected {
height: 0;
padding-bottom: 100%
}
/* elements with aspect-ratio 1 and without margin */
#photoprism .search-results .image-container,
#photoprism .cards-view .result .image,
#photoprism .list-view .result .image,
#photoprism .list-view .result.image,
#photoprism .mosaic-view .result.is-selected {
height: 0;
padding-bottom: 100%
}
/* elements with aspect-ratio 1 and with margin */
#photoprism .mosaic-view .result
{
height: 0;
/*
8px is required because this aspect-ratio-fallback doesn't take
margins into consideration
*/
padding-bottom: calc(100% - 8px)
}
/* elements with aspect-ratio 1 and with margin */
#photoprism .mosaic-view .result {
height: 0;
/*
8px is required because this aspect-ratio-fallback doesn't take
margins into consideration
*/
padding-bottom: calc(100% - 8px)
}
#photoprism .live-player video {
margin-top: 100%;
}
#photoprism .live-player video {
margin-top: 100%;
}
}

View file

@ -1,16 +1,18 @@
@import url("themes/grayscale.css");
@import url("themes/shadow.css");
@import url("themes/yellowstone.css");
@import url("themes/abyss.css");
@import url("themes/vanta.css");
@import url("themes/neon.css");
@import url("themes/gemstone.css");
@import url("themes/carbon.css");
@import url("themes/nordic.css");
@import url("themes/lavender.css");
@import url("themes/default.css");
@import url("themes/abyss.css");
@import url("themes/carbon.css");
@import url("themes/chrome.css");
@import url("themes/gemstone.css");
@import url("themes/grayscale.css");
@import url("themes/lavender.css");
@import url("themes/mint.css");
@import url("themes/neon.css");
@import url("themes/nordic.css");
@import url("themes/shadow.css");
@import url("themes/vanta.css");
@import url("themes/yellowstone.css");
/* General Styles */
/* Input Style Overrides */
:-webkit-autofill,
:-webkit-autofill:hover,
@ -21,90 +23,15 @@ input:-webkit-autofill:focus {
transition: background-color 9999s !important;
}
body.dark-theme #photoprism .v-tabs .v-badge__badge {
color: #000000;
}
body.dark-theme #photoprism .theme--light.v-table thead th {
color: #ffffff;
}
.card {
background-color: #e0e0e0;
}
body.dark-theme .card {
background-color: #1a1a1a;
}
body.dark-theme #photoprism .v-table .theme--light.v-text-field--solo>.v-input__control>.v-input__slot {
background: transparent;
}
body.dark-theme .theme--light.v-list .v-list__tile--highlighted,
body.dark-theme .theme--light.v-list a:hover {
background: rgba(255,255,255,0.3) !important;
}
body.dark-theme .v-input input::placeholder {
color: rgba(255,255,255,0.5) !important;
}
.v-text-field>.v-input__control>.v-input__slot:after,
.v-text-field>.v-input__control>.v-input__slot:before {
display: none !important;
}
/*
body.dark-theme .v-text-field.v-text-field--enclosed .v-text-field__details {
padding-left: 0;
}*/
.theme--light.v-list .v-list__tile--highlighted,
.theme--light.v-list a:hover {
background: rgba(155,155,155,0.3) !important;
}
body.dark-theme #photoprism .map-control .theme--light.v-input:not(.v-input--is-disabled) i,
body.dark-theme #photoprism .map-control .theme--light.v-input:not(.v-input--is-disabled) input {
color: #333333;
}
body:not(.dark-theme) .theme--dark.v-btn.v-btn--disabled:not(.v-btn--icon):not(.v-btn--flat):not(.v-btn--outline) {
color: rgb(51, 51, 51)!important;
background-color: #d9dadc!important;
}
body.dark-theme #photoprism .theme--light.v-chip,
body.dark-theme #photoprism .v-card .theme--light.v-text-field--box>.v-input__control>.v-input__slot {
background: #00000033;
}
body.dark-theme #photoprism,
body.dark-theme #photoprism .p-page a,
body.dark-theme #photoprism .v-datatable a,
body.dark-theme #photoprism .theme--light.v-expansion-panel .v-expansion-panel__container,
body.dark-theme #photoprism .theme--light.v-tabs__bar .v-tabs__div,
body.dark-theme #photoprism .theme--light {
color: #ffffff;
caret-color: #ffffff;
stroke: #ffffff;
}
body.dark-theme #photoprism .theme--light.v-label {
color: #ffffffaa;
}
body.dark-theme #photoprism .theme--light.v-select .v-select__selections {
color: #ffffffee;
}
#photoprism .v-select.v-text-field--box .v-select__selections {
padding-top: 20px;
}
/* Exceptions */
#photoprism .theme--light.v-text-field--solo.background-inherit>.v-input__control>.v-input__slot {
background: inherit;
box-shadow: none;

View file

@ -33,8 +33,8 @@ body.dark-theme.theme-abyss,
background: #333;
}
#photoprism.theme-abyss .theme--light.v-text-field--solo > .v-input__control > .v-input__slot {
background: #262626;
#photoprism.theme-abyss .theme--light.v-text-field--solo>.v-input__control>.v-input__slot {
background: rgba(250, 250, 255, 0.1);
}
#photoprism.theme-abyss .theme--light.v-input--selection-controls.v-input--is-disabled .v-icon {

View file

@ -1,4 +1,4 @@
/* Carbon Theme */
/* Carbon Dark Theme */
body.dark-theme.theme-carbon,
.theme-carbon .v-content__wrap,

View file

@ -0,0 +1,146 @@
/* Chrome Dark Theme */
body.dark-theme.theme-chrome,
.theme-chrome .v-content__wrap,
.theme-chrome .p-page,
.theme-chrome .form,
.theme-chrome .v-content {
background: #1d1d1d !important;
}
#photoprism.theme-chrome .theme--light.v-small-dialog__content,
#photoprism.theme-chrome .theme--light.v-sheet,
#photoprism.theme-chrome .theme--light.v-card,
.theme-chrome .application.theme--light {
background: #202020;
}
#photoprism.container.theme-chrome {
background-image: linear-gradient(160deg, #808080 0%, #262626 100%);
}
#photoprism.theme-chrome .theme--light .v-table {
background: #262626;
}
body.dark-theme #photoprism.theme-chrome,
body.dark-theme #photoprism.theme-chrome .v-datatable a,
body.dark-theme #photoprism.theme-chrome .theme--light.v-expansion-panel .v-expansion-panel__container,
body.dark-theme #photoprism.theme-chrome .theme--light.v-tabs__bar .v-tabs__div {
color: #ffffff;
caret-color: #ffffff;
stroke: #ffffff;
}
body.dark-theme #photoprism.theme-chrome .p-page a,
body.dark-theme #photoprism.theme-chrome .theme--light,
body.dark-theme #photoprism.theme-chrome #p-navigation .navigation-menu.theme--dark.v-list,
body.dark-theme #photoprism.theme-chrome #p-navigation .navigation-menu .theme--dark.v-icon {
color: #d8d8d8;
caret-color: #d8d8d8;
stroke: #d8d8d8;
}
body.dark-theme #photoprism.theme-chrome .v-input--selection-controls__input .theme--light {
color: #8e8e8e;
caret-color: #8e8e8e;
stroke: #8e8e8e;
}
body.dark-theme #photoprism.theme-chrome #p-navigation .navigation-menu .theme--dark.v-icon {
color: inherit;
}
#photoprism.theme-chrome .theme--light.v-table thead th,
#photoprism.theme-chrome .theme--light.v-table tbody td {
color: #fff;
}
#photoprism.theme-chrome .theme--light.v-table tbody tr:hover {
background: #2b2b2b;
}
#photoprism.theme-chrome .theme--light.v-text-field--solo>.v-input__control>.v-input__slot,
#photoprism.theme-chrome .theme--light.v-text-field--solo>.v-input__control>.v-input__slot {
background: rgba(255, 255, 255, 0.1);
}
#photoprism.theme-chrome .secondary--text {
color: rgba(255, 255, 255, 0.2)!important;
}
body.dark-theme #photoprism.theme-chrome #map .secondary-dark.theme--light,
body.dark-theme #photoprism.theme-chrome #map .secondary-dark--text {
color: #000000!important;
caret-color: #000000!important;
stroke: #000000!important;
}
body.dark-theme #photoprism.theme-chrome .map-control .theme--light {
color: #757575;
caret-color: #757575;
stroke: #757575;
}
body.dark-theme #photoprism.theme-chrome .v-card .theme--light.v-text-field--box>.v-input__control>.v-input__slot {
background: rgba(255, 255, 255, 0.04);
}
#photoprism.theme-chrome .theme--light.v-input--selection-controls.v-input--is-disabled .v-icon {
color: #999 !important;
}
#photoprism.theme-chrome .theme--light.v-input--selection-controls.v-input--is-disabled .v-icon,
#photoprism.theme-chrome .theme--light.v-input--is-disabled .v-label,
#photoprism.theme-chrome .theme--light.v-input--is-disabled input,
#photoprism.theme-chrome .theme--light.v-input--is-disabled textarea {
color: #aaaaaa;
}
#photoprism.theme-chrome .theme--light.v-list {
background: #232425;
}
#photoprism.theme-chrome a.text-link {
color: #ffffff !important;
}
#photoprism.theme-chrome .footer .body-link {
color: #ffffff !important;
}
#photoprism.theme-chrome .theme--light.v-list .v-list__tile__sub-title,
#photoprism.theme-chrome .accent--text {
color: #ffffff !important;
}
#photoprism.theme-chrome .theme--light.v-input:not(.v-input--is-disabled) input,
#photoprism.theme-chrome .theme--light.v-input:not(.v-input--is-disabled) textarea {
color: #fff;
}
#photoprism.theme-chrome .theme--light.v-btn.v-btn--disabled,
#photoprism.theme-chrome .theme--light.v-btn.v-btn--disabled .v-btn__loading,
#photoprism.theme-chrome .theme--light.v-btn.v-btn--disabled .v-icon {
color: #999 !important;
}
#photoprism.theme-chrome .theme--light.v-list .v-list__tile__mask {
color: #cccccc;
background: transparent;
}
#photoprism.theme-chrome .cards-view .card.is-selected .card-details {
color: #fff;
background-color: #5C5C5C;
}
#photoprism.theme-chrome .cards-view .card.is-selected,
#photoprism.theme-chrome .cards-view .card.is-selected .card-background {
background-color: #5C5C5C !important;
}
#photoprism.theme-chrome .cards-view .card.is-selected .card-details .v-icon {
color: #fff;
}

View file

@ -1,7 +1,75 @@
/* Default Theme */
/* Component Color Defaults */
#photoprism.theme-default .theme--light.v-text-field--solo>.v-input__control>.v-input__slot,
#photoprism.theme-default .theme--light.v-text-field--solo>.v-input__control>.v-input__slot {
.card {
background-color: #e0e0e0;
}
body.dark-theme .card {
background-color: #1a1a1a;
}
body.dark-theme #photoprism .v-table .theme--light.v-text-field--solo>.v-input__control>.v-input__slot {
background: transparent;
}
body.dark-theme .theme--light.v-list .v-list__tile--highlighted,
body.dark-theme .theme--light.v-list a:hover {
background: rgba(255,255,255,0.3) !important;
}
body.dark-theme .v-input input::placeholder {
color: rgba(255,255,255,0.5) !important;
}
body.dark-theme .theme--light .v-table {
background: #303030;
}
body.dark-theme .theme--light.v-table tbody tr:hover {
background: #343434;
}
.theme--light.v-list .v-list__tile--highlighted,
.theme--light.v-list a:hover {
background: rgba(155,155,155,0.3) !important;
}
body:not(.dark-theme) .theme--dark.v-btn.v-btn--disabled:not(.v-btn--icon):not(.v-btn--flat):not(.v-btn--outline) {
color: rgb(51, 51, 51)!important;
background-color: #d9dadc!important;
}
body.dark-theme #photoprism .theme--light.v-chip,
body.dark-theme #photoprism .v-card .theme--light.v-text-field--box>.v-input__control>.v-input__slot {
background: #00000033;
}
body.dark-theme #photoprism,
body.dark-theme #photoprism .p-page a,
body.dark-theme #photoprism .v-datatable a,
body.dark-theme #photoprism .theme--light.v-expansion-panel .v-expansion-panel__container,
body.dark-theme #photoprism .theme--light.v-tabs__bar .v-tabs__div,
body.dark-theme #photoprism .theme--light {
color: #ffffff;
caret-color: #ffffff;
stroke: #ffffff;
}
body.dark-theme #photoprism .theme--light.v-label {
color: #ffffffaa;
}
body.dark-theme #photoprism .theme--light.v-select .v-select__selections {
color: #ffffffee;
}
body.dark-theme .theme--light.v-small-dialog__content,
body.dark-theme .theme--light.v-sheet,
body.dark-theme .theme--light.v-card {
background: #2f3031;
}
body.dark-theme .theme--light.v-text-field--solo>.v-input__control>.v-input__slot {
background: rgba(250, 250, 255, 0.1);
}
@ -20,7 +88,10 @@ body.dark-theme #photoprism .p-page a,
body.dark-theme #photoprism .v-datatable a,
body.dark-theme #photoprism .theme--light.v-expansion-panel .v-expansion-panel__container,
body.dark-theme #photoprism .theme--light.v-tabs__bar .v-tabs__div,
body.dark-theme #photoprism .theme--light {
body.dark-theme #photoprism .theme--light,
body.dark-theme #photoprism .theme--light.v-table thead th,
body.dark-theme .theme--light.v-table thead th,
body.dark-theme .theme--light.v-table tbody td {
color: #ffffff;
}
@ -36,6 +107,12 @@ body.dark-theme #photoprism .theme--light.v-select .v-select__selections {
padding-top: 20px;
}
body.dark-theme #photoprism .v-tabs .v-badge__badge {
color: #000000;
}
/* Default Theme */
body.dark-theme.theme-default,
.theme-default .v-content__wrap,
.theme-default .p-page,
@ -51,10 +128,6 @@ body.dark-theme.theme-default,
background: #2f3031;
}
#photoprism.theme-default .theme--light .v-table {
background: #37393a;
}
#photoprism.container.theme-default {
background-image: linear-gradient(160deg, #808080 0%, #262626 100%);
}
@ -68,6 +141,10 @@ body.dark-theme.theme-default,
stroke: rgba(196, 241, 229, 0.3);
}
#photoprism.theme-default .theme--light .v-table {
background: #37393a;
}
#photoprism.theme-default .theme--light.v-table thead th,
#photoprism.theme-default .theme--light.v-table tbody td {
color: #fff;
@ -81,6 +158,11 @@ body.dark-theme.theme-default,
color: #999 !important;
}
#photoprism.theme-default .theme--light.v-text-field--solo>.v-input__control>.v-input__slot,
#photoprism.theme-default .theme--light.v-text-field--solo>.v-input__control>.v-input__slot {
background: rgba(250, 250, 255, 0.1);
}
#photoprism.theme-default .theme--light.v-input--selection-controls.v-input--is-disabled .v-icon,
#photoprism.theme-default .theme--light.v-input--is-disabled .v-label,
#photoprism.theme-default .theme--light.v-input--is-disabled input,
@ -123,12 +205,12 @@ body.dark-theme.theme-default,
#photoprism.theme-default .cards-view .card.is-selected .card-details {
color: #fff;
background-color: #4b4e4f;
background-color: #636869;
}
#photoprism.theme-default .cards-view .card.is-selected,
#photoprism.theme-default .cards-view .card.is-selected .card-background {
background-color: #4b4e4f !important;
background-color: #636869 !important;
}
#photoprism.theme-default .cards-view .card.is-selected .card-details .v-icon {

View file

@ -1,4 +1,4 @@
/* Gemstone Theme */
/* Gemstone Dark Theme */
body.dark-theme.theme-gemstone,
.theme-gemstone .v-content__wrap,

View file

@ -1,4 +1,4 @@
/* Grayscale Theme */
/* Grayscale Dark Theme */
body.dark-theme.theme-grayscale {
background: #525252 !important;

View file

@ -0,0 +1,92 @@
/* Mint Dark Theme */
body.dark-theme.theme-mint,
.theme-mint .v-content__wrap,
.theme-mint .p-page,
.theme-mint .form,
.theme-mint .v-content {
background: #121212 !important;
}
#photoprism.theme-mint .theme--light.v-small-dialog__content,
#photoprism.theme-mint .theme--light.v-sheet,
#photoprism.theme-mint .theme--light.v-card,
.theme-mint .application.theme--light {
background: #1e1e1e;
}
#photoprism.container.theme-mint {
background-image: linear-gradient(160deg, #808080 0%, #262626 100%);
}
#photoprism.theme-mint .theme--light .v-table {
background: #1a1a1a;
}
#photoprism.theme-mint .theme--light.v-table thead th,
#photoprism.theme-mint .theme--light.v-table tbody td {
color: #fff;
}
#photoprism.theme-mint .theme--light.v-table tbody tr:hover {
background: #2b2b2b;
}
#photoprism.theme-mint .theme--light.v-input--selection-controls.v-input--is-disabled .v-icon {
color: #999 !important;
}
#photoprism.theme-mint .theme--light.v-input--selection-controls.v-input--is-disabled .v-icon,
#photoprism.theme-mint .theme--light.v-input--is-disabled .v-label,
#photoprism.theme-mint .theme--light.v-input--is-disabled input,
#photoprism.theme-mint .theme--light.v-input--is-disabled textarea {
color: #ccc;
}
#photoprism.theme-mint .theme--light.v-list {
background: #232425;
}
#photoprism.theme-mint a.text-link {
color: #f6f7e8 !important;
}
#photoprism.theme-mint .footer .body-link {
color: #f6f7e8 !important;
}
#photoprism.theme-mint .theme--light.v-list .v-list__tile__sub-title,
#photoprism.theme-mint .accent--text {
color: #2bb14c !important;
}
#photoprism.theme-mint .theme--light.v-input:not(.v-input--is-disabled) input,
#photoprism.theme-mint .theme--light.v-input:not(.v-input--is-disabled) textarea {
color: #fff;
}
#photoprism.theme-mint .theme--light.v-btn.v-btn--disabled,
#photoprism.theme-mint .theme--light.v-btn.v-btn--disabled .v-btn__loading,
#photoprism.theme-mint .theme--light.v-btn.v-btn--disabled .v-icon {
color: #999 !important;
}
#photoprism.theme-mint .theme--light.v-list .v-list__tile__mask {
color: #cccccc;
background: transparent;
}
#photoprism.theme-mint .cards-view .card.is-selected .card-details {
color: #fff;
background-color: #333333;
}
#photoprism.theme-mint .cards-view .card.is-selected,
#photoprism.theme-mint .cards-view .card.is-selected .card-background {
background-color: #333333 !important;
}
#photoprism.theme-mint .cards-view .card.is-selected .card-details .v-icon {
color: #fff;
}

View file

@ -1,4 +1,4 @@
/* Neon Theme */
/* Neon Dark Theme */
.theme-neon .v-snack.v-snack--active.v-snack--bottom,
.theme-neon .v-speed-dial .v-btn--floating.v-btn--small {

View file

@ -1,4 +1,4 @@
/* Shadow Theme */
/* Shadow Dark Theme */
body.dark-theme.theme-shadow {
background: #444 !important;

View file

@ -1,4 +1,4 @@
/* Vanta Theme */
/* Vanta Dark Theme */
body.dark-theme.theme-vanta {
background: #212121 !important;

View file

@ -1,4 +1,4 @@
/* Yellowstone Theme */
/* Yellowstone Dark Theme */
body.dark-theme.theme-yellowstone,
.theme-yellowstone .v-content__wrap,

View file

@ -39,6 +39,10 @@ button.v-btn.compact {
height: 34px;
}
.caption.filename {
font-weight: 500;
}
/* Line Height */
.lh-15 {

View file

@ -10,7 +10,7 @@
top: 0;
bottom: 0;
right: 0;
background-color: rgba(0,0,0,1);
background-color: rgba(0,0,0,0.72);
}
#photoprism .video-wrapper {

View file

@ -1,5 +1,5 @@
<template>
<v-dialog :value="show" lazy persistent max-width="350" class="p-photo-delete-dialog" @keydown.esc="cancel">
<v-dialog :value="show" lazy persistent max-width="360" class="p-photo-delete-dialog" @keydown.esc="cancel">
<v-card raised elevation="24">
<v-container fluid class="pb-2 pr-2 pl-2">
<v-layout row wrap>
@ -7,18 +7,25 @@
<v-icon size="54" color="secondary-dark lighten-1">delete_outline</v-icon>
</v-flex>
<v-flex xs9 text-xs-left align-self-center>
<div class="subheading pr-1">
<div v-if="text === ''" class="subheading pr-1">
<translate>Are you sure you want to permanently delete these pictures?</translate>
</div>
<div v-else class="subheading pr-1">
{{ text }}
</div>
</v-flex>
<v-flex xs12 text-xs-right class="pt-3">
<v-btn depressed color="secondary-light" class="action-cancel" @click.stop="cancel">
<translate key="Cancel">Cancel</translate>
</v-btn>
<v-btn color="primary-button" depressed dark class="action-confirm"
<v-btn v-if="action === ''" color="primary-button" depressed dark class="action-confirm"
@click.stop="confirm">
<translate key="Delete">Delete</translate>
</v-btn>
<v-btn v-else color="primary-button" depressed dark class="action-confirm"
@click.stop="confirm">
{{ action }}
</v-btn>
</v-flex>
</v-layout>
</v-container>
@ -30,6 +37,14 @@ export default {
name: 'PPhotoDeleteDialog',
props: {
show: Boolean,
text: {
type: String,
default: "",
},
action: {
type: String,
default: "",
},
},
data() {
return {};

View file

@ -24,12 +24,11 @@
</v-toolbar>
<v-tabs
v-model="active"
flat
grow
flat grow
class="form"
color="secondary"
slider-color="secondary-dark"
:height="$vuetify.breakpoint.smAndDown ? 48 : 64"
class="form"
>
<v-tab id="tab-details" ripple>
<v-icon v-if="$vuetify.breakpoint.smAndDown" :title="$gettext('Details')">edit</v-icon>
@ -82,7 +81,7 @@
</v-tab>
<v-tabs-items touchless>
<v-tab-item>
<v-tab-item lazy>
<p-tab-photo-details :key="uid" ref="details" :model="model" :uid="uid"
@close="close" @prev="prev" @next="next"></p-tab-photo-details>
</v-tab-item>

View file

@ -1,412 +1,408 @@
<template>
<div class="p-tab p-tab-photo-details">
<v-container fluid>
<v-form ref="form" lazy-validation
dense class="p-form-photo-details-meta" accept-charset="UTF-8"
@submit.prevent="save">
<v-layout row wrap align-top fill-height>
<v-flex
class="p-photo pa-2"
xs12 sm4 md2
>
<v-card tile
class="ma-0 elevation-0"
:title="model.Title">
<v-img v-touch="{left, right}"
:src="model.thumbnailUrl('tile_500')"
aspect-ratio="1"
class="card darken-1 elevation-0 clickable"
@click.exact="openPhoto()"
>
</v-img>
<v-form ref="form" lazy-validation
dense class="p-form-photo-details-meta" accept-charset="UTF-8"
@submit.prevent="save">
<v-layout class="pa-2" row wrap align-top fill-height>
<v-flex class="pa-2 p-photo" xs12 sm4 md2 fill-height>
<v-card tile
class="pa-0 ma-0 elevation-0"
:title="model.Title">
<v-img v-touch="{left, right}"
:src="model.thumbnailUrl('tile_500')"
aspect-ratio="1"
class="card darken-1 elevation-0 clickable"
@click.exact="openPhoto()"
>
</v-img>
</v-card>
</v-flex>
<v-flex xs12 sm8 md10 fill-height>
<v-layout row wrap>
<v-flex xs12 lg6 class="pa-2">
<v-text-field
v-model="model.Title"
:append-icon="model.TitleSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:rules="[textRule]"
hide-details box flat
:label="$pgettext('Photo', 'Title')"
placeholder=""
color="secondary-dark"
browser-autocomplete="off"
class="input-title"
></v-text-field>
</v-flex>
</v-card>
</v-flex>
<v-flex xs12 sm8 md10 fill-height>
<v-layout row wrap>
<v-flex xs12 lg6 class="pa-2">
<v-text-field
v-model="model.Title"
:append-icon="model.TitleSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:rules="[textRule]"
hide-details box flat
:label="$pgettext('Photo', 'Title')"
placeholder=""
color="secondary-dark"
browser-autocomplete="off"
class="input-title"
></v-text-field>
</v-flex>
<v-flex xs4 md1 pa-2>
<v-autocomplete
v-model="model.Day"
:append-icon="model.TakenSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:error="invalidDate"
:label="$gettext('Day')"
browser-autocomplete="off"
hide-details box flat hide-no-data
color="secondary-dark"
:items="options.Days()"
class="input-day"
@change="updateTime">
</v-autocomplete>
</v-flex>
<v-flex xs4 md1 pa-2>
<v-autocomplete
v-model="model.Month"
:append-icon="model.TakenSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:error="invalidDate"
:label="$gettext('Month')"
browser-autocomplete="off"
hide-details box flat hide-no-data
color="secondary-dark"
:items="options.MonthsShort()"
class="input-month"
@change="updateTime">
</v-autocomplete>
</v-flex>
<v-flex xs4 md2 pa-2>
<v-autocomplete
v-model="model.Year"
:append-icon="model.TakenSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:error="invalidDate"
:label="$gettext('Year')"
browser-autocomplete="off"
hide-details box flat hide-no-data
color="secondary-dark"
:items="options.Years()"
class="input-year"
@change="updateTime">
</v-autocomplete>
</v-flex>
<v-flex xs4 md1 pa-2>
<v-autocomplete
v-model="model.Day"
:append-icon="model.TakenSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:error="invalidDate"
:label="$gettext('Day')"
browser-autocomplete="off"
hide-details box flat hide-no-data
color="secondary-dark"
:items="options.Days()"
class="input-day"
@change="updateTime">
</v-autocomplete>
</v-flex>
<v-flex xs4 md1 pa-2>
<v-autocomplete
v-model="model.Month"
:append-icon="model.TakenSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:error="invalidDate"
:label="$gettext('Month')"
browser-autocomplete="off"
hide-details box flat hide-no-data
color="secondary-dark"
:items="options.MonthsShort()"
class="input-month"
@change="updateTime">
</v-autocomplete>
</v-flex>
<v-flex xs4 md2 pa-2>
<v-autocomplete
v-model="model.Year"
:append-icon="model.TakenSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:error="invalidDate"
:label="$gettext('Year')"
browser-autocomplete="off"
hide-details box flat hide-no-data
color="secondary-dark"
:items="options.Years()"
class="input-year"
@change="updateTime">
</v-autocomplete>
</v-flex>
<v-flex xs6 md2 class="pa-2">
<v-text-field
v-model="time"
:append-icon="model.TakenSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:label="model.timeIsUTC() ? $gettext('Time UTC') : $gettext('Local Time')"
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
hide-details box flat
return-masked-value mask="##:##:##"
color="secondary-dark"
class="input-local-time"
></v-text-field>
</v-flex>
<v-flex xs6 md2 class="pa-2">
<v-text-field
v-model="time"
:append-icon="model.TakenSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:label="model.timeIsUTC() ? $gettext('Time UTC') : $gettext('Local Time')"
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
hide-details box flat
return-masked-value mask="##:##:##"
color="secondary-dark"
class="input-local-time"
></v-text-field>
</v-flex>
<v-flex xs6 sm6 md6 lg3 class="pa-2">
<v-autocomplete
v-model="model.TimeZone"
:disabled="disabled"
:label="$gettext('Time Zone')"
browser-autocomplete="off"
hide-details box flat hide-no-data
color="secondary-dark"
item-value="ID"
item-text="Name"
:items="options.TimeZones()"
class="input-timezone"
@change="updateTime">
</v-autocomplete>
</v-flex>
<v-flex xs6 sm6 md6 lg3 class="pa-2">
<v-autocomplete
v-model="model.TimeZone"
:disabled="disabled"
:label="$gettext('Time Zone')"
browser-autocomplete="off"
hide-details box flat hide-no-data
color="secondary-dark"
item-value="ID"
item-text="Name"
:items="options.TimeZones()"
class="input-timezone"
@change="updateTime">
</v-autocomplete>
</v-flex>
<v-flex xs12 sm8 md4 lg3 class="pa-2">
<v-autocomplete
v-model="model.Country"
:append-icon="model.PlaceSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:readonly="!!(model.Lat || model.Lng)"
:label="$gettext('Country')" hide-details box flat
hide-no-data
browser-autocomplete="off"
color="secondary-dark"
item-value="Code"
item-text="Name"
:items="countries"
class="input-country">
</v-autocomplete>
</v-flex>
<v-flex xs12 sm8 md4 lg3 class="pa-2">
<v-autocomplete
v-model="model.Country"
:append-icon="model.PlaceSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:readonly="!!(model.Lat || model.Lng)"
:label="$gettext('Country')" hide-details box flat
hide-no-data
browser-autocomplete="off"
color="secondary-dark"
item-value="Code"
item-text="Name"
:items="countries"
class="input-country">
</v-autocomplete>
</v-flex>
<v-flex xs4 md2 lg2 class="pa-2">
<v-text-field
v-model="model.Altitude"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
:label="$gettext('Altitude (m)')"
placeholder=""
color="secondary-dark"
class="input-altitude"
></v-text-field>
</v-flex>
<v-flex xs4 md2 lg2 class="pa-2">
<v-text-field
v-model="model.Altitude"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
:label="$gettext('Altitude (m)')"
placeholder=""
color="secondary-dark"
class="input-altitude"
></v-text-field>
</v-flex>
<v-flex xs4 sm6 md3 lg2 class="pa-2">
<v-text-field
v-model="model.Lat"
:append-icon="model.PlaceSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
:label="$gettext('Latitude')"
placeholder=""
color="secondary-dark"
class="input-latitude"
></v-text-field>
</v-flex>
<v-flex xs4 sm6 md3 lg2 class="pa-2">
<v-text-field
v-model="model.Lat"
:append-icon="model.PlaceSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
:label="$gettext('Latitude')"
placeholder=""
color="secondary-dark"
class="input-latitude"
@paste="pastePosition"
></v-text-field>
</v-flex>
<v-flex xs4 sm6 md3 lg2 class="pa-2">
<v-text-field
v-model="model.Lng"
:append-icon="model.PlaceSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
:label="$gettext('Longitude')"
placeholder=""
color="secondary-dark"
class="input-longitude"
></v-text-field>
</v-flex>
<v-flex xs4 sm6 md3 lg2 class="pa-2">
<v-text-field
v-model="model.Lng"
:append-icon="model.PlaceSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
:label="$gettext('Longitude')"
placeholder=""
color="secondary-dark"
class="input-longitude"
@paste="pastePosition"
></v-text-field>
</v-flex>
<v-flex xs12 md6 pa-2 class="p-camera-select">
<v-select
v-model="model.CameraID"
:append-icon="model.CameraSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:label="$gettext('Camera')"
:menu-props="{'maxHeight':346}"
browser-autocomplete="off"
hide-details box flat
color="secondary-dark"
item-value="ID"
item-text="Name"
:items="cameraOptions"
class="input-camera">
</v-select>
</v-flex>
<v-flex xs12 md6 pa-2 class="p-camera-select">
<v-select
v-model="model.CameraID"
:append-icon="model.CameraSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:label="$gettext('Camera')"
:menu-props="{'maxHeight':346}"
browser-autocomplete="off"
hide-details box flat
color="secondary-dark"
item-value="ID"
item-text="Name"
:items="cameraOptions"
class="input-camera">
</v-select>
</v-flex>
<v-flex xs6 md3 class="pa-2">
<v-text-field
v-model="model.Iso"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
label="ISO"
placeholder=""
color="secondary-dark"
class="input-iso"
></v-text-field>
</v-flex>
<v-flex xs6 md3 class="pa-2">
<v-text-field
v-model="model.Iso"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
label="ISO"
placeholder=""
color="secondary-dark"
class="input-iso"
></v-text-field>
</v-flex>
<v-flex xs6 md3 class="pa-2">
<v-text-field
v-model="model.Exposure"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
:label="$gettext('Exposure')"
placeholder=""
color="secondary-dark"
class="input-exposure"
></v-text-field>
</v-flex>
<v-flex xs6 md3 class="pa-2">
<v-text-field
v-model="model.Exposure"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
:label="$gettext('Exposure')"
placeholder=""
color="secondary-dark"
class="input-exposure"
></v-text-field>
</v-flex>
<v-flex xs12 md6 pa-2 class="p-lens-select">
<v-select
v-model="model.LensID"
:append-icon="model.CameraSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:label="$gettext('Lens')"
:menu-props="{'maxHeight':346}"
browser-autocomplete="off"
hide-details box flat
color="secondary-dark"
item-value="ID"
item-text="Name"
:items="lensOptions"
class="input-lens">
</v-select>
</v-flex>
<v-flex xs12 md6 pa-2 class="p-lens-select">
<v-select
v-model="model.LensID"
:append-icon="model.CameraSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:label="$gettext('Lens')"
:menu-props="{'maxHeight':346}"
browser-autocomplete="off"
hide-details box flat
color="secondary-dark"
item-value="ID"
item-text="Name"
:items="lensOptions"
class="input-lens">
</v-select>
</v-flex>
<v-flex xs6 md3 class="pa-2">
<v-text-field
v-model="model.FNumber" f
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
:label="$gettext('F Number')"
placeholder=""
color="secondary-dark"
class="input-fnumber"
></v-text-field>
</v-flex>
<v-flex xs6 md3 class="pa-2">
<v-text-field
v-model="model.FNumber" f
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
:label="$gettext('F Number')"
placeholder=""
color="secondary-dark"
class="input-fnumber"
></v-text-field>
</v-flex>
<v-flex xs6 md3 class="pa-2">
<v-text-field
v-model="model.FocalLength"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
:label="$gettext('Focal Length')"
placeholder=""
color="secondary-dark"
class="input-focal-length"
></v-text-field>
</v-flex>
<v-flex xs6 md3 class="pa-2">
<v-text-field
v-model="model.FocalLength"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
:label="$gettext('Focal Length')"
placeholder=""
color="secondary-dark"
class="input-focal-length"
></v-text-field>
</v-flex>
<v-flex xs12 md6 class="pa-2">
<v-text-field
v-model="model.Details.Artist"
:append-icon="model.Details.ArtistSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:rules="[textRule]"
hide-details box flat
browser-autocomplete="off"
:label="$gettext('Artist')"
placeholder=""
color="secondary-dark"
class="input-artist"
></v-text-field>
</v-flex>
<v-flex xs12 md6 class="pa-2">
<v-text-field
v-model="model.Details.Artist"
:append-icon="model.Details.ArtistSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:rules="[textRule]"
hide-details box flat
browser-autocomplete="off"
:label="$gettext('Artist')"
placeholder=""
color="secondary-dark"
class="input-artist"
></v-text-field>
</v-flex>
<v-flex xs6 md3 class="pa-2">
<v-text-field
v-model="model.Details.Copyright"
:append-icon="model.Details.CopyrightSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:rules="[textRule]"
hide-details box flat
browser-autocomplete="off"
:label="$gettext('Copyright')"
placeholder=""
color="secondary-dark"
class="input-copyright"
></v-text-field>
</v-flex>
<v-flex xs6 md3 class="pa-2">
<v-text-field
v-model="model.Details.Copyright"
:append-icon="model.Details.CopyrightSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:rules="[textRule]"
hide-details box flat
browser-autocomplete="off"
:label="$gettext('Copyright')"
placeholder=""
color="secondary-dark"
class="input-copyright"
></v-text-field>
</v-flex>
<v-flex xs6 md3 class="pa-2">
<v-textarea
v-model="model.Details.License"
:append-icon="model.Details.LicenseSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:rules="[textRule]"
hide-details box flat
browser-autocomplete="off"
auto-grow
:label="$gettext('License')"
placeholder=""
:rows="1"
color="secondary-dark"
class="input-license"
></v-textarea>
</v-flex>
<v-flex xs6 md3 class="pa-2">
<v-textarea
v-model="model.Details.License"
:append-icon="model.Details.LicenseSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:rules="[textRule]"
hide-details box flat
browser-autocomplete="off"
auto-grow
:label="$gettext('License')"
placeholder=""
:rows="1"
color="secondary-dark"
class="input-license"
></v-textarea>
</v-flex>
<v-flex xs12 class="pa-2">
<v-textarea
v-model="model.Details.Subject"
:append-icon="model.Details.SubjectSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:rules="[textRule]"
hide-details box flat
browser-autocomplete="off"
auto-grow
:label="$gettext('Subject')"
placeholder=""
:rows="1"
color="secondary-dark"
class="input-subject"
></v-textarea>
</v-flex>
<v-flex xs12 class="pa-2">
<v-textarea
v-model="model.Details.Subject"
:append-icon="model.Details.SubjectSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
:rules="[textRule]"
hide-details box flat
browser-autocomplete="off"
auto-grow
:label="$gettext('Subject')"
placeholder=""
:rows="1"
color="secondary-dark"
class="input-subject"
></v-textarea>
</v-flex>
<v-flex xs12 class="pa-2">
<v-textarea
v-model="model.Description"
:append-icon="model.DescriptionSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
auto-grow
:label="$gettext('Description')"
placeholder=""
:rows="1"
color="secondary-dark"
class="input-description"
></v-textarea>
</v-flex>
<v-flex xs12 class="pa-2">
<v-textarea
v-model="model.Description"
:append-icon="model.DescriptionSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
auto-grow
:label="$gettext('Description')"
placeholder=""
:rows="1"
color="secondary-dark"
class="input-description"
></v-textarea>
</v-flex>
<v-flex xs12 md8 class="pa-2">
<v-textarea
v-model="model.Details.Keywords"
:append-icon="model.Details.KeywordsSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
auto-grow
:label="$gettext('Keywords')"
placeholder=""
:rows="1"
color="secondary-dark"
class="input-keywords"
></v-textarea>
</v-flex>
<v-flex xs12 md8 class="pa-2">
<v-textarea
v-model="model.Details.Keywords"
:append-icon="model.Details.KeywordsSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
auto-grow
:label="$gettext('Keywords')"
placeholder=""
:rows="1"
color="secondary-dark"
class="input-keywords"
></v-textarea>
</v-flex>
<v-flex xs12 md4 class="pa-2">
<v-textarea
v-model="model.Details.Notes"
:append-icon="model.Details.NotesSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
auto-grow
:label="$gettext('Notes')"
placeholder=""
:rows="1"
color="secondary-dark"
class="input-notes"
></v-textarea>
</v-flex>
<v-flex xs12 md4 class="pa-2">
<v-textarea
v-model="model.Details.Notes"
:append-icon="model.Details.NotesSrc === 'manual' ? 'check' : ''"
:disabled="disabled"
hide-details box flat
browser-autocomplete="off"
auto-grow
:label="$gettext('Notes')"
placeholder=""
:rows="1"
color="secondary-dark"
class="input-notes"
></v-textarea>
</v-flex>
<v-flex v-if="!disabled" xs12 :text-xs-right="!rtl" :text-xs-left="rtl" class="pt-3">
<v-btn depressed color="secondary-light" class="compact action-close"
@click.stop="close">
<translate>Close</translate>
</v-btn>
<v-btn color="primary-button" depressed dark class="compact action-apply action-approve"
@click.stop="save(false)">
<span v-if="$config.feature('review') && model.Quality < 3"><translate>Approve</translate></span>
<span v-else><translate>Apply</translate></span>
</v-btn>
<v-btn color="primary-button" depressed dark class="compact action-done hidden-xs-only"
@click.stop="save(true)">
<translate>Done</translate>
</v-btn>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
<div class="mt-1 clear"></div>
</v-form>
</v-container>
<v-flex v-if="!disabled" xs12 :text-xs-right="!rtl" :text-xs-left="rtl" class="pt-3">
<v-btn depressed color="secondary-light" class="compact action-close"
@click.stop="close">
<translate>Close</translate>
</v-btn>
<v-btn color="primary-button" depressed dark class="compact action-apply action-approve"
@click.stop="save(false)">
<span v-if="$config.feature('review') && model.Quality < 3"><translate>Approve</translate></span>
<span v-else><translate>Apply</translate></span>
</v-btn>
<v-btn color="primary-button" depressed dark class="compact action-done hidden-xs-only"
@click.stop="save(true)">
<translate>Done</translate>
</v-btn>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
<div class="mt-1 clear"></div>
</v-form>
</div>
</template>
@ -475,6 +471,37 @@ export default {
this.time = taken.toFormat("HH:mm:ss");
},
pastePosition(event) {
// Auto-fills the lat and lng fields if the text in the clipboard contains two float values.
const clipboard = event.clipboardData ? event.clipboardData : window.clipboardData;
if (!clipboard) {
return;
}
// Get values from browser clipboard.
const text = clipboard.getData("text");
// Trim spaces before splitting by whitespace and/or commas.
const val = text.trim().split(/[ ,]+/);
// Two values found?
if (val.length >= 2) {
// Parse values.
const lat = parseFloat(val[0]);
const lng = parseFloat(val[1]);
// Lat and long must be valid floating point numbers.
if (!isNaN(lat) && lat >= -90 && lat <= 90 &&
!isNaN(lng) && lng >= -180 && lng <= 180) {
// Update model values.
this.model.Lat = lat;
this.model.Lng = lng;
// Prevent default action.
event.preventDefault();
}
}
},
updateModel() {
if (!this.model.hasId()) {
return;

View file

@ -5,7 +5,7 @@
<v-expansion-panel-content v-if="!file.Missing" :key="file.UID" class="pa-0 elevation-0 secondary-light"
style="margin-top: 1px;">
<template #header>
<div class="caption">{{ file.baseName(70) }}</div>
<div class="caption filename">{{ file.baseName(70) }}</div>
</template>
<v-card>
<v-card-text class="white pa-0">
@ -77,25 +77,25 @@
<td title="Unique ID">
UID
</td>
<td>{{ file.UID | uppercase }}</td>
<td><span class="clickable" @click.stop.prevent="copyText(file.UID)">{{ file.UID | uppercase }}</span></td>
</tr>
<tr v-if="file.InstanceID" title="XMP">
<td>
<translate>Instance ID</translate>
</td>
<td>{{ file.InstanceID | uppercase }}</td>
<td><span class="clickable" @click.stop.prevent="copyText(file.InstanceID)">{{ file.InstanceID | uppercase }}</span></td>
</tr>
<tr>
<td title="SHA-1">
<translate>Hash</translate>
</td>
<td>{{ file.Hash }}</td>
<td><span class="clickable" @click.stop.prevent="copyText(file.Hash)">{{ file.Hash }}</span></td>
</tr>
<tr v-if="file.Name">
<td>
<translate>Filename</translate>
</td>
<td>{{ file.Name }}</td>
<td><span class="clickable" @click.stop.prevent="copyText(file.Name)">{{ file.Name }}</span></td>
</tr>
<tr v-if="file.Root">
<td>
@ -107,7 +107,7 @@
<td>
<translate>Original Name</translate>
</td>
<td>{{ file.OriginalName }}</td>
<td><span class="clickable" @click.stop.prevent="copyText(file.OriginalName)">{{ file.OriginalName }}</span></td>
</tr>
<tr>
<td>
@ -207,7 +207,7 @@
hide-details
color="secondary-dark"
:items="options.Orientations()"
:readonly="readonly || !features.edit || (file.FileType !== 'jpg' && file.FileType !== 'png') || file.Error"
:readonly="readonly || !features.edit || file.Error || (file.Frames && file.Frames > 1) || (file.Duration && file.Duration > 1) || (file.FileType !== 'jpg' && file.FileType !== 'png')"
:disabled="busy"
class="input-orientation"
@change="changeOrientation(file)">
@ -294,7 +294,10 @@ export default {
type: Object,
default: () => {},
},
uid: String,
uid: {
type: String,
default: "",
},
},
data() {
return {
@ -329,6 +332,18 @@ export default {
},
computed: {},
methods: {
async copyText(text) {
if (!text) {
return;
}
try {
await Util.copyToMachineClipboard(text);
this.$notify.success(this.$gettext("Copied to clipboard"));
} catch (error) {
this.$notify.error(this.$gettext("Failed copying to clipboard"));
}
},
orientationClass(file) {
if (!file) {
return [];
@ -365,8 +380,11 @@ export default {
}
const name = m.Name;
const path = name.substring(0, name.lastIndexOf('/'));
// "#" chars in path names must be explicitly escaped,
// see https://github.com/photoprism/photoprism/issues/3695
const path = name.substring(0, name.lastIndexOf('/'))
.replaceAll(":", "%3A").replaceAll("#", "%23");
return this.$router.resolve({ path: '/index/files/' + path }).href;
},
downloadFile(file) {

View file

@ -1,23 +1,24 @@
<template>
<div class="p-tab p-tab-photo-advanced">
<div class="v-table__overflow">
<table class="v-datatable v-table theme--light">
<tbody>
<tr>
<td>UID</td>
<td>{{ model.UID | uppercase }}</td>
</tr>
<tr v-if="model.DocumentID">
<td>Document ID</td>
<td>{{ model.DocumentID | uppercase }}</td>
</tr>
<tr>
<td :title="model.TypeSrc">
<translate>Type</translate>
<v-icon v-if="model.TypeSrc === 'manual'" class="src">check</v-icon>
</td>
<td>
<v-select
<v-form ref="form" lazy-validation dense accept-charset="UTF-8" @submit.prevent>
<div class="v-table__overflow">
<table class="v-datatable v-table theme--light">
<tbody>
<tr>
<td>UID</td>
<td><span class="clickable" @click.stop.prevent="copyText(model.UID)">{{ model.UID | uppercase }}</span></td>
</tr>
<tr v-if="model.DocumentID">
<td>Document ID</td>
<td><span class="clickable" @click.stop.prevent="copyText(model.DocumentID)">{{ model.DocumentID | uppercase }}</span></td>
</tr>
<tr>
<td :title="model.TypeSrc">
<translate>Type</translate>
<v-icon v-if="model.TypeSrc === 'manual'" class="src">check</v-icon>
</td>
<td>
<v-select
v-model="model.Type"
flat solo
browser-autocomplete="off"
@ -26,27 +27,27 @@
:items="options.PhotoTypes()"
class="input-type"
@change="save">
</v-select>
</td>
</tr>
<tr v-if="model.Path">
<td>
<translate>Folder</translate>
</td>
<td>{{ model.Path }}</td>
</tr>
<tr>
<td>
<translate>Name</translate>
</td>
<td>{{ model.Name }}</td>
</tr>
<tr v-if="model.OriginalName">
<td>
<translate>Original Name</translate>
</td>
<td>
<v-text-field
</v-select>
</td>
</tr>
<tr v-if="model.Path">
<td>
<translate>Folder</translate>
</td>
<td><span class="clickable" @click.stop.prevent="copyText(model.Path)">{{ model.Path }}</span></td>
</tr>
<tr>
<td>
<translate>Name</translate>
</td>
<td><span class="clickable" @click.stop.prevent="copyText(model.Name)">{{ model.Name }}</span></td>
</tr>
<tr v-if="model.OriginalName">
<td>
<translate>Original Name</translate>
</td>
<td>
<v-text-field
v-model="model.OriginalName"
flat solo dense hide-details
browser-autocomplete="off"
@ -54,64 +55,71 @@
autocapitalize="none"
color="secondary-dark"
@change="save"
></v-text-field>
</td>
</tr>
<tr>
<td :title="model.TitleSrc">
<translate>Title</translate>
<v-icon v-if="model.TitleSrc === 'manual'" class="src">check</v-icon>
</td>
<td>{{ model.Title }}</td>
</tr>
<tr>
<td :title="model.TakenSrc">
<translate>Taken</translate>
<v-icon v-if="model.TakenSrc === 'manual'" class="src">check</v-icon>
</td>
<td>{{ model.getDateString() }}</td>
</tr>
<tr v-if="albums.length > 0">
<td>
<translate>Albums</translate>
</td>
<td>
<a v-for="(a, i) in albums" :key="i" :href="a.url" class="primary--text text-link" target="_blank"><span v-if="i > 0">, </span>{{ a.title }}</a>
</td>
</tr>
<tr>
<td>
<translate>Quality Score</translate>
</td>
<td>
<v-rating v-model="model.Quality" :length="7" readonly small></v-rating>
</td>
</tr>
<tr>
<td>
<translate>Resolution</translate>
</td>
<td>{{ model.Resolution }} MP</td>
</tr>
<tr v-if="model.Faces > 0">
<td>
<translate>Faces</translate>
</td>
<td>{{ model.Faces }}</td>
</tr>
<tr v-if="model.CameraSerial">
<td>
<translate>Camera Serial</translate>
</td>
<td>{{ model.CameraSerial }}
</td>
</tr>
<tr v-if="model.Stack < 1">
<td>
<translate>Stackable</translate>
</td>
<td>
<v-switch
></v-text-field>
</td>
</tr>
<tr>
<td :title="sourceName(model.TitleSrc)">
<translate>Title</translate>
<v-icon v-if="model.TitleSrc === 'manual'" class="src">check</v-icon>
</td>
<td :title="sourceName(model.TitleSrc)">
<span class="clickable" @click.stop.prevent="copyText(model.Title)">{{ model.Title }}</span>
<v-icon v-if="model.TitleSrc === 'name'" class="src">insert_drive_file</v-icon>
</td>
</tr>
<tr>
<td :title="sourceName(model.TakenSrc)">
<translate>Taken</translate>
<v-icon v-if="model.TakenSrc === 'manual'" class="src">check</v-icon>
</td>
<td :title="sourceName(model.TakenSrc)">
{{ model.getDateString() }}
<v-icon v-if="model.TakenSrc === 'name' || model.TakenSrc === 'estimate'" class="src">insights</v-icon>
</td>
</tr>
<tr v-if="albums.length > 0">
<td>
<translate>Albums</translate>
</td>
<td>
<a v-for="(a, i) in albums" :key="i" :href="a.url" class="primary--text text-link"
target="_blank"><span v-if="i > 0">, </span>{{ a.title }}</a>
</td>
</tr>
<tr>
<td>
<translate>Quality Score</translate>
</td>
<td>
<v-rating v-model="model.Quality" :length="7" readonly small></v-rating>
</td>
</tr>
<tr>
<td>
<translate>Resolution</translate>
</td>
<td>{{ model.Resolution }} MP</td>
</tr>
<tr v-if="model.Faces > 0">
<td>
<translate>Faces</translate>
</td>
<td>{{ model.Faces }}</td>
</tr>
<tr v-if="model.CameraSerial">
<td>
<translate>Camera Serial</translate>
</td>
<td>{{ model.CameraSerial }}
</td>
</tr>
<tr v-if="model.Stack < 1">
<td>
<translate>Stackable</translate>
</td>
<td>
<v-switch
v-model="model.Stack"
hide-details
class="input-stackable"
@ -119,104 +127,105 @@
:false-value="-1"
:label="model.Stack > - 1 ? $gettext('Yes') : $gettext('No')"
@change="save"
></v-switch>
</td>
</tr>
<tr>
<td>
<translate>Favorite</translate>
</td>
<td>
<v-switch
></v-switch>
</td>
</tr>
<tr>
<td>
<translate>Favorite</translate>
</td>
<td>
<v-switch
v-model="model.Favorite"
hide-details
class="input-favorite"
:label="model.Favorite ? $gettext('Yes') : $gettext('No')"
@change="save"
></v-switch>
</td>
</tr>
<tr v-if="$config.feature('private')">
<td>
<translate>Private</translate>
</td>
<td>
<v-switch
></v-switch>
</td>
</tr>
<tr v-if="$config.feature('private')">
<td>
<translate>Private</translate>
</td>
<td>
<v-switch
v-model="model.Private"
hide-details
class="input-private"
:label="model.Private ? $gettext('Yes') : $gettext('No')"
@change="save"
></v-switch>
</td>
</tr>
<tr>
<td>
<translate>Scan</translate>
</td>
<td>
<v-switch
></v-switch>
</td>
</tr>
<tr>
<td>
<translate>Scan</translate>
</td>
<td>
<v-switch
v-model="model.Scan"
hide-details
class="input-scan"
:label="model.Scan ? $gettext('Yes') : $gettext('No')"
@change="save"
></v-switch>
</td>
</tr>
<tr>
<td>
<translate>Panorama</translate>
</td>
<td>
<v-switch
></v-switch>
</td>
</tr>
<tr>
<td>
<translate>Panorama</translate>
</td>
<td>
<v-switch
v-model="model.Panorama"
hide-details
class="input-panorama"
:label="model.Panorama ? $gettext('Yes') : $gettext('No')"
@change="save"
></v-switch>
</td>
</tr>
<tr>
<td :title="model.PlaceSrc">
<translate>Place</translate>
<v-icon v-if="model.PlaceSrc === 'manual'" class="src">check</v-icon>
</td>
<td>
{{ model.locationInfo() }}
</td>
</tr>
<tr v-if="model.Lat">
<td>
<translate>Latitude</translate>
</td>
<td>
{{ model.Lat }}
</td>
</tr>
<tr v-if="model.Lng">
<td>
<translate>Longitude</translate>
</td>
<td>
{{ model.Lng }}
</td>
</tr>
<tr v-if="model.Altitude">
<td>
<translate>Altitude</translate>
</td>
<td>
{{ model.Altitude }} m
</td>
</tr>
<tr v-if="model.Lat">
<td>
<translate>Accuracy</translate>
</td>
<td>
<v-text-field
></v-switch>
</td>
</tr>
<tr>
<td :title="sourceName(model.PlaceSrc)">
<translate>Place</translate>
<v-icon v-if="model.PlaceSrc === 'manual'" class="src">check</v-icon>
</td>
<td :title="sourceName(model.PlaceSrc)">
{{ model.locationInfo() }}
<v-icon v-if="model.PlaceSrc === 'estimate'" class="src">insights</v-icon>
</td>
</tr>
<tr v-if="model.Lat">
<td>
<translate>Latitude</translate>
</td>
<td>
{{ model.Lat }}
</td>
</tr>
<tr v-if="model.Lng">
<td>
<translate>Longitude</translate>
</td>
<td>
{{ model.Lng }}
</td>
</tr>
<tr v-if="model.Altitude">
<td>
<translate>Altitude</translate>
</td>
<td>
{{ model.Altitude }} m
</td>
</tr>
<tr v-if="model.Lat">
<td>
<translate>Accuracy</translate>
</td>
<td>
<v-text-field
v-model="model.CellAccuracy"
flat solo dense hide-details
browser-autocomplete="off"
@ -227,52 +236,53 @@
suffix="m"
style="width: 100px;"
@change="save"
></v-text-field>
</td>
</tr>
<tr>
<td>
<translate>Created</translate>
</td>
<td>
{{ formatTime(model.CreatedAt) }}
</td>
</tr>
<tr>
<td>
<translate>Updated</translate>
</td>
<td>
{{ formatTime(model.UpdatedAt) }}
</td>
</tr>
<tr v-if="model.EditedAt">
<td>
<translate>Edited</translate>
</td>
<td>
{{ formatTime(model.EditedAt) }}
</td>
</tr>
<tr v-if="model.CheckedAt">
<td>
<translate>Checked</translate>
</td>
<td>
{{ formatTime(model.CheckedAt) }}
</td>
</tr>
<tr v-if="model.DeletedAt">
<td>
<translate>Archived</translate>
</td>
<td>
{{ formatTime(model.DeletedAt) }}
</td>
</tr>
</tbody>
</table>
</div>
></v-text-field>
</td>
</tr>
<tr>
<td>
<translate>Created</translate>
</td>
<td>
{{ formatTime(model.CreatedAt) }}
</td>
</tr>
<tr>
<td>
<translate>Updated</translate>
</td>
<td>
{{ formatTime(model.UpdatedAt) }}
</td>
</tr>
<tr v-if="model.EditedAt">
<td>
<translate>Edited</translate>
</td>
<td>
{{ formatTime(model.EditedAt) }}
</td>
</tr>
<tr v-if="model.CheckedAt">
<td>
<translate>Checked</translate>
</td>
<td>
{{ formatTime(model.CheckedAt) }}
</td>
</tr>
<tr v-if="model.DeletedAt">
<td>
<translate>Archived</translate>
</td>
<td>
{{ formatTime(model.DeletedAt) }}
</td>
</tr>
</tbody>
</table>
</div>
</v-form>
</div>
</template>
@ -280,15 +290,21 @@
import Thumb from "model/thumb";
import {DateTime, Info} from "luxon";
import * as options from "options/options";
import {T} from "common/vm";
import Util from "common/util";
export default {
name: 'PTabPhotoAdvanced',
props: {
model: {
type: Object,
default: () => {},
default: () => {
},
},
uid: {
type: String,
default: "",
},
uid: String,
},
data() {
return {
@ -324,6 +340,40 @@ export default {
},
},
methods: {
async copyText(text) {
if (!text) {
return;
}
try {
await Util.copyToMachineClipboard(text);
this.$notify.success(this.$gettext("Copied to clipboard"));
} catch (error) {
this.$notify.error(this.$gettext("Failed copying to clipboard"));
}
},
sourceName(s) {
switch (s) {
case "":
case "auto":
case "manual":
return "";
case "meta":
return this.$gettext('Metadata');
case "xmp":
return "XMP";
case "estimate":
return this.$gettext("Estimate");
case "name":
return this.$gettext("Name");
case "image":
return this.$gettext("Image");
case "location":
return this.$gettext("Location");
default:
return T(Util.capitalize(s));
}
},
formatTime(s) {
return DateTime.fromISO(s).toLocaleString(DateTime.DATETIME_MED);
},
@ -341,7 +391,7 @@ export default {
return '#';
}
return this.$router.resolve({ name: 'album', params: { uid: m.UID, slug: 'view' }}).href;
return this.$router.resolve({name: 'album', params: {uid: m.UID, slug: 'view'}}).href;
},
},
};

View file

@ -1,102 +1,117 @@
<template>
<div class="p-tab p-tab-photo-labels">
<v-data-table
v-model="selected"
:headers="listColumns"
:items="model.Labels"
hide-actions
class="elevation-0 p-files p-files-list p-results"
disable-initial-sort
item-key="ID"
:no-data-text="$gettext('No labels found')"
>
<template #items="props" class="p-file">
<td>
<v-edit-dialog
:return-value.sync="props.item.Label.Name"
lazy
class="p-inline-edit"
@save="renameLabel(props.item.Label)"
<v-form ref="form" lazy-validation dense accept-charset="UTF-8" @submit.prevent>
<v-layout class="pa-2-md-and-up" row wrap align-top fill-height>
<v-flex class="pa-2 hidden-sm-and-down" xs12 md2 xxl1 fill-height>
<p-photo-preview :model="model"></p-photo-preview>
</v-flex>
<v-flex class="pa-2-md-and-up ra-4-table-md-and-up" xs12 md10 xxl11 fill-width fill-height>
<v-data-table
v-model="selected"
:headers="listColumns"
:items="model.Labels"
hide-actions
class="elevation-0 p-results"
disable-initial-sort
item-key="ID"
:no-data-text="$gettext('No labels found')"
>
{{ props.item.Label.Name }}
<template #input>
<v-text-field
v-model="props.item.Label.Name"
:rules="[nameRule]"
:label="$gettext('Name')"
color="secondary-dark"
class="input-rename background-inherit elevation-0"
single-line autofocus solo hide-details
></v-text-field>
<template #items="props" class="p-file">
<td>
<v-edit-dialog
:return-value.sync="props.item.Label.Name"
lazy
class="p-inline-edit"
@save="renameLabel(props.item.Label)"
>
{{ props.item.Label.Name }}
<template #input>
<v-text-field
v-model="props.item.Label.Name"
:rules="[nameRule]"
:label="$gettext('Name')"
color="secondary-dark"
class="input-rename background-inherit elevation-0"
single-line autofocus solo hide-details
></v-text-field>
</template>
</v-edit-dialog>
</td>
<td class="text-xs-left">{{ sourceName(props.item.LabelSrc) }}</td>
<td class="text-xs-center">{{ 100 - props.item.Uncertainty }}%</td>
<td class="text-xs-center">
<v-btn v-if="disabled" icon small flat :ripple="false"
class="action-view" title="Search"
@click.stop.prevent="searchLabel(props.item.Label)">
<v-icon color="secondary-dark">search</v-icon>
</v-btn>
<v-btn v-else-if="props.item.Uncertainty < 100 && props.item.LabelSrc === 'manual'" icon
small flat :ripple="false"
class="action-delete" title="Delete"
@click.stop.prevent="removeLabel(props.item.Label)">
<v-icon color="secondary-dark">delete</v-icon>
</v-btn>
<v-btn v-else-if="props.item.Uncertainty < 100" icon small flat :ripple="false"
class="action-remove" title="Remove"
@click.stop.prevent="removeLabel(props.item.Label)">
<v-icon color="secondary-dark">remove</v-icon>
</v-btn>
<v-btn v-else icon small flat :ripple="false"
class="action-on" title="Activate"
@click.stop.prevent="activateLabel(props.item.Label)">
<v-icon color="secondary-dark">add</v-icon>
</v-btn>
</td>
</template>
</v-edit-dialog>
</td>
<td class="text-xs-left">{{ sourceName(props.item.LabelSrc) }}</td>
<td class="text-xs-center">{{ 100 - props.item.Uncertainty }}%</td>
<td class="text-xs-center">
<v-btn v-if="disabled" icon small flat :ripple="false"
class="action-view" title="Search"
@click.stop.prevent="searchLabel(props.item.Label)">
<v-icon color="secondary-dark">search</v-icon>
</v-btn>
<v-btn v-else-if="props.item.Uncertainty < 100 && props.item.LabelSrc === 'manual'" icon
small flat :ripple="false"
class="action-delete" title="Delete"
@click.stop.prevent="removeLabel(props.item.Label)">
<v-icon color="secondary-dark">delete</v-icon>
</v-btn>
<v-btn v-else-if="props.item.Uncertainty < 100" icon small flat :ripple="false"
class="action-remove" title="Remove"
@click.stop.prevent="removeLabel(props.item.Label)">
<v-icon color="secondary-dark">remove</v-icon>
</v-btn>
<v-btn v-else icon small flat :ripple="false"
class="action-on" title="Activate"
@click.stop.prevent="activateLabel(props.item.Label)">
<v-icon color="secondary-dark">add</v-icon>
</v-btn>
</td>
</template>
<template v-if="!disabled" #footer>
<td>
<v-text-field
v-model="newLabel"
:rules="[nameRule]"
color="secondary-dark"
browser-autocomplete="off"
:label="$gettext('Name')"
single-line
flat solo hide-details
autofocus
class="input-label"
@keyup.enter.native="addLabel"
></v-text-field>
</td>
<td class="text-xs-left">{{ sourceName('manual') }}</td>
<td class="text-xs-center">100%</td>
<td class="text-xs-center">
<v-btn icon small flat :ripple="false" title="Add"
class="p-photo-label-add"
@click.stop.prevent="addLabel">
<v-icon color="secondary-dark">add</v-icon>
</v-btn>
</td>
</template>
</v-data-table>
<template v-if="!disabled" #footer>
<td>
<v-text-field
v-model="newLabel"
:rules="[nameRule]"
color="secondary-dark"
browser-autocomplete="off"
:label="$gettext('Name')"
single-line
flat solo hide-details
autofocus
class="input-label"
@keyup.enter.native="addLabel"
></v-text-field>
</td>
<td class="text-xs-left">{{ sourceName('manual') }}</td>
<td class="text-xs-center">100%</td>
<td class="text-xs-center">
<v-btn icon small flat :ripple="false" title="Add"
class="p-photo-label-add"
@click.stop.prevent="addLabel">
<v-icon color="secondary-dark">add</v-icon>
</v-btn>
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
<!-- div class="mt-1 clear"></div -->
</v-form>
</div>
</template>
<script>
import Label from "model/label";
import Thumb from "model/thumb";
export default {
name: 'PTabPhotoLabels',
props: {
model: {
type: Object,
default: () => {},
default: () => {
},
},
uid: {
type: String,
default: "",
},
uid: String,
},
data() {
return {
@ -170,6 +185,9 @@ export default {
this.$router.push({name: 'all', query: {q: 'label:' + label.Slug}}).catch(() => {});
this.$emit('close');
},
openPhoto() {
this.$viewer.show(Thumb.fromFiles([this.model]), 0);
},
},
};
</script>

View file

@ -13,7 +13,7 @@
<translate>Recognition starts after indexing has been completed.</translate>
</p>
</v-alert>
<v-layout row wrap class="search-results face-results cards-view">
<v-layout class="search-results face-results cards-view" row wrap fill-height>
<v-flex
v-for="(marker, index) in markers"
:key="index"

View file

@ -408,7 +408,7 @@ export default {
for (let i = 0; i < thumbs.length; i++) {
let t = thumbs[i];
result.push({"text": t.w + 'x' + t.h, "value": t.size});
result.push({"text": t.w + ' × ' + t.h, "value": t.size});
}
return result;

View file

@ -62,12 +62,16 @@
<p class="px-2 ma-0 text-xs-right opacity-85"><span v-if="eta">{{ eta }}</span></p>
</v-progress-linear>
<p v-if="safe" class="body-1">
<p v-if="isDemo" class="body-2">
<translate :translate-params="{n: fileLimit}">You can upload up to %{n} files for test purposes.</translate>
<translate>Please do not upload any private, unlawful or offensive pictures. </translate>
</p>
<p v-else-if="rejectNSFW" class="body-2">
<translate>Please don't upload photos containing offensive content.</translate>
<translate>Uploads that may contain such images will be rejected automatically.</translate>
</p>
<p v-if="review" class="body-1">
<p v-if="featReview" class="body-1">
<translate>Non-photographic and low-quality images require a review before they appear in search results.</translate>
</p>
@ -99,8 +103,13 @@ export default {
name: 'PUploadDialog',
props: {
show: Boolean,
data: {
type: Object,
default: () => {},
},
},
data() {
const isDemo = this.$config.get("demo");
return {
albums: [],
selectedAlbums: [],
@ -120,16 +129,29 @@ export default {
remainingTime: -1,
eta: "",
token: "",
review: this.$config.feature("review"),
safe: !this.$config.get("uploadNSFW"),
isDemo: isDemo,
fileLimit: isDemo ? 3 : 0,
rejectNSFW: !this.$config.get("uploadNSFW"),
featReview: this.$config.feature("review"),
rtl: this.$rtl,
};
},
watch: {
show: function () {
this.reset();
this.review = this.$config.feature("review");
this.safe = !this.$config.get("uploadNSFW");
this.isDemo = this.$config.get("demo");
this.fileLimit = this.isDemo ? 3 : 0;
this.rejectNSFW = !this.$config.get("uploadNSFW");
this.featReview = this.$config.feature("review");
// Set currently selected albums.
if (this.data && Array.isArray(this.data.albums)) {
this.selectedAlbums = this.data.albums;
} else {
this.selectedAlbums = [];
}
// Fetch albums from backend.
this.findAlbums("");
}
},
@ -180,8 +202,8 @@ export default {
this.failed = false;
this.current = 0;
this.total = 0;
this.totalFailed = 0;
this.totalSize = 0;
this.totalFailed = 0;
this.completedSize = 0;
this.completedTotal = 0;
this.started = 0;
@ -233,10 +255,19 @@ export default {
return;
}
this.selected = this.$refs.upload.files;
this.total = this.selected.length;
const files = this.$refs.upload.files;
if (this.total < 1) {
// Too many files selected for upload?
if (this.isDemo && files && files.length > this.fileLimit) {
Notify.error(this.$gettext("Too many files selected"));
return;
}
this.selected = files;
this.total = files.length;
// No files selected?
if (!this.selected || this.total < 1) {
return;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

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