aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/api/apiBase.ts27
-rw-r--r--src/components/auth/Invite.tsx8
-rw-r--r--src/components/services/content/ServiceView.tsx44
-rw-r--r--src/components/settings/navigation/SettingsNavigation.tsx6
-rw-r--r--src/components/settings/services/ServiceItem.tsx2
-rw-r--r--src/components/ui/Loader.tsx2
-rw-r--r--src/components/ui/Slider.tsx2
-rw-r--r--src/components/ui/button/index.tsx32
-rw-r--r--src/components/ui/imageUpload/index.tsx2
-rw-r--r--src/components/ui/select/index.tsx16
-rw-r--r--src/containers/settings/EditServiceScreen.tsx6
-rw-r--r--src/containers/settings/RecipesScreen.tsx8
-rw-r--r--src/containers/settings/ServicesScreen.tsx2
-rw-r--r--src/electron/Settings.ts6
-rw-r--r--src/electron/ipc-api/autoUpdate.ts8
-rw-r--r--src/electron/ipc-api/download.ts12
-rw-r--r--src/environment-remote.ts6
-rw-r--r--src/features/appearance/index.ts37
-rw-r--r--src/features/quickSwitch/Component.tsx15
-rw-r--r--src/features/todos/preload.ts3
-rw-r--r--src/features/todos/store.ts9
-rw-r--r--src/features/webControls/components/WebControls.tsx2
-rw-r--r--src/helpers/update-helpers.ts2
-rw-r--r--src/helpers/userAgent-helpers.ts2
-rw-r--r--src/index.ts6
-rw-r--r--src/internal-server/app/ImageHelper.js2
-rw-r--r--src/internal-server/app/Middleware/ConvertEmptyStringsToNull.js2
-rw-r--r--src/internal-server/start/migrate.js6
-rw-r--r--src/internal-server/test.ts1
-rw-r--r--src/lib/Menu.ts64
-rw-r--r--src/stores/AppStore.ts6
-rw-r--r--src/stores/ServicesStore.ts41
-rw-r--r--src/stores/SettingsStore.ts8
-rw-r--r--src/stores/UIStore.ts14
-rw-r--r--src/webview/darkmode.ts4
-rw-r--r--src/webview/lib/RecipeWebview.ts4
-rw-r--r--src/webview/recipe.ts6
37 files changed, 228 insertions, 195 deletions
diff --git a/src/api/apiBase.ts b/src/api/apiBase.ts
index fad20ca5e..bc2cb3dd1 100644
--- a/src/api/apiBase.ts
+++ b/src/api/apiBase.ts
@@ -58,17 +58,21 @@ export function serverBase() {
58 58
59 let terms; 59 let terms;
60 switch (serverType) { 60 switch (serverType) {
61 case LIVE_FRANZ_API: 61 case LIVE_FRANZ_API: {
62 terms = DEV_API_FRANZ_WEBSITE; 62 terms = DEV_API_FRANZ_WEBSITE;
63 break; 63 break;
64 case noServerFerdi: 64 }
65 case noServerFerdi: {
65 terms = LIVE_FERDIUM_API; 66 terms = LIVE_FERDIUM_API;
66 break; 67 break;
67 case noServerFerdium: 68 }
69 case noServerFerdium: {
68 terms = LIVE_FERDIUM_API; 70 terms = LIVE_FERDIUM_API;
69 break; 71 break;
70 default: 72 }
73 default: {
71 terms = serverType; 74 terms = serverType;
75 }
72 } 76 }
73 77
74 return fixUrl(terms); 78 return fixUrl(terms);
@@ -81,20 +85,25 @@ export function serverName(): string {
81 85
82 let nameServer; 86 let nameServer;
83 switch (serverType) { 87 switch (serverType) {
84 case LIVE_FRANZ_API: 88 case LIVE_FRANZ_API: {
85 nameServer = 'Franz'; 89 nameServer = 'Franz';
86 break; 90 break;
87 case LIVE_FERDIUM_API: 91 }
92 case LIVE_FERDIUM_API: {
88 nameServer = 'Ferdium'; 93 nameServer = 'Ferdium';
89 break; 94 break;
90 case noServerFerdi: 95 }
96 case noServerFerdi: {
91 nameServer = 'No'; 97 nameServer = 'No';
92 break; 98 break;
93 case noServerFerdium: 99 }
100 case noServerFerdium: {
94 nameServer = 'No'; 101 nameServer = 'No';
95 break; 102 break;
96 default: 103 }
104 default: {
97 nameServer = 'Custom'; 105 nameServer = 'Custom';
106 }
98 } 107 }
99 108
100 return nameServer; 109 return nameServer;
diff --git a/src/components/auth/Invite.tsx b/src/components/auth/Invite.tsx
index 4ab5157a8..cebef9365 100644
--- a/src/components/auth/Invite.tsx
+++ b/src/components/auth/Invite.tsx
@@ -192,7 +192,7 @@ class Invite extends Component<IProps, IState> {
192 return ( 192 return (
193 <div 193 <div
194 className={ 194 className={
195 !embed ? 'auth__container auth__container--signup' : 'settings__main' 195 embed ? 'settings__main' : 'auth__container auth__container--signup'
196 } 196 }
197 > 197 >
198 {embed && ( 198 {embed && (
@@ -200,10 +200,10 @@ class Invite extends Component<IProps, IState> {
200 <H1>{intl.formatMessage(messages.settingsHeadline)}</H1> 200 <H1>{intl.formatMessage(messages.settingsHeadline)}</H1>
201 </div> 201 </div>
202 )} 202 )}
203 {!embed ? ( 203 {embed ? (
204 <div>{renderForm}</div>
205 ) : (
206 <div className="settings__body invite__form">{renderForm}</div> 204 <div className="settings__body invite__form">{renderForm}</div>
205 ) : (
206 <div>{renderForm}</div>
207 )} 207 )}
208 </div> 208 </div>
209 ); 209 );
diff --git a/src/components/services/content/ServiceView.tsx b/src/components/services/content/ServiceView.tsx
index e41184431..0754bccc5 100644
--- a/src/components/services/content/ServiceView.tsx
+++ b/src/components/services/content/ServiceView.tsx
@@ -135,29 +135,9 @@ class ServiceView extends Component<IProps, IState> {
135 )} 135 )}
136 </> 136 </>
137 )} 137 )}
138 {!service.isEnabled ? ( 138 {service.isEnabled ? (
139 <> 139 <>
140 {service.isActive && ( 140 {service.isHibernating ? (
141 <ServiceDisabled
142 name={service.name !== '' ? service.name : service.recipe.name}
143 // webview={service.webview} // TODO - [TECH DEBT][PROPS NOT EXIST IN COMPONENT] check it
144 enable={enable}
145 />
146 )}
147 </>
148 ) : (
149 <>
150 {!service.isHibernating ? (
151 <>
152 {showNavBar && <WebControlsScreen service={service} />}
153 <ServiceWebview
154 service={service}
155 setWebviewReference={setWebviewRef}
156 detachService={detachService}
157 isSpellcheckerEnabled={isSpellcheckerEnabled}
158 />
159 </>
160 ) : (
161 <div 141 <div
162 style={{ 142 style={{
163 display: 'flex', 143 display: 'flex',
@@ -180,6 +160,26 @@ class ServiceView extends Component<IProps, IState> {
180 <br /> 160 <br />
181 Try switching services or reloading Ferdium. 161 Try switching services or reloading Ferdium.
182 </div> 162 </div>
163 ) : (
164 <>
165 {showNavBar && <WebControlsScreen service={service} />}
166 <ServiceWebview
167 service={service}
168 setWebviewReference={setWebviewRef}
169 detachService={detachService}
170 isSpellcheckerEnabled={isSpellcheckerEnabled}
171 />
172 </>
173 )}
174 </>
175 ) : (
176 <>
177 {service.isActive && (
178 <ServiceDisabled
179 name={service.name === '' ? service.recipe.name : service.name}
180 // webview={service.webview} // TODO - [TECH DEBT][PROPS NOT EXIST IN COMPONENT] check it
181 enable={enable}
182 />
183 )} 183 )}
184 </> 184 </>
185 )} 185 )}
diff --git a/src/components/settings/navigation/SettingsNavigation.tsx b/src/components/settings/navigation/SettingsNavigation.tsx
index 95c69027c..4e2c7f410 100644
--- a/src/components/settings/navigation/SettingsNavigation.tsx
+++ b/src/components/settings/navigation/SettingsNavigation.tsx
@@ -191,9 +191,9 @@ class SettingsNavigation extends Component<IProps> {
191 className="settings-navigation__link" 191 className="settings-navigation__link"
192 onClick={this.handleLogout.bind(this)} 192 onClick={this.handleLogout.bind(this)}
193 > 193 >
194 {!isUsingWithoutAccount 194 {isUsingWithoutAccount
195 ? intl.formatMessage(messages.logout) 195 ? 'Exit session'
196 : 'Exit session'} 196 : intl.formatMessage(messages.logout)}
197 </button> 197 </button>
198 </div> 198 </div>
199 ); 199 );
diff --git a/src/components/settings/services/ServiceItem.tsx b/src/components/settings/services/ServiceItem.tsx
index fd961a0a8..0737a680c 100644
--- a/src/components/settings/services/ServiceItem.tsx
+++ b/src/components/settings/services/ServiceItem.tsx
@@ -63,7 +63,7 @@ class ServiceItem extends Component<IProps> {
63 onClick={goToServiceForm} 63 onClick={goToServiceForm}
64 role="gridcell" 64 role="gridcell"
65 > 65 >
66 {service.name !== '' ? service.name : service.recipe.name} 66 {service.name === '' ? service.recipe.name : service.name}
67 </td> 67 </td>
68 <td 68 <td
69 className="service-table__column-info" 69 className="service-table__column-info"
diff --git a/src/components/ui/Loader.tsx b/src/components/ui/Loader.tsx
index ebb437d9d..17cb35f41 100644
--- a/src/components/ui/Loader.tsx
+++ b/src/components/ui/Loader.tsx
@@ -25,7 +25,7 @@ class LoaderComponent extends Component<IProps> {
25 } = this.props; 25 } = this.props;
26 26
27 const loaderColor = 27 const loaderColor =
28 color !== 'ACCENT' ? color : this.props.stores!.settings.app.accentColor; 28 color === 'ACCENT' ? this.props.stores!.settings.app.accentColor : color;
29 29
30 return ( 30 return (
31 <Loader 31 <Loader
diff --git a/src/components/ui/Slider.tsx b/src/components/ui/Slider.tsx
index ed9fe9073..be0846513 100644
--- a/src/components/ui/Slider.tsx
+++ b/src/components/ui/Slider.tsx
@@ -51,7 +51,7 @@ class Slider extends Component<IProps> {
51 value={field.value} 51 value={field.value}
52 min="1" 52 min="1"
53 max="100" 53 max="100"
54 onChange={e => (!disabled ? this.onChange(e) : null)} 54 onChange={e => (disabled ? null : this.onChange(e))}
55 /> 55 />
56 </div> 56 </div>
57 57
diff --git a/src/components/ui/button/index.tsx b/src/components/ui/button/index.tsx
index dc984bf95..9444efde2 100644
--- a/src/components/ui/button/index.tsx
+++ b/src/components/ui/button/index.tsx
@@ -117,12 +117,12 @@ const styles = (theme: Theme) => ({
117 zIndex: 9999, 117 zIndex: 9999,
118 }, 118 },
119 loaderContainer: { 119 loaderContainer: {
120 width: (props: IProps): string => (!props.busy ? '0' : '40px'), 120 width: (props: IProps): string => (props.busy ? '40px' : '0'),
121 height: 20, 121 height: 20,
122 overflow: 'hidden', 122 overflow: 'hidden',
123 transition: loaderContainerTransition, 123 transition: loaderContainerTransition,
124 marginLeft: (props: IProps): number => (!props.busy ? 10 : 20), 124 marginLeft: (props: IProps): number => (props.busy ? 20 : 10),
125 marginRight: (props: IProps): number => (!props.busy ? -10 : -20), 125 marginRight: (props: IProps): number => (props.busy ? -20 : -10),
126 position: (): Property.Position => 'inherit', 126 position: (): Property.Position => 'inherit',
127 }, 127 },
128 icon: { 128 icon: {
@@ -217,38 +217,38 @@ class ButtonComponent extends Component<IProps, IState> {
217 </> 217 </>
218 ); 218 );
219 219
220 const wrapperComponent = !href ? ( 220 const wrapperComponent = href ? (
221 <button 221 <a
222 id={id} 222 href={href}
223 type={type} 223 target={target}
224 onClick={onClick} 224 onClick={onClick}
225 className={classnames({ 225 className={classnames({
226 [`${classes.button}`]: true, 226 [`${classes.button}`]: true,
227 [`${classes[buttonType as ButtonType]}`]: true, 227 [`${classes[buttonType as ButtonType]}`]: true,
228 [`${classes.disabled}`]: disabled,
229 [`${className}`]: className, 228 [`${className}`]: className,
230 })} 229 })}
231 disabled={disabled} 230 rel={target === '_blank' ? 'noopener' : ''}
232 data-type="franz-button" 231 data-type="franz-button"
233 {...(htmlForm && { form: htmlForm })}
234 > 232 >
235 {content} 233 {content}
236 </button> 234 </a>
237 ) : ( 235 ) : (
238 <a 236 <button
239 href={href} 237 id={id}
240 target={target} 238 type={type}
241 onClick={onClick} 239 onClick={onClick}
242 className={classnames({ 240 className={classnames({
243 [`${classes.button}`]: true, 241 [`${classes.button}`]: true,
244 [`${classes[buttonType as ButtonType]}`]: true, 242 [`${classes[buttonType as ButtonType]}`]: true,
243 [`${classes.disabled}`]: disabled,
245 [`${className}`]: className, 244 [`${className}`]: className,
246 })} 245 })}
247 rel={target === '_blank' ? 'noopener' : ''} 246 disabled={disabled}
248 data-type="franz-button" 247 data-type="franz-button"
248 {...(htmlForm && { form: htmlForm })}
249 > 249 >
250 {content} 250 {content}
251 </a> 251 </button>
252 ); 252 );
253 253
254 return wrapperComponent; 254 return wrapperComponent;
diff --git a/src/components/ui/imageUpload/index.tsx b/src/components/ui/imageUpload/index.tsx
index 89e2c65a2..3b164ed41 100644
--- a/src/components/ui/imageUpload/index.tsx
+++ b/src/components/ui/imageUpload/index.tsx
@@ -46,7 +46,7 @@ class ImageUpload extends Component<IProps, IState> {
46 this.setState({ errorState: false }); 46 this.setState({ errorState: false });
47 47
48 for (const file of acceptedFiles) { 48 for (const file of acceptedFiles) {
49 const imgPath = isWindows ? file.path.replace(/\\/g, '/') : file.path; 49 const imgPath = isWindows ? file.path.replaceAll('\\', '/') : file.path;
50 this.setState({ 50 this.setState({
51 path: imgPath, 51 path: imgPath,
52 }); 52 });
diff --git a/src/components/ui/select/index.tsx b/src/components/ui/select/index.tsx
index 31aa8a15f..695e70e28 100644
--- a/src/components/ui/select/index.tsx
+++ b/src/components/ui/select/index.tsx
@@ -321,10 +321,12 @@ class SelectComponent extends Component<IProps, IState> {
321 case 39: 321 case 39:
322 case 38: 322 case 38:
323 case 40: // Arrow keys 323 case 40: // Arrow keys
324 case 32: 324 case 32: {
325 break; // Space 325 break;
326 default: 326 } // Space
327 break; // do not block other keys 327 default: {
328 break;
329 } // do not block other keys
328 } 330 }
329 } 331 }
330 332
@@ -381,12 +383,12 @@ class SelectComponent extends Component<IProps, IState> {
381 [`${classes.hasError}`]: error, 383 [`${classes.hasError}`]: error,
382 })} 384 })}
383 onClick={ 385 onClick={
384 !disabled 386 disabled
385 ? () => 387 ? noop
388 : () =>
386 this.setState((state: IState) => ({ 389 this.setState((state: IState) => ({
387 open: !state.open, 390 open: !state.open,
388 })) 391 }))
389 : noop
390 } 392 }
391 > 393 >
392 {selection} 394 {selection}
diff --git a/src/containers/settings/EditServiceScreen.tsx b/src/containers/settings/EditServiceScreen.tsx
index d4186560f..0a079c608 100644
--- a/src/containers/settings/EditServiceScreen.tsx
+++ b/src/containers/settings/EditServiceScreen.tsx
@@ -175,9 +175,9 @@ class EditServiceScreen extends Component<IProps> {
175 { default: defaultSpellcheckerLanguage }, 175 { default: defaultSpellcheckerLanguage },
176 ), 176 ),
177 automaticDetectionText: 177 automaticDetectionText:
178 stores.settings.app.spellcheckerLanguage !== 'automatic' 178 stores.settings.app.spellcheckerLanguage === 'automatic'
179 ? intl.formatMessage(globalMessages.spellcheckerAutomaticDetection) 179 ? ''
180 : '', 180 : intl.formatMessage(globalMessages.spellcheckerAutomaticDetection),
181 }); 181 });
182 182
183 const config: FormFields = { 183 const config: FormFields = {
diff --git a/src/containers/settings/RecipesScreen.tsx b/src/containers/settings/RecipesScreen.tsx
index abbb79b39..1fb2673a8 100644
--- a/src/containers/settings/RecipesScreen.tsx
+++ b/src/containers/settings/RecipesScreen.tsx
@@ -129,8 +129,9 @@ class RecipesScreen extends Component<IProps, IState> {
129 129
130 const { needle } = this.state; 130 const { needle } = this.state;
131 const allRecipes = 131 const allRecipes =
132 needle !== null 132 needle === null
133 ? this.prepareRecipes([ 133 ? recipeFilter
134 : this.prepareRecipes([
134 // All search recipes from server 135 // All search recipes from server
135 ...recipePreviews.searchResults, 136 ...recipePreviews.searchResults,
136 // All search recipes from local recipes 137 // All search recipes from local recipes
@@ -143,8 +144,7 @@ class RecipesScreen extends Component<IProps, IState> {
143 ), 144 ),
144 ), 145 ),
145 ), 146 ),
146 ]).sort(this._sortByName) 147 ]).sort(this._sortByName);
147 : recipeFilter;
148 148
149 const customWebsiteRecipe = recipePreviews.all.find( 149 const customWebsiteRecipe = recipePreviews.all.find(
150 service => service.id === CUSTOM_WEBSITE_RECIPE_ID, 150 service => service.id === CUSTOM_WEBSITE_RECIPE_ID,
diff --git a/src/containers/settings/ServicesScreen.tsx b/src/containers/settings/ServicesScreen.tsx
index 780b7331e..70eeffed4 100644
--- a/src/containers/settings/ServicesScreen.tsx
+++ b/src/containers/settings/ServicesScreen.tsx
@@ -33,7 +33,7 @@ class ServicesScreen extends Component<IProps> {
33 } = this.props.actions.service; 33 } = this.props.actions.service;
34 const isLoading = services.allServicesRequest.isExecuting; 34 const isLoading = services.allServicesRequest.isExecuting;
35 const allServices = 35 const allServices =
36 services.filterNeedle !== null ? services.filtered : services.all; 36 services.filterNeedle === null ? services.all : services.filtered;
37 37
38 return ( 38 return (
39 <ErrorBoundary> 39 <ErrorBoundary>
diff --git a/src/electron/Settings.ts b/src/electron/Settings.ts
index 3e9c6ed99..7bb12338e 100644
--- a/src/electron/Settings.ts
+++ b/src/electron/Settings.ts
@@ -18,10 +18,10 @@ export default class Settings {
18 this.store = defaultState; 18 this.store = defaultState;
19 this.defaultState = defaultState; 19 this.defaultState = defaultState;
20 20
21 if (!pathExistsSync(this.settingsFile)) { 21 if (pathExistsSync(this.settingsFile)) {
22 this._writeFile();
23 } else {
24 this._hydrate(); 22 this._hydrate();
23 } else {
24 this._writeFile();
25 } 25 }
26 } 26 }
27 27
diff --git a/src/electron/ipc-api/autoUpdate.ts b/src/electron/ipc-api/autoUpdate.ts
index bf3e79c85..14214aacb 100644
--- a/src/electron/ipc-api/autoUpdate.ts
+++ b/src/electron/ipc-api/autoUpdate.ts
@@ -7,10 +7,7 @@ const debug = require('../../preload-safe-debug')('Ferdium:ipcApi:autoUpdate');
7export default (params: { mainWindow: BrowserWindow; settings: any }) => { 7export default (params: { mainWindow: BrowserWindow; settings: any }) => {
8 const enableUpdate = Boolean(params.settings.app.get('automaticUpdates')); 8 const enableUpdate = Boolean(params.settings.app.get('automaticUpdates'));
9 9
10 if (!enableUpdate) { 10 if (enableUpdate) {
11 autoUpdater.autoInstallOnAppQuit = false;
12 autoUpdater.autoDownload = false;
13 } else {
14 ipcMain.on('autoUpdate', (event, args) => { 11 ipcMain.on('autoUpdate', (event, args) => {
15 if (enableUpdate) { 12 if (enableUpdate) {
16 try { 13 try {
@@ -71,5 +68,8 @@ export default (params: { mainWindow: BrowserWindow; settings: any }) => {
71 debug('update-error'); 68 debug('update-error');
72 params.mainWindow.webContents.send('autoUpdate', { error }); 69 params.mainWindow.webContents.send('autoUpdate', { error });
73 }); 70 });
71 } else {
72 autoUpdater.autoInstallOnAppQuit = false;
73 autoUpdater.autoDownload = false;
74 } 74 }
75}; 75};
diff --git a/src/electron/ipc-api/download.ts b/src/electron/ipc-api/download.ts
index 21af0d045..518a7091c 100644
--- a/src/electron/ipc-api/download.ts
+++ b/src/electron/ipc-api/download.ts
@@ -23,12 +23,7 @@ export default (params: { mainWindow: BrowserWindow }) => {
23 const win = BrowserWindow.getFocusedWindow(); 23 const win = BrowserWindow.getFocusedWindow();
24 24
25 try { 25 try {
26 if (!content) { 26 if (content) {
27 const dl = await download(win!, url, {
28 saveAs: true,
29 });
30 debug('File saved to', dl.savePath);
31 } else {
32 const extension = mime.extension(fileOptions.mime); 27 const extension = mime.extension(fileOptions.mime);
33 const filename = `${fileOptions.name}.${extension}`; 28 const filename = `${fileOptions.name}.${extension}`;
34 29
@@ -50,6 +45,11 @@ export default (params: { mainWindow: BrowserWindow }) => {
50 } catch (error) { 45 } catch (error) {
51 console.error(error); 46 console.error(error);
52 } 47 }
48 } else {
49 const dl = await download(win!, url, {
50 saveAs: true,
51 });
52 debug('File saved to', dl.savePath);
53 } 53 }
54 } catch (error) { 54 } catch (error) {
55 console.error(error); 55 console.error(error);
diff --git a/src/environment-remote.ts b/src/environment-remote.ts
index bb14448a3..5f2b68dab 100644
--- a/src/environment-remote.ts
+++ b/src/environment-remote.ts
@@ -35,9 +35,9 @@ if (process.env.FERDIUM_APPDATA_DIR != null) {
35} 35}
36 36
37export const isDevMode: boolean = 37export const isDevMode: boolean =
38 process.env.ELECTRON_IS_DEV !== undefined 38 process.env.ELECTRON_IS_DEV === undefined
39 ? Number.parseInt(process.env.ELECTRON_IS_DEV, 10) === 1 39 ? !app.isPackaged
40 : !app.isPackaged; 40 : Number.parseInt(process.env.ELECTRON_IS_DEV, 10) === 1;
41if (isDevMode) { 41if (isDevMode) {
42 app.setPath('userData', join(app.getPath('appData'), `${app.name}Dev`)); 42 app.setPath('userData', join(app.getPath('appData'), `${app.name}Dev`));
43} 43}
diff --git a/src/features/appearance/index.ts b/src/features/appearance/index.ts
index 9c9f3e175..b6e944724 100644
--- a/src/features/appearance/index.ts
+++ b/src/features/appearance/index.ts
@@ -19,7 +19,7 @@ function createStyleElement() {
19 const styles = document.createElement('style'); 19 const styles = document.createElement('style');
20 styles.id = STYLE_ELEMENT_ID; 20 styles.id = STYLE_ELEMENT_ID;
21 21
22 document.querySelector('head')?.appendChild(styles); 22 document.querySelector('head')?.append(styles);
23} 23}
24 24
25function setAppearance(style) { 25function setAppearance(style) {
@@ -153,40 +153,47 @@ function generateServiceRibbonWidthStyle(
153 const verticalStyleOffset = 29; 153 const verticalStyleOffset = 29;
154 154
155 switch (width) { 155 switch (width) {
156 case 35: 156 case 35: {
157 fontSize = 9; 157 fontSize = 9;
158 tabItemHeightBias = 25; 158 tabItemHeightBias = 25;
159 sidebarSizeBias = 48; 159 sidebarSizeBias = 48;
160 break; 160 break;
161 case 45: 161 }
162 case 45: {
162 fontSize = 10; 163 fontSize = 10;
163 tabItemHeightBias = 21; 164 tabItemHeightBias = 21;
164 sidebarSizeBias = 44; 165 sidebarSizeBias = 44;
165 break; 166 break;
166 case 55: 167 }
168 case 55: {
167 fontSize = 11; 169 fontSize = 11;
168 tabItemHeightBias = 13; 170 tabItemHeightBias = 13;
169 sidebarSizeBias = 37; 171 sidebarSizeBias = 37;
170 break; 172 break;
171 case 80: 173 }
174 case 80: {
172 fontSize = 11; 175 fontSize = 11;
173 tabItemHeightBias = 3; 176 tabItemHeightBias = 3;
174 sidebarSizeBias = 27; 177 sidebarSizeBias = 27;
175 break; 178 break;
176 case 90: 179 }
180 case 90: {
177 fontSize = 12; 181 fontSize = 12;
178 tabItemHeightBias = 0; 182 tabItemHeightBias = 0;
179 sidebarSizeBias = 25; 183 sidebarSizeBias = 25;
180 break; 184 break;
181 case 100: 185 }
186 case 100: {
182 fontSize = 13; 187 fontSize = 13;
183 tabItemHeightBias = 2; 188 tabItemHeightBias = 2;
184 sidebarSizeBias = 25; 189 sidebarSizeBias = 25;
185 break; 190 break;
186 default: 191 }
192 default: {
187 fontSize = 11; 193 fontSize = 11;
188 tabItemHeightBias = 13; 194 tabItemHeightBias = 13;
189 sidebarSizeBias = 37; 195 sidebarSizeBias = 37;
196 }
190 } 197 }
191 198
192 if (!isLabelEnabled) { 199 if (!isLabelEnabled) {
@@ -203,18 +210,22 @@ function generateServiceRibbonWidthStyle(
203 210
204 let sidebarServicesAlignment; 211 let sidebarServicesAlignment;
205 switch (sidebarServicesLocation) { 212 switch (sidebarServicesLocation) {
206 case SIDEBAR_SERVICES_LOCATION_TOPLEFT: 213 case SIDEBAR_SERVICES_LOCATION_TOPLEFT: {
207 sidebarServicesAlignment = horizontal ? 'left' : 'start'; 214 sidebarServicesAlignment = horizontal ? 'left' : 'start';
208 break; 215 break;
209 case SIDEBAR_SERVICES_LOCATION_CENTER: 216 }
217 case SIDEBAR_SERVICES_LOCATION_CENTER: {
210 sidebarServicesAlignment = horizontal ? 'center' : 'center'; 218 sidebarServicesAlignment = horizontal ? 'center' : 'center';
211 break; 219 break;
212 case SIDEBAR_SERVICES_LOCATION_BOTTOMRIGHT: 220 }
221 case SIDEBAR_SERVICES_LOCATION_BOTTOMRIGHT: {
213 sidebarServicesAlignment = horizontal ? 'right' : 'end'; 222 sidebarServicesAlignment = horizontal ? 'right' : 'end';
214 break; 223 break;
215 default: 224 }
225 default: {
216 sidebarServicesAlignment = horizontal ? 'left' : 'start'; 226 sidebarServicesAlignment = horizontal ? 'left' : 'start';
217 break; 227 break;
228 }
218 } 229 }
219 230
220 const graysacleServices = `filter: grayscale(1); 231 const graysacleServices = `filter: grayscale(1);
@@ -268,7 +279,7 @@ function generateServiceRibbonWidthStyle(
268 ? width 279 ? width
269 : width + 280 : width +
270 sidebarSizeBias + 281 sidebarSizeBias +
271 (sizeDragArea !== 0 ? 4 - sizeDragArea : 4) 282 (sizeDragArea === 0 ? 4 : 4 - sizeDragArea)
272 }px !important; 283 }px !important;
273 } 284 }
274 .darwin .workspaces-drawer { 285 .darwin .workspaces-drawer {
diff --git a/src/features/quickSwitch/Component.tsx b/src/features/quickSwitch/Component.tsx
index fb85d61e1..ab07e5d4d 100644
--- a/src/features/quickSwitch/Component.tsx
+++ b/src/features/quickSwitch/Component.tsx
@@ -215,24 +215,29 @@ class QuickSwitchModal extends Component<IProps, IState> {
215 _handleKeyDown(event: KeyboardEvent): void { 215 _handleKeyDown(event: KeyboardEvent): void {
216 if (ModalState.isModalVisible) { 216 if (ModalState.isModalVisible) {
217 switch (event.keyCode) { 217 switch (event.keyCode) {
218 case this.ARROW_DOWN: 218 case this.ARROW_DOWN: {
219 this.changeSelected(1); 219 this.changeSelected(1);
220 break; 220 break;
221 case this.TAB: 221 }
222 case this.TAB: {
222 if (event.shiftKey) { 223 if (event.shiftKey) {
223 this.changeSelected(-1); 224 this.changeSelected(-1);
224 } else { 225 } else {
225 this.changeSelected(1); 226 this.changeSelected(1);
226 } 227 }
227 break; 228 break;
228 case this.ARROW_UP: 229 }
230 case this.ARROW_UP: {
229 this.changeSelected(-1); 231 this.changeSelected(-1);
230 break; 232 break;
231 case this.ENTER: 233 }
234 case this.ENTER: {
232 this.openService(this.state.selected); 235 this.openService(this.state.selected);
233 break; 236 break;
234 default: 237 }
238 default: {
235 break; 239 break;
240 }
236 } 241 }
237 } 242 }
238 } 243 }
diff --git a/src/features/todos/preload.ts b/src/features/todos/preload.ts
index 0d76efd7a..de594651b 100644
--- a/src/features/todos/preload.ts
+++ b/src/features/todos/preload.ts
@@ -9,9 +9,10 @@ debug('Preloading Todos Webview');
9 9
10let hostMessageListener = ({ action }) => { 10let hostMessageListener = ({ action }) => {
11 switch (action) { 11 switch (action) {
12 case 'todos:initialize-as-service': 12 case 'todos:initialize-as-service': {
13 ipcRenderer.sendToHost('hello'); 13 ipcRenderer.sendToHost('hello');
14 break; 14 break;
15 }
15 default: 16 default:
16 } 17 }
17}; 18};
diff --git a/src/features/todos/store.ts b/src/features/todos/store.ts
index bff099eb1..94be4db6a 100644
--- a/src/features/todos/store.ts
+++ b/src/features/todos/store.ts
@@ -197,13 +197,15 @@ export default class TodoStore extends FeatureStore {
197 }) => { 197 }) => {
198 debug('_handleClientMessage', channel, message); 198 debug('_handleClientMessage', channel, message);
199 switch (message.action) { 199 switch (message.action) {
200 case 'todos:initialized': 200 case 'todos:initialized': {
201 this._onTodosClientInitialized(); 201 this._onTodosClientInitialized();
202 break; 202 break;
203 case 'todos:goToService': 203 }
204 case 'todos:goToService': {
204 this._goToService(message.data); 205 this._goToService(message.data);
205 break; 206 break;
206 default: 207 }
208 default: {
207 debug('Other message received', channel, message); 209 debug('Other message received', channel, message);
208 if (this.stores.services.isTodosServiceAdded && this.actions) { 210 if (this.stores.services.isTodosServiceAdded && this.actions) {
209 this.actions.service.handleIPCMessage({ 211 this.actions.service.handleIPCMessage({
@@ -212,6 +214,7 @@ export default class TodoStore extends FeatureStore {
212 args: message, 214 args: message,
213 }); 215 });
214 } 216 }
217 }
215 } 218 }
216 }; 219 };
217 220
diff --git a/src/features/webControls/components/WebControls.tsx b/src/features/webControls/components/WebControls.tsx
index 51bf7e541..74b343948 100644
--- a/src/features/webControls/components/WebControls.tsx
+++ b/src/features/webControls/components/WebControls.tsx
@@ -115,7 +115,7 @@ class WebControls extends Component<IProps, IState> {
115 const { url: inputUrl } = props; 115 const { url: inputUrl } = props;
116 const { editUrl } = state; 116 const { editUrl } = state;
117 117
118 return !editUrl ? { inputUrl, editUrl } : null; 118 return editUrl ? null : { inputUrl, editUrl };
119 } 119 }
120 120
121 constructor(props: IProps) { 121 constructor(props: IProps) {
diff --git a/src/helpers/update-helpers.ts b/src/helpers/update-helpers.ts
index daeef5413..9a36850fc 100644
--- a/src/helpers/update-helpers.ts
+++ b/src/helpers/update-helpers.ts
@@ -13,7 +13,7 @@ export function getFerdiumVersion(
13} 13}
14 14
15export function updateVersionParse(updateVersion: string): string { 15export function updateVersionParse(updateVersion: string): string {
16 return updateVersion !== '' ? `?version=${updateVersion}` : ''; 16 return updateVersion === '' ? '' : `?version=${updateVersion}`;
17} 17}
18 18
19export function onAuthGoToReleaseNotes( 19export function onAuthGoToReleaseNotes(
diff --git a/src/helpers/userAgent-helpers.ts b/src/helpers/userAgent-helpers.ts
index 52568555c..c811b34c9 100644
--- a/src/helpers/userAgent-helpers.ts
+++ b/src/helpers/userAgent-helpers.ts
@@ -16,7 +16,7 @@ function macOS() {
16 if (cpuName && /\(/.test(cpuName)) { 16 if (cpuName && /\(/.test(cpuName)) {
17 cpuName = cpuName.split('(')[0]; 17 cpuName = cpuName.split('(')[0];
18 } 18 }
19 return `Macintosh; ${cpuName} Mac OS X ${version.replace(/\./g, '_')}`; 19 return `Macintosh; ${cpuName} Mac OS X ${version.replaceAll('.', '_')}`;
20} 20}
21 21
22function windows() { 22function windows() {
diff --git a/src/index.ts b/src/index.ts
index bb6d64d1e..182a281fa 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -108,9 +108,7 @@ const liftSingleInstanceLock = retrieveSettingValue(
108const gotTheLock = liftSingleInstanceLock 108const gotTheLock = liftSingleInstanceLock
109 ? true 109 ? true
110 : app.requestSingleInstanceLock(); 110 : app.requestSingleInstanceLock();
111if (!gotTheLock) { 111if (gotTheLock) {
112 app.quit();
113} else {
114 app.on('second-instance', (_event, argv) => { 112 app.on('second-instance', (_event, argv) => {
115 // Someone tried to run a second instance, we should focus our window. 113 // Someone tried to run a second instance, we should focus our window.
116 if (mainWindow) { 114 if (mainWindow) {
@@ -152,6 +150,8 @@ if (!gotTheLock) {
152 } 150 }
153 } 151 }
154 }); 152 });
153} else {
154 app.quit();
155} 155}
156 156
157// Fix Unity indicator issue 157// Fix Unity indicator issue
diff --git a/src/internal-server/app/ImageHelper.js b/src/internal-server/app/ImageHelper.js
index 905ba81ab..fba610069 100644
--- a/src/internal-server/app/ImageHelper.js
+++ b/src/internal-server/app/ImageHelper.js
@@ -21,7 +21,7 @@ const moveIcon = async icon => {
21 name: iconId, 21 name: iconId,
22 overwrite: true, 22 overwrite: true,
23 }); 23 });
24 return !icon.moved() ? '-1' : iconId; 24 return icon.moved() ? iconId : '-1';
25}; 25};
26 26
27const deduceIconUrl = iconId => 27const deduceIconUrl = iconId =>
diff --git a/src/internal-server/app/Middleware/ConvertEmptyStringsToNull.js b/src/internal-server/app/Middleware/ConvertEmptyStringsToNull.js
index 9591cdc41..91ab22ee5 100644
--- a/src/internal-server/app/Middleware/ConvertEmptyStringsToNull.js
+++ b/src/internal-server/app/Middleware/ConvertEmptyStringsToNull.js
@@ -3,7 +3,7 @@ class ConvertEmptyStringsToNull {
3 if (Object.keys(request.body).length > 0) { 3 if (Object.keys(request.body).length > 0) {
4 request.body = Object.assign( 4 request.body = Object.assign(
5 ...Object.keys(request.body).map(key => ({ 5 ...Object.keys(request.body).map(key => ({
6 [key]: request.body[key] !== '' ? request.body[key] : null, 6 [key]: request.body[key] === '' ? null : request.body[key],
7 })), 7 })),
8 ); 8 );
9 } 9 }
diff --git a/src/internal-server/start/migrate.js b/src/internal-server/start/migrate.js
index 0af33a977..4cd502c3f 100644
--- a/src/internal-server/start/migrate.js
+++ b/src/internal-server/start/migrate.js
@@ -21,13 +21,13 @@ module.exports = async () => {
21 21
22 const user = await User.find(1); 22 const user = await User.find(1);
23 let settings; 23 let settings;
24 if (!user) { 24 if (user) {
25 settings = convertToJSON(user.settings);
26 } else {
25 migrateLog("🎩 Migrating from old Ferdium version as user doesn't exist"); 27 migrateLog("🎩 Migrating from old Ferdium version as user doesn't exist");
26 28
27 // Create new user 29 // Create new user
28 await Database.raw('INSERT INTO "users" ("id") VALUES (\'1\');'); 30 await Database.raw('INSERT INTO "users" ("id") VALUES (\'1\');');
29 } else {
30 settings = convertToJSON(user.settings);
31 } 31 }
32 32
33 if ( 33 if (
diff --git a/src/internal-server/test.ts b/src/internal-server/test.ts
index 5bb1f2b36..6949df79e 100644
--- a/src/internal-server/test.ts
+++ b/src/internal-server/test.ts
@@ -6,4 +6,5 @@ const dummyUserFolder = join(__dirname, 'user_data');
6 6
7ensureDirSync(dummyUserFolder); 7ensureDirSync(dummyUserFolder);
8 8
9// eslint-disable-next-line unicorn/prefer-top-level-await
9server(dummyUserFolder, 46_568, 'test').catch(console.log); 10server(dummyUserFolder, 46_568, 'test').catch(console.log);
diff --git a/src/lib/Menu.ts b/src/lib/Menu.ts
index b1510cec3..936785b9b 100644
--- a/src/lib/Menu.ts
+++ b/src/lib/Menu.ts
@@ -453,7 +453,7 @@ function titleBarTemplateFactory(
453 }, 453 },
454 { 454 {
455 label: intl.formatMessage(menuItems.back), 455 label: intl.formatMessage(menuItems.back),
456 accelerator: `${!isMac ? altKey() : cmdOrCtrlShortcutKey()}+Left`, 456 accelerator: `${isMac ? cmdOrCtrlShortcutKey() : altKey()}+Left`,
457 click() { 457 click() {
458 const activeService = getActiveService(); 458 const activeService = getActiveService();
459 if (!activeService) { 459 if (!activeService) {
@@ -464,7 +464,7 @@ function titleBarTemplateFactory(
464 }, 464 },
465 { 465 {
466 label: intl.formatMessage(menuItems.forward), 466 label: intl.formatMessage(menuItems.forward),
467 accelerator: `${!isMac ? altKey() : cmdOrCtrlShortcutKey()}+Right`, 467 accelerator: `${isMac ? cmdOrCtrlShortcutKey() : altKey()}+Right`,
468 click() { 468 click() {
469 const activeService = getActiveService(); 469 const activeService = getActiveService();
470 if (!activeService) { 470 if (!activeService) {
@@ -728,7 +728,36 @@ class FranzMenu implements StoresProps {
728 }); 728 });
729 } 729 }
730 730
731 if (!locked) { 731 if (locked) {
732 const touchIdEnabled = isMac
733 ? this.stores.settings.app.useTouchIdToUnlock &&
734 systemPreferences.canPromptTouchID()
735 : false;
736
737 (tpl[0].submenu as MenuItemConstructorOptions[]).unshift(
738 {
739 label: intl.formatMessage(menuItems.touchId),
740 accelerator: `${lockFerdiumShortcutKey()}`,
741 visible: touchIdEnabled,
742 click() {
743 systemPreferences
744 .promptTouchID(intl.formatMessage(menuItems.touchId))
745 .then(() => {
746 actions.settings.update({
747 type: 'app',
748 data: {
749 locked: false,
750 },
751 });
752 });
753 },
754 },
755 {
756 type: 'separator',
757 visible: touchIdEnabled,
758 },
759 );
760 } else {
732 (tpl[1].submenu as MenuItemConstructorOptions[]).push( 761 (tpl[1].submenu as MenuItemConstructorOptions[]).push(
733 { 762 {
734 type: 'separator', 763 type: 'separator',
@@ -834,35 +863,6 @@ class FranzMenu implements StoresProps {
834 tpl[3].submenu = this.workspacesMenu(); 863 tpl[3].submenu = this.workspacesMenu();
835 864
836 tpl[4].submenu = this.todosMenu(); 865 tpl[4].submenu = this.todosMenu();
837 } else {
838 const touchIdEnabled = isMac
839 ? this.stores.settings.app.useTouchIdToUnlock &&
840 systemPreferences.canPromptTouchID()
841 : false;
842
843 (tpl[0].submenu as MenuItemConstructorOptions[]).unshift(
844 {
845 label: intl.formatMessage(menuItems.touchId),
846 accelerator: `${lockFerdiumShortcutKey()}`,
847 visible: touchIdEnabled,
848 click() {
849 systemPreferences
850 .promptTouchID(intl.formatMessage(menuItems.touchId))
851 .then(() => {
852 actions.settings.update({
853 type: 'app',
854 data: {
855 locked: false,
856 },
857 });
858 });
859 },
860 },
861 {
862 type: 'separator',
863 visible: touchIdEnabled,
864 },
865 );
866 } 866 }
867 867
868 tpl.unshift({ 868 tpl.unshift({
diff --git a/src/stores/AppStore.ts b/src/stores/AppStore.ts
index 02d616241..18b38799e 100644
--- a/src/stores/AppStore.ts
+++ b/src/stores/AppStore.ts
@@ -529,14 +529,14 @@ export default class AppStore extends TypedStore {
529 529
530 // Reactions 530 // Reactions
531 _offlineCheck() { 531 _offlineCheck() {
532 if (!this.isOnline) { 532 if (this.isOnline) {
533 this.timeOfflineStart = moment();
534 } else {
535 const deltaTime = moment().diff(this.timeOfflineStart); 533 const deltaTime = moment().diff(this.timeOfflineStart);
536 534
537 if (deltaTime > ms('30m')) { 535 if (deltaTime > ms('30m')) {
538 this.actions.service.reloadAll(); 536 this.actions.service.reloadAll();
539 } 537 }
538 } else {
539 this.timeOfflineStart = moment();
540 } 540 }
541 } 541 }
542 542
diff --git a/src/stores/ServicesStore.ts b/src/stores/ServicesStore.ts
index 829c64d76..9c15d3a07 100644
--- a/src/stores/ServicesStore.ts
+++ b/src/stores/ServicesStore.ts
@@ -294,19 +294,20 @@ export default class ServicesStore extends TypedStore {
294 service.lastPoll - service.lastPollAnswer > ms('1m') 294 service.lastPoll - service.lastPollAnswer > ms('1m')
295 ) { 295 ) {
296 // If service did not reply for more than 1m try to reload. 296 // If service did not reply for more than 1m try to reload.
297 if (!service.isActive) { 297 if (service.isActive) {
298 if (this.stores.app.isOnline && service.lostRecipeReloadAttempt < 3) {
299 debug(
300 `Reloading service: ${service.name} (${service.id}). Attempt: ${service.lostRecipeReloadAttempt}`,
301 );
302 // service.webview.reload();
303 service.lostRecipeReloadAttempt += 1;
304
305 service.lostRecipeConnection = false;
306 }
307 } else {
308 debug(`Service lost connection: ${service.name} (${service.id}).`); 298 debug(`Service lost connection: ${service.name} (${service.id}).`);
309 service.lostRecipeConnection = true; 299 service.lostRecipeConnection = true;
300 } else if (
301 this.stores.app.isOnline &&
302 service.lostRecipeReloadAttempt < 3
303 ) {
304 debug(
305 `Reloading service: ${service.name} (${service.id}). Attempt: ${service.lostRecipeReloadAttempt}`,
306 );
307 // service.webview.reload();
308 service.lostRecipeReloadAttempt += 1;
309
310 service.lostRecipeConnection = false;
310 } 311 }
311 } else { 312 } else {
312 service.lostRecipeConnection = false; 313 service.lostRecipeConnection = false;
@@ -512,11 +513,11 @@ export default class ServicesStore extends TypedStore {
512 } 513 }
513 514
514 if (data.team) { 515 if (data.team) {
515 if (!data.customURL) { 516 if (data.customURL) {
516 serviceData.team = data.team;
517 } else {
518 // TODO: Is this correct? 517 // TODO: Is this correct?
519 serviceData.customUrl = data.team; 518 serviceData.customUrl = data.team;
519 } else {
520 serviceData.team = data.team;
520 } 521 }
521 } 522 }
522 523
@@ -893,9 +894,7 @@ export default class ServicesStore extends TypedStore {
893 break; 894 break;
894 } 895 }
895 case 'set-service-spellchecker-language': { 896 case 'set-service-spellchecker-language': {
896 if (!args) { 897 if (args) {
897 console.warn('Did not receive locale');
898 } else {
899 this.actions.service.updateService({ 898 this.actions.service.updateService({
900 serviceId, 899 serviceId,
901 serviceData: { 900 serviceData: {
@@ -903,6 +902,8 @@ export default class ServicesStore extends TypedStore {
903 }, 902 },
904 redirect: false, 903 redirect: false,
905 }); 904 });
905 } else {
906 console.warn('Did not receive locale');
906 } 907 }
907 908
908 break; 909 break;
@@ -1176,13 +1177,13 @@ export default class ServicesStore extends TypedStore {
1176 service.lastPoll = Date.now(); 1177 service.lastPoll = Date.now();
1177 }; 1178 };
1178 1179
1179 if (!serviceId) { 1180 if (serviceId) {
1180 for (const service of this.allDisplayed) resetTimer(service);
1181 } else {
1182 const service = this.one(serviceId); 1181 const service = this.one(serviceId);
1183 if (service) { 1182 if (service) {
1184 resetTimer(service); 1183 resetTimer(service);
1185 } 1184 }
1185 } else {
1186 for (const service of this.allDisplayed) resetTimer(service);
1186 } 1187 }
1187 } 1188 }
1188 1189
diff --git a/src/stores/SettingsStore.ts b/src/stores/SettingsStore.ts
index 811bc6f76..5ca499160 100644
--- a/src/stores/SettingsStore.ts
+++ b/src/stores/SettingsStore.ts
@@ -157,10 +157,7 @@ export default class SettingsStore extends TypedStore {
157 157
158 @action async _update({ type, data }): Promise<void> { 158 @action async _update({ type, data }): Promise<void> {
159 const appSettings = this.all; 159 const appSettings = this.all;
160 if (!this.fileSystemSettingsTypes.includes(type)) { 160 if (this.fileSystemSettingsTypes.includes(type)) {
161 debug('Update settings', type, data, this.all);
162 localStorage.setItem(type, Object.assign(appSettings[type], data));
163 } else {
164 debug('Update settings on file system', type, data); 161 debug('Update settings on file system', type, data);
165 ipcRenderer.send('updateAppSettings', { 162 ipcRenderer.send('updateAppSettings', {
166 type, 163 type,
@@ -168,6 +165,9 @@ export default class SettingsStore extends TypedStore {
168 }); 165 });
169 166
170 Object.assign(this._fileSystemSettingsCache[type], data); 167 Object.assign(this._fileSystemSettingsCache[type], data);
168 } else {
169 debug('Update settings', type, data, this.all);
170 localStorage.setItem(type, Object.assign(appSettings[type], data));
171 } 171 }
172 } 172 }
173 173
diff --git a/src/stores/UIStore.ts b/src/stores/UIStore.ts
index e0589729f..4ed45fc3b 100644
--- a/src/stores/UIStore.ts
+++ b/src/stores/UIStore.ts
@@ -98,7 +98,7 @@ export default class UIStore extends TypedStore {
98 98
99 // Actions 99 // Actions
100 @action _openSettings({ path = '/settings' }): void { 100 @action _openSettings({ path = '/settings' }): void {
101 const settingsPath = path !== '/settings' ? `/settings/${path}` : path; 101 const settingsPath = path === '/settings' ? path : `/settings/${path}`;
102 this.stores.router.push(settingsPath); 102 this.stores.router.push(settingsPath);
103 } 103 }
104 104
@@ -116,19 +116,19 @@ export default class UIStore extends TypedStore {
116 116
117 // Reactions 117 // Reactions
118 _setupThemeInDOM(): void { 118 _setupThemeInDOM(): void {
119 if (!this.isDarkThemeActive) { 119 if (this.isDarkThemeActive) {
120 document.body.classList.remove('theme__dark');
121 } else {
122 document.body.classList.add('theme__dark'); 120 document.body.classList.add('theme__dark');
121 } else {
122 document.body.classList.remove('theme__dark');
123 } 123 }
124 } 124 }
125 125
126 _setupModeInDOM(): void { 126 _setupModeInDOM(): void {
127 if (!this.isSplitModeActive) { 127 if (this.isSplitModeActive) {
128 document.body.classList.remove('mode__split');
129 } else {
130 document.body.classList.add('mode__split'); 128 document.body.classList.add('mode__split');
131 document.body.dataset.columns = this.splitColumnsNo.toString(); 129 document.body.dataset.columns = this.splitColumnsNo.toString();
130 } else {
131 document.body.classList.remove('mode__split');
132 } 132 }
133 } 133 }
134 134
diff --git a/src/webview/darkmode.ts b/src/webview/darkmode.ts
index 9944a7afa..f5e8700e0 100644
--- a/src/webview/darkmode.ts
+++ b/src/webview/darkmode.ts
@@ -5,7 +5,7 @@ const debug = require('../preload-safe-debug')('Ferdium:DarkMode');
5 5
6const chars = [...'abcdefghijklmnopqrstuvwxyz']; 6const chars = [...'abcdefghijklmnopqrstuvwxyz'];
7 7
8const ID = [...Array.from({ length: 20 })] 8const ID = Array.from({ length: 20 })
9 .map(() => chars[Math.trunc(Math.random() * chars.length)]) 9 .map(() => chars[Math.trunc(Math.random() * chars.length)])
10 .join(''); 10 .join('');
11 11
@@ -26,7 +26,7 @@ export function injectDarkModeStyle(recipePath: string) {
26 styles.innerHTML = data.toString(); 26 styles.innerHTML = data.toString();
27 debug('Loaded darkmode.css from: ', darkmodeCss); 27 debug('Loaded darkmode.css from: ', darkmodeCss);
28 28
29 document.querySelector('head')?.appendChild(styles); 29 document.querySelector('head')?.append(styles);
30 30
31 debug('Injected Dark Mode style with ID', ID); 31 debug('Injected Dark Mode style with ID', ID);
32 } 32 }
diff --git a/src/webview/lib/RecipeWebview.ts b/src/webview/lib/RecipeWebview.ts
index 436525b9e..44b3c5ab4 100644
--- a/src/webview/lib/RecipeWebview.ts
+++ b/src/webview/lib/RecipeWebview.ts
@@ -101,13 +101,13 @@ class RecipeWebview {
101 * @param {string | number | undefined | null} text to be parsed 101 * @param {string | number | undefined | null} text to be parsed
102 */ 102 */
103 isImage(link): boolean { 103 isImage(link): boolean {
104 if (typeof link === 'undefined') { 104 if (link === undefined) {
105 return false; 105 return false;
106 } 106 }
107 107
108 const { role } = link.dataset; 108 const { role } = link.dataset;
109 109
110 if (typeof role !== 'undefined') { 110 if (role !== undefined) {
111 const roles = ['img']; 111 const roles = ['img'];
112 return roles.includes(role); 112 return roles.includes(role);
113 } 113 }
diff --git a/src/webview/recipe.ts b/src/webview/recipe.ts
index 36b8b7c98..0d18e4347 100644
--- a/src/webview/recipe.ts
+++ b/src/webview/recipe.ts
@@ -280,12 +280,12 @@ class RecipeController {
280 } 280 }
281 }; 281 };
282 282
283 if (document.readyState !== 'loading') { 283 if (document.readyState === 'loading') {
284 loadUserJs();
285 } else {
286 document.addEventListener('DOMContentLoaded', () => { 284 document.addEventListener('DOMContentLoaded', () => {
287 loadUserJs(); 285 loadUserJs();
288 }); 286 });
287 } else {
288 loadUserJs();
289 } 289 }
290 } 290 }
291 } 291 }