diff options
Diffstat (limited to 'compiler/src/Resource.hs')
-rw-r--r-- | compiler/src/Resource.hs | 90 |
1 files changed, 53 insertions, 37 deletions
diff --git a/compiler/src/Resource.hs b/compiler/src/Resource.hs index e134468..f59eed6 100644 --- a/compiler/src/Resource.hs +++ b/compiler/src/Resource.hs | |||
@@ -17,9 +17,15 @@ | |||
17 | -- along with this program. If not, see <https://www.gnu.org/licenses/>. | 17 | -- along with this program. If not, see <https://www.gnu.org/licenses/>. |
18 | 18 | ||
19 | module Resource | 19 | module Resource |
20 | ( ItemProcessor, ThumbnailProcessor | 20 | ( ItemProcessor |
21 | , GalleryItem(..), GalleryItemProps(..), Resolution(..), Resource(..), Thumbnail(..) | 21 | , GalleryItem(..) |
22 | , buildGalleryTree, galleryCleanupResourceDir | 22 | , GalleryItemProps(..) |
23 | , Resolution(..) | ||
24 | , Resource(..) | ||
25 | , Thumbnail(..) | ||
26 | , buildGalleryTree | ||
27 | , galleryCleanupResourceDir | ||
28 | , flattenGalleryTree | ||
23 | ) where | 29 | ) where |
24 | 30 | ||
25 | 31 | ||
@@ -29,15 +35,16 @@ import Data.List.Ordered (minusBy) | |||
29 | import Data.Char (toLower) | 35 | import Data.Char (toLower) |
30 | import Data.Maybe (mapMaybe, fromMaybe) | 36 | import Data.Maybe (mapMaybe, fromMaybe) |
31 | import Data.Function ((&)) | 37 | import Data.Function ((&)) |
38 | import Data.Functor ((<&>)) | ||
32 | import qualified Data.Set as Set | 39 | import qualified Data.Set as Set |
33 | import Data.Text (pack) | 40 | import Data.Text (pack, unpack, breakOn) |
34 | import Data.Time.Clock (UTCTime) | 41 | import Data.Time.Clock (UTCTime) |
35 | import Data.Time.LocalTime (ZonedTime, utc, utcToZonedTime, zonedTimeToUTC) | 42 | import Data.Time.LocalTime (ZonedTime, utc, utcToZonedTime, zonedTimeToUTC) |
36 | import Data.Time.Format (formatTime, defaultTimeLocale) | 43 | import Data.Time.Format (formatTime, parseTimeM, defaultTimeLocale) |
37 | import Safe.Foldable (maximumByMay) | 44 | import Safe.Foldable (maximumByMay) |
38 | 45 | ||
39 | import GHC.Generics (Generic) | 46 | import GHC.Generics (Generic) |
40 | import Data.Aeson (ToJSON, genericToJSON, genericToEncoding) | 47 | import Data.Aeson (ToJSON, FromJSON, genericToJSON, genericToEncoding, genericParseJSON) |
41 | import qualified Data.Aeson as JSON | 48 | import qualified Data.Aeson as JSON |
42 | 49 | ||
43 | import Files | 50 | import Files |
@@ -69,12 +76,23 @@ instance ToJSON Resource where | |||
69 | where | 76 | where |
70 | timestamp = formatTime defaultTimeLocale "%s" modTime | 77 | timestamp = formatTime defaultTimeLocale "%s" modTime |
71 | 78 | ||
79 | instance FromJSON Resource where | ||
80 | parseJSON = JSON.withText "Resource" (unpackRes . breakOn "?") | ||
81 | where | ||
82 | unpackRes (resPathStr, modTimeStr) = | ||
83 | Resource (fromWebPath $ unpack resPathStr) | ||
84 | <$> parseTimeM True defaultTimeLocale "?%s" (unpack modTimeStr) | ||
85 | |||
72 | 86 | ||
73 | data GalleryItemProps = | 87 | data GalleryItemProps = |
74 | Directory { items :: [GalleryItem] } | 88 | Directory { items :: [GalleryItem] } |
75 | | Picture | 89 | | Picture |
76 | { resource :: Resource | 90 | { resource :: Resource |
77 | , resolution :: Resolution } | 91 | , resolution :: Resolution } |
92 | | PlainText { resource :: Resource } | ||
93 | | PDF { resource :: Resource } | ||
94 | | Video { resource :: Resource } | ||
95 | | Audio { resource :: Resource } | ||
78 | | Other { resource :: Resource } | 96 | | Other { resource :: Resource } |
79 | deriving (Generic, Show) | 97 | deriving (Generic, Show) |
80 | 98 | ||
@@ -82,15 +100,14 @@ instance ToJSON GalleryItemProps where | |||
82 | toJSON = genericToJSON encodingOptions | 100 | toJSON = genericToJSON encodingOptions |
83 | toEncoding = genericToEncoding encodingOptions | 101 | toEncoding = genericToEncoding encodingOptions |
84 | 102 | ||
103 | instance FromJSON GalleryItemProps where | ||
104 | parseJSON = genericParseJSON encodingOptions | ||
105 | |||
85 | 106 | ||
86 | data Thumbnail = Thumbnail | 107 | data Thumbnail = Thumbnail |
87 | { resource :: Resource | 108 | { resource :: Resource |
88 | , resolution :: Resolution | 109 | , resolution :: Resolution |
89 | } deriving (Generic, Show) | 110 | } deriving (Generic, Show, ToJSON, FromJSON) |
90 | |||
91 | instance ToJSON Thumbnail where | ||
92 | toJSON = genericToJSON encodingOptions | ||
93 | toEncoding = genericToEncoding encodingOptions | ||
94 | 111 | ||
95 | 112 | ||
96 | data GalleryItem = GalleryItem | 113 | data GalleryItem = GalleryItem |
@@ -101,49 +118,49 @@ data GalleryItem = GalleryItem | |||
101 | , path :: Path | 118 | , path :: Path |
102 | , thumbnail :: Maybe Thumbnail | 119 | , thumbnail :: Maybe Thumbnail |
103 | , properties :: GalleryItemProps | 120 | , properties :: GalleryItemProps |
104 | } deriving (Generic, Show) | 121 | } deriving (Generic, Show, ToJSON, FromJSON) |
105 | |||
106 | instance ToJSON GalleryItem where | ||
107 | toJSON = genericToJSON encodingOptions | ||
108 | toEncoding = genericToEncoding encodingOptions | ||
109 | 122 | ||
110 | 123 | ||
111 | type ItemProcessor = Path -> IO GalleryItemProps | 124 | type ItemProcessor a = |
112 | type ThumbnailProcessor = Path -> IO (Maybe Thumbnail) | 125 | Path -- Item path |
126 | -> Path -- Resource Path | ||
127 | -> IO a | ||
113 | 128 | ||
114 | 129 | ||
115 | buildGalleryTree :: | 130 | buildGalleryTree :: |
116 | ItemProcessor -> ThumbnailProcessor -> TagsFromDirectoriesConfig | 131 | ItemProcessor GalleryItemProps -> ItemProcessor (Maybe Thumbnail) -> TagsFromDirectoriesConfig |
117 | -> InputTree -> IO GalleryItem | 132 | -> InputTree -> IO GalleryItem |
118 | buildGalleryTree processItem processThumbnail tagsFromDirsConfig inputTree = | 133 | buildGalleryTree processItem processThumbnail tagsFromDirsConfig = |
119 | mkGalleryItem [] inputTree | 134 | mkGalleryItem [] |
120 | where | 135 | where |
121 | mkGalleryItem :: [Tag] -> InputTree -> IO GalleryItem | 136 | mkGalleryItem :: [Tag] -> InputTree -> IO GalleryItem |
122 | mkGalleryItem inheritedTags InputFile{path, modTime, sidecar} = | 137 | mkGalleryItem inheritedTags InputFile{path, modTime, sidecar, thumbnailPath} = |
123 | do | 138 | do |
124 | properties <- processItem path | 139 | let itemPath = "/" /> path |
125 | processedThumbnail <- processThumbnail path | 140 | properties <- processItem itemPath path |
141 | processedThumbnail <- processThumbnail itemPath (thumbnailPath ?? path) | ||
126 | return GalleryItem | 142 | return GalleryItem |
127 | { title = Input.title sidecar ?? fileName path ?? "" | 143 | { title = Input.title sidecar ?? fileName path ?? "" |
128 | , datetime = Input.datetime sidecar ?? toZonedTime modTime | 144 | , datetime = Input.datetime sidecar ?? toZonedTime modTime |
129 | , description = Input.description sidecar ?? "" | 145 | , description = Input.description sidecar ?? "" |
130 | , tags = unique ((Input.tags sidecar ?? []) ++ inheritedTags ++ parentDirTags path) | 146 | , tags = unique ((Input.tags sidecar ?? []) ++ inheritedTags ++ parentDirTags path) |
131 | , path = "/" /> path | 147 | , path = itemPath |
132 | , thumbnail = processedThumbnail | 148 | , thumbnail = processedThumbnail |
133 | , properties = properties } | 149 | , properties = properties } |
134 | 150 | ||
135 | mkGalleryItem inheritedTags InputDir{path, modTime, sidecar, dirThumbnailPath, items} = | 151 | mkGalleryItem inheritedTags InputDir{path, modTime, sidecar, thumbnailPath, items} = |
136 | do | 152 | do |
153 | let itemPath = "/" /> path | ||
137 | let dirTags = (Input.tags sidecar ?? []) ++ inheritedTags | 154 | let dirTags = (Input.tags sidecar ?? []) ++ inheritedTags |
138 | processedItems <- parallel $ map (mkGalleryItem dirTags) items | 155 | processedItems <- parallel $ map (mkGalleryItem dirTags) items |
139 | processedThumbnail <- maybeThumbnail dirThumbnailPath | 156 | processedThumbnail <- maybeThumbnail itemPath thumbnailPath |
140 | return GalleryItem | 157 | return GalleryItem |
141 | { title = Input.title sidecar ?? fileName path ?? "" | 158 | { title = Input.title sidecar ?? fileName path ?? "" |
142 | , datetime = Input.datetime sidecar ?? mostRecentModTime processedItems | 159 | , datetime = Input.datetime sidecar ?? mostRecentModTime processedItems |
143 | ?? toZonedTime modTime | 160 | ?? toZonedTime modTime |
144 | , description = Input.description sidecar ?? "" | 161 | , description = Input.description sidecar ?? "" |
145 | , tags = unique (aggregateTags processedItems ++ parentDirTags path) | 162 | , tags = unique (aggregateTags processedItems ++ parentDirTags path) |
146 | , path = "/" /> path | 163 | , path = itemPath |
147 | , thumbnail = processedThumbnail | 164 | , thumbnail = processedThumbnail |
148 | , properties = Directory processedItems } | 165 | , properties = Directory processedItems } |
149 | 166 | ||
@@ -163,9 +180,9 @@ buildGalleryTree processItem processThumbnail tagsFromDirsConfig inputTree = | |||
163 | aggregateTags :: [GalleryItem] -> [Tag] | 180 | aggregateTags :: [GalleryItem] -> [Tag] |
164 | aggregateTags = concatMap (\item -> tags (item::GalleryItem)) | 181 | aggregateTags = concatMap (\item -> tags (item::GalleryItem)) |
165 | 182 | ||
166 | maybeThumbnail :: Maybe Path -> IO (Maybe Thumbnail) | 183 | maybeThumbnail :: Path -> Maybe Path -> IO (Maybe Thumbnail) |
167 | maybeThumbnail Nothing = return Nothing | 184 | maybeThumbnail _ Nothing = return Nothing |
168 | maybeThumbnail (Just thumbnailPath) = processThumbnail thumbnailPath | 185 | maybeThumbnail itemPath (Just thumbnailPath) = processThumbnail itemPath thumbnailPath |
169 | 186 | ||
170 | mostRecentModTime :: [GalleryItem] -> Maybe ZonedTime | 187 | mostRecentModTime :: [GalleryItem] -> Maybe ZonedTime |
171 | mostRecentModTime = | 188 | mostRecentModTime = |
@@ -186,7 +203,7 @@ flattenGalleryTree simple = [simple] | |||
186 | 203 | ||
187 | galleryOutputDiff :: GalleryItem -> FSNode -> [Path] | 204 | galleryOutputDiff :: GalleryItem -> FSNode -> [Path] |
188 | galleryOutputDiff resources ref = | 205 | galleryOutputDiff resources ref = |
189 | (filesystemPaths ref) \\ (compiledPaths $ flattenGalleryTree resources) | 206 | filesystemPaths ref \\ compiledPaths (flattenGalleryTree resources) |
190 | where | 207 | where |
191 | filesystemPaths :: FSNode -> [Path] | 208 | filesystemPaths :: FSNode -> [Path] |
192 | filesystemPaths = map Files.path . tail . flattenDir | 209 | filesystemPaths = map Files.path . tail . flattenDir |
@@ -208,8 +225,7 @@ galleryOutputDiff resources ref = | |||
208 | 225 | ||
209 | thumbnailPaths :: [GalleryItem] -> [Path] | 226 | thumbnailPaths :: [GalleryItem] -> [Path] |
210 | thumbnailPaths = | 227 | thumbnailPaths = |
211 | map resourcePath | 228 | map (resourcePath . (resource :: (Thumbnail -> Resource))) |
212 | . map (resource :: (Thumbnail -> Resource)) | ||
213 | . mapMaybe thumbnail | 229 | . mapMaybe thumbnail |
214 | 230 | ||
215 | (\\) :: [Path] -> [Path] -> [Path] | 231 | (\\) :: [Path] -> [Path] -> [Path] |
@@ -231,7 +247,7 @@ galleryOutputDiff resources ref = | |||
231 | galleryCleanupResourceDir :: GalleryItem -> FileName -> IO () | 247 | galleryCleanupResourceDir :: GalleryItem -> FileName -> IO () |
232 | galleryCleanupResourceDir resourceTree outputDir = | 248 | galleryCleanupResourceDir resourceTree outputDir = |
233 | readDirectory outputDir | 249 | readDirectory outputDir |
234 | >>= return . galleryOutputDiff resourceTree . root | 250 | <&> galleryOutputDiff resourceTree . root |
235 | >>= return . sortOn ((0 -) . pathLength) -- nested files before their parent dirs | 251 | <&> sortOn ((0 -) . pathLength) -- nested files before their parent dirs |
236 | >>= return . map (localPath . (/>) outputDir) | 252 | <&> map (localPath . (/>) outputDir) |
237 | >>= mapM_ remove | 253 | >>= mapM_ remove |