Skip to content
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
73 changes: 73 additions & 0 deletions src/components/TopBar/TopBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,22 @@
</div>
</a>

<a v-if="showUpcomingEvent"
class="upcoming-event"
:href="nextEvent.calendarAppUrl"
:title="t('spreed', 'Open Calendar')"
target="_blank">
<div class="icon">
<CalendarBlank :size="20" />
</div>
<div class="event-info">
<p class="event-info__header">
{{ t('spreed', 'Next call') }}
</p>
<p> {{ eventInfo }} </p>
</div>
</a>

<!-- Call time -->
<CallTime v-if="isInCall"
:start="conversation.callStartTime" />
Expand Down Expand Up @@ -93,11 +109,14 @@

<script>
import AccountMultiple from 'vue-material-design-icons/AccountMultiple.vue'
import CalendarBlank from 'vue-material-design-icons/CalendarBlank.vue'

import { emit } from '@nextcloud/event-bus'
import { t, n } from '@nextcloud/l10n'
import moment from '@nextcloud/moment'

import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import { useIsMobile } from '@nextcloud/vue/dist/Composables/useIsMobile.js'
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip.js'
import richEditor from '@nextcloud/vue/dist/Mixins/richEditor.js'

Expand All @@ -113,6 +132,7 @@ import { useGetParticipants } from '../../composables/useGetParticipants.js'
import { CONVERSATION } from '../../constants.js'
import BrowserStorage from '../../services/BrowserStorage.js'
import { getTalkConfig } from '../../services/CapabilitiesManager.ts'
import { useChatExtrasStore } from '../../stores/chatExtras.js'
import { getStatusMessage } from '../../utils/userStatus.js'
import { localCallParticipantModel, localMediaModel } from '../../utils/webrtc/index.js'

Expand All @@ -135,6 +155,7 @@ export default {
ReactionMenu,
// Icons
AccountMultiple,
CalendarBlank,
},

mixins: [richEditor],
Expand Down Expand Up @@ -162,6 +183,8 @@ export default {
localCallParticipantModel,
localMediaModel,
iconSize,
chatExtrasStore: useChatExtrasStore(),
isMobile: useIsMobile(),
}
},

Expand Down Expand Up @@ -257,6 +280,30 @@ export default {
'--original-color-main-background': window.getComputedStyle(document.body).getPropertyValue('--color-main-background')
}
},

nextEvent() {
return this.chatExtrasStore.getNextEvent(this.token)
},

eventInfo() {
return this.nextEvent ? moment(this.nextEvent.start * 1000).calendar() : null
},

showUpcomingEvent() {
return this.nextEvent && !this.isInCall && !this.isSidebar && !this.isMobile
},
},

watch: {
token: {
immediate: true,
handler(value) {
if (!value || this.isSidebar) {
return
}
this.chatExtrasStore.getUpcomingEvents(value)
}
},
},

mounted() {
Expand Down Expand Up @@ -385,4 +432,30 @@ export default {
border-color: var(--original-color-main-background) !important;
background-color: var(--original-color-main-background) !important;
}

.icon {
display: flex;
}

.upcoming-event {
display: flex;
flex-direction: row;
gap: calc(var(--default-grid-baseline) * 2);
padding: 0 calc(var(--default-grid-baseline) * 2);
background-color: rgba(var(--color-info-rgb), 0.1);
height: 100%;
border-radius: var(--border-radius);
}

.event-info {
display: flex;
flex-direction: column;
justify-content: center;
line-height: 1.2;

&__header {
font-weight: 500;
}
}

</style>
15 changes: 15 additions & 0 deletions src/services/conversationsService.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@ const fetchConversations = async function(options) {
return axios.get(generateOcsUrl('apps/spreed/api/v4/room'), options)
}

/**
* fetch future events for a given conversation within the next 31 days.
*
* @param {string} location room's absolute url
* @param {object} options options
*/
const getUpcomingEvents = async (location) => {
return axios.get(generateOcsUrl('/apps/dav/api/v1/events/upcoming'), {
params: {
location,
},
})
}

/**
* Fetches a conversation from the server.
*
Expand Down Expand Up @@ -357,6 +371,7 @@ export {
fetchConversations,
fetchConversation,
fetchNoteToSelfConversation,
getUpcomingEvents,
searchListedConversations,
searchPossibleConversations,
createOneToOneConversation,
Expand Down
18 changes: 18 additions & 0 deletions src/stores/chatExtras.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
import { defineStore } from 'pinia'
import Vue from 'vue'

import { generateUrl, getBaseUrl } from '@nextcloud/router'

import BrowserStorage from '../services/BrowserStorage.js'
import { getUpcomingEvents } from '../services/conversationsService.js'
import { EventBus } from '../services/EventBus.js'
import { getUserAbsence } from '../services/participantsService.js'
import { parseSpecialSymbols, parseMentions } from '../utils/textParse.ts'
Expand All @@ -32,6 +35,7 @@ export const useChatExtrasStore = defineStore('chatExtras', {
state: () => ({
absence: {},
parentToReply: {},
upcomingEvents: {},
chatInput: {},
messageIdToEdit: {},
chatEditInput: {},
Expand All @@ -51,6 +55,10 @@ export const useChatExtrasStore = defineStore('chatExtras', {
getMessageIdToEdit: (state) => (token) => {
return state.messageIdToEdit[token]
},

getNextEvent: (state) => (token) => {
return state.upcomingEvents[token]?.[0]
},
},

actions: {
Expand Down Expand Up @@ -89,6 +97,16 @@ export const useChatExtrasStore = defineStore('chatExtras', {
}
},

async getUpcomingEvents(token) {
const location = generateUrl('call/{token}', { token }, { baseURL: getBaseUrl() })
try {
const response = await getUpcomingEvents(location)
Vue.set(this.upcomingEvents, token, response.data.ocs.data.events)
} catch (error) {
console.error(error)
}
},

/**
* Drop an absence status from the store
*
Expand Down