seen user db

This commit is contained in:
Alejandro Gomez 2023-01-15 02:46:13 +01:00
parent 5cc08aaace
commit 344e309d4e
No known key found for this signature in database
GPG Key ID: 4DF39E566658C817
8 changed files with 77 additions and 16 deletions

View File

@ -16,6 +16,8 @@
"@types/webscopeio__react-textarea-autocomplete": "^4.7.2",
"@webscopeio/react-textarea-autocomplete": "^4.9.2",
"bech32": "^2.0.0",
"dexie": "^3.2.2",
"dexie-react-hooks": "^1.1.1",
"light-bolt11-decoder": "^2.1.0",
"qr-code-styling": "^1.6.0-rc.1",
"react": "^18.2.0",

16
src/db.ts Normal file
View File

@ -0,0 +1,16 @@
import Dexie, { Table } from 'dexie';
import type { User } from './nostr/types';
export class MySubClassedDexie extends Dexie {
users!: Table<User>;
constructor() {
super('snortDB');
this.version(1).stores({
users: '++pubkey, name, display_name, about, nip05' // Primary key and indexed props
});
}
}
export const db = new MySubClassedDexie();

View File

@ -1,4 +1,5 @@
import { Component } from "react";
import { useSelector } from "react-redux";
import { useLiveQuery } from "dexie-react-hooks";
import ReactTextareaAutocomplete from "@webscopeio/react-textarea-autocomplete";
@ -11,10 +12,11 @@ import Nostrich from "../nostrich.jpg";
// @ts-expect-error
import { hexToBech32 } from "../Util";
import type { User } from "../nostr/types";
import { db } from "../db";
function searchUsers(query: string, users: Record<string, User>) {
function searchUsers(query: string, users: User[]) {
const q = query.toLowerCase()
return Object.values(users).filter(({ name, display_name, about, nip05 }) => {
return users.filter(({ name, display_name, about, nip05 }: User) => {
return name?.toLowerCase().includes(q)
|| display_name?.toLowerCase().includes(q)
|| about?.toLowerCase().includes(q)
@ -37,29 +39,39 @@ const UserItem = ({ pubkey, display_name, picture, nip05, ...rest }: User) => {
)
}
export default class Textarea extends Component {
render() {
function normalizeUser({ pubkey, about, nip05, name, display_name }: User) {
return { pubkey, about, nip05, name, display_name }
}
const Textarea = ({ onChange, ...rest }: any) => {
// @ts-expect-error
const { users, onChange, ...rest } = this.props
const { users } = useSelector(s => s.users)
const dbUsers = useLiveQuery(
() => db.users.toArray().then(usrs => {
return usrs.reduce((acc, usr) => {
return { ...acc, [usr.pubkey]: normalizeUser(usr)}
}, {})
})
)
const cachedUsers = dbUsers ? dbUsers : {}
const allUsers: User[] = Object.values({...cachedUsers, ...users})
return (
<ReactTextareaAutocomplete
{...rest}
loadingComponent={() => <span>Loading....</span>}
placeholder="Say something!"
ref={rta => {
// @ts-expect-error
this.rta = rta;
}}
onChange={onChange}
trigger={{
"@": {
afterWhitespace: true,
dataProvider: token => searchUsers(token, users),
dataProvider: token => dbUsers ? searchUsers(token, allUsers) : [],
component: (props: any) => <UserItem {...props.entity} />,
output: (item: any) => `@${hexToBech32("npub", item.pubkey)}`
}
}}
/>
)
}
}
export default Textarea

View File

@ -4,6 +4,7 @@ import EventKind from "../nostr/EventKind";
import { Subscriptions } from "../nostr/Subscriptions";
import { addDirectMessage, addNotifications, setFollows, setRelays } from "../state/Login";
import { setUserData } from "../state/Users";
import { db } from "../db";
import useSubscription from "./Subscription";
import { mapEventToProfile } from "./UsersFeed";
@ -41,7 +42,8 @@ export default function useLoginFeed() {
useEffect(() => {
let contactList = notes.filter(a => a.kind === EventKind.ContactList);
let notifications = notes.filter(a => a.kind === EventKind.TextNote);
let metadata = notes.filter(a => a.kind === EventKind.SetMetadata).map(a => mapEventToProfile(a));
let metadata = notes.filter(a => a.kind === EventKind.SetMetadata)
let profiles = metadata.map(a => mapEventToProfile(a));
let dms = notes.filter(a => a.kind === EventKind.DirectMessage);
for (let cl of contactList) {
@ -60,7 +62,11 @@ export default function useLoginFeed() {
}
}
dispatch(addNotifications(notifications));
dispatch(setUserData(metadata));
dispatch(setUserData(profiles));
const userMetadata = metadata.map(ev => {
return {...JSON.parse(ev.content), pubkey: ev.pubkey }
})
db.users.bulkPut(metadata);
dispatch(addDirectMessage(dms));
}, [notes]);
}

View File

@ -2,6 +2,7 @@ import { useEffect, useMemo } from "react";
import { useDispatch, useSelector } from "react-redux";
import { ProfileCacheExpire } from "../Const";
import EventKind from "../nostr/EventKind";
import { db } from "../db";
import { Subscriptions } from "../nostr/Subscriptions";
import { setUserData } from "../state/Users";
import useSubscription from "./Subscription";
@ -34,7 +35,12 @@ export default function useUsersCache() {
const results = useSubscription(sub);
useEffect(() => {
dispatch(setUserData(results.notes.map(a => mapEventToProfile(a))));
const userData = results.notes.map(a => mapEventToProfile(a));
dispatch(setUserData(userData));
const profiles = results.notes.map(ev => {
return {...JSON.parse(ev.content), pubkey: ev.pubkey }
});
db.users.bulkPut(profiles);
}, [results]);
return results;

View File

@ -1,4 +1,4 @@
export type User = {
export interface User {
name?: string
about?: string
display_name?: string

View File

@ -1,5 +1,6 @@
import { createSlice } from '@reduxjs/toolkit'
import { ProfileCacheExpire } from '../Const';
import { db } from '../db';
const UsersSlice = createSlice({
name: "Users",
@ -67,6 +68,14 @@ const UsersSlice = createSlice({
};
}
state.users[x.pubkey] = x;
db.users.put({
pubkey: x.pubkey,
name: x.name,
display_name: x.display_name,
nip05: x.nip05,
picture: x.picture,
about: x.about,
})
window.localStorage.setItem(`user:${x.pubkey}`, JSON.stringify(x));
state.users = {

View File

@ -3704,6 +3704,16 @@ detective@^5.2.1:
defined "^1.0.0"
minimist "^1.2.6"
dexie-react-hooks@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/dexie-react-hooks/-/dexie-react-hooks-1.1.1.tgz#ff405cc89e5d899ddbac5e40d593f83f9a74106a"
integrity sha512-Cam5JP6PxHN564RvWEoe8cqLhosW0O4CAZ9XEVYeGHJBa6KEJlOpd9CUpV3kmU9dm2MrW97/lk7qkf1xpij7gA==
dexie@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/dexie/-/dexie-3.2.2.tgz#fa6f2a3c0d6ed0766f8d97a03720056f88fe0e01"
integrity sha512-q5dC3HPmir2DERlX+toCBbHQXW5MsyrFqPFcovkH9N2S/UW/H3H5AWAB6iEOExeraAu+j+zRDG+zg/D7YhH0qg==
didyoumean@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"