Merge pull request #396 from Strencher/development

rewrite emote menu + add de translation
This commit is contained in:
Zack 2020-07-24 10:53:52 -04:00 committed by GitHub
commit f8e3121600
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 457 additions and 187 deletions

307
assets/locales/de.json Normal file
View File

@ -0,0 +1,307 @@
{
"Panels": {
"plugins": "Plugins",
"themes": "Themes",
"customcss": "Custom-CSS"
},
"Collections": {
"settings": {
"name": "Einstellungen",
"general": {
"name": "Allgemein",
"emotes": {
"name": "Emote-Funktion",
"note": "Aktiviert die BD Emote-Funktion."
},
"publicServers": {
"name": "Öffentliche Sever",
"note": "Zeigt den Button zum Öffnen einer Liste öffentlicher Server."
},
"voiceDisconnect": {
"name": "Verbindung zum Sprachchat trennen",
"note": "Trennt beim Schließen von Discord die Verbindung zum Sprachchat."
},
"twentyFourHour": {
"name": "24h Zeitstempel",
"note": "Zeigt die Zeitstempel in einem 24h format an."
},
"classNormalizer": {
"name": "Normalisierte klassen",
"note": "Fügt stetige Klassen zu Elementen hinzu (z.B. .da-channels zu .channels-Ie2l6A)"
},
"showToasts": {
"name": "Benachrichtigungen anzeigen",
"note": "Zeigt kleine Benachrichtigung für wichtige informationen an."
}
},
"appearance": {
"name": "Aussehen",
"voiceMode": {
"name": "Sprachmodus",
"note": "Verbirgt alles, was kein Sprachkanal ist."
},
"minimalMode": {
"name": "Minimaler Modus",
"note": "Verbirgt Elemente und reduziert die Größe von elementen."
},
"hideChannels": {
"name": "Kanäle verbergen",
"note": "Verbirgt Kanäle, wenn \"Minimaler Modus\" aktiviert ist."
},
"darkMode": {
"name": "Dunkelmodus",
"note": "Aktivert einen noch dunkleren Modus in Discord."
},
"coloredText": {
"name": "Farbiger Text",
"note": "Macht die Textfarbe gleich mit der Rollenfarbe."
}
},
"addons": {
"name": "Erweiterungs-Manager",
"addonErrors": {
"name": "Zeige Erweiterungsfehler",
"note": "Zeigt einen Popup mit Erweiterungsfehlern."
},
"autoScroll": {
"name": "Zu Einstellungen scollen",
"note": "Scrollt automatisch zu den Erweiterungs-Einstellungen."
},
"autoReload": {
"name": "Automatisches Laden",
"note": "Läd und entfernt Plugins und Themes automatisch."
},
"editAction": {
"name": "Bearbeitungsaktion",
"note": "Wo Plugins und Themes zum Bearbeiten geöffnet werden.",
"options": {
"detached": "Popout-Fenster",
"system": "System-Editor"
}
}
},
"customcss": {
"name": "Custom-CSS",
"customcss": {
"name": "Custom-CSS",
"note": "Aktiviert den \"Custom-CSS\"-Tab in den Einstellungen."
},
"liveUpdate": {
"name": "Live-Aktualisierung",
"note": "Aktualisiere den CSS-Editor beim Bearbeiten."
},
"startDetached": {
"name": "Als Popout starten",
"note": "Das Klicken auf den \"Custom-CSS\"-Tab öffnet den editor in einem Popoup-Fenster."
},
"nativeOpen": {
"name": "Im System-Editor öffnen",
"note": "Das Klicken auf den \"Custom-CSS\"-Tab öffnet dein \"Custom-CSS\" in deinem System-Editor."
},
"openAction": {
"name": "Editor-Location",
"note": "Wo Custom-CSS standardmäßig geöffnet werden soll",
"options": {
"settings": "Einstellungs-Menü",
"detached": "Popout-Fenster",
"system": "System-Editor"
}
}
},
"developer": {
"name": "Entwickler-Einstellungen",
"debuggerHotkey": {
"name": "Debugger-Hotkey",
"note": "Starte den Debugger durch das Drücken der F8-Taste."
},
"copySelector": {
"name": "Selektor kopieren",
"note": "Fügt eine \"Selektor kopieren\"-Option zu den Context-Menüs hinzu."
},
"reactDevTools": {
"name": "React-Developer-Tools",
"note": "Fügt die lokale Installation der React Developer Tools in Discord hinzu."
}
},
"window": {
"name": "Fenster-Einstellungen",
"transparency": {
"name": "Transparenz aktivieren",
"note": "Macht den Discord-Hintergrund transparent."
},
"frame": {
"name": "Standard-Design",
"note": "Stellt das Hauptfenster im Standard-Design des Betriebssystems dar."
}
}
},
"emotes": {
"name": "Emotes",
"general": {
"name": "Allgemein",
"download": {
"name": "Emotes herunterladen",
"note": "Lade Emotes herunter, wenn sie nicht mehr aktuell sind"
},
"emoteMenu": {
"name": "Emote-Menü",
"note": "Twitch- und favorisierte Emotes im Emote-Menü anzeigen"
},
"hideEmojiMenu": {
"name": "Emoji-Menü verstecken",
"note": "Versteckt Discords Emoji-Menü bei der Nutzung des Emote-Menüs"
},
"autoCaps": {
"name": "Automatische Großschreibung von Emotes",
"note": "Emote-Befehle werden automatisch großgeschrieben"
},
"showNames": {
"name": "Namen anzeigen",
"note": "Zeigt den Emote-Namen beim Hovern über diesem an"
},
"modifiers": {
"name": "Emote-Modifikatoren anzeigen",
"note": "Aktiviert Emote-Modifikatoren (flip, spin, pulse, spin2, spin3, 1spin, 2spin, 3spin, tr, bl, br, shake, shake2, shake3, flap)"
},
"animateOnHover": {
"name": "Beim Hovern animieren",
"note": "Animiert Emote-Modifikatoren nur beim Hovern über dem Emote"
}
},
"categories": {
"name": "Kategorien",
"twitchglobal": {
"name": "Twitch Global",
"note": "Twitch-Global-Emotes anzeigen"
},
"twitchsubscriber": {
"name": "Twitch Subscribers",
"note": "Twitch-Subscriber-Emotes anzeigen"
},
"frankerfacez": {
"name": "FrankerFaceZ",
"note": "FFZ-Emotes anzeigen"
},
"bttv": {
"name": "BetterTTV",
"note": "BTTV-Emotes anzeigen"
}
}
}
},
"Addons": {
"title": "{{name}} v{{version}} von {{author}}",
"openFolder": "Öffne {{type}}-Ordner",
"reload": "Neu laden",
"addonSettings": "Einstellungen",
"website": "Website",
"source": "Source",
"invite": "Support-Server",
"donate": "Spenden",
"patreon": "Patreon",
"name": "Name",
"author": "Autor",
"version": "Version",
"added": "Hinzufügedatum",
"modified": "Bearbeitungsdatum",
"search": "{{type}} suchen",
"editAddon": "Bearbeiten",
"deleteAddon": "Löschen",
"confirmDelete": "Bist du dir sicher, dass du {{name}} löschen willst?",
"confirmationText": "Du hast ungespeicherte Änderungen in {{name}}. Durch das Schließen dieses Fensters verlierst du alle Änderungen.",
"enabled": "{{name}} wurde aktiviert.",
"disabled": "{{name}} wurde deaktiviert.",
"couldNotEnable": "{{name}} konnte nicht aktiviert werden.",
"couldNotDisable": "{{name}} konnte nicht deaktiviert werden.",
"couldNotStart": "{{name}} konnte nicht gestartet werden.",
"couldNotStop": "{{name}} konnte nicht gestoppt werden.",
"methodError": "{{method}} konnte nicht ausgeführt werden.",
"unknownAuthor": "Unbekannter Autor",
"noDescription": "Keine Beschreibung angegeben.",
"alreadyExists": "Es existiert bereits ein {{type}} mit dem Namen {{name}}",
"metaError": "META konnte nicht geparst werden.",
"missingNameData": "META missing name data.",
"metaNotFound": "META nicht gefunden.",
"compileError": "Konnte nicht kompiliert werden.",
"wasUnloaded": "{{name}} was unloaded.",
"alreadyWatching": "Already watching {{prefix}} addons.",
"startingWatch": "Starting to watch {{prefix}} addons.",
"wasNotWatching": "Was not watching {{prefix}} addons.",
"noLongerWatching": "No longer watching {{prefix}} addons."
},
"CustomCSS": {
"confirmationText": "Du hast ungespeicherte Änderungen im Custom-CSS. Durch das Schließen dieses Fensters verlierst du alle Änderungen.",
"update": "Aktualisieren",
"save": "Speichern",
"openNative": "Im System-Editor öffnen",
"openDetached": "Fenster trennen",
"settings": "Editor-Einstellungen",
"editorTitle": "Custom-CSS-Editor"
},
"Developer": {
"copySelector": "Selektor kopieren"
},
"Emotes": {
"loading": "Lade alle Emotes im Hintergrund.",
"loaded": "Alle Emotes erfolgreich geladen.",
"clearEmotes": "Emote-Daten löschen",
"favoriteAction": "Favorisieren!"
},
"PublicServers": {
"button": "public",
"join": "Beitreten",
"joining": "Trete bei",
"joined": "Beigetreten",
"loading": "Laden",
"loadMore": "Mehr laden",
"notConnected": "Nicht mit DiscordServers.com verbunden!",
"search": "Suchen",
"connect": "Verbinden",
"reconnect": "Wiederverbinden",
"categories": "Kategorien",
"connection": "Verbunden als: {{username}}#{{discriminator}}",
"results": "Zeige {{start}}-{{end}} von {{total}} Ergebnissen in {{category}}",
"query": "für {{query}}"
},
"Modals": {
"confirmAction": "Bist du dir sicher?",
"okay": "Okay",
"cancel": "Abbrechen",
"close": "Schließen",
"name": "Name",
"message": "Nachricht",
"error": "Fehler",
"addonErrors": "Erweiterungsfehler",
"restartRequired": "Neustart erforderlich",
"restartNow": "Jetzt neustarten",
"restartLater": "Später neustarten",
"additionalInfo": "Zusätzliche Informationen"
},
"ReactDevTools": {
"notFound": "Erweiterung nicht gefunden",
"notFoundDetails": "React Developer Tools-Erweiterung konnte nicht gefunden werden. Füg die Erweiterung zu deiner Chrome-Installation hinzu."
},
"Sorting": {
"sortBy": "Sortieren nach",
"order": "Reihenfolge",
"ascending": "Aufsteigend",
"descending": "Absteigend"
},
"Startup": {
"notSupported": "Nicht unterstützt",
"versionMismatch": "BandagedBD Injector v{{injector}} wird nicht von der letzten Onlineversion (v{{remote}}) unterstützt.\n\nBitte lade den neusten Installer von [GitHub](https://github.com/rauenzi/BetterDiscordApp/releases/latest) herunter.",
"incompatibleApp": "BandagedBD ist nicht mit {{app}} kompatiblem. Bitte entferne entweder BetterDiscord oder {{app}}.",
"updateNow": "Jetzt aktualisieren",
"maybeLater": "Später",
"updateAvailable": "Update verfügbar",
"updateInfo": "Ein Update für BandagedBDs Injector ({{version}}) ist verfügbar.\n\nDu kannst entweder jetzt oder später aktualisieren und neustarten",
"updateFailed": "Konnte nicht aktualisiert werden",
"manualUpdate": "Die automatische Aktualisierung schlug fehl. Bitte lade den Installer herunter und installiere BetterDiscord erneut.\n\n[Installer herunterladen](https://github.com/rauenzi/BetterDiscordApp/releases/latest)",
"jqueryFailed": "jQuery konnte nicht geladen werden",
"jqueryFailedDetails": "jQuery konnte nicht geladen werden, wodurch einige Plugins gegebenenfalls nicht richtig funktionieren."
},
"WindowPrefs": {
"enabledInfo": "Um diese Funktion zu verwenden, benötigst du ein Theme mit transparentem Hintergrund. Auf Windows funktioniert das Maximieren des Fensters ggf. nicht mehr.\n\nUm die Änderungen zu übernehmen muss Discord neugeladen werden. Willst du jetzt neuladen?",
"disabledInfo": "Um die Änderungen zu übernehmen muss Discord neugeladen werden. Willst du jetzt neuladen?"
}
}

