Skip to content

Commit b68dcb0

Browse files
committed
Exoport emoteGroup to it's own file
1 parent 98d6400 commit b68dcb0

File tree

4 files changed

+150
-237
lines changed

4 files changed

+150
-237
lines changed

src/components/emoteGroup.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import {Button, Card, Divider, Grid, Popup} from "semantic-ui-react";
2+
import {Emote, EmoteCard} from "./emote";
3+
import React, {useState} from "react";
4+
import Alert from "react-s-alert";
5+
import JSZip from "jszip";
6+
7+
import '../semantic/src/definitions/modules/popup.less';
8+
import "../pages/guild_builder/guild_builder.css";
9+
10+
function sortEmotes(emotes) {
11+
return emotes.sort((a, b) => a.name.localeCompare(b.name))
12+
}
13+
14+
function doDownload(blob, fileName) {
15+
const link = document.createElement('a');
16+
link.href = window.URL.createObjectURL(blob);
17+
link.setAttribute('download', fileName);
18+
19+
document.body.appendChild(link);
20+
link.click();
21+
document.body.removeChild(link);
22+
}
23+
24+
export async function downloadEmotes(emotes, fileName = null) {
25+
if (emotes.length === 0) {
26+
Alert.info("No emotes to download")
27+
} else if (fileName === null) {
28+
const emote = new Emote(emotes[0]);
29+
doDownload(await emote.toBlob(), emote.downloadName());
30+
} else {
31+
const zipFile = new JSZip();
32+
await Promise.all(emotes.map(async e => {
33+
const emote = new Emote(e);
34+
zipFile.file(emote.downloadName(), await emote.toBlob());
35+
}));
36+
const blob = await zipFile.generateAsync({type:"blob"});
37+
doDownload(blob, fileName);
38+
}
39+
}
40+
41+
export default function EmoteGroup({packName, emotes, title, downloadAll, fileName, emotePopup, setEmotePopup}) {
42+
const [isDownloading, setIsDownloading] = useState(false);
43+
44+
if (emotes.length === 0) {
45+
return <></>;
46+
}
47+
return (
48+
<>
49+
<Divider/>
50+
<Grid>
51+
<Grid.Column width={10}>
52+
<h2>{title}</h2>
53+
</Grid.Column>
54+
<Grid.Column width={6}>
55+
<Button
56+
primary
57+
fluid
58+
disabled={isDownloading}
59+
loading={isDownloading}
60+
onClick={async () => {
61+
setIsDownloading(true);
62+
await downloadEmotes(emotes, fileName);
63+
setIsDownloading(false);
64+
}}
65+
>
66+
{downloadAll}
67+
</Button>
68+
</Grid.Column>
69+
</Grid>
70+
<Card.Group className="centered guild_creator">
71+
{sortEmotes(emotes).map(emote =>
72+
<Popup
73+
key={emote.id}
74+
position="top right"
75+
trigger={<EmoteCard emote={emote} onClick={() => setEmotePopup(emote.id)}/>}
76+
open={emote.id === emotePopup}
77+
onClose={() => setEmotePopup(null)}
78+
content={
79+
<Button.Group vertical fluid>
80+
<Button primary onClick={() => {
81+
downloadEmotes([emote]);
82+
setEmotePopup(null);
83+
}}>
84+
Download Emoji
85+
</Button>
86+
<Button secondary onClick={() => {
87+
const e = new Emote(emote);
88+
e.copyToClipboard(packName);
89+
setEmotePopup(null);
90+
}}>
91+
Copy to clipboard
92+
</Button>
93+
</Button.Group>
94+
}
95+
>
96+
</Popup>
97+
)}
98+
</Card.Group>
99+
</>
100+
);
101+
}
Lines changed: 36 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,133 +1,39 @@
1-
import React, {Component} from "react";
2-
import connect from "react-redux/es/connect/connect";
3-
4-
import {Container, Header, Button, Divider, Menu, Icon} from 'semantic-ui-react';
5-
6-
import '../../../semantic/src/definitions/elements/container.less';
7-
import '../../../semantic/src/definitions/elements/header.less';
8-
import '../../../semantic/src/definitions/elements/button.less';
9-
import '../../../semantic/src/definitions/elements/divider.less';
10-
import '../../../semantic/src/definitions/collections/menu.less';
11-
import '../../../semantic/src/definitions/elements/icon.less';
12-
13-
import EmotePreview from "./emotes/preview";
14-
import {postGuildEmotes} from "../../../actions/guild"
15-
import {receiveGuildEmotes} from "../../../actions/user"
16-
17-
import {withRouter} from "react-router-dom";
18-
19-
20-
class EmoteSettings extends Component {
21-
constructor(props) {
22-
super(props);
23-
const emotes = this.props.emotes[this.props.guildID] || [];
24-
this.state = {emotes};
25-
}
26-
27-
componentDidUpdate(prevProps) {
28-
if ((prevProps.guildID !== this.props.guildID) ||
29-
(prevProps.emotes[prevProps.guildID] !== this.props.emotes[this.props.guildID])) {
30-
const emotes = this.props.emotes[this.props.guildID] || [];
31-
this.setState({emotes});
32-
}
33-
}
34-
35-
unsetNames(emotes) {
36-
this.setState({emotes: this.state.emotes.filter(({id}) => !emotes.some(e => e.id === id))});
37-
}
38-
39-
updateEmotes(emotes) {
40-
const guild = this.props.guilds[this.props.guildID];
41-
let totals = [
42-
this.state.emotes.filter(e => !e.animated).length,
43-
this.state.emotes.filter(e => e.animated).length
44-
];
45-
const concat = emotes.filter(emote => totals[emote.animated ? 1: 0]++ < guild.emote_limit);
46-
const filteredEmotes = this.state.emotes.filter(({id}) => !concat.some(e => e.id === id)).concat(concat);
47-
this.setState({emotes: filteredEmotes});
48-
}
49-
50-
save() {
51-
this.props.postGuildEmotes(this.props.guildID, this.state.emotes, (ids) => {
52-
const emotes = this.state.emotes.map(emote => {
53-
if (Object.keys(ids).includes(emote.id)) {
54-
emote.id = ids[emote.id];
55-
}
56-
return emote;
57-
});
58-
console.log(emotes);
59-
this.props.receiveGuildEmotes(this.props.guildID, emotes);
60-
});
61-
}
62-
63-
render() {
64-
const guild = this.props.guilds[this.props.guildID];
65-
66-
if (!guild.bot_permissions.includes("manage_emojis")) {
67-
return (
68-
<Container>
69-
<Header as="b">
70-
This server does not allow the bot to manage emotes, so you cannot change them here.
71-
</Header>
72-
<Divider hidden={true}/>
73-
<EmotePreview emotes={this.state.emotes} modifiable={false}/>
74-
</Container>
75-
);
76-
}
77-
return (
78-
<Container>
79-
<Menu>
80-
<Menu.Item
81-
position='right'
82-
>
83-
{this.state.emotes.filter(e => !e.animated).length} / {guild.emote_limit} Static
84-
</Menu.Item>
85-
<Menu.Item
86-
position='right'
87-
>
88-
{this.state.emotes.filter(e => e.animated).length} / {guild.emote_limit} Animated
89-
</Menu.Item>
90-
<Menu.Item
91-
position='right'
92-
>
93-
<Button
94-
primary
95-
icon
96-
labelPosition="right"
97-
onClick={() => this.save()}
98-
>
99-
Save
100-
<Icon name='save' />
101-
</Button>
102-
</Menu.Item>
103-
</Menu>
104-
<EmotePreview
105-
emotes={this.state.emotes}
106-
setAliases={(emotes) => this.updateEmotes(emotes)}
107-
changeAliases={(emotes) => this.updateEmotes(emotes)}
108-
unsetAliases={(emotes) => this.unsetNames(emotes)}
109-
modifiable={true}
110-
/>
111-
</Container>
112-
);
113-
}
1+
import React, {useState} from "react";
2+
3+
import {Container, Menu} from 'semantic-ui-react';
4+
5+
import EmoteGroup from "../../../components/emoteGroup";
6+
7+
function EmoteSettings(props) {
8+
const [emotePopup, setEmotePopup] = useState(null);
9+
10+
return (
11+
<Container>
12+
<Menu>
13+
<Menu.Item
14+
position='right'
15+
>
16+
{props.emotes.filter(e => !e.animated).length} / {props.guild.emote_limit} Static
17+
</Menu.Item>
18+
<Menu.Item
19+
position='right'
20+
>
21+
{props.emotes.filter(e => e.animated).length} / {props.guild.emote_limit} Animated
22+
</Menu.Item>
23+
</Menu>
24+
25+
<EmoteGroup
26+
packName={null}
27+
emotes={props.emotes}
28+
title={`"${props.guild.name}" Emojis`}
29+
downloadAll="Download all emojis as zip"
30+
fileName={`${props.guild.name}.zip`}
31+
emotePopup={emotePopup}
32+
setEmotePopup={setEmotePopup}
33+
/>
34+
</Container>
35+
);
11436
}
11537

116-
const mapStateToProps = (state) => {
117-
return {
118-
guilds: state.user.guilds,
119-
emotes: state.user.guild_emotes,
120-
}
121-
};
122-
123-
const mapDispatchToProps = dispatch => {
124-
return {
125-
postGuildEmotes: (guildID, emotes, cb) => dispatch(postGuildEmotes(guildID, emotes, cb)),
126-
receiveGuildEmotes: (guildID, emotes) => dispatch(receiveGuildEmotes(guildID, emotes))
127-
}
128-
};
12938

130-
export default withRouter(connect(
131-
mapStateToProps,
132-
mapDispatchToProps
133-
)(EmoteSettings));
39+
export default EmoteSettings;

src/pages/guild_dashboard/settings_root.js

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ class GuildSettingsRoot extends Component {
2222
const page = {
2323
settings: <GuildSettings guildID={this.props.guildID} showHeader={true}/>,
2424
logs: <AuditLogs guildID={this.props.guildID}/>,
25-
emotes: <EmoteSettings guildID={this.props.guildID}/>,
26-
upload_emotes: <EmoteSettings guildID={this.props.guildID}/>,
25+
emojis: <EmoteSettings guild={guild} emotes={this.props.emotes[this.props.guildID] || []}/>,
2726
permissions: <GuildPermissions guildID={this.props.guildID}/>
2827
}[pageName];
2928
return (
@@ -47,6 +46,11 @@ class GuildSettingsRoot extends Component {
4746
active={pageName === "logs"}
4847
onClick={() => this.props.history.push("./logs")}
4948
/>}
49+
{guild.user_permissions.includes("manage_expressions") && <Menu.Item
50+
name='Custom Emojis'
51+
active={pageName === "emojis"}
52+
onClick={() => this.props.history.push("./emojis")}
53+
/>}
5054
</Menu>
5155
<Segment attached='bottom'>
5256
{page}
@@ -56,17 +60,10 @@ class GuildSettingsRoot extends Component {
5660
}
5761
}
5862

59-
/*
60-
<Menu.Item
61-
name='Custom Emotes'
62-
active={["emotes", "upload_emotes"].includes(pageName)}
63-
onClick={() => this.props.history.push("./emotes")}
64-
/>
65-
*/
66-
6763
const mapStateToProps = (state) => {
6864
return {
69-
guilds: state.user.guilds
65+
guilds: state.user.guilds,
66+
emotes: state.user.guild_emotes,
7067
}
7168
};
7269

0 commit comments

Comments
 (0)