This commit is contained in:
Ren Amamiya 2023-06-03 15:32:47 +07:00
parent 6e1fa10402
commit 93711e1d36
17 changed files with 128 additions and 50 deletions

View File

@ -21,6 +21,7 @@
"@vidstack/react": "^0.4.5",
"dayjs": "^1.11.7",
"destr": "^1.2.2",
"embla-carousel-react": "8.0.0-rc06",
"immer": "^10.0.2",
"light-bolt11-decoder": "^3.0.0",
"nostr-relaypool": "^0.6.28",

View File

@ -25,6 +25,9 @@ dependencies:
destr:
specifier: ^1.2.2
version: 1.2.2
embla-carousel-react:
specifier: 8.0.0-rc06
version: 8.0.0-rc06(react@18.2.0)
immer:
specifier: ^10.0.2
version: 10.0.2
@ -1256,6 +1259,28 @@ packages:
resolution: {integrity: sha512-AUYh0XDTb2vrj0rj82jb3P9hHSyzQNdTPYWZIhPdCOui7/vpme7+HTE07BE5jwuqg/34TZ8ktlRz6GImJ4IXjA==}
dev: true
/embla-carousel-react@8.0.0-rc06(react@18.2.0):
resolution: {integrity: sha512-aZfVqTptCA6uq3VLPFXLKGSkxVdoiNjQa1sjVOJc+9FL6pbwImaVR0oL7jA0kfW9l67XoQOEOq1gRiImbYr/Ew==}
peerDependencies:
react: ^16.8.0 || ^17.0.1 || ^18.0.0
dependencies:
embla-carousel: 8.0.0-rc06
embla-carousel-reactive-utils: 8.0.0-rc06(embla-carousel@8.0.0-rc06)
react: 18.2.0
dev: false
/embla-carousel-reactive-utils@8.0.0-rc06(embla-carousel@8.0.0-rc06):
resolution: {integrity: sha512-AlTrD9eh8aNlDsSjnEOM15Z9f4vQVgG+ULLMSl3BfWdqYvxsbinRcVQd2Buj3KlNq3pH7pm20G63CEz1h8p/Ig==}
peerDependencies:
embla-carousel: 8.0.0-rc06
dependencies:
embla-carousel: 8.0.0-rc06
dev: false
/embla-carousel@8.0.0-rc06:
resolution: {integrity: sha512-Dq27CG9OgZjKxK+JJS3uyEW4dwQ3oVkvlTHEP17idVnP8vmuhi4WtGe4UVGj8m0O2WASR4kNu4efFXkF7u6A+g==}
dev: false
/emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
dev: true

View File

