Merge remote-tracking branch 'origin/develop' into settings-changed
* origin/develop: fix fontello Translated using Weblate (Russian) Translated using Weblate (Italian) lint fix fixed copy-pasting leftovers improved algorithm, possibly speed too fix 8x spaces inside this paren feat/reorder-emojis-by-position-of-keyword rename to gravestone Apply 1 suggestion(s) to 1 file(s) change i18n phrasing separate reply button to its own component, add changelog entry add basic deletes support that works with masto WS
This commit is contained in:
commit
a664fde02f
16 changed files with 127 additions and 26 deletions
|
@ -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)
|
- New option to optimize timeline rendering to make the site more responsive (enabled by default)
|
||||||
|
|
||||||
## [Unreleased patch]
|
## [Unreleased patch]
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fixed chats list not updating its order when new messages come in
|
- 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
|
- 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
|
### Added
|
||||||
- Import/export a muted users
|
- Import/export a muted users
|
||||||
|
- Proper handling of deletes when using websocket streaming
|
||||||
|
|
||||||
## [2.1.1] - 2020-09-08
|
## [2.1.1] - 2020-09-08
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -97,6 +97,7 @@ module.exports = {
|
||||||
}),
|
}),
|
||||||
new FontelloPlugin({
|
new FontelloPlugin({
|
||||||
config: require('../static/fontello.json'),
|
config: require('../static/fontello.json'),
|
||||||
|
host: 'https://fontello.com',
|
||||||
name: 'fontello',
|
name: 'fontello',
|
||||||
output: {
|
output: {
|
||||||
css: 'static/[name].' + now + '.css', // [hash] is not supported. Use the current timestamp instead for versioning.
|
css: 'static/[name].' + now + '.css', // [hash] is not supported. Use the current timestamp instead for versioning.
|
||||||
|
|
|
@ -8,10 +8,20 @@ const LOAD_EMOJI_BY = 60
|
||||||
const LOAD_EMOJI_MARGIN = 64
|
const LOAD_EMOJI_MARGIN = 64
|
||||||
|
|
||||||
const filterByKeyword = (list, keyword = '') => {
|
const filterByKeyword = (list, keyword = '') => {
|
||||||
|
if (keyword === '') return list
|
||||||
|
|
||||||
const keywordLowercase = keyword.toLowerCase()
|
const keywordLowercase = keyword.toLowerCase()
|
||||||
return list.filter(emoji =>
|
let orderedEmojiList = []
|
||||||
emoji.displayText.toLowerCase().includes(keywordLowercase)
|
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 = {
|
const EmojiPicker = {
|
||||||
|
|
|
@ -28,9 +28,17 @@ const ReactButton = {
|
||||||
emojis () {
|
emojis () {
|
||||||
if (this.filterWord !== '') {
|
if (this.filterWord !== '') {
|
||||||
const filterWordLowercase = this.filterWord.toLowerCase()
|
const filterWordLowercase = this.filterWord.toLowerCase()
|
||||||
return this.$store.state.instance.emoji.filter(emoji =>
|
let orderedEmojiList = []
|
||||||
emoji.displayText.toLowerCase().includes(filterWordLowercase)
|
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 || []
|
return this.$store.state.instance.emoji || []
|
||||||
},
|
},
|
||||||
|
|
12
src/components/reply_button/reply_button.js
Normal file
12
src/components/reply_button/reply_button.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
const ReplyButton = {
|
||||||
|
name: 'ReplyButton',
|
||||||
|
props: ['status', 'replying'],
|
||||||
|
computed: {
|
||||||
|
loggedIn () {
|
||||||
|
return !!this.$store.state.users.currentUser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReplyButton
|
21
src/components/reply_button/reply_button.vue
Normal file
21
src/components/reply_button/reply_button.vue
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<i
|
||||||
|
v-if="loggedIn"
|
||||||
|
class="button-icon button-reply icon-reply"
|
||||||
|
:title="$t('tool_tip.reply')"
|
||||||
|
:class="{'-active': replying}"
|
||||||
|
@click.prevent="$emit('toggle')"
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
v-else
|
||||||
|
class="button-icon button-reply -disabled icon-reply"
|
||||||
|
:title="$t('tool_tip.reply')"
|
||||||
|
/>
|
||||||
|
<span v-if="status.replies_count > 0">
|
||||||
|
{{ status.replies_count }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./reply_button.js"></script>
|
|
@ -1,3 +1,4 @@
|
||||||
|
import ReplyButton from '../reply_button/reply_button.vue'
|
||||||
import FavoriteButton from '../favorite_button/favorite_button.vue'
|
import FavoriteButton from '../favorite_button/favorite_button.vue'
|
||||||
import ReactButton from '../react_button/react_button.vue'
|
import ReactButton from '../react_button/react_button.vue'
|
||||||
import RetweetButton from '../retweet_button/retweet_button.vue'
|
import RetweetButton from '../retweet_button/retweet_button.vue'
|
||||||
|
@ -19,6 +20,7 @@ import { unescape, uniqBy } from 'lodash'
|
||||||
const Status = {
|
const Status = {
|
||||||
name: 'Status',
|
name: 'Status',
|
||||||
components: {
|
components: {
|
||||||
|
ReplyButton,
|
||||||
FavoriteButton,
|
FavoriteButton,
|
||||||
ReactButton,
|
ReactButton,
|
||||||
RetweetButton,
|
RetweetButton,
|
||||||
|
@ -158,7 +160,7 @@ const Status = {
|
||||||
return this.mergedConfig.hideFilteredStatuses
|
return this.mergedConfig.hideFilteredStatuses
|
||||||
},
|
},
|
||||||
hideStatus () {
|
hideStatus () {
|
||||||
return this.deleted || (this.muted && this.hideFilteredStatuses) || this.virtualHidden
|
return (this.muted && this.hideFilteredStatuses) || this.virtualHidden
|
||||||
},
|
},
|
||||||
isFocused () {
|
isFocused () {
|
||||||
// retweet or root of an expanded conversation
|
// retweet or root of an expanded conversation
|
||||||
|
|
|
@ -30,6 +30,18 @@ $status-margin: 0.75em;
|
||||||
border-left-style: solid;
|
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 {
|
.status-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: $status-margin;
|
padding: $status-margin;
|
||||||
|
|
|
@ -95,6 +95,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
v-if="!deleted"
|
||||||
:class="[userClass, { highlighted: userStyle, '-repeat': retweet && !inConversation }]"
|
:class="[userClass, { highlighted: userStyle, '-repeat': retweet && !inConversation }]"
|
||||||
:style="[ userStyle ]"
|
:style="[ userStyle ]"
|
||||||
class="status-container"
|
class="status-container"
|
||||||
|
@ -323,21 +324,11 @@
|
||||||
v-if="!noHeading && !isPreview"
|
v-if="!noHeading && !isPreview"
|
||||||
class="status-actions"
|
class="status-actions"
|
||||||
>
|
>
|
||||||
<div>
|
<reply-button
|
||||||
<i
|
:replying="replying"
|
||||||
v-if="loggedIn"
|
:status="status"
|
||||||
class="button-icon button-reply icon-reply"
|
@toggle="toggleReplying"
|
||||||
:title="$t('tool_tip.reply')"
|
|
||||||
:class="{'-active': replying}"
|
|
||||||
@click.prevent="toggleReplying"
|
|
||||||
/>
|
/>
|
||||||
<i
|
|
||||||
v-else
|
|
||||||
class="button-icon button-reply -disabled icon-reply"
|
|
||||||
:title="$t('tool_tip.reply')"
|
|
||||||
/>
|
|
||||||
<span v-if="status.replies_count > 0">{{ status.replies_count }}</span>
|
|
||||||
</div>
|
|
||||||
<retweet-button
|
<retweet-button
|
||||||
:visibility="status.visibility"
|
:visibility="status.visibility"
|
||||||
:logged-in="loggedIn"
|
:logged-in="loggedIn"
|
||||||
|
@ -360,6 +351,25 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="gravestone"
|
||||||
|
>
|
||||||
|
<div class="left-side">
|
||||||
|
<UserAvatar :compact="compact" />
|
||||||
|
</div>
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="deleted-text">
|
||||||
|
{{ $t('status.status_deleted') }}
|
||||||
|
</div>
|
||||||
|
<reply-button
|
||||||
|
v-if="replying"
|
||||||
|
:replying="replying"
|
||||||
|
:status="status"
|
||||||
|
@toggle="toggleReplying"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="replying"
|
v-if="replying"
|
||||||
class="status-container reply-form"
|
class="status-container reply-form"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<StillImage
|
<StillImage
|
||||||
|
v-if="user"
|
||||||
class="Avatar"
|
class="Avatar"
|
||||||
:alt="user.screen_name"
|
:alt="user.screen_name"
|
||||||
:title="user.screen_name"
|
:title="user.screen_name"
|
||||||
|
@ -7,6 +8,11 @@
|
||||||
:class="{ 'avatar-compact': compact, 'better-shadow': betterShadow }"
|
:class="{ 'avatar-compact': compact, 'better-shadow': betterShadow }"
|
||||||
:image-load-error="imageLoadError"
|
:image-load-error="imageLoadError"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="Avatar -placeholder"
|
||||||
|
:class="{ 'avatar-compact': compact }"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./user_avatar.js"></script>
|
<script src="./user_avatar.js"></script>
|
||||||
|
@ -42,5 +48,10 @@
|
||||||
border-radius: $fallback--avatarAltRadius;
|
border-radius: $fallback--avatarAltRadius;
|
||||||
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
|
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.-placeholder {
|
||||||
|
background-color: $fallback--fg;
|
||||||
|
background-color: var(--fg, $fallback--fg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -665,7 +665,8 @@
|
||||||
"show_full_subject": "Show full subject",
|
"show_full_subject": "Show full subject",
|
||||||
"hide_full_subject": "Hide full subject",
|
"hide_full_subject": "Hide full subject",
|
||||||
"show_content": "Show content",
|
"show_content": "Show content",
|
||||||
"hide_content": "Hide content"
|
"hide_content": "Hide content",
|
||||||
|
"status_deleted": "This post was deleted"
|
||||||
},
|
},
|
||||||
"user_card": {
|
"user_card": {
|
||||||
"approve": "Approve",
|
"approve": "Approve",
|
||||||
|
|
|
@ -578,7 +578,8 @@
|
||||||
"show_full_subject": "Näytä koko otsikko",
|
"show_full_subject": "Näytä koko otsikko",
|
||||||
"hide_full_subject": "Piilota koko otsikko",
|
"hide_full_subject": "Piilota koko otsikko",
|
||||||
"show_content": "Näytä sisältö",
|
"show_content": "Näytä sisältö",
|
||||||
"hide_content": "Piilota sisältö"
|
"hide_content": "Piilota sisältö",
|
||||||
|
"status_deleted": "Poistettu viesti"
|
||||||
},
|
},
|
||||||
"user_card": {
|
"user_card": {
|
||||||
"approve": "Hyväksy",
|
"approve": "Hyväksy",
|
||||||
|
|
|
@ -702,7 +702,8 @@
|
||||||
"reply_to": "Rispondi a",
|
"reply_to": "Rispondi a",
|
||||||
"delete_confirm": "Vuoi veramente eliminare questo messaggio?",
|
"delete_confirm": "Vuoi veramente eliminare questo messaggio?",
|
||||||
"unbookmark": "Rimuovi segnalibro",
|
"unbookmark": "Rimuovi segnalibro",
|
||||||
"bookmark": "Aggiungi segnalibro"
|
"bookmark": "Aggiungi segnalibro",
|
||||||
|
"status_deleted": "Questo messagio è stato cancellato"
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
"years_short": "{0}a",
|
"years_short": "{0}a",
|
||||||
|
|
|
@ -473,5 +473,10 @@
|
||||||
"tool_tip": {
|
"tool_tip": {
|
||||||
"accept_follow_request": "Принять запрос на чтение",
|
"accept_follow_request": "Принять запрос на чтение",
|
||||||
"reject_follow_request": "Отклонить запрос на чтение"
|
"reject_follow_request": "Отклонить запрос на чтение"
|
||||||
|
},
|
||||||
|
"image_cropper": {
|
||||||
|
"save_without_cropping": "Сохранить не обрезая",
|
||||||
|
"save": "Сохранить",
|
||||||
|
"crop_picture": "Обрезать картинку"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,8 @@ const api = {
|
||||||
showImmediately: timelineData.visibleStatuses.length === 0,
|
showImmediately: timelineData.visibleStatuses.length === 0,
|
||||||
timeline: 'friends'
|
timeline: 'friends'
|
||||||
})
|
})
|
||||||
|
} else if (message.event === 'delete') {
|
||||||
|
dispatch('deleteStatusById', message.id)
|
||||||
} else if (message.event === 'pleroma:chat_update') {
|
} else if (message.event === 'pleroma:chat_update') {
|
||||||
dispatch('addChatMessages', {
|
dispatch('addChatMessages', {
|
||||||
chatId: message.chatUpdate.id,
|
chatId: message.chatUpdate.id,
|
||||||
|
|
|
@ -611,6 +611,10 @@ const statuses = {
|
||||||
commit('setDeleted', { status })
|
commit('setDeleted', { status })
|
||||||
apiService.deleteStatus({ id: status.id, credentials: rootState.users.currentUser.credentials })
|
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) {
|
markStatusesAsDeleted ({ commit }, condition) {
|
||||||
commit('setManyDeleted', condition)
|
commit('setManyDeleted', condition)
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue