diff options
-rw-r--r-- | compiler/src/Processors.hs | 28 | ||||
-rw-r--r-- | compiler/src/Resource.hs | 4 | ||||
-rw-r--r-- | readme.md | 2 | ||||
-rw-r--r-- | viewer/package-lock.json | 15 | ||||
-rw-r--r-- | viewer/package.json | 3 | ||||
-rw-r--r-- | viewer/src/@types/gallery.d.ts | 10 | ||||
-rw-r--r-- | viewer/src/components/LdPicture.vue | 56 | ||||
-rw-r--r-- | viewer/src/services/ldzoom.ts | 134 | ||||
-rw-r--r-- | viewer/src/views/MainLayout.vue | 1 |
9 files changed, 211 insertions, 42 deletions
diff --git a/compiler/src/Processors.hs b/compiler/src/Processors.hs index b1b688a..02db325 100644 --- a/compiler/src/Processors.hs +++ b/compiler/src/Processors.hs | |||
@@ -138,6 +138,17 @@ getImageResolution fsPath = | |||
138 | (Just w, Just h) -> return $ Resolution w h | 138 | (Just w, Just h) -> return $ Resolution w h |
139 | _ -> throwIO $ ProcessingException fsPath "Unable to read image resolution." | 139 | _ -> throwIO $ ProcessingException fsPath "Unable to read image resolution." |
140 | 140 | ||
141 | getPictureProps :: ItemDescriber | ||
142 | getPictureProps fsPath resource = | ||
143 | getImageResolution fsPath | ||
144 | >>= return . Picture resource | ||
145 | |||
146 | |||
147 | type ItemDescriber = | ||
148 | FilePath | ||
149 | -> Resource | ||
150 | -> IO GalleryItemProps | ||
151 | |||
141 | 152 | ||
142 | type ItemFileProcessor = | 153 | type ItemFileProcessor = |
143 | FileName -- ^ Input base path | 154 | FileName -- ^ Input base path |
@@ -147,19 +158,20 @@ type ItemFileProcessor = | |||
147 | 158 | ||
148 | itemFileProcessor :: Maybe Resolution -> Cache -> ItemFileProcessor | 159 | itemFileProcessor :: Maybe Resolution -> Cache -> ItemFileProcessor |
149 | itemFileProcessor maxResolution cached inputBase outputBase resClass inputRes = | 160 | itemFileProcessor maxResolution cached inputBase outputBase resClass inputRes = |
150 | cached processor inPath outPath | 161 | cached processor inPath outPath |
151 | >> resourceAt outPath relOutPath | 162 | >> resourceAt outPath relOutPath |
152 | >>= return . props | 163 | >>= descriptor outPath |
153 | where | 164 | where |
154 | relOutPath = resClass /> inputRes | 165 | relOutPath = resClass /> inputRes |
155 | inPath = localPath $ inputBase /> inputRes | 166 | inPath = localPath $ inputBase /> inputRes |
156 | outPath = localPath $ outputBase /> relOutPath | 167 | outPath = localPath $ outputBase /> relOutPath |
157 | (processor, props) = processorFor maxResolution $ formatFromPath inputRes | 168 | (processor, descriptor) = processorFor (formatFromPath inputRes) maxResolution |
158 | 169 | ||
159 | processorFor :: Maybe Resolution -> Format -> (FileProcessor, Resource -> GalleryItemProps) | 170 | processorFor :: Format -> Maybe Resolution -> (FileProcessor, ItemDescriber) |
160 | processorFor (Just maxRes) PictureFormat = (resizePictureUpTo maxRes, Picture) | 171 | processorFor PictureFormat (Just maxRes) = (resizePictureUpTo maxRes, getPictureProps) |
161 | processorFor Nothing PictureFormat = (copyFileProcessor, Picture) | 172 | processorFor PictureFormat Nothing = (copyFileProcessor, getPictureProps) |
162 | processorFor _ Unknown = (copyFileProcessor, Other) -- TODO: handle video reencoding and others? | 173 | -- TODO: handle video reencoding and others? |
174 | processorFor Unknown _ = (copyFileProcessor, const $ return . Other) | ||
163 | 175 | ||
164 | 176 | ||
165 | type ThumbnailFileProcessor = | 177 | type ThumbnailFileProcessor = |
diff --git a/compiler/src/Resource.hs b/compiler/src/Resource.hs index b2a6bbf..e134468 100644 --- a/compiler/src/Resource.hs +++ b/compiler/src/Resource.hs | |||
@@ -72,7 +72,9 @@ instance ToJSON Resource where | |||
72 | 72 | ||
73 | data GalleryItemProps = | 73 | data GalleryItemProps = |
74 | Directory { items :: [GalleryItem] } | 74 | Directory { items :: [GalleryItem] } |
75 | | Picture { resource :: Resource } | 75 | | Picture |
76 | { resource :: Resource | ||
77 | , resolution :: Resolution } | ||
76 | | Other { resource :: Resource } | 78 | | Other { resource :: Resource } |
77 | deriving (Generic, Show) | 79 | deriving (Generic, Show) |
78 | 80 | ||
@@ -54,6 +54,8 @@ Builds of this software embed and make use of the following libraries: | |||
54 | * fortawesome/vue-fontawesome, licensed under the MIT License | 54 | * fortawesome/vue-fontawesome, licensed under the MIT License |
55 | * buefy, licensed under the MIT License | 55 | * buefy, licensed under the MIT License |
56 | * core-js, licensed under the MIT License | 56 | * core-js, licensed under the MIT License |
57 | * resize-observer-polyfill, licensed under the MIT License | ||
58 | * hammerjs, licensed under the MIT License | ||
57 | * v-lazy-image, licensed under the MIT License | 59 | * v-lazy-image, licensed under the MIT License |
58 | * vue, licensed under the MIT License | 60 | * vue, licensed under the MIT License |
59 | * vue-class-component, licensed under the MIT License | 61 | * vue-class-component, licensed under the MIT License |
diff --git a/viewer/package-lock.json b/viewer/package-lock.json index 228788d..d4a5fb0 100644 --- a/viewer/package-lock.json +++ b/viewer/package-lock.json | |||
@@ -1232,6 +1232,11 @@ | |||
1232 | "@types/node": "*" | 1232 | "@types/node": "*" |
1233 | } | 1233 | } |
1234 | }, | 1234 | }, |
1235 | "@types/hammerjs": { | ||
1236 | "version": "2.0.36", | ||
1237 | "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.36.tgz", | ||
1238 | "integrity": "sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ==" | ||
1239 | }, | ||
1235 | "@types/json-schema": { | 1240 | "@types/json-schema": { |
1236 | "version": "7.0.4", | 1241 | "version": "7.0.4", |
1237 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", | 1242 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", |
@@ -6487,6 +6492,11 @@ | |||
6487 | "pify": "^4.0.1" | 6492 | "pify": "^4.0.1" |
6488 | } | 6493 | } |
6489 | }, | 6494 | }, |
6495 | "hammerjs": { | ||
6496 | "version": "2.0.8", | ||
6497 | "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", | ||
6498 | "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" | ||
6499 | }, | ||
6490 | "handle-thing": { | 6500 | "handle-thing": { |
6491 | "version": "2.0.1", | 6501 | "version": "2.0.1", |
6492 | "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", | 6502 | "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", |
@@ -10464,6 +10474,11 @@ | |||
10464 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", | 10474 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", |
10465 | "dev": true | 10475 | "dev": true |
10466 | }, | 10476 | }, |
10477 | "resize-observer-polyfill": { | ||
10478 | "version": "1.5.1", | ||
10479 | "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", | ||
10480 | "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" | ||
10481 | }, | ||
10467 | "resolve": { | 10482 | "resolve": { |
10468 | "version": "1.14.1", | 10483 | "version": "1.14.1", |
10469 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", | 10484 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", |
diff --git a/viewer/package.json b/viewer/package.json index 40a91ba..bc63dfd 100644 --- a/viewer/package.json +++ b/viewer/package.json | |||
@@ -13,8 +13,11 @@ | |||
13 | "@fortawesome/fontawesome-svg-core": "^1.2.28", | 13 | "@fortawesome/fontawesome-svg-core": "^1.2.28", |
14 | "@fortawesome/free-solid-svg-icons": "^5.13.0", | 14 | "@fortawesome/free-solid-svg-icons": "^5.13.0", |
15 | "@fortawesome/vue-fontawesome": "^0.1.9", | 15 | "@fortawesome/vue-fontawesome": "^0.1.9", |
16 | "@types/hammerjs": "^2.0.36", | ||
16 | "buefy": "^0.8.15", | 17 | "buefy": "^0.8.15", |
17 | "core-js": "^3.6.4", | 18 | "core-js": "^3.6.4", |
19 | "hammerjs": "^2.0.8", | ||
20 | "resize-observer-polyfill": "^1.5.1", | ||
18 | "v-lazy-image": "^1.4.0", | 21 | "v-lazy-image": "^1.4.0", |
19 | "vue": "^2.6.11", | 22 | "vue": "^2.6.11", |
20 | "vue-class-component": "^7.2.3", | 23 | "vue-class-component": "^7.2.3", |
diff --git a/viewer/src/@types/gallery.d.ts b/viewer/src/@types/gallery.d.ts index de1c0dd..956ab6b 100644 --- a/viewer/src/@types/gallery.d.ts +++ b/viewer/src/@types/gallery.d.ts | |||
@@ -49,12 +49,17 @@ declare namespace Gallery { | |||
49 | thumbnail?: Thumbnail | 49 | thumbnail?: Thumbnail |
50 | properties: OtherProperties | PictureProperties | DirectoryProperties, | 50 | properties: OtherProperties | PictureProperties | DirectoryProperties, |
51 | } | 51 | } |
52 | interface Resolution { | ||
53 | width: number, | ||
54 | height: number, | ||
55 | } | ||
52 | interface OtherProperties { | 56 | interface OtherProperties { |
53 | type: "other", | 57 | type: "other", |
54 | } | 58 | } |
55 | interface PictureProperties { | 59 | interface PictureProperties { |
56 | type: "picture", | 60 | type: "picture", |
57 | resource: string, | 61 | resource: string, |
62 | resolution: Resolution | ||
58 | } | 63 | } |
59 | interface DirectoryProperties { | 64 | interface DirectoryProperties { |
60 | type: "directory", | 65 | type: "directory", |
@@ -62,10 +67,7 @@ declare namespace Gallery { | |||
62 | } | 67 | } |
63 | interface Thumbnail { | 68 | interface Thumbnail { |
64 | resource: string, | 69 | resource: string, |
65 | resolution: { | 70 | resolution: Resolution |
66 | width: number, | ||
67 | height: number, | ||
68 | } | ||
69 | } | 71 | } |
70 | type RawTag = string; | 72 | type RawTag = string; |
71 | type ItemType = "other" | "picture" | "directory"; | 73 | type ItemType = "other" | "picture" | "directory"; |
diff --git a/viewer/src/components/LdPicture.vue b/viewer/src/components/LdPicture.vue index 3170c81..de46bcb 100644 --- a/viewer/src/components/LdPicture.vue +++ b/viewer/src/components/LdPicture.vue | |||
@@ -18,17 +18,21 @@ | |||
18 | --> | 18 | --> |
19 | 19 | ||
20 | <template> | 20 | <template> |
21 | <!-- FIXME: v-dragscroll interferes with pinch-to-zoom --> | ||
21 | <div | 22 | <div |
23 | ref="containerElement" | ||
22 | v-dragscroll | 24 | v-dragscroll |
23 | class="scrollbar" | 25 | class="scrollbar ld-picture-container" |
24 | :class="{'fit-to-screen': !$uiStore.fullscreen, 'original-size': $uiStore.fullscreen}" | ||
25 | @click.capture="e => dragScrollClickFix.onClickCapture(e)" | 26 | @click.capture="e => dragScrollClickFix.onClickCapture(e)" |
26 | @click="$uiStore.toggleFullscreen()" | 27 | @dblclick="$uiStore.toggleFullscreen()" |
28 | @dragstart.prevent | ||
27 | @dragscrollstart="dragScrollClickFix.onDragScrollStart()" | 29 | @dragscrollstart="dragScrollClickFix.onDragScrollStart()" |
28 | @dragscrollend="dragScrollClickFix.onDragScrollEnd()" | 30 | @dragscrollend="dragScrollClickFix.onDragScrollEnd()" |
29 | > | 31 | > |
30 | <v-lazy-image | 32 | <v-lazy-image |
33 | ref="imageElement" | ||
31 | :src="pictureSrc(picture.properties.resource)" | 34 | :src="pictureSrc(picture.properties.resource)" |
35 | class="ld-picture-element" | ||
32 | :class="{'slow-loading': Boolean(slowLoadingStyle)}" | 36 | :class="{'slow-loading': Boolean(slowLoadingStyle)}" |
33 | :style="slowLoadingStyle" | 37 | :style="slowLoadingStyle" |
34 | @load="clearSlowLoading" | 38 | @load="clearSlowLoading" |
@@ -38,12 +42,15 @@ | |||
38 | </template> | 42 | </template> |
39 | 43 | ||
40 | <script lang="ts"> | 44 | <script lang="ts"> |
41 | import { Component, Vue, Prop } from "vue-property-decorator"; | 45 | import { Component, Vue, Prop, Ref } from "vue-property-decorator"; |
46 | import LdZoom from "@/se |