diff --git a/apps/desktop/src/routes/auth/create.tsx b/apps/desktop/src/routes/auth/create.tsx
index f51616a7..599a8531 100644
--- a/apps/desktop/src/routes/auth/create.tsx
+++ b/apps/desktop/src/routes/auth/create.tsx
@@ -40,8 +40,8 @@ const Item = ({ event }: { event: NDKEvent }) => {
export function CreateAccountScreen() {
const ark = useArk();
const storage = useStorage();
- const navigate = useNavigate();
const services = useLoaderData() as NDKEvent[];
+ const navigate = useNavigate();
const setOnboarding = useSetAtom(onboardingAtom);
const [serviceId, setServiceId] = useState(services?.[0]?.id);
@@ -162,7 +162,7 @@ export function CreateAccountScreen() {
ark.updateNostrSigner({ signer: finalSigner });
// remove default nsecbunker profile and contact list
- await ark.createEvent({ kind: NDKKind.Metadata, content: "", tags: [] });
+ // await ark.createEvent({ kind: NDKKind.Metadata, content: "", tags: [] });
await ark.createEvent({ kind: NDKKind.Contacts, content: "", tags: [] });
setOnboarding(true);
diff --git a/packages/ark/src/ark.ts b/packages/ark/src/ark.ts
index b05a9466..7c04d90c 100644
--- a/packages/ark/src/ark.ts
+++ b/packages/ark/src/ark.ts
@@ -276,7 +276,7 @@ export class Ark {
if (content.includes("nostr:note1") || content.includes("nostr:nevent1"))
return null;
- const events = tags.filter((el) => el[0] === "e");
+ const events = tags.filter((el) => el[0] === "e" && el[3] !== "mention");
if (!events.length) return null;
@@ -325,7 +325,9 @@ export class Ark {
if (events.length > 0) {
const replies = new Set();
for (const event of events) {
- const tags = event.tags.filter((el) => el[0] === "e" && el[1] !== id);
+ const tags = event.tags.filter(
+ (el) => el[0] === "e" && el[1] !== id && el[3] !== "mention",
+ );
if (tags.length > 0) {
for (const tag of tags) {
const rootIndex = events.findIndex((el) => el.id === tag[1]);
diff --git a/packages/ark/src/components/note/mentions/note.tsx b/packages/ark/src/components/note/mentions/note.tsx
index c9256806..536e8974 100644
--- a/packages/ark/src/components/note/mentions/note.tsx
+++ b/packages/ark/src/components/note/mentions/note.tsx
@@ -1,11 +1,13 @@
-import { PinIcon, RefreshIcon } from "@lume/icons";
-import { COL_TYPES } from "@lume/utils";
-import { memo } from "react";
+import { PinIcon } from "@lume/icons";
+import { COL_TYPES, NOSTR_MENTIONS } from "@lume/utils";
+import { ReactNode, memo, useMemo } from "react";
import { Link } from "react-router-dom";
-import { Note } from "../";
+import reactStringReplace from "react-string-replace";
import { useEvent } from "../../../hooks/useEvent";
import { useColumnContext } from "../../column/provider";
import { User } from "../../user";
+import { Hashtag } from "./hashtag";
+import { MentionUser } from "./user";
export const MentionNote = memo(function MentionNote({
eventId,
@@ -14,6 +16,71 @@ export const MentionNote = memo(function MentionNote({
const { addColumn } = useColumnContext();
const { isLoading, isError, data } = useEvent(eventId);
+ const richContent = useMemo(() => {
+ if (!data) return "";
+
+ let parsedContent: string | ReactNode[] = data.content.replace(
+ /\n+/g,
+ "\n",
+ );
+
+ const text = parsedContent as string;
+ const words = text.split(/( |\n)/);
+
+ const hashtags = words.filter((word) => word.startsWith("#"));
+ const mentions = words.filter((word) =>
+ NOSTR_MENTIONS.some((el) => word.startsWith(el)),
+ );
+
+ try {
+ if (hashtags.length) {
+ for (const hashtag of hashtags) {
+ parsedContent = reactStringReplace(
+ parsedContent,
+ hashtag,
+ (match, i) => {
+ return ;
+ },
+ );
+ }
+ }
+
+ if (mentions.length) {
+ for (const mention of mentions) {
+ parsedContent = reactStringReplace(
+ parsedContent,
+ mention,
+ (match, i) => ,
+ );
+ }
+ }
+
+ parsedContent = reactStringReplace(
+ parsedContent,
+ /(https?:\/\/\S+)/g,
+ (match, i) => {
+ const url = new URL(match);
+ return (
+
+ {url.toString()}
+
+ );
+ },
+ );
+
+ return parsedContent;
+ } catch (e) {
+ console.log(e);
+ return parsedContent;
+ }
+ }, [data]);
+
if (isLoading) {
return (
- Failed to fetch event
+ Failed to fetch event.
);
}
return (
-
-
+
+
@@ -52,7 +119,9 @@ export const MentionNote = memo(function MentionNote({
-
+
+ {richContent}
+
{openable ? (
) : (
-
+
)}
-
-
+
+
);
});
diff --git a/packages/ark/src/components/note/primitives/reply.tsx b/packages/ark/src/components/note/primitives/reply.tsx
index 0fc5306e..0ff655db 100644
--- a/packages/ark/src/components/note/primitives/reply.tsx
+++ b/packages/ark/src/components/note/primitives/reply.tsx
@@ -38,6 +38,7 @@ export function Reply({
)}
+
diff --git a/packages/ark/src/components/user/about.tsx b/packages/ark/src/components/user/about.tsx
index cdd02cfa..401911bc 100644
--- a/packages/ark/src/components/user/about.tsx
+++ b/packages/ark/src/components/user/about.tsx
@@ -6,7 +6,7 @@ export function UserAbout({ className }: { className?: string }) {
if (!user) {
return (
- <>
+
);
}
diff --git a/packages/ark/src/components/user/cover.tsx b/packages/ark/src/components/user/cover.tsx
index 68101d52..79870241 100644
--- a/packages/ark/src/components/user/cover.tsx
+++ b/packages/ark/src/components/user/cover.tsx
@@ -15,9 +15,17 @@ export function UserCover({ className }: { className?: string }) {
);
}
+ if (user && !user.banner) {
+ return (
+
+ );
+ }
+
return (
) => {
);
activitySub.addListener("event", async (event: NDKEvent) => {
+ if (event.pubkey === storage.currentUser.pubkey) return;
+
setUnreadActivity((state) => state + 1);
const profile = await ark.getUserProfile(event.pubkey);
+
switch (event.kind) {
case NDKKind.Text:
return await sendNativeNotification(
diff --git a/packages/ui/src/editor/replyForm.tsx b/packages/ui/src/editor/replyForm.tsx
index 0878d3fc..2340cf22 100644
--- a/packages/ui/src/editor/replyForm.tsx
+++ b/packages/ui/src/editor/replyForm.tsx
@@ -2,10 +2,9 @@ import { MentionNote, User, useArk } from "@lume/ark";
import { LoaderIcon, TrashIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { NDKCacheUserProfile } from "@lume/types";
-import { cn, editorValueAtom } from "@lume/utils";
+import { cn } from "@lume/utils";
import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";
import { Portal } from "@radix-ui/react-dropdown-menu";
-import { useAtom } from "jotai";
import { useEffect, useRef, useState } from "react";
import {
Descendant,
@@ -193,7 +192,12 @@ export function ReplyForm({
const storage = useStorage();
const ref = useRef();
- const [editorValue, setEditorValue] = useAtom(editorValueAtom);
+ const [editorValue, setEditorValue] = useState([
+ {
+ type: "paragraph",
+ children: [{ text: "" }],
+ },
+ ]);
const [contacts, setContacts] = useState([]);
const [target, setTarget] = useState();
const [index, setIndex] = useState(0);
diff --git a/packages/ui/src/onboarding/follow.tsx b/packages/ui/src/onboarding/follow.tsx
index 79771967..3bc2df5a 100644
--- a/packages/ui/src/onboarding/follow.tsx
+++ b/packages/ui/src/onboarding/follow.tsx
@@ -218,7 +218,6 @@ export function OnboardingFollowScreen() {
>
)}
- UU
))
diff --git a/packages/ui/src/onboarding/profileSettings.tsx b/packages/ui/src/onboarding/profileSettings.tsx
index 263e3bb6..c3467703 100644
--- a/packages/ui/src/onboarding/profileSettings.tsx
+++ b/packages/ui/src/onboarding/profileSettings.tsx
@@ -23,7 +23,7 @@ export function OnboardingProfileSettingsScreen() {
const { register, handleSubmit } = useForm();
const svgURI = `data:image/svg+xml;utf8,${encodeURIComponent(
- minidenticon("lume new account", 90, 50),
+ minidenticon(ark.account.pubkey, 90, 50),
)}`;
const onSubmit = async (data: { name: string; about: string }) => {
@@ -39,7 +39,7 @@ export function OnboardingProfileSettingsScreen() {
const profile: NDKUserProfile = {
...data,
- lud16: oldProfile?.lud16 || "",
+ lud16: "", // temporary remove lud16
nip05: oldProfile?.nip05 || "",
display_name: data.name,
bio: data.about,
@@ -56,9 +56,10 @@ export function OnboardingProfileSettingsScreen() {
if (publish) {
// invalid cache
await storage.clearProfileCache(ark.account.pubkey);
- await queryClient.setQueryData(["user", ark.account.pubkey], () => {
- return profile;
- });
+ await queryClient.setQueryData(
+ ["user", ark.account.pubkey],
+ () => profile,
+ );
setLoading(false);
navigate("/follow");