Skip to content

Commit f44ad7e

Browse files
hamza221backportbot[bot]
authored andcommitted
fix(image-editor): open newly created image when closing the image editor
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com> [skip ci]
1 parent d7eded2 commit f44ad7e

File tree

5 files changed

+110
-2
lines changed

5 files changed

+110
-2
lines changed

cypress/e2e/actions/edit.cy.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
describe('Open the new saved as image', function() {
7+
before(function() {
8+
cy.createRandomUser().then(user => {
9+
cy.uploadFile(user, 'image1.jpg', 'image/jpeg')
10+
cy.login(user)
11+
cy.visit('/apps/files')
12+
})
13+
})
14+
after(function() {
15+
cy.logout()
16+
})
17+
18+
it('See images in the list', function() {
19+
cy.getFile('image1.jpg', { timeout: 10000 })
20+
.should('contain', 'image1 .jpg')
21+
})
22+
it('Open the viewer on file click', function() {
23+
cy.openFile('image1.jpg')
24+
cy.get('body > .viewer').should('be.visible')
25+
})
26+
it('open the image editor', function() {
27+
cy.get('button[aria-label="Edit"]').click()
28+
})
29+
it('Save the image', function() {
30+
cy.get('.FIE_topbar-save-button').click()
31+
cy.get('input[type="text"].SfxInput-Base').clear()
32+
cy.get('input[type="text"].SfxInput-Base').type('imageSave')
33+
cy.get('.SfxModal-Container button[color="primary"].SfxButton-root').contains('Save').click()
34+
cy.get('.FIE_topbar-close-button').click()
35+
cy.get('.modal-header__name').should('contain', 'imageSave.jpg')
36+
cy.get('.modal-header button[aria-label="Close"]').click()
37+
})
38+
it('See the new saved image in the list', function() {
39+
40+
cy.getFile('imageSave.jpg', { timeout: 10000 })
41+
.should('contain', 'imageSave .jpg')
42+
})
43+
44+
})

src/components/ImageEditor.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,16 @@ export default {
249249
try {
250250
const blob = await new Promise(resolve => imageCanvas.toBlob(resolve, mimeType, quality))
251251
const response = await axios.put(putUrl, new File([blob], fullName))
252-
253252
logger.info('Edited image saved!', { response })
254253
showSuccess(t('viewer', 'Image saved'))
255254
if (putUrl !== this.src) {
256-
emit('files:node:created', { fileid: parseInt(response?.headers?.['oc-fileid']?.split('oc')[0]) || null })
255+
const fileId = parseInt(response?.headers?.['oc-fileid']?.split('oc')[0]) || null
256+
emit('editor:file:created', putUrl)
257+
if (fileId) {
258+
const newParams = window.OCP.Files.Router.params
259+
newParams.fileId = fileId
260+
window.OCP.Files.Router.goToRoute(null, newParams, window.OCP.Files.Router.query)
261+
}
257262
} else {
258263
this.$emit('updated')
259264
const updatedFile = await rawStat(origin, decodeURI(pathname))

src/services/FetchFile.ts

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

src/utils/fileUtils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
*/
2222
import type { FileStat } from 'webdav'
2323
import { encodePath } from '@nextcloud/paths'
24+
import { getCurrentUser } from '@nextcloud/auth'
2425
import camelcase from 'camelcase'
2526

2627
import { isNumber } from './numberUtil'
@@ -41,6 +42,24 @@ const extractFilePaths = function(path) {
4142
return [dirPath, fileName]
4243
}
4344

45+
/**
46+
* Extract path from source
47+
*
48+
* @param source the full source URL
49+
* @return path
50+
*/
51+
export function extractFilePathFromSource(source: string): string {
52+
const uid = getCurrentUser()?.uid
53+
54+
if (uid) {
55+
const path = source.split(`${uid}/`)[1]
56+
if (path) {
57+
return path
58+
}
59+
}
60+
throw new Error(`Invalid source URL: ${source}. Unable to extract file paths.`)
61+
}
62+
4463
/**
4564
* Sorting comparison function
4665
*

src/views/Viewer.vue

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@
163163
:is-sidebar-shown="isSidebarShown"
164164
:loaded.sync="currentFile.loaded"
165165
class="viewer__file viewer__file--active"
166+
@update:editing="toggleEditor"
166167
@error="currentFailed" />
167168
<Error v-else
168169
:name="currentFile.basename" />
@@ -208,6 +209,7 @@ import canDownload from '../utils/canDownload.js'
208209
import Error from '../components/Error.vue'
209210
import File from '../models/file.js'
210211
import getFileInfo from '../services/FileInfo.ts'
212+
import fetchNode from '../services/FetchFile.ts'
211213
import getFileList from '../services/FileList.ts'
212214
import legacyFilesActionHandler from '../services/LegacyFilesActionHandler.js'
213215
import logger from '../services/logger.js'
@@ -563,6 +565,7 @@ export default defineComponent({
563565
subscribe('files:node:updated', this.handleFileUpdated)
564566
subscribe('viewer:trapElements:changed', this.handleTrapElementsChange)
565567
subscribe('editor:toggle', this.toggleEditor)
568+
subscribe('editor:file:created', this.handleNewFile)
566569
window.addEventListener('keydown', this.keyboardDeleteFile)
567570
window.addEventListener('keydown', this.keyboardDownloadFile)
568571
window.addEventListener('keydown', this.keyboardEditFile)
@@ -664,6 +667,22 @@ export default defineComponent({
664667
}
665668
}
666669
},
670+
async handleNewFile(source) {
671+
let path
672+
try {
673+
path = extractFilePathFromSource(source)
674+
this.openFile(path)
675+
676+
} catch (e) {
677+
logger.error('Could not extract file path from source', { source, e })
678+
}
679+
try {
680+
const node = await fetchNode('/' + path)
681+
emit('files:node:created', node)
682+
} catch (e) {
683+
logger.error('Could not fetch new file', { path, e })
684+
}
685+
},
667686
668687
/**
669688
* Open the view and display the clicked file from a known file info object

0 commit comments

Comments
 (0)