2022-03-17 12:31:06 +05:00
|
|
|
import { Text, Flex } from "rebass";
|
|
|
|
|
import Dialog from "./dialog";
|
|
|
|
|
import * as Icon from "../icons";
|
|
|
|
|
import { getHomeRoute, hardNavigate } from "../../navigation";
|
|
|
|
|
import { appVersion } from "../../utils/version";
|
|
|
|
|
import Config from "../../utils/config";
|
2022-03-17 13:25:45 +05:00
|
|
|
import { isTesting } from "../../utils/platform";
|
2022-03-17 12:31:06 +05:00
|
|
|
|
|
|
|
|
type CallToAction = {
|
|
|
|
|
title: string;
|
|
|
|
|
icon?: (props: any) => JSX.Element;
|
|
|
|
|
action?: () => void;
|
|
|
|
|
};
|
|
|
|
|
type SubFeature = {
|
|
|
|
|
title: string;
|
|
|
|
|
icon?: (props: any) => JSX.Element;
|
|
|
|
|
subtitle?: string | JSX.Element;
|
|
|
|
|
};
|
|
|
|
|
type Feature = {
|
|
|
|
|
shouldShow?: () => boolean;
|
|
|
|
|
title: string;
|
|
|
|
|
subtitle?: string;
|
|
|
|
|
cta: CallToAction;
|
|
|
|
|
subFeatures?: SubFeature[];
|
|
|
|
|
};
|
|
|
|
|
|
2022-04-14 17:33:46 +05:00
|
|
|
export type FeatureKeys = "confirmed" | "highlights";
|
2022-03-17 12:31:06 +05:00
|
|
|
const features: Record<FeatureKeys, Feature> = {
|
|
|
|
|
confirmed: {
|
|
|
|
|
title: "Email confirmed!",
|
|
|
|
|
subtitle: "You can now sync your notes to unlimited devices.",
|
|
|
|
|
cta: {
|
|
|
|
|
title: "Continue",
|
|
|
|
|
icon: Icon.ArrowRight,
|
|
|
|
|
action: () => hardNavigate(getHomeRoute()),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
highlights: {
|
|
|
|
|
title: "✨ Highlights ✨",
|
|
|
|
|
subtitle: `Welcome to v${appVersion.clean}`,
|
|
|
|
|
subFeatures: [
|
|
|
|
|
{
|
2022-04-14 15:55:54 +05:00
|
|
|
title: "All panes are now resizable",
|
2022-03-17 12:31:06 +05:00
|
|
|
subtitle: (
|
|
|
|
|
<>
|
2022-04-14 15:55:54 +05:00
|
|
|
You can now adjust the width of all the panes as you see fit. And
|
|
|
|
|
they persist across sessions too!
|
2022-03-17 12:31:06 +05:00
|
|
|
</>
|
|
|
|
|
),
|
2022-04-14 15:55:54 +05:00
|
|
|
icon: Icon.Resize,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: "Sort alphabetically when group by = none",
|
|
|
|
|
subtitle: <>No idea why this wasn't included earlier.</>,
|
|
|
|
|
icon: Icon.SortBy,
|
2022-03-17 12:31:06 +05:00
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
cta: {
|
|
|
|
|
title: "Got it",
|
|
|
|
|
icon: Icon.Checkmark,
|
|
|
|
|
action: () => {
|
|
|
|
|
Config.set(`${appVersion.numerical}:highlights`, true);
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
shouldShow: () => {
|
2022-04-14 17:33:46 +05:00
|
|
|
const key = `${appVersion.numerical}:highlights`;
|
|
|
|
|
const hasShownBefore = Config.get(key, false) as boolean;
|
|
|
|
|
const hasShownAny = Config.has((k) => k.endsWith(":highlights"));
|
|
|
|
|
if (!hasShownAny) Config.set(key, true);
|
|
|
|
|
return hasShownAny && !isTesting() && !hasShownBefore;
|
2022-03-17 12:31:06 +05:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type FeatureDialogProps = {
|
|
|
|
|
featureName: FeatureKeys;
|
|
|
|
|
onClose: (result: boolean) => void;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function FeatureDialog(props: FeatureDialogProps) {
|
|
|
|
|
const { featureName } = props;
|
|
|
|
|
const feature = features[featureName];
|
2022-04-06 02:31:42 +05:00
|
|
|
if (!feature || (feature.shouldShow && !feature.shouldShow())) {
|
|
|
|
|
props.onClose(false);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-17 12:31:06 +05:00
|
|
|
return (
|
|
|
|
|
<Dialog
|
|
|
|
|
isOpen={true}
|
|
|
|
|
title={feature.title}
|
|
|
|
|
description={feature.subtitle}
|
|
|
|
|
alignment="center"
|
|
|
|
|
positiveButton={{
|
|
|
|
|
text: (
|
|
|
|
|
<Flex>
|
|
|
|
|
{feature.cta.icon && (
|
|
|
|
|
<feature.cta.icon color="primary" size={16} sx={{ mr: 1 }} />
|
|
|
|
|
)}
|
|
|
|
|
{feature.cta.title}
|
|
|
|
|
</Flex>
|
|
|
|
|
),
|
|
|
|
|
onClick: () => {
|
|
|
|
|
if (feature.cta.action) feature.cta.action();
|
|
|
|
|
props.onClose(true);
|
|
|
|
|
},
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Flex flexDirection="column" overflowY="auto" mt={2}>
|
|
|
|
|
{feature.subFeatures?.map((feature) => (
|
|
|
|
|
<Flex
|
|
|
|
|
mb={2}
|
|
|
|
|
bg="bgSecondary"
|
|
|
|
|
p={2}
|
|
|
|
|
sx={{ borderRadius: "default", ":hover": { bg: "hover" } }}
|
|
|
|
|
flexDirection="column"
|
|
|
|
|
>
|
|
|
|
|
<Flex alignItems={"center"} justifyContent="start">
|
|
|
|
|
{feature.icon && <feature.icon size={14} color="primary" />}
|
|
|
|
|
<Text variant="subtitle" fontWeight="normal" ml={1}>
|
|
|
|
|
{feature.title}
|
|
|
|
|
</Text>
|
|
|
|
|
</Flex>
|
|
|
|
|
{feature.subtitle && (
|
|
|
|
|
<Text variant="body" color="icon">
|
|
|
|
|
{feature.subtitle}
|
|
|
|
|
</Text>
|
|
|
|
|
)}
|
|
|
|
|
</Flex>
|
|
|
|
|
))}
|
|
|
|
|
</Flex>
|
|
|
|
|
</Dialog>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
export default FeatureDialog;
|
|
|
|
|
|
|
|
|
|
type CodeProps = { text: string; href?: string };
|
|
|
|
|
export function Code(props: CodeProps) {
|
|
|
|
|
return (
|
|
|
|
|
<Text
|
|
|
|
|
as="code"
|
|
|
|
|
sx={{
|
|
|
|
|
bg: "background",
|
|
|
|
|
color: "text",
|
|
|
|
|
px: 1,
|
|
|
|
|
borderRadius: 5,
|
|
|
|
|
fontFamily: "monospace",
|
|
|
|
|
fontSize: "subBody",
|
|
|
|
|
border: "1px solid var(--border)",
|
|
|
|
|
cursor: props.href ? "pointer" : "unset",
|
|
|
|
|
}}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
if (props.href) window.open(props.href, "_target");
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{props.text}
|
|
|
|
|
</Text>
|
|
|
|
|
);
|
|
|
|
|
}
|