aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/background/infrastructures/ContentMessageClient.ts8
-rw-r--r--src/background/presenters/NotifyPresenter.ts11
-rw-r--r--src/background/usecases/SettingUseCase.ts16
-rw-r--r--src/settings/components/form/PropertiesForm.tsx9
-rw-r--r--src/settings/storage.ts7
-rw-r--r--src/shared/Settings.ts9
-rw-r--r--src/shared/operations.ts26
-rw-r--r--src/shared/property-defs.ts6
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',
+};