aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/Gallery.hs
blob: 1fa40366ad142db9dd390f1ebf5c52f83f1f13aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
-- ldgallery - A static generator which turns a collection of tagged
--             pictures into a searchable web gallery.
--
-- Copyright (C) 2019  Pacien TRAN-GIRARD
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Affero General Public License as
-- published by the Free Software Foundation, either version 3 of the
-- License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU Affero General Public License for more details.
--
-- You should have received a copy of the GNU Affero General Public License
-- along with this program.  If not, see <https://www.gnu.org/licenses/>.

{-# LANGUAGE
    DuplicateRecordFields
  , DeriveGeneric
  , DeriveAnyClass
#-}

module Gallery
  ( GalleryItem(..), buildGallery
  ) where


import GHC.Generics (Generic)
import Data.Char (toLower)
import Data.Function ((&))
import Data.Maybe (fromMaybe)

import Data.Aeson (ToJSON, genericToJSON, genericToEncoding)
import qualified Data.Aeson as JSON

import qualified Data.Set as Set

import Files
import Input
import Resource


encodingOptions :: JSON.Options
encodingOptions = JSON.defaultOptions
  { JSON.fieldLabelModifier = map toLower
  , JSON.constructorTagModifier = map toLower
  , JSON.sumEncoding = JSON.defaultTaggedObject
      { JSON.tagFieldName = "type"
      , JSON.contentsFieldName = "contents"
      }
  }


type ResourcePath = String
type Tag = String
type FileSizeKB = Int


data Resolution = Resolution
  { width :: Int
  , height :: Int
  } deriving (Generic, Show)

instance ToJSON Resolution where
  toJSON = genericToJSON encodingOptions
  toEncoding = genericToEncoding encodingOptions


data GalleryItemProps =
    Directory { items :: [GalleryItem] }
--  | Image { resolution :: Resolution, filesize :: FileSizeKB }
--  | Video { filesize :: FileSizeKB }
  | Unknown
  deriving (Generic, Show)

instance ToJSON GalleryItemProps where
  toJSON = genericToJSON encodingOptions
  toEncoding = genericToEncoding encodingOptions


-- TODO: fuse GalleryItem and GalleryItemProps
data GalleryItem = GalleryItem
  { title :: String
  , date :: String -- TODO: checked ISO8601 date
  , description :: String
  , tags :: [Tag]
  , path :: ResourcePath
  , thumbnail :: Maybe ResourcePath
  , properties :: GalleryItemProps
  } deriving (Generic, Show)

instance ToJSON GalleryItem where
  toJSON = genericToJSON encodingOptions
  toEncoding = genericToEncoding encodingOptions


buildGalleryTree :: ResourceTree -> GalleryItem
buildGalleryTree (ItemResource sidecar path@(filename:_) thumbnail) =
  GalleryItem
    { title = optMeta title filename
    , date = optMeta date "" -- TODO: check and normalise dates
    , description = optMeta description ""
    , tags = optMeta tags []
    , path = webPath path
    , thumbnail = fmap webPath thumbnail
    , properties = Unknown } -- TODO
  where
    optMeta :: (Sidecar -> Maybe a) -> a -> a
    optMeta get fallback = fromMaybe fallback $ get sidecar

buildGalleryTree (DirResource dirItems path@(dirname:_) thumbnail) =
  map buildGalleryTree dirItems
  & \items -> GalleryItem
    { title = dirname
      -- TODO: consider using the most recent item's date? what if empty?
    , date = ""
      -- TODO: consider allowing metadata sidecars for directories too
    , description = ""
    , tags = aggregateChildTags items
    , path = webPath path
    , thumbnail = fmap webPath thumbnail
    , properties = Directory items }
  where
    aggregateChildTags :: [GalleryItem] -> [Tag]
    aggregateChildTags = unique . concatMap (\item -> tags (item::GalleryItem))

    unique :: Ord a => [a] -> [a]
    unique = Set.toList . Set.fromList

buildGallery :: String -> ResourceTree -> GalleryItem
buildGallery galleryName resourceTree =
  (buildGalleryTree resourceTree) { title = galleryName }