feat: PLEBHY search

This commit is contained in:
Kieran 2023-04-04 12:44:04 +01:00
parent 403ed97ad3
commit 081a07e384
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
3 changed files with 86 additions and 2 deletions

View File

@ -11,7 +11,8 @@
}
.user-item,
.emoji-item {
.emoji-item,
.gif-item {
color: var(--font-color);
background: var(--note-bg);
display: flex;
@ -22,7 +23,8 @@
}
.user-item:hover,
.emoji-item:hover {
.emoji-item:hover,
.gif-item:hover {
background: var(--gray-tertiary);
}

View File

@ -9,9 +9,11 @@ import { NostrPrefix } from "@snort/nostr";
import Avatar from "Element/Avatar";
import Nip05 from "Element/Nip05";
import { ProxyImg } from "Element/ProxyImg";
import { hexToBech32 } from "Util";
import { MetadataCache } from "Cache";
import { UserCache } from "Cache/UserCache";
import PLEBHY, { PLEBHYItem } from "Plebhy";
import messages from "./messages";
@ -44,6 +46,17 @@ const UserItem = (metadata: MetadataCache) => {
);
};
const PlebhyItem = (item: PLEBHYItem) => {
return (
<div key={item.etag} className="gif-item">
<div className="gif">
<ProxyImg src={decodeURIComponent(item.images.original.url)} width={100} />
</div>
<div className="gif-name">{item.name}</div>
</div>
);
};
interface TextareaProps {
autoFocus: boolean;
className: string;
@ -53,6 +66,7 @@ interface TextareaProps {
}
const Textarea = (props: TextareaProps) => {
const plebHy = new PLEBHY();
const { formatMessage } = useIntl();
const userDataProvider = async (token: string) => {
@ -65,6 +79,10 @@ const Textarea = (props: TextareaProps) => {
.map(({ name, char }) => ({ name, char }));
};
const plebhyDataProvider = (token: string) => {
return plebHy.search(token);
};
return (
// @ts-expect-error If anybody can figure out how to type this, please do
<ReactTextareaAutocomplete
@ -85,6 +103,11 @@ const Textarea = (props: TextareaProps) => {
component: (props: { entity: MetadataCache }) => <UserItem {...props.entity} />,
output: (item: { pubkey: string }) => `@${hexToBech32(NostrPrefix.PublicKey, item.pubkey)}`,
},
"~": {
dataProvider: plebhyDataProvider,
component: (props: { entity: PLEBHYItem }) => <PlebhyItem {...props.entity} />,
output: (item: PLEBHYItem) => decodeURIComponent(item.images.original.url),
},
}}
/>
);

View File

@ -0,0 +1,59 @@
export interface PLEBHYItem {
type: "gif" | "sticker";
sid: string;
ptag: string;
etag: string;
name: string;
title: string;
images: {
original: PLEBHYImage;
downsized: PLEBHYImage;
};
}
export interface PLEBHYImage {
url: string;
size: number;
width: number;
height: number;
}
export default class PLEBHY {
#url: string;
#key: string;
constructor(url?: string, key?: string) {
this.#url = url ?? "https://getcurrent.io";
this.#key = key ?? "8B4362ACDA28567FB47C9D7BCA952";
}
async search(term: string, limit?: number) {
const { data } = await this.#getJson<{ data: Array<PLEBHYItem> }>(
`/plebhy?apikey=${this.#key}&search=${encodeURIComponent(term)}&limit=${limit ?? 10}`
);
return data;
}
async #getJson<T>(
path: string,
method?: "GET" | string,
body?: { [key: string]: string },
headers?: { [key: string]: string }
): Promise<T> {
const rsp = await fetch(`${this.#url}${path}`, {
method: method,
body: body ? JSON.stringify(body) : undefined,
headers: {
accept: "application/json",
...(body ? { "content-type": "application/json" } : {}),
...headers,
},
});
const obj = await rsp.json();
if ("error" in obj) {
throw new Error(obj.error);
}
return obj as T;
}
}