Play icon overlay for video thumbnails + responsive mobile design

pull/3/head
Toni Melisma 4 years ago
parent 2d0aacf211
commit a3553a4dc9
No known key found for this signature in database
GPG Key ID: FFF9A7EDDEA34756

@ -6,6 +6,7 @@
- Deals with any file formats (ncluding HEIC, HEVC) - Deals with any file formats (ncluding HEIC, HEVC)
- Only updates changed files, runs incrementally - Only updates changed files, runs incrementally
- Uses relative paths (safe for using in subdirectory or S3) - Uses relative paths (safe for using in subdirectory or S3)
- Minimal bloat (no third party frontend libraries, minimal CSS)
*Please note that fastgallery is still pre-alpha, I am actively working on it* *Please note that fastgallery is still pre-alpha, I am actively working on it*
@ -34,3 +35,8 @@ Then, for dependencies, install libvips42 for images and optionally ffmpeg (if y
## Roadmap ## Roadmap
For the prioritised roadmap, please see https://github.com/tonimelisma/fastgallery/projects/1 For the prioritised roadmap, please see https://github.com/tonimelisma/fastgallery/projects/1
## Third party libraries
- (govips)[https://github.com/davidbyttow/govips], lightning fast image processing and resizing library
- (Feather)[https://github.com/feathericons/feather] icons, simple and beautiful
- (Primer)[https://github.com/primer/css] CSS, Github's in-house design system

@ -16,6 +16,9 @@ import (
"github.com/davidbyttow/govips/v2/vips" "github.com/davidbyttow/govips/v2/vips"
) )
// assets
const assetPlaybuttonImage = "/home/toni/go/src/github.com/tonimelisma/fastgallery/assets/playbutton.png"
// global defaults // global defaults
const optSymlinkDir = "_original" const optSymlinkDir = "_original"
const optFullsizeDir = "_pictures" const optFullsizeDir = "_pictures"
@ -438,12 +441,30 @@ func resizeThumbnailVideo(source string, destination string) {
ffmpegCommand.Stdout = os.Stdout ffmpegCommand.Stdout = os.Stdout
ffmpegCommand.Stderr = os.Stderr ffmpegCommand.Stderr = os.Stderr
// TODO overlay triangle to thumbnail to implicate it's video instead of image
err := ffmpegCommand.Run() err := ffmpegCommand.Run()
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Could create thumbnail of video %s", source) fmt.Fprintf(os.Stderr, "Could not create thumbnail of video %s", source)
} }
// Take thumbnail and overlay triangle image on top of it
image, err := vips.NewImageFromFile(destination)
checkError(err)
// TODO don't load overlay separately
playbuttonOverlayImage, err := vips.NewImageFromFile(assetPlaybuttonImage)
checkError(err)
// overlay play button in the middle of thumbnail picture
err = image.Composite(playbuttonOverlayImage, vips.BlendModeSource, (thumbnailWidth/2)-(playbuttonOverlayImage.Width()/2), (thumbnailHeight/2)-(playbuttonOverlayImage.Height()/2))
checkError(err)
ep := vips.NewDefaultJPEGExportParams()
imageBytes, _, err := image.Export(ep)
checkError(err)
err = ioutil.WriteFile(destination, imageBytes, optFileMode)
checkError(err)
} }
func resizeFullsizeVideo(source string, destination string) { func resizeFullsizeVideo(source string, destination string) {
@ -453,7 +474,7 @@ func resizeFullsizeVideo(source string, destination string) {
err := ffmpegCommand.Run() err := ffmpegCommand.Run()
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Could create full-size video of %s", source) fmt.Fprintf(os.Stderr, "Could not create full-size video of %s", source)
} }
} }

@ -9,7 +9,7 @@
#modalHeader, #modalHeader,
#modalFooter { #modalFooter {
width: 500px; min-width: 300px;
} }
.modalControl:hover, .modalControl:hover,

