commit: 88a3cf8705f925c31b5fad67d0fb709a51447156
parent 8e97a40c700797819bf92c61398daff230404228
Author: HJ <30-hj@users.noreply.git.pleroma.social>
Date: Mon, 22 Aug 2022 21:56:55 +0000
Merge branch 'from/develop/tusooa/user-profile-routes' into 'develop'
Stop generating /:nickname user profile routes
See merge request pleroma/pleroma-fe!1589
Diffstat:
6 files changed, 94 insertions(+), 23 deletions(-)
diff --git a/src/boot/routes.js b/src/boot/routes.js
@@ -61,7 +61,7 @@ export default (store) => {
component: RemoteUserResolver,
beforeEnter: validateAuthenticatedRoute
},
- { name: 'external-user-profile', path: '/users/:id', component: UserProfile },
+ { name: 'external-user-profile', path: '/users/$:id', component: UserProfile },
{ name: 'interactions', path: '/users/:username/interactions', component: Interactions, beforeEnter: validateAuthenticatedRoute },
{ name: 'dms', path: '/users/:username/dms', component: DMs, beforeEnter: validateAuthenticatedRoute },
{ name: 'registration', path: '/registration', component: Registration },
@@ -75,7 +75,8 @@ export default (store) => {
{ name: 'search', path: '/search', component: Search, props: (route) => ({ query: route.query.query }) },
{ name: 'who-to-follow', path: '/who-to-follow', component: WhoToFollow, beforeEnter: validateAuthenticatedRoute },
{ name: 'about', path: '/about', component: About },
- { name: 'user-profile', path: '/:_(users)?/:name', component: UserProfile },
+ { name: 'user-profile', path: '/users/:name', component: UserProfile },
+ { name: 'legacy-user-profile', path: '/:name', component: UserProfile },
{ name: 'lists', path: '/lists', component: Lists },
{ name: 'lists-timeline', path: '/lists/:id', component: ListsTimeline },
{ name: 'lists-edit', path: '/lists/:id/edit', component: ListsEdit }
diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js
@@ -45,7 +45,7 @@ const UserProfile = {
},
created () {
const routeParams = this.$route.params
- this.load(routeParams.name || routeParams.id)
+ this.load({ name: routeParams.name, id: routeParams.id })
this.tab = get(this.$route, 'query.tab', defaultTabKey)
},
unmounted () {
@@ -106,12 +106,17 @@ const UserProfile = {
this.userId = null
this.error = false
+ const maybeId = userNameOrId.id
+ const maybeName = userNameOrId.name
+
// Check if user data is already loaded in store
- const user = this.$store.getters.findUser(userNameOrId)
+ const user = maybeId ? this.$store.getters.findUser(maybeId) : this.$store.getters.findUserByName(maybeName)
if (user) {
loadById(user.id)
} else {
- this.$store.dispatch('fetchUser', userNameOrId)
+ (maybeId
+ ? this.$store.dispatch('fetchUser', maybeId)
+ : this.$store.dispatch('fetchUserByName', maybeName))
.then(({ id }) => loadById(id))
.catch((reason) => {
const errorMessage = get(reason, 'error.error')
@@ -150,12 +155,12 @@ const UserProfile = {
watch: {
'$route.params.id': function (newVal) {
if (newVal) {
- this.switchUser(newVal)
+ this.switchUser({ id: newVal })
}
},
'$route.params.name': function (newVal) {
if (newVal) {
- this.switchUser(newVal)
+ this.switchUser({ name: newVal })
}
},
'$route.query': function (newVal) {
diff --git a/src/modules/users.js b/src/modules/users.js
@@ -16,9 +16,6 @@ export const mergeOrAdd = (arr, obj, item) => {
// This is a new item, prepare it
arr.push(item)
obj[item.id] = item
- if (item.screen_name && !item.screen_name.includes('@')) {
- obj[item.screen_name.toLowerCase()] = item
- }
return { item, new: true }
}
}
@@ -162,7 +159,11 @@ export const mutations = {
if (user.relationship) {
state.relationships[user.relationship.id] = user.relationship
}
- mergeOrAdd(state.users, state.usersObject, user)
+ const res = mergeOrAdd(state.users, state.usersObject, user)
+ const item = res.item
+ if (res.new && item.screen_name && !item.screen_name.includes('@')) {
+ state.usersByNameObject[item.screen_name.toLowerCase()] = item
+ }
})
},
updateUserRelationship (state, relationships) {
@@ -239,12 +240,10 @@ export const mutations = {
export const getters = {
findUser: state => query => {
- const result = state.usersObject[query]
- // In case it's a screen_name, we can try searching case-insensitive
- if (!result && typeof query === 'string') {
- return state.usersObject[query.toLowerCase()]
- }
- return result
+ return state.usersObject[query]
+ },
+ findUserByName: state => query => {
+ return state.usersByNameObject[query.toLowerCase()]
},
findUserByUrl: state => query => {
return state.users
@@ -263,6 +262,7 @@ export const defaultState = {
currentUser: false,
users: [],
usersObject: {},
+ usersByNameObject: {},
signUpPending: false,
signUpErrors: [],
relationships: {}
@@ -285,6 +285,13 @@ const users = {
return user
})
},
+ fetchUserByName (store, name) {
+ return store.rootState.api.backendInteractor.fetchUserByName({ name })
+ .then((user) => {
+ store.commit('addNewUsers', [user])
+ return user
+ })
+ },
fetchUserRelationship (store, id) {
if (store.state.currentUser) {
store.rootState.api.backendInteractor.fetchUserRelationship({ id })
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
@@ -50,6 +50,7 @@ const MASTODON_USER_HOME_TIMELINE_URL = '/api/v1/timelines/home'
const MASTODON_STATUS_URL = id => `/api/v1/statuses/${id}`
const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context`
const MASTODON_USER_URL = '/api/v1/accounts'
+const MASTODON_USER_LOOKUP_URL = '/api/v1/accounts/lookup'
const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships'
const MASTODON_USER_TIMELINE_URL = id => `/api/v1/accounts/${id}/statuses`
const MASTODON_LIST_URL = id => `/api/v1/lists/${id}`
@@ -318,6 +319,25 @@ const fetchUser = ({ id, credentials }) => {
.then((data) => parseUser(data))
}
+const fetchUserByName = ({ name, credentials }) => {
+ return promisedRequest({
+ url: MASTODON_USER_LOOKUP_URL,
+ credentials,
+ params: { acct: name }
+ })
+ .then(data => data.id)
+ .catch(error => {
+ if (error && error.statusCode === 404) {
+ // Either the backend does not support lookup endpoint,
+ // or there is no user with such name. Fallback and treat name as id.
+ return name
+ } else {
+ throw error
+ }
+ })
+ .then(id => fetchUser({ id, credentials }))
+}
+
const fetchUserRelationship = ({ id, credentials }) => {
const url = `${MASTODON_USER_RELATIONSHIPS_URL}/?id=${id}`
return fetch(url, { headers: authHeaders(credentials) })
@@ -1481,6 +1501,7 @@ const apiService = {
blockUser,
unblockUser,
fetchUser,
+ fetchUserByName,
fetchUserRelationship,
favorite,
unfavorite,
diff --git a/test/unit/specs/components/user_profile.spec.js b/test/unit/specs/components/user_profile.spec.js
@@ -15,6 +15,7 @@ const actions = {
const testGetters = {
findUser: state => getters.findUser(state.users),
+ findUserByName: state => getters.findUserByName(state.users),
relationship: state => getters.relationship(state.users),
mergedConfig: state => ({
colors: '',
@@ -95,6 +96,7 @@ const externalProfileStore = createStore({
credentials: ''
},
usersObject: { 100: extUser },
+ usersByNameObject: {},
users: [extUser],
relationships: {}
}
@@ -163,7 +165,8 @@ const localProfileStore = createStore({
currentUser: {
credentials: ''
},
- usersObject: { 100: localUser, testuser: localUser },
+ usersObject: { 100: localUser },
+ usersByNameObject: { testuser: localUser },
users: [localUser],
relationships: {}
}
diff --git a/test/unit/specs/modules/users.spec.js b/test/unit/specs/modules/users.spec.js
@@ -57,24 +57,27 @@ describe('The users module', () => {
})
describe('findUser', () => {
- it('returns user with matching screen_name', () => {
+ it('does not return user with matching screen_name', () => {
const user = { screen_name: 'Guy', id: '1' }
const state = {
usersObject: {
- 1: user,
+ 1: user
+ },
+ usersByNameObject: {
guy: user
}
}
const name = 'Guy'
- const expected = { screen_name: 'Guy', id: '1' }
- expect(getters.findUser(state)(name)).to.eql(expected)
+ expect(getters.findUser(state)(name)).to.eql(undefined)
})
it('returns user with matching id', () => {
const user = { screen_name: 'Guy', id: '1' }
const state = {
usersObject: {
- 1: user,
+ 1: user
+ },
+ usersByNameObject: {
guy: user
}
}
@@ -83,4 +86,35 @@ describe('The users module', () => {
expect(getters.findUser(state)(id)).to.eql(expected)
})
})
+
+ describe('findUserByName', () => {
+ it('returns user with matching screen_name', () => {
+ const user = { screen_name: 'Guy', id: '1' }
+ const state = {
+ usersObject: {
+ 1: user
+ },
+ usersByNameObject: {
+ guy: user
+ }
+ }
+ const name = 'Guy'
+ const expected = { screen_name: 'Guy', id: '1' }
+ expect(getters.findUserByName(state)(name)).to.eql(expected)
+ })
+
+ it('does not return user with matching id', () => {
+ const user = { screen_name: 'Guy', id: '1' }
+ const state = {
+ usersObject: {
+ 1: user
+ },
+ usersByNameObject: {
+ guy: user
+ }
+ }
+ const id = '1'
+ expect(getters.findUserByName(state)(id)).to.eql(undefined)
+ })
+ })
})