1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-24 20:19:10 +02:00

iOS: Rich Text Editor: Fix the "edit" button for code blocks (#12924)

This commit is contained in:
Henry Heino
2025-08-18 08:46:02 -07:00
committed by GitHub
parent ab3e9d1a3e
commit c92701c52f
5 changed files with 57 additions and 10 deletions

View File

@@ -1104,6 +1104,7 @@ packages/editor/ProseMirror/types.js
packages/editor/ProseMirror/utils/UndoStackSynchronizer.js
packages/editor/ProseMirror/utils/canReplaceSelectionWith.js
packages/editor/ProseMirror/utils/computeSelectionFormatting.js
packages/editor/ProseMirror/utils/dom/createButton.js
packages/editor/ProseMirror/utils/dom/createTextArea.js
packages/editor/ProseMirror/utils/dom/createTextNode.js
packages/editor/ProseMirror/utils/dom/createUniqueId.js

1
.gitignore vendored
View File

@@ -1077,6 +1077,7 @@ packages/editor/ProseMirror/types.js
packages/editor/ProseMirror/utils/UndoStackSynchronizer.js
packages/editor/ProseMirror/utils/canReplaceSelectionWith.js
packages/editor/ProseMirror/utils/computeSelectionFormatting.js
packages/editor/ProseMirror/utils/dom/createButton.js
packages/editor/ProseMirror/utils/dom/createTextArea.js
packages/editor/ProseMirror/utils/dom/createTextNode.js
packages/editor/ProseMirror/utils/dom/createUniqueId.js

View File

@@ -13,14 +13,16 @@ interface Options {
doneLabel: string|Promise<string>;
block: SourceBlockData;
onSave: (newContent: SourceBlockData)=> void;
onDismiss: ()=> void;
}
const createEditorDialog = ({ editorLabel, doneLabel, block, onSave }: Options) => {
const createEditorDialog = ({ editorLabel, doneLabel, block, onSave, onDismiss }: Options) => {
const dialog = document.createElement('dialog');
dialog.classList.add('editor-dialog', '-visible');
document.body.appendChild(dialog);
dialog.onclose = () => {
onDismiss();
dialog.remove();
};

View File

@@ -5,8 +5,8 @@ import sanitizeHtml from '../../utils/sanitizeHtml';
import createEditorDialog from './createEditorDialog';
import { getEditorApi } from '../joplinEditorApiPlugin';
import { msleep } from '@joplin/utils/time';
import createTextNode from '../../utils/dom/createTextNode';
import postProcessRenderedHtml from './postProcessRenderedHtml';
import createButton from '../../utils/dom/createButton';
import makeLinksClickableInElement from '../../utils/makeLinksClickableInElement';
// See the fold example for more information about
@@ -117,6 +117,7 @@ export const nodeSpecs = {
type GetPosition = ()=> number;
class EditableSourceBlockView implements NodeView {
private editDialogVisible_ = false;
public readonly dom: HTMLElement;
public constructor(private node: Node, inline: boolean, private view: EditorView, private getPosition: GetPosition) {
if ((node.attrs.contentHtml ?? undefined) === undefined) {
@@ -134,6 +135,10 @@ class EditableSourceBlockView implements NodeView {
}
private showEditDialog_() {
if (this.editDialogVisible_) {
return;
}
const { localize: _ } = getEditorApi(this.view.state);
let saveCounter = 0;
@@ -177,6 +182,9 @@ class EditableSourceBlockView implements NodeView {
),
);
},
onDismiss: () => {
this.editDialogVisible_ = false;
},
});
}
@@ -187,16 +195,10 @@ class EditableSourceBlockView implements NodeView {
const attrs = this.node.attrs as JoplinEditableAttributes;
const addEditButton = () => {
const editButton = document.createElement('button');
editButton.classList.add('edit');
const { localize: _ } = getEditorApi(this.view.state);
editButton.appendChild(createTextNode(_('Edit')));
editButton.onclick = (event) => {
this.showEditDialog_();
event.preventDefault();
};
const editButton = createButton(_('Edit'), () => this.showEditDialog_());
editButton.classList.add('edit');
if (!attrs.readOnly) {
this.dom.appendChild(editButton);

View File

@@ -0,0 +1,41 @@
import { LocalizationResult } from '../../../types';
import createTextNode from './createTextNode';
type OnClick = ()=> void;
const createButton = (label: LocalizationResult, onClick: OnClick) => {
const button = document.createElement('button');
button.appendChild(createTextNode(label));
// Works around an issue on iOS in which certain <button> elements within the selected
// region of a contenteditable container do not emit a "click" event when tapped with a touchscreen.
const applyIOSClickWorkaround = () => {
// touchend events can be received even when a touch is no longer contained within
// the initial element.
const buttonContainsTouch = (touch: Touch) => {
return document.elementFromPoint(touch.clientX, touch.clientY) === button;
};
let containedTouchStart = false;
button.addEventListener('touchcancel', () => {
containedTouchStart = false;
});
button.addEventListener('touchstart', () => {
containedTouchStart = true;
});
button.addEventListener('touchend', (event) => {
if (containedTouchStart && event.touches.length === 0 && buttonContainsTouch(event.changedTouches[0])) {
onClick();
event.preventDefault();
}
containedTouchStart = false;
});
};
applyIOSClickWorkaround();
button.onclick = onClick;
return button;
};
export default createButton;