Merge remote-tracking branch 'origin/markdown-toolbar-not-responsive' into staging

This commit is contained in:
yflory 2025-06-23 15:51:10 +02:00
commit 19fe19a3f7
11 changed files with 296 additions and 33 deletions

View File

@ -147,6 +147,9 @@ define(req, function(AppConfig, Default, Language) {
Messages.previous_templateList = "Previous template list";
Messages.contact_mastodon = 'Mastodon'; // XXX
Messages.contact_forum = 'Forum'; // XXX
Messages.toolbar_text_tools = "Text tools";
Messages.toolbar_show_text_tools = "Show text tools";
Messages.toolbar_hide_text_tools = "Hide text tools";
return Messages;

View File

@ -289,3 +289,32 @@
}
}
//reusable styling for the markdown toggle button across all apps
.markdown-toolbar-button-style() {
padding: 3px 5px;
height: fit-content;
margin: 0;
line-height: 1;
border-radius: @variables_radius;
display: inline-flex;
background-color: @cp_toolbar-bottom-bg;
color: @cp_toolbar-bottom-fg;
&:hover {
background-color: fade(@cryptpad_text_col, 20%);
border-color: @cryptpad_text_col;
color: @cryptpad_text_col;
}
&.cp-toolbar-button-active {
background-color: @cp_toolbar-bg;
border-color: @cp_toolbar-fg;
color: @cp_toolbar-fg;
&:hover {
background-color: fade(@cryptpad_text_col, 20%);
}
}
}

View File

