updated image picker

This commit is contained in:
Ren Amamiya
2023-04-21 08:20:12 +07:00
parent df2f6b0ce7
commit 5a7389b7e8
7 changed files with 58 additions and 23 deletions

View File

@@ -3,9 +3,13 @@ import { MuteButton } from '@components/channels/messages/muteButton';
import { ReplyButton } from '@components/channels/messages/replyButton'; import { ReplyButton } from '@components/channels/messages/replyButton';
import { MessageUser } from '@components/chats/messageUser'; import { MessageUser } from '@components/chats/messageUser';
import { messageParser } from '@utils/parser';
import { memo } from 'react'; import { memo } from 'react';
const ChannelMessageItem = ({ data }: { data: any }) => { const ChannelMessageItem = ({ data }: { data: any }) => {
const content = messageParser(data.content);
return ( return (
<div className="group relative flex h-min min-h-min w-full select-text flex-col px-5 py-2 hover:bg-black/20"> <div className="group relative flex h-min min-h-min w-full select-text flex-col px-5 py-2 hover:bg-black/20">
<div className="flex flex-col"> <div className="flex flex-col">
@@ -13,7 +17,7 @@ const ChannelMessageItem = ({ data }: { data: any }) => {
<div className="-mt-[17px] pl-[48px]"> <div className="-mt-[17px] pl-[48px]">
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<div className="prose prose-zinc max-w-none break-words text-sm leading-tight dark:prose-invert prose-p:m-0 prose-p:text-sm prose-p:leading-tight prose-a:font-normal prose-a:text-fuchsia-500 prose-a:no-underline prose-img:m-0 prose-video:m-0"> <div className="prose prose-zinc max-w-none break-words text-sm leading-tight dark:prose-invert prose-p:m-0 prose-p:text-sm prose-p:leading-tight prose-a:font-normal prose-a:text-fuchsia-500 prose-a:no-underline prose-img:m-0 prose-video:m-0">
{data.content} {content}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -53,7 +53,7 @@ export default function FormBase() {
<div className="absolute bottom-2 w-full px-2"> <div className="absolute bottom-2 w-full px-2">
<div className="flex w-full items-center justify-between bg-zinc-800"> <div className="flex w-full items-center justify-between bg-zinc-800">
<div className="flex items-center gap-2 divide-x divide-zinc-700"> <div className="flex items-center gap-2 divide-x divide-zinc-700">
<ImagePicker /> <ImagePicker type="note" />
<div className="flex items-center gap-2 pl-2"></div> <div className="flex items-center gap-2 pl-2"></div>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">

View File

@@ -1,30 +1,31 @@
import ImagePicker from '@components/form/imagePicker'; import { ImagePicker } from '@components/form/imagePicker';
import { RelayContext } from '@components/relaysProvider'; import { RelayContext } from '@components/relaysProvider';
import { UserMini } from '@components/user/mini'; import { UserMini } from '@components/user/mini';
import { channelReplyAtom } from '@stores/channel'; import { channelContentAtom, channelReplyAtom } from '@stores/channel';
import { FULL_RELAYS } from '@stores/constants'; import { FULL_RELAYS } from '@stores/constants';
import { dateToUnix } from '@utils/getDate'; import { dateToUnix } from '@utils/getDate';
import useLocalStorage from '@rehooks/local-storage'; import useLocalStorage from '@rehooks/local-storage';
import { Cancel } from 'iconoir-react'; import { Cancel } from 'iconoir-react';
import { useAtomValue } from 'jotai'; import { useAtom, useAtomValue } from 'jotai';
import { useResetAtom } from 'jotai/utils'; import { useResetAtom } from 'jotai/utils';
import { getEventHash, signEvent } from 'nostr-tools'; import { getEventHash, signEvent } from 'nostr-tools';
import { useCallback, useContext, useState } from 'react'; import { useCallback, useContext } from 'react';
export const FormChannel = ({ eventId }: { eventId: string | string[] }) => { export const FormChannel = ({ eventId }: { eventId: string | string[] }) => {
const [pool, relays]: any = useContext(RelayContext); const [pool, relays]: any = useContext(RelayContext);
const [value, setValue] = useState('');
const [activeAccount]: any = useLocalStorage('account', {}); const [activeAccount]: any = useLocalStorage('account', {});
const [value, setValue] = useAtom(channelContentAtom);
const resetValue = useResetAtom(channelContentAtom);
const channelReply = useAtomValue(channelReplyAtom); const channelReply = useAtomValue(channelReplyAtom);
const resetChannelReply = useResetAtom(channelReplyAtom); const resetChannelReply = useResetAtom(channelReplyAtom);
const submitEvent = useCallback(() => { const submitEvent = useCallback(() => {
let tags; let tags: any[][];
if (channelReply.id !== null) { if (channelReply.id !== null) {
tags = [ tags = [
@@ -49,7 +50,7 @@ export const FormChannel = ({ eventId }: { eventId: string | string[] }) => {
// publish note // publish note
pool.publish(event, FULL_RELAYS); pool.publish(event, FULL_RELAYS);
// reset state // reset state
setValue(''); resetValue();
// reset channel reply // reset channel reply
resetChannelReply(); resetChannelReply();
}, [ }, [
@@ -112,7 +113,7 @@ export const FormChannel = ({ eventId }: { eventId: string | string[] }) => {
<div className="absolute bottom-2 w-full px-2"> <div className="absolute bottom-2 w-full px-2">
<div className="flex w-full items-center justify-between bg-zinc-800"> <div className="flex w-full items-center justify-between bg-zinc-800">
<div className="flex items-center gap-2 divide-x divide-zinc-700"> <div className="flex items-center gap-2 divide-x divide-zinc-700">
<ImagePicker /> <ImagePicker type="channel" />
<div className="flex items-center gap-2 pl-2"></div> <div className="flex items-center gap-2 pl-2"></div>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">

View File

@@ -1,18 +1,24 @@
import ImagePicker from '@components/form/imagePicker'; import { ImagePicker } from '@components/form/imagePicker';
import { RelayContext } from '@components/relaysProvider'; import { RelayContext } from '@components/relaysProvider';
import { chatContentAtom } from '@stores/chat';
import { FULL_RELAYS } from '@stores/constants';
import { dateToUnix } from '@utils/getDate'; import { dateToUnix } from '@utils/getDate';
import useLocalStorage from '@rehooks/local-storage'; import useLocalStorage from '@rehooks/local-storage';
import { useAtom } from 'jotai';
import { useResetAtom } from 'jotai/utils';
import { getEventHash, nip04, signEvent } from 'nostr-tools'; import { getEventHash, nip04, signEvent } from 'nostr-tools';
import { useCallback, useContext, useState } from 'react'; import { useCallback, useContext } from 'react';
export default function FormChat({ receiverPubkey }: { receiverPubkey: string }) { export default function FormChat({ receiverPubkey }: { receiverPubkey: string }) {
const [pool, relays]: any = useContext(RelayContext); const [pool, relays]: any = useContext(RelayContext);
const [value, setValue] = useState('');
const [activeAccount]: any = useLocalStorage('account', {}); const [activeAccount]: any = useLocalStorage('account', {});
const [value, setValue] = useAtom(chatContentAtom);
const resetValue = useResetAtom(chatContentAtom);
const encryptMessage = useCallback( const encryptMessage = useCallback(
async (privkey: string) => { async (privkey: string) => {
return await nip04.encrypt(privkey, receiverPubkey, value); return await nip04.encrypt(privkey, receiverPubkey, value);
@@ -33,12 +39,12 @@ export default function FormChat({ receiverPubkey }: { receiverPubkey: string })
event.id = getEventHash(event); event.id = getEventHash(event);
event.sig = signEvent(event, activeAccount.privkey); event.sig = signEvent(event, activeAccount.privkey);
// publish note // publish note
pool.publish(event, relays); pool.publish(event, FULL_RELAYS);
// reset state // reset state
setValue(''); resetValue();
}) })
.catch(console.error); .catch(console.error);
}, [encryptMessage, activeAccount.privkey, activeAccount.pubkey, receiverPubkey, pool, relays]); }, [encryptMessage, activeAccount.privkey, activeAccount.pubkey, receiverPubkey, pool]);
const handleEnterPress = (e) => { const handleEnterPress = (e) => {
if (e.key === 'Enter' && !e.shiftKey) { if (e.key === 'Enter' && !e.shiftKey) {
@@ -62,7 +68,7 @@ export default function FormChat({ receiverPubkey }: { receiverPubkey: string })
<div className="absolute bottom-2 w-full px-2"> <div className="absolute bottom-2 w-full px-2">
<div className="flex w-full items-center justify-between bg-zinc-800"> <div className="flex w-full items-center justify-between bg-zinc-800">
<div className="flex items-center gap-2 divide-x divide-zinc-700"> <div className="flex items-center gap-2 divide-x divide-zinc-700">
<ImagePicker /> <ImagePicker type="chat" />
<div className="flex items-center gap-2 pl-2"></div> <div className="flex items-center gap-2 pl-2"></div>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">

View File

@@ -1,3 +1,5 @@
import { channelContentAtom } from '@stores/channel';
import { chatContentAtom } from '@stores/chat';
import { noteContentAtom } from '@stores/note'; import { noteContentAtom } from '@stores/note';
import { createBlobFromFile } from '@utils/createBlobFromFile'; import { createBlobFromFile } from '@utils/createBlobFromFile';
@@ -8,9 +10,25 @@ import { Plus } from 'iconoir-react';
import { useSetAtom } from 'jotai'; import { useSetAtom } from 'jotai';
import { useState } from 'react'; import { useState } from 'react';
export const ImagePicker = () => { export const ImagePicker = ({ type }: { type: string }) => {
let atom;
switch (type) {
case 'note':
atom = noteContentAtom;
break;
case 'chat':
atom = chatContentAtom;
break;
case 'channel':
atom = channelContentAtom;
break;
default:
throw new Error('Invalid type');
}
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const setNoteContent = useSetAtom(noteContentAtom); const setValue = useSetAtom(atom);
const openFileDialog = async () => { const openFileDialog = async () => {
const selected: any = await open({ const selected: any = await open({
@@ -18,7 +36,7 @@ export const ImagePicker = () => {
filters: [ filters: [
{ {
name: 'Image', name: 'Image',
extensions: ['png', 'jpeg', 'jpg', 'webp', 'avif'], extensions: ['png', 'jpeg', 'jpg', 'gif'],
}, },
], ],
}); });
@@ -47,7 +65,7 @@ export const ImagePicker = () => {
}); });
const webpImage = 'https://void.cat/d/' + res.data.file.id + '.webp'; const webpImage = 'https://void.cat/d/' + res.data.file.id + '.webp';
setNoteContent((content) => content + ' ' + webpImage); setValue((content: string) => content + ' ' + webpImage);
setLoading(false); setLoading(false);
} }
}; };

View File

@@ -9,3 +9,6 @@ export const sortedChannelMessagesAtom = atom((get) => {
const messages = get(channelMessagesAtom); const messages = get(channelMessagesAtom);
return messages.sort((x: { created_at: number }, y: { created_at: number }) => x.created_at - y.created_at); return messages.sort((x: { created_at: number }, y: { created_at: number }) => x.created_at - y.created_at);
}); });
// channel message content
export const channelContentAtom = atomWithReset('');

View File

@@ -6,3 +6,6 @@ export const sortedChatMessagesAtom = atom((get) => {
const messages = get(chatMessagesAtom); const messages = get(chatMessagesAtom);
return messages.sort((x: { created_at: number }, y: { created_at: number }) => x.created_at - y.created_at); return messages.sort((x: { created_at: number }, y: { created_at: number }) => x.created_at - y.created_at);
}); });
// chat content
export const chatContentAtom = atomWithReset('');