diff options
Diffstat (limited to 'gui/src/components/nostr/User.tsx')
| -rw-r--r-- | gui/src/components/nostr/User.tsx | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/gui/src/components/nostr/User.tsx b/gui/src/components/nostr/User.tsx new file mode 100644 index 0000000..a9e9e2f --- /dev/null +++ b/gui/src/components/nostr/User.tsx @@ -0,0 +1,128 @@ +import useLocalState from "@/state/state"; +import { useState } from "react"; +import Icon from "@/components/Icon"; +import toast from "react-hot-toast"; +import type { UserType } from "@/types/nostrill"; +import type { FC } from "@/types/trill"; +import Composer from "../composer/Composer"; +import PostList from "@/components/feed/PostList"; + +export default function NostrUser({ + user, + userString, + feed, + isFollowLoading, + setIsFollowLoading, + isAccessLoading, + setIsAccessLoading, +}: { + user: UserType; + userString: string; + feed: FC | undefined; + isFollowLoading: boolean; + setIsFollowLoading: (b: boolean) => void; + isAccessLoading: boolean; + setIsAccessLoading: (b: boolean) => void; +}) { + const { api } = useLocalState((s) => ({ + api: s.api, + })); + const [fc, setFC] = useState<FC>(); + + // Show empty state with resync option when no feed data + + async function refetch() { + // + } + async function handleFollow() { + if (!api) return; + + setIsFollowLoading(true); + try { + if (feed) { + await api.unfollow(user); + } else { + await api.follow(user); + toast.success(`Follow request sent to ${userString}`); + } + } catch (error) { + toast.error(`Failed to ${!!feed ? "unfollow" : "follow"} ${userString}`); + setIsFollowLoading(false); + console.error("Follow error:", error); + } + } + async function handleRequestAccess() { + if (!api) return; + + setIsAccessLoading(true); + // try { + // const res = await api.peekFeed(user.urbit); + // toast.success(`Access request sent to ${user.urbit}`); + // addNotification({ + // type: "access_request", + // from: userString, + // message: `Access request sent to ${userString}`, + // }); + // if ("error" in res) toast.error(res.error); + // else { + // console.log("peeked", res.ok.feed); + // setFC(res.ok.feed); + // if (res.ok.profile) addProfile(userString, res.ok.profile); + // } + // } catch (error) { + // toast.error(`Failed to request access from ${user.urbit}`); + // console.error("Access request error:", error); + // } finally { + // setIsAccessLoading(false); + // } + } + return ( + <> + <div className="user-actions"> + <button + onClick={handleFollow} + disabled={isFollowLoading} + className={`action-btn ${!!feed ? "" : "follow"}`} + > + {isFollowLoading ? ( + <> + <Icon name="settings" size={16} /> + {!!feed ? "Unfollowing..." : "Following..."} + </> + ) : ( + <> + <Icon name={!!feed ? "bell" : "pals"} size={16} /> + {!!feed ? "Unfollow" : "Follow"} + </> + )} + </button> + + {(!feed || !feed.feed || Object.keys(feed.feed).length === 0) && ( + <button + onClick={handleRequestAccess} + disabled={isAccessLoading} + className="action-btn access" + > + {isAccessLoading ? ( + <> + <Icon name="settings" size={16} /> + Fetching... + </> + ) : ( + <> + <Icon name="key" size={16} /> + Fetch Feed + </> + )} + </button> + )} + </div> + {(feed || fc) && ( + <div id="feed-proper"> + <Composer /> + <PostList data={(feed || fc)!} refetch={refetch} /> + </div> + )} + </> + ); +} |
