wip
This commit is contained in:
@@ -5,20 +5,24 @@ import { AvatarUploader } from "@shared/avatarUploader";
|
||||
import { CancelIcon, LoaderIcon, PlusIcon } from "@shared/icons";
|
||||
import { Image } from "@shared/image";
|
||||
import { RelayContext } from "@shared/relayProvider";
|
||||
import { useActiveAccount } from "@stores/accounts";
|
||||
import { DEFAULT_AVATAR } from "@stores/constants";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { dateToUnix } from "@utils/date";
|
||||
import { useAccount } from "@utils/hooks/useAccount";
|
||||
import { Fragment, useContext, useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { navigate } from "vite-plugin-ssr/client/router";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
export function ChannelCreateModal() {
|
||||
const ndk = useContext(RelayContext);
|
||||
const account = useActiveAccount((state: any) => state.account);
|
||||
const queryClient = useQueryClient();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [image, setImage] = useState(DEFAULT_AVATAR);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [image, setImage] = useState(DEFAULT_AVATAR);
|
||||
|
||||
const { account } = useAccount();
|
||||
|
||||
const closeModal = () => {
|
||||
setIsOpen(false);
|
||||
@@ -36,6 +40,21 @@ export function ChannelCreateModal() {
|
||||
formState: { isDirty, isValid },
|
||||
} = useForm();
|
||||
|
||||
const addChannel = useMutation({
|
||||
mutationFn: (event: any) =>
|
||||
createChannel(
|
||||
event.id,
|
||||
event.pubkey,
|
||||
event.name,
|
||||
event.picture,
|
||||
event.about,
|
||||
event.created_at,
|
||||
),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["channels"] });
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = (data: any) => {
|
||||
setLoading(true);
|
||||
|
||||
@@ -55,7 +74,12 @@ export function ChannelCreateModal() {
|
||||
event.publish();
|
||||
|
||||
// insert to database
|
||||
createChannel(event.id, event.pubkey, event.content, event.created_at);
|
||||
addChannel.mutate({
|
||||
...event,
|
||||
name: data.name,
|
||||
picture: data.picture,
|
||||
about: data.about,
|
||||
});
|
||||
|
||||
// reset form
|
||||
reset();
|
||||
@@ -64,7 +88,7 @@ export function ChannelCreateModal() {
|
||||
// close modal
|
||||
setIsOpen(false);
|
||||
// redirect to channel page
|
||||
navigate(`/app/channel?id=${event.id}`);
|
||||
navigate(`/app/channel/${event.id}`);
|
||||
}, 1000);
|
||||
} catch (e) {
|
||||
console.log("error: ", e);
|
||||
|
||||
@@ -1,29 +1,20 @@
|
||||
import { useChannelProfile } from "@app/channel/hooks/useChannelProfile";
|
||||
import { Link } from "@shared/link";
|
||||
import { usePageContext } from "@utils/hooks/usePageContext";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function ChannelsListItem({ data }: { data: any }) {
|
||||
const channel: any = useChannelProfile(data.event_id);
|
||||
const pageContext = usePageContext();
|
||||
|
||||
const searchParams: any = pageContext.urlParsed.search;
|
||||
const pageID = searchParams.id;
|
||||
|
||||
const channel = useChannelProfile(data.event_id);
|
||||
return (
|
||||
<Link
|
||||
href={`/app/channel?id=${data.event_id}`}
|
||||
className={twMerge(
|
||||
"inline-flex h-9 items-center gap-2.5 rounded-md px-2.5",
|
||||
pageID === data.event_id ? "bg-zinc-900 text-zinc-100" : "",
|
||||
)}
|
||||
<NavLink
|
||||
to={`/app/channel/${data.event_id}`}
|
||||
className={({ isActive }) =>
|
||||
twMerge(
|
||||
"inline-flex h-9 items-center gap-2.5 rounded-md px-2.5",
|
||||
isActive ? "bg-zinc-900/50 text-zinc-100" : "",
|
||||
)
|
||||
}
|
||||
>
|
||||
<div
|
||||
className={twMerge(
|
||||
"inline-flex shrink-0 h-6 w-6 items-center justify-center rounded border-t border-zinc-800/50 bg-zinc-900",
|
||||
pageID === data.event_id ? "bg-zinc-800" : "",
|
||||
)}
|
||||
>
|
||||
<div className="inline-flex shrink-0 h-6 w-6 items-center justify-center rounded border-t border-zinc-800/50 bg-zinc-900">
|
||||
<span className="text-xs text-zinc-100">#</span>
|
||||
</div>
|
||||
<div className="w-full inline-flex items-center justify-between">
|
||||
@@ -36,6 +27,6 @@ export function ChannelsListItem({ data }: { data: any }) {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</NavLink>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,27 +1,36 @@
|
||||
import { ChannelCreateModal } from "@app/channel/components/createModal";
|
||||
import { ChannelsListItem } from "@app/channel/components/item";
|
||||
import { useChannels } from "@stores/channels";
|
||||
import { useEffect } from "react";
|
||||
import { getChannels } from "@libs/storage";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
export function ChannelsList() {
|
||||
const channels = useChannels((state: any) => state.channels);
|
||||
const fetchChannels = useChannels((state: any) => state.fetch);
|
||||
|
||||
useEffect(() => {
|
||||
fetchChannels();
|
||||
}, [fetchChannels]);
|
||||
const {
|
||||
status,
|
||||
data: channels,
|
||||
isFetching,
|
||||
} = useQuery(
|
||||
["channels"],
|
||||
async () => {
|
||||
return await getChannels();
|
||||
},
|
||||
{
|
||||
refetchOnMount: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnWindowFocus: false,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
{!channels ? (
|
||||
{status === "loading" ? (
|
||||
<>
|
||||
<div className="inline-flex h-9 items-center gap-2 rounded-md px-2.5">
|
||||
<div className="relative h-5 w-5 shrink-0 animate-pulse rounded bg-zinc-800" />
|
||||
<div className="h-3 w-full animate-pulse rounded-sm bg-zinc-800" />
|
||||
<div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5">
|
||||
<div className="relative h-6 w-6 shrink-0 animate-pulse rounded bg-zinc-800" />
|
||||
<div className="h-3.5 w-full animate-pulse rounded-sm bg-zinc-800" />
|
||||
</div>
|
||||
<div className="inline-flex h-9 items-center gap-2 rounded-md px-2.5">
|
||||
<div className="relative h-5 w-5 shrink-0 animate-pulse rounded bg-zinc-800" />
|
||||
<div className="h-3 w-full animate-pulse rounded-sm bg-zinc-800" />
|
||||
<div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5">
|
||||
<div className="relative h-6 w-6 shrink-0 animate-pulse rounded bg-zinc-800" />
|
||||
<div className="h-3.5 w-full animate-pulse rounded-sm bg-zinc-800" />
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
@@ -29,6 +38,12 @@ export function ChannelsList() {
|
||||
<ChannelsListItem key={item.event_id} data={item} />
|
||||
))
|
||||
)}
|
||||
{isFetching && (
|
||||
<div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5">
|
||||
<div className="relative h-6 w-6 shrink-0 animate-pulse rounded bg-zinc-800" />
|
||||
<div className="h-3.5 w-full animate-pulse rounded-sm bg-zinc-800" />
|
||||
</div>
|
||||
)}
|
||||
<ChannelCreateModal />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { Member } from "@app/channel/components/member";
|
||||
import { getChannelUsers } from "@libs/storage";
|
||||
import useSWR from "swr";
|
||||
|
||||
const fetcher = ([, id]) => getChannelUsers(id);
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
export function ChannelMembers({ id }: { id: string }) {
|
||||
const { data, isLoading }: any = useSWR(["channel-members", id], fetcher);
|
||||
const { status, data, isFetching } = useQuery(
|
||||
["channel-members", id],
|
||||
async () => {
|
||||
return await getChannelUsers(id);
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mt-3">
|
||||
@@ -13,8 +16,7 @@ export function ChannelMembers({ id }: { id: string }) {
|
||||
Members
|
||||
</h5>
|
||||
<div className="mt-3 w-full flex flex-wrap gap-1.5">
|
||||
{isLoading && <p>Loading...</p>}
|
||||
{!data ? (
|
||||
{status === "loading" || isFetching ? (
|
||||
<p>Loading...</p>
|
||||
) : (
|
||||
data.map((member: { pubkey: string }) => (
|
||||
|
||||
@@ -3,14 +3,13 @@ import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
|
||||
import { CancelIcon, EnterIcon } from "@shared/icons";
|
||||
import { MediaUploader } from "@shared/mediaUploader";
|
||||
import { RelayContext } from "@shared/relayProvider";
|
||||
import { useActiveAccount } from "@stores/accounts";
|
||||
import { useChannelMessages } from "@stores/channels";
|
||||
import { dateToUnix } from "@utils/date";
|
||||
import { useAccount } from "@utils/hooks/useAccount";
|
||||
import { useContext, useState } from "react";
|
||||
|
||||
export function ChannelMessageForm({ channelID }: { channelID: string }) {
|
||||
const ndk = useContext(RelayContext);
|
||||
const account = useActiveAccount((state: any) => state.account);
|
||||
|
||||
const [value, setValue] = useState("");
|
||||
const [replyTo, closeReply] = useChannelMessages((state: any) => [
|
||||
@@ -18,6 +17,8 @@ export function ChannelMessageForm({ channelID }: { channelID: string }) {
|
||||
state.closeReply,
|
||||
]);
|
||||
|
||||
const { account } = useAccount();
|
||||
|
||||
const submit = () => {
|
||||
let tags: string[][];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user