├── .gitignore
├── LICENSE
├── README.md
├── commands
├── disable.js
├── enable.js
└── index.js
├── components
└── Settings.jsx
├── i18n
├── de.json
├── en-US.json
└── index.js
├── index.js
├── manifest.json
└── style.css
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 redstonekasi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # This plugin has been archived, it should continue to work in the future because Powercord is not updating v2 internals anymore.
2 |
3 | # Theme Toggler
4 | Simple plugin for [Powercord](https://powercord.dev) that allows toggling themes.
5 |
6 | ## Installation
7 | 1. Go to your powercord plugins folder. Run `git clone https://github.com/redstonekasi/theme-toggler`
8 | 2. Restart discord or fetch missing plugins.
9 |
--------------------------------------------------------------------------------
/commands/disable.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | command: 'disable',
3 | description: 'Allows you to disable a selected theme from the given list.',
4 | usage: '{c} [ theme ID ]',
5 | executor (args) {
6 | let result;
7 | const themeID = powercord.styleManager.getThemes().find(theme => theme.toLowerCase() === args[0].toLowerCase());
8 |
9 | if (powercord.styleManager.themes.has(themeID)) {
10 | if (!powercord.styleManager.isEnabled(themeID)) {
11 | result = `->> ERROR: Tried to disable an already disabled theme!
12 | (${themeID})`;
13 | } else {
14 | powercord.styleManager.disable(themeID);
15 | result = `+>> SUCCESS: Theme un-loaded!
16 | (${themeID})`;
17 | }
18 | } else {
19 | result = `->> ERROR: Tried to disbale a non-installed theme!
20 | (${args[0]})`;
21 | }
22 |
23 | return {
24 | send: false,
25 | result: `\`\`\`diff\n${result}\`\`\``
26 | };
27 | },
28 | autocomplete (args) {
29 | const themes = powercord.styleManager.getThemes()
30 | .sort((a, b) => a - b)
31 | .map(theme => powercord.styleManager.themes.get(theme));
32 |
33 | if (args.length > 1) {
34 | return false;
35 | }
36 |
37 | return {
38 | commands: themes
39 | .filter(theme => theme.entityID.toLowerCase().includes(args[0].toLowerCase()))
40 | .map(theme => ({
41 | command: theme.entityID,
42 | description: theme.manifest.description
43 | }))
44 | .slice(0, 10),
45 | header: 'powercord theme list'
46 | };
47 | }
48 | };
--------------------------------------------------------------------------------
/commands/enable.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | command: 'enable',
3 | description: 'Allows you to enable a selected theme from the given list.',
4 | usage: '{c} [ theme ID ]',
5 | executor (args) {
6 | let result;
7 | const themeID = powercord.styleManager.getThemes().find(theme => theme.toLowerCase() === args[0].toLowerCase());
8 |
9 | if (powercord.styleManager.themes.has(themeID)) {
10 | if (powercord.styleManager.isEnabled(themeID)) {
11 | result = `->> ERROR: Tried to load an already loaded theme!
12 | (${themeID})`;
13 | } else {
14 | powercord.styleManager.enable(themeID);
15 | result = `+>> SUCCESS: Theme loaded!
16 | (${themeID})`;
17 | }
18 | } else {
19 | result = `->> ERROR: Tried to enable a non-installed theme!
20 | (${args[0]})`;
21 | }
22 |
23 | return {
24 | send: false,
25 | result: `\`\`\`diff\n${result}\`\`\``
26 | };
27 | },
28 | autocomplete (args) {
29 | const themes = powercord.styleManager.getThemes()
30 | .sort((a, b) => a - b)
31 | .map(theme => powercord.styleManager.themes.get(theme));
32 |
33 | if (args.length > 1) {
34 | return false;
35 | }
36 |
37 | return {
38 | commands: themes
39 | .filter(theme => theme.entityID.toLowerCase().includes(args[0].toLowerCase()))
40 | .map(theme => ({
41 | command: theme.entityID,
42 | description: theme.manifest.description
43 | }))
44 | .slice(0, 10),
45 | header: 'powercord theme list'
46 | };
47 | }
48 | };
--------------------------------------------------------------------------------
/commands/index.js:
--------------------------------------------------------------------------------
1 | require('fs')
2 | .readdirSync(__dirname)
3 | .filter(file => file !== 'index.js')
4 | .forEach(filename => {
5 | const moduleName = filename.split('.')[0];
6 | exports[moduleName] = require(`${__dirname}/${filename}`);
7 | });
--------------------------------------------------------------------------------
/components/Settings.jsx:
--------------------------------------------------------------------------------
1 | const { React, contextMenu, i18n: { Messages } } = require('powercord/webpack');
2 | const { Divider, Button, ContextMenu, Icons: { Overflow } } = require('powercord/components');
3 |
4 | const { join } = require('path');
5 | const { shell } = require('electron');
6 |
7 | const InstalledProduct = require('../../pc-moduleManager/components/parts/InstalledProduct');
8 |
9 | module.exports = class ThemeTogglerSettings extends React.Component {
10 | constructor(props) {
11 | super(props);
12 | }
13 |
14 | render() {
15 | return (
16 |
17 |
18 |
{Messages[`POWERCORD_THEMES_INSTALLED`]}
19 |
20 |
23 |
26 | this.openContextMenu(e)} onContextMenu={e => this.openContextMenu(e)} />
27 |
28 |
29 |
30 | {this.renderBody()}
31 |
32 | );
33 | }
34 |
35 | renderBody() {
36 | const items = [];
37 | powercord.styleManager.themes.forEach(theme => items.push(this.renderItem(theme)));
38 |
39 | return (
40 |
41 | {items}
42 |
43 | );
44 | }
45 |
46 | renderItem(item) {
47 | return (
48 | {
52 | if (v) powercord.styleManager.enable(item.entityID);
53 | else powercord.styleManager.disable(item.entityID);
54 | }}
55 | />
56 | );
57 | }
58 |
59 | enableAll() {
60 | powercord.styleManager.themes.forEach(theme =>
61 | powercord.styleManager.enable(theme.entityID));
62 | }
63 |
64 | disableAll() {
65 | powercord.styleManager.themes.forEach(theme =>
66 | powercord.styleManager.disable(theme.entityID));
67 | }
68 |
69 | openContextMenu(e) {
70 | contextMenu.openContextMenu(e, () =>
71 | React.createElement(ContextMenu, {
72 | width: '50px',
73 | itemGroups: [
74 | [
75 | {
76 | type: 'button',
77 | name: Messages['POWERCORD_THEMES_OPEN_FOLDER'],
78 | onClick: () => shell.openPath(join(__dirname, '..', '..', '..', 'themes'))
79 | },
80 | {
81 | type: 'button',
82 | name: Messages['POWERCORD_THEMES_LOAD_MISSING'],
83 | onClick: () => this.loadMissing()
84 | },
85 | {
86 | type: 'checkbox',
87 | name: Messages['THEME_TOGGLER_INTEGRATE_TOGGLE'],
88 | defaultState: this.props.getSetting('integrate', false),
89 | onToggle: (state) => this.props.updateSetting('integrate', state)
90 | }
91 | ]
92 | ]
93 | })
94 | );
95 | }
96 |
97 | loadMissing() {
98 | powercord.pluginManager.get('pc-moduleManager')._fetchEntities('themes');
99 | }
100 | }
--------------------------------------------------------------------------------
/i18n/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "THEME_TOGGLER_ENABLE_ALL": "Alle aktivieren",
3 | "THEME_TOGGLER_DISABLE_ALL": "Alle deaktivieren",
4 | "THEME_TOGGLER_INTEGRATE_TOGGLE": "Integrate into \"Themes\""
5 | }
--------------------------------------------------------------------------------
/i18n/en-US.json:
--------------------------------------------------------------------------------
1 | {
2 | "THEME_TOGGLER_ENABLE_ALL": "Enable all",
3 | "THEME_TOGGLER_DISABLE_ALL": "Disable all",
4 | "THEME_TOGGLER_INTEGRATE_TOGGLE": "Integrate into \"Themes\""
5 | }
--------------------------------------------------------------------------------
/i18n/index.js:
--------------------------------------------------------------------------------
1 | require('fs')
2 | .readdirSync(__dirname)
3 | .filter(file => file !== 'index.js')
4 | .forEach(filename => {
5 | const moduleName = filename.split('.')[0];
6 | module.exports[moduleName] = require(`${__dirname}/${filename}`);
7 | });
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const { Plugin } = require('powercord/entities');
2 | const { inject, uninject } = require('powercord/injector');
3 | const { React } = require('powercord/webpack');
4 |
5 | const Settings = require('./components/Settings');
6 | const i18n = require('./i18n');
7 | const commands = require('./commands');
8 |
9 | const Base = require('../pc-moduleManager/components/manage/Base');
10 | const Themes = require('../pc-moduleManager/components/manage/Themes');
11 |
12 | module.exports = class ThemeToggler extends Plugin {
13 | startPlugin() {
14 | this.registerMain()
15 | this.loadStylesheet('style.css');
16 | powercord.api.i18n.loadAllStrings(i18n);
17 | powercord.api.settings.registerSettings('theme-toggler', {
18 | category: this.entityID,
19 | label: 'Theme Toggler',
20 | render: Settings
21 | });
22 |
23 | const _this = this;
24 | inject('tt-base-render', Base.prototype, 'render', function(_, res) {
25 | return this.state.key === 'THEMES' && _this.settings.get('integrate', false) ? this.renderBody() : res;
26 | });
27 |
28 | // powercord.api.settings.tabs[_this.entityID].render is the settings page connected to the flux decorator for this plugin
29 | inject('tt-themes-body', Themes.prototype, 'renderBody', function(_, res) {
30 | return _this.settings.get('integrate', false) ? React.createElement(powercord.api.settings.tabs[_this.entityID].render) : res;
31 | });
32 | }
33 |
34 | pluginWillUnload() {
35 | powercord.api.settings.unregisterSettings('theme-toggler');
36 | powercord.api.commands.unregisterCommand('theme');
37 |
38 | uninject('tt-base-render');
39 | uninject('tt-themes-body');
40 | }
41 |
42 | registerMain() {
43 | powercord.api.commands.registerCommand({
44 | command: 'theme',
45 | description: 'Enable and disable a theme.',
46 | usage: '{c} [ enable, disable ] [ theme ID ]',
47 | executor: (args) => {
48 | const subcommand = commands[args[0]];
49 | if (!subcommand) {
50 | return {
51 | send: false,
52 | result: `\`${args[0]}\` is not a valid subcommand. Specify one of ${Object.keys(commands).map(cmd => `\`${cmd}\``).join(', ')}.`
53 | };
54 | }
55 |
56 | return subcommand.executor(args.slice(1), this);
57 | },
58 | autocomplete: (args) => {
59 | if (args[0] !== void 0 && args.length === 1) {
60 | return {
61 | commands: Object.values(commands).filter(({ command }) => command.includes(args[0].toLowerCase())),
62 | header: 'theme subcommands'
63 | };
64 | }
65 |
66 | const subcommand = commands[args[0]];
67 | if (!subcommand || !subcommand.autocomplete) {
68 | return false;
69 | }
70 |
71 | return subcommand.autocomplete(args.slice(1), this.settings);
72 | }
73 | });
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Theme Toggler",
3 | "description": "Adds a new tab to toggle themes",
4 | "author": "redstonekasi#9696",
5 | "version": "1.2.0",
6 | "license": "MIT"
7 | }
8 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | .theme-toggler-buttons > button {
2 | margin-left: 12px;
3 | }
4 |
5 | .theme-toggler-buttons > svg {
6 | margin-left: 6px;
7 | }
--------------------------------------------------------------------------------