diff --git a/apps/files/src/actions/editLocallyAction.ts b/apps/files/src/actions/editLocallyAction.ts
index 7e44927eba29a38ce79393a5b31f1760969c29ee..0badf7e93d418ae2d41c6212e95099eb8d7bba2b 100644
--- a/apps/files/src/actions/editLocallyAction.ts
+++ b/apps/files/src/actions/editLocallyAction.ts
@@ -6,11 +6,62 @@ import { encodePath } from '@nextcloud/paths'
 import { generateOcsUrl } from '@nextcloud/router'
 import { getCurrentUser } from '@nextcloud/auth'
 import { FileAction, Permission, type Node } from '@nextcloud/files'
-import { showError } from '@nextcloud/dialogs'
+import { showError, DialogBuilder } from '@nextcloud/dialogs'
 import { translate as t } from '@nextcloud/l10n'
 import axios from '@nextcloud/axios'
-
 import LaptopSvg from '@mdi/svg/svg/laptop.svg?raw'
+import IconCancel from '@mdi/svg/svg/cancel.svg?raw'
+import IconCheck from '@mdi/svg/svg/check.svg?raw'
+
+const confirmLocalEditDialog = (
+	localEditCallback: (openingLocally: boolean) => void = () => {},
+) => {
+	let callbackCalled = false
+
+	return new DialogBuilder()
+		.setName(t('files', 'Edit file locally'))
+		.setText(t('files', 'The file should now open locally. If you don\'t see this happening, make sure that the desktop client is installed on your system.'))
+		.setButtons([
+			{
+				label: t('files', 'Retry local edit'),
+				icon: IconCancel,
+				callback: () => {
+					callbackCalled = true
+					localEditCallback(false)
+				},
+			},
+			{
+				label: t('files', 'Edit online'),
+				icon: IconCheck,
+				type: 'primary',
+				callback: () => {
+					callbackCalled = true
+					localEditCallback(true)
+				},
+			},
+		])
+		.build()
+		.show()
+		.then(() => {
+			// Ensure the callback is called even if the dialog is dismissed in other ways
+			if (!callbackCalled) {
+				localEditCallback(true)
+			}
+		})
+}
+
+const attemptOpenLocalClient = async (path: string) => {
+	openLocalClient(path)
+	confirmLocalEditDialog(
+		(openLocally: boolean) => {
+			if (!openLocally) {
+				window.OCA.Viewer.open({ path })
+				return
+			}
+			openLocalClient(path)
+		},
+	)
+}
 
 const openLocalClient = async function(path: string) {
 	const link = generateOcsUrl('apps/files/api/v1') + '/openlocaleditor?format=json'
@@ -43,7 +94,7 @@ export const action = new FileAction({
 	},
 
 	async exec(node: Node) {
-		openLocalClient(node.path)
+		attemptOpenLocalClient(node.path)
 		return null
 	},