diff --git a/package.json b/package.json
index 37ae2a7f..9b12f64a 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,6 @@
},
"dependencies": {
"@ctrl/magnet-link": "^3.1.2",
- "@headlessui/react": "^1.7.17",
"@nostr-dev-kit/ndk": "^0.8.21",
"@nostr-fetch/adapter-ndk": "^0.12.2",
"@radix-ui/react-alert-dialog": "^1.0.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f5f4f05e..c41e43e7 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4,9 +4,6 @@ dependencies:
'@ctrl/magnet-link':
specifier: ^3.1.2
version: 3.1.2
- '@headlessui/react':
- specifier: ^1.7.17
- version: 1.7.17(react-dom@18.2.0)(react@18.2.0)
'@nostr-dev-kit/ndk':
specifier: ^0.8.21
version: 0.8.21(typescript@5.2.2)
@@ -872,18 +869,6 @@ packages:
resolution: {integrity: sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==}
dev: false
- /@headlessui/react@1.7.17(react-dom@18.2.0)(react@18.2.0):
- resolution: {integrity: sha512-4am+tzvkqDSSgiwrsEpGWqgGo9dz8qU5M3znCkC4PgkpY4HcCZzEDEvozltGGGHIKl9jbXbZPSH5TWn4sWJdow==}
- engines: {node: '>=10'}
- peerDependencies:
- react: ^16 || ^17 || ^18
- react-dom: ^16 || ^17 || ^18
- dependencies:
- client-only: 0.0.1
- react: 18.2.0
- react-dom: 18.2.0(react@18.2.0)
- dev: false
-
/@humanwhocodes/config-array@0.11.10:
resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==}
engines: {node: '>=10.10.0'}
@@ -3064,10 +3049,6 @@ packages:
string-width: 5.1.2
dev: true
- /client-only@0.0.1:
- resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
- dev: false
-
/clone-regexp@3.0.0:
resolution: {integrity: sha512-ujdnoq2Kxb8s3ItNBtnYeXdm07FcU0u8ARAT1lQ2YdMwQC+cdiXX8KoqMVuglztILivceTtp4ivqGSmEmhBUJw==}
engines: {node: '>=12'}
diff --git a/src/app/chats/components/modal.tsx b/src/app/chats/components/modal.tsx
index 4e140e33..b0a3747c 100644
--- a/src/app/chats/components/modal.tsx
+++ b/src/app/chats/components/modal.tsx
@@ -6,7 +6,7 @@ import { User } from '@app/auth/components/user';
import { useStorage } from '@libs/storage/provider';
-import { CancelIcon, LoaderIcon, PlusIcon } from '@shared/icons';
+import { CancelIcon, PlusIcon } from '@shared/icons';
export function NewMessageModal() {
const navigate = useNavigate();
@@ -54,29 +54,23 @@ export function NewMessageModal() {
- {status === 'loading' ? (
-
-
-
- ) : (
- db.account?.follows?.map((follow) => (
-
-
-
-
-
+ {db.account?.follows?.map((follow) => (
+
+
+
+
- ))
- )}
+
+ ))}
diff --git a/src/app/settings/components/autoStart.tsx b/src/app/settings/components/autoStart.tsx
index 36877cc5..addaf7d7 100644
--- a/src/app/settings/components/autoStart.tsx
+++ b/src/app/settings/components/autoStart.tsx
@@ -1,56 +1,10 @@
-import { Switch } from '@headlessui/react';
-import { disable, enable, isEnabled } from '@tauri-apps/plugin-autostart';
-import { useEffect, useState } from 'react';
-import { twMerge } from 'tailwind-merge';
-
export function AutoStartSetting() {
- const [enabled, setEnabled] = useState(false);
-
- const toggle = async () => {
- if (!enabled) {
- await enable();
- // await updateSetting('auto_start', 1);
- console.log(`registered for autostart? ${await isEnabled()}`);
- } else {
- await disable();
- // await updateSetting('auto_start', 0);
- }
- setEnabled(!enabled);
- };
-
- useEffect(() => {
- async function getAppSetting() {
- const setting = '0';
- if (parseInt(setting) === 0) {
- setEnabled(false);
- } else {
- setEnabled(true);
- }
- }
- getAppSetting();
- }, []);
-
return (
Auto start
Auto start at login
-
-
-
);
}
diff --git a/src/app/space/components/modals/feed.tsx b/src/app/space/components/modals/feed.tsx
deleted file mode 100644
index 0905d6a1..00000000
--- a/src/app/space/components/modals/feed.tsx
+++ /dev/null
@@ -1,190 +0,0 @@
-import { Combobox } from '@headlessui/react';
-import * as Dialog from '@radix-ui/react-dialog';
-import { nip19 } from 'nostr-tools';
-import { useState } from 'react';
-import { useForm } from 'react-hook-form';
-
-import { User } from '@app/auth/components/user';
-
-import { useStorage } from '@libs/storage/provider';
-
-import { CancelIcon, CheckCircleIcon, CommandIcon, LoaderIcon } from '@shared/icons';
-
-import { WidgetKinds, useWidgets } from '@stores/widgets';
-
-export function FeedModal() {
- const setWidget = useWidgets((state) => state.setWidget);
-
- const [open, setOpen] = useState(false);
- const [loading, setLoading] = useState(false);
- const [selected, setSelected] = useState([]);
- const [query, setQuery] = useState('');
-
- const { db } = useStorage();
- const {
- register,
- handleSubmit,
- reset,
- formState: { isDirty, isValid },
- } = useForm();
-
- const onSubmit = (data: { kind: number; title: string; content: string }) => {
- setLoading(true);
-
- selected.forEach((item, index) => {
- if (item.substring(0, 4) === 'npub') {
- selected[index] = nip19.decode(item).data;
- }
- });
-
- // update state
- setWidget(db, {
- kind: WidgetKinds.feed,
- title: data.title,
- content: JSON.stringify(selected),
- });
-
- setLoading(false);
- // reset form
- reset();
- // close modal
- setOpen(false);
- };
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- Create feed block
-
-
-
-
-
-
- Specific newsfeed space for people you want to keep up to date
-
-
-
-
-
-
-
-
- );
-}
diff --git a/src/app/space/components/modals/hashtag.tsx b/src/app/space/components/modals/hashtag.tsx
deleted file mode 100644
index 1dced02c..00000000
--- a/src/app/space/components/modals/hashtag.tsx
+++ /dev/null
@@ -1,119 +0,0 @@
-import * as Dialog from '@radix-ui/react-dialog';
-import { useState } from 'react';
-import { useForm } from 'react-hook-form';
-
-import { useStorage } from '@libs/storage/provider';
-
-import { CancelIcon, CommandIcon, LoaderIcon } from '@shared/icons';
-
-import { WidgetKinds, useWidgets } from '@stores/widgets';
-
-export function HashtagModal() {
- const setWidget = useWidgets((state) => state.setWidget);
-
- const [loading, setLoading] = useState(false);
- const [open, setOpen] = useState(false);
-
- const { db } = useStorage();
- const {
- register,
- handleSubmit,
- reset,
- formState: { isDirty, isValid },
- } = useForm();
-
- const onSubmit = async (data: { hashtag: string }) => {
- setLoading(true);
-
- // update state
- setWidget(db, {
- kind: WidgetKinds.hashtag,
- title: data.hashtag,
- content: data.hashtag.replace('#', ''),
- });
-
- setLoading(false);
- // reset form
- reset();
- // close modal
- setOpen(false);
- };
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- Create hashtag block
-
-
-
-
-
-
- Pin the hashtag you want to keep follow up
-
-
-
-
-
-
-
-
- );
-}
diff --git a/src/app/users/components/modal.tsx b/src/app/users/components/modal.tsx
new file mode 100644
index 00000000..2cf76878
--- /dev/null
+++ b/src/app/users/components/modal.tsx
@@ -0,0 +1,295 @@
+import { NDKEvent, NDKUserProfile } from '@nostr-dev-kit/ndk';
+import * as Dialog from '@radix-ui/react-dialog';
+import { useQueryClient } from '@tanstack/react-query';
+import { useEffect, useState } from 'react';
+import { useForm } from 'react-hook-form';
+
+import { useStorage } from '@libs/storage/provider';
+
+import { AvatarUploader } from '@shared/avatarUploader';
+import { BannerUploader } from '@shared/bannerUploader';
+import { CancelIcon, CheckCircleIcon, LoaderIcon, UnverifiedIcon } from '@shared/icons';
+import { Image } from '@shared/image';
+
+import { useNostr } from '@utils/hooks/useNostr';
+
+export function EditProfileModal() {
+ const queryClient = useQueryClient();
+
+ const [isOpen, setIsOpen] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const [picture, setPicture] = useState('https://void.cat/d/5VKmKyuHyxrNMf9bWSVPih');
+ const [banner, setBanner] = useState(null);
+ const [nip05, setNIP05] = useState({ verified: false, text: '' });
+
+ const { db } = useStorage();
+ const { publish } = useNostr();
+ const {
+ register,
+ handleSubmit,
+ reset,
+ setError,
+ formState: { isValid, errors },
+ } = useForm({
+ defaultValues: async () => {
+ const res: NDKUserProfile = queryClient.getQueryData(['user', db.account.pubkey]);
+ if (res.image) {
+ setPicture(res.image);
+ }
+ if (res.banner) {
+ setBanner(res.banner);
+ }
+ if (res.nip05) {
+ setNIP05((prev) => ({ ...prev, text: res.nip05 }));
+ }
+ return res;
+ },
+ });
+
+ const verifyNIP05 = async (nip05: string) => {
+ const url = nip05.split('@');
+ const username = url[0];
+ const service = url[1];
+ const verifyURL = `https://${service}/.well-known/nostr.json?name=${username}`;
+
+ const res = await fetch(verifyURL, {
+ headers: {
+ 'Content-Type': 'application/json; charset=utf-8',
+ },
+ });
+
+ console.log(res);
+ return true;
+ };
+
+ const onSubmit = async (data: NDKUserProfile) => {
+ // start loading
+ setLoading(true);
+
+ let event: NDKEvent;
+
+ const content = {
+ ...data,
+ username: data.name,
+ display_name: data.name,
+ bio: data.about,
+ image: data.picture,
+ };
+
+ if (data.nip05) {
+ const nip05IsVerified = await verifyNIP05(data.nip05);
+ if (nip05IsVerified) {
+ event = await publish({
+ content: JSON.stringify({ ...content, nip05: data.nip05 }),
+ kind: 0,
+ tags: [],
+ });
+ } else {
+ setNIP05((prev) => ({ ...prev, verified: false }));
+ setError('nip05', {
+ type: 'manual',
+ message: "Can't verify your Lume ID / NIP-05, please check again",
+ });
+ }
+ } else {
+ event = await publish({
+ content: JSON.stringify(content),
+ kind: 0,
+ tags: [],
+ });
+ }
+
+ if (event.id) {
+ // invalid cache
+ queryClient.invalidateQueries(['user', db.account.pubkey]);
+ // reset form
+ reset();
+ // reset state
+ setLoading(false);
+ setIsOpen(false);
+ setPicture('https://void.cat/d/5VKmKyuHyxrNMf9bWSVPih');
+ setBanner(null);
+ } else {
+ setLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ if (!nip05.verified && /\S+@\S+\.\S+/.test(nip05.text)) {
+ verifyNIP05(nip05.text);
+ }
+ }, [nip05.text]);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ Edit profile
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/users/components/profile.tsx b/src/app/users/components/profile.tsx
index 2f132bc4..c7d6d468 100644
--- a/src/app/users/components/profile.tsx
+++ b/src/app/users/components/profile.tsx
@@ -1,11 +1,11 @@
import { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
+import { EditProfileModal } from '@app/users/components/modal';
import { UserStats } from '@app/users/components/stats';
import { useStorage } from '@libs/storage/provider';
-import { EditProfileModal } from '@shared/editProfileModal';
import { Image } from '@shared/image';
import { useNostr } from '@utils/hooks/useNostr';
diff --git a/src/shared/avatarUploader.tsx b/src/shared/avatarUploader.tsx
index e433f5c2..c2a6525d 100644
--- a/src/shared/avatarUploader.tsx
+++ b/src/shared/avatarUploader.tsx
@@ -7,9 +7,7 @@ import { useImageUploader } from '@utils/hooks/useUploader';
export function AvatarUploader({
setPicture,
}: {
- setPicture: Dispatch<
- SetStateAction<{ url: undefined | string; error?: undefined | string }>
- >;
+ setPicture: Dispatch>;
}) {
const upload = useImageUploader();
const [loading, setLoading] = useState(false);
diff --git a/src/shared/editProfileModal.tsx b/src/shared/editProfileModal.tsx
deleted file mode 100644
index e07156ab..00000000
--- a/src/shared/editProfileModal.tsx
+++ /dev/null
@@ -1,347 +0,0 @@
-import { Dialog, Transition } from '@headlessui/react';
-import { NDKEvent } from '@nostr-dev-kit/ndk';
-import { useQueryClient } from '@tanstack/react-query';
-import { Fragment, useEffect, useState } from 'react';
-import { useForm } from 'react-hook-form';
-
-import { useStorage } from '@libs/storage/provider';
-
-import { AvatarUploader } from '@shared/avatarUploader';
-import { BannerUploader } from '@shared/bannerUploader';
-import { CancelIcon, CheckCircleIcon, LoaderIcon, UnverifiedIcon } from '@shared/icons';
-import { Image } from '@shared/image';
-
-import { useNostr } from '@utils/hooks/useNostr';
-
-export function EditProfileModal() {
- const queryClient = useQueryClient();
-
- const [isOpen, setIsOpen] = useState(false);
- const [loading, setLoading] = useState(false);
- const [picture, setPicture] = useState('https://void.cat/d/5VKmKyuHyxrNMf9bWSVPih');
- const [banner, setBanner] = useState('');
- const [nip05, setNIP05] = useState({ verified: false, text: '' });
-
- const { db } = useStorage();
- const { publish } = useNostr();
- const {
- register,
- handleSubmit,
- reset,
- setError,
- formState: { isValid, errors },
- } = useForm({
- defaultValues: async () => {
- const res: any = queryClient.getQueryData(['user', db.account.pubkey]);
- if (res.image) {
- setPicture(res.image);
- }
- if (res.banner) {
- setBanner(res.banner);
- }
- if (res.nip05) {
- setNIP05((prev) => ({ ...prev, text: res.nip05 }));
- }
- return res;
- },
- });
-
- const closeModal = () => {
- setIsOpen(false);
- };
-
- const openModal = () => {
- setIsOpen(true);
- };
-
- const verifyNIP05 = async (data: string) => {
- if (data) {
- const url = data.split('@');
- const username = url[0];
- const service = url[1];
- const verifyURL = `https://${service}/.well-known/nostr.json?name=${username}`;
-
- const res: any = await fetch(verifyURL, {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json; charset=utf-8',
- },
- });
-
- if (!res.ok) return false;
- if (res.data.names[username] === db.account.pubkey) {
- setNIP05((prev) => ({ ...prev, verified: true }));
- return true;
- } else {
- return false;
- }
- }
- };
-
- const onSubmit = async (data: any) => {
- // start loading
- setLoading(true);
-
- let event: NDKEvent;
-
- const content = {
- ...data,
- username: data.name,
- display_name: data.name,
- bio: data.about,
- image: data.picture,
- };
-
- if (data.nip05) {
- const verify = await verifyNIP05(data.nip05);
- if (verify) {
- event = await publish({
- content: JSON.stringify({ ...content, nip05: data.nip05 }),
- kind: 0,
- tags: [],
- });
- } else {
- setNIP05((prev) => ({ ...prev, verified: false }));
- setError('nip05', {
- type: 'manual',
- message: "Can't verify your Lume ID / NIP-05, please check again",
- });
- }
- } else {
- event = await publish({
- content: JSON.stringify(content),
- kind: 0,
- tags: [],
- });
- }
-
- if (event.id) {
- setTimeout(() => {
- // invalid cache
- queryClient.invalidateQueries(['user', db.account.pubkey]);
- // reset form
- reset();
- // reset state
- setLoading(false);
- setIsOpen(false);
- setPicture('https://void.cat/d/5VKmKyuHyxrNMf9bWSVPih');
- setBanner(null);
- }, 1200);
- } else {
- setLoading(false);
- }
- };
-
- useEffect(() => {
- if (!nip05.verified && /\S+@\S+\.\S+/.test(nip05.text)) {
- verifyNIP05(nip05.text);
- }
- }, [nip05.text]);
-
- return (
- <>
-
-
-
-
- >
- );
-}