mobile: cleanup

This commit is contained in:
Ammar Ahmed
2025-09-10 12:28:44 +05:00
committed by Abdullah Atta
parent cfa9f11f44
commit 7d46dd4fb0
9 changed files with 82 additions and 266 deletions

View File

@@ -17,13 +17,13 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { isFeatureAvailable } from "@notesnook/common";
import {
EV,
EVENTS,
EventManagerSubscription,
SYNC_CHECK_IDS,
SubscriptionPlan,
SubscriptionType,
SyncStatusEvent,
User
} from "@notesnook/core";
@@ -51,7 +51,9 @@ import { MMKV } from "../common/database/mmkv";
import { endProgress, startProgress } from "../components/dialogs/progress";
import Migrate from "../components/sheets/migrate";
import NewFeature from "../components/sheets/new-feature";
import PaywallSheet from "../components/sheets/paywall";
import { Walkthrough } from "../components/walkthroughs";
import AddReminder from "../screens/add-reminder";
import {
resetTabStore,
useTabStore
@@ -104,9 +106,6 @@ import { getGithubVersion } from "../utils/github-version";
import { fluidTabsRef } from "../utils/global-refs";
import { NotesnookModule } from "../utils/notesnook-module";
import { sleep } from "../utils/time";
import AddReminder from "../screens/add-reminder";
import { isFeatureAvailable } from "@notesnook/common";
import PaywallSheet from "../components/sheets/paywall";
import useFeatureManager from "./use-feature-manager";
const onCheckSyncStatus = async (type: SyncStatusEvent) => {
@@ -226,11 +225,7 @@ const onUserEmailVerified = async () => {
const onUserSubscriptionStatusChanged = async (
subscription: User["subscription"]
) => {
if (
!PremiumService.get() &&
(subscription.type === SubscriptionType.PREMIUM ||
subscription.plan != SubscriptionPlan.FREE)
) {
if (!PremiumService.get() && subscription.plan !== SubscriptionPlan.FREE) {
PremiumService.subscriptions.clear();
useUserStore.setState({
user: {

View File

@@ -18,11 +18,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { ReactElement } from "react";
import { View } from "react-native";
import { AttachmentDialog } from "../../components/attachments";
import { ChangePassword } from "../../components/auth/change-password";
import { DefaultAppStyles } from "../../utils/styles";
import { AttachmentGroupProgress } from "./attachment-group-progress";
import { ChangeEmail } from "./change-email";
import DebugLogs from "./debug";
import { ConfigureToolbar } from "./editor/configure-toolbar";
import { Licenses } from "./licenses";
import { AttachmentGroupProgress } from "./attachment-group-progress";
import {
ApplockTimerPicker,
BackupReminderPicker,
@@ -37,18 +41,12 @@ import {
import { RestoreBackup } from "./restore-backup";
import { ServersConfiguration } from "./server-config";
import SoundPicker from "./sound-picker";
import { Subscription } from "./subscription";
import ThemeSelector from "./theme-selector";
import { TitleFormat } from "./title-format";
import { View } from "react-native";
import { DefaultAppStyles } from "../../utils/styles";
import { ChangePassword } from "../../components/auth/change-password";
import { ChangeEmail } from "./change-email";
export const components: { [name: string]: ReactElement } = {
homeselector: <HomePicker />,
autobackups: <BackupReminderPicker />,
subscription: <Subscription />,
configuretoolbar: <ConfigureToolbar />,
"debug-logs": <DebugLogs />,
"sound-picker": <SoundPicker />,

View File

@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { formatBytes } from "@notesnook/common";
import { User } from "@notesnook/core";
import { SubscriptionPlan, SubscriptionStatus, User } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import notifee from "@notifee/react-native";
import Clipboard from "@react-native-clipboard/clipboard";
@@ -27,7 +27,6 @@ import React from "react";
import { Appearance, Linking, Platform } from "react-native";
import { getVersion } from "react-native-device-info";
import * as RNIap from "react-native-iap";
//@ts-ignore
import { enabled } from "react-native-privacy-snapshot";
import ScreenGuardModule from "react-native-screenguard";
import { db } from "../../common/database";
@@ -57,7 +56,6 @@ import SettingsService from "../../services/settings";
import Sync from "../../services/sync";
import { useThemeStore } from "../../stores/use-theme-store";
import { useUserStore } from "../../stores/use-user-store";
import { SUBSCRIPTION_STATUS } from "../../utils/constants";
import { eCloseSheet, eOpenRecoveryKeyDialog } from "../../utils/events";
import { NotesnookModule } from "../../utils/notesnook-module";
import { sleep } from "../../utils/time";
@@ -75,59 +73,67 @@ export const settingsGroups: SettingSection[] = [
useHook: () => useUserStore((state) => state.user),
hidden: (current) => !current,
sections: [
// {
// id: "subscription-status",
// useHook: () => useUserStore((state) => state.user),
// hidden: (current) => !current,
// name: (current) => {
// const user = (current as User) || useUserStore.getState().user;
// if (!user) return strings.upgradePlan();
// const isBasic = user.subscription?.type === SUBSCRIPTION_STATUS.BASIC;
// const isTrial = user.subscription?.type === SUBSCRIPTION_STATUS.TRIAL;
// return isBasic || !user.subscription?.type
// ? strings.upgradePlan()
// : isTrial
// ? strings.trialStarted()
// : strings.subDetails();
// ``;
// },
// type: "component",
// component: "subscription",
// icon: "crown",
// description: (current) => {
// const user = current as User;
// if (!user) return strings.neverHesitate();
// const subscriptionDaysLeft =
// user &&
// getTimeLeft(
// parseInt(user.subscription?.expiry as unknown as string)
// );
// const expiryDate = dayjs(user?.subscription?.expiry).format(
// "MMMM D, YYYY"
// );
// const startDate = dayjs(user?.subscription?.start).format(
// "MMMM D, YYYY"
// );
{
id: "subscription-status",
useHook: () => useUserStore((state) => state.user),
hidden: (current) =>
!current ||
(current as User).subscription?.plan === SubscriptionPlan.FREE,
name: (current) => {
const user = (current as User) || useUserStore.getState().user;
return (
strings.subscriptionProviderInfo[
user?.subscription?.provider
].title() || "Unknown provider"
);
},
icon: "credit-card",
modifer: () => {
const user = useUserStore.getState().user;
if (!user) return;
const subscriptionProviderInfo =
strings.subscriptionProviderInfo[user?.subscription.provider];
presentSheet({
title: subscriptionProviderInfo.title(),
paragraph: subscriptionProviderInfo.desc()
});
},
description: (current) => {
const user = current as User;
if (!user) return strings.neverHesitate();
const subscriptionDaysLeft =
user && getTimeLeft(user.subscription?.expiry);
const expiryDate = dayjs(user?.subscription?.expiry).format(
"dddd, MMMM D, YYYY h:mm A"
);
const startDate = dayjs(user?.subscription?.start).format(
"dddd, MMMM D, YYYY h:mm A"
);
// if (user.subscription.provider === 4) {
// return strings.subEndsOn(expiryDate);
// }
if (user.subscription.plan !== SubscriptionPlan.FREE) {
const status = user.subscription.status;
return status === SubscriptionStatus.TRIAL
? strings.trialEndsOn(
dayjs(user?.subscription?.start)
.add(
user?.subscription?.productId.includes("monthly") ? 7 : 14
)
.format("dddd, MMMM D, YYYY h:mm A")
)
: status === SubscriptionStatus.ACTIVE
? strings.subRenewOn(expiryDate)
: status === SubscriptionStatus.CANCELED
? strings.subEndsOn(expiryDate)
: status === SubscriptionStatus.EXPIRED
? subscriptionDaysLeft.time < -3
? strings.subEnded()
: strings.accountDowngradedIn(3)
: strings.neverHesitate();
}
// return user.subscription?.type === 2
// ? strings.signedUpOn(startDate)
// : user.subscription?.type === 1
// ? strings.trialEndsOn(expiryDate)
// : user.subscription?.type === 6
// ? subscriptionDaysLeft.time < -3
// ? strings.subEnded()
// : strings.accountDowngradedIn(3)
// : user.subscription?.type === 7
// ? strings.subEndsOn(expiryDate)
// : user.subscription?.type === 5
// ? strings.subRenewOn(expiryDate)
// : strings.neverHesitate();
// }
// },
return strings.neverHesitate();
}
},
{
id: "redeem-gift-code",
name: strings.redeemGiftCode(),
@@ -137,9 +143,7 @@ export const settingsGroups: SettingSection[] = [
},
useHook: () =>
useUserStore(
(state) =>
state.user?.subscription.type == SUBSCRIPTION_STATUS.TRIAL ||
state.user?.subscription.type == SUBSCRIPTION_STATUS.BASIC
(state) => state.user?.subscription.plan === SubscriptionPlan.FREE
),
icon: "gift",
modifer: () => {

View File

@@ -1,146 +0,0 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import React from "react";
import { Linking, Platform, View } from "react-native";
import Config from "react-native-config";
import { usePricing } from "../../hooks/use-pricing";
import {
eSendEvent,
presentSheet,
ToastManager
} from "../../services/event-manager";
import PremiumService from "../../services/premium";
import { useUserStore } from "../../stores/use-user-store";
import { SUBSCRIPTION_STATUS } from "../../utils/constants";
import { eOpenPremiumDialog } from "../../utils/events";
export const Subscription = () => {
const user = useUserStore((state) => state.user);
const monthlyPlan = usePricing("monthly");
const isNotPro =
user?.subscription?.type !== SUBSCRIPTION_STATUS.PREMIUM &&
user?.subscription?.type !== SUBSCRIPTION_STATUS.BETA;
const hasCancelledPremium =
SUBSCRIPTION_STATUS.PREMIUM_CANCELLED === user?.subscription?.type;
const subscriptionProviderInfo =
strings.subscriptionProviderInfo[user?.subscription?.provider];
const manageSubscription = () => {
if (!user?.isEmailConfirmed) {
PremiumService.showVerifyEmailDialog();
return;
}
if (Config.GITHUB_RELEASE === "true") {
presentSheet({
paragraph: strings.subNotSupported(),
action: () => {
Linking.openURL("https://app.notesnook.com");
},
actionText: strings.goToWebApp()
});
return;
}
if (hasCancelledPremium && Platform.OS === "android") {
if (user.subscription?.provider === 3) {
ToastManager.show({
heading: strings.subOnWeb(),
message: strings.openInBrowserToManageSub(),
type: "success"
});
return;
}
Linking.openURL("https://play.google.com/store/account/subscriptions");
/**
*
* Platform.OS === 'ios'
? 'https://apps.apple.com/account/subscriptions'
: 'https://play.google.com/store/account/subscriptions'
*/
} else {
eSendEvent(eOpenPremiumDialog);
}
};
function getPrice() {
return Platform.OS === "android"
? monthlyPlan?.product?.subscriptionOfferDetails[0]?.pricingPhases
.pricingPhaseList?.[0]?.formattedPrice
: monthlyPlan?.product?.localizedPrice;
}
return (
<View>
{/* {isNotPro ? (
<Button
height={40}
style={{
borderRadius: 100,
paddingHorizontal: DefaultAppStyles.GAP,
alignSelf: "flex-start"
}}
fontSize={AppFontSize.sm}
type="accent"
onPress={manageSubscription}
title={
!user?.isEmailConfirmed
? strings.confirmEmail()
: user.subscription?.provider === 3 && hasCancelledPremium
? strings.manageSubDesktop()
: hasCancelledPremium &&
Platform.OS === "android" &&
Config.GITHUB_RELEASE !== "true"
? strings.resubFromPlaystore()
: user.subscription?.type ===
SUBSCRIPTION_STATUS.PREMIUM_EXPIRED || hasCancelledPremium
? `${strings.resubToPro()} (${getPrice() || "$4.49"} / mo)`
: `${strings.getPro()} (${getPrice() || "$4.49"} / mo)`
}
/>
) : null} */}
{/* {subscriptionProviderInfo &&
user.subscription?.type !== SUBSCRIPTION_STATUS.PREMIUM_EXPIRED &&
user.subscription?.type !== SUBSCRIPTION_STATUS.BASIC ? (
<Button
title={subscriptionProviderInfo?.title()}
onPress={() => {
presentSheet({
title: subscriptionProviderInfo.title(),
paragraph: subscriptionProviderInfo.desc()
});
}}
style={{
alignSelf: "flex-start",
width: "100%",
paddingHorizontal: 0
}}
fontSize={AppFontSize.xs}
height={30}
type="secondaryAccented"
/>
) : null} */}
</View>
);
};

View File

@@ -18,11 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { formatBytes } from "@notesnook/common";
import {
SubscriptionPlan,
SubscriptionStatus,
SubscriptionType
} from "@notesnook/core";
import { SubscriptionPlan, SubscriptionStatus } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import { useNetInfo } from "@react-native-community/netinfo";
@@ -46,7 +42,6 @@ import { planToDisplayName } from "../../utils/constants";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { SectionItem } from "./section-item";
import { Notice } from "../../components/ui/notice";
export const getTimeLeft = (t2) => {
let daysRemaining = dayjs(t2).diff(dayjs(), "days");
@@ -135,6 +130,8 @@ const SettingsUserSection = ({ item }) => {
const userProfile = useUserStore((state) => state.profile);
const used = user?.storageUsed || 0;
const total = user?.totalStorage || 0;
const subscriptionProviderInfo =
strings.subscriptionProviderInfo[user?.subscription?.provider];
const getSubscriptionStatus = () => {
if (!user) return strings.neverHesitate();
@@ -164,18 +161,6 @@ const SettingsUserSection = ({ item }) => {
: strings.accountDowngradedIn(3)
: strings.neverHesitate();
}
return user.subscription?.type === SubscriptionType.TRIAL
? strings.trialEndsOn(expiryDate)
: user.subscription?.type === SubscriptionType.PREMIUM_EXPIRED
? subscriptionDaysLeft.time < -3
? strings.subEnded()
: strings.accountDowngradedIn(3)
: user.subscription?.type === SubscriptionType.PREMIUM_CANCELED
? strings.subEndsOn(expiryDate)
: user.subscription?.type === SubscriptionType.PREMIUM
? strings.subRenewOn(expiryDate)
: strings.neverHesitate();
};
return (
@@ -185,8 +170,7 @@ const SettingsUserSection = ({ item }) => {
<View
style={{
paddingHorizontal: DefaultAppStyles.GAP,
paddingTop: 25,
paddingBottom: 20
paddingTop: 25
}}
>
<View
@@ -305,8 +289,7 @@ const SettingsUserSection = ({ item }) => {
style={{
paddingVertical: DefaultAppStyles.GAP_SMALL,
gap: DefaultAppStyles.GAP_VERTICAL,
borderRadius: 10,
marginBottom: 10
borderRadius: 10
}}
>
<View
@@ -370,10 +353,7 @@ const SettingsUserSection = ({ item }) => {
}}
>
<Paragraph size={AppFontSize.sm}>
{user.subscription.plan === 0 &&
user.subscription.type === SubscriptionType.PREMIUM
? strings.proPlan()
: planToDisplayName(user.subscription.plan)}
{planToDisplayName(user.subscription.plan)}
</Paragraph>
<Paragraph
color={colors.secondary.paragraph}
@@ -402,14 +382,6 @@ const SettingsUserSection = ({ item }) => {
/>
</View>
</View>
{user.subscription.plan === SubscriptionPlan.FREE ? null : (
<Notice
size="small"
text={getSubscriptionStatus()}
type="information"
/>
)}
</View>
{item.sections.map((item) => (

View File

@@ -17,14 +17,13 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { User } from "@notesnook/core";
import { SubscriptionPlan, SubscriptionStatus, User } from "@notesnook/core";
import { Platform } from "react-native";
import { getVersion } from "react-native-device-info";
import create, { State } from "zustand";
import { db } from "../common/database";
import { MMKV } from "../common/database/mmkv";
import PremiumService from "../services/premium";
import { SUBSCRIPTION_STATUS } from "../utils/constants";
export interface MessageStore extends State {
message: Message;
setMessage: (message: Message) => void;
@@ -168,15 +167,13 @@ async function shouldShowAnnouncement(announcement: Announcement) {
if (!show) return false;
if (!show) return false;
const user = (await db.user?.getUser()) as User;
const subStatus = user?.subscription?.type || SUBSCRIPTION_STATUS.BASIC;
const subStatus = user?.subscription?.status;
show = announcement.userTypes.some((userType) => {
switch (userType) {
case "pro":
return PremiumService.get();
case "trial":
return subStatus === SUBSCRIPTION_STATUS.TRIAL;
case "trialExpired":
return subStatus === SUBSCRIPTION_STATUS.BASIC;
return subStatus === SubscriptionStatus.TRIAL;
case "loggedOut":
return !user;
case "verified":
@@ -185,11 +182,6 @@ async function shouldShowAnnouncement(announcement: Announcement) {
return !!user;
case "unverified":
return !user?.isEmailConfirmed;
case "proExpired":
return (
subStatus === SUBSCRIPTION_STATUS.PREMIUM_EXPIRED ||
subStatus === SUBSCRIPTION_STATUS.PREMIUM_CANCELLED
);
case "any":
default:
return false;

View File

@@ -101,7 +101,8 @@ const EXTRA_ICON_NAMES = [
"format-list-bulleted",
"file-tree",
"github",
"open-source-initiative"
"open-source-initiative",
"credit-card"
];
const __filename = fileURLToPath(import.meta.url);

File diff suppressed because one or more lines are too long