Compare commits

...

21 Commits

Author SHA1 Message Date
Ammar Ahmed
14c1567c07 editor: fix scrollLeft value on mobile when using scroll container 2025-10-27 12:50:16 +05:00
Ammar Ahmed
fb778f56ed editor: use default scroll container on mobile to fix selection bugs 2025-10-27 12:47:41 +05:00
Ammar Ahmed
ece7b29005 Merge pull request #8839 from streetwriters/mobile-release-3.3.6
Mobile release 3.3.6
2025-10-24 09:01:33 +05:00
Ammar Ahmed
8cd8e93487 mobile: fix styles in editor 2025-10-23 21:58:27 +05:00
Ammar Ahmed
8900a6b080 mobile: release v3.3.6 2025-10-23 21:39:20 +05:00
Ammar Ahmed
19d90fa221 mobile: allow users to open redeem code url from app 2025-10-23 21:38:55 +05:00
Ammar Ahmed
2e5ff859eb Merge pull request #8835 from streetwriters/fix-reminder-widget
mobile: fix reminders widget on android
2025-10-23 13:48:28 +05:00
Ammar Ahmed
06747575ee Merge pull request #8834 from streetwriters/fix-signup-navigation
mobile: fix navigation after signup complete broken
2025-10-23 13:48:07 +05:00
Ammar Ahmed
98bb8ca186 Merge pull request #8833 from streetwriters/fix-app-lock-free-user
mobile: fix app-lock disabled dialog does not show to free users
2025-10-23 13:47:46 +05:00
Ammar Ahmed
d5f68602b6 Merge pull request #8832 from streetwriters/fix-vault-biometrics-unlock
mobile: fix vault biometrics state incorrect on app launch
2025-10-23 13:47:09 +05:00
Ammar Ahmed
312999aa5b Merge pull request #8827 from streetwriters/fix-delete-note-locked-bulk
mobile: ask user for vault password before deleting locked notes in bulk
2025-10-23 13:46:09 +05:00
Ammar Ahmed
607a4d26f4 Merge pull request #8826 from streetwriters/fix-restore-button-mobile
mobile: fix restore button is hidden in history preview item
2025-10-23 13:44:09 +05:00
Ammar Ahmed
a88b6615e4 Merge pull request #8825 from streetwriters/fix-gesture-navigation
mobile: fix gesture navigation not working
2025-10-23 13:43:50 +05:00
Ammar Ahmed
f900098201 mobile: fix app-lock disabled dialog does not show to free users 2025-10-23 12:17:01 +05:00
Ammar Ahmed
e9a48ae028 mobile: fix reminders widget on android 2025-10-23 11:01:28 +05:00
Ammar Ahmed
90a0f619ec mobile: ask user for vault password before deleting locked notes in bulk 2025-10-22 19:27:43 +05:00
Ammar Ahmed
ed3662a636 mobile: fix restore button is hidden in history preview item 2025-10-22 14:54:47 +05:00
Ammar Ahmed
26eda3b105 mobile: fix gesture navigation not working 2025-10-22 14:40:56 +05:00
Ammar Ahmed
8f43882e29 mobile: fix navigation after signup complete broken 2025-10-22 14:27:26 +05:00
Ammar Ahmed
e239597eb1 Merge pull request #8821 from streetwriters/fix--disable-post-install-script
Fix fdroid build failing due to postinstall script using bun
2025-10-22 09:11:41 +05:00
Ammar Ahmed
bf1ef07d3a mobile: fix fdroid build failing due to postinstall script using bun 2025-10-22 09:09:32 +05:00
53 changed files with 477 additions and 457 deletions

View File

@@ -47,6 +47,11 @@ jobs:
- name: Install Detox CLI
run: npm install detox-cli --global
- name: Check for typescript errors
run: |
cd apps/mobile
npx tsc --noEmit
- name: Detox build
run: |
yarn build:android

View File

@@ -73,6 +73,12 @@ jobs:
- name: CCache Stats Before Build
run: ccache -sv
- name: Check for typescript errors
run: |
npm run tx mobile:build
cd apps/mobile
npx tsc --noEmit
- name: Build unsigned app bundle
run: yarn release:android:bundle

View File

@@ -73,6 +73,12 @@ jobs:
- name: CCache Stats Before Build
run: ccache -sv
- name: Check for typescript errors
run: |
npm run tx mobile:build
cd apps/mobile
npx tsc --noEmit
- name: Build unsigned app bundle
run: yarn release:android:bundle

View File

@@ -64,6 +64,12 @@ jobs:
bundle install
RCT_NEW_ARCH_ENABLED=0 bundle exec pod install
- name: Check for typescript errors
run: |
npm run tx mobile:build
cd apps/mobile
npx tsc --noEmit
- name: CCache Stats Before Build
run: ccache -sv

View File

@@ -94,7 +94,9 @@ export async function encryptDatabaseKeyWithPassword(appLockPassword: string) {
}
export async function restoreDatabaseKeyToKeyChain(appLockPassword: string) {
const databaseKeyCipher: Cipher = CipherStorage.getMap(DB_KEY_CIPHER);
const databaseKeyCipher: Cipher = CipherStorage.getMap(
DB_KEY_CIPHER
) as Cipher;
const databaseKey = (await decrypt(
{
password: appLockPassword
@@ -135,7 +137,9 @@ export async function clearAppLockVerificationCipher() {
export async function validateAppLockPassword(appLockPassword: string) {
try {
const appLockCipher: Cipher = CipherStorage.getMap(APPLOCK_CIPHER);
const appLockCipher: Cipher = CipherStorage.getMap(
APPLOCK_CIPHER
) as Cipher;
if (!appLockCipher) return true;
const key = await Sodium.deriveKey(appLockPassword, appLockCipher.salt);
const decrypted = await decrypt(key, appLockCipher);
@@ -159,7 +163,9 @@ export function clearDatabaseKey() {
export async function getDatabaseKey(appLockPassword?: string) {
if (DB_KEY) return DB_KEY;
if (appLockPassword) {
const databaseKeyCipher: Cipher = CipherStorage.getMap("databaseKeyCipher");
const databaseKeyCipher: Cipher = CipherStorage.getMap(
"databaseKeyCipher"
) as Cipher;
const databaseKey = await decrypt(
{
password: appLockPassword
@@ -293,7 +299,7 @@ export async function deriveCryptoKey(data: SerializedKey) {
export async function getCryptoKey() {
try {
const keyCipher: Cipher = MMKV.getMap(USER_KEY_CIPHER);
const keyCipher: Cipher = MMKV.getMap(USER_KEY_CIPHER) as Cipher;
if (!keyCipher) {
DatabaseLogger.info("User key cipher is null");
return undefined;

View File

@@ -136,6 +136,12 @@ export const Storage: IStorage = {
clear(): Promise<void> {
return DefaultStorage.clear();
},
generateCryptoKeyPair() {
throw new Error("Not implemented");
},
decryptAsymmetric() {
throw new Error("Not implemented");
},
getAllKeys(): Promise<string[]> {
return DefaultStorage.getAllKeys();
},

View File

@@ -39,6 +39,7 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { AuthHeader } from "./header";
import { SignupContext } from "./signup-context";
import SettingsService from "../../services/settings";
const SignupSteps = {
signup: 0,

View File

@@ -99,7 +99,7 @@ export const useLogin = (
callback && callback(false);
} catch (e) {
callback && callback(false);
if (e.message === "invalid_grant") {
if ((e as Error).message === "invalid_grant") {
eSendEvent(eCloseSimpleDialog, "two_factor_verify");
setLoading(false);
setStep(LoginSteps.emailAuth);

View File

@@ -35,29 +35,35 @@ import SheetProvider from "../sheet-provider";
import RateAppSheet from "../sheets/rate-app";
import RecoveryKeySheet from "../sheets/recovery-key";
import Progress from "../dialogs/progress";
import { useSettingStore } from "../../stores/use-setting-store";
const DialogProvider = () => {
const { colors } = useThemeColors();
const isAppLoading = useSettingStore((state) => state.isAppLoading);
return (
<>
<AppLockPassword />
<LoadingDialog />
<Dialog context="global" />
<AuthModal colors={colors} />
<MergeConflicts />
<RecoveryKeySheet colors={colors} />
<SheetProvider />
<SheetProvider context="sync_progress" />
<ResultDialog />
<VaultDialog colors={colors} />
<RateAppSheet />
<ImagePreview />
<AnnouncementDialog />
<SessionExpired />
<PDFPreview />
<JumpToSectionDialog />
<Dialog context="global" />
<Progress />
{isAppLoading ? null : (
<>
<MergeConflicts />
<RecoveryKeySheet colors={colors} />
<ResultDialog />
<VaultDialog colors={colors} />
<RateAppSheet />
<ImagePreview />
<AnnouncementDialog />
<SessionExpired />
<PDFPreview />
<JumpToSectionDialog />
</>
)}
</>
);
};

View File

@@ -41,7 +41,7 @@ export const openNotebook = (item: Notebook | BaseTrashItem<Notebook>) => {
positiveText: strings.restore(),
negativeText: strings.delete(),
positivePress: async () => {
if ((await db.trash.restore(item.id)) === false) return;
await db.trash.restore(item.id);
Navigation.queueRoutesForUpdate();
useSelectionStore.getState().setSelectionMode(undefined);
ToastManager.show({

View File

@@ -117,7 +117,8 @@ export default function NotePreview({ session, content, note }) {
{!session?.locked && !locked ? (
<View
style={{
flex: 1
flex: 1,
backgroundColor: colors.primary.background
}}
>
<ReadonlyEditor

View File

@@ -44,6 +44,7 @@ import Config from "react-native-config";
import * as RNIap from "react-native-iap";
import { SafeAreaView } from "react-native-safe-area-context";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
//@ts-ignore
import ToggleSwitch from "toggle-switch-react-native";
import {
ANDROID_POLICE_SVG,

View File

@@ -29,6 +29,7 @@ import {
View
} from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
//@ts-ignore
import ToggleSwitch from "toggle-switch-react-native";
import { db } from "../../../common/database";
import { requestInAppReview } from "../../../services/app-review";

View File

@@ -171,7 +171,7 @@ const onAppOpenedFromURL = async (event: { url: string }) => {
eSendEvent(eOnLoadNote, { newNote: true });
fluidTabsRef.current?.goToPage("editor", false);
return;
} else if (url.startsWith("https://notesnook.com/open_note")) {
} else if (url.startsWith("https://app.notesnook.com/open_note")) {
const id = new URL(url).searchParams.get("id");
if (id) {
const note = await db.notes.note(id);
@@ -182,13 +182,13 @@ const onAppOpenedFromURL = async (event: { url: string }) => {
fluidTabsRef.current?.goToPage("editor", false);
}
}
} else if (url.startsWith("https://notesnook.com/open_reminder")) {
} else if (url.startsWith("https://app.notesnook.com/open_reminder")) {
const id = new URL(url).searchParams.get("id");
if (id) {
const reminder = await db.reminders.reminder(id);
if (reminder) AddReminder.present(reminder);
}
} else if (url.startsWith("https://notesnook.com/new_reminder")) {
} else if (url.startsWith("https://app.notesnook.com/new_reminder")) {
const reminderFeature = await isFeatureAvailable("activeReminders");
if (!reminderFeature.isAllowed) {
ToastManager.show({
@@ -780,13 +780,11 @@ export const useAppEvents = () => {
if (!isAppLoading && !appLocked) {
setTimeout(() => {
sub = AppState.addEventListener("change", onAppStateChanged);
if (
refValues.current.initialUrl &&
!refValues.current.initialUrl?.includes("open_note")
) {
if (refValues.current.initialUrl) {
onAppOpenedFromURL({
url: refValues.current.initialUrl!
});
refValues.current.initialUrl = undefined;
}
}, 1000);

View File

@@ -69,36 +69,6 @@ export default function useFeatureManager() {
db.settings.setDefaultTag(undefined);
}
}
const isAppLocked = useUserStore.getState().appLocked;
let unsub: () => void;
if (isAppLocked) {
unsub = useUserStore.subscribe((state) => {
if (!state.appLocked && !features?.appLock?.isAllowed) {
unsub();
SettingsService.setProperty("appLockEnabled", false);
setTimeout(() => {
presentDialog({
title: "App Lock Disabled",
paragraph: features?.appLock?.error,
positiveText: strings.upgrade(),
negativeText: strings.cancel(),
positivePress: async () => {
eSendEvent(eCloseSimpleDialog);
if (SettingsService.getProperty("serverUrls")) return;
Navigation.navigate("PayWall", {
context: "logged-in"
});
}
});
}, 1000);
}
});
}
return () => {
unsub?.();
};
}, [features, plan]);
return true;

View File

@@ -1,67 +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 { useEffect, useState } from "react";
import { Platform } from "react-native";
import { Subscription } from "react-native-iap";
import PremiumService from "../services/premium";
import { db } from "../common/database";
import { Product } from "@notesnook/core";
const skuInfos: { [name: string]: Product | undefined } = {};
export const usePricing = (period: "monthly" | "yearly") => {
const [current, setCurrent] = useState<{
period: string;
info?: Product;
product?: Subscription;
}>();
const getDefaultSku = (period: "monthly" | "yearly") => {
return period === "monthly"
? "com.streetwriters.notesnook.sub.mo"
: "com.streetwriters.notesnook.sub.yr";
};
useEffect(() => {
(async () => {
const skuInfo =
skuInfos[period] ||
(await db.pricing?.sku(
Platform.OS === "android" ? "android" : "ios",
period
));
skuInfos[period] = skuInfo;
const products = (await (
await PremiumService.loadProductsAndSubs()
).subs) as Subscription[];
let product = products.find((p) => p.productId === skuInfo?.sku);
if (!product)
product = products.find((p) => p.productId === getDefaultSku(period));
setCurrent({
info: skuInfo,
period,
product
});
})();
}, [period]);
return current;
};

View File

@@ -49,6 +49,7 @@ import { AppFontSize, defaultBorderRadius } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { getFormattedDate, useIsFeatureAvailable } from "@notesnook/common";
import PaywallSheet from "../../components/sheets/paywall";
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
const ReminderModes =
Platform.OS === "ios"
@@ -89,6 +90,7 @@ const ReminderNotificationModes = {
export default function AddReminder(props: NavigationProps<"AddReminder">) {
const { reminder, reference } = props.route.params;
useNavigationFocus(props.navigation, { focusOnInit: true });
const { colors, isDark } = useThemeColors();
const [reminderMode, setReminderMode] = useState<Reminder["mode"]>(
reminder?.mode || "once"

View File

@@ -82,6 +82,7 @@ import { editorState, openInternalLink } from "./utils";
import AddReminder from "../../add-reminder";
import { isFeatureAvailable, useAreFeaturesAvailable } from "@notesnook/common";
import PaywallSheet from "../../../components/sheets/paywall";
import useNavigationStore from "../../../stores/use-navigation-store";
const publishNote = async () => {
const user = useUserStore.getState().user;
@@ -274,7 +275,15 @@ export const useEditorEvents = (
const onHardwareBackPress = useCallback(() => {
if (fluidTabsRef.current?.page() === "editor") {
onBackPress();
if (
useNavigationStore.getState().currentRoute === "ManageTags" ||
useNavigationStore.getState().currentRoute === "LinkNotebooks" ||
useNavigationStore.getState().currentRoute === "AddReminder"
) {
Navigation.goBack();
} else {
onBackPress();
}
return true;
}
}, [onBackPress]);

View File

@@ -185,7 +185,7 @@ export default function DebugLogs() {
paragraph: strings.clearLogsConfirmation(currentLog.key),
negativeText: strings.cancel(),
positiveText: strings.clear(),
positivePress: () => {
positivePress: async () => {
const index = logs.findIndex((l) => (l.key = currentLog.key));
logManager?.delete(currentLog.key);
if (logs.length > 1) {

View File

@@ -2,7 +2,8 @@ import { CirclePartner, SubscriptionStatus } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import Clipboard from "@react-native-clipboard/clipboard";
import { useEffect, useState } from "react";
import { useState } from "react";
import { useAsync } from "react-async-hook";
import {
ActivityIndicator,
Image,
@@ -13,6 +14,7 @@ import {
import { db } from "../../common/database";
import AppIcon from "../../components/ui/AppIcon";
import { Button } from "../../components/ui/button";
import { Notice } from "../../components/ui/notice";
import Heading from "../../components/ui/typography/heading";
import Paragraph from "../../components/ui/typography/paragraph";
import { ToastManager } from "../../services/event-manager";
@@ -21,8 +23,8 @@ import PremiumService from "../../services/premium";
import { useUserStore } from "../../stores/use-user-store";
import { AppFontSize, defaultBorderRadius } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { useAsync } from "react-async-hook";
import { Notice } from "../../components/ui/notice";
import { openLinkInBrowser } from "../../utils/functions";
import { Pressable } from "../../components/ui/pressable";
export const NotesnookCircle = () => {
const user = useUserStore((state) => state.user);
@@ -156,32 +158,53 @@ const Partner = ({
}}
/>
) : (
<TouchableOpacity
style={{
backgroundColor: colors.secondary.background,
borderRadius: defaultBorderRadius,
alignItems: "center",
justifyContent: "center",
padding: DefaultAppStyles.GAP_SMALL,
borderWidth: 0.5,
borderColor: colors.secondary.border,
flexDirection: "row",
gap: DefaultAppStyles.GAP_SMALL
}}
activeOpacity={0.9}
onPress={() => {
Clipboard.setString(code);
}}
>
<Paragraph
size={AppFontSize.lg}
color={colors.secondary.paragraph}
<>
<TouchableOpacity
style={{
backgroundColor: colors.secondary.background,
borderRadius: defaultBorderRadius,
alignItems: "center",
justifyContent: "center",
padding: DefaultAppStyles.GAP_SMALL,
borderWidth: 0.5,
borderColor: colors.secondary.border,
flexDirection: "row",
gap: DefaultAppStyles.GAP_SMALL
}}
activeOpacity={0.9}
onPress={() => {
Clipboard.setString(code);
}}
>
{code}
</Paragraph>
<Paragraph
size={AppFontSize.lg}
color={colors.secondary.paragraph}
>
{code}
</Paragraph>
<AppIcon name="content-copy" />
</TouchableOpacity>
<AppIcon name="content-copy" />
</TouchableOpacity>
{item.codeRedeemUrl ? (
<Pressable
onPress={() => {
if (item.codeRedeemUrl) {
openLinkInBrowser(
item.codeRedeemUrl.replace("{{code}}", code)
);
}
}}
>
<Paragraph
color={colors.secondary.paragraph}
size={AppFontSize.xxs}
>
{strings.clickToDirectlyClaimPromo()}
</Paragraph>
</Pressable>
) : null}
</>
)}
</>
) : null}

View File

@@ -26,18 +26,17 @@ import {
import React, { useEffect, useRef, useState } from "react";
import { ActivityIndicator, TextInput, View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
//@ts-ignore
import { FeatureResult, useIsFeatureAvailable } from "@notesnook/common";
import { strings } from "@notesnook/intl";
//@ts-ignore
import ToggleSwitch from "toggle-switch-react-native";
import PaywallSheet from "../../components/sheets/paywall";
import AppIcon from "../../components/ui/AppIcon";
import { IconButton } from "../../components/ui/icon-button";
import Input from "../../components/ui/input";
import { Pressable } from "../../components/ui/pressable";
import Seperator from "../../components/ui/seperator";
import Heading from "../../components/ui/typography/heading";
import Paragraph from "../../components/ui/typography/paragraph";
import { ToastManager } from "../../services/event-manager";
import SettingsService from "../../services/settings";
import useNavigationStore from "../../stores/use-navigation-store";
import { SettingStore, useSettingStore } from "../../stores/use-setting-store";
@@ -45,7 +44,6 @@ import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { components } from "./components";
import { RouteParams, SettingSection } from "./types";
import AppIcon from "../../components/ui/AppIcon";
const _SectionItem = ({ item }: { item: SettingSection }) => {
const { colors } = useThemeColors();

View File

@@ -32,6 +32,7 @@ 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 { DatabaseLogger, db } from "../../common/database";

View File

@@ -580,7 +580,7 @@ function openSettingsDialog(context: string) {
positivePress:
Platform.OS === "ios"
? undefined
: () => {
: async () => {
resolve(true);
},
onClose: () => {

View File

@@ -17,8 +17,15 @@ 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 { Profile, User } from "@notesnook/core";
import create, { State } from "zustand";
import SettingsService from "../services/settings";
import { presentDialog } from "../components/dialog/functions";
import { strings } from "@notesnook/intl";
import { eSendEvent } from "../services/event-manager";
import { eCloseSimpleDialog } from "../utils/events";
import Navigation from "../services/navigation";
export enum SyncStatus {
Passed,
@@ -57,6 +64,28 @@ export const useUserStore = create<UserStore>((set) => ({
setLastSynced: (lastSynced) => set({ lastSynced: lastSynced }),
lockApp: (appLocked) => {
set({ appLocked });
if (!appLocked) {
isFeatureAvailable("appLock").then((feature) => {
if (!feature.isAllowed) {
SettingsService.setProperty("appLockEnabled", false);
setTimeout(() => {
presentDialog({
title: "App Lock Disabled",
paragraph: feature?.error,
positiveText: strings.upgrade(),
negativeText: strings.cancel(),
positivePress: async () => {
eSendEvent(eCloseSimpleDialog);
if (SettingsService.getProperty("serverUrls")) return;
Navigation.navigate("PayWall", {
context: "logged-in"
});
}
});
}, 1000);
}
});
}
},
lastSyncStatus: SyncStatus.Never,
disableAppLockRequests: false,

View File

@@ -33,6 +33,7 @@ import { useNotebookStore } from "../stores/use-notebook-store";
import { useRelationStore } from "../stores/use-relation-store";
import { useTagStore } from "../stores/use-tag-store";
import { eUpdateNoteInEditor } from "./events";
import { unlockVault } from "./unlock-vault";
export function getObfuscatedEmail(email: string) {
if (!email) return "";
@@ -56,7 +57,7 @@ function confirmDeleteAllNotes(
title: strings.doActions.delete.notebook(items.length),
positiveText: strings.delete(),
negativeText: strings.cancel(),
positivePress: (_inputValue, value) => {
positivePress: async (_inputValue, value) => {
setTimeout(() => {
resolve({ delete: true, deleteNotes: value });
});
@@ -98,6 +99,30 @@ export const deleteItems = async (
await db.reminders.remove(...itemIds);
useRelationStore.getState().update();
} else if (type === "note") {
let someNotesLocked = false;
for (const id of itemIds) {
if (
await db.vaults.itemExists({
id: id,
type: "note"
})
) {
someNotesLocked = true;
break;
}
}
if (someNotesLocked) {
const unlocked = await unlockVault({
title: strings.unlockVault(),
paragraph: strings.unlockVaultDesc(),
context: "global",
requirePassword: true
});
if (!unlocked) return;
}
for (const id of itemIds) {
if (db.monographs.isPublished(id)) {
ToastManager.show({
@@ -108,6 +133,7 @@ export const deleteItems = async (
});
continue;
}
await db.notes.moveToTrash(id);
eSendEvent(
@@ -157,7 +183,7 @@ export const deleteItems = async (
heading: message,
type: "success",
func: async () => {
if ((await db.trash.restore(...deletedIds)) === false) return;
await db.trash.restore(...deletedIds);
Navigation.queueRoutesForUpdate();
useMenuStore.getState().setMenuPins();
useMenuStore.getState().setColorNotes();

View File

@@ -27,18 +27,20 @@ let unlockPromise: Promise<any> | undefined = undefined;
export async function unlockVault({
context,
title,
paragraph
paragraph,
requirePassword
}: {
context?: string;
title: string;
paragraph: string;
requirePassword?: boolean;
}) {
if (unlockPromise) {
return unlockPromise;
}
unlockPromise = new Promise(async (resolve) => {
const result = await (async () => {
if (db.vault.unlocked) return true;
if (db.vault.unlocked && !requirePassword) return true;
const biometry = await BiometricService.isBiometryAvailable();
const fingerprint = await BiometricService.hasInternetCredentials();
if (biometry && fingerprint) {

View File

@@ -124,7 +124,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled true
versionCode 3074
versionCode 3075
versionName getNpmVersion()
testBuildType System.getProperty('testBuildType', 'debug')
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'

View File

@@ -33,7 +33,7 @@ public class NotePreviewWidget extends AppWidgetProvider {
intent.putExtra(OpenNoteId, note.getId());
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(RCTNNativeModule.IntentType, "OpenNote");
intent.setData(Uri.parse("https://notesnook.com/open_note?id=" + note.getId()));
intent.setData(Uri.parse("https://app.notesnook.com/open_note?id=" + note.getId()));
PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE, getActivityOptionsBundle());
views.setOnClickPendingIntent(R.id.open_note, pendingIntent);

View File

@@ -75,7 +75,7 @@ class ReminderRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactor
final Intent fillInIntent = new Intent();
final Bundle extras = new Bundle();
extras.putString(ReminderViewsService.OpenReminderId, reminder.getId());
fillInIntent.setData(Uri.parse("https://notesnook.com/open_reminder?id=" + reminder.getId()));
fillInIntent.setData(Uri.parse("https://app.notesnook.com/open_reminder?id=" + reminder.getId()));
fillInIntent.putExtra(RCTNNativeModule.IntentType, "OpenReminder");
fillInIntent.putExtras(extras);
views.setOnClickFillInIntent(R.id.reminder_item_btn, fillInIntent);

View File

@@ -43,7 +43,7 @@ public class ReminderWidgetProvider extends AppWidgetProvider {
new_reminder_intent.putExtra(NewReminder, NewReminder);
new_reminder_intent.setAction(Intent.ACTION_VIEW);
new_reminder_intent.putExtra(RCTNNativeModule.IntentType, "NewReminder");
new_reminder_intent.setData(Uri.parse("https://notesnook.com/new_reminder"));
new_reminder_intent.setData(Uri.parse("https://app.notesnook.com/new_reminder"));
PendingIntent pendingIntent2 = PendingIntent.getActivity(context, appWidgetId, new_reminder_intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE, getActivityOptionsBundle());
views.setOnClickPendingIntent(R.id.add_button, pendingIntent2);

View File

@@ -2,6 +2,7 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="10dp"
android:id="@+id/reminder_item_btn">
<TextView

View File

@@ -2,6 +2,7 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="10dp"
android:id="@+id/reminder_item_btn">
<TextView

View File

@@ -25,9 +25,9 @@
android:text="Upcoming Reminders"/>
<ImageButton
android:layout_width="30dp"
android:layout_width="35dp"
android:id="@+id/add_button"
android:layout_height="30dp"
android:layout_height="35dp"
android:layout_alignParentRight="true"
android:background="@drawable/ic_newnote" />
</RelativeLayout>

View File

@@ -1,5 +1,3 @@
- Collapsible Headings
- Notesnook Circle
- Minor bug fixes and improvements
Thank you for using Notesnook!

View File

@@ -1091,7 +1091,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2153;
CURRENT_PROJECT_VERSION = 2154;
DEVELOPMENT_TEAM = 53CWBG3QUC;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1165,7 +1165,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.3.5;
MARKETING_VERSION = 3.3.6;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -1196,7 +1196,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2153;
CURRENT_PROJECT_VERSION = 2154;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1270,7 +1270,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.3.5;
MARKETING_VERSION = 3.3.6;
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = (
"$(inherited)",
@@ -1429,7 +1429,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2153;
CURRENT_PROJECT_VERSION = 2154;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1441,7 +1441,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.3.5;
MARKETING_VERSION = 3.3.6;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
@@ -1472,7 +1472,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2153;
CURRENT_PROJECT_VERSION = 2154;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1485,7 +1485,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.3.5;
MARKETING_VERSION = 3.3.6;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1515,7 +1515,7 @@
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2153;
CURRENT_PROJECT_VERSION = 2154;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1596,7 +1596,7 @@
"@executable_path/../../Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)";
MARKETING_VERSION = 3.3.5;
MARKETING_VERSION = 3.3.6;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
@@ -1627,7 +1627,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2153;
CURRENT_PROJECT_VERSION = 2154;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1709,7 +1709,7 @@
"@executable_path/../../Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)";
MARKETING_VERSION = 3.3.5;
MARKETING_VERSION = 3.3.6;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@@ -72,10 +72,10 @@
"react-native-begin-background-task": "github:blockfirm/react-native-begin-background-task",
"react-native-privacy-snapshot": "github:standardnotes/react-native-privacy-snapshot",
"@ammarahmed/react-native-fingerprint-scanner": "^5.0.0",
"@ammarahmed/react-native-share-extension": "^2.9.0",
"react-native-pager-view": "^6.5.1",
"react-native-tab-view": "^4.0.2",
"react-native-orientation-locker": "^1.7.0"
"react-native-orientation-locker": "^1.7.0",
"@ammarahmed/react-native-share-extension": "^2.9.5"
},
"devDependencies": {
"@babel/core": "^7.27.1",

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@notesnook/mobile",
"version": "3.3.5",
"version": "3.3.6",
"private": true,
"license": "GPL-3.0-or-later",
"workspaces": [
@@ -56,4 +56,4 @@
"react": "18.2.0",
"react-native": "0.77.2"
}
}
}

View File

@@ -68,11 +68,10 @@ export const useShareStore = create((set) => ({
let appendNote = MMKV.getString(StorageKeys.appendNote);
let selectedNotebooks = MMKV.getString(StorageKeys.selectedNotebooks);
let selectedTags = MMKV.getString(StorageKeys.selectedTag);
appendNote = JSON.parse(appendNote);
set({
appendNote: appendNote,
selectedNotebooks: selectedNotebooks ? JSON.parse(selectedNotebooks) : [],
selectedTag: selectedTags ? JSON.parse(selectedTags) : []
selectedTags: selectedTags ? JSON.parse(selectedTags) : []
});
},
selectedTags: [],

View File

@@ -15,10 +15,7 @@
"@notesnook/theme": ["../../packages/theme"],
"@types/react": ["./node_modules/@types/react"],
"react": ["./node_modules/react"]
},
"incremental": true,
"maxNodeModuleJsDepth": 5,
"downlevelIteration": true
}
},
"exclude": ["native", "e2e"]
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
- Minor bug fixes and improvements
Thank you for using Notesnook!

View File

@@ -63,7 +63,7 @@
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {
"@notesnook-importer/core": "^2.2.2",
"@notesnook-importer/core": "^2.2.5",
"@notesnook/common": "file:../common",
"@notesnook/intl": "file:../intl",
"@notesnook/theme": "file:../theme",

View File

@@ -34,7 +34,11 @@
}
.ProseMirror > :first-child {
margin-top: 0.4em !important;
margin-top: 5px !important;
}
.ProseMirror:first-child {
margin-top: 0px !important;
}
#root {

View File

@@ -580,7 +580,8 @@ const Tiptap = ({
display: "flex",
alignItems: "center",
padding: "0px 16px",
paddingBottom: "6px"
paddingBottom: "3px",
boxSizing: "border-box"
}}
>
<StatusBar

View File

@@ -77,26 +77,19 @@ function StatusBar({
fontSize: 12,
color: "var(--nn_secondary_paragraph)",
paddingBottom: 0,
fontFamily: "Inter",
userSelect: "none"
};
return (
<div
style={{
display: "flex",
height: "25px",
alignItems: "center"
<p
onMouseDown={(e) => {
setShowChars(!showChars);
}}
style={paragraphStyle}
>
<p
onMouseDown={(e) => {
setShowChars(!showChars);
}}
style={paragraphStyle}
>
{showChars ? strings.charactersCount(chars) : words}
</p>
</div>
{showChars ? strings.charactersCount(chars) : words}
</p>
);
}

View File

@@ -55,7 +55,6 @@ function Tags(props: { settings: Settings; loading?: boolean }) {
style={{
display: "flex",
alignItems: "center",
minHeight: "25px",
opacity: props.loading ? 0 : 1,
gap: 6
}}

View File

@@ -1535,39 +1535,6 @@
"@styled-system/css": "^5.1.5"
}
},
"node_modules/@theme-ui/color-modes": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@theme-ui/color-modes/-/color-modes-0.16.2.tgz",
"integrity": "sha512-jWEWx53lxNgWCT38i/kwLV2rsvJz8lVZgi5oImnVwYba9VejXD23q1ckbNFJHosQ8KKXY87ht0KPC6BQFIiHtQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@theme-ui/core": "^0.16.2",
"@theme-ui/css": "^0.16.2",
"deepmerge": "^4.2.2"
},
"peerDependencies": {
"@emotion/react": "^11.11.1",
"react": ">=18"
}
},
"node_modules/@theme-ui/color-modes/node_modules/@theme-ui/core": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@theme-ui/core/-/core-0.16.2.tgz",
"integrity": "sha512-bBd/ltbwO9vIUjF1jtlOX6XN0IIOdf1vzBp2JCKsSOqdfn84m+XL8OogIe/zOhQ+aM94Nrq4+32tFJc8sFav4Q==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@theme-ui/css": "^0.16.2",
"deepmerge": "^4.2.2"
},
"peerDependencies": {
"@emotion/react": "^11.11.1",
"react": ">=18"
}
},
"node_modules/@theme-ui/components": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/@theme-ui/components/-/components-0.16.1.tgz",
@@ -1613,39 +1580,6 @@
"@emotion/react": "^11.11.1"
}
},
"node_modules/@theme-ui/theme-provider": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@theme-ui/theme-provider/-/theme-provider-0.16.2.tgz",
"integrity": "sha512-LRnVevODcGqO0JyLJ3wht+PV3ZoZcJ7XXLJAJWDoGeII4vZcPQKwVy4Lpz/juHsZppQxKcB3U+sQDGBnP25irQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@theme-ui/color-modes": "^0.16.2",
"@theme-ui/core": "^0.16.2",
"@theme-ui/css": "^0.16.2"
},
"peerDependencies": {
"@emotion/react": "^11.11.1",
"react": ">=18"
}
},
"node_modules/@theme-ui/theme-provider/node_modules/@theme-ui/core": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@theme-ui/core/-/core-0.16.2.tgz",
"integrity": "sha512-bBd/ltbwO9vIUjF1jtlOX6XN0IIOdf1vzBp2JCKsSOqdfn84m+XL8OogIe/zOhQ+aM94Nrq4+32tFJc8sFav4Q==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@theme-ui/css": "^0.16.2",
"deepmerge": "^4.2.2"
},
"peerDependencies": {
"@emotion/react": "^11.11.1",
"react": ">=18"
}
},
"node_modules/@tiptap/core": {
"version": "2.6.6",
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.6.6.tgz",
@@ -3556,7 +3490,8 @@
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
},
"node_modules/js-yaml": {
"version": "3.14.1",
@@ -3676,6 +3611,7 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dev": true,
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
@@ -5198,6 +5134,7 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"dev": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -5218,6 +5155,7 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"dev": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -5532,6 +5470,7 @@
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"dev": true,
"dependencies": {
"loose-envify": "^1.1.0"
}

View File

@@ -22,7 +22,7 @@ import { ReactNodeView, ReactNodeViewProps } from "../react/index.js";
import { Node as ProsemirrorNode } from "prosemirror-model";
import { Editor } from "../../types.js";
import { Editor as TiptapEditor } from "@tiptap/core";
import { useEffect, useRef } from "react";
import { useCallback, useEffect, useRef } from "react";
import { updateColumnsOnResize } from "@tiptap/pm/tables";
import { EditorView, NodeView } from "prosemirror-view";
import {
@@ -32,7 +32,7 @@ import {
TableProperties
} from "../../toolbar/tools/table.js";
import { getToolDefinition } from "../../toolbar/tool-definitions.js";
import { getPosition } from "@notesnook/ui";
import { getPosition, ScrollContainer } from "@notesnook/ui";
import {
findSelectedDOMNode,
hasSameAttributes
@@ -41,12 +41,14 @@ import { DesktopOnly } from "../../components/responsive/index.js";
import { TextDirections } from "../text-direction/index.js";
import { strings } from "@notesnook/intl";
import SimpleBar from "simplebar-react";
import { useIsMobile } from "../../toolbar/stores/toolbar-store.js";
export function TableComponent(props: ReactNodeViewProps) {
const { editor, node, forwardRef } = props;
const colgroupRef = useRef<HTMLTableColElement>(null);
const tableRef = useRef<HTMLTableElement>();
const { textDirection } = node.attrs;
const isMobile = useIsMobile();
useEffect(() => {
if (!colgroupRef.current || !tableRef.current) return;
@@ -54,6 +56,22 @@ export function TableComponent(props: ReactNodeViewProps) {
updateColumnsOnResize(node, colgroupRef.current, tableRef.current, 50);
}, [node]);
const renderScrollContent = useCallback(() => {
return (
<div dir={textDirection}>
<table
ref={(ref) => {
forwardRef?.(ref);
tableRef.current = ref || undefined;
}}
>
<colgroup ref={colgroupRef} />
{/* <tbody /> */}
</table>
</div>
);
}, [forwardRef, textDirection]);
return (
<>
<DesktopOnly>
@@ -68,19 +86,12 @@ export function TableComponent(props: ReactNodeViewProps) {
textDirection={textDirection}
/>
</DesktopOnly>
<SimpleBar autoHide>
<Box dir={textDirection}>
<table
ref={(ref) => {
forwardRef?.(ref);
tableRef.current = ref || undefined;
}}
>
<colgroup ref={colgroupRef} />
{/* <tbody /> */}
</table>
</Box>
</SimpleBar>
{isMobile ? (
<ScrollContainer>{renderScrollContent()}</ScrollContainer>
) : (
<SimpleBar>{renderScrollContent()}</SimpleBar>
)}
</>
);
}
@@ -208,6 +219,7 @@ function TableRowToolbar(props: TableToolbarProps) {
function TableColumnToolbar(props: TableToolbarProps) {
const { editor, table } = props;
const columnToolsRef = useRef<HTMLDivElement>(null);
const isMobile = useIsMobile();
useEffect(() => {
function onSelectionUpdate() {
@@ -234,8 +246,9 @@ function TableColumnToolbar(props: TableToolbarProps) {
yOffset: 2
});
const scrollLeft =
table.current?.closest(".simplebar-content-wrapper")?.scrollLeft || 0;
const scrollLeft = isMobile
? table.current.parentElement?.parentElement?.scrollLeft || 0
: table.current?.closest(".simplebar-content-wrapper")?.scrollLeft || 0;
columnToolsRef.current.style.left = `${pos.left - scrollLeft}px`;
columnToolsRef.current.style.top = `${pos.top}px`;
@@ -245,7 +258,7 @@ function TableColumnToolbar(props: TableToolbarProps) {
return () => {
editor.off("selectionUpdate", onSelectionUpdate);
};
}, []);
}, [isMobile]);
return (
<Flex

View File

@@ -1580,6 +1580,10 @@ msgstr ""
"\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.**"
#: src/strings.ts:2606
msgid "Click here to directly claim the promotion."
msgstr "Click here to directly claim the promotion."
#: src/strings.ts:239
msgid "Click to deselect"
msgstr "Click to deselect"
@@ -2842,7 +2846,7 @@ msgstr "Filter attachments by filename, type or hash"
msgid "Filter languages"
msgstr "Filter languages"
#: src/strings.ts:2594
#: src/strings.ts:2603
msgid "Finish your purchase in the browser."
msgstr "Finish your purchase in the browser."
@@ -3032,7 +3036,7 @@ msgstr "Getting recovery codes"
msgid "GNU GENERAL PUBLIC LICENSE Version 3"
msgstr "GNU GENERAL PUBLIC LICENSE Version 3"
#: src/strings.ts:2595
#: src/strings.ts:2604
msgid "Go back"
msgstr "Go back"

View File

@@ -1569,6 +1569,10 @@ msgid ""
"**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 ""
#: src/strings.ts:2606
msgid "Click here to directly claim the promotion."
msgstr ""
#: src/strings.ts:239
msgid "Click to deselect"
msgstr ""
@@ -2831,7 +2835,7 @@ msgstr ""
msgid "Filter languages"
msgstr ""
#: src/strings.ts:2594
#: src/strings.ts:2603
msgid "Finish your purchase in the browser."
msgstr ""
@@ -3014,7 +3018,7 @@ msgstr ""
msgid "GNU GENERAL PUBLIC LICENSE Version 3"
msgstr ""
#: src/strings.ts:2595
#: src/strings.ts:2604
msgid "Go back"
msgstr ""

View File

@@ -2601,5 +2601,7 @@ Use this if changes from other devices are not appearing on this device. This wi
freeUserCircleNotice: () =>
t`The Notesnook Circle is exclusive to subscribers. Please consider subscribing to gain access to Notesnook Circle and enjoy additional benefits.`,
finishPurchaseInBrowser: () => t`Finish your purchase in the browser.`,
goBack: () => t`Go back`
goBack: () => t`Go back`,
clickToDirectlyClaimPromo: () =>
t`Click here to directly claim the promotion.`
};

View File

@@ -53,6 +53,7 @@ const IGNORED_NATIVE_PACKAGES = [
"canvas",
// optional dependency only used on Node.js platform
"@azure/msal-node-runtime",
"react-native-quick-sqlite",
// not needed on mobile
...(args.scope === "mobile" ? ["esbuild"] : [])
];