diff --git a/src/extension.ts b/src/extension.ts index 38073f0..d34d37d 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,33 +1,47 @@ // Import the required functions & object types from various packages. import { Client } from 'discord-rpc'; import { basename, extname } from 'path'; -import { ExtensionContext, commands, window, workspace, Uri, TextDocumentChangeEvent, TextDocument } from 'vscode'; import { setInterval, clearInterval } from 'timers'; +import { + ExtensionContext, + commands, + window, + workspace, + TextDocumentChangeEvent, + Disposable +} from 'vscode'; // Define the RPC variable and its type. let rpc: Client; +// Define the eventHandler variable and its type. +let eventHandler: Disposable; +// Define the config variable and its type. +let config; +// Define the reconnect timer and its type. +let reconnect: NodeJS.Timer; // `Activate` is fired when the extension is enabled. This SHOULD only fire once. export function activate(context: ExtensionContext) { - // Get the workspace's configuration for "discord". - const config = workspace.getConfiguration('discord'); + config = workspace.getConfiguration('discord'); // Obtain whether or not the extension is activated. if (config.get('enabled')) { initRPC(config.get('clientID')); } - + // Register the `discord.enable` command, and set the `enabled` config option to true. const enabler = commands.registerCommand('discord.enable', () => { config.update('enabled', true); initRPC(config.get('clientID')); }); - + // Register the `discord.disable` command, and set the `enabled` config option to false. const disabler = commands.registerCommand('discord.disable', () => { config.update('enabled', false); + eventHandler.dispose(); rpc.setActivity({}); + destroyRPC(); }); // Push the new commands into the subscriptions. @@ -36,17 +50,57 @@ export function activate(context: ExtensionContext) { // `Deactivate` is fired whenever the extension is deactivated. export function deactivate(context: ExtensionContext) { - // If there's an RPC Client initalized, destroy it. - if (rpc) rpc.destroy(); + destroyRPC(); +} + +// Initalize the RPC systems. +function initRPC(clientID: string): void { + // Update the RPC variable with a new RPC Client. + rpc = new Client({ transport: 'ipc' }); + + // Once the RPC Client is ready, set the activity. + rpc.once('ready', () => { + if (reconnect) { + // Clear the reconnect interval. + clearInterval(reconnect); + // Null reconnect variable. + reconnect = null; + } + setActivity(); + eventHandler = workspace.onDidChangeTextDocument((e: TextDocumentChangeEvent) => setActivity()); + // Make sure to listen to the close event and dispose and destroy everything accordingly. + rpc.transport.once('close', () => { + eventHandler.dispose(); + destroyRPC(); + // Set an interval for reconnecting. + reconnect = setInterval(() => initRPC(config.get('clientID')), 5000); + }); + }); + + // Log in to the RPC Client, and check whether or not it errors. + rpc.login(clientID).catch(error => + error.message.includes('ENOENT') + ? window.showErrorMessage('No Discord Client detected!') + : window.showErrorMessage(`Could not connect to discord via rpc: ${error.message}`) + ); +} + +// Cleanly destroy the RPC client (if it isn't already). +function destroyRPC(): void { + // Do not continue if RPC isn't initalized. + if (!rpc) return; + // If there's an RPC Client initalized, destroy it. + rpc.destroy(); + // Null the RPC variable. + rpc = null; } // This function updates the activity (The Client's Rich Presence status). function setActivity(): void { - // Do not continue if RPC isn't initalized. if (!rpc) return; - + // Create a JSON Object with the user's activity information. const activity = { details: window.activeTextEditor @@ -72,23 +126,3 @@ function setActivity(): void { // Update the user's activity to the `activity` variable. rpc.setActivity(activity); } - -/// Initalize the RPC systems. -function initRPC(clientID: string): void { - - // Update the RPC variable with a new RPC Client. - rpc = new Client({ transport: 'ipc' }); - - // Once the RPC Client is ready, set the activity. - rpc.once('ready', () => { - setActivity(); - workspace.onDidChangeTextDocument((e: TextDocumentChangeEvent) => setActivity()); - }); - - // Log in to the RPC Client, and check whether or not it errors. - rpc.login(clientID).catch(error => - error.message.includes('ENOENT') - ? window.showErrorMessage('No Discord Client detected!') - : window.showErrorMessage(`Could not connect to discord via rpc: ${error.message}`) - ); -}