diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 7909607fce..3e8ac412a6 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -206,6 +206,7 @@ public function index(): TemplateResponse { 'attachment-size-limit' => $this->config->getSystemValue('app.mail.attachment-size-limit', 0), 'app-version' => $this->config->getAppValue('mail', 'installed_version'), 'external-avatars' => $this->preferences->getPreference($this->currentUserId, 'external-avatars', 'true'), + 'layout-mode' => $this->preferences->getPreference($this->currentUserId, 'layout-mode', 'vertical-split'), 'reply-mode' => $this->preferences->getPreference($this->currentUserId, 'reply-mode', 'top'), 'collect-data' => $this->preferences->getPreference($this->currentUserId, 'collect-data', 'true'), 'search-priority-body' => $this->preferences->getPreference($this->currentUserId, 'search-priority-body', 'false'), diff --git a/src/components/AppSettingsMenu.vue b/src/components/AppSettingsMenu.vue index 7aa1501777..df4caed50c 100755 --- a/src/components/AppSettingsMenu.vue +++ b/src/components/AppSettingsMenu.vue @@ -4,6 +4,32 @@ :name="t('mail', 'Mail settings')" :show-navigation="true" :open.sync="showSettings"> + + + + {{ t('mail', 'List') }} + + + + {{ t('mail', 'Vertical split') }} + +
- {{ t('mail', 'Newest') }} - - + {{ t('mail', 'Oldest') }} - +
@@ -202,12 +228,14 @@ - diff --git a/src/components/EnvelopeList.vue b/src/components/EnvelopeList.vue index 654669b26d..eb53216d7a 100644 --- a/src/components/EnvelopeList.vue +++ b/src/components/EnvelopeList.vue @@ -320,6 +320,7 @@ export default { showMoveModal: false, showTagModal: false, lastToggledIndex: undefined, + defaultView: false, } }, computed: { diff --git a/src/components/Mailbox.vue b/src/components/Mailbox.vue index f44c27ef9b..096444cd19 100644 --- a/src/components/Mailbox.vue +++ b/src/components/Mailbox.vue @@ -2,6 +2,7 @@ - @copyright 2020 Christoph Wurst - - @author 2020 Christoph Wurst + - @author Richard Steinmetz - - @license AGPL-3.0-or-later - @@ -111,7 +112,7 @@ export default { error: false, refreshing: false, loadingMore: false, - loadingEnvelopes: true, + loadingEnvelopes: false, loadingCacheInitialization: false, loadMailboxInterval: undefined, expanded: false, @@ -161,11 +162,14 @@ export default { this.loadMailboxInterval = setInterval(this.loadMailbox, 60000) }, async mounted() { - this.loadEnvelopes() - .then(() => { - logger.debug(`syncing mailbox ${this.mailbox.databaseId} (${this.searchQuery}) after mount`) - this.sync(false) - }) + if (this.$store.getters.hasFetchedInitialEnvelopes) { + return + } + + await this.loadEnvelopes() + logger.debug(`syncing mailbox ${this.mailbox.databaseId} (${this.searchQuery}) after mount`) + await this.sync(false) + this.$store.commit('setHasFetchedInitialEnvelopes', true) }, destroyed() { this.bus.off('load-more', this.onScroll) diff --git a/src/components/MailboxThread.vue b/src/components/MailboxThread.vue index 2bec34801f..81fa8b10b6 100644 --- a/src/components/MailboxThread.vue +++ b/src/components/MailboxThread.vue @@ -1,7 +1,10 @@ @@ -138,9 +142,13 @@ export default { priorityImportantQuery, priorityOtherQuery, startMailboxTimer: undefined, + hasContent: false, } }, computed: { + layoutMode() { + return this.$store.getters.getPreference('layout-mode', 'vertical-split') + }, unifiedAccount() { return this.$store.getters.getAccount(UNIFIED_ACCOUNT_ID) }, @@ -331,11 +339,6 @@ export default { background-color: var(--color-background-dark); } } -:deep(.button-vue--vue-secondary) { - position: sticky; - top:40px; - left: 10px; -} :deep(.app-content-wrapper) { overflow: auto; } @@ -351,10 +354,17 @@ export default { margin-bottom: 20px; } } -.header__button { +.list__wrapper { display: flex; flex: 1 0 0; flex-direction: column; - height: calc(100vh - var(--header-height)); + height: 100%; +} +:deep(.app-details-toggle) { + opacity: 1; +} + // temporary fix +:deep(.app-content-list) { + min-height: 0; } diff --git a/src/main.js b/src/main.js index 877fdd8cbc..2d04682a06 100644 --- a/src/main.js +++ b/src/main.js @@ -109,6 +109,10 @@ store.commit('savePreference', { key: 'password-is-unavailable', value: loadState('mail', 'password-is-unavailable', false), }) +store.commit('savePreference', { + key: 'layout-mode', + value: getPreferenceFromPage('layout-mode'), +}) const accountSettings = loadState('mail', 'account-settings') const accounts = loadState('mail', 'accounts', []) diff --git a/src/store/actions.js b/src/store/actions.js index c65d65ed63..7c0b4f0a85 100644 --- a/src/store/actions.js +++ b/src/store/actions.js @@ -1499,4 +1499,13 @@ export default { }, }) }, + async setLayout({ commit }, { list }) { + try { + commit('setOneLineLayout', { + list, + }) + } catch (error) { + logger.error('Could not set layouts', { error }) + } + }, } diff --git a/src/store/getters.js b/src/store/getters.js index ab7fbfd7f4..226d17b59a 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -155,4 +155,6 @@ export const getters = { getInbox: (state, getters) => (accountId) => { return getters.findMailboxBySpecialRole(accountId, 'inbox') }, + isOneLineLayout: (state) => state.list, + hasFetchedInitialEnvelopes: (state) => state.hasFetchedInitialEnvelopes, } diff --git a/src/store/index.js b/src/store/index.js index 6bdbda6fe3..5deb66f57a 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -107,6 +107,7 @@ export default new Store({ sieveScript: {}, calendars: [], smimeCertificates: [], + hasFetchedInitialEnvelopes: false, }, getters, mutations, diff --git a/src/store/mutations.js b/src/store/mutations.js index f07f88fbe8..712856f68d 100644 --- a/src/store/mutations.js +++ b/src/store/mutations.js @@ -506,4 +506,10 @@ export default { addSmimeCertificate(state, { certificate }) { state.smimeCertificates = [...state.smimeCertificates, certificate] }, + setOneLineLayout(state, { list }) { + Vue.set(state, 'list', list) + }, + setHasFetchedInitialEnvelopes(state, hasFetchedInitialEnvelopes) { + state.hasFetchedInitialEnvelopes = hasFetchedInitialEnvelopes + }, } diff --git a/src/tests/unit/components/Envelope.vue.spec.js b/src/tests/unit/components/Envelope.vue.spec.js index a2353a45c9..ede0dd0757 100644 --- a/src/tests/unit/components/Envelope.vue.spec.js +++ b/src/tests/unit/components/Envelope.vue.spec.js @@ -52,6 +52,7 @@ describe('Envelope', () => { getAccount: () => (id) => ({}), getEnvelopeTags: () => (id) => ([]), getMailbox: () => (id) => ({}), + getPreference: () => (key, defaultValue) => defaultValue, } store = new Vuex.Store({ actions, diff --git a/src/views/Home.vue b/src/views/Home.vue index 95a34d2f24..0ef21bcfcf 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -175,8 +175,4 @@ export default { flex: 1 1 100%; min-width: 70%; } -// Align the appNavigation toggle with the apps header toolbar -:deep(button.app-navigation-toggle) { - top: 8px; -} diff --git a/templates/index.php b/templates/index.php index acb3f98501..a5f1d5896f 100644 --- a/templates/index.php +++ b/templates/index.php @@ -33,4 +33,5 @@ + diff --git a/tests/Unit/Controller/PageControllerTest.php b/tests/Unit/Controller/PageControllerTest.php index 1515d2c9ba..5435def4f1 100644 --- a/tests/Unit/Controller/PageControllerTest.php +++ b/tests/Unit/Controller/PageControllerTest.php @@ -168,7 +168,7 @@ public function testIndex(): void { $account1 = $this->createMock(Account::class); $account2 = $this->createMock(Account::class); $mailbox = $this->createMock(Mailbox::class); - $this->preferences->expects($this->exactly(8)) + $this->preferences->expects($this->exactly(9)) ->method('getPreference') ->willReturnMap([ [$this->userId, 'account-settings', '[]', json_encode([])], @@ -179,6 +179,7 @@ public function testIndex(): void { [$this->userId, 'search-priority-body', 'false', 'false'], [$this->userId, 'start-mailbox-id', null, '123'], [$this->userId, 'tag-classified-messages', 'true', 'true'], + [$this->userId, 'layout-mode', 'vertical-split', 'vertical-split'], ]); $this->accountService->expects($this->once()) ->method('findByUserId') @@ -323,6 +324,7 @@ public function testIndex(): void { 'start-mailbox-id' => '123', 'tag-classified-messages' => 'true', 'search-priority-body' => 'false', + 'layout-mode' => 'vertical-split', ]); $csp = new ContentSecurityPolicy(); $csp->addAllowedFrameDomain('\'self\'');