Progress
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
.link-preview-container {
|
||||
border-radius: 0px 0px 12px 12px;
|
||||
border-radius: 12px;
|
||||
background: #151515;
|
||||
overflow: hidden;
|
||||
}
|
||||
@ -14,11 +14,26 @@
|
||||
|
||||
.link-preview-title {
|
||||
padding: 0 10px 10px 10px;
|
||||
line-height: 21px;
|
||||
}
|
||||
|
||||
.link-preview-title > h1 {
|
||||
padding: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.link-preview-container:hover .link-preview-title > h1 {
|
||||
color: var(--highlight);
|
||||
}
|
||||
|
||||
.link-preview-title > small {
|
||||
color: var(--font-secondary-color);
|
||||
font-size: small;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.link-preview-title > small.host {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.link-preview-image {
|
||||
@ -30,3 +45,7 @@
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.light .link-preview-container {
|
||||
background: #ddd;
|
||||
}
|
||||
|
@ -73,15 +73,12 @@ const LinkPreview = ({ url }: { url: string }) => {
|
||||
{preview && (
|
||||
<a href={url} onClick={e => e.stopPropagation()} target="_blank" rel="noreferrer" className="ext">
|
||||
{previewElement()}
|
||||
<p className="link-preview-title">
|
||||
{preview?.title}
|
||||
{preview?.description && (
|
||||
<>
|
||||
<br />
|
||||
<small>{preview.description.slice(0, 160)}</small>
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
<div className="link-preview-title">
|
||||
<h1>{preview?.title}</h1>
|
||||
{preview?.description && <small>{preview.description.slice(0, 160)}</small>}
|
||||
<br />
|
||||
<small className="host">{new URL(url).host}</small>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{!preview && <Spinner className="f-center" />}
|
||||
|
@ -1,47 +0,0 @@
|
||||
.live-chat {
|
||||
height: calc(100vh - 100px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.live-chat > div:nth-child(1) {
|
||||
font-size: 24px;
|
||||
line-height: 29px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.live-chat > div:nth-child(2) {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
flex-direction: column-reverse;
|
||||
margin-block-end: 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.live-chat > div:nth-child(3) {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.live-chat .message {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.live-chat .message .name {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: var(--highlight);
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.live-chat .message .avatar {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
import "./LiveChat.css";
|
||||
import { EventKind, NostrLink, TaggedNostrEvent } from "@snort/system";
|
||||
import { useUserProfile } from "@snort/system-react";
|
||||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import Textarea from "Element/Textarea";
|
||||
import { useLiveChatFeed } from "Feed/LiveChatFeed";
|
||||
import useEventPublisher from "Feed/EventPublisher";
|
||||
import { getDisplayName } from "Element/ProfileImage";
|
||||
import Avatar from "Element/Avatar";
|
||||
import AsyncButton from "Element/AsyncButton";
|
||||
import Text from "Element/Text";
|
||||
import { System } from "index";
|
||||
import { profileLink } from "SnortUtils";
|
||||
|
||||
export function LiveChat({ ev, link }: { ev: TaggedNostrEvent; link: NostrLink }) {
|
||||
const [chat, setChat] = useState("");
|
||||
const messages = useLiveChatFeed(link);
|
||||
const pub = useEventPublisher();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
async function sendChatMessage() {
|
||||
if (chat.length > 1) {
|
||||
const reply = await pub?.generic(eb => {
|
||||
return eb
|
||||
.kind(1311 as EventKind)
|
||||
.content(chat)
|
||||
.tag(["a", `${link.kind}:${link.author}:${link.id}`])
|
||||
.processContent();
|
||||
});
|
||||
if (reply) {
|
||||
console.debug(reply);
|
||||
System.BroadcastEvent(reply);
|
||||
}
|
||||
setChat("");
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div className="live-chat">
|
||||
<div>
|
||||
<FormattedMessage defaultMessage="Stream Chat" />
|
||||
</div>
|
||||
<div>
|
||||
{[...(messages.data ?? [])]
|
||||
.sort((a, b) => b.created_at - a.created_at)
|
||||
.map(a => (
|
||||
<ChatMessage ev={a} key={a.id} />
|
||||
))}
|
||||
</div>
|
||||
<div>
|
||||
<Textarea
|
||||
autoFocus={false}
|
||||
className=""
|
||||
onChange={v => setChat(v.target.value)}
|
||||
value={chat}
|
||||
onFocus={() => {}}
|
||||
placeholder={formatMessage({
|
||||
defaultMessage: "Message...",
|
||||
})}
|
||||
onKeyDown={async e => {
|
||||
if (e.code === "Enter") {
|
||||
e.preventDefault();
|
||||
await sendChatMessage();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<AsyncButton onClick={sendChatMessage}>
|
||||
<FormattedMessage defaultMessage="Send" />
|
||||
</AsyncButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ChatMessage({ ev }: { ev: TaggedNostrEvent }) {
|
||||
const profile = useUserProfile(System, ev.pubkey);
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<div className="message">
|
||||
<div className="name" onClick={() => navigate(profileLink(ev.pubkey, ev.relays))}>
|
||||
<Avatar user={profile} />
|
||||
{getDisplayName(profile, ev.pubkey)}:
|
||||
</div>
|
||||
<span>
|
||||
<Text disableMedia={true} content={ev.content} creator={ev.pubkey} tags={ev.tags} />
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -13,7 +13,7 @@ import { useWallet } from "Wallet";
|
||||
import { PaymentsCache } from "Cache";
|
||||
import { Payment } from "Db";
|
||||
import PageSpinner from "Element/PageSpinner";
|
||||
import { LiveVideoPlayer } from "Element/LiveVideoPlayer";
|
||||
|
||||
/*
|
||||
[
|
||||
"imeta",
|
||||
@ -183,9 +183,6 @@ export function MediaElement(props: MediaElementProps) {
|
||||
} else if (props.mime.startsWith("audio/")) {
|
||||
return <audio key={props.url} src={url} controls onError={() => probeFor402()} />;
|
||||
} else if (props.mime.startsWith("video/")) {
|
||||
if (props.url.endsWith(".m3u8")) {
|
||||
return <LiveVideoPlayer stream={props.url} />;
|
||||
}
|
||||
return <video key={props.url} src={url} controls onError={() => probeFor402()} />;
|
||||
} else {
|
||||
return (
|
||||
|
@ -1,5 +1,8 @@
|
||||
.note {
|
||||
min-height: 110px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.note:hover {
|
||||
@ -64,30 +67,13 @@
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.note-quote.note > .body {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.note > .body .text-frag {
|
||||
padding-left: 61px;
|
||||
}
|
||||
|
||||
.note > .body .text-frag {
|
||||
text-overflow: ellipsis;
|
||||
white-space: pre-wrap;
|
||||
word-break: normal;
|
||||
overflow-x: hidden;
|
||||
overflow-y: visible;
|
||||
}
|
||||
|
||||
.note > .body img,
|
||||
.note > .body video,
|
||||
.note > .body audio {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.note > .footer {
|
||||
padding: 16px 0 0px 61px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.note .footer .footer-reactions {
|
||||
|
@ -98,7 +98,7 @@ export default function Note(props: NoteProps) {
|
||||
const deletions = useMemo(() => getReactions(related, ev.id, EventKind.Deletion), [related]);
|
||||
const { isMuted } = useModeration();
|
||||
const isOpMuted = isMuted(ev?.pubkey);
|
||||
const { ref, inView, entry } = useInView({ triggerOnce: true });
|
||||
const { ref, inView } = useInView({ triggerOnce: true });
|
||||
const login = useLogin();
|
||||
const { pinned, bookmarked } = login;
|
||||
const publisher = useEventPublisher();
|
||||
|
@ -36,7 +36,7 @@ export function NoteContextMenu({ ev, ...props }: NosteContextMenuProps) {
|
||||
const dispatch = useDispatch();
|
||||
const { formatMessage } = useIntl();
|
||||
const login = useLogin();
|
||||
const { pinned, bookmarked, publicKey, preferences: prefs, relays } = login;
|
||||
const { pinned, bookmarked, publicKey, preferences: prefs } = login;
|
||||
const { mute, block } = useModeration();
|
||||
const publisher = useEventPublisher();
|
||||
const showReBroadcastModal = useSelector((s: RootState) => s.reBroadcast.show);
|
||||
|
@ -244,9 +244,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
||||
allocatePool={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="zaps-container">
|
||||
<ZapsSummary zaps={zaps} />
|
||||
</div>
|
||||
<ZapsSummary zaps={zaps} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { NostrEvent } from "@snort/system";
|
||||
import { FormattedMessage, FormattedNumber } from "react-intl";
|
||||
import { LNURL } from "@snort/shared";
|
||||
|
||||
import { dedupe, hexToBech32, unixNow } from "SnortUtils";
|
||||
import { dedupe, hexToBech32 } from "SnortUtils";
|
||||
import FollowListBase from "Element/FollowListBase";
|
||||
import AsyncButton from "Element/AsyncButton";
|
||||
import { useWallet } from "Wallet";
|
||||
|
@ -5,7 +5,6 @@ import { useIntl, FormattedMessage } from "react-intl";
|
||||
import { HexKey, NostrEvent, EventPublisher } from "@snort/system";
|
||||
import { LNURL, LNURLError, LNURLErrorCode, LNURLInvoice, LNURLSuccessAction } from "@snort/shared";
|
||||
|
||||
import { System } from "index";
|
||||
import { formatShort } from "Number";
|
||||
import Icon from "Icons/Icon";
|
||||
import useEventPublisher from "Feed/EventPublisher";
|
||||
|
@ -2,11 +2,9 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
overflow-x: scroll;
|
||||
-ms-overflow-style: none; /* for Internet Explorer, Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
margin-bottom: 18px;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tabs::-webkit-scrollbar {
|
||||
@ -14,22 +12,16 @@
|
||||
}
|
||||
|
||||
.tab {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
color: var(--font-tertiary-color);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 16px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
padding: 6px 12px;
|
||||
text-align: center;
|
||||
font-feature-settings: "tnum";
|
||||
}
|
||||
|
||||
.tab:not(:last-of-type) {
|
||||
margin-right: 8px;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.tab.active {
|
||||
border-color: var(--font-color);
|
||||
border-bottom: 1px solid var(--highlight);
|
||||
color: var(--font-color);
|
||||
}
|
||||
|
||||
@ -44,5 +36,5 @@
|
||||
}
|
||||
|
||||
.tab:hover {
|
||||
border-color: var(--font-color);
|
||||
border-color: var(--highlight);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ interface TabElementProps extends Omit<TabsProps, "tabs"> {
|
||||
export const TabElement = ({ t, tab, setTab }: TabElementProps) => {
|
||||
return (
|
||||
<div
|
||||
className={`tab ${tab.value === t.value ? "active" : ""} ${t.disabled ? "disabled" : ""}`}
|
||||
className={`tab${tab.value === t.value ? " active" : ""}${t.disabled ? " disabled" : ""}`}
|
||||
onClick={() => !t.disabled && setTab(t)}>
|
||||
{t.text}
|
||||
</div>
|
||||
|
@ -45,10 +45,8 @@
|
||||
}
|
||||
|
||||
.zaps-summary {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-left: 56px;
|
||||
}
|
||||
|
||||
.note.thread-root .zaps-summary {
|
||||
|
@ -5,7 +5,7 @@ import { LoginSessionType, LoginStore } from "Login";
|
||||
import { generateBip39Entropy, entropyToPrivateKey } from "nip6";
|
||||
import { getNip05PubKey } from "Pages/LoginPage";
|
||||
import { bech32ToHex } from "SnortUtils";
|
||||
import { Nip7Signer, Nip46Signer } from "@snort/system";
|
||||
import { Nip46Signer } from "@snort/system";
|
||||
|
||||
export default function useLoginHandler() {
|
||||
const { formatMessage } = useIntl();
|
||||
|
@ -28,20 +28,15 @@ header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.header-actions .btn-rnd {
|
||||
position: relative;
|
||||
margin-right: 8px;
|
||||
.header-actions .btn {
|
||||
border-radius: 0;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
@media (min-width: 520px) {
|
||||
.header-actions .btn-rnd:last-of-type {
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.header-actions .btn-rnd .has-unread {
|
||||
.header-actions .btn .has-unread {
|
||||
background: var(--highlight);
|
||||
border-radius: 100%;
|
||||
width: 9px;
|
||||
@ -52,20 +47,24 @@ header {
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.header-actions .btn-rnd .has-unread {
|
||||
.header-actions .btn .has-unread {
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.search {
|
||||
margin: 0 10px 0 10px;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
padding: 9px 16px;
|
||||
background: var(--gray-superdark);
|
||||
border-radius: 1000px;
|
||||
}
|
||||
|
||||
.search input {
|
||||
margin: 0 5px 0 5px;
|
||||
}
|
||||
|
||||
.search .btn {
|
||||
display: none;
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
font-size: 15px;
|
||||
line-height: 21px;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import "./Layout.css";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { useUserProfile } from "@snort/system-react";
|
||||
|
||||
import messages from "./messages";
|
||||
@ -113,15 +113,13 @@ export default function Layout() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{publicKey ? (
|
||||
<AccountHeader />
|
||||
) : (
|
||||
<button type="button" onClick={() => navigate("/login")}>
|
||||
<FormattedMessage {...messages.Login} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{publicKey ? (
|
||||
<AccountHeader />
|
||||
) : (
|
||||
<button type="button" onClick={() => navigate("/login")}>
|
||||
<FormattedMessage {...messages.Login} />
|
||||
</button>
|
||||
)}
|
||||
</header>
|
||||
)}
|
||||
<Outlet />
|
||||
@ -141,6 +139,7 @@ export default function Layout() {
|
||||
|
||||
const AccountHeader = () => {
|
||||
const navigate = useNavigate();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const { publicKey, latestNotification, readNotifications } = useLogin();
|
||||
const profile = useUserProfile(System, publicKey);
|
||||
@ -169,17 +168,15 @@ const AccountHeader = () => {
|
||||
|
||||
return (
|
||||
<div className="header-actions">
|
||||
<div className="btn btn-rnd" onClick={() => navigate("/wallet")}>
|
||||
<Icon name="wallet" />
|
||||
<div className="search">
|
||||
<input type="text" placeholder={formatMessage({ defaultMessage: "Search" })} className="w-max" />
|
||||
<Icon name="search" size={24} />
|
||||
</div>
|
||||
<div className="btn btn-rnd" onClick={() => navigate("/search")}>
|
||||
<Icon name="search" />
|
||||
</div>
|
||||
<div className="btn btn-rnd" onClick={() => navigate("/messages")}>
|
||||
<div className="btn" onClick={() => navigate("/messages")}>
|
||||
<Icon name="mail" size={24} />
|
||||
{unreadDms > 0 && <span className="has-unread"></span>}
|
||||
</div>
|
||||
<div className="btn btn-rnd" onClick={goToNotifications}>
|
||||
<div className="btn" onClick={goToNotifications}>
|
||||
<Icon name="bell-v2" size={24} />
|
||||
{hasNotifications && <span className="has-unread"></span>}
|
||||
</div>
|
||||
|
@ -1,31 +0,0 @@
|
||||
.live-page {
|
||||
display: grid;
|
||||
height: calc(100% - 105px);
|
||||
padding: 24px;
|
||||
grid-template-columns: auto 350px;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
@media (min-width: 2000px) {
|
||||
.live-page {
|
||||
grid-template-columns: auto 450px;
|
||||
}
|
||||
}
|
||||
|
||||
.live-page > div:nth-child(1) {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.live-page video {
|
||||
width: 100%;
|
||||
aspect-ratio: 16/9;
|
||||
}
|
||||
|
||||
.live-page .pill {
|
||||
padding: 4px 8px;
|
||||
border-radius: 20px;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--font-secondary-color);
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
import "./LivePage.css";
|
||||
import { parseNostrLink } from "@snort/system";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
import { LiveVideoPlayer } from "Element/LiveVideoPlayer";
|
||||
import { findTag, unwrap } from "SnortUtils";
|
||||
import PageSpinner from "Element/PageSpinner";
|
||||
import { LiveChat } from "Element/LiveChat";
|
||||
import useEventFeed from "Feed/EventFeed";
|
||||
import ProfilePreview from "Element/ProfilePreview";
|
||||
import AsyncButton from "Element/AsyncButton";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import Icon from "Icons/Icon";
|
||||
|
||||
export function LivePage() {
|
||||
const params = useParams();
|
||||
const link = parseNostrLink(unwrap(params.id));
|
||||
const thisEvent = useEventFeed(link);
|
||||
|
||||
if (!thisEvent.data) {
|
||||
return <PageSpinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="live-page main-content">
|
||||
<div>
|
||||
<LiveVideoPlayer stream={unwrap(findTag(thisEvent.data, "streaming"))} autoPlay={true} />
|
||||
<div className="flex">
|
||||
<div className="f-grow">
|
||||
<h1>{findTag(thisEvent.data, "title")}</h1>
|
||||
<p>{findTag(thisEvent.data, "summary")}</p>
|
||||
<div>
|
||||
{thisEvent.data?.tags
|
||||
.filter(a => a[0] === "t")
|
||||
.map(a => a[1])
|
||||
.map(a => (
|
||||
<div className="pill" key={a}>
|
||||
{a}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<ProfilePreview
|
||||
pubkey={thisEvent.data.pubkey}
|
||||
className="g10"
|
||||
options={{
|
||||
about: false,
|
||||
}}
|
||||
actions={
|
||||
<div className="flex">
|
||||
<AsyncButton onClick={() => {}}>
|
||||
<Icon name="zap" size={16} className="mr5" />
|
||||
<FormattedMessage defaultMessage="Zap" />
|
||||
</AsyncButton>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<LiveChat ev={thisEvent.data} link={link} />
|
||||
</div>
|
||||
);
|
||||
}
|
@ -35,22 +35,12 @@ export default function RootPage() {
|
||||
value: 1,
|
||||
data: "/conversations",
|
||||
},
|
||||
Global: {
|
||||
text: formatMessage(messages.Global),
|
||||
value: 2,
|
||||
data: "/global",
|
||||
},
|
||||
Discover: {
|
||||
text: formatMessage({ defaultMessage: "Discover" }),
|
||||
value: 3,
|
||||
data: "/discover",
|
||||
},
|
||||
};
|
||||
|
||||
const tagTabs = tags.item.map((t, idx) => {
|
||||
return { text: `#${t}`, value: idx + 3, data: `/tag/${t}` };
|
||||
});
|
||||
const tabs = [RootTab.Notes, RootTab.Conversations, RootTab.Global, RootTab.Discover, ...tagTabs];
|
||||
const tabs = [RootTab.Notes, RootTab.Conversations, ...tagTabs];
|
||||
const tab = useMemo(() => {
|
||||
const pTab = location.pathname.split("/").slice(-1)[0];
|
||||
|
||||
@ -66,12 +56,6 @@ export default function RootPage() {
|
||||
case "conversations": {
|
||||
return RootTab.Conversations;
|
||||
}
|
||||
case "global": {
|
||||
return RootTab.Global;
|
||||
}
|
||||
case "discover": {
|
||||
return RootTab.Discover;
|
||||
}
|
||||
default: {
|
||||
return RootTab.Notes;
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { matchSorter } from "match-sorter";
|
||||
|
||||
export default async function searchEmoji(key: string) {
|
||||
const { lib } = await import("emojilib");
|
||||
const emoji = await import("emojilib");
|
||||
/* build proper library with included name of the emoji */
|
||||
const library = Object.entries(lib).map(([name, emojiObject]) => ({
|
||||
...emojiObject,
|
||||
keywords: [name, ...emojiObject.keywords],
|
||||
name,
|
||||
const library = Object.entries(emoji).map(([emoji, keywords]) => ({
|
||||
name: keywords[0],
|
||||
keywords,
|
||||
char: emoji,
|
||||
}));
|
||||
return matchSorter(library, key, { keys: ["keywords"] });
|
||||
}
|
||||
|
@ -14,9 +14,6 @@
|
||||
--success: #2ad544;
|
||||
--warning: #ff8800;
|
||||
|
||||
/* V2 */
|
||||
--border-primary: #1a1a1a;
|
||||
|
||||
--gray-superlight: #eee;
|
||||
--gray-light: #999;
|
||||
--gray-medium: #7b7b7b;
|
||||
@ -125,12 +122,8 @@ body #root > div:not(.page) header {
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 16px 12px;
|
||||
border-bottom: 1px solid var(--border-primary);
|
||||
}
|
||||
|
||||
html.light .card {
|
||||
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.05);
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid var(--gray-superdark);
|
||||
}
|
||||
|
||||
.card .header {
|
||||
@ -247,7 +240,7 @@ button.icon:hover {
|
||||
user-select: none;
|
||||
background: none;
|
||||
border: none;
|
||||
display: inline-block;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.btn-warn {
|
||||
@ -554,7 +547,7 @@ small.xs {
|
||||
}
|
||||
|
||||
.main-content {
|
||||
border: 1px solid var(--border-primary);
|
||||
border: 1px solid var(--gray-superdark);
|
||||
}
|
||||
|
||||
.bold {
|
||||
|
@ -35,7 +35,6 @@ import DebugPage from "Pages/Debug";
|
||||
import { db } from "Db";
|
||||
import { preload, RelayMetrics, UserCache, UserRelays } from "Cache";
|
||||
import { LoginStore } from "Login";
|
||||
import { LivePage } from "Pages/LivePage";
|
||||
|
||||
/**
|
||||
* Singleton nostr system
|
||||
@ -145,10 +144,6 @@ export const router = createBrowserRouter([
|
||||
path: "/zap-pool",
|
||||
element: <ZapPoolPage />,
|
||||
},
|
||||
{
|
||||
path: "/live/:id",
|
||||
element: <LivePage />,
|
||||
},
|
||||
...NewUserRoutes,
|
||||
...WalletRoutes,
|
||||
...SubscribeRoutes,
|
||||
|
Reference in New Issue
Block a user