Several text formatting fixes
This commit is contained in:
parent
f93b4235d5
commit
5395741f11
11 changed files with 72 additions and 50 deletions
|
@ -5,6 +5,9 @@ $inter: Inter, 'Helvetica Neue', 'Source Sans Pro', 'Source Han Sans SC',
|
||||||
'Source Han Sans CN', 'Hiragino Sans GB', 'Hiragino Kaku Gothic',
|
'Source Han Sans CN', 'Hiragino Sans GB', 'Hiragino Kaku Gothic',
|
||||||
'Microsoft Yahei UI', Helvetica, Arial, sans-serif;
|
'Microsoft Yahei UI', Helvetica, Arial, sans-serif;
|
||||||
|
|
||||||
|
$monospace: 'SF Mono', SFMono-Regular, ui-monospace, 'DejaVu Sans Mono', Menlo,
|
||||||
|
Consolas, monospace;
|
||||||
|
|
||||||
// -- V3 Colors
|
// -- V3 Colors
|
||||||
|
|
||||||
$color-accent-blue: #2c6bed;
|
$color-accent-blue: #2c6bed;
|
||||||
|
|
|
@ -395,7 +395,7 @@ button.CompositionInput__link-preview__close-button {
|
||||||
|
|
||||||
.quill {
|
.quill {
|
||||||
&--monospace {
|
&--monospace {
|
||||||
font-family: monospace;
|
font-family: $monospace;
|
||||||
}
|
}
|
||||||
&--spoiler {
|
&--spoiler {
|
||||||
@include light-theme {
|
@include light-theme {
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&__text {
|
&__text {
|
||||||
font-family: Monaco, Consolas, 'Courier New', Courier, monospace;
|
font-family: $monospace;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// strikethrough is handled by <s> element
|
// strikethrough is handled by <s> element
|
||||||
|
|
||||||
&--monospace {
|
&--monospace {
|
||||||
font-family: monospace;
|
font-family: $monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: only used in the left pane for search results, not in message bubbles
|
// Note: only used in the left pane for search results, not in message bubbles
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&--spoiler--noninteractive {
|
&--spoiler--noninteractive {
|
||||||
cursor: default;
|
cursor: inherit;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
|
|
||||||
&__number {
|
&__number {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
font-family: monospace;
|
font-family: $monospace;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
margin: 24px auto;
|
margin: 24px auto;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
|
|
|
@ -48,7 +48,28 @@ export class FormattingMenu {
|
||||||
|
|
||||||
this.quill.on('editor-change', this.onEditorChange.bind(this));
|
this.quill.on('editor-change', this.onEditorChange.bind(this));
|
||||||
|
|
||||||
// Note: Bold and Italic are built-in
|
// We override these keybindings, which means that we need to move their priority
|
||||||
|
// above the built-in shortcuts, which don't exactly do what we want.
|
||||||
|
|
||||||
|
const boldChar = 'B';
|
||||||
|
const boldCharCode = boldChar.charCodeAt(0);
|
||||||
|
this.quill.keyboard.addBinding({ key: boldChar, shortKey: true }, () =>
|
||||||
|
this.toggleForStyle(QuillFormattingStyle.bold)
|
||||||
|
);
|
||||||
|
quill.keyboard.bindings[boldCharCode].unshift(
|
||||||
|
quill.keyboard.bindings[boldCharCode].pop()
|
||||||
|
);
|
||||||
|
|
||||||
|
const italicChar = 'I';
|
||||||
|
const italicCharCode = italicChar.charCodeAt(0);
|
||||||
|
this.quill.keyboard.addBinding({ key: italicChar, shortKey: true }, () =>
|
||||||
|
this.toggleForStyle(QuillFormattingStyle.italic)
|
||||||
|
);
|
||||||
|
quill.keyboard.bindings[italicCharCode].unshift(
|
||||||
|
quill.keyboard.bindings[italicCharCode].pop()
|
||||||
|
);
|
||||||
|
|
||||||
|
// No need for changing priority for these new keybindings
|
||||||
|
|
||||||
this.quill.keyboard.addBinding({ key: 'E', shortKey: true }, () =>
|
this.quill.keyboard.addBinding({ key: 'E', shortKey: true }, () =>
|
||||||
this.toggleForStyle(QuillFormattingStyle.monospace)
|
this.toggleForStyle(QuillFormattingStyle.monospace)
|
||||||
|
@ -134,8 +155,8 @@ export class FormattingMenu {
|
||||||
// where the editor ends, we fix the popover so it stays connected to the
|
// where the editor ends, we fix the popover so it stays connected to the
|
||||||
// visible editor. Important for the 'Cmd-A' scenario when scrolled down.
|
// visible editor. Important for the 'Cmd-A' scenario when scrolled down.
|
||||||
const updatedY = Math.max(
|
const updatedY = Math.max(
|
||||||
editorElement?.getClientRects()[0]?.y || 0,
|
(editorElement?.getClientRects()[0]?.y || 0) - 10,
|
||||||
rect.y
|
(rect?.y || 0) - 10
|
||||||
);
|
);
|
||||||
|
|
||||||
return DOMRect.fromRect({
|
return DOMRect.fromRect({
|
||||||
|
|
|
@ -6,11 +6,7 @@ import { createSelector } from 'reselect';
|
||||||
import type { StateType } from '../reducer';
|
import type { StateType } from '../reducer';
|
||||||
import type { ComposerStateType, QuotedMessageType } from '../ducks/composer';
|
import type { ComposerStateType, QuotedMessageType } from '../ducks/composer';
|
||||||
import { getComposerStateForConversation } from '../ducks/composer';
|
import { getComposerStateForConversation } from '../ducks/composer';
|
||||||
import {
|
import { getRemoteConfig, isRemoteConfigFlagEnabled } from './items';
|
||||||
getRemoteConfig,
|
|
||||||
getTextFormattingEnabled,
|
|
||||||
isRemoteConfigFlagEnabled,
|
|
||||||
} from './items';
|
|
||||||
|
|
||||||
export const getComposerState = (state: StateType): ComposerStateType =>
|
export const getComposerState = (state: StateType): ComposerStateType =>
|
||||||
state.composer;
|
state.composer;
|
||||||
|
@ -28,27 +24,19 @@ export const getQuotedMessageSelector = createSelector(
|
||||||
composerStateForConversationIdSelector(conversationId).quotedMessage
|
composerStateForConversationIdSelector(conversationId).quotedMessage
|
||||||
);
|
);
|
||||||
|
|
||||||
export const getIsFormattingEnabled = createSelector(
|
export const getIsFormattingFlagEnabled = createSelector(
|
||||||
getTextFormattingEnabled,
|
|
||||||
getRemoteConfig,
|
getRemoteConfig,
|
||||||
(isOptionEnabled, remoteConfig) => {
|
remoteConfig => {
|
||||||
return (
|
return isRemoteConfigFlagEnabled(remoteConfig, 'desktop.textFormatting');
|
||||||
isOptionEnabled &&
|
|
||||||
isRemoteConfigFlagEnabled(remoteConfig, 'desktop.textFormatting')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const getIsFormattingSpoilersEnabled = createSelector(
|
export const getIsFormattingSpoilersFlagEnabled = createSelector(
|
||||||
getTextFormattingEnabled,
|
|
||||||
getRemoteConfig,
|
getRemoteConfig,
|
||||||
(isOptionEnabled, remoteConfig) => {
|
remoteConfig => {
|
||||||
return (
|
return isRemoteConfigFlagEnabled(
|
||||||
isOptionEnabled &&
|
remoteConfig,
|
||||||
isRemoteConfigFlagEnabled(
|
'desktop.textFormatting.spoilerSend'
|
||||||
remoteConfig,
|
|
||||||
'desktop.textFormatting.spoilerSend'
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { imageToBlurHash } from '../../util/imageToBlurHash';
|
||||||
import { getPreferredBadgeSelector } from '../selectors/badges';
|
import { getPreferredBadgeSelector } from '../selectors/badges';
|
||||||
import { selectRecentEmojis } from '../selectors/emojis';
|
import { selectRecentEmojis } from '../selectors/emojis';
|
||||||
import { getIntl, getTheme, getUserConversationId } from '../selectors/user';
|
import { getIntl, getTheme, getUserConversationId } from '../selectors/user';
|
||||||
import { getEmojiSkinTone } from '../selectors/items';
|
import { getEmojiSkinTone, getTextFormattingEnabled } from '../selectors/items';
|
||||||
import {
|
import {
|
||||||
getConversationSelector,
|
getConversationSelector,
|
||||||
getGroupAdminsSelector,
|
getGroupAdminsSelector,
|
||||||
|
@ -34,8 +34,8 @@ import {
|
||||||
import { isSignalConversation } from '../../util/isSignalConversation';
|
import { isSignalConversation } from '../../util/isSignalConversation';
|
||||||
import {
|
import {
|
||||||
getComposerStateForConversationIdSelector,
|
getComposerStateForConversationIdSelector,
|
||||||
getIsFormattingEnabled,
|
getIsFormattingFlagEnabled,
|
||||||
getIsFormattingSpoilersEnabled,
|
getIsFormattingSpoilersFlagEnabled,
|
||||||
} from '../selectors/composer';
|
} from '../selectors/composer';
|
||||||
import type { SmartCompositionRecordingProps } from './CompositionRecording';
|
import type { SmartCompositionRecordingProps } from './CompositionRecording';
|
||||||
import { SmartCompositionRecording } from './CompositionRecording';
|
import { SmartCompositionRecording } from './CompositionRecording';
|
||||||
|
@ -98,8 +98,11 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
|
||||||
|
|
||||||
const selectedMessageIds = getSelectedMessageIds(state);
|
const selectedMessageIds = getSelectedMessageIds(state);
|
||||||
|
|
||||||
const isFormattingEnabled = getIsFormattingEnabled(state);
|
const isFormattingEnabled =
|
||||||
const isFormattingSpoilersEnabled = getIsFormattingSpoilersEnabled(state);
|
getIsFormattingFlagEnabled(state) && getTextFormattingEnabled(state);
|
||||||
|
const isFormattingSpoilersEnabled =
|
||||||
|
getIsFormattingSpoilersFlagEnabled(state) &&
|
||||||
|
getTextFormattingEnabled(state);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// Base
|
// Base
|
||||||
|
|
|
@ -13,9 +13,10 @@ import { useActions as useItemsActions } from '../ducks/items';
|
||||||
import { getPreferredBadgeSelector } from '../selectors/badges';
|
import { getPreferredBadgeSelector } from '../selectors/badges';
|
||||||
import { useComposerActions } from '../ducks/composer';
|
import { useComposerActions } from '../ducks/composer';
|
||||||
import {
|
import {
|
||||||
getIsFormattingEnabled,
|
getIsFormattingFlagEnabled,
|
||||||
getIsFormattingSpoilersEnabled,
|
getIsFormattingSpoilersFlagEnabled,
|
||||||
} from '../selectors/composer';
|
} from '../selectors/composer';
|
||||||
|
import { getTextFormattingEnabled } from '../selectors/items';
|
||||||
|
|
||||||
export type SmartCompositionTextAreaProps = Pick<
|
export type SmartCompositionTextAreaProps = Pick<
|
||||||
CompositionTextAreaProps,
|
CompositionTextAreaProps,
|
||||||
|
@ -41,10 +42,12 @@ export function SmartCompositionTextArea(
|
||||||
const { onTextTooLong } = useComposerActions();
|
const { onTextTooLong } = useComposerActions();
|
||||||
|
|
||||||
const getPreferredBadge = useSelector(getPreferredBadgeSelector);
|
const getPreferredBadge = useSelector(getPreferredBadgeSelector);
|
||||||
const isFormattingEnabled = useSelector(getIsFormattingEnabled);
|
const isFormattingOptionEnabled = useSelector(getTextFormattingEnabled);
|
||||||
const isFormattingSpoilersEnabled = useSelector(
|
const isFormattingEnabled =
|
||||||
getIsFormattingSpoilersEnabled
|
useSelector(getIsFormattingFlagEnabled) && isFormattingOptionEnabled;
|
||||||
);
|
const isFormattingSpoilersEnabled =
|
||||||
|
useSelector(getIsFormattingSpoilersFlagEnabled) &&
|
||||||
|
isFormattingOptionEnabled;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CompositionTextArea
|
<CompositionTextArea
|
||||||
|
|
|
@ -15,8 +15,8 @@ import {
|
||||||
getReceivedStickerPacks,
|
getReceivedStickerPacks,
|
||||||
} from '../selectors/stickers';
|
} from '../selectors/stickers';
|
||||||
import {
|
import {
|
||||||
getIsFormattingEnabled,
|
getIsFormattingFlagEnabled,
|
||||||
getIsFormattingSpoilersEnabled,
|
getIsFormattingSpoilersFlagEnabled,
|
||||||
} from '../selectors/composer';
|
} from '../selectors/composer';
|
||||||
|
|
||||||
const mapStateToProps = (state: StateType) => {
|
const mapStateToProps = (state: StateType) => {
|
||||||
|
@ -25,8 +25,9 @@ const mapStateToProps = (state: StateType) => {
|
||||||
const knownPacks = getKnownStickerPacks(state);
|
const knownPacks = getKnownStickerPacks(state);
|
||||||
const receivedPacks = getReceivedStickerPacks(state);
|
const receivedPacks = getReceivedStickerPacks(state);
|
||||||
|
|
||||||
const isFormattingFlagEnabled = getIsFormattingEnabled(state);
|
const isFormattingFlagEnabled = getIsFormattingFlagEnabled(state);
|
||||||
const isFormattingSpoilersFlagEnabled = getIsFormattingSpoilersEnabled(state);
|
const isFormattingSpoilersFlagEnabled =
|
||||||
|
getIsFormattingSpoilersFlagEnabled(state);
|
||||||
|
|
||||||
const hasInstalledStickers =
|
const hasInstalledStickers =
|
||||||
countStickers({
|
countStickers({
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
getEmojiSkinTone,
|
getEmojiSkinTone,
|
||||||
getHasStoryViewReceiptSetting,
|
getHasStoryViewReceiptSetting,
|
||||||
getPreferredReactionEmoji,
|
getPreferredReactionEmoji,
|
||||||
|
getTextFormattingEnabled,
|
||||||
isInternalUser,
|
isInternalUser,
|
||||||
} from '../selectors/items';
|
} from '../selectors/items';
|
||||||
import { getIntl, getPlatform } from '../selectors/user';
|
import { getIntl, getPlatform } from '../selectors/user';
|
||||||
|
@ -40,8 +41,8 @@ import { useGlobalModalActions } from '../ducks/globalModals';
|
||||||
import { useStoriesActions } from '../ducks/stories';
|
import { useStoriesActions } from '../ducks/stories';
|
||||||
import { useIsWindowActive } from '../../hooks/useIsWindowActive';
|
import { useIsWindowActive } from '../../hooks/useIsWindowActive';
|
||||||
import {
|
import {
|
||||||
getIsFormattingEnabled,
|
getIsFormattingFlagEnabled,
|
||||||
getIsFormattingSpoilersEnabled,
|
getIsFormattingSpoilersFlagEnabled,
|
||||||
} from '../selectors/composer';
|
} from '../selectors/composer';
|
||||||
|
|
||||||
export function SmartStoryViewer(): JSX.Element | null {
|
export function SmartStoryViewer(): JSX.Element | null {
|
||||||
|
@ -93,10 +94,12 @@ export function SmartStoryViewer(): JSX.Element | null {
|
||||||
getHasStoryViewReceiptSetting
|
getHasStoryViewReceiptSetting
|
||||||
);
|
);
|
||||||
|
|
||||||
const isFormattingEnabled = useSelector(getIsFormattingEnabled);
|
const isFormattingOptionEnabled = useSelector(getTextFormattingEnabled);
|
||||||
const isFormattingSpoilersEnabled = useSelector(
|
const isFormattingEnabled =
|
||||||
getIsFormattingSpoilersEnabled
|
useSelector(getIsFormattingFlagEnabled) && isFormattingOptionEnabled;
|
||||||
);
|
const isFormattingSpoilersEnabled =
|
||||||
|
useSelector(getIsFormattingSpoilersFlagEnabled) &&
|
||||||
|
isFormattingOptionEnabled;
|
||||||
|
|
||||||
const { pauseVoiceNotePlayer } = useAudioPlayerActions();
|
const { pauseVoiceNotePlayer } = useAudioPlayerActions();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue