Merge branch 'master' into beta

This commit is contained in:
Ammar Ahmed
2025-11-01 09:43:46 +05:00
26 changed files with 382 additions and 125 deletions

View File

@@ -39,9 +39,7 @@ import {
presentSheet
} from "../../../services/event-manager";
import Exporter from "../../../services/exporter";
import PremiumService from "../../../services/premium";
import { useSettingStore } from "../../../stores/use-setting-store";
import { useUserStore } from "../../../stores/use-user-store";
import { getElevationStyle } from "../../../utils/elevation";
import { AppFontSize, defaultBorderRadius } from "../../../utils/size";
import { DefaultAppStyles } from "../../../utils/styles";
@@ -83,7 +81,6 @@ const ExportNotesSheet = ({
type: "pdf" | "txt" | "md" | "html" | "md-frontmatter"
) => {
if (exporting) return;
if (!PremiumService.get() && type !== "txt") return;
setExporting(true);
update?.({ disableClosing: true } as PresentSheetOptions);
setComplete(false);
@@ -145,8 +142,7 @@ const ExportNotesSheet = ({
await exportNoteAs("txt");
},
icon: "card-text",
id: notesnook.ids.dialogs.export.text,
pro: true
id: notesnook.ids.dialogs.export.text
},
{
title: "HTML",
@@ -194,8 +190,7 @@ const ExportNotesSheet = ({
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
justifyContent: "flex-start",
borderRadius: 0,
paddingHorizontal: DefaultAppStyles.GAP,
opacity: item.pro ? 1 : 0.5
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<View

View File

@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useRef } from "react";
import React, { useRef, useState } from "react";
import { View } from "react-native";
import { TextInput } from "react-native-gesture-handler";
import { IconButton } from "../../components/ui/icon-button";
@@ -36,6 +36,7 @@ export const SearchBar = ({
onChangeText: (value: string) => void;
loading?: boolean;
}) => {
const [clearButton, setClearButton] = useState(false);
const selectionMode = useSelectionStore((state) => state.selectionMode);
const isFocused = useNavigationStore(
(state) => state.focusedRouteId === "Search"
@@ -45,6 +46,7 @@ export const SearchBar = ({
const inputRef = useRef<TextInput>(null);
const _onChangeText = (value: string) => {
onChangeText(value);
setClearButton(!!value);
};
return selectionMode && isFocused ? null : (
@@ -100,6 +102,23 @@ export const SearchBar = ({
autoCorrect={false}
placeholderTextColor={colors.primary.placeholder}
/>
{clearButton ? (
<IconButton
name="close"
size={AppFontSize.xxl}
top={10}
testID="clear-search"
bottom={10}
onPress={() => {
inputRef.current?.clear();
onChangeText("");
setClearButton(false);
}}
color={colors.primary.paragraph}
type="plain"
/>
) : null}
</View>
</View>
);

View File

@@ -82,15 +82,22 @@ export const settingsGroups: SettingSection[] = [
{
id: "subscription-status",
useHook: () => useUserStore((state) => state.user),
hidden: (current) =>
!current ||
(current as User).subscription?.plan === SubscriptionPlan.FREE,
hidden: (current) => {
const user = current as User;
return (
!user ||
!user.subscription ||
user.subscription.provider === undefined ||
!strings.subscriptionProviderInfo[user?.subscription?.provider] ||
user.subscription?.plan === SubscriptionPlan.FREE
);
},
name: (current) => {
const user = (current as User) || useUserStore.getState().user;
return (
strings.subscriptionProviderInfo[
user?.subscription?.provider
].title() || "Unknown provider"
]?.title() || `Unknown provider id: ${user?.subscription?.provider}`
);
},
icon: "credit-card",
@@ -100,6 +107,8 @@ export const settingsGroups: SettingSection[] = [
const subscriptionProviderInfo =
strings.subscriptionProviderInfo[user?.subscription?.provider];
if (!subscriptionProviderInfo) return;
const isCurrentPlatform =
(user.subscription?.provider === SubscriptionProvider.APPLE &&
Platform.OS === "ios") ||

View File

@@ -1,5 +1,5 @@
import { execSync } from "child_process";
//@ts-ignore
import { pathExists, ensureDir } from "fs-extra";
import { resolveConfig } from "detox/internals";

View File

@@ -28,6 +28,9 @@ describe("Search", () => {
.typeTextById("search-input", "Test")
.wait(1000)
.isVisibleByText("1")
.waitAndTapById("clear-search")
.wait(2000)
.isNotVisibleByText("1")
.run();
});
});

View File

@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { expect as jestExpect } from "@jest/globals";
import { device as _device, expect } from "detox";
import { readFileSync } from "fs";
//@ts-ignore
import { toMatchImageSnapshot } from "jest-image-snapshot";
import type { RouteName } from "../../app/stores/use-navigation-store";
import { notesnook } from "../test.ids";

View File

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

View File

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

View File

@@ -654,6 +654,7 @@
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Notesnook/Pods-Notesnook-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/RNImageCropPickerPrivacyInfo.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
@@ -665,6 +666,7 @@
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNImageCropPickerPrivacyInfo.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
@@ -821,6 +823,7 @@
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Notesnook-NotesnookTests/Pods-Notesnook-NotesnookTests-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/RNImageCropPickerPrivacyInfo.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
@@ -832,6 +835,7 @@
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNImageCropPickerPrivacyInfo.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
@@ -1091,7 +1095,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2154;
CURRENT_PROJECT_VERSION = 2155;
DEVELOPMENT_TEAM = 53CWBG3QUC;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1165,7 +1169,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.3.6;
MARKETING_VERSION = 3.3.7;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -1196,7 +1200,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2154;
CURRENT_PROJECT_VERSION = 2155;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1270,7 +1274,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.3.6;
MARKETING_VERSION = 3.3.7;
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = (
"$(inherited)",
@@ -1429,7 +1433,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2154;
CURRENT_PROJECT_VERSION = 2155;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1441,7 +1445,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.3.6;
MARKETING_VERSION = 3.3.7;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
@@ -1472,7 +1476,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2154;
CURRENT_PROJECT_VERSION = 2155;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1485,7 +1489,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.3.6;
MARKETING_VERSION = 3.3.7;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1515,7 +1519,7 @@
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2154;
CURRENT_PROJECT_VERSION = 2155;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1596,7 +1600,7 @@
"@executable_path/../../Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)";
MARKETING_VERSION = 3.3.6;
MARKETING_VERSION = 3.3.7;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
@@ -1627,7 +1631,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2154;
CURRENT_PROJECT_VERSION = 2155;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1709,7 +1713,7 @@
"@executable_path/../../Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)";
MARKETING_VERSION = 3.3.6;
MARKETING_VERSION = 3.3.7;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1786,7 +1790,10 @@
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited) ";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
@@ -1851,7 +1858,10 @@
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited) ";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;

View File

@@ -9,6 +9,7 @@
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>3B52.1</string>
<string>C617.1</string>
</array>
</dict>

View File

@@ -1273,11 +1273,11 @@ PODS:
- React-Core
- react-native-keep-awake (1.3.1):
- React-Core
- react-native-mmkv-storage (0.11.2):
- react-native-mmkv-storage (12.0.0):
- DoubleConversion
- glog
- hermes-engine
- MMKV (~> 1.3.9)
- MMKV (~> 1.3.14)
- RCT-Folly (= 2024.11.18.00)
- RCTRequired
- RCTTypeSafety
@@ -1372,7 +1372,7 @@ PODS:
- react-native-screenguard (1.0.0):
- React-Core
- SDWebImage (~> 5.11.1)
- react-native-share-extension (2.9.0):
- react-native-share-extension (2.9.5):
- React
- react-native-sodium (1.6.5):
- React
@@ -1770,15 +1770,53 @@ PODS:
- Yoga
- RNIap (12.16.2):
- React-Core
- RNImageCropPicker (0.40.2):
- RNImageCropPicker (0.51.1):
- DoubleConversion
- glog
- hermes-engine
- RCT-Folly (= 2024.11.18.00)
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-NativeModulesApple
- React-RCTFabric
- React-RCTImage
- RNImageCropPicker/QBImagePickerController (= 0.40.2)
- TOCropViewController
- RNImageCropPicker/QBImagePickerController (0.40.2):
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- RNImageCropPicker/QBImagePickerController (= 0.51.1)
- TOCropViewController (~> 2.8.0)
- Yoga
- RNImageCropPicker/QBImagePickerController (0.51.1):
- DoubleConversion
- glog
- hermes-engine
- RCT-Folly (= 2024.11.18.00)
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-NativeModulesApple
- React-RCTFabric
- React-RCTImage
- TOCropViewController
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- TOCropViewController (~> 2.8.0)
- Yoga
- RNKeychain (4.0.5):
- React
- RNNotifee (7.4.9):
@@ -1975,7 +2013,7 @@ PODS:
- SwiftyRSA (1.7.0):
- SwiftyRSA/ObjC (= 1.7.0)
- SwiftyRSA/ObjC (1.7.0)
- TOCropViewController (2.7.4)
- TOCropViewController (2.8.0)
- toolbar-android (0.2.1):
- React
- Yoga (0.0.0)
@@ -2425,7 +2463,7 @@ SPEC CHECKSUMS:
react-native-image-resizer: 24c5d06fae2176dc0caed4b6396e02befb44064a
react-native-in-app-review: b3d1eed3d1596ebf6539804778272c4c65e4a400
react-native-keep-awake: 03b74eebe4f2bb5e8478fc8f420651a92463b6f8
react-native-mmkv-storage: 51c33c6f6678d67061059cce8189a57c3e47192e
react-native-mmkv-storage: 935d661dc3913a41be70d041aa3ff860d6aa4873
react-native-netinfo: 66c9ac0d0ae92a57a9ed99ab8a75429740700c73
react-native-notification-sounds: ce106d58df0dd384bccbd2e84fb53accab7cc068
react-native-orientation-locker: cc6f357b289a2e0dd2210fea0c52cb8e0727fdaa
@@ -2434,7 +2472,7 @@ SPEC CHECKSUMS:
react-native-quick-sqlite: 1bfc7f1e9acbe9a5aa5c4cc81712e9bde3ab7672
react-native-safe-area-context: 9d72abf6d8473da73033b597090a80b709c0b2f1
react-native-screenguard: 82437eeb0086a90b5e5d7e54130bb04fb406373e
react-native-share-extension: bcb7e466390a9e50c742f4b1019d6f181aedd7ad
react-native-share-extension: fdc6aaab51591a2d445df239c446aaa3a99658ec
react-native-sodium: 285eec063e4232cb67347ef6a434b85e588d38cb
react-native-theme-switch-animation: d90fe2de0d9e87a63cd6235d98cba6e7054e9a10
react-native-webview: 079eca50edf657503318b66687dadfb903731aa8
@@ -2479,7 +2517,7 @@ SPEC CHECKSUMS:
RNFlashList: ff5a0b3113c4cda0eaf4b94df8572ccad3c40fd5
RNGestureHandler: 92e89a04cd0d1c77f383a55d14c15e7f423f4c00
RNIap: f94647b3a3dbd5fa08ad7ed847eb588aa5fe95fe
RNImageCropPicker: 30d770b383d84e1067d82ea7b5ed4fff851bbbb2
RNImageCropPicker: aa81bda9f887e20542b569938cde5ce50a4ec404
RNKeychain: ffd0513e676445c637410b47249460cbf56bc9cb
RNNotifee: dabf3cdd7bfd9340bb84358cc78f635af4bc80e2
RNPrivacySnapshot: ccad3a548338c2f526bb7b1789af3fb0618b7d1d
@@ -2495,7 +2533,7 @@ SPEC CHECKSUMS:
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
SwiftyRSA: 8c6dd1ea7db1b8dc4fb517a202f88bb1354bc2c6
TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654
TOCropViewController: 797deaf39c90e6e9ddd848d88817f6b9a8a09888
toolbar-android: c426ed5bd3dcccfed20fd79533efc0d1ae0ef018
Yoga: 31a098f74c16780569aebd614a0f37a907de0189

File diff suppressed because one or more lines are too long

View File

@@ -21,6 +21,7 @@
"@react-navigation/native": "^6.0.10",
"@react-navigation/native-stack": "6.6.2",
"@sayem314/react-native-keep-awake": "^1.3.1",
"react-native-image-crop-picker": "^0.51.1",
"react": "18.2.0",
"react-native": "0.77.2",
"react-native-actions-shortcuts": "^1.0.1",
@@ -48,7 +49,7 @@
"react-native-navigation-bar-color": "2.0.2",
"react-native-notification-sounds": "0.5.5",
"@shopify/flash-list": "^1.8.0",
"react-native-mmkv-storage": "^0.11.2",
"react-native-mmkv-storage": "^12.0.0",
"react-native-quick-sqlite": "^8.2.7",
"react-native-svg": "^15.12.0",
"react-native-webview": "^13.13.5",
@@ -61,7 +62,6 @@
"react-native-zip-archive": "6.0.9",
"react-native-theme-switch-animation": "^0.6.0",
"@ammarahmed/react-native-background-fetch": "^4.2.2",
"react-native-image-crop-picker": "^0.40.2",
"react-native-url-polyfill": "^2.0.0",
"react-native-screenguard": "^1.0.0",
"@formatjs/intl-locale": "4.0.0",

View File

@@ -1,12 +1,12 @@
{
"name": "@notesnook/mobile",
"version": "3.3.6",
"version": "3.3.7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@notesnook/mobile",
"version": "3.3.6",
"version": "3.3.7",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"workspaces": [
@@ -28361,10 +28361,10 @@
"react-native-gzip": "1.1.0",
"react-native-html-to-pdf-lite": "^0.9.1",
"react-native-iap": "12.16.2",
"react-native-image-crop-picker": "^0.40.2",
"react-native-image-crop-picker": "^0.51.1",
"react-native-in-app-review": "4.3.3",
"react-native-keychain": "4.0.5",
"react-native-mmkv-storage": "^0.11.2",
"react-native-mmkv-storage": "^12.0.0",
"react-native-modal-datetime-picker": "14.0.0",
"react-native-navigation-bar-color": "2.0.2",
"react-native-notification-sounds": "0.5.5",
@@ -44519,10 +44519,13 @@
}
},
"node_modules/react-native-image-crop-picker": {
"version": "0.40.2",
"version": "0.51.1",
"resolved": "https://registry.npmjs.org/react-native-image-crop-picker/-/react-native-image-crop-picker-0.51.1.tgz",
"integrity": "sha512-GIFRyXJgv1dPceKd/hraK9q9V38v45rSg2ONR6RiSePcOJemkHpc/PMU86pq6lWPilDYHSxbZmea2pNMk85ayw==",
"license": "MIT",
"peerDependencies": {
"react-native": ">=0.40.0"
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-image-pan-zoom": {
@@ -44590,9 +44593,9 @@
}
},
"node_modules/react-native-mmkv-storage": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/react-native-mmkv-storage/-/react-native-mmkv-storage-0.11.2.tgz",
"integrity": "sha512-/jbYNOUrwgVU09WyXDK6lFGXqBs+23oR9X37z3N68rwHNiXF5WDyXnT38dU2tF07ZlvmsobNHgdxgTu4kGQUKQ==",
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/react-native-mmkv-storage/-/react-native-mmkv-storage-12.0.0.tgz",
"integrity": "sha512-sssZInILQBquytDDfjosjEdvevwMPk3fqQQjdjfnH362IcsBsApvtT8yJS406Mz9aJ6VhqVsZw/awltsUuPSYg==",
"license": "MIT",
"bin": {
"mmkv-link": "autolink/postlink/run.js"

View File

@@ -1,6 +1,6 @@
{
"name": "@notesnook/mobile",
"version": "3.3.6",
"version": "3.3.7",
"private": true,
"license": "GPL-3.0-or-later",
"workspaces": [

View File

@@ -1,27 +1,27 @@
diff --git a/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java b/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java
index 5de0845..1b158d8 100644
--- a/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java
+++ b/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java
@@ -692,6 +692,7 @@ class PickerModule extends ReactContextBaseJavaModule implements ActivityEventLi
image.putString("mime", options.outMimeType);
diff --git a/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/ImageCropPicker.java b/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/ImageCropPicker.java
index b9c494e..34ef800 100644
--- a/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/ImageCropPicker.java
+++ b/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/ImageCropPicker.java
@@ -679,6 +679,7 @@ class ImageCropPicker implements ActivityEventListener {
image.putInt("size", (int) new File(compressedImagePath).length());
image.putString("modificationDate", String.valueOf(modificationDate));
image.putString("filename", new File(path).getName());
+ image.putString("sourceURL", path);
if (includeBase64) {
image.putString("data", getBase64StringFromFile(compressedImagePath));
diff --git a/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.m b/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.m
index 9f20973..5e14da8 100644
--- a/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.m
+++ b/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.m
@@ -595,8 +595,10 @@ - (void)qb_imagePickerController:
NSString *mimeType = [self determineMimeTypeFromImageData:imageData];
diff --git a/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.mm b/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.mm
index 354ad09..622f779 100644
--- a/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.mm
+++ b/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.mm
@@ -603,7 +603,10 @@ - (void)qb_imagePickerController:(QBImagePickerController *)imagePickerControlle
Boolean isKnownMimeType = [mimeType length] > 0;
+ Boolean isHeicOrHeif = [mimeType isEqualToString:@"image/heic"] || [mimeType isEqualToString:@"image/heif"];
+
ImageResult *imageResult = [[ImageResult alloc] init];
- if (isLossless && useOriginalWidth && useOriginalHeight && isKnownMimeType && !forceJpg) {
+
+ Boolean isHeicOrHeif = [mimeType isEqualToString:@"image/heic"] || [mimeType isEqualToString:@"image/heif"];
+
+ if (isLossless && useOriginalWidth && useOriginalHeight && isKnownMimeType && !forceJpg && !isHeicOrHeif) {
// Use original, unmodified image
imageResult.data = imageData;

View File

@@ -0,0 +1,169 @@
diff --git a/node_modules/react-native-keychain/android/build.gradle b/node_modules/react-native-keychain/android/build.gradle
index bd2fe04..53ce4b1 100755
--- a/node_modules/react-native-keychain/android/build.gradle
+++ b/node_modules/react-native-keychain/android/build.gradle
@@ -51,5 +51,4 @@ dependencies {
//noinspection GradleDynamicVersion
implementation 'com.facebook.react:react-native:+' // From node_modules
implementation 'androidx.annotation:annotation:1.1.0'
- implementation 'com.facebook.conceal:conceal:1.1.3@aar'
}
diff --git a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java
index 61d061e..be49f8a 100644
--- a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java
+++ b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java
@@ -15,7 +15,6 @@ import com.oblador.keychain.PrefsStorage.ResultSet;
import com.oblador.keychain.cipherStorage.CipherStorage;
import com.oblador.keychain.cipherStorage.CipherStorage.DecryptionResult;
import com.oblador.keychain.cipherStorage.CipherStorage.EncryptionResult;
-import com.oblador.keychain.cipherStorage.CipherStorageFacebookConceal;
import com.oblador.keychain.cipherStorage.CipherStorageKeystoreAESCBC;
import com.oblador.keychain.exceptions.CryptoFailedException;
import com.oblador.keychain.exceptions.EmptyParameterException;
@@ -48,7 +47,6 @@ public class KeychainModule extends ReactContextBaseJavaModule {
super(reactContext);
prefsStorage = new PrefsStorage(reactContext);
- addCipherStorageToMap(new CipherStorageFacebookConceal(reactContext));
addCipherStorageToMap(new CipherStorageKeystoreAESCBC());
}
diff --git a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/PrefsStorage.java b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/PrefsStorage.java
index 99448b1..792c24c 100644
--- a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/PrefsStorage.java
+++ b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/PrefsStorage.java
@@ -7,7 +7,6 @@ import android.util.Base64;
import com.facebook.react.bridge.ReactApplicationContext;
import com.oblador.keychain.cipherStorage.CipherStorage.EncryptionResult;
-import com.oblador.keychain.cipherStorage.CipherStorageFacebookConceal;
public class PrefsStorage {
public static final String KEYCHAIN_DATA = "RN_KEYCHAIN";
@@ -35,10 +34,6 @@ public class PrefsStorage {
byte[] bytesForPassword = getBytesForPassword(service);
String cipherStorageName = getCipherStorageName(service);
if (bytesForUsername != null && bytesForPassword != null) {
- if (cipherStorageName == null) {
- // If the CipherStorage name is not found, we assume it is because the entry was written by an older version of this library. The older version used Facebook Conceal, so we default to that.
- cipherStorageName = CipherStorageFacebookConceal.CIPHER_STORAGE_NAME;
- }
return new ResultSet(cipherStorageName, bytesForUsername, bytesForPassword);
}
return null;
diff --git a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/cipherStorage/CipherStorageFacebookConceal.java b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/cipherStorage/CipherStorageFacebookConceal.java
deleted file mode 100644
index 3162f99..0000000
--- a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/cipherStorage/CipherStorageFacebookConceal.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.oblador.keychain.cipherStorage;
-
-import android.os.Build;
-import androidx.annotation.NonNull;
-
-import com.facebook.android.crypto.keychain.AndroidConceal;
-import com.facebook.android.crypto.keychain.SharedPrefsBackedKeyChain;
-import com.facebook.crypto.Crypto;
-import com.facebook.crypto.CryptoConfig;
-import com.facebook.crypto.Entity;
-import com.facebook.crypto.keychain.KeyChain;
-import com.facebook.react.bridge.ReactApplicationContext;
-import com.oblador.keychain.SecurityLevel;
-import com.oblador.keychain.exceptions.CryptoFailedException;
-
-import java.nio.charset.Charset;
-
-public class CipherStorageFacebookConceal implements CipherStorage {
- public static final String CIPHER_STORAGE_NAME = "FacebookConceal";
- public static final String KEYCHAIN_DATA = "RN_KEYCHAIN";
- private final Crypto crypto;
-
- public CipherStorageFacebookConceal(ReactApplicationContext reactContext) {
- KeyChain keyChain = new SharedPrefsBackedKeyChain(reactContext, CryptoConfig.KEY_256);
- this.crypto = AndroidConceal.get().createDefaultCrypto(keyChain);
- }
-
- @Override
- public String getCipherStorageName() {
- return CIPHER_STORAGE_NAME;
- }
-
- @Override
- public int getMinSupportedApiLevel() {
- return Build.VERSION_CODES.JELLY_BEAN;
- }
-
- @Override
- public SecurityLevel securityLevel() {
- return SecurityLevel.ANY;
- }
-
- @Override
- public boolean supportsSecureHardware() {
- return false;
- }
-
- @Override
- public EncryptionResult encrypt(@NonNull String service, @NonNull String username, @NonNull String password, SecurityLevel level) throws CryptoFailedException {
-
- if (!this.securityLevel().satisfiesSafetyThreshold(level)) {
- throw new CryptoFailedException(String.format("Insufficient security level (wants %s; got %s)", level, this.securityLevel()));
- }
-
- if (!crypto.isAvailable()) {
- throw new CryptoFailedException("Crypto is missing");
- }
- Entity usernameEntity = createUsernameEntity(service);
- Entity passwordEntity = createPasswordEntity(service);
-
- try {
- byte[] encryptedUsername = crypto.encrypt(username.getBytes(Charset.forName("UTF-8")), usernameEntity);
- byte[] encryptedPassword = crypto.encrypt(password.getBytes(Charset.forName("UTF-8")), passwordEntity);
-
- return new EncryptionResult(encryptedUsername, encryptedPassword, this);
- } catch (Exception e) {
- throw new CryptoFailedException("Encryption failed for service " + service, e);
- }
- }
-
- @Override
- public DecryptionResult decrypt(@NonNull String service, @NonNull byte[] username, @NonNull byte[] password) throws CryptoFailedException {
- if (!crypto.isAvailable()) {
- throw new CryptoFailedException("Crypto is missing");
- }
- Entity usernameEntity = createUsernameEntity(service);
- Entity passwordEntity = createPasswordEntity(service);
-
- try {
- byte[] decryptedUsername = crypto.decrypt(username, usernameEntity);
- byte[] decryptedPassword = crypto.decrypt(password, passwordEntity);
-
- return new DecryptionResult(
- new String(decryptedUsername, Charset.forName("UTF-8")),
- new String(decryptedPassword, Charset.forName("UTF-8")),
- SecurityLevel.ANY);
- } catch (Exception e) {
- throw new CryptoFailedException("Decryption failed for service " + service, e);
- }
- }
-
- @Override
- public void removeKey(@NonNull String service) {
- // Facebook Conceal stores only one key across all services, so we cannot delete the key (otherwise decryption will fail for encrypted data of other services).
- }
-
- private Entity createUsernameEntity(String service) {
- String prefix = getEntityPrefix(service);
- return Entity.create(prefix + "user");
- }
-
- private Entity createPasswordEntity(String service) {
- String prefix = getEntityPrefix(service);
- return Entity.create(prefix + "pass");
- }
-
- private String getEntityPrefix(String service) {
- return KEYCHAIN_DATA + ":" + service;
- }
-}

View File

@@ -1,14 +0,0 @@
diff --git a/node_modules/react-native-mmkv-storage/android/build.gradle b/node_modules/react-native-mmkv-storage/android/build.gradle
index abb696e..ba35baa 100644
--- a/node_modules/react-native-mmkv-storage/android/build.gradle
+++ b/node_modules/react-native-mmkv-storage/android/build.gradle
@@ -98,7 +98,8 @@ android {
cmake {
cppFlags "-O3 -frtti -fexceptions -Wall -fstack-protector-all"
arguments "-DANDROID_STL=c++_shared",
- "-DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}"
+ "-DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}",
+ "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
abiFilters (*reactNativeArchitectures())
}
}

View File

@@ -28,7 +28,6 @@ import RNFetchBlob from "react-native-blob-util";
import WebView from "react-native-webview";
import { Config } from "./store";
import { db } from "../app/common/database";
import { SUBSCRIPTION_STATUS } from "../app/utils/constants";
export const fetchHandle = createRef();
export const HtmlLoadingWebViewAgent = React.memo(
@@ -40,6 +39,7 @@ export const HtmlLoadingWebViewAgent = React.memo(
const webview = useRef();
const premium = useRef(false);
const corsProxy = Config.corsProxy;
const [isLoggedIn, setIsLoggedIn] = useState();
useImperativeHandle(
fetchHandle,
@@ -72,11 +72,8 @@ export const HtmlLoadingWebViewAgent = React.memo(
useEffect(() => {
(async () => {
const user = await db.user.getUser();
const subscriptionStatus =
user?.subscription?.type || SUBSCRIPTION_STATUS.BASIC;
premium.current =
user && subscriptionStatus !== SUBSCRIPTION_STATUS.BASIC;
setIsLoggedIn(!!user);
console.log("USER", !!user);
const clipperPath =
Platform.OS === "ios"
? RNFetchBlob.fs.dirs.MainBundleDir +
@@ -91,6 +88,7 @@ export const HtmlLoadingWebViewAgent = React.memo(
.catch((e) => console.log(e));
})();
}, []);
console.log(isLoggedIn);
return !source || !clipper ? null : (
<WebView
@@ -103,7 +101,8 @@ export const HtmlLoadingWebViewAgent = React.memo(
height: 100,
position: "absolute",
opacity: 0,
zIndex: -1
zIndex: -1,
pointerEvents: "none"
}}
useSharedProcessPool={false}
pointerEvents="none"
@@ -123,7 +122,11 @@ export const HtmlLoadingWebViewAgent = React.memo(
console.log("Error handling webview message", e);
}
}}
injectedJavaScriptBeforeContentLoaded={script(clipper, premium.current)}
injectedJavaScriptBeforeContentLoaded={script(
clipper,
corsProxy,
isLoggedIn
)}
onError={() => {
console.log("Error loading page");
loadHandler.current?.();
@@ -137,9 +140,11 @@ export const HtmlLoadingWebViewAgent = React.memo(
() => true
);
const script = (clipper, pro) => `
const script = (clipper, corsProxy, loggedIn) => `
globalThis.module = {};
${clipper}
function postMessage(type, value) {
if (window.ReactNativeWebView) {
window.ReactNativeWebView.postMessage(
@@ -158,10 +163,10 @@ function postMessage(type, value) {
postMessage("error", globalThis.Clipper.clipPage);
} else {
globalThis.Clipper.clipPage(document,false, {
images: ${pro},
images: ${loggedIn ? "true" : "false"},
inlineImages: false,
styles: false,
corsProxy: undefined
corsProxy: ${corsProxy ? `"${corsProxy}"` : "undefined"}
}).then(result => {
postMessage("html", result);
}).catch(e => {

View File

@@ -267,7 +267,6 @@ const ShareView = () => {
);
const onLoad = useCallback(() => {
console.log(noteContent.current, "current...");
eSendEvent(eOnLoadNote + "shareEditor", {
id: null,
content: {
@@ -747,7 +746,7 @@ const ShareView = () => {
</Paragraph>
{rawData.value && isURL(rawData.value) ? (
<Button
type={mode === 2 ? "inverted" : "transparent"}
type={mode === 2 ? "inverted" : "plain"}
icon={mode === 2 ? "radiobox-marked" : "radiobox-blank"}
onPress={() => changeMode(2)}
title={modes[2].title}
@@ -758,9 +757,9 @@ const ShareView = () => {
/>
) : null}
<Button
type={mode === 1 ? "inverted" : "transparent"}
type={mode === 1 ? "inverted" : "plain"}
icon={mode === 1 ? "radiobox-marked" : "radiobox-blank"}
onPress={() => changeMode(2)}
onPress={() => changeMode(1)}
title={modes[1].title}
height={30}
style={{

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

@@ -104,6 +104,10 @@
"run-ios",
"build-ios",
"build-android",
"build-android-debug",
"e2e-android-debug",
"e2e-android",
"e2e-ios",
"release-android",
"release-android-bundle",
"release-ios",

View File

@@ -26,7 +26,7 @@ declare global {
};
}
global.Clipper = {
globalThis.Clipper = {
clipArticle,
clipPage
};

View File

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

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