diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6244951a73..99f601a504 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,7 +8,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- New option to optimize timeline rendering to make the site more responsive (enabled by default)
## [Unreleased patch]
-
### Fixed
- Fixed chats list not updating its order when new messages come in
- Fixed chat messages sometimes getting lost when you receive a message at the same time
@@ -16,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added
- Import/export a muted users
+- Proper handling of deletes when using websocket streaming
## [2.1.1] - 2020-09-08
### Changed
diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js
index dfef37a636..ef40333ce4 100644
--- a/build/webpack.base.conf.js
+++ b/build/webpack.base.conf.js
@@ -97,6 +97,7 @@ module.exports = {
}),
new FontelloPlugin({
config: require('../static/fontello.json'),
+ host: 'https://fontello.com',
name: 'fontello',
output: {
css: 'static/[name].' + now + '.css', // [hash] is not supported. Use the current timestamp instead for versioning.
diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js
index 5c09f6ca7b..3ad80df33e 100644
--- a/src/components/emoji_picker/emoji_picker.js
+++ b/src/components/emoji_picker/emoji_picker.js
@@ -8,10 +8,20 @@ const LOAD_EMOJI_BY = 60
const LOAD_EMOJI_MARGIN = 64
const filterByKeyword = (list, keyword = '') => {
+ if (keyword === '') return list
+
const keywordLowercase = keyword.toLowerCase()
- return list.filter(emoji =>
- emoji.displayText.toLowerCase().includes(keywordLowercase)
- )
+ let orderedEmojiList = []
+ for (const emoji of list) {
+ const indexOfKeyword = emoji.displayText.toLowerCase().indexOf(keywordLowercase)
+ if (indexOfKeyword > -1) {
+ if (!Array.isArray(orderedEmojiList[indexOfKeyword])) {
+ orderedEmojiList[indexOfKeyword] = []
+ }
+ orderedEmojiList[indexOfKeyword].push(emoji)
+ }
+ }
+ return orderedEmojiList.flat()
}
const EmojiPicker = {
diff --git a/src/components/react_button/react_button.js b/src/components/react_button/react_button.js
index 11627e9cbb..dd71e5465a 100644
--- a/src/components/react_button/react_button.js
+++ b/src/components/react_button/react_button.js
@@ -28,9 +28,17 @@ const ReactButton = {
emojis () {
if (this.filterWord !== '') {
const filterWordLowercase = this.filterWord.toLowerCase()
- return this.$store.state.instance.emoji.filter(emoji =>
- emoji.displayText.toLowerCase().includes(filterWordLowercase)
- )
+ let orderedEmojiList = []
+ for (const emoji of this.$store.state.instance.emoji) {
+ const indexOfFilterWord = emoji.displayText.toLowerCase().indexOf(filterWordLowercase)
+ if (indexOfFilterWord > -1) {
+ if (!Array.isArray(orderedEmojiList[indexOfFilterWord])) {
+ orderedEmojiList[indexOfFilterWord] = []
+ }
+ orderedEmojiList[indexOfFilterWord].push(emoji)
+ }
+ }
+ return orderedEmojiList.flat()
}
return this.$store.state.instance.emoji || []
},
diff --git a/src/components/reply_button/reply_button.js b/src/components/reply_button/reply_button.js
new file mode 100644
index 0000000000..2295765040
--- /dev/null
+++ b/src/components/reply_button/reply_button.js
@@ -0,0 +1,12 @@
+
+const ReplyButton = {
+ name: 'ReplyButton',
+ props: ['status', 'replying'],
+ computed: {
+ loggedIn () {
+ return !!this.$store.state.users.currentUser
+ }
+ }
+}
+
+export default ReplyButton
diff --git a/src/components/reply_button/reply_button.vue b/src/components/reply_button/reply_button.vue
new file mode 100644
index 0000000000..b2904b5c4a
--- /dev/null
+++ b/src/components/reply_button/reply_button.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+ {{ status.replies_count }}
+
+
+
+
+
diff --git a/src/components/status/status.js b/src/components/status/status.js
index cd6e2f729f..e48b2eb885 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -1,3 +1,4 @@
+import ReplyButton from '../reply_button/reply_button.vue'
import FavoriteButton from '../favorite_button/favorite_button.vue'
import ReactButton from '../react_button/react_button.vue'
import RetweetButton from '../retweet_button/retweet_button.vue'
@@ -19,6 +20,7 @@ import { unescape, uniqBy } from 'lodash'
const Status = {
name: 'Status',
components: {
+ ReplyButton,
FavoriteButton,
ReactButton,
RetweetButton,
@@ -158,7 +160,7 @@ const Status = {
return this.mergedConfig.hideFilteredStatuses
},
hideStatus () {
- return this.deleted || (this.muted && this.hideFilteredStatuses) || this.virtualHidden
+ return (this.muted && this.hideFilteredStatuses) || this.virtualHidden
},
isFocused () {
// retweet or root of an expanded conversation
diff --git a/src/components/status/status.scss b/src/components/status/status.scss
index c92d870bbb..66a91c1ee4 100644
--- a/src/components/status/status.scss
+++ b/src/components/status/status.scss
@@ -30,6 +30,18 @@ $status-margin: 0.75em;
border-left-style: solid;
}
+ .gravestone {
+ padding: $status-margin;
+ color: $fallback--faint;
+ color: var(--faint, $fallback--faint);
+ display: flex;
+
+ .deleted-text {
+ margin: 0.5em 0;
+ align-items: center;
+ }
+ }
+
.status-container {
display: flex;
padding: $status-margin;
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index aa67e433f3..ffae32fccd 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -95,6 +95,7 @@
-
-
-
- {{ status.replies_count }}
-
+
+
+
+
+
+
+
+ {{ $t('status.status_deleted') }}
+
+
+
+
+
@@ -42,5 +48,10 @@
border-radius: $fallback--avatarAltRadius;
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
}
+
+ &.-placeholder {
+ background-color: $fallback--fg;
+ background-color: var(--fg, $fallback--fg);
+ }
}
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 01f895038f..d3d575624e 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -665,7 +665,8 @@
"show_full_subject": "Show full subject",
"hide_full_subject": "Hide full subject",
"show_content": "Show content",
- "hide_content": "Hide content"
+ "hide_content": "Hide content",
+ "status_deleted": "This post was deleted"
},
"user_card": {
"approve": "Approve",
diff --git a/src/i18n/fi.json b/src/i18n/fi.json
index 3832dcaa88..2524f2788a 100644
--- a/src/i18n/fi.json
+++ b/src/i18n/fi.json
@@ -578,7 +578,8 @@
"show_full_subject": "Näytä koko otsikko",
"hide_full_subject": "Piilota koko otsikko",
"show_content": "Näytä sisältö",
- "hide_content": "Piilota sisältö"
+ "hide_content": "Piilota sisältö",
+ "status_deleted": "Poistettu viesti"
},
"user_card": {
"approve": "Hyväksy",
diff --git a/src/i18n/it.json b/src/i18n/it.json
index 4d09600411..ce50863091 100644
--- a/src/i18n/it.json
+++ b/src/i18n/it.json
@@ -702,7 +702,8 @@
"reply_to": "Rispondi a",
"delete_confirm": "Vuoi veramente eliminare questo messaggio?",
"unbookmark": "Rimuovi segnalibro",
- "bookmark": "Aggiungi segnalibro"
+ "bookmark": "Aggiungi segnalibro",
+ "status_deleted": "Questo messagio è stato cancellato"
},
"time": {
"years_short": "{0}a",
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
index 3444a26d48..8f421b50de 100644
--- a/src/i18n/ru.json
+++ b/src/i18n/ru.json
@@ -473,5 +473,10 @@
"tool_tip": {
"accept_follow_request": "Принять запрос на чтение",
"reject_follow_request": "Отклонить запрос на чтение"
+ },
+ "image_cropper": {
+ "save_without_cropping": "Сохранить не обрезая",
+ "save": "Сохранить",
+ "crop_picture": "Обрезать картинку"
}
}
diff --git a/src/modules/api.js b/src/modules/api.js
index 73511442d7..0a354c3f3a 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -72,6 +72,8 @@ const api = {
showImmediately: timelineData.visibleStatuses.length === 0,
timeline: 'friends'
})
+ } else if (message.event === 'delete') {
+ dispatch('deleteStatusById', message.id)
} else if (message.event === 'pleroma:chat_update') {
dispatch('addChatMessages', {
chatId: message.chatUpdate.id,
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 155cc4b91e..e673141d48 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -611,6 +611,10 @@ const statuses = {
commit('setDeleted', { status })
apiService.deleteStatus({ id: status.id, credentials: rootState.users.currentUser.credentials })
},
+ deleteStatusById ({ rootState, commit }, id) {
+ const status = rootState.statuses.allStatusesObject[id]
+ commit('setDeleted', { status })
+ },
markStatusesAsDeleted ({ commit }, condition) {
commit('setManyDeleted', condition)
},