40
dist/index.js vendored

File diff suppressed because one or more lines are too long

4
dist/style.css vendored
View File

@ -419,6 +419,10 @@ body .ace_closeButton:active {
display: none;
}
.bd-em-scroller {
height: 400px;
}
#emote-container {
padding: 10px;
}

2
dist/style.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -1,45 +1,7 @@
import Builtin from "../../structs/builtin";
import {Utilities, Events, DOM} from "modules";
import Modals from "../../ui/modals";
import EmoteModule from "./emotes";
const headerHTML = `<div id="bd-qem">
<button class="active" id="bd-qem-twitch">Twitch</button>
<button id="bd-qem-favourite">Favourite</button>
<button id="bd-qem-emojis">Emojis</buttond>
</div>`;
const twitchEmoteHTML = `<div id="bd-qem-twitch-container">
<div class="scroller-wrap scrollerWrap-2lJEkd fade">
<div class="scroller scroller-2FKFPG">
<div class="emote-menu-inner">
</div>
</div>
</div>
</div>`;
const favoritesHTML = `<div id="bd-qem-favourite-container">
<div class="scroller-wrap scrollerWrap-2lJEkd fade">
<div class="scroller scroller-2FKFPG">
<div class="emote-menu-inner">
</div>
</div>
</div>
</div>`;
const makeEmote = (emote, url, options = {}) => {
const {onContextMenu, onClick} = options;
const emoteContainer = DOM.createElement(`<div class="emote-container">
<img class="emote-icon" alt="${emote}" src="${url}" title="${emote}">
</div>`);
if (onContextMenu) emoteContainer.addEventListener("contextmenu", onContextMenu);
emoteContainer.addEventListener("click", onClick);
return emoteContainer;
};
import {Utilities, WebpackModules, React} from "modules";
import Tabs from "./tabs";
const EmojiPicker = WebpackModules.find(m => m.type && m.type.displayName == "ExpressionPicker");
export default new class EmoteMenu extends Builtin {
get name() {return "EmoteMenu";}
get collection() {return "emotes";}
@ -50,151 +12,37 @@ export default new class EmoteMenu extends Builtin {
constructor() {
super();
this.lastTab = "bd-qem-emojis";
this.qmeHeader = DOM.createElement(headerHTML);
for (const button of this.qmeHeader.getElementsByTagName("button")) button.addEventListener("click", this.switchMenu.bind(this));
this.teContainer = DOM.createElement(twitchEmoteHTML);
this.teContainerInner = this.teContainer.querySelector(".emote-menu-inner");
this.faContainer = DOM.createElement(favoritesHTML);
this.faContainerInner = this.faContainer.querySelector(".emote-menu-inner");
this.observer = new MutationObserver(mutations => {for (const mutation of mutations) this.observe(mutation);});
this.enableHideEmojis = this.enableHideEmojis.bind(this);
this.disableHideEmojis = this.disableHideEmojis.bind(this);
this.updateTwitchEmotes = this.updateTwitchEmotes.bind(this);
}
async enabled() {
// Temporary measure, so not using Strings/translation
return Modals.alert("Emote Menu Broken", "Emote Menu is currently broken, it is recommended to disable this until it is fixed.");
// this.log("Starting to observe");
// this.observer.observe(document.getElementById("app-mount"), {
// childList: true,
// subtree: true
// });
// this.hideEmojiCancel = this.registerSetting(this.hideEmojisID, this.enableHideEmojis, this.disableHideEmojis);
// if (this.hideEmojis) this.enableHideEmojis();
// if (EmoteModule.emotesLoaded) this.updateTwitchEmotes();
// this.updateFavorites();
// Events.on("emotes-loaded", this.updateTwitchEmotes);
}
enabled() {
this.before(EmojiPicker, "type", (_, [args], ret) => {
if(args.expressionPickerView == "emoji" && this.hideEmojis) args.expressionPickerView = "gif";
});
this.after(EmojiPicker, "type", (_, [args], ret) => {
const head = Utilities.getNestedProp(ret, "props.children.props.children.1.props.children.0.props.children.props.children");
const body = Utilities.getNestedProp(ret, "props.children.props.children.1.props.children");
if(!head || !body) return ret;
const selected = args.expressionPickerView;
const currentTab = Tabs.find(e => e.id === selected);
let tabProps = head[0].props;
head.push(
...Tabs.map(e => React.createElement("div", {
id: e.id+"-tab",
role: "tab",
"aria-selected": selected == e.id,
className: tabProps.className,
}, React.createElement(tabProps.children.type, {
viewType: e.id,
isActive: selected == e.id,
setActiveView: tabProps.children.props.setActiveView
}, e.label))
));
if(currentTab) body[2] = currentTab.element();
if(this.hideEmojis) head.splice(head.findIndex(e=>e.props.id == "emoji-picker-tab"), 1);
})
}
disabled() {
Events.off("emotes-loaded", this.updateTwitchEmotes);
this.observer.disconnect();
this.disableHideEmojis();
if (this.hideEmojiCancel) this.hideEmojiCancel();
}
enableHideEmojis() {
const picker = document.querySelector(".emojiPicker-3m1S-j");
if (picker) picker.classList.add("bd-qme-hidden");
}
disableHideEmojis() {
const picker = document.querySelector(".emojiPicker-3m1S-j");
if (picker) picker.classList.remove("bd-qme-hidden");
}
insertEmote(emote) {
const ta = Utilities.getTextArea();
Utilities.insertText(ta[0], ta.val().slice(-1) == " " ? ta.val() + emote : ta.val() + " " + emote);
}
favContext(e) {
e.stopPropagation();
const em = e.target.closest(".emote-container").children[0];
const menu = $(`<div id="removemenu" class="bd-context-menu context-menu theme-dark">Remove</div>`);
menu.css({
top: e.pageY - $("#bd-qem-favourite-container").offset().top,
left: e.pageX - $("#bd-qem-favourite-container").offset().left
});
$(em).parent().append(menu);
menu.on("click", (event) => {
event.preventDefault();
event.stopPropagation();
$(em).remove();
EmoteModule.removeFavorite($(em).attr("title"));
this.updateFavorites();
$(document).off("mousedown.emotemenu");
});
$(document).on("mousedown.emotemenu", function(event) {
if (event.target.id == "removemenu") return;
$("#removemenu").remove();
$(document).off("mousedown.emotemenu");
});
}
switchMenu(e) {
let id = typeof(e) == "string" ? e : e.target.id;
if (id == "bd-qem-emojis" && this.hideEmojis) id = "bd-qem-favourite";
const twitch = $("#bd-qem-twitch");
const fav = $("#bd-qem-favourite");
const emojis = $("#bd-qem-emojis");
twitch.removeClass("active");
fav.removeClass("active");
emojis.removeClass("active");
$(".emojiPicker-3m1S-j").hide();
$("#bd-qem-favourite-container").hide();
$("#bd-qem-twitch-container").hide();
switch (id) {
case "bd-qem-twitch":
twitch.addClass("active");
$("#bd-qem-twitch-container").show();
break;
case "bd-qem-favourite":
fav.addClass("active");
$("#bd-qem-favourite-container").show();
break;
case "bd-qem-emojis":
emojis.addClass("active");
$(".emojiPicker-3m1S-j").show();
$(".emojiPicker-3m1S-j input").focus();
break;
}
if (id) this.lastTab = id;
}
observe(mutation) {
if (!mutation.addedNodes.length || !(mutation.addedNodes[0] instanceof Element)) return;
const node = mutation.addedNodes[0];
// if (!node.classList.contains("popout-2iWAc-") || node.classList.contains("popoutLeft-30WmrD") || !node.getElementsByClassName("emojiPicker-3m1S-j").length) return;
if (!node.classList.contains("layer-v9HyYc") || !node.getElementsByClassName("emojiPicker-3m1S-j").length || node.querySelector(".emojiPicker-3m1S-j").parentElement.classList.contains("animatorLeft-1EQxU0")) return;
const e = $(node);
if (this.hideEmojis) e.addClass("bd-qme-hidden");
else e.removeClass("bd-qme-hidden");
e.prepend(this.qmeHeader);
e.append(this.teContainer);
e.append(this.faContainer);
this.switchMenu(this.lastTab);
}
updateTwitchEmotes() {
while (this.teContainerInner.firstChild) this.teContainerInner.firstChild.remove();
for (const emote in EmoteModule.getCategory("TwitchGlobal")) {
if (!EmoteModule.getCategory("TwitchGlobal").hasOwnProperty(emote)) continue;
const url = EmoteModule.getUrl("TwitchGlobal", emote);
const emoteElement = makeEmote(emote, url, {onClick: this.insertEmote.bind(this, emote)});
this.teContainerInner.append(emoteElement);
}
}
updateFavorites() {
while (this.faContainerInner.firstChild) this.faContainerInner.firstChild.remove();
for (const emote in EmoteModule.favorites) {
const url = EmoteModule.favorites[emote];
const emoteElement = makeEmote(emote, url, {onClick: this.insertEmote.bind(this, emote), onContextMenu: this.favContext.bind(this)});
this.faContainerInner.append(emoteElement);
}
EmoteModule.saveFavorites();
this.unpatchAll();
}
};

View File

@ -0,0 +1,25 @@
import {React} from "modules";
import EmoteModule from "./emotes";
import EmoteMenuCard from "../../ui/emotemenucard";
import EmoteIcon from "../../ui/emoteicon";
export default [
{
id: "twitchEmotes",
label: "Twitch Emotes",
element: () => React.createElement(EmoteMenuCard, {
type: "twitch"
}, Object.keys(EmoteModule.getCategory("TwitchGlobal")).map(emote=> {
const url = EmoteModule.getUrl("TwitchGlobal", emote);
return React.createElement(EmoteIcon, {emote, url});
}))
},
{
id: "favoriteEmotes",
label: "Favorite Emotes",
element: () => React.createElement(EmoteMenuCard, {
type: "favourite"
}, Object.entries(EmoteModule.favorites).map(([emote, url]) => {
return React.createElement(EmoteIcon, {emote, url});
}))
}
]

View File

@ -11,13 +11,17 @@ import ThemeManager from "./thememanager";
import Settings from "./settingsmanager";
import Logger from "./logger";
import Patcher from "./patcher";
import Emotes from "../builtins/emotes/emotes";
const BdApi = {
get React() { return DiscordModules.React; },
get ReactDOM() { return DiscordModules.ReactDOM; },
get WindowConfigFile() {return "";},
get settings() {return Settings.collections;},
get emotes() {return {};},
get emotes() {return new Proxy(Emotes.Emotes, {
get() { return Emotes.Emotes},
set() { Logger.warn("Emotes", "Addon policy for plugins #5 https://github.com/rauenzi/BetterDiscordApp/wiki/Addon-Policies#plugins");}
});},
get version() {return Config.version;}
};

View File

@ -127,4 +127,7 @@
.bd-qme-hidden #bd-qem-emojis {
display: none;
}
.bd-em-scroller {
height: 400px;
}

