Skip to content

Commit 72ee207

Browse files
committed
fix(image-editor): open newly created image when closing the image editor
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>
1 parent e95908e commit 72ee207

File tree

4 files changed

+81
-15
lines changed

4 files changed

+81
-15
lines changed

src/components/ImageEditor.vue

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export default {
3939
data() {
4040
return {
4141
imageEditor: null,
42+
observer: null,
4243
}
4344
},
4445
@@ -133,14 +134,31 @@ export default {
133134
)
134135
this.imageEditor.render()
135136
window.addEventListener('keydown', this.handleKeydown, true)
136-
window.addEventListener('DOMNodeInserted', this.handleSfxModal)
137+
138+
this.observer = new MutationObserver((mutations) => {
139+
mutations.forEach((mutation) => {
140+
if (mutation.type === 'childList') {
141+
mutation.addedNodes.forEach((node) => {
142+
if (node.classList.contains('FIE_root') || node.classList.contains('SfxModal-Wrapper')) {
143+
emit('viewer:trapElements:changed', node)
144+
}
145+
})
146+
}
147+
})
148+
})
149+
// using body instead of the editor ref because save modal is not mounted in editor
150+
this.observer.observe(document.body, {
151+
childList: true,
152+
subtree: true,
153+
})
137154
138155
},
139156
140157
beforeDestroy() {
141158
if (this.imageEditor) {
142159
this.imageEditor.terminate()
143160
}
161+
this.observer.disconnect()
144162
window.removeEventListener('keydown', this.handleKeydown, true)
145163
},
146164
@@ -235,11 +253,16 @@ export default {
235253
try {
236254
const blob = await new Promise(resolve => imageCanvas.toBlob(resolve, mimeType, quality))
237255
const response = await axios.put(putUrl, new File([blob], fullName))
238-
239256
logger.info('Edited image saved!', { response })
240257
showSuccess(t('viewer', 'Image saved'))
241258
if (putUrl !== this.src) {
242-
emit('files:node:created', { fileid: parseInt(response?.headers?.['oc-fileid']?.split('oc')[0]) || null })
259+
const fileId = parseInt(response?.headers?.['oc-fileid']?.split('oc')[0]) || null
260+
emit('editor:file:created', putUrl)
261+
if (fileId) {
262+
const newParams = window.OCP.Files.Router.params
263+
newParams.fileId = fileId
264+
window.OCP.Files.Router.goToRoute(null, newParams, window.OCP.Files.Router.query)
265+
}
243266
} else {
244267
this.$emit('updated')
245268
const updatedFile = await rawStat(origin, decodeURI(pathname))
@@ -290,17 +313,6 @@ export default {
290313
}
291314
},
292315
293-
/**
294-
* Watch out for Modal inject in document root
295-
* That way we can adjust the focusTrap
296-
*
297-
* @param {Event} event Dom insertion event
298-
*/
299-
handleSfxModal(event) {
300-
if (event.target?.classList && event.target.classList.contains('SfxModal-Wrapper')) {
301-
emit('viewer:trapElements:changed', event.target)
302-
}
303-
},
304316
},
305317
}
306318
</script>

src/services/FetchFile.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { getClient, getDefaultPropfind, getRootPath, resultToNode } from '@nextcloud/files/dav'
2+
import type { FileStat, ResponseDataDetailed } from 'webdav'
3+
import type { Node } from '@nextcloud/files'
4+
5+
export default async (path: string): Promise<Node> => {
6+
if (!path.startsWith('/')) {
7+
path = `/${path}`
8+
}
9+
const client = getClient()
10+
const propfindPayload = getDefaultPropfind()
11+
const result = await client.stat(`${getRootPath()}${path}`, {
12+
details: true,
13+
data: propfindPayload,
14+
}) as ResponseDataDetailed<FileStat>
15+
return resultToNode(result.data)
16+
}

src/utils/fileUtils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { FileStat } from 'webdav'
77
import { davRemoteURL, davRootPath } from '@nextcloud/files'
88
import { getLanguage } from '@nextcloud/l10n'
99
import { encodePath } from '@nextcloud/paths'
10+
import { getCurrentUser } from '@nextcloud/auth'
1011
import camelcase from 'camelcase'
1112

1213
import { isNumber } from './numberUtil'
@@ -64,6 +65,24 @@ export function extractFilePaths(path: string): [string, string] {
6465
return [dirPath, fileName]
6566
}
6667

68+
/**
69+
* Extract path from source
70+
*
71+
* @param source the full source URL
72+
* @return path
73+
*/
74+
export function extractFilePathFromSource(source: string): string {
75+
const uid = getCurrentUser()?.uid
76+
77+
if (uid) {
78+
const path = source.split(`${uid}/`)[1]
79+
if (path) {
80+
return path
81+
}
82+
}
83+
throw new Error(`Invalid source URL: ${source}. Unable to extract file paths.`)
84+
}
85+
6786
/**
6887
* Sorting comparison function
6988
*

src/views/Viewer.vue

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@
148148
:is-sidebar-shown="isSidebarShown"
149149
:loaded.sync="currentFile.loaded"
150150
class="viewer__file viewer__file--active"
151+
@update:editing="toggleEditor"
151152
@error="currentFailed" />
152153
<Error v-else
153154
:name="currentFile.basename" />
@@ -187,12 +188,13 @@ import isFullscreen from '@nextcloud/vue/dist/Mixins/isFullscreen.js'
187188
import isMobile from '@nextcloud/vue/dist/Mixins/isMobile.js'
188189
189190
import { canDownload } from '../utils/canDownload.ts'
190-
import { extractFilePaths, sortCompare } from '../utils/fileUtils.ts'
191+
import { extractFilePaths, sortCompare, extractFilePathFromSource } from '../utils/fileUtils.ts'
191192
import getSortingConfig from '../services/FileSortingConfig.ts'
192193
import cancelableRequest from '../utils/CancelableRequest.js'
193194
import Error from '../components/Error.vue'
194195
import File from '../models/file.js'
195196
import getFileInfo from '../services/FileInfo.ts'
197+
import fetchNode from '../services/FetchFile.ts'
196198
import getFileList from '../services/FileList.ts'
197199
import Mime from '../mixins/Mime.js'
198200
import logger from '../services/logger.js'
@@ -545,6 +547,7 @@ export default defineComponent({
545547
subscribe('files:node:updated', this.handleFileUpdated)
546548
subscribe('viewer:trapElements:changed', this.handleTrapElementsChange)
547549
subscribe('editor:toggle', this.toggleEditor)
550+
subscribe('editor:file:created', this.handleNewFile)
548551
window.addEventListener('keydown', this.keyboardDeleteFile)
549552
window.addEventListener('keydown', this.keyboardDownloadFile)
550553
window.addEventListener('keydown', this.keyboardEditFile)
@@ -659,6 +662,22 @@ export default defineComponent({
659662
}
660663
}
661664
},
665+
async handleNewFile(source) {
666+
let path
667+
try {
668+
path = extractFilePathFromSource(source)
669+
this.openFile(path)
670+
671+
} catch (e) {
672+
logger.error('Could not extract file path from source', { source, e })
673+
}
674+
try {
675+
const node = await fetchNode('/' + path)
676+
emit('files:node:created', node)
677+
} catch (e) {
678+
logger.error('Could not fetch new file', { path, e })
679+
}
680+
},
662681
663682
/**
664683
* Open the view and display the clicked file from a known file info object

0 commit comments

Comments
 (0)