mirror of
https://github.com/KoalaSat/nostros.git
synced 2024-09-28 14:20:43 +00:00
Connection to contacts relays
This commit is contained in:
parent
4466d7d80f
commit
42022a5c82
@ -27,6 +27,7 @@ module.exports = {
|
||||
'@typescript-eslint/no-misused-promises': 'off',
|
||||
'@typescript-eslint/restrict-template-expressions': 'off',
|
||||
'@typescript-eslint/restrict-plus-operands': 'off',
|
||||
'@typescript-eslint/key-spacing': 'off',
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
|
@ -261,8 +261,6 @@ dependencies {
|
||||
implementation 'com.facebook.fresco:webpsupport:2.6.0'
|
||||
|
||||
implementation 'com.facebook.fresco:animated-gif:2.6.0'
|
||||
|
||||
// implementation 'com.github.Samourai-Wallet:ExtLibJ:0.0.11'
|
||||
|
||||
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
|
||||
exclude group:'com.facebook.fbjni'
|
||||
|
@ -269,7 +269,7 @@ public class Database {
|
||||
String relayUrl = cursor.getString(0);
|
||||
int active = cursor.getInt(1);
|
||||
int globalFeed = cursor.getInt(2);
|
||||
Relay relay = new Relay(relayUrl, active, globalFeed,this, reactContext);
|
||||
Relay relay = new Relay(relayUrl, active, globalFeed,0, this, reactContext);
|
||||
relayList.add(relay);
|
||||
} catch (IOException e) {
|
||||
Log.d("WebSocket", e.toString());
|
||||
|
@ -10,8 +10,6 @@ import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
//import com.samourai.wallet.segwit.bech32.Bech32;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
@ -16,12 +16,14 @@ public class Relay {
|
||||
public int active;
|
||||
public int globalFeed;
|
||||
public int paid;
|
||||
public int resilient;
|
||||
|
||||
public Relay(String serverUrl, int isActive, int showGlobalFeed, Database database, ReactApplicationContext reactContext) throws IOException {
|
||||
public Relay(String serverUrl, int isActive, int showGlobalFeed, int isResilient, Database database, ReactApplicationContext reactContext) throws IOException {
|
||||
webSocket = new Websocket(serverUrl, database, reactContext);
|
||||
url = serverUrl;
|
||||
active = isActive;
|
||||
globalFeed = showGlobalFeed;
|
||||
resilient = isResilient;
|
||||
}
|
||||
|
||||
public int active() {
|
||||
@ -58,6 +60,7 @@ public class Relay {
|
||||
values.put("paid", paid);
|
||||
values.put("active", active);
|
||||
values.put("global_feed", globalFeed);
|
||||
values.put("resilient", resilient);
|
||||
values.put("deleted_at", 0);
|
||||
database.instance.replace("nostros_relays", null, values);
|
||||
}
|
||||
|
@ -31,16 +31,9 @@ public class RelayPoolModule extends ReactContextBaseJavaModule {
|
||||
return "RelayPoolModule";
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void add(String url, Callback callback) {
|
||||
add(url);
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void add(String url) {
|
||||
private void add(String url, int resilient, int showGlobalFeed) {
|
||||
try {
|
||||
Relay relay = new Relay(url, 1, 1, database, context);
|
||||
Relay relay = new Relay(url, 1, showGlobalFeed, resilient, database, context);
|
||||
relay.connect(userPubKey);
|
||||
relays.add(relay);
|
||||
database.saveRelay(relay);
|
||||
@ -49,6 +42,12 @@ public class RelayPoolModule extends ReactContextBaseJavaModule {
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void add(String url, int resilient, int showGlobalFeed, Callback callback) {
|
||||
this.add(url, resilient, showGlobalFeed);
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void remove(String url, Callback callback) {
|
||||
ListIterator<Relay> iterator = relays.listIterator();
|
||||
@ -94,7 +93,7 @@ public class RelayPoolModule extends ReactContextBaseJavaModule {
|
||||
}
|
||||
|
||||
if (!relayExists) {
|
||||
this.add(url);
|
||||
this.add(url, 0, 1);
|
||||
}
|
||||
|
||||
callback.invoke();
|
||||
|
@ -11,7 +11,7 @@ import {
|
||||
TouchableRipple,
|
||||
useTheme,
|
||||
} from 'react-native-paper'
|
||||
import { getGroup, Group } from '../../Functions/DatabaseFunctions/Groups'
|
||||
import { getGroup, type Group } from '../../Functions/DatabaseFunctions/Groups'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { validImageUrl } from '../../Functions/NativeFunctions'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
@ -22,9 +22,9 @@ import { UserContext } from '../../Contexts/UserContext'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { Event } from '../../lib/nostr/Events'
|
||||
import { type Event } from '../../lib/nostr/Events'
|
||||
import { goBack } from '../../lib/Navigation'
|
||||
import { getUser, User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { getUser, type User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import ProfileData from '../ProfileData'
|
||||
import GroupShare from '../GroupShare'
|
||||
import DatabaseModule from '../../lib/Native/DatabaseModule'
|
||||
|
@ -4,10 +4,10 @@ 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 type 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 { type Group } from '../../Functions/DatabaseFunctions/Groups'
|
||||
import { getNoteRelays } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
|
||||
|
@ -1,15 +1,15 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import { User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { ListRenderItem, StyleSheet, View } from 'react-native'
|
||||
import { type User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { type ListRenderItem, StyleSheet, View } from 'react-native'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import { Button, Divider, Text, TextInput, TouchableRipple, useTheme } from 'react-native-paper'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import LnPreview from '../LnPreview'
|
||||
import { Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { type Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { getNpub } from '../../lib/nostr/Nip19'
|
||||
import { formatPubKey } from '../../Functions/RelayFunctions/Users'
|
||||
import { getZaps, Zap } from '../../Functions/DatabaseFunctions/Zaps'
|
||||
import { getZaps, type Zap } from '../../Functions/DatabaseFunctions/Zaps'
|
||||
import { FlatList, ScrollView } from 'react-native-gesture-handler'
|
||||
import ProfileData from '../ProfileData'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
|
@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import { Card, IconButton, Text, useTheme } from 'react-native-paper'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { decode, PaymentRequestObject, TagsObject } from 'bolt11'
|
||||
import { decode, type PaymentRequestObject, type TagsObject } from 'bolt11'
|
||||
|
||||
interface LnPreviewProps {
|
||||
setOpen?: (open: boolean) => void
|
||||
|
@ -4,7 +4,12 @@ import { FlatList, StyleSheet, TouchableNativeFeedback, View } from 'react-nativ
|
||||
import { Divider, IconButton, List, 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 {
|
||||
getNoteRelays,
|
||||
getNotes,
|
||||
type Note,
|
||||
type NoteRelay,
|
||||
} from '../../Functions/DatabaseFunctions/Notes'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import NoteShare from '../NoteShare'
|
||||
import { navigate } from '../../lib/Navigation'
|
||||
|
@ -5,17 +5,17 @@ import {
|
||||
getRepliesCount,
|
||||
getRepostCount,
|
||||
isUserReposted,
|
||||
Note,
|
||||
NoteRelay,
|
||||
type Note,
|
||||
type NoteRelay,
|
||||
} from '../../Functions/DatabaseFunctions/Notes'
|
||||
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 { Event } from '../../lib/nostr/Events'
|
||||
import { type Event } from '../../lib/nostr/Events'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import { Relay, searchRelays } from '../../Functions/DatabaseFunctions/Relays'
|
||||
import { type Relay, searchRelays } from '../../Functions/DatabaseFunctions/Relays'
|
||||
import TextContent from '../../Components/TextContent'
|
||||
import { formatPubKey } from '../../Functions/RelayFunctions/Users'
|
||||
import { getReactions } from '../../Functions/DatabaseFunctions/Reactions'
|
||||
|
@ -4,11 +4,11 @@ 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 type 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 { getNoteRelays, type Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { getNevent } from '../../lib/nostr/Nip19'
|
||||
|
||||
interface NoteShareProps {
|
||||
|
@ -1,19 +1,19 @@
|
||||
import { t } from 'i18next'
|
||||
import * as React from 'react'
|
||||
import { StyleSheet, View, ListRenderItem, Switch, FlatList } from 'react-native'
|
||||
import { StyleSheet, View, type ListRenderItem, Switch, FlatList } from 'react-native'
|
||||
import { Button, IconButton, List, Snackbar, Text, useTheme } from 'react-native-paper'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { UserContext } from '../../Contexts/UserContext'
|
||||
import { getUser, User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { getUser, type User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { populatePets, username } from '../../Functions/RelayFunctions/Users'
|
||||
import LnPayment from '../LnPayment'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import { navigate } from '../../lib/Navigation'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import { getUserRelays, NoteRelay } from '../../Functions/DatabaseFunctions/NotesRelays'
|
||||
import { getUserRelays, type NoteRelay } from '../../Functions/DatabaseFunctions/NotesRelays'
|
||||
import { relayToColor } from '../../Functions/NativeFunctions'
|
||||
import { Relay } from '../../Functions/DatabaseFunctions/Relays'
|
||||
import { type Relay } from '../../Functions/DatabaseFunctions/Relays'
|
||||
import ProfileShare from '../ProfileShare'
|
||||
import { ScrollView } from 'react-native-gesture-handler'
|
||||
import { Kind } from 'nostr-tools'
|
||||
|
@ -3,12 +3,12 @@ import * as React from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import { Divider, Snackbar, TouchableRipple, useTheme } from 'react-native-paper'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { getUser, User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { getUser, type User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { usernamePubKey } from '../../Functions/RelayFunctions/Users'
|
||||
import LnPayment from '../LnPayment'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import { push } from '../../lib/Navigation'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import type RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import { getNpub } from '../../lib/nostr/Nip19'
|
||||
import ProfileData from '../ProfileData'
|
||||
import ProfileActions from '../ProfileActions'
|
||||
|
@ -3,9 +3,9 @@ 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 { User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { type User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import Share from 'react-native-share'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import type RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import { getNprofile } from '../../lib/nostr/Nip19'
|
||||
import QRCode from 'react-native-qrcode-svg'
|
||||
import { useContext } from 'react'
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import { getRelay, Relay, RelayInfo } from '../../Functions/DatabaseFunctions/Relays'
|
||||
import { getRelay, type Relay, type RelayInfo } from '../../Functions/DatabaseFunctions/Relays'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import { relayToColor } from '../../Functions/NativeFunctions'
|
||||
import axios from 'axios'
|
||||
@ -26,7 +26,7 @@ import { UserContext } from '../../Contexts/UserContext'
|
||||
import { getRawUserReactions } from '../../Functions/DatabaseFunctions/Reactions'
|
||||
import { getRawUserConversation } from '../../Functions/DatabaseFunctions/DirectMessages'
|
||||
import { getUsers } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { Event } from '../../lib/nostr/Events'
|
||||
import { type Event } from '../../lib/nostr/Events'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { usersToTags } from '../../Functions/RelayFunctions/Users'
|
||||
|
@ -4,7 +4,7 @@ import { Avatar, Card, Text, useTheme } from 'react-native-paper'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import LnPreview from '../../LnPreview'
|
||||
import { decode, PaymentRequestObject, TagsObject } from 'bolt11'
|
||||
import { decode, type PaymentRequestObject, type TagsObject } from 'bolt11'
|
||||
import { AppContext } from '../../../Contexts/AppContext'
|
||||
import { navigate } from '../../../lib/Navigation'
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React, { useContext, useEffect, useState } from 'react'
|
||||
import ParsedText from 'react-native-parsed-text'
|
||||
import { Event } from '../../lib/nostr/Events'
|
||||
import { type Event } from '../../lib/nostr/Events'
|
||||
import { Clipboard, Linking, StyleSheet, View } from 'react-native'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { getUser, User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { getUser, type User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { formatPubKey } from '../../Functions/RelayFunctions/Users'
|
||||
import getUnixTime from 'date-fns/getUnixTime'
|
||||
import { useTheme } from 'react-native-paper'
|
||||
|
@ -3,7 +3,7 @@ import { StyleSheet, View } from 'react-native'
|
||||
import { Button, Card, Snackbar, Text, useTheme } from 'react-native-paper'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import { Asset, launchImageLibrary } from 'react-native-image-picker'
|
||||
import { type Asset, launchImageLibrary } from 'react-native-image-picker'
|
||||
import { imageHostingServices } from '../../Constants/Services'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
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 { Config } from '../Pages/ConfigPage'
|
||||
import { type Config } from '../Pages/ConfigPage'
|
||||
import { imageHostingServices } from '../Constants/Services'
|
||||
import { randomInt, validNip21 } from '../Functions/NativeFunctions'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
|
@ -3,10 +3,10 @@ import RelayPool, { fallbackRelays } from '../lib/nostr/RelayPool/intex'
|
||||
import { AppContext } from './AppContext'
|
||||
import { DeviceEventEmitter } from 'react-native'
|
||||
import debounce from 'lodash.debounce'
|
||||
import { getActiveRelays, getRelays, Relay } from '../Functions/DatabaseFunctions/Relays'
|
||||
import { getActiveRelays, getRelays, type Relay } from '../Functions/DatabaseFunctions/Relays'
|
||||
import { UserContext } from './UserContext'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import { Event } from '../lib/nostr/Events'
|
||||
import { type Event } from '../lib/nostr/Events'
|
||||
import { randomInt } from '../Functions/NativeFunctions'
|
||||
|
||||
export interface RelayPoolContextProps {
|
||||
@ -99,7 +99,6 @@ export const RelayPoolContextProvider = ({
|
||||
if (database && publicKey) {
|
||||
const initRelayPool = new RelayPool(privateKey)
|
||||
initRelayPool.connect(publicKey, () => {
|
||||
initRelayPool.resilientMode(database, publicKey)
|
||||
setRelayPool(initRelayPool)
|
||||
})
|
||||
}
|
||||
@ -143,11 +142,11 @@ export const RelayPoolContextProvider = ({
|
||||
})
|
||||
}
|
||||
|
||||
const addRelayItem: (relay: Relay) => Promise<void> = async (relay, send = true) => {
|
||||
const addRelayItem: (relay: Relay) => Promise<void> = async (relay) => {
|
||||
setRelays((prev) => [...prev, relay])
|
||||
return await new Promise((resolve, _reject) => {
|
||||
if (relayPool && database && publicKey) {
|
||||
relayPool.add(relay.url, () => {
|
||||
relayPool.add(relay.url, relay.resilient ?? 0, relay.global_feed ?? 1, () => {
|
||||
loadRelays().then(() => {
|
||||
resolve()
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { getItems } from '..'
|
||||
import { Event, evetDatabaseToEntity } from '../../../lib/nostr/Events'
|
||||
import { type Event, evetDatabaseToEntity } from '../../../lib/nostr/Events'
|
||||
|
||||
export interface DirectMessage extends Event {
|
||||
conversation_id: string
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { QueryResult, QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { type QueryResult, type QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { getItems } from '..'
|
||||
import { Event } from '../../../lib/nostr/Events'
|
||||
import { type Event } from '../../../lib/nostr/Events'
|
||||
|
||||
export interface Group extends Event {
|
||||
name?: string
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { getItems } from '..'
|
||||
import { Event, evetDatabaseToEntity } from '../../../lib/nostr/Events'
|
||||
import { type Event, evetDatabaseToEntity } from '../../../lib/nostr/Events'
|
||||
|
||||
export interface List extends Event {}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { getItems } from '..'
|
||||
import { Event, evetDatabaseToEntity } from '../../../lib/nostr/Events'
|
||||
import { type Event, evetDatabaseToEntity } from '../../../lib/nostr/Events'
|
||||
|
||||
export interface Note extends Event {
|
||||
name: string
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { getItems } from '..'
|
||||
import { Relay } from '../Relays'
|
||||
import { type Relay } from '../Relays'
|
||||
|
||||
export interface NoteRelay extends Relay {
|
||||
relay_url: string
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { getItems } from '..'
|
||||
import { Event, evetDatabaseToEntity } from '../../../lib/nostr/Events'
|
||||
import { type Event, evetDatabaseToEntity } from '../../../lib/nostr/Events'
|
||||
|
||||
export interface Reaction extends Event {
|
||||
positive: boolean
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { getItems } from '..'
|
||||
import { Event } from '../../../lib/nostr/Events'
|
||||
import { type Event } from '../../../lib/nostr/Events'
|
||||
|
||||
export interface RelayMetadata extends Event {
|
||||
url: string
|
||||
@ -26,7 +26,7 @@ export const getRawRelayMetadata: (
|
||||
publicKey: string,
|
||||
) => Promise<Event[]> = async (db, publicKey) => {
|
||||
const notesQuery = 'SELECT * FROM nostros_relay_metadata WHERE pubkey = ?;'
|
||||
const resultSet = await db.execute(notesQuery, [publicKey])
|
||||
const resultSet = db.execute(notesQuery, [publicKey])
|
||||
const items: object[] = getItems(resultSet)
|
||||
const relays: Event[] = items.map((object) => databaseToRawEntity(object))
|
||||
return relays
|
||||
@ -38,8 +38,18 @@ export const getRelayMetadata: (
|
||||
) => Promise<RelayMetadata> = async (db, publicKey) => {
|
||||
const notesQuery =
|
||||
'SELECT * FROM nostros_relay_metadata WHERE pubkey = ? ORDER BY created_at DESC;'
|
||||
const resultSet = await db.execute(notesQuery, [publicKey])
|
||||
const resultSet = db.execute(notesQuery, [publicKey])
|
||||
const items: object[] = getItems(resultSet)
|
||||
const relays: RelayMetadata[] = items.map((object) => databaseToEntity(object))
|
||||
return relays[0]
|
||||
}
|
||||
|
||||
export const getAllRelayMetadata: (db: QuickSQLiteConnection) => Promise<RelayMetadata[]> = async (
|
||||
db,
|
||||
) => {
|
||||
const notesQuery = 'SELECT * FROM nostros_relay_metadata;'
|
||||
const resultSet = db.execute(notesQuery)
|
||||
const items: object[] = getItems(resultSet)
|
||||
const relays: RelayMetadata[] = items.map((object) => databaseToEntity(object))
|
||||
return relays
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { getItems } from '..'
|
||||
import { median } from '../../NativeFunctions'
|
||||
import { getNoteRelaysUsage } from '../NotesRelays'
|
||||
@ -33,7 +33,7 @@ export const searchRelays: (
|
||||
db: QuickSQLiteConnection,
|
||||
) => Promise<Relay[]> = async (relayUrl, db) => {
|
||||
const searchQuery = `SELECT * FROM nostros_relays WHERE url = '${relayUrl}' AND deleted_at = 0;`
|
||||
const results = await db.execute(searchQuery)
|
||||
const results = db.execute(searchQuery)
|
||||
const items: object[] = getItems(results)
|
||||
const relays: Relay[] = items.map((object) => databaseToEntity(object))
|
||||
return relays
|
||||
@ -41,15 +41,16 @@ export const searchRelays: (
|
||||
|
||||
export const getRelays: (db: QuickSQLiteConnection) => Promise<Relay[]> = async (db) => {
|
||||
const notesQuery = 'SELECT * FROM nostros_relays WHERE deleted_at = 0;'
|
||||
const resultSet = await db.execute(notesQuery)
|
||||
const resultSet = db.execute(notesQuery)
|
||||
const items: object[] = getItems(resultSet)
|
||||
const relays: Relay[] = items.map((object) => databaseToEntity(object))
|
||||
return relays
|
||||
}
|
||||
|
||||
export const getActiveRelays: (db: QuickSQLiteConnection) => Promise<Relay[]> = async (db) => {
|
||||
const notesQuery = 'SELECT * FROM nostros_relays WHERE active = 1 AND deleted_at = 0;'
|
||||
const resultSet = await db.execute(notesQuery)
|
||||
const notesQuery =
|
||||
'SELECT * FROM nostros_relays WHERE active = 1 AND deleted_at = 0 AND resilient != 0;'
|
||||
const resultSet = db.execute(notesQuery)
|
||||
const items: object[] = getItems(resultSet)
|
||||
const relays: Relay[] = items.map((object) => databaseToEntity(object))
|
||||
return relays
|
||||
@ -60,7 +61,7 @@ export const getRelay: (db: QuickSQLiteConnection, url: string) => Promise<Relay
|
||||
url,
|
||||
) => {
|
||||
const notesQuery = 'SELECT * FROM nostros_relays WHERE url = ? AND deleted_at = 0;'
|
||||
const resultSet = await db.execute(notesQuery, [url])
|
||||
const resultSet = db.execute(notesQuery, [url])
|
||||
const items: object[] = getItems(resultSet)
|
||||
const relays: Relay[] = items.map((object) => databaseToEntity(object))
|
||||
return relays[0]
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { getItems } from '..'
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
|
||||
export interface User {
|
||||
id: string
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { getItems } from '..'
|
||||
import { Event } from '../../../lib/nostr/Events'
|
||||
import { type Event } from '../../../lib/nostr/Events'
|
||||
|
||||
export interface Zap extends Event {
|
||||
amount: boolean
|
||||
|
@ -1,8 +1,8 @@
|
||||
import {
|
||||
open,
|
||||
QuickSQLiteConnection,
|
||||
BatchQueryResult,
|
||||
QueryResult,
|
||||
type QuickSQLiteConnection,
|
||||
type BatchQueryResult,
|
||||
type QueryResult,
|
||||
} from 'react-native-quick-sqlite'
|
||||
|
||||
export const initDatabase: () => QuickSQLiteConnection = () => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DirectMessage } from '../../DatabaseFunctions/DirectMessages'
|
||||
import { type DirectMessage } from '../../DatabaseFunctions/DirectMessages'
|
||||
|
||||
export const getOtherPubKey: (message: DirectMessage, ownPubKey: string) => string = (
|
||||
message,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Event } from '../../../lib/nostr/Events'
|
||||
import { type Event } from '../../../lib/nostr/Events'
|
||||
|
||||
export const getReplyEventId: (event: Event) => string | null = (event) => {
|
||||
const eTags = getETags(event)
|
||||
@ -43,6 +43,10 @@ export const getTaggedPubKeys: (event: Event) => string[] = (event) => {
|
||||
return mainEventETags.map((item) => item[1] ?? '')
|
||||
}
|
||||
|
||||
export const getRTags: (event: Event) => string[][] = (event) => {
|
||||
return event?.tags.filter((tag) => tag[0] === 'r') || []
|
||||
}
|
||||
|
||||
export const getETags: (event: Event) => string[][] = (event) => {
|
||||
return event?.tags.filter((tag) => tag[0] === 'e') || []
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import getUnixTime from 'date-fns/getUnixTime'
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import RelayPool from '../../../lib/nostr/RelayPool/intex'
|
||||
import { Event } from '../../../lib/nostr/Events'
|
||||
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'
|
||||
|
||||
|
70
frontend/Functions/RelayFunctions/Metadata/index.ts
Normal file
70
frontend/Functions/RelayFunctions/Metadata/index.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { type RelayMetadata } from '../../DatabaseFunctions/RelayMetadatas'
|
||||
import { type Relay } from '../../DatabaseFunctions/Relays'
|
||||
import { median } from '../../NativeFunctions'
|
||||
import { getRTags } from '../Events'
|
||||
|
||||
export interface ResilientAssignation {
|
||||
resilientRelays: string[]
|
||||
smallRelays: string[]
|
||||
centralizedRelays: string[]
|
||||
}
|
||||
|
||||
export const getContactsRelays: (
|
||||
userRelays: Relay[],
|
||||
relayMetadada: RelayMetadata[],
|
||||
) => Promise<string[]> = async (userRelays, relayMetadada) => {
|
||||
const localhostRegExp = /.*:4848\/?.*$/
|
||||
const pubKeys: string[] = []
|
||||
// Url => pubkey[]
|
||||
const relaysPresence: Record<string, string[]> = {}
|
||||
relayMetadada.forEach((metadata) => {
|
||||
const rTags: string[][] = getRTags(metadata)
|
||||
pubKeys.push(metadata.pubkey)
|
||||
const urls = rTags.map((tags) => tags[1])
|
||||
urls.forEach((url) => {
|
||||
if (!localhostRegExp.test(url)) {
|
||||
relaysPresence[url] = [...(relaysPresence[url] ?? []), metadata.pubkey]
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Median of users per relay
|
||||
const medianUsage = median(
|
||||
Object.keys(relaysPresence).map((relay) => relaysPresence[relay].length),
|
||||
)
|
||||
|
||||
// Sort relays by abs distance from the mediam
|
||||
const relaysByPresence = Object.keys(relaysPresence).sort((n1: string, n2: string) => {
|
||||
return (
|
||||
Math.abs(relaysPresence[n1].length - medianUsage) -
|
||||
Math.abs(relaysPresence[n2].length - medianUsage)
|
||||
)
|
||||
})
|
||||
|
||||
// Set helpers
|
||||
const userRelayUrls = userRelays
|
||||
.map((relay) => relay.url)
|
||||
.filter((url) => !localhostRegExp.test(url))
|
||||
|
||||
// Allocate contacts to user's relays
|
||||
let allocatedUsers: string[] = []
|
||||
userRelayUrls.forEach((url) => {
|
||||
allocatedUsers = [...allocatedUsers, ...relaysPresence[url]]
|
||||
})
|
||||
|
||||
// Iterate over remaining sorted relays and assigns as much users as possible
|
||||
const resilientAssignation: string[] = []
|
||||
const remainingUsers = pubKeys.filter((pubKey) => !allocatedUsers.includes(pubKey))
|
||||
relaysByPresence.forEach((relayUrl) => {
|
||||
remainingUsers.forEach((pubKey) => {
|
||||
if (!allocatedUsers.includes(pubKey) && relaysPresence[relayUrl].includes(pubKey)) {
|
||||
allocatedUsers.push(pubKey)
|
||||
if (!resilientAssignation.includes(relayUrl)) {
|
||||
resilientAssignation.push(relayUrl)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return resilientAssignation
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
import getUnixTime from 'date-fns/getUnixTime'
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import RelayPool from '../../../lib/nostr/RelayPool/intex'
|
||||
import { getUser, getUsers, User } from '../../DatabaseFunctions/Users'
|
||||
import { Event } from '../../../lib/nostr/Events'
|
||||
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'
|
||||
import { Kind } from 'nostr-tools'
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Thanks to v0l/snort for the nice code!
|
||||
// https://github.com/v0l/snort/blob/39fbe3b10f94b7542df01fb085e4f164aab15fca/src/Feed/VoidUpload.ts
|
||||
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { getRelays, Relay } from '../../DatabaseFunctions/Relays'
|
||||
import { type QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { getRelays, type Relay } from '../../DatabaseFunctions/Relays'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import { Event, signEvent } from '../../../lib/nostr/Events'
|
||||
import { type Event, signEvent } from '../../../lib/nostr/Events'
|
||||
import { requestInvoiceWithServiceParams, requestPayServiceParams } from 'lnurl-pay'
|
||||
import axios from 'axios'
|
||||
|
||||
|
@ -252,7 +252,9 @@
|
||||
},
|
||||
"relaysPage": {
|
||||
"pushListTitle": "Push relay list to the network",
|
||||
"pushListDescription": "Only relays on \"My relays\" list will be pushed.",
|
||||
"pushList": "Push list",
|
||||
"contactsList": "Contact's relays",
|
||||
"freeAccess": "Free access",
|
||||
"paid": "Paid",
|
||||
"paidRelay": "Paid relay",
|
||||
|
@ -41,6 +41,7 @@
|
||||
}
|
||||
},
|
||||
"profileLoadPage": {
|
||||
"connect": "Connect and go home",
|
||||
"foundRelays": "Relays found",
|
||||
"searchingContacts": "Searching for your contacts",
|
||||
"retry": "Retry",
|
||||
@ -48,6 +49,8 @@
|
||||
"nextStep": "Next step",
|
||||
"searchingRelays": "Searching for your relays",
|
||||
"reconnectOther": "Reconnect to other relays",
|
||||
"contactRelays": "Contact's relays",
|
||||
"contactRelaysDescription": "Searching for relays where your contacts can be found",
|
||||
"relaysDescripion": "Connect with other relays if you have problems finding your data.",
|
||||
"relays": "See relays",
|
||||
"home": "Go Home",
|
||||
@ -252,7 +255,9 @@
|
||||
},
|
||||
"relaysPage": {
|
||||
"pushListTitle": "Push relay list to the network",
|
||||
"pushListDescription": "Only relays on \"My relays\" list will be pushed.",
|
||||
"pushList": "Push list",
|
||||
"contactsList": "Contact's relays",
|
||||
"freeAccess": "Free access",
|
||||
"paid": "Paid",
|
||||
"paidRelay": "Paid relay",
|
||||
|
@ -303,9 +303,11 @@
|
||||
},
|
||||
"relaysPage": {
|
||||
"pushListTitle": "Subir lista de relays",
|
||||
"pushListDescription": "Solo se subirán los relays en la lista \"Mis relays\".",
|
||||
"pushList": "Subir lista",
|
||||
"freeAccess": "Acceso libre",
|
||||
"paid": "Pago",
|
||||
"contactsList": "Relays de tus contactos",
|
||||
"paidRelay": "Relay de pago",
|
||||
"resilienceTitle": "Resilience (experimental)",
|
||||
"resilienceDescription": "The Nostr protocol provides a good number of tools to build a decentralized network, but unlike other decentralized protocols such as Bitcoin, it is not inherently bound to its use. To achieve the goal of a decentralized network, clients (e.g., Nostros) and relays (content servers) should actively cooperate. The Nostros resilience mode seeks first to raise awareness of this among users, and second to test new patterns and methods to improve the resilience of the network.\nA working implementation for this will soon be applied in Nostros.",
|
||||
|
@ -300,7 +300,9 @@
|
||||
},
|
||||
"relaysPage": {
|
||||
"pushListTitle": "Push relay list to the network",
|
||||
"pushListDescription": "Only relays on \"My relays\" list will be pushed.",
|
||||
"pushList": "Push list",
|
||||
"contactsList": "Contact's relays",
|
||||
"freeAccess": "Free access",
|
||||
"paid": "Paid",
|
||||
"paidRelay": "Paid relay",
|
||||
|
@ -295,7 +295,9 @@
|
||||
},
|
||||
"relaysPage": {
|
||||
"pushListTitle": "Push relay list to the network",
|
||||
"pushListDescription": "Only relays on \"My relays\" list will be pushed.",
|
||||
"pushList": "Push list",
|
||||
"contactsList": "Contact's relays",
|
||||
"freeAccess": "Free access",
|
||||
"paid": "Paid",
|
||||
"paidRelay": "Paid relay",
|
||||
|
@ -271,9 +271,11 @@
|
||||
},
|
||||
"relaysPage": {
|
||||
"pushListTitle": "Push relay list to the network",
|
||||
"pushListDescription": "Only relays on \"My relays\" list will be pushed.",
|
||||
"pushList": "Push list",
|
||||
"freeAccess": "Free access",
|
||||
"paid": "Paid",
|
||||
"contactsList": "Contact's relays",
|
||||
"paidRelay": "Paid relay",
|
||||
"resilienceTitle": "弹性模式 (试验性)",
|
||||
"resilienceDescription": "Nostr 协议提供了大量工具来构建去中心化网络,但与比特币等其他去中心化协议不同,它并不是默认使用的。 \n\n为了实现这样的目标,客户端和中继应该积极协作。 Nostros 弹性模式首先尝试将这些问题暴露给用户,其次开始尝试新的模式和方法来帮助提高网络的弹性。 \n\n该功能的实现将很快默认出现在 Nostros 上",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { FlatList, Linking, ListRenderItem, StyleSheet } from 'react-native'
|
||||
import { FlatList, Linking, type ListRenderItem, StyleSheet } from 'react-native'
|
||||
import { Divider, List, Text, useTheme } from 'react-native-paper'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import VersionNumber from 'react-native-version-number'
|
||||
|
@ -1,14 +1,14 @@
|
||||
import React, { useContext, useEffect, useState } from 'react'
|
||||
import { NativeScrollEvent, NativeSyntheticEvent, StyleSheet, View } from 'react-native'
|
||||
import { type NativeScrollEvent, type NativeSyntheticEvent, StyleSheet, View } from 'react-native'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import {
|
||||
getBlocked,
|
||||
getFollowersAndFollowing,
|
||||
User,
|
||||
type User,
|
||||
getUsers,
|
||||
} from '../../Functions/DatabaseFunctions/Users'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
|
@ -2,18 +2,21 @@ import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import {
|
||||
FlatList,
|
||||
Animated,
|
||||
ListRenderItem,
|
||||
NativeScrollEvent,
|
||||
NativeSyntheticEvent,
|
||||
ScrollView,
|
||||
type ListRenderItem,
|
||||
type NativeScrollEvent,
|
||||
type NativeSyntheticEvent,
|
||||
type ScrollView,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { Event } from '../../lib/nostr/Events'
|
||||
import { DirectMessage, getDirectMessages } from '../../Functions/DatabaseFunctions/DirectMessages'
|
||||
import { getUser, User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { type Event } from '../../lib/nostr/Events'
|
||||
import {
|
||||
type DirectMessage,
|
||||
getDirectMessages,
|
||||
} from '../../Functions/DatabaseFunctions/DirectMessages'
|
||||
import { getUser, type User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { username, usernamePubKey, usersToTags } from '../../Functions/RelayFunctions/Users'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
|
@ -2,9 +2,9 @@ import React, { useContext, useEffect, useState } from 'react'
|
||||
import {
|
||||
Dimensions,
|
||||
FlatList,
|
||||
ListRenderItem,
|
||||
NativeScrollEvent,
|
||||
NativeSyntheticEvent,
|
||||
type ListRenderItem,
|
||||
type NativeScrollEvent,
|
||||
type NativeSyntheticEvent,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
@ -13,11 +13,11 @@ import { AppContext } from '../../Contexts/AppContext'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import {
|
||||
DirectMessage,
|
||||
type DirectMessage,
|
||||
getGroupedDirectMessages,
|
||||
getUserLastDirectMessages,
|
||||
} from '../../Functions/DatabaseFunctions/DirectMessages'
|
||||
import { getUsers, User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { getUsers, type User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { getOtherPubKey } from '../../Functions/RelayFunctions/DirectMessages'
|
||||
import { username } from '../../Functions/RelayFunctions/Users'
|
||||
import {
|
||||
|
@ -2,15 +2,15 @@ import React, { useContext, useEffect, useState } from 'react'
|
||||
import {
|
||||
Animated,
|
||||
FlatList,
|
||||
ListRenderItem,
|
||||
NativeScrollEvent,
|
||||
NativeSyntheticEvent,
|
||||
type ListRenderItem,
|
||||
type NativeScrollEvent,
|
||||
type NativeSyntheticEvent,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { Event } from '../../lib/nostr/Events'
|
||||
import { type Event } from '../../lib/nostr/Events'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { formatPubKey, username, usernamePubKey } from '../../Functions/RelayFunctions/Users'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
@ -31,9 +31,9 @@ import { Kind } from 'nostr-tools'
|
||||
import { formatDate, handleInfinityScroll } from '../../Functions/NativeFunctions'
|
||||
import NostrosAvatar from '../../Components/NostrosAvatar'
|
||||
import UploadImage from '../../Components/UploadImage'
|
||||
import { getGroupMessages, GroupMessage } from '../../Functions/DatabaseFunctions/Groups'
|
||||
import { RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
import { getUsers, User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { getGroupMessages, type GroupMessage } from '../../Functions/DatabaseFunctions/Groups'
|
||||
import { type RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
import { getUsers, type User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import ProfileData from '../../Components/ProfileData'
|
||||
import { ScrollView, Swipeable } from 'react-native-gesture-handler'
|
||||
import { getETags } from '../../Functions/RelayFunctions/Events'
|
||||
|
@ -17,7 +17,7 @@ import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import UploadImage from '../../Components/UploadImage'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { Event } from '../../lib/nostr/Events'
|
||||
import { type Event } from '../../lib/nostr/Events'
|
||||
import { UserContext } from '../../Contexts/UserContext'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
@ -27,13 +27,13 @@ import {
|
||||
getGroupMessagesCount,
|
||||
getGroupMessagesMentionsCount,
|
||||
getGroups,
|
||||
Group,
|
||||
type Group,
|
||||
} from '../../Functions/DatabaseFunctions/Groups'
|
||||
import { formatId } from '../../Functions/RelayFunctions/Users'
|
||||
import NostrosAvatar from '../../Components/NostrosAvatar'
|
||||
import { navigate } from '../../lib/Navigation'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import { type RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
import { validNip21 } from '../../Functions/NativeFunctions'
|
||||
import { getNip19Key } from '../../lib/nostr/Nip19'
|
||||
import DatabaseModule from '../../lib/Native/DatabaseModule'
|
||||
|
@ -1,22 +1,22 @@
|
||||
import React, { useCallback, useContext, useState, useEffect } from 'react'
|
||||
import {
|
||||
NativeScrollEvent,
|
||||
NativeSyntheticEvent,
|
||||
type NativeScrollEvent,
|
||||
type NativeSyntheticEvent,
|
||||
RefreshControl,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { AppContext } from '../../../Contexts/AppContext'
|
||||
import { getNotes, Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { getNotes, type Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { handleInfinityScroll } from '../../../Functions/NativeFunctions'
|
||||
import { UserContext } from '../../../Contexts/UserContext'
|
||||
import { RelayPoolContext } from '../../../Contexts/RelayPoolContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
import { type RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
import { ActivityIndicator, Button, Text } from 'react-native-paper'
|
||||
import NoteCard from '../../../Components/NoteCard'
|
||||
import { useTheme } from '@react-navigation/native'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { getContactsCount } from '../../../Functions/DatabaseFunctions/Users'
|
||||
|
@ -1,25 +1,29 @@
|
||||
import React, { useCallback, useContext, useState, useEffect } from 'react'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
NativeScrollEvent,
|
||||
NativeSyntheticEvent,
|
||||
type NativeScrollEvent,
|
||||
type NativeSyntheticEvent,
|
||||
RefreshControl,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { AppContext } from '../../../Contexts/AppContext'
|
||||
import { getMainNotes, getMainNotesCount, Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import {
|
||||
getMainNotes,
|
||||
getMainNotesCount,
|
||||
type Note,
|
||||
} from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { handleInfinityScroll } from '../../../Functions/NativeFunctions'
|
||||
import { UserContext } from '../../../Contexts/UserContext'
|
||||
import { RelayPoolContext } from '../../../Contexts/RelayPoolContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
import { type RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
import { Chip, Button, Text } from 'react-native-paper'
|
||||
import NoteCard from '../../../Components/NoteCard'
|
||||
import { useTheme } from '@react-navigation/native'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import { t } from 'i18next'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
|
||||
interface GlobalFeedProps {
|
||||
navigation: any
|
||||
|
@ -1,25 +1,25 @@
|
||||
import React, { useCallback, useContext, useState, useEffect } from 'react'
|
||||
import {
|
||||
NativeScrollEvent,
|
||||
NativeSyntheticEvent,
|
||||
type NativeScrollEvent,
|
||||
type NativeSyntheticEvent,
|
||||
RefreshControl,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { AppContext } from '../../../Contexts/AppContext'
|
||||
import { getMainNotes, Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { getMainNotes, type Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { handleInfinityScroll } from '../../../Functions/NativeFunctions'
|
||||
import { UserContext } from '../../../Contexts/UserContext'
|
||||
import { RelayPoolContext } from '../../../Contexts/RelayPoolContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
import { type RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
import { ActivityIndicator, Button, Text } from 'react-native-paper'
|
||||
import NoteCard from '../../../Components/NoteCard'
|
||||
import { useTheme } from '@react-navigation/native'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { getContactsCount, getUsers, User } from '../../../Functions/DatabaseFunctions/Users'
|
||||
import { getContactsCount, getUsers, type User } from '../../../Functions/DatabaseFunctions/Users'
|
||||
|
||||
interface MyFeedProps {
|
||||
navigation: any
|
||||
|
@ -1,27 +1,27 @@
|
||||
import React, { useCallback, useContext, useState, useEffect } from 'react'
|
||||
import {
|
||||
NativeScrollEvent,
|
||||
NativeSyntheticEvent,
|
||||
type NativeScrollEvent,
|
||||
type NativeSyntheticEvent,
|
||||
RefreshControl,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { AppContext } from '../../../Contexts/AppContext'
|
||||
import { getNotes, Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { getNotes, type Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { handleInfinityScroll } from '../../../Functions/NativeFunctions'
|
||||
import { UserContext } from '../../../Contexts/UserContext'
|
||||
import { RelayPoolContext } from '../../../Contexts/RelayPoolContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
import { type RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
import { ActivityIndicator, Button, Text } from 'react-native-paper'
|
||||
import NoteCard from '../../../Components/NoteCard'
|
||||
import { useTheme } from '@react-navigation/native'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { getMostZapedNotesContacts } from '../../../Functions/DatabaseFunctions/Zaps'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import { getUsers, User } from '../../../Functions/DatabaseFunctions/Users'
|
||||
import { getUsers, type User } from '../../../Functions/DatabaseFunctions/Users'
|
||||
|
||||
interface ZapsFeedProps {
|
||||
navigation: any
|
||||
|
@ -8,7 +8,7 @@ import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import AboutPage from '../../Pages/AboutPage'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import ProfileCreatePage from '../../Pages/ProfileCreatePage'
|
||||
import { DrawerNavigationProp } from '@react-navigation/drawer'
|
||||
import { type DrawerNavigationProp } from '@react-navigation/drawer'
|
||||
import RelaysPage from '../RelaysPage'
|
||||
import ConfigPage from '../ConfigPage'
|
||||
import QrReaderPage from '../QrReaderPage'
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React, { useCallback, useContext, useEffect, useState } from 'react'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { getNotes, Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { getNotes, type Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import NoteCard from '../../Components/NoteCard'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { Dimensions, RefreshControl, StyleSheet, View } from 'react-native'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import { getDirectReplies } from '../../Functions/RelayFunctions/Events'
|
||||
import { AnimatedFAB, useTheme } from 'react-native-paper'
|
||||
import { UserContext } from '../../Contexts/UserContext'
|
||||
@ -13,7 +13,7 @@ import { navigate } from '../../lib/Navigation'
|
||||
import { useFocusEffect } from '@react-navigation/native'
|
||||
import { SkeletonNote } from '../../Components/SkeletonNote/SkeletonNote'
|
||||
import { ScrollView } from 'react-native-gesture-handler'
|
||||
import { RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
import { type RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
|
||||
interface NotePageProps {
|
||||
route: { params: { noteId: string } }
|
||||
|
@ -1,14 +1,14 @@
|
||||
import React, { useCallback, useContext, useEffect, useState } from 'react'
|
||||
import {
|
||||
NativeScrollEvent,
|
||||
NativeSyntheticEvent,
|
||||
type NativeScrollEvent,
|
||||
type NativeSyntheticEvent,
|
||||
RefreshControl,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import SInfo from 'react-native-sensitive-info'
|
||||
import { getMentionNotes, Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { getMentionNotes, type Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import NoteCard from '../../Components/NoteCard'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
@ -20,8 +20,8 @@ import { useTranslation } from 'react-i18next'
|
||||
import { navigate } from '../../lib/Navigation'
|
||||
import { useFocusEffect } from '@react-navigation/native'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import { Config } from '../../Functions/DatabaseFunctions/Config'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { type Config } from '../../Functions/DatabaseFunctions/Config'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import { getETags } from '../../Functions/RelayFunctions/Events'
|
||||
|
||||
export const NotificationsFeed: React.FC = () => {
|
||||
|
@ -4,13 +4,13 @@ import { Keyboard, StyleSheet, View } from 'react-native'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import { Button, Checkbox, Snackbar, Text, TextInput } from 'react-native-paper'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { DrawerNavigationHelpers } from '@react-navigation/drawer/lib/typescript/src/types'
|
||||
import { type DrawerNavigationHelpers } from '@react-navigation/drawer/lib/typescript/src/types'
|
||||
import { UserContext } from '../../Contexts/UserContext'
|
||||
import { privateKeyFromSeedWords } from 'nostr-tools/nip06'
|
||||
import { nsecEncode } from 'nostr-tools/nip19'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import { Event } from '../../lib/nostr/Events'
|
||||
import { type Event } from '../../lib/nostr/Events'
|
||||
|
||||
interface ProfileCreatePageProps {
|
||||
navigation: DrawerNavigationHelpers
|
||||
|
@ -9,7 +9,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import { AppContext } from '../../../Contexts/AppContext'
|
||||
import {
|
||||
getRelayMetadata,
|
||||
RelayMetadata,
|
||||
type RelayMetadata,
|
||||
} from '../../../Functions/DatabaseFunctions/RelayMetadatas'
|
||||
|
||||
interface FirstStepProps {
|
||||
@ -115,12 +115,12 @@ export const FirstStep: React.FC<FirstStepProps> = ({ nextStep }) => {
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.buttons}>
|
||||
<Button mode='contained' onPress={finish} disabled={!profileFound}>
|
||||
{t('profileLoadPage.nextStep')}
|
||||
</Button>
|
||||
<Button mode='outlined' onPress={() => reconnectRelays()}>
|
||||
{t('profileLoadPage.reconnectOther')}
|
||||
</Button>
|
||||
<Button mode='contained' onPress={finish} disabled={!profileFound}>
|
||||
{t('profileLoadPage.nextStep')}
|
||||
</Button>
|
||||
<Button mode='outlined' onPress={() => setUserState('ready')}>
|
||||
{t('profileLoadPage.home')}
|
||||
</Button>
|
||||
|
@ -1,14 +1,23 @@
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import React, { useContext, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ActivityIndicator, StyleSheet, View } from 'react-native'
|
||||
import { Button, Text } from 'react-native-paper'
|
||||
import { type Relay } from '../../../Functions/DatabaseFunctions/Relays'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
FlatList,
|
||||
type ListRenderItem,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { Button, Divider, List, Text, useTheme } from 'react-native-paper'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import Logo from '../../../Components/Logo'
|
||||
import { AppContext } from '../../../Contexts/AppContext'
|
||||
import { RelayPoolContext } from '../../../Contexts/RelayPoolContext'
|
||||
import { UserContext } from '../../../Contexts/UserContext'
|
||||
import { getUsers, User } from '../../../Functions/DatabaseFunctions/Users'
|
||||
import { getUsers, type User } from '../../../Functions/DatabaseFunctions/Users'
|
||||
import { relayToColor } from '../../../Functions/NativeFunctions'
|
||||
|
||||
interface SecondStepProps {
|
||||
nextStep: () => void
|
||||
@ -16,8 +25,9 @@ interface SecondStepProps {
|
||||
|
||||
export const SecondStep: React.FC<SecondStepProps> = ({ nextStep }) => {
|
||||
const { t } = useTranslation('common')
|
||||
const theme = useTheme()
|
||||
const { database } = useContext(AppContext)
|
||||
const { relayPool, relayPoolReady, lastEventId } = useContext(RelayPoolContext)
|
||||
const { relayPool, relayPoolReady, lastEventId, relays } = useContext(RelayPoolContext)
|
||||
const { publicKey, setUserState } = useContext(UserContext)
|
||||
const [contactsCount, setContactsCount] = useState<number>()
|
||||
|
||||
@ -38,17 +48,10 @@ export const SecondStep: React.FC<SecondStepProps> = ({ nextStep }) => {
|
||||
kinds: [Kind.Contacts],
|
||||
authors: [publicKey],
|
||||
},
|
||||
])
|
||||
relayPool?.subscribe('profile-load-others', [
|
||||
{
|
||||
kinds: [Kind.ChannelCreation, Kind.ChannelMetadata],
|
||||
authors: [publicKey],
|
||||
},
|
||||
{
|
||||
kinds: [1002],
|
||||
authors: [publicKey],
|
||||
limit: 1,
|
||||
},
|
||||
{
|
||||
kinds: [10000],
|
||||
authors: [publicKey],
|
||||
@ -60,7 +63,7 @@ export const SecondStep: React.FC<SecondStepProps> = ({ nextStep }) => {
|
||||
limit: 1,
|
||||
},
|
||||
{
|
||||
kinds: [3001],
|
||||
kinds: [30001],
|
||||
authors: [publicKey],
|
||||
limit: 1,
|
||||
},
|
||||
@ -73,26 +76,55 @@ export const SecondStep: React.FC<SecondStepProps> = ({ nextStep }) => {
|
||||
getUsers(database, {}).then((results) => {
|
||||
if (results.length > 0) {
|
||||
setContactsCount(results.filter((user) => user.contact).length)
|
||||
const authors = [...results.map((user: User) => user.id), publicKey]
|
||||
const authors = [...results.map((user: User) => user.id)]
|
||||
relayPool?.subscribe('profile-load-notes', [
|
||||
{
|
||||
kinds: [Kind.Metadata, 10002],
|
||||
authors,
|
||||
},
|
||||
{
|
||||
kinds: [Kind.Text],
|
||||
authors,
|
||||
since: getUnixTime(new Date()) - 43200,
|
||||
},
|
||||
])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const renderItem: ListRenderItem<Relay> = ({ item, index }) => {
|
||||
return (
|
||||
<View style={styles.relayItem}>
|
||||
<List.Item
|
||||
key={index}
|
||||
title={item.url.replace('wss://', '').replace('ws://', '')}
|
||||
right={() => {
|
||||
if (!item?.paid) return <></>
|
||||
return (
|
||||
<MaterialCommunityIcons
|
||||
name='wallet-outline'
|
||||
size={16}
|
||||
color={theme.colors.onPrimaryContainer}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
left={() => (
|
||||
<MaterialCommunityIcons
|
||||
style={styles.relayColor}
|
||||
name='circle'
|
||||
color={relayToColor(item.url)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View>
|
||||
<View style={styles.loadingProfile}>
|
||||
<Text variant='titleMedium'>{t('profileLoadPage.connectedRelays')}</Text>
|
||||
<Text variant='titleMedium' style={{ color: '#7ADC70' }}>
|
||||
{relays.length}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.logo}>
|
||||
<Logo onlyIcon size='medium' />
|
||||
</View>
|
||||
@ -106,12 +138,28 @@ export const SecondStep: React.FC<SecondStepProps> = ({ nextStep }) => {
|
||||
: t('profileLoadPage.searchingContacts')}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.list}>
|
||||
<View style={styles.titleWrapper}>
|
||||
<Text style={styles.title} variant='titleMedium'>
|
||||
{t('relaysPage.myList')}
|
||||
</Text>
|
||||
<Divider />
|
||||
</View>
|
||||
<ScrollView horizontal={false}>
|
||||
<FlatList
|
||||
showsVerticalScrollIndicator={false}
|
||||
data={relays}
|
||||
renderItem={renderItem}
|
||||
ItemSeparatorComponent={Divider}
|
||||
/>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.buttons}>
|
||||
<Button mode='outlined' onPress={() => {}}>
|
||||
{t('profileLoadPage.retry')}
|
||||
<Button mode='contained' onPress={nextStep} disabled={contactsCount === undefined}>
|
||||
{t('profileLoadPage.nextStep')}
|
||||
</Button>
|
||||
<Button mode='contained' onPress={() => setUserState('ready')}>
|
||||
<Button mode='outlined' onPress={() => setUserState('ready')}>
|
||||
{t('profileLoadPage.home')}
|
||||
</Button>
|
||||
</View>
|
||||
@ -126,7 +174,7 @@ const styles = StyleSheet.create({
|
||||
flex: 1,
|
||||
},
|
||||
buttons: {
|
||||
height: 120,
|
||||
height: 100,
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
logo: {
|
||||
@ -134,6 +182,9 @@ const styles = StyleSheet.create({
|
||||
alignContent: 'center',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
list: {
|
||||
maxHeight: 400,
|
||||
},
|
||||
center: {
|
||||
alignContent: 'center',
|
||||
textAlign: 'center',
|
||||
@ -146,6 +197,35 @@ const styles = StyleSheet.create({
|
||||
activityIndicator: {
|
||||
paddingRight: 16,
|
||||
},
|
||||
titleWrapper: {
|
||||
marginBottom: 4,
|
||||
marginTop: 24,
|
||||
},
|
||||
title: {
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
marginBottom: 8,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
relayItem: {
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
},
|
||||
relayButtons: {
|
||||
paddingBottom: 16,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
relayButton: {
|
||||
marginRight: 16,
|
||||
},
|
||||
relayActionButtons: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
relayColor: {
|
||||
paddingTop: 9,
|
||||
},
|
||||
})
|
||||
|
||||
export default SecondStep
|
||||
|
187
frontend/Pages/ProfileLoadPage/ThirdStep/index.tsx
Normal file
187
frontend/Pages/ProfileLoadPage/ThirdStep/index.tsx
Normal file
@ -0,0 +1,187 @@
|
||||
import React, { useContext, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { FlatList, type ListRenderItem, ScrollView, StyleSheet, View } from 'react-native'
|
||||
import { Button, Divider, List, Text } from 'react-native-paper'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import Logo from '../../../Components/Logo'
|
||||
import { AppContext } from '../../../Contexts/AppContext'
|
||||
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 } from '../../../Functions/DatabaseFunctions/RelayMetadatas'
|
||||
import { getContactsRelays } from '../../../Functions/RelayFunctions/Metadata'
|
||||
|
||||
interface ThirdStepProps {
|
||||
nextStep: () => void
|
||||
}
|
||||
|
||||
export const ThirdStep: React.FC<ThirdStepProps> = ({ nextStep }) => {
|
||||
const { t } = useTranslation('common')
|
||||
const { database } = useContext(AppContext)
|
||||
const { relayPool, relayPoolReady, lastEventId, relays, addRelayItem } =
|
||||
useContext(RelayPoolContext)
|
||||
const { publicKey, setUserState } = useContext(UserContext)
|
||||
const [asignation, setAsignation] = useState<string[]>()
|
||||
|
||||
React.useEffect(() => {
|
||||
loadPetsRelays()
|
||||
}, [])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (database) {
|
||||
getAllRelayMetadata(database).then((relayMetadata) => {
|
||||
getContactsRelays(relays, relayMetadata).then(setAsignation)
|
||||
})
|
||||
}
|
||||
}, [lastEventId])
|
||||
|
||||
const loadPetsRelays: () => void = () => {
|
||||
if (database && publicKey && relayPoolReady) {
|
||||
getUsers(database, {}).then((results) => {
|
||||
if (results.length > 0) {
|
||||
const authors = [...results.map((user: User) => user.id), publicKey]
|
||||
relayPool?.subscribe('profile-load-relays', [
|
||||
{
|
||||
kinds: [10002],
|
||||
authors,
|
||||
},
|
||||
])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const renderItem: ListRenderItem<string> = ({ item, index }) => {
|
||||
return (
|
||||
<View style={styles.relayItem}>
|
||||
<List.Item
|
||||
key={index}
|
||||
title={item.replace('wss://', '').replace('ws://', '')}
|
||||
left={() => (
|
||||
<MaterialCommunityIcons
|
||||
style={styles.relayColor}
|
||||
name='circle'
|
||||
color={relayToColor(item)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const connect: () => void = () => {
|
||||
if (asignation) {
|
||||
asignation.forEach(async (url) => await addRelayItem({ url, resilient: 1, global_feed: 0 }))
|
||||
}
|
||||
setUserState('ready')
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View>
|
||||
<View style={styles.loadingProfile}>
|
||||
<Text variant='titleMedium'>{t('profileLoadPage.connectedRelays')}</Text>
|
||||
<Text variant='titleMedium' style={{ color: '#7ADC70' }}>
|
||||
{relays.length}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.logo}>
|
||||
<Logo onlyIcon size='medium' />
|
||||
</View>
|
||||
<View style={styles.loadingProfile}>
|
||||
<Text variant='titleMedium' style={styles.center}>
|
||||
{t('profileLoadPage.contactRelaysDescription')}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.list}>
|
||||
<View style={styles.titleWrapper}>
|
||||
<Text style={styles.title} variant='titleMedium'>
|
||||
{t('profileLoadPage.contactRelays')}
|
||||
</Text>
|
||||
<Divider />
|
||||
</View>
|
||||
<ScrollView horizontal={false}>
|
||||
<FlatList
|
||||
showsVerticalScrollIndicator={false}
|
||||
data={asignation}
|
||||
renderItem={renderItem}
|
||||
ItemSeparatorComponent={Divider}
|
||||
/>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.buttons}>
|
||||
<Button mode='contained' onPress={connect}>
|
||||
{t('profileLoadPage.connect')}
|
||||
</Button>
|
||||
<Button mode='outlined' onPress={() => setUserState('ready')}>
|
||||
{t('profileLoadPage.home')}
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
padding: 16,
|
||||
justifyContent: 'space-between',
|
||||
flex: 1,
|
||||
},
|
||||
buttons: {
|
||||
height: 100,
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
logo: {
|
||||
justifyContent: 'center',
|
||||
alignContent: 'center',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
list: {
|
||||
maxHeight: 450,
|
||||
},
|
||||
center: {
|
||||
alignContent: 'center',
|
||||
textAlign: 'center',
|
||||
},
|
||||
loadingProfile: {
|
||||
justifyContent: 'center',
|
||||
alignContent: 'center',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
activityIndicator: {
|
||||
paddingRight: 16,
|
||||
},
|
||||
titleWrapper: {
|
||||
marginBottom: 4,
|
||||
marginTop: 24,
|
||||
},
|
||||
title: {
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
marginBottom: 8,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
relayItem: {
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
},
|
||||
relayButtons: {
|
||||
paddingBottom: 16,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
relayButton: {
|
||||
marginRight: 16,
|
||||
},
|
||||
relayActionButtons: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
relayColor: {
|
||||
paddingTop: 9,
|
||||
},
|
||||
})
|
||||
|
||||
export default ThirdStep
|
@ -4,6 +4,7 @@ import { StyleSheet, View } from 'react-native'
|
||||
import { useFocusEffect } from '@react-navigation/native'
|
||||
import FirstStep from './FirstStep'
|
||||
import SecondStep from './SecondStep'
|
||||
import ThirdStep from './ThirdStep'
|
||||
|
||||
export const ProfileLoadPage: React.FC = () => {
|
||||
const { relayPool } = useContext(RelayPoolContext)
|
||||
@ -15,8 +16,8 @@ export const ProfileLoadPage: React.FC = () => {
|
||||
relayPool?.unsubscribe([
|
||||
'profile-load-meta',
|
||||
'profile-load-contacts',
|
||||
'profile-load-others',
|
||||
'profile-load-notes',
|
||||
'profile-load-relays',
|
||||
])
|
||||
}, []),
|
||||
)
|
||||
@ -29,6 +30,7 @@ export const ProfileLoadPage: React.FC = () => {
|
||||
<View style={styles.container}>
|
||||
{step === 0 && <FirstStep nextStep={nextStep} />}
|
||||
{step === 1 && <SecondStep nextStep={nextStep} />}
|
||||
{step === 2 && <ThirdStep nextStep={nextStep} />}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
import React, { useContext, useState, useEffect } from 'react'
|
||||
import { NativeScrollEvent, NativeSyntheticEvent, StyleSheet, View } from 'react-native'
|
||||
import { type NativeScrollEvent, type NativeSyntheticEvent, StyleSheet, View } from 'react-native'
|
||||
import { AppContext } from '../../../Contexts/AppContext'
|
||||
import { getNotes, Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { getNotes, type Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { RelayPoolContext } from '../../../Contexts/RelayPoolContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { ActivityIndicator, Text, useTheme } from 'react-native-paper'
|
||||
import NoteCard from '../../../Components/NoteCard'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import { handleInfinityScroll } from '../../../Functions/NativeFunctions'
|
||||
import { getETags } from '../../../Functions/RelayFunctions/Events'
|
||||
import { getList } from '../../../Functions/DatabaseFunctions/Lists'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
import { type RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
|
||||
interface BookmarksFeedProps {
|
||||
publicKey: string
|
||||
|
@ -1,14 +1,14 @@
|
||||
import React, { useContext, useState, useEffect } from 'react'
|
||||
import { NativeScrollEvent, NativeSyntheticEvent, StyleSheet, View } from 'react-native'
|
||||
import { type NativeScrollEvent, type NativeSyntheticEvent, StyleSheet, View } from 'react-native'
|
||||
import { AppContext } from '../../../Contexts/AppContext'
|
||||
import { getMainNotes, Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { getMainNotes, type Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { RelayPoolContext } from '../../../Contexts/RelayPoolContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { ActivityIndicator } from 'react-native-paper'
|
||||
import NoteCard from '../../../Components/NoteCard'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import { handleInfinityScroll } from '../../../Functions/NativeFunctions'
|
||||
import { RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
import { type RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
|
||||
interface NotesFeedProps {
|
||||
publicKey: string
|
||||
|
@ -1,14 +1,14 @@
|
||||
import React, { useContext, useState, useEffect } from 'react'
|
||||
import { NativeScrollEvent, NativeSyntheticEvent, StyleSheet, View } from 'react-native'
|
||||
import { type NativeScrollEvent, type NativeSyntheticEvent, StyleSheet, View } from 'react-native'
|
||||
import { AppContext } from '../../../Contexts/AppContext'
|
||||
import { getReplyNotes, Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { getReplyNotes, type Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { RelayPoolContext } from '../../../Contexts/RelayPoolContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { ActivityIndicator } from 'react-native-paper'
|
||||
import NoteCard from '../../../Components/NoteCard'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import { handleInfinityScroll } from '../../../Functions/NativeFunctions'
|
||||
import { RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
import { type RelayFilters } from '../../../lib/nostr/RelayPool/intex'
|
||||
|
||||
interface RepliesFeedProps {
|
||||
publicKey: string
|
||||
|
@ -1,12 +1,12 @@
|
||||
import React, { useContext, useState, useEffect } from 'react'
|
||||
import { NativeScrollEvent, NativeSyntheticEvent, StyleSheet, View } from 'react-native'
|
||||
import { type NativeScrollEvent, type NativeSyntheticEvent, StyleSheet, View } from 'react-native'
|
||||
import { AppContext } from '../../../Contexts/AppContext'
|
||||
import { getNotes, Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { getNotes, type Note } from '../../../Functions/DatabaseFunctions/Notes'
|
||||
import { RelayPoolContext } from '../../../Contexts/RelayPoolContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { ActivityIndicator } from 'react-native-paper'
|
||||
import NoteCard from '../../../Components/NoteCard'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import { getMostZapedNotes } from '../../../Functions/DatabaseFunctions/Zaps'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import { handleInfinityScroll } from '../../../Functions/NativeFunctions'
|
||||
|
@ -4,7 +4,7 @@ import { Surface, Text, Snackbar } from 'react-native-paper'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { UserContext } from '../../Contexts/UserContext'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { getUser, User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { getUser, type User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useFocusEffect } from '@react-navigation/native'
|
||||
|
@ -1,19 +1,19 @@
|
||||
import React, { useCallback, useContext, useState, useEffect } from 'react'
|
||||
import {
|
||||
NativeScrollEvent,
|
||||
NativeSyntheticEvent,
|
||||
type NativeScrollEvent,
|
||||
type NativeSyntheticEvent,
|
||||
RefreshControl,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { getReactedNotes, Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { getReactedNotes, type Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { handleInfinityScroll } from '../../Functions/NativeFunctions'
|
||||
import { UserContext } from '../../Contexts/UserContext'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
import { type RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
import { ActivityIndicator, Text } from 'react-native-paper'
|
||||
import NoteCard from '../../Components/NoteCard'
|
||||
import { useTheme } from '@react-navigation/native'
|
||||
|
@ -1,8 +1,15 @@
|
||||
import React, { useContext, useState } from 'react'
|
||||
import { Clipboard, FlatList, ListRenderItem, ScrollView, StyleSheet, View } from 'react-native'
|
||||
import {
|
||||
Clipboard,
|
||||
FlatList,
|
||||
type ListRenderItem,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { Relay } from '../../Functions/DatabaseFunctions/Relays'
|
||||
import { type Relay } from '../../Functions/DatabaseFunctions/Relays'
|
||||
import { REGEX_SOCKET_LINK } from '../../Constants/Relay'
|
||||
import {
|
||||
List,
|
||||
@ -21,7 +28,7 @@ import { relayToColor } from '../../Functions/NativeFunctions'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import { useFocusEffect } from '@react-navigation/native'
|
||||
import { UserContext } from '../../Contexts/UserContext'
|
||||
import { Event } from '../../lib/nostr/Events'
|
||||
import { type Event } from '../../lib/nostr/Events'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
|
||||
export const RelaysPage: React.FC = () => {
|
||||
@ -126,12 +133,14 @@ export const RelaysPage: React.FC = () => {
|
||||
|
||||
const onPressPushRelay: () => void = () => {
|
||||
if (publicKey) {
|
||||
const activeRelays = relays.filter((relay) => relay?.active)
|
||||
const activeRelays = relays.filter(
|
||||
(relay) => relay?.active && (!relay.resilient || relay.resilient < 0),
|
||||
)
|
||||
const tags: string[][] = activeRelays.map((relay) => [
|
||||
'r',
|
||||
relay.url ?? '',
|
||||
relay.mode ?? '',
|
||||
relay.paid ? 'paid' : 'free',
|
||||
relay.paid ? 'paid' : '',
|
||||
])
|
||||
const event: Event = {
|
||||
content: '',
|
||||
@ -174,14 +183,16 @@ export const RelaysPage: React.FC = () => {
|
||||
key={index}
|
||||
title={item.url.replace('wss://', '').replace('ws://', '')}
|
||||
right={() => {
|
||||
if (!item?.paid) return <></>
|
||||
return (
|
||||
const icons: string[] = []
|
||||
if (item?.paid) icons.push('wallet-outline')
|
||||
return icons.map((icon) => (
|
||||
<MaterialCommunityIcons
|
||||
name='wallet-outline'
|
||||
key={icon}
|
||||
name={icon}
|
||||
size={16}
|
||||
color={theme.colors.onPrimaryContainer}
|
||||
/>
|
||||
)
|
||||
))
|
||||
}}
|
||||
left={() => (
|
||||
<MaterialCommunityIcons
|
||||
@ -258,12 +269,31 @@ export const RelaysPage: React.FC = () => {
|
||||
showsVerticalScrollIndicator={false}
|
||||
data={relays.filter((relay) => {
|
||||
return (
|
||||
((relay.paid === undefined || relay.paid < 1) && showFreeRelays) ||
|
||||
(relay.paid !== undefined && relay.paid > 0 && showPaidRelays)
|
||||
(!relay.resilient &&
|
||||
(relay.paid === undefined || relay.paid < 1) &&
|
||||
showFreeRelays) ||
|
||||
(!relay.resilient && relay.paid !== undefined && relay.paid > 0 && showPaidRelays)
|
||||
)
|
||||
})}
|
||||
renderItem={renderItem}
|
||||
ItemSeparatorComponent={Divider}
|
||||
/>
|
||||
<View style={styles.titleWrapper}>
|
||||
<Text style={styles.title} variant='titleMedium'>
|
||||
{t('relaysPage.contactsList')}
|
||||
</Text>
|
||||
<Divider />
|
||||
</View>
|
||||
<FlatList
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={styles.relayList}
|
||||
data={relays.filter((relay) => {
|
||||
return (
|
||||
(relay.resilient && (relay.paid === undefined || relay.paid < 1) && showFreeRelays) ??
|
||||
(relay.resilient && relay.paid !== undefined && relay.paid > 0 && showPaidRelays)
|
||||
)
|
||||
})}
|
||||
renderItem={renderItem}
|
||||
ItemSeparatorComponent={Divider}
|
||||
/>
|
||||
</ScrollView>
|
||||
@ -300,6 +330,7 @@ export const RelaysPage: React.FC = () => {
|
||||
<View style={styles.addRelay}>
|
||||
<View style={styles.bottomDrawerButton}>
|
||||
<Text variant='titleLarge'>{t('relaysPage.pushListTitle')}</Text>
|
||||
<Text variant='bodyMedium'>{t('relaysPage.pushListDescription')}</Text>
|
||||
</View>
|
||||
<View style={styles.bottomDrawerButton}>
|
||||
<Button mode='contained' onPress={onPressPushRelay}>
|
||||
|
@ -1,19 +1,19 @@
|
||||
import React, { useCallback, useContext, useState, useEffect } from 'react'
|
||||
import {
|
||||
NativeScrollEvent,
|
||||
NativeSyntheticEvent,
|
||||
type NativeScrollEvent,
|
||||
type NativeSyntheticEvent,
|
||||
RefreshControl,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { FlashList, ListRenderItem } from '@shopify/flash-list'
|
||||
import { FlashList, type ListRenderItem } from '@shopify/flash-list'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { getRepostedNotes, Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { getRepostedNotes, type Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { handleInfinityScroll } from '../../Functions/NativeFunctions'
|
||||
import { UserContext } from '../../Contexts/UserContext'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
import { type RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
import { ActivityIndicator, Text } from 'react-native-paper'
|
||||
import NoteCard from '../../Components/NoteCard'
|
||||
import { useTheme } from '@react-navigation/native'
|
||||
|
@ -1,13 +1,13 @@
|
||||
import React, { useContext, useEffect, useState } from 'react'
|
||||
import { Dimensions, ScrollView, StyleSheet, View } from 'react-native'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { Event } from '../../lib/nostr/Events'
|
||||
import { type Event } from '../../lib/nostr/Events'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import getUnixTime from 'date-fns/getUnixTime'
|
||||
import { Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { type Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { getETags } from '../../Functions/RelayFunctions/Events'
|
||||
import { getUsers, User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { getUsers, type User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { formatPubKey } from '../../Functions/RelayFunctions/Users'
|
||||
import { Button, IconButton, Switch, Text, TextInput, useTheme } from 'react-native-paper'
|
||||
import { UserContext } from '../../Contexts/UserContext'
|
||||
|
@ -5,7 +5,7 @@ interface RelayPoolInterface {
|
||||
sendAll: (message: string, globalFeed: boolean) => void
|
||||
sendRelay: (message: string, relayUrl: string) => void
|
||||
connect: (pubKey: string, callback: (eventId: string) => void) => void
|
||||
add: (url: string, callback: () => void) => void
|
||||
add: (url: string, resilient: number, globalFeed: number, callback: () => void) => void
|
||||
remove: (url: string, callback: () => void) => void
|
||||
removeAll: (callback?: () => void) => void
|
||||
update: (
|
||||
|
@ -1,5 +1,5 @@
|
||||
import schnorr from 'bip-schnorr'
|
||||
import { Kind } from 'nostr-tools'
|
||||
import { type Kind } from 'nostr-tools'
|
||||
|
||||
export interface Event {
|
||||
content: string
|
||||
|
@ -1,10 +1,10 @@
|
||||
import {
|
||||
decode,
|
||||
EventPointer,
|
||||
type EventPointer,
|
||||
neventEncode,
|
||||
nprofileEncode,
|
||||
npubEncode,
|
||||
ProfilePointer,
|
||||
type ProfilePointer,
|
||||
} from 'nostr-tools/nip19'
|
||||
|
||||
export function getNpub(key: string | undefined): string {
|
||||
|
@ -1,10 +1,5 @@
|
||||
// import { spawnThread } from 'react-native-multithreading'
|
||||
import { signEvent, validateEvent, Event } from '../Events'
|
||||
import { signEvent, validateEvent, type Event } from '../Events'
|
||||
import RelayPoolModule from '../../Native/WebsocketModule'
|
||||
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
|
||||
import { median, randomInt } from '../../../Functions/NativeFunctions'
|
||||
import { getNoteRelaysPresence } from '../../../Functions/DatabaseFunctions/NotesRelays'
|
||||
import DatabaseModule from '../../Native/DatabaseModule'
|
||||
|
||||
export interface RelayFilters {
|
||||
ids?: string[]
|
||||
@ -21,13 +16,6 @@ export interface RelayMessage {
|
||||
data: string
|
||||
}
|
||||
|
||||
export interface ResilientAssignation {
|
||||
resilientRelays: Record<string, string[]>
|
||||
smallRelays: Record<string, string[]>
|
||||
centralizedRelays: Record<string, string[]>
|
||||
fallback: Record<string, string[]>
|
||||
}
|
||||
|
||||
export const fallbackRelays = [
|
||||
'wss://brb.io',
|
||||
'wss://nostr-pub.wellorder.net',
|
||||
@ -78,17 +66,10 @@ class RelayPool {
|
||||
constructor(privateKey?: string) {
|
||||
this.privateKey = privateKey
|
||||
this.subscriptions = {}
|
||||
this.resilientAssignation = {
|
||||
resilientRelays: {},
|
||||
smallRelays: {},
|
||||
centralizedRelays: {},
|
||||
fallback: {},
|
||||
}
|
||||
}
|
||||
|
||||
private readonly privateKey?: string
|
||||
private subscriptions: Record<string, string[]>
|
||||
public resilientAssignation: ResilientAssignation
|
||||
|
||||
private readonly sendAll: (message: object, globalFeed?: boolean) => void = async (
|
||||
message,
|
||||
@ -111,94 +92,13 @@ class RelayPool {
|
||||
RelayPoolModule.connect(publicKey, onEventId)
|
||||
}
|
||||
|
||||
public readonly resilientMode: (db: QuickSQLiteConnection, publicKey: string) => void = async (
|
||||
db,
|
||||
) => {
|
||||
await DatabaseModule.desactivateResilientRelays()
|
||||
// Get relays with contacts' pubkeys with at least one event found, randomly sorted
|
||||
const relaysPresence: Record<string, string[]> = await getNoteRelaysPresence(db)
|
||||
// Median of users per relay
|
||||
const medianUsage = median(
|
||||
Object.keys(relaysPresence).map((relay) => relaysPresence[relay].length),
|
||||
)
|
||||
|
||||
// Sort relays by abs distance from the mediam
|
||||
const relaysByPresence = Object.keys(relaysPresence).sort((n1: string, n2: string) => {
|
||||
return (
|
||||
Math.abs(relaysPresence[n1].length - medianUsage) -
|
||||
Math.abs(relaysPresence[n2].length - medianUsage)
|
||||
)
|
||||
})
|
||||
// Get top5 relays closer to the mediam
|
||||
const medianRelays = relaysByPresence.slice(0, 5)
|
||||
|
||||
// Set helpers
|
||||
let biggestRelayLenght = 0
|
||||
this.resilientAssignation.resilientRelays = {}
|
||||
const allocatedUsers: string[] = []
|
||||
medianRelays.forEach((relayUrl) => {
|
||||
this.resilientAssignation.resilientRelays[relayUrl] = []
|
||||
const length = relaysPresence[relayUrl].length
|
||||
if (length > biggestRelayLenght) biggestRelayLenght = length
|
||||
})
|
||||
|
||||
// Iterate over the N index of top5 relay list removing identical pubkey from others
|
||||
for (let index = 0; index < biggestRelayLenght - 1; index++) {
|
||||
medianRelays.forEach((relayUrl) => {
|
||||
const pubKey = relaysPresence[relayUrl][index]
|
||||
if (pubKey && !allocatedUsers.includes(pubKey)) {
|
||||
allocatedUsers.push(pubKey)
|
||||
this.resilientAssignation.resilientRelays[relayUrl].push(pubKey)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Iterate over remaining relays and assigns as much remaining users as possible
|
||||
relaysByPresence.slice(5, relaysByPresence.length).forEach((relayUrl) => {
|
||||
relaysPresence[relayUrl].forEach((pubKey) => {
|
||||
if (!allocatedUsers.includes(pubKey)) {
|
||||
allocatedUsers.push(pubKey)
|
||||
if (relaysPresence[relayUrl].length > medianUsage) {
|
||||
if (!this.resilientAssignation.centralizedRelays[relayUrl])
|
||||
this.resilientAssignation.centralizedRelays[relayUrl] = []
|
||||
this.resilientAssignation.centralizedRelays[relayUrl].push(pubKey)
|
||||
} else {
|
||||
if (!this.resilientAssignation.smallRelays[relayUrl])
|
||||
this.resilientAssignation.smallRelays[relayUrl] = []
|
||||
this.resilientAssignation.smallRelays[relayUrl].push(pubKey)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Target list size is 5, adds random relays from a fallback list
|
||||
const resilientUrls = [
|
||||
...Object.keys(this.resilientAssignation.resilientRelays),
|
||||
...Object.keys(this.resilientAssignation.centralizedRelays),
|
||||
...Object.keys(this.resilientAssignation.smallRelays),
|
||||
]
|
||||
while (resilientUrls.length < 5) {
|
||||
let fallbackRelay = ''
|
||||
while (fallbackRelay === '') {
|
||||
const randomRelayIndex = randomInt(0, fallbackRelays.length - 1)
|
||||
if (!resilientUrls.includes(fallbackRelays[randomRelayIndex])) {
|
||||
fallbackRelay = fallbackRelays[randomRelayIndex]
|
||||
}
|
||||
}
|
||||
resilientUrls.push(fallbackRelay)
|
||||
this.resilientAssignation.centralizedRelays[fallbackRelay] = []
|
||||
}
|
||||
|
||||
// Stores in DB
|
||||
// resilientUrls.forEach((url) => DatabaseModule.createResilientRelay(url))
|
||||
// resilientUrls.forEach((url) => DatabaseModule.activateResilientRelay(url))
|
||||
}
|
||||
|
||||
public readonly add: (relayUrl: string, callback?: () => void) => void = async (
|
||||
relayUrl,
|
||||
callback = () => {},
|
||||
) => {
|
||||
RelayPoolModule.add(relayUrl, callback)
|
||||
public readonly add: (
|
||||
relayUrl: string,
|
||||
resilient: number,
|
||||
globalFeed: number,
|
||||
callback?: () => void,
|
||||
) => void = async (relayUrl, resilient, globalFeed, callback = () => {}) => {
|
||||
RelayPoolModule.add(relayUrl, resilient, globalFeed, callback)
|
||||
}
|
||||
|
||||
public readonly remove: (relayUrl: string, callback?: () => void) => void = async (
|
||||
|
10
package.json
10
package.json
@ -29,20 +29,20 @@
|
||||
"cryptr": "^6.1.0",
|
||||
"date-fns": "^2.29.3",
|
||||
"events": "^3.3.0",
|
||||
"i18next": "^22.4.9",
|
||||
"i18next": "^22.4.10",
|
||||
"lnurl-pay": "^2.2.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"nostr-tools": "^1.2.1",
|
||||
"react": "18.2.0",
|
||||
"react-content-loader": "^6.2.0",
|
||||
"react-i18next": "^12.1.5",
|
||||
"react-i18next": "^12.2.0",
|
||||
"react-native": "0.70.6",
|
||||
"react-native-action-button": "^2.8.5",
|
||||
"react-native-bidirectional-infinite-scroll": "^0.3.3",
|
||||
"react-native-blob-util": "^0.17.1",
|
||||
"react-native-fast-image": "^8.6.3",
|
||||
"react-native-gesture-handler": "^2.8.0",
|
||||
"react-native-image-picker": "^5.0.1",
|
||||
"react-native-image-picker": "^5.1.0",
|
||||
"react-native-multithreading": "^1.1.1",
|
||||
"react-native-pager-view": "^6.1.4",
|
||||
"react-native-paper": "^5.1.3",
|
||||
@ -81,7 +81,7 @@
|
||||
"@types/react-native": "^0.70.8",
|
||||
"@types/react-native-sqlite-storage": "^5.0.2",
|
||||
"@types/react-native-vector-icons": "^6.4.13",
|
||||
"@types/react-test-renderer": "^16.9.2",
|
||||
"@types/react-test-renderer": "^18.0.0",
|
||||
"@types/sqlstring": "^2.3.0",
|
||||
"@types/uuid": "^9.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.43.0",
|
||||
@ -100,7 +100,7 @@
|
||||
"jest": "^29.4.3",
|
||||
"metro-react-native-babel-preset": "^0.75.0",
|
||||
"prettier": "^2.8.4",
|
||||
"react-test-renderer": "18.1.0",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"resolutions": {
|
||||
|
57
yarn.lock
57
yarn.lock
@ -1795,14 +1795,14 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-test-renderer@^16.9.2":
|
||||
version "16.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-16.9.5.tgz#edab67da470f7c3e997f58d55dcfe2643cc30a68"
|
||||
integrity sha512-C4cN7C2uSSGOYelp2XfdtJb5TsCP+QiZ+0Bm4U3ZfUswN8oN9O/l86XO/OvBSFCmWY7w75fzsQvZ50eGkFN34A==
|
||||
"@types/react-test-renderer@^18.0.0":
|
||||
version "18.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-18.0.0.tgz#7b7f69ca98821ea5501b21ba24ea7b6139da2243"
|
||||
integrity sha512-C7/5FBJ3g3sqUahguGi03O79b8afNeSD6T8/GU50oQrJCU0bVCCGQHaGKUbg2Ce8VQEEqTw8/HiS6lXHHdgkdQ==
|
||||
dependencies:
|
||||
"@types/react" "^16"
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^16", "@types/react@^17":
|
||||
"@types/react@*", "@types/react@^17":
|
||||
version "17.0.52"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.52.tgz#10d8b907b5c563ac014a541f289ae8eaa9bf2e9b"
|
||||
integrity sha512-vwk8QqVODi0VaZZpDXQCmEmiOuyjEFPY7Ttaw5vjM112LOq37yz1CDJGrRJwA1fYEq4Iitd5rnjd1yWAc/bT+A==
|
||||
@ -4601,10 +4601,10 @@ human-signals@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
|
||||
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
|
||||
|
||||
i18next@^22.4.9:
|
||||
version "22.4.9"
|
||||
resolved "https://registry.yarnpkg.com/i18next/-/i18next-22.4.9.tgz#98c8384c6bd41ff937da98b1e809ba03d3b41053"
|
||||
integrity sha512-8gWMmUz460KJDQp/ob3MNUX84cVuDRY9PLFPnV8d+Qezz/6dkjxwOaH70xjrCNDO+JrUL25iXfAIN9wUkInNZw==
|
||||
i18next@^22.4.10:
|
||||
version "22.4.11"
|
||||
resolved "https://registry.yarnpkg.com/i18next/-/i18next-22.4.11.tgz#8b6c9be95176de90d3f10a78af125d95d3a3258d"
|
||||
integrity sha512-ShfTzXVMjXdF2iPiT/wbizOrssLh9Ab6VpuVROihLCAu+u25KbZiEYVgsA0W6g0SgjPa/JmGWcUEV/g6cKzEjQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.20.6"
|
||||
|
||||
@ -6944,15 +6944,15 @@ react-freeze@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/react-freeze/-/react-freeze-1.0.3.tgz#5e3ca90e682fed1d73a7cb50c2c7402b3e85618d"
|
||||
integrity sha512-ZnXwLQnGzrDpHBHiC56TXFXvmolPeMjTn1UOm610M4EXGzbEDR7oOIyS2ZiItgbs6eZc4oU/a0hpk8PrcKvv5g==
|
||||
|
||||
react-i18next@^12.1.5:
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-12.1.5.tgz#b65f5733dd2f96188a9359c009b7dbe27443f009"
|
||||
integrity sha512-7PQAv6DA0TcStG96fle+8RfTwxVbHVlZZJPoEszwUNvDuWpGldJmNWa3ZPesEsZQZGF6GkzwvEh6p57qpFD2gQ==
|
||||
react-i18next@^12.2.0:
|
||||
version "12.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-12.2.0.tgz#010e3f6070b8d700442947233352ebe4b252d7a1"
|
||||
integrity sha512-5XeVgSygaGfyFmDd2WcXvINRw2WEC1XviW1LXY/xLOEMzsCFRwKqfnHN+hUjla8ZipbVJR27GCMSuTr0BhBBBQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.20.6"
|
||||
html-parse-stringify "^3.0.1"
|
||||
|
||||
"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.1.0:
|
||||
"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
|
||||
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
|
||||
@ -7018,10 +7018,10 @@ react-native-gradle-plugin@^0.70.3:
|
||||
resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.70.3.tgz#cbcf0619cbfbddaa9128701aa2d7b4145f9c4fc8"
|
||||
integrity sha512-oOanj84fJEXUg9FoEAQomA8ISG+DVIrTZ3qF7m69VQUJyOGYyDZmPqKcjvRku4KXlEH6hWO9i4ACLzNBh8gC0A==
|
||||
|
||||
react-native-image-picker@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react-native-image-picker/-/react-native-image-picker-5.0.1.tgz#c9e99217396bc82a977785e39e14afb4819e8448"
|
||||
integrity sha512-+poQTHOnEGrbxJnut591XA9006svFOyfPg/i5bv+fLuwoSHh5HW0E/PVhvT8lbX0Z5C108vh3DAsnrfFFnPBGw==
|
||||
react-native-image-picker@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-image-picker/-/react-native-image-picker-5.1.0.tgz#78b84533a52a8e9704bacf6d18e7c979d9766271"
|
||||
integrity sha512-p506trG3PDSrdm+Yd0QolsnR3FtSe37gkP7OVsMa9UYwn1teaLGzhmx3QMZ4ZBwdV1AKBUFA5HF1ECAVSDTdQQ==
|
||||
|
||||
react-native-multithreading@^1.1.1:
|
||||
version "1.1.1"
|
||||
@ -7199,14 +7199,14 @@ react-shallow-renderer@^16.15.0:
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.12.0 || ^17.0.0 || ^18.0.0"
|
||||
|
||||
react-test-renderer@18.1.0:
|
||||
version "18.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-18.1.0.tgz#35b75754834cf9ab517b6813db94aee0a6b545c3"
|
||||
integrity sha512-OfuueprJFW7h69GN+kr4Ywin7stcuqaYAt1g7airM5cUgP0BoF5G5CXsPGmXeDeEkncb2fqYNECO4y18sSqphg==
|
||||
react-test-renderer@18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-18.2.0.tgz#1dd912bd908ff26da5b9fca4fd1c489b9523d37e"
|
||||
integrity sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==
|
||||
dependencies:
|
||||
react-is "^18.1.0"
|
||||
react-is "^18.2.0"
|
||||
react-shallow-renderer "^16.15.0"
|
||||
scheduler "^0.22.0"
|
||||
scheduler "^0.23.0"
|
||||
|
||||
react@18.2.0:
|
||||
version "18.2.0"
|
||||
@ -7511,6 +7511,13 @@ scheduler@^0.22.0:
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
scheduler@^0.23.0:
|
||||
version "0.23.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
|
||||
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
secp256k1@^4.0.2:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303"
|
||||
|
Loading…
Reference in New Issue
Block a user