30
src/ui/emoteicon.jsx Normal file
View File

@ -0,0 +1,30 @@
import {React, WebpackModules, DiscordModules} from "modules";
import EmoteModule from "../builtins/emotes/emotes";
const {openContextMenu, closeContextMenu} = WebpackModules.getByProps("openContextMenu");
const {MenuItem, MenuGroup} = WebpackModules.find(m => m.MenuRadioItem && !m.default);
const ContextMenu = WebpackModules.getByProps("default", "MenuStyle").default;
const {ComponentDispatch} = WebpackModules.getByProps("ComponentDispatch");
export default class EmoteIcon extends React.Component {
render() {
return <div className="emote-container" onClick={this.handleOnClick.bind(this)} onContextMenu={this.handleOnContextMenu.bind(this)}>
<img src={this.props.url} alt={this.props.emote} title={this.props.emote}/>
</div>
}
handleOnClick() {
this.insertText(this.props.emote);
}
handleOnContextMenu(e) {
openContextMenu(e, () => <ContextMenu navId="EmoteContextMenu" onClose={closeContextMenu}>
<MenuGroup>
<MenuItem label={EmoteModule.isFavorite(this.props.emote) ? "Remove Favorite" : "Add Favorite"} id="favorite" action={this.handlefavorite.bind(this)} onClose={closeContextMenu}/>
</MenuGroup>
</ContextMenu>);
}
handlefavorite() {
closeContextMenu();
EmoteModule.isFavorite(this.props.emote) ? EmoteModule.removeFavorite(this.props.emote) : EmoteModule.addFavorite(this.props.emote, this.props.url);
}
insertText(emote) {
ComponentDispatch.dispatchToLastSubscribed("INSERT_TEXT", {content: emote})
}
}

13
src/ui/emotemenucard.jsx Normal file
View File

@ -0,0 +1,13 @@
import {React, WebpackModules} from "modules";
const Scroller = WebpackModules.getByDisplayName("VerticalScroller");
export default class EmoteMenuCard extends React.Component {
render() {
return <div className={`bd-qem-${this.props.type}-container`}>
<Scroller className="bd-em-scroller">
<div className="emote-menu-inner">
{this.props.children}
</div>
</Scroller>
</div>
}
}