diff --git a/src/builtins/appearance/hidegifbutton.js b/src/builtins/appearance/hidegifbutton.js
index 341a09f2..3d7dc07e 100644
--- a/src/builtins/appearance/hidegifbutton.js
+++ b/src/builtins/appearance/hidegifbutton.js
@@ -9,7 +9,7 @@ export default new class HideGIFButton extends Builtin {
enabled() {
this.after(WebpackModules.find(m => m.type && m.type.render && m.type.render.displayName === "ChannelTextAreaContainer").type, "render", (_, __, returnValue) => {
- const buttons = Utilities.getNestedProp(returnValue, "props.children.props.children.props.children.1.props.children.props.children.2.props.children");
+ const buttons = Utilities.getNestedProp(returnValue, "props.children.props.children.1.props.children.props.children.2.props.children");
if (Array.isArray(buttons)) {
for (const button of buttons) {
if (!button) continue;
diff --git a/src/builtins/appearance/hidegiftbutton.js b/src/builtins/appearance/hidegiftbutton.js
index 225240bb..104de326 100644
--- a/src/builtins/appearance/hidegiftbutton.js
+++ b/src/builtins/appearance/hidegiftbutton.js
@@ -9,7 +9,7 @@ export default new class HideGiftButton extends Builtin {
enabled() {
this.after(WebpackModules.find(m => m.type && m.type.render && m.type.render.displayName === "ChannelTextAreaContainer").type, "render", (_, __, returnValue) => {
- const buttons = Utilities.getNestedProp(returnValue, "props.children.props.children.props.children.1.props.children.props.children.2.props.children");
+ const buttons = Utilities.getNestedProp(returnValue, "props.children.props.children.1.props.children.props.children.2.props.children");
if (Array.isArray(buttons)) {
for (const button of buttons) {
if (!button || !button.props) continue;
diff --git a/src/builtins/emotes/category.jsx b/src/builtins/emotes/category.jsx
new file mode 100644
index 00000000..c6b8adee
--- /dev/null
+++ b/src/builtins/emotes/category.jsx
@@ -0,0 +1,27 @@
+import {React} from "modules";
+import DownArrow from "../../ui/icons/downarrow";
+
+export default class Category extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ opened: true
+ };
+ }
+ render() {
+ return
+
+
this.setState({opened: !this.state.opened})}>
+
+ {this.props.icon ? this.props.icon : null}
+
+
{this.props.label}
+
+
+
+
+
+ {this.state.opened && this.props.children}
+
;
+ }
+}
\ No newline at end of file
diff --git a/src/builtins/emotes/emotemenu.js b/src/builtins/emotes/emotemenu.js
index b716b24b..81958f6f 100644
--- a/src/builtins/emotes/emotemenu.js
+++ b/src/builtins/emotes/emotemenu.js
@@ -1,8 +1,13 @@
import Builtin from "../../structs/builtin";
import {Utilities, WebpackModules, React} from "modules";
-import Tabs from "./tabs";
-
+import EmoteModule from "./emotes";
+import EmoteMenuCard from "../../ui/emotemenucard";
+import EmoteIcon from "../../ui/emoteicon";
+import Category from "./category";
+import Favorite from "../../ui/icons/favorite";
+import Twitch from "../../ui/icons/twitch";
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";}
@@ -11,32 +16,57 @@ export default new class EmoteMenu extends Builtin {
get hideEmojisID() {return "hideEmojiMenu";}
get hideEmojis() {return this.get(this.hideEmojisID);}
+ getSelected(body) {
+ if (body[1]) return {id: "stickers", index: 1};
+ else if (body[2]) return {id: "gif", index: 2};
+ else if (body[3]) return {id: "emoji", index: 3};
+ return {id: "bd-emotes", index: 3};
+ }
+
enabled() {
- this.before(EmojiPicker, "type", (_, [props]) => {
- if (props.expressionPickerView == "emoji" && this.hideEmojis) props.expressionPickerView = "gif";
- });
- this.after(EmojiPicker, "type", (_, [props], returnValue) => {
+ this.after(EmojiPicker, "type", (_, __, returnValue) => {
const head = Utilities.getNestedProp(returnValue, "props.children.props.children.props.children.1.props.children.0.props.children.props.children");
const body = Utilities.getNestedProp(returnValue, "props.children.props.children.props.children.1.props.children");
if (!head || !body) return returnValue;
-
- const selected = props.expressionPickerView;
- const currentTab = Tabs.find(e => e.id === selected);
+
+ let activePicker = this.getSelected(body);
+ let isActive = activePicker.id == "bd-emotes";
const tabProps = head[0].props;
+ if (!isActive && activePicker.id == "emoji" && this.hideEmojis) {
+ activePicker = {id: "bd-emotes", index: 3};
+ isActive = true;
+ }
+ if (this.hideEmojis) head.splice(head.findIndex(e => e && e.props && e.props.id == "emoji-picker-tab"), 1);
head.push(
- ...Tabs.map(e => React.createElement("div", {
- "id": e.id + "-tab",
+ React.createElement("div", {
+ "id": "bd-emotes-tab",
"role": "tab",
- "aria-selected": selected == e.id,
+ "aria-selected": isActive,
"className": tabProps.className,
}, React.createElement(tabProps.children.type, {
- viewType: e.id,
- isActive: selected == e.id,
- setActiveView: tabProps.children.props.setActiveView
- }, e.label))
+ viewType: "bd-emotes",
+ isActive: isActive,
+ }, "Twitch")
));
- if (currentTab) body[2] = currentTab.element();
- if (this.hideEmojis) head.splice(head.findIndex(e => e && e.props && e.props.id == "emoji-picker-tab"), 1);
+ if (isActive) {
+ body[activePicker.index] = React.createElement(EmoteMenuCard, {
+ type: "twitch",
+ }, [
+ React.createElement(Category, {
+ label: "Favorites",
+ icon: React.createElement(Favorite, {}),
+ }, Object.entries(EmoteModule.favorites).map(([emote, url]) => {
+ return React.createElement(EmoteIcon, {emote, url});
+ })),
+ React.createElement(Category, {
+ label: "Twitch Emotes",
+ icon: React.createElement(Twitch, {})
+ }, Object.keys(EmoteModule.getCategory("TwitchGlobal")).map(emote=> {
+ const url = EmoteModule.getUrl("TwitchGlobal", emote);
+ return React.createElement(EmoteIcon, {emote, url});
+ }))
+ ]);
+ }
});
}
diff --git a/src/builtins/emotes/tabs.js b/src/builtins/emotes/tabs.js
deleted file mode 100644
index e886c8a6..00000000
--- a/src/builtins/emotes/tabs.js
+++ /dev/null
@@ -1,25 +0,0 @@
-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});
- }))
- }
-];
\ No newline at end of file
diff --git a/src/styles/builtins/emotemenu.css b/src/styles/builtins/emotemenu.css
index 9621438e..baf151b2 100644
--- a/src/styles/builtins/emotemenu.css
+++ b/src/styles/builtins/emotemenu.css
@@ -108,20 +108,18 @@
background-color: #e2e2e2;
}
-#bd-qem-twitch-container,
-#bd-qem-favourite-container {
+#bd-emote-menu {
width: 346px;
height: 329px;
background-color: #fff;
border-radius: 0 0 5px 5px;
}
-#bd-qem-twitch-container .scroller-wrap,
-#bd-qem-favourite-container .scroller-wrap {
+#bd-emote-menu .scrollerBase-289Jih {
height: 100%;
}
-.emote-menu-inner {
+.bd-emote-menu-inner {
padding: 5px 0 0 15px;
}
diff --git a/src/styles/builtins/emotes.css b/src/styles/builtins/emotes.css
index 65a2e018..38a637b9 100644
--- a/src/styles/builtins/emotes.css
+++ b/src/styles/builtins/emotes.css
@@ -1,3 +1,64 @@
+.bd-emote-header {
+ color: var(--header-secondary);
+ justify-content: flex-start;
+ font-size: 12px;
+ font-weight: 600;
+ transition: color 0.125s;
+ align-items: center;
+ display: flex;
+}
+
+.bd-emote-scroller {
+ max-height: 380px;
+}
+
+.bd-emote-category {
+ margin-bottom: 12px;
+}
+
+.bd-emote-content {
+ cursor: pointer;
+ position: sticky;
+ top: 0;
+ background: var(--background-secondary);
+ z-index: 2;
+}
+
+.bd-emote-wrapper {
+ background-color: var(--background-secondary);
+ box-sizing: border-box;
+ height: 32px;
+ padding: 0 4px;
+ z-index: 1;
+}
+
+.bd-emote-headerIcon {
+ width: 14px;
+ height: 14px;
+ margin-right: 8px;
+}
+
+.bd-emote-headerLabel {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ text-transform: uppercase;
+ white-space: nowrap;
+ margin-right: 8px;
+}
+
+.bd-emote-headerIcon + .bd-emote-headerLabel {
+ margin-left: 8px;
+}
+
+.bd-emote-headerCollapseIcon .bd-emote-opened {
+ transition: 0.3s;
+}
+
+.bd-emote-headerCollapseIcon .bd-emote-closed {
+ transform: rotate(90deg);
+ transition: 0.3s;
+}
+
#emote-container {
padding: 10px;
}
diff --git a/src/ui/emotemenucard.jsx b/src/ui/emotemenucard.jsx
index 8b9a82f5..b50ffe69 100644
--- a/src/ui/emotemenucard.jsx
+++ b/src/ui/emotemenucard.jsx
@@ -1,10 +1,10 @@
import {React, WebpackModules} from "modules";
-const Scroller = WebpackModules.getByDisplayName("VerticalScroller");
+const {ScrollerAuto: Scroller} = WebpackModules.getByProps("ScrollerAuto");
export default class EmoteMenuCard extends React.Component {
render() {
- return
-
-
+ return
+
+
{this.props.children}
diff --git a/src/ui/icons/favorite.jsx b/src/ui/icons/favorite.jsx
new file mode 100644
index 00000000..1d85e40b
--- /dev/null
+++ b/src/ui/icons/favorite.jsx
@@ -0,0 +1,9 @@
+import {React} from "modules";
+
+export default class Favorite extends React.Component {
+ render() {
+ return
;
+ }
+}
\ No newline at end of file
diff --git a/src/ui/icons/twitch.jsx b/src/ui/icons/twitch.jsx
new file mode 100644
index 00000000..1c7182c3
--- /dev/null
+++ b/src/ui/icons/twitch.jsx
@@ -0,0 +1,9 @@
+import {React} from "modules";
+
+export default class Twitch extends React.Component {
+ render() {
+ return
;
+ }
+}
\ No newline at end of file