Videos: Refactor codec, content and file type specifications #4770

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer
2025-02-05 00:30:45 +01:00
parent 30a6ff248b
commit 6a89519e63
254 changed files with 1193 additions and 1032 deletions

View File

@@ -780,7 +780,7 @@ fmt-js:
fmt-go: fmt-go:
go fmt ./pkg/... ./internal/... ./cmd/... go fmt ./pkg/... ./internal/... ./cmd/...
gofmt -w -s pkg internal cmd gofmt -w -s pkg internal cmd
goimports -w pkg internal cmd goimports -w -local "github.com/photoprism" pkg internal cmd
tidy: tidy:
go mod tidy go mod tidy
users: users:

View File

@@ -11,9 +11,10 @@ import (
"text/template" "text/template"
"unicode" "unicode"
"gopkg.in/yaml.v2"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/fs" "github.com/photoprism/photoprism/pkg/fs"
"gopkg.in/yaml.v2"
) )
// LabelRule defines the rule for a given Label // LabelRule defines the rule for a given Label

View File

@@ -13,9 +13,9 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/disintegration/imaging"
tf "github.com/tensorflow/tensorflow/tensorflow/go" tf "github.com/tensorflow/tensorflow/tensorflow/go"
"github.com/disintegration/imaging"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
) )

View File

@@ -11,6 +11,7 @@ import (
"sort" "sort"
pigo "github.com/esimov/pigo/core" pigo "github.com/esimov/pigo/core"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/fs" "github.com/photoprism/photoprism/pkg/fs"
) )

View File

