Compare commits

...
Sign in to create a new pull request.

6 commits

Author SHA1 Message Date
saltrafael
763b118a40
Highlight livestream comment and menu button on hover 2021-10-08 10:15:47 -03:00
saltrafael
5b29107d08
Fix mentions and timestamps not parsed in bullet lists 2021-10-08 10:15:47 -03:00
saltrafael
bf6d42dee8
Fix nested indents in Live Chat 2021-10-08 10:11:59 -03:00
saltrafael
b4f3e40a0b
Disable copy link menu option on livestream comments 2021-10-08 09:33:48 -03:00
saltrafael
57f9e85758
Fix Markdown Lists in Comments 2021-10-08 09:30:55 -03:00
saltrafael
fa325ac48c
Fix CSS for live chat embeds 2021-10-08 09:27:23 -03:00
8 changed files with 76 additions and 25 deletions

View file

@ -20,6 +20,7 @@ type Props = {
disableEdit?: boolean, disableEdit?: boolean,
disableRemove?: boolean, disableRemove?: boolean,
supportAmount?: any, supportAmount?: any,
isLiveComment: boolean,
// --- select --- // --- select ---
claim: ?Claim, claim: ?Claim,
claimIsMine: boolean, claimIsMine: boolean,
@ -54,6 +55,7 @@ function CommentMenuList(props: Props) {
disableEdit, disableEdit,
disableRemove, disableRemove,
supportAmount, supportAmount,
isLiveComment,
doToast, doToast,
handleEditComment, handleEditComment,
openModal, openModal,
@ -229,7 +231,7 @@ function CommentMenuList(props: Props) {
</> </>
)} )}
{IS_WEB && ( {IS_WEB && !isLiveComment && (
<MenuItem className="comment__menu-option" onSelect={handleCopyCommentLink}> <MenuItem className="comment__menu-option" onSelect={handleCopyCommentLink}>
<div className="menu__link"> <div className="menu__link">
<Icon aria-hidden icon={ICONS.COPY_LINK} /> <Icon aria-hidden icon={ICONS.COPY_LINK} />

View file

@ -10,7 +10,7 @@ import remarkFrontMatter from 'remark-frontmatter';
import reactRenderer from 'remark-react'; import reactRenderer from 'remark-react';
import MarkdownLink from 'component/markdownLink'; import MarkdownLink from 'component/markdownLink';
import defaultSchema from 'hast-util-sanitize/lib/github.json'; 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 { formattedTimestamp, inlineTimestamp } from 'util/remark-timestamp';
import ZoomableImage from 'component/zoomableImage'; import ZoomableImage from 'component/zoomableImage';
import { CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS, SIMPLE_SITE } from 'config'; import { CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS, SIMPLE_SITE } from 'config';
@ -133,8 +133,9 @@ function isStakeEnoughForPreview(stakedLevel) {
const MarkdownPreview = (props: MarkdownProps) => { const MarkdownPreview = (props: MarkdownProps) => {
const { content, strip, simpleLinks, noDataStore, className, parentCommentId, isMarkdownPost, stakedLevel } = props; const { content, strip, simpleLinks, noDataStore, className, parentCommentId, isMarkdownPost, stakedLevel } = props;
const strippedContent = content 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 // Let the browser try to create an iframe to see if the markup is valid
const outer = document.createElement('div'); const outer = document.createElement('div');
outer.innerHTML = iframeHtml; 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 = { const remarkOptions: Object = {
sanitize: schema, sanitize: schema,
fragment: React.Fragment, fragment: React.Fragment,
@ -192,10 +197,22 @@ const MarkdownPreview = (props: MarkdownProps) => {
}; };
// Strip all content and just render text // Strip all content and just render text
if (strip) { if (strip || stripQuote) {
// Remove new lines and extra space // Remove new lines and extra space
remarkOptions.remarkReactComponents.p = SimpleText; 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"> <span dir="auto" className="markdown-preview">
{ {
remark() remark()
@ -215,7 +232,7 @@ const MarkdownPreview = (props: MarkdownProps) => {
.use(remarkAttr, remarkAttrOpts) .use(remarkAttr, remarkAttrOpts)
// Remark plugins for lbry urls // Remark plugins for lbry urls
// Note: The order is important // Note: The order is important
.use(formatedLinks) .use(formattedLinks)
.use(inlineLinks) .use(inlineLinks)
.use(isMarkdownPost ? null : inlineTimestamp) .use(isMarkdownPost ? null : inlineTimestamp)
.use(isMarkdownPost ? null : formattedTimestamp) .use(isMarkdownPost ? null : formattedTimestamp)

View file

@ -11,6 +11,7 @@ import classnames from 'classnames';
import CommentMenuList from 'component/commentMenuList'; import CommentMenuList from 'component/commentMenuList';
import Button from 'component/button'; import Button from 'component/button';
import CreditAmount from 'component/common/credit-amount'; import CreditAmount from 'component/common/credit-amount';
import useHover from 'effects/use-hover';
type Props = { type Props = {
uri: string, uri: string,
@ -43,14 +44,18 @@ function LivestreamComment(props: Props) {
isPinned, isPinned,
} = props; } = 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); const { claimName } = parseURI(authorUri);
return ( return (
<li <li
className={classnames('livestream-comment', { className={classnames('livestream-comment', {
'livestream-comment--superchat': supportAmount > 0, 'livestream-comment--superchat': supportAmount > 0,
'livestream-comment--hover': isHovering,
})} })}
ref={commentRef}
> >
{supportAmount > 0 && ( {supportAmount > 0 && (
<div className="super-chat livestream-superchat__banner"> <div className="super-chat livestream-superchat__banner">
@ -78,7 +83,7 @@ function LivestreamComment(props: Props) {
</Tooltip> </Tooltip>
)} )}
{commentByOwnerOfContent && ( {commentByContentOwner && (
<Tooltip label={__('Streamer')}> <Tooltip label={__('Streamer')}>
<span className="comment__badge"> <span className="comment__badge">
<Icon icon={ICONS.BADGE_STREAMER} size={16} /> <Icon icon={ICONS.BADGE_STREAMER} size={16} />
@ -88,7 +93,7 @@ function LivestreamComment(props: Props) {
<Button <Button
className={classnames('button--uri-indicator comment__author', { className={classnames('button--uri-indicator comment__author', {
'comment__author--creator': commentByOwnerOfContent, 'comment__author--creator': commentByContentOwner,
})} })}
target="_blank" target="_blank"
navigate={authorUri} navigate={authorUri}
@ -119,10 +124,11 @@ function LivestreamComment(props: Props) {
commentId={commentId} commentId={commentId}
authorUri={authorUri} authorUri={authorUri}
commentIsMine={commentIsMine} commentIsMine={commentIsMine}
disableEdit
isTopLevel
isPinned={isPinned} isPinned={isPinned}
disableRemove={supportAmount > 0} disableRemove={supportAmount > 0}
isTopLevel
disableEdit
isLiveComment
/> />
</Menu> </Menu>
</div> </div>

View file

@ -268,9 +268,12 @@ $thumbnailWidthSmall: 1rem;
max-width: 35rem; max-width: 35rem;
color: var(--color-text); color: var(--color-text);
ul li, ul li {
ol li { list-style-type: disc;
list-style-position: inside;
ul li {
list-style-type: circle;
}
} }
p { p {

View file

@ -91,11 +91,22 @@ $recent-msg-button__height: 2rem;
} }
} }
.livestream-comment__info {
overflow: hidden;
}
.livestream-comment--superchat { .livestream-comment--superchat {
+ .livestream-comment--superchat { + .livestream-comment--superchat {
margin-bottom: var(--spacing-xxs); margin-bottom: var(--spacing-xxs);
} }
.livestream-comment__body {
display: flex;
align-items: flex-start;
flex-direction: unset;
flex: unset;
}
.livestream-comment__info { .livestream-comment__info {
margin-top: calc(var(--spacing-xxs) / 2); margin-top: calc(var(--spacing-xxs) / 2);
} }
@ -113,15 +124,24 @@ $recent-msg-button__height: 2rem;
} }
} }
.livestream-comment__body { .livestream-comment--hover {
display: flex; background-color: var(--color-card-background-highlighted);
align-items: flex-start; }
@media (min-width: $breakpoint-small) {
.livestream-comment:not(:hover) {
.menu__button:not(:focus):not([aria-expanded='true']) {
opacity: 0;
}
}
} }
.livestream-comment__body { .livestream-comment__body {
display: flex; display: flex;
align-items: flex-start; flex-direction: column;
flex: 2;
margin-left: var(--spacing-s); margin-left: var(--spacing-s);
overflow: hidden;
.channel-thumbnail { .channel-thumbnail {
@include handleChannelGif(2rem); @include handleChannelGif(2rem);
@ -353,6 +373,7 @@ $recent-msg-button__height: 2rem;
.livestream-comment__text { .livestream-comment__text {
padding-right: var(--spacing-xl); padding-right: var(--spacing-xl);
padding-bottom: var(--spacing-xxs); padding-bottom: var(--spacing-xxs);
.markdown-preview { .markdown-preview {
p { p {
word-break: break-word; word-break: break-word;

View file

@ -1,4 +1,6 @@
.markdown-preview { .markdown-preview {
word-break: break-all;
> :first-child { > :first-child {
margin-top: 0; margin-top: 0;
} }

View file

@ -108,15 +108,15 @@ function tokenizeURI(eat, value, silent) {
// Configure tokenizer for lbry urls // Configure tokenizer for lbry urls
tokenizeURI.locator = locateURI; tokenizeURI.locator = locateURI;
tokenizeURI.notInList = true; tokenizeURI.notInList = false;
tokenizeURI.notInLink = true; tokenizeURI.notInLink = true;
tokenizeURI.notInBlock = true; tokenizeURI.notInBlock = false;
// Configure tokenizer for lbry channels // Configure tokenizer for lbry channels
tokenizeMention.locator = locateMention; tokenizeMention.locator = locateMention;
tokenizeMention.notInList = true; tokenizeMention.notInList = false;
tokenizeMention.notInLink = true; tokenizeMention.notInLink = true;
tokenizeMention.notInBlock = true; tokenizeMention.notInBlock = false;
const visitor = (node, index, parent) => { const visitor = (node, index, parent) => {
if (node.type === 'link' && parent && parent.type === 'paragraph') { if (node.type === 'link' && parent && parent.type === 'paragraph') {
@ -149,7 +149,7 @@ const transform = (tree) => {
visit(tree, ['link'], visitor); visit(tree, ['link'], visitor);
}; };
export const formatedLinks = () => transform; export const formattedLinks = () => transform;
// Main module // Main module
export function inlineLinks() { export function inlineLinks() {

View file

@ -108,9 +108,9 @@ function tokenizeTimestamp(eat, value, silent) {
} }
tokenizeTimestamp.locator = locateTimestamp; 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.notInLink = true;
tokenizeTimestamp.notInBlock = true; tokenizeTimestamp.notInBlock = false;
export function inlineTimestamp() { export function inlineTimestamp() {
const Parser = this.Parser; const Parser = this.Parser;