update gitignore
21
.gitignore
vendored
|
@ -1,21 +0,0 @@
|
||||||
BAZECOR
|
|
||||||
chromium
|
|
||||||
dconf
|
|
||||||
discord
|
|
||||||
EOS-arch-news.conf
|
|
||||||
EOS-arch-news-for-you.conf
|
|
||||||
EOS-greeter.conf
|
|
||||||
EOS-initial-wallpaper.XFCE
|
|
||||||
pavucontrol.ini
|
|
||||||
ristretto
|
|
||||||
systemd
|
|
||||||
Thunar
|
|
||||||
user-dirs.dirs
|
|
||||||
user-dirs.locale
|
|
||||||
xfce4
|
|
||||||
yay
|
|
||||||
.stack-work
|
|
||||||
**/.surf/cache
|
|
||||||
xmonad-x86_64-linux
|
|
||||||
__pycache__
|
|
||||||
*/kitty/kitty-themes
|
|
|
@ -1,72 +0,0 @@
|
||||||
*.background: #282828
|
|
||||||
color5: #ff0000
|
|
||||||
|
|
||||||
Xcursor.size: 16
|
|
||||||
Xcursor.theme: capitaine-cursors-light
|
|
||||||
|
|
||||||
Xft.autohint: 0
|
|
||||||
Xft.antialias: 1
|
|
||||||
Xft.hinting: true
|
|
||||||
Xft.hintstyle: hintslight
|
|
||||||
Xft.dpi: 96
|
|
||||||
Xft.rgba: rgb
|
|
||||||
Xft.lcdfilter: lcddefault
|
|
||||||
|
|
||||||
rofi.lines: 5
|
|
||||||
rofi.eh: 2
|
|
||||||
rofi.padding: 200
|
|
||||||
rofi.fullscreen: true
|
|
||||||
rofi.bw: 0
|
|
||||||
rofi.separator-style: none
|
|
||||||
rofi.hide-scrollbar: true
|
|
||||||
rofi.color-enabled: true
|
|
||||||
|
|
||||||
! 'background', 'border', 'separator'
|
|
||||||
rofi.color-window: argb:c82d303b, #7c8389, #1d1f21
|
|
||||||
! State: 'bg', 'fg', 'bgalt', 'hlbg', 'hlfg'
|
|
||||||
rofi.color-normal: argb:031d1f21, #f3f4f5, argb:031d1f21, argb:031d1f21, #9575cd
|
|
||||||
rofi.color-urgent: argb:031d1f21, #f3f4f5, argb:bc303541, argb:031d1f21, #9575cd
|
|
||||||
rofi.color-active: argb:031d1f21, #f3f4f5, argb:031d1f21, argb:031d1f21, #9575cd
|
|
||||||
rofi.font: System San Francisco Display 18
|
|
||||||
|
|
||||||
dzen.font: -*-fixed-medium-r-s*--12-87-*-*-*-*-iso10???-1
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
URxvt.font: xft:scientifica
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
!URxvt.color24: #076678
|
|
||||||
!URxvt.color66: #427b58
|
|
||||||
!URxvt.color88: #9d0006
|
|
||||||
!URxvt.color96: #8f3f71
|
|
||||||
!URxvt.color100: #79740e
|
|
||||||
!URxvt.color108: #8ec07c
|
|
||||||
!URxvt.color109: #83a598
|
|
||||||
!URxvt.color130: #af3a03
|
|
||||||
!URxvt.color136: #b57614
|
|
||||||
!URxvt.color142: #b8bb26
|
|
||||||
!URxvt.color167: #fb4934
|
|
||||||
!URxvt.color175: #d3869b
|
|
||||||
!URxvt.color208: #fe8019
|
|
||||||
!URxvt.color214: #fabd2f
|
|
||||||
!URxvt.color223: #ebdbb2
|
|
||||||
!URxvt.color228: #f2e5bc
|
|
||||||
!URxvt.color229: #fbf1c7
|
|
||||||
!URxvt.color230: #f9f5d7
|
|
||||||
!URxvt.color234: #1d2021
|
|
||||||
!URxvt.color235: #282828
|
|
||||||
!URxvt.color236: #32302f
|
|
||||||
!URxvt.color237: #3c3836
|
|
||||||
!URxvt.color239: #504945
|
|
||||||
!URxvt.color241: #665c54
|
|
||||||
!URxvt.color243: #7c6f64
|
|
||||||
!URxvt.color244: #928374
|
|
||||||
!URxvt.color245: #928374
|
|
||||||
!URxvt.color246: #a89984
|
|
||||||
!URxvt.color248: #bdae93
|
|
||||||
!URxvt.color250: #d5c4a1
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "eslint:recommended",
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"node": true,
|
|
||||||
"es6": true
|
|
||||||
},
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 8
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"no-console": "off",
|
|
||||||
"no-unused-vars": "warn",
|
|
||||||
"no-useless-escape": "warn",
|
|
||||||
"no-empty": "warn",
|
|
||||||
"no-var": "error",
|
|
||||||
"no-mixed-spaces-and-tabs": "warn",
|
|
||||||
"prefer-const": "warn"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
name: Discord Source detection
|
|
||||||
on: [issues]
|
|
||||||
jobs:
|
|
||||||
autoclose:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Autoclose Discord Source issues
|
|
||||||
uses: IndyV/IssueChecker@v1.0
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
issue-close-message: "@${issue.user.login} This issue was automatically closed because we don't accept issue reports from Discord Source.\nThe reason for this is because usually these issues aren't well thought out and are often duplicates.\n\nPlease take a few more minutes to create a well-made, proper issue report."
|
|
||||||
issue-pattern: "Discord Source - .Issue Report]"
|
|
3
files/.config/EnhancedDiscord/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
||||||
**/.vs
|
|
||||||
**/bin
|
|
||||||
**/obj
|
|
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2019 joe27g
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,48 +0,0 @@
|
||||||
# EnhancedDiscord
|
|
||||||
A lightweight client mod designed to enhance your Discord experience without slowing down your PC.
|
|
||||||
|
|
||||||
Support server:
|
|
||||||
<a href="https://discord.gg/XAvh9tq"><img src="https://discordapp.com/api/guilds/415246389287583755/embed.png" alt="Discord server" /></a>
|
|
||||||
(https://discord.gg/XAvh9tq)
|
|
||||||
|
|
||||||
#### DISCLAIMER!
|
|
||||||
> **Using EnhancedDiscord, or any other client mod, is against [Discord's Terms of Service](https://discordapp.com/terms). Use it at your own risk.**
|
|
||||||
> *It's very unlikely any action will be taken against you, but we take no responsibility if anything happens.*
|
|
||||||
|
|
||||||
By default, this loads my theme, with some settings applied. More info [on its repo](https://github.com/joe27g/Discord-Theme). To change this, edit `plugins/style.css` or change the theme location in settings.
|
|
||||||
|
|
||||||
You can download more quality plugins from the following repos:
|
|
||||||
- [joe27g/EnhancedDiscord-Plugins](https://github.com/joe27g/EnhancedDiscord-Plugins)
|
|
||||||
- [rauenzi/EnhancedDiscordPlugins](https://github.com/rauenzi/EnhancedDiscordPlugins)
|
|
||||||
- [jakuski/ed_plugins](https://github.com/jakuski/ed_plugins)
|
|
||||||
|
|
||||||
If you enable "BD Plugins" in the EnhancedDiscord settings, you can also load BetterDiscord plugins. See the #faq in the support server for more details.
|
|
||||||
*Note: some BD plugins are notorious for being laggy. In general, the fewer plugins you have, the faster your client will be.*
|
|
||||||
|
|
||||||
### Installing the easy way:
|
|
||||||
|
|
||||||
*Currently, only Windows and Ubuntu 18.04+ are supported for the new installer, due to lack of devices to compile on*
|
|
||||||
|
|
||||||
Go to https://enhanceddiscord.com/ and hit the 'Download' button, or if you're lazy, click [here](https://enhanceddiscord.com/EnhancedDiscord.exe).
|
|
||||||
|
|
||||||
If you're having errors (especially related to `InteropServices`), you may need to download [.NET Framework 4.7.1](https://www.microsoft.com/en-us/download/details.aspx?id=56116).
|
|
||||||
|
|
||||||
If you're on Linux or MacOS consider using [this install script](https://github.com/Cr3atable/LinuxED) that is specifically made for Unix.
|
|
||||||
LinuxED is unaffiliated with EnhancedDiscord so please do not request support for this script in an issue.
|
|
||||||
|
|
||||||
### Installing the hard way:
|
|
||||||
|
|
||||||
If the installer doesn't work for you, and you choose not to use LinuxED, you can also install it manually in just a few minutes.
|
|
||||||
To do so, see the [advanced installation guide](/advanced_installation.md).
|
|
||||||
|
|
||||||
### Explanation of files:
|
|
||||||
|
|
||||||
From now on, please refer to https://enhanceddiscord.com for explanations of included plugins.
|
|
||||||
|
|
||||||
### Custom plugins
|
|
||||||
|
|
||||||
To create your own plugin, check out [the plugin readme](/plugins.md).
|
|
||||||
|
|
||||||
### Contributing
|
|
||||||
|
|
||||||
Feel free to make pull requests or make your own plugins repository. If you do make your own plugins, request the 'Plugin Developer' role in the support server so you can announce your releases!
|
|
|
@ -1,26 +0,0 @@
|
||||||
# Installing the hard way
|
|
||||||
|
|
||||||
#### Recommended for people that have trouble with the installers or really like wasting time.
|
|
||||||
|
|
||||||
1. Download/clone this repo to wherever you want your ED files to reside.
|
|
||||||
|
|
||||||
2. Find your appdata folder:
|
|
||||||
- For PC: `%appdata%/discord`
|
|
||||||
- For Mac: `~/Library/Application Support`
|
|
||||||
- For Linux: `$XDG_CONFIG_HOME/discord` or `~/.config/discord/`
|
|
||||||
- *Replace `discord` with `discordcanary` etc. as needed.*
|
|
||||||
|
|
||||||
3. In the appdata folder, find `/x.x.xxx/modules/discord_desktop_core/index.js`, where `x.x.xxx` is your current version of the Discord client, and open it.
|
|
||||||
|
|
||||||
4. At the top, add these lines:
|
|
||||||
```js
|
|
||||||
process.env.injDir = '<path>';
|
|
||||||
require(`${process.env.injDir}/injection.js`);
|
|
||||||
```
|
|
||||||
where `<path>` is the location of the ED folder.
|
|
||||||
|
|
||||||
Make sure to escape paths, for example `C:\Users\<Username>\Documents\EnhancedDiscord\EnhancedDiscord` should be `C:\\Users\\<Username>\\Documents\\EnhancedDiscord\\EnhancedDiscord`
|
|
||||||
|
|
||||||
5. Create `config.json` in your ED folder and set its contents to `{}`.
|
|
||||||
|
|
||||||
6. Restart your Discord client and installation should be complete.
|
|
|
@ -1,245 +0,0 @@
|
||||||
#bd-settingspane-container h2.ui-form-title {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 600;
|
|
||||||
line-height: 20px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
display: inline-block;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
#bd-settingspane-container h2.ui-form-title {
|
|
||||||
color: #f6f6f7;
|
|
||||||
}
|
|
||||||
.theme-light #bd-settingspane-container h2.ui-form-title {
|
|
||||||
color: #4f545c;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container .ui-switch-item {
|
|
||||||
flex-direction: column;
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container .ui-switch-item h3 {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 24px;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
#bd-settingspane-container .ui-switch-item h3 {
|
|
||||||
color: #f6f6f7;
|
|
||||||
}
|
|
||||||
.theme-light #bd-settingspane-container .ui-switch-item h3 {
|
|
||||||
color: #4f545c;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container .ui-switch-item .style-description {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 20px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
border-bottom: 1px solid hsla(218,5%,47%,.3);
|
|
||||||
}
|
|
||||||
#bd-settingspane-container .ui-switch-item .style-description {
|
|
||||||
color: #72767d;
|
|
||||||
}
|
|
||||||
.theme-light #bd-settingspane-container .ui-switch-item .style-description {
|
|
||||||
color: rgba(114,118,125,.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container .ui-switch-item .ui-switch-wrapper {
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
position: relative;
|
|
||||||
width: 44px;
|
|
||||||
height: 24px;
|
|
||||||
display: block;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container .ui-switch-item .ui-switch-wrapper input {
|
|
||||||
position: absolute;
|
|
||||||
opacity: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container .ui-switch-item .ui-switch-wrapper .ui-switch {
|
|
||||||
background: #7289da;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
background: #72767d;
|
|
||||||
border-radius: 14px;
|
|
||||||
transition: background .15s ease-in-out,box-shadow .15s ease-in-out,border .15s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container .ui-switch-item .ui-switch-wrapper .ui-switch:before {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
position: absolute;
|
|
||||||
top: 3px;
|
|
||||||
left: 3px;
|
|
||||||
bottom: 3px;
|
|
||||||
background: #f6f6f7;
|
|
||||||
border-radius: 10px;
|
|
||||||
transition: all .15s ease;
|
|
||||||
box-shadow: 0 3px 1px 0 rgba(0,0,0,.05),0 2px 2px 0 rgba(0,0,0,.1),0 3px 3px 0 rgba(0,0,0,.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container .ui-switch-item .ui-switch-wrapper .ui-switch.checked {
|
|
||||||
background: #7289da;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container .ui-switch-item .ui-switch-wrapper .ui-switch.checked:before {
|
|
||||||
transform: translateX(20px);
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container .plugin-settings {
|
|
||||||
padding: 0 12px 12px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes bd-modal-backdrop {
|
|
||||||
to { opacity: 0.85; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes bd-modal-anim {
|
|
||||||
to { transform: scale(1); opacity: 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes bd-modal-backdrop-closing {
|
|
||||||
to { opacity: 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes bd-modal-closing {
|
|
||||||
to { transform: scale(0.7); opacity: 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container .backdrop {
|
|
||||||
animation: bd-modal-backdrop 250ms ease;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
background-color: rgb(0, 0, 0);
|
|
||||||
transform: translateZ(0px);
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container.closing .backdrop {
|
|
||||||
animation: bd-modal-backdrop-closing 200ms linear;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
animation-delay: 50ms;
|
|
||||||
opacity: 0.85;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container.closing .modal {
|
|
||||||
animation: bd-modal-closing 250ms cubic-bezier(0.19, 1, 0.22, 1);
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#bd-settingspane-container .modal {
|
|
||||||
animation: bd-modal-anim 250ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
transform: scale(0.7);
|
|
||||||
transform-origin: 50% 50%;
|
|
||||||
}
|
|
||||||
/* Toast CSS */
|
|
||||||
|
|
||||||
.toasts {
|
|
||||||
position: fixed;
|
|
||||||
display: flex;
|
|
||||||
top: 0;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 4000;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes toast-up {
|
|
||||||
from {
|
|
||||||
transform: translateY(0);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast {
|
|
||||||
animation: toast-up 300ms ease;
|
|
||||||
transform: translateY(-10px);
|
|
||||||
background: #36393F;
|
|
||||||
padding: 10px;
|
|
||||||
border-radius: 5px;
|
|
||||||
box-shadow: 0 0 0 1px rgba(32,34,37,.6), 0 2px 10px 0 rgba(0,0,0,.2);
|
|
||||||
font-weight: 500;
|
|
||||||
color: #fff;
|
|
||||||
user-select: text;
|
|
||||||
font-size: 14px;
|
|
||||||
opacity: 1;
|
|
||||||
margin-top: 10px;
|
|
||||||
pointer-events: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes toast-down {
|
|
||||||
to {
|
|
||||||
transform: translateY(0px);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast.closing {
|
|
||||||
animation: toast-down 200ms ease;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(-10px);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.toast.icon {
|
|
||||||
padding-left: 30px;
|
|
||||||
background-size: 20px 20px;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: 6px 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast.toast-info {
|
|
||||||
background-color: #4a90e2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast.toast-info.icon {
|
|
||||||
background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPiAgICA8cGF0aCBkPSJNMTIgMkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMCAxMC00LjQ4IDEwLTEwUzE3LjUyIDIgMTIgMnptMSAxNWgtMnYtNmgydjZ6bTAtOGgtMlY3aDJ2MnoiLz48L3N2Zz4=);
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast.toast-success {
|
|
||||||
background-color: #43b581;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast.toast-success.icon {
|
|
||||||
background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPiAgICA8cGF0aCBkPSJNMTIgMkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMCAxMC00LjQ4IDEwLTEwUzE3LjUyIDIgMTIgMnptLTIgMTVsLTUtNSAxLjQxLTEuNDFMMTAgMTQuMTdsNy41OS03LjU5TDE5IDhsLTkgOXoiLz48L3N2Zz4=);
|
|
||||||
}
|
|
||||||
.toast.toast-danger,
|
|
||||||
.toast.toast-error {
|
|
||||||
background-color: #f04747;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast.toast-danger.icon,
|
|
||||||
.toast.toast-error.icon {
|
|
||||||
background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTEyIDJDNi40NyAyIDIgNi40NyAyIDEyczQuNDcgMTAgMTAgMTAgMTAtNC40NyAxMC0xMFMxNy41MyAyIDEyIDJ6bTUgMTMuNTlMMTUuNTkgMTcgMTIgMTMuNDEgOC40MSAxNyA3IDE1LjU5IDEwLjU5IDEyIDcgOC40MSA4LjQxIDcgMTIgMTAuNTkgMTUuNTkgNyAxNyA4LjQxIDEzLjQxIDEyIDE3IDE1LjU5eiIvPiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PC9zdmc+);
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast.toast-warning,
|
|
||||||
.toast.toast-warn {
|
|
||||||
background-color: #FFA600;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast.toast-warning.icon,
|
|
||||||
.toast.toast-warn.icon {
|
|
||||||
background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPiAgICA8cGF0aCBkPSJNMSAyMWgyMkwxMiAyIDEgMjF6bTEyLTNoLTJ2LTJoMnYyem0wLTRoLTJ2LTRoMnY0eiIvPjwvc3ZnPg==);
|
|
||||||
}
|
|
|
@ -1,158 +0,0 @@
|
||||||
const path = require('path');
|
|
||||||
const fs = require('fs');
|
|
||||||
const Module = require('module').Module;
|
|
||||||
const originalRequire = Module._extensions['.js'];
|
|
||||||
const EDPlugin = require('./plugin');
|
|
||||||
|
|
||||||
module.exports = class BDManager {
|
|
||||||
|
|
||||||
static async setup(currentWindow) {
|
|
||||||
this.currentWindow = currentWindow;
|
|
||||||
this.defineGlobals();
|
|
||||||
this.jqueryElement = document.createElement('script');
|
|
||||||
this.jqueryElement.src = `//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js`;
|
|
||||||
await new Promise(resolve => {
|
|
||||||
this.jqueryElement.onload = resolve;
|
|
||||||
document.head.appendChild(this.jqueryElement);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.observer = new MutationObserver((mutations) => {
|
|
||||||
for (let i = 0, mlen = mutations.length; i < mlen; i++) this.fireEvent('observer', mutations[i]);
|
|
||||||
});
|
|
||||||
this.observer.observe(document, {childList: true, subtree: true});
|
|
||||||
|
|
||||||
this.currentWindow.webContents.on('did-navigate-in-page', BDManager.onSwitch);
|
|
||||||
|
|
||||||
fs.readFile(path.join(process.env.injDir, 'bd.css'), (err, text) => {
|
|
||||||
if (err) return console.error(err);
|
|
||||||
window.EDApi.injectCSS('BDManager', text);
|
|
||||||
})
|
|
||||||
|
|
||||||
Module._extensions['.js'] = this.pluginRequire();
|
|
||||||
}
|
|
||||||
|
|
||||||
static destroy() {
|
|
||||||
window.EDApi.clearCSS('BDManager');
|
|
||||||
this.observer.disconnect();
|
|
||||||
this.currentWindow.webContents.removeEventListener('did-navigate-in-page', BDManager.onSwitch);
|
|
||||||
this.jqueryElement.remove();
|
|
||||||
Module._extensions['.js'] = originalRequire;
|
|
||||||
}
|
|
||||||
|
|
||||||
static onSwitch() {
|
|
||||||
BDManager.fireEvent('onSwitch');
|
|
||||||
}
|
|
||||||
|
|
||||||
static extractMeta(content) {
|
|
||||||
const meta = content.split('\n')[0];
|
|
||||||
const rawMeta = meta.substring(meta.lastIndexOf('//META') + 6, meta.lastIndexOf('*//'));
|
|
||||||
if (meta.indexOf('META') < 0) throw new Error('META was not found.');
|
|
||||||
if (!window.EDApi.testJSON(rawMeta)) throw new Error('META could not be parsed.');
|
|
||||||
|
|
||||||
const parsed = JSON.parse(rawMeta);
|
|
||||||
if (!parsed.name) throw new Error('META missing name data.');
|
|
||||||
return parsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
static pluginRequire() {
|
|
||||||
return function(moduleWrap, filename) {
|
|
||||||
if (!filename.endsWith('.plugin.js') || path.dirname(filename) !== path.resolve(process.env.injDir, 'plugins')) return Reflect.apply(originalRequire, this, arguments);
|
|
||||||
let content = fs.readFileSync(filename, 'utf8');
|
|
||||||
if (content.charCodeAt(0) === 0xFEFF) content = content.slice(1); // Strip BOM
|
|
||||||
const meta = BDManager.extractMeta(content);
|
|
||||||
meta.filename = path.basename(filename);
|
|
||||||
content += `\nmodule.exports = ${meta.name};`;
|
|
||||||
moduleWrap._compile(content, filename);
|
|
||||||
moduleWrap.exports = BDManager.convertPlugin(new moduleWrap.exports());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static fireEvent(event, ...args) {
|
|
||||||
const plugins = Object.values(window.ED.plugins);
|
|
||||||
for (let p = 0; p < plugins.length; p++) {
|
|
||||||
const plugin = plugins[p];
|
|
||||||
if (!plugin[event] || typeof plugin[event] !== 'function') continue;
|
|
||||||
try { plugin[event](...args); }
|
|
||||||
catch (error) { throw new Error(`Could not fire ${event} for plugin ${plugin.name}.`); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static convertPlugin(plugin) {
|
|
||||||
const newPlugin = new EDPlugin({
|
|
||||||
name: plugin.getName(),
|
|
||||||
load: function() {plugin.start();},
|
|
||||||
unload: function() {plugin.stop();},
|
|
||||||
bdplugin: plugin
|
|
||||||
});
|
|
||||||
Object.defineProperties(newPlugin, {
|
|
||||||
name: {
|
|
||||||
enumerable: true, configurable: true,
|
|
||||||
get() {return plugin.getName();}
|
|
||||||
},
|
|
||||||
author: {
|
|
||||||
enumerable: true, configurable: true,
|
|
||||||
get() {return plugin.getAuthor();}
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
enumerable: true, configurable: true,
|
|
||||||
get() {return plugin.getDescription();}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (typeof plugin.getSettingsPanel == 'function') newPlugin.getSettingsPanel = function() {return plugin.getSettingsPanel();};
|
|
||||||
if (typeof plugin.onSwitch == 'function') newPlugin.onSwitch = function() {return plugin.onSwitch();};
|
|
||||||
if (typeof plugin.observer == 'function') newPlugin.observer = function(e) {return plugin.observer(e);};
|
|
||||||
return newPlugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
static defineGlobals() {
|
|
||||||
window.bdConfig = {dataPath: process.env.injDir};
|
|
||||||
window.bdplugins = window.bdthemes = window.pluginCookie = window.themeCookie = window.settingsCookie = {};
|
|
||||||
window.bdpluginErrors = window.bdthemeErrors = [];
|
|
||||||
|
|
||||||
window.bdPluginStorage = {get: window.EDApi.getData, set: window.EDApi.setData};
|
|
||||||
window.Utils = {monkeyPatch: window.EDApi.monkeyPatch, suppressErrors: window.EDApi.suppressErrors, escapeID: window.EDApi.escapeID};
|
|
||||||
|
|
||||||
window.BDV2 = class V2 {
|
|
||||||
static get WebpackModules() {return {find: window.EDApi.findModule, findAll: window.EDApi.findAllModules, findByUniqueProperties: window.EDApi.findModuleByProps, findByDisplayName: window.EDApi.findModuleByDisplayName};}
|
|
||||||
static getInternalInstance(node) {return window.EDApi.getInternalInstance(node);}
|
|
||||||
static get react() {return window.EDApi.React;}
|
|
||||||
static get reactDom() {return window.EDApi.ReactDOM;}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static showSettingsModal(plugin) {
|
|
||||||
const baseModalClasses = window.EDApi.findModule(m => m.modal && m.inner && !m.sizeMedium) || {modal: "modal-36zFtW", inner: "inner-2VEzy9"};
|
|
||||||
const modalClasses = window.EDApi.findModuleByProps("modal", "sizeMedium") || {modal: "backdrop-1wrmKb", sizeMedium: "sizeMedium-ctncE5", content: "content-2KoCOZ", header: "header-2nhbou", footer: "footer-30ewN8", close: "close-hhyjWJ", inner: "inner-2Z5QZX"};
|
|
||||||
const backdrop = window.EDApi.findModuleByProps("backdrop") || {backdrop: "backdrop-1wrmKb"};
|
|
||||||
const modalHTML = `<div id="bd-settingspane-container" class="theme-dark">
|
|
||||||
<div class="backdrop ${backdrop.backdrop}" style="background-color: rgb(0, 0, 0); opacity: 0.85;"></div>
|
|
||||||
<div class="modal ${baseModalClasses.modal}" style="opacity: 1;">
|
|
||||||
<div class="${baseModalClasses.inner}">
|
|
||||||
<div class="${modalClasses.modal} ${modalClasses.sizeMedium}" style="overflow: hidden;">
|
|
||||||
<div class="flex-1xMQg5 flex-1O1GKY horizontal-1ae9ci horizontal-2EEEnY flex-1O1GKY directionRow-3v3tfG justifyStart-2NDFzi alignCenter-1dQNNs noWrap-3jynv6 ${modalClasses.header}">
|
|
||||||
<h4 class="title h4-AQvcAz title-3sZWYQ size16-14cGz5 height20-mO2eIN weightSemiBold-NJexzi defaultColor-1_ajX0 defaultMarginh4-2vWMG5 marginReset-236NPn">{{modalTitle}}</h4>
|
|
||||||
<svg viewBox="0 0 12 12" name="Close" width="18" height="18" class="close-button ${modalClasses.close} flexChild-faoVW3"><g fill="none" fill-rule="evenodd"><path d="M0 0h12v12H0"></path><path class="fill" fill="currentColor" d="M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6"></path></g></svg>
|
|
||||||
</div>
|
|
||||||
<div class="scrollerWrap-2lJEkd scrollerThemed-2oenus themeGhostHairline-DBD-2d ${modalClasses.content}">
|
|
||||||
<div id="{{id}}" class="scroller-2FKFPG ${modalClasses.inner} selectable plugin-settings" data-no-focus-lock="true">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1xMQg5 flex-1O1GKY horizontalReverse-2eTKWD horizontalReverse-3tRjY7 flex-1O1GKY directionRowReverse-m8IjIq justifyStart-2NDFzi alignStretch-DpGPf3 noWrap-3jynv6 ${modalClasses.footer}" style="flex: 0 0 auto;"><button type="button" class="done-button button-38aScr lookFilled-1Gx00P colorBrand-3pXr91 sizeMedium-1AC_Sl grow-q77ONN"><div class="contents-18-Yxp">Done</div></button></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
const panel = plugin.getSettingsPanel();
|
|
||||||
if (!panel) return;
|
|
||||||
const modal = window.$(window.EDApi.formatString(modalHTML, {modalTitle: `${plugin.name} Settings`, id: `plugin-settings-${plugin.name}`}));
|
|
||||||
if (typeof panel == 'string') modal.find('.plugin-settings').html(panel);
|
|
||||||
else modal.find('.plugin-settings').append(panel);
|
|
||||||
modal.find('.backdrop, .close-button, .done-button').on('click', () => {
|
|
||||||
modal.addClass('closing');
|
|
||||||
setTimeout(() => { modal.remove(); }, 300);
|
|
||||||
});
|
|
||||||
modal.appendTo('#app-mount');
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1 +0,0 @@
|
||||||
{"anti_track":{"enabled":false},"avatar_links":{"enabled":false},"char_count":{"enabled":false},"css_loader":{"path":"glasscord_css.css","enabled":false},"direct_download":{"enabled":false},"double_click_edit":{"enabled":false},"double_click_mention":{"enabled":false},"ed_settings":{"enabled":true},"friend_count":{"onlineOnly":false,"enabled":false},"guild_count":{"enabled":false},"hidden_channels":{"enabled":false},"quick_save":{"enabled":false},"silence":{"enabled":false},"silent_typing":{"enabled":false},"tag_all":{"enabled":false}}
|
|
|
@ -1,456 +0,0 @@
|
||||||
const path = window.require('path');
|
|
||||||
const fs = window.require('fs');
|
|
||||||
const electron = window.require('electron');
|
|
||||||
const Module = window.require('module').Module;
|
|
||||||
Module.globalPaths.push(path.resolve(electron.remote.app.getAppPath(), 'node_modules'));
|
|
||||||
const currentWindow = electron.remote.getCurrentWindow();
|
|
||||||
if (currentWindow.__preload) require(currentWindow.__preload);
|
|
||||||
|
|
||||||
//Get inject directory
|
|
||||||
if (!process.env.injDir) process.env.injDir = __dirname;
|
|
||||||
|
|
||||||
//set up global functions
|
|
||||||
const c = {
|
|
||||||
log: function(msg, plugin) {
|
|
||||||
if (plugin && plugin.name)
|
|
||||||
console.log(`%c[EnhancedDiscord] %c[${plugin.name}]`, 'color: red;', `color: ${plugin.color}`, msg);
|
|
||||||
else console.log('%c[EnhancedDiscord]', 'color: red;', msg);
|
|
||||||
},
|
|
||||||
info: function(msg, plugin) {
|
|
||||||
if (plugin && plugin.name)
|
|
||||||
console.info(`%c[EnhancedDiscord] %c[${plugin.name}]`, 'color: red;', `color: ${plugin.color}`, msg);
|
|
||||||
else console.info('%c[EnhancedDiscord]', 'color: red;', msg);
|
|
||||||
},
|
|
||||||
warn: function(msg, plugin) {
|
|
||||||
if (plugin && plugin.name)
|
|
||||||
console.warn(`%c[EnhancedDiscord] %c[${plugin.name}]`, 'color: red;', `color: ${plugin.color}`, msg);
|
|
||||||
else console.warn('%c[EnhancedDiscord]', 'color: red;', msg);
|
|
||||||
},
|
|
||||||
error: function(msg, plugin) {
|
|
||||||
if (plugin && plugin.name)
|
|
||||||
console.error(`%c[EnhancedDiscord] %c[${plugin.name}]`, 'color: red;', `color: ${plugin.color}`, msg);
|
|
||||||
else console.error('%c[EnhancedDiscord]', 'color: red;', msg);
|
|
||||||
},
|
|
||||||
sleep: function(ms) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
setTimeout(resolve, ms);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// config util
|
|
||||||
window.ED = { plugins: {}, version: '2.6.2' };
|
|
||||||
Object.defineProperty(window.ED, 'config', {
|
|
||||||
get: function() {
|
|
||||||
let conf;
|
|
||||||
try{
|
|
||||||
conf = require('./config.json');
|
|
||||||
} catch (err) {
|
|
||||||
if(err.code !== 'MODULE_NOT_FOUND')
|
|
||||||
c.error(err);
|
|
||||||
conf = {};
|
|
||||||
}
|
|
||||||
return conf;
|
|
||||||
},
|
|
||||||
set: function(newSets = {}) {
|
|
||||||
let confPath;
|
|
||||||
let bDelCache;
|
|
||||||
try{
|
|
||||||
confPath = require.resolve('./config.json');
|
|
||||||
bDelCache = true;
|
|
||||||
} catch (err) {
|
|
||||||
if(err.code !== 'MODULE_NOT_FOUND')
|
|
||||||
c.error(err);
|
|
||||||
confPath = path.join(process.env.injDir, 'config.json');
|
|
||||||
bDelCache = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
fs.writeFileSync(confPath, JSON.stringify(newSets));
|
|
||||||
if(bDelCache)
|
|
||||||
delete require.cache[confPath];
|
|
||||||
} catch(err) {
|
|
||||||
c.error(err);
|
|
||||||
}
|
|
||||||
return this.config;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function loadPlugin(plugin) {
|
|
||||||
try {
|
|
||||||
if (plugin.preload)
|
|
||||||
console.log(`%c[EnhancedDiscord] %c[PRELOAD] %cLoading plugin %c${plugin.name}`, 'color: red;', 'color: yellow;', '', `color: ${plugin.color}`, `by ${plugin.author}...`);
|
|
||||||
else console.log(`%c[EnhancedDiscord] %cLoading plugin %c${plugin.name}`, 'color: red;', '', `color: ${plugin.color}`, `by ${plugin.author}...`);
|
|
||||||
plugin.load();
|
|
||||||
} catch(err) {
|
|
||||||
c.error(`Failed to load:\n${err.stack}`, plugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.ED.localStorage = window.localStorage;
|
|
||||||
|
|
||||||
process.once("loaded", async () => {
|
|
||||||
c.log(`v${window.ED.version} is running. Validating plugins...`);
|
|
||||||
|
|
||||||
const pluginFiles = fs.readdirSync(path.join(process.env.injDir, 'plugins'));
|
|
||||||
const plugins = {};
|
|
||||||
for (const i in pluginFiles) {
|
|
||||||
if (!pluginFiles[i].endsWith('.js') || pluginFiles[i].endsWith(".plugin.js")) continue;
|
|
||||||
let p;
|
|
||||||
const pName = pluginFiles[i].replace(/\.js$/, '');
|
|
||||||
try {
|
|
||||||
p = require(path.join(process.env.injDir, 'plugins', pName));
|
|
||||||
if (typeof p.name !== 'string' || typeof p.load !== 'function') {
|
|
||||||
throw new Error('Plugin must have a name and load() function.');
|
|
||||||
}
|
|
||||||
plugins[pName] = Object.assign(p, {id: pName});
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
c.warn(`Failed to load ${pluginFiles[i]}: ${err}\n${err.stack}`, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const id in plugins) {
|
|
||||||
if (!plugins[id] || !plugins[id].name || typeof plugins[id].load !== 'function') {
|
|
||||||
c.info(`Skipping invalid plugin: ${id}`); delete plugins[id]; continue;
|
|
||||||
}
|
|
||||||
plugins[id].settings; // this will set default settings in config if necessary
|
|
||||||
}
|
|
||||||
window.ED.plugins = plugins;
|
|
||||||
c.log(`Plugins validated.`);
|
|
||||||
|
|
||||||
while (!window.webpackJsonp)
|
|
||||||
await c.sleep(100); // wait until this is loaded in order to use it for modules
|
|
||||||
|
|
||||||
window.ED.webSocket = window._ws;
|
|
||||||
|
|
||||||
/* Add helper functions that make plugins easy to create */
|
|
||||||
window.req = window.webpackJsonp.push([[], {
|
|
||||||
'__extra_id__': (module, exports, req) => module.exports = req
|
|
||||||
}, [['__extra_id__']]]);
|
|
||||||
delete window.req.m['__extra_id__'];
|
|
||||||
delete window.req.c['__extra_id__'];
|
|
||||||
|
|
||||||
window.findModule = window.EDApi.findModule;
|
|
||||||
window.findModules = window.EDApi.findAllModules;
|
|
||||||
window.findRawModule = window.EDApi.findRawModule;
|
|
||||||
window.monkeyPatch = window.EDApi.monkeyPatch;
|
|
||||||
|
|
||||||
while (!window.EDApi.findModule('dispatch'))
|
|
||||||
await c.sleep(100);
|
|
||||||
|
|
||||||
c.log(`Loading preload plugins...`);
|
|
||||||
for (const id in plugins) {
|
|
||||||
if (window.ED.config[id] && window.ED.config[id].enabled == false) continue;
|
|
||||||
if (!plugins[id].preload) continue;
|
|
||||||
loadPlugin(plugins[id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const d = {resolve: () => {}};
|
|
||||||
window.monkeyPatch(window.findModule('dispatch'), 'dispatch', {before: b => {
|
|
||||||
// modules seem to all be loaded when RPC server loads
|
|
||||||
if (b.methodArguments[0].type === 'RPC_SERVER_READY') {
|
|
||||||
window.findModule('dispatch').dispatch.unpatch();
|
|
||||||
d.resolve();
|
|
||||||
}
|
|
||||||
}});
|
|
||||||
|
|
||||||
await new Promise(resolve => {
|
|
||||||
d.resolve = resolve;
|
|
||||||
})
|
|
||||||
c.log(`Modules done loading (${Object.keys(window.req.c).length})`);
|
|
||||||
|
|
||||||
if (window.ED.config.bdPlugins) {
|
|
||||||
await require('./bd_shit').setup(currentWindow);
|
|
||||||
c.log(`Preparing BD plugins...`);
|
|
||||||
for (const i in pluginFiles) {
|
|
||||||
if (!pluginFiles[i].endsWith('.js') || !pluginFiles[i].endsWith(".plugin.js")) continue;
|
|
||||||
let p;
|
|
||||||
const pName = pluginFiles[i].replace(/\.js$/, '');
|
|
||||||
try {
|
|
||||||
p = require(path.join(process.env.injDir, 'plugins', pName));
|
|
||||||
if (typeof p.name !== 'string' || typeof p.load !== 'function') {
|
|
||||||
throw new Error('Plugin must have a name and load() function.');
|
|
||||||
}
|
|
||||||
plugins[pName] = Object.assign(p, {id: pName});
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
c.warn(`Failed to load ${pluginFiles[i]}: ${err}\n${err.stack}`, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const id in plugins) {
|
|
||||||
if (!plugins[id] || !plugins[id].name || typeof plugins[id].load !== 'function') {
|
|
||||||
c.info(`Skipping invalid plugin: ${id}`); delete plugins[id]; continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.log(`Loading plugins...`);
|
|
||||||
for (const id in plugins) {
|
|
||||||
if (window.ED.config[id] && window.ED.config[id].enabled == false) continue;
|
|
||||||
if (plugins[id].preload) continue;
|
|
||||||
if (window.ED.config[id].enabled !== true && plugins[id].disabledByDefault) {
|
|
||||||
plugins[id].settings.enabled = false; continue;
|
|
||||||
}
|
|
||||||
loadPlugin(plugins[id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const ht = window.EDApi.findModule('hideToken')
|
|
||||||
// prevent client from removing token from localstorage when dev tools is opened, or reverting your token if you change it
|
|
||||||
window.EDApi.monkeyPatch(ht, 'hideToken', () => {});
|
|
||||||
window.fixedShowToken = () => {
|
|
||||||
// Only allow this to add a token, not replace it. This allows for changing of the token in dev tools.
|
|
||||||
if (!window.ED.localStorage || window.ED.localStorage.getItem("token")) return;
|
|
||||||
return window.ED.localStorage.setItem("token", '"'+ht.getToken()+'"');
|
|
||||||
};
|
|
||||||
window.EDApi.monkeyPatch(ht, 'showToken', window.fixedShowToken);
|
|
||||||
if (!window.ED.localStorage.getItem("token") && ht.getToken())
|
|
||||||
window.fixedShowToken(); // prevent you from being logged out for no reason
|
|
||||||
|
|
||||||
// change the console warning to be more fun
|
|
||||||
const wc = require('electron').remote.getCurrentWebContents();
|
|
||||||
wc.removeAllListeners("devtools-opened");
|
|
||||||
wc.on("devtools-opened", () => {
|
|
||||||
console.log("%cHold Up!", "color: #FF5200; -webkit-text-stroke: 2px black; font-size: 72px; font-weight: bold;");
|
|
||||||
console.log("%cIf you're reading this, you're probably smarter than most Discord developers.", "font-size: 16px;");
|
|
||||||
console.log("%cPasting anything in here could actually improve the Discord client.", "font-size: 18px; font-weight: bold; color: red;");
|
|
||||||
console.log("%cUnless you understand exactly what you're doing, keep this window open to browse our bad code.", "font-size: 16px;");
|
|
||||||
console.log("%cIf you don't understand exactly what you're doing, you should come work with us: https://discordapp.com/jobs", "font-size: 16px;");
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* BD/ED joint api */
|
|
||||||
window.EDApi = window.BdApi = class EDApi {
|
|
||||||
static get React() { return this.findModuleByProps('createElement'); }
|
|
||||||
static get ReactDOM() { return this.findModuleByProps('findDOMNode'); }
|
|
||||||
|
|
||||||
static escapeID(id) {
|
|
||||||
return id.replace(/^[^a-z]+|[^\w-]+/gi, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
static injectCSS(id, css) {
|
|
||||||
const style = document.createElement("style");
|
|
||||||
style.id = this.escapeID(id);
|
|
||||||
style.innerHTML = css;
|
|
||||||
document.head.append(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
static clearCSS(id) {
|
|
||||||
const element = document.getElementById(this.escapeID(id));
|
|
||||||
if (element) element.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
static linkJS(id, url) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
const script = document.createElement("script");
|
|
||||||
script.id = this.escapeID(id);
|
|
||||||
script.src = url;
|
|
||||||
script.type = "text/javascript";
|
|
||||||
script.onload = resolve;
|
|
||||||
document.head.append(script);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static unlinkJS(id) {
|
|
||||||
const element = document.getElementById(this.escapeID(id));
|
|
||||||
if (element) element.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
static getPlugin(name) {
|
|
||||||
const plugin = Object.values(window.ED.plugins).find(p => p.name == name);
|
|
||||||
if (!plugin) return null;
|
|
||||||
return plugin.bdplugin ? plugin.bdplugin : plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
static alert(title, body) {
|
|
||||||
const ModalStack = this.findModuleByProps("push", "update", "pop", "popWithKey");
|
|
||||||
const AlertModal = this.findModule(m => m.prototype && m.prototype.handleCancel && m.prototype.handleSubmit && m.prototype.handleMinorConfirm);
|
|
||||||
if (!ModalStack || !AlertModal) return window.alert(body);
|
|
||||||
ModalStack.push(function(props) {
|
|
||||||
return EDApi.React.createElement(AlertModal, Object.assign({title, body}, props));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static loadData(pluginName, key) {
|
|
||||||
if (!window.ED.config[pluginName]) window.ED.config[pluginName] = {};
|
|
||||||
return window.ED.config[pluginName][key];
|
|
||||||
}
|
|
||||||
|
|
||||||
static saveData(pluginName, key, data) {
|
|
||||||
if (!window.ED.config[pluginName]) window.ED.config[pluginName] = {};
|
|
||||||
window.ED.config[pluginName][key] = data;
|
|
||||||
window.ED.config = window.ED.config;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getData(pluginName, key) {
|
|
||||||
return this.loadData(pluginName, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
static setData(pluginName, key, data) {
|
|
||||||
this.saveData(pluginName, key, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getInternalInstance(node) {
|
|
||||||
if (!(node instanceof window.jQuery) && !(node instanceof Element)) return undefined;
|
|
||||||
if (node instanceof window.jQuery) node = node[0];
|
|
||||||
return node[Object.keys(node).find(k => k.startsWith("__reactInternalInstance"))];
|
|
||||||
}
|
|
||||||
|
|
||||||
static showToast(content, options = {}) {
|
|
||||||
if (!document.querySelector(".toasts")) {
|
|
||||||
const toastWrapper = document.createElement("div");
|
|
||||||
toastWrapper.classList.add("toasts");
|
|
||||||
const boundingElement = document.querySelector(".chat-3bRxxu form, #friends, .noChannel-Z1DQK7, .activityFeed-28jde9");
|
|
||||||
toastWrapper.style.setProperty("left", boundingElement ? boundingElement.getBoundingClientRect().left + "px" : "0px");
|
|
||||||
toastWrapper.style.setProperty("width", boundingElement ? boundingElement.offsetWidth + "px" : "100%");
|
|
||||||
toastWrapper.style.setProperty("bottom", (document.querySelector(".chat-3bRxxu form") ? document.querySelector(".chat-3bRxxu form").offsetHeight : 80) + "px");
|
|
||||||
document.querySelector("." + this.findModule('app').app).appendChild(toastWrapper);
|
|
||||||
}
|
|
||||||
const {type = "", icon = true, timeout = 3000} = options;
|
|
||||||
const toastElem = document.createElement("div");
|
|
||||||
toastElem.classList.add("toast");
|
|
||||||
if (type) toastElem.classList.add("toast-" + type);
|
|
||||||
if (type && icon) toastElem.classList.add("icon");
|
|
||||||
toastElem.innerText = content;
|
|
||||||
document.querySelector(".toasts").appendChild(toastElem);
|
|
||||||
setTimeout(() => {
|
|
||||||
toastElem.classList.add("closing");
|
|
||||||
setTimeout(() => {
|
|
||||||
toastElem.remove();
|
|
||||||
if (!document.querySelectorAll(".toasts .toast").length) document.querySelector(".toasts").remove();
|
|
||||||
}, 300);
|
|
||||||
}, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
static findModule(filter, silent = true) {
|
|
||||||
const moduleName = typeof filter === 'string' ? filter : null;
|
|
||||||
for (const i in window.req.c) {
|
|
||||||
if (window.req.c.hasOwnProperty(i)) {
|
|
||||||
const m = window.req.c[i].exports;
|
|
||||||
if (m && m.__esModule && m.default && (moduleName ? m.default[moduleName] : filter(m.default))) return m.default;
|
|
||||||
if (m && (moduleName ? m[moduleName] : filter(m))) return m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!silent) c.warn(`Could not find module ${module}.`, {name: 'Modules', color: 'black'})
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static findRawModule(filter, silent = true) {
|
|
||||||
const moduleName = typeof filter === 'string' ? filter : null;
|
|
||||||
for (const i in window.req.c) {
|
|
||||||
if (window.req.c.hasOwnProperty(i)) {
|
|
||||||
const m = window.req.c[i].exports;
|
|
||||||
if (m && m.__esModule && m.default && (moduleName ? m.default[moduleName] : filter(m.default)))
|
|
||||||
return window.req.c[i];
|
|
||||||
if (m && (moduleName ? m[moduleName] : filter(m)))
|
|
||||||
return window.req.c[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!silent) c.warn(`Could not find module ${module}.`, {name: 'Modules', color: 'black'})
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static findAllModules(filter) {
|
|
||||||
const moduleName = typeof filter === 'string' ? filter : null;
|
|
||||||
const modules = [];
|
|
||||||
for (const i in window.req.c) {
|
|
||||||
if (window.req.c.hasOwnProperty(i)) {
|
|
||||||
const m = window.req.c[i].exports;
|
|
||||||
if (m && m.__esModule && m.default && (moduleName ? m.default[moduleName] : filter(m.default))) modules.push(m.default);
|
|
||||||
else if (m && (moduleName ? m[moduleName] : filter(m))) modules.push(m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return modules;
|
|
||||||
}
|
|
||||||
|
|
||||||
static findModuleByProps(...props) {
|
|
||||||
return this.findModule(module => props.every(prop => module[prop] !== undefined));
|
|
||||||
}
|
|
||||||
|
|
||||||
static findModuleByDisplayName(name) {
|
|
||||||
return this.findModule(module => module.displayName === name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static monkeyPatch(what, methodName, options) {
|
|
||||||
if (typeof options === 'function') {
|
|
||||||
const newOptions = {instead: options, silent: true};
|
|
||||||
options = newOptions;
|
|
||||||
}
|
|
||||||
const {before, after, instead, once = false, silent = false, force = false} = options;
|
|
||||||
const displayName = options.displayName || what.displayName || what.name || what.constructor ? (what.constructor.displayName || what.constructor.name) : null;
|
|
||||||
if (!silent) console.log(`%c[EnhancedDiscord] %c[Modules]`, 'color: red;', `color: black;`, `Patched ${methodName} in module ${displayName || '<unknown>'}:`, what); // eslint-disable-line no-console
|
|
||||||
if (!what[methodName]) {
|
|
||||||
if (force) what[methodName] = function() {};
|
|
||||||
else return console.warn(`%c[EnhancedDiscord] %c[Modules]`, 'color: red;', `color: black;`, `Method ${methodName} doesn't exist in module ${displayName || '<unknown>'}`, what); // eslint-disable-line no-console
|
|
||||||
}
|
|
||||||
const origMethod = what[methodName];
|
|
||||||
const cancel = () => {
|
|
||||||
if (!silent) console.log(`%c[EnhancedDiscord] %c[Modules]`, 'color: red;', `color: black;`, `Unpatched ${methodName} in module ${displayName || '<unknown>'}:`, what); // eslint-disable-line no-console
|
|
||||||
what[methodName] = origMethod;
|
|
||||||
};
|
|
||||||
what[methodName] = function() {
|
|
||||||
const data = {
|
|
||||||
thisObject: this,
|
|
||||||
methodArguments: arguments,
|
|
||||||
cancelPatch: cancel,
|
|
||||||
originalMethod: origMethod,
|
|
||||||
callOriginalMethod: () => data.returnValue = data.originalMethod.apply(data.thisObject, data.methodArguments)
|
|
||||||
};
|
|
||||||
if (instead) {
|
|
||||||
const tempRet = EDApi.suppressErrors(instead, "`instead` callback of " + what[methodName].displayName)(data);
|
|
||||||
if (tempRet !== undefined) data.returnValue = tempRet;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (before) EDApi.suppressErrors(before, "`before` callback of " + what[methodName].displayName)(data);
|
|
||||||
data.callOriginalMethod();
|
|
||||||
if (after) EDApi.suppressErrors(after, "`after` callback of " + what[methodName].displayName)(data);
|
|
||||||
}
|
|
||||||
if (once) cancel();
|
|
||||||
return data.returnValue;
|
|
||||||
};
|
|
||||||
what[methodName].__monkeyPatched = true;
|
|
||||||
what[methodName].displayName = "patched " + (what[methodName].displayName || methodName);
|
|
||||||
what[methodName].unpatch = cancel;
|
|
||||||
return cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
static testJSON(data) {
|
|
||||||
try {
|
|
||||||
JSON.parse(data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static suppressErrors(method, description) {
|
|
||||||
return (...params) => {
|
|
||||||
try { return method(...params); }
|
|
||||||
catch (e) { console.error("Error occurred in " + description, e); }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static formatString(string, values) {
|
|
||||||
for (const val in values) {
|
|
||||||
string = string.replace(new RegExp(`\\{\\{${val}\\}\\}`, 'g'), values[val]);
|
|
||||||
}
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
static isPluginEnabled(name) {
|
|
||||||
const plugins = Object.values(window.ED.plugins);
|
|
||||||
const plugin = plugins.find(p => p.id == name || p.name == name);
|
|
||||||
if (!plugin) return false;
|
|
||||||
return !(plugin.settings.enabled === false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static isThemeEnabled() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static isSettingEnabled(id) {
|
|
||||||
return window.ED.config[id];
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,346 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2020 AryToNeX
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
:root{
|
|
||||||
/* Here you can define properties for use with Glasscord. */
|
|
||||||
|
|
||||||
/* Global properties */
|
|
||||||
/* Main switch: disabling this will disable Glasscord. */
|
|
||||||
--glasscord-enable: true;
|
|
||||||
/* Tint: it's basically a global background color. */
|
|
||||||
--glasscord-tint: rgba(0, 0, 0, 0);
|
|
||||||
|
|
||||||
/* Windows-specific properties */
|
|
||||||
/* Blur mode. Available types: acrylic (strong blur), blurbehind (light blur), transparent */
|
|
||||||
--glasscord-win-blur: acrylic;
|
|
||||||
/* Acrylic mode makes some computers pretty unresponsive when resizing/moving the window.
|
|
||||||
Should we work around it? */
|
|
||||||
--glasscord-win-performance-mode: true;
|
|
||||||
|
|
||||||
/* macOS-specific properties */
|
|
||||||
/* Vibrancy mode */
|
|
||||||
--glasscord-macos-vibrancy: hud;
|
|
||||||
|
|
||||||
/* Linux-specific properties */
|
|
||||||
/* Should Glasscord send a request to your window compositor to blur behind Discord's window? */
|
|
||||||
/* It currently supports KWin only */
|
|
||||||
--glasscord-linux-blur: false;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark{
|
|
||||||
--background-primary: transparent;
|
|
||||||
--background-primary-alt: #36393ff0;
|
|
||||||
--background-secondary: #2f313610;
|
|
||||||
--background-secondary-chat: #2f3136a0;
|
|
||||||
--background-secondary-alt: #292b2f00;
|
|
||||||
--background-tertiary: #20222570;
|
|
||||||
--background-logo: #36393fa0;
|
|
||||||
--deprecated-card-bg: #36393f4c;
|
|
||||||
--deprecated-store-bg: #36393f00;
|
|
||||||
--background-attachments: #2f313640;
|
|
||||||
--background-search-bar: #202225a0;
|
|
||||||
--background-switcher: #2f3136ff;
|
|
||||||
--background-chatbox: #20222550;
|
|
||||||
--background-lights-out: #000;
|
|
||||||
--background-pinned: #2f3136ff;
|
|
||||||
--background-profile-expand: #2f3136ff;
|
|
||||||
--text-lights-out: #f0f0f0;
|
|
||||||
--background-titlebar: #2f313650;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark .scrollerThemed-2oenus.themedWithTrack-q8E3vB .scroller-2FKFPG::-webkit-scrollbar-track-piece {
|
|
||||||
background-color: transparent;
|
|
||||||
border: 4px solid transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark .scrollerThemed-2oenus.themedWithTrack-q8E3vB .scroller-2FKFPG::-webkit-scrollbar-thumb {
|
|
||||||
background-color: #20222550;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark .container-1D34oG {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark .card-FDVird:before {
|
|
||||||
background-color: #33363c90;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark .codeRedemptionRedirect-1wVR4b {
|
|
||||||
background-color: #2f313650;
|
|
||||||
border-color: #20222550;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark .pageWrapper-1PgVDX {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-light {
|
|
||||||
--background-primary: transparent;
|
|
||||||
--background-primary-alt: #ffffffff;
|
|
||||||
--background-secondary: #f2f3f550;
|
|
||||||
--background-secondary-chat: #f2f3f5a0;
|
|
||||||
--background-secondary-alt: #ebedef00;
|
|
||||||
--background-tertiary: #e3e5e860;
|
|
||||||
--background-logo: #f2f3f5a0;
|
|
||||||
--deprecated-card-bg: #f8f9f94c;
|
|
||||||
--deprecated-store-bg: #f8f9f900;
|
|
||||||
--background-attachments: #f6f6f640;
|
|
||||||
--background-search-bar: #e3e5e8a0;
|
|
||||||
--background-switcher: #f2f3f5ff;
|
|
||||||
--background-chatbox: #e3e5e850;
|
|
||||||
--background-lights-out: #fff;
|
|
||||||
--background-pinned: #f2f3f5ff;
|
|
||||||
--background-profile-expand: #f2f3f5ff;
|
|
||||||
--text-lights-out: #202020;
|
|
||||||
--background-titlebar: #f2f3f550;
|
|
||||||
--interactive-muted: #95999d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-light .scrollerThemed-2oenus.themedWithTrack-q8E3vB .scroller-2FKFPG::-webkit-scrollbar-track-piece {
|
|
||||||
background-color: transparent;
|
|
||||||
border: 4px solid transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-light .scrollerThemed-2oenus.themedWithTrack-q8E3vB .scroller-2FKFPG::-webkit-scrollbar-thumb {
|
|
||||||
border-color: transparent;
|
|
||||||
background-color: #e3e5e850;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-light .container-1D34oG {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-light .card-FDVird:before {
|
|
||||||
background-color: #f6f6f790;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-light .codeRedemptionRedirect-1wVR4b {
|
|
||||||
background-color: #f6f6f750;
|
|
||||||
border-color: #dcddde50;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-light .pageWrapper-1PgVDX {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.withFrame-haYltI {
|
|
||||||
height: 18px;
|
|
||||||
margin-top: 0;
|
|
||||||
padding-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unread-3zKkbm {
|
|
||||||
height: 4px;
|
|
||||||
width: 4px;
|
|
||||||
margin-top: -2px;
|
|
||||||
border-radius: 2px 2px 2px 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.jumpToPresentBar-9P20AM {
|
|
||||||
border-radius: 8px;
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.platform-win .sidebar-2K8pFh {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.messagesPopoutWrap-1MQ1bW {
|
|
||||||
background-color: var(--background-pinned);
|
|
||||||
}
|
|
||||||
|
|
||||||
.notice-2FJMB4 {
|
|
||||||
background-color: var(--background-secondary) !important;
|
|
||||||
border-radius: 0;
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.appMount-3lHmkl {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-2rEoOp {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.attachment-33OFj0 {
|
|
||||||
background-color: var(--background-attachments) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-2o-2hj {
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.privateChannels-1nO12o {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.root-SR8cQa {
|
|
||||||
background-color: var(--background-profile-expand);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-PNkimc {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inset-3sAvek {
|
|
||||||
background-color: var(--background-secondary) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-1r6BKw.themed-ANHk51 {
|
|
||||||
background-color: var(--background-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper-1Rf91z {
|
|
||||||
background-color: var(--background-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.childWrapper-anI2G9 {
|
|
||||||
background-color: var(--background-logo);
|
|
||||||
}
|
|
||||||
|
|
||||||
.circleIconButton-jET_ig {
|
|
||||||
background-color: var(--background-logo);
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchBar-3dMhjb {
|
|
||||||
background-color: var(--background-search-bar);
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchBar-6Kv8R2 {
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchHeader-1l-wpR {
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channelName-1QajIf {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchResult-3pzFAB:before {
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchResult-3pzFAB:after {
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.perksModal-fSYqOq {
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ctaBar-2UsjF2 {
|
|
||||||
background-color: var(--background-attachments) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tierBody-16Chc9 {
|
|
||||||
background-color: var(--background-secondary-chat) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.perk-2WeBWW {
|
|
||||||
background-color: var(--background-attachments) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-yTz4x3:before {
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabBody-3YRQ8W:before {
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-19hC9u:before {
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-xm7Ad0:before {
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchBar-6Kv8R2 .searchBarComponent-32dTOx {
|
|
||||||
background-color: var(--background-search-bar);
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroller-1JbKMe {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroller-2TZvBN {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quickswitcher-3JagVE {
|
|
||||||
background-color: var(--background-switcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper-2aW0bm {
|
|
||||||
background-color: var(--background-primary-alt);
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchResultMessage-2VxO12.hit-NLlWXA {
|
|
||||||
background-color: var(--background-primary-alt);
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroller-zPkAnE {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.embedFull-2tM8-- {
|
|
||||||
background-color: var(--background-attachments);
|
|
||||||
}
|
|
||||||
|
|
||||||
.messagesWrapper-3lZDfY {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panels-j1Uci_ {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.titleBar-AC4pGV {
|
|
||||||
background-color: var(--background-titlebar);
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploadArea-3QgLtW {
|
|
||||||
background-color: var(--background-lights-out);
|
|
||||||
}
|
|
||||||
|
|
||||||
.backdropWithLayer-3_uhz4 {
|
|
||||||
background-color: var(--background-lights-out) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.backdrop-1wrmKB {
|
|
||||||
background-color: var(--background-lights-out) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.downloadLink-1ywL9o {
|
|
||||||
color: var(--text-lights-out) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-AYqtMd {
|
|
||||||
-webkit-mask-image: linear-gradient(#000f, #0000) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scrollableContainer-2NUZem {
|
|
||||||
background-color: var(--background-chatbox);
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
const electron = require('electron');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
electron.session.defaultSession.webRequest.onHeadersReceived(function(details, callback) {
|
|
||||||
if (!details.responseHeaders["content-security-policy-report-only"] && !details.responseHeaders["content-security-policy"]) return callback({cancel: false});
|
|
||||||
delete details.responseHeaders["content-security-policy-report-only"];
|
|
||||||
delete details.responseHeaders["content-security-policy"];
|
|
||||||
callback({cancel: false, responseHeaders: details.responseHeaders});
|
|
||||||
});
|
|
||||||
|
|
||||||
class BrowserWindow extends electron.BrowserWindow {
|
|
||||||
constructor(originalOptions) {
|
|
||||||
if (!originalOptions || !originalOptions.webPreferences || !originalOptions.title) return super(originalOptions);
|
|
||||||
const originalPreloadScript = originalOptions.webPreferences.preload;
|
|
||||||
|
|
||||||
// Make sure Node integration is enabled
|
|
||||||
originalOptions.webPreferences.nodeIntegration = true;
|
|
||||||
originalOptions.webPreferences.preload = path.join(process.env.injDir, 'dom_shit.js');
|
|
||||||
originalOptions.webPreferences.transparency = true;
|
|
||||||
|
|
||||||
super(originalOptions);
|
|
||||||
this.__preload = originalPreloadScript;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const electron_path = require.resolve('electron');
|
|
||||||
Object.assign(BrowserWindow, electron.BrowserWindow); // Assigns the new chrome-specific ones
|
|
||||||
|
|
||||||
if (electron.deprecate && electron.deprecate.promisify) {
|
|
||||||
const originalDeprecate = electron.deprecate.promisify; // Grab original deprecate promisify
|
|
||||||
electron.deprecate.promisify = (originalFunction) => originalFunction ? originalDeprecate(originalFunction) : () => void 0; // Override with falsey check
|
|
||||||
}
|
|
||||||
|
|
||||||
const newElectron = Object.assign({}, electron, {BrowserWindow});
|
|
||||||
// Tempfix for Injection breakage due to new version of Electron on Canary (Electron 7.x)
|
|
||||||
// Found by Zerebos (Zack Rauen)
|
|
||||||
delete require.cache[electron_path].exports;
|
|
||||||
// /TempFix
|
|
||||||
require.cache[electron_path].exports = newElectron;
|
|
||||||
//const browser_window_path = require.resolve(path.resolve(electron_path, '..', '..', 'browser-window.js'));
|
|
||||||
//require.cache[browser_window_path].exports = BrowserWindow;
|
|
|
@ -1,22 +0,0 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio 14
|
|
||||||
VisualStudioVersion = 14.0.25420.1
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnhancedDiscordUI", "EnhancedDiscordUI\EnhancedDiscordUI.csproj", "{3639AE05-14E6-43B2-9DDB-1A3F4F52657C}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{3639AE05-14E6-43B2-9DDB-1A3F4F52657C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{3639AE05-14E6-43B2-9DDB-1A3F4F52657C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{3639AE05-14E6-43B2-9DDB-1A3F4F52657C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{3639AE05-14E6-43B2-9DDB-1A3F4F52657C}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<startup>
|
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
|
|
||||||
</startup>
|
|
||||||
</configuration>
|
|
|
@ -1,138 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
|
||||||
<ProjectGuid>{3639AE05-14E6-43B2-9DDB-1A3F4F52657C}</ProjectGuid>
|
|
||||||
<OutputType>WinExe</OutputType>
|
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>EnhancedDiscordUI</RootNamespace>
|
|
||||||
<AssemblyName>EnhancedDiscordUI</AssemblyName>
|
|
||||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
|
||||||
<NuGetPackageImportStamp>
|
|
||||||
</NuGetPackageImportStamp>
|
|
||||||
<TargetFrameworkProfile />
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<ApplicationIcon>ed.ico</ApplicationIcon>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.IO.Compression.FileSystem" />
|
|
||||||
<Reference Include="System.Runtime.Serialization" />
|
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Deployment" />
|
|
||||||
<Reference Include="System.Drawing" />
|
|
||||||
<Reference Include="System.Net.Http" />
|
|
||||||
<Reference Include="System.Windows.Forms" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="Form1.cs">
|
|
||||||
<SubType>Form</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Form1.Designer.cs">
|
|
||||||
<DependentUpon>Form1.cs</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="LogWriter.cs" />
|
|
||||||
<Compile Include="Program.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
<EmbeddedResource Include="Form1.resx">
|
|
||||||
<DependentUpon>Form1.cs</DependentUpon>
|
|
||||||
</EmbeddedResource>
|
|
||||||
<EmbeddedResource Include="Properties\Resources.resx">
|
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
|
||||||
</EmbeddedResource>
|
|
||||||
<None Include="Properties\Settings.settings">
|
|
||||||
<Generator>SettingsSingleFileGenerator</Generator>
|
|
||||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
|
||||||
</None>
|
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DesignTime>True</DesignTime>
|
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Properties\Settings.Designer.cs">
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DependentUpon>Settings.settings</DependentUpon>
|
|
||||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="App.config" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\discord_canary_16.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\discord_stable_16.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\discord_stable_32.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\discord_stable_64.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\discord_canary_32.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\discord_canary_64.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\discord_dev_16.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\discord_dev_32.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\discord_dev_64.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\ed_og.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="ed.ico" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
|
||||||
<PropertyGroup>
|
|
||||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Target>
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
</Project>
|
|
|
@ -1,381 +0,0 @@
|
||||||
namespace EnhancedDiscordUI
|
|
||||||
{
|
|
||||||
partial class EDInstaller
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Required designer variable.
|
|
||||||
/// </summary>
|
|
||||||
private System.ComponentModel.IContainer components = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up any resources being used.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing && (components != null))
|
|
||||||
{
|
|
||||||
components.Dispose();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Windows Form Designer generated code
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required method for Designer support - do not modify
|
|
||||||
/// the contents of this method with the code editor.
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent()
|
|
||||||
{
|
|
||||||
this.components = new System.ComponentModel.Container();
|
|
||||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EDInstaller));
|
|
||||||
this.InstallButton = new System.Windows.Forms.Button();
|
|
||||||
this.Title = new System.Windows.Forms.Label();
|
|
||||||
this.UninstallButton = new System.Windows.Forms.Button();
|
|
||||||
this.UpdateButton = new System.Windows.Forms.Button();
|
|
||||||
this.InstallProgress = new System.Windows.Forms.ProgressBar();
|
|
||||||
this.StatusLabel2 = new System.Windows.Forms.Label();
|
|
||||||
this.StatusLabel = new System.Windows.Forms.Label();
|
|
||||||
this.StatusCloseButton = new System.Windows.Forms.Button();
|
|
||||||
this.StatusText = new System.Windows.Forms.TextBox();
|
|
||||||
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
|
|
||||||
this.DevButton = new System.Windows.Forms.Button();
|
|
||||||
this.CanaryButton = new System.Windows.Forms.Button();
|
|
||||||
this.PTBButton = new System.Windows.Forms.Button();
|
|
||||||
this.StableButton = new System.Windows.Forms.Button();
|
|
||||||
this.ReinjectButton = new System.Windows.Forms.Button();
|
|
||||||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
|
||||||
this.OpenFolderButton = new System.Windows.Forms.Button();
|
|
||||||
this.BetaRadio = new System.Windows.Forms.RadioButton();
|
|
||||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
|
||||||
this.SuspendLayout();
|
|
||||||
//
|
|
||||||
// InstallButton
|
|
||||||
//
|
|
||||||
this.InstallButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
|
||||||
this.InstallButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
|
||||||
this.InstallButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.InstallButton.ForeColor = System.Drawing.Color.WhiteSmoke;
|
|
||||||
this.InstallButton.Location = new System.Drawing.Point(155, 127);
|
|
||||||
this.InstallButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.InstallButton.Name = "InstallButton";
|
|
||||||
this.InstallButton.Size = new System.Drawing.Size(131, 30);
|
|
||||||
this.InstallButton.TabIndex = 0;
|
|
||||||
this.InstallButton.Text = "Install";
|
|
||||||
this.toolTip1.SetToolTip(this.InstallButton, "Downloads and injects ED into your Discord client.");
|
|
||||||
this.InstallButton.UseVisualStyleBackColor = true;
|
|
||||||
this.InstallButton.Click += new System.EventHandler(this.InstallButton_Click);
|
|
||||||
//
|
|
||||||
// Title
|
|
||||||
//
|
|
||||||
this.Title.AutoSize = true;
|
|
||||||
this.Title.Font = new System.Drawing.Font("Segoe UI Semibold", 18F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.Title.ForeColor = System.Drawing.Color.WhiteSmoke;
|
|
||||||
this.Title.Location = new System.Drawing.Point(131, 11);
|
|
||||||
this.Title.Name = "Title";
|
|
||||||
this.Title.Size = new System.Drawing.Size(255, 41);
|
|
||||||
this.Title.TabIndex = 1;
|
|
||||||
this.Title.Text = "EnhancedDiscord";
|
|
||||||
//
|
|
||||||
// UninstallButton
|
|
||||||
//
|
|
||||||
this.UninstallButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
|
||||||
this.UninstallButton.Enabled = false;
|
|
||||||
this.UninstallButton.FlatAppearance.BorderColor = System.Drawing.Color.WhiteSmoke;
|
|
||||||
this.UninstallButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
|
||||||
this.UninstallButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.UninstallButton.ForeColor = System.Drawing.Color.WhiteSmoke;
|
|
||||||
this.UninstallButton.Location = new System.Drawing.Point(155, 162);
|
|
||||||
this.UninstallButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.UninstallButton.Name = "UninstallButton";
|
|
||||||
this.UninstallButton.Size = new System.Drawing.Size(131, 30);
|
|
||||||
this.UninstallButton.TabIndex = 2;
|
|
||||||
this.UninstallButton.Text = "Uninstall";
|
|
||||||
this.toolTip1.SetToolTip(this.UninstallButton, "Uninjects ED and prompts you to delete ED\'s files.");
|
|
||||||
this.UninstallButton.UseVisualStyleBackColor = true;
|
|
||||||
this.UninstallButton.Click += new System.EventHandler(this.UninstallButton_Click);
|
|
||||||
//
|
|
||||||
// UpdateButton
|
|
||||||
//
|
|
||||||
this.UpdateButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
|
||||||
this.UpdateButton.Enabled = false;
|
|
||||||
this.UpdateButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
|
||||||
this.UpdateButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.UpdateButton.ForeColor = System.Drawing.Color.WhiteSmoke;
|
|
||||||
this.UpdateButton.Location = new System.Drawing.Point(87, 197);
|
|
||||||
this.UpdateButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.UpdateButton.Name = "UpdateButton";
|
|
||||||
this.UpdateButton.Size = new System.Drawing.Size(131, 30);
|
|
||||||
this.UpdateButton.TabIndex = 3;
|
|
||||||
this.UpdateButton.Text = "Update";
|
|
||||||
this.toolTip1.SetToolTip(this.UpdateButton, "Replaces the ED files with the most recent ones.");
|
|
||||||
this.UpdateButton.UseVisualStyleBackColor = true;
|
|
||||||
this.UpdateButton.Click += new System.EventHandler(this.UpdateButton_Click);
|
|
||||||
//
|
|
||||||
// InstallProgress
|
|
||||||
//
|
|
||||||
this.InstallProgress.Location = new System.Drawing.Point(12, 218);
|
|
||||||
this.InstallProgress.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.InstallProgress.Name = "InstallProgress";
|
|
||||||
this.InstallProgress.Size = new System.Drawing.Size(415, 23);
|
|
||||||
this.InstallProgress.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
|
|
||||||
this.InstallProgress.TabIndex = 5;
|
|
||||||
this.InstallProgress.Visible = false;
|
|
||||||
//
|
|
||||||
// StatusLabel2
|
|
||||||
//
|
|
||||||
this.StatusLabel2.AutoSize = true;
|
|
||||||
this.StatusLabel2.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.StatusLabel2.ForeColor = System.Drawing.Color.WhiteSmoke;
|
|
||||||
this.StatusLabel2.Location = new System.Drawing.Point(9, 190);
|
|
||||||
this.StatusLabel2.Name = "StatusLabel2";
|
|
||||||
this.StatusLabel2.Size = new System.Drawing.Size(89, 19);
|
|
||||||
this.StatusLabel2.TabIndex = 8;
|
|
||||||
this.StatusLabel2.Text = "Lorem ipsum";
|
|
||||||
this.StatusLabel2.Visible = false;
|
|
||||||
//
|
|
||||||
// StatusLabel
|
|
||||||
//
|
|
||||||
this.StatusLabel.AutoSize = true;
|
|
||||||
this.StatusLabel.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.StatusLabel.ForeColor = System.Drawing.Color.WhiteSmoke;
|
|
||||||
this.StatusLabel.Location = new System.Drawing.Point(8, 167);
|
|
||||||
this.StatusLabel.Name = "StatusLabel";
|
|
||||||
this.StatusLabel.Size = new System.Drawing.Size(165, 28);
|
|
||||||
this.StatusLabel.TabIndex = 9;
|
|
||||||
this.StatusLabel.Text = "Installation failed.";
|
|
||||||
this.StatusLabel.Visible = false;
|
|
||||||
//
|
|
||||||
// StatusCloseButton
|
|
||||||
//
|
|
||||||
this.StatusCloseButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
|
||||||
this.StatusCloseButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.StatusCloseButton.ForeColor = System.Drawing.Color.WhiteSmoke;
|
|
||||||
this.StatusCloseButton.Location = new System.Drawing.Point(251, 128);
|
|
||||||
this.StatusCloseButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.StatusCloseButton.Name = "StatusCloseButton";
|
|
||||||
this.StatusCloseButton.Size = new System.Drawing.Size(64, 30);
|
|
||||||
this.StatusCloseButton.TabIndex = 10;
|
|
||||||
this.StatusCloseButton.Text = "Close";
|
|
||||||
this.StatusCloseButton.UseVisualStyleBackColor = true;
|
|
||||||
this.StatusCloseButton.Visible = false;
|
|
||||||
this.StatusCloseButton.Click += new System.EventHandler(this.StatusCloseButton_Click);
|
|
||||||
//
|
|
||||||
// StatusText
|
|
||||||
//
|
|
||||||
this.StatusText.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(31)))), ((int)(((byte)(36)))), ((int)(((byte)(36)))));
|
|
||||||
this.StatusText.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
|
||||||
this.StatusText.Font = new System.Drawing.Font("Segoe UI", 10.2F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.StatusText.ForeColor = System.Drawing.Color.WhiteSmoke;
|
|
||||||
this.StatusText.Location = new System.Drawing.Point(11, 68);
|
|
||||||
this.StatusText.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.StatusText.Multiline = true;
|
|
||||||
this.StatusText.Name = "StatusText";
|
|
||||||
this.StatusText.ReadOnly = true;
|
|
||||||
this.StatusText.Size = new System.Drawing.Size(416, 26);
|
|
||||||
this.StatusText.TabIndex = 11;
|
|
||||||
this.StatusText.Text = "Make sure to launch Discord before installing!";
|
|
||||||
this.StatusText.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
|
||||||
//
|
|
||||||
// DevButton
|
|
||||||
//
|
|
||||||
this.DevButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
|
||||||
this.DevButton.FlatAppearance.BorderSize = 2;
|
|
||||||
this.DevButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
|
||||||
this.DevButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.DevButton.ForeColor = System.Drawing.Color.White;
|
|
||||||
this.DevButton.Image = global::EnhancedDiscordUI.Properties.Resources.discord_dev_64;
|
|
||||||
this.DevButton.ImageAlign = System.Drawing.ContentAlignment.TopCenter;
|
|
||||||
this.DevButton.Location = new System.Drawing.Point(320, 98);
|
|
||||||
this.DevButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.DevButton.Name = "DevButton";
|
|
||||||
this.DevButton.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
|
|
||||||
this.DevButton.Size = new System.Drawing.Size(91, 110);
|
|
||||||
this.DevButton.TabIndex = 15;
|
|
||||||
this.DevButton.Text = "Dev";
|
|
||||||
this.DevButton.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
|
|
||||||
this.toolTip1.SetToolTip(this.DevButton, "Discord Development (aka Local.)");
|
|
||||||
this.DevButton.UseVisualStyleBackColor = true;
|
|
||||||
this.DevButton.Visible = false;
|
|
||||||
this.DevButton.Click += new System.EventHandler(this.DevButton_Click);
|
|
||||||
//
|
|
||||||
// CanaryButton
|
|
||||||
//
|
|
||||||
this.CanaryButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
|
||||||
this.CanaryButton.FlatAppearance.BorderSize = 2;
|
|
||||||
this.CanaryButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
|
||||||
this.CanaryButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.CanaryButton.ForeColor = System.Drawing.Color.Gold;
|
|
||||||
this.CanaryButton.Image = global::EnhancedDiscordUI.Properties.Resources.discord_canary_64;
|
|
||||||
this.CanaryButton.ImageAlign = System.Drawing.ContentAlignment.TopCenter;
|
|
||||||
this.CanaryButton.Location = new System.Drawing.Point(224, 98);
|
|
||||||
this.CanaryButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.CanaryButton.Name = "CanaryButton";
|
|
||||||
this.CanaryButton.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
|
|
||||||
this.CanaryButton.Size = new System.Drawing.Size(91, 110);
|
|
||||||
this.CanaryButton.TabIndex = 14;
|
|
||||||
this.CanaryButton.Text = "Canary";
|
|
||||||
this.CanaryButton.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
|
|
||||||
this.toolTip1.SetToolTip(this.CanaryButton, "Discord Canary");
|
|
||||||
this.CanaryButton.UseVisualStyleBackColor = true;
|
|
||||||
this.CanaryButton.Visible = false;
|
|
||||||
this.CanaryButton.Click += new System.EventHandler(this.CanaryButton_Click);
|
|
||||||
//
|
|
||||||
// PTBButton
|
|
||||||
//
|
|
||||||
this.PTBButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
|
||||||
this.PTBButton.FlatAppearance.BorderSize = 2;
|
|
||||||
this.PTBButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
|
||||||
this.PTBButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.PTBButton.ForeColor = System.Drawing.Color.SteelBlue;
|
|
||||||
this.PTBButton.Image = global::EnhancedDiscordUI.Properties.Resources.discord_stable_64;
|
|
||||||
this.PTBButton.ImageAlign = System.Drawing.ContentAlignment.TopCenter;
|
|
||||||
this.PTBButton.Location = new System.Drawing.Point(128, 98);
|
|
||||||
this.PTBButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.PTBButton.Name = "PTBButton";
|
|
||||||
this.PTBButton.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
|
|
||||||
this.PTBButton.Size = new System.Drawing.Size(91, 110);
|
|
||||||
this.PTBButton.TabIndex = 13;
|
|
||||||
this.PTBButton.Text = "PTB";
|
|
||||||
this.PTBButton.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
|
|
||||||
this.toolTip1.SetToolTip(this.PTBButton, "Discord PTB (Public Test Build)");
|
|
||||||
this.PTBButton.UseVisualStyleBackColor = true;
|
|
||||||
this.PTBButton.Visible = false;
|
|
||||||
this.PTBButton.Click += new System.EventHandler(this.PTBButton_Click);
|
|
||||||
//
|
|
||||||
// StableButton
|
|
||||||
//
|
|
||||||
this.StableButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
|
||||||
this.StableButton.FlatAppearance.BorderSize = 2;
|
|
||||||
this.StableButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
|
||||||
this.StableButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.StableButton.ForeColor = System.Drawing.Color.SteelBlue;
|
|
||||||
this.StableButton.Image = global::EnhancedDiscordUI.Properties.Resources.discord_stable_64;
|
|
||||||
this.StableButton.ImageAlign = System.Drawing.ContentAlignment.TopCenter;
|
|
||||||
this.StableButton.Location = new System.Drawing.Point(32, 98);
|
|
||||||
this.StableButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.StableButton.Name = "StableButton";
|
|
||||||
this.StableButton.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
|
|
||||||
this.StableButton.Size = new System.Drawing.Size(91, 110);
|
|
||||||
this.StableButton.TabIndex = 12;
|
|
||||||
this.StableButton.Text = "Stable";
|
|
||||||
this.StableButton.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
|
|
||||||
this.toolTip1.SetToolTip(this.StableButton, "Normal version of Discord.");
|
|
||||||
this.StableButton.UseVisualStyleBackColor = true;
|
|
||||||
this.StableButton.Visible = false;
|
|
||||||
this.StableButton.Click += new System.EventHandler(this.StableButton_Click);
|
|
||||||
//
|
|
||||||
// ReinjectButton
|
|
||||||
//
|
|
||||||
this.ReinjectButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
|
||||||
this.ReinjectButton.Enabled = false;
|
|
||||||
this.ReinjectButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
|
||||||
this.ReinjectButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.ReinjectButton.ForeColor = System.Drawing.Color.WhiteSmoke;
|
|
||||||
this.ReinjectButton.Location = new System.Drawing.Point(225, 197);
|
|
||||||
this.ReinjectButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.ReinjectButton.Name = "ReinjectButton";
|
|
||||||
this.ReinjectButton.Size = new System.Drawing.Size(131, 30);
|
|
||||||
this.ReinjectButton.TabIndex = 17;
|
|
||||||
this.ReinjectButton.Text = "Reinject";
|
|
||||||
this.toolTip1.SetToolTip(this.ReinjectButton, "Reinjects without changing your ED folder; useful after Discord updates.");
|
|
||||||
this.ReinjectButton.UseVisualStyleBackColor = true;
|
|
||||||
this.ReinjectButton.Click += new System.EventHandler(this.ReinjectButton_Click);
|
|
||||||
//
|
|
||||||
// pictureBox1
|
|
||||||
//
|
|
||||||
this.pictureBox1.Image = global::EnhancedDiscordUI.Properties.Resources.ed_og;
|
|
||||||
this.pictureBox1.Location = new System.Drawing.Point(41, 12);
|
|
||||||
this.pictureBox1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.pictureBox1.Name = "pictureBox1";
|
|
||||||
this.pictureBox1.Size = new System.Drawing.Size(87, 50);
|
|
||||||
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
|
|
||||||
this.pictureBox1.TabIndex = 4;
|
|
||||||
this.pictureBox1.TabStop = false;
|
|
||||||
//
|
|
||||||
// OpenFolderButton
|
|
||||||
//
|
|
||||||
this.OpenFolderButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
|
||||||
this.OpenFolderButton.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.OpenFolderButton.ForeColor = System.Drawing.Color.WhiteSmoke;
|
|
||||||
this.OpenFolderButton.Location = new System.Drawing.Point(113, 128);
|
|
||||||
this.OpenFolderButton.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.OpenFolderButton.Name = "OpenFolderButton";
|
|
||||||
this.OpenFolderButton.Size = new System.Drawing.Size(125, 30);
|
|
||||||
this.OpenFolderButton.TabIndex = 16;
|
|
||||||
this.OpenFolderButton.Text = "Open Folder";
|
|
||||||
this.OpenFolderButton.UseVisualStyleBackColor = true;
|
|
||||||
this.OpenFolderButton.Visible = false;
|
|
||||||
this.OpenFolderButton.Click += new System.EventHandler(this.OpenFolderButton_Click);
|
|
||||||
//
|
|
||||||
// BetaRadio
|
|
||||||
//
|
|
||||||
this.BetaRadio.AutoSize = true;
|
|
||||||
this.BetaRadio.Font = new System.Drawing.Font("Segoe UI", 10.2F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.BetaRadio.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
|
||||||
this.BetaRadio.Location = new System.Drawing.Point(115, 95);
|
|
||||||
this.BetaRadio.Name = "BetaRadio";
|
|
||||||
this.BetaRadio.Size = new System.Drawing.Size(200, 27);
|
|
||||||
this.BetaRadio.TabIndex = 18;
|
|
||||||
this.BetaRadio.TabStop = true;
|
|
||||||
this.BetaRadio.Text = "Opt-in to beta version";
|
|
||||||
this.BetaRadio.UseVisualStyleBackColor = true;
|
|
||||||
//
|
|
||||||
// EDInstaller
|
|
||||||
//
|
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
|
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
|
||||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(31)))), ((int)(((byte)(36)))), ((int)(((byte)(36)))));
|
|
||||||
this.ClientSize = new System.Drawing.Size(439, 254);
|
|
||||||
this.Controls.Add(this.BetaRadio);
|
|
||||||
this.Controls.Add(this.ReinjectButton);
|
|
||||||
this.Controls.Add(this.OpenFolderButton);
|
|
||||||
this.Controls.Add(this.UninstallButton);
|
|
||||||
this.Controls.Add(this.StatusCloseButton);
|
|
||||||
this.Controls.Add(this.StatusLabel);
|
|
||||||
this.Controls.Add(this.StatusLabel2);
|
|
||||||
this.Controls.Add(this.InstallProgress);
|
|
||||||
this.Controls.Add(this.pictureBox1);
|
|
||||||
this.Controls.Add(this.UpdateButton);
|
|
||||||
this.Controls.Add(this.Title);
|
|
||||||
this.Controls.Add(this.InstallButton);
|
|
||||||
this.Controls.Add(this.StatusText);
|
|
||||||
this.Controls.Add(this.StableButton);
|
|
||||||
this.Controls.Add(this.DevButton);
|
|
||||||
this.Controls.Add(this.CanaryButton);
|
|
||||||
this.Controls.Add(this.PTBButton);
|
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
|
||||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
|
||||||
this.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
|
||||||
this.Name = "EDInstaller";
|
|
||||||
this.Text = "EnhancedDiscord Installer";
|
|
||||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
|
|
||||||
this.ResumeLayout(false);
|
|
||||||
this.PerformLayout();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private System.Windows.Forms.Button InstallButton;
|
|
||||||
private System.Windows.Forms.Label Title;
|
|
||||||
private System.Windows.Forms.Button UninstallButton;
|
|
||||||
private System.Windows.Forms.Button UpdateButton;
|
|
||||||
private System.Windows.Forms.PictureBox pictureBox1;
|
|
||||||
private System.Windows.Forms.ProgressBar InstallProgress;
|
|
||||||
private System.Windows.Forms.Label StatusLabel2;
|
|
||||||
private System.Windows.Forms.Label StatusLabel;
|
|
||||||
private System.Windows.Forms.Button StatusCloseButton;
|
|
||||||
private System.Windows.Forms.TextBox StatusText;
|
|
||||||
private System.Windows.Forms.ToolTip toolTip1;
|
|
||||||
private System.Windows.Forms.Button StableButton;
|
|
||||||
private System.Windows.Forms.Button PTBButton;
|
|
||||||
private System.Windows.Forms.Button CanaryButton;
|
|
||||||
private System.Windows.Forms.Button DevButton;
|
|
||||||
private System.Windows.Forms.Button OpenFolderButton;
|
|
||||||
private System.Windows.Forms.Button ReinjectButton;
|
|
||||||
private System.Windows.Forms.RadioButton BetaRadio;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,750 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Data;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Net;
|
|
||||||
using System.IO.Compression;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace EnhancedDiscordUI
|
|
||||||
{
|
|
||||||
public partial class EDInstaller : Form
|
|
||||||
{
|
|
||||||
private Process stableProcess;
|
|
||||||
private Process ptbProcess;
|
|
||||||
private Process canaryProcess;
|
|
||||||
private Process devProcess;
|
|
||||||
private string operation = "INSTALL";
|
|
||||||
private string platform;
|
|
||||||
private string branch = "master";
|
|
||||||
|
|
||||||
public EDInstaller()
|
|
||||||
{
|
|
||||||
Logger.MakeDivider();
|
|
||||||
Logger.Log("Starting...");
|
|
||||||
InitializeComponent();
|
|
||||||
if (Directory.Exists("./EnhancedDiscord"))
|
|
||||||
{
|
|
||||||
UninstallButton.Enabled = true;
|
|
||||||
UpdateButton.Enabled = true;
|
|
||||||
ReinjectButton.Enabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void endInstallation(string reason, bool failed)
|
|
||||||
{
|
|
||||||
InstallProgress.Value = 100;
|
|
||||||
BetaRadio.Hide();
|
|
||||||
InstallButton.Hide();
|
|
||||||
UninstallButton.Hide();
|
|
||||||
UpdateButton.Hide();
|
|
||||||
ReinjectButton.Hide();
|
|
||||||
StatusText.Hide();
|
|
||||||
StatusLabel.Show();
|
|
||||||
StatusLabel.Text = operation == "UPDATE" ? "Update " + (failed ? "failed" : "complete") : (operation == "UNINSTALL" ? "Unin" : "In") + "stallation " + (failed ? " failed." : "completed!");
|
|
||||||
StatusLabel.ForeColor = failed ? Color.Red : Color.Lime;
|
|
||||||
StatusLabel2.Show();
|
|
||||||
StatusLabel2.Text = reason;
|
|
||||||
StatusCloseButton.Show();
|
|
||||||
if (platform != "Linux")
|
|
||||||
{
|
|
||||||
OpenFolderButton.Show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void InstallButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (BetaRadio.Checked)
|
|
||||||
{
|
|
||||||
branch = "beta";
|
|
||||||
}
|
|
||||||
BetaRadio.Hide();
|
|
||||||
InstallButton.Hide();
|
|
||||||
UninstallButton.Hide();
|
|
||||||
UpdateButton.Hide();
|
|
||||||
ReinjectButton.Hide();
|
|
||||||
StatusText.Show();
|
|
||||||
InstallProgress.Show();
|
|
||||||
StatusText.Text = "Finding Discord processes...";
|
|
||||||
|
|
||||||
Process[] stable = Process.GetProcessesByName("Discord");
|
|
||||||
Process[] canary = Process.GetProcessesByName("DiscordCanary");
|
|
||||||
Process[] ptb = Process.GetProcessesByName("DiscordPtb");
|
|
||||||
Process[] dev = Process.GetProcessesByName("DiscordDevelopment");
|
|
||||||
|
|
||||||
List<Process> discordProcesses = new List<Process>();
|
|
||||||
discordProcesses.AddRange(stable);
|
|
||||||
discordProcesses.AddRange(canary);
|
|
||||||
discordProcesses.AddRange(ptb);
|
|
||||||
discordProcesses.AddRange(dev);
|
|
||||||
|
|
||||||
if (discordProcesses.Count == 0)
|
|
||||||
{
|
|
||||||
endInstallation("No Discord processes found. Please open Discord and try again.", true); return;
|
|
||||||
}
|
|
||||||
List<Process> uniqueProcesses = new List<Process>();
|
|
||||||
// First look for processes with unique filenames that have a title
|
|
||||||
for (int i = 0; i < discordProcesses.Count; i++)
|
|
||||||
{
|
|
||||||
bool isUnique = true;
|
|
||||||
for (int j = 0; j < uniqueProcesses.Count; j++)
|
|
||||||
{
|
|
||||||
if (uniqueProcesses[j].MainModule.FileName.Equals(discordProcesses[i].MainModule.FileName))
|
|
||||||
{
|
|
||||||
isUnique = false; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isUnique || discordProcesses[i].MainWindowTitle == "" || discordProcesses[i].MainWindowTitle.StartsWith("Developer Tools")) continue;
|
|
||||||
|
|
||||||
uniqueProcesses.Add(discordProcesses[i]);
|
|
||||||
}
|
|
||||||
// Then look for all processes with unique filenames
|
|
||||||
for (int i = 0; i < discordProcesses.Count; i++)
|
|
||||||
{
|
|
||||||
bool isUnique = true;
|
|
||||||
for (int j = 0; j < uniqueProcesses.Count; j++)
|
|
||||||
{
|
|
||||||
if (uniqueProcesses[j].MainModule.FileName.Equals(discordProcesses[i].MainModule.FileName))
|
|
||||||
{
|
|
||||||
isUnique = false; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isUnique) continue;
|
|
||||||
uniqueProcesses.Add(discordProcesses[i]);
|
|
||||||
}
|
|
||||||
StatusText.Text = "Found " + uniqueProcesses.Count + " Discord process" + (uniqueProcesses.Count == 1 ? "" : "es") + ".";
|
|
||||||
InstallProgress.Value = 10;
|
|
||||||
Process finalProcess = uniqueProcesses[0];
|
|
||||||
if (uniqueProcesses.Count > 1)
|
|
||||||
{
|
|
||||||
// Enable selection buttons
|
|
||||||
List<Button> clients = new List<Button>();
|
|
||||||
for (int i = 0; i < uniqueProcesses.Count; i++)
|
|
||||||
{
|
|
||||||
if (canary.Contains(uniqueProcesses[i]))
|
|
||||||
{
|
|
||||||
CanaryButton.Show();
|
|
||||||
clients.Add(CanaryButton);
|
|
||||||
canaryProcess = uniqueProcesses[i];
|
|
||||||
}
|
|
||||||
else if (ptb.Contains(uniqueProcesses[i]))
|
|
||||||
{
|
|
||||||
PTBButton.Show();
|
|
||||||
clients.Add(PTBButton);
|
|
||||||
ptbProcess = uniqueProcesses[i];
|
|
||||||
}
|
|
||||||
else if (dev.Contains(uniqueProcesses[i]))
|
|
||||||
{
|
|
||||||
DevButton.Show();
|
|
||||||
clients.Add(DevButton);
|
|
||||||
devProcess = uniqueProcesses[i];
|
|
||||||
}
|
|
||||||
else if (stable.Contains(uniqueProcesses[i]))
|
|
||||||
{
|
|
||||||
StableButton.Show();
|
|
||||||
clients.Add(StableButton);
|
|
||||||
stableProcess = uniqueProcesses[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// position buttons correctly
|
|
||||||
if (clients.Count == 3)
|
|
||||||
{
|
|
||||||
clients[0].Left = 55;
|
|
||||||
clients[1].Left = 131;
|
|
||||||
clients[2].Left = 207;
|
|
||||||
}
|
|
||||||
else if (clients.Count == 2)
|
|
||||||
{
|
|
||||||
clients[0].Left = 88;
|
|
||||||
clients[1].Left = 164;
|
|
||||||
}
|
|
||||||
return; // stuff continues w/ button events
|
|
||||||
}
|
|
||||||
if (operation == "UPDATE")
|
|
||||||
{
|
|
||||||
continueUpdate(finalProcess);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
continueInstall(finalProcess);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StableButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
continueInstall(stableProcess);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PTBButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
continueInstall(ptbProcess);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CanaryButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
continueInstall(canaryProcess);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DevButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
continueInstall(devProcess);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void continueInstall(Process proc)
|
|
||||||
{
|
|
||||||
string path = proc.MainModule.FileName;
|
|
||||||
string release = "discord";
|
|
||||||
if (path.Contains("DiscordPTB"))
|
|
||||||
{
|
|
||||||
release = "discordptb";
|
|
||||||
}
|
|
||||||
else if (path.Contains("DiscordCanary"))
|
|
||||||
{
|
|
||||||
release = "discordcanary";
|
|
||||||
}
|
|
||||||
else if (path.Contains("DiscordDevelopment"))
|
|
||||||
{
|
|
||||||
release = "discorddevelopment";
|
|
||||||
}
|
|
||||||
Logger.Log("Using release " + release);
|
|
||||||
StableButton.Hide();
|
|
||||||
PTBButton.Hide();
|
|
||||||
CanaryButton.Hide();
|
|
||||||
DevButton.Hide();
|
|
||||||
|
|
||||||
StatusText.Text = "Injecting...";
|
|
||||||
InstallProgress.Value = 20;
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
|
|
||||||
string dLocation = Path.GetDirectoryName(path);
|
|
||||||
platform = "";
|
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
||||||
{
|
|
||||||
platform = "Windows";
|
|
||||||
}
|
|
||||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
||||||
{
|
|
||||||
platform = "Linux";
|
|
||||||
}
|
|
||||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
|
||||||
{
|
|
||||||
platform = "Mac";
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusText.Text = "Detected platform: " + platform + " | Discord release: " + release;
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
|
|
||||||
string basePath;
|
|
||||||
string appVersion = dLocation.Substring(dLocation.IndexOf("app-") + 4);
|
|
||||||
if (platform == "Windows")
|
|
||||||
{
|
|
||||||
basePath = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(dLocation)));
|
|
||||||
basePath = Path.Combine(basePath, "Roaming");
|
|
||||||
}
|
|
||||||
else if (platform == "Mac")
|
|
||||||
{
|
|
||||||
basePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
|
|
||||||
basePath = Path.Combine(basePath, "Library", "Application Support");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
basePath = Environment.GetEnvironmentVariable("XDG_CONFIG_HOME");
|
|
||||||
if (basePath == null)
|
|
||||||
{
|
|
||||||
basePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
|
|
||||||
basePath = Path.Combine(basePath, ".config");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
string[] pathPieces = { basePath, release, appVersion, "modules", "discord_desktop_core", "index.js" };
|
|
||||||
// the base "appdata" folder ^ ^ ^
|
|
||||||
// i.e. "discord" or "discordcanary" -' |
|
|
||||||
// i.e. "0.0.300" or "0.0.204" ---------------'
|
|
||||||
string targetPath = Path.Combine(pathPieces);
|
|
||||||
|
|
||||||
if (targetPath == "" || !File.Exists(targetPath))
|
|
||||||
{
|
|
||||||
Logger.Error("Could not fine injection file with basepath " + basePath);
|
|
||||||
endInstallation("Could not find injection file.", true); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (operation == "UNINSTALL")
|
|
||||||
{
|
|
||||||
continueUninstall(proc, targetPath, platform); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string currentContents = File.ReadAllText(targetPath);
|
|
||||||
|
|
||||||
if (currentContents != "module.exports = require('./core.asar');")
|
|
||||||
{
|
|
||||||
StatusText.Text = "EnhancedDiscord was already injected. Reinjecting...";
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
}
|
|
||||||
InstallProgress.Value = 30;
|
|
||||||
|
|
||||||
string stuffToInject = Properties.Resources.injection;
|
|
||||||
string cd = Directory.GetCurrentDirectory() + "/EnhancedDiscord";
|
|
||||||
cd = cd.Replace("\\", "/").Replace("'", "\\'").Replace("/", "\\\\");
|
|
||||||
string newContents = "process.env.injDir = '" + cd + "';\n";
|
|
||||||
newContents += stuffToInject + "\nmodule.exports = require('./core.asar');";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File.WriteAllText(targetPath, newContents);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Failed to write to injection file. " + e.Message);
|
|
||||||
endInstallation("Failed to write to injection file.", true); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (operation == "REINJECT")
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
proc.Kill();
|
|
||||||
startDetached(path, null);
|
|
||||||
endInstallation("Successfully reinjected.", false);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Failed to restart Discord; do this manually. " + e.Message);
|
|
||||||
endInstallation("Failed to restart Discord; do this manually.", false);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
InstallProgress.Value = 40;
|
|
||||||
StatusText.Text = "Successfully injected. Downloading ED...";
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
|
|
||||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
|
|
||||||
string zipLink = Properties.Resources.zipLink + branch;
|
|
||||||
WebClient wc = new WebClient();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await wc.DownloadFileTaskAsync(new Uri(zipLink), "./ED_master.zip");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Failed to download ED files. " + e.Message);
|
|
||||||
endInstallation("Failed to download ED files.", true); return;
|
|
||||||
}
|
|
||||||
InstallProgress.Value = 60;
|
|
||||||
StatusText.Text = "Successfully downloaded. Extracting...";
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
|
|
||||||
if (Directory.Exists("./EnhancedDiscord") || Directory.Exists("./EnhancedDiscord-" + branch))
|
|
||||||
{
|
|
||||||
DialogResult confirmResult = MessageBox.Show("ED folder already exists. Overwrite it?", "EnhancedDiscord - Confirm Overwrite", MessageBoxButtons.YesNo);
|
|
||||||
if (confirmResult == DialogResult.No)
|
|
||||||
{
|
|
||||||
Logger.Error("Not replacing old ED files; restart Discord manually.");
|
|
||||||
endInstallation("Not replacing old ED files; restart Discord manually.", false); return;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Directory.Exists("./EnhancedDiscord"))
|
|
||||||
{
|
|
||||||
Directory.Delete("./EnhancedDiscord", true);
|
|
||||||
}
|
|
||||||
if (Directory.Exists("./EnhancedDiscord-" + branch))
|
|
||||||
{
|
|
||||||
Directory.Delete("./EnhancedDiscord-" + branch, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
StatusText.Text = "Error deleting old folders.";
|
|
||||||
Logger.Error(StatusText.Text + " " + e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ZipFile.ExtractToDirectory("./ED_master.zip", "./");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Failed to extract zip file. " + e.Message);
|
|
||||||
endInstallation("Failed to extract zip file.", true); return;
|
|
||||||
}
|
|
||||||
InstallProgress.Value = 70;
|
|
||||||
StatusText.Text = "Finished extracting zip. Cleaning up...";
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Directory.Move("./EnhancedDiscord-" + branch, "./EnhancedDiscord");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Failed to rename extracted folder. " + e.Message);
|
|
||||||
endInstallation("Failed to rename extracted folder.", true); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string[] garbage = new string[] { "./EnhancedDiscord/README.md", "./EnhancedDiscord/plugins.md", "./EnhancedDiscord/advanced_installation.md", "./EnhancedDiscord/.gitignore", "./ED_master.zip", "./EnhancedDiscord/installer", "./EnhancedDiscord/installer_cmdline" };
|
|
||||||
|
|
||||||
foreach (string filePath in garbage)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (File.Exists(filePath))
|
|
||||||
{
|
|
||||||
File.Delete(filePath);
|
|
||||||
}
|
|
||||||
if (Directory.Exists(filePath))
|
|
||||||
{
|
|
||||||
Directory.Delete(filePath, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Error during cleanup. " + e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InstallProgress.Value = 80;
|
|
||||||
StatusText.Text = "Finished cleaning up. Creating config.json...";
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
|
|
||||||
bool configSuccess = true;
|
|
||||||
if (!File.Exists("./EnhancedDiscord/config.json"))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File.WriteAllText("./EnhancedDiscord/config.json", "{}");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Failed to write config.json. " + e.Message);
|
|
||||||
configSuccess = false;
|
|
||||||
//StatusText.Text = "Failed to create config.json.";
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InstallProgress.Value = 90;
|
|
||||||
StatusText.Text = (configSuccess ? File.Exists("./EnhancedDiscord/config.json") ? "Found" : "Created" : "Failed to create") + " config.json. Relaunching Discord...";
|
|
||||||
if (configSuccess) Logger.Log(StatusText.Text);
|
|
||||||
else Logger.Error(StatusText.Text);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
proc.Kill();
|
|
||||||
startDetached(path, null);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
StatusText.Text = "Failed to restart Discord; do this manually.";
|
|
||||||
Logger.Error(StatusText.Text + " " + e.Message);
|
|
||||||
}
|
|
||||||
InstallProgress.Value = 100;
|
|
||||||
endInstallation("Finished cleaning up.", false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void continueUninstall(Process proc, string targetPath, string platform)
|
|
||||||
{
|
|
||||||
StatusText.Text = "Uninstalling...";
|
|
||||||
InstallProgress.Value = 30;
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
|
|
||||||
string path = proc.MainModule.FileName;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File.WriteAllText(targetPath, "module.exports = require('./core.asar');");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Failed to write to injection file. " + e.Message);
|
|
||||||
endInstallation("Failed to write to injection file.", true); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusText.Text = "Successfully uninjected. Deleting old files...";
|
|
||||||
InstallProgress.Value = 60;
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
|
|
||||||
if (Directory.Exists("./EnhancedDiscord"))
|
|
||||||
{
|
|
||||||
DialogResult confirmResult = MessageBox.Show("Would you like to keep your EnhancedDiscord folder?", "EnhancedDiscord - Confirm Delete", MessageBoxButtons.YesNo);
|
|
||||||
if (confirmResult == DialogResult.No)
|
|
||||||
{
|
|
||||||
bool success = true;
|
|
||||||
StatusText.Text = "Killing Discord process...";
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
proc.Kill();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
success = false;
|
|
||||||
StatusText.Text = "Failed to kill Discord process. Aborted deletion of ED directory.";
|
|
||||||
Logger.Error(StatusText.Text + " " + e.Message);
|
|
||||||
}
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Directory.Delete("./EnhancedDiscord", true);
|
|
||||||
Directory.Delete("./EnhancedDiscord", false);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
StatusText.Text = "Failed to delete EnhancedDiscord directory.";
|
|
||||||
Logger.Error(StatusText.Text + " " + e.Message);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
startDetached(path, null);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Uninjected successfully. Failed to restart Discord; do this manually. " + e.Message);
|
|
||||||
endInstallation("Uninjected successfully. Failed to restart Discord; do this manually.", false); return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
proc.Kill();
|
|
||||||
startDetached(path, null);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Uninjected successfully. Failed to restart Discord; do this manually. " + e.Message);
|
|
||||||
endInstallation("Uninjected successfully. Failed to restart Discord; do this manually.", false); return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
proc.Kill();
|
|
||||||
startDetached(path, null);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Uninjected successfully. Failed to restart Discord; do this manually. " + e.Message);
|
|
||||||
endInstallation("Uninjected successfully. Failed to restart Discord; do this manually.", false); return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Logger.Log("Uninjected and cleaned up successfully.");
|
|
||||||
endInstallation("Uninjected and cleaned up successfully.", false); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Process startDetached(string executablePath, string args)
|
|
||||||
{
|
|
||||||
if (platform == "Windows")
|
|
||||||
{
|
|
||||||
return Process.Start("cmd.exe", "/c start " + executablePath + (args == null ? "" : " " + args));
|
|
||||||
}
|
|
||||||
return Process.Start(executablePath, (args == null ? "" : args + " ") + "&"); // should work on Mac and Linux
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StatusCloseButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UninstallButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
operation = "UNINSTALL";
|
|
||||||
InstallButton_Click(sender, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OpenFolderButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (platform == "Windows")
|
|
||||||
{
|
|
||||||
startDetached("", ".\\EnhancedDiscord");
|
|
||||||
}
|
|
||||||
else if (platform == "Mac")
|
|
||||||
{
|
|
||||||
startDetached("open", "./EnhancedDiscord");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
operation = "UPDATE";
|
|
||||||
InstallButton_Click(sender, e);
|
|
||||||
}
|
|
||||||
private void ReinjectButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
operation = "REINJECT";
|
|
||||||
InstallButton_Click(sender, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
async private void continueUpdate(Process proc)
|
|
||||||
{
|
|
||||||
string path = proc.MainModule.FileName;
|
|
||||||
operation = "UPDATE";
|
|
||||||
BetaRadio.Hide();
|
|
||||||
InstallButton.Hide();
|
|
||||||
UninstallButton.Hide();
|
|
||||||
UpdateButton.Hide();
|
|
||||||
ReinjectButton.Hide();
|
|
||||||
StatusText.Show();
|
|
||||||
InstallProgress.Show();
|
|
||||||
InstallProgress.Value = 0;
|
|
||||||
|
|
||||||
string tempPath = Path.Combine(Path.GetTempPath(), "EnhancedDiscord");
|
|
||||||
if (Directory.Exists(tempPath))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Directory.Delete(tempPath, true);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
StatusText.Text = "Error deleting temp folders.";
|
|
||||||
Logger.Log(StatusText.Text + " " + e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Directory.CreateDirectory(tempPath);
|
|
||||||
|
|
||||||
StatusText.Text = "Downloading package...";
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
string zipPath = Path.Combine(tempPath, "EnhancedDiscord.zip");
|
|
||||||
string zipLink = Properties.Resources.zipLink + branch;
|
|
||||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
|
|
||||||
WebClient wc = new WebClient();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await wc.DownloadFileTaskAsync(new Uri(zipLink), zipPath);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Failed to download ED files. " + e.Message);
|
|
||||||
endInstallation("Failed to download ED files.", true); return;
|
|
||||||
}
|
|
||||||
InstallProgress.Value = 40;
|
|
||||||
StatusText.Text = "Successfully downloaded. Extracting...";
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ZipFile.ExtractToDirectory(zipPath, tempPath);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Failed to extract zip file. " + e.Message);
|
|
||||||
endInstallation("Failed to extract zip file.", true); return;
|
|
||||||
}
|
|
||||||
InstallProgress.Value = 50;
|
|
||||||
StatusText.Text = "Finished extracting zip. Checking core...";
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
|
|
||||||
string extractedPath = Path.Combine(tempPath, "EnhancedDiscord-" + branch);
|
|
||||||
string enhancedPath = "./EnhancedDiscord";
|
|
||||||
|
|
||||||
if (!File.Exists(Path.Combine(enhancedPath, "config.json")))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File.WriteAllText(Path.Combine(enhancedPath, "config.json"), "{}");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error("Failed to write config.json. " + e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string[] garbage = new string[] { "README.md", "plugins.md", ".gitignore", "advanced_installation.md" };
|
|
||||||
foreach (string file in Directory.GetFiles(extractedPath))
|
|
||||||
{
|
|
||||||
string filename = Path.GetFileName(file);
|
|
||||||
if (Array.Exists(garbage, f => f == filename)) continue;
|
|
||||||
string equiv = Path.Combine(enhancedPath, filename);
|
|
||||||
bool filesEqual = false;
|
|
||||||
bool fileExists = File.Exists(equiv);
|
|
||||||
if (fileExists) filesEqual = FilesEqual(file, equiv);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (fileExists && !filesEqual) File.Delete(equiv);
|
|
||||||
if (!fileExists || !filesEqual) File.Copy(file, equiv);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
StatusText.Text = "Could not update plugin: " + filename;
|
|
||||||
Logger.Log(StatusText.Text + " " + e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InstallProgress.Value = 70;
|
|
||||||
StatusText.Text = "Core finished. Checking plugins...";
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
|
|
||||||
string pluginPath = Path.Combine(enhancedPath, "plugins");
|
|
||||||
if (!Directory.Exists(pluginPath)) Directory.CreateDirectory(pluginPath);
|
|
||||||
foreach (string file in Directory.GetFiles(Path.Combine(extractedPath, "plugins")))
|
|
||||||
{
|
|
||||||
string filename = Path.GetFileName(file);
|
|
||||||
if (filename == "style.css") continue;
|
|
||||||
string equiv = Path.Combine(pluginPath, filename);
|
|
||||||
bool filesEqual = false;
|
|
||||||
bool fileExists = File.Exists(equiv);
|
|
||||||
if (fileExists) filesEqual = FilesEqual(file, equiv);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (fileExists && !filesEqual) File.Delete(equiv);
|
|
||||||
if (!fileExists || !filesEqual) File.Copy(file, equiv);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
StatusText.Text = "Could not update plugin: " + filename;
|
|
||||||
Logger.Log(StatusText.Text + " " + e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusText.Text = "Cleaning up...";
|
|
||||||
Logger.Log(StatusText.Text);
|
|
||||||
if (Directory.Exists(tempPath))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Directory.Delete(tempPath, true);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
StatusText.Text = "Error deleting temp folders.";
|
|
||||||
Logger.Log(StatusText.Text + " " + e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InstallProgress.Value = 90;
|
|
||||||
endInstallation("ED files updated.", false); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adapted from https://stackoverflow.com/questions/7931304/comparing-two-files-in-c-sharp
|
|
||||||
private bool FilesEqual(string filename1, string filename2)
|
|
||||||
{
|
|
||||||
if (filename1 == filename2) return true;
|
|
||||||
|
|
||||||
FileStream fileStream1 = new FileStream(filename1, FileMode.Open, FileAccess.Read);
|
|
||||||
FileStream fileStream2 = new FileStream(filename2, FileMode.Open, FileAccess.Read);
|
|
||||||
if (fileStream1.Length != fileStream2.Length)
|
|
||||||
{
|
|
||||||
fileStream1.Close();
|
|
||||||
fileStream2.Close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fileByte1;
|
|
||||||
int fileByte2;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
fileByte1 = fileStream1.ReadByte();
|
|
||||||
fileByte2 = fileStream2.ReadByte();
|
|
||||||
}
|
|
||||||
while ((fileByte1 == fileByte2) && (fileByte1 != -1));
|
|
||||||
|
|
||||||
fileStream1.Close();
|
|
||||||
fileStream2.Close();
|
|
||||||
|
|
||||||
return ((fileByte1 - fileByte2) == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,148 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
||||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:choice maxOccurs="unbounded">
|
|
||||||
<xsd:element name="metadata">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="assembly">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:attribute name="alias" type="xsd:string" />
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="data">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="resheader">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:choice>
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>2.0</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>19, 20</value>
|
|
||||||
</metadata>
|
|
||||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
|
||||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>
|
|
||||||
AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABMLAAATCwAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAACAAAAAgAAAAIAAAACAAAAAAAAAAEAAAACAAAAAgAA
|
|
||||||
AAIAAAACAAAAAQAAAAAAAAAAAAAAAAAON1cADTaWAA02lwANNpcADTaYAA0zkgAHHzgADTZUAA02mAAN
|
|
||||||
NpcADTaXAA01lwAMMYQACCJFAAEDCQACCgAAFVOdABVW/wAVU/gAFVPwABVT8AAVU/EAEUWrABNNrAAV
|
|
||||||
Vv8AFVT5ABVU8wAVVPUAFVX9ABRR7AAOO3gAAAAJABxvnQAccv8AF1y/ABRSgwAVVYQAE051ABFHOAAb
|
|
||||||
baEAHHH/ABZXjQAWWTIAF1w2ABllbwAcce0AGmjmAA01QQAiip0AI47/ACOM+gAji/UAI4z2ACGE5wAV
|
|
||||||
U1sAIomZACOM/wAaaGwAM80AABZaAAAXXwgAIoq5ACKK/AAWWmcAKaWdACqp/wAkkM0AIoeeACKJnwAi
|
|
||||||
iJ4AHXNaACGFVAAhg5IAGGFQABFFIwATSiUAIYNWACqn4wApo+4AGmhJADDBnQAyxv8AL7vvAC643wAu
|
|
||||||
ud8ALbTbAB97bAAml0UALrfQAC654gAuuOIALrnkADDA9gAxw/kAKqqOAA87CwA11WwANtiyADbZsgA2
|
|
||||||
2bMANtmzADfZtQAvu5IAHHAeADbWeQA32bUANtmzADbYswA10p4AMMBZACKIDAApowAAMsUDAC61BQAt
|
|
||||||
tAUALbQFAC20BQAttAUANM4FACqoAQAxwgIALrYFAC20BQAqqQUAHXQCACqmAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAA//8AAP//AAD//wAA//8AAAIHAAAAAQAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAQAAAAcAAP//
|
|
||||||
AAD//wAA//8AAA==
|
|
||||||
</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
|
|
@ -1,81 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace EnhancedDiscordUI
|
|
||||||
{
|
|
||||||
static public class Logger
|
|
||||||
{
|
|
||||||
static public void Log(string logMessage)
|
|
||||||
{
|
|
||||||
string m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
|
|
||||||
{
|
|
||||||
_Log("INFO", logMessage, w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static public void Warn(string logMessage)
|
|
||||||
{
|
|
||||||
string m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
|
|
||||||
{
|
|
||||||
_Log("WARN", logMessage, w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static public void Error(string logMessage)
|
|
||||||
{
|
|
||||||
string m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
|
|
||||||
{
|
|
||||||
_Log("ERROR", logMessage, w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static public void _Log(string type, string logMessage, TextWriter txtWriter)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
txtWriter.WriteLine("[{0}][{1} {2}]: {3}", type, DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString(), logMessage);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static public void MakeDivider()
|
|
||||||
{
|
|
||||||
string m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
|
|
||||||
{
|
|
||||||
w.WriteLine("---------------------------------------------------------------------");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace EnhancedDiscordUI
|
|
||||||
{
|
|
||||||
static class Program
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The main entry point for the application.
|
|
||||||
/// </summary>
|
|
||||||
[STAThread]
|
|
||||||
static void Main()
|
|
||||||
{
|
|
||||||
Application.EnableVisualStyles();
|
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
|
||||||
Application.Run(new EDInstaller());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
[assembly: AssemblyTitle("EnhancedDiscordUI")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("EnhancedDiscordUI")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
|
||||||
// to COM components. If you need to access a type in this assembly from
|
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|
||||||
[assembly: Guid("3639ae05-14e6-43b2-9ddb-1a3f4f52657c")]
|
|
||||||
|
|
||||||
// Version information for an assembly consists of the following four values:
|
|
||||||
//
|
|
||||||
// Major Version
|
|
||||||
// Minor Version
|
|
||||||
// Build Number
|
|
||||||
// Revision
|
|
||||||
//
|
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
|
||||||
// by using the '*' as shown below:
|
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
|
@ -1,181 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
// Runtime Version:4.0.30319.42000
|
|
||||||
//
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace EnhancedDiscordUI.Properties {
|
|
||||||
using System;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
|
||||||
/// </summary>
|
|
||||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
|
||||||
// class via a tool like ResGen or Visual Studio.
|
|
||||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
|
||||||
// with the /str option, or rebuild your VS project.
|
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
|
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
|
||||||
internal class Resources {
|
|
||||||
|
|
||||||
private static global::System.Resources.ResourceManager resourceMan;
|
|
||||||
|
|
||||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
|
||||||
|
|
||||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
|
||||||
internal Resources() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the cached ResourceManager instance used by this class.
|
|
||||||
/// </summary>
|
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
|
||||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
|
||||||
get {
|
|
||||||
if (object.ReferenceEquals(resourceMan, null)) {
|
|
||||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EnhancedDiscordUI.Properties.Resources", typeof(Resources).Assembly);
|
|
||||||
resourceMan = temp;
|
|
||||||
}
|
|
||||||
return resourceMan;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Overrides the current thread's CurrentUICulture property for all
|
|
||||||
/// resource lookups using this strongly typed resource class.
|
|
||||||
/// </summary>
|
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
|
||||||
internal static global::System.Globalization.CultureInfo Culture {
|
|
||||||
get {
|
|
||||||
return resourceCulture;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
resourceCulture = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap discord_canary_16 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("discord_canary_16", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap discord_canary_32 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("discord_canary_32", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap discord_canary_64 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("discord_canary_64", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap discord_dev_16 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("discord_dev_16", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap discord_dev_32 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("discord_dev_32", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap discord_dev_64 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("discord_dev_64", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap discord_stable_16 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("discord_stable_16", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap discord_stable_32 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("discord_stable_32", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap discord_stable_64 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("discord_stable_64", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap ed_og {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("ed_og", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to require(`${process.env.injDir}/injection.js`);.
|
|
||||||
/// </summary>
|
|
||||||
internal static string injection {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("injection", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to https://codeload.github.com/joe27g/EnhancedDiscord/zip/.
|
|
||||||
/// </summary>
|
|
||||||
internal static string zipLink {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("zipLink", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,157 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
||||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:choice maxOccurs="unbounded">
|
|
||||||
<xsd:element name="metadata">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="assembly">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:attribute name="alias" type="xsd:string" />
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="data">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="resheader">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:choice>
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>2.0</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
|
||||||
<data name="discord_canary_64" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\discord_canary_64.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="discord_dev_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\discord_dev_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="discord_canary_16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\discord_canary_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="discord_stable_64" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\discord_stable_64.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="discord_canary_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\discord_canary_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="discord_dev_64" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\discord_dev_64.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="discord_stable_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\discord_stable_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="discord_dev_16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\discord_dev_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="discord_stable_16" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\discord_stable_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="ed_og" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\ed_og.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="injection" xml:space="preserve">
|
|
||||||
<value>require(`${process.env.injDir}/injection.js`);</value>
|
|
||||||
</data>
|
|
||||||
<data name="zipLink" xml:space="preserve">
|
|
||||||
<value>https://codeload.github.com/joe27g/EnhancedDiscord/zip/</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
|
|
@ -1,26 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
// Runtime Version:4.0.30319.42000
|
|
||||||
//
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace EnhancedDiscordUI.Properties {
|
|
||||||
|
|
||||||
|
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
|
|
||||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
|
||||||
|
|
||||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
|
||||||
|
|
||||||
public static Settings Default {
|
|
||||||
get {
|
|
||||||
return defaultInstance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
<?xml version='1.0' encoding='utf-8'?>
|
|
||||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
|
||||||
<Profiles>
|
|
||||||
<Profile Name="(Default)" />
|
|
||||||
</Profiles>
|
|
||||||
<Settings />
|
|
||||||
</SettingsFile>
|
|
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 4 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 33 KiB |
|
@ -1,98 +0,0 @@
|
||||||
/**
|
|
||||||
* Plugin Class
|
|
||||||
*/
|
|
||||||
class Plugin {
|
|
||||||
/**
|
|
||||||
* Create your plugin, must have a name and load() function
|
|
||||||
* @constructor
|
|
||||||
* @param {object} options - Plugin options
|
|
||||||
*/
|
|
||||||
constructor (opts = {}) {
|
|
||||||
if (!opts.name || typeof opts.load !== 'function')
|
|
||||||
return 'Invalid plugin. Needs a name and a load() function.';
|
|
||||||
|
|
||||||
Object.assign(this, opts);
|
|
||||||
if (!this.color)
|
|
||||||
this.color = 'orange';
|
|
||||||
if (!this.author)
|
|
||||||
this.author = '<unknown>';
|
|
||||||
}
|
|
||||||
|
|
||||||
load () {}
|
|
||||||
|
|
||||||
unload () {}
|
|
||||||
|
|
||||||
reload () {
|
|
||||||
this.unload();
|
|
||||||
delete require.cache[require.resolve(`./plugins/${this.id}`)];
|
|
||||||
const newPlugin = require(`./plugins/${this.id}`);
|
|
||||||
window.ED.plugins[this.id] = newPlugin;
|
|
||||||
newPlugin.id = this.id;
|
|
||||||
newPlugin.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a decorated console.log prefixed with ED and your plugin name
|
|
||||||
* @param {...string} msg - Message to be logged
|
|
||||||
*/
|
|
||||||
log (...msg) {
|
|
||||||
console.log(`%c[EnhancedDiscord] %c[${this.name}]`, 'color: red;', `color: ${this.color}`, ...msg);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Send a decorated console.info prefixed with ED and your plugin name
|
|
||||||
* @param {...string} msg - Message to be logged
|
|
||||||
*/
|
|
||||||
info (...msg) {
|
|
||||||
console.info(`%c[EnhancedDiscord] %c[${this.name}]`, 'color: red;', `color: ${this.color}`, ...msg);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Send a decorated console.warn prefixed with ED and your plugin name
|
|
||||||
* @param {...string} msg - Message to be logged
|
|
||||||
*/
|
|
||||||
warn (...msg) {
|
|
||||||
console.warn(`%c[EnhancedDiscord] %c[${this.name}]`, 'color: red;', `color: ${this.color}`, ...msg);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Send a decorated console.error prefixed with ED and your plugin name
|
|
||||||
* @param {...string} msg - Message to be logged
|
|
||||||
*/
|
|
||||||
error (...msg) {
|
|
||||||
console.error(`%c[EnhancedDiscord] %c[${this.name}]`, 'color: red;', `color: ${this.color}`, ...msg);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns a Promise that resolves after ms milliseconds.
|
|
||||||
* @param {number} ms - How long to wait before resolving the promise
|
|
||||||
*/
|
|
||||||
sleep (ms) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
setTimeout(resolve, ms);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
get settings() {
|
|
||||||
//this.log('getting settings');
|
|
||||||
if (window.ED.config && window.ED.config[this.id])
|
|
||||||
return window.ED.config[this.id];
|
|
||||||
|
|
||||||
const final = {};
|
|
||||||
if (this.config)
|
|
||||||
for (const key in this.config)
|
|
||||||
final[key] = this.config[key].default;
|
|
||||||
return this.settings = final;
|
|
||||||
//return final;
|
|
||||||
}
|
|
||||||
set settings(newSets = {}) {
|
|
||||||
//this.log(__dirname, process.env.injDir);
|
|
||||||
//console.log(`setting settings for ${this.id} to`, newSets);
|
|
||||||
try {
|
|
||||||
const gay = window.ED.config;
|
|
||||||
gay[this.id] = newSets;
|
|
||||||
window.ED.config = gay;
|
|
||||||
//console.log(`set settings for ${this.id} to`, this.settings);
|
|
||||||
} catch(err) {
|
|
||||||
this.error(err);
|
|
||||||
}
|
|
||||||
return this.settings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Plugin;
|
|
|
@ -1,94 +0,0 @@
|
||||||
# How to make plugins
|
|
||||||
|
|
||||||
Let's start by showing the basic format:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const Plugin = require('../plugin');
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'A Plugin', /* Human-readable plugin name. */
|
|
||||||
author: 'Joe', /* [Optional] Put your name here to give yourself credit for making it :) */
|
|
||||||
description: 'Does absolutely nothing, lol', /* Description of what this plugin does. */
|
|
||||||
preload: false, /* [Optional] If true, load this before Discord has finished starting up */
|
|
||||||
color: '#666', /* [Optional] The color that this plugin shows in logs and in the plugin settings tab. Any valid CSS color will work here. */
|
|
||||||
|
|
||||||
load: function() {
|
|
||||||
/* What your plugin does when Discord is loaded, or when the plugin is reloaded. */
|
|
||||||
},
|
|
||||||
unload: function() {
|
|
||||||
/* What your plugin does when it is disabled or being reloaded. */
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Helper functions reference
|
|
||||||
|
|
||||||
The Plugin class adds the following functions to your plugin:
|
|
||||||
|
|
||||||
* **`log`, `info`, `warn`, `error`**: same as `console.log`, `console.info`, etc., except it adds the name and color of your plugin to the log statement. Example: `this.log('Successfully loaded!')`
|
|
||||||
|
|
||||||
* **`sleep(ms)`**: Returns a Promise that resolves after `ms` milliseconds. Usage: `await this.sleep(5000);` __[Make sure you make `load()` an async function first!]__
|
|
||||||
|
|
||||||
### Storing settings
|
|
||||||
|
|
||||||
The Plugin class and settings plugin offer the following helpers for plugin settings:
|
|
||||||
|
|
||||||
* **`settings`**: Stores your plugin's settings in the config file. It is done using getters and setters, so loading and saving your plugin's settings are as easy as reading and writing `this.settings`.
|
|
||||||
|
|
||||||
* **`config`**: Integrates with `settings`. This should essentially store all your default settings, and these will be saved to the config file the first time your plugin is loaded, or when the user resets their settings. Use this when creating your plugin, in the object that is used in `new Plugin({})`.
|
|
||||||
|
|
||||||
* This should be located in the object you used to create the plugin (i.e. between the `id` property and `load` function.)
|
|
||||||
|
|
||||||
* The format is as follows:
|
|
||||||
```js
|
|
||||||
config: {
|
|
||||||
'settingName': {
|
|
||||||
default: 'default value for this setting'
|
|
||||||
/* I highly recommend you add extra properties here to help you create the settings section, if you wish to do so. */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Global helper functions
|
|
||||||
|
|
||||||
The following functions/variables are available from the `window` object to help you make plugins:
|
|
||||||
|
|
||||||
* `findModule(name, silent)`: Looks for a module with a function called `name`. Using this can be trial-and-error sometimes. Example: `findModule('sendMessage').sendMessage('415248292767727616', {content: 'random shit'})` would send the message 'random shit' in #shitposting in the EnhancedDiscord server. The `silent` argument tells whether to send a warning in console if the module is not found.
|
|
||||||
|
|
||||||
* `findModules(name)`: Same as above, but returns an Array of modules.
|
|
||||||
|
|
||||||
* `monkeyPatch(module, functionName, newFunction)`: Replaces a function by the name of `functionName` inside a `module` with a new one (`newFunction`). **This has special properties regarding the original method - Details below.**
|
|
||||||
|
|
||||||
* To access the original arguments, use `arguments[0].methodArguments`. For example, in sendMessage, `arguments[0].methodArguments[0]` is the channel ID.
|
|
||||||
|
|
||||||
* To access the "this" object used internally, use `arguments[0].thisObject`.
|
|
||||||
|
|
||||||
* To access the original function, use `arguments[0].originalMethod`.
|
|
||||||
|
|
||||||
* To run the original function, use `arguments[0].callOriginalMethod(arguments[0].methodArguments)`.
|
|
||||||
|
|
||||||
* To undo your patch, use the `unpatch()` function; for example, `findModule('sendMessage').sendMessage.unpatch();`. The `__monkeyPatched` property, located in the same place, can be used to determine if a function is already patched.
|
|
||||||
|
|
||||||
Original versions of these two functions are from [samogot](https://github.com/samogot)'s [Lib Discord Internals](https://github.com/samogot/betterdiscord-plugins/blob/master/v2/1Lib%20Discord%20Internals/plugin.js).
|
|
||||||
|
|
||||||
### Advanced plugin functionality
|
|
||||||
|
|
||||||
You can also add your own section to EnhancedDiscord's settings in your plugin, but you'll have to do all the grunt work.
|
|
||||||
|
|
||||||
* **You must have a `config` for the following to work.** Set it to an empty object if you do not need it.
|
|
||||||
|
|
||||||
* `generateSettings`: a function that is called when EnhancedDiscord settings are opened. This should return HTML to be placed in your setttings section.
|
|
||||||
|
|
||||||
* `settingListeners`: an Object mapping selectors to eventlisteners.
|
|
||||||
* For example, if your `generateSettings` function has an element `<input type="checkbox" id="memez">`, you might use the following format:
|
|
||||||
```js
|
|
||||||
settingListeners: [{
|
|
||||||
el: '#memez',
|
|
||||||
type: 'click'
|
|
||||||
eHandler: function() {
|
|
||||||
alert('some dumb text');
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
```
|
|
||||||
|
|
||||||
#### For more examples, just browse the included plugins, namely `emoji_packs`.
|
|
|
@ -1,17 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'Anti-Track',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
description: `Prevent Discord from sending "tracking" data that they may be selling to advertisers or otherwise sharing.`,
|
|
||||||
color: 'white',
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
window.EDApi.monkeyPatch(window.EDApi.findModule('track'), 'track', () => {});
|
|
||||||
window.EDApi.monkeyPatch(window.EDApi.findModule('submitLiveCrashReport'), 'submitLiveCrashReport', () => {});
|
|
||||||
},
|
|
||||||
unload: async function() {
|
|
||||||
window.EDApi.findModule('track').track.unpatch();
|
|
||||||
window.EDApi.findModule('submitLiveCrashReport').submitLiveCrashReport.unpatch();
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,107 +0,0 @@
|
||||||
const Plugin = require("../plugin");
|
|
||||||
const Clipboard = require("electron").clipboard;
|
|
||||||
|
|
||||||
let cm = {}, Dispatcher, ImageResolver, ContextMenuActions, ree;
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: "Avatar Links",
|
|
||||||
author: "Joe 🎸#7070",
|
|
||||||
description: "Lets you copy a user or guild's avatar URL by right-clicking on it.",
|
|
||||||
color: "#ffe000",
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
ree = this;
|
|
||||||
cm = window.EDApi.findModule('contextMenu');
|
|
||||||
Dispatcher = window.EDApi.findModule("dispatch");
|
|
||||||
ImageResolver = window.EDApi.findModule("getUserAvatarURL");
|
|
||||||
ContextMenuActions = window.EDApi.findModule("closeContextMenu");
|
|
||||||
|
|
||||||
Dispatcher.subscribe("CONTEXT_MENU_OPEN", this.checkMenu);
|
|
||||||
},
|
|
||||||
|
|
||||||
unload: function() {
|
|
||||||
Dispatcher.unsubscribe("CONTEXT_MENU_OPEN", this.checkMenu);
|
|
||||||
},
|
|
||||||
|
|
||||||
checkMenu: async function() {
|
|
||||||
// Make sure it's already in the DOM
|
|
||||||
await new Promise(r => {setTimeout(r, 5)});
|
|
||||||
const theMenu = document.querySelector('.'+cm.contextMenu);
|
|
||||||
const reactData = theMenu.__reactInternalInstance$;
|
|
||||||
|
|
||||||
let label = "";
|
|
||||||
let url = "";
|
|
||||||
let props = {onHeightUpdate: () => {}};
|
|
||||||
|
|
||||||
// For users
|
|
||||||
if (
|
|
||||||
reactData.return &&
|
|
||||||
reactData.return.return &&
|
|
||||||
reactData.return.return.return &&
|
|
||||||
reactData.return.return.return.return &&
|
|
||||||
reactData.return.return.return.return.memoizedProps &&
|
|
||||||
reactData.return.return.return.return.memoizedProps.user &&
|
|
||||||
reactData.return.return.return.return.memoizedProps.type &&
|
|
||||||
reactData.return.return.return.return.memoizedProps.type.startsWith("USER_")
|
|
||||||
) {
|
|
||||||
props = reactData.return.return.return.return.memoizedProps;
|
|
||||||
label = "Copy Avatar URL";
|
|
||||||
const user = props.user;
|
|
||||||
const imageType = ImageResolver.hasAnimatedAvatar(user) ? "gif" : "png";
|
|
||||||
|
|
||||||
// Internal module maxes at 1024 hardcoded, so do that and change to 2048.
|
|
||||||
url = ImageResolver.getUserAvatarURL(user, imageType, 1024).replace("size=1024", "size=2048");
|
|
||||||
|
|
||||||
// For default avatars
|
|
||||||
if (!url.startsWith("http") && url.startsWith("/assets"))
|
|
||||||
url = `https://discordapp.com${url}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For guilds
|
|
||||||
if (
|
|
||||||
reactData.return &&
|
|
||||||
reactData.return.memoizedProps &&
|
|
||||||
reactData.return.memoizedProps.guild &&
|
|
||||||
reactData.return.memoizedProps.type == "GUILD_ICON_BAR"
|
|
||||||
) {
|
|
||||||
props = reactData.return.memoizedProps;
|
|
||||||
label = "Copy Icon URL";
|
|
||||||
const guild = props.guild;
|
|
||||||
|
|
||||||
// Internal module maxes at 1024 hardcoded, so do that and change to 2048.
|
|
||||||
url = ImageResolver.getGuildIconURL({id: guild.id, icon: guild.icon, size: 1024}).replace("size=1024", "size=2048");
|
|
||||||
|
|
||||||
// No way to make it return the animated version, do it manually
|
|
||||||
if (ImageResolver.hasAnimatedGuildIcon(guild))
|
|
||||||
url = url.replace(".webp?", ".gif?");
|
|
||||||
else
|
|
||||||
url = url.replace(".webp?", ".png?");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assume it is already in the DOM and add item ASAP
|
|
||||||
if (label && url)
|
|
||||||
ree.addMenuItem(url, label, props);
|
|
||||||
},
|
|
||||||
|
|
||||||
addMenuItem: function(imageURL, text, menu) {
|
|
||||||
const cmGroups = document.getElementsByClassName(cm.itemGroup);
|
|
||||||
if (!cmGroups || cmGroups.length == 0) return;
|
|
||||||
|
|
||||||
const newCmItem = document.createElement("div");
|
|
||||||
newCmItem.className = cm.item+' '+cm.clickable;
|
|
||||||
const newCmItemContent = document.createElement("div");
|
|
||||||
newCmItemContent.className = cm.label;
|
|
||||||
newCmItemContent.innerHTML = text;
|
|
||||||
newCmItem.appendChild(newCmItemContent);
|
|
||||||
|
|
||||||
const lastGroup = cmGroups[cmGroups.length-1];
|
|
||||||
lastGroup.appendChild(newCmItem);
|
|
||||||
|
|
||||||
menu.onHeightUpdate();
|
|
||||||
|
|
||||||
newCmItem.onclick = () => {
|
|
||||||
Clipboard.write({text: imageURL});
|
|
||||||
ContextMenuActions.closeContextMenu();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,80 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
|
|
||||||
let ml = {}, cta = {}, ta, gs, em, gc, gci, gcu, cm;
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'Character Count',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
description: `Shows the number of characters next to the message you're typing. Takes into account the extra length of resolved emojis, mentions, etc.`,
|
|
||||||
color: 'violet',
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
ml = window.EDApi.findModule('maxLength');
|
|
||||||
cta = window.EDApi.findModule('channelTextArea');
|
|
||||||
ta = window.EDApi.findModuleByDisplayName('ChannelEditorContainer').prototype;
|
|
||||||
gs = window.EDApi.findModule('getAllSettings');
|
|
||||||
em = window.EDApi.findModule(m => m.checkbox && m.errorMessage);
|
|
||||||
gc = window.EDApi.findModule('getChannel');
|
|
||||||
gci = window.EDApi.findModule('getChannelId');
|
|
||||||
gcu = window.EDApi.findModule('getCurrentUser');
|
|
||||||
cm = window.EDApi.findModule('createBotMessage');
|
|
||||||
|
|
||||||
window.EDApi.monkeyPatch(ta, 'render', {after: this.onRender, silent: true});
|
|
||||||
window.EDApi.findModule('dispatch').subscribe("MESSAGE_CREATE", this.msgListener);
|
|
||||||
},
|
|
||||||
|
|
||||||
onRender: function(b) {
|
|
||||||
const ctaElem = document.querySelector('.' + cta.channelTextArea);
|
|
||||||
if (!ctaElem) return;
|
|
||||||
if (!gs.useRichChatTextBox) return module.exports.inputListener(ctaElem); // legacy support
|
|
||||||
const txt = b.thisObject.props.textValue;
|
|
||||||
const parent = ctaElem.parentElement;
|
|
||||||
let charCountElem = parent.querySelector('.' + ml.maxLength);
|
|
||||||
const len = (txt || '').trim().length;
|
|
||||||
if (!len && charCountElem)
|
|
||||||
charCountElem.remove();
|
|
||||||
if (!len) return;
|
|
||||||
if (!charCountElem) {
|
|
||||||
charCountElem = document.createElement('div');
|
|
||||||
charCountElem.style = "bottom:3px;right:5px;";
|
|
||||||
parent.appendChild(charCountElem);
|
|
||||||
}
|
|
||||||
charCountElem.innerHTML = len + '/2000';
|
|
||||||
charCountElem.className = `ed_char_count ${ml.maxLength}${len > 2000 ? ' '+em.errorMessage : ''}`;
|
|
||||||
},
|
|
||||||
|
|
||||||
msgListener: function(event) {
|
|
||||||
// if message is not by current user or in different channel, cancel
|
|
||||||
if (event.message.author.id !== gcu.getCurrentUser().id || event.message.channel_id !== gci.getChannelId()) return;
|
|
||||||
const charCounters = document.querySelectorAll('.ed_char_count');
|
|
||||||
charCounters.forEach(cc => cc.remove());
|
|
||||||
},
|
|
||||||
|
|
||||||
inputListener: function(elem) {
|
|
||||||
if (!elem) return;
|
|
||||||
const taElem = elem.querySelector('textarea');
|
|
||||||
if (!taElem) return;
|
|
||||||
const parent = elem.parentElement;
|
|
||||||
if (!parent || !elem.className || !elem.className.includes(cta.channelTextArea)) return;
|
|
||||||
let charCountElem = parent.querySelector('.' + ml.maxLength);
|
|
||||||
if (!charCountElem) {
|
|
||||||
charCountElem = document.createElement('div');
|
|
||||||
charCountElem.style = "bottom:3px;right:5px;";
|
|
||||||
parent.appendChild(charCountElem);
|
|
||||||
}
|
|
||||||
const chan = gc.getChannel(gci.getChannelId());
|
|
||||||
let len = (taElem.value || '').trim().length;
|
|
||||||
if (chan && taElem.value) {
|
|
||||||
const msgObj = cm.parse(chan, taElem.value);
|
|
||||||
if (msgObj && msgObj.content)
|
|
||||||
len = msgObj.content.trim().length;
|
|
||||||
}
|
|
||||||
charCountElem.innerHTML = len + '/2000';
|
|
||||||
charCountElem.className = `ed_char_count ${ml.maxLength}${len > 2000 ? ' '+em.errorMessage : ''}`;
|
|
||||||
},
|
|
||||||
|
|
||||||
unload: function() {
|
|
||||||
ta.render.unpatch();
|
|
||||||
window.EDApi.findModule('dispatch').unsubscribe("MESSAGE_CREATE", this.msgListener);
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,149 +0,0 @@
|
||||||
const Plugin = require("../plugin")
|
|
||||||
const path = window.require("path")
|
|
||||||
const fs = window.require("fs")
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: "CSS Loader + Glasscord Integration",
|
|
||||||
author: "Joe 🎸#7070 + AryToNeX",
|
|
||||||
description: "Loads and hot-reloads CSS.",
|
|
||||||
preload: true, //load this before Discord has finished starting up
|
|
||||||
color: "blue",
|
|
||||||
|
|
||||||
config: {
|
|
||||||
path: {
|
|
||||||
default: "./plugins/style.css",
|
|
||||||
parse: function (filePath) {
|
|
||||||
if (!filePath || !filePath.endsWith(".css")) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (path.isAbsolute(filePath)) {
|
|
||||||
if (!fs.existsSync(filePath)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return path.relative(process.env.injDir, filePath)
|
|
||||||
} else {
|
|
||||||
const p = path.join(process.env.injDir, filePath)
|
|
||||||
if (!fs.existsSync(p)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return path.relative(process.env.injDir, p)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
load: async function () {
|
|
||||||
function readFile(path, encoding = "utf-8") {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
fs.readFile(path, encoding, (err, data) => {
|
|
||||||
if (err) reject(err)
|
|
||||||
else resolve(data)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const cssPath = path.join(process.env.injDir, this.settings.path || this.config.path.default)
|
|
||||||
|
|
||||||
readFile(cssPath)
|
|
||||||
.then((css) => {
|
|
||||||
if (!window.customCss) {
|
|
||||||
window.customCss = document.createElement("style")
|
|
||||||
document.head.appendChild(window.customCss)
|
|
||||||
}
|
|
||||||
window.customCss.innerHTML = css
|
|
||||||
this.info("Custom CSS loaded!", window.customCss)
|
|
||||||
window.require("electron").ipcRenderer.send("glasscord_refresh_variables")
|
|
||||||
|
|
||||||
if (window.cssWatcher == null) {
|
|
||||||
window.cssWatcher = fs.watch(cssPath, { encoding: "utf-8" }, (eventType) => {
|
|
||||||
if (eventType == "change") {
|
|
||||||
readFile(cssPath).then((newCss) => {
|
|
||||||
window.customCss.innerHTML = newCss
|
|
||||||
window.require("electron").ipcRenderer.send("glasscord_update")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(() => console.info("Custom CSS not found. Skipping..."))
|
|
||||||
},
|
|
||||||
unload: function () {
|
|
||||||
if (window.customCss) {
|
|
||||||
document.head.removeChild(window.customCss)
|
|
||||||
window.customCss = null
|
|
||||||
}
|
|
||||||
if (window.cssWatcher) {
|
|
||||||
window.cssWatcher.close()
|
|
||||||
window.cssWatcher = null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
generateSettings: function () {
|
|
||||||
const d = window.ED.classMaps.description
|
|
||||||
const b = window.ED.classMaps.buttons
|
|
||||||
const id = window.EDApi.findModule("inputDefault")
|
|
||||||
const m = window.EDApi.findModule("marginTop8")
|
|
||||||
|
|
||||||
const result = `<div class="${d.description} ${
|
|
||||||
d.modeDefault
|
|
||||||
}">Custom CSS Path<br>This can be relative to the EnhancedDiscord directory (e.g. <code class="inline">./big_gay.css</code>) or absolute (e.g. <code class="inline">C:/theme.css</code>.)</div><input type="text" class="${
|
|
||||||
id.inputDefault
|
|
||||||
}" value="${this.settings.path || this.config.path.default}" maxlength="2000" placeholder="${
|
|
||||||
this.config.path.default
|
|
||||||
}" id="custom-css-path"><button type="button" id="save-css-path" class="${b.button} ${
|
|
||||||
b.lookFilled
|
|
||||||
} ${b.colorBrand} ${m.marginTop8} ${
|
|
||||||
m.marginBottom8
|
|
||||||
}" style="height:24px;margin-right:10px;"><div class="${b.contents}">Save</div></button>`
|
|
||||||
return result
|
|
||||||
},
|
|
||||||
settingListeners: [
|
|
||||||
{
|
|
||||||
el: "#save-css-path",
|
|
||||||
type: "click",
|
|
||||||
eHandler: function () {
|
|
||||||
//console.log(this, e.target);
|
|
||||||
const pathInput = document.getElementById("custom-css-path")
|
|
||||||
if (!pathInput) return
|
|
||||||
if (pathInput.value && module.exports.config.path.parse(pathInput.value) == false) {
|
|
||||||
const cont = this.firstElementChild
|
|
||||||
cont.innerHTML = "Invalid file."
|
|
||||||
setTimeout(() => {
|
|
||||||
try {
|
|
||||||
cont.innerHTML = "Save"
|
|
||||||
} catch (err) {
|
|
||||||
/*do nothing*/
|
|
||||||
}
|
|
||||||
}, 3000)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const newPath =
|
|
||||||
module.exports.config.path.parse(pathInput.value) || module.exports.config.path.default
|
|
||||||
const s = module.exports.settings
|
|
||||||
if (s.path == newPath) {
|
|
||||||
const cont = this.firstElementChild
|
|
||||||
cont.innerHTML = "Path was already saved."
|
|
||||||
setTimeout(() => {
|
|
||||||
try {
|
|
||||||
cont.innerHTML = "Save"
|
|
||||||
} catch (err) {
|
|
||||||
/*do nothing*/
|
|
||||||
}
|
|
||||||
}, 3000)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.path = newPath
|
|
||||||
module.exports.settings = s
|
|
||||||
module.exports.unload()
|
|
||||||
module.exports.load()
|
|
||||||
const cont = this.firstElementChild
|
|
||||||
cont.innerHTML = "Saved!"
|
|
||||||
setTimeout(() => {
|
|
||||||
try {
|
|
||||||
cont.innerHTML = "Save"
|
|
||||||
} catch (err) {
|
|
||||||
/*do nothing*/
|
|
||||||
}
|
|
||||||
}, 3000)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
|
@ -1,104 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
|
|
||||||
// contains modified code from https://stackoverflow.com/a/47820271
|
|
||||||
const { dialog } = require('electron').remote;
|
|
||||||
const http = require('https');
|
|
||||||
const fs = require('fs');
|
|
||||||
let ttM = {}, iteM = {};
|
|
||||||
|
|
||||||
function saveAs(url, filename, fileExtension) {
|
|
||||||
const userChosenPath = dialog.showSaveDialog({ defaultPath: filename, title: 'Where would you like to store the stolen memes?', buttonLabel: 'Steal this meme', filters: [{ name: "Stolen meme", extensions: [fileExtension] }] });
|
|
||||||
if (userChosenPath) {
|
|
||||||
download(url, userChosenPath, () => {
|
|
||||||
const wrap = document.createElement('div');
|
|
||||||
wrap.className = 'theme-dark';
|
|
||||||
const gay = document.createElement('div');
|
|
||||||
gay.style = "position: fixed; bottom: 10%; left: calc(50% - 88px);"
|
|
||||||
gay.className = `${ttM.tooltip} ${ttM.tooltipTop} ${ttM.tooltipBlack}`;
|
|
||||||
gay.innerHTML = 'Successfully downloaded | ' + userChosenPath;
|
|
||||||
document.body.appendChild(wrap);
|
|
||||||
wrap.appendChild(gay);
|
|
||||||
setTimeout(() => wrap.remove(), 2000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function download (url, dest, cb) {
|
|
||||||
const file = fs.createWriteStream(dest);
|
|
||||||
http.get(url, function(response) {
|
|
||||||
response.pipe(file);
|
|
||||||
file.on('finish', function() {
|
|
||||||
file.close(cb);
|
|
||||||
});
|
|
||||||
}).on('error', function(err) {
|
|
||||||
fs.unlink(dest);
|
|
||||||
if (cb) cb(err.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function addMenuItem(url, text, filename = true, fileExtension) {
|
|
||||||
const cmGroups = document.getElementsByClassName(iteM.itemGroup);
|
|
||||||
if (!cmGroups || cmGroups.length == 0) return;
|
|
||||||
|
|
||||||
const newCmItem = document.createElement('div');
|
|
||||||
newCmItem.className = iteM.item;
|
|
||||||
newCmItem.innerHTML = text;
|
|
||||||
|
|
||||||
const lastGroup = cmGroups[cmGroups.length-1];
|
|
||||||
lastGroup.appendChild(newCmItem);
|
|
||||||
newCmItem.onclick = () => saveAs(url, filename, fileExtension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// contains code modified from https://github.com/Metalloriff/BetterDiscordPlugins/blob/master/SaveTo.plugin.js
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'Direct Download',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
description: `<del>Download files</del> Steal memes without opening a browser.`,
|
|
||||||
color: '#18770e',
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
this._cmClass = window.EDApi.findModule("contextMenu").contextMenu;
|
|
||||||
this._contClass = window.EDApi.findModule("embedWrapper").container;
|
|
||||||
ttM = window.EDApi.findModule('tooltipPointer');
|
|
||||||
iteM = window.EDApi.findModule('itemBase');
|
|
||||||
document.addEventListener("contextmenu", this.listener);
|
|
||||||
},
|
|
||||||
listener(e) {
|
|
||||||
if (document.getElementsByClassName(this._cmClass).length == 0) setTimeout(() => module.exports.onContextMenu(e), 0);
|
|
||||||
else this.onContextMenu(e);
|
|
||||||
},
|
|
||||||
onContextMenu(e) {
|
|
||||||
const messageGroup = e.target.closest('.'+this._contClass);
|
|
||||||
|
|
||||||
if (e.target.localName != "a" && e.target.localName != "img" && e.target.localName != "video" && !messageGroup && !e.target.className.includes("guildIcon") && !e.target.className.includes("image-")) return;
|
|
||||||
|
|
||||||
let saveLabel = "Download",
|
|
||||||
url = e.target.poster || e.target.style.backgroundImage.substring(e.target.style.backgroundImage.indexOf(`"`) + 1, e.target.style.backgroundImage.lastIndexOf(`"`)) || e.target.href || e.target.src;
|
|
||||||
|
|
||||||
if (e.target.className.includes("guildIcon")) saveLabel = "Download Icon";
|
|
||||||
else if (e.target.className.includes("image-")) saveLabel = "Download Avatar";
|
|
||||||
|
|
||||||
|
|
||||||
if (!url || e.target.classList.contains("emote") || url.includes("youtube.com/watch?v=") || url.includes("youtu.be/") || url.lastIndexOf("/") > url.lastIndexOf(".")) return;
|
|
||||||
|
|
||||||
url = url.split("?")[0];
|
|
||||||
|
|
||||||
url = url.replace(".webp", ".png");
|
|
||||||
|
|
||||||
let fileName = url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf("."));
|
|
||||||
const fileExtension = url.substr(url.lastIndexOf(".") + 1, url.length);
|
|
||||||
|
|
||||||
if (saveLabel.includes("Avatar") || saveLabel.includes("Icon")) url += "?size=2048";
|
|
||||||
|
|
||||||
if (e.target.classList.contains("emoji")) {
|
|
||||||
saveLabel = "Download Emoji";
|
|
||||||
fileName = e.target.alt.replace(/[^A-Za-z_-]/g, "");
|
|
||||||
}
|
|
||||||
//console.log({url, saveLabel, fileName, fileExtension});
|
|
||||||
|
|
||||||
setTimeout(() => addMenuItem(url, saveLabel, fileName, fileExtension), 5);
|
|
||||||
},
|
|
||||||
unload: function() {
|
|
||||||
document.removeEventListener("contextmenu", this.listener);
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,85 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
let contM = {}, cM, eM, dM, mM, ewM = {}, ree;
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'Double-Click Edit',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
description: 'Allows you to double-click a message to edit or hold delete + click to delete.',
|
|
||||||
color: '#ff5900',
|
|
||||||
|
|
||||||
deletePressed: false,
|
|
||||||
load: async function() {
|
|
||||||
contM = window.EDApi.findModule(m => m.container && m.containerCozy);
|
|
||||||
cM = window.EDApi.findModule('getChannelId');
|
|
||||||
eM = window.EDApi.findModule('startEditMessage');
|
|
||||||
dM = window.EDApi.findModule('deleteMessage');
|
|
||||||
mM = window.EDApi.findModule('getRawMessages');
|
|
||||||
ewM = window.EDApi.findModule('embedWrapper');
|
|
||||||
if (!cM || !eM || !dM || !ewM) {
|
|
||||||
return this.error('Aborted loading - Failed to find required modules!');
|
|
||||||
}
|
|
||||||
ree = this;
|
|
||||||
|
|
||||||
document.addEventListener("dblclick", this.editListener, false);
|
|
||||||
document.addEventListener("keydown", this.keyDownListener);
|
|
||||||
document.addEventListener("keyup", this.keyUpListener);
|
|
||||||
document.addEventListener("click", this.deleteListener);
|
|
||||||
|
|
||||||
// allow editing in "locked" (read-only) channels
|
|
||||||
const prot = window.EDApi.findModuleByDisplayName("ChannelEditorContainer").prototype;
|
|
||||||
window.EDApi.monkeyPatch(prot, 'render', b => {
|
|
||||||
if (b.thisObject.props.type === 'edit')
|
|
||||||
b.thisObject.props.disabled = false;
|
|
||||||
return b.callOriginalMethod(b.methodArguments);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
unload: async function() {
|
|
||||||
document.removeEventListener("dblclick", this.editListener);
|
|
||||||
document.removeEventListener("keydown", this.keyDownListener);
|
|
||||||
document.removeEventListener("keyup", this.keyUpListener);
|
|
||||||
document.removeEventListener("click", this.deleteListener);
|
|
||||||
},
|
|
||||||
|
|
||||||
editListener: function(e) {
|
|
||||||
const messageElem = e.target.closest('.'+contM.container);
|
|
||||||
if (!messageElem) return;
|
|
||||||
let msgObj;
|
|
||||||
try {
|
|
||||||
msgObj = messageElem.__reactInternalInstance$.return.return.memoizedProps.message;
|
|
||||||
} catch(err) {
|
|
||||||
ree.error(err);
|
|
||||||
}
|
|
||||||
if (!msgObj) return;
|
|
||||||
const channelId = cM.getChannelId();
|
|
||||||
if (!channelId) return;
|
|
||||||
const newMsgObj = mM.getMessage(msgObj.channel_id, msgObj.id);
|
|
||||||
return eM.startEditMessage(channelId, msgObj.id, newMsgObj.content || '');
|
|
||||||
},
|
|
||||||
deleteListener: function(e) {
|
|
||||||
if (!ree.deletePressed) return;
|
|
||||||
|
|
||||||
let messageElem = e.target.closest('.'+contM.container);
|
|
||||||
const wrapperElem = e.target.closest('.'+ewM.container);
|
|
||||||
if (!messageElem && wrapperElem)
|
|
||||||
messageElem = wrapperElem.parentElement.firstElementChild;
|
|
||||||
if (!messageElem) return;
|
|
||||||
let msgObj;
|
|
||||||
try {
|
|
||||||
msgObj = messageElem.__reactInternalInstance$.return.return.memoizedProps.message;
|
|
||||||
} catch(err) {
|
|
||||||
ree.error(err);
|
|
||||||
}
|
|
||||||
if (!msgObj) return;
|
|
||||||
const channelId = cM.getChannelId();
|
|
||||||
if (!channelId) return;
|
|
||||||
return dM.deleteMessage(channelId, msgObj.id);
|
|
||||||
},
|
|
||||||
keyUpListener: function(e) {
|
|
||||||
if (e.keyCode == 46)
|
|
||||||
ree.deletePressed = false;
|
|
||||||
},
|
|
||||||
keyDownListener: function(e) {
|
|
||||||
if (e.keyCode == 46)
|
|
||||||
ree.deletePressed = true;
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,42 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
let userM = {}, taM = {}, avM = {}, wM = {}, ree;
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'Double-Click Mention',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
description: 'Allows you to double-click a user\'s name to mention them.',
|
|
||||||
color: '#00bbff',
|
|
||||||
|
|
||||||
_userTag: '',
|
|
||||||
load: async function() {
|
|
||||||
taM = window.EDApi.findModule('textArea');
|
|
||||||
userM = window.EDApi.findModule('username');
|
|
||||||
avM = window.EDApi.findModule('avatar');
|
|
||||||
wM = window.EDApi.findModule(m => m.wrapper && m.avatar);
|
|
||||||
ree = this;
|
|
||||||
|
|
||||||
document.addEventListener("dblclick", this.doubleListener);
|
|
||||||
},
|
|
||||||
unload: async function() {
|
|
||||||
document.removeEventListener("dblclick", this.doubleListener);
|
|
||||||
},
|
|
||||||
|
|
||||||
doubleListener: function(e) {
|
|
||||||
if (!e || !e.target || !e.target.parentElement) return;
|
|
||||||
let tag;
|
|
||||||
try {
|
|
||||||
if (e.target.className === userM.username)
|
|
||||||
tag = e.target.parentElement.__reactInternalInstance$.return.return.memoizedProps.message.author.tag;
|
|
||||||
else if (e.target.className === wM.wrapper && e.target.parentElement.className === avM.avatar)
|
|
||||||
tag = e.target.parentElement.__reactInternalInstance$.return.return.memoizedProps.user.tag;
|
|
||||||
} catch(err) {
|
|
||||||
ree.error(err);
|
|
||||||
tag = null;
|
|
||||||
}
|
|
||||||
if (!tag) return;
|
|
||||||
|
|
||||||
const ta = document.querySelector('.'+taM.textArea);
|
|
||||||
if (!ta) return;
|
|
||||||
ta.value = `${ta.value ? ta.value.endsWith(' ') ? ta.value : ta.value+' ' : ''}@${tag} `;
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,251 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
|
|
||||||
function makePluginToggle(opts = {}) {
|
|
||||||
const a = window.ED.classMaps.alignment;
|
|
||||||
const sw = window.ED.classMaps.switchItem;
|
|
||||||
const cb = window.ED.classMaps.checkbox;
|
|
||||||
const b = window.ED.classMaps.buttons;
|
|
||||||
const d = window.ED.classMaps.description;
|
|
||||||
const settingsButton = `<button type="button" class="${b.button} ${b.lookFilled} ${b.colorBrand} ed-plugin-settings" style="height:24px;margin-right:10px;"><div class="${b.contents}">Settings</div></button>`;
|
|
||||||
|
|
||||||
return `<div id="${opts.id}-wrap" class="${a.vertical} ${a.justifyStart} ${a.alignStretch} ${a.noWrap} ${sw.switchItem}" style="flex: 1 1 auto;">
|
|
||||||
<div class="${a.horizontal} ${a.justifyStart} ${a.alignStart} ${a.noWrap}" style="flex: 1 1 auto;">
|
|
||||||
<h3 class="${sw.titleDefault}" style="flex: 1 1 auto;">${opts.title}</h3>
|
|
||||||
${opts.color ? ` <div class="status" style="background-color:${opts.color}; box-shadow:0 0 5px 2px ${opts.color};margin-left: 5px; border-radius: 50%; height: 10px; width: 10px; position: relative; top: 6px; margin-right: 8px;"></div>` : ''}
|
|
||||||
${opts.showSettingsButton ? settingsButton : ''}
|
|
||||||
${opts.id == 'bdPlugins' ? '' : `<button type="button" class="${b.button} ${b.lookFilled} ${b.colorBrand} ed-plugin-reload" style="height:24px;margin-right:10px;"><div class="${b.contents}">Reload</div></button>`}
|
|
||||||
<div id="${opts.id}" class="${cb.switchEnabled} ${cb.valueUnchecked} ${cb.sizeDefault} ${cb.themeDefault}">
|
|
||||||
<input type="checkbox" class="${cb.checkboxEnabled}" value="on">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="${d.description} ${d.modeDefault}" style="flex: 1 1 auto;">${opts.desc ? opts.desc : '<i>No Description Provided</i<'}</div>
|
|
||||||
<div class="${window.ED.classMaps.divider} ${sw.dividerDefault}"></div>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'ED Settings',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
description: 'Adds an EnhancedDiscord tab in user settings.',
|
|
||||||
color: 'darkred',
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
const parentThis = this; //Allow use of parent methods in sub functions
|
|
||||||
|
|
||||||
if (!window.ED.classMaps) {
|
|
||||||
window.ED.classMaps = {};
|
|
||||||
}
|
|
||||||
const tabsM = window.EDApi.findModule('topPill');
|
|
||||||
const divM = window.EDApi.findModule(m => m.divider && Object.keys(m).length === 1)
|
|
||||||
const contentM = window.ED.classMaps.headers = window.EDApi.findModule('defaultMarginh2');
|
|
||||||
const marginM = window.ED.classMaps.margins = window.EDApi.findModule('marginBottom8');
|
|
||||||
const div = window.ED.classMaps.divider = divM ? divM.divider : '';
|
|
||||||
const cbM = window.ED.classMaps.checkbox = window.EDApi.findModule('checkboxEnabled');
|
|
||||||
const buttM = window.ED.classMaps.buttons = window.EDApi.findModule('lookFilled');
|
|
||||||
const concentCol = window.EDApi.findModule('contentColumn');
|
|
||||||
window.ED.classMaps.switchItem = window.EDApi.findModule('switchItem');
|
|
||||||
window.ED.classMaps.alignment = window.EDApi.findModule('horizontalReverse');
|
|
||||||
window.ED.classMaps.description = window.EDApi.findModule('formText');
|
|
||||||
|
|
||||||
// use this function to trigger the loading of the settings tabs. No MutationObservers this way :)
|
|
||||||
const gss = window.EDApi.findModule('getUserSettingsSections').default.prototype;
|
|
||||||
window.EDApi.monkeyPatch(gss, 'render', function() {
|
|
||||||
|
|
||||||
const tab = document.getElementsByClassName('ed-settings');
|
|
||||||
//console.log(tab);
|
|
||||||
if (!tab || tab.length < 1) {
|
|
||||||
const parent = document.querySelector('.' + tabsM.side);
|
|
||||||
if (!parent) {
|
|
||||||
setTimeout(() => {arguments[0].thisObject.forceUpdate();}, 100);
|
|
||||||
return arguments[0].callOriginalMethod(arguments[0].methodArguments);
|
|
||||||
}
|
|
||||||
const anchor = parent.querySelectorAll(`.${tabsM.separator}`)[3];
|
|
||||||
if (!anchor)
|
|
||||||
return arguments[0].callOriginalMethod(arguments[0].methodArguments);
|
|
||||||
|
|
||||||
const header = document.createElement('div');
|
|
||||||
header.className = tabsM.header + ' ed-settings';
|
|
||||||
header.innerHTML = 'EnhancedDiscord';
|
|
||||||
anchor.parentNode.insertBefore(header, anchor.nextSibling);
|
|
||||||
|
|
||||||
const pluginsTab = document.createElement('div');
|
|
||||||
const tabClass = `${tabsM.item} ${tabsM.themed} ed-settings`;
|
|
||||||
pluginsTab.className = tabClass;
|
|
||||||
pluginsTab.innerHTML = 'Plugins';
|
|
||||||
header.parentNode.insertBefore(pluginsTab, header.nextSibling);
|
|
||||||
|
|
||||||
const settingsTab = document.createElement('div');
|
|
||||||
settingsTab.className = tabClass;
|
|
||||||
settingsTab.innerHTML = 'Settings';
|
|
||||||
pluginsTab.parentNode.insertBefore(settingsTab, pluginsTab.nextSibling);
|
|
||||||
|
|
||||||
const sep = document.createElement('div');
|
|
||||||
sep.className = tabsM.separator;
|
|
||||||
settingsTab.parentNode.insertBefore(sep, settingsTab.nextSibling);
|
|
||||||
|
|
||||||
parent.onclick = function(e) {
|
|
||||||
if (!e.target.className || e.target.className.indexOf(tabsM.item) == -1 || e.target.innerHTML === 'Change Log') return;
|
|
||||||
|
|
||||||
for (const i in tab) {
|
|
||||||
tab[i].className = (tab[i].className || '').replace(" " + tabsM.selected, '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pluginsTab.onclick = function(e) {
|
|
||||||
const settingsPane = document.querySelector(`.${concentCol.standardSidebarView} .${concentCol.contentColumn} > div`);
|
|
||||||
const otherTab = document.querySelector('.' + tabsM.item + '.' + tabsM.selected);
|
|
||||||
if (otherTab) {
|
|
||||||
otherTab.className = otherTab.className.replace(" " + tabsM.selected, '');
|
|
||||||
}
|
|
||||||
this.className += ` ${tabsM.selected}`;
|
|
||||||
|
|
||||||
if (settingsPane) {
|
|
||||||
// ED Header
|
|
||||||
settingsPane.innerHTML = `<h2 class="${contentM.h2} ${contentM.defaultColor} ${marginM.marginBottom8}">EnhancedDiscord Plugins</h2>`;
|
|
||||||
// Open Plugins Folder Button
|
|
||||||
settingsPane.innerHTML += `<button id="ed-openPluginsFolder" style="margin-bottom: 10px;" class="${buttM.button} ${buttM.lookFilled} ${buttM.colorGreen} ${buttM.sizeSmall} ${buttM.grow}"><div class="${buttM.contents}">Open Plugins Directory</div></button>`;
|
|
||||||
// Divider
|
|
||||||
settingsPane.innerHTML += `<div class="${div} ${marginM.marginBottom20}"></div>`
|
|
||||||
|
|
||||||
for (const id in window.ED.plugins) {
|
|
||||||
//if (id == 'ed_settings') continue;
|
|
||||||
|
|
||||||
settingsPane.innerHTML += makePluginToggle({id, title: window.ED.plugins[id].name, desc: window.ED.plugins[id].description, color: window.ED.plugins[id].color || 'orange', showSettingsButton: typeof window.ED.plugins[id].getSettingsPanel == 'function'});
|
|
||||||
if (!window.ED.plugins[id].settings || window.ED.plugins[id].settings.enabled !== false) {
|
|
||||||
const cb = document.getElementById(id);
|
|
||||||
if (cb && cb.className)
|
|
||||||
cb.className = cb.className.replace(cbM.valueUnchecked, cbM.valueChecked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById("ed-openPluginsFolder").onclick = function () {
|
|
||||||
const s = require("electron").shell.openItem(require("path").join(process.env.injDir, "plugins"))
|
|
||||||
if (s === false) console.error("[EnhancedDiscord] Unable to open external folder.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e.stopPropagation(); // prevent from going to parent click handler
|
|
||||||
}
|
|
||||||
|
|
||||||
settingsTab.onclick = function(e) {
|
|
||||||
const settingsPane = document.querySelector(`.${concentCol.standardSidebarView} .${concentCol.contentColumn} > div`);
|
|
||||||
const otherTab = document.querySelector('.' + tabsM.item + '.' + tabsM.selected);
|
|
||||||
if (otherTab) {
|
|
||||||
otherTab.className = otherTab.className.replace(" " + tabsM.selected, '');
|
|
||||||
}
|
|
||||||
this.className += ` ${tabsM.selected}`;
|
|
||||||
|
|
||||||
if (settingsPane) {
|
|
||||||
settingsPane.innerHTML = `<h2 class="${contentM.h2} ${contentM.defaultColor}">EnhancedDiscord Configuration</h2><div class="${div} ${marginM.marginBottom20}"></div>`;
|
|
||||||
settingsPane.innerHTML += makePluginToggle({id: 'bdPlugins', title: 'BD Plugins', desc: "Allows ED to load BD plugins natively. (Reload with ctrl+r after enabling/disabling.)"});
|
|
||||||
|
|
||||||
const bl = document.getElementById('bdPlugins');
|
|
||||||
if (bl && window.ED.config.bdPlugins == true)
|
|
||||||
bl.className = bl.className.replace(cbM.valueUnchecked, cbM.valueChecked);
|
|
||||||
//console.log(st, at);
|
|
||||||
for (const id in window.ED.plugins) {
|
|
||||||
if (window.ED.plugins[id].getSettingsPanel && typeof window.ED.plugins[id].getSettingsPanel == 'function') continue;
|
|
||||||
if (!window.ED.plugins[id].config || window.ED.config[id].enabled === false || !window.ED.plugins[id].generateSettings) continue;
|
|
||||||
|
|
||||||
settingsPane.innerHTML += `<h2 class="${contentM.h2} ${contentM.defaultColor}">${window.ED.plugins[id].name}</h2>`;
|
|
||||||
|
|
||||||
settingsPane.innerHTML += window.ED.plugins[id].generateSettings();
|
|
||||||
|
|
||||||
settingsPane.innerHTML += `<div class="${div}"></div>`;
|
|
||||||
if (window.ED.plugins[id].settingListeners) {
|
|
||||||
setTimeout(() => { // let shit render
|
|
||||||
for(const eventObject in window.ED.plugins[id].settingListeners){
|
|
||||||
const currentSettingListener = window.ED.plugins[id].settingListeners[eventObject];
|
|
||||||
//Check if plugin is using the old format
|
|
||||||
|
|
||||||
if(Array.isArray(window.ED.plugins[id].settingListeners)){
|
|
||||||
const elem = settingsPane.querySelector(currentSettingListener.el);
|
|
||||||
if (elem)
|
|
||||||
elem.addEventListener(currentSettingListener.type, currentSettingListener.eHandler);
|
|
||||||
} else {
|
|
||||||
const elem = settingsPane.querySelector(eventObject);
|
|
||||||
if (elem){
|
|
||||||
parentThis.warn(`Plugin ${window.ED.plugins[id].name} is using a deprecated plugin format (New format: https://github.com/joe27g/EnhancedDiscord/blob/beta/plugins.md#advanced-plugin-functionality). Ignore this unless you're the plugin dev`)
|
|
||||||
elem.onclick = window.ED.plugins[id].settingListeners[eventObject];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e.stopPropagation(); // prevent from going to parent click handler
|
|
||||||
}
|
|
||||||
|
|
||||||
document.querySelector(`.${concentCol.standardSidebarView} .${concentCol.contentColumn}`).onclick = function(e) {
|
|
||||||
const parent = e.target.parentElement;
|
|
||||||
if (e.target.className && ((parent.className.indexOf && parent.className.indexOf('ed-plugin-settings') > -1) || (e.target.className.indexOf && e.target.className.indexOf('ed-plugin-settings') > -1))) {
|
|
||||||
const box = e.target.className === buttM.contents ? parent.nextElementSibling.nextElementSibling : e.target.nextElementSibling.nextElementSibling;
|
|
||||||
if (!box || !box.id || !window.ED.plugins[box.id] || box.className.indexOf(cbM.valueChecked) == -1 || !window.ED.config.bdPlugins) return;
|
|
||||||
return require('../bd_shit').showSettingsModal(window.ED.plugins[box.id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.target.className && ((parent.className.indexOf && parent.className.indexOf('ed-plugin-reload') > -1) || (e.target.className.indexOf && e.target.className.indexOf('ed-plugin-reload') > -1))) {
|
|
||||||
const button = e.target.className === buttM.contents ? e.target : e.target.firstElementChild;
|
|
||||||
const plugin = e.target.className === buttM.contents ? e.target.parentElement.nextElementSibling : e.target.nextElementSibling;
|
|
||||||
//console.log(plugin);
|
|
||||||
if (!plugin || !plugin.id || !window.ED.plugins[plugin.id] || plugin.className.indexOf(cbM.valueChecked) == -1) return;
|
|
||||||
button.innerHTML = 'Reloading...';
|
|
||||||
try {
|
|
||||||
window.ED.plugins[plugin.id].reload();
|
|
||||||
button.innerHTML = 'Reloaded!';
|
|
||||||
} catch(err) {
|
|
||||||
console.error(err);
|
|
||||||
button.innerHTML = `Failed to reload (${err.name} - see console.)`;
|
|
||||||
}
|
|
||||||
setTimeout(() => {
|
|
||||||
try { button.innerHTML = 'Reload'; } catch(err){/*do nothing*/}
|
|
||||||
}, 3000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.target.tagName !== 'INPUT' || e.target.type !== 'checkbox' || !parent || !parent.className || !parent.id) return;
|
|
||||||
const p = window.ED.plugins[parent.id];
|
|
||||||
if (!p && parent.id !== 'bdPlugins') return;
|
|
||||||
//console.log('settings for '+p.id, p.settings);
|
|
||||||
|
|
||||||
if (parent.className.indexOf(cbM.valueChecked) > -1) {
|
|
||||||
if (p) {
|
|
||||||
if (p.settings.enabled === false) return;
|
|
||||||
|
|
||||||
p.settings.enabled = false;
|
|
||||||
window.ED.plugins[parent.id].settings = p.settings;
|
|
||||||
p.unload();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const edc = window.ED.config;
|
|
||||||
if (!edc[parent.id]) return;
|
|
||||||
edc[parent.id] = false;
|
|
||||||
window.ED.config = edc;
|
|
||||||
}
|
|
||||||
parent.className = parent.className.replace(cbM.valueChecked, cbM.valueUnchecked);
|
|
||||||
} else {
|
|
||||||
if (p) {
|
|
||||||
if (p.settings.enabled !== false) return;
|
|
||||||
|
|
||||||
p.settings.enabled = true;
|
|
||||||
window.ED.plugins[parent.id].settings = p.settings;
|
|
||||||
p.load();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const edc = window.ED.config;
|
|
||||||
if (edc[parent.id] === true) return;
|
|
||||||
edc[parent.id] = true;
|
|
||||||
window.ED.config = edc;
|
|
||||||
}
|
|
||||||
parent.className = parent.className.replace(cbM.valueUnchecked, cbM.valueChecked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return arguments[0].callOriginalMethod(arguments[0].methodArguments);
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
unload: function() {
|
|
||||||
window.EDApi.findModule('getUserSettingsSections').default.prototype.render.unpatch();
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,91 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
|
|
||||||
function makeToggle() {
|
|
||||||
const a = window.ED.classMaps.alignment;
|
|
||||||
const sw = window.ED.classMaps.switchItem;
|
|
||||||
const cb = window.ED.classMaps.checkbox;
|
|
||||||
const b = window.ED.classMaps.buttons;
|
|
||||||
const d = window.ED.classMaps.description;
|
|
||||||
|
|
||||||
return `<div class="${window.ED.classMaps.divider} ${sw.dividerDefault}"></div>
|
|
||||||
<div id="fc_online_wrap" class="${a.vertical} ${a.justifyStart} ${a.alignStretch} ${a.noWrap} ${sw.switchItem}" style="flex: 1 1 auto;">
|
|
||||||
<div class="${a.horizontal} ${a.justifyStart} ${a.alignStart} ${a.noWrap}" style="flex: 1 1 auto;">
|
|
||||||
<h3 class="${sw.titleDefault}" style="flex: 1 1 auto;">Online Friends</h3>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="fc_online" class="${cb.switchEnabled} ${(module.exports.settings || {}).onlineOnly ? cb.valueChecked : cb.valueUnchecked} ${cb.sizeDefault} ${cb.themeDefault}">
|
|
||||||
<input type="checkbox" class="${cb.checkboxEnabled}" value="on">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="${d.description} ${d.modeDefault}" style="flex: 1 1 auto;">Only show the number of friends online rather than all friends.</div>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'Friend Count',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
description: "Adds the number of friends/online friends under the \"Home\" button in the top left.",
|
|
||||||
color: 'cornflowerblue',
|
|
||||||
|
|
||||||
config: {
|
|
||||||
onlineOnly: {default: false}
|
|
||||||
},
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
const sep = window.findModule('guildSeparator'), ms = window.findModule('modeSelectable');
|
|
||||||
|
|
||||||
const gg = function(b) {
|
|
||||||
if (!sep) return;
|
|
||||||
const o = (module.exports.settings || {}).onlineOnly;
|
|
||||||
const num = o ? window.findModule("getOnlineFriendCount").getOnlineFriendCount() : window.findModule("getFriendIDs").getFriendIDs().length;
|
|
||||||
|
|
||||||
let friendCount = document.getElementById('ed_friend_count');
|
|
||||||
if (friendCount) {
|
|
||||||
if (num === this._num) return; // don't update if # is the same as before
|
|
||||||
friendCount.innerHTML = num + (o ? ' Online' : ' Friends');
|
|
||||||
this._num = num;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let separator = document.querySelector(`.${sep.guildSeparator}`);
|
|
||||||
if (separator) {
|
|
||||||
friendCount = document.createElement('div');
|
|
||||||
friendCount.className = `${ms ? ms.description+' ' : ''}${sep.listItem}`;
|
|
||||||
friendCount.innerHTML = num + (o ? ' Online' : ' Friends');
|
|
||||||
friendCount.id = 'ed_friend_count';
|
|
||||||
try {
|
|
||||||
separator.parentElement.insertAdjacentElement('beforebegin', friendCount);
|
|
||||||
this._num = num;
|
|
||||||
} catch(err) {
|
|
||||||
this.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const x = window.findModule('getGuilds');
|
|
||||||
findModule('subscribe').subscribe('CONNECTION_OPEN', x.getGuilds);
|
|
||||||
window.monkeyPatch(x, 'getGuilds', {silent: true, after: gg});
|
|
||||||
},
|
|
||||||
unload: function() {
|
|
||||||
let m = window.findModule('getGuilds').getGuilds;
|
|
||||||
if (m && m.__monkeyPatched)
|
|
||||||
m.unpatch();
|
|
||||||
let friendCount = document.getElementById('ed_friend_count');
|
|
||||||
if (friendCount)
|
|
||||||
friendCount.remove();
|
|
||||||
},
|
|
||||||
generateSettings: makeToggle,
|
|
||||||
settingListeners: [{
|
|
||||||
el: '#fc_online',
|
|
||||||
type: 'click',
|
|
||||||
eHandler: function(e) {
|
|
||||||
const cb = window.ED.classMaps.checkbox;
|
|
||||||
module.exports.settings = {onlineOnly: !(module.exports.settings || {}).onlineOnly};
|
|
||||||
if (module.exports.settings.onlineOnly) {
|
|
||||||
this.classList.remove(cb.valueUnchecked.split(' ')[0]);
|
|
||||||
this.classList.add(cb.valueChecked.split(' ')[0]);
|
|
||||||
} else {
|
|
||||||
this.classList.remove(cb.valueChecked.split(' ')[0]);
|
|
||||||
this.classList.add(cb.valueUnchecked.split(' ')[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
});
|
|
|
@ -1,53 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
|
|
||||||
let sep = {}, ms = {}, gg, sub;
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'Server Count',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
description: "Adds the number of servers you're currently in right above the list.",
|
|
||||||
color: 'indigo',
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
sep = window.EDApi.findModule('guildSeparator');
|
|
||||||
ms = window.EDApi.findModule('modeSelectable');
|
|
||||||
gg = window.EDApi.findModule('getGuilds');
|
|
||||||
sub = window.EDApi.findModule('subscribe');
|
|
||||||
|
|
||||||
window.EDApi.monkeyPatch(gg, 'getGuilds', {after: this.refreshCount, silent: true});
|
|
||||||
sub.subscribe('CONNECTION_OPEN', gg.getGuilds);
|
|
||||||
},
|
|
||||||
refreshCount: function(b) {
|
|
||||||
if (!sep) return;
|
|
||||||
const num = Object.keys(b.returnValue).length;
|
|
||||||
|
|
||||||
let guildCount = document.getElementById('ed_guild_count');
|
|
||||||
if (guildCount) {
|
|
||||||
if (num === this._num) return; // don't update if # is the same as before
|
|
||||||
guildCount.innerHTML = num + ' Servers';
|
|
||||||
this._num = num;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const separator = document.querySelector(`.${sep.guildSeparator}`);
|
|
||||||
if (separator) {
|
|
||||||
guildCount = document.createElement('div');
|
|
||||||
guildCount.className = `${ms ? ms.description+' ' : ''}${sep.listItem}`;
|
|
||||||
guildCount.innerHTML = num + ' Servers';
|
|
||||||
guildCount.id = 'ed_guild_count';
|
|
||||||
try {
|
|
||||||
separator.parentElement.insertAdjacentElement('beforebegin', guildCount);
|
|
||||||
this._num = num;
|
|
||||||
} catch(err) {
|
|
||||||
this.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
unload: function() {
|
|
||||||
gg.getGuilds.unpatch();
|
|
||||||
const guildCount = document.getElementById('ed_guild_count');
|
|
||||||
if (guildCount)
|
|
||||||
guildCount.remove();
|
|
||||||
sub.unsubscribe('CONNECTION_OPEN', gg.getGuilds);
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,220 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
|
|
||||||
let getChannel, g_dc, g_cat, ha, disp, chanM, fm, reb, sv, cs, csp, ghp, gs, gsr, pf, sw = {}, g = {}, ai = {};
|
|
||||||
|
|
||||||
// copied from Discord's minified JS
|
|
||||||
function N(e,o,l,n){let r;r||(r="function"==typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103);const t=e&&e.defaultProps,f=arguments.length-3;if(o||0===f||(o={children:void 0}),o&&t)for(const e in t)void 0===o[e]&&(o[e]=t[e]);else o||(o=t||{});if(1===f)o.children=n;else if(f>1){const e=new Array(f);for(let o=0;o<f;o++)e[o]=arguments[o+3];o.children=e}return{$$typeof:r,type:e,key:void 0===l?null:""+l,ref:null,props:o,_owner:null}}
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'Hidden Channels',
|
|
||||||
description: 'Shows hidden channels and lets you view server permissions.',
|
|
||||||
color: 'magenta',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
disp = window.EDApi.findModule("dispatch");
|
|
||||||
getChannel = window.EDApi.findModule('getChannel').getChannel;
|
|
||||||
sw = window.EDApi.findModule('switchItem');
|
|
||||||
g = window.EDApi.findModule(m => m.group && m.item);
|
|
||||||
ai = window.EDApi.findModule('actionIcon');
|
|
||||||
|
|
||||||
const getUser = window.EDApi.findModule('getCurrentUser').getCurrentUser;
|
|
||||||
const getAllChannels = window.EDApi.findModule('getChannels').getChannels;
|
|
||||||
const can = window.EDApi.findModule('computePermissions').can;
|
|
||||||
|
|
||||||
g_dc = window.EDApi.findModule('getDefaultChannel');
|
|
||||||
window.EDApi.monkeyPatch(g_dc, 'getChannels', b => {
|
|
||||||
const og = b.callOriginalMethod(b.methodArguments);
|
|
||||||
if (!b.methodArguments[0]) return og;
|
|
||||||
const hidden = [], allChans = getAllChannels();
|
|
||||||
for (const i in allChans) {
|
|
||||||
if (allChans[i].guild_id === b.methodArguments[0]) {
|
|
||||||
if (allChans[i].type !== 4 && !can(1024, getUser(), getChannel(allChans[i].id))) {
|
|
||||||
hidden.push(allChans[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
og.HIDDEN = hidden;
|
|
||||||
return og;
|
|
||||||
});
|
|
||||||
chanM = window.EDApi.findModule(m => m.prototype && m.prototype.isManaged);
|
|
||||||
chanM.prototype.isHidden = function() {
|
|
||||||
return [0, 4, 5].includes(this.type) && !can(1024, getUser(), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_cat = window.EDApi.findModule(m => m.getCategories && !m.EMOJI_NAME_RE);
|
|
||||||
window.EDApi.monkeyPatch(g_cat, 'getCategories', b => {
|
|
||||||
const og = b.callOriginalMethod(b.methodArguments);
|
|
||||||
const chs = g_dc.getChannels(b.methodArguments[0]);
|
|
||||||
chs.HIDDEN.forEach(c => {
|
|
||||||
const result = og[c.parent_id || "null"].filter(item => item.channel.id === c.id);
|
|
||||||
if (result.length) return; // already added
|
|
||||||
og[c.parent_id || "null"].push({channel: c, index: 0})
|
|
||||||
});
|
|
||||||
return og;
|
|
||||||
});
|
|
||||||
|
|
||||||
ha = window.EDApi.findModule('hasUnread').__proto__;
|
|
||||||
window.EDApi.monkeyPatch(ha, 'hasUnread', function(b) {
|
|
||||||
if (getChannel(b.methodArguments[0]) && getChannel(b.methodArguments[0]).isHidden())
|
|
||||||
return false; // don't show hidden channels as unread.
|
|
||||||
return b.callOriginalMethod(b.methodArguments);
|
|
||||||
});
|
|
||||||
window.EDApi.monkeyPatch(ha, 'hasUnreadPins', function(b) {
|
|
||||||
if (getChannel(b.methodArguments[0]) && getChannel(b.methodArguments[0]).isHidden())
|
|
||||||
return false; // don't show icon on hidden channel pins.
|
|
||||||
return b.callOriginalMethod(b.methodArguments);
|
|
||||||
});
|
|
||||||
|
|
||||||
disp.subscribe("CHANNEL_SELECT", module.exports.dispatchSubscription);
|
|
||||||
|
|
||||||
fm = window.EDApi.findModule("fetchMessages");
|
|
||||||
window.EDApi.monkeyPatch(fm, "fetchMessages", function(b) {
|
|
||||||
if (getChannel(b.methodArguments[0]) && getChannel(b.methodArguments[0]).isHidden()) return;
|
|
||||||
return b.callOriginalMethod(b.methodArguments);
|
|
||||||
});
|
|
||||||
|
|
||||||
const clk = window.EDApi.findModuleByDisplayName("Clickable")
|
|
||||||
//const icon = window.EDApi.findModuleByDisplayName("Icon");
|
|
||||||
|
|
||||||
reb = window.EDApi.findModule(m => m.default && m.default.prototype && m.default.prototype.renderEditButton).default.prototype;
|
|
||||||
/*window.EDApi.monkeyPatch(reb, "renderEditButton", function(b) {
|
|
||||||
return N(clk, {
|
|
||||||
className: ai.iconItem,
|
|
||||||
onClick: function() {
|
|
||||||
module.exports._editingGuild = null;
|
|
||||||
module.exports._editingChannel = b.thisObject.props.channel.id;
|
|
||||||
return b.thisObject.handleEditClick.apply(b.thisObject, arguments);
|
|
||||||
},
|
|
||||||
onMouseEnter: b.thisObject.props.onMouseEnter,
|
|
||||||
onMouseLeave: b.thisObject.props.onMouseLeave
|
|
||||||
}, void 0, N(icon, {
|
|
||||||
name: "Gear",
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
className: ai.actionIcon
|
|
||||||
}));
|
|
||||||
});*/
|
|
||||||
|
|
||||||
sv = window.EDApi.findModuleByDisplayName("SettingsView").prototype;
|
|
||||||
window.EDApi.monkeyPatch(sv, 'getPredicateSections', {before: b => {
|
|
||||||
const permSect = b.thisObject.props.sections.find(item => item.section === 'PERMISSIONS');
|
|
||||||
if (permSect) permSect.predicate = () => true;
|
|
||||||
}, silent: true});
|
|
||||||
|
|
||||||
cs = window.EDApi.findModuleByDisplayName("FluxContainer(ChannelSettings)").prototype;
|
|
||||||
window.EDApi.monkeyPatch(cs, 'render', b => {
|
|
||||||
const egg = b.callOriginalMethod(b.methodArguments);
|
|
||||||
egg.props.canManageRoles = true;
|
|
||||||
return egg;
|
|
||||||
});
|
|
||||||
|
|
||||||
csp = window.EDApi.findModuleByDisplayName("FluxContainer(ChannelSettingsPermissions)").prototype;
|
|
||||||
window.EDApi.monkeyPatch(csp, 'render', b => {
|
|
||||||
const egg = b.callOriginalMethod(b.methodArguments);
|
|
||||||
const chan = getChannel(egg.props.channel.id);
|
|
||||||
if (!chan || !chan.isHidden()) return egg;
|
|
||||||
egg.props.canSyncChannel = false;
|
|
||||||
egg.props.locked = true;
|
|
||||||
setTimeout(() => {
|
|
||||||
document.querySelectorAll('.'+g.group).forEach(elem => elem.style = "opacity: 0.5; pointer-events: none;");
|
|
||||||
});
|
|
||||||
return egg;
|
|
||||||
});
|
|
||||||
|
|
||||||
ghp = window.EDApi.findModuleByDisplayName("FluxContainer(GuildHeaderPopout)").prototype;
|
|
||||||
window.EDApi.monkeyPatch(ghp, 'render', b => {
|
|
||||||
const egg = b.callOriginalMethod(b.methodArguments);
|
|
||||||
egg.props.canAccessSettings = true;
|
|
||||||
return egg;
|
|
||||||
});
|
|
||||||
|
|
||||||
gs = window.EDApi.findModuleByDisplayName("FluxContainer(GuildSettings)").prototype;
|
|
||||||
window.EDApi.monkeyPatch(gs, 'render', b => {
|
|
||||||
const egg = b.callOriginalMethod(b.methodArguments);
|
|
||||||
module.exports._editingChannel = null;
|
|
||||||
module.exports._editingGuild = egg.props.guild.id;
|
|
||||||
egg.props.canManageRoles = true;
|
|
||||||
return egg;
|
|
||||||
});
|
|
||||||
|
|
||||||
const cancan = window.EDApi.findModuleByProps('can', 'canUser').can;
|
|
||||||
gsr = window.EDApi.findModuleByDisplayName("FluxContainer(GuildSettingsRoles)").prototype;
|
|
||||||
window.EDApi.monkeyPatch(gsr, 'render', b => {
|
|
||||||
const egg = b.callOriginalMethod(b.methodArguments);
|
|
||||||
const hasPerm = cancan(268435456, { guildId: egg.props.guild.id });
|
|
||||||
if (hasPerm) return;
|
|
||||||
setTimeout(() => {
|
|
||||||
document.querySelectorAll('.'+sw.switchItem).forEach(elem => elem.classList.add(sw.disabled));
|
|
||||||
});
|
|
||||||
return egg;
|
|
||||||
});
|
|
||||||
|
|
||||||
const getGuild = window.EDApi.findModule('getGuild').getGuild;
|
|
||||||
pf = window.EDApi.findModuleByDisplayName("PermissionsForm").prototype;
|
|
||||||
window.EDApi.monkeyPatch(pf, 'render', b => {
|
|
||||||
const egg = b.callOriginalMethod(b.methodArguments);
|
|
||||||
const guild = module.exports._editingGuild ? getGuild(module.exports._editingGuild) : null;
|
|
||||||
const channel = module.exports._editingChannel ? getChannel(module.exports._editingChannel) : null;
|
|
||||||
if (!guild && !channel) return egg;
|
|
||||||
const hasPerm = cancan(268435456, guild ? { guildId: guild.id } : { channelId: channel.id });
|
|
||||||
if (hasPerm) return;
|
|
||||||
|
|
||||||
if (!egg.props.children || !egg.props.children[1]) return egg;
|
|
||||||
egg.props.children[1].forEach(item => {item.disabled = true; item.props.disabled = true;});
|
|
||||||
return egg;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
unload: function() {
|
|
||||||
g_dc.getChannels.unpatch();
|
|
||||||
g_cat.getCategories.unpatch();
|
|
||||||
ha.hasUnread.unpatch();
|
|
||||||
ha.hasUnreadPins.unpatch();
|
|
||||||
fm.fetchMessages.unpatch();
|
|
||||||
reb.renderEditButton.unpatch();
|
|
||||||
|
|
||||||
for (const mod of [sv, cs, csp, ghp, gs, gsr, pf])
|
|
||||||
if (mod && mod.render && mod.render.unpatch) mod.render.unpatch();
|
|
||||||
|
|
||||||
disp.unsubscribe("CHANNEL_SELECT", module.exports.dispatchSubscription);
|
|
||||||
},
|
|
||||||
dispatchSubscription: function (data) {
|
|
||||||
if (data.type !== "CHANNEL_SELECT") return;
|
|
||||||
|
|
||||||
if (getChannel(data.channelId) && getChannel(data.channelId).isHidden()) {
|
|
||||||
setTimeout(module.exports.attachHiddenChanNotice);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
attachHiddenChanNotice: function () {
|
|
||||||
const messagesWrapper = document.querySelector(`.${window.EDApi.findModule("messages").messagesWrapper}`);
|
|
||||||
if (!messagesWrapper) return;
|
|
||||||
|
|
||||||
messagesWrapper.firstChild.style.display = "none"; // Remove messages shit.
|
|
||||||
messagesWrapper.parentElement.children[1].style.display = "none"; // Remove message box.
|
|
||||||
messagesWrapper.parentElement.parentElement.children[1].style.display = "none"; // Remove user list.
|
|
||||||
|
|
||||||
const toolbar = document.querySelector("."+window.EDApi.findModule(m => {
|
|
||||||
if (m instanceof Window) return;
|
|
||||||
if (m.toolbar && m.selected) return m;
|
|
||||||
}).toolbar);
|
|
||||||
|
|
||||||
toolbar.style.display = "none";
|
|
||||||
|
|
||||||
const hiddenChannelNotif = document.createElement("div");
|
|
||||||
|
|
||||||
// Class name modules
|
|
||||||
const txt = window.EDApi.findModule("h5");
|
|
||||||
const flx = window.EDApi.findModule("flex");
|
|
||||||
|
|
||||||
hiddenChannelNotif.className = flx.flexCenter;
|
|
||||||
hiddenChannelNotif.style.width = "100%";
|
|
||||||
|
|
||||||
hiddenChannelNotif.innerHTML = `
|
|
||||||
<div class="${flx.flex} ${flx.directionColumn} ${flx.alignCenter}">
|
|
||||||
<h2 class="${txt.h2} ${txt.defaultColor}">This is a hidden channel.</h2>
|
|
||||||
<h5 class="${txt.h5} ${txt.defaultColor}">You cannot see the contents of this channel. However, you may see its name and topic.</h5>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
messagesWrapper.appendChild(hiddenChannelNotif);
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,39 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'Quick Save',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
description: 'Use Ctrl+S or Cmd+S to save server, channel, or account settings.',
|
|
||||||
color: 'salmon',
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
const hcModules = window.EDApi.findAllModules('hasChanges');
|
|
||||||
this._listener = function(e) {
|
|
||||||
if ((window.navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey) && e.keyCode == 83) {
|
|
||||||
e.preventDefault();
|
|
||||||
const types = ['GUILD', 'CHANNEL', 'ACCOUNT', 'GUILD ROLES', 'CHANNEL OVERWRITES'];
|
|
||||||
let hasChanges = false;
|
|
||||||
for (const i in types) {
|
|
||||||
if (hcModules[i] && hcModules[i].hasChanges()) {
|
|
||||||
hasChanges = true;
|
|
||||||
//module.exports.log(`saving ${types[i]} settings`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasChanges) {
|
|
||||||
//module.exports.log('No setting changes detected. Aborting.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const saveButton = document.querySelector('[class*="lookFilled-"][class*="colorGreen-"]');
|
|
||||||
if (saveButton)
|
|
||||||
try { saveButton.click(); } catch(err) { module.exports.error(err); }
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.addEventListener("keydown", this._listener, false);
|
|
||||||
},
|
|
||||||
unload: function() {
|
|
||||||
document.removeEventListener("keydown", this._listener);
|
|
||||||
delete this._listener;
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,22 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'Shut up, Clyde',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
description: "Silences Clyde saying stupid shit about Nitro, for users that don't have it.",
|
|
||||||
color: '#7289da',
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
const gg = window.EDApi.findModule(m => m.getChannelId && m.getGuildId && !m.getPings), bs = window.EDApi.findModule('Messages').Messages;
|
|
||||||
|
|
||||||
window.EDApi.monkeyPatch(window.EDApi.findModule('sendBotMessage'), 'sendBotMessage', function (b) {
|
|
||||||
if (gg.getGuildId() !== null) return; // don't send Clyde messages when looking at a server
|
|
||||||
const message = b.methodArguments[1];
|
|
||||||
if (message == bs.INVALID_ANIMATED_EMOJI_BODY_UPGRADE || message == bs.INVALID_ANIMATED_EMOJI_BODY || message == bs.INVALID_EXTERNAL_EMOJI_BODY_UPGRADE || message == bs.INVALID_EXTERNAL_EMOJI_BODY) return;
|
|
||||||
return b.callOriginalMethod(b.methodArguments);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
unload: function() {
|
|
||||||
window.EDApi.findModule('sendBotMessage').sendBotMessage.unpatch();
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,16 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'Silent Typing',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
description: `Never appear as typing in any channel.`,
|
|
||||||
color: 'grey',
|
|
||||||
disabledByDefault: true,
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
window.EDApi.monkeyPatch(window.EDApi.findModule('startTyping'), 'startTyping', () => {});
|
|
||||||
},
|
|
||||||
unload: function() {
|
|
||||||
window.EDApi.findModule('startTyping').startTyping.unpatch();
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,57 +0,0 @@
|
||||||
@import url(https://enhanceddiscord.com/theme.css);
|
|
||||||
|
|
||||||
/* theme settings - uncomment (by removing the /*) and modify these lines in order to change things */
|
|
||||||
:root {
|
|
||||||
/* --bg: url(https://i.imgur.com/ybRUHPc.jpg); /* background for the entire window. Almost everything is transparent to this image. */
|
|
||||||
/* --bg-overlay: rgba(0, 0, 0, 0.8); /* overlay for the background. Generally, this should darken the picture to make text more readable. */
|
|
||||||
/* --accent-color: #900; /* color of buttons, misc. text, etc. */
|
|
||||||
/* --mention-color: #f00; /* color of mention text */
|
|
||||||
/* --mention-bg: rgba(255, 0, 0, 0.15); /* mention background color */
|
|
||||||
/* --mention-bgh: rgba(255, 0, 0, 0.4); /* mention backgroung while hovering over it */
|
|
||||||
/* --link-color: #faa61a; /* color of all links */
|
|
||||||
/* --link-color-hover: #fad61a; /* color of all links while hovering over them */
|
|
||||||
/* --tag-color: #fff; /* text color of tags (bot tags and custom) */
|
|
||||||
/* --tag-bg: rgba(255, 0, 0, 0.3); /* background of tags (bot tags and custom) */
|
|
||||||
/* --popup-background: #222; /* background of modals, confirmation messages etc. */
|
|
||||||
/* --popup-highlight: #333; /* color of headers and footers of "popouts" (linked to above) */
|
|
||||||
/* --context-menu-bg: #333; /* color of context (right-click) menus. */
|
|
||||||
/* --unread-color: #f00; /* color of unread/selected server indicators. */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* nitrofag badge */
|
|
||||||
.profileBadgePremium-3kZ9Qj, .topSectionNormal-2-vo2m .profileBadgePremium-3kZ9Qj,
|
|
||||||
.profileBadgePremium-3kZ9Qj, .topSectionPlaying-1J5E4n .profileBadgePremium-3kZ9Qj {
|
|
||||||
background-image: url(https://discordapp.com/assets/9c252d28ca4980d65054a0258052983b.svg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* unread indicators */
|
|
||||||
.theme-dark .unread-2OHH1w:not(.selected-nT-gM3):before {
|
|
||||||
background: #282828;
|
|
||||||
opacity: 0.5;
|
|
||||||
height: 50px;
|
|
||||||
width: 50px;
|
|
||||||
left: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
top: 0px;
|
|
||||||
margin-top: 0;
|
|
||||||
border-radius: 50%;
|
|
||||||
border-top-right-radius: 5px;
|
|
||||||
border-bottom-left-radius: 5px;
|
|
||||||
/* box-shadow: 16px -16px 10px -14px #f00; */
|
|
||||||
/* background: -webkit-radial-gradient(transparent 15px, #f00 25px, transparent 40px); */
|
|
||||||
box-shadow: inset 0 0 12px 2px var(--unread-color);
|
|
||||||
}
|
|
||||||
.theme-dark .selected-nT-gM3:before {
|
|
||||||
background: var(--unread-color);
|
|
||||||
}
|
|
||||||
.theme-dark .unread-2OHH1w:hover::before {
|
|
||||||
border-radius: 15px;
|
|
||||||
border-top-right-radius: 5px;
|
|
||||||
border-bottom-left-radius: 5px;
|
|
||||||
transition: border-radius 150ms;
|
|
||||||
}
|
|
||||||
/* uncomment the following lines to hide gif picker */
|
|
||||||
/*button[aria-label="Open GIF picker"] {
|
|
||||||
display: none;
|
|
||||||
}*/
|
|
|
@ -1,57 +0,0 @@
|
||||||
@import url(https://enhanceddiscord.com/theme.css);
|
|
||||||
|
|
||||||
/* theme settings - uncomment (by removing the /*) and modify these lines in order to change things */
|
|
||||||
:root {
|
|
||||||
/* --bg: url(https://i.imgur.com/ybRUHPc.jpg); /* background for the entire window. Almost everything is transparent to this image. */
|
|
||||||
/* --bg-overlay: rgba(0, 0, 0, 0.8); /* overlay for the background. Generally, this should darken the picture to make text more readable. */
|
|
||||||
/* --accent-color: #900; /* color of buttons, misc. text, etc. */
|
|
||||||
/* --mention-color: #f00; /* color of mention text */
|
|
||||||
/* --mention-bg: rgba(255, 0, 0, 0.15); /* mention background color */
|
|
||||||
/* --mention-bgh: rgba(255, 0, 0, 0.4); /* mention backgroung while hovering over it */
|
|
||||||
/* --link-color: #faa61a; /* color of all links */
|
|
||||||
/* --link-color-hover: #fad61a; /* color of all links while hovering over them */
|
|
||||||
/* --tag-color: #fff; /* text color of tags (bot tags and custom) */
|
|
||||||
/* --tag-bg: rgba(255, 0, 0, 0.3); /* background of tags (bot tags and custom) */
|
|
||||||
/* --popup-background: #222; /* background of modals, confirmation messages etc. */
|
|
||||||
/* --popup-highlight: #333; /* color of headers and footers of "popouts" (linked to above) */
|
|
||||||
/* --context-menu-bg: #333; /* color of context (right-click) menus. */
|
|
||||||
/* --unread-color: #f00; /* color of unread/selected server indicators. */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* nitrofag badge */
|
|
||||||
.profileBadgePremium-3kZ9Qj, .topSectionNormal-2-vo2m .profileBadgePremium-3kZ9Qj,
|
|
||||||
.profileBadgePremium-3kZ9Qj, .topSectionPlaying-1J5E4n .profileBadgePremium-3kZ9Qj {
|
|
||||||
background-image: url(https://discordapp.com/assets/9c252d28ca4980d65054a0258052983b.svg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* unread indicators */
|
|
||||||
.theme-dark .unread-2OHH1w:not(.selected-nT-gM3):before {
|
|
||||||
background: transparent;
|
|
||||||
opacity: 0.5;
|
|
||||||
height: 50px;
|
|
||||||
width: 50px;
|
|
||||||
left: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
top: 0px;
|
|
||||||
margin-top: 0;
|
|
||||||
border-radius: 50%;
|
|
||||||
border-top-right-radius: 5px;
|
|
||||||
border-bottom-left-radius: 5px;
|
|
||||||
/* box-shadow: 16px -16px 10px -14px #f00; */
|
|
||||||
/* background: -webkit-radial-gradient(transparent 15px, #f00 25px, transparent 40px); */
|
|
||||||
box-shadow: inset 0 0 12px 2px var(--unread-color);
|
|
||||||
}
|
|
||||||
.theme-dark .selected-nT-gM3:before {
|
|
||||||
background: var(--unread-color);
|
|
||||||
}
|
|
||||||
.theme-dark .unread-2OHH1w:hover::before {
|
|
||||||
border-radius: 15px;
|
|
||||||
border-top-right-radius: 5px;
|
|
||||||
border-bottom-left-radius: 5px;
|
|
||||||
transition: border-radius 150ms;
|
|
||||||
}
|
|
||||||
/* uncomment the following lines to hide gif picker */
|
|
||||||
/*button[aria-label="Open GIF picker"] {
|
|
||||||
display: none;
|
|
||||||
}*/
|
|
|
@ -1,78 +0,0 @@
|
||||||
const Plugin = require('../plugin');
|
|
||||||
|
|
||||||
let gg = {}, gc = {}, gu = {}, cp = {}, lg = {}, gsc = {};
|
|
||||||
|
|
||||||
module.exports = new Plugin({
|
|
||||||
name: 'TagAll',
|
|
||||||
author: 'Joe 🎸#7070',
|
|
||||||
description: `Allows you to mention roles and channels you can't normally.`,
|
|
||||||
color: 'yellow',
|
|
||||||
|
|
||||||
load: async function() {
|
|
||||||
await this.sleep(1000); // wait for hidden channels to load
|
|
||||||
|
|
||||||
gg = window.EDApi.findModule('getGuild');
|
|
||||||
gc = window.EDApi.findModule('getChannels');
|
|
||||||
gu = window.EDApi.findModule('getCurrentUser');
|
|
||||||
cp = window.EDApi.findModule('computePermissions');
|
|
||||||
lg = window.EDApi.findModule('getLastSelectedGuildId');
|
|
||||||
gsc = window.EDApi.findModule('getChannel');
|
|
||||||
|
|
||||||
this.lis = function(e) {
|
|
||||||
let text = e.target.value;
|
|
||||||
|
|
||||||
const guildID = lg.getLastSelectedGuildId();
|
|
||||||
const g = gg.getGuild(guildID);
|
|
||||||
|
|
||||||
if (!guildID || !g || !text) return;
|
|
||||||
|
|
||||||
// mention unmentionable roles
|
|
||||||
const unMen = [];
|
|
||||||
for (const id in g.roles)
|
|
||||||
if (!g.roles[id].mentionable && !g.roles[id].managed) // ignore bot roles
|
|
||||||
unMen.push(g.roles[id]);
|
|
||||||
|
|
||||||
const roles = unMen.map(r => r.name.toLowerCase().replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&"));
|
|
||||||
for (const i in roles) {
|
|
||||||
if (!roles[i]) continue; // empty role names
|
|
||||||
try {
|
|
||||||
text = text.replace( new RegExp('@'+roles[i]+'([^#])', 'gi'), `<@&${unMen[i].id}>$1`);
|
|
||||||
} catch(err) {/*do nothing*/}
|
|
||||||
}
|
|
||||||
|
|
||||||
const hiddenChans = [];
|
|
||||||
if (window.ED._hiddenChans) { // work with "hidden channels" plugin
|
|
||||||
for (const i in window.ED._hiddenChans) {
|
|
||||||
const c = gsc.getChannel(window.ED._hiddenChans[i]);
|
|
||||||
if (c && c.guild_id === guildID) {
|
|
||||||
hiddenChans.push(gsc.getChannel(window.ED._hiddenChans[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const globalChans = gc.getChannels();
|
|
||||||
const me = gu.getCurrentUser();
|
|
||||||
|
|
||||||
const hiddenChans = [];
|
|
||||||
for (const id in globalChans) {
|
|
||||||
if (globalChans[id].guild_id == guildID && !(cp.computePermissions(me, globalChans[id]) & 1024))
|
|
||||||
hiddenChans.push(globalChans[id]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// mention channels you can't see
|
|
||||||
const chans = hiddenChans.map(c => c.name ? c.name.toLowerCase().replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&") : '');
|
|
||||||
for (const i in chans) {
|
|
||||||
if (!chans[i]) continue;
|
|
||||||
text = text.replace( new RegExp('#'+chans[i]+'(\\s)', 'gi'), `<#${hiddenChans[i].id}>$1`);
|
|
||||||
}
|
|
||||||
if (e.target.value == text) return;
|
|
||||||
|
|
||||||
e.target.value = text;
|
|
||||||
};
|
|
||||||
document.addEventListener("input", this.lis);
|
|
||||||
},
|
|
||||||
|
|
||||||
unload: function() {
|
|
||||||
document.removeEventListener("input", this.lis);
|
|
||||||
this.lis = null;
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,353 +0,0 @@
|
||||||
env:
|
|
||||||
# if not set, it supposedly check's if a alacritty entry exists and uses xterm-256color otherwise
|
|
||||||
# TERM: alacritty
|
|
||||||
TERM: xterm-256color
|
|
||||||
|
|
||||||
window:
|
|
||||||
#dimensions:
|
|
||||||
# columns: 0
|
|
||||||
# lines: 0
|
|
||||||
#position:
|
|
||||||
# x: 0
|
|
||||||
# y: 0
|
|
||||||
|
|
||||||
padding:
|
|
||||||
x: 20
|
|
||||||
y: 20
|
|
||||||
|
|
||||||
#Spread additional padding evenly around the terminal content.
|
|
||||||
dynamic_padding: true
|
|
||||||
|
|
||||||
#title: Alacritty
|
|
||||||
#class:
|
|
||||||
#instance: Alacritty
|
|
||||||
#general: Alacritty
|
|
||||||
|
|
||||||
gtk_theme_variant: None
|
|
||||||
|
|
||||||
scrolling:
|
|
||||||
history: 10000
|
|
||||||
multiplier: 3
|
|
||||||
|
|
||||||
#selection:
|
|
||||||
#semantic_escape_chars: ",│`|:\"' ()[]{}<>\t"
|
|
||||||
# When set to `true`, selected text will be copied to the primary clipboard.
|
|
||||||
#save_to_clipboard: false
|
|
||||||
|
|
||||||
# Allow terminal applications to change Alacritty's window title.
|
|
||||||
dynamic_title: true
|
|
||||||
|
|
||||||
cursor:
|
|
||||||
style: Block # ▇ Block, _ Underline, | Beam
|
|
||||||
unfocused_hollow: true
|
|
||||||
# Live config reload (changes require restart)
|
|
||||||
live_config_reload: true
|
|
||||||
shell:
|
|
||||||
program: /bin/fish
|
|
||||||
#args:
|
|
||||||
#- --login
|
|
||||||
|
|
||||||
mouse:
|
|
||||||
double_click: { threshold: 300 }
|
|
||||||
triple_click: { threshold: 300 }
|
|
||||||
|
|
||||||
hide_when_typing: true
|
|
||||||
|
|
||||||
url:
|
|
||||||
launcher:
|
|
||||||
program: xdg-open
|
|
||||||
# args: []
|
|
||||||
# These are the modifiers that need to be held down for opening URLs when clicking
|
|
||||||
# on them. The available modifiers are documented in the key binding section.
|
|
||||||
#modifiers: None
|
|
||||||
|
|
||||||
|
|
||||||
# Mouse bindings --------------------------------------------- {{{
|
|
||||||
# - `mouse`:
|
|
||||||
#
|
|
||||||
# - Middle
|
|
||||||
# - Left
|
|
||||||
# - Right
|
|
||||||
# - Numeric identifier such as `5`
|
|
||||||
#
|
|
||||||
# - `action` (see key bindings)
|
|
||||||
#
|
|
||||||
# And optionally:
|
|
||||||
#
|
|
||||||
# - `mods` (see key bindings)
|
|
||||||
#mouse_bindings:
|
|
||||||
# - { mouse: Middle, action: PasteSelection }
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# Key bindings -------------------------------------------- {{{
|
|
||||||
#
|
|
||||||
# Key bindings are specified as a list of objects. For example, this is the
|
|
||||||
# default paste binding:
|
|
||||||
#
|
|
||||||
# `- { key: V, mods: Control|Shift, action: Paste }`
|
|
||||||
#
|
|
||||||
# Each key binding will specify a:
|
|
||||||
#
|
|
||||||
# - `key`: Identifier of the key pressed
|
|
||||||
#
|
|
||||||
# - A-Z
|
|
||||||
# - F1-F24
|
|
||||||
# - Key0-Key9
|
|
||||||
#
|
|
||||||
# A full list with available key codes can be found here:
|
|
||||||
# https://docs.rs/glutin/*/glutin/event/enum.VirtualKeyCode.html#variants
|
|
||||||
#
|
|
||||||
# Instead of using the name of the keys, the `key` field also supports using
|
|
||||||
# the scancode of the desired key. Scancodes have to be specified as a
|
|
||||||
# decimal number. This command will allow you to display the hex scancodes
|
|
||||||
# for certain keys:
|
|
||||||
#
|
|
||||||
# `showkey --scancodes`.
|
|
||||||
#
|
|
||||||
# Then exactly one of:
|
|
||||||
#
|
|
||||||
# - `chars`: Send a byte sequence to the running application
|
|
||||||
#
|
|
||||||
# The `chars` field writes the specified string to the terminal. This makes
|
|
||||||
# it possible to pass escape sequences. To find escape codes for bindings
|
|
||||||
# like `PageUp` (`"\x1b[5~"`), you can run the command `showkey -a` outside
|
|
||||||
# of tmux. Note that applications use terminfo to map escape sequences back
|
|
||||||
# to keys. It is therefore required to update the terminfo when changing an
|
|
||||||
# escape sequence.
|
|
||||||
#
|
|
||||||
# - `action`: Execute a predefined action
|
|
||||||
#
|
|
||||||
# - Copy
|
|
||||||
# - Paste
|
|
||||||
# - PasteSelection
|
|
||||||
# - IncreaseFontSize
|
|
||||||
# - DecreaseFontSize
|
|
||||||
# - ResetFontSize
|
|
||||||
# - ScrollPageUp
|
|
||||||
# - ScrollPageDown
|
|
||||||
# - ScrollLineUp
|
|
||||||
# - ScrollLineDown
|
|
||||||
# - ScrollToTop
|
|
||||||
# - ScrollToBottom
|
|
||||||
# - ClearHistory
|
|
||||||
# - Hide
|
|
||||||
# - Minimize
|
|
||||||
# - Quit
|
|
||||||
# - ToggleFullscreen
|
|
||||||
# - SpawnNewInstance
|
|
||||||
# - ClearLogNotice
|
|
||||||
# - ReceiveChar
|
|
||||||
# - None
|
|
||||||
#
|
|
||||||
# (macOS only):
|
|
||||||
# - ToggleSimpleFullscreen: Enters fullscreen without occupying another space
|
|
||||||
#
|
|
||||||
# - `command`: Fork and execute a specified command plus arguments
|
|
||||||
#
|
|
||||||
# The `command` field must be a map containing a `program` string and an
|
|
||||||
# `args` array of command line parameter strings. For example:
|
|
||||||
# `{ program: "alacritty", args: ["-e", "vttest"] }`
|
|
||||||
#
|
|
||||||
# And optionally:
|
|
||||||
# - `mods`: Key modifiers to filter binding actions
|
|
||||||
# - Command
|
|
||||||
# - Control
|
|
||||||
# - Option
|
|
||||||
# - Super
|
|
||||||
# - Shift
|
|
||||||
# - Alt
|
|
||||||
#
|
|
||||||
# Multiple `mods` can be combined using `|` like this:
|
|
||||||
# `mods: Control|Shift`.
|
|
||||||
# Whitespace and capitalization are relevant and must match the example.
|
|
||||||
#
|
|
||||||
# - `mode`: Indicate a binding for only specific terminal reported modes
|
|
||||||
#
|
|
||||||
# This is mainly used to send applications the correct escape sequences
|
|
||||||
# when in different modes.
|
|
||||||
#
|
|
||||||
# - AppCursor
|
|
||||||
# - AppKeypad
|
|
||||||
# - Alt
|
|
||||||
#
|
|
||||||
# A `~` operator can be used before a mode to apply the binding whenever
|
|
||||||
# the mode is *not* active, e.g. `~Alt`.
|
|
||||||
#
|
|
||||||
# Bindings are always filled by default, but will be replaced when a new
|
|
||||||
# binding with the same triggers is defined. To unset a default binding, it can
|
|
||||||
# be mapped to the `ReceiveChar` action. Alternatively, you can use `None` for
|
|
||||||
# a no-op if you do not wish to receive input characters for that binding.
|
|
||||||
#
|
|
||||||
# If the same trigger is assigned to multiple actions, all of them are executed
|
|
||||||
# at once.
|
|
||||||
#key_bindings:
|
|
||||||
# (Windows, Linux, and BSD only)
|
|
||||||
#- { key: V, mods: Control|Shift, action: Paste }
|
|
||||||
#- { key: C, mods: Control|Shift, action: Copy }
|
|
||||||
#- { key: Insert, mods: Shift, action: PasteSelection }
|
|
||||||
#- { key: Key0, mods: Control, action: ResetFontSize }
|
|
||||||
#- { key: Equals, mods: Control, action: IncreaseFontSize }
|
|
||||||
#- { key: Add, mods: Control, action: IncreaseFontSize }
|
|
||||||
#- { key: Subtract, mods: Control, action: DecreaseFontSize }
|
|
||||||
#- { key: Minus, mods: Control, action: DecreaseFontSize }
|
|
||||||
|
|
||||||
# (Windows only)
|
|
||||||
#- { key: Return, mods: Alt, action: ToggleFullscreen }
|
|
||||||
|
|
||||||
#- { key: Paste, action: Paste }
|
|
||||||
#- { key: Copy, action: Copy }
|
|
||||||
#- { key: L, mods: Control, action: ClearLogNotice }
|
|
||||||
#- { key: L, mods: Control, chars: "\x0c" }
|
|
||||||
#- { key: PageUp, mods: Shift, action: ScrollPageUp, mode: ~Alt }
|
|
||||||
#- { key: PageDown, mods: Shift, action: ScrollPageDown, mode: ~Alt }
|
|
||||||
#- { key: Home, mods: Shift, action: ScrollToTop, mode: ~Alt }
|
|
||||||
#- { key: End, mods: Shift, action: ScrollToBottom, mode: ~Alt }
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
#debug:
|
|
||||||
# Display the time it takes to redraw each frame.
|
|
||||||
#render_timer: false
|
|
||||||
|
|
||||||
# Keep the log file after quitting Alacritty.
|
|
||||||
#persistent_logging: false
|
|
||||||
|
|
||||||
# Log level
|
|
||||||
#
|
|
||||||
# Values for `log_level`:
|
|
||||||
# - None
|
|
||||||
# - Error
|
|
||||||
# - Warn
|
|
||||||
# - Info
|
|
||||||
# - Debug
|
|
||||||
# - Trace
|
|
||||||
#log_level: Warn
|
|
||||||
|
|
||||||
# Print all received window events.
|
|
||||||
#print_events: false
|
|
||||||
|
|
||||||
# schemes --------------------------------------------------------- {{{
|
|
||||||
|
|
||||||
schemes:
|
|
||||||
blueish: &blueish
|
|
||||||
colors:
|
|
||||||
# Default colors
|
|
||||||
primary:
|
|
||||||
background: '0x3f5163'
|
|
||||||
foreground: '0xe2efe6'
|
|
||||||
|
|
||||||
# Normal colors
|
|
||||||
normal:
|
|
||||||
black: '0x111111'
|
|
||||||
red: '0xa54242'
|
|
||||||
green: '0xa9b254'
|
|
||||||
yellow: '0xde935f'
|
|
||||||
blue: '0x1bcdee'
|
|
||||||
magenta: '0xbd88ce'
|
|
||||||
cyan: '0x5bc5b7'
|
|
||||||
white: '0xbceff7'
|
|
||||||
|
|
||||||
# Bright colors
|
|
||||||
bright:
|
|
||||||
black: '0xc5d2e6'
|
|
||||||
red: '0xff8484'
|
|
||||||
green: '0xebf39c'
|
|
||||||
yellow: '0xf4c76e'
|
|
||||||
blue: '0x97cfff'
|
|
||||||
magenta: '0xc3a2cd'
|
|
||||||
cyan: '0xa5f9ee'
|
|
||||||
white: '0xe7fcff'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dracula: &dracula
|
|
||||||
primary:
|
|
||||||
background: '#282a36'
|
|
||||||
foreground: '#f8f8f2'
|
|
||||||
normal:
|
|
||||||
black: '#000000'
|
|
||||||
red: '#ff5555'
|
|
||||||
green: '#50fa7b'
|
|
||||||
yellow: '#f1fa8c'
|
|
||||||
blue: '#caa9fa'
|
|
||||||
magenta: '#ff79c6'
|
|
||||||
cyan: '#8be9fd'
|
|
||||||
white: '#bfbfbf'
|
|
||||||
bright:
|
|
||||||
black: '#575b70'
|
|
||||||
red: '#ff6e67'
|
|
||||||
green: '#5af78e'
|
|
||||||
yellow: '#f4f99d'
|
|
||||||
blue: '#caa9fa'
|
|
||||||
magenta: '#ff92d0'
|
|
||||||
cyan: '#9aedfe'
|
|
||||||
white: '#e6e6e6'
|
|
||||||
gruvbox: &gruvbox
|
|
||||||
primary:
|
|
||||||
#background: '#1d2021' # hard contrast: background = '#1d2021'
|
|
||||||
background: '#282828' # hard contrast: background = '#1d2021'
|
|
||||||
foreground: '#ebdbb2' # soft contrast: background = '#32302f'
|
|
||||||
normal:
|
|
||||||
black: '#282828'
|
|
||||||
red: '#cc241d'
|
|
||||||
green: '#98971a'
|
|
||||||
yellow: '#d79921'
|
|
||||||
blue: '#458588'
|
|
||||||
magenta: '#b16286'
|
|
||||||
cyan: '#689d6a'
|
|
||||||
white: '#a89984'
|
|
||||||
bright:
|
|
||||||
black: '#928374'
|
|
||||||
red: '#fb4934'
|
|
||||||
green: '#b8bb26'
|
|
||||||
yellow: '#fabd2f'
|
|
||||||
blue: '#83a598'
|
|
||||||
magenta: '#d3869b'
|
|
||||||
cyan: '#8ec07c'
|
|
||||||
white: '#ebdbb2'
|
|
||||||
|
|
||||||
onedark: &onedark
|
|
||||||
primary:
|
|
||||||
background: '#282c34'
|
|
||||||
foreground: '#abb2bf'
|
|
||||||
normal:
|
|
||||||
black: '#282c34' # NOTE: Use '#131613' for the `black` color if you'd like to see black text on the background.
|
|
||||||
red: '#e06c75'
|
|
||||||
green: '#98c379'
|
|
||||||
yellow: '#d19a66'
|
|
||||||
blue: '#61afef'
|
|
||||||
magenta: '#c678dd'
|
|
||||||
cyan: '#56b6c2'
|
|
||||||
white: '#abb2bf'
|
|
||||||
bright:
|
|
||||||
black: '#5c6370'
|
|
||||||
red: '#e06c75'
|
|
||||||
green: '#98c379'
|
|
||||||
yellow: '#d19a66'
|
|
||||||
blue: '#61afef'
|
|
||||||
magenta: '#c678dd'
|
|
||||||
cyan: '#56b6c2'
|
|
||||||
white: '#ffffff'
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# https://github.com/alacritty/alacritty/wiki/Color-schemes
|
|
||||||
colors: *gruvbox
|
|
||||||
#background_opacity: 0.95
|
|
||||||
background_opacity: 1.0
|
|
||||||
|
|
||||||
font:
|
|
||||||
#size: 10
|
|
||||||
size: 12
|
|
||||||
normal:
|
|
||||||
#family: JetBrainsMono Nerd Font
|
|
||||||
#family: Iosevka Term
|
|
||||||
#family: cozette
|
|
||||||
family: Terminus (TTF)
|
|
||||||
#family: cherry
|
|
||||||
#family: lucy tewi2a
|
|
||||||
#family: Scientifica
|
|
||||||
offset:
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
|
@ -1,25 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
case $1 in "-a") PROMPT="Goto:"; MODE="go" ;; "-R") PROMPT="Bring:"; MODE="bring" ;; esac
|
|
||||||
|
|
||||||
if [ -n "$2" ]; then
|
|
||||||
WINDOW="$2"
|
|
||||||
else
|
|
||||||
WINDOW=$(paste \
|
|
||||||
<(xdotool search .) \
|
|
||||||
<(xdotool search . get_desktop_for_window %@ 2> /dev/null) \
|
|
||||||
<(xdotool search . getwindowname %@) |\
|
|
||||||
awk '{FS="\t"; if($2 != -1) printf "%10d [%d] %s\n",$1,$2+1,$3}' |\
|
|
||||||
vmenu --no-refocus -p $PROMPT |\
|
|
||||||
sed 's/^ *//g' |\
|
|
||||||
cut -d ' ' -f 1)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$WINDOW" ]; then
|
|
||||||
if [ bring = $MODE ]; then
|
|
||||||
if DESK=$(xdotool get_desktop 2> /dev/null); then
|
|
||||||
xdotool set_desktop_for_window "$WINDOW" $DESK
|
|
||||||
sleep 0.005 # wait for wm to notice
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
xdotool windowmap "$WINDOW" windowactivate "$WINDOW" windowfocus "$WINDOW" windowraise "$WINDOW"
|
|
||||||
fi
|
|
|
@ -1,11 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo "Usage: $0 <name of hidden scratchpad window>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
pids=$(xdotool search --class "${1}")
|
|
||||||
for pid in $pids; do
|
|
||||||
echo "Toggle $pid"
|
|
||||||
bspc node "$pid" --flag hidden -f
|
|
||||||
done
|
|
|
@ -1,107 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Config
|
|
||||||
# ======
|
|
||||||
|
|
||||||
# Where to look for wid files:
|
|
||||||
TMPDIR="$XDG_RUNTIME_DIR/drawers.wids/"
|
|
||||||
|
|
||||||
# Find and show/hide the window if it exists
|
|
||||||
# ==========================================
|
|
||||||
|
|
||||||
NAME=$1
|
|
||||||
|
|
||||||
if [[ -e $TMPDIR$NAME ]]; then
|
|
||||||
read -r WINDOW < "$TMPDIR$NAME"
|
|
||||||
|
|
||||||
# Window exists? Show/hide it and we're done.
|
|
||||||
if xdotool getwindowname "$WINDOW" &> /dev/null; then
|
|
||||||
if xdotool search --onlyvisible . | grep -q "$WINDOW"; then
|
|
||||||
xdotool windowminimize "$WINDOW"
|
|
||||||
else
|
|
||||||
~/.config/bspwm/bspwm_scripts/bringwindow -R "$WINDOW"
|
|
||||||
fi
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $# -lt 5 ]]; then
|
|
||||||
echo "Not enough args to launch a new $NAME."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# No window to show/hide, better create it. Do setup for that.
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# no xinerama for now
|
|
||||||
CFG=($(xdotool getdisplaygeometry))
|
|
||||||
SCR_WIDTH=${CFG[0]}
|
|
||||||
SCR_HEIGHT=${CFG[1]}
|
|
||||||
SCR_LEFT=0 #${CFG[2]}
|
|
||||||
SCR_TOP=0 #${CFG[3]}
|
|
||||||
|
|
||||||
SIDE=$2
|
|
||||||
WIDTH=$3
|
|
||||||
HEIGHT=$4
|
|
||||||
|
|
||||||
shift 4
|
|
||||||
|
|
||||||
# Handle fractions of screen size for width and height
|
|
||||||
# ====================================================
|
|
||||||
|
|
||||||
if [[ $WIDTH == *% ]]; then
|
|
||||||
WIDTH=${WIDTH:0:-1} # chomp '%'
|
|
||||||
WIDTH=$(( (WIDTH*10*SCR_WIDTH)/1000 ))
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $HEIGHT == *% ]]; then
|
|
||||||
HEIGHT=${HEIGHT:0:-1} # chomp '%'
|
|
||||||
HEIGHT=$(( (HEIGHT*10*SCR_HEIGHT)/1000 ))
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Figure out where to put the window
|
|
||||||
# ==================================
|
|
||||||
|
|
||||||
TOP_ADJ=$(( (SCR_HEIGHT-HEIGHT)/2 ))
|
|
||||||
LEFT_ADJ=$(( (SCR_WIDTH-WIDTH)/2 ))
|
|
||||||
|
|
||||||
case $SIDE in
|
|
||||||
"left")
|
|
||||||
LEFT=$SCR_LEFT
|
|
||||||
TOP=$(( SCR_TOP + TOP_ADJ ))
|
|
||||||
;;
|
|
||||||
"right")
|
|
||||||
LEFT=$(( SCR_WIDTH - WIDTH ))
|
|
||||||
TOP=$(( SCR_TOP + TOP_ADJ ))
|
|
||||||
;;
|
|
||||||
"bottom")
|
|
||||||
LEFT=$(( SCR_LEFT + LEFT_ADJ ))
|
|
||||||
TOP=$(( SCR_HEIGHT - HEIGHT ))
|
|
||||||
;;
|
|
||||||
"top")
|
|
||||||
LEFT=$(( SCR_LEFT + LEFT_ADJ ))
|
|
||||||
TOP=$SCR_TOP
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Create the window
|
|
||||||
# =================
|
|
||||||
|
|
||||||
$@ &
|
|
||||||
# await new window:
|
|
||||||
countWins() {
|
|
||||||
xdotool search --onlyvisible . 2> /dev/null | wc -l
|
|
||||||
}
|
|
||||||
|
|
||||||
WIN_CNT="$(countWins)"
|
|
||||||
while [[ $(countWins) = "$WIN_CNT" ]]; do sleep 0.1; done
|
|
||||||
sleep 0.25
|
|
||||||
|
|
||||||
# new window should now be active, make it our window:
|
|
||||||
WINDOW="$(xdotool getactivewindow)"
|
|
||||||
xdotool set_window --role "drawer" $WINDOW
|
|
||||||
mkdir -p "$TMPDIR"
|
|
||||||
echo "$WINDOW" > "$TMPDIR$NAME"
|
|
||||||
|
|
||||||
border_width="$(xgetres awesome border_width)"
|
|
||||||
which awesome-client &> /dev/null && echo "client.focus.floating = true; client.focus.border_width=$border_width" | awesome-client
|
|
||||||
xdotool windowmove $WINDOW $LEFT $TOP windowsize $WINDOW $WIDTH $HEIGHT windowfocus $WINDOW windowraise $WINDOW
|
|
|
@ -1,14 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
options="screenshot\nscreengif"
|
|
||||||
selected="$(echo -e "$options" | rofi -dmenu -i -theme ~/scripts/rofi-scripts/default_theme.rasi)"
|
|
||||||
case "$selected" in
|
|
||||||
screenshot)
|
|
||||||
~/scripts/screenshot.sh
|
|
||||||
;;
|
|
||||||
screengif)
|
|
||||||
notify-send gif "press M-S-C-g to end gif"
|
|
||||||
~/scripts/screengif.sh
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
pgrep "$@" > /dev/null || ("$@" &)
|
|
|
@ -1,2 +0,0 @@
|
||||||
#!/bin/dash
|
|
||||||
appres "$1" | grep "$2" | cut -f 2-
|
|
|
@ -1,34 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
|
|
||||||
sxhkd &
|
|
||||||
|
|
||||||
killall -q picom && picom --config ~/.config/picom.conf --experimental-backends --no-fading-openclose &
|
|
||||||
killall -q pasystray && pasystray &
|
|
||||||
killall -q nm-applet && nm-applet &
|
|
||||||
killall -q clipmenud && clipmenud &
|
|
||||||
|
|
||||||
xset r rate 300 50 &
|
|
||||||
/home/leon/.config/polybar/launch.sh &
|
|
||||||
feh --bg-fill /home/leon/Bilder/wallpapers/mountains_with_clounds.jpg &
|
|
||||||
|
|
||||||
bspc monitor -d 1 2 3 4 5 6 7 8 9 10
|
|
||||||
|
|
||||||
bspc config border_width 2
|
|
||||||
bspc config window_gap 14
|
|
||||||
|
|
||||||
bspc config focus_follows_pointer true
|
|
||||||
|
|
||||||
bspc config split_ratio 0.50
|
|
||||||
bspc config borderless_monocle false
|
|
||||||
bspc config gapless_monocle false
|
|
||||||
bspc config automatic_scheme alternate
|
|
||||||
|
|
||||||
bspc rule -a mplayer2 state=floating
|
|
||||||
bspc rule -a Kupfer.py focus=on
|
|
||||||
bspc rule -a Screenkey manage=off
|
|
||||||
bspc rule -a feh state=floating
|
|
||||||
bspc rule -a Sxiv state=floating
|
|
||||||
|
|
||||||
#bspc rule -a kitty_scratchpad sticky=on state=floating hidden=on
|
|
||||||
#kitty --class kitty_scratchpad &
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"lastUpdate": 1584601643868
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
{"dependencies":{}}
|
|
|
@ -1 +0,0 @@
|
||||||
{}
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"optOut": false,
|
|
||||||
"lastUpdateCheck": 1592658266558
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
# Path to Oh My Fish install.
|
|
||||||
set -q XDG_DATA_HOME
|
|
||||||
and set -gx OMF_PATH "$XDG_DATA_HOME/omf"
|
|
||||||
or set -gx OMF_PATH "$HOME/.local/share/omf"
|
|
||||||
|
|
||||||
# Load Oh My Fish configuration.
|
|
||||||
source $OMF_PATH/init.fish
|
|
|
@ -1,77 +0,0 @@
|
||||||
fish_vi_key_bindings
|
|
||||||
# fish_default_key_bindings
|
|
||||||
|
|
||||||
# disable truecolor for dvtm
|
|
||||||
# set -e fish_term24bit
|
|
||||||
#source /home/leon/.config/fish/gruvbox-colors.fish
|
|
||||||
|
|
||||||
#set -U FZF_TMUX 1
|
|
||||||
set -U FZF_DEFAULT_COMMANDS "--filepath-word --cycle"
|
|
||||||
set -U FZF_PREVIEW_FILE_CMD "head -n 10 | bat --color=always --decorations=never"
|
|
||||||
set -U fish_greeting
|
|
||||||
#function fish_greeting
|
|
||||||
#end
|
|
||||||
|
|
||||||
|
|
||||||
alias ls=lsd
|
|
||||||
alias tcolors="env TERM=xterm-256color tcolors"
|
|
||||||
abbr --add --global vim nvim
|
|
||||||
abbr --add --global tsh trash
|
|
||||||
#abbr --add --global clear "clear && ls"
|
|
||||||
abbr --add --global cxmonad "nvim /home/leon/.xmonad/lib/Config.hs"
|
|
||||||
|
|
||||||
|
|
||||||
#if status is-interactive
|
|
||||||
#and not set -q TMUX
|
|
||||||
#exec tmux
|
|
||||||
#end
|
|
||||||
|
|
||||||
abbr --add --global gaa "git add --all"
|
|
||||||
abbr --add --global gc "git commit -m "
|
|
||||||
abbr --add --global gp "git push"
|
|
||||||
abbr --add --global gs "git status"
|
|
||||||
|
|
||||||
|
|
||||||
[ (hostname) = "garnix" ] && alias rm='echo "rm is disabled. Please use trash instead."; false'
|
|
||||||
|
|
||||||
function run_stuff
|
|
||||||
set -l commandline (commandline -b)
|
|
||||||
pipr --out-file /tmp/pipr_out --default "$commandline"
|
|
||||||
set -l result (cat /tmp/pipr_out)
|
|
||||||
commandline -r $result
|
|
||||||
commandline -f repaint
|
|
||||||
end
|
|
||||||
|
|
||||||
function c
|
|
||||||
set -l result (/home/leon/scripts/conf)
|
|
||||||
commandline -r "$result"
|
|
||||||
commandline -f execute
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
bind \ca run_stuff
|
|
||||||
|
|
||||||
|
|
||||||
function replace_with_yay
|
|
||||||
set -l cmd (commandline -b)
|
|
||||||
switch $cmd
|
|
||||||
case "*pacman*"
|
|
||||||
set edited (echo $cmd | sed 's/sudo //g' | sed 's/pacman/yay/g')
|
|
||||||
case "yay*"
|
|
||||||
set edited (echo $cmd | sed 's/yay/sudo pacman/g')
|
|
||||||
end
|
|
||||||
commandline -r "$edited"
|
|
||||||
commandline -f repaint
|
|
||||||
end
|
|
||||||
|
|
||||||
bind \cy replace_with_yay
|
|
||||||
|
|
||||||
# fff file manager cd on exit
|
|
||||||
function f
|
|
||||||
fff $argv
|
|
||||||
set -q XDG_CACHE_HOME; or set XDG_CACHE_HOME $HOME/.cache
|
|
||||||
cd (cat $XDG_CACHE_HOME/fff/.fff_d)
|
|
||||||
end
|
|
||||||
set -x EDITOR "nvim"
|
|
||||||
set -x FFF_TRASH_CMD "trash" # make fff's trash function use trash-cli
|
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
# This file contains fish universal variable definitions.
|
|
||||||
# VERSION: 3.0
|
|
||||||
SETUVAR FZF_DEFAULT_COMMANDS:\x2d\x2dfilepath\x2dword\x20\x2d\x2dcycle
|
|
||||||
SETUVAR FZF_DEFAULT_OPTS:\x2d\x2dheight\x2040\x25
|
|
||||||
SETUVAR FZF_ENABLE_OPEN_PREVIEW:1
|
|
||||||
SETUVAR FZF_LEGACY_KEYBINDINGS:0
|
|
||||||
SETUVAR FZF_PREVIEW_DIR_CMD:ls
|
|
||||||
SETUVAR FZF_PREVIEW_FILE_CMD:head\x20\x2dn\x2010\x20\x7c\x20bat\x20\x2d\x2dcolor\x3dalways\x20\x2d\x2ddecorations\x3dnever
|
|
||||||
SETUVAR FZF_TMUX:1
|
|
||||||
SETUVAR FZF_TMUX_HEIGHT:40\x25
|
|
||||||
SETUVAR SXHKD_SHELL:sh
|
|
||||||
SETUVAR __fish_initialized:3100
|
|
||||||
SETUVAR dangerous_colors:000000\x1e083743\x1e445659\x1efdf6e3\x1eb58900\x1ecb4b16\x1edc121f\x1eaf005f\x1e6c71c4\x1e268bd2\x1e2aa198\x1e859900
|
|
||||||
SETUVAR dangerous_cursors:\x5c033\x5d12\x3b\x23268bd2\x5c007\x1e\x5c033\x5d12\x3b\x23b58900\x5c007\x1e\x5c033\x5d12\x3b\x23af005f\x5c007\x1e\x5c033\x5d12\x3b\x236c71c4\x5c007
|
|
||||||
SETUVAR dangerous_day:000000\x1e333333\x1e666666\x1effffff\x1effff00\x1eff6600\x1eff0000\x1eff0033\x1e3300ff\x1e00aaff\x1e00ffff\x1e00ff00
|
|
||||||
SETUVAR dangerous_night:000000\x1e083743\x1e445659\x1efdf6e3\x1eb58900\x1ecb4b16\x1edc121f\x1eaf005f\x1e6c71c4\x1e268bd2\x1e2aa198\x1e859900
|
|
||||||
SETUVAR dangerous_nocmdhist:c\x1ed\x1ell\x1els\x1em\x1es
|
|
||||||
SETUVAR dangerous_pwdstyle:short\x1elong\x1enone
|
|
||||||
SETUVAR dangerous_sessions_active:\x1d
|
|
||||||
SETUVAR dangerous_sessions_active_pid:\x1d
|
|
||||||
SETUVAR fish_color_autosuggestion:555
|
|
||||||
SETUVAR fish_color_cancel:normal
|
|
||||||
SETUVAR fish_color_command:0087d7
|
|
||||||
SETUVAR fish_color_comment:990000
|
|
||||||
SETUVAR fish_color_cwd:008000
|
|
||||||
SETUVAR fish_color_cwd_root:800000
|
|
||||||
SETUVAR fish_color_end:009900
|
|
||||||
SETUVAR fish_color_error:ff0000
|
|
||||||
SETUVAR fish_color_escape:00a6b2
|
|
||||||
SETUVAR fish_color_history_current:normal
|
|
||||||
SETUVAR fish_color_host:normal
|
|
||||||
SETUVAR fish_color_host_remote:yellow
|
|
||||||
SETUVAR fish_color_match:normal
|
|
||||||
SETUVAR fish_color_normal:normal
|
|
||||||
SETUVAR fish_color_operator:00a6b2
|
|
||||||
SETUVAR fish_color_param:0087af
|
|
||||||
SETUVAR fish_color_quote:999900
|
|
||||||
SETUVAR fish_color_redirection:00afff
|
|
||||||
SETUVAR fish_color_search_match:ffff00
|
|
||||||
SETUVAR fish_color_selection:c0c0c0
|
|
||||||
SETUVAR fish_color_status:red
|
|
||||||
SETUVAR fish_color_user:00ff00
|
|
||||||
SETUVAR fish_color_valid_path:normal
|
|
||||||
SETUVAR fish_greeting:\x1d
|
|
||||||
SETUVAR fish_key_bindings:fish_vi_key_bindings
|
|
||||||
SETUVAR fish_pager_color_completion:normal
|
|
||||||
SETUVAR fish_pager_color_description:B3A06D\x1eyellow
|
|
||||||
SETUVAR fish_pager_color_prefix:white\x1e\x2d\x2dbold\x1e\x2d\x2dunderline
|
|
||||||
SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan
|
|
||||||
SETUVAR fish_user_paths:/home/leon/\x2efzf/bin
|
|
|
@ -1 +0,0 @@
|
||||||
/home/leon/.local/share/omf/themes/lambda_better/fish_prompt.fish
|
|
|
@ -1,2 +0,0 @@
|
||||||
function fish_user_key_bindings
|
|
||||||
end
|
|
|
@ -1 +0,0 @@
|
||||||
/home/leon/.local/share/omf/themes/lambda/fish_prompt.fish
|
|
|
@ -1,67 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
function fish_prompt
|
|
||||||
# Cache exit status
|
|
||||||
set -l last_status $status
|
|
||||||
|
|
||||||
set -l normal (set_color normal)
|
|
||||||
set -l white (set_color FFFFFF)
|
|
||||||
set -l turquoise (set_color 5fdfff)
|
|
||||||
set -l orange (set_color df5f00)
|
|
||||||
set -l hotpink (set_color df005f)
|
|
||||||
set -l blue (set_color blue)
|
|
||||||
set -l limegreen (set_color 87ff00)
|
|
||||||
set -l purple (set_color af5fff)
|
|
||||||
|
|
||||||
|
|
||||||
# Configure __fish_git_prompt
|
|
||||||
set -g __fish_git_prompt_char_stateseparator ' '
|
|
||||||
set -g __fish_git_prompt_color 5fdfff
|
|
||||||
set -g __fish_git_prompt_color_flags df5f00
|
|
||||||
set -g __fish_git_prompt_color_prefix white
|
|
||||||
set -g __fish_git_prompt_color_suffix white
|
|
||||||
set -g __fish_git_prompt_showdirtystate true
|
|
||||||
set -g __fish_git_prompt_showuntrackedfiles true
|
|
||||||
set -g __fish_git_prompt_showstashstate true
|
|
||||||
set -g __fish_git_prompt_show_informative_status true
|
|
||||||
|
|
||||||
set -l current_user (whoami)
|
|
||||||
set -l vi_mode (__fish_vi_mode_prompt_real)
|
|
||||||
set -l git_prompt (__fish_git_prompt " (%s)")
|
|
||||||
#(pwd|sed "s=$HOME=~=")
|
|
||||||
|
|
||||||
set -g fish_prompt_pwd_dir_length 1
|
|
||||||
|
|
||||||
echo -n $white'╭─'$vi_mode
|
|
||||||
echo -n $white'─'$hotpink$current_user$white' in '$limegreen(prompt_pwd)
|
|
||||||
echo -n $turquoise$git_prompt
|
|
||||||
if test $last_status -gt 0
|
|
||||||
echo -n ' '$hotpink$last_status
|
|
||||||
end
|
|
||||||
echo
|
|
||||||
|
|
||||||
echo -n $white'╰─λ '
|
|
||||||
echo -n $normal
|
|
||||||
end
|
|
||||||
|
|
||||||
function __fish_vi_mode_prompt_real
|
|
||||||
set -l turquoise (set_color 5fdfff)
|
|
||||||
set -l orange (set_color df5f00)
|
|
||||||
switch $fish_bind_mode
|
|
||||||
case insert
|
|
||||||
echo -n "─"
|
|
||||||
case default
|
|
||||||
echo -n $turquoise'N'
|
|
||||||
case visual
|
|
||||||
echo -n $orange'V'
|
|
||||||
case replace_one
|
|
||||||
echo -n $turquoise'R'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# needed so fish doesn't draw it by itself
|
|
||||||
function fish_mode_prompt
|
|
||||||
end
|
|
||||||
|
|
||||||
# ⌁
|
|
|
@ -1,27 +0,0 @@
|
||||||
|
|
||||||
set -l orange '#fe8019'
|
|
||||||
set -l aqua '#8ec07c'
|
|
||||||
set -l blue '#83a598'
|
|
||||||
set -l limegreen '#b8bb26'
|
|
||||||
set -l purple '#d3869b'
|
|
||||||
set -l aqua '#8ec07c'
|
|
||||||
set -l gwhite '#ebdbb2'
|
|
||||||
set -l gray2 '#665c54'
|
|
||||||
set -l purple '#d3869b'
|
|
||||||
set -l gray '#a89984'
|
|
||||||
set -l yellow '#fabd2f'
|
|
||||||
|
|
||||||
#set -U fish_color_command $blue
|
|
||||||
#set -U fish_color_normal $gwhite
|
|
||||||
#set -U fish_color_quote $aqua
|
|
||||||
#set -U fish_color_redirection $orange
|
|
||||||
#set -U fish_color_param $aqua
|
|
||||||
#set -U fish_color_comment $gray
|
|
||||||
#set -U fish_color_match $yellow
|
|
||||||
#set -U fish_color_search_match $aqua
|
|
||||||
#set -U fish_color_autosuggestion $gray2
|
|
||||||
#set -U fish_color_cancel $aqua
|
|
||||||
#set fish_color_selection
|
|
||||||
#set fish_color_end
|
|
||||||
#set fish_color_error
|
|
||||||
#set fish_color_operator
|
|
|
@ -1,2 +0,0 @@
|
||||||
file:///home/leon/coding/projects
|
|
||||||
file:///home/leon/studium/Studium
|
|
|
@ -1,77 +0,0 @@
|
||||||
@define-color theme_fg_color #eff0f1;
|
|
||||||
@define-color theme_bg_color #31363b;
|
|
||||||
@define-color theme_text_color #eff0f1;
|
|
||||||
@define-color theme_base_color #232629;
|
|
||||||
@define-color theme_view_hover_decoration_color #3daee9;
|
|
||||||
@define-color theme_hovering_selected_bg_color #3daee9;
|
|
||||||
@define-color theme_selected_bg_color #3daee9;
|
|
||||||
@define-color theme_selected_fg_color #eff0f1;
|
|
||||||
@define-color theme_view_active_decoration_color #3daee9;
|
|
||||||
@define-color theme_button_background_normal #31363b;
|
|
||||||
@define-color theme_button_decoration_hover #3daee9;
|
|
||||||
@define-color theme_button_decoration_focus #3daee9;
|
|
||||||
@define-color theme_button_foreground_normal #eff0f1;
|
|
||||||
@define-color theme_button_foreground_active #eff0f1;
|
|
||||||
@define-color borders #606468;
|
|
||||||
@define-color warning_color #f67400;
|
|
||||||
@define-color success_color #27ae60;
|
|
||||||
@define-color error_color #da4453;
|
|
||||||
@define-color theme_unfocused_fg_color #eff0f1;
|
|
||||||
@define-color theme_unfocused_text_color #eff0f1;
|
|
||||||
@define-color theme_unfocused_bg_color #31363b;
|
|
||||||
@define-color theme_unfocused_base_color #232629;
|
|
||||||
@define-color theme_unfocused_selected_bg_color_alt #224e65;
|
|
||||||
@define-color theme_unfocused_selected_bg_color #224e65;
|
|
||||||
@define-color theme_unfocused_selected_fg_color #eff0f1;
|
|
||||||
@define-color theme_button_background_backdrop #31363b;
|
|
||||||
@define-color theme_button_decoration_hover_backdrop #3daee9;
|
|
||||||
@define-color theme_button_decoration_focus_backdrop #3daee9;
|
|
||||||
@define-color theme_button_foreground_backdrop #eff0f1;
|
|
||||||
@define-color theme_button_foreground_active_backdrop #eff0f1;
|
|
||||||
@define-color unfocused_borders #606468;
|
|
||||||
@define-color warning_color_backdrop #f67400;
|
|
||||||
@define-color success_color_backdrop #27ae60;
|
|
||||||
@define-color error_color_backdrop #da4453;
|
|
||||||
@define-color insensitive_fg_color #6e7175;
|
|
||||||
@define-color insensitive_base_fg_color #65686a;
|
|
||||||
@define-color insensitive_bg_color #2e3338;
|
|
||||||
@define-color insensitive_base_color #212427;
|
|
||||||
@define-color insensitive_selected_bg_color #2e3338;
|
|
||||||
@define-color insensitive_selected_fg_color #6e7175;
|
|
||||||
@define-color theme_button_background_insensitive #2e3338;
|
|
||||||
@define-color theme_button_decoration_hover_insensitive #325b72;
|
|
||||||
@define-color theme_button_decoration_focus_insensitive #325b72;
|
|
||||||
@define-color theme_button_foreground_insensitive #6e7175;
|
|
||||||
@define-color theme_button_foreground_active_insensitive #6e7175;
|
|
||||||
@define-color insensitive_borders #3e4347;
|
|
||||||
@define-color warning_color_insensitive #683e19;
|
|
||||||
@define-color success_color_insensitive #225139;
|
|
||||||
@define-color error_color_insensitive #5e2e35;
|
|
||||||
@define-color insensitive_unfocused_fg_color #6e7175;
|
|
||||||
@define-color theme_unfocused_view_text_color #65686a;
|
|
||||||
@define-color insensitive_unfocused_bg_color #2e3338;
|
|
||||||
@define-color theme_unfocused_view_bg_color #212427;
|
|
||||||
@define-color insensitive_unfocused_selected_bg_color #2e3338;
|
|
||||||
@define-color insensitive_unfocused_selected_fg_color #6e7175;
|
|
||||||
@define-color theme_button_background_backdrop_insensitive #2e3338;
|
|
||||||
@define-color theme_button_decoration_hover_backdrop_insensitive #325b72;
|
|
||||||
@define-color theme_button_decoration_focus_backdrop_insensitive #325b72;
|
|
||||||
@define-color theme_button_foreground_backdrop_insensitive #6e7175;
|
|
||||||
@define-color theme_button_foreground_active_backdrop_insensitive #6e7175;
|
|
||||||
@define-color unfocused_insensitive_borders #3e4347;
|
|
||||||
@define-color warning_color_insensitive_backdrop #683e19;
|
|
||||||
@define-color success_color_insensitive_backdrop #225139;
|
|
||||||
@define-color error_color_insensitive_backdrop #5e2e35;
|
|
||||||
@define-color link_color #2980b9;
|
|
||||||
@define-color link_visited_color #7f8c8d;
|
|
||||||
@define-color tooltip_text #eff0f1;
|
|
||||||
@define-color tooltip_background #31363b;
|
|
||||||
@define-color tooltip_border #606468;
|
|
||||||
@define-color content_view_bg #232629;
|
|
||||||
@define-color theme_titlebar_background rgb(49,54,59);
|
|
||||||
@define-color theme_titlebar_foreground rgb(239,240,241);
|
|
||||||
@define-color theme_titlebar_background_light #31363b;
|
|
||||||
@define-color theme_titlebar_foreground_backdrop rgb(127,140,141);
|
|
||||||
@define-color theme_titlebar_background_backdrop rgb(49,54,59);
|
|
||||||
@define-color theme_titlebar_foreground_insensitive rgb(127,140,141);
|
|
||||||
@define-color theme_titlebar_foreground_insensitive_backdrop rgb(127,140,141);
|
|
|
@ -1,8 +0,0 @@
|
||||||
.termite {
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
vte-terminal {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@import 'colors.css';
|
|
|
@ -1,25 +0,0 @@
|
||||||
[Settings]
|
|
||||||
gtk-button-images=1
|
|
||||||
gtk-cursor-theme-name=capitaine-cursors-light
|
|
||||||
gtk-cursor-theme-size=0
|
|
||||||
gtk-enable-event-sounds=0
|
|
||||||
gtk-enable-input-feedback-sounds=0
|
|
||||||
gtk-font-name=Sans 9
|
|
||||||
gtk-icon-theme-name=Arc-X-D
|
|
||||||
gtk-menu-images=1
|
|
||||||
;gtk-theme-name=Adwaita-dark
|
|
||||||
gtk-theme-name=phocus
|
|
||||||
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
|
|
||||||
gtk-toolbar-style=GTK_TOOLBAR_ICONS
|
|
||||||
gtk-xft-antialias=1
|
|
||||||
gtk-xft-hinting=1
|
|
||||||
gtk-xft-hintstyle=hintslight
|
|
||||||
gtk-xft-rgba=rgb
|
|
||||||
gtk-application-prefer-dark-theme=true
|
|
||||||
gtk-decoration-layout=:
|
|
||||||
|
|
||||||
;gtk-font-name = DejaVu Sans 1 121
|
|
||||||
;gtk-font-name = cozette 10
|
|
||||||
gtk-font-name = xos4 Terminus Regular 12
|
|
||||||
;gtk-font-name = Terminus 12
|
|
||||||
;gtk-font-name = cozette 10
|
|
|
@ -1,26 +0,0 @@
|
||||||
# Beware! This file is rewritten by htop when settings are changed in the interface.
|
|
||||||
# The parser is also very primitive, and not human-friendly.
|
|
||||||
fields=0 48 17 18 38 39 40 2 46 47 49 1
|
|
||||||
sort_key=47
|
|
||||||
sort_direction=1
|
|
||||||
hide_threads=1
|
|
||||||
hide_kernel_threads=1
|
|
||||||
hide_userland_threads=1
|
|
||||||
shadow_other_users=0
|
|
||||||
show_thread_names=0
|
|
||||||
show_program_path=1
|
|
||||||
highlight_base_name=0
|
|
||||||
highlight_megabytes=1
|
|
||||||
highlight_threads=1
|
|
||||||
tree_view=0
|
|
||||||
header_margin=1
|
|
||||||
detailed_cpu_time=0
|
|
||||||
cpu_count_from_zero=0
|
|
||||||
update_process_names=0
|
|
||||||
account_guest_in_cpu_meter=0
|
|
||||||
color_scheme=0
|
|
||||||
delay=15
|
|
||||||
left_meters=AllCPUs Memory Swap
|
|
||||||
left_meter_modes=1 1 1
|
|
||||||
right_meters=Tasks LoadAverage Uptime
|
|
||||||
right_meter_modes=2 2 2
|
|
|
@ -1 +0,0 @@
|
||||||
/home/leon/.config/kitty/kitty-themes/themes/gruvbox_dark.conf
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit fca3335489bdbab4cce150cb440d3559ff5400e2
|
|
|
@ -1,68 +0,0 @@
|
||||||
include ./gruvbox.conf
|
|
||||||
#include ./onedark.conf
|
|
||||||
|
|
||||||
#shell tmux
|
|
||||||
#background_opacity 0.95
|
|
||||||
background_opacity 1
|
|
||||||
|
|
||||||
#font_family VictorMono Nerd Font Semibold
|
|
||||||
#font_family DejaVuSansMono Nerd
|
|
||||||
font_family Iosevka Nerd Font
|
|
||||||
#font_family JetbrainsMono Nerd Font
|
|
||||||
|
|
||||||
bold_font auto
|
|
||||||
italic_font auto
|
|
||||||
bold_italic_font auto
|
|
||||||
#font_family monospace
|
|
||||||
font_size 13
|
|
||||||
|
|
||||||
enable_audio_bell no
|
|
||||||
|
|
||||||
draw_minimal_borders yes
|
|
||||||
window_padding_width 0
|
|
||||||
window_margin_width 10
|
|
||||||
tab_bar_style powerline
|
|
||||||
hide_window_decorations yes
|
|
||||||
placement_strategy top-left
|
|
||||||
|
|
||||||
|
|
||||||
clipboard_control write-clipboard write-primary read-primary read-clipboard
|
|
||||||
dynamic_background_opacity yes
|
|
||||||
allow_remote_control yes
|
|
||||||
sync_to_monitor yes
|
|
||||||
|
|
||||||
active_tab_background #6272a4
|
|
||||||
active_tab_foreground #f8f8f2
|
|
||||||
inactive_tab_background #44475a
|
|
||||||
inactive_tab_foreground #f8f8f2
|
|
||||||
|
|
||||||
# Keymaps {{{
|
|
||||||
|
|
||||||
|
|
||||||
# Windows
|
|
||||||
map kitty_mod+enter new_window_with_cwd
|
|
||||||
map ctrl+shift+left neighboring_window left
|
|
||||||
map ctrl+shift+down neighboring_window down
|
|
||||||
map ctrl+shift+right neighboring_window right
|
|
||||||
map ctrl+shift+up neighboring_window up
|
|
||||||
|
|
||||||
# tabs
|
|
||||||
#map kitty_mod+t new_tab
|
|
||||||
map kitty_mod+n new_tab_with_cwd
|
|
||||||
map ctrl+shift+l next_tab
|
|
||||||
map ctrl+shift+h previous_tab
|
|
||||||
|
|
||||||
# new os window
|
|
||||||
map kitty_mod+backspace new_os_window_with_cwd
|
|
||||||
|
|
||||||
|
|
||||||
# Other
|
|
||||||
map ctrl+shift+plus change_font_size all +2.0
|
|
||||||
map ctrl+shift+alt+h show_scrollback
|
|
||||||
|
|
||||||
# --type=overlay
|
|
||||||
# --stdin-source=@screen_scrollback
|
|
||||||
# https://sw.kovidgoyal.net/kitty/launch.html
|
|
||||||
map ctrl+shift+space launch --stdin-source=@screen --stdin-add-formatting --type=window /home/leon/scripts/autocompleteWords.sh @active-kitty-window-id
|
|
||||||
|
|
||||||
# }}}
|
|
|
@ -1,21 +0,0 @@
|
||||||
background #282c34
|
|
||||||
foreground #c4c8c5
|
|
||||||
cursor #d0d0d0
|
|
||||||
selection_background #444444
|
|
||||||
selection_foreground #161718
|
|
||||||
color0 #000000
|
|
||||||
color1 #fc5ef0
|
|
||||||
color2 #86c38a
|
|
||||||
color3 #ffd6b1
|
|
||||||
color4 #85befd
|
|
||||||
color5 #b9b5fc
|
|
||||||
color6 #85befd
|
|
||||||
color7 #dfdfdf
|
|
||||||
color8 #808080
|
|
||||||
color9 #fc5ef0
|
|
||||||
color10 #94f936
|
|
||||||
color11 #f5ffa7
|
|
||||||
color12 #95cbfe
|
|
||||||
color13 #b9b5fc
|
|
||||||
color14 #85befd
|
|
||||||
color15 #dfdfdf
|
|
|
@ -1,19 +0,0 @@
|
||||||
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
|
|
||||||
"http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd">
|
|
||||||
<!-- Do not edit manually - generated and managed by xdg-desktop-menu -->
|
|
||||||
<Menu>
|
|
||||||
<Name>Applications</Name>
|
|
||||||
<Menu>
|
|
||||||
<Name>chrome-apps</Name>
|
|
||||||
<Directory>chrome-apps.directory</Directory>
|
|
||||||
<Include>
|
|
||||||
<Filename>chrome-jjphmlaoffndcnecccgemfdaaoighkel-Default.desktop</Filename>
|
|
||||||
<Filename>chrome-ooiklbnjmhbcgemelgfhaeaocllobloj-Default.desktop</Filename>
|
|
||||||
<Filename>chrome-njhehnieenekbompacofnhlljnobgcga-Default.desktop</Filename>
|
|
||||||
<Filename>chrome-hmjkmjkepdijhoojdojkdfohbdgmmhki-Default.desktop</Filename>
|
|
||||||
<Filename>chrome-mjcnijlhddpbdemagnpefmlkjdagkogk-Default.desktop</Filename>
|
|
||||||
<Filename>chrome-gbchcmhmhahfdphkhkmpfmihenigjmpp-Default.desktop</Filename>
|
|
||||||
<Filename>chrome-hnpfjngllnobngcgfapefoaidbinmjnm-Default.desktop</Filename>
|
|
||||||
</Include>
|
|
||||||
</Menu>
|
|
||||||
</Menu>
|
|
|
@ -1,14 +0,0 @@
|
||||||
[:0.0]
|
|
||||||
file=/home/leon/Bilder/wallpapers/wallhaven-ox2gr9.jpg
|
|
||||||
mode=5
|
|
||||||
bgcolor=#000000
|
|
||||||
|
|
||||||
[xin_0]
|
|
||||||
file=/home/leon/Bilder/wallpapers/green_leaves.jpg
|
|
||||||
mode=5
|
|
||||||
bgcolor=#000000
|
|
||||||
|
|
||||||
[xin_1]
|
|
||||||
file=/home/leon/Bilder/wallpapers/green_leaves.jpg
|
|
||||||
mode=5
|
|
||||||
bgcolor=#000000
|
|
|
@ -1,12 +0,0 @@
|
||||||
[geometry]
|
|
||||||
posx=20
|
|
||||||
posy=50
|
|
||||||
sizex=1297
|
|
||||||
sizey=696
|
|
||||||
|
|
||||||
[nitrogen]
|
|
||||||
view=icon
|
|
||||||
recurse=true
|
|
||||||
sort=alpha
|
|
||||||
icon_caps=false
|
|
||||||
dirs=/home/leon/Bilder/wallpapers;
|
|
|
@ -1,178 +0,0 @@
|
||||||
# Thank you code_nomad: http://9m.no/ꪯ鵞
|
|
||||||
# and Arch Wiki contributors: https://wiki.archlinux.org/index.php/Compton
|
|
||||||
|
|
||||||
# Backend --------------------- {{{
|
|
||||||
|
|
||||||
# Backend to use: "xrender" or "glx".
|
|
||||||
# GLX backend is typically much faster but depends on a sane driver.
|
|
||||||
backend = "glx";
|
|
||||||
|
|
||||||
glx-no-stencil = true;
|
|
||||||
glx-copy-from-front = false;
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# Shadows -------------------------------- {{{
|
|
||||||
shadow = true;
|
|
||||||
#shadow-radius = 20;
|
|
||||||
#shadow-offset-x = -20;
|
|
||||||
#shadow-offset-y = -20;
|
|
||||||
|
|
||||||
#hadow-radius = 3;
|
|
||||||
#shadow-offset-x = 3;
|
|
||||||
#shadow-offset-y = 3;
|
|
||||||
#shadow-opacity = 0.6;
|
|
||||||
shadow-radius = 18;
|
|
||||||
shadow-offset-x = -14;
|
|
||||||
shadow-offset-y = -10;
|
|
||||||
shadow-opacity = 1.0;
|
|
||||||
# shadow-red = 0.0;
|
|
||||||
# shadow-green = 0.0;
|
|
||||||
# shadow-blue = 0.0;
|
|
||||||
|
|
||||||
shadow-exclude = [
|
|
||||||
"! name~=''",
|
|
||||||
#"!focused && ! class_g ?='xfce4-notifyd'",
|
|
||||||
#"name *= 'polybar'",
|
|
||||||
"name = 'Notification'",
|
|
||||||
"name = 'Plank'",
|
|
||||||
"name = 'Docky'",
|
|
||||||
"name = 'Kupfer'",
|
|
||||||
#"name = 'xfce4-notifyd'",
|
|
||||||
"name *= 'VLC'",
|
|
||||||
"name *= 'compton'",
|
|
||||||
"name *= 'picom'",
|
|
||||||
"class_g = 'Conky'",
|
|
||||||
"class_g = 'Kupfer'",
|
|
||||||
"class_g = 'Synapse'",
|
|
||||||
"class_g ?= 'Notify-osd'",
|
|
||||||
"class_g ?= 'Cairo-dock'",
|
|
||||||
#"class_g ?= 'Xfce4-notifyd'",
|
|
||||||
"class_g ?= 'Xfce4-power-manager'",
|
|
||||||
"_GTK_FRAME_EXTENTS@:c",
|
|
||||||
"_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'"
|
|
||||||
];
|
|
||||||
# Avoid drawing shadow on all shaped windows (see also: --detect-rounded-corners)
|
|
||||||
shadow-ignore-shaped = false;
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
# Opacity and blur ------------------------------------- {{{
|
|
||||||
|
|
||||||
inactive-opacity = 1;
|
|
||||||
active-opacity = 1;
|
|
||||||
frame-opacity = 1;
|
|
||||||
#inactive-opacity-override = true;
|
|
||||||
|
|
||||||
# Dim inactive windows. (0.0 - 1.0)
|
|
||||||
inactive-dim = 1;
|
|
||||||
# Do not let dimness adjust based on window opacity.
|
|
||||||
#inactive-dim-fixed = true;
|
|
||||||
# Blur background of transparent windows. Bad performance with X Render backend. GLX backend is preferred.
|
|
||||||
|
|
||||||
blur-background = false;
|
|
||||||
#blur-method = "dual_kawase";
|
|
||||||
#blur-method = "kernel";
|
|
||||||
blur-strength = 20; # max 20
|
|
||||||
blur-size = 20;
|
|
||||||
# Blur background of opaque windows with transparent frames as well.
|
|
||||||
blur-background-frame = false;
|
|
||||||
# Do not let blur radius adjust based on window opacity.
|
|
||||||
blur-background-fixed = false;
|
|
||||||
blur-background-exclude = [
|
|
||||||
#"window_type = 'dock'",
|
|
||||||
"window_type = 'desktop'",
|
|
||||||
|
|
||||||
"! name~=''",
|
|
||||||
"name *= 'slop'",
|
|
||||||
"name = 'Notification'",
|
|
||||||
"name = 'xfce4-notifyd'",
|
|
||||||
"name *= 'compton'",
|
|
||||||
"name *= 'picom'",
|
|
||||||
"class_g ?= 'Xfce4-notifyd'",
|
|
||||||
"class_g ?= 'Xfce4-power-manager'",
|
|
||||||
"_GTK_FRAME_EXTENTS@:c",
|
|
||||||
"_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'"
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
# Fading ---------------------------------- {{{
|
|
||||||
|
|
||||||
# Fade windows during opacity changes.
|
|
||||||
fading = false;
|
|
||||||
# The time between steps in a fade in milliseconds. (default 10).
|
|
||||||
fade-delta = 4;
|
|
||||||
# Opacity change between steps while fading in. (default 0.028).
|
|
||||||
fade-in-step = 0.03;
|
|
||||||
# Opacity change between steps while fading out. (default 0.03).
|
|
||||||
fade-out-step = 0.03;
|
|
||||||
# Fade windows in/out when opening/closing
|
|
||||||
no-fading-openclose = false;
|
|
||||||
|
|
||||||
# Specify a list of conditions of windows that should not be faded.
|
|
||||||
fade-exclude = [ ];
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
# Other ---------------------------------- {{{
|
|
||||||
|
|
||||||
# Try to detect WM windows and mark them as active.
|
|
||||||
mark-wmwin-focused = true;
|
|
||||||
# Mark all non-WM but override-redirect windows active (e.g. menus).
|
|
||||||
mark-ovredir-focused = true;
|
|
||||||
# Use EWMH _NET_WM_ACTIVE_WINDOW to determine which window is focused instead of using FocusIn/Out events.
|
|
||||||
# Usually more reliable but depends on a EWMH-compliant WM.
|
|
||||||
use-ewmh-active-win = true;
|
|
||||||
# Detect rounded corners and treat them as rectangular when --shadow-ignore-shaped is on.
|
|
||||||
detect-rounded-corners = true;
|
|
||||||
|
|
||||||
# Detect _NET_WM_OPACITY on client windows, useful for window managers not passing _NET_WM_OPACITY of client windows to frame windows.
|
|
||||||
# This prevents opacity being ignored for some apps.
|
|
||||||
# For example without this enabled my xfce4-notifyd is 100% opacity no matter what.
|
|
||||||
detect-client-opacity = true;
|
|
||||||
|
|
||||||
vsync = true;
|
|
||||||
# Enable DBE painting mode, intended to use with VSync to (hopefully) eliminate tearing. Reported to have no effect, though.
|
|
||||||
dbe = false;
|
|
||||||
|
|
||||||
# Unredirect all windows if a full-screen opaque window is detected, to maximize performance for full-screen windows, like games.
|
|
||||||
# Known to cause flickering when redirecting/unredirecting windows.
|
|
||||||
unredir-if-possible = false;
|
|
||||||
|
|
||||||
# Specify a list of conditions of windows that should always be considered focused.
|
|
||||||
focus-exclude = [ ];
|
|
||||||
|
|
||||||
# Use WM_TRANSIENT_FOR to group windows, and consider windows in the same group focused at the same time.
|
|
||||||
detect-transient = true;
|
|
||||||
# Use WM_CLIENT_LEADER to group windows, and consider windows in the same group focused at the same time.
|
|
||||||
# WM_TRANSIENT_FOR has higher priority if --detect-transient is enabled, too.
|
|
||||||
detect-client-leader = true;
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
# Window type settings ---------------------------------- {{{
|
|
||||||
|
|
||||||
wintypes:
|
|
||||||
{
|
|
||||||
menu = {
|
|
||||||
opacity = 1;
|
|
||||||
shadow = true;
|
|
||||||
fade = true;
|
|
||||||
full-shadow = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
dropdown_menu = {
|
|
||||||
opacity = 1;
|
|
||||||
shadow = true;
|
|
||||||
fade = true;
|
|
||||||
full-shadow = true;
|
|
||||||
};
|
|
||||||
tooltip = {
|
|
||||||
fade = true;
|
|
||||||
shadow = true;
|
|
||||||
opacity = 1.00;
|
|
||||||
focus = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
xrender-sync-fence = true;
|
|
||||||
|
|
||||||
# }}}
|
|
|
@ -1,237 +0,0 @@
|
||||||
|
|
||||||
;==========================================================
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗
|
|
||||||
; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗
|
|
||||||
; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝
|
|
||||||
; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗
|
|
||||||
; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║
|
|
||||||
; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
|
|
||||||
;
|
|
||||||
; ; To learn more about how to configure Polybar
|
|
||||||
; go to https://github.com/polybar/polybar
|
|
||||||
;
|
|
||||||
; The README contains a lot of information
|
|
||||||
;
|
|
||||||
;==========================================================
|
|
||||||
|
|
||||||
;; Colors ------------------------------------------- {{{
|
|
||||||
|
|
||||||
[colors]
|
|
||||||
;background = ${xrdb:color0:#222}
|
|
||||||
;background = #bb282828
|
|
||||||
;background = #88282828
|
|
||||||
background = #00282828
|
|
||||||
;background = #222
|
|
||||||
background-alt = #444
|
|
||||||
;foreground = ${xrdb:color7:#222}
|
|
||||||
foreground = #dfdfdf
|
|
||||||
foreground-alt = #888
|
|
||||||
primary = #ffb52a
|
|
||||||
secondary = #e60053
|
|
||||||
alert = #bd2c40
|
|
||||||
|
|
||||||
;; }}}
|
|
||||||
|
|
||||||
;; Bar config ----------------------------------------- {{{
|
|
||||||
|
|
||||||
[bar/main]
|
|
||||||
width = 100%
|
|
||||||
height = 25
|
|
||||||
radius = 0.0
|
|
||||||
enable-ipc = true
|
|
||||||
padding = 0
|
|
||||||
;; center centered modules on screen, not between other modules
|
|
||||||
fixed-center = true
|
|
||||||
|
|
||||||
separator = "%{F#aaa}|%{F-}"
|
|
||||||
separator-padding = 1
|
|
||||||
|
|
||||||
background = ${colors.background}
|
|
||||||
foreground = ${colors.foreground}
|
|
||||||
|
|
||||||
line-size = 3
|
|
||||||
line-color = #f00
|
|
||||||
|
|
||||||
border-size = 0
|
|
||||||
border-color = #00000000
|
|
||||||
|
|
||||||
padding-left = 0
|
|
||||||
padding-right = 2
|
|
||||||
|
|
||||||
module-margin-left = 1
|
|
||||||
module-margin-right = 2
|
|
||||||
|
|
||||||
font-0 = fixed:pixelsize=10;1
|
|
||||||
;font-1 = unifont:fontformat=truetype:size=8:antialias=false;0
|
|
||||||
;font-2 = siji:pixelsize=10;1
|
|
||||||
;font-7 = NotoEmoji:size=7;
|
|
||||||
;font-7 = "JetBrainsMono Nerd Font:size=7"
|
|
||||||
;font-0 = "JetBrainsMono Nerd Font:fontformat=truetype:size=10;2"
|
|
||||||
;font-0 = "Iosevka Nerd Font:size=10;1"
|
|
||||||
;font-1 = "NotoEmoji:scale=10;1"
|
|
||||||
font-1 = "Symbola:size=10;1"
|
|
||||||
font-2 = FontAwesome5Free:style=Solid:size=8;0
|
|
||||||
;font-1 = "FontAwesome:fontformat=truetype:size=12;1"
|
|
||||||
|
|
||||||
|
|
||||||
modules-left = xmonad
|
|
||||||
modules-center = timerDisplay spotify mpd gitlab-pipeline player-mpv-tail
|
|
||||||
modules-right = pulseaudio-control updates-arch network-traffic pulseaudio filesystem memory cpu date
|
|
||||||
|
|
||||||
tray-position = right
|
|
||||||
tray-padding = 2
|
|
||||||
tray-maxsize = 16
|
|
||||||
tray-background = ${colors.background}
|
|
||||||
;tray-background = #0063ff
|
|
||||||
|
|
||||||
cursor-click = pointer
|
|
||||||
cursor-scroll = ns-resize
|
|
||||||
|
|
||||||
;; }}}
|
|
||||||
|
|
||||||
;; MODULES ----------------------------------------------- {{{
|
|
||||||
|
|
||||||
; show's currently focussed window, already contained in xmonad module
|
|
||||||
[module/xwindow]
|
|
||||||
type = internal/xwindow
|
|
||||||
label = %title:0:30:...%
|
|
||||||
|
|
||||||
[module/filesystem]
|
|
||||||
type = internal/fs
|
|
||||||
interval = 25
|
|
||||||
|
|
||||||
mount-0 = /
|
|
||||||
format-mounted = <label-mounted>
|
|
||||||
;format-mounted-prefix = "disk: "
|
|
||||||
;format-mounted-prefix-foreground = ${colors.foreground-alt}
|
|
||||||
format-mounted-prefix = "%{F#0fca42} %{F-} "
|
|
||||||
;format-mounted-prefix = " "
|
|
||||||
;format-mounted-underline = #0fca42
|
|
||||||
;label-mounted = %{F#0a81f5}%mountpoint%%{F-}: %percentage_used%%
|
|
||||||
label-mounted = %percentage_used%%
|
|
||||||
label-unmounted = %mountpoint% not mounted
|
|
||||||
label-unmounted-foreground = ${colors.foreground-alt}
|
|
||||||
|
|
||||||
|
|
||||||
[module/mpd]
|
|
||||||
type = internal/mpd
|
|
||||||
format-online = <label-song> <icon-prev> <icon-stop> <toggle> <icon-next>
|
|
||||||
|
|
||||||
icon-prev =
|
|
||||||
icon-stop =
|
|
||||||
icon-play =
|
|
||||||
icon-pause =
|
|
||||||
icon-next =
|
|
||||||
|
|
||||||
label-song-maxlen = 25
|
|
||||||
label-song-ellipsis = true
|
|
||||||
|
|
||||||
|
|
||||||
[module/cpu]
|
|
||||||
type = internal/cpu
|
|
||||||
interval = 2
|
|
||||||
;format-prefix = "cpu: "
|
|
||||||
;format-prefix-foreground = ${colors.foreground-alt}
|
|
||||||
format-prefix = "%{F#f9a000} %{F-} "
|
|
||||||
;format-prefix = " "
|
|
||||||
#format-underline = #f9a000
|
|
||||||
label = %percentage:2%%
|
|
||||||
|
|
||||||
[module/memory]
|
|
||||||
type = internal/memory
|
|
||||||
interval = 2
|
|
||||||
;format-prefix = "mem: "
|
|
||||||
;format-prefix-foreground = ${colors.foreground-alt}
|
|
||||||
format-prefix = "%{F#0a6cf5} %{F-} "
|
|
||||||
;format-prefix = " "
|
|
||||||
#format-underline = #0a6cf5
|
|
||||||
label = %percentage_used%%
|
|
||||||
|
|
||||||
[module/date]
|
|
||||||
type = internal/date
|
|
||||||
interval = 5
|
|
||||||
date = %a %d-%m-%y
|
|
||||||
date-alt = %d-%m-%Y
|
|
||||||
time = %H:%M
|
|
||||||
time-alt = %H:%M:%S
|
|
||||||
|
|
||||||
format-prefix = "%{F#fbff8c} %{F-}"
|
|
||||||
;format-prefix = " "
|
|
||||||
;format-prefix-foreground = ${colors.foreground-alt}
|
|
||||||
;#format-underline = #4bffdc
|
|
||||||
#format-underline = #fbff8c
|
|
||||||
label = %time% | %date%
|
|
||||||
|
|
||||||
[module/xmonad]
|
|
||||||
type = custom/script
|
|
||||||
exec = xmonad-log
|
|
||||||
tail = true
|
|
||||||
|
|
||||||
|
|
||||||
[module/timerDisplay]
|
|
||||||
type = custom/script
|
|
||||||
exec = "[ -f ~/scripts/remainingTime.txt ] && head -n 1 scripts/remainingTime.txt"
|
|
||||||
interval = 1
|
|
||||||
|
|
||||||
|
|
||||||
;[module/gitlab-pipeline]
|
|
||||||
;type = custom/script
|
|
||||||
;exec = ~/scripts/fetch-running-pipelines.sh
|
|
||||||
;interval = 10
|
|
||||||
|
|
||||||
[module/info-pingrtt]
|
|
||||||
type = custom/script
|
|
||||||
exec = ~/.config/polybar/polybar-scripts/info-pingrtt.sh
|
|
||||||
interval = 10
|
|
||||||
|
|
||||||
|
|
||||||
[module/player-mpv-tail]
|
|
||||||
type = custom/script
|
|
||||||
exec = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -t 42 -c '#abb2bf'
|
|
||||||
tail = true
|
|
||||||
click-left = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p pause
|
|
||||||
click-middle = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p playlist-pos -1
|
|
||||||
click-right = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p playlist-pos +1
|
|
||||||
scroll-up = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p time-pos -10
|
|
||||||
scroll-down = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p time-pos +10
|
|
||||||
|
|
||||||
|
|
||||||
[module/network-traffic]
|
|
||||||
; configure interval, etc in script
|
|
||||||
type = custom/script
|
|
||||||
exec = ~/.config/polybar/polybar-scripts/network-traffic.sh
|
|
||||||
tail = true
|
|
||||||
|
|
||||||
|
|
||||||
[module/spotify]
|
|
||||||
type = custom/script
|
|
||||||
interval = 1
|
|
||||||
format = "<label> %{A1:dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous:}%{A-} %{A1:dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next:}%{A-}"
|
|
||||||
exec = python ~/.config/polybar/polybar-scripts/spotify_status.py -f '{artist} - {song} {play_pause}'
|
|
||||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause"
|
|
||||||
exec-if = "pgrep spotify"
|
|
||||||
#format-underline = #1db954
|
|
||||||
|
|
||||||
|
|
||||||
[module/updates-arch]
|
|
||||||
type = custom/script
|
|
||||||
exec = ~/.config/polybar/polybar-scripts/updates-arch-combined.sh
|
|
||||||
interval = 600
|
|
||||||
|
|
||||||
|
|
||||||
[module/pulseaudio-control]
|
|
||||||
type = custom/script
|
|
||||||
tail = true
|
|
||||||
label = %output%
|
|
||||||
|
|
||||||
click-right = exec pavucontrol &
|
|
||||||
exec = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash listen
|
|
||||||
click-left = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash togmute
|
|
||||||
click-middle = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash next-sink
|
|
||||||
scroll-up = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash up
|
|
||||||
scroll-down = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash down
|
|
||||||
label-padding = 2
|
|
||||||
label-foreground = ${colors.foreground}
|
|
||||||
|
|
|
@ -1,252 +0,0 @@
|
||||||
|
|
||||||
;==========================================================
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗
|
|
||||||
; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗
|
|
||||||
; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝
|
|
||||||
; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗
|
|
||||||
; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║
|
|
||||||
; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
|
|
||||||
;
|
|
||||||
; ; To learn more about how to configure Polybar
|
|
||||||
; go to https://github.com/polybar/polybar
|
|
||||||
;
|
|
||||||
; The README contains a lot of information
|
|
||||||
;
|
|
||||||
;==========================================================
|
|
||||||
|
|
||||||
;; Colors ------------------------------------------- {{{
|
|
||||||
|
|
||||||
[colors]
|
|
||||||
;background = ${xrdb:color0:#222}
|
|
||||||
;background = #bb282828
|
|
||||||
;background = #88282828
|
|
||||||
;background = #88282828
|
|
||||||
background = #aa282c34
|
|
||||||
;background = #ff282c34
|
|
||||||
;background = #222
|
|
||||||
background-alt = #444
|
|
||||||
;foreground = ${xrdb:color7:#222}
|
|
||||||
foreground = #dfdfdf
|
|
||||||
foreground-alt = #888
|
|
||||||
primary = #ffb52a
|
|
||||||
secondary = #e60053
|
|
||||||
alert = #bd2c40
|
|
||||||
|
|
||||||
;; }}}
|
|
||||||
|
|
||||||
;; Bar config ----------------------------------------- {{{
|
|
||||||
|
|
||||||
[bar/main]
|
|
||||||
width = 100%:-28
|
|
||||||
height = 30
|
|
||||||
|
|
||||||
offset-x = 14
|
|
||||||
offset-y = 7
|
|
||||||
|
|
||||||
radius = 0
|
|
||||||
|
|
||||||
locale = de_DE.UTF-8
|
|
||||||
|
|
||||||
enable-ipc = true
|
|
||||||
padding = 0
|
|
||||||
;; center centered modules on screen, not between other modules
|
|
||||||
fixed-center = true
|
|
||||||
|
|
||||||
separator = "%{F#aaa}|%{F-}"
|
|
||||||
separator-padding = 1
|
|
||||||
|
|
||||||
|
|
||||||
background = ${colors.background}
|
|
||||||
foreground = ${colors.foreground}
|
|
||||||
|
|
||||||
line-size = 3
|
|
||||||
line-color = #f00
|
|
||||||
|
|
||||||
border-size = 0
|
|
||||||
border-color = #00000000
|
|
||||||
|
|
||||||
padding-left = 0
|
|
||||||
padding-right = 2
|
|
||||||
|
|
||||||
module-margin-left = 1
|
|
||||||
module-margin-right = 2
|
|
||||||
|
|
||||||
font-0 = fixed:pixelsize=10;1
|
|
||||||
;font-1 = unifont:fontformat=truetype:size=8:antialias=false;0
|
|
||||||
;font-2 = siji:pixelsize=10;1
|
|
||||||
;font-7 = NotoEmoji:size=7;
|
|
||||||
;font-7 = "JetBrainsMono Nerd Font:size=7"
|
|
||||||
;font-0 = "JetBrainsMono Nerd Font:fontformat=truetype:size=10;2"
|
|
||||||
;font-0 = "Iosevka Nerd Font:size=10;1"
|
|
||||||
;font-1 = "NotoEmoji:scale=10;1"
|
|
||||||
font-1 = "Symbola:size=10;1"
|
|
||||||
font-2 = FontAwesome5Free:style=Solid:size=8;0
|
|
||||||
;font-1 = "FontAwesome:fontformat=truetype:size=12;1"
|
|
||||||
|
|
||||||
|
|
||||||
modules-left = xmonad
|
|
||||||
modules-center = timerDisplay spotify mpd gitlab-pipeline player-mpv-tail date
|
|
||||||
modules-right = pulseaudio-control updates-arch pulseaudio filesystem memory cpu
|
|
||||||
; network-traffic
|
|
||||||
|
|
||||||
tray-position = right
|
|
||||||
tray-padding = 2
|
|
||||||
tray-maxsize = 16
|
|
||||||
tray-background = ${colors.background}
|
|
||||||
;tray-background = #0063ff
|
|
||||||
|
|
||||||
cursor-click = pointer
|
|
||||||
cursor-scroll = ns-resize
|
|
||||||
|
|
||||||
;; }}}
|
|
||||||
|
|
||||||
;; MODULES ----------------------------------------------- {{{
|
|
||||||
|
|
||||||
; show's currently focussed window, already contained in xmonad module
|
|
||||||
[module/xwindow]
|
|
||||||
type = internal/xwindow
|
|
||||||
label = %title:0:30:...%
|
|
||||||
|
|
||||||
[module/filesystem]
|
|
||||||
type = internal/fs
|
|
||||||
interval = 25
|
|
||||||
|
|
||||||
mount-0 = /
|
|
||||||
format-mounted = <label-mounted>
|
|
||||||
;format-mounted-prefix = "disk: "
|
|
||||||
;format-mounted-prefix-foreground = ${colors.foreground-alt}
|
|
||||||
format-mounted-prefix = "%{F#0fca42} %{F-} "
|
|
||||||
;format-mounted-prefix = " "
|
|
||||||
;format-mounted-underline = #0fca42
|
|
||||||
;label-mounted = %{F#0a81f5}%mountpoint%%{F-}: %percentage_used%%
|
|
||||||
label-mounted = %percentage_used%%
|
|
||||||
label-unmounted = %mountpoint% not mounted
|
|
||||||
label-unmounted-foreground = ${colors.foreground-alt}
|
|
||||||
|
|
||||||
|
|
||||||
[module/mpd]
|
|
||||||
type = internal/mpd
|
|
||||||
format-online = <label-song> <icon-prev> <icon-stop> <toggle> <icon-next>
|
|
||||||
|
|
||||||
icon-prev =
|
|
||||||
icon-stop =
|
|
||||||
icon-play =
|
|
||||||
icon-pause =
|
|
||||||
icon-next =
|
|
||||||
|
|
||||||
label-song-maxlen = 25
|
|
||||||
label-song-ellipsis = true
|
|
||||||
|
|
||||||
|
|
||||||
[module/cpu]
|
|
||||||
type = internal/cpu
|
|
||||||
interval = 2
|
|
||||||
;format-prefix = "cpu: "
|
|
||||||
;format-prefix-foreground = ${colors.foreground-alt}
|
|
||||||
format-prefix = "%{F#f9a000} %{F-} "
|
|
||||||
;format-prefix = " "
|
|
||||||
#format-underline = #f9a000
|
|
||||||
label = %percentage:2%%
|
|
||||||
|
|
||||||
[module/memory]
|
|
||||||
type = internal/memory
|
|
||||||
interval = 2
|
|
||||||
;format-prefix = "mem: "
|
|
||||||
;format-prefix-foreground = ${colors.foreground-alt}
|
|
||||||
format-prefix = "%{F#0a6cf5} %{F-} "
|
|
||||||
;format-prefix = " "
|
|
||||||
#format-underline = #0a6cf5
|
|
||||||
label = %percentage_used%%
|
|
||||||
|
|
||||||
[module/date]
|
|
||||||
type = internal/date
|
|
||||||
interval = 5
|
|
||||||
date = %a %d-%m-%y
|
|
||||||
date-alt = %d-%m-%Y
|
|
||||||
time = %H:%M
|
|
||||||
time-alt = %H:%M:%S
|
|
||||||
|
|
||||||
;format-prefix = "%{F#fbff8c} %{F-}"
|
|
||||||
;format-prefix = " "
|
|
||||||
;format-prefix-foreground = ${colors.foreground-alt}
|
|
||||||
;#format-underline = #4bffdc
|
|
||||||
#format-underline = #fbff8c
|
|
||||||
label = %time% | %date%
|
|
||||||
|
|
||||||
[module/xmonad]
|
|
||||||
type = custom/script
|
|
||||||
exec = xmonad-log
|
|
||||||
tail = true
|
|
||||||
|
|
||||||
|
|
||||||
[module/timerDisplay]
|
|
||||||
type = custom/script
|
|
||||||
exec = "[ -f ~/scripts/remainingTime.txt ] && head -n 1 scripts/remainingTime.txt"
|
|
||||||
interval = 1
|
|
||||||
|
|
||||||
|
|
||||||
;[module/gitlab-pipeline]
|
|
||||||
;type = custom/script
|
|
||||||
;exec = ~/scripts/fetch-running-pipelines.sh
|
|
||||||
;interval = 10
|
|
||||||
|
|
||||||
[module/info-pingrtt]
|
|
||||||
type = custom/script
|
|
||||||
exec = ~/.config/polybar/polybar-scripts/info-pingrtt.sh
|
|
||||||
interval = 10
|
|
||||||
|
|
||||||
|
|
||||||
[module/player-mpv-tail]
|
|
||||||
type = custom/script
|
|
||||||
exec = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -t 42 -c '#abb2bf'
|
|
||||||
tail = true
|
|
||||||
click-left = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p pause
|
|
||||||
click-middle = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p playlist-pos -1
|
|
||||||
click-right = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p playlist-pos +1
|
|
||||||
scroll-up = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p time-pos -10
|
|
||||||
scroll-down = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p time-pos +10
|
|
||||||
|
|
||||||
|
|
||||||
[module/network-traffic]
|
|
||||||
; configure interval, etc in script
|
|
||||||
type = custom/script
|
|
||||||
exec = ~/.config/polybar/polybar-scripts/network-traffic.sh
|
|
||||||
tail = true
|
|
||||||
|
|
||||||
|
|
||||||
[module/spotify]
|
|
||||||
type = custom/script
|
|
||||||
interval = 1
|
|
||||||
format = "<label> %{A1:dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous:}%{A-} %{A1:dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next:}%{A-}"
|
|
||||||
exec = python ~/.config/polybar/polybar-scripts/spotify_status.py -f '{artist} - {song} {play_pause}'
|
|
||||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause"
|
|
||||||
exec-if = "pgrep spotify"
|
|
||||||
#format-underline = #1db954
|
|
||||||
|
|
||||||
|
|
||||||
[module/updates-arch]
|
|
||||||
type = custom/script
|
|
||||||
exec = ~/.config/polybar/polybar-scripts/updates-arch-combined.sh
|
|
||||||
interval = 600
|
|
||||||
|
|
||||||
|
|
||||||
[module/pulseaudio-control]
|
|
||||||
type = custom/script
|
|
||||||
tail = true
|
|
||||||
label = %output%
|
|
||||||
|
|
||||||
click-right = exec pavucontrol &
|
|
||||||
exec = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash listen
|
|
||||||
click-left = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash togmute
|
|
||||||
click-middle = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash next-sink
|
|
||||||
scroll-up = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash up
|
|
||||||
scroll-down = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash down
|
|
||||||
label-padding = 2
|
|
||||||
label-foreground = ${colors.foreground}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[global/wm]
|
|
||||||
margin-bottom = -7
|
|
|
@ -1,219 +0,0 @@
|
||||||
|
|
||||||
;==========================================================
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗
|
|
||||||
; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗
|
|
||||||
; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝
|
|
||||||
; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗
|
|
||||||
; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║
|
|
||||||
; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
|
|
||||||
;
|
|
||||||
; ; To learn more about how to configure Polybar
|
|
||||||
; go to https://github.com/polybar/polybar
|
|
||||||
;
|
|
||||||
; The README contains a lot of information
|
|
||||||
;
|
|
||||||
;==========================================================
|
|
||||||
|
|
||||||
|
|
||||||
;; Colors ------------------------------------------- {{{
|
|
||||||
|
|
||||||
[colors]
|
|
||||||
;background = ${xrdb:color0:#222}
|
|
||||||
;background = #bb282828
|
|
||||||
;background = #88282828
|
|
||||||
;background = #88282828
|
|
||||||
;background = #aa282c34
|
|
||||||
background = #ff282828
|
|
||||||
;background = #222
|
|
||||||
background-alt = #444
|
|
||||||
;foreground = ${xrdb:color7:#222}
|
|
||||||
foreground = #fbf1c7
|
|
||||||
foreground-alt = #ebdbb2
|
|
||||||
primary = #ffb52a
|
|
||||||
secondary = #e60053
|
|
||||||
alert = #bd2c40
|
|
||||||
|
|
||||||
;; }}}
|
|
||||||
|
|
||||||
;; Bar config ----------------------------------------- {{{
|
|
||||||
|
|
||||||
[global/wm]
|
|
||||||
margin-bottom = 0
|
|
||||||
|
|
||||||
[bar/main]
|
|
||||||
monitor = ${env:MONITOR:}
|
|
||||||
|
|
||||||
override-redirect = true
|
|
||||||
;wm-restack = xmonad
|
|
||||||
|
|
||||||
;width = 100%:-28
|
|
||||||
;height = 30
|
|
||||||
;offset-x = 14
|
|
||||||
;offset-y = 7
|
|
||||||
|
|
||||||
width = 100%
|
|
||||||
height = 30
|
|
||||||
offset-x = 0
|
|
||||||
offset-y = 0
|
|
||||||
|
|
||||||
radius = 0
|
|
||||||
|
|
||||||
locale = de_DE.UTF-8
|
|
||||||
|
|
||||||
enable-ipc = true
|
|
||||||
padding = 0
|
|
||||||
;; center centered modules on screen, not between other modules
|
|
||||||
fixed-center = true
|
|
||||||
|
|
||||||
separator = "%{F#aaa}|%{F-}"
|
|
||||||
separator-padding = 1
|
|
||||||
|
|
||||||
|
|
||||||
background = ${colors.background}
|
|
||||||
foreground = ${colors.foreground}
|
|
||||||
|
|
||||||
line-size = 3
|
|
||||||
line-color = #f00
|
|
||||||
|
|
||||||
border-size = 0
|
|
||||||
border-color = #00000000
|
|
||||||
|
|
||||||
padding-left = 0
|
|
||||||
padding-right = 2
|
|
||||||
|
|
||||||
module-margin-left = 0
|
|
||||||
module-margin-right = 0
|
|
||||||
|
|
||||||
;font-0 = fixed:pixelsize=10;2
|
|
||||||
;font-1 = unifont:fontformat=truetype:size=8:antialias=false;0
|
|
||||||
;font-2 = siji:pixelsize=10;1
|
|
||||||
;font-7 = NotoEmoji:size=7;
|
|
||||||
;font-7 = "JetBrainsMono Nerd Font:size=7"
|
|
||||||
;font-0 = "JetBrainsMono Nerd Font:fontformat=truetype:size=10;2"
|
|
||||||
;font-1 = "NotoEmoji:scale=10;1"
|
|
||||||
;font-0 = "JetbrainsMono Bold:size=10;2"
|
|
||||||
;font-0 = "JetbrainsMono:weight=medium:size=10;2"
|
|
||||||
;font-0 = "scientifica:size=10;2"
|
|
||||||
;font-0 = "Terminus (TTF):size=12;2"
|
|
||||||
font-0 = "cherry:size=12;2"
|
|
||||||
;font-0 = "cozette:size=10;2"
|
|
||||||
font-1 = "Symbola:size=8;1"
|
|
||||||
font-2 = "FontAwesome5Free:style=Solid:size=8;2"
|
|
||||||
font-3 = "Iosevka Nerd Font:size=10;2"
|
|
||||||
font-4 = "Symbola:size=9;2"
|
|
||||||
;font-1 = "FontAwesome:fontformat=truetype:size=12;1"
|
|
||||||
|
|
||||||
|
|
||||||
modules-left = xmonad
|
|
||||||
modules-center = timerDisplay spotify gitlab-pipeline player-mpv-tail time
|
|
||||||
modules-right = pulseaudio-control updates-arch gpuinfo filesystem memory cpu date
|
|
||||||
|
|
||||||
tray-position = ${env:TRAY_POSITION:right}
|
|
||||||
tray-padding = 2
|
|
||||||
tray-maxsize = 16
|
|
||||||
tray-background = ${colors.background}
|
|
||||||
|
|
||||||
cursor-click = pointer
|
|
||||||
cursor-scroll = ns-resize
|
|
||||||
|
|
||||||
;; }}}
|
|
||||||
|
|
||||||
;; MODULES ----------------------------------------------- {{{
|
|
||||||
|
|
||||||
|
|
||||||
[module/filesystem]
|
|
||||||
type = internal/fs
|
|
||||||
interval = 25
|
|
||||||
|
|
||||||
mount-0 = /
|
|
||||||
format-mounted = <label-mounted>
|
|
||||||
format-mounted-prefix = "%{F#8ec07c}%{F-} "
|
|
||||||
label-mounted = %percentage_used%%
|
|
||||||
|
|
||||||
[module/cpu]
|
|
||||||
type = internal/cpu
|
|
||||||
interval = 2
|
|
||||||
format-prefix = "%{A1:~/.config/polybar/polybar-scripts/toggle_gpuinfo_window.sh 'top':}%{F#fe8019}%{F-} %{A}"
|
|
||||||
label = %percentage:2%%
|
|
||||||
click-left = ""
|
|
||||||
|
|
||||||
[module/memory]
|
|
||||||
type = internal/memory
|
|
||||||
interval = 2
|
|
||||||
format-prefix = "%{F#83a598}%{F-} "
|
|
||||||
label = %percentage_used%%
|
|
||||||
|
|
||||||
[module/date]
|
|
||||||
type = internal/date
|
|
||||||
interval = 500
|
|
||||||
date = %a, %d.%m.%Y
|
|
||||||
label = "%date%"
|
|
||||||
|
|
||||||
[module/time]
|
|
||||||
type = internal/date
|
|
||||||
interval = 1
|
|
||||||
time = %H:%M:%S
|
|
||||||
label = "%time%"
|
|
||||||
|
|
||||||
[module/xmonad]
|
|
||||||
type = custom/script
|
|
||||||
exec = "~/.config/polybar/polybar-scripts/xmonad-status.sh"
|
|
||||||
label = " %output%"
|
|
||||||
tail = true
|
|
||||||
|
|
||||||
[module/timerDisplay]
|
|
||||||
type = custom/script
|
|
||||||
exec = "[ -f ~/scripts/remainingTime.txt ] && head -n 1 scripts/remainingTime.txt"
|
|
||||||
interval = 1
|
|
||||||
|
|
||||||
[module/player-mpv-tail]
|
|
||||||
type = custom/script
|
|
||||||
exec = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -t 42 -c '#8ec07c'
|
|
||||||
tail = true
|
|
||||||
click-left = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p pause
|
|
||||||
click-middle = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p playlist-pos -1
|
|
||||||
click-right = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p playlist-pos +1
|
|
||||||
scroll-up = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p time-pos -10
|
|
||||||
scroll-down = ~/.config/polybar/polybar-scripts/player-mpv-tail.py -p time-pos +10
|
|
||||||
|
|
||||||
|
|
||||||
[module/network-traffic]
|
|
||||||
; configure interval, etc in script
|
|
||||||
type = custom/script
|
|
||||||
exec = ~/.config/polybar/polybar-scripts/network-traffic.sh
|
|
||||||
tail = true
|
|
||||||
|
|
||||||
[module/spotify]
|
|
||||||
type = custom/script
|
|
||||||
interval = 1
|
|
||||||
format = "<label> %{A1:dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous:}%{A-} %{A1:dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next:}%{A-}"
|
|
||||||
exec = python ~/.config/polybar/polybar-scripts/spotify_status.py -f '{artist} - {song} {play_pause}'
|
|
||||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause"
|
|
||||||
exec-if = "pgrep spotify"
|
|
||||||
|
|
||||||
[module/updates-arch]
|
|
||||||
type = custom/script
|
|
||||||
exec = ~/.config/polybar/polybar-scripts/updates-arch-combined.sh
|
|
||||||
interval = 600
|
|
||||||
|
|
||||||
|
|
||||||
[module/gpuinfo]
|
|
||||||
type = custom/script
|
|
||||||
exec = "sudo ~/scripts/gpuinfo.sh"
|
|
||||||
format = "%{F#d3869b}%{T3}%{T-}%{F-} <label>"
|
|
||||||
click-left = "~/.config/polybar/polybar-scripts/toggle_gpuinfo_window.sh 'sudo /home/leon/scripts/gpuinfo.sh --watch'"
|
|
||||||
interval = 2
|
|
||||||
|
|
||||||
[module/pulseaudio-control]
|
|
||||||
type = custom/script
|
|
||||||
tail = true
|
|
||||||
label-foreground = ${colors.foreground}
|
|
||||||
|
|
||||||
click-right = exec pavucontrol &
|
|
||||||
exec = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash listen
|
|
||||||
click-middle = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash togmute
|
|
||||||
click-left = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash next-sink
|
|
||||||
scroll-up = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash up
|
|
||||||
scroll-down = bash ~/.config/polybar/polybar-scripts/pulseaudio-control.bash down
|
|
|
@ -1,24 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
killall -q polybar
|
|
||||||
echo "---" | tee -a /tmp/polybar1.log /tmp/polybar2.log
|
|
||||||
|
|
||||||
|
|
||||||
outputs=$(xrandr --query | grep " connected" | cut -d" " -f1)
|
|
||||||
tray_output=HDMI-A-0
|
|
||||||
for m in $outputs; do
|
|
||||||
if [[ $m != "DisplayPort-1" ]]; then
|
|
||||||
tray_output=$m
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
for m in $outputs; do
|
|
||||||
export MONITOR=$m
|
|
||||||
export TRAY_POSITION=none
|
|
||||||
if [[ $m == "$tray_output" ]]; then
|
|
||||||
TRAY_POSITION=right
|
|
||||||
fi
|
|
||||||
MONITOR=$m polybar -r --config=/home/leon/.config/polybar/config.ini main & # >>/tmp/polybar1.log 2>&1 &
|
|
||||||
done
|
|
||||||
|
|
||||||
#polybar --config=/home/leon/.config/polybar/config.ini main >>/tmp/polybar1.log 2>&1 &
|
|
|
@ -1,19 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
HOST="google.de"
|
|
||||||
|
|
||||||
if ! ping=$(ping -n -c 1 -W 1 $HOST); then
|
|
||||||
echo "# ping failed"
|
|
||||||
else
|
|
||||||
rtt=$(echo "$ping" | sed -rn 's/.*time=([0-9]{1,})\.?[0-9]{0,} ms.*/\1/p')
|
|
||||||
|
|
||||||
if [ "$rtt" -lt 50 ]; then
|
|
||||||
icon="%{F#3cb703}#%{F-}"
|
|
||||||
elif [ "$rtt" -lt 150 ]; then
|
|
||||||
icon="%{F#f9dd04}#%{F-}"
|
|
||||||
else
|
|
||||||
icon="%{F#d60606}#%{F-}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$icon $rtt ms"
|
|
||||||
fi
|
|
|
@ -1,63 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
print_bytes() {
|
|
||||||
if [ "$1" -eq 0 ] || [ "$1" -lt 1000 ]; then
|
|
||||||
bytes="0 kB/s"
|
|
||||||
elif [ "$1" -lt 1000000 ]; then
|
|
||||||
bytes="$(echo "scale=0;$1/1000" | bc -l ) kB/s"
|
|
||||||
else
|
|
||||||
bytes="$(echo "scale=1;$1/1000000" | bc -l ) MB/s"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$bytes"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_bit() {
|
|
||||||
if [ "$1" -eq 0 ] || [ "$1" -lt 10 ]; then
|
|
||||||
bit="0 B"
|
|
||||||
elif [ "$1" -lt 100 ]; then
|
|
||||||
bit="$(echo "scale=0;$1*8" | bc -l ) B"
|
|
||||||
elif [ "$1" -lt 100000 ]; then
|
|
||||||
bit="$(echo "scale=0;$1*8/1000" | bc -l ) K"
|
|
||||||
else
|
|
||||||
bit="$(echo "scale=1;$1*8/1000000" | bc -l ) M"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$bit"
|
|
||||||
}
|
|
||||||
|
|
||||||
INTERVAL=5
|
|
||||||
INTERFACES="enp0s31f6"
|
|
||||||
|
|
||||||
declare -A bytes
|
|
||||||
|
|
||||||
for interface in $INTERFACES; do
|
|
||||||
bytes[past_rx_$interface]="$(cat /sys/class/net/"$interface"/statistics/rx_bytes)"
|
|
||||||
bytes[past_tx_$interface]="$(cat /sys/class/net/"$interface"/statistics/tx_bytes)"
|
|
||||||
done
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
down=0
|
|
||||||
up=0
|
|
||||||
|
|
||||||
for interface in $INTERFACES; do
|
|
||||||
bytes[now_rx_$interface]="$(cat /sys/class/net/"$interface"/statistics/rx_bytes)"
|
|
||||||
bytes[now_tx_$interface]="$(cat /sys/class/net/"$interface"/statistics/tx_bytes)"
|
|
||||||
|
|
||||||
bytes_down=$((((${bytes[now_rx_$interface]} - ${bytes[past_rx_$interface]})) / INTERVAL))
|
|
||||||
bytes_up=$((((${bytes[now_tx_$interface]} - ${bytes[past_tx_$interface]})) / INTERVAL))
|
|
||||||
|
|
||||||
down=$(((( "$down" + "$bytes_down" ))))
|
|
||||||
up=$(((( "$up" + "$bytes_up" ))))
|
|
||||||
|
|
||||||
bytes[past_rx_$interface]=${bytes[now_rx_$interface]}
|
|
||||||
bytes[past_tx_$interface]=${bytes[now_tx_$interface]}
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "%{F#f00} %{F-}$(print_bytes $down) %{F#0f0} %{F-}$(print_bytes $up)"
|
|
||||||
#echo "D: $(print_bytes $down) U: $(print_bytes $up)"
|
|
||||||
#echo "Download: $(print_bytes $down) / Upload: $(print_bytes $up)"
|
|
||||||
# echo "Download: $(print_bit $down) / Upload: $(print_bit $up)"
|
|
||||||
|
|
||||||
sleep $INTERVAL
|
|
||||||
done
|
|
|
@ -1,148 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import socket
|
|
||||||
import json
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
def get_property_cmd(property, request_id=None):
|
|
||||||
cmd = {'command': ['get_property', property]}
|
|
||||||
if isinstance(request_id, int):
|
|
||||||
cmd['request_id'] = request_id
|
|
||||||
return (json.dumps(cmd) + '\n').encode('utf-8')
|
|
||||||
|
|
||||||
def update_property(property, get_new_value):
|
|
||||||
client.send(get_property_cmd(property))
|
|
||||||
msg = client.recv(BUFSIZE).decode('utf-8')
|
|
||||||
value = get_new_value(msg)
|
|
||||||
cmd = {'command': ['set_property', property, value]}
|
|
||||||
client.send((json.dumps(cmd) + '\n').encode('utf-8'))
|
|
||||||
|
|
||||||
MPV_SOCKET = '/tmp/mpvsocket'
|
|
||||||
BUFSIZE = 1024
|
|
||||||
METADATA_CMD = get_property_cmd('filtered-metadata', 1)
|
|
||||||
OBSERVE_METADATA_CMD = b'{ "command": ["observe_property", 1, "filtered-metadata"] }\n'
|
|
||||||
MEDIA_TITLE_CMD = get_property_cmd('media-title', 2)
|
|
||||||
PERCENT_POS_CMD = get_property_cmd('percent-pos', 3)
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('-t', '--truncate', metavar='N', type=int, help='truncate output to N characters')
|
|
||||||
parser.add_argument('-c', '--color', default='#fff', metavar='C', help='set color of underline (progress bar)')
|
|
||||||
parser.add_argument('-p', '--property', choices=['pause', 'time-pos', 'playlist-pos'], help='update mpv property and exit')
|
|
||||||
parser.add_argument('args', nargs=argparse.REMAINDER)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
if args.property:
|
|
||||||
try:
|
|
||||||
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
||||||
client.connect(MPV_SOCKET)
|
|
||||||
except (FileNotFoundError, ConnectionRefusedError):
|
|
||||||
raise RuntimeError('Failed connecting to mpv socket.')
|
|
||||||
|
|
||||||
if args.property == 'pause':
|
|
||||||
update_property('pause', lambda msg: not json.loads(msg)['data'])
|
|
||||||
elif args.property in ['time-pos', 'playlist-pos']:
|
|
||||||
update_property(args.property, lambda msg: json.loads(msg)['data'] + int(args.args[0]))
|
|
||||||
|
|
||||||
client.close()
|
|
||||||
exit()
|
|
||||||
|
|
||||||
import time
|
|
||||||
import sys
|
|
||||||
from threading import Thread
|
|
||||||
|
|
||||||
def first_value(data, keys):
|
|
||||||
for key in keys:
|
|
||||||
value = data.get(key)
|
|
||||||
if value:
|
|
||||||
return value
|
|
||||||
|
|
||||||
def maybe_truncate(text):
|
|
||||||
limit = args.truncate
|
|
||||||
return (text[:limit - 1] + '…') if limit and len(text) > limit else text
|
|
||||||
|
|
||||||
def puts(output='', pos=0):
|
|
||||||
if pos > 0:
|
|
||||||
output = f'%{{u{args.color}}}%{{+u}}{output[0:pos]}%{{-u}}{output[pos:len(output)]}'
|
|
||||||
sys.stdout.write(output + '\n')
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
def create_client():
|
|
||||||
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
client.connect(MPV_SOCKET)
|
|
||||||
client.send(METADATA_CMD)
|
|
||||||
client.send(OBSERVE_METADATA_CMD)
|
|
||||||
Thread(target=percent_pos_sender, args=[client]).start()
|
|
||||||
break
|
|
||||||
except (FileNotFoundError, ConnectionRefusedError):
|
|
||||||
time.sleep(1)
|
|
||||||
return client
|
|
||||||
|
|
||||||
def parse_msg(msg):
|
|
||||||
messages = msg.decode('utf-8').split('\n')
|
|
||||||
not_empty = filter(lambda s: s, messages)
|
|
||||||
parsed = map(lambda m: json.loads(m), not_empty)
|
|
||||||
return list(parsed)
|
|
||||||
|
|
||||||
def format_data(data):
|
|
||||||
artist = first_value(data, ['Artist', 'Album_Artist']) or ''
|
|
||||||
title = first_value(data, ['Title', 'icy-title']) or ''
|
|
||||||
not_empty = filter(lambda d: d, [artist.strip(), title.strip()])
|
|
||||||
return ' - '.join(not_empty)
|
|
||||||
|
|
||||||
def percent_pos_sender(client):
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
time.sleep(1)
|
|
||||||
client.send(PERCENT_POS_CMD)
|
|
||||||
except BrokenPipeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
client = create_client()
|
|
||||||
current_output = ''
|
|
||||||
current_pos = 0
|
|
||||||
while True:
|
|
||||||
msg = client.recv(BUFSIZE)
|
|
||||||
|
|
||||||
# If connection is broken
|
|
||||||
if len(msg) == 0:
|
|
||||||
current_output = ''
|
|
||||||
current_pos = 0
|
|
||||||
puts()
|
|
||||||
time.sleep(1)
|
|
||||||
client = create_client()
|
|
||||||
continue
|
|
||||||
|
|
||||||
for m in parse_msg(msg):
|
|
||||||
data = m.get('data')
|
|
||||||
|
|
||||||
if m.get('event') == 'seek':
|
|
||||||
client.send(PERCENT_POS_CMD)
|
|
||||||
|
|
||||||
# 'filtered-metadata' event or response
|
|
||||||
elif (m.get('id') == 1 or m.get('request_id') == 1) and isinstance(data, dict):
|
|
||||||
text = format_data(data)
|
|
||||||
if text:
|
|
||||||
output = maybe_truncate(text)
|
|
||||||
if output != current_output:
|
|
||||||
current_output = output
|
|
||||||
puts(output)
|
|
||||||
client.send(PERCENT_POS_CMD)
|
|
||||||
else:
|
|
||||||
client.send(MEDIA_TITLE_CMD)
|
|
||||||
|
|
||||||
# 'media-title' response
|
|
||||||
elif m.get('request_id') == 2:
|
|
||||||
current_output = maybe_truncate(data)
|
|
||||||
puts(current_output)
|
|
||||||
client.send(PERCENT_POS_CMD)
|
|
||||||
|
|
||||||
# 'percent-pos' response
|
|
||||||
elif m.get('request_id') == 3 and isinstance(data, float):
|
|
||||||
length = len(current_output)
|
|
||||||
pos = round(length / 100 * data)
|
|
||||||
if pos != current_pos:
|
|
||||||
current_pos = pos
|
|
||||||
puts(current_output, pos)
|
|
||||||
|
|
|
@ -1,353 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
##################################################################
|
|
||||||
# Polybar Pulseaudio Control #
|
|
||||||
# https://github.com/marioortizmanero/polybar-pulseaudio-control #
|
|
||||||
##################################################################
|
|
||||||
|
|
||||||
# Script configuration (more info in the README)
|
|
||||||
OSD="no" # On Screen Display message for KDE if enabled
|
|
||||||
INC=2 # Increment when lowering/rising the volume
|
|
||||||
MAX_VOL=130 # Maximum volume
|
|
||||||
AUTOSYNC="yes" # All programs have the same volume if enabled
|
|
||||||
VOLUME_ICONS=("🔈 " "🔉 " "🔊 ")
|
|
||||||
MUTED_ICON=" " # Muted volume icon
|
|
||||||
MUTED_COLOR="%{F#6b6b6b}" # Color when the audio is muted
|
|
||||||
NOTIFICATIONS="no" # Notifications when switching sinks if enabled
|
|
||||||
#SINK_ICON="🔈 " # The default sink icon if a custom one isn't found
|
|
||||||
SINK_ICON=""
|
|
||||||
|
|
||||||
# Blacklist of PulseAudio sink names when switching between them. To obtain
|
|
||||||
# the names of your active sinks, use `pactl list sinks short`.
|
|
||||||
SINK_BLACKLIST=(
|
|
||||||
"alsa_output.pci-0000_00_1f.3.iec958-stereo"
|
|
||||||
"alsa_output.pci-0000_28_00.4.iec958-stereo"
|
|
||||||
"alsa_output.pci-0000_26_00.1.hdmi-stereo-extra2"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Maps PulseAudio sink names to human-readable names
|
|
||||||
declare -A SINK_NICKNAMES
|
|
||||||
SINK_NICKNAMES["alsa_output.usb-Native_Instruments_Komplete_Audio_6_77316682-00.analog-surround-21"]="📢"
|
|
||||||
SINK_NICKNAMES["alsa_output.usb-Fujitsu_UC_C_USB_Value_Headset_Fujitsu_UC_C_USB_Value_Headset-00.analog-stereo"]="🎧"
|
|
||||||
|
|
||||||
|
|
||||||
# Environment & global constants for the script
|
|
||||||
LANGUAGE=en_US # Some calls depend on English outputs of pactl
|
|
||||||
END_COLOR="%{F-}"
|
|
||||||
|
|
||||||
|
|
||||||
# Saves the currently default sink into a variable named `curSink`. It will
|
|
||||||
# return an error code when pulseaudio isn't running.
|
|
||||||
function getCurSink() {
|
|
||||||
if ! pulseaudio --check; then return 1; fi
|
|
||||||
curSink=$(pacmd list-sinks | awk '/\* index:/{print $3}')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Saves the sink passed by parameter's volume into a variable named `curVol`.
|
|
||||||
function getCurVol() {
|
|
||||||
curVol=$(pacmd list-sinks | grep -A 15 'index: '"$1"'' | grep 'volume:' | grep -E -v 'base volume:' | awk -F : '{print $3}' | grep -o -P '.{0,3}%' | sed 's/.$//' | tr -d ' ')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Saves the name of the sink passed by parameter into a variable named
|
|
||||||
# `sinkName`.
|
|
||||||
function getSinkName() {
|
|
||||||
sinkName=$(pactl list sinks short | awk -v sink="$1" '{ if ($1 == sink) {print $2} }')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Saves the name to be displayed for the sink passed by parameter into a
|
|
||||||
# variable called `nickname`.
|
|
||||||
# If a mapping for the sink name exists, that is used. Otherwise, the string
|
|
||||||
# "Sink #<index>" is used.
|
|
||||||
function getNickname() {
|
|
||||||
getSinkName "$1"
|
|
||||||
if [ -n "${SINK_NICKNAMES[$sinkName]}" ]; then
|
|
||||||
nickname="${SINK_NICKNAMES[$sinkName]}"
|
|
||||||
else
|
|
||||||
nickname="Sink #$1"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Saves the status of the sink passed by parameter into a variable named
|
|
||||||
# `isMuted`.
|
|
||||||
function getIsMuted() {
|
|
||||||
isMuted=$(pacmd list-sinks | grep -A 15 "index: $1" | awk '/muted/{print $2}')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Saves all the sink inputs of the sink passed by parameter into a string
|
|
||||||
# named `sinkInputs`.
|
|
||||||
function getSinkInputs() {
|
|
||||||
sinkInputs=$(pacmd list-sink-inputs | grep -B 4 "sink: $1 " | awk '/index:/{print $2}')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function volUp() {
|
|
||||||
# Obtaining the current volume from pacmd into $curVol.
|
|
||||||
if ! getCurSink; then
|
|
||||||
echo "PulseAudio not running"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
getCurVol "$curSink"
|
|
||||||
local maxLimit=$((MAX_VOL - INC))
|
|
||||||
|
|
||||||
# Checking the volume upper bounds so that if MAX_VOL was 100% and the
|
|
||||||
# increase percentage was 3%, a 99% volume would top at 100% instead
|
|
||||||
# of 102%. If the volume is above the maximum limit, nothing is done.
|
|
||||||
if [ "$curVol" -le "$MAX_VOL" ] && [ "$curVol" -ge "$maxLimit" ]; then
|
|
||||||
pactl set-sink-volume "$curSink" "$MAX_VOL%"
|
|
||||||
elif [ "$curVol" -lt "$maxLimit" ]; then
|
|
||||||
pactl set-sink-volume "$curSink" "+$INC%"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $OSD = "yes" ]; then showOSD "$curSink"; fi
|
|
||||||
if [ $AUTOSYNC = "yes" ]; then volSync; fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function volDown() {
|
|
||||||
# Pactl already handles the volume lower bounds so that negative values
|
|
||||||
# are ignored.
|
|
||||||
if ! getCurSink; then
|
|
||||||
echo "PulseAudio not running"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
pactl set-sink-volume "$curSink" "-$INC%"
|
|
||||||
|
|
||||||
if [ $OSD = "yes" ]; then showOSD "$curSink"; fi
|
|
||||||
if [ $AUTOSYNC = "yes" ]; then volSync; fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function volSync() {
|
|
||||||
if ! getCurSink; then
|
|
||||||
echo "PulseAudio not running"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
getSinkInputs "$curSink"
|
|
||||||
getCurVol "$curSink"
|
|
||||||
|
|
||||||
# Every output found in the active sink has their volume set to the
|
|
||||||
# current one. This will only be called if $AUTOSYNC is `yes`.
|
|
||||||
for each in $sinkInputs; do
|
|
||||||
pactl set-sink-input-volume "$each" "$curVol%"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function volMute() {
|
|
||||||
# Switch to mute/unmute the volume with pactl.
|
|
||||||
if ! getCurSink; then
|
|
||||||
echo "PulseAudio not running"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
if [ "$1" = "toggle" ]; then
|
|
||||||
getIsMuted "$curSink"
|
|
||||||
if [ "$isMuted" = "yes" ]; then
|
|
||||||
pactl set-sink-mute "$curSink" "no"
|
|
||||||
else
|
|
||||||
pactl set-sink-mute "$curSink" "yes"
|
|
||||||
fi
|
|
||||||
elif [ "$1" = "mute" ]; then
|
|
||||||
pactl set-sink-mute "$curSink" "yes"
|
|
||||||
elif [ "$1" = "unmute" ]; then
|
|
||||||
pactl set-sink-mute "$curSink" "no"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $OSD = "yes" ]; then showOSD "$curSink"; fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function nextSink() {
|
|
||||||
# The final sinks list, removing the blacklisted ones from the list of
|
|
||||||
# currently available sinks.
|
|
||||||
if ! getCurSink; then
|
|
||||||
echo "PulseAudio not running"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Obtaining a tuple of sink indexes after removing the blacklisted devices
|
|
||||||
# with their name.
|
|
||||||
sinks=()
|
|
||||||
local i=0
|
|
||||||
while read -r line; do
|
|
||||||
index=$(echo "$line" | cut -f1)
|
|
||||||
name=$(echo "$line" | cut -f2)
|
|
||||||
|
|
||||||
# If it's in the blacklist, continue the main loop. Otherwise, add
|
|
||||||
# it to the list.
|
|
||||||
for sink in "${SINK_BLACKLIST[@]}"; do
|
|
||||||
if [ "$sink" = "$name" ]; then
|
|
||||||
continue 2
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
sinks[$i]="$index"
|
|
||||||
i=$((i + 1))
|
|
||||||
done < <(pactl list short sinks)
|
|
||||||
|
|
||||||
# If the resulting list is empty, nothing is done
|
|
||||||
if [ ${#sinks[@]} -eq 0 ]; then return; fi
|
|
||||||
|
|
||||||
# If the current sink is greater or equal than last one, pick the first
|
|
||||||
# sink in the list. Otherwise just pick the next sink avaliable.
|
|
||||||
local newSink
|
|
||||||
if [ "$curSink" -ge "${sinks[-1]}" ]; then
|
|
||||||
newSink=${sinks[0]}
|
|
||||||
else
|
|
||||||
for sink in "${sinks[@]}"; do
|
|
||||||
if [ "$curSink" -lt "$sink" ]; then
|
|
||||||
newSink=$sink
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# The new sink is set
|
|
||||||
pacmd set-default-sink "$newSink"
|
|
||||||
|
|
||||||
# Move all audio threads to new sink
|
|
||||||
local inputs=$(pactl list short sink-inputs | cut -f 1)
|
|
||||||
for i in $inputs; do
|
|
||||||
pacmd move-sink-input "$i" "$newSink"
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ $NOTIFICATIONS = "yes" ]; then
|
|
||||||
getNickname "$newSink"
|
|
||||||
notify-send "PulseAudio" "Changed output to $nickname" --icon=audio-headphones-symbolic &
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# This function assumes that PulseAudio is already running. It only supports
|
|
||||||
# KDE OSDs for now. It will show a system message with the status of the
|
|
||||||
# sink passed by parameter, or the currently active one by default.
|
|
||||||
function showOSD() {
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
curSink="$1"
|
|
||||||
else
|
|
||||||
getCurSink
|
|
||||||
fi
|
|
||||||
getCurVol "$curSink"
|
|
||||||
getIsMuted "$curSink"
|
|
||||||
qdbus org.kde.kded /modules/kosd showVolume "$curVol" "$isMuted"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function listen() {
|
|
||||||
local firstRun=0
|
|
||||||
|
|
||||||
# Listen for changes and immediately create new output for the bar.
|
|
||||||
# This is faster than having the script on an interval.
|
|
||||||
LANG=$LANGUAGE pactl subscribe 2>/dev/null | {
|
|
||||||
while true; do
|
|
||||||
{
|
|
||||||
# If this is the first time just continue and print the current
|
|
||||||
# state. Otherwise wait for events. This is to prevent the
|
|
||||||
# module being empty until an event occurs.
|
|
||||||
if [ $firstRun -eq 0 ]; then
|
|
||||||
firstRun=1
|
|
||||||
else
|
|
||||||
read -r event || break
|
|
||||||
# Avoid double events
|
|
||||||
if ! echo "$event" | grep -e "on card" -e "on sink" -e "on server"; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
} &>/dev/null
|
|
||||||
output
|
|
||||||
done
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function output() {
|
|
||||||
if ! getCurSink; then
|
|
||||||
echo "PulseAudio not running"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
getCurVol "$curSink"
|
|
||||||
getIsMuted "$curSink"
|
|
||||||
|
|
||||||
# Fixed volume icons over max volume
|
|
||||||
local iconsLen=${#VOLUME_ICONS[@]}
|
|
||||||
if [ "$iconsLen" -ne 0 ]; then
|
|
||||||
local volSplit=$((MAX_VOL / iconsLen))
|
|
||||||
for i in $(seq 1 "$iconsLen"); do
|
|
||||||
if [ $((i * volSplit)) -ge "$curVol" ]; then
|
|
||||||
volIcon="${VOLUME_ICONS[$((i-1))]}"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
volIcon=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
getNickname "$curSink"
|
|
||||||
|
|
||||||
# Showing the formatted message
|
|
||||||
if [ "$isMuted" = "yes" ]; then
|
|
||||||
echo "${MUTED_COLOR}${nickname} ${curVol}%${END_COLOR}"
|
|
||||||
else
|
|
||||||
echo "${nickname} ${curVol}%"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function usage() {
|
|
||||||
echo "Usage: $0 ACTION"
|
|
||||||
echo ""
|
|
||||||
echo "Actions:"
|
|
||||||
echo " help display this help and exit"
|
|
||||||
echo " output print the PulseAudio status once"
|
|
||||||
echo " listen listen for changes in PulseAudio to automatically"
|
|
||||||
echo " update this script's output"
|
|
||||||
echo " up, down increase or decrease the default sink's volume"
|
|
||||||
echo " mute, unmute mute or unmute the default sink's audio"
|
|
||||||
echo " togmute switch between muted and unmuted"
|
|
||||||
echo " next-sink switch to the next available sink"
|
|
||||||
echo " sync synchronize all the output streams volume to"
|
|
||||||
echo " the be the same as the current sink's volume"
|
|
||||||
echo ""
|
|
||||||
echo "Author:"
|
|
||||||
echo " Mario O. M."
|
|
||||||
echo "More info on GitHub:"
|
|
||||||
echo " https://github.com/marioortizmanero/polybar-pulseaudio-control"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
up)
|
|
||||||
volUp
|
|
||||||
;;
|
|
||||||
down)
|
|
||||||
volDown
|
|
||||||
;;
|
|
||||||
togmute)
|
|
||||||
volMute toggle
|
|
||||||
;;
|
|
||||||
mute)
|
|
||||||
volMute mute
|
|
||||||
;;
|
|
||||||
unmute)
|
|
||||||
volMute unmute
|
|
||||||
;;
|
|
||||||
sync)
|
|
||||||
volSync
|
|
||||||
;;
|
|
||||||
listen)
|
|
||||||
listen
|
|
||||||
;;
|
|
||||||
next-sink)
|
|
||||||
nextSink
|
|
||||||
;;
|
|
||||||
output)
|
|
||||||
output
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
usage
|
|
||||||
;;
|
|
||||||
esac
|
|
|
@ -1,123 +0,0 @@
|
||||||
#!/bin/python
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import dbus
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument(
|
|
||||||
'-t',
|
|
||||||
'--trunclen',
|
|
||||||
type=int,
|
|
||||||
metavar='trunclen'
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
'-f',
|
|
||||||
'--format',
|
|
||||||
type=str,
|
|
||||||
metavar='custom format',
|
|
||||||
dest='custom_format'
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
'-p',
|
|
||||||
'--playpause',
|
|
||||||
type=str,
|
|
||||||
metavar='play-pause indicator',
|
|
||||||
dest='play_pause'
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
'--font',
|
|
||||||
type=str,
|
|
||||||
metavar='the index of the font to use for the main label',
|
|
||||||
dest='font'
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
'--playpause-font',
|
|
||||||
type=str,
|
|
||||||
metavar='the index of the font to use to display the playpause indicator',
|
|
||||||
dest='play_pause_font'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
def fix_string(string):
|
|
||||||
# corrects encoding for the python version used
|
|
||||||
if sys.version_info.major == 3:
|
|
||||||
return string
|
|
||||||
else:
|
|
||||||
return string.encode('utf-8')
|
|
||||||
|
|
||||||
# Default parameters
|
|
||||||
output = fix_string(u'{play_pause} {artist}: {song}')
|
|
||||||
trunclen = 25
|
|
||||||
play_pause = fix_string(u'\u25B6,\u23F8') # first character is play, second is paused
|
|
||||||
|
|
||||||
label_with_font = '%{{T{font}}}{label}%{{T-}}'
|
|
||||||
font = args.font
|
|
||||||
play_pause_font = args.play_pause_font
|
|
||||||
|
|
||||||
# parameters can be overwritten by args
|
|
||||||
if args.trunclen is not None:
|
|
||||||
trunclen = args.trunclen
|
|
||||||
if args.custom_format is not None:
|
|
||||||
output = args.custom_format
|
|
||||||
if args.play_pause is not None:
|
|
||||||
play_pause = args.play_pause
|
|
||||||
|
|
||||||
try:
|
|
||||||
session_bus = dbus.SessionBus()
|
|
||||||
spotify_bus = session_bus.get_object(
|
|
||||||
'org.mpris.MediaPlayer2.spotify',
|
|
||||||
'/org/mpris/MediaPlayer2'
|
|
||||||
)
|
|
||||||
|
|
||||||
spotify_properties = dbus.Interface(
|
|
||||||
spotify_bus,
|
|
||||||
'org.freedesktop.DBus.Properties'
|
|
||||||
)
|
|
||||||
|
|
||||||
metadata = spotify_properties.Get('org.mpris.MediaPlayer2.Player', 'Metadata')
|
|
||||||
status = spotify_properties.Get('org.mpris.MediaPlayer2.Player', 'PlaybackStatus')
|
|
||||||
|
|
||||||
# Handle play/pause label
|
|
||||||
|
|
||||||
play_pause = play_pause.split(',')
|
|
||||||
|
|
||||||
if status == 'Playing':
|
|
||||||
play_pause = play_pause[0]
|
|
||||||
elif status == 'Paused':
|
|
||||||
play_pause = play_pause[1]
|
|
||||||
else:
|
|
||||||
play_pause = str()
|
|
||||||
|
|
||||||
if play_pause_font:
|
|
||||||
play_pause = label_with_font.format(font=play_pause_font, label=play_pause)
|
|
||||||
|
|
||||||
# Handle main label
|
|
||||||
|
|
||||||
artist = fix_string(metadata['xesam:artist'][0]) if metadata['xesam:artist'] else ''
|
|
||||||
song = fix_string(metadata['xesam:title']) if metadata['xesam:title'] else ''
|
|
||||||
album = fix_string(metadata['xesam:album']) if metadata['xesam:album'] else ''
|
|
||||||
|
|
||||||
if not artist and not song and not album:
|
|
||||||
print('')
|
|
||||||
else:
|
|
||||||
if len(song) > trunclen:
|
|
||||||
song = song[0:trunclen]
|
|
||||||
song += '...'
|
|
||||||
if ('(' in song) and (')' not in song):
|
|
||||||
song += ')'
|
|
||||||
|
|
||||||
if font:
|
|
||||||
artist = label_with_font.format(font=font, label=artist)
|
|
||||||
song = label_with_font.format(font=font, label=song)
|
|
||||||
album = label_with_font.format(font=font, label=album)
|
|
||||||
|
|
||||||
print(output.format(artist=artist, song=song, play_pause=play_pause, album=album))
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
if isinstance(e, dbus.exceptions.DBusException):
|
|
||||||
print('')
|
|
||||||
else:
|
|
||||||
print(e)
|
|