Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3345784
D4999.id16787.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
12 KB
Referenced Files
None
Subscribers
None
D4999.id16787.diff
View Options
diff --git a/web/markdown/markdown.css b/web/markdown/markdown.css
--- a/web/markdown/markdown.css
+++ b/web/markdown/markdown.css
@@ -17,14 +17,9 @@
box-sizing: border-box;
width: 100%;
margin: 6px 0;
-}
-div.darkBackground blockquote {
- background: #a9a9a9;
- border-left: 5px solid #808080;
-}
-div.lightBackground blockquote {
- background: #d3d3d3;
- border-left: 5px solid #c0c0c0;
+ border-radius: 8px;
+ border-left-width: 8px;
+ border-left-style: solid;
}
div.markdown code {
diff --git a/web/markdown/markdown.react.js b/web/markdown/markdown.react.js
--- a/web/markdown/markdown.react.js
+++ b/web/markdown/markdown.react.js
@@ -13,16 +13,14 @@
};
function Markdown(props: Props): React.Node {
const { children, rules } = props;
- const { simpleMarkdownRules, useDarkStyle } = rules;
+ const { simpleMarkdownRules } = rules;
const markdownClassName = React.useMemo(
() =>
classNames({
[css.markdown]: true,
- [css.darkBackground]: useDarkStyle,
- [css.lightBackground]: !useDarkStyle,
}),
- [useDarkStyle],
+ [],
);
const parser = React.useMemo(
diff --git a/web/markdown/rules.react.js b/web/markdown/rules.react.js
--- a/web/markdown/rules.react.js
+++ b/web/markdown/rules.react.js
@@ -3,7 +3,9 @@
import _memoize from 'lodash/memoize';
import * as React from 'react';
import * as SimpleMarkdown from 'simple-markdown';
+import tinycolor from 'tinycolor2';
+import { threadInfoSelector } from 'lib/selectors/thread-selectors';
import { relativeMemberInfoSelectorForMembersOfThread } from 'lib/selectors/user-selectors';
import * as SharedMarkdown from 'lib/shared/markdown';
import type { RelativeMemberInfo } from 'lib/types/thread-types';
@@ -65,76 +67,117 @@
};
});
-const markdownRules: boolean => MarkdownRules = _memoize(useDarkStyle => {
- const linkMarkdownRules = linkRules(useDarkStyle);
+const markdownRules: (
+ useDarkStyle: boolean,
+ threadColor: ?string,
+) => MarkdownRules = _memoize(
+ (useDarkStyle, threadColor) => {
+ const linkMarkdownRules = linkRules(useDarkStyle);
- const simpleMarkdownRules = {
- ...linkMarkdownRules.simpleMarkdownRules,
- autolink: SimpleMarkdown.defaultRules.autolink,
- link: {
- ...linkMarkdownRules.simpleMarkdownRules.link,
- match: SimpleMarkdown.defaultRules.link.match,
- },
- blockQuote: {
- ...SimpleMarkdown.defaultRules.blockQuote,
- // match end of blockQuote by either \n\n or end of string
- match: SharedMarkdown.matchBlockQuote(SharedMarkdown.blockQuoteRegex),
- parse: SharedMarkdown.parseBlockQuote,
- },
- inlineCode: SimpleMarkdown.defaultRules.inlineCode,
- em: SimpleMarkdown.defaultRules.em,
- strong: SimpleMarkdown.defaultRules.strong,
- del: SimpleMarkdown.defaultRules.del,
- u: SimpleMarkdown.defaultRules.u,
- heading: {
- ...SimpleMarkdown.defaultRules.heading,
- match: SimpleMarkdown.blockRegex(SharedMarkdown.headingRegex),
- },
- mailto: SimpleMarkdown.defaultRules.mailto,
- codeBlock: {
- ...SimpleMarkdown.defaultRules.codeBlock,
- match: SimpleMarkdown.blockRegex(SharedMarkdown.codeBlockRegex),
- parse: (capture: SharedMarkdown.Capture) => ({
- content: capture[0].replace(/^ {4}/gm, ''),
- }),
- },
- fence: {
- ...SimpleMarkdown.defaultRules.fence,
- match: SimpleMarkdown.blockRegex(SharedMarkdown.fenceRegex),
- parse: (capture: SharedMarkdown.Capture) => ({
- type: 'codeBlock',
- content: capture[2],
- }),
- },
- json: {
- order: SimpleMarkdown.defaultRules.paragraph.order - 1,
- match: (source: string, state: SharedMarkdown.State) => {
- if (state.inline) {
- return null;
- }
- return SharedMarkdown.jsonMatch(source);
+ const simpleMarkdownRules = {
+ ...linkMarkdownRules.simpleMarkdownRules,
+ autolink: SimpleMarkdown.defaultRules.autolink,
+ link: {
+ ...linkMarkdownRules.simpleMarkdownRules.link,
+ match: SimpleMarkdown.defaultRules.link.match,
+ },
+ blockQuote: {
+ ...SimpleMarkdown.defaultRules.blockQuote,
+ // match end of blockQuote by either \n\n or end of string
+ match: SimpleMarkdown.blockRegex(SharedMarkdown.blockQuoteRegex),
+ parse(
+ capture: SharedMarkdown.Capture,
+ parse: SharedMarkdown.Parser,
+ state: SharedMarkdown.State,
+ ) {
+ const content = capture[1].replace(/^ *> ?/gm, '');
+ return {
+ content: parse(content, state),
+ };
+ },
+ // eslint-disable-next-line react/display-name
+ react: (
+ node: SharedMarkdown.SingleASTNode,
+ output: SharedMarkdown.Output<SharedMarkdown.ReactElement>,
+ state: SharedMarkdown.State,
+ ) => {
+ const backgroundColor = threadColor
+ ? tinycolor(threadColor).darken(20).toString()
+ : tinycolor('var(--text-message-default-background)')
+ .lighten(70)
+ .toString();
+ const borderLeftColor = threadColor
+ ? tinycolor(threadColor).darken(30).toString()
+ : tinycolor('var(--text-message-default-background)')
+ .lighten(50)
+ .toString();
+
+ return (
+ <blockquote
+ key={state.key}
+ style={{ backgroundColor, borderLeftColor }}
+ >
+ {output(node.content, state)}
+ </blockquote>
+ );
+ },
+ },
+ inlineCode: SimpleMarkdown.defaultRules.inlineCode,
+ em: SimpleMarkdown.defaultRules.em,
+ strong: SimpleMarkdown.defaultRules.strong,
+ del: SimpleMarkdown.defaultRules.del,
+ u: SimpleMarkdown.defaultRules.u,
+ heading: {
+ ...SimpleMarkdown.defaultRules.heading,
+ match: SimpleMarkdown.blockRegex(SharedMarkdown.headingRegex),
},
- parse: (capture: SharedMarkdown.Capture) => {
- const jsonCapture: SharedMarkdown.JSONCapture = (capture: any);
- return {
+ mailto: SimpleMarkdown.defaultRules.mailto,
+ codeBlock: {
+ ...SimpleMarkdown.defaultRules.codeBlock,
+ match: SimpleMarkdown.blockRegex(SharedMarkdown.codeBlockRegex),
+ parse: (capture: SharedMarkdown.Capture) => ({
+ content: capture[0].replace(/^ {4}/gm, ''),
+ }),
+ },
+ fence: {
+ ...SimpleMarkdown.defaultRules.fence,
+ match: SimpleMarkdown.blockRegex(SharedMarkdown.fenceRegex),
+ parse: (capture: SharedMarkdown.Capture) => ({
type: 'codeBlock',
- content: SharedMarkdown.jsonPrint(jsonCapture),
- };
+ content: capture[2],
+ }),
},
- },
- list: {
- ...SimpleMarkdown.defaultRules.list,
- match: SharedMarkdown.matchList,
- parse: SharedMarkdown.parseList,
- },
- escape: SimpleMarkdown.defaultRules.escape,
- };
- return {
- ...linkMarkdownRules,
- simpleMarkdownRules,
- useDarkStyle,
- };
-});
+ json: {
+ order: SimpleMarkdown.defaultRules.paragraph.order - 1,
+ match: (source: string, state: SharedMarkdown.State) => {
+ if (state.inline) {
+ return null;
+ }
+ return SharedMarkdown.jsonMatch(source);
+ },
+ parse: (capture: SharedMarkdown.Capture) => {
+ const jsonCapture: SharedMarkdown.JSONCapture = (capture: any);
+ return {
+ type: 'codeBlock',
+ content: SharedMarkdown.jsonPrint(jsonCapture),
+ };
+ },
+ },
+ list: {
+ ...SimpleMarkdown.defaultRules.list,
+ match: SharedMarkdown.matchList,
+ parse: SharedMarkdown.parseList,
+ },
+ escape: SimpleMarkdown.defaultRules.escape,
+ };
+ return {
+ ...linkMarkdownRules,
+ simpleMarkdownRules,
+ useDarkStyle,
+ };
+ },
+ (...args) => JSON.stringify(args),
+);
function useTextMessageRulesFunc(
threadID: ?string,
@@ -142,21 +185,30 @@
const threadMembers = useSelector(
relativeMemberInfoSelectorForMembersOfThread(threadID),
);
+
+ const threadColor = useSelector(state => {
+ if (threadID) {
+ const threadInfo = threadInfoSelector(state)[threadID];
+ return threadInfo ? threadInfo.color : null;
+ }
+ });
+
return React.useMemo(() => {
if (!threadMembers) {
return undefined;
}
return _memoize<[boolean], MarkdownRules>((useDarkStyle: boolean) =>
- textMessageRules(threadMembers, useDarkStyle),
+ textMessageRules(threadMembers, useDarkStyle, threadColor),
);
- }, [threadMembers]);
+ }, [threadMembers, threadColor]);
}
function textMessageRules(
members: $ReadOnlyArray<RelativeMemberInfo>,
useDarkStyle: boolean,
+ threadColor: ?string,
): MarkdownRules {
- const baseRules = markdownRules(useDarkStyle);
+ const baseRules = markdownRules(useDarkStyle, threadColor);
return {
...baseRules,
simpleMarkdownRules: {
@@ -182,7 +234,7 @@
function getDefaultTextMessageRules(): MarkdownRules {
if (!defaultTextMessageRules) {
- defaultTextMessageRules = textMessageRules([], false);
+ defaultTextMessageRules = textMessageRules([], false, null);
}
return defaultTextMessageRules;
}
diff --git a/web/modals/threads/settings/thread-settings-relationship-button.react.js b/web/modals/threads/settings/thread-settings-relationship-button.react.js
--- a/web/modals/threads/settings/thread-settings-relationship-button.react.js
+++ b/web/modals/threads/settings/thread-settings-relationship-button.react.js
@@ -1,4 +1,11 @@
// @flow
+import {
+ faUserMinus,
+ faUserPlus,
+ faUserShield,
+ faUserSlash,
+} from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import invariant from 'invariant';
import * as React from 'react';
@@ -24,6 +31,7 @@
import Button from '../../../components/button.react';
import { useSelector } from '../../../redux/redux-utils';
+import css from './thread-settings-relationship-tab.css';
const loadingStatusSelector = createLoadingStatusSelector(
updateRelationshipsActionTypes,
@@ -67,6 +75,35 @@
};
}, [relationshipButton, username]);
+ const icon = React.useMemo(() => {
+ let buttonIcon = null;
+
+ if (relationshipButton === relationshipButtons.FRIEND) {
+ buttonIcon = faUserPlus;
+ } else if (relationshipButton === relationshipButtons.UNFRIEND) {
+ buttonIcon = faUserMinus;
+ } else if (relationshipButton === relationshipButtons.BLOCK) {
+ buttonIcon = faUserShield;
+ } else if (relationshipButton === relationshipButtons.UNBLOCK) {
+ buttonIcon = faUserShield;
+ } else if (relationshipButton === relationshipButtons.ACCEPT) {
+ buttonIcon = faUserPlus;
+ } else if (relationshipButton === relationshipButtons.REJECT) {
+ buttonIcon = faUserSlash;
+ } else if (relationshipButton === relationshipButtons.WITHDRAW) {
+ buttonIcon = faUserMinus;
+ }
+
+ if (buttonIcon) {
+ return (
+ <FontAwesomeIcon
+ icon={buttonIcon}
+ className={css.relationshipButtonIcon}
+ />
+ );
+ }
+ }, [relationshipButton]);
+
const dispatchActionPromise = useDispatchActionPromise();
const callUpdateRelationships = useServerCall(updateRelationships);
@@ -91,7 +128,10 @@
return (
<Button variant={variant} onClick={onClick} disabled={disabled}>
- {text}
+ <div className={css.relationshipButtonContent}>
+ {icon}
+ <div className={css.relationshipButtonText}>{text}</div>
+ </div>
</Button>
);
}
diff --git a/web/modals/threads/settings/thread-settings-relationship-tab.css b/web/modals/threads/settings/thread-settings-relationship-tab.css
--- a/web/modals/threads/settings/thread-settings-relationship-tab.css
+++ b/web/modals/threads/settings/thread-settings-relationship-tab.css
@@ -3,3 +3,18 @@
flex-direction: column;
row-gap: 10px;
}
+
+div.relationshipButtonContent {
+ display: flex;
+ flex: 1;
+ align-items: center;
+}
+
+div.relationshipButtonText {
+ flex: 1;
+ margin: 0 24px;
+}
+
+svg.relationshipButtonIcon {
+ position: absolute;
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 23, 6:59 AM (18 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2569541
Default Alt Text
D4999.id16787.diff (12 KB)
Attached To
Mode
D4999: [web] Implement darker thread color tint to blockquote container
Attached
Detach File
Event Timeline
Log In to Comment