Restore "Handle timestamp in Markdown."
This reverts the revertion in: -85f8965d44
. -d3f0e471e5
.
This commit is contained in:
parent
b9f8fd73f1
commit
897128a168
5 changed files with 109 additions and 4 deletions
|
@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
|
||||
### Added
|
||||
|
||||
- Turn timestamps in a video's description and comments into links _community pr!_ ([#5156](https://github.com/lbryio/lbry-desktop/pull/5156))
|
||||
- Mobile video player enhancements and the ability to tap on the left and right edges to seek _community pr!_ ([#5119](https://github.com/lbryio/lbry-desktop/pull/5119))
|
||||
|
||||
### Changed
|
||||
|
|
|
@ -10,6 +10,7 @@ import reactRenderer from 'remark-react';
|
|||
import MarkdownLink from 'component/markdownLink';
|
||||
import defaultSchema from 'hast-util-sanitize/lib/github.json';
|
||||
import { formatedLinks, inlineLinks } from 'util/remark-lbry';
|
||||
import { formattedTimestamp, inlineTimestamp } from 'util/remark-timestamp';
|
||||
|
||||
type SimpleTextProps = {
|
||||
children?: React.Node,
|
||||
|
@ -149,6 +150,8 @@ const MarkdownPreview = (props: MarkdownProps) => {
|
|||
// Note: The order is important
|
||||
.use(formatedLinks)
|
||||
.use(inlineLinks)
|
||||
.use(isMarkdownPost ? null : inlineTimestamp)
|
||||
.use(isMarkdownPost ? null : formattedTimestamp)
|
||||
// Emojis
|
||||
.use(remarkEmoji)
|
||||
// Render new lines without needing spaces.
|
||||
|
|
|
@ -62,10 +62,27 @@ function MarkdownLink(props: Props) {
|
|||
}
|
||||
}
|
||||
|
||||
// Return plain text if no valid url
|
||||
// Return external link if protocol is http or https
|
||||
// Return local link if protocol is lbry uri
|
||||
if (!simpleLinks && ((protocol && protocol[0] === 'lbry:' && isURIValid(decodedUri)) || lbryUrlFromLink)) {
|
||||
if (href.startsWith('?t=')) {
|
||||
// Video timestamp markers
|
||||
element = (
|
||||
<Button
|
||||
button="link"
|
||||
iconRight={undefined}
|
||||
title={title || decodedUri}
|
||||
label={children}
|
||||
className="button--external-link"
|
||||
onClick={() => {
|
||||
if (window.player) {
|
||||
window.player.currentTime(parseInt(href.substr(3)));
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else if (!simpleLinks && ((protocol && protocol[0] === 'lbry:' && isURIValid(decodedUri)) || lbryUrlFromLink)) {
|
||||
// Return plain text if no valid url
|
||||
// Return external link if protocol is http or https
|
||||
// Return local link if protocol is lbry uri
|
||||
element = (
|
||||
<ClaimLink
|
||||
uri={lbryUrlFromLink || decodedUri}
|
||||
|
|
|
@ -324,6 +324,8 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
|||
}
|
||||
});
|
||||
|
||||
window.player = player;
|
||||
|
||||
// fixes #3498 (https://github.com/lbryio/lbry-desktop/issues/3498)
|
||||
// summary: on firefox the focus would stick to the fullscreen button which caused buggy behavior with spacebar
|
||||
// $FlowFixMe
|
||||
|
@ -336,6 +338,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
|||
|
||||
if (player) {
|
||||
player.dispose();
|
||||
window.player = undefined;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
81
ui/util/remark-timestamp.js
Normal file
81
ui/util/remark-timestamp.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
import visit from 'unist-util-visit';
|
||||
|
||||
const TIMESTAMP_NODE_TYPE = 'timestamp';
|
||||
const TIMESTAMP_REGEX = /(?<!\d|:)([01]?\d|2[0-3]):([0-5]\d)(?::([0-5]\d))?(?!\d|:)/g;
|
||||
|
||||
// ***************************************************************************
|
||||
// Tokenize timestamp
|
||||
// ***************************************************************************
|
||||
|
||||
function locateTimestamp(value, fromIndex) {
|
||||
const timestamps = Array.from(value.matchAll(TIMESTAMP_REGEX));
|
||||
return timestamps.length === 0 ? -1 : timestamps[0].index;
|
||||
}
|
||||
|
||||
// Generate 'timestamp' markdown node
|
||||
const createTimestampNode = text => ({
|
||||
type: TIMESTAMP_NODE_TYPE,
|
||||
value: text,
|
||||
children: [{ type: 'text', value: text }],
|
||||
});
|
||||
|
||||
// Generate a markdown link from timestamp
|
||||
function tokenizeTimestamp(eat, value, silent) {
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const match = value.match(TIMESTAMP_REGEX);
|
||||
if (match) {
|
||||
try {
|
||||
const text = match[0];
|
||||
return eat(text)(createTimestampNode(text));
|
||||
} catch (err) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tokenizeTimestamp.locator = locateTimestamp;
|
||||
tokenizeTimestamp.notInList = true;
|
||||
tokenizeTimestamp.notInLink = true;
|
||||
tokenizeTimestamp.notInBlock = true;
|
||||
|
||||
export function inlineTimestamp() {
|
||||
const Parser = this.Parser;
|
||||
const tokenizers = Parser.prototype.inlineTokenizers;
|
||||
const methods = Parser.prototype.inlineMethods;
|
||||
|
||||
// Add an inline tokenizer (defined in the following example).
|
||||
tokenizers.timestamp = tokenizeTimestamp;
|
||||
|
||||
// Run it just before `text`.
|
||||
methods.splice(methods.indexOf('text'), 0, 'timestamp');
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// Format timestamp
|
||||
// ***************************************************************************
|
||||
|
||||
function strToSeconds(stime) {
|
||||
const tt = stime.split(':').reverse();
|
||||
return (tt.length >= 3 ? +tt[2] : 0) * 60 * 60 + (tt.length >= 2 ? +tt[1] : 0) * 60 + (tt.length >= 1 ? +tt[0] : 0);
|
||||
}
|
||||
|
||||
const transformer = (node, index, parent) => {
|
||||
if (node.type === TIMESTAMP_NODE_TYPE && parent && parent.type === 'paragraph') {
|
||||
const timestampStr = node.value;
|
||||
const seconds = strToSeconds(timestampStr);
|
||||
|
||||
node.type = 'link';
|
||||
node.url = `?t=${seconds}`;
|
||||
node.title = timestampStr;
|
||||
node.children = [{ type: 'text', value: timestampStr }];
|
||||
}
|
||||
};
|
||||
|
||||
const transform = tree => {
|
||||
visit(tree, [TIMESTAMP_NODE_TYPE], transformer);
|
||||
};
|
||||
|
||||
export const formattedTimestamp = () => transform;
|
Loading…
Reference in a new issue