Compare commits

...

1 Commits

Author SHA1 Message Date
ammarahm-ed
c52ce1302a web: add initial support for purchasing via IAP 2022-09-24 09:19:26 +05:00
7 changed files with 130 additions and 5 deletions

View File

@@ -0,0 +1,25 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2022 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/>.
*/
const { inAppPurchase } = require("electron");
module.exports = function (args, win) {
const { productIds } = args;
return inAppPurchase.getProducts(productIds);
};

View File

@@ -19,10 +19,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
const getZoomFactor = require("./getZoomFactor");
const selectDirectory = require("./selectDirectory");
const getProducts = require("./getProducts");
const calls = {
getZoomFactor,
selectDirectory
selectDirectory,
getProducts
};
module.exports.getCall = function getAction(callName) {

View File

@@ -48,6 +48,12 @@ contextBridge.exposeInMainWorld("config", {
return ipcRenderer.invoke("fromRenderer", {
type: "getZoomFactor"
});
},
products: (productIds) => {
return ipcRenderer.invoke("fromRenderer", {
type: "getProducts",
productIds
});
}
});

View File

@@ -0,0 +1,39 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2022 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 { Plan, PricingInfo } from "./types";
import { useEffect } from "react";
type AppleCheckoutProps = {
user: { id: string; email: string };
plan: Plan;
onPriceUpdated?: (pricingInfo: PricingInfo) => void;
onCouponApplied?: () => void;
coupon?: string;
};
export function AppleCheckout(props: AppleCheckoutProps) {
useEffect(() => {
(async function () {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
console.log(window.config, props.plan.id, await window.config.products([props.plan.id]));
})();
}, [props]);
return null;
}

View File

@@ -40,6 +40,7 @@ import { db } from "../../../common/db";
import { useCheckoutStore } from "./store";
import { getCurrencySymbol } from "./helpers";
import { Theme } from "@notesnook/theme";
import { AppleCheckout } from "./apple";
type BuyDialogProps = {
couponCode?: string;
@@ -227,7 +228,7 @@ function Details() {
);
const theme = useThemeStore((store) => store.theme);
if (selectedPlan && user)
if (selectedPlan && user && selectedPlan.platform === "web")
return (
<PaddleCheckout
plan={selectedPlan}
@@ -244,6 +245,28 @@ function Details() {
// pricingInfo.coupon
// );
// if (!initialCouponCode || initialCouponCode === couponCode) return;
// console.log(initialCouponCode, "applying coupon");
// onApplyCoupon(initialCouponCode);
}}
/>
);
else if (selectedPlan && user && selectedPlan.platform === "macos")
return (
<AppleCheckout
plan={selectedPlan}
user={user}
coupon={couponCode}
onCouponApplied={() => setIsApplyingCoupon(true)}
onPriceUpdated={(pricingInfo) => {
onPriceUpdated(pricingInfo);
// console.log(
// initialCouponCode,
// "applying coupon",
// couponCode,
// pricingInfo.coupon
// );
// if (!initialCouponCode || initialCouponCode === couponCode) return;
// console.log(initialCouponCode, "applying coupon");
// onApplyCoupon(initialCouponCode);

View File

@@ -18,8 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { useEffect, useState } from "react";
import { db } from "../../../common/db";
import { isTesting } from "../../../utils/platform";
import { Period, Plan } from "./types";
import { getPlatform } from "../../../utils/platform";
type PlanMetadata = {
title: string;
@@ -33,7 +35,8 @@ export const DEFAULT_PLANS: Plan[] = [
currency: "USD",
discount: 0,
id: "648884",
price: { gross: 4.49, net: 0, tax: 0 }
price: { gross: 4.49, net: 0, tax: 0 },
platform: "web"
},
{
period: "yearly",
@@ -41,7 +44,8 @@ export const DEFAULT_PLANS: Plan[] = [
currency: "USD",
discount: 0,
id: "658759",
price: { gross: 49.99, net: 0, tax: 0 }
price: { gross: 49.99, net: 0, tax: 0 },
platform: "web"
}
];
@@ -52,9 +56,34 @@ export const PLAN_METADATA: Record<Period, PlanMetadata> = {
let CACHED_PLANS: Plan[];
export async function getPlans(): Promise<Plan[] | null> {
return DEFAULT_PLANS;
if (isTesting()) return DEFAULT_PLANS;
if (CACHED_PLANS) return CACHED_PLANS;
if (getPlatform() === "macOS") {
const result = (
await Promise.all(
(["monthly", "yearly"] as const).map(
async (period): Promise<Plan | null> => {
const plan = await db.pricing?.sku("ios", period);
const price = await db.pricing?.price(period);
if (plan && price)
return {
period,
country: plan?.countryCode,
currency: "USD",
id: plan.sku,
discount: price.discount,
price: { gross: parseFloat(price.price), net: 0, tax: 0 },
originalPrice: DEFAULT_PLANS.find((p) => p.period === period)?.price,
platform: "macos"
};
return null;
}
)
)
).filter((p) => !!p);
if (result.length < 2) return DEFAULT_PLANS;
return result as Plan[];
}
const url = `https://notesnook.com/api/v1/prices/products/web`;
const response = await fetch(url);

View File

@@ -94,6 +94,7 @@ export interface Plan {
originalPrice?: Price;
discount: number;
country: string;
platform: "web" | "macos";
}
export type PricingInfo = {