feat: add option to toggle window transparent

This commit is contained in:
reya
2024-07-02 08:49:52 +07:00
parent d9fe647f8e
commit ed4f89ff66
30 changed files with 112 additions and 166 deletions

View File

@@ -17,7 +17,7 @@ export const Conversation = memo(function Conversation({
<Note.Provider event={event}> <Note.Provider event={event}>
<Note.Root <Note.Root
className={cn( className={cn(
"bg-white dark:bg-black/20 backdrop-blur-lg rounded-xl flex flex-col gap-3 shadow-primary dark:ring-1 ring-neutral-800/50", "bg-white dark:bg-black/20 rounded-xl flex flex-col gap-3 shadow-primary dark:ring-1 ring-neutral-800/50",
className, className,
)} )}
> >

View File

@@ -97,7 +97,7 @@ export function NoteContent({
return ( return (
<div className="relative flex flex-col gap-2"> <div className="relative flex flex-col gap-2">
{blurred ? ( {blurred ? (
<div className="absolute inset-0 z-10 flex items-center justify-center w-full h-full bg-black/80 backdrop-blur-xl"> <div className="absolute inset-0 z-10 flex items-center justify-center w-full h-full bg-black/80 backdrop-blur-lg">
<div className="flex flex-col items-center justify-center gap-2 text-center"> <div className="flex flex-col items-center justify-center gap-2 text-center">
<p className="text-sm text-white/60"> <p className="text-sm text-white/60">
The content is hidden because the author The content is hidden because the author

View File

@@ -1,10 +1,9 @@
import { Carousel, CarouselItem } from "@lume/ui";
export function Videos({ urls }: { urls: string[] }) { export function Videos({ urls }: { urls: string[] }) {
if (urls.length === 1) { return (
return ( <div className="group px-3">
<div className="group px-3"> {urls.map((url) => (
<video <video
key={url}
className="max-h-[400px] w-auto object-cover rounded-lg outline outline-1 -outline-offset-1 outline-black/15" className="max-h-[400px] w-auto object-cover rounded-lg outline outline-1 -outline-offset-1 outline-black/15"
preload="metadata" preload="metadata"
controls controls
@@ -13,26 +12,7 @@ export function Videos({ urls }: { urls: string[] }) {
<source src={`${urls[0]}#t=0.1`} type="video/mp4" /> <source src={`${urls[0]}#t=0.1`} type="video/mp4" />
Your browser does not support the video tag. Your browser does not support the video tag.
</video> </video>
</div> ))}
); </div>
}
return (
<Carousel
items={urls}
renderItem={({ item, isSnapPoint }) => (
<CarouselItem key={item} isSnapPoint={isSnapPoint}>
<video
className="w-full h-full object-cover rounded-lg outline outline-1 -outline-offset-1 outline-black/15"
preload="metadata"
controls={false}
muted
>
<source src={`${item}#t=0.1`} type="video/mp4" />
Your browser does not support the video tag.
</video>
</CarouselItem>
)}
/>
); );
} }

View File

@@ -15,7 +15,7 @@ export const Quote = memo(function Quote({
<Note.Provider event={event}> <Note.Provider event={event}>
<Note.Root <Note.Root
className={cn( className={cn(
"bg-white dark:bg-black/20 backdrop-blur-lg rounded-xl flex flex-col gap-3 shadow-primary dark:ring-1 ring-neutral-800/50", "bg-white dark:bg-black/20 rounded-xl flex flex-col gap-3 shadow-primary dark:ring-1 ring-neutral-800/50",
className, className,
)} )}
> >

View File

@@ -33,7 +33,7 @@ export const RepostNote = memo(function RepostNote({
return ( return (
<Note.Root <Note.Root
className={cn( className={cn(
"bg-white dark:bg-black/20 backdrop-blur-lg rounded-xl shadow-primary dark:ring-1 ring-neutral-800/50", "bg-white dark:bg-black/20 rounded-xl shadow-primary dark:ring-1 ring-neutral-800/50",
className, className,
)} )}
> >

View File

@@ -14,7 +14,7 @@ export const TextNote = memo(function TextNote({
<Note.Provider event={event}> <Note.Provider event={event}>
<Note.Root <Note.Root
className={cn( className={cn(
"bg-white dark:bg-black/20 backdrop-blur rounded-xl shadow-primary dark:ring-1 dark:ring-white/5", "bg-white dark:bg-black/20 rounded-xl shadow-primary dark:ring-1 dark:ring-white/5",
className, className,
)} )}
> >

View File

@@ -5,7 +5,7 @@ import {
PlusIcon, PlusIcon,
SearchIcon, SearchIcon,
} from "@lume/icons"; } from "@lume/icons";
import { LumeWindow, NostrAccount } from "@lume/system"; import { LumeWindow, NostrAccount, NostrQuery } from "@lume/system";
import { cn } from "@lume/utils"; import { cn } from "@lume/utils";
import { Outlet, createFileRoute } from "@tanstack/react-router"; import { Outlet, createFileRoute } from "@tanstack/react-router";
import { Menu, MenuItem, PredefinedMenuItem } from "@tauri-apps/api/menu"; import { Menu, MenuItem, PredefinedMenuItem } from "@tauri-apps/api/menu";
@@ -15,18 +15,19 @@ import { memo, useCallback, useState } from "react";
export const Route = createFileRoute("/$account")({ export const Route = createFileRoute("/$account")({
beforeLoad: async ({ params }) => { beforeLoad: async ({ params }) => {
const settings = await NostrQuery.getUserSettings();
const accounts = await NostrAccount.getAccounts(); const accounts = await NostrAccount.getAccounts();
const otherAccounts = accounts.filter( const otherAccounts = accounts.filter(
(account) => account !== params.account, (account) => account !== params.account,
); );
return { otherAccounts }; return { otherAccounts, settings };
}, },
component: Screen, component: Screen,
}); });
function Screen() { function Screen() {
const { platform } = Route.useRouteContext(); const { settings, platform } = Route.useRouteContext();
const openLumeStore = async () => { const openLumeStore = async () => {
await getCurrent().emit("columns", { await getCurrent().emit("columns", {
@@ -80,7 +81,14 @@ function Screen() {
<Accounts /> <Accounts />
</div> </div>
</div> </div>
<div className="flex-1"> <div
className={cn(
"flex-1",
settings.vibrancy
? ""
: "bg-white dark:bg-black border-t border-black/20 dark:border-white/20",
)}
>
<Outlet /> <Outlet />
</div> </div>
</div> </div>

View File

@@ -28,6 +28,13 @@ function Screen() {
const onSubmit = async (data: { url: string; purpose: string }) => { const onSubmit = async (data: { url: string; purpose: string }) => {
try { try {
if (!data.url.startsWith("wss://") || !data.url.startsWith("ws://")) {
return await message("Relay must be starts with wss:// or ws://", {
title: "Bootstrap Relays",
kind: "info",
});
}
const relay: Relay = { url: data.url, purpose: data.purpose }; const relay: Relay = { url: data.url, purpose: data.purpose };
setRelays((prev) => [...prev, relay]); setRelays((prev) => [...prev, relay]);
reset(); reset();
@@ -50,12 +57,21 @@ function Screen() {
}, [bootstrapRelays]); }, [bootstrapRelays]);
return ( return (
<div className="flex flex-col items-center justify-center w-screen h-screen"> <div
<div className="w-full max-w-sm mx-auto lg:max-w-lg"> data-tauri-drag-region
<div className="text-center h-11"> className="relative flex flex-col items-center justify-between w-full h-full"
<h1 className="font-semibold">Customize Bootstrap Relays</h1> >
<div
data-tauri-drag-region
className="absolute top-0 left-0 h-14 w-full"
/>
<div className="flex items-end justify-center flex-1 w-full px-4 pb-10">
<div className="text-center">
<h2 className="text-2xl font-semibold">Customize Bootstrap Relays</h2>
</div> </div>
<div className="flex flex-col w-full px-2 bg-white rounded-xl shadow-primary backdrop-blur-lg dark:bg-white/20 dark:ring-1 ring-neutral-800/50"> </div>
<div className="flex flex-col items-center flex-1 w-full">
<div className="flex flex-col w-full max-w-sm mx-auto p-3 overflow-hidden bg-white divide-y divide-neutral-100 dark:divide-white/5 rounded-xl shadow-primary dark:bg-white/10 dark:ring-1 ring-white/15">
{relays.map((relay) => ( {relays.map((relay) => (
<div <div
key={relay.url} key={relay.url}
@@ -117,15 +133,18 @@ function Screen() {
</form> </form>
</div> </div>
</div> </div>
<button <div className="w-full max-w-sm mx-auto">
type="button" <button
onClick={() => save()} type="button"
disabled={isLoading} onClick={() => save()}
className="inline-flex items-center justify-center w-full h-10 mt-4 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50" disabled={isLoading}
> className="inline-flex items-center justify-center w-full h-9 mt-4 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50"
{isLoading ? <Spinner /> : "Save & Relaunch"} >
</button> {isLoading ? <Spinner /> : "Save & Relaunch"}
</button>
</div>
</div> </div>
<div className="flex-1" />
</div> </div>
); );
} }

View File

@@ -96,7 +96,7 @@ function Screen() {
/> />
</div> </div>
<div className="flex flex-col items-center w-full gap-3"> <div className="flex flex-col items-center w-full gap-3">
<div className="overflow-y-auto scrollbar-none p-2 w-full h-[450px] flex flex-col gap-3 bg-black/5 dark:bg-white/5 backdrop-blur-lg rounded-xl"> <div className="overflow-y-auto scrollbar-none p-2 w-full h-[450px] flex flex-col gap-3 bg-black/5 dark:bg-white/5 rounded-xl">
<div className="flex gap-2"> <div className="flex gap-2">
<input <input
name="npub" name="npub"
@@ -122,7 +122,7 @@ function Screen() {
key={item} key={item}
type="button" type="button"
onClick={() => toggleUser(item)} onClick={() => toggleUser(item)}
className="inline-flex items-center justify-between px-3 py-2 bg-white rounded-lg dark:bg-black/20 backdrop-blur-lg shadow-primary dark:ring-1 ring-neutral-800/50" className="inline-flex items-center justify-between px-3 py-2 bg-white rounded-lg dark:bg-black/20 shadow-primary dark:ring-1 ring-neutral-800/50"
> >
<User.Provider pubkey={item}> <User.Provider pubkey={item}>
<User.Root className="flex items-center gap-2.5"> <User.Root className="flex items-center gap-2.5">
@@ -153,7 +153,7 @@ function Screen() {
key={item} key={item}
type="button" type="button"
onClick={() => toggleUser(item)} onClick={() => toggleUser(item)}
className="inline-flex items-center justify-between px-3 py-2 bg-white rounded-lg dark:bg-black/20 backdrop-blur-lg shadow-primary dark:ring-1 ring-neutral-800/50" className="inline-flex items-center justify-between px-3 py-2 bg-white rounded-lg dark:bg-black/20 shadow-primary dark:ring-1 ring-neutral-800/50"
> >
<User.Provider pubkey={item}> <User.Provider pubkey={item}>
<User.Root className="flex items-center gap-2.5"> <User.Root className="flex items-center gap-2.5">

View File

@@ -49,7 +49,7 @@ function Screen() {
}; };
return ( return (
<div className="overflow-y-auto scrollbar-none p-2 shrink-0 h-[450px] bg-white dark:bg-white/20 backdrop-blur-lg rounded-xl shadow-primary dark:ring-1 ring-neutral-800/50"> <div className="overflow-y-auto scrollbar-none p-2 shrink-0 h-[450px] bg-white dark:bg-white/20 rounded-xl shadow-primary dark:ring-1 ring-neutral-800/50">
<div className="flex flex-col justify-between h-full"> <div className="flex flex-col justify-between h-full">
<div className="flex-1 flex flex-col gap-1.5 justify-center px-5"> <div className="flex-1 flex flex-col gap-1.5 justify-center px-5">
<p className="font-semibold text-neutral-500"> <p className="font-semibold text-neutral-500">

View File

@@ -68,7 +68,7 @@ function Screen() {
return ( return (
<div className="flex flex-col items-center w-full gap-3"> <div className="flex flex-col items-center w-full gap-3">
<div className="overflow-y-auto scrollbar-none p-2 w-full h-[450px] bg-black/5 dark:bg-white/5 backdrop-blur-lg rounded-xl"> <div className="overflow-y-auto scrollbar-none p-2 w-full h-[450px] bg-black/5 dark:bg-white/5 rounded-xl">
<Suspense <Suspense
fallback={ fallback={
<div className="flex flex-col items-center justify-center w-full h-20 gap-1"> <div className="flex flex-col items-center justify-center w-full h-20 gap-1">
@@ -88,7 +88,7 @@ function Screen() {
users.profiles.map((item: { pubkey: string }) => ( users.profiles.map((item: { pubkey: string }) => (
<div <div
key={item.pubkey} key={item.pubkey}
className="w-full p-2 mb-2 overflow-hidden bg-white rounded-lg h-max dark:bg-black/20 backdrop-blur-lg shadow-primary dark:ring-1 ring-neutral-800/50" className="w-full p-2 mb-2 overflow-hidden bg-white rounded-lg h-max dark:bg-black/20shadow-primary dark:ring-1 ring-neutral-800/50"
> >
<User.Provider pubkey={item.pubkey}> <User.Provider pubkey={item.pubkey}>
<User.Root> <User.Root>

View File

@@ -75,14 +75,14 @@ function Screen() {
<span className="text-sm font-medium">Added: {topics.length}</span> <span className="text-sm font-medium">Added: {topics.length}</span>
</div> </div>
<div className="flex flex-col items-center w-full gap-3"> <div className="flex flex-col items-center w-full gap-3">
<div className="overflow-y-auto scrollbar-none p-2 w-full h-[450px] bg-black/5 dark:bg-white/5 backdrop-blur-lg rounded-xl"> <div className="overflow-y-auto scrollbar-none p-2 w-full h-[450px] bg-black/5 dark:bg-white/5 rounded-xl">
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">
{TOPICS.map((topic) => ( {TOPICS.map((topic) => (
<button <button
key={topic.title} key={topic.title}
type="button" type="button"
onClick={() => toggleTopic(topic)} onClick={() => toggleTopic(topic)}
className="flex items-center justify-between px-3 bg-white border border-transparent rounded-lg h-11 dark:bg-black/20 backdrop-blur-lg hover:border-blue-500 shadow-primary dark:ring-1 ring-neutral-800/50" className="flex items-center justify-between px-3 bg-white border border-transparent rounded-lg h-11 dark:bg-black/20 hover:border-blue-500 shadow-primary dark:ring-1 ring-neutral-800/50"
> >
<div className="inline-flex items-center gap-1"> <div className="inline-flex items-center gap-1">
<div>{topic.icon}</div> <div>{topic.icon}</div>

View File

@@ -1,12 +1,12 @@
import { Note } from "@/components/note"; import { Note } from "@/components/note";
import { LumeEvent, NostrQuery } from "@lume/system"; import { LumeEvent, NostrQuery } from "@lume/system";
import type { Meta } from "@lume/types";
import * as ScrollArea from "@radix-ui/react-scroll-area";
import { createFileRoute } from "@tanstack/react-router"; import { createFileRoute } from "@tanstack/react-router";
import { getCurrent } from "@tauri-apps/api/window";
import { useEffect, useRef, useState } from "react";
import { Virtualizer } from "virtua"; import { Virtualizer } from "virtua";
import NoteParent from "./-components/parent"; import NoteParent from "./-components/parent";
import * as ScrollArea from "@radix-ui/react-scroll-area";
import { useEffect, useRef, useState } from "react";
import { getCurrent } from "@tauri-apps/api/window";
import type { Meta } from "@lume/types";
type Payload = { type Payload = {
raw: string; raw: string;
@@ -62,7 +62,7 @@ function RootEvent() {
return ( return (
<Note.Provider event={event}> <Note.Provider event={event}>
<Note.Root className="bg-white dark:bg-black/10 backdrop-blur rounded-xl shadow-primary dark:ring-1 dark:ring-white/5"> <Note.Root className="bg-white dark:bg-black/10 rounded-xl shadow-primary dark:ring-1 dark:ring-white/5">
<div className="flex items-center justify-between px-3 h-14"> <div className="flex items-center justify-between px-3 h-14">
<Note.User /> <Note.User />
<Note.Menu /> <Note.Menu />

View File

@@ -81,7 +81,7 @@ export function Screen() {
<ScrollArea.Viewport ref={ref} className="h-full px-3 pb-3"> <ScrollArea.Viewport ref={ref} className="h-full px-3 pb-3">
<Virtualizer scrollRef={ref}> <Virtualizer scrollRef={ref}>
{isFetching && !isLoading && !isFetchingNextPage ? ( {isFetching && !isLoading && !isFetchingNextPage ? (
<div className="flex items-center justify-center w-full mb-3 h-11 bg-black/10 dark:bg-white/10 backdrop-blur-lg rounded-xl shadow-primary dark:ring-1 ring-neutral-800/50"> <div className="flex items-center justify-center w-full mb-3 h-11 bg-black/10 dark:bg-white/10 rounded-xl shadow-primary dark:ring-1 ring-neutral-800/50">
<div className="flex items-center justify-center gap-2"> <div className="flex items-center justify-center gap-2">
<Spinner className="size-5" /> <Spinner className="size-5" />
<span className="text-sm font-medium"> <span className="text-sm font-medium">

View File

@@ -95,7 +95,7 @@ export function Screen() {
<ScrollArea.Viewport ref={ref} className="h-full px-3 pb-3"> <ScrollArea.Viewport ref={ref} className="h-full px-3 pb-3">
<Virtualizer scrollRef={ref}> <Virtualizer scrollRef={ref}>
{isFetching && !isLoading && !isFetchingNextPage ? ( {isFetching && !isLoading && !isFetchingNextPage ? (
<div className="flex items-center justify-center w-full mb-3 h-11 bg-black/10 dark:bg-white/10 backdrop-blur-lg rounded-xl shadow-primary dark:ring-1 ring-neutral-800/50"> <div className="flex items-center justify-center w-full mb-3 h-11 bg-black/10 dark:bg-white/10 rounded-xl shadow-primary dark:ring-1 ring-neutral-800/50">
<div className="flex items-center justify-center gap-2"> <div className="flex items-center justify-center gap-2">
<Spinner className="size-5" /> <Spinner className="size-5" />
<span className="text-sm font-medium"> <span className="text-sm font-medium">

View File

@@ -82,7 +82,7 @@ function Screen() {
</div> </div>
</div> </div>
<div className="flex flex-col items-center flex-1 w-full gap-3"> <div className="flex flex-col items-center flex-1 w-full gap-3">
<div className="flex flex-col w-full max-w-sm mx-auto overflow-hidden bg-white divide-y divide-neutral-100 dark:divide-white/5 rounded-xl shadow-primary backdrop-blur-lg dark:bg-white/10 dark:ring-1 ring-white/15"> <div className="flex flex-col w-full max-w-sm mx-auto overflow-hidden bg-white divide-y divide-neutral-100 dark:divide-white/5 rounded-xl shadow-primary dark:bg-white/10 dark:ring-1 ring-white/15">
{context.accounts.map((account) => ( {context.accounts.map((account) => (
<div <div
key={account} key={account}

View File

@@ -12,7 +12,7 @@ function Screen() {
className="flex flex-col items-center justify-center w-screen h-screen" className="flex flex-col items-center justify-center w-screen h-screen"
> >
<div className="w-full max-w-xs mx-auto lg:max-w-md"> <div className="w-full max-w-xs mx-auto lg:max-w-md">
<div className="flex flex-col w-full gap-2 px-2 bg-white rounded-xl shadow-primary backdrop-blur-lg dark:bg-white/20 dark:ring-1 ring-neutral-800/50"> <div className="flex flex-col w-full gap-2 px-2 bg-white rounded-xl shadow-primary dark:bg-white/20 dark:ring-1 ring-neutral-800/50">
<div className="flex items-center h-20 border-b border-neutral-100 dark:border-white/5"> <div className="flex items-center h-20 border-b border-neutral-100 dark:border-white/5">
<Link <Link
to="/auth/create-profile" to="/auth/create-profile"

View File

@@ -111,7 +111,7 @@ export function Screen() {
<Listerner /> <Listerner />
<Virtualizer scrollRef={ref}> <Virtualizer scrollRef={ref}>
{isFetching && !isLoading && !isFetchingNextPage ? ( {isFetching && !isLoading && !isFetchingNextPage ? (
<div className="flex items-center justify-center w-full mb-3 h-12 bg-black/10 dark:bg-white/10 backdrop-blur-lg rounded-xl shadow-primary dark:ring-1 ring-neutral-800/50"> <div className="flex items-center justify-center w-full mb-3 h-12 bg-black/10 dark:bg-white/10 rounded-xl shadow-primary dark:ring-1 ring-neutral-800/50">
<div className="flex items-center justify-center gap-2"> <div className="flex items-center justify-center gap-2">
<Spinner className="size-5" /> <Spinner className="size-5" />
<span className="text-sm font-medium"> <span className="text-sm font-medium">

View File

@@ -22,7 +22,7 @@ function Screen() {
</p> </p>
</div> </div>
<div className="px-3 flex flex-col gap-3"> <div className="px-3 flex flex-col gap-3">
<div className="relative flex flex-col items-center justify-center rounded-xl bg-black/10 dark:bg-white/10 backdrop-blur-lg"> <div className="relative flex flex-col items-center justify-center rounded-xl bg-black/10 dark:bg-white/10">
<div className="absolute top-2 left-3 text-2xl font-semibold font-serif text-neutral-600 dark:text-neutral-400"> <div className="absolute top-2 left-3 text-2xl font-semibold font-serif text-neutral-600 dark:text-neutral-400">
01. 01.
</div> </div>
@@ -45,7 +45,7 @@ function Screen() {
</video> </video>
</div> </div>
</div> </div>
<div className="relative flex flex-col items-center justify-center rounded-xl bg-black/10 dark:bg-white/10 backdrop-blur-lg"> <div className="relative flex flex-col items-center justify-center rounded-xl bg-black/10 dark:bg-white/10">
<div className="absolute top-2 left-3 text-2xl font-semibold font-serif text-neutral-600 dark:text-neutral-400"> <div className="absolute top-2 left-3 text-2xl font-semibold font-serif text-neutral-600 dark:text-neutral-400">
02. 02.
</div> </div>
@@ -68,7 +68,7 @@ function Screen() {
</video> </video>
</div> </div>
</div> </div>
<div className="relative flex flex-col items-center justify-center rounded-xl bg-black/10 dark:bg-white/10 backdrop-blur-lg"> <div className="relative flex flex-col items-center justify-center rounded-xl bg-black/10 dark:bg-white/10">
<div className="absolute top-2 left-3 text-2xl font-semibold font-serif text-neutral-600 dark:text-neutral-400"> <div className="absolute top-2 left-3 text-2xl font-semibold font-serif text-neutral-600 dark:text-neutral-400">
03. 03.
</div> </div>
@@ -91,7 +91,7 @@ function Screen() {
</video> </video>
</div> </div>
</div> </div>
<div className="relative flex flex-col items-center justify-center rounded-xl bg-black/10 dark:bg-white/10 backdrop-blur-lg"> <div className="relative flex flex-col items-center justify-center rounded-xl bg-black/10 dark:bg-white/10">
<div className="absolute top-2 left-3 text-2xl font-semibold font-serif text-neutral-600 dark:text-neutral-400"> <div className="absolute top-2 left-3 text-2xl font-semibold font-serif text-neutral-600 dark:text-neutral-400">
04. 04.
</div> </div>

View File

@@ -188,7 +188,7 @@ function Screen() {
{[...data.reactions.entries()].map(([root, events]) => ( {[...data.reactions.entries()].map(([root, events]) => (
<div <div
key={root} key={root}
className="flex flex-col gap-1 p-2 mb-2 rounded-lg shrink-0 backdrop-blur-md bg-black/10 dark:bg-white/10" className="flex flex-col gap-1 p-2 mb-2 rounded-lg shrink-0 bg-black/10 dark:bg-white/10"
> >
<div className="flex flex-col flex-1 min-w-0 gap-2"> <div className="flex flex-col flex-1 min-w-0 gap-2">
<div className="flex items-center gap-2 pb-2 border-b border-black/5 dark:border-white/5"> <div className="flex items-center gap-2 pb-2 border-b border-black/5 dark:border-white/5">
@@ -197,7 +197,7 @@ function Screen() {
<div className="flex flex-wrap items-center gap-3"> <div className="flex flex-wrap items-center gap-3">
{events.map((event) => ( {events.map((event) => (
<User.Provider key={event.id} pubkey={event.pubkey}> <User.Provider key={event.id} pubkey={event.pubkey}>
<User.Root className="shrink-0 flex rounded-full h-8 bg-black/10 dark:bg-white/10 backdrop-blur-md p-[2px]"> <User.Root className="shrink-0 flex rounded-full h-8 bg-black/10 dark:bg-white/10 p-[2px]">
<User.Avatar className="flex-1 rounded-full size-7" /> <User.Avatar className="flex-1 rounded-full size-7" />
<div className="inline-flex items-center justify-center flex-1 text-xs truncate rounded-full size-7"> <div className="inline-flex items-center justify-center flex-1 text-xs truncate rounded-full size-7">
{event.kind === Kind.Reaction ? ( {event.kind === Kind.Reaction ? (
@@ -222,7 +222,7 @@ function Screen() {
{[...data.zaps.entries()].map(([root, events]) => ( {[...data.zaps.entries()].map(([root, events]) => (
<div <div
key={root} key={root}
className="flex flex-col gap-1 p-2 mb-2 rounded-lg shrink-0 backdrop-blur-md bg-black/10 dark:bg-white/10" className="flex flex-col gap-1 p-2 mb-2 rounded-lg shrink-0 bg-black/10 dark:bg-white/10"
> >
<div className="flex flex-col flex-1 min-w-0 gap-2"> <div className="flex flex-col flex-1 min-w-0 gap-2">
<div className="flex items-center gap-2 pb-2 border-b border-black/5 dark:border-white/5"> <div className="flex items-center gap-2 pb-2 border-b border-black/5 dark:border-white/5">
@@ -234,7 +234,7 @@ function Screen() {
key={event.id} key={event.id}
pubkey={event.tags.find((tag) => tag[0] === "P")[1]} pubkey={event.tags.find((tag) => tag[0] === "P")[1]}
> >
<User.Root className="shrink-0 flex gap-1.5 rounded-full h-8 bg-black/10 dark:bg-white/10 backdrop-blur-md p-[2px]"> <User.Root className="shrink-0 flex gap-1.5 rounded-full h-8 bg-black/10 dark:bg-white/10 p-[2px]">
<User.Avatar className="rounded-full size-7" /> <User.Avatar className="rounded-full size-7" />
<div className="flex-1 h-7 w-max pr-1.5 rounded-full inline-flex items-center justify-center text-sm truncate"> <div className="flex-1 h-7 w-max pr-1.5 rounded-full inline-flex items-center justify-center text-sm truncate">
{decodeZapInvoice(event.tags).bitcoinFormatted} {decodeZapInvoice(event.tags).bitcoinFormatted}
@@ -319,7 +319,7 @@ function TextNote({ event }: { event: LumeEvent }) {
return ( return (
<Note.Provider event={event}> <Note.Provider event={event}>
<Note.Root className="flex flex-col p-2 mb-2 rounded-lg shrink-0 backdrop-blur-md bg-black/10 dark:bg-white/10"> <Note.Root className="flex flex-col p-2 mb-2 rounded-lg shrink-0 bg-black/10 dark:bg-white/10">
<User.Provider pubkey={event.pubkey}> <User.Provider pubkey={event.pubkey}>
<User.Root className="inline-flex items-center gap-2"> <User.Root className="inline-flex items-center gap-2">
<User.Avatar className="rounded-full size-9" /> <User.Avatar className="rounded-full size-9" />

View File

@@ -69,7 +69,7 @@ function Screen() {
data.map((item) => ( data.map((item) => (
<div <div
key={item.pubkey} key={item.pubkey}
className="w-full p-3 mb-2 overflow-hidden bg-white rounded-lg h-max dark:bg-black/20 backdrop-blur-lg shadow-primary dark:ring-1 ring-neutral-800/50" className="w-full p-3 mb-2 overflow-hidden bg-white rounded-lg h-max dark:bg-black/20 shadow-primary dark:ring-1 ring-neutral-800/50"
> >
<User.Provider pubkey={item.pubkey} embedProfile={item.profile}> <User.Provider pubkey={item.pubkey} embedProfile={item.profile}>
<User.Root className="flex flex-col w-full h-full gap-2"> <User.Root className="flex flex-col w-full h-full gap-2">

View File

@@ -130,6 +130,28 @@ function Screen() {
</select> </select>
</div> </div>
</div> </div>
<div className="flex items-start justify-between w-full gap-4 py-3">
<div className="flex-1">
<h3 className="font-medium">Vibrancy Effect</h3>
<p className="text-sm text-neutral-700 dark:text-neutral-300">
Make the window transparent.
</p>
</div>
<div className="flex justify-end w-36 shrink-0">
<Switch.Root
checked={settings.vibrancy}
onClick={() =>
setSettings((prev) => ({
...prev,
vibrancy: !prev.vibrancy,
}))
}
className="relative h-7 w-12 shrink-0 cursor-default rounded-full bg-black/10 outline-none data-[state=checked]:bg-blue-500 dark:bg-white/10"
>
<Switch.Thumb className="block size-6 translate-x-0.5 rounded-full bg-white transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[19px]" />
</Switch.Root>
</div>
</div>
<div className="flex items-start justify-between w-full gap-4 py-3"> <div className="flex items-start justify-between w-full gap-4 py-3">
<div className="flex-1"> <div className="flex-1">
<h3 className="font-medium">Zap Button</h3> <h3 className="font-medium">Zap Button</h3>

View File

@@ -45,7 +45,7 @@ function Screen() {
className="absolute left-0 top-0 z-10 h-full w-full object-cover" className="absolute left-0 top-0 z-10 h-full w-full object-cover"
/> />
) : null} ) : null}
<div className="absolute bottom-0 left-0 z-20 h-16 w-full bg-black/40 px-3 backdrop-blur-xl"> <div className="absolute bottom-0 left-0 z-20 h-16 w-full bg-black/40 px-3">
<div className="flex h-full items-center justify-between"> <div className="flex h-full items-center justify-between">
<div> <div>
<h1 className="font-semibold text-white">{column.name}</h1> <h1 className="font-semibold text-white">{column.name}</h1>

View File

@@ -105,7 +105,7 @@ export function Screen() {
<ScrollArea.Viewport ref={ref} className="h-full px-3 pb-3"> <ScrollArea.Viewport ref={ref} className="h-full px-3 pb-3">
<Virtualizer scrollRef={ref}> <Virtualizer scrollRef={ref}>
{isFetching && !isLoading && !isFetchingNextPage ? ( {isFetching && !isLoading && !isFetchingNextPage ? (
<div className="flex items-center justify-center w-full mb-3 h-11 bg-black/10 dark:bg-white/10 backdrop-blur-lg rounded-xl shadow-primary dark:ring-1 ring-neutral-800/50"> <div className="flex items-center justify-center w-full mb-3 h-11 bg-black/10 dark:bg-white/10 rounded-xl shadow-primary dark:ring-1 ring-neutral-800/50">
<div className="flex items-center justify-center gap-2"> <div className="flex items-center justify-center gap-2">
<Spinner className="size-5" /> <Spinner className="size-5" />
<span className="text-sm font-medium"> <span className="text-sm font-medium">

View File

@@ -45,7 +45,7 @@ export function Screen() {
users.profiles.map((item: { pubkey: string }) => ( users.profiles.map((item: { pubkey: string }) => (
<div <div
key={item.pubkey} key={item.pubkey}
className="h-max w-full overflow-hidden mb-3 p-2 bg-black/5 dark:bg-white/5 backdrop-blur-lg rounded-xl" className="h-max w-full overflow-hidden mb-3 p-2 bg-black/5 dark:bg-white/5 rounded-xl"
> >
<User.Provider pubkey={item.pubkey}> <User.Provider pubkey={item.pubkey}>
<User.Root> <User.Root>

View File

@@ -50,7 +50,7 @@ function Screen() {
return ( return (
<Container withDrag> <Container withDrag>
<Box className="px-0 scrollbar-none bg-black/5 dark:bg-white/5 backdrop-blur-sm"> <Box className="px-0 scrollbar-none bg-black/5 dark:bg-white/5">
<WindowVirtualizer> <WindowVirtualizer>
<User.Provider pubkey={pubkey}> <User.Provider pubkey={pubkey}>
<User.Root> <User.Root>

View File

@@ -459,7 +459,7 @@ export type Column = { label: string; url: string; x: number; y: number; width:
export type Meta = { content: string; images: string[]; videos: string[]; events: string[]; mentions: string[]; hashtags: string[] } export type Meta = { content: string; images: string[]; videos: string[]; events: string[]; mentions: string[]; hashtags: string[] }
export type Relays = { connected: string[]; read: string[] | null; write: string[] | null; both: string[] | null } export type Relays = { connected: string[]; read: string[] | null; write: string[] | null; both: string[] | null }
export type RichEvent = { raw: string; parsed: Meta | null } export type RichEvent = { raw: string; parsed: Meta | null }
export type Settings = { proxy: string | null; image_resize_service: string | null; use_relay_hint: boolean; content_warning: boolean; display_avatar: boolean; display_zap_button: boolean; display_repost_button: boolean; display_media: boolean } export type Settings = { proxy: string | null; image_resize_service: string | null; use_relay_hint: boolean; content_warning: boolean; display_avatar: boolean; display_zap_button: boolean; display_repost_button: boolean; display_media: boolean; vibrancy: boolean }
export type Window = { label: string; title: string; url: string; width: number; height: number; maximizable: boolean; minimizable: boolean; hidden_title: boolean } export type Window = { label: string; title: string; url: string; width: number; height: number; maximizable: boolean; minimizable: boolean; hidden_title: boolean }
/** tauri-specta globals **/ /** tauri-specta globals **/

View File

@@ -1,84 +0,0 @@
import { ArrowLeftIcon, ArrowRightIcon } from "@lume/icons";
import { cn } from "@lume/utils";
import { useSnapCarousel } from "react-snap-carousel";
interface CarouselProps<T> {
readonly items: T[];
readonly renderItem: (
props: CarouselRenderItemProps<T>,
) => React.ReactElement<CarouselItemProps>;
}
interface CarouselRenderItemProps<T> {
readonly item: T;
readonly index: number;
readonly isSnapPoint: boolean;
}
export const Carousel = <T,>({ items, renderItem }: CarouselProps<T>) => {
const { scrollRef, pages, activePageIndex, prev, next, snapPointIndexes } =
useSnapCarousel();
return (
<div className="relative group">
<ul
ref={scrollRef}
className="relative flex overflow-auto snap-x scrollbar-none"
>
{items.map((item, index) =>
renderItem({
item,
index,
isSnapPoint: snapPointIndexes.has(index),
}),
)}
</ul>
<div
aria-hidden
className="absolute z-10 items-center justify-between hidden w-full px-5 transform -translate-x-1/2 -translate-y-1/2 group-hover:flex left-1/2 top-1/2"
>
<button
type="button"
className={cn(
"size-11 rounded-full bg-black/50 backdrop-blur-sm flex items-center justify-center text-white",
activePageIndex <= 0 ? "opacity-50" : "",
)}
onClick={() => prev()}
>
<ArrowLeftIcon className="size-6" />
</button>
<button
type="button"
className={cn(
"size-11 rounded-full bg-black/50 backdrop-blur-sm flex items-center justify-center text-white",
activePageIndex <= 0 ? "opacity-50" : "",
)}
onClick={() => next()}
>
<ArrowRightIcon className="size-6" />
</button>
</div>
<div className="absolute flex items-center justify-center w-12 h-6 text-sm font-medium text-white bg-black rounded-full top-3 right-3 mix-blend-multiply bg-opacity-20 backdrop-blur-sm">
{activePageIndex + 1} / {pages.length}
</div>
</div>
);
};
interface CarouselItemProps {
readonly isSnapPoint: boolean;
readonly children?: React.ReactNode;
}
export const CarouselItem = ({ isSnapPoint, children }: CarouselItemProps) => {
return (
<li
className={cn(
"w-[240px] h-[320px] shrink-0 pl-3 last:pr-2",
isSnapPoint ? "" : "snap-start",
)}
>
{children}
</li>
);
};

View File

@@ -1,4 +1,3 @@
export * from "./container"; export * from "./container";
export * from "./box"; export * from "./box";
export * from "./spinner"; export * from "./spinner";
export * from "./carousel";

View File

@@ -43,6 +43,7 @@ pub struct Settings {
display_zap_button: bool, display_zap_button: bool,
display_repost_button: bool, display_repost_button: bool,
display_media: bool, display_media: bool,
vibrancy: bool,
} }
impl Default for Settings { impl Default for Settings {
@@ -56,6 +57,7 @@ impl Default for Settings {
display_zap_button: true, display_zap_button: true,
display_repost_button: true, display_repost_button: true,
display_media: true, display_media: true,
vibrancy: true,
} }
} }
} }