Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the possibility to change mail list view into full width #9285

Merged
merged 1 commit into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/Controller/PageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand Down
58 changes: 52 additions & 6 deletions src/components/AppSettingsMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@
:name="t('mail', 'Mail settings')"
:show-navigation="true"
:open.sync="showSettings">
<NcAppSettingsSection id="mail-list-view" :name="t('mail', 'Layout')">
<NcCheckboxRadioSwitch value="no-split"
:button-variant="true"
name="mail-layout"
type="radio"
:checked="layoutMode"
GretaD marked this conversation as resolved.
Show resolved Hide resolved
button-variant-grouped="vertical"
@update:checked="setLayout">
<template #icon>
<CompactMode :size="20" />
</template>
{{ t('mail', 'List') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch value="vertical-split"
:button-variant="true"
name="mail-layout"
type="radio"
:checked="layoutMode"
button-variant-grouped="vertical"
@update:checked="setLayout">
<template #icon>
<VerticalSplit :size="20" />
</template>
{{ t('mail', 'Vertical split') }}
</NcCheckboxRadioSwitch>
</NcAppSettingsSection>
<NcAppSettingsSection id="account-settings" :name="t('mail', 'Account creation')">
<NcButton v-if="allowNewMailAccounts"
type="primary"
Expand Down Expand Up @@ -120,22 +146,22 @@
</NcAppSettingsSection>
<NcAppSettingsSection id="sorting-settings" :name="t('mail', 'Sorting')">
<div class="sorting">
<CheckboxRadioSwitch class="sorting__switch"
<NcCheckboxRadioSwitch class="sorting__switch"
:checked="sortOrder"
value="newest"
name="order_radio"
type="radio"
@update:checked="onSortByDate">
{{ t('mail', 'Newest') }}
</CheckboxRadioSwitch>
<CheckboxRadioSwitch class="sorting__switch"
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch class="sorting__switch"
:checked="sortOrder"
value="oldest"
name="order_radio"
type="radio"
@update:checked="onSortByDate">
{{ t('mail', 'Oldest') }}
</CheckboxRadioSwitch>
</NcCheckboxRadioSwitch>
</div>
</NcAppSettingsSection>
<NcAppSettingsSection id="mailvelope-settings" :name="t('mail', 'Mailvelope')">
Expand Down Expand Up @@ -202,12 +228,14 @@
<script>
import { generateUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs'
import CompactMode from 'vue-material-design-icons/ReorderHorizontal.vue'
import { NcAppSettingsSection, NcAppSettingsDialog, NcButton, NcLoadingIcon as IconLoading, NcCheckboxRadioSwitch as CheckboxRadioSwitch } from '@nextcloud/vue'
import { NcAppSettingsSection, NcAppSettingsDialog, NcButton, NcLoadingIcon as IconLoading, NcCheckboxRadioSwitch } from '@nextcloud/vue'
import IconAdd from 'vue-material-design-icons/Plus.vue'
import IconEmail from 'vue-material-design-icons/Email.vue'
import IconLock from 'vue-material-design-icons/Lock.vue'
import VerticalSplit from 'vue-material-design-icons/FormatColumns.vue'
import Logger from '../logger.js'
import SmimeCertificateModal from './smime/SmimeCertificateModal.vue'
import TrustedSenders from './TrustedSenders.vue'
Expand All @@ -222,9 +250,11 @@ export default {
IconLoading,
IconLock,
SmimeCertificateModal,
CheckboxRadioSwitch,
NcCheckboxRadioSwitch,
NcAppSettingsDialog,
NcAppSettingsSection,
CompactMode,
VerticalSplit,
},
props: {
open: {
Expand Down Expand Up @@ -270,6 +300,9 @@ export default {
allowNewMailAccounts() {
return this.$store.getters.getPreference('allow-new-accounts', true)
},
layoutMode() {
return this.$store.getters.getPreference('layout-mode', 'vertical-split')
},
},
watch: {
showSettings(value) {
Expand All @@ -287,6 +320,16 @@ export default {
this.sortOrder = this.$store.getters.getPreference('sort-order', 'newest')
},
methods: {
async setLayout(value) {
try {
await this.$store.dispatch('savePreference', {
key: 'layout-mode',
value,
})
} catch (error) {
Logger.error('could not save preferences', { error })
}
},
async onOpen() {
this.showSettings = true
},
Expand Down Expand Up @@ -465,4 +508,7 @@ p.app-settings {
margin-bottom: 6px;
color: var(--color-text-maxcontrast);
}
.app-settings-section {
list-style: none;
}
</style>
92 changes: 60 additions & 32 deletions src/components/Envelope.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
:data-envelope-id="data.databaseId"
:name="addresses"
:details="formatted()"
:one-line="oneLineLayout"
@click="onClick"
@click.ctrl.prevent="toggleSelected"
@update:menuOpen="closeMoreAndSnoozeOptions">
Expand All @@ -22,16 +23,19 @@
fill-color="#f9cf3d"
:size="18"
class="app-content-list-item-star favorite-icon-style"
:class="{ 'one-line': oneLineLayout, 'favorite-icon-style': !oneLineLayout }"
:data-starred="data.flags.flagged ? 'true' : 'false'"
@click.prevent="hasWriteAcl ? onToggleFlagged() : false" />
<div v-if="isImportant"
class="app-content-list-item-star svg icon-important"
:class="{ 'important-one-line': oneLineLayout, 'icon-important': !oneLineLayout }"
:data-starred="isImportant ? 'true' : 'false'"
@click.prevent="hasWriteAcl ? onToggleImportant() : false"
v-html="importantSvg" />

Check warning on line 34 in src/components/Envelope.vue

View workflow job for this annotation

GitHub Actions / NPM lint

'v-html' directive can lead to XSS attack
<JunkIcon v-if="data.flags.$junk"
:size="18"
class="app-content-list-item-star junk-icon-style"
:class="{ 'one-line': oneLineLayout, 'junk-icon-style': !oneLineLayout }"
:data-starred="data.flags.$junk ? 'true' : 'false'"
@click.prevent="hasWriteAcl ? onToggleJunk() : false" />
<div class="app-content-list-item-icon">
Expand All @@ -48,23 +52,26 @@
</div>
</template>
<template #subname>
<div class="envelope__subtitle">
<Reply v-if="data.flags.answered"
class="seen-icon-style"
:size="18" />
<IconAttachment v-if="data.flags.hasAttachments === true"
class="attachment-icon-style"
:size="18" />
<span v-else-if="draft" class="draft">
<em>{{ t('mail', 'Draft: ') }}</em>
</span>
<span class="envelope__subtitle__subject">
{{ subjectForSubtitle }}
</span>
</div>
<div v-if="data.encrypted || data.previewText"
class="envelope__preview-text">
{{ isEncrypted ? t('mail', 'Encrypted message') : data.previewText.trim() }}
<div class="line-two"
:class="{ 'one-line': oneLineLayout }">
<div class="envelope__subtitle">
<Reply v-if="data.flags.answered"
class="seen-icon-style"
:size="18" />
<IconAttachment v-if="data.flags.hasAttachments === true"
class="attachment-icon-style"
:size="18" />
<span v-else-if="draft" class="draft">
<em>{{ t('mail', 'Draft: ') }}</em>
</span>
<span class="envelope__subtitle__subject">
{{ subjectForSubtitle }}
</span>
</div>
<div v-if="data.encrypted || data.previewText"
class="envelope__preview-text">
{{ isEncrypted ? t('mail', 'Encrypted message') : data.previewText.trim() }}
</div>
</div>
</template>
<template #indicator>
Expand Down Expand Up @@ -126,7 +133,7 @@
messageLongDate
}}
</ActionText>
<ActionSeparator />
<NcActionSeparator />
<ActionButton v-if="hasWriteAcl"
:close-after-click="true"
@click.prevent="onToggleJunk">
Expand Down Expand Up @@ -320,7 +327,8 @@
NcListItem as ListItem,
NcActionButton as ActionButton,
NcActionLink as ActionLink,
NcActionSeparator as ActionSeparator,
NcActionSeparator,
NcActionInput,
NcActionText as ActionText,
} from '@nextcloud/vue'
import AlertOctagonIcon from 'vue-material-design-icons/AlertOctagon.vue'
Expand Down Expand Up @@ -364,8 +372,6 @@
import { isPgpText } from '../crypto/pgp.js'
import { mailboxHasRights } from '../util/acl.js'
import DownloadIcon from 'vue-material-design-icons/Download.vue'
import NcActionSeparator from '@nextcloud/vue/dist/Components/NcActionSeparator.js'
import NcActionInput from '@nextcloud/vue/dist/Components/NcActionInput.js'
import CalendarClock from 'vue-material-design-icons/CalendarClock.vue'
import AlarmIcon from 'vue-material-design-icons/Alarm.vue'
import moment from '@nextcloud/moment'
Expand Down Expand Up @@ -403,7 +409,6 @@
IconBullet,
Reply,
ActionLink,
ActionSeparator,
ActionText,
DownloadIcon,
ClockOutlineIcon,
Expand Down Expand Up @@ -467,6 +472,9 @@
messageLongDate() {
return messageDateTime(new Date(this.data.dateInt))
},
oneLineLayout() {
return this.$store.getters.getPreference('layout-mode', 'vertical-split') === 'no-split'
},
hasMultipleRecipients() {
if (!this.account) {
console.error('account is undefined', {
Expand Down Expand Up @@ -844,7 +852,6 @@
},
}
</script>

<style lang="scss" scoped>
.mail-message-account-color {
position: absolute;
Expand All @@ -860,20 +867,24 @@
}

&__subtitle {
display: flex;
gap: 4px;

overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&__subject {
line-height: 130%;
overflow: hidden;
text-overflow: ellipsis;
&::after {
content: '\00B7';
margin: 12px;
}
}
}
&__preview-text {
color: var(--color-text-maxcontrast);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: initial;
flex: 1 1;
}
}

Expand Down Expand Up @@ -903,6 +914,9 @@
}
}
}
.important-one-line.app-content-list-item-star:deep() {
top: 6px !important;
}

.app-content-list-item-select-checkbox {
display: inline-block;
Expand Down Expand Up @@ -974,7 +988,7 @@
border: 1px solid transparent;
border-radius: var(--border-radius-pill);
position: relative;
margin: 0 1px;
margin: 9px 1px 0;
overflow: hidden;
left: 4px;
}
Expand All @@ -986,7 +1000,7 @@
}
.icon-important.app-content-list-item-star:deep() {
position: absolute;
top: 14px;
top: 12px;
z-index: 1;
}
.app-content-list-item-star.favorite-icon-style {
Expand All @@ -1008,9 +1022,11 @@
}
.seen-icon-style {
opacity: .6;
display: inline;
}
.attachment-icon-style {
opacity: .6;
display: inline;
}
:deep(.list-item__anchor) {
margin-top: 6px;
Expand All @@ -1019,9 +1035,21 @@
:deep(.list-item) {
flex-wrap: wrap;
}
:deep(.list-item__extra) {
margin-top: 9px;
:deep(.line-two__subtitle) {
display: flex;
flex-basis: 100%;
padding-left: 40px;
width: 450px;
}
:deep(.line-one__title) {
flex-direction: row;
display: flex;
width: 200px;
}
.line-two.one-line {
display: flex;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
1 change: 1 addition & 0 deletions src/components/EnvelopeList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ export default {
showMoveModal: false,
showTagModal: false,
lastToggledIndex: undefined,
defaultView: false,
}
},
computed: {
Expand Down
16 changes: 10 additions & 6 deletions src/components/Mailbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
- @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
-
- @author 2020 Christoph Wurst <[email protected]>
- @author Richard Steinmetz <[email protected]>
-
- @license AGPL-3.0-or-later
-
Expand Down Expand Up @@ -111,7 +112,7 @@ export default {
error: false,
refreshing: false,
loadingMore: false,
loadingEnvelopes: true,
loadingEnvelopes: false,
loadingCacheInitialization: false,
loadMailboxInterval: undefined,
expanded: false,
Expand Down Expand Up @@ -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)
Expand Down
Loading
Loading