Compare commits

...

150 Commits

Author SHA1 Message Date
Abdullah Atta
9b40832b15 web: bump version to 3.1.0-beta.6 2025-04-09 12:17:55 +05:00
Abdullah Atta
e65d03ee17 editor: remove fixed line height 2025-04-09 12:03:16 +05:00
Ammar Ahmed
3dc99dcc7a mobile: fix auto theme switching 2025-04-09 12:03:15 +05:00
Ammar Ahmed
3afde8da9a mobile: fix last heading not shown in toc 2025-04-09 12:03:15 +05:00
Ammar Ahmed
3f20c6b6dd editor: add missing node types in editor 2025-04-09 12:03:15 +05:00
01zulfi
2711db0060 web: fix command palette not scrolling (#7881)
* Remove overflow: hidden styling from GroupedVirtuoso

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-09 12:03:15 +05:00
Abdullah Atta
bb21412b16 web: fix note counts not updating in tags list 2025-04-09 12:03:15 +05:00
Abdullah Atta
3c9ee4e2be web: fix note counts not updating in notebooks list 2025-04-09 12:03:15 +05:00
01zulfi
8aea836622 web: fix search result note item not updating (#7878)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-09 12:03:15 +05:00
Abdullah Atta
1b818e4df0 web: fix item counts not updating in sidebar 2025-04-09 12:03:15 +05:00
Abdullah Atta
a82720422e web: fix filter input removed when no notebooks in list 2025-04-09 12:03:15 +05:00
Ammar Ahmed
1d82193955 mobile: bug fixes 2025-04-09 12:03:15 +05:00
Ammar Ahmed
589265d49d mobile: fix orientation check 2025-04-09 12:03:15 +05:00
Ammar Ahmed
65ca629d8e mobile: fix input padding in side menu on ios 2025-04-09 12:03:15 +05:00
Ammar Ahmed
0a64ba505d mobile: release v3.1.0-beta.3 2025-04-09 12:03:15 +05:00
Abdullah Atta
6a9c4e087d web: bump version to 3.1.0-beta.5 2025-04-09 12:03:15 +05:00
Abdullah Atta
8b8b80a257 web: remove SharedWorker requirement for multi tab sqlite driver 2025-04-09 12:03:15 +05:00
Abdullah Atta
43e6b48695 web: use service worker for cross-tab communication only as a fallback
This commit basically reverts 1b63b2dccf.
Using service worker for this by default is a bad idea because:

1. It takes some time for the service worker to be installed and ready
which slows down first launch significantly
2. Service worker is not as reliable when updating from version to
version

We can, however, use it as a fallback i.e for devices that don't yet
support shared worker.
2025-04-09 12:03:15 +05:00
Ammar Ahmed
1a7efa8e6f mobile: update intl 2025-04-09 12:03:15 +05:00
Ammar Ahmed
e5bef59efb intl: update po files 2025-04-09 12:03:15 +05:00
Ammar Ahmed
6aad3ea684 mobile: focus keyboard if biometry is disabled 2025-04-09 12:03:15 +05:00
Ammar Ahmed
1f1bb5fa56 mobile: restore pinned notes on reboot 2025-04-09 12:03:15 +05:00
Ammar Ahmed
e4f4d4d533 mobile: cleanup 2025-04-09 12:03:15 +05:00
Ammar Ahmed
c7040fce6f mobile: update deps 2025-04-09 12:03:15 +05:00
Ammar Ahmed
1ed40114b4 mobile: update locales 2025-04-09 12:03:15 +05:00
Ammar Ahmed
31cf989387 mobile: bump version 2025-04-09 12:03:15 +05:00
Ammar Ahmed
143fee45ed mobile: fix virtualization errors 2025-04-09 12:03:15 +05:00
Ammar Ahmed
f0f36a061d mobile: run sync when necessary 2025-04-09 12:03:15 +05:00
Ammar Ahmed
af115ecbc3 mobile: fix slow launch 2025-04-09 12:03:15 +05:00
Ammar Ahmed
bae48d3d8c mobile: fix item counts not showing in side menu 2025-04-09 12:03:15 +05:00
Ammar Ahmed
8246ef5146 mobile: fix minor bugs in tablets 2025-04-09 12:03:15 +05:00
Ammar Ahmed
6247496830 mobile: cleanup 2025-04-09 12:03:15 +05:00
Ammar Ahmed
ccabb942c9 mobile: fix tablet rotation 2025-04-09 12:03:15 +05:00
Ammar Ahmed
6a6b879f10 mobile: fix tablet bugs 2025-04-09 12:03:15 +05:00
Ammar Ahmed
72b0ee3c79 mobile: fix login ui on tablets 2025-04-09 12:03:14 +05:00
Ammar Ahmed
c6c0849098 mobile: add notebooks button in notebook screen to view subnotebooks 2025-04-09 12:03:14 +05:00
Ammar Ahmed
b5990b1337 mobile: fix crash when clicking sort button in trash 2025-04-09 12:03:14 +05:00
Ammar Ahmed
afcf6dcd85 mobile: fix ui 2025-04-09 12:03:14 +05:00
Ammar Ahmed
171c9a156d mobile: fix sorting sheet in reminders 2025-04-09 12:03:14 +05:00
Ammar Ahmed
272a321fc8 mobile: do not call scroll into view on focus 2025-04-09 12:03:14 +05:00
Ammar Ahmed
aa65176bb4 mobile: change item positions 2025-04-09 12:03:14 +05:00
Ammar Ahmed
b4c6ff8f12 mobile: fix check mark color in dialog 2025-04-09 12:03:14 +05:00
Ammar Ahmed
f59b7330a1 mobile: fix logout button not working in user sheet 2025-04-09 12:03:14 +05:00
Ammar Ahmed
8a06d258a0 mobile: minor improvements 2025-04-09 12:03:14 +05:00
Ammar Ahmed
a7c5ecd0b8 mobile: add missing check when dragging to end 2025-04-09 12:03:14 +05:00
Ammar Ahmed
ac656adc31 mobile: fix colors 2025-04-09 12:03:14 +05:00
Ammar Ahmed
b67aceecb4 mobile: update rspack to v1.2.7 2025-04-09 12:03:14 +05:00
Ammar Ahmed
37b870ebe0 mobile: use re.pack v5 with rspack 2025-04-09 12:03:14 +05:00
Ammar Ahmed
7b6c1c981e ci: update to actions/cache@v3 2025-04-09 12:03:14 +05:00
Ammar Ahmed
0eff3707e2 ci: release app to beta track on play 2025-04-09 12:03:14 +05:00
Ammar Ahmed
ce7fb0c339 mobile: release beta 2 2025-04-09 12:03:14 +05:00
Ammar Ahmed
a6bdc0374c mobile: fix linking a note 2025-04-09 12:03:14 +05:00
Ammar Ahmed
4967f8878a mobile: fix tree filtering in move notebook 2025-04-09 12:03:14 +05:00
Ammar Ahmed
310cc2f731 mobile: fix items hides behind selection bar 2025-04-09 12:03:14 +05:00
Ammar Ahmed
dae4fa5579 mobile: cleanup 2025-04-09 12:03:14 +05:00
Ammar Ahmed
b3adc37f98 mobile: fix breadcrumbs 2025-04-09 12:03:14 +05:00
Ammar Ahmed
1eb619d863 mobile: fix properties not opening 2025-04-09 12:03:14 +05:00
Ammar Ahmed
f3cad8f0b8 mobile: fix ui 2025-04-09 12:03:14 +05:00
Ammar Ahmed
45a9a36bfb mobile: fix toggle switch color in settings 2025-04-09 12:03:14 +05:00
Ammar Ahmed
d5e9be9aea mobile: fix input border color 2025-04-09 12:03:14 +05:00
Ammar Ahmed
91b5d795c2 mobile: fix separator color 2025-04-09 12:03:14 +05:00
Ammar Ahmed
587c15f12f mobile: fix sidemenu colors 2025-04-09 12:03:14 +05:00
Ammar Ahmed
71278f7ca9 mobile: fix ui 2025-04-09 12:03:14 +05:00
Ammar Ahmed
b5abf2784a mobile: fix zindex 2025-04-09 12:03:14 +05:00
Ammar Ahmed
ae38ffadb5 mobile: fix beta release getting update dialog prompt 2025-04-09 12:03:14 +05:00
Ammar Ahmed
538ff15f8d mobile: fix loading locales in release 2025-04-09 12:03:14 +05:00
Ammar Ahmed
0bf55eb320 mobile: minor ui fixups 2025-04-09 12:03:14 +05:00
Ammar Ahmed
47ab4f3b9d mobile: minor ui fixes 2025-04-09 12:03:14 +05:00
Ammar Ahmed
7f3f726288 ci: add beta release workflow 2025-04-09 12:03:14 +05:00
Ammar Ahmed
5a8d05c9c5 mobile: ui updates 2025-04-09 12:03:14 +05:00
Ammar Ahmed
ced809d375 mobile: fix back navigation bug 2025-04-09 12:03:14 +05:00
Ammar Ahmed
18cc3d3dd5 mobile: fix editor state not restored sometimes on app launch 2025-04-09 12:03:14 +05:00
Ammar Ahmed
3f9bcec036 mobile: fix task list title rendered above status bar in editor 2025-04-09 12:03:14 +05:00
Ammar Ahmed
dba47666e4 mobile: fix selection in sidebar on app launch 2025-04-09 12:03:14 +05:00
Ammar Ahmed
04ae0eec97 mobile: fix various bugs 2025-04-09 12:03:14 +05:00
Ammar Ahmed
35f7d06b27 mobile: refactor and fix bugs 2025-04-09 12:03:14 +05:00
Ammar Ahmed
6beb4410c9 mobile: improve app launch perf 2025-04-09 12:03:14 +05:00
Ammar Ahmed
e955707daf mobile: refactor some sheets into screens 2025-04-09 12:03:14 +05:00
Ammar Ahmed
cd81aa6708 mobile: add test-id 2025-04-09 12:03:14 +05:00
Ammar Ahmed
2d3bc310ce mobile: refactor 2025-04-09 12:03:14 +05:00
Ammar Ahmed
5a974361d6 mobile: use custom cache key for persist store 2025-04-09 12:03:14 +05:00
Ammar Ahmed
42e1259587 mobile: minor refactor 2025-04-09 12:03:14 +05:00
Ammar Ahmed
7d61f9edc4 mobile: refactor 2025-04-09 12:03:14 +05:00
Ammar Ahmed
87b8b4cd27 mobile: refactor 2025-04-09 12:03:14 +05:00
Ammar Ahmed
04703919a1 mobile: fix moving and updating notebooks 2025-04-09 12:03:14 +05:00
Ammar Ahmed
44417069f4 mobile: small ui improvements and perf fixes 2025-04-09 12:03:14 +05:00
Ammar Ahmed
acaa8dbd6b mobile: make skip login work properly 2025-04-09 12:03:14 +05:00
Ammar Ahmed
156540dd29 mobile: more fixes 2025-04-09 12:03:14 +05:00
Ammar Ahmed
99d3902f70 mobile: fix selected item ui 2025-04-09 12:03:14 +05:00
Ammar Ahmed
271fa53890 mobile: fix bugs 2025-04-09 12:03:13 +05:00
Ammar Ahmed
0a496a96fa mobile: fix missing delete button in trash 2025-04-09 12:03:13 +05:00
Ammar Ahmed
19d8eaae47 mobile: fix pro button 2025-04-09 12:03:13 +05:00
Ammar Ahmed
b4275bf116 mobile: enable testing in debug build 2025-04-09 12:03:13 +05:00
Ammar Ahmed
a9fbf7ddd8 mobile: enable debug tests 2025-04-09 12:03:13 +05:00
Ammar Ahmed
ddd1772dc3 mobile: cleanup 2025-04-09 12:03:13 +05:00
Ammar Ahmed
ce780fb897 mobile: fix error set state in render 2025-04-09 12:03:13 +05:00
Ammar Ahmed
c7c173e262 mobile: add pro button in side-menu 2025-04-09 12:03:13 +05:00
Ammar Ahmed
97913ccc48 mobile: fix sidemenu padding top 2025-04-09 12:03:13 +05:00
Ammar Ahmed
5dfbcf6daf mobile: fix minor bugs 2025-04-09 12:03:13 +05:00
Ammar Ahmed
3af074db65 mobile: fix typo 2025-04-09 12:03:13 +05:00
Ammar Ahmed
3566a3072f mobile: make all e2e tests pass 2025-04-09 12:03:13 +05:00
Ammar Ahmed
f0a605107d mobile: minor cleanup 2025-04-09 12:03:13 +05:00
Ammar Ahmed
9fe3af8563 mobile: finalize sidebar and list revamp 2025-04-09 12:03:13 +05:00
Ammar Ahmed
dd80594594 mobile: refactor goToPage 2025-04-09 12:03:13 +05:00
Ammar Ahmed
2df852f1b8 mobile: fix tsc errors 2025-04-09 12:03:13 +05:00
Ammar Ahmed
04e452e3fb mobile: ui redesign 2025-04-09 12:03:13 +05:00
Abdullah Atta
492413673b web: fix tests 2025-04-09 12:03:12 +05:00
Abdullah Atta
0e82a8755b web: bump version to 3.1.0-beta.4 2025-04-09 12:03:12 +05:00
Abdullah Atta
c598a6c779 web: close expanded nav pane on navigation 2025-04-09 12:03:12 +05:00
Abdullah Atta
846e28553d web: force list pane to be visible when reveal item in list is called 2025-04-09 12:03:12 +05:00
Abdullah Atta
694b564172 web: improve item flash animation when revealing item in list
this also fixes a potential memory leak due to event listener not unsubscribing
2025-04-09 12:03:12 +05:00
Abdullah Atta
42ea9f7280 Revert "web: fix list pane not expanding (#7758)"
This reverts commit fd9db3605d.
2025-04-09 12:03:12 +05:00
Abdullah Atta
7555df5b50 web: fix active tab background 2025-04-09 12:03:12 +05:00
Abdullah Atta
f8b73bace6 web: fix Service worker did not respond. error 2025-04-09 12:03:12 +05:00
Abdullah Atta
31d164aa97 web: fix app not starting up on firefox 2025-04-09 12:03:12 +05:00
01zulfi
86d229aa5f web: don't remove properties pane when editor is refocused (#7780)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-09 12:03:12 +05:00
Abdullah Atta
d87c94595f intl: update strings 2025-04-09 12:03:12 +05:00
Abdullah Atta
cffc12fde5 web: replace shared worker with service worker for sqlite 2025-04-09 12:03:12 +05:00
01zulfi
1639178ca9 web: collapse hovered navbar when item is clicked (#7771)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-09 12:03:12 +05:00
Abdullah Atta
d81950352b web: release v3.1.0-beta.3 2025-04-09 12:03:12 +05:00
Ammar Ahmed
748d0e2fe3 web: cleanup 2025-04-09 12:03:12 +05:00
01zulfi
5a50b7f576 web: fix list pane not expanding (#7758)
* web: fix list pane not expanding
* when a nav item was clicked, list pane was removed entirely which made it difficult to re-open it, now when nav item is clicked we manually collapse, expand, or reset the list pane
* open list pane if 'reveal in list' is called
* open list pane if navigated to a different nav item

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: clicking on nav item should not collapse list pane
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: collapse hovered nav pane when notebook/tag item clicked
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

---------

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-09 12:03:12 +05:00
01zulfi
b9dba85a57 web: restore notebook crumbs (#7765)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-09 12:03:12 +05:00
Ammar Ahmed
49054256c7 web: bump version to 3.1.0-beta.2 for desktop and web 2025-04-09 12:03:12 +05:00
Abdullah Atta
38f173c52c web: make editor note properties work like toc 2025-04-09 12:03:12 +05:00
Abdullah Atta
c682844563 web: slightly improve add note button ui 2025-04-09 12:03:12 +05:00
Abdullah Atta
3e475bb4bf web: bump version to 3.1.0-beta.1 2025-04-09 12:03:12 +05:00
Abdullah Atta
319d9af17b desktop: set publish channel to beta for beta builds 2025-04-09 12:03:12 +05:00
Abdullah Atta
117a505bd2 web: minor ui fixes 2025-04-09 12:03:12 +05:00
Abdullah Atta
b49f81d9aa theme: fix button hover colors 2025-04-09 12:03:12 +05:00
Abdullah Atta
7b47c31d88 web: make notesnook branding a bit smaller 2025-04-09 12:03:12 +05:00
Abdullah Atta
b59377f9bd web: minor ui changes and fixes 2025-04-09 12:03:12 +05:00
Abdullah Atta
d0e8337438 web: fix theme not persisting 2025-04-09 12:03:12 +05:00
Abdullah Atta
ca14fd5b8a web: collapse sidebar on navigate if sidebar is temporarily expanded 2025-04-09 12:03:12 +05:00
Abdullah Atta
96e258e0e0 desktop: explicitly deny geolocation permission to electron process 2025-04-09 12:03:12 +05:00
Abdullah Atta
3e22aa2d10 web: fix scrollbar styling in sidebar 2025-04-09 12:03:12 +05:00
Abdullah Atta
47e901d910 web: reset search on navigate 2025-04-09 12:03:12 +05:00
Abdullah Atta
3fb9624be6 web: fix expand sidebar button not working 2025-04-09 12:03:12 +05:00
Abdullah Atta
82666d0c18 web: always show "X" button if there is query in search input 2025-04-09 12:03:12 +05:00
Abdullah Atta
09a5a58027 web: bump version to 3.1.0-beta.0 2025-04-09 12:03:12 +05:00
Abdullah Atta
1acf8cc655 web: use virtualized tree for rendering toc 2025-04-09 12:03:12 +05:00
Abdullah Atta
2756202c32 editor: fix toc level mapping 2025-04-09 12:03:12 +05:00
Abdullah Atta
8e31533ddb web: add support for pre-expanding tree nodes on creation 2025-04-09 12:03:12 +05:00
Abdullah Atta
89f06c4531 web: do not collapse child nodes when collapsing parent 2025-04-09 12:03:12 +05:00
Abdullah Atta
bd8be1665d web: fix all tests 2025-04-09 12:03:12 +05:00
Abdullah Atta
ea0e54c2f0 global: update ui 2025-04-09 12:03:12 +05:00
01zulfi
6719a845c9 web: fix faulty useEffect
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-09 12:02:03 +05:00
01zulfi
e42c858319 web: refactor props for Tags component
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-09 12:02:03 +05:00
01zulfi
56046f5695 web: separate component for tab items in sidebar
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-09 12:02:02 +05:00
01zulfi
a723c3c9c6 web: new sidebar ui
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-09 12:02:02 +05:00
435 changed files with 33206 additions and 25455 deletions

View File

@@ -4,7 +4,7 @@ on: workflow_dispatch
jobs:
build:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
timeout-minutes: 40
env:
CMAKE_C_COMPILER_LAUNCHER: ccache
@@ -22,7 +22,7 @@ jobs:
- name: Use specific Java version for the builds
uses: joschi/setup-jdk@v2
with:
java-version: "11"
java-version: "17"
architecture: "x64"
- name: Install node modules
@@ -58,7 +58,7 @@ jobs:
ccache -p
- name: Cache gradle
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
@@ -129,7 +129,7 @@ jobs:
serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
packageName: com.streetwriters.notesnook
releaseFiles: ${{steps.sign_app.outputs.signedReleaseFile}}
track: alpha
track: beta
status: completed
whatsNewDirectory: apps/mobile/native/android/releasenotes/
@@ -138,7 +138,7 @@ jobs:
with:
draft: true
tag_name: ${{ steps.package-version.outputs.current-version}}-beta-android
name: Notesnook Android v${{ steps.package-version.outputs.current-version}} Beta
name: Notesnook Android v${{ steps.package-version.outputs.current-version}}
repository: streetwriters/notesnook
token: ${{ secrets.GITHUB_TOKEN }}
files: |
@@ -146,6 +146,7 @@ jobs:
apps/mobile/native/android/app/build/outputs/apk/release/notesnook-armeabi-v7a.apk
apps/mobile/native/android/app/build/outputs/apk/release/notesnook-x86.apk
apps/mobile/native/android/app/build/outputs/apk/release/notesnook-x86_64.apk
${{steps.sign_app.outputs.signedReleaseFile}}
- name: Upload sourcemaps
uses: actions/upload-artifact@v4

View File

@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
const path = require("path");
const pkg = require("./package.json");
const buildRoot = process.env.NN_BUILD_ROOT || ".";
const buildFiles = [
@@ -35,6 +36,7 @@ const linuxExecutableName = process.env.NN_PRODUCT_NAME
? process.env.NN_PRODUCT_NAME.toLowerCase().replace(/\s+/g, "-")
: "notesnook";
const year = new Date().getFullYear();
const isBeta = pkg.version.includes("-beta");
module.exports = {
appId: appId,
@@ -194,7 +196,8 @@ module.exports = {
{
provider: "github",
repo: "notesnook",
owner: "streetwriters"
owner: "streetwriters",
channel: isBeta ? "beta" : "latest"
}
]
};

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"name": "@notesnook/desktop",
"productName": "Notesnook",
"description": "Your private note taking space",
"version": "3.0.32",
"version": "3.1.0-beta.6",
"appAppleId": "1544027013",
"private": true,
"main": "./dist/cjs/index.js",

View File

@@ -147,6 +147,11 @@ async function createWindow() {
await AssetManager.loadIcons();
setupDesktopIntegration(config.desktopSettings);
mainWindow.webContents.session.setPermissionRequestHandler(
(webContents, permission, callback) => {
callback(permission === "geolocation" ? false : true);
}
);
mainWindow.webContents.session.setSpellCheckerDictionaryDownloadURL(
"http://dictionaries.notesnook.com/"
);

View File

@@ -19,26 +19,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { i18n } from "@lingui/core";
import { I18nProvider } from "@lingui/react";
import {
ScopedThemeProvider,
THEME_COMPATIBILITY_VERSION,
useThemeEngineStore
} from "@notesnook/theme";
import React, { useEffect } from "react";
import { I18nManager, View } from "react-native";
import { Appearance, I18nManager, StatusBar } from "react-native";
import "react-native-gesture-handler";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { SafeAreaProvider } from "react-native-safe-area-context";
import AppLockedOverlay from "./components/app-lock-overlay";
import DialogProvider from "./components/dialog-provider";
import { withErrorBoundry } from "./components/exception-handler";
import GlobalSafeAreaProvider from "./components/globalsafearea";
import { Toast } from "./components/toast";
import { useAppEvents } from "./hooks/use-app-events";
import { ApplicationHolder } from "./navigation";
import { NotePreviewConfigure } from "./screens/note-preview-configure";
import { RootNavigation } from "./navigation/navigation-stack";
import { themeTrpcClient } from "./screens/settings/theme-selector";
import Notifications from "./services/notifications";
import SettingsService from "./services/settings";
import { TipManager } from "./services/tip-manager";
import { useThemeStore } from "./stores/use-theme-store";
import { changeSystemBarColors, useThemeStore } from "./stores/use-theme-store";
import { useUserStore } from "./stores/use-user-store";
import RNBootSplash from "react-native-bootsplash";
import AppLocked from "./components/app-lock";
I18nManager.allowRTL(false);
I18nManager.forceRTL(false);
@@ -48,11 +52,13 @@ if (appLockEnabled || appLockMode !== "none") {
useUserStore.getState().lockApp(true);
}
RNBootSplash.hide();
const App = (props: { configureMode: "note-preview" }) => {
useAppEvents();
//@ts-ignore
globalThis["IS_MAIN_APP_RUNNING"] = true;
useEffect(() => {
changeSystemBarColors();
SettingsService.onFirstLaunch();
setTimeout(async () => {
await Notifications.get();
@@ -64,42 +70,27 @@ const App = (props: { configureMode: "note-preview" }) => {
}, []);
return (
<View
style={{
height: "100%",
width: "100%",
justifyContent: "center",
alignItems: "center"
}}
>
<View
style={{
position: "absolute",
width: "100%",
height: "100%",
zIndex: -1
}}
pointerEvents="none"
>
<SafeAreaProvider>
<GlobalSafeAreaProvider />
</SafeAreaProvider>
</View>
<SafeAreaProvider>
<StatusBar translucent={true} backgroundColor="transparent" />
<GestureHandlerRootView
style={{
height: "100%",
width: "100%"
}}
>
<GlobalSafeAreaProvider />
{props.configureMode === "note-preview" ? (
<NotePreviewConfigure />
) : (
<ApplicationHolder />
<RootNavigation />
)}
<ScopedThemeProvider value="dialog">
<Toast />
</ScopedThemeProvider>
<DialogProvider />
<AppLocked />
</GestureHandlerRootView>
<AppLockedOverlay />
</View>
</SafeAreaProvider>
);
};
@@ -138,16 +129,27 @@ export const withTheme = (Element: (props: any) => JSX.Element) => {
/* empty */
});
}, 1000);
const listener = Appearance.addChangeListener(({ colorScheme }) => {
if (colorScheme && SettingsService.getProperty("useSystemTheme")) {
useThemeStore.getState().setColorScheme(colorScheme);
}
});
return () => {
listener.remove();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const nextTheme = colorScheme === "dark" ? darkTheme : lightTheme;
if (JSON.stringify(nextTheme) !== JSON.stringify(currTheme)) {
useThemeEngineStore
.getState()
.setTheme(colorScheme === "dark" ? darkTheme : lightTheme);
currTheme = nextTheme;
}
useEffect(() => {
const nextTheme = colorScheme === "dark" ? darkTheme : lightTheme;
if (JSON.stringify(nextTheme) !== JSON.stringify(currTheme)) {
useThemeEngineStore
.getState()
.setTheme(colorScheme === "dark" ? darkTheme : lightTheme);
currTheme = nextTheme;
}
}, [colorScheme, darkTheme, lightTheme]);
return (
<I18nProvider i18n={i18n}>

File diff suppressed because one or more lines are too long

View File

@@ -24,6 +24,7 @@ import { useMessageStore } from "../../stores/use-message-store";
import { useSelectionStore } from "../../stores/use-selection-store";
import { allowedOnPlatform, renderItem } from "./functions";
import { getContainerBorder } from "../../utils/colors";
import { DefaultAppStyles } from "../../utils/styles";
export const Announcement = ({ color }) => {
const { colors } = useThemeColors();
@@ -36,9 +37,8 @@ export const Announcement = ({ color }) => {
style={{
backgroundColor: colors.primary.background,
width: "100%",
paddingHorizontal: 12,
paddingTop: 12,
paddingBottom: 12
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<View
@@ -54,7 +54,7 @@ export const Announcement = ({ color }) => {
<View
style={{
width: "100%",
marginTop: 12
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
>
{announcement?.body

View File

@@ -20,12 +20,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import Paragraph from "../ui/typography/paragraph";
import { getStyle } from "./functions";
import { DefaultAppStyles } from "../../utils/styles";
export const Body = ({ text, style = {} }) => {
return (
<Paragraph
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
...getStyle(style)
}}
>

View File

@@ -23,12 +23,13 @@ import { Linking, View } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { eSendEvent, presentSheet } from "../../services/event-manager";
import { eCloseAnnouncementDialog } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { PricingPlans } from "../premium/pricing-plans";
import SheetProvider from "../sheet-provider";
import { Button } from "../ui/button";
import { allowedOnPlatform, getStyle } from "./functions";
import { DefaultAppStyles } from "../../utils/styles";
export const Cta = ({ actions, style = {}, color, inline }) => {
const { colors } = useThemeColors();
@@ -61,7 +62,7 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
return (
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
...getStyle(style),
flexDirection: inline ? "row" : "column"
}}
@@ -75,7 +76,7 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
<Button
key={item.title}
title={item.title}
fontSize={SIZE.sm}
fontSize={AppFontSize.sm}
type="transparent"
textStyle={{
textDecorationLine: "underline"
@@ -83,7 +84,7 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
onPress={() => onPress(item)}
bold
style={{
height: 30,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
alignSelf: "flex-start",
paddingHorizontal: 0
}}
@@ -95,7 +96,7 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
<Button
key={item.title}
title={item.title}
fontSize={SIZE.sm}
fontSize={AppFontSize.sm}
type="plain"
onPress={() => onPress(item)}
width={null}
@@ -118,7 +119,7 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
<Button
key={item.title}
title={item.title}
fontSize={SIZE.md}
fontSize={AppFontSize.md}
buttonType={{
color: color ? color : colors.primary.accent,
text: color
@@ -130,7 +131,7 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
onPress={() => onPress(item)}
width={250}
style={{
marginBottom: 5,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
borderRadius: 100
}}
/>
@@ -141,14 +142,14 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
<Button
key={item.title}
title={item.title}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
type="plain"
onPress={() => onPress(item)}
width={null}
height={30}
style={{
minWidth: "50%",
marginTop: 5
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
textStyle={{
textDecorationLine: "underline"

View File

@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from "react";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import Paragraph from "../ui/typography/paragraph";
import { getStyle } from "./functions";
@@ -30,7 +30,7 @@ export const Description = ({ text, style = {}, inline }) => {
...getStyle(style),
textAlign: inline ? "left" : style?.textAlign
}}
size={inline ? SIZE.sm : SIZE.md}
size={inline ? AppFontSize.sm : AppFontSize.md}
>
{text}
</Paragraph>

View File

@@ -28,6 +28,7 @@ import { List } from "./list";
import { Photo } from "./photo";
import { SubHeading } from "./subheading";
import { Title } from "./title";
import { DefaultAppStyles } from "../../utils/styles";
export function allowedOnPlatform(platforms) {
if (!platforms) return true;
@@ -53,7 +54,7 @@ const Features = () => {
return (
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
alignItems: "center",
width: "100%"
}}

View File

@@ -22,12 +22,13 @@ import { View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import Paragraph from "../ui/typography/paragraph";
import { getStyle } from "./functions";
import { DefaultAppStyles } from "../../utils/styles";
export const List = ({ items, listType, style = {} }) => {
return (
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingLeft: listType === "ordered" ? 25 : 25,
...getStyle(style)
}}
@@ -36,7 +37,7 @@ export const List = ({ items, listType, style = {} }) => {
<View
key={item.text}
style={{
paddingVertical: 6,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
flexDirection: "row"
}}
>

View File

@@ -18,17 +18,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from "react";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import Heading from "../ui/typography/heading";
import { getStyle } from "./functions";
import { DefaultAppStyles } from "../../utils/styles";
export const SubHeading = ({ text, style = {} }) => {
return (
<Heading
size={SIZE.md + 2}
size={AppFontSize.md + 2}
style={{
marginHorizontal: 12,
marginTop: 12,
marginHorizontal: DefaultAppStyles.GAP,
marginTop: DefaultAppStyles.GAP_VERTICAL,
...getStyle(style)
}}
>

View File

@@ -20,10 +20,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { View } from "react-native";
import { useMessageStore } from "../../stores/use-message-store";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { Button } from "../ui/button";
import Heading from "../ui/typography/heading";
import { getStyle } from "./functions";
import { DefaultAppStyles } from "../../utils/styles";
export const Title = ({ text, style = {}, inline }) => {
const announcements = useMessageStore((state) => state.announcements);
@@ -36,19 +37,19 @@ export const Title = ({ text, style = {}, inline }) => {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginBottom: inline ? 5 : 0
marginBottom: inline ? DefaultAppStyles.GAP_VERTICAL_SMALL : 0
}}
>
<Heading
style={{
marginHorizontal: 12,
marginTop: 12,
marginHorizontal: DefaultAppStyles.GAP,
marginTop: DefaultAppStyles.GAP_VERTICAL,
...getStyle(style),
textAlign: inline ? "left" : style?.textAlign,
flexShrink: 1
}}
numberOfLines={1}
size={inline ? SIZE.md : SIZE.xl}
size={inline ? AppFontSize.md : AppFontSize.xl}
>
{inline ? text?.toUpperCase() : text}
</Heading>
@@ -67,7 +68,7 @@ export const Title = ({ text, style = {}, inline }) => {
right: 0
}}
iconSize={24}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
style={{
borderRadius: 100,
paddingVertical: 0,
@@ -80,9 +81,9 @@ export const Title = ({ text, style = {}, inline }) => {
) : (
<Heading
style={{
marginHorizontal: 12,
marginHorizontal: DefaultAppStyles.GAP,
...getStyle(style),
marginTop: style?.marginTop || 12
marginTop: style?.marginTop || DefaultAppStyles.GAP_VERTICAL
}}
>
{text}

View File

@@ -44,7 +44,6 @@ import SettingsService from "../../services/settings";
import { useSettingStore } from "../../stores/use-setting-store";
import { useUserStore } from "../../stores/use-user-store";
import { NotesnookModule } from "../../utils/notesnook-module";
import { SIZE } from "../../utils/size";
import { Toast } from "../toast";
import { Button } from "../ui/button";
import { IconButton } from "../ui/icon-button";
@@ -54,6 +53,7 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import { strings } from "@notesnook/intl";
import { AppFontSize } from "../../utils/size";
const getUser = () => {
const user = MMKV.getString("user");
@@ -82,7 +82,7 @@ const verifyUserPassword = async (password: string) => {
}
};
const AppLockedOverlay = () => {
const AppLocked = () => {
const initialLaunchBiometricRequest = useRef(true);
const { colors } = useThemeColors();
const user = getUser();
@@ -182,7 +182,13 @@ const AppLockedOverlay = () => {
(prevState === "background" || initialLaunchBiometricRequest.current)
) {
if (SettingsService.shouldLockAppOnEnterForeground()) {
if (useSettingStore.getState().appDidEnterBackgroundForAction) {
useSettingStore.getState().setAppDidEnterBackgroundForAction(false);
return;
}
DatabaseLogger.info("Locking app on entering foreground");
useUserStore.getState().lockApp(true);
}
if (
@@ -283,6 +289,14 @@ const AppLockedOverlay = () => {
keyboardType={
appLockHasPasswordSecurity ? keyboardType : "default"
}
onLayout={async () => {
if (
!biometricsAuthEnabled ||
!(await BiometricService.isBiometryAvailable())
) {
passwordInputRef.current?.focus();
}
}}
placeholder={
appLockHasPasswordSecurity
? keyboardType === "numeric"
@@ -315,7 +329,7 @@ const AppLockedOverlay = () => {
borderRadius: 150,
marginBottom: 10
}}
fontSize={SIZE.md}
fontSize={AppFontSize.md}
/>
</>
) : null}
@@ -336,4 +350,4 @@ const AppLockedOverlay = () => {
) : null;
};
export default AppLockedOverlay;
export default AppLocked;

View File

@@ -45,7 +45,7 @@ import {
eDBItemUpdate,
eOnLoadNote
} from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { Dialog } from "../dialog";
import { presentDialog } from "../dialog/functions";
@@ -58,6 +58,7 @@ import { Pressable } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
const Actions = ({
attachment,
@@ -226,14 +227,15 @@ const Actions = ({
style={{
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
marginBottom: notes && notes.length > 0 ? 0 : 12
marginBottom:
notes && notes.length > 0 ? 0 : DefaultAppStyles.GAP_VERTICAL
}}
>
<Heading
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
size={SIZE.lg}
size={AppFontSize.lg}
>
{filename}
</Heading>
@@ -241,21 +243,21 @@ const Actions = ({
<View
style={{
flexDirection: "row",
marginBottom: 10,
paddingHorizontal: 12,
marginTop: 6,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
paddingHorizontal: DefaultAppStyles.GAP,
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL,
gap: 10
}}
>
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{attachment.mimeType}
</Paragraph>
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{formatBytes(attachment.size)}
</Paragraph>
{notes.length ? (
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{strings.notes(notes.length)}
</Paragraph>
) : null}
@@ -268,7 +270,7 @@ const Actions = ({
context: "local"
});
}}
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
>
{attachment.hash}
@@ -283,16 +285,16 @@ const Actions = ({
style={{
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
marginBottom: 12,
paddingVertical: 12
marginBottom: DefaultAppStyles.GAP_VERTICAL,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<>
<Heading
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
size={SIZE.sm}
size={AppFontSize.sm}
>
{strings.listOf()} {strings.dataTypesPlural.note()}:
</Heading>
@@ -307,14 +309,14 @@ const Actions = ({
openNote(item, (item as any).type === "trash");
}}
style={{
paddingVertical: 12,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
alignItems: "flex-start",
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
key={item.id}
>
<Paragraph size={SIZE.xs}>{item.title}</Paragraph>
<Paragraph size={AppFontSize.xs}>{item.title}</Paragraph>
</Pressable>
))}
</>
@@ -335,7 +337,7 @@ const Actions = ({
icon={item.icon}
loading={loading?.name === item.name}
type="plain"
fontSize={SIZE.sm}
fontSize={AppFontSize.sm}
style={{
borderRadius: 0,
justifyContent: "flex-start",
@@ -347,7 +349,7 @@ const Actions = ({
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{failed ? (

View File

@@ -25,13 +25,14 @@ import { TouchableOpacity, View } from "react-native";
import { db } from "../../common/database";
import { useAttachmentProgress } from "../../hooks/use-attachment-progress";
import { useDBItem } from "../../hooks/use-db-item";
import { SIZE } from "../../utils/size";
import { defaultBorderRadius, AppFontSize } from "../../utils/size";
import { IconButton } from "../ui/icon-button";
import { ProgressCircleComponent } from "../ui/svg/lazy";
import Paragraph from "../ui/typography/paragraph";
import Actions from "./actions";
import { strings } from "@notesnook/intl";
import { Pressable } from "../ui/pressable";
import { DefaultAppStyles } from "../../utils/styles";
function getFileExtension(filename: string) {
const ext = /^.+\.([^.]+)$/.exec(filename);
@@ -76,8 +77,8 @@ export const AttachmentItem = ({
flexDirection: "row",
marginVertical: 5,
justifyContent: "space-between",
padding: 12,
paddingVertical: 6,
padding: DefaultAppStyles.GAP,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
minHeight: 45
}}
>
@@ -101,7 +102,7 @@ export const AttachmentItem = ({
paddingHorizontal: 2,
width: 30,
height: 30,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
>
<Paragraph
@@ -124,7 +125,7 @@ export const AttachmentItem = ({
}}
>
<Paragraph
size={SIZE.sm}
size={AppFontSize.sm}
style={{
flexWrap: "wrap"
}}
@@ -136,7 +137,10 @@ export const AttachmentItem = ({
</Paragraph>
{!hideWhenNotDownloading ? (
<Paragraph color={colors.secondary.paragraph} size={SIZE.xxs}>
<Paragraph
color={colors.secondary.paragraph}
size={AppFontSize.xxs}
>
{strings.fileSize()}: {formatBytes(attachment.size)}
</Paragraph>
) : null}
@@ -159,7 +163,7 @@ export const AttachmentItem = ({
}}
>
<ProgressCircleComponent
size={SIZE.xxl}
size={AppFontSize.xxl}
progress={
currentProgress?.value ? currentProgress?.value / 100 : 0
}

View File

@@ -38,7 +38,7 @@ import { downloadAttachments } from "../../common/filesystem/download-attachment
import { AttachmentGroupProgress } from "../../screens/settings/attachment-group-progress";
import { presentSheet, ToastManager } from "../../services/event-manager";
import { useAttachmentStore } from "../../stores/use-attachment-store";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { Dialog } from "../dialog";
import { presentDialog } from "../dialog/functions";
import { Header } from "../header";
@@ -50,6 +50,7 @@ import Seperator from "../ui/seperator";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { AttachmentItem } from "./attachment-item";
import { DefaultAppStyles } from "../../utils/styles";
const DEFAULT_SORTING: SortOptions = {
sortBy: "dateEdited",
@@ -325,30 +326,31 @@ export const AttachmentDialog = ({
title={strings.manageAttachments()}
renderedInRoute="SettingsGroup"
canGoBack
headerRightButtons={[
{
onPress() {
onCheck();
},
title: strings.recheckAll()
},
{
onPress() {
if (!attachments) return;
presentDialog({
title: strings.doActions.download.attachment(
attachments.placeholders.length
),
positiveText: strings.network.download(),
positivePress: async () => {
downloadAttachments(await attachments.ids());
},
negativeText: strings.cancel()
});
},
title: strings.downloadAllAttachments()
}
]}
// TODO: Add headerRightButtons
// headerRightButtons={[
// {
// onPress() {
// onCheck();
// },
// title: strings.recheckAll()
// },
// {
// onPress() {
// if (!attachments) return;
// presentDialog({
// title: strings.doActions.download.attachment(
// attachments.placeholders.length
// ),
// positiveText: strings.network.download(),
// positivePress: async () => {
// downloadAttachments(await attachments.ids());
// },
// negativeText: strings.cancel()
// });
// },
// title: strings.downloadAllAttachments()
// }
// ]}
/>
) : (
<View
@@ -356,7 +358,7 @@ export const AttachmentDialog = ({
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Heading>{strings.dataTypesPluralCamelCase.attachment()}</Heading>
@@ -369,21 +371,15 @@ export const AttachmentDialog = ({
<IconButton
name="check-all"
style={{
height: 40,
width: 40,
marginRight: 10
}}
color={colors.primary.paragraph}
size={SIZE.lg}
size={AppFontSize.lg}
onPress={onCheck}
/>
<IconButton
name="download"
style={{
height: 40,
width: 40
}}
color={colors.primary.paragraph}
onPress={() => {
if (!attachments) return;
@@ -398,7 +394,7 @@ export const AttachmentDialog = ({
negativeText: strings.cancel()
});
}}
size={SIZE.lg}
size={AppFontSize.lg}
/>
</View>
</View>
@@ -408,7 +404,7 @@ export const AttachmentDialog = ({
style={{
width: "100%",
alignSelf: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
height: "100%"
}}
>
@@ -428,7 +424,7 @@ export const AttachmentDialog = ({
alignItems: "center",
width: "100%",
borderRadius: 10,
padding: 10,
padding: DefaultAppStyles.GAP_SMALL,
borderWidth: 1,
borderColor: colors.primary.border,
gap: 12,
@@ -473,7 +469,7 @@ export const AttachmentDialog = ({
<IconButton
type={rechecker.isWorking ? "errorShade" : "plain"}
name={rechecker.isWorking ? "close" : "check"}
size={SIZE.lg}
size={AppFontSize.lg}
color={
rechecker.isWorking ? colors.error.icon : colors.primary.accent
}
@@ -494,7 +490,7 @@ export const AttachmentDialog = ({
backgroundColor: colors.primary.background,
flexWrap: "wrap",
flexDirection: "row",
paddingVertical: 12
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
contentContainerStyle={{
alignItems: "center"
@@ -511,10 +507,10 @@ export const AttachmentDialog = ({
}
key={item.title}
title={item.title}
fontSize={SIZE.sm}
fontSize={AppFontSize.sm}
style={{
borderRadius: 100,
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
height: 40,
minWidth: 80
}}

View File

@@ -37,6 +37,7 @@ import { hideAuth, initialAuthMode } from "./common";
import { Login } from "./login";
import { Signup } from "./signup";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
export const AuthMode = {
login: 0,
@@ -133,7 +134,7 @@ const AuthModal = () => {
style={{
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
width: "100%",
height: 50,
justifyContent:
@@ -167,7 +168,7 @@ const AuthModal = () => {
marginTop: 2
}}
style={{
paddingHorizontal: 6
paddingHorizontal: DefaultAppStyles.GAP_SMALL
}}
/>
)}

View File

@@ -36,6 +36,7 @@ import { Dialog } from "../dialog";
import BackupService from "../../services/backup";
import { sleep } from "../../utils/time";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
export const ChangePassword = () => {
const passwordInputRef = useRef();
@@ -103,7 +104,7 @@ export const ChangePassword = () => {
<View
style={{
width: "100%",
padding: 12
padding: DefaultAppStyles.GAP
}}
>
<Dialog context="change-password-dialog" />
@@ -148,7 +149,7 @@ export const ChangePassword = () => {
<Button
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: "100%"
}}
loading={loading}

View File

@@ -20,23 +20,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { createRef } from "react";
import { eSendEvent } from "../../services/event-manager";
import { eCloseLoginDialog } from "../../utils/events";
import Navigation from "../../services/navigation";
export const AuthMode = {
login: 0,
signup: 1,
welcomeSignup: 2,
trialSignup: 3
};
export const initialAuthMode = createRef(0);
export function hideAuth() {
eSendEvent(eCloseLoginDialog);
// if (initialAuthMode.current === 2) {
// Navigation.replace(
// {
// name: 'Notes'
// },
// {
// menu: true
// }
// );
// } else {
// Navigation.goBack();
// }
// tabBarRef.current?.unlock();
if (initialAuthMode.current === AuthMode.welcomeSignup) {
Navigation.replace("FluidPanelsView");
} else {
Navigation.goBack();
}
}

View File

@@ -33,6 +33,7 @@ import Seperator from "../ui/seperator";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
export const ForgotPassword = () => {
const { colors } = useThemeColors("sheet");
@@ -107,7 +108,7 @@ export const ForgotPassword = () => {
{sent ? (
<View
style={{
padding: 12,
padding: DefaultAppStyles.GAP,
justifyContent: "center",
alignItems: "center",
paddingBottom: 50
@@ -138,7 +139,7 @@ export const ForgotPassword = () => {
backgroundColor: colors.primary.background,
zIndex: 10,
width: "100%",
padding: 12
padding: DefaultAppStyles.GAP
}}
>
<DialogHeader title={strings.accountRecovery()} />
@@ -164,7 +165,7 @@ export const ForgotPassword = () => {
<Button
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: "100%"
}}
loading={loading}

View File

@@ -17,35 +17,98 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useState } from "react";
import { View } from "react-native";
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import Navigation from "../../services/navigation";
import { Toast } from "../toast";
import { initialAuthMode } from "./common";
import { Button } from "../ui/button";
import { IconButton } from "../ui/icon-button";
import { AuthMode, initialAuthMode } from "./common";
import { Login } from "./login";
import { Signup } from "./signup";
export const AuthMode = {
login: 0,
signup: 1,
welcomeSignup: 2,
trialSignup: 3
};
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
import { DefaultAppStyles } from "../../utils/styles";
import { useSettingStore } from "../../stores/use-setting-store";
const Auth = ({ navigation, route }) => {
const [currentAuthMode, setCurrentAuthMode] = useState(
route?.params?.mode || AuthMode.login
);
const deviceMode = useSettingStore((state) => state.deviceMode);
const { colors } = useThemeColors();
const insets = useGlobalSafeAreaInsets();
initialAuthMode.current = route?.params.mode || AuthMode.login;
useNavigationFocus(navigation, {
onFocus: () => {
//tabBarRef?.current.lock();
initialAuthMode.current = route?.params.mode || AuthMode.login;
}
});
useNavigationFocus(navigation, {});
return (
<View style={{ flex: 1 }}>
<View
style={{
position: "absolute",
paddingTop: insets.top,
top: 0,
zIndex: 999,
backgroundColor:
deviceMode === "mobile" ? colors.secondary.background : null,
width: "100%"
}}
>
<View
style={{
flexDirection: "row",
alignItems: "center",
paddingHorizontal: DefaultAppStyles.GAP,
width: "100%",
height: 50,
justifyContent:
initialAuthMode.current !== AuthMode.welcomeSignup
? "space-between"
: "flex-end"
}}
>
{initialAuthMode.current === AuthMode.welcomeSignup ? null : (
<IconButton
name="arrow-left"
onPress={() => {
if (initialAuthMode.current === 2) {
Navigation.replace("FluidPanelsView");
} else {
Navigation.goBack();
}
}}
color={colors.primary.paragraph}
/>
)}
{initialAuthMode.current !== AuthMode.welcomeSignup ? null : (
<Button
title={strings.skip()}
onPress={() => {
if (initialAuthMode.current === 2) {
Navigation.replace("FluidPanelsView");
} else {
Navigation.goBack();
}
}}
iconSize={16}
type="plain"
iconPosition="right"
icon="chevron-right"
height={25}
iconStyle={{
marginTop: 2
}}
style={{
paddingHorizontal: DefaultAppStyles.GAP_SMALL
}}
/>
)}
</View>
</View>
{currentAuthMode !== AuthMode.login ? (
<Signup
changeMode={(mode) => setCurrentAuthMode(mode)}

View File

@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useEffect, useState } from "react";
import { TouchableOpacity, View, useWindowDimensions } from "react-native";
@@ -24,10 +25,9 @@ import { SheetManager } from "react-native-actions-sheet";
import { DDS } from "../../services/device-detection";
import { eSendEvent } from "../../services/event-manager";
import Sync from "../../services/sync";
import { useSettingStore } from "../../stores/use-setting-store";
import { useUserStore } from "../../stores/use-user-store";
import { eUserLoggedIn } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import SheetProvider from "../sheet-provider";
import { Progress } from "../sheets/progress";
@@ -38,7 +38,7 @@ import Paragraph from "../ui/typography/paragraph";
import { hideAuth } from "./common";
import { ForgotPassword } from "./forgot-password";
import { useLogin } from "./use-login";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
const LoginSteps = {
emailAuth: 1,
@@ -71,8 +71,8 @@ export const Login = ({ changeMode }) => {
}
}, 5000);
});
const deviceMode = useSettingStore((state) => state.deviceMode);
const { width, height } = useWindowDimensions();
const isTablet = width > 600;
useEffect(() => {
async () => {
setStep(LoginSteps.emailAuth);
@@ -96,23 +96,24 @@ export const Login = ({ changeMode }) => {
backgroundColor: colors.primary.background,
zIndex: 10,
width: "100%",
height: "100%",
alignSelf: "center"
}}
>
<View
style={{
justifyContent: "flex-end",
paddingHorizontal: 20,
paddingHorizontal: DefaultAppStyles.GAP,
backgroundColor: colors.secondary.background,
borderBottomWidth: 0.8,
marginBottom: 12,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
borderBottomColor: colors.primary.border,
alignSelf: deviceMode !== "mobile" ? "center" : undefined,
borderWidth: deviceMode !== "mobile" ? 1 : null,
borderColor: deviceMode !== "mobile" ? colors.primary.border : null,
borderRadius: deviceMode !== "mobile" ? 20 : null,
marginTop: deviceMode !== "mobile" ? 50 : null,
width: deviceMode === "mobile" ? null : "50%",
alignSelf: isTablet ? "center" : undefined,
borderWidth: isTablet ? 1 : null,
borderColor: isTablet ? colors.primary.border : null,
borderRadius: isTablet ? 20 : null,
marginTop: isTablet ? 50 : null,
width: !isTablet ? null : "70%",
minHeight: height * 0.4
}}
>
@@ -143,10 +144,10 @@ export const Login = ({ changeMode }) => {
<Heading
style={{
marginBottom: 25,
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
extraBold
size={SIZE.xxl}
size={AppFontSize.xxl}
>
{strings.loginToYourAccount()}
</Heading>
@@ -163,7 +164,7 @@ export const Login = ({ changeMode }) => {
: "99.9%",
backgroundColor: colors.primary.background,
alignSelf: "center",
paddingHorizontal: 20
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Input
@@ -216,7 +217,7 @@ export const Login = ({ changeMode }) => {
title={strings.forgotPassword()}
style={{
alignSelf: "flex-end",
height: 30,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
paddingHorizontal: 0
}}
onPress={() => {
@@ -226,7 +227,7 @@ export const Login = ({ changeMode }) => {
textStyle={{
textDecorationLine: "underline"
}}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
type="plain"
/>
</>
@@ -244,11 +245,8 @@ export const Login = ({ changeMode }) => {
login();
}}
style={{
width: 250,
borderRadius: 100
width: 250
}}
height={50}
fontSize={SIZE.md}
type="accent"
title={!loading ? strings.continue() : null}
/>
@@ -258,19 +256,16 @@ export const Login = ({ changeMode }) => {
title={strings.cancelLogin()}
style={{
alignSelf: "center",
height: 30,
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: 250
}}
onPress={() => {
if (loading) return;
setStep(LoginSteps.emailAuth);
setLoading(false);
}}
textStyle={{
textDecorationLine: "underline"
}}
fontSize={SIZE.xs}
type="errorShade"
fontSize={AppFontSize.xs}
type="secondaryAccented"
/>
)}
@@ -283,17 +278,17 @@ export const Login = ({ changeMode }) => {
activeOpacity={0.8}
style={{
alignSelf: "center",
marginTop: 12,
paddingVertical: 12
marginTop: DefaultAppStyles.GAP_VERTICAL,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<Paragraph
size={SIZE.xs + 1}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
>
{strings.dontHaveAccount()}{" "}
<Paragraph
size={SIZE.xs + 1}
size={AppFontSize.xs}
style={{ color: colors.primary.accent }}
>
{strings.signUp()}

View File

@@ -34,7 +34,7 @@ import Sync from "../../services/sync";
import { clearAllStores } from "../../stores";
import { useUserStore } from "../../stores/use-user-store";
import { eLoginSessionExpired, eUserLoggedIn } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { Dialog } from "../dialog";
import BaseDialog from "../dialog/base-dialog";
@@ -48,18 +48,8 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { LoginSteps, useLogin } from "./use-login";
import { strings } from "@notesnook/intl";
function getObfuscatedEmail(email) {
if (!email) return "";
const [username, provider] = email.split("@");
if (username.length === 1) return `****@${provider}`;
return email.replace(/(.{1})(.*)(?=@)/, function (gp1, gp2, gp3) {
for (let i = 0; i < gp3.length; i++) {
gp2 += "*";
}
return gp2;
});
}
import { getObfuscatedEmail } from "../../utils/functions";
import { DefaultAppStyles } from "../../utils/styles";
export const SessionExpired = () => {
const { colors } = useThemeColors();
@@ -168,7 +158,7 @@ export const SessionExpired = () => {
<View
style={{
width: focused ? "100%" : "99.9%",
padding: 12,
padding: DefaultAppStyles.GAP,
justifyContent: "center",
flex: 1,
backgroundColor: colors.primary.background
@@ -193,7 +183,7 @@ export const SessionExpired = () => {
color={colors.error.icon}
size={50}
/>
<Heading size={SIZE.xxxl} color={colors.primary.heading}>
<Heading size={AppFontSize.xxxl} color={colors.primary.heading}>
{strings.sessionExpired()}
</Heading>
<Paragraph
@@ -224,7 +214,7 @@ export const SessionExpired = () => {
<Button
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: 250,
borderRadius: 100
}}
@@ -236,7 +226,7 @@ export const SessionExpired = () => {
<Button
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: "100%"
}}
onPress={() => {

View File

@@ -17,6 +17,8 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useRef, useState } from "react";
import { TouchableOpacity, View, useWindowDimensions } from "react-native";
import { db } from "../../common/database";
@@ -24,19 +26,17 @@ import { DDS } from "../../services/device-detection";
import { ToastManager } from "../../services/event-manager";
import { clearMessage, setEmailVerifyMessage } from "../../services/message";
import PremiumService from "../../services/premium";
import { useThemeColors } from "@notesnook/theme";
import SettingsService from "../../services/settings";
import { useUserStore } from "../../stores/use-user-store";
import { openLinkInBrowser } from "../../utils/functions";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { Button } from "../ui/button";
import Input from "../ui/input";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { hideAuth } from "./common";
import { useSettingStore } from "../../stores/use-setting-store";
import SettingsService from "../../services/settings";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
export const Signup = ({ changeMode, trial }) => {
const { colors } = useThemeColors();
@@ -50,8 +50,8 @@ export const Signup = ({ changeMode, trial }) => {
const [loading, setLoading] = useState(false);
const setUser = useUserStore((state) => state.setUser);
const setLastSynced = useUserStore((state) => state.setLastSynced);
const deviceMode = useSettingStore((state) => state.deviceMode);
const { width, height } = useWindowDimensions();
const isTablet = width > 600;
const validateInfo = () => {
if (!password.current || !email.current || !confirmPassword.current) {
ToastManager.show({
@@ -105,23 +105,24 @@ export const Signup = ({ changeMode, trial }) => {
backgroundColor: colors.primary.background,
zIndex: 10,
width: "100%",
height: "100%",
alignSelf: "center"
}}
>
<View
style={{
justifyContent: "flex-end",
paddingHorizontal: 20,
paddingHorizontal: DefaultAppStyles.GAP,
backgroundColor: colors.secondary.background,
marginBottom: 20,
borderBottomWidth: 0.8,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
borderBottomColor: colors.primary.border,
alignSelf: deviceMode !== "mobile" ? "center" : undefined,
borderWidth: deviceMode !== "mobile" ? 1 : null,
borderColor: deviceMode !== "mobile" ? colors.primary.border : null,
borderRadius: deviceMode !== "mobile" ? 20 : null,
marginTop: deviceMode !== "mobile" ? 50 : null,
width: deviceMode === "mobile" ? null : "50%",
alignSelf: isTablet ? "center" : undefined,
borderWidth: isTablet ? 1 : null,
borderColor: isTablet ? colors.primary.border : null,
borderRadius: isTablet ? 20 : null,
marginTop: isTablet ? 50 : null,
width: !isTablet ? null : "70%",
minHeight: height * 0.4
}}
>
@@ -153,9 +154,9 @@ export const Signup = ({ changeMode, trial }) => {
extraBold
style={{
marginBottom: 25,
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
size={SIZE.xxl}
size={AppFontSize.xxl}
>
{strings.createYourAccount()}
</Heading>
@@ -164,7 +165,7 @@ export const Signup = ({ changeMode, trial }) => {
<View
style={{
width: DDS.isTab ? "50%" : "100%",
paddingHorizontal: 20,
paddingHorizontal: DefaultAppStyles.GAP,
backgroundColor: colors.primary.background,
alignSelf: "center"
}}
@@ -233,12 +234,12 @@ export const Signup = ({ changeMode, trial }) => {
style={{
marginBottom: 25
}}
size={SIZE.xs}
size={AppFontSize.xxs}
color={colors.secondary.paragraph}
>
{strings.signupAgreement[0]()}
<Paragraph
size={SIZE.xs}
size={AppFontSize.xxs}
onPress={() => {
openLinkInBrowser("https://notesnook.com/tos", colors);
}}
@@ -247,11 +248,12 @@ export const Signup = ({ changeMode, trial }) => {
}}
color={colors.primary.accent}
>
{" "}
{strings.signupAgreement[1]()}
</Paragraph>
</Paragraph>{" "}
{strings.signupAgreement[2]()}
<Paragraph
size={SIZE.xs}
size={AppFontSize.xxs}
onPress={() => {
openLinkInBrowser("https://notesnook.com/privacy", colors);
}}
@@ -260,8 +262,9 @@ export const Signup = ({ changeMode, trial }) => {
}}
color={colors.primary.accent}
>
{" "}
{strings.signupAgreement[3]()}
</Paragraph>
</Paragraph>{" "}
{strings.signupAgreement[4]()}
</Paragraph>
@@ -270,11 +273,8 @@ export const Signup = ({ changeMode, trial }) => {
type="accent"
loading={loading}
onPress={signup}
fontSize={SIZE.md}
style={{
marginRight: 12,
width: 250,
borderRadius: 100
width: 250
}}
/>
@@ -286,14 +286,14 @@ export const Signup = ({ changeMode, trial }) => {
activeOpacity={0.8}
style={{
alignSelf: "center",
marginTop: 12,
paddingVertical: 12
marginTop: DefaultAppStyles.GAP_VERTICAL,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<Paragraph size={SIZE.xs + 1} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{strings.alreadyHaveAccount()}{" "}
<Paragraph
size={SIZE.xs + 1}
size={AppFontSize.xs}
style={{ color: colors.primary.accent }}
>
{strings.login()}

View File

@@ -30,13 +30,14 @@ import {
ToastManager
} from "../../services/event-manager";
import { eCloseSheet } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { Button } from "../ui/button";
import { IconButton } from "../ui/icon-button";
import Input from "../ui/input";
import { Pressable } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { DefaultAppStyles } from "../../utils/styles";
const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
const { colors } = useThemeColors();
@@ -204,9 +205,9 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
}}
onSubmitEditing={onNext}
caretHidden
height={60}
inputStyle={{
fontSize: SIZE.lg,
height: 60,
fontSize: AppFontSize.lg,
textAlign: "center",
letterSpacing: 10,
width: 250
@@ -216,11 +217,13 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
}
enablesReturnKeyAutomatically
containerStyle={{
height: 60,
borderWidth: 0,
width: undefined,
minWidth: "50%"
}}
wrapperStyle={{
height: 60
}}
/>
<Button
@@ -229,9 +232,12 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
width={250}
loading={loading}
onPress={onNext}
style={{
borderRadius: 100
}}
/>
<Button
title={strings.cancel()}
type="secondaryAccented"
onPress={onCancel}
width={250}
/>
<Button
@@ -242,13 +248,6 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
onPress={onRequestSecondaryMethod}
height={30}
/>
<Button
title={strings.cancel()}
type="plain"
onPress={onCancel}
height={30}
/>
</>
) : (
<>
@@ -262,8 +261,8 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
});
}}
style={{
paddingHorizontal: 12,
paddingVertical: 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
marginTop: 0,
flexDirection: "row",
borderRadius: 0,
@@ -275,8 +274,6 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
<IconButton
type="secondaryAccented"
style={{
width: 40,
height: 40,
marginRight: 10
}}
size={15}
@@ -288,7 +285,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
flexShrink: 1
}}
>
<Paragraph size={SIZE.md}>{item.title}</Paragraph>
<Paragraph size={AppFontSize.md}>{item.title}</Paragraph>
</View>
</Pressable>
))}

View File

@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { useThemeColors } from "@notesnook/theme";
import { useRoute } from "@react-navigation/native";
import React, { useCallback, useEffect } from "react";
import { Keyboard, View } from "react-native";
import { Keyboard, TouchableOpacity, View, ViewStyle } from "react-native";
import Animated, {
Easing,
useAnimatedStyle,
@@ -33,20 +33,30 @@ import { editorState } from "../../screens/editor/tiptap/utils";
import { useSelectionStore } from "../../stores/use-selection-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { getElevationStyle } from "../../utils/elevation";
import { SIZE, normalize } from "../../utils/size";
import { Pressable } from "../ui/pressable";
import { AppFontSize, normalize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
interface FloatingButtonProps {
onPress: () => void;
color?: string;
shouldShow?: boolean;
alwaysVisible?: boolean;
icon?: string;
testID?: string;
position?: "left" | "right";
size?: "small" | "large";
style?: ViewStyle;
}
const FloatingButton = ({
onPress,
color,
alwaysVisible = false
alwaysVisible = false,
icon,
testID,
position = "right",
size = "large",
style
}: FloatingButtonProps) => {
const { colors } = useThemeColors();
const deviceMode = useSettingStore((state) => state.deviceMode);
@@ -108,20 +118,26 @@ const FloatingButton = ({
style={[
{
position: "absolute",
right: 12,
right: position === "right" ? DefaultAppStyles.GAP : undefined,
left: position === "left" ? DefaultAppStyles.GAP : undefined,
bottom: 20,
zIndex: 10
zIndex: 10,
...style
},
animatedStyle
]}
>
<Pressable
testID={notesnook.buttons.add}
type="accent"
accentColor={color}
<TouchableOpacity
testID={testID || notesnook.buttons.add}
activeOpacity={0.95}
style={{
...getElevationStyle(5),
borderRadius: 100
borderRadius: size === "small" ? 15 : 20,
borderTopWidth: 0,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 0,
backgroundColor: colors.primary.background
}}
onPress={onPress}
>
@@ -129,23 +145,27 @@ const FloatingButton = ({
style={{
alignItems: "center",
justifyContent: "center",
height: normalize(60),
width: normalize(60)
height: normalize(size === "small" ? 40 : 60),
width: normalize(size === "small" ? 40 : 60),
backgroundColor: colors.primary.shade,
borderRadius: size === "small" ? 15 : 20
}}
>
<Icon
name={
route.name === "Notebooks"
icon
? icon
: route.name === "Notebooks"
? "notebook-plus"
: route.name === "Trash"
? "delete"
: "plus"
}
color={colors.primary.accentForeground}
size={SIZE.xxl}
color={colors.primary.accent}
size={size === "small" ? AppFontSize.xl : AppFontSize.xxxl}
/>
</View>
</Pressable>
</TouchableOpacity>
</Animated.View>
);
};

View File

@@ -23,6 +23,8 @@ import { useMessageStore } from "../../stores/use-message-store";
import { useThemeColors } from "@notesnook/theme";
import { ColorValues } from "../../utils/colors";
import { hexToRGBA } from "../../utils/colors";
import { defaultBorderRadius } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
export const DefaultPlaceholder = ({ color }: { color: string }) => {
const { colors } = useThemeColors();
@@ -40,7 +42,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
<View
style={{
width: "100%",
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{hasAnnoucements ? (
@@ -51,7 +53,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
borderRadius: 10,
marginBottom: 20,
backgroundColor: colors.secondary.background,
padding: 12
padding: DefaultAppStyles.GAP
}}
>
<View
@@ -59,7 +61,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 150,
height: 20,
backgroundColor: colors.primary.hover,
borderRadius: 5,
borderRadius: defaultBorderRadius,
marginBottom: 10
}}
/>
@@ -68,7 +70,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 250,
height: 14,
backgroundColor: colors.primary.hover,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
/>
@@ -78,7 +80,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
height: 15,
backgroundColor: shadeColor,
borderRadius: 3,
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
/>
</View>
@@ -93,7 +95,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
marginBottom: 20,
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 20
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<View
@@ -111,7 +113,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 150,
height: 12,
backgroundColor: colors.secondary.background,
borderRadius: 5,
borderRadius: defaultBorderRadius,
marginBottom: 10
}}
/>
@@ -120,7 +122,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 250,
height: 16,
backgroundColor: colors.secondary.background,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
/>
</View>
@@ -134,7 +136,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
backgroundColor: colors.secondary.background,
borderRadius: 10,
marginBottom: 20,
padding: 5,
padding: DefaultAppStyles.GAP_SMALL,
justifyContent: "space-between",
flexDirection: "row",
alignItems: "center"
@@ -179,7 +181,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 200,
height: 16,
backgroundColor: colors.secondary.background,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
/>
<View
@@ -187,15 +189,15 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: "85%",
height: 13,
backgroundColor: colors.secondary.background,
borderRadius: 5,
marginTop: 10
borderRadius: defaultBorderRadius,
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
/>
<View
style={{
flexDirection: "row",
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
>
<View
@@ -203,7 +205,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 50,
height: 10,
backgroundColor: colors.secondary.background,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
/>
<View
@@ -211,7 +213,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 60,
height: 10,
backgroundColor: colors.secondary.background,
borderRadius: 5,
borderRadius: defaultBorderRadius,
marginLeft: 10
}}
/>

View File

@@ -17,11 +17,10 @@ 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 React from "react";
import { ViewProps } from "react-native";
import Animated, { FadeOutUp } from "react-native-reanimated";
import { useDelayLayout } from "../../hooks/use-delay-layout";
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { View, ViewProps } from "react-native";
import { useDelayLayout } from "../../hooks/use-delay-layout";
import { DefaultPlaceholder } from "./default-placeholder";
import { SettingsPlaceholder } from "./settings-placeholder";
@@ -49,8 +48,7 @@ export default function DelayLayout({
const Placeholder = placeholder[props.type || "default"];
return loading || props.wait ? (
<Animated.View
exiting={animated ? FadeOutUp : undefined}
<View
style={{
backgroundColor: colors.primary.background,
flex: 1,
@@ -58,7 +56,7 @@ export default function DelayLayout({
}}
>
<Placeholder color={props.color || colors.primary.accent} />
</Animated.View>
</View>
) : (
<>{props.children}</>
);

View File

@@ -20,6 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { View } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { defaultBorderRadius } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
export const SettingsPlaceholder = () => {
const { colors } = useThemeColors();
@@ -31,7 +33,7 @@ export const SettingsPlaceholder = () => {
width: 100,
height: 12,
backgroundColor: colors.primary.shade,
borderRadius: 5,
borderRadius: defaultBorderRadius,
marginLeft: 12,
marginBottom: 12
}}
@@ -44,7 +46,7 @@ export const SettingsPlaceholder = () => {
marginBottom: 20,
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 16
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<View
@@ -62,7 +64,7 @@ export const SettingsPlaceholder = () => {
width: 150,
height: 12,
backgroundColor: colors.secondary.background,
borderRadius: 5,
borderRadius: defaultBorderRadius,
marginBottom: 10
}}
/>
@@ -71,7 +73,7 @@ export const SettingsPlaceholder = () => {
width: 250,
height: 16,
backgroundColor: colors.secondary.background,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
/>
</View>
@@ -85,7 +87,7 @@ export const SettingsPlaceholder = () => {
marginBottom: 20,
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 16,
paddingHorizontal: DefaultAppStyles.GAP,
justifyContent: "space-between"
}}
>
@@ -104,7 +106,7 @@ export const SettingsPlaceholder = () => {
width: 150,
height: 12,
backgroundColor: colors.secondary.background,
borderRadius: 5,
borderRadius: defaultBorderRadius,
marginBottom: 10
}}
/>
@@ -113,7 +115,7 @@ export const SettingsPlaceholder = () => {
width: 250,
height: 16,
backgroundColor: colors.secondary.background,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
/>
</View>

View File

@@ -17,6 +17,7 @@ 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 { ScopedThemeProvider } from "@notesnook/theme";
import React, { PropsWithChildren, useEffect, useRef, useState } from "react";
import {
ColorValue,
@@ -30,11 +31,8 @@ import {
} from "react-native";
import useIsFloatingKeyboard from "../../hooks/use-is-floating-keyboard";
import { useSettingStore } from "../../stores/use-setting-store";
import { BouncingView } from "../ui/transitions/bouncing-view";
import { ScopedThemeProvider } from "@notesnook/theme";
import SettingsService from "../../services/settings";
import { useUserStore } from "../../stores/use-user-store";
import { useAppState } from "../../hooks/use-app-state";
import { BouncingView } from "../ui/transitions/bouncing-view";
export interface BaseDialogProps extends PropsWithChildren {
animation?: "fade" | "none" | "slide" | undefined;

View File

@@ -17,16 +17,17 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { ActivityIndicator, StyleSheet, View } from "react-native";
import { StyleSheet, View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { notesnook } from "../../../e2e/test.ids";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { getColorLinearShade } from "../../utils/colors";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { Button } from "../ui/button";
import Paragraph from "../ui/typography/paragraph";
import { getColorLinearShade } from "../../utils/colors";
import { strings } from "@notesnook/intl";
const DialogButtons = ({
onPressPositive,
@@ -46,9 +47,7 @@ const DialogButtons = ({
{
backgroundColor: colors.secondary.background,
height: 60,
borderBottomRightRadius: 5,
borderBottomLeftRadius: 5,
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
borderTopWidth: 0.7,
borderTopColor: getColorLinearShade(
colors.secondary.background,
@@ -58,9 +57,7 @@ const DialogButtons = ({
}
]}
>
{loading ? (
<ActivityIndicator color={colors.primary.accent} size={SIZE.lg} />
) : doneText ? (
{doneText ? (
<View
style={{
flexDirection: "row",
@@ -70,7 +67,7 @@ const DialogButtons = ({
<Icon
color={colors.primary.accent}
name="check-circle-outline"
size={SIZE.md}
size={AppFontSize.md}
/>
<Paragraph color={colors.primary.accent}>{" " + doneText}</Paragraph>
</View>
@@ -86,7 +83,7 @@ const DialogButtons = ({
>
<Button
onPress={onPressNegative}
fontSize={SIZE.md}
fontSize={AppFontSize.sm}
testID={notesnook.ids.default.dialog.no}
type="plain"
bold
@@ -95,11 +92,12 @@ const DialogButtons = ({
{onPressPositive ? (
<Button
onPress={onPressPositive}
fontSize={SIZE.md}
fontSize={AppFontSize.sm}
testID={notesnook.ids.default.dialog.yes}
style={{
marginLeft: 10
}}
loading={loading}
bold
type={positiveType || "transparent"}
title={positiveTitle}
@@ -117,6 +115,6 @@ const styles = StyleSheet.create({
justifyContent: "space-between",
alignItems: "center",
flexDirection: "row",
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}
});

View File

@@ -20,11 +20,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { Text, View, ViewStyle } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { Button } from "../ui/button";
import { PressableProps } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { DefaultAppStyles } from "../../utils/styles";
type DialogHeaderProps = {
icon?: string;
@@ -82,7 +83,7 @@ const DialogHeader = ({
>
<Heading
style={{ textAlign: centered ? "center" : "left" }}
size={SIZE.lg}
size={AppFontSize.lg}
>
{title}{" "}
{titlePart ? (
@@ -97,7 +98,7 @@ const DialogHeader = ({
onPress={button.onPress}
style={{
borderRadius: 100,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
loading={button.loading}
fontSize={13}

View File

@@ -17,33 +17,35 @@ 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 React, { useEffect, useRef, useState } from "react";
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { View } from "react-native";
import { DDS } from "../../services/device-detection";
import {
eSubscribeEvent,
eUnSubscribeEvent
} from "../../services/event-manager";
import { useThemeColors } from "@notesnook/theme";
import { getContainerBorder } from "../../utils/colors";
import { getElevationStyle } from "../../utils/elevation";
import { eCloseSimpleDialog, eOpenSimpleDialog } from "../../utils/events";
import { defaultBorderRadius } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { sleep } from "../../utils/time";
import { Toast } from "../toast";
import { Button } from "../ui/button";
import Input from "../ui/input";
import { Notice } from "../ui/notice";
import Seperator from "../ui/seperator";
import BaseDialog from "./base-dialog";
import DialogButtons from "./dialog-buttons";
import DialogHeader from "./dialog-header";
import { useCallback } from "react";
import { Button } from "../ui/button";
import { getContainerBorder } from "../../utils/colors";
import { Notice } from "../ui/notice";
import { strings } from "@notesnook/intl";
export const Dialog = ({ context = "global" }) => {
const { colors } = useThemeColors();
const [visible, setVisible] = useState(false);
const [checked, setChecked] = useState(false);
const [loading, setLoading] = useState(false);
const values = useRef({
inputValue: undefined
});
@@ -72,14 +74,23 @@ export const Dialog = ({ context = "global" }) => {
const onPressPositive = async () => {
if (dialogInfo.positivePress) {
inputRef.current?.blur();
let result = await dialogInfo.positivePress(
values.current.inputValue || dialogInfo.defaultValue,
checked
);
setLoading(true);
let result;
try {
result = await dialogInfo.positivePress(
values.current.inputValue || dialogInfo.defaultValue,
checked
);
} catch (e) {
/** Empty */
}
setLoading(false);
if (result === false) {
return;
}
}
setChecked(false);
values.current.inputValue = undefined;
setVisible(false);
@@ -125,10 +136,11 @@ export const Dialog = ({ context = "global" }) => {
...getElevationStyle(5),
width: DDS.isTab ? 400 : "85%",
maxHeight: 450,
borderRadius: 5,
borderRadius: defaultBorderRadius,
backgroundColor: colors.primary.background,
paddingTop: 12,
...getContainerBorder(colors.primary.border, 0.5)
...getContainerBorder(colors.primary.border, 0.5),
overflow: "hidden"
};
return visible ? (
@@ -164,7 +176,7 @@ export const Dialog = ({ context = "global" }) => {
{dialogInfo.input ? (
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Input
@@ -188,7 +200,7 @@ export const Dialog = ({ context = "global" }) => {
{dialogInfo?.notice ? (
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Notice
@@ -209,6 +221,7 @@ export const Dialog = ({ context = "global" }) => {
? "check-circle-outline"
: "checkbox-blank-circle-outline"
}
iconColor={checked ? colors.secondary.icon : colors.primary.icon}
style={{
justifyContent: "flex-start"
}}
@@ -224,6 +237,7 @@ export const Dialog = ({ context = "global" }) => {
<DialogButtons
onPressNegative={onNegativePress}
onPressPositive={dialogInfo.positivePress && onPressPositive}
loading={loading}
positiveTitle={dialogInfo.positiveText}
negativeTitle={dialogInfo.negativeText}
positiveType={dialogInfo.positiveType}

View File

@@ -39,7 +39,7 @@ import {
eCloseAppLocKPasswordDailog,
eOpenAppLockPasswordDialog
} from "../../../utils/events";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { sleep } from "../../../utils/time";
import BaseDialog from "../../dialog/base-dialog";
import DialogButtons from "../../dialog/dialog-buttons";
@@ -50,6 +50,7 @@ import { IconButton } from "../../ui/icon-button";
import Input from "../../ui/input";
import Seperator from "../../ui/seperator";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
export const AppLockPassword = () => {
const { colors } = useThemeColors();
@@ -128,7 +129,7 @@ export const AppLockPassword = () => {
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{mode === "change" ? (
@@ -192,7 +193,7 @@ export const AppLockPassword = () => {
height: 25,
marginRight: 5
}}
size={SIZE.lg}
size={AppFontSize.lg}
/>
)
}
@@ -248,7 +249,7 @@ export const AppLockPassword = () => {
setSecureTextEntry(true);
});
}}
iconSize={SIZE.lg}
iconSize={AppFontSize.lg}
type="plain"
iconColor={
accountPass ? colors.primary.accent : colors.primary.icon
@@ -259,7 +260,7 @@ export const AppLockPassword = () => {
alignSelf: "flex-start",
justifyContent: "flex-start",
paddingHorizontal: 0,
height: 30
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
/>
</>

View File

@@ -27,12 +27,13 @@ import {
import { Image as ImageType } from "react-native-image-crop-picker";
import { useThemeColors } from "@notesnook/theme";
import { presentSheet } from "../../../services/event-manager";
import { SIZE } from "../../../utils/size";
import { defaultBorderRadius, AppFontSize } from "../../../utils/size";
import { Button } from "../../ui/button";
import { IconButton } from "../../ui/icon-button";
import { Notice } from "../../ui/notice";
import Paragraph from "../../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
export default function AttachImage({
response,
@@ -50,21 +51,26 @@ export default function AttachImage({
<View
style={{
alignItems: "center",
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<View
style={{
backgroundColor: colors.secondary.background,
marginBottom: 12,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
height: 140,
width: "100%",
borderRadius: 10,
padding: 5,
paddingHorizontal: 12
padding: DefaultAppStyles.GAP_SMALL,
paddingHorizontal: DefaultAppStyles.GAP_SMALL
}}
>
<Paragraph style={{ color: colors.primary.paragraph, marginBottom: 6 }}>
<Paragraph
style={{
color: colors.primary.paragraph,
marginBottom: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
{strings.attachImageHeading(response?.length || 1)}
</Paragraph>
<ScrollView horizontal>
@@ -80,7 +86,7 @@ export default function AttachImage({
style={{
width: 100,
height: 100,
borderRadius: 5,
borderRadius: defaultBorderRadius,
backgroundColor: "black",
marginRight: 6
}}
@@ -96,7 +102,7 @@ export default function AttachImage({
style={{
flexDirection: "row",
alignSelf: "center",
marginBottom: 12,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
alignItems: "center",
width: "100%"
}}
@@ -105,7 +111,7 @@ export default function AttachImage({
}}
>
<IconButton
size={SIZE.lg}
size={AppFontSize.lg}
name={compress ? "checkbox-marked" : "checkbox-blank-outline"}
color={compress ? colors.primary.accent : colors.primary.icon}
style={{
@@ -122,7 +128,7 @@ export default function AttachImage({
flexShrink: 1,
marginLeft: 3
}}
size={SIZE.sm}
size={AppFontSize.sm}
>
{strings.compress()} ({strings.recommended().toLowerCase()})
</Paragraph>
@@ -135,7 +141,7 @@ export default function AttachImage({
size="small"
style={{
width: "100%",
marginBottom: 12
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
/>
) : (
@@ -145,7 +151,7 @@ export default function AttachImage({
size="small"
style={{
width: "100%",
marginBottom: 12
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
/>
)}

View File

@@ -34,6 +34,7 @@ import { Button } from "../../ui/button";
import Input from "../../ui/input";
import { Pressable } from "../../ui/pressable";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
const HEX_COLOR_REGEX_ALPHA =
/^#(?:(?:[\da-fA-F]{3}){1,2}|(?:[\da-fA-F]{4}){1,2})$/;
@@ -105,16 +106,16 @@ const ColorPicker = ({
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<View
style={{
flexDirection: "row",
alignItems: "center",
paddingTop: 10,
columnGap: 10,
marginBottom: 10
paddingTop: DefaultAppStyles.GAP_VERTICAL,
columnGap: DefaultAppStyles.GAP_VERTICAL,
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
>
<Input
@@ -155,7 +156,7 @@ const ColorPicker = ({
<Button
title={strings.addColor()}
style={{
marginBottom: 10
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
onPress={async () => {
if (!selectedColor)

View File

@@ -39,10 +39,11 @@ import {
eOpenJumpToDialog,
eScrollEvent
} from "../../../utils/events";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import BaseDialog from "../../dialog/base-dialog";
import { Pressable } from "../../ui/pressable";
import Paragraph from "../../ui/typography/paragraph";
import { DefaultAppStyles } from "../../../utils/styles";
const JumpToSectionDialog = () => {
const scrollRef = useRef<RefObject<FlatList>>();
@@ -152,13 +153,13 @@ const JumpToSectionDialog = () => {
maxHeight: "65%",
borderRadius: 10,
alignSelf: "center",
padding: 10,
padding: DefaultAppStyles.GAP_SMALL,
paddingTop: 30
}}
>
{loading ? (
<ActivityIndicator
size={SIZE.lg}
size={AppFontSize.lg}
color={colors.primary.accent}
style={{
marginBottom: 20
@@ -188,15 +189,15 @@ const JumpToSectionDialog = () => {
style={{
minWidth: "20%",
width: null,
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
margin: 5,
borderRadius: 100,
height: 30,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
marginVertical: 10
}}
>
<Paragraph
size={SIZE.sm}
size={AppFontSize.sm}
color={
currentIndex === index
? colors.static.white

View File

@@ -28,6 +28,7 @@ import {
} from "../../../services/event-manager";
import { useState } from "react";
import { eCloseLoading, eOpenLoading } from "../../../utils/events";
import { DefaultAppStyles } from "../../../utils/styles";
export const LoadingDialog = () => {
const { colors } = useThemeColors();
@@ -67,7 +68,7 @@ export const LoadingDialog = () => {
style={{
flexDirection: "row",
width: 100,
marginTop: 15
marginTop: DefaultAppStyles.GAP
}}
>
<ProgressBarComponent

View File

@@ -19,10 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useCallback, useEffect, useRef, useState } from "react";
import { Dimensions, TextInput, View } from "react-native";
import {
addOrientationListener,
removeOrientationListener
} from "react-native-orientation";
import Orientation from "react-native-orientation-locker";
import Pdf from "react-native-pdf";
import Animated, { FadeIn, FadeOut } from "react-native-reanimated";
import downloadAttachment from "../../../common/filesystem/download-attachment";
@@ -34,7 +31,7 @@ import {
eUnSubscribeEvent
} from "../../../services/event-manager";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { Dialog } from "../../dialog";
import BaseDialog from "../../dialog/base-dialog";
import { presentDialog } from "../../dialog/functions";
@@ -46,6 +43,7 @@ import { sleep } from "../../../utils/time";
import { MMKV } from "../../../common/database/mmkv";
import { deleteCacheFileByPath } from "../../../common/filesystem/io";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
const WIN_WIDTH = Dimensions.get("window").width;
const WIN_HEIGHT = Dimensions.get("window").height;
@@ -98,9 +96,9 @@ const PDFPreview = () => {
};
useEffect(() => {
addOrientationListener(onOrientationChange);
Orientation.addDeviceOrientationListener(onOrientationChange);
return () => {
removeOrientationListener(onOrientationChange);
Orientation.removeDeviceOrientationListener(onOrientationChange);
};
}, []);
@@ -184,7 +182,7 @@ const PDFPreview = () => {
/>
<Paragraph
style={{
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
color={colors.static.white}
>
@@ -200,7 +198,7 @@ const PDFPreview = () => {
marginTop: insets.top,
flexDirection: "row",
justifyContent: "space-between",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingLeft: 6
}}
>
@@ -216,7 +214,7 @@ const PDFPreview = () => {
style={{
marginRight: 12
}}
size={SIZE.xxl}
size={AppFontSize.xxl}
/>
</View>

View File

@@ -21,7 +21,7 @@ import { useThemeColors } from "@notesnook/theme";
import React, { useEffect } from "react";
import { View } from "react-native";
import { eSendEvent, eSubscribeEvent } from "../../../services/event-manager";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { Dialog } from "../../dialog";
import BaseDialog from "../../dialog/base-dialog";
import DialogContainer from "../../dialog/dialog-container";
@@ -29,6 +29,7 @@ import { Button } from "../../ui/button";
import { ProgressBarComponent } from "../../ui/svg/lazy";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { DefaultAppStyles } from "../../../utils/styles";
export type ProgressOptions = {
progress?: string;
@@ -111,7 +112,7 @@ export default function Progress() {
>
<DialogContainer
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingBottom: 10
}}
noBorder={data?.fillBackground ? true : false}
@@ -121,7 +122,7 @@ export default function Progress() {
style={{
justifyContent: "center",
alignItems: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
gap: 10,
paddingBottom: 20
}}
@@ -131,7 +132,7 @@ export default function Progress() {
textAlign: "center"
}}
color={colors.primary.paragraph}
size={SIZE.lg}
size={AppFontSize.lg}
>
{data?.title}
</Heading>
@@ -148,7 +149,7 @@ export default function Progress() {
style={{
flexDirection: "row",
width: 100,
paddingVertical: 12
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<ProgressBarComponent

View File

@@ -27,13 +27,14 @@ import {
import { useThemeColors } from "@notesnook/theme";
import { getElevationStyle } from "../../../utils/elevation";
import { eCloseResultDialog, eOpenResultDialog } from "../../../utils/events";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import BaseDialog from "../../dialog/base-dialog";
import { Button } from "../../ui/button";
import Seperator from "../../ui/seperator";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { ProFeatures } from "./pro-features";
import { DefaultAppStyles } from "../../../utils/styles";
const ResultDialog = () => {
const { colors } = useThemeColors();
@@ -78,15 +79,15 @@ const ResultDialog = () => {
}}
>
<Heading
size={SIZE.lg}
size={AppFontSize.lg}
textBreakStrategy="balanced"
style={{
alignSelf: "center",
textAlign: "center",
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
maxWidth: "100%",
marginBottom: 10,
paddingHorizontal: 12
marginBottom: DefaultAppStyles.GAP_VERTICAL,
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{dialogData.title}
@@ -94,12 +95,12 @@ const ResultDialog = () => {
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.md}
size={AppFontSize.md}
style={{
alignSelf: "center",
textAlign: "center",
maxWidth: "80%",
lineHeight: SIZE.sm + 5
lineHeight: AppFontSize.sm + 5
}}
>
{dialogData.paragraph}
@@ -109,7 +110,7 @@ const ResultDialog = () => {
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
alignItems: "center",
width: "100%"
}}
@@ -124,17 +125,17 @@ const ResultDialog = () => {
width: "100%",
borderBottomRightRadius: 10,
borderBottomLeftRadius: 10,
paddingVertical: 10
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<Button
title={dialogData.button}
width={null}
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
onPress={close}
fontSize={SIZE.md + 2}
fontSize={AppFontSize.md + 2}
/>
</View>
</View>

View File

@@ -27,9 +27,10 @@ import {
eCloseResultDialog,
eOpenPremiumDialog
} from "../../../utils/events";
import { SIZE } from "../../../utils/size";
import { defaultBorderRadius, AppFontSize } from "../../../utils/size";
import { sleep } from "../../../utils/time";
import Paragraph from "../../ui/typography/paragraph";
import { DefaultAppStyles } from "../../../utils/styles";
export const ProFeatures = ({ count = 6 }) => {
const { colors } = useThemeColors();
@@ -67,13 +68,17 @@ export const ProFeatures = ({ count = 6 }) => {
width: "100%",
height: 40,
paddingHorizontal: 0,
marginBottom: 10,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
alignItems: "center",
borderRadius: 5,
borderRadius: defaultBorderRadius,
justifyContent: "flex-start"
}}
>
<Icon size={SIZE.lg} color={colors.primary.accent} name="check" />
<Icon
size={AppFontSize.lg}
color={colors.primary.accent}
name="check"
/>
<Paragraph style={{ marginLeft: 5, flexShrink: 1 }}>
{item.content}
</Paragraph>
@@ -86,7 +91,7 @@ export const ProFeatures = ({ count = 6 }) => {
await sleep(300);
eSendEvent(eOpenPremiumDialog);
}}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
textDecorationLine: "underline",
color: colors.secondary.paragraph

View File

@@ -41,7 +41,7 @@ import {
eUpdateNoteInEditor
} from "../../../utils/events";
import { deleteItems } from "../../../utils/functions";
import { tabBarRef } from "../../../utils/global-refs";
import { fluidTabsRef } from "../../../utils/global-refs";
import { convertNoteToText } from "../../../utils/note-to-text";
import { sleep } from "../../../utils/time";
import BaseDialog from "../../dialog/base-dialog";
@@ -53,6 +53,7 @@ import Input from "../../ui/input";
import Seperator from "../../ui/seperator";
import Paragraph from "../../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
export class VaultDialog extends Component {
constructor(props) {
@@ -553,7 +554,7 @@ export class VaultDialog extends Component {
item: note
});
if (!DDS.isTab) {
tabBarRef.current?.goToPage(1);
fluidTabsRef.current?.goToPage("editor");
}
});
}
@@ -677,7 +678,7 @@ export class VaultDialog extends Component {
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{(novault ||
@@ -750,7 +751,7 @@ export class VaultDialog extends Component {
: "checkbox-blank-circle-outline"
}
style={{
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
width="100%"
title={strings.deleteAllNotes()}
@@ -847,7 +848,7 @@ export class VaultDialog extends Component {
});
}}
style={{
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
icon="fingerprint"
width="100%"

View File

@@ -37,12 +37,13 @@ import Animated, {
WithSpringConfig,
withTiming
} from "react-native-reanimated";
import { useTabStore } from "../../screens/editor/tiptap/use-tab-store";
import { getAppState } from "../../screens/editor/tiptap/utils";
import { eSendEvent } from "../../services/event-manager";
import { useSettingStore } from "../../stores/use-setting-store";
import { eClearEditor } from "../../utils/events";
import { useSideBarDraggingStore } from "../side-menu/dragging-store";
import { useTabStore } from "../../screens/editor/tiptap/use-tab-store";
import { rootNavigatorRef } from "../../utils/global-refs";
interface TabProps extends ViewProps {
dimensions: { width: number; height: number };
@@ -53,20 +54,22 @@ interface TabProps extends ViewProps {
onDrawerStateChange: (state: boolean) => void;
}
type FluidTabPage = "home" | "editor";
export interface TabsRef {
goToPage: (page: number, animated?: boolean) => void;
goToPage: (page: FluidTabPage, animated?: boolean) => void;
goToIndex: (index: number, animated?: boolean) => 0 | undefined;
unlock: () => boolean;
lock: () => boolean;
openDrawer: (animated?: boolean) => void;
closeDrawer: (animated?: boolean) => void;
page: () => number;
page: () => FluidTabPage;
setScrollEnabled: () => true;
isDrawerOpen: () => boolean;
node: RefObject<Animated.View>;
}
export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
export const FluidPanels = forwardRef<TabsRef, TabProps>(function FluidTabs(
{
children,
dimensions,
@@ -81,9 +84,6 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
const appState = useMemo(() => getAppState(), []);
const deviceMode = useSettingStore((state) => state.deviceMode);
const fullscreen = useSettingStore((state) => state.fullscreen);
const introCompleted = useSettingStore(
(state) => state.settings.introCompleted
);
const translateX = useSharedValue(
widths
? appState &&
@@ -118,26 +118,40 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
const isIPhone = Platform.OS === "ios";
useEffect(() => {
if (introCompleted) {
if (deviceMode === "tablet" || fullscreen) {
translateX.value = 0;
} else {
if (prevWidths.current?.sidebar !== widths.sidebar) {
translateX.value =
appState && appState?.movedAway === false
? editorPosition
: widths.sidebar;
if (translateX.value === editorPosition) {
onChangeTab?.({ i: 2, from: 1 });
}
if (deviceMode === "tablet" || fullscreen) {
translateX.value = 0;
} else {
if (prevWidths.current?.sidebar !== widths.sidebar) {
translateX.value =
appState && appState?.movedAway === false
? editorPosition
: widths.sidebar;
if (translateX.value === editorPosition) {
onChangeTab?.({ i: 2, from: 1 });
}
}
isLoaded.current = true;
prevWidths.current = widths;
}
isLoaded.current = true;
prevWidths.current = widths;
}, [
deviceMode,
widths,
fullscreen,
translateX,
editorPosition,
appState,
onChangeTab
]);
useEffect(() => {
const sub = BackHandler.addEventListener("hardwareBackPress", () => {
if (isDrawerOpen.value) {
if (isDrawerOpen.value && !forcedLock.value) {
const routeNames = rootNavigatorRef.current?.getState().routes;
if (routeNames) {
const currentRoute = routeNames[routeNames.length - 1].name;
if (currentRoute !== "FluidPanelsView") return false;
}
translateX.value = withTiming(homePosition);
onDrawerStateChange(false);
isDrawerOpen.value = false;
@@ -149,34 +163,28 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
sub && sub.remove();
};
}, [
introCompleted,
deviceMode,
widths,
fullscreen,
translateX,
isDrawerOpen,
forcedLock.value,
homePosition,
isDrawerOpen,
onDrawerStateChange,
editorPosition,
appState
translateX
]);
useImperativeHandle(
ref,
(): TabsRef => ({
goToPage: (page: number, animated = true) => {
goToPage: (page: FluidTabPage, animated = true) => {
if (deviceMode === "tablet") {
translateX.value = animated ? withTiming(0) : 0;
return;
}
page = page + 1;
if (page === 1) {
if (page === "home") {
onDrawerStateChange(false);
translateX.value = !animated
? homePosition
: withTiming(homePosition);
currentTab.value = 1;
} else if (page === 2) {
} else if (page === "editor") {
onDrawerStateChange(false);
translateX.value = !animated
? editorPosition
@@ -242,7 +250,7 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
onDrawerStateChange(false);
isDrawerOpen.value = false;
},
page: () => currentTab.value,
page: () => (currentTab.value === 1 ? "home" : "editor"),
setScrollEnabled: () => true,
node: node
}),
@@ -294,8 +302,8 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
const gesture = Gesture.Pan()
.maxPointers(1)
.enabled(enabled && !disabled)
.activeOffsetX([-5, 5])
.failOffsetY([-15, 15])
.activeOffsetX([-10, 10])
.failOffsetY([-10, 10])
.onBegin((event) => {
locked.value = false;
gestureStartValue.value = {

View File

@@ -17,60 +17,52 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useCallback, useEffect, useState } from "react";
import { Platform, StyleSheet, View } from "react-native";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { View } from "react-native";
import {
eSubscribeEvent,
eUnSubscribeEvent
} from "../../services/event-manager";
import useNavigationStore, {
RouteName
} from "../../stores/use-navigation-store";
import { RouteName } from "../../stores/use-navigation-store";
import { useSelectionStore } from "../../stores/use-selection-store";
import { eScrollEvent } from "../../utils/events";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { IconButtonProps } from "../ui/icon-button";
import { Pressable } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { LeftMenus } from "./left-menus";
import { RightMenus } from "./right-menus";
import { Title } from "./title";
type HeaderRightButton = {
title: string;
onPress: () => void;
};
export const Header = ({
renderedInRoute,
onLeftMenuButtonPress,
title,
titleHiddenOnRender,
headerRightButtons,
id,
accentColor,
isBeta,
canGoBack,
onPressDefaultRightButton,
hasSearch,
onSearch
onSearch,
rightButton
}: {
onLeftMenuButtonPress?: () => void;
renderedInRoute?: RouteName;
id?: string;
title: string;
headerRightButtons?: HeaderRightButton[];
titleHiddenOnRender?: boolean;
accentColor?: string;
isBeta?: boolean;
canGoBack?: boolean;
onPressDefaultRightButton?: () => void;
hasSearch?: boolean;
onSearch?: () => void;
rightButton?: IconButtonProps;
}) => {
const { colors } = useThemeColors();
const insets = useGlobalSafeAreaInsets();
const [borderHidden, setBorderHidden] = useState(true);
const selectionMode = useSelectionStore((state) => state.selectionMode);
const isFocused = useNavigationStore((state) => state.focusedRouteId === id);
const [selectedItemsList, selectionMode] = useSelectionStore((state) => [
state.selectedItemsList,
state.selectionMode
]);
const onScroll = useCallback(
(data: { x: number; y: number; id?: string; route: string }) => {
@@ -93,88 +85,48 @@ export const Header = ({
};
}, [borderHidden, onScroll]);
return selectionMode && isFocused ? null : (
<>
<View
style={[
styles.container,
{
marginTop: Platform.OS === "android" ? insets.top : null,
backgroundColor: colors.primary.background,
overflow: "hidden",
borderBottomWidth: 1,
borderBottomColor: borderHidden
? "transparent"
: colors.secondary.background,
justifyContent: "space-between"
}
]}
>
<>
<View style={styles.leftBtnContainer}>
<LeftMenus
canGoBack={canGoBack}
onLeftButtonPress={onLeftMenuButtonPress}
/>
const HeaderWrapper = hasSearch ? Pressable : View;
<Title
isHiddenOnRender={titleHiddenOnRender}
renderedInRoute={renderedInRoute}
id={id}
accentColor={accentColor}
title={title}
isBeta={isBeta}
/>
</View>
<RightMenus
renderedInRoute={renderedInRoute}
id={id}
headerRightButtons={headerRightButtons}
onPressDefaultRightButton={onPressDefaultRightButton}
search={hasSearch}
onSearch={onSearch}
/>
</>
</View>
</>
return (
<View
style={{
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<HeaderWrapper
style={{
flexDirection: "row",
justifyContent: "space-between",
marginTop: DefaultAppStyles.GAP_SMALL,
borderRadius: 10,
paddingVertical: 3,
borderWidth: hasSearch ? 1 : 0,
borderColor: colors.primary.border,
paddingHorizontal: !hasSearch ? 0 : DefaultAppStyles.GAP_SMALL,
alignItems: "center"
}}
testID="search-header"
onPress={() => {
onSearch?.();
}}
>
<LeftMenus
canGoBack={canGoBack}
onLeftButtonPress={onLeftMenuButtonPress}
/>
{hasSearch ? (
<Paragraph>
{selectionMode
? `${selectedItemsList.length} selected`
: strings.searchInRoute(title)}
</Paragraph>
) : (
<Heading size={AppFontSize.lg}>{title}</Heading>
)}
<RightMenus rightButton={rightButton} />
</HeaderWrapper>
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: "row",
zIndex: 11,
height: 50,
maxHeight: 50,
justifyContent: "center",
alignItems: "center",
paddingHorizontal: 12,
width: "100%"
},
leftBtnContainer: {
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
flexShrink: 1
},
leftBtn: {
justifyContent: "center",
alignItems: "center",
height: 40,
width: 40,
borderRadius: 100,
marginLeft: -5,
marginRight: 25
},
rightBtnContainer: {
flexDirection: "row",
alignItems: "center"
},
rightBtn: {
justifyContent: "center",
alignItems: "flex-end",
height: 40,
width: 40,
paddingRight: 0
}
});

View File

@@ -20,10 +20,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { notesnook } from "../../../e2e/test.ids";
import { DDS } from "../../services/device-detection";
import Navigation from "../../services/navigation";
import { useSettingStore } from "../../stores/use-setting-store";
import { tabBarRef } from "../../utils/global-refs";
import { fluidTabsRef } from "../../utils/global-refs";
import { IconButton } from "../ui/icon-button";
export const LeftMenus = ({
@@ -41,7 +40,7 @@ export const LeftMenus = ({
if (onLeftButtonPress) return onLeftButtonPress();
if (!canGoBack) {
if (tabBarRef.current?.isDrawerOpen()) {
if (fluidTabsRef.current?.isDrawerOpen()) {
Navigation.closeDrawer();
} else {
Navigation.openDrawer();
@@ -54,23 +53,14 @@ export const LeftMenus = ({
return isTablet && !canGoBack ? null : (
<IconButton
testID={notesnook.ids.default.header.buttons.left}
style={{
justifyContent: "center",
alignItems: "center",
height: 40,
width: 40,
borderRadius: 100,
marginRight: DDS.isLargeTablet() ? 10 : 7
}}
left={40}
top={40}
right={DDS.isLargeTablet() ? 10 : 10}
onPress={_onLeftButtonPress}
onLongPress={() => {
Navigation.popToTop();
}}
name={canGoBack ? "arrow-left" : "menu"}
color={colors.primary.paragraph}
color={colors.primary.icon}
/>
);
};

View File

@@ -17,127 +17,30 @@ 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 React, { useRef } from "react";
import { Platform, StyleSheet, View } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { Menu } from "react-native-material-menu";
import { notesnook } from "../../../e2e/test.ids";
import {
HeaderRightButton,
RouteName
} from "../../stores/use-navigation-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { SIZE } from "../../utils/size";
import { sleep } from "../../utils/time";
import { Button } from "../ui/button";
import { IconButton } from "../ui/icon-button";
import React from "react";
import { StyleSheet, View } from "react-native";
import { IconButton, IconButtonProps } from "../ui/icon-button";
export const RightMenus = ({
headerRightButtons,
renderedInRoute,
id,
onPressDefaultRightButton,
search,
onSearch
rightButton
}: {
headerRightButtons?: HeaderRightButton[];
renderedInRoute?: RouteName;
id?: string;
onPressDefaultRightButton?: () => void;
search?: boolean;
onSearch?: () => void;
rightButton?: IconButtonProps;
}) => {
const { colors } = useThemeColors();
const { colors: contextMenuColors } = useThemeColors("contextMenu");
const deviceMode = useSettingStore((state) => state.deviceMode);
const menuRef = useRef<Menu>(null);
return (
<View style={styles.rightBtnContainer}>
{search ? (
<IconButton
onPress={onSearch}
testID="icon-search"
name="magnify"
color={colors.primary.paragraph}
style={styles.rightBtn}
/>
) : null}
{deviceMode !== "mobile" ? (
<Button
onPress={onPressDefaultRightButton}
testID={notesnook.ids.default.addBtn}
icon={renderedInRoute === "Trash" ? "delete" : "plus"}
iconSize={SIZE.xl}
type="accent"
hitSlop={{
top: 10,
right: 10,
bottom: 10,
left: 0
}}
{rightButton ? (
<IconButton {...rightButton} color={colors.primary.icon} />
) : (
<View
style={{
marginLeft: 10,
width: 32,
height: 32,
borderRadius: 100,
paddingHorizontal: 0,
borderWidth: 1,
borderColor: colors.primary.accent
width: 40,
height: 40
}}
/>
) : null}
{headerRightButtons && headerRightButtons.length > 0 ? (
<Menu
ref={menuRef}
animationDuration={200}
style={{
borderRadius: 5,
backgroundColor: contextMenuColors.primary.background,
marginTop: 35
}}
onRequestClose={() => {
//@ts-ignore
menuRef.current?.hide();
}}
anchor={
<IconButton
onPress={() => {
//@ts-ignore
menuRef.current?.show();
}}
name="dots-vertical"
color={colors.primary.paragraph}
style={styles.rightBtn}
/>
}
>
{headerRightButtons.map((item) => (
<Button
style={{
justifyContent: "flex-start",
borderRadius: 0,
alignSelf: "flex-start",
width: "100%"
}}
type="plain"
buttonType={{
text: contextMenuColors.primary.paragraph
}}
key={item.title}
title={item.title}
onPress={async () => {
//@ts-ignore
menuRef.current?.hide();
if (Platform.OS === "ios") await sleep(300);
item.onPress();
}}
/>
))}
</Menu>
) : null}
)}
</View>
);
};
@@ -149,10 +52,6 @@ const styles = StyleSheet.create({
},
rightBtn: {
justifyContent: "center",
alignItems: "center",
height: 40,
width: 40,
marginLeft: 10,
paddingRight: 0
alignItems: "center"
}
});

View File

@@ -25,7 +25,7 @@ import {
eUnSubscribeEvent
} from "../../services/event-manager";
import { eScrollEvent } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import Tag from "../ui/tag";
import Heading from "../ui/typography/heading";
@@ -75,7 +75,7 @@ export const Title = ({
{!visible ? (
<Heading
numberOfLines={1}
size={SIZE.lg}
size={AppFontSize.lg}
style={{
flexWrap: "wrap",
marginTop: Platform.OS === "ios" ? -1 : 0
@@ -83,7 +83,7 @@ export const Title = ({
color={accentColor || colors.primary.heading}
>
{isTag ? (
<Heading size={SIZE.xl} color={colors.primary.accent}>
<Heading size={AppFontSize.xl} color={colors.primary.accent}>
#
</Heading>
) : null}

View File

@@ -38,6 +38,7 @@ import RNFetchBlob from "react-native-blob-util";
import Share from "react-native-share";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { useSettingStore } from "../../stores/use-setting-store";
import { DefaultAppStyles } from "../../utils/styles";
const ImagePreview = () => {
const { colors } = useThemeColors("dialog");
@@ -124,7 +125,7 @@ const ImagePreview = () => {
justifyContent: "flex-end",
alignItems: "center",
height: 50,
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
gap: 10
}}
>

View File

@@ -23,31 +23,28 @@ import React from "react";
import { Linking, ScrollView, useWindowDimensions, View } from "react-native";
import { SwiperFlatList } from "react-native-swiper-flatlist";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { eSendEvent } from "../../services/event-manager";
import Navigation from "../../services/navigation";
import SettingsService from "../../services/settings";
import { useSettingStore } from "../../stores/use-setting-store";
import { getElevationStyle } from "../../utils/elevation";
import { eOpenLoginDialog } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AuthMode } from "../auth";
import { AppFontSize } from "../../utils/size";
import { Button } from "../ui/button";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import SettingsService from "../../services/settings";
import { AuthMode } from "../auth/common";
import { DefaultAppStyles } from "../../utils/styles";
const Intro = ({ navigation }) => {
const Intro = () => {
const { colors } = useThemeColors();
const { width, height } = useWindowDimensions();
const deviceMode = useSettingStore((state) => state.deviceMode);
const insets = useGlobalSafeAreaInsets();
const isTablet = width > 600;
const renderItem = React.useCallback(
({ item }) => (
({ item }: { item: (typeof strings.introData)[0] }) => (
<View
style={{
justifyContent: "center",
width: deviceMode !== "mobile" ? width / 2 : width,
paddingHorizontal:
deviceMode !== "mobile" ? (width / 2) * 0.05 : width * 0.05
width: isTablet ? width / 2 : width,
paddingHorizontal: isTablet ? (width / 2) * 0.05 : width * 0.05
}}
>
<View
@@ -76,7 +73,7 @@ const Intro = ({ navigation }) => {
</View>
<View
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
maxWidth: "90%",
width: "100%"
}}
@@ -88,21 +85,21 @@ const Intro = ({ navigation }) => {
marginBottom: 5
}}
extraBold
size={SIZE.xxl}
size={AppFontSize.xxl}
>
{heading()}
</Heading>
))}
{item.body ? (
<Paragraph size={SIZE.sm}>{item.body()}</Paragraph>
<Paragraph size={AppFontSize.sm}>{item.body()}</Paragraph>
) : null}
{item.tesimonial ? (
<Paragraph
style={{
fontStyle: "italic",
fontSize: SIZE.lg
fontSize: AppFontSize.lg
}}
onPress={() => {
Linking.openURL(item.link);
@@ -114,31 +111,37 @@ const Intro = ({ navigation }) => {
</View>
</View>
),
[colors.primary.accent, colors.secondary.background, deviceMode, width]
[colors.primary.accent, colors.secondary.background, isTablet, width]
);
return (
<ScrollView
testID="notesnook.splashscreen"
style={{
width: "100%"
width: "100%",
backgroundColor: colors.primary.background
}}
>
<View
style={{
width: deviceMode !== "mobile" ? width / 2 : "100%",
backgroundColor: colors.secondary.background,
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
alignSelf: deviceMode !== "mobile" ? "center" : undefined,
borderWidth: deviceMode !== "mobile" ? 1 : null,
borderColor: deviceMode !== "mobile" ? colors.primary.border : null,
borderRadius: deviceMode !== "mobile" ? 20 : null,
marginTop: deviceMode !== "mobile" ? 50 : null,
paddingTop: insets.top + 10,
paddingBottom: insets.top + 10,
minHeight: height * 0.7 - (insets.top + insets.bottom)
}}
style={[
{
width: "100%",
backgroundColor: colors.secondary.background,
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
paddingTop: insets.top + 10,
paddingBottom: insets.top + 10,
minHeight: height * 0.7 - (insets.top + insets.bottom)
},
isTablet && {
width: width / 2,
alignSelf: "center",
borderWidth: 1,
borderColor: colors.primary.border,
borderRadius: 20,
marginTop: 50
}
]}
>
<SwiperFlatList
autoplay
@@ -170,23 +173,12 @@ const Intro = ({ navigation }) => {
<Button
width={250}
onPress={async () => {
eSendEvent(eOpenLoginDialog, AuthMode.welcomeSignup);
setTimeout(() => {
SettingsService.set({
introCompleted: true
});
Navigation.replace("Notes", {
canGoBack: false
});
}, 1000);
SettingsService.set({ introCompleted: true });
Navigation.push("Auth", {
mode: AuthMode.welcomeSignup
});
}}
style={{
paddingHorizontal: 24,
alignSelf: "center",
...getElevationStyle(5),
borderRadius: 100
}}
fontSize={SIZE.md}
fontSize={AppFontSize.md}
type="accent"
title={strings.getStarted()}
/>

File diff suppressed because one or more lines are too long

View File

@@ -24,12 +24,13 @@ import { useMessageStore } from "../../../stores/use-message-store";
import { useSelectionStore } from "../../../stores/use-selection-store";
import { Announcement } from "../../announcements/announcement";
import { Card } from "../../list/card";
import { RouteParams } from "../../../stores/use-navigation-store";
export type ListHeaderProps = {
noAnnouncement?: boolean;
color?: string;
messageCard?: boolean;
screen?: string;
screen?: keyof RouteParams;
shouldShow?: boolean;
};
@@ -50,19 +51,11 @@ export const Header = React.memo(
{announcements.length !== 0 && !noAnnouncement ? (
<Announcement color={color || colors.primary.accent} />
) : (screen as any) === "Search" ? null : !shouldShow ? (
<View
style={{
marginBottom: 5,
padding: 0,
width: "100%",
justifyContent: "center",
alignItems: "center"
}}
>
<>
{messageCard ? (
<Card color={color || colors.primary.accent} />
) : null}
</View>
</>
) : null}
</>
);

View File

@@ -17,140 +17,115 @@ 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 { getFormattedDate } from "@notesnook/common";
import { Notebook } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useState } from "react";
import React from "react";
import { View } from "react-native";
import { db } from "../../../common/database";
import { ToastManager } from "../../../services/event-manager";
import { useMenuStore } from "../../../stores/use-menu-store";
import { SIZE } from "../../../utils/size";
import { IconButton } from "../../ui/icon-button";
import { AppFontSize } from "../../../utils/size";
import { DefaultAppStyles } from "../../../utils/styles";
import AppIcon from "../../ui/AppIcon";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { getFormattedDate } from "@notesnook/common";
import { strings } from "@notesnook/intl";
import { IconButton } from "../../ui/icon-button";
import { Pressable } from "../../ui/pressable";
import NotebookScreen from "../../../screens/notebook";
import { db } from "../../../common/database";
export const NotebookHeader = ({
notebook,
onEditNotebook,
totalNotes = 0
totalNotes = 0,
breadcrumbs
}: {
notebook: Notebook;
onEditNotebook: () => void;
totalNotes: number;
breadcrumbs: { id: string; title: string }[];
}) => {
const { colors } = useThemeColors();
const [isPinnedToMenu, setIsPinnedToMenu] = useState(
db.shortcuts.exists(notebook.id)
);
const setMenuPins = useMenuStore((state) => state.setMenuPins);
const onPinNotebook = async () => {
try {
if (isPinnedToMenu) {
await db.shortcuts.remove(notebook.id);
} else {
await db.shortcuts.add({
item: {
id: notebook.id,
type: "notebook"
}
});
ToastManager.show({
heading: strings.shortcutCreated(),
type: "success"
});
}
setIsPinnedToMenu(db.shortcuts.exists(notebook.id));
setMenuPins();
} catch (e) {
console.error(e);
}
};
return (
<View
style={{
marginBottom: 5,
padding: 0,
width: "100%",
paddingVertical: 15,
paddingHorizontal: 12,
alignSelf: "center",
borderRadius: 10,
paddingTop: 25
paddingHorizontal: DefaultAppStyles.GAP,
marginTop: DefaultAppStyles.GAP,
backgroundColor: colors.secondary.background
}}
>
<Paragraph color={colors.secondary.paragraph} size={SIZE.xs}>
{getFormattedDate(notebook.dateModified, "date-time")}
</Paragraph>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center"
width: "100%",
gap: DefaultAppStyles.GAP_VERTICAL,
paddingVertical: DefaultAppStyles.GAP
}}
>
<Heading
style={{
flexShrink: 1
}}
size={SIZE.lg}
>
{notebook.title}
</Heading>
{breadcrumbs && breadcrumbs.length > 0 ? (
<View
style={{
width: "100%",
flexDirection: "row",
alignItems: "center",
flexWrap: "wrap",
paddingBottom: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
{breadcrumbs.map((item, index) => (
<Pressable
onPress={async () => {
const notebook = await db.notebooks.notebook(item.id);
if (!notebook) return;
NotebookScreen.navigate(notebook, true);
}}
key={item.id}
style={{
width: undefined,
flexDirection: "row",
paddingHorizontal: 0,
alignItems: "center"
}}
>
{index === 0 ? null : (
<IconButton
name="chevron-right"
size={16}
top={0}
left={0}
right={0}
bottom={0}
style={{ width: 20, height: 25 }}
/>
)}
<Paragraph size={AppFontSize.xs}>{item.title}</Paragraph>
</Pressable>
))}
</View>
) : null}
<AppIcon name="notebook" size={AppFontSize.xxl} />
<View>
<Heading size={AppFontSize.lg}>{notebook.title}</Heading>
{notebook.description ? (
<Paragraph size={AppFontSize.sm} color={colors.primary.paragraph}>
{notebook.description}
</Paragraph>
) : null}
</View>
<View
style={{
flexDirection: "row"
flexDirection: "row",
gap: DefaultAppStyles.GAP_SMALL
}}
>
<IconButton
name={isPinnedToMenu ? "link-variant-off" : "link-variant"}
onPress={onPinNotebook}
tooltipText={"Create shortcut in side menu"}
style={{
marginRight: 15,
width: 40,
height: 40
}}
type="transparent"
color={isPinnedToMenu ? colors.primary.accent : colors.primary.icon}
size={SIZE.lg}
/>
<IconButton
size={SIZE.lg}
onPress={onEditNotebook}
tooltipText="Edit this notebook"
name="pencil"
type="transparent"
color={colors.primary.icon}
style={{
width: 40,
height: 40
}}
/>
<Paragraph size={AppFontSize.xxs} color={colors.secondary.paragraph}>
{strings.notes(totalNotes || 0)}
</Paragraph>
<Paragraph color={colors.secondary.paragraph} size={AppFontSize.xxs}>
{getFormattedDate(notebook.dateModified, "date-time")}
</Paragraph>
</View>
</View>
{notebook.description ? (
<Paragraph size={SIZE.sm} color={colors.primary.paragraph}>
{notebook.description}
</Paragraph>
) : null}
<Paragraph
style={{
marginTop: 10,
fontStyle: "italic",
fontFamily: undefined
}}
size={SIZE.xs}
color={colors.secondary.paragraph}
>
{strings.notes(totalNotes || 0)}
</Paragraph>
</View>
);
};

View File

@@ -21,16 +21,16 @@ import { GroupHeader, GroupOptions, ItemType } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { TouchableOpacity, View, useWindowDimensions } from "react-native";
import { View } from "react-native";
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
import { presentSheet } from "../../../services/event-manager";
import SettingsService from "../../../services/settings";
import { RouteName } from "../../../stores/use-navigation-store";
import { getContainerBorder } from "../../../utils/colors";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { DefaultAppStyles } from "../../../utils/styles";
import Sort from "../../sheets/sort";
import { Button } from "../../ui/button";
import { IconButton } from "../../ui/icon-button";
import { Pressable } from "../../ui/pressable";
import Heading from "../../ui/typography/heading";
type SectionHeaderProps = {
@@ -56,8 +56,6 @@ export const SectionHeader = React.memo<
onOpenJumpToDialog
}: SectionHeaderProps) {
const { colors } = useThemeColors();
const { fontScale } = useWindowDimensions();
const groupBy = strings.groupByStrings[groupOptions.groupBy]();
const isCompactModeEnabled = useIsCompactModeEnabled(
dataType as "note" | "notebook"
);
@@ -65,104 +63,126 @@ export const SectionHeader = React.memo<
return (
<View
style={{
flexDirection: "row",
alignItems: "center",
width: "95%",
justifyContent: "space-between",
paddingHorizontal: 12,
height: 35 * fontScale,
backgroundColor: colors.secondary.background,
alignSelf: "center",
borderRadius: 5,
marginVertical: 5,
...getContainerBorder(colors.secondary.background, 0.8)
width: "100%",
paddingHorizontal: DefaultAppStyles.GAP,
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
>
<TouchableOpacity
onPress={() => {
onOpenJumpToDialog();
}}
activeOpacity={0.9}
hitSlop={{ top: 10, left: 10, right: 30, bottom: 15 }}
style={{
height: "100%",
justifyContent: "center"
}}
>
<Heading
color={color || colors.primary.accent}
size={SIZE.sm}
style={{
alignSelf: "center",
textAlignVertical: "center"
}}
>
{!item.title || item.title === "" ? strings.pinned() : item.title}
</Heading>
</TouchableOpacity>
<View
style={{
flexDirection: "row",
alignItems: "center"
alignItems: "center",
width: "100%",
alignSelf: "center",
justifyContent: "space-between",
borderBottomWidth: 1,
borderColor: colors.primary.border,
paddingBottom: 1,
paddingTop:
index === 0
? DefaultAppStyles.GAP_VERTICAL
: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
{index === 0 ? (
<>
<Button
onPress={() => {
presentSheet({
component: <Sort screen={screen} type={dataType} />
});
}}
title={groupBy}
icon={
groupOptions.sortDirection === "asc"
? "sort-ascending"
: "sort-descending"
}
height={25}
style={{
borderRadius: 100,
paddingHorizontal: 0,
backgroundColor: "transparent",
marginRight:
dataType === "note" ||
screen === "Notes" ||
dataType === "notebook"
? 10
: 0
}}
type="plain"
iconPosition="right"
/>
<Pressable
onPress={() => {
onOpenJumpToDialog();
}}
hitSlop={{ top: 10, left: 10, right: 30, bottom: 15 }}
style={{
justifyContent: "flex-start",
flexDirection: "row",
width: "auto"
}}
>
<Heading
size={AppFontSize.xxs}
style={{
alignSelf: "center",
textAlignVertical: "center"
}}
color={colors.primary.accent}
>
{!item.title || item.title === ""
? strings.pinned().toUpperCase()
: item.title.toUpperCase()}
</Heading>
</Pressable>
<IconButton
style={{
width: 25,
height: 25
}}
hidden={
dataType !== "note" &&
dataType !== "notebook" &&
screen !== "Notes"
}
testID="icon-compact-mode"
color={colors.secondary.icon}
name={isCompactModeEnabled ? "view-list" : "view-list-outline"}
onPress={() => {
SettingsService.set({
[dataType !== "notebook"
? "notesListMode"
: "notebooksListMode"]: !isCompactModeEnabled
? "compact"
: "normal"
});
}}
size={SIZE.lg - 2}
/>
</>
) : null}
<View
style={{
flexDirection: "row",
alignItems: "center",
gap: DefaultAppStyles.GAP_SMALL
}}
>
{index === 0 ? (
<>
<IconButton
name={
groupOptions.sortDirection === "asc"
? "sort-ascending"
: "sort-descending"
}
color={colors.secondary.icon}
testID="icon-sort"
onPress={() => {
if (!screen) return;
presentSheet({
component: (
<Sort
screen={screen}
type={dataType}
hideGroupOptions={screen === "Reminders"}
/>
)
});
}}
style={{
width: 25,
height: 25
}}
size={AppFontSize.lg - 2}
/>
<IconButton
hidden={
dataType !== "note" &&
dataType !== "notebook" &&
screen !== "Notes"
}
style={{
width: 25,
height: 25
}}
testID="icon-compact-mode"
color={colors.secondary.icon}
name={
isCompactModeEnabled ? "view-list" : "view-list-outline"
}
onPress={() => {
SettingsService.set({
[dataType !== "notebook"
? "notesListMode"
: "notebooksListMode"]: !isCompactModeEnabled
? "compact"
: "normal"
});
}}
size={AppFontSize.lg - 2}
/>
</>
) : null}
{/* <IconButton
style={{
width: 25,
height: 25
}}
color={colors.secondary.icon}
name={"chevron-down"}
size={SIZE.lg - 2}
/> */}
</View>
</View>
</View>
);

View File

@@ -29,24 +29,31 @@ import { EntityLevel, decode } from "entities";
import React from "react";
import { View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { notesnook } from "../../../../e2e/test.ids";
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
import NotebookScreen from "../../../screens/notebook";
import { TaggedNotes } from "../../../screens/notes/tagged";
import useNavigationStore from "../../../stores/use-navigation-store";
import { useRelationStore } from "../../../stores/use-relation-store";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import {
getFormattedDate,
NotebooksWithDateEdited,
TagsWithDateEdited
} from "@notesnook/common";
import { strings } from "@notesnook/intl";
import { notesnook } from "../../../../e2e/test.ids";
import useIsSelected from "../../../hooks/use-selected";
import { useTabStore } from "../../../screens/editor/tiptap/use-tab-store";
import { NotebooksWithDateEdited, TagsWithDateEdited } from "@notesnook/common";
import { useSelectionStore } from "../../../stores/use-selection-store";
import { DefaultAppStyles } from "../../../utils/styles";
import { Properties } from "../../properties";
import { Button } from "../../ui/button";
import AppIcon from "../../ui/AppIcon";
import { IconButton } from "../../ui/icon-button";
import { ReminderTime } from "../../ui/reminder-time";
import { TimeSince } from "../../ui/time-since";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import dayjs from "dayjs";
import { useRoute } from "@react-navigation/native";
type NoteItemProps = {
item: Note | BaseTrashItem<Note>;
@@ -74,6 +81,7 @@ const NoteItem = ({
locked,
noOpen = false
}: NoteItemProps) => {
const route = useRoute();
const isEditingNote = useTabStore(
(state) =>
state.tabs.find((t) => t.id === state.currentTab)?.session?.noteId ===
@@ -85,7 +93,8 @@ const NoteItem = ({
);
const _update = useRelationStore((state) => state.updater);
const primaryColors = isEditingNote ? colors.selected : colors.primary;
const selectionMode = useSelectionStore((state) => state.selectionMode);
const [selected] = useIsSelected(item);
return (
<>
<View
@@ -94,69 +103,27 @@ const NoteItem = ({
flexShrink: 1
}}
>
{!compactMode ? (
<View
{compactMode ? null : (
<Paragraph
style={{
flexDirection: "row",
alignItems: "center",
zIndex: 10,
elevation: 10,
marginBottom: 2.5,
flexWrap: "wrap"
fontSize: AppFontSize.xxxs,
color: colors.secondary.paragraph
}}
>
{notebooks?.items
?.filter(
(item) =>
item.id !== useNavigationStore.getState().focusedRouteId
)
.map((item) => (
<Button
title={
item.title.length > 25
? item.title.slice(0, 25) + "..."
: item.title
}
tooltipText={item.title}
key={item.id}
height={25}
icon="book-outline"
type="secondary"
fontSize={SIZE.xs}
iconSize={SIZE.sm}
textStyle={{
marginRight: 0
}}
style={{
borderRadius: 5,
marginRight: 5,
paddingHorizontal: 6,
marginBottom: 5
}}
onPress={() => {
NotebookScreen.navigate(item, true);
}}
/>
))}
<ReminderTime
reminder={reminder}
color={color?.colorCode}
onPress={() => {
Properties.present(reminder);
}}
style={{
height: 25
}}
/>
</View>
) : null}
{getFormattedDate(
date,
dayjs(date).isBefore(dayjs().subtract(1, "day").hour(23))
? "date"
: "time"
)}
</Paragraph>
)}
{compactMode ? (
<Paragraph
numberOfLines={1}
color={color?.colorCode || primaryColors.heading}
size={SIZE.sm}
size={AppFontSize.sm}
style={{
paddingRight: 10
}}
@@ -167,7 +134,7 @@ const NoteItem = ({
<Heading
numberOfLines={1}
color={color?.colorCode || primaryColors.heading}
size={SIZE.md}
size={AppFontSize.sm}
style={{
paddingRight: 10
}}
@@ -197,8 +164,10 @@ const NoteItem = ({
justifyContent: "flex-start",
alignItems: "center",
width: "100%",
marginTop: 5,
height: SIZE.md + 2
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL,
columnGap: 8,
rowGap: 4,
flexWrap: "wrap"
}}
>
{!isTrash ? (
@@ -206,10 +175,7 @@ const NoteItem = ({
{item.conflicted ? (
<Icon
name="alert-circle"
style={{
marginRight: 6
}}
size={SIZE.sm}
size={AppFontSize.sm}
color={colors.error.accent}
/>
) : null}
@@ -218,10 +184,7 @@ const NoteItem = ({
<Icon
testID="sync-off"
name="sync-off"
size={SIZE.sm}
style={{
marginRight: 6
}}
size={AppFontSize.sm}
color={primaryColors.icon}
/>
) : null}
@@ -230,41 +193,27 @@ const NoteItem = ({
<Icon
testID="pencil-lock"
name="pencil-lock"
size={SIZE.sm}
style={{
marginRight: 6
}}
size={AppFontSize.sm}
color={primaryColors.icon}
/>
) : null}
<TimeSince
style={{
fontSize: SIZE.xs,
color: colors.secondary.paragraph,
marginRight: 6
}}
time={date}
updateFrequency={Date.now() - date < 60000 ? 2000 : 60000}
/>
{attachmentsCount > 0 ? (
<View
style={{
flexDirection: "row",
alignItems: "center",
marginRight: 6,
gap: 2
}}
>
<Icon
name="attachment"
size={SIZE.sm}
size={AppFontSize.sm}
color={primaryColors.icon}
/>
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xxs}
>
{attachmentsCount}
</Paragraph>
@@ -275,10 +224,7 @@ const NoteItem = ({
<Icon
testID="icon-pinned"
name="pin-outline"
size={SIZE.sm}
style={{
marginRight: 6
}}
size={AppFontSize.sm}
color={color?.colorCode || primaryColors.accent}
/>
) : null}
@@ -287,10 +233,7 @@ const NoteItem = ({
<Icon
name="lock"
testID="note-locked-icon"
size={SIZE.sm}
style={{
marginRight: 6
}}
size={AppFontSize.sm}
color={primaryColors.icon}
/>
) : null}
@@ -299,37 +242,82 @@ const NoteItem = ({
<Icon
testID="icon-star"
name="star-outline"
size={SIZE.sm}
style={{
marginRight: 6
}}
size={AppFontSize.sm}
color="orange"
/>
) : null}
{reminder ? (
<ReminderTime
reminder={reminder}
disabled
color={color?.colorCode}
textStyle={{
fontSize: AppFontSize.xxxs
}}
iconSize={AppFontSize.xxxs}
style={{
height: "auto"
}}
/>
) : null}
{notebooks?.items
?.filter(
(item) =>
route.name !== "Notebook" ||
item.id !== useNavigationStore.getState().focusedRouteId
)
.map((item) => (
<View
key={item.id}
style={{
borderRadius: 4,
backgroundColor: colors.secondary.background,
paddingHorizontal: DefaultAppStyles.GAP_SMALL / 2,
borderWidth: 0.5,
borderColor: primaryColors.border,
paddingVertical: 1,
flexDirection: "row",
alignItems: "center",
gap: DefaultAppStyles.GAP_SMALL / 2
}}
>
<AppIcon
name="book-outline"
size={AppFontSize.xxxs}
color={colors.secondary.icon}
/>
<Paragraph
size={AppFontSize.xxxs}
color={colors.secondary.paragraph}
>
{item.title}
</Paragraph>
</View>
))}
{!isTrash && !compactMode && tags
? tags.items?.map((item) =>
item.id ? (
<Button
title={"#" + item.title}
<View
key={item.id}
height={23}
type="plain"
textStyle={{
textDecorationLine: "underline",
color: colors.secondary.paragraph
}}
hitSlop={{ top: 8, bottom: 12, left: 0, right: 0 }}
fontSize={SIZE.xs}
style={{
borderRadius: 5,
paddingHorizontal: 6,
marginRight: 4,
zIndex: 10,
maxWidth: tags.items?.length > 1 ? 130 : null
borderRadius: 4,
backgroundColor: colors.secondary.background,
paddingHorizontal: DefaultAppStyles.GAP_SMALL / 2,
borderWidth: 0.5,
borderColor: primaryColors.border,
paddingVertical: 1
}}
onPress={() => TaggedNotes.navigate(item, true)}
/>
>
<Paragraph
size={AppFontSize.xxxs}
color={colors.secondary.paragraph}
>
#{item.title}
</Paragraph>
</View>
) : null
)
: null}
@@ -338,7 +326,7 @@ const NoteItem = ({
<>
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xxs}
style={{
marginRight: 6
}}
@@ -352,7 +340,7 @@ const NoteItem = ({
<Paragraph
color={primaryColors.accent}
size={SIZE.xs}
size={AppFontSize.xxs}
style={{
marginRight: 6
}}
@@ -378,7 +366,7 @@ const NoteItem = ({
style={{
marginRight: 6
}}
size={SIZE.sm}
size={AppFontSize.sm}
color={colors.error.accent}
/>
) : null}
@@ -387,11 +375,11 @@ const NoteItem = ({
<Icon
name="lock"
testID="note-locked-icon"
size={SIZE.sm}
size={AppFontSize.sm}
style={{
marginRight: 6
}}
color={colors.secondary.background}
color={primaryColors.icon}
/>
) : null}
@@ -399,17 +387,17 @@ const NoteItem = ({
<Icon
testID="icon-star"
name="star-outline"
size={SIZE.sm}
size={AppFontSize.sm}
style={{
marginRight: 6
}}
color="orange"
color={colors.static.orange}
/>
) : null}
<TimeSince
style={{
fontSize: SIZE.xs,
fontSize: AppFontSize.xxs,
color: colors.secondary.paragraph,
marginRight: 6
}}
@@ -419,20 +407,39 @@ const NoteItem = ({
</>
) : null}
<IconButton
testID={notesnook.listitem.menu}
color={primaryColors.paragraph}
name="dots-horizontal"
size={SIZE.xl}
onPress={() => !noOpen && Properties.present(item)}
style={{
justifyContent: "center",
height: 35,
width: 35,
borderRadius: 100,
alignItems: "center"
}}
/>
{selectionMode === "note" || selectionMode === "trash" ? (
<>
<View
style={{
height: 35,
width: 35,
alignItems: "center",
justifyContent: "center"
}}
>
<AppIcon
name={selected ? "checkbox-outline" : "checkbox-blank-outline"}
color={selected ? colors.selected.icon : colors.primary.icon}
size={AppFontSize.lg}
/>
</View>
</>
) : (
<IconButton
testID={notesnook.listitem.menu}
color={colors.secondary.icon}
name="dots-horizontal"
size={AppFontSize.lg}
onPress={() => !noOpen && Properties.present(item)}
style={{
justifyContent: "center",
height: 35,
width: 35,
borderRadius: 100,
alignItems: "center"
}}
/>
)}
</View>
</>
);

View File

@@ -29,7 +29,7 @@ import {
presentSheet
} from "../../../services/event-manager";
import { eOnLoadNote, eShowMergeDialog } from "../../../utils/events";
import { tabBarRef } from "../../../utils/global-refs";
import { fluidTabsRef } from "../../../utils/global-refs";
import { NotebooksWithDateEdited, TagsWithDateEdited } from "@notesnook/common";
import NotePreview from "../../note-history/preview";
@@ -66,7 +66,7 @@ export const openNote = async (
item: note
});
if (!DDS.isTab) {
tabBarRef.current?.goToPage(1);
fluidTabsRef.current?.goToPage("editor");
}
}
};
@@ -101,6 +101,7 @@ export const NoteWrapper = React.memo<
onPress={() => openNote(item as Note, isTrash, isRenderedInActionSheet)}
isSheet={isRenderedInActionSheet}
item={item}
index={index}
color={restProps.color?.colorCode}
>
<NoteItem {...restProps} item={item} index={index} isTrash={isTrash} />

View File

@@ -19,18 +19,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { getFormattedDate } from "@notesnook/common";
import { BaseTrashItem, Notebook, TrashItem } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { notesnook } from "../../../../e2e/test.ids";
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
import { SIZE } from "../../../utils/size";
import useIsSelected from "../../../hooks/use-selected";
import { useSelectionStore } from "../../../stores/use-selection-store";
import { AppFontSize } from "../../../utils/size";
import { Properties } from "../../properties";
import AppIcon from "../../ui/AppIcon";
import { IconButton } from "../../ui/icon-button";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
type NotebookItemProps = {
item: Notebook | BaseTrashItem<Notebook>;
@@ -50,6 +54,8 @@ export const NotebookItem = ({
const compactMode = useIsCompactModeEnabled(
(item as TrashItem).itemType || item.type
);
const selectionMode = useSelectionStore((state) => state.selectionMode);
const [selected] = useIsSelected(item);
return (
<>
@@ -61,7 +67,7 @@ export const NotebookItem = ({
>
{compactMode ? (
<Paragraph
size={SIZE.sm}
size={AppFontSize.sm}
numberOfLines={1}
style={{
flexWrap: "wrap"
@@ -71,7 +77,7 @@ export const NotebookItem = ({
</Paragraph>
) : (
<Heading
size={SIZE.md}
size={AppFontSize.md}
numberOfLines={1}
style={{
flexWrap: "wrap"
@@ -83,7 +89,7 @@ export const NotebookItem = ({
{!item.description || compactMode ? null : (
<Paragraph
size={SIZE.sm}
size={AppFontSize.sm}
numberOfLines={2}
style={{
flexWrap: "wrap"
@@ -99,15 +105,15 @@ export const NotebookItem = ({
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
marginTop: 5,
height: SIZE.md + 2
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL,
height: AppFontSize.md + 2
}}
>
{isTrash ? (
<>
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
textAlignVertical: "center",
marginRight: 6
@@ -121,7 +127,7 @@ export const NotebookItem = ({
</Paragraph>
<Paragraph
color={colors.primary.accent}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
textAlignVertical: "center",
marginRight: 6
@@ -134,7 +140,7 @@ export const NotebookItem = ({
) : (
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
marginRight: 6
}}
@@ -144,7 +150,7 @@ export const NotebookItem = ({
)}
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
marginRight: 6
}}
@@ -155,7 +161,7 @@ export const NotebookItem = ({
{item.pinned ? (
<Icon
name="pin-outline"
size={SIZE.sm}
size={AppFontSize.sm}
style={{
marginRight: 10,
marginTop: 2
@@ -176,7 +182,7 @@ export const NotebookItem = ({
<>
<Paragraph
color={colors.primary.icon}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
marginRight: 6
}}
@@ -185,21 +191,39 @@ export const NotebookItem = ({
</Paragraph>
</>
) : null}
<IconButton
color={colors.primary.heading}
name="dots-horizontal"
testID={notesnook.ids.notebook.menu}
size={SIZE.xl}
onPress={() => Properties.present(item)}
style={{
justifyContent: "center",
height: 35,
width: 35,
borderRadius: 100,
alignItems: "center"
}}
/>
{selectionMode === "notebook" || selectionMode === "trash" ? (
<>
<View
style={{
height: 35,
width: 35,
alignItems: "center",
justifyContent: "center"
}}
>
<AppIcon
name={selected ? "checkbox-outline" : "checkbox-blank-outline"}
color={selected ? colors.selected.icon : colors.primary.icon}
size={AppFontSize.lg}
/>
</View>
</>
) : (
<IconButton
color={colors.primary.heading}
name="dots-horizontal"
testID={notesnook.ids.notebook.menu}
size={AppFontSize.xl}
onPress={() => Properties.present(item)}
style={{
justifyContent: "center",
height: 35,
width: 35,
borderRadius: 100,
alignItems: "center"
}}
/>
)}
</View>
</>
);

View File

@@ -22,7 +22,7 @@ import React from "react";
import { View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { notesnook } from "../../../../e2e/test.ids";
import { SIZE } from "../../../utils/size";
import { defaultBorderRadius, AppFontSize } from "../../../utils/size";
import { Properties } from "../../properties";
import ReminderSheet from "../../sheets/reminder";
import { IconButton } from "../../ui/icon-button";
@@ -31,6 +31,10 @@ import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import SelectionWrapper, { selectItem } from "../selection-wrapper";
import { strings } from "@notesnook/intl";
import { useSelectionStore } from "../../../stores/use-selection-store";
import useIsSelected from "../../../hooks/use-selected";
import AppIcon from "../../ui/AppIcon";
import { DefaultAppStyles } from "../../../utils/styles";
const ReminderItem = React.memo(
({
@@ -48,6 +52,8 @@ const ReminderItem = React.memo(
ReminderSheet.present(item, undefined, isSheet);
};
const selectionMode = useSelectionStore((state) => state.selectionMode);
const [selected] = useIsSelected(item);
return (
<SelectionWrapper onPress={openReminder} item={item} isSheet={isSheet}>
<View
@@ -62,7 +68,7 @@ const ReminderItem = React.memo(
style={{
flexWrap: "wrap"
}}
size={SIZE.md}
size={AppFontSize.md}
>
{item.title}
</Heading>
@@ -82,18 +88,18 @@ const ReminderItem = React.memo(
style={{
flexDirection: "row",
flexWrap: "wrap",
marginTop: 5
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
{item.disabled ? (
<View
style={{
backgroundColor: colors.secondary.background,
borderRadius: 5,
borderRadius: defaultBorderRadius,
flexDirection: "row",
paddingHorizontal: 6,
paddingHorizontal: DefaultAppStyles.GAP_SMALL,
alignItems: "center",
marginTop: 5,
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL,
justifyContent: "flex-start",
alignSelf: "flex-start",
marginRight: 10,
@@ -102,11 +108,11 @@ const ReminderItem = React.memo(
>
<Icon
name="bell-off-outline"
size={SIZE.md}
size={AppFontSize.md}
color={colors.error.icon}
/>
<Paragraph
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
style={{ marginLeft: 5 }}
>
@@ -118,24 +124,24 @@ const ReminderItem = React.memo(
<View
style={{
backgroundColor: colors.secondary.background,
borderRadius: 5,
borderRadius: defaultBorderRadius,
flexDirection: "row",
paddingHorizontal: 6,
paddingHorizontal: DefaultAppStyles.GAP_SMALL,
alignItems: "center",
marginTop: 5,
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL,
justifyContent: "flex-start",
alignSelf: "flex-start",
marginRight: 10,
marginRight: DefaultAppStyles.GAP_SMALL,
height: 30
}}
>
<Icon
name="reload"
size={SIZE.md}
size={AppFontSize.md}
color={colors.primary.accent}
/>
<Paragraph
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
style={{ marginLeft: 5 }}
>
@@ -147,29 +153,49 @@ const ReminderItem = React.memo(
<ReminderTime
reminder={item}
checkIsActive={false}
fontSize={SIZE.xs}
fontSize={AppFontSize.xxs}
style={{
justifyContent: "flex-start",
height: 25,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL / 2,
alignSelf: "flex-start"
}}
/>
</View>
</View>
<IconButton
testID={notesnook.listitem.menu}
color={colors.primary.paragraph}
name="dots-horizontal"
size={SIZE.xl}
onPress={() => Properties.present(item, [], isSheet)}
style={{
justifyContent: "center",
height: 35,
width: 35,
borderRadius: 100,
alignItems: "center"
}}
/>
{selectionMode === "note" || selectionMode === "trash" ? (
<>
<View
style={{
height: 35,
width: 35,
alignItems: "center",
justifyContent: "center"
}}
>
<AppIcon
name={selected ? "checkbox-outline" : "checkbox-blank-outline"}
color={selected ? colors.selected.icon : colors.primary.icon}
size={AppFontSize.lg}
/>
</View>
</>
) : (
<IconButton
testID={notesnook.listitem.menu}
color={colors.primary.paragraph}
name="dots-horizontal"
size={AppFontSize.xl}
onPress={() => Properties.present(item, isSheet)}
style={{
justifyContent: "center",
height: 35,
width: 35,
borderRadius: 100,
alignItems: "center"
}}
/>
)}
</SelectionWrapper>
);
},

View File

@@ -39,16 +39,15 @@ export const Filler = ({ item, color }: { item: Item; color?: string }) => {
style={{
position: "absolute",
width: "110%",
height: "150%",
backgroundColor: colors.selected.background,
borderLeftWidth: 5,
borderLeftColor: isEditingNote
? color
? color
: colors.selected.accent
: "transparent"
height: "100%",
backgroundColor: colors.selected.accent
// borderLeftWidth: 5,
// borderLeftColor: isEditingNote
// ? color
// ? color
// : colors.selected.accent
// : "transparent"
}}
collapsable={false}
/>
) : null;
};

View File

@@ -17,14 +17,14 @@ 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 { Item, TrashItem } from "@notesnook/core";
import { useThemeColors } from "@notesnook/theme";
import React, { PropsWithChildren, useRef } from "react";
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
import { useTabStore } from "../../../screens/editor/tiptap/use-tab-store";
import { useSelectionStore } from "../../../stores/use-selection-store";
import { DefaultAppStyles } from "../../../utils/styles";
import { Pressable } from "../../ui/pressable";
import { Filler } from "./back-fill";
import { SelectionIcon } from "./selection";
import { Item, TrashItem } from "@notesnook/core";
export function selectItem(item: Item) {
if (useSelectionStore.getState().selectionMode === item.type) {
@@ -49,6 +49,7 @@ type SelectionWrapperProps = PropsWithChildren<{
testID?: string;
isSheet?: boolean;
color?: string;
index?: number;
}>;
const SelectionWrapper = ({
@@ -57,10 +58,16 @@ const SelectionWrapper = ({
testID,
isSheet,
children,
color
color,
index = 0
}: SelectionWrapperProps) => {
const itemId = useRef(item.id);
const { colors, isDark } = useThemeColors();
const isEditingNote = useTabStore(
(state) =>
state.tabs.find((t) => t.id === state.currentTab)?.session?.noteId ===
item.id
);
const compactMode = useIsCompactModeEnabled(
(item as TrashItem).itemType || item.type
);
@@ -79,7 +86,13 @@ const SelectionWrapper = ({
return (
<Pressable
customColor={isSheet ? colors.secondary.background : "transparent"}
customColor={
isEditingNote
? colors.selected.background
: isSheet
? colors.primary.hover
: "transparent"
}
testID={testID}
onLongPress={onLongPress}
onPress={onPress}
@@ -91,15 +104,14 @@ const SelectionWrapper = ({
justifyContent: "space-between",
alignItems: "center",
width: "100%",
alignSelf: "center",
overflow: "hidden",
paddingHorizontal: 12,
paddingVertical: compactMode ? 4 : 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: compactMode ? 4 : DefaultAppStyles.GAP_VERTICAL,
borderRadius: isSheet ? 10 : 0,
marginBottom: isSheet ? 12 : undefined
marginBottom: isSheet ? DefaultAppStyles.GAP_VERTICAL : undefined
}}
>
{item.type === "note" ? <Filler item={item} color={color} /> : null}
<SelectionIcon item={item} />
{children}
</Pressable>
);

View File

@@ -24,7 +24,7 @@ import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
import useIsSelected from "../../../hooks/use-selected";
import { useSelectionStore } from "../../../stores/use-selection-store";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { Item, TrashItem } from "@notesnook/core";
export const SelectionIcon = ({ item }: { item: Item }) => {
@@ -52,7 +52,7 @@ export const SelectionIcon = ({ item }: { item: Item }) => {
>
{selected ? (
<Icon
size={compactMode ? SIZE.xl - 2 : SIZE.xl}
size={compactMode ? AppFontSize.xl - 2 : AppFontSize.xl}
color={selected ? colors.selected.accent : colors.primary.icon}
name={"check"}
/>

View File

@@ -23,13 +23,14 @@ import React from "react";
import { View } from "react-native";
import { notesnook } from "../../../../e2e/test.ids";
import { TaggedNotes } from "../../../screens/notes/tagged";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { Properties } from "../../properties";
import { IconButton } from "../../ui/icon-button";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import SelectionWrapper, { selectItem } from "../selection-wrapper";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
const TagItem = React.memo(
({
@@ -60,9 +61,9 @@ const TagItem = React.memo(
flexShrink: 1
}}
>
<Heading size={SIZE.md}>
<Heading size={AppFontSize.md}>
<Heading
size={SIZE.md}
size={AppFontSize.md}
style={{
color: colors.primary.accent
}}
@@ -73,9 +74,9 @@ const TagItem = React.memo(
</Heading>
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
marginTop: 5
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
{strings.notes(totalNotes)}
@@ -85,7 +86,7 @@ const TagItem = React.memo(
<IconButton
color={colors.primary.heading}
name="dots-horizontal"
size={SIZE.xl}
size={AppFontSize.xl}
onPress={() => {
Properties.present(item);
}}

View File

@@ -17,20 +17,28 @@ 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 { useThemeColors } from "@notesnook/theme";
import React from "react";
import { Dimensions, View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { useMessageStore } from "../../stores/use-message-store";
import { useThemeColors } from "@notesnook/theme";
import { getContainerBorder, hexToRGBA } from "../../utils/colors";
import { SIZE } from "../../utils/size";
import { Message, useMessageStore } from "../../stores/use-message-store";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { Pressable } from "../ui/pressable";
import Paragraph from "../ui/typography/paragraph";
export const Card = ({ color }: { color?: string }) => {
export const Card = ({
color,
customMessage
}: {
color?: string;
customMessage?: Omit<Message, "data">;
}) => {
const { colors } = useThemeColors();
color = color ? color : colors.primary.accent;
const messageBoardState = useMessageStore((state) => state.message);
const messageBoardState = useMessageStore(
(state) => customMessage || state.message
);
const announcements = useMessageStore((state) => state.announcements);
const fontScale = Dimensions.get("window").fontScale;
@@ -38,18 +46,19 @@ export const Card = ({ color }: { color?: string }) => {
(announcements && announcements.length) ? null : (
<View
style={{
width: "95%"
width: "100%",
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<Pressable
onPress={messageBoardState.onPress}
type="plain"
style={{
paddingVertical: 12,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingHorizontal: 0,
width: "100%"
}}
>
@@ -63,24 +72,14 @@ export const Card = ({ color }: { color?: string }) => {
<View
style={{
width: 40 * fontScale,
backgroundColor:
messageBoardState.type === "error"
? hexToRGBA(colors.error.accent, 0.15)
: hexToRGBA(color, 0.15),
height: 40 * fontScale,
borderRadius: 100,
alignItems: "center",
justifyContent: "center",
...getContainerBorder(
messageBoardState.type === "error"
? colors.error.accent
: color || colors.primary.accent,
0.4
)
justifyContent: "center"
}}
>
<Icon
size={SIZE.lg}
size={AppFontSize.xxxl}
color={
messageBoardState.type === "error" ? colors.error.icon : color
}
@@ -95,18 +94,19 @@ export const Card = ({ color }: { color?: string }) => {
marginRight: 10
}}
>
<Paragraph color={colors.secondary.paragraph} size={SIZE.xs}>
{messageBoardState.message}
</Paragraph>
<Paragraph
style={{
flexWrap: "nowrap",
flexShrink: 1
}}
size={AppFontSize.sm}
color={colors.primary.heading}
>
{messageBoardState.actionText}
</Paragraph>
<Paragraph color={colors.secondary.paragraph} size={AppFontSize.xs}>
{messageBoardState.message}
</Paragraph>
</View>
</View>
@@ -124,7 +124,7 @@ export const Card = ({ color }: { color?: string }) => {
color={
messageBoardState.type === "error" ? colors.error.icon : color
}
size={SIZE.lg}
size={AppFontSize.lg}
/>
</View>
)}

View File

@@ -19,12 +19,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { ActivityIndicator, useWindowDimensions, View } from "react-native";
import { ActivityIndicator, View } from "react-native";
import { notesnook } from "../../../e2e/test.ids";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { TTip, useTip } from "../../services/tip-manager";
import { RouteParams } from "../../stores/use-navigation-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { Tip } from "../tip";
import { Button } from "../ui/button";
import Seperator from "../ui/seperator";
@@ -46,7 +46,7 @@ type EmptyListProps = {
title?: string;
color?: string;
dataType: string;
screen?: string;
screen?: keyof RouteParams;
};
export const Empty = React.memo(function Empty({
@@ -58,8 +58,6 @@ export const Empty = React.memo(function Empty({
screen
}: EmptyListProps) {
const { colors } = useThemeColors();
const insets = useGlobalSafeAreaInsets();
const { height } = useWindowDimensions();
const introCompleted = useSettingStore(
(state) => state.settings.introCompleted
);
@@ -74,7 +72,7 @@ export const Empty = React.memo(function Empty({
<View
style={[
{
height: height - (140 + insets.top),
flex: 1,
width: "80%",
justifyContent: "center",
alignSelf: "center"
@@ -98,18 +96,13 @@ export const Empty = React.memo(function Empty({
{placeholder?.button && (
<Button
testID={notesnook.buttons.add}
type="accent"
type="secondaryAccented"
title={placeholder?.button}
iconPosition="right"
icon="arrow-right"
onPress={placeholder?.action}
buttonType={{
text: "white"
}}
style={{
alignSelf: "flex-start",
borderRadius: 5,
height: 40
alignSelf: "flex-start"
}}
/>
)}
@@ -124,12 +117,12 @@ export const Empty = React.memo(function Empty({
}}
>
<Heading>{placeholder?.title}</Heading>
<Paragraph size={SIZE.sm} textBreakStrategy="balanced">
<Paragraph size={AppFontSize.sm} textBreakStrategy="balanced">
{placeholder?.loading}
</Paragraph>
<Seperator />
<ActivityIndicator
size={SIZE.lg}
size={AppFontSize.lg}
color={color || colors.primary.accent}
/>
</View>

View File

@@ -24,9 +24,9 @@ import React, { useEffect, useRef } from "react";
import {
NativeScrollEvent,
NativeSyntheticEvent,
RefreshControl
RefreshControl,
View
} from "react-native";
import Animated, { FadeInDown } from "react-native-reanimated";
import { notesnook } from "../../../e2e/test.ids";
import { useGroupOptions } from "../../hooks/use-group-options";
import { eSendEvent } from "../../services/event-manager";
@@ -34,15 +34,16 @@ import Sync from "../../services/sync";
import { RouteName } from "../../stores/use-navigation-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { eScrollEvent } from "../../utils/events";
import { tabBarRef } from "../../utils/global-refs";
import { Footer } from "../list-items/footer";
import { fluidTabsRef } from "../../utils/global-refs";
import { Header } from "../list-items/headers/header";
import { Empty, PlaceholderData } from "./empty";
import { ListItemWrapper } from "./list-item.wrapper";
import { useSelectionStore } from "../../stores/use-selection-store";
type ListProps = {
data: VirtualizedGrouping<Item> | undefined;
dataType: Item["type"];
mode?: "drawer" | "sheet";
onRefresh?: () => void;
loading?: boolean;
headerTitle?: string;
@@ -145,70 +146,80 @@ export default function List(props: ListProps) {
return (
<>
<Animated.View
<View
style={{
flex: 1
}}
entering={props.renderedInRoute === "Search" ? undefined : FadeInDown}
>
<ListView
style={styles}
ref={scrollRef}
testID={notesnook.list.id}
data={props.data?.placeholders || []}
renderItem={renderItem}
onScroll={onListScroll}
nestedScrollEnabled={true}
onMomentumScrollEnd={() => {
tabBarRef.current?.unlock();
}}
getItemType={(item: number, index: number) => {
return props.data?.type(index);
}}
estimatedItemSize={isCompactModeEnabled ? 60 : 120}
directionalLockEnabled={true}
keyboardShouldPersistTaps="always"
keyboardDismissMode="interactive"
refreshControl={
props.isRenderedInActionSheet ? null : (
<RefreshControl
tintColor={colors.primary.accent}
colors={[colors.primary.accent]}
progressBackgroundColor={colors.secondary.background}
onRefresh={_onRefresh}
refreshing={false}
/>
)
}
ListEmptyComponent={
props.placeholder ? (
<Empty
loading={props.loading}
title={props.headerTitle}
dataType={props.dataType}
{props.data?.placeholders?.length === 0 ? (
<>
{props.CustomLisHeader ? (
props.CustomLisHeader
) : !props.headerTitle ? null : (
<Header
color={props.customAccentColor}
placeholder={props.placeholder}
screen={props.renderedInRoute}
/>
) : null
}
ListFooterComponent={
<Footer height={props.renderedInRoute === "Notebook" ? 300 : 150} />
}
ListHeaderComponent={
<>
{props.CustomLisHeader ? (
props.CustomLisHeader
) : !props.headerTitle ? null : (
<Header
color={props.customAccentColor}
screen={props.renderedInRoute}
)}
<Empty
loading={props.loading}
title={props.headerTitle}
dataType={props.dataType}
color={props.customAccentColor}
placeholder={props.placeholder}
screen={props.renderedInRoute}
/>
</>
) : (
<ListView
style={styles}
ref={scrollRef}
testID={notesnook.list.id}
data={props.data?.placeholders || []}
renderItem={renderItem}
onScroll={onListScroll}
nestedScrollEnabled={true}
onMomentumScrollEnd={() => {
fluidTabsRef.current?.unlock();
}}
getItemType={(item: number, index: number) => {
return props.data?.type(index);
}}
estimatedItemSize={isCompactModeEnabled ? 60 : 120}
directionalLockEnabled={true}
keyboardShouldPersistTaps="always"
keyboardDismissMode="interactive"
ListFooterComponent={
<View
style={{ height: props.data?.placeholders?.length ? 100 : 0 }}
/>
}
refreshControl={
props.isRenderedInActionSheet ? null : (
<RefreshControl
tintColor={colors.primary.accent}
colors={[colors.primary.accent]}
progressBackgroundColor={colors.secondary.background}
onRefresh={_onRefresh}
refreshing={false}
/>
)}
</>
}
/>
</Animated.View>
)
}
ListHeaderComponent={
<>
{props.CustomLisHeader ? (
props.CustomLisHeader
) : !props.headerTitle ? null : (
<Header
color={props.customAccentColor}
screen={props.renderedInRoute}
/>
)}
</>
}
/>
)}
</View>
</>
);
}

View File

@@ -26,8 +26,8 @@ import {
DraxListRenderItemContent
} from "react-native-drax";
import { tabBarRef } from "../../utils/global-refs";
import { SIZE } from "../../utils/size";
import { fluidTabsRef } from "../../utils/global-refs";
import { AppFontSize } from "../../utils/size";
import { useSideBarDraggingStore } from "../side-menu/dragging-store";
import { IconButton } from "../ui/icon-button";
@@ -61,9 +61,9 @@ function ReorderableList<T extends { id: string }>({
const listRef = useRef<FlatList | null>(null);
if (dragging) {
tabBarRef.current?.lock();
fluidTabsRef.current?.lock();
} else {
tabBarRef.current?.unlock();
fluidTabsRef.current?.unlock();
}
useEffect(() => {
@@ -79,13 +79,14 @@ function ReorderableList<T extends { id: string }>({
<View
style={{
flexDirection: "row",
paddingHorizontal: 12
width: "100%"
}}
>
<View
style={{
opacity: isHidden ? 0.4 : 1,
flexGrow: 1,
opacity: isHidden ? 0.4 : 1
flexShrink: 1
}}
>
{renderDraggableItem(info, props)}
@@ -94,13 +95,12 @@ function ReorderableList<T extends { id: string }>({
<IconButton
name={!isHidden ? "minus" : "plus"}
color={colors.primary.icon}
size={SIZE.lg}
size={AppFontSize.lg}
top={0}
bottom={0}
onPress={() => {
const _hiddenItems = hiddenItemsState.slice();
const index = _hiddenItems.indexOf(info.item.id);
if (index === -1) {
_hiddenItems.push(info.item?.id);
} else {

View File

@@ -38,7 +38,7 @@ import Navigation from "../../services/navigation";
import Sync from "../../services/sync";
import { useSettingStore } from "../../stores/use-setting-store";
import { eOnLoadNote, eShowMergeDialog } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import BaseDialog from "../dialog/base-dialog";
import DialogButtons from "../dialog/dialog-buttons";
import DialogContainer from "../dialog/dialog-container";
@@ -49,6 +49,7 @@ import Seperator from "../ui/seperator";
import Paragraph from "../ui/typography/paragraph";
import { diff } from "diffblazer";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
const MergeConflicts = () => {
const { colors } = useThemeColors();
@@ -142,7 +143,7 @@ const MergeConflicts = () => {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingLeft: 6
}}
>
@@ -164,7 +165,7 @@ const MergeConflicts = () => {
<Paragraph
style={{ flexWrap: "wrap" }}
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
>
<Text
style={{
@@ -201,9 +202,9 @@ const MergeConflicts = () => {
height={30}
style={{
borderRadius: 100,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
/>
) : null}
<View style={{ width: 10 }} />
@@ -218,9 +219,9 @@ const MergeConflicts = () => {
height={30}
style={{
borderRadius: 100,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
color={colors.error.paragraph}
onPress={() => {
setDialogVisible(true);
@@ -233,12 +234,12 @@ const MergeConflicts = () => {
height={30}
style={{
borderRadius: 100,
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
minWidth: 60,
marginLeft: 10
}}
type="accent"
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
title={
keeping && !isDiscarded ? strings.undo() : strings.keep()
}

View File

@@ -30,7 +30,7 @@ import { db } from "../../common/database";
import { useDBItem } from "../../hooks/use-db-item";
import { presentSheet } from "../../services/event-manager";
import { openLinkInBrowser } from "../../utils/functions";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import DialogHeader from "../dialog/dialog-header";
import SheetProvider from "../sheet-provider";
import { Pressable } from "../ui/pressable";
@@ -38,6 +38,7 @@ import Seperator from "../ui/seperator";
import Paragraph from "../ui/typography/paragraph";
import NotePreview from "./preview";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
const HistoryItem = ({
index,
@@ -88,16 +89,16 @@ const HistoryItem = ({
style={{
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
height: 45,
marginBottom: 10,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
flexDirection: "row"
}}
>
{!item ? null : (
<>
<Paragraph>{getDate(item.dateCreated, item.dateModified)}</Paragraph>
<Paragraph color={colors.secondary.paragraph} size={SIZE.xs}>
<Paragraph color={colors.secondary.paragraph} size={AppFontSize.xs}>
{getTimeAgo(item.dateModified)}
</Paragraph>
</>
@@ -148,7 +149,7 @@ export default function NoteHistory({
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
height: !history?.placeholders.length
? 300
: (history.placeholders.length + 1) * 55,
@@ -170,7 +171,7 @@ export default function NoteHistory({
>
{_loading ? (
<ActivityIndicator
size={SIZE.xl}
size={AppFontSize.xl}
color={colors.primary.accent}
/>
) : (
@@ -187,7 +188,7 @@ export default function NoteHistory({
/>
</View>
<Paragraph
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
style={{
alignSelf: "center"

View File

@@ -36,6 +36,7 @@ import { Button } from "../ui/button";
import Paragraph from "../ui/typography/paragraph";
import { diff } from "diffblazer";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
/**
*
@@ -158,7 +159,7 @@ export default function NotePreview({ session, content, note }) {
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Button
@@ -173,7 +174,7 @@ export default function NotePreview({ session, content, note }) {
type="error"
width="100%"
style={{
marginTop: 12
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
/>
</View>

View File

@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { FeatureBlock } from "./feature";
import { ScrollView } from "react-native-actions-sheet";
import { DefaultAppStyles } from "../../utils/styles";
export const CompactFeatures = ({
vertical,
@@ -84,7 +85,7 @@ export const CompactFeatures = ({
style={{
width: "100%",
maxHeight: maxHeight,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{data.map((item) => (

View File

@@ -17,6 +17,7 @@ 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 { useThemeColors } from "@notesnook/theme";
import React, { useState } from "react";
import { ActivityIndicator, Platform, ScrollView, View } from "react-native";
import { LAUNCH_ROCKET } from "../../assets/images/assets";
@@ -24,17 +25,13 @@ import { db } from "../../common/database";
import { usePricing } from "../../hooks/use-pricing";
import { DDS } from "../../services/device-detection";
import { eSendEvent, presentSheet } from "../../services/event-manager";
import { useThemeColors } from "@notesnook/theme";
import Navigation from "../../services/navigation";
import { useUserStore } from "../../stores/use-user-store";
import { getElevationStyle } from "../../utils/elevation";
import {
eClosePremiumDialog,
eCloseSheet,
eOpenLoginDialog
} from "../../utils/events";
import { SIZE } from "../../utils/size";
import { eClosePremiumDialog, eCloseSheet } from "../../utils/events";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { AuthMode } from "../auth";
import { AuthMode } from "../auth/common";
import SheetProvider from "../sheet-provider";
import { Toast } from "../toast";
import { Button } from "../ui/button";
@@ -47,6 +44,7 @@ import { Walkthrough } from "../walkthroughs";
import { features } from "./features";
import { Group } from "./group";
import { PricingPlans } from "./pricing-plans";
import { DefaultAppStyles } from "../../utils/styles";
export const Component = ({ close, promo }) => {
const { colors } = useThemeColors();
@@ -66,9 +64,9 @@ export const Component = ({ close, promo }) => {
});
} else {
close();
setTimeout(() => {
eSendEvent(eOpenLoginDialog, AuthMode.trialSignup);
}, 400);
Navigation.navigate("Auth", {
mode: AuthMode.trialSignup
});
}
};
@@ -137,14 +135,14 @@ export const Component = ({ close, promo }) => {
<Heading
key="heading"
size={SIZE.lg}
size={AppFontSize.lg}
style={{
alignSelf: "center",
paddingTop: 20
}}
>
Notesnook{" "}
<Heading size={SIZE.lg} color={colors.primary.accent}>
<Heading size={AppFontSize.lg} color={colors.primary.accent}>
Pro
</Heading>
</Heading>
@@ -154,7 +152,7 @@ export const Component = ({ close, promo }) => {
style={{
marginBottom: 20
}}
size={SIZE.md}
size={AppFontSize.md}
color={colors.primary.accent}
/>
) : (
@@ -163,7 +161,7 @@ export const Component = ({ close, promo }) => {
alignSelf: "center",
marginBottom: 20
}}
size={SIZE.md}
size={AppFontSize.md}
>
(
{Platform.OS === "android"
@@ -176,9 +174,9 @@ export const Component = ({ close, promo }) => {
<Paragraph
key="description"
size={SIZE.md}
size={AppFontSize.md}
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
textAlign: "center",
alignSelf: "center",
paddingBottom: 20,
@@ -206,7 +204,7 @@ export const Component = ({ close, promo }) => {
type="accent"
width={250}
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
marginBottom: 15,
borderRadius: 100
}}
@@ -222,7 +220,7 @@ export const Component = ({ close, promo }) => {
type={userCanRequestTrial ? "secondaryAccented" : "accent"}
width={250}
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
marginBottom: 15,
borderRadius: 100
}}
@@ -231,18 +229,18 @@ export const Component = ({ close, promo }) => {
{!user || userCanRequestTrial ? (
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
alignSelf: "center",
textAlign: "center",
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
maxWidth: "80%"
}}
>
{user
? 'On clicking "Try free for 14 days", your free trial will be activated.'
: "After sign up you will be asked to activate your free trial."}{" "}
<Paragraph size={SIZE.xs} style={{ fontWeight: "bold" }}>
<Paragraph size={AppFontSize.xs} style={{ fontWeight: "bold" }}>
No credit card is required.
</Paragraph>
</Paragraph>
@@ -257,7 +255,7 @@ export const Component = ({ close, promo }) => {
<View
key="plans"
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<PricingPlans showTrialOption={false} promo={promo} />
@@ -272,7 +270,7 @@ export const Component = ({ close, promo }) => {
}
type="accent"
style={{
paddingHorizontal: 24,
paddingHorizontal: DefaultAppStyles.GAP * 2,
position: "absolute",
borderRadius: 100,
bottom: 30,

View File

@@ -32,7 +32,7 @@ import {
eOpenResultDialog,
eOpenTrialEndingDialog
} from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import BaseDialog from "../dialog/base-dialog";
import DialogContainer from "../dialog/dialog-container";
@@ -42,6 +42,7 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { CompactFeatures } from "./compact-features";
import { Offer } from "./offer";
import { DefaultAppStyles } from "../../utils/styles";
export const Expiring = () => {
const { colors } = useThemeColors();
@@ -94,7 +95,7 @@ export const Expiring = () => {
>
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
width: "100%"
}}
>
@@ -127,7 +128,7 @@ export const Expiring = () => {
paddingTop: 0,
paddingBottom: 20
}}
size={SIZE.md + 2}
size={AppFontSize.md + 2}
>
Upgrade now to continue using all the pro features after
your trial ends
@@ -143,11 +144,11 @@ export const Expiring = () => {
await sleep(300);
eSendEvent(eOpenPremiumDialog, promo);
}}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
textDecorationLine: "underline",
color: colors.secondary.paragraph,
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
>
{"See what's included in Basic & Pro plans"}
@@ -176,11 +177,11 @@ export const Expiring = () => {
promo?.discount > 30 ? null : promo
);
}}
fontSize={SIZE.md + 2}
fontSize={AppFontSize.md + 2}
style={{
marginBottom: status.extend ? 0 : 10,
marginTop: 10,
paddingHorizontal: 24
marginTop: DefaultAppStyles.GAP_VERTICAL,
paddingHorizontal: DefaultAppStyles.GAP * 2
}}
/>
@@ -201,10 +202,10 @@ export const Expiring = () => {
button: "Continue"
});
}}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
height={30}
style={{
marginBottom: 10
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
/>
)}

View File

@@ -21,9 +21,10 @@ import React from "react";
import { Text, View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { defaultBorderRadius, AppFontSize } from "../../utils/size";
import Paragraph from "../ui/typography/paragraph";
import { ProTag } from "./pro-tag";
import { DefaultAppStyles } from "../../utils/styles";
export const FeatureBlock = ({
vertical,
@@ -40,11 +41,11 @@ export const FeatureBlock = ({
style={{
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 12,
marginBottom: 10,
paddingHorizontal: DefaultAppStyles.GAP,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
backgroundColor: colors.secondary.background,
borderRadius: 10,
paddingVertical: 12
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<Paragraph
@@ -53,7 +54,7 @@ export const FeatureBlock = ({
marginLeft: 5,
flexShrink: 1
}}
size={SIZE.sm}
size={AppFontSize.sm}
>
{content}
</Paragraph>
@@ -63,14 +64,14 @@ export const FeatureBlock = ({
style={{
height: 100,
justifyContent: "center",
padding: 10,
padding: DefaultAppStyles.GAP_SMALL,
marginRight: 10,
borderRadius: 5,
borderRadius: defaultBorderRadius,
minWidth: 100
}}
>
<Icon color={colors.primary.icon} name={icon} size={SIZE.xl} />
<Paragraph size={SIZE.md}>
<Icon color={colors.primary.icon} name={icon} size={AppFontSize.xl} />
<Paragraph size={AppFontSize.md}>
<Text style={{ color: colors.primary.accent }}>{highlight}</Text>
{content ? "\n" + content : null}
</Paragraph>
@@ -78,14 +79,14 @@ export const FeatureBlock = ({
{pro ? (
<>
<View style={{ height: 5 }} />
<ProTag width={50} size={SIZE.xs} background={proTagBg} />
<ProTag width={50} size={AppFontSize.xs} background={proTagBg} />
</>
) : (
<View
style={{
width: 30,
height: 3,
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
borderRadius: 100,
backgroundColor: colors.primary.accent
}}

View File

@@ -20,11 +20,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { ScrollView, View } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { FeatureBlock } from "./feature";
import { ProTag } from "./pro-tag";
import { DefaultAppStyles } from "../../utils/styles";
export const Group = ({ item, index }) => {
const { colors } = useThemeColors();
@@ -32,24 +33,31 @@ export const Group = ({ item, index }) => {
return (
<View
style={{
paddingHorizontal: 12,
backgroundColor: index % 2 !== 0 ? colors.primary.background : colors.secondary.background,
paddingHorizontal: DefaultAppStyles.GAP,
backgroundColor:
index % 2 !== 0
? colors.primary.background
: colors.secondary.background,
paddingVertical: 40
}}
>
{item?.pro ? (
<ProTag
size={SIZE.sm}
background={index % 2 === 0 ? colors.primary.background : colors.secondary.background}
size={AppFontSize.sm}
background={
index % 2 === 0
? colors.primary.background
: colors.secondary.background
}
/>
) : null}
<Heading>{item.title}</Heading>
<Paragraph size={SIZE.md}>{item.detail}</Paragraph>
<Paragraph size={AppFontSize.md}>{item.detail}</Paragraph>
{item.features && (
<ScrollView
style={{
marginTop: 20
marginTop: DefaultAppStyles.GAP
}}
horizontal
showsHorizontalScrollIndicator={false}
@@ -60,7 +68,11 @@ export const Group = ({ item, index }) => {
{...item}
detail={item.detail}
pro={item.pro}
proTagBg={index % 2 === 0 ? colors.primary.background : colors.secondary.background}
proTagBg={
index % 2 === 0
? colors.primary.background
: colors.secondary.background
}
/>
))}
</ScrollView>
@@ -68,9 +80,9 @@ export const Group = ({ item, index }) => {
{item.info ? (
<Paragraph
style={{
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
>
{item.info}

View File

@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { Text } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import Paragraph from "../ui/typography/paragraph";
export const Offer = ({
@@ -36,7 +36,7 @@ export const Offer = ({
textAlign: "center",
paddingVertical: padding
}}
size={SIZE.xxxl}
size={AppFontSize.xxxl}
>
GET {off}
<Text style={{ color: colors.primary.accent }}>%</Text> OFF!{"\n"}

View File

@@ -35,11 +35,12 @@ import {
eOpenPremiumDialog,
eShowGetPremium
} from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { Button } from "../ui/button";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { DefaultAppStyles } from "../../utils/styles";
export const PremiumToast = ({ context = "global", offset = 0 }) => {
const { colors } = useThemeColors();
@@ -95,7 +96,7 @@ export const PremiumToast = ({ context = "global", offset = 0 }) => {
backgroundColor: colors.secondary.background,
zIndex: 999,
...getElevationStyle(20),
padding: 12,
padding: DefaultAppStyles.GAP,
borderRadius: 10,
flexDirection: "row",
alignSelf: "center",
@@ -120,7 +121,7 @@ export const PremiumToast = ({ context = "global", offset = 0 }) => {
flexWrap: "wrap"
}}
color={colors.primary.accent}
size={SIZE.md}
size={AppFontSize.md}
>
{msg.title}
</Heading>
@@ -129,7 +130,7 @@ export const PremiumToast = ({ context = "global", offset = 0 }) => {
style={{
flexWrap: "wrap"
}}
size={SIZE.sm}
size={AppFontSize.sm}
color={colors.primary.paragraph}
>
{msg.desc}

View File

@@ -19,11 +19,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { Platform, View } from "react-native";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { Pressable } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import RNIap from "react-native-iap";
import { DefaultAppStyles } from "../../utils/styles";
export const PricingItem = ({
product,
@@ -49,7 +50,7 @@ export const PricingItem = ({
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: compact ? 15 : 10,
width: compact ? null : "100%",
minWidth: 150,
@@ -59,13 +60,13 @@ export const PricingItem = ({
>
{!compact && (
<View>
<Heading size={SIZE.lg - 2}>
<Heading size={AppFontSize.lg - 2}>
{product?.type === "yearly" || product?.offerType === "yearly"
? "Yearly"
: "Monthly"}
</Heading>
{product?.info && (
<Paragraph size={SIZE.xs}>{product.info}</Paragraph>
<Paragraph size={AppFontSize.xs}>{product.info}</Paragraph>
)}
</View>
)}
@@ -75,13 +76,13 @@ export const PricingItem = ({
style={{
textDecorationLine: strikethrough ? "line-through" : undefined
}}
size={SIZE.sm}
size={AppFontSize.sm}
>
<Heading
style={{
textDecorationLine: strikethrough ? "line-through" : undefined
}}
size={SIZE.lg - 2}
size={AppFontSize.lg - 2}
>
{Platform.OS === "android"
? (product.data as RNIap.SubscriptionAndroid | undefined)

View File

@@ -17,6 +17,8 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useCallback, useEffect, useState } from "react";
import { ActivityIndicator, Platform, Text, View } from "react-native";
import * as RNIap from "react-native-iap";
@@ -27,18 +29,19 @@ import {
presentSheet,
ToastManager
} from "../../services/event-manager";
import Navigation from "../../services/navigation";
import PremiumService from "../../services/premium";
import { useThemeColors } from "@notesnook/theme";
import { useSettingStore } from "../../stores/use-setting-store";
import { useUserStore } from "../../stores/use-user-store";
import {
eClosePremiumDialog,
eCloseSheet,
eCloseSimpleDialog,
eOpenLoginDialog
eCloseSimpleDialog
} from "../../utils/events";
import { openLinkInBrowser } from "../../utils/functions";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { AuthMode } from "../auth/common";
import { Dialog } from "../dialog";
import BaseDialog from "../dialog/base-dialog";
import { presentDialog } from "../dialog/functions";
@@ -47,8 +50,7 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { Walkthrough } from "../walkthroughs";
import { PricingItem } from "./pricing-item";
import { useSettingStore } from "../../stores/use-setting-store";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
const UUID_PREFIX = "0bdaea";
const UUID_VERSION = "4";
@@ -264,7 +266,7 @@ export const PricingPlans = ({
return loading ? (
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
justifyContent: "center",
alignItems: "center",
height: 100
@@ -275,7 +277,7 @@ export const PricingPlans = ({
) : (
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{buying ? (
@@ -290,7 +292,7 @@ export const PricingPlans = ({
style={{
alignSelf: "center"
}}
size={SIZE.lg}
size={AppFontSize.lg}
>
{(Platform.OS === "android"
? (monthlyPlan?.product as RNIap.SubscriptionAndroid | undefined)
@@ -309,9 +311,9 @@ export const PricingPlans = ({
type="accent"
width={250}
style={{
paddingHorizontal: 12,
marginBottom: 15,
marginTop: 15,
paddingHorizontal: DefaultAppStyles.GAP,
marginBottom: DefaultAppStyles.GAP,
marginTop: DefaultAppStyles.GAP,
borderRadius: 100
}}
/>
@@ -332,7 +334,7 @@ export const PricingPlans = ({
type="secondaryAccented"
width={250}
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
marginBottom: 15
}}
/>
@@ -373,7 +375,7 @@ export const PricingPlans = ({
<Heading
style={{
paddingTop: 15,
fontSize: SIZE.lg
fontSize: AppFontSize.lg
}}
>
Special offer for you
@@ -390,7 +392,7 @@ export const PricingPlans = ({
alignSelf: "center",
textAlign: "center"
}}
size={SIZE.xxl}
size={AppFontSize.xxl}
>
{Platform.OS === "android"
? (product.data as RNIap.SubscriptionAndroid)
@@ -411,7 +413,7 @@ export const PricingPlans = ({
alignSelf: "center",
textAlign: "center"
}}
size={SIZE.md}
size={AppFontSize.md}
>
then {getStandardPrice()} {product?.offerType}.
</Paragraph>
@@ -503,7 +505,7 @@ export const PricingPlans = ({
<Button
height={35}
style={{
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
onPress={() => {
presentDialog({
@@ -557,24 +559,24 @@ export const PricingPlans = ({
onPress={() => {
eSendEvent(eClosePremiumDialog);
eSendEvent(eCloseSheet);
setTimeout(() => {
eSendEvent(eOpenLoginDialog, 1);
}, 400);
Navigation.navigate("Auth", {
mode: AuthMode.login
});
}}
title={"Sign up for free"}
type="accent"
width={250}
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
marginTop: product?.type === "promo" ? 0 : 30,
marginBottom: 10
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
/>
{Platform.OS !== "ios" &&
promo &&
!promo.promoCode.startsWith("com.streetwriters.notesnook") ? (
<Paragraph
size={SIZE.md}
size={AppFontSize.md}
textBreakStrategy="balanced"
style={{
alignSelf: "center",
@@ -612,7 +614,7 @@ export const PricingPlans = ({
setProduct(undefined);
}}
style={{
marginTop: 5
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
height={30}
fontSize={13}
@@ -629,18 +631,18 @@ export const PricingPlans = ({
{!user || !upgrade ? (
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
alignSelf: "center",
textAlign: "center",
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
maxWidth: "80%"
}}
>
{user
? 'On clicking "Try free for 14 days", your free trial will be activated.'
: "After sign up you will be asked to activate your free trial."}{" "}
<Paragraph size={SIZE.xs} style={{ fontWeight: "bold" }}>
<Paragraph size={AppFontSize.xs} style={{ fontWeight: "bold" }}>
No credit card is required.
</Paragraph>
</Paragraph>
@@ -651,11 +653,11 @@ export const PricingPlans = ({
{Platform.OS === "ios" ? (
<Paragraph
textBreakStrategy="balanced"
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
style={{
alignSelf: "center",
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
textAlign: "center"
}}
>
@@ -665,11 +667,11 @@ export const PricingPlans = ({
</Paragraph>
) : (
<Paragraph
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
style={{
alignSelf: "center",
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
textAlign: "center"
}}
>
@@ -685,7 +687,7 @@ export const PricingPlans = ({
}}
>
<Paragraph
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
style={{
maxWidth: "100%",
@@ -694,7 +696,7 @@ export const PricingPlans = ({
>
By subscribing, you agree to our{" "}
<Paragraph
size={SIZE.xs}
size={AppFontSize.xs}
onPress={() => {
openLinkInBrowser("https://notesnook.com/tos")
.catch(() => {})
@@ -709,7 +711,7 @@ export const PricingPlans = ({
</Paragraph>
and{" "}
<Paragraph
size={SIZE.xs}
size={AppFontSize.xs}
onPress={() => {
openLinkInBrowser("https://notesnook.com/privacy")
.catch(() => {})

View File

@@ -22,6 +22,7 @@ import { View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { useThemeColors } from "@notesnook/theme";
import Paragraph from "../ui/typography/paragraph";
import { DefaultAppStyles } from "../../utils/styles";
/**
*
@@ -39,7 +40,7 @@ export const ProTag = ({ width, size, background }) => {
width: width || 60,
justifyContent: "center",
alignItems: "center",
paddingVertical: 2.5,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL / 2,
flexDirection: "row"
}}
>

View File

@@ -31,12 +31,13 @@ import { useMenuStore } from "../../stores/use-menu-store";
import { useRelationStore } from "../../stores/use-relation-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { refreshNotesPage } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import ColorPicker from "../dialogs/color-picker";
import { Button } from "../ui/button";
import NativeTooltip from "../../utils/tooltip";
import { Pressable } from "../ui/pressable";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
const ColorItem = ({ item, note }: { item: Color; note: Note }) => {
const { colors } = useThemeColors();
@@ -85,7 +86,12 @@ const ColorItem = ({ item, note }: { item: Color; note: Note }) => {
}}
>
{isLinked ? (
<Icon testID="icon-check" name="check" color="white" size={SIZE.lg} />
<Icon
testID="icon-check"
name="check"
color="white"
size={AppFontSize.lg}
/>
) : null}
</Pressable>
);
@@ -128,37 +134,37 @@ export const ColorTags = ({ item }: { item: Note }) => {
flexShrink: 2
}}
>
<FlashList
data={colorNotes}
estimatedItemSize={30}
horizontal
extraData={updater}
bounces={false}
renderItem={renderItem}
showsHorizontalScrollIndicator={false}
ListFooterComponent={
!colorNotes || !colorNotes.length ? (
<Button
onPress={async () => {
useSettingStore.getState().setSheetKeyboardHandler(false);
setVisible(true);
}}
buttonType={{
text: colors.primary.accent
}}
title={strings.addColor()}
type="secondary"
icon="plus"
iconPosition="right"
height={30}
fontSize={SIZE.xs}
style={{
marginRight: 5,
borderRadius: 100,
paddingHorizontal: 8
}}
/>
) : (
{!colorNotes || !colorNotes.length ? (
<Button
onPress={async () => {
useSettingStore.getState().setSheetKeyboardHandler(false);
setVisible(true);
}}
buttonType={{
text: colors.primary.accent
}}
title={strings.addColor()}
type="secondary"
icon="plus"
iconPosition="right"
height={30}
fontSize={AppFontSize.xs}
style={{
marginRight: 5,
paddingHorizontal: DefaultAppStyles.GAP_SMALL,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
/>
) : (
<FlashList
data={colorNotes}
estimatedItemSize={30}
horizontal
extraData={updater}
bounces={false}
renderItem={renderItem}
showsHorizontalScrollIndicator={false}
ListFooterComponent={
<Pressable
style={{
width: 35,
@@ -178,12 +184,12 @@ export const ColorTags = ({ item }: { item: Note }) => {
testID="icon-plus"
name="plus"
color={colors.primary.icon}
size={SIZE.lg}
size={AppFontSize.lg}
/>
</Pressable>
)
}
/>
}
/>
)}
</View>
</>
);

View File

@@ -20,10 +20,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { View } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import Paragraph from "../ui/typography/paragraph";
import { getFormattedDate } from "@notesnook/common";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
export const DateMeta = ({ item }) => {
const { colors } = useThemeColors();
@@ -44,13 +45,13 @@ export const DateMeta = ({ item }) => {
style={{
flexDirection: "row",
justifyContent: "space-between",
paddingVertical: 3
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL / 2
}}
>
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{strings.dateDescFromKey(key)}
</Paragraph>
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{getFormattedDate(item[key], "date-time")}
</Paragraph>
</View>
@@ -59,11 +60,10 @@ export const DateMeta = ({ item }) => {
return (
<View
style={{
paddingVertical: 5,
marginTop: 5,
borderTopWidth: 1,
borderTopColor: colors.primary.border,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP,
paddingTop: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
{getDateMeta().map(renderItem)}

View File

@@ -16,18 +16,19 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { Platform, View } from "react-native";
import { View } from "react-native";
import { FlatList } from "react-native-actions-sheet";
import { db } from "../../common/database";
import { DDS } from "../../services/device-detection";
import { eSendEvent, presentSheet } from "../../services/event-manager";
import { ColorValues } from "../../utils/colors";
import { eOnLoadNote } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { fluidTabsRef } from "../../utils/global-refs";
import { AppFontSize } from "../../utils/size";
import SheetProvider from "../sheet-provider";
import { useSideBarDraggingStore } from "../side-menu/dragging-store";
import { IconButton } from "../ui/icon-button";
import { Pressable } from "../ui/pressable";
import { ReminderTime } from "../ui/reminder-time";
@@ -36,10 +37,9 @@ import Paragraph from "../ui/typography/paragraph";
import { DateMeta } from "./date-meta";
import { Items } from "./items";
import Notebooks from "./notebooks";
import { Synced } from "./synced";
import { TagStrip, Tags } from "./tags";
import { tabBarRef } from "../../utils/global-refs";
import { strings } from "@notesnook/intl";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { DefaultAppStyles } from "../../utils/styles";
const Line = ({ top = 6, bottom = 6 }) => {
const { colors } = useThemeColors();
@@ -82,13 +82,14 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
data={[0]}
keyExtractor={() => "properties-scroll-item"}
renderItem={() => (
<View>
<View
style={{
gap: DefaultAppStyles.GAP_VERTICAL
}}
>
<View
style={{
paddingHorizontal: 12,
marginTop: 5,
zIndex: 10,
marginBottom: 5
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<View
@@ -101,7 +102,8 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
style={{
flexDirection: "row",
alignItems: "center",
flexShrink: 1
flexShrink: 1,
gap: 5
}}
>
{item.type === "color" ? (
@@ -116,16 +118,15 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
marginRight: 10
}}
/>
) : item.type === "tag" ? (
<Icon
name="pound"
size={AppFontSize.lg}
color={colors.primary.icon}
/>
) : null}
<Heading size={SIZE.lg}>
{item.type === "tag" && !isColor ? (
<Heading size={SIZE.xl} color={colors.primary.accent}>
#
</Heading>
) : null}
{item.title}
</Heading>
<Heading size={AppFontSize.lg}>{item.title}</Heading>
</View>
{item.type === "note" ? (
@@ -133,7 +134,7 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
name="open-in-new"
type="plain"
color={colors.primary.icon}
size={SIZE.lg}
size={AppFontSize.lg}
style={{
alignSelf: "flex-start"
}}
@@ -144,7 +145,7 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
newTab: true
});
if (!DDS.isTab) {
tabBarRef.current?.goToPage(1);
fluidTabsRef.current?.goToPage("editor");
}
}}
/>
@@ -165,35 +166,28 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
style={{
justifyContent: "flex-start",
borderWidth: 0,
height: 30,
alignSelf: "flex-start",
backgroundColor: "transparent",
paddingHorizontal: 0
paddingHorizontal: 0,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
/>
) : null}
</View>
<DateMeta item={item} />
<Line bottom={0} />
<Line bottom={0} top={0} />
{item.type === "note" ? (
<>
<Tags close={close} item={item} />
<Line bottom={0} />
<Line bottom={0} top={0} />
</>
) : null}
{item.type === "note" ? (
<View
style={{
paddingHorizontal: 12
}}
>
<Notebooks note={item} close={close} />
</View>
<Notebooks note={item} close={close} />
) : null}
<Items
item={item}
buttons={buttons}
@@ -202,8 +196,6 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
}}
/>
<Synced item={item} close={close} />
{DDS.isTab ? (
<View
style={{
@@ -218,86 +210,40 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
);
};
Properties.present = async (item, buttons = [], isSheet) => {
Properties.present = async (item, isSheet, buttons = []) => {
if (!item) return;
let type = item?.type;
let props = [];
let android = [];
let dbItem;
switch (type) {
case "trash":
props[0] = item;
props.push(["delete", "restore"]);
dbItem = item;
break;
case "note":
android = Platform.OS === "android" ? ["pin-to-notifications"] : [];
props[0] = await db.notes.note(item.id);
props.push([
"notebooks",
"add-reminder",
"share",
"export",
"copy",
"publish",
"pin",
"favorite",
"attachments",
"lock-unlock",
"trash",
"remove-from-notebook",
"history",
"read-only",
"reminders",
"local-only",
"duplicate",
"copy-link",
"references",
...android,
...buttons
]);
dbItem = await db.notes.note(item.id);
break;
case "notebook":
props[0] = await db.notebooks.notebook(item.id);
props.push([
"edit-notebook",
"pin",
"add-shortcut",
"trash",
"default-notebook",
"add-notebook",
"move-notes",
"move-notebook"
]);
dbItem = await db.notebooks.notebook(item.id);
break;
case "tag":
props[0] = await db.tags.tag(item.id);
props.push(["add-shortcut", "trash", "rename-tag"]);
dbItem = await db.tags.tag(item.id);
break;
case "color":
props[0] = await db.colors.color(item.id);
props.push([
"trash",
"rename-color",
...(useSideBarDraggingStore.getState().dragging ? [] : ["reorder"])
]);
dbItem = await db.colors.color(item.id);
break;
case "reminder": {
props[0] = await db.reminders.reminder(item.id);
props.push(["edit-reminder", "trash", "disable-reminder"]);
dbItem = await db.reminders.reminder(item.id);
break;
}
}
if (!props[0]) return;
presentSheet({
context: isSheet ? "local" : undefined,
component: (ref, close) => (
<Properties
close={() => {
close();
}}
close={close}
actionSheetRef={ref}
item={props[0]}
buttons={props[1]}
item={dbItem}
buttons={buttons}
/>
)
});

View File

@@ -1,266 +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 { useThemeColors } from "@notesnook/theme";
import React from "react";
import { Dimensions, ScrollView, View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { useActions } from "../../hooks/use-actions";
import { useStoredRef } from "../../hooks/use-stored-ref";
import { DDS } from "../../services/device-detection";
import { useSettingStore } from "../../stores/use-setting-store";
import { SIZE } from "../../utils/size";
import { Button } from "../ui/button";
import { Pressable } from "../ui/pressable";
import Paragraph from "../ui/typography/paragraph";
export const Items = ({ item, buttons, close }) => {
const { colors } = useThemeColors();
const topBarSorting = useStoredRef("topbar-sorting-ref", {});
const dimensions = useSettingStore((state) => state.dimensions);
const actions = useActions({ item, close });
const data = actions.filter((i) => buttons.indexOf(i.id) > -1 && !i.hidden);
let width = dimensions.width > 600 ? 600 : dimensions.width;
const shouldShrink =
Dimensions.get("window").fontScale > 1 &&
Dimensions.get("window").width < 450;
let columnItemsCount = DDS.isLargeTablet() ? 7 : shouldShrink ? 4 : 5;
let columnItemWidth = DDS.isTab
? (width - 12) / columnItemsCount
: (width - 12) / columnItemsCount;
const _renderRowItem = ({ item }) => (
<View
key={item.id}
testID={"icon-" + item.id}
style={{
alignItems: "center",
width: columnItemWidth,
marginBottom: 10
}}
>
<Pressable
onPress={item.func}
type={item.on ? "shade" : "secondary"}
style={{
height: columnItemWidth - 12,
width: columnItemWidth - 12,
borderRadius: 10,
justifyContent: "center",
alignItems: "center",
textAlign: "center",
textAlignVertical: "center",
marginBottom: DDS.isTab ? 7 : 3.5
}}
>
<Icon
allowFontScaling
name={item.icon}
size={DDS.isTab ? SIZE.xxl : shouldShrink ? SIZE.xxl : SIZE.lg}
color={
item.on
? colors.primary.accent
: item.id.match(/(delete|trash)/g)
? colors.error.icon
: colors.secondary.icon
}
/>
</Pressable>
<Paragraph
size={SIZE.xs}
textBreakStrategy="simple"
style={{ textAlign: "center" }}
>
{item.title}
</Paragraph>
</View>
);
const renderColumnItem = (item) => (
<Button
key={item.name + item.title}
buttonType={{
text: item.on
? colors.primary.accent
: item.name === "Delete" || item.name === "PermDelete"
? colors.error.paragraph
: colors.primary.paragraph
}}
onPress={item.func}
title={item.title}
icon={item.icon}
type={item.on ? "shade" : "plain"}
fontSize={SIZE.sm}
style={{
borderRadius: 0,
justifyContent: "flex-start",
alignSelf: "flex-start",
width: "100%"
}}
/>
);
const renderTopBarItem = (item, index) => {
return (
<Pressable
onPress={() => {
item.func();
setImmediate(() => {
const currentValue = topBarSorting.current[item.id] || 0;
topBarSorting.current = {
...topBarSorting.current,
[item.id]: currentValue + 1
};
});
}}
key={item.id}
testID={"icon-" + item.id}
activeOpacity={1}
style={{
alignSelf: "flex-start",
paddingHorizontal: 0,
flex: 1
}}
>
<View
onPress={item.func}
style={{
height: topBarItemWidth,
justifyContent: "center",
alignItems: "center",
textAlign: "center",
textAlignVertical: "center",
marginBottom: DDS.isTab ? 7 : 3.5,
borderRadius: 100
}}
>
<Icon
name={item.icon}
allowFontScaling
size={DDS.isTab ? SIZE.xxl : SIZE.md + 4}
color={
item.on
? colors.primary.accent
: item.name === "Delete" || item.name === "PermDelete"
? colors.error.icon
: colors.secondary.icon
}
/>
</View>
<Paragraph
textBreakStrategy="simple"
size={SIZE.xxs}
style={{ textAlign: "center" }}
>
{item.title}
</Paragraph>
</Pressable>
);
};
const topBarItemsList = [
"pin",
"favorite",
"copy",
"share",
"lock-unlock",
"publish",
"export",
"copy-link",
"duplicate",
"local-only",
"read-only"
];
const bottomBarItemsList = [
"notebooks",
"add-reminder",
"pin-to-notifications",
"history",
"reminders",
"attachments",
"references",
"trash"
];
const topBarItems = data
.filter((item) => topBarItemsList.indexOf(item.id) > -1)
.sort((a, b) =>
topBarItemsList.indexOf(a.id) > topBarItemsList.indexOf(b.id) ? 1 : -1
)
.sort((a, b) => {
return (
(topBarSorting.current[b.id] || 0) - (topBarSorting.current[a.id] || 0)
);
});
const bottomGridItems = data
.filter((item) => bottomBarItemsList.indexOf(item.id) > -1)
.sort((a, b) =>
bottomBarItemsList.indexOf(a.id) > bottomBarItemsList.indexOf(b.id)
? 1
: -1
);
let topBarItemWidth =
(width - (topBarItems.length * 10 + 14)) / topBarItems.length;
topBarItemWidth;
if (topBarItemWidth < 60) {
topBarItemWidth = 60;
}
return item.type === "note" ? (
<>
<ScrollView
horizontal
style={{
paddingHorizontal: 12,
marginTop: 6,
marginBottom: 6
}}
showsHorizontalScrollIndicator={false}
contentContainerStyle={{
paddingRight: 25,
gap: 15
}}
>
{topBarItems.map(renderTopBarItem)}
</ScrollView>
<View
style={{
flexDirection: "row",
flexWrap: "wrap",
alignContent: "flex-start",
marginTop: item.type !== "note" ? 10 : 0,
paddingTop: 10,
marginLeft: 6
}}
>
{bottomGridItems.map((item) => _renderRowItem({ item }))}
</View>
</>
) : (
<View data={data}>{data.map(renderColumnItem)}</View>
);
};

View File

@@ -0,0 +1,359 @@
/*
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 { Item } from "@notesnook/core";
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { Dimensions, View } from "react-native";
import SwiperFlatList from "react-native-swiper-flatlist";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { Action, ActionId, useActions } from "../../hooks/use-actions";
import { useStoredRef } from "../../hooks/use-stored-ref";
import { DDS } from "../../services/device-detection";
import { useSettingStore } from "../../stores/use-setting-store";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { Button } from "../ui/button";
import { Pressable } from "../ui/pressable";
import Paragraph from "../ui/typography/paragraph";
const TOP_BAR_ITEMS: ActionId[] = [
"pin",
"favorite",
"lock-unlock",
"publish",
"local-only",
"read-only",
"pin-to-notifications"
];
const BOTTOM_BAR_ITEMS: ActionId[] = [
"notebooks",
"add-reminder",
"history",
"reminders",
"attachments",
"references",
"copy",
"share",
"export",
"copy-link",
"duplicate",
"trash"
];
const COLUMN_BAR_ITEMS: ActionId[] = [
"select",
"add-notebook",
"edit-notebook",
"move-notes",
"move-notebook",
"pin",
"default-notebook",
"add-shortcut",
"reorder",
"rename-color",
"rename-tag",
"restore",
"trash",
"delete"
];
export const Items = ({
item,
close,
buttons
}: {
item: Item;
close: () => void;
buttons: Action[];
}) => {
const { colors } = useThemeColors();
const topBarSorting = useStoredRef<{ [name: string]: number }>(
"topbar-sorting-ref",
{}
);
const dimensions = useSettingStore((state) => state.dimensions);
const actions = useActions({ item, close });
const selectedActions = actions.filter((i) => !i.hidden);
const deviceMode = useSettingStore((state) => state.deviceMode);
const width = Math.min(dimensions.width, 600);
const shouldShrink =
Dimensions.get("window").fontScale > 1 &&
Dimensions.get("window").width < 450;
const columnItemsCount = deviceMode === "tablet" ? 7 : shouldShrink ? 4 : 5;
const columnItemWidth =
deviceMode !== "mobile"
? (width - DefaultAppStyles.GAP) / columnItemsCount
: (width - DefaultAppStyles.GAP) / columnItemsCount;
const topBarItems = selectedActions
.filter((item) => TOP_BAR_ITEMS.indexOf(item.id) > -1)
.sort((a, b) =>
TOP_BAR_ITEMS.indexOf(a.id) > TOP_BAR_ITEMS.indexOf(b.id) ? 1 : -1
)
.sort((a, b) => {
return (
(topBarSorting.current[b.id] || 0) - (topBarSorting.current[a.id] || 0)
);
});
const bottomGridItems = selectedActions
.filter((item) => BOTTOM_BAR_ITEMS.indexOf(item.id) > -1)
.sort((a, b) =>
BOTTOM_BAR_ITEMS.indexOf(a.id) > BOTTOM_BAR_ITEMS.indexOf(b.id) ? 1 : -1
);
const columnItems = selectedActions
.filter((item) => COLUMN_BAR_ITEMS.indexOf(item.id) > -1)
.sort((a, b) =>
COLUMN_BAR_ITEMS.indexOf(a.id) > COLUMN_BAR_ITEMS.indexOf(b.id) ? 1 : -1
);
const topBarItemHeight = Math.min(
(width - (topBarItems.length * 10 + 14)) / topBarItems.length,
60
);
const renderRowItem = React.useCallback(
({ item }: { item: Action }) => (
<View
key={item.id}
style={{
alignItems: "center",
width: columnItemWidth - 8
}}
>
<Pressable
onPress={item.onPress}
type={item.checked ? "shade" : "secondary"}
testID={"icon-" + item.id}
style={{
height: columnItemWidth / 1.5,
width: columnItemWidth - 8,
borderRadius: 10,
justifyContent: "center",
alignItems: "center",
marginBottom: DDS.isTab ? 7 : 3.5
}}
>
<Icon
allowFontScaling
name={item.icon}
size={
DDS.isTab
? AppFontSize.xxl
: shouldShrink
? AppFontSize.xxl
: AppFontSize.lg
}
color={
item.checked
? item.activeColor || colors.primary.accent
: item.id.match(/(delete|trash)/g)
? colors.error.icon
: colors.secondary.icon
}
/>
</Pressable>
<Paragraph
size={AppFontSize.xxs}
textBreakStrategy="simple"
style={{ textAlign: "center" }}
>
{item.title}
</Paragraph>
</View>
),
[
colors.error.icon,
colors.primary.accent,
colors.secondary.icon,
columnItemWidth,
shouldShrink
]
);
const renderColumnItem = React.useCallback(
(item: Action) => (
<Button
key={item.id}
buttonType={{
text: item.checked
? item.activeColor || colors.primary.accent
: item.id === "delete" || item.id === "trash"
? colors.error.paragraph
: colors.primary.paragraph
}}
testID={"icon-" + item.id}
onPress={item.onPress}
title={item.title}
icon={item.icon}
type={item.checked ? "inverted" : "plain"}
fontSize={AppFontSize.sm}
style={{
borderRadius: 0,
justifyContent: "flex-start",
alignSelf: "flex-start",
width: "100%"
}}
/>
),
[colors.error.paragraph, colors.primary.accent, colors.primary.paragraph]
);
const renderTopBarItem = React.useCallback(
(item: Action) => {
return (
<Pressable
onPress={() => {
item.onPress();
setImmediate(() => {
const currentValue = topBarSorting.current[item.id] || 0;
topBarSorting.current = {
...topBarSorting.current,
[item.id]: currentValue + 1
};
});
}}
key={item.id}
testID={"icon-" + item.id}
style={{
width: columnItemWidth - 8
}}
>
<View
style={{
height: columnItemWidth / 2,
width: columnItemWidth - DefaultAppStyles.GAP_SMALL,
justifyContent: "center",
alignItems: "center"
}}
>
<Icon
name={item.icon}
allowFontScaling
size={DDS.isTab ? AppFontSize.xxl : AppFontSize.md + 4}
color={
item.checked
? item.activeColor || colors.primary.accent
: item.id === "delete" || item.id === "trash"
? colors.error.icon
: colors.secondary.icon
}
/>
</View>
<Paragraph
textBreakStrategy="simple"
size={AppFontSize.xxs}
style={{ textAlign: "center" }}
>
{item.title}
</Paragraph>
</Pressable>
);
},
[
colors.error.icon,
colors.primary.accent,
colors.secondary.icon,
columnItemWidth,
topBarSorting
]
);
const getTopBarItemChunksOfFour = () => {
const chunks = [];
for (let i = 0; i < topBarItems.length; i += 5) {
chunks.push(topBarItems.slice(i, i + 5));
}
return chunks;
};
return (
<View
style={{
gap: DefaultAppStyles.GAP
}}
>
{item.type === "note" ? (
<>
<View>
<SwiperFlatList
data={getTopBarItemChunksOfFour()}
autoplay={false}
showPagination
paginationStyleItemActive={{
borderRadius: 2,
backgroundColor: colors.selected.background,
height: 6,
marginHorizontal: 2
}}
paginationStyleItemInactive={{
borderRadius: 2,
backgroundColor: colors.secondary.background,
height: 6,
marginHorizontal: 2
}}
paginationStyle={{
position: "relative",
marginHorizontal: 2,
marginBottom: 0,
marginTop: DefaultAppStyles.GAP
}}
renderItem={({ item, index }) => (
<View
style={{
flexDirection: "row",
paddingHorizontal: DefaultAppStyles.GAP,
gap: 5,
width: width
}}
>
{item.map(renderTopBarItem)}
</View>
)}
/>
</View>
<View
style={{
flexDirection: "row",
flexWrap: "wrap",
gap: 5,
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{bottomGridItems.map((item) => renderRowItem({ item }))}
</View>
</>
) : (
<View>
{buttons.map(renderColumnItem)}
{columnItems.map(renderColumnItem)}
</View>
)}
</View>
);
};

View File

@@ -25,11 +25,12 @@ import { db } from "../../common/database";
import NotebookScreen from "../../screens/notebook";
import { eSendEvent, presentSheet } from "../../services/event-manager";
import { eClearEditor } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { Button } from "../ui/button";
import Heading from "../ui/typography/heading";
import { Pressable } from "../ui/pressable";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
export default function Notebooks({ note, close, full }) {
const { colors } = useThemeColors();
@@ -59,12 +60,12 @@ export default function Notebooks({ note, close, full }) {
type={full ? "transparent" : "secondary"}
style={{
justifyContent: "flex-start",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
flexDirection: "row",
alignItems: "center",
flexShrink: 1,
flexGrow: 1,
padding: 6,
padding: DefaultAppStyles.GAP_SMALL,
borderRadius: 10,
minHeight: 42
}}
@@ -72,7 +73,7 @@ export default function Notebooks({ note, close, full }) {
<Icon
name="book-outline"
color={colors.primary.accent}
size={SIZE.sm}
size={AppFontSize.sm}
style={{
marginRight: 5
}}
@@ -82,7 +83,7 @@ export default function Notebooks({ note, close, full }) {
style={{
maxWidth: "50%"
}}
size={SIZE.sm}
size={AppFontSize.sm}
>
{item.title}
</Heading>
@@ -92,40 +93,46 @@ export default function Notebooks({ note, close, full }) {
return noteNotebooks.length === 0 ? null : (
<View
style={{
width: "100%",
borderRadius: 10,
marginTop: 6
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{full
? noteNotebooks.map(renderItem)
: noteNotebooks.slice(0, 1).map(renderItem)}
<View
style={{
width: "100%",
borderRadius: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
{full
? noteNotebooks.map(renderItem)
: noteNotebooks.slice(0, 1).map(renderItem)}
{noteNotebooks.length > 1 && !full ? (
<Button
title={strings.viewAllLinkedNotebooks()}
fontSize={SIZE.xs}
style={{
alignSelf: "flex-end",
marginRight: 12,
paddingHorizontal: 0,
backgroundColor: "transparent"
}}
type="plain"
textStyle={{
textDecorationLine: "underline"
}}
height={20}
onPress={() => {
presentSheet({
context: "properties",
component: (ref, close) => (
<Notebooks note={note} close={close} full={true} />
)
});
}}
/>
) : undefined}
{noteNotebooks.length > 1 && !full ? (
<Button
title={strings.viewAllLinkedNotebooks()}
fontSize={AppFontSize.xs}
style={{
alignSelf: "flex-end",
marginRight: 12,
paddingHorizontal: 0,
backgroundColor: "transparent"
}}
type="plain"
textStyle={{
textDecorationLine: "underline"
}}
height={20}
onPress={() => {
presentSheet({
context: "properties",
component: (ref, close) => (
<Notebooks note={note} close={close} full={true} />
)
});
}}
/>
) : undefined}
</View>
</View>
);
}

View File

@@ -19,92 +19,44 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { View, useWindowDimensions } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { useUserStore } from "../../stores/use-user-store";
import { openLinkInBrowser } from "../../utils/functions";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { sleep } from "../../utils/time";
import { Button } from "../ui/button";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
export const Synced = ({ item, close }) => {
const { colors } = useThemeColors();
const user = useUserStore((state) => state.user);
const lastSynced = useUserStore((state) => state.lastSynced);
const dimensions = useWindowDimensions();
const shouldShrink = dimensions.fontScale > 1 && dimensions.width < 450;
return user && lastSynced >= item.dateModified ? (
<View
<Button
style={{
paddingVertical: 0,
width: "100%",
paddingHorizontal: 12,
alignItems: "center",
flexDirection: "row",
justifyContent: "flex-start",
alignSelf: "center",
paddingTop: 10,
marginTop: 10,
borderTopWidth: 1,
borderTopColor: colors.primary.border
alignSelf: "flex-start",
height: "auto",
padding: DefaultAppStyles.GAP_VERTICAL_SMALL,
paddingHorizontal: DefaultAppStyles.GAP_SMALL
}}
>
<Icon
name="shield-key-outline"
color={colors.primary.accent}
size={shouldShrink ? SIZE.xxl : SIZE.xxxl}
/>
<View
style={{
flex: 1,
marginLeft: 5,
flexShrink: 1
}}
>
<Heading
color={colors.primary.heading}
size={SIZE.xs}
style={{
flexWrap: "wrap"
}}
>
{strings.noteSyncedNoticeHeading()}
</Heading>
{shouldShrink ? null : (
<Paragraph
style={{
flexWrap: "wrap"
}}
size={SIZE.xs}
color={colors.primary.paragraph}
>
{strings.noteSyncedNoticeDesc(item.itemType || item.type)}
</Paragraph>
)}
</View>
<Button
onPress={async () => {
try {
close();
await sleep(300);
await openLinkInBrowser(
"https://help.notesnook.com/how-is-my-data-encrypted",
colors
);
} catch (e) {
console.error(e);
}
}}
title={strings.learnMore()}
fontSize={SIZE.xs}
height={30}
type="secondaryAccented"
/>
</View>
fontSize={AppFontSize.xxxs}
iconSize={AppFontSize.xs}
icon="shield-key-outline"
type="shade"
title="Encrypted and synced"
onPress={async () => {
try {
close();
await sleep(300);
await openLinkInBrowser(
"https://help.notesnook.com/how-is-my-data-encrypted",
colors
);
} catch (e) {
console.error(e);
}
}}
/>
) : null;
};

View File

@@ -22,12 +22,13 @@ import { View } from "react-native";
import { db } from "../../common/database";
import { TaggedNotes } from "../../screens/notes/tagged";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import ManageTagsSheet from "../sheets/manage-tags";
import { Button } from "../ui/button";
import { ColorTags } from "./color-tags";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
export const Tags = ({ item, close }) => {
const { colors } = useThemeColors();
@@ -35,11 +36,10 @@ export const Tags = ({ item, close }) => {
return item.id ? (
<View
style={{
marginTop: 5,
flexDirection: "row",
flexWrap: "wrap",
alignItems: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
alignSelf: "center",
justifyContent: "space-between",
width: "100%"
@@ -56,11 +56,10 @@ export const Tags = ({ item, close }) => {
type="secondary"
icon="plus"
iconPosition="right"
height={30}
fontSize={SIZE.sm - 1}
fontSize={AppFontSize.xs}
style={{
height: 35,
borderRadius: 100
paddingHorizontal: DefaultAppStyles.GAP_SMALL,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
/>
<ColorTags item={item} />
@@ -86,7 +85,7 @@ export const TagStrip = ({ item, close }) => {
flexDirection: "row",
flexWrap: "wrap",
alignItems: "center",
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
gap: 5
}}
>
@@ -117,7 +116,7 @@ const TagItem = ({ tag, close }) => {
title={"#" + tag.title}
type="plain"
height={20}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
style={style}
textStyle={{
color: colors.secondary.paragraph

View File

@@ -29,24 +29,23 @@ import {
} from "react-native";
import { Menu } from "react-native-material-menu";
import { db } from "../../common/database";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { ToastManager } from "../../services/event-manager";
import Navigation from "../../services/navigation";
import useNavigationStore from "../../stores/use-navigation-store";
import { useSelectionStore } from "../../stores/use-selection-store";
import { useTrashStore } from "../../stores/use-trash-store";
import { deleteItems } from "../../utils/functions";
import { tabBarRef } from "../../utils/global-refs";
import { fluidTabsRef } from "../../utils/global-refs";
import { updateNotebook } from "../../utils/notebooks";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { sleep } from "../../utils/time";
import { presentDialog } from "../dialog/functions";
import MoveNoteSheet from "../sheets/add-to";
import ExportNotesSheet from "../sheets/export-notes";
import ManageTagsSheet from "../sheets/manage-tags";
import { MoveNotebookSheet } from "../sheets/move-notebook";
import { Button } from "../ui/button";
import { MoveNotebook } from "../../screens/move-notebook";
import { IconButton } from "../ui/icon-button";
import Heading from "../ui/typography/heading";
import NativeTooltip from "../../utils/tooltip";
export const SelectionHeader = React.memo(
({
@@ -61,23 +60,20 @@ export const SelectionHeader = React.memo(
renderedInRoute?: string;
}) => {
const menuRef = useRef<Menu>(null);
const { colors: contextMenuColors } = useThemeColors("contextMenu");
const { colors } = useThemeColors();
const selectionMode = useSelectionStore((state) => state.selectionMode);
const selectedItemsList = useSelectionStore(
(state) => state.selectedItemsList
);
const clearSelection = useSelectionStore((state) => state.clearSelection);
const insets = useGlobalSafeAreaInsets();
const allSelected =
items?.placeholders?.length === selectedItemsList.length;
const focusedRouteId = useNavigationStore((state) => state.focusedRouteId);
useEffect(() => {
if (selectionMode) {
tabBarRef.current?.lock();
fluidTabsRef.current?.lock();
} else {
tabBarRef.current?.unlock();
fluidTabsRef.current?.unlock();
}
}, [selectionMode]);
@@ -103,8 +99,11 @@ export const SelectionHeader = React.memo(
const deleteItem = async () => {
if (!type) return;
presentDialog({
title: strings.doActions.delete.unknown(type, selectedItemsList.length),
paragraph: strings.actionConfirmations.delete.unknown(
title: strings.doActions.permanentlyDelete.unknown(
type,
selectedItemsList.length
),
paragraph: strings.actionConfirmations.permanentlyDelete.unknown(
type,
selectedItemsList.length
),
@@ -113,7 +112,7 @@ export const SelectionHeader = React.memo(
positivePress: async () => {
if (!selectedItemsList.length) return;
await db.trash.delete(...selectedItemsList);
Navigation.queueRoutesForUpdate();
useTrashStore.getState().refresh();
clearSelection();
},
positiveType: "errorShade"
@@ -139,61 +138,24 @@ export const SelectionHeader = React.memo(
<View
style={{
width: "100%",
height: Platform.OS === "android" ? 50 + insets.top : 50,
paddingTop: Platform.OS === "android" ? insets.top : null,
backgroundColor: colors.primary.background,
justifyContent: "space-between",
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
alignItems: "center",
flexDirection: "row",
zIndex: 999,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP,
position: "absolute",
bottom: 0,
borderTopWidth: 1,
borderColor: colors.primary.border,
justifyContent: "space-between"
}}
>
<View
style={{
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
borderRadius: 100
}}
>
<IconButton
style={{
justifyContent: "center",
alignItems: "center",
height: 40,
width: 40,
borderRadius: 100,
marginRight: 10
}}
onPress={() => {
clearSelection();
}}
color={colors.primary.icon}
name="close"
/>
<View
style={{
height: 40,
borderRadius: 100,
paddingHorizontal: 16,
justifyContent: "center",
flexDirection: "row",
alignItems: "center"
}}
>
<Heading size={SIZE.lg} color={colors.primary.paragraph}>
{selectedItemsList.length}
</Heading>
</View>
</View>
<View
style={{
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center"
gap: DefaultAppStyles.GAP_SMALL
}}
>
<IconButton
@@ -202,159 +164,155 @@ export const SelectionHeader = React.memo(
.getState()
.setAll(allSelected ? [] : [...((await items?.ids()) || [])]);
}}
tooltipText="Select all"
tooltipPosition={4}
style={{
marginLeft: 10
}}
color={
allSelected ? colors.primary.accent : colors.primary.paragraph
}
size={AppFontSize.lg}
color={allSelected ? colors.primary.accent : colors.primary.icon}
name="select-all"
/>
{selectedItemsList.length ? (
<Menu
ref={menuRef}
animationDuration={200}
style={{
borderRadius: 5,
backgroundColor: contextMenuColors.primary.background,
marginTop: 35
}}
onRequestClose={() => {
//@ts-ignore
menuRef.current?.hide();
}}
anchor={
<IconButton
onPress={() => {
//@ts-ignore
menuRef.current?.show();
}}
name="dots-vertical"
color={colors.primary.paragraph}
/>
}
>
{[
{
title: strings.move(),
onPress: async () => {
const ids = selectedItemsList;
const notebooks = await db.notebooks.all.items(ids);
MoveNotebookSheet.present(notebooks);
},
visible: renderedInRoute === "Notebooks",
icon: "arrow-right-bold-box-outline"
},
{
title: strings.manageTags(),
onPress: async () => {
await sleep(100);
ManageTagsSheet.present(selectedItemsList);
},
visible: type === "note",
icon: "pound"
},
{
title: strings.export(),
onPress: async () => {
await sleep(100);
ExportNotesSheet.present(selectedItemsList);
},
visible: type === "note",
icon: "export"
},
{
title: strings.linkNotebook(),
onPress: async () => {
await sleep(100);
MoveNoteSheet.present();
},
visible: type === "note",
icon: "plus"
},
{
title: strings.unlinkNotebook(),
onPress: async () => {
if (!id) return;
await db.notes.removeFromNotebook(id, ...selectedItemsList);
updateNotebook(id);
Navigation.queueRoutesForUpdate();
clearSelection();
},
visible: renderedInRoute === "Notebook",
icon: "minus"
},
{
title: strings.unfavorite(),
onPress: addToFavorite,
visible: focusedRouteId === "Favorites",
icon: "star-off"
},
{
title: strings.moveToTrash(),
onPress: async () => {
const selection = useSelectionStore.getState();
if (!selection.selectionMode) return;
await deleteItems(
selection.selectionMode as ItemType,
selection.selectedItemsList
);
selection.clearSelection();
selection.setSelectionMode(undefined);
},
visible: type === "note" || type === "notebook",
icon: "delete"
},
{
title: strings.doActions.delete.unknown(
type!,
selectedItemsList.length
),
onPress: async () => {
const selection = useSelectionStore.getState();
if (!selection.selectionMode) return;
await deleteItems(
selection.selectionMode as ItemType,
selection.selectedItemsList
);
selection.clearSelection();
selection.setSelectionMode(undefined);
},
visible:
type !== "trash" && type !== "note" && type !== "notebook",
icon: "delete"
},
{
title: strings.restore(),
onPress: restoreItem,
visible: type === "trash",
icon: "delete-restore"
},
{
title: strings.delete(),
onPress: deleteItem,
visible: type === "trash",
icon: "delete"
}
].map((item) =>
{!selectedItemsList.length
? null
: (focusedRouteId === "Monographs"
? [
{
title: strings.unpublish(),
onPress: () => {
presentDialog({
title: strings.doActions.unpublish.note(
selectedItemsList.length
),
positiveText: strings.unpublish(),
negativeText: strings.cancel(),
positivePress: async () => {
for (const id of selectedItemsList) {
await db.monographs.unpublish(id);
}
Navigation.queueRoutesForUpdate();
clearSelection();
},
positiveType: "errorShade"
});
},
visible: true,
icon: "delete"
}
]
: [
{
title: strings.move(),
onPress: async () => {
const ids = selectedItemsList;
const notebooks = await db.notebooks.all.items(ids);
MoveNotebook.present(notebooks);
},
visible: renderedInRoute === "Notebooks",
icon: "arrow-right-bold-box-outline"
},
{
title: strings.manageTags(),
onPress: async () => {
ManageTagsSheet.present(selectedItemsList);
},
visible: type === "note",
icon: "pound"
},
{
title: strings.export(),
onPress: async () => {
ExportNotesSheet.present(selectedItemsList);
},
visible: type === "note",
icon: "export"
},
{
title: strings.addToNotebook(),
onPress: async () => {
Navigation.navigate("LinkNotebooks", {
noteIds: selectedItemsList
});
},
visible: type === "note",
icon: "plus"
},
{
title: strings.unlinkNotebook(),
onPress: async () => {
if (!id) return;
await db.notes.removeFromNotebook(
id,
...selectedItemsList
);
updateNotebook(id);
Navigation.queueRoutesForUpdate();
clearSelection();
},
visible: renderedInRoute === "Notebook",
icon: "minus"
},
{
title: strings.unfavorite(),
onPress: addToFavorite,
visible: focusedRouteId === "Favorites",
icon: "star-off"
},
{
title: strings.moveToTrash(),
onPress: async () => {
const selection = useSelectionStore.getState();
if (!selection.selectionMode) return;
await deleteItems(
selection.selectionMode as ItemType,
selection.selectedItemsList
);
selection.clearSelection();
selection.setSelectionMode(undefined);
},
visible: type === "note" || type === "notebook",
icon: "delete"
},
{
title: strings.doActions.delete.unknown(
type!,
selectedItemsList.length
),
onPress: async () => {
const selection = useSelectionStore.getState();
if (!selection.selectionMode) return;
await deleteItems(
selection.selectionMode as ItemType,
selection.selectedItemsList
);
selection.clearSelection();
selection.setSelectionMode(undefined);
},
visible:
type !== "trash" &&
type !== "note" &&
type !== "notebook",
icon: "delete"
},
{
title: strings.restore(),
onPress: restoreItem,
visible: type === "trash",
icon: "delete-restore"
},
{
title: strings.delete(),
onPress: deleteItem,
visible: type === "trash",
icon: "delete"
}
]
).map((item) =>
!item.visible ? null : (
<Button
style={{
justifyContent: "flex-start",
borderRadius: 0,
alignSelf: "flex-start",
width: "100%"
}}
<IconButton
size={AppFontSize.lg}
type="plain"
buttonType={{
text: contextMenuColors.primary.paragraph
}}
icon={item.icon}
tooltipText={item.title}
tooltipPosition={NativeTooltip.POSITIONS.TOP}
testID={`select-${item.icon}`}
name={item.icon}
key={item.title}
title={item.title}
color={colors.primary.icon}
onPress={async () => {
//@ts-ignore
menuRef.current?.hide();
@@ -364,9 +322,16 @@ export const SelectionHeader = React.memo(
/>
)
)}
</Menu>
) : null}
</View>
<IconButton
size={AppFontSize.lg}
onPress={() => {
clearSelection();
}}
color={colors.primary.icon}
name="close"
/>
</View>
);
}

View File

@@ -27,12 +27,13 @@ import {
} from "../../services/event-manager";
import { useThemeColors } from "@notesnook/theme";
import { eCloseSheet, eOpenSheet } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { Button } from "../ui/button";
import SheetWrapper from "../ui/sheet";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { DefaultAppStyles } from "../../utils/styles";
const SheetProvider = ({ context = "global" }) => {
const { colors } = useThemeColors();
const [visible, setVisible] = useState(false);
@@ -94,6 +95,8 @@ const SheetProvider = ({ context = "global" }) => {
[context]
);
console.log(data?.keyboardHandlerDisabled);
return !visible || !data ? null : (
<SheetWrapper
fwdRef={actionSheetRef}
@@ -120,13 +123,13 @@ const SheetProvider = ({ context = "global" }) => {
!data.progress && !data.icon && !data.title && !data.paragraph
? 0
: 10,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{data?.progress ? (
<ActivityIndicator
style={{
marginTop: 15
marginTop: DefaultAppStyles.GAP
}}
size={50}
color={colors.primary.accent}
@@ -169,7 +172,7 @@ const SheetProvider = ({ context = "global" }) => {
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
marginBottom: data.valueArray ? 12 : 0
}}
>
@@ -180,7 +183,7 @@ const SheetProvider = ({ context = "global" }) => {
type="plain"
key={v}
textStyle={{ fontWeight: "normal" }}
fontSize={SIZE.sm}
fontSize={AppFontSize.sm}
icon="check"
width="100%"
style={{
@@ -193,7 +196,7 @@ const SheetProvider = ({ context = "global" }) => {
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{data?.action ? (
@@ -220,10 +223,10 @@ const SheetProvider = ({ context = "global" }) => {
icon={item.icon && item.icon}
type={item.type || "accent"}
style={{
marginBottom: 10
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
width="100%"
fontSize={SIZE.md}
fontSize={AppFontSize.md}
/>
))}
@@ -231,17 +234,17 @@ const SheetProvider = ({ context = "global" }) => {
<Paragraph
style={{
alignSelf: "center",
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
textDecorationLine: "underline"
}}
size={SIZE.xs}
size={AppFontSize.xs}
onPress={data.learnMorePress}
color={colors.secondary.paragraph}
>
<Icon
color={colors.primary.icon}
name="information-outline"
size={SIZE.xs}
size={AppFontSize.xs}
/>{" "}
{data.learnMore}
</Paragraph>

View File

@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Notebook } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import React, { useRef, useState } from "react";
import { TextInput, View } from "react-native";
import { notesnook } from "../../../../e2e/test.ids";
@@ -30,17 +31,16 @@ import {
} from "../../../services/event-manager";
import Navigation from "../../../services/navigation";
import { useMenuStore } from "../../../stores/use-menu-store";
import { useNotebookStore } from "../../../stores/use-notebook-store";
import { useRelationStore } from "../../../stores/use-relation-store";
import { SIZE } from "../../../utils/size";
import { eOnNotebookUpdated } from "../../../utils/events";
import { getParentNotebookId } from "../../../utils/notebooks";
import { AppFontSize } from "../../../utils/size";
import { Button } from "../../ui/button";
import Input from "../../ui/input";
import Seperator from "../../ui/seperator";
import Heading from "../../ui/typography/heading";
import { MoveNotes } from "../move-notes/movenote";
import { eOnNotebookUpdated } from "../../../utils/events";
import { getParentNotebookId } from "../../../utils/notebooks";
import { useNotebookStore } from "../../../stores/use-notebook-store";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
export const AddNotebookSheet = ({
notebook,
@@ -97,18 +97,28 @@ export const AddNotebookSheet = ({
parentNotebook?.id ||
(await getParentNotebookId(notebook?.id || (id as string)));
eSendEvent(eOnNotebookUpdated, parent);
if (notebook) {
setImmediate(() => {
eSendEvent(eOnNotebookUpdated, notebook.id);
});
eSendEvent(eOnNotebookUpdated, parent || notebook?.id);
if (!parent) {
useNotebookStore.getState().refresh();
}
if (!notebook && showMoveNotesOnComplete && id) {
MoveNotes.present(await db.notebooks.notebook(id));
} else {
close?.(true);
if (showMoveNotesOnComplete && id && !notebook?.id) {
ToastManager.show({
heading: strings.notebookAdded(),
type: "success",
context: "global",
actionText: strings.addNotes(),
duration: 8000,
func: async () => {
Navigation.navigate("MoveNotes", {
notebook: (await db.notebooks.notebook(id)) as Notebook
});
ToastManager.hide();
}
});
}
close?.(true);
};
return (
@@ -116,10 +126,10 @@ export const AddNotebookSheet = ({
style={{
maxHeight: DDS.isTab ? "90%" : "97%",
borderRadius: DDS.isTab ? 5 : 0,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Heading size={SIZE.lg}>
<Heading size={AppFontSize.lg}>
{notebook ? strings.editNotebook() : strings.newNotebook()}
</Heading>
@@ -160,10 +170,8 @@ export const AddNotebookSheet = ({
<Button
title={notebook ? strings.save() : strings.add()}
type="accent"
height={45}
fontSize={SIZE.md}
style={{
paddingHorizontal: 24,
paddingHorizontal: DefaultAppStyles.GAP * 2,
width: "100%"
}}
onPress={onSaveChanges}

View File

@@ -1,343 +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 { Note } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, {
RefObject,
useCallback,
useEffect,
useRef,
useState
} from "react";
import {
ActivityIndicator,
Keyboard,
TouchableOpacity,
View
} from "react-native";
import { ActionSheetRef } from "react-native-actions-sheet";
import { FlashList } from "react-native-actions-sheet/dist/src/views/FlashList";
import { db } from "../../../common/database";
import { presentSheet } from "../../../services/event-manager";
import Navigation from "../../../services/navigation";
import { ItemSelection } from "../../../stores/item-selection-store";
import { useNotebooks } from "../../../stores/use-notebook-store";
import { useRelationStore } from "../../../stores/use-relation-store";
import { useSelectionStore } from "../../../stores/use-selection-store";
import { useSettingStore } from "../../../stores/use-setting-store";
import { updateNotebook } from "../../../utils/notebooks";
import { SIZE } from "../../../utils/size";
import { Dialog } from "../../dialog";
import DialogHeader from "../../dialog/dialog-header";
import SheetProvider from "../../sheet-provider";
import { Button } from "../../ui/button";
import { IconButton } from "../../ui/icon-button";
import Input from "../../ui/input";
import Paragraph from "../../ui/typography/paragraph";
import { AddNotebookSheet } from "../add-notebook";
import { NotebookItem } from "./notebook-item";
import { useNotebookItemSelectionStore } from "./store";
async function updateInitialSelectionState(items: string[]) {
const relations = await db.relations
.to(
{
type: "note",
ids: items
},
"notebook"
)
.get();
const initialSelectionState: ItemSelection = {};
const notebookIds = [
...new Set(relations.map((relation) => relation.fromId))
];
for (const id of notebookIds) {
const all = items.every((noteId) => {
return (
relations.findIndex(
(relation) => relation.fromId === id && relation.toId === noteId
) > -1
);
});
if (all) {
initialSelectionState[id] = "selected";
} else {
initialSelectionState[id] = "intermediate";
}
}
useNotebookItemSelectionStore.setState({
initialState: initialSelectionState,
selection: { ...initialSelectionState },
multiSelect: relations.length > 1
});
}
const MoveNoteSheet = ({
note,
actionSheetRef
}: {
note: Note | undefined;
actionSheetRef: RefObject<ActionSheetRef>;
}) => {
const { colors } = useThemeColors();
const [rootNotebooks, loading] = useNotebooks();
const searchQuery = useRef("");
const searchTimer = useRef<NodeJS.Timeout>();
const [notebooks, setNotebooks] = useState(rootNotebooks);
const dimensions = useSettingStore((state) => state.dimensions);
const selectedItemsList = useSelectionStore(
(state) => state.selectedItemsList
);
const multiSelect = useNotebookItemSelectionStore(
(state) => state.multiSelect
);
useEffect(() => {
if (!loading) {
setNotebooks(rootNotebooks);
}
}, [loading, rootNotebooks]);
useEffect(() => {
const items = note ? [note.id] : selectedItemsList;
updateInitialSelectionState(items);
return () => {
useNotebookItemSelectionStore.setState({
initialState: {},
selection: {},
multiSelect: false,
canEnableMultiSelectMode: true
});
};
}, [note, selectedItemsList]);
const onSave = async () => {
const noteIds = note ? [note.id] : selectedItemsList;
const changedNotebooks = useNotebookItemSelectionStore.getState().selection;
for (const id in changedNotebooks) {
const item = await db.notebooks.notebook(id);
if (!item) continue;
if (changedNotebooks[id] === "selected") {
for (const id of noteIds) {
await db.relations.add(item, { id: id, type: "note" });
updateNotebook(item.id);
}
} else if (changedNotebooks[id] === "deselected") {
for (const id of noteIds) {
await db.relations.unlink(item, { id: id, type: "note" });
updateNotebook(item.id);
}
}
}
Navigation.queueRoutesForUpdate();
useRelationStore.getState().update();
actionSheetRef.current?.hide();
};
const hasSelected = () => {
const selection = useNotebookItemSelectionStore.getState().selection;
return Object.keys(selection).some((key) => selection[key] === "selected");
};
const renderNotebook = useCallback(
({ index }: { item: boolean; index: number }) => (
<NotebookItem items={notebooks} id={index} index={index} />
),
[notebooks]
);
return (
<>
<Dialog context="move_note" />
<SheetProvider context="link-notebooks" />
<View>
<TouchableOpacity
style={{
width: "100%",
height: "100%",
position: "absolute"
}}
onPress={() => {
Keyboard.dismiss();
}}
/>
<View
style={{
paddingHorizontal: 12,
justifyContent: "space-between",
flexDirection: "row",
alignItems: "flex-start"
}}
>
<DialogHeader
style={{
minHeight: 10,
flexShrink: 1
}}
title={strings.selectNotebooks()}
paragraph={
!multiSelect
? strings.enableMultiSelect()
: strings.selectNotebooksDesc()
}
/>
<View
style={{
flexDirection: "row",
columnGap: 10
}}
>
{hasSelected() ? (
<IconButton
name="restore"
color={colors.primary.icon}
onPress={() => {
const items = note ? [note.id] : selectedItemsList;
updateInitialSelectionState(items);
}}
style={{
width: 40,
height: 40
}}
/>
) : null}
<Button
height={40}
style={{
borderRadius: 100,
paddingHorizontal: 24,
alignSelf: "flex-start"
}}
title={strings.save()}
type={"accent"}
onPress={onSave}
/>
</View>
</View>
<View
style={{
paddingHorizontal: 0,
maxHeight: dimensions.height * 0.85,
height: dimensions.height * 0.85,
paddingTop: 6
}}
>
<FlashList
data={notebooks?.placeholders}
style={{
width: "100%"
}}
keyboardShouldPersistTaps="handled"
ListHeaderComponent={
<View
style={{
paddingHorizontal: 12,
width: "100%",
paddingTop: 12
}}
>
<Input
placeholder={strings.searchNotebooks()}
button={{
icon: "plus",
onPress: () => {
AddNotebookSheet.present(
undefined,
undefined,
"link-notebooks",
undefined,
false,
searchQuery.current
);
},
color: colors.primary.icon
}}
onChangeText={(value) => {
searchQuery.current = value;
if (!searchQuery.current) {
setNotebooks(rootNotebooks);
return;
}
searchTimer.current = setTimeout(() => {
db.lookup
.notebooks(searchQuery.current)
.sorted()
.then((result) => {
if (searchQuery.current === value) {
setNotebooks(result);
}
});
}, 300);
}}
/>
</View>
}
estimatedItemSize={50}
renderItem={renderNotebook}
ListEmptyComponent={
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
height: 200
}}
>
{loading ? (
<ActivityIndicator
size={SIZE.lg}
color={colors.primary.accent}
/>
) : (
<Paragraph color={colors.primary.icon}>
{strings.emptyPlaceholders("notebook")}
</Paragraph>
)}
</View>
}
ListFooterComponent={<View style={{ height: 50 }} />}
/>
</View>
</View>
</>
);
};
MoveNoteSheet.present = (note?: Note) => {
presentSheet({
component: (ref) => <MoveNoteSheet actionSheetRef={ref} note={note} />,
enableGesturesInScrollView: false,
noBottomPadding: true,
keyboardHandlerDisabled: true
});
};
export default MoveNoteSheet;

View File

@@ -1,263 +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 { Notebook, VirtualizedGrouping } from "@notesnook/core";
import { useThemeColors } from "@notesnook/theme";
import React, { useEffect } from "react";
import { View, useWindowDimensions } from "react-native";
import { notesnook } from "../../../../e2e/test.ids";
import { useTotalNotes } from "../../../hooks/use-db-item";
import { useNotebook } from "../../../hooks/use-notebook";
import useNavigationStore from "../../../stores/use-navigation-store";
import { SIZE } from "../../../utils/size";
import { IconButton } from "../../ui/icon-button";
import { Pressable } from "../../ui/pressable";
import Paragraph from "../../ui/typography/paragraph";
import { AddNotebookSheet } from "../add-notebook";
import {
useNotebookExpandedStore,
useNotebookItemSelectionStore
} from "./store";
type NotebookParentProp = {
parent?: NotebookParentProp;
item?: Notebook;
};
export const NotebookItem = ({
id,
currentLevel = 0,
index,
parent,
items
}: {
id: string | number;
currentLevel?: number;
index: number;
parent?: NotebookParentProp;
items?: VirtualizedGrouping<Notebook>;
}) => {
const { nestedNotebooks, notebook: item } = useNotebook(id, items, true);
const expanded = useNotebookExpandedStore((state) =>
item?.id ? state.expanded[item?.id] : false
);
const { totalNotes: totalNotes, getTotalNotes } = useTotalNotes("notebook");
const focusedRouteId = useNavigationStore((state) => state.focusedRouteId);
const { colors } = useThemeColors("sheet");
const selection = useNotebookItemSelectionStore((state) =>
item?.id ? state.selection[item?.id] : undefined
);
const isSelected = selection === "selected";
const isFocused = focusedRouteId === id;
const { fontScale } = useWindowDimensions();
useEffect(() => {
if (item?.id) {
getTotalNotes([item?.id]);
}
}, [getTotalNotes, item?.id]);
const onPress = () => {
if (!item) return;
const state = useNotebookItemSelectionStore.getState();
if (isSelected) {
state.markAs(
item,
!state.initialState[item?.id] ? undefined : "deselected"
);
return;
}
if (!state.multiSelect) {
const keys = Object.keys(state.selection);
const nextState: any = {};
for (const key in keys) {
nextState[key] = !state.initialState[key] ? undefined : "deselected";
}
state.setSelection({
[item.id]: "selected",
...nextState
});
} else {
state.markAs(item, "selected");
}
};
return (
<View
style={{
paddingLeft: currentLevel > 0 && currentLevel < 6 ? 15 : undefined,
width: "100%"
}}
>
<Pressable
type={"transparent"}
onLongPress={() => {
if (!item) return;
useNotebookItemSelectionStore.setState({
multiSelect: true
});
const state = useNotebookItemSelectionStore.getState();
useNotebookItemSelectionStore
.getState()
.markAs(
item,
!isSelected
? "selected"
: !state.initialState[item?.id]
? undefined
: "deselected"
);
}}
testID={`add-to-notebook-item-${currentLevel}-${index}`}
onPress={onPress}
style={{
justifyContent: "space-between",
width: "100%",
alignItems: "center",
flexDirection: "row",
paddingLeft: 12,
paddingRight: 12,
borderRadius: 0,
height: 45
}}
>
<View
style={{
flexDirection: "row",
alignItems: "center"
}}
>
{nestedNotebooks?.placeholders.length ? (
<IconButton
size={SIZE.xl}
color={isSelected ? colors.selected.icon : colors.primary.icon}
onPress={() => {
if (!item?.id) return;
useNotebookExpandedStore.getState().setExpanded(item?.id);
}}
top={0}
left={0}
bottom={0}
right={0}
style={{
width: 35,
height: 35
}}
name={expanded ? "chevron-down" : "chevron-right"}
/>
) : null}
<IconButton
size={SIZE.xl}
color={
isSelected
? colors.selected.icon
: selection === "deselected"
? colors.error.accent
: colors.primary.icon
}
onPress={onPress}
top={0}
left={0}
bottom={0}
right={0}
style={{
width: 40,
height: 40
}}
name={
selection === "deselected"
? "close-circle-outline"
: isSelected
? "check-circle-outline"
: selection === "intermediate"
? "minus-circle-outline"
: "checkbox-blank-circle-outline"
}
/>
<Paragraph
color={
isFocused ? colors.selected.paragraph : colors.secondary.paragraph
}
size={SIZE.sm}
>
{item?.title}
</Paragraph>
</View>
<View
style={{
flexDirection: "row",
columnGap: 10,
alignItems: "center"
}}
>
{item?.id && totalNotes?.(item?.id) ? (
<Paragraph size={SIZE.sm} color={colors.secondary.paragraph}>
{totalNotes(item?.id)}
</Paragraph>
) : null}
<IconButton
name="plus"
style={{
width: 40 * fontScale,
height: 40 * fontScale
}}
testID={notesnook.ids.notebook.menu}
onPress={() => {
if (!item) return;
AddNotebookSheet.present(
undefined,
item,
"link-notebooks",
undefined,
false
);
}}
left={0}
right={0}
bottom={0}
top={0}
color={colors.primary.icon}
size={SIZE.xl}
/>
</View>
</Pressable>
{!expanded
? null
: nestedNotebooks?.placeholders.map((id, index) => (
<NotebookItem
key={item?.id + "_" + index}
id={index}
index={index}
currentLevel={currentLevel + 1}
items={nestedNotebooks}
parent={{
parent: parent,
item: item
}}
/>
))}
</View>
);
};

View File

@@ -31,6 +31,7 @@ import { Button } from "../../ui/button";
import Input from "../../ui/input";
import { eUserLoggedIn } from "../../../utils/events";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
type ChangeEmailProps = {
actionSheetRef: RefObject<ActionSheetRef>;
@@ -101,14 +102,14 @@ export const ChangeEmail = ({ close }: ChangeEmailProps) => {
};
return (
<View style={{ paddingHorizontal: 12 }}>
<View style={{ paddingHorizontal: DefaultAppStyles.GAP }}>
<DialogHeader
title={strings.changeEmail()}
paragraph={strings.changeEmailDesc()}
/>
<View
style={{
marginTop: 12
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
>
{step === EmailChangeSteps.verify ? (

View File

@@ -32,11 +32,12 @@ import {
import { editorController } from "../../../screens/editor/tiptap/utils";
import { eSendEvent, presentSheet } from "../../../services/event-manager";
import { eUnlockNote } from "../../../utils/events";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { IconButton } from "../../ui/icon-button";
import { Pressable } from "../../ui/pressable";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { DefaultAppStyles } from "../../../utils/styles";
const TabItemComponent = (props: {
tab: TabItem;
@@ -101,15 +102,15 @@ const TabItemComponent = (props: {
{props.tab.session?.noteLocked ? (
<>
{props.tab.session?.locked ? (
<Icon size={SIZE.md} name="lock" />
<Icon size={AppFontSize.md} name="lock" />
) : (
<Icon size={SIZE.md} name="lock-open-outline" />
<Icon size={AppFontSize.md} name="lock-open-outline" />
)}
</>
) : null}
{props.tab.session?.readonly ? (
<Icon size={SIZE.md} name="pencil-lock" />
<Icon size={AppFontSize.md} name="pencil-lock" />
) : null}
<Paragraph
@@ -119,7 +120,7 @@ const TabItemComponent = (props: {
: colors.primary.paragraph
}
numberOfLines={1}
size={SIZE.md}
size={AppFontSize.md}
>
{props.tab.session?.noteId
? item?.title || strings.untitledNote()
@@ -136,7 +137,7 @@ const TabItemComponent = (props: {
>
<IconButton
name="pin"
size={SIZE.lg}
size={AppFontSize.lg}
color={props.tab.pinned ? colors.primary.accent : colors.primary.icon}
onPress={() => {
useTabStore.getState().updateTab(props.tab.id, {
@@ -152,7 +153,7 @@ const TabItemComponent = (props: {
{!props.tab?.pinned ? (
<IconButton
name="close"
size={SIZE.lg}
size={AppFontSize.lg}
color={colors.primary.icon}
onPress={() => {
const isLastTab = useTabStore.getState().tabs.length === 1;
@@ -202,7 +203,7 @@ export default function EditorTabs({
return (
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
gap: 12,
maxHeight: "100%"
}}
@@ -215,7 +216,7 @@ export default function EditorTabs({
alignItems: "center"
}}
>
<Heading size={SIZE.lg}>{strings.tabs()}</Heading>
<Heading size={AppFontSize.lg}>{strings.tabs()}</Heading>
<IconButton
onPress={() => {
useTabStore.getState().newTab();

View File

@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { Fragment, useState } from "react";
import {
@@ -39,9 +40,11 @@ import {
} 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 { SIZE, ph, pv } from "../../../utils/size";
import { AppFontSize, defaultBorderRadius } from "../../../utils/size";
import { DefaultAppStyles } from "../../../utils/styles";
import { sleep } from "../../../utils/time";
import { Dialog } from "../../dialog";
import DialogHeader from "../../dialog/dialog-header";
@@ -52,14 +55,15 @@ import { Pressable } from "../../ui/pressable";
import Seperator from "../../ui/seperator";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
const ExportNotesSheet = ({
ids,
update
update,
close
}: {
ids: string[];
update: ((props: PresentSheetOptions) => void) | undefined;
close: ((ctx?: string) => void) | undefined;
}) => {
const { colors } = useThemeColors();
const [exporting, setExporting] = useState(false);
@@ -166,7 +170,7 @@ const ExportNotesSheet = ({
<>
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<DialogHeader
@@ -193,17 +197,17 @@ const ExportNotesSheet = ({
alignItems: "center",
flexDirection: "row",
paddingRight: 12,
paddingVertical: 10,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
justifyContent: "flex-start",
borderRadius: 0,
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
opacity: item.pro ? 1 : 0.5
}}
>
<View
style={{
backgroundColor: colors.primary.shade,
borderRadius: 5,
borderRadius: defaultBorderRadius,
height: 60,
width: 60,
justifyContent: "center",
@@ -215,7 +219,7 @@ const ExportNotesSheet = ({
color={
item.pro ? colors.primary.accent : colors.primary.icon
}
size={SIZE.xxxl + 10}
size={AppFontSize.xxxl + 10}
/>
</View>
<View
@@ -224,7 +228,7 @@ const ExportNotesSheet = ({
}}
>
{!item.pro ? <ProTag size={12} /> : null}
<Heading style={{ marginLeft: 10 }} size={SIZE.md}>
<Heading style={{ marginLeft: 10 }} size={AppFontSize.md}>
{item.title}
</Heading>
{/* <Paragraph
@@ -245,8 +249,8 @@ const ExportNotesSheet = ({
justifyContent: "center",
alignItems: "center",
width: "100%",
paddingHorizontal: 12,
paddingVertical: 20
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
{!complete ? (
@@ -273,7 +277,7 @@ const ExportNotesSheet = ({
<Heading
style={{
textAlign: "center",
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
color={colors.secondary.heading}
>
@@ -294,13 +298,13 @@ const ExportNotesSheet = ({
}
type="accent"
width={250}
fontSize={SIZE.md}
fontSize={AppFontSize.md}
style={{
marginTop: 10,
borderRadius: 100
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
onPress={async () => {
if (!result?.filePath) return;
close?.();
if (Platform.OS === "android") {
Linking.openURL(result.fileDir).catch((e) => {
ToastManager.error(e as Error);
@@ -323,13 +327,16 @@ const ExportNotesSheet = ({
title={strings.share()}
type="secondaryAccented"
width={250}
fontSize={SIZE.md}
fontSize={AppFontSize.md}
style={{
marginTop: 10,
borderRadius: 100
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
onPress={async () => {
if (!result) return;
close?.();
useSettingStore
.getState()
.setAppDidEnterBackgroundForAction(true);
if (Platform.OS === "ios") {
Share.open({
url: result?.fileDir + result.fileName
@@ -349,12 +356,11 @@ const ExportNotesSheet = ({
/>
<Button
title={strings.exportAgain()}
type="inverted"
type="secondaryAccented"
width={250}
fontSize={SIZE.md}
fontSize={AppFontSize.md}
style={{
marginTop: 10,
borderRadius: 100
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
onPress={async () => {
setComplete(false);
@@ -375,7 +381,7 @@ ExportNotesSheet.present = async (ids?: string[], allNotes?: boolean) => {
const exportNoteIds = allNotes ? await db.notes.all?.ids() : ids || [];
presentSheet({
component: (ref, close, update) => (
<ExportNotesSheet ids={exportNoteIds} update={update} />
<ExportNotesSheet ids={exportNoteIds} update={update} close={close} />
),
keyboardHandlerDisabled: true
});
@@ -384,18 +390,18 @@ ExportNotesSheet.present = async (ids?: string[], allNotes?: boolean) => {
const styles = StyleSheet.create({
container: {
...getElevationStyle(5),
borderRadius: 5,
paddingVertical: pv
borderRadius: defaultBorderRadius,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
},
buttonContainer: {
justifyContent: "space-between",
alignItems: "center"
},
button: {
paddingVertical: pv,
paddingHorizontal: ph,
marginTop: 10,
borderRadius: 5,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
paddingHorizontal: DefaultAppStyles.GAP,
marginTop: DefaultAppStyles.GAP_VERTICAL,
borderRadius: defaultBorderRadius,
width: "100%",
justifyContent: "center",
alignItems: "center",
@@ -405,7 +411,7 @@ const styles = StyleSheet.create({
buttonText: {
//fontFamily: "sans-serif",
color: "white",
fontSize: SIZE.sm,
fontSize: AppFontSize.sm,
marginLeft: 5
},
overlay: {

View File

@@ -21,9 +21,10 @@ import React from "react";
import { View } from "react-native";
import FileViewer from "react-native-file-viewer";
import { ToastManager } from "../../../services/event-manager";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { Button } from "../../ui/button";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
export const ShareComponent = ({ uri, name, padding }) => {
return (
<View
@@ -35,7 +36,7 @@ export const ShareComponent = ({ uri, name, padding }) => {
title={strings.open()}
type="accent"
width="100%"
fontSize={SIZE.md}
fontSize={AppFontSize.md}
onPress={async () => {
FileViewer.open(uri, {
showOpenWithDialog: true,
@@ -53,9 +54,9 @@ export const ShareComponent = ({ uri, name, padding }) => {
title={strings.share()}
type="shade"
width="100%"
fontSize={SIZE.md}
fontSize={AppFontSize.md}
style={{
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
onPress={async () => {
FileViewer.open(uri, {

View File

@@ -28,13 +28,14 @@ import { ToastManager } from "../../../services/event-manager";
import PremiumService from "../../../services/premium";
import { useUserStore } from "../../../stores/use-user-store";
import { openLinkInBrowser } from "../../../utils/functions";
import { SIZE } from "../../../utils/size";
import { defaultBorderRadius, AppFontSize } from "../../../utils/size";
import DialogHeader from "../../dialog/dialog-header";
import { Button } from "../../ui/button";
import Seperator from "../../ui/seperator";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
export const Issue = ({ defaultTitle, defaultBody, issueTitle }) => {
const { colors } = useThemeColors();
@@ -69,6 +70,15 @@ Pro: ${PremiumService.get()}
Logged in: ${user ? "yes" : "no"}`,
userId: user?.id
});
if (!issueUrl.current) {
setLoading(false);
ToastManager.show({
heading: "Failed to report issue on github",
type: "error",
context: "local"
});
return;
}
setLoading(false);
body.reset();
title.reset();
@@ -85,7 +95,7 @@ Logged in: ${user ? "yes" : "no"}`,
return (
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
width: "100%"
}}
>
@@ -147,11 +157,11 @@ Logged in: ${user ? "yes" : "no"}`,
style={{
borderWidth: 1,
borderColor: colors.primary.border,
borderRadius: 5,
padding: 12,
borderRadius: defaultBorderRadius,
padding: DefaultAppStyles.GAP,
fontFamily: "OpenSans-Regular",
marginBottom: 10,
fontSize: SIZE.md,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
fontSize: AppFontSize.md,
color: colors.primary.heading
}}
placeholderTextColor={colors.primary.placeholder}
@@ -180,18 +190,18 @@ Logged in: ${user ? "yes" : "no"}`,
style={{
borderWidth: 1,
borderColor: colors.primary.border,
borderRadius: 5,
padding: 12,
borderRadius: defaultBorderRadius,
padding: DefaultAppStyles.GAP,
fontFamily: "OpenSans-Regular",
maxHeight: 200,
fontSize: SIZE.sm,
fontSize: AppFontSize.sm,
marginBottom: 2.5,
color: colors.primary.paragraph
}}
placeholderTextColor={colors.primary.placeholder}
/>
<Paragraph
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
>{`App version: ${getVersion()} Platform: ${
Platform.OS
@@ -208,16 +218,18 @@ Logged in: ${user ? "yes" : "no"}`,
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
textAlign: "center"
}}
>
{strings.issueNotice[0]()}{" "}
<Text
onPress={() => {
Linking.openURL("https://github.com/streetwriters/notesnook/issues");
Linking.openURL(
"https://github.com/streetwriters/notesnook/issues"
);
}}
style={{
textDecorationLine: "underline",

Some files were not shown because too many files have changed in this diff Show More