refactor(core): set edgeless theme on doc created (#8670)

This commit is contained in:
EYHN
2024-11-04 04:38:03 +00:00
parent a4f27ef391
commit 12e3cf1d07
27 changed files with 107 additions and 126 deletions

View File

@@ -1,5 +1,5 @@
import { AffineContext } from '@affine/component/context';
import { AppFallback } from '@affine/core/components/affine/app-container';
import { AffineContext } from '@affine/core/components/context';
import { Telemetry } from '@affine/core/components/telemetry';
import { configureMobileModules } from '@affine/core/mobile/modules';
import { router } from '@affine/core/mobile/router';

View File

@@ -1,6 +1,6 @@
import { AffineContext } from '@affine/component/context';
import { GlobalLoading } from '@affine/component/global-loading';
import { AppFallback } from '@affine/core/components/affine/app-container';
import { AffineContext } from '@affine/core/components/context';
import { WindowsAppControls } from '@affine/core/components/pure/header/windows-app-controls';
import { Telemetry } from '@affine/core/components/telemetry';
import { router } from '@affine/core/desktop/router';

View File

@@ -1,6 +1,6 @@
import { ThemeProvider } from '@affine/component/theme-provider';
import { ShellAppFallback } from '@affine/core/components/affine/app-container';
import { useAppSettingHelper } from '@affine/core/components/hooks/affine/use-app-setting-helper';
import { ThemeProvider } from '@affine/core/components/theme-provider';
import { configureAppSidebarModule } from '@affine/core/modules/app-sidebar';
import {
AppTabsHeader,
@@ -9,9 +9,9 @@ import {
import { configureDesktopApiModule } from '@affine/core/modules/desktop-api';
import { configureI18nModule, I18nProvider } from '@affine/core/modules/i18n';
import { configureElectronStateStorageImpls } from '@affine/core/modules/storage';
import { configureAppThemeModule } from '@affine/core/modules/theme';
import { SplitViewFallback } from '@affine/core/modules/workbench/view/split-view/split-view';
import {
configureAppThemeModule,
configureGlobalStorageModule,
Framework,
FrameworkRoot,

View File

@@ -1,5 +1,5 @@
import { AffineContext } from '@affine/component/context';
import { AppFallback } from '@affine/core/components/affine/app-container';
import { AffineContext } from '@affine/core/components/context';
import { Telemetry } from '@affine/core/components/telemetry';
import { configureMobileModules } from '@affine/core/mobile/modules';
import { router } from '@affine/core/mobile/router';

View File

@@ -1,5 +1,5 @@
import { AffineContext } from '@affine/component/context';
import { AppFallback } from '@affine/core/components/affine/app-container';
import { AffineContext } from '@affine/core/components/context';
import { Telemetry } from '@affine/core/components/telemetry';
import { configureMobileModules } from '@affine/core/mobile/modules';
import { router } from '@affine/core/mobile/router';

View File

@@ -1,6 +1,6 @@
import { AffineContext } from '@affine/component/context';
import { GlobalLoading } from '@affine/component/global-loading';
import { AppFallback } from '@affine/core/components/affine/app-container';
import { AffineContext } from '@affine/core/components/context';
import { Telemetry } from '@affine/core/components/telemetry';
import { router } from '@affine/core/desktop/router';
import { configureCommonModules } from '@affine/core/modules';

View File

@@ -3,6 +3,7 @@ import {
AIPageRootBlockSpec,
} from '@affine/core/blocksuite/presets/ai';
import { EditorSettingService } from '@affine/core/modules/editor-setting';
import { AppThemeService } from '@affine/core/modules/theme';
import { mixpanel } from '@affine/track';
import {
ConfigExtension,
@@ -32,7 +33,6 @@ import {
} from '@blocksuite/affine-shared/utils';
import type { Container } from '@blocksuite/global/di';
import {
AppThemeService,
DocService,
DocsService,
type FrameworkProvider,

View File

@@ -2,26 +2,22 @@ import type { WeekDatePickerHandle } from '@affine/component';
import { WeekDatePicker } from '@affine/component';
import { useJournalRouteHelper } from '@affine/core/components/hooks/use-journal';
import { JournalService } from '@affine/core/modules/journal';
import type { Doc, DocCollection } from '@blocksuite/affine/store';
import type { Doc } from '@blocksuite/affine/store';
import { useLiveData, useService } from '@toeverything/infra';
import dayjs from 'dayjs';
import { useEffect, useRef, useState } from 'react';
export interface JournalWeekDatePickerProps {
docCollection: DocCollection;
page: Doc;
}
const weekStyle = { maxWidth: 800, width: '100%' };
export const JournalWeekDatePicker = ({
docCollection,
page,
}: JournalWeekDatePickerProps) => {
export const JournalWeekDatePicker = ({ page }: JournalWeekDatePickerProps) => {
const handleRef = useRef<WeekDatePickerHandle>(null);
const journalService = useService(JournalService);
const journalDateStr = useLiveData(journalService.journalDate$(page.id));
const journalDate = journalDateStr ? dayjs(journalDateStr) : null;
const { openJournal } = useJournalRouteHelper(docCollection);
const { openJournal } = useJournalRouteHelper();
const [date, setDate] = useState(
(journalDate ?? dayjs()).format('YYYY-MM-DD')
);

View File

@@ -1,18 +1,11 @@
import { Button } from '@affine/component';
import { useJournalRouteHelper } from '@affine/core/components/hooks/use-journal';
import { useI18n } from '@affine/i18n';
import type { DocCollection } from '@blocksuite/affine/store';
import { useCallback } from 'react';
export interface JournalTodayButtonProps {
docCollection: DocCollection;
}
export const JournalTodayButton = ({
docCollection,
}: JournalTodayButtonProps) => {
export const JournalTodayButton = () => {
const t = useI18n();
const journalHelper = useJournalRouteHelper(docCollection);
const journalHelper = useJournalRouteHelper();
const onToday = useCallback(() => {
journalHelper.openToday();

View File

@@ -5,11 +5,8 @@ import { WorkbenchService } from '@affine/core/modules/workbench';
import { type DocMode } from '@blocksuite/affine/blocks';
import type { DocCollection } from '@blocksuite/affine/store';
import { type DocProps, DocsService, useServices } from '@toeverything/infra';
import { useTheme } from 'next-themes';
import { useCallback, useMemo } from 'react';
import { getValueByDefaultTheme } from '../../hooks/use-journal';
export const usePageHelper = (docCollection: DocCollection) => {
const {
docsService,
@@ -25,7 +22,6 @@ export const usePageHelper = (docCollection: DocCollection) => {
const workbench = workbenchService.workbench;
const docRecordList = docsService.list;
const appSidebar = appSidebarService.sidebar;
const { resolvedTheme } = useTheme();
const createPageAndOpen = useCallback(
(mode?: DocMode, open?: boolean | 'new-tab') => {
@@ -35,14 +31,6 @@ export const usePageHelper = (docCollection: DocCollection) => {
};
const page = docsService.createDoc({ docProps });
const value = getValueByDefaultTheme(
editorSettingService.editorSetting.settings$.value.edgelessDefaultTheme,
resolvedTheme || 'light'
);
docRecordList
.doc$(page.id)
.value?.setProperty('edgelessColorTheme', value);
if (mode) {
docRecordList.doc$(page.id).value?.setPrimaryMode(mode);
}
@@ -58,7 +46,6 @@ export const usePageHelper = (docCollection: DocCollection) => {
docRecordList,
docsService,
editorSettingService.editorSetting,
resolvedTheme,
workbench,
]
);

View File

@@ -1,12 +1,11 @@
import { ConfirmModalProvider } from '@affine/component';
import { ProviderComposer } from '@affine/component/provider-composer';
import { ThemeProvider } from '@affine/component/theme-provider';
import { ThemeProvider } from '@affine/core/components/theme-provider';
import type { createStore } from 'jotai';
import { Provider } from 'jotai';
import type { PropsWithChildren } from 'react';
import { useMemo } from 'react';
import { ConfirmModalProvider } from '../../ui/modal';
export type AffineContextProps = PropsWithChildren<{
store?: ReturnType<typeof createStore>;
}>;

View File

@@ -1,9 +1,8 @@
import { EditorSettingService } from '@affine/core/modules/editor-setting';
import type { EdgelessDefaultTheme } from '@affine/core/modules/editor-setting/schema';
import { JournalService } from '@affine/core/modules/journal';
import { i18nTime } from '@affine/i18n';
import { track } from '@affine/track';
import { type DocCollection, Text } from '@blocksuite/affine/store';
import { Text } from '@blocksuite/affine/store';
import {
type DocProps,
DocsService,
@@ -12,29 +11,9 @@ import {
useServices,
} from '@toeverything/infra';
import dayjs from 'dayjs';
import { useTheme } from 'next-themes';
import { useCallback, useMemo } from 'react';
import { WorkbenchService } from '../../modules/workbench';
import { useDocCollectionHelper } from './use-block-suite-workspace-helper';
export const getValueByDefaultTheme = (
defaultTheme: EdgelessDefaultTheme,
currentAppTheme: string
) => {
switch (defaultTheme) {
case 'dark':
return 'dark';
case 'light':
return 'light';
case 'specified':
return currentAppTheme === 'dark' ? 'dark' : 'light';
case 'auto':
return 'system';
default:
return 'system';
}
};
type MaybeDate = Date | string | number;
export const JOURNAL_DATE_FORMAT = 'YYYY-MM-DD';
@@ -53,9 +32,7 @@ function toDayjs(j?: string | false) {
/**
* @deprecated use `JournalService` directly
*/
export const useJournalHelper = (docCollection: DocCollection) => {
const bsWorkspaceHelper = useDocCollectionHelper(docCollection);
const { resolvedTheme } = useTheme();
export const useJournalHelper = () => {
const { docsService, editorSettingService, journalService } = useServices({
DocsService,
EditorSettingService,
@@ -69,17 +46,11 @@ export const useJournalHelper = (docCollection: DocCollection) => {
(maybeDate: MaybeDate) => {
const day = dayjs(maybeDate);
const title = day.format(JOURNAL_DATE_FORMAT);
const page = bsWorkspaceHelper.createDoc();
const value = getValueByDefaultTheme(
editorSettingService.editorSetting.settings$.value.edgelessDefaultTheme,
resolvedTheme || 'light'
);
docsService.list
.doc$(page.id)
.value?.setProperty('edgelessColorTheme', value);
docsService.list.setPrimaryMode(page.id, 'page');
const docRecord = docsService.createDoc();
const { doc, release } = docsService.open(docRecord.id);
docsService.list.setPrimaryMode(docRecord.id, 'page');
// set created date to match the journal date
page.collection.setDocMeta(page.id, {
docRecord.setMeta({
createDate: dayjs()
.set('year', day.year())
.set('month', day.month())
@@ -91,17 +62,12 @@ export const useJournalHelper = (docCollection: DocCollection) => {
page: { title: new Text(title) },
note: editorSettingService.editorSetting.get('affine:note'),
};
initDocFromProps(page, docProps);
journalService.setJournalDate(page.id, title);
return page;
initDocFromProps(doc.blockSuiteDoc, docProps);
release();
journalService.setJournalDate(docRecord.id, title);
return docRecord;
},
[
bsWorkspaceHelper,
editorSettingService.editorSetting,
resolvedTheme,
docsService.list,
journalService,
]
[docsService, editorSettingService.editorSetting, journalService]
);
/**
@@ -138,8 +104,8 @@ export const useJournalHelper = (docCollection: DocCollection) => {
};
// split useJournalRouteHelper since it requires a <Route /> context, which may not work in lit
export const useJournalRouteHelper = (docCollection: DocCollection) => {
const { getJournalByDate } = useJournalHelper(docCollection);
export const useJournalRouteHelper = () => {
const { getJournalByDate } = useJournalHelper();
const workbench = useService(WorkbenchService).workbench;
/**
* open journal by date, create one if not exist

View File

@@ -149,9 +149,7 @@ export const RootAppSidebar = (): ReactElement => {
{t['com.affine.workspaceSubPath.all']()}
</span>
</MenuLinkItem>
<AppSidebarJournalButton
docCollection={currentWorkspace.docCollection}
/>
<AppSidebarJournalButton />
<MenuItem
data-testid="slider-bar-workspace-setting-button"
icon={<SettingsIcon />}

View File

@@ -8,23 +8,16 @@ import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
import { WorkbenchService } from '@affine/core/modules/workbench';
import { isNewTabTrigger } from '@affine/core/utils';
import { useI18n } from '@affine/i18n';
import type { DocCollection } from '@blocksuite/affine/store';
import { TodayIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra';
import { type MouseEvent } from 'react';
interface AppSidebarJournalButtonProps {
docCollection: DocCollection;
}
export const AppSidebarJournalButton = ({
docCollection,
}: AppSidebarJournalButtonProps) => {
export const AppSidebarJournalButton = () => {
const t = useI18n();
const docDisplayMetaService = useService(DocDisplayMetaService);
const workbench = useService(WorkbenchService).workbench;
const location = useLiveData(workbench.location$);
const { openToday } = useJournalRouteHelper(docCollection);
const { openToday } = useJournalRouteHelper();
const maybeDocId = location.pathname.split('/')[1];
const { isJournal } = useJournalInfoHelper(maybeDocId);

View File

@@ -1,11 +1,12 @@
import { AppThemeService, useService } from '@toeverything/infra';
import { AppThemeService } from '@affine/core/modules/theme';
import { useService } from '@toeverything/infra';
import { ThemeProvider as NextThemeProvider, useTheme } from 'next-themes';
import type { PropsWithChildren } from 'react';
import { useEffect } from 'react';
const themes = ['dark', 'light'];
export function ThemeObserver() {
function ThemeObserver() {
const { resolvedTheme } = useTheme();
const service = useService(AppThemeService);

View File

@@ -67,14 +67,9 @@ export function JournalPageHeader({ page, workspace }: PageHeaderProps) {
<ViewIcon icon="journal" />
<EditorModeSwitch />
<div className={styles.journalWeekPicker}>
<JournalWeekDatePicker
docCollection={workspace.docCollection}
page={page}
/>
<JournalWeekDatePicker page={page} />
</div>
{hideToday ? null : (
<JournalTodayButton docCollection={workspace.docCollection} />
)}
{hideToday ? null : <JournalTodayButton />}
<HeaderDivider />
<PageHeaderMenuButton
isJournal

View File

@@ -21,7 +21,6 @@ import {
DocsService,
useLiveData,
useService,
WorkspaceService,
} from '@toeverything/infra';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import clsx from 'clsx';
@@ -100,12 +99,11 @@ const mobile = environment.isMobile;
export const EditorJournalPanel = () => {
const t = useI18n();
const doc = useService(DocService).doc;
const workspace = useService(WorkspaceService).workspace;
const journalService = useService(JournalService);
const journalDateStr = useLiveData(journalService.journalDate$(doc.id));
const journalDate = journalDateStr ? dayjs(journalDateStr) : null;
const isJournal = !!journalDate;
const { openJournal } = useJournalRouteHelper(workspace.docCollection);
const { openJournal } = useJournalRouteHelper();
const onDateSelect = useCallback(
(date: string) => {

View File

@@ -26,6 +26,7 @@ import { configureShareSettingModule } from './share-setting';
import { configureSystemFontFamilyModule } from './system-font-family';
import { configureTagModule } from './tag';
import { configureTelemetryModule } from './telemetry';
import { configureAppThemeModule } from './theme';
import { configureThemeEditorModule } from './theme-editor';
import { configureUrlModule } from './url';
import { configureUserspaceModule } from './userspace';
@@ -61,4 +62,5 @@ export function configureCommonModules(framework: Framework) {
configureAppSidebarModule(framework);
configureJournalModule(framework);
configureUrlModule(framework);
configureAppThemeModule(framework);
}

View File

@@ -0,0 +1,5 @@
import { Entity, LiveData } from '@toeverything/infra';
export class AppTheme extends Entity {
theme$ = new LiveData<string | undefined>(undefined);
}

View File

@@ -0,0 +1,16 @@
export { AppThemeService } from './services/theme';
import { type Framework, WorkspaceScope } from '@toeverything/infra';
import { EditorSettingService } from '../editor-setting';
import { AppTheme } from './entities/theme';
import { EdgelessThemeService } from './services/edgeless-theme';
import { AppThemeService } from './services/theme';
export function configureAppThemeModule(framework: Framework) {
framework
.service(AppThemeService)
.entity(AppTheme)
.scope(WorkspaceScope)
.service(EdgelessThemeService, [AppThemeService, EditorSettingService]);
}

View File

@@ -0,0 +1,42 @@
import type { DocRecord } from '@toeverything/infra';
import { DocCreated, OnEvent, Service } from '@toeverything/infra';
import type { EditorSettingService } from '../../editor-setting';
import type { EdgelessDefaultTheme } from '../../editor-setting/schema';
import type { AppThemeService } from './theme';
const getValueByDefaultTheme = (
defaultTheme: EdgelessDefaultTheme,
currentAppTheme: string
) => {
switch (defaultTheme) {
case 'dark':
return 'dark';
case 'light':
return 'light';
case 'specified':
return currentAppTheme === 'dark' ? 'dark' : 'light';
case 'auto':
return 'system';
default:
return 'system';
}
};
@OnEvent(DocCreated, i => i.onDocCreated)
export class EdgelessThemeService extends Service {
constructor(
private readonly appThemeService: AppThemeService,
private readonly editorSettingService: EditorSettingService
) {
super();
}
onDocCreated(docRecord: DocRecord) {
const value = getValueByDefaultTheme(
this.editorSettingService.editorSetting.get('edgelessDefaultTheme'),
this.appThemeService.appTheme.theme$.value ?? 'light'
);
docRecord.setProperty('edgelessColorTheme', value);
}
}

View File

@@ -0,0 +1,7 @@
import { Service } from '@toeverything/infra';
import { AppTheme } from '../entities/theme';
export class AppThemeService extends Service {
appTheme = this.framework.createEntity(AppTheme);
}