Skip to content

Commit

Permalink
feat: add Labs pane to preferences (#892)
Browse files Browse the repository at this point in the history
* feat: add Labs pane to preferences

* feat: use lab_features value for account switcher

* feat: labs pane with experimental features

* fix: use toggleExperimentalFeature from features service

* fix: show premium modal if not entitled for experimental feature

* fix: add isExperimental && isExperimentalEnabled to EditorMenuItem type

* fix: hide experimental editor if not enabled

* chore(deps): update features and snjs

* fix: remove comment

* fix: remove filtering from reloadExperimentalFeatures

* fix: revert Footer.tsx

* chore(deps): bump @standardnotes packages

* fix: change experimental features layout

Co-authored-by: Johnny Almonte <[email protected]>
Co-authored-by: Mo <[email protected]>
  • Loading branch information
3 people authored Mar 8, 2022
1 parent 6d64889 commit ab6e5ac
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export type EditorMenuItem = {
name: string;
component?: SNComponent;
isEntitled: boolean;
isExperimental: boolean;
isExperimentalEnabled: boolean;
};

export type EditorMenuGroup = AccordionMenuGroup<EditorMenuItem>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,10 @@ export const ChangeEditorMenu: FunctionComponent<ChangeEditorMenuProps> = ({
selectEditor(item);
};

if (item.isExperimental && !item.isExperimentalEnabled) {
return;
}

return (
<MenuItem
type={MenuItemType.RadioButton}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export const createEditorMenuGroups = (
{
name: PLAIN_EDITOR_NAME,
isEntitled: true,
isExperimental: false,
isExperimentalEnabled: false,
},
],
'rich-text': [],
Expand All @@ -67,6 +69,13 @@ export const createEditorMenuGroups = (
editorItems[getEditorGroup(editorFeature)].push({
name: editorFeature.name as string,
isEntitled: false,
isExperimental: application.features.isExperimentalFeature(
editorFeature.identifier
),
isExperimentalEnabled:
application.features.isExperimentalFeatureEnabled(
editorFeature.identifier
),
});
}
});
Expand All @@ -78,6 +87,12 @@ export const createEditorMenuGroups = (
isEntitled:
application.features.getFeatureStatus(editor.identifier) ===
FeatureStatus.Entitled,
isExperimental: application.features.isExperimentalFeature(
editor.identifier
),
isExperimentalEnabled: application.features.isExperimentalFeatureEnabled(
editor.identifier
),
};

editorItems[getEditorGroup(editor.package_info)].push(editorItem);
Expand Down
3 changes: 2 additions & 1 deletion app/assets/javascripts/preferences/panes/General.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { WebApplication } from '@/ui_models/application';
import { AppState } from '@/ui_models/app_state';
import { FunctionComponent } from 'preact';
import { PreferencesPane } from '../components';
import { ErrorReporting, Tools, Defaults } from './general-segments';
import { ErrorReporting, Tools, Defaults, LabsPane } from './general-segments';
import { ExtensionsLatestVersions } from '@/preferences/panes/extensions-segments';
import { Advanced } from '@/preferences/panes/account';
import { observer } from 'mobx-react-lite';
Expand All @@ -19,6 +19,7 @@ export const General: FunctionComponent<GeneralProps> = observer(
<Tools application={application} />
<Defaults application={application} />
<ErrorReporting appState={appState} />
<LabsPane application={application} />
<Advanced
application={application}
appState={appState}
Expand Down
102 changes: 102 additions & 0 deletions app/assets/javascripts/preferences/panes/general-segments/Labs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { FindNativeFeature } from '@standardnotes/features';
import { Switch } from '@/components/Switch';
import {
PreferencesGroup,
PreferencesSegment,
Subtitle,
Text,
Title,
} from '@/preferences/components';
import { WebApplication } from '@/ui_models/application';
import { FeatureIdentifier, FeatureStatus } from '@standardnotes/snjs';
import { FunctionComponent } from 'preact';
import { useCallback, useEffect, useState } from 'preact/hooks';
import { usePremiumModal } from '@/components/Premium';
import { HorizontalSeparator } from '@/components/shared/HorizontalSeparator';

type Props = {
application: WebApplication;
};

export const LabsPane: FunctionComponent<Props> = ({ application }) => {
const [experimentalFeatures, setExperimentalFeatures] =
useState<FeatureIdentifier[]>();

const reloadExperimentalFeatures = useCallback(() => {
const experimentalFeatures = application.features.getExperimentalFeatures();
setExperimentalFeatures(experimentalFeatures);
}, [application.features]);

useEffect(() => {
reloadExperimentalFeatures();
}, [reloadExperimentalFeatures]);

const premiumModal = usePremiumModal();

if (!experimentalFeatures) {
return (
<div className="flex items-center justify-between">
No experimental features available.
</div>
);
}

return (
<PreferencesGroup>
<PreferencesSegment>
<Title>Labs</Title>
<div>
{experimentalFeatures?.map(
(featureIdentifier: FeatureIdentifier, index: number) => {
const feature = FindNativeFeature(featureIdentifier);
const featureName = feature?.name ?? featureIdentifier;
const featureDescription = feature?.description ?? '';

const isFeatureEnabled =
application.features.isExperimentalFeatureEnabled(
featureIdentifier
);

const toggleFeature = () => {
const isEntitled =
application.features.getFeatureStatus(featureIdentifier) ===
FeatureStatus.Entitled;
if (!isEntitled) {
premiumModal.activate(featureName);
return;
}

application.features.toggleExperimentalFeature(
featureIdentifier
);
reloadExperimentalFeatures();
};

const showHorizontalSeparator =
experimentalFeatures.length > 1 &&
index !== experimentalFeatures.length - 1;

return (
<>
<div className="flex items-center justify-between">
<div className="flex flex-col">
<Subtitle>{featureName}</Subtitle>
<Text>{featureDescription}</Text>
</div>
<Switch
onChange={toggleFeature}
checked={isFeatureEnabled}
/>
</div>
{showHorizontalSeparator && (
<HorizontalSeparator classes="mt-5 mb-3" />
)}
</>
);
}
)}
</div>
</PreferencesSegment>
</PreferencesGroup>
);
};
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './ErrorReporting';
export * from './Tools';
export * from './Defaults';
export * from './Labs';
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
"@babel/preset-typescript": "^7.16.7",
"@reach/disclosure": "^0.16.2",
"@reach/visually-hidden": "^0.16.0",
"@standardnotes/responses": "^1.3.0",
"@standardnotes/services": "^1.5.2",
"@standardnotes/responses": "1.3.1",
"@standardnotes/services": "1.5.3",
"@standardnotes/stylekit": "5.15.0",
"@svgr/webpack": "^6.2.1",
"@types/jest": "^27.4.1",
Expand Down Expand Up @@ -79,10 +79,10 @@
"@reach/listbox": "^0.16.2",
"@reach/tooltip": "^0.16.2",
"@standardnotes/components": "1.7.9",
"@standardnotes/features": "1.34.2",
"@standardnotes/settings": "^1.12.0",
"@standardnotes/features": "1.34.3",
"@standardnotes/settings": "1.12.0",
"@standardnotes/sncrypto-web": "1.7.3",
"@standardnotes/snjs": "2.77.0",
"@standardnotes/snjs": "2.77.1",
"mobx": "^6.4.2",
"mobx-react-lite": "^3.3.0",
"preact": "^10.6.6",
Expand Down
70 changes: 35 additions & 35 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2331,53 +2331,53 @@
resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.7.9.tgz#41e5fdbcee250b9b3c18045dad8998c6f668307b"
integrity sha512-/+Paw6ry/IS9ldYUM/lgC4O6qwl1fukWvNw65IMKyB9LMY3+xTh/I2BfnWynP117pVPxtu3/2+FBEnx04KvQwg==

"@standardnotes/domain-events@^2.23.24":
version "2.23.24"
resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.24.tgz#7872c178491cffb8ad9efa20eca3610a30ca669e"
integrity sha512-R8n1J4YHnY0qxUJcZt91eth+87Dy//GncsC+mpkNwEgtrzAAkS6lXO4xFwYVw7UHp6EmLtsKCnbXk+72WPzd9A==
"@standardnotes/domain-events@^2.23.25":
version "2.23.25"
resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.25.tgz#bab5773fd1355a94fe35faba995b53ae414e325a"
integrity sha512-2nhsCRAbAowtBvzXgRVBo+o4blz1VfmGLM32TabW1EEXHI1Y5K/qQ7+OrZ9TPkd6B0JNC4od/OCY7rLCma8BEg==
dependencies:
"@standardnotes/auth" "^3.17.3"
"@standardnotes/features" "^1.34.2"
"@standardnotes/features" "^1.34.3"

"@standardnotes/[email protected].2", "@standardnotes/features@^1.34.2":
version "1.34.2"
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.34.2.tgz#a3f2480e88a3873ae7dd34e6b57b9595a9f15c87"
integrity sha512-77/DyFMsL+gW4ElVl4n1huNyeYhFA1PyTPbITWkFhQib02aPhhOmjSecxJknFppSNZnBRRqd2hbBa0vMhxUWIA==
"@standardnotes/[email protected].3", "@standardnotes/features@^1.34.3":
version "1.34.3"
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.34.3.tgz#4de3259e43cfd2c2d50a0a113439566a6bed8fca"
integrity sha512-WL+nyJsm/mBq2zuR3ZlJ/mJhaVPrm3j7gvBdDr4kxdvMM5y9E4DiYHp98SeUvblIGXWmhZxVc7rdDmVaoYt99g==
dependencies:
"@standardnotes/auth" "^3.17.3"
"@standardnotes/common" "^1.15.3"

"@standardnotes/payloads@^1.4.1":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@standardnotes/payloads/-/payloads-1.4.1.tgz#5da68ecc55920080223518c5d5d186380d1a43ca"
integrity sha512-NXc6Iv2AHIOIzURCuPiHpSgLQwfBFpg8ecozwa+zRXMe1ggEljJGWLutds3ehbqp7C0eCaZr+3pGJhtVdoW06w==
"@standardnotes/payloads@^1.4.2":
version "1.4.2"
resolved "https://registry.yarnpkg.com/@standardnotes/payloads/-/payloads-1.4.2.tgz#6f9995a4f585fa814f88bfffdb8d973f078d21d6"
integrity sha512-iw2Fhr7oBQgtOtpLnDyCARbP8VWUpT9bhRdgKg47I8Ky5EmyYBcYOf2U8XuXkzypot4+zZNYc5Bgzgs4YXyDzQ==
dependencies:
"@standardnotes/applications" "^1.1.3"
"@standardnotes/common" "^1.15.3"
"@standardnotes/features" "^1.34.2"
"@standardnotes/features" "^1.34.3"
"@standardnotes/utils" "^1.2.3"

"@standardnotes/responses@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@standardnotes/responses/-/responses-1.3.0.tgz#5c4a901e4ee3fec010e83fe6a773b988e601db07"
integrity sha512-6/g+Hg9yOHvbydw69HNVeblbPH1vzDKSZGYLqWkhKpZjBIHn5dv29PnLfK4OUDJD3C5xFmweYKPBkGuZMuKXrQ==
"@standardnotes/responses@1.3.1", "@standardnotes/responses@^1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@standardnotes/responses/-/responses-1.3.1.tgz#2890e679b6e635b14e223a9eb5a5d8c44accd530"
integrity sha512-h9C/DJike0MVQjDkhZhQ8lPCreZKsAuqtEvXpwVl8vcFAOEfeS1BXacvxSlefHx90og6ti9rfF0D/FqzcI+b6Q==
dependencies:
"@standardnotes/auth" "^3.17.3"
"@standardnotes/common" "^1.15.3"
"@standardnotes/features" "^1.34.2"
"@standardnotes/payloads" "^1.4.1"
"@standardnotes/features" "^1.34.3"
"@standardnotes/payloads" "^1.4.2"

"@standardnotes/services@^1.5.2":
version "1.5.2"
resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.5.2.tgz#7c559785b659694801db391814217a2f8acaac87"
integrity sha512-MSfZmV8+eJp5SMYs9MV1I/WygBTQL0gVK+utfxB8DctC0y1HeEpF4OtooZHmariiQt38tC7vi1/kEpxqgCRL+Q==
"@standardnotes/services@1.5.3", "@standardnotes/services@^1.5.3":
version "1.5.3"
resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.5.3.tgz#0cfa7c0336b31c0084e2be976641fb2c36739e5b"
integrity sha512-NBsF5A4hJZPFOASTSJd60dTuVTiyop1IVZGlmvjs2K8UfHG9/ET59BkVwzPsCsSfnoYSJasVJkxnFunkaeJ/OA==
dependencies:
"@standardnotes/applications" "^1.1.3"
"@standardnotes/common" "^1.15.3"
"@standardnotes/responses" "^1.3.0"
"@standardnotes/responses" "^1.3.1"
"@standardnotes/utils" "^1.2.3"

"@standardnotes/settings@^1.12.0":
"@standardnotes/settings@1.12.0", "@standardnotes/settings@^1.12.0":
version "1.12.0"
resolved "https://registry.yarnpkg.com/@standardnotes/settings/-/settings-1.12.0.tgz#43f3dd7f015f726b1ed88a48fcc3737899116cd5"
integrity sha512-w6S5TT7KRpvUb+JsXZ7ucWPjlWRtpKQdsyT7cLs66ynKRXxUn40hf4kA8T9FhuLAKbG+wIYDrAZl3FRk+HvDWQ==
Expand All @@ -2396,19 +2396,19 @@
buffer "^6.0.3"
libsodium-wrappers "^0.7.9"

"@standardnotes/[email protected].0":
version "2.77.0"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.77.0.tgz#8606cc0c372e27fb099b92c418301f3d0e1add77"
integrity sha512-/JAX65BgJstGIvmQRhtm1QUeS9jRzqbyb5KtRR4WgWn9SVuGRZo2BE0d5ywlQ/y/CW64Xmbp9LDFd137O48uFA==
"@standardnotes/[email protected].1":
version "2.77.1"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.77.1.tgz#2af90c0837edfc0508579a8f71686e946a81afb6"
integrity sha512-kbCh63YxQCaKKx2AHonsBgtTlHeBR6SFtmchBIXiSKA4O7USroGJilTUaK2DVyK5L89hwafkZfot7R+nvXD9zQ==
dependencies:
"@standardnotes/applications" "^1.1.3"
"@standardnotes/auth" "^3.17.3"
"@standardnotes/common" "^1.15.3"
"@standardnotes/domain-events" "^2.23.24"
"@standardnotes/features" "^1.34.2"
"@standardnotes/payloads" "^1.4.1"
"@standardnotes/responses" "^1.3.0"
"@standardnotes/services" "^1.5.2"
"@standardnotes/domain-events" "^2.23.25"
"@standardnotes/features" "^1.34.3"
"@standardnotes/payloads" "^1.4.2"
"@standardnotes/responses" "^1.3.1"
"@standardnotes/services" "^1.5.3"
"@standardnotes/settings" "^1.12.0"
"@standardnotes/sncrypto-common" "^1.7.3"
"@standardnotes/utils" "^1.2.3"
Expand Down

0 comments on commit ab6e5ac

Please sign in to comment.