Skip to content

Commit

Permalink
feat: display image resolutions in file details (#2830)
Browse files Browse the repository at this point in the history

---------

Co-authored-by: MAERYO <[email protected]>
  • Loading branch information
maeryo and MAERYO authored Nov 25, 2023
1 parent 4dbc802 commit a09dfa8
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 1 deletion.
44 changes: 44 additions & 0 deletions files/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"crypto/sha512"
"encoding/hex"
"hash"
"image"
"io"
"log"
"mime"
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
19 changes: 19 additions & 0 deletions frontend/src/components/prompts/Info.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -126,6 +133,18 @@ export default {
: this.req.items[this.selected[0]].isDir)
);
},
resolution: function() {

Check warning on line 136 in frontend/src/components/prompts/Info.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Insert `·`
if (this.selectedCount === 1) {
const selectedItem = this.req.items[this.selected[0]];
if (selectedItem && selectedItem.type === 'image') {

Check warning on line 139 in frontend/src/components/prompts/Info.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Replace `'image'` with `"image"`
return selectedItem.resolution;
}
}

Check warning on line 142 in frontend/src/components/prompts/Info.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Replace `⏎······else·if·(this.req·&&·this.req.type·===·'image'` with `·else·if·(this.req·&&·this.req.type·===·"image"`
else if (this.req && this.req.type === 'image') {
return this.req.resolution;
}
return null;
},
},
methods: {
checksum: async function (event, algo) {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit a09dfa8

Please sign in to comment.