Skip to content

Commit 021522c

Browse files
fix: add close button when open readonly files on mobile app
Signed-off-by: Luka Trovic <luka@nextcloud.com>
1 parent 4caa745 commit 021522c

File tree

4 files changed

+80
-48
lines changed

4 files changed

+80
-48
lines changed

src/components/Editor.vue

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
:dirty="dirty"
3434
:sync-error="syncError"
3535
:has-connection-issue="requireReconnect" />
36+
<button
37+
v-if="isMobileApp"
38+
class="icon-close"
39+
@click="mobileAppClose" />
3640
</ReadonlyBar>
3741
</slot>
3842
</div>
@@ -104,6 +108,7 @@ import { useSyntaxHighlighting } from '../composables/useSyntaxHighlighting.ts'
104108
import { CollaborationCursor } from '../extensions/index.js'
105109
import { exposeForDebugging, removeFromDebugging } from '../helpers/debug.js'
106110
import { logger } from '../helpers/logger.js'
111+
import { callMobileMessage, isMobileApp } from '../helpers/mobileApp.js'
107112
import { setInitialYjsState } from '../helpers/setInitialYjsState.js'
108113
import { ERROR_TYPE, IDLE_TIMEOUT } from '../services/SyncService.ts'
109114
import { fetchNode } from '../services/WebdavClient.ts'
@@ -363,6 +368,9 @@ export default defineComponent({
363368
},
364369
}
365370
},
371+
isMobileApp() {
372+
return isMobileApp()
373+
},
366374
},
367375
watch: {
368376
displayed() {
@@ -693,6 +701,13 @@ export default defineComponent({
693701
}
694702
},
695703
704+
async mobileAppClose() {
705+
setTimeout(async () => {
706+
await this.$destroy()
707+
callMobileMessage('close')
708+
}, 0)
709+
},
710+
696711
/**
697712
* Wrapper to emit events on our own and the parent component
698713
*

src/components/Menu/ReadonlyBar.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,11 @@ export default defineComponent({
7777
display: flex;
7878
flex-grow: 1;
7979
}
80+
.text-menubar__slot {
81+
display: flex;
82+
align-items: center;
83+
}
84+
:deep(.icon-close) {
85+
background-color: transparent;
86+
}
8087
</style>

src/helpers/mobileApp.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
import { logger } from './logger.js'
6+
7+
export const isMobileApp = () => {
8+
return (
9+
window.DirectEditingMobileInterface
10+
|| (window.webkit
11+
&& window.webkit.messageHandlers
12+
&& window.webkit.messageHandlers.DirectEditingMobileInterface)
13+
)
14+
}
15+
16+
export const callMobileMessage = (messageName, attributes) => {
17+
logger.debug(`callMobileMessage ${messageName}`, { attributes })
18+
let message = messageName
19+
if (typeof attributes !== 'undefined') {
20+
message = {
21+
MessageName: messageName,
22+
Values: attributes,
23+
}
24+
}
25+
let attributesString = null
26+
try {
27+
attributesString = JSON.stringify(attributes)
28+
} catch (e) {
29+
attributesString = null
30+
}
31+
32+
// Forward to mobile handler
33+
if (
34+
window.DirectEditingMobileInterface
35+
&& typeof window.DirectEditingMobileInterface[messageName] === 'function'
36+
) {
37+
if (attributesString === null || typeof attributesString === 'undefined') {
38+
window.DirectEditingMobileInterface[messageName]()
39+
} else {
40+
window.DirectEditingMobileInterface[messageName](attributesString)
41+
}
42+
}
43+
44+
// iOS webkit fallback
45+
if (
46+
window.webkit
47+
&& window.webkit.messageHandlers
48+
&& window.webkit.messageHandlers.DirectEditingMobileInterface
49+
) {
50+
window.webkit.messageHandlers.DirectEditingMobileInterface.postMessage(
51+
message,
52+
)
53+
}
54+
55+
window.postMessage(message)
56+
}

src/views/DirectEditing.vue

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -26,54 +26,13 @@ import Vue from 'vue'
2626
import Editor from '../components/Editor.vue'
2727
2828
import { logger } from '../helpers/logger.js'
29+
import { callMobileMessage, isMobileApp } from '../helpers/mobileApp.js'
2930
3031
const log = Vue.observable({
3132
messages: [],
3233
mtime: 0,
3334
})
3435
35-
const callMobileMessage = (messageName, attributes) => {
36-
logger.debug(`callMobileMessage ${messageName}`, { attributes })
37-
let message = messageName
38-
if (typeof attributes !== 'undefined') {
39-
message = {
40-
MessageName: messageName,
41-
Values: attributes,
42-
}
43-
}
44-
let attributesString = null
45-
try {
46-
attributesString = JSON.stringify(attributes)
47-
} catch (e) {
48-
attributesString = null
49-
}
50-
51-
// Forward to mobile handler
52-
if (
53-
window.DirectEditingMobileInterface
54-
&& typeof window.DirectEditingMobileInterface[messageName] === 'function'
55-
) {
56-
if (attributesString === null || typeof attributesString === 'undefined') {
57-
window.DirectEditingMobileInterface[messageName]()
58-
} else {
59-
window.DirectEditingMobileInterface[messageName](attributesString)
60-
}
61-
}
62-
63-
// iOS webkit fallback
64-
if (
65-
window.webkit
66-
&& window.webkit.messageHandlers
67-
&& window.webkit.messageHandlers.DirectEditingMobileInterface
68-
) {
69-
window.webkit.messageHandlers.DirectEditingMobileInterface.postMessage(
70-
message,
71-
)
72-
}
73-
74-
window.postMessage(message)
75-
}
76-
7736
window.addEventListener('message', function (message) {
7837
log.messages.push(message.data)
7938
logger.debug('postMessage', { message })
@@ -95,12 +54,7 @@ export default {
9554
return JSON.parse(this.initial.session) || null
9655
},
9756
isMobile() {
98-
return (
99-
window.DirectEditingMobileInterface
100-
|| (window.webkit
101-
&& window.webkit.messageHandlers
102-
&& window.webkit.messageHandlers.DirectEditingMobileInterface)
103-
)
57+
return isMobileApp()
10458
},
10559
},
10660
beforeMount() {

0 commit comments

Comments
 (0)