Add BetterDiscord themes and plugin configurations for customization
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
body {
|
||||
--custom-guild-sidebar-width: 500px !important;
|
||||
--user-area-width: 450px !important;
|
||||
--custom-member-list-width: 550px !important;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"general": {
|
||||
"download": true,
|
||||
"emoteMenu": true,
|
||||
"hideEmojiMenu": false,
|
||||
"modifiers": true,
|
||||
"animateOnHover": false
|
||||
},
|
||||
"categories": {
|
||||
"twitchglobal": true,
|
||||
"twitchsubscriber": false,
|
||||
"frankerfacez": true,
|
||||
"bttv": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": "1.13.8",
|
||||
"drawerStates": {
|
||||
"settings": {
|
||||
"addons": true,
|
||||
"store": true,
|
||||
"customcss": true,
|
||||
"editor": true,
|
||||
"window": true,
|
||||
"developer": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"PluginRepo": false,
|
||||
"BDFDB": true,
|
||||
"GameActivityToggle": true,
|
||||
"ReadAllNotificationsButton": true,
|
||||
"ThemeRepo": false,
|
||||
"ZeresPluginLibrary": true,
|
||||
"AuroraGSI": false,
|
||||
"BetterFormattingRedux": true,
|
||||
"BetterRoleColors": false,
|
||||
"ShowConnections": true,
|
||||
"ThemeSettings": false,
|
||||
"VoiceEvents": false,
|
||||
"WhoReacted": true,
|
||||
"serverthemes": false,
|
||||
"betterdiscord-google-fonts": true,
|
||||
"PronounDB": false,
|
||||
"VoiceActivity": true,
|
||||
"InMyVoice": true,
|
||||
"VoiceChatNotifications": true,
|
||||
"AvatarHover": true,
|
||||
"BetterChatNames": true,
|
||||
"HideServersChannelsRedux": false,
|
||||
"ShowBadgesInChat": true,
|
||||
"removeTrackingURL": false,
|
||||
"BetterGuildTooltip": true,
|
||||
"Translator": true,
|
||||
"ChannelsBadges": false,
|
||||
"DisplayUsernames": true,
|
||||
"enhancecodeblocks": false,
|
||||
"StickerEmojiPreview": true,
|
||||
"WiderUserArea": true,
|
||||
"Animations": false,
|
||||
"ServerDetails": true,
|
||||
"ActivityIcons": false,
|
||||
"PermissionsViewer": true,
|
||||
"ChannelPermissions": false,
|
||||
"BetterChannelList": false,
|
||||
"ChannelTabs": false,
|
||||
"NotificationSounds": true,
|
||||
"MoreRoleColors": true,
|
||||
"BetterAnimations": false,
|
||||
"DoNotTrack": true,
|
||||
"ViewProfilePicture": true
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"general": {
|
||||
"voiceDisconnect": false,
|
||||
"showToasts": true,
|
||||
"mediaKeys": true,
|
||||
"bdContextMenu": true,
|
||||
"themeAttributes": true,
|
||||
"notificationPosition": "top-right",
|
||||
"notificationEnabled": true
|
||||
},
|
||||
"addons": {
|
||||
"addonErrors": true,
|
||||
"editAction": "detached",
|
||||
"checkForUpdates": true,
|
||||
"updateInterval": 4
|
||||
},
|
||||
"store": {
|
||||
"bdAddonStore": true,
|
||||
"alwaysEnable": false,
|
||||
"addonEmbeds": true
|
||||
},
|
||||
"customcss": {
|
||||
"customcss": true,
|
||||
"liveUpdate": true,
|
||||
"openAction": "settings"
|
||||
},
|
||||
"editor": {
|
||||
"theme": "system",
|
||||
"lineNumbers": true,
|
||||
"minimap": true,
|
||||
"hover": true,
|
||||
"quickSuggestions": true,
|
||||
"insertSpaces": false,
|
||||
"tabSize": 4,
|
||||
"fontSize": 14,
|
||||
"renderWhitespace": "selection"
|
||||
},
|
||||
"window": {
|
||||
"transparency": true,
|
||||
"removeMinimumSize": false,
|
||||
"frame": true,
|
||||
"inAppTrafficLights": false
|
||||
},
|
||||
"developer": {
|
||||
"debugLogs": false,
|
||||
"devTools": true,
|
||||
"debuggerHotkey": false,
|
||||
"reactDevTools": false,
|
||||
"inspectElement": false,
|
||||
"devToolsWarning": false,
|
||||
"recovery": true,
|
||||
"canary": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"Arindy": false,
|
||||
"FVUI": false,
|
||||
"Translucence": true
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"core-SimpleMarkdownWrapper": "46054",
|
||||
"core-React": "64700",
|
||||
"core-Dispatcher": "73153",
|
||||
"core-ReactSpring": "278420",
|
||||
"core-AccessibilityContext": "158954",
|
||||
"core-Tooltip": "397927",
|
||||
"core-contextmenu-Actions": "442433",
|
||||
"core-commandmanager-appIcons": "664929",
|
||||
"core-settings-search": "368631",
|
||||
"0PluginLibrary:1254924683": "64700",
|
||||
"0PluginLibrary:341512209": "64700",
|
||||
"0PluginLibrary:3695157183": "350535",
|
||||
"0PluginLibrary:1032993886": "117178",
|
||||
"0PluginLibrary:2508050256": "750506",
|
||||
"0PluginLibrary:3026836349": "158954",
|
||||
"0PluginLibrary:4136795093": "267102",
|
||||
"0PluginLibrary:3050996723": "652215",
|
||||
"0PluginLibrary:951786541": "158954",
|
||||
"0PluginLibrary:83147845": "64700",
|
||||
"0PluginLibrary:3075157097": "544028",
|
||||
"0PluginLibrary:377304194": "558179",
|
||||
"0PluginLibrary:2879910472": "46054",
|
||||
"BetterChatNames:1201": "967198",
|
||||
"BetterChatNames:1233": "309010",
|
||||
"BetterChatNames:1319": "166444",
|
||||
"BetterChatNames:1349": "742589",
|
||||
"BetterChatNames:1385": "415409",
|
||||
"BetterChatNames:1412": "232042",
|
||||
"BetterFormattingRedux:22226": "843472",
|
||||
"BetterFormattingRedux:22258": "111314",
|
||||
"BetterGuildTooltip:1392": "73153",
|
||||
"BetterGuildTooltip:1479": "311907",
|
||||
"BetterGuildTooltip:1803": "311907",
|
||||
"BetterGuildTooltip:1878": "485366",
|
||||
"BetterGuildTooltip:2014": "308528",
|
||||
"BetterGuildTooltip:2109": "647668",
|
||||
"0PluginLibrary:3508192550": "635071",
|
||||
"DoNotTrack:6603": "594061",
|
||||
"DoNotTrack:6630": "406935",
|
||||
"DoNotTrack:6659": "954571",
|
||||
"DoNotTrack:6693": "837921",
|
||||
"EnhanceCodeBlocks:3413228107": "278420",
|
||||
"EnhanceCodeBlocks:1829278509": "855522",
|
||||
"EnhanceCodeBlocks:1929428925": "28728",
|
||||
"EnhanceCodeBlocks:1078947860": "459127",
|
||||
"EnhanceCodeBlocks:1946862927": "102741",
|
||||
"EnhanceCodeBlocks:1082876702": "397927",
|
||||
"EnhanceCodeBlocks:1859630996": "158954",
|
||||
"EnhanceCodeBlocks:2928343028": "397927",
|
||||
"EnhanceCodeBlocks:3078982459": "453903",
|
||||
"EnhanceCodeBlocks:830998530": "103552",
|
||||
"InMyVoice:1637": "679740",
|
||||
"InMyVoice:1672": "931228",
|
||||
"InMyVoice:1864": "607567",
|
||||
"InMyVoice:1895": "635071",
|
||||
"InMyVoice:1919": "709066",
|
||||
"InMyVoice:1958": "311907",
|
||||
"MoreRoleColors:453": "481947",
|
||||
"MoreRoleColors:611": "147192",
|
||||
"MoreRoleColors:628": "288539",
|
||||
"MoreRoleColors:772": "311907",
|
||||
"MoreRoleColors:21476720": "613306",
|
||||
"MoreRoleColors:24485674": "485947",
|
||||
"MoreRoleColors:26065620": "320819",
|
||||
"MoreRoleColors:27696461": "709066",
|
||||
"PermissionsViewer:12806": "652215",
|
||||
"PermissionsViewer:12833": "820883",
|
||||
"PermissionsViewer:12870": "837921",
|
||||
"PermissionsViewer:12897": "985018",
|
||||
"PermissionsViewer:3028674": "773669",
|
||||
"PermissionsViewer:14663700": "997168",
|
||||
"PermissionsViewer:14698296": "707616",
|
||||
"PermissionsViewer:14725204": "949296",
|
||||
"PermissionsViewer:15024075": "183959",
|
||||
"PronounDB:2502": "311907",
|
||||
"PronounDB:2547": "311907",
|
||||
"StickerEmojiPreview:4460131": "151271",
|
||||
"StickerEmojiPreview:5010": "265690",
|
||||
"StickerEmojiPreview:5144": "499867",
|
||||
"StickerEmojiPreview:4461902": "338464",
|
||||
"StickerEmojiPreview:6543603": "265872",
|
||||
"StickerEmojiPreview:10469": "158954",
|
||||
"ViewProfilePicture:10993": "265690",
|
||||
"ViewProfilePicture:11127": "499867",
|
||||
"ViewProfilePicture:12451": "192308",
|
||||
"ViewProfilePicture:12492": "935462",
|
||||
"ViewProfilePicture:13508": "397927",
|
||||
"ViewProfilePicture:15403": "9578",
|
||||
"ViewProfilePicture:15425": "608214",
|
||||
"ViewProfilePicture:15619": "158954",
|
||||
"ViewProfilePicture:15639": "454290",
|
||||
"ViewProfilePicture:17226": "310784",
|
||||
"ViewProfilePicture:18000": "827734",
|
||||
"ViewProfilePicture:19610": "654107",
|
||||
"ViewProfilePicture:19993": "710016",
|
||||
"ViewProfilePicture:20235": "158954",
|
||||
"ViewProfilePicture:22447": "946356",
|
||||
"ViewProfilePicture:23582": "158954",
|
||||
"ViewProfilePicture:26590": "158954",
|
||||
"VoiceActivity:5346226": "311907",
|
||||
"VoiceActivity:5347121": "110574",
|
||||
"VoiceActivity:5408780": "701363",
|
||||
"VoiceActivity:5347431": "174279",
|
||||
"VoiceActivity:5347552": "652215",
|
||||
"VoiceActivity:525973814": "820659",
|
||||
"VoiceActivity:5347837": "714114",
|
||||
"VoiceActivity:434714749": "158954",
|
||||
"VoiceActivity:434714778": "83107",
|
||||
"VoiceActivity:434714908": "158954",
|
||||
"VoiceActivity:434715029": "158954",
|
||||
"VoiceActivity:434715159": "158954",
|
||||
"VoiceActivity:434715274": "158954",
|
||||
"VoiceActivity:5357596": "10862",
|
||||
"VoiceActivity:5357907": "976860",
|
||||
"core-SimpleMarkdown": "791332",
|
||||
"0BDFDB:3340963209": "287809",
|
||||
"BetterChatNames:1262": "976860",
|
||||
"0BDFDB:3538865044": "287809",
|
||||
"core-changelog-anchorClasses": "68380",
|
||||
"core-commandmanager-iconClasses": "382780",
|
||||
"core-commandmanager-builtInSeparatorClasses": "127461",
|
||||
"core-mdinstallcss-codeBlockStyles": "830412",
|
||||
"core-themeattributes-MessageComponent": "371741",
|
||||
"core-themeattributes-messageHook": "672341",
|
||||
"core-themeattributes-VoiceUserComponent": "481947",
|
||||
"core-themeattributes-ChatAvatar": "643204",
|
||||
"core-themeattributes-AvatarImg": "97808",
|
||||
"BetterChatNames:1263": "967198",
|
||||
"BetterChatNames:1295": "309010",
|
||||
"BetterChatNames:1324": "976860",
|
||||
"BetterChatNames:1381": "166444",
|
||||
"BetterChatNames:1411": "742589",
|
||||
"BetterChatNames:1447": "415409",
|
||||
"BetterChatNames:1474": "232042"
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"all": {
|
||||
"changeLogs": {
|
||||
"BDFDB": "4.4.6",
|
||||
"GameActivityToggle": "1.3.9",
|
||||
"NotificationSounds": "4.0.7",
|
||||
"PluginRepo": "2.6.0",
|
||||
"ReadAllNotificationsButton": "1.8.5",
|
||||
"ServerDetails": "1.3.4",
|
||||
"ShowBadgesInChat": "2.1.5",
|
||||
"ShowConnections": "1.3.2",
|
||||
"ThemeRepo": "2.6.0",
|
||||
"ThemeSettings": "9.9.9",
|
||||
"Translator": "2.7.9"
|
||||
},
|
||||
"choices": {
|
||||
"toastPosition": "right"
|
||||
},
|
||||
"general": {
|
||||
"shareData": true,
|
||||
"showToasts": true,
|
||||
"checkForUpdates": false,
|
||||
"showSupportBadges": true,
|
||||
"useChromium": false
|
||||
},
|
||||
"hashes": {
|
||||
"0BDFDB.data.json": "b7e1d2d9f648471712355e67b6df0df0208fe27b",
|
||||
"0BDFDB.raw.css": "edada1edc762888eebc5aa44e5b8c1baf2e60104"
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+8878
File diff suppressed because it is too large
Load Diff
+1848
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"settings": {
|
||||
"normalActivityIcons": true,
|
||||
"richPresenceIcons": true,
|
||||
"platformIcons": true,
|
||||
"listeningIcons": true,
|
||||
"watchingIcons": true
|
||||
},
|
||||
"currentVersionInfo": {
|
||||
"version": "1.4.11",
|
||||
"hasShownChangelog": true
|
||||
},
|
||||
"changelogVersion": "1.5.3"
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"settings": {
|
||||
"buttons": {
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"frames": [
|
||||
{
|
||||
"anim": "",
|
||||
"start": ""
|
||||
},
|
||||
{
|
||||
"anim": "",
|
||||
"start": ""
|
||||
},
|
||||
{
|
||||
"anim": "",
|
||||
"start": ""
|
||||
}
|
||||
],
|
||||
"page": 0
|
||||
},
|
||||
"delay": 0.1,
|
||||
"duration": 0.3,
|
||||
"enabled": true,
|
||||
"name": "slide-down-right",
|
||||
"page": 1,
|
||||
"selectors": "",
|
||||
"sequence": "fromLast",
|
||||
"timing": "linear"
|
||||
},
|
||||
"lists": {
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"frames": [
|
||||
{
|
||||
"anim": "",
|
||||
"start": ""
|
||||
},
|
||||
{
|
||||
"anim": "",
|
||||
"start": ""
|
||||
},
|
||||
{
|
||||
"anim": "",
|
||||
"start": ""
|
||||
}
|
||||
],
|
||||
"page": 2
|
||||
},
|
||||
"delay": "0.015",
|
||||
"duration": "0.01",
|
||||
"enabled": true,
|
||||
"name": "slide-down-right",
|
||||
"page": 1,
|
||||
"selectors": "",
|
||||
"sequence": "fromFirst",
|
||||
"timing": "linear"
|
||||
},
|
||||
"messages": {
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"frames": [
|
||||
{
|
||||
"anim": "",
|
||||
"start": ""
|
||||
},
|
||||
{
|
||||
"anim": "",
|
||||
"start": ""
|
||||
},
|
||||
{
|
||||
"anim": "",
|
||||
"start": ""
|
||||
}
|
||||
],
|
||||
"page": 0
|
||||
},
|
||||
"delay": 0.055,
|
||||
"duration": 0.3,
|
||||
"enabled": true,
|
||||
"limit": 30,
|
||||
"name": "slide-down-right",
|
||||
"page": 2,
|
||||
"sending": {
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"frames": [
|
||||
{
|
||||
"anim": "",
|
||||
"start": ""
|
||||
},
|
||||
{
|
||||
"anim": "",
|
||||
"start": ""
|
||||
},
|
||||
{
|
||||
"anim": "",
|
||||
"start": ""
|
||||
}
|
||||
],
|
||||
"page": 0
|
||||
},
|
||||
"enabled": "onsent",
|
||||
"name": "slide-down-left",
|
||||
"page": 1
|
||||
},
|
||||
"timing": "linear"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "1.1.7",
|
||||
"hasShownChangelog": true
|
||||
},
|
||||
"settings": {
|
||||
"lastMessage": {
|
||||
"enabled": true,
|
||||
"roleColors": true
|
||||
},
|
||||
"redesign": {
|
||||
"enabled": true,
|
||||
"iconSize": "small"
|
||||
},
|
||||
"resizer": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* @name BetterChatNames
|
||||
* @author Break
|
||||
* @description Improves chat names by automatically capitalising them and/or removing dashes/underscores
|
||||
* @version 1.9.0
|
||||
* @authorLink https://github.com/Break-Ben
|
||||
* @website https://github.com/Break-Ben/BetterDiscordAddons
|
||||
* @source https://github.com/Break-Ben/BetterDiscordAddons/tree/main/BetterChatNames
|
||||
* @updateUrl https://raw.githubusercontent.com/Break-Ben/BetterDiscordAddons/main/BetterChatNames/BetterChatNames.plugin.js
|
||||
*/
|
||||
|
||||
const defaultSettings = {
|
||||
capitalise: true,
|
||||
removeDashes: true,
|
||||
removeEmojis: false,
|
||||
patchUnrestricted: true,
|
||||
capitalOverrides: 'and, or, of, the, for, to, at, a, FAQ, VC, GitHub'
|
||||
}
|
||||
|
||||
const unrestrictedChannels = {
|
||||
voice: 2,
|
||||
thread: 11,
|
||||
stage: 13
|
||||
}
|
||||
const regex = {
|
||||
dash: /-|_/g,
|
||||
capital: /(?<=(^|[^\p{L}'’]))\p{L}/gu,
|
||||
word: /\b\p{L}+\b/gu,
|
||||
emoji: /([-_]?\p{Extended_Pictographic}[-_┃]?)|(\uFE0F\u20E3)/gu
|
||||
}
|
||||
|
||||
let titleObserver
|
||||
const { Webpack, Patcher, Utils, Data, UI } = new BdApi('BetterChatNames')
|
||||
const { getModule, getByStrings, getByKeys, getByPrototypeKeys } = Webpack
|
||||
const { findInTree } = Utils
|
||||
const searchOptions = { walkable: ['children', 'props'] } // For Utils.findInTree
|
||||
|
||||
const currentServer = getByKeys('getLastSelectedGuildId')
|
||||
const currentChannel = getByKeys('getLastSelectedChannelId')
|
||||
const transitionTo = getByStrings('transitionTo - Transitioning to', { searchExports: true })
|
||||
|
||||
const sidebar = getModule(m => m?.render?.toString()?.includes('.CHANNEL'))
|
||||
const header = getByStrings('.HEADER_BAR)', { defaultExport: false })
|
||||
const placeholder = getByPrototypeKeys('getPlaceholder').prototype
|
||||
const mention = getByStrings('channelWithIcon', { defaultExport: false })
|
||||
|
||||
const debounceTimeMs = 1000
|
||||
|
||||
module.exports = class BetterChatNames {
|
||||
start() {
|
||||
this.settings = Object.assign({}, defaultSettings, Data.load('settings'))
|
||||
this.updateOverrideMap()
|
||||
this.observeAppTitle()
|
||||
this.patchNames()
|
||||
this.refreshChannel()
|
||||
}
|
||||
|
||||
stop() {
|
||||
titleObserver.disconnect()
|
||||
Patcher.unpatchAll()
|
||||
this.refreshChannel()
|
||||
}
|
||||
|
||||
getSettingsPanel = () => UI.buildSettingsPanel({
|
||||
settings: [
|
||||
{
|
||||
id: 'capitalise',
|
||||
name: 'Capitalise Words',
|
||||
type: 'switch',
|
||||
value: this.settings.capitalise
|
||||
},
|
||||
{
|
||||
id: 'removeDashes',
|
||||
name: 'Remove Dashes and Underscores',
|
||||
type: 'switch',
|
||||
value: this.settings.removeDashes
|
||||
},
|
||||
{
|
||||
id: 'removeEmojis',
|
||||
name: 'Remove Emojis',
|
||||
type: 'switch',
|
||||
value: this.settings.removeEmojis
|
||||
},
|
||||
{
|
||||
id: 'patchUnrestricted',
|
||||
name: 'Patch Unrestricted Channels',
|
||||
note: 'Change the names of channels that can already contain capital letters and spaces, such as voice channels, threads, and stages.',
|
||||
type: 'switch',
|
||||
value: this.settings.patchUnrestricted
|
||||
},
|
||||
{
|
||||
id: 'capitalOverrides',
|
||||
name: 'Capitalisation Overrides',
|
||||
note: 'A comma-separated list of words with custom capitalisations. For example: "and, FAQ, GitHub, iPhone". Only enabled if "Capitalise Words" is enabled, and can be cleared to be disabled.',
|
||||
type: 'text',
|
||||
inline: false,
|
||||
value: this.settings.capitalOverrides
|
||||
}
|
||||
],
|
||||
onChange: (_, id, value) => {
|
||||
if (id === 'capitalOverrides') {
|
||||
clearTimeout(this.debounceTimer)
|
||||
this.debounceTimer = setTimeout(() => {
|
||||
this.settings[id] = value
|
||||
Data.save('settings', this.settings)
|
||||
this.updateOverrideMap()
|
||||
if (this.settings.capitalise)
|
||||
this.refreshChannel()
|
||||
}, debounceTimeMs)
|
||||
return
|
||||
}
|
||||
|
||||
this.settings[id] = value
|
||||
Data.save('settings', this.settings)
|
||||
this.refreshChannel()
|
||||
}
|
||||
})
|
||||
|
||||
observeAppTitle() {
|
||||
let lastUnpatchedAppTitle
|
||||
titleObserver = new MutationObserver(() => {
|
||||
if (document.title !== lastUnpatchedAppTitle) { // Resolves conflicts with EditChannels' MutationObserver
|
||||
lastUnpatchedAppTitle = document.title
|
||||
this.patchAppTitle()
|
||||
}
|
||||
})
|
||||
titleObserver.observe(document.querySelector('title'), { childList: true })
|
||||
}
|
||||
|
||||
patchAppTitle() {
|
||||
const patchedTitle = this.patchText(document.title)
|
||||
|
||||
if (currentServer?.getGuildId() && document.title !== patchedTitle) // If in server and title not already patched
|
||||
document.title = patchedTitle
|
||||
}
|
||||
|
||||
patchNames() {
|
||||
this.patchSidebar()
|
||||
this.patchHeader()
|
||||
this.patchChatPlaceholder()
|
||||
this.patchMention()
|
||||
}
|
||||
|
||||
patchSidebar() {
|
||||
Patcher.after(sidebar, 'render', (_, __, data) => {
|
||||
const channelName = findInTree(data, prop => prop?.name, searchOptions)
|
||||
const channelType = findInTree(data, prop => prop?.channel, searchOptions).channel.type
|
||||
|
||||
if (!Object.values(unrestrictedChannels).includes(channelType) || this.settings.patchUnrestricted) // If not a voice/stage channel or patchUnrestricted is enabled
|
||||
channelName.name = this.patchText(channelName.name)
|
||||
})
|
||||
}
|
||||
|
||||
patchHeader() {
|
||||
Patcher.after(header, 'A', (_, __, data) => {
|
||||
const rootChannel = findInTree(data, prop => prop?.level, searchOptions)
|
||||
if (!rootChannel)
|
||||
return
|
||||
|
||||
if (rootChannel.level === 1) // If not in thread
|
||||
rootChannel.children.props.children[2] = this.patchText(rootChannel.children.props.children[2])
|
||||
else if (rootChannel.level === 2) { // If in thread
|
||||
rootChannel.children = this.patchText(rootChannel.children)
|
||||
if (this.settings.patchUnrestricted) {
|
||||
const threadName = findInTree(data, prop => Array.isArray(prop) && prop[1] === ' ', searchOptions)
|
||||
threadName[2] = this.patchText(threadName[2])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
patchChatPlaceholder() {
|
||||
Patcher.after(placeholder, 'render', (_, __, data) => {
|
||||
const textArea = findInTree(data, prop => prop.channel, searchOptions)
|
||||
const isThread = textArea.channel.type === unrestrictedChannels.thread
|
||||
|
||||
if (textArea.channel.guild_id && (!isThread || this.settings.patchUnrestricted) && !textArea.disabled && textArea.type.analyticsName === 'normal') { // If in a server, not in a thread (or patchUnrestricted is enabled), can message and not editing a message
|
||||
const splitIndex = (isThread ? textArea.placeholder.indexOf('"') : textArea.placeholder.indexOf('#')) + 1 // Indicates where the channel name starts
|
||||
textArea.placeholder = textArea.placeholder.substring(0, splitIndex) + this.patchText(textArea.placeholder.substr(splitIndex))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
patchMention() {
|
||||
Patcher.after(mention, 'A', (_, __, data) => {
|
||||
const channelName = findInTree(data, prop => typeof prop.children === 'string', searchOptions)
|
||||
|
||||
if (data.props.className.includes('iconMentionText') || this.settings.patchUnrestricted) // If is a normal chat mention (not a thread) or patchUnrestricted is enabled
|
||||
channelName.children = this.patchText(channelName.children)
|
||||
})
|
||||
}
|
||||
|
||||
patchText(text) {
|
||||
if (this.settings.removeEmojis)
|
||||
text = text.replace(regex.emoji, '')
|
||||
|
||||
if (this.settings.removeDashes)
|
||||
text = text.replace(regex.dash, ' ')
|
||||
|
||||
if (this.settings.capitalise) {
|
||||
text = text.replace(regex.capital, letter => letter.toUpperCase())
|
||||
|
||||
if (this.settings.capitalOverrides) {
|
||||
let wordCount = 0
|
||||
text = text.replace(regex.word, word => {
|
||||
wordCount++
|
||||
const wordLower = word.toLowerCase()
|
||||
if (!this.overrideMap.has(wordLower))
|
||||
return word
|
||||
|
||||
const wordOverride = this.overrideMap.get(wordLower)
|
||||
if (wordCount == 1 && wordOverride === wordLower)
|
||||
return word
|
||||
|
||||
return wordOverride
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return text
|
||||
}
|
||||
|
||||
refreshChannel() {
|
||||
const currentServerId = currentServer?.getGuildId()
|
||||
const currentChannelId = currentChannel?.getChannelId()
|
||||
|
||||
if (currentServerId) { // If not in a DM
|
||||
transitionTo('/channels/@me')
|
||||
setImmediate(() => transitionTo(`/channels/${currentServerId}/${currentChannelId}`))
|
||||
}
|
||||
}
|
||||
|
||||
updateOverrideMap() {
|
||||
// Maps lowercase words to their custom capitalised versions
|
||||
this.overrideMap = new Map((this.settings.capitalOverrides).split(',').map(w => w.trim()).filter(w => w).map(w => [w.toLowerCase(), w]))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "2.3.14",
|
||||
"hasShownChangelog": true
|
||||
},
|
||||
"settings": {
|
||||
"toolbar": {
|
||||
"bold": true,
|
||||
"italic": true,
|
||||
"underline": true,
|
||||
"strikethrough": true,
|
||||
"spoiler": true,
|
||||
"code": true,
|
||||
"codeblock": true,
|
||||
"superscript": true,
|
||||
"smallcaps": true,
|
||||
"fullwidth": true,
|
||||
"upsidedown": true,
|
||||
"varied": true,
|
||||
"leet": false,
|
||||
"thicc": false
|
||||
},
|
||||
"formats": {
|
||||
"superscript": true,
|
||||
"smallcaps": true,
|
||||
"fullwidth": true,
|
||||
"upsidedown": true,
|
||||
"varied": true,
|
||||
"leet": false,
|
||||
"thicc": false
|
||||
},
|
||||
"wrappers": {
|
||||
"superscript": "^^",
|
||||
"smallcaps": "%%",
|
||||
"fullwidth": "##",
|
||||
"upsidedown": "&&",
|
||||
"varied": "==",
|
||||
"leet": "++",
|
||||
"thicc": "$$"
|
||||
},
|
||||
"formatting": {
|
||||
"fullWidthMap": true,
|
||||
"reorderUpsidedown": true,
|
||||
"fullwidth": true
|
||||
},
|
||||
"plugin": {
|
||||
"hoverOpen": true,
|
||||
"chainFormats": true,
|
||||
"closeOnSend": true
|
||||
},
|
||||
"style": {
|
||||
"icons": true,
|
||||
"rightSide": true,
|
||||
"toolbarOpacity": 1,
|
||||
"fontSize": 85
|
||||
}
|
||||
},
|
||||
"version": "2.3.15"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "1.2.3",
|
||||
"hasShownChangelog": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
/**
|
||||
* @name BetterGuildTooltip
|
||||
* @author arg0NNY
|
||||
* @authorId 633223783204782090
|
||||
* @invite M8DBtcZjXD
|
||||
* @version 1.2.3
|
||||
* @description Displays an online and total member count in the guild tooltip.
|
||||
* @website https://github.com/arg0NNY/DiscordPlugins/tree/master/BetterGuildTooltip
|
||||
* @source https://raw.githubusercontent.com/arg0NNY/DiscordPlugins/master/BetterGuildTooltip/BetterGuildTooltip.plugin.js
|
||||
* @updateUrl https://raw.githubusercontent.com/arg0NNY/DiscordPlugins/master/BetterGuildTooltip/BetterGuildTooltip.plugin.js
|
||||
*/
|
||||
|
||||
/* ### CONFIG START ### */
|
||||
const config = {
|
||||
info: {
|
||||
name: 'BetterGuildTooltip',
|
||||
version: '1.2.3',
|
||||
description: 'Displays an online and total member count in the guild tooltip.'
|
||||
},
|
||||
changelog: [
|
||||
{
|
||||
type: 'fixed',
|
||||
title: 'Fixes',
|
||||
items: [
|
||||
'Updated to work in the latest release of Discord.'
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
/* ### CONFIG END ### */
|
||||
|
||||
const {
|
||||
Webpack,
|
||||
UI,
|
||||
Patcher,
|
||||
React,
|
||||
Utils,
|
||||
Data
|
||||
} = new BdApi(config.info.name)
|
||||
const { Filters } = Webpack
|
||||
|
||||
const Dispatcher = Webpack.getModule(Filters.byKeys('dispatch', 'subscribe'), { searchExports: true })
|
||||
const GuildMemberCountStore = Webpack.getStore('GuildMemberCountStore')
|
||||
const GuildChannelStore = Webpack.getStore('GuildChannelStore')
|
||||
const Flux = Webpack.getByKeys('Store', 'connectStores')
|
||||
|
||||
const ActionTypes = {
|
||||
CONNECTION_OPEN: 'CONNECTION_OPEN',
|
||||
GUILD_CREATE: 'GUILD_CREATE',
|
||||
GUILD_DELETE: 'GUILD_DELETE',
|
||||
GUILD_MEMBER_LIST_UPDATE: 'GUILD_MEMBER_LIST_UPDATE',
|
||||
ONLINE_GUILD_MEMBER_COUNT_UPDATE: 'ONLINE_GUILD_MEMBER_COUNT_UPDATE'
|
||||
}
|
||||
|
||||
const useStateFromStores = Webpack.getModule(Filters.byStrings('useStateFromStores'), { searchExports: true })
|
||||
|
||||
const Selectors = {
|
||||
Guild: Webpack.getByKeys('statusOffline', 'guildDetail')
|
||||
}
|
||||
|
||||
const GuildStore = Webpack.getStore('GuildStore')
|
||||
const GuildActions = Webpack.getByKeys('preload', 'closePrivateChannel')
|
||||
const GuildTooltip = [...Webpack.getWithKey(Filters.byStrings('position'), { target: Webpack.getBySource('GuildTooltip') })]
|
||||
|
||||
const memberCounts = new Map()
|
||||
const onlineMemberCounts = new Map()
|
||||
|
||||
function handleConnectionOpen ({ guilds }) {
|
||||
for (const guild of guilds) {
|
||||
memberCounts.set(guild.id, guild.member_count)
|
||||
}
|
||||
}
|
||||
|
||||
function handleGuildCreate ({ guild }) {
|
||||
memberCounts.set(guild.id, guild.member_count)
|
||||
}
|
||||
|
||||
function handleGuildDelete ({ guild }) {
|
||||
memberCounts.delete(guild.id)
|
||||
onlineMemberCounts.delete(guild.id)
|
||||
}
|
||||
|
||||
function handleGuildMemberListUpdate ({ guildId, memberCount, groups }) {
|
||||
if (memberCount !== 0) {
|
||||
memberCounts.set(guildId, memberCount)
|
||||
}
|
||||
|
||||
onlineMemberCounts.set(
|
||||
guildId,
|
||||
groups.reduce((total, group) => {
|
||||
return group.id !== 'offline' ? total + group.count : total
|
||||
}, 0)
|
||||
)
|
||||
}
|
||||
|
||||
function handleOnlineGuildMemberCountUpdate ({ guildId, count }) {
|
||||
onlineMemberCounts.set(guildId, count)
|
||||
}
|
||||
|
||||
const MemberCountsStore = new class extends Flux.Store {
|
||||
initialize () {
|
||||
const nativeMemberCounts = GuildMemberCountStore.getMemberCounts()
|
||||
for (const guildId in nativeMemberCounts) {
|
||||
memberCounts.set(guildId, nativeMemberCounts[guildId])
|
||||
}
|
||||
};
|
||||
|
||||
getMemberCounts (guildId) {
|
||||
return {
|
||||
members: memberCounts.get(guildId),
|
||||
membersOnline: onlineMemberCounts.get(guildId)
|
||||
}
|
||||
};
|
||||
}(Dispatcher, {
|
||||
[ActionTypes.CONNECTION_OPEN]: handleConnectionOpen,
|
||||
[ActionTypes.GUILD_CREATE]: handleGuildCreate,
|
||||
[ActionTypes.GUILD_DELETE]: handleGuildDelete,
|
||||
[ActionTypes.GUILD_MEMBER_LIST_UPDATE]: handleGuildMemberListUpdate,
|
||||
[ActionTypes.ONLINE_GUILD_MEMBER_COUNT_UPDATE]: handleOnlineGuildMemberCountUpdate
|
||||
})
|
||||
|
||||
function formatNumber (number) {
|
||||
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ')
|
||||
}
|
||||
|
||||
function GuildTooltipCounters (props) {
|
||||
MemberCountsStore.initialize()
|
||||
|
||||
const { presenceCount, memberCount } = useStateFromStores([GuildStore], () =>
|
||||
GuildStore.getGuild(props.guild.id) ?? {}
|
||||
)
|
||||
const { members, membersOnline } = useStateFromStores([MemberCountsStore], () =>
|
||||
MemberCountsStore.getMemberCounts(props.guild.id)
|
||||
)
|
||||
|
||||
const onlineDisplayed = props.settings.displayOnline && (membersOnline || presenceCount)
|
||||
const totalDisplayed = props.settings.displayTotal && (memberCount || members)
|
||||
|
||||
return onlineDisplayed || totalDisplayed ? React.createElement(
|
||||
'div',
|
||||
{
|
||||
className: Selectors.Guild.guildDetail,
|
||||
style: props.isPopout ? {
|
||||
fontWeight: '600'
|
||||
} : {
|
||||
marginTop: '5px',
|
||||
marginBottom: '5px'
|
||||
}
|
||||
},
|
||||
React.createElement(
|
||||
'div',
|
||||
{
|
||||
className: Selectors.Guild.statusCounts,
|
||||
style: {
|
||||
columnGap: 0,
|
||||
'-webkit-column-gap': 0
|
||||
}
|
||||
},
|
||||
[
|
||||
...(onlineDisplayed ? [React.createElement(
|
||||
'i',
|
||||
{
|
||||
className: Selectors.Guild.statusOnline
|
||||
}
|
||||
),
|
||||
React.createElement(
|
||||
'span',
|
||||
{
|
||||
className: Selectors.Guild.count
|
||||
},
|
||||
formatNumber(membersOnline ?? presenceCount)
|
||||
)] : []),
|
||||
...(totalDisplayed ? [React.createElement(
|
||||
'i',
|
||||
{
|
||||
className: Selectors.Guild.statusOffline
|
||||
}
|
||||
),
|
||||
React.createElement(
|
||||
'span',
|
||||
{
|
||||
className: Selectors.Guild.count
|
||||
},
|
||||
formatNumber(memberCount ?? members)
|
||||
)] : [])
|
||||
]
|
||||
)
|
||||
) : React.createElement('div')
|
||||
}
|
||||
|
||||
const PRELOAD_DELAY = 200
|
||||
|
||||
module.exports = class BetterGuildTooltip {
|
||||
start () {
|
||||
this.patchGuildTooltip()
|
||||
|
||||
this.preloadInProccess = false
|
||||
this.preloadNext = null
|
||||
}
|
||||
|
||||
preloadGuild (guild) {
|
||||
if (!guild || this.preloadInProccess) return this.preloadNext = guild
|
||||
|
||||
this._preloadGuild(guild)
|
||||
this.preloadInProccess = true
|
||||
setTimeout(() => {
|
||||
this.preloadInProccess = false
|
||||
this.preloadGuild(this.preloadNext)
|
||||
this.preloadNext = null
|
||||
}, PRELOAD_DELAY)
|
||||
}
|
||||
|
||||
_preloadGuild (guild) {
|
||||
GuildActions.preload(
|
||||
guild.id,
|
||||
GuildChannelStore.getDefaultChannel(guild.id).id
|
||||
)
|
||||
}
|
||||
|
||||
patchGuildTooltip () {
|
||||
const callback = (index, props = {}) => (self, [{ guild }], value) => {
|
||||
if (!this.settings.displayOnline && !this.settings.displayTotal) return
|
||||
if (this.settings.displayOnline && !onlineMemberCounts.has(guild.id)) this.preloadGuild(guild)
|
||||
value.props.children.splice(index, 0, React.createElement(GuildTooltipCounters, {
|
||||
guild,
|
||||
settings: this.settings,
|
||||
...props
|
||||
}))
|
||||
}
|
||||
|
||||
Patcher.after(...GuildTooltip, (self, _, value) => {
|
||||
const nodeRef = React.useRef()
|
||||
|
||||
if (!this.settings.displayOnline && !this.settings.displayTotal) return
|
||||
|
||||
const node = Utils.findInTree(
|
||||
value,
|
||||
m => Filters.byStrings('isViewingRoles')(m?.type),
|
||||
{ walkable: ['props', 'children', '__unsupportedReactNodeAsText'] }
|
||||
)
|
||||
if (!node || nodeRef.current === node) return
|
||||
|
||||
Patcher.after(node, 'type', callback(1))
|
||||
nodeRef.current = node
|
||||
})
|
||||
}
|
||||
|
||||
stop () {
|
||||
Patcher.unpatchAll()
|
||||
}
|
||||
|
||||
constructor () {
|
||||
this.defaultSettings = {
|
||||
displayOnline: true,
|
||||
displayTotal: true
|
||||
}
|
||||
|
||||
this.settings = this.loadSettings(this.defaultSettings)
|
||||
|
||||
this.showChangelogIfNeeded()
|
||||
}
|
||||
|
||||
loadSettings (defaults = {}) {
|
||||
return Utils.extend({}, defaults, Data.load('settings'))
|
||||
}
|
||||
saveSettings (settings = this.settings) {
|
||||
return Data.save('settings', settings)
|
||||
}
|
||||
|
||||
showChangelogIfNeeded () {
|
||||
const currentVersionInfo = Utils.extend(
|
||||
{ version: config.info.version, hasShownChangelog: false },
|
||||
Data.load('currentVersionInfo')
|
||||
)
|
||||
if (currentVersionInfo.version === config.info.version && currentVersionInfo.hasShownChangelog) return
|
||||
|
||||
this.showChangelog()
|
||||
Data.save('currentVersionInfo', { version: config.info.version, hasShownChangelog: true })
|
||||
}
|
||||
showChangelog () {
|
||||
return UI.showChangelogModal({
|
||||
title: config.info.name,
|
||||
subtitle: 'Version ' + config.info.version,
|
||||
changes: config.changelog
|
||||
})
|
||||
}
|
||||
|
||||
getSettingsPanel () {
|
||||
return UI.buildSettingsPanel({
|
||||
onChange: () => this.saveSettings(),
|
||||
settings: [
|
||||
{
|
||||
type: 'switch',
|
||||
id: 'displayOnline',
|
||||
name: 'Display online count',
|
||||
note: 'Displays an online member count in the guild tooltip.',
|
||||
value: this.settings.displayOnline,
|
||||
onChange: e => this.settings.displayOnline = e
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
id: 'displayTotal',
|
||||
name: 'Display total count',
|
||||
note: 'Displays a total member count in the guild tooltip.',
|
||||
value: this.settings.displayTotal,
|
||||
onChange: e => this.settings.displayTotal = e
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "0.10.4",
|
||||
"hasShownChangelog": true
|
||||
},
|
||||
"settings": {
|
||||
"global": {
|
||||
"important": false
|
||||
},
|
||||
"modules": {
|
||||
"typing": true,
|
||||
"voice": true,
|
||||
"mentions": true,
|
||||
"chat": false,
|
||||
"botTags": true,
|
||||
"memberList": true
|
||||
},
|
||||
"popouts": {
|
||||
"username": true,
|
||||
"discriminator": true,
|
||||
"nickname": true,
|
||||
"fallback": true
|
||||
},
|
||||
"modals": {
|
||||
"username": true,
|
||||
"discriminator": true
|
||||
},
|
||||
"auditLog": {
|
||||
"username": true,
|
||||
"discriminator": false
|
||||
},
|
||||
"account": {
|
||||
"username": true,
|
||||
"discriminator": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "2.6.15",
|
||||
"hasShownChangelog": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"settings": {
|
||||
"tabs": [
|
||||
{
|
||||
"name": "#🤡│facereveal",
|
||||
"url": "/channels/821835978334535740/987679407114178620",
|
||||
"selected": true,
|
||||
"currentStatus": "none",
|
||||
"iconUrl": "https://cdn.discordapp.com/icons/821835978334535740/f03c55415ef5c81b99585e10c1008c3b.webp?size=32",
|
||||
"channelId": "987679407114178620"
|
||||
}
|
||||
],
|
||||
"favs": [
|
||||
{
|
||||
"name": "#🧀│allgemein",
|
||||
"iconUrl": "https://cdn.discordapp.com/icons/821835978334535740/f03c55415ef5c81b99585e10c1008c3b.webp?size=32",
|
||||
"url": "/channels/821835978334535740/821835978767073292",
|
||||
"channelId": "821835978767073292",
|
||||
"groupId": -1
|
||||
},
|
||||
{
|
||||
"name": "#schwitzies",
|
||||
"iconUrl": "https://cdn.discordapp.com/icons/230708419995107330/aa16ef21ab85c9e89ff8ba36a7260e20.webp?size=32",
|
||||
"url": "/channels/230708419995107330/775452873377972254",
|
||||
"channelId": "775452873377972254",
|
||||
"groupId": -1
|
||||
}
|
||||
],
|
||||
"favGroups": [],
|
||||
"showTabBar": true,
|
||||
"showFavBar": true,
|
||||
"reopenLastChannel": true,
|
||||
"showFavUnreadBadges": true,
|
||||
"showFavMentionBadges": true,
|
||||
"showFavTypingBadge": true,
|
||||
"showEmptyFavBadges": false,
|
||||
"showTabUnreadBadges": true,
|
||||
"showTabMentionBadges": true,
|
||||
"showTabTypingBadge": true,
|
||||
"showEmptyTabBadges": false,
|
||||
"showActiveTabUnreadBadges": false,
|
||||
"showActiveTabMentionBadges": false,
|
||||
"showActiveTabTypingBadge": false,
|
||||
"showEmptyActiveTabBadges": false,
|
||||
"compactStyle": true,
|
||||
"privacyMode": false,
|
||||
"radialStatusMode": true,
|
||||
"tabWidthMin": 100,
|
||||
"showFavGroupUnreadBadges": true,
|
||||
"showFavGroupMentionBadges": true,
|
||||
"showFavGroupTypingBadge": true,
|
||||
"showEmptyFavGroupBadges": false,
|
||||
"showQuickSettings": true,
|
||||
"showNavButtons": true,
|
||||
"alwaysFocusNewTabs": false,
|
||||
"useStandardNav": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"CBsettings": {
|
||||
"version": "1.1.7",
|
||||
"voice": {
|
||||
"voice": true,
|
||||
"text": true,
|
||||
"emoji": true,
|
||||
"voice_color": "#1ABC9C"
|
||||
},
|
||||
"forum": {
|
||||
"forum": true,
|
||||
"text": true,
|
||||
"emoji": true,
|
||||
"forum_color": "#206694"
|
||||
},
|
||||
"nsfw": {
|
||||
"nsfw": true,
|
||||
"text": true,
|
||||
"emoji": true,
|
||||
"nsfw_color": "#F23F42"
|
||||
},
|
||||
"rule": {
|
||||
"rule": true,
|
||||
"text": true,
|
||||
"emoji": true,
|
||||
"rule_color": "#FF9B2B"
|
||||
},
|
||||
"ads": {
|
||||
"ads": true,
|
||||
"text": true,
|
||||
"emoji": true,
|
||||
"ads_color": "#FF2BC2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "1.4.2",
|
||||
"hasShownChangelog": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
/**
|
||||
* @name DisplayUsernames
|
||||
* @author HG
|
||||
* @authorId 124667638298181632
|
||||
* @authorLink https://youtube.com/HudsonGTV
|
||||
* @description Displays Discord handle next to display names in chat and adds '@' symbol in profile cards.
|
||||
* @version 1.4.2
|
||||
* @website https://hudsongreen.com/
|
||||
* @invite H3bebA97tV
|
||||
* @donate https://www.paypal.com/donate/?business=REFHYLZAZUWHJ
|
||||
* @source https://github.com/HudsonGTV/BetterDiscordPlugins/blob/main/DisplayUsernames/DisplayUsernames.plugin.js
|
||||
*/
|
||||
|
||||
const request = require("request");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const config = {
|
||||
info: {
|
||||
name: "DisplayUsernames",
|
||||
authors: [
|
||||
{
|
||||
name: "HG",
|
||||
discord_id: "124667638298181632",
|
||||
github_username: "HudsonGTV",
|
||||
twitter_username: "HudsonKazuto"
|
||||
}
|
||||
],
|
||||
version: "1.4.2",
|
||||
description: "Displays Discord handle next to display names in chat and adds '`@`' symbol in profile cards.",
|
||||
github: "https://github.com/HudsonGTV/BetterDiscordPlugins/blob/main/DisplayUsernames/DisplayUsernames.plugin.js",
|
||||
github_raw: "https://raw.githubusercontent.com/HudsonGTV/BetterDiscordPlugins/main/DisplayUsernames/DisplayUsernames.plugin.js"
|
||||
},
|
||||
changelog: [
|
||||
{
|
||||
title: "Fixes",
|
||||
type: "fixed",
|
||||
items: [
|
||||
"`[1.4.2]` Fixed bug with usernames appearing in command replies",
|
||||
"`[1.4.1]` Fixed bug with seperator symbol in replies",
|
||||
"`[1.4.0]` Fixed username prefix not appearing due to recent Discord revamp.",
|
||||
"`[1.4.0]` Fixed bug with username handle in chat being black with certain themes."
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Additions",
|
||||
type: "added",
|
||||
items: [
|
||||
"`[1.4.2]` Added ability to hide the username in replies.",
|
||||
"`[1.4.1]` Added ability to change seperator color seperately.",
|
||||
"`[1.4.0]` Added ability to change username handle color in chat."
|
||||
]
|
||||
},
|
||||
/*{
|
||||
title: "Improvements",
|
||||
type: "improved",
|
||||
items: [
|
||||
"`[1.2.0]` Settings now apply without the need to restart Discord (Except handle symbol changes)."
|
||||
]
|
||||
}*/
|
||||
],
|
||||
defaultConfig: [
|
||||
{
|
||||
type: "textbox",
|
||||
id: "handlesymbol",
|
||||
name: "[Needs restart to fully apply] Username Handle Prefix Symbol",
|
||||
note: "The symbol used as a prefix for usernames (the @ in @username).",
|
||||
placeholder: "Blank for none; default: @",
|
||||
value: "@"
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
id: "usernamecolor",
|
||||
name: "Username Color",
|
||||
note: "The color used when displaying the username in the chat",
|
||||
value: "#949BA4"
|
||||
},
|
||||
{
|
||||
type: "color",
|
||||
id: "seperatorcolor",
|
||||
name: "Seperator Color",
|
||||
note: "The color used for the symbol that either seperates the username from the message timestamp (@username • timestamp) or the suffix in replies (@username: message)",
|
||||
value: "#949BA4"
|
||||
},
|
||||
{
|
||||
type: "switch",
|
||||
id: "usernamechat",
|
||||
name: "Show Username In Chat",
|
||||
note: "Display the message author's username next to the message timestamp.",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
type: "switch",
|
||||
id: "showinreplies",
|
||||
name: "Show Username in Chat Replies",
|
||||
note: "Shows the username in the replied message text.",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
type: "switch",
|
||||
id: "profilecard",
|
||||
name: "Show Handle Prefix In Profile Card & Friends List",
|
||||
note: "Display the username handle prefix in profile cards/popups as well as the friends list.",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
type: "switch",
|
||||
id: "friendslist",
|
||||
name: "Always Show Friends List Username",
|
||||
note: "Force Discord to always display usernames next to display names in friends list. Turn off for default Discord behavior (only show on hover).",
|
||||
value: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
module.exports = !global.ZeresPluginLibrary ? class {
|
||||
|
||||
constructor() {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
load() {
|
||||
BdApi.showConfirmationModal("Library plugin is needed",
|
||||
`The library plugin needed for ZeresPluginLibrary is missing. Please click Download Now to install it.`, {
|
||||
confirmText: "Download",
|
||||
cancelText: "Cancel",
|
||||
onConfirm: () => {
|
||||
request.get("https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js", (error, response, body) => {
|
||||
if (error)
|
||||
return electron.shell.openExternal("https://betterdiscord.net/ghdl?url=https://raw.githubusercontent.com/rauenzi/BDPluginLibrary/master/release/0PluginLibrary.plugin.js");
|
||||
|
||||
fs.writeFileSync(path.join(BdApi.Plugins.folder, "0PluginLibrary.plugin.js"), body);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
start() { }
|
||||
stop() { }
|
||||
|
||||
} : (([Plugin, Library]) => {
|
||||
|
||||
const { DiscordModules, WebpackModules, Patcher, PluginUtilities } = Library;
|
||||
const { React } = DiscordModules;
|
||||
|
||||
class plugin extends Plugin {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
onStart() {
|
||||
|
||||
// Apply CSS Styles
|
||||
this.applyStyles();
|
||||
|
||||
// Bind usernames if enabled
|
||||
if(this.settings.usernamechat) this.applyUsername();
|
||||
|
||||
}
|
||||
|
||||
onStop() {
|
||||
Patcher.unpatchAll();
|
||||
this.removeStyles();
|
||||
}
|
||||
|
||||
// Manage settings panel
|
||||
getSettingsPanel() {
|
||||
|
||||
const panel = this.buildSettingsPanel();
|
||||
|
||||
// Listen for changes in settings
|
||||
panel.addListener((id, val) => {
|
||||
switch(id) {
|
||||
case "usernamechat":
|
||||
// Check bool val
|
||||
if(val)
|
||||
this.applyUsername();
|
||||
else
|
||||
Patcher.unpatchAll(); // Change this if I add more patches to plugin
|
||||
break;
|
||||
case "showinreplies":
|
||||
case "usernamecolor":
|
||||
case "seperatorcolor":
|
||||
case "profilecard":
|
||||
case "friendslist":
|
||||
// Reload CSS
|
||||
this.removeStyles();
|
||||
this.applyStyles();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// Display settings panel
|
||||
return panel.getElement();
|
||||
}
|
||||
|
||||
applyStyles() {
|
||||
// Chat message username styles (required - configured via applyUsername())
|
||||
PluginUtilities.addStyle(
|
||||
"DisplayUsernames-ChatMessage",
|
||||
`
|
||||
/* style username in messages */
|
||||
.hg-username-handle {
|
||||
margin-left: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
color: ${this.settings.usernamecolor};
|
||||
}
|
||||
/* seperator dot */
|
||||
.hg-username-handle::after {
|
||||
margin-left: 0.5rem;
|
||||
content: "•";
|
||||
color: ${this.settings.seperatorcolor};
|
||||
}
|
||||
/* fix timestamp margin (discord likes to change it randomly) */
|
||||
.roleDot_c01716, .cozy_f5c119 .headerText_f47574, .compact__54ecc .headerText_f47574 {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
/* hide username in command replies */
|
||||
.repliedMessage_f9f2ca > .hg-username-handle {
|
||||
display: none;
|
||||
}
|
||||
/* but dont hide handle in normal replies if user wants them visible */
|
||||
[id*="message-reply-context-"] > .hg-username-handle {
|
||||
margin-left: 0;
|
||||
display: ${this.settings.showinreplies ? "inline" : "none"};
|
||||
}
|
||||
/* change seperator in replies */
|
||||
[id*="message-reply-context-"] > .hg-username-handle::after {
|
||||
margin-left: 0;
|
||||
content: ": ";
|
||||
}
|
||||
`
|
||||
);
|
||||
// Display handle symbol infront of username in profile card/friends list
|
||||
if(this.settings.profilecard) PluginUtilities.addStyle(
|
||||
"DisplayUsernames-ProfileCard",
|
||||
`
|
||||
/* display handle symbol infront of username */
|
||||
span.userTagUsername_c32acf::before, /* profile cards */
|
||||
span.discriminator_f3939d::before /* friends list */ {
|
||||
color: #777;
|
||||
content: "${this.settings.handlesymbol}";
|
||||
}
|
||||
`
|
||||
);
|
||||
// Always display usernames in friends list
|
||||
if(this.settings.friendslist) PluginUtilities.addStyle(
|
||||
"DisplayUsernames-FriendsList",
|
||||
`
|
||||
/* always show username in friends list */
|
||||
.discriminator_f3939d {
|
||||
visibility: visible !important;
|
||||
}
|
||||
`
|
||||
);
|
||||
}
|
||||
|
||||
removeStyles() {
|
||||
PluginUtilities.removeStyle("DisplayUsernames-ChatMessage");
|
||||
PluginUtilities.removeStyle("DisplayUsernames-ProfileCard");
|
||||
PluginUtilities.removeStyle("DisplayUsernames-FriendsList");
|
||||
}
|
||||
|
||||
applyUsername() {
|
||||
|
||||
const [ module, key ] = BdApi.Webpack.getWithKey(BdApi.Webpack.Filters.byStrings("userOverride", "withMentionPrefix"), { searchExports: false });
|
||||
|
||||
Patcher.after(module, key, (_, args, ret) => {
|
||||
let author = args[0].message.author;
|
||||
let discrim = author.discriminator;
|
||||
// Ensure this is not a webhook or system message
|
||||
if(discrim != "0000")
|
||||
ret.props.children.push(
|
||||
React.createElement("span", { class: "hg-username-handle" }, this.settings.handlesymbol + author.username + (discrim != "0" ? "#" + discrim : ""))
|
||||
);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return plugin;
|
||||
|
||||
})(global.ZeresPluginLibrary.buildPlugin(config));
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
/**
|
||||
* @name DoNotTrack
|
||||
* @description Stops Discord from tracking everything you do like Sentry and Analytics.
|
||||
* @version 0.1.0
|
||||
* @author Zerebos
|
||||
* @authorId 249746236008169473
|
||||
* @website https://github.com/zerebos/BetterDiscordAddons/tree/master/Plugins/DoNotTrack
|
||||
* @source https://raw.githubusercontent.com/zerebos/BetterDiscordAddons/master/Plugins/DoNotTrack/DoNotTrack.plugin.js
|
||||
*/
|
||||
|
||||
/*@cc_on
|
||||
@if (@_jscript)
|
||||
|
||||
// Offer to self-install for clueless users that try to run this directly.
|
||||
var shell = WScript.CreateObject("WScript.Shell");
|
||||
var fs = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var pathPlugins = shell.ExpandEnvironmentStrings("%APPDATA%\\BetterDiscord\\plugins");
|
||||
var pathSelf = WScript.ScriptFullName;
|
||||
// Put the user at ease by addressing them in the first person
|
||||
shell.Popup("It looks like you've mistakenly tried to run me directly. \n(Don't do that!)", 0, "I'm a plugin for BetterDiscord", 0x30);
|
||||
if (fs.GetParentFolderName(pathSelf) === fs.GetAbsolutePathName(pathPlugins)) {
|
||||
shell.Popup("I'm in the correct folder already.", 0, "I'm already installed", 0x40);
|
||||
} else if (!fs.FolderExists(pathPlugins)) {
|
||||
shell.Popup("I can't find the BetterDiscord plugins folder.\nAre you sure it's even installed?", 0, "Can't install myself", 0x10);
|
||||
} else if (shell.Popup("Should I copy myself to BetterDiscord's plugins folder for you?", 0, "Do you need some help?", 0x34) === 6) {
|
||||
fs.CopyFile(pathSelf, fs.BuildPath(pathPlugins, fs.GetFileName(pathSelf)), true);
|
||||
// Show the user where to put plugins in the future
|
||||
shell.Exec("explorer " + pathPlugins);
|
||||
shell.Popup("I'm installed!", 0, "Successfully installed", 0x40);
|
||||
}
|
||||
WScript.Quit();
|
||||
|
||||
@else@*/
|
||||
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/plugins/DoNotTrack/index.ts
|
||||
var DoNotTrack_exports = {};
|
||||
__export(DoNotTrack_exports, {
|
||||
default: () => DoNotTrack
|
||||
});
|
||||
module.exports = __toCommonJS(DoNotTrack_exports);
|
||||
|
||||
// src/common/plugin.ts
|
||||
var Plugin = class {
|
||||
meta;
|
||||
manifest;
|
||||
settings;
|
||||
defaultSettings;
|
||||
LocaleManager;
|
||||
get strings() {
|
||||
if (!this.manifest.strings) return {};
|
||||
const locale = this.LocaleManager?.getLocale().split("-")[0] ?? "en";
|
||||
if (this.manifest.strings.hasOwnProperty(locale)) return this.manifest.strings[locale];
|
||||
if (this.manifest.strings.hasOwnProperty("en")) return this.manifest.strings.en;
|
||||
return this.manifest.strings;
|
||||
}
|
||||
constructor(meta, zplConfig) {
|
||||
this.meta = meta;
|
||||
this.manifest = zplConfig;
|
||||
if (typeof this.manifest.config !== "undefined") {
|
||||
this.defaultSettings = {};
|
||||
for (let s = 0; s < this.manifest.config.length; s++) {
|
||||
const current = this.manifest.config[s];
|
||||
if (current.type != "category") {
|
||||
this.defaultSettings[current.id] = current.value;
|
||||
} else {
|
||||
for (let si = 0; si < current.settings.length; si++) {
|
||||
const subCurrent = current.settings[si];
|
||||
this.defaultSettings[subCurrent.id] = subCurrent.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.settings = BdApi.Utils.extend({}, this.defaultSettings);
|
||||
}
|
||||
const currentVersionInfo = BdApi.Data.load(this.meta.name, "version");
|
||||
if (currentVersionInfo !== this.meta.version) {
|
||||
this.#showChangelog();
|
||||
BdApi.Data.save(this.meta.name, "version", this.meta.version);
|
||||
}
|
||||
if (this.manifest.strings) this.LocaleManager = BdApi.Webpack.getModule((m) => m?.Messages && Object.keys(m?.Messages).length > 0);
|
||||
if (this.manifest.config && !this.getSettingsPanel) {
|
||||
this.getSettingsPanel = () => {
|
||||
this.#updateConfig();
|
||||
return BdApi.UI.buildSettingsPanel({
|
||||
onChange: (_, id, value) => {
|
||||
this.settings[id] = value;
|
||||
this.saveSettings();
|
||||
},
|
||||
settings: this.manifest.config
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
async start() {
|
||||
BdApi.Logger.info(this.meta.name, `version ${this.meta.version} has started.`);
|
||||
if (this.defaultSettings) this.settings = this.loadSettings();
|
||||
if (typeof this.onStart == "function") this.onStart();
|
||||
}
|
||||
stop() {
|
||||
BdApi.Logger.info(this.meta.name, `version ${this.meta.version} has stopped.`);
|
||||
if (typeof this.onStop == "function") this.onStop();
|
||||
}
|
||||
#showChangelog() {
|
||||
if (typeof this.manifest.changelog == "undefined") return;
|
||||
const changelog = {
|
||||
title: this.meta.name + " Changelog",
|
||||
subtitle: `v${this.meta.version}`,
|
||||
changes: []
|
||||
};
|
||||
if (!Array.isArray(this.manifest.changelog)) Object.assign(changelog, this.manifest.changelog);
|
||||
else changelog.changes = this.manifest.changelog;
|
||||
BdApi.UI.showChangelogModal(changelog);
|
||||
}
|
||||
saveSettings() {
|
||||
BdApi.Data.save(this.meta.name, "settings", this.settings);
|
||||
}
|
||||
loadSettings() {
|
||||
return BdApi.Utils.extend({}, this.defaultSettings ?? {}, BdApi.Data.load(this.meta.name, "settings"));
|
||||
}
|
||||
#updateConfig() {
|
||||
if (!this.manifest.config) return;
|
||||
for (const setting of this.manifest.config) {
|
||||
if (setting.type !== "category") {
|
||||
setting.value = this.settings[setting.id] ?? setting.value;
|
||||
} else {
|
||||
for (const subsetting of setting.settings) {
|
||||
subsetting.value = this.settings[subsetting.id] ?? subsetting.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
buildSettingsPanel(onChange) {
|
||||
this.#updateConfig();
|
||||
return BdApi.UI.buildSettingsPanel({
|
||||
onChange: (groupId, id, value) => {
|
||||
this.settings[id] = value;
|
||||
onChange?.(groupId, id, value);
|
||||
this.saveSettings();
|
||||
},
|
||||
settings: this.manifest.config
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// src/plugins/DoNotTrack/config.ts
|
||||
var manifest = {
|
||||
info: {
|
||||
name: "DoNotTrack",
|
||||
authors: [{
|
||||
name: "Zerebos",
|
||||
discord_id: "249746236008169473",
|
||||
github_username: "zerebos",
|
||||
twitter_username: "IAmZerebos"
|
||||
}],
|
||||
version: "0.1.0",
|
||||
description: "Stops Discord from tracking everything you do like Sentry and Analytics.",
|
||||
github: "https://github.com/zerebos/BetterDiscordAddons/tree/master/Plugins/DoNotTrack",
|
||||
github_raw: "https://raw.githubusercontent.com/zerebos/BetterDiscordAddons/master/Plugins/DoNotTrack/DoNotTrack.plugin.js"
|
||||
},
|
||||
changelog: [
|
||||
{
|
||||
title: "What's New?",
|
||||
type: "added",
|
||||
items: [
|
||||
"Plugin no longer relies on ZeresPluginLibrary!",
|
||||
"DoNotTrack should be more resilient to Discord's changes."
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Fixes",
|
||||
type: "fixed",
|
||||
items: [
|
||||
"Fixed startup issues.",
|
||||
"Hopefully fixed issues with the process monitor."
|
||||
]
|
||||
}
|
||||
],
|
||||
main: "index.ts",
|
||||
config: [
|
||||
{
|
||||
type: "switch",
|
||||
id: "stopProcessMonitor",
|
||||
name: "Stop Process Monitor",
|
||||
note: "This setting stops Discord from monitoring the processes on your PC and prevents your currently played game from showing.",
|
||||
value: true
|
||||
}
|
||||
]
|
||||
};
|
||||
var config_default = manifest;
|
||||
|
||||
// src/plugins/DoNotTrack/index.ts
|
||||
var { Patcher, Webpack, UI } = BdApi;
|
||||
var SettingsManager = Webpack.getModule((m) => m?.updateAsync && m?.type === 1, { searchExports: true });
|
||||
var BoolSetting = Webpack.getModule((m) => m?.typeName?.includes("Bool"), { searchExports: true });
|
||||
var Analytics = Webpack.getByKeys("AnalyticEventConfigs");
|
||||
var NativeModule = Webpack.getByKeys("getDiscordUtils");
|
||||
var DoNotTrack = class extends Plugin {
|
||||
constructor(meta) {
|
||||
super(meta, config_default);
|
||||
}
|
||||
onStart() {
|
||||
if (Analytics) {
|
||||
Patcher.instead(this.meta.name, Analytics.default, "track", () => {
|
||||
});
|
||||
}
|
||||
if (NativeModule) {
|
||||
Patcher.instead(this.meta.name, NativeModule, "ensureModule", (_, [moduleName], originalFunction) => {
|
||||
if (moduleName?.includes("discord_rpc")) return;
|
||||
return originalFunction(moduleName);
|
||||
});
|
||||
}
|
||||
window?.__SENTRY__?.globalEventProcessors?.splice(0, window?.__SENTRY__?.globalEventProcessors?.length);
|
||||
window?.__SENTRY__?.logger?.disable();
|
||||
const SentryHub = window.DiscordSentry?.getCurrentHub?.();
|
||||
if (SentryHub) {
|
||||
SentryHub.getClient()?.close?.(0);
|
||||
const scope = SentryHub.getScope();
|
||||
scope?.clear?.();
|
||||
scope?.setFingerprint?.(null);
|
||||
SentryHub?.setUser(null);
|
||||
SentryHub?.setTags({});
|
||||
SentryHub?.setExtras({});
|
||||
SentryHub?.endSession();
|
||||
}
|
||||
for (const method in console) {
|
||||
if (!Object.hasOwn(console[method], "__sentry_original__")) continue;
|
||||
console[method] = console[method].__sentry_original__;
|
||||
}
|
||||
if (this.settings.stopProcessMonitor) this.disableProcessMonitor();
|
||||
}
|
||||
onStop() {
|
||||
Patcher.unpatchAll(this.meta.name);
|
||||
}
|
||||
disableProcessMonitor() {
|
||||
SettingsManager?.updateAsync("status", (settings) => settings.showCurrentGame = BoolSetting?.create({ value: false }), 0);
|
||||
const DiscordUtils = NativeModule?.getDiscordUtils();
|
||||
if (!DiscordUtils) return UI.alert("DoNotTrack", "Unable to disable process monitor!");
|
||||
DiscordUtils.setObservedGamesCallback([], () => {
|
||||
});
|
||||
Patcher.instead(this.meta.name, DiscordUtils, "setObservedGamesCallback", () => {
|
||||
});
|
||||
}
|
||||
enableProcessMonitor() {
|
||||
SettingsManager?.updateAsync("status", (settings) => settings.showCurrentGame = BoolSetting?.create({ value: true }), 0);
|
||||
UI.showConfirmationModal("Reload Discord?", "To reenable the process monitor Discord needs to be reloaded.", {
|
||||
confirmText: "Reload",
|
||||
cancelText: "Later",
|
||||
onConfirm: () => window.location.reload()
|
||||
});
|
||||
}
|
||||
getSettingsPanel() {
|
||||
return this.buildSettingsPanel((_, id, value) => {
|
||||
if (id !== "stopProcessMonitor") return;
|
||||
if (value) return this.disableProcessMonitor();
|
||||
return this.enableProcessMonitor();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/*@end@*/
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"all": {
|
||||
"cachedState": {
|
||||
"date": "2026-01-24T10:37:57.110Z",
|
||||
"value": false
|
||||
},
|
||||
"general": {
|
||||
"showButton": true,
|
||||
"showItem": false,
|
||||
"playEnable": true,
|
||||
"playDisable": true
|
||||
},
|
||||
"selections": {
|
||||
"enableSound": "stream_started",
|
||||
"disableSound": "stream_ended"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,497 @@
|
||||
/**
|
||||
* @name GameActivityToggle
|
||||
* @author DevilBro
|
||||
* @authorId 278543574059057154
|
||||
* @version 1.3.9
|
||||
* @description Adds a Quick-Toggle Game Activity Button
|
||||
* @invite Jx3TjNS
|
||||
* @donate https://www.paypal.me/MircoWittrien
|
||||
* @patreon https://www.patreon.com/MircoWittrien
|
||||
* @website https://mwittrien.github.io/
|
||||
* @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/GameActivityToggle/
|
||||
* @updateUrl https://mwittrien.github.io/BetterDiscordAddons/Plugins/GameActivityToggle/GameActivityToggle.plugin.js
|
||||
*/
|
||||
|
||||
module.exports = (_ => {
|
||||
const changeLog = {
|
||||
|
||||
};
|
||||
|
||||
return !window.BDFDB_Global || (!window.BDFDB_Global.loaded && !window.BDFDB_Global.started) ? class {
|
||||
constructor (meta) {for (let key in meta) this[key] = meta[key];}
|
||||
getName () {return this.name;}
|
||||
getAuthor () {return this.author;}
|
||||
getVersion () {return this.version;}
|
||||
getDescription () {return `The Library Plugin needed for ${this.name} is missing. Open the Plugin Settings to download it. \n\n${this.description}`;}
|
||||
|
||||
downloadLibrary () {
|
||||
BdApi.Net.fetch("https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js").then(r => {
|
||||
if (!r || r.status != 200) throw new Error();
|
||||
else return r.text();
|
||||
}).then(b => {
|
||||
if (!b) throw new Error();
|
||||
else return require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0BDFDB.plugin.js"), b, _ => BdApi.UI.showToast("Finished downloading BDFDB Library", {type: "success"}));
|
||||
}).catch(error => {
|
||||
BdApi.UI.alert("Error", "Could not download BDFDB Library Plugin. Try again later or download it manually from GitHub: https://mwittrien.github.io/downloader/?library");
|
||||
});
|
||||
}
|
||||
|
||||
load () {
|
||||
if (!window.BDFDB_Global || !Array.isArray(window.BDFDB_Global.pluginQueue)) window.BDFDB_Global = Object.assign({}, window.BDFDB_Global, {pluginQueue: []});
|
||||
if (!window.BDFDB_Global.downloadModal) {
|
||||
window.BDFDB_Global.downloadModal = true;
|
||||
BdApi.UI.showConfirmationModal("Library Missing", `The Library Plugin needed for ${this.name} is missing. Please click "Download Now" to install it.`, {
|
||||
confirmText: "Download Now",
|
||||
cancelText: "Cancel",
|
||||
onCancel: _ => {delete window.BDFDB_Global.downloadModal;},
|
||||
onConfirm: _ => {
|
||||
delete window.BDFDB_Global.downloadModal;
|
||||
this.downloadLibrary();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!window.BDFDB_Global.pluginQueue.includes(this.name)) window.BDFDB_Global.pluginQueue.push(this.name);
|
||||
}
|
||||
start () {this.load();}
|
||||
stop () {}
|
||||
getSettingsPanel () {
|
||||
let template = document.createElement("template");
|
||||
template.innerHTML = `<div style="color: var(--text-strong); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${this.name} is missing.\nPlease click <a style="font-weight: 500;">Download Now</a> to install it.</div>`;
|
||||
template.content.firstElementChild.querySelector("a").addEventListener("click", this.downloadLibrary);
|
||||
return template.content.firstElementChild;
|
||||
}
|
||||
} : (([Plugin, BDFDB]) => {
|
||||
var _this;
|
||||
var toggleButton, toggleItem;
|
||||
|
||||
const ActivityToggleComponent = class ActivityToggle extends BdApi.React.Component {
|
||||
componentDidMount() {
|
||||
toggleButton = this;
|
||||
}
|
||||
render() {
|
||||
const enabled = this.props.forceState != undefined ? this.props.forceState : BDFDB.DiscordUtils.getSetting("status", "showCurrentGame");
|
||||
delete this.props.forceState;
|
||||
return BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN._gameactivitytogglebutton,
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.PanelButton, Object.assign({}, this.props, {
|
||||
redGlow: !enabled,
|
||||
tooltipText: enabled ? _this.labels.disable_activity : _this.labels.enable_activity,
|
||||
icon: iconProps => BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN.lottieicon,
|
||||
style: {
|
||||
"--__lottieIconColor": enabled ? "currentColor" : BDFDB.DiscordConstants.ColorsCSS.STATUS_DANGER,
|
||||
"display": "flex",
|
||||
"width": "20px",
|
||||
"height": "20px"
|
||||
},
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, Object.assign({}, iconProps, {
|
||||
nativeClass: true,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: "var(--__lottieIconColor)",
|
||||
name: enabled ? BDFDB.LibraryComponents.SvgIcon.Names.GAMEPAD : BDFDB.LibraryComponents.SvgIcon.Names.GAMEPAD_DISABLED
|
||||
}))
|
||||
}),
|
||||
onClick: _ => {
|
||||
_this.toggle();
|
||||
if (toggleItem) BDFDB.ReactUtils.forceUpdate(toggleItem);
|
||||
}
|
||||
}))
|
||||
}, true);
|
||||
}
|
||||
};
|
||||
|
||||
const ActivityToggleItemComponent = class ActivityToggleItem extends BdApi.React.Component {
|
||||
componentDidMount() {
|
||||
toggleItem = this;
|
||||
}
|
||||
componentWillUnmount() {
|
||||
toggleItem = null;
|
||||
}
|
||||
render() {
|
||||
const enabled = this.props.forceState != undefined ? this.props.forceState : BDFDB.DiscordUtils.getSetting("status", "showCurrentGame");
|
||||
delete this.props.forceState;
|
||||
return BDFDB.ReactUtils.createElement("li", {
|
||||
className: BDFDB.disCN.userpopoutmenuitem,
|
||||
children: BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN.userpopoutmenuiteminner,
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Clickable, {
|
||||
className: BDFDB.disCN.userpopoutmenuitemcontent,
|
||||
onClick: _ => {
|
||||
_this.toggle();
|
||||
if (toggleButton) BDFDB.ReactUtils.forceUpdate(toggleButton);
|
||||
},
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
|
||||
className: BDFDB.disCN.userpopoutmenuitemicon,
|
||||
name: BDFDB.LibraryComponents.SvgIcon.Names.GAMEPAD,
|
||||
nativeClass: true,
|
||||
width: 16,
|
||||
height: 16
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN.userpopoutmenuitemlabel,
|
||||
children: BDFDB.ReactUtils.createElement("div", {
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TextElement, {
|
||||
className: BDFDB.disCN.userpopoutmenuitemlabel,
|
||||
size: BDFDB.LibraryComponents.TextElement.Sizes.SIZE_14,
|
||||
children: BDFDB.LanguageUtils.LanguageStrings.GAME_ACTIVITY
|
||||
})
|
||||
})
|
||||
})
|
||||
]
|
||||
}),
|
||||
enabled ? BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
|
||||
className: BDFDB.disCN.menucolordefault,
|
||||
background: BDFDB.disCN.menucheckbox,
|
||||
foreground: BDFDB.disCN.menucheck,
|
||||
name: BDFDB.LibraryComponents.SvgIcon.Names.CHECKBOX,
|
||||
style: {background: "unset"}
|
||||
}) : BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
|
||||
className: BDFDB.disCN.menucolordefault,
|
||||
name: BDFDB.LibraryComponents.SvgIcon.Names.CHECKBOX_EMPTY,
|
||||
style: {background: "unset"}
|
||||
})
|
||||
]
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var sounds = [], keybind;
|
||||
|
||||
return class GameActivityToggle extends Plugin {
|
||||
onLoad () {
|
||||
_this = this;
|
||||
|
||||
this.defaults = {
|
||||
general: {
|
||||
showButton: {value: true, description: "Show Quick Toggle Button"},
|
||||
showItem: {value: false, description: "Show Quick Toggle Item"},
|
||||
playEnable: {value: true, description: "Play Enable Sound"},
|
||||
playDisable: {value: true, description: "Play Disable Sound"}
|
||||
},
|
||||
selections: {
|
||||
enableSound: {value: "stream_started", description: "Enable Sound"},
|
||||
disableSound: {value: "stream_ended", description: "Disable Sound"}
|
||||
}
|
||||
};
|
||||
|
||||
this.modulePatches = {
|
||||
after: [
|
||||
"Account",
|
||||
"AccountPopout"
|
||||
]
|
||||
};
|
||||
|
||||
this.css = `
|
||||
${BDFDB.dotCNS._gameactivitytoggleadded + BDFDB.dotCN.accountinfoavatarwrapper} {
|
||||
flex: 1 !important;
|
||||
min-width: 0 !important;
|
||||
}
|
||||
${BDFDB.dotCNS._gameactivitytoggleadded + BDFDB.dotCN._gameactivitytogglebutton} {
|
||||
margin-right: 4px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
onStart () {
|
||||
sounds = [BDFDB.LibraryModules.SoundParser && BDFDB.LibraryModules.SoundParser.keys()].flat(10).filter(n => n).map(s => s.replace("./", "").split(".")[0]).sort();
|
||||
|
||||
let cachedState = BDFDB.DataUtils.load(this, "cachedState");
|
||||
let state = BDFDB.DiscordUtils.getSetting("status", "showCurrentGame");
|
||||
if (!cachedState.date || (new Date() - cachedState.date) > 1000*60*60*24*3) {
|
||||
cachedState.value = state;
|
||||
cachedState.date = new Date();
|
||||
BDFDB.DataUtils.save(cachedState, this, "cachedState");
|
||||
}
|
||||
else if (cachedState.value != null && cachedState.value != state) BDFDB.DiscordUtils.setSetting("status", "showCurrentGame", cachedState.value);
|
||||
|
||||
let SettingsStore = BDFDB.DiscordUtils.getSettingsStore();
|
||||
if (SettingsStore) BDFDB.PatchUtils.patch(this, SettingsStore, "updateAsync", {after: e => {
|
||||
if (e.methodArguments[0] != "status") return;
|
||||
let newSettings = {value: undefined};
|
||||
e.methodArguments[1](newSettings);
|
||||
if (newSettings.showCurrentGame != undefined) {
|
||||
if (toggleButton) toggleButton.props.forceState = newSettings.showCurrentGame.value;
|
||||
BDFDB.ReactUtils.forceUpdate(toggleButton);
|
||||
if (toggleItem) toggleItem.props.forceState = newSettings.showCurrentGame.value;
|
||||
BDFDB.ReactUtils.forceUpdate(toggleItem);
|
||||
BDFDB.DataUtils.save({date: new Date(), value: newSettings.showCurrentGame.value}, this, "cachedState");
|
||||
}
|
||||
}});
|
||||
|
||||
keybind = BDFDB.DataUtils.load(this, "keybind");
|
||||
keybind = BDFDB.ArrayUtils.is(keybind) ? keybind : [];
|
||||
this.activateKeybind();
|
||||
|
||||
BDFDB.DiscordUtils.rerenderAll();
|
||||
}
|
||||
|
||||
onStop () {
|
||||
BDFDB.DiscordUtils.rerenderAll();
|
||||
}
|
||||
|
||||
getSettingsPanel (collapseStates = {}) {
|
||||
let settingsPanel;
|
||||
return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(this, {
|
||||
collapseStates: collapseStates,
|
||||
children: _ => {
|
||||
let settingsItems = [];
|
||||
|
||||
for (let key in this.defaults.general) settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Switch",
|
||||
plugin: this,
|
||||
keys: ["general", key],
|
||||
label: this.defaults.general[key].description,
|
||||
value: this.settings.general[key]
|
||||
}));
|
||||
|
||||
for (let key in this.defaults.selections) settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Select",
|
||||
plugin: this,
|
||||
keys: ["selections", key],
|
||||
label: this.defaults.selections[key].description,
|
||||
basis: "50%",
|
||||
options: sounds.map(o => ({value: o, label: o.split(/[-_]/g).map(BDFDB.StringUtils.upperCaseFirstChar).join(" ")})),
|
||||
value: this.settings.selections[key],
|
||||
onChange: value => BDFDB.LibraryModules.SoundUtils.playSound(value, .4)
|
||||
}));
|
||||
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN.settingsrowcontainer,
|
||||
children: BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN.settingsrowlabel,
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsLabel, {
|
||||
label: "Global Hotkey"
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
|
||||
className: BDFDB.disCNS.settingsrowcontrol + BDFDB.disCN.flexchild,
|
||||
grow: 0,
|
||||
wrap: true,
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.KeybindRecorder, {
|
||||
value: !keybind ? [] : keybind,
|
||||
reset: true,
|
||||
onChange: value => {
|
||||
keybind = value;
|
||||
BDFDB.DataUtils.save(keybind, this, "keybind")
|
||||
this.activateKeybind();
|
||||
}
|
||||
})
|
||||
})
|
||||
].flat(10).filter(n => n)
|
||||
})
|
||||
}));
|
||||
|
||||
return settingsItems;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
processAccount (e) {
|
||||
if (!this.settings.general.showButton) return;
|
||||
let insertButton = returnvalue => {
|
||||
let accountinfo = BDFDB.ReactUtils.findChild(returnvalue, {props: [["className", BDFDB.disCN.accountinfo]]});
|
||||
if (!accountinfo) return;
|
||||
let buttons = BDFDB.ReactUtils.findChild(returnvalue, {props: [["className", BDFDB.disCN.accountinfobuttons]]});
|
||||
if (buttons) {
|
||||
accountinfo.props.className = BDFDB.DOMUtils.formatClassName(accountinfo.props.className, BDFDB.disCN._gameactivitytoggleadded);
|
||||
buttons.props.children.unshift(BDFDB.ReactUtils.createElement(ActivityToggleComponent, {}));
|
||||
}
|
||||
else {
|
||||
let [children, index] = BDFDB.ReactUtils.findParent(returnvalue, {name: "AccountButtons"});
|
||||
if (index > -1) {
|
||||
accountinfo.props.className = BDFDB.DOMUtils.formatClassName(accountinfo.props.className, BDFDB.disCN._gameactivitytoggleadded);
|
||||
children.splice(index, 0, BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN.accountinfobuttons,
|
||||
children: BDFDB.ReactUtils.createElement(ActivityToggleComponent, {})
|
||||
}));
|
||||
}
|
||||
}
|
||||
};
|
||||
if (e.returnvalue.props.children && e.returnvalue.props.children[0] && e.returnvalue.props.children[0].props && typeof e.returnvalue.props.children[0].props.children == "function") {
|
||||
let childrenRender = e.returnvalue.props.children[0].props.children;
|
||||
e.returnvalue.props.children[0].props.children = BDFDB.TimeUtils.suppress((...args) => {
|
||||
let renderedChildren = childrenRender(...args);
|
||||
insertButton(renderedChildren);
|
||||
return renderedChildren;
|
||||
}, "Error in Children Render in Account!", this);
|
||||
}
|
||||
else if (typeof e.returnvalue.props.children[0] == "function") {
|
||||
let childrenRender = e.returnvalue.props.children;
|
||||
e.returnvalue.props.children = BDFDB.TimeUtils.suppress((...args) => {
|
||||
let renderedChildren = childrenRender(...args);
|
||||
insertButton(renderedChildren);
|
||||
return renderedChildren;
|
||||
}, "Error in Children Render in Account!", this);
|
||||
}
|
||||
else insertButton(e.returnvalue.props.children);
|
||||
}
|
||||
|
||||
processAccountPopout (e) {
|
||||
if (!this.settings.general.showItem) return;
|
||||
let userpopoutMenus = BDFDB.ReactUtils.findChild(e.returnvalue, {props: [["className", BDFDB.disCN.userpopoutmenus]]});
|
||||
if (!userpopoutMenus) return;
|
||||
userpopoutMenus.props.children.splice(1, 0, BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCNS.userpopoutoverlay + BDFDB.disCN.userpopoutmenuoverlay,
|
||||
children: BDFDB.ReactUtils.createElement("ul", {
|
||||
children: BDFDB.ReactUtils.createElement(ActivityToggleItemComponent, {})
|
||||
})
|
||||
}));
|
||||
}
|
||||
|
||||
activateKeybind () {
|
||||
if (keybind && keybind.length) BDFDB.ListenerUtils.addGlobal(this, "GAMEACTIVITY_TOGGLE", keybind, _ => this.toggle());
|
||||
else BDFDB.ListenerUtils.removeGlobal(this, "GAMEACTIVITY_TOGGLE");
|
||||
}
|
||||
|
||||
toggle () {
|
||||
const shouldEnable = !BDFDB.DiscordUtils.getSetting("status", "showCurrentGame");
|
||||
this.settings.general[shouldEnable ? "playEnable" : "playDisable"] && BDFDB.LibraryModules.SoundUtils.playSound(this.settings.selections[shouldEnable ? "enableSound" : "disableSound"], .4);
|
||||
BDFDB.DiscordUtils.setSetting("status", "showCurrentGame", shouldEnable);
|
||||
}
|
||||
|
||||
setLabelsByLanguage () {
|
||||
switch (BDFDB.LanguageUtils.getLanguage().id) {
|
||||
case "bg": // Bulgarian
|
||||
return {
|
||||
disable_activity: "Деактивирайте активността в играта",
|
||||
enable_activity: "Активирайте Game Activity"
|
||||
};
|
||||
case "da": // Danish
|
||||
return {
|
||||
disable_activity: "Deaktiver spilaktivitet",
|
||||
enable_activity: "Aktivér spilaktivitet"
|
||||
};
|
||||
case "de": // German
|
||||
return {
|
||||
disable_activity: "Spieleaktivität deaktivieren",
|
||||
enable_activity: "Spieleaktivität aktivieren"
|
||||
};
|
||||
case "el": // Greek
|
||||
return {
|
||||
disable_activity: "Απενεργοποίηση δραστηριότητας παιχνιδιού",
|
||||
enable_activity: "Ενεργοποίηση δραστηριότητας παιχνιδιού"
|
||||
};
|
||||
case "es": // Spanish
|
||||
return {
|
||||
disable_activity: "Deshabilitar la actividad del juego",
|
||||
enable_activity: "Habilitar la actividad del juego"
|
||||
};
|
||||
case "fi": // Finnish
|
||||
return {
|
||||
disable_activity: "Poista pelitoiminto käytöstä",
|
||||
enable_activity: "Ota pelitoiminta käyttöön"
|
||||
};
|
||||
case "fr": // French
|
||||
return {
|
||||
disable_activity: "Désactiver l'activité de jeu",
|
||||
enable_activity: "Activer l'activité de jeu"
|
||||
};
|
||||
case "hr": // Croatian
|
||||
return {
|
||||
disable_activity: "Onemogući aktivnost igre",
|
||||
enable_activity: "Omogući aktivnost u igrama"
|
||||
};
|
||||
case "hu": // Hungarian
|
||||
return {
|
||||
disable_activity: "Tiltsa le a játéktevékenységet",
|
||||
enable_activity: "Engedélyezze a játéktevékenységet"
|
||||
};
|
||||
case "it": // Italian
|
||||
return {
|
||||
disable_activity: "Disabilita l'attività di gioco",
|
||||
enable_activity: "Abilita attività di gioco"
|
||||
};
|
||||
case "ja": // Japanese
|
||||
return {
|
||||
disable_activity: "ゲームアクティビティを無効にする",
|
||||
enable_activity: "ゲームアクティビティを有効にする"
|
||||
};
|
||||
case "ko": // Korean
|
||||
return {
|
||||
disable_activity: "게임 활동 비활성화",
|
||||
enable_activity: "게임 활동 활성화"
|
||||
};
|
||||
case "lt": // Lithuanian
|
||||
return {
|
||||
disable_activity: "Išjungti žaidimų veiklą",
|
||||
enable_activity: "Įgalinti žaidimų veiklą"
|
||||
};
|
||||
case "nl": // Dutch
|
||||
return {
|
||||
disable_activity: "Schakel spelactiviteit uit",
|
||||
enable_activity: "Schakel spelactiviteit in"
|
||||
};
|
||||
case "no": // Norwegian
|
||||
return {
|
||||
disable_activity: "Deaktiver spillaktivitet",
|
||||
enable_activity: "Aktiver spillaktivitet"
|
||||
};
|
||||
case "pl": // Polish
|
||||
return {
|
||||
disable_activity: "Wyłącz aktywność w grach",
|
||||
enable_activity: "Włącz aktywność w grach"
|
||||
};
|
||||
case "pt-BR": // Portuguese (Brazil)
|
||||
return {
|
||||
disable_activity: "Desativar atividade de jogo",
|
||||
enable_activity: "Habilitar atividade de jogo"
|
||||
};
|
||||
case "ro": // Romanian
|
||||
return {
|
||||
disable_activity: "Dezactivați Activitatea jocului",
|
||||
enable_activity: "Activați Activitatea jocului"
|
||||
};
|
||||
case "ru": // Russian
|
||||
return {
|
||||
disable_activity: "Отключить игровую активность",
|
||||
enable_activity: "Включить игровую активность"
|
||||
};
|
||||
case "sv": // Swedish
|
||||
return {
|
||||
disable_activity: "Inaktivera spelaktivitet",
|
||||
enable_activity: "Aktivera spelaktivitet"
|
||||
};
|
||||
case "th": // Thai
|
||||
return {
|
||||
disable_activity: "ปิดการใช้งานกิจกรรมของเกม",
|
||||
enable_activity: "เปิดใช้งานกิจกรรมเกม"
|
||||
};
|
||||
case "tr": // Turkish
|
||||
return {
|
||||
disable_activity: "Oyun Etkinliğini Devre Dışı Bırak",
|
||||
enable_activity: "Oyun Etkinliğini Etkinleştir"
|
||||
};
|
||||
case "uk": // Ukrainian
|
||||
return {
|
||||
disable_activity: "Вимкнути ігрову активність",
|
||||
enable_activity: "Увімкнути ігрову активність"
|
||||
};
|
||||
case "vi": // Vietnamese
|
||||
return {
|
||||
disable_activity: "Tắt hoạt động trò chơi",
|
||||
enable_activity: "Bật hoạt động trò chơi"
|
||||
};
|
||||
case "zh-CN": // Chinese (China)
|
||||
return {
|
||||
disable_activity: "禁用游戏活动",
|
||||
enable_activity: "启用游戏活动"
|
||||
};
|
||||
case "zh-TW": // Chinese (Taiwan)
|
||||
return {
|
||||
disable_activity: "禁用遊戲活動",
|
||||
enable_activity: "啟用遊戲活動"
|
||||
};
|
||||
default: // English
|
||||
return {
|
||||
disable_activity: "Disable Game Activity",
|
||||
enable_activity: "Enable Game Activity"
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
})(window.BDFDB_Global.PluginUtils.buildPlugin(changeLog));
|
||||
})();
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "1.0.1",
|
||||
"hasShownChangelog": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "1.1.13",
|
||||
"hasShownChangelog": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "1.2.2",
|
||||
"hasShownChangelog": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* @name InMyVoice
|
||||
* @author arg0NNY
|
||||
* @authorLink https://github.com/arg0NNY/DiscordPlugins
|
||||
* @invite M8DBtcZjXD
|
||||
* @donate https://donationalerts.com/r/arg0nny
|
||||
* @version 1.2.2
|
||||
* @description Shows if a person in the text chat is also in a voice chat you're in.
|
||||
* @website https://github.com/arg0NNY/DiscordPlugins/tree/master/InMyVoice
|
||||
* @source https://github.com/arg0NNY/DiscordPlugins/blob/master/InMyVoice/InMyVoice.plugin.js
|
||||
* @updateUrl https://raw.githubusercontent.com/arg0NNY/DiscordPlugins/master/InMyVoice/InMyVoice.plugin.js
|
||||
*/
|
||||
|
||||
/* ### CONFIG START ### */
|
||||
const config = {
|
||||
info: {
|
||||
name: 'InMyVoice',
|
||||
version: '1.2.2',
|
||||
description: 'Shows if a person in the text chat is also in a voice chat you\'re in.'
|
||||
},
|
||||
changelog: [
|
||||
{
|
||||
type: 'fixed',
|
||||
title: 'Fixes',
|
||||
items: [
|
||||
'Updated to work in the latest release of Discord.'
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
/* ### CONFIG END ### */
|
||||
|
||||
const {
|
||||
Webpack,
|
||||
UI,
|
||||
React,
|
||||
Patcher,
|
||||
Utils,
|
||||
Data
|
||||
} = new BdApi(config.info.name)
|
||||
|
||||
const UserStore = Webpack.getStore('UserStore')
|
||||
const ChannelStore = Webpack.getStore('ChannelStore')
|
||||
const SelectedChannelStore = Webpack.getStore('SelectedChannelStore')
|
||||
|
||||
const findInReactTree = (tree, searchFilter) => Utils.findInTree(tree, searchFilter, { walkable: ['props', 'children', 'child', 'sibling'] })
|
||||
|
||||
const Selectors = {
|
||||
BotTag: {
|
||||
botTagCozy: Webpack.getByKeys('botTagCozy').botTagCozy,
|
||||
botTagVerified: Webpack.getByKeys('botTagVerified').botTagVerified
|
||||
}
|
||||
}
|
||||
|
||||
const UNIQUE_TAG = 'InMyVoiceTag'
|
||||
|
||||
const VoiceChannelStore = Webpack.getByKeys('getVoiceStatesForChannel')
|
||||
const MessageHeader = [...Webpack.getWithKey(Webpack.Filters.byStrings('decorations', 'withMentionPrefix'))]
|
||||
const BotTag = [...Webpack.getWithKey(m => m?.Types?.SYSTEM_DM)]
|
||||
const useStateFromStores = Webpack.getModule(Webpack.Filters.byStrings('useStateFromStores'), { searchExports: true })
|
||||
|
||||
function isInMyVoice (user) {
|
||||
const voiceChannelId = useStateFromStores([SelectedChannelStore], () => SelectedChannelStore.getVoiceChannelId())
|
||||
const currentUser = useStateFromStores([UserStore], () => UserStore.getCurrentUser())
|
||||
const channel = useStateFromStores([ChannelStore], () => voiceChannelId && ChannelStore.getChannel(voiceChannelId))
|
||||
const voiceState = useStateFromStores([VoiceChannelStore], () => channel && VoiceChannelStore.getVoiceStatesForChannel(channel))
|
||||
|
||||
if (currentUser.id === user.id || !channel) return false
|
||||
|
||||
const values = Object.values(voiceState)
|
||||
return values.findIndex(x => x.user?.id === user.id) !== -1
|
||||
}
|
||||
|
||||
function InVoiceTag ({ user }) {
|
||||
if (!isInMyVoice(user)) return null
|
||||
|
||||
return React.createElement(BotTag[0][BotTag[1]], {
|
||||
className: `${Selectors.BotTag.botTagCozy} ${UNIQUE_TAG}`,
|
||||
useRemSizes: true,
|
||||
type: 'IN_VOICE'
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = class InMyVoice {
|
||||
start () {
|
||||
this.patches()
|
||||
}
|
||||
|
||||
patches () {
|
||||
this.patchMessages()
|
||||
this.patchBotTags()
|
||||
}
|
||||
|
||||
patchMessages () {
|
||||
Patcher.before(...MessageHeader, (self, [{ decorations, message }]) => {
|
||||
if (!decorations || typeof decorations[1] !== 'object' || !'length' in decorations[1]) return
|
||||
|
||||
decorations[1].unshift(
|
||||
React.createElement(InVoiceTag, { user: message.author })
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
patchBotTags () {
|
||||
Patcher.after(...BotTag, (self, _, value) => {
|
||||
if (!value?.props?.className?.includes(UNIQUE_TAG)) return
|
||||
|
||||
const TagContainer = findInReactTree(value, e => e.children?.some(c => typeof c?.props?.children === 'string'))
|
||||
|
||||
TagContainer.children.find(c => typeof c?.props?.children === 'string').props.children = this.settings.text.toUpperCase()
|
||||
TagContainer.children.unshift(this.buildInVoiceIcon())
|
||||
})
|
||||
}
|
||||
|
||||
buildInVoiceIcon () {
|
||||
return React.createElement(
|
||||
'svg',
|
||||
{
|
||||
className: Selectors.BotTag.botTagVerified,
|
||||
width: 16,
|
||||
height: 16,
|
||||
viewBox: '0 0 28 28',
|
||||
style: {
|
||||
position: 'relative',
|
||||
top: '1px',
|
||||
left: '1px',
|
||||
marginRight: '1px'
|
||||
}
|
||||
},
|
||||
React.createElement('path', {
|
||||
fill: 'currentColor',
|
||||
d: 'M3 10v4c0 .55.45 1 1 1h3l3.29 3.29c.63.63 1.71.18 1.71-.71V6.41c0-.89-1.08-1.34-1.71-.71L7 9H4c-.55 0-1 .45-1 1zm13.5 2c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 4.45v.2c0 .38.25.71.6.85C17.18 6.53 19 9.06 19 12s-1.82 5.47-4.4 6.5c-.36.14-.6.47-.6.85v.2c0 .63.63 1.07 1.21.85C18.6 19.11 21 15.84 21 12s-2.4-7.11-5.79-8.4c-.58-.23-1.21.22-1.21.85z'
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
stop () {
|
||||
Patcher.unpatchAll()
|
||||
}
|
||||
|
||||
constructor () {
|
||||
this.defaultSettings = {
|
||||
text: 'In voice'
|
||||
}
|
||||
|
||||
this.settings = this.loadSettings(this.defaultSettings)
|
||||
|
||||
this.showChangelogIfNeeded()
|
||||
}
|
||||
|
||||
loadSettings (defaults = {}) {
|
||||
return Utils.extend({}, defaults, Data.load('settings'))
|
||||
}
|
||||
saveSettings (settings = this.settings) {
|
||||
return Data.save('settings', settings)
|
||||
}
|
||||
|
||||
showChangelogIfNeeded () {
|
||||
const currentVersionInfo = Utils.extend(
|
||||
{ version: config.info.version, hasShownChangelog: false },
|
||||
Data.load('currentVersionInfo')
|
||||
)
|
||||
if (currentVersionInfo.version === config.info.version && currentVersionInfo.hasShownChangelog) return
|
||||
|
||||
this.showChangelog()
|
||||
Data.save('currentVersionInfo', { version: config.info.version, hasShownChangelog: true })
|
||||
}
|
||||
showChangelog () {
|
||||
return UI.showChangelogModal({
|
||||
title: config.info.name,
|
||||
subtitle: 'Version ' + config.info.version,
|
||||
changes: config.changelog
|
||||
})
|
||||
}
|
||||
|
||||
getSettingsPanel () {
|
||||
return UI.buildSettingsPanel({
|
||||
onChange: () => this.saveSettings(),
|
||||
settings: [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'text',
|
||||
name: 'Tag Text',
|
||||
note: 'Sets up tag\'s text near user\'s name.',
|
||||
value: this.settings.text,
|
||||
onChange: e => this.settings.text = e
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"lastVersion": "2.0.10"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,420 @@
|
||||
{
|
||||
"all": {
|
||||
"choices": {
|
||||
"activity_end": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"activity_launch": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"activity_user_join": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"activity_user_left": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"call_calling": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": null,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"call_ringing": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": null,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"call_ringing_snow_halation": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": null,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"call_ringing_snowsgiving": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": null,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"clip_error": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"clip_save": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"deafen": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"disconnect": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"highfive_clap": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"highfive_whistle": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"ddr-down": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"ddr-left": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"ddr-right": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"ddr-up": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"reconnect": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"message1": {
|
||||
"category": "Discord",
|
||||
"invisibleMute": false,
|
||||
"mute": true,
|
||||
"sound": "Message (Current Channel)",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"message3": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": true,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"dm": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": true,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"groupdm": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": true,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"mentioned": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": true,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"everyone": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": true,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"here": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": true,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"reply": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": true,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"role": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": true,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"mute": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"ptt_start": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"ptt_stop": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"stage_waiting": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"stream_ended": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"stream_started": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"stream_user_joined": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"stream_user_left": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"success": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"undeafen": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"unmute": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"vibing_wumpus": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"user_join": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"user_leave": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"user_moved": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"voice_filter_loopback_off": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"voice_filter_loopback_on": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"voice_filter_off": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"voice_filter_on": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"voice_filter_swap": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"camera_off": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"camera_on": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
},
|
||||
"hang_status_select": {
|
||||
"category": "---",
|
||||
"invisibleMute": false,
|
||||
"mute": false,
|
||||
"sound": "---",
|
||||
"streamMute": false,
|
||||
"volume": 100
|
||||
}
|
||||
},
|
||||
"toggles": {
|
||||
"playIfMuted": false
|
||||
},
|
||||
"volumes": {
|
||||
"globalVolume": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,765 @@
|
||||
/**
|
||||
* @name NotificationSounds
|
||||
* @author DevilBro
|
||||
* @authorId 278543574059057154
|
||||
* @version 4.0.7
|
||||
* @description Allows you to replace the native Sounds with custom Sounds
|
||||
* @invite Jx3TjNS
|
||||
* @donate https://www.paypal.me/MircoWittrien
|
||||
* @patreon https://www.patreon.com/MircoWittrien
|
||||
* @website https://mwittrien.github.io/
|
||||
* @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/NotificationSounds/
|
||||
* @updateUrl https://mwittrien.github.io/BetterDiscordAddons/Plugins/NotificationSounds/NotificationSounds.plugin.js
|
||||
*/
|
||||
|
||||
module.exports = (_ => {
|
||||
const changeLog = {
|
||||
|
||||
};
|
||||
|
||||
return !window.BDFDB_Global || (!window.BDFDB_Global.loaded && !window.BDFDB_Global.started) ? class {
|
||||
constructor (meta) {for (let key in meta) this[key] = meta[key];}
|
||||
getName () {return this.name;}
|
||||
getAuthor () {return this.author;}
|
||||
getVersion () {return this.version;}
|
||||
getDescription () {return `The Library Plugin needed for ${this.name} is missing. Open the Plugin Settings to download it. \n\n${this.description}`;}
|
||||
|
||||
downloadLibrary () {
|
||||
BdApi.Net.fetch("https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js").then(r => {
|
||||
if (!r || r.status != 200) throw new Error();
|
||||
else return r.text();
|
||||
}).then(b => {
|
||||
if (!b) throw new Error();
|
||||
else return require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0BDFDB.plugin.js"), b, _ => BdApi.UI.showToast("Finished downloading BDFDB Library", {type: "success"}));
|
||||
}).catch(error => {
|
||||
BdApi.UI.alert("Error", "Could not download BDFDB Library Plugin. Try again later or download it manually from GitHub: https://mwittrien.github.io/downloader/?library");
|
||||
});
|
||||
}
|
||||
|
||||
load () {
|
||||
if (!window.BDFDB_Global || !Array.isArray(window.BDFDB_Global.pluginQueue)) window.BDFDB_Global = Object.assign({}, window.BDFDB_Global, {pluginQueue: []});
|
||||
if (!window.BDFDB_Global.downloadModal) {
|
||||
window.BDFDB_Global.downloadModal = true;
|
||||
BdApi.UI.showConfirmationModal("Library Missing", `The Library Plugin needed for ${this.name} is missing. Please click "Download Now" to install it.`, {
|
||||
confirmText: "Download Now",
|
||||
cancelText: "Cancel",
|
||||
onCancel: _ => {delete window.BDFDB_Global.downloadModal;},
|
||||
onConfirm: _ => {
|
||||
delete window.BDFDB_Global.downloadModal;
|
||||
this.downloadLibrary();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!window.BDFDB_Global.pluginQueue.includes(this.name)) window.BDFDB_Global.pluginQueue.push(this.name);
|
||||
}
|
||||
start () {this.load();}
|
||||
stop () {}
|
||||
getSettingsPanel () {
|
||||
let template = document.createElement("template");
|
||||
template.innerHTML = `<div style="color: var(--text-strong); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${this.name} is missing.\nPlease click <a style="font-weight: 500;">Download Now</a> to install it.</div>`;
|
||||
template.content.firstElementChild.querySelector("a").addEventListener("click", this.downloadLibrary);
|
||||
return template.content.firstElementChild;
|
||||
}
|
||||
} : (([Plugin, BDFDB]) => {
|
||||
var audios, choices, firedEvents;
|
||||
var volumes = {};
|
||||
var toggles = {};
|
||||
|
||||
const removeAllKey = "REMOVE_ALL_BDFDB_DEVILBRO_DO_NOT_COPY";
|
||||
const defaultDevice = "default";
|
||||
|
||||
var currentDevice = defaultDevice, createdAudios = {};
|
||||
|
||||
let types = {}, soundPacks = [];
|
||||
|
||||
const message1Types = {
|
||||
dm: {src: "./message3.mp3", name: "Message (Direct Message)"},
|
||||
groupdm: {src: "./message3.mp3", name: "Message (Group Message)"},
|
||||
mentioned: {src: "./message2.mp3", name: "Message Mentioned"},
|
||||
reply: {src: "./message2.mp3", name: "Message Mentioned (reply)"},
|
||||
role: {src: "./mention1.mp3", name: "Message Mentioned (role)"},
|
||||
everyone: {src: "./mention2.mp3", name: "Message Mentioned (@everyone)"},
|
||||
here: {src: "./mention3.mp3", name: "Message Mentioned (@here)"}
|
||||
};
|
||||
|
||||
const namePrefixes = {
|
||||
"user_join": "Voice Channel",
|
||||
"user_leave": "Voice Channel",
|
||||
"user_moved": "Voice Channel"
|
||||
};
|
||||
|
||||
const nameSynonymes = {
|
||||
"message3": "Message (Current Channel)",
|
||||
"reconnect": "Invited To Speak"
|
||||
};
|
||||
|
||||
const defaultAudios = {
|
||||
"---": {
|
||||
"---": null
|
||||
},
|
||||
"Discord": {}
|
||||
};
|
||||
|
||||
const WebAudioSound = class WebAudioSound {
|
||||
constructor (type) {
|
||||
this.name = type;
|
||||
this._src = choices[type] && audios[choices[type].category][choices[type].sound] || types[type] && types[type].src || BDFDB.LibraryModules.SoundParser(`./${type}.mp3`);
|
||||
this._volume = (choices[type] ? choices[type].volume : 100) / 100;
|
||||
}
|
||||
loop () {
|
||||
this._ensureAudio().then(audio => {
|
||||
audio.loop = true;
|
||||
audio.play();
|
||||
});
|
||||
}
|
||||
play () {
|
||||
this._ensureAudio().then(audio => {
|
||||
audio.loop = false;
|
||||
audio.play();
|
||||
});
|
||||
}
|
||||
playWithListener (duration) {
|
||||
return new Promise((callback, errorCallback) => {
|
||||
this._ensureAudio().then(audio => {
|
||||
if (!duration && duration !== 0) errorCallback(new Error("sound has no duration"));
|
||||
audio.loop = false;
|
||||
audio.play();
|
||||
setTimeout(_ => callback(true), duration);
|
||||
});
|
||||
});
|
||||
}
|
||||
pause () {
|
||||
this._audio.then(audio => {
|
||||
audio.pause();
|
||||
});
|
||||
}
|
||||
stop () {
|
||||
this._destroyAudio();
|
||||
}
|
||||
setTime (time) {
|
||||
this._audio.then(audio => {
|
||||
audio.currentTime = time;
|
||||
});
|
||||
}
|
||||
setLoop (loop) {
|
||||
this._audio.then(audio => {
|
||||
audio.loop = loop;
|
||||
});
|
||||
}
|
||||
_destroyAudio () {
|
||||
if (this._audio) {
|
||||
this._audio.then(audio => {
|
||||
audio.pause();
|
||||
audio.src = "";
|
||||
});
|
||||
this._audio = null;
|
||||
}
|
||||
}
|
||||
_ensureAudio () {
|
||||
return this._audio = this._audio || new Promise((callback, errorCallback) => {
|
||||
let audio = new Audio;
|
||||
audio.src = this._src && this._src.startsWith("data") ? this._src.replace(/ /g, "") : this._src;
|
||||
audio.onloadeddata = _ => {
|
||||
audio.volume = Math.min((BDFDB.LibraryStores.MediaEngineStore.getOutputVolume() / 100) * this._volume * (volumes.globalVolume / 100), 1);
|
||||
BDFDB.DiscordUtils.isPlaformEmbedded() && audio.setSinkId(currentDevice || defaultDevice);
|
||||
callback(audio);
|
||||
};
|
||||
audio.onerror = _ => errorCallback(new Error("could not play audio"));
|
||||
audio.onended = _ => this._destroyAudio();
|
||||
audio.load();
|
||||
}), this._audio;
|
||||
}
|
||||
};
|
||||
|
||||
return class NotificationSounds extends Plugin {
|
||||
onLoad () {
|
||||
audios = {};
|
||||
choices = {};
|
||||
firedEvents = {};
|
||||
|
||||
this.defaults = {
|
||||
volumes: {
|
||||
globalVolume: {value: 100, description: "Global Notification Sounds Volume"}
|
||||
},
|
||||
toggles: {
|
||||
playIfMuted: {value: false, description: "Play Sounds Of Muted Channels/Servers"}
|
||||
}
|
||||
};
|
||||
|
||||
this.patchPriority = 9;
|
||||
}
|
||||
|
||||
onStart () {
|
||||
soundPacks = [];
|
||||
const soundKeys = BDFDB.LibraryModules.SoundParser.keys();
|
||||
for (let key of soundKeys) {
|
||||
const id = key.replace("./", "").replace(".mp3", "");
|
||||
const name = [namePrefixes[id], (nameSynonymes[id] || id).replace("ddr-", "HotKeys_").replace("ptt_", "Push2Talk_").split(/[_-]/)].flat(10).filter(n => n).map(BDFDB.StringUtils.upperCaseFirstChar).join(" ").replace(/1$/g, "");
|
||||
const src = BDFDB.LibraryModules.SoundParser(key);
|
||||
|
||||
let soundPackName = id.split("_")[0];
|
||||
if (soundPackName != id && soundKeys.filter(n => n.indexOf(`./${soundPackName}`) > -1).length > 8) {
|
||||
soundPacks.push(soundPackName);
|
||||
soundPackName = BDFDB.StringUtils.upperCaseFirstChar(soundPackName);
|
||||
if (!defaultAudios[soundPackName]) defaultAudios[soundPackName] = {};
|
||||
defaultAudios[soundPackName][name.replace(new RegExp(`${soundPackName} `, "i"), "").replace(/bootup/i, "Discodo")] = src;
|
||||
}
|
||||
else {
|
||||
defaultAudios.Discord[name] = src;
|
||||
if (this.isSoundUsedAnywhere(id)) types[id] = {
|
||||
name: name,
|
||||
src: src,
|
||||
mute: id.startsWith("call_") ? null : false,
|
||||
streamMute: false,
|
||||
invisibleMute: false
|
||||
};
|
||||
if (id == "message1" || id == "message3") {
|
||||
types[id].mute = true;
|
||||
types[id].streamMute = false;
|
||||
types[id].invisibleMute = false;
|
||||
if (id == "message1") for (let subType in message1Types) types[subType] = {
|
||||
name: message1Types[subType].name,
|
||||
src: BDFDB.LibraryModules.SoundParser(message1Types[subType].src),
|
||||
mute: true,
|
||||
streamMute: false,
|
||||
invisibleMute: false
|
||||
}
|
||||
}
|
||||
}
|
||||
types = BDFDB.ObjectUtils.sort(types, "name");
|
||||
}
|
||||
for (let pack in defaultAudios) defaultAudios[pack] = BDFDB.ObjectUtils.sort(defaultAudios[pack]);
|
||||
|
||||
if (BDFDB.DiscordUtils.isPlaformEmbedded()) {
|
||||
let change = _ => {
|
||||
if (window.navigator.mediaDevices && window.navigator.mediaDevices.enumerateDevices) {
|
||||
window.navigator.mediaDevices.enumerateDevices().then(enumeratedDevices => {
|
||||
let id = BDFDB.LibraryStores.MediaEngineStore.getOutputDeviceId();
|
||||
let allDevices = BDFDB.LibraryStores.MediaEngineStore.getOutputDevices();
|
||||
let filteredDevices = enumeratedDevices.filter(d => d.kind == "audiooutput" && d.deviceId != "communications");
|
||||
let deviceIndex = BDFDB.LibraryModules.ArrayUtils(allDevices).sortBy(d => d.index).findIndex(d => d.id == id);
|
||||
let deviceViaId = allDevices[id];
|
||||
let deviceViaIndex = filteredDevices[deviceIndex];
|
||||
if (deviceViaId && deviceViaIndex && deviceViaIndex.label != deviceViaId.name) deviceViaIndex = filteredDevices.find(d => d.label == deviceViaId.name);
|
||||
currentDevice = deviceViaIndex ? deviceViaIndex.deviceId : defaultDevice;
|
||||
}).catch(_ => {
|
||||
currentDevice = defaultDevice;
|
||||
});
|
||||
}
|
||||
};
|
||||
BDFDB.StoreChangeUtils.add(this, BDFDB.LibraryStores.MediaEngineStore, change);
|
||||
change();
|
||||
}
|
||||
|
||||
BDFDB.PatchUtils.patch(this, BDFDB.LibraryModules.DispatchApiUtils, "dispatch", {after: e => {
|
||||
if (BDFDB.ObjectUtils.is(e.methodArguments[0]) && (e.methodArguments[0].type == "CALL_DELETE" || e.methodArguments[0].type == "CALL_UPDATE" && !e.methodArguments[0].ringing.includes(BDFDB.UserUtils.me.id))) {
|
||||
["call_ringing", "call_calling"].forEach(type => {
|
||||
if (createdAudios[type]) createdAudios[type].stop();
|
||||
});
|
||||
}
|
||||
|
||||
}, before: e => {
|
||||
if (BDFDB.ObjectUtils.is(e.methodArguments[0]) && e.methodArguments[0].type == "MESSAGE_CREATE" && e.methodArguments[0].message) {
|
||||
const message = e.methodArguments[0].message;
|
||||
const guildId = message.guild_id || null;
|
||||
if (message.author.id != BDFDB.UserUtils.me.id && !BDFDB.LibraryStores.RelationshipStore.isBlocked(message.author.id)) {
|
||||
const channel = BDFDB.LibraryStores.ChannelStore.getChannel(message.channel_id);
|
||||
|
||||
const isCurrent = BDFDB.LibraryStores.SelectedChannelStore.getChannelId() == channel.id;
|
||||
const isGroupDM = channel.isGroupDM();
|
||||
const isThread = BDFDB.ChannelUtils.isThread(channel);
|
||||
const isCurrentAndFocused = isCurrent && document.hasFocus();
|
||||
|
||||
if (!toggles.playIfMuted) {
|
||||
if ((isThread && BDFDB.LibraryStores.JoinedThreadsStore.isMuted(channel.id)) || (!isThread && BDFDB.LibraryStores.UserGuildSettingsStore.isGuildOrCategoryOrChannelMuted(guildId, channel.id))) return;
|
||||
}
|
||||
|
||||
if (isCurrent && BDFDB.LibraryStores.NotificationSettingsStore.getNotifyMessagesInSelectedChannel()) {
|
||||
this.fireEvent("message3");
|
||||
this.playAudio("message3");
|
||||
return;
|
||||
}
|
||||
else if (!guildId) {
|
||||
this.fireEvent(isGroupDM ? "groupdm" : "dm");
|
||||
!isCurrentAndFocused && this.playAudio(isGroupDM ? "groupdm" : "dm");
|
||||
return;
|
||||
}
|
||||
else if (guildId) {
|
||||
if (BDFDB.LibraryModules.MentionUtils.isRawMessageMentioned({rawMessage: message, userId: BDFDB.UserUtils.me.id})) {
|
||||
if (message.mentions.length && !this.isSuppressMentionsEnabled(guildId, channel.id)) for (const mention of message.mentions) if (mention.id == BDFDB.UserUtils.me.id) {
|
||||
if (message.message_reference && !message.interaction) {
|
||||
this.fireEvent("reply");
|
||||
!isCurrentAndFocused && this.playAudio("reply");
|
||||
return;
|
||||
}
|
||||
if (!message.message_reference) {
|
||||
this.fireEvent("mentioned");
|
||||
!isCurrentAndFocused && this.playAudio("mentioned");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (message.mention_roles.length && !BDFDB.LibraryStores.UserGuildSettingsStore.isSuppressRolesEnabled(guildId, channel.id)) {
|
||||
const member = BDFDB.LibraryStores.GuildMemberStore.getMember(guildId, BDFDB.UserUtils.me.id);
|
||||
if (member && member.roles.length) for (const roleId of message.mention_roles) if (member.roles.includes(roleId)) {
|
||||
this.fireEvent("role");
|
||||
!isCurrentAndFocused && this.playAudio("role");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (message.mention_everyone && !BDFDB.LibraryStores.UserGuildSettingsStore.isSuppressEveryoneEnabled(guildId, channel.id)) {
|
||||
if (message.content.indexOf("@everyone") > -1) {
|
||||
this.fireEvent("everyone");
|
||||
!isCurrentAndFocused && this.playAudio("everyone");
|
||||
return;
|
||||
}
|
||||
if (message.content.indexOf("@here") > -1) {
|
||||
this.fireEvent("here");
|
||||
!isCurrentAndFocused && this.playAudio("here");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (BDFDB.LibraryStores.UserGuildSettingsStore.allowAllMessages(channel) && !(isThread && !BDFDB.LibraryStores.JoinedThreadsStore.hasJoined(channel.id))) {
|
||||
this.fireEvent("message1");
|
||||
!isCurrentAndFocused && this.playAudio("message1");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}});
|
||||
|
||||
BDFDB.PatchUtils.patch(this, BDFDB.LibraryModules.DesktopNotificationUtils, "showNotification", {before: e => {
|
||||
let soundObjIndex = Array.from(e.methodArguments).findIndex(n => n && n.sound);
|
||||
if (soundObjIndex && e.methodArguments[soundObjIndex].sound.includes("message")) e.methodArguments[soundObjIndex].sound = null;
|
||||
}});
|
||||
if (BDFDB.LibraryModules.SoundUtils && BDFDB.LibraryModules.SoundUtils.createSound) {
|
||||
let cancel = BDFDB.PatchUtils.patch(this, BDFDB.LibraryModules.SoundUtils, "createSound", {after: e => {
|
||||
if (e.returnValue && e.returnValue.constructor && e.returnValue.constructor.prototype && typeof e.returnValue.constructor.prototype.play == "function") {
|
||||
cancel();
|
||||
BDFDB.PatchUtils.patch(this, e.returnValue.constructor.prototype, ["play", "loop", "playWithListener"], {instead: e2 => {
|
||||
let type = e2.instance && e2.instance.name;
|
||||
if (type && choices[type]) {
|
||||
e2.stopOriginalMethodCall();
|
||||
if (type == "message1" || type == "message3") BDFDB.TimeUtils.timeout(_ => {
|
||||
let called = false;
|
||||
for (let subType of [type].concat(Object.keys(message1Types))) if (firedEvents[subType]) {
|
||||
delete firedEvents[subType];
|
||||
called = true;
|
||||
break;
|
||||
}
|
||||
if (!called) return this.playAudio(type, e2.originalMethodName, e2.instance.duration);
|
||||
});
|
||||
else return this.playAudio(type, e2.originalMethodName, e2.instance.duration);
|
||||
}
|
||||
else return this.playAudio(type, e2.originalMethodName, e2.instance.duration);
|
||||
}});
|
||||
BDFDB.PatchUtils.patch(this, e.returnValue.constructor.prototype, "stop", {after: e2 => {
|
||||
let type = e2.instance && e2.instance.name;
|
||||
if (type && createdAudios[type]) createdAudios[type].stop();
|
||||
}});
|
||||
}
|
||||
}}, {noCache: true});
|
||||
BDFDB.LibraryModules.SoundUtils.createSound("call_calling");
|
||||
}
|
||||
|
||||
this.loadAudios();
|
||||
this.loadChoices();
|
||||
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
|
||||
onStop () {
|
||||
for (let type in createdAudios) if (createdAudios[type]) createdAudios[type].stop();
|
||||
}
|
||||
|
||||
getSettingsPanel (collapseStates = {}) {
|
||||
let successSavedAudio = data => {
|
||||
BDFDB.NotificationUtils.toast(`Sound ${data.sound} was added to category ${data.category}.`, {type: "success"});
|
||||
if (!audios[data.category]) audios[data.category] = {};
|
||||
audios[data.category][data.sound] = data.source;
|
||||
BDFDB.DataUtils.save(audios, this, "audios");
|
||||
BDFDB.PluginUtils.refreshSettingsPanel(this, settingsPanel, collapseStates);
|
||||
|
||||
};
|
||||
|
||||
let settingsPanel;
|
||||
return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(this, {
|
||||
collapseStates: collapseStates,
|
||||
children: _ => {
|
||||
let settingsItems = [];
|
||||
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
|
||||
title: "Settings",
|
||||
collapseStates: collapseStates,
|
||||
children: [
|
||||
...Object.keys(volumes).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Slider",
|
||||
plugin: this,
|
||||
keys: ["volumes", key],
|
||||
basis: "50%",
|
||||
label: this.defaults.volumes[key].description,
|
||||
value: volumes[key]
|
||||
})),
|
||||
...Object.keys(toggles).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Switch",
|
||||
plugin: this,
|
||||
keys: ["toggles", key],
|
||||
label: this.defaults.toggles[key].description,
|
||||
value: toggles[key]
|
||||
}))
|
||||
]
|
||||
}));
|
||||
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
|
||||
title: "Add new Sound",
|
||||
collapseStates: collapseStates,
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
|
||||
className: BDFDB.disCN.margintop4,
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormItem, {
|
||||
title: "Categoryname",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TextInput, {
|
||||
className: "input-newsound input-category",
|
||||
value: "",
|
||||
placeholder: "Categoryname"
|
||||
})
|
||||
})
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormItem, {
|
||||
title: "Soundname",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TextInput, {
|
||||
className: "input-newsound input-sound",
|
||||
value: "",
|
||||
placeholder: "Soundname"
|
||||
})
|
||||
})
|
||||
})
|
||||
]
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
|
||||
className: BDFDB.disCN.margintop4,
|
||||
align: BDFDB.LibraryComponents.Flex.Align.END,
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormItem, {
|
||||
title: "Source",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TextInput, {
|
||||
className: "input-newsound input-source",
|
||||
type: "file",
|
||||
filter: ["audio", "video"],
|
||||
value: "",
|
||||
placeholder: "Source"
|
||||
})
|
||||
})
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Button, {
|
||||
style: {marginBottom: 4},
|
||||
onClick: _ => {
|
||||
for (let input of settingsPanel.props._node.querySelectorAll(".input-newsound " + BDFDB.dotCN.input)) if (!input.value || input.value.length == 0 || input.value.trim().length == 0) return BDFDB.NotificationUtils.toast("Fill out all Fields to add a new Sound", {type: "danger"});
|
||||
let category = settingsPanel.props._node.querySelector(".input-category " + BDFDB.dotCN.input).value.trim();
|
||||
let sound = settingsPanel.props._node.querySelector(".input-sound " + BDFDB.dotCN.input).value.trim();
|
||||
let source = settingsPanel.props._node.querySelector(".input-source " + BDFDB.dotCN.input);
|
||||
let value = source && (source.getAttribute("file") || source.value).trim();
|
||||
if (value.indexOf("http") == 0) BDFDB.LibraryRequires.request(value, (error, response, result) => {
|
||||
if (response) {
|
||||
let type = response.headers["content-type"];
|
||||
if (type && (type.indexOf("octet-stream") > -1 || type.indexOf("audio") > -1 || type.indexOf("video") > -1)) return successSavedAudio({category, sound, source: value});
|
||||
}
|
||||
BDFDB.NotificationUtils.toast("Use a valid direct link to a video or audio source, they usually end on something like .mp3, .mp4 or .wav", {type: "danger"});
|
||||
});
|
||||
else if (value.indexOf("data:") == 0) return successSavedAudio({category, sound, source: value});
|
||||
},
|
||||
children: BDFDB.LanguageUtils.LanguageStrings.SAVE
|
||||
})
|
||||
]
|
||||
})
|
||||
]
|
||||
}));
|
||||
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
|
||||
title: "Sound Configuration",
|
||||
collapseStates: collapseStates,
|
||||
children: Object.keys(types).map(type => type == "message3" && !BDFDB.LibraryStores.NotificationSettingsStore.getNotifyMessagesInSelectedChannel() ? null : [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
|
||||
className: BDFDB.disCN.marginbottom8,
|
||||
align: BDFDB.LibraryComponents.Flex.Align.CENTER,
|
||||
direction: BDFDB.LibraryComponents.Flex.Direction.HORIZONTAL,
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsLabel, {
|
||||
label: types[type].name
|
||||
}),
|
||||
["mute", "streamMute", "invisibleMute"].some(n => types[type][n] !== null) && BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Clickable, {
|
||||
onClick: event => BDFDB.ContextMenuUtils.open(this, event, BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuGroup, {
|
||||
children: [
|
||||
{key: "mute", label: ["Mute in", BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.StatusComponents.Status, {style: {marginLeft: 6}, size: 12, status: BDFDB.LibraryComponents.StatusComponents.Types.DND})]},
|
||||
{key: "invisibleMute", label: ["Mute in", BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.StatusComponents.Status, {style: {marginLeft: 6}, size: 12, status: BDFDB.LibraryComponents.StatusComponents.Types.INVISIBLE})]},
|
||||
{key: "streamMute", label: ["Mute while", BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.StatusComponents.Status, {style: {marginLeft: 6}, size: 12, status: BDFDB.LibraryComponents.StatusComponents.Types.STREAMING})]}
|
||||
].map(n => types[type][n.key] !== null && BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuCheckboxItem, {
|
||||
label: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
|
||||
align: BDFDB.LibraryComponents.Flex.Align.CENTER,
|
||||
children: n.label
|
||||
}),
|
||||
icon: _ => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.MenuItems.MenuHint, {
|
||||
hint: n.hint
|
||||
}),
|
||||
id: BDFDB.ContextMenuUtils.createItemId(this.name, type, n.key),
|
||||
checked: choices[type][n.key],
|
||||
action: state => {
|
||||
choices[type][n.key] = state;
|
||||
this.saveChoice(type, false);
|
||||
}
|
||||
})).filter(n => n)
|
||||
})),
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
|
||||
width: 20,
|
||||
height: 20,
|
||||
name: BDFDB.LibraryComponents.SvgIcon.Names.COG
|
||||
})
|
||||
})
|
||||
].filter(n => n)
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
|
||||
className: BDFDB.disCN.marginbottom8,
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
|
||||
grow: 0,
|
||||
shrink: 0,
|
||||
basis: "31%",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormItem, {
|
||||
title: "Category",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Select, {
|
||||
value: choices[type].category,
|
||||
options: Object.keys(audios).map(name => ({value: name, label: name})),
|
||||
searchable: true,
|
||||
onChange: value => {
|
||||
const categorySounds = audios[value] || {};
|
||||
choices[type].category = value;
|
||||
choices[type].sound = categorySounds[types[type].name] ? types[type].name : Object.keys(categorySounds)[0];
|
||||
this.saveChoice(type, true);
|
||||
BDFDB.PluginUtils.refreshSettingsPanel(this, settingsPanel, collapseStates);
|
||||
}
|
||||
})
|
||||
})
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
|
||||
grow: 0,
|
||||
shrink: 0,
|
||||
basis: "31%",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormItem, {
|
||||
title: "Sound",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Select, {
|
||||
value: choices[type].sound,
|
||||
options: Object.keys(audios[choices[type].category] || {}).map(name => ({value: name, label: name})),
|
||||
searchable: true,
|
||||
onChange: value => {
|
||||
choices[type].sound = value;
|
||||
this.saveChoice(type, true);
|
||||
BDFDB.PluginUtils.refreshSettingsPanel(this, settingsPanel, collapseStates);
|
||||
}
|
||||
})
|
||||
})
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
|
||||
grow: 0,
|
||||
shrink: 0,
|
||||
basis: "31%",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormItem, {
|
||||
title: "Volume",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Slider, {
|
||||
defaultValue: choices[type].volume,
|
||||
digits: 1,
|
||||
onValueRender: value => {
|
||||
return value + "%";
|
||||
},
|
||||
onValueChange: value => {
|
||||
choices[type].volume = value;
|
||||
this.saveChoice(type, true);
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
]
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormDivider, {
|
||||
className: BDFDB.disCN.marginbottom8
|
||||
})
|
||||
]).flat(10).filter(n => n)
|
||||
}));
|
||||
|
||||
let removeableCategories = [{value: removeAllKey, label: BDFDB.LanguageUtils.LanguageStrings.ALL}].concat(Object.keys(audios).filter(category => !(defaultAudios[category] && !Object.keys(audios[category] || {}).filter(sound => defaultAudios[category][sound] === undefined).length)).map(name => ({value: name, label: name})));
|
||||
let removeableSounds = {};
|
||||
for (let category of removeableCategories) removeableSounds[category.value] = [{value: removeAllKey, label: BDFDB.LanguageUtils.LanguageStrings.ALL}].concat(Object.keys(audios[category.value] || {}).filter(sound => !(defaultAudios[category.value] && defaultAudios[category.value][sound] !== undefined)).map(name => ({value: name, label: name})));
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
|
||||
title: "Remove Sounds",
|
||||
collapseStates: collapseStates,
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
|
||||
className: BDFDB.disCN.margintop4,
|
||||
align: BDFDB.LibraryComponents.Flex.Align.END,
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
|
||||
grow: 0,
|
||||
shrink: 0,
|
||||
basis: "35%",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormItem, {
|
||||
title: "Category",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Select, {
|
||||
key: "REMOVE_CATEGORY",
|
||||
value: removeAllKey,
|
||||
options: removeableCategories,
|
||||
searchable: true,
|
||||
onChange: (category, instance) => {
|
||||
let soundSelectIns = BDFDB.ReactUtils.findOwner(BDFDB.ReactUtils.findOwner(instance, {name: ["BDFDB_Modal", "BDFDB_SettingsPanel"], up: true}), {key: "REMOVE_SOUND"});
|
||||
if (soundSelectIns && removeableSounds[category]) {
|
||||
soundSelectIns.props.options = removeableSounds[category];
|
||||
soundSelectIns.props.value = removeAllKey;
|
||||
BDFDB.ReactUtils.forceUpdate(soundSelectIns);
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
|
||||
grow: 0,
|
||||
shrink: 0,
|
||||
basis: "35%",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormItem, {
|
||||
title: "Sound",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Select, {
|
||||
key: "REMOVE_SOUND",
|
||||
value: removeAllKey,
|
||||
options: removeableSounds[removeAllKey],
|
||||
searchable: true
|
||||
})
|
||||
})
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
|
||||
grow: 0,
|
||||
shrink: 1,
|
||||
basis: "25%",
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Button, {
|
||||
style: {marginBottom: 4},
|
||||
color: BDFDB.LibraryComponents.Button.Colors.RED,
|
||||
onClick: (event, instance) => {
|
||||
let wrapperIns = BDFDB.ReactUtils.findOwner(instance, {name: ["BDFDB_Modal", "BDFDB_SettingsPanel"], up: true});
|
||||
let categorySelectIns = BDFDB.ReactUtils.findOwner(wrapperIns, {key: "REMOVE_CATEGORY"});
|
||||
let soundSelectIns = BDFDB.ReactUtils.findOwner(wrapperIns, {key: "REMOVE_SOUND"});
|
||||
if (categorySelectIns && soundSelectIns) {
|
||||
let soundAmount = 0;
|
||||
let catAll = categorySelectIns.props.value == removeAllKey;
|
||||
let soundAll = soundSelectIns.props.value == removeAllKey;
|
||||
if (catAll) soundAmount = BDFDB.ArrayUtils.sum(Object.keys(audios).map(category => Object.keys(audios[category] || {}).filter(sound => !(defaultAudios[category] && defaultAudios[category][sound] !== undefined)).length));
|
||||
else if (soundAll) soundAmount = Object.keys(audios[categorySelectIns.props.value] || {}).filter(sound => !(defaultAudios[categorySelectIns.props.value] && defaultAudios[categorySelectIns.props.value][sound] !== undefined)).length;
|
||||
else if (audios[categorySelectIns.props.value][soundSelectIns.props.value]) soundAmount = 1;
|
||||
|
||||
if (soundAmount) BDFDB.ModalUtils.confirm(this, `Are you sure you want to delete ${soundAmount} added Sound${soundAmount == 1 ? "" : "s"}?`, _ => {
|
||||
if (catAll) BDFDB.DataUtils.remove(this, "audios");
|
||||
else if (soundAll) BDFDB.DataUtils.remove(this, "audios", categorySelectIns.props.value);
|
||||
else {
|
||||
delete audios[categorySelectIns.props.value][soundSelectIns.props.value];
|
||||
if (BDFDB.ObjectUtils.isEmpty(audios[categorySelectIns.props.value])) delete audios[categorySelectIns.props.value];
|
||||
BDFDB.DataUtils.save(audios, this, "audios");
|
||||
}
|
||||
this.loadAudios();
|
||||
this.loadChoices();
|
||||
BDFDB.PluginUtils.refreshSettingsPanel(this, settingsPanel, collapseStates);
|
||||
});
|
||||
else BDFDB.NotificationUtils.toast("No Sounds to delete", {type: "danger"});
|
||||
}
|
||||
},
|
||||
children: BDFDB.LanguageUtils.LanguageStrings.DELETE
|
||||
})
|
||||
})
|
||||
]
|
||||
})
|
||||
}));
|
||||
|
||||
return settingsItems;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onSettingsClosed () {
|
||||
if (this.SettingsUpdated) {
|
||||
delete this.SettingsUpdated;
|
||||
for (let type in createdAudios) if (createdAudios[type]) createdAudios[type].stop();
|
||||
createdAudios = {};
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
}
|
||||
|
||||
forceUpdateAll () {
|
||||
volumes = BDFDB.DataUtils.get(this, "volumes");
|
||||
toggles = BDFDB.DataUtils.get(this, "toggles");
|
||||
|
||||
BDFDB.PatchUtils.forceAllUpdates(this);
|
||||
BDFDB.DiscordUtils.rerenderAll();
|
||||
}
|
||||
|
||||
loadAudios () {
|
||||
audios = Object.assign({}, BDFDB.DataUtils.load(this, "audios"), defaultAudios);
|
||||
BDFDB.DataUtils.save(BDFDB.ObjectUtils.exclude(audios, Object.keys(defaultAudios)), this, "audios");
|
||||
}
|
||||
|
||||
loadChoices () {
|
||||
let loadedChoices = BDFDB.DataUtils.load(this, "choices");
|
||||
for (let type in types) {
|
||||
let choice = loadedChoices[type] || {}, soundFound = false;
|
||||
for (let category in audios) if (choice.category == category) for (let sound in audios[category]) if (choice.sound == sound) {
|
||||
soundFound = true;
|
||||
break;
|
||||
}
|
||||
if (!soundFound) choice = {
|
||||
category: "---",
|
||||
sound: "---",
|
||||
volume: 100,
|
||||
mute: types[type].mute,
|
||||
streamMute: types[type].streamMute,
|
||||
invisibleMute: types[type].invisibleMute
|
||||
};
|
||||
choices[type] = choice;
|
||||
this.saveChoice(type, false);
|
||||
}
|
||||
}
|
||||
|
||||
saveChoice (type, play) {
|
||||
if (!choices[type]) return;
|
||||
BDFDB.DataUtils.save(choices[type], this, "choices", type);
|
||||
if (play) {
|
||||
this.SettingsUpdated = true;
|
||||
this.playAudio(type);
|
||||
}
|
||||
}
|
||||
|
||||
playAudio (type, functionCall = "play", duration = 0) {
|
||||
type = soundPacks.some(soundPack => type.startsWith(soundPack + "_")) ? type.split("_").splice(1).join("_") : type;
|
||||
if (this.dontPlayAudio(type) || BDFDB.LibraryStores.StreamerModeStore.disableSounds) return;
|
||||
if (createdAudios[type]) createdAudios[type].stop();
|
||||
createdAudios[type] = new WebAudioSound(type);
|
||||
return createdAudios[type][typeof createdAudios[type][functionCall] == "function" ? functionCall : "play"](duration);
|
||||
}
|
||||
|
||||
isSuppressMentionsEnabled (guildId, channelId) {
|
||||
let channelSettings = BDFDB.LibraryStores.UserGuildSettingsStore.getChannelMessageNotifications(guildId, channelId);
|
||||
return channelSettings && (channelSettings == BDFDB.DiscordConstants.UserNotificationSettings.NO_MESSAGES || channelSettings == BDFDB.DiscordConstants.UserNotificationSettings.NULL && BDFDB.LibraryStores.UserGuildSettingsStore.getMessageNotifications(guildId) == BDFDB.DiscordConstants.UserNotificationSettings.NO_MESSAGES);
|
||||
}
|
||||
|
||||
dontPlayAudio (type) {
|
||||
let status = BDFDB.UserUtils.getStatus();
|
||||
return choices[type] && (choices[type].mute && status == "dnd" || choices[type].streamMute && status == "streaming" || choices[type].invisibleMute && (status == "offline" || status == "invisible"));
|
||||
}
|
||||
|
||||
fireEvent (type) {
|
||||
firedEvents[type] = true;
|
||||
BDFDB.TimeUtils.timeout(_ => delete firedEvents[type], 3000);
|
||||
}
|
||||
|
||||
isSoundUsedAnywhere (type) {
|
||||
return type && type.indexOf("poggermode_") != 0 && type != "human_man" && type != "robot_man" && type != "discodo" && type != "overlayunlock" && type != "call_ringing_beat" && !(type != "message1" && type != "message3" && /\d$/.test(type));
|
||||
}
|
||||
};
|
||||
})(window.BDFDB_Global.PluginUtils.buildPlugin(changeLog));
|
||||
})();
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "0.2.11",
|
||||
"hasShownChangelog": true
|
||||
},
|
||||
"settings": {
|
||||
"contextMenus": true,
|
||||
"popouts": true,
|
||||
"displayMode": "cozy"
|
||||
},
|
||||
"version": "0.3.2"
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"all": {
|
||||
"cached": "2 7 8 9 11 14 15 17 28 29 30 59 60 61 62 63 64 65 66 67 70 71 73 74 75 76 77 80 81 82 83 85 86 87 88 89 91 92 93 94 95 96 97 98 99 100 101 102 104 105 106 108 109 110 111 120 126 127 131 132 138 139 146 157 158 159 160 162 171 176 179 181 182 183 184 186 188 189 190 193 195 196 197 228 237 240 245 262 274 278 287 291 292 293 295 306 312 314 317 318 323 331 344 350 352 353 354 356 366 368 377 379 381 382 383 390 395 401 420 421 429 442 476 479 489 518 520 523 525 535 539 547 554 577 579 589 592 593 598 599 606 608 611 614 620 638 644 645 670 671 679 686 692 693 694 699 708 760 762 772 798 802 805 806 807 819 827 843 850 856 859 867 878 881 882 883 930 936 938 953 954 970 971 979 989 996 1000 1005 1010 1016 1023 1040 1041 1044 1048 1049 1058 1063 1066 1067 1068 1069 1070 1074 1075 1077 1078 1079 1080 1081 1087 1090 1092 1097 1115 1124 1126 1130 1132 1141 1157 1163 1166 1172 1175 1185 1188 1190 1191 1204 1205 1206 1210",
|
||||
"filters": {
|
||||
"updated": true,
|
||||
"outdated": true,
|
||||
"downloadable": true
|
||||
},
|
||||
"general": {
|
||||
"notifyOutdated": true,
|
||||
"notifyNewEntries": true,
|
||||
"startDownloaded": false,
|
||||
"startUpdated": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "1.2.1",
|
||||
"hasShownChangelog": true
|
||||
},
|
||||
"settings": {
|
||||
"lastVersion": "1.4.0"
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"all": {
|
||||
"batch": {
|
||||
"dms": false,
|
||||
"guilds": true,
|
||||
"muted": true
|
||||
},
|
||||
"blacklist": [
|
||||
"775772308261830737",
|
||||
"230708419995107330",
|
||||
"594829566330273792",
|
||||
"230708419995107330",
|
||||
"594829566330273792",
|
||||
"710203122106105927",
|
||||
"775772308261830737",
|
||||
"413603118832680960",
|
||||
"707267476391723008",
|
||||
"230708419995107330",
|
||||
"594829566330273792",
|
||||
"710203122106105927",
|
||||
"775772308261830737",
|
||||
"413603118832680960",
|
||||
"707267476391723008",
|
||||
"340262122782982147",
|
||||
"738872654928281620",
|
||||
"230708419995107330",
|
||||
"594829566330273792",
|
||||
"710203122106105927",
|
||||
"775772308261830737",
|
||||
"413603118832680960",
|
||||
"340262122782982147",
|
||||
"707267476391723008",
|
||||
"738872654928281620",
|
||||
"703597941809741834",
|
||||
"821835978334535740"
|
||||
],
|
||||
"general": {
|
||||
"addClearButton": true,
|
||||
"confirmClear": false
|
||||
},
|
||||
"settings": {
|
||||
"addClearButton": true,
|
||||
"confirmClear": false,
|
||||
"includeGuilds": true,
|
||||
"includeMuted": false,
|
||||
"includeDMs": false
|
||||
}
|
||||
}
|
||||
}
|
||||
+700
@@ -0,0 +1,700 @@
|
||||
/**
|
||||
* @name ReadAllNotificationsButton
|
||||
* @author DevilBro
|
||||
* @authorId 278543574059057154
|
||||
* @version 1.8.5
|
||||
* @description Adds a Clear Button to the Server List and the Mentions Popout
|
||||
* @invite Jx3TjNS
|
||||
* @donate https://www.paypal.me/MircoWittrien
|
||||
* @patreon https://www.patreon.com/MircoWittrien
|
||||
* @website https://mwittrien.github.io/
|
||||
* @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ReadAllNotificationsButton/
|
||||
* @updateUrl https://mwittrien.github.io/BetterDiscordAddons/Plugins/ReadAllNotificationsButton/ReadAllNotificationsButton.plugin.js
|
||||
*/
|
||||
|
||||
module.exports = (_ => {
|
||||
const changeLog = {
|
||||
|
||||
};
|
||||
|
||||
return !window.BDFDB_Global || (!window.BDFDB_Global.loaded && !window.BDFDB_Global.started) ? class {
|
||||
constructor (meta) {for (let key in meta) this[key] = meta[key];}
|
||||
getName () {return this.name;}
|
||||
getAuthor () {return this.author;}
|
||||
getVersion () {return this.version;}
|
||||
getDescription () {return `The Library Plugin needed for ${this.name} is missing. Open the Plugin Settings to download it. \n\n${this.description}`;}
|
||||
|
||||
downloadLibrary () {
|
||||
BdApi.Net.fetch("https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js").then(r => {
|
||||
if (!r || r.status != 200) throw new Error();
|
||||
else return r.text();
|
||||
}).then(b => {
|
||||
if (!b) throw new Error();
|
||||
else return require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0BDFDB.plugin.js"), b, _ => BdApi.UI.showToast("Finished downloading BDFDB Library", {type: "success"}));
|
||||
}).catch(error => {
|
||||
BdApi.UI.alert("Error", "Could not download BDFDB Library Plugin. Try again later or download it manually from GitHub: https://mwittrien.github.io/downloader/?library");
|
||||
});
|
||||
}
|
||||
|
||||
load () {
|
||||
if (!window.BDFDB_Global || !Array.isArray(window.BDFDB_Global.pluginQueue)) window.BDFDB_Global = Object.assign({}, window.BDFDB_Global, {pluginQueue: []});
|
||||
if (!window.BDFDB_Global.downloadModal) {
|
||||
window.BDFDB_Global.downloadModal = true;
|
||||
BdApi.UI.showConfirmationModal("Library Missing", `The Library Plugin needed for ${this.name} is missing. Please click "Download Now" to install it.`, {
|
||||
confirmText: "Download Now",
|
||||
cancelText: "Cancel",
|
||||
onCancel: _ => {delete window.BDFDB_Global.downloadModal;},
|
||||
onConfirm: _ => {
|
||||
delete window.BDFDB_Global.downloadModal;
|
||||
this.downloadLibrary();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!window.BDFDB_Global.pluginQueue.includes(this.name)) window.BDFDB_Global.pluginQueue.push(this.name);
|
||||
}
|
||||
start () {this.load();}
|
||||
stop () {}
|
||||
getSettingsPanel () {
|
||||
let template = document.createElement("template");
|
||||
template.innerHTML = `<div style="color: var(--text-strong); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${this.name} is missing.\nPlease click <a style="font-weight: 500;">Download Now</a> to install it.</div>`;
|
||||
template.content.firstElementChild.querySelector("a").addEventListener("click", this.downloadLibrary);
|
||||
return template.content.firstElementChild;
|
||||
}
|
||||
} : (([Plugin, BDFDB]) => {
|
||||
var _this;
|
||||
var blacklist, clearing;
|
||||
|
||||
const ReadAllButtonComponent = class ReadAllButton extends BdApi.React.Component {
|
||||
clearClick() {
|
||||
if (_this.settings.batch.guilds) this.clearGuilds(_this.settings.batch.muted ? this.getGuilds() : this.getUnread());
|
||||
if (_this.settings.batch.dms) BDFDB.DMUtils.markAsRead(this.getPingedDMs());
|
||||
}
|
||||
clearGuilds(guildIds) {
|
||||
BDFDB.GuildUtils.markAsRead(guildIds.filter(id => id && !blacklist.includes(id)));
|
||||
}
|
||||
getGuilds() {
|
||||
return BDFDB.LibraryStores.SortedGuildStore.getFlattenedGuildIds().map(BDFDB.LibraryStores.GuildStore.getGuild).map(g => g.id).filter(n => n);
|
||||
}
|
||||
getUnread() {
|
||||
return this.getGuilds().filter(id => BDFDB.LibraryStores.GuildReadStateStore.hasUnread(id) || BDFDB.LibraryStores.GuildReadStateStore.getMentionCount(id) > 0);
|
||||
}
|
||||
getPinged() {
|
||||
return this.getGuilds().filter(id => BDFDB.LibraryStores.GuildReadStateStore.getMentionCount(id) > 0);
|
||||
}
|
||||
getMuted() {
|
||||
return this.getGuilds().filter(id => BDFDB.LibraryStores.UserGuildSettingsStore.isGuildOrCategoryOrChannelMuted(id));
|
||||
}
|
||||
getPingedDMs() {
|
||||
return BDFDB.LibraryStores.ChannelStore.getSortedPrivateChannels().map(c => c.id).filter(id => id && BDFDB.LibraryStores.ReadStateStore.getMentionCount(id) > 0);
|
||||
}
|
||||
render() {
|
||||
return BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCNS.guildouter + BDFDB.disCN._readallnotificationsbuttonframe,
|
||||
children: BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCNS.guildiconwrapper + BDFDB.disCN._readallnotificationsbuttoninner,
|
||||
children: BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCNS.guildiconchildwrapper + BDFDB.disCNS.guildiconchildwrappernohoverbg + BDFDB.disCN._readallnotificationsbuttonbutton,
|
||||
children: "read all",
|
||||
onClick: _ => {
|
||||
if (!_this.settings.general.confirmClear) this.clearClick();
|
||||
else BDFDB.ModalUtils.confirm(_this, _this.labels.modal_confirmnotifications, _ => this.clearClick());
|
||||
},
|
||||
onContextMenu: event => BDFDB.ContextMenuUtils.open(_this, event, BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuGroup, {
|
||||
children: [
|
||||
BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
|
||||
label: _this.labels.context_unreadguilds,
|
||||
id: BDFDB.ContextMenuUtils.createItemId(_this.name, "mark-unread-read"),
|
||||
action: _ => this.clearGuilds(this.getUnread())
|
||||
}),
|
||||
BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
|
||||
label: _this.labels.context_pingedguilds,
|
||||
id: BDFDB.ContextMenuUtils.createItemId(_this.name, "mark-pinged-read"),
|
||||
action: _ => this.clearGuilds(this.getPinged())
|
||||
}),
|
||||
BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
|
||||
label: _this.labels.context_mutedguilds,
|
||||
id: BDFDB.ContextMenuUtils.createItemId(_this.name, "mark-muted-read"),
|
||||
action: _ => this.clearGuilds(this.getMuted())
|
||||
}),
|
||||
BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
|
||||
label: _this.labels.context_guilds,
|
||||
id: BDFDB.ContextMenuUtils.createItemId(_this.name, "mark-all-read"),
|
||||
action: _ => this.clearGuilds(this.getGuilds())
|
||||
}),
|
||||
BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
|
||||
label: _this.labels.context_dms,
|
||||
id: BDFDB.ContextMenuUtils.createItemId(_this.name, "mark-dms-read"),
|
||||
action: _ => BDFDB.DMUtils.markAsRead(this.getPingedDMs())
|
||||
})
|
||||
]
|
||||
}))
|
||||
})
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return class ReadAllNotificationsButton extends Plugin {
|
||||
onLoad () {
|
||||
_this = this;
|
||||
|
||||
this.defaults = {
|
||||
general: {
|
||||
addClearButton: {value: true, description: "Adds a 'Clear Mentions' button to the recent mentions popout"},
|
||||
confirmClear: {value: false, description: "Asks for your confirmation before clearing reads"}
|
||||
},
|
||||
batch: {
|
||||
guilds: {value: true, description: "unread Servers"},
|
||||
muted: {value: false, description: "muted unread Servers"},
|
||||
dms: {value: false, description: "unread DMs"}
|
||||
}
|
||||
};
|
||||
|
||||
this.modulePatches = {
|
||||
after: [
|
||||
"UnreadDMs",
|
||||
"InboxHeader"
|
||||
]
|
||||
};
|
||||
|
||||
this.css = `
|
||||
${BDFDB.dotCN.messagespopouttabbar} {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
${BDFDB.dotCN.messagespopoutcontrols} {
|
||||
display: flex;
|
||||
}
|
||||
${BDFDB.dotCN.messagespopoutcontrols} > * {
|
||||
margin-left: 10px;
|
||||
}
|
||||
${BDFDB.dotCN._readallnotificationsbuttonframe} {
|
||||
--guildbar-avatar-size: 48px;
|
||||
}
|
||||
${BDFDB.dotCN._readallnotificationsbuttonframe}:active {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
#app-mount ${BDFDB.dotCN._readallnotificationsbuttonframe},
|
||||
#app-mount ${BDFDB.dotCN._readallnotificationsbuttoninner},
|
||||
#app-mount ${BDFDB.dotCN._readallnotificationsbuttonbutton} {
|
||||
height: 24px;
|
||||
}
|
||||
${BDFDB.dotCN._readallnotificationsbuttonbutton} {
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
line-height: 1.3;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
onStart () {
|
||||
let loadedBlacklist = BDFDB.DataUtils.load(this, "blacklist");
|
||||
this.saveBlacklist(!BDFDB.ArrayUtils.is(loadedBlacklist) ? [] : loadedBlacklist);
|
||||
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
|
||||
onStop () {
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
|
||||
getSettingsPanel (collapseStates = {}) {
|
||||
let settingsPanel, settingsItems = [];
|
||||
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
|
||||
title: "Settings",
|
||||
collapseStates: collapseStates,
|
||||
children: Object.keys(this.defaults.general).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Switch",
|
||||
plugin: this,
|
||||
keys: ["general", key],
|
||||
label: this.defaults.general[key].description,
|
||||
value: this.settings.general[key]
|
||||
})).concat(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsPanelList, {
|
||||
title: "When left clicking the 'read all' Button mark following Elements as read:",
|
||||
first: false,
|
||||
last: true,
|
||||
children: Object.keys(this.defaults.batch).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Switch",
|
||||
plugin: this,
|
||||
keys: ["batch", key],
|
||||
label: this.defaults.batch[key].description,
|
||||
value: this.settings.batch[key]
|
||||
}))
|
||||
}))
|
||||
}));
|
||||
|
||||
let listInstance = null, batchSetGuilds = value => {
|
||||
if (!value) {
|
||||
for (let id of BDFDB.LibraryStores.SortedGuildStore.getFlattenedGuildIds()) blacklist.push(id);
|
||||
blacklist = BDFDB.ArrayUtils.removeCopies(blacklist);
|
||||
}
|
||||
else blacklist = [];
|
||||
this.saveBlacklist(blacklist);
|
||||
if (listInstance) {
|
||||
listInstance.props.disabled = blacklist;
|
||||
BDFDB.ReactUtils.forceUpdate(listInstance);
|
||||
}
|
||||
};
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
|
||||
title: "Server Black List",
|
||||
collapseStates: collapseStates,
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsGuildList, {
|
||||
className: BDFDB.disCN.marginbottom20,
|
||||
disabled: BDFDB.DataUtils.load(this, "blacklist"),
|
||||
onClick: disabledGuilds => this.saveBlacklist(disabledGuilds),
|
||||
ref: instance => {listInstance = instance;}
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, {
|
||||
type: "Button",
|
||||
color: BDFDB.LibraryComponents.Button.Colors.GREEN,
|
||||
label: "Enable for all Servers",
|
||||
onClick: _ => batchSetGuilds(true),
|
||||
children: BDFDB.LanguageUtils.LanguageStrings.ENABLE
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, {
|
||||
type: "Button",
|
||||
color: BDFDB.LibraryComponents.Button.Colors.PRIMARY,
|
||||
label: "Disable for all Servers",
|
||||
onClick: _ => batchSetGuilds(false),
|
||||
children: BDFDB.LanguageUtils.LanguageStrings.DISABLE
|
||||
})
|
||||
]
|
||||
}));
|
||||
|
||||
return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(this, settingsItems);
|
||||
}
|
||||
|
||||
onSettingsClosed () {
|
||||
if (this.SettingsUpdated) {
|
||||
delete this.SettingsUpdated;
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
}
|
||||
|
||||
forceUpdateAll () {
|
||||
BDFDB.DiscordUtils.rerenderAll();
|
||||
}
|
||||
|
||||
processUnreadDMs (e) {
|
||||
e.returnvalue = [e.returnvalue].flat(10);
|
||||
e.returnvalue.push(BDFDB.ReactUtils.createElement(ReadAllButtonComponent, {}));
|
||||
}
|
||||
|
||||
processInboxHeader (e) {
|
||||
if (!this.settings.general.addClearButton || e.instance.props.tab != BDFDB.DiscordConstants.InboxTabs.MENTIONS) return;
|
||||
let mentionedMessages = BDFDB.LibraryStores.RecentMentionsStore.getMentions();
|
||||
if (!mentionedMessages || !mentionedMessages.length) return;
|
||||
let controls = BDFDB.ReactUtils.findChild(e.returnvalue, {props: [["className", BDFDB.disCN.messagespopoutcontrols]]});
|
||||
if (controls) controls.props.children = [
|
||||
controls.props.children,
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, {
|
||||
text: `${BDFDB.LanguageUtils.LanguageStrings.CLOSE} (${BDFDB.LanguageUtils.LanguageStrings.ALL})`,
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Clickable, {
|
||||
className: BDFDB.disCNS.messagespopoutbutton + BDFDB.disCNS.messagespopoutbuttonsm + BDFDB.disCN.messagespopoutbuttonsecondary,
|
||||
children: BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN.messagespopoutbuttonchildrenwrapper,
|
||||
children: BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN.messagespopoutbuttonchildren,
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
|
||||
nativeClass: true,
|
||||
name: BDFDB.LibraryComponents.SvgIcon.Names.CLOSE,
|
||||
width: 16,
|
||||
height: 16
|
||||
})
|
||||
})
|
||||
}),
|
||||
onClick: _ => {
|
||||
let clear = _ => {
|
||||
if (clearing) return BDFDB.NotificationUtils.toast(`${this.labels.toast_alreadyclearing} - ${BDFDB.LanguageUtils.LibraryStrings.please_wait}`, {type: "danger"});
|
||||
let messages = [].concat(mentionedMessages).filter(n => n);
|
||||
if (messages.length) {
|
||||
clearing = true;
|
||||
let toast = BDFDB.NotificationUtils.toast(`${this.labels.toast_clearing} - ${BDFDB.LanguageUtils.LibraryStrings.please_wait}`, {timeout: 0, ellipsis: true});
|
||||
for (let i = 0; i < messages.length; i++) BDFDB.TimeUtils.timeout(_ => {
|
||||
BDFDB.LibraryModules.HTTPUtils.del({
|
||||
url: BDFDB.DiscordConstants.Endpoints.MENTIONS_MESSAGE_ID(messages[i].id),
|
||||
retries: 2,
|
||||
oldFormErrors: true
|
||||
});
|
||||
if (i == messages.length - 1) {
|
||||
clearing = false;
|
||||
toast.close();
|
||||
BDFDB.NotificationUtils.toast(this.labels.toastcleared, {type: "success"});
|
||||
}
|
||||
}, i * 1000);
|
||||
}
|
||||
};
|
||||
if (this.settings.general.confirmClear) BDFDB.ModalUtils.confirm(this, this.labels.modal_confirmmentions, clear);
|
||||
else clear();
|
||||
}
|
||||
})
|
||||
})
|
||||
].flat(10);
|
||||
}
|
||||
|
||||
saveBlacklist (savedBlacklist) {
|
||||
blacklist = savedBlacklist;
|
||||
BDFDB.DataUtils.save(savedBlacklist, this, "blacklist");
|
||||
}
|
||||
|
||||
setLabelsByLanguage () {
|
||||
switch (BDFDB.LanguageUtils.getLanguage().id) {
|
||||
case "bg": // Bulgarian
|
||||
return {
|
||||
context_dms: "Директно съобщение",
|
||||
context_guilds: "Всички сървъри",
|
||||
context_mutedguilds: "Приглушени сървъри",
|
||||
context_pingedguilds: "Pinged сървъри",
|
||||
context_unreadguilds: "Непрочетени сървъри",
|
||||
modal_confirmmentions: "Наистина ли искате да изтриете всички непрочетени споменавания?",
|
||||
modal_confirmnotifications: "Наистина ли искате да изтриете всички непрочетени известия?",
|
||||
toast_alreadyclearing: "Изтрива някои споменавания вече",
|
||||
toast_cleared: "Всички последни споменавания бяха изтрити",
|
||||
toast_clearing: "Изчиства всички скорошни споменавания"
|
||||
};
|
||||
case "da": // Danish
|
||||
return {
|
||||
context_dms: "Direkte beskeder",
|
||||
context_guilds: "Alle servere",
|
||||
context_mutedguilds: "Dæmpede servere",
|
||||
context_pingedguilds: "Pingede servere",
|
||||
context_unreadguilds: "Ulæste servere",
|
||||
modal_confirmmentions: "Er du sikker på, at du vil slette alle ulæste omtaler?",
|
||||
modal_confirmnotifications: "Er du sikker på, at du vil slette alle ulæste meddelelser?",
|
||||
toast_alreadyclearing: "Sletter allerede nogle omtaler",
|
||||
toast_cleared: "Alle nylige omtaler er blevet slettet",
|
||||
toast_clearing: "Rydder alle nylige omtaler"
|
||||
};
|
||||
case "de": // German
|
||||
return {
|
||||
context_dms: "Direktnachrichten",
|
||||
context_guilds: "Alle Server",
|
||||
context_mutedguilds: "Stummgeschaltete Server",
|
||||
context_pingedguilds: "Gepingte Server",
|
||||
context_unreadguilds: "Ungelesene Server",
|
||||
modal_confirmmentions: "Möchten Sie wirklich alle ungelesenen Erwähnungen löschen?",
|
||||
modal_confirmnotifications: "Möchten Sie wirklich alle ungelesenen Benachrichtigungen löschen?",
|
||||
toast_alreadyclearing: "Löscht bereits einige Erwähnungen",
|
||||
toast_cleared: "Alle kürzlich Erwähnungen wurden gelöscht",
|
||||
toast_clearing: "Löscht alle letzten Erwähnungen"
|
||||
};
|
||||
case "el": // Greek
|
||||
return {
|
||||
context_dms: "Αμεσα μηνύματα",
|
||||
context_guilds: "Όλοι οι διακομιστές",
|
||||
context_mutedguilds: "Σίγαση διακομιστών",
|
||||
context_pingedguilds: "Διακομιστές Ping",
|
||||
context_unreadguilds: "Μη αναγνωσμένοι διακομιστές",
|
||||
modal_confirmmentions: "Είστε βέβαιοι ότι θέλετε να διαγράψετε όλες τις μη αναγνωσμένες αναφορές;",
|
||||
modal_confirmnotifications: "Είστε βέβαιοι ότι θέλετε να διαγράψετε όλες τις μη αναγνωσμένες ειδοποιήσεις;",
|
||||
toast_alreadyclearing: "Διαγράφει ήδη κάποιες αναφορές",
|
||||
toast_cleared: "Όλες οι πρόσφατες αναφορές έχουν διαγραφεί",
|
||||
toast_clearing: "Διαγράφει όλες τις πρόσφατες αναφορές"
|
||||
};
|
||||
case "es": // Spanish
|
||||
return {
|
||||
context_dms: "Mensajes directos",
|
||||
context_guilds: "Todos los servidores",
|
||||
context_mutedguilds: "Servidores silenciados",
|
||||
context_pingedguilds: "Servidores con ping",
|
||||
context_unreadguilds: "Servidores no leídos",
|
||||
modal_confirmmentions: "¿Estás seguro de que deseas eliminar todas las menciones no leídas?",
|
||||
modal_confirmnotifications: "¿Está seguro de que desea eliminar todas las notificaciones no leídas?",
|
||||
toast_alreadyclearing: "Elimina algunas menciones ya",
|
||||
toast_cleared: "Se han eliminado todas las menciones recientes",
|
||||
toast_clearing: "Borra todas las menciones recientes"
|
||||
};
|
||||
case "fi": // Finnish
|
||||
return {
|
||||
context_dms: "Suorat viestit",
|
||||
context_guilds: "Kaikki palvelimet",
|
||||
context_mutedguilds: "Mykistetyt palvelimet",
|
||||
context_pingedguilds: "Pinged-palvelimet",
|
||||
context_unreadguilds: "Lukemattomat palvelimet",
|
||||
modal_confirmmentions: "Haluatko varmasti poistaa kaikki lukemattomat maininnat?",
|
||||
modal_confirmnotifications: "Haluatko varmasti poistaa kaikki lukemattomat ilmoitukset?",
|
||||
toast_alreadyclearing: "Poistaa jo joitain mainintoja",
|
||||
toast_cleared: "Kaikki viimeisimmät maininnat on poistettu",
|
||||
toast_clearing: "Tyhjentää kaikki viimeisimmät maininnat"
|
||||
};
|
||||
case "fr": // French
|
||||
return {
|
||||
context_dms: "Messages directs",
|
||||
context_guilds: "Tous les serveurs",
|
||||
context_mutedguilds: "Serveurs muets",
|
||||
context_pingedguilds: "Serveurs ping",
|
||||
context_unreadguilds: "Serveurs non lus",
|
||||
modal_confirmmentions: "Voulez-vous vraiment supprimer toutes les mentions non lues?",
|
||||
modal_confirmnotifications: "Voulez-vous vraiment supprimer toutes les notifications non lues?",
|
||||
toast_alreadyclearing: "Supprime déjà certaines mentions",
|
||||
toast_cleared: "Toutes les mentions récentes ont été supprimées",
|
||||
toast_clearing: "Efface toutes les mentions récentes"
|
||||
};
|
||||
case "hr": // Croatian
|
||||
return {
|
||||
context_dms: "Direktna poruka",
|
||||
context_guilds: "Svi poslužitelji",
|
||||
context_mutedguilds: "Prigušeni poslužitelji",
|
||||
context_pingedguilds: "Pingirani poslužitelji",
|
||||
context_unreadguilds: "Nepročitani poslužitelji",
|
||||
modal_confirmmentions: "Jeste li sigurni da želite izbrisati sva nepročitana spominjanja?",
|
||||
modal_confirmnotifications: "Jeste li sigurni da želite izbrisati sve nepročitane obavijesti?",
|
||||
toast_alreadyclearing: "Briše već spomenute",
|
||||
toast_cleared: "Sva nedavna spominjanja su izbrisana",
|
||||
toast_clearing: "Briše sva nedavna spominjanja"
|
||||
};
|
||||
case "hu": // Hungarian
|
||||
return {
|
||||
context_dms: "Közvetlen üzenet",
|
||||
context_guilds: "Minden szerver",
|
||||
context_mutedguilds: "Némított szerverek",
|
||||
context_pingedguilds: "Pingelt szerverek",
|
||||
context_unreadguilds: "Olvasatlan szerverek",
|
||||
modal_confirmmentions: "Biztosan törli az összes olvasatlan említést?",
|
||||
modal_confirmnotifications: "Biztosan törli az összes olvasatlan értesítést?",
|
||||
toast_alreadyclearing: "Néhány említést már töröl",
|
||||
toast_cleared: "Az összes közelmúltbeli említést törölték",
|
||||
toast_clearing: "Törli az összes közelmúltbeli említést"
|
||||
};
|
||||
case "it": // Italian
|
||||
return {
|
||||
context_dms: "Messaggi diretti",
|
||||
context_guilds: "Tutti i server",
|
||||
context_mutedguilds: "Server disattivati",
|
||||
context_pingedguilds: "Server sottoposti a ping",
|
||||
context_unreadguilds: "Server non letti",
|
||||
modal_confirmmentions: "Sei sicuro di voler eliminare tutte le menzioni non lette?",
|
||||
modal_confirmnotifications: "Sei sicuro di voler eliminare tutte le notifiche non lette?",
|
||||
toast_alreadyclearing: "Elimina già alcune menzioni",
|
||||
toast_cleared: "Tutte le menzioni recenti sono state eliminate",
|
||||
toast_clearing: "Cancella tutte le menzioni recenti"
|
||||
};
|
||||
case "ja": // Japanese
|
||||
return {
|
||||
context_dms: "ダイレクトメッセージ",
|
||||
context_guilds: "すべてのサーバー",
|
||||
context_mutedguilds: "ミュートされたサーバー",
|
||||
context_pingedguilds: "pingされたサーバー",
|
||||
context_unreadguilds: "未読サーバー",
|
||||
modal_confirmmentions: "未読のメンションをすべて削除してもよろしいですか?",
|
||||
modal_confirmnotifications: "未読の通知をすべて削除してもよろしいですか?",
|
||||
toast_alreadyclearing: "すでにいくつかの言及を削除します",
|
||||
toast_cleared: "最近の言及はすべて削除されました",
|
||||
toast_clearing: "最近の言及をすべてクリアします"
|
||||
};
|
||||
case "ko": // Korean
|
||||
return {
|
||||
context_dms: "쪽지",
|
||||
context_guilds: "모든 서버",
|
||||
context_mutedguilds: "음소거 된 서버",
|
||||
context_pingedguilds: "핑된 서버",
|
||||
context_unreadguilds: "읽지 않은 서버",
|
||||
modal_confirmmentions: "읽지 않은 모든 멘션을 삭제 하시겠습니까?",
|
||||
modal_confirmnotifications: "읽지 않은 모든 알림을 삭제 하시겠습니까?",
|
||||
toast_alreadyclearing: "이미 일부 멘션을 삭제합니다.",
|
||||
toast_cleared: "모든 최근 멘션이 삭제되었습니다.",
|
||||
toast_clearing: "최근 멘션을 모두 지 웁니다."
|
||||
};
|
||||
case "lt": // Lithuanian
|
||||
return {
|
||||
context_dms: "Tiesioginiai pranešimai",
|
||||
context_guilds: "Visi serveriai",
|
||||
context_mutedguilds: "Nutildyti serveriai",
|
||||
context_pingedguilds: "„Pinged“ serveriai",
|
||||
context_unreadguilds: "Neskaityti serveriai",
|
||||
modal_confirmmentions: "Ar tikrai norite ištrinti visus neperskaitytus paminėjimus?",
|
||||
modal_confirmnotifications: "Ar tikrai norite ištrinti visus neperskaitytus pranešimus?",
|
||||
toast_alreadyclearing: "Kai kurie paminėjimai jau ištrinami",
|
||||
toast_cleared: "Visi naujausi paminėjimai buvo ištrinti",
|
||||
toast_clearing: "Išvalo visus naujausius paminėjimus"
|
||||
};
|
||||
case "nl": // Dutch
|
||||
return {
|
||||
context_dms: "Directe berichten",
|
||||
context_guilds: "Alle servers",
|
||||
context_mutedguilds: "Gedempte servers",
|
||||
context_pingedguilds: "Gepingde servers",
|
||||
context_unreadguilds: "Ongelezen servers",
|
||||
modal_confirmmentions: "Weet u zeker dat u alle ongelezen vermeldingen wilt verwijderen?",
|
||||
modal_confirmnotifications: "Weet u zeker dat u alle ongelezen meldingen wilt verwijderen?",
|
||||
toast_alreadyclearing: "Verwijdert al enkele vermeldingen",
|
||||
toast_cleared: "Alle recente vermeldingen zijn verwijderd",
|
||||
toast_clearing: "Wist alle recente vermeldingen"
|
||||
};
|
||||
case "no": // Norwegian
|
||||
return {
|
||||
context_dms: "Direktemeldinger",
|
||||
context_guilds: "Alle servere",
|
||||
context_mutedguilds: "Dempede servere",
|
||||
context_pingedguilds: "Pingede servere",
|
||||
context_unreadguilds: "Uleste servere",
|
||||
modal_confirmmentions: "Er du sikker på at du vil slette alle uleste omtaler?",
|
||||
modal_confirmnotifications: "Er du sikker på at du vil slette alle uleste varsler?",
|
||||
toast_alreadyclearing: "Sletter allerede noen omtaler",
|
||||
toast_cleared: "Alle nylige omtaler er slettet",
|
||||
toast_clearing: "Fjerner alle nylige omtaler"
|
||||
};
|
||||
case "pl": // Polish
|
||||
return {
|
||||
context_dms: "Bezpośrednie wiadomości",
|
||||
context_guilds: "Wszystkie serwery",
|
||||
context_mutedguilds: "Wyciszone serwery",
|
||||
context_pingedguilds: "Serwery pingowane",
|
||||
context_unreadguilds: "Nieprzeczytane serwery",
|
||||
modal_confirmmentions: "Czy na pewno chcesz usunąć wszystkie nieprzeczytane wzmianki?",
|
||||
modal_confirmnotifications: "Czy na pewno chcesz usunąć wszystkie nieprzeczytane powiadomienia?",
|
||||
toast_alreadyclearing: "Usuwa już niektóre wzmianki",
|
||||
toast_cleared: "Wszystkie ostatnie wzmianki zostały usunięte",
|
||||
toast_clearing: "Usuwa wszystkie ostatnie wzmianki"
|
||||
};
|
||||
case "pt-BR": // Portuguese (Brazil)
|
||||
return {
|
||||
context_dms: "Mensagens diretas",
|
||||
context_guilds: "Todos os servidores",
|
||||
context_mutedguilds: "Servidores Silenciados",
|
||||
context_pingedguilds: "Servidores com ping",
|
||||
context_unreadguilds: "Servidores não lidos",
|
||||
modal_confirmmentions: "Tem certeza de que deseja excluir todas as menções não lidas?",
|
||||
modal_confirmnotifications: "Tem certeza de que deseja excluir todas as notificações não lidas?",
|
||||
toast_alreadyclearing: "Exclui algumas menções já",
|
||||
toast_cleared: "Todas as menções recentes foram excluídas",
|
||||
toast_clearing: "Limpa todas as menções recentes"
|
||||
};
|
||||
case "ro": // Romanian
|
||||
return {
|
||||
context_dms: "Mesaje directe",
|
||||
context_guilds: "Toate serverele",
|
||||
context_mutedguilds: "Servere mutate",
|
||||
context_pingedguilds: "Servere pinged",
|
||||
context_unreadguilds: "Servere necitite",
|
||||
modal_confirmmentions: "Sigur doriți să ștergeți toate mențiunile necitite?",
|
||||
modal_confirmnotifications: "Sigur doriți să ștergeți toate notificările necitite?",
|
||||
toast_alreadyclearing: "Șterge deja câteva mențiuni",
|
||||
toast_cleared: "Toate mențiunile recente au fost șterse",
|
||||
toast_clearing: "Șterge toate mențiunile recente"
|
||||
};
|
||||
case "ru": // Russian
|
||||
return {
|
||||
context_dms: "Прямые сообщения",
|
||||
context_guilds: "Все серверы",
|
||||
context_mutedguilds: "Отключенные серверы",
|
||||
context_pingedguilds: "Проверенные серверы",
|
||||
context_unreadguilds: "Непрочитанные серверы",
|
||||
modal_confirmmentions: "Вы уверены, что хотите удалить все непрочитанные упоминания?",
|
||||
modal_confirmnotifications: "Вы действительно хотите удалить все непрочитанные уведомления?",
|
||||
toast_alreadyclearing: "Удаляет уже некоторые упоминания",
|
||||
toast_cleared: "Все недавние упоминания были удалены",
|
||||
toast_clearing: "Удаляет все недавние упоминания"
|
||||
};
|
||||
case "sv": // Swedish
|
||||
return {
|
||||
context_dms: "Direktmeddelanden",
|
||||
context_guilds: "Alla servrar",
|
||||
context_mutedguilds: "Dämpade servrar",
|
||||
context_pingedguilds: "Pingade servrar",
|
||||
context_unreadguilds: "Olästa servrar",
|
||||
modal_confirmmentions: "Är du säker på att du vill ta bort alla olästa omnämnanden?",
|
||||
modal_confirmnotifications: "Är du säker på att du vill ta bort alla olästa aviseringar?",
|
||||
toast_alreadyclearing: "Raderar några omnämnanden redan",
|
||||
toast_cleared: "Alla nya omnämnanden har tagits bort",
|
||||
toast_clearing: "Rensar alla senaste omnämnanden"
|
||||
};
|
||||
case "th": // Thai
|
||||
return {
|
||||
context_dms: "ข้อความโดยตรง",
|
||||
context_guilds: "เซิร์ฟเวอร์ทั้งหมด",
|
||||
context_mutedguilds: "เซิร์ฟเวอร์ที่ปิดเสียง",
|
||||
context_pingedguilds: "เซิร์ฟเวอร์ Pinged",
|
||||
context_unreadguilds: "เซิร์ฟเวอร์ที่ยังไม่ได้อ่าน",
|
||||
modal_confirmmentions: "แน่ใจไหมว่าต้องการลบข้อความที่ยังไม่ได้อ่านทั้งหมด",
|
||||
modal_confirmnotifications: "แน่ใจไหมว่าต้องการลบการแจ้งเตือนที่ยังไม่ได้อ่านทั้งหมด",
|
||||
toast_alreadyclearing: "ลบการกล่าวถึงบางส่วนแล้ว",
|
||||
toast_cleared: "ลบการกล่าวถึงล่าสุดทั้งหมดแล้ว",
|
||||
toast_clearing: "ล้างการพูดถึงล่าสุดทั้งหมด"
|
||||
};
|
||||
case "tr": // Turkish
|
||||
return {
|
||||
context_dms: "Direkt Mesajlar",
|
||||
context_guilds: "Tüm Sunucular",
|
||||
context_mutedguilds: "Sessiz Sunucular",
|
||||
context_pingedguilds: "Ping Gönderilen Sunucular",
|
||||
context_unreadguilds: "Okunmamış Sunucular",
|
||||
modal_confirmmentions: "Okunmamış tüm bahisleri silmek istediğinizden emin misiniz?",
|
||||
modal_confirmnotifications: "Okunmamış tüm bildirimleri silmek istediğinizden emin misiniz?",
|
||||
toast_alreadyclearing: "Zaten bazı bahsetmeleri siler",
|
||||
toast_cleared: "Son bahsedenlerin tümü silindi",
|
||||
toast_clearing: "Tüm son bahsedilenleri temizler"
|
||||
};
|
||||
case "uk": // Ukrainian
|
||||
return {
|
||||
context_dms: "Прямі повідомлення",
|
||||
context_guilds: "Усі сервери",
|
||||
context_mutedguilds: "Приглушені сервери",
|
||||
context_pingedguilds: "Pinged сервери",
|
||||
context_unreadguilds: "Непрочитані сервери",
|
||||
modal_confirmmentions: "Ви впевнені, що хочете видалити всі непрочитані згадки?",
|
||||
modal_confirmnotifications: "Ви впевнені, що хочете видалити всі непрочитані сповіщення?",
|
||||
toast_alreadyclearing: "Видаляє деякі згадки вже",
|
||||
toast_cleared: "Усі останні згадування були видалені",
|
||||
toast_clearing: "Очищає всі останні згадування"
|
||||
};
|
||||
case "vi": // Vietnamese
|
||||
return {
|
||||
context_dms: "Tin nhắn trực tiếp",
|
||||
context_guilds: "Tất cả máy chủ",
|
||||
context_mutedguilds: "Máy chủ bị tắt tiếng",
|
||||
context_pingedguilds: "Máy chủ Pinged",
|
||||
context_unreadguilds: "Máy chủ chưa đọc",
|
||||
modal_confirmmentions: "Bạn có chắc chắn muốn xóa tất cả các đề cập chưa đọc không?",
|
||||
modal_confirmnotifications: "Bạn có chắc chắn muốn xóa tất cả các thông báo chưa đọc không?",
|
||||
toast_alreadyclearing: "Đã xóa một số đề cập",
|
||||
toast_cleared: "Tất cả các đề cập gần đây đã bị xóa",
|
||||
toast_clearing: "Xóa tất cả các đề cập gần đây"
|
||||
};
|
||||
case "zh-CN": // Chinese (China)
|
||||
return {
|
||||
context_dms: "直接讯息",
|
||||
context_guilds: "所有服务器",
|
||||
context_mutedguilds: "静音服务器",
|
||||
context_pingedguilds: "绑定服务器",
|
||||
context_unreadguilds: "未读服务器",
|
||||
modal_confirmmentions: "您确定要删除所有未读的提及吗?",
|
||||
modal_confirmnotifications: "您确定要删除所有未读的通知吗?",
|
||||
toast_alreadyclearing: "已删除一些提及",
|
||||
toast_cleared: "最近所有提及的内容均已删除",
|
||||
toast_clearing: "清除所有最近提及的内容"
|
||||
};
|
||||
case "zh-TW": // Chinese (Taiwan)
|
||||
return {
|
||||
context_dms: "直接訊息",
|
||||
context_guilds: "所有服務器",
|
||||
context_mutedguilds: "靜音服務器",
|
||||
context_pingedguilds: "綁定服務器",
|
||||
context_unreadguilds: "未讀服務器",
|
||||
modal_confirmmentions: "您確定要刪除所有未讀的提及嗎?",
|
||||
modal_confirmnotifications: "您確定要刪除所有未讀的通知嗎?",
|
||||
toast_alreadyclearing: "已刪除一些提及",
|
||||
toast_cleared: "最近所有提及的內容均已刪除",
|
||||
toast_clearing: "清除所有最近提及的內容"
|
||||
};
|
||||
default: // English
|
||||
return {
|
||||
context_dms: "Direct Messages",
|
||||
context_guilds: "All Servers",
|
||||
context_mutedguilds: "Muted Servers",
|
||||
context_pingedguilds: "Pinged Servers",
|
||||
context_unreadguilds: "Unread Servers",
|
||||
modal_confirmmentions: "Are you sure you want to delete all unread Mentions?",
|
||||
modal_confirmnotifications: "Are you sure you want to delete all unread Notifications?",
|
||||
toast_alreadyclearing: "Already clearing some Mentions",
|
||||
toast_cleared: "All recent Mentions have been cleared",
|
||||
toast_clearing: "Clearing all recent Mentions"
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
})(window.BDFDB_Global.PluginUtils.buildPlugin(changeLog));
|
||||
})();
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"all": {
|
||||
"amounts": {
|
||||
"tooltipDelay": 0,
|
||||
"tooltipWidth": 300
|
||||
},
|
||||
"colors": {
|
||||
"tooltipColor": ""
|
||||
},
|
||||
"dates": {
|
||||
"tooltipDates": {}
|
||||
},
|
||||
"general": {
|
||||
"onlyShowOnShift": false
|
||||
},
|
||||
"items": {
|
||||
"icon": true,
|
||||
"owner": true,
|
||||
"creationDate": true,
|
||||
"joinDate": true,
|
||||
"members": true,
|
||||
"channels": true,
|
||||
"roles": true,
|
||||
"boosts": true,
|
||||
"language": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,577 @@
|
||||
/**
|
||||
* @name ServerDetails
|
||||
* @author DevilBro
|
||||
* @authorId 278543574059057154
|
||||
* @version 1.3.4
|
||||
* @description Shows Server Details in the Server List Tooltip
|
||||
* @invite Jx3TjNS
|
||||
* @donate https://www.paypal.me/MircoWittrien
|
||||
* @patreon https://www.patreon.com/MircoWittrien
|
||||
* @website https://mwittrien.github.io/
|
||||
* @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ServerDetails/
|
||||
* @updateUrl https://mwittrien.github.io/BetterDiscordAddons/Plugins/ServerDetails/ServerDetails.plugin.js
|
||||
*/
|
||||
|
||||
module.exports = (_ => {
|
||||
const changeLog = {
|
||||
|
||||
};
|
||||
|
||||
return !window.BDFDB_Global || (!window.BDFDB_Global.loaded && !window.BDFDB_Global.started) ? class {
|
||||
constructor (meta) {for (let key in meta) this[key] = meta[key];}
|
||||
getName () {return this.name;}
|
||||
getAuthor () {return this.author;}
|
||||
getVersion () {return this.version;}
|
||||
getDescription () {return `The Library Plugin needed for ${this.name} is missing. Open the Plugin Settings to download it. \n\n${this.description}`;}
|
||||
|
||||
downloadLibrary () {
|
||||
BdApi.Net.fetch("https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js").then(r => {
|
||||
if (!r || r.status != 200) throw new Error();
|
||||
else return r.text();
|
||||
}).then(b => {
|
||||
if (!b) throw new Error();
|
||||
else return require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0BDFDB.plugin.js"), b, _ => BdApi.UI.showToast("Finished downloading BDFDB Library", {type: "success"}));
|
||||
}).catch(error => {
|
||||
BdApi.UI.alert("Error", "Could not download BDFDB Library Plugin. Try again later or download it manually from GitHub: https://mwittrien.github.io/downloader/?library");
|
||||
});
|
||||
}
|
||||
|
||||
load () {
|
||||
if (!window.BDFDB_Global || !Array.isArray(window.BDFDB_Global.pluginQueue)) window.BDFDB_Global = Object.assign({}, window.BDFDB_Global, {pluginQueue: []});
|
||||
if (!window.BDFDB_Global.downloadModal) {
|
||||
window.BDFDB_Global.downloadModal = true;
|
||||
BdApi.UI.showConfirmationModal("Library Missing", `The Library Plugin needed for ${this.name} is missing. Please click "Download Now" to install it.`, {
|
||||
confirmText: "Download Now",
|
||||
cancelText: "Cancel",
|
||||
onCancel: _ => {delete window.BDFDB_Global.downloadModal;},
|
||||
onConfirm: _ => {
|
||||
delete window.BDFDB_Global.downloadModal;
|
||||
this.downloadLibrary();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!window.BDFDB_Global.pluginQueue.includes(this.name)) window.BDFDB_Global.pluginQueue.push(this.name);
|
||||
}
|
||||
start () {this.load();}
|
||||
stop () {}
|
||||
getSettingsPanel () {
|
||||
let template = document.createElement("template");
|
||||
template.innerHTML = `<div style="color: var(--text-strong); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${this.name} is missing.\nPlease click <a style="font-weight: 500;">Download Now</a> to install it.</div>`;
|
||||
template.content.firstElementChild.querySelector("a").addEventListener("click", this.downloadLibrary);
|
||||
return template.content.firstElementChild;
|
||||
}
|
||||
} : (([Plugin, BDFDB]) => {
|
||||
var _this;
|
||||
|
||||
const GuildDetailsComponent = class GuildDetails extends BdApi.React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {fetchedOwner: false, delayed: false, repositioned: false, shouldReposition: false, forced: false};
|
||||
}
|
||||
componentDidUpdate() {
|
||||
let tooltip = BDFDB.DOMUtils.getParent(BDFDB.dotCN.tooltip, BDFDB.ReactUtils.findDOMNode(this));
|
||||
if (tooltip) BDFDB.DOMUtils.addClass(tooltip, BDFDB.disCN._serverdetailstooltip);
|
||||
else if (this.props.tooltipContainer && this.props.tooltipContainer.tooltip) BDFDB.DOMUtils.removeClass(this.props.tooltipContainer.tooltip.firstElementChild, BDFDB.disCN._serverdetailstooltip);
|
||||
if (this.state.shouldReposition || _this.settings.amounts.tooltipDelay && this.state.delayed && !this.state.repositioned) {
|
||||
this.state.repositioned = true;
|
||||
this.state.shouldReposition = false;
|
||||
if (this.props.tooltipContainer && this.props.tooltipContainer.tooltip) this.props.tooltipContainer.tooltip.update();
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
if (!_this.settings.amounts.tooltipDelay && (!_this.settings.general.onlyShowOnShift || _this.settings.general.onlyShowOnShift && this.props.shiftKey)) BDFDB.DOMUtils.addClass(BDFDB.DOMUtils.getParent(BDFDB.dotCN.tooltip, BDFDB.ReactUtils.findDOMNode(this)), BDFDB.disCN._serverdetailstooltip);
|
||||
}
|
||||
render() {
|
||||
if (_this.settings.general.onlyShowOnShift) {
|
||||
let addListener = expanded => {
|
||||
let triggered = false, listener = event => {
|
||||
if (event.which != 16 || triggered) return;
|
||||
triggered = true;
|
||||
document.removeEventListener(expanded ? "keyup" : "keydown", listener);
|
||||
this.props.shiftKey = !expanded;
|
||||
this.state.forced = !expanded;
|
||||
this.state.repositioned = false;
|
||||
this.state.shouldReposition = true;
|
||||
BDFDB.ReactUtils.forceUpdate(this);
|
||||
};
|
||||
document.addEventListener(expanded ? "keyup" : "keydown", listener);
|
||||
};
|
||||
if (!this.props.shiftKey) {
|
||||
addListener(false);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
addListener(true);
|
||||
}
|
||||
}
|
||||
let owner = BDFDB.LibraryStores.UserStore.getUser(this.props.guild.ownerId);
|
||||
if (!owner && !this.state.fetchedOwner) {
|
||||
this.state.fetchedOwner = true;
|
||||
BDFDB.LibraryModules.UserProfileUtils.getUser(this.props.guild.ownerId).then(_ => BDFDB.ReactUtils.forceUpdate(this));
|
||||
}
|
||||
if (_this.settings.amounts.tooltipDelay && !this.state.delayed && !this.state.shouldReposition) {
|
||||
BDFDB.TimeUtils.timeout(_ => {
|
||||
this.state.delayed = true;
|
||||
BDFDB.ReactUtils.forceUpdate(this);
|
||||
}, this.state.forced ? 0 : (_this.settings.amounts.tooltipDelay * 1000));
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
let src = BDFDB.GuildUtils.getIcon(this.props.guild.id, 4096, this.props.guild.icon && BDFDB.LibraryModules.IconUtils.isAnimatedIconHash(this.props.guild.icon));
|
||||
let roles = BDFDB.LibraryStores.GuildRoleStore.getSortedRoles(this.props.guild.id);
|
||||
return BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
|
||||
direction: BDFDB.LibraryComponents.Flex.Direction.VERTICAL,
|
||||
align: BDFDB.LibraryComponents.Flex.Align.CENTER,
|
||||
children: [
|
||||
_this.settings.items.icon && (src ? BDFDB.ReactUtils.createElement("img", {
|
||||
className: BDFDB.disCN._serverdetailsicon,
|
||||
src: src
|
||||
}) : BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN._serverdetailsicon,
|
||||
children: this.props.guild.acronym
|
||||
})),
|
||||
_this.settings.items.owner && BDFDB.ReactUtils.createElement(GuildDetailsRowComponent, {
|
||||
prefix: BDFDB.LanguageUtils.LanguageStrings.SERVER_OWNER,
|
||||
string: !owner ? BDFDB.LanguageUtils.LanguageStrings.UNKNOWN_USER : owner.username
|
||||
}),
|
||||
_this.settings.items.creationDate && BDFDB.ReactUtils.createElement(GuildDetailsRowComponent, {
|
||||
prefix: _this.labels.creation_date,
|
||||
string: BDFDB.LibraryComponents.DateInput.format(_this.settings.dates.tooltipDates, BDFDB.LibraryModules.TimestampUtils.extractTimestamp(this.props.guild.id))
|
||||
}),
|
||||
_this.settings.items.joinDate && BDFDB.ReactUtils.createElement(GuildDetailsRowComponent, {
|
||||
prefix: _this.labels.join_date,
|
||||
string: BDFDB.LibraryComponents.DateInput.format(_this.settings.dates.tooltipDates, this.props.guild.joinedAt)
|
||||
}),
|
||||
_this.settings.items.members && BDFDB.ReactUtils.createElement(GuildDetailsRowComponent, {
|
||||
prefix: BDFDB.LanguageUtils.LanguageStrings.MEMBERS,
|
||||
string: BDFDB.LibraryStores.GuildMemberCountStore.getMemberCount(this.props.guild.id)
|
||||
}),
|
||||
_this.settings.items.boosts && BDFDB.ReactUtils.createElement(GuildDetailsRowComponent, {
|
||||
prefix: _this.labels.boosts,
|
||||
string: this.props.guild.premiumSubscriberCount
|
||||
}),
|
||||
_this.settings.items.channels && BDFDB.ReactUtils.createElement(GuildDetailsRowComponent, {
|
||||
prefix: BDFDB.LanguageUtils.LanguageStrings.CHANNELS,
|
||||
string: BDFDB.LibraryStores.GuildChannelStore.getChannels(this.props.guild.id).count
|
||||
}),
|
||||
_this.settings.items.roles && roles && roles.length && BDFDB.ReactUtils.createElement(GuildDetailsRowComponent, {
|
||||
prefix: BDFDB.LanguageUtils.LanguageStrings.ROLES,
|
||||
string: roles.filter(n => n.id != this.props.guild.id).length
|
||||
}),
|
||||
_this.settings.items.language && BDFDB.ReactUtils.createElement(GuildDetailsRowComponent, {
|
||||
prefix: BDFDB.LanguageUtils.LanguageStrings.LANGUAGE,
|
||||
string: BDFDB.LanguageUtils.getName(BDFDB.LanguageUtils.languages[this.props.guild.preferredLocale]) || this.props.guild.preferredLocale
|
||||
})
|
||||
].flat(10).filter(n => n)
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const GuildDetailsRowComponent = class GuildDetailsRow extends BdApi.React.Component {
|
||||
render() {
|
||||
return (this.props.prefix.length + this.props.string.length) > Math.round(34 * (_this.settings.amounts.tooltipWidth/300)) ? [
|
||||
BDFDB.ReactUtils.createElement("div", {
|
||||
children: `${this.props.prefix}:`
|
||||
}),
|
||||
BDFDB.ReactUtils.createElement("div", {
|
||||
children: this.props.string
|
||||
})
|
||||
] : BDFDB.ReactUtils.createElement("div", {
|
||||
children: `${BDFDB.StringUtils.upperCaseFirstChar(this.props.prefix)}: ${this.props.string}`
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return class ServerDetails extends Plugin {
|
||||
onLoad () {
|
||||
_this = this;
|
||||
|
||||
this.defaults = {
|
||||
general: {
|
||||
onlyShowOnShift: {value: false, description: "Only show the Details Tooltip, while holding 'Shift'"}
|
||||
},
|
||||
items: {
|
||||
icon: {value: true, description: "icon"},
|
||||
owner: {value: true, description: "SERVER_OWNER"},
|
||||
creationDate: {value: true, description: "creation_date"},
|
||||
joinDate: {value: true, description: "join_date"},
|
||||
members: {value: true, description: "MEMBERS"},
|
||||
channels: {value: true, description: "CHANNELS"},
|
||||
roles: {value: true, description: "ROLES"},
|
||||
boosts: {value: true, description: "boosts"},
|
||||
language: {value: true, description: "LANGUAGE"}
|
||||
},
|
||||
dates: {
|
||||
tooltipDates: {value: {}, description: "Tooltip Dates"}
|
||||
},
|
||||
colors: {
|
||||
tooltipColor: {value: "", description: "Tooltip Color"}
|
||||
},
|
||||
amounts: {
|
||||
tooltipDelay: {value: 0, min: 0, max: 10, digits: 1, unit: "s", description: "Tooltip Delay"},
|
||||
tooltipWidth: {value: 300, min: 200, max: 600, digits: 0, unit: "px", description: "Tooltip Width"}
|
||||
}
|
||||
};
|
||||
|
||||
this.modulePatches = {
|
||||
after: [
|
||||
"GuildItem"
|
||||
]
|
||||
};
|
||||
|
||||
this.patchPriority = 9;
|
||||
|
||||
this.css = `
|
||||
${BDFDB.dotCNS._serverdetailstooltip + BDFDB.dotCN.tooltipcontent} {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
max-width: unset;
|
||||
word-wrap: unset;
|
||||
}
|
||||
${BDFDB.dotCNS._serverdetailstooltip + BDFDB.dotCN._serverdetailsicon} {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
${BDFDB.dotCN._serverdetailstooltip} div${BDFDB.dotCN._serverdetailsicon} {
|
||||
background-color: var(--background-base-low);
|
||||
color: var(--text-subtle);
|
||||
font-size: 40px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
onStart () {
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
|
||||
onStop () {
|
||||
this.forceUpdateAll();
|
||||
|
||||
BDFDB.DOMUtils.removeLocalStyle(this.name + "TooltipWidth");
|
||||
}
|
||||
|
||||
getSettingsPanel (collapseStates = {}) {
|
||||
let settingsPanel;
|
||||
return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(this, {
|
||||
collapseStates: collapseStates,
|
||||
children: _ => {
|
||||
let settingsItems = [];
|
||||
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
|
||||
title: "General",
|
||||
collapseStates: collapseStates,
|
||||
children: Object.keys(this.defaults.general).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Switch",
|
||||
plugin: this,
|
||||
keys: ["general", key],
|
||||
label: this.defaults.general[key].description,
|
||||
value: this.settings.general[key]
|
||||
}))
|
||||
}));
|
||||
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
|
||||
title: "Tooltip Items",
|
||||
collapseStates: collapseStates,
|
||||
children: Object.keys(this.defaults.items).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Switch",
|
||||
plugin: this,
|
||||
keys: ["items", key],
|
||||
label: this.labels[this.defaults.items[key].description] || BDFDB.LanguageUtils.LanguageStrings[this.defaults.items[key].description],
|
||||
value: this.settings.items[key]
|
||||
}))
|
||||
}));
|
||||
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, {
|
||||
title: "Tooltip Format",
|
||||
collapseStates: collapseStates,
|
||||
children: Object.keys(this.defaults.dates).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.DateInput, Object.assign({}, this.settings.dates[key], {
|
||||
label: this.defaults.dates[key].description,
|
||||
onChange: valueObj => {
|
||||
this.SettingsUpdated = true;
|
||||
this.settings.dates[key] = valueObj;
|
||||
BDFDB.DataUtils.save(this.settings.dates, this, "dates");
|
||||
}
|
||||
}))).concat(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormDivider, {
|
||||
className: BDFDB.disCN.marginbottom8
|
||||
})).concat(Object.keys(this.defaults.amounts).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Slider",
|
||||
plugin: this,
|
||||
keys: ["amounts", key],
|
||||
label: this.defaults.amounts[key].description,
|
||||
basis: "70%",
|
||||
min: this.defaults.amounts[key].min,
|
||||
max: this.defaults.amounts[key].max,
|
||||
digits: this.defaults.amounts[key].digits,
|
||||
markerAmount: 11,
|
||||
onValueRender: value => value + this.defaults.amounts[key].unit,
|
||||
childProps: {type: "number"},
|
||||
value: this.settings.amounts[key]
|
||||
}))).concat(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormDivider, {
|
||||
className: BDFDB.disCN.marginbottom8
|
||||
})).concat(Object.keys(this.defaults.colors).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "TextInput",
|
||||
plugin: this,
|
||||
keys: ["colors", key],
|
||||
basis: "70%",
|
||||
label: this.defaults.colors[key].description,
|
||||
value: this.settings.colors[key],
|
||||
childProps: {type: "color"},
|
||||
placeholder: this.settings.colors[key]
|
||||
})))
|
||||
}));
|
||||
|
||||
return settingsItems;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onSettingsClosed () {
|
||||
if (this.SettingsUpdated) {
|
||||
delete this.SettingsUpdated;
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
}
|
||||
|
||||
forceUpdateAll () {
|
||||
let iconSize = this.settings.amounts.tooltipWidth - 80;
|
||||
BDFDB.DOMUtils.appendLocalStyle(this.name + "TooltipWidth", `
|
||||
${BDFDB.dotCN._serverdetailstooltip} {
|
||||
min-width: ${this.settings.amounts.tooltipWidth}px !important;
|
||||
width: unset !important;
|
||||
max-width: unset !important;
|
||||
}
|
||||
${BDFDB.dotCNS._serverdetailstooltip + BDFDB.dotCN._serverdetailsicon} {
|
||||
width: ${iconSize > 0 ? iconSize : 30}px;
|
||||
height: ${iconSize > 0 ? iconSize : 30}px;
|
||||
}
|
||||
`);
|
||||
|
||||
BDFDB.DiscordUtils.rerenderAll();
|
||||
}
|
||||
|
||||
processGuildItem (e) {
|
||||
if (!e.instance.props.guild || typeof e.instance.props?.children?.props?.className != "string" || e.instance.props?.children?.props?.className.indexOf(BDFDB.disCN.guildcontainer) == -1) return;
|
||||
if (!BDFDB.GuildUtils.is(e.instance.props.guild)) return;
|
||||
let tooltipContainer;
|
||||
e.returnvalue = BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, Object.assign({}, e.returnvalue.props, {
|
||||
ref: instance => {if (instance) tooltipContainer = instance;},
|
||||
tooltipConfig: Object.assign({
|
||||
backgroundColor: this.settings.colors.tooltipColor
|
||||
}, e.returnvalue.props.tooltipConfig, {
|
||||
type: "right",
|
||||
guild: e.instance.props.guild,
|
||||
list: true,
|
||||
offset: 4
|
||||
}),
|
||||
text: (instance, event) => BDFDB.ReactUtils.createElement(GuildDetailsComponent, {
|
||||
shiftKey: event.shiftKey,
|
||||
tooltipContainer: tooltipContainer,
|
||||
guild: e.instance.props.guild
|
||||
}),
|
||||
children: typeof e.returnvalue.props.children == "function" ? e.instance.props.children : e.returnvalue.props.children
|
||||
}));
|
||||
}
|
||||
|
||||
setLabelsByLanguage () {
|
||||
switch (BDFDB.LanguageUtils.getLanguage().id) {
|
||||
case "bg": // Bulgarian
|
||||
return {
|
||||
boosts: "Бустери",
|
||||
creation_date: "Дата на създаване",
|
||||
icon: "Икона",
|
||||
join_date: "Дата на присъединяване"
|
||||
};
|
||||
case "da": // Danish
|
||||
return {
|
||||
boosts: "Boosts",
|
||||
creation_date: "Oprettelsesdato",
|
||||
icon: "Ikon",
|
||||
join_date: "Deltag i dato"
|
||||
};
|
||||
case "de": // German
|
||||
return {
|
||||
boosts: "Boosts",
|
||||
creation_date: "Erstellungsdatum",
|
||||
icon: "Symbol",
|
||||
join_date: "Beitrittsdatum"
|
||||
};
|
||||
case "el": // Greek
|
||||
return {
|
||||
boosts: "Ενισχυτές",
|
||||
creation_date: "Ημερομηνία δημιουργίας",
|
||||
icon: "Εικονίδιο",
|
||||
join_date: "Ημερομηνία προσχώρησης"
|
||||
};
|
||||
case "es": // Spanish
|
||||
return {
|
||||
boosts: "Impulsores",
|
||||
creation_date: "Fecha de creación",
|
||||
icon: "Icono",
|
||||
join_date: "Fecha de Ingreso"
|
||||
};
|
||||
case "fi": // Finnish
|
||||
return {
|
||||
boosts: "Tehostimet",
|
||||
creation_date: "Luomispäivä",
|
||||
icon: "Kuvake",
|
||||
join_date: "Liittymispäivä"
|
||||
};
|
||||
case "fr": // French
|
||||
return {
|
||||
boosts: "Boosts",
|
||||
creation_date: "Date de création",
|
||||
icon: "Icône",
|
||||
join_date: "Date d'inscription"
|
||||
};
|
||||
case "hr": // Croatian
|
||||
return {
|
||||
boosts: "Pojačala",
|
||||
creation_date: "Datum stvaranja",
|
||||
icon: "Ikona",
|
||||
join_date: "Datum pridruživanja"
|
||||
};
|
||||
case "hu": // Hungarian
|
||||
return {
|
||||
boosts: "Emlékeztetők",
|
||||
creation_date: "Létrehozás dátuma",
|
||||
icon: "Ikon",
|
||||
join_date: "Csatlakozás dátuma"
|
||||
};
|
||||
case "it": // Italian
|
||||
return {
|
||||
boosts: "Boosts",
|
||||
creation_date: "Data di creazione",
|
||||
icon: "Icona",
|
||||
join_date: "Data di iscrizione"
|
||||
};
|
||||
case "ja": // Japanese
|
||||
return {
|
||||
boosts: "ブースター",
|
||||
creation_date: "作成日",
|
||||
icon: "アイコン",
|
||||
join_date: "参加日"
|
||||
};
|
||||
case "ko": // Korean
|
||||
return {
|
||||
boosts: "부스터",
|
||||
creation_date: "제작 일",
|
||||
icon: "상",
|
||||
join_date: "가입 날짜"
|
||||
};
|
||||
case "lt": // Lithuanian
|
||||
return {
|
||||
boosts: "Stiprintuvai",
|
||||
creation_date: "Sukūrimo data",
|
||||
icon: "Piktograma",
|
||||
join_date: "Įstojimo data"
|
||||
};
|
||||
case "nl": // Dutch
|
||||
return {
|
||||
boosts: "Boosts",
|
||||
creation_date: "Aanmaakdatum",
|
||||
icon: "Icoon",
|
||||
join_date: "Toetredingsdatum"
|
||||
};
|
||||
case "no": // Norwegian
|
||||
return {
|
||||
boosts: "Boosts",
|
||||
creation_date: "Opprettelsesdato",
|
||||
icon: "Ikon",
|
||||
join_date: "Bli med på dato"
|
||||
};
|
||||
case "pl": // Polish
|
||||
return {
|
||||
boosts: "Boosty",
|
||||
creation_date: "Data utworzenia",
|
||||
icon: "Ikona",
|
||||
join_date: "Data dołączenia"
|
||||
};
|
||||
case "pt-BR": // Portuguese (Brazil)
|
||||
return {
|
||||
boosts: "Boosts",
|
||||
creation_date: "Data de criação",
|
||||
icon: "Ícone",
|
||||
join_date: "Data de afiliação"
|
||||
};
|
||||
case "ro": // Romanian
|
||||
return {
|
||||
boosts: "Amplificatoare",
|
||||
creation_date: "Data crearii",
|
||||
icon: "Pictogramă",
|
||||
join_date: "Data înscrierii"
|
||||
};
|
||||
case "ru": // Russian
|
||||
return {
|
||||
boosts: "Бустеры",
|
||||
creation_date: "Дата создания",
|
||||
icon: "Икона",
|
||||
join_date: "Дате вступления"
|
||||
};
|
||||
case "sv": // Swedish
|
||||
return {
|
||||
boosts: "Boosts",
|
||||
creation_date: "Skapelsedagen",
|
||||
icon: "Ikon",
|
||||
join_date: "Gå med datum"
|
||||
};
|
||||
case "th": // Thai
|
||||
return {
|
||||
boosts: "บูสเตอร์",
|
||||
creation_date: "วันที่สร้าง",
|
||||
icon: "ไอคอน",
|
||||
join_date: "วันที่เข้าร่วม"
|
||||
};
|
||||
case "tr": // Turkish
|
||||
return {
|
||||
boosts: "Güçlendiriciler",
|
||||
creation_date: "Oluşturulma tarihi",
|
||||
icon: "Simge",
|
||||
join_date: "Üyelik Tarihi"
|
||||
};
|
||||
case "uk": // Ukrainian
|
||||
return {
|
||||
boosts: "Підсилювачі",
|
||||
creation_date: "Дата створення",
|
||||
icon: "Піктограма",
|
||||
join_date: "Дата приєднання"
|
||||
};
|
||||
case "vi": // Vietnamese
|
||||
return {
|
||||
boosts: "Bộ tăng tốc",
|
||||
creation_date: "Ngày thành lập",
|
||||
icon: "Biểu tượng",
|
||||
join_date: "Ngày tham gia"
|
||||
};
|
||||
case "zh-CN": // Chinese (China)
|
||||
return {
|
||||
boosts: "助推器",
|
||||
creation_date: "创建日期",
|
||||
icon: "图标",
|
||||
join_date: "参加日期"
|
||||
};
|
||||
case "zh-TW": // Chinese (Taiwan)
|
||||
return {
|
||||
boosts: "加成數",
|
||||
creation_date: "創建日期",
|
||||
icon: "圖示",
|
||||
join_date: "參加日期"
|
||||
};
|
||||
default: // English
|
||||
return {
|
||||
boosts: "Boosts",
|
||||
creation_date: "Creation Date",
|
||||
icon: "Icon",
|
||||
join_date: "Join Date"
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
})(window.BDFDB_Global.PluginUtils.buildPlugin(changeLog));
|
||||
})();
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"themeAssignments": {
|
||||
"noguild": "Frosted Glass",
|
||||
"191163742346543104": "Default",
|
||||
"230708419995107330": "Default",
|
||||
"301021184051642369": "Default",
|
||||
"340262122782982147": " Lluna Plena",
|
||||
"413603118832680960": "Default",
|
||||
"423075122610700288": "Default",
|
||||
"501047524963123212": "Default",
|
||||
"514422760781643786": "Default",
|
||||
"594829566330273792": "Default",
|
||||
"607901720806293515": "Default",
|
||||
"609090770712002575": "Default",
|
||||
"679071578021167135": "Default",
|
||||
"703597941809741834": "Default",
|
||||
"707267476391723008": "Default",
|
||||
"710203122106105927": "Default",
|
||||
"734060708219846666": "Default",
|
||||
"738872654928281620": "Default",
|
||||
"775772308261830737": "Default",
|
||||
"834834066008309800": "Default"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,411 @@
|
||||
/**
|
||||
* @name ShowBadgesInChat
|
||||
* @author DevilBro
|
||||
* @authorId 278543574059057154
|
||||
* @version 2.1.5
|
||||
* @description Displays Badges (Nitro, Hypesquad, etc...) in the Chat/MemberList/DMList
|
||||
* @invite Jx3TjNS
|
||||
* @donate https://www.paypal.me/MircoWittrien
|
||||
* @patreon https://www.patreon.com/MircoWittrien
|
||||
* @website https://mwittrien.github.io/
|
||||
* @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ShowBadgesInChat/
|
||||
* @updateUrl https://mwittrien.github.io/BetterDiscordAddons/Plugins/ShowBadgesInChat/ShowBadgesInChat.plugin.js
|
||||
*/
|
||||
|
||||
module.exports = (_ => {
|
||||
const changeLog = {
|
||||
|
||||
};
|
||||
|
||||
return !window.BDFDB_Global || (!window.BDFDB_Global.loaded && !window.BDFDB_Global.started) ? class {
|
||||
constructor (meta) {for (let key in meta) this[key] = meta[key];}
|
||||
getName () {return this.name;}
|
||||
getAuthor () {return this.author;}
|
||||
getVersion () {return this.version;}
|
||||
getDescription () {return `The Library Plugin needed for ${this.name} is missing. Open the Plugin Settings to download it. \n\n${this.description}`;}
|
||||
|
||||
downloadLibrary () {
|
||||
BdApi.Net.fetch("https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js").then(r => {
|
||||
if (!r || r.status != 200) throw new Error();
|
||||
else return r.text();
|
||||
}).then(b => {
|
||||
if (!b) throw new Error();
|
||||
else return require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0BDFDB.plugin.js"), b, _ => BdApi.UI.showToast("Finished downloading BDFDB Library", {type: "success"}));
|
||||
}).catch(error => {
|
||||
BdApi.UI.alert("Error", "Could not download BDFDB Library Plugin. Try again later or download it manually from GitHub: https://mwittrien.github.io/downloader/?library");
|
||||
});
|
||||
}
|
||||
|
||||
load () {
|
||||
if (!window.BDFDB_Global || !Array.isArray(window.BDFDB_Global.pluginQueue)) window.BDFDB_Global = Object.assign({}, window.BDFDB_Global, {pluginQueue: []});
|
||||
if (!window.BDFDB_Global.downloadModal) {
|
||||
window.BDFDB_Global.downloadModal = true;
|
||||
BdApi.UI.showConfirmationModal("Library Missing", `The Library Plugin needed for ${this.name} is missing. Please click "Download Now" to install it.`, {
|
||||
confirmText: "Download Now",
|
||||
cancelText: "Cancel",
|
||||
onCancel: _ => {delete window.BDFDB_Global.downloadModal;},
|
||||
onConfirm: _ => {
|
||||
delete window.BDFDB_Global.downloadModal;
|
||||
this.downloadLibrary();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!window.BDFDB_Global.pluginQueue.includes(this.name)) window.BDFDB_Global.pluginQueue.push(this.name);
|
||||
}
|
||||
start () {this.load();}
|
||||
stop () {}
|
||||
getSettingsPanel () {
|
||||
let template = document.createElement("template");
|
||||
template.innerHTML = `<div style="color: var(--text-strong); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${this.name} is missing.\nPlease click <a style="font-weight: 500;">Download Now</a> to install it.</div>`;
|
||||
template.content.firstElementChild.querySelector("a").addEventListener("click", this.downloadLibrary);
|
||||
return template.content.firstElementChild;
|
||||
}
|
||||
} : (([Plugin, BDFDB]) => {
|
||||
var _this;
|
||||
var badgeConfigs = {}, loadedUsers = {}, queuedInstances = {}, requestQueue = {queue: [], timeout: null, id: null}, cacheTimeout;
|
||||
|
||||
const places = ["chat", "memberList", "dmsList"];
|
||||
|
||||
const userBadgeFlagNameMap = {
|
||||
"BOT_HTTP_INTERACTIONS": "bot_commands",
|
||||
"HYPESQUAD_ONLINE_HOUSE_1": "hypesquad_house_1",
|
||||
"HYPESQUAD_ONLINE_HOUSE_2": "hypesquad_house_2",
|
||||
"HYPESQUAD_ONLINE_HOUSE_3": "hypesquad_house_3",
|
||||
"bot_commands": "BOT_HTTP_INTERACTIONS",
|
||||
"hypesquad_house_1": "HYPESQUAD_ONLINE_HOUSE_1",
|
||||
"hypesquad_house_2": "HYPESQUAD_ONLINE_HOUSE_2",
|
||||
"hypesquad_house_3": "HYPESQUAD_ONLINE_HOUSE_3"
|
||||
};
|
||||
|
||||
const badges = {};
|
||||
|
||||
return class ShowBadgesInChat extends Plugin {
|
||||
onLoad () {
|
||||
_this = this;
|
||||
|
||||
this.modulePatches = {
|
||||
before: [
|
||||
"MessageUsername"
|
||||
],
|
||||
after: [
|
||||
"NameContainerDecorators",
|
||||
"PrivateChannel",
|
||||
"UserBadges"
|
||||
]
|
||||
};
|
||||
|
||||
for (let key in BDFDB.DiscordConstants.UserBadges) {
|
||||
let basicKey = key.replace(/_lvl\d+|_tenure_\d+_month_v2/g, "");
|
||||
if (!badges[basicKey]) badges[basicKey] = {value: true, keys: []};
|
||||
badges[basicKey].keys.push(key);
|
||||
}
|
||||
|
||||
this.css = `
|
||||
${BDFDB.dotCN._showbadgesinchatbadges} {
|
||||
display: inline-flex !important;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
position: relative;
|
||||
margin: 0 0 0 4px;
|
||||
padding: 0;
|
||||
user-select: none;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
${BDFDB.dotCN._showbadgesinchatbadges} > * {
|
||||
margin: 0;
|
||||
}
|
||||
${BDFDB.dotCNS._showbadgesinchatbadges + BDFDB.dotCN.userbadge} {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
${BDFDB.dotCNS._showbadgesinchatbadges + BDFDB.dotCN.userbadge + BDFDB.dotCN._showbadgesinchatindicator}::before {
|
||||
display: none;
|
||||
}
|
||||
${BDFDB.dotCNS._showbadgesinchatbadgessettings + BDFDB.dotCN.userbadge} {
|
||||
width: 24px !important;
|
||||
height: 20px !important;
|
||||
}
|
||||
${BDFDB.dotCN.memberpremiumicon} {
|
||||
display: none;
|
||||
}
|
||||
${BDFDB.dotCNS._showbadgesinchatbadges + BDFDB.dotCN.memberpremiumicon} {
|
||||
display: block;
|
||||
position: static;
|
||||
margin: 0;
|
||||
}
|
||||
${BDFDB.dotCNS.messageheadertext + BDFDB.dotCN._showbadgesinchatbadgeschat} {
|
||||
top: 0.2rem;
|
||||
}
|
||||
${BDFDB.dotCNS.messagerepliedmessage + BDFDB.dotCN._showbadgesinchatbadgeschat} {
|
||||
top: 0;
|
||||
}
|
||||
${BDFDB.dotCN.messageheadertext}:has(${BDFDB.dotCN._showbadgesinchatbadges}) ${BDFDB.dotCN.bottag} {
|
||||
top: 0.4rem;
|
||||
}
|
||||
${BDFDB.dotCNS.messagecompact + BDFDB.dotCN.messageusername} ~ ${BDFDB.dotCN._showbadgesinchatbadges},
|
||||
${BDFDB.dotCNS.messagerepliedmessage + BDFDB.dotCN.messageusername} ~ ${BDFDB.dotCN._showbadgesinchatbadges} {
|
||||
text-indent: 0;
|
||||
}
|
||||
${BDFDB.dotCNS.messagerepliedmessage + BDFDB.dotCN.messageusername} ~ ${BDFDB.dotCN._showbadgesinchatbadges} {
|
||||
margin-left: 0;
|
||||
margin-right: .25rem;
|
||||
}
|
||||
|
||||
${BDFDB.dotCN._showbadgesinchatbadgessettings} {
|
||||
color: var(--text-strong);
|
||||
}
|
||||
${BDFDB.dotCN._showbadgesinchatbadgessettings} * {
|
||||
cursor: default;
|
||||
}
|
||||
${BDFDB.dotCN._showbadgesinchatbadgessettings}:last-child {
|
||||
margin-right: 8px;
|
||||
}
|
||||
${BDFDB.dotCN._showbadgesinchatbadges} .bd-profile-badge {
|
||||
height: 15px;
|
||||
}
|
||||
${BDFDB.dotCN._showbadgesinchatbadgeschat} .bd-profile-badge {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
${BDFDB.dotCN._showbadgesinchatbadgesmemberlist} .bd-profile-badge {
|
||||
display: none;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
onStart () {
|
||||
queuedInstances = {}, loadedUsers = {};
|
||||
requestQueue = {queue: [], timeout: null, id: null};
|
||||
|
||||
badgeConfigs = BDFDB.DataUtils.load(this, "badgeConfigs");
|
||||
for (let key in badges) {
|
||||
if (!badgeConfigs[key]) badgeConfigs[key] = {};
|
||||
for (let key2 of places) if (badgeConfigs[key][key2] == undefined) badgeConfigs[key][key2] = true;
|
||||
badgeConfigs[key].key = key;
|
||||
}
|
||||
|
||||
let badgeCache = BDFDB.DataUtils.load(this, "badgeCache");
|
||||
if (badgeCache) {
|
||||
let now = (new Date()).getTime(), month = 1000*60*60*24*30;
|
||||
for (let id in badgeCache) {
|
||||
if (now - badgeCache[id].date > month) delete badgeCache[id];
|
||||
else loadedUsers[id] = badgeCache[id];
|
||||
}
|
||||
BDFDB.DataUtils.save(badgeCache, this, "badgeCache");
|
||||
}
|
||||
|
||||
const processUser = (id, data) => {
|
||||
loadedUsers[id] = {}
|
||||
loadedUsers[id].badges = data.badges;
|
||||
loadedUsers[id].date = (new Date()).getTime();
|
||||
|
||||
BDFDB.TimeUtils.clear(cacheTimeout);
|
||||
cacheTimeout = BDFDB.TimeUtils.timeout(_ => BDFDB.DataUtils.save(loadedUsers, this, "badgeCache"), 5000);
|
||||
|
||||
if (requestQueue.id && requestQueue.id == id) {
|
||||
BDFDB.ReactUtils.forceUpdate(queuedInstances[requestQueue.id]);
|
||||
delete queuedInstances[requestQueue.id];
|
||||
requestQueue.id = null;
|
||||
BDFDB.TimeUtils.timeout(_ => this.runQueue(), 1000);
|
||||
}
|
||||
};
|
||||
BDFDB.PatchUtils.patch(this, BDFDB.LibraryModules.DispatchApiUtils, "dispatch", {after: e => {
|
||||
if (BDFDB.ObjectUtils.is(e.methodArguments[0]) && e.methodArguments[0].type == "USER_PROFILE_FETCH_FAILURE" && e.methodArguments[0].userId) {
|
||||
const user = BDFDB.LibraryStores.UserStore.getUser(e.methodArguments[0].userId);
|
||||
if (user && !loadedUsers[user.id]) processUser(e.methodArguments[0].userId, {user: user || {}, flags: user ? user.publicFlags : 0});
|
||||
}
|
||||
else if (BDFDB.ObjectUtils.is(e.methodArguments[0]) && e.methodArguments[0].type == "USER_PROFILE_FETCH_SUCCESS") {
|
||||
let userProfile = e.methodArguments[0].userProfile || e.methodArguments[0];
|
||||
if (userProfile && userProfile.user) processUser(userProfile.user.id, userProfile);
|
||||
}
|
||||
}});
|
||||
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
|
||||
onStop () {
|
||||
BDFDB.TimeUtils.clear(requestQueue.timeout);
|
||||
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
|
||||
getSettingsPanel (collapseStates = {}) {
|
||||
let settingsPanel;
|
||||
return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(this, {
|
||||
collapseStates: collapseStates,
|
||||
children: _ => {
|
||||
let settingsItems = [];
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormTitle.Title, {
|
||||
className: BDFDB.disCN.marginbottom4,
|
||||
tag: BDFDB.LibraryComponents.FormTitle.Tags.H3,
|
||||
children: "Show Badges in"
|
||||
}));
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsList, {
|
||||
settings: places,
|
||||
data: Object.keys(badges).filter(n => n.indexOf("BOT_") != 0).map(key => badgeConfigs[key]),
|
||||
noRemove: true,
|
||||
renderLabel: (cardData, instance) => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex.Child, {
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Clickable, {
|
||||
onClick: _ => {
|
||||
for (let settingId of places) badgeConfigs[cardData.key][settingId] = true;
|
||||
BDFDB.DataUtils.save(badgeConfigs, this, "badgeConfigs");
|
||||
BDFDB.ReactUtils.forceUpdate(instance);
|
||||
this.SettingsUpdated = true;
|
||||
},
|
||||
onContextMenu: _ => {
|
||||
for (let settingId of places) badgeConfigs[cardData.key][settingId] = false;
|
||||
BDFDB.DataUtils.save(badgeConfigs, this, "badgeConfigs");
|
||||
BDFDB.ReactUtils.forceUpdate(instance);
|
||||
this.SettingsUpdated = true;
|
||||
},
|
||||
children: cardData.key.split("_").map(n => BDFDB.StringUtils.upperCaseFirstChar(n.toLowerCase())).join(" ")
|
||||
})
|
||||
}),
|
||||
badges[cardData.key] && badges[cardData.key].keys.map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.UserBadges, {
|
||||
className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN._showbadgesinchatbadges, BDFDB.disCN._showbadgesinchatbadgessettings),
|
||||
place: "settings",
|
||||
custom: true,
|
||||
badges: [{id: key, icon: BDFDB.DiscordConstants.UserBadges[key]}]
|
||||
}))
|
||||
]
|
||||
}),
|
||||
onHeaderClick: (settingId, instance) => {
|
||||
for (let key in badgeConfigs) badgeConfigs[key][settingId] = true;
|
||||
BDFDB.DataUtils.save(badgeConfigs, this, "badgeConfigs");
|
||||
BDFDB.ReactUtils.forceUpdate(instance);
|
||||
this.SettingsUpdated = true;
|
||||
},
|
||||
onHeaderContextMenu: (settingId, instance) => {
|
||||
for (let key in badgeConfigs) badgeConfigs[key][settingId] = false;
|
||||
BDFDB.DataUtils.save(badgeConfigs, this, "badgeConfigs");
|
||||
BDFDB.ReactUtils.forceUpdate(instance);
|
||||
this.SettingsUpdated = true;
|
||||
},
|
||||
onCheckboxChange: (value, instance) => {
|
||||
badgeConfigs[instance.props.cardId][instance.props.settingId] = value;
|
||||
BDFDB.DataUtils.save(badgeConfigs, this, "badgeConfigs");
|
||||
this.SettingsUpdated = true;
|
||||
}
|
||||
}));
|
||||
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, {
|
||||
type: "Button",
|
||||
color: BDFDB.LibraryComponents.Button.Colors.RED,
|
||||
label: "Reset cached Badge Data",
|
||||
onClick: _ => BDFDB.ModalUtils.confirm(this, "Are you sure you want to reset the Badge Cache? This will force all Badges to rerender.", _ => {
|
||||
BDFDB.DataUtils.remove(this, "badgeCache");
|
||||
this.SettingsUpdated = true;
|
||||
}),
|
||||
children: BDFDB.LanguageUtils.LanguageStrings.RESET
|
||||
}));
|
||||
|
||||
return settingsItems;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onSettingsClosed () {
|
||||
if (this.SettingsUpdated) {
|
||||
delete this.SettingsUpdated;
|
||||
this.forceUpdateAll();
|
||||
}
|
||||
}
|
||||
|
||||
forceUpdateAll () {
|
||||
BDFDB.PatchUtils.forceAllUpdates(this);
|
||||
BDFDB.MessageUtils.rerenderAll();
|
||||
}
|
||||
|
||||
processMessageUsername (e) {
|
||||
if (!e.instance.props.message) return;
|
||||
const author = e.instance.props.userOverride || e.instance.props.message.author;
|
||||
let index = e.instance.props.compact ? 1 : 0;
|
||||
if (!BDFDB.ArrayUtils.is(e.instance.props.decorations[index])) e.instance.props.decorations[index] = [e.instance.props.decorations[index]].filter(n => n);
|
||||
this.injectBadges(e.instance.props.decorations[index], author, (BDFDB.LibraryStores.ChannelStore.getChannel(e.instance.props.message.channel_id) || {}).guild_id, "chat");
|
||||
}
|
||||
|
||||
processNameContainerDecorators (e) {
|
||||
if (!e.instance.props.user) return;
|
||||
this.injectBadges(e.returnvalue.props.children, e.instance.props.user, BDFDB.LibraryStores.SelectedGuildStore.getGuildId(), "memberList");
|
||||
}
|
||||
|
||||
processPrivateChannel (e) {
|
||||
if (!e.instance.props.user) return;
|
||||
let wrapper = e.returnvalue && e.returnvalue.props.children && e.returnvalue.props.children.props && typeof e.returnvalue.props.children.props.children == "function" ? e.returnvalue.props.children : e.returnvalue;
|
||||
if (typeof wrapper.props.children == "function") {
|
||||
let childrenRender = wrapper.props.children;
|
||||
wrapper.props.children = BDFDB.TimeUtils.suppress((...args) => {
|
||||
let children = childrenRender(...args);
|
||||
this._processPrivateChannel(e.instance, children);
|
||||
return children;
|
||||
}, "Error in Children Render of PrivateChannel!", this);
|
||||
}
|
||||
else this._processPrivateChannel(e.instance, wrapper);
|
||||
}
|
||||
|
||||
_processPrivateChannel (instance, returnvalue, a) {
|
||||
const wrapper = returnvalue.props.decorators ? returnvalue : BDFDB.ReactUtils.findChild(returnvalue, {props: ["decorators"]}) || returnvalue;
|
||||
if (!wrapper) return;
|
||||
wrapper.props.decorators = [wrapper.props.decorators].flat(10);
|
||||
this.injectBadges(wrapper.props.decorators, instance.props.user, null, "dmsList");
|
||||
}
|
||||
|
||||
processUserBadges (e) {
|
||||
if (!e.instance.props.custom) return;
|
||||
let filter = e.instance.props.place != "settings";
|
||||
for (let i in e.returnvalue.props.children) if (e.returnvalue.props.children[i]) {
|
||||
let keyName = filter && Object.keys(badges).find(n => badges[n].keys.includes(e.returnvalue.props.children[i].key.split("-")[0]));
|
||||
if (keyName && badgeConfigs[keyName] && !badgeConfigs[keyName][e.instance.props.place]) e.returnvalue.props.children[i] = null;
|
||||
else if (typeof e.returnvalue.props.children[i].props.children == "function" && e.returnvalue.props.children[i].props.text) {
|
||||
e.returnvalue.props.children[i] = BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, e.returnvalue.props.children[i].props);
|
||||
}
|
||||
}
|
||||
if (!e.returnvalue.props.children.filter(n => n).length) return null;
|
||||
}
|
||||
|
||||
injectBadges (children, user, guildId, place) {
|
||||
if (!BDFDB.ArrayUtils.is(children) || !user || user.isNonUserBot()) return;
|
||||
if (!loadedUsers[user.id] || !loadedUsers[user.id].badges || ((new Date()).getTime() - loadedUsers[user.id].date >= 1000*60*60*24*7)) {
|
||||
queuedInstances[user.id] = [].concat(queuedInstances[user.id]).filter(n => n);
|
||||
if (requestQueue.queue.indexOf(user.id) == -1) requestQueue.queue.push(user.id);
|
||||
this.runQueue();
|
||||
}
|
||||
children.push(BDFDB.ReactUtils.createElement(class extends BDFDB.ReactUtils.Component {
|
||||
render() {
|
||||
if (!loadedUsers[user.id] || !loadedUsers[user.id].badges || ((new Date()).getTime() - loadedUsers[user.id].date >= 1000*60*60*24*7)) {
|
||||
queuedInstances[user.id] = [].concat(queuedInstances[user.id]).filter(n => n);
|
||||
if (queuedInstances[user.id].indexOf(this) == -1) queuedInstances[user.id].push(this);
|
||||
return null;
|
||||
}
|
||||
else return BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.UserBadges, {
|
||||
className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN._showbadgesinchatbadges, BDFDB.disCN[`_showbadgesinchatbadges${place.toLowerCase()}`]),
|
||||
place: place,
|
||||
custom: true,
|
||||
badges: loadedUsers[user.id].badges
|
||||
});
|
||||
}
|
||||
}, {}, true));
|
||||
}
|
||||
|
||||
runQueue () {
|
||||
if (!requestQueue.id) {
|
||||
let id = requestQueue.queue.shift();
|
||||
if (id) {
|
||||
requestQueue.id = id;
|
||||
BDFDB.TimeUtils.clear(requestQueue.timeout);
|
||||
requestQueue.timeout = BDFDB.TimeUtils.timeout(_ => {
|
||||
requestQueue.id = null;
|
||||
this.runQueue();
|
||||
}, 30000);
|
||||
|
||||
BDFDB.LibraryModules.UserProfileUtils.fetchProfile(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
})(window.BDFDB_Global.PluginUtils.buildPlugin(changeLog));
|
||||
})();
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"all": {
|
||||
"connections": {
|
||||
"amazon-music": true,
|
||||
"battlenet": true,
|
||||
"bluesky": true,
|
||||
"bungie": true,
|
||||
"crunchyroll": true,
|
||||
"domain": true,
|
||||
"ebay": true,
|
||||
"epicgames": true,
|
||||
"facebook": true,
|
||||
"github": true,
|
||||
"instagram": true,
|
||||
"leagueoflegends": true,
|
||||
"mastodon": true,
|
||||
"meta_quest_or_horizon": true,
|
||||
"paypal": true,
|
||||
"playstation": true,
|
||||
"playstation-stg": true,
|
||||
"reddit": true,
|
||||
"riotgames": true,
|
||||
"roblox": true,
|
||||
"samsung": true,
|
||||
"skype": true,
|
||||
"spotify": true,
|
||||
"steam": true,
|
||||
"tiktok": true,
|
||||
"twitch": true,
|
||||
"twitter_legacy": true,
|
||||
"twitter": true,
|
||||
"xbox": true,
|
||||
"youtube": true
|
||||
},
|
||||
"general": {
|
||||
"useColoredIcons": false,
|
||||
"useColoredTooltips": false,
|
||||
"showDetails": true,
|
||||
"showVerifiedBadge": true,
|
||||
"openWebpage": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
* @name ShowConnections
|
||||
* @author DevilBro
|
||||
* @authorId 278543574059057154
|
||||
* @version 1.3.2
|
||||
* @description Shows the connected Accounts of a User in the UserPopout
|
||||
* @invite Jx3TjNS
|
||||
* @donate https://www.paypal.me/MircoWittrien
|
||||
* @patreon https://www.patreon.com/MircoWittrien
|
||||
* @website https://mwittrien.github.io/
|
||||
* @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ShowConnections/
|
||||
* @updateUrl https://mwittrien.github.io/BetterDiscordAddons/Plugins/ShowConnections/ShowConnections.plugin.js
|
||||
*/
|
||||
|
||||
module.exports = (_ => {
|
||||
const changeLog = {
|
||||
|
||||
};
|
||||
|
||||
return !window.BDFDB_Global || (!window.BDFDB_Global.loaded && !window.BDFDB_Global.started) ? class {
|
||||
constructor (meta) {for (let key in meta) this[key] = meta[key];}
|
||||
getName () {return this.name;}
|
||||
getAuthor () {return this.author;}
|
||||
getVersion () {return this.version;}
|
||||
getDescription () {return `The Library Plugin needed for ${this.name} is missing. Open the Plugin Settings to download it. \n\n${this.description}`;}
|
||||
|
||||
downloadLibrary () {
|
||||
BdApi.Net.fetch("https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js").then(r => {
|
||||
if (!r || r.status != 200) throw new Error();
|
||||
else return r.text();
|
||||
}).then(b => {
|
||||
if (!b) throw new Error();
|
||||
else return require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0BDFDB.plugin.js"), b, _ => BdApi.UI.showToast("Finished downloading BDFDB Library", {type: "success"}));
|
||||
}).catch(error => {
|
||||
BdApi.UI.alert("Error", "Could not download BDFDB Library Plugin. Try again later or download it manually from GitHub: https://mwittrien.github.io/downloader/?library");
|
||||
});
|
||||
}
|
||||
|
||||
load () {
|
||||
if (!window.BDFDB_Global || !Array.isArray(window.BDFDB_Global.pluginQueue)) window.BDFDB_Global = Object.assign({}, window.BDFDB_Global, {pluginQueue: []});
|
||||
if (!window.BDFDB_Global.downloadModal) {
|
||||
window.BDFDB_Global.downloadModal = true;
|
||||
BdApi.UI.showConfirmationModal("Library Missing", `The Library Plugin needed for ${this.name} is missing. Please click "Download Now" to install it.`, {
|
||||
confirmText: "Download Now",
|
||||
cancelText: "Cancel",
|
||||
onCancel: _ => {delete window.BDFDB_Global.downloadModal;},
|
||||
onConfirm: _ => {
|
||||
delete window.BDFDB_Global.downloadModal;
|
||||
this.downloadLibrary();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!window.BDFDB_Global.pluginQueue.includes(this.name)) window.BDFDB_Global.pluginQueue.push(this.name);
|
||||
}
|
||||
start () {this.load();}
|
||||
stop () {}
|
||||
getSettingsPanel () {
|
||||
let template = document.createElement("template");
|
||||
template.innerHTML = `<div style="color: var(--text-strong); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${this.name} is missing.\nPlease click <a style="font-weight: 500;">Download Now</a> to install it.</div>`;
|
||||
template.content.firstElementChild.querySelector("a").addEventListener("click", this.downloadLibrary);
|
||||
return template.content.firstElementChild;
|
||||
}
|
||||
} : (([Plugin, BDFDB]) => {
|
||||
var _this;
|
||||
var loadedUsers, requestedUsers, queuedInstances;
|
||||
|
||||
const UserConnectionsComponents = class UserConnections extends BdApi.React.Component {
|
||||
render() {
|
||||
if (!loadedUsers[this.props.user.id] && !requestedUsers[this.props.user.id]) {
|
||||
requestedUsers[this.props.user.id] = true;
|
||||
queuedInstances[this.props.user.id] = [].concat(queuedInstances[this.props.user.id]).filter(n => n);
|
||||
BDFDB.LibraryModules.UserProfileUtils.fetchProfile(this.props.user.id);
|
||||
}
|
||||
if (!loadedUsers[this.props.user.id]) {
|
||||
if (queuedInstances[this.props.user.id].indexOf(this) == -1) queuedInstances[this.props.user.id].push(this);
|
||||
return null;
|
||||
}
|
||||
let connections = loadedUsers[this.props.user.id].filter(c => _this.settings.connections[c.type]);
|
||||
if (!connections.length) return null;
|
||||
let isLightTheme = (!this.props.theme || this.props.theme == "light") && BDFDB.DiscordUtils.getTheme() == BDFDB.disCN.themelight;
|
||||
return BDFDB.ReactUtils.createElement("section", {
|
||||
className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN.userprofilesection, BDFDB.disCN._showconnectionsconnectionswrapper),
|
||||
children: BDFDB.ReactUtils.createElement("div", {
|
||||
className: BDFDB.disCN._showconnectionsconnections,
|
||||
children: connections.map(c => {
|
||||
let provider = BDFDB.LibraryModules.ConnectionProviderUtils.get(c.type);
|
||||
let url = _this.settings.general.openWebpage && provider.getPlatformUserUrl && provider.getPlatformUserUrl(c);
|
||||
let metadata = [];
|
||||
if (_this.settings.general.showDetails && provider.hasMetadata && c.metadata) {
|
||||
if (c.metadata.created_at) metadata.push(BDFDB.ReactUtils.createElement("span", {children: BDFDB.LanguageUtils.LanguageStringsFormat("MEMBER_SINCE_PLACEHOLDER", (new Date(c.metadata.created_at)).toLocaleDateString("default", {year: "numeric", month: "long", day: "numeric"}))}));
|
||||
}
|
||||
return BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, {
|
||||
text: `${provider.name}: ${c.name}`,
|
||||
note: metadata && metadata.length ? BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Flex, {
|
||||
direction: BDFDB.LibraryComponents.Flex.Direction.VERTICAL,
|
||||
children: metadata
|
||||
}): null,
|
||||
tooltipConfig: {backgroundColor: _this.settings.general.useColoredTooltips && BDFDB.ColorUtils.change(provider.color, -0.3), color: !_this.settings.general.useColoredTooltips || !provider.color ? "primary" : null},
|
||||
children: BDFDB.ReactUtils.createElement(!url ? "div" : BDFDB.LibraryComponents.Anchor, Object.assign(!url ? {} : {
|
||||
href: url
|
||||
}, {
|
||||
className: BDFDB.DOMUtils.formatClassName(BDFDB.disCN._showconnectionsconnection, url && BDFDB.disCN.cursorpointer),
|
||||
onContextMenu: event => {
|
||||
BDFDB.ContextMenuUtils.open(_this, event, BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuGroup, {
|
||||
children: [
|
||||
BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
|
||||
label: BDFDB.LanguageUtils.LibraryStringsFormat("copy", BDFDB.LanguageUtils.LanguageStrings.USERNAME),
|
||||
id: BDFDB.ContextMenuUtils.createItemId(_this.name, "copy-name"),
|
||||
action: _ => BDFDB.LibraryModules.WindowUtils.copy(c.name)
|
||||
}),
|
||||
url && BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, {
|
||||
label: BDFDB.LanguageUtils.LibraryStringsFormat("copy", BDFDB.LanguageUtils.LanguageStrings.COPY_LINK),
|
||||
id: BDFDB.ContextMenuUtils.createItemId(_this.name, "copy-url"),
|
||||
action: _ => BDFDB.LibraryModules.WindowUtils.copy(url)
|
||||
})
|
||||
]
|
||||
}));
|
||||
},
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement("img", {
|
||||
className: BDFDB.disCN._showconnectionsicon,
|
||||
alt: BDFDB.LanguageUtils.LanguageStringsFormat("PLACEHOLDER_LOGO", provider.name),
|
||||
src: provider.icon[this.props.popoutColor ? (BDFDB.ColorUtils.isBright(this.props.popoutColor) ? "lightSVG" : "darkSVG") : (_this.settings.general.useColoredIcons ? (isLightTheme ? "lightSVG" : "darkSVG") : "whiteSVG")]
|
||||
}),
|
||||
_this.settings.general.showVerifiedBadge && c.verified && BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, {
|
||||
text: BDFDB.LanguageUtils.LanguageStrings.VERIFIED_CONNECTION,
|
||||
tooltipConfig: {color: "brand", type: "bottom"},
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FlowerStar, {
|
||||
className: BDFDB.disCN._showconnectionsverifiedbadge,
|
||||
size: "50%",
|
||||
color: isLightTheme ? BDFDB.DiscordConstants.Colors.PRIMARY_200 : BDFDB.DiscordConstants.Colors.PRIMARY,
|
||||
children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, {
|
||||
name: BDFDB.LibraryComponents.SvgIcon.Names.CHECKMARK,
|
||||
width: "70%",
|
||||
height: "70%",
|
||||
color: isLightTheme ? BDFDB.DiscordConstants.Colors.PRIMARY_500 : BDFDB.DiscordConstants.Colors.WHITE
|
||||
})
|
||||
})
|
||||
})
|
||||
]
|
||||
}))
|
||||
});
|
||||
})
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return class ShowConnections extends Plugin {
|
||||
onLoad () {
|
||||
_this = this;
|
||||
loadedUsers = {};
|
||||
requestedUsers = {};
|
||||
queuedInstances = {};
|
||||
|
||||
this.patchPriority = 9;
|
||||
|
||||
this.modulePatches = {
|
||||
after: [
|
||||
"UserHeaderUsername"
|
||||
]
|
||||
};
|
||||
|
||||
this.defaults = {
|
||||
general: {
|
||||
useColoredIcons: {value: true, description: "Uses colored Version of the Icons"},
|
||||
useColoredTooltips: {value: true, description: "Uses colored Version of the Tooltips"},
|
||||
showDetails: {value: true, description: "Shows Details of Connection on hover"},
|
||||
showVerifiedBadge: {value: true, description: "Shows the Badge for verified Connections"},
|
||||
openWebpage: {value: true, description: "Opens the Connection Page when clicking the Icon"}
|
||||
},
|
||||
connections: {}
|
||||
};
|
||||
|
||||
for (let connection of BDFDB.LibraryModules.ConnectionProviderUtils.filter(n => n)) this.defaults.connections[connection.type] = Object.assign({}, connection, {value: true});
|
||||
|
||||
this.css = `
|
||||
${BDFDB.dotCN._showconnectionsconnectionswrapper} {
|
||||
order: 999;
|
||||
}
|
||||
${BDFDB.dotCN._showconnectionsconnections} {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
${BDFDB.dotCN._showconnectionsconnection} {
|
||||
position: relative;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
margin: 4px 10px 6px 0;
|
||||
}
|
||||
${BDFDB.dotCN._showconnectionsicon} {
|
||||
margin: -15% 0 0 -15%;
|
||||
width: 130%;
|
||||
height: 130%;
|
||||
}
|
||||
${BDFDB.dotCN._showconnectionsverifiedbadge} {
|
||||
position: absolute;
|
||||
bottom: -10%;
|
||||
right: -10%;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
onStart () {
|
||||
BDFDB.PatchUtils.patch(this, BDFDB.LibraryModules.DispatchApiUtils, "dispatch", {after: e => {
|
||||
if (BDFDB.ObjectUtils.is(e.methodArguments[0]) && e.methodArguments[0].type == "USER_PROFILE_FETCH_SUCCESS") {
|
||||
let userProfile = e.methodArguments[0].userProfile || e.methodArguments[0];
|
||||
if (userProfile.user && userProfile.connected_accounts) {
|
||||
delete requestedUsers[userProfile.user.id];
|
||||
loadedUsers[userProfile.user.id] = userProfile.connected_accounts;
|
||||
BDFDB.ReactUtils.forceUpdate(queuedInstances[userProfile.user.id]);
|
||||
delete queuedInstances[userProfile.user.id];
|
||||
}
|
||||
}
|
||||
}});
|
||||
}
|
||||
|
||||
onStop () {}
|
||||
|
||||
getSettingsPanel (collapseStates = {}) {
|
||||
let settingsPanel;
|
||||
return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(this, {
|
||||
collapseStates: collapseStates,
|
||||
children: _ => {
|
||||
let settingsItems = [];
|
||||
|
||||
for (let key in this.defaults.general) settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Switch",
|
||||
plugin: this,
|
||||
keys: ["general", key],
|
||||
label: this.defaults.general[key].description,
|
||||
value: this.settings.general[key]
|
||||
}));
|
||||
|
||||
settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsPanelList, {
|
||||
title: "Display Connections:",
|
||||
children: Object.keys(this.defaults.connections).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, {
|
||||
type: "Switch",
|
||||
plugin: this,
|
||||
keys: ["connections", key],
|
||||
label: this.defaults.connections[key].name,
|
||||
value: this.settings.connections[key],
|
||||
labelChildren: [
|
||||
BDFDB.ReactUtils.createElement("img", {style: {width: 28, height: 28}, src: this.defaults.connections[key].icon.lightSVG}),
|
||||
BDFDB.ReactUtils.createElement("img", {style: {width: 28, height: 28}, src: this.defaults.connections[key].icon.whiteSVG})
|
||||
]
|
||||
}))
|
||||
}));
|
||||
|
||||
return settingsItems;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
processUserHeaderUsername (e) {
|
||||
let themeType = BDFDB.ObjectUtils.get(e.instance, "props.tags.props.themeType");
|
||||
if (themeType != "SIDEBAR" && themeType != "POPOUT" || e.instance.props.className) return;
|
||||
let user = e.instance.props.user || BDFDB.LibraryStores.UserStore.getUser(e.instance.props.userId);
|
||||
if (!user || user.isNonUserBot()) return;
|
||||
e.returnvalue = [e.returnvalue].flat(10);
|
||||
e.returnvalue.push(BDFDB.ReactUtils.createElement(UserConnectionsComponents, {
|
||||
user: user,
|
||||
popoutColor: BDFDB.ObjectUtils.get(e.instance, "props.tags.props.displayProfile.themeColors.1"),
|
||||
theme: e.instance.props.theme
|
||||
}, true));
|
||||
}
|
||||
};
|
||||
})(window.BDFDB_Global.PluginUtils.buildPlugin(changeLog));
|
||||
})();
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"settings": {
|
||||
"previewState": false,
|
||||
"previewDefaultState": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,375 @@
|
||||
/**
|
||||
* @name StickerEmojiPreview
|
||||
* @description Adds a zoomed preview to those tiny Stickers and Emojis
|
||||
* @version 1.3.3
|
||||
* @author Skamt
|
||||
* @website https://github.com/Skamt/BDAddons/tree/main/StickerEmojiPreview
|
||||
* @source https://raw.githubusercontent.com/Skamt/BDAddons/main/StickerEmojiPreview/StickerEmojiPreview.plugin.js
|
||||
*/
|
||||
|
||||
// config:@Config
|
||||
var Config_default = {
|
||||
"info": {
|
||||
"name": "StickerEmojiPreview",
|
||||
"version": "1.3.3",
|
||||
"description": "Adds a zoomed preview to those tiny Stickers and Emojis",
|
||||
"source": "https://raw.githubusercontent.com/Skamt/BDAddons/main/StickerEmojiPreview/StickerEmojiPreview.plugin.js",
|
||||
"github": "https://github.com/Skamt/BDAddons/tree/main/StickerEmojiPreview",
|
||||
"authors": [{
|
||||
"name": "Skamt"
|
||||
}]
|
||||
},
|
||||
"settings": {
|
||||
"previewState": false,
|
||||
"previewDefaultState": false
|
||||
}
|
||||
};
|
||||
|
||||
// common/Api.js
|
||||
var Api = new BdApi(Config_default.info.name);
|
||||
var DOM = /* @__PURE__ */ (() => Api.DOM)();
|
||||
var Data = /* @__PURE__ */ (() => Api.Data)();
|
||||
var React = /* @__PURE__ */ (() => Api.React)();
|
||||
var Patcher = /* @__PURE__ */ (() => Api.Patcher)();
|
||||
var Logger = /* @__PURE__ */ (() => Api.Logger)();
|
||||
var Webpack = /* @__PURE__ */ (() => Api.Webpack)();
|
||||
|
||||
// common/Utils/Logger.js
|
||||
Logger.patchError = (patchId) => {
|
||||
console.error(`%c[${Config_default.info.name}] %cCould not find module for %c[${patchId}]`, "color: #3a71c1;font-weight: bold;", "", "color: red;font-weight: bold;");
|
||||
};
|
||||
var Logger_default = Logger;
|
||||
|
||||
// common/Utils/EventEmitter.js
|
||||
var EventEmitter_default = class {
|
||||
constructor() {
|
||||
this.listeners = {};
|
||||
}
|
||||
isInValid(event, handler) {
|
||||
return typeof event !== "string" || typeof handler !== "function";
|
||||
}
|
||||
once(event, handler) {
|
||||
if (this.isInValid(event, handler)) return;
|
||||
if (!this.listeners[event]) this.listeners[event] = /* @__PURE__ */ new Set();
|
||||
const wrapper = () => {
|
||||
handler();
|
||||
this.off(event, wrapper);
|
||||
};
|
||||
this.listeners[event].add(wrapper);
|
||||
}
|
||||
on(event, handler) {
|
||||
if (this.isInValid(event, handler)) return;
|
||||
if (!this.listeners[event]) this.listeners[event] = /* @__PURE__ */ new Set();
|
||||
this.listeners[event].add(handler);
|
||||
return () => this.off(event, handler);
|
||||
}
|
||||
off(event, handler) {
|
||||
if (this.isInValid(event, handler)) return;
|
||||
if (!this.listeners[event]) return;
|
||||
this.listeners[event].delete(handler);
|
||||
if (this.listeners[event].size !== 0) return;
|
||||
delete this.listeners[event];
|
||||
}
|
||||
emit(event, ...payload) {
|
||||
if (!this.listeners[event]) return;
|
||||
for (const listener of this.listeners[event]) {
|
||||
try {
|
||||
listener.apply(null, payload);
|
||||
} catch (err) {
|
||||
Logger_default.error(`Could not run listener for ${event}`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// common/Utils/Plugin.js
|
||||
var Events = {
|
||||
START: "START",
|
||||
STOP: "STOP"
|
||||
};
|
||||
var Plugin_default = new class extends EventEmitter_default {
|
||||
start() {
|
||||
this.emit(Events.START);
|
||||
}
|
||||
stop() {
|
||||
this.emit(Events.STOP);
|
||||
}
|
||||
}();
|
||||
|
||||
// common/Utils/StylesLoader.js
|
||||
var styleLoader = {
|
||||
_styles: [],
|
||||
push(styles) {
|
||||
this._styles.push(styles);
|
||||
}
|
||||
};
|
||||
Plugin_default.on(Events.START, () => {
|
||||
DOM.addStyle(styleLoader._styles.join("\n"));
|
||||
});
|
||||
Plugin_default.on(Events.STOP, () => {
|
||||
DOM.removeStyle();
|
||||
});
|
||||
var StylesLoader_default = styleLoader;
|
||||
|
||||
// src/StickerEmojiPreview/styles.css
|
||||
StylesLoader_default.push(`.stickersPreview {
|
||||
width: 400px;
|
||||
font-size: 14px;
|
||||
background: oklab(0.278867 0.00249027 -0.00875303);
|
||||
border-radius: 5px;
|
||||
padding: 0.5em;
|
||||
box-shadow: var(--elevation-high);
|
||||
}
|
||||
|
||||
.stickersPreview img {
|
||||
min-width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.animated img {
|
||||
border: 1px dashed #ff8f09;
|
||||
padding: 1px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
`);
|
||||
|
||||
// common/React.jsx
|
||||
var useRef = /* @__PURE__ */ (() => React.useRef)();
|
||||
var React_default = /* @__PURE__ */ (() => React)();
|
||||
|
||||
// common/Webpack.js
|
||||
var getModule = /* @__PURE__ */ (() => Webpack.getModule)();
|
||||
var Filters = /* @__PURE__ */ (() => Webpack.Filters)();
|
||||
var getMangled = /* @__PURE__ */ (() => Webpack.getMangled)();
|
||||
|
||||
function getModuleAndKey(filter, options) {
|
||||
let module2;
|
||||
const target = getModule((entry, m) => filter(entry) ? module2 = m : false, options);
|
||||
module2 = module2?.exports;
|
||||
if (!module2) return;
|
||||
const key = Object.keys(module2).find((k) => module2[k] === target);
|
||||
if (!key) return;
|
||||
return { module: module2, key };
|
||||
}
|
||||
|
||||
// MODULES-AUTO-LOADER:@Patch/CloseExpressionPicker
|
||||
var CloseExpressionPicker_default = getModuleAndKey(Filters.byStrings("activeView:null,activeViewType:null"), { searchExports: true }) || {};
|
||||
|
||||
// common/DiscordModules/zustand.js
|
||||
var { zustand } = getMangled(Filters.bySource("useSyncExternalStoreWithSelector", "useDebugValue", "subscribe"), {
|
||||
_: Filters.byStrings("subscribe"),
|
||||
zustand: () => true
|
||||
});
|
||||
var subscribeWithSelector = getModule(Filters.byStrings("getState", "equalityFn", "fireImmediately"), { searchExports: true });
|
||||
|
||||
function create(initialState) {
|
||||
const Store = zustand(initialState);
|
||||
Object.defineProperty(Store, "state", {
|
||||
configurable: false,
|
||||
get: () => Store.getState()
|
||||
});
|
||||
return Store;
|
||||
}
|
||||
|
||||
// common/Utils/index.js
|
||||
var nop = () => {};
|
||||
|
||||
// common/Utils/Settings.js
|
||||
var SettingsStore = create(subscribeWithSelector(() => Object.assign(Config_default.settings, Data.load("settings") || {})));
|
||||
((state) => {
|
||||
const selectors = {};
|
||||
const actions = {};
|
||||
for (const [key, value] of Object.entries(state)) {
|
||||
actions[`set${key}`] = (newValue) => SettingsStore.setState({
|
||||
[key]: newValue });
|
||||
selectors[key] = (state2) => state2[key];
|
||||
}
|
||||
Object.defineProperty(SettingsStore, "selectors", { value: Object.assign(selectors) });
|
||||
Object.assign(SettingsStore, actions);
|
||||
})(SettingsStore.getInitialState());
|
||||
SettingsStore.subscribe(
|
||||
(state) => state,
|
||||
() => Data.save("settings", SettingsStore.state)
|
||||
);
|
||||
Object.assign(SettingsStore, {
|
||||
useSetting: (key) => {
|
||||
const val = SettingsStore((state) => state[key]);
|
||||
return [val, SettingsStore[`set${key}`]];
|
||||
}
|
||||
});
|
||||
var Settings_default = SettingsStore;
|
||||
|
||||
// src/StickerEmojiPreview/patches/patchCloseExpressionPicker.js
|
||||
Plugin_default.on(Events.START, () => {
|
||||
const { module: module2, key } = CloseExpressionPicker_default;
|
||||
if (!module2 || !key) return Logger_default.patchError("CloseExpressionPicker");
|
||||
const unpatch = Patcher.after(module2, key, (_, args, ret) => {
|
||||
Settings_default.setpreviewState(Settings_default.state.previewDefaultState);
|
||||
});
|
||||
Plugin_default.once(Events.STOP, unpatch);
|
||||
});
|
||||
|
||||
// MODULES-AUTO-LOADER:@Patch/ExpressionPickerInspector
|
||||
var ExpressionPickerInspector_default = getModuleAndKey(Filters.byStrings("graphicPrimary", "titlePrimary"), { searchExports: false }) || {};
|
||||
|
||||
// common/DiscordModules/Modules.js
|
||||
var DiscordPopout = /* @__PURE__ */ (() => getModule((a) => a?.prototype?.render && a.Animation, { searchExports: true }))();
|
||||
|
||||
// src/StickerEmojiPreview/Constants.js
|
||||
var PREVIEW_SIZE = 300;
|
||||
var PREVIEW_UNAVAILABLE = `data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="rgb(202 204 206)" d="M12 2C6.477 2 2 6.477 2 12C2 17.522 6.477 22 12 22C17.523 22 22 17.522 22 12C22 6.477 17.523 2 12 2ZM8 6C9.104 6 10 6.896 10 8C10 9.105 9.104 10 8 10C6.896 10 6 9.105 6 8C6 6.896 6.896 6 8 6ZM18 14C18 16.617 15.14 19 12 19C8.86 19 6 16.617 6 14V13H18V14ZM16 10C14.896 10 14 9.105 14 8C14 6.896 14.896 6 16 6C17.104 6 18 6.896 18 8C18 9.105 17.104 10 16 10Z"></path></svg>`;
|
||||
|
||||
// src/StickerEmojiPreview/components/PreviewComponent.jsx
|
||||
var PreviewComponent_default = ({ target, previewComponent }) => {
|
||||
const [show, setShow] = Settings_default.useSetting("previewState");
|
||||
const ref = useRef();
|
||||
React_default.useEffect(() => {
|
||||
function keyupHandler(e) {
|
||||
if (e.key === "Control") {
|
||||
setShow(!show);
|
||||
}
|
||||
}
|
||||
document.addEventListener("keyup", keyupHandler);
|
||||
return () => document.removeEventListener("keyup", keyupHandler);
|
||||
}, [show]);
|
||||
return /* @__PURE__ */ React_default.createElement(
|
||||
DiscordPopout, {
|
||||
renderPopout: () => /* @__PURE__ */ React_default.createElement(
|
||||
"div", {
|
||||
className: "stickersPreview",
|
||||
style: { width: `${PREVIEW_SIZE}px` }
|
||||
},
|
||||
previewComponent
|
||||
),
|
||||
targetElementRef: ref,
|
||||
shouldShow: show,
|
||||
position: "left",
|
||||
align: "bottom",
|
||||
animation: "1",
|
||||
spacing: 60
|
||||
},
|
||||
() => React_default.cloneElement(target, { ref })
|
||||
);
|
||||
};
|
||||
|
||||
// common/Components/ErrorBoundary/index.jsx
|
||||
var ErrorBoundary = class extends React_default.Component {
|
||||
state = { hasError: false, error: null, info: null };
|
||||
componentDidCatch(error, info) {
|
||||
this.setState({ error, info, hasError: true });
|
||||
const errorMessage = `
|
||||
${error?.message || ""}${(info?.componentStack || "").split("\n").slice(0, 20).join("\n")}`;
|
||||
console.error(`%c[${Config_default?.info?.name || "Unknown Plugin"}] %cthrew an exception at %c[${this.props.id}]
|
||||
`, "color: #3a71c1;font-weight: bold;", "", "color: red;font-weight: bold;", errorMessage);
|
||||
}
|
||||
renderErrorBoundary() {
|
||||
return /* @__PURE__ */ React_default.createElement("div", { style: { background: "#292c2c", padding: "20px", borderRadius: "10px" } }, /* @__PURE__ */ React_default.createElement("b", { style: { color: "#e0e1e5" } }, "An error has occured while rendering ", /* @__PURE__ */ React_default.createElement("span", { style: { color: "orange" } }, this.props.id)));
|
||||
}
|
||||
renderFallback() {
|
||||
if (React_default.isValidElement(this.props.fallback)) {
|
||||
if (this.props.passMetaProps)
|
||||
this.props.fallback.props = {
|
||||
id: this.props.id,
|
||||
plugin: Config_default?.info?.name || "Unknown Plugin",
|
||||
...this.props.fallback.props
|
||||
};
|
||||
return this.props.fallback;
|
||||
}
|
||||
return /* @__PURE__ */ React_default.createElement(
|
||||
this.props.fallback, {
|
||||
id: this.props.id,
|
||||
plugin: Config_default?.info?.name || "Unknown Plugin"
|
||||
}
|
||||
);
|
||||
}
|
||||
render() {
|
||||
if (!this.state.hasError) return this.props.children;
|
||||
return this.props.fallback ? this.renderFallback() : this.renderErrorBoundary();
|
||||
}
|
||||
};
|
||||
|
||||
// src/StickerEmojiPreview/patches/patchPickerInspector.jsx
|
||||
function getMediaInfo({ props, type }) {
|
||||
if (props.sticker) return [type, props];
|
||||
if (props.src) return [type, { src: props.src.replace(/([?&]size=)(\d+)/, `$1${PREVIEW_SIZE}`) || PREVIEW_UNAVAILABLE }];
|
||||
return ["img", null];
|
||||
}
|
||||
|
||||
function getPreviewComponent(graphicPrimary) {
|
||||
const [TypeComponent, props] = getMediaInfo(graphicPrimary);
|
||||
return /* @__PURE__ */ React.createElement(
|
||||
TypeComponent, {
|
||||
...props,
|
||||
disableAnimation: false,
|
||||
size: PREVIEW_SIZE
|
||||
}
|
||||
);
|
||||
}
|
||||
Plugin_default.on(Events.START, () => {
|
||||
const { module: module2, key } = ExpressionPickerInspector_default;
|
||||
if (!module2 || !key) return Logger_default.patchError("ExpressionPickerInspector");
|
||||
const unpatch = Patcher.after(module2, key, (_, [{ graphicPrimary, titlePrimary }], ret) => {
|
||||
if (titlePrimary?.toLowerCase().includes("upload")) return;
|
||||
return /* @__PURE__ */ React.createElement(
|
||||
ErrorBoundary, {
|
||||
id: "PreviewComponent",
|
||||
plugin: Config_default.info.name,
|
||||
fallback: ret
|
||||
},
|
||||
/* @__PURE__ */
|
||||
React.createElement(
|
||||
PreviewComponent_default, {
|
||||
target: ret,
|
||||
previewComponent: getPreviewComponent(graphicPrimary)
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
Plugin_default.once(Events.STOP, unpatch);
|
||||
});
|
||||
|
||||
// MODULES-AUTO-LOADER:@Modules/FormSwitch
|
||||
var FormSwitch_default = getModule(Filters.byStrings("note", "tooltipNote"), { searchExports: true });
|
||||
|
||||
// common/Components/Switch/index.jsx
|
||||
var Switch_default = getModule(Filters.byStrings('"data-toggleable-component":"switch"', 'layout:"horizontal"'), { searchExports: true }) || function SwitchComponentFallback(props) {
|
||||
return /* @__PURE__ */ React.createElement("div", { style: { color: "#fff" } }, props.children, /* @__PURE__ */ React.createElement(
|
||||
"input", {
|
||||
type: "checkbox",
|
||||
checked: props.value,
|
||||
onChange: (e) => props.onChange(e.target.checked)
|
||||
}
|
||||
));
|
||||
};
|
||||
|
||||
// common/Components/SettingSwtich/index.jsx
|
||||
function SettingSwtich({ settingKey, note, onChange = nop, description, ...rest }) {
|
||||
const [val, set] = Settings_default.useSetting(settingKey);
|
||||
return /* @__PURE__ */ React.createElement(
|
||||
Switch_default, {
|
||||
...rest,
|
||||
checked: val,
|
||||
label: description || settingKey,
|
||||
description: note,
|
||||
onChange: (e) => {
|
||||
set(e);
|
||||
onChange(e);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// src/StickerEmojiPreview/components/SettingComponent.jsx
|
||||
function SettingComponent() {
|
||||
return [{
|
||||
settingKey: "previewDefaultState",
|
||||
description: "Preview open by default.",
|
||||
onChange() {
|
||||
Settings_default.setpreviewState(Settings_default.state.previewDefaultState);
|
||||
}
|
||||
}].map(SettingSwtich);
|
||||
}
|
||||
|
||||
// src/StickerEmojiPreview/index.jsx
|
||||
Plugin_default.getSettingsPanel = () => /* @__PURE__ */ React_default.createElement(SettingComponent, null);
|
||||
module.exports = () => Plugin_default;
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"all": {
|
||||
"cached": "1 3 16 18 22 23 32 33 39 40 41 45 46 47 48 49 52 53 56 112 124 125 142 144 147 153 155 156 161 166 172 174 177 204 205 209 218 226 252 256 257 286 296 308 320 342 359 371 385 412 422 439 468 483 507 508 515 541 553 572 576 580 581 597 601 607 613 636 637 641 642 643 653 659 662 664 695 712 713 714 722 734 735 736 746 752 753 770 813 823 858 865 866 894 915 922 928 929 933 973 1006 1008 1014 1030 1033 1098 1125 1128 1138 1143 1152 1183 1221",
|
||||
"filters": {
|
||||
"updated": true,
|
||||
"outdated": true,
|
||||
"downloadable": true
|
||||
},
|
||||
"general": {
|
||||
"notifyOutdated": true,
|
||||
"notifyNewEntries": true,
|
||||
"startDownloaded": false,
|
||||
"startUpdated": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"all": {
|
||||
"choices": {
|
||||
"received": {
|
||||
"input": "auto",
|
||||
"output": "$discord"
|
||||
},
|
||||
"sent": {
|
||||
"input": "auto",
|
||||
"output": "$discord"
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"translator": "googleapi",
|
||||
"backup": "----"
|
||||
},
|
||||
"exceptions": {
|
||||
"wordStart": [
|
||||
"!"
|
||||
]
|
||||
},
|
||||
"general": {
|
||||
"addTranslateButton": true,
|
||||
"addQuickTranslateButton": true,
|
||||
"usePerChatTranslation": true,
|
||||
"sendOriginalMessage": false,
|
||||
"showOriginalMessage": false,
|
||||
"useSpoilerInOriginal": false
|
||||
},
|
||||
"prefixes": {
|
||||
"translationPrefixData": [
|
||||
{
|
||||
"prefix": "$fr",
|
||||
"language": "fr"
|
||||
},
|
||||
{
|
||||
"prefix": "$de",
|
||||
"language": "de"
|
||||
},
|
||||
{
|
||||
"prefix": "$es",
|
||||
"language": "es"
|
||||
},
|
||||
{
|
||||
"prefix": "$jp",
|
||||
"language": "ja"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"settings": {
|
||||
"showOnHover": true,
|
||||
"bannerColor": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,895 @@
|
||||
/**
|
||||
* @name ViewProfilePicture
|
||||
* @description Adds a button to the user popout and profile that allows you to view the Avatar and banner.
|
||||
* @version 1.3.7
|
||||
* @author Skamt
|
||||
* @website https://github.com/Skamt/BDAddons/tree/main/ViewProfilePicture
|
||||
* @source https://raw.githubusercontent.com/Skamt/BDAddons/main/ViewProfilePicture/ViewProfilePicture.plugin.js
|
||||
*/
|
||||
|
||||
// config:@Config
|
||||
var Config_default = {
|
||||
"info": {
|
||||
"name": "ViewProfilePicture",
|
||||
"version": "1.3.7",
|
||||
"description": "Adds a button to the user popout and profile that allows you to view the Avatar and banner.",
|
||||
"source": "https://raw.githubusercontent.com/Skamt/BDAddons/main/ViewProfilePicture/ViewProfilePicture.plugin.js",
|
||||
"github": "https://github.com/Skamt/BDAddons/tree/main/ViewProfilePicture",
|
||||
"authors": [{
|
||||
"name": "Skamt"
|
||||
}]
|
||||
},
|
||||
"settings": {
|
||||
"showOnHover": false,
|
||||
"bannerColor": false
|
||||
}
|
||||
};
|
||||
|
||||
// common/Api.js
|
||||
var Api = new BdApi(Config_default.info.name);
|
||||
var UI = /* @__PURE__ */ (() => Api.UI)();
|
||||
var DOM = /* @__PURE__ */ (() => Api.DOM)();
|
||||
var Data = /* @__PURE__ */ (() => Api.Data)();
|
||||
var React = /* @__PURE__ */ (() => Api.React)();
|
||||
var Patcher = /* @__PURE__ */ (() => Api.Patcher)();
|
||||
var Logger = /* @__PURE__ */ (() => Api.Logger)();
|
||||
var Webpack = /* @__PURE__ */ (() => Api.Webpack)();
|
||||
var findInTree = /* @__PURE__ */ (() => Api.Utils.findInTree)();
|
||||
|
||||
// common/Utils/Logger.js
|
||||
Logger.patchError = (patchId) => {
|
||||
console.error(`%c[${Config_default.info.name}] %cCould not find module for %c[${patchId}]`, "color: #3a71c1;font-weight: bold;", "", "color: red;font-weight: bold;");
|
||||
};
|
||||
var Logger_default = Logger;
|
||||
|
||||
// common/Utils/EventEmitter.js
|
||||
var EventEmitter_default = class {
|
||||
constructor() {
|
||||
this.listeners = {};
|
||||
}
|
||||
isInValid(event, handler) {
|
||||
return typeof event !== "string" || typeof handler !== "function";
|
||||
}
|
||||
once(event, handler) {
|
||||
if (this.isInValid(event, handler)) return;
|
||||
if (!this.listeners[event]) this.listeners[event] = /* @__PURE__ */ new Set();
|
||||
const wrapper = () => {
|
||||
handler();
|
||||
this.off(event, wrapper);
|
||||
};
|
||||
this.listeners[event].add(wrapper);
|
||||
}
|
||||
on(event, handler) {
|
||||
if (this.isInValid(event, handler)) return;
|
||||
if (!this.listeners[event]) this.listeners[event] = /* @__PURE__ */ new Set();
|
||||
this.listeners[event].add(handler);
|
||||
return () => this.off(event, handler);
|
||||
}
|
||||
off(event, handler) {
|
||||
if (this.isInValid(event, handler)) return;
|
||||
if (!this.listeners[event]) return;
|
||||
this.listeners[event].delete(handler);
|
||||
if (this.listeners[event].size !== 0) return;
|
||||
delete this.listeners[event];
|
||||
}
|
||||
emit(event, ...payload) {
|
||||
if (!this.listeners[event]) return;
|
||||
for (const listener of this.listeners[event]) {
|
||||
try {
|
||||
listener.apply(null, payload);
|
||||
} catch (err) {
|
||||
Logger_default.error(`Could not run listener for ${event}`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// common/Utils/Plugin.js
|
||||
var Events = {
|
||||
START: "START",
|
||||
STOP: "STOP"
|
||||
};
|
||||
var Plugin_default = new class extends EventEmitter_default {
|
||||
start() {
|
||||
this.emit(Events.START);
|
||||
}
|
||||
stop() {
|
||||
this.emit(Events.STOP);
|
||||
}
|
||||
}();
|
||||
|
||||
// common/Utils/StylesLoader.js
|
||||
var styleLoader = {
|
||||
_styles: [],
|
||||
push(styles) {
|
||||
this._styles.push(styles);
|
||||
}
|
||||
};
|
||||
Plugin_default.on(Events.START, () => {
|
||||
DOM.addStyle(styleLoader._styles.join("\n"));
|
||||
});
|
||||
Plugin_default.on(Events.STOP, () => {
|
||||
DOM.removeStyle();
|
||||
});
|
||||
var StylesLoader_default = styleLoader;
|
||||
|
||||
// src/ViewProfilePicture/styles.css
|
||||
StylesLoader_default.push(`/* View Profile Button */
|
||||
.VPP-Button {
|
||||
background: rgb(1 0 1 / 54%);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.VPP-float {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
z-index: 987;
|
||||
}
|
||||
|
||||
.VPP-Button svg {
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
/* Bigger icon on profile */
|
||||
.VPP-settings svg,
|
||||
.VPP-profile svg {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.VPP-Button:hover {
|
||||
background: rgb(1 0 1 / 64%);
|
||||
}
|
||||
|
||||
/* div replacement if No banner */
|
||||
.VPP-NoBanner {
|
||||
width: 70vw;
|
||||
height: 50vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Carousel Modal */
|
||||
.VPP-carousel-modal {
|
||||
background: #0000;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.VPP-carousel {
|
||||
position: static;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.VPP-carousel > div[role="button"] {
|
||||
margin: 0 15px;
|
||||
background: var(--background-surface-high);
|
||||
color: var(--interactive-text-default);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.VPP-carousel > div[role="button"]:hover {
|
||||
background: var(--background-surface-highest);
|
||||
color: var(--interactive-text-default);
|
||||
}
|
||||
|
||||
/* Copy color button */
|
||||
.VPP-copy-color-container {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.VPP-copy-color-label,
|
||||
.VPP-copy-color {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
line-height: 30px;
|
||||
transition: opacity 0.15s ease;
|
||||
opacity: 0.5;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.VPP-copy-color:hover {
|
||||
opacity: 1;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.VPP-separator {
|
||||
line-height: 30px;
|
||||
opacity: 0.5;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.VPP-copy-color-label {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.VPP-hover {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.VPP-container:hover .VPP-hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.VPP-colorFormat-options {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.VPP-colorFormat-options > div {
|
||||
flex: 1;
|
||||
}
|
||||
`);
|
||||
|
||||
// common/Utils/index.js
|
||||
function fit({ width, height, gap = 0.8 }) {
|
||||
const ratio = Math.min(innerWidth / width, innerHeight / height);
|
||||
width = Math.round(width * ratio);
|
||||
height = Math.round(height * ratio);
|
||||
return {
|
||||
width,
|
||||
height,
|
||||
maxHeight: height * gap,
|
||||
maxWidth: width * gap
|
||||
};
|
||||
}
|
||||
|
||||
function concateClassNames(...args) {
|
||||
return args.filter(Boolean).join(" ");
|
||||
}
|
||||
var promiseHandler = (promise) => promise.then((data) => [void 0, data]).catch((err) => [err]);
|
||||
|
||||
function copy(data) {
|
||||
DiscordNative.clipboard.copy(data);
|
||||
}
|
||||
|
||||
function getNestedProp(obj, path) {
|
||||
return path.split(".").reduce((ob, prop) => ob?.[prop], obj);
|
||||
}
|
||||
var nop = () => {};
|
||||
|
||||
function getImageDimensions(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.onload = () => resolve({
|
||||
width: img.width,
|
||||
height: img.height
|
||||
});
|
||||
img.onerror = reject;
|
||||
img.src = url;
|
||||
});
|
||||
}
|
||||
|
||||
// common/React.jsx
|
||||
var useState = /* @__PURE__ */ (() => React.useState)();
|
||||
var useMemo = /* @__PURE__ */ (() => React.useMemo)();
|
||||
var React_default = /* @__PURE__ */ (() => React)();
|
||||
|
||||
// common/Components/ErrorBoundary/index.jsx
|
||||
var ErrorBoundary = class extends React_default.Component {
|
||||
state = { hasError: false, error: null, info: null };
|
||||
componentDidCatch(error, info) {
|
||||
this.setState({ error, info, hasError: true });
|
||||
const errorMessage = `
|
||||
${error?.message || ""}${(info?.componentStack || "").split("\n").slice(0, 20).join("\n")}`;
|
||||
console.error(`%c[${Config_default?.info?.name || "Unknown Plugin"}] %cthrew an exception at %c[${this.props.id}]
|
||||
`, "color: #3a71c1;font-weight: bold;", "", "color: red;font-weight: bold;", errorMessage);
|
||||
}
|
||||
renderErrorBoundary() {
|
||||
return /* @__PURE__ */ React_default.createElement("div", { style: { background: "#292c2c", padding: "20px", borderRadius: "10px" } }, /* @__PURE__ */ React_default.createElement("b", { style: { color: "#e0e1e5" } }, "An error has occured while rendering ", /* @__PURE__ */ React_default.createElement("span", { style: { color: "orange" } }, this.props.id)));
|
||||
}
|
||||
renderFallback() {
|
||||
if (React_default.isValidElement(this.props.fallback)) {
|
||||
if (this.props.passMetaProps)
|
||||
this.props.fallback.props = {
|
||||
id: this.props.id,
|
||||
plugin: Config_default?.info?.name || "Unknown Plugin",
|
||||
...this.props.fallback.props
|
||||
};
|
||||
return this.props.fallback;
|
||||
}
|
||||
return /* @__PURE__ */ React_default.createElement(
|
||||
this.props.fallback, {
|
||||
id: this.props.id,
|
||||
plugin: Config_default?.info?.name || "Unknown Plugin"
|
||||
}
|
||||
);
|
||||
}
|
||||
render() {
|
||||
if (!this.state.hasError) return this.props.children;
|
||||
return this.props.fallback ? this.renderFallback() : this.renderErrorBoundary();
|
||||
}
|
||||
};
|
||||
|
||||
// common/Components/icons/ErrorIcon/index.jsx
|
||||
var ErrorIcon_default = (props) => /* @__PURE__ */ React.createElement("div", { ...props }, /* @__PURE__ */ React.createElement(
|
||||
"svg", {
|
||||
xmlns: "http://www.w3.org/2000/svg",
|
||||
viewBox: "0 0 24 24",
|
||||
fill: "red",
|
||||
width: "18",
|
||||
height: "18"
|
||||
},
|
||||
/* @__PURE__ */
|
||||
React.createElement(
|
||||
"path", {
|
||||
d: "M0 0h24v24H0z",
|
||||
fill: "none"
|
||||
}
|
||||
),
|
||||
/* @__PURE__ */
|
||||
React.createElement("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" })
|
||||
));
|
||||
|
||||
// common/Webpack.js
|
||||
var getModule = /* @__PURE__ */ (() => Webpack.getModule)();
|
||||
var Filters = /* @__PURE__ */ (() => Webpack.Filters)();
|
||||
var getMangled = /* @__PURE__ */ (() => Webpack.getMangled)();
|
||||
var getStore = /* @__PURE__ */ (() => Webpack.getStore)();
|
||||
|
||||
function reactRefMemoFilter(type, ...args) {
|
||||
const filter = Filters.byStrings(...args);
|
||||
return (target) => target[type] && filter(target[type]);
|
||||
}
|
||||
|
||||
// common/DiscordModules/zustand.js
|
||||
var { zustand } = getMangled(Filters.bySource("useSyncExternalStoreWithSelector", "useDebugValue", "subscribe"), {
|
||||
_: Filters.byStrings("subscribe"),
|
||||
zustand: () => true
|
||||
});
|
||||
var subscribeWithSelector = getModule(Filters.byStrings("getState", "equalityFn", "fireImmediately"), { searchExports: true });
|
||||
|
||||
function create(initialState) {
|
||||
const Store = zustand(initialState);
|
||||
Object.defineProperty(Store, "state", {
|
||||
configurable: false,
|
||||
get: () => Store.getState()
|
||||
});
|
||||
return Store;
|
||||
}
|
||||
|
||||
// common/Utils/Settings.js
|
||||
var SettingsStore = create(subscribeWithSelector(() => Object.assign(Config_default.settings, Data.load("settings") || {})));
|
||||
((state) => {
|
||||
const selectors = {};
|
||||
const actions = {};
|
||||
for (const [key, value] of Object.entries(state)) {
|
||||
actions[`set${key}`] = (newValue) => SettingsStore.setState({
|
||||
[key]: newValue });
|
||||
selectors[key] = (state2) => state2[key];
|
||||
}
|
||||
Object.defineProperty(SettingsStore, "selectors", { value: Object.assign(selectors) });
|
||||
Object.assign(SettingsStore, actions);
|
||||
})(SettingsStore.getInitialState());
|
||||
SettingsStore.subscribe(
|
||||
(state) => state,
|
||||
() => Data.save("settings", SettingsStore.state)
|
||||
);
|
||||
Object.assign(SettingsStore, {
|
||||
useSetting: (key) => {
|
||||
const val = SettingsStore((state) => state[key]);
|
||||
return [val, SettingsStore[`set${key}`]];
|
||||
}
|
||||
});
|
||||
var Settings_default = SettingsStore;
|
||||
|
||||
// common/Utils/Modals/styles.css
|
||||
StylesLoader_default.push(`.transparent-background.transparent-background{
|
||||
background: transparent;
|
||||
border:unset;
|
||||
}`);
|
||||
|
||||
// common/Utils/Modals/index.jsx
|
||||
var ModalActions = getModule((a) => a.useModalsStore);
|
||||
var Modals = /* @__PURE__ */ getMangled( /* @__PURE__ */ Filters.bySource("MODAL_ROOT", "transitionState"), {
|
||||
ModalRoot: /* @__PURE__ */ Filters.byStrings("transitionState"),
|
||||
ModalFooter: /* @__PURE__ */ Filters.byStrings(".HORIZONTAL_REVERSE"),
|
||||
ModalContent: /* @__PURE__ */ Filters.byStrings("scrollbarType", "scrollerRef"),
|
||||
ModalHeader: /* @__PURE__ */ Filters.byStrings("headerIdIsManaged", "headerId", ".HORIZONTAL"),
|
||||
Animations: (a) => a.SUBTLE,
|
||||
Sizes: (a) => a.DYNAMIC,
|
||||
ModalCloseButton: Filters.byStrings("withCircleBackground")
|
||||
});
|
||||
var openModal = (children, tag, { className, ...modalRootProps } = {}) => {
|
||||
const id = `${tag ? `${tag}-` : ""}modal`;
|
||||
return ModalActions.openModal((props) => {
|
||||
return /* @__PURE__ */ React.createElement(
|
||||
ErrorBoundary, {
|
||||
id,
|
||||
plugin: Config_default.info.name
|
||||
},
|
||||
/* @__PURE__ */
|
||||
React.createElement(
|
||||
Modals.ModalRoot, {
|
||||
onClick: props.onClose,
|
||||
transitionState: props.transitionState,
|
||||
className: concateClassNames("transparent-background", className),
|
||||
size: Modals.Sizes.DYNAMIC,
|
||||
...modalRootProps
|
||||
},
|
||||
React.cloneElement(children, { ...props })
|
||||
)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// MODULES-AUTO-LOADER:@Modules/Tooltip
|
||||
var Tooltip_default = getModule(Filters.byPrototypeKeys("renderTooltip"), { searchExports: true });
|
||||
|
||||
// common/Components/Tooltip/index.jsx
|
||||
var Tooltip_default2 = ({ note, position, children }) => {
|
||||
return /* @__PURE__ */ React.createElement(
|
||||
Tooltip_default, {
|
||||
text: note,
|
||||
position: position || "top"
|
||||
},
|
||||
(props) => React.cloneElement(children, {
|
||||
...props,
|
||||
...children.props
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
// common/Components/icons/ImageIcon/index.jsx
|
||||
function ImageIcon(props) {
|
||||
return /* @__PURE__ */ React.createElement(
|
||||
"svg", {
|
||||
fill: "currentColor",
|
||||
width: "24",
|
||||
height: "24",
|
||||
viewBox: "-50 -50 484 484",
|
||||
...props
|
||||
},
|
||||
/* @__PURE__ */
|
||||
React.createElement("path", { d: "M341.333,0H42.667C19.093,0,0,19.093,0,42.667v298.667C0,364.907,19.093,384,42.667,384h298.667 C364.907,384,384,364.907,384,341.333V42.667C384,19.093,364.907,0,341.333,0z M42.667,320l74.667-96l53.333,64.107L245.333,192l96,128H42.667z" })
|
||||
);
|
||||
}
|
||||
|
||||
// common/Utils/ImageModal/styles.css
|
||||
StylesLoader_default.push(`.downloadLink {
|
||||
color: white !important;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
/* line-height: 18px;*/
|
||||
text-decoration: none;
|
||||
transition: opacity.15s ease;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.imageModalwrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.imageModalOptions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
}
|
||||
`);
|
||||
|
||||
// MODULES-AUTO-LOADER:@Stores/AccessibilityStore
|
||||
var AccessibilityStore_default = getStore("AccessibilityStore");
|
||||
|
||||
// common/Utils/ImageModal/index.jsx
|
||||
var RenderLinkComponent = getModule((m) => m.type?.toString?.().includes("MASKED_LINK"), { searchExports: false });
|
||||
var ImageModal = getModule(reactRefMemoFilter("type", "renderLinkComponent"), { searchExports: true });
|
||||
|
||||
function h(e, t) {
|
||||
let n = arguments.length > 2 && void 0 !== arguments[2] && arguments[2];
|
||||
true === n || AccessibilityStore_default.useReducedMotion ? e.set(t) : e.start(t);
|
||||
}
|
||||
var useSomeScalingHook = getModule(Filters.byStrings("reducedMotion.enabled", "useSpring", "respect-motion-settings"), { searchExports: true });
|
||||
var context = getModule((a) => a?._currentValue?.scale, { searchExports: true });
|
||||
var ImageComponent = ({ url, ...rest }) => {
|
||||
const [x, P] = useState(false);
|
||||
const [M, w] = useSomeScalingHook(() => ({
|
||||
scale: AccessibilityStore_default.useReducedMotion ? 1 : 0.9,
|
||||
x: 0,
|
||||
y: 0,
|
||||
config: {
|
||||
friction: 30,
|
||||
tension: 300
|
||||
}
|
||||
}));
|
||||
const contextVal = useMemo(
|
||||
() => ({
|
||||
scale: M.scale,
|
||||
x: M.x,
|
||||
y: M.y,
|
||||
setScale(e, t) {
|
||||
h(M.scale, e, null == t ? void 0 : t.immediate);
|
||||
},
|
||||
setOffset(e, t, n) {
|
||||
h(M.x, e, null == n ? void 0 : n.immediate), h(M.y, t, null == n ? void 0 : n.immediate);
|
||||
},
|
||||
zoomed: x,
|
||||
setZoomed(e) {
|
||||
P(e), h(M.scale, e ? 2.5 : 1), e || (h(M.x, 0), h(M.y, 0));
|
||||
}
|
||||
}),
|
||||
[x, M]
|
||||
);
|
||||
return /* @__PURE__ */ React_default.createElement(context.Provider, { value: contextVal }, /* @__PURE__ */ React_default.createElement("div", { className: "imageModalwrapper" }, /* @__PURE__ */ React_default.createElement(
|
||||
ImageModal, {
|
||||
maxWidth: rest.maxWidth,
|
||||
maxHeight: rest.maxHeight,
|
||||
media: {
|
||||
...rest,
|
||||
type: "IMAGE",
|
||||
url,
|
||||
proxyUrl: url
|
||||
}
|
||||
}
|
||||
), !x && /* @__PURE__ */ React_default.createElement("div", { className: "imageModalOptions" }, /* @__PURE__ */ React_default.createElement(
|
||||
RenderLinkComponent, {
|
||||
className: "downloadLink",
|
||||
href: url
|
||||
},
|
||||
"Open in Browser"
|
||||
))));
|
||||
};
|
||||
|
||||
// MODULES-AUTO-LOADER:@Modules/Color
|
||||
var Color_default = getModule(Filters.byKeys("Color", "hex", "hsl"), { searchExports: false });
|
||||
|
||||
// MODULES-AUTO-LOADER:@Stores/ThemeStore
|
||||
var ThemeStore_default = getStore("ThemeStore");
|
||||
|
||||
// common/Utils/Toast.js
|
||||
function showToast(content, type) {
|
||||
UI.showToast(`[${Config_default.info.name}] ${content}`, { timeout: 5e3, type });
|
||||
}
|
||||
var Toast_default = {
|
||||
success(content) {
|
||||
showToast(content, "success");
|
||||
},
|
||||
info(content) {
|
||||
showToast(content, "info");
|
||||
},
|
||||
warning(content) {
|
||||
showToast(content, "warning");
|
||||
},
|
||||
error(content) {
|
||||
showToast(content, "error");
|
||||
}
|
||||
};
|
||||
|
||||
// src/ViewProfilePicture/components/ColorModalComponent.jsx
|
||||
var DesignSystem = getModule((a) => a?.unsafe_rawColors?.PRIMARY_800?.resolve);
|
||||
|
||||
function resolveColor() {
|
||||
if (!DesignSystem?.unsafe_rawColors?.PRIMARY_800) return "#111214";
|
||||
return DesignSystem.unsafe_rawColors?.PRIMARY_800.resolve({
|
||||
theme: ThemeStore_default.theme,
|
||||
saturation: AccessibilityStore_default.saturation
|
||||
}).hex();
|
||||
}
|
||||
|
||||
function copyColor(type, color) {
|
||||
let c3 = color;
|
||||
try {
|
||||
switch (type) {
|
||||
case "hex":
|
||||
c3 = Color_default(color).hex();
|
||||
break;
|
||||
case "rgba":
|
||||
c3 = Color_default(color).css("rgba");
|
||||
break;
|
||||
case "hsla":
|
||||
c3 = Color_default(color).css("hsla");
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
copy(c3);
|
||||
Toast_default.success(`${c3} Copied!`);
|
||||
}
|
||||
}
|
||||
|
||||
function SimpleColorModal({ color }) {
|
||||
return /* @__PURE__ */ React_default.createElement(
|
||||
"div", {
|
||||
onClick: (e) => e.stopPropagation(),
|
||||
className: "VPP-NoBanner",
|
||||
style: { backgroundColor: Color_default(color).css() }
|
||||
},
|
||||
/* @__PURE__ */
|
||||
React_default.createElement("div", { className: "VPP-copy-color-container" }, /* @__PURE__ */ React_default.createElement("span", { className: "VPP-copy-color-label" }, "Copy Color:"), ["hex", false, "rgba", false, "hsla"].map(
|
||||
(name) => name ? /* @__PURE__ */ React_default.createElement(
|
||||
"a", {
|
||||
className: "VPP-copy-color",
|
||||
onClick: (e) => {
|
||||
e.stopPropagation();
|
||||
copyColor(name, color);
|
||||
}
|
||||
},
|
||||
name
|
||||
) : /* @__PURE__ */ React_default.createElement("span", { className: "VPP-separator" }, "|")
|
||||
))
|
||||
);
|
||||
}
|
||||
var palletHook = getModule(Filters.byStrings("toHexString", "toHsl", "palette"), { searchExports: true }) || {};
|
||||
|
||||
function ColorModal({ displayProfile, user }) {
|
||||
const color = palletHook(user.getAvatarURL(displayProfile.guildId, 80));
|
||||
return /* @__PURE__ */ React_default.createElement(SimpleColorModal, { color: color || resolveColor() });
|
||||
}
|
||||
var ColorModalComponent_default = {
|
||||
SimpleColorModal,
|
||||
ColorModal
|
||||
};
|
||||
|
||||
// MODULES-AUTO-LOADER:@Modules/ModalCarousel
|
||||
var ModalCarousel_default = getModule(Filters.byPrototypeKeys("navigateTo", "preloadImage"), { searchExports: false });
|
||||
|
||||
// src/ViewProfilePicture/components/ModalCarousel.jsx
|
||||
var ModalCarousel_default2 = class extends ModalCarousel_default {
|
||||
preloadNextImages() {}
|
||||
};
|
||||
|
||||
// MODULES-AUTO-LOADER:@Modules/Spinner
|
||||
var Spinner_default = getModule((a) => a?.Type?.CHASING_DOTS, { searchExports: true });
|
||||
|
||||
// src/ViewProfilePicture/components/ViewProfilePictureButtonComponent.jsx
|
||||
function Banner({ url, src }) {
|
||||
const [loaded, setLoaded] = React_default.useState(false);
|
||||
const dimsRef = React_default.useRef();
|
||||
React_default.useEffect(() => {
|
||||
(async () => {
|
||||
const [err, dims] = await promiseHandler(getImageDimensions(src));
|
||||
dimsRef.current = fit(err ? {} : dims);
|
||||
setLoaded(true);
|
||||
})();
|
||||
}, []);
|
||||
if (!loaded) return /* @__PURE__ */ React_default.createElement(Spinner_default, { type: Spinner_default.Type.SPINNING_CIRCLE });
|
||||
return /* @__PURE__ */ React_default.createElement(
|
||||
ImageComponent, {
|
||||
url,
|
||||
...dimsRef.current
|
||||
}
|
||||
);
|
||||
}
|
||||
var ViewProfilePictureButtonComponent_default = ({ className, user, displayProfile }) => {
|
||||
const showOnHover = Settings_default(Settings_default.selectors.showOnHover);
|
||||
const handler = () => {
|
||||
const avatarURL = user.getAvatarURL(displayProfile.guildId, 4096, true);
|
||||
const bannerURL = displayProfile.getBannerURL({ canAnimate: true, size: 4096 });
|
||||
const color = displayProfile.accentColor || displayProfile.primaryColor;
|
||||
const items = [
|
||||
/* @__PURE__ */
|
||||
React_default.createElement(
|
||||
ImageComponent, {
|
||||
url: avatarURL,
|
||||
...fit({ width: 4096, height: 4096 })
|
||||
}
|
||||
),
|
||||
bannerURL && /* @__PURE__ */ React_default.createElement(
|
||||
Banner, {
|
||||
url: bannerURL,
|
||||
src: displayProfile.getBannerURL({ canAnimate: true, size: 20 })
|
||||
}
|
||||
),
|
||||
(!bannerURL || Settings_default.getState().bannerColor) && (color ? /* @__PURE__ */ React_default.createElement(ColorModalComponent_default.SimpleColorModal, { color }) : /* @__PURE__ */ React_default.createElement(
|
||||
ColorModalComponent_default.ColorModal, {
|
||||
user,
|
||||
displayProfile
|
||||
}
|
||||
))
|
||||
].filter(Boolean).map((item) => ({ component: item }));
|
||||
openModal(
|
||||
/* @__PURE__ */
|
||||
React_default.createElement(
|
||||
ModalCarousel_default2, {
|
||||
startWith: 0,
|
||||
className: "VPP-carousel",
|
||||
items
|
||||
}
|
||||
),
|
||||
"VPP-carousel", { className: "VPP-carousel-modal" }
|
||||
);
|
||||
};
|
||||
return /* @__PURE__ */ React_default.createElement(Tooltip_default2, { note: "View profile picture" }, /* @__PURE__ */ React_default.createElement(
|
||||
"div", {
|
||||
onClick: handler,
|
||||
className: concateClassNames(className, showOnHover && "VPP-hover")
|
||||
},
|
||||
/* @__PURE__ */
|
||||
React_default.createElement(ImageIcon, null)
|
||||
));
|
||||
};
|
||||
|
||||
// src/ViewProfilePicture/patches/patchVPPButton.jsx
|
||||
var UserProfileModalforwardRef = getModule(Filters.byKeys("Overlay", "render"));
|
||||
var typeFilter = Filters.byStrings("div", "children:");
|
||||
Plugin_default.on(Events.START, () => {
|
||||
if (!UserProfileModalforwardRef) return Logger_default.patchError("patchVPPButton");
|
||||
const unpatch = Patcher.after(UserProfileModalforwardRef, "render", (_, [props], ret) => {
|
||||
const t = getNestedProp(ret, "props.children.props.children.props.children.props.children.1");
|
||||
const target = typeFilter(t?.type) && t || findInTree(ret, (a) => a?.type === "header" || a?.props?.className?.includes("profileHeader"), { walkable: ["props", "children"] });
|
||||
if (!target) return;
|
||||
ret.props.className = `${ret.props.className} VPP-container`;
|
||||
const children = Array.isArray(target.props.children) ? target.props.children : [target.props.children];
|
||||
children.unshift(
|
||||
/* @__PURE__ */
|
||||
React.createElement(
|
||||
ErrorBoundary, {
|
||||
id: "ViewProfilePictureButtonComponent",
|
||||
plugin: Config_default.info.name,
|
||||
fallback: /* @__PURE__ */ React.createElement(ErrorIcon_default, { className: "VPP-Button" })
|
||||
},
|
||||
/* @__PURE__ */
|
||||
React.createElement(
|
||||
ViewProfilePictureButtonComponent_default, {
|
||||
className: concateClassNames("VPP-Button", !typeFilter(target?.type) && "VPP-float"),
|
||||
user: props.user,
|
||||
displayProfile: props.displayProfile
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
target.props.children = children;
|
||||
});
|
||||
Plugin_default.once(Events.STOP, unpatch);
|
||||
});
|
||||
|
||||
// MODULES-AUTO-LOADER:@Modules/FormSwitch
|
||||
var FormSwitch_default = getModule(Filters.byStrings("note", "tooltipNote"), { searchExports: true });
|
||||
|
||||
// common/Components/Switch/index.jsx
|
||||
var Switch_default = getModule(Filters.byStrings('"data-toggleable-component":"switch"', 'layout:"horizontal"'), { searchExports: true }) || function SwitchComponentFallback(props) {
|
||||
return /* @__PURE__ */ React.createElement("div", { style: { color: "#fff" } }, props.children, /* @__PURE__ */ React.createElement(
|
||||
"input", {
|
||||
type: "checkbox",
|
||||
checked: props.value,
|
||||
onChange: (e) => props.onChange(e.target.checked)
|
||||
}
|
||||
));
|
||||
};
|
||||
|
||||
// common/Components/Divider/styles.css
|
||||
StylesLoader_default.push(`.divider-horizontal {
|
||||
border-top: thin solid var(--border-subtle);
|
||||
align-self: stretch;
|
||||
margin:var(--divider-gap) var(--divider-gutter) var(--divider-gap) var(--divider-gutter) ;
|
||||
}
|
||||
|
||||
.divider-vertical {
|
||||
border-left: thin solid var(--border-subtle);
|
||||
align-self: stretch;
|
||||
margin:var(--divider-gutter) var(--divider-gap) var(--divider-gutter) var(--divider-gap);
|
||||
}
|
||||
`);
|
||||
|
||||
// common/Utils/css.js
|
||||
var classNameFactory = (prefix = "", connector = "-") => (...args) => {
|
||||
const classNames = /* @__PURE__ */ new Set();
|
||||
for (const arg of args) {
|
||||
if (arg && typeof arg === "string") classNames.add(arg);
|
||||
else if (Array.isArray(arg)) arg.forEach((name) => classNames.add(name));
|
||||
else if (arg && typeof arg === "object") Object.entries(arg).forEach(([name, value]) => value && classNames.add(name));
|
||||
}
|
||||
return Array.from(classNames, (name) => `${prefix}${connector}${name}`).join(" ");
|
||||
};
|
||||
|
||||
// common/Components/Divider/index.jsx
|
||||
var c = classNameFactory("divider");
|
||||
|
||||
function Divider({ gap = 15, gutter = 0, direction = Divider.direction.HORIZONTAL }) {
|
||||
return /* @__PURE__ */ React_default.createElement(
|
||||
"div", {
|
||||
style: { "--divider-gap": `${gap}px`, "--divider-gutter": `${gutter}%` },
|
||||
className: c("base", direction)
|
||||
}
|
||||
);
|
||||
}
|
||||
Divider.direction = {
|
||||
HORIZONTAL: "horizontal",
|
||||
VERTICAL: "vertical"
|
||||
};
|
||||
|
||||
// common/Components/SettingSwtich/index.jsx
|
||||
function SettingSwtich({ settingKey, note, border = false, onChange = nop, description, ...rest }) {
|
||||
const [val, set] = Settings_default.useSetting(settingKey);
|
||||
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
||||
Switch_default, {
|
||||
...rest,
|
||||
checked: val,
|
||||
label: description || settingKey,
|
||||
description: note,
|
||||
onChange: (e) => {
|
||||
set(e);
|
||||
onChange(e);
|
||||
}
|
||||
}
|
||||
), border && /* @__PURE__ */ React.createElement(Divider, { gap: 15 }));
|
||||
}
|
||||
|
||||
// common/Components/FieldSet/styles.css
|
||||
StylesLoader_default.push(`.fieldset-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.fieldset-label {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.fieldset-description {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.fieldset-label + .fieldset-description{
|
||||
margin-top:-8px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.fieldset-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
`);
|
||||
|
||||
// MODULES-AUTO-LOADER:@Modules/Heading
|
||||
var Heading_default = getModule((a) => a?.render?.toString().includes("data-excessive-heading-level"), { searchExports: true });
|
||||
|
||||
// common/Components/FieldSet/index.jsx
|
||||
var c2 = classNameFactory("fieldset");
|
||||
|
||||
function FieldSet({ label, description, children, contentGap = 16 }) {
|
||||
return /* @__PURE__ */ React_default.createElement("fieldset", { className: c2("container") }, label && /* @__PURE__ */ React_default.createElement(
|
||||
Heading_default, {
|
||||
className: c2("label"),
|
||||
tag: "legend",
|
||||
variant: "text-lg/medium"
|
||||
},
|
||||
label
|
||||
), description && /* @__PURE__ */ React_default.createElement(
|
||||
Heading_default, {
|
||||
className: c2("description"),
|
||||
variant: "text-sm/normal",
|
||||
color: "text-secondary"
|
||||
},
|
||||
description
|
||||
), /* @__PURE__ */ React_default.createElement("div", { className: c2("content"), style: { gap: contentGap } }, children));
|
||||
}
|
||||
|
||||
// src/ViewProfilePicture/components/SettingComponent.jsx
|
||||
function SettingComponent() {
|
||||
return /* @__PURE__ */ React_default.createElement(FieldSet, { contentGap: 8 }, [{
|
||||
settingKey: "showOnHover",
|
||||
note: "By default hide ViewProfilePicture button and show on hover.",
|
||||
description: "Show on hover"
|
||||
},
|
||||
{
|
||||
settingKey: "bannerColor",
|
||||
note: "Always include banner color in carousel, even if a banner is present.",
|
||||
description: "Include banner color."
|
||||
}
|
||||
].map(SettingSwtich));
|
||||
}
|
||||
|
||||
// src/ViewProfilePicture/index.jsx
|
||||
Plugin_default.getSettingsPanel = () => /* @__PURE__ */ React_default.createElement(SettingComponent, null);
|
||||
module.exports = () => Plugin_default;
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "1.8.33",
|
||||
"hasShownChangelog": true
|
||||
},
|
||||
"settings": {
|
||||
"showMemberListIcons": true,
|
||||
"showDMListIcons": true,
|
||||
"showPeopleListIcons": true,
|
||||
"currentChannelColor": true,
|
||||
"ignoreEnabled": false,
|
||||
"ignoredChannels": [],
|
||||
"ignoredGuilds": []
|
||||
},
|
||||
"changelogVersion": "1.12.1"
|
||||
}
|
||||
@@ -0,0 +1,892 @@
|
||||
/**
|
||||
* @name VoiceActivity
|
||||
* @author Neodymium
|
||||
* @version 1.12.1
|
||||
* @description Shows icons and info in popouts, the member list, and more when someone is in a voice channel.
|
||||
* @source https://github.com/Neodymium7/BetterDiscordStuff/blob/main/VoiceActivity/VoiceActivity.plugin.js
|
||||
* @invite fRbsqH87Av
|
||||
*/
|
||||
|
||||
/*@cc_on
|
||||
@if (@_jscript)
|
||||
|
||||
// Offer to self-install for clueless users that try to run this directly.
|
||||
var shell = WScript.CreateObject("WScript.Shell");
|
||||
var fs = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var pathPlugins = shell.ExpandEnvironmentStrings("%APPDATA%\BetterDiscord\plugins");
|
||||
var pathSelf = WScript.ScriptFullName;
|
||||
// Put the user at ease by addressing them in the first person
|
||||
shell.Popup("It looks like you've mistakenly tried to run me directly. \n(Don't do that!)", 0, "I'm a plugin for BetterDiscord", 0x30);
|
||||
if (fs.GetParentFolderName(pathSelf) === fs.GetAbsolutePathName(pathPlugins)) {
|
||||
shell.Popup("I'm in the correct folder already.", 0, "I'm already installed", 0x40);
|
||||
} else if (!fs.FolderExists(pathPlugins)) {
|
||||
shell.Popup("I can't find the BetterDiscord plugins folder.\nAre you sure it's even installed?", 0, "Can't install myself", 0x10);
|
||||
} else if (shell.Popup("Should I copy myself to BetterDiscord's plugins folder for you?", 0, "Do you need some help?", 0x34) === 6) {
|
||||
fs.CopyFile(pathSelf, fs.BuildPath(pathPlugins, fs.GetFileName(pathSelf)), true);
|
||||
// Show the user where to put plugins in the future
|
||||
shell.Exec("explorer " + pathPlugins);
|
||||
shell.Popup("I'm installed!", 0, "Successfully installed", 0x40);
|
||||
}
|
||||
WScript.Quit();
|
||||
|
||||
@else@*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const betterdiscord = new BdApi("VoiceActivity");
|
||||
const react = BdApi.React;
|
||||
|
||||
// styles
|
||||
let _styles = "";
|
||||
function _loadStyle(path, css) {
|
||||
_styles += "/*" + path + "*/\n" + css + "\n";
|
||||
}
|
||||
function styles() {
|
||||
return _styles;
|
||||
}
|
||||
|
||||
// @lib/settings.ts
|
||||
class SettingsManager {
|
||||
settings = betterdiscord.Data.load("settings");
|
||||
listeners = new Set();
|
||||
constructor(defaultSettings) {
|
||||
if (!this.settings) {
|
||||
betterdiscord.Data.save("settings", defaultSettings);
|
||||
this.settings = defaultSettings;
|
||||
return;
|
||||
}
|
||||
if (Object.keys(this.settings) !== Object.keys(defaultSettings)) {
|
||||
this.settings = { ...defaultSettings, ...this.settings };
|
||||
let changed = false;
|
||||
for (const key in this.settings) {
|
||||
if (!(key in defaultSettings)) {
|
||||
delete this.settings[key];
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (changed) betterdiscord.Data.save("settings", this.settings);
|
||||
}
|
||||
}
|
||||
addListener(listener) {
|
||||
this.listeners.add(listener);
|
||||
return () => {
|
||||
this.listeners.delete(listener);
|
||||
};
|
||||
}
|
||||
clearListeners() {
|
||||
this.listeners.clear();
|
||||
}
|
||||
useSettingsState(...keys) {
|
||||
let initialState = this.settings;
|
||||
if (keys.length) initialState = Object.fromEntries(keys.map((key) => [key, initialState[key]]));
|
||||
const [state, setState] = react.useState(initialState);
|
||||
react.useEffect(() => {
|
||||
return this.addListener((key, value) => {
|
||||
if (!keys.length || keys.includes(key)) setState((state2) => ({ ...state2, [key]: value }));
|
||||
});
|
||||
}, []);
|
||||
return state;
|
||||
}
|
||||
get(key) {
|
||||
return this.settings[key];
|
||||
}
|
||||
set(key, value) {
|
||||
this.settings[key] = value;
|
||||
betterdiscord.Data.save("settings", this.settings);
|
||||
for (const listener of this.listeners) listener(key, value);
|
||||
}
|
||||
}
|
||||
function buildSettingsPanel(settingsManager, settings) {
|
||||
for (const setting of settings) {
|
||||
setting.value = settingsManager.get(setting.id);
|
||||
}
|
||||
return betterdiscord.UI.buildSettingsPanel({
|
||||
settings,
|
||||
onChange: (_, id, value) => settingsManager.set(id, value)
|
||||
});
|
||||
}
|
||||
|
||||
// @lib/strings.ts
|
||||
const LocaleStore = betterdiscord.Webpack.getStore("LocaleStore");
|
||||
class StringsManager {
|
||||
locales;
|
||||
defaultLocale;
|
||||
strings;
|
||||
constructor(locales, defaultLocale) {
|
||||
this.locales = locales;
|
||||
this.defaultLocale = defaultLocale;
|
||||
this.strings = locales[defaultLocale];
|
||||
}
|
||||
setLocale = () => {
|
||||
this.strings = this.locales[LocaleStore.locale] || this.locales[this.defaultLocale];
|
||||
};
|
||||
subscribe() {
|
||||
this.setLocale();
|
||||
LocaleStore.addReactChangeListener(this.setLocale);
|
||||
}
|
||||
unsubscribe() {
|
||||
LocaleStore.removeReactChangeListener(this.setLocale);
|
||||
}
|
||||
get(key) {
|
||||
return this.strings[key] || this.locales[this.defaultLocale][key];
|
||||
}
|
||||
}
|
||||
|
||||
// @lib/changelog.ts
|
||||
function showChangelog(changes, meta) {
|
||||
if (!changes || changes.length == 0) return;
|
||||
const changelogVersion = betterdiscord.Data.load("changelogVersion");
|
||||
if (meta.version === changelogVersion) return;
|
||||
betterdiscord.UI.showChangelogModal({
|
||||
title: meta.name,
|
||||
subtitle: meta.version,
|
||||
changes
|
||||
});
|
||||
betterdiscord.Data.save("changelogVersion", meta.version);
|
||||
}
|
||||
|
||||
// @lib/utils/webpack.ts
|
||||
function getClasses(...classes) {
|
||||
return betterdiscord.Webpack.getModule((m) => betterdiscord.Webpack.Filters.byKeys(...classes)(m) && typeof m[classes[0]] == "string");
|
||||
}
|
||||
function getSelectors(...classes) {
|
||||
const module = getClasses(...classes);
|
||||
if (!module) return void 0;
|
||||
return classes.reduce((obj, className) => {
|
||||
obj[className] = "." + module[className].replaceAll(" ", ".");
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
function getIcon(searchString) {
|
||||
const filter = (m) => betterdiscord.Webpack.Filters.byStrings(searchString, '"svg"')(m) && typeof m === "function";
|
||||
return betterdiscord.Webpack.getModule(filter, {
|
||||
searchExports: true
|
||||
});
|
||||
}
|
||||
function expect(object, options) {
|
||||
if (object) return object;
|
||||
const fallbackMessage = !options.fatal && options.fallback ? " Using fallback value instead." : "";
|
||||
const errorMessage = `Module ${options.name} not found.${fallbackMessage}\n\nContact the plugin developer to inform them of this error.`;
|
||||
betterdiscord.Logger.error(errorMessage);
|
||||
options.onError?.();
|
||||
if (options.fatal) throw new Error(errorMessage);
|
||||
return options.fallback;
|
||||
}
|
||||
function expectModule(options) {
|
||||
return expect(betterdiscord.Webpack.getModule(options.filter, options), options);
|
||||
}
|
||||
function expectWithKey(options) {
|
||||
const [module, key] = betterdiscord.Webpack.getWithKey(options.filter, options);
|
||||
if (module) return [module, key];
|
||||
const fallback = expect(module, options);
|
||||
if (fallback) {
|
||||
const key2 = "__key";
|
||||
return [{ [key2]: fallback }, key2];
|
||||
}
|
||||
return void 0;
|
||||
}
|
||||
function expectSelectors(name, classes) {
|
||||
return expect(getSelectors(...classes), {
|
||||
name
|
||||
});
|
||||
}
|
||||
function expectIcon(name, searchString) {
|
||||
return expect(getIcon(searchString), {
|
||||
name,
|
||||
fallback: (_props) => null
|
||||
});
|
||||
}
|
||||
function byType(type) {
|
||||
return (e) => typeof e === type;
|
||||
}
|
||||
|
||||
// manifest.json
|
||||
const changelog = [
|
||||
{
|
||||
title: "Fixed",
|
||||
type: "fixed",
|
||||
items: [
|
||||
"Fixed member list icons."
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// @discord/stores.ts
|
||||
const UserStore = betterdiscord.Webpack.getStore("UserStore");
|
||||
const VoiceStateStore = betterdiscord.Webpack.getStore("VoiceStateStore");
|
||||
const GuildStore = betterdiscord.Webpack.getStore("GuildStore");
|
||||
const ChannelStore = betterdiscord.Webpack.getStore("ChannelStore");
|
||||
const PermissionStore = betterdiscord.Webpack.getStore("PermissionStore");
|
||||
const useStateFromStores = expectModule({
|
||||
filter: betterdiscord.Webpack.Filters.byStrings("useStateFromStores"),
|
||||
name: "Flux",
|
||||
fallback(stores, callback) {
|
||||
return callback();
|
||||
},
|
||||
searchExports: true
|
||||
});
|
||||
|
||||
// modules/discordmodules.tsx
|
||||
function useUserVoiceStateFallback({ userId }) {
|
||||
const voiceState = useStateFromStores(
|
||||
[VoiceStateStore],
|
||||
() => userId && VoiceStateStore.getDiscoverableVoiceStateForUser(userId)
|
||||
);
|
||||
const channel = useStateFromStores([ChannelStore], () => {
|
||||
if (voiceState?.channelId) return ChannelStore.getChannel(voiceState?.channelId);
|
||||
});
|
||||
const visible = useStateFromStores(
|
||||
[PermissionStore],
|
||||
() => channel?.isPrivate() || PermissionStore.can(Permissions.VIEW_CHANNEL, channel)
|
||||
);
|
||||
if (visible) {
|
||||
return {
|
||||
voiceState,
|
||||
voiceChannel: channel
|
||||
};
|
||||
} else return {};
|
||||
}
|
||||
const MemberListItem = expectModule({
|
||||
filter: (m) => m.type?.toString?.().includes("MemberListItem"),
|
||||
name: "MemberListItem",
|
||||
searchExports: true
|
||||
});
|
||||
const PrivateChannel = expectWithKey({
|
||||
filter: betterdiscord.Webpack.Filters.byStrings("PrivateChannel", "getTypingUsers"),
|
||||
name: "PrivateChannel",
|
||||
defaultExport: false
|
||||
});
|
||||
const PeopleListItem = expectModule({
|
||||
filter: (m) => m?.prototype?.render && betterdiscord.Webpack.Filters.byStrings("this.peopleListItemRef")(m),
|
||||
name: "PeopleListItem"
|
||||
});
|
||||
const Permissions = expectModule({
|
||||
filter: betterdiscord.Webpack.Filters.byKeys("VIEW_CREATOR_MONETIZATION_ANALYTICS"),
|
||||
searchExports: true,
|
||||
name: "Permissions",
|
||||
fallback: {
|
||||
VIEW_CHANNEL: 1024n
|
||||
}
|
||||
});
|
||||
const memberSelectors = expectSelectors("Children Class", ["avatar", "children", "layout"]);
|
||||
const useUserVoiceState = expectModule({
|
||||
filter: betterdiscord.Webpack.Filters.byStrings("getDiscoverableVoiceState", "getDiscoverableVoiceStateForUser"),
|
||||
name: "useUserVoiceState",
|
||||
fallback: useUserVoiceStateFallback
|
||||
});
|
||||
|
||||
// locales.json
|
||||
const el = {
|
||||
SETTINGS_PROFILE: "Τομέας Προφίλ",
|
||||
SETTINGS_PROFILE_NOTE: "Εμφανίζει τον τομέα προφίλ για την τρέχουσα δραστηριότητα φωνής στα αναδυόμενα χρήστη και στην πλευρικές μπάρες προφίλ των Άμεσων Μηνυμάτων.",
|
||||
SETTINGS_ICONS: "Εικονίδια Λίστας Μελών",
|
||||
SETTINGS_ICONS_NOTE: "Εμφανίζει εικονίδια στη λίστα μελών όταν κάποιος είναι σε κανάλι φωνής.",
|
||||
SETTINGS_DM_ICONS: "Εικονίδια Άμεσων Μηνυμάτων",
|
||||
SETTINGS_DM_ICONS_NOTE: "Εμφανίζει εικονίδια στη λίστα Άμεσων Μηνυμάτων όταν κάποιος είναι σε κανάλι φωνής.",
|
||||
SETTINGS_PEOPLE_ICONS: "Εικονίδια Λίστας Φίλων",
|
||||
SETTINGS_PEOPLE_ICONS_NOTE: "Εμφανίζει εικονίδια στη λίστα φίλων όταν κάποιος είναι σε κανάλι φωνής.",
|
||||
SETTINGS_GUILD_ICONS: "Εικονίδια Συντεχνίας",
|
||||
SETTINGS_GUILD_ICONS_NOTE: "Εμφανίζει εικονίδια στις συντεχνίες ακόμα και αν δεν συμμετέχετε.",
|
||||
SETTINGS_COLOR: "Λίστα Μελών - Χρώμα Εικονιδίου Τρέχοντος Καναλιού",
|
||||
SETTINGS_COLOR_NOTE: "Αλλάζει τα εικονίδια της Λίστας Μελών σε πράσινα όταν ο χρήστης είναι στο δικό σας τρέχον κανάλι φωνής.",
|
||||
SETTINGS_STATUS: "Λίστα Μελών - Εμφάνιση Εικονιδίων Κατάστασης",
|
||||
SETTINGS_STATUS_NOTE: "Αλλάζει τα εικονίδια της Λίστας Μελών όταν ο χρήστης είναι σε Σίγαση, Κώφωση ή έχε ενεργοποιημένο Βίντεο.",
|
||||
SETTINGS_IGNORE: "Αγνόηση",
|
||||
SETTINGS_IGNORE_NOTE: "Προσθέτει μια επιλογή στο Κανάλι Φωνής και στα μενού περιεχομένου Συντεχνίας για αγνόηση αυτού του καναλιού/συντεχνίας στα Εικονίδια Λϊστας Μελών και στα Αναδυόμενα Χρήστη.",
|
||||
CONTEXT_IGNORE: "Αγνόηση στη Δραστηριότητα Φωνής",
|
||||
VOICE_CALL: "Φωνητική Κλήση",
|
||||
PRIVATE_CALL: "Ιδιωτική Κλήση",
|
||||
GROUP_CALL: "Ομαδική Κλήση",
|
||||
LIVE: "Ζωντανά",
|
||||
HEADER: "Σε ένα Κανάλι Φωνής",
|
||||
HEADER_VOICE: "Σε μια Κλήση Φωνής",
|
||||
HEADER_PRIVATE: "Σε μια Ιδιωτική Κλήση",
|
||||
HEADER_GROUP: "Σε μια Ομαδική Κλήση",
|
||||
HEADER_STAGE: "Σε ένα Κανάλι Σταδίου",
|
||||
VIEW: "Προβολή Καναλιού",
|
||||
VIEW_CALL: "Προβολή Κλήσης",
|
||||
JOIN: "Συμμετοχή σε Κανάλι",
|
||||
JOIN_CALL: "Συμμετοχή σε Κλήση",
|
||||
JOIN_DISABLED: "Ήδη σε Κανάλι",
|
||||
JOIN_DISABLED_CALL: "Ήδη σε Κλήση",
|
||||
JOIN_VIDEO: "Συμμετοχή με Βίντεο"
|
||||
};
|
||||
const ru = {
|
||||
SETTINGS_PROFILE: "Раздел в Профиле",
|
||||
SETTINGS_PROFILE_NOTE: "Показывает раздел для текущей голосовой активности в профиле, всплывающих окнах и боковых панелях в ЛС.",
|
||||
SETTINGS_ICONS: "Иконки в Списке Участников",
|
||||
SETTINGS_ICONS_NOTE: "Показывает иконки в списке участников когда пользователь в голосовом канале.",
|
||||
SETTINGS_DM_ICONS: "Иконки в ЛС",
|
||||
SETTINGS_DM_ICONS_NOTE: "Показывает иконки в списке участников ЛС когда пользователь в голосовом канале.",
|
||||
SETTINGS_PEOPLE_ICONS: "Иконки в Списке Друзей",
|
||||
SETTINGS_PEOPLE_ICONS_NOTE: "Показывает иконки в списке друзей когда пользователь в голосовом канале.",
|
||||
SETTINGS_GUILD_ICONS: "Иконки Сервера",
|
||||
SETTINGS_GUILD_ICONS_NOTE: "Показывает голосовые иконки на серверах даже когда вы не участвуете.",
|
||||
SETTINGS_COLOR: "Цвет Иконки Голосовой Активности",
|
||||
SETTINGS_COLOR_NOTE: "Делает иконки в Списке Участников зелёными когда пользователь в голосовом канале вместе с вами.",
|
||||
SETTINGS_STATUS: "Показывать Иконки Статуса",
|
||||
SETTINGS_STATUS_NOTE: "Меняет иконки в Списке Участников когда пользователь Выключил Микрофон/Звук или Начал трансляцию.",
|
||||
SETTINGS_IGNORE: "Ингор",
|
||||
SETTINGS_IGNORE_NOTE: "Добавляет возможность в контекстных меню Голосовых Каналов и Серверов игнорировать этот канал/сервер в Списке Участников и Профилях Пользователей.",
|
||||
CONTEXT_IGNORE: "Игнор (Голосовая Активность)",
|
||||
VOICE_CALL: "Голосовой звонок",
|
||||
PRIVATE_CALL: "Приватный звонок",
|
||||
GROUP_CALL: "Групповой звонок",
|
||||
LIVE: "В ЭФИРЕ",
|
||||
HEADER: "В Голосовом Канале",
|
||||
HEADER_VOICE: "В Голосовом Звонке",
|
||||
HEADER_PRIVATE: "В Приватном Звонке",
|
||||
HEADER_GROUP: "В Групповом Звонке",
|
||||
HEADER_STAGE: "В Канале Трибуны",
|
||||
VIEW: "Просмотреть Канал",
|
||||
VIEW_CALL: "Просмотреть Звонок",
|
||||
JOIN: "Присоединиться к Каналу",
|
||||
JOIN_CALL: "Присоединиться к Звонку",
|
||||
JOIN_DISABLED: "Уже в Канале",
|
||||
JOIN_DISABLED_CALL: "Уже в Звонке",
|
||||
JOIN_VIDEO: "Присоединиться с Видео"
|
||||
};
|
||||
const de = {
|
||||
SETTINGS_PROFILE: "Profilbereich",
|
||||
SETTINGS_PROFILE_NOTE: "Zeigt den Profilbereich für die aktuelle Sprachaktivität in Benutzer-Popouts und DM-Profilseitenleisten an.",
|
||||
SETTINGS_ICONS: "Symbole in der Mitgliederliste",
|
||||
SETTINGS_ICONS_NOTE: "Zeigt Symbole in der Mitgliederliste an, wenn sich jemand in einem Sprachkanal befindet.",
|
||||
SETTINGS_DM_ICONS: "DM-Symbole",
|
||||
SETTINGS_DM_ICONS_NOTE: "Zeigt Symbole in der DM-Liste an, wenn sich jemand in einem Sprachkanal befindet.",
|
||||
SETTINGS_PEOPLE_ICONS: "Symbole in der Freundesliste",
|
||||
SETTINGS_PEOPLE_ICONS_NOTE: "Zeigt Symbole in der Freundesliste an, wenn sich jemand in einem Sprachkanal befindet.",
|
||||
SETTINGS_GUILD_ICONS: "Gildensymbole",
|
||||
SETTINGS_GUILD_ICONS_NOTE: "Zeigt Symbole für Gilden an, auch wenn du nicht teilnimmst.",
|
||||
SETTINGS_COLOR: "Mitgliederliste - Farbe des aktuellen Kanalsymbols",
|
||||
SETTINGS_COLOR_NOTE: "Die Symbole in der Mitgliederliste werden grün, wenn sich der Benutzer in Ihrem aktuellen Sprachkanal befindet.",
|
||||
SETTINGS_STATUS: "Mitgliederliste - Statussymbole anzeigen",
|
||||
SETTINGS_STATUS_NOTE: "Ändert die Symbole in der Mitgliederliste, wenn ein Benutzer stummgeschaltet oder mit aktiviertem Video ist.",
|
||||
SETTINGS_IGNORE: "Ignorieren",
|
||||
SETTINGS_IGNORE_NOTE: "Fügt eine Option in die Kontextmenüs von Sprachkanälen und Gilden hinzu, um diesen Kanal/diese Gilde in der Mitgliederliste und Benutzer-Popouts zu ignorieren.",
|
||||
CONTEXT_IGNORE: "Bei Sprachaktivität ignorieren",
|
||||
VOICE_CALL: "Sprachanruf",
|
||||
PRIVATE_CALL: "Privatanruf",
|
||||
GROUP_CALL: "Gruppenanruf",
|
||||
LIVE: "Live",
|
||||
HEADER: "In einem Sprachkanal",
|
||||
HEADER_VOICE: "In einem Sprachanruf",
|
||||
HEADER_PRIVATE: "In einem privaten Anruf",
|
||||
HEADER_GROUP: "In einem Gruppenruf",
|
||||
HEADER_STAGE: "In einem Stage Kanal",
|
||||
VIEW: "Kanal anzeigen",
|
||||
VIEW_CALL: "Anruf anzeigen",
|
||||
JOIN: "Kanal beitreten",
|
||||
JOIN_CALL: "Anruf beitreten",
|
||||
JOIN_DISABLED: "Bereits im Kanal",
|
||||
JOIN_DISABLED_CALL: "Bereits im Aufruf",
|
||||
JOIN_VIDEO: "Beitreten mit Video"
|
||||
};
|
||||
const fr = {
|
||||
SETTINGS_PROFILE: "Section de profil",
|
||||
SETTINGS_PROFILE_NOTE: "Affiche une section de profile pour l'activité vocale actuelle dans les popouts utilisateur et les profiles latéraux de MP.",
|
||||
SETTINGS_ICONS: "Icônes de la liste de membre",
|
||||
SETTINGS_ICONS_NOTE: "Affiche des icônes dans la liste de membre quand quelqu'un est dans un salon vocal.",
|
||||
SETTINGS_DM_ICONS: "Icônes de MP",
|
||||
SETTINGS_DM_ICONS_NOTE: "Affiche des icônes dans la liste de MP quand quelqu'un est dans un salon vocal.",
|
||||
SETTINGS_PEOPLE_ICONS: "Icônes de la liste d'amis",
|
||||
SETTINGS_PEOPLE_ICONS_NOTE: "Affiche des icônes dans la liste d'amis quand quelqu'un est dans un salon vocal.",
|
||||
SETTINGS_GUILD_ICONS: "Icônes de serveur",
|
||||
SETTINGS_GUILD_ICONS_NOTE: "Affiche des icônes de vocal sur les serveurs même quand vous ne participez pas.",
|
||||
SETTINGS_COLOR: "Liste de membre - Couleur d'icône du salon actuel",
|
||||
SETTINGS_COLOR_NOTE: "Rends les icônes de la liste de membre vertes quand un utilisateur est dans le salon vocal actuel.",
|
||||
SETTINGS_STATUS: "Liste de membre - Afficher les icônes de status",
|
||||
SETTINGS_STATUS_NOTE: "Change les icônes de la liste de membre quand un utilisateur est muet, mis en sourdine, ou a la vidéo activée.",
|
||||
SETTINGS_IGNORE: "Ignorer",
|
||||
SETTINGS_IGNORE_NOTE: "Ajoute une option dans les menus contextuels des salons vocaux et serveurs pour ignorer le dit salon/serveur dans les icônes de liste de membre et popouts utilisateur.",
|
||||
CONTEXT_IGNORE: "Ignorer dans Activité Vocale",
|
||||
VOICE_CALL: "Appel vocal",
|
||||
PRIVATE_CALL: "Appel privé",
|
||||
GROUP_CALL: "Appel de groupe",
|
||||
LIVE: "Live",
|
||||
HEADER: "Dans un salon vocal",
|
||||
HEADER_VOICE: "Dans un appel vocal",
|
||||
HEADER_PRIVATE: "Dans un appel privé",
|
||||
HEADER_GROUP: "Dans un appel de groupe",
|
||||
HEADER_STAGE: "Dans un salon de conférence",
|
||||
VIEW: "Voir le salon",
|
||||
VIEW_CALL: "Voir l'appel",
|
||||
JOIN: "Rejoindre le salon",
|
||||
JOIN_CALL: "Rejoindre l'appel",
|
||||
JOIN_DISABLED: "Déjà dans le salon",
|
||||
JOIN_DISABLED_CALL: "Déjà en appel",
|
||||
JOIN_VIDEO: "Rejoidre avec vidéo",
|
||||
MEMBER: "Membre",
|
||||
MEMBERS: "Membres"
|
||||
};
|
||||
const locales = {
|
||||
"en-US": {
|
||||
SETTINGS_PROFILE: "Profile Section",
|
||||
SETTINGS_PROFILE_NOTE: "Shows profile section for current voice activity in user popouts and DM profile sidebars.",
|
||||
SETTINGS_ICONS: "Member List Icons",
|
||||
SETTINGS_ICONS_NOTE: "Shows icons on the member list when someone is in a voice channel.",
|
||||
SETTINGS_DM_ICONS: "DM Icons",
|
||||
SETTINGS_DM_ICONS_NOTE: "Shows icons on the DM list when someone is in a voice channel.",
|
||||
SETTINGS_PEOPLE_ICONS: "Friends List Icons",
|
||||
SETTINGS_PEOPLE_ICONS_NOTE: "Shows icons on the friends list when someone is in a voice channel.",
|
||||
SETTINGS_GUILD_ICONS: "Server Icons",
|
||||
SETTINGS_GUILD_ICONS_NOTE: "Shows voice icons on servers even when you're not participating.",
|
||||
SETTINGS_COLOR: "Member List - Current Channel Icon Color",
|
||||
SETTINGS_COLOR_NOTE: "Makes the Member List icons green when the user is in your current voice channel.",
|
||||
SETTINGS_STATUS: "Member List - Show Status Icons",
|
||||
SETTINGS_STATUS_NOTE: "Changes the Member List icons when a user is Muted, Deafened, or has Video enabled.",
|
||||
SETTINGS_CURRENT_USER: "Current User Icon",
|
||||
SETTINGS_CURRENT_USER_NOTE: "Toggles displaying a voice channel icon for the current user.",
|
||||
SETTINGS_IGNORE: "Ignore",
|
||||
SETTINGS_IGNORE_NOTE: "Adds an option on Voice Channel and Server context menus to ignore that channel/server in Member List Icons and User Popouts.",
|
||||
CONTEXT_IGNORE: "Ignore in Voice Activity",
|
||||
VOICE_CALL: "Voice Call",
|
||||
PRIVATE_CALL: "Private Call",
|
||||
GROUP_CALL: "Group Call",
|
||||
LIVE: "Live",
|
||||
HEADER: "In a Voice Channel",
|
||||
HEADER_VOICE: "In a Voice Call",
|
||||
HEADER_PRIVATE: "In a Private Call",
|
||||
HEADER_GROUP: "In a Group Call",
|
||||
HEADER_STAGE: "In a Stage Channel",
|
||||
VIEW: "View Channel",
|
||||
VIEW_CALL: "View Call",
|
||||
JOIN: "Join Channel",
|
||||
JOIN_CALL: "Join Call",
|
||||
JOIN_DISABLED: "Already in Channel",
|
||||
JOIN_DISABLED_CALL: "Already in Call",
|
||||
JOIN_VIDEO: "Join With Video",
|
||||
MEMBER: "Member",
|
||||
MEMBERS: "Members"
|
||||
},
|
||||
el: el,
|
||||
ru: ru,
|
||||
de: de,
|
||||
fr: fr
|
||||
};
|
||||
|
||||
// modules/utils.ts
|
||||
const Settings = new SettingsManager({
|
||||
showMemberListIcons: true,
|
||||
showDMListIcons: true,
|
||||
showPeopleListIcons: true,
|
||||
currentChannelColor: true,
|
||||
showStatusIcons: true,
|
||||
currentUserIcon: true,
|
||||
ignoreEnabled: false,
|
||||
ignoredChannels: [],
|
||||
ignoredGuilds: []
|
||||
});
|
||||
const Strings = new StringsManager(locales, "en-US");
|
||||
function groupDMName(members) {
|
||||
if (members.length === 1) {
|
||||
return UserStore.getUser(members[0]).globalName;
|
||||
} else if (members.length > 1) {
|
||||
let name = "";
|
||||
for (let i = 0; i < members.length; i++) {
|
||||
if (i === members.length - 1) name += UserStore.getUser(members[i]).globalName;
|
||||
else name += UserStore.getUser(members[i]).globalName + ", ";
|
||||
}
|
||||
return name;
|
||||
}
|
||||
return "Unnamed";
|
||||
}
|
||||
|
||||
// styles/voiceicon.module.css
|
||||
const css = `
|
||||
.VoiceActivity-voiceicon-icon {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
min-width: 20px;
|
||||
border-radius: 50%;
|
||||
background-color: var(--background-accent);
|
||||
cursor: pointer;
|
||||
svg {
|
||||
padding: 3px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.VoiceActivity-voiceicon-iconCurrentCall {
|
||||
background-color: var(--status-positive);
|
||||
}
|
||||
.VoiceActivity-voiceicon-iconLive {
|
||||
height: 16px;
|
||||
border-radius: 16px;
|
||||
background-color: var(--red-400);
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
font-weight: 600;
|
||||
font-family: var(--font-display);
|
||||
text-transform: uppercase;
|
||||
& > div {
|
||||
padding: 0 6px;
|
||||
}
|
||||
}
|
||||
.VoiceActivity-voiceicon-tooltip {
|
||||
.VoiceActivity-voiceicon-header {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.VoiceActivity-voiceicon-subtext {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-top: 3px;
|
||||
& > div {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
.VoiceActivity-voiceicon-tooltipIcon {
|
||||
min-width: 16px;
|
||||
margin-right: 3px;
|
||||
color: var(--interactive-normal);
|
||||
}
|
||||
}
|
||||
.VoiceActivity-voiceicon-iconContainer {
|
||||
margin-left: auto;
|
||||
}
|
||||
.VoiceActivity-voiceicon-peopleListIcon {
|
||||
margin-right: 16px;
|
||||
}`;
|
||||
_loadStyle("voiceicon.module.css", css);
|
||||
const modules_1af761ba = {
|
||||
"icon": "VoiceActivity-voiceicon-icon",
|
||||
"iconCurrentCall": "VoiceActivity-voiceicon-iconCurrentCall",
|
||||
"iconLive": "VoiceActivity-voiceicon-iconLive",
|
||||
"tooltip": "VoiceActivity-voiceicon-tooltip",
|
||||
"header": "VoiceActivity-voiceicon-header",
|
||||
"subtext": "VoiceActivity-voiceicon-subtext",
|
||||
"tooltipIcon": "VoiceActivity-voiceicon-tooltipIcon",
|
||||
"iconContainer": "VoiceActivity-voiceicon-iconContainer",
|
||||
"peopleListIcon": "VoiceActivity-voiceicon-peopleListIcon"
|
||||
};
|
||||
const iconStyles = modules_1af761ba;
|
||||
|
||||
// @discord/icons.tsx
|
||||
const Speaker = expectIcon("Speaker", "M12 3a1 1 0 0 0-1-1h-.06a1 1 0 0 0-.74.32L5.92 7H3a1 1");
|
||||
const Muted = expectIcon(
|
||||
"Muted",
|
||||
"m2.7 22.7 20-20a1 1 0 0 0-1.4-1.4l-20 20a1 1 0 1 0 1.4 1.4ZM10.8 17.32c-.21.21-.1.58.2.62V20H9a1"
|
||||
);
|
||||
const ServerMuted = expectIcon(
|
||||
"ServerMuted",
|
||||
"M21.76.83a5.02 5.02 0 0 1 .78 7.7 5 5 0 0 1-7.07 0 5.02 5.02 0 0 1 0-7.07"
|
||||
);
|
||||
const Deafened = expectIcon(
|
||||
"Deafened",
|
||||
"M22.7 2.7a1 1 0 0 0-1.4-1.4l-20 20a1 1 0 1 0 1.4 1.4l20-20ZM17.06"
|
||||
);
|
||||
const ServerDeafened = expectIcon(
|
||||
"ServerDeafened",
|
||||
"M12.38 1c.38.02.58.45.4.78-.15.3-.3.62-.4.95A.4.4 0 0 1 12 3a9 9 0 0 0-8.95 10h1.87a5"
|
||||
);
|
||||
const Video = expectIcon("Video", "M4 4a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h11a3 3");
|
||||
const ChannelIcon = expectModule({
|
||||
filter: betterdiscord.Webpack.Filters.combine(
|
||||
betterdiscord.Webpack.Filters.byStrings("isGuildStageVoice", "isGroupDM", "isPrivate"),
|
||||
(m) => !m.toString?.().includes("intl")
|
||||
),
|
||||
name: "ChannelIcon",
|
||||
fallback: (_props) => null
|
||||
});
|
||||
|
||||
// @discord/modules.ts
|
||||
const transitionTo = expectModule({
|
||||
filter: betterdiscord.Webpack.Filters.combine(
|
||||
betterdiscord.Webpack.Filters.byStrings("transitionTo -"),
|
||||
byType("function")
|
||||
),
|
||||
searchExports: true,
|
||||
name: "transitionTo"
|
||||
});
|
||||
|
||||
// components/VoiceIcon.tsx
|
||||
function VoiceIcon(props) {
|
||||
const settingsState = Settings.useSettingsState(
|
||||
"showMemberListIcons",
|
||||
"showDMListIcons",
|
||||
"showPeopleListIcons",
|
||||
"ignoreEnabled",
|
||||
"ignoredChannels",
|
||||
"ignoredGuilds",
|
||||
"currentChannelColor",
|
||||
"showStatusIcons",
|
||||
"currentUserIcon"
|
||||
);
|
||||
const currentUser = UserStore.getCurrentUser();
|
||||
const { voiceState, voiceChannel: channel } = useUserVoiceState({ userId: props.userId });
|
||||
const { voiceState: currentUserVoiceState } = useUserVoiceState({ userId: currentUser?.id });
|
||||
if (props.context === "memberlist" && !settingsState.showMemberListIcons) return null;
|
||||
if (props.context === "dmlist" && !settingsState.showDMListIcons) return null;
|
||||
if (props.context === "peoplelist" && !settingsState.showPeopleListIcons) return null;
|
||||
if (props.userId === currentUser?.id && !settingsState.currentUserIcon) return null;
|
||||
if (!voiceState) return null;
|
||||
const guild = GuildStore.getGuild(channel.guild_id);
|
||||
const ignored = settingsState.ignoredChannels.includes(channel.id) || settingsState.ignoredGuilds.includes(guild?.id);
|
||||
if (settingsState.ignoreEnabled && ignored) return null;
|
||||
let text;
|
||||
let subtext;
|
||||
let channelPath;
|
||||
let className = iconStyles.icon;
|
||||
if (settingsState.currentChannelColor && channel.id === currentUserVoiceState?.channelId)
|
||||
className = `${iconStyles.icon} ${iconStyles.iconCurrentCall}`;
|
||||
if (voiceState.selfStream) className = iconStyles.iconLive;
|
||||
if (guild) {
|
||||
text = guild.name;
|
||||
subtext = channel.name;
|
||||
channelPath = `/channels/${guild.id}/${channel.id}`;
|
||||
} else {
|
||||
text = channel.name;
|
||||
subtext = Strings.get("VOICE_CALL");
|
||||
channelPath = `/channels/@me/${channel.id}`;
|
||||
}
|
||||
switch (channel.type) {
|
||||
case 1:
|
||||
text = UserStore.getUser(channel.recipients[0]).globalName;
|
||||
subtext = Strings.get("PRIVATE_CALL");
|
||||
break;
|
||||
case 3:
|
||||
text = channel.name || groupDMName(channel.recipients);
|
||||
subtext = Strings.get("GROUP_CALL");
|
||||
break;
|
||||
}
|
||||
let Icon = Speaker;
|
||||
if (settingsState.showStatusIcons) {
|
||||
if (voiceState.selfVideo) Icon = Video;
|
||||
else if (voiceState.deaf) Icon = ServerDeafened;
|
||||
else if (voiceState.selfDeaf) Icon = Deafened;
|
||||
else if (voiceState.mute) Icon = ServerMuted;
|
||||
else if (voiceState.selfMute) Icon = Muted;
|
||||
}
|
||||
return BdApi.React.createElement(
|
||||
"div",
|
||||
{
|
||||
className,
|
||||
onClick: (e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (channelPath) transitionTo?.(channelPath);
|
||||
}
|
||||
},
|
||||
BdApi.React.createElement(
|
||||
betterdiscord.Components.Tooltip,
|
||||
{
|
||||
text: BdApi.React.createElement("div", { className: iconStyles.tooltip }, BdApi.React.createElement("div", { className: iconStyles.header, style: { fontWeight: "600" } }, text), BdApi.React.createElement("div", { className: iconStyles.subtext }, BdApi.React.createElement(
|
||||
ChannelIcon,
|
||||
{
|
||||
className: iconStyles.tooltipIcon,
|
||||
size: "16",
|
||||
width: "16",
|
||||
height: "16",
|
||||
color: "currentColor",
|
||||
channel
|
||||
}
|
||||
), BdApi.React.createElement("div", { style: { fontWeight: "400" } }, subtext)))
|
||||
},
|
||||
(props2) => BdApi.React.createElement("div", { ...props2 }, !voiceState.selfStream ? BdApi.React.createElement(Icon, { size: "14", width: "14", height: "14", color: "currentColor" }) : Strings.get("LIVE"))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// index.tsx
|
||||
class VoiceActivity {
|
||||
meta;
|
||||
contextMenuUnpatches = new Set();
|
||||
constructor(meta) {
|
||||
this.meta = meta;
|
||||
}
|
||||
start() {
|
||||
showChangelog(changelog, this.meta);
|
||||
betterdiscord.DOM.addStyle(
|
||||
styles() + `${memberSelectors?.children}:empty { margin-left: 0; } ${memberSelectors?.children} { display: flex; gap: 8px; } ${memberSelectors?.layout} { width: 100%; }`
|
||||
);
|
||||
Strings.subscribe();
|
||||
this.patchPeopleListItem();
|
||||
this.patchMemberListItem();
|
||||
this.patchPrivateChannel();
|
||||
this.patchChannelContextMenu();
|
||||
this.patchGuildContextMenu();
|
||||
betterdiscord.Patcher.instead(VoiceStateStore, "getDiscoverableVoiceState", (_, [guildId, userId]) => {
|
||||
return VoiceStateStore.getDiscoverableVoiceStateForUser(userId);
|
||||
});
|
||||
}
|
||||
patchMemberListItem() {
|
||||
if (!MemberListItem) return;
|
||||
betterdiscord.Patcher.after(MemberListItem, "type", (_, [props], ret) => {
|
||||
if (!props.user) return ret;
|
||||
const children = ret.props.children;
|
||||
ret.props.children = (childrenProps) => {
|
||||
const childrenRet = children(childrenProps);
|
||||
const target = betterdiscord.Utils.findInTree(childrenRet, (x) => x.props?.avatar && x.props?.decorators, {
|
||||
walkable: ["props", "children"]
|
||||
});
|
||||
const icon = BdApi.React.createElement(VoiceIcon, { userId: props.user.id, context: "memberlist" });
|
||||
Array.isArray(target.props.children) ? target.props.children.unshift(icon) : target.props.children = [icon];
|
||||
return childrenRet;
|
||||
};
|
||||
});
|
||||
}
|
||||
patchPrivateChannel() {
|
||||
if (!PrivateChannel) return;
|
||||
const patchType = (props, ret) => {
|
||||
if (props.channel.type !== 1) return;
|
||||
const target = betterdiscord.Utils.findInTree(ret, (e) => typeof e?.props?.children !== "function", {
|
||||
walkable: ["children", "props"]
|
||||
})?.props?.children ?? ret;
|
||||
if (!target) return;
|
||||
const children = target.props.children;
|
||||
target.props.children = (childrenProps) => {
|
||||
const childrenRet = children(childrenProps);
|
||||
const privateChannel = betterdiscord.Utils.findInTree(childrenRet, (e) => e?.children?.props?.avatar, {
|
||||
walkable: ["children", "props"]
|
||||
});
|
||||
privateChannel.children = [
|
||||
privateChannel.children,
|
||||
BdApi.React.createElement("div", { className: iconStyles.iconContainer }, BdApi.React.createElement(VoiceIcon, { userId: props.user.id, context: "dmlist" }))
|
||||
];
|
||||
return childrenRet;
|
||||
};
|
||||
};
|
||||
let patchedType;
|
||||
betterdiscord.Patcher.after(...PrivateChannel, (_, __, containerRet) => {
|
||||
let target = containerRet.children || containerRet;
|
||||
if (patchedType) {
|
||||
target.type = patchedType;
|
||||
return containerRet;
|
||||
}
|
||||
const original = target.type;
|
||||
patchedType = (props) => {
|
||||
const ret = original(props);
|
||||
patchType(props, ret);
|
||||
return ret;
|
||||
};
|
||||
target.type = patchedType;
|
||||
});
|
||||
}
|
||||
patchPeopleListItem() {
|
||||
if (!PeopleListItem) return;
|
||||
betterdiscord.Patcher.after(PeopleListItem.prototype, "render", (that, _, ret) => {
|
||||
if (!that.props.user) return;
|
||||
const children = ret.props.children;
|
||||
ret.props.children = (childrenProps) => {
|
||||
const childrenRet = children(childrenProps);
|
||||
betterdiscord.Utils.findInTree(childrenRet, (i) => Array.isArray(i), { walkable: ["props", "children"] }).splice(
|
||||
1,
|
||||
0,
|
||||
BdApi.React.createElement("div", { className: `${iconStyles.iconContainer} ${iconStyles.peopleListIcon}` }, BdApi.React.createElement(VoiceIcon, { userId: that.props.user.id, context: "peoplelist" }))
|
||||
);
|
||||
return childrenRet;
|
||||
};
|
||||
});
|
||||
}
|
||||
patchChannelContextMenu() {
|
||||
const unpatch = betterdiscord.ContextMenu.patch("channel-context", (ret, props) => {
|
||||
if (!Settings.get("ignoreEnabled")) return ret;
|
||||
if (props.channel.type !== 2 && props.channel.type !== 13) return ret;
|
||||
const { ignoredChannels } = Settings.useSettingsState("ignoredChannels");
|
||||
const ignored = ignoredChannels.includes(props.channel.id);
|
||||
const menuItem = betterdiscord.ContextMenu.buildItem({
|
||||
type: "toggle",
|
||||
label: Strings.get("CONTEXT_IGNORE"),
|
||||
id: "voiceactivity-ignore",
|
||||
checked: ignored,
|
||||
action: () => {
|
||||
if (ignored) {
|
||||
const newIgnoredChannels = ignoredChannels.filter((id) => id !== props.channel.id);
|
||||
Settings.set("ignoredChannels", newIgnoredChannels);
|
||||
} else {
|
||||
const newIgnoredChannels = [...ignoredChannels, props.channel.id];
|
||||
Settings.set("ignoredChannels", newIgnoredChannels);
|
||||
}
|
||||
}
|
||||
});
|
||||
ret.props.children[3].props.children.splice(4, 0, menuItem);
|
||||
});
|
||||
this.contextMenuUnpatches.add(unpatch);
|
||||
}
|
||||
patchGuildContextMenu() {
|
||||
const unpatch = betterdiscord.ContextMenu.patch("guild-context", (ret, props) => {
|
||||
if (!props.guild) return ret;
|
||||
if (!Settings.get("ignoreEnabled")) return ret;
|
||||
const { ignoredGuilds } = Settings.useSettingsState("ignoredGuilds");
|
||||
const ignored = ignoredGuilds.includes(props.guild.id);
|
||||
const menuItem = betterdiscord.ContextMenu.buildItem({
|
||||
type: "toggle",
|
||||
label: Strings.get("CONTEXT_IGNORE"),
|
||||
id: "voiceactivity-ignore",
|
||||
checked: ignored,
|
||||
action: () => {
|
||||
if (ignored) {
|
||||
const newIgnoredGuilds = ignoredGuilds.filter((id) => id !== props.guild.id);
|
||||
Settings.set("ignoredGuilds", newIgnoredGuilds);
|
||||
} else {
|
||||
const newIgnoredGuilds = [...ignoredGuilds, props.guild.id];
|
||||
Settings.set("ignoredGuilds", newIgnoredGuilds);
|
||||
}
|
||||
}
|
||||
});
|
||||
ret.props.children[2].props.children.push(menuItem);
|
||||
});
|
||||
this.contextMenuUnpatches.add(unpatch);
|
||||
}
|
||||
stop() {
|
||||
betterdiscord.DOM.removeStyle();
|
||||
betterdiscord.Patcher.unpatchAll();
|
||||
this.contextMenuUnpatches.forEach((unpatch) => unpatch());
|
||||
this.contextMenuUnpatches.clear();
|
||||
Strings.unsubscribe();
|
||||
}
|
||||
getSettingsPanel() {
|
||||
return buildSettingsPanel(Settings, [
|
||||
{
|
||||
id: "showMemberListIcons",
|
||||
type: "switch",
|
||||
name: Strings.get("SETTINGS_ICONS"),
|
||||
note: Strings.get("SETTINGS_ICONS_NOTE")
|
||||
},
|
||||
{
|
||||
id: "showDMListIcons",
|
||||
type: "switch",
|
||||
name: Strings.get("SETTINGS_DM_ICONS"),
|
||||
note: Strings.get("SETTINGS_DM_ICONS_NOTE")
|
||||
},
|
||||
{
|
||||
id: "showPeopleListIcons",
|
||||
type: "switch",
|
||||
name: Strings.get("SETTINGS_PEOPLE_ICONS"),
|
||||
note: Strings.get("SETTINGS_PEOPLE_ICONS_NOTE")
|
||||
},
|
||||
{
|
||||
id: "currentChannelColor",
|
||||
type: "switch",
|
||||
name: Strings.get("SETTINGS_COLOR"),
|
||||
note: Strings.get("SETTINGS_COLOR_NOTE")
|
||||
},
|
||||
{
|
||||
id: "showStatusIcons",
|
||||
type: "switch",
|
||||
name: Strings.get("SETTINGS_STATUS"),
|
||||
note: Strings.get("SETTINGS_STATUS_NOTE")
|
||||
},
|
||||
{
|
||||
id: "currentUserIcon",
|
||||
type: "switch",
|
||||
name: Strings.get("SETTINGS_CURRENT_USER"),
|
||||
note: Strings.get("SETTINGS_CURRENT_USER_NOTE")
|
||||
},
|
||||
{
|
||||
id: "ignoreEnabled",
|
||||
type: "switch",
|
||||
name: Strings.get("SETTINGS_IGNORE"),
|
||||
note: Strings.get("SETTINGS_IGNORE_NOTE")
|
||||
}
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = VoiceActivity;
|
||||
|
||||
/*@end@*/
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "1.2.5",
|
||||
"hasShownChangelog": true
|
||||
},
|
||||
"settings": {
|
||||
"maxUsersShown": 6,
|
||||
"avatarSize": 16,
|
||||
"reactionThreshold": 10,
|
||||
"userThreshold": 100,
|
||||
"useHighestUserCount": true,
|
||||
"showSelf": false,
|
||||
"showBots": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
/**
|
||||
* @name WiderUserArea
|
||||
* @version 0.2.5
|
||||
* @description A BetterDiscord plugin that expands your user area into the server list, compatible with most themes
|
||||
* @author TheLazySquid
|
||||
* @authorId 619261917352951815
|
||||
* @website https://github.com/TheLazySquid/DiscordWiderUserArea
|
||||
* @source https://github.com/TheLazySquid/DiscordWiderUserArea/blob/main/build/WiderUserArea.plugin.js
|
||||
*/
|
||||
module.exports = class {
|
||||
constructor() {
|
||||
'use strict';
|
||||
|
||||
var styles = ":root {\r\n --user-area-bottom: 0;\r\n --user-area-left: 0;\r\n}\r\n\r\nnav[class*=\"guilds_\"] {\r\n height: var(--sidebar-height);\r\n}\r\n\r\n[class*=\"sidebar_\"] {\r\n height: calc(var(--sidebar-height) - var(--notices-height));\r\n}\r\n\r\n/* user area */\r\nsection[class*=\"panels_\"] {\r\n position: fixed;\r\n overflow: hidden;\r\n bottom: var(--user-area-bottom);\r\n left: var(--user-area-left);\r\n width: var(--user-area-width);\r\n}\r\n\r\nsection[class*=\"panels_\"] [class*=\"avatarWrapper_\"] {\r\n flex-grow: 1;\r\n}\r\n\r\n/* prevent the user info popout from clipping */\r\n[class*=\"accountProfilePopoutWrapper\"] {\r\n left: 0;\r\n}";
|
||||
|
||||
const userAreaSelector = 'section[class*="panels_"]';
|
||||
const serverListSelector = 'nav[class*="guilds_"]';
|
||||
const containerSelector = `div:has(> ${serverListSelector})`;
|
||||
const layerSelector = `[class*="baseLayer"]`;
|
||||
const channelsSelector = '[class*="sidebar_"] > nav';
|
||||
const scaleRegex = /scale\((.*)\)/;
|
||||
const UAButtonsSelector = 'div[class*="avatarWrapper_"] + div';
|
||||
const firstServerListSelector = `${serverListSelector}:first-child`;
|
||||
const secondServerListSelector = `${serverListSelector}:nth-child(2)`;
|
||||
|
||||
function scaleDOMRect(rect, scale, scaleCenterX, scaleCenterY) {
|
||||
// Calculate the distance of the rect from the scale center
|
||||
const distX = rect.x - scaleCenterX;
|
||||
const distY = rect.y - scaleCenterY;
|
||||
// Scale the distances
|
||||
const newDistX = distX * scale;
|
||||
const newDistY = distY * scale;
|
||||
// Calculate the new position of the rect
|
||||
const newX = scaleCenterX + newDistX;
|
||||
const newY = scaleCenterY + newDistY;
|
||||
// Scale the dimensions of the rect
|
||||
const newWidth = rect.width * scale;
|
||||
const newHeight = rect.height * scale;
|
||||
// Create a new DOMRect with the new dimensions and position
|
||||
const newRect = new DOMRect(newX, newY, newWidth, newHeight);
|
||||
return newRect;
|
||||
}
|
||||
|
||||
const createCallbackHandler = (callbackName) => {
|
||||
const fullName = callbackName + "Callbacks";
|
||||
this[fullName] = [];
|
||||
this[callbackName] = () => {
|
||||
for (let i = 0; i < this[fullName].length; i++) {
|
||||
this[fullName][i].callback();
|
||||
}
|
||||
};
|
||||
return (callback, once, id) => {
|
||||
let object = { callback };
|
||||
const delCallback = () => {
|
||||
this[fullName].splice(this[fullName].indexOf(object), 1);
|
||||
};
|
||||
// if once is true delete it after use
|
||||
if (once === true) {
|
||||
object.callback = () => {
|
||||
callback();
|
||||
delCallback();
|
||||
};
|
||||
}
|
||||
if (id) {
|
||||
object.id = id;
|
||||
for (let i = 0; i < this[fullName].length; i++) {
|
||||
if (this[fullName][i].id === id) {
|
||||
this[fullName][i] = object;
|
||||
return delCallback;
|
||||
}
|
||||
}
|
||||
}
|
||||
this[fullName].push(object);
|
||||
return delCallback;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Takes a callback and fires it when the plugin is started
|
||||
* @param callback - The callback to be fired
|
||||
* @param once - If true, the callback will be deleted after use
|
||||
* @param id - The id of the callback - if it already exists, it will be replaced
|
||||
* @returns A function to delete the callback
|
||||
*/
|
||||
const onStart = createCallbackHandler("start");
|
||||
/**
|
||||
* Takes a callback and fires it when the plugin is stopped
|
||||
* @param callback - The callback to be fired
|
||||
* @param once - If true, the callback will be deleted after use
|
||||
* @param id - The id of the callback - if it already exists, it will be replaced
|
||||
* @returns A function to delete the callback
|
||||
*/
|
||||
const onStop = createCallbackHandler("stop");
|
||||
/**
|
||||
* Takes a callback and fires it when the user navigates
|
||||
* @param callback - The callback to be fired
|
||||
* @param once - If true, the callback will be deleted after use
|
||||
* @param id - The id of the callback - if it already exists, it will be replaced
|
||||
* @returns A function to delete the callback
|
||||
*/
|
||||
const onSwitch = createCallbackHandler("onSwitch");
|
||||
|
||||
/**
|
||||
* Watches for an element with a given selector to be added to the DOM
|
||||
* @param selector The CSS selector to watch
|
||||
* @param callback The callback to run whenever the matching element is added to the DOM
|
||||
* @returns A function to stop watching
|
||||
*/
|
||||
function watchElement(selector, callback) {
|
||||
let observer = new MutationObserver((mutations) => {
|
||||
for (let mutation of mutations) {
|
||||
if (mutation.addedNodes.length) {
|
||||
for (let node of mutation.addedNodes) {
|
||||
if (!(node instanceof HTMLElement))
|
||||
continue;
|
||||
if (node.matches && node.matches(selector)) {
|
||||
callback(node);
|
||||
}
|
||||
if (node.querySelectorAll) {
|
||||
for (let element of node.querySelectorAll(selector)) {
|
||||
callback(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
let startDispose = onStart(() => {
|
||||
observer.observe(document.body, { childList: true, subtree: true });
|
||||
for (let element of document.querySelectorAll(selector)) {
|
||||
callback(element);
|
||||
}
|
||||
});
|
||||
let stopDispose = onStop(() => {
|
||||
observer.disconnect();
|
||||
});
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
startDispose();
|
||||
stopDispose();
|
||||
};
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
let baseChannelHeight = 0;
|
||||
let baseChannelWidth = 0;
|
||||
let varsSet = new Set();
|
||||
const recalcDebounce = BdApi.Utils.debounce(() => {
|
||||
const userArea = document.querySelector(userAreaSelector);
|
||||
if (userArea)
|
||||
userAreaFound(userArea);
|
||||
}, 150);
|
||||
watchElement(userAreaSelector, userAreaFound);
|
||||
let userAreaObserver = new ResizeObserver(entries => {
|
||||
for (let entry of entries) {
|
||||
updateVar('--sidebar-height', `${baseChannelHeight - entry.contentRect.height}px`);
|
||||
}
|
||||
});
|
||||
let channelsRect;
|
||||
let secondChannelsRect;
|
||||
let channelsObserver = new ResizeObserver(entries => {
|
||||
for (let entry of entries) {
|
||||
channelsRect = entry.contentRect;
|
||||
// hide everything but the profile picture if the channel list is hidden
|
||||
let btns = document.querySelector(UAButtonsSelector);
|
||||
if (entry.contentRect.width === 0) {
|
||||
if (btns)
|
||||
btns.style.display = 'none';
|
||||
}
|
||||
else {
|
||||
if (btns)
|
||||
btns.style.display = '';
|
||||
}
|
||||
let newWidth = entry.contentRect.right - baseChannelWidth;
|
||||
if (secondChannelsRect)
|
||||
newWidth += secondChannelsRect.width;
|
||||
updateVar('--user-area-width', `${newWidth}px`);
|
||||
}
|
||||
});
|
||||
watchElement(channelsSelector, (element) => {
|
||||
channelsObserver.disconnect();
|
||||
channelsObserver.observe(element);
|
||||
});
|
||||
let secondServerListObserver = new ResizeObserver((entries) => {
|
||||
if (!channelsRect)
|
||||
return;
|
||||
for (let entry of entries) {
|
||||
secondChannelsRect = entry.contentRect;
|
||||
let width = entry.contentRect.width;
|
||||
updateVar('--user-area-width', `${channelsRect.right - baseChannelWidth + width}px`);
|
||||
}
|
||||
});
|
||||
watchElement(secondServerListSelector, (element) => {
|
||||
secondServerListObserver.disconnect();
|
||||
secondServerListObserver.observe(element);
|
||||
});
|
||||
let themesObserver = new MutationObserver(async () => {
|
||||
// wait a bit for it to apply
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
console.log('theme changed');
|
||||
// recalculate the user area
|
||||
const userArea = document.querySelector(userAreaSelector);
|
||||
if (userArea)
|
||||
userAreaFound(userArea);
|
||||
});
|
||||
let noticesHeight = 0;
|
||||
let noticesObserver = new ResizeObserver((entries) => {
|
||||
for (let entry of entries) {
|
||||
noticesHeight = entry.contentRect.height;
|
||||
updateVar('--notices-height', `${entry.contentRect.height}px`);
|
||||
}
|
||||
});
|
||||
watchElement("#bd-notices", (el) => {
|
||||
noticesObserver.disconnect();
|
||||
noticesObserver.observe(el);
|
||||
});
|
||||
function updateVar(name, value) {
|
||||
BdApi.DOM.removeStyle(`wua-${name}`);
|
||||
BdApi.DOM.addStyle(`wua-${name}`, `:root { ${name}: ${value} !important; }`);
|
||||
varsSet.add(name);
|
||||
}
|
||||
onSwitch(() => {
|
||||
// hacky fix for betteranimations sometimes giving a parent the "perspective" style breaking the fixed positioning
|
||||
setTimeout(() => {
|
||||
const userArea = document.querySelector(userAreaSelector);
|
||||
let parent = userArea?.parentElement;
|
||||
while (parent) {
|
||||
if (parent.style.perspective) {
|
||||
parent.style.perspective = '';
|
||||
break;
|
||||
}
|
||||
parent = parent.parentElement;
|
||||
}
|
||||
userAreaFound(userArea);
|
||||
}, 5100);
|
||||
});
|
||||
function userAreaFound(element) {
|
||||
// remove the old style if it exists
|
||||
BdApi.DOM.removeStyle('wua-styles');
|
||||
const layer = document.querySelector(layerSelector);
|
||||
const container = document.querySelector(containerSelector);
|
||||
const serverList = document.querySelector(firstServerListSelector);
|
||||
const channels = document.querySelector(channelsSelector);
|
||||
const secondServerList = document.querySelector(secondServerListSelector);
|
||||
const layerScale = 1 / parseFloat(scaleRegex.exec(layer.style.transform)?.[1] ?? '1');
|
||||
const layerRect = layer.getBoundingClientRect();
|
||||
const centerX = layerRect.left + layerRect.width / 2;
|
||||
const centerY = layerRect.top + layerRect.height / 2;
|
||||
// this scaling is neccesary for compatibility with betterAnimations,
|
||||
// which sometimes scales the layer when in a settings menu, which is where theme switches would be.
|
||||
const rect = scaleDOMRect(element.getBoundingClientRect(), layerScale, centerX, centerY);
|
||||
const containerRect = scaleDOMRect(container.getBoundingClientRect(), layerScale, centerX, centerY);
|
||||
const serverListRect = scaleDOMRect(serverList.getBoundingClientRect(), layerScale, centerX, centerY);
|
||||
const channelsRect = scaleDOMRect(channels.getBoundingClientRect(), layerScale, centerX, centerY);
|
||||
// figure out how far from the bottom of the screen the user area is
|
||||
const bottom = containerRect.bottom - rect.bottom;
|
||||
baseChannelHeight = channelsRect.height + rect.height;
|
||||
baseChannelWidth = serverListRect.left - channelsRect.left;
|
||||
if (secondServerList) {
|
||||
const secondServerListRect = scaleDOMRect(secondServerList.getBoundingClientRect(), layerScale, centerX, centerY);
|
||||
baseChannelWidth += secondServerListRect.width;
|
||||
}
|
||||
// add the new style
|
||||
BdApi.DOM.addStyle('wua-styles', styles);
|
||||
updateVar('--sidebar-height', `${channelsRect.height + noticesHeight}px`);
|
||||
updateVar('--user-area-width', `${channelsRect.right - serverListRect.left}px`);
|
||||
updateVar('--user-area-left', `${serverListRect.left}px`);
|
||||
updateVar('--user-area-bottom', `${bottom}px`);
|
||||
userAreaObserver.observe(element);
|
||||
}
|
||||
onStart(() => {
|
||||
window.addEventListener('resize', recalcDebounce);
|
||||
updateVar('--notices-height', '0px');
|
||||
themesObserver.observe(document.querySelector("bd-themes"), { childList: true, subtree: true });
|
||||
});
|
||||
onStop(() => {
|
||||
userAreaObserver.disconnect();
|
||||
channelsObserver.disconnect();
|
||||
themesObserver.disconnect();
|
||||
secondServerListObserver.disconnect();
|
||||
noticesObserver.disconnect();
|
||||
BdApi.DOM.removeStyle('wua-styles');
|
||||
for (let varName of varsSet) {
|
||||
BdApi.DOM.removeStyle(`wua-${varName}`);
|
||||
}
|
||||
window.removeEventListener('resize', recalcDebounce);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"currentVersionInfo": {
|
||||
"version": "2.0.23",
|
||||
"hasShownChangelog": true
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @name betterdiscord-google-fonts
|
||||
* @version 1.0.2
|
||||
* @description Allows use of Google Fonts through a simple settings UI
|
||||
* @author Mike Orozco
|
||||
* @authorLink https://mikeorozco.dev
|
||||
* @authorId 142347724392497152
|
||||
* @updateUrl https://raw.githubusercontent.com/notmike101/betterdiscord-google-fonts/release/betterdiscord-google-fonts.plugin.js
|
||||
* @source https://github.com/notmike101/betterdiscord-google-fonts
|
||||
*/
|
||||
|
||||
// sass:/home/runner/work/betterdiscord-google-fonts/betterdiscord-google-fonts/src/styles/Global.scss
|
||||
var Global_default = `
|
||||
`;
|
||||
|
||||
// _cqfx4ul6y:/home/runner/work/betterdiscord-google-fonts/betterdiscord-google-fonts/src/templates/SettingsPanel.html
|
||||
var SettingsPanel_default = '<div class="google-font-settings">\n <div class="bd-setting-item">\n <div class="bd-setting-header">\n <label for="google-font-select" class="bd-setting-title">Selected Font</label>\n </div>\n <div class="bd-select">\n <div class="bd-select-header-custom">\n <div class="bd-select-value">{{ CURRENT_FONT }}</div>\n <svg class="bd-select-arrow" fill="currentColor" viewBox="0 0 24 24">\n <path d="M8.12 9.29L12 13.17l3.88-3.88c.39-.39 1.02-.39 1.41 0 .39.39.39 1.02 0 1.41l-4.59 4.59c-.39.39-1.02.39-1.41 0L6.7 10.7c-.39-.39-.39-1.02 0-1.41.39-.38 1.03-.39 1.42 0z"></path>\n </svg>\n </div>\n <div class="bd-select-options"></div>\n </div>\n </div>\n</div>\n';
|
||||
|
||||
// sass:/home/runner/work/betterdiscord-google-fonts/betterdiscord-google-fonts/src/styles/SettingsPanel.scss
|
||||
var SettingsPanel_default2 = `
|
||||
.google-font-settings .bd-setting-item .bd-select {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.google-font-settings .bd-setting-item .bd-select .bd-select-header-custom {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
.google-font-settings .bd-setting-item .bd-select .bd-select-header-custom .bd-select-arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.google-font-settings .bd-setting-item .bd-select .bd-select-options {
|
||||
display: none;
|
||||
position: initial;
|
||||
z-index: 0;
|
||||
}`;
|
||||
|
||||
// src/DiscordPlugin.ts
|
||||
var BdApi = window.BdApi || {};
|
||||
var DiscordPlugin = class {
|
||||
selectedFont;
|
||||
fonts;
|
||||
constructor() {
|
||||
this.selectedFont = null;
|
||||
this.fonts = [];
|
||||
}
|
||||
getName() {
|
||||
return "Google Fonts";
|
||||
}
|
||||
async load() {
|
||||
}
|
||||
async start() {
|
||||
BdApi.injectCSS("bd-google-fonts-global-css", Global_default);
|
||||
BdApi.injectCSS("bd-google-fonts-settingspanel", SettingsPanel_default2);
|
||||
this.fonts = await this.getAvailableFonts();
|
||||
this.selectedFont = BdApi.getData("betterdiscord-google-fonts", "font");
|
||||
this.updateDomFont();
|
||||
}
|
||||
stop() {
|
||||
BdApi.clearCSS("bd-google-fonts-global-css");
|
||||
BdApi.clearCSS("bd-google-fonts-custom-font");
|
||||
BdApi.clearCSS("bd-google-fonts-settingspanel");
|
||||
}
|
||||
async getAvailableFonts() {
|
||||
const existingData = BdApi.getData("betterdiscord-google-fonts", "fonts");
|
||||
const lastFetchTime = BdApi.getData("betterdiscord-google-fonts", "lastFetchTime");
|
||||
const lastFetchExpiration = new Date(lastFetchTime);
|
||||
lastFetchExpiration.setDate(lastFetchExpiration.getDate() + 1 * 7);
|
||||
if (!existingData || lastFetchTime < lastFetchExpiration) {
|
||||
const response = await fetch("https://www.googleapis.com/webfonts/v1/webfonts?key=AIzaSyCfxANDwWkAP3JjzGLv5UOPYcPEwaVAz3k");
|
||||
const json = await response.json();
|
||||
const fonts = json.items.map((font) => font.family);
|
||||
fonts.unshift("Default");
|
||||
BdApi.setData("betterdiscord-google-fonts", "fonts", fonts);
|
||||
BdApi.setData("betterdiscord-google-fonts", "lastFetchTime", new Date().getTime());
|
||||
return fonts;
|
||||
}
|
||||
return existingData;
|
||||
}
|
||||
updateDomFont() {
|
||||
BdApi.clearCSS("bd-google-fonts-custom-font");
|
||||
if (this.selectedFont) {
|
||||
const newStyle = `
|
||||
@import url('https://fonts.googleapis.com/css?family=${this.selectedFont}');
|
||||
|
||||
*:not([class*="hljs"]):not(code){
|
||||
font-family: ${this.selectedFont} !important;
|
||||
}
|
||||
`;
|
||||
BdApi.injectCSS("bd-google-fonts-custom-font", newStyle);
|
||||
}
|
||||
}
|
||||
getSettingsPanel() {
|
||||
const template = document.createElement("template");
|
||||
const currentFontString = this.selectedFont ? this.selectedFont : "Default";
|
||||
template.innerHTML = SettingsPanel_default.replace("{{ CURRENT_FONT }}", currentFontString);
|
||||
const settingsPanel = template.content.firstElementChild;
|
||||
const fontSelection = settingsPanel.querySelector(".bd-select-options");
|
||||
settingsPanel.querySelector(".bd-select").addEventListener("click", () => {
|
||||
const dropdown = settingsPanel.querySelector(".bd-select-options");
|
||||
if (dropdown.style.display === "none") {
|
||||
dropdown.style.display = "block";
|
||||
} else {
|
||||
dropdown.style.display = "none";
|
||||
}
|
||||
});
|
||||
this.fonts.forEach((font) => {
|
||||
const option = document.createElement("div");
|
||||
option.classList.add("bd-select-option");
|
||||
option.textContent = font;
|
||||
option.addEventListener("click", (e) => {
|
||||
const target = e.target;
|
||||
const selectedFont = target.textContent;
|
||||
if (selectedFont === "Default") {
|
||||
this.selectedFont = null;
|
||||
} else {
|
||||
this.selectedFont = selectedFont;
|
||||
}
|
||||
this.updateDomFont();
|
||||
document.querySelector(".google-font-settings .bd-select-value").textContent = selectedFont;
|
||||
BdApi.setData("betterdiscord-google-fonts", "font", this.selectedFont);
|
||||
});
|
||||
fontSelection.appendChild(option);
|
||||
});
|
||||
return settingsPanel;
|
||||
}
|
||||
};
|
||||
module.exports = DiscordPlugin;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* @name FVUI
|
||||
* @author feorev
|
||||
* @description Blur is the New Black
|
||||
* @version 2.0.0
|
||||
* @authorId 489785940546551831
|
||||
* @invite baEMQkgswT
|
||||
* @source https://github.com/FeoreV/Themes/tree/main/Discord/FVUI
|
||||
*/
|
||||
/* ! DO NOT TOUCH ! */
|
||||
@import url(https://feorev.github.io/Themes/Discord/FVUI/Cores/preload.css);
|
||||
@import url(https://feorev.github.io/Themes/Discord/FVUI/assets/Versions/v2.css);
|
||||
|
||||
/*=============================================
|
||||
= Info =
|
||||
==============================================*
|
||||
DiscordServer: https://discord.com/invite/baEMQkgswT
|
||||
DM - feorev
|
||||
Site - https://feorev.github.io/
|
||||
ThemeEditor - https://bdeditor.dev/theme/FVUI
|
||||
|
||||
Due to the inability to update the theme file frequently, many new additions to the theme will be posted on the discord server.
|
||||
The FVUI theme extends not only to discord, but also to other sites and areas. You can find a complete list of themes on the discord server.
|
||||
|
||||
|
||||
|
||||
/*=============================================
|
||||
= FAQ =
|
||||
==============================================*
|
||||
|
||||
/*---------- How to enable another subtheme? ----------*
|
||||
|
||||
IT IS RECOMMENDED TO USE AN EDITOR ( https://bdeditor.dev/theme/FVUI )
|
||||
|
||||
Select import and press ctrl+/
|
||||
|
||||
Enabled - @import url(...)
|
||||
Disabled - /*@import url(...)*/
|
||||
|
||||
|
||||
/*---------- I want ... ----------
|
||||
Make the background a picture - enable WIN11
|
||||
Make discord transparent - enable Mica
|
||||
Change background picture - Change the settings of the win11 subtheme - the --dark/light BG variable
|
||||
|
||||
/*---------- Any other questions? ----------
|
||||
Join the discord server c:
|
||||
https://discord.com/invite/baEMQkgswT
|
||||
|
||||
|
||||
|
||||
/*=============================================
|
||||
= Subthemes to choose =
|
||||
=============================================*/
|
||||
|
||||
/*---------- Default ----------*/
|
||||
/* Default */
|
||||
@import url(https://feorev.github.io/Themes/Discord/FVUI/assets/SubThemes/Default.css);
|
||||
/* Lite */
|
||||
/* @import url(https://feorev.github.io/Themes/Discord/FVUI/assets/SubThemes/Default_lite.css); */
|
||||
|
||||
/*---------- CustomBackground ----------*/
|
||||
/* WIN11 */
|
||||
/* @import url(https://feorev.github.io/Themes/Discord/FVUI/assets/SubThemes/CustomBackground.css); */
|
||||
/* Lite11 */
|
||||
/* @import url(https://feorev.github.io/Themes/Discord/FVUI/assets/SubThemes/CustomBackground_lite.css); */
|
||||
|
||||
/*---------- Other ----------*/
|
||||
/*MICA (Required "Mica For Everyone" and enabling transparency (Settings=>BD=>Settings=>Window preferences=>Enable transparency)*/
|
||||
/* @import url(https://feorev.github.io/Themes/Discord/FVUI/assets/SubThemes/Mica.css); */
|
||||
|
||||
|
||||
|
||||
/*=============================================
|
||||
= Addons =
|
||||
=============================================*/
|
||||
|
||||
/* Events (Any events and decorations for the holidays. For example, snow and New Year's attributes for the new year.) */
|
||||
@import url(https://feorev.github.io/Themes/Discord/FVUI/Addons/Events/Events.css);
|
||||
|
||||
/* ServerRings */
|
||||
@import url(https://feorev.github.io/Themes/Discord/FVUI/Addons/ServerRings.css);
|
||||
|
||||
/* RadialStatus */
|
||||
@import url(https://feorev.github.io/Themes/Discord/FVUI/Addons/RadialStatus.css);
|
||||
|
||||
/* MaterialYou (The theme color scheme adjusts to the accent color) */
|
||||
@import url(https://feorev.github.io/Themes/Discord/FVUI/Addons/MaterialYou.css); */
|
||||
|
||||
/* ModularDesign (Adds outline to main sections) */
|
||||
/* @import url(https://feorev.github.io/Themes/Discord/FVUI/Addons/ModularDesign.css); */
|
||||
|
||||
/* TopUserPanel (Moves the userpanel to the top corner) */
|
||||
/* @import url(https://feorev.github.io/Themes/Discord/FVUI/Addons/TopUserPanel.css); */
|
||||
|
||||
/* HorizontalServerList (Moves serverlist to the top or bottom corner. For FVUI, it is recommended to use this version of HSL, and not the official one.) */
|
||||
/* @import url(https://feorev.github.io/Themes/Discord/FVUI/Addons/HSL/HSL_top.css); */
|
||||
/* @import url(https://feorev.github.io/Themes/Discord/FVUI/Addons/HSL/HSL_bottom.css); */
|
||||
|
||||
/* TitleIsland */
|
||||
/* @import url(https://feorev.github.io/Themes/Discord/FVUI/Addons/TitleIsland.css); */
|
||||
|
||||
|
||||
|
||||
/*=============================================
|
||||
= SubThemes Settings =
|
||||
=============================================*/
|
||||
|
||||
/* Theme editor - https://bdeditor.dev/theme/FVUI */
|
||||
|
||||
/*---------- General ----------*/
|
||||
:root{
|
||||
--cursor : url('https://feorev.github.io/Themes/Discord/FVUI/assets/Cursor.cur'); /* Link to cursor / unset - to set standard */
|
||||
--font : "Comfortaa"; /* The font must be pre-installed or imported */
|
||||
--homeicon: url("https://feorev.github.io/Themes/Discord/FVUI/assets/HomeIcon/Icon.png"); /* Link to image */
|
||||
}
|
||||
|
||||
:root{
|
||||
--ColorOpacity : 1; /* Opacity multiplier / Default=1 (0.1-...) */
|
||||
--DisableOpacity: 0; /* Disable Opacity / Default=0 (0 or 1) */
|
||||
}
|
||||
|
||||
:root.theme-dark {
|
||||
--color1: 30, 40, 50; /* Additional BG / Default= | 30, 40, 50 | (any raw rgb value) */
|
||||
--color2: 9, 18, 24; /* Background / Default= | 9, 18, 24 | (any raw rgb value) */
|
||||
--color3: 35, 120, 200; /* Additional Color / Default= | 35, 120, 200 | (any raw rgb value) */
|
||||
--color4: 63, 43, 150; /* Gradient Color / Default= | 63, 43, 150 | (any raw rgb value) */
|
||||
}
|
||||
:root.theme-light {
|
||||
--color1: 211, 204, 227; /* Additional BG / Default= | 211, 204, 227 | (any raw rgb value) */
|
||||
--color2: 219, 219, 219; /* Background / Default= | 219, 219, 219 | (any raw rgb value) */
|
||||
--color3: 96, 205, 255; /* Additional Color / Default= | 96,205,255 | (any raw rgb value) */
|
||||
--color4: 63, 43, 150; /* Gradient Color / Default= | 63, 43, 150 | (any raw rgb value) */
|
||||
}
|
||||
|
||||
/*---------- CustomBackground ----------*/
|
||||
:root{
|
||||
--DarkBG : url(https://feorev.github.io/Themes/Discord/FVUI/assets/Wallpapers/dark.avif); /* Link to background image / Default= url(https://feorev.github.io/Themes/Discord/assets/Wallpapers/dark.avif) ( url(link) ) */
|
||||
--LightBG : url(https://feorev.github.io/Themes/Discord/FVUI/assets/Wallpapers/light.avif); /* Link to background image / Default= url(https://feorev.github.io/Themes/Discord/assets/Wallpapers/light.avif) ( url(link) ) */
|
||||
--OpacityBG: 60%; /* Background image transparency / Default=100% (0%-100%) */
|
||||
--BlurBG : 0px; /* Background image blur / Default=0px (any value in px) */
|
||||
}
|
||||
|
||||
|
||||
/*---------- Mica ----------*/
|
||||
:root{
|
||||
--BGopacity: 30%; /* Background image transparency / Default=30% (0%-100%) */
|
||||
--BGcolor : var(--color2); /* Сolor in RGB / Example = rgb(255,255,255) ( any value in RGB (like example) ) */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*=============================================
|
||||
= Addons Settings =
|
||||
=============================================*/
|
||||
|
||||
/*---------- MaterialYou ----------*/
|
||||
:root.theme-dark{ /* First 2 HSL values / Default= | 210, 68% | https://g.co/kgs/83i83K */
|
||||
--accentcolor-HUE: 210;
|
||||
--accentcolor-SATURATION: 68%;
|
||||
}
|
||||
:root.theme-light{ /* First 2 HSL values / Default= | 199, 100% | https://g.co/kgs/83i83K */
|
||||
--accentcolor-HUE: 199;
|
||||
--accentcolor-SATURATION: 100%;
|
||||
}
|
||||
|
||||
/*---------- ModularDesign ----------*/
|
||||
:root{ /*MainModules*/
|
||||
--outline : 3px; /* outline size / Default=3px (any value in px) */
|
||||
--outlineCLR : var(--color03); /* outline color / Example = rgb(255,255,255) ( any value in RGB (like example) ) */
|
||||
--outlineBR : 16px; /* outline rounding / Default=16px (any value in px) */
|
||||
--outlineMG : 2rem; /* outline margin / Default=2rem (any value in px/rem/...) */
|
||||
--outlineBS : 15px; /* outline glow / Default = 15px */
|
||||
--outlineBG : unset; /* outline content background color / Example = rgb(255,255,255) ( any value in RGB (like example) */
|
||||
--outlineBLUR: 0; /* (ONLY WIN11) backdrop blur / Default=0 ( any value in px */
|
||||
}
|
||||
|
||||
:root{ /*AdditionalModules*/
|
||||
--outline2 : 0; /* outline size / Default=0px (disabled) (any value in px) */
|
||||
--outlineCLR2 : var(--outlineCLR); /* outline color / Example = rgb(255,255,255) ( any value in RGB (like example) ) */
|
||||
--outlineBR2 : var(--outlineBR); /* outline rounding / (any value in px) */
|
||||
--outlineMG2 : var(--outlineMG); /* outline margin / (any value in px/rem/...) */
|
||||
--outlineBS2 : 0; /* outline glow / Default = 0 */
|
||||
--outlineBG2 : unset; /* outline content background color / Example = rgb(255,255,255) ( any value in RGB (like example) */
|
||||
--outlineBLUR2: 0 /* (ONLY WIN11) (Not recommended - bad performance) backdrop blur / Default=0 ( any value in px ) */
|
||||
}
|
||||
|
||||
/*---------- Have you tuned the theme well? ----------*/
|
||||
/* You can share your vision of the world in the channel of the Discord server by sending the settings: https://discord.gg/baEMQkgswT */
|
||||
|
||||
/*=============================================
|
||||
= Credits =
|
||||
= gibbu - RadialStatus / ServerRings =
|
||||
=============================================*/
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @name Translucence
|
||||
* @version 1.0.7
|
||||
* @description A translucent/frosted glass Discord theme
|
||||
* @author CapnKitten
|
||||
*
|
||||
* @website http://github.com/CapnKitten
|
||||
* @source https://github.com/CapnKitten/BetterDiscord/blob/master/Themes/Translucence/css/source.css
|
||||
* @donate https://paypal.me/capnkitten
|
||||
* @invite jzJkA6Z
|
||||
*/
|
||||
|
||||
@import url(https://capnkitten.github.io/BetterDiscord/Themes/Translucence/css/source.css);
|
||||
|
||||
:root {
|
||||
/* APP ELEMENTS */
|
||||
--app-bg: "";
|
||||
--app-blur: 6px;
|
||||
--app-margin: 24px;
|
||||
--app-radius: 8px;
|
||||
|
||||
/* ACCENT HSL AND TEXT COLOR SETTINGS */
|
||||
--accent-hue: 156;
|
||||
--accent-saturation: 50%;
|
||||
--accent-lightness: 25%;
|
||||
--accent-opacity: 1;
|
||||
--accent-text-color: hsl(0,0%,0%);
|
||||
|
||||
/* SIDEBARS AND CHAT AREA COLOR SETTINGS */
|
||||
--sidebar-color: hsl(0,0%,0%,0.4);
|
||||
--main-content-color: hsl(0,0%,0%,0.2);
|
||||
|
||||
/* MESSAGE SETTINGS */
|
||||
--message-color: hsl(0,0%,0%,0.4);
|
||||
--message-radius: 8px;
|
||||
--message-padding-top: 8px;
|
||||
--message-padding-side: 8px;
|
||||
|
||||
/* REPLY HSL COLOR SETTINGS */
|
||||
--reply-hue: 226;
|
||||
--reply-saturation: 77.4%;
|
||||
--reply-lightness: 61.8%;
|
||||
--reply-opacity: 1;
|
||||
|
||||
/* TEXTAREA SETTINGS */
|
||||
--textarea-color: 255,255,255;
|
||||
--textarea-alpha: 0.1;
|
||||
--textarea-alpha-focus: 0.15;
|
||||
--textarea-text-color: hsl(0,0%,100%);
|
||||
--textarea-radius: 22px;
|
||||
|
||||
/* CARD SETTINGS */
|
||||
--card-color: hsl(0,0%,0%,0.4);
|
||||
--card-color-hover: hsl(0,0%,0%,0.5);
|
||||
--card-color-select: hsl(0,0%,0%,0.7);
|
||||
|
||||
/* BUTTON SETTINGS */
|
||||
--button-height: 32px;
|
||||
--button-padding: 0 16px;
|
||||
--button-action-color: hsl(0,0%,0%);
|
||||
--button-radius: 16px;
|
||||
}
|
||||
|
||||
@supports (color:color-mix(in lch,red,blue)) {
|
||||
.visual-refresh .theme-dark,
|
||||
.visual-refresh.theme-dark {
|
||||
/* TEXT COLOR SETTINGS */
|
||||
--text-primary: hsl(0,0%,100%);
|
||||
--text-secondary: hsl(0,0%,77%);
|
||||
|
||||
/* CHANNEL COLOR SETTINGS */
|
||||
--channels-default: hsl(0,0%,62%);
|
||||
--channel-icon: hsl(0,0%,62%);
|
||||
|
||||
/* ICON COLOR SETTINGS */
|
||||
--icon-primary: hsl(0,0%,96%);
|
||||
--icon-secondary: hsl(0,0%,84%);
|
||||
--icon-tertiary: hsl(0,0%,71%);
|
||||
|
||||
/* INTERACTIVE COLOR SETTINGS */
|
||||
--interactive-normal: hsl(0,0%,79%);
|
||||
--interactive-hover: hsl(0,0%,91%);
|
||||
--interactive-active: hsl(0,0%,100%);
|
||||
--interactive-muted: hsl(0,0%,43%);
|
||||
|
||||
/* BACKGROUND MODIFIER SETTINGS */
|
||||
--background-modifier-hover: hsl(0,0%,100%,0.075);
|
||||
--background-modifier-selected: hsl(0,0%,100%,0.125);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @name Arindy
|
||||
* @author FeoreV
|
||||
* @version 2.0.0
|
||||
* @description Blur is the new black
|
||||
* @source https://github.com/FeoreV/Themes/tree/main/Discord/FVUI
|
||||
* @invite baEMQkgswT
|
||||
* @website https://feorev.github.io/
|
||||
* @authorId 489785940546551831
|
||||
* @BDEditor FVUI
|
||||
*/
|
||||
|
||||
@import url('https://fonts.googleapis.com/css2?family=Fira+Mono:wght@100;300;400;500;700&display=swap');
|
||||
@import url('https://feorev.github.io/Themes/Discord/FVUI/Cores/preload.css');
|
||||
@import url('https://feorev.github.io/Themes/Discord/FVUI/assets/SubThemes/Mica.css');
|
||||
@import url('https://feorev.github.io/Themes/Discord/FVUI/Addons/ModularDesign.css');
|
||||
@import url('https://feorev.github.io/Themes/Discord/FVUI/Addons/RadialStatus.css');
|
||||
@import url('https://feorev.github.io/Themes/Discord/FVUI/Addons/TitleIsland.css');
|
||||
|
||||
:root {
|
||||
--undefined: 0;
|
||||
--color1: 48,48,48;
|
||||
--color2: 0,0,0;
|
||||
--color3: 76,175,80;
|
||||
--undefined: 0;
|
||||
--ColorOpacity: 0.5;
|
||||
--DisableOpacity: 0;
|
||||
--cursor: transparent;
|
||||
--font: Fira Mono;
|
||||
--homeicon: url('https://feorev.github.io/Themes/Discord/FVUI/assets/HomeIcon/Icon.png');
|
||||
--undefined: 0;
|
||||
--FVUI: Arindy;
|
||||
--customdesc: "";
|
||||
--BGopacity: 50%;
|
||||
--BGcolor: #00000088;
|
||||
--undefined: 0;
|
||||
--outline: 1px;
|
||||
--outlineCLR: var(--color03);
|
||||
--outlineBR: 8px;
|
||||
--outlineMG: 0.7rem;
|
||||
--outlineBS: 14px;
|
||||
--outlineBGclr: unset;
|
||||
--outlineBGalpha: 1;
|
||||
--outlineBLUR: "";
|
||||
}
|
||||
|
||||
/* Any custom CSS below here */
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -15,5 +15,5 @@ exec-once = systemctl --user start hyprpolkitagent
|
||||
exec-once = hyprpaper &
|
||||
exec-once = waybar &
|
||||
exec-once = dunst &
|
||||
|
||||
exec-once = discord &
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ env = EDITOR,vim
|
||||
env = SHELL,fish
|
||||
env = BROWSER,$browser
|
||||
|
||||
env = MANGOHUD,1
|
||||
|
||||
cursor {
|
||||
no_hardware_cursors = true
|
||||
}
|
||||
@@ -13,7 +13,7 @@ input {
|
||||
follow_mouse = 1
|
||||
|
||||
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
||||
|
||||
numlock_by_default = 1
|
||||
touchpad {
|
||||
natural_scroll = false
|
||||
}
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
$mainMod = SUPER # Sets "Windows" key as main modifier
|
||||
|
||||
# Example binds, see https://wiki.hypr.land/Configuring/Binds/ for more
|
||||
bind = $mainMod, T, exec, $terminal
|
||||
bind = $mainMod, C, killactive,
|
||||
bind = $mainMod, E, exec, $fileManager
|
||||
bind = $mainMod, Q, exec, $browser
|
||||
bind = $mainMod, V, togglefloating,
|
||||
bind = $mainMod, space, exec, $menu
|
||||
bind = $mainMod, T, exec, $terminal # Open Terminal
|
||||
bind = $mainMod, C, killactive, # Kill active Window
|
||||
bind = $mainMod, E, exec, $fileManager # Open File Manager
|
||||
bind = $mainMod, Q, exec, $browser # Open Browser
|
||||
bind = $mainMod, V, togglefloating, # Toggle Window floating
|
||||
bind = $mainMod, space, exec, $menu # Open Menu
|
||||
bind = $mainMod, P, pseudo, # dwindle
|
||||
bind = $mainMod, F11, fullscreen, #
|
||||
bind = $mainMod, J, togglesplit, # dwindle
|
||||
bind = $mainMod, L, exec, hyprlock
|
||||
bind = $mainMod, F11, fullscreen, # Toggle Window fullscreen
|
||||
bind = $mainMod, J, togglesplit, # Toggle Window split
|
||||
bind = $mainMod, L, exec, hyprlock # Lock Desktop
|
||||
|
||||
# Move focus with mainMod + arrow keys
|
||||
bind = $mainMod, left, movefocus, l
|
||||
|
||||
@@ -8,6 +8,29 @@
|
||||
|
||||
# Example windowrules that are useful
|
||||
|
||||
# Apps
|
||||
windowrule {
|
||||
name = intellij
|
||||
match:class = jetbrains-idea
|
||||
opacity = 0.8
|
||||
}
|
||||
windowrule {
|
||||
name = thunar
|
||||
match:class = thunar
|
||||
opacity = 0.8
|
||||
}
|
||||
windowrule {
|
||||
name = steam
|
||||
match:class = steam
|
||||
opacity = 0.8
|
||||
}
|
||||
|
||||
windowrule {
|
||||
name = discord
|
||||
match:class = discord
|
||||
monitor = $right-monitor
|
||||
}
|
||||
|
||||
windowrule {
|
||||
# Ignore maximize requests from all apps. You'll probably like this.
|
||||
name = suppress-maximize-events
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# __ ___ __ __
|
||||
# / //_(_) /_/ /___ __
|
||||
# / ,< / / __/ __/ // /
|
||||
# /_/|_/_/\__/\__/\_, /
|
||||
# /___/
|
||||
#
|
||||
# Configuration
|
||||
font_family FiraCode Nerd Font
|
||||
font_size 11
|
||||
bold_font auto
|
||||
italic_font auto
|
||||
bold_italic_font auto
|
||||
remember_window_size no
|
||||
initial_window_width 950
|
||||
initial_window_height 500
|
||||
cursor_blink_interval 0.5
|
||||
cursor_stop_blinking_after 1
|
||||
scrollback_lines 2000
|
||||
wheel_scroll_min_lines 1
|
||||
enable_audio_bell no
|
||||
window_padding_width 10
|
||||
hide_window_decorations yes
|
||||
background_opacity 0.7
|
||||
dynamic_background_opacity yes
|
||||
confirm_os_window_close 0
|
||||
selection_foreground none
|
||||
selection_background none
|
||||
cursor_trail 1
|
||||
@@ -0,0 +1,141 @@
|
||||
{
|
||||
"general": {
|
||||
"accentColor": "#117703",
|
||||
"checkForMillenniumUpdates": true,
|
||||
"checkForPluginAndThemeUpdates": true,
|
||||
"injectCSS": true,
|
||||
"injectJavascript": true,
|
||||
"millenniumUpdateChannel": "stable",
|
||||
"onMillenniumUpdate": 1,
|
||||
"shouldShowThemePluginUpdateNotifications": true
|
||||
},
|
||||
"misc": {
|
||||
"hasShownWelcomeModal": true
|
||||
},
|
||||
"notifications": {
|
||||
"showNotifications": true,
|
||||
"showPluginNotifications": true,
|
||||
"showUpdateNotifications": true
|
||||
},
|
||||
"plugins": {
|
||||
"enabledPlugins": [
|
||||
"extendium",
|
||||
"hltb-for-millennium",
|
||||
"size-on-disk"
|
||||
]
|
||||
},
|
||||
"themes": {
|
||||
"activeTheme": "Minimal-Dark-for-Steam",
|
||||
"allowedScripts": true,
|
||||
"allowedStyles": true,
|
||||
"conditions": {
|
||||
"Minimal-Dark-for-Steam": {
|
||||
"Account wallet :": "Hide",
|
||||
"Alignment fix for 4K resolution :": "no",
|
||||
"Alternate view of in-game friends :": "Alternative",
|
||||
"Alternative UI for new Steam menu :": "Minimal new UI (compact)",
|
||||
"Alternative contacts icon :": "Minimal Dark #3 (fill)",
|
||||
"Alternative downloads UI :": "New UI (alt)",
|
||||
"Alternative games names hover effect :": "Default",
|
||||
"Alternative hover effect :": "Default",
|
||||
"Alternative ingame friends indicator :": "Minimal Dark default",
|
||||
"Alternative library navigation button :": "Alternative",
|
||||
"Alternative root menu icon :": "Minimal Dark",
|
||||
"Alternative topbar color :": "Grey/dark",
|
||||
"Alternative ui color for context menus/menus :": "no",
|
||||
"Alternative view for back to top button :": "no",
|
||||
"Alternative view for scrolling bloc :": "no",
|
||||
"Animated buttons hovering :": "yes",
|
||||
"Animated hovering :": "yes",
|
||||
"Animated mouseover :": "yes",
|
||||
"Avatar frame :": "Show",
|
||||
"Avatar size :": "Default",
|
||||
"Avatar status border :": "Reduce",
|
||||
"Bigger buttons :": "no",
|
||||
"Bigger font size :": "no",
|
||||
"Bigger gamepage/library buttons :": "no",
|
||||
"Bigger header :": "Full image",
|
||||
"Bigger notification button :": "no",
|
||||
"Blocs backgrounds :": "Blurred",
|
||||
"Blurred background :": "Blurred",
|
||||
"Bolder names :": "no",
|
||||
"Change UI font :": "Default",
|
||||
"Community content :": "Show",
|
||||
"Compact Webkit :": "Hide",
|
||||
"Compact avatar :": "Compact",
|
||||
"Compact collections :": "no",
|
||||
"Compact filters :": "yes",
|
||||
"Compact labels (library + whats news) :": "Compact",
|
||||
"Compact library :": "yes",
|
||||
"Compact menus/context menus :": "Compact size (static with left border)",
|
||||
"Compact mod :": "Default",
|
||||
"Compact news container :": "Ultra compact",
|
||||
"Corners radius :": "Rounded",
|
||||
"Default pointers :": "Minimal Dark",
|
||||
"Events background :": "Default background",
|
||||
"Events header :": "Minimal Dark default",
|
||||
"Font size :": "Smaller",
|
||||
"Friends conversation tabs header glow :": "Default",
|
||||
"Friends list header glow :": "no",
|
||||
"Gamepage/library buttons svg color (Play/Install) :": "White",
|
||||
"Games names overflow :": "yes",
|
||||
"Group chats position :": "Default (bottom)",
|
||||
"Header (compact mod) :": "Show",
|
||||
"Header size adjustment :": "Yes",
|
||||
"Hide '+ Add a Showcase' :": "no",
|
||||
"Hide 'post-party summary' / 'WYRTG ?' :": "Show all",
|
||||
"Hide VAC ban information on profiles :": "no",
|
||||
"Hide all activities :": "Show all activities",
|
||||
"Hide footer (fix) :": "yes",
|
||||
"Hide footer :": "yes",
|
||||
"Hide footers :": "Hide",
|
||||
"Hide scrollbars :": "Hide",
|
||||
"Hide shelf :": "no",
|
||||
"Hide topbar elements :": "Show all",
|
||||
"Hide voice chat :": "no",
|
||||
"Hours played :": "Show",
|
||||
"Hover borders on library and webkit blocks :": "Full borders",
|
||||
"Hover/active borders :": "yes",
|
||||
"Installed/selected games color :": "Minimal Dark",
|
||||
"Inverted contact bloc :": "no",
|
||||
"Inverted gamepage (known bugs) :": "Default",
|
||||
"Library games hover glow color :": "Default",
|
||||
"Library labels :": "Show",
|
||||
"Miniprofile background :": "Hide",
|
||||
"Mouseover animation of settings menu tabs :": "Animated",
|
||||
"News container :": "Show",
|
||||
"No button labels in list mod :": "yes",
|
||||
"No button labels in normal mod :": "no",
|
||||
"No left images :": "no",
|
||||
"No titlebar (Linux) :": "no",
|
||||
"Offline friends :": "Show",
|
||||
"Persistent Sidebar :": "yes",
|
||||
"Pointer fix :": "no",
|
||||
"Profiles :": "Minimal Dark",
|
||||
"Profiles headers :": "no",
|
||||
"Pure black color (OLED) :": "no",
|
||||
"Resize grip (Steam windows) :": "Default (smaller)",
|
||||
"Right Sidebar :": "Left",
|
||||
"Root menu Steam text :": "Hide",
|
||||
"Show sidebar on mouseover :": "Default",
|
||||
"Static hovering (paysage games of Recent Games | Play Next) :": "Animated",
|
||||
"Static hovering (portrait games of Library | Collections) :": "Static",
|
||||
"Steam bigpicture button :": "Hide",
|
||||
"Steam news button :": "Hide",
|
||||
"Tabs text transform :": "no",
|
||||
"Text on play/download button :": "no",
|
||||
"Title area buttons :": "Enlarged (w11 users)",
|
||||
"Topbar Store tab left icon (currency icon) :": "Fill icon (euro)",
|
||||
"Topbar icons menu hover effect :": "Fill",
|
||||
"Topbar tabs left icons (hover effect included) :": "Icons active (fill + text)",
|
||||
"Topbar tabs left icons, no text :": "no",
|
||||
"URL bar :": "Visible",
|
||||
"Uninstalled selected games color :": "Minimal Dark",
|
||||
"Vanilla topbar style :": "Minimal Dark",
|
||||
"Windows 10 fix corners :": "no",
|
||||
"Windows corners fix :": "yes",
|
||||
"Wishlist new Steam menu :": "Compact revisited menu"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
[
|
||||
{
|
||||
"layer": "top",
|
||||
"position": "top",
|
||||
"output": [
|
||||
"HDMI-A-1"
|
||||
],
|
||||
"margin-top": 14,
|
||||
"margin-bottom": 0,
|
||||
"margin-left": 14,
|
||||
"margin-right": 14,
|
||||
"spacing": 0,
|
||||
"include": [
|
||||
"~/.config/waybar/modules.jsonc"
|
||||
],
|
||||
"modules-left": [
|
||||
"group/workspaces"
|
||||
],
|
||||
// Load Modules
|
||||
"modules-center": [
|
||||
],
|
||||
"modules-right": [
|
||||
"mpd",
|
||||
"group/hardware",
|
||||
"tray"
|
||||
]
|
||||
},
|
||||
{
|
||||
"layer": "top",
|
||||
"position": "right",
|
||||
"width": 250,
|
||||
"spacing": 10,
|
||||
"output": [
|
||||
"DP-2"
|
||||
],
|
||||
"include": [
|
||||
"~/.config/waybar/modules.jsonc"
|
||||
],
|
||||
"modules-left": [
|
||||
"clock#time",
|
||||
"clock#date"
|
||||
],
|
||||
"modules-right": [
|
||||
"cpu",
|
||||
"privacy",
|
||||
"user",
|
||||
"custom/exit"
|
||||
],
|
||||
"clock#time": {
|
||||
"format": "{:%H:%M:%S}",
|
||||
"interval": 1,
|
||||
"tooltip": false
|
||||
},
|
||||
"clock#date": {
|
||||
"format": "{:%A %d %h %G}",
|
||||
"tooltip-format": "<tt><big>{calendar}</big></tt>"
|
||||
},
|
||||
"user": {
|
||||
"format": "{user} (up {work_d} days)",
|
||||
"interval": 60,
|
||||
"height": 30,
|
||||
"width": 30,
|
||||
"icon": true,
|
||||
},
|
||||
"privacy": {
|
||||
"icon-spacing": 4,
|
||||
"icon-size": 18,
|
||||
"transition-duration": 250,
|
||||
"modules": [
|
||||
{
|
||||
"type": "screenshare",
|
||||
"tooltip": true,
|
||||
"tooltip-icon-size": 24
|
||||
},
|
||||
{
|
||||
"type": "audio-out",
|
||||
"tooltip": true,
|
||||
"tooltip-icon-size": 24
|
||||
},
|
||||
{
|
||||
"type": "audio-in",
|
||||
"tooltip": true,
|
||||
"tooltip-icon-size": 24
|
||||
}
|
||||
],
|
||||
"ignore-monitor": true,
|
||||
"ignore": [
|
||||
{
|
||||
"type": "audio-in",
|
||||
"name": "cava"
|
||||
},
|
||||
{
|
||||
"type": "screenshare",
|
||||
"name": "obs"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,162 @@
|
||||
{
|
||||
"group/workspaces": {
|
||||
"orientation": "inherit",
|
||||
"modules": [
|
||||
"hyprland/workspaces",
|
||||
"hyprland/window"
|
||||
]
|
||||
},
|
||||
"hyprland/workspaces": {
|
||||
"active-only": false,
|
||||
"all-outputs": true,
|
||||
"on-click": "activate",
|
||||
"workspace-taskbar": {
|
||||
"enable": true,
|
||||
"active-window-position": "last",
|
||||
"update-active-window": true,
|
||||
"icon-theme": [
|
||||
"Silvery-Dark-Icons"
|
||||
]
|
||||
},
|
||||
"format-icons": {
|
||||
"active": ""
|
||||
},
|
||||
"format": "{icon} {windows}"
|
||||
},
|
||||
"hyprland/window": {
|
||||
"format": "[{class}] {title}",
|
||||
"rewrite": {
|
||||
"(.*) - Vivaldi": "$1",
|
||||
"(.*) - fish": "$1"
|
||||
},
|
||||
"separate-outputs": false
|
||||
},
|
||||
"custom/exit": {
|
||||
"format": "",
|
||||
"tooltip-format": "Powermenu",
|
||||
"on-click": "wlogout -b 4",
|
||||
"tooltip": false
|
||||
},
|
||||
// System tray
|
||||
"tray": {
|
||||
"orientation": "vertical",
|
||||
"show-passive-items": true,
|
||||
// "icon-size": 21,
|
||||
"spacing": 10
|
||||
},
|
||||
// Clock
|
||||
"clock": {
|
||||
// "timezone": "America/New_York",
|
||||
"tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>",
|
||||
"format-alt": "{:%Y-%m-%d}"
|
||||
},
|
||||
// System
|
||||
"custom/system": {
|
||||
"format": "",
|
||||
"tooltip": false
|
||||
},
|
||||
// CPU
|
||||
"cpu": {
|
||||
"interval": 1,
|
||||
"format": "{icon0}{icon1}{icon2}{icon3}{icon4}{icon5}{icon6}{icon7}{icon8}{icon9}{icon10}{icon11}{icon12}{icon13}{icon14}{icon15}",
|
||||
"format-icons": [
|
||||
"<span color='#69ff94'>▁</span>", // green
|
||||
"<span color='#2aa9ff'>▂</span>", // blue
|
||||
"<span color='#f8f8f2'>▃</span>", // white
|
||||
"<span color='#f8f8f2'>▄</span>", // white
|
||||
"<span color='#ffffa5'>▅</span>", // yellow
|
||||
"<span color='#ffffa5'>▆</span>", // yellow
|
||||
"<span color='#ff9977'>▇</span>", // orange
|
||||
"<span color='#dd532e'>█</span>" // red
|
||||
],
|
||||
"on-click": "kitty -e htop"
|
||||
},
|
||||
// Memory
|
||||
"memory": {
|
||||
"format": "/ M {}% ",
|
||||
"on-click": "kitty -e htop"
|
||||
},
|
||||
// Harddisc space used
|
||||
"disk": {
|
||||
"interval": 30,
|
||||
"format": "D {percentage_used}% ",
|
||||
"path": "/",
|
||||
"on-click": "kitty -e htop"
|
||||
},
|
||||
"hyprland/language": {
|
||||
"format": "/ K {short}"
|
||||
},
|
||||
// Group Hardware
|
||||
"group/hardware": {
|
||||
"orientation": "inherit",
|
||||
"drawer": {
|
||||
"transition-duration": 300,
|
||||
"children-class": "not-memory",
|
||||
"transition-left-to-right": false
|
||||
},
|
||||
"modules": [
|
||||
"custom/system",
|
||||
"pulseaudio",
|
||||
"network",
|
||||
"disk",
|
||||
"memory",
|
||||
"hyprland/language"
|
||||
]
|
||||
},
|
||||
// Network
|
||||
"network": {
|
||||
"format": "{ifname}",
|
||||
"format-wifi": " {essid} ({signalStrength}%)",
|
||||
"format-ethernet": " {ifname}",
|
||||
"format-disconnected": "Disconnected ⚠",
|
||||
"tooltip-format": " {ifname} via {gwaddri}",
|
||||
"tooltip-format-wifi": " {ifname} @ {essid}\nIP: {ipaddr}\nStrength: {signalStrength}%\nFreq: {frequency}MHz\nUp: {bandwidthUpBits} Down: {bandwidthDownBits}",
|
||||
"tooltip-format-ethernet": " {ifname}\nIP: {ipaddr}\n up: {bandwidthUpBits} down: {bandwidthDownBits}",
|
||||
"tooltip-format-disconnected": "Disconnected",
|
||||
"max-length": 50,
|
||||
"on-click": "~/.config/ml4w/settings/networkmanager.sh",
|
||||
"on-click-right": "~/.config/ml4w/scripts/nm-applet.sh toggle"
|
||||
},
|
||||
// Pulseaudio
|
||||
"pulseaudio": {
|
||||
// "scroll-step": 1, // %, can be a float
|
||||
"format": "{icon} {volume}%",
|
||||
"format-bluetooth": "{volume}% {icon}",
|
||||
"format-bluetooth-muted": " {icon}",
|
||||
"format-muted": "",
|
||||
"format-source": "{volume}% ",
|
||||
"format-source-muted": "",
|
||||
"format-icons": {
|
||||
"default": [
|
||||
"",
|
||||
" ",
|
||||
" "
|
||||
]
|
||||
},
|
||||
"on-click": "pavucontrol"
|
||||
},
|
||||
// Bluetooth
|
||||
"bluetooth": {
|
||||
"format-disabled": "",
|
||||
"format-off": "",
|
||||
"interval": 30,
|
||||
"on-click": "blueman-manager",
|
||||
"format-no-controller": ""
|
||||
},
|
||||
// Other
|
||||
"user": {
|
||||
"format": "{user}",
|
||||
"interval": 60,
|
||||
"icon": false
|
||||
},
|
||||
// Idle Inhibator
|
||||
"idle_inhibitor": {
|
||||
"format": "{icon}",
|
||||
"tooltip": true,
|
||||
"format-icons": {
|
||||
"activated": "",
|
||||
"deactivated": ""
|
||||
},
|
||||
"on-click-right": "hyprlock"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
@import url("file:///$HOME/.themes/Serpensortia/waybar/style.css");
|
||||
Binary file not shown.
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
* __ __ _ ____ _ _
|
||||
* \ \ / /_ _ _ _| |__ __ _ _ __ / ___|| |_ _ _| | ___
|
||||
* \ \ /\ / / _` | | | | '_ \ / _` | '__| \___ \| __| | | | |/ _ \
|
||||
* \ V V / (_| | |_| | |_) | (_| | | ___) | |_| |_| | | __/
|
||||
* \_/\_/ \__,_|\__, |_.__/ \__,_|_| |____/ \__|\__, |_|\___|
|
||||
* |___/ |___/
|
||||
*
|
||||
* by Stephan Raabe (2024)
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
|
||||
@define-color backgroundlight #080c08;
|
||||
@define-color backgrounddark #080c08;
|
||||
@define-color workspacesbackground1 #080c08;
|
||||
@define-color workspacesbackground2 #424a42;
|
||||
@define-color bordercolor #124326;
|
||||
@define-color textcolor1 #c0c0c0;
|
||||
@define-color textcolor2 #c0c0c0;
|
||||
@define-color textcolor3 #c0c0c0;
|
||||
@define-color iconcolor #c0c0c0;
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* General
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
* {
|
||||
font-family: "Fira Sans Semibold", "Font Awesome 7 Free", "Font Awesome 7 Brands", "Font Awesome 6 Free", "Font Awesome 6 Brands", FontAwesome, Roboto, Helvetica, Arial, sans-serif;
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
window#waybar {
|
||||
background-color: rgba(0,0,0,0.8);
|
||||
border-bottom: 0px solid #ffffff;
|
||||
/* color: #FFFFFF; */
|
||||
background: transparent;
|
||||
transition-property: background-color;
|
||||
transition-duration: .5s;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Workspaces
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#workspaces {
|
||||
background: @workspacesbackground1;
|
||||
margin: 2px 18px 3px 1px;
|
||||
padding: 0px 2px;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
opacity: 1.0;
|
||||
color: @textcolor1;
|
||||
}
|
||||
|
||||
#workspaces button {
|
||||
padding: 0px 6px;
|
||||
margin: 3px 2px;
|
||||
border-radius: 3px 3px 3px 3px;
|
||||
color: @textcolor1;
|
||||
background-color: @workspacesbackground2;
|
||||
transition: all 0.1s linear;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
#workspaces button.active {
|
||||
color: @textcolor1;
|
||||
background: @workspacesbackground2;
|
||||
border-radius: 3px 3px 3px 3px;
|
||||
min-width: 30px;
|
||||
transition: all 0.1s linear;
|
||||
opacity:1.0;
|
||||
}
|
||||
|
||||
#workspaces button:hover {
|
||||
color: @textcolor1;
|
||||
background: @workspacesbackground2;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
opacity:0.7;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Tooltips
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
tooltip {
|
||||
border-radius: 16px;
|
||||
background-color: @backgroundlight;
|
||||
opacity:0.9;
|
||||
padding:20px;
|
||||
margin:0px;
|
||||
}
|
||||
|
||||
tooltip label {
|
||||
color: @textcolor2;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Window
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#window {
|
||||
margin: 3px 15px 3px 0px;
|
||||
padding: 2px 10px 0px 10px;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
color:#c0c0c0;
|
||||
font-size:16px;
|
||||
font-weight:normal;
|
||||
opacity:1.0;
|
||||
}
|
||||
|
||||
window#waybar.empty #window {
|
||||
background-color:transparent;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Taskbar
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#taskbar {
|
||||
background: @backgroundlight;
|
||||
margin: 3px 15px 3px 0px;
|
||||
padding:0px;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
opacity:1.0;
|
||||
border: 3px solid @backgroundlight;
|
||||
}
|
||||
|
||||
#taskbar button {
|
||||
margin:0;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
padding: 0px 5px 0px 5px;
|
||||
}
|
||||
|
||||
#taskbar.empty {
|
||||
background:transparent;
|
||||
border:0;
|
||||
padding:0;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Modules
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
.modules-left > widget:first-child > #workspaces {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.modules-right > widget:last-child > #workspaces {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Custom Quicklinks
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#custom-brave,
|
||||
#custom-browser,
|
||||
#custom-keybindings,
|
||||
#custom-outlook,
|
||||
#custom-filemanager,
|
||||
#custom-teams,
|
||||
#custom-chatgpt,
|
||||
#custom-calculator,
|
||||
#custom-windowsvm,
|
||||
#custom-cliphist,
|
||||
#custom-settings,
|
||||
#custom-wallpaper,
|
||||
#custom-system,
|
||||
#custom-hyprshade,
|
||||
#custom-hypridle,
|
||||
#custom-tools,
|
||||
#custom-quicklink1,
|
||||
#custom-quicklink2,
|
||||
#custom-quicklink3,
|
||||
#custom-quicklink4,
|
||||
#custom-quicklink5,
|
||||
#custom-quicklink6,
|
||||
#custom-quicklink7,
|
||||
#custom-quicklink8,
|
||||
#custom-quicklink9,
|
||||
#custom-quicklink10,
|
||||
#custom-quicklink_chromium,
|
||||
#custom-quicklink_edge,
|
||||
#custom-quicklink_firefox,
|
||||
#custom-quicklink_browser,
|
||||
#custom-quicklink_filemanager,
|
||||
#custom-quicklink_email,
|
||||
#custom-quicklink_thunderbird,
|
||||
#custom-quicklink_calculator,
|
||||
#custom-waybarthemes {
|
||||
margin-right: 10px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
opacity: 1.0;
|
||||
color: @iconcolor;
|
||||
}
|
||||
|
||||
#custom-quicklink1,
|
||||
#custom-quicklink2,
|
||||
#custom-quicklink3,
|
||||
#custom-quicklink4,
|
||||
#custom-quicklink5,
|
||||
#custom-quicklink6,
|
||||
#custom-quicklink7,
|
||||
#custom-quicklink8,
|
||||
#custom-quicklink9,
|
||||
#custom-quicklink10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
#custom-tools {
|
||||
margin-right:12px;
|
||||
}
|
||||
|
||||
#custom-hypridle.active {
|
||||
color: @iconcolor;
|
||||
}
|
||||
|
||||
#custom-hypridle.notactive {
|
||||
color: #dc2f2f;
|
||||
}
|
||||
|
||||
#custom-ml4w-welcome {
|
||||
margin-right: 12px;
|
||||
background-image: url("../assets/ml4w-icon.svg");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
#custom-chatgpt {
|
||||
margin-right: 16px;
|
||||
background-image: url("../assets/openai.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: contain;
|
||||
padding-right: 18px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Idle Inhibator
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#idle_inhibitor {
|
||||
margin-right: 15px;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
opacity: 0.8;
|
||||
color: @iconcolor;
|
||||
}
|
||||
|
||||
#idle_inhibitor.activated {
|
||||
margin-right: 15px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
opacity: 0.8;
|
||||
color: #dc2f2f;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Custom Modules
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#custom-appmenu {
|
||||
background-color: @backgrounddark;
|
||||
font-size: 16px;
|
||||
color: @textcolor1;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
padding: 0px 10px 0px 10px;
|
||||
margin: 2px 17px 2px 0px;
|
||||
opacity:1.0;
|
||||
border:3px solid @bordercolor;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Custom Notification
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#custom-notification {
|
||||
margin: 0px 13px 0px 0px;
|
||||
padding:0px;
|
||||
font-size:20px;
|
||||
color: @iconcolor;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Custom Exit
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#custom-exit {
|
||||
margin: 0px 13px 0px 0px;
|
||||
padding:0px;
|
||||
font-size:20px;
|
||||
color: @iconcolor;
|
||||
opacity: 0.8;
|
||||
border:3px solid @bordercolor;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Custom Updates
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#custom-updates {
|
||||
background-color: @backgroundlight;
|
||||
font-size: 16px;
|
||||
color: @textcolor2;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
padding: 2px 10px 0px 10px;
|
||||
margin: 3px 15px 3px 0px;
|
||||
opacity:1.0;
|
||||
}
|
||||
|
||||
#custom-updates.green {
|
||||
background-color: @backgroundlight;
|
||||
}
|
||||
|
||||
#custom-updates.yellow {
|
||||
background-color: #ff9a3c;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
#custom-updates.red {
|
||||
background-color: #dc2f2f;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Hardware Group
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#disk,#memory,#cpu,#language {
|
||||
margin:0px 10px 0px 0px;
|
||||
padding:0px;
|
||||
font-size:16px;
|
||||
color:@iconcolor;
|
||||
}
|
||||
|
||||
#language {
|
||||
margin-right:10px;
|
||||
}
|
||||
|
||||
#group-workspaces {
|
||||
border:3px solid @bordercolor;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Power Profiles Daemon
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#power-profiles-daemon {
|
||||
margin: 0px 13px 0px 0px;
|
||||
padding:0px;
|
||||
font-size:16px;
|
||||
color:@iconcolor;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Clock
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#clock {
|
||||
background-color: @backgrounddark;
|
||||
font-size: 16px;
|
||||
color: @textcolor1;
|
||||
border-radius: 3px 5px 3px 5px;
|
||||
padding: 1px 10px 0px 10px;
|
||||
margin: 3px 10px 3px 0px;
|
||||
opacity:1.0;
|
||||
border:3px solid @bordercolor;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Backlight
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#backlight {
|
||||
background-color: @backgroundlight;
|
||||
font-size: 16px;
|
||||
color: @textcolor2;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
padding: 2px 10px 0px 10px;
|
||||
margin: 3px 15px 3px 0px;
|
||||
opacity:1.0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Pulseaudio
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#pulseaudio {
|
||||
background-color: @backgroundlight;
|
||||
font-size: 16px;
|
||||
color: @textcolor2;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
padding: 2px 10px 0px 10px;
|
||||
margin: 3px 15px 3px 0px;
|
||||
opacity:1.0;
|
||||
}
|
||||
|
||||
#pulseaudio.muted {
|
||||
background-color: @backgrounddark;
|
||||
color: @textcolor1;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Network
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#network {
|
||||
background-color: @backgroundlight;
|
||||
font-size: 16px;
|
||||
color: @textcolor2;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
padding: 2px 10px 0px 10px;
|
||||
margin: 3px 15px 3px 0px;
|
||||
opacity:1.0;
|
||||
}
|
||||
|
||||
#network.ethernet {
|
||||
background-color: @backgroundlight;
|
||||
color: @textcolor2;
|
||||
}
|
||||
|
||||
#network.wifi {
|
||||
background-color: @backgroundlight;
|
||||
color: @textcolor2;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Bluetooth
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#bluetooth, #bluetooth.on, #bluetooth.connected {
|
||||
background-color: @backgroundlight;
|
||||
font-size: 16px;
|
||||
color: @textcolor2;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
padding: 2px 10px 0px 10px;
|
||||
margin: 3px 15px 3px 0px;
|
||||
opacity:1.0;
|
||||
}
|
||||
|
||||
#bluetooth.off {
|
||||
background-color: transparent;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Battery
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#battery {
|
||||
background-color: @backgroundlight;
|
||||
font-size: 16px;
|
||||
color: @textcolor2;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
padding: 2px 15px 0px 10px;
|
||||
margin: 3px 15px 3px 0px;
|
||||
opacity:1.0;
|
||||
}
|
||||
|
||||
#battery.charging, #battery.plugged {
|
||||
color: @textcolor2;
|
||||
background-color: @backgroundlight;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
to {
|
||||
background-color: @backgroundlight;
|
||||
color: @textcolor2;
|
||||
}
|
||||
}
|
||||
|
||||
#battery.critical:not(.charging) {
|
||||
background-color: #f53c3c;
|
||||
color: @textcolor3;
|
||||
animation-name: blink;
|
||||
animation-duration: 0.5s;
|
||||
animation-timing-function: linear;
|
||||
animation-iteration-count: infinite;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Tray
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
#tray {
|
||||
padding: 0px 15px 0px 0px;
|
||||
}
|
||||
|
||||
#tray > .passive {
|
||||
-gtk-icon-effect: dim;
|
||||
}
|
||||
|
||||
#tray > .needs-attention {
|
||||
-gtk-icon-effect: highlight;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,46 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
packages=(
|
||||
"wget"
|
||||
"unzip"
|
||||
"bluez"
|
||||
"bluez-utils"
|
||||
"blueman"
|
||||
"brightnessctl"
|
||||
"bun"
|
||||
"discord"
|
||||
"betterdiscord-installer-bin"
|
||||
"dunst"
|
||||
"easyeffects"
|
||||
"fastfetch"
|
||||
"flatpak"
|
||||
"git"
|
||||
"go"
|
||||
"gum"
|
||||
"gvfs"
|
||||
"hicolor-icon-theme"
|
||||
"htop"
|
||||
"hyprland"
|
||||
"waybar"
|
||||
"rofi"
|
||||
"hyprlock"
|
||||
"hyprpaper"
|
||||
"hyprpolkitagent"
|
||||
"jetbrains-toolbox"
|
||||
"jq"
|
||||
"kitty"
|
||||
"dunst"
|
||||
"flatpak"
|
||||
"networkmanager"
|
||||
"qt5-wayland"
|
||||
"qt5ct"
|
||||
"qt6-wayland"
|
||||
"qt6ct"
|
||||
"rofi"
|
||||
"scite"
|
||||
"thunar"
|
||||
"thunar-archive-plugin"
|
||||
"thunar-media-tags-plugin"
|
||||
"thunar-shares-plugin"
|
||||
"thunar-vcs-plugin"
|
||||
"thunar-volman"
|
||||
"qt5-wayland"
|
||||
"qt6-wayland"
|
||||
"qt5ct"
|
||||
"qt6ct"
|
||||
"go"
|
||||
"hyprpaper"
|
||||
"hyprlock"
|
||||
"hyprpolkitagent"
|
||||
"hicolor-icon-theme"
|
||||
"woff2-font-awesome"
|
||||
"ttf-fira-code"
|
||||
"ttf-fira-sans"
|
||||
"ttf-firacode-nerd"
|
||||
"unzip"
|
||||
"vim"
|
||||
"vivaldi"
|
||||
"fastfetch"
|
||||
"ttf-fira-sans"
|
||||
"ttf-fira-code"
|
||||
"ttf-firacode-nerd"
|
||||
"jq"
|
||||
"brightnessctl"
|
||||
"networkmanager"
|
||||
"waybar"
|
||||
"wget"
|
||||
"wireplumber"
|
||||
"wlogout"
|
||||
"jetbrains-toolbox"
|
||||
"woff2-font-awesome"
|
||||
"xdg-desktop-portal-hyprland"
|
||||
"steam"
|
||||
"millennium"
|
||||
"mangohud"
|
||||
"goverlay"
|
||||
)
|
||||
|
||||
packagesToRemove=(
|
||||
@@ -141,6 +154,7 @@ _copyConfig() {
|
||||
done
|
||||
# use envsubst for qt6ct.conf
|
||||
envsubst < dotfiles/.config/qt6ct/qt6ct.conf > "$HOME/.config/qt6ct/qt6ct.conf"
|
||||
envsubst < dotfiles/.config/waybar/style.css > "$HOME/.config/waybar/style.css"
|
||||
# copy qt6 to qt5
|
||||
mkdir -p "$HOME/.config/qt5ct"
|
||||
cp -v "$HOME/.config/qt6ct/qt6ct.conf" "$HOME/.config/qt5ct/qt5ct.conf"
|
||||
@@ -177,6 +191,9 @@ _copyConfig
|
||||
_copyScripts
|
||||
|
||||
hyprctl reload
|
||||
killall -9 waybar
|
||||
sleep 1
|
||||
waybar &
|
||||
echo ":::::::::::::::::::::::::::"
|
||||
echo ":: Installation complete ::"
|
||||
echo ":::::::::::::::::::::::::::"
|
||||
|
||||
Reference in New Issue
Block a user