UPSTREAM BASELINE: nextcloud/spreed v22.0.12 (без изменений)
Type checking / changes (push) Has been cancelled
Type checking / test (push) Has been cancelled
Type checking / typescript-summary (push) Has been cancelled
Node tests / changes (push) Has been cancelled
Node tests / test (push) Has been cancelled
Node tests / test-summary (push) Has been cancelled
Type checking / changes (push) Has been cancelled
Type checking / test (push) Has been cancelled
Type checking / typescript-summary (push) Has been cancelled
Node tests / changes (push) Has been cancelled
Node tests / test (push) Has been cancelled
Node tests / test-summary (push) Has been cancelled
Источник: https://github.com/nextcloud/spreed/archive/refs/tags/v22.0.12.tar.gz С этого коммита ветка официального Nextcloud Talk отрезана (решение владельца 2026-07-06). Все дальнейшие изменения — только наши; версии релизов: 22.0.12-f7.N.
This commit is contained in:
@@ -0,0 +1,579 @@
|
||||
<!--
|
||||
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
<script lang="ts" setup>
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
import { emit } from '@nextcloud/event-bus'
|
||||
import { isRTL, t } from '@nextcloud/l10n'
|
||||
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 NcInputField from '@nextcloud/vue/components/NcInputField'
|
||||
import NcPopover from '@nextcloud/vue/components/NcPopover'
|
||||
import IconArrowLeft from 'vue-material-design-icons/ArrowLeft.vue'
|
||||
import IconArrowRight from 'vue-material-design-icons/ArrowRight.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'
|
||||
import IconPhoneOutline from 'vue-material-design-icons/PhoneOutline.vue'
|
||||
import IconPlus from 'vue-material-design-icons/Plus.vue'
|
||||
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, localCapabilities } from '../../services/CapabilitiesManager.ts'
|
||||
import { EventBus } from '../../services/EventBus.ts'
|
||||
import { useActorStore } from '../../stores/actor.ts'
|
||||
import { useDashboardStore } from '../../stores/dashboard.ts'
|
||||
import { hasUnreadMentions } from '../../utils/conversation.ts'
|
||||
import { copyConversationLinkToClipboard } from '../../utils/handleUrl.ts'
|
||||
|
||||
const supportsUpcomingReminders = hasTalkFeature('local', 'upcoming-reminders')
|
||||
const canModerateSipDialOut = hasTalkFeature('local', 'sip-support-dialout')
|
||||
&& getTalkConfig('local', 'call', 'sip-enabled')
|
||||
&& getTalkConfig('local', 'call', 'sip-dialout-enabled')
|
||||
&& getTalkConfig('local', 'call', 'can-enable-sip')
|
||||
const isCallEnabled = getTalkConfig('local', 'call', 'enabled')
|
||||
const canStartConversations = getTalkConfig('local', 'conversations', 'can-create')
|
||||
const isCalendarEnabled = localCapabilities.calendar?.webui ?? false
|
||||
const isDirectionRTL = isRTL()
|
||||
const isMobile = useIsMobile()
|
||||
const isSmallMobile = useIsSmallMobile()
|
||||
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const dashboardStore = useDashboardStore()
|
||||
const actorStore = useActorStore()
|
||||
const forwardScrollable = ref(false)
|
||||
const backwardScrollable = ref(false)
|
||||
const eventCardsWrapper = ref<HTMLDivElement | null>(null)
|
||||
const eventRooms = computed(() => dashboardStore.eventRooms || [])
|
||||
const upcomingReminders = computed(() => dashboardStore.upcomingReminders || [])
|
||||
const eventsInitialised = computed(() => dashboardStore.eventRoomsInitialised)
|
||||
const remindersInitialised = computed(() => dashboardStore.upcomingRemindersInitialised)
|
||||
const conversationName = ref('')
|
||||
let actualizeDataInterval: ReturnType<typeof setInterval> | null = null
|
||||
|
||||
// Data fetching handlers
|
||||
|
||||
/**
|
||||
* Fetches all necessary data for the dashboard.
|
||||
*/
|
||||
async function actualizeData() {
|
||||
await Promise.all([
|
||||
dashboardStore.fetchDashboardEventRooms(),
|
||||
dashboardStore.fetchUpcomingReminders(),
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the data fetching interval and fetches initial data.
|
||||
*/
|
||||
function initActualizeData() {
|
||||
if (actualizeDataInterval) {
|
||||
clearInterval(actualizeDataInterval)
|
||||
}
|
||||
actualizeData()
|
||||
actualizeDataInterval = setInterval(actualizeData, 300_000)
|
||||
}
|
||||
|
||||
initActualizeData()
|
||||
EventBus.on('refresh-talk-dashboard', initActualizeData)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (actualizeDataInterval) {
|
||||
clearInterval(actualizeDataInterval)
|
||||
}
|
||||
|
||||
if (eventCardsWrapper?.value) {
|
||||
resizeObserver.disconnect()
|
||||
}
|
||||
|
||||
EventBus.off('refresh-talk-dashboard', initActualizeData)
|
||||
})
|
||||
|
||||
watch(eventCardsWrapper, (newValue) => {
|
||||
if (newValue) {
|
||||
resizeObserver.observe(newValue)
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Updates the scrollable flags based on the current scroll position.
|
||||
*/
|
||||
async function updateScrollableFlags() {
|
||||
await nextTick()
|
||||
if (eventCardsWrapper.value) {
|
||||
const { scrollLeft, scrollWidth, clientWidth } = eventCardsWrapper.value
|
||||
backwardScrollable.value = isDirectionRTL ? scrollLeft < 0 : scrollLeft > 0
|
||||
forwardScrollable.value = (isDirectionRTL ? -1 : 1) * scrollLeft + clientWidth < scrollWidth - 10 // 10px tolerance
|
||||
}
|
||||
}
|
||||
|
||||
// Use ResizeObserver to detect size changes
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
updateScrollableFlags()
|
||||
})
|
||||
|
||||
const conversationsInitialised = computed(() => store.getters.conversationsInitialised)
|
||||
const filteredConversations = computed(() => store.getters.conversationsList.filter(hasUnreadMentions))
|
||||
|
||||
/**
|
||||
* Creates a new group conversation and navigates to the conversation page.
|
||||
*/
|
||||
async function startMeeting() {
|
||||
try {
|
||||
const conversation = await store.dispatch('createGroupConversation', {
|
||||
// TRANSLATORS: Section header for meeting-related settings; also a static name fallback for instant meeting conversation
|
||||
roomName: conversationName.value || t('spreed', 'Meeting'),
|
||||
roomType: CONVERSATION.TYPE.PUBLIC,
|
||||
objectType: CONVERSATION.OBJECT_TYPE.INSTANT_MEETING,
|
||||
objectId: Math.floor(Date.now() / 1000).toString(),
|
||||
})
|
||||
await copyConversationLinkToClipboard(conversation.token)
|
||||
await router.push({
|
||||
name: 'conversation',
|
||||
params: { token: conversation.token },
|
||||
hash: '#direct-call',
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error creating conversation:', error)
|
||||
showError(t('spreed', 'Error while creating the conversation'))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls the event cards wrapper in the specified direction.
|
||||
*
|
||||
* @param payload
|
||||
* @param payload.direction - The direction to scroll ('backward' or 'forward').
|
||||
*/
|
||||
function scrollEventCards({ direction }: { direction: 'backward' | 'forward' }) {
|
||||
const scrollDirection = (direction === 'backward' ? -1 : 1) * (isDirectionRTL ? -1 : 1)
|
||||
if (eventCardsWrapper.value) {
|
||||
const ITEM_WIDTH = 300 + 8 // 300px width + 8px gap
|
||||
let scrollAmount = 0
|
||||
const visibleItems = Math.floor(eventCardsWrapper.value.clientWidth / ITEM_WIDTH)
|
||||
if (visibleItems === 0) {
|
||||
scrollAmount = eventCardsWrapper.value.clientWidth * scrollDirection
|
||||
} else {
|
||||
scrollAmount = visibleItems * ITEM_WIDTH * scrollDirection
|
||||
// Arrow buttons are 34px wide
|
||||
if (!backwardScrollable.value && scrollDirection === 1) {
|
||||
scrollAmount -= 34
|
||||
} else if (!forwardScrollable.value && scrollDirection === -1) {
|
||||
scrollAmount += 34
|
||||
}
|
||||
}
|
||||
|
||||
eventCardsWrapper.value.scrollBy({
|
||||
left: scrollAmount,
|
||||
behavior: 'smooth',
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="talk-dashboard-wrapper"
|
||||
:class="{
|
||||
'talk-dashboard-wrapper--mobile': isMobile,
|
||||
'talk-dashboard-wrapper--small-mobile': isSmallMobile,
|
||||
}">
|
||||
<div class="talk-dashboard__menu">
|
||||
<h2 class="talk-dashboard__header">
|
||||
{{ t('spreed', 'Hello, {displayName}', { displayName: actorStore.displayName }, { escape: false }) }}
|
||||
</h2>
|
||||
<div class="talk-dashboard__actions">
|
||||
<NcPopover
|
||||
v-if="canStartConversations"
|
||||
popupRole="dialog">
|
||||
<template #trigger>
|
||||
<NcButton
|
||||
v-if="isCallEnabled"
|
||||
variant="primary">
|
||||
<template #icon>
|
||||
<IconVideoOutline />
|
||||
</template>
|
||||
{{ t('spreed', 'Start meeting now') }}
|
||||
</NcButton>
|
||||
</template>
|
||||
<div
|
||||
role="dialog"
|
||||
aria-labelledby="instant_meeting_dialog"
|
||||
class="instant-meeting__dialog"
|
||||
aria-modal="true">
|
||||
<strong>{{ t('spreed', 'Give your meeting a title') }}</strong>
|
||||
<NcInputField
|
||||
id="room-name"
|
||||
v-model="conversationName"
|
||||
:placeholder="t('spreed', 'Meeting')" />
|
||||
<NcButton
|
||||
variant="primary"
|
||||
@click="startMeeting">
|
||||
{{ t('spreed', 'Create and copy link') }}
|
||||
</NcButton>
|
||||
</div>
|
||||
</NcPopover>
|
||||
<NcButton
|
||||
v-if="canStartConversations"
|
||||
@click="EventBus.emit('new-conversation-dialog:show')">
|
||||
<template #icon>
|
||||
<IconPlus :size="20" />
|
||||
</template>
|
||||
{{ t('spreed', 'Create a new conversation') }}
|
||||
</NcButton>
|
||||
|
||||
<NcButton @click="EventBus.emit('open-conversations-list:show')">
|
||||
<template #icon>
|
||||
<IconList :size="20" />
|
||||
</template>
|
||||
{{ t('spreed', 'Join open conversations') }}
|
||||
</NcButton>
|
||||
|
||||
<NcButton
|
||||
v-if="isCallEnabled && canModerateSipDialOut"
|
||||
@click="EventBus.emit('call-phone-dialog:show')">
|
||||
<template #icon>
|
||||
<IconPhoneOutline :size="20" />
|
||||
</template>
|
||||
{{ t('spreed', 'Call a phone number') }}
|
||||
</NcButton>
|
||||
<NcButton
|
||||
variant="secondary"
|
||||
@click="emit('talk:media-settings:show', 'device-check')">
|
||||
<template #icon>
|
||||
<IconMicrophoneOutline :size="20" />
|
||||
</template>
|
||||
{{ t('spreed', 'Check devices') }}
|
||||
</NcButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="talk-dashboard__items">
|
||||
<div class="event-section">
|
||||
<template v-if="eventsInitialised && eventRooms.length > 0">
|
||||
<h3 class="title">
|
||||
{{ t('spreed', 'Upcoming meetings') }}
|
||||
</h3>
|
||||
<div
|
||||
class="talk-dashboard__event-cards-wrapper"
|
||||
:class="{ 'forward-scrollable': forwardScrollable, 'backward-scrollable': backwardScrollable }">
|
||||
<div
|
||||
ref="eventCardsWrapper"
|
||||
class="talk-dashboard__event-cards"
|
||||
@scroll.passive="updateScrollableFlags">
|
||||
<EventCard
|
||||
v-for="eventRoom in eventRooms"
|
||||
:key="eventRoom.eventLink"
|
||||
:eventRoom="eventRoom"
|
||||
class="talk-dashboard__event-card" />
|
||||
</div>
|
||||
<div class="talk-dashboard__event-cards__scroll-indicator">
|
||||
<NcButton
|
||||
v-show="backwardScrollable"
|
||||
class="button-slide backward"
|
||||
variant="tertiary"
|
||||
:title="t('spreed', 'Scroll backward')"
|
||||
:aria-label="t('spreed', 'Scroll backward')"
|
||||
@click="scrollEventCards({ direction: 'backward' })">
|
||||
<template #icon>
|
||||
<IconArrowLeft class="bidirectional-icon" />
|
||||
</template>
|
||||
</NcButton>
|
||||
<NcButton
|
||||
v-show="forwardScrollable"
|
||||
class="button-slide forward"
|
||||
variant="tertiary"
|
||||
:title="t('spreed', 'Scroll forward')"
|
||||
:aria-label="t('spreed', 'Scroll forward')"
|
||||
@click="scrollEventCards({ direction: 'forward' })">
|
||||
<template #icon>
|
||||
<IconArrowRight class="bidirectional-icon" />
|
||||
</template>
|
||||
</NcButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<LoadingPlaceholder
|
||||
v-else-if="!eventsInitialised"
|
||||
type="event-cards" />
|
||||
<DashboardSection
|
||||
v-else
|
||||
class="event-section--empty"
|
||||
wide
|
||||
:title="t('spreed', 'Schedule meetings')"
|
||||
:subtitle="t('spreed', 'You don\'t have any upcoming meetings')"
|
||||
:description="t('spreed', 'Schedule a meeting from your calendar. A Talk conversation needs to be set as location to show up here')">
|
||||
<template #image>
|
||||
<img :src="imagePath('spreed', 'dashboard/meetings.png')">
|
||||
</template>
|
||||
<template #action>
|
||||
<NcButton
|
||||
v-if="isCalendarEnabled"
|
||||
variant="secondary"
|
||||
:href="generateUrl('apps/calendar')"
|
||||
target="_blank">
|
||||
<template #icon>
|
||||
<IconCalendarBlankOutline :size="20" />
|
||||
</template>
|
||||
{{ t('spreed', 'Open calendar') }}
|
||||
</NcButton>
|
||||
</template>
|
||||
</DashboardSection>
|
||||
</div>
|
||||
<div class="talk-dashboard__chats">
|
||||
<div class="talk-dashboard__unread-mentions">
|
||||
<DashboardSection
|
||||
v-if="filteredConversations.length > 0 || !conversationsInitialised"
|
||||
:title="t('spreed', 'Unread mentions')">
|
||||
<template #list>
|
||||
<ConversationsListVirtual
|
||||
class="talk-dashboard__conversations-list"
|
||||
:conversations="filteredConversations"
|
||||
:loading="!conversationsInitialised" />
|
||||
</template>
|
||||
</DashboardSection>
|
||||
<DashboardSection
|
||||
v-else
|
||||
:title="t('spreed', 'Unread mentions')"
|
||||
:description="t('spreed', 'Messages where you were mentioned will show up here. You can mention people by typing @ followed by their name')">
|
||||
<template #image>
|
||||
<img :src="imagePath('spreed', 'dashboard/mentions.png')">
|
||||
</template>
|
||||
</DashboardSection>
|
||||
</div>
|
||||
<div
|
||||
v-if="supportsUpcomingReminders"
|
||||
class="talk-dashboard__upcoming-reminders">
|
||||
<DashboardSection
|
||||
v-if="upcomingReminders.length > 0 || !remindersInitialised"
|
||||
:title="t('spreed', 'Upcoming reminders')">
|
||||
<template #list>
|
||||
<ul v-if="remindersInitialised" class="upcoming-reminders-list">
|
||||
<SearchMessageItem
|
||||
v-for="reminder in upcomingReminders"
|
||||
:key="reminder.messageId"
|
||||
:messageId="reminder.messageId"
|
||||
:title="reminder.actorDisplayName"
|
||||
:subline="reminder.message"
|
||||
:messageParameters="reminder.messageParameters"
|
||||
:token="reminder.roomToken"
|
||||
:to="{
|
||||
name: 'conversation',
|
||||
params: { token: reminder.roomToken },
|
||||
hash: `#message_${reminder.messageId}`,
|
||||
}"
|
||||
:actorId="reminder.actorId"
|
||||
:actorType="reminder.actorType"
|
||||
:timestamp="reminder.reminderTimestamp"
|
||||
isReminder />
|
||||
</ul>
|
||||
<LoadingPlaceholder
|
||||
v-else
|
||||
class="upcoming-reminders__loading-placeholder"
|
||||
type="conversations" />
|
||||
</template>
|
||||
</DashboardSection>
|
||||
<DashboardSection
|
||||
v-else
|
||||
:title="t('spreed', 'Message reminders')"
|
||||
:description="t('spreed', 'Set a reminder on a message to be notified')">
|
||||
<template #image>
|
||||
<img :src="imagePath('spreed', 'dashboard/reminders.png')">
|
||||
</template>
|
||||
</DashboardSection>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '../../assets/variables' as *;
|
||||
|
||||
.talk-dashboard-wrapper {
|
||||
padding: calc(var(--default-grid-baseline) * 2) calc(var(--default-grid-baseline) * 3);
|
||||
width: min(100%, 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) * 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.talk-dashboard__menu {
|
||||
margin-bottom: calc(var(--default-grid-baseline) * 4);
|
||||
}
|
||||
|
||||
.talk-dashboard__header {
|
||||
font-size: 21px; // NcDialog header font size
|
||||
font-weight: bold;
|
||||
margin: 0 auto calc(var(--default-grid-baseline) * 2);
|
||||
padding-inline-start: calc(var(--default-clickable-area) + var(--default-grid-baseline)); // navigation button
|
||||
}
|
||||
|
||||
.talk-dashboard__actions {
|
||||
display: flex;
|
||||
gap: calc(var(--default-grid-baseline) * 3);
|
||||
padding-block: var(--default-grid-baseline);
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
|
||||
:deep(.button-vue),
|
||||
:deep(.v-popper--theme-dropdown) {
|
||||
height: var(--header-menu-item-height);
|
||||
border-radius: var(--border-radius-large);
|
||||
}
|
||||
|
||||
: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;
|
||||
gap: calc(var(--default-grid-baseline) * 2);
|
||||
margin-block: var(--default-grid-baseline);
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
border-radius: var(--border-radius-large);
|
||||
}
|
||||
|
||||
.talk-dashboard__event-cards-wrapper {
|
||||
position: relative;
|
||||
margin-bottom: calc(var(--default-grid-baseline) * 2);
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: var(--default-clickable-area);
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.button-slide {
|
||||
position: absolute !important;
|
||||
display: flex;
|
||||
top: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
margin: 0 !important;
|
||||
z-index: 3;
|
||||
justify-content: left;
|
||||
background: var(--color-main-background);
|
||||
border-radius: var(--border-radius-large);
|
||||
|
||||
&.backward {
|
||||
inset-inline-start: 0;
|
||||
}
|
||||
|
||||
&.forward {
|
||||
inset-inline-end: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.talk-dashboard__calendar-button {
|
||||
position: absolute !important;
|
||||
bottom: calc(var(--default-grid-baseline) * 2);
|
||||
inset-inline-start: calc(var(--default-grid-baseline) * 2);
|
||||
}
|
||||
|
||||
.talk-dashboard__items {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
min-width: 0;
|
||||
flex-grow: 3;
|
||||
}
|
||||
|
||||
.talk-dashboard__chats {
|
||||
display: grid;
|
||||
gap: calc(var(--default-grid-baseline) * 8);
|
||||
grid-template-columns: 1fr 1fr;
|
||||
flex-grow: 1;
|
||||
|
||||
&> div {
|
||||
max-height: 320px;
|
||||
}
|
||||
}
|
||||
|
||||
.upcoming-reminders {
|
||||
&-list {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
&__loading-placeholder {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.talk-dashboard__conversations-list {
|
||||
flex-grow: 1;
|
||||
margin-block: var(--default-grid-baseline);
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
margin-block: 0 calc(var(--default-grid-baseline) * 2);
|
||||
}
|
||||
|
||||
.instant-meeting__dialog {
|
||||
padding: calc(var(--default-grid-baseline) * 2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--default-grid-baseline) ;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
// Override NcButton styles for narrow screen size
|
||||
@media screen and (max-width: $breakpoint-mobile-small) {
|
||||
.talk-dashboard__actions {
|
||||
:deep(.button-vue),
|
||||
& > div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.button-vue) {
|
||||
padding-inline-end: calc(var(--default-grid-baseline) * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user