mirror of
https://github.com/outline/outline.git
synced 2025-12-21 10:39:41 -06:00
Add user preference to disable smart quotes (#7881)
This commit is contained in:
committed by
GitHub
parent
68377c3c46
commit
f5de2834d6
@@ -255,6 +255,7 @@ function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
|
||||
<ErrorBoundary component="div" reloadOnChunkMissing>
|
||||
<>
|
||||
<LazyLoadedEditor
|
||||
key={props.extensions?.length || 0}
|
||||
ref={mergeRefs([ref, localRef, handleRefChanged])}
|
||||
uploadFile={handleUploadFile}
|
||||
embeds={embeds}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { observer } from "mobx-react";
|
||||
import * as React from "react";
|
||||
import { UserPreferenceDefaults } from "@shared/constants";
|
||||
import { basicExtensions, withComments } from "@shared/editor/nodes";
|
||||
import HardBreak from "@shared/editor/nodes/HardBreak";
|
||||
import { UserPreference } from "@shared/types";
|
||||
import Editor, { Props as EditorProps } from "~/components/Editor";
|
||||
import type { Editor as SharedEditor } from "~/editor";
|
||||
import ClipboardTextSerializer from "~/editor/extensions/ClipboardTextSerializer";
|
||||
@@ -13,24 +15,30 @@ import PreventTab from "~/editor/extensions/PreventTab";
|
||||
import SmartText from "~/editor/extensions/SmartText";
|
||||
import useCurrentUser from "~/hooks/useCurrentUser";
|
||||
|
||||
const extensions = [
|
||||
...withComments(basicExtensions),
|
||||
HardBreak,
|
||||
SmartText,
|
||||
PasteHandler,
|
||||
ClipboardTextSerializer,
|
||||
EmojiMenuExtension,
|
||||
MentionMenuExtension,
|
||||
// Order these default key handlers last
|
||||
PreventTab,
|
||||
Keys,
|
||||
];
|
||||
|
||||
const CommentEditor = (
|
||||
props: EditorProps,
|
||||
ref: React.RefObject<SharedEditor>
|
||||
) => {
|
||||
const user = useCurrentUser({ rejectOnEmpty: false });
|
||||
const enableSmartText =
|
||||
user?.getPreference(UserPreference.EnableSmartText) ??
|
||||
UserPreferenceDefaults.enableSmartText;
|
||||
|
||||
const extensions = React.useMemo(
|
||||
() => [
|
||||
...withComments(basicExtensions),
|
||||
HardBreak,
|
||||
...(enableSmartText ? [SmartText] : []),
|
||||
PasteHandler,
|
||||
ClipboardTextSerializer,
|
||||
EmojiMenuExtension,
|
||||
MentionMenuExtension,
|
||||
// Order these default key handlers last
|
||||
PreventTab,
|
||||
Keys,
|
||||
],
|
||||
[enableSmartText]
|
||||
);
|
||||
|
||||
return (
|
||||
<Editor extensions={extensions} userId={user?.id} {...props} ref={ref} />
|
||||
|
||||
@@ -4,8 +4,9 @@ import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { mergeRefs } from "react-merge-refs";
|
||||
import { useHistory, useRouteMatch } from "react-router-dom";
|
||||
import { UserPreferenceDefaults } from "@shared/constants";
|
||||
import { richExtensions, withComments } from "@shared/editor/nodes";
|
||||
import { TeamPreference } from "@shared/types";
|
||||
import { TeamPreference, UserPreference } from "@shared/types";
|
||||
import { colorPalette } from "@shared/utils/collections";
|
||||
import Comment from "~/models/Comment";
|
||||
import Document from "~/models/Document";
|
||||
@@ -38,21 +39,6 @@ import MultiplayerEditor from "./AsyncMultiplayerEditor";
|
||||
import DocumentMeta from "./DocumentMeta";
|
||||
import DocumentTitle from "./DocumentTitle";
|
||||
|
||||
const extensions = [
|
||||
...withComments(richExtensions),
|
||||
SmartText,
|
||||
PasteHandler,
|
||||
ClipboardTextSerializer,
|
||||
BlockMenuExtension,
|
||||
EmojiMenuExtension,
|
||||
MentionMenuExtension,
|
||||
FindAndReplaceExtension,
|
||||
HoverPreviewsExtension,
|
||||
// Order these default key handlers last
|
||||
PreventTab,
|
||||
Keys,
|
||||
];
|
||||
|
||||
type Props = Omit<EditorProps, "editorStyle"> & {
|
||||
onChangeTitle: (title: string) => void;
|
||||
onChangeIcon: (icon: string | null, color: string | null) => void;
|
||||
@@ -94,6 +80,28 @@ function DocumentEditor(props: Props, ref: React.RefObject<any>) {
|
||||
} = props;
|
||||
const can = usePolicy(document);
|
||||
|
||||
const enableSmartText =
|
||||
user?.getPreference(UserPreference.EnableSmartText) ??
|
||||
UserPreferenceDefaults.enableSmartText;
|
||||
|
||||
const extensions = React.useMemo(
|
||||
() => [
|
||||
...withComments(richExtensions),
|
||||
...(enableSmartText ? [SmartText] : []),
|
||||
PasteHandler,
|
||||
ClipboardTextSerializer,
|
||||
BlockMenuExtension,
|
||||
EmojiMenuExtension,
|
||||
MentionMenuExtension,
|
||||
FindAndReplaceExtension,
|
||||
HoverPreviewsExtension,
|
||||
// Order these default key handlers last
|
||||
PreventTab,
|
||||
Keys,
|
||||
],
|
||||
[enableSmartText]
|
||||
);
|
||||
|
||||
const iconColor = document.color ?? (last(colorPalette) as string);
|
||||
const childRef = React.useRef<HTMLDivElement>(null);
|
||||
const focusAtStart = React.useCallback(() => {
|
||||
|
||||
@@ -153,7 +153,6 @@ function Preferences() {
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
border={false}
|
||||
name={UserPreference.RememberLastPath}
|
||||
label={t("Remember previous location")}
|
||||
description={t(
|
||||
@@ -167,6 +166,21 @@ function Preferences() {
|
||||
onChange={handlePreferenceChange(false)}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
border={false}
|
||||
name={UserPreference.EnableSmartText}
|
||||
label={t("Smart text replacements")}
|
||||
description={t(
|
||||
"Auto-format text by replacing shortcuts with symbols, dashes, smart quotes, and other typographical elements."
|
||||
)}
|
||||
>
|
||||
<Switch
|
||||
id={UserPreference.EnableSmartText}
|
||||
name={UserPreference.EnableSmartText}
|
||||
checked={!!user.getPreference(UserPreference.EnableSmartText)}
|
||||
onChange={handlePreferenceChange(false)}
|
||||
/>
|
||||
</SettingRow>
|
||||
|
||||
{can.delete && (
|
||||
<>
|
||||
|
||||
@@ -33,4 +33,5 @@ export const UserPreferenceDefaults: UserPreferences = {
|
||||
[UserPreference.UseCursorPointer]: true,
|
||||
[UserPreference.CodeBlockLineNumers]: true,
|
||||
[UserPreference.SortCommentsByOrderInDocument]: false,
|
||||
[UserPreference.EnableSmartText]: true,
|
||||
};
|
||||
|
||||
@@ -961,6 +961,8 @@
|
||||
"When enabled, documents have a separate editing mode. When disabled, documents are always editable when you have permission.": "When enabled, documents have a separate editing mode. When disabled, documents are always editable when you have permission.",
|
||||
"Remember previous location": "Remember previous location",
|
||||
"Automatically return to the document you were last viewing when the app is re-opened.": "Automatically return to the document you were last viewing when the app is re-opened.",
|
||||
"Smart text replacements": "Smart text replacements",
|
||||
"Auto-format text by replacing shortcuts with symbols, dashes, smart quotes, and other typographical elements.": "Auto-format text by replacing shortcuts with symbols, dashes, smart quotes, and other typographical elements.",
|
||||
"You may delete your account at any time, note that this is unrecoverable": "You may delete your account at any time, note that this is unrecoverable",
|
||||
"Profile saved": "Profile saved",
|
||||
"Profile picture updated": "Profile picture updated",
|
||||
|
||||
@@ -170,6 +170,8 @@ export enum UserPreference {
|
||||
FullWidthDocuments = "fullWidthDocuments",
|
||||
/** Whether to sort the comments by their order in the document. */
|
||||
SortCommentsByOrderInDocument = "sortCommentsByOrderInDocument",
|
||||
/** Whether smart text replacements should be enabled. */
|
||||
EnableSmartText = "enableSmartText",
|
||||
}
|
||||
|
||||
export type UserPreferences = { [key in UserPreference]?: boolean };
|
||||
|
||||
Reference in New Issue
Block a user