Skip to content

Commit

Permalink
Updated change detection
Browse files Browse the repository at this point in the history
  • Loading branch information
PKief committed Feb 27, 2018
1 parent 58476c5 commit 30e9b3b
Show file tree
Hide file tree
Showing 20 changed files with 173 additions and 142 deletions.
2 changes: 1 addition & 1 deletion scripts/icons/generateJson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as path from 'path';
import * as fs from 'fs';
import * as painter from '../helpers/painter';

createIconFile().then((fileName) => {
createIconFile().then((fileName: string) => {
const filePath = path.resolve('src', fileName);
const out = path.resolve('out', 'src', fileName);
fs.rename(filePath, out, (err) => {
Expand Down
4 changes: 2 additions & 2 deletions src/commands/folderColor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ const validateColorInput = (colorInput: string) => {
export const checkFolderColorStatus = (): Promise<string> => {
const defaultOptions = getDefaultIconOptions();
return helpers.getMaterialIconsJSON().then((config) =>
config.options.folderColor === undefined ?
defaultOptions.folderColor : config.options.folderColor);
config.options.folders.color === undefined ?
defaultOptions.folders.color : config.options.folders.color);
};

const setColorConfig = (value: string) => {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/folders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ const handleQuickPickActions = (value: vscode.QuickPickItem) => {

/** Are the folder icons enabled? */
export const checkFolderIconsStatus = (): Promise<string> => {
return helpers.getMaterialIconsJSON().then((config) => config.options.folderTheme);
return helpers.getMaterialIconsJSON().then((config) => config.options.folders.theme);
};
2 changes: 1 addition & 1 deletion src/commands/iconPacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const handleQuickPickActions = (value: vscode.QuickPickItem, activePack: string)
};

const getActiveIconPack = (): Promise<string> => {
return helpers.getMaterialIconsJSON().then((config) => config.options.activatedPack);
return helpers.getMaterialIconsJSON().then((config) => config.options.activeIconPack);
};

const isPackActive = (activePack: string, pack: string) => {
Expand Down
12 changes: 6 additions & 6 deletions src/commands/restoreConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { getDefaultIconOptions } from '../icons/index';
/** Restore all configurations to default. */
export const restoreDefaultConfig = () => {
const defaultOptions = getDefaultIconOptions();
helpers.setThemeConfig('activeIconPack', defaultOptions.activatedPack, true);
helpers.setThemeConfig('folders.theme', defaultOptions.folderTheme, true);
helpers.setThemeConfig('folders.color', defaultOptions.folderColor, true);
helpers.setThemeConfig('activeIconPack', defaultOptions.activeIconPack, true);
helpers.setThemeConfig('folders.theme', defaultOptions.folders.theme, true);
helpers.setThemeConfig('folders.color', defaultOptions.folders.color, true);
helpers.setThemeConfig('hidesExplorerArrows', defaultOptions.hidesExplorerArrows, true);
helpers.setThemeConfig('files.associations', defaultOptions.fileAssociations, true);
helpers.setThemeConfig('folders.associations', defaultOptions.folderAssociations, true);
helpers.setThemeConfig('languages.associations', defaultOptions.languageAssociations, true);
helpers.setThemeConfig('files.associations', defaultOptions.files.associations, true);
helpers.setThemeConfig('folders.associations', defaultOptions.folders.associations, true);
helpers.setThemeConfig('languages.associations', defaultOptions.languages.associations, true);
};
4 changes: 1 addition & 3 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ export const activate = (context: vscode.ExtensionContext) => {
showStartMessages(checkThemeStatus(context.globalState));
}).catch(err => console.error(err));

context.subscriptions.push(
...commands.commands
);
context.subscriptions.push(...commands.commands);

detectConfigChanges().catch(e => {
console.error(e);
Expand Down
91 changes: 41 additions & 50 deletions src/helpers/change-detection.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,56 @@
import * as helpers from './index';
import * as vscode from 'vscode';
import * as i18n from './../i18n';
import { createIconFile, getDefaultIconOptions } from '../icons/index';
import { checkFolderIconsStatus } from '../commands/folders';
import { IconPack, IconJsonOptions, IconAssociations } from '../models/index';
import * as merge from 'lodash.merge';
import { createIconFile } from '../icons/index';
import { getObjectPropertyValue, setObjectPropertyValue } from './objects';
import { getExtensionConfiguration, promptToReload, getMaterialIconsJSON, getThemeConfig } from '.';

/** Watch for changes in the configurations to update the icons theme. */
export const watchForConfigChanges = () => {
vscode.workspace.onDidChangeConfiguration(detectConfigChanges);
};

/**
* Compare the workspace and the user configurations
* with the current setup of the icons.
*/
/** Compare the workspace and the user configurations with the current setup of the icons. */
export const detectConfigChanges = () => {
return helpers.getMaterialIconsJSON()
.then((json) => {
compareConfig<string>('activeIconPack', json.options.activatedPack);
compareConfig<string>('folders.theme', json.options.folderTheme);
compareConfig<string>('folders.color', json.options.folderColor);
compareConfig<boolean>('hidesExplorerArrows', json.options.hidesExplorerArrows);
compareConfig<IconAssociations>('files.associations', json.options.fileAssociations);
compareConfig<IconAssociations>('folders.associations', json.options.folderAssociations);
compareConfig<IconAssociations>('languages.associations', json.options.languageAssociations);
const configs = Object.keys(getExtensionConfiguration())
.map(c => c.split('.').slice(1).join('.'));

return compareConfigs(configs).then(changes => {
// if there's nothing to update
if (Object.keys(changes).length === 0) return;

// update icon json file with new options
return createIconFile(changes).then(() => {
promptToReload();
}).catch(err => {
console.error(err);
});
};

const compareConfig = <T>(config: string, currentState: T): Promise<void> => {
const configValue = <T>helpers.getThemeConfig(config).globalValue;

return helpers.getMaterialIconsJSON().then(result => {
if (configValue !== undefined && JSON.stringify(configValue) !== JSON.stringify(currentState)) {
updateIconJson();
}
});
};

const updateIconJson = () => {
const defaultOptions = getDefaultIconOptions();

// adjust options
const options: IconJsonOptions = {
folderTheme: getCurrentConfig<string>('folders.theme', defaultOptions.folderTheme),
folderColor: getCurrentConfig<string>('folders.color', defaultOptions.folderColor),
activatedPack: getCurrentConfig<string>('activeIconPack', defaultOptions.activatedPack),
hidesExplorerArrows: getCurrentConfig<boolean>('hidesExplorerArrows', defaultOptions.hidesExplorerArrows),
fileAssociations: getCurrentConfig<IconAssociations>('files.associations', defaultOptions.fileAssociations),
folderAssociations: getCurrentConfig<IconAssociations>('folders.associations', defaultOptions.folderAssociations),
languageAssociations: getCurrentConfig<IconAssociations>('languages.associations', defaultOptions.languageAssociations),
};
/**
* Compares a specific configuration in the settings with a current configuration state.
* The current configuration state is read from the icons json file.
* @param configs List of configuration names
* @returns List of configurations that needs to be updated.
*/
const compareConfigs = (configs: string[]): Promise<{ [name: string]: any }> => {
// object with the config properties that must be updated
const updateRequired: { [name: string]: any } = {};

return getMaterialIconsJSON().then((json) => {
configs.forEach(configName => {
const configValue = getThemeConfig(configName).globalValue;
const currentState = getObjectPropertyValue(json.options, configName);

if (configValue !== undefined && JSON.stringify(configValue) !== JSON.stringify(currentState)) {
setObjectPropertyValue(updateRequired, configName, configValue);
}
});

// update icon json file with new options
return createIconFile(options).then(() => {
helpers.promptToReload();
}).catch(err => {
console.error(err);
if (Object.keys(updateRequired).length > 0) {
return merge({}, json.options, updateRequired);
} else {
return {};
}
});
};

const getCurrentConfig = <T>(config: string, defaultValue: T): T => {
const result = <T>helpers.getThemeConfig(config).globalValue;
return result !== undefined ? result : defaultValue;
};
6 changes: 5 additions & 1 deletion src/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ export const getConfig = (section?: string) => {
return vscode.workspace.getConfiguration(section) as AdvancedWorkspaceConfiguration;
};

/** Get list of configuration entries of package.json */
export const getExtensionConfiguration = (): { [config: string]: any } => {
return vscode.extensions.getExtension('PKief.material-icon-theme').packageJSON.contributes.configuration.properties;
};

/** Update configuration of vs code. */
export const setConfig = (section: string, value: any, global: boolean = false) => {
return getConfig().update(section, value, global);
Expand Down Expand Up @@ -81,4 +86,3 @@ export const capitalizeFirstLetter = (name: string): string => name.charAt(0).to
export const toTitleCase = (str) => {
return str.replace(/\w\S*/g, (txt) => { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); });
};

55 changes: 55 additions & 0 deletions src/helpers/objects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Get the nested properties of an object
* This solution is lighter than the lodash get-version and works fine for the translations.
* Source: http://stackoverflow.com/a/6491621/6942210
*/
export const getObjectPropertyValue = (obj: Object, path: string) => {
// convert indexes to properties
path = path.replace(/\[(\w+)\]/g, '.$1');

// strip a leading dot
path = path.replace(/^\./, '');

// separate paths in array
let pathArray = path.split('.');

/** Avoid errors in the getValue function. */
const isObject = (object) => {
return object === Object(object);
};

for (let i = 0; i < pathArray.length; ++i) {
let k = pathArray[i];
if (isObject(obj) && k in obj) {
obj = obj[k];
} else {
return;
}
}
return obj;
};

/**
* Set a value for a nested object property.
* @param obj Object
* @param path Properties as string e.g. `'a.b.c'`
* @param value Value to be set for the given property
* Source: https://stackoverflow.com/a/13719799/6942210
*/
export const setObjectPropertyValue = (obj: Object, path, value) => {
if (typeof path === 'string') {
path = path.split('.');
}

if (path.length > 1) {
let e = path.shift();
setObjectPropertyValue(obj[e] =
Object.prototype.toString.call(obj[e]) === '[object Object]'
? obj[e]
: {},
path,
value);
} else {
obj[path[0]] = value;
}
};
40 changes: 6 additions & 34 deletions src/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as vscode from 'vscode';
import * as fs from 'fs';
import { getObjectPropertyValue } from '../helpers/objects';

// Get current language of the vs code workspace
export const getCurrentLanguage = (): string =>
Expand Down Expand Up @@ -45,18 +46,18 @@ const getTranslationObject = async (language: string): Promise<any> => {
* and the fallback (required for testing purposes).
* */
export const getTranslationValue = (key: string, translations = currentTranslation, fallback = fallbackTranslation) => {
return getValue(translations, key) ?
getValue(translations, key) :
getValue(fallback, key) ?
getValue(fallback, key) : undefined;
return getObjectPropertyValue(translations, key) ?
getObjectPropertyValue(translations, key) :
getObjectPropertyValue(fallback, key) ?
getObjectPropertyValue(fallback, key) : undefined;
};

/**
* The instant method is required for the translate pipe.
* It helps to translate a word instantly.
*/
export const translate = (key: string, words?: string | string[]) => {
const translation: string = getTranslationValue(key);
const translation = <string>getTranslationValue(key);

if (!words) return translation;
return replace(translation, words);
Expand All @@ -77,32 +78,3 @@ export const replace = (value: string = '', words: string | string[]) => {

return translation;
};

/** Get the nested keys of an object (http://stackoverflow.com/a/6491621/6942210)
*
* *This solution is lighter than the lodash get-version and works fine for the translations.* */
export const getValue = (obj: any, key: string): string => {
// convert indexes to properties
key = key.replace(/\[(\w+)\]/g, '.$1');

// strip a leading dot
key = key.replace(/^\./, '');

// separate keys in array
let keyArray = key.split('.');

/** Avoid errors in the getValue function. */
const isObject = (object) => {
return object === Object(object);
};

for (let i = 0; i < keyArray.length; ++i) {
let k = keyArray[i];
if (isObject(obj) && k in obj) {
obj = obj[k];
} else {
return;
}
}
return obj;
};
10 changes: 5 additions & 5 deletions src/icons/generator/constants.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
/**
* Path where the icons are located.
*/
export const iconFolderPath = './../../icons/';
export const iconFolderPath: string = './../../icons/';

/**
* File name of the JSON file that will be generated to the out folder.
*/
export const iconJsonName = 'material-icons.json';
export const iconJsonName: string = 'material-icons.json';

/**
* File ending for opened folders.
*/
export const openedFolder = '-open';
export const openedFolder: string = '-open';

/**
* FIle ending for light icons.
*/
export const lightVersion = '_light';
export const lightVersion: string = '_light';

/**
* File ending for high contrast icons.
*/
export const highContrastVersion = '_highContrast';
export const highContrastVersion: string = '_highContrast';
4 changes: 2 additions & 2 deletions src/icons/generator/fileGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import * as merge from 'lodash.merge';
*/
export const getFileIconDefinitions = (fileIcons: FileIcons, config: IconConfiguration, options: IconJsonOptions): IconConfiguration => {
config = merge({}, config);
const enabledIcons = disableIconsByPack(fileIcons, options.activatedPack);
const customIcons = getCustomIcons(options.fileAssociations);
const enabledIcons = disableIconsByPack(fileIcons, options.activeIconPack);
const customIcons = getCustomIcons(options.files.associations);
const allFileIcons = [...enabledIcons, ...customIcons];

allFileIcons.forEach(icon => {
Expand Down
8 changes: 4 additions & 4 deletions src/icons/generator/folderGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import * as path from 'path';
export const getFolderIconDefinitions = (folderThemes: FolderTheme[], config: IconConfiguration, options: IconJsonOptions): IconConfiguration => {
config = merge({}, config);
config.hidesExplorerArrows = options.hidesExplorerArrows;
const activeTheme = getEnabledFolderTheme(folderThemes, options.folderTheme);
const enabledIcons = disableIconsByPack(activeTheme, options.activatedPack);
const customIcons = getCustomIcons(options.folderAssociations);
const activeTheme = getEnabledFolderTheme(folderThemes, options.folders.theme);
const enabledIcons = disableIconsByPack(activeTheme, options.activeIconPack);
const customIcons = getCustomIcons(options.folders.associations);
const allIcons = [...enabledIcons, ...customIcons];

if (options.folderTheme === 'none') {
if (options.folders.theme === 'none') {
return config;
}

Expand Down

0 comments on commit 30e9b3b

Please sign in to comment.