fix: modify experimental features to app-level (#6823)

This commit is contained in:
Akumatus
2024-05-08 12:21:02 +08:00
committed by GitHub
parent e85548b393
commit 4a032eb260
15 changed files with 94 additions and 49 deletions

View File

@@ -23,6 +23,7 @@ export const runtimeFlagsSchema = z.object({
enableEnhanceShareMode: z.boolean(), enableEnhanceShareMode: z.boolean(),
enablePayment: z.boolean(), enablePayment: z.boolean(),
enablePageHistory: z.boolean(), enablePageHistory: z.boolean(),
enableExperimentalFeature: z.boolean(),
allowLocalWorkspace: z.boolean(), allowLocalWorkspace: z.boolean(),
// this is for the electron app // this is for the electron app
serverUrlPrefix: z.string(), serverUrlPrefix: z.string(),

View File

@@ -26,7 +26,7 @@ const ExperimentalFeaturesPrompt = ({
}, []); }, []);
return ( return (
<div className={styles.promptRoot}> <div className={styles.promptRoot} data-testid="experimental-prompt">
<div className={styles.promptTitle}> <div className={styles.promptTitle}>
{t[ {t[
'com.affine.settings.workspace.experimental-features.prompt-header' 'com.affine.settings.workspace.experimental-features.prompt-header'
@@ -49,14 +49,23 @@ const ExperimentalFeaturesPrompt = ({
<div className={styles.spacer} /> <div className={styles.spacer} />
<label className={styles.promptDisclaimer}> <label className={styles.promptDisclaimer}>
<Checkbox checked={checked} onChange={onChange} /> <Checkbox
checked={checked}
onChange={onChange}
data-testid="experimental-prompt-disclaimer"
/>
{t[ {t[
'com.affine.settings.workspace.experimental-features.prompt-disclaimer' 'com.affine.settings.workspace.experimental-features.prompt-disclaimer'
]()} ]()}
</label> </label>
<div className={styles.promptDisclaimerConfirm}> <div className={styles.promptDisclaimerConfirm}>
<Button disabled={!checked} onClick={onConfirm} type="primary"> <Button
disabled={!checked}
onClick={onConfirm}
type="primary"
data-testid="experimental-confirm-button"
>
{t[ {t[
'com.affine.settings.workspace.experimental-features.get-started' 'com.affine.settings.workspace.experimental-features.get-started'
]()} ]()}
@@ -158,7 +167,10 @@ const ExperimentalFeaturesMain = () => {
'com.affine.settings.workspace.experimental-features.header.plugins' 'com.affine.settings.workspace.experimental-features.header.plugins'
]()} ]()}
/> />
<div className={styles.settingsContainer}> <div
className={styles.settingsContainer}
data-testid="experimental-settings"
>
<SplitViewSettingRow /> <SplitViewSettingRow />
<BlocksuiteFeatureFlagSettings /> <BlocksuiteFeatureFlagSettings />
</div> </div>

View File

@@ -1,17 +1,21 @@
import { UserFeatureService } from '@affine/core/modules/cloud/services/user-feature';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { import {
AppearanceIcon, AppearanceIcon,
ExperimentIcon,
InformationIcon, InformationIcon,
KeyboardIcon, KeyboardIcon,
} from '@blocksuite/icons'; } from '@blocksuite/icons';
import { useLiveData, useService } from '@toeverything/infra'; import { useLiveData, useServices } from '@toeverything/infra';
import type { ReactElement, SVGProps } from 'react'; import type { ReactElement, SVGProps } from 'react';
import { useEffect } from 'react';
import { AuthService, ServerConfigService } from '../../../../modules/cloud'; import { AuthService, ServerConfigService } from '../../../../modules/cloud';
import type { GeneralSettingKey } from '../types'; import type { GeneralSettingKey } from '../types';
import { AboutAffine } from './about'; import { AboutAffine } from './about';
import { AppearanceSettings } from './appearance'; import { AppearanceSettings } from './appearance';
import { BillingSettings } from './billing'; import { BillingSettings } from './billing';
import { ExperimentalFeatures } from './experimental-features';
import { PaymentIcon, UpgradeIcon } from './icons'; import { PaymentIcon, UpgradeIcon } from './icons';
import { AFFiNEPricingPlans } from './plans'; import { AFFiNEPricingPlans } from './plans';
import { Shortcuts } from './shortcuts'; import { Shortcuts } from './shortcuts';
@@ -27,11 +31,22 @@ export type GeneralSettingList = GeneralSettingListItem[];
export const useGeneralSettingList = (): GeneralSettingList => { export const useGeneralSettingList = (): GeneralSettingList => {
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const status = useLiveData(useService(AuthService).session.status$); const { authService, serverConfigService, userFeatureService } = useServices({
const serverConfig = useService(ServerConfigService).serverConfig; AuthService,
ServerConfigService,
UserFeatureService,
});
const status = useLiveData(authService.session.status$);
const hasPaymentFeature = useLiveData( const hasPaymentFeature = useLiveData(
serverConfig.features$.map(f => f?.payment) serverConfigService.serverConfig.features$.map(f => f?.payment)
); );
const isEarlyAccess = useLiveData(
userFeatureService.userFeature.isEarlyAccess$
);
useEffect(() => {
userFeatureService.userFeature.revalidate();
}, [userFeatureService]);
const settings: GeneralSettingListItem[] = [ const settings: GeneralSettingListItem[] = [
{ {
@@ -71,6 +86,15 @@ export const useGeneralSettingList = (): GeneralSettingList => {
} }
} }
if (isEarlyAccess || runtimeConfig.enableExperimentalFeature) {
settings.push({
key: 'experimental-features',
title: t['com.affine.settings.workspace.experimental-features'](),
icon: ExperimentIcon,
testId: 'experimental-features-trigger',
});
}
return settings; return settings;
}; };
@@ -90,6 +114,8 @@ export const GeneralSetting = ({ generalKey }: GeneralSettingProps) => {
return <AFFiNEPricingPlans />; return <AFFiNEPricingPlans />;
case 'billing': case 'billing':
return <BillingSettings />; return <BillingSettings />;
case 'experimental-features':
return <ExperimentalFeatures />;
default: default:
return null; return null;
} }

View File

@@ -234,10 +234,6 @@ const subTabConfigs = [
key: 'preference', key: 'preference',
title: 'com.affine.settings.workspace.preferences', title: 'com.affine.settings.workspace.preferences',
}, },
{
key: 'experimental-features',
title: 'com.affine.settings.workspace.experimental-features',
},
{ {
key: 'properties', key: 'properties',
title: 'com.affine.settings.workspace.properties', title: 'com.affine.settings.workspace.properties',
@@ -267,9 +263,6 @@ const WorkspaceListItem = ({
const currentWorkspace = workspaceService.workspace; const currentWorkspace = workspaceService.workspace;
const isCurrent = currentWorkspace.id === meta.id; const isCurrent = currentWorkspace.id === meta.id;
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const isEarlyAccess = useLiveData(
userFeatureService.userFeature.isEarlyAccess$
);
useEffect(() => { useEffect(() => {
userFeatureService.userFeature.revalidate(); userFeatureService.userFeature.revalidate();
@@ -280,30 +273,23 @@ const WorkspaceListItem = ({
}, [onClick]); }, [onClick]);
const subTabs = useMemo(() => { const subTabs = useMemo(() => {
return subTabConfigs return subTabConfigs.map(({ key, title }) => {
.filter(({ key }) => { return (
if (key === 'experimental-features') { <div
return information?.isOwner && isEarlyAccess; data-testid={`workspace-list-item-${key}`}
} onClick={() => {
return true; onClick(key);
}) }}
.map(({ key, title }) => { className={clsx(style.sidebarSelectSubItem, {
return ( active: activeSubTab === key,
<div })}
data-testid={`workspace-list-item-${key}`} key={key}
onClick={() => { >
onClick(key); {t[title]()}
}} </div>
className={clsx(style.sidebarSelectSubItem, { );
active: activeSubTab === key, });
})} }, [activeSubTab, onClick, t]);
key={key}
>
{t[title]()}
</div>
);
});
}, [activeSubTab, information?.isOwner, isEarlyAccess, onClick, t]);
return ( return (
<> <>

View File

@@ -4,13 +4,10 @@ export const GeneralSettingKeys = [
'about', 'about',
'plans', 'plans',
'billing', 'billing',
'experimental-features',
] as const; ] as const;
export const WorkspaceSubTabs = [ export const WorkspaceSubTabs = ['preference', 'properties'] as const;
'preference',
'experimental-features',
'properties',
] as const;
export type GeneralSettingKey = (typeof GeneralSettingKeys)[number]; export type GeneralSettingKey = (typeof GeneralSettingKeys)[number];

View File

@@ -1,6 +1,6 @@
import type { WorkspaceMetadata } from '@toeverything/infra'; import type { WorkspaceMetadata } from '@toeverything/infra';
import { ExperimentalFeatures } from './experimental-features'; import type { WorkspaceSubTab } from '../types';
import { WorkspaceSettingDetail } from './new-workspace-setting-detail'; import { WorkspaceSettingDetail } from './new-workspace-setting-detail';
import { WorkspaceSettingProperties } from './properties'; import { WorkspaceSettingProperties } from './properties';
@@ -9,13 +9,11 @@ export const WorkspaceSetting = ({
subTab, subTab,
}: { }: {
workspaceMetadata: WorkspaceMetadata; workspaceMetadata: WorkspaceMetadata;
subTab: 'preference' | 'experimental-features' | 'properties'; subTab: WorkspaceSubTab;
}) => { }) => {
switch (subTab) { switch (subTab) {
case 'preference': case 'preference':
return <WorkspaceSettingDetail workspaceMetadata={workspaceMetadata} />; return <WorkspaceSettingDetail workspaceMetadata={workspaceMetadata} />;
case 'experimental-features':
return <ExperimentalFeatures />;
case 'properties': case 'properties':
return ( return (
<WorkspaceSettingProperties workspaceMetadata={workspaceMetadata} /> <WorkspaceSettingProperties workspaceMetadata={workspaceMetadata} />

View File

@@ -1129,7 +1129,7 @@
"com.affine.settings.translucent-style-description": "Use transparency effect on the sidebar.", "com.affine.settings.translucent-style-description": "Use transparency effect on the sidebar.",
"com.affine.settings.workspace": "Workspace", "com.affine.settings.workspace": "Workspace",
"com.affine.settings.workspace.description": "You can view current workspace's information here.", "com.affine.settings.workspace.description": "You can view current workspace's information here.",
"com.affine.settings.workspace.experimental-features": "Plugins", "com.affine.settings.workspace.experimental-features": "Experimental Features",
"com.affine.settings.workspace.experimental-features.get-started": "Get Started", "com.affine.settings.workspace.experimental-features.get-started": "Get Started",
"com.affine.settings.workspace.experimental-features.header.plugins": "Experimental Features", "com.affine.settings.workspace.experimental-features.header.plugins": "Experimental Features",
"com.affine.settings.workspace.experimental-features.prompt-disclaimer": "I am aware of the risks, and I am willing to continue to use it.", "com.affine.settings.workspace.experimental-features.prompt-disclaimer": "I am aware of the risks, and I am willing to continue to use it.",

View File

@@ -2,8 +2,10 @@ import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page'; import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitForEditorLoad } from '@affine-test/kit/utils/page-logic'; import { waitForEditorLoad } from '@affine-test/kit/utils/page-logic';
import { import {
confirmExperimentalPrompt,
openAboutPanel, openAboutPanel,
openAppearancePanel, openAppearancePanel,
openExperimentalFeaturesPanel,
openSettingModal, openSettingModal,
openShortcutsPanel, openShortcutsPanel,
} from '@affine-test/kit/utils/setting'; } from '@affine-test/kit/utils/setting';
@@ -87,6 +89,18 @@ test('Open about panel', async ({ page }) => {
await expect(title).toBeVisible(); await expect(title).toBeVisible();
}); });
test('Open experimental features panel', async ({ page }) => {
await openHomePage(page);
await waitForEditorLoad(page);
await openSettingModal(page);
await openExperimentalFeaturesPanel(page);
const prompt = page.getByTestId('experimental-prompt');
await expect(prompt).toBeVisible();
await confirmExperimentalPrompt(page);
const settings = page.getByTestId('experimental-settings');
await expect(settings).toBeVisible();
});
test('Different workspace should have different name in the setting panel', async ({ test('Different workspace should have different name in the setting panel', async ({
page, page,
}) => { }) => {

View File

@@ -24,6 +24,15 @@ export async function openAboutPanel(page: Page) {
await page.getByTestId('about-panel-trigger').click(); await page.getByTestId('about-panel-trigger').click();
} }
export async function openExperimentalFeaturesPanel(page: Page) {
await page.getByTestId('experimental-features-trigger').click();
}
export async function confirmExperimentalPrompt(page: Page) {
await page.getByTestId('experimental-prompt-disclaimer').click();
await page.getByTestId('experimental-confirm-button').click();
}
export async function openWorkspaceSettingPanel( export async function openWorkspaceSettingPanel(
page: Page, page: Page,
workspaceName: string workspaceName: string

View File

@@ -22,6 +22,7 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig {
enableEnhanceShareMode: false, enableEnhanceShareMode: false,
enablePayment: true, enablePayment: true,
enablePageHistory: true, enablePageHistory: true,
enableExperimentalFeature: false,
allowLocalWorkspace: buildFlags.distribution === 'desktop' ? true : false, allowLocalWorkspace: buildFlags.distribution === 'desktop' ? true : false,
serverUrlPrefix: 'https://app.affine.pro', serverUrlPrefix: 'https://app.affine.pro',
appVersion: packageJson.version, appVersion: packageJson.version,
@@ -61,6 +62,7 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig {
enableEnhanceShareMode: false, enableEnhanceShareMode: false,
enablePayment: true, enablePayment: true,
enablePageHistory: true, enablePageHistory: true,
enableExperimentalFeature: true,
allowLocalWorkspace: buildFlags.distribution === 'desktop' ? true : false, allowLocalWorkspace: buildFlags.distribution === 'desktop' ? true : false,
serverUrlPrefix: 'https://affine.fail', serverUrlPrefix: 'https://affine.fail',
appVersion: packageJson.version, appVersion: packageJson.version,