@ -64,7 +64,10 @@
}
.cp-markdown-toolbar {
height: @toolbar_line-height;
min-height: @toolbar_line-height;
padding: 0.1rem 0;
height: auto;
flex-wrap: wrap;
background-color: @cp_toolbar-bg;
color: @cp_toolbar-fg;
display: none;
@ -74,7 +77,10 @@
border-radius: @variables_radius;
color: @toolbar-color;
.toolbar_button;
font: normal normal normal 14px/1 FontAwesome;
.fa {
font: normal normal normal 14px/1 FontAwesome;
font-family: FontAwesome;
}
&:hover {
background-color: contrast(@cp_toolbar-bg, darken(@cp_toolbar-bg, 5%), lighten(@cp_toolbar-bg, 5%));
}
@ -85,6 +91,11 @@
button:nth-of-type(1) {
margin-left: 0.3rem;
}
@media screen and (max-width: @browser_media-medium-screen) {
button:nth-of-type(1) {
margin-left: 0;
}
}
}
.cp-toolbar-container {
@ -400,7 +411,6 @@
.fa {
font: normal normal normal 14px/1 FontAwesome;
font-family: FontAwesome;
}
.tools_unselectable();

View File

@ -578,6 +578,13 @@ define([
framework.setCursorGetter(CodeMirror.getCursor);
editor.on('cursorActivity', updateCursor);
editor.setOption("extraKeys", {
"Esc": function(cm, event) {
event.preventDefault();
document.body.focus();
}
});
framework.onEditableChange(function () {
editor.setOption('readOnly', framework.isLocked() || framework.isReadOnly());
});

View File

@ -905,7 +905,8 @@ define([
case 'toggle':
button = $(h('button.cp-toolbar-tools', {
//title: data.title || '', // TODO display if the label text is collapsed
'aria-label': data.text || Messages.toolbar_tools // Fallback
'aria-label': data.text || Messages.toolbar_tools, // Fallback
'aria-pressed': false
}, [
h('i.fa.' + (data.icon || 'fa-wrench')),
h('span.cp-toolbar-name', data.text || Messages.toolbar_tools)
@ -923,6 +924,7 @@ define([
button.click(function (e) {
data.element.toggle();
var isVisible = data.element.is(':visible');
button.attr('aria-pressed', isVisible ? 'true' : 'false');
if (callback) { callback(isVisible); }
if (isVisible) {
button.addClass('cp-toolbar-button-active');
@ -1157,20 +1159,40 @@ define([
};
for (var k in actions) {
let $b = $('<button>', {
'data-notippy':1,
'data-type': k,
'class': 'pure-button fa ' + actions[k].icon,
title: Messages['mdToolbar_' + k] || k
}).click(onClick);
'class': 'pure-button cp-markdown-' + k,
'title': Messages['mdToolbar_' + k] || k,
'aria-label': Messages['mdToolbar_' + k] || k
}).append(
$('<i>', {
'class': 'fa ' + actions[k].icon,
'aria-hidden': 'true'
})).click(onClick);
if (k === "embed") { $toolbar.prepend($b); }
else { $toolbar.append($b); }
}
$('<button>', {
'class': 'pure-button fa fa-question cp-markdown-help',
title: Messages.mdToolbar_help
}).click(function () {
'data-notippy':1,
'class': 'pure-button cp-markdown-help',
'title': Messages.mdToolbar_help,
'aria-label': Messages.mdToolbar_help
}).append(
$('<i>', {
'class': 'fa fa-question',
'aria-hidden': 'true'
})).click(function () {
var href = Messages.mdToolbar_tutorial;
common.openUnsafeURL(href);
}).appendTo($toolbar);
$toolbar.on('keydown', function (e) {
if (e.key === 'Escape' || e.keyCode === 27) {
editor.focus();
e.preventDefault();
}
});
return $toolbar;
};
UIElements.createMarkdownToolbar = function (common, editor, opts) {
@ -1229,6 +1251,71 @@ define([
$toolbarButton.show();
};
function isSmallScreen() {
return window.innerHeight < 530 || window.innerWidth < 530;
}
var toolbarVisibleOnSmallScreen = false;
var $toolbarToggleButton = null;
var appType = common.getMetadataMgr().getPrivateData().app;
function updateToolbarVisibility() {
var $wrapper = $(opts && opts.wrapper ? opts.wrapper : $toolbar.parent());
if (isSmallScreen()) {
if (!$toolbarToggleButton) {
$toolbarToggleButton = $(h('button.btn.cp-markdown-toggle-button', {
'aria-label': Messages.toolbar_show_text_tools,
'aria-pressed': 'false',
'data-notippy': 1,
'type': 'button',
'title': Messages.toolbar_show_text_tools
})).append([
h('i.fa.fa-wrench', { 'aria-hidden': 'true' }),
h('span.cp-toolbar-label', {}, Messages.toolbar_text_tools)
]).click(function () {
var isExpanded = $toolbar.is(':visible');
$toolbar.toggle();
$(this).toggleClass('cp-toolbar-button-active', !isExpanded)
.attr('aria-pressed', String(!isExpanded))
.attr('title', !isExpanded ? Messages.toolbar_hide_text_tools : Messages.toolbar_show_text_tools)
.attr('aria-label', !isExpanded ? Messages.toolbar_hide_text_tools : Messages.toolbar_show_text_tools);
toolbarVisibleOnSmallScreen = !isExpanded;
}).on('keydown keyup', e => {
// don't close modals when pressing Enter
// on the button
e.stopPropagation();
});
$wrapper.append($toolbarToggleButton);
}
if (toolbarVisibleOnSmallScreen) {
$toolbar.show();
$toolbarToggleButton.addClass('cp-toolbar-button-active')
.attr('aria-pressed', 'true');
} else {
$toolbar.hide();
$toolbarToggleButton.removeClass('cp-toolbar-button-active')
.attr('aria-pressed', 'false');
}
} else {
if ($toolbarToggleButton) {
$toolbarToggleButton.remove();
$toolbarToggleButton = null;
}
$toolbar.show();
}
}
if (appType !== 'code' && appType !== 'slide') {
$(window).on('resize', updateToolbarVisibility);
updateToolbarVisibility();
// Small delay to ensure the toolbar layout has rendered before checking for wrapping (ex: profile medium screen size)
setTimeout(() => {
updateToolbarVisibility();
}, 10);
}
return {
toolbar: $toolbar,
button: $toolbarButton,
@ -1318,7 +1405,6 @@ define([
text: text
};
};
/* Create a usage bar which keeps track of how much storage space is used
by your CryptDrive. The getPinnedUsage RPC is one of the heavier calls,
so we throttle its usage. Clients will not update more than once per

View File

@ -176,6 +176,16 @@
flex: 1;
justify-content: center;
min-width: 300px;
.cp-markdown-toggle-row {
margin: 0.5rem 0;
position: relative;
.cp-markdown-toggle-button {
.markdown-toolbar-button-style() !important;
&.cp-toolbar-button-active {
background-color: transparent !important;
}
}
}
div.timeline-container {
width: 100%;
@ -381,6 +391,12 @@
}
}
}
div.cp-form-response-msg-container {
.cp-markdown-toolbar {
background-color: transparent;
border-radius: @variables_radius @variables_radius 0 0;
}
}
}
div.cp-form-creator-results {
.cp-form-block {
@ -431,6 +447,14 @@
}
}
.cp-editor-wrapper {
.cp-form-edit-options-block {
padding: 1px;
overflow: hidden;
border: 1px solid @cp_forms-border;
}
}
.cp-form-creator-add-inline {
display: flex;
flex-flow: row;
@ -532,7 +556,6 @@
padding-bottom: 75px;
button {
white-space: initial;
line-height: 25px;
padding: 5.5px 6px;
}
.cp-form-response-msg-hint {
@ -819,6 +842,9 @@
display: flex;
flex-wrap: wrap;
align-items: baseline;
border-radius: @variables_radius;
margin-top: 0.5rem;
padding: 1px;
.CodeMirror {
cursor: default;
flex: 1;
@ -827,13 +853,16 @@
width: 80%;
min-height: 200px;
height: 200px;
border: 1px solid @cp_forms-border;
.CodeMirror-placeholder {
color: #777;
}
}
.cp-markdown-toolbar {
display: block;
padding: 0.1rem 0;
border-radius: @variables_radius 0;
width: 100%;
background-color: transparent;
}
}
.cp-form-edit-block {
@ -1358,8 +1387,12 @@
}
}
.cp-form-response-modal {
.CodeMirror {
.cp-form-markdown-editor-wrapper {
border: 1px solid @cp_forms-border;
border-radius: @variables_radius;
}
.CodeMirror {
border-radius: 0 0 @variables_radius @variables_radius;
}
}

View File

@ -1098,6 +1098,7 @@ define([
editor.setOption("extraKeys", {
"Esc": function () {
editor.display.input.blur();
$(cancelBlock).focus();
},
});
editor.setOption('lineNumbers', true);
@ -1115,18 +1116,25 @@ define([
}
editor.refresh();
editor.save();
editor.focus();
var firstBtn = $(markdownTb.toolbar).find('button').get(0);
if (firstBtn) {
firstBtn.focus();
} else {
editor.focus(); // fallback
}
});
var toggleRow = h('div.cp-markdown-toggle-row');
if (APP.common && !(tmp && tmp.block) && cm) {
var markdownTb = APP.common.createMarkdownToolbar(editor, {
embed: function (mt) {
editor.focus();
editor.replaceSelection($(mt)[0].outerHTML);
}
},
wrapper: toggleRow
});
$(block).prepend(markdownTb.toolbar);
$(markdownTb.toolbar).show();
$(block).prepend(toggleRow);
cm.configureTheme(APP.common, function () {});
}
@ -1159,8 +1167,13 @@ define([
};
};
var outerWrapper = h('div.cp-editor-wrapper', [
toggleRow,
block
]);
return [
block,
outerWrapper,
cancelBlock
];
},
@ -5561,30 +5574,39 @@ define([
]);
var editButtons = h('div.cp-form-edit-buttons-container', [ preview, edit, del ]);
var toggleRow = h('div.cp-markdown-toggle-row');
var markdownWrapper = h('div.cp-form-markdown-editor-wrapper', t);
var editDiv, previewDiv;
var div = h('div.cp-form-block.editable.nodrag.cp-form-submit-message', [
h('div.cp-form-block-content', [
p,
editDiv = h('div.cp-form-response-modal', t),
editDiv = h('div.cp-form-response-modal', toggleRow, markdownWrapper),
previewDiv = h('div.cp-form-response-preview#cp-response-preview'),
editButtons
]),
]);
var cm = APP.responseCM = SFCodeMirror.create("gfm", CMeditor, t);
var editor = APP.responseEditor = cm.editor;
editor.setOption("extraKeys", {
"Esc": function() {
editor.display.input.blur();
$(preview).focus();
}
});
var markdownTb = APP.common.createMarkdownToolbar(editor, {
embed: function (mt) {
editor.focus();
editor.replaceSelection($(mt)[0].outerHTML);
}
},
wrapper: toggleRow
});
var $tb = $(markdownTb.toolbar).insertAfter($(p));
$(markdownWrapper).prepend(markdownTb.toolbar);
var $edit = $(editDiv);
var $preview = $(previewDiv);
var $p = $(preview);
var $e = $(edit);
var $tb = $(markdownTb);
var previewState = true;
var updatePreview = function () {
@ -5601,6 +5623,14 @@ define([
$preview.hide();
editor.refresh();
$tb.show();
setTimeout(function () {
var firstBtn = $(markdownTb.toolbar).find('button').get(0);
if (firstBtn) {
firstBtn.focus();
} else {
editor.focus(); // fallback
}
}, 0);
});
APP.$e = $e;
APP.$p = $p;

View File

@ -120,9 +120,31 @@
}
margin-bottom: 5px;
}
.cp-markdown-label-row {
margin-bottom: 0.5rem;
position: relative;
}
.cp-markdown-label-row label {
display: inline-block;
margin: 0;
vertical-align: middle;
}
.cp-markdown-toggle-button {
.markdown-toolbar-button-style();
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
&.cp-toolbar-button-active {
background-color: transparent;
}
}
#cp-kanban-edit-body {
border: 1px solid @cp_forms-border;
border-radius: @variables_radius;
overflow: hidden;
.CodeMirror {
height: 105px;
resize: vertical;
@ -132,7 +154,7 @@
box-sizing: content-box;
}
.cp-markdown-toolbar {
background-color: @cp_kanban-conflict-bg;
background-color: transparent;
color: @cp_kanban-fg;
border-radius: @variables_radius @variables_radius 0px 0px;
button {
@ -141,6 +163,20 @@
color: @cp_kanban-conflict-bg;
}
}
.btn {
outline: 0;
border-radius: @variables_radius;
.fa {
font: normal normal normal 14px/1 FontAwesome;
font-family: FontAwesome;
}
&:hover {
background-color: contrast(@cp_toolbar-bg, darken(@cp_toolbar-bg, 5%), lighten(@cp_toolbar-bg, 5%));
}
&:focus-visible {
outline: @variables_focus_style;
}
}
}
margin-bottom: 15px;
}

View File

@ -174,7 +174,6 @@ define([
}
_updateBoardsThrottle(framework, kanban, boards);
};
var editModal;
var PROPERTIES = ['title', 'body', 'tags', 'color'];
var BOARD_PROPERTIES = ['title', 'color'];
@ -200,6 +199,10 @@ define([
commit();
});
var markdownEditorWrapper = h('div.cp-markdown-label-row', [
h('label', { for: 'cp-kanban-edit-body' }, Messages.kanban_body)
]);
var conflicts, conflictContainer, titleInput, tagsDiv, text;
var content = h('div', [
conflictContainer = h('div#cp-kanban-edit-conflicts', [
@ -208,7 +211,7 @@ define([
]),
h('label', {for:'cp-kanban-edit-title'}, Messages.kanban_title),
titleInput = h('input#cp-kanban-edit-title'),
h('label', {for:'cp-kanban-edit-body'}, Messages.kanban_body),
markdownEditorWrapper,
h('div#cp-kanban-edit-body', [
text = h('textarea')
]),
@ -280,10 +283,20 @@ define([
embed: function (mt) {
editor.focus();
editor.replaceSelection($(mt)[0].outerHTML);
},
wrapper: markdownEditorWrapper
});
$(markdownTb.toolbar).on('keydown', function (e) {
if (e.which === 27) { // Escape key
e.preventDefault();
e.stopPropagation();
editor.focus(); // Focus the editor instead of closing the modal
}
else if (e.which === 13 || e.which === 9) { // "Enter" or "Tab" key should not close modal
e.stopPropagation();
}
});
$(text).before(markdownTb.toolbar);
$(markdownTb.toolbar).show();
editor.refresh();
var body = {
getValue: function () {

View File

@ -113,6 +113,12 @@
margin: 5px !important;
}
}
.cp-markdown-toggle-row {
margin-bottom: 0.5rem;
.btn.cp-markdown-toggle-button {
.markdown-toolbar-button-style() !important;
}
}
.cp-app-profile-resizer {
text-align: center;
@ -207,9 +213,9 @@
.cp-app-profile-description-code {
display: none;
.cp-markdown-toolbar {
display: flex;
height: auto;
flex-wrap: wrap;
max-width: 31rem;
background-color: @cp_toolbar-bg;
border-radius: @variables_radius @variables_radius 0 0;
}
}
#cp-app-profile-description-info {
@ -232,6 +238,7 @@
font-size: 16px;
line-height: initial;
max-width: 31rem;
border-radius: 0 0 @variables_radius @variables_radius;
pre {
margin: 0;
font-family: inherit;

View File

@ -558,19 +558,28 @@ define([
cm.configureTheme(common, function () {});
editor.setOption("extraKeys", {
"Esc": function () {
cm.getInputField().blur();
editor.getInputField().blur();
$(save).focus();
}
});
var markdownTb = common.createMarkdownToolbar(editor);
var toggleRow = h('div.cp-markdown-toggle-row');
var markdownTb = common.createMarkdownToolbar(editor, {
wrapper: toggleRow
});
$(code).prepend(markdownTb.toolbar);
$(markdownTb.toolbar).show();
$(code).prepend(toggleRow);
if(!Util.isSmallScreen()) {
$(markdownTb.toolbar).show();
}
$(button).click(function () {
$(code).show();
APP.editor.refresh();
$(button).hide();
var firstBtn = $(markdownTb.toolbar).find('button').get(0);
if (firstBtn) {
firstBtn.focus();
}
});
$(save).click(function () {
$(save).hide();