From b54cd34500109e5db4ddb4bf87c78a024ac6a324 Mon Sep 17 00:00:00 2001
From: Ren Amamiya <123083837+reyamir@users.noreply.github.com>
Date: Tue, 11 Apr 2023 09:55:36 +0700
Subject: [PATCH] added channel message list and form
---
src/components/channels/browseChannelItem.tsx | 34 +++++++++
.../channels/channelMessageItem.tsx | 22 ++++++
.../channels/channelMessageList.tsx | 39 ++++++++++
src/components/chats/chatList.tsx | 3 +-
src/components/form/channelMessage.tsx | 71 +++++++++++++++++++
src/pages/channels/[id].tsx | 24 +++++--
src/pages/channels/index.tsx | 39 +++-------
7 files changed, 198 insertions(+), 34 deletions(-)
create mode 100644 src/components/channels/browseChannelItem.tsx
create mode 100644 src/components/channels/channelMessageItem.tsx
create mode 100644 src/components/channels/channelMessageList.tsx
create mode 100644 src/components/form/channelMessage.tsx
diff --git a/src/components/channels/browseChannelItem.tsx b/src/components/channels/browseChannelItem.tsx
new file mode 100644
index 00000000..7187257c
--- /dev/null
+++ b/src/components/channels/browseChannelItem.tsx
@@ -0,0 +1,34 @@
+import { ImageWithFallback } from '@components/imageWithFallback';
+
+import { DEFAULT_AVATAR } from '@stores/constants';
+
+import { useRouter } from 'next/router';
+
+export const BrowseChannelItem = ({ data }: { data: any }) => {
+ const router = useRouter();
+ const channel = JSON.parse(data.content);
+
+ const openChannel = (id) => {
+ router.push({
+ pathname: '/channels/[id]',
+ query: { id: id },
+ });
+ };
+
+ return (
+
openChannel(data.eventId)} className="flex items-center gap-2 px-3 py-2 hover:bg-zinc-950">
+
+
+
+
+ {channel.name}
+ {channel.about}
+
+
+ );
+};
diff --git a/src/components/channels/channelMessageItem.tsx b/src/components/channels/channelMessageItem.tsx
new file mode 100644
index 00000000..3884bd7c
--- /dev/null
+++ b/src/components/channels/channelMessageItem.tsx
@@ -0,0 +1,22 @@
+import { MessageUser } from '@components/chats/messageUser';
+
+import { memo } from 'react';
+
+const ChannelMessageItem = ({ data }: { data: any }) => {
+ return (
+
+ );
+};
+
+export default memo(ChannelMessageItem);
diff --git a/src/components/channels/channelMessageList.tsx b/src/components/channels/channelMessageList.tsx
new file mode 100644
index 00000000..4414fd50
--- /dev/null
+++ b/src/components/channels/channelMessageList.tsx
@@ -0,0 +1,39 @@
+import ChannelMessageItem from '@components/channels/channelMessageItem';
+
+import { useCallback, useRef } from 'react';
+import { Virtuoso } from 'react-virtuoso';
+
+export const ChannelMessageList = ({ data }: { data: any }) => {
+ const virtuosoRef = useRef(null);
+
+ const itemContent: any = useCallback(
+ (index: string | number) => {
+ return ;
+ },
+ [data]
+ );
+
+ const computeItemKey = useCallback(
+ (index: string | number) => {
+ return data[index].id;
+ },
+ [data]
+ );
+
+ return (
+
+
+
+ );
+};
diff --git a/src/components/chats/chatList.tsx b/src/components/chats/chatList.tsx
index 4cad15b9..7857d09d 100644
--- a/src/components/chats/chatList.tsx
+++ b/src/components/chats/chatList.tsx
@@ -11,11 +11,10 @@ import { useEffect, useState } from 'react';
export default function ChatList() {
const router = useRouter();
+ const [list, setList] = useState([]);
const [activeAccount]: any = useLocalStorage('activeAccount');
const accountProfile = JSON.parse(activeAccount.metadata);
- const [list, setList] = useState([]);
-
const openSelfChat = () => {
router.push({
pathname: '/chats/[pubkey]',
diff --git a/src/components/form/channelMessage.tsx b/src/components/form/channelMessage.tsx
new file mode 100644
index 00000000..3cd4abd0
--- /dev/null
+++ b/src/components/form/channelMessage.tsx
@@ -0,0 +1,71 @@
+import ImagePicker from '@components/form/imagePicker';
+import { RelayContext } from '@components/relaysProvider';
+
+import { dateToUnix } from '@utils/getDate';
+
+import useLocalStorage from '@rehooks/local-storage';
+import { getEventHash, signEvent } from 'nostr-tools';
+import { useCallback, useContext, useState } from 'react';
+
+export default function FormChannelMessage({ eventId }: { eventId: string | string[] }) {
+ const [pool, relays]: any = useContext(RelayContext);
+
+ const [value, setValue] = useState('');
+ const [activeAccount]: any = useLocalStorage('activeAccount');
+
+ const submitEvent = useCallback(() => {
+ const event: any = {
+ content: value,
+ created_at: dateToUnix(),
+ kind: 42,
+ pubkey: activeAccount.pubkey,
+ tags: [['e', eventId, '', 'root']],
+ };
+ event.id = getEventHash(event);
+ event.sig = signEvent(event, activeAccount.privkey);
+
+ // publish note
+ pool.publish(event, relays);
+ // reset state
+ setValue('');
+ }, [activeAccount.privkey, activeAccount.pubkey, eventId, value, pool, relays]);
+
+ const handleEnterPress = (e) => {
+ if (e.key === 'Enter' && !e.shiftKey) {
+ e.preventDefault();
+ submitEvent();
+ }
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/pages/channels/[id].tsx b/src/pages/channels/[id].tsx
index f0b3f6a7..5c059f79 100644
--- a/src/pages/channels/[id].tsx
+++ b/src/pages/channels/[id].tsx
@@ -1,10 +1,20 @@
import BaseLayout from '@layouts/base';
import WithSidebarLayout from '@layouts/withSidebar';
+import { ChannelMessageList } from '@components/channels/channelMessageList';
+import FormChannelMessage from '@components/form/channelMessage';
import { RelayContext } from '@components/relaysProvider';
import { useRouter } from 'next/router';
-import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useEffect } from 'react';
+import {
+ JSXElementConstructor,
+ ReactElement,
+ ReactFragment,
+ ReactPortal,
+ useContext,
+ useEffect,
+ useState,
+} from 'react';
export default function Page() {
const [pool, relays]: any = useContext(RelayContext);
@@ -12,28 +22,34 @@ export default function Page() {
const router = useRouter();
const id: string | string[] = router.query.id || null;
+ const [messages, setMessages] = useState([]);
+
useEffect(() => {
const unsubscribe = pool.subscribe(
[
{
+ '#e': [id],
kinds: [42],
since: 0,
},
],
relays,
(event: any) => {
- console.log(event);
+ setMessages((messages) => [event, ...messages]);
}
);
return () => {
unsubscribe;
};
- }, [pool, relays]);
+ }, [id, pool, relays]);
return (
-
{id}
+
a.created_at - b.created_at)} />
+
+
+
);
}
diff --git a/src/pages/channels/index.tsx b/src/pages/channels/index.tsx
index 263a918c..b5f8c36d 100644
--- a/src/pages/channels/index.tsx
+++ b/src/pages/channels/index.tsx
@@ -1,45 +1,28 @@
import BaseLayout from '@layouts/base';
import WithSidebarLayout from '@layouts/withSidebar';
-import { RelayContext } from '@components/relaysProvider';
+import { BrowseChannelItem } from '@components/channels/browseChannelItem';
-import {
- JSXElementConstructor,
- ReactElement,
- ReactFragment,
- ReactPortal,
- useContext,
- useEffect,
- useState,
-} from 'react';
+import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useEffect, useState } from 'react';
export default function Page() {
- const [pool, relays]: any = useContext(RelayContext);
const [list, setList] = useState([]);
useEffect(() => {
- const unsubscribe = pool.subscribe(
- [
- {
- kinds: [40],
- since: 0,
- },
- ],
- relays,
- (event: any) => {
- setList((list) => [event, ...list]);
- }
- );
-
- return () => {
- unsubscribe;
+ const fetchChannels = async () => {
+ const { getChannels } = await import('@utils/bindings');
+ return await getChannels({ limit: 100, offset: 0 });
};
- }, [pool, relays]);
+
+ fetchChannels()
+ .then((res) => setList(res))
+ .catch(console.error);
+ }, []);
return (
{list.map((channel) => (
-
{channel.content}
+
))}
);