mirror of
https://github.com/KoalaSat/nostros.git
synced 2024-09-28 22:30:41 +00:00
Pull to load lists (#8)
This commit is contained in:
commit
903b770a1c
@ -24,6 +24,7 @@ module.exports = {
|
||||
'@typescript-eslint/no-dynamic-delete': 'off',
|
||||
'@typescript-eslint/no-floating-promises': 'off',
|
||||
'@typescript-eslint/no-misused-promises': 'off',
|
||||
'@typescript-eslint/restrict-template-expressions': 'off',
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Button, Card, Input, Layout, List, Modal, useTheme } from '@ui-kitten/components';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { Button, Card, Input, Layout, Modal, useTheme } from '@ui-kitten/components';
|
||||
import React, { useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { RefreshControl, ScrollView, StyleSheet } from 'react-native';
|
||||
import ActionButton from 'react-native-action-button';
|
||||
import { AppContext } from '../../Contexts/AppContext';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
@ -22,6 +22,7 @@ export const ContactsPage: React.FC = () => {
|
||||
const { relayPool, publicKey, lastEventId, setLastEventId } = useContext(RelayPoolContext);
|
||||
const theme = useTheme();
|
||||
const [users, setUsers] = useState<User[]>([]);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [showAddContact, setShowAddContant] = useState<boolean>(false);
|
||||
const [contactInput, setContactInput] = useState<string>();
|
||||
const { t } = useTranslation('common');
|
||||
@ -35,26 +36,33 @@ export const ContactsPage: React.FC = () => {
|
||||
}, [lastEventId]);
|
||||
|
||||
useEffect(() => {
|
||||
relayPool?.unsubscribeAll();
|
||||
relayPool?.on('event', 'contacts', (relay: Relay, _subId?: string, event?: Event) => {
|
||||
console.log('CONTACTS PAGE EVENT =======>', relay.url, event);
|
||||
if (database && event?.id && event.kind === EventKind.petNames) {
|
||||
insertUserContact(event, database).finally(() => setLastEventId(event?.id ?? ''));
|
||||
relayPool?.subscribe('main-channel', {
|
||||
kinds: [EventKind.meta],
|
||||
authors: event.tags.map((tag) => tagToUser(tag).id),
|
||||
});
|
||||
relayPool?.removeOn('event', 'contacts');
|
||||
}
|
||||
});
|
||||
if (publicKey) {
|
||||
relayPool?.subscribe('main-channel', {
|
||||
kinds: [EventKind.petNames],
|
||||
authors: [publicKey],
|
||||
});
|
||||
}
|
||||
subscribeContacts();
|
||||
}, []);
|
||||
|
||||
const subscribeContacts: () => Promise<void> = async () => {
|
||||
return await new Promise<void>((resolve, _reject) => {
|
||||
relayPool?.unsubscribeAll();
|
||||
relayPool?.on('event', 'contacts', (relay: Relay, _subId?: string, event?: Event) => {
|
||||
console.log('CONTACTS PAGE EVENT =======>', relay.url, event);
|
||||
if (database && event?.id && event.kind === EventKind.petNames) {
|
||||
insertUserContact(event, database).finally(() => setLastEventId(event?.id ?? ''));
|
||||
relayPool?.subscribe('main-channel', {
|
||||
kinds: [EventKind.meta],
|
||||
authors: event.tags.map((tag) => tagToUser(tag).id),
|
||||
});
|
||||
relayPool?.removeOn('event', 'contacts');
|
||||
}
|
||||
});
|
||||
if (publicKey) {
|
||||
relayPool?.subscribe('main-channel', {
|
||||
kinds: [EventKind.petNames],
|
||||
authors: [publicKey],
|
||||
});
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
|
||||
const onPressAddContact: () => void = () => {
|
||||
if (contactInput && relayPool && database && publicKey) {
|
||||
addContact(contactInput, database).then(() => {
|
||||
@ -64,6 +72,12 @@ export const ContactsPage: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const onRefresh = useCallback(() => {
|
||||
setRefreshing(true);
|
||||
relayPool?.unsubscribeAll();
|
||||
subscribeContacts().finally(() => setRefreshing(false));
|
||||
}, []);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
@ -94,7 +108,13 @@ export const ContactsPage: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<Layout style={styles.container} level='3'>
|
||||
<List data={users} renderItem={(item) => <UserCard user={item.item} />} />
|
||||
<ScrollView
|
||||
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
|
||||
>
|
||||
{users.map((user) => (
|
||||
<UserCard user={user} key={user.id} />
|
||||
))}
|
||||
</ScrollView>
|
||||
</Layout>
|
||||
<Modal
|
||||
style={styles.modal}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Card, Layout, List, useTheme } from '@ui-kitten/components';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { Card, Layout, useTheme } from '@ui-kitten/components';
|
||||
import React, { useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { RefreshControl, ScrollView, StyleSheet } from 'react-native';
|
||||
import { AppContext } from '../../Contexts/AppContext';
|
||||
import { getNotes, Note } from '../../Functions/DatabaseFunctions/Notes';
|
||||
import NoteCard from '../NoteCard';
|
||||
@ -20,37 +20,43 @@ export const HomePage: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
const [notes, setNotes] = useState<Note[]>([]);
|
||||
const [totalContacts, setTotalContacts] = useState<number>(-1);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const { t } = useTranslation('common');
|
||||
|
||||
const loadNotes: () => void = () => {
|
||||
if (database && publicKey) {
|
||||
getNotes(database, { contacts: true, includeIds: [publicKey], limit: 30 }).then((notes) => {
|
||||
getNotes(database, { contacts: true, includeIds: [publicKey], limit: 15 }).then((notes) => {
|
||||
setNotes(notes);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const subscribeNotes: () => void = () => {
|
||||
if (database && publicKey && relayPool) {
|
||||
getNotes(database, { limit: 1 }).then((notes) => {
|
||||
getUsers(database, { contacts: true, includeIds: [publicKey] }).then((users) => {
|
||||
setTotalContacts(users.length);
|
||||
let message: RelayFilters = {
|
||||
kinds: [EventKind.textNote, EventKind.recommendServer],
|
||||
authors: users.map((user) => user.id),
|
||||
limit: 20,
|
||||
};
|
||||
|
||||
if (notes.length !== 0) {
|
||||
message = {
|
||||
...message,
|
||||
since: notes[0].created_at,
|
||||
const subscribeNotes: () => Promise<void> = async () => {
|
||||
return await new Promise<void>((resolve, reject) => {
|
||||
if (database && publicKey && relayPool) {
|
||||
getNotes(database, { limit: 1 }).then((notes) => {
|
||||
getUsers(database, { contacts: true, includeIds: [publicKey] }).then((users) => {
|
||||
setTotalContacts(users.length);
|
||||
let message: RelayFilters = {
|
||||
kinds: [EventKind.textNote, EventKind.recommendServer],
|
||||
authors: users.map((user) => user.id),
|
||||
limit: 15,
|
||||
};
|
||||
}
|
||||
relayPool?.subscribe('main-channel', message);
|
||||
|
||||
if (notes.length !== 0) {
|
||||
message = {
|
||||
...message,
|
||||
since: notes[0].created_at,
|
||||
};
|
||||
}
|
||||
relayPool?.subscribe('main-channel', message);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
reject(new Error('Not Ready'));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -66,6 +72,12 @@ export const HomePage: React.FC = () => {
|
||||
subscribeNotes();
|
||||
}, [database, publicKey, relayPool]);
|
||||
|
||||
const onRefresh = useCallback(() => {
|
||||
setRefreshing(true);
|
||||
relayPool?.unsubscribeAll();
|
||||
subscribeNotes().finally(() => setRefreshing(false));
|
||||
}, []);
|
||||
|
||||
const onPress: (note: Note) => void = (note) => {
|
||||
if (note.kind !== EventKind.recommendServer) {
|
||||
const replyEventId = getReplyEventId(note);
|
||||
@ -79,7 +91,7 @@ export const HomePage: React.FC = () => {
|
||||
|
||||
const itemCard: (note: Note) => JSX.Element = (note) => {
|
||||
return (
|
||||
<Card onPress={() => onPress(note)}>
|
||||
<Card onPress={() => onPress(note)} key={note.id ?? ''}>
|
||||
<NoteCard note={note} />
|
||||
</Card>
|
||||
);
|
||||
@ -101,7 +113,12 @@ export const HomePage: React.FC = () => {
|
||||
{notes.length === 0 && totalContacts !== 0 ? (
|
||||
<Loading />
|
||||
) : (
|
||||
<List data={notes} renderItem={(item) => itemCard(item.item)} />
|
||||
<ScrollView
|
||||
horizontal={false}
|
||||
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
|
||||
>
|
||||
{notes.map((note) => itemCard(note))}
|
||||
</ScrollView>
|
||||
)}
|
||||
</Layout>
|
||||
<ActionButton
|
||||
|
@ -2,16 +2,19 @@ import React, { useContext } from 'react';
|
||||
import { BottomNavigation, BottomNavigationTab, useTheme } from '@ui-kitten/components';
|
||||
import { AppContext } from '../../Contexts/AppContext';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext';
|
||||
|
||||
export const NavigationBar: React.FC = () => {
|
||||
const { goToPage, page } = useContext(AppContext);
|
||||
const { publicKey } = useContext(RelayPoolContext);
|
||||
const theme = useTheme();
|
||||
const profilePage = `profile#${publicKey ?? ''}`;
|
||||
|
||||
const pageIndex: string[] = ['home', 'contacts', 'profile'];
|
||||
const pageIndex: string[] = ['home', 'contacts', profilePage];
|
||||
|
||||
const getIndex: () => number = () => {
|
||||
if (page.includes('profile')) {
|
||||
return !page.includes('profile#') ? 2 : 1;
|
||||
return page === profilePage ? 2 : 1;
|
||||
} else if (page.includes('note#')) {
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -1,12 +1,5 @@
|
||||
import {
|
||||
Card,
|
||||
Layout,
|
||||
List,
|
||||
TopNavigation,
|
||||
TopNavigationAction,
|
||||
useTheme,
|
||||
} from '@ui-kitten/components';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { Card, Layout, TopNavigation, TopNavigationAction, useTheme } from '@ui-kitten/components';
|
||||
import React, { useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { AppContext } from '../../Contexts/AppContext';
|
||||
import { getNotes, Note } from '../../Functions/DatabaseFunctions/Notes';
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext';
|
||||
@ -14,7 +7,7 @@ import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
import NoteCard from '../NoteCard';
|
||||
import { EventKind } from '../../lib/nostr/Events';
|
||||
import { RelayFilters } from '../../lib/nostr/Relay';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { RefreshControl, ScrollView, StyleSheet } from 'react-native';
|
||||
import Loading from '../Loading';
|
||||
import ActionButton from 'react-native-action-button';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -25,6 +18,7 @@ export const NotePage: React.FC = () => {
|
||||
const { lastEventId, relayPool } = useContext(RelayPoolContext);
|
||||
const [note, setNote] = useState<Note>();
|
||||
const [replies, setReplies] = useState<Note[]>();
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation('common');
|
||||
const breadcrump = page.split('%');
|
||||
@ -43,33 +37,7 @@ export const NotePage: React.FC = () => {
|
||||
useEffect(reload, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (database) {
|
||||
getNotes(database, { filters: { id: eventId } }).then((events) => {
|
||||
if (events.length > 0) {
|
||||
const event = events[0];
|
||||
setNote(event);
|
||||
if (!replies) {
|
||||
relayPool?.subscribe('main-channel', {
|
||||
kinds: [EventKind.textNote],
|
||||
'#e': [eventId],
|
||||
});
|
||||
}
|
||||
getNotes(database, { filters: { reply_event_id: eventId } }).then((notes) => {
|
||||
const rootReplies = getDirectReplies(event, notes);
|
||||
if (rootReplies.length > 0) {
|
||||
setReplies(rootReplies as Note[]);
|
||||
const message: RelayFilters = {
|
||||
kinds: [EventKind.meta],
|
||||
authors: [...rootReplies.map((note) => note.pubkey), event.pubkey],
|
||||
};
|
||||
relayPool?.subscribe('main-channel', message);
|
||||
} else {
|
||||
setReplies([]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
subscribeNotes();
|
||||
}, [lastEventId, page]);
|
||||
|
||||
const onPressBack: () => void = () => {
|
||||
@ -119,16 +87,16 @@ export const NotePage: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const ItemCard: (note?: Note) => JSX.Element = (note) => {
|
||||
const itemCard: (note?: Note) => JSX.Element = (note) => {
|
||||
if (note?.id === eventId) {
|
||||
return (
|
||||
<Layout style={styles.main} level='2'>
|
||||
<Layout style={styles.main} level='2' key={note.id ?? ''}>
|
||||
<NoteCard note={note} />
|
||||
</Layout>
|
||||
);
|
||||
} else if (note) {
|
||||
return (
|
||||
<Card onPress={() => onPressNote(note)}>
|
||||
<Card onPress={() => onPressNote(note)} key={note.id ?? ''}>
|
||||
<NoteCard note={note} />
|
||||
</Card>
|
||||
);
|
||||
@ -137,6 +105,49 @@ export const NotePage: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const subscribeNotes: () => Promise<void> = async () => {
|
||||
return await new Promise<void>((resolve, reject) => {
|
||||
if (database) {
|
||||
getNotes(database, { filters: { id: eventId } }).then((events) => {
|
||||
if (events.length > 0) {
|
||||
const event = events[0];
|
||||
setNote(event);
|
||||
if (!replies) {
|
||||
relayPool?.subscribe('main-channel', {
|
||||
kinds: [EventKind.textNote],
|
||||
'#e': [eventId],
|
||||
});
|
||||
}
|
||||
getNotes(database, { filters: { reply_event_id: eventId } }).then((notes) => {
|
||||
const rootReplies = getDirectReplies(event, notes);
|
||||
if (rootReplies.length > 0) {
|
||||
setReplies(rootReplies as Note[]);
|
||||
const message: RelayFilters = {
|
||||
kinds: [EventKind.meta],
|
||||
authors: [...rootReplies.map((note) => note.pubkey), event.pubkey],
|
||||
};
|
||||
relayPool?.subscribe('main-channel', message);
|
||||
} else {
|
||||
setReplies([]);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
reject(new Error('Not Ready'));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const onRefresh = useCallback(() => {
|
||||
setRefreshing(true);
|
||||
relayPool?.unsubscribeAll();
|
||||
subscribeNotes().finally(() => setRefreshing(false));
|
||||
}, []);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
main: {
|
||||
paddingBottom: 32,
|
||||
@ -159,7 +170,11 @@ export const NotePage: React.FC = () => {
|
||||
/>
|
||||
<Layout level='4'>
|
||||
{note ? (
|
||||
<List data={[note, ...(replies ?? [])]} renderItem={(item) => ItemCard(item?.item)} />
|
||||
<ScrollView
|
||||
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
|
||||
>
|
||||
{[note, ...(replies ?? [])].map((note) => itemCard(note))}
|
||||
</ScrollView>
|
||||
) : (
|
||||
<Loading style={styles.loading} />
|
||||
)}
|
||||
|
@ -1,15 +1,14 @@
|
||||
import {
|
||||
Card,
|
||||
Layout,
|
||||
List,
|
||||
Spinner,
|
||||
Text,
|
||||
TopNavigation,
|
||||
TopNavigationAction,
|
||||
useTheme,
|
||||
} from '@ui-kitten/components';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { StyleSheet, TouchableOpacity } from 'react-native';
|
||||
import React, { useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { RefreshControl, ScrollView, StyleSheet, TouchableOpacity } from 'react-native';
|
||||
import { AppContext } from '../../Contexts/AppContext';
|
||||
import UserAvatar from 'react-native-user-avatar';
|
||||
import { getNotes, Note } from '../../Functions/DatabaseFunctions/Notes';
|
||||
@ -39,50 +38,19 @@ export const ProfilePage: React.FC = () => {
|
||||
const [notes, setNotes] = useState<Note[]>();
|
||||
const { t } = useTranslation('common');
|
||||
const [user, setUser] = useState<User>();
|
||||
const [contacts, setContactsIds] = useState<string[]>();
|
||||
const [contactsIds, setContactsIds] = useState<string[]>();
|
||||
const [isContact, setIsContact] = useState<boolean>();
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const breadcrump = page.split('%');
|
||||
const userId = breadcrump[breadcrump.length - 1].split('#')[1] ?? publicKey;
|
||||
const username = user?.name === '' ? user?.id : user?.name;
|
||||
|
||||
useEffect(() => {
|
||||
setContactsIds(undefined);
|
||||
setNotes(undefined);
|
||||
setUser(undefined);
|
||||
relayPool?.subscribe('main-channel', {
|
||||
kinds: [EventKind.meta, EventKind.petNames],
|
||||
authors: [userId],
|
||||
});
|
||||
relayPool?.on('event', 'profile', (_relay: Relay, _subId?: string, event?: Event) => {
|
||||
console.log('PROFILE EVENT =======>', event);
|
||||
if (database) {
|
||||
if (event?.id && event.pubkey === userId) {
|
||||
if (event.kind === EventKind.petNames) {
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
getNotes(database, { filters: { pubkey: userId }, limit: 1 }).then((results) => {
|
||||
if (results) {
|
||||
const notesEvent: RelayFilters = {
|
||||
kinds: [EventKind.textNote, EventKind.recommendServer],
|
||||
authors: [userId],
|
||||
limit: 15,
|
||||
};
|
||||
|
||||
if (results.length >= 15) {
|
||||
notesEvent.since = results[0]?.created_at;
|
||||
}
|
||||
|
||||
relayPool?.subscribe('main-channel', notesEvent);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [page, relayPool]);
|
||||
loadProfile();
|
||||
}, [page]);
|
||||
|
||||
useEffect(() => {
|
||||
if (database) {
|
||||
@ -97,11 +65,11 @@ export const ProfilePage: React.FC = () => {
|
||||
setContactsIds(users.map((user) => user.id));
|
||||
});
|
||||
}
|
||||
getNotes(database, { filters: { pubkey: userId } }).then((results) => {
|
||||
getNotes(database, { filters: { pubkey: userId }, limit: 10 }).then((results) => {
|
||||
if (results.length > 0) setNotes(results);
|
||||
});
|
||||
}
|
||||
}, [lastEventId, database]);
|
||||
}, [lastEventId]);
|
||||
|
||||
const removeAuthor: () => void = () => {
|
||||
if (relayPool && database && publicKey) {
|
||||
@ -171,6 +139,60 @@ export const ProfilePage: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const onRefresh = useCallback(() => {
|
||||
setRefreshing(true);
|
||||
relayPool?.unsubscribeAll();
|
||||
loadProfile().finally(() => setRefreshing(false));
|
||||
}, []);
|
||||
|
||||
const subscribeNotes: () => void = () => {
|
||||
if (database) {
|
||||
getNotes(database, { filters: { pubkey: userId }, limit: 10 }).then((results) => {
|
||||
if (results) {
|
||||
const notesEvent: RelayFilters = {
|
||||
kinds: [EventKind.textNote, EventKind.recommendServer],
|
||||
authors: [userId],
|
||||
limit: 10,
|
||||
};
|
||||
|
||||
if (results.length >= 10) {
|
||||
notesEvent.since = results[0]?.created_at;
|
||||
}
|
||||
|
||||
relayPool?.subscribe('main-channel', notesEvent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const loadProfile: () => Promise<void> = async () => {
|
||||
return await new Promise<void>((resolve, reject) => {
|
||||
relayPool?.subscribe('main-channel', {
|
||||
kinds: [EventKind.meta, EventKind.petNames],
|
||||
authors: [userId],
|
||||
});
|
||||
relayPool?.on('event', 'profile', (_relay: Relay, _subId?: string, event?: Event) => {
|
||||
console.log('PROFILE EVENT =======>', event);
|
||||
if (database) {
|
||||
if (event?.id && event.pubkey === userId) {
|
||||
if (event.kind === EventKind.petNames) {
|
||||
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);
|
||||
});
|
||||
}
|
||||
subscribeNotes();
|
||||
}
|
||||
} else {
|
||||
reject(new Error('Not Ready'));
|
||||
}
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
list: {
|
||||
flex: 1,
|
||||
@ -204,9 +226,11 @@ export const ProfilePage: React.FC = () => {
|
||||
},
|
||||
stats: {
|
||||
flex: 1,
|
||||
},
|
||||
statsItem: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginBottom: 5,
|
||||
},
|
||||
description: {
|
||||
marginTop: 16,
|
||||
@ -216,7 +240,7 @@ export const ProfilePage: React.FC = () => {
|
||||
|
||||
const itemCard: (note: Note) => JSX.Element = (note) => {
|
||||
return (
|
||||
<Card onPress={() => onPressNote(note)}>
|
||||
<Card onPress={() => onPressNote(note)} key={note.id ?? ''}>
|
||||
<NoteCard note={note} />
|
||||
</Card>
|
||||
);
|
||||
@ -238,6 +262,44 @@ export const ProfilePage: React.FC = () => {
|
||||
// Clipboard.setString(user?.id ?? '');
|
||||
};
|
||||
|
||||
const isFollowingUser: () => boolean = () => {
|
||||
if (contactsIds !== undefined && publicKey) {
|
||||
return contactsIds?.includes(publicKey);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const stats: () => JSX.Element = () => {
|
||||
if (contactsIds === undefined) {
|
||||
return (
|
||||
<Layout style={styles.stats} level='3'>
|
||||
<Spinner size='tiny' />
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout style={styles.stats} level='3'>
|
||||
<Layout style={styles.statsItem} level='3'>
|
||||
<Icon name='address-book' size={16} color={theme['text-basic-color']} solid />
|
||||
<Text>{` ${contactsIds?.length}`}</Text>
|
||||
</Layout>
|
||||
{publicKey !== userId && (
|
||||
<Layout style={styles.statsItem} level='3'>
|
||||
<Text>
|
||||
<Icon
|
||||
name='people-arrows'
|
||||
size={16}
|
||||
color={theme[isFollowingUser() ? 'text-basic-color' : 'color-primary-disabled']}
|
||||
solid
|
||||
/>
|
||||
</Text>
|
||||
</Layout>
|
||||
)}
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
const profile: JSX.Element = (
|
||||
<Layout style={styles.profile} level='3'>
|
||||
<Layout style={styles.avatar} level='3'>
|
||||
@ -258,10 +320,7 @@ export const ProfilePage: React.FC = () => {
|
||||
<Layout style={styles.description} level='3'>
|
||||
{user && (
|
||||
<>
|
||||
<Layout style={styles.stats} level='3'>
|
||||
<Text>{contacts?.length ?? <Spinner size='tiny' />} </Text>
|
||||
<Icon name='address-book' size={16} color={theme['text-basic-color']} solid />
|
||||
</Layout>
|
||||
{stats()}
|
||||
<Layout style={styles.about} level='3'>
|
||||
<Text numberOfLines={5} ellipsizeMode='tail'>
|
||||
{user?.about}
|
||||
@ -283,7 +342,15 @@ export const ProfilePage: React.FC = () => {
|
||||
/>
|
||||
{profile}
|
||||
<Layout style={styles.list} level='3'>
|
||||
{notes ? <List data={notes} renderItem={(item) => itemCard(item.item)} /> : <Loading />}
|
||||
{notes ? (
|
||||
<ScrollView
|
||||
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
|
||||
>
|
||||
{notes.map((note) => itemCard(note))}
|
||||
</ScrollView>
|
||||
) : (
|
||||
<Loading />
|
||||
)}
|
||||
</Layout>
|
||||
{publicKey === userId && (
|
||||
<ActionButton
|
||||
|
@ -3,6 +3,7 @@ import { initReactI18next } from 'react-i18next';
|
||||
import en from './Locales/en.json';
|
||||
|
||||
i18n.use(initReactI18next).init({
|
||||
compatibilityJSON: 'v3',
|
||||
fallbackLng: 'en',
|
||||
resources: {
|
||||
en,
|
||||
|
Loading…
Reference in New Issue
Block a user