@@ -6,9 +6,9 @@ import (
"testing" "testing"
"github.com/dustin/go-humanize/english" "github.com/dustin/go-humanize/english"
"github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/pkg/fs/fastwalk" "github.com/photoprism/photoprism/pkg/fs/fastwalk"
"github.com/stretchr/testify/assert"
) )
func TestDetect(t *testing.T) { func TestDetect(t *testing.T) {

View File

@@ -7,10 +7,11 @@ import (
"path/filepath" "path/filepath"
"sync" "sync"
"github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/fs"
tf "github.com/tensorflow/tensorflow/tensorflow/go" tf "github.com/tensorflow/tensorflow/tensorflow/go"
"github.com/tensorflow/tensorflow/tensorflow/go/op" "github.com/tensorflow/tensorflow/tensorflow/go/op"
"github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/fs"
) )
// Detector uses TensorFlow to label drawing, hentai, neutral, porn and sexy images. // Detector uses TensorFlow to label drawing, hentai, neutral, porn and sexy images.
@@ -29,7 +30,7 @@ func New(modelPath string) *Detector {
// File returns matching labels for a jpeg media file. // File returns matching labels for a jpeg media file.
func (t *Detector) File(filename string) (result Labels, err error) { func (t *Detector) File(filename string) (result Labels, err error) {
if fs.MimeType(filename) != fs.MimeTypeJPEG { if fs.MimeType(filename) != fs.MimeTypeJpeg {
return result, fmt.Errorf("nsfw: %s is not a jpeg file", clean.Log(filepath.Base(filename))) return result, fmt.Errorf("nsfw: %s is not a jpeg file", clean.Log(filepath.Base(filename)))
} }

View File

@@ -12,7 +12,7 @@ import (
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/i18n" "github.com/photoprism/photoprism/pkg/i18n"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
//go:embed embed/video.mp4 //go:embed embed/video.mp4
@@ -128,6 +128,6 @@ func AbortVideo(c *gin.Context) {
func AbortVideoWithStatus(c *gin.Context, code int) { func AbortVideoWithStatus(c *gin.Context, code int) {
if c != nil { if c != nil {
c.Data(code, header.ContentTypeAVC32, brokenVideo) c.Data(code, header.ContentTypeMp4Avc720, brokenVideo)
} }
} }

View File

@@ -8,7 +8,7 @@ import (
"github.com/photoprism/photoprism/internal/event" "github.com/photoprism/photoprism/internal/event"
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
// Auth checks if the user is authorized to access a resource with the given permission // Auth checks if the user is authorized to access a resource with the given permission

View File

@@ -10,7 +10,7 @@ import (
"github.com/photoprism/photoprism/internal/auth/acl" "github.com/photoprism/photoprism/internal/auth/acl"
"github.com/photoprism/photoprism/internal/auth/session" "github.com/photoprism/photoprism/internal/auth/session"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
func TestAuth(t *testing.T) { func TestAuth(t *testing.T) {

View File

@@ -3,7 +3,7 @@ package api
import ( import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
// ClientIP returns the client IP address from the request context or a placeholder if it is unknown. // ClientIP returns the client IP address from the request context or a placeholder if it is unknown.

View File

@@ -8,7 +8,7 @@ import (
"github.com/photoprism/photoprism/internal/entity" "github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/photoprism/get" "github.com/photoprism/photoprism/internal/photoprism/get"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
// AddCountHeader adds the actual result count to the response. // AddCountHeader adds the actual result count to the response.

View File

@@ -16,7 +16,7 @@ import (
"github.com/photoprism/photoprism/internal/form" "github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/internal/photoprism/get" "github.com/photoprism/photoprism/internal/photoprism/get"
"github.com/photoprism/photoprism/internal/server/limiter" "github.com/photoprism/photoprism/internal/server/limiter"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
type CloseableResponseRecorder struct { type CloseableResponseRecorder struct {

View File

@@ -12,7 +12,7 @@ import (
"github.com/photoprism/photoprism/internal/photoprism/get" "github.com/photoprism/photoprism/internal/photoprism/get"
"github.com/photoprism/photoprism/internal/thumb" "github.com/photoprism/photoprism/internal/thumb"
"github.com/photoprism/photoprism/pkg/fs" "github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
) )
@@ -63,7 +63,7 @@ func RemoveFromAlbumCoverCache(uid string) {
} }
// Delete share preview, if exists. // Delete share preview, if exists.
if sharePreview := path.Join(get.Config().ThumbCachePath(), "share", uid+fs.ExtJPEG); fs.FileExists(sharePreview) { if sharePreview := path.Join(get.Config().ThumbCachePath(), "share", uid+fs.ExtJpeg); fs.FileExists(sharePreview) {
_ = os.Remove(sharePreview) _ = os.Remove(sharePreview)
} }

View File

@@ -7,7 +7,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
func TestAddVideoCacheHeader(t *testing.T) { func TestAddVideoCacheHeader(t *testing.T) {

View File

@@ -13,7 +13,7 @@ import (
swagger "github.com/swaggo/gin-swagger" swagger "github.com/swaggo/gin-swagger"
"github.com/photoprism/photoprism/internal/photoprism/get" "github.com/photoprism/photoprism/internal/photoprism/get"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
//go:embed swagger.json //go:embed swagger.json

View File

@@ -9,7 +9,7 @@ import (
"github.com/photoprism/photoprism/internal/photoprism/get" "github.com/photoprism/photoprism/internal/photoprism/get"
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/i18n" "github.com/photoprism/photoprism/pkg/i18n"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
// OAuthAuthorize should gather consent and authorization from resource owners when using the // OAuthAuthorize should gather consent and authorization from resource owners when using the

View File

@@ -14,7 +14,7 @@ import (
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/i18n" "github.com/photoprism/photoprism/pkg/i18n"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
) )

View File

@@ -13,7 +13,7 @@ import (
"github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/entity" "github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/form" "github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
) )

View File

@@ -16,7 +16,7 @@ import (
"github.com/photoprism/photoprism/internal/server/limiter" "github.com/photoprism/photoprism/internal/server/limiter"
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
// OAuthToken creates a new access token for clients that authenticate with valid OAuth2 client credentials. // OAuthToken creates a new access token for clients that authenticate with valid OAuth2 client credentials.

View File

@@ -11,7 +11,7 @@ import (
"github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
func TestOAuthToken(t *testing.T) { func TestOAuthToken(t *testing.T) {

View File

@@ -9,7 +9,7 @@ import (
"github.com/photoprism/photoprism/internal/photoprism/get" "github.com/photoprism/photoprism/internal/photoprism/get"
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/i18n" "github.com/photoprism/photoprism/pkg/i18n"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
// OAuthUserinfo should return information about the authenticated user, // OAuthUserinfo should return information about the authenticated user,

View File

@@ -10,7 +10,7 @@ import (
"github.com/photoprism/photoprism/internal/server/limiter" "github.com/photoprism/photoprism/internal/server/limiter"
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/i18n" "github.com/photoprism/photoprism/pkg/i18n"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
// OIDCLogin redirects a browser to the login page of the configured OpenID Connect provider, if any. // OIDCLogin redirects a browser to the login page of the configured OpenID Connect provider, if any.

View File

@@ -17,7 +17,7 @@ import (
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/i18n" "github.com/photoprism/photoprism/pkg/i18n"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
"github.com/photoprism/photoprism/pkg/time/unix" "github.com/photoprism/photoprism/pkg/time/unix"
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"

View File

@@ -4,8 +4,9 @@ import (
"net/http" "net/http"
"testing" "testing"
"github.com/photoprism/photoprism/internal/config"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/config"
) )
func TestOIDCRedirect(t *testing.T) { func TestOIDCRedirect(t *testing.T) {

View File

@@ -206,7 +206,7 @@ func GetPhotoYaml(router *gin.RouterGroup) {
} }
if c.Query("download") != "" { if c.Query("download") != "" {
AddDownloadHeader(c, clean.UID(c.Param("uid"))+fs.ExtYAML) AddDownloadHeader(c, clean.UID(c.Param("uid"))+fs.ExtYaml)
} }
c.Data(http.StatusOK, "text/x-yaml; charset=utf-8", data) c.Data(http.StatusOK, "text/x-yaml; charset=utf-8", data)

View File

@@ -12,7 +12,7 @@ import (
"github.com/photoprism/photoprism/internal/form" "github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/internal/photoprism/get" "github.com/photoprism/photoprism/internal/photoprism/get"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"
) )

View File

@@ -4,9 +4,10 @@ import (
"net/http" "net/http"
"testing" "testing"
"github.com/photoprism/photoprism/pkg/i18n"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"github.com/photoprism/photoprism/pkg/i18n"
) )
func TestUploadToService(t *testing.T) { func TestUploadToService(t *testing.T) {

View File

@@ -13,7 +13,7 @@ import (
"github.com/photoprism/photoprism/internal/server/limiter" "github.com/photoprism/photoprism/internal/server/limiter"
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/i18n" "github.com/photoprism/photoprism/pkg/i18n"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
// CreateSession creates a new client session and returns it as JSON if authentication was successful. // CreateSession creates a new client session and returns it as JSON if authentication was successful.

View File

@@ -3,6 +3,8 @@ package api
import ( import (
"net/http" "net/http"
"github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/photoprism/photoprism/internal/auth/acl" "github.com/photoprism/photoprism/internal/auth/acl"
@@ -13,7 +15,6 @@ import (
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/i18n" "github.com/photoprism/photoprism/pkg/i18n"
"github.com/photoprism/photoprism/pkg/net/header"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
) )

View File

@@ -8,7 +8,7 @@ import (
"github.com/photoprism/photoprism/internal/auth/acl" "github.com/photoprism/photoprism/internal/auth/acl"
"github.com/photoprism/photoprism/internal/photoprism/get" "github.com/photoprism/photoprism/internal/photoprism/get"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
) )

View File

@@ -49,7 +49,7 @@ func SharePreview(router *gin.RouterGroup) {
return return
} }
previewFilename := filepath.Join(thumbPath, shared+fs.ExtJPEG) previewFilename := filepath.Join(thumbPath, shared+fs.ExtJpeg)
expires := entity.Now().Add(-1 * time.Hour) expires := entity.Now().Add(-1 * time.Hour)

View File

@@ -148,7 +148,7 @@ func GetThumb(router *gin.RouterGroup) {
} }
// Find supported preview image if media file is not a JPEG or PNG. // Find supported preview image if media file is not a JPEG or PNG.
if f.NoJPEG() && f.NoPNG() { if f.NoJpeg() && f.NoPng() {
if f, err = query.FileByPhotoUID(f.PhotoUID); err != nil { if f, err = query.FileByPhotoUID(f.PhotoUID); err != nil {
c.Data(http.StatusOK, "image/svg+xml", fileIconSvg) c.Data(http.StatusOK, "image/svg+xml", fileIconSvg)
return return

View File

@@ -99,9 +99,9 @@ func UploadUserAvatar(router *gin.RouterGroup) {
return return
} else { } else {
switch { switch {
case mimeType.Is(fs.MimeTypePNG): case mimeType.Is(fs.MimeTypePng):
fileName = "avatar.png" fileName = "avatar.png"
case mimeType.Is(fs.MimeTypeJPEG): case mimeType.Is(fs.MimeTypeJpeg):
fileName = "avatar.jpg" fileName = "avatar.jpg"
default: default:
event.AuditWarn([]string{ClientIP(c), "session %s", "upload avatar", " %s not supported"}, s.RefID, mimeType) event.AuditWarn([]string{ClientIP(c), "session %s", "upload avatar", " %s not supported"}, s.RefID, mimeType)

View File

@@ -17,7 +17,7 @@ import (
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/i18n" "github.com/photoprism/photoprism/pkg/i18n"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
) )

View File

@@ -4,8 +4,9 @@ import (
"net/http" "net/http"
"testing" "testing"
"github.com/photoprism/photoprism/internal/config"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/config"
) )
func TestFindUserSessions(t *testing.T) { func TestFindUserSessions(t *testing.T) {

View File

@@ -6,10 +6,11 @@ import (
"net/http" "net/http"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/entity" "github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/form" "github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert"
) )
func TestUpdateUser(t *testing.T) { func TestUpdateUser(t *testing.T) {

View File

@@ -13,8 +13,8 @@ import (
"github.com/photoprism/photoprism/internal/photoprism/get" "github.com/photoprism/photoprism/internal/photoprism/get"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/fs" "github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/media/video" "github.com/photoprism/photoprism/pkg/media/video"
"github.com/photoprism/photoprism/pkg/net/header"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
) )
@@ -153,7 +153,7 @@ func GetVideo(router *gin.RouterGroup) {
if avcFile, avcErr := conv.ToAvc(mediaFile, get.Config().FFmpegEncoder(), false, false); avcFile != nil && avcErr == nil { if avcFile, avcErr := conv.ToAvc(mediaFile, get.Config().FFmpegEncoder(), false, false); avcFile != nil && avcErr == nil {
videoFileName = avcFile.FileName() videoFileName = avcFile.FileName()
AddContentTypeHeader(c, header.ContentTypeAVC) AddContentTypeHeader(c, header.ContentTypeMp4Avc)
} else { } else {
// Log error and default to 404.mp4 // Log error and default to 404.mp4
log.Errorf("video: failed to transcode %s", clean.Log(f.FileName)) log.Errorf("video: failed to transcode %s", clean.Log(f.FileName))

View File

@@ -9,15 +9,15 @@ import (
"github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/media/video" "github.com/photoprism/photoprism/pkg/media/video"
"github.com/photoprism/photoprism/pkg/net/header"
) )
func TestGetVideo(t *testing.T) { func TestGetVideo(t *testing.T) {
t.Run("ContentTypeAVC", func(t *testing.T) { t.Run("ContentTypeAVC", func(t *testing.T) {
assert.Equal(t, header.ContentTypeAVC, clean.ContentType("video/mp4; codecs=\"avc1\"")) assert.Equal(t, header.ContentTypeMp4Avc, clean.ContentType("video/mp4; codecs=\"avc1\""))
mimeType := fmt.Sprintf("video/mp4; codecs=\"%s\"", clean.Codec("avc1")) mimeType := fmt.Sprintf("video/mp4; codecs=\"%s\"", clean.Codec("avc1"))
assert.Equal(t, header.ContentTypeAVC, video.ContentType(mimeType, "mp4", "avc1")) assert.Equal(t, header.ContentTypeMp4Avc, video.ContentType(mimeType, "mp4", "avc1"))
}) })
t.Run("NoHash", func(t *testing.T) { t.Run("NoHash", func(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package oidc
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/config"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/config"
) )
func TestClientConfig(t *testing.T) { func TestClientConfig(t *testing.T) {

View File

@@ -4,8 +4,9 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/photoprism/photoprism/internal/config/pwa"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/config/pwa"
) )
func TestConfig_AppName(t *testing.T) { func TestConfig_AppName(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
) )
func TestConfig_CdnUrl(t *testing.T) { func TestConfig_CdnUrl(t *testing.T) {

View File

@@ -65,7 +65,7 @@ func (c *Config) WallpaperUri() string {
wallpaperUri = "welcome.jpg" wallpaperUri = "welcome.jpg"
} else if !strings.Contains(wallpaperUri, ".") { } else if !strings.Contains(wallpaperUri, ".") {
wallpaperUri += fs.ExtJPEG wallpaperUri += fs.ExtJpeg
} }
// Complete URI as needed if file path is valid. // Complete URI as needed if file path is valid.

View File

@@ -9,8 +9,8 @@ import (
"github.com/photoprism/photoprism/internal/config/ttl" "github.com/photoprism/photoprism/internal/config/ttl"
"github.com/photoprism/photoprism/internal/server/limiter" "github.com/photoprism/photoprism/internal/server/limiter"
"github.com/photoprism/photoprism/pkg/fs" "github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/net/scheme" "github.com/photoprism/photoprism/pkg/media/http/scheme"
) )
const ( const (

View File

@@ -8,7 +8,7 @@ import (
"github.com/photoprism/photoprism/internal/config/ttl" "github.com/photoprism/photoprism/internal/config/ttl"
"github.com/photoprism/photoprism/pkg/fs" "github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/pkg/net/scheme" "github.com/photoprism/photoprism/pkg/media/http/scheme"
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"
) )

View File

@@ -3,8 +3,9 @@ package config
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/thumb"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/thumb"
) )
func TestConfig_ConvertSize(t *testing.T) { func TestConfig_ConvertSize(t *testing.T) {

View File

@@ -15,8 +15,8 @@ import (
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/i18n" "github.com/photoprism/photoprism/pkg/i18n"
"github.com/photoprism/photoprism/pkg/media" "github.com/photoprism/photoprism/pkg/media"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/net/scheme" "github.com/photoprism/photoprism/pkg/media/http/scheme"
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"
) )

View File

@@ -3,8 +3,9 @@ package config
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/pkg/fs"
) )
func TestNewOptions(t *testing.T) { func TestNewOptions(t *testing.T) {

View File

@@ -4,9 +4,10 @@ import (
"testing" "testing"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"github.com/photoprism/photoprism/pkg/fs"
) )
func TestConfig_TestdataPath2(t *testing.T) { func TestConfig_TestdataPath2(t *testing.T) {

View File

@@ -5,10 +5,10 @@ import (
"testing" "testing"
"time" "time"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/entity/sortby" "github.com/photoprism/photoprism/internal/entity/sortby"
"github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"
) )

View File

@@ -68,7 +68,7 @@ func (m *Album) YamlFileName(backupPath string) (absolute, relative string, err
return "", "", fmt.Errorf("album uid is empty") return "", "", fmt.Errorf("album uid is empty")
} }
relative = filepath.Join(m.AlbumType, m.AlbumUID+fs.ExtYAML) relative = filepath.Join(m.AlbumType, m.AlbumUID+fs.ExtYaml)
if backupPath == "" { if backupPath == "" {
return "", relative, fmt.Errorf("backup path is empty") return "", relative, fmt.Errorf("backup path is empty")

View File

@@ -3,8 +3,9 @@ package entity
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func Test_AddClient(t *testing.T) { func Test_AddClient(t *testing.T) {

View File

@@ -18,7 +18,7 @@ import (
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/i18n" "github.com/photoprism/photoprism/pkg/i18n"
"github.com/photoprism/photoprism/pkg/list" "github.com/photoprism/photoprism/pkg/list"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
"github.com/photoprism/photoprism/pkg/time/unix" "github.com/photoprism/photoprism/pkg/time/unix"
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"

View File

@@ -13,7 +13,7 @@ import (
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/i18n" "github.com/photoprism/photoprism/pkg/i18n"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"
) )

View File

@@ -10,7 +10,7 @@ import (
"github.com/photoprism/photoprism/internal/auth/acl" "github.com/photoprism/photoprism/internal/auth/acl"
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/net/header" "github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
"github.com/photoprism/photoprism/pkg/time/unix" "github.com/photoprism/photoprism/pkg/time/unix"
"github.com/photoprism/photoprism/pkg/txt/report" "github.com/photoprism/photoprism/pkg/txt/report"

View File

@@ -1,10 +1,10 @@
package entity package entity
import ( import (
"github.com/photoprism/photoprism/pkg/authn"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"github.com/photoprism/photoprism/internal/form" "github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
) )

View File

@@ -3,8 +3,9 @@ package entity
import ( import (
"time" "time"
"github.com/photoprism/photoprism/internal/event"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/photoprism/photoprism/internal/event"
) )
// Error represents an error message log. // Error represents an error message log.

View File

@@ -360,7 +360,7 @@ func (m *File) ReplaceHash(newHash string) error {
m.FileHash = newHash m.FileHash = newHash
// Ok to skip updating related tables? // Ok to skip updating related tables?
if m.NoJPEG() || m.FileHash == "" { if m.NoJpeg() || m.FileHash == "" {
return nil return nil
} }
@@ -590,13 +590,13 @@ func (m *File) RelatedPhoto() *Photo {
} }
// NoJPEG returns true if the file is not a JPEG image. // NoJPEG returns true if the file is not a JPEG image.
func (m *File) NoJPEG() bool { func (m *File) NoJpeg() bool {
return fs.ImageJPEG.NotEqual(m.FileType) return fs.ImageJpeg.NotEqual(m.FileType)
} }
// NoPNG returns true if the file is not a PNG image. // NoPNG returns true if the file is not a PNG image.
func (m *File) NoPNG() bool { func (m *File) NoPng() bool {
return fs.ImagePNG.NotEqual(m.FileType) return fs.ImagePng.NotEqual(m.FileType)
} }
// Type returns the file type. // Type returns the file type.

View File

@@ -2602,7 +2602,7 @@ var FileFixtures = FileMap{
FileHash: "pcad9168fa6acc5c5c2965adf6ec465ca42fd3451", FileHash: "pcad9168fa6acc5c5c2965adf6ec465ca42fd3451",
FileSize: 921858, FileSize: 921858,
FileCodec: "jpeg", FileCodec: "jpeg",
FileType: string(fs.ImageJPEG), FileType: string(fs.ImageJpeg),
MediaType: media.Image.String(), MediaType: media.Image.String(),
FileMime: "image/jpg", FileMime: "image/jpg",
FilePrimary: true, FilePrimary: true,

View File

@@ -11,8 +11,8 @@ import (
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/fs" "github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/pkg/media/colors" "github.com/photoprism/photoprism/pkg/media/colors"
"github.com/photoprism/photoprism/pkg/media/http/header"
"github.com/photoprism/photoprism/pkg/media/projection" "github.com/photoprism/photoprism/pkg/media/projection"
"github.com/photoprism/photoprism/pkg/net/header"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
) )
@@ -63,7 +63,7 @@ func TestFile_ShareFileName(t *testing.T) {
assert.Contains(t, filename, "20190115-000000-Berlin-Morning-Mood") assert.Contains(t, filename, "20190115-000000-Berlin-Morning-Mood")
assert.Equal(t, "20190115-000000-Berlin-Morning-Mood.jpg", filename) assert.Equal(t, "20190115-000000-Berlin-Morning-Mood.jpg", filename)
assert.Contains(t, filename, fs.ExtJPEG) assert.Contains(t, filename, fs.ExtJpeg)
}) })
t.Run("WithPhotoTitleSequence", func(t *testing.T) { t.Run("WithPhotoTitleSequence", func(t *testing.T) {
photo := &Photo{TakenAtLocal: time.Date(2019, 01, 15, 0, 0, 0, 0, time.UTC), PhotoTitle: "Berlin / Morning Mood"} photo := &Photo{TakenAtLocal: time.Date(2019, 01, 15, 0, 0, 0, 0, time.UTC), PhotoTitle: "Berlin / Morning Mood"}
@@ -73,7 +73,7 @@ func TestFile_ShareFileName(t *testing.T) {
assert.Contains(t, filename, "20190115-000000-Berlin-Morning-Mood") assert.Contains(t, filename, "20190115-000000-Berlin-Morning-Mood")
assert.Equal(t, "20190115-000000-Berlin-Morning-Mood (2).jpg", filename) assert.Equal(t, "20190115-000000-Berlin-Morning-Mood (2).jpg", filename)
assert.Contains(t, filename, fs.ExtJPEG) assert.Contains(t, filename, fs.ExtJpeg)
}) })
t.Run("EmptyPhotoTitle", func(t *testing.T) { t.Run("EmptyPhotoTitle", func(t *testing.T) {
photo := &Photo{TakenAtLocal: time.Date(2019, 01, 15, 0, 0, 0, 0, time.UTC), PhotoTitle: ""} photo := &Photo{TakenAtLocal: time.Date(2019, 01, 15, 0, 0, 0, 0, time.UTC), PhotoTitle: ""}
@@ -303,14 +303,14 @@ func TestFile_Links(t *testing.T) {
}) })
} }
func TestFile_NoJPEG(t *testing.T) { func TestFile_NoJpeg(t *testing.T) {
t.Run("true", func(t *testing.T) { t.Run("true", func(t *testing.T) {
file := &File{Photo: nil, FileType: "xmp", FileSize: 500} file := &File{Photo: nil, FileType: "xmp", FileSize: 500}
assert.True(t, file.NoJPEG()) assert.True(t, file.NoJpeg())
}) })
t.Run("false", func(t *testing.T) { t.Run("false", func(t *testing.T) {
file := &File{Photo: nil, FileType: "jpg", FileSize: 500} file := &File{Photo: nil, FileType: "jpg", FileSize: 500}
assert.False(t, file.NoJPEG()) assert.False(t, file.NoJpeg())
}) })
} }
@@ -432,12 +432,12 @@ func TestFile_OriginalBase(t *testing.T) {
filename := file.OriginalBase(0) filename := file.OriginalBase(0)
assert.Contains(t, filename, "20190115-000000-Berlin-Morning-Mood") assert.Contains(t, filename, "20190115-000000-Berlin-Morning-Mood")
assert.Contains(t, filename, fs.ExtJPEG) assert.Contains(t, filename, fs.ExtJpeg)
filename2 := file.OriginalBase(1) filename2 := file.OriginalBase(1)
assert.Contains(t, filename2, "20190115-000000-Berlin-Morning-Mood") assert.Contains(t, filename2, "20190115-000000-Berlin-Morning-Mood")
assert.Contains(t, filename2, "(1)") assert.Contains(t, filename2, "(1)")
assert.Contains(t, filename2, fs.ExtJPEG) assert.Contains(t, filename2, fs.ExtJpeg)
}) })
t.Run("original name empty", func(t *testing.T) { t.Run("original name empty", func(t *testing.T) {
photo := &Photo{TakenAtLocal: time.Date(2019, 01, 15, 0, 0, 0, 0, time.UTC), PhotoTitle: "Berlin / Morning Mood"} photo := &Photo{TakenAtLocal: time.Date(2019, 01, 15, 0, 0, 0, 0, time.UTC), PhotoTitle: "Berlin / Morning Mood"}
@@ -446,12 +446,12 @@ func TestFile_OriginalBase(t *testing.T) {
filename := file.OriginalBase(0) filename := file.OriginalBase(0)
assert.Contains(t, filename, "sonnenaufgang") assert.Contains(t, filename, "sonnenaufgang")
assert.Contains(t, filename, fs.ExtJPEG) assert.Contains(t, filename, fs.ExtJpeg)
filename2 := file.OriginalBase(1) filename2 := file.OriginalBase(1)
assert.Contains(t, filename2, "sonnenaufgang") assert.Contains(t, filename2, "sonnenaufgang")
assert.Contains(t, filename2, "(1)") assert.Contains(t, filename2, "(1)")
assert.Contains(t, filename2, fs.ExtJPEG) assert.Contains(t, filename2, fs.ExtJpeg)
}) })
t.Run("original name not empty", func(t *testing.T) { t.Run("original name not empty", func(t *testing.T) {
photo := &Photo{TakenAtLocal: time.Date(2019, 01, 15, 0, 0, 0, 0, time.UTC), PhotoTitle: "Berlin / Morning Mood"} photo := &Photo{TakenAtLocal: time.Date(2019, 01, 15, 0, 0, 0, 0, time.UTC), PhotoTitle: "Berlin / Morning Mood"}
@@ -460,12 +460,12 @@ func TestFile_OriginalBase(t *testing.T) {
filename := file.OriginalBase(0) filename := file.OriginalBase(0)
assert.Contains(t, filename, "Sonnenaufgang") assert.Contains(t, filename, "Sonnenaufgang")
assert.Contains(t, filename, fs.ExtJPEG) assert.Contains(t, filename, fs.ExtJpeg)
filename2 := file.OriginalBase(1) filename2 := file.OriginalBase(1)
assert.Contains(t, filename2, "Sonnenaufgang") assert.Contains(t, filename2, "Sonnenaufgang")
assert.Contains(t, filename2, "(1)") assert.Contains(t, filename2, "(1)")
assert.Contains(t, filename2, fs.ExtJPEG) assert.Contains(t, filename2, fs.ExtJpeg)
}) })
} }
@@ -476,12 +476,12 @@ func TestFile_DownloadName(t *testing.T) {
filename := file.DownloadName(customize.DownloadNameFile, 0) filename := file.DownloadName(customize.DownloadNameFile, 0)
assert.Contains(t, filename, "filename") assert.Contains(t, filename, "filename")
assert.Contains(t, filename, fs.ExtJPEG) assert.Contains(t, filename, fs.ExtJpeg)
filename2 := file.DownloadName(customize.DownloadNameOriginal, 1) filename2 := file.DownloadName(customize.DownloadNameOriginal, 1)
assert.Contains(t, filename2, "originalName") assert.Contains(t, filename2, "originalName")
assert.Contains(t, filename2, "(1)") assert.Contains(t, filename2, "(1)")
assert.Contains(t, filename2, fs.ExtJPEG) assert.Contains(t, filename2, fs.ExtJpeg)
filename3 := file.DownloadName("xxx", 0) filename3 := file.DownloadName("xxx", 0)
assert.Contains(t, filename3, "20190115-000000-Berlin-Morning-Mood") assert.Contains(t, filename3, "20190115-000000-Berlin-Morning-Mood")
@@ -881,14 +881,14 @@ func TestFile_ContentType(t *testing.T) {
t.Run("Image", func(t *testing.T) { t.Run("Image", func(t *testing.T) {
m := FileFixtures.Get("exampleFileName.jpg") m := FileFixtures.Get("exampleFileName.jpg")
assert.Equal(t, false, m.FileVideo) assert.Equal(t, false, m.FileVideo)
assert.Equal(t, header.ContentTypeJPEG, m.ContentType()) assert.Equal(t, header.ContentTypeJpeg, m.ContentType())
}) })
t.Run("Video", func(t *testing.T) { t.Run("Video", func(t *testing.T) {
avc := FileFixtures.Get("Video.mp4") avc := FileFixtures.Get("Video.mp4")
assert.Equal(t, true, avc.FileVideo) assert.Equal(t, true, avc.FileVideo)
assert.Equal(t, header.ContentTypeAVC, avc.ContentType()) assert.Equal(t, header.ContentTypeMp4Avc, avc.ContentType())
hevc := FileFixtures.Get("Photo21.mp4") hevc := FileFixtures.Get("Photo21.mp4")
assert.Equal(t, true, hevc.FileVideo) assert.Equal(t, true, hevc.FileVideo)
assert.Equal(t, header.ContentTypeHEVC, hevc.ContentType()) assert.Equal(t, header.ContentTypeMp4Hevc, hevc.ContentType())
}) })
} }

View File

@@ -3,8 +3,9 @@ package entity
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/pkg/rnd"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/pkg/rnd"
) )
func TestNewLink(t *testing.T) { func TestNewLink(t *testing.T) {

View File

@@ -4,9 +4,10 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form" "github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/internal/thumb/crop" "github.com/photoprism/photoprism/internal/thumb/crop"
"github.com/stretchr/testify/assert"
) )
var testArea = crop.Area{ var testArea = crop.Area{

View File

@@ -5,6 +5,7 @@ import (
"github.com/dustin/go-humanize/english" "github.com/dustin/go-humanize/english"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"github.com/photoprism/photoprism/pkg/list" "github.com/photoprism/photoprism/pkg/list"
) )

View File

@@ -8,12 +8,12 @@ import (
"image/png" "image/png"
"time" "time"
"github.com/pquerna/otp"
"github.com/pquerna/otp/totp" "github.com/pquerna/otp/totp"
"github.com/photoprism/photoprism/pkg/authn" "github.com/photoprism/photoprism/pkg/authn"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
"github.com/pquerna/otp"
) )
// Passcode represents a two-factor authentication key. // Passcode represents a two-factor authentication key.
@@ -326,7 +326,7 @@ func (m *Passcode) Image(size int) (image.Image, error) {
} }
// PNG returns a PNG image buffer with a QR Code that can be used to initialize compatible authenticator apps. // PNG returns a PNG image buffer with a QR Code that can be used to initialize compatible authenticator apps.
func (m *Passcode) PNG(size int) *bytes.Buffer { func (m *Passcode) Png(size int) *bytes.Buffer {
if m == nil { if m == nil {
return nil return nil
} }

View File

@@ -23,7 +23,7 @@ func (m *Passcode) MarshalJSON() ([]byte, error) {
UID: m.UID, UID: m.UID,
Type: m.KeyType, Type: m.KeyType,
Secret: m.Secret(), Secret: m.Secret(),
QRCode: media.Base64(m.PNG(350)), QRCode: media.Base64(m.Png(350)),
RecoveryCode: m.RecoveryCode, RecoveryCode: m.RecoveryCode,
CreatedAt: m.CreatedAt, CreatedAt: m.CreatedAt,
UpdatedAt: m.UpdatedAt, UpdatedAt: m.UpdatedAt,

View File

@@ -7,12 +7,13 @@ import (
"github.com/dustin/go-humanize/english" "github.com/dustin/go-humanize/english"
"gopkg.in/photoprism/go-tz.v2/tz"
"github.com/photoprism/photoprism/internal/ai/classify" "github.com/photoprism/photoprism/internal/ai/classify"
"github.com/photoprism/photoprism/internal/service/maps" "github.com/photoprism/photoprism/internal/service/maps"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/geo" "github.com/photoprism/photoprism/pkg/geo"
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"
"gopkg.in/photoprism/go-tz.v2/tz"
) )
// SetCoordinates changes the photo lat, lng and altitude if not empty and from an acceptable source. // SetCoordinates changes the photo lat, lng and altitude if not empty and from an acceptable source.

View File

@@ -4,6 +4,7 @@ import (
"sync" "sync"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
) )

View File

@@ -67,8 +67,8 @@ func (m *Photo) SaveAsYaml(fileName string) error {
// YamlFileName returns both the absolute file path and the relative name for the YAML sidecar file, e.g. for logging. // YamlFileName returns both the absolute file path and the relative name for the YAML sidecar file, e.g. for logging.
func (m *Photo) YamlFileName(originalsPath, sidecarPath string) (absolute, relative string, err error) { func (m *Photo) YamlFileName(originalsPath, sidecarPath string) (absolute, relative string, err error) {
absolute, err = fs.FileName(filepath.Join(originalsPath, m.PhotoPath, m.PhotoName), sidecarPath, originalsPath, fs.ExtYAML) absolute, err = fs.FileName(filepath.Join(originalsPath, m.PhotoPath, m.PhotoName), sidecarPath, originalsPath, fs.ExtYaml)
relative = filepath.Join(m.PhotoPath, m.PhotoName) + fs.ExtYAML relative = filepath.Join(m.PhotoPath, m.PhotoName) + fs.ExtYaml
return absolute, relative, err return absolute, relative, err
} }

View File

@@ -3,8 +3,9 @@ package query
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/entity"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/entity"
) )
func TestAccountUploads(t *testing.T) { func TestAccountUploads(t *testing.T) {

View File

@@ -61,13 +61,13 @@ func ShareSelection(originals bool) FileSelection {
} }
omitTypes = []string{ omitTypes = []string{
fs.ImagePNG.String(), fs.ImagePng.String(),
fs.ImageWebP.String(), fs.ImageWebp.String(),
fs.ImageTIFF.String(), fs.ImageTiff.String(),
fs.ImageAVIF.String(), fs.ImageAvif.String(),
fs.ImageHEIC.String(), fs.ImageHeic.String(),
fs.ImageBMP.String(), fs.ImageBmp.String(),
fs.ImageGIF.String(), fs.ImageGif.String(),
} }
} }

View File

@@ -4,8 +4,9 @@ import (
"testing" "testing"
"time" "time"
"github.com/photoprism/photoprism/internal/entity"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/entity"
) )
func TestFileShares(t *testing.T) { func TestFileShares(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package query
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/entity"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/entity"
) )
func TestFileSyncs(t *testing.T) { func TestFileSyncs(t *testing.T) {

View File

@@ -85,7 +85,7 @@ func VideoByPhotoUID(photoUID string) (*entity.File, error) {
} }
err := Db().Where("photo_uid = ? AND file_missing = 0", photoUID). err := Db().Where("photo_uid = ? AND file_missing = 0", photoUID).
Where("file_video = 1 OR file_duration > 0 OR file_frames > 0 OR file_type = ?", fs.ImageGIF). Where("file_video = 1 OR file_duration > 0 OR file_frames > 0 OR file_type = ?", fs.ImageGif).
Order("file_error ASC, file_video DESC, file_duration DESC, file_frames DESC"). Order("file_error ASC, file_video DESC, file_duration DESC, file_frames DESC").
Preload("Photo").First(&f).Error Preload("Photo").First(&f).Error

View File

@@ -4,8 +4,9 @@ import (
"testing" "testing"
"time" "time"
"github.com/photoprism/photoprism/internal/entity"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/entity"
) )
func TestFilesByPath(t *testing.T) { func TestFilesByPath(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package query
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/entity"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/entity"
) )
func TestFolderCoverByUID(t *testing.T) { func TestFolderCoverByUID(t *testing.T) {

View File

@@ -4,8 +4,9 @@ import (
"testing" "testing"
"time" "time"
"github.com/photoprism/photoprism/internal/entity"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/entity"
) )
func TestPurgeOrphans(t *testing.T) { func TestPurgeOrphans(t *testing.T) {

View File

@@ -26,6 +26,7 @@ package query
import ( import (
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"github.com/photoprism/photoprism/internal/entity" "github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/event" "github.com/photoprism/photoprism/internal/event"
) )

View File

@@ -3,9 +3,10 @@ package search
import ( import (
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/entity" "github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/form" "github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert"
) )
func TestAccounts(t *testing.T) { func TestAccounts(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosFilterAlbum(t *testing.T) { func TestPhotosFilterAlbum(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosFilterAlt(t *testing.T) { func TestPhotosFilterAlt(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosQueryAnimated(t *testing.T) { func TestPhotosQueryAnimated(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosQueryArchived(t *testing.T) { func TestPhotosQueryArchived(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosQueryError(t *testing.T) { func TestPhotosQueryError(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosFilterFNumber(t *testing.T) { func TestPhotosFilterFNumber(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosFilterFaces(t *testing.T) { func TestPhotosFilterFaces(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosQueryFavorite(t *testing.T) { func TestPhotosQueryFavorite(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosFilterFilename(t *testing.T) { func TestPhotosFilterFilename(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosFilterFocalLength(t *testing.T) { func TestPhotosFilterFocalLength(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosFilterFolder(t *testing.T) { func TestPhotosFilterFolder(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosQueryGeo(t *testing.T) { func TestPhotosQueryGeo(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosQueryHidden(t *testing.T) { func TestPhotosQueryHidden(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosFilterIso(t *testing.T) { func TestPhotosFilterIso(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosFilterKeywords(t *testing.T) { func TestPhotosFilterKeywords(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosFilterLabel(t *testing.T) { func TestPhotosFilterLabel(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosQueryLandscape(t *testing.T) { func TestPhotosQueryLandscape(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosQueryLive(t *testing.T) { func TestPhotosQueryLive(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosQueryMono(t *testing.T) { func TestPhotosQueryMono(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosFilterName(t *testing.T) { func TestPhotosFilterName(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosQueryPanorama(t *testing.T) { func TestPhotosQueryPanorama(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosFilterPath(t *testing.T) { func TestPhotosFilterPath(t *testing.T) {

View File

@@ -3,8 +3,9 @@ package search
import ( import (
"testing" "testing"
"github.com/photoprism/photoprism/internal/form"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/photoprism/photoprism/internal/form"
) )
func TestPhotosQueryPhoto(t *testing.T) { func TestPhotosQueryPhoto(t *testing.T) {

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