1
Fork 0

Improve integration with ui

This commit is contained in:
viktorstrate 2020-02-10 12:05:58 +01:00
parent a3a4dda286
commit 6e72caf2f0
13 changed files with 356 additions and 91 deletions

View File

@ -78,15 +78,21 @@ type ComplexityRoot struct {
Photo struct { Photo struct {
Album func(childComplexity int) int Album func(childComplexity int) int
Downloads func(childComplexity int) int
Exif func(childComplexity int) int Exif func(childComplexity int) int
HighRes func(childComplexity int) int HighRes func(childComplexity int) int
ID func(childComplexity int) int ID func(childComplexity int) int
Original func(childComplexity int) int
Path func(childComplexity int) int Path func(childComplexity int) int
Shares func(childComplexity int) int
Thumbnail func(childComplexity int) int Thumbnail func(childComplexity int) int
Title func(childComplexity int) int Title func(childComplexity int) int
} }
PhotoDownload struct {
Title func(childComplexity int) int
URL func(childComplexity int) int
}
PhotoExif struct { PhotoExif struct {
Aperture func(childComplexity int) int Aperture func(childComplexity int) int
Camera func(childComplexity int) int Camera func(childComplexity int) int
@ -165,11 +171,12 @@ type MutationResolver interface {
SharePhoto(ctx context.Context, photoID int, expire *time.Time, password *string) (*models.ShareToken, error) SharePhoto(ctx context.Context, photoID int, expire *time.Time, password *string) (*models.ShareToken, error)
} }
type PhotoResolver interface { type PhotoResolver interface {
Original(ctx context.Context, obj *models.Photo) (*models.PhotoURL, error)
Thumbnail(ctx context.Context, obj *models.Photo) (*models.PhotoURL, error) Thumbnail(ctx context.Context, obj *models.Photo) (*models.PhotoURL, error)
HighRes(ctx context.Context, obj *models.Photo) (*models.PhotoURL, error) HighRes(ctx context.Context, obj *models.Photo) (*models.PhotoURL, error)
Album(ctx context.Context, obj *models.Photo) (*models.Album, error) Album(ctx context.Context, obj *models.Photo) (*models.Album, error)
Exif(ctx context.Context, obj *models.Photo) (*models.PhotoExif, error) Exif(ctx context.Context, obj *models.Photo) (*models.PhotoExif, error)
Shares(ctx context.Context, obj *models.Photo) ([]*models.ShareToken, error)
Downloads(ctx context.Context, obj *models.Photo) ([]*models.PhotoDownload, error)
} }
type QueryResolver interface { type QueryResolver interface {
SiteInfo(ctx context.Context) (*models.SiteInfo, error) SiteInfo(ctx context.Context) (*models.SiteInfo, error)
@ -377,6 +384,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Photo.Album(childComplexity), true return e.complexity.Photo.Album(childComplexity), true
case "Photo.downloads":
if e.complexity.Photo.Downloads == nil {
break
}
return e.complexity.Photo.Downloads(childComplexity), true
case "Photo.exif": case "Photo.exif":
if e.complexity.Photo.Exif == nil { if e.complexity.Photo.Exif == nil {
break break
@ -398,13 +412,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Photo.ID(childComplexity), true return e.complexity.Photo.ID(childComplexity), true
case "Photo.original":
if e.complexity.Photo.Original == nil {
break
}
return e.complexity.Photo.Original(childComplexity), true
case "Photo.path": case "Photo.path":
if e.complexity.Photo.Path == nil { if e.complexity.Photo.Path == nil {
break break
@ -412,6 +419,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Photo.Path(childComplexity), true return e.complexity.Photo.Path(childComplexity), true
case "Photo.shares":
if e.complexity.Photo.Shares == nil {
break
}
return e.complexity.Photo.Shares(childComplexity), true
case "Photo.thumbnail": case "Photo.thumbnail":
if e.complexity.Photo.Thumbnail == nil { if e.complexity.Photo.Thumbnail == nil {
break break
@ -426,6 +440,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Photo.Title(childComplexity), true return e.complexity.Photo.Title(childComplexity), true
case "PhotoDownload.title":
if e.complexity.PhotoDownload.Title == nil {
break
}
return e.complexity.PhotoDownload.Title(childComplexity), true
case "PhotoDownload.url":
if e.complexity.PhotoDownload.URL == nil {
break
}
return e.complexity.PhotoDownload.URL(childComplexity), true
case "PhotoEXIF.aperture": case "PhotoEXIF.aperture":
if e.complexity.PhotoExif.Aperture == nil { if e.complexity.PhotoExif.Aperture == nil {
break break
@ -926,22 +954,26 @@ type PhotoURL {
height: Int! height: Int!
} }
type PhotoDownload {
title: String!
url: String!
}
type Photo { type Photo {
id: Int! id: Int!
title: String! title: String!
"Local filepath for the photo" "Local filepath for the photo"
path: String! path: String!
"URL to display the photo in full resolution"
original: PhotoURL!
"URL to display the photo in a smaller resolution" "URL to display the photo in a smaller resolution"
thumbnail: PhotoURL! thumbnail: PhotoURL!
"URL to display the photo in full resolution"
highRes: PhotoURL! highRes: PhotoURL!
"The album that holds the photo" "The album that holds the photo"
album: Album! album: Album!
exif: PhotoEXIF exif: PhotoEXIF
# shares: [ShareToken] shares: [ShareToken!]!
# downloads: [PhotoDownload] downloads: [PhotoDownload!]!
} }
"EXIF metadata from the camera" "EXIF metadata from the camera"
@ -2137,43 +2169,6 @@ func (ec *executionContext) _Photo_path(ctx context.Context, field graphql.Colle
return ec.marshalNString2string(ctx, field.Selections, res) return ec.marshalNString2string(ctx, field.Selections, res)
} }
func (ec *executionContext) _Photo_original(ctx context.Context, field graphql.CollectedField, obj *models.Photo) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "Photo",
Field: field,
Args: nil,
IsMethod: true,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Photo().Original(rctx, obj)
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !ec.HasError(rctx) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(*models.PhotoURL)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalNPhotoURL2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoURL(ctx, field.Selections, res)
}
func (ec *executionContext) _Photo_thumbnail(ctx context.Context, field graphql.CollectedField, obj *models.Photo) (ret graphql.Marshaler) { func (ec *executionContext) _Photo_thumbnail(ctx context.Context, field graphql.CollectedField, obj *models.Photo) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field) ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() { defer func() {
@ -2319,6 +2314,154 @@ func (ec *executionContext) _Photo_exif(ctx context.Context, field graphql.Colle
return ec.marshalOPhotoEXIF2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoExif(ctx, field.Selections, res) return ec.marshalOPhotoEXIF2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoExif(ctx, field.Selections, res)
} }
func (ec *executionContext) _Photo_shares(ctx context.Context, field graphql.CollectedField, obj *models.Photo) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "Photo",
Field: field,
Args: nil,
IsMethod: true,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Photo().Shares(rctx, obj)
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !ec.HasError(rctx) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.([]*models.ShareToken)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalNShareToken2ᚕᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐShareTokenᚄ(ctx, field.Selections, res)
}
func (ec *executionContext) _Photo_downloads(ctx context.Context, field graphql.CollectedField, obj *models.Photo) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "Photo",
Field: field,
Args: nil,
IsMethod: true,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Photo().Downloads(rctx, obj)
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !ec.HasError(rctx) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.([]*models.PhotoDownload)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalNPhotoDownload2ᚕᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoDownloadᚄ(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoDownload_title(ctx context.Context, field graphql.CollectedField, obj *models.PhotoDownload) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoDownload",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Title, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !ec.HasError(rctx) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(string)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalNString2string(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoDownload_url(ctx context.Context, field graphql.CollectedField, obj *models.PhotoDownload) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
ec.Tracer.EndFieldExecution(ctx)
}()
rctx := &graphql.ResolverContext{
Object: "PhotoDownload",
Field: field,
Args: nil,
IsMethod: false,
}
ctx = graphql.WithResolverContext(ctx, rctx)
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.URL, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !ec.HasError(rctx) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(string)
rctx.Result = res
ctx = ec.Tracer.StartFieldChildExecution(ctx)
return ec.marshalNString2string(ctx, field.Selections, res)
}
func (ec *executionContext) _PhotoEXIF_photo(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) { func (ec *executionContext) _PhotoEXIF_photo(ctx context.Context, field graphql.CollectedField, obj *models.PhotoExif) (ret graphql.Marshaler) {
ctx = ec.Tracer.StartFieldExecution(ctx, field) ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() { defer func() {
@ -5249,20 +5392,6 @@ func (ec *executionContext) _Photo(ctx context.Context, sel ast.SelectionSet, ob
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
atomic.AddUint32(&invalids, 1) atomic.AddUint32(&invalids, 1)
} }
case "original":
field := field
out.Concurrently(i, func() (res graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
}
}()
res = ec._Photo_original(ctx, field, obj)
if res == graphql.Null {
atomic.AddUint32(&invalids, 1)
}
return res
})
case "thumbnail": case "thumbnail":
field := field field := field
out.Concurrently(i, func() (res graphql.Marshaler) { out.Concurrently(i, func() (res graphql.Marshaler) {
@ -5316,6 +5445,66 @@ func (ec *executionContext) _Photo(ctx context.Context, sel ast.SelectionSet, ob
res = ec._Photo_exif(ctx, field, obj) res = ec._Photo_exif(ctx, field, obj)
return res return res
}) })
case "shares":
field := field
out.Concurrently(i, func() (res graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
}
}()
res = ec._Photo_shares(ctx, field, obj)
if res == graphql.Null {
atomic.AddUint32(&invalids, 1)
}
return res
})
case "downloads":
field := field
out.Concurrently(i, func() (res graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
}
}()
res = ec._Photo_downloads(ctx, field, obj)
if res == graphql.Null {
atomic.AddUint32(&invalids, 1)
}
return res
})
default:
panic("unknown field " + strconv.Quote(field.Name))
}
}
out.Dispatch()
if invalids > 0 {
return graphql.Null
}
return out
}
var photoDownloadImplementors = []string{"PhotoDownload"}
func (ec *executionContext) _PhotoDownload(ctx context.Context, sel ast.SelectionSet, obj *models.PhotoDownload) graphql.Marshaler {
fields := graphql.CollectFields(ec.RequestContext, sel, photoDownloadImplementors)
out := graphql.NewFieldSet(fields)
var invalids uint32
for i, field := range fields {
switch field.Name {
case "__typename":
out.Values[i] = graphql.MarshalString("PhotoDownload")
case "title":
out.Values[i] = ec._PhotoDownload_title(ctx, field, obj)
if out.Values[i] == graphql.Null {
invalids++
}
case "url":
out.Values[i] = ec._PhotoDownload_url(ctx, field, obj)
if out.Values[i] == graphql.Null {
invalids++
}
default: default:
panic("unknown field " + strconv.Quote(field.Name)) panic("unknown field " + strconv.Quote(field.Name))
} }
@ -6128,6 +6317,57 @@ func (ec *executionContext) marshalNPhoto2ᚖgithubᚗcomᚋviktorstrateᚋphoto
return ec._Photo(ctx, sel, v) return ec._Photo(ctx, sel, v)
} }
func (ec *executionContext) marshalNPhotoDownload2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoDownload(ctx context.Context, sel ast.SelectionSet, v models.PhotoDownload) graphql.Marshaler {
return ec._PhotoDownload(ctx, sel, &v)
}
func (ec *executionContext) marshalNPhotoDownload2ᚕᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoDownloadᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.PhotoDownload) graphql.Marshaler {
ret := make(graphql.Array, len(v))
var wg sync.WaitGroup
isLen1 := len(v) == 1
if !isLen1 {
wg.Add(len(v))
}
for i := range v {
i := i
rctx := &graphql.ResolverContext{
Index: &i,
Result: &v[i],
}
ctx := graphql.WithResolverContext(ctx, rctx)
f := func(i int) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = nil
}
}()
if !isLen1 {
defer wg.Done()
}
ret[i] = ec.marshalNPhotoDownload2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoDownload(ctx, sel, v[i])
}
if isLen1 {
f(i)
} else {
go f(i)
}
}
wg.Wait()
return ret
}
func (ec *executionContext) marshalNPhotoDownload2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoDownload(ctx context.Context, sel ast.SelectionSet, v *models.PhotoDownload) graphql.Marshaler {
if v == nil {
if !ec.HasError(graphql.GetResolverContext(ctx)) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
return ec._PhotoDownload(ctx, sel, v)
}
func (ec *executionContext) marshalNPhotoURL2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoURL(ctx context.Context, sel ast.SelectionSet, v models.PhotoURL) graphql.Marshaler { func (ec *executionContext) marshalNPhotoURL2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhotoURL(ctx context.Context, sel ast.SelectionSet, v models.PhotoURL) graphql.Marshaler {
return ec._PhotoURL(ctx, sel, &v) return ec._PhotoURL(ctx, sel, &v)
} }

View File

@ -22,6 +22,11 @@ type Filter struct {
Offset *int `json:"offset"` Offset *int `json:"offset"`
} }
type PhotoDownload struct {
Title string `json:"title"`
URL string `json:"url"`
}
// EXIF metadata from the camera // EXIF metadata from the camera
type PhotoExif struct { type PhotoExif struct {
Photo *Photo `json:"photo"` Photo *Photo `json:"photo"`

View File

@ -24,7 +24,6 @@ type PhotoPurpose string
const ( const (
PhotoThumbnail PhotoPurpose = "thumbnail" PhotoThumbnail PhotoPurpose = "thumbnail"
PhotoHighRes PhotoPurpose = "high-res" PhotoHighRes PhotoPurpose = "high-res"
PhotoOriginal PhotoPurpose = "original"
) )
type PhotoURL struct { type PhotoURL struct {

View File

@ -3,6 +3,7 @@ package resolvers
import ( import (
"context" "context"
"errors" "errors"
"log"
api "github.com/viktorstrate/photoview/api/graphql" api "github.com/viktorstrate/photoview/api/graphql"
"github.com/viktorstrate/photoview/api/graphql/auth" "github.com/viktorstrate/photoview/api/graphql/auth"
@ -56,12 +57,20 @@ func (r *Resolver) Photo() api.PhotoResolver {
return &photoResolver{r} return &photoResolver{r}
} }
func (r *photoResolver) HighRes(ctx context.Context, obj *models.Photo) (*models.PhotoURL, error) { func (r *photoResolver) Shares(ctx context.Context, obj *models.Photo) ([]*models.ShareToken, error) {
panic("not implemented") log.Println("Photo: shares not implemented")
shares := make([]*models.ShareToken, 0)
return shares, nil
} }
func (r *photoResolver) Original(ctx context.Context, obj *models.Photo) (*models.PhotoURL, error) { func (r *photoResolver) Downloads(ctx context.Context, obj *models.Photo) ([]*models.PhotoDownload, error) {
row := r.Database.QueryRow("SELECT * FROM photo_url WHERE photo_id = ? AND purpose = ?", obj.PhotoID, models.PhotoOriginal) log.Println("Photo: downloads not implemented")
downloads := make([]*models.PhotoDownload, 0)
return downloads, nil
}
func (r *photoResolver) HighRes(ctx context.Context, obj *models.Photo) (*models.PhotoURL, error) {
row := r.Database.QueryRow("SELECT * FROM photo_url WHERE photo_id = ? AND purpose = ?", obj.PhotoID, models.PhotoHighRes)
url, err := models.NewPhotoURLFromRow(row) url, err := models.NewPhotoURLFromRow(row)
if err != nil { if err != nil {
@ -87,5 +96,6 @@ func (r *photoResolver) Album(ctx context.Context, obj *models.Photo) (*models.A
} }
func (r *photoResolver) Exif(ctx context.Context, obj *models.Photo) (*models.PhotoExif, error) { func (r *photoResolver) Exif(ctx context.Context, obj *models.Photo) (*models.PhotoExif, error) {
panic("not implemented") log.Println("Photo: EXIF not implemented")
return nil, nil
} }

View File

@ -135,22 +135,26 @@ type PhotoURL {
height: Int! height: Int!
} }
type PhotoDownload {
title: String!
url: String!
}
type Photo { type Photo {
id: Int! id: Int!
title: String! title: String!
"Local filepath for the photo" "Local filepath for the photo"
path: String! path: String!
"URL to display the photo in full resolution"
original: PhotoURL!
"URL to display the photo in a smaller resolution" "URL to display the photo in a smaller resolution"
thumbnail: PhotoURL! thumbnail: PhotoURL!
"URL to display the photo in full resolution"
highRes: PhotoURL! highRes: PhotoURL!
"The album that holds the photo" "The album that holds the photo"
album: Album! album: Album!
exif: PhotoEXIF exif: PhotoEXIF
# shares: [ShareToken] shares: [ShareToken!]!
# downloads: [PhotoDownload] downloads: [PhotoDownload!]!
} }
"EXIF metadata from the camera" "EXIF metadata from the camera"

View File

@ -42,7 +42,7 @@ func PhotoRoutes(db *sql.DB) chi.Router {
} }
} }
if purpose == models.PhotoOriginal { if purpose == models.PhotoHighRes {
var err error var err error
file, err = os.Open(path) file, err = os.Open(path)
if err != nil { if err != nil {

View File

@ -68,15 +68,17 @@ func ProcessImage(tx *sql.Tx, photoPath string, albumId int, content_type string
photoBaseName := photoName[0 : len(photoName)-len(path.Ext(photoName))] photoBaseName := photoName[0 : len(photoName)-len(path.Ext(photoName))]
photoBaseExt := path.Ext(photoName) photoBaseExt := path.Ext(photoName)
original_image_name := fmt.Sprintf("%s_%s", photoBaseName, utils.GenerateToken()) // high res
original_image_name = strings.ReplaceAll(original_image_name, " ", "_") + photoBaseExt highres_image_name := fmt.Sprintf("%s_%s", photoBaseName, utils.GenerateToken())
highres_image_name = strings.ReplaceAll(highres_image_name, " ", "_") + photoBaseExt
_, err = tx.Exec("INSERT INTO photo_url (photo_id, photo_name, width, height, purpose, content_type) VALUES (?, ?, ?, ?, ?, ?)", photo_id, original_image_name, image.Bounds().Max.X, image.Bounds().Max.Y, models.PhotoOriginal, content_type) _, err = tx.Exec("INSERT INTO photo_url (photo_id, photo_name, width, height, purpose, content_type) VALUES (?, ?, ?, ?, ?, ?)", photo_id, highres_image_name, image.Bounds().Max.X, image.Bounds().Max.Y, models.PhotoHighRes, content_type)
if err != nil { if err != nil {
log.Printf("Could not insert original photo url: %d, %s\n", photo_id, photoName) log.Printf("Could not insert high-res photo url: %d, %s\n", photo_id, photoName)
return err return err
} }
// Thumbnail
thumbnailImage := resize.Thumbnail(1024, 1024, image, resize.Bilinear) thumbnailImage := resize.Thumbnail(1024, 1024, image, resize.Bilinear)
if _, err := os.Stat("image-cache"); os.IsNotExist(err) { if _, err := os.Stat("image-cache"); os.IsNotExist(err) {

View File

@ -177,7 +177,7 @@ func directoryContainsPhotos(rootPath string, cache *scanner_cache) bool {
return false return false
} }
var supported_mimetypes = [...]string{ var SupportedMimetypes = [...]string{
"image/jpeg", "image/jpeg",
"image/png", "image/png",
"image/tiff", "image/tiff",
@ -186,6 +186,13 @@ var supported_mimetypes = [...]string{
"image/bmp", "image/bmp",
} }
var WebMimetypes = [...]string{
"image/jpeg",
"image/png",
"image/webp",
"image/bmp",
}
func isPathImage(path string, cache *scanner_cache) bool { func isPathImage(path string, cache *scanner_cache) bool {
if cache.get_photo_type(path) != nil { if cache.get_photo_type(path) != nil {
log.Printf("Image cache hit: %s\n", path) log.Printf("Image cache hit: %s\n", path)
@ -209,7 +216,7 @@ func isPathImage(path string, cache *scanner_cache) bool {
return false return false
} }
for _, supported_mime := range supported_mimetypes { for _, supported_mime := range SupportedMimetypes {
if supported_mime == imgType.MIME.Value { if supported_mime == imgType.MIME.Value {
cache.insert_photo_type(path, supported_mime) cache.insert_photo_type(path, supported_mime)
return true return true

View File

@ -30,7 +30,7 @@ const albumQuery = gql`
width width
height height
} }
original { highRes {
url url
} }
} }

View File

@ -22,7 +22,7 @@ const photoQuery = gql`
width width
height height
} }
original { highRes {
url url
} }
} }

View File

@ -50,7 +50,7 @@ export const PresentPhoto = ({ photo, imageLoaded, ...otherProps }) => {
<StyledPhoto src={photo.thumbnail.url} /> <StyledPhoto src={photo.thumbnail.url} />
<StyledPhoto <StyledPhoto
style={{ display: 'none' }} style={{ display: 'none' }}
src={photo.original.url} src={photo.highRes.url}
onLoad={e => { onLoad={e => {
e.target.style.display = 'initial' e.target.style.display = 'initial'
imageLoaded && imageLoaded() imageLoaded && imageLoaded()

View File

@ -13,7 +13,7 @@ const photoQuery = gql`
photo(id: $id) { photo(id: $id) {
id id
title title
original { highRes {
url url
width width
height height
@ -22,9 +22,7 @@ const photoQuery = gql`
camera camera
maker maker
lens lens
dateShot { dateShot
formatted
}
fileSize fileSize
exposure exposure
aperture aperture
@ -77,7 +75,7 @@ const SidebarContent = ({ photo, hidePreview }) => {
{} {}
) )
exif.dateShot = new Date(exif.dateShot.formatted).toLocaleString() exif.dateShot = new Date(exif.dateShot).toLocaleString()
exifItems = exifKeys.map(key => ( exifItems = exifKeys.map(key => (
<SidebarItem key={key} name={exifNameLookup[key]} value={exif[key]} /> <SidebarItem key={key} name={exifNameLookup[key]} value={exif[key]} />
@ -86,7 +84,7 @@ const SidebarContent = ({ photo, hidePreview }) => {
let previewUrl = null let previewUrl = null
if (photo) { if (photo) {
if (photo.original) previewUrl = photo.original.url if (photo.highRes) previewUrl = photo.highRes.url
else if (photo.thumbnail) previewUrl = photo.thumbnail.url else if (photo.thumbnail) previewUrl = photo.thumbnail.url
} }

View File

@ -54,7 +54,7 @@ const SidebarDownload = ({ photoId }) => {
} }
SidebarDownload.propTypes = { SidebarDownload.propTypes = {
photoId: PropTypes.string, photoId: PropTypes.number,
} }
export default SidebarDownload export default SidebarDownload