Skip to content

Commit

Permalink
Merge pull request #401 from reyamir/improve-1
Browse files Browse the repository at this point in the history
Improve performance
  • Loading branch information
earonesty authored Jul 21, 2023
2 parents 0f7d78a + 7c89568 commit c909609
Show file tree
Hide file tree
Showing 14 changed files with 144 additions and 61 deletions.
2 changes: 1 addition & 1 deletion app/arclib
6 changes: 6 additions & 0 deletions app/components/DirectMessageReply.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Icon } from "./Icon"
import ReText from "./ReText"
import React from "react"
import { TouchableFeedback } from "./TouchableFeedback"
import { useStores } from "app/models"

export type ReplyInfo = {
sender: string
Expand All @@ -17,6 +18,10 @@ type DirectMessageReplyProps = {
}

const DirectMessageReply: React.FC<DirectMessageReplyProps> = ({ replyInfo, height = 60 }) => {
const {
userStore: { clearReply },
} = useStores()

// This progress will be used to animate all the components inside the reply container
const progress = useDerivedValue(() => {
return withTiming(replyInfo.value ? 1 : 0)
Expand Down Expand Up @@ -62,6 +67,7 @@ const DirectMessageReply: React.FC<DirectMessageReplyProps> = ({ replyInfo, heig
style={[styles.iconContainer, styles.clearIcon]}
onPress={() => {
replyInfo.value = null
clearReply()
}}
>
<Icon icon="X" color={colors.palette.cyan600} size={25} />
Expand Down
34 changes: 22 additions & 12 deletions app/components/LinkPreview.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,43 @@
import React, { useEffect, useState } from "react"
import React from "react"
import { Linking, TextStyle, View, ViewStyle } from "react-native"
import { getLinkPreview } from "link-preview-js"
import AutoHeightImage from "react-native-auto-height-image"
import { Text } from "app/components"
import { colors, spacing } from "app/theme"
import { useQuery } from "@tanstack/react-query"

export function LinkPreview({ width, url }: { width: number; url: string }) {
const domain = new URL(url)
const [preview, setPreview] = useState(null)

useEffect(() => {
getLinkPreview(url).then((data) => setPreview(data))
}, [url])
const { status, data: preview } = useQuery(
["og", url],
async () => {
return await getLinkPreview(url)
},
{
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
staleTime: Infinity,
},
)

return (
<View style={$opWrapper}>
{!preview ? (
{status === "loading" ? (
<Text text="Loading..." />
) : status === "error" ? (
<Text text="Failed to fetch open graph..." />
) : (
<>
{preview.images[0] && (
<AutoHeightImage width={width} source={{ uri: preview.images[0] }} />
{preview?.images?.[0] && (
<AutoHeightImage width={width} source={{ uri: preview?.images[0] }} />
)}
<View style={$opContent}>
<Text text={preview.title} preset="bold" size="sm" style={$ogTitle} />
<Text text={preview.description} size="sm" style={$ogDesc} />
<Text text={preview?.title} preset="bold" size="sm" style={$ogTitle} />
<Text text={preview?.description} size="sm" style={$ogDesc} numberOfLines={3} />
<Text
text={domain.hostname}
onPress={() => Linking.openURL(preview.url)}
onPress={() => Linking.openURL(preview?.url)}
style={$ogDomain}
/>
</View>
Expand Down
21 changes: 13 additions & 8 deletions app/components/ReplyUser.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { useQuery } from "@tanstack/react-query"
import { useQuery, useQueryClient } from "@tanstack/react-query"
import React, { useContext } from "react"
import { TextStyle, View } from "react-native"
import { RelayContext, Text } from "app/components"
import { colors } from "app/theme"

export function ReplyUser({ pubkey }: { pubkey: string }) {
const queryClient = useQueryClient()
const { pool } = useContext(RelayContext)

const { data: profile } = useQuery(["user", pubkey], async () => {
const list = await pool.list([{ kinds: [0], authors: [pubkey] }], true)
const latest = list.slice(-1)[0]
if (latest) {
return JSON.parse(latest.content)
}
return null
const { data: profile } = useQuery({
queryKey: ["user", pubkey],
queryFn: async () => {
const list = await pool.list([{ kinds: [0], authors: [pubkey] }], true)
const latest = list.slice(-1)[0]
if (latest) {
return JSON.parse(latest.content)
}
return null
},
initialData: () => queryClient.getQueryData(["user", pubkey]),
})

return (
Expand Down
21 changes: 13 additions & 8 deletions app/components/User.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ImageStyle, Pressable, TextStyle, View, ViewStyle } from "react-native"
import { colors, spacing } from "app/theme"
import { shortenKey } from "app/utils/shortenKey"
import { useNavigation } from "@react-navigation/native"
import { useQuery } from "@tanstack/react-query"
import { useQuery, useQueryClient } from "@tanstack/react-query"
import { VenetianMaskIcon } from "lucide-react-native"
import { useStores } from "app/models"

Expand All @@ -15,18 +15,23 @@ interface UserProp {
}

export const User = memo(function User({ pubkey, reverse, blinded }: UserProp) {
const queryClient = useQueryClient()
const navigation = useNavigation<any>()

const { pool } = useContext(RelayContext)
const { userStore } = useStores()

const { data: profile } = useQuery(["user", pubkey], async () => {
const list = await pool.list([{ kinds: [0], authors: [pubkey] }], true)
const latest = list.slice(-1)[0]
if (latest) {
return JSON.parse(latest.content)
}
return null
const { data: profile } = useQuery({
queryKey: ["user", pubkey],
queryFn: async () => {
const list = await pool.list([{ kinds: [0], authors: [pubkey] }], true)
const latest = list.slice(-1)[0]
if (latest) {
return JSON.parse(latest.content)
}
return null
},
initialData: () => queryClient.getQueryData(["user", pubkey]),
})

const redirect = () => {
Expand Down
19 changes: 15 additions & 4 deletions app/models/Channel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChannelManager, NostrEvent } from "app/arclib/src"
import { ChannelManager, NostrEvent, NostrPool } from "app/arclib/src"
import {
Instance,
SnapshotIn,
Expand All @@ -10,8 +10,9 @@ import {
} from "mobx-state-tree"
import { withSetPropAction } from "./helpers/withSetPropAction"
import { MessageModel } from "./Message"
import { QueryClient } from "@tanstack/react-query"

// 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,13 +47,23 @@ export const ChannelModel = types
},
}))
.actions((self) => ({
fetchMessages: flow(function* (channel: ChannelManager) {
fetchMessages: flow(function* (
queryClient: QueryClient,
pool: NostrPool,
channel: ChannelManager,
) {
const events = yield channel.list({
channel_id: self.id,
filter: { limit: 500 },
filter: { since: nHoursAgo(72), limit: 200 },
db_only: self.db,
privkey: self.privkey,
})
// batch fetch user's metadata
const authors = [...new Set(events.map((ev: NostrEvent) => ev.pubkey))] as string[]
const meta: NostrEvent[] = yield pool.list([{ authors, kinds: [0] }], self.db)
meta.forEach((user) => {
queryClient.setQueryData(["user", user.pubkey], JSON.parse(user.content))
})
// we need make sure event's content is string (some client allow content as number, ex: coracle)
// but this function maybe hurt performance
events.forEach((event: NostrEvent) => {
Expand Down
2 changes: 1 addition & 1 deletion app/screens/AddContactScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const AddContactScreen: FC<AddContactScreenProps> = observer(function Add
pubkey = nip19.decode(pubkey).data as string
}
if (getContacts.find((e) => e.pubkey === pubkey)) {
alert("Contact has been added")
alert("Contact has been added already")
return
}
addContact({ pubkey, legacy: true, secret: false }, contactManager)
Expand Down
13 changes: 11 additions & 2 deletions app/screens/ChannelsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { observer } from "mobx-react-lite"
import { ImageStyle, Pressable, View, ViewStyle } from "react-native"
import { NativeStackScreenProps } from "@react-navigation/native-stack"
import { AppStackScreenProps } from "app/navigators"
import { Card, Header, Screen, Text, Button, AutoImage } from "app/components"
import { Card, Header, Screen, Text, Button, AutoImage, ActivityIndicator } from "app/components"
import { useNavigation } from "@react-navigation/native"
import { colors, spacing } from "app/theme"
import { FlashList } from "@shopify/flash-list"
Expand Down Expand Up @@ -146,7 +146,11 @@ export const ChannelsScreen: FC<ChannelsScreenProps> = observer(function Channel
data={data}
extraData={userStore.getChannels}
renderItem={renderItem}
ListEmptyComponent={<Text text="Loading..." />}
ListEmptyComponent={
<View style={$emptyState}>
<ActivityIndicator type="small" />
</View>
}
estimatedItemSize={300}
/>
</View>
Expand Down Expand Up @@ -233,3 +237,8 @@ const $itemButton: ViewStyle = {
height: 30,
minHeight: 30,
}

const $emptyState: ViewStyle = {
alignSelf: "center",
paddingVertical: spacing.medium,
}
11 changes: 6 additions & 5 deletions app/screens/ChatScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ export const ChatScreen: FC<ChatScreenProps> = observer(function ChatScreen({
}

async function subscribe() {
console.log("subscribe")
return await channelManager.sub({
channel_id: channel.id,
callback: handleNewMessage,
Expand All @@ -135,19 +134,21 @@ export const ChatScreen: FC<ChatScreenProps> = observer(function ChatScreen({
})
}

// subscribe for new messages
subscribe().catch(console.error)
// channel finish loading, subscribe for new messages
if (channel.loading === false) {
subscribe().catch(console.error)
}

return () => {
console.log("unsubscribe")
pool.unsub(handleNewMessage)
}
}, []),
}, [id, channel.loading]),
)

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

return () => {
clearReply()
Expand Down
35 changes: 22 additions & 13 deletions app/screens/DirectMessageScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
MessageContent,
Reply,
} from "app/components"
import { useNavigation } from "@react-navigation/native"
import { useFocusEffect, useNavigation } from "@react-navigation/native"
import { colors, spacing } from "app/theme"
import { FlashList } from "@shopify/flash-list"
import { useStores } from "app/models"
Expand Down Expand Up @@ -69,22 +69,33 @@ export const DirectMessageScreen: FC<DirectMessageScreenProps> = observer(
})
}, [])

useEffect(() => {
async function handleNewMessage(event) {
setData((prev) => {
if (prev && prev.find((ev) => ev.id === event.id)) return prev
return [event, ...prev]
})
}
useFocusEffect(
useCallback(() => {
function handleNewDM(event) {
setData((prev) => {
if (prev && prev.find((ev) => ev.id === event.id)) return prev
return [event, ...prev]
})
}

// subscribe for new message
privMessageManager.sub(handleNewDM, { since: Math.floor(Date.now() / 1000) }, undefined, id)

return () => {
pool.unsub(handleNewDM)
}
}, [loading]),
)

useEffect(() => {
async function initDMS() {
try {
const list = await privMessageManager.list({ limit: 500 }, true, id, handleNewMessage)
console.log("dm: showing", list.length)
const list = await privMessageManager.list({ limit: 500 }, true, id)
const sorted = list.sort((a, b) => b.created_at - a.created_at).filter((e) => e?.content)

console.log("dm: showing", list.length)
// update state
setData(sorted)
setLoading(false)
} catch (e) {
console.log("dm: error loading messages", e)
}
Expand All @@ -96,8 +107,6 @@ export const DirectMessageScreen: FC<DirectMessageScreenProps> = observer(

return () => {
clearReply()
console.log("dm: unsubscribing...")
pool.unsub(handleNewMessage)
}
}, [id])

Expand Down
6 changes: 6 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import React from "react"
import { AppRegistry } from "react-native"
import RNBootSplash from "react-native-bootsplash"

/*
if (__DEV__) {
require('basil-ws-flipper').wsDebugPlugin;
}
*/

function IgniteApp() {
return <App hideSplashScreen={RNBootSplash.hide} />
}
Expand Down
6 changes: 6 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,8 @@ PODS:
- React-jsinspector (0.71.8)
- React-logger (0.71.8):
- glog
- react-native-flipper (0.207.0):
- React-Core
- react-native-image-picker (5.4.2):
- React-Core
- react-native-quick-sqlite (8.0.2):
Expand Down Expand Up @@ -595,6 +597,7 @@ DEPENDENCIES:
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
- react-native-flipper (from `../node_modules/react-native-flipper`)
- react-native-image-picker (from `../node_modules/react-native-image-picker`)
- react-native-quick-sqlite (from `../node_modules/react-native-quick-sqlite`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
Expand Down Expand Up @@ -717,6 +720,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
React-logger:
:path: "../node_modules/react-native/ReactCommon/logger"
react-native-flipper:
:path: "../node_modules/react-native-flipper"
react-native-image-picker:
:path: "../node_modules/react-native-image-picker"
react-native-quick-sqlite:
Expand Down Expand Up @@ -823,6 +828,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: 747911ab5921641b4ed7e4900065896597142125
React-jsinspector: c712f9e3bb9ba4122d6b82b4f906448b8a281580
React-logger: 342f358b8decfbf8f272367f4eacf4b6154061be
react-native-flipper: 457f5d70546cdd4281e748ff3726385ffa06ba41
react-native-image-picker: 77f552291e993f3fdcdf48cc3c280ef7f11789c8
react-native-quick-sqlite: 2b225dadc63b670f027111e58f6f169773f6d755
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
Expand Down
Loading

0 comments on commit c909609

Please sign in to comment.