add nsfw warning dialog

This commit is contained in:
Rhiannon Morris 2020-10-06 22:07:39 +02:00
parent d671a4c01e
commit c807895244
12 changed files with 346 additions and 102 deletions

View File

@ -4,6 +4,7 @@ module GalleryPage (make) where
import BuilderQQ
import Date
import Info
import qualified NsfwWarning
import Data.Foldable
import Data.Function (on, (&))
@ -38,45 +39,50 @@ make' root (GalleryInfo {title, desc, prefix, filters, hidden}) infos = [b|@0
<meta name=twitter:card content=summary>
<script src=/script/gallery.js></script>
$0.nsfwScript
<title>$title</title>
<header>
<h1>$title</h1>
<h2 class="right corner">
<a href=rss.xml>rss</a>
</h2>
</header>
$0.nsfwDialog
<nav id=filters>
<details id=filters-details>
<summary><h2>filters</h2></summary>
<div>
<h3>show only</h3>
<ul id=require class="buttonbar bb-choice">
$8.requireFilters
</ul>
<div class=page>
<header>
<h1>$title</h1>
<h2 class="right corner">
<a href=rss.xml>rss</a>
</h2>
</header>
<h3>exclude</h3>
<ul id=exclude class="buttonbar bb-choice">
$8.excludeFilters
</ul>
<nav id=filters>
<details id=filters-details>
<summary><h2>filters</h2></summary>
<div>
<h3>show only</h3>
<ul id=require class="buttonbar bb-choice">
$10.requireFilters
</ul>
<a href=# id=clear>clear</a>
<a href=# id=singles>toggle single-use tags</a>
</div>
</details>
</nav>
<h3>exclude</h3>
<ul id=exclude class="buttonbar bb-choice">
$10.excludeFilters
</ul>
<main>
<ul class=grid>
$4.items
</ul>
</main>
<a href=# id=clear>clear</a>
<a href=# id=singles>toggle single-use tags</a>
</div>
</details>
</nav>
<footer>
<a href=$undir>all galleries</a>
</footer>
<main>
<ul class=grid>
$6.items
</ul>
</main>
<footer>
<a href=$undir>all galleries</a>
</footer>
</div>
|]
where
items = map (uncurry $ makeYearItems nsfw) infosByYear
@ -106,8 +112,11 @@ make' root (GalleryInfo {title, desc, prefix, filters, hidden}) infos = [b|@0
| (_, (p0, i0) : _) : _ <- infosByYear = getThumb (takeDirectory p0) i0
| otherwise = "/style/card.png"
nsfwScript = NsfwWarning.script nsfw
nsfwDialog = NsfwWarning.dialog nsfw
makeFilter :: Text -> HashSet Text -> Text -> Int -> Builder
makeFilter prefix initial tag count = [b|@8
makeFilter prefix initial tag count = [b|@0
<li>
<input type=checkbox id="$id'" value="$tag"$checked>
<label for="$id'" data-count=$count>$tag</label>
@ -121,17 +130,17 @@ makeYearItems :: Bool -- ^ nsfw
-> Int -- ^ year
-> [(FilePath, Info)]
-> Builder
makeYearItems nsfw year infos = [b|@4
makeYearItems nsfw year infos = [b|@0
<li class="item year-marker" id="marker-$year">
<span class=year-text>$year'</span>
$4.items
$0.items
|]
where
items = map (uncurry $ makeItem nsfw) infos
year' = show year & foldMap \c -> [b|<span class=y>$c</span>|]
makeItem :: Bool -> FilePath -> Info -> Builder
makeItem nsfw file info@(Info {title, bg}) = [b|@4
makeItem nsfw file info@(Info {title, bg}) = [b|@0
<li class="item post$nsfw'" data-date="$date'" data-year=$year'
data-updated="$updated'"
data-tags="$tags'">

View File

@ -27,30 +27,32 @@ make' root (IndexInfo {title, desc, galleries, links, footer}) = [b|@0
<title>$title</title>
<header>
<h1 id=title>$title</h1>
</header>
<div class=page>
<header>
<h1 id=title>$title</h1>
</header>
<main>
$galleryList
$linkList
</main>
<main>
$4.galleryList
$4.linkList
</main>
$footer'
$2.footer'
</div>
|]
where
galleryList = if null galleries then "" else [b|@2
galleryList = if null galleries then "" else [b|@0
<nav aria-label="gallery list">
<ul id=gallery-list class=list>
$6.items
$4.items
</ul>
</nav>
|]
where items = map makeItem galleries
linkList = if null links then "" else [b|@2
linkList = if null links then "" else [b|@0
<nav aria-label="other links">
<ul id=link-list class=list>
$6.items
$4.items
</ul>
</nav>
|]
@ -65,13 +67,13 @@ make' root (IndexInfo {title, desc, galleries, links, footer}) = [b|@0
url = [b|$root|]
makeItem :: GalleryInfo -> Builder
makeItem (GalleryInfo {title, desc, prefix, filters}) = [b|@6
makeItem (GalleryInfo {title, desc, prefix, filters}) = [b|@0
<li$nsfw><a href=$prefix title="$desc">$title</a></li>
|]
where nsfw = if hasNsfw filters then [b| class=nsfw|] else ""
makeLink :: Link -> Builder
makeLink (Link {title, url, nsfw}) = [b|@6
makeLink (Link {title, url, nsfw}) = [b|@0
<li$nsfw'><a href=$url>$title</a>
|]
where nsfw' = if nsfw then [b| class=nsfw|] else ""

30
make-pages/NsfwWarning.hs Normal file
View File

@ -0,0 +1,30 @@
{-# OPTIONS_GHC -fdefer-typed-holes #-}
module NsfwWarning (script, dialog) where
import BuilderQQ
script :: Bool -> Builder
script False = ""
script True = [b|<script src=/script/nsfw-warning.js></script>|]
dialog :: Bool -> Builder
dialog False = ""
dialog True = [b|@0
<div class=dialog id=nsfw-dialog>
<div class=dialog-inner>
<h1>cw: lewd</h1>
<img class=dialog-icon src=/style/stop_hand.svg>
<div class=dialog-message>
are you an adult? <br> if not please don't look!
</div>
<div class=dialog-buttons>
<button id=nsfw-yes class=yes>yes i am and i wanna see</button>
<button id=nsfw-no class=no>no im not</button>
</div>
</div>
</div>
|]

View File

@ -4,6 +4,7 @@ import Date
import Info
import BuilderQQ
import Records ()
import qualified NsfwWarning
import Control.Exception
import qualified Data.Map.Strict as Map
@ -60,7 +61,7 @@ make' root prefix nsfw dataDir dir
let makePrefetch (Image {path}) = [b|<link rel=prefetch href=$path>|]
let prefetches = map (makePrefetch . #first) $ tail images
let makeWarning w = [b|@4
let makeWarning w = [b|@0
<figcaption id=cw aria-role=button tabindex=0>
<span id=cw-text>$w</span>
</figcaption>
@ -82,6 +83,9 @@ make' root prefix nsfw dataDir dir
let updateDate = ifJust (Map.lookupMax updates) \(formatLong -> u, _) ->
[b|<br> <span class=updated>updated $u</span>|]
let nsfwScript = NsfwWarning.script nsfw
let nsfwDialog = NsfwWarning.dialog nsfw
pure [b|@0
<!DOCTYPE html>
<html lang=en>
@ -100,44 +104,49 @@ make' root prefix nsfw dataDir dir
<meta name=twitter:card content=summary>
<script src=/script/single.js></script>
$nsfwScript
$bgStyle
$0.prefetches
<title>$title</title>
<header>
<h1>$title</h1>
$artistTag
<h2 id=date class="right corner">
$formattedDate $updateDate
</h2>
</header>
$nsfwDialog
$buttonBar
<div class=page>
<header>
<h1>$title</h1>
$artistTag
<h2 id=date class="right corner">
$formattedDate $updateDate
</h2>
</header>
<main>
<figure id=mainfig data-width=$width0 data-height=$height0>
$warning'
<a id=mainlink href="$download0" title="download full version">
<img id=mainimg src="$path0'" alt="">
</a>
</figure>
$2.buttonBar
<div id=info>
$descSection
<main>
<figure id=mainfig data-width=$width0 data-height=$height0>
$warning'
<a id=mainlink href="$download0" title="download full version">
<img id=mainimg src="$path0'" alt="">
</a>
</figure>
$tagsList
<div id=info>
$6.descSection
$linksList
$6.tagsList
$updatesList
</div>
</main>
$6.linksList
<footer>
<a href=$undir>back to gallery</a>
</footer>
$6.updatesList
</div>
</main>
<footer>
<a href=$undir>back to gallery</a>
</footer>
</div>
<template id=cw-template>
$warningT
@ -153,11 +162,11 @@ makeArtist (Artist {name, url}) =
Nothing -> [b|$name|]
makeDesc :: Maybe Strict.Text -> Builder
makeDesc mdesc = ifJust mdesc \desc -> [b|@4
makeDesc mdesc = ifJust mdesc \desc -> [b|@0
<section id=desc class=info-section>
<h2>about</h2>
<div>
$8.desc
$4.desc
</div>
</section>
|]
@ -177,7 +186,7 @@ makeButtonBar title images =
where alts = map (\(i, (im, sz)) -> altButton i im sz) $ zip [0..] images
altButton :: Int -> Image -> Size -> Builder
altButton i (Image {label, path, nsfw, warning}) (Size {width, height}) = [b|@4
altButton i (Image {label, path, nsfw, warning}) (Size {width, height}) = [b|@0
<li$nsfwClass>
<input type=radio$checked name=variant id="$idLabel" value="$path'"
data-link="$path"$warning'
@ -194,11 +203,11 @@ altButton i (Image {label, path, nsfw, warning}) (Size {width, height}) = [b|@4
makeTags :: FilePath -> [Strict.Text] -> Builder
makeTags undir tags =
if null tags then "" else [b|@4
if null tags then "" else [b|@0
<nav id=tags class=info-section>
<h2>tags</h2>
<ul class="buttonbar bb-links">
$8.tagList
$4.tagList
</ul>
</nav>
|]
@ -209,11 +218,11 @@ makeTags undir tags =
extLinks :: [Link] -> Builder
extLinks links =
if null links then "" else [b|@4
if null links then "" else [b|@0
<nav id=links class=info-section>
<h2>links</h2>
<ul class="buttonbar bb-links">
$8.linkList
$4.linkList
</ul>
</nav>
|]

View File

@ -15,16 +15,17 @@ executable make-pages
main-is: Main.hs
other-modules:
BuilderQQ,
Date,
Depend,
GalleryPage,
Info,
IndexPage,
ListTags,
Options,
Records,
Date,
Info,
Depend,
NsfwWarning,
GalleryPage,
IndexPage,
SinglePage,
RSS
RSS,
ListTags,
Options
default-language: Haskell2010
default-extensions:
BlockArguments,

35
script/nsfw-warning.js Normal file
View File

@ -0,0 +1,35 @@
(function () {
'use strict';
let nsfwOk = 'nsfw-ok';
function alreadyYes() {
return sessionStorage.getItem(nsfwOk);
}
function dismiss() {
let dialog = document.getElementById('nsfw-dialog');
dialog.parentElement.removeChild(dialog);
}
function yes() {
sessionStorage.setItem(nsfwOk, 1);
dismiss();
}
function no() {
history.go(-1);
}
function setup() {
if (alreadyYes()) {
dismiss();
} else {
document.getElementById('nsfw-yes').onclick = yes;
document.getElementById('nsfw-no').onclick = no;
}
}
document.addEventListener('DOMContentLoaded', setup);
})();

View File

@ -17,6 +17,13 @@
--focus-box: 0 0 20px hsl(55deg, 60%, 90%, 80%);
--focus-text: hsl(334deg, 87%, 90%);
--shadow-col: hsl(42deg, 82%, 90%, 75%);
--border-col: var(--text-col);
--border: 3px solid var(--border-col);
--border-radius: 1.5em;
--shadow: 0 0 3em var(--shadow-col);
--background: hsla(0, 0%, 0%, 60%);
font-family: Muller;
font-size: x-large;
font-weight: 600;
@ -35,18 +42,15 @@ h1 { font-size: 300%; }
h2 { font-size: 125%; }
h3 { font-size: 110%; }
body {
--shadow: hsl(42deg, 82%, 90%, 75%);
--border-col: var(--text-col);
background: hsla(0, 0%, 0%, 60%);
border: 3px solid var(--border-col);
box-shadow: 0 0 3em var(--shadow);
.page {
background: var(--background);
border: var(--border);
box-shadow: var(--shadow);
position: relative;
padding: 2em 4em;
margin: 3em auto 3.5em;
border-radius: 1.5em;
border-radius: var(--border-radius);
color: var(--text-col);
--text-shadow: 2px 2px 3px hsl(0, 0%, 0%, 75%);
@ -207,7 +211,7 @@ dd + dt {
}
body {
--shadow: hsl(42deg, 82%, 90%, 20%);
--shadow-col: hsl(42deg, 82%, 90%, 20%);
--border-col: black;
}

View File

@ -1,10 +1,11 @@
@import url(base.css);
@import url(nsfw-warning.css);
:root {
--image-size: 200px;
}
body {
.page {
--gap: 1em;
max-width: calc(4 * var(--image-size) + 3 * var(--gap));
padding-left: 4em;

View File

@ -7,7 +7,7 @@
justify-content: center;
}
body {
.page {
width: 37.5em;
}

View File

@ -0,0 +1,78 @@
.dialog {
position: fixed;
top: 0; left: 0;
width: 100vw; height: 100vh;
margin: 0;
z-index: 1000;
background: hsl(340deg, 35%, 15%, 90%);
backdrop-filter: blur(15px);
color: var(--text-col);
display: grid;
}
.dialog-inner {
place-self: center;
display: grid;
grid-template:
"header header"
"icon text"
"buttons buttons"
/ 1fr 3fr;
grid-gap: 0.5em;
align-items: center;
min-height: 20vh;
max-width: 60vw;
padding: 1.5em 3em 2em;
background: var(--background);
border: var(--border);
border-radius: var(--border-radius);
}
.dialog h1 {
margin: 0;
grid-area: header;
justify-self: center;
}
.dialog-icon {
height: 3em;
width: 3em;
grid-area: icon;
justify-self: center;
}
.dialog-message {
grid-area: text;
justify-self: start;
}
.dialog-buttons {
grid-area: buttons;
justify-self: center;
}
.dialog button + button {
margin-left: 1em;
}
.dialog button {
border: none;
border-radius: 0.75em;
padding: 0.5em 1em;
font-family: Muller;
font-weight: 600;
color: black;
}
button.yes {
background: hsl(100deg, 70%, 80%);
}
button.no {
background: hsl(5deg, 70%, 80%);
}

View File

@ -1,10 +1,11 @@
@import url(base.css);
@import url(nsfw-warning.css);
:root {
--image-width: 1000px;
}
body {
.page {
max-width: var(--image-width);
}

74
style/stop_hand.svg Normal file
View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
clip-rule="evenodd"
fill-rule="evenodd"
stroke-linejoin="round"
stroke-miterlimit="2"
viewBox="0 0 32 32"
version="1.1"
id="svg17"
sodipodi:docname="hand_paw_c2.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<defs
id="defs21" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="711"
inkscape:window-height="480"
id="namedview19"
showgrid="false"
inkscape:zoom="7.375"
inkscape:cx="16"
inkscape:cy="16"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="g15" />
<clipPath
id="a">
<path
clip-rule="evenodd"
d="m0 0h32v32h-32z"
id="path2" />
</clipPath>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<path
d="m0 0h32v32h-32z"
fill="none"
id="path7" />
<g
clip-path="url(#a)"
id="g15">
<path
d="m11.414 2.609c.714-1.542 2.276-2.613 4.086-2.613 1.914 0 3.551 1.198 4.201 2.885 1.043-.77 2.41-1.085 3.764-.747 2.41.603 3.877 3.048 3.275 5.457l-1.701 6.805c1.822-.775 4.012-.42 5.496 1.065 1.952 1.951 1.952 5.119 0 7.071 0 0-3.608 3.608-5.979 5.979-2.234 2.234-5.264 3.489-8.423 3.489h-.133v-.004h-1.035c-5.571 0-10.426-3.79-11.778-9.194-1.19-4.754-2.68-10.71-2.68-10.71-.603-2.409.863-4.854 3.272-5.457.293-.074.586-.116.877-.131-.004-2.126 1.507-4.021 3.671-4.427 1.103-.207 2.187.009 3.087.532z"
id="path9" />
<path
d="m13 4.493c.002-.313.059-.622.173-.913.189-.478.526-.891.955-1.173.211-.14.444-.247.688-.316.263-.075.539-.106.813-.092.279.015.556.076.816.182.288.118.554.291.779.506.233.221.422.488.555.781.146.323.219.673.221 1.028v8.689.315c.001.067.013.133.039.195.081.191.279.315.487.304.058-.003.115-.016.169-.038.055-.024.106-.058.15-.099.046-.044.084-.098.111-.156.029-.065.043-.135.044-.206v-3.812l.949-3.794c.334-1.339 1.693-2.154 3.031-1.819 1.339.334 2.154 1.693 1.819 3.031l-2.799 11.198v1.449l2.879-2.878c1.17-1.171 3.071-1.171 4.242 0s1.171 3.072 0 4.242c0 0-3.608 3.609-5.979 5.98-1.859 1.859-4.38 2.903-7.009 2.903h-.133v-.004h-1.039c-4.65 0-8.705-3.163-9.836-7.674-1.193-4.755-2.687-10.714-2.687-10.714-.336-1.338.478-2.697 1.817-3.033.664-.166 1.333-.05 1.879.273l1.123 6.734c.012.07.038.137.077.196.036.053.082.1.135.136.05.034.106.058.165.072.056.014.115.017.173.011.206-.024.381-.178.429-.381.016-.065.017-.132.007-.198l-1.554-9.324c.01-.062.023-.124.038-.185.076-.312.213-.609.401-.87.182-.253.411-.471.673-.64.236-.152.496-.264.769-.329.266-.064.543-.085.815-.06.253.023.501.085.735.183.473.199.881.543 1.154.978.167.266.28.56.339.868l.387 2.062v5.899c.001.067.013.133.039.195.081.191.279.315.487.304.058-.003.115-.016.169-.038.055-.024.106-.058.15-.099.046-.044.084-.098.111-.156.029-.065.043-.135.044-.206z"
fill="#00e2d7"
id="path11" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB