more cleanup

This commit is contained in:
Theo Browne 2025-02-26 01:05:05 -08:00
parent c83c3583a9
commit 1014de4096
No known key found for this signature in database
GPG key ID: BDDADD971F49875D
11 changed files with 46 additions and 3340 deletions

2975
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
"name": "vsc-material-theme-but-i-wont-sue-you",
"displayName": "Material Theme (But I Won't Sue You)",
"description": "A Apache-2 licensed fork of Material Theme with no threats of legal action",
"version": "35.0.0",
"version": "35.0.1",
"publisher": "t3dotgg",
"license": "Apache-2.0",
"author": "Theo",
@ -23,17 +23,15 @@
"vscode": "^1.51.0"
},
"scripts": {
"build": "run-s cleanup build:ts build:generate-themes build:ui",
"build": "run-s cleanup build:ts build:generate-themes",
"cleanup": "rimraf build && rimraf dist",
"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 && ncp material-theme.config.json build",
"postinstall": "node ./node_modules/vscode/bin/install && tsc -p tsconfig.json"
},
"categories": [
"Themes",
"Other"
"Themes"
],
"keywords": [
"VSCode",
@ -175,7 +173,7 @@
"fs-extra": "9.0.1",
"ncp": "2.0.0",
"npm-run-all": "4.1.5",
"standard-version": "9.5.0",
"rimraf": "3.0.2",
"typescript": "4.1.3",
"vscode": "1.1.37"
},

View file

@ -1,17 +0,0 @@
import * as fs from 'fs-extra';
import * as path from 'path';
import {BUILD_FOLDER_PATH} from '../../src/env';
const UI_FOLDER_BUILD_PATH = path.join(BUILD_FOLDER_PATH, 'ui');
const run = async (): Promise<void> => {
try {
await fs.mkdirp(UI_FOLDER_BUILD_PATH);
} catch (error) {
console.error('ERROR build:ui:', error);
process.exit(1);
}
};
void run();

View file

@ -17,16 +17,10 @@ type PackageJSON = {
};
};
type InstallationType = {
firstInstall: boolean;
update: boolean;
};
export interface IExtensionManager {
init: (context: ExtensionContext) => Promise<void>;
getPackageJSON: () => PackageJSON;
getConfig: () => MaterialThemeConfig;
getInstallationType: () => Record<string, unknown>;
updateConfig: (config: Partial<MaterialThemeConfig>) => Promise<void>;
VERSION_KEY: string;
}
@ -36,7 +30,6 @@ class ExtensionManager implements IExtensionManager {
return 'vsc-material-theme.version';
}
installationType: InstallationType;
private readonly configFileUri: Uri;
private readonly userConfigFileUri: Uri;
private configJSON: MaterialThemeConfig;
@ -55,10 +48,6 @@ class ExtensionManager implements IExtensionManager {
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'));
@ -67,62 +56,27 @@ class ExtensionManager implements IExtensionManager {
async init(context: ExtensionContext): Promise<void> {
try {
const packageJSON = this.getPackageJSON();
const userConfig = await this.getUserConfig();
const mementoStateVersion = context.globalState.get(this.VERSION_KEY);
const themeNeverUsed = mementoStateVersion === undefined || typeof mementoStateVersion !== 'string';
this.installationType = {
update: userConfig && this.isVersionUpdate(userConfig, packageJSON),
firstInstall: !userConfig && themeNeverUsed
};
// Theme not used before across devices
if (themeNeverUsed) {
await context.globalState.update(this.VERSION_KEY, packageJSON.version);
}
// Load configuration
const configBuffer = await workspace.fs.readFile(this.configFileUri);
const configContent = Buffer.from(configBuffer).toString('utf8');
this.configJSON = JSON.parse(configContent) as MaterialThemeConfig;
// Update version in user config
const userConfigUpdate = {...this.configJSON, changelog: {lastversion: packageJSON.version}};
await workspace.fs.writeFile(
this.userConfigFileUri,
Buffer.from(JSON.stringify(userConfigUpdate), 'utf-8')
);
// Store version in global state
await context.globalState.update(this.VERSION_KEY, packageJSON.version);
} catch (error) {
this.configJSON = {accentsProperties: {}, accents: {}};
await window
.showErrorMessage(`Material Theme: there was an error while loading the configuration. Please retry or open an issue: ${String(error)}`);
}
}
private isVersionUpdate(userConfig: MaterialThemeConfig, packageJSON: PackageJSON): 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 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 {}
}
}
export const extensionManager = new ExtensionManager();

