Sign block height (#418)

This commit is contained in:
KoalaSat 2023-03-11 22:35:21 +00:00 committed by GitHub
commit 812d91d1d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 255 additions and 143 deletions

View File

@ -37,7 +37,7 @@ export const GroupHeaderIcon: React.FC<GroupHeaderIconProps> = ({ groupId }) =>
const { t } = useTranslation('common')
const { database } = useContext(AppContext)
const { publicKey } = useContext(UserContext)
const { relayPool, lastEventId } = useContext(RelayPoolContext)
const { sendEvent, lastEventId } = useContext(RelayPoolContext)
const theme = useTheme()
const [group, setGroup] = useState<Group>()
const [user, setUser] = useState<User>()
@ -91,7 +91,7 @@ export const GroupHeaderIcon: React.FC<GroupHeaderIconProps> = ({ groupId }) =>
pubkey: publicKey,
tags: [['e', group?.id, '']],
}
relayPool?.sendEvent(event)
sendEvent(event)
bottomSheetEditGroupRef.current?.close()
}
}

View File

@ -23,6 +23,7 @@ import {
removeBookmarkList,
removeList,
} from '../../Functions/RelayFunctions/Lists'
import { getBitcoinTag } from '../../Functions/RelayFunctions/Events'
interface NoteActionsProps {
bottomSheetRef: React.RefObject<RBSheet>
@ -30,14 +31,23 @@ interface NoteActionsProps {
export const NoteActions: React.FC<NoteActionsProps> = ({ bottomSheetRef }) => {
const theme = useTheme()
const { reloadLists, publicBookmarks, publicKey, privateKey, privateBookmarks, mutedEvents } =
React.useContext(UserContext)
const {
reloadLists,
reloadBookmarks,
publicBookmarks,
publicKey,
privateKey,
privateBookmarks,
mutedEvents,
} = React.useContext(UserContext)
const { database, displayNoteDrawer, relayColouring } = React.useContext(AppContext)
const { relayPool, setDisplayrelayDrawer, lastEventId } = React.useContext(RelayPoolContext)
const { relayPool, setDisplayrelayDrawer, lastEventId, sendEvent } =
React.useContext(RelayPoolContext)
const [note, setNote] = React.useState<Note>()
const [relays, setRelays] = React.useState<NoteRelay[]>([])
const [bookmarked, setBookmarked] = React.useState<boolean>(false)
const [isMuted, setIsMuted] = React.useState<boolean>()
const [bitcoinTag, setBitcoinTag] = React.useState<string[]>()
const bottomSheetShareRef = React.useRef<RBSheet>(null)
const bottomBookmarkRef = React.useRef<RBSheet>(null)
@ -60,6 +70,7 @@ export const NoteActions: React.FC<NoteActionsProps> = ({ bottomSheetRef }) => {
React.useEffect(() => {
reloadLists()
reloadBookmarks()
loadNote()
}, [displayNoteDrawer, lastEventId, bookmarked, isMuted])
@ -68,6 +79,7 @@ export const NoteActions: React.FC<NoteActionsProps> = ({ bottomSheetRef }) => {
const allBookmarks = [...publicBookmarks, ...privateBookmarks]
setBookmarked(allBookmarks.find((id) => id === note.id) !== undefined)
setIsMuted(mutedEvents.find((id) => id === note.id) !== undefined)
setBitcoinTag(getBitcoinTag(note)[0] ?? undefined)
}
}, [publicBookmarks, privateBookmarks, note, mutedEvents])
@ -85,9 +97,9 @@ export const NoteActions: React.FC<NoteActionsProps> = ({ bottomSheetRef }) => {
const changeBookmark: (publicBookmark: boolean) => void = (publicBookmark) => {
if (relayPool && database && publicKey && privateKey && note?.id) {
if (bookmarked) {
removeBookmarkList(relayPool, database, privateKey, publicKey, note.id)
removeBookmarkList(sendEvent, database, privateKey, publicKey, note.id)
} else {
addBookmarkList(relayPool, database, privateKey, publicKey, note.id, publicBookmark)
addBookmarkList(sendEvent, database, privateKey, publicKey, note.id, publicBookmark)
}
setBookmarked(!bookmarked)
bottomBookmarkRef.current?.close()
@ -97,9 +109,9 @@ export const NoteActions: React.FC<NoteActionsProps> = ({ bottomSheetRef }) => {
const changeMute: () => void = () => {
if (relayPool && database && publicKey && note?.id) {
if (isMuted) {
removeList(relayPool, database, publicKey, note.id, 'mute')
removeList(sendEvent, database, publicKey, note.id, 'mute')
} else {
addList(relayPool, database, publicKey, note.id, 'mute')
addList(sendEvent, database, publicKey, note.id, 'mute')
}
setIsMuted(!isMuted)
}
@ -122,7 +134,25 @@ export const NoteActions: React.FC<NoteActionsProps> = ({ bottomSheetRef }) => {
return (
<View style={styles.container}>
<Text variant='titleMedium'>{formatId(note?.id)}</Text>
<Text variant='titleMedium'>{t('noteActions.note')}</Text>
<Text variant='titleSmall'>
{t('noteActions.id')}
{`: ${formatId(note?.id)}`}
</Text>
{bitcoinTag && (
<View>
<Divider style={styles.divider} />
<Text variant='titleMedium'>{t('noteActions.bitcoinBlock')}</Text>
<Text variant='titleSmall'>
{t('noteActions.bitcoinBlockHeight')}
{`: ${bitcoinTag[2]}`}
</Text>
<Text variant='bodySmall'>
{t('noteActions.id')}
{`: ${bitcoinTag[1]}`}
</Text>
</View>
)}
<View style={styles.mainLayout}>
<View style={styles.actionButton}>
<IconButton
@ -289,6 +319,10 @@ const styles = StyleSheet.create({
flex: 1,
height: 10,
},
divider: {
marginTop: 16,
marginBottom: 16,
},
})
export default NoteActions

View File

@ -12,7 +12,7 @@ import { StyleSheet, View } from 'react-native'
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
import { AppContext } from '../../Contexts/AppContext'
import { t } from 'i18next'
import { isContentWarning } from '../../Functions/RelayFunctions/Events'
import { getBitcoinTag, isContentWarning } from '../../Functions/RelayFunctions/Events'
import { type Event } from '../../lib/nostr/Events'
import { getUnixTime } from 'date-fns'
import { type Relay, searchRelays } from '../../Functions/DatabaseFunctions/Relays'
@ -72,7 +72,7 @@ export const NoteCard: React.FC<NoteCardProps> = ({
}) => {
const theme = useTheme()
const { publicKey, privateKey, mutedUsers } = React.useContext(UserContext)
const { relayPool, lastEventId, addRelayItem } = useContext(RelayPoolContext)
const { sendEvent, lastEventId, addRelayItem } = useContext(RelayPoolContext)
const {
database,
showSensitive,
@ -98,6 +98,7 @@ export const NoteCard: React.FC<NoteCardProps> = ({
const [loadingZap, setLoadingZap] = React.useState<boolean>(false)
const [mutedUser, setMutedUser] = React.useState<boolean>(false)
const [zapInvoice, setZapInvoice] = React.useState<string>()
const [bitcoinTag, setBitcoinTag] = React.useState<string[]>()
useEffect(() => {
if (database && publicKey && note?.id) {
@ -125,6 +126,7 @@ export const NoteCard: React.FC<NoteCardProps> = ({
}
getNoteRelays(database, note.id).then(setRelays)
setMutedUser(mutedUsers.find((e) => e === note.pubkey) !== undefined)
setBitcoinTag(getBitcoinTag(note)[0] ?? undefined)
}
}, [lastEventId])
@ -154,7 +156,7 @@ export const NoteCard: React.FC<NoteCardProps> = ({
pubkey: publicKey,
tags: [...note.tags, ['e', note.id], ['p', note.pubkey]],
}
relayPool?.sendEvent(event)
sendEvent(event)
}
}
@ -412,6 +414,7 @@ export const NoteCard: React.FC<NoteCardProps> = ({
lnAddress={note?.ln_address}
picture={showAvatarImage ? note?.picture : undefined}
timestamp={note?.created_at}
bitcoinTag={bitcoinTag}
/>
</TouchableRipple>
</View>

View File

@ -35,7 +35,7 @@ export const ProfileActions: React.FC<ProfileActionsProps> = ({
const theme = useTheme()
const { database } = React.useContext(AppContext)
const { publicKey, privateKey, mutedUsers, reloadLists } = React.useContext(UserContext)
const { relayPool, updateRelayItem, lastEventId } = React.useContext(RelayPoolContext)
const { relayPool, updateRelayItem, lastEventId, sendEvent } = React.useContext(RelayPoolContext)
const [isContact, setIsContact] = React.useState<boolean>()
const [isMuted, setIsMuted] = React.useState<boolean>()
const [isGroupHidden, setIsGroupHidden] = React.useState<boolean>()
@ -68,22 +68,20 @@ export const ProfileActions: React.FC<ProfileActionsProps> = ({
const hideGroupsUser: () => void = () => {
if (publicKey && relayPool && database && user.id) {
relayPool
?.sendEvent({
content: '',
created_at: getUnixTime(new Date()),
kind: Kind.ChannelMuteUser,
pubkey: publicKey,
tags: [['p', user.id]],
})
.then(() => {
if (database) {
DatabaseModule.updateUserMutesGroups(user.id, true, () => {
setIsGroupHidden(true)
bottomSheetMuteRef.current?.close()
})
}
})
sendEvent({
content: '',
created_at: getUnixTime(new Date()),
kind: Kind.ChannelMuteUser,
pubkey: publicKey,
tags: [['p', user.id]],
}).then(() => {
if (database) {
DatabaseModule.updateUserMutesGroups(user.id, true, () => {
setIsGroupHidden(true)
bottomSheetMuteRef.current?.close()
})
}
})
}
}
@ -118,10 +116,10 @@ export const ProfileActions: React.FC<ProfileActionsProps> = ({
if (database && publicKey && privateKey && relayPool) {
DatabaseModule.addUser(user.id, () => {
if (isMuted) {
removeMutedUsersList(relayPool, database, publicKey, user.id)
removeMutedUsersList(sendEvent, database, publicKey, user.id)
DatabaseModule.updateUserBlock(user.id, false, () => {})
} else {
addMutedUsersList(relayPool, database, publicKey, user.id)
addMutedUsersList(sendEvent, database, publicKey, user.id)
}
setIsMuted(!isMuted)
reloadLists()
@ -134,7 +132,7 @@ export const ProfileActions: React.FC<ProfileActionsProps> = ({
const removeContact: () => void = () => {
if (relayPool && database && publicKey) {
DatabaseModule.updateUserContact(user.id, false, () => {
populatePets(relayPool, database, publicKey)
populatePets(sendEvent, database, publicKey)
setIsContact(false)
setShowNotification('contactRemoved')
})
@ -144,7 +142,7 @@ export const ProfileActions: React.FC<ProfileActionsProps> = ({
const addContact: () => void = () => {
if (relayPool && database && publicKey) {
DatabaseModule.updateUserContact(user.id, true, () => {
populatePets(relayPool, database, publicKey)
populatePets(sendEvent, database, publicKey)
setIsContact(true)
setShowNotification('contactAdded')
})

View File

@ -6,6 +6,7 @@ import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityI
import NostrosAvatar from '../NostrosAvatar'
import { getNpub } from '../../lib/nostr/Nip19'
import { formatDate } from '../../Functions/NativeFunctions'
import { AppContext } from '../../Contexts/AppContext'
interface ProfileCardProps {
username?: string
@ -17,6 +18,7 @@ interface ProfileCardProps {
picture?: string
avatarSize?: number
timestamp?: number
bitcoinTag?: string[]
}
export const ProfileData: React.FC<ProfileCardProps> = ({
@ -29,8 +31,10 @@ export const ProfileData: React.FC<ProfileCardProps> = ({
picture,
avatarSize,
timestamp,
bitcoinTag,
}) => {
const theme = useTheme()
const { signHeight } = React.useContext(AppContext)
const nPub = React.useMemo(() => (publicKey ? getNpub(publicKey) : ''), [publicKey])
const date = React.useMemo(() => formatDate(timestamp), [timestamp])
@ -62,6 +66,7 @@ export const ProfileData: React.FC<ProfileCardProps> = ({
</View>
<Text numberOfLines={1}>
{timestamp ? date : validNip05 ? getNip05Domain(nip05) : ''}
{signHeight && bitcoinTag ? ` (${bitcoinTag[2]})` : ''}
</Text>
</View>
</View>

View File

@ -42,7 +42,7 @@ interface RelayCardProps {
export const RelayCard: React.FC<RelayCardProps> = ({ url, bottomSheetRef }) => {
const theme = useTheme()
const { publicKey } = React.useContext(UserContext)
const { updateRelayItem, relayPool, removeRelayItem, sendRelays } =
const { updateRelayItem, relayPool, removeRelayItem, sendRelays, sendEvent } =
React.useContext(RelayPoolContext)
const { database } = React.useContext(AppContext)
const [relay, setRelay] = React.useState<Relay>()
@ -67,20 +67,20 @@ export const RelayCard: React.FC<RelayCardProps> = ({ url, bottomSheetRef }) =>
getRawUserNotes(database, publicKey).then((resultNotes) => {
resultNotes.forEach((note) => {
note.content = note.content.replace("''", "'")
relayPool.sendEvent(note, url)
sendEvent(note, url)
})
setPushDone(true)
setShowNotification('pushCompleted')
})
getRawUserReactions(database, publicKey).then((resultReactions) => {
resultReactions.forEach((reaction) => {
relayPool.sendEvent(reaction, url)
sendEvent(reaction, url)
})
})
getRawUserConversation(database, publicKey).then((resultConversations) => {
resultConversations.forEach((conversation) => {
conversation.content = conversation.content.replace("''", "'")
relayPool.sendEvent(conversation, url)
sendEvent(conversation, url)
})
})
getUsers(database, { exludeIds: [publicKey], contacts: true }).then((users) => {
@ -92,27 +92,27 @@ export const RelayCard: React.FC<RelayCardProps> = ({ url, bottomSheetRef }) =>
pubkey: publicKey,
tags: usersToTags(users),
}
relayPool?.sendEvent(event, url)
sendEvent(event, url)
}
})
getRawUserGroupMessages(database, publicKey).then((resultGroupMessages) => {
resultGroupMessages.forEach((groupMessage) => {
relayPool.sendEvent(groupMessage, url)
sendEvent(groupMessage, url)
})
})
getRawUserGroups(database, publicKey).then((resultGroups) => {
resultGroups.forEach((group) => {
relayPool.sendEvent(group, url)
sendEvent(group, url)
})
})
getRawLists(database, publicKey).then((lists) => {
lists.forEach((list) => {
relayPool.sendEvent(list, url)
sendEvent(list, url)
})
})
getRawRelayMetadata(database, publicKey).then((lists) => {
lists.forEach((list) => {
relayPool.sendEvent(list, url)
sendEvent(list, url)
})
})
sendRelays(url)

View File

@ -4,12 +4,24 @@ import { initDatabase } from '../Functions/DatabaseFunctions'
import SInfo from 'react-native-sensitive-info'
import { AppState, Linking, NativeModules, Platform, StyleSheet } from 'react-native'
import { Text } from 'react-native-paper'
import { type Config } from '../Pages/ConfigPage'
import { imageHostingServices } from '../Constants/Services'
import { randomInt, validNip21 } from '../Functions/NativeFunctions'
import Clipboard from '@react-native-clipboard/clipboard'
import i18next from 'i18next'
export interface Config {
satoshi: 'kebab' | 'sats'
show_public_images: boolean
show_sensitive: boolean
last_notification_seen_at: number
last_pets_at: number
image_hosting_service: string
language: string
relay_coloruring: boolean
long_press_zap: number | undefined
sign_height: boolean
}
export interface AppContextProps {
init: () => void
loadingDb: boolean
@ -45,6 +57,8 @@ export interface AppContextProps {
setPushedTab: (pushedTab: string) => void
qrReader?: string
setQrReader: (qrReader: string | undefined) => void
signHeight: boolean
setSignWithHeight: (signHeight: boolean) => void
}
export interface AppContextProviderProps {
@ -86,6 +100,8 @@ export const initialAppContext: AppContextProps = {
setDisplayNoteDrawer: () => {},
longPressZap: undefined,
setLongPressZap: () => {},
signHeight: false,
setSignWithHeight: () => {},
}
export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.Element => {
@ -114,6 +130,7 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E
const [displayUserDrawer, setDisplayUserDrawer] = React.useState<string>()
const [displayNoteDrawer, setDisplayNoteDrawer] = React.useState<string>()
const [pushedTab, setPushedTab] = useState<string>()
const [signHeight, setSignWithHeight] = useState<boolean>(initialAppContext.signHeight)
useEffect(() => {
if (pushedTab) setPushedTab(undefined)
@ -161,6 +178,7 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E
setLanguage(config.language ?? initialAppContext.language)
setLongPressZap(config.long_press_zap ?? initialAppContext.longPressZap)
setRelayColouring(config.relay_coloruring ?? initialAppContext.relayColouring)
setSignWithHeight(config.sign_height ?? initialAppContext.signHeight)
} else {
const config: Config = {
show_public_images: initialAppContext.showPublicImages,
@ -172,6 +190,7 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E
language: initialAppContext.language,
relay_coloruring: initialAppContext.relayColouring,
long_press_zap: initialAppContext.longPressZap,
sign_height: initialAppContext.signHeight,
}
SInfo.setItem('config', JSON.stringify(config), {})
}
@ -249,6 +268,8 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E
setDisplayNoteDrawer,
qrReader,
setQrReader,
signHeight,
setSignWithHeight,
}}
>
{children}

View File

@ -8,6 +8,7 @@ import { UserContext } from './UserContext'
import { getUnixTime } from 'date-fns'
import { type Event } from '../lib/nostr/Events'
import { randomInt } from '../Functions/NativeFunctions'
import axios from 'axios'
export interface RelayPoolContextProps {
relayPoolReady: boolean
@ -24,6 +25,7 @@ export interface RelayPoolContextProps {
sendRelays: (url?: string) => Promise<void>
loadRelays: () => Promise<Relay[]>
createRandomRelays: () => Promise<void>
sendEvent: (event: Event, relayUrl?: string) => Promise<Event | null | undefined>
}
export interface WebsocketEvent {
@ -46,15 +48,15 @@ export const initialRelayPoolContext: RelayPoolContextProps = {
sendRelays: async () => {},
loadRelays: async () => [],
createRandomRelays: async () => {},
sendEvent: async () => null,
}
export const RelayPoolContextProvider = ({
children,
images,
}: RelayPoolContextProviderProps): JSX.Element => {
const { database } = useContext(AppContext)
const { database, signHeight } = useContext(AppContext)
const { publicKey, privateKey } = React.useContext(UserContext)
const [relayPool, setRelayPool] = useState<RelayPool>()
const [relayPoolReady, setRelayPoolReady] = useState<boolean>(false)
const [lastEventId, setLastEventId] = useState<string>('')
@ -62,6 +64,23 @@ export const RelayPoolContextProvider = ({
const [relays, setRelays] = React.useState<Relay[]>([])
const [displayRelayDrawer, setDisplayrelayDrawer] = React.useState<string>()
const sendEvent: (event: Event, relayUrl?: string) => Promise<Event | null | undefined> = async (
event,
relayUrl,
) => {
if (signHeight) {
try {
const response = await axios.get('https://mempool.space/api/v1/blocks')
if (response) {
const lastBlock: { id: string; height: number } = response.data[0]
event.tags.push(['bitcoin', lastBlock.id, lastBlock.height.toString()])
}
} catch {}
}
return await relayPool?.sendEvent(event, relayUrl)
}
const sendRelays: (url?: string) => Promise<void> = async (url) => {
if (publicKey && database) {
getActiveRelays(database).then((results) => {
@ -73,7 +92,7 @@ export const RelayPoolContextProvider = ({
pubkey: publicKey,
tags: results.map((relay) => ['r', relay.url, relay.mode ?? '']),
}
url ? relayPool?.sendEvent(event, url) : relayPool?.sendEvent(event)
url ? sendEvent(event, url) : sendEvent(event)
}
})
}
@ -211,6 +230,7 @@ export const RelayPoolContextProvider = ({
sendRelays,
loadRelays,
createRandomRelays,
sendEvent,
}}
>
{children}

View File

@ -25,6 +25,7 @@ export interface UserContextProps {
setPrivateKey: (privateKey: string | undefined) => void
reloadUser: () => void
reloadLists: () => void
reloadBookmarks: () => void
publicBookmarks: string[]
privateBookmarks: string[]
mutedEvents: string[]
@ -56,6 +57,7 @@ export const initialUserContext: UserContextProps = {
setPrivateKey: () => {},
reloadUser: () => {},
reloadLists: () => {},
reloadBookmarks: () => {},
logout: () => {},
setName: () => {},
setPicture: () => {},
@ -105,6 +107,26 @@ export const UserContextProvider = ({ children }: UserContextProviderProps): JSX
}
}
const decryptBookmarks: (content: string) => void = async (content) => {
if (privateKey && publicKey && content && content !== '') {
const privateJson = decrypt(privateKey, publicKey, content)
const privateList: string[][] = JSON.parse(privateJson)
setPrivateBookmarks(privateList.map((tag) => tag[1]))
}
}
const reloadBookmarks: () => void = () => {
if (database && publicKey && privateKey) {
getList(database, 10001, publicKey).then((result) => {
if (result) {
const eTags = getETags(result)
setPublicBookmarks(eTags.map((tag) => tag[1]))
decryptBookmarks(result.content)
}
})
}
}
const reloadLists: () => void = () => {
if (database && publicKey && privateKey) {
getList(database, 10000, publicKey).then((result) => {
@ -113,15 +135,6 @@ export const UserContextProvider = ({ children }: UserContextProviderProps): JSX
setMutedUsers(eTags.map((tag) => tag[1]))
}
})
getList(database, 10001, publicKey).then((result) => {
if (result) {
const eTags = getETags(result)
setPublicBookmarks(eTags.map((tag) => tag[1]))
const privateJson = decrypt(privateKey, publicKey, result.content ?? '')
const privateList: string[][] = JSON.parse(privateJson)
setPrivateBookmarks(privateList.map((tag) => tag[1]))
}
})
getList(database, 30001, publicKey, 'mute').then((result) => {
if (result) {
const eTags = getETags(result)
@ -172,6 +185,7 @@ export const UserContextProvider = ({ children }: UserContextProviderProps): JSX
setNpub(getNpub(publicKey))
reloadUser()
reloadLists()
reloadBookmarks()
}
}, [publicKey])
@ -222,6 +236,7 @@ export const UserContextProvider = ({ children }: UserContextProviderProps): JSX
setPrivateKey,
reloadUser,
reloadLists,
reloadBookmarks,
publicBookmarks,
privateBookmarks,
mutedEvents,

View File

@ -51,6 +51,10 @@ export const getETags: (event: Event) => string[][] = (event) => {
return event?.tags.filter((tag) => tag[0] === 'e') || []
}
export const getBitcoinTag: (event: Event) => string[][] = (event) => {
return event?.tags.filter((tag) => tag[0] === 'bitcoin') || []
}
export const getPTags: (event: Event) => string[][] = (event) => {
return event?.tags.filter((tag) => tag[0] === 'p') || []
}

View File

@ -1,18 +1,17 @@
import getUnixTime from 'date-fns/getUnixTime'
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
import type RelayPool from '../../../lib/nostr/RelayPool/intex'
import { type Event } from '../../../lib/nostr/Events'
import { getList } from '../../DatabaseFunctions/Lists'
import { decrypt, encrypt } from '../../../lib/nostr/Nip04'
export const addBookmarkList: (
relayPool: RelayPool,
sendEvent: (event: Event, relayUrl?: string) => Promise<Event | null | undefined>,
database: QuickSQLiteConnection,
privateKey: string,
publicKey: string,
eventId: string,
publicBookmark: boolean,
) => void = async (relayPool, database, privateKey, publicKey, eventId, publicBookmark) => {
) => void = async (sendEvent, database, privateKey, publicKey, eventId, publicBookmark) => {
if (!eventId || eventId === '') return
const result = await getList(database, 10001, publicKey)
@ -39,15 +38,15 @@ export const addBookmarkList: (
pubkey: publicKey,
tags,
}
relayPool?.sendEvent(event)
sendEvent(event)
}
export const addMutedUsersList: (
relayPool: RelayPool,
sendEvent: (event: Event, relayUrl?: string) => Promise<Event | null | undefined>,
database: QuickSQLiteConnection,
publicKey: string,
userId: string,
) => void = async (relayPool, database, publicKey, userId) => {
) => void = async (sendEvent, database, publicKey, userId) => {
if (!userId || userId === '') return
const result = await getList(database, 10000, publicKey)
@ -62,16 +61,16 @@ export const addMutedUsersList: (
pubkey: publicKey,
tags,
}
relayPool?.sendEvent(event)
sendEvent(event)
}
export const addList: (
relayPool: RelayPool,
sendEvent: (event: Event, relayUrl?: string) => Promise<Event | null | undefined>,
database: QuickSQLiteConnection,
publicKey: string,
eventId: string,
tag: string,
) => void = async (relayPool, database, publicKey, eventId, tag) => {
) => void = async (sendEvent, database, publicKey, eventId, tag) => {
if (!eventId || eventId === '') return
const result = await getList(database, 30001, publicKey, tag)
@ -86,16 +85,16 @@ export const addList: (
pubkey: publicKey,
tags,
}
relayPool?.sendEvent(event)
sendEvent(event)
}
export const removeBookmarkList: (
relayPool: RelayPool,
sendEvent: (event: Event, relayUrl?: string) => Promise<Event | null | undefined>,
database: QuickSQLiteConnection,
privateKey: string,
publicKey: string,
eventId: string,
) => void = async (relayPool, database, privateKey, publicKey, eventId) => {
) => void = async (sendEvent, database, privateKey, publicKey, eventId) => {
if (!eventId || eventId === '') return
const result = await getList(database, 10001, publicKey)
@ -115,16 +114,16 @@ export const removeBookmarkList: (
pubkey: publicKey,
tags,
}
relayPool?.sendEvent(event)
sendEvent(event)
}
}
export const removeMutedUsersList: (
relayPool: RelayPool,
sendEvent: (event: Event, relayUrl?: string) => Promise<Event | null | undefined>,
database: QuickSQLiteConnection,
publicKey: string,
userId: string,
) => void = async (relayPool, database, publicKey, userId) => {
) => void = async (sendEvent, database, publicKey, userId) => {
if (!userId || userId === '') return
const result = await getList(database, 10000, publicKey)
@ -138,16 +137,16 @@ export const removeMutedUsersList: (
pubkey: publicKey,
tags,
}
relayPool?.sendEvent(event)
sendEvent(event)
}
export const removeList: (
relayPool: RelayPool,
sendEvent: (event: Event, relayUrl?: string) => Promise<Event | null | undefined>,
database: QuickSQLiteConnection,
publicKey: string,
eventId: string,
tag: string,
) => void = async (relayPool, database, publicKey, eventId, tag) => {
) => void = async (sendEvent, database, publicKey, eventId, tag) => {
if (!eventId || eventId === '') return
const result = await getList(database, 30001, publicKey, tag)
@ -161,6 +160,6 @@ export const removeList: (
pubkey: publicKey,
tags,
}
relayPool?.sendEvent(event)
sendEvent(event)
}
}

View File

@ -1,6 +1,5 @@
import getUnixTime from 'date-fns/getUnixTime'
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
import type RelayPool from '../../../lib/nostr/RelayPool/intex'
import { getUser, getUsers, type User } from '../../DatabaseFunctions/Users'
import { type Event } from '../../../lib/nostr/Events'
import { getNpub } from '../../../lib/nostr/Nip19'
@ -58,10 +57,10 @@ export const getNip05Domain: (nip05: string | undefined) => string | null = (nip
}
export const populatePets: (
relayPool: RelayPool,
sendEvent: (event: Event, relayUrl?: string) => Promise<Event | null | undefined>,
database: QuickSQLiteConnection,
publicKey: string,
) => void = async (relayPool, database, publicKey) => {
) => void = async (sendEvent, database, publicKey) => {
const results = await getUsers(database, { exludeIds: [publicKey], contacts: true })
if (results) {
const event: Event = {
@ -71,15 +70,15 @@ export const populatePets: (
pubkey: publicKey,
tags: usersToTags(results),
}
relayPool?.sendEvent(event)
sendEvent(event)
}
}
export const populateProfile: (
relayPool: RelayPool,
sendEvent: (event: Event, relayUrl?: string) => Promise<Event | null | undefined>,
database: QuickSQLiteConnection,
publicKey: string,
) => void = async (relayPool, database, publicKey) => {
) => void = async (sendEvent, database, publicKey) => {
const result = await getUser(publicKey, database)
if (result) {
const profile = {
@ -95,6 +94,6 @@ export const populateProfile: (
pubkey: publicKey,
tags: usersToTags([result]),
}
relayPool?.sendEvent(event)
sendEvent(event)
}
}

View File

@ -92,6 +92,7 @@
"logout": "Abmelden"
},
"configPage": {
"signHeight": "Sign events with latest Bitcoin block",
"showPublicImages": "Bilder aus globalem Feed Anzeigen",
"showSensitive": "Sensible Inhalte anzeigen",
"satoshi": "Satoshi Symbol",

View File

@ -99,6 +99,7 @@
"showSensitive": "Show sensitive notes",
"satoshi": "Satoshi symbol",
"imageHostingService": "Image hosting service",
"signHeight": "Sign with latest Bitcoin block",
"random": "Random",
"language": "Language",
"relayColoruring": "Relay colouring",
@ -113,6 +114,10 @@
"disable": "Disable"
},
"noteActions": {
"note": "Note",
"bitcoinBlock": "Bitcoin block",
"bitcoinBlockHeight": "Height",
"id": "ID",
"publicBookmark": "Add to public bookmarks",
"privateBookmark": "Add to private bookmarks",
"copy": "Copy",

View File

@ -113,6 +113,7 @@
"logout": "Salir"
},
"configPage": {
"signHeight": "Firmar con el último bloque bitcoin",
"showPublicImages": "Mostrar imágenes en feed global",
"showSensitive": "Mostrar notas sensibles",
"satoshi": "Símbolo de satoshi",

View File

@ -121,6 +121,7 @@
"zhCn": "简体中文"
},
"configPage": {
"signHeight": "Sign events with latest Bitcoin block",
"showPublicImages": "Afficher les images dans le flux global",
"showSensitive": "Montrer les notes sensibles",
"satoshi": "Symbole de satoshi",

View File

@ -114,6 +114,7 @@
"imageHostingService": "Хостинг изображений"
},
"configPage": {
"signHeight": "Sign events with latest Bitcoin block",
"showPublicImages": "Show images on public feed",
"showSensitive": "Show sensitive notes",
"satoshi": "Satoshi symbol",

View File

@ -112,6 +112,7 @@
"logout": "退出"
},
"configPage": {
"signHeight": "Sign events with latest Bitcoin block",
"showPublicImages": "显示发现页图片",
"showSensitive": "显示敏感的 Notes",
"satoshi": "聪符号",

View File

@ -4,21 +4,9 @@ import { FlatList, StyleSheet } from 'react-native'
import { Button, Divider, List, Switch, Text, TextInput, useTheme } from 'react-native-paper'
import SInfo from 'react-native-sensitive-info'
import RBSheet from 'react-native-raw-bottom-sheet'
import { AppContext } from '../../Contexts/AppContext'
import { AppContext, Config } from '../../Contexts/AppContext'
import { imageHostingServices } from '../../Constants/Services'
export interface Config {
satoshi: 'kebab' | 'sats'
show_public_images: boolean
show_sensitive: boolean
last_notification_seen_at: number
last_pets_at: number
image_hosting_service: string
language: string
relay_coloruring: boolean
long_press_zap: number | undefined
}
export const ConfigPage: React.FC = () => {
const theme = useTheme()
const { t } = useTranslation('common')
@ -38,6 +26,8 @@ export const ConfigPage: React.FC = () => {
setRelayColouring,
longPressZap,
setLongPressZap,
signHeight,
setSignWithHeight,
} = React.useContext(AppContext)
const bottomSheetSatoshiRef = React.useRef<RBSheet>(null)
const bottomSheetImageHostingRef = React.useRef<RBSheet>(null)
@ -148,6 +138,22 @@ export const ConfigPage: React.FC = () => {
</Text>
)}
/>
<List.Item
title={t('configPage.signHeight')}
right={() => (
<Switch
value={signHeight}
onValueChange={(value) => {
setSignWithHeight(value)
SInfo.getItem('config', {}).then((result) => {
const config: Config = JSON.parse(result)
config.sign_height = value
SInfo.setItem('config', JSON.stringify(config), {})
})
}}
/>
)}
/>
<List.Item title={t('configPage.feed')} />
<Divider />
<List.Item

View File

@ -31,7 +31,6 @@ import { useFocusEffect } from '@react-navigation/native'
import ProfileData from '../../Components/ProfileData'
import { handleInfinityScroll } from '../../Functions/NativeFunctions'
import { queryProfile } from 'nostr-tools/nip05'
import { navigate } from '../../lib/Navigation'
import DatabaseModule from '../../lib/Native/DatabaseModule'
import { removeMutedUsersList } from '../../Functions/RelayFunctions/Lists'
@ -40,7 +39,7 @@ export const ContactsPage: React.FC = () => {
const initialPageSize = 20
const { database, setDisplayUserDrawer, qrReader, setQrReader } = useContext(AppContext)
const { privateKey, publicKey, nPub, mutedUsers, reloadLists } = React.useContext(UserContext)
const { relayPool, lastEventId } = useContext(RelayPoolContext)
const { relayPool, lastEventId, sendEvent } = useContext(RelayPoolContext)
const theme = useTheme()
const [pageSize, setPageSize] = useState<number>(initialPageSize)
const bottomSheetAddContactRef = React.useRef<RBSheet>(null)
@ -158,7 +157,7 @@ export const ContactsPage: React.FC = () => {
if (hexKey) {
DatabaseModule.updateUserContact(hexKey, true, () => {
populatePets(relayPool, database, publicKey)
populatePets(sendEvent, database, publicKey)
loadUsers()
setIsAddingContact(false)
setShowNotification('contactAdded')
@ -179,7 +178,7 @@ export const ContactsPage: React.FC = () => {
const removeContact: (user: User) => void = (user) => {
if (relayPool && database && publicKey) {
DatabaseModule.updateUserContact(user.id, false, () => {
populatePets(relayPool, database, publicKey)
populatePets(sendEvent, database, publicKey)
setShowNotification('contactRemoved')
loadUsers()
})
@ -189,7 +188,7 @@ export const ContactsPage: React.FC = () => {
const addContact: (user: User) => void = (user) => {
if (relayPool && database && publicKey) {
DatabaseModule.updateUserContact(user.id, true, () => {
populatePets(relayPool, database, publicKey)
populatePets(sendEvent, database, publicKey)
setShowNotification('contactRemoved')
loadUsers()
})
@ -199,7 +198,7 @@ export const ContactsPage: React.FC = () => {
const unmute: (user: User) => void = (user) => {
if (relayPool && database && publicKey) {
DatabaseModule.updateUserBlock(user.id, false, () => {
removeMutedUsersList(relayPool, database, publicKey, user.id)
removeMutedUsersList(sendEvent, database, publicKey, user.id)
setShowNotification('contactUnmuted')
loadUsers()
reloadLists()

View File

@ -51,7 +51,7 @@ export const ConversationPage: React.FC<ConversationPageProps> = ({ route }) =>
const theme = useTheme()
const scrollViewRef = useRef<ScrollView>()
const { database, setRefreshBottomBarAt, setDisplayUserDrawer } = useContext(AppContext)
const { relayPool, lastEventId } = useContext(RelayPoolContext)
const { relayPool, lastEventId, sendEvent } = useContext(RelayPoolContext)
const { publicKey, privateKey, name, picture, validNip05 } = useContext(UserContext)
const otherPubKey = useMemo(() => route.params.pubKey, [])
const [pageSize, setPageSize] = useState<number>(initialPageSize)
@ -177,14 +177,12 @@ export const ConversationPage: React.FC<ConversationPageProps> = ({ route }) =>
}
encrypt(privateKey, otherPubKey, input)
.then((encryptedcontent) => {
relayPool
?.sendEvent({
...event,
content: encryptedcontent,
})
.catch(() => {
setShowNotification('privateMessageSendError')
})
sendEvent({
...event,
content: encryptedcontent,
}).catch(() => {
setShowNotification('privateMessageSendError')
})
})
.catch(() => {
setShowNotification('privateMessageSendError')

View File

@ -47,7 +47,7 @@ export const GroupPage: React.FC<GroupPageProps> = ({ route }) => {
const initialPageSize = 20
const theme = useTheme()
const { database, setDisplayUserDrawer } = useContext(AppContext)
const { relayPool, lastEventId } = useContext(RelayPoolContext)
const { relayPool, lastEventId, sendEvent } = useContext(RelayPoolContext)
const { publicKey, privateKey, name, picture, validNip05 } = useContext(UserContext)
const [pageSize, setPageSize] = useState<number>(initialPageSize)
const [groupMessages, setGroupMessages] = useState<GroupMessage[]>([])
@ -204,7 +204,7 @@ export const GroupPage: React.FC<GroupPageProps> = ({ route }) => {
pubkey: publicKey,
tags,
}
relayPool?.sendEvent(event)
sendEvent(event)
const groupMessage = event as GroupMessage
groupMessage.pending = true
groupMessage.valid_nip05 = validNip05

View File

@ -178,7 +178,7 @@ export const GroupsFeed: React.FC = () => {
pubkey: publicKey,
tags: [],
}
relayPool?.sendEvent(event)
sendEvent(event)
bottomSheetCreateRef.current?.close()
bottomSheetFabActionRef.current?.close()
}

View File

@ -40,7 +40,7 @@ export const BookmarksFeed: React.FC<BookmarksFeedProps> = ({
const theme = useTheme()
const { t } = useTranslation('common')
const { database, pushedTab } = useContext(AppContext)
const { publicKey, publicBookmarks, privateBookmarks, reloadLists } = useContext(UserContext)
const { publicKey, publicBookmarks, privateBookmarks, reloadBookmarks } = useContext(UserContext)
const { lastEventId, relayPool, lastConfirmationtId } = useContext(RelayPoolContext)
const initialPageSize = 10
const [notes, setNotes] = useState<Note[]>([])
@ -50,7 +50,7 @@ export const BookmarksFeed: React.FC<BookmarksFeedProps> = ({
const flashListRef = React.useRef<FlashList<Note>>(null)
useEffect(() => {
reloadLists()
reloadBookmarks()
}, [])
useEffect(() => {
@ -79,7 +79,7 @@ export const BookmarksFeed: React.FC<BookmarksFeedProps> = ({
useEffect(() => {
if (pageSize > initialPageSize) {
loadNotes()
reloadLists()
reloadBookmarks()
}
}, [pageSize])

View File

@ -6,7 +6,7 @@ import {
StyleSheet,
View,
} from 'react-native'
import { AppContext } from '../../Contexts/AppContext'
import { AppContext, Config } from '../../Contexts/AppContext'
import SInfo from 'react-native-sensitive-info'
import { getMentionNotes, type Note } from '../../Functions/DatabaseFunctions/Notes'
import NoteCard from '../../Components/NoteCard'
@ -20,7 +20,6 @@ import { useTranslation } from 'react-i18next'
import { navigate } from '../../lib/Navigation'
import { useFocusEffect } from '@react-navigation/native'
import { getUnixTime } from 'date-fns'
import { type Config } from '../../Functions/DatabaseFunctions/Config'
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
import { getETags } from '../../Functions/RelayFunctions/Events'

View File

@ -32,7 +32,7 @@ export const ProfileConfigPage: React.FC = () => {
const bottomSheetNip05Ref = React.useRef<RBSheet>(null)
const bottomSheetLud06Ref = React.useRef<RBSheet>(null)
const { database } = useContext(AppContext)
const { relayPool, lastEventId, lastConfirmationtId } = useContext(RelayPoolContext)
const { relayPool, lastEventId, lastConfirmationtId, sendEvent } = useContext(RelayPoolContext)
const {
publicKey,
nPub,
@ -87,22 +87,20 @@ export const ProfileConfigPage: React.FC = () => {
const publishUser: () => Promise<void> = async () => {
return await new Promise<void>((resolve) => {
if (publicKey && relayPool) {
relayPool
?.sendEvent({
content: JSON.stringify({
name,
about,
lud06: lnurl,
lud16: lnAddress,
nip05,
picture,
}),
created_at: getUnixTime(new Date()),
kind: Kind.Metadata,
pubkey: publicKey,
tags: [],
})
.then(() => resolve())
sendEvent({
content: JSON.stringify({
name,
about,
lud06: lnurl,
lud16: lnAddress,
nip05,
picture,
}),
created_at: getUnixTime(new Date()),
kind: Kind.Metadata,
pubkey: publicKey,
tags: [],
}).then(() => resolve())
} else {
resolve()
}

View File

@ -19,7 +19,7 @@ interface ProfileCreatePageProps {
export const ProfileCreatePage: React.FC<ProfileCreatePageProps> = ({ navigation }) => {
const { t } = useTranslation('common')
const { setPrivateKey, setUserState, publicKey } = useContext(UserContext)
const { createRandomRelays, relayPool, relays } = useContext(RelayPoolContext)
const { createRandomRelays, sendEvent, relays } = useContext(RelayPoolContext)
const [key, setKey] = useState<string>()
const [inputValue, setInputValue] = useState<string>()
const [keyboardShow, setKeyboardShow] = useState<boolean>(false)
@ -73,7 +73,7 @@ export const ProfileCreatePage: React.FC<ProfileCreatePageProps> = ({ navigation
pubkey: publicKey,
tags: relays.map((relay) => ['r', relay.url, '']),
}
relayPool?.sendEvent(event)
sendEvent(event)
}
if (validConfirmation()) {
setPrivateKey(key)

View File

@ -9,7 +9,10 @@ import { RelayPoolContext } from '../../../Contexts/RelayPoolContext'
import { UserContext } from '../../../Contexts/UserContext'
import { getUsers, type User } from '../../../Functions/DatabaseFunctions/Users'
import { relayToColor } from '../../../Functions/NativeFunctions'
import { getAllRelayMetadata, RelayMetadata } from '../../../Functions/DatabaseFunctions/RelayMetadatas'
import {
getAllRelayMetadata,
RelayMetadata,
} from '../../../Functions/DatabaseFunctions/RelayMetadatas'
import { getContactsRelays } from '../../../Functions/RelayFunctions/Metadata'
interface ThirdStepProps {

View File

@ -80,8 +80,8 @@ export const QrReaderPage: React.FC = () => {
</Text>
</View>
</View>
// ) : (
// NoPermissionsComponent
// ) : (
// NoPermissionsComponent
)
}

View File

@ -37,6 +37,7 @@ export const RelaysPage: React.FC = () => {
updateRelayItem,
addRelayItem,
relayPool,
sendEvent,
setDisplayrelayDrawer,
relays,
lastEventId,
@ -144,7 +145,7 @@ export const RelaysPage: React.FC = () => {
pubkey: publicKey,
tags,
}
relayPool?.sendEvent(event)
sendEvent(event)
}
bottomSheetPushRef.current?.close()
setShowNotification('listPushed')

View File

@ -27,7 +27,7 @@ export const SendPage: React.FC<SendPageProps> = ({ route }) => {
const theme = useTheme()
const { database } = useContext(AppContext)
const { publicKey } = useContext(UserContext)
const { relayPool, lastConfirmationtId } = useContext(RelayPoolContext)
const { sendEvent, lastConfirmationtId } = useContext(RelayPoolContext)
const { t } = useTranslation('common')
// state
const [content, setContent] = useState<string>('')
@ -104,7 +104,7 @@ export const SendPage: React.FC<SendPageProps> = ({ route }) => {
pubkey: publicKey,
tags,
}
relayPool?.sendEvent(event).catch(() => {})
sendEvent(event).catch(() => {})
}
}