feat(core): add split view to experimental features settings (#6093)

This commit is contained in:
Peng Xiao
2024-03-14 05:13:04 +00:00
parent 05583dbe98
commit dd9a253772
12 changed files with 157 additions and 36 deletions

View File

@@ -5,11 +5,10 @@ import {
import { Avatar } from '@affine/component/ui/avatar';
import { Tooltip } from '@affine/component/ui/tooltip';
import { useIsWorkspaceOwner } from '@affine/core/hooks/affine/use-is-workspace-owner';
import { useIsEarlyAccess } from '@affine/core/hooks/affine/use-user-features';
import { useWorkspaceBlobObjectUrl } from '@affine/core/hooks/use-workspace-blob';
import { useWorkspaceAvailableFeatures } from '@affine/core/hooks/use-workspace-features';
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { Logo1Icon } from '@blocksuite/icons';
import {
@@ -253,7 +252,7 @@ const WorkspaceListItem = ({
const isCurrent = currentWorkspace.id === meta.id;
const t = useAFFiNEI18N();
const isOwner = useIsWorkspaceOwner(meta);
const availableFeatures = useWorkspaceAvailableFeatures(meta);
const isEarlyAccess = useIsEarlyAccess();
const onClickPreference = useCallback(() => {
onClick('preference');
@@ -263,11 +262,7 @@ const WorkspaceListItem = ({
return subTabConfigs
.filter(({ key }) => {
if (key === 'experimental-features') {
return (
isOwner &&
meta.flavour === WorkspaceFlavour.AFFINE_CLOUD &&
availableFeatures.length > 0
);
return isOwner && isEarlyAccess;
}
return true;
})
@@ -287,14 +282,7 @@ const WorkspaceListItem = ({
</div>
);
});
}, [
activeSubTab,
availableFeatures.length,
isOwner,
meta.flavour,
onClick,
t,
]);
}, [activeSubTab, isEarlyAccess, isOwner, onClick, t]);
return (
<>

View File

@@ -1,5 +1,6 @@
import { Button, Checkbox, Loading, Switch } from '@affine/component';
import { SettingHeader } from '@affine/component/setting-components';
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import {
useSetWorkspaceFeature,
@@ -79,6 +80,29 @@ interface ExperimentalFeaturesItemProps {
}
const ExperimentalFeaturesItem = ({
title,
isMutating,
checked,
onChange,
}: {
title: React.ReactNode;
isMutating?: boolean;
checked: boolean;
onChange: (checked: boolean) => void;
}) => {
return (
<div className={styles.switchRow}>
{title}
<Switch
checked={checked}
onChange={onChange}
className={isMutating ? styles.switchDisabled : ''}
/>
</div>
);
};
const WorkspaceFeaturesSettingItem = ({
feature,
title,
workspaceMetadata,
@@ -96,14 +120,51 @@ const ExperimentalFeaturesItem = ({
);
return (
<div className={styles.switchRow}>
{title}
<Switch
checked={localEnabled}
onChange={onChange}
className={isMutating ? styles.switchDisabled : ''}
/>
</div>
<ExperimentalFeaturesItem
title={title}
isMutating={isMutating}
checked={localEnabled}
onChange={onChange}
/>
);
};
const CopilotSettingRow = ({
workspaceMetadata,
}: {
workspaceMetadata: WorkspaceMetadata;
}) => {
const features = useWorkspaceAvailableFeatures(workspaceMetadata);
return features.includes(FeatureType.Copilot) ? (
<WorkspaceFeaturesSettingItem
title="AI POC"
workspaceMetadata={workspaceMetadata}
feature={FeatureType.Copilot}
/>
) : null;
};
const SplitViewSettingRow = () => {
const { appSettings, updateSettings } = useAppSettingHelper();
const onToggle = useCallback(
(checked: boolean) => {
updateSettings('enableMultiView', checked);
},
[updateSettings]
);
if (!environment.isDesktop) {
return null; // only enable on desktop
}
return (
<ExperimentalFeaturesItem
title="Split View"
checked={appSettings.enableMultiView}
onChange={onToggle}
/>
);
};
@@ -113,7 +174,6 @@ const ExperimentalFeaturesMain = ({
workspaceMetadata: WorkspaceMetadata;
}) => {
const t = useAFFiNEI18N();
const features = useWorkspaceAvailableFeatures(workspaceMetadata);
return (
<>
@@ -122,14 +182,8 @@ const ExperimentalFeaturesMain = ({
'com.affine.settings.workspace.experimental-features.header.plugins'
]()}
/>
{features.includes(FeatureType.Copilot) ? (
<ExperimentalFeaturesItem
title="AI POC"
workspaceMetadata={workspaceMetadata}
feature={FeatureType.Copilot}
/>
) : null}
<CopilotSettingRow workspaceMetadata={workspaceMetadata} />
<SplitViewSettingRow />
</>
);
};

View File

@@ -0,0 +1,24 @@
import { FeatureType, getUserFeaturesQuery } from '@affine/graphql';
import type { BareFetcher, Middleware } from 'swr';
import { useQueryImmutable } from '../use-query';
const wrappedFetcher = (fetcher: BareFetcher<any> | null, ...args: any[]) =>
fetcher?.(...args).catch(() => null);
const errorHandler: Middleware = useSWRNext => (key, fetcher, config) => {
return useSWRNext(key, wrappedFetcher.bind(null, fetcher), config);
};
export function useIsEarlyAccess() {
const { data } = useQueryImmutable(
{
query: getUserFeaturesQuery,
},
{
use: [errorHandler],
}
);
return data?.currentUser?.features.includes(FeatureType.EarlyAccess) ?? false;
}

View File

@@ -1,3 +1,4 @@
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
import { useService } from '@toeverything/infra/di';
import type { To } from 'history';
import { useCallback } from 'react';
@@ -13,12 +14,13 @@ export const WorkbenchLink = ({
{ to: To } & React.HTMLProps<HTMLAnchorElement>
>) => {
const workbench = useService(Workbench);
const { appSettings } = useAppSettingHelper();
const handleClick = useCallback(
(event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
// TODO: open this when multi view control is implemented
if (
(window as any).enableMultiView &&
appSettings.enableMultiView &&
environment.isDesktop &&
(event.ctrlKey || event.metaKey)
) {
@@ -29,7 +31,7 @@ export const WorkbenchLink = ({
onClick?.(event);
},
[onClick, to, workbench]
[appSettings.enableMultiView, onClick, to, workbench]
);
return (
<a {...other} href="#" onClick={handleClick}>