diff --git a/android/app/src/main/java/com/nostros/classes/Database.java b/android/app/src/main/java/com/nostros/classes/Database.java index 78f8107..602c3e6 100644 --- a/android/app/src/main/java/com/nostros/classes/Database.java +++ b/android/app/src/main/java/com/nostros/classes/Database.java @@ -243,6 +243,19 @@ public class Database { try { instance.execSQL("ALTER TABLE nostros_users ADD COLUMN tags TEXT;"); } catch (SQLException e) { } + try { + instance.execSQL("CREATE TABLE IF NOT EXISTS nostros_notifications(\n" + + " id TEXT PRIMARY KEY NOT NULL, \n" + + " content TEXT NOT NULL,\n" + + " created_at INT NOT NULL,\n" + + " kind INT NOT NULL,\n" + + " pubkey TEXT NOT NULL,\n" + + " tags TEXT NOT NULL\n," + + " amount FLOAT,\n" + + " event_id TEXT\n" + + " );"); + instance.execSQL("CREATE INDEX nostros_notifications_index ON nostros_notifications(created_at);"); + } catch (SQLException e) { } } public void saveEvent(JSONObject data, String userPubKey, String relayUrl) throws JSONException { diff --git a/android/app/src/main/java/com/nostros/classes/Event.java b/android/app/src/main/java/com/nostros/classes/Event.java index 6f195ec..8e4a488 100644 --- a/android/app/src/main/java/com/nostros/classes/Event.java +++ b/android/app/src/main/java/com/nostros/classes/Event.java @@ -67,7 +67,7 @@ public class Event { } else if (kind.equals("4")) { saveDirectMessage(database); } else if (kind.equals("7")) { - saveReaction(database); + saveReaction(database, userPubKey); } else if (kind.equals("40")) { saveGroup(database); } else if (kind.equals("41")) { @@ -81,7 +81,7 @@ public class Event { } else if (kind.equals("10002")) { saveRelayMetadata(database); } else if (kind.equals("9735")) { - saveZap(database); + saveZap(database, userPubKey); } else if (kind.equals("10000") || kind.equals("10001") || kind.equals("30001")) { saveList(database); } @@ -258,10 +258,33 @@ public class Event { return ""; } + protected void saveNotification(SQLiteDatabase database, String eventId, double amount) { + String query = "SELECT id FROM nostros_notifications WHERE id = ?"; + @SuppressLint("Recycle") Cursor cursor = database.rawQuery(query, new String[] {id}); + if (cursor.getCount() == 0) { + ContentValues values = new ContentValues(); + values.put("id", id); + values.put("content", content); + values.put("created_at", created_at); + values.put("kind", kind); + values.put("pubkey", pubkey); + values.put("tags", tags.toString()); + values.put("amount", amount); + values.put("event_id", eventId); + database.replace("nostros_notifications", null, values); + } + } + protected void saveNote(SQLiteDatabase database, String userPubKey) { String query = "SELECT id FROM nostros_notes WHERE id = ?"; @SuppressLint("Recycle") Cursor cursor = database.rawQuery(query, new String[] {id}); + int userMentioned = getUserMentioned(userPubKey); + String repostId = getRepostId(); + if (userMentioned > 0 && !pubkey.equals(userPubKey)) { + saveNotification(database, repostId, 0); + } + if (cursor.getCount() == 0) { ContentValues values = new ContentValues(); values.put("id", id); @@ -273,8 +296,8 @@ public class Event { values.put("tags", tags.toString()); values.put("main_event_id", getMainEventId()); values.put("reply_event_id", getReplyEventId()); - values.put("user_mentioned", getUserMentioned(userPubKey)); - values.put("repost_id", getRepostId()); + values.put("user_mentioned", userMentioned); + values.put("repost_id", repostId); database.replace("nostros_notes", null, values); } } @@ -480,7 +503,7 @@ public class Event { } } - protected void saveReaction(SQLiteDatabase database) throws JSONException { + protected void saveReaction(SQLiteDatabase database, String userPubKey) throws JSONException { String query = "SELECT created_at FROM nostros_reactions WHERE id = ?"; @SuppressLint("Recycle") Cursor cursor = database.rawQuery(query, new String[] {id}); @@ -497,6 +520,10 @@ public class Event { reacted_user_id = pTags.getJSONArray(pTags.length() - 1).getString(1); } + if (!pubkey.equals(userPubKey) && reacted_user_id.equals(userPubKey)) { + saveNotification(database, reacted_event_id, 0); + } + ContentValues values = new ContentValues(); values.put("id", id); values.put("content", content); @@ -556,7 +583,7 @@ public class Event { } } - protected void saveZap(SQLiteDatabase database) throws JSONException { + protected void saveZap(SQLiteDatabase database, String userPubKey) throws JSONException { String query = "SELECT created_at FROM nostros_zaps WHERE id = ?"; @SuppressLint("Recycle") Cursor cursor = database.rawQuery(query, new String[] {id}); @@ -595,6 +622,10 @@ public class Event { @SuppressLint("Recycle") Cursor userCursor = database.rawQuery(userQuery, new String[] {pubkey, zapped_user_id}); if (userCursor.moveToFirst()) { + if (zapped_user_id.equals(userPubKey) && !pubkey.equals(userPubKey)) { + saveNotification(database, zapped_event_id, amount); + } + ContentValues values = new ContentValues(); values.put("id", id); values.put("content", content); diff --git a/frontend/Functions/DatabaseFunctions/Notifications/index.ts b/frontend/Functions/DatabaseFunctions/Notifications/index.ts new file mode 100644 index 0000000..e725094 --- /dev/null +++ b/frontend/Functions/DatabaseFunctions/Notifications/index.ts @@ -0,0 +1,49 @@ +import { type Kind } from 'nostr-tools' +import { type QuickSQLiteConnection } from 'react-native-quick-sqlite' +import { getItems } from '..' + +export interface Notification { + content: string + created_at: number + id?: string + kind: Kind | number + pubkey: string + amount: number + event_id?: string + tags: string[][] + name: string +} +const databaseToEntity: (object: any) => Notification = (object) => { + object.tags = object.tags ? JSON.parse(object.tags) : [] + return object as Notification +} + +export const getNotifications: ( + db: QuickSQLiteConnection, + options: { + limit?: number + since?: number + }, +) => Promise = async (db, { limit, since }) => { + let notificationsQuery = ` + SELECT + nostros_notifications.*, nostros_users.name + FROM + nostros_notifications + LEFT JOIN + nostros_users ON nostros_users.id = nostros_notifications.pubkey + ` + if (since) { + notificationsQuery += `WHERE nostros_notifications.created_at > ${since} ` + } + notificationsQuery += 'ORDER BY nostros_notifications.created_at DESC ' + if (limit) { + notificationsQuery += `LIMIT ${limit} ` + } + + const resultSet = db.execute(notificationsQuery) + const items: object[] = getItems(resultSet) + const messages: Notification[] = items.map((object) => databaseToEntity(object)) + + return messages +} diff --git a/frontend/Functions/DatabaseFunctions/index.ts b/frontend/Functions/DatabaseFunctions/index.ts index 896b007..a64d9c1 100644 --- a/frontend/Functions/DatabaseFunctions/index.ts +++ b/frontend/Functions/DatabaseFunctions/index.ts @@ -38,6 +38,7 @@ export const dropTables: (db: QuickSQLiteConnection) => Promise { { kinds: [Kind.ChannelMessage], '#e': results.map((group) => group.id ?? ''), + limit: 30, }, ]) } diff --git a/frontend/Pages/HomePage/HomeFeed/GlobalFeed/index.tsx b/frontend/Pages/HomePage/HomeFeed/GlobalFeed/index.tsx index 8a3f799..66e11d4 100644 --- a/frontend/Pages/HomePage/HomeFeed/GlobalFeed/index.tsx +++ b/frontend/Pages/HomePage/HomeFeed/GlobalFeed/index.tsx @@ -107,6 +107,13 @@ export const GlobalFeed: React.FC = ({ setRefreshing(false) if (results.length > 0) { setNotes(results) + const message: RelayFilters[] = [ + { + kinds: [Kind.Metadata], + authors: results.map((r) => r.pubkey), + }, + ] + relayPool?.subscribe('homepage-global-meta', message) const repostIds = notes .filter((note) => note.repost_id) .map((note) => note.repost_id ?? '') diff --git a/frontend/Pages/HomePage/HomeFeed/MyFeed/index.tsx b/frontend/Pages/HomePage/HomeFeed/MyFeed/index.tsx index 57b4fb4..ec3f733 100644 --- a/frontend/Pages/HomePage/HomeFeed/MyFeed/index.tsx +++ b/frontend/Pages/HomePage/HomeFeed/MyFeed/index.tsx @@ -90,11 +90,13 @@ export const MyFeed: React.FC = ({ setNotes(results) setRefreshing(false) - relayPool?.subscribe('homepage-myfeed-main', [{ - kinds: [Kind.Text, Kind.RecommendRelay], - authors: contacts, - limit: pageSize - }]) + relayPool?.subscribe('homepage-myfeed-main', [ + { + kinds: [Kind.Text, Kind.RecommendRelay], + authors: contacts, + limit: pageSize, + }, + ]) if (results.length > 0) { const noteIds = results.map((note) => note.id ?? '') diff --git a/frontend/Pages/HomePage/HomeFeed/ZapsFeed/index.tsx b/frontend/Pages/HomePage/HomeFeed/ZapsFeed/index.tsx index 751c05e..55bc4b6 100644 --- a/frontend/Pages/HomePage/HomeFeed/ZapsFeed/index.tsx +++ b/frontend/Pages/HomePage/HomeFeed/ZapsFeed/index.tsx @@ -72,7 +72,7 @@ export const ZapsFeed: React.FC = ({ if (database && publicKey) { const users: User[] = await getUsers(database, { contacts: true, order: 'created_at DESC' }) const contacts: string[] = [...users.map((user) => user.id), publicKey] - relayPool?.subscribe(`profile-zaps${publicKey}`, [ + relayPool?.subscribe(`homepage-zaps`, [ { kinds: [9735], '#p': contacts, diff --git a/frontend/Pages/HomePage/HomeFeed/index.tsx b/frontend/Pages/HomePage/HomeFeed/index.tsx index d061c56..177c5f2 100644 --- a/frontend/Pages/HomePage/HomeFeed/index.tsx +++ b/frontend/Pages/HomePage/HomeFeed/index.tsx @@ -32,6 +32,7 @@ export const HomeFeed: React.FC = ({ navigation }) => { 'homepage-zapped-notes', 'homepage-zapped-reactions', 'homepage-zapped-reposts', + 'homepage-zaps', ]) } if (activeTab !== 'myFeed') { @@ -42,7 +43,11 @@ export const HomeFeed: React.FC = ({ navigation }) => { ]) } if (activeTab !== 'globalFeed') { - relayPool?.unsubscribe(['homepage-global-main', 'homepage-global-reposts']) + relayPool?.unsubscribe([ + 'homepage-global-main', + 'homepage-global-reposts', + 'homepage-global-meta', + ]) } } diff --git a/frontend/Pages/HomePage/NotificationsFeed/index.tsx b/frontend/Pages/HomePage/NotificationsFeed/index.tsx index 44b43ac..41c1948 100644 --- a/frontend/Pages/HomePage/NotificationsFeed/index.tsx +++ b/frontend/Pages/HomePage/NotificationsFeed/index.tsx @@ -8,7 +8,7 @@ import { } from 'react-native' import { AppContext, type Config } from '../../../Contexts/AppContext' import SInfo from 'react-native-sensitive-info' -import { getMentionNotes, getNotes, type Note } from '../../../Functions/DatabaseFunctions/Notes' +import { type Note } from '../../../Functions/DatabaseFunctions/Notes' import { RelayPoolContext } from '../../../Contexts/RelayPoolContext' import { Kind } from 'nostr-tools' import { UserContext } from '../../../Contexts/UserContext' @@ -18,31 +18,27 @@ import { navigate } from '../../../lib/Navigation' import { useFocusEffect } from '@react-navigation/native' import { format, fromUnixTime, getUnixTime } from 'date-fns' import { FlashList, type ListRenderItem } from '@shopify/flash-list' -import { getETags } from '../../../Functions/RelayFunctions/Events' -import { getReactions, type Reaction } from '../../../Functions/DatabaseFunctions/Reactions' -import { getUsers, type User } from '../../../Functions/DatabaseFunctions/Users' import { username } from '../../../Functions/RelayFunctions/Users' import { TouchableWithoutFeedback } from 'react-native-gesture-handler' -import { getUserZaps, type Zap } from '../../../Functions/DatabaseFunctions/Zaps' import { formatDate, handleInfinityScroll } from '../../../Functions/NativeFunctions' import { useTranslation } from 'react-i18next' +import { + getNotifications, + type Notification, +} from '../../../Functions/DatabaseFunctions/Notifications' +import { getTaggedEventIds } from '../../../Functions/RelayFunctions/Events' export const NotificationsFeed: React.FC = () => { - const initialLimitDate = React.useMemo(() => getUnixTime(new Date()) - 86400, []) + const initialLimitPage = React.useMemo(() => 20, []) const theme = useTheme() const { t } = useTranslation('common') const { database, setNotificationSeenAt, pushedTab, getSatoshiSymbol } = useContext(AppContext) const { publicKey, reloadLists, mutedEvents, mutedUsers } = useContext(UserContext) const { lastEventId, relayPool } = useContext(RelayPoolContext) - const [pubKeys, setPubKeys] = React.useState([]) - const [users, setUsers] = React.useState([]) - const [userNotes, setUserNotes] = useState([]) - const [mentionNotes, setMentionNotes] = useState([]) - const [reactions, setReaction] = useState([]) - const [zaps, setZaps] = useState([]) + const [notifications, setNotifications] = useState([]) const [refreshing, setRefreshing] = useState(true) const flashListRef = React.useRef>(null) - const [limitDate, setLimitDate] = useState(initialLimitDate) + const [limitPage, setLimitPage] = useState(initialLimitPage) useFocusEffect( React.useCallback(() => { @@ -76,18 +72,6 @@ export const NotificationsFeed: React.FC = () => { } }, [pushedTab]) - useEffect(() => { - if (database && pubKeys.length > 0) { - getUsers(database, { includeIds: pubKeys }).then(setUsers) - relayPool?.subscribe('notification-users', [ - { - kinds: [Kind.Metadata], - authors: pubKeys.filter((key, index, array) => array.indexOf(key) === index), - }, - ]) - } - }, [pubKeys]) - const updateLastSeen: () => void = () => { const unixtime = getUnixTime(new Date()) setNotificationSeenAt(unixtime) @@ -100,31 +84,16 @@ export const NotificationsFeed: React.FC = () => { const subscribeNotes: () => void = async () => { if (!publicKey || !database) return - - getNotes(database, { filters: { pubkey: [publicKey] }, limitDate }).then((results) => { - if (results) { - setUserNotes(results) - const eventIds = results.map((e) => e.id ?? '') - if (eventIds.length > 0) { - relayPool?.subscribe('notification-reactions', [ - { - kinds: [Kind.Reaction, 9735], - '#e': eventIds, - }, - ]) - } - } - }) relayPool?.subscribe('notification-feed', [ { kinds: [Kind.Text], '#p': [publicKey], - since: limitDate, + limit: limitPage, }, { - kinds: [Kind.Text], - '#e': [publicKey], - since: limitDate, + kinds: [Kind.Reaction, 9735], + '#p': [publicKey], + limit: limitPage, }, { kinds: [30001], @@ -135,29 +104,22 @@ export const NotificationsFeed: React.FC = () => { const loadNotes: () => void = async () => { if (database && publicKey) { - getReactions(database, { reactedUser: publicKey, limitDate }).then((results) => { - setPubKeys((prev) => [...prev, ...results.map((res) => res.pubkey)]) - setReaction(results) - }) - getUserZaps(database, publicKey, limitDate).then((results) => { - setZaps(results) - setPubKeys((prev) => [...prev, ...results.map((res) => res.zapper_user_id)]) - }) - getMentionNotes(database, publicKey, limitDate).then(async (notes) => { - const unmutedThreads = notes.filter((note) => { - if (!note?.id) return false - const eTags = getETags(note) - return ( - !eTags.some((tag) => mutedEvents.includes(tag[1])) && !mutedUsers.includes(note.pubkey) - ) + getNotifications(database, { limit: limitPage }).then((results) => { + const filtered = results.filter((event) => { + const eTags = getTaggedEventIds(event) + return !mutedUsers.includes(event.pubkey) && !mutedEvents.some((id) => eTags.includes(id)) }) - setMentionNotes(unmutedThreads) - setRefreshing(false) - if (notes.length > 0) { - setPubKeys((prev) => [...prev, ...notes.map((note) => note.pubkey ?? '')]) - } - if (notes.length < 5) { - setLimitDate(limitDate - 86400) + if (filtered.length > 0) { + setNotifications(filtered) + const pubKeys = filtered + .map((n) => n.pubkey) + .filter((key, index, array) => array.indexOf(key) === index) + relayPool?.subscribe('notification-users', [ + { + kinds: [Kind.Metadata], + authors: pubKeys, + }, + ]) } }) } @@ -171,41 +133,30 @@ export const NotificationsFeed: React.FC = () => { }, []) useEffect(() => { - if (limitDate < initialLimitDate) { + if (limitPage < initialLimitPage) { loadNotes() } - }, [limitDate]) + }, [limitPage]) - const generateItemVariables: (item: Note | Reaction | Zap) => { - user: User | undefined - eventId: string | undefined - content: string | undefined + const generateItemVariables: (item: Notification) => { + noteId: string | undefined + content: string icon: string iconColor: string description: string } = (item) => { - let note: Note | undefined - let user: User | undefined - let content: string | undefined - let eventId: string | undefined + let noteId: string | undefined = item.event_id + let content: string = item.content.replace(/nostr:\S*/, '').trim() let icon: string let iconColor: string let description: string if (item.kind === 9735) { - note = userNotes.find((note) => note.id === item.zapped_event_id) - user = users.find((user) => user.id === item.zapper_user_id) - const zapDescription = item.tags?.find((tag) => tag[0] === 'description') - content = zapDescription ? JSON.parse(zapDescription[1])?.content : '' - eventId = note?.id icon = 'lightning-bolt' iconColor = '#F5D112' description = 'notificationsFeed.zap' } else if (item.kind === Kind.Reaction) { - note = userNotes.find((note) => note.id === item.reacted_event_id) - user = users.find((user) => user.id === item.pubkey) - content = note?.content - eventId = note?.id + content = '' if (item.content === '-') { icon = 'thumb-down' iconColor = theme.colors.error @@ -215,60 +166,54 @@ export const NotificationsFeed: React.FC = () => { iconColor = theme.colors.onPrimaryContainer description = 'notificationsFeed.like' } - } else if (item.repost_id) { - note = userNotes.find((note) => note.id === item.repost_id) - user = users.find((user) => user.id === item.pubkey) - content = note?.content - eventId = note?.id + } else if (item.event_id) { icon = 'cached' iconColor = '#7ADC70' description = 'notificationsFeed.reposted' } else { - note = userNotes.find((note) => note.id === item.reacted_event_id) - user = users.find((user) => user.id === item.pubkey) - content = item?.content - eventId = item?.id + noteId = item.id icon = 'message-outline' iconColor = theme.colors.onPrimaryContainer description = 'notificationsFeed.replied' } return { - eventId, + noteId, content, - user, icon, iconColor, description, } } - const renderItem: ListRenderItem = ({ item }) => { + const renderItem: ListRenderItem = ({ item }) => { const date = fromUnixTime(item.created_at) - const { user, icon, iconColor, description, content, eventId } = generateItemVariables(item) + const { noteId, content, icon, iconColor, description } = generateItemVariables(item) return ( - navigate('Note', { noteId: eventId })}> + noteId && navigate('Note', { noteId })}> - {username(user)} + {username({ name: item.name, id: item.pubkey })} {t(description, { amount: item.amount ?? '' })} {item.kind === 9735 && getSatoshiSymbol(16)} - - {content?.replace(/#\[\d\]/, '')} - + {content !== '' && ( + + {content?.replace(/#\[\d\]/, '')} + + )} {formatDate(item.created_at, false)} @@ -304,7 +249,7 @@ export const NotificationsFeed: React.FC = () => { const onScroll: (event: NativeSyntheticEvent) => void = (event) => { if (handleInfinityScroll(event)) { - setLimitDate(limitDate - 86400) + setLimitPage(limitPage + initialLimitPage) } } @@ -312,7 +257,7 @@ export const NotificationsFeed: React.FC = () => { b.created_at - a.created_at)} + data={notifications.sort((a, b) => b.created_at - a.created_at)} renderItem={renderItem} refreshControl={} refreshing={refreshing} @@ -320,7 +265,7 @@ export const NotificationsFeed: React.FC = () => { horizontal={false} estimatedItemSize={100} ListFooterComponent={ - mentionNotes.length > 0 ? ( + notifications.length > 0 ? ( ) : ( <> diff --git a/frontend/Pages/HomePage/index.tsx b/frontend/Pages/HomePage/index.tsx index f485034..7939f62 100644 --- a/frontend/Pages/HomePage/index.tsx +++ b/frontend/Pages/HomePage/index.tsx @@ -8,24 +8,22 @@ import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityI import { UserContext } from '../../Contexts/UserContext' import { RelayPoolContext } from '../../Contexts/RelayPoolContext' import { Kind, nip19 } from 'nostr-tools' -import { getMentionNotes, getNotificationsIds } from '../../Functions/DatabaseFunctions/Notes' import { AppContext } from '../../Contexts/AppContext' import { StyleSheet } from 'react-native' import RBSheet from 'react-native-raw-bottom-sheet' import { useTranslation } from 'react-i18next' import { navigate } from '../../lib/Navigation' -import { - getDirectMessagesCount, - getGroupedDirectMessages, -} from '../../Functions/DatabaseFunctions/DirectMessages' +import { getDirectMessagesCount } from '../../Functions/DatabaseFunctions/DirectMessages' import GroupsFeed from './GroupsFeed' import { getUserGroupMessagesCount } from '../../Functions/DatabaseFunctions/Groups' +import { getNotifications } from '../../Functions/DatabaseFunctions/Notifications' +import { getTaggedEventIds } from '../../Functions/RelayFunctions/Events' export const HomePage: React.FC = () => { const theme = useTheme() const { t } = useTranslation('common') const { language, setPushedTab } = React.useContext(AppContext) - const { privateKey, publicKey, mutedEvents } = React.useContext(UserContext) + const { privateKey, publicKey, mutedEvents, mutedUsers } = React.useContext(UserContext) const { database, notificationSeenAt, clipboardNip21, setClipboardNip21, refreshBottomBarAt } = useContext(AppContext) const { relayPool, lastEventId } = useContext(RelayPoolContext) @@ -42,12 +40,15 @@ export const HomePage: React.FC = () => { useEffect(() => { if (publicKey && database && relayPool) { - getNotificationsIds(database, publicKey, notificationSeenAt).then((results) => { - const unmutedThreads = results.filter((id) => { - if (!id ?? id === '') return false - return !mutedEvents.includes(id) - }) - setNewNotifications(unmutedThreads.length) + getNotifications(database, { since: notificationSeenAt }).then((results) => { + setNewNotifications( + results.filter((event) => { + const eTags = getTaggedEventIds(event) + return ( + !mutedUsers.includes(event.pubkey) && !mutedEvents.some((id) => eTags.includes(id)) + ) + }).length, + ) }) getUserGroupMessagesCount(database, publicKey).then(setNewGroupMessages) getDirectMessagesCount(database, publicKey).then(setNewdirectMessages) @@ -57,35 +58,23 @@ export const HomePage: React.FC = () => { const subscribe: () => void = () => { if (publicKey && database) { - getMentionNotes(database, publicKey, 1).then((mentionResults) => { - getGroupedDirectMessages(database, { limit: 1 }).then((directMessageResults) => { - relayPool?.subscribe('notification-icon', [ - { - kinds: [Kind.ChannelMessage], - '#p': [publicKey], - limit: 30, - }, - { - kinds: [Kind.EncryptedDirectMessage], - '#p': [publicKey], - since: directMessageResults[0]?.created_at ?? 0, - limit: 30, - }, - { - kinds: [Kind.Text], - '#p': [publicKey], - since: mentionResults[0]?.created_at ?? 0, - limit: 30, - }, - { - kinds: [Kind.Text], - '#e': [publicKey], - since: mentionResults[0]?.created_at ?? 0, - limit: 30, - }, - ]) - }) - }) + relayPool?.subscribe('notification-icon', [ + { + kinds: [Kind.ChannelMessage], + '#p': [publicKey], + limit: 30, + }, + { + kinds: [Kind.EncryptedDirectMessage], + '#p': [publicKey], + limit: 30, + }, + { + kinds: [Kind.Text, Kind.Reaction, 9735], + '#p': [publicKey], + limit: 30, + }, + ]) } } diff --git a/frontend/Pages/NotePage/index.tsx b/frontend/Pages/NotePage/index.tsx index 969dd9a..0483bac 100644 --- a/frontend/Pages/NotePage/index.tsx +++ b/frontend/Pages/NotePage/index.tsx @@ -52,7 +52,7 @@ export const NotePage: React.FC = ({ route }) => { const loadGroup: () => void = async () => { if (database) { getGroup(database, route.params.noteId).then((result) => { - if (result) { + if (result.id) { navigate('Group', { groupId: result.id, title: result.name ?? formatId(result.id), @@ -99,6 +99,7 @@ export const NotePage: React.FC = ({ route }) => { }, []) const subscribeNotes: (past?: boolean) => Promise = async (past) => { + console.log(route.params) if (database && route.params.noteId) { relayPool?.subscribe(`notepage${route.params.noteId.substring(0, 8)}`, [ { diff --git a/package.json b/package.json index 84acfe0..a896baa 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "dependencies": { "@eva-design/eva": "^2.1.0", "@react-native-clipboard/clipboard": "^1.11.2", - "@react-native-community/cli-platform-android": "^10.2.0", + "@react-native-community/cli-platform-android": "^11.1.0", "@react-navigation/bottom-tabs": "^6.5.3", "@react-navigation/drawer": "^6.5.7", "@react-navigation/native": "^6.1.2", @@ -30,7 +30,7 @@ "cryptr": "^6.1.0", "date-fns": "^2.29.3", "events": "^3.3.0", - "i18next": "^22.4.13", + "i18next": "^22.4.14", "lnurl-pay": "^2.2.0", "lodash.debounce": "^4.0.8", "nostr-tools": "^1.7.5", @@ -67,7 +67,7 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@babel/core": "^7.20.2", + "@babel/core": "^7.21.4", "@babel/runtime": "^7.20.13", "@react-native-community/eslint-config": "^3.2.0", "@types/create-hash": "^1.2.2", @@ -84,7 +84,7 @@ "eslint": "^8.36.0", "eslint-config-prettier": "^8.8.0", "eslint-config-standard-with-typescript": "^34.0.1", - "eslint-import-resolver-typescript": "^3.5.3", + "eslint-import-resolver-typescript": "^3.5.4", "eslint-plugin-i18next": "^6.0.0-8", "eslint-plugin-import": "^2.27.5", "eslint-plugin-n": "^15.6.0", diff --git a/yarn.lock b/yarn.lock index d318e30..6e93fbb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -49,12 +49,24 @@ dependencies: "@babel/highlight" "^7.18.6" +"@babel/code-frame@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39" + integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g== + dependencies: + "@babel/highlight" "^7.18.6" + "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.5": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.0.tgz#c241dc454e5b5917e40d37e525e2f4530c399298" integrity sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g== -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.14.0", "@babel/core@^7.20.0", "@babel/core@^7.20.2": +"@babel/compat-data@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.4.tgz#457ffe647c480dff59c2be092fc3acf71195c87f" + integrity sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.14.0", "@babel/core@^7.20.0": version "7.21.3" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.3.tgz#cf1c877284a469da5d1ce1d1e53665253fae712e" integrity sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw== @@ -75,6 +87,27 @@ json5 "^2.2.2" semver "^6.3.0" +"@babel/core@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.4.tgz#c6dc73242507b8e2a27fd13a9c1814f9fa34a659" + integrity sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.21.4" + "@babel/generator" "^7.21.4" + "@babel/helper-compilation-targets" "^7.21.4" + "@babel/helper-module-transforms" "^7.21.2" + "@babel/helpers" "^7.21.0" + "@babel/parser" "^7.21.4" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.4" + "@babel/types" "^7.21.4" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.2" + semver "^6.3.0" + "@babel/eslint-parser@^7.18.2": version "7.21.3" resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.21.3.tgz#d79e822050f2de65d7f368a076846e7184234af7" @@ -94,6 +127,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.4.tgz#64a94b7448989f421f919d5239ef553b37bb26bc" + integrity sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA== + dependencies: + "@babel/types" "^7.21.4" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" @@ -112,6 +155,17 @@ lru-cache "^5.1.1" semver "^6.3.0" +"@babel/helper-compilation-targets@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz#770cd1ce0889097ceacb99418ee6934ef0572656" + integrity sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg== + dependencies: + "@babel/compat-data" "^7.21.4" + "@babel/helper-validator-option" "^7.21.0" + browserslist "^4.21.3" + lru-cache "^5.1.1" + semver "^6.3.0" + "@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz#64f49ecb0020532f19b1d014b03bccaa1ab85fb9" @@ -297,6 +351,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.3.tgz#1d285d67a19162ff9daa358d4cb41d50c06220b3" integrity sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ== +"@babel/parser@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.4.tgz#94003fdfc520bbe2875d4ae557b43ddb6d880f17" + integrity sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw== + "@babel/plugin-proposal-async-generator-functions@^7.0.0": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz#bfb7276d2d573cb67ba379984a2334e262ba5326" @@ -787,6 +846,22 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.4.tgz#a836aca7b116634e97a6ed99976236b3282c9d36" + integrity sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q== + dependencies: + "@babel/code-frame" "^7.21.4" + "@babel/generator" "^7.21.4" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.21.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.21.4" + "@babel/types" "^7.21.4" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.21.3", "@babel/types@^7.3.0", "@babel/types@^7.3.3": version "7.21.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.3.tgz#4865a5357ce40f64e3400b0f3b737dc6d4f64d05" @@ -796,6 +871,15 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@babel/types@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.4.tgz#2d5d6bb7908699b3b416409ffd3b5daa25b030d4" + integrity sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -1302,6 +1386,17 @@ glob "^7.1.3" logkitty "^0.7.1" +"@react-native-community/cli-platform-android@^11.1.0": + version "11.1.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-11.1.1.tgz#843381104e61417f2d337598c6f5ff484d1fa1b2" + integrity sha512-+qim4c00uomP0N2VxsE4Qk3ixYLeElsIuwN5DkrSRzKwGSJqzdvkChEof7mkW803OyCl6cEBT1yrRWpvtSZOHA== + dependencies: + "@react-native-community/cli-tools" "11.1.1" + chalk "^4.1.2" + execa "^5.0.0" + glob "^7.1.3" + logkitty "^0.7.1" + "@react-native-community/cli-platform-ios@10.2.0": version "10.2.0" resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-10.2.0.tgz#be21c0e3bbf17358d540cc23e5556bf679f6322e" @@ -1358,6 +1453,21 @@ serve-static "^1.13.1" ws "^7.5.1" +"@react-native-community/cli-tools@11.1.1": + version "11.1.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-11.1.1.tgz#6ec1b6bf714cb7bdb360ca4a213e969e10b644f2" + integrity sha512-wkyzFxIncZCYfCHt1nwGE0pKspuP6yknNCF9nHxFXag0gPkTphpZWoV+uRVNRd+Fudx/qOtPiFAivGfw+8Pp2w== + dependencies: + appdirsjs "^1.2.4" + chalk "^4.1.2" + find-up "^5.0.0" + mime "^2.4.1" + node-fetch "^2.6.0" + open "^6.2.0" + ora "^5.4.1" + semver "^6.3.0" + shell-quote "^1.7.3" + "@react-native-community/cli-tools@^10.1.1": version "10.1.1" resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-10.1.1.tgz#fa66e509c0d3faa31f7bb87ed7d42ad63f368ddd" @@ -3369,7 +3479,7 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^5.10.0: +enhanced-resolve@^5.12.0: version "5.12.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== @@ -3536,18 +3646,18 @@ eslint-import-resolver-node@^0.3.7: is-core-module "^2.11.0" resolve "^1.22.1" -eslint-import-resolver-typescript@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.3.tgz#db5ed9e906651b7a59dd84870aaef0e78c663a05" - integrity sha512-njRcKYBc3isE42LaTcJNVANR3R99H9bAxBDMNDr2W7yq5gYPxbU3MkdhsQukxZ/Xg9C2vcyLlDsbKfRDg0QvCQ== +eslint-import-resolver-typescript@^3.5.4: + version "3.5.4" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.4.tgz#7370c326c3c08f0c1839c592d79d20b704de15d4" + integrity sha512-9xUpnedEmSfG57sN1UvWPiEhfJ8bPt0Wg2XysA7Mlc79iFGhmJtRUg9LxtkK81FhMUui0YuR2E8iUsVhePkh4A== dependencies: debug "^4.3.4" - enhanced-resolve "^5.10.0" - get-tsconfig "^4.2.0" - globby "^13.1.2" - is-core-module "^2.10.0" + enhanced-resolve "^5.12.0" + get-tsconfig "^4.5.0" + globby "^13.1.3" + is-core-module "^2.11.0" is-glob "^4.0.3" - synckit "^0.8.4" + synckit "^0.8.5" eslint-module-utils@^2.7.4: version "2.7.4" @@ -4194,10 +4304,10 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -get-tsconfig@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.4.0.tgz#64eee64596668a81b8fce18403f94f245ee0d4e5" - integrity sha512-0Gdjo/9+FzsYhXCEFueo2aY1z1tpXrxWZzP7k8ul9qt1U5o8rYJwTJYmaeHdrVosYIVYkOy2iwCJ9FdpocJhPQ== +get-tsconfig@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.5.0.tgz#6d52d1c7b299bd3ee9cd7638561653399ac77b0f" + integrity sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ== get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" @@ -4266,7 +4376,7 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -globby@^13.1.2: +globby@^13.1.3: version "13.1.3" resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.3.tgz#f62baf5720bcb2c1330c8d4ef222ee12318563ff" integrity sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw== @@ -4461,10 +4571,10 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -i18next@^22.4.13: - version "22.4.13" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-22.4.13.tgz#02e291ab0056eab13b7d356fb454ff991923eaa0" - integrity sha512-GX7flMHRRqQA0I1yGLmaZ4Hwt1JfLqagk8QPDPZsqekbKtXsuIngSVWM/s3SLgNkrEXjA+0sMGNuOEkkmyqmWg== +i18next@^22.4.14: + version "22.4.14" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-22.4.14.tgz#18dd94e9adc2618497c7de101a206e1ca3a18727" + integrity sha512-VtLPtbdwGn0+DAeE00YkiKKXadkwg+rBUV+0v8v0ikEjwdiJ0gmYChVE4GIa9HXymY6wKapkL93vGT7xpq6aTw== dependencies: "@babel/runtime" "^7.20.6" @@ -4612,7 +4722,7 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.10.0, is-core-module@^2.11.0, is-core-module@^2.9.0: +is-core-module@^2.11.0, is-core-module@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== @@ -7805,7 +7915,7 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -synckit@^0.8.4: +synckit@^0.8.5: version "0.8.5" resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.5.tgz#b7f4358f9bb559437f9f167eb6bc46b3c9818fa3" integrity sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==