diff --git a/CHANGELOG.md b/CHANGELOG.md
index 24c193b9..ebd0e613 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,8 +2,29 @@
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
## [Unreleased]
+### Changed
+- Removed the use of with_move parameters when fetching notifications
+
+## [2.0.3] - 2020-05-02
+### Fixed
+- Show more/less works correctly with auto-collapsed subjects and long posts
+- RTL characters won't look messed up in notifications
+
+### Changed
+- Emoji autocomplete will match any part of the word and not just start, for example :drool will now helpfully suggest :blobcatdrool: and :blobcatdroolreach:
+
+### Add
+- Follow request notification support
+
+## [2.0.2] - 2020-04-08
+### Fixed
+- Favorite/Repeat avatars not showing up on private instances/non-public posts
+- Autocorrect getting triggered in the captcha field
+- Overflow on long domains in follow/move notifications
+
+### Changed
+- Polish translation updated
## [2.0.0] - 2020-02-28
### Added
diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index d70e1058..9fb9a853 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -241,6 +241,9 @@ const getNodeInfo = async ({ store }) => {
: federation.enabled
})
+ const accountActivationRequired = metadata.accountActivationRequired
+ store.dispatch('setInstanceOption', { name: 'accountActivationRequired', value: accountActivationRequired })
+
const accounts = metadata.staffAccounts
resolveStaffAccounts({ store, accounts })
} else {
diff --git a/src/components/emoji_input/suggestor.js b/src/components/emoji_input/suggestor.js
index aec5c39d..15a71eff 100644
--- a/src/components/emoji_input/suggestor.js
+++ b/src/components/emoji_input/suggestor.js
@@ -29,17 +29,29 @@ export default data => input => {
export const suggestEmoji = emojis => input => {
const noPrefix = input.toLowerCase().substr(1)
return emojis
- .filter(({ displayText }) => displayText.toLowerCase().startsWith(noPrefix))
+ .filter(({ displayText }) => displayText.toLowerCase().match(noPrefix))
.sort((a, b) => {
let aScore = 0
let bScore = 0
- // Make custom emojis a priority
- aScore += a.imageUrl ? 10 : 0
- bScore += b.imageUrl ? 10 : 0
+ // An exact match always wins
+ aScore += a.displayText.toLowerCase() === noPrefix ? 200 : 0
+ bScore += b.displayText.toLowerCase() === noPrefix ? 200 : 0
- // Sort alphabetically
- const alphabetically = a.displayText > b.displayText ? 1 : -1
+ // Prioritize custom emoji a lot
+ aScore += a.imageUrl ? 100 : 0
+ bScore += b.imageUrl ? 100 : 0
+
+ // Prioritize prefix matches somewhat
+ aScore += a.displayText.toLowerCase().startsWith(noPrefix) ? 10 : 0
+ bScore += b.displayText.toLowerCase().startsWith(noPrefix) ? 10 : 0
+
+ // Sort by length
+ aScore -= a.displayText.length
+ bScore -= b.displayText.length
+
+ // Break ties alphabetically
+ const alphabetically = a.displayText > b.displayText ? 0.5 : -0.5
return bScore - aScore + alphabetically
})
diff --git a/src/components/follow_request_card/follow_request_card.js b/src/components/follow_request_card/follow_request_card.js
index a8931787..cbd75311 100644
--- a/src/components/follow_request_card/follow_request_card.js
+++ b/src/components/follow_request_card/follow_request_card.js
@@ -1,4 +1,5 @@
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
+import { notificationsFromStore } from '../../services/notification_utils/notification_utils.js'
const FollowRequestCard = {
props: ['user'],
@@ -6,13 +7,32 @@ const FollowRequestCard = {
BasicUserCard
},
methods: {
+ findFollowRequestNotificationId () {
+ const notif = notificationsFromStore(this.$store).find(
+ (notif) => notif.from_profile.id === this.user.id && notif.type === 'follow_request'
+ )
+ return notif && notif.id
+ },
approveUser () {
this.$store.state.api.backendInteractor.approveUser({ id: this.user.id })
this.$store.dispatch('removeFollowRequest', this.user)
+
+ const notifId = this.findFollowRequestNotificationId()
+ this.$store.dispatch('markSingleNotificationAsSeen', { id: notifId })
+ this.$store.dispatch('updateNotification', {
+ id: notifId,
+ updater: notification => {
+ notification.type = 'follow'
+ }
+ })
},
denyUser () {
+ const notifId = this.findFollowRequestNotificationId()
this.$store.state.api.backendInteractor.denyUser({ id: this.user.id })
- this.$store.dispatch('removeFollowRequest', this.user)
+ .then(() => {
+ this.$store.dispatch('dismissNotificationLocal', { id: notifId })
+ this.$store.dispatch('removeFollowRequest', this.user)
+ })
}
}
}
diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js
index e7bd769e..1ae81ce4 100644
--- a/src/components/notification/notification.js
+++ b/src/components/notification/notification.js
@@ -2,6 +2,7 @@ import Status from '../status/status.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import UserCard from '../user_card/user_card.vue'
import Timeago from '../timeago/timeago.vue'
+import { isStatusNotification } from '../../services/notification_utils/notification_utils.js'
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
@@ -32,6 +33,24 @@ const Notification = {
},
toggleMute () {
this.unmuted = !this.unmuted
+ },
+ approveUser () {
+ this.$store.state.api.backendInteractor.approveUser({ id: this.user.id })
+ this.$store.dispatch('removeFollowRequest', this.user)
+ this.$store.dispatch('markSingleNotificationAsSeen', { id: this.notification.id })
+ this.$store.dispatch('updateNotification', {
+ id: this.notification.id,
+ updater: notification => {
+ notification.type = 'follow'
+ }
+ })
+ },
+ denyUser () {
+ this.$store.state.api.backendInteractor.denyUser({ id: this.user.id })
+ .then(() => {
+ this.$store.dispatch('dismissNotificationLocal', { id: this.notification.id })
+ this.$store.dispatch('removeFollowRequest', this.user)
+ })
}
},
computed: {
@@ -57,6 +76,9 @@ const Notification = {
},
needMute () {
return this.user.muted
+ },
+ isStatusNotification () {
+ return isStatusNotification(this.notification.type)
}
}
}
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index 411c0271..f6da07dd 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -47,7 +47,7 @@
-
{{ $t('notifications.followed_you') }}
+
+
+ {{ $t('notifications.follow_request') }}
+
{{ $t('notifications.migrated_to') }}
@@ -87,18 +91,7 @@
-
-
-
-
-
+
+
+
+
+
-
+
@{{ notification.from_profile.screen_name }}
+
+
+
+
this.accountActivationRequired) },
+ username: { required },
+ fullname: { required },
+ password: { required },
+ confirm: {
+ required,
+ sameAsPassword: sameAs('password')
+ }
}
}
},
@@ -43,7 +45,8 @@ const registration = {
signedIn: (state) => !!state.users.currentUser,
isPending: (state) => state.users.signUpPending,
serverValidationErrors: (state) => state.users.signUpErrors,
- termsOfService: (state) => state.instance.tos
+ termsOfService: (state) => state.instance.tos,
+ accountActivationRequired: (state) => state.instance.accountActivationRequired
})
},
methods: {
diff --git a/src/components/status/status.js b/src/components/status/status.js
index fc5956ec..61d66301 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -188,23 +188,22 @@ const Status = {
}
return this.status.attentions.length > 0
},
+
+ // When a status has a subject and is also tall, we should only have one show more/less button. If the default is to collapse statuses with subjects, we just treat it like a status with a subject; otherwise, we just treat it like a tall status.
+ mightHideBecauseSubject () {
+ return this.status.summary && (!this.tallStatus || this.localCollapseSubjectDefault)
+ },
+ mightHideBecauseTall () {
+ return this.tallStatus && (!this.status.summary || !this.localCollapseSubjectDefault)
+ },
hideSubjectStatus () {
- if (this.tallStatus && !this.localCollapseSubjectDefault) {
- return false
- }
- return !this.expandingSubject && this.status.summary
+ return this.mightHideBecauseSubject && !this.expandingSubject
},
hideTallStatus () {
- if (this.status.summary && this.localCollapseSubjectDefault) {
- return false
- }
- if (this.showingTall) {
- return false
- }
- return this.tallStatus
+ return this.mightHideBecauseTall && !this.showingTall
},
showingMore () {
- return (this.tallStatus && this.showingTall) || (this.status.summary && this.expandingSubject)
+ return (this.mightHideBecauseTall && this.showingTall) || (this.mightHideBecauseSubject && this.expandingSubject)
},
nsfwClickthrough () {
if (!this.status.nsfw) {
@@ -408,14 +407,10 @@ const Status = {
this.userExpanded = !this.userExpanded
},
toggleShowMore () {
- if (this.showingTall) {
- this.showingTall = false
- } else if (this.expandingSubject && this.status.summary) {
- this.expandingSubject = false
- } else if (this.hideTallStatus) {
- this.showingTall = true
- } else if (this.hideSubjectStatus && this.status.summary) {
- this.expandingSubject = true
+ if (this.mightHideBecauseTall) {
+ this.showingTall = !this.showingTall
+ } else if (this.mightHideBecauseSubject) {
+ this.expandingSubject = !this.expandingSubject
}
},
generateUserProfileLink (id, name) {
diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
index 8b2336b4..ad184520 100644
--- a/src/components/user_settings/user_settings.vue
+++ b/src/components/user_settings/user_settings.vue
@@ -379,6 +379,7 @@
:label="$t('settings.notifications')"
>
+
{{ $t('settings.notification_setting_filters') }}
{{ $t('settings.notification_setting') }}
+
+
+
+
{{ $t('settings.notification_setting_privacy') }}
+
+
+ {{ $t('settings.notification_setting_privacy_option') }}
+
+
+
+
{{ $t('settings.notification_mutes') }}
{{ $t('settings.notification_blocks') }}