Skip to content

Commit 7772cf0

Browse files
WofWcanicodh
andcommitted
fix: "Replace Draft?" prompt not appearing
Namely, when doing - 'Share Profile' - `webxdc.sendToChat()` - bot command click - `mailto:...?body=...` click The issue was described in #5643. The problem was that, since we save the draft the the backend on debounce and not immediately, it is not enough to utilize `BackendRemote.rpc.getDraft()` to check whether a draft is present. So let's instead treat the source of truth for the draft state as being inside of `useDraft`, and overall move more draft logic to inside of `useDraft`. The problem with this, however, is that `useDraft` is not always rendered with the `accountId` and `chatId` that we need, so we have to store the "set draft request" until the correct chat has been selected and loaded. Co-authored-by: Nico de Haen <[email protected]>
1 parent abbd22c commit 7772cf0

File tree

6 files changed

+191
-83
lines changed

6 files changed

+191
-83
lines changed

packages/frontend/src/components/dialogs/ViewProfile/menu.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,9 @@ function ShareProfileDialog(
219219
await createDraftMessage(accountId, chatId, '', {
220220
name: `${contact.displayName}.vcard`,
221221
path: filePath,
222+
viewType: 'Vcard',
223+
deleteTempFileWhenDone: true,
222224
})
223-
runtime.removeTempFile(filePath)
224225
} else {
225226
await createDraftMessage(accountId, chatId, contact.address)
226227
}

