diff --git a/package.json b/package.json
index 49bb721b..3ac57ebd 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,8 @@
"@radix-ui/react-tabs": "^1.0.3",
"@rehooks/local-storage": "^2.4.4",
"@supabase/supabase-js": "^2.12.0",
+ "@tanstack/query-core": "^4.27.0",
+ "@tanstack/react-virtual": "3.0.0-beta.54",
"@tauri-apps/api": "^1.2.0",
"@uiw/react-markdown-preview": "^4.1.10",
"@uiw/react-md-editor": "^3.20.5",
@@ -28,6 +30,7 @@
"dayjs": "^1.11.7",
"framer-motion": "^9.1.7",
"jotai": "^2.0.3",
+ "jotai-tanstack-query": "^0.6.0",
"moment": "^2.29.4",
"next": "^13.2.4",
"next-remove-imports": "^1.0.10",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index dbcecb85..79d385a1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -10,6 +10,8 @@ specifiers:
'@rehooks/local-storage': ^2.4.4
'@supabase/supabase-js': ^2.12.0
'@tailwindcss/typography': ^0.5.9
+ '@tanstack/query-core': ^4.27.0
+ '@tanstack/react-virtual': 3.0.0-beta.54
'@tauri-apps/api': ^1.2.0
'@tauri-apps/cli': ^1.2.3
'@trivago/prettier-plugin-sort-imports': ^4.1.1
@@ -33,6 +35,7 @@ specifiers:
framer-motion: ^9.1.7
husky: ^8.0.3
jotai: ^2.0.3
+ jotai-tanstack-query: ^0.6.0
lint-staged: ^13.2.0
moment: ^2.29.4
next: ^13.2.4
@@ -65,6 +68,8 @@ dependencies:
'@radix-ui/react-tabs': 1.0.3_biqbaboplfbrettd7655fr4n2y
'@rehooks/local-storage': 2.4.4_react@18.2.0
'@supabase/supabase-js': 2.12.0
+ '@tanstack/query-core': 4.27.0
+ '@tanstack/react-virtual': 3.0.0-beta.54_react@18.2.0
'@tauri-apps/api': 1.2.0
'@uiw/react-markdown-preview': 4.1.10_zula6vjvt3wdocc4mwcxqa6nzi
'@uiw/react-md-editor': 3.20.5_zula6vjvt3wdocc4mwcxqa6nzi
@@ -73,6 +78,7 @@ dependencies:
dayjs: 1.11.7
framer-motion: 9.1.7_biqbaboplfbrettd7655fr4n2y
jotai: 2.0.3_react@18.2.0
+ jotai-tanstack-query: 0.6.0_jqgumvl52k2nlr5n23qdneaa6y
moment: 2.29.4
next: 13.2.4_biqbaboplfbrettd7655fr4n2y
next-remove-imports: 1.0.10
@@ -1302,6 +1308,26 @@ packages:
tailwindcss: 3.2.7_postcss@8.4.21
dev: true
+ /@tanstack/query-core/4.27.0:
+ resolution:
+ { integrity: sha512-sm+QncWaPmM73IPwFlmWSKPqjdTXZeFf/7aEmWh00z7yl2FjqophPt0dE1EHW9P1giMC5rMviv7OUbSDmWzXXA== }
+ dev: false
+
+ /@tanstack/react-virtual/3.0.0-beta.54_react@18.2.0:
+ resolution:
+ { integrity: sha512-D1mDMf4UPbrtHRZZriCly5bXTBMhylslm4dhcHqTtDJ6brQcgGmk8YD9JdWBGWfGSWPKoh2x1H3e7eh+hgPXtQ== }
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ dependencies:
+ '@tanstack/virtual-core': 3.0.0-beta.54
+ react: 18.2.0
+ dev: false
+
+ /@tanstack/virtual-core/3.0.0-beta.54:
+ resolution:
+ { integrity: sha512-jtkwqdP2rY2iCCDVAFuaNBH3fiEi29aTn2RhtIoky8DTTiCdc48plpHHreLwmv1PICJ4AJUUESaq3xa8fZH8+g== }
+ dev: false
+
/@tauri-apps/api/1.2.0:
resolution:
{ integrity: sha512-lsI54KI6HGf7VImuf/T9pnoejfgkNoXveP14pVV7XarrQ46rOejIVJLFqHI9sRReJMGdh2YuCoI3cc/yCWCsrw== }
@@ -3836,6 +3862,17 @@ packages:
{ integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw== }
dev: true
+ /jotai-tanstack-query/0.6.0_jqgumvl52k2nlr5n23qdneaa6y:
+ resolution:
+ { integrity: sha512-87oD6MnjrgfLWeCJXB/dQt4xyCmyFYZeG9jw4Y2lIprtwLKS5s/vCEjNP5fnYG2nuPBkopiRECTEqtIysvHSxg== }
+ peerDependencies:
+ '@tanstack/query-core': '*'
+ jotai: '>=1.11.0'
+ dependencies:
+ '@tanstack/query-core': 4.27.0
+ jotai: 2.0.3_react@18.2.0
+ dev: false
+
/jotai/2.0.3_react@18.2.0:
resolution:
{ integrity: sha512-MMjhSPAL3RoeZD9WbObufRT2quThEAEknHHridf2ma8Ml7ZVQmUiHk0ssdbR3F0h3kcwhYqSGJ59OjhPge7RRg== }
diff --git a/src-tauri/migrations/20230226004139_create_tables.sql b/src-tauri/migrations/20230226004139_create_tables.sql
index 3ae80b73..c040da30 100644
--- a/src-tauri/migrations/20230226004139_create_tables.sql
+++ b/src-tauri/migrations/20230226004139_create_tables.sql
@@ -48,7 +48,7 @@ CREATE TABLE
npub TEXT NOT NULL,
nsec TEXT NOT NULL,
is_active INTEGER NOT NULL DEFAULT 0,
- metadata JSON
+ metadata TEXT
);
-- create follows
@@ -61,7 +61,7 @@ CREATE TABLE
pubkey TEXT NOT NULL,
account TEXT NOT NULL,
kind INTEGER NOT NULL DEFAULT 0,
- metadata JSON
+ metadata TEXT
);
-- create index for pubkey in follows
@@ -71,7 +71,7 @@ CREATE UNIQUE INDEX index_pubkey_on_follows ON follows (pubkey);
CREATE TABLE
cache_profiles (
id TEXT PRIMARY KEY,
- metadata JSON,
+ metadata TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
@@ -84,5 +84,8 @@ CREATE TABLE
created_at TEXT,
kind INTEGER NOT NULL DEFAULT 1,
tags TEXT NOT NULL,
- content TEXT NOT NULL
+ content TEXT NOT NULL,
+ is_circle INTEGER NOT NULL DEFAULT 0,
+ is_root INTEGER NOT NULL DEFAULT 0,
+ is_reply INTEGER NOT NULL DEFAULT 0
);
\ No newline at end of file
diff --git a/src/components/contexts/database.tsx b/src/components/contexts/database.tsx
index 31b7aaee..83e55d87 100644
--- a/src/components/contexts/database.tsx
+++ b/src/components/contexts/database.tsx
@@ -48,17 +48,25 @@ export default function DatabaseProvider({ children }: { children: React.ReactNo
return;
}, []);
+ const clearCacheNote = useCallback(async () => {
+ const result: any = await db.select('SELECT COUNT(*) AS "total" FROM cache_notes');
+ if (result[0].total >= 1000) {
+ await db.execute('DELETE FROM cache_notes');
+ }
+ }, []);
+
useEffect(() => {
getRelays().catch(console.error);
getAccount()
.then((res) => {
if (res) {
getFollows(res.id).catch(console.error);
+ clearCacheNote().catch(console.error);
}
setDone(true);
})
.catch(console.error);
- }, [getAccount, getFollows, getRelays]);
+ }, [getAccount, getFollows, clearCacheNote, getRelays]);
if (!done) {
return <>>;
diff --git a/src/components/note/connector.tsx b/src/components/note/connector.tsx
index 618bb9f6..16735a17 100644
--- a/src/components/note/connector.tsx
+++ b/src/components/note/connector.tsx
@@ -1,7 +1,7 @@
import { DatabaseContext } from '@components/contexts/database';
import { RelayContext } from '@components/contexts/relay';
-import { atomHasNewerNote } from '@stores/note';
+import { hasNewerNoteAtom } from '@stores/note';
import { dateToUnix, hoursAgo } from '@utils/getDate';
@@ -16,7 +16,7 @@ export const NoteConnector = memo(function NoteConnector() {
const [follows]: any = useLocalStorage('follows');
const [relays]: any = useLocalStorage('relays');
- const setHasNewerNote = useSetAtom(atomHasNewerNote);
+ const setHasNewerNote = useSetAtom(hasNewerNoteAtom);
const [isOnline, setIsOnline] = useState(navigator.onLine);
const now = useRef(new Date());
@@ -25,7 +25,7 @@ export const NoteConnector = memo(function NoteConnector() {
// insert to local database
await db.execute(
'INSERT OR IGNORE INTO cache_notes (id, pubkey, created_at, kind, content, tags) VALUES (?, ?, ?, ?, ?, ?);',
- [event.id, event.pubkey, event.created_at, event.kind, event.content, JSON.stringify(event.tags)]
+ [event.id, event.pubkey, event.created_at, event.kind, event.content, String(event.tags)]
);
},
[db]
diff --git a/src/components/note/content/index.tsx b/src/components/note/content/index.tsx
index 8742ffd9..2dec501c 100644
--- a/src/components/note/content/index.tsx
+++ b/src/components/note/content/index.tsx
@@ -9,11 +9,9 @@ import reactStringReplace from 'react-string-replace';
export const Content = memo(function Content({ data }: { data: any }) {
const content = useMemo(() => {
let parsedContent;
- let tags;
// get data tags
- if (data.tags.length > 1) {
- tags = JSON.parse(data.tags);
- }
+ const tags = String(data.tags).replaceAll("'", '"');
+ const parseTags = JSON.parse(tags);
// remove all image urls
parsedContent = data.content.replace(/(https?:\/\/.*\.(jpg|jpeg|gif|png|webp|mp4|webm)((\?.*)$|$))/gim, '');
// handle urls
@@ -29,10 +27,10 @@ export const Content = memo(function Content({ data }: { data: any }) {
));
// handle mentions
- if (tags.length > 0) {
+ if (parseTags.length > 0) {
parsedContent = reactStringReplace(parsedContent, /\#\[(\d+)\]/gm, (match, i) => {
- if (tags[match][0] === 'p') {
- return ;
+ if (parseTags[match][0] === 'p') {
+ return ;
} else {
// #TODO: handle mention other note
// console.log(tags[match]);
@@ -48,7 +46,7 @@ export const Content = memo(function Content({ data }: { data: any }) {
-
+
{content}
diff --git a/src/components/note/counter/likes.tsx b/src/components/note/counter/likes.tsx
index 9a59c3e5..07e35470 100644
--- a/src/components/note/counter/likes.tsx
+++ b/src/components/note/counter/likes.tsx
@@ -7,7 +7,7 @@ import LikedIcon from '@assets/icons/liked';
import { useLocalStorage } from '@rehooks/local-storage';
import { getEventHash, signEvent } from 'nostr-tools';
-import { memo, useContext, useState } from 'react';
+import { memo, useContext, useEffect, useState } from 'react';
export const LikesCounter = memo(function LikesCounter({
count,
@@ -24,7 +24,7 @@ export const LikesCounter = memo(function LikesCounter({
const [currentUser]: any = useLocalStorage('current-user');
const [isReact, setIsReact] = useState(false);
- const [like, setLike] = useState(count);
+ const [like, setLike] = useState(0);
const handleLike = (e: any) => {
e.stopPropagation();
@@ -49,6 +49,10 @@ export const LikesCounter = memo(function LikesCounter({
setLike(like + 1);
};
+ useEffect(() => {
+ setLike(count);
+ }, [count]);
+
return (