✨ Create lightTheme action
Changes vscode theme and windows color scheme
This commit is contained in:
151
src/backend/pubSubClient/actions/lightTheme/helpers.ts
Normal file
151
src/backend/pubSubClient/actions/lightTheme/helpers.ts
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
import * as regedit from "regedit";
|
||||||
|
|
||||||
|
import { ColorTheme, RegeditListResult, RegisterColorTheme } from "./types";
|
||||||
|
import { readFile, stat, writeFile } from "fs/promises";
|
||||||
|
import { vsCodeDarkTheme, vsCodeLightTheme } from ".";
|
||||||
|
|
||||||
|
import { platform } from "os";
|
||||||
|
import { resolve } from "path";
|
||||||
|
|
||||||
|
const isWindows = platform() === "win32";
|
||||||
|
const registerColorThemePath =
|
||||||
|
"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
|
||||||
|
|
||||||
|
function vsCodeSettingsPath(): string {
|
||||||
|
if (!isWindows) {
|
||||||
|
throw new Error("This function only supports win32 platform");
|
||||||
|
}
|
||||||
|
|
||||||
|
const vsCodeSettings = resolve(
|
||||||
|
// @ts-expect-error Type string | undefined is not assignable
|
||||||
|
process.env.APPDATA,
|
||||||
|
"./Code/User/settings.json"
|
||||||
|
);
|
||||||
|
|
||||||
|
return vsCodeSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function existsVsCodeSettings(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await stat(vsCodeSettingsPath());
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function changeVsCodeColorTheme(colorTheme: ColorTheme): Promise<void> {
|
||||||
|
let theme: string;
|
||||||
|
|
||||||
|
switch (colorTheme) {
|
||||||
|
case "light":
|
||||||
|
theme = vsCodeLightTheme;
|
||||||
|
break;
|
||||||
|
case "dark":
|
||||||
|
default:
|
||||||
|
theme = vsCodeDarkTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!theme) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = vsCodeSettingsPath();
|
||||||
|
const settings = JSON.parse((await readFile(filePath)).toString());
|
||||||
|
|
||||||
|
const colorThemeSettingKey = "workbench.colorTheme";
|
||||||
|
|
||||||
|
if (settings[colorThemeSettingKey] === theme) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
settings[colorThemeSettingKey] = theme;
|
||||||
|
|
||||||
|
await writeFile(filePath, JSON.stringify(settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
function regeditList(keys: string | Array<string>): Promise<RegeditListResult> {
|
||||||
|
const listKeys = Array.isArray(keys) ? keys : [keys];
|
||||||
|
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
regedit.list(listKeys, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
rej(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
res(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function regeditPut(values: regedit.RegistryItemPutCollection): Promise<void> {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
regedit.putValue(values, (err) => {
|
||||||
|
if (err) {
|
||||||
|
rej(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
res();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function changeRegisterColorTheme(
|
||||||
|
value: RegisterColorTheme
|
||||||
|
): Promise<void> {
|
||||||
|
const type = "REG_DWORD";
|
||||||
|
|
||||||
|
const values: regedit.RegistryItemPutCollection = {
|
||||||
|
[registerColorThemePath]: {
|
||||||
|
SystemUsesLightTheme: {
|
||||||
|
value,
|
||||||
|
type,
|
||||||
|
},
|
||||||
|
AppsUseLightTheme: {
|
||||||
|
value,
|
||||||
|
type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await regeditPut(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerColorThemeValue(colorTheme: ColorTheme): RegisterColorTheme {
|
||||||
|
let registerValue: RegisterColorTheme;
|
||||||
|
|
||||||
|
switch (colorTheme) {
|
||||||
|
case "light":
|
||||||
|
registerValue = RegisterColorTheme.Light;
|
||||||
|
break;
|
||||||
|
case "dark":
|
||||||
|
default:
|
||||||
|
registerValue = RegisterColorTheme.Dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
return registerValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function changeWindowsColorTheme(colorTheme: ColorTheme): Promise<void> {
|
||||||
|
const registerValue = registerColorThemeValue(colorTheme);
|
||||||
|
const listResult = await regeditList(registerColorThemePath);
|
||||||
|
const keyValues = listResult[registerColorThemePath].values;
|
||||||
|
const { AppsUseLightTheme, SystemUsesLightTheme } = keyValues;
|
||||||
|
|
||||||
|
if (
|
||||||
|
AppsUseLightTheme.value === registerValue &&
|
||||||
|
SystemUsesLightTheme.value === registerValue
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await changeRegisterColorTheme(registerValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
isWindows,
|
||||||
|
existsVsCodeSettings,
|
||||||
|
changeVsCodeColorTheme,
|
||||||
|
changeWindowsColorTheme,
|
||||||
|
};
|
107
src/backend/pubSubClient/actions/lightTheme/index.ts
Normal file
107
src/backend/pubSubClient/actions/lightTheme/index.ts
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import {
|
||||||
|
changeVsCodeColorTheme,
|
||||||
|
changeWindowsColorTheme,
|
||||||
|
existsVsCodeSettings,
|
||||||
|
isWindows,
|
||||||
|
} from "./helpers";
|
||||||
|
|
||||||
|
import { ColorTheme } from "./types";
|
||||||
|
import { LOG_PREFIX } from "../..";
|
||||||
|
import { RedemptionMessage } from "../../../../interfaces/RedemptionMessage";
|
||||||
|
import { isProduction } from "../../../helpers/util";
|
||||||
|
|
||||||
|
const vsCodeLightTheme = "Min Light";
|
||||||
|
const vsCodeDarkTheme = "Min Dark";
|
||||||
|
|
||||||
|
const minEventDuration = 10;
|
||||||
|
|
||||||
|
let restoreAt = 0;
|
||||||
|
let restoreTimeout: NodeJS.Timeout | null;
|
||||||
|
|
||||||
|
function calculateEventDurationMs(rewardCost: number): number {
|
||||||
|
const reduceBase = 200;
|
||||||
|
const ms = 1e3;
|
||||||
|
|
||||||
|
const eventDuration = Math.max(minEventDuration, rewardCost - reduceBase);
|
||||||
|
|
||||||
|
return eventDuration * ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
function msText(ms: number): string {
|
||||||
|
let amountTime: number;
|
||||||
|
let amountUnit: string;
|
||||||
|
|
||||||
|
const second = 1e3;
|
||||||
|
const minute = 60e3;
|
||||||
|
|
||||||
|
if (ms >= minute) {
|
||||||
|
amountTime = ms / minute;
|
||||||
|
amountUnit = "minuto";
|
||||||
|
} else {
|
||||||
|
amountTime = ms / second;
|
||||||
|
amountUnit = "segundo";
|
||||||
|
}
|
||||||
|
|
||||||
|
const decimalPrecision = 1e2;
|
||||||
|
const roundedAmountTime =
|
||||||
|
Math.round(amountTime * decimalPrecision) / decimalPrecision;
|
||||||
|
// eslint-disable-next-line no-magic-numbers
|
||||||
|
const pluralize = roundedAmountTime > 1 ? "s" : "";
|
||||||
|
|
||||||
|
return `${roundedAmountTime} ${amountUnit}${pluralize}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function lightTheme(msg: RedemptionMessage): Promise<RedemptionMessage> {
|
||||||
|
if (!isWindows) {
|
||||||
|
throw new Error("Only available on Windows platform");
|
||||||
|
}
|
||||||
|
|
||||||
|
const colorTheme: ColorTheme = "light";
|
||||||
|
|
||||||
|
if (isProduction) {
|
||||||
|
if (await existsVsCodeSettings()) {
|
||||||
|
await changeVsCodeColorTheme(colorTheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
await changeWindowsColorTheme(colorTheme);
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
`${LOG_PREFIX}Light Theme not changed to ${colorTheme} (not production)`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const eventDuration = calculateEventDurationMs(msg.rewardCost);
|
||||||
|
|
||||||
|
if (restoreTimeout) {
|
||||||
|
clearTimeout(restoreTimeout);
|
||||||
|
|
||||||
|
msg.message = `Aumentado el tiempo con tema claro por ${msText(
|
||||||
|
eventDuration
|
||||||
|
)}`;
|
||||||
|
} else {
|
||||||
|
restoreAt = Date.now();
|
||||||
|
|
||||||
|
msg.message = `Disfruta de un dia iluminado`;
|
||||||
|
}
|
||||||
|
|
||||||
|
restoreAt += eventDuration;
|
||||||
|
|
||||||
|
const timeoutTime = restoreAt - Date.now();
|
||||||
|
|
||||||
|
msg.message += ` (tiempo acumulado ${msText(timeoutTime)})`;
|
||||||
|
|
||||||
|
restoreTimeout = setTimeout(async () => {
|
||||||
|
const colorTheme: ColorTheme = "dark";
|
||||||
|
|
||||||
|
restoreTimeout = null;
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
changeVsCodeColorTheme(colorTheme),
|
||||||
|
changeWindowsColorTheme(colorTheme),
|
||||||
|
]);
|
||||||
|
}, timeoutTime);
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { lightTheme, vsCodeDarkTheme, vsCodeLightTheme };
|
15
src/backend/pubSubClient/actions/lightTheme/types.ts
Normal file
15
src/backend/pubSubClient/actions/lightTheme/types.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import * as regedit from "regedit";
|
||||||
|
|
||||||
|
type ColorTheme = "light" | "dark";
|
||||||
|
|
||||||
|
type RegeditListResult = Record<string, regedit.RegistryItem>;
|
||||||
|
|
||||||
|
const registerDarkValue = 0;
|
||||||
|
const registerLightValue = 1;
|
||||||
|
|
||||||
|
enum RegisterColorTheme {
|
||||||
|
Dark = registerDarkValue,
|
||||||
|
Light = registerLightValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
export { ColorTheme, RegeditListResult, RegisterColorTheme };
|
Reference in New Issue
Block a user