From 4630f30eed913ad82bc636cb0bbf00e758dbab1d Mon Sep 17 00:00:00 2001 From: KoalaSat Date: Wed, 2 Nov 2022 03:35:11 +0100 Subject: [PATCH] Some fixes and SQL improvement --- App.tsx | 3 + android/build.gradle | 2 +- frontend/Components/ContactsPage/index.tsx | 9 ++- frontend/Components/HomePage/index.tsx | 50 ++++++------- .../Components/LandingPage/Logger/index.tsx | 10 +-- frontend/Components/NotePage/index.tsx | 4 +- frontend/Components/ProfilePage/index.tsx | 75 ++++++++----------- frontend/Contexts/AppContext.tsx | 16 ++-- frontend/Contexts/RelayPoolContext.tsx | 63 +++++++++------- frontend/Functions/DatabaseFunctions/index.ts | 11 ++- 10 files changed, 116 insertions(+), 127 deletions(-) diff --git a/App.tsx b/App.tsx index fe12dae..8b4afad 100644 --- a/App.tsx +++ b/App.tsx @@ -1,6 +1,9 @@ import App from './frontend' import { Buffer as SafeBuffer } from 'safe-buffer' +import SQLite from 'react-native-sqlite-storage' global.Buffer = SafeBuffer +SQLite.DEBUG(true) + export default App diff --git a/android/build.gradle b/android/build.gradle index f9f081a..e08fcdb 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -5,7 +5,7 @@ buildscript { buildToolsVersion = "31.0.0" minSdkVersion = 21 compileSdkVersion = 31 - targetSdkVersion = 31 + targetSdkVersion = 29 if (System.properties['os.arch'] == "aarch64") { // For M1 Users we need to use the NDK 24 which added support for aarch64 diff --git a/frontend/Components/ContactsPage/index.tsx b/frontend/Components/ContactsPage/index.tsx index c899205..33820b5 100644 --- a/frontend/Components/ContactsPage/index.tsx +++ b/frontend/Components/ContactsPage/index.tsx @@ -21,8 +21,8 @@ export const ContactsPage: React.FC = () => { const { relayPool, publicKey, lastEventId, setLastEventId, privateKey } = useContext(RelayPoolContext) const theme = useTheme() - const [users, setUsers] = useState([]) - const [refreshing, setRefreshing] = useState(false) + const [users, setUsers] = useState() + const [refreshing, setRefreshing] = useState(true) const [showAddContact, setShowAddContant] = useState(false) const [contactInput, setContactInput] = useState() const { t } = useTranslation('common') @@ -30,6 +30,7 @@ export const ContactsPage: React.FC = () => { useEffect(() => { if (database && publicKey) { getUsers(database, { contacts: true }).then((results) => { + if (users) setRefreshing(false) if (results) setUsers(results) }) } @@ -75,7 +76,7 @@ export const ContactsPage: React.FC = () => { const onRefresh = useCallback(() => { setRefreshing(true) relayPool?.unsubscribeAll() - subscribeContacts().finally(() => setRefreshing(false)) + subscribeContacts() }, []) const styles = StyleSheet.create({ @@ -112,7 +113,7 @@ export const ContactsPage: React.FC = () => { horizontal={false} refreshControl={} > - {users.map((user) => ( + {users?.map((user) => ( ))} diff --git a/frontend/Components/HomePage/index.tsx b/frontend/Components/HomePage/index.tsx index c8516aa..2797d47 100644 --- a/frontend/Components/HomePage/index.tsx +++ b/frontend/Components/HomePage/index.tsx @@ -18,7 +18,6 @@ import { EventKind } from '../../lib/nostr/Events' import { RelayFilters } from '../../lib/nostr/Relay' import { getReplyEventId } from '../../Functions/RelayFunctions/Events' import { getUsers, User } from '../../Functions/DatabaseFunctions/Users' -import Loading from '../Loading' import { handleInfinityScroll } from '../../Functions/NativeFunctions' export const HomePage: React.FC = () => { @@ -29,11 +28,11 @@ export const HomePage: React.FC = () => { const [pageSize, setPageSize] = useState(initialPageSize) const [notes, setNotes] = useState([]) const [authors, setAuthors] = useState([]) - const [refreshing, setRefreshing] = useState(false) + const [refreshing, setRefreshing] = useState(true) const calculateInitialNotes: () => Promise = async () => { - return await new Promise((resolve, reject) => { - if (database && publicKey && relayPool) { + return await new Promise((resolve) => { + if (database && publicKey) { getNotes(database, { limit: 1 }).then((notes) => { getUsers(database, { contacts: true, includeIds: [publicKey] }).then((users) => { setAuthors(users) @@ -41,8 +40,6 @@ export const HomePage: React.FC = () => { resolve() }) }) - } else { - reject(new Error('Not Ready')) } }) } @@ -71,6 +68,9 @@ export const HomePage: React.FC = () => { getNotes(database, { contacts: true, includeIds: [publicKey], limit: pageSize }).then( (notes) => { setNotes(notes) + if (notes.length > 0 || authors.length === 0) { + setRefreshing(false) + } }, ) } @@ -78,7 +78,8 @@ export const HomePage: React.FC = () => { useEffect(() => { relayPool?.unsubscribeAll() - }, []) + calculateInitialNotes().then(() => loadNotes()) + }, [publicKey]) useEffect(() => { loadNotes() @@ -92,15 +93,10 @@ export const HomePage: React.FC = () => { } }, [pageSize]) - useEffect(() => { - loadNotes() - calculateInitialNotes() - }, [database, publicKey, relayPool]) - const onRefresh = useCallback(() => { setRefreshing(true) relayPool?.unsubscribeAll() - calculateInitialNotes().finally(() => setRefreshing(false)) + calculateInitialNotes().then(() => loadNotes()) }, []) const onPress: (note: Note) => void = (note) => { @@ -149,22 +145,18 @@ export const HomePage: React.FC = () => { return ( <> - {notes.length === 0 && authors.length !== 0 ? ( - - ) : ( - } - > - {notes.map((note) => itemCard(note))} - {notes.length >= initialPageSize && ( - - - - )} - - )} + } + > + {notes.map((note) => itemCard(note))} + {notes.length >= initialPageSize && ( + + + + )} + {privateKey && ( { - const { database, goToPage } = useContext(AppContext) - const { privateKey, publicKey, relayPool, setPrivateKey, setPublicKey } = + const { database, goToPage, loadingDb } = useContext(AppContext) + const { privateKey, publicKey, relayPool, loadingRelayPool, setPrivateKey, setPublicKey } = useContext(RelayPoolContext) const { t } = useTranslation('common') const theme = useTheme() @@ -27,7 +27,7 @@ export const Logger: React.FC = () => { const [loadedUsers, setLoadedUsers] = useState() useEffect(() => { - if (relayPool && publicKey) { + if (!loadingRelayPool && publicKey) { relayPool?.unsubscribeAll() setStatus(1) initEvents() @@ -36,7 +36,7 @@ export const Logger: React.FC = () => { authors: [publicKey], }) } - }, [relayPool, publicKey]) + }, [loadingRelayPool, publicKey, loadingDb]) useEffect(() => { if (status > 2) { @@ -46,7 +46,7 @@ export const Logger: React.FC = () => { }, [status]) useEffect(() => { - if (status) { + if (status > 1) { const timer = setTimeout(() => setStatus(3), 8000) return () => { clearTimeout(timer) diff --git a/frontend/Components/NotePage/index.tsx b/frontend/Components/NotePage/index.tsx index 082c3b9..7d631cc 100644 --- a/frontend/Components/NotePage/index.tsx +++ b/frontend/Components/NotePage/index.tsx @@ -110,7 +110,7 @@ export const NotePage: React.FC = () => { } const subscribeNotes: () => Promise = async () => { - return await new Promise((resolve, reject) => { + return await new Promise((resolve) => { if (database) { getNotes(database, { filters: { id: eventId } }).then((events) => { if (events.length > 0) { @@ -140,8 +140,6 @@ export const NotePage: React.FC = () => { resolve() } }) - } else { - reject(new Error('Not Ready')) } }) } diff --git a/frontend/Components/ProfilePage/index.tsx b/frontend/Components/ProfilePage/index.tsx index 2d5f033..488d641 100644 --- a/frontend/Components/ProfilePage/index.tsx +++ b/frontend/Components/ProfilePage/index.tsx @@ -23,13 +23,7 @@ import UserAvatar from 'react-native-user-avatar' import { getNotes, Note } from '../../Functions/DatabaseFunctions/Notes' import NoteCard from '../NoteCard' import { RelayPoolContext } from '../../Contexts/RelayPoolContext' -import { - getUser, - removeContact, - addContact, - User, - getUsers, -} from '../../Functions/DatabaseFunctions/Users' +import { getUser, removeContact, addContact, User } from '../../Functions/DatabaseFunctions/Users' import { EventKind, Event } from '../../lib/nostr/Events' import Relay, { RelayFilters } from '../../lib/nostr/Relay' import Icon from 'react-native-vector-icons/FontAwesome5' @@ -38,14 +32,11 @@ import { getReplyEventId } from '../../Functions/RelayFunctions/Events' import Loading from '../Loading' import { storeEvent } from '../../Functions/DatabaseFunctions/Events' import { handleInfinityScroll } from '../../Functions/NativeFunctions' -import { useTranslation } from 'react-i18next' export const ProfilePage: React.FC = () => { const { database, page, goToPage, goBack } = useContext(AppContext) - const { publicKey, privateKey, lastEventId, relayPool, setLastEventId } = - useContext(RelayPoolContext) + const { publicKey, privateKey, lastEventId, relayPool } = useContext(RelayPoolContext) const theme = useTheme() - const { t } = useTranslation('common') const initialPageSize = 10 const [notes, setNotes] = useState() const [user, setUser] = useState() @@ -58,13 +49,35 @@ export const ProfilePage: React.FC = () => { const username = user?.name === '' ? user?.id : user?.name useEffect(() => { - setContactsIds(undefined) - setNotes(undefined) - setUser(undefined) - loadProfile() + if (page !== '') { + setContactsIds(undefined) + setNotes(undefined) + setUser(undefined) + loadProfile() + } }, [page]) useEffect(() => { + loadUser() + loadNotes() + }, [lastEventId]) + + useEffect(() => { + if (pageSize > initialPageSize && notes) { + relayPool?.unsubscribeAll() + loadUser() + loadNotes() + subscribeNotes(undefined, notes[notes.length - 1]?.created_at) + } + }, [pageSize]) + + const onRefresh = useCallback(() => { + setRefreshing(true) + relayPool?.unsubscribeAll() + loadProfile().finally(() => setRefreshing(false)) + }, []) + + const loadUser: () => void = () => { if (database) { getUser(userId, database).then((result) => { if (result) { @@ -72,14 +85,8 @@ export const ProfilePage: React.FC = () => { setIsContact(result?.contact) } }) - if (userId === publicKey) { - getUsers(database, { contacts: true }).then((users) => { - setContactsIds(users.map((user) => user.id)) - }) - } - loadNotes() } - }, [lastEventId]) + } const removeAuthor: () => void = () => { if (relayPool && database && publicKey) { @@ -149,20 +156,6 @@ export const ProfilePage: React.FC = () => { } } - const onRefresh = useCallback(() => { - setRefreshing(true) - relayPool?.unsubscribeAll() - loadProfile().finally(() => setRefreshing(false)) - }, []) - - useEffect(() => { - if (pageSize > initialPageSize && notes) { - relayPool?.unsubscribeAll() - subscribeNotes(undefined, notes[notes.length - 1]?.created_at) - loadNotes() - } - }, [pageSize]) - const loadNotes: () => void = () => { if (database) { getNotes(database, { filters: { pubkey: userId }, limit: pageSize }).then((results) => { @@ -197,7 +190,7 @@ export const ProfilePage: React.FC = () => { } const loadProfile: () => Promise = async () => { - return await new Promise((resolve, reject) => { + return await new Promise((resolve) => { relayPool?.subscribe('main-channel', { kinds: [EventKind.meta, EventKind.petNames], authors: [userId], @@ -210,14 +203,10 @@ export const ProfilePage: React.FC = () => { const ids = event.tags.map((tag) => tagToUser(tag).id) setContactsIds(ids) } else if (event.kind === EventKind.meta) { - storeEvent(event, database).finally(() => { - if (event?.id) setLastEventId(event.id) - }) + storeEvent(event, database) } calculateInitialNotes() } - } else { - reject(new Error('Not Ready')) } }) resolve() @@ -357,7 +346,7 @@ export const ProfilePage: React.FC = () => { /> ) : ( - {t('profilePage.profileNotCreated')} + <> )} diff --git a/frontend/Contexts/AppContext.tsx b/frontend/Contexts/AppContext.tsx index 7a70bd1..d6458e3 100644 --- a/frontend/Contexts/AppContext.tsx +++ b/frontend/Contexts/AppContext.tsx @@ -34,15 +34,17 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E const init: () => void = () => { SInfo.getItem('privateKey', {}).then((result) => { - const db = initDatabase() - setDatabase(db) - if (!result || result === '') { - createInitDatabase(db).then(() => { + const onReady: () => void = () => { + if (!result || result === '') { + createInitDatabase(db).then(() => { + setLoadingDb(false) + }) + } else { setLoadingDb(false) - }) - } else { - setLoadingDb(false) + } } + const db = initDatabase(onReady) + setDatabase(db) }) } diff --git a/frontend/Contexts/RelayPoolContext.tsx b/frontend/Contexts/RelayPoolContext.tsx index d7e5249..2ae00d3 100644 --- a/frontend/Contexts/RelayPoolContext.tsx +++ b/frontend/Contexts/RelayPoolContext.tsx @@ -10,6 +10,7 @@ import SInfo from 'react-native-sensitive-info' import { getPublickey } from '../lib/nostr/Bip' export interface RelayPoolContextProps { + loadingRelayPool: boolean relayPool?: RelayPool setRelayPool: (relayPool: RelayPool) => void publicKey?: string @@ -25,6 +26,7 @@ export interface RelayPoolContextProviderProps { } export const initialRelayPoolContext: RelayPoolContextProps = { + loadingRelayPool: true, setPublicKey: () => {}, setPrivateKey: () => {}, setRelayPool: () => {}, @@ -39,7 +41,10 @@ export const RelayPoolContextProvider = ({ const [publicKey, setPublicKey] = useState() const [privateKey, setPrivateKey] = useState() const [relayPool, setRelayPool] = useState() - const [lastEventId, setLastEventId] = useState() + const [loadingRelayPool, setLoadingRelayPool] = useState( + initialRelayPoolContext.loadingRelayPool, + ) + const [lastEventId, setLastEventId] = useState('') const [lastPage, setLastPage] = useState(page) const loadRelayPool: () => void = () => { @@ -74,23 +79,16 @@ export const RelayPoolContextProvider = ({ (relay: Relay, _subId?: string, event?: Event) => { console.log('RELAYPOOL EVENT =======>', relay.url, event) if (database && event?.id && event.kind !== EventKind.petNames) { - storeEvent(event, database) - .then(() => setLastEventId(event.id)) - .catch(() => setLastEventId(event.id)) + storeEvent(event, database).finally(() => setLastEventId(event.id)) } }, ) setRelayPool(initRelayPool) + setLoadingRelayPool(false) }) } } - useEffect(() => { - if ((privateKey !== '' || publicKey !== '') && !loadingDb && !relayPool) { - loadRelayPool() - } - }, [privateKey, loadingDb]) - useEffect(() => { if (relayPool && lastPage !== page) { relayPool.removeOn('event', lastPage) @@ -99,29 +97,36 @@ export const RelayPoolContextProvider = ({ }, [page]) useEffect(() => { - SInfo.getItem('privateKey', {}).then((privateResult) => { - if (privateResult && privateResult !== '') { - loadRelayPool() - goToPage('home', true) - setPrivateKey(privateResult) - setPublicKey(getPublickey(privateResult)) - } else { - SInfo.getItem('publicKey', {}).then((publicResult) => { - if (publicResult && publicResult !== '') { - loadRelayPool() - goToPage('home', true) - setPublicKey(publicResult) - } else { - goToPage('landing', true) - } - }) - } - }) - }, []) + if (publicKey && publicKey !== '') { + loadRelayPool() + } + }, [publicKey]) + + useEffect(() => { + if (!loadingDb) { + SInfo.getItem('privateKey', {}).then((privateResult) => { + if (privateResult && privateResult !== '') { + goToPage('home', true) + setPrivateKey(privateResult) + setPublicKey(getPublickey(privateResult)) + } else { + SInfo.getItem('publicKey', {}).then((publicResult) => { + if (publicResult && publicResult !== '') { + goToPage('home', true) + setPublicKey(publicResult) + } else { + goToPage('landing', true) + } + }) + } + }) + } + }, [loadingDb]) return ( SQLiteDatabase = () => { - return SQLite.openDatabase( - { name: 'nostros.db', location: 'default' }, - () => {}, - () => {}, - ) +export const initDatabase: (onReady: () => void, onError?: () => void) => SQLiteDatabase = ( + onReady, + onError, +) => { + return SQLite.openDatabase({ name: 'nostros.db' }, onReady, onError) } export const getItems: (resultSet: ResultSet) => object[] = (resultSet) => {