@ -47,15 +47,19 @@ export function ChannelCreateModal() {
pubkey: account.pubkey,
tags: [],
};
event.id = getEventHash(event);
event.sig = getSignature(event, account.privkey);
// publish channel
pool.publish(event, WRITEONLY_RELAYS);
// insert to database
createChannel(event.id, event.pubkey, event.content, event.created_at);
// reset form
reset();
setTimeout(() => {
// close modal
setIsOpen(false);
@ -111,12 +115,12 @@ export function ChannelCreateModal() {
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel 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="h-min w-full shrink-0 border-b border-zinc-800 px-5 py-5">
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between">
<Dialog.Title
as="h3"
className="text-xl font-semibold leading-none text-white"
className="text-lg font-semibold leading-none text-white"
>
Create channel
</Dialog.Title>
@ -132,7 +136,7 @@ export function ChannelCreateModal() {
/>
</button>
</div>
<Dialog.Description className="leading-tight text-zinc-300">
<Dialog.Description className="text-sm leading-tight text-zinc-400">
Channels are freedom square, everyone can speech freely,
no one can stop you or deceive what to speech
</Dialog.Description>
@ -150,7 +154,7 @@ export function ChannelCreateModal() {
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-white dark:shadow-black/10 dark:placeholder:text-zinc-500"
/>
<div className="flex flex-col gap-1">
<label className="text-base font-semibold uppercase tracking-wider text-zinc-400">
<label className="text-sm font-medium uppercase tracking-wider text-zinc-400">
Picture
</label>
<div className="relative inline-flex h-36 w-full items-center justify-center overflow-hidden rounded-lg border border-zinc-900 bg-zinc-950">
@ -165,7 +169,7 @@ export function ChannelCreateModal() {
</div>
</div>
<div className="flex flex-col gap-1">
<label className="text-base font-semibold uppercase tracking-wider text-zinc-400">
<label className="text-sm font-medium 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">
@ -181,7 +185,7 @@ export function ChannelCreateModal() {
</div>
</div>
<div className="flex flex-col gap-1">
<label className="text-base font-semibold uppercase tracking-wider text-zinc-400">
<label className="text-sm font-medium 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">
@ -192,20 +196,14 @@ export function ChannelCreateModal() {
/>
</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-base font-bold leading-none text-white">
Make Private
</span>
<div className="inline-flex items-center rounded-md bg-zinc-400/10 px-2 py-0.5 text-base 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-base leading-none text-zinc-400">
Private channels can only be viewed by member
<div className="flex h-20 items-center justify-between gap-1 rounded-lg bg-zinc-800 px-4 py-2">
<div className="flex flex-col gap-1">
<span className="font-semibold leading-none text-white">
Encrypted
</span>
<p className="w-4/5 text-sm leading-none text-zinc-400">
All messages are encrypted and only invited members
can view and send message
</p>
</div>
<div>

View File

@ -113,12 +113,12 @@ export function ChannelUpdateModal({ id }: { id: string }) {
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel 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="h-min w-full shrink-0 border-b border-zinc-800 px-5 py-5">
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between">
<Dialog.Title
as="h3"
className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-xl font-semibold leading-none text-transparent"
className="text-lg font-semibold leading-none text-white"
>
Update channel
</Dialog.Title>
@ -134,7 +134,7 @@ export function ChannelUpdateModal({ id }: { id: string }) {
/>
</button>
</div>
<Dialog.Description className="leading-tight text-zinc-400">
<Dialog.Description className="text-sm leading-tight text-zinc-400">
New metadata will be published on all relays, and will be
immediately available to all users, so please carefully.
</Dialog.Description>
@ -152,7 +152,7 @@ export function ChannelUpdateModal({ id }: { id: string }) {
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-white dark:shadow-black/10 dark:placeholder:text-zinc-500"
/>
<div className="flex flex-col gap-1">
<label className="text-base font-semibold uppercase tracking-wider text-zinc-400">
<label className="text-sm font-medium uppercase tracking-wider text-zinc-400">
Picture
</label>
<div className="relative inline-flex h-36 w-full items-center justify-center overflow-hidden rounded-lg border border-zinc-900 bg-zinc-950">
@ -167,7 +167,7 @@ export function ChannelUpdateModal({ id }: { id: string }) {
</div>
</div>
<div className="flex flex-col gap-1">
<label className="text-base font-semibold uppercase tracking-wider text-zinc-400">
<label className="text-sm font-medium 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">
@ -183,7 +183,7 @@ export function ChannelUpdateModal({ id }: { id: string }) {
</div>
</div>
<div className="flex flex-col gap-1">
<label className="text-base font-semibold uppercase tracking-wider text-zinc-400">
<label className="text-sm font-medium 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">

View File

@ -29,7 +29,7 @@ export function NoteBase({ event }: { event: any }) {
)}
<div className="flex flex-col">
<NoteDefaultUser pubkey={event.pubkey} time={event.created_at} />
<div className="-mt-5 pl-[48px]">
<div className="-mt-5 pl-[49px]">
{event.kind === 1 && <Kind1 content={content} />}
{event.kind === 1063 && <Kind1063 metadata={event.tags} />}
<NoteMetadata id={event.event_id} eventPubkey={event.pubkey} />

View File

@ -44,7 +44,7 @@ export const MentionNote = memo(function MentionNote({ id }: { id: string }) {
return (
<NoteWrapper
href={`/app/note?id=${id}`}
className="mt-3 rounded-lg border border-zinc-800 px-3 pt-3"
className="mt-3 rounded-lg border border-zinc-800 px-3 py-3"
>
{data ? (
<>
@ -52,6 +52,21 @@ export const MentionNote = memo(function MentionNote({ id }: { id: string }) {
<div className="mt-2">
{kind1 && <Kind1 content={kind1} truncate={true} />}
{kind1063 && <Kind1063 metadata={kind1063} />}
{!kind1 && !kind1063 && (
<div className="flex flex-col gap-2">
<div className="px-2 py-2 inline-flex flex-col gap-1 bg-zinc-800 rounded-md">
<span className="text-zinc-500 text-sm font-medium leading-none">
Kind: {data.kind}
</span>
<p className="text-fuchsia-500 text-sm leading-none">
Lume isn't fully support this kind in newsfeed
</p>
</div>
<div className="markdown">
<p>{data.content}</p>
</div>
</div>
)}
</div>
</>
) : (

View File

@ -62,7 +62,7 @@ export function NoteMetadata({
});
return (
<div className="inline-flex items-center gap-2 w-full h-14 mt-5 border-t border-zinc-800">
<div className="inline-flex items-center gap-2 w-full h-12 mt-4">
<NoteReply id={id} replies={replies} />
<NoteRepost id={id} pubkey={eventPubkey} reposts={reposts} />
<div className="ml-auto">

View File

@ -42,14 +42,29 @@ export const NoteParent = memo(function NoteParent({ id }: { id: string }) {
const kind1063 = !error && data?.kind === 1063 ? data.tags : null;
return (
<div className="relative flex flex-col pb-6">
<div className="relative overflow-hidden flex flex-col pb-6">
<div className="absolute left-[18px] top-0 h-full w-0.5 bg-gradient-to-t from-zinc-800 to-zinc-600" />
{data ? (
<>
<NoteDefaultUser pubkey={data.pubkey} time={data.created_at} />
<div className="-mt-5 pl-[48px]">
<div className="-mt-5 pl-[49px]">
{kind1 && <Kind1 content={kind1} />}
{kind1063 && <Kind1063 metadata={kind1063} />}
{!kind1 && !kind1063 && (
<div className="flex flex-col gap-2">
<div className="px-2 py-2 inline-flex flex-col gap-1 bg-zinc-800 rounded-md">
<span className="text-zinc-500 text-sm font-medium leading-none">
Kind: {data.kind}
</span>
<p className="text-fuchsia-500 text-sm leading-none">
Lume isn't fully support this kind in newsfeed
</p>
</div>
<div className="markdown">
<p>{data.content}</p>
</div>
</div>
)}
<NoteMetadata id={data.id} eventPubkey={data.pubkey} />
</div>
</>

View File

@ -1,14 +1,21 @@
import { Image } from "@shared/image";
import useEmblaCarousel from "embla-carousel-react";
export function ImagePreview({ urls }: { urls: string[] }) {
const [emblaRef] = useEmblaCarousel();
return (
<div className="mt-3 grid h-full w-full grid-cols-3">
<div className="col-span-3">
<Image
src={urls[0]}
alt="image"
className="h-auto w-full rounded-lg object-cover"
/>
<div ref={emblaRef} className="mt-3 overflow-hidden">
<div className="flex">
{urls.map((url) => (
<div className="mr-2 min-w-0 grow-0 shrink-0 basis-full">
<Image
src={url}
alt="image"
className="h-auto w-full rounded-lg object-cover"
/>
</div>
))}
</div>
</div>
);

View File

@ -77,7 +77,7 @@ export const RootNote = memo(function RootNote({
pubkey={parseFallback.pubkey}
time={parseFallback.created_at}
/>
<div className="-mt-5 pl-[48px]">
<div className="-mt-5 pl-[49px]">
<Kind1 content={contentFallback} />
<NoteMetadata
id={parseFallback.id}
@ -97,9 +97,24 @@ export const RootNote = memo(function RootNote({
{data ? (
<>
<NoteDefaultUser pubkey={data.pubkey} time={data.created_at} />
<div className="-mt-5 pl-[48px]">
<div className="-mt-5 pl-[49px]">
{kind1 && <Kind1 content={kind1} />}
{kind1063 && <Kind1063 metadata={kind1063} />}
{!kind1 && !kind1063 && (
<div className="flex flex-col gap-2">
<div className="px-2 py-2 inline-flex flex-col gap-1 bg-zinc-800 rounded-md">
<span className="text-zinc-500 text-sm font-medium leading-none">
Kind: {data.kind}
</span>
<p className="text-fuchsia-500 text-sm leading-none">
Lume isn't fully support this kind in newsfeed
</p>
</div>
<div className="markdown">
<p>{data.content}</p>
</div>
</div>
)}
<NoteMetadata id={data.id} eventPubkey={data.pubkey} />
</div>
</>

View File

@ -1,7 +1,6 @@
import { Dialog, Transition } from "@headlessui/react";
import { CancelIcon } from "@shared/icons";
import { useActiveAccount } from "@stores/accounts";
import { createBlock } from "@utils/storage";
import { nip19 } from "nostr-tools";
import { Fragment, useState } from "react";
import { useForm } from "react-hook-form";
@ -72,7 +71,7 @@ export function AddFeedBlock({ parentState }: { parentState: any }) {
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel 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="h-min w-full shrink-0 border-b border-zinc-800 px-5 py-5">
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between">
<Dialog.Title

View File

@ -146,7 +146,7 @@ export function AddImageBlock({ parentState }: { parentState: any }) {
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel 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="h-min w-full shrink-0 border-b border-zinc-800 px-5 py-5">
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between">
<Dialog.Title

View File

@ -15,7 +15,7 @@ button {
}
.markdown {
@apply prose prose-zinc max-w-none select-text break-words dark:prose-invert prose-p:mt-0 prose-p:text-[15px] prose-p:leading-tight prose-a:text-[15px] prose-a:font-normal prose-a:leading-tight prose-a:text-fuchsia-500 hover:prose-a:text-fuchsia-600 prose-ol:mb-1 prose-ul:mb-1 prose-li:text-[15px] prose-li:leading-tight;
@apply prose prose-zinc max-w-none select-text break-words dark:prose-invert prose-p:m-0 prose-p:leading-tight prose-a:text-[15px] prose-a:font-normal prose-a:leading-tight prose-a:text-fuchsia-500 hover:prose-a:text-fuchsia-600 prose-ol:mb-1 prose-ul:mb-1 prose-li:text-[15px] prose-li:leading-tight prose-blockquote:m-0 prose-hr:mx-0 prose-hr:my-2;
}
/* For Webkit-based browsers (Chrome, Safari and Opera) */

View File

@ -51,7 +51,7 @@ export function MultiAccounts() {
</>
<button
type="button"
className="group relative flex h-10 w-10 shrink items-center justify-center rounded-lg border-2 border-dashed border-transparent hover:border-zinc-600"
className="group relative flex h-10 w-10 shrink items-center justify-center rounded-md border border-dashed border-transparent hover:border-zinc-600"
>
<PlusIcon
width={16}

View File

@ -34,7 +34,7 @@ export function Navigation() {
<ActiveLink
href="/app/threads"
className="flex h-8 items-center gap-2.5 rounded-md px-2.5 text-zinc-200 hover:text-white"
activeClassName=""
activeClassName="bg-zinc-900/50 hover:bg-zinc-900"
>
<span className="inline-flex h-5 w-5 items-center justify-center rounded bg-zinc-900">
<ThreadsIcon width={12} height={12} className="text-white" />

View File

@ -22,6 +22,12 @@ export const useActiveAccount = create(
const response = await createAccount(npub, pubkey, privkey, null, 1);
if (response) {
const activeAccount = await getActiveAccount();
await addBlockToDB(
activeAccount.id,
0,
"Freedom Awaits",
"https://void.cat/d/88M2kWHtjZLRtdyfAajHbu.webp",
);
set({
account: activeAccount,
});

View File

@ -55,10 +55,7 @@ export function noteParser(event: Event) {
}
if (profile) {
content.parsed = content.parsed.replace(
item.text,
`[${profile.pubkey}](/user?pubkey=${profile.pubkey})`,
);
content.parsed = content.parsed.replace(item.text, `*${profile.pubkey}*`);
}
});