blob: bfe668b08db68a6f2590a1755a7983e965318dd5 [file] [log] [blame]
Adrià Vilanova Martínez53f7a7f2022-05-30 13:59:59 +02001import {convertLanguages, isoLangs} from './consts.js';
2
3export const TAB_OPTIONS = [
4 // Open in new tab for each translation
5 {
6 value: '',
7 labelMsg: 'options_tabsoption_1',
8 deprecatedValues: [],
9 },
10 // Open in a unique tab
11 {
12 value: 'yep',
13 labelMsg: 'options_tabsoption_2',
14 deprecatedValues: [],
15 },
16 // Open in a popup
17 {
18 value: 'popup',
19 labelMsg: 'options_tabsoption_3',
20 deprecatedValues: ['panel'],
21 },
22];
23
24// Class which can be used to retrieve the user options in order to act
25// accordingly.
26export default class Options {
27 constructor(options, isFirstRun) {
28 this._options = options;
29 this.isFirstRun = isFirstRun;
30 }
31
32 get uniqueTab() {
33 return this._options.uniquetab;
34 }
35
36 get targetLangs() {
37 return this._options.translateinto;
38 }
39
40 // Returns a promise that resolves in an instance of the Object class with the
41 // current options.
42 static getOptions(readOnly = true) {
43 return Options.getOptionsRaw(readOnly).then(res => {
44 return new Options(res.options, res.isFirstRun);
45 });
46 }
47
48 // Returns a promise that resolves to an object containing:
49 // - |options|: normalized options object which can be used to initialize the
50 // Options class, and which contains the current options set up by the user.
51 // - |isFirstRun|: whether the extension is running for the first time and
52 // needs to be set up.
53 //
54 // If the options needed to be normalized/created, they are also saved in the
55 // sync storage area.
56 static getOptionsRaw(readOnly) {
57 return new Promise((res, rej) => {
58 chrome.storage.sync.get(null, items => {
59 if (chrome.runtime.lastError) {
60 return rej(chrome.runtime.lastError);
61 }
62
63 let didTranslateintoChange = false;
64 let didUniquetabChange = false;
65 let returnObject = {};
66
67 // If the extension sync storage area is blank, set this as being the
68 // first run.
69 returnObject.isFirstRun = Object.keys(items).length === 0;
70
71 // Create |translateinto| property if it doesn't exist.
72 if (items.translateinto === undefined) {
73 didTranslateintoChange = true;
74
75 // Upgrade from a version previous to v0.7 if applicable, otherwise
76 // create the property with the default values.
77 if (items.languages !== undefined) {
78 items.translateinto =
79 Object.assign({}, Object.values(items.languages));
80 } else {
81 let uiLocale = chrome.i18n.getMessage('@@ui_locale');
82 let defaultLang1 = uiLocale.replace('_', '-');
83 let defaultLang2 = uiLocale.split('_')[0];
84
85 items.translateinto = {};
86 if (isoLangs[default_language_1] != undefined)
87 items.translateinto['0'] = defaultLang1;
88 else if (isoLangs[default_language_2] != undefined)
89 items.translateinto['0'] = defaultLang2;
90 }
91 }
92
93 // Normalize |translateinto| property: remove non-existent languages or
94 // change them with the correct language code.
95 for (let [index, language] of Object.entries(items.translateinto)) {
96 if (isoLangs[language] === undefined) {
97 didTranslateintoChange = true;
98 if (convertLanguages[language] === undefined) {
99 // The language doesn't exist
100 console.log(
101 'Deleting ' + language +
102 ' from items.translateinto because it doesn\'t exist.');
103 delete items.translateinto[index];
104 } else {
105 // The language doesn't exist but a known replacement is known
106 let newLanguage = convertLanguages[language];
107 console.log('Replacing ' + language + ' with ' + newLanguage);
108
109 // If the converted language is already on the list, just remove
110 // the wrong language, otherwise convert the language
111 if (Object.values(items.translateinto).includes(newLanguage))
112 delete items.translateinto[index];
113 else
114 items.translateinto[index] = newLanguage;
115 }
116 }
117 }
118
119 // Normalize |uniquetab| property:
120 // - If it is set to a valid value, leave it alone.
121 // - If it is set to a deprecated value, change it to the corresponding
122 // value we use now.
123 // - If it is set to an incorrect value or it isn't set, change it to
124 // the default value.
125 let foundValue = false;
126 for (let opt of TAB_OPTIONS) {
127 if (opt.value == items?.uniquetab) {
128 foundValue = true;
129 break;
130 }
131 if (opt.deprecatedValues.includes(items?.uniquetab)) {
132 foundValue = true;
133 items.uniquetab = opt.value;
134 break;
135 }
136 }
137 if (!foundValue) {
138 items.uniquetab = 'popup';
139 didUniquetabChange = true;
140 }
141
142 // Clean up deprecated properties
143 if (items.languages !== undefined) {
144 delete items.languages;
145 chrome.storage.sync.remove('languages');
146 }
147
148 // Save properties that have changed if we're not in read-only mode
149 if (!readOnly) {
150 if (didTranslateintoChange || didUniquetabChange) {
151 chrome.storage.sync.set({
152 translateinto: items.translateinto,
153 uniquetab: items.uniquetab,
154 });
155 }
156 }
157
158 returnObject.options = items;
159 res(returnObject);
160 });
161 });
162 }
163}