From 031e17658c29af72066845b67f8ce81d2f46473b Mon Sep 17 00:00:00 2001 From: David Battersby Date: Wed, 10 Jun 2026 11:35:44 +0400 Subject: [PATCH] DEV: move discourse gifs to core (#40162) Moves the theme component from Discourse Gifs and brings it into core as an upcoming change. This PR also brings gifs under a single provider (Klipy). --- .../stylesheets/common/components/_index.scss | 1 + .../stylesheets/common/components/gifs.scss | 104 ++++++ app/models/site_setting.rb | 1 + config/locales/client.en.yml | 12 + config/locales/server.en.yml | 7 + config/routes.rb | 1 + config/site_settings.yml | 44 +++ .../controllers/admin-config/gifs/settings.js | 3 + .../admin/routes/admin-config/gifs.js | 8 + .../discourse/admin/routes/admin-route-map.js | 3 + .../templates/admin-config/gifs/settings.gjs | 30 ++ .../app/components/gifs/result-list.gjs | 66 ++++ .../discourse/app/components/gifs/result.gjs | 49 +++ .../discourse/app/components/modal/gifs.gjs | 338 ++++++++++++++++++ .../app/instance-initializers/enable-gifs.js | 31 ++ .../discourse/app/lib/load-minimasonry.js | 7 + .../app/lib/sidebar/admin-sidebar.js | 13 + frontend/discourse/package.json | 1 + .../tests/acceptance/modal/gifs-test.gjs | 155 ++++++++ lib/discourse_gifs.rb | 18 + lib/site_settings/label_formatter.rb | 1 + lib/svg_sprite.rb | 1 + lib/tasks/migrate_discourse_gifs_to_core.rake | 193 ++++++++++ lib/upcoming_changes.rb | 6 + .../discourse/initializers/chat-setup.js | 26 ++ .../discourse/lib/gif-pick-handler.js | 25 ++ .../unit/lib/gif-pick-handler-test.js | 123 +++++++ pnpm-lock.yaml | 8 + .../images/upcoming_changes/enable_gifs.png | Bin 0 -> 108393 bytes spec/lib/discourse_gifs_spec.rb | 31 ++ .../migrate_discourse_gifs_to_core_spec.rb | 248 +++++++++++++ .../assets/svg-icons/discourse-additional.svg | 5 + 32 files changed, 1559 insertions(+) create mode 100644 app/assets/stylesheets/common/components/gifs.scss create mode 100644 frontend/discourse/admin/controllers/admin-config/gifs/settings.js create mode 100644 frontend/discourse/admin/routes/admin-config/gifs.js create mode 100644 frontend/discourse/admin/templates/admin-config/gifs/settings.gjs create mode 100644 frontend/discourse/app/components/gifs/result-list.gjs create mode 100644 frontend/discourse/app/components/gifs/result.gjs create mode 100644 frontend/discourse/app/components/modal/gifs.gjs create mode 100644 frontend/discourse/app/instance-initializers/enable-gifs.js create mode 100644 frontend/discourse/app/lib/load-minimasonry.js create mode 100644 frontend/discourse/tests/acceptance/modal/gifs-test.gjs create mode 100644 lib/discourse_gifs.rb create mode 100644 lib/tasks/migrate_discourse_gifs_to_core.rake create mode 100644 plugins/chat/assets/javascripts/discourse/lib/gif-pick-handler.js create mode 100644 plugins/chat/test/javascripts/unit/lib/gif-pick-handler-test.js create mode 100644 public/images/upcoming_changes/enable_gifs.png create mode 100644 spec/lib/discourse_gifs_spec.rb create mode 100644 spec/tasks/migrate_discourse_gifs_to_core_spec.rb diff --git a/app/assets/stylesheets/common/components/_index.scss b/app/assets/stylesheets/common/components/_index.scss index 9190ef1c9c8..ecaa07daa6e 100644 --- a/app/assets/stylesheets/common/components/_index.scss +++ b/app/assets/stylesheets/common/components/_index.scss @@ -79,6 +79,7 @@ @import "welcome-header"; @import "notifications-tracking"; @import "emoji-picker"; +@import "gifs"; @import "d-icon-grid-picker"; @import "filter-input"; @import "filter-navigation"; diff --git a/app/assets/stylesheets/common/components/gifs.scss b/app/assets/stylesheets/common/components/gifs.scss new file mode 100644 index 00000000000..9845fbab1cb --- /dev/null +++ b/app/assets/stylesheets/common/components/gifs.scss @@ -0,0 +1,104 @@ +.gifs-modal { + .d-modal__container { + --modal-max-width: 920px; + } + + &__input { + background: var(--primary-very-low); + padding: 0.5em; + position: relative; + + > input { + width: 100%; + margin-right: 1em; + margin-bottom: 0; + } + + .spinner { + position: absolute; + right: 1.2em; + top: 0.9em; + } + } + + &__content { + overflow-y: auto; + min-width: 320px; + max-height: 65vh; + margin-top: 0.5em; + + @media screen and (width >= 768px) { + min-width: 650px; + } + + @media screen and (width >= 1200px) { + min-width: 860px; + } + } + + &__box { + .gifs-result-list { + position: relative; + + .gifs-result { + position: absolute; + } + } + + div.loading-container { + display: block; + height: 10px; + } + } + + &__categories-header { + margin: 0.5em 0; + font-size: var(--font-0); + color: var(--primary-medium); + font-weight: normal; + } + + &__loading-categories { + display: flex; + justify-content: center; + align-items: center; + min-height: 200px; + } + + &__no-results { + padding: 3em 1em; + font-size: var(--font-up-2); + color: var(--primary-low-mid); + background: var(--primary-very-low); + font-weight: bold; + text-align: center; + } +} + +.gifs-result { + &__img { + width: 100%; + height: auto; + cursor: pointer; + } + + &--category { + .gifs-result__img { + object-fit: cover; + } + } + + &__category-label { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 0.5em; + background: linear-gradient(transparent, rgb(0, 0, 0, 0.7)); + color: white; + font-weight: bold; + font-size: var(--font-down-1); + text-align: center; + cursor: pointer; + } +} diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb index 945ba9b5aba..1eb3a90302d 100644 --- a/app/models/site_setting.rb +++ b/app/models/site_setting.rb @@ -18,6 +18,7 @@ class SiteSetting < ActiveRecord::Base experimental flags fonts + gifs group_permissions interface legal diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 2948edfad05..d1e60103d02 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -3143,6 +3143,15 @@ en: confirm_publish: "Are you sure you want to publish this draft?" publishing: "Publishing Topic…" + gifs: + modal_title: "Search GIFs" + composer_title: "Insert GIF" + no_results: "Enter a keyword above to search for GIFs." + browse_categories: "Browse by category" + bad_api_key: "Klipy API key is missing or invalid. Please check the gifs API key setting." + error_rate_limit: "We have reached the GIF API rate limits. Please wait a moment and try again." + error_search_too_long: "Please shorten your search query to under 50 characters and try again." + composer: autocomplete: username_missing: "Selected autocomplete result is missing username." @@ -6614,6 +6623,9 @@ en: notifications: title: "Notifications" header_description: "Configure how notifications are managed and delivered for users, including email preferences, push notifications, mention limits, and notification consolidation" + gifs: + title: "GIFs" + header_description: "Configure the GIF picker that lets users search and insert GIFs into posts and chat messages. Site texts for the modal can be customized in customize/site_texts." onebox: title: "Onebox" header_description: "Configure how onebox previews are generated and displayed for your site" diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 9dc64a1552e..0b4d772e875 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -2664,6 +2664,13 @@ en: enable_inline_emoji_translation: "Enables translation for inline emojis (without any space or punctuation before)" emoji_deny_list: "These emoji will not be available to use in menus or shortcodes." enable_gifs: "Adds a button to easily search and insert GIFs in posts." + klipy_api_key: "Klipy API key. Required to power GIF search. Note: this key is exposed to anyone viewing your site." + klipy_file_detail: "Image format to use. WebP has smaller files that load quicker, while GIF provides compatibility with older browsers." + klipy_content_filter: "Content safety level for GIF search results." + klipy_country: "Two-letter country code for GIF search results." + klipy_locale: "Language code for GIF search results, in xx_YY format (language plus optional country)." + klipy_limit_infinite_search_results: "Limit the number of GIF results returned as users scroll, to avoid hitting API rate limits." + klipy_max_results_limit: "When 'limit infinite search results' is enabled, stop loading after this many results. Each API call retrieves 24 GIFs." approve_post_count: "The amount of posts from a new or basic user that must be approved" approve_unless_allowed_groups: "Posts created by users not in these groups must be approved. Posts created by admins and moderators are always approved." diff --git a/config/routes.rb b/config/routes.rb index 757471cf94a..b087ea1a7a6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -435,6 +435,7 @@ Discourse::Application.routes.draw do # Needed for back-end routing to work. # + get "gifs" => "site_settings#index" get "navigation" => "site_settings#index" get "notifications" => "site_settings#index" get "rate-limits" => "site_settings#index" diff --git a/config/site_settings.yml b/config/site_settings.yml index 04332efc199..feaf483f7ff 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -1636,6 +1636,50 @@ posting: default: false client: true hidden: true + area: "gifs" + upcoming_change: + status: "experimental" + impact: "feature,all_members" + learn_more_url: "https://meta.discourse.org/t/-/404829" + klipy_api_key: + default: "" + client: true + area: "gifs" + klipy_file_detail: + default: "webp" + client: true + area: "gifs" + type: enum + choices: + - webp + - gif + klipy_content_filter: + default: "high" + client: true + area: "gifs" + type: enum + choices: + - high + - medium + - low + - "off" + klipy_country: + default: "US" + client: true + area: "gifs" + klipy_locale: + default: "en_US" + client: true + area: "gifs" + klipy_limit_infinite_search_results: + default: false + client: true + area: "gifs" + klipy_max_results_limit: + default: 240 + client: true + area: "gifs" + min: 24 approve_post_count: default: 0 area: "posts_and_topics" diff --git a/frontend/discourse/admin/controllers/admin-config/gifs/settings.js b/frontend/discourse/admin/controllers/admin-config/gifs/settings.js new file mode 100644 index 00000000000..14d6b3a167d --- /dev/null +++ b/frontend/discourse/admin/controllers/admin-config/gifs/settings.js @@ -0,0 +1,3 @@ +import AdminAreaSettingsBaseController from "discourse/admin/controllers/admin-area-settings-base"; + +export default class AdminConfigGifsSettingsController extends AdminAreaSettingsBaseController {} diff --git a/frontend/discourse/admin/routes/admin-config/gifs.js b/frontend/discourse/admin/routes/admin-config/gifs.js new file mode 100644 index 00000000000..9f101ee5fad --- /dev/null +++ b/frontend/discourse/admin/routes/admin-config/gifs.js @@ -0,0 +1,8 @@ +import { i18n } from "discourse-i18n"; +import AdminConfigWithSettingsRoute from "../admin-config-with-settings-route"; + +export default class AdminConfigGifsRoute extends AdminConfigWithSettingsRoute { + titleToken() { + return i18n("admin.config.gifs.title"); + } +} diff --git a/frontend/discourse/admin/routes/admin-route-map.js b/frontend/discourse/admin/routes/admin-route-map.js index d96ad5ed6ca..82fd4d7525c 100644 --- a/frontend/discourse/admin/routes/admin-route-map.js +++ b/frontend/discourse/admin/routes/admin-route-map.js @@ -379,6 +379,9 @@ export default function () { }); this.route("logo"); this.route("fonts"); + this.route("gifs", function () { + this.route("settings", { path: "/" }); + }); this.route("adminWelcomeBanner", { path: "/welcome-banner" }); this.route("navigation", function () { this.route("settings", { path: "/" }); diff --git a/frontend/discourse/admin/templates/admin-config/gifs/settings.gjs b/frontend/discourse/admin/templates/admin-config/gifs/settings.gjs new file mode 100644 index 00000000000..ee213a3b242 --- /dev/null +++ b/frontend/discourse/admin/templates/admin-config/gifs/settings.gjs @@ -0,0 +1,30 @@ +import AdminAreaSettings from "discourse/admin/components/admin-area-settings"; +import DBreadcrumbsItem from "discourse/ui-kit/d-breadcrumbs-item"; +import DPageHeader from "discourse/ui-kit/d-page-header"; +import { i18n } from "discourse-i18n"; + +export default diff --git a/frontend/discourse/app/components/gifs/result-list.gjs b/frontend/discourse/app/components/gifs/result-list.gjs new file mode 100644 index 00000000000..a148f53f662 --- /dev/null +++ b/frontend/discourse/app/components/gifs/result-list.gjs @@ -0,0 +1,66 @@ +import Component from "@glimmer/component"; +import { action } from "@ember/object"; +import didInsert from "@ember/render-modifiers/modifiers/did-insert"; +import didUpdate from "@ember/render-modifiers/modifiers/did-update"; +import { schedule } from "@ember/runloop"; +import { service } from "@ember/service"; +import GifsResult from "discourse/components/gifs/result"; +import loadMiniMasonry from "discourse/lib/load-minimasonry"; +import DConditionalLoadingSpinner from "discourse/ui-kit/d-conditional-loading-spinner"; +import DLoadMore from "discourse/ui-kit/d-load-more"; + +export default class GifsResultList extends Component { + @service site; + + masonry; + + willDestroy() { + super.willDestroy(...arguments); + this.masonry?.destroy(); + } + + get loadMoreEnabled() { + return this.args.content?.length > 0 && (this.args.canLoadMore ?? true); + } + + @action + async setup() { + const MiniMasonry = await loadMiniMasonry(); + + this.masonry = new MiniMasonry({ + container: ".gifs-result-list", + baseWidth: this.site.mobileView ? 145 : 200, + surroundingGutter: false, + }); + + schedule("afterRender", () => this.masonry.layout()); + } + + @action + update() { + schedule("afterRender", () => this.masonry?.layout()); + } + + +} diff --git a/frontend/discourse/app/components/gifs/result.gjs b/frontend/discourse/app/components/gifs/result.gjs new file mode 100644 index 00000000000..5495ce08de7 --- /dev/null +++ b/frontend/discourse/app/components/gifs/result.gjs @@ -0,0 +1,49 @@ +import Component from "@glimmer/component"; +import { fn } from "@ember/helper"; +import { on } from "@ember/modifier"; +import { action } from "@ember/object"; +import { trustHTML } from "@ember/template"; +import dConcatClass from "discourse/ui-kit/helpers/d-concat-class"; + +export default class GifsResult extends Component { + get style() { + const { width, height } = this.args.gif; + + if (width && height) { + return trustHTML(`--aspect-ratio: ${width / height};`); + } + } + + @action + keyDown(event) { + if (event.key === "Enter") { + this.args.pick(this.args.gif); + } + } + + +} diff --git a/frontend/discourse/app/components/modal/gifs.gjs b/frontend/discourse/app/components/modal/gifs.gjs new file mode 100644 index 00000000000..fabd69961fa --- /dev/null +++ b/frontend/discourse/app/components/modal/gifs.gjs @@ -0,0 +1,338 @@ +import Component from "@glimmer/component"; +import { tracked } from "@glimmer/tracking"; +import { Input } from "@ember/component"; +import { on } from "@ember/modifier"; +import { action } from "@ember/object"; +import { service } from "@ember/service"; +import GifsResultList from "discourse/components/gifs/result-list"; +import { addUniqueValuesToArray } from "discourse/lib/array-tools"; +import discourseDebounce from "discourse/lib/debounce"; +import { autoTrackedArray } from "discourse/lib/tracked-tools"; +import DModal from "discourse/ui-kit/d-modal"; +import dLoadingSpinner from "discourse/ui-kit/helpers/d-loading-spinner"; +import { i18n } from "discourse-i18n"; + +const KLIPY_SEARCH_URL = "https://api.klipy.com/v2/search"; +const KLIPY_CATEGORIES_URL = "https://api.klipy.com/v2/categories"; +const PAGE_SIZE = 24; +const MIN_QUERY_LENGTH = 3; + +export default class GifsModal extends Component { + @service appEvents; + @service dialog; + @service siteSettings; + + @tracked categories = []; + @tracked loading = false; + @tracked loadingCategories = false; + @tracked offset = 0; + @tracked query = ""; + @tracked hasMore = true; + @autoTrackedArray currentGifs = []; + + constructor() { + super(...arguments); + this.fetchCategories(); + } + + get showingCategories() { + return this.query.length < MIN_QUERY_LENGTH && this.categories.length > 0; + } + + @action + pick(content) { + const markup = `\n![${content.title}|${content.width}x${content.height}](${content.original})\n`; + + if (this.args.model?.customPickHandler) { + this.args.model.customPickHandler(markup); + } else { + this.appEvents.trigger("composer:insert-text", markup); + } + + this.args.closeModal(); + } + + @action + async loadMore() { + if (this.loading || !this.hasMore) { + return; + } + await this.search(false); + } + + @action + refresh(event) { + this.query = event.target.value; + discourseDebounce(this, this.search, 700); + } + + @action + selectCategory(category) { + this.query = category.searchterm; + this.search(true, true); + } + + async fetchCategories() { + if (this.siteSettings.klipy_api_key === "") { + return; + } + + this.loadingCategories = true; + + try { + const params = { + key: this.siteSettings.klipy_api_key, + country: this.siteSettings.klipy_country, + locale: this.siteSettings.klipy_locale, + type: "featured", + contentfilter: this.siteSettings.klipy_content_filter, + }; + + const response = await fetch( + `${KLIPY_CATEGORIES_URL}?${new URLSearchParams(params)}` + ); + + if (this.isDestroying || this.isDestroyed) { + return; + } + + if (!response.ok) { + return; + } + + const data = await response.json(); + + if (this.isDestroying || this.isDestroyed) { + return; + } + + this.categories = await this.loadCategoryDimensions(data.tags || []); + } catch { + // Silently fail - user can still search manually + } finally { + this.loadingCategories = false; + } + } + + async loadCategoryDimensions(tags) { + return Promise.all( + tags.map( + (tag) => + new Promise((resolve) => { + const img = new Image(); + const finish = (width, height) => { + resolve({ + title: tag.name, + preview: tag.image, + original: tag.image, + width, + height, + isCategory: true, + searchterm: tag.searchterm, + }); + }; + img.onload = () => finish(img.naturalWidth, img.naturalHeight); + img.onerror = () => finish(200, 150); + img.src = tag.image; + }) + ) + ); + } + + async search(clearResults = true, skipLengthCheck = false) { + if (clearResults) { + this.currentGifs = []; + this.offset = 0; + this.hasMore = true; + } + + const meetsLengthRequirement = + skipLengthCheck || this.query.length >= MIN_QUERY_LENGTH; + + if (!meetsLengthRequirement) { + return; + } + + const limitReached = + this.siteSettings.klipy_limit_infinite_search_results && + this.currentGifs.length >= this.siteSettings.klipy_max_results_limit; + + if (limitReached) { + this.hasMore = false; + return; + } + + this.loading = true; + + try { + if (this.siteSettings.klipy_api_key === "") { + throw new Error(i18n("gifs.bad_api_key")); + } + + const response = await fetch(this.getEndpoint(this.query, this.offset)); + + if (this.isDestroying || this.isDestroyed) { + return; + } + + if (!response.ok) { + throw new Error(await this.errorFromResponse(response)); + } + + const data = await response.json(); + if (this.isDestroying || this.isDestroyed) { + return; + } + + const fileDetail = this.siteSettings.klipy_file_detail; + const images = data.results.map((gif) => { + const mediaFormat = gif.media_formats[fileDetail]; + return { + title: gif.title, + preview: mediaFormat.url, + original: mediaFormat.url, + width: mediaFormat.dims[0], + height: mediaFormat.dims[1], + }; + }); + + if (data.next === "" || data.next == null) { + this.hasMore = false; + } else { + this.offset = data.next; + } + addUniqueValuesToArray(this.currentGifs, images); + } catch (error) { + this.dialog.alert({ message: error.message ?? error }); + } finally { + this.loading = false; + } + } + + async errorFromResponse(response) { + if (response.status === 429) { + return i18n("gifs.error_rate_limit"); + } + if (response.status === 414) { + return i18n("gifs.error_search_too_long"); + } + if (response.status === 403 || response.status === 401) { + return i18n("gifs.bad_api_key"); + } + + const body = await response.text().catch(() => ""); + + let parsed; + try { + parsed = body && JSON.parse(body); + } catch { + parsed = null; + } + + const message = this.extractErrorMessage(parsed) ?? body ?? "unknown error"; + + if (/api key is invalid|API_KEY_INVALID/i.test(message)) { + return i18n("gifs.bad_api_key"); + } + + return `Klipy status ${response.status}: ${this.redactApiKey(message)}`; + } + + extractErrorMessage(parsed) { + if (!parsed) { + return null; + } + // Klipy: { result: false, errors: { message: ["..."] } } + const klipyMessages = parsed.errors?.message; + if (Array.isArray(klipyMessages) && klipyMessages.length) { + return klipyMessages[0]; + } + // Google-style: { error: { message, details: [{ reason }] } } + return ( + parsed.error?.message ?? + (typeof parsed.error === "string" ? parsed.error : null) ?? + parsed.message ?? + null + ); + } + + redactApiKey(message) { + const apiKey = this.siteSettings.klipy_api_key; + if (!apiKey || typeof message !== "string") { + return message; + } + return message.replaceAll(apiKey, "[redacted]"); + } + + getEndpoint(query, offset) { + const params = { + key: this.siteSettings.klipy_api_key, + q: query, + country: this.siteSettings.klipy_country, + locale: this.siteSettings.klipy_locale, + contentfilter: this.siteSettings.klipy_content_filter, + media_filter: this.siteSettings.klipy_file_detail, + limit: PAGE_SIZE, + pos: offset, + }; + return `${KLIPY_SEARCH_URL}?${new URLSearchParams(params)}`; + } + + +} diff --git a/frontend/discourse/app/instance-initializers/enable-gifs.js b/frontend/discourse/app/instance-initializers/enable-gifs.js new file mode 100644 index 00000000000..411c96748fa --- /dev/null +++ b/frontend/discourse/app/instance-initializers/enable-gifs.js @@ -0,0 +1,31 @@ +import GifsModal from "discourse/components/modal/gifs"; +import { withPluginApi } from "discourse/lib/plugin-api"; + +export default { + initialize(owner) { + const siteSettings = owner.lookup("service:site-settings"); + + if (!siteSettings.enable_gifs) { + return; + } + + withPluginApi((api) => { + api.onToolbarCreate((toolbar) => { + if (!toolbar.context?.composerEvents) { + return; + } + + toolbar.addButton({ + id: "gifs", + group: "extras", + icon: "gif", + title: "gifs.composer_title", + sendAction: () => { + const modal = api.container.lookup("service:modal"); + modal.show(GifsModal); + }, + }); + }); + }); + }, +}; diff --git a/frontend/discourse/app/lib/load-minimasonry.js b/frontend/discourse/app/lib/load-minimasonry.js new file mode 100644 index 00000000000..ba1a6bd4982 --- /dev/null +++ b/frontend/discourse/app/lib/load-minimasonry.js @@ -0,0 +1,7 @@ +import { waitForPromise } from "@ember/test-waiters"; + +export default async function loadMiniMasonry() { + const promise = import("minimasonry"); + waitForPromise(promise); + return (await promise).default; +} diff --git a/frontend/discourse/app/lib/sidebar/admin-sidebar.js b/frontend/discourse/app/lib/sidebar/admin-sidebar.js index b531a380e5f..00554fd3b50 100644 --- a/frontend/discourse/app/lib/sidebar/admin-sidebar.js +++ b/frontend/discourse/app/lib/sidebar/admin-sidebar.js @@ -417,6 +417,19 @@ export default class AdminSidebarPanel extends BaseCustomSidebarPanel { ]); } + if (siteSettings.enable_gifs) { + this.adminNavManager.amendLinksToSection("appearance", [ + { + name: "admin_gifs", + route: "adminConfig.gifs.settings", + label: "admin.config.gifs.title", + description: "admin.config.gifs.header_description", + icon: "gif", + settings_area: "gifs", + }, + ]); + } + this.adminNavManager.amendLinksToSection("root", [ { name: "admin_upcoming_changes", diff --git a/frontend/discourse/package.json b/frontend/discourse/package.json index 455cf31f75d..44d3d71ee80 100644 --- a/frontend/discourse/package.json +++ b/frontend/discourse/package.json @@ -71,6 +71,7 @@ "highlight.js": "11.11.1", "immer": "^11.1.8", "jspreadsheet-ce": "^5.0.4", + "minimasonry": "^1.3.2", "moment": "2.30.1", "moment-timezone": "0.6.2", "morphlex": "^1.0.5", diff --git a/frontend/discourse/tests/acceptance/modal/gifs-test.gjs b/frontend/discourse/tests/acceptance/modal/gifs-test.gjs new file mode 100644 index 00000000000..dbd2c2ea5f3 --- /dev/null +++ b/frontend/discourse/tests/acceptance/modal/gifs-test.gjs @@ -0,0 +1,155 @@ +import { getOwner } from "@ember/owner"; +import { click, fillIn, settled, visit } from "@ember/test-helpers"; +import { test } from "qunit"; +import sinon from "sinon"; +import GifsModal from "discourse/components/modal/gifs"; +import { acceptance } from "discourse/tests/helpers/qunit-helpers"; + +function fetchResponse(body) { + return { ok: true, status: 200, json: async () => body }; +} + +function categoriesResponse(tags = []) { + return fetchResponse({ tags }); +} + +function searchResponse({ results = [], next = "" } = {}) { + return fetchResponse({ results, next }); +} + +function gif(title, url = "https://example.com/g.gif") { + return { + title, + media_formats: { gif: { url, dims: [200, 150] } }, + }; +} + +acceptance("Modal - GIFs", function (needs) { + needs.user(); + needs.settings({ + enable_gifs: true, + klipy_api_key: "test-key", + klipy_country: "US", + klipy_locale: "en_US", + klipy_content_filter: "high", + klipy_file_detail: "gif", + klipy_limit_infinite_search_results: false, + klipy_max_results_limit: 100, + }); + + let fetchStub; + + needs.hooks.beforeEach(function () { + fetchStub = sinon.stub(window, "fetch"); + }); + + test("fetches categories when opened", async function (assert) { + fetchStub.resolves(categoriesResponse()); + + await visit("/"); + const modalService = getOwner(this).lookup("service:modal"); + modalService.show(GifsModal); + await settled(); + + assert.dom(".gifs-modal").exists("renders the modal"); + + const categoriesCall = fetchStub + .getCalls() + .find((c) => c.args[0].includes("/v2/categories")); + assert.notStrictEqual( + categoriesCall, + undefined, + "called the Klipy categories endpoint" + ); + assert.true( + categoriesCall.args[0].includes("key=test-key"), + "passes api key in query" + ); + }); + + test("search triggers a Klipy fetch with the query", async function (assert) { + fetchStub.callsFake(async (url) => { + if (url.includes("/v2/categories")) { + return categoriesResponse(); + } + return searchResponse({ results: [gif("a hello gif")] }); + }); + + await visit("/"); + const modalService = getOwner(this).lookup("service:modal"); + modalService.show(GifsModal); + await settled(); + + await fillIn(".gifs-modal input[name=query]", "hello"); + + const searchCall = fetchStub + .getCalls() + .find((c) => c.args[0].includes("/v2/search")); + + assert.notStrictEqual( + searchCall, + undefined, + "called the Klipy search endpoint" + ); + assert.true(searchCall.args[0].includes("q=hello"), "passes the query"); + assert + .dom(".gifs-modal .gifs-result") + .exists({ count: 1 }, "renders the result returned by Klipy"); + }); + + test("picking a result invokes customPickHandler with markup", async function (assert) { + fetchStub.callsFake(async (url) => { + if (url.includes("/v2/categories")) { + return categoriesResponse(); + } + return searchResponse({ + results: [gif("party parrot", "https://klipy.example/parrot.gif")], + }); + }); + + let receivedMarkup; + await visit("/"); + const modalService = getOwner(this).lookup("service:modal"); + const closed = modalService.show(GifsModal, { + model: { + customPickHandler: (markup) => { + receivedMarkup = markup; + }, + }, + }); + + await settled(); + await fillIn(".gifs-modal input[name=query]", "party"); + + await click(".gifs-modal .gifs-result"); + + assert.strictEqual( + receivedMarkup, + "\n![party parrot|200x150](https://klipy.example/parrot.gif)\n", + "invokes customPickHandler with the gif markup" + ); + assert.dom(".gifs-modal").doesNotExist("closes the modal after pick"); + + await closed; + }); + + test("renders a no results state when Klipy returns nothing", async function (assert) { + fetchStub.callsFake(async (url) => { + if (url.includes("/v2/categories")) { + return categoriesResponse(); + } + return searchResponse({ results: [], next: "" }); + }); + + await visit("/"); + const modalService = getOwner(this).lookup("service:modal"); + modalService.show(GifsModal); + await settled(); + + await fillIn(".gifs-modal input[name=query]", "nothingmatches"); + + assert + .dom(".gifs-modal .gifs-modal__no-results") + .exists("renders the no-results message"); + }); +}); diff --git a/lib/discourse_gifs.rb b/lib/discourse_gifs.rb new file mode 100644 index 00000000000..7284f05b421 --- /dev/null +++ b/lib/discourse_gifs.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module DiscourseGifs + REPO_URL = "https://github.com/discourse/discourse-gifs" + COMPONENT_NAME = "discourse-gifs" + REMOTE_URLS = [REPO_URL, "#{REPO_URL}.git"].freeze + + def self.component_installed? + component_scope.exists? + end + + def self.component_scope + Theme + .joins(:remote_theme) + .where(component: true) + .where(remote_themes: { remote_url: REMOTE_URLS }) + end +end diff --git a/lib/site_settings/label_formatter.rb b/lib/site_settings/label_formatter.rb index 4570c9a4b04..27970f0f019 100644 --- a/lib/site_settings/label_formatter.rb +++ b/lib/site_settings/label_formatter.rb @@ -28,6 +28,7 @@ module SiteSettings fg ga gb + gif gpu gpt gtm diff --git a/lib/svg_sprite.rb b/lib/svg_sprite.rb index 630fa147ede..4756f74ddda 100644 --- a/lib/svg_sprite.rb +++ b/lib/svg_sprite.rb @@ -182,6 +182,7 @@ module SvgSprite forward-step gavel gear + gif gift globe grip-lines diff --git a/lib/tasks/migrate_discourse_gifs_to_core.rake b/lib/tasks/migrate_discourse_gifs_to_core.rake new file mode 100644 index 00000000000..1b44b197256 --- /dev/null +++ b/lib/tasks/migrate_discourse_gifs_to_core.rake @@ -0,0 +1,193 @@ +# frozen_string_literal: true + +require "discourse_gifs" + +module DiscourseGifsMigration + # Mapping from each TC provider's theme settings to core site settings. + # `value:` is an optional lookup table for non-1:1 translations. + PROVIDER_MAPPINGS = { + "giphy" => { + "giphy_file_format" => { + name: "klipy_file_detail", + }, + "giphy_content_rating" => { + name: "klipy_content_filter", + value: { + "g" => "high", + "pg" => "medium", + "pg-13" => "low", + "r" => "low", + }, + }, + "giphy_locale" => { + name: "klipy_locale", + }, + }, + "tenor" => { + "tenor_file_detail" => { + name: "klipy_file_detail", + value: { + "mediumgif" => "webp", + "tinygif" => "webp", + "nanogif" => "webp", + "gif" => "gif", + }, + }, + "tenor_content_filter" => { + name: "klipy_content_filter", + }, + "tenor_country" => { + name: "klipy_country", + }, + "tenor_locale" => { + name: "klipy_locale", + }, + }, + "klipy" => { + "klipy_api_key" => { + name: "klipy_api_key", + }, + "klipy_file_detail" => { + name: "klipy_file_detail", + }, + "klipy_content_filter" => { + name: "klipy_content_filter", + }, + "klipy_country" => { + name: "klipy_country", + }, + "klipy_locale" => { + name: "klipy_locale", + }, + }, + }.freeze + + # Settings the TC applied regardless of provider — migrated for everyone. + SHARED_MAPPINGS = { + "limit_infinite_search_results" => { + name: "klipy_limit_infinite_search_results", + }, + "max_results_limit" => { + name: "klipy_max_results_limit", + }, + }.freeze + + module_function + + def find_components + if ENV["RAILS_DB"].present? + db = ENV["RAILS_DB"] + + if !RailsMultisite::ConnectionManagement.has_db?(db) + default_db = RailsMultisite::ConnectionManagement::DEFAULT + puts "\e[31m✗ Database \e[1;101m[#{db}]\e[0m \e[31mnot found\e[0m" + puts "Using default database instead: \e[1;104m[#{default_db}]\e[0m\n\n" + db = default_db + end + + RailsMultisite::ConnectionManagement.establish_connection(db: db) + Array(find_component_in_db(db)) + else + [].tap do |components| + RailsMultisite::ConnectionManagement.each_connection do |db| + components.concat(Array(find_component_in_db(db))) + end + end + end + end + + def find_component_in_db(db) + puts "Accessing database: \e[1;104m[#{db}]\e[0m" + puts " Searching for #{DiscourseGifs::COMPONENT_NAME} theme component..." + + themes = + RemoteTheme + .where(remote_url: DiscourseGifs::REMOTE_URLS) + .includes(theme: :theme_settings) + .map(&:theme) + + if themes.length > 1 + puts " \e[33mMultiple (#{themes.length}) #{DiscourseGifs::COMPONENT_NAME} components found:\e[0m" + themes.each { |t| puts " - #{t.name} (ID: #{t.id})" } + puts " \e[33mInstall a single instance before running this task.\e[0m" + return nil + elsif themes.one? + theme = themes.first + puts " \e[1;34m✓ Found: \e[1m#{theme.name} (ID: #{theme.id})\e[0m" + return theme + end + + puts " \e[33m✗ Not found.\e[0m" + nil + end + + def migrate_component(theme, enable_gifs:) + puts "\n Migrating settings for \e[1m#{theme.name} (ID: #{theme.id})\e[0m..." + + overrides = theme.theme_settings.each_with_object({}) { |ts, h| h[ts.name] = ts.value } + # TC's default api_provider is "giphy" — applies to any site that never picked one. + provider = overrides["api_provider"].presence || "giphy" + puts " Detected provider: \e[1m#{provider}\e[0m" + + mapping = (PROVIDER_MAPPINGS[provider] || {}).merge(SHARED_MAPPINGS) + + migrated = 0 + errors = [] + + mapping.each do |tc_name, target| + raw = overrides[tc_name] + next if raw.blank? + + new_value = target[:value] ? (target[:value][raw] || raw) : raw + + begin + SiteSetting.set_and_log( + target[:name], + new_value, + Discourse.system_user, + "Migrated from #{DiscourseGifs::COMPONENT_NAME} theme component", + ) + puts " - \e[0;31m#{tc_name}: #{raw}\e[0m => \e[0;32m#{target[:name]}: #{new_value}\e[0m" + migrated += 1 + rescue StandardError => e + errors << e + puts " \e[31m- failed to migrate '#{tc_name}': \e[1m#{e.message}\e[0m" + end + end + + if enable_gifs + begin + SiteSetting.set_and_log( + :enable_gifs, + true, + Discourse.system_user, + "Migrated from #{DiscourseGifs::COMPONENT_NAME} theme component", + ) + puts " - \e[0;32menable_gifs: true\e[0m (auto-enabled per task argument)" + migrated += 1 + rescue StandardError => e + errors << e + puts " \e[31m- failed to enable enable_gifs: \e[1m#{e.message}\e[0m" + end + end + + puts " \e[1;32m✓ Migrated #{migrated} setting#{"s" if migrated != 1}\e[0m" + puts " \e[1;31m#{errors.size} error#{"s" if errors.size != 1}\e[0m" if errors.any? + end +end + +desc "Migrate #{DiscourseGifs::COMPONENT_NAME} theme component settings to core site settings. " \ + "Set ENABLE_GIFS=1 to also flip enable_gifs to true after migration." +task "themes:discourse_gifs:migrate" => :environment do + enable_gifs = %w[true yes 1].include?(ENV["ENABLE_GIFS"].to_s.strip.downcase) + + components = DiscourseGifsMigration.find_components + + if components.any? + puts "\nMigrating settings..." + puts "---------------------" + components.each { |c| DiscourseGifsMigration.migrate_component(c, enable_gifs: enable_gifs) } + else + puts "\nNo #{DiscourseGifs::COMPONENT_NAME} theme component found. Nothing to migrate." + end +end diff --git a/lib/upcoming_changes.rb b/lib/upcoming_changes.rb index e4d7da4d81d..2a843cf1245 100644 --- a/lib/upcoming_changes.rb +++ b/lib/upcoming_changes.rb @@ -26,6 +26,12 @@ module UpcomingChanges def self.should_display_enable_horizon_high_context_topic_cards? Themes::Action::HorizonHighContextTopicCardsToggled.should_display_upcoming_change? end + + # Sites already running the discourse-gifs theme component will have their + # configuration migrated separately so they don't need to opt in via the upcoming change. + def self.should_display_enable_gifs? + !DiscourseGifs.component_installed? + end end def self.user_enabled_reasons diff --git a/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js b/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js index 9eb385e6468..b495479f55d 100644 --- a/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js +++ b/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js @@ -1,6 +1,7 @@ import { setOwner } from "@ember/owner"; import { service } from "@ember/service"; import EmojiPickerDetached from "discourse/components/emoji-picker/detached"; +import GifsModal from "discourse/components/modal/gifs"; import { bind } from "discourse/lib/decorators"; import EmbedMode from "discourse/lib/embed-mode"; import { number } from "discourse/lib/formatter"; @@ -8,6 +9,7 @@ import { replaceIcon } from "discourse/lib/icon-library"; import { withPluginApi } from "discourse/lib/plugin-api"; import { i18n } from "discourse-i18n"; import { clearChatComposerButtons } from "discourse/plugins/chat/discourse/lib/chat-composer-buttons"; +import { buildGifPickHandler } from "discourse/plugins/chat/discourse/lib/gif-pick-handler"; import ChannelHashtagType from "discourse/plugins/chat/discourse/lib/hashtag-types/channel"; import richEditorExtension from "../../lib/rich-editor-extension"; import ChatHeaderIcon from "../components/chat/header/icon"; @@ -102,6 +104,30 @@ class ChatSetupInit { }, }); + if (this.siteSettings.enable_gifs) { + api.registerChatComposerButton({ + id: "gifs", + label: "gifs.composer_title", + icon: "gif", + position: "dropdown", + action(context) { + const modal = owner.lookup("service:modal"); + const currentUser = owner.lookup("service:current-user"); + + modal.show(GifsModal, { + model: { + customPickHandler: buildGifPickHandler({ + api, + draft: this.draft, + isThread: context === "thread", + currentUser, + }), + }, + }); + }, + }); + } + if (this.siteSettings.discourse_local_dates_enabled) { api.registerChatComposerButton({ label: "discourse_local_dates.title", diff --git a/plugins/chat/assets/javascripts/discourse/lib/gif-pick-handler.js b/plugins/chat/assets/javascripts/discourse/lib/gif-pick-handler.js new file mode 100644 index 00000000000..1a016f074fe --- /dev/null +++ b/plugins/chat/assets/javascripts/discourse/lib/gif-pick-handler.js @@ -0,0 +1,25 @@ +// Builds the customPickHandler passed to GifsModal from the chat composer's +// GIF button. Extracted so the send + draft-reset interplay can be unit tested. +// +// The returned handler: +// - Sends the picked GIF as a chat message in the active context (channel or +// thread, with inReplyTo when replying in a channel). +// - On a successful send, resets the *correct* draft (thread when in a +// thread context, channel otherwise) for the given user. +// - On send failure, leaves the draft intact so the user can retry. +export function buildGifPickHandler({ api, draft, isThread, currentUser }) { + const draftHolder = isThread ? draft.thread : draft.channel; + + return async (message) => { + try { + await api.sendChatMessage(draft.channel.id, { + message, + threadId: isThread ? draft.thread?.id : null, + inReplyToId: !isThread ? draft.inReplyTo?.id : null, + }); + } catch { + return; + } + draftHolder?.resetDraft?.(currentUser); + }; +} diff --git a/plugins/chat/test/javascripts/unit/lib/gif-pick-handler-test.js b/plugins/chat/test/javascripts/unit/lib/gif-pick-handler-test.js new file mode 100644 index 00000000000..28818908de9 --- /dev/null +++ b/plugins/chat/test/javascripts/unit/lib/gif-pick-handler-test.js @@ -0,0 +1,123 @@ +import { module, test } from "qunit"; +import sinon from "sinon"; +import { buildGifPickHandler } from "discourse/plugins/chat/discourse/lib/gif-pick-handler"; + +function setupDraft() { + const channelDraft = { resetDraft: sinon.spy() }; + const threadDraft = { resetDraft: sinon.spy() }; + return { + draft: { + channel: { id: 7, resetDraft: channelDraft.resetDraft }, + thread: { id: 13, resetDraft: threadDraft.resetDraft }, + inReplyTo: { id: 42 }, + }, + channelDraft, + threadDraft, + }; +} + +module("Unit | Lib | buildGifPickHandler", function () { + test("sends a channel message with inReplyToId when not in a thread", async function (assert) { + const api = { sendChatMessage: sinon.stub().resolves() }; + const { draft } = setupDraft(); + const currentUser = { id: 1 }; + + const handler = buildGifPickHandler({ + api, + draft, + isThread: false, + currentUser, + }); + + await handler("![g](u)"); + + assert.true(api.sendChatMessage.calledOnce); + assert.deepEqual(api.sendChatMessage.firstCall.args, [ + 7, + { message: "![g](u)", threadId: null, inReplyToId: 42 }, + ]); + }); + + test("sends a thread message with threadId when in a thread", async function (assert) { + const api = { sendChatMessage: sinon.stub().resolves() }; + const { draft } = setupDraft(); + + const handler = buildGifPickHandler({ + api, + draft, + isThread: true, + currentUser: { id: 1 }, + }); + + await handler("![g](u)"); + + assert.deepEqual(api.sendChatMessage.firstCall.args, [ + 7, + { message: "![g](u)", threadId: 13, inReplyToId: null }, + ]); + }); + + test("resets the channel draft on a successful channel-context send", async function (assert) { + const api = { sendChatMessage: sinon.stub().resolves() }; + const { draft, channelDraft, threadDraft } = setupDraft(); + const currentUser = { id: 1 }; + + const handler = buildGifPickHandler({ + api, + draft, + isThread: false, + currentUser, + }); + + await handler("![g](u)"); + + assert.true( + channelDraft.resetDraft.calledOnceWith(currentUser), + "channel draft is reset" + ); + assert.false(threadDraft.resetDraft.called, "thread draft is left alone"); + }); + + test("resets the thread draft on a successful thread-context send", async function (assert) { + const api = { sendChatMessage: sinon.stub().resolves() }; + const { draft, channelDraft, threadDraft } = setupDraft(); + const currentUser = { id: 1 }; + + const handler = buildGifPickHandler({ + api, + draft, + isThread: true, + currentUser, + }); + + await handler("![g](u)"); + + assert.true( + threadDraft.resetDraft.calledOnceWith(currentUser), + "thread draft is reset" + ); + assert.false( + channelDraft.resetDraft.called, + "channel draft is left alone in thread context" + ); + }); + + test("does not reset the draft when sendChatMessage rejects", async function (assert) { + const api = { sendChatMessage: sinon.stub().rejects(new Error("nope")) }; + const { draft, channelDraft } = setupDraft(); + + const handler = buildGifPickHandler({ + api, + draft, + isThread: false, + currentUser: { id: 1 }, + }); + + await handler("![g](u)"); + + assert.false( + channelDraft.resetDraft.called, + "draft preserved so the user can retry" + ); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 29d6cf55eb7..2ac87f8c772 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -333,6 +333,9 @@ importers: jspreadsheet-ce: specifier: ^5.0.4 version: 5.0.4 + minimasonry: + specifier: ^1.3.2 + version: 1.3.2 moment: specifier: 2.30.1 version: 2.30.1 @@ -5894,6 +5897,9 @@ packages: peerDependencies: webpack: ^5.0.0 + minimasonry@1.3.2: + resolution: {integrity: sha512-ygvf5JIR4NT1LbM6o8z1oz1icTkta72gXKwidvSqIVxuzVd/P21UI0Wbq1J+MStAu50Vvr8qWYNSz1W4uycqMQ==} + minimatch@10.2.5: resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} engines: {node: 18 || 20 || >=22} @@ -14298,6 +14304,8 @@ snapshots: schema-utils: 4.3.3 tapable: 2.3.2 + minimasonry@1.3.2: {} + minimatch@10.2.5: dependencies: brace-expansion: 5.0.6 diff --git a/public/images/upcoming_changes/enable_gifs.png b/public/images/upcoming_changes/enable_gifs.png new file mode 100644 index 0000000000000000000000000000000000000000..aebac7cae5653891711dade534ee74164990b5ac GIT binary patch literal 108393 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 "high", "pg" => "medium", "pg-13" => "low", "r" => "low" } + + rating_mappings.each do |giphy_rating, expected_filter| + component.theme_settings.destroy_all + add_overrides(component, api_provider: "giphy", giphy_content_rating: giphy_rating) + + run_migration(component) + + expect(SiteSetting.klipy_content_filter).to eq(expected_filter), + "expected giphy '#{giphy_rating}' to map to '#{expected_filter}', got '#{SiteSetting.klipy_content_filter}'" + end + end + + it "passes the Giphy locale through unchanged" do + add_overrides(component, api_provider: "giphy", giphy_locale: "fr") + + run_migration(component) + + expect(SiteSetting.klipy_locale).to eq("fr") + end + + it "does not migrate the Giphy API key into klipy_api_key" do + add_overrides(component, api_provider: "giphy", giphy_api_key: "old-giphy-key") + original_api_key = SiteSetting.klipy_api_key + + run_migration(component) + + expect(SiteSetting.klipy_api_key).to eq(original_api_key) + end + end + + context "when the TC was configured for Tenor" do + it "maps every Tenor file detail to the matching Klipy file detail", :aggregate_failures do + detail_mappings = { + "mediumgif" => "webp", + "tinygif" => "webp", + "nanogif" => "webp", + "gif" => "gif", + } + + detail_mappings.each do |tenor_detail, expected_klipy| + component.theme_settings.destroy_all + add_overrides(component, api_provider: "tenor", tenor_file_detail: tenor_detail) + + run_migration(component) + + expect(SiteSetting.klipy_file_detail).to eq(expected_klipy), + "expected tenor '#{tenor_detail}' to map to '#{expected_klipy}', got '#{SiteSetting.klipy_file_detail}'" + end + end + + it "passes Tenor content filter, country and locale through unchanged", :aggregate_failures do + add_overrides( + component, + api_provider: "tenor", + tenor_content_filter: "medium", + tenor_country: "GB", + tenor_locale: "en_GB", + ) + + run_migration(component) + + expect(SiteSetting.klipy_content_filter).to eq("medium") + expect(SiteSetting.klipy_country).to eq("GB") + expect(SiteSetting.klipy_locale).to eq("en_GB") + end + + it "does not migrate the Tenor API key into klipy_api_key" do + add_overrides(component, api_provider: "tenor", tenor_api_key: "old-tenor-key") + original_api_key = SiteSetting.klipy_api_key + + run_migration(component) + + expect(SiteSetting.klipy_api_key).to eq(original_api_key) + end + end + + context "when the TC was already configured for Klipy" do + it "copies every Klipy setting through, including the API key", :aggregate_failures do + add_overrides( + component, + api_provider: "klipy", + klipy_api_key: "existing-klipy-key", + klipy_file_detail: "gif", + klipy_content_filter: "low", + klipy_country: "DE", + klipy_locale: "de_DE", + ) + + run_migration(component) + + expect(SiteSetting.klipy_api_key).to eq("existing-klipy-key") + expect(SiteSetting.klipy_file_detail).to eq("gif") + expect(SiteSetting.klipy_content_filter).to eq("low") + expect(SiteSetting.klipy_country).to eq("DE") + expect(SiteSetting.klipy_locale).to eq("de_DE") + end + end + + context "with shared settings that apply regardless of provider" do + it "migrates limit_infinite_search_results" do + add_overrides(component, api_provider: "tenor", limit_infinite_search_results: "true") + + run_migration(component) + + expect(SiteSetting.klipy_limit_infinite_search_results).to eq(true) + end + + it "migrates max_results_limit" do + add_overrides(component, api_provider: "giphy", max_results_limit: "96") + + run_migration(component) + + expect(SiteSetting.klipy_max_results_limit).to eq(96) + end + end + + context "when api_provider is not set in theme settings" do + it "defaults to giphy and applies giphy mappings" do + add_overrides(component, giphy_content_rating: "pg") + + run_migration(component) + + expect(SiteSetting.klipy_content_filter).to eq("medium") + end + end + + context "with the enable_gifs keyword" do + it "leaves enable_gifs untouched by default" do + SiteSetting.enable_gifs = false + add_overrides(component, api_provider: "klipy", klipy_api_key: "key") + + run_migration(component, enable_gifs: false) + + expect(SiteSetting.enable_gifs).to eq(false) + end + + it "flips enable_gifs to true when enable_gifs: true is passed" do + SiteSetting.enable_gifs = false + add_overrides(component, api_provider: "klipy", klipy_api_key: "key") + + run_migration(component, enable_gifs: true) + + expect(SiteSetting.enable_gifs).to eq(true) + end + end + + it "records migrated settings in the staff action log with an audit reason" do + add_overrides(component, api_provider: "klipy", klipy_locale: "de_DE") + + run_migration(component) + + log = + UserHistory.where( + action: UserHistory.actions[:change_site_setting], + subject: "klipy_locale", + ).last + expect(log).to be_present + expect(log.details).to include("Migrated from discourse-gifs theme component") + end + end +end diff --git a/vendor/assets/svg-icons/discourse-additional.svg b/vendor/assets/svg-icons/discourse-additional.svg index 34217c123c1..a35c45b9023 100644 --- a/vendor/assets/svg-icons/discourse-additional.svg +++ b/vendor/assets/svg-icons/discourse-additional.svg @@ -3,6 +3,11 @@ Additional SVG icons --> + + + + +