View file

@ -1,45 +0,0 @@
// 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';
// }
// get id(): string {
// return 'materialTheme.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()
// };
// }
// private getAvailableScopes(): Array<['user' | 'workspace', string]> {
// const scopes: Array<['user' | 'workspace', string]> = [['user', 'User']];
// return scopes
// .concat(
// Workspace.workspaceFolders?.length ?
// ['workspace', 'Workspace'] :
// []
// );
// }
// }

View file

@ -1,161 +0,0 @@
import * as path from 'path';
import {
workspace as Workspace,
Disposable,
ExtensionContext,
WebviewPanel,
ViewColumn,
window,
WebviewPanelOnDidChangeViewStateEvent,
Uri
} from 'vscode';
import {Invalidates, Message} from './interfaces';
export abstract class WebviewController<TBootstrap> extends Disposable {
private panel: WebviewPanel | undefined;
private disposablePanel: Disposable | undefined;
private invalidateOnVisible: Invalidates;
private readonly context: ExtensionContext;
constructor(context: ExtensionContext) {
// Applying dispose callback for our disposable function
super(() => this.dispose());
this.context = context;
}
dispose(): void {
if (this.disposablePanel) {
this.disposablePanel.dispose();
}
}
async show(): Promise<void> {
const html = await this.getHtml();
// If panel already opened just reveal
if (this.panel !== undefined) {
// Replace placeholders in html content for assets and adding configurations as `window.bootstrap`
const fullHtml = this.replaceInPanel(html);
this.panel.webview.html = fullHtml;
return this.panel.reveal(ViewColumn.Active);
}
this.panel = window.createWebviewPanel(
this.id,
this.title,
ViewColumn.Active,
{
retainContextWhenHidden: true,
enableFindWidget: true,
enableCommandUris: true,
enableScripts: true
}
);
// Applying listeners
this.disposablePanel = Disposable.from(
this.panel,
this.panel.onDidDispose(this.onPanelDisposed, this),
this.panel.onDidChangeViewState(this.onViewStateChanged, this),
this.panel.webview.onDidReceiveMessage(this.onMessageReceived, this)
);
// Replace placeholders in html content for assets and adding configurations as `window.bootstrap`
const fullHtml = this.replaceInPanel(html);
this.panel.webview.html = fullHtml;
}
protected onMessageReceived(event: Message): void {
if (event === null) {
return;
}
console.log(`WebviewEditor.onMessageReceived: type=${event.type}, data=${JSON.stringify(event)}`);
switch (event.type) {
case 'saveSettings':
// TODO: update settings
break;
default:
break;
}
}
private replaceInPanel(html: string): string {
// Replace placeholders in html content for assets and adding configurations as `window.bootstrap`
const fullHtml = html
.replace(/{{root}}/g, this.panel.webview.asWebviewUri(Uri.file(this.context.asAbsolutePath('./build'))).toString())
.replace(/{{cspSource}}/g, this.panel.webview.cspSource)
.replace('\'{{bootstrap}}\'', JSON.stringify(this.getBootstrap()));
return fullHtml;
}
private async getHtml(): Promise<string> {
const doc = await Workspace
.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;
// }
// 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;
// }
// return result;
// }
// 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) {
this.disposablePanel.dispose();
}
this.panel = undefined;
}
private async onViewStateChanged(event: WebviewPanelOnDidChangeViewStateEvent): Promise<void> {
console.log('WebviewEditor.onViewStateChanged', event.webviewPanel.visible);
if (!this.invalidateOnVisible || !event.webviewPanel.visible) {
return;
}
// Update the view since it can be outdated
const invalidContext = this.invalidateOnVisible;
this.invalidateOnVisible = undefined;
switch (invalidContext) {
case 'config':
// Post the new configuration to the view
// return this.postUpdatedConfiguration();
return;
default:
return this.show();
}
}
abstract get filename(): string;
abstract get id(): string;
abstract get title(): string;
abstract getBootstrap(): TBootstrap;
}

