From 47f17fde452b5e9f0c9e96ce0e2c878dd0574b7f Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sat, 18 May 2024 16:08:35 +0300 Subject: Add support for sending gifs via Giphy Fixes #22 Closes #75 Co-authored-by: Nischay --- web/src/giphy.js | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 web/src/giphy.js (limited to 'web/src/giphy.js') diff --git a/web/src/giphy.js b/web/src/giphy.js new file mode 100644 index 0000000..16dcae3 --- /dev/null +++ b/web/src/giphy.js @@ -0,0 +1,107 @@ +import {Component, html} from "../lib/htm/preact.js"; +import * as widgetAPI from "./widget-api.js"; +import {SearchBox} from "./search-box.js"; + +const GIPHY_SEARCH_DEBOUNCE = 1000 +let GIPHY_API_KEY = "" +let GIPHY_MXC_PREFIX = "mxc://giphy.mau.dev/" + +export function giphyIsEnabled() { + return GIPHY_API_KEY !== "" +} + +export function setGiphyAPIKey(apiKey, mxcPrefix) { + GIPHY_API_KEY = apiKey + if (mxcPrefix) { + GIPHY_MXC_PREFIX = mxcPrefix + } +} + +export class GiphySearchTab extends Component { + constructor(props) { + super(props) + this.state = { + searchTerm: "", + gifs: [], + loading: false, + error: null, + } + this.handleGifClick = this.handleGifClick.bind(this) + this.searchKeyUp = this.searchKeyUp.bind(this) + this.updateGifSearchQuery = this.updateGifSearchQuery.bind(this) + this.searchTimeout = null + } + + async makeGifSearchRequest() { + try { + const resp = await fetch(`https://api.giphy.com/v1/gifs/search?q=${this.state.searchTerm}&api_key=${GIPHY_API_KEY}`) + // TODO handle error responses properly? + const data = await resp.json() + if (data.data.length === 0) { + this.setState({gifs: [], error: "No results"}) + } else { + this.setState({gifs: data.data, error: null}) + } + } catch (error) { + this.setState({error}) + } + } + + componentWillUnmount() { + clearTimeout(this.searchTimeout) + } + + searchKeyUp(event) { + if (event.key === "Enter") { + clearTimeout(this.searchTimeout) + this.makeGifSearchRequest() + } + } + + updateGifSearchQuery(event) { + this.setState({searchTerm: event.target.value}) + clearTimeout(this.searchTimeout) + this.searchTimeout = setTimeout(() => this.makeGifSearchRequest(), GIPHY_SEARCH_DEBOUNCE) + } + + handleGifClick(gif) { + widgetAPI.sendSticker({ + "body": gif.title, + "info": { + "h": gif.images.original.height, + "w": gif.images.original.width, + "size": gif.images.original.size, + "mimetype": "image/webp", + }, + "msgtype": "m.image", + "url": GIPHY_MXC_PREFIX + gif.id, + + "id": gif.id, + "filename": gif.id + ".webp", + }) + } + + render() { + // TODO display loading state? + return html` + <${SearchBox} onInput=${this.updateGifSearchQuery} onKeyUp=${this.searchKeyUp} value=${this.state.searchTerm} placeholder="Find GIFs"/> +
+
+
+ ${this.state.error} +
+
+ ${this.state.gifs.map((gif) => html` +
this.handleGifClick(gif)} data-gif-id=${gif.id}> + ${gif.title} +
+ `)} +
+ +
+
+ ` + } +} -- cgit v1.2.3