Skip to content

Commit

Permalink
Merge pull request #11589 from nextcloud/chore11583/room-selector-fol…
Browse files Browse the repository at this point in the history
…low-ups

chore(RoomSelector): reduce bundle size
  • Loading branch information
Antreesy authored Feb 20, 2024
2 parents 77e2e8a + 8f05d42 commit 72e729f
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 70 deletions.
9 changes: 6 additions & 3 deletions src/collections.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,28 @@ import Vue from 'vue'
container.id = 'spreed-room-select'
const body = document.getElementById('body-user')
body.appendChild(container)

const RoomSelector = () => import('./components/RoomSelector.vue')
const ComponentVM = new Vue({
el: container,
render: h => h(RoomSelector, {
props: {
// Even if it is used from Talk the Collections menu is
// independently loaded, so the properties that depend
// on the store need to be explicitly injected.
container: window.store ? window.store.getters.getMainContainerSelector() : undefined,
isPlugin: true,
},
}),
})
ComponentVM.$mount(container)

ComponentVM.$root.$on('close', () => {
ComponentVM.$el.remove()
ComponentVM.$destroy()
reject(new Error('User cancelled resource selection'))
})
ComponentVM.$root.$on('select', (id) => {
resolve(id)
ComponentVM.$root.$on('select', ({ token }) => {
resolve(token)
ComponentVM.$el.remove()
ComponentVM.$destroy()
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<NcListItem :key="item.token"
:name="item.displayName"
:title="item.displayName"
:active="item.token === selectedRoom"
:active="item.token === selectedRoom?.token"
:bold="exposeMessages && !!item.unreadMessages"
:counter-number="exposeMessages ? item.unreadMessages : 0"
:counter-type="counterType"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default {
this.modal = false
},

openConversation(token) {
openConversation({ token }) {
this.$router.push({ name: 'conversation', params: { token } })
.catch(err => console.debug(`Error while pushing the new conversation's route: ${err}`))
this.closeModal()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import Check from 'vue-material-design-icons/Check.vue'

import { showError } from '@nextcloud/dialogs'
import { generateUrl } from '@nextcloud/router'

import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
Expand Down Expand Up @@ -93,6 +94,7 @@ export default {
data() {
return {
selectedConversationToken: null,
selectedConversationName: null,
showForwardedConfirmation: false,
forwardedMessageID: '',
}
Expand All @@ -110,16 +112,12 @@ export default {
dialogSubtitle() {
return t('spreed', 'Choose a conversation to forward the selected message.')
},

selectedConversationName() {
return this.$store.getters?.conversation(this.selectedConversationToken).displayName
},

},

methods: {
async setSelectedConversationToken(token) {
this.selectedConversationToken = token
async setSelectedConversationToken(conversation) {
this.selectedConversationToken = conversation.token
this.selectedConversationName = conversation.displayName
try {
const response = await this.$store.dispatch('forwardMessage', {
targetToken: this.selectedConversationToken,
Expand All @@ -134,17 +132,26 @@ export default {
},

openConversation() {
if (window.location.href.includes('/apps/files')) {
// Native redirect to Talk from Files sidebar
const url = generateUrl('/call/{token}#message_{messageId}', {
token: this.selectedConversationToken,
messageId: this.forwardedMessageID,
})
window.open(url, '_blank').focus()
} else {
this.$router.push({
name: 'conversation',
hash: `#message_${this.forwardedMessageID}`,
params: {
token: `${this.selectedConversationToken}`,
},
}).catch(err => console.debug(`Error while pushing the new conversation's route: ${err}`))
}

this.$router.push({
name: 'conversation',
hash: `#message_${this.forwardedMessageID}`,
params: {
token: `${this.selectedConversationToken}`,
},
})
.catch(err => console.debug(`Error while pushing the new conversation's route: ${err}`))
this.showForwardedConfirmation = false
this.forwardedMessageID = ''
this.$emit('close')
},

handleClose() {
Expand Down
18 changes: 16 additions & 2 deletions src/components/RoomSelector.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ describe('RoomSelector', () => {
// Arrange
const wrapper = await mountRoomSelector()
const eventHandler = jest.fn()
wrapper.vm.$root.$on('select', eventHandler)
wrapper.vm.$on('select', eventHandler)

// Act: click on second item, then click 'Select conversation'
const list = wrapper.findComponent({ name: 'ConversationsSearchListVirtual' })
Expand All @@ -229,13 +229,27 @@ describe('RoomSelector', () => {
await wrapper.findComponent(NcButton).vm.$emit('click')

// Assert
expect(eventHandler).toHaveBeenCalledWith('token-3')
expect(eventHandler).toHaveBeenCalledWith(conversations[0])
})

it('emits close event', async () => {
// Arrange
const wrapper = await mountRoomSelector()
const eventHandler = jest.fn()
wrapper.vm.$on('close', eventHandler)

// Act: close modal
const modal = wrapper.findComponent({ name: 'NcModal' })
await modal.vm.$emit('close')

// Assert
expect(eventHandler).toHaveBeenCalled()
})

it('emits close event on $root as plugin', async () => {
// Arrange
const wrapper = await mountRoomSelector({ isPlugin: true })
const eventHandler = jest.fn()
wrapper.vm.$root.$on('close', eventHandler)

// Act: close modal
Expand Down
26 changes: 19 additions & 7 deletions src/components/RoomSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,14 @@ export default {
type: Boolean,
default: false,
},

/**
* Whether component is used as plugin and should emit on $root.
*/
isPlugin: {
type: Boolean,
default: false,
},
},

emits: ['close', 'select'],
Expand Down Expand Up @@ -201,19 +209,23 @@ export default {
},

close() {
// FIXME: should not emit on $root but on itself
this.$root.$emit('close')
this.$emit('close')
if (this.isPlugin) {
this.$root.$emit('close')
} else {
this.$emit('close')
}
},

onSelect(item) {
this.selectedRoom = item.token
this.selectedRoom = item
},

onSubmit() {
// FIXME: should not emit on $root but on itself
this.$root.$emit('select', this.selectedRoom)
this.$emit('select', this.selectedRoom)
if (this.isPlugin) {
this.$root.$emit('select', this.selectedRoom)
} else {
this.$emit('select', this.selectedRoom)
}
},
},
}
Expand Down
48 changes: 23 additions & 25 deletions src/deck.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,35 +28,30 @@ import { showSuccess, showError } from '@nextcloud/dialogs'
import { translate, translatePlural } from '@nextcloud/l10n'
import { generateFilePath, generateUrl } from '@nextcloud/router'

import RoomSelector from './components/RoomSelector.vue'

import { fetchConversation } from './services/conversationsService.js'
import { postRichObjectToConversation } from './services/messagesService.js'

import '@nextcloud/dialogs/style.css'

(function(OC, OCA, t, n) {
/**
* @param {object} card The card object given by the deck app
* @param {string} token The conversation to post to
* @param {object} conversation The conversation object given by the RoomSelector
* @param {string} conversation.token The conversation token
* @param {string} conversation.displayName The conversation display name
*/
async function postCardToRoom(card, token) {
async function postCardToRoom(card, { token, displayName }) {
try {
const [responsePostCard, responseGetConversation] = await Promise.allSettled([
postRichObjectToConversation(token, {
objectType: 'deck-card',
objectId: card.id,
metaData: JSON.stringify(card),
}),
fetchConversation(token),
])

const messageId = responsePostCard.value.data.ocs.data.id
const conversation = responseGetConversation.value.data.ocs.data.displayName
const response = await postRichObjectToConversation(token, {
objectType: 'deck-card',
objectId: card.id,
metaData: JSON.stringify(card),
})

const messageId = response.data.ocs.data.id
const targetUrl = generateUrl('/call/{token}#message_{messageId}', { token, messageId })

showSuccess(t('spreed', 'Deck card has been posted to {conversation}')
.replace(/\{conversation}/g, `<a target="_blank" class="external" href="${targetUrl}">${escapeHtml(conversation)} ↗</a>`),
.replace(/\{conversation}/g, `<a target="_blank" class="external" href="${targetUrl}">${escapeHtml(displayName)} ↗</a>`),
{
isHTML: true,
})
Expand Down Expand Up @@ -87,24 +82,27 @@ import '@nextcloud/dialogs/style.css'
const body = document.getElementById('body-user')
body.appendChild(container)

const ComponentVM = Vue.extend(RoomSelector)
const vm = new ComponentVM({
const RoomSelector = () => import('./components/RoomSelector.vue')
const vm = new Vue({
el: container,
propsData: {
dialogTitle: t('spreed', 'Post to conversation'),
showPostableOnly: true,
},
render: h => h(RoomSelector, {
props: {
dialogTitle: t('spreed', 'Post to conversation'),
showPostableOnly: true,
isPlugin: true,
},
}),
})

vm.$root.$on('close', () => {
vm.$el.remove()
vm.$destroy()
})
vm.$root.$on('select', (token) => {
vm.$root.$on('select', (conversation) => {
vm.$el.remove()
vm.$destroy()

postCardToRoom(card, token)
postCardToRoom(card, conversation)
})
},
})
Expand Down
36 changes: 20 additions & 16 deletions src/maps.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,26 @@
*
*/

import escapeHtml from 'escape-html'
import Vue from 'vue'

import { getRequestToken } from '@nextcloud/auth'
import { showSuccess, showError } from '@nextcloud/dialogs'
import { translate, translatePlural } from '@nextcloud/l10n'
import { generateFilePath, generateUrl } from '@nextcloud/router'

import RoomSelector from './components/RoomSelector.vue'

import { postRichObjectToConversation } from './services/messagesService.js'

import '@nextcloud/dialogs/style.css'

(function(OC, OCA, t, n) {
/**
* @param {object} location Geo location object
* @param {string} token Conversation token to be posted to
* @return {Promise<void>}
* @param {object} conversation The conversation object given by the RoomSelector
* @param {string} conversation.token The conversation token
* @param {string} conversation.displayName The conversation display name
*/
async function postLocationToRoom(location, token) {
async function postLocationToRoom(location, { token, displayName }) {
try {
const response = await postRichObjectToConversation(token, {
objectType: 'geo-location',
Expand All @@ -48,9 +48,10 @@ import '@nextcloud/dialogs/style.css'
})
const messageId = response.data.ocs.data.id
const targetUrl = generateUrl('/call/{token}#message_{messageId}', { token, messageId })
showSuccess(t('spreed', 'Location has been posted to the selected <a href="{link}">conversation</a>', {
link: targetUrl,
}), {

showSuccess(t('spreed', 'Location has been posted to {conversation}')
.replace(/\{conversation}/g, `<a target="_blank" class="external" href="${targetUrl}">${escapeHtml(displayName)} ↗</a>`),
{
isHTML: true,
})
} catch (exception) {
Expand Down Expand Up @@ -80,24 +81,27 @@ import '@nextcloud/dialogs/style.css'
const body = document.getElementById('body-user')
body.appendChild(container)

const ComponentVM = Vue.extend(RoomSelector)
const vm = new ComponentVM({
const RoomSelector = () => import('./components/RoomSelector.vue')
const vm = new Vue({
el: container,
propsData: {
dialogTitle: t('spreed', 'Share to conversation'),
showPostableOnly: true,
},
render: h => h(RoomSelector, {
props: {
dialogTitle: t('spreed', 'Share to conversation'),
showPostableOnly: true,
isPlugin: true,
},
}),
})

vm.$root.$on('close', () => {
vm.$el.remove()
vm.$destroy()
})
vm.$root.$on('select', (token) => {
vm.$root.$on('select', (conversation) => {
vm.$el.remove()
vm.$destroy()

postLocationToRoom(location, token)
postLocationToRoom(location, conversation)
})
},
})
Expand Down

0 comments on commit 72e729f

Please sign in to comment.