View file

@ -1,33 +0,0 @@
export interface ISettingsChangedMessage {
type: 'settingsChanged';
config: Record<string, unknown>;
}
export interface ISaveSettingsMessage {
type: 'saveSettings';
changes: {
[key: string]: any;
};
removes: string[];
scope: 'user' | 'workspace';
uri: string;
}
export type Message = ISaveSettingsMessage | ISettingsChangedMessage;
export type Invalidates = 'all' | 'config' | undefined;
export interface IBootstrap {
config: Record<string, unknown>;
}
export interface ISettingsBootstrap extends IBootstrap {
scope: 'user' | 'workspace';
scopes: Array<['user' | 'workspace', string]>;
defaults: Record<string, unknown>;
}
declare global {
interface Window {
bootstrap: IBootstrap | ISettingsBootstrap | Record<string, unknown>;
}
}

View file

@ -1,20 +0,0 @@
import {ISettingsBootstrap} from '../../interfaces';
// 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);
console.log(defaults);
console.log(config);
};
const bind = (): void => {
document.querySelector('#fixIconsCTA').addEventListener('click', () => {
console.log('Test click');
});
};
run();

View file

@ -1,26 +0,0 @@
// Import {IAccents} from '../../../../interfaces/idefaults';
const templateSingleAccent = (accentName: string, accentColor: string): string => {
const dashAccentName = accentName.toLowerCase().replace(/ /gi, '-');
return `
<label for="${dashAccentName}" data-color="${accentColor}">${accentName}</label>
<input type="radio" name="accents" id="${dashAccentName}" value="${dashAccentName}" />
`;
};
export default (containerSelector: string, accentsObject: Record<string, string>, currentAccent: string): void => {
const container = document.querySelector(containerSelector);
for (const accentKey of Object.keys(accentsObject)) {
const el = document.createElement('div');
el.innerHTML = templateSingleAccent(accentKey, accentsObject[accentKey]);
if (accentKey === currentAccent) {
el.setAttribute('selected', 'true');
el.querySelector('input').setAttribute('checked', 'checked');
}
container.appendChild(el);
}
};

View file

@ -1,39 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Material Theme Settings Editor</title>
<link rel="stylesheet" href="{{root}}/ui/settings/style.css">
<link rel="stylesheet" href="https://unpkg.com/@native-elements/native-elements/dist/native-elements.css">
</head>
<body>
<header>
<h1>Material Theme Settings Editor (preview)</h1>
</header>
<main>
<button ne-button tabindex="2" autofocus>Button</button>
<div class="SettingsContainer">
<div>
<label>Fix file icons</label>
<input id="fixIconsCTA" type="submit" value="Fix">
</div>
<div class="AccentsRadioContainer" data-setting="accentSelector">
<!-- Populated by js -->
</div>
</div>
</main>
<input value="Example input">
<script type="text/javascript">
window.bootstrap = '{{bootstrap}}';
</script>
<script type="text/javascript" src="{{root}}/ui/settings.js"></script>
</body>
</html>

View file

@ -1,4 +0,0 @@
.AccentsRadioContainer > div {
display: inline-block;
margin-right: 10px;
}