mirror of
https://github.com/KoalaSat/nostros.git
synced 2024-09-29 14:40:43 +00:00
Reactions (#85)
This commit is contained in:
commit
57d26ca337
@ -47,6 +47,8 @@ public class Event {
|
|||||||
}
|
}
|
||||||
} else if (kind.equals("4")) {
|
} else if (kind.equals("4")) {
|
||||||
saveDirectMessage(database);
|
saveDirectMessage(database);
|
||||||
|
} else if (kind.equals("7")) {
|
||||||
|
saveReaction(database);
|
||||||
}
|
}
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -99,11 +101,11 @@ public class Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Boolean getUserMentioned(String userPubKey) {
|
protected Boolean getUserMentioned(String userPubKey) {
|
||||||
JSONArray eTags = filterTags("p");
|
JSONArray pTags = filterTags("p");
|
||||||
Boolean userMentioned = false;
|
Boolean userMentioned = false;
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < eTags.length(); ++i) {
|
for (int i = 0; i < pTags.length(); ++i) {
|
||||||
JSONArray tag = eTags.getJSONArray(i);
|
JSONArray tag = pTags.getJSONArray(i);
|
||||||
if (tag.getString(1).equals(userPubKey)) {
|
if (tag.getString(1).equals(userPubKey)) {
|
||||||
userMentioned = true;
|
userMentioned = true;
|
||||||
}
|
}
|
||||||
@ -115,26 +117,6 @@ public class Event {
|
|||||||
return userMentioned;
|
return userMentioned;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String saveFollower(String pubKey) {
|
|
||||||
JSONArray eTags = filterTags("p");
|
|
||||||
String mainEventId = null;
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < eTags.length(); ++i) {
|
|
||||||
JSONArray tag = eTags.getJSONArray(i);
|
|
||||||
if (tag.getString(3).equals("reply")) {
|
|
||||||
mainEventId = tag.getString(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mainEventId == null && eTags.length() > 0) {
|
|
||||||
mainEventId = eTags.getJSONArray(eTags.length() - 1).getString(1);
|
|
||||||
}
|
|
||||||
} catch (JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return mainEventId;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected JSONArray filterTags(String kind) {
|
protected JSONArray filterTags(String kind) {
|
||||||
JSONArray filtered = new JSONArray();
|
JSONArray filtered = new JSONArray();
|
||||||
|
|
||||||
@ -190,13 +172,29 @@ public class Event {
|
|||||||
@SuppressLint("Recycle") Cursor cursor = database.rawQuery(query, new String[] {id});
|
@SuppressLint("Recycle") Cursor cursor = database.rawQuery(query, new String[] {id});
|
||||||
if (cursor.getCount() == 0) {
|
if (cursor.getCount() == 0) {
|
||||||
database.insert("nostros_direct_messages", null, values);
|
database.insert("nostros_direct_messages", null, values);
|
||||||
} else {
|
}
|
||||||
String whereClause = "id = ?";
|
}
|
||||||
String[] whereArgs = new String[] {
|
|
||||||
id
|
protected void saveReaction(SQLiteDatabase database) throws JSONException {
|
||||||
};
|
JSONArray pTags = filterTags("p");
|
||||||
values.put("read", cursor.getInt(0));
|
JSONArray eTags = filterTags("e");
|
||||||
database.update("nostros_direct_messages", values, whereClause, whereArgs);
|
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put("id", id);
|
||||||
|
values.put("content", content.replace("'", "''"));
|
||||||
|
values.put("created_at", created_at);
|
||||||
|
values.put("kind", kind);
|
||||||
|
values.put("pubkey", pubkey);
|
||||||
|
values.put("sig", sig);
|
||||||
|
values.put("tags", tags.toString());
|
||||||
|
values.put("positive", !content.equals("-"));
|
||||||
|
values.put("reacted_event_id", eTags.getJSONArray(eTags.length() - 1).getString(1));
|
||||||
|
values.put("reacted_user_id", pTags.getJSONArray(pTags.length() - 1).getString(1));
|
||||||
|
|
||||||
|
String query = "SELECT id FROM nostros_reactions WHERE id = ?";
|
||||||
|
@SuppressLint("Recycle") Cursor cursor = database.rawQuery(query, new String[] {id});
|
||||||
|
if (cursor.getCount() == 0) {
|
||||||
|
database.insert("nostros_reactions", null, values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,18 @@ public class DatabaseModule {
|
|||||||
try {
|
try {
|
||||||
database.execSQL("ALTER TABLE nostros_users ADD COLUMN created_at INT DEFAULT 0;");
|
database.execSQL("ALTER TABLE nostros_users ADD COLUMN created_at INT DEFAULT 0;");
|
||||||
} catch (SQLException e) { }
|
} catch (SQLException e) { }
|
||||||
|
database.execSQL("CREATE TABLE IF NOT EXISTS nostros_reactions(\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" +
|
||||||
|
" sig TEXT NOT NULL,\n" +
|
||||||
|
" tags TEXT NOT NULL,\n" +
|
||||||
|
" positive BOOLEAN DEFAULT TRUE,\n" +
|
||||||
|
" reacted_event_id TEXT,\n" +
|
||||||
|
" reacted_user_id TEXT\n" +
|
||||||
|
" );");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveEvent(JSONObject data, String userPubKey) throws JSONException {
|
public void saveEvent(JSONObject data, String userPubKey) throws JSONException {
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
getReplyEventId,
|
getReplyEventId,
|
||||||
isContentWarning,
|
isContentWarning,
|
||||||
} from '../../Functions/RelayFunctions/Events'
|
} from '../../Functions/RelayFunctions/Events'
|
||||||
|
import { Event } from '../../../lib/nostr/Events'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { populateRelay } from '../../Functions/RelayFunctions'
|
import { populateRelay } from '../../Functions/RelayFunctions'
|
||||||
import Avatar from '../Avatar'
|
import Avatar from '../Avatar'
|
||||||
@ -20,6 +21,7 @@ import { searchRelays } from '../../Functions/DatabaseFunctions/Relays'
|
|||||||
import { RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
import { RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||||
import TextContent from '../../Components/TextContent'
|
import TextContent from '../../Components/TextContent'
|
||||||
import { formatPubKey } from '../../Functions/RelayFunctions/Users'
|
import { formatPubKey } from '../../Functions/RelayFunctions/Users'
|
||||||
|
import { getReactionsCount, getUserReaction } from '../../Functions/DatabaseFunctions/Reactions'
|
||||||
|
|
||||||
interface NoteCardProps {
|
interface NoteCardProps {
|
||||||
note: Note
|
note: Note
|
||||||
@ -33,12 +35,36 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
|||||||
onlyContactsReplies = false,
|
onlyContactsReplies = false,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const { relayPool, publicKey } = useContext(RelayPoolContext)
|
const { relayPool, publicKey, lastEventId } = useContext(RelayPoolContext)
|
||||||
const { database, goToPage } = useContext(AppContext)
|
const { database, goToPage } = useContext(AppContext)
|
||||||
const [relayAdded, setRelayAdded] = useState<boolean>(false)
|
const [relayAdded, setRelayAdded] = useState<boolean>(false)
|
||||||
const [replies, setReplies] = useState<Note[]>([])
|
const [replies, setReplies] = useState<Note[]>([])
|
||||||
|
const [positiveReactions, setPositiveReactions] = useState<number>(0)
|
||||||
|
const [negaiveReactions, setNegativeReactions] = useState<number>(0)
|
||||||
|
const [userUpvoted, setUserUpvoted] = useState<boolean>(false)
|
||||||
|
const [userDownvoted, setUserDownvoted] = useState<boolean>(false)
|
||||||
const [hide, setHide] = useState<boolean>(isContentWarning(note))
|
const [hide, setHide] = useState<boolean>(isContentWarning(note))
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (database && publicKey && note.id) {
|
||||||
|
getReactionsCount(database, { positive: true, eventId: note.id }).then((result) => {
|
||||||
|
setPositiveReactions(result ?? 0)
|
||||||
|
})
|
||||||
|
getReactionsCount(database, { positive: false, eventId: note.id }).then((result) => {
|
||||||
|
setNegativeReactions(result ?? 0)
|
||||||
|
})
|
||||||
|
getUserReaction(database, publicKey, { eventId: note.id }).then((results) => {
|
||||||
|
results.forEach((reaction) => {
|
||||||
|
if (reaction.positive) {
|
||||||
|
setUserUpvoted(true)
|
||||||
|
} else {
|
||||||
|
setUserDownvoted(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [lastEventId])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (database && note) {
|
if (database && note) {
|
||||||
searchRelays(note.content, database).then((result) => {
|
searchRelays(note.content, database).then((result) => {
|
||||||
@ -63,6 +89,17 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
|||||||
}
|
}
|
||||||
}, [database])
|
}, [database])
|
||||||
|
|
||||||
|
const publishReaction: (positive: boolean) => void = (positive) => {
|
||||||
|
const event: Event = {
|
||||||
|
content: positive ? '+' : '-',
|
||||||
|
created_at: moment().unix(),
|
||||||
|
kind: EventKind.reaction,
|
||||||
|
pubkey: publicKey,
|
||||||
|
tags: [...note.tags, ['e', note.id], ['p', note.pubkey]],
|
||||||
|
}
|
||||||
|
relayPool?.sendEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
const textNote: (note: Note) => JSX.Element = (note) => {
|
const textNote: (note: Note) => JSX.Element = (note) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -99,6 +136,54 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
|||||||
</Layout>
|
</Layout>
|
||||||
<Layout style={styles.footer}>
|
<Layout style={styles.footer}>
|
||||||
<Text appearance='hint'>{moment.unix(note.created_at).format('HH:mm DD-MM-YY')}</Text>
|
<Text appearance='hint'>{moment.unix(note.created_at).format('HH:mm DD-MM-YY')}</Text>
|
||||||
|
<Layout style={styles.reactions}>
|
||||||
|
<Button
|
||||||
|
appearance='ghost'
|
||||||
|
status={userUpvoted ? 'success' : 'primary'}
|
||||||
|
onPress={() => {
|
||||||
|
if (!userUpvoted) {
|
||||||
|
setUserUpvoted(true)
|
||||||
|
setPositiveReactions((prev) => prev + 1)
|
||||||
|
publishReaction(true)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
accessoryLeft={
|
||||||
|
<Icon
|
||||||
|
name='arrow-up'
|
||||||
|
size={16}
|
||||||
|
color={userUpvoted ? theme['color-success-500'] : theme['color-primary-500']}
|
||||||
|
solid
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
size='small'
|
||||||
|
>
|
||||||
|
{positiveReactions === undefined || positiveReactions === 0
|
||||||
|
? '-'
|
||||||
|
: positiveReactions}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
appearance='ghost'
|
||||||
|
status={userDownvoted ? 'danger' : 'primary'}
|
||||||
|
onPress={() => {
|
||||||
|
if (!userDownvoted) {
|
||||||
|
setUserDownvoted(true)
|
||||||
|
setNegativeReactions((prev) => prev + 1)
|
||||||
|
publishReaction(false)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
accessoryLeft={
|
||||||
|
<Icon
|
||||||
|
name='arrow-down'
|
||||||
|
size={16}
|
||||||
|
color={userDownvoted ? theme['color-danger-500'] : theme['color-primary-500']}
|
||||||
|
solid
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
size='small'
|
||||||
|
>
|
||||||
|
{negaiveReactions === undefined || negaiveReactions === 0 ? '-' : negaiveReactions}
|
||||||
|
</Button>
|
||||||
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
</>
|
</>
|
||||||
@ -192,6 +277,14 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
|||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
marginTop: 10,
|
||||||
|
},
|
||||||
|
reactions: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
flexDirection: 'row',
|
||||||
},
|
},
|
||||||
tags: {
|
tags: {
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
|
@ -112,7 +112,12 @@ export const TextContent: React.FC<TextContentProps> = ({ event, content, previe
|
|||||||
{text}
|
{text}
|
||||||
</ParsedText>
|
</ParsedText>
|
||||||
{preview && containsUrl() && (
|
{preview && containsUrl() && (
|
||||||
<LinkPreview text={text} renderText={() => ''} textContainerStyle={{ height: 0 }} />
|
<LinkPreview
|
||||||
|
text={text}
|
||||||
|
renderText={() => ''}
|
||||||
|
textContainerStyle={{ height: 0 }}
|
||||||
|
enableAnimation={true}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
67
frontend/Functions/DatabaseFunctions/Reactions/index.ts
Normal file
67
frontend/Functions/DatabaseFunctions/Reactions/index.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||||
|
import { getItems } from '..'
|
||||||
|
import { Event } from '../../../lib/nostr/Events'
|
||||||
|
|
||||||
|
export interface Reaction extends Event {
|
||||||
|
positive: boolean
|
||||||
|
reacted_event_id: string
|
||||||
|
reacted_user_id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const databaseToEntity: (object: object) => Reaction = (object) => {
|
||||||
|
return object as Reaction
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getReactionsCount: (
|
||||||
|
db: QuickSQLiteConnection,
|
||||||
|
filters: {
|
||||||
|
eventId?: string
|
||||||
|
pubKey?: string
|
||||||
|
positive: boolean
|
||||||
|
},
|
||||||
|
) => Promise<number> = async (db, { eventId, pubKey, positive }) => {
|
||||||
|
let notesQuery = `
|
||||||
|
SELECT
|
||||||
|
COUNT(*)
|
||||||
|
FROM
|
||||||
|
nostros_reactions
|
||||||
|
WHERE positive = ${positive ? '1' : '0'}
|
||||||
|
`
|
||||||
|
|
||||||
|
if (eventId) {
|
||||||
|
notesQuery += `AND reacted_event_id = "${eventId}" `
|
||||||
|
} else if (pubKey) {
|
||||||
|
notesQuery += `AND reacted_user_id = "${pubKey}" `
|
||||||
|
}
|
||||||
|
|
||||||
|
const resultSet = await db.execute(notesQuery)
|
||||||
|
const item: { 'COUNT(*)': number } = resultSet?.rows?.item(0)
|
||||||
|
|
||||||
|
return item['COUNT(*)']
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getUserReaction: (
|
||||||
|
db: QuickSQLiteConnection,
|
||||||
|
pubKey: string,
|
||||||
|
filters: {
|
||||||
|
eventId?: string
|
||||||
|
},
|
||||||
|
) => Promise<Reaction[]> = async (db, pubKey, { eventId }) => {
|
||||||
|
let notesQuery = `
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
nostros_reactions
|
||||||
|
WHERE pubkey = '${pubKey}'
|
||||||
|
`
|
||||||
|
|
||||||
|
if (eventId) {
|
||||||
|
notesQuery += `AND reacted_event_id = "${eventId}" `
|
||||||
|
}
|
||||||
|
|
||||||
|
const resultSet = await db.execute(notesQuery)
|
||||||
|
const items: object[] = getItems(resultSet)
|
||||||
|
const reactions: Reaction[] = items.map((object) => databaseToEntity(object))
|
||||||
|
|
||||||
|
return reactions
|
||||||
|
}
|
@ -22,6 +22,8 @@ export const isContentWarning: (event: Event) => boolean = (event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const isDirectReply: (mainEvent: Event, reply: Event) => boolean = (mainEvent, reply) => {
|
export const isDirectReply: (mainEvent: Event, reply: Event) => boolean = (mainEvent, reply) => {
|
||||||
|
if (mainEvent.id === reply.id) return false
|
||||||
|
|
||||||
const taggedMainEventsIds: string[] = getTaggedEventIds(mainEvent)
|
const taggedMainEventsIds: string[] = getTaggedEventIds(mainEvent)
|
||||||
const taggedReplyEventsIds: string[] = getTaggedEventIds(reply)
|
const taggedReplyEventsIds: string[] = getTaggedEventIds(reply)
|
||||||
const difference = taggedReplyEventsIds.filter((item) => !taggedMainEventsIds.includes(item))
|
const difference = taggedReplyEventsIds.filter((item) => !taggedMainEventsIds.includes(item))
|
||||||
|
@ -49,7 +49,7 @@ export const HomePage: React.FC = () => {
|
|||||||
authors: [...users.map((user) => user.id), publicKey],
|
authors: [...users.map((user) => user.id), publicKey],
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastNote && lastNotes.length > 0 && !past) {
|
if (lastNote && lastNotes.length >= pageSize && !past) {
|
||||||
message.since = lastNote.created_at
|
message.since = lastNote.created_at
|
||||||
} else {
|
} else {
|
||||||
message.limit = pageSize + initialPageSize
|
message.limit = pageSize + initialPageSize
|
||||||
@ -67,6 +67,10 @@ export const HomePage: React.FC = () => {
|
|||||||
kinds: [EventKind.meta],
|
kinds: [EventKind.meta],
|
||||||
authors: notes.map((note) => note.pubkey),
|
authors: notes.map((note) => note.pubkey),
|
||||||
})
|
})
|
||||||
|
relayPool?.subscribe('main-channel', {
|
||||||
|
kinds: [EventKind.reaction],
|
||||||
|
'#e': notes.map((note) => note.id ?? ''),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,9 +162,11 @@ export const HomePage: React.FC = () => {
|
|||||||
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
|
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
|
||||||
>
|
>
|
||||||
{notes.map((note) => itemCard(note))}
|
{notes.map((note) => itemCard(note))}
|
||||||
<Layout style={styles.spinner}>
|
{notes.length >= 10 && (
|
||||||
<Spinner size='small' />
|
<Layout style={styles.spinner}>
|
||||||
</Layout>
|
<Spinner size='small' />
|
||||||
|
</Layout>
|
||||||
|
)}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
) : (
|
) : (
|
||||||
<Layout style={styles.empty} level='3'>
|
<Layout style={styles.empty} level='3'>
|
||||||
|
@ -42,6 +42,10 @@ export const MentionsPage: React.FC = () => {
|
|||||||
if (database && publicKey) {
|
if (database && publicKey) {
|
||||||
getMentionNotes(database, publicKey, pageSize).then((notes) => {
|
getMentionNotes(database, publicKey, pageSize).then((notes) => {
|
||||||
setNotes(notes)
|
setNotes(notes)
|
||||||
|
relayPool?.subscribe('main-channel', {
|
||||||
|
kinds: [EventKind.reaction],
|
||||||
|
'#e': notes.map((note) => note.id ?? ''),
|
||||||
|
})
|
||||||
const missingDataNotes = notes
|
const missingDataNotes = notes
|
||||||
.filter((note) => !note.picture || note.picture === '')
|
.filter((note) => !note.picture || note.picture === '')
|
||||||
.map((note) => note.pubkey)
|
.map((note) => note.pubkey)
|
||||||
@ -124,9 +128,11 @@ export const MentionsPage: React.FC = () => {
|
|||||||
{notes && notes.length > 0 ? (
|
{notes && notes.length > 0 ? (
|
||||||
<ScrollView onScroll={onScroll} horizontal={false}>
|
<ScrollView onScroll={onScroll} horizontal={false}>
|
||||||
{notes.map((note) => itemCard(note))}
|
{notes.map((note) => itemCard(note))}
|
||||||
<Layout style={styles.spinner}>
|
{notes.length >= 10 && (
|
||||||
<Spinner size='small' />
|
<Layout style={styles.spinner}>
|
||||||
</Layout>
|
<Spinner size='small' />
|
||||||
|
</Layout>
|
||||||
|
)}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
) : (
|
) : (
|
||||||
<Layout style={styles.empty} level='3'>
|
<Layout style={styles.empty} level='3'>
|
||||||
|
@ -76,17 +76,10 @@ export const NotePage: React.FC = () => {
|
|||||||
kinds: [EventKind.textNote],
|
kinds: [EventKind.textNote],
|
||||||
ids: [eventId],
|
ids: [eventId],
|
||||||
})
|
})
|
||||||
const notes = await getNotes(database, { filters: { reply_event_id: eventId } })
|
relayPool?.subscribe('main-channel', {
|
||||||
const eventMessages: RelayFilters = {
|
kinds: [EventKind.reaction, EventKind.textNote],
|
||||||
kinds: [EventKind.textNote],
|
|
||||||
'#e': [eventId],
|
'#e': [eventId],
|
||||||
}
|
})
|
||||||
if (past) {
|
|
||||||
eventMessages.until = notes[notes.length - 1]?.created_at
|
|
||||||
} else {
|
|
||||||
eventMessages.since = notes[0]?.created_at
|
|
||||||
}
|
|
||||||
relayPool?.subscribe('main-channel', eventMessages)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,10 @@ export const ProfilePage: React.FC = () => {
|
|||||||
getNotes(database, { filters: { pubkey: userId }, limit: pageSize }).then((results) => {
|
getNotes(database, { filters: { pubkey: userId }, limit: pageSize }).then((results) => {
|
||||||
setNotes(results)
|
setNotes(results)
|
||||||
setRefreshing(false)
|
setRefreshing(false)
|
||||||
|
relayPool?.subscribe('main-channel', {
|
||||||
|
kinds: [EventKind.reaction],
|
||||||
|
'#e': results.map((note) => note.id ?? ''),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,7 +83,6 @@ export const ProfilePage: React.FC = () => {
|
|||||||
authors: [userId],
|
authors: [userId],
|
||||||
limit: pageSize,
|
limit: pageSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
relayPool?.subscribe('main-channel', message)
|
relayPool?.subscribe('main-channel', message)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,9 +334,11 @@ export const ProfilePage: React.FC = () => {
|
|||||||
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
|
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
|
||||||
>
|
>
|
||||||
{notes.map((note) => itemCard(note))}
|
{notes.map((note) => itemCard(note))}
|
||||||
<Layout style={styles.spinner}>
|
{notes.length >= 10 && (
|
||||||
<Spinner size='small' />
|
<Layout style={styles.spinner}>
|
||||||
</Layout>
|
<Spinner size='small' />
|
||||||
|
</Layout>
|
||||||
|
)}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
) : (
|
) : (
|
||||||
<Loading />
|
<Loading />
|
||||||
|
@ -16,6 +16,7 @@ export enum EventKind {
|
|||||||
recommendServer = 2,
|
recommendServer = 2,
|
||||||
petNames = 3,
|
petNames = 3,
|
||||||
directMessage = 4,
|
directMessage = 4,
|
||||||
|
reaction = 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const serializeEvent: (event: Event) => string = (event) => {
|
export const serializeEvent: (event: Event) => string = (event) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user