web: disable hardcoded tenor gifs and add configured fallback
All checks were successful
CI / test (push) Successful in 21s
All checks were successful
CI / test (push) Successful in 21s
This commit is contained in:
@@ -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}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user