feat: simple relay page

This commit is contained in:
2024-09-09 16:19:39 +01:00
parent 40ffebb0c2
commit 68b5cd60a6
15 changed files with 186 additions and 243 deletions

View File

@ -100,7 +100,7 @@ export function Note(props: NoteProps) {
<div
className={classNames(baseClassName, {
active: highlight,
"hover:bg-nearly-bg-color cursor-pointer": !opt?.isRoot,
"hover:bg-nearly-bg-background cursor-pointer": !opt?.isRoot,
})}
onClick={e => goToEvent(e, ev)}
ref={ref}>

View File

@ -1,11 +0,0 @@
.relay {
border-radius: 5px;
display: grid;
grid-template-columns: min-content auto;
overflow: hidden;
font-size: var(--font-size-small);
}
.relay > div {
padding: 5px;
}

View File

@ -1,16 +1,13 @@
import "./Relay.css";
import { RelaySettings } from "@snort/system";
import classNames from "classnames";
import { useMemo } from "react";
import { FormattedMessage } from "react-intl";
import { useNavigate } from "react-router-dom";
import { AsyncIcon } from "@/Components/Button/AsyncIcon";
import useRelayState from "@/Feed/RelayState";
import useLogin from "@/Hooks/useLogin";
import { getRelayName } from "@/Utils";
import { RelayFavicon } from "./RelaysMetadata";
import Icon from "../Icons/Icon";
export interface RelayProps {
addr: string;
@ -19,67 +16,68 @@ export interface RelayProps {
export default function Relay(props: RelayProps) {
const navigate = useNavigate();
const { state } = useLogin(s => ({ v: s.state.version, state: s.state }));
const name = useMemo(() => getRelayName(props.addr), [props.addr]);
const connection = useRelayState(props.addr);
const relaySettings = state.relays?.find(a => a.url === props.addr)?.settings;
if (!relaySettings || !connection) return;
const settings = state.relays?.find(a => a.url === props.addr)?.settings;
if (!connection || !settings) return;
async function configure(o: RelaySettings) {
await state.updateRelay(props.addr, o);
}
const name = connection.info?.name ?? getRelayName(props.addr);
return (
<>
<div className="relay bg-dark">
<div className={classNames("flex items-center", connection.isOpen ? "bg-success" : "bg-error")}>
<RelayFavicon url={props.addr} />
</div>
<div className="flex flex-col g8">
<div>
<b>{name}</b>
</div>
{!connection?.ephemeral && (
<div className="flex g8">
<AsyncIcon
iconName="write"
iconSize={16}
className={classNames("button-icon-sm transparent", { active: relaySettings.write })}
onClick={() =>
configure({
write: !relaySettings.write,
read: relaySettings.read,
})
}
/>
<AsyncIcon
iconName="read"
iconSize={16}
className={classNames("button-icon-sm transparent", { active: relaySettings.read })}
onClick={() =>
configure({
write: relaySettings.write,
read: !relaySettings.read,
})
}
/>
<AsyncIcon
iconName="trash"
iconSize={16}
className="button-icon-sm transparent trash-icon"
onClick={() => state.removeRelay(props.addr)}
/>
<AsyncIcon
iconName="gear"
iconSize={16}
className="button-icon-sm transparent"
onClick={() => navigate(connection?.id ?? "")}
/>
</div>
<tr>
<td className="text-ellipsis" title={props.addr}>
{name.length > 20 ? <>{name.slice(0, 20)}...</> : name}
</td>
<td>
<div className="flex gap-1 items-center">
<div
className={classNames("rounded-full w-4 h-4", {
"bg-success": connection.isOpen,
"bg-error": !connection.isOpen,
})}></div>
{connection.isOpen ? (
<FormattedMessage defaultMessage="Connected" />
) : (
<FormattedMessage defaultMessage="Offline" />
)}
</div>
</div>
</>
</td>
<td>
<div className="flex gap-2 cursor-pointer select-none justify-center">
<div
className={settings.read ? "" : "text-gray"}
onClick={() =>
configure({
read: !settings.read,
write: settings.write,
})
}>
<FormattedMessage defaultMessage="Read" />
</div>
<div
className={settings.write ? "" : "text-gray"}
onClick={() =>
configure({
read: settings.read,
write: !settings.write,
})
}>
<FormattedMessage defaultMessage="Write" />
</div>
</div>
</td>
<td>
<Icon
name="trash"
className="text-gray-light cursor-pointer"
onClick={() => {
state.removeRelay(props.addr, true);
}}
/>
</td>
</tr>
);
}

View File

@ -134,9 +134,7 @@ export default function SearchBox() {
className="absolute top-full mt-2 w-full border border-neutral-200 dark:border-neutral-700 bg-white dark:bg-black shadow-lg rounded-lg z-10 overflow-hidden"
ref={resultListRef}>
<div
className={`p-2 cursor-pointer ${
activeIndex === 0 ? "bg-bg-secondary" : "bg-bg-color hover:bg-bg-secondary"
}`}
className={`p-2 cursor-pointer ${activeIndex === 0 ? "bg-secondary" : "bg-background hover:bg-secondary"}`}
onMouseEnter={() => setActiveIndex(0)}
onClick={() => navigate(`/search/${encodeURIComponent(search)}`, { state: { forceRefresh: true } })}>
<FormattedMessage defaultMessage="Search notes" />: <b>{search}</b>
@ -145,7 +143,7 @@ export default function SearchBox() {
<div
key={idx}
className={`p-2 cursor-pointer ${
activeIndex === idx + 1 ? "bg-bg-secondary" : "bg-bg-color hover:bg-bg-secondary"
activeIndex === idx + 1 ? "bg-secondary" : "bg-background hover:bg-secondary"
}`}
onMouseEnter={() => setActiveIndex(idx + 1)}>
<ProfileImage pubkey={result.pubkey} showProfileCard={false} />

View File

@ -98,7 +98,7 @@ export function SpotlightMedia(props: SpotlightMediaProps) {
{mediaEl}
<div className="absolute flex flex-row items-center gap-4 left-0 top-0 p-4">
<span
className="p-2 bg-bg-color rounded-full cursor-pointer opacity-80 hover:opacity-70"
className="p-2 bg-background rounded-full cursor-pointer opacity-80 hover:opacity-70"
onClick={props.onClose}>
<Icon name="x-close" size={24} />
</span>

View File

@ -43,7 +43,7 @@ export function SpotlightThreadModal(props: SpotlightThreadModalProps) {
onPrev={props.onPrev}
/>
</div>
<div className="hidden md:flex w-1/3 min-w-[400px] flex-shrink-0 overflow-y-auto bg-bg-color">
<div className="hidden md:flex w-1/3 min-w-[400px] flex-shrink-0 overflow-y-auto bg-background">
<Thread onBack={onBack} disableSpotlight={true} />
</div>
</div>