aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/services/content/ServiceView.js2
-rw-r--r--src/components/settings/settings/EditSettingsForm.js4
-rw-r--r--src/containers/settings/EditSettingsScreen.js10
-rw-r--r--src/environment.js1
-rw-r--r--src/features/workspaces/store.js11
-rw-r--r--src/i18n/locales/en-US.json1
-rw-r--r--src/i18n/locales/pl.json1
-rw-r--r--src/stores/ServicesStore.js18
-rw-r--r--src/stores/UIStore.ts21
-rw-r--r--src/styles/layout.scss4
-rw-r--r--src/styles/services.scss20
11 files changed, 90 insertions, 3 deletions
diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.js
index fa866e153..81401b1d2 100644
--- a/src/components/services/content/ServiceView.js
+++ b/src/components/services/content/ServiceView.js
@@ -108,7 +108,7 @@ class ServiceView extends Component {
108 } 108 }
109 109
110 return ( 110 return (
111 <div className={webviewClasses}> 111 <div className={webviewClasses} data-name={service.name}>
112 {service.isActive && service.isEnabled && ( 112 {service.isActive && service.isEnabled && (
113 <> 113 <>
114 {service.hasCrashed && ( 114 {service.hasCrashed && (
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index f7e0fdd6f..f5a29ff82 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -537,6 +537,10 @@ class EditSettingsForm extends Component {
537 537
538 <Hr /> 538 <Hr />
539 539
540 <Toggle field={form.$('splitMode')} />
541
542 <Hr />
543
540 <Select field={form.$('serviceRibbonWidth')} /> 544 <Select field={form.$('serviceRibbonWidth')} />
541 545
542 <Toggle field={form.$('useVerticalStyle')} /> 546 <Toggle field={form.$('useVerticalStyle')} />
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js
index 92985b68c..36b9e949b 100644
--- a/src/containers/settings/EditSettingsScreen.js
+++ b/src/containers/settings/EditSettingsScreen.js
@@ -164,6 +164,10 @@ const messages = defineMessages({
164 id: 'settings.app.form.universalDarkMode', 164 id: 'settings.app.form.universalDarkMode',
165 defaultMessage: 'Enable universal Dark Mode', 165 defaultMessage: 'Enable universal Dark Mode',
166 }, 166 },
167 splitMode: {
168 id: 'settings.app.form.splitMode',
169 defaultMessage: 'Enable Split View Mode',
170 },
167 serviceRibbonWidth: { 171 serviceRibbonWidth: {
168 id: 'settings.app.form.serviceRibbonWidth', 172 id: 'settings.app.form.serviceRibbonWidth',
169 defaultMessage: 'Sidebar width', 173 defaultMessage: 'Sidebar width',
@@ -288,6 +292,7 @@ class EditSettingsScreen extends Component {
288 darkMode: Boolean(settingsData.darkMode), 292 darkMode: Boolean(settingsData.darkMode),
289 adaptableDarkMode: Boolean(settingsData.adaptableDarkMode), 293 adaptableDarkMode: Boolean(settingsData.adaptableDarkMode),
290 universalDarkMode: Boolean(settingsData.universalDarkMode), 294 universalDarkMode: Boolean(settingsData.universalDarkMode),
295 splitMode: Boolean(settingsData.splitMode),
291 serviceRibbonWidth: Number(settingsData.serviceRibbonWidth), 296 serviceRibbonWidth: Number(settingsData.serviceRibbonWidth),
292 iconSize: Number(settingsData.iconSize), 297 iconSize: Number(settingsData.iconSize),
293 useVerticalStyle: Boolean(settingsData.useVerticalStyle), 298 useVerticalStyle: Boolean(settingsData.useVerticalStyle),
@@ -580,6 +585,11 @@ class EditSettingsScreen extends Component {
580 value: settings.all.app.universalDarkMode, 585 value: settings.all.app.universalDarkMode,
581 default: DEFAULT_APP_SETTINGS.universalDarkMode, 586 default: DEFAULT_APP_SETTINGS.universalDarkMode,
582 }, 587 },
588 splitMode: {
589 label: intl.formatMessage(messages.splitMode),
590 value: settings.all.app.splitMode,
591 default: DEFAULT_APP_SETTINGS.splitMode,
592 },
583 serviceRibbonWidth: { 593 serviceRibbonWidth: {
584 label: intl.formatMessage(messages.serviceRibbonWidth), 594 label: intl.formatMessage(messages.serviceRibbonWidth),
585 value: settings.all.app.serviceRibbonWidth, 595 value: settings.all.app.serviceRibbonWidth,
diff --git a/src/environment.js b/src/environment.js
index b30e3778d..b315466fc 100644
--- a/src/environment.js
+++ b/src/environment.js
@@ -136,6 +136,7 @@ export const DEFAULT_APP_SETTINGS = {
136 enableSpellchecking: true, 136 enableSpellchecking: true,
137 spellcheckerLanguage: 'en-us', 137 spellcheckerLanguage: 'en-us',
138 darkMode: isMac && electronApi.nativeTheme.shouldUseDarkColors, 138 darkMode: isMac && electronApi.nativeTheme.shouldUseDarkColors,
139 splitMode: false,
139 locale: '', 140 locale: '',
140 fallbackLocale: 'en-US', 141 fallbackLocale: 'en-US',
141 beta: false, 142 beta: false,
diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js
index 73e882990..db2b69f99 100644
--- a/src/features/workspaces/store.js
+++ b/src/features/workspaces/store.js
@@ -190,6 +190,12 @@ export default class WorkspacesStore extends FeatureStore {
190 setTimeout(() => { 190 setTimeout(() => {
191 this.isSwitchingWorkspace = false; 191 this.isSwitchingWorkspace = false;
192 this.nextWorkspace = null; 192 this.nextWorkspace = null;
193 if (this.stores.settings.app.splitMode) {
194 const serviceNames = new Set(this.getWorkspaceServices(workspace).map(service => service.name));
195 for (const wrapper of document.querySelectorAll('.services__webview-wrapper')) {
196 wrapper.style.display = serviceNames.has(wrapper.dataset.name) ? '' : 'none';
197 }
198 }
193 }, 1000); 199 }, 1000);
194 }; 200 };
195 201
@@ -205,6 +211,11 @@ export default class WorkspacesStore extends FeatureStore {
205 // Indicate that we are done switching to the default workspace 211 // Indicate that we are done switching to the default workspace
206 setTimeout(() => { 212 setTimeout(() => {
207 this.isSwitchingWorkspace = false; 213 this.isSwitchingWorkspace = false;
214 if (this.stores.settings.app.splitMode) {
215 for (const wrapper of document.querySelectorAll('.services__webview-wrapper')) {
216 wrapper.style.display = '';
217 }
218 }
208 }, 1000); 219 }, 1000);
209 }; 220 };
210 221
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index e2e0cdc83..25eedb456 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -239,6 +239,7 @@
239 "settings.app.form.showDisabledServices": "Display disabled services tabs", 239 "settings.app.form.showDisabledServices": "Display disabled services tabs",
240 "settings.app.form.showDragArea": "Show draggable area on window", 240 "settings.app.form.showDragArea": "Show draggable area on window",
241 "settings.app.form.showMessagesBadgesWhenMuted": "Show unread message badge when notifications are disabled", 241 "settings.app.form.showMessagesBadgesWhenMuted": "Show unread message badge when notifications are disabled",
242 "settings.app.form.splitMode": "Enable Split View Mode",
242 "settings.app.form.startMinimized": "Start minimized", 243 "settings.app.form.startMinimized": "Start minimized",
243 "settings.app.form.universalDarkMode": "Enable universal Dark Mode", 244 "settings.app.form.universalDarkMode": "Enable universal Dark Mode",
244 "settings.app.form.useTouchIdToUnlock": "Allow using TouchID to unlock Ferdi", 245 "settings.app.form.useTouchIdToUnlock": "Allow using TouchID to unlock Ferdi",
diff --git a/src/i18n/locales/pl.json b/src/i18n/locales/pl.json
index d0bbe725d..2d79744a6 100644
--- a/src/i18n/locales/pl.json
+++ b/src/i18n/locales/pl.json
@@ -239,6 +239,7 @@
239 "settings.app.form.showDisabledServices": "Wyświetlaj karty wyłączonych usług", 239 "settings.app.form.showDisabledServices": "Wyświetlaj karty wyłączonych usług",
240 "settings.app.form.showDragArea": "Show draggable area on window", 240 "settings.app.form.showDragArea": "Show draggable area on window",
241 "settings.app.form.showMessagesBadgesWhenMuted": "Pokaż licznik nieprzeczytanych wiadomości gdy powiadomienia są wyłączone", 241 "settings.app.form.showMessagesBadgesWhenMuted": "Pokaż licznik nieprzeczytanych wiadomości gdy powiadomienia są wyłączone",
242 "settings.app.form.splitMode": "Włącz tryb podzielony",
242 "settings.app.form.startMinimized": "Uruchom zminimalizowany", 243 "settings.app.form.startMinimized": "Uruchom zminimalizowany",
243 "settings.app.form.universalDarkMode": "Włącz uniwersalny tryb ciemny", 244 "settings.app.form.universalDarkMode": "Włącz uniwersalny tryb ciemny",
244 "settings.app.form.useTouchIdToUnlock": "Allow using TouchID to unlock Ferdi", 245 "settings.app.form.useTouchIdToUnlock": "Allow using TouchID to unlock Ferdi",
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index 67fd4103f..16defb327 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -163,6 +163,13 @@ export default class ServicesStore extends Store {
163 ); 163 );
164 164
165 reaction( 165 reaction(
166 () => this.stores.settings.app.splitMode,
167 () => {
168 this._shareSettingsWithServiceProcess();
169 },
170 );
171
172 reaction(
166 () => this.stores.settings.app.searchEngine, 173 () => this.stores.settings.app.searchEngine,
167 () => { 174 () => {
168 this._shareSettingsWithServiceProcess(); 175 this._shareSettingsWithServiceProcess();
@@ -667,12 +674,21 @@ export default class ServicesStore extends Store {
667 } 674 }
668 } 675 }
669 676
670 @action _focusActiveService() { 677 @action _focusActiveService(focusEvent = null) {
671 if (this.stores.user.isLoggedIn) { 678 if (this.stores.user.isLoggedIn) {
672 // TODO: add checks to not focus service when router path is /settings or /auth 679 // TODO: add checks to not focus service when router path is /settings or /auth
673 const service = this.active; 680 const service = this.active;
674 if (service) { 681 if (service) {
675 this._focusService({ serviceId: service.id }); 682 this._focusService({ serviceId: service.id });
683 if (this.stores.settings.app.splitMode && !focusEvent) {
684 setTimeout(() => {
685 document.querySelector('.services__webview-wrapper.is-active').scrollIntoView({
686 behavior: 'smooth',
687 block: 'end',
688 inline: 'nearest',
689 });
690 }, 10);
691 }
676 } else { 692 } else {
677 debug('No service is active'); 693 debug('No service is active');
678 } 694 }
diff --git a/src/stores/UIStore.ts b/src/stores/UIStore.ts
index ec48eeb40..6ab63c2ee 100644
--- a/src/stores/UIStore.ts
+++ b/src/stores/UIStore.ts
@@ -51,6 +51,13 @@ export default class UIStore extends Store {
51 }, 51 },
52 { fireImmediately: true }, 52 { fireImmediately: true },
53 ); 53 );
54 reaction(
55 () => this.isSplitModeActive,
56 () => {
57 this._setupModeInDOM();
58 },
59 { fireImmediately: true },
60 );
54 } 61 }
55 62
56 @computed get showMessageBadgesEvenWhenMuted() { 63 @computed get showMessageBadgesEvenWhenMuted() {
@@ -77,6 +84,10 @@ export default class UIStore extends Store {
77 ); 84 );
78 } 85 }
79 86
87 @computed get isSplitModeActive() {
88 return this.stores.settings.app.splitMode;
89 }
90
80 @computed get theme() { 91 @computed get theme() {
81 const themeId = 92 const themeId =
82 this.isDarkThemeActive || this.stores.settings.app.darkMode 93 this.isDarkThemeActive || this.stores.settings.app.darkMode
@@ -114,4 +125,14 @@ export default class UIStore extends Store {
114 body?.classList.add('theme__dark'); 125 body?.classList.add('theme__dark');
115 } 126 }
116 } 127 }
128
129 _setupModeInDOM() {
130 const body = document.querySelector('body');
131
132 if (!this.isSplitModeActive) {
133 body?.classList.remove('mode__split');
134 } else {
135 body?.classList.add('mode__split');
136 }
137 }
117} 138}
diff --git a/src/styles/layout.scss b/src/styles/layout.scss
index 49e041022..b5d4d86d0 100644
--- a/src/styles/layout.scss
+++ b/src/styles/layout.scss
@@ -82,6 +82,10 @@ body.win32:not(.isFullScreen) .app .app__content {
82 height: calc(100% - 28px); 82 height: calc(100% - 28px);
83} 83}
84 84
85.mode__split .app .app__service {
86 overflow-x: auto;
87}
88
85.app { 89.app {
86 .app__content { 90 .app__content {
87 display: flex; 91 display: flex;
diff --git a/src/styles/services.scss b/src/styles/services.scss
index 8b8c27e10..dd053e93d 100644
--- a/src/styles/services.scss
+++ b/src/styles/services.scss
@@ -18,6 +18,24 @@
18 } 18 }
19} 19}
20 20
21.mode__split .services {
22 display: flex;
23 overflow: visible;
24
25 .services__webview {
26 position: relative;
27 flex: 1 0 50%;
28
29 @media (min-width: 1280px) {
30 flex-basis: 33.33%;
31 }
32
33 @media (min-width: 2048px) {
34 flex-basis: 25%;
35 }
36 }
37}
38
21.services { 39.services {
22 background: #FFF; 40 background: #FFF;
23 flex: 1; 41 flex: 1;
@@ -71,7 +89,7 @@
71 } 89 }
72 90
73 .services__info-layer { 91 .services__info-layer {
74 position: absolut; 92 position: absolute;
75 z-index: 110; 93 z-index: 110;
76 } 94 }
77 95