feat: message list density
Signed-off-by: Sebastian <krupinski01@gmail.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onBeforeUnmount, ref } from 'vue'
|
import { computed, onBeforeUnmount, ref } from 'vue'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
import type { EntityIdentifier } from '@MailManager/types/common'
|
import type { EntityIdentifier } from '@MailManager/types/common'
|
||||||
import type { EntityObject } from '@MailManager/models'
|
import type { EntityObject } from '@MailManager/models'
|
||||||
import type { CollectionObject } from '@MailManager/models/collection'
|
import type { CollectionObject } from '@MailManager/models/collection'
|
||||||
|
import { messageListDensityConfig, useMailSettingsStore } from '@/stores/mailSettingsStore'
|
||||||
import RecipientDetails from '@/components/common/RecipientDetails.vue'
|
import RecipientDetails from '@/components/common/RecipientDetails.vue'
|
||||||
import MessageListItemMenu from '@/components/MessageListItemMenu.vue'
|
import MessageListItemMenu from '@/components/MessageListItemMenu.vue'
|
||||||
|
|
||||||
@@ -39,6 +41,10 @@ const emit = defineEmits<{
|
|||||||
selectionFlag: [flag: string, value: boolean]
|
selectionFlag: [flag: string, value: boolean]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const mailSettingsStore = useMailSettingsStore()
|
||||||
|
const { messageListDensity } = storeToRefs(mailSettingsStore)
|
||||||
|
const densityConfig = computed(() => messageListDensityConfig[messageListDensity.value])
|
||||||
|
|
||||||
const longPressTimer = ref<number | null>(null)
|
const longPressTimer = ref<number | null>(null)
|
||||||
const longPressActivated = ref(false)
|
const longPressActivated = ref(false)
|
||||||
const suppressNextClick = ref(false)
|
const suppressNextClick = ref(false)
|
||||||
@@ -377,7 +383,7 @@ onBeforeUnmount(() => {
|
|||||||
<v-virtual-scroll
|
<v-virtual-scroll
|
||||||
v-else
|
v-else
|
||||||
:items="sortedMessages"
|
:items="sortedMessages"
|
||||||
:item-height="80"
|
:item-height="densityConfig.itemHeight"
|
||||||
class="message-virtual-scroll"
|
class="message-virtual-scroll"
|
||||||
>
|
>
|
||||||
<template v-slot:default="{ item: message }">
|
<template v-slot:default="{ item: message }">
|
||||||
@@ -397,7 +403,7 @@ onBeforeUnmount(() => {
|
|||||||
@touchend="handleTouchEnd"
|
@touchend="handleTouchEnd"
|
||||||
@touchcancel="handleTouchEnd"
|
@touchcancel="handleTouchEnd"
|
||||||
@touchmove="handleTouchMove"
|
@touchmove="handleTouchMove"
|
||||||
lines="three"
|
:lines="densityConfig.lines"
|
||||||
>
|
>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<div class="message-item-prepend">
|
<div class="message-item-prepend">
|
||||||
@@ -419,7 +425,7 @@ onBeforeUnmount(() => {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<v-list-item-title class="d-flex align-center">
|
<v-list-item-title class="d-flex align-center">
|
||||||
<span class="flex-grow-1 text-truncate">
|
<span class="message-sender text-truncate">
|
||||||
<RecipientDetails
|
<RecipientDetails
|
||||||
:address="message.properties.from"
|
:address="message.properties.from"
|
||||||
@clicked="handleRecipientClick(message)"
|
@clicked="handleRecipientClick(message)"
|
||||||
@@ -429,16 +435,22 @@ onBeforeUnmount(() => {
|
|||||||
</template>
|
</template>
|
||||||
</RecipientDetails>
|
</RecipientDetails>
|
||||||
</span>
|
</span>
|
||||||
<span class="text-caption text-medium-emphasis ml-2">
|
<span
|
||||||
|
v-if="!densityConfig.showSubjectLine"
|
||||||
|
class="message-inline-subject text-medium-emphasis text-truncate ml-2"
|
||||||
|
>
|
||||||
|
{{ message.properties.subject || '(No subject)' }}
|
||||||
|
</span>
|
||||||
|
<span class="message-date text-caption text-medium-emphasis ml-2">
|
||||||
{{ formatDate(timeStamp(message)) }}
|
{{ formatDate(timeStamp(message)) }}
|
||||||
</span>
|
</span>
|
||||||
</v-list-item-title>
|
</v-list-item-title>
|
||||||
|
|
||||||
<v-list-item-subtitle class="text-truncate">
|
<v-list-item-subtitle v-if="densityConfig.showSubjectLine" class="text-truncate">
|
||||||
{{ message.properties.subject || '(No subject)' }}
|
{{ message.properties.subject || '(No subject)' }}
|
||||||
</v-list-item-subtitle>
|
</v-list-item-subtitle>
|
||||||
|
|
||||||
<v-list-item-subtitle class="text-caption text-truncate">
|
<v-list-item-subtitle v-if="densityConfig.showThirdLine" class="text-caption text-truncate">
|
||||||
{{ '' }}
|
{{ '' }}
|
||||||
</v-list-item-subtitle>
|
</v-list-item-subtitle>
|
||||||
|
|
||||||
@@ -632,6 +644,21 @@ onBeforeUnmount(() => {
|
|||||||
background-color: rgba(var(--v-theme-primary), 0.14);
|
background-color: rgba(var(--v-theme-primary), 0.14);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-sender {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-inline-subject {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-date {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.message-person-link {
|
.message-person-link {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { folderViewModeOptions, useMailSettingsStore } from '@/stores/mailSettingsStore'
|
import {
|
||||||
|
folderViewModeOptions,
|
||||||
|
messageListDensityOptions,
|
||||||
|
useMailSettingsStore,
|
||||||
|
} from '@/stores/mailSettingsStore'
|
||||||
|
|
||||||
const mailSettingsStore = useMailSettingsStore()
|
const mailSettingsStore = useMailSettingsStore()
|
||||||
const { folderViewMode } = storeToRefs(mailSettingsStore)
|
const { folderViewMode, messageListDensity } = storeToRefs(mailSettingsStore)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -26,6 +30,22 @@ const { folderViewMode } = storeToRefs(mailSettingsStore)
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
|
||||||
|
<v-list-item>
|
||||||
|
<v-list-item-title>Message list density</v-list-item-title>
|
||||||
|
<v-list-item-subtitle>Control row height and how much detail is shown</v-list-item-subtitle>
|
||||||
|
<template #append>
|
||||||
|
<v-select
|
||||||
|
v-model="messageListDensity"
|
||||||
|
:items="messageListDensityOptions"
|
||||||
|
item-value="value"
|
||||||
|
item-title="title"
|
||||||
|
density="compact"
|
||||||
|
variant="outlined"
|
||||||
|
style="width: 150px"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -5,13 +5,34 @@ import { useUserStore } from '@KTXC'
|
|||||||
const MESSAGE_READ_ENABLED_KEY = 'mail.behaviour.messageReadEnabled'
|
const MESSAGE_READ_ENABLED_KEY = 'mail.behaviour.messageReadEnabled'
|
||||||
const MESSAGE_READ_DELAY_KEY = 'mail.behaviour.messageReadDelay'
|
const MESSAGE_READ_DELAY_KEY = 'mail.behaviour.messageReadDelay'
|
||||||
const FOLDER_VIEW_MODE_KEY = 'mail.folderViewMode'
|
const FOLDER_VIEW_MODE_KEY = 'mail.folderViewMode'
|
||||||
|
const MESSAGE_LIST_DENSITY_KEY = 'mail.messageListDensity'
|
||||||
|
|
||||||
const DEFAULT_MESSAGE_READ_ENABLED = false
|
const DEFAULT_MESSAGE_READ_ENABLED = false
|
||||||
const DEFAULT_MESSAGE_READ_DELAY = 5
|
const DEFAULT_MESSAGE_READ_DELAY = 5
|
||||||
const DEFAULT_FOLDER_VIEW_MODE = 'tree'
|
const DEFAULT_FOLDER_VIEW_MODE = 'tree'
|
||||||
|
const DEFAULT_MESSAGE_LIST_DENSITY = 'cozy'
|
||||||
|
|
||||||
export type FolderViewMode = 'tree' | 'page'
|
export type FolderViewMode = 'tree' | 'page'
|
||||||
|
|
||||||
|
export type MessageListDensity = 'compact' | 'cozy' | 'comfortable'
|
||||||
|
|
||||||
|
export const messageListDensityOptions = [
|
||||||
|
{ value: 'compact', title: 'Compact' },
|
||||||
|
{ value: 'cozy', title: 'Cozy' },
|
||||||
|
{ value: 'comfortable', title: 'Comfortable' },
|
||||||
|
]
|
||||||
|
|
||||||
|
export const messageListDensityConfig: Record<MessageListDensity, {
|
||||||
|
itemHeight: number
|
||||||
|
lines: 'one' | 'two' | 'three'
|
||||||
|
showSubjectLine: boolean
|
||||||
|
showThirdLine: boolean
|
||||||
|
}> = {
|
||||||
|
compact: { itemHeight: 56, lines: 'one', showSubjectLine: false, showThirdLine: false },
|
||||||
|
cozy: { itemHeight: 72, lines: 'two', showSubjectLine: true, showThirdLine: false },
|
||||||
|
comfortable: { itemHeight: 96, lines: 'three', showSubjectLine: true, showThirdLine: true },
|
||||||
|
}
|
||||||
|
|
||||||
export const messageReadDelayOptions = [
|
export const messageReadDelayOptions = [
|
||||||
{ value: 2, title: '2 seconds' },
|
{ value: 2, title: '2 seconds' },
|
||||||
{ value: 5, title: '5 seconds' },
|
{ value: 5, title: '5 seconds' },
|
||||||
@@ -42,6 +63,10 @@ function normalizeFolderViewMode(value: unknown, fallback: FolderViewMode): Fold
|
|||||||
return value === 'tree' || value === 'page' ? value : fallback
|
return value === 'tree' || value === 'page' ? value : fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeMessageListDensity(value: unknown, fallback: MessageListDensity): MessageListDensity {
|
||||||
|
return value === 'compact' || value === 'cozy' || value === 'comfortable' ? value : fallback
|
||||||
|
}
|
||||||
|
|
||||||
export const useMailSettingsStore = defineStore('mailSettingsStore', () => {
|
export const useMailSettingsStore = defineStore('mailSettingsStore', () => {
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
@@ -66,8 +91,17 @@ export const useMailSettingsStore = defineStore('mailSettingsStore', () => {
|
|||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const messageListDensity = computed({
|
||||||
|
get: () => normalizeMessageListDensity(userStore.getSetting(MESSAGE_LIST_DENSITY_KEY), DEFAULT_MESSAGE_LIST_DENSITY),
|
||||||
|
set: (value: MessageListDensity) => userStore.setSetting(
|
||||||
|
MESSAGE_LIST_DENSITY_KEY,
|
||||||
|
normalizeMessageListDensity(value, DEFAULT_MESSAGE_LIST_DENSITY),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
folderViewMode,
|
folderViewMode,
|
||||||
|
messageListDensity,
|
||||||
messageReadEnabled,
|
messageReadEnabled,
|
||||||
messageReadDelay,
|
messageReadDelay,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user