Animated GIFs are transcoded to AVC because it is much smaller and thus also suitable for long/large animations. In addition, this commit adds support for more metadata fields such as frame rate, number of frames, file capture timestamp (unix milliseconds), media type, and software version. Support for SVG files can later be implemented in a similar way.
This commit is contained in:
parent
4253045b14
commit
82d61d1f93
165 changed files with 1569 additions and 768 deletions
|
@ -1,5 +1,5 @@
|
|||
# Debian 12, Codename "Bookworm"
|
||||
FROM photoprism/develop:220405-bookworm
|
||||
FROM photoprism/develop:220413-bookworm
|
||||
|
||||
## alternative base images
|
||||
# FROM photoprism/develop:bullseye # Debian 11, Codename "Bullseye"
|
||||
|
|
6
LICENSE
6
LICENSE
|
@ -623,9 +623,9 @@ copy of the Program in return for a fee.
|
|||
(a) PhotoPrism’s Brand Assets — including trademarks, logos, icons, fonts,
|
||||
corporate design, product and service names, and any other brand features
|
||||
and elements, whether registered or unregistered („Brand Assets“) — are
|
||||
proprietary assets owned exclusively by Michael Mayer and his legal successors
|
||||
(„PhotoPrism“). We reserve the right to object to any use or misuse in any
|
||||
jurisdiction worldwide. Visit <https://photoprism.app/trademark> to learn more.
|
||||
proprietary assets owned exclusively by PhotoPrism UG („PhotoPrism“). We
|
||||
reserve the right to object to any use or misuse in any jurisdiction
|
||||
worldwide. Visit <https://photoprism.app/trademark> to learn more.
|
||||
|
||||
(b) Contributors, licensees, business partners, and other third parties
|
||||
may never claim ownership of PhotoPrism's Brand Assets or brands confusingly
|
||||
|
|
|
@ -4,64 +4,72 @@
|
|||
TERMS OF USE
|
||||
|
||||
(a) We hereby grant you a non-exclusive, non-transferable right to use the
|
||||
Digital Assets accompanying the software, embedded in the documentation,
|
||||
or provided for download — such as icons, fonts, illustrations, graphics,
|
||||
Digital Assets accompanying the software, embedded in the documentation, or
|
||||
provided for download — such as icons, fonts, illustrations, graphics,
|
||||
wallpapers, videos, sounds, models, and sample files („Digital Assets“) —
|
||||
as part of the Official Software Distribution, unless otherwise noted.
|
||||
as part of the Software distributed by us, unless otherwise noted.
|
||||
|
||||
(b) Because some Digital Assets are licensed to us solely for direct
|
||||
distribution, we cannot redistribute them under a more permissive license
|
||||
for other purposes. If the author or copyright holder has not released them
|
||||
under a permissive license, you must obtain a license before using them in
|
||||
your own work, whether commercial or non-commercial in nature.
|
||||
distribution, we cannot redistribute them under a more permissive license for
|
||||
other purposes. If the author or copyright holder has not released them under a
|
||||
permissive license, you must obtain a license before using them in your own
|
||||
work, whether commercial or non-commercial in nature.
|
||||
|
||||
(c) Related documentation is available under the terms of the CC BY-NC-SA
|
||||
4.0 License, see <https://docs.photoprism.app/license/docs>. Other terms may
|
||||
apply to Digital Assets — in particular illustrations, graphics, and videos
|
||||
— embedded in the documentation if they are licensed to us solely for direct
|
||||
distribution. When in doubt, please ask before distributing or using
|
||||
them for other works.
|
||||
(c) Related documentation is available under the terms of the CC BY-NC-SA 4.0
|
||||
License. Other terms may apply to Digital Assets — in particular
|
||||
illustrations, graphics, and videos — embedded in the documentation if they
|
||||
are licensed to us solely for direct distribution. When in doubt, please ask
|
||||
before distributing or using them for other works.
|
||||
|
||||
TRADEMARK AND BRAND ASSETS
|
||||
|
||||
(a) PhotoPrism’s Brand Assets — including trademarks, logos, icons, fonts,
|
||||
corporate design, product and service names, and any other brand features
|
||||
and elements, whether registered or unregistered („Brand Assets“) — are
|
||||
proprietary assets owned exclusively by Michael Mayer and his legal successors
|
||||
(„PhotoPrism“). We reserve the right to object to any use or misuse in any
|
||||
jurisdiction worldwide. Visit <https://photoprism.app/trademark> to learn more.
|
||||
corporate design, product and service names, and any other brand features and
|
||||
elements, whether registered or unregistered („Brand Assets“) — are
|
||||
proprietary assets owned exclusively by PhotoPrism UG („PhotoPrism“). We
|
||||
reserve the right to object to any use or misuse in any jurisdiction worldwide.
|
||||
Visit photoprism.app/trademark to learn more.
|
||||
|
||||
(b) Contributors, licensees, business partners, and other third parties
|
||||
may never claim ownership of PhotoPrism's Brand Assets or brands confusingly
|
||||
similar to PhotoPrism's Brand Assets in any way, including, without
|
||||
limitation, as a trademark, service mark, company name or designation,
|
||||
domain name, social media profile/handle, or in any other manner.
|
||||
(b) Contributors, licensees, business partners, and other third parties may
|
||||
never claim ownership of PhotoPrism's Brand Assets or brands confusingly
|
||||
similar to PhotoPrism's Brand Assets in any way, including, without limitation,
|
||||
as a trademark, service mark, company name or designation, domain name, social
|
||||
media profile/handle, or in any other manner.
|
||||
|
||||
(c) You may not include the PhotoPrism trademark in the name of your app,
|
||||
product, or service, whether commercial or non-commercial in nature. This
|
||||
includes online services such as e-commerce, community, blog, information,
|
||||
advertising, and personal home pages, as well as apps, app stores, client
|
||||
apps, or third-party apps that interact with PhotoPrism.
|
||||
advertising, and personal home pages, as well as apps, app stores, client apps,
|
||||
or third-party apps that interact with PhotoPrism.
|
||||
|
||||
(d) In the event that any provision is found to be unenforceable by a court
|
||||
or other competent jurisdiction, the remaining portions hereof shall remain
|
||||
in full force and effect.
|
||||
|
||||
DISCLAIMER OF WARRANTY AND LIMITATION OF LIABILITY
|
||||
DISCLAIMER OF WARRANTY
|
||||
|
||||
OUR SOFTWARE, SERVICES, DOCUMENTATION, AND DIGITAL ASSETS ARE PROVIDED
|
||||
“AS-IS” AND WITHOUT WARRANTY OF ANY KIND. WE DISCLAIM ALL WARRANTIES,
|
||||
EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, TITLE, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
LIMITATION OF LIABILITY
|
||||
|
||||
WE WILL NOT BE LIABLE FOR ANY DAMAGES ASSOCIATED WITH OUR SOFTWARE AND
|
||||
SERVICES, INCLUDING WITHOUT LIMITATION ORDINARY, INCIDENTAL, INDIRECT, OR
|
||||
CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING BUT NOT LIMITED TO DAMAGES
|
||||
RELATING TO LOST DATA OR LOST PROFITS, EVEN IF WE HAVE BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided above
|
||||
cannot be given local legal effect according to their terms, reviewing courts
|
||||
shall apply local law that most closely approximates an absolute waiver of
|
||||
all civil liability in connection with our software and services, unless a
|
||||
warranty or assumption of liability was provided in return for a fee.
|
||||
SEVERABILITY
|
||||
|
||||
(a) If the Disclaimer of Warranty and Limitation of Liability set forth above
|
||||
cannot be given local legal effect according to their terms, the reviewing
|
||||
courts shall apply the local law that most closely approximates an absolute
|
||||
waiver of any civil liability in connection with our software and services,
|
||||
unless a written warranty or assumption of liability has been granted for a fee.
|
||||
|
||||
(b) In the event that any provision set forth above is found by a court of
|
||||
competent jurisdiction to be invalid, illegal, void or unenforceable, the
|
||||
remaining provisions shall remain in full force and effect and shall not be
|
||||
impaired, affected or invalidated in any way.
|
||||
|
||||
(c) It is hereby agreed and declared that it is the intention of the parties to
|
||||
enforce the remaining provisions without the inclusion of those provisions that
|
||||
may subsequently be declared invalid, illegal, void or unenforceable.
|
||||
|
|
|
@ -3,65 +3,73 @@
|
|||
## Terms of Use ##
|
||||
|
||||
(a) We hereby grant you a non-exclusive, non-transferable right to use the
|
||||
Digital Assets accompanying the software, embedded in the documentation,
|
||||
or provided for download — such as icons, fonts, illustrations, graphics,
|
||||
Digital Assets accompanying the software, embedded in the documentation, or
|
||||
provided for download — such as icons, fonts, illustrations, graphics,
|
||||
wallpapers, videos, sounds, models, and sample files („Digital Assets“) —
|
||||
as part of the Official Software Distribution, **unless otherwise noted**.
|
||||
as part of the Software distributed by us, unless otherwise noted.
|
||||
|
||||
(b) Because some Digital Assets are licensed to us solely for direct
|
||||
distribution, we cannot redistribute them under a more permissive license
|
||||
for other purposes. If the author or copyright holder has not released them
|
||||
under a permissive license, you must obtain a license before using them in
|
||||
your own work, whether commercial or non-commercial in nature.
|
||||
distribution, we cannot redistribute them under a more permissive license for
|
||||
other purposes. If the author or copyright holder has not released them under a
|
||||
permissive license, you must obtain a license before using them in your own
|
||||
work, whether commercial or non-commercial in nature.
|
||||
|
||||
(c) Related [documentation](https://docs.photoprism.app/) is available under
|
||||
the terms of the [CC BY-NC-SA 4.0 License](https://docs.photoprism.app/license/docs/).
|
||||
Other terms may apply to Digital Assets — in particular illustrations,
|
||||
graphics, and videos — embedded in the documentation if they are licensed
|
||||
to us solely for direct distribution. When in doubt, please ask before
|
||||
distributing or using them for other works.
|
||||
Other terms may apply to Digital Assets — in particular illustrations, graphics,
|
||||
and videos — embedded in the documentation if they are licensed to us solely
|
||||
for direct distribution. When in doubt, please ask before distributing or
|
||||
using them for other works.
|
||||
|
||||
## Trademark and Brand Assets ##
|
||||
|
||||
(a) PhotoPrism’s Brand Assets — including trademarks, logos, icons, fonts,
|
||||
corporate design, product and service names, and any other brand features
|
||||
and elements, whether registered or unregistered („Brand Assets“) — are
|
||||
proprietary assets owned exclusively by Michael Mayer and his legal successors
|
||||
(„PhotoPrism“). We reserve the right to object to any use or misuse in any
|
||||
jurisdiction worldwide. Visit [photoprism.app/trademark](https://photoprism.app/trademark)
|
||||
to learn more.
|
||||
corporate design, product and service names, and any other brand features and
|
||||
elements, whether registered or unregistered („Brand Assets“) — are
|
||||
proprietary assets owned exclusively by PhotoPrism UG („PhotoPrism“). We
|
||||
reserve the right to object to any use or misuse in any jurisdiction worldwide.
|
||||
Visit photoprism.app/trademark to learn more.
|
||||
|
||||
(b) Contributors, licensees, business partners, and other third parties
|
||||
may never claim ownership of PhotoPrism's Brand Assets or brands confusingly
|
||||
similar to PhotoPrism's Brand Assets in any way, including, without
|
||||
limitation, as a trademark, service mark, company name or designation,
|
||||
domain name, social media profile/handle, or in any other manner.
|
||||
(b) Contributors, licensees, business partners, and other third parties may
|
||||
never claim ownership of PhotoPrism's Brand Assets or brands confusingly
|
||||
similar to PhotoPrism's Brand Assets in any way, including, without limitation,
|
||||
as a trademark, service mark, company name or designation, domain name, social
|
||||
media profile/handle, or in any other manner.
|
||||
|
||||
(c) You may not include the PhotoPrism trademark in the name of your app,
|
||||
product, or service, whether commercial or non-commercial in nature. This
|
||||
includes online services such as e-commerce, community, blog, information,
|
||||
advertising, and personal home pages, as well as apps, app stores, client
|
||||
apps, or third-party apps that interact with PhotoPrism.
|
||||
advertising, and personal home pages, as well as apps, app stores, client apps,
|
||||
or third-party apps that interact with PhotoPrism.
|
||||
|
||||
(d) In the event that any provision is found to be unenforceable by a court
|
||||
or other competent jurisdiction, the remaining portions hereof shall remain
|
||||
in full force and effect.
|
||||
|
||||
## Disclaimer of Warranty and Limitation of Liability ##
|
||||
## Disclaimer of Warranty ##
|
||||
|
||||
OUR SOFTWARE, SERVICES, DOCUMENTATION, AND DIGITAL ASSETS ARE PROVIDED
|
||||
“AS-IS” AND WITHOUT WARRANTY OF ANY KIND. WE DISCLAIM ALL WARRANTIES,
|
||||
EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, TITLE, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
## Limitation of Liability ##
|
||||
|
||||
WE WILL NOT BE LIABLE FOR ANY DAMAGES ASSOCIATED WITH OUR SOFTWARE AND
|
||||
SERVICES, INCLUDING WITHOUT LIMITATION ORDINARY, INCIDENTAL, INDIRECT, OR
|
||||
CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING BUT NOT LIMITED TO DAMAGES
|
||||
RELATING TO LOST DATA OR LOST PROFITS, EVEN IF WE HAVE BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided above
|
||||
cannot be given local legal effect according to their terms, reviewing courts
|
||||
shall apply local law that most closely approximates an absolute waiver of
|
||||
all civil liability in connection with our software and services, unless a
|
||||
warranty or assumption of liability was provided in return for a fee.
|
||||
## Severability ##
|
||||
|
||||
(a) If the Disclaimer of Warranty and Limitation of Liability set forth above
|
||||
cannot be given local legal effect according to their terms, the reviewing
|
||||
courts shall apply the local law that most closely approximates an absolute
|
||||
waiver of any civil liability in connection with our software and services,
|
||||
unless a written warranty or assumption of liability has been granted for a fee.
|
||||
|
||||
(b) In the event that any provision set forth above is found by a court of
|
||||
competent jurisdiction to be invalid, illegal, void or unenforceable, the
|
||||
remaining provisions shall remain in full force and effect and shall not be
|
||||
impaired, affected or invalidated in any way.
|
||||
|
||||
(c) It is hereby agreed and declared that it is the intention of the parties to
|
||||
enforce the remaining provisions without the inclusion of those provisions that
|
||||
may subsequently be declared invalid, illegal, void or unenforceable.
|
||||
|
|
6
assets/examples/NOTICE.md
Normal file
6
assets/examples/NOTICE.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
Sample File Attribution
|
||||
===========================================================================
|
||||
|
||||
| Filename | Author | URL |
|
||||
|----------------|------------|----------------------------------------------------------------------|
|
||||
| pythagoras.gif | Petrus3743 | <https://commons.wikimedia.org/wiki/File:01-Satz_des_Pythagoras.gif> |
|
25
assets/examples/example.gif.json
Normal file
25
assets/examples/example.gif.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
[{
|
||||
"SourceFile": "example.gif",
|
||||
"ExifToolVersion": 12.40,
|
||||
"FileName": "example.gif",
|
||||
"Directory": ".",
|
||||
"FileSize": 5760,
|
||||
"FileModifyDate": "2021:11:01 14:39:36+00:00",
|
||||
"FileAccessDate": "2022:04:12 15:49:52+00:00",
|
||||
"FileInodeChangeDate": "2022:03:02 20:29:31+00:00",
|
||||
"FilePermissions": 100666,
|
||||
"FileType": "GIF",
|
||||
"FileTypeExtension": "GIF",
|
||||
"MIMEType": "image/gif",
|
||||
"GIFVersion": "89a",
|
||||
"ImageWidth": 100,
|
||||
"ImageHeight": 67,
|
||||
"HasColorMap": 1,
|
||||
"ColorResolutionDepth": 8,
|
||||
"BitsPerPixel": 8,
|
||||
"BackgroundColor": 0,
|
||||
"AnimationIterations": 0,
|
||||
"TransparentColor": 255,
|
||||
"ImageSize": "100 67",
|
||||
"Megapixels": 0.0067
|
||||
}]
|
BIN
assets/examples/pythagoras.gif
Normal file
BIN
assets/examples/pythagoras.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 187 KiB |
28
assets/examples/pythagoras.json
Normal file
28
assets/examples/pythagoras.json
Normal file
|
@ -0,0 +1,28 @@
|
|||
[{
|
||||
"SourceFile": "pythagoras.gif",
|
||||
"ExifToolVersion": 12.40,
|
||||
"FileName": "pythagoras.gif",
|
||||
"Directory": ".",
|
||||
"FileSize": 191371,
|
||||
"FileModifyDate": "2022:04:13 08:42:33+00:00",
|
||||
"FileAccessDate": "2022:04:13 10:52:43+00:00",
|
||||
"FileInodeChangeDate": "2022:04:13 08:42:42+00:00",
|
||||
"FilePermissions": 100664,
|
||||
"FileType": "GIF",
|
||||
"FileTypeExtension": "GIF",
|
||||
"MIMEType": "image/gif",
|
||||
"GIFVersion": "89a",
|
||||
"ImageWidth": 591,
|
||||
"ImageHeight": 639,
|
||||
"HasColorMap": 1,
|
||||
"ColorResolutionDepth": 7,
|
||||
"BitsPerPixel": 8,
|
||||
"BackgroundColor": 255,
|
||||
"AnimationIterations": 0,
|
||||
"Comment": "Created with GIMP",
|
||||
"TransparentColor": 255,
|
||||
"FrameCount": 201,
|
||||
"Duration": 49.8,
|
||||
"ImageSize": "591 639",
|
||||
"Megapixels": 0.377649
|
||||
}]
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
@ -38,7 +38,7 @@ var version = "development"
|
|||
var log = event.Log
|
||||
|
||||
const appDescription = "Visit https://docs.photoprism.app/ to learn more."
|
||||
const appCopyright = "(c) 2018-2022 Michael Mayer <hello@photoprism.app>"
|
||||
const appCopyright = "(c) 2018-2022 PhotoPrism UG. All rights reserved."
|
||||
|
||||
func main() {
|
||||
defer func() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
232
frontend/package-lock.json
generated
232
frontend/package-lock.json
generated
|
@ -3230,9 +3230,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001328",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001328.tgz",
|
||||
"integrity": "sha512-Ue55jHkR/s4r00FLNiX+hGMMuwml/QGqqzVeMQ5thUewznU2EdULFvI3JR7JJid6OrjJNfFvHY2G2dIjmRaDDQ==",
|
||||
"version": "1.0.30001331",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001331.tgz",
|
||||
"integrity": "sha512-Y1xk6paHpUXKP/P6YjQv1xqyTbgAP05ycHBcRdQjTcyXlWol868sJJPlmk5ylOekw2BrucWes5jk+LvVd7WZ5Q==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
@ -3837,25 +3837,28 @@
|
|||
}
|
||||
},
|
||||
"node_modules/css-loader/node_modules/lru-cache": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz",
|
||||
"integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/css-loader/node_modules/semver": {
|
||||
"version": "7.3.6",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz",
|
||||
"integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==",
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^7.4.0"
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/css-prefers-color-scheme": {
|
||||
|
@ -4479,9 +4482,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.9.2",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz",
|
||||
"integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==",
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
|
||||
"integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
"tapable": "^2.2.0"
|
||||
|
@ -4523,9 +4526,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/es-abstract": {
|
||||
"version": "1.19.3",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.3.tgz",
|
||||
"integrity": "sha512-4axXLNovnMYf0+csS5rVnS5hLmV1ek+ecx9MuCjByL1E5Nn54avf6CHQxIjgQIHBnfX9AMxTRIy0q+Yu5J/fXA==",
|
||||
"version": "1.19.4",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.4.tgz",
|
||||
"integrity": "sha512-flV8e5g9/xulChMG48Fygk1ptpo4lQRJ0eJYtxJFgi7pklLx7EFcOJ34jnvr8pbWlaFN/AT1cZpe0hiFel9Hqg==",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"es-to-primitive": "^1.2.1",
|
||||
|
@ -5192,25 +5195,28 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vue/node_modules/lru-cache": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz",
|
||||
"integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vue/node_modules/semver": {
|
||||
"version": "7.3.6",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz",
|
||||
"integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==",
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^7.4.0"
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-rule-docs": {
|
||||
|
@ -6053,19 +6059,19 @@
|
|||
"integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg=="
|
||||
},
|
||||
"node_modules/flow-parser": {
|
||||
"version": "0.175.1",
|
||||
"resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.175.1.tgz",
|
||||
"integrity": "sha512-gYes5/nxeLYiu02MMb+WH4KaOIYrVcTVIuV9M4aP/4hqJ+zULxxS/In+WEj/tEBsQ+8/wSHo9IDWKQL1FhrLmA==",
|
||||
"version": "0.176.0",
|
||||
"resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.176.0.tgz",
|
||||
"integrity": "sha512-h3OUIHINMtdOnaMXyJH5ryqly1rft0Lt/di22dJB35FCnulSTxWvQhDtOH2dxQMU48/wtUmAOo4sv7Mj7XNyng==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/flow-remove-types": {
|
||||
"version": "2.175.1",
|
||||
"resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.175.1.tgz",
|
||||
"integrity": "sha512-malB3a9t7zEi5TMBbQlSZ47vqH673aiN+a34Xlv6/q3fJwyaXYlIz2wa9tMa3h5kM26aH7dFRS0GeBbfV1C5IQ==",
|
||||
"version": "2.176.0",
|
||||
"resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.176.0.tgz",
|
||||
"integrity": "sha512-jvNyonnqDe9v0OkLPTNeZwpgc0zaGvqFcpz3rfmgbSvynnJ8ldcv7mcYZ62UtdCbZas23bXUIxMsrgLiIkScPQ==",
|
||||
"dependencies": {
|
||||
"flow-parser": "^0.175.1",
|
||||
"flow-parser": "^0.176.0",
|
||||
"pirates": "^3.0.2",
|
||||
"vlq": "^0.2.1"
|
||||
},
|
||||
|
@ -7494,9 +7500,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/karma": {
|
||||
"version": "6.3.17",
|
||||
"resolved": "https://registry.npmjs.org/karma/-/karma-6.3.17.tgz",
|
||||
"integrity": "sha512-2TfjHwrRExC8yHoWlPBULyaLwAFmXmxQrcuFImt/JsAsSZu1uOWTZ1ZsWjqQtWpHLiatJOHL5jFjXSJIgCd01g==",
|
||||
"version": "6.3.18",
|
||||
"resolved": "https://registry.npmjs.org/karma/-/karma-6.3.18.tgz",
|
||||
"integrity": "sha512-YEwXVHRILKWKN7uEW9IkgTPjnYGb3YA3MDvlp04xpSRAyrNPoRmsBayLDgHykKAwBm6/mAOckj4xi/1JdQfhzQ==",
|
||||
"dependencies": {
|
||||
"@colors/colors": "1.5.0",
|
||||
"body-parser": "^1.19.0",
|
||||
|
@ -7517,7 +7523,7 @@
|
|||
"qjobs": "^1.2.0",
|
||||
"range-parser": "^1.2.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"socket.io": "^4.2.0",
|
||||
"socket.io": "^4.4.1",
|
||||
"source-map": "^0.6.1",
|
||||
"tmp": "^0.2.1",
|
||||
"ua-parser-js": "^0.7.30",
|
||||
|
@ -9292,25 +9298,28 @@
|
|||
}
|
||||
},
|
||||
"node_modules/postcss-loader/node_modules/lru-cache": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz",
|
||||
"integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-loader/node_modules/semver": {
|
||||
"version": "7.3.6",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz",
|
||||
"integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==",
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^7.4.0"
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-logical": {
|
||||
|
@ -12033,25 +12042,28 @@
|
|||
}
|
||||
},
|
||||
"node_modules/vue-eslint-parser/node_modules/lru-cache": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz",
|
||||
"integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-eslint-parser/node_modules/semver": {
|
||||
"version": "7.3.6",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz",
|
||||
"integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==",
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^7.4.0"
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-fullscreen": {
|
||||
|
@ -15132,9 +15144,9 @@
|
|||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001328",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001328.tgz",
|
||||
"integrity": "sha512-Ue55jHkR/s4r00FLNiX+hGMMuwml/QGqqzVeMQ5thUewznU2EdULFvI3JR7JJid6OrjJNfFvHY2G2dIjmRaDDQ=="
|
||||
"version": "1.0.30001331",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001331.tgz",
|
||||
"integrity": "sha512-Y1xk6paHpUXKP/P6YjQv1xqyTbgAP05ycHBcRdQjTcyXlWol868sJJPlmk5ylOekw2BrucWes5jk+LvVd7WZ5Q=="
|
||||
},
|
||||
"chai": {
|
||||
"version": "4.3.6",
|
||||
|
@ -15571,16 +15583,19 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz",
|
||||
"integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg=="
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.6",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz",
|
||||
"integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==",
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||
"requires": {
|
||||
"lru-cache": "^7.4.0"
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16039,9 +16054,9 @@
|
|||
}
|
||||
},
|
||||
"enhanced-resolve": {
|
||||
"version": "5.9.2",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz",
|
||||
"integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==",
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
|
||||
"integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
"tapable": "^2.2.0"
|
||||
|
@ -16071,9 +16086,9 @@
|
|||
}
|
||||
},
|
||||
"es-abstract": {
|
||||
"version": "1.19.3",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.3.tgz",
|
||||
"integrity": "sha512-4axXLNovnMYf0+csS5rVnS5hLmV1ek+ecx9MuCjByL1E5Nn54avf6CHQxIjgQIHBnfX9AMxTRIy0q+Yu5J/fXA==",
|
||||
"version": "1.19.4",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.4.tgz",
|
||||
"integrity": "sha512-flV8e5g9/xulChMG48Fygk1ptpo4lQRJ0eJYtxJFgi7pklLx7EFcOJ34jnvr8pbWlaFN/AT1cZpe0hiFel9Hqg==",
|
||||
"requires": {
|
||||
"call-bind": "^1.0.2",
|
||||
"es-to-primitive": "^1.2.1",
|
||||
|
@ -16655,16 +16670,19 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz",
|
||||
"integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg=="
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.6",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz",
|
||||
"integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==",
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||
"requires": {
|
||||
"lru-cache": "^7.4.0"
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17177,16 +17195,16 @@
|
|||
"integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg=="
|
||||
},
|
||||
"flow-parser": {
|
||||
"version": "0.175.1",
|
||||
"resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.175.1.tgz",
|
||||
"integrity": "sha512-gYes5/nxeLYiu02MMb+WH4KaOIYrVcTVIuV9M4aP/4hqJ+zULxxS/In+WEj/tEBsQ+8/wSHo9IDWKQL1FhrLmA=="
|
||||
"version": "0.176.0",
|
||||
"resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.176.0.tgz",
|
||||
"integrity": "sha512-h3OUIHINMtdOnaMXyJH5ryqly1rft0Lt/di22dJB35FCnulSTxWvQhDtOH2dxQMU48/wtUmAOo4sv7Mj7XNyng=="
|
||||
},
|
||||
"flow-remove-types": {
|
||||
"version": "2.175.1",
|
||||
"resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.175.1.tgz",
|
||||
"integrity": "sha512-malB3a9t7zEi5TMBbQlSZ47vqH673aiN+a34Xlv6/q3fJwyaXYlIz2wa9tMa3h5kM26aH7dFRS0GeBbfV1C5IQ==",
|
||||
"version": "2.176.0",
|
||||
"resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.176.0.tgz",
|
||||
"integrity": "sha512-jvNyonnqDe9v0OkLPTNeZwpgc0zaGvqFcpz3rfmgbSvynnJ8ldcv7mcYZ62UtdCbZas23bXUIxMsrgLiIkScPQ==",
|
||||
"requires": {
|
||||
"flow-parser": "^0.175.1",
|
||||
"flow-parser": "^0.176.0",
|
||||
"pirates": "^3.0.2",
|
||||
"vlq": "^0.2.1"
|
||||
},
|
||||
|
@ -18159,9 +18177,9 @@
|
|||
}
|
||||
},
|
||||
"karma": {
|
||||
"version": "6.3.17",
|
||||
"resolved": "https://registry.npmjs.org/karma/-/karma-6.3.17.tgz",
|
||||
"integrity": "sha512-2TfjHwrRExC8yHoWlPBULyaLwAFmXmxQrcuFImt/JsAsSZu1uOWTZ1ZsWjqQtWpHLiatJOHL5jFjXSJIgCd01g==",
|
||||
"version": "6.3.18",
|
||||
"resolved": "https://registry.npmjs.org/karma/-/karma-6.3.18.tgz",
|
||||
"integrity": "sha512-YEwXVHRILKWKN7uEW9IkgTPjnYGb3YA3MDvlp04xpSRAyrNPoRmsBayLDgHykKAwBm6/mAOckj4xi/1JdQfhzQ==",
|
||||
"requires": {
|
||||
"@colors/colors": "1.5.0",
|
||||
"body-parser": "^1.19.0",
|
||||
|
@ -18182,7 +18200,7 @@
|
|||
"qjobs": "^1.2.0",
|
||||
"range-parser": "^1.2.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"socket.io": "^4.2.0",
|
||||
"socket.io": "^4.4.1",
|
||||
"source-map": "^0.6.1",
|
||||
"tmp": "^0.2.1",
|
||||
"ua-parser-js": "^0.7.30",
|
||||
|
@ -19440,16 +19458,19 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz",
|
||||
"integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg=="
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.6",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz",
|
||||
"integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==",
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||
"requires": {
|
||||
"lru-cache": "^7.4.0"
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21417,16 +21438,19 @@
|
|||
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz",
|
||||
"integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg=="
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.6",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz",
|
||||
"integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==",
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||
"requires": {
|
||||
"lru-cache": "^7.4.0"
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "photoprism",
|
||||
"version": "1.0.0",
|
||||
"description": "PhotoPrism Progressive Web App (PWA)",
|
||||
"author": "Michael Mayer",
|
||||
"description": "AI-Powered Photos App",
|
||||
"author": "PhotoPrism UG",
|
||||
"license": "AGPL-3.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
@ -32,6 +32,10 @@ const Hour = 60 * Minute;
|
|||
let start = new Date();
|
||||
|
||||
export default class Util {
|
||||
static fps(fps) {
|
||||
return `${fps.toFixed(1)} FPS`;
|
||||
}
|
||||
|
||||
static duration(d) {
|
||||
let u = d;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -9,10 +9,9 @@
|
|||
</v-flex>
|
||||
|
||||
<v-flex xs12 sm6 class="px-0 pb-2 body-1 text-xs-left text-sm-right">
|
||||
<a href="https://photoprism.app/team/" target="_blank">© 2018-2022 Michael Mayer</a><br>
|
||||
<a href="https://photoprism.app/team/" target="_blank">© 2018-2022 PhotoPrism UG</a><br>
|
||||
<a href="https://raw.githubusercontent.com/photoprism/photoprism/develop/NOTICE"
|
||||
target="_blank" class="text-link">
|
||||
3rd-party software packages</a>
|
||||
target="_blank" class="text-link">3rd-party software packages</a>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-card-actions>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -106,6 +106,15 @@
|
|||
</v-list-tile-content>
|
||||
</v-list-tile>
|
||||
|
||||
<v-list-tile :to="{name: 'browse', query: { q: 'type:animated' }}" :exact="true" class="nav-animated"
|
||||
@click.stop="">
|
||||
<v-list-tile-content>
|
||||
<v-list-tile-title :class="`menu-item ${rtl ? '--rtl' : ''}`">
|
||||
<translate>Animated</translate>
|
||||
</v-list-tile-title>
|
||||
</v-list-tile-content>
|
||||
</v-list-tile>
|
||||
|
||||
<v-list-tile :to="{name: 'photos', query: { q: 'stack:true' }}" :exact="true" class="nav-stacks" @click.stop="">
|
||||
<v-list-tile-content>
|
||||
<v-list-tile-title :class="`p-flex-menuitem menu-item ${rtl ? '--rtl' : ''}`">
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
@mouseover="playLive(photo)"
|
||||
@mouseleave="pauseLive(photo)"
|
||||
>
|
||||
<v-layout v-if="photo.Type === 'live'" class="live-player">
|
||||
<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>
|
||||
<source :src="photo.videoUrl()">
|
||||
|
@ -153,7 +153,7 @@
|
|||
{{ photo.getDateString(true) }}
|
||||
</button>
|
||||
<br>
|
||||
<button v-if="photo.Type === 'video'" :title="labels.video"
|
||||
<button v-if="photo.Type === 'video' || photo.Type === 'animated'" :title="labels.video"
|
||||
@click.exact="openPhoto(index, true)">
|
||||
<v-icon size="14">movie</v-icon>
|
||||
{{ photo.getVideoInfo() }}
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
<v-icon color="white" class="select-on">check_circle</v-icon>
|
||||
<v-icon color="white" class="select-off">radio_button_off</v-icon>
|
||||
</v-btn>
|
||||
<v-btn v-else-if="props.item.Type === 'video' || props.item.Type === 'live'"
|
||||
<v-btn v-else-if="props.item.Type === 'video' || props.item.Type === 'live' || props.item.Type === 'animated'"
|
||||
:ripple="false"
|
||||
flat icon large absolute class="input-open"
|
||||
@click.stop.prevent="openPhoto(props.index, true)">
|
||||
|
@ -211,7 +211,7 @@ export default {
|
|||
} else if (this.photos[index]) {
|
||||
let photo = this.photos[index];
|
||||
|
||||
if (photo.Type === 'video' && photo.isPlayable()) {
|
||||
if ((photo.Type === 'video' || photo.Type === 'animated') && photo.isPlayable()) {
|
||||
this.openPhoto(index, true);
|
||||
} else {
|
||||
this.openPhoto(index, false);
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
@mouseover="playLive(photo)"
|
||||
@mouseleave="pauseLive(photo)"
|
||||
>
|
||||
<v-layout v-if="photo.Type === 'live'" class="live-player">
|
||||
<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>
|
||||
<source :src="photo.videoUrl()">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -300,6 +300,7 @@ body.chrome #photoprism .search-results .result {
|
|||
#photoprism .search-results.select-results .type-image .input-view,
|
||||
#photoprism .search-results .type-raw .input-open,
|
||||
#photoprism .search-results .type-video.is-playable .input-open,
|
||||
#photoprism .search-results .type-animated.is-playable .input-open,
|
||||
#photoprism .search-results .type-live.is-playable .input-open,
|
||||
#photoprism .search-results .type-image.is-stack .input-open {
|
||||
display: inline-flex;
|
||||
|
@ -311,6 +312,7 @@ body.chrome #photoprism .search-results .result {
|
|||
|
||||
#photoprism .search-results .type-raw .input-open .action-raw,
|
||||
#photoprism .search-results .type-video.is-playable .input-open .action-play,
|
||||
#photoprism .search-results .type-animated.is-playable .input-open .action-play,
|
||||
#photoprism .search-results .type-live.is-playable .input-open .action-live,
|
||||
#photoprism .search-results .type-image.is-stack .input-open .action-stack {
|
||||
display: inline-flex;
|
||||
|
@ -320,6 +322,7 @@ body.chrome #photoprism .search-results .result {
|
|||
display: none;
|
||||
}
|
||||
|
||||
#photoprism .search-results .type-animated.is-playable:hover .live-player,
|
||||
#photoprism .search-results .type-live.is-playable:hover .live-player {
|
||||
display: flex;
|
||||
overflow: hidden !important;
|
||||
|
@ -330,6 +333,7 @@ body.chrome #photoprism .search-results .result {
|
|||
}
|
||||
|
||||
#photoprism .search-results.list-view .type-video.is-playable .input-play,
|
||||
#photoprism .search-results.list-view .type-animated.is-playable .input-play,
|
||||
#photoprism .search-results.list-view .type-live.is-playable .input-play {
|
||||
display: inline-flex;
|
||||
opacity: 0.75;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<div class="v-table__overflow">
|
||||
<table class="v-datatable v-table theme--light photo-files">
|
||||
<tbody>
|
||||
<tr v-if="file.Type === 'jpg'">
|
||||
<tr v-if="file.FileType === 'jpg'">
|
||||
<td>
|
||||
<translate>Preview</translate>
|
||||
</td>
|
||||
|
@ -45,7 +45,7 @@
|
|||
@click.stop.prevent="downloadFile(file)">
|
||||
<translate>Download</translate>
|
||||
</v-btn>
|
||||
<v-btn v-if="features.edit && file.Type === 'jpg' && !file.Error && !file.Primary" small depressed dark
|
||||
<v-btn v-if="features.edit && file.FileType === 'jpg' && !file.Error && !file.Primary" small depressed dark
|
||||
color="primary-button"
|
||||
class="ma-0 action-primary"
|
||||
@click.stop.prevent="primaryFile(file)">
|
||||
|
@ -106,7 +106,7 @@
|
|||
</td>
|
||||
<td>{{ file.sizeInfo() }}</td>
|
||||
</tr>
|
||||
<tr v-if="file.Type">
|
||||
<tr v-if="file.FileType">
|
||||
<td>
|
||||
<translate>Type</translate>
|
||||
</td>
|
||||
|
@ -118,6 +118,18 @@
|
|||
</td>
|
||||
<td>{{ codecName(file) }}</td>
|
||||
</tr>
|
||||
<tr v-if="file.Frames">
|
||||
<td>
|
||||
<translate>Frames</translate>
|
||||
</td>
|
||||
<td>{{ file.Frames }}</td>
|
||||
</tr>
|
||||
<tr v-if="file.FPS">
|
||||
<td>
|
||||
<translate>FPS</translate>
|
||||
</td>
|
||||
<td>{{ file.FPS.toFixed(1) }}</td>
|
||||
</tr>
|
||||
<tr v-if="file.Primary">
|
||||
<td>
|
||||
<translate>Primary</translate>
|
||||
|
|
|
@ -41,15 +41,15 @@ msgstr ""
|
|||
msgid "%{n} pictures found"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:371
|
||||
#: src/options/options.js:375
|
||||
msgid "1 hour"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:373
|
||||
#: src/options/options.js:377
|
||||
msgid "12 hours"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:372
|
||||
#: src/options/options.js:376
|
||||
msgid "4 hours"
|
||||
msgstr ""
|
||||
|
||||
|
@ -57,7 +57,7 @@ msgstr ""
|
|||
msgid "A click will copy it to your clipboard."
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:398
|
||||
#: src/component/navigation.vue:406
|
||||
#: src/component/navigation.vue:27
|
||||
#: src/pages/about/about.vue:4
|
||||
#: src/pages/about/about.vue:183
|
||||
|
@ -120,8 +120,8 @@ msgstr ""
|
|||
msgid "Add to album"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:171
|
||||
#: src/dialog/photo/files.vue:168
|
||||
#: src/dialog/photo/files.vue:183
|
||||
#: src/dialog/photo/files.vue:180
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
|
@ -129,23 +129,23 @@ msgstr ""
|
|||
msgid "Advanced"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:381
|
||||
#: src/options/options.js:385
|
||||
msgid "After 1 day"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:382
|
||||
#: src/options/options.js:386
|
||||
msgid "After 3 days"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:383
|
||||
#: src/options/options.js:387
|
||||
msgid "After 7 days"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:385
|
||||
#: src/options/options.js:389
|
||||
msgid "After one month"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:387
|
||||
#: src/options/options.js:391
|
||||
msgid "After one year"
|
||||
msgstr ""
|
||||
|
||||
|
@ -154,11 +154,11 @@ msgstr ""
|
|||
msgid "After selecting pictures from search results, you can add them to an album using the context menu."
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:386
|
||||
#: src/options/options.js:390
|
||||
msgid "After two months"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:384
|
||||
#: src/options/options.js:388
|
||||
msgid "After two weeks"
|
||||
msgstr ""
|
||||
|
||||
|
@ -173,10 +173,10 @@ msgstr ""
|
|||
|
||||
#: src/app/routes.js:129
|
||||
#: src/app/routes.js:136
|
||||
#: src/component/navigation.vue:136
|
||||
#: src/component/navigation.vue:146
|
||||
#: src/component/navigation.vue:144
|
||||
#: src/component/navigation.vue:154
|
||||
#: src/component/navigation.vue:4
|
||||
#: src/component/navigation.vue:572
|
||||
#: src/component/navigation.vue:601
|
||||
#: src/share/albums.vue:4
|
||||
msgid "Albums"
|
||||
msgstr ""
|
||||
|
@ -264,6 +264,12 @@ msgstr ""
|
|||
msgid "An error occurred - are you offline?"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:98
|
||||
#: src/options/options.js:310
|
||||
msgid "Animated"
|
||||
msgstr ""
|
||||
|
||||
#: src/model/file.js:189
|
||||
#: src/pages/settings/general.vue:533
|
||||
msgid "Animation"
|
||||
msgstr ""
|
||||
|
@ -288,7 +294,7 @@ msgid "Approve"
|
|||
msgstr ""
|
||||
|
||||
#: src/app/routes.js:210
|
||||
#: src/component/navigation.vue:123
|
||||
#: src/component/navigation.vue:131
|
||||
#: src/component/photo/cards.vue:36
|
||||
#: src/component/photo/clipboard.vue:216
|
||||
#: src/pages/settings/general.vue:294
|
||||
|
@ -332,8 +338,8 @@ msgstr ""
|
|||
msgid "Artist"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:131
|
||||
#: src/dialog/photo/files.vue:128
|
||||
#: src/dialog/photo/files.vue:143
|
||||
#: src/dialog/photo/files.vue:140
|
||||
msgid "Aspect Ratio"
|
||||
msgstr ""
|
||||
|
||||
|
@ -358,19 +364,19 @@ msgstr ""
|
|||
msgid "Bio"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:406
|
||||
#: src/options/options.js:410
|
||||
msgid "Black"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:419
|
||||
#: src/options/options.js:423
|
||||
msgid "Blackman: Lanczos Modification, Less Ringing Artifacts"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:402
|
||||
#: src/options/options.js:406
|
||||
msgid "Blue"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:403
|
||||
#: src/options/options.js:407
|
||||
msgid "Brown"
|
||||
msgstr ""
|
||||
|
||||
|
@ -382,7 +388,7 @@ msgstr ""
|
|||
msgid "Browse indexed files and folders in Library."
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:413
|
||||
#: src/options/options.js:417
|
||||
msgid "Bug Report"
|
||||
msgstr ""
|
||||
|
||||
|
@ -392,8 +398,8 @@ msgstr ""
|
|||
|
||||
#: src/app/routes.js:142
|
||||
#: src/app/routes.js:149
|
||||
#: src/component/navigation.vue:242
|
||||
#: src/component/navigation.vue:934
|
||||
#: src/component/navigation.vue:250
|
||||
#: src/component/navigation.vue:963
|
||||
msgid "Calendar"
|
||||
msgstr ""
|
||||
|
||||
|
@ -456,7 +462,7 @@ msgstr ""
|
|||
msgid "Cards"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/photo/toolbar.vue:351
|
||||
#: src/component/photo/toolbar.vue:352
|
||||
#: src/dialog/album/edit.vue:162
|
||||
#: src/pages/about/feedback.vue:108
|
||||
#: src/pages/albums.vue:130
|
||||
|
@ -479,8 +485,8 @@ msgstr ""
|
|||
msgid "Checked"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:157
|
||||
#: src/dialog/photo/files.vue:154
|
||||
#: src/dialog/photo/files.vue:169
|
||||
#: src/dialog/photo/files.vue:166
|
||||
msgid "Chroma"
|
||||
msgstr ""
|
||||
|
||||
|
@ -496,12 +502,12 @@ msgstr ""
|
|||
msgid "Codec"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/photo/toolbar.vue:327
|
||||
#: src/component/photo/toolbar.vue:328
|
||||
msgid "Color"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:145
|
||||
#: src/dialog/photo/files.vue:142
|
||||
#: src/dialog/photo/files.vue:157
|
||||
#: src/dialog/photo/files.vue:154
|
||||
msgid "Color Profile"
|
||||
msgstr ""
|
||||
|
||||
|
@ -581,7 +587,7 @@ msgstr ""
|
|||
msgid "Creating thumbnails for"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:421
|
||||
#: src/options/options.js:425
|
||||
msgid "Cubic: Moderate Quality, Good Performance"
|
||||
msgstr ""
|
||||
|
||||
|
@ -589,11 +595,11 @@ msgstr ""
|
|||
msgid "Current Password"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:410
|
||||
#: src/options/options.js:414
|
||||
msgid "Customer Support"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:401
|
||||
#: src/options/options.js:405
|
||||
msgid "Cyan"
|
||||
msgstr ""
|
||||
|
||||
|
@ -601,7 +607,7 @@ msgstr ""
|
|||
msgid "Cyano"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:374
|
||||
#: src/options/options.js:378
|
||||
msgid "Daily"
|
||||
msgstr ""
|
||||
|
||||
|
@ -614,7 +620,7 @@ msgid "Debug Logs"
|
|||
msgstr ""
|
||||
|
||||
#: src/options/options.js:194
|
||||
#: src/options/options.js:325
|
||||
#: src/options/options.js:329
|
||||
msgid "Default"
|
||||
msgstr ""
|
||||
|
||||
|
@ -632,7 +638,7 @@ msgstr ""
|
|||
#: src/dialog/photo/delete.vue:18
|
||||
#: src/dialog/photo/files.vue:41
|
||||
#: src/dialog/photo/files.vue:38
|
||||
#: src/dialog/share.vue:234
|
||||
#: src/dialog/share.vue:235
|
||||
#: src/pages/library/errors.vue:94
|
||||
#: src/pages/settings/general.vue:206
|
||||
msgid "Delete"
|
||||
|
@ -741,7 +747,7 @@ msgstr ""
|
|||
msgid "Don't use TensorFlow for image classification."
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:414
|
||||
#: src/options/options.js:418
|
||||
msgid "Donations"
|
||||
msgstr ""
|
||||
|
||||
|
@ -859,7 +865,7 @@ msgstr ""
|
|||
msgid "Enables RAW converter presets. May reduce performance."
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:365
|
||||
#: src/component/navigation.vue:373
|
||||
msgid "Errors"
|
||||
msgstr ""
|
||||
|
||||
|
@ -871,7 +877,7 @@ msgstr ""
|
|||
msgid "Estimates"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:375
|
||||
#: src/options/options.js:379
|
||||
msgid "Every two days"
|
||||
msgstr ""
|
||||
|
||||
|
@ -884,7 +890,7 @@ msgstr ""
|
|||
msgid "Exclude hidden"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:279
|
||||
#: src/component/navigation.vue:280
|
||||
msgid "Expand"
|
||||
msgstr ""
|
||||
|
||||
|
@ -943,16 +949,16 @@ msgid "Favorite"
|
|||
msgstr ""
|
||||
|
||||
#: src/app/routes.js:175
|
||||
#: src/component/navigation.vue:216
|
||||
#: src/component/navigation.vue:846
|
||||
#: src/component/navigation.vue:224
|
||||
#: src/component/navigation.vue:875
|
||||
msgid "Favorites"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:412
|
||||
#: src/options/options.js:416
|
||||
msgid "Feature Request"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:406
|
||||
#: src/component/navigation.vue:414
|
||||
#: src/component/navigation.vue:35
|
||||
msgid "Feedback"
|
||||
msgstr ""
|
||||
|
@ -961,7 +967,7 @@ msgstr ""
|
|||
msgid "Feel free to contact us at hello@photoprism.app if you have any questions."
|
||||
msgstr ""
|
||||
|
||||
#: src/model/file.js:241
|
||||
#: src/model/file.js:254
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1002,8 +1008,8 @@ msgstr ""
|
|||
|
||||
#: src/app/routes.js:155
|
||||
#: src/app/routes.js:162
|
||||
#: src/component/navigation.vue:302
|
||||
#: src/component/navigation.vue:1142
|
||||
#: src/component/navigation.vue:310
|
||||
#: src/component/navigation.vue:1171
|
||||
msgid "Folders"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1011,6 +1017,16 @@ msgstr ""
|
|||
msgid "Forgot password?"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:107
|
||||
#: src/dialog/photo/files.vue:104
|
||||
msgid "FPS"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:101
|
||||
#: src/dialog/photo/files.vue:98
|
||||
msgid "Frames"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/photo-viewer.vue:174
|
||||
msgid "Fullscreen"
|
||||
msgstr ""
|
||||
|
@ -1027,7 +1043,7 @@ msgstr ""
|
|||
msgid "Getting Support"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:396
|
||||
#: src/options/options.js:400
|
||||
msgid "Gold"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1035,11 +1051,11 @@ msgstr ""
|
|||
msgid "Grayscale"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:399
|
||||
#: src/options/options.js:403
|
||||
msgid "Green"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:405
|
||||
#: src/options/options.js:409
|
||||
msgid "Grey"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1058,7 +1074,7 @@ msgstr ""
|
|||
msgid "Help"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:356
|
||||
#: src/component/navigation.vue:364
|
||||
msgid "Hidden"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1075,12 +1091,12 @@ msgstr ""
|
|||
msgid "Hide photos that have been moved to archive."
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:329
|
||||
#: src/options/options.js:333
|
||||
msgid "High"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:109
|
||||
#: src/dialog/photo/files.vue:106
|
||||
#: src/dialog/photo/files.vue:121
|
||||
#: src/dialog/photo/files.vue:118
|
||||
msgid "High Dynamic Range (HDR)"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1138,10 +1154,10 @@ msgstr ""
|
|||
msgid "Importing files to originals…"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:174
|
||||
#: src/dialog/photo/files.vue:186
|
||||
#: src/dialog/photo/files.vue:195
|
||||
#: src/dialog/photo/files.vue:183
|
||||
#: src/dialog/photo/files.vue:171
|
||||
#: src/dialog/photo/files.vue:180
|
||||
#: src/dialog/photo/files.vue:192
|
||||
msgid "in"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1218,8 +1234,8 @@ msgid "Label"
|
|||
msgstr ""
|
||||
|
||||
#: src/app/routes.js:261
|
||||
#: src/component/navigation.vue:289
|
||||
#: src/component/navigation.vue:1097
|
||||
#: src/component/navigation.vue:297
|
||||
#: src/component/navigation.vue:1126
|
||||
#: src/dialog/photo/edit.vue:39
|
||||
#: src/dialog/photo/edit.vue:6
|
||||
#: src/dialog/photo/edit.vue:215
|
||||
|
@ -1231,7 +1247,7 @@ msgstr ""
|
|||
msgid "Labels deleted"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:420
|
||||
#: src/options/options.js:424
|
||||
msgid "Lanczos: Detail Preservation, Minimal Artifacts"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1259,16 +1275,16 @@ msgstr ""
|
|||
#: src/app/routes.js:293
|
||||
#: src/app/routes.js:300
|
||||
#: src/app/routes.js:307
|
||||
#: src/component/navigation.vue:328
|
||||
#: src/component/navigation.vue:338
|
||||
#: src/component/navigation.vue:336
|
||||
#: src/component/navigation.vue:346
|
||||
#: src/component/navigation.vue:4
|
||||
#: src/component/navigation.vue:1234
|
||||
#: src/component/navigation.vue:1263
|
||||
#: src/pages/settings.vue:41
|
||||
#: src/pages/settings/general.vue:404
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:414
|
||||
#: src/component/navigation.vue:422
|
||||
#: src/component/navigation.vue:43
|
||||
#: src/dialog/photo/details.vue:544
|
||||
#: src/pages/about/license.vue:4
|
||||
|
@ -1279,7 +1295,7 @@ msgstr ""
|
|||
msgid "Like"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:398
|
||||
#: src/options/options.js:402
|
||||
msgid "Lime"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1287,7 +1303,7 @@ msgstr ""
|
|||
msgid "Limit reached, showing first %{n} files"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:422
|
||||
#: src/options/options.js:426
|
||||
msgid "Linear: Very Smooth, Best Performance"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1301,11 +1317,11 @@ msgid "List"
|
|||
msgstr ""
|
||||
|
||||
#: src/app/routes.js:182
|
||||
#: src/component/navigation.vue:189
|
||||
#: src/component/navigation.vue:197
|
||||
#: src/component/photo/cards.vue:215
|
||||
#: src/component/photo/list.vue:186
|
||||
#: src/component/photo/mosaic.vue:190
|
||||
#: src/options/options.js:314
|
||||
#: src/options/options.js:318
|
||||
#: src/share/photo/cards.vue:188
|
||||
#: src/share/photo/list.vue:165
|
||||
#: src/share/photo/mosaic.vue:171
|
||||
|
@ -1334,14 +1350,14 @@ msgstr ""
|
|||
msgid "Log messages appear here whenever PhotoPrism comes across broken files, or there are other potential issues."
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:428
|
||||
#: src/component/navigation.vue:1570
|
||||
#: src/component/navigation.vue:436
|
||||
#: src/component/navigation.vue:1599
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:475
|
||||
#: src/component/navigation.vue:1680
|
||||
#: src/component/navigation.vue:1711
|
||||
#: src/component/navigation.vue:483
|
||||
#: src/component/navigation.vue:1709
|
||||
#: src/component/navigation.vue:1740
|
||||
msgid "Logout"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1355,16 +1371,16 @@ msgstr ""
|
|||
msgid "Longitude"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:333
|
||||
#: src/options/options.js:337
|
||||
msgid "Low"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:392
|
||||
#: src/options/options.js:396
|
||||
msgid "Magenta"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:151
|
||||
#: src/dialog/photo/files.vue:148
|
||||
#: src/dialog/photo/files.vue:163
|
||||
#: src/dialog/photo/files.vue:160
|
||||
msgid "Main Color"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1392,19 +1408,19 @@ msgstr ""
|
|||
msgid "Message sent"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:232
|
||||
#: src/component/navigation.vue:233
|
||||
msgid "Minimize"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:163
|
||||
#: src/dialog/photo/files.vue:160
|
||||
#: src/dialog/photo/files.vue:175
|
||||
#: src/dialog/photo/files.vue:172
|
||||
msgid "Missing"
|
||||
msgstr ""
|
||||
|
||||
#: src/app/routes.js:116
|
||||
#: src/app/routes.js:123
|
||||
#: src/component/navigation.vue:229
|
||||
#: src/component/navigation.vue:889
|
||||
#: src/component/navigation.vue:237
|
||||
#: src/component/navigation.vue:918
|
||||
#: src/pages/settings/general.vue:360
|
||||
msgid "Moments"
|
||||
msgstr ""
|
||||
|
@ -1496,8 +1512,8 @@ msgstr ""
|
|||
msgid "Name too long"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:370
|
||||
#: src/options/options.js:380
|
||||
#: src/options/options.js:374
|
||||
#: src/options/options.js:384
|
||||
#: src/pages/settings/sync.vue:50
|
||||
msgid "Never"
|
||||
msgstr ""
|
||||
|
@ -1604,7 +1620,7 @@ msgid "Non-photographic and low-quality images require a review before they appe
|
|||
msgstr ""
|
||||
|
||||
#: src/options/options.js:261
|
||||
#: src/options/options.js:337
|
||||
#: src/options/options.js:341
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1636,8 +1652,8 @@ msgstr ""
|
|||
msgid "Nothing to see here yet. Be patient."
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:444
|
||||
#: src/component/navigation.vue:1615
|
||||
#: src/component/navigation.vue:452
|
||||
#: src/component/navigation.vue:1644
|
||||
#: src/options/options.js:280
|
||||
msgid "Offline"
|
||||
msgstr ""
|
||||
|
@ -1648,7 +1664,7 @@ msgstr ""
|
|||
msgid "Oldest first"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:376
|
||||
#: src/options/options.js:380
|
||||
msgid "Once a week"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1697,12 +1713,12 @@ msgstr ""
|
|||
msgid "or ask in our Community Chat"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:395
|
||||
#: src/options/options.js:399
|
||||
msgid "Orange"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:137
|
||||
#: src/dialog/photo/files.vue:134
|
||||
#: src/dialog/photo/files.vue:149
|
||||
#: src/dialog/photo/files.vue:146
|
||||
msgid "Orientation"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1716,14 +1732,14 @@ msgstr ""
|
|||
msgid "Original Name"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:347
|
||||
#: src/component/navigation.vue:355
|
||||
#: src/dialog/account/edit.vue:104
|
||||
#: src/pages/library/files.vue:6
|
||||
#: src/pages/settings/general.vue:316
|
||||
msgid "Originals"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:415
|
||||
#: src/options/options.js:419
|
||||
msgid "Other"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1757,8 +1773,8 @@ msgstr ""
|
|||
|
||||
#: src/app/routes.js:267
|
||||
#: src/app/routes.js:287
|
||||
#: src/component/navigation.vue:203
|
||||
#: src/component/navigation.vue:801
|
||||
#: src/component/navigation.vue:211
|
||||
#: src/component/navigation.vue:830
|
||||
#: src/dialog/photo/edit.vue:52
|
||||
#: src/dialog/photo/edit.vue:6
|
||||
#: src/dialog/photo/edit.vue:266
|
||||
|
@ -1778,7 +1794,7 @@ msgstr ""
|
|||
msgid "Permanently remove files to free up storage."
|
||||
msgstr ""
|
||||
|
||||
#: src/model/photo.js:925
|
||||
#: src/model/photo.js:958
|
||||
msgid "Photo"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1794,7 +1810,7 @@ msgstr ""
|
|||
msgid "Photos"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:393
|
||||
#: src/options/options.js:397
|
||||
msgid "Pink"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1810,10 +1826,10 @@ msgstr ""
|
|||
#: src/app/routes.js:223
|
||||
#: src/app/routes.js:229
|
||||
#: src/app/routes.js:236
|
||||
#: src/component/navigation.vue:255
|
||||
#: src/component/navigation.vue:265
|
||||
#: src/component/navigation.vue:263
|
||||
#: src/component/navigation.vue:273
|
||||
#: src/component/navigation.vue:4
|
||||
#: src/component/navigation.vue:979
|
||||
#: src/component/navigation.vue:1008
|
||||
#: src/pages/settings/general.vue:108
|
||||
#: src/pages/settings/general.vue:450
|
||||
msgid "Places"
|
||||
|
@ -1834,8 +1850,8 @@ msgstr ""
|
|||
msgid "Please don't upload photos containing offensive content."
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:117
|
||||
#: src/dialog/photo/files.vue:114
|
||||
#: src/dialog/photo/files.vue:129
|
||||
#: src/dialog/photo/files.vue:126
|
||||
msgid "Portrait"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1866,31 +1882,31 @@ msgid "Preview"
|
|||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:35
|
||||
#: src/dialog/photo/files.vue:101
|
||||
#: src/dialog/photo/files.vue:113
|
||||
#: src/dialog/photo/files.vue:32
|
||||
#: src/dialog/photo/files.vue:98
|
||||
#: src/dialog/photo/files.vue:110
|
||||
#: src/dialog/photo/files.vue:28
|
||||
msgid "Primary"
|
||||
msgstr ""
|
||||
|
||||
#: src/app/routes.js:203
|
||||
#: src/component/navigation.vue:315
|
||||
#: src/component/navigation.vue:1187
|
||||
#: src/component/navigation.vue:323
|
||||
#: src/component/navigation.vue:1216
|
||||
#: src/dialog/photo/info.vue:102
|
||||
#: src/pages/settings/general.vue:272
|
||||
msgid "Private"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:411
|
||||
#: src/options/options.js:415
|
||||
msgid "Product Feedback"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:125
|
||||
#: src/dialog/photo/files.vue:122
|
||||
#: src/dialog/photo/files.vue:137
|
||||
#: src/dialog/photo/files.vue:134
|
||||
msgid "Projection"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:391
|
||||
#: src/options/options.js:395
|
||||
msgid "Purple"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1910,7 +1926,7 @@ msgstr ""
|
|||
msgid "Raspberry"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:310
|
||||
#: src/options/options.js:314
|
||||
msgid "Raw"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1959,7 +1975,7 @@ msgstr ""
|
|||
msgid "Recognizes faces so that specific people can be found."
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:394
|
||||
#: src/options/options.js:398
|
||||
msgid "Red"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2028,7 +2044,7 @@ msgid "Retype Password"
|
|||
msgstr ""
|
||||
|
||||
#: src/app/routes.js:196
|
||||
#: src/component/navigation.vue:114
|
||||
#: src/component/navigation.vue:122
|
||||
msgid "Review"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2042,7 +2058,7 @@ msgstr ""
|
|||
msgid "Scan"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:106
|
||||
#: src/component/navigation.vue:114
|
||||
msgid "Scans"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2050,7 +2066,7 @@ msgstr ""
|
|||
#: src/component/navigation.vue:62
|
||||
#: src/component/navigation.vue:72
|
||||
#: src/component/navigation.vue:4
|
||||
#: src/component/navigation.vue:311
|
||||
#: src/component/navigation.vue:312
|
||||
#: src/component/photo/toolbar.vue:50
|
||||
#: src/pages/albums.vue:114
|
||||
#: src/pages/labels.vue:81
|
||||
|
@ -2119,12 +2135,12 @@ msgstr ""
|
|||
#: src/app/routes.js:339
|
||||
#: src/app/routes.js:351
|
||||
#: src/app/routes.js:363
|
||||
#: src/component/navigation.vue:379
|
||||
#: src/component/navigation.vue:389
|
||||
#: src/component/navigation.vue:387
|
||||
#: src/component/navigation.vue:397
|
||||
#: src/component/navigation.vue:8
|
||||
#: src/component/navigation.vue:18
|
||||
#: src/component/navigation.vue:4
|
||||
#: src/component/navigation.vue:1408
|
||||
#: src/component/navigation.vue:1437
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2191,7 +2207,7 @@ msgstr ""
|
|||
msgid "Shows more detailed log messages. Requires a restart."
|
||||
msgstr ""
|
||||
|
||||
#: src/model/file.js:182
|
||||
#: src/model/file.js:195
|
||||
msgid "Sidecar"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2256,7 +2272,7 @@ msgstr ""
|
|||
msgid "Stackable"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:98
|
||||
#: src/component/navigation.vue:106
|
||||
#: src/pages/settings/library.vue:34
|
||||
msgid "Stacks"
|
||||
msgstr ""
|
||||
|
@ -2273,7 +2289,7 @@ msgstr ""
|
|||
msgid "Start/Stop Slideshow"
|
||||
msgstr ""
|
||||
|
||||
#: src/component/navigation.vue:275
|
||||
#: src/component/navigation.vue:283
|
||||
msgid "States"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2324,7 +2340,7 @@ msgstr ""
|
|||
msgid "Taken"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:400
|
||||
#: src/options/options.js:404
|
||||
msgid "Teal"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2451,12 +2467,12 @@ msgstr ""
|
|||
#: src/dialog/photo/details.vue:16
|
||||
#: src/dialog/photo/info.vue:24
|
||||
#: src/model/album.js:179
|
||||
#: src/model/photo.js:585
|
||||
#: src/model/photo.js:602
|
||||
#: src/model/photo.js:625
|
||||
#: src/model/photo.js:639
|
||||
#: src/model/photo.js:724
|
||||
#: src/model/photo.js:737
|
||||
#: src/model/photo.js:611
|
||||
#: src/model/photo.js:628
|
||||
#: src/model/photo.js:651
|
||||
#: src/model/photo.js:665
|
||||
#: src/model/photo.js:750
|
||||
#: src/model/photo.js:763
|
||||
#: src/options/options.js:20
|
||||
#: src/options/options.js:34
|
||||
#: src/options/options.js:51
|
||||
|
@ -2469,7 +2485,7 @@ msgid "Unknown"
|
|||
msgstr ""
|
||||
|
||||
#: src/app/routes.js:168
|
||||
#: src/component/navigation.vue:156
|
||||
#: src/component/navigation.vue:164
|
||||
msgid "Unsorted"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2478,8 +2494,8 @@ msgstr ""
|
|||
msgid "Unstack"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialog/photo/files.vue:180
|
||||
#: src/dialog/photo/files.vue:177
|
||||
#: src/dialog/photo/files.vue:192
|
||||
#: src/dialog/photo/files.vue:189
|
||||
#: src/dialog/photo/info.vue:175
|
||||
msgid "Updated"
|
||||
msgstr ""
|
||||
|
@ -2505,7 +2521,7 @@ msgid "Updating stacks"
|
|||
msgstr ""
|
||||
|
||||
#: src/component/album/toolbar.vue:176
|
||||
#: src/component/navigation.vue:132
|
||||
#: src/component/navigation.vue:133
|
||||
#: src/component/photo/toolbar.vue:128
|
||||
#: src/dialog/share/upload.vue:35
|
||||
#: src/dialog/upload.vue:8
|
||||
|
@ -2581,10 +2597,10 @@ msgstr ""
|
|||
#: src/component/photo/cards.vue:225
|
||||
#: src/component/photo/list.vue:196
|
||||
#: src/component/photo/mosaic.vue:200
|
||||
#: src/model/file.js:180
|
||||
#: src/model/photo.js:676
|
||||
#: src/model/photo.js:690
|
||||
#: src/options/options.js:318
|
||||
#: src/model/file.js:193
|
||||
#: src/model/photo.js:702
|
||||
#: src/model/photo.js:716
|
||||
#: src/options/options.js:322
|
||||
#: src/share/photo/cards.vue:38
|
||||
#: src/share/photo/cards.vue:198
|
||||
#: src/share/photo/list.vue:175
|
||||
|
@ -2593,10 +2609,10 @@ msgid "Video"
|
|||
msgstr ""
|
||||
|
||||
#: src/app/routes.js:189
|
||||
#: src/component/navigation.vue:169
|
||||
#: src/component/navigation.vue:179
|
||||
#: src/component/navigation.vue:177
|
||||
#: src/component/navigation.vue:187
|
||||
#: src/component/navigation.vue:4
|
||||
#: src/component/navigation.vue:685
|
||||
#: src/component/navigation.vue:714
|
||||
msgid "Videos"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2629,7 +2645,7 @@ msgstr ""
|
|||
msgid "WebDAV Upload"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:404
|
||||
#: src/options/options.js:408
|
||||
msgid "White"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2638,7 +2654,7 @@ msgstr ""
|
|||
msgid "Year"
|
||||
msgstr ""
|
||||
|
||||
#: src/options/options.js:397
|
||||
#: src/options/options.js:401
|
||||
msgid "Yellow"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2649,14 +2665,14 @@ msgstr ""
|
|||
#: src/dialog/confirm.vue:18
|
||||
#: src/dialog/people/merge.vue:18
|
||||
#: src/dialog/photo/archive.vue:18
|
||||
#: src/dialog/photo/files.vue:104
|
||||
#: src/dialog/photo/files.vue:112
|
||||
#: src/dialog/photo/files.vue:120
|
||||
#: src/dialog/photo/files.vue:166
|
||||
#: src/dialog/photo/files.vue:101
|
||||
#: src/dialog/photo/files.vue:109
|
||||
#: src/dialog/photo/files.vue:117
|
||||
#: src/dialog/photo/files.vue:163
|
||||
#: src/dialog/photo/files.vue:116
|
||||
#: src/dialog/photo/files.vue:124
|
||||
#: src/dialog/photo/files.vue:132
|
||||
#: src/dialog/photo/files.vue:178
|
||||
#: src/dialog/photo/files.vue:113
|
||||
#: src/dialog/photo/files.vue:121
|
||||
#: src/dialog/photo/files.vue:129
|
||||
#: src/dialog/photo/files.vue:175
|
||||
#: src/dialog/photo/info.vue:287
|
||||
#: src/dialog/photo/info.vue:308
|
||||
#: src/dialog/photo/info.vue:328
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
@ -30,6 +30,7 @@ import Util from "common/util";
|
|||
import { config } from "app/session";
|
||||
import { $gettext } from "common/vm";
|
||||
import download from "common/download";
|
||||
import { MediaAnimated } from "./photo";
|
||||
|
||||
export class File extends RestModel {
|
||||
getDefaults() {
|
||||
|
@ -44,7 +45,8 @@ export class File extends RestModel {
|
|||
Size: 0,
|
||||
ModTime: 0,
|
||||
Codec: "",
|
||||
Type: "",
|
||||
FileType: "",
|
||||
MediaType: "",
|
||||
Mime: "",
|
||||
Primary: false,
|
||||
Sidecar: false,
|
||||
|
@ -52,19 +54,22 @@ export class File extends RestModel {
|
|||
Portrait: false,
|
||||
Video: false,
|
||||
Duration: 0,
|
||||
FPS: 0.0,
|
||||
Frames: 0,
|
||||
Width: 0,
|
||||
Height: 0,
|
||||
Orientation: 0,
|
||||
Projection: "",
|
||||
AspectRatio: 1.0,
|
||||
HDR: false,
|
||||
Watermark: false,
|
||||
ColorProfile: "",
|
||||
MainColor: "",
|
||||
Colors: "",
|
||||
Luminance: "",
|
||||
Diff: 0,
|
||||
Chroma: 0,
|
||||
Notes: "",
|
||||
Software: "",
|
||||
Error: "",
|
||||
Markers: [],
|
||||
CreatedAt: "",
|
||||
|
@ -112,7 +117,7 @@ export class File extends RestModel {
|
|||
thumbnailUrl(size) {
|
||||
if (this.Error || this.Missing) {
|
||||
return `${config.contentUri}/svg/broken`;
|
||||
} else if (this.Type === "raw") {
|
||||
} else if (this.FileType === "raw") {
|
||||
return `${config.contentUri}/svg/raw`;
|
||||
} else if (this.Sidecar) {
|
||||
return `${config.contentUri}/svg/file`;
|
||||
|
@ -162,27 +167,35 @@ export class File extends RestModel {
|
|||
getInfo() {
|
||||
let info = [];
|
||||
|
||||
if (this.Type) {
|
||||
info.push(this.Type.toUpperCase());
|
||||
if (this.FileType) {
|
||||
info.push(this.FileType.toUpperCase());
|
||||
}
|
||||
|
||||
if (this.Duration > 0) {
|
||||
info.push(Util.duration(this.Duration));
|
||||
}
|
||||
|
||||
if (this.FPS > 0) {
|
||||
info.push(Util.fps(this.FPS));
|
||||
}
|
||||
|
||||
this.addSizeInfo(info);
|
||||
|
||||
return info.join(", ");
|
||||
}
|
||||
|
||||
typeInfo() {
|
||||
if (this.Type === MediaAnimated) {
|
||||
return $gettext("Animation");
|
||||
}
|
||||
|
||||
if (this.Video) {
|
||||
return $gettext("Video");
|
||||
} else if (this.Sidecar) {
|
||||
return $gettext("Sidecar");
|
||||
}
|
||||
|
||||
return this.Type.toUpperCase();
|
||||
return this.FileType.toUpperCase();
|
||||
}
|
||||
|
||||
sizeInfo() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
@ -39,11 +39,13 @@ import * as src from "common/src";
|
|||
export const CodecAvc1 = "avc1";
|
||||
export const FormatMp4 = "mp4";
|
||||
export const FormatAvc = "avc";
|
||||
export const FormatGif = "gif";
|
||||
export const FormatJpeg = "jpg";
|
||||
export const TypeImage = "image";
|
||||
export const TypeVideo = "video";
|
||||
export const TypeLive = "live";
|
||||
export const TypeRaw = "raw";
|
||||
export const MediaImage = "image";
|
||||
export const MediaAnimated = "animated";
|
||||
export const MediaVideo = "video";
|
||||
export const MediaLive = "live";
|
||||
export const MediaRaw = "raw";
|
||||
export const YearUnknown = -1;
|
||||
export const MonthUnknown = -1;
|
||||
export const DayUnknown = -1;
|
||||
|
@ -84,7 +86,7 @@ export class Photo extends RestModel {
|
|||
ID: "",
|
||||
UID: "",
|
||||
DocumentID: "",
|
||||
Type: TypeImage,
|
||||
Type: MediaImage,
|
||||
TypeSrc: "",
|
||||
Stack: 0,
|
||||
Favorite: false,
|
||||
|
@ -138,6 +140,8 @@ export class Photo extends RestModel {
|
|||
CopyrightSrc: "",
|
||||
License: "",
|
||||
LicenseSrc: "",
|
||||
Software: "",
|
||||
SoftwareSrc: "",
|
||||
},
|
||||
Files: [],
|
||||
Labels: [],
|
||||
|
@ -157,6 +161,10 @@ export class Photo extends RestModel {
|
|||
FileUID: "",
|
||||
FileRoot: "",
|
||||
FileName: "",
|
||||
FileType: "",
|
||||
MediaType: "",
|
||||
FPS: 0.0,
|
||||
Frames: 0,
|
||||
Hash: "",
|
||||
Width: "",
|
||||
Height: "",
|
||||
|
@ -343,7 +351,9 @@ export class Photo extends RestModel {
|
|||
}
|
||||
|
||||
isPlayable() {
|
||||
if (!this.Files) {
|
||||
if (this.Type === MediaAnimated) {
|
||||
return true;
|
||||
} else if (!this.Files) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -360,6 +370,10 @@ export class Photo extends RestModel {
|
|||
let main = this.mainFile();
|
||||
let file = this.videoFile();
|
||||
|
||||
if (!file) {
|
||||
file = main;
|
||||
}
|
||||
|
||||
const vw = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
|
||||
const vh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
|
||||
|
||||
|
@ -393,7 +407,7 @@ export class Photo extends RestModel {
|
|||
height = newHeight;
|
||||
}
|
||||
|
||||
const loop = file.Duration >= 0 && file.Duration <= 5000000000;
|
||||
const loop = this.Type === MediaAnimated || (file.Duration >= 0 && file.Duration <= 5000000000);
|
||||
const poster = this.thumbnailUrl("fit_720");
|
||||
const error = false;
|
||||
|
||||
|
@ -408,18 +422,30 @@ export class Photo extends RestModel {
|
|||
let file = this.Files.find((f) => f.Codec === CodecAvc1);
|
||||
|
||||
if (!file) {
|
||||
file = this.Files.find((f) => f.Type === FormatMp4);
|
||||
file = this.Files.find((f) => f.FileType === FormatMp4);
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
file = this.Files.find((f) => !!f.Video);
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
file = this.gifFile();
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
gifFile() {
|
||||
if (!this.Files) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.Files.find((f) => f.FileType === FormatGif);
|
||||
}
|
||||
|
||||
videoUrl() {
|
||||
const file = this.videoFile();
|
||||
let file = this.videoFile();
|
||||
|
||||
if (file) {
|
||||
return `${config.apiUri}/videos/${file.Hash}/${config.previewToken()}/${FormatAvc}`;
|
||||
|
@ -439,7 +465,7 @@ export class Photo extends RestModel {
|
|||
return file;
|
||||
}
|
||||
|
||||
return this.Files.find((f) => f.Type === FormatJpeg);
|
||||
return this.Files.find((f) => f.FileType === FormatJpeg);
|
||||
}
|
||||
|
||||
jpegFiles() {
|
||||
|
@ -447,7 +473,7 @@ export class Photo extends RestModel {
|
|||
return [this];
|
||||
}
|
||||
|
||||
return this.Files.filter((f) => f.Type === FormatJpeg);
|
||||
return this.Files.filter((f) => f.FileType === FormatJpeg);
|
||||
}
|
||||
|
||||
mainFileHash() {
|
||||
|
@ -542,14 +568,14 @@ export class Photo extends RestModel {
|
|||
}
|
||||
|
||||
// Skip RAW images.
|
||||
if (!settings.download.raw && file.Type === TypeRaw) {
|
||||
if (!settings.download.raw && file.FileType === MediaRaw) {
|
||||
if (config.debug) console.log("download: skipped raw", file);
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip related images if video.
|
||||
// see https://github.com/photoprism/photoprism/issues/1436
|
||||
if (this.Type === TypeVideo && !file.Video) {
|
||||
if (this.Type === MediaVideo && !file.Video) {
|
||||
if (config.debug) console.log("download: skipped image", file);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
@ -193,7 +193,7 @@ export class Thumb extends Model {
|
|||
for (let j = 0; j < p.Files.length; j++) {
|
||||
let f = p.Files[j];
|
||||
|
||||
if (!f || f.Type !== "jpg") {
|
||||
if (!f || f.FileType !== "jpg") {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -2,7 +2,7 @@ import { timeZonesNames } from "@vvo/tzdb";
|
|||
import { $gettext } from "common/vm";
|
||||
import { Info } from "luxon";
|
||||
import { config } from "app/session";
|
||||
import { TypeImage, TypeLive, TypeRaw, TypeVideo } from "model/photo";
|
||||
import { MediaAnimated, MediaImage, MediaLive, MediaRaw, MediaVideo } from "model/photo";
|
||||
|
||||
export const TimeZones = () =>
|
||||
[
|
||||
|
@ -304,19 +304,23 @@ export const MapsStyle = () => [
|
|||
export const PhotoTypes = () => [
|
||||
{
|
||||
text: $gettext("Image"),
|
||||
value: TypeImage,
|
||||
value: MediaImage,
|
||||
},
|
||||
{
|
||||
text: $gettext("Animated"),
|
||||
value: MediaAnimated,
|
||||
},
|
||||
{
|
||||
text: $gettext("Raw"),
|
||||
value: TypeRaw,
|
||||
value: MediaRaw,
|
||||
},
|
||||
{
|
||||
text: $gettext("Live"),
|
||||
value: TypeLive,
|
||||
value: MediaLive,
|
||||
},
|
||||
{
|
||||
text: $gettext("Video"),
|
||||
value: TypeVideo,
|
||||
value: MediaVideo,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -666,10 +666,10 @@
|
|||
<h4><a name="trademark"></a>18. PhotoPrism® Trademark and Brand Assets</h4>
|
||||
<p>
|
||||
(a) PhotoPrism’s Brand Assets — including trademarks, logos, icons, fonts,
|
||||
corporate design, product and service names, and any other brand features and
|
||||
elements, whether registered or unregistered („Brand Assets“) — are proprietary
|
||||
assets owned exclusively by Michael Mayer and his legal successors („PhotoPrism“).
|
||||
We reserve the right to object to any use or misuse in any jurisdiction worldwide.
|
||||
corporate design, product and service names, and any other brand features
|
||||
and elements, whether registered or unregistered („Brand Assets“) — are
|
||||
proprietary assets owned exclusively by PhotoPrism UG („PhotoPrism“). We
|
||||
reserve the right to object to any use or misuse in any jurisdiction worldwide.
|
||||
Visit <a target="_blank" href="https://photoprism.app/trademark">photoprism.app/trademark</a>
|
||||
to learn more.
|
||||
</p>
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {Photo, TypeLive, TypeRaw, TypeVideo} from "model/photo";
|
||||
import {Photo, MediaLive, MediaRaw, MediaVideo, MediaAnimated} from "model/photo";
|
||||
import Album from "model/album";
|
||||
import Thumb from "model/thumb";
|
||||
import Event from "pubsub-js";
|
||||
|
@ -79,7 +79,7 @@ export default {
|
|||
uid: uid,
|
||||
results: [],
|
||||
scrollDisabled: true,
|
||||
scrollDistance: window.innerHeight*2,
|
||||
scrollDistance: window.innerHeight * 2,
|
||||
batchSize: batchSize,
|
||||
offset: 0,
|
||||
page: 0,
|
||||
|
@ -99,7 +99,7 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
selectMode: function() {
|
||||
selectMode: function () {
|
||||
return this.selection.length > 0;
|
||||
},
|
||||
},
|
||||
|
@ -182,11 +182,11 @@ export default {
|
|||
const selected = this.results[index];
|
||||
|
||||
// Don't open as stack when user is selecting pictures, or a RAW has only one JPEG.
|
||||
if (this.selection.length > 0 || selected.Type === TypeRaw && selected.jpegFiles().length < 2) {
|
||||
if (this.selection.length > 0 || selected.Type === MediaRaw && selected.jpegFiles().length < 2) {
|
||||
showMerged = false;
|
||||
}
|
||||
|
||||
if (showMerged && selected.Type === TypeLive || selected.Type === TypeVideo) {
|
||||
if (showMerged && selected.Type === MediaLive || selected.Type === MediaVideo || selected.Type === MediaAnimated) {
|
||||
if (selected.isPlayable()) {
|
||||
this.$viewer.play({video: selected, album: this.album});
|
||||
} else {
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {Photo, TypeLive, TypeRaw, TypeVideo} from "model/photo";
|
||||
import {Photo, MediaLive, MediaRaw, MediaVideo, MediaAnimated} from "model/photo";
|
||||
import Thumb from "model/thumb";
|
||||
import Viewer from "common/viewer";
|
||||
import Event from "pubsub-js";
|
||||
|
@ -228,11 +228,11 @@ export default {
|
|||
const selected = this.results[index];
|
||||
|
||||
// Don't open as stack when user is selecting pictures, or a RAW has only one JPEG.
|
||||
if (this.selection.length > 0 || selected.Type === TypeRaw && selected.jpegFiles().length < 2) {
|
||||
if (this.selection.length > 0 || selected.Type === MediaRaw && selected.jpegFiles().length < 2) {
|
||||
showMerged = false;
|
||||
}
|
||||
|
||||
if (showMerged && selected.Type === TypeLive || selected.Type === TypeVideo) {
|
||||
if (showMerged && selected.Type === MediaLive || selected.Type === MediaVideo|| selected.Type === MediaAnimated) {
|
||||
if (selected.isPlayable()) {
|
||||
this.$viewer.play({video: selected});
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
@mouseover="playLive(photo)"
|
||||
@mouseleave="pauseLive(photo)"
|
||||
>
|
||||
<v-layout v-if="photo.Type === 'live'" class="live-player">
|
||||
<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>
|
||||
<source :src="photo.videoUrl()">
|
||||
|
@ -109,7 +109,7 @@
|
|||
{{ photo.getDateString(true) }}
|
||||
</div>
|
||||
<template v-if="!photo.Description">
|
||||
<div v-if="photo.Type === 'video'" :title="labels.video">
|
||||
<div v-if="photo.Type === 'video' || photo.Type === 'animated'" :title="labels.video">
|
||||
<v-icon size="14">movie</v-icon>
|
||||
{{ photo.getVideoInfo() }}
|
||||
</div>
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
<v-icon color="white" class="select-on">check_circle</v-icon>
|
||||
<v-icon color="white" class="select-off">radio_button_off</v-icon>
|
||||
</v-btn>
|
||||
<v-btn v-else-if="props.item.Type === 'video' || props.item.Type === 'live'"
|
||||
<v-btn v-else-if="props.item.Type === 'video' || props.item.Type === 'live' || props.item.Type === 'animated'"
|
||||
:ripple="false"
|
||||
flat icon large absolute class="input-open"
|
||||
@click.stop.prevent="openPhoto(props.index, true)">
|
||||
|
@ -186,7 +186,7 @@ export default {
|
|||
} else if (this.photos[index]) {
|
||||
let photo = this.photos[index];
|
||||
|
||||
if (photo.Type === 'video' && photo.isPlayable()) {
|
||||
if ((photo.Type === 'video' || photo.Type === 'animated') && photo.isPlayable()) {
|
||||
this.openPhoto(index, true);
|
||||
} else {
|
||||
this.openPhoto(index, false);
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
@mouseover="playLive(photo)"
|
||||
@mouseleave="pauseLive(photo)"
|
||||
>
|
||||
<v-layout v-if="photo.Type === 'live'" class="live-player">
|
||||
<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>
|
||||
<source :src="photo.videoUrl()">
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {Photo, TypeLive, TypeRaw, TypeVideo} from "model/photo";
|
||||
import {Photo, MediaLive, MediaRaw, MediaVideo, MediaAnimated} from "model/photo";
|
||||
import Album from "model/album";
|
||||
import Thumb from "model/thumb";
|
||||
import Event from "pubsub-js";
|
||||
|
@ -238,11 +238,11 @@ export default {
|
|||
const selected = this.results[index];
|
||||
|
||||
// Don't open as stack when user is selecting pictures, or a RAW has only one JPEG.
|
||||
if (this.selection.length > 0 || selected.Type === TypeRaw && selected.jpegFiles().length < 2) {
|
||||
if (this.selection.length > 0 || selected.Type === MediaRaw && selected.jpegFiles().length < 2) {
|
||||
showMerged = false;
|
||||
}
|
||||
|
||||
if (showMerged && selected.Type === TypeLive || selected.Type === TypeVideo) {
|
||||
if (showMerged && selected.Type === MediaLive || selected.Type === MediaVideo|| selected.Type === MediaAnimated) {
|
||||
if (selected.isPlayable()) {
|
||||
this.$viewer.play({video: selected, album: this.album});
|
||||
} else {
|
||||
|
|
|
@ -2,7 +2,7 @@ const clientConfig = {
|
|||
mode: "user",
|
||||
name: "PhotoPrism",
|
||||
version: "210710-bae1f2d7-Linux-x86_64-DEBUG",
|
||||
copyright: "(c) 2018-2022 Michael Mayer <hello@photoprism.app>",
|
||||
copyright: "(c) 2018-2022 PhotoPrism UG. All rights reserved.",
|
||||
flags: "public debug experimental settings",
|
||||
baseUri: "",
|
||||
staticUri: "/static",
|
||||
|
|
|
@ -56,7 +56,7 @@ Mock.onPost("api/v1/photos/pqbemz8276mhtobh/files/fqbfk181n4ca5sud/primary").rep
|
|||
UID: "fqbfk181n4ca5sud",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: true,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Hash: "1xxbgdt55",
|
||||
},
|
||||
],
|
||||
|
@ -75,7 +75,7 @@ Mock.onPut("api/v1/photos/pqbemz8276mhtobh").reply(
|
|||
UID: "fqbfk181n4ca5sud",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Hash: "1xxbgdt55",
|
||||
},
|
||||
],
|
||||
|
|
|
@ -74,7 +74,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Name: "1/2/IMG123.jpg",
|
||||
};
|
||||
const file = new File(values);
|
||||
|
@ -91,7 +91,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Name: "1/2/IMG123.jpg",
|
||||
Type: "raw",
|
||||
FileType: "raw",
|
||||
};
|
||||
const file3 = new File(values3);
|
||||
assert.equal(file3.thumbnailUrl("tile_224"), "/api/v1/svg/raw");
|
||||
|
@ -99,7 +99,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Name: "1/2/IMG123.jpg",
|
||||
Sidecar: true,
|
||||
};
|
||||
|
@ -112,7 +112,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Name: "1/2/IMG123.jpg",
|
||||
};
|
||||
const file = new File(values);
|
||||
|
@ -123,7 +123,7 @@ describe("model/file", () => {
|
|||
const values = {
|
||||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Name: "1/2/IMG123.jpg",
|
||||
};
|
||||
const file = new File(values);
|
||||
|
@ -135,7 +135,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 700,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
|
@ -147,7 +147,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 900,
|
||||
Height: 850,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
|
@ -159,7 +159,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 750,
|
||||
Height: 850,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
|
@ -174,7 +174,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Name: "1/2/IMG123.jpg",
|
||||
CreatedAt: "2012-07-08T14:45:39Z",
|
||||
UpdatedAt: "2012-07-08T14:45:39Z",
|
||||
|
@ -188,7 +188,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Duration: 8009,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
CreatedAt: "2012-07-08T14:45:39Z",
|
||||
|
@ -203,7 +203,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Duration: 8009,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
CreatedAt: "2012-07-08T14:45:39Z",
|
||||
|
@ -215,7 +215,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Duration: 8009,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
Video: true,
|
||||
|
@ -228,7 +228,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Duration: 8009,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
Sidecar: true,
|
||||
|
@ -244,7 +244,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Size: 8009,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
CreatedAt: "2012-07-08T14:45:39Z",
|
||||
|
@ -256,7 +256,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Size: 8009999987,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
CreatedAt: "2012-07-08T14:45:39Z",
|
||||
|
@ -268,7 +268,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Size: 8009999987,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
Width: 500,
|
||||
|
@ -285,7 +285,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Duration: 8009,
|
||||
Favorite: false,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
|
@ -303,7 +303,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Duration: 8009,
|
||||
Favorite: true,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
|
@ -321,7 +321,7 @@ describe("model/file", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Duration: 8009,
|
||||
Favorite: true,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
|
@ -342,7 +342,7 @@ describe("model/file", () => {
|
|||
PhotoUID: "bgad457",
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Duration: 8009,
|
||||
Favorite: true,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
|
|
|
@ -46,7 +46,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -64,7 +64,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
},
|
||||
|
@ -88,7 +88,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Video: true,
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
|
@ -98,7 +98,7 @@ describe("model/photo", () => {
|
|||
UID: "123fde",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdkkk",
|
||||
|
@ -415,7 +415,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Hash: "1xxbgdt55",
|
||||
},
|
||||
],
|
||||
|
@ -501,7 +501,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "TypeJpeg",
|
||||
FileType: "TypeJpeg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -532,7 +532,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "TypeJpeg",
|
||||
FileType: "TypeJpeg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -560,7 +560,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "TypeJpeg",
|
||||
FileType: "TypeJpeg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -583,7 +583,7 @@ describe("model/photo", () => {
|
|||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Video: true,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -603,7 +603,7 @@ describe("model/photo", () => {
|
|||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: false,
|
||||
Video: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -627,7 +627,7 @@ describe("model/photo", () => {
|
|||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Video: true,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 900,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -651,7 +651,7 @@ describe("model/photo", () => {
|
|||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Video: true,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 0,
|
||||
Height: 0,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -685,7 +685,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -707,7 +707,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -727,7 +727,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: false,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -752,7 +752,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -777,7 +777,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -785,6 +785,7 @@ describe("model/photo", () => {
|
|||
],
|
||||
};
|
||||
const photo3 = new Photo(values3);
|
||||
|
||||
assert.equal(photo3.videoUrl(), "/api/v1/videos/1xxbgdt55/public/avc");
|
||||
const values4 = {
|
||||
ID: 1,
|
||||
|
@ -796,7 +797,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: false,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -804,6 +805,7 @@ describe("model/photo", () => {
|
|||
},
|
||||
],
|
||||
};
|
||||
|
||||
const photo4 = new Photo(values4);
|
||||
assert.equal(photo4.videoUrl(), "/api/v1/videos/1xxbgdt53/public/avc");
|
||||
});
|
||||
|
@ -820,7 +822,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -829,7 +831,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: false,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt56",
|
||||
|
@ -847,7 +849,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/NotMainKitten.jpg",
|
||||
Primary: false,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -856,7 +858,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/MainKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt54",
|
||||
|
@ -883,7 +885,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: false,
|
||||
Type: FormatJpeg,
|
||||
FileType: FormatJpeg,
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -892,7 +894,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgz",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt66",
|
||||
|
@ -916,7 +918,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -925,7 +927,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: false,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt56",
|
||||
|
@ -948,7 +950,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/cat.jpg",
|
||||
Primary: false,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -957,7 +959,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1999/01/dog.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt56",
|
||||
|
@ -974,7 +976,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/cat.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -983,7 +985,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1999/01/dog.jpg",
|
||||
Primary: false,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt56",
|
||||
|
@ -1000,7 +1002,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/cat.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -1044,7 +1046,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Hash: "1xxbgdt55",
|
||||
},
|
||||
],
|
||||
|
@ -1059,7 +1061,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -1079,7 +1081,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Hash: "1xxbgdt55",
|
||||
Duration: 6000,
|
||||
Size: 10240,
|
||||
|
@ -1089,7 +1091,7 @@ describe("model/photo", () => {
|
|||
UID: "345fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Hash: "1xxbgjhu5",
|
||||
Width: 300,
|
||||
Height: 500,
|
||||
|
@ -1115,7 +1117,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Hash: "1xxbgdt55",
|
||||
},
|
||||
],
|
||||
|
@ -1137,7 +1139,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -1156,7 +1158,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -1168,7 +1170,7 @@ describe("model/photo", () => {
|
|||
UID: "123fgx",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 800,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt55",
|
||||
|
@ -1236,7 +1238,7 @@ describe("model/photo", () => {
|
|||
UID: "fqbfk181n4ca5sud",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Hash: "1xxbgdt55",
|
||||
},
|
||||
],
|
||||
|
@ -1262,7 +1264,7 @@ describe("model/photo", () => {
|
|||
UID: "fqbfk181n4ca5sud",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Hash: "1xxbgdt55",
|
||||
},
|
||||
],
|
||||
|
@ -1288,14 +1290,14 @@ describe("model/photo", () => {
|
|||
UID: "fqbfk181n4ca5sud",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Hash: "1xxbgdt55",
|
||||
},
|
||||
{
|
||||
UID: "fqbfk181n4ca5abc",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: true,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Hash: "1xxbgdt89",
|
||||
},
|
||||
],
|
||||
|
@ -1396,7 +1398,7 @@ describe("model/photo", () => {
|
|||
UID: "fqbfk181n4ca5sud",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Hash: "1xxbgdt55",
|
||||
},
|
||||
],
|
||||
|
@ -1461,7 +1463,7 @@ describe("model/photo", () => {
|
|||
UID: "fqbfk181n4ca5sud",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: false,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Hash: "1xxbgdt55",
|
||||
},
|
||||
],
|
||||
|
@ -1482,7 +1484,7 @@ describe("model/photo", () => {
|
|||
UID: "fqbfk181n4ca5sud",
|
||||
Name: "1980/01/superCuteKitten.mp4",
|
||||
Primary: true,
|
||||
Type: "mp4",
|
||||
FileType: "mp4",
|
||||
Hash: "1xxbgdt55",
|
||||
Markers: [
|
||||
{
|
||||
|
|
|
@ -133,7 +133,7 @@ describe("model/thumb", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -157,7 +157,7 @@ describe("model/thumb", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "mov",
|
||||
FileType: "mov",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -190,7 +190,7 @@ describe("model/thumb", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -238,7 +238,7 @@ describe("model/thumb", () => {
|
|||
UID: "123fgb",
|
||||
Name: "1980/01/superCuteKitten.jpg",
|
||||
Primary: true,
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 500,
|
||||
Height: 600,
|
||||
Hash: "1xxbgdt53",
|
||||
|
@ -258,7 +258,7 @@ describe("model/thumb", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Name: "1/2/IMG123.jpg",
|
||||
};
|
||||
const file = new File(values);
|
||||
|
@ -266,7 +266,7 @@ describe("model/thumb", () => {
|
|||
const values2 = {
|
||||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Name: "1/2/IMG123.jpg",
|
||||
};
|
||||
const file2 = new File(values2);
|
||||
|
@ -278,7 +278,7 @@ describe("model/thumb", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Name: "1/2/IMG123.jpg",
|
||||
};
|
||||
const file = new File(values);
|
||||
|
@ -297,7 +297,7 @@ describe("model/thumb", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 900,
|
||||
Height: 850,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
|
@ -310,7 +310,7 @@ describe("model/thumb", () => {
|
|||
InstanceID: 5,
|
||||
UID: "ABC123",
|
||||
Hash: "54ghtfd",
|
||||
Type: "jpg",
|
||||
FileType: "jpg",
|
||||
Width: 750,
|
||||
Height: 850,
|
||||
Name: "1/2/IMG123.jpg",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -15,7 +15,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Package acl contains PhotoPrism's access control lists for authorizing user actions.
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -17,7 +17,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Package api contains PhotoPrism REST API handlers.
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -17,7 +17,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/sanitize"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
|
@ -69,10 +71,10 @@ func SaveConfigOptions(router *gin.RouterGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
fileName := conf.ConfigFile()
|
||||
fileName := conf.OptionsYaml()
|
||||
|
||||
if fileName == "" {
|
||||
log.Errorf("options: empty config file name")
|
||||
log.Errorf("config: empty options.yml file path")
|
||||
AbortSaveFailed(c)
|
||||
return
|
||||
}
|
||||
|
@ -85,20 +87,20 @@ func SaveConfigOptions(router *gin.RouterGroup) {
|
|||
yamlData, err := os.ReadFile(fileName)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("options: %s", err)
|
||||
log.Errorf("config: failed loading values from %s (%s)", sanitize.Log(fileName), err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := yaml.Unmarshal(yamlData, v); err != nil {
|
||||
log.Errorf("options: %s", err)
|
||||
log.Warnf("config: failed parsing values in %s (%s)", sanitize.Log(fileName), err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.BindJSON(&v); err != nil {
|
||||
log.Errorf("options: %s", err)
|
||||
log.Errorf("config: %s (bind json)", err)
|
||||
AbortBadRequest(c)
|
||||
return
|
||||
}
|
||||
|
@ -106,27 +108,28 @@ func SaveConfigOptions(router *gin.RouterGroup) {
|
|||
yamlData, err := yaml.Marshal(v)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("options: %s", err)
|
||||
log.Errorf("config: %s (marshal yaml)", err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure directory exists.
|
||||
if err := os.MkdirAll(filepath.Dir(fileName), os.ModePerm); err != nil {
|
||||
log.Errorf("options: %s", err)
|
||||
log.Errorf("config: failed creating config path %s (%s)", filepath.Dir(fileName), err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Write YAML data to file.
|
||||
if err := os.WriteFile(fileName, yamlData, os.ModePerm); err != nil {
|
||||
log.Errorf("options: %s", err)
|
||||
log.Errorf("config: failed writing values to %s (%s)", sanitize.Log(fileName), err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Reload options.
|
||||
if err := conf.Options().Load(fileName); err != nil {
|
||||
log.Errorf("options: %s", err)
|
||||
log.Warnf("config: failed loading values from %s (%s)", sanitize.Log(fileName), err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ func PhotoUnstack(router *gin.RouterGroup) {
|
|||
}
|
||||
|
||||
// Reset type for existing photo stack to image.
|
||||
if err := stackPhoto.Update("PhotoType", entity.TypeImage); err != nil {
|
||||
if err := stackPhoto.Update("PhotoType", entity.MediaImage); err != nil {
|
||||
log.Errorf("photo: %s (unstack %s)", err, sanitize.Log(baseName))
|
||||
AbortUnexpected(c)
|
||||
return
|
||||
|
|
|
@ -44,7 +44,7 @@ func TestGetFoldersOriginals(t *testing.T) {
|
|||
|
||||
for _, folder := range folders {
|
||||
assert.Equal(t, "", folder.FolderDescription)
|
||||
assert.Equal(t, entity.TypeDefault, folder.FolderType)
|
||||
assert.Equal(t, entity.MediaUnknown, folder.FolderType)
|
||||
assert.Equal(t, entity.SortOrderName, folder.FolderOrder)
|
||||
assert.Equal(t, entity.RootOriginals, folder.Root)
|
||||
assert.IsType(t, "", folder.FolderUID)
|
||||
|
@ -81,7 +81,7 @@ func TestGetFoldersOriginals(t *testing.T) {
|
|||
|
||||
for _, folder := range folders {
|
||||
assert.Equal(t, "", folder.FolderDescription)
|
||||
assert.Equal(t, entity.TypeDefault, folder.FolderType)
|
||||
assert.Equal(t, entity.MediaUnknown, folder.FolderType)
|
||||
assert.Equal(t, entity.SortOrderName, folder.FolderOrder)
|
||||
assert.Equal(t, entity.RootOriginals, folder.Root)
|
||||
assert.IsType(t, "", folder.FolderUID)
|
||||
|
@ -127,7 +127,7 @@ func TestGetFoldersImport(t *testing.T) {
|
|||
|
||||
for _, folder := range folders {
|
||||
assert.Equal(t, "", folder.FolderDescription)
|
||||
assert.Equal(t, entity.TypeDefault, folder.FolderType)
|
||||
assert.Equal(t, entity.MediaUnknown, folder.FolderType)
|
||||
assert.Equal(t, entity.SortOrderName, folder.FolderOrder)
|
||||
assert.Equal(t, entity.RootImport, folder.Root)
|
||||
assert.IsType(t, "", folder.FolderUID)
|
||||
|
@ -164,7 +164,7 @@ func TestGetFoldersImport(t *testing.T) {
|
|||
|
||||
for _, folder := range folders {
|
||||
assert.Equal(t, "", folder.FolderDescription)
|
||||
assert.Equal(t, entity.TypeDefault, folder.FolderType)
|
||||
assert.Equal(t, entity.MediaUnknown, folder.FolderType)
|
||||
assert.Equal(t, entity.SortOrderName, folder.FolderOrder)
|
||||
assert.Equal(t, entity.RootImport, folder.Root)
|
||||
assert.IsType(t, "", folder.FolderUID)
|
||||
|
|
|
@ -52,7 +52,7 @@ func SaveSettings(router *gin.RouterGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := settings.Save(conf.SettingsFile()); err != nil {
|
||||
if err := settings.Save(conf.SettingsYaml()); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Package auto contains index & import background workers.
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -17,7 +17,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Package classify encapsulates image classification using TensorFlow.
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -17,7 +17,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Package commands provides photoprism CLI (sub-)commands.
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -17,7 +17,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -23,12 +23,12 @@ func TestShowConfigCommand(t *testing.T) {
|
|||
}
|
||||
|
||||
// Expected config command output.
|
||||
assert.Contains(t, output, "config-file")
|
||||
assert.Contains(t, output, "darktable-cli")
|
||||
assert.Contains(t, output, "config-path")
|
||||
assert.Contains(t, output, "originals-path")
|
||||
assert.Contains(t, output, "import-path")
|
||||
assert.Contains(t, output, "cache-path")
|
||||
assert.Contains(t, output, "assets-path")
|
||||
assert.Contains(t, output, "darktable-cli")
|
||||
}
|
||||
|
||||
func TestShowFiltersCommand(t *testing.T) {
|
||||
|
|
|
@ -411,8 +411,8 @@ func (c *Config) UserConfig() ClientConfig {
|
|||
Table("photos").
|
||||
Select("SUM(photo_type = 'video' AND photo_quality >= 0 AND photo_private = 0) AS videos, " +
|
||||
"SUM(photo_type = 'live' AND photo_quality >= 0 AND photo_private = 0) AS live, " +
|
||||
"SUM(photo_quality = -1) AS hidden, SUM(photo_type IN ('image','raw') AND photo_private = 0 AND photo_quality >= 0) AS photos, " +
|
||||
"SUM(photo_type IN ('image','raw','live') AND photo_quality < 3 AND photo_quality >= 0 AND photo_private = 0) AS review, " +
|
||||
"SUM(photo_quality = -1) AS hidden, SUM(photo_type IN ('image','raw','animated') AND photo_private = 0 AND photo_quality >= 0) AS photos, " +
|
||||
"SUM(photo_type IN ('image','raw','live','animated') AND photo_quality < 3 AND photo_quality >= 0 AND photo_private = 0) AS review, " +
|
||||
"SUM(photo_favorite = 1 AND photo_private = 0 AND photo_quality >= 0) AS favorites, " +
|
||||
"SUM(photo_private = 1 AND photo_quality >= 0) AS private").
|
||||
Where("photos.id NOT IN (SELECT photo_id FROM files WHERE file_primary = 1 AND (file_missing = 1 OR file_error <> ''))").
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Package config contains CLI config related config functionality.
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -17,7 +17,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Package crop provides image crop data structures and helpers.
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -17,7 +17,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package entity
|
||||
|
||||
import "github.com/photoprism/photoprism/pkg/fs"
|
||||
|
||||
// Panorama Projection Types
|
||||
// TODO: Move to separate package.
|
||||
|
||||
|
@ -12,19 +14,19 @@ const (
|
|||
ProjPseudocylindricalCompromise = "pseudocylindrical-compromise"
|
||||
)
|
||||
|
||||
// Content Types
|
||||
|
||||
// Media Types.
|
||||
const (
|
||||
TypeDefault = ""
|
||||
TypeImage = "image"
|
||||
TypeLive = "live"
|
||||
TypeVideo = "video"
|
||||
TypeRaw = "raw"
|
||||
TypeText = "text"
|
||||
MediaUnknown = ""
|
||||
MediaImage = string(fs.MediaImage)
|
||||
MediaVector = string(fs.MediaVector)
|
||||
MediaAnimated = "animated"
|
||||
MediaLive = "live"
|
||||
MediaVideo = string(fs.MediaVideo)
|
||||
MediaRaw = string(fs.MediaRaw)
|
||||
TypeMeta = "meta"
|
||||
)
|
||||
|
||||
// Root Directories Types
|
||||
|
||||
// Root Dirs.
|
||||
const (
|
||||
RootUnknown = ""
|
||||
RootOriginals = "/"
|
||||
|
@ -34,8 +36,7 @@ const (
|
|||
RootPath = "/"
|
||||
)
|
||||
|
||||
// Unknown Values
|
||||
|
||||
// Defaults.
|
||||
const (
|
||||
UnknownYear = -1
|
||||
UnknownMonth = -1
|
||||
|
|
|
@ -25,6 +25,8 @@ type Details struct {
|
|||
CopyrightSrc string `gorm:"type:VARBINARY(8);" json:"CopyrightSrc" yaml:"CopyrightSrc,omitempty"`
|
||||
License string `gorm:"type:VARCHAR(1024);" json:"License" yaml:"License,omitempty"`
|
||||
LicenseSrc string `gorm:"type:VARBINARY(8);" json:"LicenseSrc" yaml:"LicenseSrc,omitempty"`
|
||||
Software string `gorm:"type:VARCHAR(1024);" json:"Software" yaml:"Software,omitempty"`
|
||||
SoftwareSrc string `gorm:"type:VARBINARY(8);" json:"SoftwareSrc" yaml:"SoftwareSrc,omitempty"`
|
||||
CreatedAt time.Time `yaml:"-"`
|
||||
UpdatedAt time.Time `yaml:"-"`
|
||||
}
|
||||
|
@ -109,6 +111,11 @@ func (m *Details) NoLicense() bool {
|
|||
return m.License == ""
|
||||
}
|
||||
|
||||
// NoSoftware tests if the photo has no Software.
|
||||
func (m *Details) NoSoftware() bool {
|
||||
return m.Software == ""
|
||||
}
|
||||
|
||||
// HasKeywords tests if the photo has a Keywords.
|
||||
func (m *Details) HasKeywords() bool {
|
||||
return !m.NoKeywords()
|
||||
|
@ -139,6 +146,11 @@ func (m *Details) HasLicense() bool {
|
|||
return !m.NoLicense()
|
||||
}
|
||||
|
||||
// HasSoftware tests if the photo has a Software.
|
||||
func (m *Details) HasSoftware() bool {
|
||||
return !m.NoSoftware()
|
||||
}
|
||||
|
||||
// SetKeywords updates the photo details field.
|
||||
func (m *Details) SetKeywords(data, src string) {
|
||||
val := txt.Clip(data, txt.ClipText)
|
||||
|
@ -242,3 +254,19 @@ func (m *Details) SetLicense(data, src string) {
|
|||
m.License = val
|
||||
m.LicenseSrc = src
|
||||
}
|
||||
|
||||
// SetSoftware updates the photo details field.
|
||||
func (m *Details) SetSoftware(data, src string) {
|
||||
val := txt.Clip(data, txt.ClipShortText)
|
||||
|
||||
if val == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if (SrcPriority[src] < SrcPriority[m.SoftwareSrc]) && m.HasSoftware() {
|
||||
return
|
||||
}
|
||||
|
||||
m.Software = val
|
||||
m.SoftwareSrc = src
|
||||
}
|
||||
|
|
|
@ -332,3 +332,27 @@ func TestDetails_SetLicense(t *testing.T) {
|
|||
assert.Equal(t, "new", description.License)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDetails_SetSoftware(t *testing.T) {
|
||||
t.Run("Empty", func(t *testing.T) {
|
||||
description := &Details{PhotoID: 123, Software: ""}
|
||||
assert.False(t, description.HasSoftware())
|
||||
|
||||
description.SetSoftware("", "manual")
|
||||
assert.False(t, description.HasSoftware())
|
||||
})
|
||||
t.Run("NoPriority", func(t *testing.T) {
|
||||
description := &Details{PhotoID: 123, Software: "old", SoftwareSrc: SrcManual}
|
||||
assert.Equal(t, "old", description.Software)
|
||||
|
||||
description.SetSoftware("new", SrcAuto)
|
||||
assert.Equal(t, "old", description.Software)
|
||||
})
|
||||
t.Run("NewValue", func(t *testing.T) {
|
||||
description := &Details{PhotoID: 123, Software: "old", SoftwareSrc: SrcMeta}
|
||||
assert.Equal(t, "old", description.Software)
|
||||
|
||||
description.SetSoftware("new", SrcManual)
|
||||
assert.Equal(t, "new", description.Software)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package entity
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
@ -14,7 +15,6 @@ import (
|
|||
"github.com/ulule/deepcopier"
|
||||
|
||||
"github.com/photoprism/photoprism/internal/face"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/colors"
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
"github.com/photoprism/photoprism/pkg/rnd"
|
||||
|
@ -44,6 +44,7 @@ type File struct {
|
|||
PhotoID uint `gorm:"index:idx_files_photo_id;" json:"-" yaml:"-"`
|
||||
PhotoUID string `gorm:"type:VARBINARY(42);index;" json:"PhotoUID" yaml:"PhotoUID"`
|
||||
PhotoTakenAt time.Time `gorm:"type:DATETIME;index;" json:"TakenAt" yaml:"TakenAt"`
|
||||
MetaUTC int64 `gorm:"column:meta_utc;index;" json:"MetaUTC" yaml:"MetaUTC,omitempty"`
|
||||
TimeIndex *string `gorm:"type:VARBINARY(48);" json:"TimeIndex" yaml:"TimeIndex"`
|
||||
MediaID *string `gorm:"type:VARBINARY(32);" json:"MediaID" yaml:"MediaID"`
|
||||
InstanceID string `gorm:"type:VARBINARY(42);index;" json:"InstanceID,omitempty" yaml:"InstanceID,omitempty"`
|
||||
|
@ -54,7 +55,8 @@ type File struct {
|
|||
FileHash string `gorm:"type:VARBINARY(128);index" json:"Hash" yaml:"Hash,omitempty"`
|
||||
FileSize int64 `json:"Size" yaml:"Size,omitempty"`
|
||||
FileCodec string `gorm:"type:VARBINARY(32)" json:"Codec" yaml:"Codec,omitempty"`
|
||||
FileType string `gorm:"type:VARBINARY(32)" json:"Type" yaml:"Type,omitempty"`
|
||||
FileType string `gorm:"type:VARBINARY(16)" json:"FileType" yaml:"FileType,omitempty"`
|
||||
MediaType string `gorm:"type:VARBINARY(16)" json:"MediaType" yaml:"MediaType,omitempty"`
|
||||
FileMime string `gorm:"type:VARBINARY(64)" json:"Mime" yaml:"Mime,omitempty"`
|
||||
FilePrimary bool `gorm:"index:idx_files_photo_id;" json:"Primary" yaml:"Primary,omitempty"`
|
||||
FileSidecar bool `json:"Sidecar" yaml:"Sidecar,omitempty"`
|
||||
|
@ -62,18 +64,22 @@ type File struct {
|
|||
FilePortrait bool `json:"Portrait" yaml:"Portrait,omitempty"`
|
||||
FileVideo bool `json:"Video" yaml:"Video,omitempty"`
|
||||
FileDuration time.Duration `json:"Duration" yaml:"Duration,omitempty"`
|
||||
FileFPS float64 `gorm:"column:file_fps;" json:"FPS" yaml:"FPS,omitempty"`
|
||||
FileFrames int `json:"Frames" yaml:"Frames,omitempty"`
|
||||
FileWidth int `json:"Width" yaml:"Width,omitempty"`
|
||||
FileHeight int `json:"Height" yaml:"Height,omitempty"`
|
||||
FileOrientation int `json:"Orientation" yaml:"Orientation,omitempty"`
|
||||
FileProjection string `gorm:"type:VARBINARY(64);" json:"Projection,omitempty" yaml:"Projection,omitempty"`
|
||||
FileAspectRatio float32 `gorm:"type:FLOAT;" json:"AspectRatio" yaml:"AspectRatio,omitempty"`
|
||||
FileHDR bool `gorm:"column:file_hdr;" json:"IsHDR" yaml:"IsHDR,omitempty"`
|
||||
FileHDR bool `gorm:"column:file_hdr;" json:"HDR" yaml:"HDR,omitempty"`
|
||||
FileWatermark bool `gorm:"column:file_watermark;" json:"Watermark" yaml:"Watermark,omitempty"`
|
||||
FileColorProfile string `gorm:"type:VARBINARY(64);" json:"ColorProfile,omitempty" yaml:"ColorProfile,omitempty"`
|
||||
FileMainColor string `gorm:"type:VARBINARY(16);index;" json:"MainColor" yaml:"MainColor,omitempty"`
|
||||
FileColors string `gorm:"type:VARBINARY(9);" json:"Colors" yaml:"Colors,omitempty"`
|
||||
FileLuminance string `gorm:"type:VARBINARY(9);" json:"Luminance" yaml:"Luminance,omitempty"`
|
||||
FileDiff uint32 `json:"Diff" yaml:"Diff,omitempty"`
|
||||
FileChroma uint8 `json:"Chroma" yaml:"Chroma,omitempty"`
|
||||
FileSoftware string `gorm:"type:VARCHAR(64)" json:"Software" yaml:"Software,omitempty"`
|
||||
FileError string `gorm:"type:VARBINARY(512)" json:"Error" yaml:"Error,omitempty"`
|
||||
ModTime int64 `json:"ModTime" yaml:"-"`
|
||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||
|
@ -574,6 +580,16 @@ func (m *File) ResetHDR() {
|
|||
m.FileHDR = false
|
||||
}
|
||||
|
||||
// HasWatermark returns true if the file has a watermark.
|
||||
func (m *File) HasWatermark() bool {
|
||||
return m.FileWatermark
|
||||
}
|
||||
|
||||
// IsAnimated returns true if the file has animated image frames.
|
||||
func (m *File) IsAnimated() bool {
|
||||
return m.FileFrames > 1 && m.MediaType == MediaImage
|
||||
}
|
||||
|
||||
// ColorProfile returns the ICC color profile name if any.
|
||||
func (m *File) ColorProfile() string {
|
||||
return SanitizeStringType(m.FileColorProfile)
|
||||
|
@ -596,6 +612,69 @@ func (m *File) ResetColorProfile() {
|
|||
m.FileColorProfile = ""
|
||||
}
|
||||
|
||||
// SetSoftware sets the software name.
|
||||
func (m *File) SetSoftware(name string) {
|
||||
if name = SanitizeStringType(name); name != "" {
|
||||
m.FileSoftware = name
|
||||
}
|
||||
}
|
||||
|
||||
// SetDuration sets the video/animation duration.
|
||||
func (m *File) SetDuration(d time.Duration) {
|
||||
if d <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
m.FileDuration = d.Round(time.Second)
|
||||
|
||||
// Update number of frames.
|
||||
if m.FileFrames <= 0 && m.FileFPS > 0 {
|
||||
m.FileFrames = int(math.Round(m.FileFPS * m.FileDuration.Seconds()))
|
||||
}
|
||||
|
||||
// Update number of frames per second.
|
||||
if m.FileFPS <= 0 && m.FileFrames > 0 {
|
||||
m.FileFPS = float64(m.FileFrames) / m.FileDuration.Seconds()
|
||||
}
|
||||
}
|
||||
|
||||
// SetFPS sets the average number of frames per second.
|
||||
func (m *File) SetFPS(frameRate float64) {
|
||||
if frameRate <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
m.FileFPS = frameRate
|
||||
|
||||
// Update number of frames.
|
||||
if m.FileFrames <= 0 && m.FileDuration > 0 {
|
||||
m.FileFrames = int(math.Round(m.FileFPS * m.FileDuration.Seconds()))
|
||||
}
|
||||
}
|
||||
|
||||
// SetFrames sets the number of video/animation frames.
|
||||
func (m *File) SetFrames(n int) {
|
||||
if n <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
m.FileFrames = n
|
||||
|
||||
// Update FPS.
|
||||
if m.FileFPS <= 0 && m.FileDuration > 0 {
|
||||
m.FileFPS = float64(m.FileFrames) / m.FileDuration.Seconds()
|
||||
}
|
||||
}
|
||||
|
||||
// SetMetaUTC sets the creation date found in the metadata as a unix ms timestamp.
|
||||
func (m *File) SetMetaUTC(taken time.Time) {
|
||||
if taken.IsZero() {
|
||||
return
|
||||
}
|
||||
|
||||
m.MetaUTC = taken.UTC().UnixMilli()
|
||||
}
|
||||
|
||||
// AddFaces adds face markers to the file.
|
||||
func (m *File) AddFaces(faces face.Faces) {
|
||||
sort.Slice(faces, func(i, j int) bool {
|
||||
|
|
|
@ -10,21 +10,27 @@ func (m *File) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(&struct {
|
||||
UID string
|
||||
PhotoUID string
|
||||
InstanceID string `json:",omitempty"`
|
||||
Name string
|
||||
Root string
|
||||
OriginalName string `json:",omitempty"`
|
||||
Hash string
|
||||
Size int64
|
||||
Codec string `json:",omitempty"`
|
||||
Type string
|
||||
Mime string `json:",omitempty"`
|
||||
Primary bool
|
||||
MetaUTC int64 `json:",omitempty"`
|
||||
TimeIndex *string `json:",omitempty"`
|
||||
MediaID *string `json:",omitempty"`
|
||||
InstanceID string `json:",omitempty"`
|
||||
OriginalName string `json:",omitempty"`
|
||||
Codec string `json:",omitempty"`
|
||||
FileType string `json:"FileType"`
|
||||
MediaType string `json:"MediaType"`
|
||||
Mime string `json:",omitempty"`
|
||||
Sidecar bool `json:",omitempty"`
|
||||
Missing bool `json:",omitempty"`
|
||||
Portrait bool `json:",omitempty"`
|
||||
Video bool `json:",omitempty"`
|
||||
Duration time.Duration `json:",omitempty"`
|
||||
FPS float64 `json:",omitempty"`
|
||||
Frames int `json:",omitempty"`
|
||||
Width int `json:",omitempty"`
|
||||
Height int `json:",omitempty"`
|
||||
Orientation int `json:",omitempty"`
|
||||
|
@ -37,6 +43,8 @@ func (m *File) MarshalJSON() ([]byte, error) {
|
|||
Diff uint32 `json:",omitempty"`
|
||||
Chroma uint8 `json:",omitempty"`
|
||||
HDR bool `json:",omitempty"`
|
||||
Watermark bool `json:",omitempty"`
|
||||
Software string `json:",omitempty"`
|
||||
Error string `json:",omitempty"`
|
||||
ModTime int64 `json:",omitempty"`
|
||||
CreatedAt time.Time `json:",omitempty"`
|
||||
|
@ -48,21 +56,27 @@ func (m *File) MarshalJSON() ([]byte, error) {
|
|||
}{
|
||||
UID: m.FileUID,
|
||||
PhotoUID: m.PhotoUID,
|
||||
InstanceID: m.InstanceID,
|
||||
Name: m.FileName,
|
||||
Root: m.FileRoot,
|
||||
OriginalName: m.OriginalName,
|
||||
Hash: m.FileHash,
|
||||
Size: m.FileSize,
|
||||
Codec: m.FileCodec,
|
||||
Type: m.FileType,
|
||||
Mime: m.FileMime,
|
||||
Primary: m.FilePrimary,
|
||||
MetaUTC: m.MetaUTC,
|
||||
TimeIndex: m.TimeIndex,
|
||||
MediaID: m.MediaID,
|
||||
InstanceID: m.InstanceID,
|
||||
OriginalName: m.OriginalName,
|
||||
Codec: m.FileCodec,
|
||||
FileType: m.FileType,
|
||||
MediaType: m.MediaType,
|
||||
Mime: m.FileMime,
|
||||
Sidecar: m.FileSidecar,
|
||||
Missing: m.FileMissing,
|
||||
Portrait: m.FilePortrait,
|
||||
Video: m.FileVideo,
|
||||
Duration: m.FileDuration,
|
||||
FPS: m.FileFPS,
|
||||
Frames: m.FileFrames,
|
||||
Width: m.FileWidth,
|
||||
Height: m.FileHeight,
|
||||
Orientation: m.FileOrientation,
|
||||
|
@ -75,6 +89,8 @@ func (m *File) MarshalJSON() ([]byte, error) {
|
|||
Diff: m.FileDiff,
|
||||
Chroma: m.FileChroma,
|
||||
HDR: m.FileHDR,
|
||||
Watermark: m.FileWatermark,
|
||||
Software: m.FileSoftware,
|
||||
Error: m.FileError,
|
||||
ModTime: m.ModTime,
|
||||
CreatedAt: m.CreatedAt,
|
||||
|
|
|
@ -669,3 +669,106 @@ func TestFile_SetColorProfile(t *testing.T) {
|
|||
assert.False(t, m.HasColorProfile(colors.ProfileDisplayP3))
|
||||
})
|
||||
}
|
||||
|
||||
func TestFile_SetFPS(t *testing.T) {
|
||||
t.Run("FileDuration", func(t *testing.T) {
|
||||
m := File{FileDuration: time.Second * 60}
|
||||
|
||||
assert.Equal(t, time.Minute, m.FileDuration)
|
||||
assert.Equal(t, 0.0, m.FileFPS)
|
||||
assert.Equal(t, 0, m.FileFrames)
|
||||
|
||||
m.SetFPS(10)
|
||||
|
||||
assert.Equal(t, time.Minute, m.FileDuration)
|
||||
assert.Equal(t, 10.0, m.FileFPS)
|
||||
assert.Equal(t, 600, m.FileFrames)
|
||||
|
||||
m.SetFPS(20)
|
||||
|
||||
assert.Equal(t, time.Minute, m.FileDuration)
|
||||
assert.Equal(t, 20.0, m.FileFPS)
|
||||
assert.Equal(t, 600, m.FileFrames)
|
||||
|
||||
m.FileFrames = 0
|
||||
m.SetFPS(20)
|
||||
|
||||
assert.Equal(t, time.Minute, m.FileDuration)
|
||||
assert.Equal(t, 20.0, m.FileFPS)
|
||||
assert.Equal(t, 1200, m.FileFrames)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFile_SetFrames(t *testing.T) {
|
||||
t.Run("FileDuration", func(t *testing.T) {
|
||||
m := File{FileDuration: time.Second * 60}
|
||||
|
||||
assert.Equal(t, time.Minute, m.FileDuration)
|
||||
assert.Equal(t, 0.0, m.FileFPS)
|
||||
assert.Equal(t, 0, m.FileFrames)
|
||||
|
||||
m.SetFrames(120)
|
||||
|
||||
assert.Equal(t, time.Minute, m.FileDuration)
|
||||
assert.Equal(t, 2.0, m.FileFPS)
|
||||
assert.Equal(t, 120, m.FileFrames)
|
||||
|
||||
m.SetFrames(30)
|
||||
|
||||
assert.Equal(t, time.Minute, m.FileDuration)
|
||||
assert.Equal(t, 2.0, m.FileFPS)
|
||||
assert.Equal(t, 30, m.FileFrames)
|
||||
|
||||
m.FileFPS = 0
|
||||
m.SetFrames(30)
|
||||
|
||||
assert.Equal(t, time.Minute, m.FileDuration)
|
||||
assert.Equal(t, 0.5, m.FileFPS)
|
||||
assert.Equal(t, 30, m.FileFrames)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFile_SetDuration(t *testing.T) {
|
||||
t.Run("FileFPS", func(t *testing.T) {
|
||||
m := File{FileFPS: 20}
|
||||
|
||||
assert.Equal(t, time.Duration(0), m.FileDuration)
|
||||
assert.Equal(t, 20.0, m.FileFPS)
|
||||
assert.Equal(t, 0, m.FileFrames)
|
||||
|
||||
m.SetDuration(time.Second * 10)
|
||||
|
||||
assert.Equal(t, time.Second*10, m.FileDuration)
|
||||
assert.Equal(t, 20.0, m.FileFPS)
|
||||
assert.Equal(t, 200, m.FileFrames)
|
||||
|
||||
m.SetDuration(time.Minute)
|
||||
|
||||
assert.Equal(t, time.Minute, m.FileDuration)
|
||||
assert.Equal(t, 20.0, m.FileFPS)
|
||||
assert.Equal(t, 200, m.FileFrames)
|
||||
})
|
||||
t.Run("FileFrames", func(t *testing.T) {
|
||||
m := File{FileFrames: 600}
|
||||
|
||||
assert.Equal(t, time.Duration(0), m.FileDuration)
|
||||
assert.Equal(t, 0.0, m.FileFPS)
|
||||
assert.Equal(t, 600, m.FileFrames)
|
||||
|
||||
m.SetDuration(time.Minute)
|
||||
|
||||
assert.Equal(t, time.Minute, m.FileDuration)
|
||||
assert.Equal(t, 10.0, m.FileFPS)
|
||||
assert.Equal(t, 600, m.FileFrames)
|
||||
|
||||
m.FileFPS = 0
|
||||
m.FileFrames = 0
|
||||
|
||||
m.SetDuration(time.Hour)
|
||||
m.SetFrames(216000)
|
||||
|
||||
assert.Equal(t, time.Hour, m.FileDuration)
|
||||
assert.Equal(t, 60.0, m.FileFPS)
|
||||
assert.Equal(t, 216000, m.FileFrames)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ func NewFolder(root, pathName string, modTime time.Time) Folder {
|
|||
FolderUID: rnd.PPID('d'),
|
||||
Root: root,
|
||||
Path: pathName,
|
||||
FolderType: TypeDefault,
|
||||
FolderType: MediaUnknown,
|
||||
FolderOrder: SortOrderName,
|
||||
FolderCountry: UnknownCountry.ID,
|
||||
FolderYear: year,
|
||||
|
|
|
@ -116,7 +116,7 @@ func (Photo) TableName() string {
|
|||
func NewPhoto(stackable bool) Photo {
|
||||
m := Photo{
|
||||
PhotoTitle: UnknownTitle,
|
||||
PhotoType: TypeImage,
|
||||
PhotoType: MediaImage,
|
||||
PhotoCountry: UnknownCountry.ID,
|
||||
CameraID: UnknownCamera.ID,
|
||||
LensID: UnknownLens.ID,
|
||||
|
|
|
@ -36,13 +36,13 @@ func (m *Photo) SetTakenAt(taken, local time.Time, zone, source string) {
|
|||
}
|
||||
|
||||
// Round times to avoid jitter.
|
||||
taken = taken.Round(time.Second).UTC()
|
||||
taken = taken.Truncate(time.Second).UTC()
|
||||
|
||||
// Default local time to taken if zero or invalid.
|
||||
if local.IsZero() || local.Year() < 1000 {
|
||||
local = taken
|
||||
} else {
|
||||
local = local.Round(time.Second)
|
||||
local = local.Truncate(time.Second)
|
||||
}
|
||||
|
||||
// Don't update older date.
|
||||
|
|
|
@ -18,7 +18,7 @@ func (m *Photo) EstimateCountry() {
|
|||
if SrcPriority[m.PlaceSrc] > SrcPriority[SrcEstimate] || m.HasLocation() || m.HasPlace() {
|
||||
// Keep existing data.
|
||||
return
|
||||
} else if m.UnknownCamera() && m.PhotoType == TypeImage {
|
||||
} else if m.UnknownCamera() && m.PhotoType == MediaImage {
|
||||
// Don't estimate if it seems to be a non-photographic image.
|
||||
return
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ func (m *Photo) EstimateLocation(force bool) {
|
|||
m.EstimatedAt = TimePointer()
|
||||
|
||||
// Don't estimate if it seems to be a non-photographic image.
|
||||
if m.UnknownCamera() && m.PhotoType == TypeImage {
|
||||
if m.UnknownCamera() && m.PhotoType == MediaImage {
|
||||
m.RemoveLocation(SrcEstimate, false)
|
||||
m.RemoveLocationLabels()
|
||||
return
|
||||
|
|
|
@ -61,7 +61,7 @@ func (m *Photo) QualityScore() (score int) {
|
|||
score++
|
||||
}
|
||||
|
||||
if score < 3 && (m.PhotoType != TypeImage || m.EditedAt != nil) {
|
||||
if score < 3 && (m.PhotoType != MediaImage || m.EditedAt != nil) {
|
||||
score = 3
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ const Day = time.Hour * 24
|
|||
|
||||
// TimeStamp returns the current timestamp in UTC rounded to seconds.
|
||||
func TimeStamp() time.Time {
|
||||
return time.Now().UTC().Round(time.Second)
|
||||
return time.Now().UTC().Truncate(time.Second)
|
||||
}
|
||||
|
||||
// TimePointer returns a pointer to the current timestamp.
|
||||
|
|
|
@ -6,15 +6,61 @@ import (
|
|||
)
|
||||
|
||||
func TestTimeStamp(t *testing.T) {
|
||||
result := TimeStamp()
|
||||
t.Run("UTC", func(t *testing.T) {
|
||||
if TimeStamp().Location() != time.UTC {
|
||||
t.Fatal("timestamp zone must be utc")
|
||||
}
|
||||
})
|
||||
t.Run("Past", func(t *testing.T) {
|
||||
if TimeStamp().After(time.Now().Add(time.Second)) {
|
||||
t.Fatal("timestamp should be in the past from now")
|
||||
}
|
||||
})
|
||||
t.Run("JSON", func(t *testing.T) {
|
||||
t1 := TimeStamp().Add(time.Nanosecond * 123456)
|
||||
|
||||
if result.Location() != time.UTC {
|
||||
t.Fatal("timestamp zone must be utc")
|
||||
}
|
||||
if b, err := t1.MarshalJSON(); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
t.Logf("JSON: %s", b)
|
||||
}
|
||||
})
|
||||
t.Run("UnixMicro", func(t *testing.T) {
|
||||
t1 := time.Date(-3000, 1, 1, 1, 1, 1, 0, time.UTC)
|
||||
t2 := TimeStamp().Add(time.Nanosecond * 123456)
|
||||
t3 := time.Date(3000, 1, 1, 1, 1, 1, 0, time.UTC)
|
||||
|
||||
if result.After(time.Now().Add(time.Second)) {
|
||||
t.Fatal("timestamp should be in the past from now")
|
||||
}
|
||||
ms1 := t1.UnixMilli()
|
||||
ms2 := t2.UnixMilli()
|
||||
ms3 := t3.UnixMilli()
|
||||
|
||||
m1 := t1.UnixMicro()
|
||||
m2 := t2.UnixMicro()
|
||||
m3 := t3.UnixMicro()
|
||||
|
||||
t.Logf("MS1: %20d", ms1)
|
||||
t.Logf("MS2: %20d", ms2)
|
||||
t.Logf("MS3: %20d", ms3)
|
||||
|
||||
t.Logf("U1: %20d", m1)
|
||||
t.Logf("U2: %20d", m2)
|
||||
t.Logf("U3: %20d", m3)
|
||||
|
||||
i1, i2, i3 := 1e18-m1, 1e18-m2, 1e18-m3
|
||||
|
||||
t.Logf("ZZ: %20d", 9223372036854775807)
|
||||
t.Logf("I1: %20d", i1)
|
||||
t.Logf("I2: %20d", i2)
|
||||
t.Logf("I3: %20d", i3)
|
||||
|
||||
t.Logf("T1: %20d", 1e18-i1)
|
||||
t.Logf("T2: %20d", 1e18-i2)
|
||||
t.Logf("T3: %20d", 1e18-i3)
|
||||
|
||||
t.Logf("D1: %s", time.UnixMicro(1e18-i1).String())
|
||||
t.Logf("D2: %s", time.UnixMicro(1e18-i2).String())
|
||||
t.Logf("D3: %s", time.UnixMicro(1e18-i3).String())
|
||||
})
|
||||
}
|
||||
|
||||
func TestTimePointer(t *testing.T) {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Package event provides a publish-subscribe event hub and a global logger.
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -17,7 +17,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Package face provides facial recognition.
|
||||
|
||||
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||
|
@ -17,7 +17,7 @@ Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
|||
which describe how our Brand Assets may be used:
|
||||
<https://photoprism.app/trademark>
|
||||
|
||||
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||
Feel free to send an email to hello@photoprism.app if you have questions,
|
||||
want to support our work, or just want to say hello.
|
||||
|
||||
Additional information can be found in our Developer Guide:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue