mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
fix(core): add option to disable middle click paste behavior on linux (#11496)
fix BS-3028
This commit is contained in:
@@ -25,14 +25,13 @@ import type { DefaultOpenProperty } from '../../components/doc-properties';
|
||||
import { BlocksuiteDocEditor, BlocksuiteEdgelessEditor } from './lit-adaper';
|
||||
import * as styles from './styles.css';
|
||||
|
||||
interface BlocksuiteEditorContainerProps {
|
||||
interface BlocksuiteEditorContainerProps
|
||||
extends React.HTMLAttributes<HTMLDivElement> {
|
||||
page: Store;
|
||||
mode: DocMode;
|
||||
shared?: boolean;
|
||||
readonly?: boolean;
|
||||
className?: string;
|
||||
defaultOpenProperty?: DefaultOpenProperty;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export interface AffineEditorContainer extends HTMLElement {
|
||||
@@ -51,7 +50,7 @@ export const BlocksuiteEditorContainer = forwardRef<
|
||||
AffineEditorContainer,
|
||||
BlocksuiteEditorContainerProps
|
||||
>(function AffineEditorContainer(
|
||||
{ page, mode, className, style, shared, readonly, defaultOpenProperty },
|
||||
{ page, mode, shared, readonly, defaultOpenProperty, ...props },
|
||||
ref
|
||||
) {
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
@@ -159,15 +158,16 @@ export const BlocksuiteEditorContainer = forwardRef<
|
||||
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
data-testid={`editor-${page.id}`}
|
||||
dir={enableEditorRTL ? 'rtl' : 'ltr'}
|
||||
className={clsx(
|
||||
`editor-wrapper ${mode}-mode`,
|
||||
styles.docEditorRoot,
|
||||
className
|
||||
props.className
|
||||
)}
|
||||
data-affine-editor-container
|
||||
style={style}
|
||||
style={props.style}
|
||||
ref={rootRef}
|
||||
>
|
||||
{mode === 'page' ? (
|
||||
|
||||
@@ -16,8 +16,8 @@ import type { Store } from '@blocksuite/affine/store';
|
||||
import { Slot } from '@radix-ui/react-slot';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import type { CSSProperties, HTMLAttributes } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import type { DefaultOpenProperty } from '../../components/doc-properties';
|
||||
import {
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
} from './blocksuite-editor-container';
|
||||
import { NoPageRootError } from './no-page-error';
|
||||
|
||||
export type EditorProps = {
|
||||
export interface EditorProps extends HTMLAttributes<HTMLDivElement> {
|
||||
page: Store;
|
||||
mode: DocMode;
|
||||
shared?: boolean;
|
||||
@@ -34,9 +34,7 @@ export type EditorProps = {
|
||||
defaultOpenProperty?: DefaultOpenProperty;
|
||||
// on Editor ready
|
||||
onEditorReady?: (editor: AffineEditorContainer) => (() => void) | void;
|
||||
style?: CSSProperties;
|
||||
className?: string;
|
||||
};
|
||||
}
|
||||
|
||||
const BlockSuiteEditorImpl = ({
|
||||
mode,
|
||||
@@ -47,6 +45,7 @@ const BlockSuiteEditorImpl = ({
|
||||
style,
|
||||
onEditorReady,
|
||||
defaultOpenProperty,
|
||||
...props
|
||||
}: EditorProps) => {
|
||||
useEffect(() => {
|
||||
const disposable = page.slots.blockUpdated.subscribe(() => {
|
||||
@@ -111,6 +110,7 @@ const BlockSuiteEditorImpl = ({
|
||||
|
||||
return (
|
||||
<BlocksuiteEditorContainer
|
||||
{...props}
|
||||
mode={mode}
|
||||
page={page}
|
||||
shared={shared}
|
||||
@@ -133,6 +133,7 @@ export const BlockSuiteEditor = (props: EditorProps) => {
|
||||
fontFamily: s.fontFamily,
|
||||
customFontFamily: s.customFontFamily,
|
||||
fullWidthLayout: s.fullWidthLayout,
|
||||
disableMiddleClickPaste: s.disableMiddleClickPaste,
|
||||
}))
|
||||
);
|
||||
const fontFamily = useMemo(() => {
|
||||
@@ -169,12 +170,24 @@ export const BlockSuiteEditor = (props: EditorProps) => {
|
||||
};
|
||||
}, [props.page]);
|
||||
|
||||
const handleMouseDown = useCallback(
|
||||
(e: React.MouseEvent<HTMLDivElement>) => {
|
||||
if (settings.disableMiddleClickPaste && e.button === 1) {
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
[settings.disableMiddleClickPaste]
|
||||
);
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return (
|
||||
<Slot style={{ '--affine-font-family': fontFamily } as CSSProperties}>
|
||||
<Slot
|
||||
style={{ '--affine-font-family': fontFamily } as CSSProperties}
|
||||
onMouseDown={handleMouseDown}
|
||||
>
|
||||
{isLoading ? (
|
||||
<EditorLoading />
|
||||
) : (
|
||||
|
||||
@@ -487,6 +487,36 @@ const SpellCheckSettings = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const MiddleClickPasteSettings = () => {
|
||||
const t = useI18n();
|
||||
const editorSettingService = useService(EditorSettingService);
|
||||
const settings = useLiveData(editorSettingService.editorSetting.settings$);
|
||||
const onToggleMiddleClickPaste = useCallback(
|
||||
(checked: boolean) => {
|
||||
editorSettingService.editorSetting.set(
|
||||
'disableMiddleClickPaste',
|
||||
checked
|
||||
);
|
||||
},
|
||||
[editorSettingService.editorSetting]
|
||||
);
|
||||
return (
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.general.middle-click-paste.title'
|
||||
]()}
|
||||
desc={t[
|
||||
'com.affine.settings.editorSettings.general.middle-click-paste.description'
|
||||
]()}
|
||||
>
|
||||
<Switch
|
||||
checked={settings.disableMiddleClickPaste}
|
||||
onChange={onToggleMiddleClickPaste}
|
||||
/>
|
||||
</SettingRow>
|
||||
);
|
||||
};
|
||||
|
||||
export const General = () => {
|
||||
const t = useI18n();
|
||||
|
||||
@@ -497,6 +527,7 @@ export const General = () => {
|
||||
<CustomFontFamilySettings />
|
||||
<NewDocDefaultModeSettings />
|
||||
{BUILD_CONFIG.isElectron && <SpellCheckSettings />}
|
||||
{environment.isLinux && <MiddleClickPasteSettings />}
|
||||
{/* // TODO(@akumatus): implement these settings
|
||||
<DeFaultCodeBlockSettings />
|
||||
*/}
|
||||
|
||||
@@ -34,6 +34,8 @@ const AffineEditorSettingSchema = z.object({
|
||||
'open-in-center-peek',
|
||||
])
|
||||
.default('open-in-active-view'),
|
||||
// linux only:
|
||||
disableMiddleClickPaste: z.boolean().default(false),
|
||||
});
|
||||
|
||||
export const EditorSettingSchema = BSEditorSettingSchema.merge(
|
||||
|
||||
@@ -5167,6 +5167,14 @@ export function useAFFiNEI18N(): {
|
||||
* `Page`
|
||||
*/
|
||||
["com.affine.settings.editorSettings.page"](): string;
|
||||
/**
|
||||
* `Middle click paste`
|
||||
*/
|
||||
["com.affine.settings.editorSettings.general.middle-click-paste.title"](): string;
|
||||
/**
|
||||
* `Disable default middle click paste behavior on Linux.`
|
||||
*/
|
||||
["com.affine.settings.editorSettings.general.middle-click-paste.description"](): string;
|
||||
/**
|
||||
* `Display bi-directional links on the doc.`
|
||||
*/
|
||||
|
||||
@@ -1287,6 +1287,8 @@
|
||||
"com.affine.settings.editorSettings.general.spell-check.title": "Spell check",
|
||||
"com.affine.settings.editorSettings.general.spell-check.restart-hint": "Settings changed; please restart the app. <1>Restart</1>",
|
||||
"com.affine.settings.editorSettings.page": "Page",
|
||||
"com.affine.settings.editorSettings.general.middle-click-paste.title": "Middle click paste",
|
||||
"com.affine.settings.editorSettings.general.middle-click-paste.description": "Disable default middle click paste behavior on Linux.",
|
||||
"com.affine.settings.editorSettings.page.display-bi-link.description": "Display bi-directional links on the doc.",
|
||||
"com.affine.settings.editorSettings.page.display-bi-link.title": "Display bi-directional links",
|
||||
"com.affine.settings.editorSettings.page.display-doc-info.description": "Display document information on the doc.",
|
||||
|
||||
Reference in New Issue
Block a user