Add a basic HTML interface
This commit is contained in:
parent
257712bfae
commit
831b361eda
|
@ -0,0 +1,128 @@
|
|||
<!Doctype HTML>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #201b27;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
#thumbnails {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 30px;
|
||||
justify-content: center;
|
||||
}
|
||||
.thumbnail-card {
|
||||
height: 400px;
|
||||
}
|
||||
#focused-panel {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: rgba(0, 0, 0, 60%);
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
}
|
||||
#focused-panel > img {
|
||||
max-height: 80vh;
|
||||
max-width: 60vw;
|
||||
padding: 50px;
|
||||
}
|
||||
#spinner {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
#loader-text {
|
||||
position: absolute;
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto auto;
|
||||
text-align: center;
|
||||
font-size: 31px;
|
||||
}
|
||||
|
||||
/* Yoinked from https://codepen.io/AdamDipinto/pen/eYOaGvY
|
||||
with modifications */
|
||||
.loader {
|
||||
position: relative;
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(#ff52bf, #f1f1f1, #1ed3ec);
|
||||
animation: animate 1.2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes animate {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.loader span {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(#ff52bf, #f1f1f1, #1ed3ec);
|
||||
}
|
||||
|
||||
.loader span:nth-child(1) {
|
||||
filter: blur(5px);
|
||||
}
|
||||
|
||||
.loader span:nth-child(2) {
|
||||
filter: blur(10px);
|
||||
}
|
||||
|
||||
.loader span:nth-child(3) {
|
||||
filter: blur(25px);
|
||||
}
|
||||
|
||||
.loader span:nth-child(4) {
|
||||
filter: blur(50px);
|
||||
}
|
||||
|
||||
.loader:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
right: 10px;
|
||||
bottom: 10px;
|
||||
background: #201b27;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
<script src="/index.js"></script>
|
||||
<script src="https://unpkg.com/rescript-blurhash@0.4.0/dist/production.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="spinner">
|
||||
<div class="loader">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
<div id="loader-text">Downloading<br/>Gallery...</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,6 +1,7 @@
|
|||
module Main where
|
||||
|
||||
import Prelude
|
||||
import Aviary.FFI (removeSpinner)
|
||||
import Aviary.UI (component)
|
||||
import Aviary.Logic (fetch_and_decrypt_gallery, get_parameters)
|
||||
import Aviary.Model (Model(..))
|
||||
|
@ -8,6 +9,7 @@ import Aviary.Model (Model(..))
|
|||
import Data.Either (Either(..))
|
||||
import Effect (Effect)
|
||||
import Effect.Aff (Aff, launchAff)
|
||||
import Effect.Class (liftEffect)
|
||||
import Halogen.Aff (awaitBody)
|
||||
import Halogen.VDom.Driver (runUI)
|
||||
|
||||
|
@ -18,6 +20,7 @@ main_aff = do
|
|||
gallery <- case parameters of
|
||||
Left e -> pure $ GError e
|
||||
Right parameters' -> fetch_and_decrypt_gallery parameters'
|
||||
_ <- liftEffect $ removeSpinner
|
||||
_ <- runUI (component gallery) unit body
|
||||
pure unit
|
||||
|
||||
|
|
14
src/UI.purs
14
src/UI.purs
|
@ -25,6 +25,7 @@ data Event = LoadThumbs
|
|||
| ThumbLoaded Int ImageData
|
||||
| FullLoaded Int ImageData
|
||||
| Focus Int
|
||||
| Unfocus
|
||||
|
||||
component :: forall query input. Model -> H.Component query input Event Aff
|
||||
component initialState = H.mkComponent
|
||||
|
@ -52,8 +53,8 @@ renderThumbnail pos image =
|
|||
renderFocused :: forall m. Image -> H.ComponentHTML Event () m
|
||||
renderFocused image =
|
||||
HH.div
|
||||
[ HP.class_ $ ClassName "focused-panel"
|
||||
, HP.class_ $ ClassName "visible"
|
||||
[ HP.id $ "focused-panel"
|
||||
, HE.onClick \_ -> Unfocus
|
||||
]
|
||||
( [ HH.img $
|
||||
maybe [] (HP.src >>> pure) (fullOrBlurhash image)
|
||||
|
@ -107,11 +108,18 @@ update (Focus newFocus) = do
|
|||
Just focusedImage' -> fetchFullAction newFocus focusedImage'
|
||||
Nothing ->
|
||||
H.put $ GError $ UnexpectedError "Focus event raised with an out of bounds index!"
|
||||
update Unfocus = H.modify_ \model -> case model of
|
||||
GError e -> GError e
|
||||
GLoaded gal -> GLoaded gal { focus = Nothing }
|
||||
|
||||
render :: forall m. Model -> H.ComponentHTML Event () m
|
||||
render (GError e) = HH.p_ [ HH.text $ show e ]
|
||||
render (GLoaded {title, desc, images, focus}) = HH.div_
|
||||
((maybe [] (HH.text >>> pure >>> HH.h1_ >>> pure) title) <>
|
||||
(maybe [] (HH.text >>> pure >>> HH.p_ >>> pure) desc) <>
|
||||
(mapWithIndex renderThumbnail images) <>
|
||||
[ HH.div
|
||||
[ HP.id "thumbnails"
|
||||
]
|
||||
(mapWithIndex renderThumbnail images)
|
||||
] <>
|
||||
(maybe [] (renderFocused >>> pure) (index images =<< focus)))
|
||||
|
|
|
@ -21,3 +21,7 @@ export function decodeBlurhashImpl(just) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function removeSpinner() {
|
||||
document.getElementById("spinner").remove()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
module Aviary.FFI where
|
||||
|
||||
import Prelude
|
||||
|
||||
import Data.ArrayBuffer.Types (ArrayBuffer)
|
||||
import Data.Maybe (Maybe(..))
|
||||
import Effect (Effect)
|
||||
import Web.File.Blob (Blob)
|
||||
|
||||
-- mimeType :: String
|
||||
|
@ -15,3 +18,5 @@ decodeBlurhash :: Int -> Int -> String -> Maybe String
|
|||
decodeBlurhash = decodeBlurhashImpl Just Nothing
|
||||
decodeBlurhash32 :: String -> Maybe String
|
||||
decodeBlurhash32 = decodeBlurhash 32 32
|
||||
|
||||
foreign import removeSpinner :: Effect Unit
|
||||
|
|
Loading…
Reference in New Issue