This commit is contained in:
Ren Amamiya 2023-07-26 09:26:40 +07:00
parent 89dd4f5c9d
commit f52ea04541
13 changed files with 69 additions and 140 deletions

View File

@ -34,7 +34,7 @@ export function User({ pubkey, fallback }: { pubkey: string; fallback?: string }
<span className="truncate font-medium leading-tight text-zinc-100">
{user?.name || user?.displayName || user?.display_name}
</span>
<span className="text-base leading-tight text-zinc-400">
<span className="max-w-[15rem] truncate text-base leading-tight text-zinc-400">
{user?.nip05?.toLowerCase() || shortenKey(pubkey)}
</span>
</div>

View File

@ -24,12 +24,13 @@ export function CreateStep3Screen() {
formState: { isDirty, isValid },
} = useForm();
const onSubmit = (data: any) => {
const onSubmit = (data: { name: string; about: string }) => {
setLoading(true);
try {
const profile = {
...data,
username: data.name,
name: data.name,
display_name: data.name,
bio: data.about,
};

View File

@ -22,7 +22,7 @@ export function OnboardingScreen() {
// publish event
publish({
content: 'Running Lume, join with me: https://lume.nu',
content: 'Running Lume, join with me #nostr #lume : https://lume.nu',
kind: 1,
tags: [],
});
@ -55,7 +55,7 @@ export function OnboardingScreen() {
<User pubkey={account.pubkey} time={Math.floor(Date.now() / 1000)} />
)}
<div className="-mt-6 select-text whitespace-pre-line break-words pl-[49px] text-base text-zinc-100">
<p>Running Lume, join with me</p>
<p>Running Lume, join with me #nostr #lume</p>
<a
href="https://lume.nu"
className="font-normal text-fuchsia-500 no-underline hover:text-fuchsia-600"

View File

@ -88,6 +88,7 @@ export function UserScreen() {
<NoteKind_1 event={data[virtualRow.index]} />
</div>
))}
<div className="h-10" />
</div>
</div>
)}

View File

@ -55,7 +55,7 @@ export async function createAccount(
await createBlock(
0,
'Have fun together!',
'https://i.nostrimg.com/cf7bdc227592686a0fcefcecb63fa860aab74c3c36dcd1cb6b09530188db7791/file.jpg'
'https://void.cat/d/N5KUHEQCVg7SywXUPiJ7yq.jpg'
);
}
const getAccount = await getActiveAccount();

View File

