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
This commit is contained in:
Henry Jameson 2019-03-08 00:35:30 +02:00
parent 09736691ea
commit ee49409049
6 changed files with 59 additions and 10 deletions

View file

@ -15,6 +15,9 @@ export default {
betterShadow: this.$store.state.interface.browserSupport.cssFilter betterShadow: this.$store.state.interface.browserSupport.cssFilter
} }
}, },
created () {
this.$store.dispatch('fetchUserRelationship', this.user.id)
},
computed: { computed: {
classes () { classes () {
return [{ return [{

View file

@ -43,6 +43,7 @@ const UserProfile = {
this.startFetchFavorites() this.startFetchFavorites()
if (!this.user.id) { if (!this.user.id) {
this.$store.dispatch('fetchUser', this.fetchBy) this.$store.dispatch('fetchUser', this.fetchBy)
.then(() => this.$store.dispatch('fetchUserRelationship', this.fetchBy))
.catch((reason) => { .catch((reason) => {
const errorMessage = get(reason, 'error.error') const errorMessage = get(reason, 'error.error')
if (errorMessage === 'No user with such user_id') { // Known 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') 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 () { destroyed () {

View file

@ -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 apiService from '../services/api/api.service.js'
// import parse from '../services/status_parser/status_parser.js' // import parse from '../services/status_parser/status_parser.js'
@ -72,7 +72,9 @@ const mergeOrAdd = (arr, obj, item) => {
if (oldItem) { if (oldItem) {
// We already have this, so only merge the new info. // 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. // Reactivity fix.
oldItem.attachments.splice(oldItem.attachments.length) oldItem.attachments.splice(oldItem.attachments.length)
return {item: oldItem, new: false} return {item: oldItem, new: false}

View file

@ -1,5 +1,5 @@
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js' 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 { set } from 'vue'
import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js' import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js'
import oauthApi from '../services/new_api/oauth' import oauthApi from '../services/new_api/oauth'
@ -11,7 +11,7 @@ export const mergeOrAdd = (arr, obj, item) => {
const oldItem = obj[item.id] const oldItem = obj[item.id]
if (oldItem) { if (oldItem) {
// We already have this, so only merge the new info. // We already have this, so only merge the new info.
merge(oldItem, item) merge(oldItem, omitBy(item, _ => _ === null))
return { item: oldItem, new: false } return { item: oldItem, new: false }
} else { } else {
// This is a new item, prepare it // This is a new item, prepare it
@ -39,7 +39,7 @@ export const mutations = {
}, },
setCurrentUser (state, user) { setCurrentUser (state, user) {
state.lastLoginName = user.screen_name state.lastLoginName = user.screen_name
state.currentUser = merge(state.currentUser || {}, user) state.currentUser = merge(state.currentUser || {}, omitBy(user, _ => _ === null))
}, },
clearCurrentUser (state) { clearCurrentUser (state) {
state.currentUser = false state.currentUser = false
@ -91,6 +91,16 @@ export const mutations = {
addNewUsers (state, users) { addNewUsers (state, users) {
each(users, (user) => mergeOrAdd(state.users, state.usersObject, user)) 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) { saveBlocks (state, blockIds) {
state.currentUser.blockIds = blockIds state.currentUser.blockIds = blockIds
}, },
@ -98,11 +108,17 @@ export const mutations = {
state.currentUser.muteIds = muteIds state.currentUser.muteIds = muteIds
}, },
setUserForStatus (state, status) { 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) { setUserForNotification (state, notification) {
notification.action.user = state.usersObject[notification.action.user.id] // Not setting it again since it's already reactive if it has getters
notification.from_profile = state.usersObject[notification.action.user.id] 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 }) { setColor (state, { user: { id }, highlighted }) {
const user = state.usersObject[id] const user = state.usersObject[id]
@ -149,6 +165,10 @@ const users = {
return store.rootState.api.backendInteractor.fetchUser({ id }) return store.rootState.api.backendInteractor.fetchUser({ id })
.then((user) => store.commit('addNewUsers', [user])) .then((user) => store.commit('addNewUsers', [user]))
}, },
fetchUserRelationship (store, id) {
return store.rootState.api.backendInteractor.fetchUserRelationship({ id })
.then((relationships) => store.commit('updateUserRelationship', relationships))
},
fetchBlocks (store) { fetchBlocks (store) {
return store.rootState.api.backendInteractor.fetchBlocks() return store.rootState.api.backendInteractor.fetchBlocks()
.then((blocks) => { .then((blocks) => {

View file

@ -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 QVITTER_USER_NOTIFICATIONS_READ_URL = '/api/qvitter/statuses/notifications/read.json'
const BLOCKING_URL = '/api/blocks/create.json' const BLOCKING_URL = '/api/blocks/create.json'
const UNBLOCKING_URL = '/api/blocks/destroy.json' const UNBLOCKING_URL = '/api/blocks/destroy.json'
const USER_URL = '/api/users/show.json'
const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import' const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import'
const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account' const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account'
const CHANGE_PASSWORD_URL = '/api/pleroma/change_password' 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 SUGGESTIONS_URL = '/api/v1/suggestions'
const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites' 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 { each, map } from 'lodash'
import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js' import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js'
@ -243,7 +244,7 @@ const denyUser = ({id, credentials}) => {
} }
const fetchUser = ({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) }) return fetch(url, { headers: authHeaders(credentials) })
.then((response) => { .then((response) => {
return new Promise((resolve, reject) => response.json() return new Promise((resolve, reject) => response.json()
@ -257,6 +258,20 @@ const fetchUser = ({id, credentials}) => {
.then((data) => parseUser(data)) .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}) => { const fetchFriends = ({id, page, credentials}) => {
let url = `${FRIENDS_URL}?user_id=${id}` let url = `${FRIENDS_URL}?user_id=${id}`
if (page) { if (page) {
@ -588,6 +603,7 @@ const apiService = {
blockUser, blockUser,
unblockUser, unblockUser,
fetchUser, fetchUser,
fetchUserRelationship,
favorite, favorite,
unfavorite, unfavorite,
retweet, retweet,

View file

@ -30,6 +30,10 @@ const backendInteractorService = (credentials) => {
return apiService.fetchUser({id, credentials}) return apiService.fetchUser({id, credentials})
} }
const fetchUserRelationship = ({id}) => {
return apiService.fetchUserRelationship({id, credentials})
}
const followUser = (id) => { const followUser = (id) => {
return apiService.followUser({credentials, id}) return apiService.followUser({credentials, id})
} }
@ -92,6 +96,7 @@ const backendInteractorService = (credentials) => {
blockUser, blockUser,
unblockUser, unblockUser,
fetchUser, fetchUser,
fetchUserRelationship,
fetchAllFollowing, fetchAllFollowing,
verifyCredentials: apiService.verifyCredentials, verifyCredentials: apiService.verifyCredentials,
startFetching, startFetching,