diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/background/infrastructures/ContentMessageClient.ts | 8 | ||||
-rw-r--r-- | src/background/presenters/NotifyPresenter.ts | 11 | ||||
-rw-r--r-- | src/background/usecases/SettingUseCase.ts | 16 | ||||
-rw-r--r-- | src/settings/components/form/PropertiesForm.tsx | 9 | ||||
-rw-r--r-- | src/settings/storage.ts | 7 | ||||
-rw-r--r-- | src/shared/Settings.ts | 9 | ||||
-rw-r--r-- | src/shared/operations.ts | 26 | ||||
-rw-r--r-- | src/shared/property-defs.ts | 6 |
8 files changed, 64 insertions, 28 deletions
diff --git a/src/background/infrastructures/ContentMessageClient.ts b/src/background/infrastructures/ContentMessageClient.ts index 2983409..4d2284c 100644 --- a/src/background/infrastructures/ContentMessageClient.ts +++ b/src/background/infrastructures/ContentMessageClient.ts @@ -22,14 +22,14 @@ export default class ContentMessageClient { return enabled as any as boolean; } - toggleAddonEnabled(tabId: number): Promise<void> { - return browser.tabs.sendMessage(tabId, { + async toggleAddonEnabled(tabId: number): Promise<void> { + await browser.tabs.sendMessage(tabId, { type: messages.ADDON_TOGGLE_ENABLED, }); } - scrollTo(tabId: number, x: number, y: number): Promise<void> { - return browser.tabs.sendMessage(tabId, { + async scrollTo(tabId: number, x: number, y: number): Promise<void> { + await browser.tabs.sendMessage(tabId, { type: messages.TAB_SCROLL_TO, x, y, diff --git a/src/background/presenters/NotifyPresenter.ts b/src/background/presenters/NotifyPresenter.ts index 9785278..defb601 100644 --- a/src/background/presenters/NotifyPresenter.ts +++ b/src/background/presenters/NotifyPresenter.ts @@ -26,11 +26,20 @@ export default class NotifyPresenter { }); } - async notifyInvalidSettings(): Promise<void> { + async notifyInvalidSettings(onclick: () => void): Promise<void> { let title = `Loaded settings is invalid`; // eslint-disable-next-line max-len let message = 'The default settings is used due to the last saved settings is invalid. Check your current settings from the add-on preference'; + const listener = (id: string) => { + if (id !== NOTIFICATION_ID_INVALID_SETTINGS) { + return; + } + onclick(); + browser.notifications.onClicked.removeListener(listener); + }; + browser.notifications.onClicked.addListener(listener); + await browser.notifications.create(NOTIFICATION_ID_INVALID_SETTINGS, { 'type': 'basic', 'iconUrl': browser.extension.getURL('resources/icon_48x48.png'), diff --git a/src/background/usecases/SettingUseCase.ts b/src/background/usecases/SettingUseCase.ts index 53c8f1d..d73521f 100644 --- a/src/background/usecases/SettingUseCase.ts +++ b/src/background/usecases/SettingUseCase.ts @@ -21,7 +21,12 @@ export default class SettingUseCase { } async reload(): Promise<Settings> { - let data = await this.persistentSettingRepository.load(); + let data; + try { + data = await this.persistentSettingRepository.load(); + } catch (e) { + this.showUnableToLoad(e); + } if (!data) { data = DefaultSettingData; } @@ -30,10 +35,17 @@ export default class SettingUseCase { try { value = data.toSettings(); } catch (e) { - this.notifyPresenter.notifyInvalidSettings(); + this.showUnableToLoad(e); value = DefaultSettingData.toSettings(); } this.settingRepository.update(value!!); return value; } + + private showUnableToLoad(e: Error) { + console.error('unable to load settings', e); + this.notifyPresenter.notifyInvalidSettings(() => { + browser.runtime.openOptionsPage(); + }); + } } diff --git a/src/settings/components/form/PropertiesForm.tsx b/src/settings/components/form/PropertiesForm.tsx index 0be5f5c..ee98b7e 100644 --- a/src/settings/components/form/PropertiesForm.tsx +++ b/src/settings/components/form/PropertiesForm.tsx @@ -25,12 +25,19 @@ class PropertiesForm extends React.Component<Props> { Object.keys(types).map((name) => { let type = types[name]; let inputType = ''; + let onChange = this.bindValue.bind(this); if (type === 'string') { inputType = 'text'; } else if (type === 'number') { inputType = 'number'; } else if (type === 'boolean') { inputType = 'checkbox'; + + // Settings are saved onBlur, but checkbox does not fire it + onChange = (e) => { + this.bindValue(e); + this.props.onBlur(); + }; } else { return null; } @@ -40,7 +47,7 @@ class PropertiesForm extends React.Component<Props> { <input type={inputType} name={name} className='column-input' value={value[name] ? value[name] : ''} - onChange={this.bindValue.bind(this)} + onChange={onChange} onBlur={this.props.onBlur} checked={value[name]} /> diff --git a/src/settings/storage.ts b/src/settings/storage.ts index c0005b7..32b6351 100644 --- a/src/settings/storage.ts +++ b/src/settings/storage.ts @@ -5,7 +5,12 @@ export const load = async(): Promise<SettingData> => { if (!settings) { return DefaultSettingData; } - return SettingData.valueOf(settings as any); + try { + return SettingData.valueOf(settings as any); + } catch (e) { + console.error('unable to load settings', e); + return DefaultSettingData; + } }; export const save = (data: SettingData) => { diff --git a/src/shared/Settings.ts b/src/shared/Settings.ts index 2a392df..d338e2a 100644 --- a/src/shared/Settings.ts +++ b/src/shared/Settings.ts @@ -21,13 +21,6 @@ export default interface Settings { blacklist: string[]; } -const DefaultProperties: Properties = PropertyDefs.defs.reduce( - (o: {[name: string]: PropertyDefs.Type}, def) => { - o[def.name] = def.defaultValue; - return o; - }, {}) as Properties; - - export const keymapsValueOf = (o: any): Keymaps => { return Object.keys(o).reduce((keymaps: Keymaps, key: string): Keymaps => { let op = operations.valueOf(o[key]); @@ -82,7 +75,7 @@ export const propertiesValueOf = (o: any): Properties => { } } return { - ...DefaultProperties, + ...PropertyDefs.defaultValues, ...o, }; }; diff --git a/src/shared/operations.ts b/src/shared/operations.ts index 2df2e67..1ce5256 100644 --- a/src/shared/operations.ts +++ b/src/shared/operations.ts @@ -368,7 +368,9 @@ export type Operation = const assertOptionalBoolean = (obj: any, name: string) => { if (Object.prototype.hasOwnProperty.call(obj, name) && typeof obj[name] !== 'boolean') { - throw new TypeError(`Not a boolean parameter: '${name}'`); + throw new TypeError( + `Not a boolean parameter: '${name} (${typeof obj[name]})'`, + ); } }; @@ -376,7 +378,9 @@ const assertOptionalString = (obj: any, name: string, values?: string[]) => { if (Object.prototype.hasOwnProperty.call(obj, name)) { let value = obj[name]; if (typeof value !== 'string') { - throw new TypeError(`Not a string parameter: '${name}'`); + throw new TypeError( + `Not a string parameter: '${name}' (${typeof value})`, + ); } if (values && values.length && values.indexOf(value) === -1) { // eslint-disable-next-line max-len @@ -421,32 +425,32 @@ export const valueOf = (o: any): Operation => { assertOptionalBoolean(o, 'background'); return { type: FOLLOW_START, - newTab: Boolean(typeof o.newTab === undefined ? false : o.newTab), - background: Boolean(typeof o.background === undefined ? true : o.background), // eslint-disable-line max-len + newTab: Boolean(typeof o.newTab === 'undefined' ? false : o.newTab), + background: Boolean(typeof o.background === 'undefined' ? true : o.background), // eslint-disable-line max-len }; case PAGE_HOME: assertOptionalBoolean(o, 'newTab'); return { type: PAGE_HOME, - newTab: Boolean(typeof o.newTab === undefined ? false : o.newTab), + newTab: Boolean(typeof o.newTab === 'undefined' ? false : o.newTab), }; case TAB_CLOSE: assertOptionalString(o, 'select', ['left', 'right']); return { type: TAB_CLOSE, - select: (typeof o.select === undefined ? 'right' : o.select), + select: (typeof o.select === 'undefined' ? 'right' : o.select), }; case TAB_RELOAD: assertOptionalBoolean(o, 'cache'); return { type: TAB_RELOAD, - cache: Boolean(typeof o.cache === undefined ? false : o.cache), + cache: Boolean(typeof o.cache === 'undefined' ? false : o.cache), }; case URLS_PASTE: assertOptionalBoolean(o, 'newTab'); return { type: URLS_PASTE, - newTab: Boolean(typeof o.newTab === undefined ? false : o.newTab), + newTab: Boolean(typeof o.newTab === 'undefined' ? false : o.newTab), }; case INTERNAL_OPEN_URL: assertOptionalBoolean(o, 'newTab'); @@ -456,9 +460,9 @@ export const valueOf = (o: any): Operation => { return { type: INTERNAL_OPEN_URL, url: o.url, - newTab: Boolean(typeof o.newTab === undefined ? false : o.newTab), - newWindow: Boolean(typeof o.newWindow === undefined ? false : o.newWindow), // eslint-disable-line max-len - background: Boolean(typeof o.background === undefined ? true : o.background), // eslint-disable-line max-len + newTab: Boolean(typeof o.newTab === 'undefined' ? false : o.newTab), + newWindow: Boolean(typeof o.newWindow === 'undefined' ? false : o.newWindow), // eslint-disable-line max-len + background: Boolean(typeof o.background === 'undefined' ? true : o.background), // eslint-disable-line max-len }; case CANCEL: case ADDON_ENABLE: diff --git a/src/shared/property-defs.ts b/src/shared/property-defs.ts index 6315030..fec9f80 100644 --- a/src/shared/property-defs.ts +++ b/src/shared/property-defs.ts @@ -48,3 +48,9 @@ export const defs: Def[] = [ 'which are completed at the open page', 'sbh'), ]; + +export const defaultValues = { + hintchars: 'abcdefghijklmnopqrstuvwxyz', + smoothscroll: false, + complete: 'sbh', +}; |