mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-29 16:30:55 +00:00
wip: basic support multi windows
This commit is contained in:
parent
a0d9a729dd
commit
296b11b7b8
@ -1,7 +1,7 @@
|
|||||||
import { useArk } from "@lume/ark";
|
import { useArk } from "@lume/ark";
|
||||||
import { ArrowRightCircleIcon, LoaderIcon, SearchIcon } from "@lume/icons";
|
import { ArrowRightCircleIcon, LoaderIcon, SearchIcon } from "@lume/icons";
|
||||||
import { Event, Kind } from "@lume/types";
|
import { Event, Kind } from "@lume/types";
|
||||||
import { EmptyFeed, TextNote } from "@lume/ui";
|
import { EmptyFeed, RepostNote, TextNote } from "@lume/ui";
|
||||||
import { FETCH_LIMIT } from "@lume/utils";
|
import { FETCH_LIMIT } from "@lume/utils";
|
||||||
import { useInfiniteQuery } from "@tanstack/react-query";
|
import { useInfiniteQuery } from "@tanstack/react-query";
|
||||||
import { createLazyFileRoute } from "@tanstack/react-router";
|
import { createLazyFileRoute } from "@tanstack/react-router";
|
||||||
@ -18,13 +18,13 @@ function Home() {
|
|||||||
queryKey: ["timeline"],
|
queryKey: ["timeline"],
|
||||||
initialPageParam: 0,
|
initialPageParam: 0,
|
||||||
queryFn: async ({ pageParam }: { pageParam: number }) => {
|
queryFn: async ({ pageParam }: { pageParam: number }) => {
|
||||||
const events = await ark.get_text_events(FETCH_LIMIT, pageParam);
|
const events = await ark.get_text_events(FETCH_LIMIT, pageParam, true);
|
||||||
return events;
|
return events;
|
||||||
},
|
},
|
||||||
getNextPageParam: (lastPage) => {
|
getNextPageParam: (lastPage) => {
|
||||||
const lastEvent = lastPage.at(-1);
|
const lastEvent = lastPage.at(-1);
|
||||||
if (!lastEvent) return;
|
if (!lastEvent) return;
|
||||||
return lastEvent.created_at;
|
return lastEvent.created_at - 1;
|
||||||
},
|
},
|
||||||
select: (data) => data?.pages.flatMap((page) => page),
|
select: (data) => data?.pages.flatMap((page) => page),
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
@ -32,8 +32,8 @@ function Home() {
|
|||||||
|
|
||||||
const renderItem = (event: Event) => {
|
const renderItem = (event: Event) => {
|
||||||
switch (event.kind) {
|
switch (event.kind) {
|
||||||
case Kind.Text:
|
case Kind.Repost:
|
||||||
return <TextNote key={event.id} event={event} />;
|
return <RepostNote key={event.id} event={event} />;
|
||||||
default:
|
default:
|
||||||
return <TextNote key={event.id} event={event} />;
|
return <TextNote key={event.id} event={event} />;
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ function Home() {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Virtualizer overscan={2}>
|
<Virtualizer overscan={3}>
|
||||||
{data.map((item) => renderItem(item))}
|
{data.map((item) => renderItem(item))}
|
||||||
</Virtualizer>
|
</Virtualizer>
|
||||||
)}
|
)}
|
||||||
|
11
apps/desktop2/src/routes/events/$eventId.lazy.tsx
Normal file
11
apps/desktop2/src/routes/events/$eventId.lazy.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { createLazyFileRoute } from "@tanstack/react-router";
|
||||||
|
|
||||||
|
export const Route = createLazyFileRoute("/events/$eventId")({
|
||||||
|
component: Event,
|
||||||
|
});
|
||||||
|
|
||||||
|
function Event() {
|
||||||
|
const { eventId } = Route.useParams();
|
||||||
|
|
||||||
|
return <div>{eventId}</div>;
|
||||||
|
}
|
11
apps/desktop2/src/routes/users/$pubkey.lazy.tsx
Normal file
11
apps/desktop2/src/routes/users/$pubkey.lazy.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { createLazyFileRoute } from "@tanstack/react-router";
|
||||||
|
|
||||||
|
export const Route = createLazyFileRoute("/users/$pubkey")({
|
||||||
|
component: User,
|
||||||
|
});
|
||||||
|
|
||||||
|
function User() {
|
||||||
|
const { pubkey } = Route.useParams();
|
||||||
|
|
||||||
|
return <div>{pubkey}</div>;
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import type { CurrentAccount, Event, Keys, Metadata } from "@lume/types";
|
import type { CurrentAccount, Event, Keys, Metadata } from "@lume/types";
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
|
import { WebviewWindow } from "@tauri-apps/api/webview";
|
||||||
|
|
||||||
export class Ark {
|
export class Ark {
|
||||||
public account: CurrentAccount;
|
public account: CurrentAccount;
|
||||||
@ -59,21 +60,56 @@ export class Ark {
|
|||||||
|
|
||||||
public async get_event(id: string) {
|
public async get_event(id: string) {
|
||||||
try {
|
try {
|
||||||
const cmd: string = await invoke("get_event", { id });
|
const eventId: string = id
|
||||||
|
.replace("nostr:", "")
|
||||||
|
.split("'")[0]
|
||||||
|
.split(".")[0];
|
||||||
|
const cmd: string = await invoke("get_event", { id: eventId });
|
||||||
const event = JSON.parse(cmd) as Event;
|
const event = JSON.parse(cmd) as Event;
|
||||||
|
|
||||||
return event;
|
return event;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async get_text_events(limit: number, asOf?: number) {
|
public async get_text_events(limit: number, asOf?: number, dedup?: boolean) {
|
||||||
try {
|
try {
|
||||||
let until: string = undefined;
|
let until: string = undefined;
|
||||||
if (asOf && asOf > 0) until = asOf.toString();
|
if (asOf && asOf > 0) until = asOf.toString();
|
||||||
|
|
||||||
const cmd: Event[] = await invoke("get_text_events", { limit, until });
|
const seenIds = new Set<string>();
|
||||||
return cmd;
|
const dedupQueue = new Set<string>();
|
||||||
|
|
||||||
|
const nostrEvents: Event[] = await invoke("get_text_events", {
|
||||||
|
limit,
|
||||||
|
until,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (dedup) {
|
||||||
|
for (const event of nostrEvents) {
|
||||||
|
const tags = event.tags
|
||||||
|
.filter((el) => el[0] === "e")
|
||||||
|
?.map((item) => item[1]);
|
||||||
|
|
||||||
|
if (tags.length) {
|
||||||
|
for (const tag of tags) {
|
||||||
|
if (seenIds.has(tag)) {
|
||||||
|
dedupQueue.add(event.id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
seenIds.add(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nostrEvents
|
||||||
|
.filter((event) => !dedupQueue.has(event.id))
|
||||||
|
.sort((a, b) => b.created_at - a.created_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nostrEvents.sort((a, b) => b.created_at - a.created_at);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -170,9 +206,16 @@ export class Ark {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async get_profile(id: string) {
|
public async get_profile(pubkey: string) {
|
||||||
try {
|
try {
|
||||||
|
const id = pubkey
|
||||||
|
.replace("nostr:", "")
|
||||||
|
.split("'")[0]
|
||||||
|
.split(".")[0]
|
||||||
|
.split(",")[0]
|
||||||
|
.split("?")[0];
|
||||||
const cmd: Metadata = await invoke("get_profile", { id });
|
const cmd: Metadata = await invoke("get_profile", { id });
|
||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
@ -202,4 +245,26 @@ export class Ark {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public open_thread(id: string) {
|
||||||
|
return new WebviewWindow(`event-${id}`, {
|
||||||
|
title: "Thread",
|
||||||
|
url: `/events/${id}`,
|
||||||
|
width: 600,
|
||||||
|
height: 800,
|
||||||
|
hiddenTitle: true,
|
||||||
|
titleBarStyle: "overlay",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public open_profile(pubkey: string) {
|
||||||
|
return new WebviewWindow(`user-${pubkey}`, {
|
||||||
|
title: "Profile",
|
||||||
|
url: `/users/${pubkey}`,
|
||||||
|
width: 600,
|
||||||
|
height: 800,
|
||||||
|
hiddenTitle: true,
|
||||||
|
titleBarStyle: "overlay",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,12 @@ import { ReplyIcon } from "@lume/icons";
|
|||||||
import * as Tooltip from "@radix-ui/react-tooltip";
|
import * as Tooltip from "@radix-ui/react-tooltip";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNoteContext } from "../provider";
|
import { useNoteContext } from "../provider";
|
||||||
|
import { useArk } from "@lume/ark";
|
||||||
|
|
||||||
export function NoteReply() {
|
export function NoteReply() {
|
||||||
|
const ark = useArk();
|
||||||
const event = useNoteContext();
|
const event = useNoteContext();
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -13,6 +16,7 @@ export function NoteReply() {
|
|||||||
<Tooltip.Trigger asChild>
|
<Tooltip.Trigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
onClick={() => ark.open_thread(event.id)}
|
||||||
className="group inline-flex h-7 w-7 items-center justify-center text-neutral-800 dark:text-neutral-200"
|
className="group inline-flex h-7 w-7 items-center justify-center text-neutral-800 dark:text-neutral-200"
|
||||||
>
|
>
|
||||||
<ReplyIcon className="size-5 group-hover:text-blue-500" />
|
<ReplyIcon className="size-5 group-hover:text-blue-500" />
|
||||||
|
@ -110,7 +110,7 @@ export function NoteChild({
|
|||||||
</div>
|
</div>
|
||||||
<User.Provider pubkey={data.pubkey}>
|
<User.Provider pubkey={data.pubkey}>
|
||||||
<User.Root>
|
<User.Root>
|
||||||
<User.Avatar className="size-10 shrink-0 rounded-lg object-cover" />
|
<User.Avatar className="size-10 shrink-0 rounded-full object-cover" />
|
||||||
<div className="absolute left-2 top-2 inline-flex items-center gap-1.5 font-semibold leading-tight">
|
<div className="absolute left-2 top-2 inline-flex items-center gap-1.5 font-semibold leading-tight">
|
||||||
<User.Name className="max-w-[10rem] truncate" />
|
<User.Name className="max-w-[10rem] truncate" />
|
||||||
<div className="font-normal text-neutral-700 dark:text-neutral-300">
|
<div className="font-normal text-neutral-700 dark:text-neutral-300">
|
||||||
|
@ -32,10 +32,7 @@ export function NoteMenu() {
|
|||||||
return (
|
return (
|
||||||
<DropdownMenu.Root>
|
<DropdownMenu.Root>
|
||||||
<DropdownMenu.Trigger asChild>
|
<DropdownMenu.Trigger asChild>
|
||||||
<button
|
<button type="button">
|
||||||
type="button"
|
|
||||||
className="inline-flex size-6 items-center justify-center"
|
|
||||||
>
|
|
||||||
<HorizontalDotsIcon className="size-4 hover:text-blue-500 dark:text-neutral-200" />
|
<HorizontalDotsIcon className="size-4 hover:text-blue-500 dark:text-neutral-200" />
|
||||||
</button>
|
</button>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
|
@ -73,17 +73,17 @@ export function RepostNote({
|
|||||||
return (
|
return (
|
||||||
<Note.Root
|
<Note.Root
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex flex-col rounded-xl bg-neutral-50 dark:bg-neutral-950",
|
"mb-3 flex flex-col gap-2 border-b border-neutral-100 pb-3 dark:border-neutral-900",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<User.Provider pubkey={event.pubkey}>
|
<User.Provider pubkey={event.pubkey}>
|
||||||
<User.Root className="flex h-14 gap-2 px-3">
|
<User.Root className="flex gap-3">
|
||||||
<div className="inline-flex w-10 shrink-0 items-center justify-center">
|
<div className="inline-flex w-10 shrink-0 items-center justify-center">
|
||||||
<RepostIcon className="h-5 w-5 text-blue-500" />
|
<RepostIcon className="h-5 w-5 text-blue-500" />
|
||||||
</div>
|
</div>
|
||||||
<div className="inline-flex items-center gap-2">
|
<div className="inline-flex items-center gap-2">
|
||||||
<User.Avatar className="size-6 shrink-0 rounded object-cover" />
|
<User.Avatar className="size-6 shrink-0 rounded-full object-cover" />
|
||||||
<div className="inline-flex items-baseline gap-1">
|
<div className="inline-flex items-baseline gap-1">
|
||||||
<User.Name className="font-medium text-neutral-900 dark:text-neutral-100" />
|
<User.Name className="font-medium text-neutral-900 dark:text-neutral-100" />
|
||||||
<span className="text-blue-500">{t("note.reposted")}</span>
|
<span className="text-blue-500">{t("note.reposted")}</span>
|
||||||
@ -92,18 +92,23 @@ export function RepostNote({
|
|||||||
</User.Root>
|
</User.Root>
|
||||||
</User.Provider>
|
</User.Provider>
|
||||||
<Note.Provider event={repostEvent}>
|
<Note.Provider event={repostEvent}>
|
||||||
<div className="relative flex flex-col gap-2 px-3">
|
<div className="flex flex-col gap-2">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-start justify-between">
|
||||||
<Note.User className="flex-1 pr-2" />
|
<Note.User className="flex-1 pr-2" />
|
||||||
<Note.Menu />
|
<Note.Menu />
|
||||||
</div>
|
</div>
|
||||||
<Note.Content />
|
<div className="flex gap-3">
|
||||||
<div className="flex h-14 items-center justify-between">
|
<div className="size-10 shrink-0" />
|
||||||
<Note.Pin />
|
<div className="min-w-0 flex-1">
|
||||||
<div className="inline-flex items-center gap-4">
|
<Note.Content />
|
||||||
<Note.Reply />
|
<div className="mt-5 flex items-center justify-between">
|
||||||
<Note.Repost />
|
<Note.Reaction />
|
||||||
<Note.Zap />
|
<div className="inline-flex items-center gap-4">
|
||||||
|
<Note.Reply />
|
||||||
|
<Note.Repost />
|
||||||
|
<Note.Zap />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -24,8 +24,8 @@ export function TextNote({
|
|||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<div className="size-10 shrink-0" />
|
<div className="size-10 shrink-0" />
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<Note.Content className="mb-2" />
|
|
||||||
<Note.Thread className="mb-2" />
|
<Note.Thread className="mb-2" />
|
||||||
|
<Note.Content />
|
||||||
<div className="mt-5 flex items-center justify-between">
|
<div className="mt-5 flex items-center justify-between">
|
||||||
<Note.Reaction />
|
<Note.Reaction />
|
||||||
<div className="inline-flex items-center gap-4">
|
<div className="inline-flex items-center gap-4">
|
||||||
|
@ -20,12 +20,12 @@ export function NoteThread({ className }: { className?: string }) {
|
|||||||
return (
|
return (
|
||||||
<div className={cn("w-full", className)}>
|
<div className={cn("w-full", className)}>
|
||||||
<div className="flex h-min w-full flex-col gap-3 rounded-lg bg-neutral-100 p-3 dark:bg-neutral-900">
|
<div className="flex h-min w-full flex-col gap-3 rounded-lg bg-neutral-100 p-3 dark:bg-neutral-900">
|
||||||
{thread.replyEventId ? (
|
|
||||||
<Note.Child eventId={thread.replyEventId} />
|
|
||||||
) : null}
|
|
||||||
{thread.rootEventId ? (
|
{thread.rootEventId ? (
|
||||||
<Note.Child eventId={thread.rootEventId} isRoot />
|
<Note.Child eventId={thread.rootEventId} isRoot />
|
||||||
) : null}
|
) : null}
|
||||||
|
{thread.replyEventId ? (
|
||||||
|
<Note.Child eventId={thread.replyEventId} />
|
||||||
|
) : null}
|
||||||
<div className="inline-flex items-center justify-between">
|
<div className="inline-flex items-center justify-between">
|
||||||
<a
|
<a
|
||||||
href={`/events/${thread?.rootEventId || thread?.replyEventId}`}
|
href={`/events/${thread?.rootEventId || thread?.replyEventId}`}
|
||||||
|
@ -2,22 +2,22 @@ import { cn } from "@lume/utils";
|
|||||||
import { useUserContext } from "./provider";
|
import { useUserContext } from "./provider";
|
||||||
|
|
||||||
export function UserName({ className }: { className?: string }) {
|
export function UserName({ className }: { className?: string }) {
|
||||||
const user = useUserContext();
|
const user = useUserContext();
|
||||||
|
|
||||||
if (!user.profile) {
|
if (!user.profile) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-4 w-20 self-center bg-black/20 dark:bg-white/20 rounded animate-pulse",
|
"mb-1 h-3 w-20 animate-pulse self-center rounded bg-black/20 dark:bg-white/20",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn("max-w-[12rem] truncate", className)}>
|
<div className={cn("max-w-[12rem] truncate", className)}>
|
||||||
{user.profile.display_name || user.profile.name || "Anon"}
|
{user.profile.display_name || user.profile.name || "Anon"}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ export function UserNip05({ className }: { className?: string }) {
|
|||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
if (!user.profile?.nip05) return false;
|
if (!user.profile?.nip05) return false;
|
||||||
const verify = await ark.verify_nip05(user.pubkey, user.profile?.nip05);
|
const verify = await ark.verify_nip05(user.pubkey, user.profile?.nip05);
|
||||||
console.log(verify);
|
|
||||||
return verify;
|
return verify;
|
||||||
},
|
},
|
||||||
enabled: !!user.profile,
|
enabled: !!user.profile,
|
||||||
@ -23,7 +22,7 @@ export function UserNip05({ className }: { className?: string }) {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-4 w-20 animate-pulse rounded bg-black/20 dark:bg-white/20",
|
"h-3 w-20 animate-pulse rounded bg-black/20 dark:bg-white/20",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
@ -2,10 +2,13 @@ import { cn, formatCreatedAt } from "@lume/utils";
|
|||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
|
||||||
export function UserTime({
|
export function UserTime({
|
||||||
time,
|
time,
|
||||||
className,
|
className,
|
||||||
}: { time: number; className?: string }) {
|
}: {
|
||||||
const createdAt = useMemo(() => formatCreatedAt(time), [time]);
|
time: number;
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
const createdAt = useMemo(() => formatCreatedAt(time), [time]);
|
||||||
|
|
||||||
return <div className={cn("", className)}>{createdAt}</div>;
|
return <div className={cn("leading-tight", className)}>{createdAt}</div>;
|
||||||
}
|
}
|
||||||
|
@ -1,46 +1,49 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../gen/schemas/desktop-schema.json",
|
"$schema": "../gen/schemas/desktop-schema.json",
|
||||||
"identifier": "desktop-capability",
|
"identifier": "desktop-capability",
|
||||||
"description": "Capability for the desktop",
|
"description": "Capability for the desktop",
|
||||||
"platforms": ["linux", "macOS", "windows"],
|
"platforms": ["linux", "macOS", "windows"],
|
||||||
"windows": ["main", "settings", "event-*", "user-*", "column-*"],
|
"windows": ["main", "settings", "event-*", "user-*", "column-*"],
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"path:default",
|
"path:default",
|
||||||
"event:default",
|
"event:default",
|
||||||
"window:default",
|
"window:default",
|
||||||
"app:default",
|
"app:default",
|
||||||
"resources:default",
|
"resources:default",
|
||||||
"menu:default",
|
"menu:default",
|
||||||
"tray:default",
|
"tray:default",
|
||||||
"theme:allow-set-theme",
|
"theme:allow-set-theme",
|
||||||
"theme:allow-get-theme",
|
"theme:allow-get-theme",
|
||||||
"notification:allow-is-permission-granted",
|
"notification:allow-is-permission-granted",
|
||||||
"notification:allow-request-permission",
|
"notification:allow-request-permission",
|
||||||
"notification:default",
|
"notification:default",
|
||||||
"os:allow-locale",
|
"os:allow-locale",
|
||||||
"os:allow-platform",
|
"os:allow-platform",
|
||||||
"updater:allow-check",
|
"updater:allow-check",
|
||||||
"updater:default",
|
"updater:default",
|
||||||
"window:allow-start-dragging",
|
"window:allow-start-dragging",
|
||||||
"store:allow-get",
|
"store:allow-get",
|
||||||
{
|
"clipboard-manager:allow-write",
|
||||||
"identifier": "http:default",
|
"clipboard-manager:allow-read",
|
||||||
"allow": [
|
"webview:allow-create-webview-window",
|
||||||
{
|
{
|
||||||
"url": "http://**/"
|
"identifier": "http:default",
|
||||||
},
|
"allow": [
|
||||||
{
|
{
|
||||||
"url": "https://**/"
|
"url": "http://**/"
|
||||||
}
|
},
|
||||||
]
|
{
|
||||||
},
|
"url": "https://**/"
|
||||||
{
|
}
|
||||||
"identifier": "fs:allow-read-text-file",
|
]
|
||||||
"allow": [
|
},
|
||||||
{
|
{
|
||||||
"path": "$RESOURCE/locales/*"
|
"identifier": "fs:allow-read-text-file",
|
||||||
}
|
"allow": [
|
||||||
]
|
{
|
||||||
}
|
"path": "$RESOURCE/locales/*"
|
||||||
]
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
{"desktop-capability":{"identifier":"desktop-capability","description":"Capability for the desktop","context":"local","windows":["main","settings","event-*","user-*","column-*"],"permissions":["path:default","event:default","window:default","app:default","resources:default","menu:default","tray:default","theme:allow-set-theme","theme:allow-get-theme","notification:allow-is-permission-granted","notification:allow-request-permission","notification:default","os:allow-locale","os:allow-platform","updater:allow-check","updater:default","window:allow-start-dragging","store:allow-get",{"identifier":"http:default","allow":[{"url":"http://**/"},{"url":"https://**/"}]},{"identifier":"fs:allow-read-text-file","allow":[{"path":"$RESOURCE/locales/*"}]}],"platforms":["linux","macOS","windows"]}}
|
{"desktop-capability":{"identifier":"desktop-capability","description":"Capability for the desktop","context":"local","windows":["main","settings","event-*","user-*","column-*"],"permissions":["path:default","event:default","window:default","app:default","resources:default","menu:default","tray:default","theme:allow-set-theme","theme:allow-get-theme","notification:allow-is-permission-granted","notification:allow-request-permission","notification:default","os:allow-locale","os:allow-platform","updater:allow-check","updater:default","window:allow-start-dragging","store:allow-get","clipboard-manager:allow-write","clipboard-manager:allow-read","webview:allow-create-webview-window",{"identifier":"http:default","allow":[{"url":"http://**/"},{"url":"https://**/"}]},{"identifier":"fs:allow-read-text-file","allow":[{"path":"$RESOURCE/locales/*"}]}],"platforms":["linux","macOS","windows"]}}
|
@ -6,15 +6,14 @@ use tauri::State;
|
|||||||
#[tauri::command(async)]
|
#[tauri::command(async)]
|
||||||
pub async fn get_event(id: &str, nostr: State<'_, Nostr>) -> Result<String, String> {
|
pub async fn get_event(id: &str, nostr: State<'_, Nostr>) -> Result<String, String> {
|
||||||
let client = &nostr.client;
|
let client = &nostr.client;
|
||||||
let event_id;
|
let event_id: EventId = match Nip19::from_bech32(id) {
|
||||||
|
Ok(val) => match val {
|
||||||
if id.starts_with("note") {
|
Nip19::EventId(id) => id,
|
||||||
event_id = EventId::from_bech32(id).unwrap();
|
Nip19::Event(event) => event.event_id,
|
||||||
} else if id.starts_with("nevent") {
|
_ => panic!("not nip19"),
|
||||||
event_id = Nip19Event::from_bech32(id).unwrap().event_id;
|
},
|
||||||
} else {
|
Err(_) => EventId::from_hex(id).unwrap(),
|
||||||
event_id = EventId::from_hex(id).unwrap();
|
};
|
||||||
}
|
|
||||||
|
|
||||||
let filter = Filter::new().id(event_id);
|
let filter = Filter::new().id(event_id);
|
||||||
let events = client
|
let events = client
|
||||||
|
@ -6,15 +6,14 @@ use tauri::State;
|
|||||||
#[tauri::command(async)]
|
#[tauri::command(async)]
|
||||||
pub async fn get_profile(id: &str, nostr: State<'_, Nostr>) -> Result<Metadata, ()> {
|
pub async fn get_profile(id: &str, nostr: State<'_, Nostr>) -> Result<Metadata, ()> {
|
||||||
let client = &nostr.client;
|
let client = &nostr.client;
|
||||||
let public_key;
|
let public_key: XOnlyPublicKey = match Nip19::from_bech32(id) {
|
||||||
|
Ok(val) => match val {
|
||||||
if id.starts_with("nprofile1") {
|
Nip19::Pubkey(pubkey) => pubkey,
|
||||||
public_key = XOnlyPublicKey::from_bech32(id).unwrap();
|
Nip19::Profile(profile) => profile.public_key,
|
||||||
} else if id.starts_with("npub1") {
|
_ => panic!("not nip19"),
|
||||||
public_key = XOnlyPublicKey::from_bech32(id).unwrap();
|
},
|
||||||
} else {
|
Err(_) => XOnlyPublicKey::from_str(id).unwrap(),
|
||||||
public_key = XOnlyPublicKey::from_str(id).unwrap();
|
};
|
||||||
}
|
|
||||||
|
|
||||||
let filter = Filter::new()
|
let filter = Filter::new()
|
||||||
.author(public_key)
|
.author(public_key)
|
||||||
|
Loading…
Reference in New Issue
Block a user