web: make monograph analytics a pro feature

This commit is contained in:
Abdullah Atta
2025-11-08 12:49:36 +05:00
parent 71952a354e
commit 28b563b95b
2 changed files with 58 additions and 23 deletions

View File

@@ -23,15 +23,20 @@ import { Loading, Refresh } from "../icons";
import { db } from "../../common/db";
import { writeText } from "clipboard-polyfill";
import { showToast } from "../../utils/toast";
import { EV, EVENTS, hosts, Monograph, MonographStats } from "@notesnook/core";
import { EV, EVENTS, hosts, MonographAnalytics } from "@notesnook/core";
import { useStore } from "../../stores/monograph-store";
import { Note } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { getFormattedDate, usePromise } from "@notesnook/common";
import {
getFormattedDate,
useIsFeatureAvailable,
usePromise
} from "@notesnook/common";
import { createRoot, Root } from "react-dom/client";
import { PopupPresenter } from "@notesnook/ui";
import { BaseDialogProps, DialogManager } from "../../common/dialog-manager";
import Dialog from "../../components/dialog";
import { UpgradeDialog } from "../../dialogs/buy-dialog/upgrade-dialog";
type PublishViewProps = {
note: Note;
@@ -43,11 +48,11 @@ function PublishView(props: PublishViewProps) {
const [selfDestruct, setSelfDestruct] = useState(
props.monograph?.selfDestruct
);
const [stats, setStats] = useState<MonographStats>(
props.monograph?.stats || { viewCount: 0 }
const [analytics, setAnalytics] = useState<MonographAnalytics>(
props.monograph?.analytics || { totalViews: 0 }
);
const [status, setStatus] = useState<{
action: "publish" | "unpublish" | "stats";
action: "publish" | "unpublish" | "analytics";
}>();
const [processingStatus, setProcessingStatus] = useState<{
total?: number;
@@ -57,6 +62,7 @@ function PublishView(props: PublishViewProps) {
const publishNote = useStore((store) => store.publish);
const unpublishNote = useStore((store) => store.unpublish);
const [monograph, setMonograph] = useState(props.monograph);
const monographAnalytics = useIsFeatureAvailable("monographAnalytics");
useEffect(() => {
const fileDownloadedEvent = EV.subscribe(
@@ -144,25 +150,43 @@ function PublishView(props: PublishViewProps) {
}}
>
<Text variant="body">{strings.views()}</Text>
<Flex sx={{ alignItems: "center", gap: 1 }}>
<Text variant="body" sx={{ color: "paragraph-secondary" }}>
{stats.viewCount}
</Text>
{monographAnalytics?.isAllowed ? (
<Flex sx={{ alignItems: "center", gap: 1 }}>
<Text
variant="body"
sx={{
color: "paragraph-secondary"
}}
>
{analytics.totalViews}
</Text>
<Button
variant="tertiary"
onClick={async () => {
try {
setStatus({ action: "analytics" });
const analytics = await db.monographs.analytics(
monograph?.id
);
setAnalytics(analytics);
} finally {
setStatus(undefined);
}
}}
>
<Refresh size={14} rotate={status?.action === "analytics"} />
</Button>
</Flex>
) : monographAnalytics ? (
<Button
variant="tertiary"
onClick={async () => {
try {
setStatus({ action: "stats" });
const stats = await db.monographs.stats(monograph?.id);
setStats(stats);
} finally {
setStatus(undefined);
}
}}
variant="anchor"
onClick={() =>
UpgradeDialog.show({ feature: monographAnalytics })
}
>
<Refresh size={14} rotate={status?.action === "stats"} />
{strings.upgrade()}
</Button>
</Flex>
) : null}
</Flex>
) : null}
<Flex
@@ -396,7 +420,7 @@ type ResolvedMonograph = {
id: string;
selfDestruct: boolean;
publishedAt?: number;
stats: MonographStats;
analytics: MonographAnalytics;
password?: string;
};
@@ -409,7 +433,7 @@ async function resolveMonograph(
id: monographId,
selfDestruct: !!monograph.selfDestruct,
publishedAt: monograph.datePublished,
stats: await db.monographs.stats(monographId),
analytics: await db.monographs.analytics(monographId),
password: monograph.password
? await db.monographs.decryptPassword(monograph.password)
: undefined

View File

@@ -437,6 +437,17 @@ const features = {
legacyPro: createLimit(true)
}
}),
monographAnalytics: createFeature({
id: "monographAnalytics",
title: "Monographs analytics",
availability: {
free: createLimit(false),
essential: createLimit(false),
pro: createLimit(true),
believer: createLimit(true),
legacyPro: createLimit(true)
}
}),
sms2FA: createFeature({
id: "sms2FA",
title: "2FA via SMS",