@ -14,57 +14,81 @@
<!-- Thumbnail view. First subfolders, then media. --> <!-- Thumbnail view. First subfolders, then media. -->
<div class="container-xl"> <div class="container-xl">
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0">
<a href="temp2"> <a href="temp2">
<img class="width-fit" src="_thumbnails/temp2/2018-10-14 15.59.20.jpg" alt="diipadaapa"> <img class="width-fit" src="_thumbnails/temp2/2018-10-14 15.59.20.jpg" alt="diipadaapa">
</a> </a>
<span class="width-fit css-truncate css-truncate-target p-1">temp2</span> <span class="width-fit css-truncate css-truncate-target p-1">temp2</span>
</div> </div>
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0" onclick="changePicture(0);displayModal(true);"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(0);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-03-31 16.48.28.jpg" alt="2018-03-31 16.48.28.jpg"> <img class="width-fit" src="_thumbnails/2018-03-31 16.48.28.jpg" alt="2018-03-31 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-03-31 16.48.28.jpg</span> <span class="width-fit css-truncate css-truncate-target p-1">2018-03-31 16.48.28.jpg</span>
</div> </div>
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0" onclick="changePicture(1);displayModal(true);"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(1);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-07-16 17.28.12 -000.jpg" alt="2018-03-31 16.48.28.jpg"> <img class="width-fit" src="_thumbnails/2018-07-16 17.28.12 -000.jpg" alt="2018-03-31 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span> <span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span>
</div> </div>
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0" onclick="changePicture(2);displayModal(true);"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(2);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-11-10 12.36.05.jpg" alt="2018-11-10 16.48.28.jpg"> <img class="width-fit" src="_thumbnails/2018-11-10 12.36.05.jpg" alt="2018-11-10 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span> <span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span>
</div> </div>
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0" onclick="changePicture(3);displayModal(true);"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(3);displayModal(true);">
<img class="width-fit" src="_thumbnails/2016-05-01 18.20.21.jpg" alt="2016-05-01 18.20.21.jpg"> <img class="width-fit" src="_thumbnails/2016-05-01 18.20.21.jpg" alt="2016-05-01 18.20.21.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2016-05-01 18.20.21</span> <span class="width-fit css-truncate css-truncate-target p-1">2016-05-01 18.20.21</span>
</div> </div>
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0" onclick="changePicture(0);displayModal(true);"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(0);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-03-31 16.48.28.jpg" alt="2018-03-31 16.48.28.jpg"> <img class="width-fit" src="_thumbnails/2018-03-31 16.48.28.jpg" alt="2018-03-31 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-03-31 16.48.28.jpg</span> <span class="width-fit css-truncate css-truncate-target p-1">2018-03-31 16.48.28.jpg</span>
</div> </div>
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0" onclick="changePicture(1);displayModal(true);"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(1);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-07-16 17.28.12 -000.jpg" alt="2018-03-31 16.48.28.jpg"> <img class="width-fit" src="_thumbnails/2018-07-16 17.28.12 -000.jpg" alt="2018-03-31 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span> <span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span>
</div> </div>
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0" onclick="changePicture(2);displayModal(true);"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(2);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-11-10 12.36.05.jpg" alt="2018-11-10 16.48.28.jpg"> <img class="width-fit" src="_thumbnails/2018-11-10 12.36.05.jpg" alt="2018-11-10 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span> <span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span>
</div> </div>
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0" onclick="changePicture(3);displayModal(true);"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(3);displayModal(true);">
<img class="width-fit" src="_thumbnails/2016-05-01 18.20.21.jpg" alt="2016-05-01 18.20.21.jpg"> <img class="width-fit" src="_thumbnails/2016-05-01 18.20.21.jpg" alt="2016-05-01 18.20.21.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2016-05-01 18.20.21</span> <span class="width-fit css-truncate css-truncate-target p-1">2016-05-01 18.20.21</span>
</div> </div>
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0" onclick="changePicture(0);displayModal(true);"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(0);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-03-31 16.48.28.jpg" alt="2018-03-31 16.48.28.jpg"> <img class="width-fit" src="_thumbnails/2018-03-31 16.48.28.jpg" alt="2018-03-31 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-03-31 16.48.28.jpg</span> <span class="width-fit css-truncate css-truncate-target p-1">2018-03-31 16.48.28.jpg</span>
</div> </div>
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0" onclick="changePicture(1);displayModal(true);"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(1);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-07-16 17.28.12 -000.jpg" alt="2018-03-31 16.48.28.jpg"> <img class="width-fit" src="_thumbnails/2018-07-16 17.28.12 -000.jpg" alt="2018-03-31 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span> <span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span>
</div> </div>
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0" onclick="changePicture(2);displayModal(true);"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(2);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-11-10 12.36.05.jpg" alt="2018-11-10 16.48.28.jpg"> <img class="width-fit" src="_thumbnails/2018-11-10 12.36.05.jpg" alt="2018-11-10 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span> <span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span>
</div> </div>
<div class="col-2 d-inline-block box border border-gray box-shadow m-3 p-0" onclick="changePicture(3);displayModal(true);"> <div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(0);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-03-31 16.48.28.jpg" alt="2018-03-31 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-03-31 16.48.28.jpg</span>
</div>
<div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(1);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-07-16 17.28.12 -000.jpg" alt="2018-03-31 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span>
</div>
<div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(2);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-11-10 12.36.05.jpg" alt="2018-11-10 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span>
</div>
<div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(0);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-03-31 16.48.28.jpg" alt="2018-03-31 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-03-31 16.48.28.jpg</span>
</div>
<div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(1);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-07-16 17.28.12 -000.jpg" alt="2018-03-31 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span>
</div>
<div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(2);displayModal(true);">
<img class="width-fit" src="_thumbnails/2018-11-10 12.36.05.jpg" alt="2018-11-10 16.48.28.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2018-07-16 17.28.12 -000.jpg</span>
</div>
<div class="col-sm-4 col-md-3 col-lg-2 d-inline-block box border border-gray box-shadow m-md-1 m-lg-2 p-0" onclick="changePicture(3);displayModal(true);">
<img class="width-fit" src="_thumbnails/2016-05-01 18.20.21.jpg" alt="2016-05-01 18.20.21.jpg"> <img class="width-fit" src="_thumbnails/2016-05-01 18.20.21.jpg" alt="2016-05-01 18.20.21.jpg">
<span class="width-fit css-truncate css-truncate-target p-1">2016-05-01 18.20.21</span> <span class="width-fit css-truncate css-truncate-target p-1">2016-05-01 18.20.21</span>
</div> </div>
@ -77,14 +101,14 @@
fix order of header icons, picture height --> fix order of header icons, picture height -->
<div class="position-fixed top-0 left-0 width-full height-full d-flex flex-column flex-justify-center flex-items-center box border border-gray box-shadow p-0 bg-gray" id="modal" hidden> <div class="position-fixed top-0 left-0 width-full height-full d-flex flex-column flex-justify-center flex-items-center box border border-gray box-shadow p-0 bg-gray" id="modal" hidden>
<div class="bg-gray clearfix position-absolute top-0 " id="modalHeader"> <div class="bg-gray clearfix position-absolute top-0 " id="modalHeader">
<div class="float-right modalControl d-inline-block" onclick="displayModal(false);">
<i data-feather="x"></i>
</div>
<div class="float-right modalControl d-inline-block"> <div class="float-right modalControl d-inline-block">
<a href="#" id="modalDownload" download> <a href="#" id="modalDownload" download>
<i data-feather="download"></i> <i data-feather="download"></i>
</a> </a>
</div> </div>
<div class="float-right modalControl d-inline-block" onclick="displayModal(false);">
<i data-feather="x"></i>
</div>
</div> </div>
<img id="modalPicture"> <img id="modalPicture">
<div class="bg-gray position-absolute bottom-0" id="modalFooter"> <div class="bg-gray position-absolute bottom-0" id="modalFooter">

Loading…
Cancel
Save