Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interactive checklist in messages #11402

Closed
1 of 4 tasks
Tracked by #11403
Antreesy opened this issue Jan 18, 2024 · 1 comment · Fixed by #12063
Closed
1 of 4 tasks
Tracked by #11403

Interactive checklist in messages #11402

Antreesy opened this issue Jan 18, 2024 · 1 comment · Fixed by #12063

Comments

@Antreesy
Copy link
Contributor

Antreesy commented Jan 18, 2024

How to use GitHub

  • Please use the 👍 reaction to show that you are interested into the same feature.
  • Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
  • Subscribe to receive notifications on status change and new comments.

Clients support:

As editing API is there, we could reuse the endpoint to modify text message written in markdown to show checkbox:
- [ ] to - [x] to tick the checkbox
- [x] to - [ ] to reverse

@Antreesy
Copy link
Contributor Author

Antreesy commented Mar 14, 2024

Simple patch is under spoiler:

diff --git a/src/components/MessagesList/MessagesGroup/Message/MessagePart/MessageBody.vue b/src/components/MessagesList/MessagesGroup/Message/MessagePart/MessageBody.vue
--- a/src/components/MessagesList/MessagesGroup/Message/MessagePart/MessageBody.vue	(revision b553b17864338596cd7747cd62099bdc8793609b)
+++ b/src/components/MessagesList/MessagesGroup/Message/MessagePart/MessageBody.vue	(date 1710423378379)
@@ -62,7 +62,9 @@
 				autolink
 				dir="auto"
 				:use-extended-markdown="markdown"
-				:reference-limit="1" />
+				:interactive="markdown && isEditable"
+				:reference-limit="1"
+				@interact:todo="handleTickCheckbox" />
 
 			<!-- Additional controls -->
 			<NcButton v-if="containsCodeBlocks"
@@ -133,6 +135,7 @@
 import ContentCopyIcon from 'vue-material-design-icons/ContentCopy.vue'
 import ReloadIcon from 'vue-material-design-icons/Reload.vue'
 
+import { getCapabilities } from '@nextcloud/capabilities'
 import { showError, showSuccess } from '@nextcloud/dialogs'
 import moment from '@nextcloud/moment'
 
@@ -145,7 +148,9 @@
 
 import { useIsInCall } from '../../../../../composables/useIsInCall.js'
 import { EventBus } from '../../../../../services/EventBus.js'
+import { CONVERSATION, PARTICIPANT } from '../../../../../constants.js'
 
+const canEditMessage = getCapabilities()?.spreed?.features?.includes('edit-messages')
 // Regular expression to check for Unicode emojis in message text
 const regex = emojiRegex()
 
@@ -293,6 +298,36 @@
 			return this.isInCall && !!this.$store.getters.getNewPolls[this.messageParameters.object.id]
 		},
 
+		conversation() {
+			return this.$store.getters.conversation(this.token)
+		},
+
+		isConversationReadOnly() {
+			return this.conversation.readOnly === CONVERSATION.STATE.READ_ONLY
+		},
+
+		isModifiable() {
+			return !this.isConversationReadOnly && this.conversation.participantType !== PARTICIPANT.TYPE.GUEST
+		},
+
+		isObjectShare() {
+			return Object.keys(Object(this.messageParameters)).some(key => key.startsWith('object'))
+		},
+
+		isMyMsg() {
+			return this.actorId === this.$store.getters.getActorId()
+				&& this.actorType === this.$store.getters.getActorType()
+		},
+
+		isEditable() {
+			if (!canEditMessage || !this.isModifiable || this.isObjectShare
+				|| (!this.$store.getters.isModerator && !this.isMyMsg)) {
+				return false
+			}
+
+			return (moment(this.timestamp * 1000).add(1, 'd')) > moment()
+		},
+
 		hideDate() {
 			return this.isTemporary || this.isDeleting || !!this.sendingFailure
 		},
@@ -406,6 +441,27 @@
 			}
 		},
 
+		async handleTickCheckbox(event) {
+			if (!this.isEditable) {
+				return
+			}
+			const uncheckedItem = '- [ ] ' + event.label
+			const checkedItem = '- [x] ' + event.label
+			const newText = event.value
+				? this.message.replace(uncheckedItem + event.id, checkedItem)
+				: this.message.replace(checkedItem + event.id, uncheckedItem)
+
+			try {
+				await this.$store.dispatch('editMessage', {
+					token: this.token,
+					messageId: this.id,
+					updatedMessage: newText.trim(),
+				})
+			} catch {
+				showError(t('spreed', 'The message could not be edited'))
+			}
+		},
+
 		handleRetry() {
 			if (this.sendingErrorCanRetry) {
 				if (this.sendingFailure === 'failed-upload') {

Known issues:

  • duplicate of code from MessageButtonsBar - need to extract to composable
  • doesn't work correctly, if you have two similar list items, and want to click on the second one:
- [ ] test
- [ ] test

from the event we know input id in DOM and innerText of the label, but can't think of tracking the correct input

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants