feat: display image resolutions in file details (#2830)
--------- Co-authored-by: MAERYO <maeryo@hanwha.com>pull/2823/head^2
parent
4dbc802972
commit
a09dfa8d9f
|
@ -7,6 +7,7 @@ import (
|
|||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
"hash"
|
||||
"image"
|
||||
"io"
|
||||
"log"
|
||||
"mime"
|
||||
|
@ -44,6 +45,7 @@ type FileInfo struct {
|
|||
Checksums map[string]string `json:"checksums,omitempty"`
|
||||
Token string `json:"token,omitempty"`
|
||||
currentDir []os.FileInfo `json:"-"`
|
||||
Resolution *ImageResolution `json:"resolution,omitempty"`
|
||||
}
|
||||
|
||||
// FileOptions are the options when getting a file info.
|
||||
|
@ -58,6 +60,11 @@ type FileOptions struct {
|
|||
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
|
||||
// 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.
|
||||
|
@ -236,6 +243,12 @@ func (i *FileInfo) detectType(modify, saveContent, readHeader bool) error {
|
|||
return nil
|
||||
case strings.HasPrefix(mimetype, "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
|
||||
case strings.HasSuffix(mimetype, "pdf"):
|
||||
i.Type = "pdf"
|
||||
|
@ -264,6 +277,28 @@ func (i *FileInfo) detectType(modify, saveContent, readHeader bool) error {
|
|||
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 {
|
||||
reader, err := i.Fs.Open(i.Path)
|
||||
if err != nil {
|
||||
|
@ -361,6 +396,15 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
|
|||
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 {
|
||||
listing.NumDirs++
|
||||
} else {
|
||||
|
|
|
@ -12,10 +12,17 @@
|
|||
<p class="break-word" v-if="selected.length < 2">
|
||||
<strong>{{ $t("prompts.displayName") }}</strong> {{ name }}
|
||||
</p>
|
||||
|
||||
<p v-if="!dir || selected.length > 1">
|
||||
<strong>{{ $t("prompts.size") }}:</strong>
|
||||
<span id="content_length"></span> {{ humanSize }}
|
||||
</p>
|
||||
|
||||
<div v-if="resolution">
|
||||
<strong>{{ $t("prompts.resolution") }}:</strong>
|
||||
{{ resolution.width }} x {{ resolution.height }}
|
||||
</div>
|
||||
|
||||
<p v-if="selected.length < 2" :title="modTime">
|
||||
<strong>{{ $t("prompts.lastModified") }}:</strong> {{ humanTime }}
|
||||
</p>
|
||||
|
@ -126,6 +133,18 @@ export default {
|
|||
: 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: {
|
||||
checksum: async function (event, algo) {
|
||||
|
|
|
@ -161,7 +161,8 @@
|
|||
"upload": "Upload",
|
||||
"uploadFiles": "Uploading {files} files...",
|
||||
"uploadMessage": "Select an option to upload.",
|
||||
"optionalPassword": "Optional password"
|
||||
"optionalPassword": "Optional password",
|
||||
"resolution": "Resolution"
|
||||
},
|
||||
"search": {
|
||||
"images": "Images",
|
||||
|
|
Loading…
Reference in New Issue