Skip to content

Instantly share code, notes, and snippets.

@12944qwerty
Last active March 11, 2022 14:49
Show Gist options
  • Save 12944qwerty/a256c0fabcad64d69da7000645a6e7c5 to your computer and use it in GitHub Desktop.
Save 12944qwerty/a256c0fabcad64d69da7000645a6e7c5 to your computer and use it in GitHub Desktop.
A way to select guilds and store them in a certain place. In powercord

Select Servers

A way to select guilds and store them in a certain place. Requires powercord

Usage

  1. Copy the file into your plugin
  2. Import the ServerChooser Component.
  3. Add the component with <ServerChooser>

Props

  • note - The note that informs the user of what the setting is for
  • title - The title text that will appear. Uses button if not specified
  • button - The button and/or title text that will appear
  • settingsKey - The settings key you designate that the "enabled" servers will be stored in.
  • getSetting - The callback that should return the "enabled" servers. Same as powercord's setting's function.
  • updateSetting - The callback that updates the "enabled" servers. Same as powercord's setting's function.

Example

module.exports = class Settings extends React.PureComponent {
    render() {
        const { getSetting, updateSetting } = this.props;

        return <>
            <ServerChooser
                note="Choose what guilds you want to whitelist"
                button="Open Server Chooser"
                settingsKey="whitelist-guilds"
                {...this.props} // All props that the Settings component has, including getSetting and updateSetting
            >
                Open Server Chooser
            </ServerChooser>
        </>
    }
}

Example image of button in settings screen Example modal of all guilds. Some enabled and disabled

To-Do

  • Make category variant

Credit

/**
* Copyright 2022-present 12944qwerty
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
const { React, getModule, getModuleByDisplayName } = require('powercord/webpack');
const { Clickable, FormTitle, Flex, Button } = require('powercord/components');
const { ButtonItem } = require('powercord/components/settings');
const { open } = require("powercord/modal");
const { marginLeft8 } = getModule(['marginLeft8'], false);
const { marginTop4 } = getModule(['marginTop4'], false);
const { marginBottom4 } = getModule(['marginBottom4'], false);
const { Modal } = require("powercord/components/modal");
const { close: closeModal } = require("powercord/modal");
class ServerChooserModal extends React.PureComponent {
render() {
const { getSetting, updateSetting } = this.props;
const { getFlattenedGuilds } = getModule([ 'initialize', 'getSortedGuilds' ], false);
const GuildTooltip = getModuleByDisplayName('GuildTooltip', false);
const GuildIconWrapper = getModuleByDisplayName('GuildIconWrapper', false);
const allGuilds = getFlattenedGuilds();
return <>
<Modal className="powercord-text" size={Modal.ModalSize.MEDIUM}>
<Modal.Header>
<FormTitle tag="h4">{this.props.note || "Select some guilds"}</FormTitle>
</Modal.Header>
<Modal.Content>
<Flex wrap={Flex.Wrap.WRAP} className={[marginBottom4, marginTop4]}>
{Object.values(allGuilds).map(g => {
try {
let settings = getSetting(this.props.settingsKey, Object.values(allGuilds).map(g => g.id));
let isDisabled = settings.indexOf(g.id) < 0
let styles = {borderRadius: '50%', border: '3px solid #43b581', borderColor: '#43b581', boxSizing: 'border-box', cursor: 'pointer', margin: '3px', overflow: 'hidden'};
let disabled = {}
if (isDisabled) disabled = {borderColor: '#747f8d', filter: 'grayscale(100%) brightness(50%)'};
return (
<Clickable
className={[marginLeft8, marginBottom4, marginTop4]}
style={{...styles, ...disabled}}
onClick={() => {
if (!isDisabled) {
settings.splice(settings.indexOf(g.id), 1);
} else {
settings.push(g.id);
}
updateSetting(this.props.settingsKey, settings);
this.forceUpdate()
}}
>
<GuildTooltip includeActivity={false} guild={g}>
<GuildIconWrapper guild={g} />
</GuildTooltip>
</Clickable>
)
} catch(err) {
console.log(err);
return null
}
})}
</Flex>
</Modal.Content>
<Modal.Footer>
<Button
color={Button.Colors.GREEN}
className={marginLeft8}
onClick={closeModal}
>
Save & Close
</Button>
<Button
color={Button.Colors.BLUE}
className={marginLeft8}
onClick={() => {updateSetting(this.props.settingsKey, Object.values(allGuilds).map(g => g.id));this.forceUpdate()}}
>
Enable All
</Button>
<Button
color={Button.Colors.BLUE}
className={marginLeft8}
onClick={() => {updateSetting(this.props.settingsKey, []);this.forceUpdate()}}
>
Disable All
</Button>
</Modal.Footer>
</Modal>
</>
}
}
class ServerChooser extends React.PureComponent {
constructor(props) {
super(props);
try {
if (!this.props.settingsKey) {
console.log(
`%c[settingsKey:${this.constructor.name}]`, 'color: #f04747',
'This component requires a property named `settingsKey`. This is used for setting the guilds you select\nIf you\'re unable to solve this error, contact King Fish#4444 (499400512559382538) or comment on the gist.'
);
this.state = {error: `'settingsKey' is a required property to pass into '${this.constructor.name}'`}
} else {
try {
let ret = this.props.getSetting(this.props.settingsKey, []) // Test that it accepts two arguments
if (!ret) throw new Error(); // Make sure that getSetting returns something no matter what
try {
this.props.updateSetting(this.props.settingsKey, ret) // Test that it accepts two arguments
} catch (err) {
console.log(
`%c[updateSetting:${this.constructor.name}]`, 'color: #f04747',
'`updateSetting` is not a valid callback for this component. updateSetting should have two arguments.\nIf you\'re unable to solve this error, contact King Fish#4444 (499400512559382538) or comment on the gist.'
);
this.state = {error: `'updateSetting' is not a valid callback. See console for more details`}
}
} catch (err) {
console.log(
`%c[getSetting:${this.constructor.name}]`, 'color: #f04747',
'`getSetting` is not a valid callback for this component. getSetting should have two arguments and return the setting.\nIf you\'re unable to solve this error, contact King Fish#4444 (499400512559382538) or comment on the gist.'
);
this.state = {error: `'getSetting' is not a valid callback. See console for more details`}
}
}
} catch (err) {
console.log(`%c[${this.constructor.name}]`, 'color: #f04747', err);
}
}
render() {
return <>
<ButtonItem
note={this?.state?.error ? this?.state?.error : this.props.note || "Select some guilds"}
button={this.props.button || "Open Server Chooser"}
disabled={this?.state?.error}
onClick={() => open(() => React.createElement(ServerChooserModal, this.props))}
>
{this.props.title || (this.props.button || "Open Server Chooser")}
</ButtonItem>
</>
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment