From 4a5ad7b677bd3df89c97459d7557461151a4b06c Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sat, 25 Feb 2023 21:02:56 +0700 Subject: [PATCH 01/21] added system tray --- src-tauri/Cargo.lock | 36 ++++++++++++++++++++++++++++++++++++ src-tauri/Cargo.toml | 2 +- src-tauri/icons/icon.png | Bin 162394 -> 107992 bytes src-tauri/src/main.rs | 5 ++++- src-tauri/tauri.conf.json | 12 +++++------- 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 46d8f26f..cd1ac1ec 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1393,6 +1393,30 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "libappindicator" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2d3cb96d092b4824cb306c9e544c856a4cb6210c1081945187f7f1924b47e8" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b3b6681973cea8cc3bce7391e6d7d5502720b80a581c9a95c9cbaf592826aa" +dependencies = [ + "gtk-sys", + "libloading", + "once_cell", +] + [[package]] name = "libc" version = "0.2.139" @@ -1408,6 +1432,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + [[package]] name = "libsqlite3-sys" version = "0.24.2" @@ -2917,6 +2951,7 @@ dependencies = [ "core-foundation", "core-graphics", "crossbeam-channel", + "dirs-next", "dispatch", "gdk", "gdk-pixbuf", @@ -2930,6 +2965,7 @@ dependencies = [ "instant", "jni", "lazy_static", + "libappindicator", "libc", "log", "ndk", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 785e2ee2..760eeb08 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -16,7 +16,7 @@ tauri-build = { version = "1.2", features = [] } [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.2", features = ["clipboard-all", "notification-all", "shell-open", "window-start-dragging"] } +tauri = { version = "1.2", features = ["clipboard-all", "notification-all", "shell-open", "system-tray", "window-start-dragging"] } webpage = "1.5.0" [dependencies.tauri-plugin-sql] diff --git a/src-tauri/icons/icon.png b/src-tauri/icons/icon.png index a23cdeafe0a75f6982a24aa54c10c41ad51cdb3c..ac86aaaea17559989d5db6b5f861a756c4156d72 100644 GIT binary patch literal 107992 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

ti33hv>b7mtp(PbOC;P(O@n1OGrM2@y*9 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

nr34+d0x{>0_0t?dPTWV-q_{K#DjuLIs! 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 ^wE_AIhT{ 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 W@W3M^&AK57c&RFCDwN8Z2L3;kdI)C# diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 38c406f3..0763c0b3 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -9,7 +9,7 @@ extern crate objc; use std::time::Duration; -use tauri::{Manager, WindowEvent}; +use tauri::{Manager, WindowEvent, SystemTray}; use webpage::{Webpage, WebpageOptions}; use window_ext::WindowExt; @@ -49,6 +49,8 @@ async fn opengraph(url: String) -> OpenGraphResponse { } fn main() { + let tray = SystemTray::new(); + tauri::Builder::default() .setup(|app| { let main_window = app.get_window("main").unwrap(); @@ -57,6 +59,7 @@ fn main() { Ok(()) }) + .system_tray(tray) .invoke_handler(tauri::generate_handler![opengraph]) .plugin(tauri_plugin_sql::Builder::default().build()) .on_window_event(|e| { diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 5a489f2f..96b62eb9 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -37,13 +37,7 @@ "depends": [] }, "externalBin": [], - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], + "icon": ["icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"], "identifier": "com.uselume.xyz", "longDescription": "", "macOS": { @@ -68,6 +62,10 @@ "updater": { "active": false }, + "systemTray": { + "iconPath": "icons/icon.png", + "iconAsTemplate": true + }, "windows": [ { "theme": "Dark", From a2fcb12eef65bb1de346f6c24b02b7d8dc064417 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sun, 26 Feb 2023 09:01:19 +0700 Subject: [PATCH 02/21] moved default table migration to rust --- package.json | 4 +- pnpm-lock.yaml | 38 ++--- src-tauri/Cargo.lock | 132 +----------------- src-tauri/Cargo.toml | 3 +- .../20230226004139_create_tables.sql | 40 ++++++ src-tauri/src/main.rs | 54 ++----- src/pages/index.tsx | 90 +++++------- 7 files changed, 116 insertions(+), 245 deletions(-) create mode 100644 src-tauri/migrations/20230226004139_create_tables.sql diff --git a/package.json b/package.json index 39897477..22196a3c 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "devDependencies": { "@tailwindcss/typography": "^0.5.9", "@tauri-apps/cli": "^1.2.3", - "@trivago/prettier-plugin-sort-imports": "^4.1.0", + "@trivago/prettier-plugin-sort-imports": "^4.1.1", "@types/node": "^18.14.1", "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", @@ -55,7 +55,7 @@ "eslint-config-prettier": "^8.6.0", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", - "husky": "^8.0.0", + "husky": "^8.0.3", "lint-staged": "^13.1.2", "postcss": "^8.4.21", "prettier": "^2.8.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fc513b5c..b13df7b0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,7 +9,7 @@ specifiers: '@tailwindcss/typography': ^0.5.9 '@tauri-apps/api': ^1.2.0 '@tauri-apps/cli': ^1.2.3 - '@trivago/prettier-plugin-sort-imports': ^4.1.0 + '@trivago/prettier-plugin-sort-imports': ^4.1.1 '@types/node': ^18.14.1 '@types/react': ^18.0.28 '@types/react-dom': ^18.0.11 @@ -27,7 +27,7 @@ specifiers: eslint-plugin-react: ^7.32.2 eslint-plugin-react-hooks: ^4.6.0 framer-motion: ^9.1.7 - husky: ^8.0.0 + husky: ^8.0.3 lint-staged: ^13.1.2 moment: ^2.29.4 nanostores: ^0.7.4 @@ -82,7 +82,7 @@ dependencies: devDependencies: '@tailwindcss/typography': 0.5.9_tailwindcss@3.2.7 '@tauri-apps/cli': 1.2.3 - '@trivago/prettier-plugin-sort-imports': 4.1.0_prettier@2.8.4 + '@trivago/prettier-plugin-sort-imports': 4.1.1_prettier@2.8.4 '@types/node': 18.14.1 '@types/react': 18.0.28 '@types/react-dom': 18.0.11 @@ -99,7 +99,7 @@ devDependencies: lint-staged: 13.1.2 postcss: 8.4.21 prettier: 2.8.4 - prettier-plugin-tailwindcss: 0.2.3_3p4xqifn6m4d44r76wgcnqfi3i + prettier-plugin-tailwindcss: 0.2.3_zmkqdpv3ldc45e6wei6qtrbrca prop-types: 15.8.1 tailwindcss: 3.2.7_postcss@8.4.21 typescript: 4.9.5 @@ -1134,8 +1134,8 @@ packages: '@tauri-apps/cli-win32-x64-msvc': 1.2.3 dev: true - /@trivago/prettier-plugin-sort-imports/4.1.0_prettier@2.8.4: - resolution: { integrity: sha512-aTr6QPFaPAAzPRFn9yWB/9yKi3ZAFqfGpxIGLPWuQfYJFGUed+W3KKwxntsoCiNvNE2iuKOg6haMo5KG8WXltg== } + /@trivago/prettier-plugin-sort-imports/4.1.1_prettier@2.8.4: + resolution: { integrity: sha512-dQ2r2uzNr1x6pJsuh/8x0IRA3CBUB+pWEW3J/7N98axqt7SQSm+2fy0FLNXvXGg77xEDC7KHxJlHfLYyi7PDcw== } peerDependencies: '@vue/compiler-sfc': 3.x prettier: 2.x @@ -1609,7 +1609,7 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.21.5 - caniuse-lite: 1.0.30001457 + caniuse-lite: 1.0.30001458 fraction.js: 4.2.0 normalize-range: 0.1.2 picocolors: 1.0.0 @@ -1714,8 +1714,8 @@ packages: engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } hasBin: true dependencies: - caniuse-lite: 1.0.30001457 - electron-to-chromium: 1.4.310 + caniuse-lite: 1.0.30001458 + electron-to-chromium: 1.4.311 node-releases: 2.0.10 update-browserslist-db: 1.0.10_browserslist@4.21.5 @@ -1736,8 +1736,8 @@ packages: engines: { node: '>= 6' } dev: true - /caniuse-lite/1.0.30001457: - resolution: { integrity: sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA== } + /caniuse-lite/1.0.30001458: + resolution: { integrity: sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w== } /ccount/2.0.1: resolution: { integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== } @@ -2030,8 +2030,8 @@ packages: resolution: { integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== } dev: true - /electron-to-chromium/1.4.310: - resolution: { integrity: sha512-/xlATgfwkm5uDDwLw5nt/MNEf7c1oazLURMZLy39vOioGYyYzLWIDT8fZMJak6qTiAJ7udFTy7JG7ziyjNutiA== } + /electron-to-chromium/1.4.311: + resolution: { integrity: sha512-RoDlZufvrtr2Nx3Yx5MB8jX3aHIxm8nRWPJm3yVvyHmyKaRvn90RjzB6hNnt0AkhS3IInJdyRfQb4mWhPvUjVw== } /emoji-regex/8.0.0: resolution: { integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== } @@ -2264,7 +2264,7 @@ packages: object.values: 1.1.6 resolve: 1.22.1 semver: 6.3.0 - tsconfig-paths: 3.14.1 + tsconfig-paths: 3.14.2 transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -3923,7 +3923,7 @@ packages: dependencies: '@next/env': 13.2.1 '@swc/helpers': 0.4.14 - caniuse-lite: 1.0.30001457 + caniuse-lite: 1.0.30001458 postcss: 8.4.14 react: 18.2.0 react-dom: 18.2.0_react@18.2.0 @@ -4336,7 +4336,7 @@ packages: engines: { node: '>= 0.8.0' } dev: true - /prettier-plugin-tailwindcss/0.2.3_3p4xqifn6m4d44r76wgcnqfi3i: + /prettier-plugin-tailwindcss/0.2.3_zmkqdpv3ldc45e6wei6qtrbrca: resolution: { integrity: sha512-s2N5Dh7Ao5KTV1mao5ZBnn8EKtUcDPJEkGViZIjI0Ij9TTI5zgTz4IHOxW33jOdjHKa8CSjM88scelUiC5TNRQ== } engines: { node: '>=12.17.0' } peerDependencies: @@ -4388,7 +4388,7 @@ packages: prettier-plugin-twig-melody: optional: true dependencies: - '@trivago/prettier-plugin-sort-imports': 4.1.0_prettier@2.8.4 + '@trivago/prettier-plugin-sort-imports': 4.1.1_prettier@2.8.4 prettier: 2.8.4 dev: true @@ -5146,8 +5146,8 @@ packages: resolution: { integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== } dev: false - /tsconfig-paths/3.14.1: - resolution: { integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== } + /tsconfig-paths/3.14.2: + resolution: { integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== } dependencies: '@types/json5': 0.0.29 json5: 1.0.2 diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index cd1ac1ec..91cbe2c4 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -465,36 +465,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" -[[package]] -name = "curl" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" -dependencies = [ - "curl-sys", - "libc", - "openssl-probe", - "openssl-sys", - "schannel", - "socket2", - "winapi", -] - -[[package]] -name = "curl-sys" -version = "0.4.59+curl-7.86.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cfce34829f448b08f55b7db6d0009e23e2e86a34e8c2b366269bf5799b4a407" -dependencies = [ - "cc", - "libc", - "libz-sys", - "openssl-sys", - "pkg-config", - "vcpkg", - "winapi", -] - [[package]] name = "darling" version = "0.13.4" @@ -1453,18 +1423,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "libz-sys" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "line-wrap" version = "0.1.1" @@ -1519,7 +1477,6 @@ dependencies = [ "tauri", "tauri-build", "tauri-plugin-sql", - "webpage", ] [[package]] @@ -1538,7 +1495,7 @@ dependencies = [ "dirs-next", "objc-foundation", "objc_id", - "time 0.3.17", + "time", ] [[package]] @@ -1564,18 +1521,6 @@ dependencies = [ "tendril", ] -[[package]] -name = "markup5ever_rcdom" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f015da43bcd8d4f144559a3423f4591d69b8ce0652c905374da7205df336ae2b" -dependencies = [ - "html5ever", - "markup5ever", - "tendril", - "xml5ever", -] - [[package]] name = "matchers" version = "0.1.0" @@ -1829,25 +1774,6 @@ dependencies = [ "windows-sys 0.42.0", ] -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" -dependencies = [ - "autocfg", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -2102,7 +2028,7 @@ dependencies = [ "line-wrap", "quick-xml 0.26.0", "serde", - "time 0.3.17", + "time", ] [[package]] @@ -2455,15 +2381,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "schannel" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" -dependencies = [ - "windows-sys 0.42.0", -] - [[package]] name = "scoped-tls" version = "1.0.1" @@ -3083,7 +3000,7 @@ dependencies = [ "sha2", "tauri-utils", "thiserror", - "time 0.3.17", + "time", "uuid 1.3.0", "walkdir", ] @@ -3105,7 +3022,7 @@ dependencies = [ [[package]] name = "tauri-plugin-sql" version = "0.1.0" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=fix/sql-types#f1a7136b1e0b145ea5c5fb9d336cac0cb1dc6265" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=dev#8f34eb83e4f9a8c72fd3823a066c94f861f2d021" dependencies = [ "futures", "log", @@ -3256,17 +3173,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.3.17" @@ -3576,12 +3482,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -3711,18 +3611,6 @@ dependencies = [ "system-deps 6.0.3", ] -[[package]] -name = "webpage" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d261bbae112cb48a95d3cc9e8873a4e40933bc54ae8eddc1eef70e952dd3b232" -dependencies = [ - "curl", - "html5ever", - "markup5ever_rcdom", - "serde_json", -] - [[package]] name = "webpki" version = "0.22.0" @@ -4087,15 +3975,3 @@ checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" dependencies = [ "libc", ] - -[[package]] -name = "xml5ever" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9234163818fd8e2418fcde330655e757900d4236acd8cc70fef345ef91f6d865" -dependencies = [ - "log", - "mac", - "markup5ever", - "time 0.1.45", -] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 760eeb08..7818d44b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -17,11 +17,10 @@ tauri-build = { version = "1.2", features = [] } serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.2", features = ["clipboard-all", "notification-all", "shell-open", "system-tray", "window-start-dragging"] } -webpage = "1.5.0" [dependencies.tauri-plugin-sql] git = "https://github.com/tauri-apps/plugins-workspace" -branch = "fix/sql-types" +branch = "dev" features = ["sqlite"] [target.'cfg(target_os = "macos")'.dependencies] diff --git a/src-tauri/migrations/20230226004139_create_tables.sql b/src-tauri/migrations/20230226004139_create_tables.sql new file mode 100644 index 00000000..22955e5a --- /dev/null +++ b/src-tauri/migrations/20230226004139_create_tables.sql @@ -0,0 +1,40 @@ +-- Add migration script here +-- create accounts +CREATE TABLE + accounts ( + id TEXT PRIMARY KEY, + privkey TEXT NOT NULL, + npub TEXT NOT NULL, + nsec TEXT NOT NULL, + metadata JSON + ); + +-- create follows +CREATE TABLE + follows ( + id INTEGER PRIMARY KEY, + pubkey TEXT NOT NULL, + account TEXT NOT NULL, + metadata JSON + ); + +-- create index for pubkey in follows +CREATE UNIQUE INDEX index_pubkey ON follows (pubkey); + +-- create cache profiles +CREATE TABLE + cache_profiles ( + id TEXT PRIMARY KEY, + metadata JSON, + created_at TEXT, + updated_at TEXT + ); + +-- create cache notes +CREATE TABLE + cache_notes ( + id TEXT PRIMARY KEY, + note JSON, + created_at TEXT, + updated_at TEXT + ); \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 0763c0b3..4b0c9868 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -7,47 +7,12 @@ #[macro_use] extern crate objc; -use std::time::Duration; - -use tauri::{Manager, WindowEvent, SystemTray}; -use webpage::{Webpage, WebpageOptions}; +use tauri::{Manager, SystemTray, WindowEvent}; +use tauri_plugin_sql::{Migration, MigrationKind}; use window_ext::WindowExt; mod window_ext; -#[derive(serde::Serialize)] -struct OpenGraphResponse { - title: String, - description: String, - url: String, - image: String, -} - -async fn fetch_opengraph(url: String) -> OpenGraphResponse { - let options = WebpageOptions { - allow_insecure: false, - max_redirections: 3, - timeout: Duration::from_secs(30), - useragent: "lume - desktop app".to_string(), - ..Default::default() - }; - let result = Webpage::from_url(&url, options).expect("Could not read from URL"); - let html = result.html; - - return OpenGraphResponse { - title: html.opengraph.properties["title"].to_string(), - description: html.opengraph.properties["description"].to_string(), - url: html.opengraph.properties["url"].to_string(), - image: html.opengraph.images[0].url.to_string(), - }; -} - -#[tauri::command] -async fn opengraph(url: String) -> OpenGraphResponse { - let result = fetch_opengraph(url).await; - return result; -} - fn main() { let tray = SystemTray::new(); @@ -60,8 +25,19 @@ fn main() { Ok(()) }) .system_tray(tray) - .invoke_handler(tauri::generate_handler![opengraph]) - .plugin(tauri_plugin_sql::Builder::default().build()) + .plugin( + tauri_plugin_sql::Builder::default() + .add_migrations( + "sqlite:lume.db", + vec![Migration { + version: 1, + description: "create default tables", + sql: include_str!("../migrations/20230226004139_create_tables.sql"), + kind: MigrationKind::Up, + }], + ) + .build(), + ) .on_window_event(|e| { let apply_offset = || { let win = e.window(); diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 49db3ffb..cd066c79 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -19,24 +19,7 @@ export default function Page() { const router = useRouter(); const [loading, setLoading] = useState(true); - const initDB = useCallback(async () => { - if (db) { - await db.execute( - 'CREATE TABLE IF NOT EXISTS accounts (id INTEGER PRIMARY KEY, privkey TEXT NOT NULL, pubkey TEXT NOT NULL, npub TEXT, nsec TEXT, current INTEGER DEFAULT "0" NOT NULL, metadata JSON, UNIQUE(privkey));' - ); - await db.execute('CREATE TABLE IF NOT EXISTS follows (id INTEGER PRIMARY KEY, pubkey TEXT NOT NULL, account TEXT, UNIQUE(pubkey));'); - await db.execute( - 'CREATE TABLE IF NOT EXISTS note_reactions (id INTEGER PRIMARY KEY, reaction_id TEXT NOT NULL, e TEXT, p TEXT, UNIQUE(reaction_id));' - ); - await db.execute('CREATE TABLE IF NOT EXISTS note_replies (id INTEGER PRIMARY KEY, reply_id TEXT NOT NULL, e TEXT, p TEXT, UNIQUE(reply_id));'); - await db.execute('CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, event_id TEXT, event JSON, UNIQUE(event_id));'); - await db.execute('CREATE TABLE IF NOT EXISTS cache_profiles (id INTEGER PRIMARY KEY, pubkey TEXT, metadata JSON, UNIQUE(pubkey));'); - await db.execute('CREATE TABLE IF NOT EXISTS block_pubkeys (id INTEGER PRIMARY KEY, pubkey TEXT, UNIQUE(pubkey));'); - await db.close(); - } - }, []); - - const notification = useCallback(async () => { + const requestNotification = useCallback(async () => { // NOTE: notification don't work in dev mode (only affect MacOS) // ref: https://github.com/tauri-apps/tauri/issues/4965 let permissionGranted = await isPermissionGranted(); @@ -47,18 +30,18 @@ export default function Page() { if (permissionGranted) { sendNotification({ title: 'Lume', body: 'Nostr is awesome' }); } + + return permissionGranted; }, []); const getAccount = useCallback(async () => { - const db = await Database.load('sqlite:lume.db'); - const result = await db.select(`SELECT * FROM accounts WHERE current = "1" ORDER BY id ASC LIMIT 1`); + const result = await db.select(`SELECT id FROM accounts ASC LIMIT 1`); return result; }, []); const getFollows = useCallback(async (account) => { const arr = []; - const db = await Database.load('sqlite:lume.db'); const result: any = await db.select(`SELECT pubkey FROM follows WHERE account = "${account.pubkey}"`); result.forEach((item: { pubkey: string }) => { @@ -69,41 +52,38 @@ export default function Page() { }, []); // Explain: - // Step 1: check DB tables, if not exist then create new table. #TODO: move this function to Rust code - // Step 2: request allow notification from system - // Step 3: get first account. #TODO: get last used account instead (part of multi account feature) - // Step 4: get follows by account + // Step 1: request allow notification from system + // Step 2: get first account. #TODO: get last used account instead (part of multi account feature) + // Step 3: get follows by account useEffect(() => { - initDB() - .then(() => notification()) - .then(() => { - getAccount() - .then((res: any) => { - if (res.length === 0) { - setTimeout(() => { - setLoading(false); - router.push('/onboarding'); - }, 1500); - } else { - // store current user in localstorage - currentUser.set(res[0]); - getFollows(res[0]) - .then(async (res) => { - // store follows in localstorage - follows.set(res); - // redirect to newsfeed - setTimeout(() => { - setLoading(false); - router.push('/feed/following'); - }, 1500); - }) - .catch(console.error); - } - }) - .catch(console.error); - }) - .catch(console.error); - }, [getAccount, getFollows, initDB, notification, router]); + requestNotification().then(() => { + getAccount() + .then((res: any) => { + console.log(res); + if (res.length === 0) { + setTimeout(() => { + setLoading(false); + router.push('/onboarding'); + }, 1500); + } else { + // store current user in localstorage + currentUser.set(res[0]); + getFollows(res[0]) + .then(async (res) => { + // store follows in localstorage + follows.set(res); + // redirect to newsfeed + setTimeout(() => { + setLoading(false); + router.push('/feed/following'); + }, 1500); + }) + .catch(console.error); + } + }) + .catch(console.error); + }); + }, [getAccount, getFollows, requestNotification, router]); return (

From 3fbe6b398674efcc56de156e4cf164b085aa208c Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sun, 26 Feb 2023 11:19:18 +0700 Subject: [PATCH 03/21] fixed sql query --- src/components/note/atoms/user.tsx | 28 +++--------- src/pages/index.tsx | 5 +-- src/pages/onboarding/create.tsx | 57 +++++------------------- src/pages/onboarding/fetch-follows.tsx | 42 +++--------------- src/pages/onboarding/fetch-profile.tsx | 61 +++++++------------------- src/pages/onboarding/following.tsx | 57 +++++------------------- src/pages/onboarding/import.tsx | 30 +++---------- 7 files changed, 60 insertions(+), 220 deletions(-) diff --git a/src/components/note/atoms/user.tsx b/src/components/note/atoms/user.tsx index 632fe39d..44ae2d45 100644 --- a/src/components/note/atoms/user.tsx +++ b/src/components/note/atoms/user.tsx @@ -27,11 +27,7 @@ export const User = memo(function User({ pubkey, time }: { pubkey: string; time: const metadata: any = JSON.parse(rawMetadata.content); if (profile.picture === null || profile.name === null) { setProfile(metadata); - await db.execute( - `INSERT OR IGNORE INTO cache_profiles (pubkey, metadata) VALUES ("${pubkey}", '${JSON.stringify( - metadata - )}')` - ); + await db.execute(`INSERT OR IGNORE INTO cache_profiles (id, metadata) VALUES ("${pubkey}", '${JSON.stringify(metadata)}')`); } else { return; } @@ -42,9 +38,7 @@ export const User = memo(function User({ pubkey, time }: { pubkey: string; time: useEffect(() => { const initialProfile = async () => { - const result: any = await db.select( - `SELECT metadata FROM cache_profiles WHERE pubkey = "${pubkey}"` - ); + const result: any = await db.select(`SELECT metadata FROM cache_profiles WHERE id = "${pubkey}"`); db.close; return result; }; @@ -62,27 +56,15 @@ export const User = memo(function User({ pubkey, time }: { pubkey: string; time:
{profile.picture ? ( - + ) : ( - + )}
- - {profile.name ? profile.name : truncate(pubkey, 16, ' .... ')} - + {profile.name ? profile.name : truncate(pubkey, 16, ' .... ')} · {time} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index cd066c79..06993360 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -35,14 +35,14 @@ export default function Page() { }, []); const getAccount = useCallback(async () => { - const result = await db.select(`SELECT id FROM accounts ASC LIMIT 1`); + const result = await db.select(`SELECT * FROM accounts ASC LIMIT 1`); return result; }, []); const getFollows = useCallback(async (account) => { const arr = []; - const result: any = await db.select(`SELECT pubkey FROM follows WHERE account = "${account.pubkey}"`); + const result: any = await db.select(`SELECT pubkey FROM follows WHERE account = "${account.id}"`); result.forEach((item: { pubkey: string }) => { arr.push(item.pubkey); @@ -59,7 +59,6 @@ export default function Page() { requestNotification().then(() => { getAccount() .then((res: any) => { - console.log(res); if (res.length === 0) { setTimeout(() => { setLoading(false); diff --git a/src/pages/onboarding/create.tsx b/src/pages/onboarding/create.tsx index 2034edce..01043ce4 100644 --- a/src/pages/onboarding/create.tsx +++ b/src/pages/onboarding/create.tsx @@ -43,12 +43,8 @@ export default function Page() { const [privKey] = useState(() => generatePrivateKey()); const [name] = useState(() => uniqueNamesGenerator(config).toString()); - const [avatar] = useState( - () => defaultAvatars[Math.floor(Math.random() * defaultAvatars.length)] - ); - const [banner] = useState( - () => defaultBanners[Math.floor(Math.random() * defaultBanners.length)] - ); + const [avatar] = useState(() => defaultAvatars[Math.floor(Math.random() * defaultAvatars.length)]); + const [banner] = useState(() => defaultBanners[Math.floor(Math.random() * defaultBanners.length)]); const pubKey = getPublicKey(privKey); const npub = nip19.npubEncode(pubKey); @@ -81,9 +77,7 @@ export default function Page() { // save account to database const db = await Database.load('sqlite:lume.db'); await db.execute( - `INSERT INTO accounts (privkey, pubkey, npub, nsec, current, metadata) VALUES ("${privKey}", "${pubKey}", "${npub}", "${nsec}", "1", '${JSON.stringify( - data - )}')` + `INSERT INTO accounts (id, privkey, npub, nsec, metadata) VALUES ("${pubKey}", "${privKey}", "${npub}", "${nsec}", '${JSON.stringify(data)}')` ); await db.close(); @@ -115,14 +109,12 @@ export default function Page() {
{/* spacer */}
- + Create new key - Lume will generate key with default profile for you, you can edit it later, and please - store your key safely so you can restore your account or use other client + Lume will generate key with default profile for you, you can edit it later, and please store your key safely so you can restore your + account or use other client
@@ -145,9 +137,7 @@ export default function Page() { value={nsec} className="relative w-full rounded-lg border border-black/5 px-3.5 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-600" /> -
- +
- +
@@ -193,18 +176,8 @@ export default function Page() {
{loading === true ? ( - - + + > - | ReactFragment - | ReactPortal + page: string | number | boolean | ReactElement> | ReactFragment | ReactPortal ) { return ( diff --git a/src/pages/onboarding/fetch-follows.tsx b/src/pages/onboarding/fetch-follows.tsx index 2088f7f2..335aea3f 100644 --- a/src/pages/onboarding/fetch-follows.tsx +++ b/src/pages/onboarding/fetch-follows.tsx @@ -5,14 +5,7 @@ import OnboardingLayout from '@layouts/onboardingLayout'; import { motion } from 'framer-motion'; import { useRouter } from 'next/router'; import { useNostrEvents } from 'nostr-react'; -import { - JSXElementConstructor, - ReactElement, - ReactFragment, - ReactPortal, - useEffect, - useState, -} from 'react'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useEffect, useState } from 'react'; import Database from 'tauri-plugin-sql-api'; export default function Page() { @@ -44,9 +37,7 @@ export default function Page() { const db = await Database.load('sqlite:lume.db'); follows.forEach(async (item) => { if (item) { - await db.execute( - `INSERT OR IGNORE INTO follows (pubkey, account) VALUES ("${item[1]}", "${pubkey}")` - ); + await db.execute(`INSERT OR IGNORE INTO follows (pubkey, account) VALUES ("${item[1]}", "${pubkey}")`); } }); }; @@ -68,32 +59,19 @@ export default function Page() {
{/* spacer */}
- + Fetching your follows... - Not only profile, every nostr client can sync your follows list when you move to a new - client, so please keep your key safely (again) + Not only profile, every nostr client can sync your follows list when you move to a new client, so please keep your key safely (again)
{loading === true ? ( - - + + > - | ReactFragment - | ReactPortal + page: string | number | boolean | ReactElement> | ReactFragment | ReactPortal ) { return ( diff --git a/src/pages/onboarding/fetch-profile.tsx b/src/pages/onboarding/fetch-profile.tsx index fc3c5d54..031e17f0 100644 --- a/src/pages/onboarding/fetch-profile.tsx +++ b/src/pages/onboarding/fetch-profile.tsx @@ -6,14 +6,7 @@ import { motion } from 'framer-motion'; import { useRouter } from 'next/router'; import { useNostrEvents } from 'nostr-react'; import { getPublicKey, nip19 } from 'nostr-tools'; -import { - JSXElementConstructor, - ReactElement, - ReactFragment, - ReactPortal, - useEffect, - useState, -} from 'react'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useCallback, useEffect, useState } from 'react'; import Database from 'tauri-plugin-sql-api'; export default function Page() { @@ -43,20 +36,19 @@ export default function Page() { } }); + const insertDB = useCallback(async () => { + // save account to database + const db = await Database.load('sqlite:lume.db'); + const metadata = JSON.stringify(account); + await db.execute( + `INSERT INTO accounts (id, privkey, npub, nsec, metadata) VALUES ("${pubkey}", "${privkey}", "${npub}", "${nsec}", '${metadata}')` + ); + await db.close(); + }, [account, npub, nsec, privkey, pubkey]); + useEffect(() => { setLoading(true); - const insertDB = async () => { - // save account to database - const db = await Database.load('sqlite:lume.db'); - await db.execute( - `INSERT INTO accounts (privkey, pubkey, npub, nsec, current, metadata) VALUES ("${privkey}", "${pubkey}", "${npub}", "${nsec}", "1", '${JSON.stringify( - account - )}')` - ); - await db.close(); - }; - if (account !== null) { insertDB() .then(() => { @@ -70,39 +62,26 @@ export default function Page() { }) .catch(console.error); } - }, [account, npub, nsec, privkey, pubkey, router]); + }, [account, insertDB, npub, nsec, privkey, pubkey, router]); return (
{/* spacer */}
- + Fetching your profile... - As long as you have private key, you alway can sync your profile on every nostr client, - so please keep your key safely + As long as you have private key, you alway can sync your profile on every nostr client, so please keep your key safely
{loading === true ? ( - - + + > - | ReactFragment - | ReactPortal + page: string | number | boolean | ReactElement> | ReactFragment | ReactPortal ) { return ( diff --git a/src/pages/onboarding/following.tsx b/src/pages/onboarding/following.tsx index e9a60993..2d5e8cef 100644 --- a/src/pages/onboarding/following.tsx +++ b/src/pages/onboarding/following.tsx @@ -33,14 +33,11 @@ export default function Page() { const insertDB = async () => { const db = await Database.load('sqlite:lume.db'); - await db.execute( - `INSERT INTO follows (pubkey, account) VALUES ("${$currentUser.pubkey}", "${$currentUser.pubkey}")` - ); + // self followed + await db.execute(`INSERT INTO follows (pubkey, account) VALUES ("${$currentUser.pubkey}", "${$currentUser.pubkey}")`); follow.forEach(async (npub) => { const { data } = nip19.decode(npub); - await db.execute( - `INSERT INTO follows (pubkey, account) VALUES ("${data}", "${$currentUser.pubkey}")` - ); + await db.execute(`INSERT INTO follows (pubkey, account) VALUES ("${data}", "${$currentUser.pubkey}")`); }); }; @@ -60,14 +57,11 @@ export default function Page() {
{/* spacer */}
- + Choose 10 people you want to following - For better experiences, you should follow the people you care about to personalize your - newsfeed, otherwise you will be very bored + For better experiences, you should follow the people you care about to personalize your newsfeed, otherwise you will be very bored
@@ -81,27 +75,14 @@ export default function Page() { follow.includes(item.npub) ? 'bg-zinc-800' : '' }`}>
- {item.name} + {item.name}

{item.name}

-

- {truncate(item.npub, 16, ' .... ')} -

-
-
- {follow.includes(item.npub) ? ( - - ) : ( - <> - )} +

{truncate(item.npub, 16, ' .... ')}

+
{follow.includes(item.npub) ? : <>}
))} @@ -111,18 +92,8 @@ export default function Page() {
{loading === true ? ( - - + + > - | ReactFragment - | ReactPortal + page: string | number | boolean | ReactElement> | ReactFragment | ReactPortal ) { return ( diff --git a/src/pages/onboarding/import.tsx b/src/pages/onboarding/import.tsx index a3e9604b..454fae06 100644 --- a/src/pages/onboarding/import.tsx +++ b/src/pages/onboarding/import.tsx @@ -60,14 +60,12 @@ export default function Page() {
{/* spacer */}
- + Import your private key - You can import private key format as hex string or nsec. If you have installed Nostr - Connect compality wallet in your mobile, you can connect by scan QR Code below + You can import private key format as hex string or nsec. If you have installed Nostr Connect compality wallet in your mobile, you can + connect by scan QR Code below
@@ -85,18 +83,8 @@ export default function Page() {
{isSubmitting ? ( - - + + > - | ReactFragment - | ReactPortal + page: string | number | boolean | ReactElement> | ReactFragment | ReactPortal ) { return ( From f3da53f0984ab64296d7b4539489de803158a880 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sun, 26 Feb 2023 18:01:28 +0700 Subject: [PATCH 04/21] wip: migrated to nostr-relaypool --- package.json | 4 ++- pnpm-lock.yaml | 52 ++++++++++++++++++++++++++-- src/pages/_app.tsx | 12 +++---- src/pages/feed/following.tsx | 67 +++++++++++++++++++----------------- src/pages/index.tsx | 4 +-- src/stores/context.tsx | 11 ++++++ 6 files changed, 106 insertions(+), 44 deletions(-) create mode 100644 src/stores/context.tsx diff --git a/package.json b/package.json index 22196a3c..1e3cf888 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "next": "^13.2.1", "next-remove-imports": "^1.0.10", "nostr-react": "^0.6.4", + "nostr-relaypool": "^0.5.3", "nostr-tools": "^1.6.0", "qrcode.react": "^3.1.0", "react": "^18.2.0", @@ -37,7 +38,8 @@ "react-player": "^2.11.2", "react-virtuoso": "^4.1.0", "tauri-plugin-sql-api": "github:tauri-apps/tauri-plugin-sql", - "unique-names-generator": "^4.7.1" + "unique-names-generator": "^4.7.1", + "ws": "^8.12.1" }, "devDependencies": { "@tailwindcss/typography": "^0.5.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b13df7b0..7c7bb1c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,6 +34,7 @@ specifiers: next: ^13.2.1 next-remove-imports: ^1.0.10 nostr-react: ^0.6.4 + nostr-relaypool: ^0.5.3 nostr-tools: ^1.6.0 postcss: ^8.4.21 prettier: ^2.8.4 @@ -50,6 +51,7 @@ specifiers: tauri-plugin-sql-api: github:tauri-apps/tauri-plugin-sql typescript: ^4.9.5 unique-names-generator: ^4.7.1 + ws: ^8.12.1 dependencies: '@nanostores/persistent': 0.7.0_nanostores@0.7.4 @@ -68,6 +70,7 @@ dependencies: next: 13.2.1_biqbaboplfbrettd7655fr4n2y next-remove-imports: 1.0.10 nostr-react: 0.6.4_react@18.2.0 + nostr-relaypool: 0.5.3_ws@8.12.1 nostr-tools: 1.6.0 qrcode.react: 3.1.0_react@18.2.0 react: 18.2.0 @@ -78,6 +81,7 @@ dependencies: react-virtuoso: 4.1.0_biqbaboplfbrettd7655fr4n2y tauri-plugin-sql-api: github.com/tauri-apps/tauri-plugin-sql/abd8759ef49e1ba441540a2260b453d43d86c7ee unique-names-generator: 4.7.1 + ws: 8.12.1 devDependencies: '@tailwindcss/typography': 0.5.9_tailwindcss@3.2.7 @@ -411,6 +415,15 @@ packages: resolution: { integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== } dev: true + /@jest/source-map/29.4.3: + resolution: { integrity: sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w== } + engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + dependencies: + '@jridgewell/trace-mapping': 0.3.17 + callsites: 3.1.0 + graceful-fs: 4.2.10 + dev: false + /@jridgewell/gen-mapping/0.1.1: resolution: { integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== } engines: { node: '>=6.0.0' } @@ -1729,7 +1742,6 @@ packages: /callsites/3.1.0: resolution: { integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== } engines: { node: '>=6' } - dev: true /camelcase-css/2.0.1: resolution: { integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== } @@ -2734,7 +2746,6 @@ packages: /graceful-fs/4.2.10: resolution: { integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== } - dev: true /grapheme-splitter/1.0.4: resolution: { integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== } @@ -3187,6 +3198,14 @@ packages: resolution: { integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== } dev: true + /isomorphic-ws/5.0.0_ws@8.12.1: + resolution: { integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== } + peerDependencies: + ws: '*' + dependencies: + ws: 8.12.1 + dev: false + /javascript-natural-sort/0.7.1: resolution: { integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw== } dev: true @@ -3983,6 +4002,17 @@ packages: - jotai-zustand dev: false + /nostr-relaypool/0.5.3_ws@8.12.1: + resolution: { integrity: sha512-1INGKleOTuUTFUs3RnnZrew4+G/idLUewh44WBtmTTJ9g+kRiQtMMaBGTVUpf9621nBNleEVOB8p3XSNcaX3FQ== } + dependencies: + '@jest/source-map': 29.4.3 + isomorphic-ws: 5.0.0_ws@8.12.1 + nostr-tools: 1.6.0 + safe-stable-stringify: 2.4.2 + transitivePeerDependencies: + - ws + dev: false + /nostr-tools/1.6.0: resolution: { integrity: sha512-qjjJQ7YxJUMzgS24eVlxkZ87PKJtU6dlH04OzVuK6w+GSPL+VdUZkMe2lfSpnb7OkCrDIzmbFbtx+Q4LXdU2xw== } dependencies: @@ -4824,6 +4854,11 @@ packages: is-regex: 1.1.4 dev: true + /safe-stable-stringify/2.4.2: + resolution: { integrity: sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA== } + engines: { node: '>=10' } + dev: false + /scheduler/0.23.0: resolution: { integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== } dependencies: @@ -5447,6 +5482,19 @@ packages: resolution: { integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== } dev: true + /ws/8.12.1: + resolution: { integrity: sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew== } + engines: { node: '>=10.0.0' } + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /xtend/4.0.2: resolution: { integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== } engines: { node: '>=0.4' } diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 7f2d2930..97c17e48 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,11 +1,11 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import RelayProvider from '@stores/context'; import { relays } from '@stores/relays'; import { useStore } from '@nanostores/react'; import type { NextPage } from 'next'; import type { AppProps } from 'next/app'; -import { NostrProvider } from 'nostr-react'; -import type { ReactElement, ReactNode } from 'react'; +import { ReactElement, ReactNode } from 'react'; import '../App.css'; @@ -21,12 +21,8 @@ type AppPropsWithLayout = AppProps & { export default function MyApp({ Component, pageProps }: AppPropsWithLayout) { // Use the layout defined at the page level, if available const getLayout = Component.getLayout ?? ((page) => page); - // Get relays + // Get all relays const $relays = useStore(relays); - return ( - - {getLayout()} - - ); + return {getLayout()}; } diff --git a/src/pages/feed/following.tsx b/src/pages/feed/following.tsx index 00766a4a..1ad966fc 100644 --- a/src/pages/feed/following.tsx +++ b/src/pages/feed/following.tsx @@ -1,54 +1,59 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import BaseLayout from '@layouts/baseLayout'; import NewsFeedLayout from '@layouts/newsfeedLayout'; -import { Placeholder } from '@components/note/placeholder'; -import { Thread } from '@components/thread'; - import { hoursAgo } from '@utils/getDate'; +import { RelayContext } from '@stores/context'; import { follows } from '@stores/follows'; +import { relays } from '@stores/relays'; import { useStore } from '@nanostores/react'; -import { dateToUnix, useNostrEvents } from 'nostr-react'; -import { - JSXElementConstructor, - ReactElement, - ReactFragment, - ReactPortal, - Suspense, - useRef, -} from 'react'; +import { dateToUnix } from 'nostr-react'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useEffect, useRef, useState } from 'react'; export default function Page() { - const $follows = useStore(follows); + const relayPool: any = useContext(RelayContext); + + const [data, setData] = useState([]); const now = useRef(new Date()); - const { events } = useNostrEvents({ - filter: { - authors: $follows, - since: dateToUnix(hoursAgo(6, now.current)), - kinds: [1], - limit: 100, - }, - }); + const $follows = useStore(follows); + const $relays = useStore(relays); + + useEffect(() => { + const unsub = relayPool.subscribe( + [ + { + kinds: [1], + authors: $follows, + since: dateToUnix(hoursAgo(12, now.current)), + }, + ], + $relays, + (event: any) => { + setData((data) => [event, ...data]); + }, + undefined, + (events: any, relayURL: any) => { + console.log(events, relayURL); + } + ); + + return () => unsub(); + }, [$follows, $relays, relayPool]); return (
- }> - - + {data.map((item, index) => ( +

{item.id}

+ ))}
); } Page.getLayout = function getLayout( - page: - | string - | number - | boolean - | ReactElement> - | ReactFragment - | ReactPortal + page: string | number | boolean | ReactElement> | ReactFragment | ReactPortal ) { return ( diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 06993360..14a98545 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -40,7 +40,7 @@ export default function Page() { return result; }, []); - const getFollows = useCallback(async (account) => { + const getFollows = useCallback(async (account: { id: string }) => { const arr = []; const result: any = await db.select(`SELECT pubkey FROM follows WHERE account = "${account.id}"`); @@ -82,7 +82,7 @@ export default function Page() { }) .catch(console.error); }); - }, [getAccount, getFollows, requestNotification, router]); + }, [requestNotification, getAccount, getFollows, router]); return (
diff --git a/src/stores/context.tsx b/src/stores/context.tsx new file mode 100644 index 00000000..41b30048 --- /dev/null +++ b/src/stores/context.tsx @@ -0,0 +1,11 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { RelayPool } from 'nostr-relaypool'; +import { createContext, useMemo } from 'react'; + +export const RelayContext = createContext({}); + +export default function RelayProvider({ relays, children }: { relays: any; children: React.ReactNode }) { + const value = useMemo(() => new RelayPool(relays, { useEventCache: true }), [relays]); + + return {children}; +} From 3fa2fc442f11d14adee326c48ed1bc08c4dffa95 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sun, 26 Feb 2023 20:51:25 +0700 Subject: [PATCH 05/21] updated migration --- src-tauri/migrations/20230226004139_create_tables.sql | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src-tauri/migrations/20230226004139_create_tables.sql b/src-tauri/migrations/20230226004139_create_tables.sql index 22955e5a..e7f9fcec 100644 --- a/src-tauri/migrations/20230226004139_create_tables.sql +++ b/src-tauri/migrations/20230226004139_create_tables.sql @@ -15,6 +15,7 @@ CREATE TABLE id INTEGER PRIMARY KEY, pubkey TEXT NOT NULL, account TEXT NOT NULL, + kind INTEGER NOT NULL DEFAULT 0, metadata JSON ); @@ -26,8 +27,8 @@ CREATE TABLE cache_profiles ( id TEXT PRIMARY KEY, metadata JSON, - created_at TEXT, - updated_at TEXT + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ); -- create cache notes @@ -35,6 +36,8 @@ CREATE TABLE cache_notes ( id TEXT PRIMARY KEY, note JSON, - created_at TEXT, - updated_at TEXT + kind INTEGER NOT NULL DEFAULT 1, + is_multi BOOLEAN DEFAULT 0, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ); \ No newline at end of file From 2ef3e9ba85f955a5ecd0f4a2e4514aebfbb8a07f Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sun, 26 Feb 2023 20:51:46 +0700 Subject: [PATCH 06/21] disabled relaypool cache --- src/stores/context.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/context.tsx b/src/stores/context.tsx index 41b30048..4bc45ad7 100644 --- a/src/stores/context.tsx +++ b/src/stores/context.tsx @@ -5,7 +5,7 @@ import { createContext, useMemo } from 'react'; export const RelayContext = createContext({}); export default function RelayProvider({ relays, children }: { relays: any; children: React.ReactNode }) { - const value = useMemo(() => new RelayPool(relays, { useEventCache: true }), [relays]); + const value = useMemo(() => new RelayPool(relays, { useEventCache: false }), [relays]); return {children}; } From 690d55e0eb54dfa46311a761cc3a3be2ba2a0dd3 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sun, 26 Feb 2023 20:52:28 +0700 Subject: [PATCH 07/21] updated onboarding pre-following process --- src/pages/onboarding/following.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/onboarding/following.tsx b/src/pages/onboarding/following.tsx index 2d5e8cef..b4d923b7 100644 --- a/src/pages/onboarding/following.tsx +++ b/src/pages/onboarding/following.tsx @@ -33,8 +33,9 @@ export default function Page() { const insertDB = async () => { const db = await Database.load('sqlite:lume.db'); - // self followed + // self follow await db.execute(`INSERT INTO follows (pubkey, account) VALUES ("${$currentUser.pubkey}", "${$currentUser.pubkey}")`); + // follow selected follow.forEach(async (npub) => { const { data } = nip19.decode(npub); await db.execute(`INSERT INTO follows (pubkey, account) VALUES ("${data}", "${$currentUser.pubkey}")`); From 18900f14106f4c2ae5d335458f2d71e0c13d21d2 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Sun, 26 Feb 2023 21:21:35 +0700 Subject: [PATCH 08/21] added database provider & refactor sql execute --- src/components/contexts/database.tsx | 13 ++++ .../contexts/relay.tsx} | 0 src/pages/_app.tsx | 10 ++- src/pages/feed/following.tsx | 46 ++++++++----- src/pages/index.tsx | 31 +++++---- src/pages/onboarding/create.tsx | 67 ++++++++----------- src/pages/onboarding/fetch-follows.tsx | 50 ++++++++------ src/pages/onboarding/fetch-profile.tsx | 45 ++++++++----- src/pages/onboarding/following.tsx | 12 ++-- 9 files changed, 161 insertions(+), 113 deletions(-) create mode 100644 src/components/contexts/database.tsx rename src/{stores/context.tsx => components/contexts/relay.tsx} (100%) diff --git a/src/components/contexts/database.tsx b/src/components/contexts/database.tsx new file mode 100644 index 00000000..c4059a99 --- /dev/null +++ b/src/components/contexts/database.tsx @@ -0,0 +1,13 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { createContext } from 'react'; +import Database from 'tauri-plugin-sql-api'; + +export const DatabaseContext = createContext({}); + +const db = typeof window !== 'undefined' ? await Database.load('sqlite:lume.db') : null; + +export default function DatabaseProvider({ children }: { children: React.ReactNode }) { + const value = db; + + return {children}; +} diff --git a/src/stores/context.tsx b/src/components/contexts/relay.tsx similarity index 100% rename from src/stores/context.tsx rename to src/components/contexts/relay.tsx diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 97c17e48..ff4c5514 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,5 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import RelayProvider from '@stores/context'; +import DatabaseProvider from '@components/contexts/database'; +import RelayProvider from '@components/contexts/relay'; + import { relays } from '@stores/relays'; import { useStore } from '@nanostores/react'; @@ -24,5 +26,9 @@ export default function MyApp({ Component, pageProps }: AppPropsWithLayout) { // Get all relays const $relays = useStore(relays); - return {getLayout()}; + return ( + + {getLayout()} + + ); } diff --git a/src/pages/feed/following.tsx b/src/pages/feed/following.tsx index 1ad966fc..a90ad029 100644 --- a/src/pages/feed/following.tsx +++ b/src/pages/feed/following.tsx @@ -2,37 +2,59 @@ import BaseLayout from '@layouts/baseLayout'; import NewsFeedLayout from '@layouts/newsfeedLayout'; +import { RelayContext } from '@components/contexts/relay'; + import { hoursAgo } from '@utils/getDate'; -import { RelayContext } from '@stores/context'; +import { currentUser } from '@stores/currentUser'; import { follows } from '@stores/follows'; import { relays } from '@stores/relays'; import { useStore } from '@nanostores/react'; import { dateToUnix } from 'nostr-react'; -import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useEffect, useRef, useState } from 'react'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useEffect, useRef } from 'react'; export default function Page() { const relayPool: any = useContext(RelayContext); - - const [data, setData] = useState([]); const now = useRef(new Date()); const $follows = useStore(follows); const $relays = useStore(relays); + const $currentUser = useStore(currentUser); useEffect(() => { const unsub = relayPool.subscribe( [ { - kinds: [1], + kinds: [0, 1, 3, 5, 7], authors: $follows, since: dateToUnix(hoursAgo(12, now.current)), }, ], $relays, - (event: any) => { - setData((data) => [event, ...data]); + async (event: any) => { + switch (event.kind) { + case 0: + //await db.execute(`INSERT OR IGNORE INTO cache_profiles (id, metadata) VALUES ("${event.pubkey}", '${JSON.stringify(event.content)}')`); + break; + case 3: + //await db.execute(`INSERT OR IGNORE INTO follows (pubkey, account, kind) VALUES ("${event.pubkey}", "${$currentUser.pubkey}", "1")`); + break; + case 1: + case 5: + case 7: + /* + const isMulti = event.tags.length > 0; + await db.execute( + `INSERT OR IGNORE INTO cache_notes (id, note, kind, is_multi) VALUES ("${event.pubkey}", '${JSON.stringify(event)}', "${ + event.kind + }", "${isMulti}")` + ); + */ + break; + default: + break; + } }, undefined, (events: any, relayURL: any) => { @@ -41,15 +63,9 @@ export default function Page() { ); return () => unsub(); - }, [$follows, $relays, relayPool]); + }, [$currentUser.pubkey, $follows, $relays, relayPool]); - return ( -
- {data.map((item, index) => ( -

{item.id}

- ))} -
- ); + return
; } Page.getLayout = function getLayout( diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 14a98545..688b4954 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -2,6 +2,8 @@ import BaseLayout from '@layouts/baseLayout'; import FullLayout from '@layouts/fullLayout'; +import { DatabaseContext } from '@components/contexts/database'; + import { currentUser } from '@stores/currentUser'; import { follows } from '@stores/follows'; @@ -10,12 +12,11 @@ import LumeSymbol from '@assets/icons/Lume'; import { isPermissionGranted, requestPermission, sendNotification } from '@tauri-apps/api/notification'; import { motion } from 'framer-motion'; import { useRouter } from 'next/router'; -import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useCallback, useEffect, useState } from 'react'; -import Database from 'tauri-plugin-sql-api'; - -const db = typeof window !== 'undefined' ? await Database.load('sqlite:lume.db') : null; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useCallback, useContext, useEffect, useState } from 'react'; export default function Page() { + const db: any = useContext(DatabaseContext); + const router = useRouter(); const [loading, setLoading] = useState(true); @@ -36,20 +37,22 @@ export default function Page() { const getAccount = useCallback(async () => { const result = await db.select(`SELECT * FROM accounts ASC LIMIT 1`); - return result; - }, []); + }, [db]); - const getFollows = useCallback(async (account: { id: string }) => { - const arr = []; - const result: any = await db.select(`SELECT pubkey FROM follows WHERE account = "${account.id}"`); + const getFollows = useCallback( + async (account: { id: string }) => { + const arr = []; + const result: any = await db.select(`SELECT pubkey FROM follows WHERE account = "${account.id}"`); - result.forEach((item: { pubkey: string }) => { - arr.push(item.pubkey); - }); + result.forEach((item: { pubkey: string }) => { + arr.push(item.pubkey); + }); - return arr; - }, []); + return arr; + }, + [db] + ); // Explain: // Step 1: request allow notification from system diff --git a/src/pages/onboarding/create.tsx b/src/pages/onboarding/create.tsx index 01043ce4..c836db7f 100644 --- a/src/pages/onboarding/create.tsx +++ b/src/pages/onboarding/create.tsx @@ -2,84 +2,79 @@ import BaseLayout from '@layouts/baseLayout'; import OnboardingLayout from '@layouts/onboardingLayout'; -import { currentUser } from '@stores/currentUser'; +import { DatabaseContext } from '@components/contexts/database'; +import { RelayContext } from '@components/contexts/relay'; +import { currentUser } from '@stores/currentUser'; +import { relays } from '@stores/relays'; + +import { useStore } from '@nanostores/react'; import { EyeClosedIcon, EyeOpenIcon } from '@radix-ui/react-icons'; import { motion } from 'framer-motion'; import Image from 'next/image'; import { useRouter } from 'next/router'; -import { dateToUnix, useNostr } from 'nostr-react'; import { generatePrivateKey, getEventHash, getPublicKey, nip19, signEvent } from 'nostr-tools'; -import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useState } from 'react'; -import Database from 'tauri-plugin-sql-api'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useState } from 'react'; import { Config, names, uniqueNamesGenerator } from 'unique-names-generator'; const config: Config = { dictionaries: [names], }; -const defaultAvatars = [ - 'https://bafybeidfsbrzqbvontmucteomoz2rkrxugu462l5hyhh6uioslkfzzs4oq.ipfs.w3s.link/avatar-11.png', - 'https://bafybeid7mrvznbnd6r2ju2iu7lsxkcikufys6z6ssy5ldxrxq5qh3yqf4u.ipfs.w3s.link/avatar-12.png', - 'https://bafybeih5gpwu53ohui6p7scekjpxjk2d4lusq2jqohqhjsvhfkeu56ea4e.ipfs.w3s.link/avatar-13.png', - 'https://bafybeibpbvrpuphkerjygdbnh26av5brqggzunbbbmfl3ozlvcn2mj6zxa.ipfs.w3s.link/avatar-14.png', - 'https://bafybeia4ue4loinuflu7y5q3xu6hcvt653mzw5yorw25oarf2wqksig4ma.ipfs.w3s.link/avatar-15.png', - 'https://bafybeib3gzl6n2bebiru2cpkdljmlzbtqfsl6xcnqtabxt6jrpj7l7ltm4.ipfs.w3s.link/avatar-16.png', -]; - -const defaultBanners = [ - 'https://bafybeiacwit7hjmdefqggxqtgh6ht5dhth7ndptwn2msl5kpkodudsr7py.ipfs.w3s.link/banner-1.jpg', - 'https://bafybeiderllqadxsikh3envikobmyka3uwgojriwh6epctqartq2loswyi.ipfs.w3s.link/banner-2.jpg', - 'https://bafybeiba4tifde2kczvd26vxhbb5jpqi3wmgvccpkcrle4hse2cqrwlwiy.ipfs.w3s.link/banner-3.jpg', - 'https://bafybeifqpny2eom7ccvmaguxxxfajutmn5h3fotaasga7gce2xfx37p6oy.ipfs.w3s.link/banner-4.jpg', -]; - export default function Page() { + const db: any = useContext(DatabaseContext); const router = useRouter(); - const { publish } = useNostr(); + + const relayPool: any = useContext(RelayContext); + const $relays = useStore(relays); const [type, setType] = useState('password'); const [loading, setLoading] = useState(false); const [privKey] = useState(() => generatePrivateKey()); const [name] = useState(() => uniqueNamesGenerator(config).toString()); - const [avatar] = useState(() => defaultAvatars[Math.floor(Math.random() * defaultAvatars.length)]); - const [banner] = useState(() => defaultBanners[Math.floor(Math.random() * defaultBanners.length)]); const pubKey = getPublicKey(privKey); const npub = nip19.npubEncode(pubKey); const nsec = nip19.nsecEncode(privKey); + const showPrivateKey = () => { + if (type === 'password') { + setType('text'); + } else { + setType('password'); + } + }; + // auto-generated profile const data = { display_name: name, name: name, username: name.toLowerCase(), - picture: avatar, - banner: banner, + picture: 'https://bafybeidfsbrzqbvontmucteomoz2rkrxugu462l5hyhh6uioslkfzzs4oq.ipfs.w3s.link/avatar-11.png', + banner: 'https://bafybeiacwit7hjmdefqggxqtgh6ht5dhth7ndptwn2msl5kpkodudsr7py.ipfs.w3s.link/banner-1.jpg', }; const createAccount = async () => { setLoading(true); - // publish account to relays + // build event const event: any = { content: JSON.stringify(data), - created_at: dateToUnix(), + created_at: Math.floor(Date.now() / 1000), kind: 0, pubkey: pubKey, tags: [], }; event.id = getEventHash(event); event.sig = signEvent(event, privKey); - publish(event); + // publish to relays + relayPool.publish(event, $relays); // save account to database - const db = await Database.load('sqlite:lume.db'); await db.execute( `INSERT INTO accounts (id, privkey, npub, nsec, metadata) VALUES ("${pubKey}", "${privKey}", "${npub}", "${nsec}", '${JSON.stringify(data)}')` ); - await db.close(); // set currentUser in global state currentUser.set({ @@ -96,14 +91,6 @@ export default function Page() { }, 1500); }; - const showNsec = () => { - if (type === 'password') { - setType('text'); - } else { - setType('password'); - } - }; - return (
{/* spacer */}
@@ -137,7 +124,9 @@ export default function Page() { value={nsec} className="relative w-full rounded-lg border border-black/5 px-3.5 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-600" /> -
@@ -65,9 +62,7 @@ export default function NavigatorBar() {

Direct Messages

-
diff --git a/src/pages/feed/following.tsx b/src/pages/feed/following.tsx index 1c69a43a..34410613 100644 --- a/src/pages/feed/following.tsx +++ b/src/pages/feed/following.tsx @@ -3,56 +3,29 @@ import BaseLayout from '@layouts/baseLayout'; import NewsFeedLayout from '@layouts/newsfeedLayout'; import { DatabaseContext } from '@components/contexts/database'; -import { RelayContext } from '@components/contexts/relay'; import { Placeholder } from '@components/note/placeholder'; import { Thread } from '@components/thread'; -import { hoursAgo } from '@utils/getDate'; - -import { follows } from '@stores/follows'; -import { relays } from '@stores/relays'; - -import { useStore } from '@nanostores/react'; -import { dateToUnix } from 'nostr-react'; import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, Suspense, useContext, useEffect, useRef, useState } from 'react'; export default function Page() { const db: any = useContext(DatabaseContext); - const relayPool: any = useContext(RelayContext); - - const now = useRef(new Date()); - - const $follows = useStore(follows); - const $relays = useStore(relays); - - const [events, setEvents] = useState([]); + const [data, setData] = useState([]); + const limit = useRef(25); useEffect(() => { - const unsub = relayPool.subscribe( - [ - { - kinds: [1], - authors: $follows, - since: dateToUnix(hoursAgo(12, now.current)), - }, - ], - $relays, - async (event: any) => { - setEvents((events) => [event, ...events]); - }, - undefined, - (events: any, relayURL: any) => { - console.log(events, relayURL); - } - ); + const getData = async () => { + const result = await db.select(`SELECT * FROM cache_notes ORDER BY created_at DESC LIMIT ${limit.current}`); + setData(result); + }; - return () => unsub(); - }, [$follows, $relays, db, relayPool]); + getData().catch(console.error); + }, [db]); return (
}> - +
); From 964343ccc81f1c01703d885ed8fcaa4a30402ed1 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Tue, 28 Feb 2023 14:53:27 +0700 Subject: [PATCH 12/21] implemented infinite loading --- package.json | 4 +- pnpm-lock.yaml | 112 +++++++++++++++-------------- src/components/connectors/note.tsx | 3 +- src/components/thread.tsx | 53 -------------- src/pages/feed/following.tsx | 65 ++++++++++++++--- src/utils/getDate.tsx | 6 ++ 6 files changed, 122 insertions(+), 121 deletions(-) delete mode 100644 src/components/thread.tsx diff --git a/package.json b/package.json index 5d433f7a..2816c16c 100644 --- a/package.json +++ b/package.json @@ -48,8 +48,8 @@ "@types/node": "^18.14.2", "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", - "@typescript-eslint/eslint-plugin": "^5.53.0", - "@typescript-eslint/parser": "^5.53.0", + "@typescript-eslint/eslint-plugin": "^5.54.0", + "@typescript-eslint/parser": "^5.54.0", "autoprefixer": "^10.4.13", "csstype": "^3.1.1", "eslint": "^8.35.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e3f6df6f..505384a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,8 +13,8 @@ specifiers: '@types/node': ^18.14.2 '@types/react': ^18.0.28 '@types/react-dom': ^18.0.11 - '@typescript-eslint/eslint-plugin': ^5.53.0 - '@typescript-eslint/parser': ^5.53.0 + '@typescript-eslint/eslint-plugin': ^5.54.0 + '@typescript-eslint/parser': ^5.54.0 '@uiw/react-markdown-preview': ^4.1.9 '@uiw/react-md-editor': ^3.20.5 autoprefixer: ^10.4.13 @@ -90,8 +90,8 @@ devDependencies: '@types/node': 18.14.2 '@types/react': 18.0.28 '@types/react-dom': 18.0.11 - '@typescript-eslint/eslint-plugin': 5.53.0_cjo54hduev4bqhpjw5znwiokqu - '@typescript-eslint/parser': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu + '@typescript-eslint/eslint-plugin': 5.54.0_6mj2wypvdnknez7kws2nfdgupi + '@typescript-eslint/parser': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu autoprefixer: 10.4.13_postcss@8.4.21 csstype: 3.1.1 eslint: 8.35.0 @@ -1240,8 +1240,8 @@ packages: resolution: { integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== } dev: false - /@typescript-eslint/eslint-plugin/5.53.0_cjo54hduev4bqhpjw5znwiokqu: - resolution: { integrity: sha512-alFpFWNucPLdUOySmXCJpzr6HKC3bu7XooShWM+3w/EL6J2HIoB2PFxpLnq4JauWVk6DiVeNKzQlFEaE+X9sGw== } + /@typescript-eslint/eslint-plugin/5.54.0_6mj2wypvdnknez7kws2nfdgupi: + resolution: { integrity: sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw== } engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } peerDependencies: '@typescript-eslint/parser': ^5.0.0 @@ -1251,10 +1251,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu - '@typescript-eslint/scope-manager': 5.53.0 - '@typescript-eslint/type-utils': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu - '@typescript-eslint/utils': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu + '@typescript-eslint/parser': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu + '@typescript-eslint/scope-manager': 5.54.0 + '@typescript-eslint/type-utils': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu + '@typescript-eslint/utils': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu debug: 4.3.4 eslint: 8.35.0 grapheme-splitter: 1.0.4 @@ -1268,8 +1268,8 @@ packages: - supports-color dev: true - /@typescript-eslint/parser/5.53.0_ycpbpc6yetojsgtrx3mwntkhsu: - resolution: { integrity: sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ== } + /@typescript-eslint/parser/5.54.0_ycpbpc6yetojsgtrx3mwntkhsu: + resolution: { integrity: sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ== } engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1278,9 +1278,9 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.53.0 - '@typescript-eslint/types': 5.53.0 - '@typescript-eslint/typescript-estree': 5.53.0_typescript@4.9.5 + '@typescript-eslint/scope-manager': 5.54.0 + '@typescript-eslint/types': 5.54.0 + '@typescript-eslint/typescript-estree': 5.54.0_typescript@4.9.5 debug: 4.3.4 eslint: 8.35.0 typescript: 4.9.5 @@ -1288,16 +1288,16 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager/5.53.0: - resolution: { integrity: sha512-Opy3dqNsp/9kBBeCPhkCNR7fmdSQqA+47r21hr9a14Bx0xnkElEQmhoHga+VoaoQ6uDHjDKmQPIYcUcKJifS7w== } + /@typescript-eslint/scope-manager/5.54.0: + resolution: { integrity: sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg== } engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } dependencies: - '@typescript-eslint/types': 5.53.0 - '@typescript-eslint/visitor-keys': 5.53.0 + '@typescript-eslint/types': 5.54.0 + '@typescript-eslint/visitor-keys': 5.54.0 dev: true - /@typescript-eslint/type-utils/5.53.0_ycpbpc6yetojsgtrx3mwntkhsu: - resolution: { integrity: sha512-HO2hh0fmtqNLzTAme/KnND5uFNwbsdYhCZghK2SoxGp3Ifn2emv+hi0PBUjzzSh0dstUIFqOj3bp0AwQlK4OWw== } + /@typescript-eslint/type-utils/5.54.0_ycpbpc6yetojsgtrx3mwntkhsu: + resolution: { integrity: sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ== } engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } peerDependencies: eslint: '*' @@ -1306,8 +1306,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.53.0_typescript@4.9.5 - '@typescript-eslint/utils': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu + '@typescript-eslint/typescript-estree': 5.54.0_typescript@4.9.5 + '@typescript-eslint/utils': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu debug: 4.3.4 eslint: 8.35.0 tsutils: 3.21.0_typescript@4.9.5 @@ -1316,13 +1316,13 @@ packages: - supports-color dev: true - /@typescript-eslint/types/5.53.0: - resolution: { integrity: sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A== } + /@typescript-eslint/types/5.54.0: + resolution: { integrity: sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ== } engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } dev: true - /@typescript-eslint/typescript-estree/5.53.0_typescript@4.9.5: - resolution: { integrity: sha512-eKmipH7QyScpHSkhbptBBYh9v8FxtngLquq292YTEQ1pxVs39yFBlLC1xeIZcPPz1RWGqb7YgERJRGkjw8ZV7w== } + /@typescript-eslint/typescript-estree/5.54.0_typescript@4.9.5: + resolution: { integrity: sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ== } engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } peerDependencies: typescript: '*' @@ -1330,8 +1330,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.53.0 - '@typescript-eslint/visitor-keys': 5.53.0 + '@typescript-eslint/types': 5.54.0 + '@typescript-eslint/visitor-keys': 5.54.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -1342,17 +1342,17 @@ packages: - supports-color dev: true - /@typescript-eslint/utils/5.53.0_ycpbpc6yetojsgtrx3mwntkhsu: - resolution: { integrity: sha512-VUOOtPv27UNWLxFwQK/8+7kvxVC+hPHNsJjzlJyotlaHjLSIgOCKj9I0DBUjwOOA64qjBwx5afAPjksqOxMO0g== } + /@typescript-eslint/utils/5.54.0_ycpbpc6yetojsgtrx3mwntkhsu: + resolution: { integrity: sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw== } engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: '@types/json-schema': 7.0.11 '@types/semver': 7.3.13 - '@typescript-eslint/scope-manager': 5.53.0 - '@typescript-eslint/types': 5.53.0 - '@typescript-eslint/typescript-estree': 5.53.0_typescript@4.9.5 + '@typescript-eslint/scope-manager': 5.54.0 + '@typescript-eslint/types': 5.54.0 + '@typescript-eslint/typescript-estree': 5.54.0_typescript@4.9.5 eslint: 8.35.0 eslint-scope: 5.1.1 eslint-utils: 3.0.0_eslint@8.35.0 @@ -1362,11 +1362,11 @@ packages: - typescript dev: true - /@typescript-eslint/visitor-keys/5.53.0: - resolution: { integrity: sha512-JqNLnX3leaHFZEN0gCh81sIvgrp/2GOACZNgO4+Tkf64u51kTpAyWFOY8XHx8XuXr3N2C9zgPPHtcpMg6z1g0w== } + /@typescript-eslint/visitor-keys/5.54.0: + resolution: { integrity: sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA== } engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } dependencies: - '@typescript-eslint/types': 5.53.0 + '@typescript-eslint/types': 5.54.0 eslint-visitor-keys: 3.3.0 dev: true @@ -1733,7 +1733,7 @@ packages: hasBin: true dependencies: caniuse-lite: 1.0.30001458 - electron-to-chromium: 1.4.311 + electron-to-chromium: 1.4.313 node-releases: 2.0.10 update-browserslist-db: 1.0.10_browserslist@4.21.5 @@ -2047,8 +2047,8 @@ packages: resolution: { integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== } dev: true - /electron-to-chromium/1.4.311: - resolution: { integrity: sha512-RoDlZufvrtr2Nx3Yx5MB8jX3aHIxm8nRWPJm3yVvyHmyKaRvn90RjzB6hNnt0AkhS3IInJdyRfQb4mWhPvUjVw== } + /electron-to-chromium/1.4.313: + resolution: { integrity: sha512-QckB9OVqr2oybjIrbMI99uF+b9+iTja5weFe0ePbqLb5BHqXOJUO1SG6kDj/1WtWPRIBr51N153AEq8m7HuIaA== } /emoji-regex/8.0.0: resolution: { integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== } @@ -2172,11 +2172,11 @@ packages: dependencies: '@next/eslint-plugin-next': 13.2.1 '@rushstack/eslint-patch': 1.2.0 - '@typescript-eslint/parser': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu + '@typescript-eslint/parser': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu eslint: 8.35.0 eslint-import-resolver-node: 0.3.7 eslint-import-resolver-typescript: 3.5.3_yckic57kx266ph64dhq6ozvb54 - eslint-plugin-import: 2.27.5_z4t62rwba3aha3c5ltpvvca4q4 + eslint-plugin-import: 2.27.5_tqrcrxlenpngfto46ddarus52y eslint-plugin-jsx-a11y: 6.7.1_eslint@8.35.0 eslint-plugin-react: 7.32.2_eslint@8.35.0 eslint-plugin-react-hooks: 4.6.0_eslint@8.35.0 @@ -2215,7 +2215,7 @@ packages: debug: 4.3.4 enhanced-resolve: 5.12.0 eslint: 8.35.0 - eslint-plugin-import: 2.27.5_z4t62rwba3aha3c5ltpvvca4q4 + eslint-plugin-import: 2.27.5_tqrcrxlenpngfto46ddarus52y get-tsconfig: 4.4.0 globby: 13.1.3 is-core-module: 2.11.0 @@ -2225,7 +2225,7 @@ packages: - supports-color dev: true - /eslint-module-utils/2.7.4_wptzf6m7n4mzoakxgrlp7sjl2e: + /eslint-module-utils/2.7.4_igrub7c6rucg6hjc3uqgumd66y: resolution: { integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA== } engines: { node: '>=4' } peerDependencies: @@ -2246,7 +2246,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu + '@typescript-eslint/parser': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu debug: 3.2.7 eslint: 8.35.0 eslint-import-resolver-node: 0.3.7 @@ -2255,7 +2255,7 @@ packages: - supports-color dev: true - /eslint-plugin-import/2.27.5_z4t62rwba3aha3c5ltpvvca4q4: + /eslint-plugin-import/2.27.5_tqrcrxlenpngfto46ddarus52y: resolution: { integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== } engines: { node: '>=4' } peerDependencies: @@ -2265,7 +2265,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu + '@typescript-eslint/parser': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 @@ -2273,7 +2273,7 @@ packages: doctrine: 2.1.0 eslint: 8.35.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4_wptzf6m7n4mzoakxgrlp7sjl2e + eslint-module-utils: 2.7.4_igrub7c6rucg6hjc3uqgumd66y has: 1.0.3 is-core-module: 2.11.0 is-glob: 4.0.3 @@ -3472,7 +3472,7 @@ packages: dependencies: '@types/mdast': 3.0.10 escape-string-regexp: 5.0.0 - unist-util-is: 5.2.0 + unist-util-is: 5.2.1 unist-util-visit-parents: 5.1.3 dev: false @@ -3555,7 +3555,7 @@ packages: resolution: { integrity: sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg== } dependencies: '@types/mdast': 3.0.10 - unist-util-is: 5.2.0 + unist-util-is: 5.2.1 dev: false /mdast-util-to-hast/12.3.0: @@ -5274,7 +5274,7 @@ packages: resolution: { integrity: sha512-RynicUM/vbOSTSiUK+BnaK9XMfmQUh6gyi7L6taNgc7FIf84GukXVV3ucGzEN/PhUUkdP5hb1MmXc+3cvPUm5Q== } dependencies: '@types/unist': 2.0.6 - unist-util-is: 5.2.0 + unist-util-is: 5.2.1 unist-util-visit-parents: 5.1.3 dev: false @@ -5282,8 +5282,10 @@ packages: resolution: { integrity: sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A== } dev: false - /unist-util-is/5.2.0: - resolution: { integrity: sha512-Glt17jWwZeyqrFqOK0pF1Ded5U3yzJnFr8CG1GMjCWTp9zDo2p+cmD6pWbZU8AgM5WU3IzRv6+rBwhzsGh6hBQ== } + /unist-util-is/5.2.1: + resolution: { integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw== } + dependencies: + '@types/unist': 2.0.6 dev: false /unist-util-position/4.0.4: @@ -5302,14 +5304,14 @@ packages: resolution: { integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg== } dependencies: '@types/unist': 2.0.6 - unist-util-is: 5.2.0 + unist-util-is: 5.2.1 dev: false /unist-util-visit/4.1.2: resolution: { integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg== } dependencies: '@types/unist': 2.0.6 - unist-util-is: 5.2.0 + unist-util-is: 5.2.1 unist-util-visit-parents: 5.1.3 dev: false diff --git a/src/components/connectors/note.tsx b/src/components/connectors/note.tsx index b2ae2f6c..334b8d0d 100644 --- a/src/components/connectors/note.tsx +++ b/src/components/connectors/note.tsx @@ -2,13 +2,12 @@ import { DatabaseContext } from '@components/contexts/database'; import { RelayContext } from '@components/contexts/relay'; -import { hoursAgo } from '@utils/getDate'; +import { dateToUnix, hoursAgo } from '@utils/getDate'; import { follows } from '@stores/follows'; import { relays } from '@stores/relays'; import { useStore } from '@nanostores/react'; -import { dateToUnix } from 'nostr-react'; import { memo, useCallback, useContext, useRef } from 'react'; export const NoteConnector = memo(function NoteConnector() { diff --git a/src/components/thread.tsx b/src/components/thread.tsx deleted file mode 100644 index 86d3a4ce..00000000 --- a/src/components/thread.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Placeholder } from '@components/note/placeholder'; -import { Repost } from '@components/note/repost'; -import { Single } from '@components/note/single'; - -import { useCallback } from 'react'; -import { Virtuoso } from 'react-virtuoso'; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function Thread({ data }: { data: any }) { - const ItemContent = useCallback( - (index: string | number) => { - const event = data[index]; - - if (event.content.includes('#[0]') && event.tags[0][0] == 'e') { - // type: repost - return ; - } else { - // type: default - return ; - } - }, - [data] - ); - - const computeItemKey = useCallback( - (index) => { - return data[index].id; - }, - [data] - ); - - return ( - , - ScrollSeekPlaceholder: () => , - }} - computeItemKey={computeItemKey} - scrollSeekConfiguration={{ - enter: (velocity) => Math.abs(velocity) > 800, - exit: (velocity) => Math.abs(velocity) < 500, - }} - overscan={800} - increaseViewportBy={1000} - className="scrollbar-hide relative h-full w-full rounded-lg" - style={{ - contain: 'strict', - }} - /> - ); -} diff --git a/src/pages/feed/following.tsx b/src/pages/feed/following.tsx index 34410613..165420ff 100644 --- a/src/pages/feed/following.tsx +++ b/src/pages/feed/following.tsx @@ -4,14 +4,18 @@ import NewsFeedLayout from '@layouts/newsfeedLayout'; import { DatabaseContext } from '@components/contexts/database'; import { Placeholder } from '@components/note/placeholder'; -import { Thread } from '@components/thread'; +import { Repost } from '@components/note/repost'; +import { Single } from '@components/note/single'; -import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, Suspense, useContext, useEffect, useRef, useState } from 'react'; +import { useCallback } from 'react'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useEffect, useRef, useState } from 'react'; +import { Virtuoso } from 'react-virtuoso'; export default function Page() { const db: any = useContext(DatabaseContext); - const [data, setData] = useState([]); - const limit = useRef(25); + const [data, setData] = useState(() => []); + const limit = useRef(30); + const offset = useRef(0); useEffect(() => { const getData = async () => { @@ -22,12 +26,55 @@ export default function Page() { getData().catch(console.error); }, [db]); + const loadMore = useCallback(async () => { + offset.current += limit.current; + // next query + const result = await db.select(`SELECT * FROM cache_notes ORDER BY created_at DESC LIMIT ${limit.current} OFFSET ${offset.current}`); + setData((data) => [...data, ...result]); + }, [db]); + + const ItemContent = useCallback( + (index: string | number) => { + const event = data[index]; + if (event.content.includes('#[0]') && event.tags[0][0] == 'e') { + // type: repost + return ; + } else { + // type: default + return ; + } + }, + [data] + ); + + const computeItemKey = useCallback( + (index: string | number) => { + return data[index].id; + }, + [data] + ); + return ( -
- }> - - -
+ , + ScrollSeekPlaceholder: () => , + }} + computeItemKey={computeItemKey} + scrollSeekConfiguration={{ + enter: (velocity) => Math.abs(velocity) > 800, + exit: (velocity) => Math.abs(velocity) < 500, + }} + endReached={loadMore} + overscan={800} + increaseViewportBy={1000} + className="scrollbar-hide relative h-full w-full rounded-lg" + style={{ + contain: 'strict', + }} + /> ); } diff --git a/src/utils/getDate.tsx b/src/utils/getDate.tsx index 416c6845..66a165e9 100644 --- a/src/utils/getDate.tsx +++ b/src/utils/getDate.tsx @@ -11,3 +11,9 @@ export const hoursAgo = (numOfHours, date = new Date()) => { return hoursAgo; }; + +export const dateToUnix = (_date?: Date) => { + const date = _date || new Date(); + + return Math.floor(date.getTime() / 1000); +}; From 458f826958c85a87f322150a6c7f07e8d680c70d Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Wed, 1 Mar 2023 15:35:10 +0700 Subject: [PATCH 13/21] refactor initial database and state management --- .prettierrc | 11 +- package.json | 3 +- pnpm-lock.yaml | 43 ++----- .../20230226004139_create_tables.sql | 26 ++++ src/components/accountBar/index.tsx | 9 +- src/components/connectors/note.tsx | 13 +- src/components/contexts/database.tsx | 51 +++++++- src/components/navigatorBar/createPost.tsx | 14 +-- src/components/navigatorBar/index.tsx | 10 +- src/components/note/atoms/reaction.tsx | 28 ++--- src/layouts/userLayout.tsx | 10 +- src/pages/_app.tsx | 10 +- src/pages/index.tsx | 92 +++----------- .../{create.tsx => create/index.tsx} | 73 ++++++----- .../{following.tsx => create/pre-follows.tsx} | 15 +-- src/pages/onboarding/fetch-profile.tsx | 116 ------------------ src/pages/onboarding/index.tsx | 18 +-- .../{fetch-follows.tsx => login/fetch.tsx} | 91 ++++++++------ .../{import.tsx => login/index.tsx} | 2 +- src/pages/profile/update.tsx | 84 ++++--------- src/stores/currentUser.tsx | 10 -- src/stores/follows.tsx | 10 -- src/stores/relays.tsx | 25 ---- tsconfig.json | 1 - 24 files changed, 259 insertions(+), 506 deletions(-) rename src/pages/onboarding/{create.tsx => create/index.tsx} (88%) rename src/pages/onboarding/{following.tsx => create/pre-follows.tsx} (93%) delete mode 100644 src/pages/onboarding/fetch-profile.tsx rename src/pages/onboarding/{fetch-follows.tsx => login/fetch.tsx} (57%) rename src/pages/onboarding/{import.tsx => login/index.tsx} (98%) delete mode 100644 src/stores/currentUser.tsx delete mode 100644 src/stores/follows.tsx delete mode 100644 src/stores/relays.tsx diff --git a/.prettierrc b/.prettierrc index 3cae53df..0060a5d8 100644 --- a/.prettierrc +++ b/.prettierrc @@ -8,16 +8,7 @@ "endOfLine": "lf", "bracketSpacing": true, "bracketSameLine": true, - "importOrder": [ - "^@layouts/(.*)$", - "^@pages/(.*)$", - "^@components/(.*)$", - "^@utils/(.*)$", - "^@stores/(.*)$", - "^@assets/(.*)$", - "", - "^[./]" - ], + "importOrder": ["^@layouts/(.*)$", "^@pages/(.*)$", "^@components/(.*)$", "^@utils/(.*)$", "^@stores/(.*)$", "", "^[./]"], "importOrderSeparation": true, "importOrderSortSpecifiers": true, "plugins": ["@trivago/prettier-plugin-sort-imports", "prettier-plugin-tailwindcss"], diff --git a/package.json b/package.json index 2816c16c..b366fbeb 100644 --- a/package.json +++ b/package.json @@ -12,11 +12,10 @@ "**/*": "prettier --write --ignore-unknown" }, "dependencies": { - "@nanostores/persistent": "^0.7.0", - "@nanostores/react": "^0.4.1", "@radix-ui/react-dialog": "^1.0.2", "@radix-ui/react-dropdown-menu": "^2.0.3", "@radix-ui/react-icons": "^1.2.0", + "@rehooks/local-storage": "^2.4.4", "@tauri-apps/api": "^1.2.0", "@uiw/react-markdown-preview": "^4.1.9", "@uiw/react-md-editor": "^3.20.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 505384a9..32cc97c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,11 +1,10 @@ lockfileVersion: 5.4 specifiers: - '@nanostores/persistent': ^0.7.0 - '@nanostores/react': ^0.4.1 '@radix-ui/react-dialog': ^1.0.2 '@radix-ui/react-dropdown-menu': ^2.0.3 '@radix-ui/react-icons': ^1.2.0 + '@rehooks/local-storage': ^2.4.4 '@tailwindcss/typography': ^0.5.9 '@tauri-apps/api': ^1.2.0 '@tauri-apps/cli': ^1.2.3 @@ -54,11 +53,10 @@ specifiers: ws: ^8.12.1 dependencies: - '@nanostores/persistent': 0.7.0_nanostores@0.7.4 - '@nanostores/react': 0.4.1_nkfnbc2tpc77iht7asm3uqwau4 '@radix-ui/react-dialog': 1.0.2_zula6vjvt3wdocc4mwcxqa6nzi '@radix-ui/react-dropdown-menu': 2.0.3_zula6vjvt3wdocc4mwcxqa6nzi '@radix-ui/react-icons': 1.2.0_react@18.2.0 + '@rehooks/local-storage': 2.4.4_react@18.2.0 '@tauri-apps/api': 1.2.0 '@uiw/react-markdown-preview': 4.1.9_zula6vjvt3wdocc4mwcxqa6nzi '@uiw/react-md-editor': 3.20.5_zula6vjvt3wdocc4mwcxqa6nzi @@ -467,27 +465,6 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: false - /@nanostores/persistent/0.7.0_nanostores@0.7.4: - resolution: { integrity: sha512-4PAInL/T1hbftZUJ0cmgdFHBMalUoq7BUXFBy7QfyMv/8X3LPTYNh/yxspL7+J+XM3UNvVI7IFRMMs6FBasjhQ== } - engines: { node: ^14.0.0 || ^16.0.0 || >=18.0.0 } - peerDependencies: - nanostores: ^0.7.0 - dependencies: - nanostores: 0.7.4 - dev: false - - /@nanostores/react/0.4.1_nkfnbc2tpc77iht7asm3uqwau4: - resolution: { integrity: sha512-lsv0CYrMxczbXtoV/mxFVEoL/uVjEjseoP89srO/5yNAOkJka+dSFS7LYyWEbuvCPO7EgbtkvRpO5V+OztKQOw== } - engines: { node: ^14.0.0 || ^16.0.0 || >=18.0.0 } - peerDependencies: - nanostores: ^0.7.0 - react: '>=18.0.0' - dependencies: - nanostores: 0.7.4 - react: 18.2.0 - use-sync-external-store: 1.2.0_react@18.2.0 - dev: false - /@next/env/13.2.1: resolution: { integrity: sha512-Hq+6QZ6kgmloCg8Kgrix+4F0HtvLqVK3FZAnlAoS0eonaDemHe1Km4kwjSWRE3JNpJNcKxFHF+jsZrYo0SxWoQ== } dev: false @@ -1009,6 +986,14 @@ packages: '@babel/runtime': 7.21.0 dev: false + /@rehooks/local-storage/2.4.4_react@18.2.0: + resolution: { integrity: sha512-zE+kfOkG59n/1UTxdmbwktIosclr67Nlbf2MzUJ9mNtCSypVscNHeD1qT6JCSo5Pjj8DO893IKWNLJqKKzDL/Q== } + peerDependencies: + react: '>=16.8.0' + dependencies: + react: 18.2.0 + dev: false + /@rushstack/eslint-patch/1.2.0: resolution: { integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg== } dev: true @@ -5374,14 +5359,6 @@ packages: tslib: 2.5.0 dev: false - /use-sync-external-store/1.2.0_react@18.2.0: - resolution: { integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== } - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - react: 18.2.0 - dev: false - /util-deprecate/1.0.2: resolution: { integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== } dev: true diff --git a/src-tauri/migrations/20230226004139_create_tables.sql b/src-tauri/migrations/20230226004139_create_tables.sql index a35c977e..7e923494 100644 --- a/src-tauri/migrations/20230226004139_create_tables.sql +++ b/src-tauri/migrations/20230226004139_create_tables.sql @@ -1,4 +1,28 @@ -- Add migration script here +-- create relays +CREATE TABLE + relays ( + id INTEGER PRIMARY KEY, + relay_url TEXT NOT NULL, + relay_status INTEGER NOT NULL DEFAULT 1, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + +INSERT INTO + relays (relay_url, relay_status) +VALUES + ("wss://relay.damus.io", "1"), + ("wss://relay.uselume.xyz", "0"), + ("wss://nostr-pub.wellorder.net", "1"), + ("wss://nostr.bongbong.com", "1"), + ("wss://nostr.zebedee.cloud", "1"), + ("wss://nostr.fmt.wiz.biz", "1"), + ("wss://nostr.walletofsatoshi.com", "1"), + ("wss://relay.snort.social", "1"), + ("wss://offchain.pub", "1"), + ("wss://nos.lol", "1"); + -- create accounts CREATE TABLE accounts ( @@ -6,6 +30,7 @@ CREATE TABLE privkey TEXT NOT NULL, npub TEXT NOT NULL, nsec TEXT NOT NULL, + is_active INTEGER NOT NULL DEFAULT 0, metadata JSON ); @@ -40,5 +65,6 @@ CREATE TABLE kind INTEGER NOT NULL DEFAULT 1, tags TEXT NOT NULL, content TEXT NOT NULL, + relay TEXT, is_multi BOOLEAN DEFAULT 0 ); \ No newline at end of file diff --git a/src/components/accountBar/index.tsx b/src/components/accountBar/index.tsx index d32cc447..515a2af4 100644 --- a/src/components/accountBar/index.tsx +++ b/src/components/accountBar/index.tsx @@ -1,19 +1,16 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Account } from '@components/accountBar/account'; -import { currentUser } from '@stores/currentUser'; - import LumeSymbol from '@assets/icons/Lume'; - -import { useStore } from '@nanostores/react'; import { PlusIcon } from '@radix-ui/react-icons'; +import { useLocalStorage } from '@rehooks/local-storage'; import Link from 'next/link'; import { useCallback, useEffect, useState } from 'react'; import Database from 'tauri-plugin-sql-api'; export default function AccountBar() { const [users, setUsers] = useState([]); - const $currentUser: any = useStore(currentUser); + const [currentUser]: any = useLocalStorage('current-user'); const getAccounts = useCallback(async () => { const db = await Database.load('sqlite:lume.db'); @@ -30,7 +27,7 @@ export default function AccountBar() {
{users.map((user, index) => ( - + ))} { @@ -35,11 +32,11 @@ export const NoteConnector = memo(function NoteConnector() { [ { kinds: [1], - authors: $follows, + authors: follows, since: dateToUnix(hoursAgo(12, now.current)), }, ], - $relays, + relays, (event: any) => { insertDB(event).catch(console.error); }, diff --git a/src/components/contexts/database.tsx b/src/components/contexts/database.tsx index c4059a99..45f3032b 100644 --- a/src/components/contexts/database.tsx +++ b/src/components/contexts/database.tsx @@ -1,13 +1,56 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { createContext } from 'react'; +import { writeStorage } from '@rehooks/local-storage'; +import { createContext, useEffect, useMemo } from 'react'; import Database from 'tauri-plugin-sql-api'; export const DatabaseContext = createContext({}); -const db = typeof window !== 'undefined' ? await Database.load('sqlite:lume.db') : null; +const initDB = typeof window !== 'undefined' ? await Database.load('sqlite:lume.db') : null; export default function DatabaseProvider({ children }: { children: React.ReactNode }) { - const value = db; + const db = useMemo(() => initDB, []); - return {children}; + useEffect(() => { + const getRelays = async () => { + const arr = []; + const result: any[] = await db.select('SELECT relay_url FROM relays WHERE relay_status = "1"'); + + result.forEach((item: { relay_url: string }) => { + arr.push(item.relay_url); + }); + + writeStorage('relays', arr); + }; + + const getAccount = async () => { + const result = await db.select(`SELECT * FROM accounts LIMIT 1`); + writeStorage('current-user', result[0]); + + return result[0]; + }; + + const getFollows = async (id: string) => { + const arr = []; + const result: any[] = await db.select(`SELECT pubkey FROM follows WHERE account = "${id}"`); + + result.forEach((item: { pubkey: string }) => { + arr.push(item.pubkey); + }); + + writeStorage('follows', arr); + }; + + if (db !== null) { + getRelays().catch(console.error); + getAccount() + .then((res) => { + if (res) { + getFollows(res.id).catch(console.error); + } + }) + .catch(console.error); + } + }, [db]); + + return {children}; } diff --git a/src/components/navigatorBar/createPost.tsx b/src/components/navigatorBar/createPost.tsx index 2ce53f11..957355b2 100644 --- a/src/components/navigatorBar/createPost.tsx +++ b/src/components/navigatorBar/createPost.tsx @@ -1,8 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { currentUser } from '@stores/currentUser'; - -import { useStore } from '@nanostores/react'; import * as Dialog from '@radix-ui/react-dialog'; +import { useLocalStorage } from '@rehooks/local-storage'; import * as commands from '@uiw/react-md-editor/lib/commands'; import dynamic from 'next/dynamic'; import { dateToUnix, useNostr } from 'nostr-react'; @@ -17,9 +15,9 @@ export default function CreatePost() { const { publish } = useNostr(); const [value, setValue] = useState(''); - const $currentUser: any = useStore(currentUser); - const pubkey = $currentUser.pubkey; - const privkey = $currentUser.privkey; + const [currentUser]: any = useLocalStorage('current-user'); + const pubkey = currentUser.pubkey; + const privkey = currentUser.privkey; const postButton = { name: 'post', @@ -27,9 +25,7 @@ export default function CreatePost() { buttonProps: { className: 'cta-btn', 'aria-label': 'Post a message' }, icon: (
- - Post - + Post
), diff --git a/src/components/navigatorBar/index.tsx b/src/components/navigatorBar/index.tsx index 6b62181f..904fd70e 100644 --- a/src/components/navigatorBar/index.tsx +++ b/src/components/navigatorBar/index.tsx @@ -4,14 +4,12 @@ import { NoteConnector } from '@components/connectors/note'; import CreatePost from '@components/navigatorBar/createPost'; import { ProfileMenu } from '@components/navigatorBar/profileMenu'; -import { currentUser } from '@stores/currentUser'; - -import { useStore } from '@nanostores/react'; import { PlusIcon } from '@radix-ui/react-icons'; +import { useLocalStorage } from '@rehooks/local-storage'; export default function NavigatorBar() { - const $currentUser: any = useStore(currentUser); - const profile = $currentUser.metadata !== undefined ? JSON.parse($currentUser.metadata) : { display_name: null, username: null }; + const [currentUser]: any = useLocalStorage('current-user'); + const profile = currentUser.metadata !== undefined ? JSON.parse(currentUser.metadata) : { display_name: null, username: null }; return (
@@ -25,7 +23,7 @@ export default function NavigatorBar() {
{profile.display_name || ''}
- +
@{profile.username || ''}
diff --git a/src/components/note/atoms/reaction.tsx b/src/components/note/atoms/reaction.tsx index 8665fc78..7c2a36cd 100644 --- a/src/components/note/atoms/reaction.tsx +++ b/src/components/note/atoms/reaction.tsx @@ -1,26 +1,18 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { currentUser } from '@stores/currentUser'; - -import { useStore } from '@nanostores/react'; import { HeartFilledIcon, HeartIcon } from '@radix-ui/react-icons'; +import { useLocalStorage } from '@rehooks/local-storage'; import { dateToUnix, useNostr, useNostrEvents } from 'nostr-react'; import { getEventHash, signEvent } from 'nostr-tools'; import { useState } from 'react'; -export default function Reaction({ - eventID, - eventPubkey, -}: { - eventID: string; - eventPubkey: string; -}) { +export default function Reaction({ eventID, eventPubkey }: { eventID: string; eventPubkey: string }) { const { publish } = useNostr(); const [reaction, setReaction] = useState(0); const [isReact, setIsReact] = useState(false); - const $currentUser: any = useStore(currentUser); - const pubkey = $currentUser.pubkey; - const privkey = $currentUser.privkey; + const [currentUser]: any = useLocalStorage('current-user'); + const pubkey = currentUser.pubkey; + const privkey = currentUser.privkey; const { onEvent } = useNostrEvents({ filter: { @@ -65,15 +57,9 @@ export default function Reaction({ }; return ( - diff --git a/src/layouts/userLayout.tsx b/src/layouts/userLayout.tsx index b04a159b..814472e1 100644 --- a/src/layouts/userLayout.tsx +++ b/src/layouts/userLayout.tsx @@ -2,12 +2,10 @@ import AccountBar from '@components/accountBar'; import ActiveLink from '@components/activeLink'; -import { currentUser } from '@stores/currentUser'; - -import { useStore } from '@nanostores/react'; +import { useLocalStorage } from '@rehooks/local-storage'; export default function UserLayout({ children }: { children: React.ReactNode }) { - const $currentUser: any = useStore(currentUser); + const [currentUser]: any = useLocalStorage('current-user'); return (
@@ -27,13 +25,13 @@ export default function UserLayout({ children }: { children: React.ReactNode })
Personal Page Update Profile diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index ff4c5514..b72c3c50 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -2,9 +2,7 @@ import DatabaseProvider from '@components/contexts/database'; import RelayProvider from '@components/contexts/relay'; -import { relays } from '@stores/relays'; - -import { useStore } from '@nanostores/react'; +import { useLocalStorage } from '@rehooks/local-storage'; import type { NextPage } from 'next'; import type { AppProps } from 'next/app'; import { ReactElement, ReactNode } from 'react'; @@ -23,12 +21,12 @@ type AppPropsWithLayout = AppProps & { export default function MyApp({ Component, pageProps }: AppPropsWithLayout) { // Use the layout defined at the page level, if available const getLayout = Component.getLayout ?? ((page) => page); - // Get all relays - const $relays = useStore(relays); + // Get relays from localstorage + const [relays] = useLocalStorage('relays'); return ( - {getLayout()} + {getLayout()} ); } diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 688b4954..661ef1f2 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -2,90 +2,32 @@ import BaseLayout from '@layouts/baseLayout'; import FullLayout from '@layouts/fullLayout'; -import { DatabaseContext } from '@components/contexts/database'; - -import { currentUser } from '@stores/currentUser'; -import { follows } from '@stores/follows'; - import LumeSymbol from '@assets/icons/Lume'; - -import { isPermissionGranted, requestPermission, sendNotification } from '@tauri-apps/api/notification'; +import { useLocalStorage } from '@rehooks/local-storage'; import { motion } from 'framer-motion'; import { useRouter } from 'next/router'; -import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useCallback, useContext, useEffect, useState } from 'react'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useEffect, useState } from 'react'; export default function Page() { - const db: any = useContext(DatabaseContext); - const router = useRouter(); + + const [currentUser]: any = useLocalStorage('current-user'); const [loading, setLoading] = useState(true); - const requestNotification = useCallback(async () => { - // NOTE: notification don't work in dev mode (only affect MacOS) - // ref: https://github.com/tauri-apps/tauri/issues/4965 - let permissionGranted = await isPermissionGranted(); - if (!permissionGranted) { - const permission = await requestPermission(); - permissionGranted = permission === 'granted'; - } - if (permissionGranted) { - sendNotification({ title: 'Lume', body: 'Nostr is awesome' }); - } - - return permissionGranted; - }, []); - - const getAccount = useCallback(async () => { - const result = await db.select(`SELECT * FROM accounts ASC LIMIT 1`); - return result; - }, [db]); - - const getFollows = useCallback( - async (account: { id: string }) => { - const arr = []; - const result: any = await db.select(`SELECT pubkey FROM follows WHERE account = "${account.id}"`); - - result.forEach((item: { pubkey: string }) => { - arr.push(item.pubkey); - }); - - return arr; - }, - [db] - ); - - // Explain: - // Step 1: request allow notification from system - // Step 2: get first account. #TODO: get last used account instead (part of multi account feature) - // Step 3: get follows by account useEffect(() => { - requestNotification().then(() => { - getAccount() - .then((res: any) => { - if (res.length === 0) { - setTimeout(() => { - setLoading(false); - router.push('/onboarding'); - }, 1500); - } else { - // store current user in localstorage - currentUser.set(res[0]); - getFollows(res[0]) - .then(async (res) => { - // store follows in localstorage - follows.set(res); - // redirect to newsfeed - setTimeout(() => { - setLoading(false); - router.push('/feed/following'); - }, 1500); - }) - .catch(console.error); - } - }) - .catch(console.error); - }); - }, [requestNotification, getAccount, getFollows, router]); + console.log(currentUser); + if (!currentUser) { + setTimeout(() => { + setLoading(false); + router.push('/onboarding'); + }, 1500); + } else { + setTimeout(() => { + setLoading(false); + router.push('/feed/following'); + }, 1500); + } + }, [currentUser, router]); return (
diff --git a/src/pages/onboarding/create.tsx b/src/pages/onboarding/create/index.tsx similarity index 88% rename from src/pages/onboarding/create.tsx rename to src/pages/onboarding/create/index.tsx index c836db7f..7958e985 100644 --- a/src/pages/onboarding/create.tsx +++ b/src/pages/onboarding/create/index.tsx @@ -5,16 +5,13 @@ import OnboardingLayout from '@layouts/onboardingLayout'; import { DatabaseContext } from '@components/contexts/database'; import { RelayContext } from '@components/contexts/relay'; -import { currentUser } from '@stores/currentUser'; -import { relays } from '@stores/relays'; - -import { useStore } from '@nanostores/react'; import { EyeClosedIcon, EyeOpenIcon } from '@radix-ui/react-icons'; +import { useLocalStorage, writeStorage } from '@rehooks/local-storage'; import { motion } from 'framer-motion'; import Image from 'next/image'; import { useRouter } from 'next/router'; import { generatePrivateKey, getEventHash, getPublicKey, nip19, signEvent } from 'nostr-tools'; -import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useState } from 'react'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useCallback, useContext, useMemo, useState } from 'react'; import { Config, names, uniqueNamesGenerator } from 'unique-names-generator'; const config: Config = { @@ -22,11 +19,12 @@ const config: Config = { }; export default function Page() { - const db: any = useContext(DatabaseContext); const router = useRouter(); + const { db }: any = useContext(DatabaseContext); const relayPool: any = useContext(RelayContext); - const $relays = useStore(relays); + + const [relays] = useLocalStorage('relays'); const [type, setType] = useState('password'); const [loading, setLoading] = useState(false); @@ -47,13 +45,22 @@ export default function Page() { }; // auto-generated profile - const data = { - display_name: name, - name: name, - username: name.toLowerCase(), - picture: 'https://bafybeidfsbrzqbvontmucteomoz2rkrxugu462l5hyhh6uioslkfzzs4oq.ipfs.w3s.link/avatar-11.png', - banner: 'https://bafybeiacwit7hjmdefqggxqtgh6ht5dhth7ndptwn2msl5kpkodudsr7py.ipfs.w3s.link/banner-1.jpg', - }; + const data = useMemo( + () => ({ + display_name: name, + name: name, + username: name.toLowerCase(), + picture: 'https://bafybeidfsbrzqbvontmucteomoz2rkrxugu462l5hyhh6uioslkfzzs4oq.ipfs.w3s.link/avatar-11.png', + banner: 'https://bafybeiacwit7hjmdefqggxqtgh6ht5dhth7ndptwn2msl5kpkodudsr7py.ipfs.w3s.link/banner-1.jpg', + }), + [name] + ); + + const insertDB = useCallback(async () => { + await db.execute( + `INSERT INTO accounts (id, privkey, npub, nsec, metadata) VALUES ("${pubKey}", "${privKey}", "${npub}", "${nsec}", '${JSON.stringify(data)}')` + ); + }, [data, db, npub, nsec, privKey, pubKey]); const createAccount = async () => { setLoading(true); @@ -68,27 +75,25 @@ export default function Page() { }; event.id = getEventHash(event); event.sig = signEvent(event, privKey); - // publish to relays - relayPool.publish(event, $relays); - // save account to database - await db.execute( - `INSERT INTO accounts (id, privkey, npub, nsec, metadata) VALUES ("${pubKey}", "${privKey}", "${npub}", "${nsec}", '${JSON.stringify(data)}')` - ); - - // set currentUser in global state - currentUser.set({ - metadata: JSON.stringify(data), - npub: npub, - privkey: privKey, - pubkey: pubKey, - }); - - // redirect to pre-follow - setTimeout(() => { - setLoading(false); - router.push('/onboarding/following'); - }, 1500); + insertDB() + .then(() => { + // publish to relays + relayPool.publish(event, relays); + // set currentUser in global state + writeStorage('current-user', { + metadata: JSON.stringify(data), + npub: npub, + privkey: privKey, + pubkey: pubKey, + }); + // redirect to pre-follow + setTimeout(() => { + setLoading(false); + router.push('/onboarding/create/pre-follows'); + }, 1500); + }) + .catch(console.error); }; return ( diff --git a/src/pages/onboarding/following.tsx b/src/pages/onboarding/create/pre-follows.tsx similarity index 93% rename from src/pages/onboarding/following.tsx rename to src/pages/onboarding/create/pre-follows.tsx index 7ced300c..762a70f3 100644 --- a/src/pages/onboarding/following.tsx +++ b/src/pages/onboarding/create/pre-follows.tsx @@ -6,28 +6,25 @@ import { DatabaseContext } from '@components/contexts/database'; import { truncate } from '@utils/truncate'; -import { currentUser } from '@stores/currentUser'; - import data from '@assets/directory.json'; - -import { useStore } from '@nanostores/react'; import { CheckCircledIcon } from '@radix-ui/react-icons'; +import { useLocalStorage } from '@rehooks/local-storage'; import { motion } from 'framer-motion'; import Image from 'next/image'; import { useRouter } from 'next/router'; import { nip19 } from 'nostr-tools'; import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useState } from 'react'; +const shuffle = (arr: { name: string; avatar: string; npub: string }[]) => [...arr].sort(() => Math.random() - 0.5); + export default function Page() { const db: any = useContext(DatabaseContext); const router = useRouter(); - const shuffle = (arr) => [...arr].sort(() => Math.random() - 0.5); - const [follow, setFollow] = useState([]); const [loading, setLoading] = useState(false); const [list] = useState(shuffle(data)); - const $currentUser: any = useStore(currentUser); + const [currentUser]: any = useLocalStorage('current-user'); const followUser = (e) => { const npub = e.currentTarget.getAttribute('data-npub'); @@ -36,11 +33,11 @@ export default function Page() { const insertDB = async () => { // self follow - await db.execute(`INSERT INTO follows (pubkey, account, kind) VALUES ("${$currentUser.pubkey}", "${$currentUser.pubkey}", "0")`); + await db.execute(`INSERT INTO follows (pubkey, account, kind) VALUES ("${currentUser.pubkey}", "${currentUser.pubkey}", "0")`); // follow selected follow.forEach(async (npub) => { const { data } = nip19.decode(npub); - await db.execute(`INSERT INTO follows (pubkey, account, kind) VALUES ("${data}", "${$currentUser.pubkey}", "0")`); + await db.execute(`INSERT INTO follows (pubkey, account, kind) VALUES ("${data}", "${currentUser.pubkey}", "0")`); }); }; diff --git a/src/pages/onboarding/fetch-profile.tsx b/src/pages/onboarding/fetch-profile.tsx deleted file mode 100644 index a5ecd28c..00000000 --- a/src/pages/onboarding/fetch-profile.tsx +++ /dev/null @@ -1,116 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import BaseLayout from '@layouts/baseLayout'; -import OnboardingLayout from '@layouts/onboardingLayout'; - -import { DatabaseContext } from '@components/contexts/database'; -import { RelayContext } from '@components/contexts/relay'; - -import { relays } from '@stores/relays'; - -import { useStore } from '@nanostores/react'; -import { motion } from 'framer-motion'; -import { useRouter } from 'next/router'; -import { getPublicKey, nip19 } from 'nostr-tools'; -import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useCallback, useContext, useEffect, useState } from 'react'; - -export default function Page() { - const db: any = useContext(DatabaseContext); - const relayPool: any = useContext(RelayContext); - const $relays = useStore(relays); - - const router = useRouter(); - const { privkey }: any = router.query; - - const [account, setAccount] = useState(null); - const [loading, setLoading] = useState(false); - - const pubkey = privkey ? getPublicKey(privkey) : null; - const npub = privkey ? nip19.npubEncode(pubkey) : null; - const nsec = privkey ? nip19.nsecEncode(privkey) : null; - - relayPool.subscribe( - [ - { - authors: [pubkey], - kinds: [0], - }, - ], - $relays, - (event: any) => { - const metadata = JSON.parse(event.content); - setAccount(metadata); - }, - undefined, - (events: any, relayURL: any) => { - console.log(events, relayURL); - } - ); - - const insertDB = useCallback(async () => { - // save account to database - const metadata = JSON.stringify(account); - await db.execute( - `INSERT INTO accounts (id, privkey, npub, nsec, metadata) VALUES ("${pubkey}", "${privkey}", "${npub}", "${nsec}", '${metadata}')` - ); - await db.close(); - }, [account, db, npub, nsec, privkey, pubkey]); - - useEffect(() => { - setLoading(true); - - if (account !== null) { - insertDB() - .then(() => { - setTimeout(() => { - setLoading(false); - router.push({ - pathname: '/onboarding/fetch-follows', - query: { pubkey: pubkey }, - }); - }, 1500); - }) - .catch(console.error); - } - }, [account, insertDB, npub, nsec, privkey, pubkey, router]); - - return ( -
-
{/* spacer */}
- -
- - Fetching your profile... - - - As long as you have private key, you alway can sync your profile on every nostr client, so please keep your key safely - -
-
- -
- {loading === true ? ( - - - - - ) : ( - <> - )} -
-
-
- ); -} - -Page.getLayout = function getLayout( - page: string | number | boolean | ReactElement> | ReactFragment | ReactPortal -) { - return ( - - {page} - - ); -}; diff --git a/src/pages/onboarding/index.tsx b/src/pages/onboarding/index.tsx index 0075558d..718357f0 100644 --- a/src/pages/onboarding/index.tsx +++ b/src/pages/onboarding/index.tsx @@ -10,9 +10,7 @@ export default function Page() {
{/* spacer */}
- + Other social network require email/password
nostr use{' '} @@ -21,8 +19,8 @@ export default function Page() {
- If you have used nostr before, you can import your own private key. Otherwise, you can - create a new key or use auto-generated account created by system. + If you have used nostr before, you can import your own private key. Otherwise, you can create a new key or use auto-generated account + created by system. @@ -32,7 +30,7 @@ export default function Page() { Create new key Login with private key @@ -44,13 +42,7 @@ export default function Page() { } Page.getLayout = function getLayout( - page: - | string - | number - | boolean - | ReactElement> - | ReactFragment - | ReactPortal + page: string | number | boolean | ReactElement> | ReactFragment | ReactPortal ) { return ( diff --git a/src/pages/onboarding/fetch-follows.tsx b/src/pages/onboarding/login/fetch.tsx similarity index 57% rename from src/pages/onboarding/fetch-follows.tsx rename to src/pages/onboarding/login/fetch.tsx index b9406b9a..97daf505 100644 --- a/src/pages/onboarding/fetch-follows.tsx +++ b/src/pages/onboarding/login/fetch.tsx @@ -5,35 +5,69 @@ import OnboardingLayout from '@layouts/onboardingLayout'; import { DatabaseContext } from '@components/contexts/database'; import { RelayContext } from '@components/contexts/relay'; -import { relays } from '@stores/relays'; - -import { useStore } from '@nanostores/react'; +import { useLocalStorage } from '@rehooks/local-storage'; import { motion } from 'framer-motion'; +import Link from 'next/link'; import { useRouter } from 'next/router'; -import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useEffect, useState } from 'react'; +import { getPublicKey, nip19 } from 'nostr-tools'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useCallback, useContext, useMemo, useState } from 'react'; export default function Page() { - const db: any = useContext(DatabaseContext); + const { db }: any = useContext(DatabaseContext); const relayPool: any = useContext(RelayContext); - const $relays = useStore(relays); + + const [loading, setLoading] = useState(false); + const [relays] = useLocalStorage('relays'); const router = useRouter(); - const { pubkey }: any = router.query; + const { privkey }: any = router.query; - const [follows, setFollows] = useState([null]); - const [loading, setLoading] = useState(false); + const pubkey = useMemo(() => (privkey ? getPublicKey(privkey) : null), [privkey]); + + // save account to database + const insertAccount = useCallback( + async (metadata) => { + if (loading === false) { + const npub = privkey ? nip19.npubEncode(pubkey) : null; + const nsec = privkey ? nip19.nsecEncode(privkey) : null; + await db.execute( + `INSERT OR IGNORE INTO accounts (id, privkey, npub, nsec, metadata) VALUES ("${pubkey}", "${privkey}", "${npub}", "${nsec}", '${metadata}')` + ); + setLoading(true); + } + }, + [db, privkey, pubkey, loading] + ); + + // save follows to database + const insertFollows = useCallback( + async (follows) => { + follows.forEach(async (item) => { + if (item) { + await db.execute(`INSERT OR IGNORE INTO follows (pubkey, account, kind) VALUES ("${item[1]}", "${pubkey}", "0")`); + } + }); + }, + [db, pubkey] + ); relayPool.subscribe( [ { authors: [pubkey], - kinds: [0], + kinds: [0, 3], since: 0, }, ], - $relays, + relays, (event: any) => { - setFollows(event.tags); + if (event.kind === 0) { + insertAccount(event.content); + } else { + if (event.tags.length > 0) { + insertFollows(event.tags); + } + } }, undefined, (events: any, relayURL: any) => { @@ -41,39 +75,16 @@ export default function Page() { } ); - useEffect(() => { - setLoading(true); - - const insertDB = async () => { - follows.forEach(async (item) => { - if (item) { - await db.execute(`INSERT OR IGNORE INTO follows (pubkey, account, kind) VALUES ("${item[1]}", "${pubkey}", "0")`); - } - }); - }; - - if (follows !== null && follows.length > 0) { - insertDB() - .then(() => { - setTimeout(() => { - setLoading(false); - router.push('/'); - }, 1500); - }) - .catch(console.error); - } - }, [db, follows, pubkey, router]); - return (
{/* spacer */}
- Fetching your follows... + Fetching your profile... - Not only profile, every nostr client can sync your follows list when you move to a new client, so please keep your key safely (again) + As long as you have private key, you alway can sync your profile and follows list on every nostr client, so please keep your key safely
@@ -88,7 +99,11 @@ export default function Page() { d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"> ) : ( - <> + + Finish + )}
diff --git a/src/pages/onboarding/import.tsx b/src/pages/onboarding/login/index.tsx similarity index 98% rename from src/pages/onboarding/import.tsx rename to src/pages/onboarding/login/index.tsx index 454fae06..3f883224 100644 --- a/src/pages/onboarding/import.tsx +++ b/src/pages/onboarding/login/index.tsx @@ -44,7 +44,7 @@ export default function Page() { try { router.push({ - pathname: '/onboarding/fetch-profile', + pathname: '/onboarding/login/fetch', query: { privkey: privkey }, }); } catch (error) { diff --git a/src/pages/profile/update.tsx b/src/pages/profile/update.tsx index fa0996bd..4b018bf2 100644 --- a/src/pages/profile/update.tsx +++ b/src/pages/profile/update.tsx @@ -2,9 +2,7 @@ import BaseLayout from '@layouts/baseLayout'; import UserLayout from '@layouts/userLayout'; -import { currentUser } from '@stores/currentUser'; - -import { useStore } from '@nanostores/react'; +import { useLocalStorage } from '@rehooks/local-storage'; import { useRouter } from 'next/router'; import { dateToUnix, useNostr } from 'nostr-react'; import { getEventHash, signEvent } from 'nostr-tools'; @@ -28,11 +26,8 @@ export default function Page() { const { publish } = useNostr(); const [loading, setLoading] = useState(false); - const $currentUser: any = useStore(currentUser); - const profile = - $currentUser.metadata !== undefined - ? JSON.parse($currentUser.metadata) - : { display_name: null, username: null }; + const [currentUser]: any = useLocalStorage('current-user'); + const profile = currentUser.metadata !== undefined ? JSON.parse(currentUser.metadata) : { display_name: null, username: null }; const { register, @@ -48,28 +43,24 @@ export default function Page() { content: JSON.stringify(data), created_at: dateToUnix(), kind: 0, - pubkey: $currentUser.pubkey, + pubkey: currentUser.pubkey, tags: [], }; event.id = getEventHash(event); - event.sig = signEvent(event, $currentUser.privkey); + event.sig = signEvent(event, currentUser.privkey); publish(event); // save account to database const db = await Database.load('sqlite:lume.db'); - await db.execute( - `UPDATE accounts SET metadata = '${JSON.stringify(data)}' WHERE pubkey = "${ - $currentUser.pubkey - }"` - ); + await db.execute(`UPDATE accounts SET metadata = '${JSON.stringify(data)}' WHERE pubkey = "${currentUser.pubkey}"`); await db.close(); // set currentUser in global state currentUser.set({ metadata: JSON.stringify(data), - npub: $currentUser.npub, - privkey: $currentUser.privkey, - pubkey: $currentUser.pubkey, + npub: currentUser.npub, + privkey: currentUser.privkey, + pubkey: currentUser.pubkey, }); // redirect to newsfeed @@ -80,16 +71,11 @@ export default function Page() { }; return ( -
+
-

- Update profile -

+

Update profile

- Your profile will be published to all relays, as long as you have the private key, you - always can recover your profile in any client + Your profile will be published to all relays, as long as you have the private key, you always can recover your profile in any client

@@ -105,9 +91,7 @@ export default function Page() { className="relative w-full rounded-lg border border-black/5 px-3.5 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-500" />
- - {errors.display_name &&

{errors.display_name.message}

} -
+ {errors.display_name &&

{errors.display_name.message}

}
@@ -122,9 +106,7 @@ export default function Page() { className="relative w-full rounded-lg border border-black/5 px-3.5 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-500" />
- - {errors.name &&

{errors.name.message}

} -
+ {errors.name &&

{errors.name.message}

}
@@ -139,9 +121,7 @@ export default function Page() { className="relative w-full rounded-lg border border-black/5 px-3.5 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-500" />
- - {errors.username &&

{errors.username.message}

} -
+ {errors.username &&

{errors.username.message}

}
@@ -156,9 +136,7 @@ export default function Page() { className="relative w-full rounded-lg border border-black/5 px-3.5 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-500" />
- - {errors.picture &&

{errors.picture.message}

} -
+ {errors.picture &&

{errors.picture.message}

}
@@ -173,9 +151,7 @@ export default function Page() { className="relative w-full rounded-lg border border-black/5 px-3.5 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-500" />
- - {errors.banner &&

{errors.banner.message}

} -
+ {errors.banner &&

{errors.banner.message}

}
@@ -190,27 +166,15 @@ export default function Page() { className="relative h-24 w-full resize-none rounded-lg border border-black/5 px-3.5 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-500" />
- - {errors.about &&

{errors.about.message}

} -
+ {errors.about &&

{errors.about.message}

}
{loading === true ? ( - - + + > - | ReactFragment - | ReactPortal + page: string | number | boolean | ReactElement> | ReactFragment | ReactPortal ) { return ( diff --git a/src/stores/currentUser.tsx b/src/stores/currentUser.tsx deleted file mode 100644 index ddfc4912..00000000 --- a/src/stores/currentUser.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { persistentAtom } from '@nanostores/persistent'; - -export const currentUser = persistentAtom( - 'currentUser', - {}, - { - encode: JSON.stringify, - decode: JSON.parse, - } -); diff --git a/src/stores/follows.tsx b/src/stores/follows.tsx deleted file mode 100644 index 8016660d..00000000 --- a/src/stores/follows.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { persistentAtom } from '@nanostores/persistent'; - -export const follows = persistentAtom('follows', [], { - encode(value) { - return JSON.stringify(value); - }, - decode(value) { - return JSON.parse(value); - }, -}); diff --git a/src/stores/relays.tsx b/src/stores/relays.tsx deleted file mode 100644 index 27344318..00000000 --- a/src/stores/relays.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { persistentAtom } from '@nanostores/persistent'; - -export const relays = persistentAtom( - 'relays', - [ - 'wss://relay.uselume.xyz', - 'wss://nostr-pub.wellorder.net', - 'wss://nostr.bongbong.com', - 'wss://nostr.zebedee.cloud', - 'wss://nostr.fmt.wiz.biz', - 'wss://nostr.walletofsatoshi.com', - 'wss://relay.snort.social', - 'wss://offchain.pub', - 'wss://nos.lol', - 'wss://relay.damus.io', - ], - { - encode(value) { - return JSON.stringify(value); - }, - decode(value) { - return JSON.parse(value); - }, - } -); diff --git a/tsconfig.json b/tsconfig.json index 99c5f7e8..db64c2f8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,6 @@ "@layouts/*": ["src/layouts/*"], "@components/*": ["src/components/*"], "@utils/*": ["src/utils/*"], - "@stores/*": ["src/stores/*"], "@assets/*": ["src/assets/*"] }, "target": "es2017", From 3b78123939b406570c29ea91a69b13cb03b89e8e Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Wed, 1 Mar 2023 21:19:31 +0700 Subject: [PATCH 14/21] fixed duplicate connection --- src/components/connectors/note.tsx | 2 +- src/components/contexts/database.tsx | 31 ++++++++--------- src/components/navigatorBar/index.tsx | 2 +- src/components/note/atoms/user.tsx | 1 - .../note/atoms/userWithUsername.tsx | 33 ++++--------------- src/pages/feed/following.tsx | 12 ++++--- src/pages/index.tsx | 1 - src/pages/profile/update.tsx | 1 - 8 files changed, 31 insertions(+), 52 deletions(-) diff --git a/src/components/connectors/note.tsx b/src/components/connectors/note.tsx index dcbe0f0c..ebe099a4 100644 --- a/src/components/connectors/note.tsx +++ b/src/components/connectors/note.tsx @@ -8,7 +8,7 @@ import { useLocalStorage } from '@rehooks/local-storage'; import { memo, useCallback, useContext, useRef } from 'react'; export const NoteConnector = memo(function NoteConnector() { - const db: any = useContext(DatabaseContext); + const { db }: any = useContext(DatabaseContext); const relayPool: any = useContext(RelayContext); const now = useRef(new Date()); diff --git a/src/components/contexts/database.tsx b/src/components/contexts/database.tsx index 45f3032b..84116eeb 100644 --- a/src/components/contexts/database.tsx +++ b/src/components/contexts/database.tsx @@ -1,14 +1,14 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { writeStorage } from '@rehooks/local-storage'; -import { createContext, useEffect, useMemo } from 'react'; +import { createContext, useEffect, useState } from 'react'; import Database from 'tauri-plugin-sql-api'; export const DatabaseContext = createContext({}); -const initDB = typeof window !== 'undefined' ? await Database.load('sqlite:lume.db') : null; +const db = typeof window !== 'undefined' ? await Database.load('sqlite:lume.db') : null; export default function DatabaseProvider({ children }: { children: React.ReactNode }) { - const db = useMemo(() => initDB, []); + const [done, setDone] = useState(false); useEffect(() => { const getRelays = async () => { @@ -40,17 +40,18 @@ export default function DatabaseProvider({ children }: { children: React.ReactNo writeStorage('follows', arr); }; - if (db !== null) { - getRelays().catch(console.error); - getAccount() - .then((res) => { - if (res) { - getFollows(res.id).catch(console.error); - } - }) - .catch(console.error); - } - }, [db]); + getRelays().catch(console.error); + getAccount() + .then((res) => { + if (res) { + getFollows(res.id).catch(console.error); + } + setDone(true); + }) + .catch(console.error); + }, []); - return {children}; + if (done === true) { + return {children}; + } } diff --git a/src/components/navigatorBar/index.tsx b/src/components/navigatorBar/index.tsx index 904fd70e..6d9d3d85 100644 --- a/src/components/navigatorBar/index.tsx +++ b/src/components/navigatorBar/index.tsx @@ -9,7 +9,7 @@ import { useLocalStorage } from '@rehooks/local-storage'; export default function NavigatorBar() { const [currentUser]: any = useLocalStorage('current-user'); - const profile = currentUser.metadata !== undefined ? JSON.parse(currentUser.metadata) : { display_name: null, username: null }; + const profile = JSON.parse(currentUser.metadata); return (
diff --git a/src/components/note/atoms/user.tsx b/src/components/note/atoms/user.tsx index 44ae2d45..464800e5 100644 --- a/src/components/note/atoms/user.tsx +++ b/src/components/note/atoms/user.tsx @@ -39,7 +39,6 @@ export const User = memo(function User({ pubkey, time }: { pubkey: string; time: useEffect(() => { const initialProfile = async () => { const result: any = await db.select(`SELECT metadata FROM cache_profiles WHERE id = "${pubkey}"`); - db.close; return result; }; diff --git a/src/components/note/atoms/userWithUsername.tsx b/src/components/note/atoms/userWithUsername.tsx index abc6b50f..a581599c 100644 --- a/src/components/note/atoms/userWithUsername.tsx +++ b/src/components/note/atoms/userWithUsername.tsx @@ -26,11 +26,7 @@ export const UserWithUsername = memo(function UserWithUsername({ pubkey }: { pub const metadata: any = JSON.parse(rawMetadata.content); if (profile.picture === null || profile.name === null) { setProfile(metadata); - await db.execute( - `INSERT OR IGNORE INTO cache_profiles (pubkey, metadata) VALUES ("${pubkey}", '${JSON.stringify( - metadata - )}')` - ); + await db.execute(`INSERT OR IGNORE INTO cache_profiles (pubkey, metadata) VALUES ("${pubkey}", '${JSON.stringify(metadata)}')`); } else { return; } @@ -41,10 +37,7 @@ export const UserWithUsername = memo(function UserWithUsername({ pubkey }: { pub useEffect(() => { const initialProfile = async () => { - const result: any = await db.select( - `SELECT metadata FROM cache_profiles WHERE pubkey = "${pubkey}"` - ); - db.close; + const result: any = await db.select(`SELECT metadata FROM cache_profiles WHERE pubkey = "${pubkey}"`); return result; }; @@ -61,30 +54,16 @@ export const UserWithUsername = memo(function UserWithUsername({ pubkey }: { pub
{profile.picture ? ( - + ) : ( - + )}
- - {profile.name ? profile.name : truncate(pubkey, 16, ' .... ')} - - - {profile.username ? profile.username : truncate(pubkey, 16, ' .... ')} - + {profile.name ? profile.name : truncate(pubkey, 16, ' .... ')} + {profile.username ? profile.username : truncate(pubkey, 16, ' .... ')}
diff --git a/src/pages/feed/following.tsx b/src/pages/feed/following.tsx index 165420ff..a1dd9072 100644 --- a/src/pages/feed/following.tsx +++ b/src/pages/feed/following.tsx @@ -7,20 +7,22 @@ import { Placeholder } from '@components/note/placeholder'; import { Repost } from '@components/note/repost'; import { Single } from '@components/note/single'; +import { useLocalStorage, writeStorage } from '@rehooks/local-storage'; import { useCallback } from 'react'; -import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useEffect, useRef, useState } from 'react'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useEffect, useRef } from 'react'; import { Virtuoso } from 'react-virtuoso'; export default function Page() { - const db: any = useContext(DatabaseContext); - const [data, setData] = useState(() => []); + const { db }: any = useContext(DatabaseContext); + const [data]: any = useLocalStorage('notes'); + const limit = useRef(30); const offset = useRef(0); useEffect(() => { const getData = async () => { const result = await db.select(`SELECT * FROM cache_notes ORDER BY created_at DESC LIMIT ${limit.current}`); - setData(result); + writeStorage('notes', result); }; getData().catch(console.error); @@ -30,7 +32,7 @@ export default function Page() { offset.current += limit.current; // next query const result = await db.select(`SELECT * FROM cache_notes ORDER BY created_at DESC LIMIT ${limit.current} OFFSET ${offset.current}`); - setData((data) => [...data, ...result]); + writeStorage('notes', (data) => [...data, ...result]); }, [db]); const ItemContent = useCallback( diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 661ef1f2..544b4c4f 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -15,7 +15,6 @@ export default function Page() { const [loading, setLoading] = useState(true); useEffect(() => { - console.log(currentUser); if (!currentUser) { setTimeout(() => { setLoading(false); diff --git a/src/pages/profile/update.tsx b/src/pages/profile/update.tsx index 4b018bf2..37a93b57 100644 --- a/src/pages/profile/update.tsx +++ b/src/pages/profile/update.tsx @@ -53,7 +53,6 @@ export default function Page() { // save account to database const db = await Database.load('sqlite:lume.db'); await db.execute(`UPDATE accounts SET metadata = '${JSON.stringify(data)}' WHERE pubkey = "${currentUser.pubkey}"`); - await db.close(); // set currentUser in global state currentUser.set({ From 0dcba44c4d7e88324b738a521b819786678b4b20 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Wed, 1 Mar 2023 21:51:47 +0700 Subject: [PATCH 15/21] updated note connector --- src/components/navigatorBar/index.tsx | 4 -- .../note.tsx => note/connector.tsx} | 15 +++++- src/pages/feed/following.tsx | 53 ++++++++++--------- 3 files changed, 41 insertions(+), 31 deletions(-) rename src/components/{connectors/note.tsx => note/connector.tsx} (68%) diff --git a/src/components/navigatorBar/index.tsx b/src/components/navigatorBar/index.tsx index 6d9d3d85..8cd04bf7 100644 --- a/src/components/navigatorBar/index.tsx +++ b/src/components/navigatorBar/index.tsx @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import ActiveLink from '@components/activeLink'; -import { NoteConnector } from '@components/connectors/note'; import CreatePost from '@components/navigatorBar/createPost'; import { ProfileMenu } from '@components/navigatorBar/profileMenu'; @@ -15,9 +14,6 @@ export default function NavigatorBar() {
{/* main */}
-
- -
{/* Create post */}
diff --git a/src/components/connectors/note.tsx b/src/components/note/connector.tsx similarity index 68% rename from src/components/connectors/note.tsx rename to src/components/note/connector.tsx index ebe099a4..df09466f 100644 --- a/src/components/connectors/note.tsx +++ b/src/components/note/connector.tsx @@ -47,8 +47,19 @@ export const NoteConnector = memo(function NoteConnector() { ); return ( -
-

Note

+
+
+

# following

+
+
+
+ + + + +

Online

+
+
); }); diff --git a/src/pages/feed/following.tsx b/src/pages/feed/following.tsx index a1dd9072..177b4a4e 100644 --- a/src/pages/feed/following.tsx +++ b/src/pages/feed/following.tsx @@ -3,18 +3,18 @@ import BaseLayout from '@layouts/baseLayout'; import NewsFeedLayout from '@layouts/newsfeedLayout'; import { DatabaseContext } from '@components/contexts/database'; +import { NoteConnector } from '@components/note/connector'; import { Placeholder } from '@components/note/placeholder'; import { Repost } from '@components/note/repost'; import { Single } from '@components/note/single'; -import { useLocalStorage, writeStorage } from '@rehooks/local-storage'; -import { useCallback } from 'react'; +import { useCallback, useState } from 'react'; import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useEffect, useRef } from 'react'; import { Virtuoso } from 'react-virtuoso'; export default function Page() { const { db }: any = useContext(DatabaseContext); - const [data]: any = useLocalStorage('notes'); + const [data, setData] = useState([]); const limit = useRef(30); const offset = useRef(0); @@ -22,7 +22,7 @@ export default function Page() { useEffect(() => { const getData = async () => { const result = await db.select(`SELECT * FROM cache_notes ORDER BY created_at DESC LIMIT ${limit.current}`); - writeStorage('notes', result); + setData(result); }; getData().catch(console.error); @@ -32,7 +32,7 @@ export default function Page() { offset.current += limit.current; // next query const result = await db.select(`SELECT * FROM cache_notes ORDER BY created_at DESC LIMIT ${limit.current} OFFSET ${offset.current}`); - writeStorage('notes', (data) => [...data, ...result]); + setData((data) => [...data, ...result]); }, [db]); const ItemContent = useCallback( @@ -57,26 +57,29 @@ export default function Page() { ); return ( - , - ScrollSeekPlaceholder: () => , - }} - computeItemKey={computeItemKey} - scrollSeekConfiguration={{ - enter: (velocity) => Math.abs(velocity) > 800, - exit: (velocity) => Math.abs(velocity) < 500, - }} - endReached={loadMore} - overscan={800} - increaseViewportBy={1000} - className="scrollbar-hide relative h-full w-full rounded-lg" - style={{ - contain: 'strict', - }} - /> +
+ + , + ScrollSeekPlaceholder: () => , + }} + computeItemKey={computeItemKey} + scrollSeekConfiguration={{ + enter: (velocity) => Math.abs(velocity) > 800, + exit: (velocity) => Math.abs(velocity) < 500, + }} + endReached={loadMore} + overscan={800} + increaseViewportBy={1000} + className="scrollbar-hide relative h-full w-full" + style={{ + contain: 'strict', + }} + /> +
); } From 6d1b40d6dc60b578a8ebda46e64a861cdf2da0e3 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Wed, 1 Mar 2023 22:31:08 +0700 Subject: [PATCH 16/21] updated user profile component --- src/components/accountBar/account.tsx | 7 +-- src/components/contexts/relay.tsx | 2 +- src/components/note/atoms/user.tsx | 69 ++++++++++++++++----------- 3 files changed, 42 insertions(+), 36 deletions(-) diff --git a/src/components/accountBar/account.tsx b/src/components/accountBar/account.tsx index c5c13690..4f0c7357 100644 --- a/src/components/accountBar/account.tsx +++ b/src/components/accountBar/account.tsx @@ -16,12 +16,7 @@ export const Account = memo(function Account({ user, current }: { user: any; cur current === user.pubkey ? 'ring-1 ring-fuchsia-500 ring-offset-4 ring-offset-black' : '' }`}> {userData?.picture !== undefined ? ( - user's avatar + user's avatar ) : (
)} diff --git a/src/components/contexts/relay.tsx b/src/components/contexts/relay.tsx index 4bc45ad7..41b30048 100644 --- a/src/components/contexts/relay.tsx +++ b/src/components/contexts/relay.tsx @@ -5,7 +5,7 @@ import { createContext, useMemo } from 'react'; export const RelayContext = createContext({}); export default function RelayProvider({ relays, children }: { relays: any; children: React.ReactNode }) { - const value = useMemo(() => new RelayPool(relays, { useEventCache: false }), [relays]); + const value = useMemo(() => new RelayPool(relays, { useEventCache: true }), [relays]); return {children}; } diff --git a/src/components/note/atoms/user.tsx b/src/components/note/atoms/user.tsx index 464800e5..18e739f8 100644 --- a/src/components/note/atoms/user.tsx +++ b/src/components/note/atoms/user.tsx @@ -1,55 +1,66 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { DatabaseContext } from '@components/contexts/database'; +import { RelayContext } from '@components/contexts/relay'; import { ImageWithFallback } from '@components/imageWithFallback'; import { truncate } from '@utils/truncate'; import { DotsHorizontalIcon } from '@radix-ui/react-icons'; +import useLocalStorage from '@rehooks/local-storage'; import Avatar from 'boring-avatars'; -import { useNostrEvents } from 'nostr-react'; -import { memo, useEffect, useState } from 'react'; +import { memo, useCallback, useContext, useEffect, useState } from 'react'; import Moment from 'react-moment'; -import Database from 'tauri-plugin-sql-api'; - -const db = typeof window !== 'undefined' ? await Database.load('sqlite:lume.db') : null; export const User = memo(function User({ pubkey, time }: { pubkey: string; time: any }) { + const { db }: any = useContext(DatabaseContext); + const relayPool: any = useContext(RelayContext); + + const [relays] = useLocalStorage('relays'); const [profile, setProfile] = useState({ picture: null, name: null, username: null }); - const { onEvent } = useNostrEvents({ - filter: { - authors: [pubkey], - kinds: [0], - }, - }); - - onEvent(async (rawMetadata) => { - try { - const metadata: any = JSON.parse(rawMetadata.content); + relayPool.subscribe( + [ + { + authors: [pubkey], + kinds: [0], + }, + ], + relays, + (event: any) => { if (profile.picture === null || profile.name === null) { - setProfile(metadata); - await db.execute(`INSERT OR IGNORE INTO cache_profiles (id, metadata) VALUES ("${pubkey}", '${JSON.stringify(metadata)}')`); - } else { - return; + insertCacheProfile(event); } - } catch (err) { - console.error(err, rawMetadata); + }, + undefined, + (events: any, relayURL: any) => { + console.log(events, relayURL); } - }); + ); + + const insertCacheProfile = useCallback( + async (event) => { + const metadata: any = JSON.parse(event.content); + + await db.execute(`INSERT OR IGNORE INTO cache_profiles (id, metadata) VALUES ("${pubkey}", '${JSON.stringify(metadata)}')`); + setProfile(metadata); + }, + [db, pubkey] + ); + + const getCacheProfile = useCallback(async () => { + const result: any = await db.select(`SELECT metadata FROM cache_profiles WHERE id = "${pubkey}"`); + return result; + }, [db, pubkey]); useEffect(() => { - const initialProfile = async () => { - const result: any = await db.select(`SELECT metadata FROM cache_profiles WHERE id = "${pubkey}"`); - return result; - }; - - initialProfile() + getCacheProfile() .then((res) => { if (res[0] !== undefined) { setProfile(JSON.parse(res[0].metadata)); } }) .catch(console.error); - }, [pubkey]); + }, [getCacheProfile]); return (
From 862082c857fe57110f6cfb3bb9b18bbbb75f5128 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Thu, 2 Mar 2023 14:00:18 +0700 Subject: [PATCH 17/21] removed nostr-react --- package.json | 1 - pnpm-lock.yaml | 68 ------------------- src/components/navigatorBar/createPost.tsx | 14 ++-- src/components/note/atoms/reaction.tsx | 48 +++++++------ src/components/note/atoms/reply.tsx | 15 ++-- src/components/note/atoms/user.tsx | 35 +++------- src/components/note/atoms/userRepost.tsx | 29 +++----- .../note/atoms/userWithUsername.tsx | 41 ++--------- src/components/note/modal/index.tsx | 31 ++++++--- src/components/note/repost.tsx | 35 +++++++--- src/pages/profile/update.tsx | 15 ++-- 11 files changed, 123 insertions(+), 209 deletions(-) diff --git a/package.json b/package.json index b366fbeb..bc3f8403 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ "nanostores": "^0.7.4", "next": "^13.2.1", "next-remove-imports": "^1.0.10", - "nostr-react": "^0.6.4", "nostr-relaypool": "^0.5.3", "nostr-tools": "^1.7.1", "qrcode.react": "^3.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 32cc97c1..c59c06fa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,7 +32,6 @@ specifiers: nanostores: ^0.7.4 next: ^13.2.1 next-remove-imports: ^1.0.10 - nostr-react: ^0.6.4 nostr-relaypool: ^0.5.3 nostr-tools: ^1.7.1 postcss: ^8.4.21 @@ -67,7 +66,6 @@ dependencies: nanostores: 0.7.4 next: 13.2.1_biqbaboplfbrettd7655fr4n2y next-remove-imports: 1.0.10 - nostr-react: 0.6.4_react@18.2.0 nostr-relaypool: 0.5.3_ws@8.12.1 nostr-tools: 1.7.1 qrcode.react: 3.1.0_react@18.2.0 @@ -3201,49 +3199,6 @@ packages: resolution: { integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw== } dev: true - /jotai/1.13.1_react@18.2.0: - resolution: { integrity: sha512-RUmH1S4vLsG3V6fbGlKzGJnLrDcC/HNb5gH2AeA9DzuJknoVxSGvvg8OBB7lke+gDc4oXmdVsaKn/xDUhWZ0vw== } - engines: { node: '>=12.20.0' } - peerDependencies: - '@babel/core': '*' - '@babel/template': '*' - jotai-devtools: '*' - jotai-immer: '*' - jotai-optics: '*' - jotai-redux: '*' - jotai-tanstack-query: '*' - jotai-urql: '*' - jotai-valtio: '*' - jotai-xstate: '*' - jotai-zustand: '*' - react: '>=16.8' - peerDependenciesMeta: - '@babel/core': - optional: true - '@babel/template': - optional: true - jotai-devtools: - optional: true - jotai-immer: - optional: true - jotai-optics: - optional: true - jotai-redux: - optional: true - jotai-tanstack-query: - optional: true - jotai-urql: - optional: true - jotai-valtio: - optional: true - jotai-xstate: - optional: true - jotai-zustand: - optional: true - dependencies: - react: 18.2.0 - dev: false - /js-sdsl/4.3.0: resolution: { integrity: sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ== } dev: true @@ -3970,29 +3925,6 @@ packages: engines: { node: '>=0.10.0' } dev: true - /nostr-react/0.6.4_react@18.2.0: - resolution: { integrity: sha512-esRgmhTP5kPQ8ufs8cFAQxxJtMmzuba/k2QfXevG/ejHP3IMa41pb82qi8V0aPzY3KJ0Nr54x0OSa39d2InKzA== } - engines: { node: '>=12' } - peerDependencies: - react: '>=16' - dependencies: - jotai: 1.13.1_react@18.2.0 - nostr-tools: 1.7.1 - react: 18.2.0 - transitivePeerDependencies: - - '@babel/core' - - '@babel/template' - - jotai-devtools - - jotai-immer - - jotai-optics - - jotai-redux - - jotai-tanstack-query - - jotai-urql - - jotai-valtio - - jotai-xstate - - jotai-zustand - dev: false - /nostr-relaypool/0.5.3_ws@8.12.1: resolution: { integrity: sha512-1INGKleOTuUTFUs3RnnZrew4+G/idLUewh44WBtmTTJ9g+kRiQtMMaBGTVUpf9621nBNleEVOB8p3XSNcaX3FQ== } dependencies: diff --git a/src/components/navigatorBar/createPost.tsx b/src/components/navigatorBar/createPost.tsx index 957355b2..b813b287 100644 --- a/src/components/navigatorBar/createPost.tsx +++ b/src/components/navigatorBar/createPost.tsx @@ -1,18 +1,23 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { RelayContext } from '@components/contexts/relay'; + +import { dateToUnix } from '@utils/getDate'; + import * as Dialog from '@radix-ui/react-dialog'; import { useLocalStorage } from '@rehooks/local-storage'; import * as commands from '@uiw/react-md-editor/lib/commands'; import dynamic from 'next/dynamic'; -import { dateToUnix, useNostr } from 'nostr-react'; import { getEventHash, signEvent } from 'nostr-tools'; -import { useState } from 'react'; +import { useContext, useState } from 'react'; const MDEditor = dynamic(() => import('@uiw/react-md-editor').then((mod) => mod.default), { ssr: false, }); export default function CreatePost() { - const { publish } = useNostr(); + const relayPool: any = useContext(RelayContext); + const [relays]: any = useLocalStorage('relays'); + const [value, setValue] = useState(''); const [currentUser]: any = useLocalStorage('current-user'); @@ -40,11 +45,10 @@ export default function CreatePost() { pubkey: pubkey, tags: [], }; - event.id = getEventHash(event); event.sig = signEvent(event, privkey); - publish(event); + relayPool.publish(event, relays); setValue(''); } }, diff --git a/src/components/note/atoms/reaction.tsx b/src/components/note/atoms/reaction.tsx index 7c2a36cd..b2b6a619 100644 --- a/src/components/note/atoms/reaction.tsx +++ b/src/components/note/atoms/reaction.tsx @@ -1,12 +1,17 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { RelayContext } from '@components/contexts/relay'; + +import { dateToUnix } from '@utils/getDate'; + import { HeartFilledIcon, HeartIcon } from '@radix-ui/react-icons'; import { useLocalStorage } from '@rehooks/local-storage'; -import { dateToUnix, useNostr, useNostrEvents } from 'nostr-react'; import { getEventHash, signEvent } from 'nostr-tools'; -import { useState } from 'react'; +import { useContext, useState } from 'react'; export default function Reaction({ eventID, eventPubkey }: { eventID: string; eventPubkey: string }) { - const { publish } = useNostr(); + const relayPool: any = useContext(RelayContext); + const [relays]: any = useLocalStorage('relays'); + const [reaction, setReaction] = useState(0); const [isReact, setIsReact] = useState(false); @@ -14,25 +19,26 @@ export default function Reaction({ eventID, eventPubkey }: { eventID: string; ev const pubkey = currentUser.pubkey; const privkey = currentUser.privkey; - const { onEvent } = useNostrEvents({ - filter: { - '#e': [eventID], - since: 0, - kinds: [7], - limit: 20, - }, - }); - - onEvent((rawMetadata) => { - try { - const content = rawMetadata.content; - if (content === '🤙' || content === '+') { - setReaction(reaction + 1); + relayPool.subscribe( + [ + { + '#e': [eventID], + since: 0, + kinds: [7], + limit: 10, + }, + ], + relays, + (event: any) => { + if (event.content === '🤙' || event.content === '+') { + //setReaction(reaction + 1); } - } catch (err) { - console.error(err, rawMetadata); + }, + undefined, + (events: any, relayURL: any) => { + console.log(events, relayURL); } - }); + ); const handleReaction = (e: any) => { e.stopPropagation(); @@ -50,7 +56,7 @@ export default function Reaction({ eventID, eventPubkey }: { eventID: string; ev event.id = getEventHash(event); event.sig = signEvent(event, privkey); - publish(event); + relayPool.publish(event, relays); setIsReact(true); setReaction(reaction + 1); diff --git a/src/components/note/atoms/reply.tsx b/src/components/note/atoms/reply.tsx index 67a3a5d9..88d97844 100644 --- a/src/components/note/atoms/reply.tsx +++ b/src/components/note/atoms/reply.tsx @@ -1,22 +1,17 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { ChatBubbleIcon } from '@radix-ui/react-icons'; -import { useNostrEvents } from 'nostr-react'; +import { useState } from 'react'; export default function Reply({ eventID }: { eventID: string }) { - const { events } = useNostrEvents({ - filter: { - '#e': [eventID], - since: 0, - kinds: [1], - limit: 10, - }, - }); + console.log(eventID); + const [count] = useState(0); return ( ); } diff --git a/src/components/note/atoms/user.tsx b/src/components/note/atoms/user.tsx index 18e739f8..20e73bf0 100644 --- a/src/components/note/atoms/user.tsx +++ b/src/components/note/atoms/user.tsx @@ -1,42 +1,18 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { DatabaseContext } from '@components/contexts/database'; -import { RelayContext } from '@components/contexts/relay'; import { ImageWithFallback } from '@components/imageWithFallback'; import { truncate } from '@utils/truncate'; import { DotsHorizontalIcon } from '@radix-ui/react-icons'; -import useLocalStorage from '@rehooks/local-storage'; import Avatar from 'boring-avatars'; import { memo, useCallback, useContext, useEffect, useState } from 'react'; import Moment from 'react-moment'; export const User = memo(function User({ pubkey, time }: { pubkey: string; time: any }) { const { db }: any = useContext(DatabaseContext); - const relayPool: any = useContext(RelayContext); - - const [relays] = useLocalStorage('relays'); const [profile, setProfile] = useState({ picture: null, name: null, username: null }); - relayPool.subscribe( - [ - { - authors: [pubkey], - kinds: [0], - }, - ], - relays, - (event: any) => { - if (profile.picture === null || profile.name === null) { - insertCacheProfile(event); - } - }, - undefined, - (events: any, relayURL: any) => { - console.log(events, relayURL); - } - ); - const insertCacheProfile = useCallback( async (event) => { const metadata: any = JSON.parse(event.content); @@ -57,10 +33,19 @@ export const User = memo(function User({ pubkey, time }: { pubkey: string; time: .then((res) => { if (res[0] !== undefined) { setProfile(JSON.parse(res[0].metadata)); + } else { + fetch(`https://rbr.bio/${pubkey}/metadata.json`).then((res) => + res.json().then((res) => { + // update state + setProfile(JSON.parse(res.content)); + // save profile to database + insertCacheProfile(res); + }) + ); } }) .catch(console.error); - }, [getCacheProfile]); + }, [getCacheProfile, insertCacheProfile, pubkey]); return (
diff --git a/src/components/note/atoms/userRepost.tsx b/src/components/note/atoms/userRepost.tsx index 1e49009d..702e6f57 100644 --- a/src/components/note/atoms/userRepost.tsx +++ b/src/components/note/atoms/userRepost.tsx @@ -1,30 +1,19 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { truncate } from '@utils/truncate'; -import { useNostrEvents } from 'nostr-react'; -import { memo, useState } from 'react'; +import { memo, useEffect, useState } from 'react'; export const UserRepost = memo(function UserRepost({ pubkey }: { pubkey: string }) { const [profile, setProfile] = useState({ picture: null, name: null }); - const { onEvent } = useNostrEvents({ - filter: { - authors: [pubkey], - kinds: [0], - }, - }); - - // #TODO: save response to DB - onEvent((rawMetadata) => { - try { - const metadata: any = JSON.parse(rawMetadata.content); - if (metadata) { - setProfile(metadata); - } - } catch (err) { - console.error(err, rawMetadata); - } - }); + useEffect(() => { + fetch(`https://rbr.bio/${pubkey}/metadata.json`).then((res) => + res.json().then((res) => { + // update state + setProfile(JSON.parse(res.content)); + }) + ); + }, [pubkey]); return (
diff --git a/src/components/note/atoms/userWithUsername.tsx b/src/components/note/atoms/userWithUsername.tsx index a581599c..1dd2fd96 100644 --- a/src/components/note/atoms/userWithUsername.tsx +++ b/src/components/note/atoms/userWithUsername.tsx @@ -5,49 +5,18 @@ import { truncate } from '@utils/truncate'; import { DotsHorizontalIcon } from '@radix-ui/react-icons'; import Avatar from 'boring-avatars'; -import { useNostrEvents } from 'nostr-react'; import { memo, useEffect, useState } from 'react'; -import Database from 'tauri-plugin-sql-api'; - -const db = typeof window !== 'undefined' ? await Database.load('sqlite:lume.db') : null; export const UserWithUsername = memo(function UserWithUsername({ pubkey }: { pubkey: string }) { const [profile, setProfile] = useState({ picture: null, name: null, username: null }); - const { onEvent } = useNostrEvents({ - filter: { - authors: [pubkey], - kinds: [0], - }, - }); - - onEvent(async (rawMetadata) => { - try { - const metadata: any = JSON.parse(rawMetadata.content); - if (profile.picture === null || profile.name === null) { - setProfile(metadata); - await db.execute(`INSERT OR IGNORE INTO cache_profiles (pubkey, metadata) VALUES ("${pubkey}", '${JSON.stringify(metadata)}')`); - } else { - return; - } - } catch (err) { - console.error(err, rawMetadata); - } - }); - useEffect(() => { - const initialProfile = async () => { - const result: any = await db.select(`SELECT metadata FROM cache_profiles WHERE pubkey = "${pubkey}"`); - return result; - }; - - initialProfile() - .then((res) => { - if (res[0] !== undefined) { - setProfile(JSON.parse(res[0].metadata)); - } + fetch(`https://rbr.bio/${pubkey}/metadata.json`).then((res) => + res.json().then((res) => { + // update state + setProfile(JSON.parse(res.content)); }) - .catch(console.error); + ); }, [pubkey]); return ( diff --git a/src/components/note/modal/index.tsx b/src/components/note/modal/index.tsx index 5665c7cb..91824bd0 100644 --- a/src/components/note/modal/index.tsx +++ b/src/components/note/modal/index.tsx @@ -1,18 +1,33 @@ +import { RelayContext } from '@components/contexts/relay'; import { Content } from '@components/note/content'; import NoteReply from '@components/note/modal/noteReply'; -import { useNostrEvents } from 'nostr-react'; -import { memo } from 'react'; +import useLocalStorage from '@rehooks/local-storage'; +import { memo, useContext, useState } from 'react'; /* eslint-disable @typescript-eslint/no-explicit-any */ const Modal = ({ event }: { event: any }) => { - const { events } = useNostrEvents({ - filter: { - '#e': [event.id], - since: event.created_at, - kinds: [1], + const relayPool: any = useContext(RelayContext); + const [relays]: any = useLocalStorage('relays'); + const [events, setEvents] = useState([]); + + relayPool.subscribe( + [ + { + '#e': [event.id], + since: event.created_at, + kinds: [1], + }, + ], + relays, + (event: any) => { + setEvents((events) => [event, ...events]); }, - }); + undefined, + (events: any, relayURL: any) => { + console.log(events, relayURL); + } + ); return (
diff --git a/src/components/note/repost.tsx b/src/components/note/repost.tsx index 7d6c257b..8dbb4aec 100644 --- a/src/components/note/repost.tsx +++ b/src/components/note/repost.tsx @@ -1,13 +1,14 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { RelayContext } from '@components/contexts/relay'; import { UserRepost } from '@components/note/atoms/userRepost'; import { Content } from '@components/note/content'; import { Placeholder } from '@components/note/placeholder'; import * as Dialog from '@radix-ui/react-dialog'; import { LoopIcon } from '@radix-ui/react-icons'; +import useLocalStorage from '@rehooks/local-storage'; import dynamic from 'next/dynamic'; -import { useNostrEvents } from 'nostr-react'; -import { memo } from 'react'; +import { memo, useContext, useState } from 'react'; const Modal = dynamic(() => import('@components/note/modal'), { ssr: false, @@ -15,13 +16,27 @@ const Modal = dynamic(() => import('@components/note/modal'), { }); export const Repost = memo(function Repost({ root, user }: { root: any; user: string }) { - const { events } = useNostrEvents({ - filter: { - ids: [root[0][1]], - since: 0, - kinds: [1], + const relayPool: any = useContext(RelayContext); + const [relays]: any = useLocalStorage('relays'); + const [events, setEvents] = useState([]); + + relayPool.subscribe( + [ + { + ids: [root[0][1]], + since: 0, + kinds: [1], + }, + ], + relays, + (event: any) => { + setEvents((events) => [event, ...events]); }, - }); + undefined, + (events: any, relayURL: any) => { + console.log(events, relayURL); + } + ); if (events !== null && Object.keys(events).length > 0) { return ( @@ -38,9 +53,7 @@ export const Repost = memo(function Repost({ root, user }: { root: any; user: st
- - {events[0].content && } - + {events[0].content && } diff --git a/src/pages/profile/update.tsx b/src/pages/profile/update.tsx index 37a93b57..dc7e6bda 100644 --- a/src/pages/profile/update.tsx +++ b/src/pages/profile/update.tsx @@ -2,11 +2,14 @@ import BaseLayout from '@layouts/baseLayout'; import UserLayout from '@layouts/userLayout'; +import { RelayContext } from '@components/contexts/relay'; + +import { dateToUnix } from '@utils/getDate'; + import { useLocalStorage } from '@rehooks/local-storage'; import { useRouter } from 'next/router'; -import { dateToUnix, useNostr } from 'nostr-react'; import { getEventHash, signEvent } from 'nostr-tools'; -import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useState } from 'react'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useState } from 'react'; import { useForm } from 'react-hook-form'; import Database from 'tauri-plugin-sql-api'; @@ -22,8 +25,10 @@ type FormValues = { // TODO: update the design export default function Page() { + const relayPool: any = useContext(RelayContext); + const [relays]: any = useLocalStorage('relays'); + const router = useRouter(); - const { publish } = useNostr(); const [loading, setLoading] = useState(false); const [currentUser]: any = useLocalStorage('current-user'); @@ -46,9 +51,11 @@ export default function Page() { pubkey: currentUser.pubkey, tags: [], }; + event.id = getEventHash(event); event.sig = signEvent(event, currentUser.privkey); - publish(event); + + relayPool.publish(event, relays); // save account to database const db = await Database.load('sqlite:lume.db'); From 09c7ccc02348d53819fcd4f23b7361f9be5b326e Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Thu, 2 Mar 2023 15:16:23 +0700 Subject: [PATCH 18/21] added reload button for newsfeed --- src/components/note/connector.tsx | 16 ++++++++++------ src/components/note/repost.tsx | 31 ++++++++----------------------- src/components/note/single.tsx | 24 +++--------------------- src/pages/feed/following.tsx | 21 +++++++++++---------- 4 files changed, 32 insertions(+), 60 deletions(-) diff --git a/src/components/note/connector.tsx b/src/components/note/connector.tsx index df09466f..23a37e30 100644 --- a/src/components/note/connector.tsx +++ b/src/components/note/connector.tsx @@ -4,10 +4,11 @@ import { RelayContext } from '@components/contexts/relay'; import { dateToUnix, hoursAgo } from '@utils/getDate'; +import { ReloadIcon } from '@radix-ui/react-icons'; import { useLocalStorage } from '@rehooks/local-storage'; import { memo, useCallback, useContext, useRef } from 'react'; -export const NoteConnector = memo(function NoteConnector() { +export const NoteConnector = memo(function NoteConnector({ setReload }: { setReload: any }) { const { db }: any = useContext(DatabaseContext); const relayPool: any = useContext(RelayContext); @@ -51,13 +52,16 @@ export const NoteConnector = memo(function NoteConnector() {

# following

-
-
- +
+ +
+ - + -

Online

+

Online

diff --git a/src/components/note/repost.tsx b/src/components/note/repost.tsx index 8dbb4aec..4bc3dcea 100644 --- a/src/components/note/repost.tsx +++ b/src/components/note/repost.tsx @@ -4,17 +4,10 @@ import { UserRepost } from '@components/note/atoms/userRepost'; import { Content } from '@components/note/content'; import { Placeholder } from '@components/note/placeholder'; -import * as Dialog from '@radix-ui/react-dialog'; import { LoopIcon } from '@radix-ui/react-icons'; import useLocalStorage from '@rehooks/local-storage'; -import dynamic from 'next/dynamic'; import { memo, useContext, useState } from 'react'; -const Modal = dynamic(() => import('@components/note/modal'), { - ssr: false, - loading: () => <>, -}); - export const Repost = memo(function Repost({ root, user }: { root: any; user: string }) { const relayPool: any = useContext(RelayContext); const [relays]: any = useLocalStorage('relays'); @@ -40,23 +33,15 @@ export const Repost = memo(function Repost({ root, user }: { root: any; user: st if (events !== null && Object.keys(events).length > 0) { return ( - - -
-
- -
- -
-
- {events[0].content && } +
+
+ +
+
- - - {events[0].content && } - - - +
+ {events[0].content && } +
); } else { return ( diff --git a/src/components/note/single.tsx b/src/components/note/single.tsx index e6d56b59..926bf63b 100644 --- a/src/components/note/single.tsx +++ b/src/components/note/single.tsx @@ -1,30 +1,12 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Content } from '@components/note/content'; -import * as Dialog from '@radix-ui/react-dialog'; -import dynamic from 'next/dynamic'; import { memo } from 'react'; -const Modal = dynamic(() => import('@components/note/modal'), { - ssr: false, - loading: () => <>, -}); - -// eslint-disable-next-line @typescript-eslint/no-explicit-any export const Single = memo(function Single({ event }: { event: any }) { return ( - - -
- -
-
- - - - - - -
+
+ +
); }); diff --git a/src/pages/feed/following.tsx b/src/pages/feed/following.tsx index 177b4a4e..790ecdf3 100644 --- a/src/pages/feed/following.tsx +++ b/src/pages/feed/following.tsx @@ -15,19 +15,11 @@ import { Virtuoso } from 'react-virtuoso'; export default function Page() { const { db }: any = useContext(DatabaseContext); const [data, setData] = useState([]); + const [reload, setReload] = useState(false); const limit = useRef(30); const offset = useRef(0); - useEffect(() => { - const getData = async () => { - const result = await db.select(`SELECT * FROM cache_notes ORDER BY created_at DESC LIMIT ${limit.current}`); - setData(result); - }; - - getData().catch(console.error); - }, [db]); - const loadMore = useCallback(async () => { offset.current += limit.current; // next query @@ -49,6 +41,15 @@ export default function Page() { [data] ); + useEffect(() => { + const getData = async () => { + const result = await db.select(`SELECT * FROM cache_notes ORDER BY created_at DESC LIMIT ${limit.current}`); + setData(result); + }; + + getData().catch(console.error); + }, [db, reload]); + const computeItemKey = useCallback( (index: string | number) => { return data[index].id; @@ -58,7 +59,7 @@ export default function Page() { return (
- + Date: Thu, 2 Mar 2023 16:10:59 +0700 Subject: [PATCH 19/21] disabled global newsfeed and reply, reaction count --- src/components/note/atoms/reaction.tsx | 4 ++- src/components/note/atoms/reply.tsx | 3 +- src/pages/feed/global.tsx | 38 ++------------------------ 3 files changed, 7 insertions(+), 38 deletions(-) diff --git a/src/components/note/atoms/reaction.tsx b/src/components/note/atoms/reaction.tsx index b2b6a619..ac6e49f3 100644 --- a/src/components/note/atoms/reaction.tsx +++ b/src/components/note/atoms/reaction.tsx @@ -19,6 +19,7 @@ export default function Reaction({ eventID, eventPubkey }: { eventID: string; ev const pubkey = currentUser.pubkey; const privkey = currentUser.privkey; + /* relayPool.subscribe( [ { @@ -31,7 +32,7 @@ export default function Reaction({ eventID, eventPubkey }: { eventID: string; ev relays, (event: any) => { if (event.content === '🤙' || event.content === '+') { - //setReaction(reaction + 1); + setReaction(reaction + 1); } }, undefined, @@ -39,6 +40,7 @@ export default function Reaction({ eventID, eventPubkey }: { eventID: string; ev console.log(events, relayURL); } ); + */ const handleReaction = (e: any) => { e.stopPropagation(); diff --git a/src/components/note/atoms/reply.tsx b/src/components/note/atoms/reply.tsx index 88d97844..cde060c0 100644 --- a/src/components/note/atoms/reply.tsx +++ b/src/components/note/atoms/reply.tsx @@ -2,8 +2,7 @@ import { ChatBubbleIcon } from '@radix-ui/react-icons'; import { useState } from 'react'; -export default function Reply({ eventID }: { eventID: string }) { - console.log(eventID); +export default function Reply() { const [count] = useState(0); return ( diff --git a/src/pages/feed/global.tsx b/src/pages/feed/global.tsx index c8ce0a63..204bd2fc 100644 --- a/src/pages/feed/global.tsx +++ b/src/pages/feed/global.tsx @@ -1,50 +1,18 @@ import BaseLayout from '@layouts/baseLayout'; import NewsFeedLayout from '@layouts/newsfeedLayout'; -import { Placeholder } from '@components/note/placeholder'; -import { Thread } from '@components/thread'; - -import { hoursAgo } from '@utils/getDate'; - -import { dateToUnix, useNostrEvents } from 'nostr-react'; -import { - JSXElementConstructor, - ReactElement, - ReactFragment, - ReactPortal, - Suspense, - useRef, -} from 'react'; +import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal } from 'react'; export default function Page() { - const now = useRef(new Date()); - - const { events } = useNostrEvents({ - filter: { - until: dateToUnix(now.current), - since: dateToUnix(hoursAgo(1, now.current)), - kinds: [1], - limit: 10, - }, - }); - return (
- }> - - +

Global

); } Page.getLayout = function getLayout( - page: - | string - | number - | boolean - | ReactElement> - | ReactFragment - | ReactPortal + page: string | number | boolean | ReactElement> | ReactFragment | ReactPortal ) { return ( From 5d3c1aec2e1ecb46cf1a60a0e563ce4e03f91206 Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Thu, 2 Mar 2023 20:49:37 +0700 Subject: [PATCH 20/21] optimized note connector --- src/components/note/connector.tsx | 62 ++++++++++++++++++++----------- src/pages/feed/following.tsx | 38 +++++++++++++++---- 2 files changed, 70 insertions(+), 30 deletions(-) diff --git a/src/components/note/connector.tsx b/src/components/note/connector.tsx index 23a37e30..dcea4506 100644 --- a/src/components/note/connector.tsx +++ b/src/components/note/connector.tsx @@ -6,14 +6,20 @@ import { dateToUnix, hoursAgo } from '@utils/getDate'; import { ReloadIcon } from '@radix-ui/react-icons'; import { useLocalStorage } from '@rehooks/local-storage'; -import { memo, useCallback, useContext, useRef } from 'react'; +import { memo, useCallback, useContext, useEffect } from 'react'; -export const NoteConnector = memo(function NoteConnector({ setReload }: { setReload: any }) { +export const NoteConnector = memo(function NoteConnector({ + setParentReload, + setHasNewNote, + currentDate, +}: { + setParentReload: any; + setHasNewNote: any; + currentDate: any; +}) { const { db }: any = useContext(DatabaseContext); const relayPool: any = useContext(RelayContext); - const now = useRef(new Date()); - const [follows]: any = useLocalStorage('follows'); const [relays]: any = useLocalStorage('relays'); @@ -29,34 +35,46 @@ export const NoteConnector = memo(function NoteConnector({ setReload }: { setRel [db] ); - relayPool.subscribe( - [ - { - kinds: [1], - authors: follows, - since: dateToUnix(hoursAgo(12, now.current)), + const fetchEvent = useCallback(() => { + relayPool.subscribe( + [ + { + kinds: [1], + authors: follows, + since: dateToUnix(hoursAgo(12, currentDate)), + }, + ], + relays, + (event: any) => { + // insert event to local database + insertDB(event).catch(console.error); + // show trigger update newer event + if (event.created_at > dateToUnix(currentDate)) { + setHasNewNote(true); + } }, - ], - relays, - (event: any) => { - insertDB(event).catch(console.error); - }, - undefined, - (events: any, relayURL: any) => { - console.log(events, relayURL); - } - ); + undefined, + (events: any, relayURL: any) => { + console.log(events, relayURL); + } + ); + }, [relayPool, follows, currentDate, relays, insertDB, setHasNewNote]); + + useEffect(() => { + fetchEvent(); + }, [fetchEvent]); return ( -
+

# following

-
+ {/* #TODO: get user network status */} diff --git a/src/pages/feed/following.tsx b/src/pages/feed/following.tsx index 790ecdf3..388e9d91 100644 --- a/src/pages/feed/following.tsx +++ b/src/pages/feed/following.tsx @@ -8,22 +8,34 @@ import { Placeholder } from '@components/note/placeholder'; import { Repost } from '@components/note/repost'; import { Single } from '@components/note/single'; +import { dateToUnix } from '@utils/getDate'; + +import { writeStorage } from '@rehooks/local-storage'; import { useCallback, useState } from 'react'; import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useEffect, useRef } from 'react'; import { Virtuoso } from 'react-virtuoso'; export default function Page() { const { db }: any = useContext(DatabaseContext); - const [data, setData] = useState([]); - const [reload, setReload] = useState(false); + const [data, setData] = useState([]); + const [parentReload, setParentReload] = useState(false); + const [hasNewNote, setHasNewNote] = useState(false); + + const now = useRef(new Date()); const limit = useRef(30); const offset = useRef(0); const loadMore = useCallback(async () => { offset.current += limit.current; // next query - const result = await db.select(`SELECT * FROM cache_notes ORDER BY created_at DESC LIMIT ${limit.current} OFFSET ${offset.current}`); + const result = await db.select( + `SELECT * FROM + cache_notes + WHERE created_at <= ${dateToUnix(now.current)} + ORDER BY created_at DESC + LIMIT ${limit.current} OFFSET ${offset.current}` + ); setData((data) => [...data, ...result]); }, [db]); @@ -43,12 +55,17 @@ export default function Page() { useEffect(() => { const getData = async () => { - const result = await db.select(`SELECT * FROM cache_notes ORDER BY created_at DESC LIMIT ${limit.current}`); - setData(result); + const result = await db.select( + `SELECT * FROM cache_notes WHERE created_at <= ${dateToUnix(now.current)} ORDER BY created_at DESC LIMIT ${limit.current}` + ); + if (result) { + setData(result); + writeStorage('settings', new Date()); + } }; getData().catch(console.error); - }, [db, reload]); + }, [db, parentReload]); const computeItemKey = useCallback( (index: string | number) => { @@ -58,8 +75,13 @@ export default function Page() { ); return ( -
- +
+ + {hasNewNote && ( +
+ +
+ )} Date: Fri, 3 Mar 2023 13:29:51 +0700 Subject: [PATCH 21/21] minor updates --- next.config.js | 3 +++ src/components/navigatorBar/index.tsx | 15 --------------- src/components/note/connector.tsx | 23 +++++++++++++++++++---- src/pages/feed/following.tsx | 2 +- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/next.config.js b/next.config.js index 07e914ab..3bd71dbc 100644 --- a/next.config.js +++ b/next.config.js @@ -9,6 +9,9 @@ module.exports = removeImports({ typescript: { ignoreBuildErrors: true, }, + experimental: { + scrollRestoration: true, + }, webpack: (config) => { config.experiments = { ...config.experiments, topLevelAwait: true }; return config; diff --git a/src/components/navigatorBar/index.tsx b/src/components/navigatorBar/index.tsx index 8cd04bf7..83bbe7b7 100644 --- a/src/components/navigatorBar/index.tsx +++ b/src/components/navigatorBar/index.tsx @@ -12,7 +12,6 @@ export default function NavigatorBar() { return (
- {/* main */}
{/* Create post */}
@@ -66,17 +65,3 @@ export default function NavigatorBar() {
); } - -/* Channels -
-
-

Channels

- -
-
-
-*/ diff --git a/src/components/note/connector.tsx b/src/components/note/connector.tsx index dcea4506..f27da0d4 100644 --- a/src/components/note/connector.tsx +++ b/src/components/note/connector.tsx @@ -6,7 +6,7 @@ import { dateToUnix, hoursAgo } from '@utils/getDate'; import { ReloadIcon } from '@radix-ui/react-icons'; import { useLocalStorage } from '@rehooks/local-storage'; -import { memo, useCallback, useContext, useEffect } from 'react'; +import { memo, useCallback, useContext, useEffect, useRef, useState } from 'react'; export const NoteConnector = memo(function NoteConnector({ setParentReload, @@ -23,6 +23,17 @@ export const NoteConnector = memo(function NoteConnector({ const [follows]: any = useLocalStorage('follows'); const [relays]: any = useLocalStorage('relays'); + const [reload, setReload] = useState(false); + const timeout = useRef(null); + + const reloadNewsfeed = () => { + setParentReload(true); + setReload(true); + timeout.current = setTimeout(() => { + setReload(false); + }, 2000); + }; + const insertDB = useCallback( async (event: any) => { await db.execute( @@ -46,12 +57,12 @@ export const NoteConnector = memo(function NoteConnector({ ], relays, (event: any) => { - // insert event to local database - insertDB(event).catch(console.error); // show trigger update newer event if (event.created_at > dateToUnix(currentDate)) { setHasNewNote(true); } + // insert event to local database + insertDB(event).catch(console.error); }, undefined, (events: any, relayURL: any) => { @@ -62,6 +73,10 @@ export const NoteConnector = memo(function NoteConnector({ useEffect(() => { fetchEvent(); + + return () => { + clearTimeout(timeout.current); + }; }, [fetchEvent]); return ( @@ -70,7 +85,7 @@ export const NoteConnector = memo(function NoteConnector({

# following

-
diff --git a/src/pages/feed/following.tsx b/src/pages/feed/following.tsx index 388e9d91..a47e7518 100644 --- a/src/pages/feed/following.tsx +++ b/src/pages/feed/following.tsx @@ -97,7 +97,7 @@ export default function Page() { endReached={loadMore} overscan={800} increaseViewportBy={1000} - className="scrollbar-hide relative h-full w-full" + className="relative h-full w-full" style={{ contain: 'strict', }}