Skip to content
This repository was archived by the owner on Oct 9, 2025. It is now read-only.

Commit e7531ed

Browse files
author
KoalaSat
authored
New UI performance improvements (#140)
2 parents 806d6a5 + b3a4c33 commit e7531ed

27 files changed

Lines changed: 594 additions & 323 deletions

File tree

frontend/Components/NostrosAvatar/index.tsx

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react'
22
import { StyleSheet, View } from 'react-native'
33
import { Avatar as PaperAvatar, useTheme } from 'react-native-paper'
4+
import { validImageUrl } from '../../Functions/NativeFunctions'
45

56
interface NostrosAvatarProps {
67
pubKey: string
@@ -21,18 +22,10 @@ export const NostrosAvatar: React.FC<NostrosAvatarProps> = ({
2122
const displayName = name && name !== '' ? name : pubKey ?? ''
2223
const hasLud06 = lud06 && lud06 !== ''
2324
const lud06IconSize = size / 2.85
24-
const validImage: () => boolean = () => {
25-
if (src) {
26-
const regexp = /^(https?:\/\/.*\.(?:png|jpg|jpeg))$/
27-
return regexp.test(src)
28-
} else {
29-
return false
30-
}
31-
}
3225

3326
return (
3427
<View>
35-
{validImage() ? (
28+
{validImageUrl(src) ? (
3629
<PaperAvatar.Image size={size} source={{ uri: src }} />
3730
) : (
3831
<PaperAvatar.Text size={size} label={displayName.substring(0, 2).toUpperCase()} />

frontend/Components/NoteCard/index.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const NoteCard: React.FC<NoteCardProps> = ({
5151
const [userDownvoted, setUserDownvoted] = useState<boolean>(false)
5252
const [repliesCount, setRepliesCount] = React.useState<number>(0)
5353
const [hide, setHide] = useState<boolean>(isContentWarning(note))
54-
const timestamp = useMemo(() => moment.unix(note.created_at).format('HH:mm L'), [note])
54+
const timestamp = useMemo(() => moment.unix(note.created_at).format('L HH:mm'), [note])
5555
const nPub = useMemo(() => npubEncode(note.pubkey), [note])
5656

5757
useEffect(() => {
@@ -60,8 +60,12 @@ export const NoteCard: React.FC<NoteCardProps> = ({
6060
const total = result.length
6161
let positive = 0
6262
result.forEach((reaction) => {
63-
if (reaction) positive = positive + 1
64-
if (reaction.pubkey === publicKey) setUserUpvoted(reaction.positive)
63+
if (reaction.positive) {
64+
positive = positive + 1
65+
if (reaction.pubkey === publicKey) setUserUpvoted(true)
66+
} else if (reaction.pubkey === publicKey) {
67+
setUserDownvoted(true)
68+
}
6569
})
6670
setPositiveReactions(positive)
6771
setNegativeReactions(total - positive)
@@ -195,8 +199,8 @@ export const NoteCard: React.FC<NoteCardProps> = ({
195199
size={54}
196200
/>
197201
</View>
198-
<View>
199-
<Text>{usernamePubKey(note.name, nPub)}</Text>
202+
<View style={styles.titleUserInfo}>
203+
<Text style={styles.titleUsername}>{usernamePubKey(note.name, nPub)}</Text>
200204
<Text>{timestamp}</Text>
201205
</View>
202206
</View>
@@ -223,7 +227,6 @@ export const NoteCard: React.FC<NoteCardProps> = ({
223227
size={25}
224228
/>
225229
)}
226-
disabled={userDownvoted}
227230
>
228231
{negaiveReactions === undefined || negaiveReactions === 0 ? '-' : negaiveReactions}
229232
</Button>
@@ -241,7 +244,6 @@ export const NoteCard: React.FC<NoteCardProps> = ({
241244
size={25}
242245
/>
243246
)}
244-
disabled={userUpvoted}
245247
>
246248
{positiveReactions === undefined || positiveReactions === 0 ? '-' : positiveReactions}
247249
</Button>
@@ -255,6 +257,13 @@ const styles = StyleSheet.create({
255257
container: {
256258
padding: 16,
257259
},
260+
titleUsername: {
261+
fontWeight: 'bold',
262+
},
263+
titleUserInfo: {
264+
paddingTop: 10,
265+
paddingLeft: 16,
266+
},
258267
title: {
259268
flexDirection: 'row',
260269
justifyContent: 'space-between',

frontend/Components/ProfileCard/index.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { AppContext } from '../../Contexts/AppContext'
77
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
88
import { UserContext } from '../../Contexts/UserContext'
99
import { getUser, updateUserContact, User } from '../../Functions/DatabaseFunctions/Users'
10-
import { populatePets } from '../../Functions/RelayFunctions/Users'
10+
import { populatePets, usernamePubKey } from '../../Functions/RelayFunctions/Users'
1111
import NostrosAvatar from '../NostrosAvatar'
1212
import LnPayment from '../LnPayment'
1313
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
@@ -85,14 +85,14 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({ userPubKey, bottomShee
8585
/>
8686
</View>
8787
<View>
88-
<View style={styles.userName}>
89-
<Text variant='titleMedium'>{user?.name}</Text>
88+
<View style={styles.username}>
89+
<Text variant='titleMedium'>{usernamePubKey(user?.name ?? '', nPub)}</Text>
9090
{/* <MaterialCommunityIcons name="check-decagram-outline" size={16} /> */}
91+
<Text>{user?.nip05}</Text>
9192
</View>
92-
<Text>{user?.nip05}</Text>
9393
</View>
9494
</View>
95-
<View>
95+
<View style={styles.about}>
9696
<Text>
9797
{`${user?.about ? user?.about?.slice(0, 75) : ''}${
9898
user?.about && user?.about?.length > 75 ? ' ...' : ''
@@ -178,6 +178,9 @@ const styles = StyleSheet.create({
178178
margin: 16,
179179
width: '100%',
180180
},
181+
username: {
182+
paddingLeft: 16,
183+
},
181184
contacts: {
182185
flexDirection: 'row',
183186
alignItems: 'center',
@@ -188,6 +191,9 @@ const styles = StyleSheet.create({
188191
alignItems: 'center',
189192
justifyContent: 'space-around',
190193
},
194+
about: {
195+
maxHeight: 50,
196+
},
191197
userName: {
192198
flexDirection: 'row',
193199
alignItems: 'center',

frontend/Components/TextContent/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import moment from 'moment'
99
import { Card, Text, useTheme } from 'react-native-paper'
1010
import { getLinkPreview } from 'link-preview-js'
1111
import { push } from '../../lib/Navigation'
12+
import { validImageUrl } from '../../Functions/NativeFunctions'
1213

1314
interface TextContentProps {
1415
event?: Event
@@ -102,7 +103,7 @@ export const TextContent: React.FC<TextContentProps> = ({ event, content, previe
102103

103104
return (
104105
<Card style={styles.previewCard} onPress={() => handleUrlPress(linkPreview.url)}>
105-
<Card.Cover source={{ uri: coverUrl }} />
106+
{validImageUrl(coverUrl) && <Card.Cover source={{ uri: coverUrl }} resizeMode='contain' />}
106107
<Card.Content style={styles.previewContent}>
107108
<Text variant='titleSmall'>{linkPreview.title || linkPreview.url}</Text>
108109
{linkPreview.description && <Text variant='bodySmall'>{linkPreview.description}</Text>}

frontend/Functions/DatabaseFunctions/DirectMessages/index.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const updateConversationRead: (
1717
db: QuickSQLiteConnection,
1818
) => Promise<QueryResult | null> = async (conversationId, db) => {
1919
const userQuery = `UPDATE nostros_direct_messages SET read = ? WHERE conversation_id = ?`
20+
console.log(userQuery)
2021
return db.execute(userQuery, [1, conversationId])
2122
}
2223

@@ -44,23 +45,28 @@ export const getGroupedDirectMessages: (
4445

4546
export const getDirectMessages: (
4647
db: QuickSQLiteConnection,
48+
conversationId: string,
49+
publicKey: string,
50+
otherPubKey: string,
4751
options: {
48-
conversationId?: string
4952
order?: 'DESC' | 'ASC'
5053
},
51-
) => Promise<DirectMessage[]> = async (db, { conversationId, order = 'DESC' }) => {
52-
let notesQuery = `
54+
) => Promise<DirectMessage[]> = async (
55+
db,
56+
conversationId,
57+
publicKey,
58+
otherPubKey,
59+
{ order = 'DESC' },
60+
) => {
61+
const notesQuery = `
5362
SELECT
5463
*
5564
FROM
5665
nostros_direct_messages
66+
WHERE conversation_id = "${conversationId}"
67+
ORDER BY created_at ${order}
5768
`
58-
59-
if (conversationId) {
60-
notesQuery += `WHERE conversation_id = "${conversationId}" `
61-
}
62-
63-
notesQuery += `ORDER BY created_at ${order}`
69+
// WHERE conversation_id = "${conversationId}"
6470

6571
const resultSet = await db.execute(notesQuery)
6672
const items: object[] = getItems(resultSet)

frontend/Functions/DatabaseFunctions/Notes/index.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export interface Note extends Event {
77
picture: string
88
lnurl: string
99
reply_event_id: string
10+
user_created_at: number
1011
}
1112

1213
const databaseToEntity: (object: any) => Note = (object) => {
@@ -21,7 +22,7 @@ export const getMainNotes: (
2122
) => Promise<Note[]> = async (db, pubKey, limit) => {
2223
const notesQuery = `
2324
SELECT
24-
nostros_notes.*, nostros_users.lnurl, nostros_users.name, nostros_users.picture, nostros_users.contact FROM nostros_notes
25+
nostros_notes.*, nostros_users.lnurl, nostros_users.name, nostros_users.picture, nostros_users.contact, nostros_users.created_at as user_created_at FROM nostros_notes
2526
LEFT JOIN
2627
nostros_users ON nostros_users.id = nostros_notes.pubkey
2728
WHERE (nostros_users.contact = 1 OR nostros_notes.pubkey = '${pubKey}')
@@ -44,7 +45,7 @@ export const getMentionNotes: (
4445
) => Promise<Note[]> = async (db, pubKey, limit) => {
4546
const notesQuery = `
4647
SELECT
47-
nostros_notes.*, nostros_users.lnurl, nostros_users.name, nostros_users.picture, nostros_users.contact FROM nostros_notes
48+
nostros_notes.*, nostros_users.lnurl, nostros_users.name, nostros_users.picture, nostros_users.contact, nostros_users.created_at as user_created_at FROM nostros_notes
4849
LEFT JOIN
4950
nostros_users ON nostros_users.id = nostros_notes.pubkey
5051
WHERE (nostros_notes.reply_event_id IN (
@@ -78,6 +79,30 @@ export const getRepliesCount: (
7879
return item['COUNT(*)'] ?? 0
7980
}
8081

82+
export const getLastReply: (
83+
db: QuickSQLiteConnection,
84+
filters: {
85+
eventIds: string[]
86+
},
87+
) => Promise<Note> = async (db, { eventIds }) => {
88+
const eventIdsQuery = eventIds.join('", "')
89+
const replyQuery = `
90+
SELECT
91+
*
92+
FROM
93+
nostros_notes
94+
WHERE reply_event_id IN ("${eventIdsQuery}")
95+
ORDER BY created_at DESC
96+
LIMIT 1
97+
`
98+
99+
const resultSet = await db.execute(replyQuery)
100+
const item: object = getItems(resultSet)[0]
101+
const reaction: Note = databaseToEntity(item)
102+
103+
return reaction
104+
}
105+
81106
export const getNotes: (
82107
db: QuickSQLiteConnection,
83108
options: {
@@ -89,7 +114,7 @@ export const getNotes: (
89114
) => Promise<Note[]> = async (db, { filters = {}, limit, contacts, includeIds }) => {
90115
let notesQuery = `
91116
SELECT
92-
nostros_notes.*, nostros_users.lnurl, nostros_users.name, nostros_users.picture, nostros_users.contact FROM nostros_notes
117+
nostros_notes.*, nostros_users.lnurl, nostros_users.name, nostros_users.picture, nostros_users.contact, nostros_users.created_at as user_created_at FROM nostros_notes
93118
LEFT JOIN
94119
nostros_users ON nostros_users.id = nostros_notes.pubkey
95120
`

frontend/Functions/DatabaseFunctions/Reactions/index.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,28 @@ export const getReactions: (
3232

3333
return reactions
3434
}
35+
36+
export const getLastReaction: (
37+
db: QuickSQLiteConnection,
38+
filters: {
39+
eventIds: string[]
40+
},
41+
) => Promise<Reaction> = async (db, { eventIds }) => {
42+
const eventIdsQuery = eventIds.join('", "')
43+
44+
const reactionsQuery = `
45+
SELECT
46+
*
47+
FROM
48+
nostros_reactions
49+
WHERE reacted_event_id IN ("${eventIdsQuery}")
50+
ORDER BY created_at DESC
51+
LIMIT 1
52+
`
53+
54+
const resultSet = await db.execute(reactionsQuery)
55+
const item: object = getItems(resultSet)[0]
56+
const reaction: Reaction = databaseToEntity(item)
57+
58+
return reaction
59+
}

frontend/Functions/DatabaseFunctions/Users/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export interface User {
1111
follower?: boolean
1212
lnurl?: string
1313
nip05?: string
14+
created_at?: number
1415
}
1516

1617
const databaseToEntity: (object: object) => User = (object) => {
@@ -73,7 +74,8 @@ export const getFollowersCount: (db: QuickSQLiteConnection) => Promise<number> =
7374
export const getFollowersAndFollowing: (db: QuickSQLiteConnection) => Promise<User[]> = async (
7475
db,
7576
) => {
76-
const userQuery = 'SELECT * FROM nostros_users WHERE follower = 1 OR contact = 1'
77+
const userQuery =
78+
'SELECT * FROM nostros_users WHERE follower = 1 OR contact = 1 ORDER BY created_at DESC'
7779
const resultSet = db.execute(userQuery)
7880
if (resultSet.rows && resultSet.rows.length > 0) {
7981
const items: object[] = getItems(resultSet)

frontend/Functions/NativeFunctions/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,12 @@ export const pickRandomItems = <T extends unknown>(arr: T[], n: number): T[] =>
2424
const shuffled = Array.from(arr).sort(() => 0.5 - Math.random())
2525
return shuffled.slice(0, n)
2626
}
27+
28+
export const validImageUrl: (url: string | undefined) => boolean = (url) => {
29+
if (url) {
30+
const regexp = /^(https?:\/\/.*\.(?:png|jpg|jpeg))$/
31+
return regexp.test(url)
32+
} else {
33+
return false
34+
}
35+
}

frontend/Functions/RelayFunctions/DirectMessages/index.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { DirectMessage } from '../../DatabaseFunctions/DirectMessages'
2-
import { v4 as uuidv4 } from 'uuid'
32

43
export const getOtherPubKey: (message: DirectMessage, ownPubKey: string) => string = (
54
message,
@@ -14,17 +13,6 @@ export const getOtherPubKey: (message: DirectMessage, ownPubKey: string) => stri
1413
return otherPubKey
1514
}
1615

17-
export const generateConversationId: (pubKey: string, otherPubKey: string) => string = (
18-
pubKey,
19-
otherPubKey,
20-
) => {
21-
const pubKeys = [pubKey, otherPubKey].sort().join('')
22-
23-
return uuidv4({
24-
random: convertStringToByteArray(pubKeys),
25-
})
26-
}
27-
2816
export const convertStringToByteArray: (string: string) => number[] = (string) => {
2917
const bytes = []
3018
for (let i = 0; i < string.length; ++i) {

0 commit comments

Comments
 (0)