From f156f380d4de118e31036e80144154bdcb664ed6 Mon Sep 17 00:00:00 2001 From: Andinus Date: Sat, 11 Jun 2022 13:59:33 +0530 Subject: Display gallery title, fix authentication, show directories - Earlier non-authenticated users could access the images too. - Serve original image if thumbnail doesn't exist. - Show directories in gallery. - Remove lazy loading attribute. --- lib/Crater/Gallery.rakumod | 51 +++++++++++++++++++++++++++------------ lib/Crater/Routes/Auth.rakumod | 1 - lib/Crater/Routes/Gallery.rakumod | 15 +++++++++--- resources/css/style.css | 32 ++++++++++++++++-------- resources/js/gallery.js | 2 +- templates/gallery.crotmp | 8 +++++- 6 files changed, 77 insertions(+), 32 deletions(-) diff --git a/lib/Crater/Gallery.rakumod b/lib/Crater/Gallery.rakumod index 19b0d69..448593f 100644 --- a/lib/Crater/Gallery.rakumod +++ b/lib/Crater/Gallery.rakumod @@ -1,25 +1,46 @@ class Crater::Gallery { has IO $.directory is required; + has Str $!title; + + submethod TWEAK() { + my $title-file = $!directory.add(".crater/title"); + $!title = $title-file.slurp.chomp if $title-file.f; + } + + #| Accessor for $!title. + method title() { $!title } method list() { my @gallery; - for $!directory.dir.sort(*.modified) { - if .IO.d { + my @paths = $!directory.dir; + + with $!title { + push @gallery, %( :type, :text($_) ); + } + + # Add directories on top. + for @paths.grep(*.d) { + push @gallery, %( :type, + :text($_.relative($!directory)) ); + } - } elsif .IO.f { - my Str $ext = .extension.lc; - if $ext eq "jpg"|"png" { - push @gallery, %( - :type, :src($_.relative($!directory)), - :alt($_) - ); - } elsif $ext eq "0" { - push @gallery, %( :type, :text($_.slurp) ); - } elsif $ext eq "txt" { - push @gallery, %( :type, :text($_.slurp) ); - } else { - warn "Unhandled file :$_"; + for @paths.grep(*.f).sort(*.modified) { + my Str $ext = .extension.lc; + # For images get the original if thumbnail doesn't exist, + # otherwise use the thumbnail. + if $ext eq "jpg"|"png" { + my $rel = $_.relative($!directory); + my $alt = $rel; + unless $!directory.add(".crater/thumbnails").add($rel).f { + $rel ~= "?original"; } + push @gallery, %( :type, :src($rel), :$alt ); + } elsif $ext eq "0" { + push @gallery, %( :type, :text($_.slurp.chomp) ); + } elsif $ext eq "txt" { + push @gallery, %( :type, :text($_.slurp.chomp) ); + } else { + note "Unhandled file: $_"; } } return @gallery; diff --git a/lib/Crater/Routes/Auth.rakumod b/lib/Crater/Routes/Auth.rakumod index 23872e9..73e6dc7 100644 --- a/lib/Crater/Routes/Auth.rakumod +++ b/lib/Crater/Routes/Auth.rakumod @@ -13,7 +13,6 @@ sub auth-routes( get -> Crater::Session $session, 'login' { template 'login.crotmp', { :!error }; } - post -> Crater::Session $session, 'login' { request-body -> (:$pass!, *%) { if $password eq $pass { diff --git a/lib/Crater/Routes/Gallery.rakumod b/lib/Crater/Routes/Gallery.rakumod index cf79cc6..aa3e4b6 100644 --- a/lib/Crater/Routes/Gallery.rakumod +++ b/lib/Crater/Routes/Gallery.rakumod @@ -8,6 +8,15 @@ sub gallery-routes( Crater::Gallery :$gallery!, #= gallery object ) is export { route { + # Logged in users can view images. + get -> LoggedIn $session, 'resources', 'img', *@path, :$original { + my $dir = $gallery.directory; + # Serve the thumbnail unless original image was requested. + $dir .= add(".crater/thumbnails") unless $original.defined; + static $dir, @path; + } + + # Gallery view. get -> LoggedIn $session { template 'gallery.crotmp', { gallery => $gallery.list(), @@ -15,11 +24,9 @@ sub gallery-routes( }; } - get -> { - redirect '/login', :see-other; - } + # Redirect to login page if not logged in. get -> *@path { - static $gallery.directory.add(".crater/thumbnails"), @path; + redirect '/login', :see-other; } } } diff --git a/resources/css/style.css b/resources/css/style.css index 76af98e..cc2cb3a 100644 --- a/resources/css/style.css +++ b/resources/css/style.css @@ -56,21 +56,20 @@ img { min-width: 30%; } -img, .text { width: 400px; } -.heading { width: 380px; } +img { width: 400px; } +.heading, .text, .directory { width: 380px; } @media only screen and (max-width: 512px) { - img, .text { width: 368px; } - .heading { width: 350px; } + img { width: 368px; } + .heading, .text, .directory { width: 350px; } } @media only screen and (max-width: 450px) { - img, .text { width: 350px; } - .heading { width: 330px; } + img { width: 350px; } + .heading, .text, .directory { width: 330px; } } @media only screen and (max-width: 400px) { - img, .text { width: 330px; } - .heading { width: 310px; } + img { width: 330px; } + .heading, .text, .directory { width: 310px; } } - .heading { box-shadow: var(--blue-intense-bg) 0px 0px 0px 2px inset, var(--bg-main) 10px -10px 0px -3px, @@ -83,7 +82,6 @@ img, .text { width: 400px; } var(--red-intense-bg) 40px -40px; padding: 1em; } - .text { box-shadow: var(--magenta-intense-bg) 0px 0px 0px 3px, var(--green-subtle-bg) 0px 0px 0px 6px, @@ -92,6 +90,20 @@ img, .text { width: 400px; } var(--red-intense-bg) 0px 0px 0px 15px; padding: 1em; } +.directory { + box-shadow: var(--bg-special-cold) 0px 0px 0px 3px, + var(--bg-special-calm) 0px 0px 0px 6px; + padding: 1em; +} +.directory:hover { + background-color: var(--bg-alt); +} +.directory:before { + content: '📁 '; +} +.directory:hover:before { + content: '📂 '; +} #gallery { margin: auto; diff --git a/resources/js/gallery.js b/resources/js/gallery.js index 2a608f5..5643ce2 100644 --- a/resources/js/gallery.js +++ b/resources/js/gallery.js @@ -71,7 +71,7 @@ const onImagesLoaded = (container, event) => { const gallery = document.getElementById("gallery"); const imagesLoaded = (remaining, failed, progressBar) => { - bricks.pack(); + bricks.pack(); // packing images progressBar.value = 100; document.getElementById("loading").style.display = "none"; diff --git a/templates/gallery.crotmp b/templates/gallery.crotmp index 6aead73..253339e 100644 --- a/templates/gallery.crotmp +++ b/templates/gallery.crotmp @@ -1,5 +1,8 @@ <:use 'templates/base.crotmp'> <|page(.title)> +
@@ -10,8 +13,11 @@