44<script >
55import { basename , dirname , extname , join } from ' path'
66import { emit } from ' @nextcloud/event-bus'
7+ import { showError , showSuccess } from ' @nextcloud/dialogs'
78import axios from ' @nextcloud/axios'
89import FilerobotImageEditor from ' filerobot-image-editor'
910
@@ -143,39 +144,38 @@ export default {
143144 this .$emit (' close' )
144145 },
145146
146- async onSave (imageData ) {
147+ /**
148+ * User saved the image
149+ *
150+ * @see https://github.com/scaleflex/filerobot-image-editor#onsave
151+ * @param {object} props destructuring object
152+ * @param {string} props.fullName the file name
153+ * @param {HTMLCanvasElement} props.imageCanvas the image canvas
154+ * @param {string} props.mimeType the image mime type
155+ * @param {number} props.quality the image saving quality
156+ */
157+ async onSave ({ fullName, imageCanvas, mimeType, quality }) {
147158 const { origin , pathname } = new URL (this .src )
148- const putUrl = origin + join (dirname (pathname), imageData . fullName )
149- logger .debug (' Saving image...' , { putUrl, src: this .src , fullName: imageData . fullName })
159+ const putUrl = origin + join (dirname (pathname), fullName)
160+ logger .debug (' Saving image...' , { putUrl, src: this .src , fullName })
150161
151162 try {
152- const file = this . dataURLtoFile ( imageData . imageBase64 , imageData . fullName )
153- const response = await axios .put (putUrl, file )
163+ const blob = await new Promise ( resolve => imageCanvas . toBlob (resolve, mimeType, quality) )
164+ const response = await axios .put (putUrl, new File ([blob], fullName) )
154165
155166 logger .info (' Edited image saved!' , { response })
167+ showSuccess (t (' viewer' , ' Image saved' ))
156168 if (putUrl !== this .src ) {
157169 emit (' files:file:created' , { fileid: parseInt (response? .headers ? .[' oc-fileid' ]? .split (' oc' )[0 ]) || null })
158170 } else {
159171 emit (' files:file:updated' , { fileid: this .fileid })
160172 }
161173 } catch (error) {
162174 logger .error (' Error saving image' , { error })
175+ showError (t (' viewer' , ' Error saving image' ))
163176 }
164177 },
165178
166- dataURLtoFile (dataurl , filename ) {
167- const arr = dataurl .split (' ,' )
168- const mime = arr[0 ].match (/ :(. *? );/ )[1 ]
169- const bstr = atob (arr[1 ])
170- let n = bstr .length
171- const u8arr = new Uint8Array (n)
172- while (n) {
173- u8arr[n - 1 ] = bstr .charCodeAt (n - 1 )
174- n -= 1
175- }
176- return new File ([u8arr], filename, { type: mime })
177- },
178-
179179 /**
180180 * Show warning if unsaved changes
181181 */
@@ -240,14 +240,15 @@ export default {
240240< style lang= " scss" scoped>
241241// Take full screen size ()
242242.viewer__image - editor {
243- width : 100 % ;
244- height : 100vh ;
243+ position : absolute ;
244+ z - index : 10100 ;
245245 top: calc (var (-- header- height) * - 1 );
246246 bottom: calc (var (-- header- height) * - 1 );
247247 left: 0 ;
248- position : absolute ;
249- z - index : 10100 ;
248+ width : 100 % ;
249+ height : 100vh ;
250250}
251+
251252< / style>
252253
253254< style lang= " scss" >
@@ -279,12 +280,12 @@ export default {
279280
280281 // Fix button ratio and center content
281282 button {
282- padding: 6px 12px ;
283- min- width: 44px ;
284- min- height: 44px ;
285283 display: flex;
286- justify- content: center;
287284 align- items: center;
285+ justify- content: center;
286+ min- width: 44px ;
287+ min- height: 44px ;
288+ padding: 6px 12px ;
288289 }
289290}
290291
@@ -304,21 +305,21 @@ export default {
304305
305306// Global buttons
306307.SfxButton - root {
307- margin: 0 ! important;
308308 min- height: 44px ! important;
309+ margin: 0 ! important;
309310 border: transparent ! important;
310311 & [color= ' error' ] {
311- background- color: var (-- color- error) ! important;
312312 color: white ! important;
313+ background- color: var (-- color- error) ! important;
313314 & : hover,
314315 & : focus {
315316 border- color: white ! important;
316317 background- color: var (-- color- error- hover) ! important;
317318 }
318319 }
319320 & [color= ' primary' ] {
320- background- color: var (-- color- primary- element) ! important;
321321 color: var (-- color- primary- text) ! important;
322+ background- color: var (-- color- primary- element) ! important;
322323 & : hover,
323324 & : focus {
324325 background- color: var (-- color- primary- element- hover) ! important;
@@ -332,11 +333,11 @@ export default {
332333 padding- left: 8px ! important;
333334 // Center the menu entry icon and fix width
334335 > div {
335- cursor: pointer;
336336 margin- right: 0 ;
337337 padding: 14px ;
338338 // Minus the parent padding-left
339339 padding: calc (14px - 8px );
340+ cursor: pointer;
340341 }
341342
342343 // Disable jpeg saving (jpg is already here)
@@ -347,8 +348,8 @@ export default {
347348
348349// Modal
349350.SfxModal - Container {
350- padding: 22px ;
351351 min- height: 300px ;
352+ padding: 22px ;
352353
353354 // Fill height
354355 .SfxModal - root,
@@ -358,14 +359,15 @@ export default {
358359 color: var (-- color- main- text);
359360 }
360361 .SfxModalTitle - Icon {
361- background: none ! important;
362362 margin- bottom: 22px ! important;
363+ background: none ! important;
363364 // Fit EmptyContent styling
364365 svg {
365366 width: 64px ;
366367 height: 64px ;
367368 opacity: .4 ;
368369 // Override all coloured icons
370+
369371 -- color- primary: var (-- color- main- text);
370372 -- color- error: var (-- color- main- text);
371373 }
@@ -392,9 +394,9 @@ export default {
392394}
393395
394396.FIE_tab {
395- padding: 8px ;
396397 width: 80px ! important;
397398 height: 80px ! important;
399+ padding: 8px ;
398400 border- radius: var (-- border- radius- large) ! important;
399401 svg {
400402 width: 16px ;
@@ -425,24 +427,24 @@ export default {
425427 // Matching buttons tools
426428 & > div[class $= ' -tool-button' ],
427429 & > div[class $= ' -tool' ] {
428- height: 44px ;
429- min- width: 44px ;
430430 display: flex;
431- justify- content: center;
432431 align- items: center;
433- border- radius: var (-- border- radius- pill);
432+ justify- content: center;
433+ min- width: 44px ;
434+ height: 44px ;
434435 padding: 6px 16px ;
436+ border- radius: var (-- border- radius- pill);
435437 }
436438}
437439
438440// Crop preset select button
439441.FIE_crop - presets- opener- button {
440- background - color : transparent ! important;
441- border : none ! important;
442+ // override default button width
443+ min - width : 0 ! important;
442444 padding: 5px ! important;
443445 padding- left: 10px ! important;
444- // override default button width
445- min - width : 0px ! important;
446+ border : none ! important;
447+ background - color : transparent ! important;
446448}
447449
448450// Force icon-only style
@@ -478,18 +480,37 @@ export default {
478480
479481// Save button fixes
480482.FIE_topbar - save- button {
481- background- color: var (-- color- primary- element) ! important;
482483 color: var (-- color- primary- text) ! important;
483484 border: none ! important;
485+ background- color: var (-- color- primary- element) ! important;
484486 & : hover,
485487 & : focus {
486488 background- color: var (-- color- primary- element- hover) ! important;
487489 }
488490}
489491
492+ // Save Modal fixes
493+ .FIE_resize - tool- options {
494+ .FIE_resize - width- option,
495+ .FIE_resize - height- option {
496+ flex: 1 1 ;
497+ min- width: 0 ;
498+ }
499+ }
500+
490501// Resize lock
491502.FIE_resize - ratio- locker {
492503 margin- right: 8px ! important;
504+ // Icon is very thin
505+ svg {
506+ width: 20px ;
507+ height: 20px ;
508+ path {
509+ stroke- width: 1 ;
510+ stroke: var (-- color- main- text);
511+ fill: var (-- color- main- text);
512+ }
513+ }
493514}
494515
495516// Close editor button fixes
@@ -517,22 +538,24 @@ export default {
517538}
518539
519540.FIE_spinner :: before {
520- z- index: 2 ;
521- content: ' ' ;
522- height: 28px ;
523- width: 28px ;
524- margin: - 16px 0 0 - 16px ;
525541 position: absolute;
542+ z- index: 2 ;
526543 top: 50 % ;
527544 left: 50 % ;
528- border- radius: 100 % ;
529- - webkit- animation: rotate .8s infinite linear;
530- animation: rotate .8s infinite linear;
545+ width: 28px ;
546+ height: 28px ;
547+ margin: - 16px 0 0 - 16px ;
548+ content: ' ' ;
531549 - webkit- transform- origin: center;
532550 - ms- transform- origin: center;
533551 transform- origin: center;
552+ - webkit- animation: rotate .8s infinite linear;
553+ animation: rotate .8s infinite linear;
534554 border: 2px solid var (-- color- loading- light);
535555 border- top- color: var (-- color- loading- dark);
556+ border- radius: 100 % ;
557+
536558 filter: var (-- background- invert- if - dark);
537559}
560+
538561< / style>
0 commit comments