diff --git a/REUSE.toml b/REUSE.toml index 35feb1c0332..302c6380c0b 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -71,6 +71,12 @@ precedence = "aggregate" SPDX-FileCopyrightText = "2018-2025 Google LLC" SPDX-License-Identifier = "Apache-2.0" +[[annotations]] +path = "img/dashboard/**.png" +precedence = "aggregate" +SPDX-FileCopyrightText = "Nextcloud GmbH " +SPDX-License-Identifier = "LicenseRef-NextcloudTrademarks" + [[annotations]] path = "img/emojis/**.gif" precedence = "aggregate" diff --git a/img/dashboard/meetings.png b/img/dashboard/meetings.png new file mode 100644 index 00000000000..5d5f9342c99 Binary files /dev/null and b/img/dashboard/meetings.png differ diff --git a/img/dashboard/mentions.png b/img/dashboard/mentions.png new file mode 100644 index 00000000000..73a642557bf Binary files /dev/null and b/img/dashboard/mentions.png differ diff --git a/img/dashboard/reminders.png b/img/dashboard/reminders.png new file mode 100644 index 00000000000..3bf94746994 Binary files /dev/null and b/img/dashboard/reminders.png differ diff --git a/img/dashboard/welcome.png b/img/dashboard/welcome.png new file mode 100644 index 00000000000..8a056145fdb Binary files /dev/null and b/img/dashboard/welcome.png differ diff --git a/src/components/Dashboard/DashboardSection.vue b/src/components/Dashboard/DashboardSection.vue new file mode 100644 index 00000000000..e522974cf7f --- /dev/null +++ b/src/components/Dashboard/DashboardSection.vue @@ -0,0 +1,117 @@ + + + + + + + + + + + + {{ title }} + + {{ subtitle }} + {{ description }} + + + + + + + + + diff --git a/src/components/Dashboard/EventCard.vue b/src/components/Dashboard/EventCard.vue index 735cb8a437b..a8b293d90e8 100644 --- a/src/components/Dashboard/EventCard.vue +++ b/src/components/Dashboard/EventCard.vue @@ -246,7 +246,7 @@ function handleJoin({ call }: { call: boolean }) { flex-direction: column; flex: 0 0 100%; max-width: 300px; - border: 3px solid var(--color-border); + border: 2px solid var(--color-border); padding: calc(var(--default-grid-baseline) * 2); border-radius: var(--border-radius-large); background-color: var(--color-main-background); @@ -255,7 +255,7 @@ function handleJoin({ call }: { call: boolean }) { background-color: var(--color-primary-light); &:not(.event-card--in-call) { - border-color: var(--color-primary-light) !important; + border-color: var(--color-primary-element-light-hover) !important; } } diff --git a/src/components/Dashboard/TalkDashboard.vue b/src/components/Dashboard/TalkDashboard.vue index 40c48c02f2e..233ec226695 100644 --- a/src/components/Dashboard/TalkDashboard.vue +++ b/src/components/Dashboard/TalkDashboard.vue @@ -6,18 +6,16 @@ import { showError } from '@nextcloud/dialogs' import { emit } from '@nextcloud/event-bus' import { isRTL, t } from '@nextcloud/l10n' -import { generateUrl } from '@nextcloud/router' -import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue' +import { generateUrl, imagePath } from '@nextcloud/router' +import { useIsMobile, useIsSmallMobile } from '@nextcloud/vue/composables/useIsMobile' +import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue' import { useRouter } from 'vue-router' import { useStore } from 'vuex' import NcButton from '@nextcloud/vue/components/NcButton' -import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent' import NcInputField from '@nextcloud/vue/components/NcInputField' import NcPopover from '@nextcloud/vue/components/NcPopover' -import IconAlarm from 'vue-material-design-icons/Alarm.vue' import IconArrowLeft from 'vue-material-design-icons/ArrowLeft.vue' import IconArrowRight from 'vue-material-design-icons/ArrowRight.vue' -import IconAt from 'vue-material-design-icons/At.vue' import IconCalendarBlankOutline from 'vue-material-design-icons/CalendarBlankOutline.vue' import IconList from 'vue-material-design-icons/FormatListBulleted.vue' import IconMicrophoneOutline from 'vue-material-design-icons/MicrophoneOutline.vue' @@ -27,6 +25,7 @@ import IconVideoOutline from 'vue-material-design-icons/VideoOutline.vue' import ConversationsListVirtual from '../LeftSidebar/ConversationsList/ConversationsListVirtual.vue' import SearchMessageItem from '../RightSidebar/SearchMessages/SearchMessageItem.vue' import LoadingPlaceholder from '../UIShared/LoadingPlaceholder.vue' +import DashboardSection from './DashboardSection.vue' import EventCard from './EventCard.vue' import { CONVERSATION } from '../../constants.ts' import { getTalkConfig, hasTalkFeature } from '../../services/CapabilitiesManager.ts' @@ -43,6 +42,8 @@ const canModerateSipDialOut = hasTalkFeature('local', 'sip-support-dialout') && getTalkConfig('local', 'call', 'can-enable-sip') const canStartConversations = getTalkConfig('local', 'conversations', 'can-create') const isDirectionRTL = isRTL() +const isMobile = useIsMobile() +const isSmallMobile = useIsSmallMobile() const store = useStore() const router = useRouter() @@ -177,171 +178,190 @@ function scrollEventCards({ direction }: { direction: 'backward' | 'forward' }) - - - {{ t('spreed', 'Hello, {displayName}', { displayName: actorStore.displayName }, { escape: false }) }} - - - - - - - - - {{ t('spreed', 'Start meeting now') }} - - - - {{ t('spreed', 'Give your meeting a title') }} - - - {{ t('spreed', 'Create and copy link') }} - - - - - - - - {{ t('spreed', 'Create a new conversation') }} - + + + + {{ t('spreed', 'Hello, {displayName}', { displayName: actorStore.displayName }, { escape: false }) }} + + + + + + + + + {{ t('spreed', 'Start meeting now') }} + + + + {{ t('spreed', 'Give your meeting a title') }} + + + {{ t('spreed', 'Create and copy link') }} + + + + + + + + {{ t('spreed', 'Create a new conversation') }} + - - - - - {{ t('spreed', 'Join open conversations') }} - + + + + + {{ t('spreed', 'Join open conversations') }} + - - - - - {{ t('spreed', 'Call a phone number') }} - - - - - - {{ t('spreed', 'Check devices') }} - - - - {{ t('spreed', 'Upcoming meetings') }} - - - - - - - + - + + {{ t('spreed', 'Call a phone number') }} - + - + + {{ t('spreed', 'Check devices') }} - - - {{ t('spreed', 'You have no upcoming meetings') }} - - {{ t('spreed', 'Schedule a meeting with a colleague from your calendar') }} - - - - + + + + + {{ t('spreed', 'Upcoming meetings') }} + + + + + + + + + + + + + + + + + + - {{ t('spreed', 'Open calendar') }} - - - - - - {{ t('spreed', 'Unread mentions') }} - - - - - + + + + + + + + + + + {{ t('spreed', 'Open calendar') }} + - + - - - {{ t('spreed', 'Upcoming reminders') }} - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - @@ -351,21 +371,38 @@ function scrollEventCards({ direction }: { direction: 'backward' | 'forward' }) @import '../../assets/variables'; .talk-dashboard-wrapper { - --title-height: calc(var(--default-clickable-area) + var(--default-grid-baseline) * 3); // '.title' height - --section-width: 300px; - --section-height: 300px; - --content-height: calc(100% - var(--title-height)); - padding: 0 calc(var(--default-grid-baseline) * 3); - max-width: calc($messages-list-max-width + 400px); // FIXME: to change to a readable value + padding: calc(var(--default-grid-baseline) * 2) calc(var(--default-grid-baseline) * 3); + width: calc(100vw - 300px - var(--body-container-margin) * 2); // 300px for the left sidebar and body container margins margin: 0 auto; + display: flex; + flex-direction: column; + height: 100%; + max-height: 800px; + max-width: 1200px; + + &--mobile { + width: 100%; + } + + &--small-mobile { + width: 100%; + height: auto; + + .talk-dashboard__chats { + grid-template-columns: 1fr; + gap: calc(var(--default-grid-baseline) * 6); + } + } +} + +.talk-dashboard__menu { + margin-bottom: calc(var(--default-grid-baseline) * 5); } .talk-dashboard__header { font-size: 21px; // NcDialog header font size font-weight: bold; - height: 51px; // top bar height - line-height: 51px; - margin: 0 auto; + margin: 0 auto calc(var(--default-grid-baseline) * 2); padding-inline-start: calc(var(--default-clickable-area) + var(--default-grid-baseline)); // navigation button } @@ -374,13 +411,29 @@ function scrollEventCards({ direction }: { direction: 'backward' | 'forward' }) gap: calc(var(--default-grid-baseline) * 3); padding-block: var(--default-grid-baseline); flex-wrap: wrap; + justify-content: space-evenly; - :deep(.button-vue) { + :deep(.button-vue), + :deep(.v-popper--theme-dropdown) { height: var(--header-menu-item-height); + border-radius: var(--border-radius-large); + flex: 1; + width: 100%; + } + + :deep(.button-vue) { padding-inline: calc(var(--default-grid-baseline) * 2) calc(var(--default-grid-baseline) * 4); } } +.event-section { + margin-block-end: calc(var(--default-grid-baseline) * 6); + + &--empty { + height: 225px; + } +} + .talk-dashboard__event-cards { display: flex; flex-wrap: nowrap; @@ -434,92 +487,52 @@ function scrollEventCards({ direction }: { direction: 'backward' | 'forward' }) inset-inline-start: calc(var(--default-grid-baseline) * 2); } -.talk-dashboard__chats { +.talk-dashboard__items { display: flex; - gap: calc(var(--default-grid-baseline) * 2); - padding-block-end: calc(var(--default-grid-baseline) * 2); - flex-wrap: wrap; -} - -.talk-dashboard__unread-mentions { - height: var(--section-height); - width: var(--section-width); - flex-shrink: 0; + flex-direction: column; + justify-content: space-around; + min-width: 0; + flex-grow: 3; } -.talk-dashboard__upcoming-reminders { - height: var(--section-height); - width: var(--section-width); - flex-shrink: 0; +.talk-dashboard__chats { + display: grid; + gap: calc(var(--default-grid-baseline) * 8); + grid-template-columns: 1fr 1fr; + flex-grow: 1; - &-list { - overflow-y: auto; - height: var(--content-height); + &> div { + max-height: 360px; } } .upcoming-reminders { &-list { overflow-y: auto; - height: var(--content-height); } &__loading-placeholder { overflow: hidden; - height: var(--content-height); } } -.talk-dashboard__empty-content { - border-radius: var(--border-radius-large); - padding: calc(var(--default-grid-baseline) * 2); - margin: var(--default-grid-baseline) 0; - border: 3px solid var(--color-border); - height: var(--content-height); -} - -.talk-dashboard__empty-event-card { - display: flex; - flex-direction: column; - position: relative; - height: 225px; - width: var(--section-width); - border-radius: var(--border-radius-large); - border: 3px solid var(--color-border); - padding: calc(var(--default-grid-baseline) * 2); - margin-bottom: calc(var(--default-grid-baseline) * 2); -} - .talk-dashboard__conversations-list { margin: var(--default-grid-baseline) 0; - height: var(--content-height); + height: 225px; line-height: 20px; } .title { - font-weight: bold; - font-size: inherit; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - display: block; - height: var(--default-clickable-area); - margin-block: calc(var(--default-grid-baseline) * 2) var(--default-grid-baseline); - margin-inline: var(--default-grid-baseline); -} - -.secondary_text { - color: var(--color-text-maxcontrast); - font-size: var(--font-size-small); - overflow: hidden; - text-overflow: ellipsis; + font-size: 1.25rem; + font-weight: bold; + margin-block: 0 calc(var(--default-grid-baseline) * 2); } .instant-meeting__dialog { - padding: 8px; + padding: calc(var(--default-grid-baseline) * 2); display: flex; flex-direction: column; - gap: 4px; + gap: var(--default-grid-baseline) ; align-items: center; } @@ -528,7 +541,11 @@ function scrollEventCards({ direction }: { direction: 'backward' | 'forward' }) .talk-dashboard__actions { :deep(.button-vue), :deep(.v-popper--theme-dropdown) { - width: 100%; + flex: initial; + } + + :deep(.button-vue) { + padding-inline-end: calc(var(--default-grid-baseline) * 2); } } }