mirror of
https://github.com/irislib/iris-messenger.git
synced 2024-09-19 01:34:14 +00:00
useProfile hook, hooks reorg
This commit is contained in:
parent
e698638fed
commit
eb3df4098f
@ -4,7 +4,6 @@ import { useEffect, useState } from 'preact/hooks';
|
||||
|
||||
import Events from '../../../nostr/Events';
|
||||
import Key from '../../../nostr/Key';
|
||||
import SocialNetwork from '../../../nostr/SocialNetwork';
|
||||
|
||||
const Like = ({ event }) => {
|
||||
const [state, setState] = useState({
|
||||
@ -14,16 +13,7 @@ const Like = ({ event }) => {
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const unsubProfile = SocialNetwork.getProfile(event.pubkey, (profile) => {
|
||||
if (!profile) return;
|
||||
});
|
||||
|
||||
const unsubLikes = Events.getLikes(event.id, handleLikes);
|
||||
|
||||
return () => {
|
||||
unsubProfile();
|
||||
unsubLikes();
|
||||
};
|
||||
return Events.getLikes(event.id, handleLikes);
|
||||
}, [event]);
|
||||
|
||||
const handleLikes = (likedBy) => {
|
||||
|
@ -3,7 +3,6 @@ import { useEffect, useState } from 'preact/hooks';
|
||||
|
||||
import Events from '../../../nostr/Events';
|
||||
import Key from '../../../nostr/Key';
|
||||
import SocialNetwork from '../../../nostr/SocialNetwork';
|
||||
|
||||
const Repost = ({ event }) => {
|
||||
const [state, setState] = useState({
|
||||
@ -13,16 +12,7 @@ const Repost = ({ event }) => {
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const unsubProfile = SocialNetwork.getProfile(event.pubkey, (profile) => {
|
||||
if (!profile) return;
|
||||
});
|
||||
|
||||
const unsubReposts = Events.getReposts(event.id, handleReposts);
|
||||
|
||||
return () => {
|
||||
unsubProfile();
|
||||
unsubReposts();
|
||||
};
|
||||
return Events.getReposts(event.id, handleReposts);
|
||||
}, [event]);
|
||||
|
||||
const handleReposts = (repostedBy) => {
|
||||
|
@ -4,13 +4,13 @@ import { useEffect, useState } from 'preact/hooks';
|
||||
|
||||
import Show from '@/components/helpers/Show';
|
||||
import EventDB from '@/nostr/EventDB';
|
||||
import { useProfile } from '@/nostr/hooks/useProfile.ts';
|
||||
import Key from '@/nostr/Key';
|
||||
import { getZappingUser } from '@/nostr/utils';
|
||||
import useLocalState from '@/state/useLocalState.ts';
|
||||
import Icons from '@/utils/Icons';
|
||||
|
||||
import Events from '../../../nostr/Events';
|
||||
import SocialNetwork from '../../../nostr/SocialNetwork';
|
||||
import { decodeInvoice, formatAmount } from '../../../utils/Lightning';
|
||||
import ZapModal from '../../modal/Zap';
|
||||
|
||||
@ -20,12 +20,13 @@ const Zap = ({ event }) => {
|
||||
formattedZapAmount: '',
|
||||
zapped: false,
|
||||
showZapModal: false,
|
||||
lightning: undefined,
|
||||
defaultZapAmount: 0,
|
||||
});
|
||||
|
||||
const [defaultZapAmount] = useLocalState('defaultZapAmount', 0);
|
||||
const [longPress, setLongPress] = useState(false); // state to determine if it's a long press
|
||||
const { lud16, lud06 } = useProfile(event.pubkey);
|
||||
const lightning = lud16 || lud06;
|
||||
|
||||
let pressTimer: any = null;
|
||||
|
||||
@ -55,21 +56,7 @@ const Zap = ({ event }) => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const unsubProfile = SocialNetwork.getProfile(event.pubkey, (profile) => {
|
||||
if (!profile) return;
|
||||
const lightning = profile.lud16 || profile.lud06;
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
lightning,
|
||||
}));
|
||||
});
|
||||
|
||||
const unsubZaps = Events.getZaps(event.id, handleZaps);
|
||||
|
||||
return () => {
|
||||
unsubProfile();
|
||||
unsubZaps();
|
||||
};
|
||||
return Events.getZaps(event.id, handleZaps);
|
||||
}, [event]);
|
||||
|
||||
const handleZaps = debounce(
|
||||
@ -102,7 +89,7 @@ const Zap = ({ event }) => {
|
||||
{ leading: true },
|
||||
);
|
||||
|
||||
return state.lightning ? (
|
||||
return lightning ? (
|
||||
<>
|
||||
<a
|
||||
onMouseDown={onMouseDown}
|
||||
@ -120,7 +107,7 @@ const Zap = ({ event }) => {
|
||||
<ZapModal
|
||||
quickZap={!!defaultZapAmount && !longPress}
|
||||
show={true}
|
||||
lnurl={state.lightning}
|
||||
lnurl={lightning}
|
||||
note={event.id}
|
||||
recipient={event.pubkey}
|
||||
onClose={() => setState((prevState) => ({ ...prevState, showZapModal: false }))}
|
||||
|
@ -8,7 +8,7 @@ import ShowNewEvents from '@/components/feed/ShowNewEvents';
|
||||
import { FeedProps } from '@/components/feed/types';
|
||||
import InfiniteScroll from '@/components/helpers/InfiniteScroll';
|
||||
import Show from '@/components/helpers/Show';
|
||||
import useSubscribe from '@/hooks/useSubscribe';
|
||||
import useSubscribe from '@/nostr/hooks/useSubscribe';
|
||||
import Key from '@/nostr/Key';
|
||||
import useHistoryState from '@/state/useHistoryState.ts';
|
||||
import useLocalState from '@/state/useLocalState.ts';
|
||||
|
@ -2,6 +2,8 @@ import React, { useEffect, useState } from 'react';
|
||||
import { sha256 } from '@noble/hashes/sha256';
|
||||
import Identicon from 'identicon.js';
|
||||
|
||||
import { useProfile } from '@/nostr/hooks/useProfile.ts';
|
||||
|
||||
import Key from '../../nostr/Key';
|
||||
import SocialNetwork from '../../nostr/SocialNetwork';
|
||||
import Show from '../helpers/Show';
|
||||
@ -17,16 +19,18 @@ type Props = {
|
||||
};
|
||||
|
||||
const MyAvatar: React.FC<Props> = (props) => {
|
||||
const [picture, setPicture] = useState<string | null>(null);
|
||||
const [name, setName] = useState<string | null>(null);
|
||||
const [activity] = useState<string | null>(null); // TODO
|
||||
const [avatar, setAvatar] = useState<string | null>(null);
|
||||
const [hasError, setHasError] = useState<boolean>(false);
|
||||
|
||||
const hex = React.useMemo(() => Key.toNostrHexAddress(props.str as string), [props.str]);
|
||||
|
||||
const { picture, name } = useProfile(hex || '');
|
||||
|
||||
useEffect(() => {
|
||||
const updateAvatar = () => {
|
||||
if (!hex) {
|
||||
return;
|
||||
}
|
||||
const hash = sha256(hex || (props.str as string));
|
||||
const hexVal = Array.from(new Uint8Array(hash))
|
||||
.map((b) => b.toString(16).padStart(2, '0'))
|
||||
@ -38,20 +42,6 @@ const MyAvatar: React.FC<Props> = (props) => {
|
||||
});
|
||||
|
||||
setAvatar(`data:image/svg+xml;base64,${identicon.toString()}`);
|
||||
};
|
||||
|
||||
if (hex) {
|
||||
updateAvatar();
|
||||
|
||||
const unsub = SocialNetwork.getProfile(hex, (profile) => {
|
||||
if (profile) {
|
||||
setPicture(profile.picture);
|
||||
setName(profile.name);
|
||||
}
|
||||
});
|
||||
|
||||
return () => unsub?.();
|
||||
}
|
||||
}, [hex, props.str]);
|
||||
|
||||
const width = props.width;
|
||||
|
@ -1,25 +0,0 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import SocialNetwork from '../nostr/SocialNetwork';
|
||||
import { ID } from '../utils/UniqueIds';
|
||||
|
||||
export const useProfile = (pub: string) => {
|
||||
const [nostrAddr] = useState(pub);
|
||||
const [profile, setProfile] = useState(SocialNetwork.profiles.get(ID(nostrAddr)));
|
||||
|
||||
useEffect(() => {
|
||||
if (!nostrAddr) return;
|
||||
|
||||
const unsub = SocialNetwork.getProfile(nostrAddr, (p) => {
|
||||
if (p) {
|
||||
setProfile(p);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
unsub();
|
||||
};
|
||||
}, [nostrAddr]);
|
||||
|
||||
return profile;
|
||||
};
|
18
src/js/nostr/hooks/useProfile.ts
Normal file
18
src/js/nostr/hooks/useProfile.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { ID } from '../../utils/UniqueIds.ts';
|
||||
import SocialNetwork from '../SocialNetwork.ts';
|
||||
|
||||
export const useProfile = (pub: string) => {
|
||||
const [profile, setProfile] = useState(SocialNetwork.profiles.get(ID(pub)) || {});
|
||||
|
||||
useEffect(() => {
|
||||
if (!pub) return;
|
||||
|
||||
return SocialNetwork.getProfile(pub, (p) => {
|
||||
p && setProfile(p);
|
||||
});
|
||||
}, [pub]);
|
||||
|
||||
return profile;
|
||||
};
|
@ -2,9 +2,9 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import throttle from 'lodash/throttle';
|
||||
import { Event } from 'nostr-tools';
|
||||
|
||||
import Filter from '@/nostr/Filter';
|
||||
import PubSub from '@/nostr/PubSub';
|
||||
import SortedMap from '@/utils/SortedMap';
|
||||
import Filter from '@/nostr/Filter.ts';
|
||||
import PubSub from '@/nostr/PubSub.ts';
|
||||
import SortedMap from '@/utils/SortedMap.tsx';
|
||||
|
||||
interface SubscribeOptions {
|
||||
filter: Filter;
|
@ -6,8 +6,6 @@ function useHistoryState(initialValue, key) {
|
||||
const myInitialValue = currentHistoryState === undefined ? initialValue : currentHistoryState;
|
||||
const [state, setState] = useState(myInitialValue);
|
||||
|
||||
console.log('loaded history state for key', key, 'with value', currentHistoryState, initialValue);
|
||||
|
||||
const latestValue = useRef(state);
|
||||
|
||||
const throttledSetHistoryState = useRef(
|
||||
|
@ -2,15 +2,16 @@ import { memo, useMemo } from 'react';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { Link, route } from 'preact-router';
|
||||
|
||||
import { useProfile } from '@/nostr/hooks/useProfile';
|
||||
|
||||
import FollowButton from '../components/buttons/Follow';
|
||||
import SmallFeed from '../components/feed/SmallFeed';
|
||||
import SearchBox from '../components/SearchBox';
|
||||
import Avatar from '../components/user/Avatar';
|
||||
import Name from '../components/user/Name';
|
||||
import useCachedFetch from '../hooks/useCachedFetch';
|
||||
import { useProfile } from '../hooks/useProfile';
|
||||
import Events from '../nostr/Events';
|
||||
import Key from '../nostr/Key';
|
||||
import useCachedFetch from '../utils/useCachedFetch.ts';
|
||||
|
||||
const SuggestionProfile = memo(({ pubkey }: { pubkey: string }) => {
|
||||
const profile = useProfile(pubkey);
|
||||
|
@ -2,6 +2,7 @@ import debounce from 'lodash/debounce';
|
||||
import { useEffect, useState } from 'preact/hooks';
|
||||
import { route } from 'preact-router';
|
||||
|
||||
import { ID } from '@/utils/UniqueIds.ts';
|
||||
import { RouteProps } from '@/views/types.ts';
|
||||
|
||||
import Upload from '../../components/buttons/Upload.tsx';
|
||||
@ -19,7 +20,7 @@ const explainers = {
|
||||
};
|
||||
|
||||
const EditProfile: React.FC<RouteProps> = () => {
|
||||
const [profile, setProfile] = useState({});
|
||||
const [profile, setProfile] = useState(SocialNetwork.profiles.get(ID(Key.getPubKey())) || {});
|
||||
const [newFieldName, setNewFieldName] = useState('');
|
||||
const [newFieldValue, setNewFieldValue] = useState('');
|
||||
const [edited, setEdited] = useState(false);
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useEffect, useState } from 'preact/hooks';
|
||||
import { useEffect, useMemo, useState } from 'preact/hooks';
|
||||
import { route } from 'preact-router';
|
||||
|
||||
import SimpleImageModal from '@/components/modal/Image.tsx';
|
||||
import { useProfile } from '@/nostr/hooks/useProfile.ts';
|
||||
import { getEventReplyingTo, isRepost } from '@/nostr/utils.ts';
|
||||
import useLocalState from '@/state/useLocalState.ts';
|
||||
import ProfileHelmet from '@/views/profile/Helmet.tsx';
|
||||
@ -20,11 +20,45 @@ function Profile(props) {
|
||||
const [blocked, setBlocked] = useState(false);
|
||||
const [hexPub, setHexPub] = useState('');
|
||||
const [npub, setNpub] = useState('');
|
||||
const [profile, setProfile] = useState({} as any);
|
||||
const [banner, setBanner] = useState('');
|
||||
const [bannerModalOpen, setBannerModalOpen] = useState(false);
|
||||
const setIsMyProfile = useLocalState('isMyProfile', false)[1];
|
||||
|
||||
const profile = useProfile(hexPub);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hexPub) {
|
||||
return;
|
||||
}
|
||||
const isMyProfile = hexPub === Key.getPubKey();
|
||||
setIsMyProfile(isMyProfile);
|
||||
SocialNetwork.getBlockedUsers((blockedUsers) => {
|
||||
setBlocked(blockedUsers.has(hexPub));
|
||||
});
|
||||
}, [hexPub]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!profile) {
|
||||
return;
|
||||
}
|
||||
let bannerURL;
|
||||
|
||||
try {
|
||||
bannerURL = profile.banner && new URL(profile.banner).toString();
|
||||
if (!bannerURL) {
|
||||
return;
|
||||
}
|
||||
|
||||
bannerURL = isSafeOrigin(bannerURL)
|
||||
? bannerURL
|
||||
: `https://imgproxy.iris.to/insecure/rs:fit:948:948/plain/${bannerURL}`;
|
||||
|
||||
setBanner(bannerURL);
|
||||
} catch (e) {
|
||||
console.log('Invalid banner URL', profile.banner);
|
||||
}
|
||||
}, [profile]);
|
||||
|
||||
useEffect(() => {
|
||||
const pub = props.id;
|
||||
const npubComputed = Key.toNostrBech32Address(pub, 'npub');
|
||||
@ -35,7 +69,11 @@ function Profile(props) {
|
||||
}
|
||||
|
||||
const hexPubComputed = Key.toNostrHexAddress(pub) || '';
|
||||
if (!hexPubComputed) {
|
||||
|
||||
if (hexPubComputed) {
|
||||
setHexPub(hexPubComputed);
|
||||
setNpub(Key.toNostrBech32Address(hexPubComputed, 'npub') || '');
|
||||
} else {
|
||||
let nostrAddress = pub;
|
||||
if (!nostrAddress.match(/.+@.+\..+/)) {
|
||||
if (nostrAddress.match(/.+\..+/)) {
|
||||
@ -51,7 +89,6 @@ function Profile(props) {
|
||||
if (npubComputed && npubComputed !== pubKey) {
|
||||
setNpub(npubComputed);
|
||||
setHexPub(pubKey);
|
||||
loadProfile(pubKey);
|
||||
}
|
||||
} else {
|
||||
setNpub(''); // To indicate not found
|
||||
@ -59,9 +96,6 @@ function Profile(props) {
|
||||
});
|
||||
}
|
||||
|
||||
setHexPub(hexPubComputed);
|
||||
setNpub(Key.toNostrBech32Address(hexPubComputed, 'npub') || '');
|
||||
loadProfile(hexPubComputed);
|
||||
setTimeout(() => {
|
||||
window.prerenderReady = true;
|
||||
}, 1000);
|
||||
@ -90,40 +124,6 @@ function Profile(props) {
|
||||
];
|
||||
}, [hexPub]);
|
||||
|
||||
const loadProfile = (hexPub) => {
|
||||
if (!hexPub) {
|
||||
return;
|
||||
}
|
||||
const isMyProfile = hexPub === Key.getPubKey();
|
||||
setIsMyProfile(isMyProfile);
|
||||
SocialNetwork.getBlockedUsers((blockedUsers) => {
|
||||
setBlocked(blockedUsers.has(hexPub));
|
||||
});
|
||||
|
||||
SocialNetwork.getProfile(hexPub, (profileData) => {
|
||||
if (!profileData) {
|
||||
return;
|
||||
}
|
||||
setProfile(profileData);
|
||||
let bannerURL;
|
||||
|
||||
try {
|
||||
bannerURL = profileData.banner && new URL(profileData.banner).toString();
|
||||
if (!bannerURL) {
|
||||
return;
|
||||
}
|
||||
|
||||
bannerURL = isSafeOrigin(bannerURL)
|
||||
? bannerURL
|
||||
: `https://imgproxy.iris.to/insecure/rs:fit:948:948/plain/${bannerURL}`;
|
||||
|
||||
setBanner(bannerURL);
|
||||
} catch (e) {
|
||||
console.log('Invalid banner URL', profileData.banner);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (!hexPub) {
|
||||
return <div></div>;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user