diff options
-rw-r--r-- | lib/Crater/Gallery.rakumod | 51 | ||||
-rw-r--r-- | lib/Crater/Routes/Auth.rakumod | 1 | ||||
-rw-r--r-- | lib/Crater/Routes/Gallery.rakumod | 15 | ||||
-rw-r--r-- | resources/css/style.css | 32 | ||||
-rw-r--r-- | resources/js/gallery.js | 2 | ||||
-rw-r--r-- | 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<heading>, :text($_) ); + } + + # Add directories on top. + for @paths.grep(*.d) { + push @gallery, %( :type<directory>, + :text($_.relative($!directory)) ); + } - } elsif .IO.f { - my Str $ext = .extension.lc; - if $ext eq "jpg"|"png" { - push @gallery, %( - :type<img>, :src($_.relative($!directory)), - :alt($_) - ); - } elsif $ext eq "0" { - push @gallery, %( :type<heading>, :text($_.slurp) ); - } elsif $ext eq "txt" { - push @gallery, %( :type<text>, :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<img>, :src($rel), :$alt ); + } elsif $ext eq "0" { + push @gallery, %( :type<heading>, :text($_.slurp.chomp) ); + } elsif $ext eq "txt" { + push @gallery, %( :type<text>, :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)> + <noscript> + <div class="alert" role="alert">JavaScript required.</div> + </noscript> <div id="loading"> <label for="loading-progress">Loading Images:</label> <progress id="loading-progress" max="100" value="0"></progress> @@ -10,8 +13,11 @@ </div> <div id="gallery"> <@gallery : $i> + <?{ $i.<type> eq 'directory' }> + <div class="directory"><$i.<text>></div> + </?> <?{ $i.<type> eq 'img' }> - <img alt="<$i.<alt>>" src="<$i.<src>>" loading="lazy"> + <img alt="<$i.<alt>>" src="/resources/img/<$i.<src>>"> </?> <?{ $i.<type> eq 'text' }> <div class="text"><$i.<text>></div> |