Compare commits

...

135 Commits

Author SHA1 Message Date
Abdullah Atta
ade6e305db web: bump version to 3.1.0-beta.5 2025-03-28 20:59:20 +05:00
Abdullah Atta
692635dc31 web: remove SharedWorker requirement for multi tab sqlite driver 2025-03-28 20:56:26 +05:00
Abdullah Atta
a2131b9f37 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-03-28 20:56:26 +05:00
Ammar Ahmed
a79cbbc643 mobile: update intl 2025-03-28 16:13:54 +05:00
Ammar Ahmed
6ab8d1beba intl: update po files 2025-03-28 16:13:54 +05:00
Ammar Ahmed
890d6a49f9 mobile: focus keyboard if biometry is disabled 2025-03-28 16:13:54 +05:00
Ammar Ahmed
a532ebb2c7 mobile: restore pinned notes on reboot 2025-03-28 16:13:54 +05:00
Ammar Ahmed
29ecc3e7a5 mobile: cleanup 2025-03-28 16:13:54 +05:00
Ammar Ahmed
0082c02e17 mobile: update deps 2025-03-28 16:13:54 +05:00
Ammar Ahmed
d3ed0d5571 mobile: update locales 2025-03-28 16:13:54 +05:00
Ammar Ahmed
e1034e3a99 mobile: bump version 2025-03-28 16:13:54 +05:00
Ammar Ahmed
aa46ae6c07 mobile: fix virtualization errors 2025-03-28 16:13:54 +05:00
Ammar Ahmed
b4d1719e13 mobile: run sync when necessary 2025-03-28 16:13:54 +05:00
Ammar Ahmed
1094781774 mobile: fix slow launch 2025-03-28 16:13:54 +05:00
Ammar Ahmed
f8f82b8975 mobile: fix item counts not showing in side menu 2025-03-28 16:13:54 +05:00
Ammar Ahmed
a1c0d33bf2 mobile: fix minor bugs in tablets 2025-03-28 16:13:54 +05:00
Ammar Ahmed
2a89166724 mobile: cleanup 2025-03-28 16:13:54 +05:00
Ammar Ahmed
4887434607 mobile: fix tablet rotation 2025-03-28 16:13:54 +05:00
Ammar Ahmed
806f130832 mobile: fix tablet bugs 2025-03-28 16:13:54 +05:00
Ammar Ahmed
cb72a46c29 mobile: fix login ui on tablets 2025-03-28 16:13:54 +05:00
Ammar Ahmed
7ba56357f3 mobile: add notebooks button in notebook screen to view subnotebooks 2025-03-28 16:13:54 +05:00
Ammar Ahmed
b3718f25aa mobile: fix crash when clicking sort button in trash 2025-03-28 16:13:54 +05:00
Ammar Ahmed
7abfa8e4ce mobile: fix ui 2025-03-28 16:13:54 +05:00
Ammar Ahmed
ff02a2bcd1 mobile: fix sorting sheet in reminders 2025-03-28 16:13:54 +05:00
Ammar Ahmed
d829c97a7e mobile: do not call scroll into view on focus 2025-03-28 16:13:54 +05:00
Ammar Ahmed
0048da3090 mobile: change item positions 2025-03-28 16:13:54 +05:00
Ammar Ahmed
05e87d627a mobile: fix check mark color in dialog 2025-03-28 16:13:54 +05:00
Ammar Ahmed
796f6f14b4 mobile: fix logout button not working in user sheet 2025-03-28 16:13:54 +05:00
Ammar Ahmed
521c13dfa3 mobile: minor improvements 2025-03-28 16:13:54 +05:00
Ammar Ahmed
b2aaac01db mobile: add missing check when dragging to end 2025-03-28 16:13:54 +05:00
Ammar Ahmed
eba96d483c mobile: fix colors 2025-03-28 16:13:54 +05:00
Ammar Ahmed
8c12344123 mobile: update rspack to v1.2.7 2025-03-28 16:13:54 +05:00
Ammar Ahmed
b1edeb0f5b mobile: use re.pack v5 with rspack 2025-03-28 16:13:54 +05:00
Ammar Ahmed
788023c95d ci: update to actions/cache@v3 2025-03-28 16:13:54 +05:00
Ammar Ahmed
8cd1be5d6b ci: release app to beta track on play 2025-03-28 16:13:54 +05:00
Ammar Ahmed
7b3b0fc9fe mobile: release beta 2 2025-03-28 16:13:54 +05:00
Ammar Ahmed
f0e46def68 mobile: fix linking a note 2025-03-28 16:13:54 +05:00
Ammar Ahmed
880655e220 mobile: fix tree filtering in move notebook 2025-03-28 16:13:54 +05:00
Ammar Ahmed
1bcc5c3ba4 mobile: fix items hides behind selection bar 2025-03-28 16:13:54 +05:00
Ammar Ahmed
db6e52ce07 mobile: cleanup 2025-03-28 16:13:54 +05:00
Ammar Ahmed
2199b86f71 mobile: fix breadcrumbs 2025-03-28 16:13:54 +05:00
Ammar Ahmed
b0a7bf5c02 mobile: fix properties not opening 2025-03-28 16:13:54 +05:00
Ammar Ahmed
e233fe783e mobile: fix ui 2025-03-28 16:13:54 +05:00
Ammar Ahmed
90b67c2a1c mobile: fix toggle switch color in settings 2025-03-28 16:13:54 +05:00
Ammar Ahmed
b6506a2ab4 mobile: fix input border color 2025-03-28 16:13:54 +05:00
Ammar Ahmed
22601b4181 mobile: fix separator color 2025-03-28 16:13:54 +05:00
Ammar Ahmed
710c28f3c2 mobile: fix sidemenu colors 2025-03-28 16:13:54 +05:00
Ammar Ahmed
25d4f2666f mobile: fix ui 2025-03-28 16:13:54 +05:00
Ammar Ahmed
2fd23807a6 mobile: fix zindex 2025-03-28 16:13:54 +05:00
Ammar Ahmed
f4b3fc4f4e mobile: fix beta release getting update dialog prompt 2025-03-28 16:13:54 +05:00
Ammar Ahmed
10742aa3fa mobile: fix loading locales in release 2025-03-28 16:13:54 +05:00
Ammar Ahmed
74b70df6d7 mobile: minor ui fixups 2025-03-28 16:13:54 +05:00
Ammar Ahmed
658585cc1d mobile: minor ui fixes 2025-03-28 16:13:54 +05:00
Ammar Ahmed
af1f1510d0 ci: add beta release workflow 2025-03-28 16:13:54 +05:00
Ammar Ahmed
e74a50675f mobile: ui updates 2025-03-28 16:13:54 +05:00
Ammar Ahmed
34dc49ac4c mobile: fix back navigation bug 2025-03-28 16:13:54 +05:00
Ammar Ahmed
17e105b3c6 mobile: fix editor state not restored sometimes on app launch 2025-03-28 16:13:54 +05:00
Ammar Ahmed
f7e4ffc650 mobile: fix task list title rendered above status bar in editor 2025-03-28 16:13:54 +05:00
Ammar Ahmed
0dfd98a27b mobile: fix selection in sidebar on app launch 2025-03-28 16:13:54 +05:00
Ammar Ahmed
df90332eab mobile: fix various bugs 2025-03-28 16:13:54 +05:00
Ammar Ahmed
15db924150 mobile: refactor and fix bugs 2025-03-28 16:13:54 +05:00
Ammar Ahmed
61552ec87f mobile: improve app launch perf 2025-03-28 16:13:54 +05:00
Ammar Ahmed
ef2a4f5126 mobile: refactor some sheets into screens 2025-03-28 16:13:54 +05:00
Ammar Ahmed
47c959374c mobile: add test-id 2025-03-28 16:13:54 +05:00
Ammar Ahmed
c2f32f02a2 mobile: refactor 2025-03-28 16:13:54 +05:00
Ammar Ahmed
d16db9ad23 mobile: use custom cache key for persist store 2025-03-28 16:13:54 +05:00
Ammar Ahmed
3ccf016c65 mobile: minor refactor 2025-03-28 16:13:54 +05:00
Ammar Ahmed
5494c25aa8 mobile: refactor 2025-03-28 16:13:54 +05:00
Ammar Ahmed
b2dc460a7e mobile: refactor 2025-03-28 16:13:54 +05:00
Ammar Ahmed
6b664d9c56 mobile: fix moving and updating notebooks 2025-03-28 16:13:54 +05:00
Ammar Ahmed
076297dcd0 mobile: small ui improvements and perf fixes 2025-03-28 16:13:54 +05:00
Ammar Ahmed
956fdd4bc9 mobile: make skip login work properly 2025-03-28 16:13:54 +05:00
Ammar Ahmed
60ad9801be mobile: more fixes 2025-03-28 16:13:54 +05:00
Ammar Ahmed
4a00dc21a0 mobile: fix selected item ui 2025-03-28 16:13:54 +05:00
Ammar Ahmed
a63bd53622 mobile: fix bugs 2025-03-28 16:13:54 +05:00
Ammar Ahmed
990df2a392 mobile: fix missing delete button in trash 2025-03-28 16:13:54 +05:00
Ammar Ahmed
97979e1631 mobile: fix pro button 2025-03-28 16:13:54 +05:00
Ammar Ahmed
5e7292f04d mobile: enable testing in debug build 2025-03-28 16:13:54 +05:00
Ammar Ahmed
863d6bf465 mobile: enable debug tests 2025-03-28 16:13:54 +05:00
Ammar Ahmed
1bb25b6128 mobile: cleanup 2025-03-28 16:13:54 +05:00
Ammar Ahmed
5fe3c51c5f mobile: fix error set state in render 2025-03-28 16:13:54 +05:00
Ammar Ahmed
5a1cdf054b mobile: add pro button in side-menu 2025-03-28 16:13:54 +05:00
Ammar Ahmed
2ae2a19a6f mobile: fix sidemenu padding top 2025-03-28 16:13:54 +05:00
Ammar Ahmed
b8d7a41e4b mobile: fix minor bugs 2025-03-28 16:13:54 +05:00
Ammar Ahmed
48156b86e6 mobile: fix typo 2025-03-28 16:13:54 +05:00
Ammar Ahmed
b8b0dbbc3e mobile: make all e2e tests pass 2025-03-28 16:13:54 +05:00
Ammar Ahmed
f61ba08096 mobile: minor cleanup 2025-03-28 16:13:54 +05:00
Ammar Ahmed
7d324b7999 mobile: finalize sidebar and list revamp 2025-03-28 16:13:54 +05:00
Ammar Ahmed
fdb436adfa mobile: refactor goToPage 2025-03-28 16:13:54 +05:00
Ammar Ahmed
8fa1cb616d mobile: fix tsc errors 2025-03-28 16:13:54 +05:00
Ammar Ahmed
2c0a6eec48 mobile: ui redesign 2025-03-28 16:13:54 +05:00
Abdullah Atta
8895f13c51 web: fix tests 2025-03-28 16:09:15 +05:00
Abdullah Atta
fb6f0a0c1e web: bump version to 3.1.0-beta.4 2025-03-28 16:09:15 +05:00
Abdullah Atta
8ee3249ecb web: close expanded nav pane on navigation 2025-03-28 16:09:15 +05:00
Abdullah Atta
7fdf5ca10f web: force list pane to be visible when reveal item in list is called 2025-03-28 16:09:15 +05:00
Abdullah Atta
286050b323 web: improve item flash animation when revealing item in list
this also fixes a potential memory leak due to event listener not unsubscribing
2025-03-28 16:09:15 +05:00
Abdullah Atta
fd5af6a8eb Revert "web: fix list pane not expanding (#7758)"
This reverts commit fd9db3605d.
2025-03-28 16:09:15 +05:00
Abdullah Atta
f431ccb45c web: fix active tab background 2025-03-28 16:09:15 +05:00
Abdullah Atta
fcd3728a83 web: fix Service worker did not respond. error 2025-03-28 16:09:15 +05:00
Abdullah Atta
da9eeea741 web: fix app not starting up on firefox 2025-03-28 16:09:15 +05:00
01zulfi
54edbc3f2e web: don't remove properties pane when editor is refocused (#7780)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:09:15 +05:00
Abdullah Atta
04986b594a intl: update strings 2025-03-28 16:09:15 +05:00
Abdullah Atta
8972296445 web: replace shared worker with service worker for sqlite 2025-03-28 16:09:15 +05:00
01zulfi
3dddf995d0 web: collapse hovered navbar when item is clicked (#7771)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:09:15 +05:00
Abdullah Atta
d0197bf095 web: release v3.1.0-beta.3 2025-03-28 16:09:15 +05:00
Ammar Ahmed
6a34319455 web: cleanup 2025-03-28 16:09:15 +05:00
01zulfi
b65fcedf29 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-03-28 16:09:15 +05:00
01zulfi
9addf95c76 web: restore notebook crumbs (#7765)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:09:15 +05:00
Ammar Ahmed
55adcc906f web: bump version to 3.1.0-beta.2 for desktop and web 2025-03-28 16:09:15 +05:00
Abdullah Atta
f1f39f17da web: make editor note properties work like toc 2025-03-28 16:09:15 +05:00
Abdullah Atta
1dcb0a363c web: slightly improve add note button ui 2025-03-28 16:09:15 +05:00
Abdullah Atta
c6c6f62319 web: bump version to 3.1.0-beta.1 2025-03-28 16:09:15 +05:00
Abdullah Atta
5faf8378a2 desktop: set publish channel to beta for beta builds 2025-03-28 16:09:15 +05:00
Abdullah Atta
bcc7a6fb05 web: minor ui fixes 2025-03-28 16:09:15 +05:00
Abdullah Atta
a44650ee1a theme: fix button hover colors 2025-03-28 16:09:15 +05:00
Abdullah Atta
e734e87c14 web: make notesnook branding a bit smaller 2025-03-28 16:09:15 +05:00
Abdullah Atta
232dfad3ac web: minor ui changes and fixes 2025-03-28 16:09:15 +05:00
Abdullah Atta
f61c868eed web: fix theme not persisting 2025-03-28 16:09:15 +05:00
Abdullah Atta
8e211d65ce web: collapse sidebar on navigate if sidebar is temporarily expanded 2025-03-28 16:09:15 +05:00
Abdullah Atta
9a0d6fbbb4 desktop: explicitly deny geolocation permission to electron process 2025-03-28 16:09:15 +05:00
Abdullah Atta
9256aec1c9 web: fix scrollbar styling in sidebar 2025-03-28 16:09:15 +05:00
Abdullah Atta
2734965bce web: reset search on navigate 2025-03-28 16:09:15 +05:00
Abdullah Atta
453ccf0a89 web: fix expand sidebar button not working 2025-03-28 16:09:15 +05:00
Abdullah Atta
564e7190e8 web: always show "X" button if there is query in search input 2025-03-28 16:08:56 +05:00
Abdullah Atta
9c32fe9c2e web: bump version to 3.1.0-beta.0 2025-03-28 16:08:56 +05:00
Abdullah Atta
5a23223a85 web: use virtualized tree for rendering toc 2025-03-28 16:08:11 +05:00
Abdullah Atta
a7c8cef69c editor: fix toc level mapping 2025-03-28 16:08:11 +05:00
Abdullah Atta
fa37d6cc25 web: add support for pre-expanding tree nodes on creation 2025-03-28 16:08:11 +05:00
Abdullah Atta
c52eb4608d web: do not collapse child nodes when collapsing parent 2025-03-28 16:08:11 +05:00
Abdullah Atta
c156defd57 web: fix all tests 2025-03-28 16:08:11 +05:00
Abdullah Atta
a0b4553344 global: update ui 2025-03-28 16:08:11 +05:00
01zulfi
c3080e9446 web: fix faulty useEffect
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:08:11 +05:00
01zulfi
c020b0ae7c web: refactor props for Tags component
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:08:11 +05:00
01zulfi
7802e4a530 web: separate component for tab items in sidebar
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:08:11 +05:00
01zulfi
9978532f57 web: new sidebar ui
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:08:11 +05:00
429 changed files with 17020 additions and 16748 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.5",
"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 { 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>
);
};
@@ -141,13 +132,15 @@ export const withTheme = (Element: (props: any) => JSX.Element) => {
// 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: DefaultAppStyles.GAP_VERTICAL_SMALL - 2,
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,87 +210,36 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
);
};
Properties.present = async (item, buttons = [], isSheet) => {
Properties.present = async (item, isSheet) => {
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();
}}
actionSheetRef={ref}
item={props[0]}
buttons={props[1]}
/>
<Properties close={close} actionSheetRef={ref} item={dbItem} />
)
});
};

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,348 @@
/*
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 }: { item: Item; close: () => void }) => {
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>{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