Skip to content

Commit

Permalink
Fix small bugs (#384)
Browse files Browse the repository at this point in the history
* fix contacts issue on relogin

* fix collision error in channels screen

* update channel screen

* fix flickering in flashlist

* fix ux

* consistent default image

* refetch profile when focus

* clear contacts cache when user logout

* clear joined channels cache when logout

* update channel load

* update invite screen

* update create channel screen

* fix

* add fetch invites

* update

* update
  • Loading branch information
reyamir authored Jul 19, 2023
1 parent 7fabb34 commit 0f7d78a
Show file tree
Hide file tree
Showing 22 changed files with 491 additions and 444 deletions.
2 changes: 1 addition & 1 deletion app/components/ChannelItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const ChannelItem = observer(function ChannelItem({
return (
<Pressable onPress={() => navigate("Chat", { id: channel.id })} style={styles.$messageItem}>
<Image
source={{ uri: channel.picture || "https://void.cat/d/KmypFh2fBdYCEvyJrPiN89.webp" }}
source={{ uri: channel.picture || "https://void.cat/d/HxXbwgU9ChcQohiVxSybCs.jpg" }}
style={styles.$messageAvatar}
/>
<View style={styles.$messageContent}>
Expand Down
2 changes: 1 addition & 1 deletion app/components/ChannelManagerItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const ChannelManagerItem = observer(function ChannelItem({
return (
<Pressable onPress={() => navigate("Chat", { id: channel.id })} style={$messageItem}>
<AutoImage
source={{ uri: channel?.picture || "https://void.cat/d/KmypFh2fBdYCEvyJrPiN89.webp" }}
source={{ uri: channel?.picture || "https://void.cat/d/HxXbwgU9ChcQohiVxSybCs.jpg" }}
style={$messageAvatar}
/>
<View style={$messageContent}>
Expand Down
4 changes: 2 additions & 2 deletions app/components/ContactItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ export function ContactItem({ pubkey, fallback }: { pubkey: string; fallback?: s
<View style={$item}>
<Image
source={{
uri: profile?.picture || "https://void.cat/d/KmypFh2fBdYCEvyJrPiN89.webp",
uri: profile?.picture || "https://void.cat/d/HxXbwgU9ChcQohiVxSybCs.jpg",
}}
style={$itemAvatar}
/>
<View>
<Text
text={profile?.display_name || profile?.username || profile?.name || "No name"}
text={profile?.username || profile?.name || profile?.display_name || "No name"}
preset="bold"
numberOfLines={1}
style={$itemName}
Expand Down
2 changes: 1 addition & 1 deletion app/components/DirectMessageItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const DirectMessageItem = memo(function DirectMessageItem({ dm }: { dm: B
style={styles.$messageItem}
>
<Image
source={{ uri: profile?.picture || "https://void.cat/d/KmypFh2fBdYCEvyJrPiN89.webp" }}
source={{ uri: profile?.picture || "https://void.cat/d/HxXbwgU9ChcQohiVxSybCs.jpg" }}
style={styles.$messageAvatar}
/>
<View style={styles.$messageContent}>
Expand Down
6 changes: 3 additions & 3 deletions app/models/Channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { withSetPropAction } from "./helpers/withSetPropAction"
import { MessageModel } from "./Message"

const nHoursAgo = (hrs: number): number => Math.floor((Date.now() - hrs * 60 * 60 * 1000) / 1000)
// const nHoursAgo = (hrs: number): number => Math.floor((Date.now() - hrs * 60 * 60 * 1000) / 1000)

/**
* Model description here for TypeScript hints.
Expand Down Expand Up @@ -46,10 +46,10 @@ export const ChannelModel = types
},
}))
.actions((self) => ({
fetchMessages: flow(function* (channel: ChannelManager, hours: number) {
fetchMessages: flow(function* (channel: ChannelManager) {
const events = yield channel.list({
channel_id: self.id,
filter: { since: nHoursAgo(hours) },
filter: { limit: 500 },
db_only: self.db,
privkey: self.privkey,
})
Expand Down
1 change: 1 addition & 0 deletions app/models/ChannelStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const ChannelStoreModel = types
about: meta.about,
privkey: meta.privkey,
lastMessageAt: Math.floor(Date.now() / 1000),
is_private: meta.is_private,
})
}
},
Expand Down
37 changes: 31 additions & 6 deletions app/models/UserStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export const UserStoreModel = types

// this updates the home screen prop when new messages arrive
// by passing in all our contact keys, we can decrypt new blinded messages
const list = yield privMessageManager.list({ limit: 200 }, false, keys)
const list = yield privMessageManager.list({ limit: 500 }, false, keys)
const map = new Map<string, NostrEvent>()
list.forEach((ev) => {
const was = map.get(ev.pubkey)
Expand All @@ -194,6 +194,20 @@ export const UserStoreModel = types
if (index !== -1) self.channels.splice(index, 1)
mgr.leave(id)
},
fetchInvites: flow(function* (
pool: NostrPool,
privMessageManager: PrivateMessageManager,
pubkey: string,
) {
const invites = yield pool.list([{ kinds: [99], "#p": [pubkey] }], false)
for (const ev of invites) {
const invite = yield privMessageManager.decrypt(ev, [ev.pubkey])
const channel = JSON.parse(invite.content)
// join invite channel
const index = self.channels.findIndex((el: { id: string }) => el.id === channel.id)
if (index === -1) self.channels.push(ChannelModel.create(channel))
}
}),
async afterCreate() {
const sec = await secureGet("privkey")
if (sec) {
Expand Down Expand Up @@ -266,20 +280,31 @@ export const UserStoreModel = types
privMessages,
})
}),
async logout() {
await secureDel("privkey")
logout: flow(function* (
pool: NostrPool,
contactManager: ContactManager,
channelManager: ChannelManager,
) {
pool.ident = null
contactManager.contacts = new Map()
channelManager.joined = new Set()

yield secureDel("privkey")
applySnapshot(self, {
pubkey: "",
privkey: "",
isLoggedIn: false,
channels: [],
contacts: [],
privMessages: [],
metadata: null,
})
},
}),
fetchContacts: flow(function* (mgr: ContactManager) {
if (!self.pubkey) throw new Error("pubkey not found")
const res = yield mgr.list()
self.setProp("contacts", res)
yield mgr.readContacts()
const get = yield mgr.list()
self.setProp("contacts", get)
}),
addContact: flow(function* (contact: Contact & { metadata?: string }, mgr: ContactManager) {
yield mgr.add(contact)
Expand Down
4 changes: 2 additions & 2 deletions app/navigators/AppNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export type AppStackParamList = {
DirectMessage: undefined
CreateChannel: undefined
Contacts: undefined
ContactPicker: undefined
Invite: undefined
ChannelManager: undefined
RelayManager: undefined
NotificationSetting: undefined
Expand Down Expand Up @@ -78,7 +78,7 @@ const AppStack = observer(function AppStack() {
<Stack.Screen name="DirectMessage" component={Screens.DirectMessageScreen} />
<Stack.Screen name="AddContact" component={Screens.AddContactScreen} />
<Stack.Screen name="Contacts" component={Screens.ContactsScreen} />
<Stack.Screen name="ContactPicker" component={Screens.ContactPickerScreen} />
<Stack.Screen name="Invite" component={Screens.InviteScreen} />
<Stack.Screen name="ChannelManager" component={Screens.ChannelManagerScreen} />
<Stack.Screen name="RelayManager" component={Screens.RelayManagerScreen} />
<Stack.Screen name="NotificationSetting" component={Screens.NotificationSettingScreen} />
Expand Down
2 changes: 1 addition & 1 deletion app/screens/ChannelManagerScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const ChannelManagerScreen: FC<ChannelManagerScreenProps> = observer(
}

const invite = (info: { id: string; name: string; privkey: string }) => {
navigation.navigate("ContactPicker", {
navigation.navigate("Invite", {
id: info.id,
name: info.name,
privkey: info.privkey,
Expand Down
2 changes: 1 addition & 1 deletion app/screens/ChannelMembersScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const ChannelMembersScreen: FC<ChannelMembersScreenProps> = observer(
rightIcon="Plus"
rightIconColor={colors.palette.cyan400}
onRightPress={() =>
navigation.navigate("ContactPicker", {
navigation.navigate("Invite", {
id,
name,
privkey,
Expand Down
91 changes: 46 additions & 45 deletions app/screens/ChannelsScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC, useContext, useEffect, useLayoutEffect, useState } from "react"
import React, { FC, useCallback, useContext, useEffect, useLayoutEffect, useState } from "react"
import { observer } from "mobx-react-lite"
import { ImageStyle, Pressable, View, ViewStyle } from "react-native"
import { NativeStackScreenProps } from "@react-navigation/native-stack"
Expand All @@ -9,7 +9,6 @@ import { colors, spacing } from "app/theme"
import { FlashList } from "@shopify/flash-list"
import { RelayContext } from "app/components/RelayProvider"
import { useStores } from "app/models"
import { isImage } from "app/utils/isImage"
import { PlusIcon } from "lucide-react-native"
import { ChannelInfo, Nip28ChannelInfo, NostrEvent } from "app/arclib/src"

Expand Down Expand Up @@ -86,10 +85,14 @@ export const ChannelsScreen: FC<ChannelsScreenProps> = observer(function Channel
}

async function initChannels(prev) {
const res = await channelManager.listChannels(true)
const final = Array.from(new Set([...prev, ...res])).sort(
(a, b) => +b.is_private - +a.is_private,
)
let res = await channelManager.listChannels(true)

// remove private channel
res = res.filter((el) => !el.is_private)

// merge array, remove dup
const final = [...new Map([...prev, ...res].map((el) => [el.id, el])).values()]

setData(final)
}

Expand All @@ -98,6 +101,42 @@ export const ChannelsScreen: FC<ChannelsScreenProps> = observer(function Channel
.catch(console.error)
}, [])

const renderItem = useCallback(({ item }: { item: ChannelInfo }) => {
return (
<Card
preset="reversed"
ContentComponent={
<View style={$item}>
<View style={$itemContent}>
<AutoImage
source={{
uri: item.picture || "https://void.cat/d/HxXbwgU9ChcQohiVxSybCs.jpg",
}}
style={$itemImage}
/>
<View>
<Text text={item.name} preset="bold" />
<Text text={item.about} />
</View>
</View>
<View style={$itemActions}>
{!userStore.channels.find((el) => el.id === item.id) ? (
<Button onPress={() => joinChannel(item)} text="Join" style={$itemButton} />
) : (
<Button
onPress={() => navigation.navigate("Chat", item)}
text="View channel"
style={$itemButton}
/>
)}
</View>
</View>
}
style={item.privkey ? $itemWrapperPrivate : $itemWrapper}
/>
)
}, [])

return (
<Screen style={$root} preset="scroll">
<View style={[$root, $container]}>
Expand All @@ -106,45 +145,7 @@ export const ChannelsScreen: FC<ChannelsScreenProps> = observer(function Channel
keyExtractor={(item) => item.id}
data={data}
extraData={userStore.getChannels}
renderItem={({ item }) => {
// no name or short channel name, mostly spam
if (!item.name) {
return null
}
// invalid image url, mark as spam
if (!isImage(item.picture) && !item.is_private) {
return null
}
// user joined channel, skip
if (userStore.channels.find((el) => el.id === item.id)) {
return null
}
return (
<Card
preset="reversed"
ContentComponent={
<View style={$item}>
<View style={$itemContent}>
<AutoImage
source={{
uri: item.picture || "https://void.cat/d/KmypFh2fBdYCEvyJrPiN89.webp",
}}
style={$itemImage}
/>
<View>
<Text text={item.name} preset="bold" />
<Text text={item.about} />
</View>
</View>
<View style={$itemActions}>
<Button onPress={() => joinChannel(item)} text="Join" style={$itemButton} />
</View>
</View>
}
style={item.privkey ? $itemWrapperPrivate : $itemWrapper}
/>
)
}}
renderItem={renderItem}
ListEmptyComponent={<Text text="Loading..." />}
estimatedItemSize={300}
/>
Expand Down
7 changes: 3 additions & 4 deletions app/screens/ChatScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ export const ChatScreen: FC<ChatScreenProps> = observer(function ChatScreen({
channelStore: { getChannel },
} = useStores()

// Pull in navigation via hook
const navigation = useNavigation<any>()

// get channel by using resolver identifier
Expand Down Expand Up @@ -148,7 +147,8 @@ export const ChatScreen: FC<ChatScreenProps> = observer(function ChatScreen({

useEffect(() => {
// fetch messages in 24 hours ago
channel.fetchMessages(channelManager, 24)
channel.fetchMessages(channelManager)

return () => {
clearReply()
channel.updateLastMessage()
Expand Down Expand Up @@ -239,8 +239,7 @@ export const ChatScreen: FC<ChatScreenProps> = observer(function ChatScreen({
</View>
}
contentContainerStyle={$list}
removeClippedSubviews={true}
estimatedItemSize={60}
estimatedItemSize={120}
inverted={channel.allMessages.length !== 0}
keyboardDismissMode="none"
/>
Expand Down
Loading

0 comments on commit 0f7d78a

Please sign in to comment.