update repost
This commit is contained in:
@@ -36,7 +36,7 @@ export function ChatsListItem({ data }: { data: any }) {
|
||||
<Image
|
||||
src={user?.image || DEFAULT_AVATAR}
|
||||
alt={data.sender_pubkey}
|
||||
className="h-5 w-5 rounded bg-white object-cover"
|
||||
className="h-5 w-5 rounded object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full inline-flex items-center justify-between">
|
||||
|
||||
@@ -8,33 +8,31 @@ import {
|
||||
ComposeIcon,
|
||||
} from "@shared/icons";
|
||||
import { useActiveAccount } from "@stores/accounts";
|
||||
import { Fragment, useState } from "react";
|
||||
|
||||
export function ComposerModal() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [composer] = useState({ type: "post" });
|
||||
import { useComposer } from "@stores/composer";
|
||||
import { Fragment } from "react";
|
||||
|
||||
export function Composer() {
|
||||
const account = useActiveAccount((state: any) => state.account);
|
||||
const [toggle, open] = useComposer((state: any) => [
|
||||
state.toggleModal,
|
||||
state.open,
|
||||
]);
|
||||
|
||||
const closeModal = () => {
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const openModal = () => {
|
||||
setIsOpen(true);
|
||||
toggle(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => openModal()}
|
||||
onClick={() => toggle(true)}
|
||||
className="inline-flex h-8 w-max items-center justify-center gap-1 rounded-md bg-fuchsia-500 px-2.5 text-sm font-medium text-zinc-100 shadow-button hover:bg-fuchsia-600 focus:outline-none"
|
||||
>
|
||||
<ComposeIcon width={14} height={14} />
|
||||
Compose
|
||||
</button>
|
||||
<Transition appear show={isOpen} as={Fragment}>
|
||||
<Transition appear show={open} as={Fragment}>
|
||||
<Dialog as="div" className="relative z-10" onClose={closeModal}>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
@@ -68,7 +66,7 @@ export function ComposerModal() {
|
||||
className="text-zinc-500"
|
||||
/>
|
||||
</span>
|
||||
<div className="inline-flex h-6 w-max items-center justify-center gap-0.5 rounded bg-zinc-800 pl-3 pr-1.5 text-base font-medium text-zinc-400 shadow-mini-button">
|
||||
<div className="inline-flex h-6 w-max items-center justify-center gap-0.5 rounded bg-zinc-800 pl-3 pr-1.5 text-sm font-medium text-zinc-400">
|
||||
New Post
|
||||
<ChevronDownIcon width={14} height={14} />
|
||||
</div>
|
||||
@@ -85,9 +83,7 @@ export function ComposerModal() {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{composer.type === "post" && account && (
|
||||
<Post pubkey={account.pubkey} privkey={account.privkey} />
|
||||
)}
|
||||
<Post pubkey={account.pubkey} privkey={account.privkey} />
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
|
||||
import { ImageUploader } from "@shared/composer/imageUploader";
|
||||
import { TrashIcon } from "@shared/icons";
|
||||
import { MentionNote } from "@shared/notes/mentions/note";
|
||||
import { RelayContext } from "@shared/relayProvider";
|
||||
import { useComposer } from "@stores/composer";
|
||||
import { dateToUnix } from "@utils/date";
|
||||
import { useCallback, useContext, useMemo, useState } from "react";
|
||||
import { Node, Transforms, createEditor } from "slate";
|
||||
@@ -59,7 +61,10 @@ const ImagePreview = ({
|
||||
|
||||
export function Post({ pubkey, privkey }: { pubkey: string; privkey: string }) {
|
||||
const ndk = useContext(RelayContext);
|
||||
|
||||
const [repost, toggle] = useComposer((state: any) => [
|
||||
state.repost,
|
||||
state.toggle,
|
||||
]);
|
||||
const editor = useMemo(
|
||||
() => withReact(withImages(withHistory(createEditor()))),
|
||||
[],
|
||||
@@ -87,14 +92,25 @@ export function Post({ pubkey, privkey }: { pubkey: string; privkey: string }) {
|
||||
ndk.signer = signer;
|
||||
|
||||
const event = new NDKEvent(ndk);
|
||||
event.kind = 1;
|
||||
event.content = serializedContent;
|
||||
event.created_at = dateToUnix();
|
||||
event.pubkey = pubkey;
|
||||
event.tags = [];
|
||||
if (repost.id && repost.pubkey) {
|
||||
event.kind = 6;
|
||||
event.tags = [
|
||||
["e", repost.id],
|
||||
["p", repost.pubkey],
|
||||
];
|
||||
} else {
|
||||
event.kind = 1;
|
||||
event.tags = [];
|
||||
}
|
||||
|
||||
// publish event
|
||||
event.publish();
|
||||
|
||||
// close modal
|
||||
toggle(false);
|
||||
};
|
||||
|
||||
const renderElement = useCallback((props: any) => {
|
||||
@@ -115,17 +131,20 @@ export function Post({ pubkey, privkey }: { pubkey: string; privkey: string }) {
|
||||
<div className="flex w-8 shrink-0 items-center justify-center">
|
||||
<div className="h-full w-[2px] bg-zinc-800" />
|
||||
</div>
|
||||
<div className="w-full markdown">
|
||||
<div className="w-full">
|
||||
<Editable
|
||||
autoFocus
|
||||
placeholder="What's on your mind?"
|
||||
spellCheck="false"
|
||||
className="!min-h-[86px]"
|
||||
className={`${
|
||||
repost.id ? "!min-h-42" : "!min-h-[86px]"
|
||||
} markdown`}
|
||||
renderElement={renderElement}
|
||||
/>
|
||||
{repost.id && <MentionNote id={repost.id} />}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="mt-4 flex items-center justify-between">
|
||||
<ImageUploader />
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -3,21 +3,19 @@ import { ChatsList } from "@app/chat/components/list";
|
||||
import { Disclosure } from "@headlessui/react";
|
||||
import { ActiveLink } from "@shared/activeLink";
|
||||
import { AppHeader } from "@shared/appHeader";
|
||||
import { ComposerModal } from "@shared/composer/modal";
|
||||
import {
|
||||
NavArrowDownIcon,
|
||||
SpaceIcon,
|
||||
TrendingIcon,
|
||||
WorldIcon,
|
||||
} from "@shared/icons";
|
||||
import { Composer } from "@shared/composer/modal";
|
||||
import { NavArrowDownIcon, SpaceIcon, TrendingIcon } from "@shared/icons";
|
||||
import { useComposer } from "@stores/composer";
|
||||
|
||||
export function Navigation() {
|
||||
const toggle = useComposer((state: any) => state.toggleModal);
|
||||
|
||||
return (
|
||||
<div className="flex w-[232px] flex-col gap-3 border-r border-zinc-900">
|
||||
<AppHeader />
|
||||
<div className="flex flex-col gap-3 h-full overflow-y-auto scrollbar-hide">
|
||||
<div className="inlin-lflex h-8 px-3.5">
|
||||
<ComposerModal />
|
||||
<Composer />
|
||||
</div>
|
||||
{/* Newsfeed */}
|
||||
<div className="flex flex-col gap-0.5 px-1.5">
|
||||
|
||||
@@ -10,8 +10,12 @@ export function Kind1({
|
||||
}: { content: any; truncate?: boolean }) {
|
||||
return (
|
||||
<>
|
||||
<div className="select-text whitespace-pre-line break-words text-base text-zinc-100">
|
||||
{truncate ? truncateContent(content.original, 100) : content.parsed}
|
||||
<div
|
||||
className={`select-text whitespace-pre-line break-words text-base text-zinc-100 ${
|
||||
truncate ? "line-clamp-3" : ""
|
||||
}`}
|
||||
>
|
||||
{content.parsed}
|
||||
</div>
|
||||
{Array.isArray(content.images) && content.images.length ? (
|
||||
<ImagePreview urls={content.images} />
|
||||
|
||||
@@ -1,49 +1,18 @@
|
||||
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
|
||||
import { RepostIcon } from "@shared/icons";
|
||||
import { RelayContext } from "@shared/relayProvider";
|
||||
import { useActiveAccount } from "@stores/accounts";
|
||||
import { dateToUnix } from "@utils/date";
|
||||
import { useComposer } from "@stores/composer";
|
||||
import { compactNumber } from "@utils/number";
|
||||
import { useContext, useState } from "react";
|
||||
|
||||
export function NoteRepost({
|
||||
id,
|
||||
pubkey,
|
||||
reposts,
|
||||
}: { id: string; pubkey: string; reposts: number }) {
|
||||
const ndk = useContext(RelayContext);
|
||||
const account = useActiveAccount((state: any) => state.account);
|
||||
|
||||
const [count, setCount] = useState(reposts);
|
||||
|
||||
const submitEvent = (e: any) => {
|
||||
e.stopPropagation();
|
||||
|
||||
const signer = new NDKPrivateKeySigner(account.privkey);
|
||||
ndk.signer = signer;
|
||||
|
||||
const event = new NDKEvent(ndk);
|
||||
// build event
|
||||
event.content = "";
|
||||
event.kind = 6;
|
||||
event.created_at = dateToUnix();
|
||||
event.pubkey = account.pubkey;
|
||||
event.tags = [
|
||||
["e", id],
|
||||
["p", pubkey],
|
||||
];
|
||||
|
||||
// publish event
|
||||
event.publish();
|
||||
|
||||
// update state
|
||||
setCount(count + 1);
|
||||
};
|
||||
const setRepost = useComposer((state: any) => state.setRepost);
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => submitEvent(e)}
|
||||
onClick={() => setRepost(id, pubkey)}
|
||||
className="w-20 group inline-flex items-center gap-1.5"
|
||||
>
|
||||
<RepostIcon
|
||||
@@ -52,7 +21,7 @@ export function NoteRepost({
|
||||
className="text-zinc-400 group-hover:text-blue-400"
|
||||
/>
|
||||
<span className="text-base leading-none text-zinc-400 group-hover:text-zinc-100">
|
||||
{compactNumber.format(count)}
|
||||
{compactNumber.format(reposts)}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
|
||||
@@ -27,12 +27,14 @@ export function User({
|
||||
}`}
|
||||
>
|
||||
<Popover.Button
|
||||
className={`${avatarWidth} ${avatarHeight} shrink-0 overflow-hidden rounded-md bg-zinc-900`}
|
||||
className={`${avatarWidth} ${avatarHeight} shrink-0 overflow-hidden`}
|
||||
>
|
||||
<Image
|
||||
src={user?.image || DEFAULT_AVATAR}
|
||||
alt={pubkey}
|
||||
className={`${avatarWidth} ${avatarHeight} rounded-md object-cover`}
|
||||
className={`${avatarWidth} ${avatarHeight} ${
|
||||
size === "small" ? "rounded" : "rounded-md"
|
||||
} object-cover`}
|
||||
/>
|
||||
</Popover.Button>
|
||||
<div className="flex flex-wrap items-baseline gap-1">
|
||||
|
||||
20
src/stores/composer.tsx
Normal file
20
src/stores/composer.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
export const useComposer = create((set) => ({
|
||||
open: false,
|
||||
repost: { id: null, pubkey: null },
|
||||
reply: null,
|
||||
toggleModal: (status: boolean) => {
|
||||
set({ open: status });
|
||||
if (!status) {
|
||||
set({ repost: { id: null, pubkey: null } });
|
||||
}
|
||||
},
|
||||
setRepost: (id: string, pubkey: string) => {
|
||||
set({ repost: { id: id, pubkey: pubkey } });
|
||||
set({ open: true });
|
||||
},
|
||||
clearRepost: () => {
|
||||
set({ repost: { id: null, pubkey: null } });
|
||||
},
|
||||
}));
|
||||
@@ -1,6 +1,6 @@
|
||||
export const APP_VERSION = "1.0.0";
|
||||
|
||||
export const DEFAULT_AVATAR = "https://void.cat/d/PZcdCxNc24rCCxV8QXbdFQ";
|
||||
export const DEFAULT_AVATAR = "https://void.cat/d/5VKmKyuHyxrNMf9bWSVPih";
|
||||
|
||||
export const OPENGRAPH_KEY = "9EJG4SY-19Q4M5J-H8R29C9-091XPCC";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user