Redo expanding
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
This commit is contained in:
parent
45d0270bca
commit
61281a855c
2 changed files with 91 additions and 59 deletions
|
@ -501,10 +501,12 @@ $left-gutter: 64px;
|
|||
}
|
||||
}
|
||||
|
||||
.mx_EventTile_content_collapsedCode {
|
||||
pre {
|
||||
max-height: 30vh;
|
||||
}
|
||||
.mx_EventTile_expandedCodeBlock {
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.mx_EventTile_collapsedCodeBlock {
|
||||
max-height: 30vh;
|
||||
}
|
||||
|
||||
.mx_EventTile:hover .mx_EventTile_body pre,
|
||||
|
@ -531,6 +533,35 @@ $left-gutter: 64px;
|
|||
background-color: $message-action-bar-fg-color;
|
||||
}
|
||||
|
||||
|
||||
// Inserted adjacent to <pre> blocks, (See TextualBody)
|
||||
.mx_EventTile_expandButton {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
cursor: pointer;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
mask-image: url($copy-button-url);
|
||||
background-color: $message-action-bar-fg-color;
|
||||
}
|
||||
|
||||
// Inserted adjacent to <pre> blocks, (See TextualBody)
|
||||
.mx_EventTile_collapseButton {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
cursor: pointer;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
mask-image: url($copy-button-url);
|
||||
background-color: $message-action-bar-fg-color;
|
||||
}
|
||||
|
||||
.mx_EventTile_body .mx_EventTile_pre_container:focus-within .mx_EventTile_copyButton,
|
||||
.mx_EventTile_body .mx_EventTile_pre_container:hover .mx_EventTile_copyButton {
|
||||
visibility: visible;
|
||||
|
|
|
@ -35,7 +35,6 @@ import {isPermalinkHost} from "../../../utils/permalinks/Permalinks";
|
|||
import {toRightOf} from "../../structures/ContextMenu";
|
||||
import {copyPlaintext} from "../../../utils/strings";
|
||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||
import classNames from "classnames";
|
||||
|
||||
export default class TextualBody extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -70,7 +69,6 @@ export default class TextualBody extends React.Component {
|
|||
|
||||
// track whether the preview widget is hidden
|
||||
widgetHidden: false,
|
||||
codeBlockExpanded: SettingsStore.getValue("expandCodeByDefault"),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -93,29 +91,70 @@ export default class TextualBody extends React.Component {
|
|||
this.calculateUrlPreview();
|
||||
|
||||
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html") {
|
||||
const blocks = ReactDOM.findDOMNode(this).getElementsByTagName("code");
|
||||
const blocks = ReactDOM.findDOMNode(this).getElementsByTagName("pre");
|
||||
if (blocks.length > 0) {
|
||||
for (let i = 0; i < blocks.length; i++) {
|
||||
this._handleCodeBlockExpansion(blocks[i]);
|
||||
this._addCodeCopyButton(blocks[i]);
|
||||
}
|
||||
// Do this asynchronously: parsing code takes time and we don't
|
||||
// need to block the DOM update on it.
|
||||
setTimeout(() => {
|
||||
if (this._unmounted) return;
|
||||
for (let i = 0; i < blocks.length; i++) {
|
||||
if (SettingsStore.getValue("enableSyntaxHighlightLanguageDetection")) {
|
||||
highlight.highlightBlock(blocks[i]);
|
||||
} else {
|
||||
// Only syntax highlight if there's a class starting with language-
|
||||
const classes = blocks[i].className.split(/\s+/).filter(function(cl) {
|
||||
return cl.startsWith('language-') && !cl.startsWith('language-_');
|
||||
});
|
||||
|
||||
if (classes.length != 0) {
|
||||
highlight.highlightBlock(blocks[i]);
|
||||
}
|
||||
}
|
||||
this._highlightCode(blocks[i].firstChild);
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
this._addCodeCopyButton();
|
||||
}
|
||||
}
|
||||
|
||||
_addCodeCopyButton(codeBlock) {
|
||||
const button = document.createElement("span");
|
||||
button.className = "mx_EventTile_copyButton";
|
||||
button.onclick = async () => {
|
||||
const copyCode = button.parentNode.getElementsByTagName("pre")[0];
|
||||
const successful = await copyPlaintext(copyCode.textContent);
|
||||
|
||||
const buttonRect = button.getBoundingClientRect();
|
||||
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
|
||||
const {close} = ContextMenu.createMenu(GenericTextContextMenu, {
|
||||
...toRightOf(buttonRect, 2),
|
||||
message: successful ? _t('Copied!') : _t('Failed to copy'),
|
||||
});
|
||||
button.onmouseleave = close;
|
||||
};
|
||||
|
||||
// Wrap a div around <pre> so that the copy button can be correctly positioned
|
||||
// when the <pre> overflows and is scrolled horizontally.
|
||||
const div = document.createElement("div");
|
||||
div.className = "mx_EventTile_pre_container";
|
||||
|
||||
// Insert containing div in place of <pre> block
|
||||
codeBlock.parentNode.replaceChild(div, codeBlock);
|
||||
|
||||
// Append <pre> block and copy button to container
|
||||
div.appendChild(codeBlock);
|
||||
div.appendChild(button);
|
||||
}
|
||||
|
||||
_handleCodeBlockExpansion(codeBlock) {
|
||||
const expandCodeBlock = SettingsStore.getValue("expandCodeByDefault");
|
||||
codeBlock.className = expandCodeBlock ? "mx_EventTile_expandedCodeBlock" : "mx_EventTile_collapsedCodeBlock";
|
||||
}
|
||||
|
||||
_highlightCode(codeBlock) {
|
||||
if (SettingsStore.getValue("enableSyntaxHighlightLanguageDetection")) {
|
||||
highlight.highlightBlock(codeBlock);
|
||||
} else {
|
||||
// Only syntax highlight if there's a class starting with language-
|
||||
const classes = codeBlock.className.split(/\s+/).filter(function(cl) {
|
||||
return cl.startsWith('language-') && !cl.startsWith('language-_');
|
||||
});
|
||||
|
||||
if (classes.length != 0) {
|
||||
highlight.highlightBlock(codeBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,38 +295,6 @@ export default class TextualBody extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
_addCodeCopyButton() {
|
||||
// Add 'copy' buttons to pre blocks
|
||||
Array.from(ReactDOM.findDOMNode(this).querySelectorAll('.mx_EventTile_body pre')).forEach((p) => {
|
||||
const button = document.createElement("span");
|
||||
button.className = "mx_EventTile_copyButton";
|
||||
button.onclick = async () => {
|
||||
const copyCode = button.parentNode.getElementsByTagName("pre")[0];
|
||||
const successful = await copyPlaintext(copyCode.textContent);
|
||||
|
||||
const buttonRect = button.getBoundingClientRect();
|
||||
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
|
||||
const {close} = ContextMenu.createMenu(GenericTextContextMenu, {
|
||||
...toRightOf(buttonRect, 2),
|
||||
message: successful ? _t('Copied!') : _t('Failed to copy'),
|
||||
});
|
||||
button.onmouseleave = close;
|
||||
};
|
||||
|
||||
// Wrap a div around <pre> so that the copy button can be correctly positioned
|
||||
// when the <pre> overflows and is scrolled horizontally.
|
||||
const div = document.createElement("div");
|
||||
div.className = "mx_EventTile_pre_container";
|
||||
|
||||
// Insert containing div in place of <pre> block
|
||||
p.parentNode.replaceChild(div, p);
|
||||
|
||||
// Append <pre> block and copy button to container
|
||||
div.appendChild(p);
|
||||
div.appendChild(button);
|
||||
});
|
||||
}
|
||||
|
||||
onCancelClick = event => {
|
||||
this.setState({ widgetHidden: true });
|
||||
// FIXME: persist this somewhere smarter than local storage
|
||||
|
@ -439,12 +446,6 @@ export default class TextualBody extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
const defaultCaseClasses = classNames({
|
||||
mx_MTextBody: true,
|
||||
mx_EventTile_content: true,
|
||||
mx_EventTile_content_collapsedCode: !this.state.codeBlockExpanded,
|
||||
});
|
||||
|
||||
switch (content.msgtype) {
|
||||
case "m.emote":
|
||||
return (
|
||||
|
@ -470,7 +471,7 @@ export default class TextualBody extends React.Component {
|
|||
);
|
||||
default: // including "m.text"
|
||||
return (
|
||||
<span className={defaultCaseClasses}>
|
||||
<span className="mx_MTextBody mx_EventTile_content">
|
||||
{ body }
|
||||
{ widgets }
|
||||
</span>
|
||||
|
|
Loading…
Reference in a new issue