Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/spreed.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/appstore-build-publish.yml42
-rw-r--r--CHANGELOG.md40
-rw-r--r--Makefile5
-rw-r--r--appinfo/info.xml2
-rw-r--r--docs/Talkbuchet.js162
-rw-r--r--docs/reaction.md3
-rw-r--r--l10n/pt_BR.js3
-rw-r--r--l10n/pt_BR.json3
-rw-r--r--lib/Share/RoomShareProvider.php4
-rw-r--r--src/components/MessagesList/MessagesGroup/Message/Message.spec.js14
-rw-r--r--src/components/MessagesList/MessagesGroup/Message/Message.vue19
-rw-r--r--src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue8
-rw-r--r--src/components/NewMessageForm/NewMessageForm.vue2
-rw-r--r--src/store/messagesStore.js7
-rw-r--r--src/store/reactionsStore.js15
-rw-r--r--src/views/Dashboard.vue3
16 files changed, 263 insertions, 69 deletions
diff --git a/.github/workflows/appstore-build-publish.yml b/.github/workflows/appstore-build-publish.yml
index ba532ca14..fc04383c6 100644
--- a/.github/workflows/appstore-build-publish.yml
+++ b/.github/workflows/appstore-build-publish.yml
@@ -23,16 +23,16 @@ jobs:
- name: Check actor permission
uses: skjnldsv/check-actor-permission@v2
with:
- require: admin
+ require: write
- name: Set app env
run: |
- # Split and keep last
+ # Split and keep last
echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
echo "APP_VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
path: ${{ env.APP_NAME }}
@@ -41,22 +41,22 @@ jobs:
uses: skjnldsv/xpath-action@master
with:
filename: ${{ env.APP_NAME }}/appinfo/info.xml
- expression: '//info//dependencies//nextcloud/@min-version'
+ expression: "//info//dependencies//nextcloud/@min-version"
- name: Read package.json node and npm engines version
- uses: skjnldsv/read-package-engines-version-actions@v1.1
+ uses: skjnldsv/read-package-engines-version-actions@v1.2
id: versions
# Continue if no package.json
continue-on-error: true
with:
path: ${{ env.APP_NAME }}
- fallbackNode: '^12'
- fallbackNpm: '^6'
+ fallbackNode: "^12"
+ fallbackNpm: "^6"
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
# Skip if no package.json
if: ${{ steps.versions.outputs.nodeVersion }}
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v3
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
@@ -91,11 +91,29 @@ jobs:
npm ci
npm run build
- - name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }}
- # Try krankerl, fallback to makefile
+ - name: Check Krankerl config
+ id: krankerl
+ uses: andstor/file-existence-action@v1
+ with:
+ files: ${{ env.APP_NAME }}/krankerl.toml
+
+ - name: Install Krankerl
+ if: steps.krankerl.outputs.files_exists == 'true'
+ run: |
+ wget https://github.com/ChristophWurst/krankerl/releases/download/v0.13.0/krankerl_0.13.0_amd64.deb
+ sudo dpkg -i krankerl_0.13.0_amd64.deb
+
+ - name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }} with krankerl
+ if: steps.krankerl.outputs.files_exists == 'true'
+ run: |
+ cd ${{ env.APP_NAME }}
+ krankerl package
+
+ - name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }} with makefile
+ if: steps.krankerl.outputs.files_exists != 'true'
run: |
cd ${{ env.APP_NAME }}
- krankerl package || make appstore
+ make appstore
- name: Checkout server ${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}
continue-on-error: true
@@ -106,7 +124,7 @@ jobs:
unzip latest-$NCVERSION.zip
- name: Checkout server master fallback
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
if: ${{ steps.server-checkout.outcome != 'success' }}
with:
repository: nextcloud/server
diff --git a/CHANGELOG.md b/CHANGELOG.md
index afd8a360d..1305be75c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,46 @@
# Changelog
All notable changes to this project will be documented in this file.
+## 14.0.0-beta.1 – 2022-04-08
+### Added
+- Reactions for chat messages
+- Implement `OCP\Talk\IBroker` to allow apps to create conversations
+- Sharing a browser tab in Chrome-based browsers can now also share the audio of that tab
+ [#6810](https://github.com/nextcloud/spreed/pull/6810)
+
+### Still in progress
+- Media tab showing all shared items of the conversation
+
+### Changed
+- Messages of shared objects and files can now be deleted (shares will be removed, files persist)
+ [#7047](https://github.com/nextcloud/spreed/pull/7047)
+- Actions like calling and chatting in big rooms should now be much smoother
+- Compatibility with Nextcloud 24
+
+## 13.0.5 – 2022-04-08
+### Fixed
+- Fix reconnection when media permissions change
+ [#7092](https://github.com/nextcloud/spreed/pull/7092)
+- Fix forced reconnection without the High-performance backend
+ [#7095](https://github.com/nextcloud/spreed/pull/7095)
+- Compatibility with LDAP user backends and more than 64 characters display names
+ [#7073](https://github.com/nextcloud/spreed/pull/7073)
+- Compatibility with Oracle and MySQL ONLY_FULL_GROUP_BY
+ [#7036](https://github.com/nextcloud/spreed/pull/7036)
+- Fix broken avatars when search for users to add to a conversation
+ [#7037](https://github.com/nextcloud/spreed/pull/7037)
+- Fix sort order of guests and logged-in users
+ [#7053](https://github.com/nextcloud/spreed/pull/7053)
+- Allow copying links of open conversations without joining
+ [#7070](https://github.com/nextcloud/spreed/pull/7070)
+
+## 12.2.5 – 2022-04-08
+### Fixed
+- Compatibility with LDAP user backends and more than 64 characters display names
+ [#7074](https://github.com/nextcloud/spreed/pull/7074)
+- Compatibility with Oracle and MySQL ONLY_FULL_GROUP_BY
+ [#7040](https://github.com/nextcloud/spreed/pull/7040)
+
## 13.0.4 – 2022-03-17
### Fixed
- Fix several modals, dialogs and popovers in fullscreen mode
diff --git a/Makefile b/Makefile
index 093617369..721254998 100644
--- a/Makefile
+++ b/Makefile
@@ -63,6 +63,7 @@ appstore:
--exclude=composer.json \
--exclude=composer.lock \
--exclude=docs \
+ --exclude=.drone.jsonnet \
--exclude=.drone.yml \
--exclude=.eslintignore \
--exclude=.eslintrc.js \
@@ -77,8 +78,10 @@ appstore:
--exclude=node_modules \
--exclude=package.json \
--exclude=package-lock.json \
- --exclude=.php_cs.dist \
+ --exclude=.php-cs-fixer.cache \
+ --exclude=.php-cs-fixer.dist.php \
--exclude=.php_cs.cache \
+ --exclude=.php_cs.dist \
--exclude=psalm.xml \
--exclude=README.md \
--exclude=src \
diff --git a/appinfo/info.xml b/appinfo/info.xml
index f9afae1ff..593471a19 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -16,7 +16,7 @@ And in the works for the [coming versions](https://github.com/nextcloud/spreed/m
]]></description>
- <version>14.0.0-dev.3</version>
+ <version>14.0.0-beta.1</version>
<licence>agpl</licence>
<author>Aleksandra Lazarević</author>
diff --git a/docs/Talkbuchet.js b/docs/Talkbuchet.js
index 513b71c94..c8dd34df3 100644
--- a/docs/Talkbuchet.js
+++ b/docs/Talkbuchet.js
@@ -22,22 +22,27 @@
/**
* HOW TO SETUP:
* -----------------------------------------------------------------------------
- * - Set the right values in "user" and "appToken" (a user must be used; guests
- * do not work; generate an apptoken at index.php/settings/user/security ).
- * - If HPB clustering is enabled, set the token of a conversation in "token"
- * (otherwise leave empty).
- * - Set whether to use audio, video or both in "mediaConstraints".
- * - Set the desired numbers in "publishersCount" and
- * "subscribersPerPublisherCount" (in a regular call with N participants you
- * would have N publishers and N-1 subscribers).
+ * - In the browser, log in the Nextcloud server (with the same user as in this
+ * script).
+ * - Copy and paste the full script in the console of the browser.
+ * - Set the user and appToken (a user must be used; guests do not work;
+ * generate an apptoken at index.php/settings/user/security) by calling
+ * "setCredentials(user, appToken)" in the console.
+ * - If HPB clustering is enabled, set the token of a conversation (otherwise
+ * leave empty) by calling "setToken(token)" in the console.
+ * - If media other than just audio should be used, start it by calling
+ * "startMedia(audio, video)" in the console.
+ * - Set the desired numbers of publishers and subscribers per publisher (in a
+ * regular call with N participants you would have N publishers and N-1
+ * subscribers) by calling "setPublishersAndSubscribersCount(publishersCount,
+ * subscribersPerPublisherCount)" in the console.
*
* HOW TO RUN:
* -----------------------------------------------------------------------------
- * - In the browser, log in the Nextcloud server (with the same user as in this
- * script).
- * - Copy and paste the full script in the console of the browser to run it.
- * - To run it again execute "closeConnections()" in the console; then you must
- * reload the page and copy and paste the script again.
+ * - Once all the needed parameters are set execute "siege()" in the console.
+ * - To run it again execute "siege()" again in the console; if any parameter
+ * needs to be changed it is recommended to first stop the previous siege by
+ * calling "closeConnections()" in the console before changing the parameters.
*
* HOW TO ENABLE AND DISABLE THE MEDIA DURING A TEST:
* -----------------------------------------------------------------------------
@@ -126,27 +131,24 @@
// a second time causes the first guest to be unregistered.
// Regular users do not need to join the conversation, so the same user can be
// connected several times to the HPB.
-const user = ''
-const appToken = ''
-
-const signalingApiVersion = 2 // FIXME get from capabilities endpoint
-const conversationApiVersion = 3 // FIXME get from capabilities endpoint
+let user = ''
+let appToken = ''
// The conversation token is only strictly needed for guests or if HPB
// clustering is enabled.
-const token = ''
+let token = ''
// Number of streams to send
-const publishersCount = 5
+let publishersCount = 5
// Number of streams to receive
-const subscribersPerPublisherCount = 40
+let subscribersPerPublisherCount = 40
const mediaConstraints = {
audio: true,
video: false,
}
-const connectionWarningTimeout = 5000
+let connectionWarningTimeout = 5000
/*
* End of configuration section
@@ -155,15 +157,55 @@ const connectionWarningTimeout = 5000
// To run the script the current page in the browser must be a page of the
// target Nextcloud instance, as cross-doman requests are not allowed, so the
// host is directly got from the current location.
-const talkOcsApiUrl = 'https://' + window.location.host + '/ocs/v2.php/apps/spreed/api/'
+const host = 'https://' + window.location.host
+
+const capabitiliesUrl = host + '/ocs/v1.php/cloud/capabilities'
+
+async function getCapabilities() {
+ const fetchOptions = {
+ headers: {
+ 'OCS-ApiRequest': true,
+ 'Accept': 'json',
+ },
+ }
+
+ const capabilitiesResponse = await fetch(capabitiliesUrl, fetchOptions)
+ const capabilities = await capabilitiesResponse.json()
+
+ return capabilities.ocs.data
+}
+
+const capabilities = await getCapabilities()
+
+function extractFeatureVersion(feature) {
+ const talkFeatures = capabilities?.capabilities?.spreed?.features
+ if (!talkFeatures) {
+ console.error('Talk features not found', capabilities)
+ throw new Error()
+ }
+
+ for (const talkFeature of talkFeatures) {
+ if (talkFeature.startsWith(feature + '-v')) {
+ return talkFeature.substring(feature.length + 2)
+ }
+ }
+
+ console.error('Failed to get feature version for ' + feature, talkFeatures)
+ throw new Error()
+}
+
+const signalingApiVersion = extractFeatureVersion('signaling')
+const conversationApiVersion = extractFeatureVersion('conversation')
+
+const talkOcsApiUrl = host + '/ocs/v2.php/apps/spreed/api/'
const signalingSettingsUrl = talkOcsApiUrl + 'v' + signalingApiVersion + '/signaling/settings'
const signalingBackendUrl = talkOcsApiUrl + 'v' + signalingApiVersion + '/signaling/backend'
-const joinRoomUrl = talkOcsApiUrl + 'v' + conversationApiVersion + '/room/' + token + '/participants/active'
+let joinRoomUrl = talkOcsApiUrl + 'v' + conversationApiVersion + '/room/' + token + '/participants/active'
const publishers = []
const subscribers = []
-const stream = await navigator.mediaDevices.getUserMedia(mediaConstraints)
+let stream
async function getSignalingSettings(user, appToken, token) {
const fetchOptions = {
@@ -608,14 +650,21 @@ const closeConnections = function() {
subscribers.forEach(subscriber => {
subscriber.peerConnection.close()
})
+ subscribers.splice(0)
Object.values(publishers).forEach(publisher => {
publisher.peerConnection.close()
})
-
- stream.getTracks().forEach(track => {
- track.stop()
+ Object.keys(publishers).forEach(publisherSessionId => {
+ delete publishers[publisherSessionId]
})
+
+ if (stream) {
+ stream.getTracks().forEach(track => {
+ track.stop()
+ })
+ stream = null
+ }
}
const setAudioEnabled = function(enabled) {
@@ -723,7 +772,58 @@ const checkSubscribersConnections = function() {
console.info(' - Failed: ' + (iceConnectionStateCount['failed'] ?? 0))
}
-console.info('Preparing to siege')
+const setCredentials = function(userToSet, appTokenToSet) {
+ user = userToSet
+ appToken = appTokenToSet
+}
+
+const setToken = function(tokenToSet) {
+ token = tokenToSet
+
+ joinRoomUrl = talkOcsApiUrl + 'v' + conversationApiVersion + '/room/' + token + '/participants/active'
+}
+
+const setPublishersAndSubscribersCount = function(publishersCountToSet, subscribersPerPublisherCountToSet) {
+ publishersCount = publishersCountToSet
+ subscribersPerPublisherCount = subscribersPerPublisherCountToSet
+}
+
+const startMedia = async function(audio, video) {
+ if (stream) {
+ stream.getTracks().forEach(track => {
+ track.stop()
+ })
+ }
+
+ if (audio !== undefined) {
+ mediaConstraints.audio = audio
+ }
+ if (video !== undefined) {
+ mediaConstraints.video = video
+ }
+
+ stream = await navigator.mediaDevices.getUserMedia(mediaConstraints)
+}
+
+const setConnectionWarningTimeout = function(connectionWarningTimeoutToSet) {
+ connectionWarningTimeout = connectionWarningTimeoutToSet
+}
+
+const siege = async function() {
+ if (!user || !appToken) {
+ console.error('Credentials (user and appToken) are not set')
+
+ return
+ }
-await initPublishers()
-await initSubscribers()
+ closeConnections()
+
+ if (!stream) {
+ await startMedia()
+ }
+
+ console.info('Preparing to siege')
+
+ await initPublishers()
+ await initSubscribers()
+}
diff --git a/docs/reaction.md b/docs/reaction.md
index f4ed4b7b4..e135ef482 100644
--- a/docs/reaction.md
+++ b/docs/reaction.md
@@ -16,10 +16,9 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`
* Response:
- Status code:
+ `200 OK` Reaction already exists
- + `201 Created`
+ + `201 Created` User reacted with a new reaction
+ `400 Bad Request` In case of no reaction support, message out of reactions context or any other error
+ `404 Not Found` When the conversation or message to react could not be found for the participant
- + `409 Conflict` User already did this reaction to this message
- Data:
Array with data of reactions:
diff --git a/l10n/pt_BR.js b/l10n/pt_BR.js
index 248b7d704..1eae61749 100644
--- a/l10n/pt_BR.js
+++ b/l10n/pt_BR.js
@@ -47,6 +47,7 @@ OC.L10N.register(
"The command does not exist" : "O comando não existe",
"An error occurred while running the command. Please ask an administrator to check the logs." : "Ocorreu um erro ao executar o comando. Por favor, peça a um administrador para verificar os logs.",
"Talk updates ✅" : "Atualizações do Talk ✅",
+ "Reaction deleted by author" : "Reação excluída pelo autor",
"{actor} created the conversation" : "{actor} criou a conversa",
"You created the conversation" : "Você criou uma conversa",
"An administrator created the conversation" : "Um administrador criou a conversa",
@@ -148,6 +149,8 @@ OC.L10N.register(
"You stopped Matterbridge" : "Você parou Matterbridge.",
"{actor} deleted a message" : "{actor} excluiu uma mensagem",
"You deleted a message" : "Você excluiu uma mensagem",
+ "{actor} deleted a reaction" : "{actor} excluiu uma reação",
+ "You deleted a reaction" : "Você excluiu uma reação",
"{actor} cleared the history of the conversation" : "{actor} limpou o histórico da conversa ",
"You cleared the history of the conversation" : "Você limpou o histórico da conversa ",
"Message deleted by author" : "Mensagem excluída pelo autor",
diff --git a/l10n/pt_BR.json b/l10n/pt_BR.json
index eda94ab66..d8062ec06 100644
--- a/l10n/pt_BR.json
+++ b/l10n/pt_BR.json
@@ -45,6 +45,7 @@
"The command does not exist" : "O comando não existe",
"An error occurred while running the command. Please ask an administrator to check the logs." : "Ocorreu um erro ao executar o comando. Por favor, peça a um administrador para verificar os logs.",
"Talk updates ✅" : "Atualizações do Talk ✅",
+ "Reaction deleted by author" : "Reação excluída pelo autor",
"{actor} created the conversation" : "{actor} criou a conversa",
"You created the conversation" : "Você criou uma conversa",
"An administrator created the conversation" : "Um administrador criou a conversa",
@@ -146,6 +147,8 @@
"You stopped Matterbridge" : "Você parou Matterbridge.",
"{actor} deleted a message" : "{actor} excluiu uma mensagem",
"You deleted a message" : "Você excluiu uma mensagem",
+ "{actor} deleted a reaction" : "{actor} excluiu uma reação",
+ "You deleted a reaction" : "Você excluiu uma reação",
"{actor} cleared the history of the conversation" : "{actor} limpou o histórico da conversa ",
"You cleared the history of the conversation" : "Você limpou o histórico da conversa ",
"Message deleted by author" : "Mensagem excluída pelo autor",
diff --git a/lib/Share/RoomShareProvider.php b/lib/Share/RoomShareProvider.php
index df8311f10..287477884 100644
--- a/lib/Share/RoomShareProvider.php
+++ b/lib/Share/RoomShareProvider.php
@@ -970,12 +970,12 @@ class RoomShareProvider implements IShareProvider {
$userList = $this->participantService->getParticipantUserIds($room);
foreach ($userList as $uid) {
- $users[$uid] = $users[$uid] ?? [];
+ $users[$uid] ??= [];
$users[$uid][$row['id']] = $row;
}
} elseif ($type === self::SHARE_TYPE_USERROOM && $currentAccess === true) {
$uid = $row['share_with'];
- $users[$uid] = $users[$uid] ?? [];
+ $users[$uid] ??= [];
$users[$uid][$row['id']] = $row;
}
}
diff --git a/src/components/MessagesList/MessagesGroup/Message/Message.spec.js b/src/components/MessagesList/MessagesGroup/Message/Message.spec.js
index a12c40f26..0bf661642 100644
--- a/src/components/MessagesList/MessagesGroup/Message/Message.spec.js
+++ b/src/components/MessagesList/MessagesGroup/Message/Message.spec.js
@@ -809,8 +809,10 @@ describe('Message.vue', () => {
test('dispatches store action upon picking an emoji from the emojipicker', () => {
const addReactionToMessageAction = jest.fn()
const userHasReactedGetter = jest.fn().mockReturnValue(() => false)
+ const reactionsLoadedGetter = jest.fn().mockReturnValue(() => true)
testStoreConfig.modules.quoteReplyStore.actions.addReactionToMessage = addReactionToMessageAction
testStoreConfig.modules.messagesStore.getters.userHasReacted = userHasReactedGetter
+ testStoreConfig.modules.messagesStore.getters.reactionsLoaded = reactionsLoadedGetter
store = new Store(testStoreConfig)
@@ -821,11 +823,6 @@ describe('Message.vue', () => {
stubs: {
EmojiPicker,
},
- data() {
- return {
- detailedReactionsRequested: true,
- }
- },
})
const emojiPicker = wrapper.findComponent(EmojiPicker)
@@ -844,8 +841,10 @@ describe('Message.vue', () => {
test('dispatches store action to remove an emoji upon clicking reaction button', async () => {
const removeReactionFromMessageAction = jest.fn()
const userHasReactedGetter = jest.fn().mockReturnValue(() => true)
+ const reactionsLoadedGetter = jest.fn().mockReturnValue(() => true)
testStoreConfig.modules.quoteReplyStore.actions.removeReactionFromMessage = removeReactionFromMessageAction
testStoreConfig.modules.messagesStore.getters.userHasReacted = userHasReactedGetter
+ testStoreConfig.modules.messagesStore.getters.reactionsLoaded = reactionsLoadedGetter
store = new Store(testStoreConfig)
@@ -853,11 +852,6 @@ describe('Message.vue', () => {
localVue,
store,
propsData: messageProps,
- data() {
- return {
- detailedReactionsRequested: true,
- }
- },
})
// Click reaction button upon having already reacted
diff --git a/src/components/MessagesList/MessagesGroup/Message/Message.vue b/src/components/MessagesList/MessagesGroup/Message/Message.vue
index 2e9d073f9..28181b355 100644
--- a/src/components/MessagesList/MessagesGroup/Message/Message.vue
+++ b/src/components/MessagesList/MessagesGroup/Message/Message.vue
@@ -359,7 +359,7 @@ export default {
isActionMenuOpen: false,
isEmojiPickerOpen: false,
isReactionsMenuOpen: false,
- detailedReactionsRequested: false,
+ detailedReactionsLoading: false,
}
},
@@ -568,6 +568,10 @@ export default {
detailedReactions() {
return this.$store.getters.reactions(this.token, this.id)
},
+
+ detailedReactionsLoaded() {
+ return this.$store.getters.reactionsLoaded(this.token, this.id)
+ },
},
watch: {
@@ -625,7 +629,7 @@ export default {
},
handleReactionsMouseOver() {
- if (this.hasReactions && !this.detailedReactionsRequested) {
+ if (this.hasReactions && !this.detailedReactionsLoaded) {
this.getReactions()
}
},
@@ -637,24 +641,29 @@ export default {
},
async getReactions() {
+ if (this.detailedReactionsLoading) {
+ // FIXME not sure how to await the other execution
+ }
+
try {
/**
* Get reaction details when the message is hovered for the first
* time. After that we rely on system messages to update the
* reactions.
*/
- this.detailedReactionsRequested = true
+ this.detailedReactionsLoading = true
await this.$store.dispatch('getReactions', {
token: this.token,
messageId: this.id,
})
+ this.detailedReactionsLoading = false
} catch {
- this.detailedReactionsRequested = false
+ this.detailedReactionsLoading = false
}
},
async handleReactionClick(clickedEmoji) {
- if (!this.detailedReactionsRequested) {
+ if (!this.detailedReactionsLoaded) {
await this.getReactions()
}
// Check if current user has already added this reaction to the message
diff --git a/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue b/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue
index f02664994..b6e2a5f8a 100644
--- a/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue
+++ b/src/components/MessagesList/MessagesGroup/Message/MessageButtonsBar/MessageButtonsBar.vue
@@ -67,7 +67,7 @@
:href="linkToFile">
{{ t('spreed', 'Go to file') }}
</ActionLink>
- <ActionButton v-if="!isCurrentGuest && !isFileShare"
+ <ActionButton v-if="!isCurrentGuest && !isFileShare && !isDeletedMessage"
:close-after-click="true"
@click.stop="showForwarder = true">
<Share slot="icon"
@@ -326,7 +326,7 @@ export default {
},
acceptsReactions() {
- return !this.isConversationReadOnly
+ return !this.isConversationReadOnly && !this.isDeletedMessage
},
messageActions() {
@@ -356,6 +356,10 @@ export default {
isConversationReadOnly() {
return this.conversation.readOnly === CONVERSATION.STATE.READ_ONLY
},
+
+ isDeletedMessage() {
+ return this.messageType === 'comment_deleted'
+ },
},
methods: {
diff --git a/src/components/NewMessageForm/NewMessageForm.vue b/src/components/NewMessageForm/NewMessageForm.vue
index 4ffb5a2b1..0942e316e 100644
--- a/src/components/NewMessageForm/NewMessageForm.vue
+++ b/src/components/NewMessageForm/NewMessageForm.vue
@@ -68,7 +68,7 @@
@select="addEmoji">
<Button :disabled="disabled"
:aria-label="t('spreed', 'Add emoji')"
- type="tertiary"
+ type="tertiary-no-background"
:aria-haspopup="true">
<EmoticonOutline :size="16"
decorative
diff --git a/src/store/messagesStore.js b/src/store/messagesStore.js
index 46346b428..e10fd2094 100644
--- a/src/store/messagesStore.js
+++ b/src/store/messagesStore.js
@@ -391,6 +391,13 @@ const actions = {
})
}
+ if (message.systemMessage === 'reaction' || message.systemMessage === 'reaction_revoked') {
+ context.commit('resetReactions', {
+ token: message.token,
+ messageId: message.parent,
+ })
+ }
+
context.commit('addMessage', message)
},
diff --git a/src/store/reactionsStore.js b/src/store/reactionsStore.js
index c9f1c67fc..c70a14a0b 100644
--- a/src/store/reactionsStore.js
+++ b/src/store/reactionsStore.js
@@ -41,6 +41,14 @@ const getters = {
}
},
+ reactionsLoaded: (state) => (token, messageId) => {
+ if (state.reactions?.[token]?.[messageId]) {
+ return true
+ } else {
+ return false
+ }
+ },
+
// Checks if a user has already reacted to a message with a particular reaction
userHasReacted: (state) => (actorType, actorId, token, messageId, reaction) => {
if (!state?.reactions?.[token]?.[messageId]?.[reaction]) {
@@ -60,6 +68,13 @@ const mutations = {
}
Vue.set(state.reactions[token], messageId, reactions)
},
+
+ resetReactions(state, { token, messageId }) {
+ if (!state.reactions[token]) {
+ Vue.set(state.reactions, token, {})
+ }
+ Vue.delete(state.reactions[token], messageId)
+ },
}
const actions = {
diff --git a/src/views/Dashboard.vue b/src/views/Dashboard.vue
index eed707118..66834ef0f 100644
--- a/src/views/Dashboard.vue
+++ b/src/views/Dashboard.vue
@@ -31,8 +31,7 @@
<DashboardWidgetItem :target-url="getItemTargetUrl(item)"
:main-text="getMainText(item)"
:sub-text="getSubText(item)"
- :item="item"
- v-on="handlers">
+ :item="item">
<template #avatar>
<ConversationIcon :item="item"
:hide-favorite="true"