mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-29 16:30:55 +00:00
chore: follow up
This commit is contained in:
parent
7fabf949c6
commit
5d59040224
@ -1,12 +1,8 @@
|
||||
import { useArk } from "@lume/ark";
|
||||
import { Account } from "@lume/types";
|
||||
import { User } from "@lume/ui";
|
||||
import { useNavigate, useParams, useSearch } from "@tanstack/react-router";
|
||||
import { useNavigate, useParams } from "@tanstack/react-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import * as Popover from "@radix-ui/react-popover";
|
||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
||||
import { BackupDialog } from "./backup";
|
||||
import { LoginDialog } from "./login";
|
||||
|
||||
export function Accounts() {
|
||||
const ark = useArk();
|
||||
@ -60,91 +56,11 @@ function Inactive({ pubkey }: { pubkey: string }) {
|
||||
}
|
||||
|
||||
function Active({ pubkey }: { pubkey: string }) {
|
||||
const ark = useArk();
|
||||
const navigate = useNavigate();
|
||||
|
||||
// @ts-ignore, magic !!!
|
||||
const { guest } = useSearch({ strict: false });
|
||||
// @ts-ignore, magic !!!
|
||||
const { account } = useParams({ strict: false });
|
||||
|
||||
if (guest) {
|
||||
return (
|
||||
<Popover.Root open={true}>
|
||||
<Popover.Trigger asChild>
|
||||
<button type="button">
|
||||
<User.Provider pubkey={pubkey}>
|
||||
<User.Root className="rounded-full ring-1 ring-teal-500 ring-offset-2 ring-offset-neutral-200 dark:ring-offset-neutral-950">
|
||||
<User.Avatar className="aspect-square h-auto w-7 rounded-full object-cover" />
|
||||
</User.Root>
|
||||
</User.Provider>
|
||||
</button>
|
||||
</Popover.Trigger>
|
||||
<Popover.Portal>
|
||||
<Popover.Content
|
||||
className="flex w-[280px] flex-col gap-4 rounded-xl bg-black p-5 text-neutral-100 focus:outline-none dark:bg-white dark:text-neutral-900 dark:shadow-none"
|
||||
sideOffset={10}
|
||||
side="bottom"
|
||||
>
|
||||
<div>
|
||||
<h1 className="mb-1 font-semibold">
|
||||
You're using random account
|
||||
</h1>
|
||||
<p className="text-sm text-neutral-500 dark:text-neutral-600">
|
||||
You can continue by claim and backup this account, or you can
|
||||
import your own account.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<BackupDialog />
|
||||
<LoginDialog />
|
||||
</div>
|
||||
<Popover.Arrow className="fill-black dark:fill-white" />
|
||||
</Popover.Content>
|
||||
</Popover.Portal>
|
||||
</Popover.Root>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownMenu.Root>
|
||||
<DropdownMenu.Trigger>
|
||||
<User.Provider pubkey={pubkey}>
|
||||
<User.Root className="rounded-full ring-1 ring-teal-500 ring-offset-2 ring-offset-neutral-200 dark:ring-offset-neutral-950">
|
||||
<User.Avatar className="aspect-square h-auto w-7 rounded-full object-cover" />
|
||||
</User.Root>
|
||||
</User.Provider>
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Portal>
|
||||
<DropdownMenu.Content
|
||||
className="flex w-[220px] flex-col rounded-xl bg-black p-2 text-neutral-100 focus:outline-none dark:bg-white dark:text-neutral-900 dark:shadow-none"
|
||||
sideOffset={10}
|
||||
side="bottom"
|
||||
>
|
||||
<DropdownMenu.Item className="group relative flex h-9 select-none items-center rounded-md px-3 text-sm font-medium leading-none outline-none hover:bg-neutral-900 dark:hover:bg-neutral-100">
|
||||
Add account
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item
|
||||
onClick={() => ark.open_profile(account)}
|
||||
className="group relative flex h-9 select-none items-center rounded-md px-3 text-sm font-medium leading-none outline-none hover:bg-neutral-900 dark:hover:bg-neutral-100"
|
||||
>
|
||||
Profile
|
||||
<div className="ml-auto pl-5 text-xs text-neutral-800 dark:text-neutral-200">
|
||||
⌘+Shift+P
|
||||
</div>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item
|
||||
onClick={() => navigate({ to: "/", search: { manually: true } })}
|
||||
className="group relative flex h-9 select-none items-center rounded-md px-3 text-sm font-medium leading-none outline-none hover:bg-neutral-900 dark:hover:bg-neutral-100"
|
||||
>
|
||||
Logout
|
||||
<div className="ml-auto pl-5 text-xs text-neutral-800 dark:text-neutral-200">
|
||||
⌘+Shift+L
|
||||
</div>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Arrow className="fill-black dark:fill-white" />
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Portal>
|
||||
</DropdownMenu.Root>
|
||||
<User.Provider pubkey={pubkey}>
|
||||
<User.Root className="rounded-full ring-1 ring-teal-500 ring-offset-2 ring-offset-neutral-200 dark:ring-offset-neutral-950">
|
||||
<User.Avatar className="aspect-square h-auto w-7 rounded-full object-cover" />
|
||||
</User.Root>
|
||||
</User.Provider>
|
||||
);
|
||||
}
|
||||
|
@ -120,3 +120,5 @@ export * from "./src/local";
|
||||
export * from "./src/global";
|
||||
export * from "./src/infoCircle";
|
||||
export * from "./src/cancelCircle";
|
||||
export * from "./src/laurel";
|
||||
export * from "./src/quote";
|
||||
|
13
packages/icons/src/laurel.tsx
Normal file
13
packages/icons/src/laurel.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
export function LaurelIcon(props: JSX.IntrinsicElements["svg"]) {
|
||||
return (
|
||||
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" {...props}>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
d="M9.405 18.105c-1.573 1.336-3.136 1.17-4.712-.5 3.665-3.643 8.229 1.637 4.189 3.645m5.713-3.145c1.573 1.336 3.136 1.17 4.712-.5-3.665-3.643-8.229 1.637-4.189 3.645m-8.333-6.084c-.584-2.476-2.086-3.338-4.535-2.603.584 2.476 2.086 3.338 4.535 2.603Zm-1.21-3.464c.74-2.434-.127-3.927-2.617-4.508-.74 2.435.127 3.928 2.618 4.508ZM6.719 2.75c-2.141 1.393-2.442 3.09-.91 5.127 2.141-1.393 2.442-3.09.91-5.127Zm10.497 12.416c.584-2.476 2.086-3.338 4.535-2.603-.584 2.476-2.086 3.338-4.535 2.603Zm1.21-3.464c-.74-2.434.127-3.927 2.617-4.508.74 2.435-.127 3.928-2.618 4.508ZM17.281 2.75c2.141 1.393 2.442 3.09.91 5.127-2.141-1.393-2.442-3.09-.91-5.127Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
@ -1,16 +1,12 @@
|
||||
import { SVGProps } from "react";
|
||||
|
||||
export function LinkIcon(
|
||||
props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
|
||||
) {
|
||||
export function LinkIcon(props: JSX.IntrinsicElements["svg"]) {
|
||||
return (
|
||||
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" {...props}>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M9 6H7.2c-1.12 0-1.68 0-2.108.218a2 2 0 0 0-.874.874C4 7.52 4 8.08 4 9.2v7.6c0 1.12 0 1.68.218 2.108a2 2 0 0 0 .874.874C5.52 20 6.08 20 7.2 20h7.6c1.12 0 1.68 0 2.108-.218a2 2 0 0 0 .874-.874C18 18.48 18 17.92 18 16.8V15M14 4h6m0 0v6m0-6-9 9"
|
||||
strokeWidth="1.5"
|
||||
d="M9.25 3.75h-2.3c-1.12 0-1.68 0-2.108.218a2 2 0 0 0-.874.874c-.218.428-.218.988-.218 2.108v10.1c0 1.12 0 1.68.218 2.108a2 2 0 0 0 .874.874c.428.218.988.218 2.108.218h10.1c1.12 0 1.68 0 2.108-.218a2 2 0 0 0 .874-.874c.218-.428.218-.988.218-2.108v-2.3m-6.5-11h6.5m0 0v6.5m0-6.5L11 13"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
13
packages/icons/src/quote.tsx
Normal file
13
packages/icons/src/quote.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
export function QuoteIcon(props: JSX.IntrinsicElements["svg"]) {
|
||||
return (
|
||||
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" {...props}>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
d="M11.855 21.25c-1.032-.26-3.16-.908-5.45-3.222C2.58 14.161 1.6 8.88 4.219 6.233 6.369 4.06 10.55 4.185 14 6.5m3.5 3.5c2.977 3.473 3.86 6.797 1.576 8.644-1.711 1.383-3.877-.217-5.14-1.45m-.748-3.944H10.75v-2.421a2 2 0 0 1 .586-1.415l5.499-5.499a2 2 0 0 1 2.83.001l.424.425a2 2 0 0 1 0 2.826l-5.485 5.496a2 2 0 0 1-1.416.587Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
@ -3,10 +3,9 @@ export function ReplyIcon(props: JSX.IntrinsicElements["svg"]) {
|
||||
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" {...props}>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M12 21a9 9 0 1 0-9-9c0 1.354.3 2.639.835 3.791.102.219.133.465.076.7l-.778 3.191a1 1 0 0 0 1.191 1.213l3.33-.752c.224-.05.458-.02.667.073A8.969 8.969 0 0 0 12 21Z"
|
||||
strokeWidth="1.5"
|
||||
d="m21.76 11.45-8.146-7.535a.75.75 0 0 0-1.26.55V8a.51.51 0 0 1-.504.504C3.765 8.632 1.604 11.92 1.604 20.25c1.47-2.94 2.22-4.679 10.245-4.748a.501.501 0 0 1 .505.498v3.535a.75.75 0 0 0 1.26.55l8.145-7.535a.75.75 0 0 0 0-1.1Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
@ -5,8 +5,8 @@ export function RepostIcon(props: JSX.IntrinsicElements["svg"]) {
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="m17.25 21 2.47-2.47a.75.75 0 0 0 0-1.06L17.25 15M6.75 3 4.28 5.47a.75.75 0 0 0 0 1.06L6.75 9M5 6h13a2 2 0 0 1 2 2v3M4 13v3a2 2 0 0 0 2 2h13"
|
||||
strokeWidth="1.5"
|
||||
d="m17.5 21.25 2.47-2.47a.75.75 0 0 0 0-1.06l-2.47-2.47m-11-12.5L4.03 5.22a.75.75 0 0 0 0 1.06L6.5 8.75m-1.25-3h13a2 2 0 0 1 2 2v3m-16.5 3v2.5a2 2 0 0 0 2 2h13"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
@ -4,8 +4,8 @@ export function ZapIcon(props: JSX.IntrinsicElements["svg"]) {
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M19.566 9H13.5a.5.5 0 0 1-.5-.5V2.401a.5.5 0 0 0-.916-.277L4.018 14.223a.5.5 0 0 0 .416.777H10.5a.5.5 0 0 1 .5.5v6.099a.5.5 0 0 0 .916.277l8.066-12.099A.5.5 0 0 0 19.566 9Z"
|
||||
strokeWidth="1.5"
|
||||
d="M19.798 8.75H13.75a.5.5 0 0 1-.5-.5V2.356a.5.5 0 0 0-.912-.284L3.791 14.466a.5.5 0 0 0 .411.784h6.048a.5.5 0 0 1 .5.5v5.894a.5.5 0 0 0 .912.284l8.547-12.394a.5.5 0 0 0-.411-.784Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
7
packages/types/index.d.ts
vendored
7
packages/types/index.d.ts
vendored
@ -81,6 +81,7 @@ export interface RichContent {
|
||||
}
|
||||
|
||||
export interface LumeColumn {
|
||||
id: number;
|
||||
content: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
@ -88,6 +89,12 @@ export interface LumeColumn {
|
||||
logo?: string;
|
||||
}
|
||||
|
||||
export interface EventColumns {
|
||||
type: "add" | "remove" | "update" | "left" | "right";
|
||||
id?: number;
|
||||
column?: LumeColumn;
|
||||
}
|
||||
|
||||
export interface Opengraph {
|
||||
url: string;
|
||||
title?: string;
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { LinkIcon, ReplyIcon } from "@lume/icons";
|
||||
import { ReplyIcon } from "@lume/icons";
|
||||
import * as Tooltip from "@radix-ui/react-tooltip";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNoteContext } from "../provider";
|
||||
import { useArk } from "@lume/ark";
|
||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
||||
|
||||
export function NoteReply() {
|
||||
const ark = useArk();
|
||||
@ -12,52 +11,24 @@ export function NoteReply() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<DropdownMenu.Root>
|
||||
<Tooltip.Provider>
|
||||
<Tooltip.Root delayDuration={150}>
|
||||
<DropdownMenu.Trigger asChild>
|
||||
<Tooltip.Trigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="group inline-flex size-7 items-center justify-center text-neutral-800 dark:text-neutral-200"
|
||||
>
|
||||
<ReplyIcon className="size-5 group-hover:text-blue-500" />
|
||||
</button>
|
||||
</Tooltip.Trigger>
|
||||
</DropdownMenu.Trigger>
|
||||
<Tooltip.Portal>
|
||||
<Tooltip.Content className="data-[state=delayed-open]:data-[side=bottom]:animate-slideUpAndFade data-[state=delayed-open]:data-[side=left]:animate-slideRightAndFade data-[state=delayed-open]:data-[side=right]:animate-slideLeftAndFade data-[state=delayed-open]:data-[side=top]:animate-slideDownAndFade inline-flex h-7 select-none items-center justify-center rounded-md bg-neutral-950 px-3.5 text-sm text-neutral-50 will-change-[transform,opacity] dark:bg-neutral-50 dark:text-neutral-950">
|
||||
{t("note.menu.viewThread")}
|
||||
<Tooltip.Arrow className="fill-neutral-950 dark:fill-neutral-50" />
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Portal>
|
||||
</Tooltip.Root>
|
||||
</Tooltip.Provider>
|
||||
<DropdownMenu.Portal>
|
||||
<DropdownMenu.Content className="flex w-[200px] flex-col overflow-hidden rounded-xl bg-black p-1 shadow-md shadow-neutral-500/20 focus:outline-none dark:bg-white">
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => ark.open_thread(event.id)}
|
||||
className="inline-flex h-9 items-center gap-2 rounded-lg px-3 text-sm font-medium text-white hover:bg-neutral-900 focus:outline-none dark:text-black dark:hover:bg-neutral-100"
|
||||
>
|
||||
<LinkIcon className="size-4" />
|
||||
{t("note.buttons.open")}
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => ark.open_editor(event.id)}
|
||||
className="inline-flex h-9 items-center gap-2 rounded-lg px-3 text-sm font-medium text-white hover:bg-neutral-900 focus:outline-none dark:text-black dark:hover:bg-neutral-100"
|
||||
>
|
||||
<ReplyIcon className="size-4" />
|
||||
{t("note.buttons.reply")}
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Arrow className="fill-black dark:fill-white" />
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Portal>
|
||||
</DropdownMenu.Root>
|
||||
<Tooltip.Provider>
|
||||
<Tooltip.Root delayDuration={150}>
|
||||
<Tooltip.Trigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => ark.open_editor(event.id)}
|
||||
className="group inline-flex size-7 items-center justify-center text-neutral-800 dark:text-neutral-200"
|
||||
>
|
||||
<ReplyIcon className="size-5 group-hover:text-blue-500" />
|
||||
</button>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Portal>
|
||||
<Tooltip.Content className="data-[state=delayed-open]:data-[side=bottom]:animate-slideUpAndFade data-[state=delayed-open]:data-[side=left]:animate-slideRightAndFade data-[state=delayed-open]:data-[side=right]:animate-slideLeftAndFade data-[state=delayed-open]:data-[side=top]:animate-slideDownAndFade inline-flex h-7 select-none items-center justify-center rounded-md bg-neutral-950 px-3.5 text-sm text-neutral-50 will-change-[transform,opacity] dark:bg-neutral-50 dark:text-neutral-950">
|
||||
{t("note.menu.viewThread")}
|
||||
<Tooltip.Arrow className="fill-neutral-950 dark:fill-neutral-50" />
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Portal>
|
||||
</Tooltip.Root>
|
||||
</Tooltip.Provider>
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { LoaderIcon, ReplyIcon, RepostIcon } from "@lume/icons";
|
||||
import { LoaderIcon, QuoteIcon, ReplyIcon, RepostIcon } from "@lume/icons";
|
||||
import { cn } from "@lume/utils";
|
||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
||||
import * as Tooltip from "@radix-ui/react-tooltip";
|
||||
@ -84,7 +84,7 @@ export function NoteRepost() {
|
||||
onClick={() => ark.open_editor(event.id, true)}
|
||||
className="inline-flex h-9 items-center gap-2 rounded-lg px-3 text-sm font-medium text-white hover:bg-neutral-900 focus:outline-none dark:text-black dark:hover:bg-neutral-100"
|
||||
>
|
||||
<ReplyIcon className="size-4" />
|
||||
<QuoteIcon className="size-4" />
|
||||
{t("note.buttons.quote")}
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
|
@ -1,2 +1,3 @@
|
||||
pub mod folder;
|
||||
pub mod opg;
|
||||
pub mod window;
|
||||
|
69
src-tauri/src/commands/window.rs
Normal file
69
src-tauri/src/commands/window.rs
Normal file
@ -0,0 +1,69 @@
|
||||
use std::path::PathBuf;
|
||||
use tauri::{LogicalPosition, LogicalSize, Manager, WebviewUrl};
|
||||
|
||||
#[tauri::command]
|
||||
pub fn create_column(
|
||||
label: &str,
|
||||
x: f32,
|
||||
y: f32,
|
||||
width: f32,
|
||||
height: f32,
|
||||
url: &str,
|
||||
app_handle: tauri::AppHandle,
|
||||
) -> Result<String, String> {
|
||||
match app_handle.get_window("main") {
|
||||
Some(main_window) => match app_handle.get_webview(label) {
|
||||
Some(_) => Err("Webview is exist".into()),
|
||||
None => {
|
||||
let path = PathBuf::from(url);
|
||||
let webview_url = WebviewUrl::App(path);
|
||||
let builder = tauri::webview::WebviewBuilder::new(label, webview_url)
|
||||
.auto_resize()
|
||||
.user_agent("Lume/4.0")
|
||||
.transparent(true);
|
||||
match main_window.add_child(
|
||||
builder,
|
||||
LogicalPosition::new(x, y),
|
||||
LogicalSize::new(width, height),
|
||||
) {
|
||||
Ok(webview) => Ok(webview.label().into()),
|
||||
Err(_) => Err("Something is wrong".into()),
|
||||
}
|
||||
}
|
||||
},
|
||||
None => Err("Main window not found".into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn close_column(label: &str, app_handle: tauri::AppHandle) -> Result<bool, String> {
|
||||
match app_handle.get_webview(label) {
|
||||
Some(webview) => {
|
||||
if let Ok(_) = webview.close() {
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
None => Err("Webview not found".into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn reposition_column(
|
||||
label: &str,
|
||||
x: f32,
|
||||
y: f32,
|
||||
app_handle: tauri::AppHandle,
|
||||
) -> Result<(), String> {
|
||||
match app_handle.get_webview(label) {
|
||||
Some(webview) => {
|
||||
if let Ok(_) = webview.set_position(LogicalPosition::new(x, y)) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err("Reposition column failed".into())
|
||||
}
|
||||
}
|
||||
None => Err("Webview not found".into()),
|
||||
}
|
||||
}
|
@ -117,6 +117,9 @@ fn main() {
|
||||
commands::folder::show_in_folder,
|
||||
commands::folder::get_accounts,
|
||||
commands::opg::fetch_opg,
|
||||
commands::window::create_column,
|
||||
commands::window::close_column,
|
||||
commands::window::reposition_column
|
||||
])
|
||||
.build(tauri::generate_context!())
|
||||
.expect("error while running tauri application")
|
||||
|
Loading…
Reference in New Issue
Block a user