web: disable hardcoded tenor gifs and add configured fallback
All checks were successful
CI / test (push) Successful in 21s

This commit is contained in:
2026-03-08 13:55:24 +03:00
parent bc9d943d11
commit b6175352d0
2 changed files with 22 additions and 3 deletions

View File

@@ -31,8 +31,10 @@ const GIF_PRESETS: Array<{ name: string; url: string }> = [
const STICKER_FAVORITES_KEY = "bm_sticker_favorites_v1";
const GIF_FAVORITES_KEY = "bm_gif_favorites_v1";
const TENOR_API_KEY = "LIVDSRZULELA";
const TENOR_CLIENT_KEY = "benya_messenger_web";
const GIF_PROVIDER = (import.meta.env.VITE_GIF_PROVIDER ?? "").toLowerCase();
const TENOR_API_KEY = (import.meta.env.VITE_TENOR_API_KEY ?? "").trim();
const TENOR_CLIENT_KEY = (import.meta.env.VITE_TENOR_CLIENT_KEY ?? "benya_messenger_web").trim();
const GIF_SEARCH_ENABLED = GIF_PROVIDER === "tenor" && TENOR_API_KEY.length > 0;
function loadFavorites(key: string): Set<string> {
try {
@@ -102,6 +104,7 @@ export function MessageComposer() {
const [gifQuery, setGifQuery] = useState("");
const [gifResults, setGifResults] = useState<Array<{ name: string; url: string }>>([]);
const [gifLoading, setGifLoading] = useState(false);
const [gifSearchError, setGifSearchError] = useState<string | null>(null);
const [favoriteStickers, setFavoriteStickers] = useState<Set<string>>(() => loadFavorites(STICKER_FAVORITES_KEY));
const [favoriteGifs, setFavoriteGifs] = useState<Set<string>>(() => loadFavorites(GIF_FAVORITES_KEY));
const [captionDraft, setCaptionDraft] = useState("");
@@ -321,11 +324,19 @@ export function MessageComposer() {
if (!showGifMenu || term.length < 2) {
setGifResults([]);
setGifLoading(false);
setGifSearchError(null);
return;
}
if (!GIF_SEARCH_ENABLED) {
setGifResults([]);
setGifLoading(false);
setGifSearchError("GIF search is not configured. Using preset GIFs.");
return;
}
let cancelled = false;
const timer = window.setTimeout(() => {
setGifLoading(true);
setGifSearchError(null);
void (async () => {
try {
const params = new URLSearchParams({
@@ -338,6 +349,9 @@ export function MessageComposer() {
});
const response = await fetch(`https://tenor.googleapis.com/v2/search?${params.toString()}`);
if (!response.ok) {
if (response.status === 400) {
throw new Error("GIF provider rejected the request. Configure your own API key.");
}
throw new Error("gif search failed");
}
const data = (await response.json()) as {
@@ -355,6 +369,7 @@ export function MessageComposer() {
} catch {
if (!cancelled) {
setGifResults([]);
setGifSearchError("GIF search is unavailable right now. Using preset GIFs.");
}
} finally {
if (!cancelled) {
@@ -902,7 +917,7 @@ export function MessageComposer() {
) : null}
{showStickerMenu ? (
<div className="mb-2 rounded-xl border border-slate-700/80 bg-slate-900/95 p-2">
<div className="mb-2 rounded-xl border border-slate-700/80 bg-slate-900/95 p-2">
<div className="mb-2 flex items-center justify-between">
<p className="text-xs font-semibold text-slate-200">Stickers</p>
<div className="flex items-center gap-1">
@@ -1008,6 +1023,7 @@ export function MessageComposer() {
))}
</div>
{gifLoading ? <p className="mt-2 text-xs text-slate-400">Searching GIF...</p> : null}
{gifSearchError ? <p className="mt-2 text-xs text-amber-300">{gifSearchError}</p> : null}
</div>
) : null}