mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
Merge remote-tracking branch 'origin/master' into payment-system
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { atom, useAtom } from 'jotai';
|
||||
import { atom } from 'jotai';
|
||||
import { atomWithStorage } from 'jotai/utils';
|
||||
|
||||
export type DateFormats =
|
||||
@@ -75,7 +75,3 @@ export const appSettingAtom = atom<
|
||||
set(appSettingBaseAtom, { ...prev, ...next });
|
||||
}
|
||||
);
|
||||
|
||||
export const useAppSetting = () => {
|
||||
return useAtom(appSettingAtom);
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ export function registerAffineCreationCommands({
|
||||
registerAffineCommand({
|
||||
id: 'affine:new-page',
|
||||
category: 'affine:creation',
|
||||
label: t['com.affine.cmdk.affine.new-page'],
|
||||
label: t['com.affine.cmdk.affine.new-page'](),
|
||||
icon: <PlusIcon />,
|
||||
keyBinding: environment.isDesktop
|
||||
? {
|
||||
@@ -39,7 +39,7 @@ export function registerAffineCreationCommands({
|
||||
id: 'affine:new-edgeless-page',
|
||||
category: 'affine:creation',
|
||||
icon: <PlusIcon />,
|
||||
label: t['com.affine.cmdk.affine.new-edgeless-page'],
|
||||
label: t['com.affine.cmdk.affine.new-edgeless-page'](),
|
||||
run() {
|
||||
pageHelper.createEdgeless();
|
||||
},
|
||||
@@ -51,7 +51,7 @@ export function registerAffineCreationCommands({
|
||||
id: 'affine:new-workspace',
|
||||
category: 'affine:creation',
|
||||
icon: <PlusIcon />,
|
||||
label: t['com.affine.cmdk.affine.new-workspace'],
|
||||
label: t['com.affine.cmdk.affine.new-workspace'](),
|
||||
run() {
|
||||
store.set(openCreateWorkspaceModalAtom, 'new');
|
||||
},
|
||||
@@ -62,7 +62,7 @@ export function registerAffineCreationCommands({
|
||||
id: 'affine:import-workspace',
|
||||
category: 'affine:creation',
|
||||
icon: <ImportIcon />,
|
||||
label: t['com.affine.cmdk.affine.import-workspace'],
|
||||
label: t['com.affine.cmdk.affine.import-workspace'](),
|
||||
preconditionStrategy: () => {
|
||||
return environment.isDesktop;
|
||||
},
|
||||
|
||||
@@ -18,7 +18,7 @@ export function registerAffineHelpCommands({
|
||||
id: 'affine:help-whats-new',
|
||||
category: 'affine:help',
|
||||
icon: <NewIcon />,
|
||||
label: () => t['com.affine.cmdk.affine.whats-new'](),
|
||||
label: t['com.affine.cmdk.affine.whats-new'](),
|
||||
run() {
|
||||
window.open(runtimeConfig.changelogUrl, '_blank');
|
||||
},
|
||||
@@ -29,7 +29,7 @@ export function registerAffineHelpCommands({
|
||||
id: 'affine:help-contact-us',
|
||||
category: 'affine:help',
|
||||
icon: <ContactWithUsIcon />,
|
||||
label: () => t['com.affine.cmdk.affine.contact-us'](),
|
||||
label: t['com.affine.cmdk.affine.contact-us'](),
|
||||
run() {
|
||||
store.set(openSettingModalAtom, {
|
||||
open: true,
|
||||
@@ -44,7 +44,7 @@ export function registerAffineHelpCommands({
|
||||
id: 'affine:help-getting-started',
|
||||
category: 'affine:help',
|
||||
icon: <UserGuideIcon />,
|
||||
label: () => t['com.affine.cmdk.affine.getting-started'](),
|
||||
label: t['com.affine.cmdk.affine.getting-started'](),
|
||||
preconditionStrategy: () => environment.isDesktop,
|
||||
run() {
|
||||
store.set(openOnboardingModalAtom, true);
|
||||
|
||||
@@ -17,14 +17,11 @@ export function registerAffineLayoutCommands({
|
||||
id: 'affine:toggle-left-sidebar',
|
||||
category: 'affine:layout',
|
||||
icon: <SidebarIcon />,
|
||||
label: () => {
|
||||
const open = store.get(appSidebarOpenAtom);
|
||||
return t[
|
||||
open
|
||||
? 'com.affine.cmdk.affine.left-sidebar.collapse'
|
||||
: 'com.affine.cmdk.affine.left-sidebar.expand'
|
||||
]();
|
||||
},
|
||||
label: () =>
|
||||
store.get(appSidebarOpenAtom)
|
||||
? t['com.affine.cmdk.affine.left-sidebar.collapse']()
|
||||
: t['com.affine.cmdk.affine.left-sidebar.expand'](),
|
||||
|
||||
keyBinding: {
|
||||
binding: '$mod+/',
|
||||
},
|
||||
|
||||
@@ -33,7 +33,7 @@ export function registerAffineNavigationCommands({
|
||||
id: 'affine:goto-all-pages',
|
||||
category: 'affine:navigation',
|
||||
icon: <ArrowRightBigIcon />,
|
||||
label: () => t['com.affine.cmdk.affine.navigation.goto-all-pages'](),
|
||||
label: t['com.affine.cmdk.affine.navigation.goto-all-pages'](),
|
||||
run() {
|
||||
navigationHelper.jumpToSubPath(workspace.id, WorkspaceSubPath.ALL);
|
||||
setPageListMode('all');
|
||||
@@ -49,7 +49,7 @@ export function registerAffineNavigationCommands({
|
||||
preconditionStrategy: () => {
|
||||
return pageListMode !== 'page';
|
||||
},
|
||||
label: () => t['com.affine.cmdk.affine.navigation.goto-page-list'](),
|
||||
label: t['com.affine.cmdk.affine.navigation.goto-page-list'](),
|
||||
run() {
|
||||
navigationHelper.jumpToSubPath(workspace.id, WorkspaceSubPath.ALL);
|
||||
setPageListMode('page');
|
||||
@@ -65,7 +65,7 @@ export function registerAffineNavigationCommands({
|
||||
preconditionStrategy: () => {
|
||||
return pageListMode !== 'edgeless';
|
||||
},
|
||||
label: () => t['com.affine.cmdk.affine.navigation.goto-edgeless-list'](),
|
||||
label: t['com.affine.cmdk.affine.navigation.goto-edgeless-list'](),
|
||||
run() {
|
||||
navigationHelper.jumpToSubPath(workspace.id, WorkspaceSubPath.ALL);
|
||||
setPageListMode('edgeless');
|
||||
@@ -78,7 +78,7 @@ export function registerAffineNavigationCommands({
|
||||
id: 'affine:goto-workspace',
|
||||
category: 'affine:navigation',
|
||||
icon: <ArrowRightBigIcon />,
|
||||
label: () => t['com.affine.cmdk.affine.navigation.goto-workspace'](),
|
||||
label: t['com.affine.cmdk.affine.navigation.goto-workspace'](),
|
||||
run() {
|
||||
store.set(openWorkspaceListModalAtom, true);
|
||||
},
|
||||
@@ -90,7 +90,7 @@ export function registerAffineNavigationCommands({
|
||||
id: 'affine:open-settings',
|
||||
category: 'affine:navigation',
|
||||
icon: <ArrowRightBigIcon />,
|
||||
label: () => t['com.affine.cmdk.affine.navigation.open-settings'](),
|
||||
label: t['com.affine.cmdk.affine.navigation.open-settings'](),
|
||||
run() {
|
||||
store.set(openSettingModalAtom, {
|
||||
activeTab: 'appearance',
|
||||
@@ -106,7 +106,7 @@ export function registerAffineNavigationCommands({
|
||||
id: 'affine:goto-trash',
|
||||
category: 'affine:navigation',
|
||||
icon: <ArrowRightBigIcon />,
|
||||
label: () => t['com.affine.cmdk.affine.navigation.goto-trash'](),
|
||||
label: t['com.affine.cmdk.affine.navigation.goto-trash'](),
|
||||
run() {
|
||||
navigationHelper.jumpToSubPath(workspace.id, WorkspaceSubPath.TRASH);
|
||||
setPageListMode('all');
|
||||
|
||||
@@ -1,76 +1,16 @@
|
||||
import { Trans } from '@affine/i18n';
|
||||
import type { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { SettingsIcon } from '@blocksuite/icons';
|
||||
import {
|
||||
PreconditionStrategy,
|
||||
registerAffineCommand,
|
||||
} from '@toeverything/infra/command';
|
||||
import { type createStore, useAtomValue } from 'jotai';
|
||||
import { type createStore } from 'jotai';
|
||||
import type { useTheme } from 'next-themes';
|
||||
|
||||
import { openQuickSearchModalAtom } from '../atoms';
|
||||
import { appSettingAtom } from '../atoms/settings';
|
||||
import type { useLanguageHelper } from '../hooks/affine/use-language-helper';
|
||||
|
||||
// todo - find a better way to abstract the following translations components
|
||||
const ClientBorderStyleLabel = () => {
|
||||
const { clientBorder } = useAtomValue(appSettingAtom);
|
||||
return (
|
||||
<Trans
|
||||
i18nKey="com.affine.cmdk.affine.client-border-style.to"
|
||||
values={{
|
||||
state: clientBorder ? 'OFF' : 'ON',
|
||||
}}
|
||||
>
|
||||
Change Client Border Style to
|
||||
<strong>state</strong>
|
||||
</Trans>
|
||||
);
|
||||
};
|
||||
|
||||
const FullWidthLayoutLabel = () => {
|
||||
const { fullWidthLayout } = useAtomValue(appSettingAtom);
|
||||
return (
|
||||
<Trans
|
||||
i18nKey="com.affine.cmdk.affine.full-width-layout.to"
|
||||
values={{
|
||||
state: fullWidthLayout ? 'OFF' : 'ON',
|
||||
}}
|
||||
>
|
||||
Change Full Width Layout to
|
||||
<strong>state</strong>
|
||||
</Trans>
|
||||
);
|
||||
};
|
||||
|
||||
const NoisyBackgroundLabel = () => {
|
||||
const { enableNoisyBackground } = useAtomValue(appSettingAtom);
|
||||
return (
|
||||
<Trans
|
||||
i18nKey="com.affine.cmdk.affine.noise-background-on-the-sidebar.to"
|
||||
values={{
|
||||
state: enableNoisyBackground ? 'OFF' : 'ON',
|
||||
}}
|
||||
>
|
||||
Change Noise Background On The Sidebar to <strong>state</strong>
|
||||
</Trans>
|
||||
);
|
||||
};
|
||||
|
||||
const BlurBackgroundLabel = () => {
|
||||
const { enableBlurBackground } = useAtomValue(appSettingAtom);
|
||||
return (
|
||||
<Trans
|
||||
i18nKey="com.affine.cmdk.affine.translucent-ui-on-the-sidebar.to"
|
||||
values={{
|
||||
state: enableBlurBackground ? 'OFF' : 'ON',
|
||||
}}
|
||||
>
|
||||
Change Translucent UI On The Sidebar to <strong>state</strong>
|
||||
</Trans>
|
||||
);
|
||||
};
|
||||
|
||||
export function registerAffineSettingsCommands({
|
||||
t,
|
||||
store,
|
||||
@@ -83,7 +23,7 @@ export function registerAffineSettingsCommands({
|
||||
languageHelper: ReturnType<typeof useLanguageHelper>;
|
||||
}) {
|
||||
const unsubs: Array<() => void> = [];
|
||||
const { onSelect, languagesList, currentLanguage } = languageHelper;
|
||||
const { onLanguageChange, languagesList, currentLanguage } = languageHelper;
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: 'affine:show-quick-search',
|
||||
@@ -92,6 +32,7 @@ export function registerAffineSettingsCommands({
|
||||
keyBinding: {
|
||||
binding: '$mod+K',
|
||||
},
|
||||
label: '',
|
||||
icon: <SettingsIcon />,
|
||||
run() {
|
||||
const quickSearchModalState = store.get(openQuickSearchModalAtom);
|
||||
@@ -104,14 +45,9 @@ export function registerAffineSettingsCommands({
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: 'affine:change-color-scheme-to-auto',
|
||||
label: (
|
||||
<Trans
|
||||
i18nKey="com.affine.cmdk.affine.color-scheme.to"
|
||||
values={{ colour: 'Auto' }}
|
||||
>
|
||||
Change Colour Scheme to <strong>colour</strong>
|
||||
</Trans>
|
||||
),
|
||||
label: `${t['com.affine.cmdk.affine.color-scheme.to']()} ${t[
|
||||
'com.affine.themeSettings.system'
|
||||
]()}`,
|
||||
category: 'affine:settings',
|
||||
icon: <SettingsIcon />,
|
||||
preconditionStrategy: () => theme.theme !== 'system',
|
||||
@@ -123,14 +59,9 @@ export function registerAffineSettingsCommands({
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: 'affine:change-color-scheme-to-dark',
|
||||
label: (
|
||||
<Trans
|
||||
i18nKey="com.affine.cmdk.affine.color-scheme.to"
|
||||
values={{ colour: 'Dark' }}
|
||||
>
|
||||
Change Colour Scheme to <strong>colour</strong>
|
||||
</Trans>
|
||||
),
|
||||
label: `${t['com.affine.cmdk.affine.color-scheme.to']()} ${t[
|
||||
'com.affine.themeSettings.dark'
|
||||
]()}`,
|
||||
category: 'affine:settings',
|
||||
icon: <SettingsIcon />,
|
||||
preconditionStrategy: () => theme.theme !== 'dark',
|
||||
@@ -143,14 +74,9 @@ export function registerAffineSettingsCommands({
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: 'affine:change-color-scheme-to-light',
|
||||
label: (
|
||||
<Trans
|
||||
i18nKey="com.affine.cmdk.affine.color-scheme.to"
|
||||
values={{ colour: 'Light' }}
|
||||
>
|
||||
Change Colour Scheme to <strong>colour</strong>
|
||||
</Trans>
|
||||
),
|
||||
label: `${t['com.affine.cmdk.affine.color-scheme.to']()} ${t[
|
||||
'com.affine.themeSettings.light'
|
||||
]()}`,
|
||||
category: 'affine:settings',
|
||||
icon: <SettingsIcon />,
|
||||
preconditionStrategy: () => theme.theme !== 'light',
|
||||
@@ -164,16 +90,9 @@ export function registerAffineSettingsCommands({
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: 'affine:change-font-style-to-sans',
|
||||
label: (
|
||||
<Trans
|
||||
i18nKey="com.affine.cmdk.affine.font-style.to"
|
||||
values={{
|
||||
fontFamily: t['com.affine.appearanceSettings.fontStyle.sans'](),
|
||||
}}
|
||||
>
|
||||
Change Font Style to <strong>fontFamily</strong>
|
||||
</Trans>
|
||||
),
|
||||
label: `${t['com.affine.cmdk.affine.font-style.to']()} ${t[
|
||||
'com.affine.appearanceSettings.fontStyle.sans'
|
||||
]()}`,
|
||||
category: 'affine:settings',
|
||||
icon: <SettingsIcon />,
|
||||
preconditionStrategy: () =>
|
||||
@@ -190,19 +109,9 @@ export function registerAffineSettingsCommands({
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: 'affine:change-font-style-to-serif',
|
||||
label: (
|
||||
<Trans
|
||||
i18nKey="com.affine.cmdk.affine.font-style.to"
|
||||
values={{
|
||||
fontFamily: t['com.affine.appearanceSettings.fontStyle.serif'](),
|
||||
}}
|
||||
>
|
||||
Change Font Style to
|
||||
<strong style={{ fontFamily: 'var(--affine-font-serif-family)' }}>
|
||||
fontFamily
|
||||
</strong>
|
||||
</Trans>
|
||||
),
|
||||
label: `${t['com.affine.cmdk.affine.font-style.to']()} ${t[
|
||||
'com.affine.appearanceSettings.fontStyle.serif'
|
||||
]()}`,
|
||||
category: 'affine:settings',
|
||||
icon: <SettingsIcon />,
|
||||
preconditionStrategy: () =>
|
||||
@@ -219,19 +128,9 @@ export function registerAffineSettingsCommands({
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: 'affine:change-font-style-to-mono',
|
||||
label: (
|
||||
<Trans
|
||||
i18nKey="com.affine.cmdk.affine.font-style.to"
|
||||
values={{
|
||||
fontFamily: t['com.affine.appearanceSettings.fontStyle.mono'](),
|
||||
}}
|
||||
>
|
||||
Change Font Style to
|
||||
<strong style={{ fontFamily: 'var(--affine-font-mono-family)' }}>
|
||||
fontFamily
|
||||
</strong>
|
||||
</Trans>
|
||||
),
|
||||
label: `${t['com.affine.cmdk.affine.font-style.to']()} ${t[
|
||||
'com.affine.appearanceSettings.fontStyle.mono'
|
||||
]()}`,
|
||||
category: 'affine:settings',
|
||||
icon: <SettingsIcon />,
|
||||
preconditionStrategy: () =>
|
||||
@@ -250,22 +149,14 @@ export function registerAffineSettingsCommands({
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `affine:change-display-language-to-${language.name}`,
|
||||
label: (
|
||||
<Trans
|
||||
i18nKey="com.affine.cmdk.affine.display-language.to"
|
||||
values={{
|
||||
language: language.originalName,
|
||||
}}
|
||||
>
|
||||
Change Display Language to
|
||||
<strong>language</strong>
|
||||
</Trans>
|
||||
),
|
||||
label: `${t['com.affine.cmdk.affine.display-language.to']()} ${
|
||||
language.originalName
|
||||
}`,
|
||||
category: 'affine:settings',
|
||||
icon: <SettingsIcon />,
|
||||
preconditionStrategy: () => currentLanguage?.tag !== language.tag,
|
||||
run() {
|
||||
onSelect(language.tag);
|
||||
onLanguageChange(language.tag);
|
||||
},
|
||||
})
|
||||
);
|
||||
@@ -275,7 +166,12 @@ export function registerAffineSettingsCommands({
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `affine:change-client-border-style`,
|
||||
label: <ClientBorderStyleLabel />,
|
||||
label: () => `${t['com.affine.cmdk.affine.client-border-style.to']()} ${t[
|
||||
store.get(appSettingAtom).clientBorder
|
||||
? 'com.affine.cmdk.affine.switch-state.off'
|
||||
: 'com.affine.cmdk.affine.switch-state.on'
|
||||
]()}
|
||||
`,
|
||||
category: 'affine:settings',
|
||||
icon: <SettingsIcon />,
|
||||
preconditionStrategy: () => environment.isDesktop,
|
||||
@@ -291,7 +187,12 @@ export function registerAffineSettingsCommands({
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `affine:change-full-width-layout`,
|
||||
label: <FullWidthLayoutLabel />,
|
||||
label: () =>
|
||||
`${t['com.affine.cmdk.affine.full-width-layout.to']()} ${t[
|
||||
store.get(appSettingAtom).fullWidthLayout
|
||||
? 'com.affine.cmdk.affine.switch-state.off'
|
||||
: 'com.affine.cmdk.affine.switch-state.on'
|
||||
]()}`,
|
||||
category: 'affine:settings',
|
||||
icon: <SettingsIcon />,
|
||||
run() {
|
||||
@@ -306,7 +207,14 @@ export function registerAffineSettingsCommands({
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `affine:change-noise-background-on-the-sidebar`,
|
||||
label: <NoisyBackgroundLabel />,
|
||||
label: () =>
|
||||
`${t[
|
||||
'com.affine.cmdk.affine.noise-background-on-the-sidebar.to'
|
||||
]()} ${t[
|
||||
store.get(appSettingAtom).enableNoisyBackground
|
||||
? 'com.affine.cmdk.affine.switch-state.off'
|
||||
: 'com.affine.cmdk.affine.switch-state.on'
|
||||
]()}`,
|
||||
category: 'affine:settings',
|
||||
icon: <SettingsIcon />,
|
||||
preconditionStrategy: () => environment.isDesktop,
|
||||
@@ -322,7 +230,12 @@ export function registerAffineSettingsCommands({
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `affine:change-translucent-ui-on-the-sidebar`,
|
||||
label: <BlurBackgroundLabel />,
|
||||
label: () =>
|
||||
`${t['com.affine.cmdk.affine.translucent-ui-on-the-sidebar.to']()} ${t[
|
||||
store.get(appSettingAtom).enableBlurBackground
|
||||
? 'com.affine.cmdk.affine.switch-state.off'
|
||||
: 'com.affine.cmdk.affine.switch-state.on'
|
||||
]()}`,
|
||||
category: 'affine:settings',
|
||||
icon: <SettingsIcon />,
|
||||
preconditionStrategy: () => environment.isDesktop,
|
||||
|
||||
@@ -18,7 +18,7 @@ export function registerAffineUpdatesCommands({
|
||||
id: 'affine:restart-to-upgrade',
|
||||
category: 'affine:updates',
|
||||
icon: <ResetIcon />,
|
||||
label: () => t['com.affine.cmdk.affine.restart-to-upgrade'](),
|
||||
label: t['com.affine.cmdk.affine.restart-to-upgrade'](),
|
||||
preconditionStrategy: () => !!store.get(updateReadyAtom),
|
||||
run() {
|
||||
window.apis?.updater.quitAndInstall().catch(err => {
|
||||
|
||||
@@ -3,10 +3,10 @@ import {
|
||||
type WorkspaceRootProps,
|
||||
} from '@affine/component/workspace';
|
||||
|
||||
import { useAppSetting } from '../../atoms/settings';
|
||||
import { useAppSettingHelper } from '../../hooks/affine/use-app-setting-helper';
|
||||
|
||||
export const AppContainer = (props: WorkspaceRootProps) => {
|
||||
const [appSettings] = useAppSetting();
|
||||
const { appSettings } = useAppSettingHelper();
|
||||
|
||||
return (
|
||||
<AppContainerWithoutSettings
|
||||
|
||||
@@ -5,7 +5,8 @@ import { useLanguageHelper } from '../../../hooks/affine/use-language-helper';
|
||||
|
||||
// Fixme: keyboard focus should be supported by Menu component
|
||||
const LanguageMenuContent = memo(function LanguageMenuContent() {
|
||||
const { currentLanguage, languagesList, onSelect } = useLanguageHelper();
|
||||
const { currentLanguage, languagesList, onLanguageChange } =
|
||||
useLanguageHelper();
|
||||
return (
|
||||
<>
|
||||
{languagesList.map(option => {
|
||||
@@ -14,7 +15,7 @@ const LanguageMenuContent = memo(function LanguageMenuContent() {
|
||||
key={option.name}
|
||||
selected={currentLanguage?.originalName === option.originalName}
|
||||
title={option.name}
|
||||
onSelect={() => onSelect(option.tag)}
|
||||
onSelect={() => onLanguageChange(option.tag)}
|
||||
>
|
||||
{option.originalName}
|
||||
</MenuItem>
|
||||
|
||||
@@ -66,12 +66,7 @@ const PublishPanelAffine = (props: PublishPanelAffineProps) => {
|
||||
marginBottom: isPublic ? '12px' : '25px',
|
||||
}}
|
||||
>
|
||||
<Switch
|
||||
checked={isPublic}
|
||||
// onChange={useCallback(value => {
|
||||
// console.log('onChange', value);
|
||||
// }, [])}
|
||||
/>
|
||||
<Switch checked={isPublic} />
|
||||
</SettingRow>
|
||||
{isPublic ? (
|
||||
<FlexWrapper justifyContent="space-between" marginBottom={25}>
|
||||
|
||||
@@ -15,7 +15,7 @@ export const relatedLinks = [
|
||||
},
|
||||
{
|
||||
icon: <TwitterIcon />,
|
||||
title: 'Twitter',
|
||||
title: 'X',
|
||||
link: 'https://twitter.com/AffineOfficial',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// The icons here have been specially adjusted, they’re different from the ones in the @blocksuite/icons.
|
||||
|
||||
export { TwitterIcon } from '@blocksuite/icons';
|
||||
export const LogoIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
@@ -33,23 +36,6 @@ export const DocIcon = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const TwitterIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M22 5.88235C21.2639 6.21176 20.4704 6.42824 19.6482 6.53176C20.4895 6.03294 21.1396 5.24235 21.4455 4.29176C20.652 4.76235 19.7725 5.09176 18.8451 5.28C18.0899 4.47059 17.0287 4 15.8241 4C13.5774 4 11.7419 5.80706 11.7419 8.03765C11.7419 8.35765 11.7801 8.66824 11.847 8.96C8.4436 8.79059 5.413 7.18118 3.39579 4.74353C3.04207 5.33647 2.8413 6.03294 2.8413 6.76706C2.8413 8.16941 3.55832 9.41176 4.6673 10.1176C3.98853 10.1176 3.35755 9.92941 2.80306 9.64706V9.67529C2.80306 11.6329 4.21797 13.2706 6.09178 13.6376C5.49018 13.7997 4.8586 13.8223 4.24665 13.7035C4.50632 14.5059 5.01485 15.2079 5.70078 15.711C6.38671 16.2141 7.21553 16.4929 8.07075 16.5082C6.62106 17.6381 4.82409 18.2488 2.97514 18.24C2.6501 18.24 2.32505 18.2212 2 18.1835C3.81644 19.3318 5.97706 20 8.29063 20C15.8241 20 19.9637 13.8447 19.9637 8.50824C19.9637 8.32941 19.9637 8.16 19.9541 7.98118C20.7572 7.41647 21.4455 6.70118 22 5.88235Z"
|
||||
fill="#1D9BF0"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export const GithubIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
|
||||
@@ -4,21 +4,14 @@ import { SettingRow } from '@affine/component/setting-components';
|
||||
import { SettingWrapper } from '@affine/component/setting-components';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { ArrowRightSmallIcon, OpenInNewIcon } from '@blocksuite/icons';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { type AppSetting, useAppSetting } from '../../../../../atoms/settings';
|
||||
import { useAppSettingHelper } from '../../../../../hooks/affine/use-app-setting-helper';
|
||||
import { relatedLinks } from './config';
|
||||
import { communityItem, communityWrapper, link } from './style.css';
|
||||
|
||||
export const AboutAffine = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const [appSettings, setAppSettings] = useAppSetting();
|
||||
const changeSwitch = useCallback(
|
||||
(key: keyof AppSetting, checked: boolean) => {
|
||||
setAppSettings({ [key]: checked });
|
||||
},
|
||||
[setAppSettings]
|
||||
);
|
||||
const { appSettings, updateSettings } = useAppSettingHelper();
|
||||
return (
|
||||
<>
|
||||
<SettingHeader
|
||||
@@ -47,7 +40,7 @@ export const AboutAffine = () => {
|
||||
>
|
||||
<Switch
|
||||
checked={appSettings.autoCheckUpdate}
|
||||
onChange={checked => changeSwitch('autoCheckUpdate', checked)}
|
||||
onChange={checked => updateSettings('autoCheckUpdate', checked)}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
@@ -58,7 +51,7 @@ export const AboutAffine = () => {
|
||||
>
|
||||
<Switch
|
||||
checked={appSettings.autoCheckUpdate}
|
||||
onChange={checked => changeSwitch('autoCheckUpdate', checked)}
|
||||
onChange={checked => updateSettings('autoCheckUpdate', checked)}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
|
||||
@@ -5,8 +5,8 @@ import { useCallback } from 'react';
|
||||
import {
|
||||
dateFormatOptions,
|
||||
type DateFormats,
|
||||
useAppSetting,
|
||||
} from '../../../../../atoms/settings';
|
||||
import { useAppSettingHelper } from '../../../../../hooks/affine/use-app-setting-helper';
|
||||
|
||||
interface DateFormatMenuContentProps {
|
||||
currentOption: DateFormats;
|
||||
@@ -35,12 +35,12 @@ const DateFormatMenuContent = ({
|
||||
};
|
||||
|
||||
export const DateFormatSetting = () => {
|
||||
const [appearanceSettings, setAppSettings] = useAppSetting();
|
||||
const { appSettings, updateSettings } = useAppSettingHelper();
|
||||
const handleSelect = useCallback(
|
||||
(option: DateFormats) => {
|
||||
setAppSettings({ dateFormat: option });
|
||||
updateSettings('dateFormat', option);
|
||||
},
|
||||
[setAppSettings]
|
||||
[updateSettings]
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -48,12 +48,12 @@ export const DateFormatSetting = () => {
|
||||
items={
|
||||
<DateFormatMenuContent
|
||||
onSelect={handleSelect}
|
||||
currentOption={appearanceSettings.dateFormat}
|
||||
currentOption={appSettings.dateFormat}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<MenuTrigger data-testid="date-format-menu-trigger" block>
|
||||
{dayjs(new Date()).format(appearanceSettings.dateFormat)}
|
||||
{dayjs(new Date()).format(appSettings.dateFormat)}
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
@@ -9,9 +9,9 @@ import { useCallback } from 'react';
|
||||
import {
|
||||
type AppSetting,
|
||||
fontStyleOptions,
|
||||
useAppSetting,
|
||||
windowFrameStyleOptions,
|
||||
} from '../../../../../atoms/settings';
|
||||
import { useAppSettingHelper } from '../../../../../hooks/affine/use-app-setting-helper';
|
||||
import { LanguageMenu } from '../../../language-menu';
|
||||
import { DateFormatSetting } from './date-format-setting';
|
||||
import { settingWrapper } from './style.css';
|
||||
@@ -47,7 +47,7 @@ export const ThemeSettings = () => {
|
||||
|
||||
const FontFamilySettings = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const [appSettings, setAppSettings] = useAppSetting();
|
||||
const { appSettings, updateSettings } = useAppSettingHelper();
|
||||
return (
|
||||
<RadioButtonGroup
|
||||
width={250}
|
||||
@@ -55,9 +55,9 @@ const FontFamilySettings = () => {
|
||||
value={appSettings.fontStyle}
|
||||
onValueChange={useCallback(
|
||||
(key: AppSetting['fontStyle']) => {
|
||||
setAppSettings({ fontStyle: key });
|
||||
updateSettings('fontStyle', key);
|
||||
},
|
||||
[setAppSettings]
|
||||
[updateSettings]
|
||||
)}
|
||||
>
|
||||
{fontStyleOptions.map(({ key, value }) => {
|
||||
@@ -95,14 +95,8 @@ const FontFamilySettings = () => {
|
||||
export const AppearanceSettings = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const [appSettings, setAppSettings] = useAppSetting();
|
||||
const { appSettings, updateSettings } = useAppSettingHelper();
|
||||
|
||||
const changeSwitch = useCallback(
|
||||
(key: keyof AppSetting, checked: boolean) => {
|
||||
setAppSettings({ [key]: checked });
|
||||
},
|
||||
[setAppSettings]
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<SettingHeader
|
||||
@@ -139,7 +133,7 @@ export const AppearanceSettings = () => {
|
||||
>
|
||||
<Switch
|
||||
checked={appSettings.clientBorder}
|
||||
onChange={checked => changeSwitch('clientBorder', checked)}
|
||||
onChange={checked => updateSettings('clientBorder', checked)}
|
||||
/>
|
||||
</SettingRow>
|
||||
) : null}
|
||||
@@ -151,7 +145,7 @@ export const AppearanceSettings = () => {
|
||||
<Switch
|
||||
data-testid="full-width-layout-trigger"
|
||||
checked={appSettings.fullWidthLayout}
|
||||
onChange={checked => changeSwitch('fullWidthLayout', checked)}
|
||||
onChange={checked => updateSettings('fullWidthLayout', checked)}
|
||||
/>
|
||||
</SettingRow>
|
||||
{runtimeConfig.enableNewSettingUnstableApi && environment.isDesktop ? (
|
||||
@@ -164,7 +158,7 @@ export const AppearanceSettings = () => {
|
||||
width={250}
|
||||
defaultValue={appSettings.windowFrameStyle}
|
||||
onValueChange={(value: AppSetting['windowFrameStyle']) => {
|
||||
setAppSettings({ windowFrameStyle: value });
|
||||
updateSettings('windowFrameStyle', value);
|
||||
}}
|
||||
>
|
||||
{windowFrameStyleOptions.map(option => {
|
||||
@@ -194,7 +188,7 @@ export const AppearanceSettings = () => {
|
||||
>
|
||||
<Switch
|
||||
checked={appSettings.startWeekOnMonday}
|
||||
onChange={checked => changeSwitch('startWeekOnMonday', checked)}
|
||||
onChange={checked => updateSettings('startWeekOnMonday', checked)}
|
||||
/>
|
||||
</SettingRow>
|
||||
</SettingWrapper>
|
||||
@@ -213,7 +207,7 @@ export const AppearanceSettings = () => {
|
||||
<Switch
|
||||
checked={appSettings.enableNoisyBackground}
|
||||
onChange={checked =>
|
||||
changeSwitch('enableNoisyBackground', checked)
|
||||
updateSettings('enableNoisyBackground', checked)
|
||||
}
|
||||
/>
|
||||
</SettingRow>
|
||||
@@ -227,7 +221,7 @@ export const AppearanceSettings = () => {
|
||||
<Switch
|
||||
checked={appSettings.enableBlurBackground}
|
||||
onChange={checked =>
|
||||
changeSwitch('enableBlurBackground', checked)
|
||||
updateSettings('enableBlurBackground', checked)
|
||||
}
|
||||
/>
|
||||
</SettingRow>
|
||||
|
||||
@@ -29,7 +29,8 @@ import {
|
||||
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
|
||||
|
||||
import { pageSettingFamily } from '../atoms';
|
||||
import { fontStyleOptions, useAppSetting } from '../atoms/settings';
|
||||
import { fontStyleOptions } from '../atoms/settings';
|
||||
import { useAppSettingHelper } from '../hooks/affine/use-app-setting-helper';
|
||||
import { BlockSuiteEditor as Editor } from './blocksuite/block-suite-editor';
|
||||
import { Bookmark } from './bookmark';
|
||||
import * as styles from './page-detail-editor.css';
|
||||
@@ -68,7 +69,7 @@ const EditorWrapper = memo(function EditorWrapper({
|
||||
const currentMode = pageSetting?.mode ?? 'page';
|
||||
|
||||
const setBlockHub = useSetAtom(rootBlockHubAtom);
|
||||
const [appSettings] = useAppSetting();
|
||||
const { appSettings } = useAppSettingHelper();
|
||||
|
||||
assertExists(meta);
|
||||
const value = useMemo(() => {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { commandScore } from '@affine/cmdk';
|
||||
import { useCollectionManager } from '@affine/component/page-list';
|
||||
import type { Collection } from '@affine/env/filter';
|
||||
import { Trans } from '@affine/i18n';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { EdgelessIcon, PageIcon, ViewLayersIcon } from '@blocksuite/icons';
|
||||
import type { Page, PageMeta } from '@blocksuite/store';
|
||||
@@ -150,19 +149,28 @@ export const pageToCommand = (
|
||||
page: PageMeta,
|
||||
store: ReturnType<typeof getCurrentStore>,
|
||||
navigationHelper: ReturnType<typeof useNavigateHelper>,
|
||||
t: ReturnType<typeof useAFFiNEI18N>
|
||||
t: ReturnType<typeof useAFFiNEI18N>,
|
||||
label?: {
|
||||
title: string;
|
||||
subTitle?: string;
|
||||
}
|
||||
): CMDKCommand => {
|
||||
const pageMode = store.get(pageSettingsAtom)?.[page.id]?.mode;
|
||||
const currentWorkspaceId = store.get(currentWorkspaceIdAtom);
|
||||
const label = page.title || t['Untitled']();
|
||||
|
||||
const title = page.title || t['Untitled']();
|
||||
const commandLabel = label || {
|
||||
title: title,
|
||||
};
|
||||
|
||||
return {
|
||||
id: page.id,
|
||||
label: label,
|
||||
label: commandLabel,
|
||||
// hack: when comparing, the part between >>> and <<< will be ignored
|
||||
// adding this patch so that CMDK will not complain about duplicated commands
|
||||
value:
|
||||
label + valueWrapperStart + page.id + '.' + category + valueWrapperEnd,
|
||||
originalValue: label,
|
||||
title + valueWrapperStart + page.id + '.' + category + valueWrapperEnd,
|
||||
originalValue: title,
|
||||
category: category,
|
||||
run: () => {
|
||||
if (!currentWorkspaceId) {
|
||||
@@ -179,8 +187,6 @@ export const pageToCommand = (
|
||||
const contentMatchedMagicString = '__$$content_matched$$__';
|
||||
|
||||
export const usePageCommands = () => {
|
||||
// todo: considering collections for searching pages
|
||||
// const { savedCollections } = useCollectionManager(currentCollectionsAtom);
|
||||
const recentPages = useRecentPages();
|
||||
const pages = useWorkspacePages();
|
||||
const store = getCurrentStore();
|
||||
@@ -203,11 +209,11 @@ export const usePageCommands = () => {
|
||||
workspace.blockSuiteWorkspace.search({ query }).values()
|
||||
) as unknown as { space: string; content: string }[];
|
||||
|
||||
const pageIds = searchResults.map(id => {
|
||||
if (id.space.startsWith('space:')) {
|
||||
return id.space.slice(6);
|
||||
const pageIds = searchResults.map(result => {
|
||||
if (result.space.startsWith('space:')) {
|
||||
return result.space.slice(6);
|
||||
} else {
|
||||
return id.space;
|
||||
return result.space;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -215,12 +221,21 @@ export const usePageCommands = () => {
|
||||
const pageMode = store.get(pageSettingsAtom)?.[page.id]?.mode;
|
||||
const category =
|
||||
pageMode === 'edgeless' ? 'affine:edgeless' : 'affine:pages';
|
||||
|
||||
const label = {
|
||||
title: page.title || t['Untitled'](), // Used to ensure that a title exists
|
||||
subTitle:
|
||||
searchResults.find(result => result.space === page.id)?.content ||
|
||||
'',
|
||||
};
|
||||
|
||||
const command = pageToCommand(
|
||||
category,
|
||||
page,
|
||||
store,
|
||||
navigationHelper,
|
||||
t
|
||||
t,
|
||||
label
|
||||
);
|
||||
|
||||
if (pageIds.includes(page.id)) {
|
||||
@@ -235,14 +250,7 @@ export const usePageCommands = () => {
|
||||
if (results.every(command => command.originalValue !== query)) {
|
||||
results.push({
|
||||
id: 'affine:pages:create-page',
|
||||
label: (
|
||||
<Trans
|
||||
i18nKey="com.affine.cmdk.affine.create-new-page-as"
|
||||
values={{ query }}
|
||||
>
|
||||
Create New Page as: <strong>query</strong>
|
||||
</Trans>
|
||||
),
|
||||
label: `${t['com.affine.cmdk.affine.create-new-page-as']()} ${query}`,
|
||||
value: 'affine::create-page' + query, // hack to make the page always showing in the search result
|
||||
category: 'affine:creation',
|
||||
run: async () => {
|
||||
@@ -255,14 +263,9 @@ export const usePageCommands = () => {
|
||||
|
||||
results.push({
|
||||
id: 'affine:pages:create-edgeless',
|
||||
label: (
|
||||
<Trans
|
||||
values={{ query }}
|
||||
i18nKey="com.affine.cmdk.affine.create-new-edgeless-as"
|
||||
>
|
||||
Create New Edgeless as: <strong>query</strong>
|
||||
</Trans>
|
||||
),
|
||||
label: `${t[
|
||||
'com.affine.cmdk.affine.create-new-edgeless-as'
|
||||
]()} ${query}`,
|
||||
value: 'affine::create-edgeless' + query, // hack to make the page always showing in the search result
|
||||
category: 'affine:creation',
|
||||
run: async () => {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
export const highlightContainer = style({
|
||||
display: 'flex',
|
||||
flexWrap: 'nowrap',
|
||||
});
|
||||
|
||||
export const highlightText = style({
|
||||
whiteSpace: 'pre',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
});
|
||||
|
||||
export const highlightKeyword = style({
|
||||
color: 'var(--affine-primary-color)',
|
||||
whiteSpace: 'pre',
|
||||
overflow: 'visible',
|
||||
flexShrink: 0,
|
||||
});
|
||||
|
||||
export const labelTitle = style({
|
||||
fontSize: 'var(--affine-font-base)',
|
||||
lineHeight: '24px',
|
||||
fontWeight: 400,
|
||||
textAlign: 'justify',
|
||||
});
|
||||
|
||||
export const labelContent = style({
|
||||
fontSize: 'var(--affine-font-xs)',
|
||||
lineHeight: '20px',
|
||||
fontWeight: 400,
|
||||
textAlign: 'justify',
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
import { escapeRegExp } from 'lodash-es';
|
||||
import { memo } from 'react';
|
||||
|
||||
import {
|
||||
highlightContainer,
|
||||
highlightKeyword,
|
||||
highlightText,
|
||||
labelContent,
|
||||
labelTitle,
|
||||
} from './highlight.css';
|
||||
|
||||
type SearchResultLabel = {
|
||||
title: string;
|
||||
subTitle?: string;
|
||||
};
|
||||
|
||||
type HighlightProps = {
|
||||
text: string;
|
||||
highlight: string;
|
||||
};
|
||||
|
||||
type HighlightLabelProps = {
|
||||
label: SearchResultLabel;
|
||||
highlight: string;
|
||||
};
|
||||
|
||||
export const Highlight = memo(function Highlight({
|
||||
text = '',
|
||||
highlight = '',
|
||||
}: HighlightProps) {
|
||||
//Regex is used to ignore case
|
||||
const regex = highlight.trim()
|
||||
? new RegExp(`(${escapeRegExp(highlight)})`, 'ig')
|
||||
: null;
|
||||
|
||||
if (!regex) {
|
||||
return <span>{text}</span>;
|
||||
}
|
||||
const parts = text.split(regex);
|
||||
|
||||
return (
|
||||
<div className={highlightContainer}>
|
||||
{parts.map((part, i) => {
|
||||
if (regex.test(part)) {
|
||||
return (
|
||||
<span key={i} className={highlightKeyword}>
|
||||
{part}
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<span key={i} className={highlightText}>
|
||||
{part}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export const HighlightLabel = memo(function HighlightLabel({
|
||||
label,
|
||||
highlight,
|
||||
}: HighlightLabelProps) {
|
||||
return (
|
||||
<div>
|
||||
<div className={labelTitle}>
|
||||
<Highlight text={label.title} highlight={highlight} />
|
||||
</div>
|
||||
{label.subTitle ? (
|
||||
<div className={labelContent}>
|
||||
<Highlight text={label.subTitle} highlight={highlight} />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
@@ -76,6 +76,8 @@ export const timestamp = style({
|
||||
display: 'flex',
|
||||
fontSize: 'var(--affine-font-xs)',
|
||||
color: 'var(--affine-text-secondary-color)',
|
||||
minWidth: 120,
|
||||
flexDirection: 'row-reverse',
|
||||
});
|
||||
|
||||
export const keybinding = style({
|
||||
@@ -153,8 +155,8 @@ globalStyle(`${root} [cmdk-list]:hover::-webkit-scrollbar-thumb:hover`, {
|
||||
|
||||
globalStyle(`${root} [cmdk-item]`, {
|
||||
display: 'flex',
|
||||
height: 44,
|
||||
padding: '0 12px',
|
||||
minHeight: 44,
|
||||
padding: '6px 12px',
|
||||
alignItems: 'center',
|
||||
cursor: 'default',
|
||||
borderRadius: 4,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import type { PageMeta } from '@blocksuite/store';
|
||||
import type { CommandCategory } from '@toeverything/infra/command';
|
||||
import clsx from 'clsx';
|
||||
import { useAtom, useSetAtom } from 'jotai';
|
||||
import { useAtom } from 'jotai';
|
||||
import { Suspense, useLayoutEffect, useMemo, useState } from 'react';
|
||||
|
||||
import {
|
||||
@@ -13,8 +13,10 @@ import {
|
||||
customCommandFilter,
|
||||
useCMDKCommandGroups,
|
||||
} from './data';
|
||||
import { HighlightLabel } from './highlight';
|
||||
import * as styles from './main.css';
|
||||
import { CMDKModal, type CMDKModalProps } from './modal';
|
||||
import { NotFoundGroup } from './not-found';
|
||||
import type { CMDKCommand } from './types';
|
||||
|
||||
type NoParametersKeys<T> = {
|
||||
@@ -52,10 +54,16 @@ const QuickSearchGroup = ({
|
||||
}) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const i18nkey = categoryToI18nKey[category];
|
||||
const setQuery = useSetAtom(cmdkQueryAtom);
|
||||
const [query, setQuery] = useAtom(cmdkQueryAtom);
|
||||
return (
|
||||
<Command.Group key={category} heading={t[i18nkey]()}>
|
||||
{commands.map(command => {
|
||||
const label =
|
||||
typeof command.label === 'string'
|
||||
? {
|
||||
title: command.label,
|
||||
}
|
||||
: command.label;
|
||||
return (
|
||||
<Command.Item
|
||||
key={command.id}
|
||||
@@ -78,7 +86,7 @@ const QuickSearchGroup = ({
|
||||
command.originalValue ? command.originalValue : undefined
|
||||
}
|
||||
>
|
||||
{command.label}
|
||||
<HighlightLabel highlight={query} label={label} />
|
||||
</div>
|
||||
{command.timestamp ? (
|
||||
<div className={styles.timestamp}>
|
||||
@@ -197,6 +205,7 @@ export const CMDKContainer = ({
|
||||
<Command.List data-opening={opening ? true : undefined}>
|
||||
{children}
|
||||
</Command.List>
|
||||
<NotFoundGroup />
|
||||
</Command>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
export const notFoundContainer = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: '0 8px',
|
||||
marginBottom: 8,
|
||||
});
|
||||
|
||||
export const notFoundItem = style({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
padding: '0 12px',
|
||||
gap: 16,
|
||||
});
|
||||
|
||||
export const notFoundIcon = style({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
fontSize: 20,
|
||||
color: 'var(--affine-icon-secondary)',
|
||||
padding: '12px 0',
|
||||
});
|
||||
|
||||
export const notFoundTitle = style({
|
||||
fontSize: 'var(--affine-font-xs)',
|
||||
color: 'var(--affine-text-secondary-color)',
|
||||
fontWeight: '600',
|
||||
lineHeight: '20px',
|
||||
textAlign: 'justify',
|
||||
padding: '8px',
|
||||
});
|
||||
|
||||
export const notFoundText = style({
|
||||
fontSize: 'var(--affine-font-sm)',
|
||||
color: 'var(--affine-text-primary-color)',
|
||||
lineHeight: '22px',
|
||||
fontWeight: '400',
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import { useCommandState } from '@affine/cmdk';
|
||||
import { SearchIcon } from '@blocksuite/icons';
|
||||
import { useAtomValue } from 'jotai';
|
||||
|
||||
import { cmdkQueryAtom } from './data';
|
||||
import * as styles from './not-found.css';
|
||||
|
||||
export const NotFoundGroup = () => {
|
||||
const query = useAtomValue(cmdkQueryAtom);
|
||||
// hack: we know that the filtered count is 2 when there is no result (create page & edgeless)
|
||||
const renderNoResult =
|
||||
useCommandState(state => state.filtered.count === 2) || false;
|
||||
|
||||
if (!renderNoResult) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div className={styles.notFoundContainer}>
|
||||
<div
|
||||
className={styles.notFoundTitle}
|
||||
data-testid="cmdk-search-not-found"
|
||||
>{`Search for "${query}"`}</div>
|
||||
<div className={styles.notFoundItem}>
|
||||
<div className={styles.notFoundIcon}>
|
||||
<SearchIcon />
|
||||
</div>
|
||||
<div className={styles.notFoundText}>No results found</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -11,7 +11,12 @@ export interface CommandContext {
|
||||
// we can use a single render function to render all different commands
|
||||
export interface CMDKCommand {
|
||||
id: string;
|
||||
label: string | React.ReactNode;
|
||||
label:
|
||||
| string
|
||||
| {
|
||||
title: string;
|
||||
subTitle?: string;
|
||||
};
|
||||
icon?: React.ReactNode;
|
||||
category: CommandCategory;
|
||||
keyBinding?: string | { binding: string };
|
||||
|
||||
@@ -10,7 +10,7 @@ import { currentPageIdAtom } from '@toeverything/infra/atom';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { useAppSetting } from '../../../atoms/settings';
|
||||
import { useAppSettingHelper } from '../../../hooks/affine/use-app-setting-helper';
|
||||
import { useBlockSuiteMetaHelper } from '../../../hooks/affine/use-block-suite-meta-helper';
|
||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||
import { useNavigateHelper } from '../../../hooks/use-navigate-helper';
|
||||
@@ -29,7 +29,7 @@ export const TrashButtonGroup = () => {
|
||||
);
|
||||
assertExists(pageMeta);
|
||||
const t = useAFFiNEI18N();
|
||||
const [appSettings] = useAppSetting();
|
||||
const { appSettings } = useAppSettingHelper();
|
||||
const { jumpToSubPath } = useNavigateHelper();
|
||||
const { restoreFromTrash } = useBlockSuiteMetaHelper(blockSuiteWorkspace);
|
||||
const restoreRef = useRef(null);
|
||||
|
||||
@@ -26,7 +26,7 @@ import { forwardRef, useCallback, useEffect, useMemo } from 'react';
|
||||
|
||||
import { openWorkspaceListModalAtom } from '../../atoms';
|
||||
import { useHistoryAtom } from '../../atoms/history';
|
||||
import { useAppSetting } from '../../atoms/settings';
|
||||
import { useAppSettingHelper } from '../../hooks/affine/use-app-setting-helper';
|
||||
import { useGeneralShortcuts } from '../../hooks/affine/use-shortcuts';
|
||||
import { useTrashModalHelper } from '../../hooks/affine/use-trash-modal-helper';
|
||||
import { useRegisterBlocksuiteEditorCommands } from '../../hooks/use-shortcut-commands';
|
||||
@@ -100,7 +100,7 @@ export const RootAppSidebar = ({
|
||||
onOpenSettingModal,
|
||||
}: RootAppSidebarProps): ReactElement => {
|
||||
const currentWorkspaceId = currentWorkspace.id;
|
||||
const [appSettings] = useAppSetting();
|
||||
const { appSettings } = useAppSettingHelper();
|
||||
const { backToAll } = useCollectionManager(currentCollectionsAtom);
|
||||
const blockSuiteWorkspace = currentWorkspace.blockSuiteWorkspace;
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { useAtom } from 'jotai';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { type AppSetting, appSettingAtom } from '../../atoms/settings';
|
||||
|
||||
export function useAppSettingHelper() {
|
||||
const [appSettings, setAppSettings] = useAtom(appSettingAtom);
|
||||
|
||||
const updateSettings = useCallback(
|
||||
<K extends keyof AppSetting>(key: K, value: AppSetting[K]) => {
|
||||
setAppSettings(prevSettings => ({ ...prevSettings, [key]: value }));
|
||||
},
|
||||
[setAppSettings]
|
||||
);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
appSettings,
|
||||
updateSettings,
|
||||
}),
|
||||
[appSettings, updateSettings]
|
||||
);
|
||||
}
|
||||
@@ -16,7 +16,7 @@ export function useLanguageHelper() {
|
||||
})),
|
||||
[]
|
||||
);
|
||||
const onSelect = useCallback(
|
||||
const onLanguageChange = useCallback(
|
||||
(event: string) => {
|
||||
i18n.changeLanguage(event);
|
||||
},
|
||||
@@ -27,8 +27,8 @@ export function useLanguageHelper() {
|
||||
() => ({
|
||||
currentLanguage,
|
||||
languagesList,
|
||||
onSelect,
|
||||
onLanguageChange,
|
||||
}),
|
||||
[currentLanguage, languagesList, onSelect]
|
||||
[currentLanguage, languagesList, onLanguageChange]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { appSidebarOpenAtom } from '@affine/component/app-sidebar';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
export function useSwitchSidebarStatus() {
|
||||
const [isOpened, setOpened] = useAtom(appSidebarOpenAtom);
|
||||
|
||||
const onOpenChange = useCallback(() => {
|
||||
setOpened(open => !open);
|
||||
}, [setOpened]);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
onOpenChange,
|
||||
isOpened,
|
||||
}),
|
||||
[isOpened, onOpenChange]
|
||||
);
|
||||
}
|
||||
@@ -52,7 +52,7 @@ export function useRegisterWorkspaceCommands() {
|
||||
languageHelper,
|
||||
})
|
||||
);
|
||||
unsubs.push(registerAffineLayoutCommands({ store, t }));
|
||||
unsubs.push(registerAffineLayoutCommands({ t, store }));
|
||||
unsubs.push(
|
||||
registerAffineCreationCommands({
|
||||
store,
|
||||
|
||||
@@ -38,7 +38,6 @@ import { Map as YMap } from 'yjs';
|
||||
|
||||
import { openQuickSearchModalAtom, openSettingModalAtom } from '../atoms';
|
||||
import { mainContainerAtom } from '../atoms/element';
|
||||
import { useAppSetting } from '../atoms/settings';
|
||||
import { AdapterProviderWrapper } from '../components/adapter-worksapce-wrapper';
|
||||
import { AppContainer } from '../components/affine/app-container';
|
||||
import { usePageHelper } from '../components/blocksuite/block-suite-page-list/utils';
|
||||
@@ -50,6 +49,7 @@ import {
|
||||
DROPPABLE_SIDEBAR_TRASH,
|
||||
RootAppSidebar,
|
||||
} from '../components/root-app-sidebar';
|
||||
import { useAppSettingHelper } from '../hooks/affine/use-app-setting-helper';
|
||||
import { useBlockSuiteMetaHelper } from '../hooks/affine/use-block-suite-meta-helper';
|
||||
import { useCurrentWorkspace } from '../hooks/current/use-current-workspace';
|
||||
import { useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||
@@ -230,7 +230,7 @@ export const WorkspaceLayoutInner = ({
|
||||
[moveToTrash, t]
|
||||
);
|
||||
|
||||
const [appSetting] = useAppSetting();
|
||||
const { appSettings } = useAppSettingHelper();
|
||||
const location = useLocation();
|
||||
const { pageId } = useParams();
|
||||
const pageMeta = useBlockSuitePageMeta(
|
||||
@@ -269,7 +269,7 @@ export const WorkspaceLayoutInner = ({
|
||||
<Suspense fallback={<MainContainer ref={setMainContainer} />}>
|
||||
<MainContainer
|
||||
ref={setMainContainer}
|
||||
padding={appSetting.clientBorder}
|
||||
padding={appSettings.clientBorder}
|
||||
inTrashPage={inTrashPage}
|
||||
>
|
||||
{incompatible ? <MigrationFallback /> : children}
|
||||
|
||||
Reference in New Issue
Block a user