mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-08-30 18:48:27 +02:00
Compare commits
155 Commits
fix/select
...
fix-readon
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6502ce7cc | ||
|
|
97a75d9498 | ||
|
|
950028e3b4 | ||
|
|
874726c712 | ||
|
|
0f380b9962 | ||
|
|
2ce569726c | ||
|
|
a38fe7da43 | ||
|
|
057b563608 | ||
|
|
3741e26219 | ||
|
|
86bf8f68bf | ||
|
|
e7f67d1bb9 | ||
|
|
9c28e6bb93 | ||
|
|
0f84fab810 | ||
|
|
228a8e612f | ||
|
|
175c6cdba0 | ||
|
|
d3e2fcc3ac | ||
|
|
dafc2de2b3 | ||
|
|
f9eb9a1ad9 | ||
|
|
1f5001210b | ||
|
|
3150eafb89 | ||
|
|
ad1e3f2c67 | ||
|
|
d67b78d86e | ||
|
|
25f74ff04d | ||
|
|
be7c1453fe | ||
|
|
daa60939c3 | ||
|
|
ac659b05e4 | ||
|
|
8391d51e02 | ||
|
|
ad78b3a931 | ||
|
|
e3a1fdd87d | ||
|
|
12f24db3af | ||
|
|
2af805017c | ||
|
|
97d4ca0afe | ||
|
|
8b5c246531 | ||
|
|
8f2113b155 | ||
|
|
a378bd397b | ||
|
|
a315473ea4 | ||
|
|
7dc581b9f3 | ||
|
|
5ef392ca31 | ||
|
|
846c949cd1 | ||
|
|
d88ead4609 | ||
|
|
055c109563 | ||
|
|
378a7197c2 | ||
|
|
89ee0f8d27 | ||
|
|
c9ea9b1d4e | ||
|
|
a91532839f | ||
|
|
b32f6b2460 | ||
|
|
e02970b936 | ||
|
|
1f24fd4758 | ||
|
|
5a16403a13 | ||
|
|
48bbaad1b8 | ||
|
|
520711eec9 | ||
|
|
3f82a4ebd4 | ||
|
|
4feb22fc12 | ||
|
|
4e0e8dbb66 | ||
|
|
431c4eae14 | ||
|
|
6373cbc9a4 | ||
|
|
bbf3477512 | ||
|
|
ca30ac86d7 | ||
|
|
88aecb3af2 | ||
|
|
c5a78b0293 | ||
|
|
b0bc1ec4a6 | ||
|
|
84b3892053 | ||
|
|
d985683c0f | ||
|
|
008ce9222e | ||
|
|
c360fa8c9b | ||
|
|
c1afd4692d | ||
|
|
7748cf453c | ||
|
|
34d0123351 | ||
|
|
af1cfc92c2 | ||
|
|
59e06ef938 | ||
|
|
9d12ef82c0 | ||
|
|
0a9bfd4b69 | ||
|
|
329248ebbd | ||
|
|
cd51f2f2c9 | ||
|
|
a3e7d5bd84 | ||
|
|
6a261d284f | ||
|
|
eddf9f6d04 | ||
|
|
33e0f81988 | ||
|
|
0df8f80b48 | ||
|
|
2f4590fbb6 | ||
|
|
a011857286 | ||
|
|
cc9e7e10b6 | ||
|
|
78e04bfac5 | ||
|
|
652231d5fd | ||
|
|
343920d376 | ||
|
|
1f3e7574f5 | ||
|
|
ea9b10ff23 | ||
|
|
232a347f4a | ||
|
|
00053cb99d | ||
|
|
03a2a2f9cc | ||
|
|
09c8c66841 | ||
|
|
53e4bda69d | ||
|
|
4c77c8e22c | ||
|
|
9afb4a52c2 | ||
|
|
b3d6fd7f5b | ||
|
|
245d022f58 | ||
|
|
2d226db271 | ||
|
|
9281f9a390 | ||
|
|
d30bb56e75 | ||
|
|
eb92989478 | ||
|
|
d0dcdcd337 | ||
|
|
60aa92ca03 | ||
|
|
e2bbc1425b | ||
|
|
fc01103353 | ||
|
|
22919561fe | ||
|
|
745cbc082f | ||
|
|
6671a97181 | ||
|
|
b7aaa382b1 | ||
|
|
ecfa0e2c6b | ||
|
|
58c6cce4e4 | ||
|
|
b388a550a5 | ||
|
|
f0c5f6b949 | ||
|
|
459cd70c32 | ||
|
|
ece142e8d8 | ||
|
|
5f1f308540 | ||
|
|
7437b29518 | ||
|
|
7acb0a8c0f | ||
|
|
a1a24ee865 | ||
|
|
02008ad098 | ||
|
|
0a02431f6a | ||
|
|
9291711036 | ||
|
|
f3e0fda5fa | ||
|
|
0e721a4948 | ||
|
|
e0a704d022 | ||
|
|
e36bc816ea | ||
|
|
f8a62ca437 | ||
|
|
22ecb079b0 | ||
|
|
06333cf9aa | ||
|
|
1ad199ce53 | ||
|
|
ceebda5314 | ||
|
|
e2d33381cc | ||
|
|
2417f8e233 | ||
|
|
a240b0b3d7 | ||
|
|
fab085579a | ||
|
|
a5faa4acea | ||
|
|
4014f2a5b5 | ||
|
|
fb62839dad | ||
|
|
7bf8f1cfc1 | ||
|
|
b8a727eee8 | ||
|
|
52e12de296 | ||
|
|
0bb2345ccb | ||
|
|
78e957eed4 | ||
|
|
865efaa860 | ||
|
|
2931fd0b3e | ||
|
|
faae68928b | ||
|
|
21ada0e2d2 | ||
|
|
2337b8cd85 | ||
|
|
52c8d0b86c | ||
|
|
ce98cea4e7 | ||
|
|
b66a093cc2 | ||
|
|
a3e5ae4cf5 | ||
|
|
cddd08c32d | ||
|
|
5c3ad96cbe | ||
|
|
55b441d14e | ||
|
|
f740a211ce |
100
.github/workflows/android.e2e.yml
vendored
Normal file
100
.github/workflows/android.e2e.yml
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
name: e2e-android
|
||||
on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
e2e-android:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
API_LEVEL: 34
|
||||
ARCH: x86_64
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Enable KVM
|
||||
run: |
|
||||
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
|
||||
sudo udevadm control --reload-rules
|
||||
sudo udevadm trigger --name-match=kvm
|
||||
|
||||
- name: Free Disk Space
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
tool-cache: false
|
||||
android: false
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
- name: Install node modules
|
||||
run: |
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=mobile
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
with:
|
||||
gradle-version: wrapper
|
||||
cache-read-only: false
|
||||
|
||||
- name: Use specific Java version for the builds
|
||||
uses: joschi/setup-jdk@v2
|
||||
with:
|
||||
java-version: "17"
|
||||
architecture: "x64"
|
||||
|
||||
- name: Install Detox CLI
|
||||
run: npm install detox-cli --global
|
||||
|
||||
- name: Detox build
|
||||
run: |
|
||||
yarn build:android
|
||||
ls apps/mobile/native/android/app/build/outputs/apk
|
||||
ls apps/mobile/native/android/app/build/outputs/apk/release
|
||||
|
||||
- name: Get device name
|
||||
id: device
|
||||
run: |
|
||||
AVD_NAME=$(node -p "require('./apps/mobile/native/.detoxrc.js').devices.emulator.device.avdName")
|
||||
echo "AVD_NAME=$AVD_NAME" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: AVD cache
|
||||
uses: actions/cache@v4
|
||||
id: avd-cache
|
||||
with:
|
||||
path: |
|
||||
~/.android/avd/*
|
||||
~/.android/adb*
|
||||
key: ${{ steps.device.outputs.AVD_NAME }}
|
||||
|
||||
- name: create AVD and generate snapshot for caching
|
||||
if: steps.avd-cache.outputs.cache-hit != 'true'
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ env.API_LEVEL }}
|
||||
arch: ${{ env.ARCH }}
|
||||
avd-name: ${{ steps.device.outputs.AVD_NAME }}
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
disable-animations: true
|
||||
script: echo "Generated AVD snapshot for caching."
|
||||
|
||||
- name: Detox test
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ env.API_LEVEL }}
|
||||
arch: ${{ env.ARCH }}
|
||||
avd-name: ${{ steps.device.outputs.AVD_NAME }}
|
||||
disable-animations: true
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
force-avd-creation: false
|
||||
script: yarn test:android --headless --record-logs failing --record-videos failing --take-screenshots failing
|
||||
|
||||
- name: Upload artifacts
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: detox-artifacts
|
||||
path: artifacts
|
||||
retention-days: 14
|
||||
2
.github/workflows/core.tests.yml
vendored
2
.github/workflows/core.tests.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
46
.github/workflows/desktop.publish.yml
vendored
46
.github/workflows/desktop.publish.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
@@ -84,6 +84,26 @@ jobs:
|
||||
files: ./notesnook_build_v${{ steps.app_metadata.outputs.app_version }}.zip
|
||||
prerelease: ${{ endsWith(steps.app_metadata.outputs.app_version, '-beta') }}
|
||||
|
||||
- name: Generate flatpak sources
|
||||
if: inputs.publish-github && inputs.build-linux
|
||||
run: |
|
||||
sudo apt-get install -y flatpak flatpak-builder pipx
|
||||
git clone https://github.com/flatpak/flatpak-builder-tools.git /tmp/flatpak-builder-tools
|
||||
cd /tmp/flatpak-builder-tools/node
|
||||
pipx install .
|
||||
cd -
|
||||
node scripts/generate-sources.mjs
|
||||
|
||||
- name: Upload flatpak sources
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: inputs.publish-github && inputs.build-linux
|
||||
with:
|
||||
draft: true
|
||||
name: Notesnook Desktop v${{ steps.app_metadata.outputs.app_version }}
|
||||
tag_name: v${{ steps.app_metadata.outputs.app_version }}
|
||||
files: ./generated-sources.json
|
||||
prerelease: ${{ endsWith(steps.app_metadata.outputs.app_version, '-beta') }}
|
||||
|
||||
build-macos:
|
||||
name: Build for macOS
|
||||
needs: build
|
||||
@@ -92,7 +112,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
@@ -136,6 +156,12 @@ jobs:
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=desktop
|
||||
|
||||
- name: Install sqlite-better-trigram for all arch
|
||||
run: |
|
||||
npm i --cpu arm64 sqlite-better-trigram
|
||||
npm i --cpu x64 sqlite-better-trigram
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Install provisioning profile
|
||||
run: echo "${{ secrets.MAC_PROVISIONING_PROFILE }}" | base64 --decode > embedded.provisionprofile
|
||||
working-directory: ./apps/desktop
|
||||
@@ -188,7 +214,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
@@ -212,6 +238,12 @@ jobs:
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=desktop
|
||||
|
||||
- name: Install sqlite-better-trigram for all arch
|
||||
run: |
|
||||
npm i --cpu arm64 sqlite-better-trigram
|
||||
npm i --cpu x64 sqlite-better-trigram
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Build Electron wrapper
|
||||
run: npx nx run release --project @notesnook/desktop
|
||||
working-directory: ./apps/desktop
|
||||
@@ -247,7 +279,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET Core SDK
|
||||
uses: actions/setup-dotnet@v2
|
||||
@@ -272,6 +304,12 @@ jobs:
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=desktop
|
||||
|
||||
- name: Install sqlite-better-trigram for all arch
|
||||
run: |
|
||||
npm i --cpu arm64 sqlite-better-trigram
|
||||
npm i --cpu x64 sqlite-better-trigram
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Build
|
||||
run: npx nx run release --project @notesnook/desktop
|
||||
|
||||
|
||||
233
.github/workflows/desktop.tests.yml
vendored
Normal file
233
.github/workflows/desktop.tests.yml
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
name: Test @notesnook/desktop
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
paths:
|
||||
- "app/desktop/**"
|
||||
# re-run workflow if workflow file changes
|
||||
- ".github/workflows/desktop.tests.yml"
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=web
|
||||
|
||||
- name: Setup environment
|
||||
run: |
|
||||
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Generate desktop build
|
||||
run: npx nx build:desktop @notesnook/web
|
||||
|
||||
- name: Archive build artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build
|
||||
path: apps/web/build/**/*
|
||||
|
||||
test-macos-x64:
|
||||
name: Test macOS x64
|
||||
needs: build
|
||||
runs-on: macos-13
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
- name: Download build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build
|
||||
path: ./apps/web/build
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=desktop
|
||||
|
||||
- name: Build Electron wrapper
|
||||
run: npx nx run release --project @notesnook/desktop
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Build app
|
||||
run: |
|
||||
yarn electron-builder --mac --dir --x64
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Run tests x64
|
||||
run: |
|
||||
EXECUTABLE_PATH=output/mac/Notesnook.app/Contents/MacOS/Notesnook npm run test
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: test-results-macos-x64
|
||||
path: apps/desktop/test-results
|
||||
retention-days: 5
|
||||
|
||||
test-macos:
|
||||
name: Test macOS
|
||||
needs: build
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
- name: Download build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build
|
||||
path: ./apps/web/build
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=desktop
|
||||
|
||||
- name: Build Electron wrapper
|
||||
run: npx nx run release --project @notesnook/desktop
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Build app
|
||||
run: |
|
||||
yarn electron-builder --mac --dir --arm64
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Run tests arm64
|
||||
run: |
|
||||
EXECUTABLE_PATH=output/mac-arm64/Notesnook.app/Contents/MacOS/Notesnook npm run test
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: test-results-macos
|
||||
path: apps/desktop/test-results
|
||||
retention-days: 5
|
||||
|
||||
test-linux:
|
||||
name: Test for Linux
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
- name: Download build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build
|
||||
path: ./apps/web/build
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=desktop
|
||||
|
||||
- name: Install sqlite-better-trigram for all arch
|
||||
run: |
|
||||
npm i --cpu arm64 sqlite-better-trigram
|
||||
npm i --cpu x64 sqlite-better-trigram
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Build Electron wrapper
|
||||
run: npx nx run release --project @notesnook/desktop
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Build app
|
||||
run: |
|
||||
yarn electron-builder --linux --dir --arm64 --x64
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
EXECUTABLE_PATH=output/linux-unpacked/notesnook xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" -- npm run test
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: test-results-linux
|
||||
path: apps/desktop/test-results
|
||||
retention-days: 5
|
||||
|
||||
test-windows:
|
||||
name: Test for Windows
|
||||
needs: build
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
- name: Download build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build
|
||||
path: ./apps/web/build
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=desktop
|
||||
|
||||
- name: Install sqlite-better-trigram for all arch
|
||||
run: |
|
||||
npm i --cpu arm64 sqlite-better-trigram
|
||||
npm i --cpu x64 sqlite-better-trigram
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Build Electron wrapper
|
||||
run: npx nx run release --project @notesnook/desktop
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Build app
|
||||
run: |
|
||||
npx cross-env NOTESNOOK_STAGING=true yarn electron-builder --win --dir --arm64 --x64
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
npx cross-env EXECUTABLE_PATH=output/win-unpacked/Notesnook.exe npm run test
|
||||
working-directory: ./apps/desktop
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: test-results-win
|
||||
path: apps/desktop/test-results
|
||||
retention-days: 5
|
||||
2
.github/workflows/editor.tests.yml
vendored
2
.github/workflows/editor.tests.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
4
.github/workflows/help.publish.yml
vendored
4
.github/workflows/help.publish.yml
vendored
@@ -1,6 +1,6 @@
|
||||
name: Publish Notesnook Help
|
||||
|
||||
on:
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
2
.github/workflows/ios.publish.yml
vendored
2
.github/workflows/ios.publish.yml
vendored
@@ -4,7 +4,7 @@ on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-13
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
|
||||
2
.github/workflows/theme-builder.publish.yml
vendored
2
.github/workflows/theme-builder.publish.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
2
.github/workflows/vericrypt.publish.yml
vendored
2
.github/workflows/vericrypt.publish.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
44
.github/workflows/web.benchmarks.yml
vendored
Normal file
44
.github/workflows/web.benchmarks.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: Benchmark @notesnook/web
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
paths:
|
||||
- "apps/web/**"
|
||||
# re-run workflow if workflow file changes
|
||||
- ".github/workflows/web.benchmarks.yml"
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
bench:
|
||||
name: Bench
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
- name: Install packages
|
||||
run: |
|
||||
npm ci --ignore-scripts --prefer-offline --no-audit
|
||||
npm run bootstrap -- --scope=web
|
||||
|
||||
- name: Setup environment
|
||||
run: |
|
||||
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build
|
||||
run: npm run build:web
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: npx playwright install chromium --with-deps
|
||||
working-directory: apps/web
|
||||
|
||||
- name: Run benchmarks
|
||||
id: benchmark
|
||||
run: node __bench__/app.bench.mjs
|
||||
working-directory: apps/web
|
||||
2
.github/workflows/web.publish.yml
vendored
2
.github/workflows/web.publish.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
|
||||
4
.github/workflows/web.tests.yml
vendored
4
.github/workflows/web.tests.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node-with-cache
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download build
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
53
apps/desktop/__tests__/launch.test.mjs
Normal file
53
apps/desktop/__tests__/launch.test.mjs
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
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 test from "node:test";
|
||||
import { launchApp } from "./utils.mjs";
|
||||
import assert from "assert";
|
||||
import slugify from "slugify";
|
||||
import path from "path";
|
||||
import { mkdir } from "fs/promises";
|
||||
|
||||
test("make sure app loads", async (t) => {
|
||||
const { app, page } = await launchApp();
|
||||
try {
|
||||
await page.waitForSelector("#authForm");
|
||||
|
||||
assert.ok(
|
||||
await page.getByRole("button", { name: "Create account" }).isVisible()
|
||||
);
|
||||
|
||||
await page
|
||||
.getByRole("button", { name: "Skip & go directly to the app" })
|
||||
.click();
|
||||
|
||||
await page.waitForSelector(".ProseMirror");
|
||||
} catch (e) {
|
||||
await mkdir("test-results", { recursive: true });
|
||||
await page.screenshot({
|
||||
path: path.join(
|
||||
"test-results",
|
||||
`${slugify(t.name)}-${process.platform}-${process.arch}-error.png`
|
||||
)
|
||||
});
|
||||
throw e;
|
||||
} finally {
|
||||
await app.close();
|
||||
}
|
||||
});
|
||||
@@ -17,12 +17,22 @@ 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 { motion } from "framer-motion";
|
||||
import { Flex, Box, Image, Text } from "@theme-ui/components";
|
||||
import { Input } from "@theme-ui/components";
|
||||
import { _electron as electron } from "playwright";
|
||||
|
||||
export const AnimatedFlex = motion(Flex);
|
||||
export const AnimatedBox = motion(Box);
|
||||
export const AnimatedImage = motion(Image);
|
||||
export const AnimatedText = motion(Text);
|
||||
export const AnimatedInput = motion(Input);
|
||||
const executablePath = process.env.EXECUTABLE_PATH;
|
||||
|
||||
// process.platform === "linux"
|
||||
// ? "output/linux-unpacked/Notesnook"
|
||||
// : process.platform === "darwin"
|
||||
// ? "output/mac/Notesnook.app/Contents/MacOS/Notesnook"
|
||||
// : "output/win-unpacked/Notesnook.exe";
|
||||
|
||||
export async function launchApp() {
|
||||
const app = await electron.launch({
|
||||
executablePath
|
||||
});
|
||||
|
||||
const page = await app.firstWindow();
|
||||
|
||||
return { app, page };
|
||||
}
|
||||
1552
apps/desktop/package-lock.json
generated
1552
apps/desktop/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,11 +2,25 @@
|
||||
"name": "@notesnook/desktop",
|
||||
"productName": "Notesnook",
|
||||
"description": "Your private note taking space",
|
||||
"version": "3.0.18",
|
||||
"version": "3.0.21",
|
||||
"appAppleId": "1544027013",
|
||||
"private": true,
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"main": "./dist/cjs/index.js",
|
||||
"module": "./dist/esm/index.js",
|
||||
"types": "./dist/types/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
".": {
|
||||
"require": {
|
||||
"types": "./dist/types/index.d.ts",
|
||||
"default": "./dist/cjs/index.js"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/types/index.d.ts",
|
||||
"default": "./dist/esm/index.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"homepage": "https://notesnook.com/",
|
||||
"repository": "https://github.com/streetwriters/notesnook",
|
||||
"license": "GPL-3.0-or-later",
|
||||
@@ -15,10 +29,11 @@
|
||||
"@notesnook/intl": "file:../../packages/intl",
|
||||
"@trpc/client": "10.45.2",
|
||||
"@trpc/server": "10.45.2",
|
||||
"better-sqlite3-multiple-ciphers": "11.2.1",
|
||||
"better-sqlite3-multiple-ciphers": "11.5.0",
|
||||
"electron-trpc": "0.6.1",
|
||||
"electron-updater": "^6.3.4",
|
||||
"icojs": "^0.19.4",
|
||||
"sqlite-better-trigram": "^0.0.2",
|
||||
"typed-emitter": "^2.1.0",
|
||||
"yargs": "^17.7.2",
|
||||
"zod": "^3.23.8"
|
||||
@@ -28,14 +43,17 @@
|
||||
"@types/node": "22.7.0",
|
||||
"@types/yargs": "^17.0.33",
|
||||
"chokidar": "^4.0.1",
|
||||
"electron": "^30.5.1",
|
||||
"electron-builder": "^25.1.7",
|
||||
"electron": "^31.7.4",
|
||||
"electron-builder": "^25.1.8",
|
||||
"esbuild": "^0.24.0",
|
||||
"node-abi": "^3.68.0",
|
||||
"node-gyp-build": "^4.8.2",
|
||||
"playwright": "^1.48.2",
|
||||
"prebuildify": "^6.0.1",
|
||||
"slugify": "^1.6.6",
|
||||
"tree-kill": "^1.2.2",
|
||||
"undici": "^6.19.8"
|
||||
"undici": "^6.19.8",
|
||||
"vitest": "^2.1.5"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"dmg-license": "^1.0.11"
|
||||
@@ -44,10 +62,11 @@
|
||||
"start": "node scripts/dev.mjs",
|
||||
"staging": "node scripts/build.mjs --run",
|
||||
"release": "node scripts/build.mjs",
|
||||
"build": "tsc",
|
||||
"build": "node ../../scripts/build.mjs",
|
||||
"bundle": "esbuild electron=./src/main.ts ./src/preload.ts --external:electron --external:fsevents --external:better-sqlite3-multiple-ciphers --external:sodium-native --minify --bundle --outdir=./build --platform=node --tsconfig=tsconfig.json --define:MAC_APP_STORE=false --define:RELEASE=true",
|
||||
"bundle:mas": "esbuild electron=./src/main.ts ./src/preload.ts --minify --external:electron --external:fsevents --bundle --outdir=./build --platform=node --tsconfig=tsconfig.json --define:MAC_APP_STORE=true --define:RELEASE=true",
|
||||
"postinstall": "patch-package"
|
||||
"postinstall": "patch-package",
|
||||
"test": "node --test --test-timeout 30000 --test-force-exit"
|
||||
},
|
||||
"author": {
|
||||
"name": "Streetwriters (Private) Limited",
|
||||
@@ -76,7 +95,20 @@
|
||||
"node_modules/file-uri-to-path",
|
||||
"node_modules/bindings",
|
||||
"node_modules/node-gyp-build",
|
||||
"node_modules/sqlite-better-trigram",
|
||||
"node_modules/sodium-native/prebuilds/${platform}-${arch}",
|
||||
{
|
||||
"from": "node_modules/sqlite-better-trigram-linux-${arch}",
|
||||
"to": "node_modules/sqlite-better-trigram-linux-${arch}"
|
||||
},
|
||||
{
|
||||
"from": "node_modules/sqlite-better-trigram-darwin-${arch}",
|
||||
"to": "node_modules/sqlite-better-trigram-darwin-${arch}"
|
||||
},
|
||||
{
|
||||
"from": "node_modules/sqlite-better-trigram-windows-${arch}",
|
||||
"to": "node_modules/sqlite-better-trigram-windows-${arch}"
|
||||
},
|
||||
"node_modules/sodium-native/index.js",
|
||||
"node_modules/sodium-native/package.json"
|
||||
],
|
||||
@@ -149,10 +181,12 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"signingHashAlgorithms": [
|
||||
"sha256"
|
||||
],
|
||||
"sign": "./scripts/sign.js",
|
||||
"signtoolOptions": {
|
||||
"signingHashAlgorithms": [
|
||||
"sha256"
|
||||
],
|
||||
"sign": "./scripts/sign.js"
|
||||
},
|
||||
"icon": "assets/icons/app.ico"
|
||||
},
|
||||
"portable": {
|
||||
|
||||
@@ -63,7 +63,7 @@ if (args.variant === "mas") {
|
||||
await exec(`yarn run bundle`);
|
||||
}
|
||||
|
||||
await exec(`yarn tsc`);
|
||||
await exec(`yarn run build`);
|
||||
|
||||
if (args.run) {
|
||||
await exec(`yarn electron-builder --dir --x64`);
|
||||
@@ -94,7 +94,7 @@ async function patchBetterSQLite3() {
|
||||
);
|
||||
const json = JSON.parse(await readFile(jsonPath, "utf-8"));
|
||||
|
||||
json.version = "11.2.2";
|
||||
json.version = "11.5.1";
|
||||
json.homepage = "https://github.com/thecodrr/better-sqlite3-multiple-ciphers";
|
||||
json.repository.url =
|
||||
"git://github.com/thecodrr/better-sqlite3-multiple-ciphers.git";
|
||||
|
||||
@@ -36,6 +36,8 @@ const ENV = {
|
||||
FORCE_COLOR: "false",
|
||||
COLOR: "0"
|
||||
};
|
||||
process.chdir(path.join(__dirname, ".."));
|
||||
|
||||
await onChange(true);
|
||||
|
||||
console.log("Watching...");
|
||||
@@ -53,11 +55,13 @@ async function onChange(first) {
|
||||
if (first) {
|
||||
await fs.rm("./build/", { force: true, recursive: true });
|
||||
|
||||
await exec("npm rebuild electron --verbose --foreground-scripts");
|
||||
|
||||
await exec("yarn electron-builder install-app-deps");
|
||||
}
|
||||
|
||||
await exec(`yarn run bundle`);
|
||||
execAsync(`yarn`, [`tsc`]);
|
||||
await exec(`yarn run build`);
|
||||
|
||||
if (await isBundleSame()) {
|
||||
console.log("Bundle is same. Doing nothing.");
|
||||
|
||||
@@ -46,6 +46,8 @@ export class SQLite {
|
||||
this.sqlite = require("better-sqlite3-multiple-ciphers")(
|
||||
filePath
|
||||
).unsafeMode(true);
|
||||
const betterTrigram = require("sqlite-better-trigram");
|
||||
betterTrigram.load(this.sqlite);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +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/>.
|
||||
*/
|
||||
|
||||
export * from "./constants";
|
||||
export { PATHS } from "./constants";
|
||||
export type { AppRouter } from "./api";
|
||||
export { type UpdateInfo } from "builder-util-runtime";
|
||||
export { type DesktopIntegration } from "./utils/config";
|
||||
|
||||
@@ -101,7 +101,7 @@ async function createWindow() {
|
||||
...(config.desktopSettings.nativeTitlebar
|
||||
? {}
|
||||
: {
|
||||
titleBarStyle: "hidden",
|
||||
titleBarStyle: process.platform === "win32" || process.platform === "darwin" ? "hidden" : "default",
|
||||
frame: process.platform === "win32" || process.platform === "darwin",
|
||||
titleBarOverlay: {
|
||||
height: 37,
|
||||
|
||||
@@ -19,22 +19,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* eslint-disable no-var */
|
||||
|
||||
import { ELECTRON_TRPC_CHANNEL } from "electron-trpc/main";
|
||||
import { type RendererGlobalElectronTRPC } from "electron-trpc/src/types";
|
||||
// import type { NNCrypto } from "@notesnook/crypto";
|
||||
import { ipcRenderer } from "electron";
|
||||
import { platform } from "os";
|
||||
|
||||
declare global {
|
||||
var os: () => "mas" | ReturnType<typeof platform>;
|
||||
var electronTRPC: RendererGlobalElectronTRPC;
|
||||
var electronTRPC: any;
|
||||
// var NativeNNCrypto: (new () => NNCrypto) | undefined;
|
||||
}
|
||||
|
||||
process.once("loaded", async () => {
|
||||
const electronTRPC: RendererGlobalElectronTRPC = {
|
||||
sendMessage: (operation) =>
|
||||
const electronTRPC = {
|
||||
sendMessage: (operation: any) =>
|
||||
ipcRenderer.send(ELECTRON_TRPC_CHANNEL, operation),
|
||||
onMessage: (callback) =>
|
||||
onMessage: (callback: any) =>
|
||||
ipcRenderer.on(ELECTRON_TRPC_CHANNEL, (_event, args) => callback(args))
|
||||
};
|
||||
globalThis.electronTRPC = electronTRPC;
|
||||
|
||||
@@ -57,7 +57,8 @@ function getSystemTheme() {
|
||||
nativeTheme.themeSource = oldThemeSource;
|
||||
|
||||
setTimeout(
|
||||
() => listeners.forEach((a) => nativeTheme.addListener("updated", a)),
|
||||
() =>
|
||||
listeners.forEach((a) => nativeTheme.addListener("updated", () => a())),
|
||||
1000
|
||||
);
|
||||
return currentTheme;
|
||||
@@ -72,7 +73,8 @@ function changeTheme(theme: Theme) {
|
||||
nativeTheme.themeSource = theme;
|
||||
|
||||
setTimeout(
|
||||
() => listeners.forEach((a) => nativeTheme.addListener("updated", a)),
|
||||
() =>
|
||||
listeners.forEach((a) => nativeTheme.addListener("updated", () => a())),
|
||||
1000
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/",
|
||||
"lib": ["ESNext"]
|
||||
"lib": ["ESNext"],
|
||||
"moduleResolution": "Bundler"
|
||||
},
|
||||
"include": ["src", "global.d.ts"]
|
||||
}
|
||||
|
||||
1
apps/mobile/.gitignore
vendored
1
apps/mobile/.gitignore
vendored
@@ -39,6 +39,7 @@ DerivedData
|
||||
*.xcuserstate
|
||||
*.hprof
|
||||
**/.xcode.env.local
|
||||
native/cache
|
||||
# Android/IntelliJ
|
||||
#
|
||||
rn-build-deps/
|
||||
|
||||
@@ -54,10 +54,10 @@ export async function setupDatabase(password) {
|
||||
storage: Storage,
|
||||
eventsource: Platform.OS === "ios" ? EventSource : AndroidEventSource,
|
||||
fs: filesystem,
|
||||
compressor: {
|
||||
compressor: () => ({
|
||||
compress: Gzip.deflate,
|
||||
decompress: Gzip.inflate
|
||||
},
|
||||
}),
|
||||
batchSize: 100,
|
||||
sqliteOptions: {
|
||||
dialect: (name) => ({
|
||||
|
||||
@@ -140,7 +140,7 @@ export async function downloadAttachments(attachments) {
|
||||
useAttachmentStore.getState().setDownloading({
|
||||
current: 0,
|
||||
total: 1,
|
||||
message: `${strings.savingZipFile()}... ${strings.pleaseWait()}`,
|
||||
message: strings.savingZipFile(),
|
||||
groupId
|
||||
});
|
||||
// If all goes well, zip the notesnook-attachments folder in cache.
|
||||
@@ -150,9 +150,7 @@ export async function downloadAttachments(attachments) {
|
||||
groupId,
|
||||
current: progress,
|
||||
total: 1,
|
||||
message: `${strings.savingZipFile()} (${(progress * 100).toFixed(
|
||||
1
|
||||
)}%)... ${strings.pleaseWait()}`
|
||||
message: strings.savingZipFile((progress * 100).toFixed(1))
|
||||
});
|
||||
});
|
||||
await zip(zipSourceFolder, zipOutputFile);
|
||||
@@ -246,7 +244,7 @@ export default async function downloadAttachment(
|
||||
);
|
||||
}
|
||||
|
||||
let filename = getFileNameWithExtension(
|
||||
let filename = await getFileNameWithExtension(
|
||||
attachment.filename,
|
||||
attachment.mimeType
|
||||
);
|
||||
|
||||
@@ -235,7 +235,7 @@ export const AttachmentDialog = ({
|
||||
for (let i = 0; i < filteredAttachments.placeholders.length; i++) {
|
||||
if (!getState().isWorking) {
|
||||
ToastManager.show({
|
||||
message: "Attachment recheck cancelled",
|
||||
message: strings.attachmentRecheckCancelled(),
|
||||
type: "info",
|
||||
context: isSheet ? "local" : "global"
|
||||
});
|
||||
@@ -322,7 +322,7 @@ export const AttachmentDialog = ({
|
||||
) : null}
|
||||
{!isSheet ? (
|
||||
<Header
|
||||
title="Manage attachments"
|
||||
title={strings.manageAttachments()}
|
||||
renderedInRoute="SettingsGroup"
|
||||
canGoBack
|
||||
headerRightButtons={[
|
||||
@@ -330,23 +330,23 @@ export const AttachmentDialog = ({
|
||||
onPress() {
|
||||
onCheck();
|
||||
},
|
||||
title: "Recheck all"
|
||||
title: strings.recheckAll()
|
||||
},
|
||||
{
|
||||
onPress() {
|
||||
if (!attachments) return;
|
||||
presentDialog({
|
||||
title: `Download ${attachments.placeholders.length} attachments`,
|
||||
paragraph:
|
||||
"Are you sure you want to download all attachments?",
|
||||
positiveText: "Download",
|
||||
title: strings.doActions.download.attachment(
|
||||
attachments.placeholders.length
|
||||
),
|
||||
positiveText: strings.network.download(),
|
||||
positivePress: async () => {
|
||||
downloadAttachments(await attachments.ids());
|
||||
},
|
||||
negativeText: "Cancel"
|
||||
negativeText: strings.cancel()
|
||||
});
|
||||
},
|
||||
title: "Download all"
|
||||
title: strings.downloadAllAttachments()
|
||||
}
|
||||
]}
|
||||
/>
|
||||
@@ -388,15 +388,14 @@ export const AttachmentDialog = ({
|
||||
onPress={() => {
|
||||
if (!attachments) return;
|
||||
presentDialog({
|
||||
title: `Download ${attachments.placeholders.length} attachments`,
|
||||
paragraph:
|
||||
"Are you sure you want to download all attachments?",
|
||||
context: "local",
|
||||
positiveText: "Download",
|
||||
title: strings.doActions.download.attachment(
|
||||
attachments.placeholders.length
|
||||
),
|
||||
positiveText: strings.network.download(),
|
||||
positivePress: async () => {
|
||||
downloadAttachments(await attachments.ids());
|
||||
},
|
||||
negativeText: "Cancel"
|
||||
negativeText: strings.cancel()
|
||||
});
|
||||
}}
|
||||
size={SIZE.lg}
|
||||
@@ -457,14 +456,16 @@ export const AttachmentDialog = ({
|
||||
<Paragraph>
|
||||
{rechecker.isWorking
|
||||
? note
|
||||
? `Checking ${rechecker.filter.toLowerCase()} note attachments`
|
||||
: `Checking ${rechecker.filter.toLowerCase()} attachments`
|
||||
: "Attachments recheck complete"}
|
||||
? strings.checkingNoteAttachments()
|
||||
: strings.checkingAllAttachments()
|
||||
: strings.attachmentRecheckComplete()}
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
{`${rechecker.isWorking ? "Please wait... " : ""}Passed: ${
|
||||
{`${
|
||||
rechecker.isWorking ? `${strings.pleaseWait()} ` : ""
|
||||
}${strings.passed()}: ${
|
||||
rechecker.passed
|
||||
}, Failed: ${rechecker.failed}`}
|
||||
}, ${strings.failed()}: ${rechecker.failed}`}
|
||||
</Paragraph>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -17,8 +17,11 @@ 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 { ScrollView } from "react-native-actions-sheet";
|
||||
import { db } from "../../common/database/index";
|
||||
import useTimer from "../../hooks/use-timer";
|
||||
import {
|
||||
@@ -26,19 +29,14 @@ import {
|
||||
presentSheet,
|
||||
ToastManager
|
||||
} from "../../services/event-manager";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import { eCloseSheet } from "../../utils/events";
|
||||
import { SIZE } 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 Seperator from "../ui/seperator";
|
||||
import Heading from "../ui/typography/heading";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
import { useCallback } from "react";
|
||||
import { ScrollView } from "react-native-actions-sheet";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
|
||||
const { colors } = useThemeColors();
|
||||
@@ -164,7 +162,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
|
||||
textAlign: "center"
|
||||
}}
|
||||
>
|
||||
{strings["2faCodeHelpText"][currentMethod.method]() ||
|
||||
{strings["2faCodeHelpText"][currentMethod.method]?.() ||
|
||||
strings.select2faCodeHelpText()}
|
||||
</Paragraph>
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
View
|
||||
} from "react-native";
|
||||
import { Image as ImageType } from "react-native-image-crop-picker";
|
||||
import { useThemeColors } from "../../../../../../packages/theme/dist";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import { presentSheet } from "../../../services/event-manager";
|
||||
import { SIZE } from "../../../utils/size";
|
||||
import { Button } from "../../ui/button";
|
||||
|
||||
@@ -164,7 +164,7 @@ export default function Progress() {
|
||||
/>
|
||||
</View>
|
||||
|
||||
{data?.canHideProgress ? null : (
|
||||
{!data?.canHideProgress ? null : (
|
||||
<Button
|
||||
title={cancelCallback.current ? "Cancel" : "Hide"}
|
||||
type="secondaryAccented"
|
||||
|
||||
@@ -311,8 +311,10 @@ export class VaultDialog extends Component {
|
||||
loading: true
|
||||
});
|
||||
try {
|
||||
let verified = await db.user.verifyPassword(this.password);
|
||||
if (!(await db.user.getUser())) verified = true;
|
||||
let verified = true;
|
||||
if (await db.user.getUser()) {
|
||||
verified = await db.user.verifyPassword(this.password);
|
||||
}
|
||||
if (verified) {
|
||||
let noteIds = [];
|
||||
if (this.state.deleteAll) {
|
||||
@@ -320,20 +322,21 @@ export class VaultDialog extends Component {
|
||||
const relations = await db.relations.from(vault, "note").get();
|
||||
noteIds = relations.map((item) => item.toId);
|
||||
}
|
||||
|
||||
await db.vault.delete(this.state.deleteAll);
|
||||
|
||||
noteIds.forEach((id) => {
|
||||
eSendEvent(
|
||||
eUpdateNoteInEditor,
|
||||
{
|
||||
id: id,
|
||||
deleted: true
|
||||
},
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
if (this.state.deleteAll) {
|
||||
noteIds.forEach((id) => {
|
||||
eSendEvent(
|
||||
eUpdateNoteInEditor,
|
||||
{
|
||||
id: id,
|
||||
deleted: true
|
||||
},
|
||||
true
|
||||
);
|
||||
});
|
||||
}
|
||||
console.log("VAULT UPDATED EVENT");
|
||||
eSendEvent("vaultUpdated");
|
||||
this.setState({
|
||||
loading: false
|
||||
@@ -517,7 +520,6 @@ export class VaultDialog extends Component {
|
||||
});
|
||||
this.close();
|
||||
} else {
|
||||
eSendEvent("vaultUpdated");
|
||||
ToastManager.show({
|
||||
heading: strings.vaultCreated(),
|
||||
type: "success",
|
||||
@@ -525,6 +527,7 @@ export class VaultDialog extends Component {
|
||||
});
|
||||
this.close();
|
||||
}
|
||||
eSendEvent("vaultUpdated");
|
||||
}
|
||||
|
||||
_permanantUnlock() {
|
||||
|
||||
@@ -33,7 +33,6 @@ import { eScrollEvent } from "../../utils/events";
|
||||
import { LeftMenus } from "./left-menus";
|
||||
import { RightMenus } from "./right-menus";
|
||||
import { Title } from "./title";
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
|
||||
type HeaderRightButton = {
|
||||
title: string;
|
||||
|
||||
@@ -17,30 +17,23 @@ 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 {
|
||||
Linking,
|
||||
ScrollView,
|
||||
TouchableOpacity,
|
||||
useWindowDimensions,
|
||||
View
|
||||
} from "react-native";
|
||||
import { Linking, ScrollView, useWindowDimensions, View } from "react-native";
|
||||
import { SwiperFlatList } from "react-native-swiper-flatlist";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import { getElevationStyle } from "../../utils/elevation";
|
||||
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 { Button } from "../ui/button";
|
||||
import Heading from "../ui/typography/heading";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
import Navigation from "../../services/navigation";
|
||||
import { eOpenLoginDialog } from "../../utils/events";
|
||||
import { AuthMode } from "../auth";
|
||||
import { eSendEvent } from "../../services/event-manager";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
const Intro = ({ navigation }) => {
|
||||
const { colors } = useThemeColors();
|
||||
@@ -90,7 +83,7 @@ const Intro = ({ navigation }) => {
|
||||
>
|
||||
{item.headings?.map((heading) => (
|
||||
<Heading
|
||||
key={heading}
|
||||
key={heading()}
|
||||
style={{
|
||||
marginBottom: 5
|
||||
}}
|
||||
|
||||
@@ -41,7 +41,7 @@ export const openNotebook = (item: Notebook | BaseTrashItem<Notebook>) => {
|
||||
positiveText: strings.restore(),
|
||||
negativeText: strings.delete(),
|
||||
positivePress: async () => {
|
||||
await db.trash.restore(item.id);
|
||||
if ((await db.trash.restore(item.id)) === false) return;
|
||||
Navigation.queueRoutesForUpdate();
|
||||
useSelectionStore.getState().setSelectionMode(undefined);
|
||||
ToastManager.show({
|
||||
|
||||
@@ -34,12 +34,13 @@ import {
|
||||
Reminder,
|
||||
Tag,
|
||||
TrashItem,
|
||||
VirtualizedGrouping
|
||||
VirtualizedGrouping,
|
||||
getSortValue
|
||||
} from "@notesnook/core";
|
||||
import { getSortValue } from "@notesnook/core";
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import { db } from "../../common/database";
|
||||
import { useIsCompactModeEnabled } from "../../hooks/use-is-compact-mode-enabled";
|
||||
import { eSendEvent } from "../../services/event-manager";
|
||||
import { RouteName } from "../../stores/use-navigation-store";
|
||||
import { eOpenJumpToDialog } from "../../utils/events";
|
||||
@@ -48,7 +49,6 @@ import { NoteWrapper } from "../list-items/note/wrapper";
|
||||
import { NotebookWrapper } from "../list-items/notebook/wrapper";
|
||||
import ReminderItem from "../list-items/reminder";
|
||||
import TagItem from "../list-items/tag";
|
||||
import { useIsCompactModeEnabled } from "../../hooks/use-is-compact-mode-enabled";
|
||||
|
||||
type ListItemWrapperProps<TItem = Item> = {
|
||||
group?: GroupingKey;
|
||||
|
||||
@@ -48,7 +48,7 @@ export default function NotePreview({ session, content, note }) {
|
||||
|
||||
async function restore() {
|
||||
if (note && note.type === "trash") {
|
||||
await db.trash.restore(note.id);
|
||||
if ((await db.trash.restore(note.id)) === false) return;
|
||||
Navigation.queueRoutesForUpdate();
|
||||
useSelectionStore.getState().setSelectionMode(false);
|
||||
ToastManager.show({
|
||||
|
||||
@@ -137,14 +137,13 @@ export const Items = ({ item, buttons, close }) => {
|
||||
style={{
|
||||
alignSelf: "flex-start",
|
||||
paddingHorizontal: 0,
|
||||
width: topBarItemWidth
|
||||
flex: 1
|
||||
}}
|
||||
>
|
||||
<View
|
||||
onPress={item.func}
|
||||
style={{
|
||||
height: topBarItemWidth,
|
||||
width: topBarItemWidth,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
textAlign: "center",
|
||||
@@ -169,7 +168,7 @@ export const Items = ({ item, buttons, close }) => {
|
||||
|
||||
<Paragraph
|
||||
textBreakStrategy="simple"
|
||||
size={SIZE.xxs + 1}
|
||||
size={SIZE.xxs}
|
||||
style={{ textAlign: "center" }}
|
||||
>
|
||||
{item.title}
|
||||
@@ -242,7 +241,7 @@ export const Items = ({ item, buttons, close }) => {
|
||||
showsHorizontalScrollIndicator={false}
|
||||
contentContainerStyle={{
|
||||
paddingRight: 25,
|
||||
gap: 5
|
||||
gap: 15
|
||||
}}
|
||||
>
|
||||
{topBarItems.map(renderTopBarItem)}
|
||||
|
||||
@@ -90,7 +90,7 @@ export const SelectionHeader = React.memo(
|
||||
|
||||
const restoreItem = async () => {
|
||||
if (!selectedItemsList.length) return;
|
||||
await db.trash.restore(...selectedItemsList);
|
||||
if ((await db.trash.restore(...selectedItemsList)) === false) return;
|
||||
Navigation.queueRoutesForUpdate();
|
||||
|
||||
clearSelection();
|
||||
@@ -102,9 +102,8 @@ export const SelectionHeader = React.memo(
|
||||
|
||||
const deleteItem = async () => {
|
||||
presentDialog({
|
||||
title: strings.deleteItems(type as string, selectedItemsList.length),
|
||||
paragraph: strings.deleteItemsConfirmation(
|
||||
type as string,
|
||||
title: strings.doActions.delete[type](selectedItemsList.length),
|
||||
paragraph: strings.actionConfirmations.delete[type](
|
||||
selectedItemsList.length
|
||||
),
|
||||
positiveText: strings.delete(),
|
||||
|
||||
@@ -81,7 +81,7 @@ export const AddNotebookSheet = ({
|
||||
id: notebook?.id
|
||||
});
|
||||
|
||||
if (parentNotebook) {
|
||||
if (parentNotebook && id) {
|
||||
await db.relations.add(parentNotebook, {
|
||||
type: "notebook",
|
||||
id: id
|
||||
@@ -94,7 +94,8 @@ export const AddNotebookSheet = ({
|
||||
useNotebookStore.getState().refresh();
|
||||
|
||||
const parent =
|
||||
parentNotebook?.id || (await getParentNotebookId(notebook?.id || id));
|
||||
parentNotebook?.id ||
|
||||
(await getParentNotebookId(notebook?.id || (id as string)));
|
||||
|
||||
eSendEvent(eOnNotebookUpdated, parent);
|
||||
if (notebook) {
|
||||
@@ -104,7 +105,7 @@ export const AddNotebookSheet = ({
|
||||
});
|
||||
}
|
||||
|
||||
if (!notebook && showMoveNotesOnComplete) {
|
||||
if (!notebook && showMoveNotesOnComplete && id) {
|
||||
MoveNotes.present(await db.notebooks.notebook(id));
|
||||
} else {
|
||||
close?.(true);
|
||||
|
||||
@@ -18,6 +18,7 @@ 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,
|
||||
@@ -49,13 +50,11 @@ 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";
|
||||
import { AddNotebookSheet } from "../add-notebook";
|
||||
import Input from "../../ui/input";
|
||||
import { presentDialog } from "../../dialog/functions";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
async function updateInitialSelectionState(items: string[]) {
|
||||
const relations = await db.relations
|
||||
|
||||
@@ -171,7 +171,7 @@ const ExportNotesSheet = ({
|
||||
>
|
||||
<DialogHeader
|
||||
icon="export"
|
||||
title={`${strings.export()} ${strings.notes(ids.length)}`}
|
||||
title={strings.exportNotes(ids.length)}
|
||||
/>
|
||||
</View>
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ const NewFeature = ({
|
||||
version
|
||||
}: {
|
||||
features: FeatureType[];
|
||||
version?: string | null;
|
||||
version?: string;
|
||||
}) => {
|
||||
const { colors } = useThemeColors();
|
||||
|
||||
@@ -57,7 +57,7 @@ const NewFeature = ({
|
||||
}}
|
||||
>
|
||||
<Heading color={colors.secondary.heading} size={SIZE.md}>
|
||||
{!version ? `${strings.newVersion()} ` : `v${version} `}Highlights 🎉
|
||||
{strings.newVersionHighlights(version)}
|
||||
</Heading>
|
||||
|
||||
<Seperator />
|
||||
@@ -122,7 +122,7 @@ NewFeature.present = () => {
|
||||
component: (
|
||||
<NewFeature
|
||||
features={features}
|
||||
version={SettingsService.getProperty("version")}
|
||||
version={SettingsService.getProperty("version") || undefined}
|
||||
/>
|
||||
),
|
||||
disableClosing: true
|
||||
|
||||
@@ -206,7 +206,7 @@ export const NotebookSheet = () => {
|
||||
backgroundInteractionEnabled
|
||||
gestureEnabled
|
||||
>
|
||||
<View
|
||||
{/* <View
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: 24 + normalize(50),
|
||||
@@ -214,17 +214,11 @@ export const NotebookSheet = () => {
|
||||
}}
|
||||
>
|
||||
<Pressable
|
||||
testID={notesnook.buttons.add}
|
||||
testID="add-notebook-button"
|
||||
type="secondary"
|
||||
onPress={() => {
|
||||
if (!notebook) return;
|
||||
AddNotebookSheet.present(
|
||||
undefined,
|
||||
notebook,
|
||||
undefined,
|
||||
undefined,
|
||||
false
|
||||
);
|
||||
|
||||
}}
|
||||
style={{
|
||||
borderRadius: 100
|
||||
@@ -245,7 +239,7 @@ export const NotebookSheet = () => {
|
||||
/>
|
||||
</View>
|
||||
</Pressable>
|
||||
</View>
|
||||
</View> */}
|
||||
|
||||
<View
|
||||
style={{
|
||||
@@ -404,6 +398,27 @@ export const NotebookSheet = () => {
|
||||
height: 40 * fontScale
|
||||
}}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
testID="add-notebook-button"
|
||||
name="notebook-plus"
|
||||
onPress={() => {
|
||||
if (!notebook) return;
|
||||
AddNotebookSheet.present(
|
||||
undefined,
|
||||
notebook,
|
||||
undefined,
|
||||
undefined,
|
||||
false
|
||||
);
|
||||
}}
|
||||
color={colors.primary.icon}
|
||||
size={22}
|
||||
style={{
|
||||
width: 40 * fontScale,
|
||||
height: 40 * fontScale
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
|
||||
@@ -36,7 +36,7 @@ import Seperator from "../../ui/seperator";
|
||||
import Heading from "../../ui/typography/heading";
|
||||
import Paragraph from "../../ui/typography/paragraph";
|
||||
import { requestInAppReview } from "../../../services/app-review";
|
||||
import { Note } from "@notesnook/core";
|
||||
import { hosts, Note } from "@notesnook/core";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
const PublishNoteSheet = ({
|
||||
@@ -54,7 +54,7 @@ const PublishNoteSheet = ({
|
||||
const [note, setNote] = useState<Note | undefined>(item);
|
||||
const [publishing, setPublishing] = useState(false);
|
||||
const publishUrl =
|
||||
note && `https://monogr.ph/${db.monographs.monograph(note?.id)}`;
|
||||
note && `${hosts.MONOGRAPH_HOST}/${db.monographs.monograph(note?.id)}`;
|
||||
const isPublished = note && db.monographs.isPublished(note?.id);
|
||||
const pwdInput = useRef(null);
|
||||
const passwordValue = useRef<string>();
|
||||
@@ -121,8 +121,8 @@ const PublishNoteSheet = ({
|
||||
}}
|
||||
>
|
||||
<DialogHeader
|
||||
title={`${strings.publish()} ${strings.note()}`}
|
||||
paragraph={strings.publishDesc()}
|
||||
title={strings.publishNote()}
|
||||
paragraph={strings.publishNoteDesc()}
|
||||
/>
|
||||
|
||||
{publishing ? (
|
||||
|
||||
@@ -16,8 +16,8 @@ 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 { VirtualizedGrouping } from "@notesnook/core";
|
||||
import { Item, ItemReference } from "@notesnook/core";
|
||||
import { Item, ItemReference, VirtualizedGrouping } from "@notesnook/core";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { RefObject, useEffect, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
@@ -37,8 +37,6 @@ import SheetProvider from "../../sheet-provider";
|
||||
import { Button } from "../../ui/button";
|
||||
import { PressableProps } from "../../ui/pressable";
|
||||
import Paragraph from "../../ui/typography/paragraph";
|
||||
import { isStringLiteralOrJsxExpression } from "typescript";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
type RelationsListProps = {
|
||||
actionSheetRef: RefObject<ActionSheetRef>;
|
||||
@@ -125,7 +123,9 @@ export const RelationsList = ({
|
||||
// width="100%"
|
||||
type="inverted"
|
||||
icon="plus"
|
||||
title={strings.addItem(referenceType)}
|
||||
title={strings.addItem(
|
||||
referenceType as "notebook" | "tag" | "reminder" | "note"
|
||||
)}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
|
||||
@@ -154,7 +154,9 @@ export const Toast = ({ context = "global" }) => {
|
||||
>
|
||||
<Icon
|
||||
name={
|
||||
toastOptions.type === "success"
|
||||
toastOptions.icon
|
||||
? toastOptions.icon
|
||||
: toastOptions.type === "success"
|
||||
? "check"
|
||||
: toastOptions.type === "info"
|
||||
? "information"
|
||||
|
||||
@@ -70,7 +70,6 @@ interface InputProps extends TextInputProps {
|
||||
};
|
||||
buttons?: React.ReactNode;
|
||||
onBlurInput?: () => void;
|
||||
onPress?: () => void;
|
||||
height?: number;
|
||||
fontSize?: number;
|
||||
onFocusInput?: () => void;
|
||||
|
||||
@@ -17,6 +17,9 @@ 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 } from "@notesnook/core";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React from "react";
|
||||
import { Linking, View } from "react-native";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
@@ -26,26 +29,22 @@ import {
|
||||
SUPPORT_SVG,
|
||||
WELCOME_SVG
|
||||
} from "../../assets/images/assets";
|
||||
import { ThemeStore } from "../../stores/use-theme-store";
|
||||
import useRotator from "../../hooks/use-rotator";
|
||||
import { eSendEvent } from "../../services/event-manager";
|
||||
import { getContainerBorder } from "../../utils/colors";
|
||||
import { getElevationStyle } from "../../utils/elevation";
|
||||
import { eOpenAddNotebookDialog } from "../../utils/events";
|
||||
import { SIZE } from "../../utils/size";
|
||||
import useRotator from "../../hooks/use-rotator";
|
||||
import { AccentColorPicker } from "../../screens/settings/appearance";
|
||||
import { Button } from "../ui/button";
|
||||
import { SvgView } from "../ui/svg";
|
||||
import { PinItem } from "../side-menu/pinned-section";
|
||||
import { Button } from "../ui/button";
|
||||
import Seperator from "../ui/seperator";
|
||||
import { SvgView } from "../ui/svg";
|
||||
import Heading from "../ui/typography/heading";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import { getContainerBorder } from "../../utils/colors";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
export type TStep = {
|
||||
text?: string;
|
||||
walkthroughItem: (colors: ThemeStore["colors"]) => React.ReactNode;
|
||||
walkthroughItem: (colors: any) => React.ReactNode;
|
||||
title?: string;
|
||||
button?: {
|
||||
type: "next" | "done";
|
||||
@@ -62,18 +61,18 @@ const NotebookWelcome = () => {
|
||||
const { colors } = useThemeColors();
|
||||
const data = useRotator([
|
||||
{
|
||||
title: "Work and office",
|
||||
description: "Everything related to my job",
|
||||
title: strings.workAndOffice(),
|
||||
description: strings.workAndOfficeDesc(),
|
||||
count: 2
|
||||
},
|
||||
{
|
||||
title: "School work",
|
||||
description: "I don't like doing this but I have to.",
|
||||
title: strings.schoolWork(),
|
||||
description: strings.schoolWorkDesc(),
|
||||
count: 5
|
||||
},
|
||||
{
|
||||
title: "Recipes",
|
||||
description: "I love cooking and collecting recipes",
|
||||
title: strings.recipes(),
|
||||
description: strings.recipesDesc(),
|
||||
count: 10
|
||||
}
|
||||
]);
|
||||
@@ -122,17 +121,17 @@ const notebooks: { id: string; steps: TStep[] } = {
|
||||
id: "notebooks",
|
||||
steps: [
|
||||
{
|
||||
title: "Notebooks",
|
||||
text: "Boost your productivity with Notebooks and organize your notes.",
|
||||
title: strings.notebooks(),
|
||||
text: strings.boostProductivityNotebook(),
|
||||
walkthroughItem: () => <NotebookWelcome />,
|
||||
button: {
|
||||
type: "next",
|
||||
title: "Next"
|
||||
title: strings.next()
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Notebook > Notes",
|
||||
text: "Every Notebook can have notes and sub notebooks.",
|
||||
title: strings.notebookNotes(),
|
||||
text: strings.notebookNotesDesc(),
|
||||
walkthroughItem: (colors: any) => (
|
||||
<View
|
||||
style={{
|
||||
@@ -154,9 +153,9 @@ const notebooks: { id: string; steps: TStep[] } = {
|
||||
}}
|
||||
>
|
||||
<Heading size={SIZE.md} color={colors.primary.heading}>
|
||||
Work and office
|
||||
{strings.workAndOffice()}
|
||||
</Heading>
|
||||
<Paragraph>Everything related to my job in one place.</Paragraph>
|
||||
<Paragraph>{strings.workAndOfficeDesc()}</Paragraph>
|
||||
|
||||
<Paragraph
|
||||
style={{
|
||||
@@ -165,7 +164,7 @@ const notebooks: { id: string; steps: TStep[] } = {
|
||||
size={SIZE.xs}
|
||||
color={colors.secondary.paragraph}
|
||||
>
|
||||
Notebook - 2 notes
|
||||
{strings.notes(2)}
|
||||
</Paragraph>
|
||||
</View>
|
||||
<View
|
||||
@@ -184,7 +183,7 @@ const notebooks: { id: string; steps: TStep[] } = {
|
||||
size={SIZE.sm}
|
||||
name="bookmark"
|
||||
/>{" "}
|
||||
Tasks
|
||||
{strings.tasks()}
|
||||
</Paragraph>
|
||||
</View>
|
||||
<View
|
||||
@@ -200,7 +199,7 @@ const notebooks: { id: string; steps: TStep[] } = {
|
||||
>
|
||||
<Paragraph size={SIZE.xs}>
|
||||
<Icon color={colors.primary.icon} size={SIZE.sm} name="note" />{" "}
|
||||
February 2022 Week 2
|
||||
{strings.taskAValue()}
|
||||
</Paragraph>
|
||||
</View>
|
||||
<View
|
||||
@@ -216,7 +215,7 @@ const notebooks: { id: string; steps: TStep[] } = {
|
||||
>
|
||||
<Paragraph size={SIZE.xs}>
|
||||
<Icon color={colors.primary.icon} size={SIZE.sm} name="note" />{" "}
|
||||
February 2022 Week 1
|
||||
{strings.taskBValue()}
|
||||
</Paragraph>
|
||||
</View>
|
||||
<View
|
||||
@@ -235,19 +234,19 @@ const notebooks: { id: string; steps: TStep[] } = {
|
||||
size={SIZE.sm}
|
||||
name="bookmark"
|
||||
/>{" "}
|
||||
Meetings
|
||||
{strings.meetings()}
|
||||
</Paragraph>
|
||||
</View>
|
||||
</View>
|
||||
),
|
||||
button: {
|
||||
type: "next",
|
||||
title: "Next"
|
||||
title: strings.next()
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Easy access",
|
||||
text: "You can create shortcuts of frequently accessed notebooks in the side menu",
|
||||
title: strings.easyAccess(),
|
||||
text: strings.easyAccessDesc(),
|
||||
walkthroughItem: () => (
|
||||
<View
|
||||
style={{
|
||||
@@ -256,29 +255,31 @@ const notebooks: { id: string; steps: TStep[] } = {
|
||||
}}
|
||||
>
|
||||
<PinItem
|
||||
index={0}
|
||||
placeholder={true}
|
||||
item={{
|
||||
title: "Tasks",
|
||||
type: "topic"
|
||||
}}
|
||||
isPlaceholder={true}
|
||||
item={
|
||||
{
|
||||
title: strings.tasks(),
|
||||
type: "notebook"
|
||||
} as Notebook
|
||||
}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
|
||||
<PinItem
|
||||
index={1}
|
||||
placeholder={true}
|
||||
item={{
|
||||
title: "Work and office",
|
||||
type: "notebook"
|
||||
}}
|
||||
isPlaceholder={true}
|
||||
item={
|
||||
{
|
||||
title: strings.workAndOffice(),
|
||||
type: "notebook"
|
||||
} as Notebook
|
||||
}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
</View>
|
||||
),
|
||||
button: {
|
||||
type: "done",
|
||||
title: "Add your first notebook",
|
||||
title: strings.addFirstNotebook(),
|
||||
action: () => {
|
||||
eSendEvent(eOpenAddNotebookDialog);
|
||||
}
|
||||
@@ -287,67 +288,32 @@ const notebooks: { id: string; steps: TStep[] } = {
|
||||
]
|
||||
};
|
||||
|
||||
const ChooseTheme = () => {
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
alignItems: "center",
|
||||
marginTop: 20
|
||||
}}
|
||||
>
|
||||
<Heading>Make yourself at home</Heading>
|
||||
|
||||
<Paragraph
|
||||
style={{
|
||||
textAlign: "center",
|
||||
alignSelf: "center",
|
||||
maxWidth: "80%"
|
||||
}}
|
||||
size={SIZE.md}
|
||||
>
|
||||
Pick a theme of your choice
|
||||
</Paragraph>
|
||||
<Seperator />
|
||||
<AccentColorPicker />
|
||||
<Seperator />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const trialstarted: { id: string; steps: TStep[] } = {
|
||||
id: "trialstarted",
|
||||
steps: [
|
||||
{
|
||||
title: "Your trial is activated",
|
||||
text: "You can use all premium features for free for the next 14 days",
|
||||
title: strings.trialStarted(),
|
||||
text: strings.trialStartedDesc(),
|
||||
walkthroughItem: (colors) => (
|
||||
<SvgView src={LAUNCH_ROCKET(colors.primary.paragraph)} />
|
||||
),
|
||||
button: {
|
||||
type: "next",
|
||||
title: "Next"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
walkthroughItem: () => <ChooseTheme />,
|
||||
button: {
|
||||
type: "next",
|
||||
title: "Next"
|
||||
title: strings.next()
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Join the cause",
|
||||
text: "Meet other privacy-minded people and talk to us directly about your concerns, issues and suggestions.",
|
||||
title: strings.joinTheCause(),
|
||||
text: strings.meetPrivacyMinded(),
|
||||
walkthroughItem: (colors) => (
|
||||
<SvgView src={COMMUNITY_SVG(colors.primary.paragraph)} />
|
||||
),
|
||||
button: {
|
||||
type: "done",
|
||||
title: "Continue"
|
||||
title: strings.continue()
|
||||
},
|
||||
actionButton: {
|
||||
text: "Join Discord Community",
|
||||
text: strings.joinDiscord(),
|
||||
action: () => {
|
||||
Linking.openURL("https://discord.gg/zQBK97EE22").catch(console.log);
|
||||
}
|
||||
@@ -360,14 +326,14 @@ const emailconfirmed: { id: string; steps: TStep[] } = {
|
||||
id: "emailconfirmed",
|
||||
steps: [
|
||||
{
|
||||
title: "Email confirmed",
|
||||
text: "Your email was confirmed successfully. Thank you for choosing end-to-end encrypted note taking.",
|
||||
title: strings.emailConfirmed(),
|
||||
text: strings.emailNotConfirmedDesc(),
|
||||
walkthroughItem: (colors) => (
|
||||
<SvgView src={WELCOME_SVG(colors.primary.paragraph)} />
|
||||
),
|
||||
button: {
|
||||
type: "done",
|
||||
title: "Continue"
|
||||
title: strings.continue()
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -382,15 +348,14 @@ const Support = () => {
|
||||
}}
|
||||
>
|
||||
<SvgView src={SUPPORT_SVG()} />
|
||||
<Heading>Get Priority Support</Heading>
|
||||
<Heading>{strings.prioritySupport()}</Heading>
|
||||
<Paragraph
|
||||
style={{
|
||||
textAlign: "center"
|
||||
}}
|
||||
size={SIZE.md}
|
||||
>
|
||||
You can reach out to us via multiple channels if you face an issue or
|
||||
want to just talk.
|
||||
{strings.weAreAlwaysListening()}
|
||||
</Paragraph>
|
||||
<Seperator />
|
||||
|
||||
@@ -405,7 +370,7 @@ const Support = () => {
|
||||
}}
|
||||
icon="discord"
|
||||
type="secondary"
|
||||
title="Join our community on Discord"
|
||||
title={strings.joinDiscord()}
|
||||
/>
|
||||
|
||||
<Button
|
||||
@@ -419,7 +384,7 @@ const Support = () => {
|
||||
}}
|
||||
icon="telegram"
|
||||
type="secondary"
|
||||
title="Join our Telegram group"
|
||||
title={strings.joinTelegram()}
|
||||
/>
|
||||
<Button
|
||||
style={{
|
||||
@@ -429,7 +394,7 @@ const Support = () => {
|
||||
}}
|
||||
icon="bug"
|
||||
type="secondary"
|
||||
title="Submit an issue from Settings"
|
||||
title={strings.reportAnIssue()}
|
||||
/>
|
||||
<Button
|
||||
style={{
|
||||
@@ -439,7 +404,7 @@ const Support = () => {
|
||||
}}
|
||||
icon="mail"
|
||||
type="secondary"
|
||||
title="Email us at support@streetwriters.co"
|
||||
title={strings.emailSupport()}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
@@ -449,21 +414,21 @@ const prouser: { id: string; steps: TStep[] } = {
|
||||
id: "prouser",
|
||||
steps: [
|
||||
{
|
||||
title: "Welcome to Notesnook Pro",
|
||||
text: "Thank you for reaffirming our idea that privacy comes first",
|
||||
title: strings.welcomeToNotesnookPro(),
|
||||
text: strings.thankYouPrivacy(),
|
||||
walkthroughItem: (colors) => (
|
||||
<SvgView src={LAUNCH_ROCKET(colors.primary.paragraph)} />
|
||||
),
|
||||
button: {
|
||||
type: "next",
|
||||
title: "Next"
|
||||
title: strings.next()
|
||||
}
|
||||
},
|
||||
{
|
||||
walkthroughItem: () => <Support />,
|
||||
button: {
|
||||
type: "done",
|
||||
title: "Continue"
|
||||
title: strings.continue()
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -17,7 +17,6 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* eslint-disable no-inner-declarations */
|
||||
import { VAULT_ERRORS } from "@notesnook/core";
|
||||
import {
|
||||
Color,
|
||||
ItemReference,
|
||||
@@ -25,8 +24,11 @@ import {
|
||||
Notebook,
|
||||
Reminder,
|
||||
Tag,
|
||||
TrashItem
|
||||
TrashItem,
|
||||
VAULT_ERRORS,
|
||||
createInternalLink
|
||||
} from "@notesnook/core";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { DisplayedNotification } from "@notifee/react-native";
|
||||
import Clipboard from "@react-native-clipboard/clipboard";
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
@@ -39,8 +41,10 @@ import NoteHistory from "../components/note-history";
|
||||
import { AddNotebookSheet } from "../components/sheets/add-notebook";
|
||||
import MoveNoteSheet from "../components/sheets/add-to";
|
||||
import ExportNotesSheet from "../components/sheets/export-notes";
|
||||
import { MoveNotebookSheet } from "../components/sheets/move-notebook";
|
||||
import { MoveNotes } from "../components/sheets/move-notes/movenote";
|
||||
import PublishNoteSheet from "../components/sheets/publish-note";
|
||||
import { ReferencesList } from "../components/sheets/references";
|
||||
import { RelationsList } from "../components/sheets/relations-list/index";
|
||||
import ReminderSheet from "../components/sheets/reminder";
|
||||
import { useSideBarDraggingStore } from "../components/side-menu/dragging-store";
|
||||
@@ -60,15 +64,10 @@ import { useRelationStore } from "../stores/use-relation-store";
|
||||
import { useSelectionStore } from "../stores/use-selection-store";
|
||||
import { useTagStore } from "../stores/use-tag-store";
|
||||
import { useUserStore } from "../stores/use-user-store";
|
||||
import Errors from "../utils/errors";
|
||||
import { eOpenLoginDialog, eUpdateNoteInEditor } from "../utils/events";
|
||||
import { deleteItems } from "../utils/functions";
|
||||
import { convertNoteToText } from "../utils/note-to-text";
|
||||
import { sleep } from "../utils/time";
|
||||
import { ReferencesList } from "../components/sheets/references";
|
||||
import { createInternalLink } from "@notesnook/core";
|
||||
import { MoveNotebookSheet } from "../components/sheets/move-notebook";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
export const useActions = ({
|
||||
close,
|
||||
@@ -141,7 +140,7 @@ export const useActions = ({
|
||||
async function restoreTrashItem() {
|
||||
if (!checkItemSynced()) return;
|
||||
close();
|
||||
await db.trash.restore(item.id);
|
||||
if ((await db.trash.restore(item.id)) === false) return;
|
||||
Navigation.queueRoutesForUpdate();
|
||||
const type = item.type === "trash" ? item.itemType : item.type;
|
||||
ToastManager.show({
|
||||
@@ -255,8 +254,8 @@ export const useActions = ({
|
||||
item.type === "color"
|
||||
) {
|
||||
presentDialog({
|
||||
title: strings.deleteItem(item.type),
|
||||
paragraph: strings.deleteItemConfirmation(item.type),
|
||||
title: strings.doActions.delete[item.type](1),
|
||||
paragraph: strings.actionConfirmations.delete[item.type](1),
|
||||
positivePress: async () => {
|
||||
if (item.type === "reminder") {
|
||||
await db.reminders.remove(item.id);
|
||||
@@ -304,8 +303,8 @@ export const useActions = ({
|
||||
close();
|
||||
await sleep(300);
|
||||
presentDialog({
|
||||
title: strings.delete(),
|
||||
paragraph: strings.deleteItemsConfirmation(item.itemType, 1),
|
||||
title: strings.doActions.delete[item.itemType](1),
|
||||
paragraph: strings.actionConfirmations.delete[item.itemType](1),
|
||||
positiveText: strings.delete(),
|
||||
negativeText: strings.cancel(),
|
||||
positivePress: async () => {
|
||||
@@ -314,7 +313,10 @@ export const useActions = ({
|
||||
Navigation.queueRoutesForUpdate();
|
||||
useSelectionStore.getState().setSelectionMode(undefined);
|
||||
ToastManager.show({
|
||||
heading: strings.itemDeleted(1, item.itemType),
|
||||
heading:
|
||||
strings.actions.deleted[
|
||||
item.itemType as keyof typeof strings.actions.deleted
|
||||
](1),
|
||||
type: "success",
|
||||
context: "local"
|
||||
});
|
||||
@@ -955,7 +957,11 @@ export const useActions = ({
|
||||
id: "trash",
|
||||
title:
|
||||
item.type !== "notebook" && item.type !== "note"
|
||||
? strings.doAction(item.type, 1, "delete")
|
||||
? strings.doActions.delete[
|
||||
item.type === "trash"
|
||||
? item.itemType
|
||||
: (item.type as keyof typeof strings.doActions.delete)
|
||||
](1)
|
||||
: strings.moveToTrash(),
|
||||
icon: "delete-outline",
|
||||
type: "error",
|
||||
|
||||
@@ -93,6 +93,7 @@ import { sleep } from "../utils/time";
|
||||
import { NotesnookModule } from "../utils/notesnook-module";
|
||||
import { changeSystemBarColors } from "../stores/use-theme-store";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { endProgress, startProgress } from "../components/dialogs/progress";
|
||||
|
||||
const onCheckSyncStatus = async (type: SyncStatusEvent) => {
|
||||
const { disableSync, disableAutoSync } = SettingsService.get();
|
||||
@@ -577,6 +578,27 @@ export const useAppEvents = () => {
|
||||
EV.subscribe(EVENTS.uploadCanceled, (data) => {
|
||||
useAttachmentStore.getState().setUploading(data);
|
||||
}),
|
||||
EV.subscribe(EVENTS.migrationStarted, (name) => {
|
||||
if (
|
||||
name !== "notesnook" ||
|
||||
!SettingsService.getProperty("introCompleted")
|
||||
)
|
||||
return;
|
||||
startProgress({
|
||||
title: "Migrating Data",
|
||||
paragraph: "Please wait while we migrate your data",
|
||||
canHideProgress: false,
|
||||
fillBackground: true
|
||||
});
|
||||
}),
|
||||
EV.subscribe(EVENTS.migrationFinished, (name) => {
|
||||
if (
|
||||
name !== "notesnook" ||
|
||||
!SettingsService.getProperty("introCompleted")
|
||||
)
|
||||
return;
|
||||
endProgress();
|
||||
}),
|
||||
EV.subscribe(EVENTS.vaultLocked, async () => {
|
||||
// Lock all notes in all tabs...
|
||||
for (const tab of useTabStore.getState().tabs) {
|
||||
|
||||
@@ -18,11 +18,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useEffect } from "react";
|
||||
import { db } from "../common/database";
|
||||
import BiometricService from "../services/biometrics";
|
||||
import { eSubscribeEvent, eUnSubscribeEvent } from "../services/event-manager";
|
||||
import { db } from "../common/database";
|
||||
|
||||
const VaultStatusCache = {
|
||||
const VaultStatusDefaults = {
|
||||
exists: false,
|
||||
biometryEnrolled: false,
|
||||
isBiometryAvailable: false
|
||||
@@ -35,18 +35,12 @@ export type VaultStatusType = {
|
||||
};
|
||||
|
||||
export const useVaultStatus = () => {
|
||||
const [vaultStatus, setVaultStatus] = React.useState(VaultStatusCache);
|
||||
const [vaultStatus, setVaultStatus] = React.useState(VaultStatusDefaults);
|
||||
|
||||
const checkVaultStatus = useCallback(() => {
|
||||
db.vault?.exists().then(async (exists) => {
|
||||
const available = await BiometricService.isBiometryAvailable();
|
||||
const fingerprint = await BiometricService.hasInternetCredentials();
|
||||
if (
|
||||
VaultStatusCache.exists === exists &&
|
||||
VaultStatusCache.biometryEnrolled === fingerprint &&
|
||||
VaultStatusCache.isBiometryAvailable === available
|
||||
)
|
||||
return;
|
||||
setVaultStatus({
|
||||
exists: exists,
|
||||
biometryEnrolled: fingerprint,
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
"katex": "0.16.2",
|
||||
"@readme/data-urls": "3.0.0",
|
||||
"react-native-wheel-color-picker": "^1.3.1",
|
||||
"tinycolor2": "1.6.0",
|
||||
"@azure/core-asynciterator-polyfill": "^1.0.2",
|
||||
"@tanstack/react-query": "^4.36.1",
|
||||
"@trpc/client": "10.45.2",
|
||||
|
||||
@@ -146,15 +146,16 @@ const Editor = React.memo(
|
||||
onRenderProcessGone={onError}
|
||||
nestedScrollEnabled
|
||||
onError={onError}
|
||||
injectedJavaScriptBeforeContentLoaded={`
|
||||
globalThis.LINGUI_LOCALE = "${i18n.locale}";
|
||||
globalThis.LINGUI_LOCALE_DATA = ${JSON.stringify({
|
||||
[i18n.locale]: i18n.messages
|
||||
})};
|
||||
globalThis.__DEV__ = ${__DEV__}
|
||||
globalThis.readonly=${readonly};
|
||||
globalThis.noToolbar=${noToolbar};
|
||||
globalThis.noHeader=${noHeader};
|
||||
injectedJavaScript={`
|
||||
globalThis.__DEV__ = ${__DEV__}
|
||||
globalThis.readonly=${readonly};
|
||||
globalThis.noToolbar=${noToolbar};
|
||||
globalThis.noHeader=${noHeader};
|
||||
globalThis.LINGUI_LOCALE = "${i18n.locale}";
|
||||
globalThis.LINGUI_LOCALE_DATA = ${JSON.stringify({
|
||||
[i18n.locale]: i18n.messages
|
||||
})};
|
||||
globalThis.loadApp();
|
||||
`}
|
||||
useSharedProcessPool={false}
|
||||
javaScriptEnabled={true}
|
||||
|
||||
@@ -34,6 +34,7 @@ import { EditorEvents } from "./tiptap/utils";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||
import { db } from "../../common/database";
|
||||
import { i18n } from "@lingui/core";
|
||||
|
||||
const onShouldStartLoadWithRequest = (request: ShouldStartLoadRequest) => {
|
||||
if (request.url.includes("https")) {
|
||||
@@ -143,10 +144,17 @@ export function ReadonlyEditor(props: {
|
||||
ref={editorRef}
|
||||
key={"readonly-editor:" + props.editorId}
|
||||
nestedScrollEnabled
|
||||
injectedJavaScriptBeforeContentLoaded={`globalThis.readonlyEditor=true;`}
|
||||
injectedJavaScript="globalThis.readonlyEditor=true;"
|
||||
injectedJavaScript={`
|
||||
globalThis.__DEV__ = ${__DEV__}
|
||||
globalThis.readonlyEditor=true;
|
||||
globalThis.LINGUI_LOCALE = "${i18n.locale}";
|
||||
globalThis.LINGUI_LOCALE_DATA = ${JSON.stringify({
|
||||
[i18n.locale]: i18n.messages
|
||||
})};
|
||||
globalThis.loadApp();`}
|
||||
useSharedProcessPool={false}
|
||||
javaScriptEnabled={true}
|
||||
webviewDebuggingEnabled={__DEV__}
|
||||
focusable={true}
|
||||
setSupportMultipleWindows={false}
|
||||
overScrollMode="never"
|
||||
|
||||
@@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
import { ItemReference } from "@notesnook/core";
|
||||
import type { Attachment } from "@notesnook/editor";
|
||||
import { getDefaultPresets } from "@notesnook/editor/dist/toolbar/tool-definitions";
|
||||
import { getDefaultPresets } from "@notesnook/editor/dist/cjs/toolbar/tool-definitions";
|
||||
import Clipboard from "@react-native-clipboard/clipboard";
|
||||
import React, { useCallback, useEffect, useRef } from "react";
|
||||
import {
|
||||
|
||||
@@ -78,7 +78,7 @@ export const Home = ({ navigation, route }: NavigationProps<"Notes">) => {
|
||||
placeholder={{
|
||||
title: route.name?.toLowerCase(),
|
||||
paragraph: strings.notesEmpty(),
|
||||
button: strings.newNote(),
|
||||
button: strings.createNewNote(),
|
||||
action: openEditor,
|
||||
loading: strings.loadingNotes()
|
||||
}}
|
||||
|
||||
@@ -76,7 +76,7 @@ export const Search = ({ route, navigation }: NavigationProps<"Search">) => {
|
||||
await results.item(0);
|
||||
setResults(results);
|
||||
if (results.placeholders?.length === 0) {
|
||||
setSearchStatus(`${strings.noResultsFound(query)}`);
|
||||
setSearchStatus(strings.noResultsFound(query));
|
||||
} else {
|
||||
setSearchStatus(undefined);
|
||||
}
|
||||
@@ -125,10 +125,8 @@ export const Search = ({ route, navigation }: NavigationProps<"Search">) => {
|
||||
loading={loading}
|
||||
placeholder={{
|
||||
title: route.name,
|
||||
paragraph:
|
||||
searchStatus ||
|
||||
`${strings.typeAKeywordToSearchIn(route.params?.title)}`,
|
||||
loading: `${strings.searchingFor(currentQuery.current as string)}...`
|
||||
paragraph: searchStatus || strings.searchInRoute(route.params?.title),
|
||||
loading: strings.searchingFor(currentQuery.current as string)
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -17,18 +17,18 @@ 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 { Icons } from "@notesnook/editor/dist/toolbar/icons";
|
||||
import { Icons } from "@notesnook/editor/dist/cjs/toolbar/icons";
|
||||
import { ToolbarGroupDefinition } from "@notesnook/editor";
|
||||
import {
|
||||
getAllTools,
|
||||
getDefaultPresets
|
||||
} from "@notesnook/editor/dist/toolbar/tool-definitions";
|
||||
} from "@notesnook/editor/dist/cjs/toolbar/tool-definitions";
|
||||
import { ToolId } from "@notesnook/editor";
|
||||
|
||||
export const tools = getAllTools();
|
||||
export const tools = getAllTools() as any;
|
||||
export const presets: { [name: string]: ToolbarGroupDefinition[] } = {
|
||||
default: getDefaultPresets().default,
|
||||
minimal: getDefaultPresets().minimal,
|
||||
default: getDefaultPresets().default as any,
|
||||
minimal: getDefaultPresets().minimal as any,
|
||||
custom: []
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { DATE_FORMATS, TIME_FORMATS } from "@notesnook/core";
|
||||
import { getFontById, getFonts } from "@notesnook/editor/dist/utils/font";
|
||||
import { getFontById, getFonts } from "@notesnook/editor/dist/cjs/utils/font";
|
||||
import dayjs from "dayjs";
|
||||
import { createSettingsPicker } from ".";
|
||||
import { db } from "../../../common/database";
|
||||
|
||||
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { formatBytes, getFormattedDate } from "@notesnook/common";
|
||||
import { LegacyBackupFile } from "@notesnook/core";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { ActivityIndicator, FlatList, Platform, View } from "react-native";
|
||||
@@ -46,7 +47,6 @@ import SettingsService from "../../../services/settings";
|
||||
import { refreshAllStores } from "../../../stores/create-db-collection-store";
|
||||
import { useUserStore } from "../../../stores/use-user-store";
|
||||
import { SIZE } from "../../../utils/size";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
type PasswordOrKey = { password?: string; encryptionKey?: string };
|
||||
|
||||
@@ -153,7 +153,7 @@ const restoreBackup = async (options: {
|
||||
if (path === ".nnbackup" || path === "attachments") continue;
|
||||
|
||||
updateProgress({
|
||||
progress: `${strings.restoringBackup()}... (${count++}/${
|
||||
progress: `${strings.restoringBackup()} (${count++}/${
|
||||
extractedBackupFiles.length
|
||||
})`
|
||||
});
|
||||
@@ -242,7 +242,7 @@ const restoreBackup = async (options: {
|
||||
|
||||
await db.transaction(async () => {
|
||||
updateProgress({
|
||||
progress: strings.restoringBackup() + "..."
|
||||
progress: strings.restoringBackup()
|
||||
});
|
||||
await db.backup.import(backup, {
|
||||
encryptionKey,
|
||||
@@ -533,12 +533,11 @@ const BackupItem = ({
|
||||
}}
|
||||
onPress={() => {
|
||||
presentDialog({
|
||||
title: `Restore ${itemName}`,
|
||||
paragraph: `Are you sure you want to restore this backup?`,
|
||||
positiveText: "Restore",
|
||||
negativeText: "Cancel",
|
||||
title: `${strings.restore()} ${itemName}`,
|
||||
paragraph: strings.restoreBackupConfirm(),
|
||||
positiveText: strings.restore(),
|
||||
negativeText: strings.cancel(),
|
||||
positivePress: async () => {
|
||||
console.log("file path", (item as ScopedStorage.FileType).uri);
|
||||
restoreBackup({
|
||||
uri:
|
||||
Platform.OS === "android"
|
||||
|
||||
@@ -32,7 +32,12 @@ import SettingsService from "../../services/settings";
|
||||
import { HostId, HostIds } from "../../stores/use-setting-store";
|
||||
import { useUserStore } from "../../stores/use-user-store";
|
||||
|
||||
export const ServerIds = ["notesnook-sync", "auth", "sse"] as const;
|
||||
export const ServerIds = [
|
||||
"notesnook-sync",
|
||||
"auth",
|
||||
"sse",
|
||||
"monograph"
|
||||
] as const;
|
||||
export type ServerId = (typeof ServerIds)[number];
|
||||
type Server = {
|
||||
id: ServerId;
|
||||
@@ -40,6 +45,7 @@ type Server = {
|
||||
title: string;
|
||||
example: string;
|
||||
description: string;
|
||||
versionEndpoint: string;
|
||||
};
|
||||
type VersionResponse = {
|
||||
version: number;
|
||||
@@ -52,21 +58,32 @@ const SERVERS: Server[] = [
|
||||
host: "API_HOST",
|
||||
title: strings.syncServer(),
|
||||
example: "http://localhost:4326",
|
||||
description: strings.syncServerDesc()
|
||||
description: strings.syncServerDesc(),
|
||||
versionEndpoint: "/version"
|
||||
},
|
||||
{
|
||||
id: "auth",
|
||||
host: "AUTH_HOST",
|
||||
title: strings.authServer(),
|
||||
example: "http://localhost:5326",
|
||||
description: strings.authServerDesc()
|
||||
description: strings.authServerDesc(),
|
||||
versionEndpoint: "/version"
|
||||
},
|
||||
{
|
||||
id: "sse",
|
||||
host: "SSE_HOST",
|
||||
title: strings.sseServer(),
|
||||
example: "http://localhost:7326",
|
||||
description: strings.sseServerDesc()
|
||||
description: strings.sseServerDesc(),
|
||||
versionEndpoint: "/version"
|
||||
},
|
||||
{
|
||||
id: "monograph",
|
||||
host: "MONOGRAPH_HOST",
|
||||
title: strings.monographServer(),
|
||||
example: "http://localhost:6326",
|
||||
description: strings.monographServerDesc(),
|
||||
versionEndpoint: "/api/version"
|
||||
}
|
||||
];
|
||||
export function ServersConfiguration() {
|
||||
@@ -135,28 +152,31 @@ export function ServersConfiguration() {
|
||||
type="secondary"
|
||||
width="100%"
|
||||
onPress={async () => {
|
||||
setError(undefined);
|
||||
try {
|
||||
for (const host of HostIds) {
|
||||
const url = urls[host];
|
||||
const server = SERVERS.find((s) => s.host === host)!;
|
||||
if (!server) throw new Error(strings.serverNotFound(host));
|
||||
if (!url) throw new Error(strings.allServerUrlsRequired());
|
||||
const version = await fetch(`${url}/version`)
|
||||
const version = await fetch(`${url}${server.versionEndpoint}`)
|
||||
.then((r) => r.json() as Promise<VersionResponse>)
|
||||
.catch(() => undefined);
|
||||
if (!version)
|
||||
throw new Error(
|
||||
`${strings.couldNotConnectTo()} ${server.title}.`
|
||||
`${strings.couldNotConnectTo(server.title)}`
|
||||
);
|
||||
if (version.id !== server.id)
|
||||
throw new Error(
|
||||
`${strings.incorrectServerUrl(url)} ${server.title}.`
|
||||
`${strings.incorrectServerUrl(url, server.title)}.`
|
||||
);
|
||||
if (!isServerCompatible(version.version)) {
|
||||
throw new Error(strings.serverVersionMismatch());
|
||||
throw new Error(
|
||||
strings.serverVersionMismatch(server.title, url)
|
||||
);
|
||||
}
|
||||
}
|
||||
setSuccess(true);
|
||||
setError(undefined);
|
||||
} catch (e) {
|
||||
setError((e as Error).message);
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ import { useDragState } from "./editor/state";
|
||||
import { verifyUser, verifyUserWithApplock } from "./functions";
|
||||
import { SettingSection } from "./types";
|
||||
import { getTimeLeft } from "./user-section";
|
||||
import Clipboard from "@react-native-clipboard/clipboard";
|
||||
|
||||
type User = any;
|
||||
|
||||
@@ -339,21 +340,19 @@ export const settingsGroups: SettingSection[] = [
|
||||
presentDialog({
|
||||
title: strings.clearCacheConfirm(),
|
||||
paragraph: strings.clearCacheConfirmDesc(),
|
||||
positiveText: "Clear",
|
||||
positiveText: strings.clear(),
|
||||
positivePress: async () => {
|
||||
filesystem.clearCache();
|
||||
ToastManager.show({
|
||||
heading: "Cache cleared",
|
||||
message: "All cached attachments have been removed",
|
||||
heading: strings.cacheCleared(),
|
||||
message: strings.cacheClearedDesc(),
|
||||
type: "success"
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
description(current) {
|
||||
return `${strings.clearCacheDesc()}. Current cache size: ${
|
||||
current as number
|
||||
}`;
|
||||
return strings.clearCacheDesc(current as number);
|
||||
},
|
||||
useHook: () => {
|
||||
const [cacheSize, setCacheSize] = React.useState(0);
|
||||
@@ -380,7 +379,7 @@ export const settingsGroups: SettingSection[] = [
|
||||
presentDialog({
|
||||
title: strings.logout(),
|
||||
paragraph: strings.logoutConfirmation(),
|
||||
positiveText: "Logout",
|
||||
positiveText: strings.logout(),
|
||||
check: {
|
||||
info: strings.backupDataBeforeLogout(),
|
||||
defaultValue: true
|
||||
@@ -444,7 +443,7 @@ export const settingsGroups: SettingSection[] = [
|
||||
}
|
||||
|
||||
updateProgress({
|
||||
progress: `${strings.loggingOut()}... ${strings.pleaseWait()}`
|
||||
progress: strings.loggingOut()
|
||||
});
|
||||
|
||||
await db.user?.logout();
|
||||
@@ -804,8 +803,8 @@ export const settingsGroups: SettingSection[] = [
|
||||
{
|
||||
id: "servers",
|
||||
type: "screen",
|
||||
name: "Servers",
|
||||
description: "Configure server URLs for Notesnook",
|
||||
name: strings.servers(),
|
||||
description: strings.serversConfigurationDesc(),
|
||||
icon: "server",
|
||||
component: "server-config"
|
||||
}
|
||||
@@ -1385,7 +1384,15 @@ export const settingsGroups: SettingSection[] = [
|
||||
name: strings.emailSupport(),
|
||||
icon: "mail",
|
||||
modifer: () => {
|
||||
Linking.openURL("mailto:support@streetwriters.co");
|
||||
Clipboard.setString("support@streetwriters.co");
|
||||
ToastManager.show({
|
||||
heading: strings.emailCopied(),
|
||||
type: "success",
|
||||
icon: "content-copy"
|
||||
});
|
||||
setTimeout(() => {
|
||||
Linking.openURL("mailto:support@streetwriters.co");
|
||||
}, 1000);
|
||||
},
|
||||
description: strings.emailSupportDesc()
|
||||
},
|
||||
|
||||
@@ -17,8 +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 { strings } from "@notesnook/intl";
|
||||
import React from "react";
|
||||
import { Linking, Platform, View } from "react-native";
|
||||
import Config from "react-native-config";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { usePricing } from "../../hooks/use-pricing";
|
||||
import {
|
||||
@@ -28,14 +30,9 @@ import {
|
||||
} from "../../services/event-manager";
|
||||
import PremiumService from "../../services/premium";
|
||||
import { useUserStore } from "../../stores/use-user-store";
|
||||
import {
|
||||
SUBSCRIPTION_PROVIDER,
|
||||
SUBSCRIPTION_STATUS
|
||||
} from "../../utils/constants";
|
||||
import { SUBSCRIPTION_STATUS } from "../../utils/constants";
|
||||
import { eOpenPremiumDialog } from "../../utils/events";
|
||||
import { SIZE } from "../../utils/size";
|
||||
import Config from "react-native-config";
|
||||
import { strings } from "@notesnook/intl";
|
||||
export const Subscription = () => {
|
||||
const user = useUserStore((state) => state.user);
|
||||
const monthlyPlan = usePricing("monthly");
|
||||
|
||||
@@ -148,28 +148,31 @@ export const ToastManager = {
|
||||
type = "error",
|
||||
context = "global",
|
||||
func,
|
||||
actionText
|
||||
actionText,
|
||||
icon,
|
||||
duration = 3000
|
||||
}: ToastOptions) => {
|
||||
if (Config.isTesting) return;
|
||||
eSendEvent(eShowToast, {
|
||||
heading: heading,
|
||||
message: message,
|
||||
type: type,
|
||||
context: context,
|
||||
duration: 3000,
|
||||
func: func,
|
||||
actionText: actionText
|
||||
heading,
|
||||
message,
|
||||
type,
|
||||
context,
|
||||
func,
|
||||
actionText,
|
||||
icon,
|
||||
duration
|
||||
});
|
||||
},
|
||||
hide: () => eSendEvent(eHideToast),
|
||||
error: (e: Error, title?: string, context?: any, duration = 5000) => {
|
||||
error: (e: Error, title?: string, context?: any, duration = 6000) => {
|
||||
ToastManager.show({
|
||||
heading: title,
|
||||
message: e?.message || "",
|
||||
type: "error",
|
||||
context: context || "global",
|
||||
actionText: "Copy logs",
|
||||
duration: 6000,
|
||||
duration: duration,
|
||||
func: () => {
|
||||
Clipboard.setString(e?.stack || "");
|
||||
ToastManager.show({
|
||||
|
||||
@@ -25,7 +25,12 @@ import { FileType } from "react-native-scoped-storage";
|
||||
import create, { State } from "zustand";
|
||||
import { ThemeDark, ThemeLight, ThemeDefinition } from "@notesnook/theme";
|
||||
import { Reminder } from "@notesnook/core";
|
||||
export const HostIds = ["API_HOST", "AUTH_HOST", "SSE_HOST"] as const;
|
||||
export const HostIds = [
|
||||
"API_HOST",
|
||||
"AUTH_HOST",
|
||||
"SSE_HOST",
|
||||
"MONOGRAPH_HOST"
|
||||
] as const;
|
||||
export type HostId = (typeof HostIds)[number];
|
||||
|
||||
export type Settings = {
|
||||
|
||||
@@ -33,11 +33,9 @@ import { strings } from "@notesnook/intl";
|
||||
function confirmDeleteAllNotes(items, type, context) {
|
||||
return new Promise((resolve) => {
|
||||
presentDialog({
|
||||
title: `Delete ${
|
||||
items.length > 1 ? `${items.length} ${type}s` : `${type}`
|
||||
}?`,
|
||||
positiveText: "Delete",
|
||||
negativeText: "Cancel",
|
||||
title: strings.doActions.delete[type](items.length),
|
||||
positiveText: strings.delete(),
|
||||
negativeText: strings.cancel(),
|
||||
positivePress: (_inputValue, value) => {
|
||||
setTimeout(() => {
|
||||
resolve({ delete: true, deleteNotes: value });
|
||||
@@ -114,10 +112,10 @@ export const deleteItems = async (items, type, context) => {
|
||||
}
|
||||
} else if (type === "tag") {
|
||||
presentDialog({
|
||||
title: strings.deleteTags(ids.length),
|
||||
title: strings.doActions.delete.tag(ids.length),
|
||||
positiveText: strings.delete(),
|
||||
negativeText: strings.cancel(),
|
||||
paragraph: strings.deleteTagsConfirm(),
|
||||
paragraph: strings.actionConfirmations.delete.tag(2),
|
||||
positivePress: async () => {
|
||||
await db.tags.remove(...ids);
|
||||
useTagStore.getState().refresh();
|
||||
@@ -130,12 +128,12 @@ export const deleteItems = async (items, type, context) => {
|
||||
|
||||
let deletedIds = [...ids];
|
||||
if (type === "notebook" || type === "note") {
|
||||
let message = strings.movedToTrash(type, ids.length);
|
||||
let message = strings.actions.movedToTrash[type](ids.length);
|
||||
ToastManager.show({
|
||||
heading: message,
|
||||
type: "success",
|
||||
func: async () => {
|
||||
await db.trash.restore(...deletedIds);
|
||||
if ((await db.trash.restore(...deletedIds)) === false) return;
|
||||
Navigation.queueRoutesForUpdate();
|
||||
useMenuStore.getState().setMenuPins();
|
||||
useMenuStore.getState().setColorNotes();
|
||||
|
||||
@@ -34,7 +34,6 @@ export async function unlockVault({
|
||||
paragraph: string;
|
||||
}) {
|
||||
if (unlockPromise) {
|
||||
console.log("Unlocking.... waiting for unlock promise");
|
||||
return unlockPromise;
|
||||
}
|
||||
unlockPromise = new Promise(async (resolve) => {
|
||||
@@ -58,10 +57,10 @@ export async function unlockVault({
|
||||
context: context,
|
||||
input: true,
|
||||
secureTextEntry: true,
|
||||
positiveText: "Unlock",
|
||||
positiveText: strings.unlock(),
|
||||
title: title,
|
||||
paragraph: paragraph,
|
||||
inputPlaceholder: "Enter password",
|
||||
inputPlaceholder: strings.enterPassword(),
|
||||
positivePress: async (value) => {
|
||||
const unlocked = await db.vault.unlock(value);
|
||||
if (!unlocked) {
|
||||
|
||||
29
apps/mobile/e2e/globalSetup.ts
Normal file
29
apps/mobile/e2e/globalSetup.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { execSync } from "child_process";
|
||||
|
||||
import { pathExists, ensureDir } from "fs-extra";
|
||||
|
||||
import { resolveConfig } from "detox/internals";
|
||||
import { globalSetup } from "detox/runners/jest";
|
||||
|
||||
export default async function customGlobalSetup() {
|
||||
const config = await resolveConfig();
|
||||
if (config.device.type === "android.emulator") {
|
||||
await downloadTestButlerAPK();
|
||||
}
|
||||
|
||||
await globalSetup();
|
||||
}
|
||||
|
||||
async function downloadTestButlerAPK() {
|
||||
const version = "2.2.1";
|
||||
const artifactUrl = `https://repo1.maven.org/maven2/com/linkedin/testbutler/test-butler-app/${version}/test-butler-app-${version}.apk`;
|
||||
const filePath = `cache/test-butler-app.apk`;
|
||||
|
||||
await ensureDir("cache");
|
||||
if (!(await pathExists(filePath))) {
|
||||
console.log(`\nDownloading Test-Butler APK v${version}...`);
|
||||
execSync(`curl -f -o ${filePath} ${artifactUrl}`);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = customGlobalSetup;
|
||||
@@ -1,20 +1,21 @@
|
||||
/** @type {import('@jest/types').Config.InitialOptions} */
|
||||
module.exports = {
|
||||
rootDir: "..",
|
||||
testMatch: ["<rootDir>/e2e/**/*.e2e.js"],
|
||||
testTimeout: 120000,
|
||||
maxWorkers: 1,
|
||||
setupFilesAfterEnv: ["./e2e/setup.js"],
|
||||
globalSetup: "detox/runners/jest/globalSetup",
|
||||
testTimeout: 120000,
|
||||
globalSetup: "./e2e/globalSetup.ts",
|
||||
globalTeardown: "detox/runners/jest/globalTeardown",
|
||||
reporters: ["detox/runners/jest/reporter"],
|
||||
setupFilesAfterEnv: ["./e2e/setup.ts"],
|
||||
testEnvironment: "detox/runners/jest/testEnvironment",
|
||||
verbose: true,
|
||||
reporters: ["detox/runners/jest/reporter"],
|
||||
testRunner: "jest-circus/runner",
|
||||
testMatch: ["<rootDir>/e2e/**/*.e2e.(js|ts)"],
|
||||
transform: {
|
||||
"^.+\\.(js|jsx|ts|tsx)$": [
|
||||
"\\.tsx?$": "ts-jest",
|
||||
"^.+\\.(js|jsx)$": [
|
||||
"babel-jest",
|
||||
{ configFile: "../native/babel.config.js" }
|
||||
]
|
||||
},
|
||||
transformIgnorePatterns: ["<rootDir>/../node_modules/"]
|
||||
verbose: true
|
||||
};
|
||||
|
||||
@@ -74,7 +74,7 @@ async function login() {
|
||||
// }
|
||||
|
||||
describe("AUTH", () => {
|
||||
it("Login", async () => {
|
||||
it.skip("Login", async () => {
|
||||
await prepare();
|
||||
await openSideMenu();
|
||||
await login();
|
||||
|
||||
@@ -17,23 +17,22 @@ 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 { navigate, tapByText, prepare, sleep } from "./utils";
|
||||
import { Tests } from "./utils";
|
||||
|
||||
describe("APP LAUNCH AND NAVIGATION", () => {
|
||||
it("App should launch successfully & hide welcome screen", async () => {
|
||||
await prepare();
|
||||
await Tests.prepare();
|
||||
});
|
||||
|
||||
it("Basic navigation should work", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
await sleep(500);
|
||||
await navigate("Favorites");
|
||||
await navigate("Trash");
|
||||
await navigate("Tags");
|
||||
await navigate("Settings");
|
||||
await navigate("Monographs");
|
||||
await navigate("Reminders");
|
||||
await navigate("Notes");
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.navigate("Favorites");
|
||||
await Tests.navigate("Trash");
|
||||
await Tests.navigate("Tags");
|
||||
await Tests.navigate("Settings");
|
||||
await Tests.navigate("Monographs");
|
||||
await Tests.navigate("Reminders");
|
||||
await Tests.navigate("Notes");
|
||||
});
|
||||
});
|
||||
@@ -1,140 +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 { notesnook } from "../test.ids";
|
||||
import {
|
||||
navigate,
|
||||
tapById,
|
||||
visibleByText,
|
||||
createNote,
|
||||
prepare,
|
||||
visibleById,
|
||||
notVisibleById,
|
||||
sleep,
|
||||
exitEditor,
|
||||
tapByText,
|
||||
elementByText,
|
||||
elementById
|
||||
} from "./utils";
|
||||
|
||||
describe("NOTE TESTS", () => {
|
||||
it("Create a note in editor", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
});
|
||||
|
||||
it("Open and close a note", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await tapById(notesnook.ids.note.get(0));
|
||||
await exitEditor();
|
||||
});
|
||||
|
||||
it.only("Notes properties should show", async () => {
|
||||
await prepare();
|
||||
let note = await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await waitFor(elementByText("Created at:")).toBeVisible().withTimeout(500);
|
||||
});
|
||||
|
||||
it("Favorite and unfavorite a note", async () => {
|
||||
await prepare();
|
||||
let note = await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapById("icon-favorite");
|
||||
await visibleById("icon-star");
|
||||
await navigate("Favorites");
|
||||
await visibleByText(note.body);
|
||||
await sleep(500);
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapById("icon-favorite");
|
||||
await expect(element(by.text(note.body))).not.toBeVisible();
|
||||
await navigate("Notes");
|
||||
});
|
||||
|
||||
it("Pin a note to top", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapById("icon-pin");
|
||||
await visibleByText("Pinned");
|
||||
await visibleById("icon-pinned");
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapById("icon-pin");
|
||||
expect(element(by.id("icon-pinned"))).not.toBeVisible();
|
||||
});
|
||||
|
||||
it("Pin a note in notifications", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapById("icon-pin-to-notifications");
|
||||
await visibleByText("Unpin from notifications");
|
||||
await sleep(500);
|
||||
await tapById("icon-pin-to-notifications");
|
||||
await sleep(500);
|
||||
await visibleByText("Pin to notifications");
|
||||
});
|
||||
|
||||
it("Copy note", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await sleep(1000);
|
||||
await waitFor(elementById("icon-copy")).toBeVisible().withTimeout(500);
|
||||
await tapById("icon-copy");
|
||||
});
|
||||
|
||||
it("Assign colors to a note", async () => {
|
||||
await prepare();
|
||||
let note = await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await sleep(1000);
|
||||
await tapByText("Add color");
|
||||
await sleep(500);
|
||||
await elementById("color-title-input").typeText("Test color");
|
||||
await tapByText("Add color");
|
||||
await sleep(3000);
|
||||
await visibleById("icon-check");
|
||||
await tapById("icon-color-#efefef");
|
||||
await notVisibleById("icon-check");
|
||||
await tapById("icon-color-#efefef");
|
||||
await device.pressBack();
|
||||
await navigate("Test color");
|
||||
await visibleByText(note.body);
|
||||
});
|
||||
|
||||
it("Delete & restore a note", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await sleep(500);
|
||||
await tapById("icon-trash");
|
||||
await navigate("Trash");
|
||||
await sleep(500);
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await sleep(500);
|
||||
await tapByText("Restore note");
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await visibleByText(
|
||||
"Test note description that is very long and should not fit in text."
|
||||
);
|
||||
});
|
||||
});
|
||||
116
apps/mobile/e2e/tests/note.e2e.ts
Normal file
116
apps/mobile/e2e/tests/note.e2e.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
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 { notesnook } from "../test.ids";
|
||||
import { Tests } from "./utils";
|
||||
|
||||
describe("NOTE TESTS", () => {
|
||||
it("Create a note in editor", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
});
|
||||
|
||||
it("Open and close a note", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await Tests.fromId(notesnook.ids.note.get(0)).waitAndTap();
|
||||
await Tests.exitEditor();
|
||||
});
|
||||
|
||||
it("Notes properties should show", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.fromText("Created at").isVisible();
|
||||
});
|
||||
|
||||
it("Favorite and unfavorite a note", async () => {
|
||||
await Tests.prepare();
|
||||
let note = await Tests.createNote();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.fromId("icon-favorite").waitAndTap();
|
||||
await Tests.fromId("icon-star").isVisible();
|
||||
await Tests.navigate("Favorites");
|
||||
await Tests.fromText(note.body).isVisible();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.fromId("icon-favorite").waitAndTap();
|
||||
await Tests.fromText(note.body).isNotVisible();
|
||||
await Tests.navigate("Notes");
|
||||
});
|
||||
|
||||
it("Pin a note to top", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.fromId("icon-pin").waitAndTap();
|
||||
await Tests.fromText("Pinned").isVisible();
|
||||
await Tests.fromId("icon-pinned").isVisible();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.fromId("icon-pin").waitAndTap();
|
||||
await Tests.fromText("icon-pinned").isNotVisible();
|
||||
});
|
||||
|
||||
it.skip("Pin a note in notifications", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.fromId("icon-pin-to-notifications").waitAndTap();
|
||||
await Tests.fromText("Unpin from notifications").isVisible();
|
||||
await Tests.fromId("icon-pin-to-notifications").waitAndTap();
|
||||
await Tests.fromText("Pin to notifications").isVisible();
|
||||
});
|
||||
|
||||
it("Copy note", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.fromId("icon-copy").isVisible();
|
||||
await Tests.fromId("icon-copy").waitAndTap();
|
||||
});
|
||||
|
||||
it("Assign colors to a note", async () => {
|
||||
await Tests.prepare();
|
||||
let note = await Tests.createNote();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.fromText("Add color").waitAndTap();
|
||||
await Tests.fromId("color-title-input").element.typeText("Test color");
|
||||
await Tests.fromText("Add color").waitAndTap();
|
||||
await Tests.fromId("icon-check").isVisible();
|
||||
await Tests.fromId("icon-color-#efefef").waitAndTap();
|
||||
await Tests.fromId("icon-check").isNotVisible();
|
||||
await Tests.fromId("icon-color-#efefef").waitAndTap();
|
||||
await device.pressBack();
|
||||
await Tests.navigate("Test color");
|
||||
await Tests.fromText(note.body).isVisible();
|
||||
});
|
||||
|
||||
it("Delete & restore a note", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.fromId("icon-trash").waitAndTap();
|
||||
await Tests.navigate("Trash");
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.fromText("Restore").waitAndTap();
|
||||
await device.pressBack();
|
||||
await Tests.fromText(
|
||||
"Test note description that is very long and should not fit in text."
|
||||
).isVisible();
|
||||
});
|
||||
});
|
||||
@@ -1,309 +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 { notesnook } from "../test.ids";
|
||||
import {
|
||||
tapById,
|
||||
elementById,
|
||||
visibleByText,
|
||||
tapByText,
|
||||
createNote,
|
||||
prepare,
|
||||
notVisibleById,
|
||||
navigate,
|
||||
elementByText,
|
||||
sleep,
|
||||
notVisibleByText,
|
||||
visibleById,
|
||||
createNotebook
|
||||
} from "./utils";
|
||||
|
||||
// async function addTopic(title = "Topic") {
|
||||
// await tapById(notesnook.buttons.add);
|
||||
// await elementById("input-title").typeText(title);
|
||||
// await tapByText("Add");
|
||||
// await sleep(500);
|
||||
// }
|
||||
|
||||
describe("NOTEBOOKS", () => {
|
||||
it("Create a notebook with title only", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
await sleep(500);
|
||||
await tapByText("Add your first notebook");
|
||||
await createNotebook("Notebook 1", false, false);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await visibleByText("Notebook 1");
|
||||
});
|
||||
|
||||
it("Create a notebook title & description", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
await sleep(500);
|
||||
await tapByText("Add your first notebook");
|
||||
await createNotebook("Notebook 1", true, false);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await visibleByText("Notebook 1");
|
||||
});
|
||||
|
||||
it("Create a notebook, move notes", async () => {
|
||||
await prepare();
|
||||
let note = await createNote();
|
||||
await navigate("Notebooks");
|
||||
await sleep(500);
|
||||
await tapByText("Add your first notebook");
|
||||
await createNotebook("Notebook 1", true, true);
|
||||
await sleep(500);
|
||||
await tapById("listitem.select");
|
||||
await tapByText("Move selected notes");
|
||||
await sleep(500);
|
||||
await tapByText("Notebook 1");
|
||||
await sleep(500);
|
||||
await visibleByText(note.body);
|
||||
});
|
||||
|
||||
it("Add a sub notebook to a notebook", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
await sleep(500);
|
||||
await tapByText("Add your first notebook");
|
||||
await createNotebook("Notebook 1", true, false);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await tapByText("Notebook 1");
|
||||
await sleep(500);
|
||||
await tapById("add-notebook-button");
|
||||
await createNotebook("Sub notebook", true, true);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await visibleByText("Sub notebook");
|
||||
await tapById(notesnook.ids.notebook.menu);
|
||||
await tapByText("Move to trash");
|
||||
await sleep(300);
|
||||
await tapByText("Delete");
|
||||
await notVisibleByText("Sub notebook");
|
||||
});
|
||||
|
||||
it("Remove a sub notebook from notebook", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
await sleep(500);
|
||||
await tapByText("Add your first notebook");
|
||||
await createNotebook("Notebook 1", true, false);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await tapByText("Notebook 1");
|
||||
await sleep(500);
|
||||
await tapById("add-notebook-button");
|
||||
await createNotebook("Sub notebook", true, true);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await visibleByText("Sub notebook");
|
||||
});
|
||||
|
||||
it("Edit notebook", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
await sleep(500);
|
||||
await tapById(notesnook.buttons.add);
|
||||
await createNotebook("Notebook 1", true);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await tapById(notesnook.ids.notebook.menu);
|
||||
await tapByText("Edit notebook");
|
||||
await elementById(notesnook.ids.dialogs.notebook.inputs.title).typeText(
|
||||
" (edited)"
|
||||
);
|
||||
await tapByText("Save");
|
||||
await visibleByText("Notebook 1 (edited)");
|
||||
});
|
||||
|
||||
it("Edit a sub notebook", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
await sleep(500);
|
||||
await tapById(notesnook.buttons.add);
|
||||
await createNotebook("Notebook 1", true);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await tapByText("Notebook 1");
|
||||
await sleep(500);
|
||||
await tapById("add-notebook-button");
|
||||
await createNotebook("Sub notebook", true, true);
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await tapById(notesnook.ids.notebook.menu);
|
||||
await tapByText("Edit notebook");
|
||||
await sleep(500);
|
||||
await elementById(notesnook.ids.dialogs.notebook.inputs.title).typeText(
|
||||
" (edited)"
|
||||
);
|
||||
await tapByText("Save");
|
||||
await sleep(500);
|
||||
await visibleByText("Sub notebook (edited)");
|
||||
});
|
||||
|
||||
it("Add a note to notebook", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
await tapByText("Add your first notebook");
|
||||
await sleep(500);
|
||||
await createNotebook("Notebook 1", true, true);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await tapByText("Notebook 1");
|
||||
await createNote();
|
||||
});
|
||||
|
||||
it("Remove note from Notebook", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
await tapByText("Add your first notebook");
|
||||
await createNotebook("Notebook 1", true, true);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await tapByText("Notebook 1");
|
||||
await sleep(500);
|
||||
let note = await createNote();
|
||||
await elementByText(note.body).longPress();
|
||||
await tapById("select-minus");
|
||||
await notVisibleById(note.title);
|
||||
});
|
||||
|
||||
it("Add/Remove note to notebook from home", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
await sleep(500);
|
||||
await tapByText("Add your first notebook");
|
||||
await createNotebook("Notebook 1", true, false);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await navigate("Notes");
|
||||
await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapById("icon-notebooks");
|
||||
await sleep(500);
|
||||
await tapByText("Notebook 1");
|
||||
await tapByText("Save");
|
||||
await sleep(300);
|
||||
await visibleByText("Notebook 1");
|
||||
});
|
||||
|
||||
it("Edit notebook title, description", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
await sleep(500);
|
||||
await tapByText("Add your first notebook");
|
||||
await createNotebook();
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await visibleByText("Notebook 1");
|
||||
await tapById(notesnook.ids.notebook.menu);
|
||||
await tapByText("Edit notebook");
|
||||
await sleep(500);
|
||||
await elementById(notesnook.ids.dialogs.notebook.inputs.title).typeText(
|
||||
" (Edited)"
|
||||
);
|
||||
await elementById(
|
||||
notesnook.ids.dialogs.notebook.inputs.description
|
||||
).clearText();
|
||||
await elementById(
|
||||
notesnook.ids.dialogs.notebook.inputs.description
|
||||
).typeText("Description of Notebook 1 (Edited)");
|
||||
|
||||
await tapByText("Save");
|
||||
await sleep(500);
|
||||
await visibleByText("Notebook 1 (Edited)");
|
||||
await visibleByText("Description of Notebook 1 (Edited)");
|
||||
});
|
||||
|
||||
it.skip("Move notebook to trash", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
|
||||
await sleep(500);
|
||||
await tapByText("Add your first notebook");
|
||||
await createNotebook("Notebook 1", false, false);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await visibleByText("Notebook 1");
|
||||
await tapById(notesnook.ids.notebook.menu);
|
||||
await tapByText("Move to trash");
|
||||
await sleep(2000);
|
||||
await tapByText("Delete");
|
||||
await sleep(4000);
|
||||
await navigate("Trash");
|
||||
await visibleByText("Notebook 1");
|
||||
});
|
||||
|
||||
it("Move notebook to trash with notes", async () => {
|
||||
await prepare();
|
||||
let note = await createNote();
|
||||
await navigate("Notebooks");
|
||||
|
||||
await sleep(500);
|
||||
await tapByText("Add your first notebook");
|
||||
await createNotebook("Notebook 1", false, true);
|
||||
await sleep(500);
|
||||
await tapById("listitem.select");
|
||||
await tapByText("Move selected notes");
|
||||
await sleep(500);
|
||||
await visibleByText("Notebook 1");
|
||||
await tapById(notesnook.ids.notebook.menu);
|
||||
await tapByText("Move to trash");
|
||||
await sleep(2000);
|
||||
await tapByText("Move all notes in this notebook to trash");
|
||||
await sleep(500);
|
||||
await tapByText("Delete");
|
||||
await sleep(4000);
|
||||
await navigate("Trash");
|
||||
await visibleByText("Notebook 1");
|
||||
await visibleByText(note.body);
|
||||
});
|
||||
|
||||
it("Pin notebook to side menu", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
|
||||
await sleep(500);
|
||||
await tapByText("Add your first notebook");
|
||||
await createNotebook("Notebook 1", false, false);
|
||||
await sleep(500);
|
||||
await device.pressBack();
|
||||
await sleep(500);
|
||||
await visibleByText("Notebook 1");
|
||||
await tapById(notesnook.ids.notebook.menu);
|
||||
await tapByText("Add Shortcut");
|
||||
let menu = elementById(notesnook.ids.default.header.buttons.left);
|
||||
await menu.tap();
|
||||
await visibleByText("Notebook 1");
|
||||
});
|
||||
});
|
||||
233
apps/mobile/e2e/tests/notebook.e2e.ts
Normal file
233
apps/mobile/e2e/tests/notebook.e2e.ts
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
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 { notesnook } from "../test.ids";
|
||||
import { Tests } from "./utils";
|
||||
|
||||
describe("NOTEBOOKS", () => {
|
||||
it("Create a notebook with title only", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", false);
|
||||
await device.pressBack();
|
||||
await Tests.fromText("Notebook 1").isVisible();
|
||||
});
|
||||
|
||||
it("Create a notebook title & description", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", true);
|
||||
await device.pressBack();
|
||||
await Tests.fromText("Notebook 1").isVisible();
|
||||
});
|
||||
|
||||
it("Create a notebook, move notes", async () => {
|
||||
await Tests.prepare();
|
||||
let note = await Tests.createNote();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", true);
|
||||
await Tests.fromId("listitem.select").waitAndTap();
|
||||
await Tests.fromText("Move selected notes").waitAndTap();
|
||||
await Tests.fromText("Notebook 1").waitAndTap();
|
||||
await Tests.fromText(note.body).isVisible();
|
||||
});
|
||||
|
||||
it("Add a sub notebook to a notebook", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", true);
|
||||
await device.pressBack();
|
||||
await Tests.fromText("Notebook 1").waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromId("add-notebook-button").waitAndTap();
|
||||
await Tests.createNotebook("Sub notebook", true);
|
||||
await Tests.fromText("Sub notebook").isVisible();
|
||||
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Move to trash").waitAndTap();
|
||||
await Tests.fromText("Delete").waitAndTap();
|
||||
await Tests.fromText("Sub notebook").isNotVisible();
|
||||
});
|
||||
|
||||
it("Remove a sub notebook from notebook", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", true);
|
||||
await device.pressBack();
|
||||
await Tests.fromText("Notebook 1").waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromId("add-notebook-button").waitAndTap();
|
||||
await Tests.createNotebook("Sub notebook", true);
|
||||
await Tests.fromText("Sub notebook").isVisible();
|
||||
});
|
||||
|
||||
it("Edit notebook", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromId(notesnook.buttons.add).waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", true);
|
||||
await device.pressBack();
|
||||
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||
await Tests.fromText("Edit notebook").waitAndTap();
|
||||
await Tests.fromId(
|
||||
notesnook.ids.dialogs.notebook.inputs.title
|
||||
).element.typeText(" (edited)");
|
||||
await Tests.fromText("Save").waitAndTap();
|
||||
await Tests.fromText("Notebook 1 (edited)").isVisible();
|
||||
});
|
||||
|
||||
it("Edit a sub notebook", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromId(notesnook.buttons.add).waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", true);
|
||||
await device.pressBack();
|
||||
await Tests.fromText("Notebook 1").waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromId("add-notebook-button").waitAndTap();
|
||||
await Tests.createNotebook("Sub notebook", true);
|
||||
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Edit notebook").waitAndTap();
|
||||
await Tests.fromId(
|
||||
notesnook.ids.dialogs.notebook.inputs.title
|
||||
).element.typeText(" (edited)");
|
||||
await Tests.fromText("Save").waitAndTap();
|
||||
await Tests.fromText("Sub notebook (edited)").isVisible();
|
||||
});
|
||||
|
||||
it("Add a note to notebook", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", true);
|
||||
await device.pressBack();
|
||||
await Tests.fromText("Notebook 1").waitAndTap();
|
||||
await Tests.createNote();
|
||||
});
|
||||
|
||||
it.skip("Remove note from Notebook", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", true);
|
||||
await device.pressBack();
|
||||
await Tests.fromText("Notebook 1").waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
let note = await Tests.createNote();
|
||||
await Tests.fromText(note.body).element.longPress();
|
||||
await Tests.fromId("select-minus").waitAndTap();
|
||||
await Tests.fromId(note.title).isNotVisible();
|
||||
});
|
||||
|
||||
it("Add/Remove note to notebook from home", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", true);
|
||||
await device.pressBack();
|
||||
await Tests.navigate("Notes");
|
||||
await Tests.createNote();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromId("icon-notebooks").waitAndTap();
|
||||
await Tests.fromText("Notebook 1").waitAndTap();
|
||||
await Tests.fromText("Save").waitAndTap();
|
||||
await Tests.fromText("Notebook 1").isVisible();
|
||||
});
|
||||
|
||||
it("Edit notebook title, description", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||
await Tests.createNotebook();
|
||||
await device.pressBack();
|
||||
await Tests.fromText("Notebook 1").isVisible();
|
||||
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Edit notebook").waitAndTap();
|
||||
await Tests.fromId(
|
||||
notesnook.ids.dialogs.notebook.inputs.title
|
||||
).element.typeText(" (Edited)");
|
||||
await Tests.fromId(
|
||||
notesnook.ids.dialogs.notebook.inputs.description
|
||||
).element.clearText();
|
||||
await Tests.fromId(
|
||||
notesnook.ids.dialogs.notebook.inputs.description
|
||||
).element.typeText("Description of Notebook 1 (Edited)");
|
||||
await Tests.fromText("Save").waitAndTap();
|
||||
await Tests.fromText("Notebook 1 (Edited)").isVisible();
|
||||
await Tests.fromText("Description of Notebook 1 (Edited)").isVisible();
|
||||
});
|
||||
|
||||
it.skip("Move notebook to trash", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", false);
|
||||
await device.pressBack();
|
||||
await Tests.fromText("Notebook 1").isVisible();
|
||||
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Move to trash").waitAndTap();
|
||||
await Tests.fromText("Delete").waitAndTap();
|
||||
await Tests.navigate("Trash");
|
||||
await Tests.fromText("Notebook 1").isVisible();
|
||||
});
|
||||
|
||||
it("Move notebook to trash with notes", async () => {
|
||||
await Tests.prepare();
|
||||
let note = await Tests.createNote();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", false);
|
||||
await Tests.fromId("listitem.select").waitAndTap();
|
||||
await Tests.fromText("Move selected notes").waitAndTap();
|
||||
await Tests.fromText("Notebook 1").isVisible();
|
||||
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Move to trash").waitAndTap();
|
||||
await Tests.fromText(
|
||||
"Move all notes in this notebook to trash"
|
||||
).waitAndTap();
|
||||
await Tests.fromText("Delete").waitAndTap();
|
||||
await Tests.navigate("Trash");
|
||||
await Tests.fromText("Notebook 1").isVisible();
|
||||
await Tests.fromText(note.body).isVisible();
|
||||
});
|
||||
|
||||
it.skip("Pin notebook to side menu", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.navigate("Notebooks");
|
||||
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||
await Tests.createNotebook("Notebook 1", false);
|
||||
await device.pressBack();
|
||||
await Tests.fromText("Notebook 1").isVisible();
|
||||
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Add Shortcut").waitAndTap();
|
||||
await Tests.fromId(notesnook.ids.default.header.buttons.left).waitAndTap();
|
||||
await Tests.fromText("Notebook 1").isVisible();
|
||||
});
|
||||
});
|
||||
@@ -17,29 +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 { notesnook } from "../test.ids";
|
||||
import {
|
||||
tapById,
|
||||
visibleByText,
|
||||
createNote,
|
||||
prepare,
|
||||
elementById,
|
||||
sleep,
|
||||
tapByText
|
||||
} from "./utils";
|
||||
import { Tests } from "./utils";
|
||||
|
||||
describe("Search", () => {
|
||||
it("Search for a note", async () => {
|
||||
await prepare();
|
||||
let note = await createNote();
|
||||
await tapById("icon-search");
|
||||
await sleep(300);
|
||||
await elementById("search-input").typeText("Test");
|
||||
await sleep(1000);
|
||||
await tapByText(note.body);
|
||||
await sleep(1000);
|
||||
await Tests.prepare();
|
||||
let note = await Tests.createNote();
|
||||
await Tests.fromId("icon-search").waitAndTap();
|
||||
await Tests.fromId("search-input").element.typeText("Test");
|
||||
await Tests.fromText(note.body).waitAndTap();
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await visibleByText(note.body);
|
||||
await Tests.fromText(note.body).isVisible();
|
||||
});
|
||||
});
|
||||
@@ -1,121 +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 { notesnook } from "../test.ids";
|
||||
import {
|
||||
tapById,
|
||||
visibleByText,
|
||||
createNote,
|
||||
prepare,
|
||||
tapByText,
|
||||
notVisibleByText,
|
||||
sleep,
|
||||
navigate,
|
||||
createNotebook
|
||||
} from "./utils";
|
||||
|
||||
async function sortBy(sorting, elementText = "Default") {
|
||||
await tapByText(elementText);
|
||||
await tapByText(sorting);
|
||||
await device.pressBack();
|
||||
}
|
||||
|
||||
describe("Sort & filter", () => {
|
||||
it("Sort by date-edited/date-created", async () => {
|
||||
await prepare();
|
||||
let webview = web(by.id(notesnook.editor.id));
|
||||
await createNote("Note 1", "Note 1");
|
||||
await sleep(300);
|
||||
await createNote("Note 2", "Note 2");
|
||||
await sleep(300);
|
||||
await tapByText("Note 1");
|
||||
await sleep(500);
|
||||
await expect(webview.element(by.web.className("ProseMirror"))).toExist();
|
||||
await webview.element(by.web.className("ProseMirror")).tap();
|
||||
await webview
|
||||
.element(by.web.className("ProseMirror"))
|
||||
.typeText("Edited ", true);
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await sortBy("Date created");
|
||||
await tapById(notesnook.listitem.menu);
|
||||
//await visibleByText("Note 2");
|
||||
await device.pressBack();
|
||||
await sortBy("Date edited");
|
||||
await tapById(notesnook.listitem.menu);
|
||||
//await visibleByText("Edited Note 1");
|
||||
await device.pressBack();
|
||||
});
|
||||
|
||||
it("Disable grouping", async () => {
|
||||
await prepare();
|
||||
await createNote("Note 1", "Note 1");
|
||||
await sleep(300);
|
||||
await sortBy("None");
|
||||
await sleep(300);
|
||||
await visibleByText("None");
|
||||
});
|
||||
|
||||
it("Group by Abc", async () => {
|
||||
await prepare();
|
||||
await createNote("Note 1", "Note 1");
|
||||
await sleep(300);
|
||||
await sortBy("Abc");
|
||||
await visibleByText("N");
|
||||
});
|
||||
|
||||
it("Group by Year", async () => {
|
||||
await prepare();
|
||||
await createNote("Note 1", "Note 1");
|
||||
await sleep(300);
|
||||
await sortBy("Year");
|
||||
await sleep(300);
|
||||
await visibleByText("Year");
|
||||
});
|
||||
|
||||
it("Group by Week", async () => {
|
||||
await prepare();
|
||||
await createNote("Note 1", "Note 1");
|
||||
await sleep(300);
|
||||
await sortBy("Week");
|
||||
await sleep(300);
|
||||
await visibleByText("Week");
|
||||
});
|
||||
|
||||
it("Group by Month", async () => {
|
||||
await prepare();
|
||||
await createNote("Note 1", "Note 1");
|
||||
await sleep(300);
|
||||
await sortBy("Month");
|
||||
await sleep(300);
|
||||
await visibleByText("Month");
|
||||
});
|
||||
|
||||
it("Compact mode", async () => {
|
||||
await prepare();
|
||||
await createNote("Note 1", "Note 1");
|
||||
await sleep(300);
|
||||
await tapById("icon-compact-mode");
|
||||
await sleep(300);
|
||||
await notVisibleByText("Note 1");
|
||||
await tapById("icon-compact-mode");
|
||||
await sleep(300);
|
||||
await visibleByText("Note 1");
|
||||
});
|
||||
});
|
||||
93
apps/mobile/e2e/tests/sort.e2e.ts
Normal file
93
apps/mobile/e2e/tests/sort.e2e.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
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 { notesnook } from "../test.ids";
|
||||
import { Tests } from "./utils";
|
||||
|
||||
async function sortBy(sorting: string, elementText = "Default") {
|
||||
await Tests.fromText(elementText).waitAndTap();
|
||||
await Tests.fromText(sorting).waitAndTap();
|
||||
await device.pressBack();
|
||||
}
|
||||
|
||||
describe("Sort & filter", () => {
|
||||
it("Sort by date-edited/date-created", async () => {
|
||||
await Tests.prepare();
|
||||
let webview = web();
|
||||
await Tests.createNote("Note 1", "Note 1");
|
||||
await Tests.createNote("Note 2", "Note 2");
|
||||
await Tests.fromText("Note 1").waitAndTap();
|
||||
await webview.element(by.web.className("ProseMirror")).tap();
|
||||
await webview
|
||||
.element(by.web.className("ProseMirror"))
|
||||
.typeText("Edited ", true);
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await sortBy("Date created");
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await device.pressBack();
|
||||
await sortBy("Date edited");
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await device.pressBack();
|
||||
});
|
||||
|
||||
it("Disable grouping", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote("Note 1", "Note 1");
|
||||
await sortBy("None");
|
||||
await Tests.fromText("Default").isNotVisible();
|
||||
});
|
||||
|
||||
it("Group by Abc", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote("Note 1", "Note 1");
|
||||
await sortBy("Abc");
|
||||
await Tests.fromText("N").isVisible();
|
||||
});
|
||||
|
||||
it("Group by Year", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote("Note 1", "Note 1");
|
||||
await sortBy("Year");
|
||||
await Tests.fromText("Year").isVisible();
|
||||
});
|
||||
|
||||
it("Group by Week", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote("Note 1", "Note 1");
|
||||
await sortBy("Week");
|
||||
await Tests.fromText("Week").isVisible();
|
||||
});
|
||||
|
||||
it("Group by Month", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote("Note 1", "Note 1");
|
||||
await sortBy("Month");
|
||||
await Tests.fromText("Month").isVisible();
|
||||
});
|
||||
|
||||
it("Compact mode", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote("Note 1", "Note 1");
|
||||
await Tests.fromId("icon-compact-mode").waitAndTap();
|
||||
await Tests.fromText("Note 1").isNotVisible();
|
||||
await Tests.fromId("icon-compact-mode").waitAndTap();
|
||||
await Tests.fromText("Note 1").isVisible();
|
||||
});
|
||||
});
|
||||
@@ -1,103 +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 { notesnook } from "../test.ids";
|
||||
import {
|
||||
navigate,
|
||||
tapById,
|
||||
visibleByText,
|
||||
createNote,
|
||||
prepare,
|
||||
elementById,
|
||||
tapByText,
|
||||
notVisibleByText,
|
||||
sleep
|
||||
} from "./utils";
|
||||
|
||||
describe("Tags", () => {
|
||||
it("Tag a note", async () => {
|
||||
await prepare();
|
||||
let note = await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapByText("Add tags");
|
||||
await elementById("tag-input").typeText("testtag");
|
||||
await tapByText('Add "#testtag"');
|
||||
await visibleByText("#testtag");
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await navigate("Tags");
|
||||
await tapByText("#testtag");
|
||||
await visibleByText(note.body);
|
||||
});
|
||||
|
||||
it("Untag a note", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapByText("Add tags");
|
||||
await elementById("tag-input").typeText("testtag");
|
||||
await tapByText('Add "#testtag"');
|
||||
await visibleByText("#testtag");
|
||||
await tapByText("#testtag");
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await notVisibleByText("#testtag");
|
||||
});
|
||||
|
||||
it("Creat shortcut of a tag", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapByText("Add tags");
|
||||
await elementById("tag-input").typeText("testtag");
|
||||
await tapByText('Add "#testtag"');
|
||||
await visibleByText("#testtag");
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await navigate("Tags");
|
||||
await sleep(500);
|
||||
await tapById(notesnook.ids.tag.menu);
|
||||
await sleep(500);
|
||||
await tapByText("Add Shortcut");
|
||||
let menu = elementById(notesnook.ids.default.header.buttons.left);
|
||||
await menu.tap();
|
||||
await visibleByText("#testtag");
|
||||
});
|
||||
|
||||
it("Rename a tag", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapByText("Add tags");
|
||||
await elementById("tag-input").typeText("testtag");
|
||||
await tapByText('Add "#testtag"');
|
||||
await visibleByText("#testtag");
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await navigate("Tags");
|
||||
await tapById(notesnook.ids.tag.menu);
|
||||
await sleep(500);
|
||||
await tapByText("Rename tag");
|
||||
await sleep(500);
|
||||
await elementById("input-value").clearText();
|
||||
await elementById("input-value").typeText("testtag_edited");
|
||||
await tapByText("Save");
|
||||
await visibleByText("#testtag_edited");
|
||||
});
|
||||
});
|
||||
95
apps/mobile/e2e/tests/tag.e2e.ts
Normal file
95
apps/mobile/e2e/tests/tag.e2e.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
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 { notesnook } from "../test.ids";
|
||||
import { Tests } from "./utils";
|
||||
|
||||
describe("Tags", () => {
|
||||
it("Tag a note", async () => {
|
||||
await Tests.prepare();
|
||||
let note = await Tests.createNote();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Add tag").waitAndTap();
|
||||
await Tests.fromId("tag-input").element.typeText("testtag");
|
||||
await Tests.fromText('Add "#testtag"').waitAndTap();
|
||||
await Tests.fromText("#testtag").isVisible();
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await Tests.navigate("Tags");
|
||||
await Tests.fromText("#testtag").waitAndTap();
|
||||
await Tests.fromText(note.body).isVisible();
|
||||
});
|
||||
|
||||
it("Untag a note", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Add tag").waitAndTap();
|
||||
await Tests.fromId("tag-input").element.typeText("testtag");
|
||||
await Tests.fromText('Add "#testtag"').waitAndTap();
|
||||
await Tests.fromText("#testtag").isVisible();
|
||||
await Tests.fromText("#testtag").waitAndTap();
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await Tests.fromText("#testtag").isNotVisible();
|
||||
});
|
||||
|
||||
it("Create shortcut of a tag", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Add tag").waitAndTap();
|
||||
await Tests.fromId("tag-input").element.typeText("testtag");
|
||||
await Tests.fromText('Add "#testtag"').waitAndTap();
|
||||
await Tests.fromText("#testtag").isVisible();
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await Tests.navigate("Tags");
|
||||
await Tests.fromId(notesnook.ids.tag.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Add shortcut").waitAndTap();
|
||||
await Tests.fromId(notesnook.ids.default.header.buttons.left).waitAndTap();
|
||||
await Tests.fromText("testtag").isVisible();
|
||||
});
|
||||
|
||||
it("Rename a tag", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Add tag").waitAndTap();
|
||||
await Tests.fromId("tag-input").element.typeText("testtag");
|
||||
await Tests.fromText('Add "#testtag"').waitAndTap();
|
||||
await Tests.fromText("#testtag").isVisible();
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await Tests.navigate("Tags");
|
||||
await Tests.fromId(notesnook.ids.tag.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Rename").waitAndTap();
|
||||
await Tests.sleep(100);
|
||||
await Tests.fromId("input-value").element.clearText();
|
||||
await Tests.fromId("input-value").element.typeText("testtag_edited");
|
||||
await Tests.fromText("Save").waitAndTap();
|
||||
await Tests.fromText("#testtag_edited").isVisible();
|
||||
});
|
||||
});
|
||||
@@ -1,166 +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 { notesnook } from "../test.ids";
|
||||
import { readFileSync } from "fs";
|
||||
import { expect as jestExpect } from "@jest/globals";
|
||||
import { toMatchImageSnapshot } from "jest-image-snapshot";
|
||||
import { device as _device } from "detox";
|
||||
jestExpect.extend({ toMatchImageSnapshot });
|
||||
|
||||
const sleep = (duration) =>
|
||||
new Promise((resolve) =>
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, duration)
|
||||
);
|
||||
|
||||
async function LaunchApp() {
|
||||
await waitFor(element(by.id(notesnook.ids.default.root)))
|
||||
.toBeVisible()
|
||||
.withTimeout(500);
|
||||
}
|
||||
|
||||
function elementById(id) {
|
||||
return element(by.id(id)).atIndex(0);
|
||||
}
|
||||
|
||||
function elementByText(text) {
|
||||
return element(by.text(text)).atIndex(0);
|
||||
}
|
||||
|
||||
async function tapById(id) {
|
||||
await elementById(id).tap();
|
||||
}
|
||||
|
||||
async function tapByText(text) {
|
||||
await elementByText(text).tap();
|
||||
}
|
||||
|
||||
async function visibleByText(text) {
|
||||
await expect(elementByText(text)).toBeVisible();
|
||||
}
|
||||
|
||||
async function visibleById(id) {
|
||||
await expect(elementById(id)).toBeVisible();
|
||||
}
|
||||
|
||||
async function notVisibleById(id) {
|
||||
await expect(elementById(id)).not.toBeVisible();
|
||||
}
|
||||
|
||||
async function notVisibleByText(text) {
|
||||
await expect(elementByText(text)).not.toBeVisible();
|
||||
}
|
||||
|
||||
async function exitEditor() {
|
||||
await _device.pressBack();
|
||||
await _device.pressBack();
|
||||
}
|
||||
|
||||
async function createNote(_title, _body) {
|
||||
let title = _title || "Test note description that ";
|
||||
let body =
|
||||
_body ||
|
||||
"Test note description that is very long and should not fit in text.";
|
||||
await tapById(notesnook.buttons.add);
|
||||
let webview = web(by.id(notesnook.editor.id));
|
||||
await expect(webview.element(by.web.className("ProseMirror"))).toExist();
|
||||
await webview.element(by.web.className("ProseMirror")).tap();
|
||||
await webview.element(by.web.className("ProseMirror")).typeText(body, true);
|
||||
await exitEditor();
|
||||
await waitFor(element(by.text(body)))
|
||||
.toBeVisible()
|
||||
.withTimeout(500);
|
||||
|
||||
return { title, body };
|
||||
}
|
||||
|
||||
async function openSideMenu() {
|
||||
let menu = elementById(notesnook.ids.default.header.buttons.left);
|
||||
await menu.tap();
|
||||
}
|
||||
|
||||
async function navigate(screen) {
|
||||
let menu = elementById(notesnook.ids.default.header.buttons.left);
|
||||
await waitFor(menu).toBeVisible().withTimeout(300);
|
||||
await menu.tap();
|
||||
|
||||
await waitFor(elementByText(screen)).toBeVisible().withTimeout(300);
|
||||
await elementByText(screen).tap();
|
||||
}
|
||||
|
||||
const testvars = {
|
||||
isFirstTest: true
|
||||
};
|
||||
|
||||
async function prepare() {
|
||||
await device.disableSynchronization();
|
||||
if (testvars.isFirstTest) {
|
||||
testvars.isFirstTest = false;
|
||||
return await LaunchApp();
|
||||
}
|
||||
await device.reverseTcpPort(8081);
|
||||
await device.uninstallApp();
|
||||
await device.installApp();
|
||||
await device.launchApp({ newInstance: true });
|
||||
await LaunchApp();
|
||||
}
|
||||
|
||||
async function matchSnapshot(element, name) {
|
||||
let path = await element.takeScreenshot(name);
|
||||
const bitmapBuffer = readFileSync(path);
|
||||
jestExpect(bitmapBuffer).toMatchImageSnapshot({
|
||||
failureThreshold: 200,
|
||||
failureThresholdType: "pixel"
|
||||
});
|
||||
}
|
||||
|
||||
async function createNotebook(title = "Notebook 1", description = true) {
|
||||
await elementById(notesnook.ids.dialogs.notebook.inputs.title).typeText(
|
||||
title
|
||||
);
|
||||
if (description) {
|
||||
await elementById(
|
||||
notesnook.ids.dialogs.notebook.inputs.description
|
||||
).typeText(`Description of ${title}`);
|
||||
}
|
||||
await tapByText("Add");
|
||||
await sleep(300);
|
||||
}
|
||||
|
||||
export {
|
||||
matchSnapshot,
|
||||
createNotebook,
|
||||
prepare,
|
||||
LaunchApp,
|
||||
createNote,
|
||||
navigate,
|
||||
openSideMenu,
|
||||
notVisibleById,
|
||||
notVisibleByText,
|
||||
visibleById,
|
||||
visibleByText,
|
||||
tapById,
|
||||
tapByText,
|
||||
elementByText,
|
||||
elementById,
|
||||
sleep,
|
||||
exitEditor
|
||||
};
|
||||
149
apps/mobile/e2e/tests/utils.ts
Normal file
149
apps/mobile/e2e/tests/utils.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
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 { expect as jestExpect } from "@jest/globals";
|
||||
import { device as _device, expect } from "detox";
|
||||
import { readFileSync } from "fs";
|
||||
import { toMatchImageSnapshot } from "jest-image-snapshot";
|
||||
import type { RouteName } from "../../app/stores/use-navigation-store";
|
||||
import { notesnook } from "../test.ids";
|
||||
jestExpect.extend({ toMatchImageSnapshot });
|
||||
|
||||
const testvars = {
|
||||
isFirstTest: true
|
||||
};
|
||||
|
||||
class Element {
|
||||
element: Detox.NativeElement;
|
||||
constructor(public type: "id" | "text", public value: string) {
|
||||
if (type == "id") {
|
||||
this.element = element(by.id(value)).atIndex(0);
|
||||
} else {
|
||||
this.element = element(by.text(value)).atIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
isVisible(timeout?: number) {
|
||||
return waitFor(this.element)
|
||||
.toBeVisible()
|
||||
.withTimeout(timeout || 500);
|
||||
}
|
||||
|
||||
isNotVisible(timeout?: number) {
|
||||
return waitFor(this.element)
|
||||
.not.toBeVisible()
|
||||
.withTimeout(timeout || 500);
|
||||
}
|
||||
|
||||
async waitAndTap(timeout?: number) {
|
||||
await waitFor(this.element)
|
||||
.toBeVisible()
|
||||
.withTimeout(timeout || 500);
|
||||
await this.element.tap();
|
||||
}
|
||||
|
||||
tap(point?: Detox.Point2D): Promise<void> {
|
||||
return this.element.tap(point);
|
||||
}
|
||||
|
||||
static fromId(id: string) {
|
||||
return new Element("id", id);
|
||||
}
|
||||
static fromText(text: string) {
|
||||
return new Element("text", text);
|
||||
}
|
||||
}
|
||||
|
||||
const Tests = {
|
||||
awaitLaunch: async () => {
|
||||
await waitFor(element(by.id(notesnook.ids.default.root)))
|
||||
.toBeVisible()
|
||||
.withTimeout(500);
|
||||
},
|
||||
sleep: (duration: number) => {
|
||||
return new Promise((resolve) =>
|
||||
setTimeout(() => {
|
||||
resolve(undefined);
|
||||
}, duration)
|
||||
);
|
||||
},
|
||||
fromId: Element.fromId,
|
||||
fromText: Element.fromText,
|
||||
async exitEditor() {
|
||||
await _device.pressBack();
|
||||
await _device.pressBack();
|
||||
},
|
||||
async createNote(_title?: string, _body?: string) {
|
||||
let title = _title || "Test note description that ";
|
||||
let body =
|
||||
_body ||
|
||||
"Test note description that is very long and should not fit in text.";
|
||||
await Tests.fromId(notesnook.buttons.add).tap();
|
||||
await expect(web().element(by.web.className("ProseMirror"))).toExist();
|
||||
// await web().element(by.web.className("ProseMirror")).tap();
|
||||
await web().element(by.web.className("ProseMirror")).typeText(body, true);
|
||||
await Tests.exitEditor();
|
||||
await Tests.fromText(body).isVisible();
|
||||
return { title, body };
|
||||
},
|
||||
async navigate(screen: RouteName | ({} & string)) {
|
||||
let menu = Tests.fromId(notesnook.ids.default.header.buttons.left);
|
||||
await menu.waitAndTap();
|
||||
await Tests.fromText(screen).waitAndTap();
|
||||
},
|
||||
async openSideMenu() {
|
||||
await Tests.fromId(notesnook.ids.default.header.buttons.left).waitAndTap();
|
||||
},
|
||||
async prepare() {
|
||||
await device.disableSynchronization();
|
||||
if (testvars.isFirstTest) {
|
||||
testvars.isFirstTest = false;
|
||||
return await Tests.awaitLaunch();
|
||||
}
|
||||
await device.reverseTcpPort(8081);
|
||||
await device.uninstallApp();
|
||||
await device.installApp();
|
||||
await device.launchApp({ newInstance: true });
|
||||
await Tests.awaitLaunch();
|
||||
},
|
||||
async createNotebook(title = "Notebook 1", description = true) {
|
||||
await Tests.sleep(1000);
|
||||
const titleInput = Tests.fromId(
|
||||
notesnook.ids.dialogs.notebook.inputs.title
|
||||
);
|
||||
await titleInput.isVisible();
|
||||
await titleInput.element.typeText(title);
|
||||
if (description) {
|
||||
await Tests.fromId(
|
||||
notesnook.ids.dialogs.notebook.inputs.description
|
||||
).element.typeText(`Description of ${title}`);
|
||||
}
|
||||
await Tests.fromText("Add").waitAndTap();
|
||||
},
|
||||
async matchSnapshot(element: Element, name: string) {
|
||||
let path = await element.element.takeScreenshot(name);
|
||||
const bitmapBuffer = readFileSync(path);
|
||||
(jestExpect(bitmapBuffer) as any).toMatchImageSnapshot({
|
||||
failureThreshold: 200,
|
||||
failureThresholdType: "pixel"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export { Element, Tests };
|
||||
@@ -1,145 +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 { notesnook } from "../test.ids";
|
||||
import {
|
||||
tapById,
|
||||
elementById,
|
||||
visibleByText,
|
||||
tapByText,
|
||||
createNote,
|
||||
prepare,
|
||||
visibleById,
|
||||
matchSnapshot,
|
||||
notVisibleById,
|
||||
navigate
|
||||
} from "./utils";
|
||||
import { sleep } from "./utils";
|
||||
|
||||
async function lockNote() {
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapById("icon-lock-unlock");
|
||||
await sleep(1000);
|
||||
await visibleByText("Lock");
|
||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText("1234");
|
||||
await elementById(notesnook.ids.dialogs.vault.pwdAlt).typeText("1234");
|
||||
await tapByText("Lock");
|
||||
await sleep(500);
|
||||
await visibleById("note-locked-icon");
|
||||
}
|
||||
|
||||
async function removeFromVault() {
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapById("icon-lock-unlock");
|
||||
await sleep(1000);
|
||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText("1234");
|
||||
await tapByText("Unlock");
|
||||
await sleep(1000);
|
||||
await notVisibleById("note-locked-icon");
|
||||
}
|
||||
|
||||
async function openLockedNote(pwd) {
|
||||
await tapById(notesnook.ids.note.get(1));
|
||||
await sleep(1000);
|
||||
await visibleByText("Open");
|
||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText(pwd || "1234");
|
||||
await tapByText("Open");
|
||||
await sleep(3000);
|
||||
await matchSnapshot(elementById("editor-wrapper"), "note-after-vault-unlock");
|
||||
}
|
||||
|
||||
async function goToPrivacySecuritySettings() {
|
||||
await navigate("Settings");
|
||||
await tapByText("Vault");
|
||||
await sleep(500);
|
||||
}
|
||||
|
||||
describe("VAULT", () => {
|
||||
it("Create vault from settings", async () => {
|
||||
await prepare();
|
||||
await goToPrivacySecuritySettings();
|
||||
await tapByText("Create vault");
|
||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText("1234");
|
||||
await elementById(notesnook.ids.dialogs.vault.pwdAlt).typeText("1234");
|
||||
await tapByText("Create");
|
||||
await sleep(500);
|
||||
await visibleByText("Clear vault");
|
||||
});
|
||||
|
||||
it("Change vault password", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await lockNote();
|
||||
await goToPrivacySecuritySettings();
|
||||
await tapByText("Change vault password");
|
||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText("1234");
|
||||
await elementById(notesnook.ids.dialogs.vault.changePwd).typeText("2362");
|
||||
await tapByText("Change");
|
||||
await sleep(2000);
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await openLockedNote("2362");
|
||||
});
|
||||
|
||||
it("Delete vault", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await lockNote();
|
||||
await goToPrivacySecuritySettings();
|
||||
await tapByText("Delete vault");
|
||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText("1234");
|
||||
await tapByText("Delete");
|
||||
await sleep(500);
|
||||
await visibleByText("Create vault");
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await visibleById(notesnook.listitem.menu);
|
||||
});
|
||||
|
||||
it("Delete vault with locked notes", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await lockNote();
|
||||
await goToPrivacySecuritySettings();
|
||||
await tapByText("Delete vault");
|
||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText("1234");
|
||||
await tapByText("Delete all notes");
|
||||
await tapByText("Delete");
|
||||
await sleep(500);
|
||||
await visibleByText("Create vault");
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await notVisibleById(notesnook.listitem.menu);
|
||||
});
|
||||
|
||||
it("Add a note to vault", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await lockNote();
|
||||
await openLockedNote();
|
||||
});
|
||||
|
||||
it("Remove note from vault", async () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await lockNote();
|
||||
await removeFromVault();
|
||||
});
|
||||
});
|
||||
146
apps/mobile/e2e/tests/vault.e2e.ts
Normal file
146
apps/mobile/e2e/tests/vault.e2e.ts
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
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 { expect } from "detox";
|
||||
import { notesnook } from "../test.ids";
|
||||
import { Tests } from "./utils";
|
||||
|
||||
async function lockNote() {
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromId("icon-lock-unlock").waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromText("Lock").isVisible();
|
||||
await Tests.fromId(notesnook.ids.dialogs.vault.pwd).element.typeText("1234");
|
||||
await Tests.fromId(notesnook.ids.dialogs.vault.pwdAlt).element.typeText(
|
||||
"1234"
|
||||
);
|
||||
await Tests.fromText("Lock").waitAndTap();
|
||||
await Tests.fromId("note-locked-icon").isVisible();
|
||||
}
|
||||
|
||||
async function removeFromVault() {
|
||||
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromId("icon-lock-unlock").waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await Tests.fromId(notesnook.ids.dialogs.vault.pwd).element.typeText("1234");
|
||||
await Tests.fromText("Unlock").waitAndTap();
|
||||
await Tests.fromId("note-locked-icon").isNotVisible();
|
||||
}
|
||||
|
||||
async function openLockedNote(pwd?: string) {
|
||||
await Tests.fromId(notesnook.ids.note.get(0)).waitAndTap();
|
||||
await Tests.sleep(500);
|
||||
await web()
|
||||
.element(by.web.name("password"))
|
||||
.typeText(pwd || "1234", false);
|
||||
await web().element(by.web.className("unlock-note")).tap();
|
||||
await Tests.sleep(500);
|
||||
await expect(web().element(by.web.className("unlock-note"))).not.toExist();
|
||||
}
|
||||
|
||||
async function goToPrivacySecuritySettings() {
|
||||
await Tests.navigate("Settings");
|
||||
await Tests.sleep(300);
|
||||
await Tests.fromText("Vault").waitAndTap();
|
||||
}
|
||||
|
||||
describe("VAULT", () => {
|
||||
it("Create vault from settings", async () => {
|
||||
await Tests.prepare();
|
||||
await goToPrivacySecuritySettings();
|
||||
await Tests.fromText("Create vault").waitAndTap();
|
||||
await Tests.fromId(notesnook.ids.dialogs.vault.pwd).element.typeText(
|
||||
"1234"
|
||||
);
|
||||
await Tests.fromId(notesnook.ids.dialogs.vault.pwdAlt).element.typeText(
|
||||
"1234"
|
||||
);
|
||||
await Tests.fromText("Create").waitAndTap();
|
||||
await Tests.fromText("Clear vault").isVisible();
|
||||
});
|
||||
|
||||
it("Change vault password", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await lockNote();
|
||||
await goToPrivacySecuritySettings();
|
||||
await Tests.fromText("Change vault password").waitAndTap();
|
||||
await Tests.fromId(notesnook.ids.dialogs.vault.pwd).element.typeText(
|
||||
"1234"
|
||||
);
|
||||
await Tests.fromId(notesnook.ids.dialogs.vault.changePwd).element.typeText(
|
||||
"2362"
|
||||
);
|
||||
await Tests.fromText("Change").waitAndTap();
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await Tests.sleep(500);
|
||||
await openLockedNote("2362");
|
||||
});
|
||||
|
||||
it("Delete vault", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await lockNote();
|
||||
await goToPrivacySecuritySettings();
|
||||
await Tests.fromText("Delete vault").waitAndTap();
|
||||
await Tests.fromId(notesnook.ids.dialogs.vault.pwd).element.typeText(
|
||||
"1234"
|
||||
);
|
||||
await Tests.fromText("Delete").waitAndTap();
|
||||
await Tests.sleep(300);
|
||||
await Tests.fromText("Create vault").isVisible();
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await Tests.fromId(notesnook.listitem.menu).isVisible();
|
||||
});
|
||||
|
||||
it("Delete vault with locked notes", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await lockNote();
|
||||
await goToPrivacySecuritySettings();
|
||||
await Tests.fromText("Delete vault").waitAndTap();
|
||||
await Tests.fromId(notesnook.ids.dialogs.vault.pwd).element.typeText(
|
||||
"1234"
|
||||
);
|
||||
await Tests.fromText("Delete notes in this vault").waitAndTap();
|
||||
await Tests.fromText("Delete").waitAndTap();
|
||||
await Tests.sleep(300);
|
||||
await Tests.fromText("Create vault").isVisible();
|
||||
await device.pressBack();
|
||||
await device.pressBack();
|
||||
await Tests.fromId(notesnook.listitem.menu).isNotVisible();
|
||||
});
|
||||
|
||||
it("Add a note to vault", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await lockNote();
|
||||
await openLockedNote();
|
||||
});
|
||||
|
||||
it("Remove note from vault", async () => {
|
||||
await Tests.prepare();
|
||||
await Tests.createNote();
|
||||
await lockNote();
|
||||
await removeFromVault();
|
||||
});
|
||||
});
|
||||
@@ -52,7 +52,7 @@ module.exports = {
|
||||
emulator: {
|
||||
type: 'android.emulator',
|
||||
device: {
|
||||
avdName: 'Pixel_5_API_31'
|
||||
avdName: 'Pixel_5_API_34'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -116,7 +116,7 @@ android {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
multiDexEnabled true
|
||||
versionCode 3028
|
||||
versionCode 3031
|
||||
versionName getNpmVersion()
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
@@ -164,10 +164,7 @@ android {
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
pickFirst 'lib/x86/libc++_shared.so'
|
||||
pickFirst 'lib/x86_64/libc++_shared.so'
|
||||
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
|
||||
pickFirst 'lib/arm64-v8a/libc++_shared.so'
|
||||
pickFirst '**/libc++_shared.so'
|
||||
jniLibs {
|
||||
useLegacyPackaging isBuildingAAB == false
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ buildscript {
|
||||
androidXCoreVersion = "1.7.0"
|
||||
androidXCore = "1.7.0"
|
||||
androidXBrowser = "1.0.0"
|
||||
ndkVersion = "23.1.7779620"
|
||||
ndkVersion = "23.2.8568313"
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
||||
@@ -16,6 +16,7 @@ org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
# org.gradle.configuration-cache=true
|
||||
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
- Fix random crashes on system startup and when app enter background
|
||||
- Attachments manager now shows progress for uploading/downloading/checking attachments
|
||||
- Attachments manager has two new tabs, Errors and Orphaned, to help you manage your attachments
|
||||
- New and improved toast message design
|
||||
- Fix statusbar flicker on app launch
|
||||
- Many other bug fixes and small improvements
|
||||
- Added full support for localization in Notesnook
|
||||
- Improved search experience
|
||||
- Allow user to cancel logging in
|
||||
- Fixed scrolling focused line into view
|
||||
- Support self hosted monograph server
|
||||
- Fixed markdown link pasting in editor
|
||||
- Many other bug fixes and improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
@@ -18,10 +18,10 @@ import { i18n } from "@lingui/core";
|
||||
import { ScriptManager, Script } from '@callstack/repack/client';
|
||||
import {
|
||||
messages as $en
|
||||
} from "@notesnook/intl/locales/$en.json";
|
||||
} from "@notesnook/intl/dist/locales/$en.json";
|
||||
import {
|
||||
messages as $pseudo
|
||||
} from "@notesnook/intl/locales/$pseudo-LOCALE.json";
|
||||
} from "@notesnook/intl/dist/locales/$pseudo-LOCALE.json";
|
||||
|
||||
i18n.load({
|
||||
en: __DEV__ ? $pseudo : $en
|
||||
@@ -30,6 +30,17 @@ setI18nGlobal(i18n);
|
||||
i18n.activate("en");
|
||||
setI18nGlobal(i18n);
|
||||
|
||||
if (global.__DEV__) {
|
||||
const err = console.error;
|
||||
console.error = function (message) {
|
||||
if (typeof message === 'string' && message.includes('VirtualizedLists should never be')) {
|
||||
err.apply(console, ["VirtualizedLists should never be nested inside plain ScrollViews"]);
|
||||
return;
|
||||
}
|
||||
err.apply(console, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
ScriptManager.shared.addResolver(async (scriptId) => {
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
2D02E4901E0B4A5D006451C7 /* Notesnook-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Notesnook-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
41D57E9831C724F59F18FBAE /* libPods-Notesnook-Add to Notes.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Notesnook-Add to Notes.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
47AE097A087A651BD60CAD7B /* Pods-Notesnook-Make Note.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Notesnook-Make Note.release.xcconfig"; path = "Target Support Files/Pods-Notesnook-Make Note/Pods-Notesnook-Make Note.release.xcconfig"; sourceTree = "<group>"; };
|
||||
4B679E87FDFB1312CAD6CF45 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = Notesnook/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
4B679E87FDFB1312CAD6CF45 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = Notesnook/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
4BD34AE0C0FD2416E48803B8 /* libPods-Notesnook.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Notesnook.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4C4AF691C324D95337F2FB0A /* libPods-Make Note.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Make Note.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6510E6D62877215700DACAA9 /* build.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = build.bundle; path = "../../../../packages/editor-mobile/build.bundle"; sourceTree = "<group>"; };
|
||||
@@ -124,6 +124,7 @@
|
||||
6529D2B0257B4A2900B49BC3 /* NotesnookDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = NotesnookDebug.entitlements; path = Notesnook/NotesnookDebug.entitlements; sourceTree = "<group>"; };
|
||||
656835802BB29A8300144BAB /* OpenSans-Italic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "OpenSans-Italic.ttf"; path = "../../../../packages/editor-mobile/public/fonts/OpenSans-Italic.ttf"; sourceTree = "<group>"; };
|
||||
6593E4A2281C345400492C50 /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = Notesnook/AppDelegate.mm; sourceTree = "<group>"; };
|
||||
6594DDF22CD8BFE8007F5EC2 /* BetterTrigram.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = BetterTrigram.xcframework; sourceTree = "<group>"; };
|
||||
659BE46625E11A5100E05671 /* notesnook-text.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "notesnook-text.png"; path = "Notesnook/Images.xcassets/notesnook-text.png"; sourceTree = "<group>"; };
|
||||
65A7F34F255689AD00699170 /* Notesnook.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Notesnook.entitlements; path = Notesnook/Notesnook.entitlements; sourceTree = "<group>"; };
|
||||
65AA857725E6DDEC00772A01 /* NotesWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotesWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -152,7 +153,7 @@
|
||||
88211800FA8BF60638327ADE /* Pods-Make Note.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Make Note.debug.xcconfig"; path = "Target Support Files/Pods-Make Note/Pods-Make Note.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
A03E3F5851D27269540E147C /* libPods-Notesnook-tvOSTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Notesnook-tvOSTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A84F3F0D50641D1CD4569B0E /* Pods-Make Note.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Make Note.release.xcconfig"; path = "Target Support Files/Pods-Make Note/Pods-Make Note.release.xcconfig"; sourceTree = "<group>"; };
|
||||
B5216B66C0B4A91C0A69128B /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = Notesnook/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
B5216B66C0B4A91C0A69128B /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = Notesnook/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
B9989E5C777BB11343A62D09 /* Pods-Notesnook-NotesnookTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Notesnook-NotesnookTests.debug.xcconfig"; path = "Target Support Files/Pods-Notesnook-NotesnookTests/Pods-Notesnook-NotesnookTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
D1710CA05FED221CC56D2BE1 /* Pods-Notesnook-tvOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Notesnook-tvOSTests.release.xcconfig"; path = "Target Support Files/Pods-Notesnook-tvOSTests/Pods-Notesnook-tvOSTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
@@ -255,6 +256,7 @@
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6594DDF22CD8BFE8007F5EC2 /* BetterTrigram.xcframework */,
|
||||
6515C42E2580AA2F00E83E39 /* StoreKit.framework */,
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||
ED2971642150620600B7C4FE /* JavaScriptCore.framework */,
|
||||
@@ -1061,7 +1063,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2115;
|
||||
CURRENT_PROJECT_VERSION = 2118;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
ENABLE_BITCODE = NO;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1135,7 +1137,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.0.18;
|
||||
MARKETING_VERSION = 3.0.21;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -1166,7 +1168,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 2115;
|
||||
CURRENT_PROJECT_VERSION = 2118;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1240,7 +1242,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.0.18;
|
||||
MARKETING_VERSION = 3.0.21;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
@@ -1399,7 +1401,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2115;
|
||||
CURRENT_PROJECT_VERSION = 2118;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1411,7 +1413,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.0.18;
|
||||
MARKETING_VERSION = 3.0.21;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
|
||||
@@ -1442,7 +1444,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 2115;
|
||||
CURRENT_PROJECT_VERSION = 2118;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
|
||||
@@ -1455,7 +1457,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.0.18;
|
||||
MARKETING_VERSION = 3.0.21;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -1485,7 +1487,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2115;
|
||||
CURRENT_PROJECT_VERSION = 2118;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1559,7 +1561,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.0.18;
|
||||
MARKETING_VERSION = 3.0.21;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
|
||||
@@ -1590,7 +1592,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 2115;
|
||||
CURRENT_PROJECT_VERSION = 2118;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
|
||||
@@ -1665,7 +1667,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.0.18;
|
||||
MARKETING_VERSION = 3.0.21;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -1742,10 +1744,7 @@
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CFLAGS = "$(inherited)";
|
||||
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
" ",
|
||||
);
|
||||
OTHER_LDFLAGS = "$(inherited) ";
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
USE_HERMES = true;
|
||||
@@ -1809,10 +1808,7 @@
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
OTHER_CFLAGS = "$(inherited)";
|
||||
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
" ",
|
||||
);
|
||||
OTHER_LDFLAGS = "$(inherited) ";
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
USE_HERMES = true;
|
||||
|
||||
@@ -113,7 +113,7 @@ post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
if target.name == "react-native-quick-sqlite" then
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = 'SQLITE_ENABLE_FTS5=1 SQLITE3MC_OMIT_AES_HARDWARE_SUPPORT=1 HAVE_CIPHER_AES_128_CBC=0 HAVE_CIPHER_AES_256_CBC=0 HAVE_CIPHER_SQLCIPHER=0 HAVE_CIPHER_RC4=0 HAVE_CIPHER_CHACHA20=1 SQLITE_OMIT_PROGRESS_CALLBACK=1 SQLITE_MAX_EXPR_DEPTH=0 SQLITE_OMIT_DEPRECATED=1 SQLITE_LIKE_DOESNT_MATCH_BLOBS=1 SQLITE_DQS=0 SQLITE_DEFAULT_MEMSTATUS=0 SQLITE_USE_ALLOCA=1'
|
||||
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = 'SQLITE_CORE=1 SQLITE_ENABLE_FTS5=1 SQLITE3MC_OMIT_AES_HARDWARE_SUPPORT=1 HAVE_CIPHER_AES_128_CBC=0 HAVE_CIPHER_AES_256_CBC=0 HAVE_CIPHER_SQLCIPHER=0 HAVE_CIPHER_RC4=0 HAVE_CIPHER_CHACHA20=1 SQLITE_OMIT_PROGRESS_CALLBACK=1 SQLITE_MAX_EXPR_DEPTH=0 SQLITE_OMIT_DEPRECATED=1 SQLITE_LIKE_DOESNT_MATCH_BLOBS=1 SQLITE_DQS=0 SQLITE_DEFAULT_MEMSTATUS=0 SQLITE_USE_ALLOCA=1'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1017,9 +1017,9 @@ PODS:
|
||||
- react-native-screenguard (1.0.0):
|
||||
- React-Core
|
||||
- SDWebImage (~> 5.11.1)
|
||||
- react-native-share-extension (3.0.0):
|
||||
- react-native-share-extension (2.6.0):
|
||||
- React
|
||||
- react-native-sodium (1.5.4):
|
||||
- react-native-sodium (1.5.6):
|
||||
- React
|
||||
- react-native-theme-switch-animation (0.6.0):
|
||||
- DoubleConversion
|
||||
@@ -1303,7 +1303,7 @@ PODS:
|
||||
- React-Core
|
||||
- RNCMaskedView (0.2.9):
|
||||
- React-Core
|
||||
- RNDateTimePicker (6.6.0):
|
||||
- RNDateTimePicker (8.2.0):
|
||||
- React-Core
|
||||
- RNDeviceInfo (8.7.1):
|
||||
- React-Core
|
||||
@@ -1849,11 +1849,11 @@ SPEC CHECKSUMS:
|
||||
react-native-notification-sounds: da78c828fe1bcbb92d8b505d5261890ed315ff39
|
||||
react-native-orientation: f1caf84d65f1a4fd4511a18f2b924e634ad7a628
|
||||
react-native-pdf: 33c622cbdf776a649929e8b9d1ce2d313347c4fa
|
||||
react-native-quick-sqlite: e0e23b749382a85e4b57146f753de737a6c3a9e1
|
||||
react-native-quick-sqlite: 18e1367c34faac90e37f6eb3e78c196e9b674b5d
|
||||
react-native-safe-area-context: b7daa1a8df36095a032dff095a1ea8963cb48371
|
||||
react-native-screenguard: 8b36a3df84c76cd2b82c477f71c26fa1c8cc14a0
|
||||
react-native-share-extension: faed334b1ddf165f1e576fcabd3dc1c9e748bfa9
|
||||
react-native-sodium: 955bb0dc3ea05f8ea06d5e96cb89d1be7b5d7681
|
||||
react-native-share-extension: 25437eb1039f7409be6e80a7edf8d02b42e1dc99
|
||||
react-native-sodium: 605c1523ec8ff5fbff5e9e7769bbacceb571a3c6
|
||||
react-native-theme-switch-animation: d3eb50365a3829ce5572628888fa514752703f61
|
||||
react-native-webview: 553abd09f58e340fdc7746c9e2ae096839e99911
|
||||
React-nativeconfig: ba9a2e54e2f0882cf7882698825052793ed4c851
|
||||
@@ -1884,7 +1884,7 @@ SPEC CHECKSUMS:
|
||||
RNCCheckbox: 43bcc6493611468af0e19f19f029dab3da8561c4
|
||||
RNCClipboard: 3f0451a8100393908bea5c5c5b16f96d45f30bfc
|
||||
RNCMaskedView: 949696f25ec596bfc697fc88e6f95cf0c79669b6
|
||||
RNDateTimePicker: 818672afa85519722533d017b832ed09539d9ddb
|
||||
RNDateTimePicker: 40ffda97d071a98a10fdca4fa97e3977102ccd14
|
||||
RNDeviceInfo: aad3c663b25752a52bf8fce93f2354001dd185aa
|
||||
RNExitApp: c4e052df2568b43bec8a37c7cd61194d4cfee2c3
|
||||
RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592
|
||||
@@ -1901,7 +1901,7 @@ SPEC CHECKSUMS:
|
||||
RNShare: a5dc3b9c53ddc73e155b8cd9a94c70c91913c43c
|
||||
RNSVG: d7d7bc8229af3842c9cfc3a723c815a52cdd1105
|
||||
RNTooltips: 5424d4bf0b3d441104127943b1115cc7f0616b1f
|
||||
RNZipArchive: 68a0c6db4b1c103f846f1559622050df254a3ade
|
||||
RNZipArchive: 9d90367b1573903b5561a8c0b911e5cc12626e74
|
||||
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
|
||||
SexyTooltip: 5c9b4dec52bfb317938cb0488efd9da3717bb6fd
|
||||
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
|
||||
@@ -1911,6 +1911,6 @@ SPEC CHECKSUMS:
|
||||
toolbar-android: 2a73856e98b750d7e71ce4644d3f41cc98211719
|
||||
Yoga: 2246eea72aaf1b816a68a35e6e4b74563653ae09
|
||||
|
||||
PODFILE CHECKSUM: 98f600b3236e314680588e77819982573fb4d9f7
|
||||
PODFILE CHECKSUM: aa07aca16c1d92394d8ce12f2c5fcaa8a3ae4997
|
||||
|
||||
COCOAPODS: 1.15.2
|
||||
|
||||
@@ -10,13 +10,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ammarahmed/notifee-react-native": "7.4.7",
|
||||
"@ammarahmed/react-native-share-extension": "^3.0.0",
|
||||
"@ammarahmed/react-native-sodium": "1.5.4",
|
||||
"@bam.tech/react-native-image-resizer": "3.0.5",
|
||||
"@callstack/repack": "^4.1.1",
|
||||
"@react-native-clipboard/clipboard": "^1.9.0",
|
||||
"@react-native-community/checkbox": "^0.5.8",
|
||||
"@react-native-community/datetimepicker": "6.6.0",
|
||||
"@react-native-community/netinfo": "^9.3.7",
|
||||
"@react-native-community/toolbar-android": "^0.2.1",
|
||||
"@react-native-masked-view/masked-view": "^0.2.6",
|
||||
@@ -52,7 +49,6 @@
|
||||
"react-native-iap": "12.15.1",
|
||||
"react-native-in-app-review": "4.3.3",
|
||||
"react-native-keychain": "4.0.5",
|
||||
"react-native-mmkv-storage": "^0.10.2",
|
||||
"react-native-modal-datetime-picker": "14.0.0",
|
||||
"react-native-navigation-bar-color": "2.0.2",
|
||||
"react-native-notification-sounds": "0.5.5",
|
||||
@@ -73,7 +69,12 @@
|
||||
"react-native-url-polyfill": "^2.0.0",
|
||||
"react-native-screenguard": "^1.0.0",
|
||||
"@formatjs/intl-locale": "4.0.0",
|
||||
"@formatjs/intl-pluralrules": "5.2.14"
|
||||
"@formatjs/intl-pluralrules": "5.2.14",
|
||||
"detox": "^20.27.6",
|
||||
"@ammarahmed/react-native-share-extension": "^2.6.0",
|
||||
"@ammarahmed/react-native-sodium": "1.5.6",
|
||||
"react-native-mmkv-storage": "^0.10.2",
|
||||
"@react-native-community/datetimepicker": "^8.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
@@ -86,7 +87,6 @@
|
||||
"@react-native/metro-config": "0.74.86",
|
||||
"@tsconfig/react-native": "^3.0.2",
|
||||
"@types/html-to-text": "^8.0.1",
|
||||
"@types/jest": "^29.2.1",
|
||||
"@types/metro-config": "^0.76.3",
|
||||
"@types/react": "^18.2.6",
|
||||
"@types/react-native": "^0.69.1",
|
||||
@@ -98,19 +98,13 @@
|
||||
"babel-loader": "^8.2.5",
|
||||
"babel-plugin-module-resolver": "^4.1.0",
|
||||
"babel-plugin-transform-remove-console": "6.9.4",
|
||||
"detox": "^20.11.2",
|
||||
"eslint": "^8.19.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-react": "^7.28.0",
|
||||
"eslint-plugin-react-native": "^4.0.0",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"expect": "^29.6.2",
|
||||
"jest": "^29.6.3",
|
||||
"jest-circus": "^29.6.2",
|
||||
"jest-image-snapshot": "^6.2.0",
|
||||
"@react-native/babel-preset": "0.74.86",
|
||||
"pixelmatch": "^5.3.0",
|
||||
"prettier": "2.8.8",
|
||||
"react-native-actions-shortcuts": "^1.0.1",
|
||||
"react-native-bundle-visualizer": "^3.1.1",
|
||||
@@ -118,10 +112,16 @@
|
||||
"react-refresh": "0.14.0",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"terser-webpack-plugin": "^5.3.5",
|
||||
"ts-jest": "^29.1.1",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack": "^5.88.2",
|
||||
"metro-react-native-babel-preset": "0.77.0",
|
||||
"acorn-import-attributes": "1.9.5"
|
||||
"acorn-import-attributes": "1.9.5",
|
||||
"expect": "^29.7.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-circus": "^29.7.0",
|
||||
"jest-image-snapshot": "^6.4.0",
|
||||
"ts-jest": "^29.2.5",
|
||||
"pixelmatch": "^6.0.0",
|
||||
"@types/jest": "^29.5.14"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ const PerformanceNow =
|
||||
(global.performance && global.performance.now) ||
|
||||
global.performanceNow ||
|
||||
global.nativePerformanceNow || (() => { try {
|
||||
var now = require('fbjs/lib/performanceNow')
|
||||
var now = __DEV__ ? require('fbjs/lib/performanceNow') : () => Date.now()
|
||||
} finally { return now }})();
|
||||
|
||||
const DEFAULT_LABEL = 'default';
|
||||
|
||||
@@ -217,6 +217,7 @@ module.exports = (env) => {
|
||||
/node_modules(.*[/\\])+@tanstack[/\\]react-query/,
|
||||
/node_modules(.*[/\\])+@trpc[/\\]react-query/,
|
||||
/node_modules(.*[/\\])+katex/,
|
||||
/node_modules(.*[/\\])+mime/,
|
||||
/node_modules(.*[/\\])+@notesnook[/\\]core/,
|
||||
/node_modules(.*[/\\])+whatwg-url-without-unicode/,
|
||||
/node_modules(.*[/\\])+whatwg-url/,
|
||||
|
||||
1035
apps/mobile/package-lock.json
generated
1035
apps/mobile/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "3.0.18",
|
||||
"version": "3.0.21",
|
||||
"private": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"workspaces": [
|
||||
@@ -46,7 +46,6 @@
|
||||
"diffblazer": "^1.0.1",
|
||||
"react": "18.2.0",
|
||||
"react-native": "0.74.5",
|
||||
"react-native-actions-sheet": "^0.9.7",
|
||||
"react-native-mmkv-storage": "^0.10.2"
|
||||
"react-native-actions-sheet": "^0.9.7"
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user