discord-vscode/src/activity.ts

258 lines
7.8 KiB
TypeScript
Raw Normal View History

2021-02-10 03:24:42 +00:00
import { basename, parse, sep } from 'path';
import { debug, env, Selection, TextDocument, window, workspace } from 'vscode';
2021-02-10 03:24:42 +00:00
import {
CONFIG_KEYS,
DEBUG_IMAGE_KEY,
EMPTY,
FAKE_EMPTY,
2021-02-10 03:24:42 +00:00
FILE_SIZES,
IDLE_IMAGE_KEY,
REPLACE_KEYS,
2021-02-10 15:54:44 +00:00
UNKNOWN_GIT_BRANCH,
UNKNOWN_GIT_REPO_NAME,
2021-02-10 03:24:42 +00:00
VSCODE_IMAGE_KEY,
VSCODE_INSIDERS_IMAGE_KEY,
} from './constants';
import { log, LogLevel } from './logger';
import { getConfig, getGit, resolveFileIcon, toLower, toTitle, toUpper } from './util';
2021-02-10 03:24:42 +00:00
interface ActivityPayload {
2021-02-10 15:54:44 +00:00
details?: string;
2021-02-10 03:24:42 +00:00
state?: string;
startTimestamp?: number | null;
largeImageKey?: string;
largeImageText?: string;
smallImageKey?: string;
smallImageText?: string;
partyId?: string;
partySize?: number;
partyMax?: number;
matchSecret?: string;
joinSecret?: string;
spectateSecret?: string;
2021-02-10 19:14:27 +00:00
buttons?: { label: string; url: string }[];
2021-02-10 03:24:42 +00:00
instance?: boolean;
}
2021-02-10 15:54:44 +00:00
export async function activity(previous: ActivityPayload = {}) {
2021-02-10 03:24:42 +00:00
const config = getConfig();
2021-02-10 17:32:13 +00:00
const swapBigAndSmallImage = config[CONFIG_KEYS.SwapBigAndSmallImage];
2021-02-10 03:24:42 +00:00
const appName = env.appName;
const defaultSmallImageKey = debug.activeDebugSession
? DEBUG_IMAGE_KEY
: appName.includes('Insiders')
? VSCODE_INSIDERS_IMAGE_KEY
: VSCODE_IMAGE_KEY;
2021-02-10 17:32:13 +00:00
const defaultSmallImageText = config[CONFIG_KEYS.SmallImage].replace(REPLACE_KEYS.AppName, appName);
const defaultLargeImageText = config[CONFIG_KEYS.LargeImageIdling];
const removeDetails = config[CONFIG_KEYS.RemoveDetails];
const removeLowerDetails = config[CONFIG_KEYS.RemoveLowerDetails];
const removeRemoteRepository = config[CONFIG_KEYS.RemoveRemoteRepository];
const git = await getGit();
2021-02-10 03:24:42 +00:00
let state: ActivityPayload = {
details: removeDetails
? undefined
: await details(CONFIG_KEYS.DetailsIdling, CONFIG_KEYS.DetailsEditing, CONFIG_KEYS.DetailsDebugging),
2021-02-26 19:01:36 +00:00
startTimestamp: config[CONFIG_KEYS.RemoveTimestamp] ? undefined : previous.startTimestamp ?? Date.now(),
2021-02-10 03:24:42 +00:00
largeImageKey: IDLE_IMAGE_KEY,
2021-02-10 17:32:13 +00:00
largeImageText: defaultLargeImageText,
2021-02-10 03:24:42 +00:00
smallImageKey: defaultSmallImageKey,
2021-02-10 17:32:13 +00:00
smallImageText: defaultSmallImageText,
2021-02-10 03:24:42 +00:00
};
2021-02-10 17:32:13 +00:00
if (swapBigAndSmallImage) {
state = {
...state,
largeImageKey: defaultSmallImageKey,
largeImageText: defaultSmallImageText,
smallImageKey: IDLE_IMAGE_KEY,
smallImageText: defaultLargeImageText,
};
}
if (!removeRemoteRepository && git?.repositories.length) {
let repo = git.repositories.find((repo) => repo.ui.selected)?.state.remotes[0]?.fetchUrl;
if (repo) {
if (repo.startsWith('git@')) {
repo = repo.replace(':', '/').replace('git@', 'https://').replace('.git', '');
} else {
repo = repo.replace(/(https:\/\/)([^@]*)@(.*?$)/, '$1$3').replace('.git', '');
}
state = {
...state,
buttons: [{ label: 'View Repository', url: repo }],
};
}
}
2021-02-10 03:24:42 +00:00
if (window.activeTextEditor) {
const largeImageKey = resolveFileIcon(window.activeTextEditor.document);
const largeImageText = config[CONFIG_KEYS.LargeImage]
.replace(REPLACE_KEYS.LanguageLowerCase, toLower(largeImageKey))
.replace(REPLACE_KEYS.LanguageTitleCase, toTitle(largeImageKey))
.replace(REPLACE_KEYS.LanguageUpperCase, toUpper(largeImageKey))
.padEnd(2, FAKE_EMPTY);
2021-02-10 03:24:42 +00:00
state = {
...state,
details: removeDetails
? undefined
: await details(CONFIG_KEYS.DetailsIdling, CONFIG_KEYS.DetailsEditing, CONFIG_KEYS.DetailsDebugging),
state: removeLowerDetails
? undefined
: await details(
CONFIG_KEYS.LowerDetailsIdling,
CONFIG_KEYS.LowerDetailsEditing,
CONFIG_KEYS.LowerDetailsDebugging,
),
2021-02-10 03:24:42 +00:00
};
2021-02-10 15:54:44 +00:00
2021-02-10 17:32:13 +00:00
if (swapBigAndSmallImage) {
state = {
...state,
smallImageKey: largeImageKey,
smallImageText: largeImageText,
};
} else {
state = {
...state,
largeImageKey,
largeImageText,
};
}
2021-02-10 15:54:44 +00:00
log(LogLevel.Trace, `VSCode language id: ${window.activeTextEditor.document.languageId}`);
2021-02-10 03:24:42 +00:00
}
2021-02-10 15:54:44 +00:00
log(LogLevel.Debug, `Discord Presence being sent to discord:\n${JSON.stringify(state, null, 2)}`);
2021-02-10 03:24:42 +00:00
return state;
}
async function details(idling: CONFIG_KEYS, editing: CONFIG_KEYS, debugging: CONFIG_KEYS) {
const config = getConfig();
let raw = (config[idling] as string).replace(REPLACE_KEYS.Empty, FAKE_EMPTY);
2021-02-10 03:24:42 +00:00
if (window.activeTextEditor) {
const fileName = basename(window.activeTextEditor.document.fileName);
const { dir } = parse(window.activeTextEditor.document.fileName);
const split = dir.split(sep);
const dirName = split[split.length - 1];
const noWorkspaceFound = config[CONFIG_KEYS.LowerDetailsNoWorkspaceFound].replace(REPLACE_KEYS.Empty, FAKE_EMPTY);
2021-02-10 03:24:42 +00:00
const workspaceFolder = workspace.getWorkspaceFolder(window.activeTextEditor.document.uri);
const workspaceFolderName = workspaceFolder?.name ?? noWorkspaceFound;
const workspaceName = workspace.name?.replace(REPLACE_KEYS.VSCodeWorkspace, EMPTY) ?? workspaceFolderName;
const workspaceAndFolder = `${workspaceName}${
workspaceFolderName === FAKE_EMPTY ? '' : ` - ${workspaceFolderName}`
}`;
2021-02-10 03:24:42 +00:00
const fileIcon = resolveFileIcon(window.activeTextEditor.document);
if (debug.activeDebugSession) {
raw = config[debugging] as string;
} else {
raw = config[editing] as string;
}
if (workspaceFolder) {
const { name } = workspaceFolder;
const relativePath = workspace.asRelativePath(window.activeTextEditor.document.fileName).split(sep);
relativePath.splice(-1, 1);
raw = raw.replace(REPLACE_KEYS.FullDirName, `${name}${sep}${relativePath.join(sep)}`);
}
try {
raw = await fileDetails(raw, window.activeTextEditor.document, window.activeTextEditor.selection);
} catch (error) {
log(LogLevel.Error, `Failed to generate file details: ${error as string}`);
}
2021-02-10 03:24:42 +00:00
raw = raw
.replace(REPLACE_KEYS.FileName, fileName)
.replace(REPLACE_KEYS.DirName, dirName)
.replace(REPLACE_KEYS.Workspace, workspaceName)
.replace(REPLACE_KEYS.WorkspaceFolder, workspaceFolderName)
.replace(REPLACE_KEYS.WorkspaceAndFolder, workspaceAndFolder)
.replace(REPLACE_KEYS.LanguageLowerCase, toLower(fileIcon))
.replace(REPLACE_KEYS.LanguageTitleCase, toTitle(fileIcon))
.replace(REPLACE_KEYS.LanguageUpperCase, toUpper(fileIcon));
}
return raw;
}
async function fileDetails(_raw: string, document: TextDocument, selection: Selection) {
let raw = _raw.slice();
if (raw.includes(REPLACE_KEYS.TotalLines)) {
2021-02-10 17:32:13 +00:00
raw = raw.replace(REPLACE_KEYS.TotalLines, document.lineCount.toLocaleString());
2021-02-10 03:24:42 +00:00
}
if (raw.includes(REPLACE_KEYS.CurrentLine)) {
raw = raw.replace(REPLACE_KEYS.CurrentLine, (selection.active.line + 1).toLocaleString());
}
if (raw.includes(REPLACE_KEYS.CurrentColumn)) {
raw = raw.replace(REPLACE_KEYS.CurrentColumn, (selection.active.character + 1).toLocaleString());
}
if (raw.includes(REPLACE_KEYS.FileSize)) {
let currentDivision = 0;
2021-02-15 10:06:12 +00:00
let size: number;
try {
({ size } = await workspace.fs.stat(document.uri));
} catch {
size = document.getText().length;
}
2021-02-10 03:24:42 +00:00
const originalSize = size;
if (originalSize > 1000) {
size /= 1000;
currentDivision++;
while (size > 1000) {
currentDivision++;
size /= 1000;
}
}
raw = raw.replace(
REPLACE_KEYS.FileSize,
`${originalSize > 1000 ? size.toFixed(2) : size}${FILE_SIZES[currentDivision]}`,
);
}
const git = await getGit();
2021-02-10 03:24:42 +00:00
if (raw.includes(REPLACE_KEYS.GitBranch)) {
if (git?.repositories.length) {
raw = raw.replace(
REPLACE_KEYS.GitBranch,
git.repositories.find((repo) => repo.ui.selected)?.state.HEAD?.name ?? FAKE_EMPTY,
2021-02-10 03:24:42 +00:00
);
} else {
2021-02-10 15:54:44 +00:00
raw = raw.replace(REPLACE_KEYS.GitBranch, UNKNOWN_GIT_BRANCH);
2021-02-10 03:24:42 +00:00
}
}
if (raw.includes(REPLACE_KEYS.GitRepoName)) {
if (git?.repositories.length) {
raw = raw.replace(
REPLACE_KEYS.GitRepoName,
git.repositories
.find((repo) => repo.ui.selected)
?.state.remotes[0].fetchUrl?.split('/')[1]
.replace('.git', '') ?? FAKE_EMPTY,
2021-02-10 03:24:42 +00:00
);
} else {
2021-02-10 15:54:44 +00:00
raw = raw.replace(REPLACE_KEYS.GitRepoName, UNKNOWN_GIT_REPO_NAME);
2021-02-10 03:24:42 +00:00
}
}
return raw;
}