feat: display image resolutions in file details (#2830)

---------

Co-authored-by: MAERYO <maeryo@hanwha.com>
pull/2823/head^2
M A E R Y O 2023-11-25 21:35:00 +09:00 committed by GitHub
parent 4dbc802972
commit a09dfa8d9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 1 deletions

View File

@ -7,6 +7,7 @@ import (
"crypto/sha512" "crypto/sha512"
"encoding/hex" "encoding/hex"
"hash" "hash"
"image"
"io" "io"
"log" "log"
"mime" "mime"
@ -44,6 +45,7 @@ type FileInfo struct {
Checksums map[string]string `json:"checksums,omitempty"` Checksums map[string]string `json:"checksums,omitempty"`
Token string `json:"token,omitempty"` Token string `json:"token,omitempty"`
currentDir []os.FileInfo `json:"-"` currentDir []os.FileInfo `json:"-"`
Resolution *ImageResolution `json:"resolution,omitempty"`
} }
// FileOptions are the options when getting a file info. // FileOptions are the options when getting a file info.
@ -58,6 +60,11 @@ type FileOptions struct {
Content bool Content bool
} }
type ImageResolution struct {
Width int `json:"width"`
Height int `json:"height"`
}
// NewFileInfo creates a File object from a path and a given user. This File // NewFileInfo creates a File object from a path and a given user. This File
// object will be automatically filled depending on if it is a directory // object will be automatically filled depending on if it is a directory
// or a file. If it's a video file, it will also detect any subtitles. // or a file. If it's a video file, it will also detect any subtitles.
@ -236,6 +243,12 @@ func (i *FileInfo) detectType(modify, saveContent, readHeader bool) error {
return nil return nil
case strings.HasPrefix(mimetype, "image"): case strings.HasPrefix(mimetype, "image"):
i.Type = "image" i.Type = "image"
resolution, err := calculateImageResolution(i.Fs, i.Path)
if err != nil {
log.Printf("Error calculating image resolution: %v", err)
} else {
i.Resolution = resolution
}
return nil return nil
case strings.HasSuffix(mimetype, "pdf"): case strings.HasSuffix(mimetype, "pdf"):
i.Type = "pdf" i.Type = "pdf"
@ -264,6 +277,28 @@ func (i *FileInfo) detectType(modify, saveContent, readHeader bool) error {
return nil return nil
} }
func calculateImageResolution(fs afero.Fs, filePath string) (*ImageResolution, error) {
file, err := fs.Open(filePath)
if err != nil {
return nil, err
}
defer func() {
if cErr := file.Close(); cErr != nil {
log.Printf("Failed to close file: %v", cErr)
}
}()
config, _, err := image.DecodeConfig(file)
if err != nil {
return nil, err
}
return &ImageResolution{
Width: config.Width,
Height: config.Height,
}, nil
}
func (i *FileInfo) readFirstBytes() []byte { func (i *FileInfo) readFirstBytes() []byte {
reader, err := i.Fs.Open(i.Path) reader, err := i.Fs.Open(i.Path)
if err != nil { if err != nil {
@ -361,6 +396,15 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
currentDir: dir, currentDir: dir,
} }
if !file.IsDir && strings.HasPrefix(mime.TypeByExtension(file.Extension), "image/") {
resolution, err := calculateImageResolution(file.Fs, file.Path)
if err != nil {
log.Printf("Error calculating resolution for image %s: %v", file.Path, err)
} else {
file.Resolution = resolution
}
}
if file.IsDir { if file.IsDir {
listing.NumDirs++ listing.NumDirs++
} else { } else {

View File

@ -12,10 +12,17 @@
<p class="break-word" v-if="selected.length < 2"> <p class="break-word" v-if="selected.length < 2">
<strong>{{ $t("prompts.displayName") }}</strong> {{ name }} <strong>{{ $t("prompts.displayName") }}</strong> {{ name }}
</p> </p>
<p v-if="!dir || selected.length > 1"> <p v-if="!dir || selected.length > 1">
<strong>{{ $t("prompts.size") }}:</strong> <strong>{{ $t("prompts.size") }}:</strong>
<span id="content_length"></span> {{ humanSize }} <span id="content_length"></span> {{ humanSize }}
</p> </p>
<div v-if="resolution">
<strong>{{ $t("prompts.resolution") }}:</strong>
{{ resolution.width }} x {{ resolution.height }}
</div>
<p v-if="selected.length < 2" :title="modTime"> <p v-if="selected.length < 2" :title="modTime">
<strong>{{ $t("prompts.lastModified") }}:</strong> {{ humanTime }} <strong>{{ $t("prompts.lastModified") }}:</strong> {{ humanTime }}
</p> </p>
@ -126,6 +133,18 @@ export default {
: this.req.items[this.selected[0]].isDir) : this.req.items[this.selected[0]].isDir)
); );
}, },
resolution: function() {
if (this.selectedCount === 1) {
const selectedItem = this.req.items[this.selected[0]];
if (selectedItem && selectedItem.type === 'image') {
return selectedItem.resolution;
}
}
else if (this.req && this.req.type === 'image') {
return this.req.resolution;
}
return null;
},
}, },
methods: { methods: {
checksum: async function (event, algo) { checksum: async function (event, algo) {

View File

@ -161,7 +161,8 @@
"upload": "Upload", "upload": "Upload",
"uploadFiles": "Uploading {files} files...", "uploadFiles": "Uploading {files} files...",
"uploadMessage": "Select an option to upload.", "uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password" "optionalPassword": "Optional password",
"resolution": "Resolution"
}, },
"search": { "search": {
"images": "Images", "images": "Images",