updated create channel modal

This commit is contained in:
Ren Amamiya 2023-04-23 15:10:07 +07:00
parent 97c45a8c8f
commit 340e453b3e
5 changed files with 95 additions and 49 deletions

View File

@ -1,26 +1,15 @@
import { ChannelListItem } from '@components/channels/channelListItem';
import { CreateChannelModal } from '@components/channels/createChannelModal';
import { DEFAULT_CHANNELS } from '@stores/constants';
import { Plus } from 'iconoir-react';
export default function ChannelList() {
return (
<div className="flex flex-col gap-px">
{DEFAULT_CHANNELS.map((item) => (
<ChannelListItem key={item.event_id} data={item} />
))}
<a
href="/create-channel"
className="group inline-flex items-center gap-2 rounded-md px-2.5 py-1.5 hover:bg-zinc-900"
>
<div className="inline-flex h-5 w-5 shrink items-center justify-center rounded bg-zinc-900 group-hover:bg-zinc-800">
<Plus width={12} height={12} className="text-zinc-500" />
</div>
<div>
<h5 className="text-sm font-medium text-zinc-500 group-hover:text-zinc-400">Add a new channel</h5>
</div>
</a>
<CreateChannelModal />
</div>
);
}

View File

@ -1,6 +1,9 @@
import { RelayContext } from '@components/relaysProvider';
import { FULL_RELAYS } from '@stores/constants';
import { dateToUnix } from '@utils/getDate';
import { createChannel } from '@utils/storage';
import * as Dialog from '@radix-ui/react-dialog';
import useLocalStorage from '@rehooks/local-storage';
@ -10,7 +13,7 @@ import { useContext, useState } from 'react';
import { useForm } from 'react-hook-form';
export const CreateChannelModal = () => {
const [pool, relays]: any = useContext(RelayContext);
const [pool]: any = useContext(RelayContext);
const [open, setOpen] = useState(false);
const [activeAccount]: any = useLocalStorage('account', {});
@ -21,7 +24,7 @@ export const CreateChannelModal = () => {
formState: { isDirty, isValid },
} = useForm();
const onSubmit = (data) => {
const onSubmit = (data: any) => {
const event: any = {
content: JSON.stringify(data),
created_at: dateToUnix(),
@ -33,7 +36,9 @@ export const CreateChannelModal = () => {
event.sig = signEvent(event, activeAccount.privkey);
// publish channel
pool.publish(event, relays);
pool.publish(event, FULL_RELAYS);
// insert to database
createChannel(event.id, event.content, event.created_at);
// close modal
setOpen(false);
// reset form
@ -53,43 +58,48 @@ export const CreateChannelModal = () => {
</div>
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className="fixed inset-0 z-50 bg-black bg-opacity-30 backdrop-blur-sm data-[state=open]:animate-overlayShow" />
<Dialog.Overlay className="fixed inset-0 z-50 bg-black bg-opacity-30 backdrop-blur-md data-[state=open]:animate-overlayShow" />
<Dialog.Content className="fixed inset-0 z-50 overflow-y-auto">
<div className="flex min-h-full items-center justify-center">
<div className="relative flex h-min w-full max-w-xl flex-col rounded-lg shadow-modal">
<div className="sticky left-0 top-0 flex h-12 w-full shrink-0 items-center justify-between rounded-t-lg bg-zinc-950 px-3">
<div className="flex w-full items-center justify-between">
<h5 className="font-medium leading-none text-zinc-500"># Create channel</h5>
<Dialog.Close asChild>
<button
autoFocus={false}
className="inline-flex h-5 w-5 items-center justify-center rounded hover:bg-zinc-900"
>
<Cancel width={12} height={12} className="text-zinc-500" />
</button>
</Dialog.Close>
<div className="relative flex h-min w-full max-w-lg flex-col gap-2 rounded-lg border border-zinc-800 bg-zinc-900">
<div className="h-min w-full shrink-0 border-b border-zinc-800 px-5 py-6">
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between">
<h5 className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-2xl font-semibold leading-none text-transparent">
Create channel
</h5>
<Dialog.Close asChild>
<button
autoFocus={false}
className="inline-flex h-5 w-5 items-center justify-center rounded hover:bg-zinc-900"
>
<Cancel width={20} height={20} className="text-zinc-300" />
</button>
</Dialog.Close>
</div>
<p className="leading-tight text-zinc-400">
Channels are freedom square, everyone can speech freely, no one can stop you or deceive what to
speech
</p>
</div>
</div>
<div className="flex h-full w-full flex-col overflow-y-auto rounded-b-lg bg-zinc-950 px-3 pb-3">
<form
onSubmit={handleSubmit(onSubmit)}
className="flex h-full w-full flex-col gap-4 rounded-lg border border-white/20 bg-zinc-900 p-4"
>
<div className="flex h-full w-full flex-col overflow-y-auto px-5 pb-5 pt-3">
<form onSubmit={handleSubmit(onSubmit)} className="flex h-full w-full flex-col gap-4">
<div className="flex flex-col gap-1">
<label className="text-xs font-semibold uppercase tracking-wider text-zinc-300">
<label className="text-xs font-semibold uppercase tracking-wider text-zinc-400">
Channel name *
</label>
<div className="relative w-full shrink-0 overflow-hidden before:pointer-events-none before:absolute before:-inset-1 before:rounded-[11px] before:border before:border-fuchsia-500 before:opacity-0 before:ring-2 before:ring-fuchsia-500/20 before:transition after:pointer-events-none after:absolute after:inset-px after:rounded-[7px] after:shadow-highlight after:shadow-white/5 after:transition focus-within:before:opacity-100 focus-within:after:shadow-fuchsia-500/100 dark:focus-within:after:shadow-fuchsia-500/20">
<input
type={'text'}
{...register('name', { required: true })}
{...register('name', { required: true, minLength: 4 })}
spellCheck={false}
className="relative h-10 w-full rounded-lg border border-black/5 px-3 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-500"
/>
</div>
</div>
<div className="flex flex-col gap-1">
<label className="text-xs font-semibold uppercase tracking-wider text-zinc-300">Picture</label>
<label className="text-xs font-semibold uppercase tracking-wider text-zinc-400">Picture</label>
<div className="relative w-full shrink-0 overflow-hidden before:pointer-events-none before:absolute before:-inset-1 before:rounded-[11px] before:border before:border-fuchsia-500 before:opacity-0 before:ring-2 before:ring-fuchsia-500/20 before:transition after:pointer-events-none after:absolute after:inset-px after:rounded-[7px] after:shadow-highlight after:shadow-white/5 after:transition focus-within:before:opacity-100 focus-within:after:shadow-fuchsia-500/100 dark:focus-within:after:shadow-fuchsia-500/20">
<input
type={'text'}
@ -100,7 +110,7 @@ export const CreateChannelModal = () => {
</div>
</div>
<div className="flex flex-col gap-1">
<label className="text-xs font-semibold uppercase tracking-wider text-zinc-300">About</label>
<label className="text-xs font-semibold uppercase tracking-wider text-zinc-400">Description</label>
<div className="relative h-20 w-full shrink-0 overflow-hidden before:pointer-events-none before:absolute before:-inset-1 before:rounded-[11px] before:border before:border-fuchsia-500 before:opacity-0 before:ring-2 before:ring-fuchsia-500/20 before:transition after:pointer-events-none after:absolute after:inset-px after:rounded-[7px] after:shadow-highlight after:shadow-white/5 after:transition focus-within:before:opacity-100 focus-within:after:shadow-fuchsia-500/100 dark:focus-within:after:shadow-fuchsia-500/20">
<textarea
{...register('about')}
@ -109,6 +119,31 @@ export const CreateChannelModal = () => {
/>
</div>
</div>
<div className="flex h-14 items-center justify-between gap-1 rounded-lg bg-zinc-800 px-4 py-2">
<div className="flex flex-col gap-0.5">
<div className="inline-flex items-center gap-1">
<span className="text-sm font-bold leading-none text-zinc-200">Make Private</span>
<div className="inline-flex items-center rounded-md bg-zinc-400/10 px-2 py-0.5 text-xs font-medium ring-1 ring-inset ring-zinc-400/20">
<span className="bg-gradient-to-r from-fuchsia-300 via-orange-100 to-amber-300 bg-clip-text text-transparent">
Coming soon
</span>
</div>
</div>
<p className="text-sm leading-none text-zinc-400">
Private channels can only be viewed by member
</p>
</div>
<div>
<button
disabled
className="relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent bg-zinc-900 transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-fuchsia-600 focus:ring-offset-2"
role="switch"
aria-checked="false"
>
<span className="pointer-events-none inline-block h-5 w-5 translate-x-0 transform rounded-full bg-zinc-600 shadow ring-0 transition duration-200 ease-in-out"></span>
</button>
</div>
</div>
<div>
<button
type="submit"

View File

@ -0,0 +1,31 @@
import AppHeader from '@components/appHeader';
import MultiAccounts from '@components/multiAccounts';
import Navigation from '@components/navigation';
export default function ChannelLayout({ children }: { children: React.ReactNode }) {
return (
<div className="h-screen w-screen bg-zinc-50 text-zinc-900 dark:bg-black dark:text-white">
<div className="flex h-screen w-full flex-col">
<div
data-tauri-drag-region
className="relative h-11 shrink-0 border-b border-zinc-100 bg-white dark:border-zinc-900 dark:bg-black"
>
<AppHeader collector={true} />
</div>
<div className="relative flex min-h-0 w-full flex-1">
<div className="relative w-[68px] shrink-0 border-r border-zinc-900">
<MultiAccounts />
</div>
<div className="grid w-full grid-cols-4 xl:grid-cols-5">
<div className="scrollbar-hide col-span-1 overflow-y-auto overflow-x-hidden border-r border-zinc-900">
<Navigation />
</div>
<div className="col-span-3 m-3 overflow-hidden xl:col-span-4 xl:mr-1.5">
<div className="h-full w-full rounded-lg">{children}</div>
</div>
</div>
</div>
</div>
</div>
);
}

View File

@ -1,9 +0,0 @@
import NewsfeedLayout from '@components/layouts/newsfeed';
export function Page() {
return (
<NewsfeedLayout>
<h1>TODO</h1>
</NewsfeedLayout>
);
}

View File

@ -2,7 +2,6 @@ import { RelayContext } from '@components/relaysProvider';
import { dateToUnix, hoursAgo } from '@utils/getDate';
import {
countTotalChannels,
countTotalNotes,
createChannel,
createChat,
@ -30,7 +29,6 @@ export function Page() {
async (account: { id: number; pubkey: string; chats: string[] }, tags: any) => {
const lastLogin = await getLastLogin();
const notes = await countTotalNotes();
const channels = await countTotalChannels();
const chats = account.chats?.length || 0;
const follows = JSON.parse(tags);
@ -64,6 +62,7 @@ export function Page() {
});
}
// kind 40 (channels) query
/*
if (channels.total === 0) {
query.push({
kinds: [40],
@ -71,6 +70,7 @@ export function Page() {
until: dateToUnix(now.current),
});
}
*/
// subscribe relays
const unsubscribe = pool.subscribe(
query,