Compare commits
6 commits
master
...
chat-markd
Author | SHA1 | Date | |
---|---|---|---|
|
763b118a40 | ||
|
5b29107d08 | ||
|
bf6d42dee8 | ||
|
b4f3e40a0b | ||
|
57f9e85758 | ||
|
fa325ac48c |
8 changed files with 76 additions and 25 deletions
|
@ -20,6 +20,7 @@ type Props = {
|
|||
disableEdit?: boolean,
|
||||
disableRemove?: boolean,
|
||||
supportAmount?: any,
|
||||
isLiveComment: boolean,
|
||||
// --- select ---
|
||||
claim: ?Claim,
|
||||
claimIsMine: boolean,
|
||||
|
@ -54,6 +55,7 @@ function CommentMenuList(props: Props) {
|
|||
disableEdit,
|
||||
disableRemove,
|
||||
supportAmount,
|
||||
isLiveComment,
|
||||
doToast,
|
||||
handleEditComment,
|
||||
openModal,
|
||||
|
@ -229,7 +231,7 @@ function CommentMenuList(props: Props) {
|
|||
</>
|
||||
)}
|
||||
|
||||
{IS_WEB && (
|
||||
{IS_WEB && !isLiveComment && (
|
||||
<MenuItem className="comment__menu-option" onSelect={handleCopyCommentLink}>
|
||||
<div className="menu__link">
|
||||
<Icon aria-hidden icon={ICONS.COPY_LINK} />
|
||||
|
|
|
@ -10,7 +10,7 @@ import remarkFrontMatter from 'remark-frontmatter';
|
|||
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 { formattedLinks, inlineLinks } from 'util/remark-lbry';
|
||||
import { formattedTimestamp, inlineTimestamp } from 'util/remark-timestamp';
|
||||
import ZoomableImage from 'component/zoomableImage';
|
||||
import { CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS, SIMPLE_SITE } from 'config';
|
||||
|
@ -133,8 +133,9 @@ function isStakeEnoughForPreview(stakedLevel) {
|
|||
|
||||
const MarkdownPreview = (props: MarkdownProps) => {
|
||||
const { content, strip, simpleLinks, noDataStore, className, parentCommentId, isMarkdownPost, stakedLevel } = props;
|
||||
|
||||
const strippedContent = content
|
||||
? content.replace(REPLACE_REGEX, (iframeHtml, y, iframeSrc) => {
|
||||
? content.replace(REPLACE_REGEX, (iframeHtml) => {
|
||||
// Let the browser try to create an iframe to see if the markup is valid
|
||||
const outer = document.createElement('div');
|
||||
outer.innerHTML = iframeHtml;
|
||||
|
@ -152,6 +153,10 @@ const MarkdownPreview = (props: MarkdownProps) => {
|
|||
})
|
||||
: '';
|
||||
|
||||
const initialQuote = strippedContent.split(' ').find((word) => word.length > 0 || word.charAt(0) === '>');
|
||||
let stripQuote;
|
||||
if (initialQuote && initialQuote.charAt(0) === '>') stripQuote = true;
|
||||
|
||||
const remarkOptions: Object = {
|
||||
sanitize: schema,
|
||||
fragment: React.Fragment,
|
||||
|
@ -192,10 +197,22 @@ const MarkdownPreview = (props: MarkdownProps) => {
|
|||
};
|
||||
|
||||
// Strip all content and just render text
|
||||
if (strip) {
|
||||
if (strip || stripQuote) {
|
||||
// Remove new lines and extra space
|
||||
remarkOptions.remarkReactComponents.p = SimpleText;
|
||||
return (
|
||||
return stripQuote ? (
|
||||
<span dir="auto" className="markdown-preview">
|
||||
<blockquote>
|
||||
{
|
||||
remark()
|
||||
.use(remarkStrip)
|
||||
.use(remarkFrontMatter, ['yaml'])
|
||||
.use(reactRenderer, remarkOptions)
|
||||
.processSync(content).contents
|
||||
}
|
||||
</blockquote>
|
||||
</span>
|
||||
) : (
|
||||
<span dir="auto" className="markdown-preview">
|
||||
{
|
||||
remark()
|
||||
|
@ -215,7 +232,7 @@ const MarkdownPreview = (props: MarkdownProps) => {
|
|||
.use(remarkAttr, remarkAttrOpts)
|
||||
// Remark plugins for lbry urls
|
||||
// Note: The order is important
|
||||
.use(formatedLinks)
|
||||
.use(formattedLinks)
|
||||
.use(inlineLinks)
|
||||
.use(isMarkdownPost ? null : inlineTimestamp)
|
||||
.use(isMarkdownPost ? null : formattedTimestamp)
|
||||
|
|
|
@ -11,6 +11,7 @@ import classnames from 'classnames';
|
|||
import CommentMenuList from 'component/commentMenuList';
|
||||
import Button from 'component/button';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
import useHover from 'effects/use-hover';
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
|
@ -43,14 +44,18 @@ function LivestreamComment(props: Props) {
|
|||
isPinned,
|
||||
} = props;
|
||||
|
||||
const commentByOwnerOfContent = claim && claim.signing_channel && claim.signing_channel.permanent_url === authorUri;
|
||||
const commentRef = React.useRef();
|
||||
const isHovering = useHover(commentRef);
|
||||
const commentByContentOwner = claim && claim.signing_channel && claim.signing_channel.permanent_url === authorUri;
|
||||
const { claimName } = parseURI(authorUri);
|
||||
|
||||
return (
|
||||
<li
|
||||
className={classnames('livestream-comment', {
|
||||
'livestream-comment--superchat': supportAmount > 0,
|
||||
'livestream-comment--hover': isHovering,
|
||||
})}
|
||||
ref={commentRef}
|
||||
>
|
||||
{supportAmount > 0 && (
|
||||
<div className="super-chat livestream-superchat__banner">
|
||||
|
@ -78,7 +83,7 @@ function LivestreamComment(props: Props) {
|
|||
</Tooltip>
|
||||
)}
|
||||
|
||||
{commentByOwnerOfContent && (
|
||||
{commentByContentOwner && (
|
||||
<Tooltip label={__('Streamer')}>
|
||||
<span className="comment__badge">
|
||||
<Icon icon={ICONS.BADGE_STREAMER} size={16} />
|
||||
|
@ -88,7 +93,7 @@ function LivestreamComment(props: Props) {
|
|||
|
||||
<Button
|
||||
className={classnames('button--uri-indicator comment__author', {
|
||||
'comment__author--creator': commentByOwnerOfContent,
|
||||
'comment__author--creator': commentByContentOwner,
|
||||
})}
|
||||
target="_blank"
|
||||
navigate={authorUri}
|
||||
|
@ -119,10 +124,11 @@ function LivestreamComment(props: Props) {
|
|||
commentId={commentId}
|
||||
authorUri={authorUri}
|
||||
commentIsMine={commentIsMine}
|
||||
disableEdit
|
||||
isTopLevel
|
||||
isPinned={isPinned}
|
||||
disableRemove={supportAmount > 0}
|
||||
isTopLevel
|
||||
disableEdit
|
||||
isLiveComment
|
||||
/>
|
||||
</Menu>
|
||||
</div>
|
||||
|
|
|
@ -268,9 +268,12 @@ $thumbnailWidthSmall: 1rem;
|
|||
max-width: 35rem;
|
||||
color: var(--color-text);
|
||||
|
||||
ul li,
|
||||
ol li {
|
||||
list-style-position: inside;
|
||||
ul li {
|
||||
list-style-type: disc;
|
||||
|
||||
ul li {
|
||||
list-style-type: circle;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
|
|
|
@ -91,11 +91,22 @@ $recent-msg-button__height: 2rem;
|
|||
}
|
||||
}
|
||||
|
||||
.livestream-comment__info {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.livestream-comment--superchat {
|
||||
+ .livestream-comment--superchat {
|
||||
margin-bottom: var(--spacing-xxs);
|
||||
}
|
||||
|
||||
.livestream-comment__body {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: unset;
|
||||
flex: unset;
|
||||
}
|
||||
|
||||
.livestream-comment__info {
|
||||
margin-top: calc(var(--spacing-xxs) / 2);
|
||||
}
|
||||
|
@ -113,15 +124,24 @@ $recent-msg-button__height: 2rem;
|
|||
}
|
||||
}
|
||||
|
||||
.livestream-comment__body {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
.livestream-comment--hover {
|
||||
background-color: var(--color-card-background-highlighted);
|
||||
}
|
||||
|
||||
@media (min-width: $breakpoint-small) {
|
||||
.livestream-comment:not(:hover) {
|
||||
.menu__button:not(:focus):not([aria-expanded='true']) {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.livestream-comment__body {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
flex: 2;
|
||||
margin-left: var(--spacing-s);
|
||||
overflow: hidden;
|
||||
|
||||
.channel-thumbnail {
|
||||
@include handleChannelGif(2rem);
|
||||
|
@ -353,6 +373,7 @@ $recent-msg-button__height: 2rem;
|
|||
.livestream-comment__text {
|
||||
padding-right: var(--spacing-xl);
|
||||
padding-bottom: var(--spacing-xxs);
|
||||
|
||||
.markdown-preview {
|
||||
p {
|
||||
word-break: break-word;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
.markdown-preview {
|
||||
word-break: break-all;
|
||||
|
||||
> :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
|
|
@ -108,15 +108,15 @@ function tokenizeURI(eat, value, silent) {
|
|||
|
||||
// Configure tokenizer for lbry urls
|
||||
tokenizeURI.locator = locateURI;
|
||||
tokenizeURI.notInList = true;
|
||||
tokenizeURI.notInList = false;
|
||||
tokenizeURI.notInLink = true;
|
||||
tokenizeURI.notInBlock = true;
|
||||
tokenizeURI.notInBlock = false;
|
||||
|
||||
// Configure tokenizer for lbry channels
|
||||
tokenizeMention.locator = locateMention;
|
||||
tokenizeMention.notInList = true;
|
||||
tokenizeMention.notInList = false;
|
||||
tokenizeMention.notInLink = true;
|
||||
tokenizeMention.notInBlock = true;
|
||||
tokenizeMention.notInBlock = false;
|
||||
|
||||
const visitor = (node, index, parent) => {
|
||||
if (node.type === 'link' && parent && parent.type === 'paragraph') {
|
||||
|
@ -149,7 +149,7 @@ const transform = (tree) => {
|
|||
visit(tree, ['link'], visitor);
|
||||
};
|
||||
|
||||
export const formatedLinks = () => transform;
|
||||
export const formattedLinks = () => transform;
|
||||
|
||||
// Main module
|
||||
export function inlineLinks() {
|
||||
|
|
|
@ -108,9 +108,9 @@ function tokenizeTimestamp(eat, value, silent) {
|
|||
}
|
||||
|
||||
tokenizeTimestamp.locator = locateTimestamp;
|
||||
tokenizeTimestamp.notInList = true; // Flag doesn't work? It'll always tokenizes in List and never in Bullet.
|
||||
tokenizeTimestamp.notInList = false; // Flag doesn't work? It'll always tokenizes in List and never in Bullet.
|
||||
tokenizeTimestamp.notInLink = true;
|
||||
tokenizeTimestamp.notInBlock = true;
|
||||
tokenizeTimestamp.notInBlock = false;
|
||||
|
||||
export function inlineTimestamp() {
|
||||
const Parser = this.Parser;
|
||||
|
|
Loading…
Reference in a new issue