Skip to content

Commit

Permalink
Merge pull request #12431 from nextcloud/fix/12206/speed-up-new-conve…
Browse files Browse the repository at this point in the history
…rsation

fix(NewConversationDialog): speed up conversation creation flow
  • Loading branch information
Antreesy authored May 28, 2024
2 parents 63f26a8 + 7f4b551 commit 29e65da
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 125 deletions.
72 changes: 31 additions & 41 deletions src/components/ConversationSettings/ConversationAvatarEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -292,60 +292,50 @@ export default {
this.emojiAvatar = emoji
},

saveAvatar() {
async saveAvatar() {
this.loading = true

if (this.emojiAvatar) {
this.saveEmojiAvatar()
} else {
this.savePictureAvatar()
}
},

async saveEmojiAvatar() {
try {
await this.$store.dispatch('setConversationEmojiAvatarAction', {
token: this.conversation.token,
emoji: this.emojiAvatar,
color: this.backgroundColor ? this.backgroundColor.slice(1) : null,
})
this.emojiAvatar = ''
this.backgroundColor = ''
if (this.emojiAvatar) {
await this.saveEmojiAvatar()
} else {
await this.savePictureAvatar()
}
} catch (error) {
showError(t('spreed', 'Could not set the conversation picture: {error}',
{ error: error.message },
))
showError(t('spreed', 'Could not set the conversation picture: {error}', { error: error.message }))
this.cancel()
} finally {
this.loading = false
}
},

savePictureAvatar() {
async saveEmojiAvatar() {
await this.$store.dispatch('setConversationEmojiAvatarAction', {
token: this.conversation.token,
emoji: this.emojiAvatar,
color: this.backgroundColor ? this.backgroundColor.slice(1) : null,
})
this.emojiAvatar = ''
this.backgroundColor = ''
},

async savePictureAvatar() {
this.showCropper = false
const canvasData = this.$refs.cropper.getCroppedCanvas()
const scaleFactor = canvasData.width > 512 ? 512 / canvasData.width : 1
this.$refs.cropper.scale(scaleFactor, scaleFactor).getCroppedCanvas().toBlob(async (blob) => {
if (blob === null) {
showError(t('spreed', 'Error cropping conversation picture'))
this.cancel()
return
}

const formData = new FormData()
formData.append('file', blob)

try {
await this.$store.dispatch('setConversationAvatarAction', {
token: this.conversation.token,
file: formData,
})
} catch (error) {
showError(t('spreed', 'Could not set the conversation picture: {error}',
{ error: error.message },
))
} finally {
this.loading = false
}
const blob = await new Promise((resolve, reject) => {
this.$refs.cropper.scale(scaleFactor, scaleFactor).getCroppedCanvas()
.toBlob(blob => blob === null
? reject(new Error(t('spreed', 'Error cropping conversation picture')))
: resolve(blob))
})
const formData = new FormData()
formData.append('file', blob)

await this.$store.dispatch('setConversationAvatarAction', {
token: this.conversation.token,
file: formData,
})
},

Expand Down
125 changes: 41 additions & 84 deletions src/components/NewConversationDialog/NewConversationDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,8 @@ import NewConversationSetupPage from './NewConversationSetupPage.vue'
import LoadingComponent from '../LoadingComponent.vue'

import { useIsInCall } from '../../composables/useIsInCall.js'
import { CONVERSATION, PRIVACY } from '../../constants.js'
import {
createPublicConversation,
createPrivateConversation,
setConversationPassword,
} from '../../services/conversationsService.js'
import { CONVERSATION } from '../../constants.js'
import { setConversationPassword } from '../../services/conversationsService.js'
import { addParticipant } from '../../services/participantsService.js'
import { copyConversationLinkToClipboard } from '../../utils/handleUrl.ts'

Expand Down Expand Up @@ -288,106 +284,67 @@ export default {
async handleCreateConversation() {
this.page = 2

// TODO: move all operations to a single store action
// and commit + addConversation only once at the very end
try {
if (this.isPublic) {
await this.createConversation(PRIVACY.PUBLIC)
if (this.password && this.newConversation.hasPassword) {
await setConversationPassword(this.newConversation.token, this.password)
}
} else {
await this.createConversation(PRIVACY.PRIVATE)
this.newConversation.token = await this.$store.dispatch('createGroupConversation', {
conversationName: this.conversationName,
isPublic: this.isPublic,
})

// Gather all secondary requests to run in parallel
const promises = []

if (this.isPublic && this.password && this.newConversation.hasPassword) {
promises.push(setConversationPassword(this.newConversation.token, this.password))
}
} catch (exception) {
console.error(exception)
this.isLoading = false
this.error = true
// Stop the execution of the method on exceptions.
return
}

try {
await this.$store.dispatch('setListable', {
token: this.newConversation.token,
listable: this.listable,
})
if (this.isAvatarEdited) {
promises.push(this.$refs.setupPage.$refs.conversationAvatar.saveAvatar)
}

if (this.newConversation.description) {
promises.push(this.$store.dispatch('setConversationDescription', {
token: this.newConversation.token,
description: this.newConversation.description,
}))
}

if (this.listable !== CONVERSATION.LISTABLE.NONE) {
promises.push(this.$store.dispatch('setListable', {
token: this.newConversation.token,
listable: this.listable,
}))
}

for (const participant of this.selectedParticipants) {
promises.push(addParticipant(this.newConversation.token, participant.id, participant.source))
}

await Promise.all(promises)
} catch (exception) {
console.error(exception)
console.error('Error creating new conversation: ', exception)
this.isLoading = false
this.error = true
// Stop the execution of the method on exceptions.
return
}

for (const participant of this.selectedParticipants) {
try {
await addParticipant(this.newConversation.token, participant.id, participant.source)
} catch (exception) {
console.error(exception)
this.isLoading = false
this.error = true
// Stop the execution of the method on exceptions.
return
}
}

this.success = true
this.isLoading = false

if (!this.isInCall) {
// Push the newly created conversation's route.
this.pushNewRoute()
this.$router.push({ name: 'conversation', params: { token: this.newConversation.token } })
.catch(err => console.debug(`Error while pushing the new conversation's route: ${err}`))

// Get complete participant list in advance
this.$store.dispatch('fetchParticipants', { token: this.newConversation.token })
}

// Close the modal right away if the conversation is public.
if (!this.isPublic) {
this.closeModal()
}
},
/**
* Creates a new private or public conversation, adds it to the store and sets
* the local token value to the newly created conversation's token
*
* @param {number} flag choose to send a request with private or public flag
*/
async createConversation(flag) {
try {
let response
if (flag === PRIVACY.PRIVATE) {
response = await createPrivateConversation(this.conversationName)
} else if (flag === PRIVACY.PUBLIC) {
response = await createPublicConversation(this.conversationName)
}
const conversation = response.data.ocs.data
this.$store.dispatch('addConversation', conversation)
this.newConversation.token = conversation.token
if (this.isAvatarEdited) {
this.$refs.setupPage.$refs.conversationAvatar.saveAvatar()
}
if (this.newConversation.description) {
this.handleUpdateDescription()
}
} catch (error) {
console.error('Error creating new conversation: ', error)
}
},
pushNewRoute() {
this.$router.push({ name: 'conversation', params: { token: this.newConversation.token } })
.catch(err => console.debug(`Error while pushing the new conversation's route: ${err}`))
},

async handleUpdateDescription() {
try {
await this.$store.dispatch('setConversationDescription', {
token: this.newConversation.token,
description: this.newConversation.description,
})
} catch (error) {
console.error('Error while setting conversation description', error)
showError(t('spreed', 'Error while updating conversation description'))
}
},

/** Handles the press of the enter key */
handleEnter() {
Expand Down
25 changes: 25 additions & 0 deletions src/store/conversationsStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import {
setCallPermissions,
setMessageExpiration,
setConversationPassword,
createPublicConversation,
createPrivateConversation,
} from '../services/conversationsService.js'
import {
clearConversationHistory,
Expand Down Expand Up @@ -918,6 +920,29 @@ const actions = {
}
},

/**
* Creates a new private or public conversation, adds it to the store
*
* @param {object} context default store context;
* @param {object} payload action payload;
* @param {string} payload.conversationName displayed name for a new conversation
* @param {number} payload.isPublic whether a conversation is public or private
* @return {string} token of new conversation
*/
async createGroupConversation(context, { conversationName, isPublic }) {
try {
const response = isPublic
? await createPublicConversation(conversationName)
: await createPrivateConversation(conversationName)
const conversation = response.data.ocs.data
context.dispatch('addConversation', conversation)
return conversation.token
} catch (error) {
console.error('Error creating new group conversation: ', error)
return ''
}
},

async setConversationPermissions(context, { token, permissions }) {
try {
await setConversationPermissions(token, permissions)
Expand Down

0 comments on commit 29e65da

Please sign in to comment.