Feat/generator 4 iteration (#400)
* chore: move env into src for better build * chore: removed unused things from webviews * feat: a better "defaults" - material-theme.config.json * chore: fix paths for scripts * feat: new folder "core" with managers * chore: cleanup all useless things * chore: update messages to be messages * refactor: new setAccent command and better material.theme.config entry
This commit is contained in:
parent
1ddcebf4c0
commit
72a12df8e1
38 changed files with 422 additions and 502 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -8,3 +8,4 @@ node_modules/
|
|||
/ui/
|
||||
build
|
||||
dist
|
||||
user.material-theme.config.json
|
||||
|
|
5
env.ts
5
env.ts
|
@ -1,5 +0,0 @@
|
|||
import * as path from 'path';
|
||||
|
||||
export const SRC_FOLDER_PATH = path.resolve('./src');
|
||||
export const BUILD_FOLDER_PATH = path.resolve('./build');
|
||||
export const TS_BUILD_FOLDER_PATH = path.resolve('./dist');
|
109
material-theme.config.json
Normal file
109
material-theme.config.json
Normal file
|
@ -0,0 +1,109 @@
|
|||
{
|
||||
"accents": {
|
||||
"Acid Lime": "#C6FF00",
|
||||
"Blue": "#2979FF",
|
||||
"Breaking Bad": "#388E3C",
|
||||
"Bright Teal": "#64FFDA",
|
||||
"Cyan": "#00BCD4",
|
||||
"Graphite": "#616161",
|
||||
"Indigo": "#5C6BC0",
|
||||
"Lime": "#7CB342",
|
||||
"Orange": "#FF7042",
|
||||
"Pink": "#FF4081",
|
||||
"Purple": "#AB47BC",
|
||||
"Red": "#E57373",
|
||||
"Sky": "#84FFFF",
|
||||
"Tomato": "#F44336",
|
||||
"Teal": "#80CBC4",
|
||||
"Yellow": "#FFA000"
|
||||
},
|
||||
"accentsProperties": {
|
||||
"activityBarBadge.background": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"list.activeSelectionForeground": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"list.inactiveSelectionForeground": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"list.highlightForeground": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"scrollbarSlider.activeBackground": {
|
||||
"alpha": 50,
|
||||
"value": null
|
||||
},
|
||||
"editorSuggestWidget.highlightForeground": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"textLink.foreground": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"progressBar.background": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"pickerGroup.foreground": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"tab.activeBorder": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"notificationLink.foreground": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"editorWidget.resizeBorder": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"editorWidget.border": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"settings.modifiedItemIndicator": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"settings.headerForeground": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"panelTitle.activeBorder": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"breadcrumb.activeSelectionForeground": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"menu.selectionForeground": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"menubar.selectionForeground": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"editor.findMatchBorder": {
|
||||
"alpha": 100,
|
||||
"value": null
|
||||
},
|
||||
"selection.background": {
|
||||
"alpha": 40,
|
||||
"value": null
|
||||
}
|
||||
},
|
||||
"changelog": {
|
||||
"lastversion": "30.0.0"
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
},
|
||||
"engines": {
|
||||
"node": "<=10",
|
||||
"vscode": ">=1.39.0"
|
||||
"vscode": ">=1.1.36"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn cleanup && yarn build:ts && yarn build:generate-themes && yarn build:ui",
|
||||
|
@ -29,7 +29,7 @@
|
|||
"lint": "eslint .",
|
||||
"build:ui": "node dist/scripts/ui/index.js",
|
||||
"build:generate-themes": "node dist/scripts/generator/index.js",
|
||||
"build:ts": "tsc -p ./tsconfig.json && ncp dist/src/ build",
|
||||
"build:ts": "tsc -p ./tsconfig.json && ncp dist/src/ build && ncp material-theme.config.json build",
|
||||
"postinstall": "node ./node_modules/vscode/bin/install && opencollective postinstall && tsc -p tsconfig.json"
|
||||
},
|
||||
"categories": [
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as path from 'path';
|
|||
import {generateTheme} from '@moxer/vscode-theme-generator';
|
||||
import {ThemeSetting} from './types';
|
||||
import {getColorSet} from './color-set';
|
||||
import {BUILD_FOLDER_PATH} from '../../env';
|
||||
import {BUILD_FOLDER_PATH} from '../../src/env';
|
||||
|
||||
const THEME_BUILD_PATH = path.join(BUILD_FOLDER_PATH, 'themes');
|
||||
const themes = ['default', 'darker', 'lighter', 'ocean', 'palenight'];
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as fs from 'fs-extra';
|
|||
import * as path from 'path';
|
||||
import browserify from 'browserify';
|
||||
|
||||
import {BUILD_FOLDER_PATH, SRC_FOLDER_PATH, TS_BUILD_FOLDER_PATH} from '../../env';
|
||||
import {BUILD_FOLDER_PATH, SRC_FOLDER_PATH, TS_BUILD_FOLDER_PATH} from '../../src/env';
|
||||
|
||||
const UI_FOLDER_PATH = path.join(SRC_FOLDER_PATH, 'webviews', 'ui');
|
||||
const UI_JS_FOLDER_PATH = path.join(TS_BUILD_FOLDER_PATH, 'src', 'webviews', 'ui');
|
||||
|
@ -14,7 +14,7 @@ const copyStatics = async (): Promise<void[]> => {
|
|||
dest: path.join(UI_FOLDER_BUILD_PATH, 'release-notes.html')
|
||||
}, {
|
||||
src: path.join(UI_FOLDER_PATH, 'release-notes', 'style.css'),
|
||||
dest: path.join(UI_FOLDER_BUILD_PATH, 'style.css')
|
||||
dest: path.join(UI_FOLDER_BUILD_PATH, 'release-notes.css')
|
||||
}];
|
||||
|
||||
return Promise.all(paths.map(async path => fs.copyFile(path.src, path.dest)));
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
export default {
|
||||
PURGE_KEY: 'Remove accents'
|
||||
};
|
|
@ -1,67 +0,0 @@
|
|||
import * as vscode from 'vscode';
|
||||
|
||||
import {getDefaultValues, getAccentsProperties} from './../../helpers/fs';
|
||||
import consts from './consts';
|
||||
|
||||
const REGEXP_HEX: RegExp = /^#([0-9A-F]{6}|[0-9A-F]{8})$/i;
|
||||
|
||||
/**
|
||||
* Assigns colours
|
||||
*/
|
||||
const assignColorCustomizations = (colour: string): Object => {
|
||||
const accentsProperties = getAccentsProperties();
|
||||
const newColour = isValidColour(colour) ? colour : undefined;
|
||||
return Object.keys(accentsProperties).reduce((acc: any, propName) => {
|
||||
const accent = accentsProperties[propName];
|
||||
let colorProp = newColour;
|
||||
|
||||
if (colour && accent.alpha < 100) {
|
||||
colorProp = `${ colour }${ accent.alpha > 10 ? accent.alpha : `0${ accent.alpha }` }`;
|
||||
}
|
||||
|
||||
acc[propName] = colorProp;
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if a string is a valid colour
|
||||
*/
|
||||
const isValidColour = (colour: string | null | undefined): boolean =>
|
||||
typeof colour === 'string' && REGEXP_HEX.test(colour);
|
||||
|
||||
/**
|
||||
* Sets workbench options
|
||||
*/
|
||||
const setWorkbenchOptions = (config: any): Thenable<boolean> =>
|
||||
vscode.workspace.getConfiguration().update('workbench.colorCustomizations', config, true)
|
||||
.then(() => true, reason => vscode.window.showErrorMessage(reason));
|
||||
/**
|
||||
* VSCode command
|
||||
*/
|
||||
export default async (accent?: string): Promise<boolean> => {
|
||||
const themeConfigCommon = getDefaultValues();
|
||||
const config: any = vscode.workspace.getConfiguration().get('workbench.colorCustomizations');
|
||||
|
||||
switch (accent) {
|
||||
case consts.PURGE_KEY: {
|
||||
const newConfig = {
|
||||
...config,
|
||||
...assignColorCustomizations(undefined)
|
||||
};
|
||||
|
||||
return setWorkbenchOptions(newConfig)
|
||||
.then(() => Promise.resolve(true));
|
||||
}
|
||||
default: {
|
||||
const newConfig = {
|
||||
...config,
|
||||
...assignColorCustomizations(themeConfigCommon.accents[accent])
|
||||
};
|
||||
|
||||
return setWorkbenchOptions(newConfig)
|
||||
.then(() => Boolean(accent));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
import * as vscode from 'vscode';
|
||||
import {getDefaultValues} from '../../helpers/fs';
|
||||
import consts from './consts';
|
||||
|
||||
export default async () => {
|
||||
const themeConfigCommon = getDefaultValues();
|
||||
const options: string[] = Object.keys(themeConfigCommon.accents).concat(consts.PURGE_KEY);
|
||||
return vscode.window.showQuickPick(options);
|
||||
};
|
|
@ -1,2 +1 @@
|
|||
export {default as accentsSetter} from './accents-setter';
|
||||
export {default as accentsQuickPick} from './accents-setter/quick-pick';
|
||||
export {command as setAccent} from './set-accent';
|
||||
|
|
55
src/commands/set-accent.ts
Normal file
55
src/commands/set-accent.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
import {workspace, window} from 'vscode';
|
||||
import {extensionManager} from '../core/extension-manager';
|
||||
import {settingsManager} from '../core/settings-manager';
|
||||
|
||||
const PURGE_KEY = 'Remove accents';
|
||||
|
||||
const isValidColor = (color: string | null | undefined): boolean =>
|
||||
color && /^#([0-9A-F]{6}|[0-9A-F]{8})$/i.test(color);
|
||||
|
||||
const getThemeColorCustomizationsConfig = (accentColor?: string): Record<string, unknown> => {
|
||||
const {accentsProperties} = extensionManager.getConfig();
|
||||
const color = isValidColor(accentColor) ? accentColor : undefined;
|
||||
|
||||
const themeColorCustomConfig = Object.keys(accentsProperties).reduce((acc: any, propName) => {
|
||||
const currentProp = accentsProperties[propName];
|
||||
const shouldModify = color && currentProp.alpha < 100;
|
||||
const colorProp = shouldModify ? `${color}${currentProp.alpha > 10 ? currentProp.alpha : `0${currentProp.alpha}`}` : color;
|
||||
acc[propName] = colorProp;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return themeColorCustomConfig;
|
||||
};
|
||||
|
||||
const updateColorCustomizationsConfig = async (config: any): Promise<boolean> => {
|
||||
try {
|
||||
workspace.getConfiguration().update('workbench.colorCustomizations', config, true);
|
||||
return true;
|
||||
} catch (error) {
|
||||
window.showErrorMessage(error);
|
||||
}
|
||||
};
|
||||
|
||||
const quickPick = async (): Promise<string> => {
|
||||
const themeConfig = extensionManager.getConfig();
|
||||
const options: string[] = Object.keys(themeConfig.accents).concat(PURGE_KEY);
|
||||
return window.showQuickPick(options);
|
||||
};
|
||||
|
||||
export const command = async (): Promise<void> => {
|
||||
const themeConfig = extensionManager.getConfig();
|
||||
const currentColorCustomizationsConfig: any = workspace.getConfiguration().get('workbench.colorCustomizations');
|
||||
const accent = await quickPick();
|
||||
|
||||
const config = accent === PURGE_KEY ? {
|
||||
...currentColorCustomizationsConfig,
|
||||
...getThemeColorCustomizationsConfig()
|
||||
} : {
|
||||
...currentColorCustomizationsConfig,
|
||||
...getThemeColorCustomizationsConfig(themeConfig.accents[accent])
|
||||
};
|
||||
|
||||
await updateColorCustomizationsConfig(config);
|
||||
await settingsManager.updateSetting('accent', accent);
|
||||
};
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* File charset
|
||||
*/
|
||||
export const CHARSET: string = 'utf-8';
|
|
@ -1,14 +0,0 @@
|
|||
import * as path from 'path';
|
||||
|
||||
import {IPaths} from '../interfaces/ipaths';
|
||||
|
||||
export const PATHS: IPaths = {
|
||||
SRC: './src',
|
||||
THEMES: './out/themes',
|
||||
UI: './out/ui',
|
||||
VSIX_SRC_DIR: path.join(__dirname, '../..'), // From "src" dir
|
||||
VSIX_DIR: path.join(__dirname, '../../..'), // From "out" dir
|
||||
EXT_DIR: path.join(__dirname, '..')
|
||||
};
|
||||
|
||||
export default PATHS;
|
28
src/core/changelog-manager.ts
Normal file
28
src/core/changelog-manager.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import {window} from 'vscode';
|
||||
import {MESSAGES} from '../helpers/messages';
|
||||
|
||||
type AskMessage = {
|
||||
message: string;
|
||||
options: {
|
||||
ok: string;
|
||||
cancel: string;
|
||||
};
|
||||
};
|
||||
|
||||
class ChangelogManager {
|
||||
private readonly askMessage: AskMessage;
|
||||
|
||||
constructor(message: AskMessage) {
|
||||
this.askMessage = message;
|
||||
}
|
||||
|
||||
async askShowChangelog(): Promise<boolean> {
|
||||
return await window.showInformationMessage(
|
||||
this.askMessage.message,
|
||||
this.askMessage.options.ok,
|
||||
this.askMessage.options.cancel
|
||||
) === this.askMessage.options.ok;
|
||||
}
|
||||
}
|
||||
|
||||
export const changelogManager = new ChangelogManager(MESSAGES.CHANGELOG);
|
103
src/core/extension-manager.ts
Normal file
103
src/core/extension-manager.ts
Normal file
|
@ -0,0 +1,103 @@
|
|||
import {extensions, workspace, window, Uri} from 'vscode';
|
||||
import {posix} from 'path';
|
||||
import {CONFIG_FILE_NAME, USER_CONFIG_FILE_NAME, MATERIAL_THEME_EXT_ID} from '../env';
|
||||
|
||||
type MaterialThemeConfig = {
|
||||
accents: Record<string, string>;
|
||||
accentsProperties: Record<string, {alpha: number; value: null }>;
|
||||
changelog?: { lastversion?: string };
|
||||
};
|
||||
|
||||
type InstallationType = {
|
||||
firstInstall: boolean;
|
||||
update: boolean;
|
||||
};
|
||||
|
||||
export interface IExtensionManager {
|
||||
getPackageJSON: () => Record<string, any>;
|
||||
getConfig: () => MaterialThemeConfig;
|
||||
getInstallationType: () => {};
|
||||
updateConfig: (config: Partial<MaterialThemeConfig>) => Promise<void>;
|
||||
}
|
||||
|
||||
class ExtensionManager implements IExtensionManager {
|
||||
installationType: InstallationType;
|
||||
private readonly configFileUri: Uri;
|
||||
private readonly userConfigFileUri: Uri;
|
||||
private configJSON: MaterialThemeConfig;
|
||||
|
||||
constructor() {
|
||||
const extensionFolderUri = Uri.file(extensions.getExtension(MATERIAL_THEME_EXT_ID).extensionPath);
|
||||
this.configFileUri = extensionFolderUri.with({path: posix.join(extensionFolderUri.path, CONFIG_FILE_NAME)});
|
||||
this.userConfigFileUri = extensionFolderUri.with({path: posix.join(extensionFolderUri.path, USER_CONFIG_FILE_NAME)});
|
||||
this.init();
|
||||
}
|
||||
|
||||
getPackageJSON(): Record<string, any> {
|
||||
return extensions.getExtension(MATERIAL_THEME_EXT_ID).packageJSON;
|
||||
}
|
||||
|
||||
getConfig(): MaterialThemeConfig {
|
||||
return this.configJSON;
|
||||
}
|
||||
|
||||
getInstallationType(): InstallationType {
|
||||
return this.installationType;
|
||||
}
|
||||
|
||||
async updateConfig(config: Partial<MaterialThemeConfig>): Promise<void> {
|
||||
const newConfig = {...this.configJSON, ...config};
|
||||
await workspace.fs.writeFile(this.configFileUri, Buffer.from(JSON.stringify(newConfig), 'utf-8'));
|
||||
}
|
||||
|
||||
private isVersionUpdate(userConfig: MaterialThemeConfig): boolean {
|
||||
const splitVersion = (input: string): {major: number; minor: number; patch: number} => {
|
||||
const [major, minor, patch] = input.split('.').map(i => parseInt(i, 10));
|
||||
return {major, minor, patch};
|
||||
};
|
||||
|
||||
const packageJSON = this.getPackageJSON();
|
||||
|
||||
const versionCurrent = splitVersion(packageJSON.version);
|
||||
const versionOld = splitVersion(userConfig.changelog.lastversion);
|
||||
|
||||
const update = (
|
||||
versionCurrent.major > versionOld.major ||
|
||||
versionCurrent.minor > versionOld.minor ||
|
||||
versionCurrent.patch > versionOld.patch
|
||||
);
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
private async getUserConfig(): Promise<MaterialThemeConfig | undefined> {
|
||||
try {
|
||||
const configBuffer = await workspace.fs.readFile(this.userConfigFileUri);
|
||||
const configContent = Buffer.from(configBuffer).toString('utf8');
|
||||
return JSON.parse(configContent) as MaterialThemeConfig;
|
||||
} catch {}
|
||||
}
|
||||
|
||||
private async init(): Promise<void> {
|
||||
try {
|
||||
const userConfig = await this.getUserConfig();
|
||||
this.installationType = {
|
||||
update: userConfig && this.isVersionUpdate(userConfig),
|
||||
firstInstall: !userConfig
|
||||
};
|
||||
|
||||
const configBuffer = await workspace.fs.readFile(this.configFileUri);
|
||||
const configContent = Buffer.from(configBuffer).toString('utf8');
|
||||
|
||||
await workspace.fs.writeFile(this.userConfigFileUri, configBuffer);
|
||||
|
||||
this.configJSON = JSON.parse(configContent) as MaterialThemeConfig;
|
||||
} catch (error) {
|
||||
this.configJSON = {accentsProperties: {}, accents: {}};
|
||||
window
|
||||
.showErrorMessage(`Material Theme: there was an error while loading the configuration. Please retry or open an issue: ${String(error)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const extensionManager = new ExtensionManager();
|
28
src/core/settings-manager.ts
Normal file
28
src/core/settings-manager.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
|
||||
import {workspace} from 'vscode';
|
||||
|
||||
type ThemeCustomSettings = {
|
||||
accent?: string;
|
||||
};
|
||||
|
||||
export interface ISettingsManager {
|
||||
getSettings: () => ThemeCustomSettings;
|
||||
}
|
||||
|
||||
class SettingsManager implements ISettingsManager {
|
||||
private readonly customSettings: ThemeCustomSettings;
|
||||
|
||||
constructor() {
|
||||
this.customSettings = workspace.getConfiguration().get<ThemeCustomSettings>('materialTheme', {});
|
||||
}
|
||||
|
||||
getSettings(): ThemeCustomSettings {
|
||||
return this.customSettings;
|
||||
}
|
||||
|
||||
async updateSetting(key: keyof ThemeCustomSettings, value: string): Promise<void> {
|
||||
await workspace.getConfiguration().update(`materialTheme.${key}`, value, true);
|
||||
}
|
||||
}
|
||||
|
||||
export const settingsManager = new SettingsManager();
|
8
src/env.ts
Normal file
8
src/env.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import * as path from 'path';
|
||||
|
||||
export const SRC_FOLDER_PATH = path.resolve('./src');
|
||||
export const BUILD_FOLDER_PATH = path.resolve('./build');
|
||||
export const TS_BUILD_FOLDER_PATH = path.resolve('./dist');
|
||||
export const CONFIG_FILE_NAME = 'material-theme.config.json';
|
||||
export const USER_CONFIG_FILE_NAME = 'user.material-theme.config.json';
|
||||
export const MATERIAL_THEME_EXT_ID = 'equinusocio.vsc-material-theme';
|
|
@ -1,34 +0,0 @@
|
|||
import {getDefaultValues, getPackageJSON} from './fs';
|
||||
import {IInstallationType} from '../interfaces/iinstallation-type';
|
||||
|
||||
const splitVersion = (input: string): {major: number; minor: number; patch: number} => {
|
||||
const [major, minor, patch] = input.split('.').map(i => parseInt(i, 10));
|
||||
return {major, minor, patch};
|
||||
};
|
||||
|
||||
export default (): IInstallationType => {
|
||||
const out: IInstallationType = {
|
||||
isUpdate: false,
|
||||
isFirstInstall: false
|
||||
};
|
||||
|
||||
const defaults = getDefaultValues();
|
||||
const packageJSON = getPackageJSON();
|
||||
|
||||
const isFirstInstall = defaults.changelog === undefined ||
|
||||
(defaults.changelog !== undefined && typeof defaults.changelog.lastversion !== 'string');
|
||||
|
||||
if (isFirstInstall) {
|
||||
return {...out, isFirstInstall};
|
||||
}
|
||||
|
||||
const versionCurrent = splitVersion(packageJSON.version);
|
||||
const versionOld = isFirstInstall ? null : splitVersion(defaults.changelog.lastversion);
|
||||
|
||||
const isUpdate = !versionOld ||
|
||||
versionCurrent.major > versionOld.major ||
|
||||
versionCurrent.minor > versionOld.minor ||
|
||||
versionCurrent.patch > versionOld.patch;
|
||||
|
||||
return {...out, isUpdate};
|
||||
};
|
|
@ -1,47 +0,0 @@
|
|||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import {IPackageJSON} from '../interfaces/ipackage.json';
|
||||
|
||||
import {CHARSET} from './../consts/files';
|
||||
import {IDefaults} from '../interfaces/idefaults';
|
||||
import {PATHS} from '../consts/paths';
|
||||
|
||||
export function ensureDir(dirname: string): void {
|
||||
if (!fs.existsSync(dirname)) {
|
||||
fs.mkdirSync(dirname);
|
||||
}
|
||||
}
|
||||
|
||||
export function getDefaultValues(): IDefaults {
|
||||
const defaults: IDefaults = require(path.join(PATHS.VSIX_DIR, 'defaults.json'));
|
||||
|
||||
if (defaults === undefined || defaults === null) {
|
||||
throw new Error('Cannot find defaults params');
|
||||
}
|
||||
|
||||
return defaults;
|
||||
}
|
||||
|
||||
export function getAbsolutePath(input: string): string {
|
||||
return path.join(PATHS.VSIX_DIR, input);
|
||||
}
|
||||
|
||||
export function getAccentsProperties() {
|
||||
return getDefaultValues().accentsProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets package JSON
|
||||
*/
|
||||
export function getPackageJSON(): IPackageJSON {
|
||||
return require(path.join(PATHS.VSIX_DIR, './package.json'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a file inside the vsix directory
|
||||
*/
|
||||
export function writeFile(filename: string, filecontent: string): void {
|
||||
const filePath = path.join(PATHS.VSIX_DIR, filename);
|
||||
fs.writeFileSync(filePath, filecontent, {encoding: CHARSET});
|
||||
}
|
|
@ -2,7 +2,7 @@ import {
|
|||
window as Window
|
||||
} from 'vscode';
|
||||
|
||||
const MESSAGES = {
|
||||
export const MESSAGES = {
|
||||
CHANGELOG: {
|
||||
message: 'Material Theme was updated. Check the release notes for more details.',
|
||||
options: {ok: 'Show me', cancel: 'Maybe later'}
|
||||
|
@ -12,14 +12,7 @@ const MESSAGES = {
|
|||
}
|
||||
};
|
||||
|
||||
export const changelogMessage = async () =>
|
||||
await Window.showInformationMessage(
|
||||
MESSAGES.CHANGELOG.message,
|
||||
MESSAGES.CHANGELOG.options.ok,
|
||||
MESSAGES.CHANGELOG.options.cancel
|
||||
) === MESSAGES.CHANGELOG.options.ok;
|
||||
|
||||
export const installationMessage = async () =>
|
||||
await Window.showInformationMessage(
|
||||
export const installationMessage = async (): Promise<string> =>
|
||||
Window.showInformationMessage(
|
||||
MESSAGES.INSTALLATION.message
|
||||
);
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
import * as vscode from 'vscode';
|
||||
|
||||
import {IDefaults} from './../interfaces/idefaults';
|
||||
import {IThemeCustomSettings} from './../interfaces/itheme-custom-properties';
|
||||
import {getPackageJSON} from './fs';
|
||||
|
||||
/**
|
||||
* Gets saved accent
|
||||
*/
|
||||
export function getAccent(): string | undefined {
|
||||
return getCustomSettings().accent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets custom settings
|
||||
*/
|
||||
export function getCustomSettings(): IThemeCustomSettings {
|
||||
return vscode.workspace.getConfiguration().get<IThemeCustomSettings>('materialTheme', {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get showReloadNotification
|
||||
*/
|
||||
export function isReloadNotificationEnable(): boolean {
|
||||
return vscode.workspace.getConfiguration().get<boolean>('materialTheme.showReloadNotification');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given string could be an accent
|
||||
*/
|
||||
export function isAccent(accentName: string, defaults: IDefaults): boolean {
|
||||
return Boolean(Object.keys(defaults.accents).find(name => name === accentName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the passing theme id is a material theme
|
||||
*/
|
||||
export function isMaterialTheme(themeName: string): boolean {
|
||||
const packageJSON = getPackageJSON();
|
||||
return Boolean(packageJSON.contributes.themes.find(contrib => contrib.label === themeName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom property in custom settings
|
||||
*/
|
||||
export function setCustomSetting(settingName: string, value: any): Thenable<string> {
|
||||
return vscode.workspace.getConfiguration().update(`materialTheme.${settingName}`, value, true).then(() => settingName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates accent name
|
||||
*/
|
||||
export function updateAccent(accentName: string): Thenable<string> {
|
||||
return setCustomSetting('accent', accentName);
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
import * as vscode from 'vscode';
|
||||
|
||||
/**
|
||||
* Gets your current theme ID
|
||||
*/
|
||||
export function getCurrentThemeID(): string {
|
||||
return vscode.workspace.getConfiguration().get<string>('workbench.colorTheme');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads current vscode window.
|
||||
*/
|
||||
export function reloadWindow(): void {
|
||||
vscode.commands.executeCommand('workbench.action.reloadWindow');
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import * as path from 'path';
|
||||
import {getDefaultValues, getPackageJSON, writeFile} from './fs';
|
||||
|
||||
import {IDefaults} from '../interfaces/idefaults';
|
||||
|
||||
const writeDefaults = (defaults: IDefaults) =>
|
||||
writeFile(path.join('./defaults.json'), JSON.stringify(defaults, null, 2));
|
||||
|
||||
export default (): void => {
|
||||
const defaults = getDefaultValues();
|
||||
const packageJSON = getPackageJSON();
|
||||
|
||||
const newChangelog = {...defaults.changelog, lastversion: packageJSON.version};
|
||||
const newDefaults = {...defaults, changelog: newChangelog};
|
||||
writeDefaults(newDefaults);
|
||||
};
|
|
@ -1,4 +0,0 @@
|
|||
export interface IAccentCustomProperty {
|
||||
alpha: number;
|
||||
value: any;
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
import {IGenericObject} from './igeneric-object';
|
||||
import {IAccentCustomProperty} from './iaccent-custom-property';
|
||||
|
||||
export interface IDefaults {
|
||||
accents: IAccents;
|
||||
accentsProperties: IGenericObject <IAccentCustomProperty>;
|
||||
changelog: IChangelog;
|
||||
themeVariants: IDefaultsThemeVariant;
|
||||
themeVariantsColours: IDefaultsThemeVariant;
|
||||
themeVariantsUITheme: IDefaultsThemeVariant;
|
||||
[Symbol.iterator](): IterableIterator<IDefaults>;
|
||||
}
|
||||
|
||||
export interface IAccents {
|
||||
teal: string;
|
||||
[index: string]: string;
|
||||
}
|
||||
|
||||
export interface IChangelog {
|
||||
lastversion: string;
|
||||
[Symbol.iterator](): IterableIterator<IChangelog>;
|
||||
}
|
||||
|
||||
export interface IDefaultsThemeVariant {
|
||||
[index: string]: string;
|
||||
Darker: string;
|
||||
DarkerHighContrast: string;
|
||||
Default: string;
|
||||
DefaultHighContrast: string;
|
||||
Light: string;
|
||||
LightHighContrast: string;
|
||||
PalenightHighContrast: string;
|
||||
Ocean: string;
|
||||
OceanHighContrast: string;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
export interface IGenericObject<TValue> {
|
||||
[index: string]: TValue;
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
export interface IInstallationType {
|
||||
isUpdate: boolean;
|
||||
isFirstInstall: boolean;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
import {IGenericObject} from '../interfaces/igeneric-object';
|
||||
|
||||
export interface IPackageJSONBadge {
|
||||
description: string;
|
||||
href: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface IPackageJSONContributes {
|
||||
commands: IPackageJSONCommand[];
|
||||
configuration: IPackageJSONConfiguration;
|
||||
themes: IPackageJSONTheme[];
|
||||
}
|
||||
|
||||
export interface IPackageJSONConfiguration {
|
||||
properties: {};
|
||||
}
|
||||
|
||||
export interface IPackageJSONCommand {
|
||||
category: string;
|
||||
command: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface IPackageJSONTheme {
|
||||
label: string;
|
||||
path: string;
|
||||
uiTheme: string;
|
||||
}
|
||||
|
||||
export interface IPackageJSON {
|
||||
activationEvents: string[];
|
||||
badges: IPackageJSONBadge[];
|
||||
contributes: IPackageJSONContributes;
|
||||
bugs: IGenericObject<string>;
|
||||
categories: string[];
|
||||
description: string;
|
||||
displayName: string;
|
||||
engines: IGenericObject<string>;
|
||||
galleryBanner: IGenericObject<string>;
|
||||
homepage: string;
|
||||
icon: string;
|
||||
license: string;
|
||||
main: string;
|
||||
name: string;
|
||||
preview: boolean;
|
||||
publisher: string;
|
||||
repository: IGenericObject<string>;
|
||||
scripts: IGenericObject<string>;
|
||||
version: string;
|
||||
devDependencies: IGenericObject<string>;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
export interface IPaths {
|
||||
/**
|
||||
* Src dir
|
||||
*/
|
||||
SRC: string;
|
||||
/**
|
||||
* Themes dir
|
||||
*/
|
||||
THEMES: string;
|
||||
/**
|
||||
* Extension directory
|
||||
*/
|
||||
VSIX_DIR: string;
|
||||
VSIX_SRC_DIR: string;
|
||||
/**
|
||||
* Internal Extensions directory
|
||||
*/
|
||||
EXT_DIR: string;
|
||||
/**
|
||||
* UI directory
|
||||
*/
|
||||
UI: string;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
export interface IThemeCustomSettings {
|
||||
accent?: string;
|
||||
}
|
|
@ -4,33 +4,25 @@ import {
|
|||
} from 'vscode';
|
||||
|
||||
import * as ThemeCommands from './commands';
|
||||
import {updateAccent} from './helpers/settings';
|
||||
import {changelogMessage, installationMessage} from './helpers/messages';
|
||||
import checkInstallation from './helpers/check-installation';
|
||||
import writeChangelog from './helpers/write-changelog';
|
||||
import {installationMessage} from './helpers/messages';
|
||||
import {ReleaseNotesWebview} from './webviews/ReleaseNotes';
|
||||
import {changelogManager} from './core/changelog-manager';
|
||||
import {extensionManager} from './core/extension-manager';
|
||||
|
||||
export async function activate(context: ExtensionContext): Promise<void> {
|
||||
const installationType = checkInstallation();
|
||||
const releaseNotesView = new ReleaseNotesWebview(context);
|
||||
const installationType = extensionManager.getInstallationType();
|
||||
|
||||
writeChangelog();
|
||||
|
||||
if (installationType.isFirstInstall) {
|
||||
// TODO: BEFORE RELEASE add new message for new install because with the refactor also updates will be considered as new install, for the first time
|
||||
if (installationType.firstInstall) {
|
||||
await installationMessage();
|
||||
}
|
||||
|
||||
const shouldShowChangelog = (installationType.isFirstInstall || installationType.isUpdate) && await changelogMessage();
|
||||
if (shouldShowChangelog) {
|
||||
releaseNotesView.show();
|
||||
if ((installationType.firstInstall || installationType.update) && await changelogManager.askShowChangelog()) {
|
||||
await releaseNotesView.show();
|
||||
}
|
||||
|
||||
// Registering commands
|
||||
Commands.registerCommand('materialTheme.setAccent', async () => {
|
||||
const accentPicked = await ThemeCommands.accentsQuickPick();
|
||||
await ThemeCommands.accentsSetter(accentPicked);
|
||||
await updateAccent(accentPicked);
|
||||
});
|
||||
|
||||
Commands.registerCommand('materialTheme.setAccent', ThemeCommands.setAccent);
|
||||
Commands.registerCommand('materialTheme.showReleaseNotes', async () => releaseNotesView.show());
|
||||
}
|
||||
|
|
|
@ -1,44 +1,45 @@
|
|||
import {WebviewController} from './Webview';
|
||||
import {
|
||||
workspace as Workspace
|
||||
} from 'vscode';
|
||||
import {ISettingsBootstrap} from './interfaces';
|
||||
import {getCustomSettings} from '../helpers/settings';
|
||||
import {getDefaultValues} from '../helpers/fs';
|
||||
// WIP
|
||||
// Import {WebviewController} from './Webview';
|
||||
// import {
|
||||
// workspace as Workspace
|
||||
// } from 'vscode';
|
||||
// import {ISettingsBootstrap} from './interfaces';
|
||||
// import {getCustomSettings} from '../helpers/settings';
|
||||
// import {getDefaultValues} from '../helpers/fs';
|
||||
|
||||
export class SettingsWebview extends WebviewController<ISettingsBootstrap> {
|
||||
get filename(): string {
|
||||
return 'settings.html';
|
||||
}
|
||||
// export class SettingsWebview extends WebviewController<ISettingsBootstrap> {
|
||||
// get filename(): string {
|
||||
// return 'settings.html';
|
||||
// }
|
||||
|
||||
get id(): string {
|
||||
return 'materialTheme.settings';
|
||||
}
|
||||
// get id(): string {
|
||||
// return 'materialTheme.settings';
|
||||
// }
|
||||
|
||||
get title(): string {
|
||||
return 'Material Theme Settings';
|
||||
}
|
||||
// get title(): string {
|
||||
// return 'Material Theme Settings';
|
||||
// }
|
||||
|
||||
/**
|
||||
* This will be called by the WebviewController when init the view
|
||||
* passing as `window.bootstrap` to the view.
|
||||
*/
|
||||
getBootstrap(): ISettingsBootstrap {
|
||||
return {
|
||||
config: getCustomSettings(),
|
||||
defaults: getDefaultValues(),
|
||||
scope: 'user',
|
||||
scopes: this.getAvailableScopes()
|
||||
};
|
||||
}
|
||||
// /**
|
||||
// * This will be called by the WebviewController when init the view
|
||||
// * passing as `window.bootstrap` to the view.
|
||||
// */
|
||||
// getBootstrap(): ISettingsBootstrap {
|
||||
// return {
|
||||
// config: getCustomSettings(),
|
||||
// defaults: getDefaultValues(),
|
||||
// scope: 'user',
|
||||
// scopes: this.getAvailableScopes()
|
||||
// };
|
||||
// }
|
||||
|
||||
private getAvailableScopes(): Array<['user' | 'workspace', string]> {
|
||||
const scopes: Array<['user' | 'workspace', string]> = [['user', 'User']];
|
||||
return scopes
|
||||
.concat(
|
||||
Workspace.workspaceFolders?.length ?
|
||||
['workspace', 'Workspace'] :
|
||||
[]
|
||||
);
|
||||
}
|
||||
}
|
||||
// private getAvailableScopes(): Array<['user' | 'workspace', string]> {
|
||||
// const scopes: Array<['user' | 'workspace', string]> = [['user', 'User']];
|
||||
// return scopes
|
||||
// .concat(
|
||||
// Workspace.workspaceFolders?.length ?
|
||||
// ['workspace', 'Workspace'] :
|
||||
// []
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -12,8 +12,7 @@ import {
|
|||
Uri
|
||||
} from 'vscode';
|
||||
|
||||
import {getCustomSettings} from '../helpers/settings';
|
||||
import {Invalidates, Message, ISettingsChangedMessage} from './interfaces';
|
||||
import {Invalidates, Message} from './interfaces';
|
||||
|
||||
export abstract class WebviewController<TBootstrap> extends Disposable {
|
||||
private panel: WebviewPanel | undefined;
|
||||
|
@ -38,7 +37,7 @@ export abstract class WebviewController<TBootstrap> extends Disposable {
|
|||
const html = await this.getHtml();
|
||||
|
||||
const rootPath = Uri
|
||||
.file(this.context.asAbsolutePath('./out'))
|
||||
.file(this.context.asAbsolutePath('./build'))
|
||||
.with({scheme: 'vscode-resource'}).toString();
|
||||
|
||||
// Replace placeholders in html content for assets and adding configurations as `window.bootstrap`
|
||||
|
@ -93,32 +92,32 @@ export abstract class WebviewController<TBootstrap> extends Disposable {
|
|||
|
||||
private async getHtml(): Promise<string> {
|
||||
const doc = await Workspace
|
||||
.openTextDocument(this.context.asAbsolutePath(path.join('out/ui', this.filename)));
|
||||
.openTextDocument(this.context.asAbsolutePath(path.join('build/ui', this.filename)));
|
||||
return doc.getText();
|
||||
}
|
||||
|
||||
private async postMessage(message: Message, invalidates: Invalidates = 'all'): Promise<boolean> {
|
||||
if (this.panel === undefined) {
|
||||
return false;
|
||||
}
|
||||
// Private async postMessage(message: Message, invalidates: Invalidates = 'all'): Promise<boolean> {
|
||||
// if (this.panel === undefined) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
const result = await this.panel.webview.postMessage(message);
|
||||
// const result = await this.panel.webview.postMessage(message);
|
||||
|
||||
// If post was ok, update invalidateOnVisible if different than default
|
||||
if (!result && this.invalidateOnVisible !== 'all') {
|
||||
this.invalidateOnVisible = invalidates;
|
||||
}
|
||||
// // If post was ok, update invalidateOnVisible if different than default
|
||||
// if (!result && this.invalidateOnVisible !== 'all') {
|
||||
// this.invalidateOnVisible = invalidates;
|
||||
// }
|
||||
|
||||
return result;
|
||||
}
|
||||
// return result;
|
||||
// }
|
||||
|
||||
private async postUpdatedConfiguration(): Promise<boolean> {
|
||||
// Post full raw configuration
|
||||
return this.postMessage({
|
||||
type: 'settingsChanged',
|
||||
config: getCustomSettings()
|
||||
} as ISettingsChangedMessage, 'config');
|
||||
}
|
||||
// Private async postUpdatedConfiguration(): Promise<boolean> {
|
||||
// // Post full raw configuration
|
||||
// return this.postMessage({
|
||||
// type: 'settingsChanged',
|
||||
// config: getCustomSettings()
|
||||
// } as ISettingsChangedMessage, 'config');
|
||||
// }
|
||||
|
||||
private onPanelDisposed(): void {
|
||||
if (this.disposablePanel) {
|
||||
|
@ -142,7 +141,8 @@ export abstract class WebviewController<TBootstrap> extends Disposable {
|
|||
switch (invalidContext) {
|
||||
case 'config':
|
||||
// Post the new configuration to the view
|
||||
return this.postUpdatedConfiguration();
|
||||
// return this.postUpdatedConfiguration();
|
||||
return;
|
||||
default:
|
||||
return this.show();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
import {IThemeCustomSettings} from '../interfaces/itheme-custom-properties';
|
||||
import {IDefaults} from '../interfaces/idefaults';
|
||||
|
||||
export interface IChangeType {
|
||||
children: Array<{
|
||||
text: string;
|
||||
|
@ -22,7 +19,7 @@ export interface IPostNormalized {
|
|||
}
|
||||
export interface ISettingsChangedMessage {
|
||||
type: 'settingsChanged';
|
||||
config: IThemeCustomSettings;
|
||||
config: {};
|
||||
}
|
||||
|
||||
export interface ISaveSettingsMessage {
|
||||
|
@ -39,13 +36,13 @@ export type Message = ISaveSettingsMessage | ISettingsChangedMessage;
|
|||
export type Invalidates = 'all' | 'config' | undefined;
|
||||
|
||||
export interface IBootstrap {
|
||||
config: IThemeCustomSettings;
|
||||
config: {};
|
||||
}
|
||||
|
||||
export interface ISettingsBootstrap extends IBootstrap {
|
||||
scope: 'user' | 'workspace';
|
||||
scopes: Array<['user' | 'workspace', string]>;
|
||||
defaults: IDefaults;
|
||||
defaults: {};
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as sanityClient from '@sanity/client';
|
||||
import sanityClient from '@sanity/client';
|
||||
|
||||
import {IPost, IPostNormalized} from '../../interfaces';
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import {ISettingsBootstrap} from '../../interfaces';
|
||||
import accentsSelector from './lib/accents-selector';
|
||||
// Import accentsSelector from './lib/accents-selector';
|
||||
|
||||
const run = (): void => {
|
||||
bind();
|
||||
|
||||
const {config, defaults} = window.bootstrap as ISettingsBootstrap;
|
||||
accentsSelector('[data-setting="accentSelector"]', defaults.accents, config.accent);
|
||||
// AccentsSelector('[data-setting="accentSelector"]', defaults.accents, config.accent);
|
||||
|
||||
console.log(defaults);
|
||||
console.log(config);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {IAccents} from '../../../../interfaces/idefaults';
|
||||
// Import {IAccents} from '../../../../interfaces/idefaults';
|
||||
|
||||
const templateSingleAccent = (accentName: string, accentColor: string): string => {
|
||||
const dashAccentName = accentName.toLowerCase().replace(/ /gi, '-');
|
||||
|
@ -9,7 +9,7 @@ const templateSingleAccent = (accentName: string, accentColor: string): string =
|
|||
`;
|
||||
};
|
||||
|
||||
export default (containerSelector: string, accentsObject: IAccents, currentAccent: string): void => {
|
||||
export default (containerSelector: string, accentsObject: Record<string, string>, currentAccent: string): void => {
|
||||
const container = document.querySelector(containerSelector);
|
||||
|
||||
for (const accentKey of Object.keys(accentsObject)) {
|
||||
|
|
|
@ -19,8 +19,7 @@
|
|||
"./types",
|
||||
"./src/**/*",
|
||||
"./test/**/*",
|
||||
"./scripts/**/*",
|
||||
"./env.ts"
|
||||
"./scripts/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
|
|
Loading…
Reference in a new issue