From 6184c88ac70b33e66a87222142344f693406bd87 Mon Sep 17 00:00:00 2001
From: Henry Jameson
Date: Sun, 3 Mar 2019 15:15:41 +0200
Subject: Initial work on deprecating scopeModesEnabled in favor of
minimalScopeMode
---
src/components/features_panel/features_panel.js | 2 +-
.../post_status_form/post_status_form.js | 27 ++++++-----
.../post_status_form/post_status_form.vue | 13 ++---
src/components/scope_selector/scope_selector.js | 55 ++++++++++++++++++++++
src/components/scope_selector/scope_selector.vue | 30 ++++++++++++
src/components/settings/settings.js | 10 +++-
src/components/settings/settings.vue | 6 +++
src/components/user_settings/user_settings.js | 6 ++-
src/components/user_settings/user_settings.vue | 10 ++--
9 files changed, 132 insertions(+), 27 deletions(-)
create mode 100644 src/components/scope_selector/scope_selector.js
create mode 100644 src/components/scope_selector/scope_selector.vue
(limited to 'src/components')
diff --git a/src/components/features_panel/features_panel.js b/src/components/features_panel/features_panel.js
index e0b7a118..0a7234cc 100644
--- a/src/components/features_panel/features_panel.js
+++ b/src/components/features_panel/features_panel.js
@@ -6,7 +6,7 @@ const FeaturesPanel = {
gopher: function () { return this.$store.state.instance.gopherAvailable },
whoToFollow: function () { return this.$store.state.instance.suggestionsEnabled },
mediaProxy: function () { return this.$store.state.instance.mediaProxyAvailable },
- scopeOptions: function () { return this.$store.state.instance.scopeOptionsEnabled },
+ scopeOptionsMinimal: function () { return this.$store.state.instance.scopeOptionsMinimal },
textlimit: function () { return this.$store.state.instance.textlimit }
}
}
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index c28c51bf..b0882f70 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -1,5 +1,6 @@
import statusPoster from '../../services/status_poster/status_poster.service.js'
import MediaUpload from '../media_upload/media_upload.vue'
+import ScopeSelector from '../scope_selector/scope_selector.vue'
import fileTypeService from '../../services/file_type/file_type.service.js'
import Completion from '../../services/completion/completion.js'
import { take, filter, reject, map, uniqBy } from 'lodash'
@@ -28,7 +29,8 @@ const PostStatusForm = {
'subject'
],
components: {
- MediaUpload
+ MediaUpload,
+ ScopeSelector
},
mounted () {
this.resize(this.$refs.textarea)
@@ -78,14 +80,6 @@ const PostStatusForm = {
}
},
computed: {
- vis () {
- return {
- public: { selected: this.newStatus.visibility === 'public' },
- unlisted: { selected: this.newStatus.visibility === 'unlisted' },
- private: { selected: this.newStatus.visibility === 'private' },
- direct: { selected: this.newStatus.visibility === 'direct' }
- }
- },
candidates () {
const firstchar = this.textAtCaret.charAt(0)
if (firstchar === '@') {
@@ -133,6 +127,15 @@ const PostStatusForm = {
users () {
return this.$store.state.users.users
},
+ userDefaultScope () {
+ return this.$store.state.users.currentUser.default_scope
+ },
+ showAllScopes () {
+ const minimalScopesMode = typeof this.$store.state.config.minimalScopesMode === 'undefined'
+ ? this.$store.state.instance.minimalScopesMode
+ : this.$store.state.config.minimalScopesMode
+ return !minimalScopesMode
+ },
emoji () {
return this.$store.state.instance.emoji || []
},
@@ -157,8 +160,8 @@ const PostStatusForm = {
isOverLengthLimit () {
return this.hasStatusLengthLimit && (this.charactersLeft < 0)
},
- scopeOptionsEnabled () {
- return this.$store.state.instance.scopeOptionsEnabled
+ scopeOptionsMinimal () {
+ return this.$store.state.instance.scopeOptionsMinimal
},
alwaysShowSubject () {
if (typeof this.$store.state.config.alwaysShowSubjectInput !== 'undefined') {
@@ -166,7 +169,7 @@ const PostStatusForm = {
} else if (typeof this.$store.state.instance.alwaysShowSubjectInput !== 'undefined') {
return this.$store.state.instance.alwaysShowSubjectInput
} else {
- return this.$store.state.instance.scopeOptionsEnabled
+ return true
}
},
formattingOptionsEnabled () {
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
index 5085570b..b3d731cd 100644
--- a/src/components/post_status_form/post_status_form.vue
+++ b/src/components/post_status_form/post_status_form.vue
@@ -44,12 +44,13 @@
-
-
-
-
-
-
+
diff --git a/src/components/scope_selector/scope_selector.js b/src/components/scope_selector/scope_selector.js
new file mode 100644
index 00000000..578f1ba5
--- /dev/null
+++ b/src/components/scope_selector/scope_selector.js
@@ -0,0 +1,55 @@
+const ScopeSelector = {
+ props: [
+ 'showAll',
+ 'userEnabled',
+ 'userDefault',
+ 'originalScope',
+ 'initialScope',
+ 'onScopeChange'
+ ],
+ data () {
+ return {
+ currentScope: this.initialScope
+ }
+ },
+ computed: {
+ showNothing () {
+ return !this.showPublic && !this.showUnlisted && !this.showPrivate && !this.showDirect
+ },
+ showPublic () {
+ return this.originalScope !== 'direct' && this.shouldShow('public')
+ },
+ showUnlisted () {
+ return this.originalScope !== 'direct' && this.shouldShow('unlisted')
+ },
+ showPrivate () {
+ return this.originalScope !== 'direct' && this.shouldShow('private')
+ },
+ showDirect () {
+ return this.shouldShow('direct')
+ },
+ css () {
+ return {
+ public: {selected: this.currentScope === 'public'},
+ unlisted: {selected: this.currentScope === 'unlisted'},
+ private: {selected: this.currentScope === 'private'},
+ direct: {selected: this.currentScope === 'direct'}
+ }
+ }
+ },
+ methods: {
+ shouldShow (scope) {
+ return this.showAll ||
+ this.currentScope === scope ||
+ this.originalScope === scope ||
+ this.userDefault === scope ||
+ this.userEnabled.includes(scope)
+ },
+ changeVis (scope) {
+ this.currentScope = scope
+ this.onScopeChange && this.onScopeChange(scope)
+ }
+ }
+}
+
+export default ScopeSelector
diff --git a/src/components/scope_selector/scope_selector.vue b/src/components/scope_selector/scope_selector.vue
new file mode 100644
index 00000000..33ea488f
--- /dev/null
+++ b/src/components/scope_selector/scope_selector.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js
index 6e2dff7b..104be1a8 100644
--- a/src/components/settings/settings.js
+++ b/src/components/settings/settings.js
@@ -60,13 +60,18 @@ const settings = {
alwaysShowSubjectInputLocal: typeof user.alwaysShowSubjectInput === 'undefined'
? instance.alwaysShowSubjectInput
: user.alwaysShowSubjectInput,
- alwaysShowSubjectInputDefault: instance.alwaysShowSubjectInput,
+ alwaysShowSubjectInputDefault: this.$t('settings.values.' + instance.alwaysShowSubjectInput),
scopeCopyLocal: typeof user.scopeCopy === 'undefined'
? instance.scopeCopy
: user.scopeCopy,
scopeCopyDefault: this.$t('settings.values.' + instance.scopeCopy),
+ minimalScopesModeLocal: typeof user.minimalScopesMode === 'undefined'
+ ? instance.minimalScopesMode
+ : user.minimalScopesMode,
+ minimalScopesModeDefault: this.$t('settings.values.' + instance.minimalScopesMode),
+
stopGifs: user.stopGifs,
webPushNotificationsLocal: user.webPushNotifications,
loopVideoSilentOnlyLocal: user.loopVideosSilentOnly,
@@ -175,6 +180,9 @@ const settings = {
postContentTypeLocal (value) {
this.$store.dispatch('setOption', { name: 'postContentType', value })
},
+ minimalScopesModeLocal (value) {
+ this.$store.dispatch('setOption', { name: 'minimalScopesMode', value })
+ },
stopGifs (value) {
this.$store.dispatch('setOption', { name: 'stopGifs', value })
},
diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index 5041b3a3..d9b72ee0 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -122,6 +122,12 @@
+
+
+
+
diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js
index d6972737..1911ab23 100644
--- a/src/components/user_settings/user_settings.js
+++ b/src/components/user_settings/user_settings.js
@@ -4,6 +4,7 @@ import get from 'lodash/get'
import TabSwitcher from '../tab_switcher/tab_switcher.js'
import ImageCropper from '../image_cropper/image_cropper.vue'
import StyleSwitcher from '../style_switcher/style_switcher.vue'
+import ScopeSelector from '../scope_selector/scope_selector.vue'
import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
import BlockCard from '../block_card/block_card.vue'
import MuteCard from '../mute_card/mute_card.vue'
@@ -66,6 +67,7 @@ const UserSettings = {
},
components: {
StyleSwitcher,
+ ScopeSelector,
TabSwitcher,
ImageCropper,
BlockList,
@@ -78,8 +80,8 @@ const UserSettings = {
pleromaBackend () {
return this.$store.state.instance.pleromaBackend
},
- scopeOptionsEnabled () {
- return this.$store.state.instance.scopeOptionsEnabled
+ scopeOptionsMinimal () {
+ return this.$store.state.instance.scopeOptionsMinimal
},
vis () {
return {
diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
index a1123638..7bd391ba 100644
--- a/src/components/user_settings/user_settings.vue
+++ b/src/components/user_settings/user_settings.vue
@@ -29,13 +29,13 @@
-
+
-
-
-
-
+
--
cgit v1.2.3-70-g09d2
From ee49409049430dedf042ddbeb73898f605664cd2 Mon Sep 17 00:00:00 2001
From: Henry Jameson
Date: Fri, 8 Mar 2019 00:35:30 +0200
Subject: Partially transitioned user data to MastoAPI. Added support for
fetching relationship data. Upgraded code to be more resilient to nulls
caused by missing data in either APIs
---
src/components/user_card/user_card.js | 3 ++
src/components/user_profile/user_profile.js | 3 ++
src/modules/statuses.js | 6 ++--
src/modules/users.js | 32 ++++++++++++++++++----
src/services/api/api.service.js | 20 ++++++++++++--
.../backend_interactor_service.js | 5 ++++
6 files changed, 59 insertions(+), 10 deletions(-)
(limited to 'src/components')
diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js
index 80d15a27..43a77f45 100644
--- a/src/components/user_card/user_card.js
+++ b/src/components/user_card/user_card.js
@@ -15,6 +15,9 @@ export default {
betterShadow: this.$store.state.interface.browserSupport.cssFilter
}
},
+ created () {
+ this.$store.dispatch('fetchUserRelationship', this.user.id)
+ },
computed: {
classes () {
return [{
diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js
index 54126514..345e7035 100644
--- a/src/components/user_profile/user_profile.js
+++ b/src/components/user_profile/user_profile.js
@@ -43,6 +43,7 @@ const UserProfile = {
this.startFetchFavorites()
if (!this.user.id) {
this.$store.dispatch('fetchUser', this.fetchBy)
+ .then(() => this.$store.dispatch('fetchUserRelationship', this.fetchBy))
.catch((reason) => {
const errorMessage = get(reason, 'error.error')
if (errorMessage === 'No user with such user_id') { // Known error
@@ -53,6 +54,8 @@ const UserProfile = {
this.error = this.$t('user_profile.profile_loading_error')
}
})
+ } else if (typeof this.user.following === 'undefined' || this.user.following === null) {
+ this.$store.dispatch('fetchUserRelationship', this.fetchBy)
}
},
destroyed () {
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 7571b62a..2b0215f0 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -1,4 +1,4 @@
-import { remove, slice, each, find, maxBy, minBy, merge, first, last, isArray } from 'lodash'
+import { remove, slice, each, find, maxBy, minBy, merge, first, last, isArray, omitBy } from 'lodash'
import apiService from '../services/api/api.service.js'
// import parse from '../services/status_parser/status_parser.js'
@@ -72,7 +72,9 @@ const mergeOrAdd = (arr, obj, item) => {
if (oldItem) {
// We already have this, so only merge the new info.
- merge(oldItem, item)
+ // We ignore null values to avoid overwriting existing properties with missing data
+ // we also skip 'used' because that is handled by users module
+ merge(oldItem, omitBy(item, (v, k) => v === null || k === 'user'))
// Reactivity fix.
oldItem.attachments.splice(oldItem.attachments.length)
return {item: oldItem, new: false}
diff --git a/src/modules/users.js b/src/modules/users.js
index 4159964c..a81ed964 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -1,5 +1,5 @@
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
-import { compact, map, each, merge, find } from 'lodash'
+import { compact, map, each, merge, find, omitBy } from 'lodash'
import { set } from 'vue'
import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js'
import oauthApi from '../services/new_api/oauth'
@@ -11,7 +11,7 @@ export const mergeOrAdd = (arr, obj, item) => {
const oldItem = obj[item.id]
if (oldItem) {
// We already have this, so only merge the new info.
- merge(oldItem, item)
+ merge(oldItem, omitBy(item, _ => _ === null))
return { item: oldItem, new: false }
} else {
// This is a new item, prepare it
@@ -39,7 +39,7 @@ export const mutations = {
},
setCurrentUser (state, user) {
state.lastLoginName = user.screen_name
- state.currentUser = merge(state.currentUser || {}, user)
+ state.currentUser = merge(state.currentUser || {}, omitBy(user, _ => _ === null))
},
clearCurrentUser (state) {
state.currentUser = false
@@ -91,6 +91,16 @@ export const mutations = {
addNewUsers (state, users) {
each(users, (user) => mergeOrAdd(state.users, state.usersObject, user))
},
+ updateUserRelationship (state, relationships) {
+ relationships.forEach((relationship) => {
+ const user = state.usersObject[relationship.id]
+
+ user.follows_you = relationship.followed_by
+ user.following = relationship.following
+ user.muted = relationship.muting
+ user.statusnet_blocking = relationship.blocking
+ })
+ },
saveBlocks (state, blockIds) {
state.currentUser.blockIds = blockIds
},
@@ -98,11 +108,17 @@ export const mutations = {
state.currentUser.muteIds = muteIds
},
setUserForStatus (state, status) {
- status.user = state.usersObject[status.user.id]
+ // Not setting it again since it's already reactive if it has getters
+ if (!Object.getOwnPropertyDescriptor(status.user, 'id').get) {
+ status.user = state.usersObject[status.user.id]
+ }
},
setUserForNotification (state, notification) {
- notification.action.user = state.usersObject[notification.action.user.id]
- notification.from_profile = state.usersObject[notification.action.user.id]
+ // Not setting it again since it's already reactive if it has getters
+ if (!Object.getOwnPropertyDescriptor(notification.action.user, 'id').get) {
+ notification.action.user = state.usersObject[notification.action.user.id]
+ notification.from_profile = state.usersObject[notification.action.user.id]
+ }
},
setColor (state, { user: { id }, highlighted }) {
const user = state.usersObject[id]
@@ -149,6 +165,10 @@ const users = {
return store.rootState.api.backendInteractor.fetchUser({ id })
.then((user) => store.commit('addNewUsers', [user]))
},
+ fetchUserRelationship (store, id) {
+ return store.rootState.api.backendInteractor.fetchUserRelationship({ id })
+ .then((relationships) => store.commit('updateUserRelationship', relationships))
+ },
fetchBlocks (store) {
return store.rootState.api.backendInteractor.fetchBlocks()
.then((blocks) => {
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 2de87026..d512b120 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -33,7 +33,6 @@ const QVITTER_USER_NOTIFICATIONS_URL = '/api/qvitter/statuses/notifications.json
const QVITTER_USER_NOTIFICATIONS_READ_URL = '/api/qvitter/statuses/notifications/read.json'
const BLOCKING_URL = '/api/blocks/create.json'
const UNBLOCKING_URL = '/api/blocks/destroy.json'
-const USER_URL = '/api/users/show.json'
const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import'
const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account'
const CHANGE_PASSWORD_URL = '/api/pleroma/change_password'
@@ -43,6 +42,8 @@ const DENY_USER_URL = '/api/pleroma/friendships/deny'
const SUGGESTIONS_URL = '/api/v1/suggestions'
const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
+const MASTODON_USER_URL = '/api/v1/accounts/'
+const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships'
import { each, map } from 'lodash'
import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
@@ -243,7 +244,7 @@ const denyUser = ({id, credentials}) => {
}
const fetchUser = ({id, credentials}) => {
- let url = `${USER_URL}?user_id=${id}`
+ let url = `${MASTODON_USER_URL}/${id}`
return fetch(url, { headers: authHeaders(credentials) })
.then((response) => {
return new Promise((resolve, reject) => response.json()
@@ -257,6 +258,20 @@ const fetchUser = ({id, credentials}) => {
.then((data) => parseUser(data))
}
+const fetchUserRelationship = ({id, credentials}) => {
+ let url = `${MASTODON_USER_RELATIONSHIPS_URL}/?id=${id}`
+ return fetch(url, { headers: authHeaders(credentials) })
+ .then((response) => {
+ return new Promise((resolve, reject) => response.json()
+ .then((json) => {
+ if (!response.ok) {
+ return reject(new StatusCodeError(response.status, json, { url }, response))
+ }
+ return resolve(json)
+ }))
+ })
+}
+
const fetchFriends = ({id, page, credentials}) => {
let url = `${FRIENDS_URL}?user_id=${id}`
if (page) {
@@ -588,6 +603,7 @@ const apiService = {
blockUser,
unblockUser,
fetchUser,
+ fetchUserRelationship,
favorite,
unfavorite,
retweet,
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index 7e972d7b..cbd0b733 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -30,6 +30,10 @@ const backendInteractorService = (credentials) => {
return apiService.fetchUser({id, credentials})
}
+ const fetchUserRelationship = ({id}) => {
+ return apiService.fetchUserRelationship({id, credentials})
+ }
+
const followUser = (id) => {
return apiService.followUser({credentials, id})
}
@@ -92,6 +96,7 @@ const backendInteractorService = (credentials) => {
blockUser,
unblockUser,
fetchUser,
+ fetchUserRelationship,
fetchAllFollowing,
verifyCredentials: apiService.verifyCredentials,
startFetching,
--
cgit v1.2.3-70-g09d2
From 4f3a220487c3c8b3596e5a8de7b65cc7c4f0c981 Mon Sep 17 00:00:00 2001
From: Henry Jameson
Date: Fri, 8 Mar 2019 22:40:57 +0200
Subject: Since BE doesn't support fetching user by screen name over MastoAPI
we'll gonna just fetching it over QvitterAPI real quick :DDDDDDDDD
---
src/components/block_card/block_card.js | 2 +-
src/components/mute_card/mute_card.js | 2 +-
src/components/user_profile/user_profile.js | 63 +++++++++-------------
src/components/user_profile/user_profile.vue | 4 +-
src/modules/statuses.js | 1 +
src/modules/users.js | 12 ++---
src/services/api/api.service.js | 23 ++++++--
.../backend_interactor_service.js | 5 ++
test/unit/specs/components/user_profile.spec.js | 3 +-
test/unit/specs/modules/users.spec.js | 6 +--
10 files changed, 65 insertions(+), 56 deletions(-)
(limited to 'src/components')
diff --git a/src/components/block_card/block_card.js b/src/components/block_card/block_card.js
index 11fa27b4..c459ff1b 100644
--- a/src/components/block_card/block_card.js
+++ b/src/components/block_card/block_card.js
@@ -9,7 +9,7 @@ const BlockCard = {
},
computed: {
user () {
- return this.$store.getters.userById(this.userId)
+ return this.$store.getters.findUser(this.userId)
},
blocked () {
return this.user.statusnet_blocking
diff --git a/src/components/mute_card/mute_card.js b/src/components/mute_card/mute_card.js
index 5dd0a9e5..65c9cfb5 100644
--- a/src/components/mute_card/mute_card.js
+++ b/src/components/mute_card/mute_card.js
@@ -9,7 +9,7 @@ const MuteCard = {
},
computed: {
user () {
- return this.$store.getters.userById(this.userId)
+ return this.$store.getters.findUser(this.userId)
},
muted () {
return this.user.muted
diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js
index 345e7035..4f920ae2 100644
--- a/src/components/user_profile/user_profile.js
+++ b/src/components/user_profile/user_profile.js
@@ -9,7 +9,7 @@ import withList from '../../hocs/with_list/with_list'
const FollowerList = compose(
withLoadMore({
fetch: (props, $store) => $store.dispatch('addFollowers', props.userId),
- select: (props, $store) => get($store.getters.userById(props.userId), 'followers', []),
+ select: (props, $store) => get($store.getters.findUser(props.userId), 'followers', []),
destory: (props, $store) => $store.dispatch('clearFollowers', props.userId),
childPropName: 'entries',
additionalPropNames: ['userId']
@@ -20,7 +20,7 @@ const FollowerList = compose(
const FriendList = compose(
withLoadMore({
fetch: (props, $store) => $store.dispatch('addFriends', props.userId),
- select: (props, $store) => get($store.getters.userById(props.userId), 'friends', []),
+ select: (props, $store) => get($store.getters.findUser(props.userId), 'friends', []),
destory: (props, $store) => $store.dispatch('clearFriends', props.userId),
childPropName: 'entries',
additionalPropNames: ['userId']
@@ -31,19 +31,22 @@ const FriendList = compose(
const UserProfile = {
data () {
return {
- error: false
+ error: false,
+ fetchedUserId: null
}
},
created () {
- this.$store.commit('clearTimeline', { timeline: 'user' })
- this.$store.commit('clearTimeline', { timeline: 'favorites' })
- this.$store.commit('clearTimeline', { timeline: 'media' })
- this.$store.dispatch('startFetching', { timeline: 'user', userId: this.fetchBy })
- this.$store.dispatch('startFetching', { timeline: 'media', userId: this.fetchBy })
- this.startFetchFavorites()
if (!this.user.id) {
- this.$store.dispatch('fetchUser', this.fetchBy)
- .then(() => this.$store.dispatch('fetchUserRelationship', this.fetchBy))
+ let fetchPromise
+ if (this.userId) {
+ fetchPromise = this.$store.dispatch('fetchUser', this.userId)
+ } else {
+ fetchPromise = this.$store.dispatch('fetchUserByScreenName', this.userName)
+ .then(userId => {
+ this.fetchedUserId = userId
+ })
+ }
+ fetchPromise
.catch((reason) => {
const errorMessage = get(reason, 'error.error')
if (errorMessage === 'No user with such user_id') { // Known error
@@ -54,8 +57,7 @@ const UserProfile = {
this.error = this.$t('user_profile.profile_loading_error')
}
})
- } else if (typeof this.user.following === 'undefined' || this.user.following === null) {
- this.$store.dispatch('fetchUserRelationship', this.fetchBy)
+ .then(() => this.startUp())
}
},
destroyed () {
@@ -72,7 +74,7 @@ const UserProfile = {
return this.$store.state.statuses.timelines.media
},
userId () {
- return this.$route.params.id || this.user.id
+ return this.$route.params.id || this.user.id || this.fetchedUserId
},
userName () {
return this.$route.params.name || this.user.screen_name
@@ -82,10 +84,8 @@ const UserProfile = {
this.userId === this.$store.state.users.currentUser.id
},
userInStore () {
- if (this.isExternal) {
- return this.$store.getters.userById(this.userId)
- }
- return this.$store.getters.userByName(this.userName)
+ const routeParams = this.$route.params
+ return this.$store.getters.findUser(routeParams.name || routeParams.iid)
},
user () {
if (this.timeline.statuses[0]) {
@@ -96,9 +96,6 @@ const UserProfile = {
}
return {}
},
- fetchBy () {
- return this.isExternal ? this.userId : this.userName
- },
isExternal () {
return this.$route.name === 'external-user-profile'
},
@@ -112,13 +109,13 @@ const UserProfile = {
methods: {
startFetchFavorites () {
if (this.isUs) {
- this.$store.dispatch('startFetching', { timeline: 'favorites', userId: this.fetchBy })
+ this.$store.dispatch('startFetching', { timeline: 'favorites', userId: this.userId })
}
},
startUp () {
- this.$store.dispatch('startFetching', { timeline: 'user', userId: this.fetchBy })
- this.$store.dispatch('startFetching', { timeline: 'media', userId: this.fetchBy })
-
+ this.$store.dispatch('fetchUserRelationship', this.userId)
+ this.$store.dispatch('startFetching', { timeline: 'user', userId: this.userId })
+ this.$store.dispatch('startFetching', { timeline: 'media', userId: this.userId })
this.startFetchFavorites()
},
cleanUp () {
@@ -131,19 +128,11 @@ const UserProfile = {
}
},
watch: {
- userName () {
- if (this.isExternal) {
- return
- }
- this.cleanUp()
- this.startUp()
- },
- userId () {
- if (!this.isExternal) {
- return
+ userId (newVal, oldVal) {
+ if (newVal) {
+ this.cleanUp()
+ this.startUp()
}
- this.cleanUp()
- this.startUp()
},
$route () {
this.$refs.tabSwitcher.activateTab(0)()
diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue
index 7d4a8b1f..d449eb85 100644
--- a/src/components/user_profile/user_profile.vue
+++ b/src/components/user_profile/user_profile.vue
@@ -11,7 +11,7 @@
:title="$t('user_profile.timeline_title')"
:timeline="timeline"
:timeline-name="'user'"
- :user-id="fetchBy"
+ :user-id="userId"
/>
@@ -25,7 +25,7 @@
:embedded="true" :title="$t('user_card.media')"
timeline-name="media"
:timeline="media"
- :user-id="fetchBy"
+ :user-id="userId"
/>
id =>
- state.users.find(user => user.id === id),
- userByName: state => name =>
- state.users.find(user => user.screen_name &&
- (user.screen_name.toLowerCase() === name.toLowerCase())
- )
+ findUser: state => query => state.usersObject[query]
}
export const defaultState = {
@@ -165,6 +160,11 @@ const users = {
return store.rootState.api.backendInteractor.fetchUser({ id })
.then((user) => store.commit('addNewUsers', [user]))
},
+ fetchUserByScreenName (store, screenName) {
+ return store.rootState.api.backendInteractor.figureOutUserId({ screenName })
+ .then((qvitterUserData) => store.rootState.api.backendInteractor.fetchUser({ id: qvitterUserData.id }))
+ .then((user) => store.commit('addNewUsers', [user]) || user.id)
+ },
fetchUserRelationship (store, id) {
return store.rootState.api.backendInteractor.fetchUserRelationship({ id })
.then((relationships) => store.commit('updateUserRelationship', relationships))
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 744c2f64..5a0aa2de 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -32,6 +32,7 @@ const QVITTER_USER_NOTIFICATIONS_URL = '/api/qvitter/statuses/notifications.json
const QVITTER_USER_NOTIFICATIONS_READ_URL = '/api/qvitter/statuses/notifications/read.json'
const BLOCKING_URL = '/api/blocks/create.json'
const UNBLOCKING_URL = '/api/blocks/destroy.json'
+const USER_URL = '/api/users/show.json'
const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import'
const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account'
const CHANGE_PASSWORD_URL = '/api/pleroma/change_password'
@@ -41,7 +42,7 @@ const DENY_USER_URL = '/api/pleroma/friendships/deny'
const SUGGESTIONS_URL = '/api/v1/suggestions'
const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
-const MASTODON_USER_URL = '/api/v1/accounts/'
+const MASTODON_USER_URL = '/api/v1/accounts'
const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships'
const MASTODON_USER_TIMELINE_URL = id => `/api/v1/accounts/${id}/statuses`
@@ -272,6 +273,22 @@ const fetchUserRelationship = ({id, credentials}) => {
})
}
+// TODO remove once MastoAPI supports screen_name in fetchUser one
+const figureOutUserId = ({screenName, credentials}) => {
+ let url = `${USER_URL}/?user_id=${screenName}`
+ return fetch(url, { headers: authHeaders(credentials) })
+ .then((response) => {
+ return new Promise((resolve, reject) => response.json()
+ .then((json) => {
+ if (!response.ok) {
+ return reject(new StatusCodeError(response.status, json, { url }, response))
+ }
+ return resolve(json)
+ }))
+ })
+ .then((data) => parseUser(data))
+}
+
const fetchFriends = ({id, page, credentials}) => {
let url = `${FRIENDS_URL}?user_id=${id}`
if (page) {
@@ -382,9 +399,6 @@ const fetchTimeline = ({timeline, credentials, since = false, until = false, use
if (until) {
params.push(['max_id', until])
}
- if (userId) {
- params.push(['user_id', userId])
- }
if (tag) {
url += `/${tag}.json`
}
@@ -608,6 +622,7 @@ const apiService = {
unblockUser,
fetchUser,
fetchUserRelationship,
+ figureOutUserId,
favorite,
unfavorite,
retweet,
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index cbd0b733..48689167 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -26,6 +26,10 @@ const backendInteractorService = (credentials) => {
return apiService.fetchAllFollowing({username, credentials})
}
+ const figureOutUserId = ({screenName}) => {
+ return apiService.figureOutUserId({screenName, credentials})
+ }
+
const fetchUser = ({id}) => {
return apiService.fetchUser({id, credentials})
}
@@ -95,6 +99,7 @@ const backendInteractorService = (credentials) => {
unfollowUser,
blockUser,
unblockUser,
+ figureOutUserId,
fetchUser,
fetchUserRelationship,
fetchAllFollowing,
diff --git a/test/unit/specs/components/user_profile.spec.js b/test/unit/specs/components/user_profile.spec.js
index 41fd9cd0..1524c4eb 100644
--- a/test/unit/specs/components/user_profile.spec.js
+++ b/test/unit/specs/components/user_profile.spec.js
@@ -13,8 +13,7 @@ const mutations = {
}
const testGetters = {
- userByName: state => getters.userByName(state.users),
- userById: state => getters.userById(state.users)
+ findUser: state => getters.findUser(state.users)
}
const localUser = {
diff --git a/test/unit/specs/modules/users.spec.js b/test/unit/specs/modules/users.spec.js
index 4d49ee24..dae7e580 100644
--- a/test/unit/specs/modules/users.spec.js
+++ b/test/unit/specs/modules/users.spec.js
@@ -43,7 +43,7 @@ describe('The users module', () => {
}
const name = 'Guy'
const expected = { screen_name: 'Guy', id: '1' }
- expect(getters.userByName(state)(name)).to.eql(expected)
+ expect(getters.findUser(state)(name)).to.eql(expected)
})
it('returns user with matching screen_name with different case', () => {
@@ -54,7 +54,7 @@ describe('The users module', () => {
}
const name = 'Guy'
const expected = { screen_name: 'guy', id: '1' }
- expect(getters.userByName(state)(name)).to.eql(expected)
+ expect(getters.findUser(state)(name)).to.eql(expected)
})
})
@@ -67,7 +67,7 @@ describe('The users module', () => {
}
const id = '1'
const expected = { screen_name: 'Guy', id: '1' }
- expect(getters.userById(state)(id)).to.eql(expected)
+ expect(getters.findUser(state)(id)).to.eql(expected)
})
})
})
--
cgit v1.2.3-70-g09d2
From 690c1dcd7ac09f3e6cd4ba5778dce5bd360ee68e Mon Sep 17 00:00:00 2001
From: Henry Jameson
Date: Sat, 9 Mar 2019 01:19:56 +0200
Subject: revert some stuff, turns out it's actually breaking. Fixed some local
user things
---
src/components/user_profile/user_profile.js | 53 +++++++++++++++++------------
src/modules/users.js | 12 ++-----
2 files changed, 34 insertions(+), 31 deletions(-)
(limited to 'src/components')
diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js
index 4f920ae2..0f387f66 100644
--- a/src/components/user_profile/user_profile.js
+++ b/src/components/user_profile/user_profile.js
@@ -37,27 +37,7 @@ const UserProfile = {
},
created () {
if (!this.user.id) {
- let fetchPromise
- if (this.userId) {
- fetchPromise = this.$store.dispatch('fetchUser', this.userId)
- } else {
- fetchPromise = this.$store.dispatch('fetchUserByScreenName', this.userName)
- .then(userId => {
- this.fetchedUserId = userId
- })
- }
- fetchPromise
- .catch((reason) => {
- const errorMessage = get(reason, 'error.error')
- if (errorMessage === 'No user with such user_id') { // Known error
- this.error = this.$t('user_profile.profile_does_not_exist')
- } else if (errorMessage) {
- this.error = errorMessage
- } else {
- this.error = this.$t('user_profile.profile_loading_error')
- }
- })
- .then(() => this.startUp())
+ this.fetchUserId()
}
},
destroyed () {
@@ -112,8 +92,30 @@ const UserProfile = {
this.$store.dispatch('startFetching', { timeline: 'favorites', userId: this.userId })
}
},
+ fetchUserId () {
+ let fetchPromise
+ if (this.userId && !this.$route.params.name) {
+ fetchPromise = this.$store.dispatch('fetchUser', this.userId)
+ } else {
+ fetchPromise = this.$store.dispatch('fetchUserByScreenName', this.userName)
+ .then(userId => {
+ this.fetchedUserId = userId
+ })
+ }
+ fetchPromise
+ .catch((reason) => {
+ const errorMessage = get(reason, 'error.error')
+ if (errorMessage === 'No user with such user_id') { // Known error
+ this.error = this.$t('user_profile.profile_does_not_exist')
+ } else if (errorMessage) {
+ this.error = errorMessage
+ } else {
+ this.error = this.$t('user_profile.profile_loading_error')
+ }
+ })
+ .then(() => this.startUp())
+ },
startUp () {
- this.$store.dispatch('fetchUserRelationship', this.userId)
this.$store.dispatch('startFetching', { timeline: 'user', userId: this.userId })
this.$store.dispatch('startFetching', { timeline: 'media', userId: this.userId })
this.startFetchFavorites()
@@ -134,6 +136,13 @@ const UserProfile = {
this.startUp()
}
},
+ userName (newVal, oldVal) {
+ if (this.$route.params.name) {
+ this.fetchUserId()
+ this.cleanUp()
+ this.startUp()
+ }
+ },
$route () {
this.$refs.tabSwitcher.activateTab(0)()
}
diff --git a/src/modules/users.js b/src/modules/users.js
index 4e17ebf2..e4146c31 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -108,17 +108,11 @@ export const mutations = {
state.currentUser.muteIds = muteIds
},
setUserForStatus (state, status) {
- // Not setting it again since it's already reactive if it has getters
- if (!Object.getOwnPropertyDescriptor(status.user, 'id').get) {
- status.user = state.usersObject[status.user.id]
- }
+ status.user = state.usersObject[status.user.id]
},
setUserForNotification (state, notification) {
- // Not setting it again since it's already reactive if it has getters
- if (!Object.getOwnPropertyDescriptor(notification.action.user, 'id').get) {
- notification.action.user = state.usersObject[notification.action.user.id]
- notification.from_profile = state.usersObject[notification.action.user.id]
- }
+ notification.action.user = state.usersObject[notification.action.user.id]
+ notification.from_profile = state.usersObject[notification.action.user.id]
},
setColor (state, { user: { id }, highlighted }) {
const user = state.usersObject[id]
--
cgit v1.2.3-70-g09d2
From fe624f6114220320e1528981af83fb7ab39c0e67 Mon Sep 17 00:00:00 2001
From: Henry Jameson
Date: Sat, 9 Mar 2019 01:34:15 +0200
Subject: fix reply-to marker, also whoops console log
---
src/components/status/status.js | 8 ++++----
src/modules/statuses.js | 1 -
2 files changed, 4 insertions(+), 5 deletions(-)
(limited to 'src/components')
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 9e18fe15..43572fe8 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -145,11 +145,11 @@ const Status = {
return !!(this.status.in_reply_to_status_id && this.status.in_reply_to_user_id)
},
replyToName () {
- const user = this.$store.state.users.usersObject[this.status.in_reply_to_user_id]
- if (user) {
- return user.screen_name
- } else {
+ const user = this.$store.getters.findUser(this.status.in_reply_to_user_id)
+ if (this.status.in_reply_to_screen_name) {
return this.status.in_reply_to_screen_name
+ } else {
+ return user.screen_name
}
},
hideReply () {
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 4ee75d48..2b0215f0 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -135,7 +135,6 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
// This makes sure that user timeline won't get data meant for other
// user. I.e. opening different user profiles makes request which could
// return data late after user already viewing different user profile
- console.log('TIMEINLINE', timelineObject.userId)
if ((timeline === 'user' || timeline === 'media') && timelineObject.userId !== userId) {
return
}
--
cgit v1.2.3-70-g09d2
From a02a74e9b9b999cd6c640c541dfbfcff3b2ebd9a Mon Sep 17 00:00:00 2001
From: Henry Jameson
Date: Sat, 9 Mar 2019 01:36:35 +0200
Subject: attempt at fixing switching to user TL
---
src/components/status/status.js | 4 ++--
src/components/user_profile/user_profile.js | 11 ++++++++---
2 files changed, 10 insertions(+), 5 deletions(-)
(limited to 'src/components')
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 43572fe8..c90da6d4 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -145,11 +145,11 @@ const Status = {
return !!(this.status.in_reply_to_status_id && this.status.in_reply_to_user_id)
},
replyToName () {
- const user = this.$store.getters.findUser(this.status.in_reply_to_user_id)
if (this.status.in_reply_to_screen_name) {
return this.status.in_reply_to_screen_name
} else {
- return user.screen_name
+ const user = this.$store.getters.findUser(this.status.in_reply_to_user_id)
+ return user && user.screen_name
}
},
hideReply () {
diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js
index 0f387f66..dc9cdeeb 100644
--- a/src/components/user_profile/user_profile.js
+++ b/src/components/user_profile/user_profile.js
@@ -38,6 +38,9 @@ const UserProfile = {
created () {
if (!this.user.id) {
this.fetchUserId()
+ .then(() => this.startUp())
+ } else {
+ this.startUp()
}
},
destroyed () {
@@ -116,9 +119,11 @@ const UserProfile = {
.then(() => this.startUp())
},
startUp () {
- this.$store.dispatch('startFetching', { timeline: 'user', userId: this.userId })
- this.$store.dispatch('startFetching', { timeline: 'media', userId: this.userId })
- this.startFetchFavorites()
+ if (this.userId) {
+ this.$store.dispatch('startFetching', { timeline: 'user', userId: this.userId })
+ this.$store.dispatch('startFetching', { timeline: 'media', userId: this.userId })
+ this.startFetchFavorites()
+ }
},
cleanUp () {
this.$store.dispatch('stopFetching', 'user')
--
cgit v1.2.3-70-g09d2
From 489f840d84b0057cf9ddddcb8dc594bfc5ad628f Mon Sep 17 00:00:00 2001
From: Henry Jameson
Date: Sat, 9 Mar 2019 11:54:11 +0200
Subject: fix error
---
src/components/user_profile/user_profile.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src/components')
diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js
index dc9cdeeb..2d186bc5 100644
--- a/src/components/user_profile/user_profile.js
+++ b/src/components/user_profile/user_profile.js
@@ -105,7 +105,7 @@ const UserProfile = {
this.fetchedUserId = userId
})
}
- fetchPromise
+ return fetchPromise
.catch((reason) => {
const errorMessage = get(reason, 'error.error')
if (errorMessage === 'No user with such user_id') { // Known error
--
cgit v1.2.3-70-g09d2
From 49b0f0a04a74039a1b82fbde731828e599123e93 Mon Sep 17 00:00:00 2001
From: Henry Jameson
Date: Sat, 9 Mar 2019 18:33:49 +0200
Subject: Fetching convos via MastoAPI. Had to change conversation component a
bit for better support, since MastoAPI doesn't have coversation ids
---
src/components/conversation/conversation.js | 23 ++++++++++---------
src/services/api/api.service.js | 35 +++++++++++++++++++----------
2 files changed, 35 insertions(+), 23 deletions(-)
(limited to 'src/components')
diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
index 48b8aaaa..fd4303ca 100644
--- a/src/components/conversation/conversation.js
+++ b/src/components/conversation/conversation.js
@@ -25,7 +25,8 @@ const sortAndFilterConversation = (conversation) => {
const conversation = {
data () {
return {
- highlight: null
+ highlight: null,
+ relevantIds: []
}
},
props: [
@@ -48,9 +49,11 @@ const conversation = {
return []
}
- const conversationId = this.status.statusnet_conversation_id
- const statuses = this.$store.state.statuses.allStatuses
- const conversation = filter(statuses, { statusnet_conversation_id: conversationId })
+ const statusesObject = this.$store.state.statuses.allStatusesObject
+ const conversation = this.relevantIds.reduce((acc, id) => {
+ acc.push(statusesObject[id])
+ return acc
+ }, [])
return sortAndFilterConversation(conversation)
},
replies () {
@@ -83,15 +86,13 @@ const conversation = {
methods: {
fetchConversation () {
if (this.status) {
- const conversationId = this.status.statusnet_conversation_id
+ const conversationId = this.status.id
this.$store.state.api.backendInteractor.fetchConversation({id: conversationId})
- .then((statuses) => this.$store.dispatch('addNewStatuses', { statuses }))
+ .then((statuses) => {
+ this.$store.dispatch('addNewStatuses', { statuses })
+ statuses.forEach(status => this.relevantIds.push(status.id))
+ })
.then(() => this.setHighlight(this.statusId))
- } else {
- const id = this.$route.params.id
- this.$store.state.api.backendInteractor.fetchStatus({id})
- .then((status) => this.$store.dispatch('addNewStatuses', { statuses: [status] }))
- .then(() => this.fetchConversation())
}
},
getReplies (id) {
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 2de87026..a273f32e 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -11,9 +11,7 @@ const RETWEET_URL = '/api/statuses/retweet'
const UNRETWEET_URL = '/api/statuses/unretweet'
const STATUS_UPDATE_URL = '/api/statuses/update.json'
const STATUS_DELETE_URL = '/api/statuses/destroy'
-const STATUS_URL = '/api/statuses/show'
const MEDIA_UPLOAD_URL = '/api/statusnet/media/upload'
-const CONVERSATION_URL = '/api/statusnet/conversation'
const MENTIONS_URL = '/api/statuses/mentions.json'
const DM_TIMELINE_URL = '/api/statuses/dm_timeline.json'
const FOLLOWERS_URL = '/api/statuses/followers.json'
@@ -43,6 +41,8 @@ const DENY_USER_URL = '/api/pleroma/friendships/deny'
const SUGGESTIONS_URL = '/api/v1/suggestions'
const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
+const MASTODON_STATUS_URL = id => `/api/v1/statuses/${id}`
+const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context`
import { each, map } from 'lodash'
import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
@@ -298,20 +298,31 @@ const fetchFollowRequests = ({credentials}) => {
}
const fetchConversation = ({id, credentials}) => {
- let url = `${CONVERSATION_URL}/${id}.json?count=100`
- return fetch(url, { headers: authHeaders(credentials) })
- .then((data) => {
- if (data.ok) {
- return data
- }
- throw new Error('Error fetching timeline', data)
- })
- .then((data) => data.json())
+ let url = MASTODON_STATUS_URL(id)
+ let urlContext = MASTODON_STATUS_CONTEXT_URL(id)
+ return Promise.all([
+ fetch(url, { headers: authHeaders(credentials) })
+ .then((data) => {
+ if (data.ok) {
+ return data
+ }
+ throw new Error('Error fetching timeline', data)
+ })
+ .then((data) => data.json()),
+ fetch(urlContext, { headers: authHeaders(credentials) })
+ .then((data) => {
+ if (data.ok) {
+ return data
+ }
+ throw new Error('Error fetching timeline', data)
+ })
+ .then((data) => data.json())])
+ .then(([status, context]) => [...context.ancestors, status, ...context.descendants])
.then((data) => data.map(parseStatus))
}
const fetchStatus = ({id, credentials}) => {
- let url = `${STATUS_URL}/${id}.json`
+ let url = MASTODON_STATUS_URL(id)
return fetch(url, { headers: authHeaders(credentials) })
.then((data) => {
if (data.ok) {
--
cgit v1.2.3-70-g09d2
From 068c9724e45fe801ecedbea491234d0b95695629 Mon Sep 17 00:00:00 2001
From: Edijs
Date: Sun, 10 Mar 2019 16:58:12 -0700
Subject: Added new tab to display versions of BE/FE
---
src/boot/after_store.js | 6 ++++++
src/components/settings/settings.js | 17 +++++++++++++++--
src/components/settings/settings.vue | 22 ++++++++++++++++++++++
src/i18n/en.json | 5 +++++
src/modules/instance.js | 6 +++++-
src/services/version/version.service.js | 10 ++++++++++
6 files changed, 63 insertions(+), 3 deletions(-)
create mode 100644 src/services/version/version.service.js
(limited to 'src/components')
diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index a8e2bf35..dfaf4d68 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -176,6 +176,12 @@ const afterStoreSetup = ({ store, i18n }) => {
const suggestions = metadata.suggestions
store.dispatch('setInstanceOption', { name: 'suggestionsEnabled', value: suggestions.enabled })
store.dispatch('setInstanceOption', { name: 'suggestionsWeb', value: suggestions.web })
+
+ const software = data.software
+ store.dispatch('setInstanceOption', { name: 'backendVersion', value: software.version })
+
+ const frontendVersion = window.___pleromafe_commit_hash
+ store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion })
})
}
diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js
index 979457a5..d208ee5a 100644
--- a/src/components/settings/settings.js
+++ b/src/components/settings/settings.js
@@ -1,8 +1,10 @@
/* eslint-env browser */
+import { filter, trim } from 'lodash'
+
import TabSwitcher from '../tab_switcher/tab_switcher.js'
import StyleSwitcher from '../style_switcher/style_switcher.vue'
import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
-import { filter, trim } from 'lodash'
+import { parseBackendVersionString, parseFrontendVersionString } from '../../services/version/version.service'
const settings = {
data () {
@@ -78,7 +80,10 @@ const settings = {
// Future spec, still not supported in Nightly 63 as of 08/2018
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks'),
playVideosInModal: user.playVideosInModal,
- useContainFit: user.useContainFit
+ useContainFit: user.useContainFit,
+
+ backendVersion: instance.backendVersion,
+ frontendVersion: instance.frontendVersion
}
},
components: {
@@ -98,6 +103,14 @@ const settings = {
},
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel }
},
+ methods: {
+ parseBackendVersion (versionString) {
+ return parseBackendVersionString(versionString)
+ },
+ parseFrontendVersion (versionString) {
+ return parseFrontendVersionString(versionString)
+ }
+ },
watch: {
hideAttachmentsLocal (value) {
this.$store.dispatch('setOption', { name: 'hideAttachments', value })
diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index d2346747..3ca7bdc0 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -261,6 +261,28 @@
+