mirror of
https://github.com/KoalaSat/nostros.git
synced 2024-09-28 22:30:41 +00:00
Merge branch 'main' into dependabot/npm_and_yarn/types/react-native-vector-icons-6.4.13
This commit is contained in:
commit
3d10ae6ae8
50
.github/workflows/notify.yml
vendored
50
.github/workflows/notify.yml
vendored
@ -18,15 +18,47 @@ jobs:
|
||||
go install github.com/fiatjaf/noscl@latest
|
||||
~/go/bin/noscl setprivate '${{ secrets.NOSTROS_PRIVATE_KEY }}'
|
||||
~/go/bin/noscl relay add "wss://brb.io"
|
||||
~/go/bin/noscl relay add "wss://damus.io"
|
||||
~/go/bin/noscl relay add "wss://nostr-pub.wellorder.net"
|
||||
~/go/bin/noscl relay add "wss://nostr.swiss-enigma.ch"
|
||||
~/go/bin/noscl relay add "wss://nostr.onsats.org"
|
||||
~/go/bin/noscl relay add "wss://nostr-pub.semisol.dev"
|
||||
~/go/bin/noscl relay add "wss://nostr.openchain.fr"
|
||||
~/go/bin/noscl relay add "wss://relay.nostr.info"
|
||||
~/go/bin/noscl relay add "wss://nostr.oxtr.dev"
|
||||
~/go/bin/noscl relay add "wss://nostr.ono.re"
|
||||
~/go/bin/noscl relay add "wss://relay.grunch.dev"
|
||||
~/go/bin/noscl relay add "wss://nostr.developer.li"
|
||||
~/go/bin/noscl relay add "wss://nostr.oxtr.dev"
|
||||
~/go/bin/noscl relay add "wss://nostr.swiss-enigma.ch"
|
||||
~/go/bin/noscl relay add "wss://relay.nostr.snblago.com"
|
||||
~/go/bin/noscl relay add "wss://nos.lol"
|
||||
~/go/bin/noscl relay add "wss://relay.austrich.net"
|
||||
~/go/bin/noscl relay add "wss://nostr.cro.social"
|
||||
~/go/bin/noscl relay add "wss://relay.koreus.social"
|
||||
~/go/bin/noscl relay add "wss://spore.ws"
|
||||
~/go/bin/noscl relay add "wss://nostr.web3infra.xyz"
|
||||
~/go/bin/noscl relay add "wss://nostr.snblago.com"
|
||||
~/go/bin/noscl relay add "wss://relay.nostrified.org"
|
||||
~/go/bin/noscl relay add "wss://relay.ryzizub.com"
|
||||
~/go/bin/noscl relay add "wss://relay.wellorder.net"
|
||||
~/go/bin/noscl relay add "wss://nostr.btcmp.com"
|
||||
~/go/bin/noscl relay add "wss://relay.nostromo.social"
|
||||
~/go/bin/noscl relay add "wss://relay.stoner.com"
|
||||
~/go/bin/noscl relay add "wss://nostr.massmux.com"
|
||||
~/go/bin/noscl relay add "wss://nostr.robotesc.ro"
|
||||
~/go/bin/noscl relay add "wss://relay.humanumest.social"
|
||||
~/go/bin/noscl relay add "wss://relay-local.cowdle.gg"
|
||||
~/go/bin/noscl relay add "wss://nostr-2.afarazit.eu"
|
||||
~/go/bin/noscl relay add "wss://nostr.data.haus"
|
||||
~/go/bin/noscl relay add "wss://nostr-pub.wellorder.net"
|
||||
~/go/bin/noscl relay add "wss://nostr.thank.eu"
|
||||
~/go/bin/noscl relay add "wss://relay-dev.cowdle.gg"
|
||||
~/go/bin/noscl relay add "wss://nostrsxz4lbwe-nostr.functions.fnc.fr-par.scw.cloud"
|
||||
~/go/bin/noscl relay add "wss://relay.nostrcheck.me"
|
||||
~/go/bin/noscl relay add "wss://relay.nostrich.de"
|
||||
~/go/bin/noscl relay add "wss://nostr.com.de"
|
||||
~/go/bin/noscl relay add "wss://relay.nostr.scot"
|
||||
~/go/bin/noscl relay add "wss://nostr.8e23.net"
|
||||
~/go/bin/noscl relay add "wss://nostr.mouton.dev"
|
||||
~/go/bin/noscl relay add "wss://nostr.l00p.org"
|
||||
~/go/bin/noscl relay add "wss://nostr.island.network"
|
||||
~/go/bin/noscl relay add "wss://nostr.handyjunky.com"
|
||||
~/go/bin/noscl relay add "wss://relay.valera.co"
|
||||
~/go/bin/noscl relay add "wss://relay.nostr.vet"
|
||||
~/go/bin/noscl relay add "wss://tmp-relay.cesc.trade"
|
||||
~/go/bin/noscl relay add "wss://relay.dwadziesciajeden.pl"
|
||||
~/go/bin/noscl relay add "wss://nostr-1.afarazit.eu"
|
||||
~/go/bin/noscl relay add "wss://lbrygen.xyz"
|
||||
~/go/bin/noscl publish "${{ github.event.release.body }}"
|
||||
|
@ -44,6 +44,7 @@ Nostros chat
|
||||
- [x] Global feed filters and blocked users
|
||||
- [x] Relay colouring
|
||||
- [x] Push events to private relay
|
||||
- [x] Zaps
|
||||
|
||||
# Kudos
|
||||
|
||||
|
@ -139,8 +139,8 @@ android {
|
||||
applicationId "com.nostros"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 51
|
||||
versionName "v0.3.0.4-alpha"
|
||||
versionCode 53
|
||||
versionName "v0.3.0.6-alpha"
|
||||
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
||||
|
||||
if (isNewArchitectureEnabled()) {
|
||||
|
@ -183,7 +183,7 @@ public class Event {
|
||||
String name = parts[0];
|
||||
String domain = parts[1];
|
||||
|
||||
if (!name.matches("^[a-z0-9-_]+$")) return false;
|
||||
if (!name.matches("^[a-zA-Z0-9-_]+$")) return false;
|
||||
|
||||
try {
|
||||
String url = "https://" + domain + "/.well-known/nostr.json?name=" + name;
|
||||
@ -575,6 +575,7 @@ public class Event {
|
||||
values.put("active", 0);
|
||||
values.put("global_feed", 0);
|
||||
values.put("manual", 1);
|
||||
values.put("deleted_at", 0);
|
||||
database.insert("nostros_relays", null, values);
|
||||
} else if (cursor.moveToFirst() && created_at > cursor.getInt(0)) {
|
||||
values.put("updated_at", created_at);
|
||||
|
@ -52,14 +52,17 @@ public class Relay {
|
||||
values.put("url", url);
|
||||
values.put("active", active);
|
||||
values.put("global_feed", globalFeed);
|
||||
values.put("deleted_at", 0);
|
||||
database.replace("nostros_relays", null, values);
|
||||
}
|
||||
|
||||
public void destroy(SQLiteDatabase database) {
|
||||
public void delete(SQLiteDatabase database) {
|
||||
String whereClause = "url = ?";
|
||||
String[] whereArgs = new String[] {
|
||||
url
|
||||
};
|
||||
database.delete ("nostros_relays", whereClause, whereArgs);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("deleted_at", System.currentTimeMillis() / 1000L);
|
||||
database.update ("nostros_relays", values, whereClause, whereArgs);
|
||||
}
|
||||
}
|
||||
|
@ -196,6 +196,9 @@ public class DatabaseModule {
|
||||
" );");
|
||||
database.execSQL("CREATE INDEX nostros_nostros_zaps_zapped_event_id_index ON nostros_zaps(zapped_event_id);");
|
||||
} catch (SQLException e) { }
|
||||
try {
|
||||
database.execSQL("ALTER TABLE nostros_relays ADD COLUMN deleted_at INT DEFAULT 0;");
|
||||
} catch (SQLException e) { }
|
||||
}
|
||||
|
||||
public void saveEvent(JSONObject data, String userPubKey, String relayUrl) throws JSONException {
|
||||
@ -207,13 +210,13 @@ public class DatabaseModule {
|
||||
relay.save(database);
|
||||
}
|
||||
|
||||
public void destroyRelay(Relay relay) {
|
||||
relay.destroy(database);
|
||||
public void deleteRelay(Relay relay) {
|
||||
relay.delete(database);
|
||||
}
|
||||
|
||||
public List<Relay> getRelays(ReactApplicationContext reactContext) {
|
||||
List<Relay> relayList = new ArrayList<>();
|
||||
String query = "SELECT url, active, global_feed FROM nostros_relays;";
|
||||
String query = "SELECT url, active, global_feed FROM nostros_relays WHERE deleted_at = 0 AND active = 1;";
|
||||
@SuppressLint("Recycle") Cursor cursor = database.rawQuery(query, new String[] {});
|
||||
if (cursor.getCount() > 0) {
|
||||
cursor.moveToFirst();
|
||||
|
@ -55,7 +55,7 @@ public class RelayPoolModule extends ReactContextBaseJavaModule {
|
||||
if(url.equals(relay.url)){
|
||||
relay.disconnect();
|
||||
iterator.remove();
|
||||
database.destroyRelay(relay);
|
||||
database.deleteRelay(relay);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { t } from 'i18next'
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import { Dimensions, StyleSheet, View } from 'react-native'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import { IconButton, Snackbar, Text, TouchableRipple } from 'react-native-paper'
|
||||
import Share from 'react-native-share'
|
||||
@ -8,16 +8,28 @@ import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import { getNevent } from '../../lib/nostr/Nip19'
|
||||
import QRCode from 'react-native-qrcode-svg'
|
||||
import { Group } from '../../Functions/DatabaseFunctions/Groups'
|
||||
import { getNoteRelays } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
|
||||
interface GroupShareProps {
|
||||
group: Group
|
||||
}
|
||||
|
||||
export const GroupShare: React.FC<GroupShareProps> = ({ group }) => {
|
||||
const { database } = React.useContext(AppContext)
|
||||
const bottomSheetShareRef = React.useRef<RBSheet>(null)
|
||||
const [qrCode, setQrCode] = React.useState<any>()
|
||||
const [showNotification, setShowNotification] = React.useState<undefined | string>()
|
||||
const nEvent = React.useMemo(() => getNevent(group.id), [group])
|
||||
const [nEvent, setNevent] = React.useState<undefined | string>()
|
||||
|
||||
React.useEffect(() => {
|
||||
if (database && group.id) {
|
||||
getNoteRelays(database, group.id).then((results) => {
|
||||
const urls = results.map((item) => item.relay_url)
|
||||
setNevent(getNevent(group.id, [...new Set(urls)]))
|
||||
})
|
||||
}
|
||||
}, [group, database])
|
||||
|
||||
return (
|
||||
<View style={styles.mainLayout}>
|
||||
@ -37,7 +49,7 @@ export const GroupShare: React.FC<GroupShareProps> = ({ group }) => {
|
||||
<QRCode
|
||||
quietZone={8}
|
||||
value={`nostr:${nEvent}`}
|
||||
size={350}
|
||||
size={Dimensions.get('window').width - 64}
|
||||
logoBorderRadius={50}
|
||||
logoSize={100}
|
||||
logo={{ uri: group?.picture }}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import QRCode from 'react-native-qrcode-svg'
|
||||
import { Linking, StyleSheet, View } from 'react-native'
|
||||
import { Dimensions, Linking, StyleSheet, View } from 'react-native'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
@ -76,7 +76,7 @@ export const LnPreview: React.FC<LnPreviewProps> = ({
|
||||
<Card style={styles.qrContainer}>
|
||||
<Card.Content>
|
||||
<View style={styles.qr}>
|
||||
<QRCode value={invoice} size={300} quietZone={8} />
|
||||
<QRCode value={invoice} quietZone={8} size={Dimensions.get('window').width - 64} />
|
||||
</View>
|
||||
<View style={styles.qrText}>
|
||||
<Text>{decodedLnUrl?.satoshis} </Text>
|
||||
|
185
frontend/Components/NoteActions/index.tsx
Normal file
185
frontend/Components/NoteActions/index.tsx
Normal file
@ -0,0 +1,185 @@
|
||||
import { t } from 'i18next'
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, TouchableNativeFeedback, View } from 'react-native'
|
||||
import { IconButton, Text, useTheme } from 'react-native-paper'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import { getNoteRelays, getNotes, Note, NoteRelay } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import NoteShare from '../NoteShare'
|
||||
import { navigate } from '../../lib/Navigation'
|
||||
import { relayToColor } from '../../Functions/NativeFunctions'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { formatId } from '../../Functions/RelayFunctions/Users'
|
||||
|
||||
interface NoteActionsProps {
|
||||
bottomSheetRef: React.RefObject<RBSheet>
|
||||
}
|
||||
|
||||
export const NoteActions: React.FC<NoteActionsProps> = ({ bottomSheetRef }) => {
|
||||
const theme = useTheme()
|
||||
const { database, displayNoteDrawer, relayColouring } = React.useContext(AppContext)
|
||||
const { setDisplayrelayDrawer, lastEventId } = React.useContext(RelayPoolContext)
|
||||
const [note, setNote] = React.useState<Note>()
|
||||
const [relays, setRelays] = React.useState<NoteRelay[]>([])
|
||||
const bottomSheetShareRef = React.useRef<RBSheet>(null)
|
||||
|
||||
React.useEffect(() => {
|
||||
loadNote()
|
||||
}, [displayNoteDrawer, lastEventId])
|
||||
|
||||
const loadNote: () => void = () => {
|
||||
if (database && displayNoteDrawer) {
|
||||
getNotes(database, { filters: { id: displayNoteDrawer } }).then((results) => {
|
||||
if (results.length > 0) {
|
||||
setNote(results[0])
|
||||
}
|
||||
})
|
||||
getNoteRelays(database, displayNoteDrawer).then(setRelays)
|
||||
}
|
||||
}
|
||||
|
||||
const bottomSheetStyles = React.useMemo(() => {
|
||||
return {
|
||||
container: {
|
||||
backgroundColor: theme.colors.background,
|
||||
paddingTop: 16,
|
||||
paddingRight: 16,
|
||||
paddingBottom: 32,
|
||||
paddingLeft: 16,
|
||||
borderTopRightRadius: 28,
|
||||
borderTopLeftRadius: 28,
|
||||
height: 'auto',
|
||||
},
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text variant='titleMedium'>{formatId(note?.id)}</Text>
|
||||
<View style={styles.mainLayout}>
|
||||
<View style={styles.actionButton}>
|
||||
<IconButton
|
||||
icon='eye'
|
||||
size={28}
|
||||
onPress={() => {
|
||||
bottomSheetRef.current?.close()
|
||||
navigate('Note', { noteId: note?.id })
|
||||
}}
|
||||
/>
|
||||
<Text>{t('noteActions.view')}</Text>
|
||||
</View>
|
||||
<View style={styles.actionButton}>
|
||||
<IconButton
|
||||
icon='content-copy'
|
||||
size={28}
|
||||
onPress={() => {
|
||||
note?.content && Clipboard.setString(note?.content)
|
||||
bottomSheetRef.current?.close()
|
||||
}}
|
||||
/>
|
||||
<Text>{t('noteActions.copy')}</Text>
|
||||
</View>
|
||||
<View style={styles.actionButton}>
|
||||
<IconButton
|
||||
icon='share-variant-outline'
|
||||
size={28}
|
||||
onPress={() => bottomSheetShareRef.current?.open()}
|
||||
/>
|
||||
<Text>{t('noteActions.share')}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.relayList}>
|
||||
{relayColouring &&
|
||||
relays.map((relay, index) => (
|
||||
<TouchableNativeFeedback
|
||||
onPress={() => setDisplayrelayDrawer(relay.relay_url)}
|
||||
key={relay.relay_url}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.relay,
|
||||
{ backgroundColor: relayToColor(relay.relay_url) },
|
||||
index === 0 ? { borderBottomLeftRadius: 50, borderTopLeftRadius: 50 } : {},
|
||||
index === relays.length - 1
|
||||
? { borderBottomRightRadius: 50, borderTopRightRadius: 50 }
|
||||
: {},
|
||||
]}
|
||||
/>
|
||||
</TouchableNativeFeedback>
|
||||
))}
|
||||
</View>
|
||||
{note && (
|
||||
<RBSheet
|
||||
ref={bottomSheetShareRef}
|
||||
closeOnDragDown={true}
|
||||
customStyles={bottomSheetStyles}
|
||||
onClose={() => bottomSheetRef.current?.close()}
|
||||
>
|
||||
<NoteShare note={note} />
|
||||
</RBSheet>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
relayList: {
|
||||
flexDirection: 'row',
|
||||
marginTop: 16,
|
||||
},
|
||||
container: {
|
||||
width: '100%',
|
||||
paddingRight: 16,
|
||||
paddingLeft: 16,
|
||||
},
|
||||
relayColor: {
|
||||
paddingTop: 9,
|
||||
},
|
||||
mainLayout: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
marginTop: 16,
|
||||
marginBottom: 16,
|
||||
},
|
||||
actionButton: {
|
||||
alignItems: 'center',
|
||||
},
|
||||
snackbar: {
|
||||
marginLeft: 16,
|
||||
bottom: 16,
|
||||
},
|
||||
switch: {
|
||||
marginLeft: 32,
|
||||
},
|
||||
listHeader: {
|
||||
paddingRight: 5,
|
||||
paddingLeft: 16,
|
||||
textAlign: 'center',
|
||||
},
|
||||
warning: {
|
||||
borderRadius: 4,
|
||||
padding: 16,
|
||||
marginTop: 16,
|
||||
marginBottom: 16,
|
||||
},
|
||||
warningTitle: {
|
||||
marginBottom: 8,
|
||||
},
|
||||
buttonSpacer: {
|
||||
marginTop: 16,
|
||||
marginBottom: 16,
|
||||
},
|
||||
muteContainer: {
|
||||
paddingRight: 16,
|
||||
},
|
||||
relaysList: {
|
||||
maxHeight: '90%',
|
||||
},
|
||||
relay: {
|
||||
flex: 1,
|
||||
height: 10,
|
||||
},
|
||||
})
|
||||
|
||||
export default NoteActions
|
@ -15,8 +15,7 @@ import { t } from 'i18next'
|
||||
import { isContentWarning } from '../../Functions/RelayFunctions/Events'
|
||||
import { Event } from '../../lib/nostr/Events'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import { populateRelay } from '../../Functions/RelayFunctions'
|
||||
import { searchRelays } from '../../Functions/DatabaseFunctions/Relays'
|
||||
import { Relay, searchRelays } from '../../Functions/DatabaseFunctions/Relays'
|
||||
import TextContent from '../../Components/TextContent'
|
||||
import { formatPubKey } from '../../Functions/RelayFunctions/Users'
|
||||
import { getReactions } from '../../Functions/DatabaseFunctions/Reactions'
|
||||
@ -30,6 +29,7 @@ import {
|
||||
TouchableRipple,
|
||||
Chip,
|
||||
Surface,
|
||||
IconButton,
|
||||
} from 'react-native-paper'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import { REGEX_SOCKET_LINK } from '../../Constants/Relay'
|
||||
@ -55,13 +55,11 @@ interface NoteCardProps {
|
||||
showPreview?: boolean
|
||||
showRepostPreview?: boolean
|
||||
numberOfLines?: number
|
||||
copyOnPress?: boolean
|
||||
mode?: 'elevated' | 'outlined' | 'contained'
|
||||
}
|
||||
|
||||
export const NoteCard: React.FC<NoteCardProps> = ({
|
||||
note,
|
||||
copyOnPress = true,
|
||||
showRelayColors = true,
|
||||
showAvatarImage = true,
|
||||
showAnswerData = true,
|
||||
@ -74,9 +72,15 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const { publicKey, privateKey } = React.useContext(UserContext)
|
||||
const { relayPool, lastEventId, setDisplayrelayDrawer } = useContext(RelayPoolContext)
|
||||
const { database, showSensitive, setDisplayUserDrawer, relayColouring, longPressZap } =
|
||||
useContext(AppContext)
|
||||
const { relayPool, lastEventId, addRelayItem } = useContext(RelayPoolContext)
|
||||
const {
|
||||
database,
|
||||
showSensitive,
|
||||
setDisplayUserDrawer,
|
||||
setDisplayNoteDrawer,
|
||||
relayColouring,
|
||||
longPressZap,
|
||||
} = useContext(AppContext)
|
||||
const [relayAdded, setRelayAdded] = useState<boolean>(false)
|
||||
const [positiveReactions, setPositiveReactions] = useState<number>(0)
|
||||
const [negativeReactions, setNegativeReactions] = useState<number>(0)
|
||||
@ -187,7 +191,6 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
||||
onPressUser={(user) => setDisplayUserDrawer(user.id)}
|
||||
showPreview={showPreview}
|
||||
numberOfLines={numberOfLines}
|
||||
copyOnPress={copyOnPress}
|
||||
/>
|
||||
)}
|
||||
{note?.repost_id && (
|
||||
@ -199,7 +202,6 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
||||
showRepostPreview={false}
|
||||
showAction={false}
|
||||
showRelayColors={false}
|
||||
copyOnPress={false}
|
||||
/>
|
||||
) : (
|
||||
<Chip
|
||||
@ -228,15 +230,8 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
||||
}
|
||||
|
||||
const recommendServer: () => JSX.Element = () => {
|
||||
const relayName = note?.content
|
||||
|
||||
const addRelayItem: () => void = () => {
|
||||
if (relayPool && database && publicKey && note) {
|
||||
relayPool.add(note.content, () => {
|
||||
populateRelay(relayPool, database, publicKey)
|
||||
setRelayAdded(true)
|
||||
})
|
||||
}
|
||||
const relay: Relay = {
|
||||
url: note?.content ?? '',
|
||||
}
|
||||
|
||||
return (
|
||||
@ -244,7 +239,7 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
||||
<Card>
|
||||
<Card.Title
|
||||
title={t('noteCard.recommendation')}
|
||||
subtitle={relayName}
|
||||
subtitle={relay.url}
|
||||
left={(props) => (
|
||||
<Avatar.Icon
|
||||
{...props}
|
||||
@ -257,7 +252,7 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
||||
/>
|
||||
{!relayAdded && note && REGEX_SOCKET_LINK.test(note.content) && (
|
||||
<Card.Content style={[styles.bottomActions, { borderColor: theme.colors.onSecondary }]}>
|
||||
<Button mode='contained' onPress={addRelayItem}>
|
||||
<Button mode='contained' onPress={async () => await addRelayItem(relay)}>
|
||||
{t('noteCard.addRelay')}
|
||||
</Button>
|
||||
</Card.Content>
|
||||
@ -404,6 +399,7 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
||||
return note ? (
|
||||
<Card mode={mode}>
|
||||
<Card.Content style={styles.title}>
|
||||
<View>
|
||||
<TouchableRipple onPress={() => setDisplayUserDrawer(note.pubkey)}>
|
||||
<ProfileData
|
||||
username={note?.name}
|
||||
@ -416,6 +412,14 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
||||
timestamp={note?.created_at}
|
||||
/>
|
||||
</TouchableRipple>
|
||||
</View>
|
||||
<View style={styles.noteOptionsIcon}>
|
||||
<IconButton
|
||||
icon='dots-vertical'
|
||||
size={28}
|
||||
onPress={() => setDisplayNoteDrawer(note.id)}
|
||||
/>
|
||||
</View>
|
||||
</Card.Content>
|
||||
{getNoteContent()}
|
||||
{showAction && (
|
||||
@ -478,14 +482,11 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
||||
{relayColouring &&
|
||||
showRelayColors &&
|
||||
relays.map((relay, index) => (
|
||||
<TouchableNativeFeedback
|
||||
onPress={() => setDisplayrelayDrawer(relay.relay_url)}
|
||||
key={relay.relay_url}
|
||||
>
|
||||
<TouchableNativeFeedback key={relay.relay_url}>
|
||||
<View
|
||||
style={[
|
||||
styles.relay,
|
||||
{ backgroundColor: relayToColor(relay.relay_url) },
|
||||
{ borderBottomColor: relayToColor(relay.relay_url) },
|
||||
index === 0 ? { borderBottomLeftRadius: 50 } : {},
|
||||
index === relays.length - 1 ? { borderBottomRightRadius: 50 } : {},
|
||||
]}
|
||||
@ -502,7 +503,7 @@ export const NoteCard: React.FC<NoteCardProps> = ({
|
||||
const styles = StyleSheet.create({
|
||||
relayList: {
|
||||
flexDirection: 'row',
|
||||
marginTop: 8,
|
||||
bottom: 2,
|
||||
marginBottom: -16,
|
||||
marginLeft: -16,
|
||||
marginRight: -16,
|
||||
@ -510,6 +511,7 @@ const styles = StyleSheet.create({
|
||||
relay: {
|
||||
flex: 1,
|
||||
height: 10,
|
||||
borderBottomWidth: 2,
|
||||
},
|
||||
titleUsername: {
|
||||
fontWeight: 'bold',
|
||||
@ -529,6 +531,7 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
title: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
paddingBottom: 16,
|
||||
},
|
||||
userBlockedWrapper: {
|
||||
@ -580,6 +583,16 @@ const styles = StyleSheet.create({
|
||||
paddingTop: 4,
|
||||
paddingLeft: 5,
|
||||
},
|
||||
snackbar: {
|
||||
marginBottom: 50,
|
||||
marginLeft: 0,
|
||||
width: '100%',
|
||||
},
|
||||
noteOptionsIcon: {
|
||||
marginBottom: -16,
|
||||
marginRight: -16,
|
||||
marginTop: -8,
|
||||
},
|
||||
})
|
||||
|
||||
export default NoteCard
|
||||
|
111
frontend/Components/NoteShare/index.tsx
Normal file
111
frontend/Components/NoteShare/index.tsx
Normal file
@ -0,0 +1,111 @@
|
||||
import { t } from 'i18next'
|
||||
import * as React from 'react'
|
||||
import { Dimensions, StyleSheet, View } from 'react-native'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import { IconButton, Snackbar, Text, TouchableRipple } from 'react-native-paper'
|
||||
import Share from 'react-native-share'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import QRCode from 'react-native-qrcode-svg'
|
||||
import { useContext } from 'react'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { getNoteRelays, Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { getNevent } from '../../lib/nostr/Nip19'
|
||||
|
||||
interface NoteShareProps {
|
||||
note: Note
|
||||
}
|
||||
|
||||
export const NoteShare: React.FC<NoteShareProps> = ({ note }) => {
|
||||
const { database } = useContext(AppContext)
|
||||
const bottomSheetShareRef = React.useRef<RBSheet>(null)
|
||||
const [qrCode, setQrCode] = React.useState<any>()
|
||||
const [showNotification, setShowNotification] = React.useState<undefined | string>()
|
||||
const [nEvent, setNevent] = React.useState<undefined | string>()
|
||||
|
||||
React.useEffect(() => {
|
||||
if (database && note.id) {
|
||||
getNoteRelays(database, note.id).then((results) => {
|
||||
const urls = results.map((item) => item.relay_url)
|
||||
setNevent(getNevent(note.id, [...new Set(urls)]))
|
||||
})
|
||||
}
|
||||
}, [note, database])
|
||||
|
||||
return (
|
||||
<View style={styles.mainLayout}>
|
||||
<View style={styles.qr}>
|
||||
<TouchableRipple
|
||||
onPress={() => {
|
||||
if (qrCode) {
|
||||
qrCode.toDataURL((base64: string) => {
|
||||
Share.open({
|
||||
url: `data:image/png;base64,${base64}`,
|
||||
filename: note?.id ?? 'nostrosshare',
|
||||
})
|
||||
})
|
||||
}
|
||||
}}
|
||||
>
|
||||
<QRCode
|
||||
quietZone={8}
|
||||
value={`nostr:${nEvent}`}
|
||||
size={Dimensions.get('window').width - 64}
|
||||
logoBorderRadius={50}
|
||||
logoSize={100}
|
||||
logo={{ uri: note?.picture }}
|
||||
getRef={setQrCode}
|
||||
/>
|
||||
</TouchableRipple>
|
||||
</View>
|
||||
<View style={styles.shareActionButton}>
|
||||
<IconButton
|
||||
icon='key-outline'
|
||||
size={28}
|
||||
onPress={() => {
|
||||
setShowNotification('npubCopied')
|
||||
Clipboard.setString(nEvent ?? '')
|
||||
bottomSheetShareRef.current?.close()
|
||||
}}
|
||||
/>
|
||||
<Text>{t('profileShare.copyNPub')}</Text>
|
||||
</View>
|
||||
{showNotification && (
|
||||
<Snackbar
|
||||
style={styles.snackbar}
|
||||
visible={showNotification !== undefined}
|
||||
duration={Snackbar.DURATION_SHORT}
|
||||
onIconPress={() => setShowNotification(undefined)}
|
||||
onDismiss={() => setShowNotification(undefined)}
|
||||
>
|
||||
{t(`profileShare.notifications.${showNotification}`)}
|
||||
</Snackbar>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
snackbar: {
|
||||
marginBottom: 85,
|
||||
width: '100%',
|
||||
},
|
||||
mainLayout: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
},
|
||||
qr: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: 16,
|
||||
},
|
||||
shareActionButton: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexBasis: '100%',
|
||||
marginBottom: 4,
|
||||
},
|
||||
})
|
||||
|
||||
export default NoteShare
|
@ -277,6 +277,7 @@ export const ProfileActions: React.FC<ProfileActionsProps> = ({
|
||||
closeOnDragDown={true}
|
||||
customStyles={bottomSheetStyles}
|
||||
dragFromTopOnly={true}
|
||||
onClose={() => onActionDone()}
|
||||
>
|
||||
<View>
|
||||
<Text variant='titleLarge'>{t('profileCard.relaysTitle')}</Text>
|
||||
@ -309,10 +310,20 @@ export const ProfileActions: React.FC<ProfileActionsProps> = ({
|
||||
</Snackbar>
|
||||
)}
|
||||
</RBSheet>
|
||||
<RBSheet ref={bottomSheetShareRef} closeOnDragDown={true} customStyles={bottomSheetStyles}>
|
||||
<RBSheet
|
||||
ref={bottomSheetShareRef}
|
||||
closeOnDragDown={true}
|
||||
customStyles={bottomSheetStyles}
|
||||
onClose={() => onActionDone()}
|
||||
>
|
||||
<ProfileShare user={user} />
|
||||
</RBSheet>
|
||||
<RBSheet ref={bottomSheetMuteRef} closeOnDragDown={true} customStyles={bottomSheetStyles}>
|
||||
<RBSheet
|
||||
ref={bottomSheetMuteRef}
|
||||
closeOnDragDown={true}
|
||||
customStyles={bottomSheetStyles}
|
||||
onClose={() => onActionDone()}
|
||||
>
|
||||
<View style={styles.muteContainer}>
|
||||
<Text variant='titleLarge'>
|
||||
{t('profileCard.muteUser', { username: username(user) })}
|
||||
|
@ -60,12 +60,9 @@ export const ProfileData: React.FC<ProfileCardProps> = ({
|
||||
<></>
|
||||
)}
|
||||
</View>
|
||||
<Text numberOfLines={1}>{validNip05 ? getNip05Domain(nip05) : ''}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.right}>
|
||||
<View style={styles.date}>
|
||||
<Text numberOfLines={1}>{date ?? ''}</Text>
|
||||
<Text numberOfLines={1}>
|
||||
{timestamp ? date : validNip05 ? getNip05Domain(nip05) : ''}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@ -73,14 +70,8 @@ export const ProfileData: React.FC<ProfileCardProps> = ({
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
right: {
|
||||
flexDirection: 'row',
|
||||
width: '50%',
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
left: {
|
||||
flexDirection: 'row',
|
||||
width: '50%',
|
||||
},
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
|
@ -40,7 +40,7 @@ interface RelayCardProps {
|
||||
export const RelayCard: React.FC<RelayCardProps> = ({ url, bottomSheetRef }) => {
|
||||
const theme = useTheme()
|
||||
const { publicKey } = React.useContext(UserContext)
|
||||
const { updateRelayItem, relayPool, removeRelayItem, sendRelays, relays } =
|
||||
const { updateRelayItem, relayPool, removeRelayItem, sendRelays } =
|
||||
React.useContext(RelayPoolContext)
|
||||
const { database } = React.useContext(AppContext)
|
||||
const [relay, setRelay] = React.useState<Relay>()
|
||||
@ -57,7 +57,7 @@ export const RelayCard: React.FC<RelayCardProps> = ({ url, bottomSheetRef }) =>
|
||||
|
||||
React.useEffect(() => {
|
||||
loadRelay()
|
||||
}, [])
|
||||
}, [url])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (pushUserHistoric && url && database && publicKey && relayPool) {
|
||||
@ -103,7 +103,7 @@ export const RelayCard: React.FC<RelayCardProps> = ({ url, bottomSheetRef }) =>
|
||||
relayPool.sendEvent(group, url)
|
||||
})
|
||||
})
|
||||
sendRelays(relays, url)
|
||||
sendRelays(url)
|
||||
}
|
||||
}, [pushUserHistoric])
|
||||
|
||||
@ -133,9 +133,8 @@ export const RelayCard: React.FC<RelayCardProps> = ({ url, bottomSheetRef }) =>
|
||||
|
||||
const removeRelay: () => void = () => {
|
||||
if (relay) {
|
||||
removeRelayItem(relay).then(() => {
|
||||
removeRelayItem(relay)
|
||||
bottomSheetRef.current?.close()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@ import { Avatar, Card, Text, useTheme } from 'react-native-paper'
|
||||
import { getNip19Key, getNpub } from '../../lib/nostr/Nip19'
|
||||
import { navigate } from '../../lib/Navigation'
|
||||
import { validBlueBirdUrl, validImageUrl, validMediaUrl } from '../../Functions/NativeFunctions'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { decode, PaymentRequestObject, TagsObject } from 'bolt11'
|
||||
@ -22,7 +21,6 @@ interface TextContentProps {
|
||||
showPreview?: boolean
|
||||
onPressUser?: (user: User) => void
|
||||
numberOfLines?: number
|
||||
copyOnPress?: boolean
|
||||
}
|
||||
|
||||
export const TextContent: React.FC<TextContentProps> = ({
|
||||
@ -31,7 +29,6 @@ export const TextContent: React.FC<TextContentProps> = ({
|
||||
showPreview = true,
|
||||
onPressUser = () => {},
|
||||
numberOfLines,
|
||||
copyOnPress = true,
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const { t } = useTranslation('common')
|
||||
@ -267,8 +264,8 @@ export const TextContent: React.FC<TextContentProps> = ({
|
||||
},
|
||||
]}
|
||||
childrenProps={{ allowFontScaling: false }}
|
||||
onLongPress={copyOnPress ? () => Clipboard.setString(text) : undefined}
|
||||
numberOfLines={numberOfLines}
|
||||
selectable
|
||||
>
|
||||
{text}
|
||||
</ParsedText>
|
||||
|
@ -35,6 +35,8 @@ export interface AppContextProps {
|
||||
checkClipboard: () => void
|
||||
displayUserDrawer?: string
|
||||
setDisplayUserDrawer: (displayUserDrawer: string | undefined) => void
|
||||
displayNoteDrawer?: string
|
||||
setDisplayNoteDrawer: (displayNoteDrawer: string | undefined) => void
|
||||
refreshBottomBarAt?: number
|
||||
setRefreshBottomBarAt: (refreshBottomBarAt: number) => void
|
||||
longPressZap?: number | undefined
|
||||
@ -78,6 +80,7 @@ export const initialAppContext: AppContextProps = {
|
||||
getSatoshiSymbol: () => <></>,
|
||||
setClipboardNip21: () => {},
|
||||
setDisplayUserDrawer: () => {},
|
||||
setDisplayNoteDrawer: () => {},
|
||||
longPressZap: undefined,
|
||||
setLongPressZap: () => {},
|
||||
}
|
||||
@ -105,6 +108,7 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E
|
||||
const [clipboardLoads, setClipboardLoads] = React.useState<string[]>([])
|
||||
const [clipboardNip21, setClipboardNip21] = React.useState<string>()
|
||||
const [displayUserDrawer, setDisplayUserDrawer] = React.useState<string>()
|
||||
const [displayNoteDrawer, setDisplayNoteDrawer] = React.useState<string>()
|
||||
const [pushedTab, setPushedTab] = useState<string>()
|
||||
|
||||
useEffect(() => {
|
||||
@ -238,6 +242,8 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E
|
||||
setPushedTab,
|
||||
longPressZap,
|
||||
setLongPressZap,
|
||||
displayNoteDrawer,
|
||||
setDisplayNoteDrawer,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
@ -7,7 +7,7 @@ import { getActiveRelays, getRelays, Relay } from '../Functions/DatabaseFunction
|
||||
import { UserContext } from './UserContext'
|
||||
import { randomInt } from '../Functions/NativeFunctions'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import { Event } from '../../lib/nostr/Events'
|
||||
import { Event } from '../lib/nostr/Events'
|
||||
|
||||
export interface RelayPoolContextProps {
|
||||
relayPoolReady: boolean
|
||||
@ -21,7 +21,7 @@ export interface RelayPoolContextProps {
|
||||
addRelayItem: (relay: Relay) => Promise<void>
|
||||
removeRelayItem: (relay: Relay) => Promise<void>
|
||||
updateRelayItem: (relay: Relay) => Promise<void>
|
||||
sendRelays: (relays: Relay[], url?: string) => Promise<void>
|
||||
sendRelays: (url?: string) => Promise<void>
|
||||
}
|
||||
|
||||
export interface WebsocketEvent {
|
||||
@ -36,12 +36,12 @@ export interface RelayPoolContextProviderProps {
|
||||
export const initialRelayPoolContext: RelayPoolContextProps = {
|
||||
relayPoolReady: true,
|
||||
setRelayPool: () => {},
|
||||
addRelayItem: async () => await new Promise(() => {}),
|
||||
removeRelayItem: async () => await new Promise(() => {}),
|
||||
updateRelayItem: async () => await new Promise(() => {}),
|
||||
addRelayItem: async () => {},
|
||||
removeRelayItem: async () => {},
|
||||
updateRelayItem: async () => {},
|
||||
relays: [],
|
||||
setDisplayrelayDrawer: () => {},
|
||||
sendRelays: () => {},
|
||||
sendRelays: async () => {},
|
||||
}
|
||||
|
||||
export const RelayPoolContextProvider = ({
|
||||
@ -58,17 +58,21 @@ export const RelayPoolContextProvider = ({
|
||||
const [relays, setRelays] = React.useState<Relay[]>([])
|
||||
const [displayRelayDrawer, setDisplayrelayDrawer] = React.useState<string>()
|
||||
|
||||
const sendRelays: (relayList: Relay[], url?: string) => void = (relayList, url) => {
|
||||
if (publicKey && relayList.length > 0) {
|
||||
const sendRelays: (url?: string) => Promise<void> = async (url) => {
|
||||
if (publicKey && database) {
|
||||
getActiveRelays(database).then((results) => {
|
||||
if (publicKey && results.length > 0) {
|
||||
const event: Event = {
|
||||
content: '',
|
||||
created_at: getUnixTime(new Date()),
|
||||
kind: 1002,
|
||||
pubkey: publicKey,
|
||||
tags: relayList.map((relay) => ['r', relay.url, relay.mode ?? '']),
|
||||
tags: results.map((relay) => ['r', relay.url, relay.mode ?? '']),
|
||||
}
|
||||
url ? relayPool?.sendEvent(event, url) : relayPool?.sendEvent(event)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const changeEventIdHandler: (event: WebsocketEvent) => void = (event) => {
|
||||
@ -79,11 +83,11 @@ export const RelayPoolContextProvider = ({
|
||||
}
|
||||
|
||||
const debouncedEventIdHandler = useMemo(
|
||||
() => debounce(changeEventIdHandler, 1000),
|
||||
() => debounce(changeEventIdHandler, 250),
|
||||
[setLastEventId],
|
||||
)
|
||||
const debouncedConfirmationHandler = useMemo(
|
||||
() => debounce(changeConfirmationIdHandler, 500),
|
||||
() => debounce(changeConfirmationIdHandler, 250),
|
||||
[setLastConfirmationId],
|
||||
)
|
||||
|
||||
@ -146,8 +150,8 @@ export const RelayPoolContextProvider = ({
|
||||
return await new Promise((resolve, _reject) => {
|
||||
if (relayPool && database && publicKey) {
|
||||
relayPool.add(relay.url, () => {
|
||||
loadRelays().then((results) => {
|
||||
sendRelays(results)
|
||||
loadRelays().then(() => {
|
||||
sendRelays()
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
@ -160,8 +164,8 @@ export const RelayPoolContextProvider = ({
|
||||
return await new Promise((resolve, _reject) => {
|
||||
if (relayPool && database && publicKey) {
|
||||
relayPool.remove(relay.url, () => {
|
||||
loadRelays().then((results) => {
|
||||
sendRelays(results)
|
||||
loadRelays().then(() => {
|
||||
sendRelays()
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
@ -31,7 +31,7 @@ export const searchRelays: (
|
||||
relayUrl: string,
|
||||
db: QuickSQLiteConnection,
|
||||
) => Promise<Relay[]> = async (relayUrl, db) => {
|
||||
const searchQuery = `SELECT * FROM nostros_relays WHERE url = '${relayUrl}';`
|
||||
const searchQuery = `SELECT * FROM nostros_relays WHERE url = '${relayUrl}' AND deleted_at = 0;`
|
||||
const results = await db.execute(searchQuery)
|
||||
const items: object[] = getItems(results)
|
||||
const relays: Relay[] = items.map((object) => databaseToEntity(object))
|
||||
@ -39,7 +39,7 @@ export const searchRelays: (
|
||||
}
|
||||
|
||||
export const getRelays: (db: QuickSQLiteConnection) => Promise<Relay[]> = async (db) => {
|
||||
const notesQuery = 'SELECT * FROM nostros_relays;'
|
||||
const notesQuery = 'SELECT * FROM nostros_relays WHERE deleted_at = 0;'
|
||||
const resultSet = await db.execute(notesQuery)
|
||||
const items: object[] = getItems(resultSet)
|
||||
const relays: Relay[] = items.map((object) => databaseToEntity(object))
|
||||
@ -47,7 +47,7 @@ export const getRelays: (db: QuickSQLiteConnection) => Promise<Relay[]> = async
|
||||
}
|
||||
|
||||
export const getActiveRelays: (db: QuickSQLiteConnection) => Promise<Relay[]> = async (db) => {
|
||||
const notesQuery = 'SELECT * FROM nostros_relays WHERE active = 1;'
|
||||
const notesQuery = 'SELECT * FROM nostros_relays WHERE active = 1 AND deleted_at = 0;'
|
||||
const resultSet = await db.execute(notesQuery)
|
||||
const items: object[] = getItems(resultSet)
|
||||
const relays: Relay[] = items.map((object) => databaseToEntity(object))
|
||||
@ -58,23 +58,13 @@ export const getRelay: (db: QuickSQLiteConnection, url: string) => Promise<Relay
|
||||
db,
|
||||
url,
|
||||
) => {
|
||||
const notesQuery = 'SELECT * FROM nostros_relays WHERE url = ?;'
|
||||
const notesQuery = 'SELECT * FROM nostros_relays WHERE url = ? AND deleted_at = 0;'
|
||||
const resultSet = await db.execute(notesQuery, [url])
|
||||
const items: object[] = getItems(resultSet)
|
||||
const relays: Relay[] = items.map((object) => databaseToEntity(object))
|
||||
return relays[0]
|
||||
}
|
||||
|
||||
export const createRelay: (db: QuickSQLiteConnection, url: string) => Promise<QueryResult> = async (
|
||||
db,
|
||||
url,
|
||||
) => {
|
||||
const query = `
|
||||
INSERT OR IGNORE INTO nostros_relays (url) VALUES (?)
|
||||
`
|
||||
return db.execute(query, [url])
|
||||
}
|
||||
|
||||
export const createResilientRelay: (
|
||||
db: QuickSQLiteConnection,
|
||||
url: string,
|
||||
|
@ -1,12 +0,0 @@
|
||||
import RelayPool from '../../lib/nostr/RelayPool/intex'
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { populatePets, populateProfile } from './Users'
|
||||
|
||||
export const populateRelay: (
|
||||
relayPool: RelayPool,
|
||||
database: QuickSQLiteConnection,
|
||||
publicKey: string,
|
||||
) => void = (relayPool, database, publicKey) => {
|
||||
populateProfile(relayPool, database, publicKey)
|
||||
populatePets(relayPool, database, publicKey)
|
||||
}
|
@ -86,14 +86,22 @@
|
||||
"app": "App",
|
||||
"feed": "Feed",
|
||||
"zaps": "Zaps",
|
||||
"disabled": "Disabled",
|
||||
"longPressZap": "Long press Zaps",
|
||||
"longPressZapDescription": "Define a default amount to automatically generate invoices after a long press on the Zap button.",
|
||||
"defaultZapAmount": "Defaul Zap amount",
|
||||
"update": "Update",
|
||||
"disable": "Disable"
|
||||
"disabled": "deaktiviert",
|
||||
"longPressZap": "Zaps lange drücken",
|
||||
"longPressZapDescription": "Lege den voreingestellten Betrag fest, mit der Invoices erstellt werden sollen, wenn Zaps lange gedrückt wird.",
|
||||
"defaultZapAmount": "Standard Zap Betrag",
|
||||
"update": "Aktualisieren",
|
||||
"disable": "Deaktivieren"
|
||||
},
|
||||
"noteActions": {
|
||||
"copy": "Kopieren",
|
||||
"share": "Teilen",
|
||||
"view": "Ansehen"
|
||||
},
|
||||
"noteCard": {
|
||||
"notifications": {
|
||||
"zapServerError": "Beim Anfragen des Invoice hat es einen Fehler vom Server gegeben."
|
||||
},
|
||||
"answering": "{{pubkey}} antworten",
|
||||
"reposting": "{{pubkey}} reposten",
|
||||
"seeParent": "Notiz ansehen",
|
||||
@ -110,7 +118,7 @@
|
||||
"cancel": "Abbrechen",
|
||||
"copy": "Kopieren",
|
||||
"open": "Öffne Wallet",
|
||||
"anonTip": "Anonymous tip",
|
||||
"anonTip": "Anonymer Tip",
|
||||
"zap": "Zap"
|
||||
},
|
||||
"notificationsFeed": {
|
||||
@ -210,9 +218,9 @@
|
||||
"resilienceCategoriesDescription": "Ein erster Ansatz, den Nostros testet, ist die zufällige Berechnung (auf der Grundlage der empfangenen Kontaktereignisse), welche Relays am ausgewogensten sind. Dabei wird versucht, sowohl Relays mit zu vielen Ereignissen (Zentralisierung) als auch Relays mit fast keinen Ereignissen (Akkuentladung) zu vermeiden\n\nEs ist das Ziel, eine Liste von 5 Relays zu erstellen, die alle Kontakte abdeckt. Sollte dies jedoch nicht möglich sein, wird Nostros unter anderen Relays suchen und den Benutzer darüber warnen.",
|
||||
"centralized": "Zentralisiert",
|
||||
"small": "Klein",
|
||||
"contacts": "# Kontakte",
|
||||
"contacts": "zugewiesene Kontakte",
|
||||
"resilienceMode": "Beständigkeit (experimental)",
|
||||
"relayName": "Addresse",
|
||||
"relayName": "Adresse",
|
||||
"globalFeed": "Globaler Feed",
|
||||
"active": "Aktiv",
|
||||
"labelAdd": "Beschreibung des Relays",
|
||||
@ -233,7 +241,6 @@
|
||||
"alreadyExists": "Relay existiert bereits"
|
||||
}
|
||||
},
|
||||
|
||||
"relayCard": {
|
||||
"pushDone": "Fertig",
|
||||
"pushHistoricTitle": "Alle meine Daten hochladen",
|
||||
@ -241,7 +248,7 @@
|
||||
"pushHistoricAlertTitle": "Wichtig!",
|
||||
"pushHistoricAlert": "Öffentliche Relays haben strenge Anti-Spam Regeln, diese Aktion kann dein Profil sperren oder verbannen. Stelle zuvor sicher, das du große Datenmengen auf diesen Relay schieben darfst.\n\nWir empfehlen, dieses Feature ausschlisslich für private Relays zu benutzen, wie z.B. Umbrel's Nostr Relay.",
|
||||
"pushConsent": "Ich schiebe meine Daten auf einen privaten Relay",
|
||||
"pushingEvent": "Event {{eventId}} pushed",
|
||||
"pushingEvent": "Event {{eventId}} hochgeladen",
|
||||
"pushRelay": "Alle meine Daten hochladen",
|
||||
"cancel": "Abbrechen",
|
||||
"moreInfo": "Mehr Infos",
|
||||
@ -266,10 +273,9 @@
|
||||
"pubkeyCopied": "Öffentlichen Schlüssel kopiert.",
|
||||
"contactCopied": "Kontakt kopiert.",
|
||||
"urlCopied": "URL kopiert.",
|
||||
"pushCompleted": "All your data has been pushed."
|
||||
"pushCompleted": "Alle deine Daten wurden hochgeladen"
|
||||
}
|
||||
},
|
||||
|
||||
"profileConfigPage": {
|
||||
"notifications": {
|
||||
"nsecCopied": "Privater Schlüssel kopiert.",
|
||||
@ -318,7 +324,7 @@
|
||||
"active": "Relay aktiviert.",
|
||||
"desactive": "Relay deaktiviert."
|
||||
},
|
||||
"invoice": "Zap",
|
||||
"invoice": "Tip",
|
||||
"message": "Nachricht",
|
||||
"follow": "Folgen",
|
||||
"isFollower": "folgt dir",
|
||||
@ -327,15 +333,15 @@
|
||||
"relaysDescription": "Dies sind {{username}}'s Relays, aktiviere diejenigen, zu denen du verbunden werden möchtest."
|
||||
},
|
||||
"groupPage": {
|
||||
"typeMessage": "Nachricht schreiben"
|
||||
"typeMessage": "Nachricht schreiben",
|
||||
"replyText": "Nachricht"
|
||||
},
|
||||
"groupHeaderIcon": {
|
||||
"delete": "Leave group",
|
||||
"share": "Share group",
|
||||
"edit": "Edit group"
|
||||
"delete": "Gruppe verlassen",
|
||||
"share": "Gruppe teilen",
|
||||
"edit": "Gruppe editieren"
|
||||
},
|
||||
"groupsFeed": {
|
||||
"delete": "Gruppe verlassen",
|
||||
"updateTitle": "Gruppe aktualisieren",
|
||||
"newGroupName": "Name",
|
||||
"newGroupDescription": "Beschreibung",
|
||||
@ -345,7 +351,8 @@
|
||||
"createTitle": "Gruppe erstellen",
|
||||
"groupId": "Gruppen ID",
|
||||
"addTitle": "Bestehende Gruppe hinzufügen",
|
||||
"add": "Gruppe hinzufügen"
|
||||
"add": "Gruppe hinzufügen",
|
||||
"delete": "Gruppe löschen"
|
||||
},
|
||||
"homePage": {
|
||||
"clipboardTitle": "Nostr Schlüssel entdeckt",
|
||||
@ -368,7 +375,6 @@
|
||||
"copyNip05": "NIP-05 kopieren",
|
||||
"copyNPub": "Schlüssel kopieren"
|
||||
},
|
||||
|
||||
"profileCard": {
|
||||
"notifications": {
|
||||
"contactAdded": "Aboniert",
|
||||
@ -376,7 +382,7 @@
|
||||
"userUnblocked": "Profil entblockt",
|
||||
"userBlocked": "Profile geblockt"
|
||||
},
|
||||
"invoice": "Zap",
|
||||
"invoice": "Tip",
|
||||
"message": "Nachricht",
|
||||
"follow": "Folgen",
|
||||
"block": "Blockieren",
|
||||
@ -384,9 +390,14 @@
|
||||
"unblock": "Erlauben",
|
||||
"unfollow": "Abo entfernen",
|
||||
"relaysTitle": "Relays",
|
||||
"blocked": "Blocked",
|
||||
"mute": "Mute",
|
||||
"muted": "Muted"
|
||||
"blocked": "Blockiert",
|
||||
"mute": "Stumm",
|
||||
"muted": "Stumm",
|
||||
"muteUser": "{{username}} in Chats stumm schalten",
|
||||
"muteWarningTitle": "Wichtig",
|
||||
"muteWarning": "Diese Aktion wird Nachrichten dieses Benutzers in allen Chats unwiderruflich verstecken und kann nicht rückgängig gemacht werden.",
|
||||
"muteForever": "{{username}} für immer stumm schalten",
|
||||
"cancel": "Abbrechen"
|
||||
},
|
||||
"conversationsFeed": {
|
||||
"openMessage": "Unterhaltung beginnen",
|
||||
|
@ -89,11 +89,19 @@
|
||||
"disabled": "Disabled",
|
||||
"longPressZap": "Long press Zaps",
|
||||
"longPressZapDescription": "Define a default amount to automatically generate invoices after a long press on the Zap button.",
|
||||
"defaultZapAmount": "Defaul Zap amount",
|
||||
"defaultZapAmount": "Default Zap amount",
|
||||
"update": "Update",
|
||||
"disable": "Disable"
|
||||
},
|
||||
"noteActions": {
|
||||
"copy": "Copy",
|
||||
"share": "Share",
|
||||
"view": "View"
|
||||
},
|
||||
"noteCard": {
|
||||
"notifications": {
|
||||
"zapServerError": "There was an error on the server while trying to request the invoice."
|
||||
},
|
||||
"answering": "Answer to {{pubkey}}",
|
||||
"reposting": "Reposted {{pubkey}}",
|
||||
"userBlocked": "User blocked",
|
||||
@ -127,7 +135,7 @@
|
||||
"skip": "Skip",
|
||||
"confirmTitle": "Type the words in the right order.",
|
||||
"warningTitle": "Important",
|
||||
"warningDescription": "Store your key in a safe place. If lose it, you won't be able to access or recover your profile.",
|
||||
"warningDescription": "Store your key in a safe place. If you lose it, you won't be able to access or recover your profile.",
|
||||
"warningAction": "Copy private key",
|
||||
"continue": "Continue",
|
||||
"mnemonicTitle": "These words or your private key are the only way to recover your account.",
|
||||
|
@ -114,7 +114,15 @@
|
||||
"update": "Actualizar",
|
||||
"disable": "Desabilitar"
|
||||
},
|
||||
"noteActions": {
|
||||
"copy": "Copiar",
|
||||
"share": "Compartir",
|
||||
"view": "Ver"
|
||||
},
|
||||
"noteCard": {
|
||||
"notifications": {
|
||||
"zapServerError": "Ha ocurrido un error en el servidor mientras se intentaba obtener la factura."
|
||||
},
|
||||
"answering": "Responder a {{pubkey}}",
|
||||
"reposting": "Reposted {{pubkey}}",
|
||||
"seeParent": "Ver nota",
|
||||
|
@ -121,7 +121,15 @@
|
||||
"update": "Update",
|
||||
"disable": "Disable"
|
||||
},
|
||||
"noteActions": {
|
||||
"copy": "Copier",
|
||||
"share": "Partager",
|
||||
"view": "View"
|
||||
},
|
||||
"noteCard": {
|
||||
"notifications": {
|
||||
"zapServerError": "There was an error on the server while trying to request for the invoice."
|
||||
},
|
||||
"answering": "Répondre à {{pubkey}}",
|
||||
"reposting": "Republié {{pubkey}}",
|
||||
"seeParent": "Voir la note",
|
||||
|
@ -114,7 +114,15 @@
|
||||
"update": "Update",
|
||||
"disable": "Disable"
|
||||
},
|
||||
"noteActions": {
|
||||
"copy": "Скопировать",
|
||||
"share": "Поделиться",
|
||||
"view": "View"
|
||||
},
|
||||
"noteCard": {
|
||||
"notifications": {
|
||||
"zapServerError": "There was an error on the server while trying to request for the invoice."
|
||||
},
|
||||
"answering": "Ответить {{pubkey}}",
|
||||
"reposting": "Reposted {{pubkey}}",
|
||||
"seeParent": "See note",
|
||||
|
@ -96,7 +96,7 @@
|
||||
"logout": "退出"
|
||||
},
|
||||
"configPage": {
|
||||
"showPublicImages": "在发现页显示图片",
|
||||
"showPublicImages": "显示发现页图片",
|
||||
"showSensitive": "显示敏感的 Notes",
|
||||
"satoshi": "聪符号",
|
||||
"imageHostingService": "图片托管服务",
|
||||
@ -104,16 +104,24 @@
|
||||
"language": "语言",
|
||||
"relayColoruring": "颜色标示中继状态",
|
||||
"app": "App",
|
||||
"feed": "Feed",
|
||||
"feed": "信息流",
|
||||
"zaps": "Zaps",
|
||||
"disabled": "Disabled",
|
||||
"longPressZap": "Long press Zaps",
|
||||
"longPressZapDescription": "Define a default amount to automatically generate invoices after a long press on the Zap button.",
|
||||
"defaultZapAmount": "Defaul Zap amount",
|
||||
"update": "Update",
|
||||
"disable": "Disable"
|
||||
"disabled": "停用",
|
||||
"longPressZap": "长按 Zaps",
|
||||
"longPressZapDescription": "设置长按 Zap 按钮后自动生成账单的默认金额",
|
||||
"defaultZapAmount": "默认 Zap 金额",
|
||||
"update": "更新",
|
||||
"disable": "停用"
|
||||
},
|
||||
"noteActions": {
|
||||
"copy": "复制",
|
||||
"share": "分享",
|
||||
"view": "查看"
|
||||
},
|
||||
"noteCard": {
|
||||
"notifications": {
|
||||
"zapServerError": "尝试请求收据时服务器出现错误。"
|
||||
},
|
||||
"answering": "回复 {{pubkey}}",
|
||||
"reposting": "已转发 {{pubkey}}",
|
||||
"userBlocked": "用户已屏蔽",
|
||||
@ -130,7 +138,7 @@
|
||||
"npub": "公钥",
|
||||
"copy": "复制",
|
||||
"open": "打开钱包",
|
||||
"anonTip": "Anonymous tip",
|
||||
"anonTip": "匿名赞赏",
|
||||
"zap": "Zap"
|
||||
},
|
||||
"notificationsFeed": {
|
||||
@ -243,7 +251,7 @@
|
||||
"myList": "我的中继",
|
||||
"notifications": {
|
||||
"globalFeedActive": "已为发现页开启",
|
||||
"globalFeedActiveUnactive": "已为发现页禁用",
|
||||
"globalFeedActiveUnactive": "已为发现页停用",
|
||||
"add": "中继已添加",
|
||||
"remove": "中继已移除",
|
||||
"active": "中继已启用",
|
||||
@ -276,7 +284,7 @@
|
||||
"pubkeyCopied": "已复制私钥",
|
||||
"contactCopied": "已复制联系人",
|
||||
"urlCopied": "已复制链接",
|
||||
"pushCompleted": "All your data has been pushed."
|
||||
"pushCompleted": "您的所有数据都已推送"
|
||||
}
|
||||
},
|
||||
"profileConfigPage": {
|
||||
@ -285,7 +293,7 @@
|
||||
"npubCopied": "已复制公钥",
|
||||
"profilePublished": "简介已发布",
|
||||
"lud06Published": "LUDs 已发布",
|
||||
"nip05Published": "NIP-05 已发布 \n\n{{nip05}}",
|
||||
"nip05Published": "NIP-05 已发布\n\n{{nip05}}",
|
||||
"picturePublished": "头像已发布",
|
||||
"connectionError": "连接错误",
|
||||
"active": "中继已启用",
|
||||
@ -331,7 +339,7 @@
|
||||
"unfollow": "关注中",
|
||||
"copyNPub": "复制公钥",
|
||||
"relaysTitle": "中继",
|
||||
"relaysDescription": "以下是{{username}}的中继,您可以激活想要连接的中继"
|
||||
"relaysDescription": "以下是{{username}}的中继,您可以启用想要连接的中继"
|
||||
},
|
||||
"homePage": {
|
||||
"clipboardTitle": "检测到 Nostr 公钥",
|
||||
|
@ -23,15 +23,23 @@ import { getUnixTime } from 'date-fns'
|
||||
import ContactsPage from '../ContactsPage'
|
||||
import GroupPage from '../GroupPage'
|
||||
import GroupHeaderIcon from '../../Components/GroupHeaderIcon'
|
||||
import NoteActions from '../../Components/NoteActions'
|
||||
|
||||
export const HomeNavigator: React.FC = () => {
|
||||
const theme = useTheme()
|
||||
const { t } = useTranslation('common')
|
||||
const { displayRelayDrawer, setDisplayrelayDrawer } = React.useContext(RelayPoolContext)
|
||||
const { displayUserDrawer, setDisplayUserDrawer, setRefreshBottomBarAt, database } =
|
||||
React.useContext(AppContext)
|
||||
const {
|
||||
displayUserDrawer,
|
||||
setDisplayNoteDrawer,
|
||||
displayNoteDrawer,
|
||||
setDisplayUserDrawer,
|
||||
setRefreshBottomBarAt,
|
||||
database,
|
||||
} = React.useContext(AppContext)
|
||||
const bottomSheetRef = React.useRef<RBSheet>(null)
|
||||
const bottomSheetProfileRef = React.useRef<RBSheet>(null)
|
||||
const bottomSheetNoteRef = React.useRef<RBSheet>(null)
|
||||
const bottomSheetRelayRef = React.useRef<RBSheet>(null)
|
||||
const Stack = React.useMemo(() => createStackNavigator(), [])
|
||||
const cardStyleInterpolator = React.useMemo(
|
||||
@ -74,6 +82,10 @@ export const HomeNavigator: React.FC = () => {
|
||||
if (displayRelayDrawer) bottomSheetRelayRef.current?.open()
|
||||
}, [displayRelayDrawer])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (displayNoteDrawer) bottomSheetNoteRef.current?.open()
|
||||
}, [displayNoteDrawer])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (displayUserDrawer) bottomSheetProfileRef.current?.open()
|
||||
}, [displayUserDrawer])
|
||||
@ -172,6 +184,14 @@ export const HomeNavigator: React.FC = () => {
|
||||
>
|
||||
<ProfileCard bottomSheetRef={bottomSheetProfileRef} />
|
||||
</RBSheet>
|
||||
<RBSheet
|
||||
ref={bottomSheetNoteRef}
|
||||
closeOnDragDown={true}
|
||||
customStyles={bottomSheetStyles}
|
||||
onClose={() => setDisplayNoteDrawer(undefined)}
|
||||
>
|
||||
<NoteActions bottomSheetRef={bottomSheetNoteRef} />
|
||||
</RBSheet>
|
||||
<RBSheet
|
||||
ref={bottomSheetRelayRef}
|
||||
closeOnDragDown={true}
|
||||
|
@ -329,8 +329,8 @@ export const GroupPage: React.FC<GroupPageProps> = ({ route }) => {
|
||||
friction={2}
|
||||
overshootRight={false}
|
||||
onSwipeableOpen={() => {
|
||||
setReply(item)
|
||||
row[index].close()
|
||||
setReply(item)
|
||||
}}
|
||||
>
|
||||
<View style={styles.messageRow} key={index}>
|
||||
|
@ -6,24 +6,18 @@ import { useTranslation } from 'react-i18next'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import getUnixTime from 'date-fns/getUnixTime'
|
||||
import { Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { getETags, getTaggedPubKeys } from '../../Functions/RelayFunctions/Events'
|
||||
import { getETags } from '../../Functions/RelayFunctions/Events'
|
||||
import { getUsers, User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { formatPubKey } from '../../Functions/RelayFunctions/Users'
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
Switch,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableRipple,
|
||||
useTheme,
|
||||
} from 'react-native-paper'
|
||||
import { Button, IconButton, Switch, Text, TextInput, useTheme } from 'react-native-paper'
|
||||
import { UserContext } from '../../Contexts/UserContext'
|
||||
import { goBack } from '../../lib/Navigation'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import ProfileData from '../../Components/ProfileData'
|
||||
import NoteCard from '../../Components/NoteCard'
|
||||
import UploadImage from '../../Components/UploadImage'
|
||||
import { useFocusEffect } from '@react-navigation/native'
|
||||
import { TouchableWithoutFeedback } from 'react-native-gesture-handler'
|
||||
|
||||
interface SendPageProps {
|
||||
route: { params: { note: Note; type?: 'reply' | 'repost' } | undefined }
|
||||
@ -38,6 +32,7 @@ export const SendPage: React.FC<SendPageProps> = ({ route }) => {
|
||||
// state
|
||||
const [content, setContent] = useState<string>('')
|
||||
const [contentWarning, setContentWarning] = useState<boolean>(false)
|
||||
const [users, setUsers] = useState<User[]>([])
|
||||
const [userSuggestions, setUserSuggestions] = useState<User[]>([])
|
||||
const [userMentions, setUserMentions] = useState<User[]>([])
|
||||
const [isSending, setIsSending] = useState<boolean>(false)
|
||||
@ -45,26 +40,23 @@ export const SendPage: React.FC<SendPageProps> = ({ route }) => {
|
||||
const [startUpload, setStartUpload] = useState<boolean>(false)
|
||||
const note = React.useMemo(() => route.params?.note, [])
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
if (database) getUsers(database, {}).then(setUsers)
|
||||
|
||||
return () => {}
|
||||
}, []),
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (isSending) goBack()
|
||||
}, [lastConfirmationtId])
|
||||
|
||||
const onChangeText: (text: string) => void = (text) => {
|
||||
const match = text.match(/.*@(.*)$/)
|
||||
const note: Note | undefined = route.params?.note
|
||||
if (database && match && match?.length > 0) {
|
||||
if (match[1] === '' && note) {
|
||||
const taggedPubKeys = getTaggedPubKeys(note)
|
||||
getUsers(database, {
|
||||
includeIds: [...taggedPubKeys, note.pubkey],
|
||||
}).then((results) => {
|
||||
if (results) setUserSuggestions(results.filter((item) => item.id !== publicKey))
|
||||
})
|
||||
} else {
|
||||
getUsers(database, { name: match[1] }).then((results) => {
|
||||
if (results) setUserSuggestions(results.filter((item) => item.id !== publicKey))
|
||||
})
|
||||
}
|
||||
if (database && match && match[1] !== '') {
|
||||
const search = match[1].toLocaleLowerCase()
|
||||
setUserSuggestions(users.filter((item) => item.name?.toLocaleLowerCase()?.includes(search)))
|
||||
} else {
|
||||
setUserSuggestions([])
|
||||
}
|
||||
@ -130,7 +122,7 @@ export const SendPage: React.FC<SendPageProps> = ({ route }) => {
|
||||
}
|
||||
|
||||
const renderContactItem: (item: User, index: number) => JSX.Element = (item, index) => (
|
||||
<TouchableRipple onPress={() => addUserMention(item)}>
|
||||
<TouchableWithoutFeedback onPress={() => addUserMention(item)}>
|
||||
<View key={index} style={styles.contactRow}>
|
||||
<ProfileData
|
||||
username={item?.name}
|
||||
@ -142,12 +134,17 @@ export const SendPage: React.FC<SendPageProps> = ({ route }) => {
|
||||
picture={item?.picture}
|
||||
/>
|
||||
</View>
|
||||
</TouchableRipple>
|
||||
</TouchableWithoutFeedback>
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<View style={[styles.textInputContainer]}>
|
||||
<ScrollView
|
||||
style={[styles.textInputContainer]}
|
||||
keyboardShouldPersistTaps='handled'
|
||||
scrollEnabled={false}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
{note && (
|
||||
<View style={styles.noteCard}>
|
||||
<NoteCard
|
||||
@ -172,10 +169,12 @@ export const SendPage: React.FC<SendPageProps> = ({ route }) => {
|
||||
value={content}
|
||||
onChangeText={onChangeText}
|
||||
scrollEnabled
|
||||
// cursorColor={theme.colors.inverseOnSurface}
|
||||
// selectionColor={theme.colors.inverseOnSurface}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.actions}>
|
||||
</ScrollView>
|
||||
<View>
|
||||
{userSuggestions.length > 0 ? (
|
||||
<View style={[styles.contactsList, { backgroundColor: theme.colors.background }]}>
|
||||
<ScrollView>
|
||||
@ -238,9 +237,7 @@ const styles = StyleSheet.create({
|
||||
bottom: 100,
|
||||
width: '100%',
|
||||
},
|
||||
textInputContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
textInputContainer: {},
|
||||
textInput: {
|
||||
paddingBottom: 0,
|
||||
},
|
||||
@ -253,9 +250,6 @@ const styles = StyleSheet.create({
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
},
|
||||
actions: {
|
||||
zIndex: 999,
|
||||
},
|
||||
contactsList: {
|
||||
bottom: 0,
|
||||
maxHeight: 180,
|
||||
|
@ -35,12 +35,12 @@ export function getNprofile(key: string, relays: string[]): string {
|
||||
return key
|
||||
}
|
||||
|
||||
export function getNevent(key: string | undefined): string {
|
||||
export function getNevent(key: string | undefined, relays: string[]): string {
|
||||
if (!key) return ''
|
||||
if (isPublicKey(key)) return key
|
||||
|
||||
try {
|
||||
return neventEncode({ id: key, relays: [] })
|
||||
return neventEncode({ id: key, relays })
|
||||
} catch {
|
||||
console.log('Error encoding')
|
||||
}
|
||||
|
10
package.json
10
package.json
@ -35,7 +35,7 @@
|
||||
"nostr-tools": "^1.2.1",
|
||||
"react": "18.2.0",
|
||||
"react-content-loader": "^6.2.0",
|
||||
"react-i18next": "^12.1.4",
|
||||
"react-i18next": "^12.1.5",
|
||||
"react-native": "0.70.6",
|
||||
"react-native-action-button": "^2.8.5",
|
||||
"react-native-bidirectional-infinite-scroll": "^0.3.3",
|
||||
@ -44,10 +44,10 @@
|
||||
"react-native-gesture-handler": "^2.8.0",
|
||||
"react-native-image-picker": "^5.0.1",
|
||||
"react-native-multithreading": "^1.1.1",
|
||||
"react-native-pager-view": "^6.1.2",
|
||||
"react-native-pager-view": "^6.1.4",
|
||||
"react-native-paper": "^5.1.3",
|
||||
"react-native-parsed-text": "^0.0.22",
|
||||
"react-native-qrcode-svg": "^6.1.2",
|
||||
"react-native-qrcode-svg": "^6.2.0",
|
||||
"react-native-quick-sqlite": "^7.0.0",
|
||||
"react-native-raw-bottom-sheet": "^2.2.0",
|
||||
"react-native-reanimated": "^2.14.4",
|
||||
@ -73,7 +73,7 @@
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@react-native-community/eslint-config": "^3.2.0",
|
||||
"@types/create-hash": "^1.2.2",
|
||||
"@types/jest": "^29.2.6",
|
||||
"@types/jest": "^29.4.0",
|
||||
"@types/linkify-it": "^3.0.2",
|
||||
"@types/lodash.debounce": "^4.0.7",
|
||||
"@types/react-native": "^0.70.8",
|
||||
@ -95,7 +95,7 @@
|
||||
"eslint-plugin-promise": "^6.1.0",
|
||||
"eslint-plugin-react": "^7.31.11",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"jest": "^29.3.1",
|
||||
"jest": "^29.4.3",
|
||||
"metro-react-native-babel-preset": "^0.75.0",
|
||||
"prettier": "^2.8.4",
|
||||
"react-test-renderer": "18.1.0",
|
||||
|
Loading…
Reference in New Issue
Block a user