From 48c6feaf756904a50313e5d1de5f08d6a4dc4dd5 Mon Sep 17 00:00:00 2001 From: Alessio Occhipinti Date: Sun, 12 Aug 2018 19:09:36 +0200 Subject: [PATCH] Ux/reload notification (#232) * chore: check on installation type now as single module * feat(Reload notification): added support for after-install notification * feat(Reload notification): added support never show again notification --- extensions/helpers/check-installation.ts | 34 ++++++++++++++++++ extensions/helpers/configuration-change.ts | 24 ++++--------- extensions/helpers/handle-autoapply.ts | 31 ++++++++++++++++ extensions/helpers/messages.ts | 40 +++++++++++++++++---- extensions/helpers/settings.ts | 9 ++++- extensions/helpers/should-show-changelog.ts | 35 ------------------ extensions/helpers/write-changelog.ts | 16 +++++++++ extensions/interfaces/iinstallation-type.ts | 4 +++ extensions/material.theme.config.ts | 31 +++++++++------- package.json | 7 +++- 10 files changed, 158 insertions(+), 73 deletions(-) create mode 100644 extensions/helpers/check-installation.ts create mode 100644 extensions/helpers/handle-autoapply.ts delete mode 100644 extensions/helpers/should-show-changelog.ts create mode 100644 extensions/helpers/write-changelog.ts create mode 100644 extensions/interfaces/iinstallation-type.ts diff --git a/extensions/helpers/check-installation.ts b/extensions/helpers/check-installation.ts new file mode 100644 index 0000000..fc52488 --- /dev/null +++ b/extensions/helpers/check-installation.ts @@ -0,0 +1,34 @@ +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}; +}; diff --git a/extensions/helpers/configuration-change.ts b/extensions/helpers/configuration-change.ts index ef1e1aa..2ce4074 100644 --- a/extensions/helpers/configuration-change.ts +++ b/extensions/helpers/configuration-change.ts @@ -1,13 +1,10 @@ import { ConfigurationChangeEvent } from 'vscode'; -import {getCustomSettings, isMaterialThemeIcons, isAutoApplyEnable, isMaterialTheme} from './settings'; +import {getCustomSettings, isMaterialThemeIcons, isMaterialTheme} from './settings'; import {getCurrentThemeIconsID, getCurrentThemeID} from './vscode'; -import * as ThemeCommands from './../commands'; -import {infoMessage} from './messages'; - -const icons = () => isAutoApplyEnable() ? ThemeCommands.fixIcons() : infoMessage(); +import handleAutoapply from './handle-autoapply'; const onIconsChanged = () => { const customSettings = getCustomSettings(); @@ -16,27 +13,18 @@ const onIconsChanged = () => { } const currentIconsTheme = getCurrentThemeIconsID(); - if (isMaterialThemeIcons(currentIconsTheme)) { - return icons(); - } + return handleAutoapply(isMaterialThemeIcons(currentIconsTheme)); }; const onThemeChanged = () => { const currentTheme = getCurrentThemeID(); - if (isMaterialTheme(currentTheme)) { - return icons(); - } + return handleAutoapply(isMaterialTheme(currentTheme)); }; export const onChangeConfiguration = (event: ConfigurationChangeEvent) => { const isColorTheme = event.affectsConfiguration('workbench.colorTheme'); const isIconTheme = event.affectsConfiguration('workbench.iconTheme'); - if (isIconTheme) { - return onIconsChanged(); - } - - if (isColorTheme) { - return onThemeChanged(); - } + return isIconTheme ? onIconsChanged() : + isColorTheme ? onThemeChanged() : null; }; diff --git a/extensions/helpers/handle-autoapply.ts b/extensions/helpers/handle-autoapply.ts new file mode 100644 index 0000000..b2d914b --- /dev/null +++ b/extensions/helpers/handle-autoapply.ts @@ -0,0 +1,31 @@ +import {isAutoApplyEnable, isReloadNotificationEnable, setCustomSetting} from './settings'; +import {infoMessage} from './messages'; +import {fixIcons} from '../commands'; + +export default async (doubleCheck: boolean) => { + if (!doubleCheck) { + return; + } + + if (isAutoApplyEnable()) { + return fixIcons(); + } + + if (!isReloadNotificationEnable()) { + return; + } + + const result = await infoMessage(); + + if (result.nomore) { + return setCustomSetting('showReloadNotification', false); + } + + if (result.autoreload) { + setCustomSetting('autoApplyIcons', true); + } + + if (result.reload) { + return fixIcons(); + } +}; diff --git a/extensions/helpers/messages.ts b/extensions/helpers/messages.ts index c68c9d8..470ec59 100644 --- a/extensions/helpers/messages.ts +++ b/extensions/helpers/messages.ts @@ -2,24 +2,52 @@ import { window as Window } from 'vscode'; -import * as ThemeCommands from './../commands'; - const MESSAGES = { INFO: { message: 'Do you want to reload to apply Material Theme Icons to enjoy the full experience?', - options: {ok: 'Yeah, releoad', cancel: 'No, thank you'} + options: {ok: 'Yeah, reload', autoreload: 'Yes and enable auto-reload', cancel: 'No, thank you', nomore: 'Never show again'} }, CHANGELOG: { message: 'Material Theme was updated. Check the release notes for more details.', options: {ok: 'Show me', cancel: 'Maybe later'} + }, + INSTALLATION: { + message: 'Thank you for installing Material Theme! Would you like to enable the auto-application (with window reload when needed) of the Material Theme icons?', + options: {ok: 'Sure!', cancel: 'Nope :('} } }; export const infoMessage = async () => { - if (await Window.showInformationMessage(MESSAGES.INFO.message, MESSAGES.INFO.options.ok, MESSAGES.INFO.options.cancel) === MESSAGES.INFO.options.ok) { - ThemeCommands.fixIcons(); + const result = await Window.showInformationMessage( + MESSAGES.INFO.message, + MESSAGES.INFO.options.ok, + MESSAGES.INFO.options.autoreload, + MESSAGES.INFO.options.cancel, + MESSAGES.INFO.options.nomore + ); + + switch (result) { + case MESSAGES.INFO.options.ok: + return {reload: true}; + case MESSAGES.INFO.options.autoreload: + return {reload: true, autoreload: true}; + case MESSAGES.INFO.options.nomore: + return {nomore: true}; + default: + return {}; } }; export const changelogMessage = async () => - await Window.showInformationMessage(MESSAGES.CHANGELOG.message, MESSAGES.CHANGELOG.options.ok, MESSAGES.CHANGELOG.options.cancel) === MESSAGES.CHANGELOG.options.ok; + 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( + MESSAGES.INSTALLATION.message, + MESSAGES.INSTALLATION.options.ok, + MESSAGES.INSTALLATION.options.cancel, + ) === MESSAGES.INSTALLATION.options.ok; diff --git a/extensions/helpers/settings.ts b/extensions/helpers/settings.ts index 1c2073b..c726015 100644 --- a/extensions/helpers/settings.ts +++ b/extensions/helpers/settings.ts @@ -22,7 +22,14 @@ export function getCustomSettings(): IThemeCustomProperties { * Get autoApplyIcons */ export function isAutoApplyEnable(): boolean { - return vscode.workspace.getConfiguration().get('materialTheme.autoApplyIcons', true); + return vscode.workspace.getConfiguration().get('materialTheme.autoApplyIcons'); +} + +/** + * Get showReloadNotification + */ +export function isReloadNotificationEnable(): boolean { + return vscode.workspace.getConfiguration().get('materialTheme.showReloadNotification'); } /** diff --git a/extensions/helpers/should-show-changelog.ts b/extensions/helpers/should-show-changelog.ts deleted file mode 100644 index f05b780..0000000 --- a/extensions/helpers/should-show-changelog.ts +++ /dev/null @@ -1,35 +0,0 @@ -import * as path from 'path'; - -import {IDefaults} from './../interfaces/idefaults'; - -import {getDefaultValues, getPackageJSON, writeFile} from './fs'; - -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 writeDefaults = (defaults: IDefaults) => - writeFile(path.join('./extensions/defaults.json'), JSON.stringify(defaults, null, 2)); - -export default (): boolean => { - const defaults = getDefaultValues(); - const packageJSON = getPackageJSON(); - - const defaultsNotPresent = defaults.changelog === undefined || - (defaults.changelog !== undefined && typeof defaults.changelog.lastversion !== 'string'); - - const versionCurrent = splitVersion(packageJSON.version); - const versionOld = defaultsNotPresent ? null : splitVersion(defaults.changelog.lastversion); - - const out = !versionOld || - versionCurrent.major > versionOld.major || - versionCurrent.minor > versionOld.minor || - versionCurrent.patch > versionOld.patch; - - const newChangelog = {...defaults.changelog, lastversion: packageJSON.version}; - const newDefaults = {...defaults, changelog: newChangelog}; - writeDefaults(newDefaults); - - return out; -}; diff --git a/extensions/helpers/write-changelog.ts b/extensions/helpers/write-changelog.ts new file mode 100644 index 0000000..53fa129 --- /dev/null +++ b/extensions/helpers/write-changelog.ts @@ -0,0 +1,16 @@ +import * as path from 'path'; +import {getDefaultValues, getPackageJSON, writeFile} from './fs'; + +import {IDefaults} from './../interfaces/idefaults'; + +const writeDefaults = (defaults: IDefaults) => + writeFile(path.join('./extensions/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); +}; diff --git a/extensions/interfaces/iinstallation-type.ts b/extensions/interfaces/iinstallation-type.ts new file mode 100644 index 0000000..b3d6325 --- /dev/null +++ b/extensions/interfaces/iinstallation-type.ts @@ -0,0 +1,4 @@ +export interface IInstallationType { + isUpdate: boolean; + isFirstInstall: boolean; +} diff --git a/extensions/material.theme.config.ts b/extensions/material.theme.config.ts index e3086e9..900b75f 100644 --- a/extensions/material.theme.config.ts +++ b/extensions/material.theme.config.ts @@ -4,13 +4,18 @@ import { } from 'vscode'; import * as ThemeCommands from './commands'; -import {isAutoApplyEnable} from './helpers/settings'; +import {setCustomSetting} from './helpers/settings'; import {onChangeConfiguration} from './helpers/configuration-change'; -import {infoMessage, changelogMessage} from './helpers/messages'; -import shouldShowChangelog from './helpers/should-show-changelog'; +import {changelogMessage, installationMessage} from './helpers/messages'; +import checkInstallation from './helpers/check-installation'; +import writeChangelog from './helpers/write-changelog'; +import handleAutoapply from './helpers/handle-autoapply'; export async function activate() { const config = Workspace.getConfiguration(); + const installationType = checkInstallation(); + + writeChangelog(); // Listen on set theme: when the theme is Material Theme, just adjust icon and accent. Workspace.onDidChangeConfiguration(onChangeConfiguration); @@ -20,20 +25,22 @@ export async function activate() { config.update('materialTheme.cache.workbench', undefined, true); } - if (shouldShowChangelog()) { - const show = await changelogMessage(); - if (show) { - ThemeCommands.showChangelog(); - } + if (installationType.isFirstInstall) { + const enableAutoApply = await installationMessage(); + await setCustomSetting('autoApplyIcons', enableAutoApply); + // Set true always on new installation + await setCustomSetting('showReloadNotification', true); + } + + const shouldShowChangelog = (installationType.isFirstInstall || installationType.isUpdate) && await changelogMessage(); + if (shouldShowChangelog) { + ThemeCommands.showChangelog(); } // Registering commands Commands.registerCommand('materialTheme.setAccent', async () => { const wasSet = await ThemeCommands.accentsSetter(); - - if (wasSet) { - return isAutoApplyEnable() ? ThemeCommands.fixIcons() : infoMessage(); - } + handleAutoapply(wasSet); }); Commands.registerCommand('materialTheme.fixIcons', () => ThemeCommands.fixIcons()); Commands.registerCommand('materialTheme.toggleApplyIcons', () => ThemeCommands.toggleApplyIcons()); diff --git a/package.json b/package.json index 8e58291..9aa89e6 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,12 @@ }, "materialTheme.autoApplyIcons": { "type": "boolean", - "description": "Enable/disable auto-apply of Material Theme icons", + "description": "Enable/disable auto-apply of Material Theme icons with window reload when needed", + "default": false + }, + "materialTheme.showReloadNotification": { + "type": "boolean", + "description": "Useful when autoApplyIcons is false and you want to be asked to reload the window when needed", "default": true }, "materialTheme.fixIconsRunning": {