packages/frontend/src/components/dialogs/WebxdcSendToChat/index.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,18 @@ export default function WebxdcSaveToChatDialog(props: Props) {
2323
const createDraftMessage = useCreateDraftMessage()
2424

2525
const onChatClick = async (chatId: number) => {
26-
const file2 = file
26+
const file2: Parameters<typeof createDraftMessage>[3] = file
2727
? {
2828
path: await runtime.writeTempFileFromBase64(
2929
file.file_name,
3030
file.file_content
3131
),
3232
name: file.file_name,
33+
deleteTempFileWhenDone: true,
34+
// viewType: undefined
3335
}
3436
: undefined
3537
await createDraftMessage(accountId, chatId, messageText ?? '', file2)
36-
if (file2) {
37-
await runtime.removeTempFile(file2.path)
38-
}
3938
onClose()
4039
}
4140

packages/frontend/src/components/message/MessageParser.tsx

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import { BackendRemote } from '../../backend-com'
1212
import { selectedAccountId } from '../../ScreenController'
1313
import { MessagesDisplayContext } from '../../contexts/MessagesDisplayContext'
1414
import useChat from '../../hooks/chat/useChat'
15-
import useConfirmationDialog from '../../hooks/dialog/useConfirmationDialog'
1615
import useCreateChatByEmail from '../../hooks/chat/useCreateChatByEmail'
1716

1817
const log = getLogger('renderer/message-parser')
@@ -237,7 +236,6 @@ function BotCommandSuggestion({
237236
suggestion: string
238237
tabIndex: -1 | 0
239238
}) {
240-
const openConfirmationDialog = useConfirmationDialog()
241239
const messageDisplay = useContext(MessagesDisplayContext)
242240
const accountId = selectedAccountId()
243241
const { selectChat } = useChat()
@@ -269,42 +267,16 @@ function BotCommandSuggestion({
269267
return
270268
}
271269

272-
// IDEA: Optimisation - unify these two calls in a new backend call that only returns the info we need
273-
const [chat, draft] = await Promise.all([
274-
BackendRemote.rpc.getBasicChatInfo(accountId, chatId),
275-
BackendRemote.rpc.getDraft(accountId, chatId),
276-
])
277-
278-
if (!chat) {
279-
log.error('chat not defined')
280-
return
281-
}
282-
283-
const { name } = chat
284-
285-
if (draft) {
286-
// Ask if the draft should be replaced
287-
const confirmed: boolean = await openConfirmationDialog({
288-
message: window.static_translate('confirm_replace_draft', name),
289-
confirmLabel: window.static_translate('replace_draft'),
290-
})
291-
292-
if (!confirmed) {
293-
return
294-
}
270+
// Copy-pasted from `useCreateDraftMesssage`.
271+
if (window.__setDraftRequest != undefined) {
272+
log.error('previous BotCommandSuggestion has not worked?')
295273
}
296-
297-
await BackendRemote.rpc.miscSetDraft(
274+
window.__setDraftRequest = {
298275
accountId,
299276
chatId,
300-
suggestion,
301-
null,
302-
null,
303-
null,
304-
'Text'
305-
)
306-
307-
window.__reloadDraft && window.__reloadDraft()
277+
text: suggestion,
278+
}
279+
window.__checkSetDraftRequest?.()
308280
}
309281

310282
return (

packages/frontend/src/global.d.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,35 @@ declare global {
1818
__settingsOpened: boolean
1919
__keybindingsDialogOpened: boolean
2020
__aboutDialogOpened: boolean
21+
2122
__setQuoteInDraft: ((msgId: number) => void) | null
23+
/**
24+
* Setting this will make `useDraft` set the draft to this state,
25+
* as soon as it renders with the specified `accountId` and `chatId`.
26+
*
27+
* @see {@linkcode __internal_jump_to_message_asap}
28+
*/
29+
__setDraftRequest?: {
30+
accountId: number
31+
chatId: number
32+
file?: {
33+
path: string
34+
name?: string
35+
viewType: T.Viewtype
36+
deleteTempFileWhenDone: boolean
37+
}
38+
text?: string
39+
}
40+
/**
41+
* This should be called after assigning to {@linkcode __setDraftRequest}
42+
* so that we don't have to wait for `useDraft` to re-render.
43+
*
44+
* @see {@linkcode __internal_check_jump_to_message}
45+
*/
46+
__checkSetDraftRequest?: () => void
47+
2248
__enterEditMessageMode: ((messageToEdit: T.Message) => void) | null
23-
__reloadDraft: (() => void) | null
49+
2450
__chatlistSetSearch:
2551
| ((searchTerm: string, chatId: number | null) => void)
2652
| undefined
@@ -39,6 +65,8 @@ declare global {
3965
* Ensuring that MessageList _will_ load the chat with the specified
4066
* `accountId` and `chatId` is the responsibility of whoever
4167
* accesses this property.
68+
*
69+
* @see {@linkcode __setDraftRequest}
4270
*/
4371
__internal_jump_to_message_asap?: {
4472
accountId: number
@@ -66,6 +94,7 @@ declare global {
6694
*
6795
* This property is managed by the MessageList component instance,
6896
* it gets assigned when the component gets rendered.
97+
* @see {@linkcode __checkSetDraftRequest}
6998
*/
7099
__internal_check_jump_to_message?: () => void
71100
/**
Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
import { useCallback } from 'react'
22

33
import useChat from './useChat'
4-
import useConfirmationDialog from '../dialog/useConfirmationDialog'
5-
import useTranslationFunction from '../useTranslationFunction'
6-
import { BackendRemote } from '../../backend-com'
4+
import { getLogger } from '@deltachat-desktop/shared/logger'
5+
import type { T } from '@deltachat/jsonrpc-client'
6+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
7+
import type { runtime } from '@deltachat-desktop/runtime-interface'
8+
9+
const log = getLogger('useCreateDraftMessage')
710

811
export type CreateDraftMessage = (
912
accountId: number,
1013
chatId: number,
1114
messageText: string,
12-
file?: { path: string; name?: string }
15+
file?: {
16+
path: string
17+
name?: string
18+
viewType?: T.Viewtype
19+
/**
20+
* If the provided file is a temp file, set this to `true`,
21+
* and the file will be deleted (with {@linkcode runtime.removeTempFile})
22+
* when we're done adding it to the draft (or if something failed).
23+
*/
24+
deleteTempFileWhenDone: boolean
25+
}
1326
) => Promise<void>
1427

1528
/**
@@ -19,45 +32,29 @@ export type CreateDraftMessage = (
1932
* replace it.
2033
*/
2134
export default function useCreateDraftMessage() {
22-
const tx = useTranslationFunction()
23-
const openConfirmationDialog = useConfirmationDialog()
2435
const { selectChat } = useChat()
2536

2637
return useCallback<CreateDraftMessage>(
2738
async (accountId, chatId, messageText, file) => {
28-
const draft = await BackendRemote.rpc.getDraft(accountId, chatId)
29-
3039
selectChat(accountId, chatId)
3140

32-
if (draft) {
33-
const { name } = await BackendRemote.rpc.getBasicChatInfo(
34-
accountId,
35-
chatId
36-
)
37-
38-
// Ask if the draft should be replaced
39-
const continueProcess = await openConfirmationDialog({
40-
message: tx('confirm_replace_draft', name),
41-
confirmLabel: tx('replace_draft'),
42-
})
43-
44-
if (!continueProcess) {
45-
return
46-
}
41+
if (window.__setDraftRequest != undefined) {
42+
log.error('previous createDraftMessage has not worked?')
4743
}
48-
49-
await BackendRemote.rpc.miscSetDraft(
44+
window.__setDraftRequest = {
5045
accountId,
5146
chatId,
52-
messageText,
53-
file?.path || null,
54-
file?.name || null,
55-
null,
56-
file ? 'File' : 'Text'
57-
)
58-
59-
window.__reloadDraft?.()
47+
file: file
48+
? {
49+
...file,
50+
// Should we make `viewType` required?
51+
viewType: file.viewType ?? 'File',
52+
}
53+
: undefined,
54+
text: messageText,
55+
}
56+
window.__checkSetDraftRequest?.()
6057
},
61-
[tx, openConfirmationDialog, selectChat]
58+
[selectChat]
6259
)
6360
}

0 commit comments

Comments
 (0)