@ -1,54 +1,18 @@
import { open } from '@tauri-apps/api/dialog';
import { Body, fetch } from '@tauri-apps/api/http';
import { useState } from 'react';
import { LoaderIcon, PlusIcon } from '@shared/icons';
import { createBlobFromFile } from '@utils/createBlobFromFile';
import { useImageUploader } from '@utils/hooks/useUploader';
export function AvatarUploader({ setPicture }: { setPicture: any }) {
const upload = useImageUploader();
const [loading, setLoading] = useState(false);
const openFileDialog = async () => {
const selected: any = await open({
multiple: false,
filters: [
{
name: 'Image',
extensions: ['png', 'jpeg', 'jpg', 'gif'],
},
],
});
if (Array.isArray(selected)) {
// user selected multiple files
} else if (selected === null) {
// user cancelled the selection
} else {
setLoading(true);
const filename = selected.split('/').pop();
const file = await createBlobFromFile(selected);
const buf = await file.arrayBuffer();
const res: { data: { file: { id: string } } } = await fetch(
'https://void.cat/upload?cli=false',
{
method: 'POST',
timeout: 5,
headers: {
accept: '*/*',
'Content-Type': 'application/octet-stream',
'V-Filename': filename,
'V-Description': 'Upload from https://lume.nu',
'V-Strip-Metadata': 'true',
},
body: Body.bytes(buf),
}
);
const image = `https://void.cat/d/${res.data.file.id}.jpg`;
const uploadAvatar = async () => {
const image = await upload(null);
if (image.url) {
// update parent state
setPicture(image);
setPicture(image.url);
// disable loader
setLoading(false);
@ -58,7 +22,7 @@ export function AvatarUploader({ setPicture }: { setPicture: any }) {
return (
<button
type="button"
onClick={() => openFileDialog()}
onClick={() => uploadAvatar()}
className="inline-flex h-full w-full items-center justify-center bg-zinc-900/40"
>
{loading ? (

View File

@ -1,52 +1,16 @@
import { open } from '@tauri-apps/api/dialog';
import { Body, fetch } from '@tauri-apps/api/http';
import { useState } from 'react';
import { LoaderIcon, PlusIcon } from '@shared/icons';
import { createBlobFromFile } from '@utils/createBlobFromFile';
import { useImageUploader } from '@utils/hooks/useUploader';
export function BannerUploader({ setBanner }: { setBanner: any }) {
const upload = useImageUploader();
const [loading, setLoading] = useState(false);
const openFileDialog = async () => {
const selected: any = await open({
multiple: false,
filters: [
{
name: 'Image',
extensions: ['png', 'jpeg', 'jpg', 'gif'],
},
],
});
if (Array.isArray(selected)) {
// user selected multiple files
} else if (selected === null) {
// user cancelled the selection
} else {
setLoading(true);
const filename = selected.split('/').pop();
const file = await createBlobFromFile(selected);
const buf = await file.arrayBuffer();
const res: { data: { file: { id: string } } } = await fetch(
'https://void.cat/upload?cli=false',
{
method: 'POST',
timeout: 5,
headers: {
accept: '*/*',
'Content-Type': 'application/octet-stream',
'V-Filename': filename,
'V-Description': 'Upload from https://lume.nu',
'V-Strip-Metadata': 'true',
},
body: Body.bytes(buf),
}
);
const image = `https://void.cat/d/${res.data.file.id}.jpg`;
const uploadBanner = async () => {
const image = await upload(null);
if (image.url) {
// update parent state
setBanner(image);
@ -58,7 +22,7 @@ export function BannerUploader({ setBanner }: { setBanner: any }) {
return (
<button
type="button"
onClick={() => openFileDialog()}
onClick={() => uploadBanner()}
className="inline-flex h-full w-full items-center justify-center bg-zinc-900/40"
>
{loading ? (

View File

@ -312,6 +312,20 @@ export function EditProfileModal() {
className="relative h-10 w-full rounded-lg bg-zinc-800 px-3 py-2 text-zinc-100 !outline-none placeholder:text-zinc-500"
/>
</div>
<div className="flex flex-col gap-1">
<label
htmlFor="website"
className="text-sm font-semibold uppercase tracking-wider text-zinc-400"
>
Lightning address
</label>
<input
type={'text'}
{...register('lud16', { required: false })}
spellCheck={false}
className="relative h-10 w-full rounded-lg bg-zinc-800 px-3 py-2 text-zinc-100 !outline-none placeholder:text-zinc-500"
/>
</div>
<div>
<button
type="submit"

View File

@ -1,57 +1,20 @@
import * as Tooltip from '@radix-ui/react-tooltip';
import { open } from '@tauri-apps/api/dialog';
import { Body, fetch } from '@tauri-apps/api/http';
import { useState } from 'react';
import { LoaderIcon, MediaIcon } from '@shared/icons';
import { createBlobFromFile } from '@utils/createBlobFromFile';
import { useImageUploader } from '@utils/hooks/useUploader';
export function MediaUploader({ setState }: { setState: any }) {
const upload = useImageUploader();
const [loading, setLoading] = useState(false);
const openFileDialog = async () => {
const selected: any = await open({
multiple: false,
filters: [
{
name: 'Image & Video',
extensions: ['png', 'jpeg', 'jpg', 'gif', 'mp4', 'mov'],
},
],
});
if (Array.isArray(selected)) {
// user selected multiple files
} else if (selected === null) {
// user cancelled the selection
} else {
// start loading
setLoading(true);
const filename = selected.split('/').pop();
const file = await createBlobFromFile(selected);
const buf = await file.arrayBuffer();
const res: { data: { file: { id: string } } } = await fetch(
'https://void.cat/upload?cli=false',
{
method: 'POST',
timeout: 5,
headers: {
accept: '*/*',
'Content-Type': 'application/octet-stream',
'V-Filename': filename,
'V-Description': 'Upload from https://lume.nu',
'V-Strip-Metadata': 'true',
},
body: Body.bytes(buf),
}
);
const image = `https://void.cat/d/${res.data.file.id}.webp`;
const uploadMedia = async () => {
const image = await upload(null);
if (image.url) {
// update state
setState((prev: string) => `${prev}\n${image}`);
setState((prev: string) => `${prev}\n${image.url}`);
// stop loading
setLoading(false);
}
@ -63,7 +26,7 @@ export function MediaUploader({ setState }: { setState: any }) {
<Tooltip.Trigger asChild>
<button
type="button"
onClick={() => openFileDialog()}
onClick={() => uploadMedia()}
className="group inline-flex h-6 w-6 items-center justify-center rounded bg-zinc-700 hover:bg-zinc-600"
>
{loading ? (

View File

@ -8,6 +8,7 @@ import { NoteZap } from '@shared/notes/actions/zap';
import { BLOCK_KINDS } from '@stores/constants';
import { useAccount } from '@utils/hooks/useAccount';
import { useBlock } from '@utils/hooks/useBlock';
export function NoteActions({
@ -22,6 +23,7 @@ export function NoteActions({
root?: string;
}) {
const { add } = useBlock();
const { account } = useAccount();
return (
<Tooltip.Provider>
@ -30,7 +32,7 @@ export function NoteActions({
<NoteReply id={id} pubkey={pubkey} root={root} />
<NoteReaction id={id} pubkey={pubkey} />
<NoteRepost id={id} pubkey={pubkey} />
<NoteZap id={id} />
{(account?.lud06 || account?.lud16) && <NoteZap id={id} />}
</div>
{!noOpenThread && (
<>

View File

@ -23,7 +23,7 @@ export function NoteZap({ id }: { id: string }) {
};
const createZapRequest = async () => {
const res = await createZap(event as NostrEvent, amount);
const res = await createZap(event as unknown as NostrEvent, amount);
if (res) setInvoice(res);
};

View File

@ -1,6 +1,8 @@
import { ReactNode } from 'react';
import { Navigate } from 'react-router-dom';
import { LoaderIcon } from '@shared/icons';
import { useStronghold } from '@stores/stronghold';
import { useAccount } from '@utils/hooks/useAccount';
@ -9,15 +11,23 @@ export function Protected({ children }: { children: ReactNode }) {
const privkey = useStronghold((state) => state.privkey);
const { status, account } = useAccount();
if (status === 'success' && !account) {
if (status === 'loading') {
return (
<div className="flex h-full w-full items-center justify-center">
<LoaderIcon className="h-6 w-6 animate-spin text-zinc-100" />
</div>
);
}
if (!account) {
return <Navigate to="/auth/welcome" replace />;
}
if (status === 'success' && account && account.privkey.length > 35) {
if (account && account.privkey.length > 35) {
return <Navigate to="/auth/migrate" replace />;
}
if (status === 'success' && account && !privkey) {
if (account && !privkey) {
return <Navigate to="/auth/unlock" replace />;
}

View File

@ -1,11 +1,21 @@
import { useQuery } from '@tanstack/react-query';
import { useNDK } from '@libs/ndk/provider';
import { getActiveAccount } from '@libs/storage';
export function useAccount() {
const { ndk } = useNDK();
const { status, data: account } = useQuery(
['currentAccount'],
async () => await getActiveAccount(),
async () => {
const account = await getActiveAccount();
if (account?.pubkey) {
const user = ndk.getUser({ hexpubkey: account?.pubkey });
await user.fetchProfile();
return { ...account, ...user.profile };
}
return account;
},
{
staleTime: Infinity,
refetchOnMount: true,