mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-01 19:49:54 +02:00
Compare commits
18 Commits
release/3.
...
mobile/fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04f6e1068b | ||
|
|
9bea4adcf9 | ||
|
|
a5790de23c | ||
|
|
eb4edeea8f | ||
|
|
e3ccd504da | ||
|
|
4627d7d5df | ||
|
|
f216c1b65d | ||
|
|
4692ba7183 | ||
|
|
543825918c | ||
|
|
9f995b861b | ||
|
|
9963a6c655 | ||
|
|
1696ec5c72 | ||
|
|
7c95faad21 | ||
|
|
ca80441c14 | ||
|
|
9c497fd2bb | ||
|
|
ef5e5e5b4c | ||
|
|
ede900fdbd | ||
|
|
1758f03f93 |
51
.github/workflows/desktop.preview.yml
vendored
51
.github/workflows/desktop.preview.yml
vendored
@@ -101,7 +101,6 @@ jobs:
|
||||
|
||||
- name: Build dmg
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CSC_LINK: ${{ secrets.mac_certs }}
|
||||
CSC_KEY_PASSWORD: ${{ secrets.mac_certs_password }}
|
||||
APPLE_API_KEY: ~/private_keys/AuthKey_${{ secrets.api_key_id }}.p8
|
||||
@@ -153,8 +152,6 @@ jobs:
|
||||
run: npm run tx @notesnook/desktop:release
|
||||
|
||||
- name: Build AppImage
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: yarn electron-builder --config=electron-builder.config.js --linux AppImage:x64 -p never
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
@@ -165,6 +162,49 @@ jobs:
|
||||
name: linux-x64-build
|
||||
path: apps/desktop/output/*.AppImage
|
||||
|
||||
build-linux-arm64:
|
||||
name: Build for Linux arm64
|
||||
needs: build
|
||||
runs-on: ubuntu-22.04-arm
|
||||
outputs:
|
||||
linux-arm64-artifact-url: ${{ steps.artifact-upload-step.outputs.artifact-url }}
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
- name: Download build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build
|
||||
path: ./apps/web/build
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=desktop
|
||||
|
||||
- name: Install sqlite-better-trigram for all arch
|
||||
run: |
|
||||
npm i --cpu arm64 sqlite-better-trigram
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Build Electron wrapper
|
||||
run: npm run tx @notesnook/desktop:release
|
||||
|
||||
- name: Build AppImage
|
||||
run: yarn electron-builder --config=electron-builder.config.js --linux AppImage:arm64 -p never
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Upload AppImage artifact
|
||||
id: artifact-upload-step
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux-arm64-build
|
||||
path: apps/desktop/output/*.AppImage
|
||||
|
||||
build-windows:
|
||||
name: Build for Windows
|
||||
needs: build
|
||||
@@ -216,7 +256,8 @@ jobs:
|
||||
|
||||
post-pr-comment:
|
||||
name: Post PR comment with preview URLs
|
||||
needs: [build, build-macos, build-linux-x64, build-windows]
|
||||
needs:
|
||||
[build, build-macos, build-linux-x64, build-linux-arm64, build-windows]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Post or update PR comment
|
||||
@@ -224,6 +265,7 @@ jobs:
|
||||
env:
|
||||
macos_artifact_url: ${{ needs.build-macos.outputs.macos-artifact-url }}
|
||||
linux_x64_artifact_url: ${{ needs.build-linux-x64.outputs.linux-x64-artifact-url }}
|
||||
linux_arm64_artifact_url: ${{ needs.build-linux-arm64.outputs.linux-arm64-artifact-url }}
|
||||
windows_artifact_url: ${{ needs.build-windows.outputs.windows-artifact-url }}
|
||||
with:
|
||||
script: |
|
||||
@@ -232,6 +274,7 @@ jobs:
|
||||
const previewUrl = [
|
||||
{ platform: 'macOS', url: process.env.macos_artifact_url },
|
||||
{ platform: 'Linux x64', url: process.env.linux_x64_artifact_url },
|
||||
{ platform: 'Linux arm64', url: process.env.linux_arm64_artifact_url },
|
||||
{ platform: 'Windows x64', url: process.env.windows_artifact_url },
|
||||
].filter(u => u.url).map(u => `- [${u.platform}](${u.url})`).join('\n');
|
||||
const body = `${marker}\n**Desktop Previews**\n\n${previewUrl || 'Preview URL unavailable — check workflow logs.'}\n\nCommit: ${process.env.GITHUB_SHA}\n`;
|
||||
|
||||
@@ -198,6 +198,9 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
},
|
||||
toolsets: {
|
||||
appimage: "1.0.2"
|
||||
},
|
||||
snap: {
|
||||
autoStart: false,
|
||||
confinement: "strict",
|
||||
|
||||
2128
apps/desktop/package-lock.json
generated
2128
apps/desktop/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -48,7 +48,7 @@
|
||||
"@types/yargs": "^17.0.33",
|
||||
"chokidar": "^4.0.3",
|
||||
"electron": "^37.0.0",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-builder": "^26.8.1",
|
||||
"esbuild": "0.21.5",
|
||||
"node-abi": "^4.5.0",
|
||||
"node-gyp-build": "^4.8.4",
|
||||
|
||||
@@ -178,7 +178,9 @@ export const osIntegrationRouter = t.router({
|
||||
})
|
||||
});
|
||||
notification.show();
|
||||
if (input.urgency === "critical") {
|
||||
if (input.urgency === "critical" && process.platform !== "linux") {
|
||||
// due to an Electron bug in versions below 40.x, shell.beep() causes a segfault on Linux.
|
||||
// TODO: Remove when migrating to Electron 40.x or newer.
|
||||
shell.beep();
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ android {
|
||||
if (project.hasProperty("prBuildNumber")) {
|
||||
versionCode Integer.parseInt(prBuildNumber())
|
||||
} else {
|
||||
versionCode 3099
|
||||
versionCode 3100
|
||||
}
|
||||
versionName getNpmVersion()
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
- Fix clearing note title adds generated title instead of staying empty
|
||||
- Improved table cell selection, table scrolling, and table cell editing on mobile
|
||||
- Fixed app on launch randomly focuses editor instead of notes list
|
||||
- Fixed file size check shows error but continues adding the file to editor
|
||||
- Note title headline format should get content from first paragraph
|
||||
- Minor bug fixes and performance improvements
|
||||
- Bug fixes and improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
Thank you for using Notesnook!
|
||||
@@ -194,6 +194,7 @@ export const VaultDialog: React.FC = () => {
|
||||
close();
|
||||
}, 100);
|
||||
} else {
|
||||
setLoading(false);
|
||||
ToastManager.show({
|
||||
heading: strings.passwordIncorrect(),
|
||||
type: "error",
|
||||
@@ -227,6 +228,10 @@ export const VaultDialog: React.FC = () => {
|
||||
setLoading(false);
|
||||
close();
|
||||
eSendEvent("vaultUpdated");
|
||||
ToastManager.show({
|
||||
message: strings.vaultCleared(),
|
||||
type: "success"
|
||||
});
|
||||
} catch (e) {
|
||||
ToastManager.show({
|
||||
heading: strings.passwordIncorrect(),
|
||||
@@ -741,7 +746,8 @@ export const VaultDialog: React.FC = () => {
|
||||
width: DDS.isTab ? 350 : "85%",
|
||||
borderRadius: 10,
|
||||
backgroundColor: colors.primary.background,
|
||||
paddingTop: 12
|
||||
paddingTop: 12,
|
||||
overflow: "hidden"
|
||||
}}
|
||||
>
|
||||
<DialogHeader
|
||||
@@ -808,7 +814,8 @@ export const VaultDialog: React.FC = () => {
|
||||
!isBiometryAvailable ||
|
||||
isCreateVault ||
|
||||
isChangePassword ||
|
||||
isCustomAction ? null : (
|
||||
isCustomAction ||
|
||||
isDeleteVault ? null : (
|
||||
<Button
|
||||
onPress={() =>
|
||||
onPressFingerprintAuth(strings.unlockNote(), "")
|
||||
|
||||
@@ -76,7 +76,9 @@ const MergeConflicts = () => {
|
||||
const applyChanges = async () => {
|
||||
const contentToSave = selectedContent;
|
||||
if (!contentToSave) return;
|
||||
const note = await db.notes.note(contentToSave.noteId);
|
||||
const note = await db.notes.note(
|
||||
(content.current as UnencryptedContentItem).noteId
|
||||
);
|
||||
if (!note) return;
|
||||
await db.notes.add({
|
||||
id: note.id,
|
||||
|
||||
@@ -18,13 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { getFeaturesTable } from "@notesnook/common";
|
||||
import {
|
||||
EVENTS,
|
||||
Plan,
|
||||
SKUResponse,
|
||||
SubscriptionPlan,
|
||||
User
|
||||
} from "@notesnook/core";
|
||||
import { EVENTS, Plan, SubscriptionPlan, User } from "@notesnook/core";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { useEffect, useState } from "react";
|
||||
@@ -54,6 +48,7 @@ import {
|
||||
TECHLORE_SVG,
|
||||
XDA_SVG
|
||||
} from "../../assets/images/assets";
|
||||
import { db } from "../../common/database";
|
||||
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
|
||||
import usePricingPlans, {
|
||||
PlanOverView,
|
||||
@@ -75,7 +70,6 @@ import { IconButton } from "../ui/icon-button";
|
||||
import { SvgView } from "../ui/svg";
|
||||
import Heading from "../ui/typography/heading";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
import { db } from "../../common/database";
|
||||
|
||||
const Steps = {
|
||||
select: 1,
|
||||
@@ -935,7 +929,10 @@ const PricingPlanCard = ({
|
||||
setStep: (step: number) => void;
|
||||
}) => {
|
||||
const { colors } = useThemeColors();
|
||||
const [regionalDiscount, setRegionaDiscount] = useState<SKUResponse>();
|
||||
const regionalDiscount =
|
||||
annualBilling && plan.id === "pro"
|
||||
? pricingPlans?.regionalDiscount
|
||||
: undefined;
|
||||
const { width } = useWindowDimensions();
|
||||
const isTablet = width > 600;
|
||||
|
||||
@@ -958,26 +955,6 @@ const PricingPlanCard = ({
|
||||
annualBilling
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (pricingPlans?.isGithubRelease || !annualBilling) return;
|
||||
pricingPlans
|
||||
?.getRegionalDiscount(
|
||||
plan.id,
|
||||
pricingPlans.isGithubRelease
|
||||
? (WebPlan?.period as string)
|
||||
: `notesnook.${plan.id}.${annualBilling ? "yearly" : "monthly"}`
|
||||
)
|
||||
.then((value) => {
|
||||
setRegionaDiscount(value);
|
||||
});
|
||||
}, [WebPlan?.period, annualBilling, plan.id, pricingPlans]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!annualBilling) {
|
||||
setRegionaDiscount(undefined);
|
||||
}
|
||||
}, [annualBilling]);
|
||||
|
||||
const isSubscribed =
|
||||
product?.productId &&
|
||||
pricingPlans?.user?.subscription?.productId?.includes(plan.id) &&
|
||||
|
||||
@@ -16,11 +16,11 @@ 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, SKUResponse } from "@notesnook/core";
|
||||
import { Plan } from "@notesnook/core";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import dayjs from "dayjs";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
Linking,
|
||||
Platform,
|
||||
@@ -330,7 +330,10 @@ const ProductItem = (props: {
|
||||
productId: string;
|
||||
}) => {
|
||||
const { colors } = useThemeColors();
|
||||
const [regionalDiscount, setRegionaDiscount] = useState<SKUResponse>();
|
||||
const regionalDiscount =
|
||||
props.productId === "notesnook.pro.yearly"
|
||||
? props.pricingPlans.regionalDiscount
|
||||
: undefined;
|
||||
const product =
|
||||
props.pricingPlans?.currentPlan?.subscriptions?.[
|
||||
regionalDiscount?.sku || props.productId
|
||||
@@ -367,30 +370,6 @@ const ProductItem = (props: {
|
||||
props.pricingPlans.user?.subscription?.productId ===
|
||||
(product as Plan)?.id);
|
||||
|
||||
useEffect(() => {
|
||||
if (product) {
|
||||
props.pricingPlans
|
||||
?.getRegionalDiscount(
|
||||
props.pricingPlans.currentPlan?.id as string,
|
||||
props.pricingPlans.isGithubRelease
|
||||
? ((product as Plan)?.period as string)
|
||||
: props.productId
|
||||
)
|
||||
.then((value) => {
|
||||
if (
|
||||
value &&
|
||||
value.sku?.startsWith(
|
||||
(props.pricingPlans.selectedProduct as RNIap.Subscription)
|
||||
?.productId
|
||||
)
|
||||
) {
|
||||
props.pricingPlans.selectProduct(value?.sku as string);
|
||||
}
|
||||
setRegionaDiscount(value);
|
||||
});
|
||||
}
|
||||
}, [product, props.pricingPlans, props.productId]);
|
||||
|
||||
const discountValue =
|
||||
(isAnnual && !isGithubRelease) ||
|
||||
(isGithubRelease && (product as Plan)?.discount?.amount)
|
||||
|
||||
@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import { useAreFeaturesAvailable } from "@notesnook/common";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { View } from "react-native";
|
||||
import {
|
||||
eSendEvent,
|
||||
@@ -28,7 +28,11 @@ import {
|
||||
ToastManager
|
||||
} from "../../../services/event-manager";
|
||||
import SettingsService from "../../../services/settings";
|
||||
import { eAfterSync, eCloseSheet } from "../../../utils/events";
|
||||
import {
|
||||
eAfterSync,
|
||||
eCloseSheet,
|
||||
eMenuItemUpdate
|
||||
} from "../../../utils/events";
|
||||
import { SideMenuItem } from "../../../utils/menu-items";
|
||||
import { AppFontSize } from "../../../utils/size";
|
||||
import { DefaultAppStyles } from "../../../utils/styles";
|
||||
@@ -40,14 +44,22 @@ import PaywallSheet from "../paywall";
|
||||
import { presentDialog } from "../../dialog/functions";
|
||||
import { db } from "../../../common/database";
|
||||
import { useTrashStore } from "../../../stores/use-trash-store";
|
||||
import { useSettingStore } from "../../../stores/use-setting-store";
|
||||
export const MenuItemProperties = ({ item }: { item: SideMenuItem }) => {
|
||||
const { colors } = useThemeColors();
|
||||
const featuresAvailable = useAreFeaturesAvailable([
|
||||
"customHomepage",
|
||||
"customizableSidebar"
|
||||
]);
|
||||
const isAppLoading = useSettingStore((state) => state.isAppLoading);
|
||||
const trash = useTrashStore((state) => state.items);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAppLoading) {
|
||||
useTrashStore.getState().refresh();
|
||||
}
|
||||
}, [isAppLoading]);
|
||||
|
||||
return !featuresAvailable ? null : (
|
||||
<View
|
||||
style={{
|
||||
@@ -121,6 +133,7 @@ export const MenuItemProperties = ({ item }: { item: SideMenuItem }) => {
|
||||
positivePress: async () => {
|
||||
await db.trash.clear();
|
||||
useTrashStore.getState().clear();
|
||||
eSendEvent(eMenuItemUpdate);
|
||||
eSendEvent(eAfterSync);
|
||||
ToastManager.show({
|
||||
message: strings.trashCleared(),
|
||||
|
||||
@@ -71,7 +71,7 @@ export function MenuItem({
|
||||
if (item.data) {
|
||||
getTotalNotesRef.current([item.data?.id]);
|
||||
}
|
||||
}, [update]);
|
||||
}, [item.data, update]);
|
||||
|
||||
useEffect(() => {
|
||||
const onSyncComplete = async () => {
|
||||
@@ -94,7 +94,9 @@ export function MenuItem({
|
||||
setItemCount(await db.notes.archived.count());
|
||||
break;
|
||||
case "Trash":
|
||||
setItemCount((await db.trash.all()).length);
|
||||
{
|
||||
setItemCount((await db.trash.all()).length);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -38,10 +38,10 @@ import {
|
||||
import { getElevationStyle } from "../../utils/elevation";
|
||||
import { eHideToast, eShowToast } from "../../utils/events";
|
||||
import { AppFontSize, defaultBorderRadius } from "../../utils/size";
|
||||
import { DefaultAppStyles } from "../../utils/styles";
|
||||
import { Button } from "../ui/button";
|
||||
import Heading from "../ui/typography/heading";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
import { DefaultAppStyles } from "../../utils/styles";
|
||||
|
||||
export const Toast = ({ context = "global" }) => {
|
||||
const { colors, isDark } = useThemeColors();
|
||||
@@ -119,10 +119,7 @@ export const Toast = ({ context = "global" }) => {
|
||||
width: DDS.isTab ? dimensions.width / 2 : "100%",
|
||||
alignItems: "center",
|
||||
alignSelf: "center",
|
||||
bottom:
|
||||
insets.bottom +
|
||||
15 +
|
||||
(keyboard.keyboardShown ? Math.max(0, keyboard.keyboardHeight) : 0),
|
||||
bottom: insets.bottom + 15,
|
||||
position: "absolute",
|
||||
zIndex: 999,
|
||||
elevation: 15
|
||||
|
||||
@@ -37,11 +37,10 @@ export default function useFeatureManager() {
|
||||
"disableTrashCleanup",
|
||||
"fullOfflineMode"
|
||||
]);
|
||||
const user = useUserStore((state) => state.user);
|
||||
const plan = useUserStore((state) => state.user?.subscription?.plan);
|
||||
|
||||
useEffect(() => {
|
||||
if (!user || !features) return;
|
||||
if (!useUserStore.getState().user || !features) return;
|
||||
|
||||
if (!features.createNoteFromNotificationDrawer.isAllowed) {
|
||||
SettingsService.setProperty("notifNotes", false);
|
||||
@@ -82,7 +81,8 @@ export default function useFeatureManager() {
|
||||
db.settings.setDefaultTag(undefined);
|
||||
}
|
||||
}
|
||||
}, [features, plan, user]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [features, plan]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -16,16 +16,17 @@ 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, SubscriptionPlan, SubscriptionPlanId } from "@notesnook/core";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Plan, SubscriptionPlan } from "@notesnook/core";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useAsync } from "react-async-hook";
|
||||
import { Platform } from "react-native";
|
||||
import Config from "react-native-config";
|
||||
import * as RNIap from "react-native-iap";
|
||||
import { DatabaseLogger, db } from "../common/database";
|
||||
import PremiumService from "../services/premium";
|
||||
import SettingsService from "../services/settings";
|
||||
import { useSettingStore } from "../stores/use-setting-store";
|
||||
import { useUserStore } from "../stores/use-user-store";
|
||||
import SettingsService from "../services/settings";
|
||||
function numberWithCommas(x: string) {
|
||||
const parts = x.toString().split(".");
|
||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
@@ -155,9 +156,18 @@ const planIdToIndex = (planId: string) => {
|
||||
return planIndex;
|
||||
};
|
||||
let WebPlanCache: Plan[];
|
||||
const isGithubRelease = Config.GITHUB_RELEASE === "true";
|
||||
const usePricingPlans = (options?: PricingPlansOptions) => {
|
||||
const isGithubRelease = Config.GITHUB_RELEASE === "true";
|
||||
const user = useUserStore((state) => state.user);
|
||||
const regionalDiscount = useAsync(
|
||||
() =>
|
||||
db.pricing.sku(
|
||||
Platform.OS === "android" ? "google" : "apple",
|
||||
"yearly",
|
||||
"pro"
|
||||
),
|
||||
[]
|
||||
);
|
||||
const [currentPlan, setCurrentPlan] = useState<string>(
|
||||
options?.planId || pricingPlans[2].id
|
||||
);
|
||||
@@ -172,17 +182,20 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
|
||||
const [userCanRequestTrial, setUserCanRequestTrial] = useState(false);
|
||||
const [webPricingPlans, setWebPricingPlans] = useState<Plan[]>([]);
|
||||
|
||||
const getProduct = (planId: string, skuId: string) => {
|
||||
if (isGithubRelease)
|
||||
return webPricingPlans.find(
|
||||
(plan) => planIdToIndex(planId) === plan.plan && skuId === plan.period
|
||||
);
|
||||
const getProduct = React.useCallback(
|
||||
(planId: string, skuId: string) => {
|
||||
if (isGithubRelease)
|
||||
return webPricingPlans.find(
|
||||
(plan) => planIdToIndex(planId) === plan.plan && skuId === plan.period
|
||||
);
|
||||
|
||||
return (
|
||||
plans.find((p) => p.id === planId)?.subscriptions?.[skuId] ||
|
||||
plans.find((p) => p.id === planId)?.products?.[skuId]
|
||||
);
|
||||
};
|
||||
return (
|
||||
plans.find((p) => p.id === planId)?.subscriptions?.[skuId] ||
|
||||
plans.find((p) => p.id === planId)?.products?.[skuId]
|
||||
);
|
||||
},
|
||||
[plans, webPricingPlans]
|
||||
);
|
||||
|
||||
const getProductAndroid = (planId: string, skuId: string) => {
|
||||
if (isGithubRelease)
|
||||
@@ -196,37 +209,45 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
|
||||
return getProduct(planId, skuId) as RNIap.SubscriptionIOS;
|
||||
};
|
||||
|
||||
const hasTrialOffer = (planId?: string, productId?: string) => {
|
||||
if (!selectedProductSku && !productId) return false;
|
||||
const hasTrialOffer = React.useCallback(
|
||||
(planId?: string, productId?: string) => {
|
||||
if (!selectedProductSku && !productId) return false;
|
||||
|
||||
if (productId?.includes("5year")) return false;
|
||||
if (isGithubRelease) {
|
||||
if (
|
||||
user?.subscription?.trialsAvailed?.some(
|
||||
(plan) => plan === planIdToIndex(planId || currentPlan)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
if (productId?.includes("5year")) return false;
|
||||
if (isGithubRelease) {
|
||||
if (
|
||||
user?.subscription?.trialsAvailed?.some(
|
||||
(plan) => plan === planIdToIndex(planId || currentPlan)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Platform.OS === "ios"
|
||||
? (
|
||||
getProduct(
|
||||
planId || currentPlan,
|
||||
productId || selectedProductSku
|
||||
) as RNIap.SubscriptionIOS
|
||||
)?.introductoryPricePaymentModeIOS === "FREETRIAL"
|
||||
: (
|
||||
getProduct(
|
||||
planId || currentPlan,
|
||||
productId || selectedProductSku
|
||||
) as RNIap.SubscriptionAndroid
|
||||
)?.subscriptionOfferDetails?.[0]?.pricingPhases?.pricingPhaseList
|
||||
?.length > 1;
|
||||
};
|
||||
return Platform.OS === "ios"
|
||||
? (
|
||||
getProduct(
|
||||
planId || currentPlan,
|
||||
productId || selectedProductSku
|
||||
) as RNIap.SubscriptionIOS
|
||||
)?.introductoryPricePaymentModeIOS === "FREETRIAL"
|
||||
: (
|
||||
getProduct(
|
||||
planId || currentPlan,
|
||||
productId || selectedProductSku
|
||||
) as RNIap.SubscriptionAndroid
|
||||
)?.subscriptionOfferDetails?.[0]?.pricingPhases?.pricingPhaseList
|
||||
?.length > 1;
|
||||
},
|
||||
[
|
||||
currentPlan,
|
||||
getProduct,
|
||||
selectedProductSku,
|
||||
user?.subscription?.trialsAvailed
|
||||
]
|
||||
);
|
||||
|
||||
// user && (!user.subscription || !user.subscription.expiry) ? true : false;
|
||||
|
||||
@@ -649,21 +670,6 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
|
||||
);
|
||||
};
|
||||
|
||||
async function getRegionalDiscount(plan: string, productId: string) {
|
||||
if (productId !== "notesnook.pro.yearly") {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
return await db.pricing.sku(
|
||||
Platform.OS === "android" ? "google" : "apple",
|
||||
"yearly",
|
||||
plan as SubscriptionPlanId
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
function isSubscribedToPlan(planId: string) {
|
||||
if (!PremiumService.get()) return false;
|
||||
return user?.subscription?.productId?.includes(planId);
|
||||
@@ -734,7 +740,7 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
|
||||
(plan) => plan.plan === planIndex && plan.period === period
|
||||
);
|
||||
},
|
||||
getRegionalDiscount,
|
||||
regionalDiscount: regionalDiscount.result,
|
||||
isGithubRelease: isGithubRelease,
|
||||
isSubscribed: () => user?.subscription?.plan !== SubscriptionPlan.FREE,
|
||||
finish: () => options?.onBuy?.()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Production iOS build identifiers
|
||||
IOS_CURRENT_PROJECT_VERSION = 2179
|
||||
IOS_MARKETING_VERSION = 3.3.19
|
||||
IOS_CURRENT_PROJECT_VERSION = 2180
|
||||
IOS_MARKETING_VERSION = 3.3.20
|
||||
IOS_MAIN_BUNDLE_ID = org.streetwriters.notesnook
|
||||
IOS_WIDGET_BUNDLE_ID = org.streetwriters.notesnook.notewidget
|
||||
IOS_SHARE_BUNDLE_ID = org.streetwriters.notesnook.share
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Production iOS build identifiers
|
||||
IOS_CURRENT_PROJECT_VERSION = 2179
|
||||
IOS_MARKETING_VERSION = 3.3.19
|
||||
IOS_CURRENT_PROJECT_VERSION = 2180
|
||||
IOS_MARKETING_VERSION = 3.3.20
|
||||
IOS_MAIN_BUNDLE_ID = org.streetwriters.notesnook
|
||||
IOS_WIDGET_BUNDLE_ID = org.streetwriters.notesnook.notewidget
|
||||
IOS_SHARE_BUNDLE_ID = org.streetwriters.notesnook.share
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Staging iOS build identifiers
|
||||
IOS_CURRENT_PROJECT_VERSION = 2179
|
||||
IOS_MARKETING_VERSION = 3.3.19
|
||||
IOS_CURRENT_PROJECT_VERSION = 2180
|
||||
IOS_MARKETING_VERSION = 3.3.20
|
||||
IOS_MAIN_BUNDLE_ID = org.streetwriters.notesnook
|
||||
IOS_WIDGET_BUNDLE_ID = org.streetwriters.notesnook.notewidget
|
||||
IOS_SHARE_BUNDLE_ID = org.streetwriters.notesnook.share
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "3.3.19",
|
||||
"version": "3.3.20",
|
||||
"private": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"scripts": {
|
||||
@@ -202,4 +202,4 @@
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -324,6 +324,7 @@ function GroupHeader(props: GroupHeaderProps) {
|
||||
cursor: "pointer",
|
||||
px: 1,
|
||||
py: 1,
|
||||
pr: 2,
|
||||
borderBottom: "1px solid var(--border)",
|
||||
// border: isMenuTarget ? "1px solid" : "none",
|
||||
// borderColor: isMenuTarget ? "accent" : "transparent",
|
||||
|
||||
@@ -55,6 +55,8 @@ export const CustomScrollbarsVirtualList = forwardRef<
|
||||
return (
|
||||
<ScrollContainer
|
||||
{...props}
|
||||
trackStyle={() => ({ width: 6 })}
|
||||
thumbStyle={() => ({ width: 6 })}
|
||||
forwardedRef={(sRef) => {
|
||||
if (typeof ref === "function") ref(sRef);
|
||||
else if (ref) ref.current = sRef;
|
||||
|
||||
@@ -148,6 +148,7 @@ function ListItem<TItem extends Item, TContext>(
|
||||
sx={{
|
||||
px: 1,
|
||||
py: isCompact ? 0 : 1,
|
||||
pr: isCompact ? 10 : 0,
|
||||
height: isCompact ? 25 : "inherit",
|
||||
cursor: "pointer",
|
||||
position: "relative",
|
||||
|
||||
@@ -713,7 +713,7 @@ function colorsToMenuItems(
|
||||
const isChecked = !!noteColor && noteColor.id === color.id;
|
||||
return {
|
||||
type: "button",
|
||||
key: color.title,
|
||||
key: color.id,
|
||||
title: color.title,
|
||||
icon: Circle.path,
|
||||
styles: { icon: { color: color.colorCode } },
|
||||
|
||||
@@ -68,13 +68,23 @@ export function getWindowControls(
|
||||
];
|
||||
}
|
||||
export const TITLE_BAR_HEIGHT = 37;
|
||||
export function TitleBar({ isUnderlay = isMac() }: { isUnderlay?: boolean }) {
|
||||
export function TitleBar({
|
||||
isUnderlay = isMac(),
|
||||
force = false
|
||||
}: {
|
||||
isUnderlay?: boolean;
|
||||
force?: boolean;
|
||||
}) {
|
||||
const { isFullscreen, hasNativeWindowControls, isMaximized } =
|
||||
useWindowControls();
|
||||
const isTablet = useTablet();
|
||||
const isMobile = useMobile();
|
||||
if ((!isMac() && !isMobile && !isTablet) || (isFullscreen && isMac()))
|
||||
if (
|
||||
!force &&
|
||||
((!isMac() && !isMobile && !isTablet) || (isFullscreen && isMac()))
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tools = getWindowControls(
|
||||
hasNativeWindowControls,
|
||||
|
||||
@@ -128,7 +128,10 @@ export function PaddleCheckout(props: PaddleCheckoutProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!callback_data.data || SUBSCRIBED_EVENTS.indexOf(event_name) === -1) {
|
||||
if (
|
||||
!callback_data?.data ||
|
||||
SUBSCRIBED_EVENTS.indexOf(event_name) === -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ export interface Checkout {
|
||||
export type PaddleEvent = {
|
||||
action: "event";
|
||||
event_name: CheckoutEventNames;
|
||||
callback_data: PaddleEventData;
|
||||
callback_data?: PaddleEventData;
|
||||
};
|
||||
|
||||
export type PlanMetadata = Record<
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
import { desktop } from "./common/desktop-bridge";
|
||||
import { useKeyStore } from "./interfaces/key-store";
|
||||
import { usePromise } from "@notesnook/common";
|
||||
import { AuthProps } from "./views/auth";
|
||||
import { AuthProps, isAuthRouteActive } from "./views/auth";
|
||||
import { loadDatabase } from "./hooks/use-database";
|
||||
import AppLock from "./views/app-lock";
|
||||
import { Text } from "@theme-ui/components";
|
||||
@@ -57,7 +57,7 @@ export async function startApp(children?: React.ReactNode) {
|
||||
|
||||
root.render(
|
||||
<>
|
||||
<TitleBar />
|
||||
<TitleBar force={isAuthRouteActive()} />
|
||||
<ErrorBoundary>
|
||||
<GlobalErrorHandler>
|
||||
<BaseThemeProvider
|
||||
|
||||
@@ -30,7 +30,12 @@ import {
|
||||
Warn
|
||||
} from "../components/icons";
|
||||
import Field, { FieldProps } from "../components/field";
|
||||
import { getQueryParams, hardNavigate, makeURL } from "../navigation";
|
||||
import {
|
||||
getCurrentPath,
|
||||
getQueryParams,
|
||||
hardNavigate,
|
||||
makeURL
|
||||
} from "../navigation";
|
||||
import { store as userstore } from "../stores/user-store";
|
||||
import { db } from "../common/db";
|
||||
import Config from "../utils/config";
|
||||
@@ -163,6 +168,11 @@ const routePaths: Record<AuthRoutes, string> = {
|
||||
signup: "/signup"
|
||||
};
|
||||
|
||||
export function isAuthRouteActive() {
|
||||
const path = getCurrentPath();
|
||||
return Object.values(routePaths).includes(path);
|
||||
}
|
||||
|
||||
const authorizedRoutes: AuthRoutes[] = [
|
||||
"login:email",
|
||||
"login:password",
|
||||
|
||||
3
fastlane/metadata/android/en-US/changelogs/15504.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/15504.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- Bug fixes and improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
@@ -1,6 +1,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"POT-Creation-Date: 2025-09-22 09:18+0500\n"
|
||||
"POT-Creation-Date: 2026-04-20 11:33+0500\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"POT-Creation-Date: 2025-09-22 09:18+0500\n"
|
||||
"POT-Creation-Date: 2026-04-20 11:33+0500\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
@@ -626,7 +626,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1008
|
||||
msgid "2FA code sent via {method}"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2585
|
||||
msgid "5 year plan (One time purchase)"
|
||||
@@ -738,7 +738,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2245
|
||||
msgid "Add to dictionary"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2618
|
||||
msgid "Add to home"
|
||||
@@ -754,7 +754,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:975
|
||||
msgid "Add your first notebook"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2621
|
||||
msgid "Adjust the line height of the editor"
|
||||
@@ -846,7 +846,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:250
|
||||
msgid "An error occurred while migrating your data. You can logout of your account and try to relogin. However this is not recommended as it may result in some data loss if your data was not synced."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2579
|
||||
msgid "and"
|
||||
@@ -866,7 +866,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1397
|
||||
msgid "and we will manually confirm your account."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2596
|
||||
msgid "ANNOUNCEMENT"
|
||||
@@ -1108,7 +1108,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2155
|
||||
msgid "Available on iOS & Android"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2644
|
||||
msgid "Back"
|
||||
@@ -1204,7 +1204,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2472
|
||||
msgid "Believer plan"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2582
|
||||
msgid "Best value"
|
||||
@@ -1268,7 +1268,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:405
|
||||
msgid "By"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2577
|
||||
msgid "By joining you agree to our"
|
||||
@@ -1288,7 +1288,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:549
|
||||
msgid "Cancel"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2575
|
||||
msgid "Cancel anytime, subscription auto-renews."
|
||||
@@ -1377,7 +1377,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:434
|
||||
msgid "Change password"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2589
|
||||
msgid "Change plan"
|
||||
@@ -1489,7 +1489,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1133
|
||||
msgid "Choose how dates are displayed in the app"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2624
|
||||
msgid "Choose how day is displayed in the app"
|
||||
@@ -1505,7 +1505,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:402
|
||||
msgid "Choose how you want to secure your notes locally."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2629
|
||||
msgid "Choose what day to display as the first day of the week"
|
||||
@@ -1588,7 +1588,7 @@ msgid ""
|
||||
"---\n"
|
||||
"\n"
|
||||
"**Only use this for troubleshooting purposes. If you are having persistent issues, it is recommended that you reach out to us via support@streetwriters.co so we can help you resolve it permanently.**"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2229
|
||||
msgid "Clearing trash will permanently delete all the items in your trash. This action is IRREVERSIBLE."
|
||||
@@ -1612,7 +1612,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2393
|
||||
msgid "Click to reset {title}"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2619
|
||||
msgid "Click to save"
|
||||
@@ -1761,7 +1761,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1487
|
||||
msgid "Confirm pin"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2643
|
||||
msgid "Confirmation email sent"
|
||||
@@ -2048,7 +2048,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1841
|
||||
msgid "Day"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2623
|
||||
msgid "Day format"
|
||||
@@ -2133,7 +2133,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2293
|
||||
msgid "Delete column"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2640
|
||||
msgid "Delete data"
|
||||
@@ -2390,7 +2390,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1777
|
||||
msgid "Edit"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2630
|
||||
msgid "Edit creation date"
|
||||
@@ -2420,7 +2420,7 @@ msgstr ""
|
||||
#: src/strings.ts:1142
|
||||
#: src/strings.ts:1526
|
||||
msgid "Editor"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2586
|
||||
msgid "Education plan"
|
||||
@@ -2608,7 +2608,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:120
|
||||
msgid "Enter the recovery code to continue logging in"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2622
|
||||
msgid "Enter title"
|
||||
@@ -2704,7 +2704,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2072
|
||||
msgid "Experience the next level of private note taking\""
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2636
|
||||
msgid "Expiry date"
|
||||
@@ -2733,7 +2733,7 @@ msgstr ""
|
||||
#. placeholder {0}: format ? " " + format : ""
|
||||
#: src/strings.ts:2035
|
||||
msgid "Export as{0}"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2637
|
||||
msgid "Export CSV"
|
||||
@@ -2761,7 +2761,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2404
|
||||
msgid "Failed"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2641
|
||||
msgid "Failed to attach file"
|
||||
@@ -2898,7 +2898,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1833
|
||||
msgid "Filter languages"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2608
|
||||
msgid "Finish your purchase in the browser."
|
||||
@@ -3081,7 +3081,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2162
|
||||
msgid "GNU GENERAL PUBLIC LICENSE Version 3"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2609
|
||||
msgid "Go back"
|
||||
@@ -3125,7 +3125,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2539
|
||||
msgid "Google will remind you 2 days before your trial ends."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:586
|
||||
msgid "Got it"
|
||||
@@ -3339,7 +3339,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1751
|
||||
msgid "Import completed"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2638
|
||||
msgid "Import CSV"
|
||||
@@ -3427,7 +3427,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1482
|
||||
msgid "Invalid email"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2646
|
||||
msgid "Invalid recovery key. Make sure to input your account recovery key, not a 2FA recovery code."
|
||||
@@ -3577,7 +3577,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2357
|
||||
msgid "Line {line}, Column {column}"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2620
|
||||
msgid "Line height"
|
||||
@@ -3750,7 +3750,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1362
|
||||
msgid "Login to encrypt and sync notes"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2613
|
||||
msgid "Login to upload attachments. [Read more](https://help.notesnook.com/faqs/login-to-upload-attachments)"
|
||||
@@ -4148,7 +4148,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:202
|
||||
msgid "No one can view this {type} except you."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2616
|
||||
msgid "No password"
|
||||
@@ -4285,7 +4285,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2543
|
||||
msgid "Notesnook"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2601
|
||||
msgid "Notesnook Circle"
|
||||
@@ -4580,7 +4580,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:523
|
||||
msgid "Pinned"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2583
|
||||
msgid "Plan limits"
|
||||
@@ -4844,7 +4844,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1180
|
||||
msgid "Privacy mode"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2578
|
||||
msgid "privacy policy"
|
||||
@@ -4916,7 +4916,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:487
|
||||
msgid "Publish note"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2617
|
||||
msgid "Publish to the web"
|
||||
@@ -4940,7 +4940,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:271
|
||||
msgid "Published note link will be automatically deleted once it is viewed by someone."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2571
|
||||
msgid "Purchase"
|
||||
@@ -5080,7 +5080,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2436
|
||||
msgid "Redeem"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2600
|
||||
msgid "Redeem code"
|
||||
@@ -5856,7 +5856,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1333
|
||||
msgid "Set automatic trash cleanup interval from Settings > Behaviour > Clean trash interval."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2634
|
||||
msgid "Set expiry"
|
||||
@@ -6046,7 +6046,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2355
|
||||
msgid "Spaces"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2593
|
||||
msgid "Special Offer"
|
||||
@@ -6126,7 +6126,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:580
|
||||
msgid "Submit"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2572
|
||||
msgid "Subscribe"
|
||||
@@ -6382,7 +6382,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:102
|
||||
msgid "Terms of Service "
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2580
|
||||
msgid "terms of use."
|
||||
@@ -6414,7 +6414,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2551
|
||||
msgid "Thank you for subscribing"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2588
|
||||
msgid "Thank you for the purchase"
|
||||
@@ -6430,7 +6430,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1643
|
||||
msgid "The {title} at {url} is not compatible with this client."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2633
|
||||
msgid "The incoming note could not be unlocked with the provided password. Enter the correct password for the incoming note"
|
||||
@@ -6438,7 +6438,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:231
|
||||
msgid "The information above will be publically available at"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2607
|
||||
msgid "The Notesnook Circle is exclusive to subscribers. Please consider subscribing to gain access to Notesnook Circle and enjoy additional benefits."
|
||||
@@ -6518,7 +6518,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1934
|
||||
msgid "This image cannot be previewed"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2574
|
||||
msgid "This is a one time purchase, no subscription."
|
||||
@@ -6531,7 +6531,7 @@ msgstr ""
|
||||
#: src/strings.ts:1101
|
||||
#: src/strings.ts:1110
|
||||
msgid "This must only be used for troubleshooting. Using it regularly for sync is not recommended and will lead to unexpected data loss and other issues. If you are having persistent issues with sync, please report them to us at support@streetwriters.co."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2639
|
||||
msgid "This note is empty"
|
||||
@@ -6725,7 +6725,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:854
|
||||
msgid "Unfavorite"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2584
|
||||
msgid "Unlimited"
|
||||
@@ -6741,7 +6741,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:157
|
||||
msgid "Unlock"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2631
|
||||
msgid "Unlock incoming note"
|
||||
@@ -6758,7 +6758,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:888
|
||||
msgid "Unlock note to delete it"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2642
|
||||
msgid "Unlock note to merge conflicts"
|
||||
@@ -6810,7 +6810,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2086
|
||||
msgid "Unregister"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2635
|
||||
msgid "Unset expiry"
|
||||
@@ -6859,7 +6859,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:749
|
||||
msgid "Upgrade to Pro"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2599
|
||||
msgid "Upgrade to redeem"
|
||||
@@ -7090,7 +7090,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1062
|
||||
msgid "View your recovery codes to recover your account in case you lose access to your two-factor authentication methods."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2614
|
||||
msgid "Views"
|
||||
@@ -7158,7 +7158,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:664
|
||||
msgid "Week"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2627
|
||||
msgid "Week format"
|
||||
@@ -7175,7 +7175,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1888
|
||||
msgid "Welcome back!"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2587
|
||||
msgid "Welcome to Notesnook {plan}"
|
||||
@@ -7252,7 +7252,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:106
|
||||
msgid "You also agree to recieve marketing emails from us which you can opt-out of from app settings."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2592
|
||||
msgid "You are already subscribed to this plan."
|
||||
@@ -7284,7 +7284,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2064
|
||||
msgid "You can change the theme at any time from Settings or the side menu."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2595
|
||||
msgid "You can change your subscription plan from the web app"
|
||||
@@ -7349,7 +7349,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2192
|
||||
msgid "You have been logged out."
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2591
|
||||
msgid "You have made a one time purchase. To change your plan please contact support."
|
||||
@@ -7470,7 +7470,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2099
|
||||
msgid "Your current 2FA method is {method}"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2598
|
||||
msgid "Your current subscription does not allow changing plans"
|
||||
@@ -7518,7 +7518,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1403
|
||||
msgid "Your free trial is ending soon"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2626
|
||||
msgid "Your free trial is on-going. Your subscription will start on {trialExpiryDate}"
|
||||
|
||||
@@ -21,8 +21,8 @@ import React, {
|
||||
useCallback,
|
||||
useRef,
|
||||
useEffect,
|
||||
PropsWithChildren,
|
||||
useState
|
||||
useState,
|
||||
PropsWithChildren
|
||||
} from "react";
|
||||
import { Box, FlexProps, Text } from "@theme-ui/components";
|
||||
import { getPosition } from "../../utils/position.js";
|
||||
@@ -68,6 +68,7 @@ export function Menu(props: MenuProps) {
|
||||
const focusedItem = items[focusIndex];
|
||||
|
||||
const subMenuRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const item = items[focusIndex];
|
||||
if (!item || !subMenuRef.current) return;
|
||||
@@ -80,15 +81,23 @@ export function Menu(props: MenuProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { top, left } = getPosition(subMenuRef.current, {
|
||||
// yOffset: menuItemElement.offsetHeight,
|
||||
target: menuItemElement,
|
||||
location: "right"
|
||||
});
|
||||
function repositionSubmenu() {
|
||||
if (!subMenuRef.current || !menuItemElement) return;
|
||||
|
||||
const { top, left } = getPosition(subMenuRef.current, {
|
||||
target: menuItemElement,
|
||||
location: "right"
|
||||
});
|
||||
subMenuRef.current.style.top = `${top}px`;
|
||||
subMenuRef.current.style.left = `${left}px`;
|
||||
}
|
||||
|
||||
repositionSubmenu();
|
||||
subMenuRef.current.style.visibility = "visible";
|
||||
subMenuRef.current.style.top = `${top}px`;
|
||||
subMenuRef.current.style.left = `${left}px`;
|
||||
|
||||
const observer = new ResizeObserver(() => repositionSubmenu());
|
||||
observer.observe(subMenuRef.current);
|
||||
return () => observer.disconnect();
|
||||
}, [isSubmenuOpen, focusIndex, items]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -209,14 +209,21 @@ Options:
|
||||
// ---------------------------------------------------------------------------
|
||||
// Stack frame parsing
|
||||
//
|
||||
// Handles frames like:
|
||||
// Handles frames like (V8/Node):
|
||||
// at XB (https://example.com/assets/app-HASH.js:136:27466)
|
||||
// at https://example.com/assets/app-HASH.js:12:345 (anonymous)
|
||||
// at https://example.com/assets/app-HASH.js:12:345
|
||||
// at+XB+(https://example.com/assets/app-HASH.js:136:27466) (URL-encoded)
|
||||
// And Safari/WebKit:
|
||||
// E@https://example.com/assets/app-HASH.js:23:45428
|
||||
// @https://example.com/assets/app-HASH.js:23:45428 (anonymous)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Groups:
|
||||
// V8 named: m[1]=symbol m[2]=url m[3]=line m[4]=col
|
||||
// V8 anonymous: m[5]=url m[6]=line m[7]=col
|
||||
// Safari: m[8]=symbol m[9]=url m[10]=line m[11]=col
|
||||
const FRAME_RE =
|
||||
/at\s+(?:async\s+)?(\S+)\s+\(?(https?:\/\/[^\s):]+):(\d+):(\d+)\)?|at\s+(?:async\s+)?(https?:\/\/[^\s):]+):(\d+):(\d+)/g;
|
||||
/at\s+(?:async\s+)?(\S+)\s+\(?(https?:\/\/[^\s):]+):(\d+):(\d+)\)?|at\s+(?:async\s+)?(https?:\/\/[^\s):]+):(\d+):(\d+)|(\S*)@(https?:\/\/[^\s:)]+):(\d+):(\d+)/g;
|
||||
|
||||
function parseStackTrace(raw) {
|
||||
// Replace URL-encoded + with spaces so the regex works uniformly
|
||||
@@ -233,7 +240,7 @@ function parseStackTrace(raw) {
|
||||
}
|
||||
|
||||
if (m[2]) {
|
||||
// "at symbol (url:line:col)"
|
||||
// V8: "at symbol (url:line:col)"
|
||||
frames.push({
|
||||
raw: line,
|
||||
parsed: true,
|
||||
@@ -242,8 +249,8 @@ function parseStackTrace(raw) {
|
||||
line: parseInt(m[3], 10),
|
||||
col: parseInt(m[4], 10)
|
||||
});
|
||||
} else {
|
||||
// "at url:line:col"
|
||||
} else if (m[5]) {
|
||||
// V8: "at url:line:col"
|
||||
frames.push({
|
||||
raw: line,
|
||||
parsed: true,
|
||||
@@ -252,6 +259,16 @@ function parseStackTrace(raw) {
|
||||
line: parseInt(m[6], 10),
|
||||
col: parseInt(m[7], 10)
|
||||
});
|
||||
} else {
|
||||
// Safari/WebKit: "symbol@url:line:col"
|
||||
frames.push({
|
||||
raw: line,
|
||||
parsed: true,
|
||||
symbol: m[8] || null,
|
||||
url: m[9],
|
||||
line: parseInt(m[10], 10),
|
||||
col: parseInt(m[11], 10)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,7 +355,10 @@ function tryDemangleDotted(consumer, generatedLine, generatedCol, symbol) {
|
||||
let col = generatedCol;
|
||||
|
||||
for (let i = parts.length - 1; i >= 0; i--) {
|
||||
const pos = consumer.originalPositionFor({ line: generatedLine, column: col });
|
||||
const pos = consumer.originalPositionFor({
|
||||
line: generatedLine,
|
||||
column: col
|
||||
});
|
||||
if (pos.name) resolved[i] = pos.name;
|
||||
// Step back past this identifier and the dot that precedes it
|
||||
col -= parts[i].length + 1;
|
||||
@@ -507,7 +527,13 @@ async function main() {
|
||||
console.log(` at ${name} (${src}:${pos.line}:${pos.column})`);
|
||||
|
||||
// Source context
|
||||
const ctx = getSourceContext(consumer, pos.source, pos.line, pos.column, opts.context);
|
||||
const ctx = getSourceContext(
|
||||
consumer,
|
||||
pos.source,
|
||||
pos.line,
|
||||
pos.column,
|
||||
opts.context
|
||||
);
|
||||
if (ctx) {
|
||||
for (const l of ctx) {
|
||||
const gutter = l.isTarget ? ">" : " ";
|
||||
|
||||
Reference in New Issue
Block a user