0.2.88
This commit is contained in:
1 parent
df403c0aa7
commit
9e133628e5
17 files changed
+270
-34
No files matched your search
@@ -4099,6 +4099,16 @@ dialog::backdrop {
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.markdown-body .task-list-item--cancelled>.list-item-content {
|
||||
text-decoration: line-through;
|
||||
color: var(--text-subtle);
|
||||
}
|
||||
|
||||
.markdown-body .task-list-item--cancelled>.task-checkbox {
|
||||
cursor: not-allowed;
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
.markdown-body .task-list-item>ul,
|
||||
.markdown-body .task-list-item>ol {
|
||||
min-width: 0;
|
||||
|
||||
@@ -274,7 +274,7 @@ function renderStandaloneMedia(line, sourceLine) {
|
||||
}
|
||||
|
||||
function listLine(line) {
|
||||
const match = line.match(/^(\s*)([-*+]|(\d+)\.)\s+(?:\[([ xX])\]\s+)?(.+)$/);
|
||||
const match = line.match(/^(\s*)([-*+]|(\d+)\.)\s+(?:\[([ xX~])\]\s+)?(.+)$/);
|
||||
if (!match) return null;
|
||||
const indent = match[1].replace(/\t/g, " ").length;
|
||||
return {
|
||||
@@ -283,6 +283,7 @@ function listLine(line) {
|
||||
type: match[3] ? "ol" : "ul",
|
||||
number: match[3] ? Number(match[3]) : null,
|
||||
checked: match[4] == null ? null : match[4].toLowerCase() === "x",
|
||||
cancelled: match[4] === "~",
|
||||
text: match[5],
|
||||
marker: match[3] ? `${match[3]}. ` : `${match[2]} `
|
||||
};
|
||||
@@ -302,14 +303,14 @@ function renderList(lines, start, lineOffset = 0, baseIndent = null, forcedType
|
||||
if (!item || item.indent < indent || item.indent !== indent || item.type !== type) break;
|
||||
|
||||
const sourceLine = index + lineOffset + 1;
|
||||
const prefix = `${item.whitespace}${item.marker}${item.checked == null ? "" : `[${item.checked ? "x" : " "}] `}`;
|
||||
const prefix = `${item.whitespace}${item.marker}${item.checked == null ? "" : `[${item.cancelled ? "~" : item.checked ? "x" : " "}] `}`;
|
||||
const valueAttr = "";
|
||||
const taskClass = item.checked == null ? "" : " task-list-item";
|
||||
const taskClass = item.checked == null ? "" : ` task-list-item${item.cancelled ? " task-list-item--cancelled" : ""}`;
|
||||
hasTask ||= item.checked != null;
|
||||
const gutterOffset = `${(depth + 1) * 1.75}em`;
|
||||
body += `<li class="preview-source-line list-source-line${taskClass}" data-source-line="${sourceLine}"${valueAttr} style="--list-gutter-offset:${gutterOffset}">`;
|
||||
if (item.checked != null) {
|
||||
body += `<input type="checkbox" class="task-checkbox" data-source-line="${sourceLine}"${item.checked ? " checked" : ""}>`;
|
||||
body += `<input type="checkbox" class="task-checkbox" data-source-line="${sourceLine}"${item.checked ? " checked" : ""}${item.cancelled ? " disabled aria-label=\"Cancelled task\"" : ""}>`;
|
||||
}
|
||||
body += `<span class="preview-editable list-item-content" data-source-line="${sourceLine}" data-source-prefix="${escapeHtml(prefix)}">${inline(item.text)}</span>`;
|
||||
index++;
|
||||
|
||||
@@ -1247,6 +1247,21 @@ export function startNoteEditor(adapter) {
|
||||
});
|
||||
}
|
||||
const render = createRenderQueue(renderNow);
|
||||
// Collaborative edits can arrive many times per second. Keep typing and
|
||||
// WebSocket processing responsive by batching expensive Markdown/DOM work.
|
||||
let deferredRenderTimer = null;
|
||||
let firstDeferredRenderAt = 0;
|
||||
function scheduleDocumentRender() {
|
||||
const now = performance.now();
|
||||
if (deferredRenderTimer === null) firstDeferredRenderAt = now;
|
||||
else clearTimeout(deferredRenderTimer);
|
||||
const delay = Math.min(180, Math.max(0, 750 - (now - firstDeferredRenderAt)));
|
||||
deferredRenderTimer = setTimeout(() => {
|
||||
deferredRenderTimer = null;
|
||||
firstDeferredRenderAt = 0;
|
||||
render();
|
||||
}, delay);
|
||||
}
|
||||
function queueCollaborativeOperation(operation, ownerReplacements = []) {
|
||||
if (!collaboration.ready || !canEditDocument()) return false;
|
||||
try {
|
||||
@@ -1407,7 +1422,7 @@ export function startNoteEditor(adapter) {
|
||||
if (ownerMap != null) authorship = adoptCurrentOwnerAliases(parseAuthorship(content, ownerMap), content.length);
|
||||
previousContent = content;
|
||||
editHistory.syncCurrent();
|
||||
renderGutter();
|
||||
scheduleDocumentRender();
|
||||
requestAnimationFrame(revealLinkedLine);
|
||||
return;
|
||||
}
|
||||
@@ -1427,7 +1442,7 @@ export function startNoteEditor(adapter) {
|
||||
applyingRemote = false;
|
||||
if (resetHistory) editHistory.reset();
|
||||
else editHistory.syncCurrent();
|
||||
render();
|
||||
scheduleDocumentRender();
|
||||
editor.scrollTop = initialLoad ? 0 : scrollTop;
|
||||
editor.scrollLeft = scrollLeft;
|
||||
syncEditorLayers();
|
||||
@@ -2238,7 +2253,7 @@ export function startNoteEditor(adapter) {
|
||||
});
|
||||
preview.addEventListener("change", event => {
|
||||
const checkbox = event.target.closest(".task-checkbox");
|
||||
if (!checkbox) return;
|
||||
if (!checkbox || checkbox.disabled) return;
|
||||
if (!canEditDocument()) {
|
||||
checkbox.checked = !checkbox.checked;
|
||||
saveState.textContent = "Read only";
|
||||
@@ -2488,7 +2503,7 @@ export function startNoteEditor(adapter) {
|
||||
authorship = replaceAuthorshipOwner(authorship, owner => ownerName(owner) === nickname, currentOwner(), previous.length);
|
||||
authorship = applyAuthorshipEdit(authorship, previous, nextContent, currentOwner());
|
||||
previousContent = nextContent;
|
||||
render();
|
||||
scheduleDocumentRender();
|
||||
if (applyingRemote || applyingHistory) return;
|
||||
queueCollaborativeOperation(operationFromEdit(previous, nextContent, authorship));
|
||||
editHistory.record(event.inputType || "");
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ async function renderMediaPlayers() { const nodes = content.querySelectorAll("[d
|
||||
function lockPublicContent(allowTaskUpdates) {
|
||||
content.querySelectorAll('[contenteditable]').forEach(node => node.removeAttribute('contenteditable'));
|
||||
content.querySelectorAll('.preview-editable').forEach(node => node.classList.remove('preview-editable'));
|
||||
content.querySelectorAll('.task-checkbox').forEach(box => { box.disabled = !allowTaskUpdates; box.title = allowTaskUpdates ? t("public.task.update", {}, "Update this task") : t("public.task.disabled", {}, "Task updates are disabled by the owner"); });
|
||||
content.querySelectorAll('.task-checkbox').forEach(box => { box.disabled = box.disabled || !allowTaskUpdates; box.title = box.disabled ? t("public.task.update", {}, "Update this task") : t("public.task.disabled", {}, "Task updates are disabled by the owner"); });
|
||||
}
|
||||
function publicAnchorTarget(hash) {
|
||||
const rawId = String(hash || "").replace(/^#/, "");
|
||||
|
||||
Reference in new issue
Block a user