2022-10-22 01:17:06 +02:00
/ * !
* Vencord , a modification for Discord ' s desktop app
* Copyright ( c ) 2022 Vendicated and contributors
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < https : //www.gnu.org/licenses/>.
* /
2025-07-15 15:57:24 +02:00
// DO NOT REMOVE UNLESS YOU WISH TO FACE THE WRATH OF THE CIRCULAR DEPENDENCY DEMON!!!!!!!
import "~plugins" ;
2022-08-29 22:05:22 +02:00
export * as Api from "./api" ;
2025-11-16 15:17:35 +01:00
export * as Plugins from "./api/PluginManager" ;
2024-05-17 23:01:07 +02:00
export * as Components from "./components" ;
2022-10-14 21:34:35 +02:00
export * as Util from "./utils" ;
2022-10-22 18:18:41 +02:00
export * as Updater from "./utils/updater" ;
export * as Webpack from "./webpack" ;
2025-02-07 20:07:17 -03:00
export * as WebpackPatcher from "./webpack/patchWebpack" ;
2022-10-26 13:54:23 +02:00
export { PlainSettings , Settings } ;
2022-08-29 20:27:47 +02:00
2025-10-11 01:42:14 +02:00
import { addVencordUiStyles } from "@components/css" ;
2025-11-21 13:04:09 +01:00
import { openSettingsTabModal , UpdaterTab } from "@components/settings" ;
2025-11-16 15:17:35 +01:00
import { debounce } from "@shared/debounce" ;
2025-07-15 15:57:24 +02:00
import { IS_WINDOWS } from "@utils/constants" ;
2025-10-11 01:42:14 +02:00
import { createAndAppendStyle } from "@utils/css" ;
2023-11-22 06:14:16 +01:00
import { StartAt } from "@utils/types" ;
2023-08-04 19:10:12 +01:00
import { get as dsGet } from "./api/DataStore" ;
2025-05-13 22:39:56 +02:00
import { NotificationData , showNotification } from "./api/Notifications" ;
2025-11-16 15:17:35 +01:00
import { initPluginManager , PMLogger , startAllPlugins } from "./api/PluginManager" ;
import { PlainSettings , Settings , SettingsStore } from "./api/Settings" ;
import { getCloudSettings , putCloudSettings } from "./api/SettingsSync/cloudSync" ;
2023-04-07 01:27:18 +01:00
import { localStorage } from "./utils/localStorage" ;
2023-04-15 13:50:00 +01:00
import { relaunch } from "./utils/native" ;
2023-05-06 01:36:00 +02:00
import { checkForUpdates , update , UpdateLogger } from "./utils/updater" ;
2022-10-01 00:42:50 +02:00
import { onceReady } from "./webpack" ;
2025-12-06 17:35:35 -05:00
import { openUserSettingsPanel } from "./webpack/common" ;
2025-11-16 15:17:35 +01:00
import { patches } from "./webpack/patchWebpack" ;
2022-08-31 20:47:07 +02:00
2024-05-31 23:28:58 -03:00
if ( IS_REPORTER ) {
require ( "./debug/runReporter" ) ;
}
2023-04-07 01:27:18 +01:00
async function syncSettings() {
2025-03-31 17:36:21 -04:00
// Check if cloud auth exists for current user before attempting sync
const hasCloudAuth = await dsGet ( "Vencord_cloudSecret" ) ;
if ( ! hasCloudAuth ) {
if ( Settings . cloud . authenticated ) {
// User switched to an account that isn't connected to cloud
showNotification ( {
title : "Cloud Settings" ,
2025-09-24 09:31:26 -04:00
body : "Cloud sync was disabled because this account isn't connected to the cloud App. You can enable it again by connecting this account in Cloud Settings. (note: it will store your preferences separately)" ,
2025-03-31 17:36:21 -04:00
color : "var(--yellow-360)" ,
2025-12-06 17:35:35 -05:00
onClick : ( ) = > openUserSettingsPanel ( "equicord_cloud" )
2025-03-31 17:36:21 -04:00
} ) ;
// Disable cloud sync globally
Settings . cloud . authenticated = false ;
}
return ;
}
2023-08-04 19:10:12 +01:00
// pre-check for local shared settings
if (
Settings . cloud . authenticated &&
2025-03-31 17:36:21 -04:00
! hasCloudAuth // this has been enabled due to local settings share or some other bug
2023-08-04 19:10:12 +01:00
) {
// show a notification letting them know and tell them how to fix it
showNotification ( {
title : "Cloud Integrations" ,
body : "We've noticed you have cloud integrations enabled in another client! Due to limitations, you will " +
"need to re-authenticate to continue using them. Click here to go to the settings page to do so!" ,
color : "var(--yellow-360)" ,
2025-12-06 17:35:35 -05:00
onClick : ( ) = > openUserSettingsPanel ( "equicord_cloud" )
2023-08-04 19:10:12 +01:00
} ) ;
return ;
}
2023-04-07 01:27:18 +01:00
if (
Settings . cloud . settingsSync && // if it's enabled
Settings . cloud . authenticated // if cloud integrations are enabled
) {
if ( localStorage . Vencord_settingsDirty ) {
await putCloudSettings ( ) ;
delete localStorage . Vencord_settingsDirty ;
2024-10-14 19:33:17 -04:00
} else if ( await getCloudSettings ( false ) ) {
// if we synchronized something (false means no sync)
2023-04-07 01:27:18 +01:00
// we show a notification here instead of allowing getCloudSettings() to show one to declutter the amount of
// potential notifications that might occur. getCloudSettings() will always send a notification regardless if
// there was an error to notify the user, but besides that we only want to show one notification instead of all
// of the possible ones it has (such as when your settings are newer).
showNotification ( {
title : "Cloud Settings" ,
body : "Your settings have been updated! Click here to restart to fully apply changes!" ,
color : "var(--green-360)" ,
2023-04-15 13:50:00 +01:00
onClick : relaunch
2023-04-07 01:27:18 +01:00
} ) ;
}
}
2025-11-16 15:17:35 +01:00
const saveSettingsOnFrequentAction = debounce ( async ( ) = > {
if ( Settings . cloud . settingsSync && Settings . cloud . authenticated ) {
await putCloudSettings ( ) ;
delete localStorage . Vencord_settingsDirty ;
}
} , 60 _000 ) ;
SettingsStore . addGlobalChangeListener ( ( ) = > {
localStorage . Vencord_settingsDirty = true ;
saveSettingsOnFrequentAction ( ) ;
} ) ;
2023-04-07 01:27:18 +01:00
}
2025-05-13 22:39:56 +02:00
let notifiedForUpdatesThisSession = false ;
async function runUpdateCheck() {
2025-11-21 13:04:09 +01:00
if ( IS_UPDATER_DISABLED ) return ;
2025-05-13 22:39:56 +02:00
const notify = ( data : NotificationData ) = > {
if ( notifiedForUpdatesThisSession ) return ;
notifiedForUpdatesThisSession = true ;
setTimeout ( ( ) = > showNotification ( {
permanent : true ,
noPersist : true ,
. . . data
} ) , 10 _000 ) ;
} ;
try {
const isOutdated = await checkForUpdates ( ) ;
if ( ! isOutdated ) return ;
if ( Settings . autoUpdate ) {
await update ( ) ;
2025-09-10 02:47:12 -04:00
if ( Settings . autoUpdateNotification ) {
2025-05-13 22:39:56 +02:00
notify ( {
2025-05-14 14:46:57 -04:00
title : "Equicord has been updated!" ,
2025-05-13 22:39:56 +02:00
body : "Click here to restart" ,
onClick : relaunch
} ) ;
}
return ;
}
notify ( {
2025-05-14 14:46:57 -04:00
title : "A Equicord update is available!" ,
2025-05-13 22:39:56 +02:00
body : "Click here to view the update" ,
2025-11-21 13:04:09 +01:00
onClick : ( ) = > openSettingsTabModal ( UpdaterTab ! )
2025-05-13 22:39:56 +02:00
} ) ;
} catch ( err ) {
UpdateLogger . error ( "Failed to check for updates" , err ) ;
}
}
2022-10-01 00:42:50 +02:00
async function init() {
await onceReady ;
2023-11-22 06:14:16 +01:00
startAllPlugins ( StartAt . WebpackReady ) ;
2022-10-01 00:42:50 +02:00
2023-04-07 01:27:18 +01:00
syncSettings ( ) ;
2025-09-14 17:04:49 -04:00
if ( ! IS_DEV && ! IS_WEB && ! IS_UPDATER_DISABLED ) {
2025-05-13 22:39:56 +02:00
runUpdateCheck ( ) ;
2025-06-07 00:46:49 +02:00
// this tends to get really annoying, so only do this if the user has auto-update without notification enabled
if ( Settings . autoUpdate && ! Settings . autoUpdateNotification ) {
setInterval ( runUpdateCheck , 1000 * 60 * 30 ) ; // 30 minutes
}
2022-10-01 00:42:50 +02:00
}
2022-10-30 20:45:18 +01:00
if ( IS_DEV ) {
const pendingPatches = patches . filter ( p = > ! p . all && p . predicate ? . ( ) !== false ) ;
if ( pendingPatches . length )
PMLogger . warn (
"Webpack has finished initialising, but some patches haven't been applied yet." ,
"This might be expected since some Modules are lazy loaded, but please verify" ,
"that all plugins are working as intended." ,
2025-05-14 15:58:32 -04:00
"You are seeing this warning because this is a Development build of Equicord." ,
2022-10-30 20:45:18 +01:00
"\nThe following patches have not been applied:" ,
"\n\n" + pendingPatches . map ( p = > ` ${ p . plugin } : ${ p . find } ` ) . join ( "\n" )
) ;
}
2022-10-01 00:42:50 +02:00
}
2025-11-16 15:17:35 +01:00
initPluginManager ( ) ;
2025-03-30 13:56:37 -04:00
startAllPlugins ( StartAt . Init ) ;
init ( ) ;
2023-02-28 22:17:39 +01:00
2024-07-10 15:25:18 -04:00
document . addEventListener ( "DOMContentLoaded" , ( ) = > {
2025-10-11 01:42:14 +02:00
addVencordUiStyles ( ) ;
2025-03-30 13:56:37 -04:00
startAllPlugins ( StartAt . DOMContentLoaded ) ;
2023-11-22 06:14:16 +01:00
2025-10-11 01:42:14 +02:00
// FIXME
2025-07-15 15:57:24 +02:00
if ( IS_DISCORD_DESKTOP && Settings . winNativeTitleBar && IS_WINDOWS ) {
2025-10-11 01:42:14 +02:00
createAndAppendStyle ( "vencord-native-titlebar-style" ) . textContent = "[class*=titleBar]{display: none!important}" ;
2024-07-10 15:25:18 -04:00
}
} , { once : true } ) ;