Merge pull request #661 from h3poteto/iss-657

closes #657 Show follow/unfollow button in follow/followers tab in profile
This commit is contained in:
AkiraFukushima 2018-10-16 08:30:55 +09:00 committed by GitHub
commit 3bbe228bdd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 196 additions and 48 deletions

View File

@ -16,6 +16,17 @@
<icon name="times"></icon>
</el-button>
</div>
<div class="tool" v-if="relationship">
<el-button v-if="relationship.following" class="unfollow" type="text" @click.stop.prevent="unfollowAccount(user)" :title="$t('side_bar.account_profile.unfollow')">
<icon name="user-times"></icon>
</el-button>
<el-button v-else-if="relationship.requested" class="requested" type="text" :title="$t('side_bar.account_profile.follow_requested')">
<icon name="hourglass"></icon>
</el-button>
<el-button v-else-if="!relationship.following" class="follow" type="text" @click.stop.prevent="followAccount(user)" :title="$t('side_bar.account_profile.follow')">
<icon name="user-plus"></icon>
</el-button>
</div>
</div>
</div>
</template>
@ -31,6 +42,10 @@ export default {
remove: {
type: Boolean,
default: false
},
relationship: {
type: Object,
default: null
}
},
methods: {
@ -48,6 +63,12 @@ export default {
},
removeAccount (account) {
this.$emit('removeAccount', account)
},
unfollowAccount (account) {
this.$emit('unfollowAccount', account)
},
followAccount (account) {
this.$emit('followAccount', account)
}
}
}
@ -74,6 +95,7 @@ export default {
.name {
display: inline-block;
padding-left: 8px;
overflow: hidden;
.acct {
color: #909399;
@ -87,6 +109,18 @@ export default {
.tool {
margin-left: auto;
.follow {
color: var(--theme-primary-color);
}
.unfollow {
color: #409eff;
}
.requested {
color: var(--theme-primary-color);
}
}
}
</style>

View File

@ -165,22 +165,30 @@ export default {
}
},
follow (account) {
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/follow', account)
.catch(() => {
this.$message({
message: this.$t('message.follow_error'),
type: 'error'
})
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
try {
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/follow', account)
} catch (err) {
this.$message({
message: this.$t('message.follow_error'),
type: 'error'
})
} finally {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
}
},
unfollow (account) {
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unfollow', account)
.catch(() => {
this.$message({
message: this.$t('message.unfollow_error'),
type: 'error'
})
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
try {
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unfollow', account)
} catch (err) {
this.$message({
message: this.$t('message.unfollow_error'),
type: 'error'
})
} finally {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
}
},
changeTab (index) {
this.activeTab = index

View File

@ -1,7 +1,12 @@
<template>
<div id="followers">
<template v-for="follow in followers">
<user :user="follow"></user>
<user :user="follow"
:relationship="targetRelation(follow.id)"
@followAccount="followAccount"
@unfollowAccount="unfollowAccount"
>
</user>
</template>
</div>
</template>
@ -15,8 +20,9 @@ export default {
props: [ 'account' ],
components: { User },
computed: {
...mapState({
followers: state => state.TimelineSpace.Contents.SideBar.AccountProfile.Followers.followers
...mapState('TimelineSpace/Contents/SideBar/AccountProfile/Followers', {
followers: state => state.followers,
relationships: state => state.relationships
})
},
created () {
@ -28,14 +34,50 @@ export default {
}
},
methods: {
load () {
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchFollowers', this.account)
.catch(() => {
this.$message({
message: this.$t('message.followers_fetch_error'),
type: 'error'
})
async load () {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
try {
const followers = await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchFollowers', this.account)
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchRelationships', followers)
} catch (err) {
this.$message({
message: this.$t('message.followers_fetch_error'),
type: 'error'
})
} finally {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
}
},
targetRelation (id) {
return this.relationships.find(r => r.id === id)
},
async followAccount (account) {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
try {
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/follow', account)
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchRelationships', this.followers)
} catch (err) {
this.$message({
message: this.$t('message.follow_error'),
type: 'error'
})
} finally {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
}
},
async unfollowAccount (account) {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
try {
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unfollow', account)
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchRelationships', this.followers)
} catch (err) {
this.$message({
message: this.$t('message.unfollow_error'),
type: 'error'
})
} finally {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
}
}
}
}

View File

@ -1,7 +1,12 @@
<template>
<div id="follows">
<template v-for="follow in follows">
<user :user="follow"></user>
<user :user="follow"
:relationship="targetRelation(follow.id)"
@followAccount="followAccount"
@unfollowAccount="unfollowAccount"
>
</user>
</template>
</div>
</template>
@ -15,8 +20,9 @@ export default {
props: [ 'account' ],
components: { User },
computed: {
...mapState({
follows: state => state.TimelineSpace.Contents.SideBar.AccountProfile.Follows.follows
...mapState('TimelineSpace/Contents/SideBar/AccountProfile/Follows', {
follows: state => state.follows,
relationships: state => state.relationships
})
},
created () {
@ -28,14 +34,50 @@ export default {
}
},
methods: {
load () {
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchFollows', this.account)
.catch(() => {
this.$message({
message: this.$t('message.follows_fetch_error'),
type: 'error'
})
async load () {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
try {
const follows = await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchFollows', this.account)
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchRelationships', follows)
} catch (err) {
this.$message({
message: this.$t('message.follows_fetch_error'),
type: 'error'
})
} finally {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
}
},
targetRelation (id) {
return this.relationships.find(r => r.id === id)
},
async followAccount (account) {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
try {
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/follow', account)
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchRelationships', this.follows)
} catch (err) {
this.$message({
message: this.$t('message.follow_error'),
type: 'error'
})
} finally {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
}
},
async unfollowAccount (account) {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
try {
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unfollow', account)
await this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchRelationships', this.follows)
} catch (err) {
this.$message({
message: this.$t('message.unfollow_error'),
type: 'error'
})
} finally {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
}
}
}
}

View File

@ -63,24 +63,17 @@ const AccountProfile = {
})
},
follow ({ state, commit, rootState }, account) {
commit('changeLoading', true)
const client = new Mastodon(
rootState.TimelineSpace.account.accessToken,
rootState.TimelineSpace.account.baseURL + '/api/v1'
)
return client.post(`/accounts/${account.id}/follow`)
.then(res => {
commit('changeLoading', false)
commit('changeRelationship', res.data)
return res.data
})
.catch(err => {
commit('changeLoading', false)
throw err
})
},
unfollow ({ commit, rootState }, account) {
commit('changeLoading', true)
const client = new Mastodon(
rootState.TimelineSpace.account.accessToken,
rootState.TimelineSpace.account.baseURL + '/api/v1'
@ -90,9 +83,6 @@ const AccountProfile = {
commit('changeRelationship', res.data)
return res.data
})
.finally(() => {
commit('changeLoading', false)
})
},
close ({ commit }) {
commit('changeAccount', null)

View File

@ -3,26 +3,42 @@ import Mastodon from 'megalodon'
const Followers = {
namespaced: true,
state: {
followers: []
followers: [],
relationships: []
},
mutations: {
updateFollowers (state, users) {
state.followers = users
},
updateRelationships (state, relations) {
state.relationships = relations
}
},
actions: {
fetchFollowers ({ state, commit, rootState }, account) {
commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true, { root: true })
const client = new Mastodon(
rootState.TimelineSpace.account.accessToken,
rootState.TimelineSpace.account.baseURL + '/api/v1'
)
return client.get(`/accounts/${account.id}/followers`, { limit: 80 })
.then(res => {
commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false, { root: true })
commit('updateFollowers', res.data)
return res.data
})
},
fetchRelationships ({ commit, rootState }, accounts) {
const ids = accounts.map(a => a.id)
const client = new Mastodon(
rootState.TimelineSpace.account.accessToken,
rootState.TimelineSpace.account.baseURL + '/api/v1'
)
return client.get(`/accounts/relationships`, {
id: ids
})
.then(res => {
commit('updateRelationships', res.data)
return res.data
})
}
}
}

View File

@ -3,26 +3,42 @@ import Mastodon from 'megalodon'
const Follows = {
namespaced: true,
state: {
follows: []
follows: [],
relationships: []
},
mutations: {
updateFollows (state, users) {
state.follows = users
},
updateRelationships (state, relations) {
state.relationships = relations
}
},
actions: {
fetchFollows ({ state, commit, rootState }, account) {
commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true, { root: true })
const client = new Mastodon(
rootState.TimelineSpace.account.accessToken,
rootState.TimelineSpace.account.baseURL + '/api/v1'
)
return client.get(`/accounts/${account.id}/following`, { limit: 80 })
.then(res => {
commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false, { root: true })
commit('updateFollows', res.data)
return res.data
})
},
fetchRelationships ({ commit, rootState }, accounts) {
const ids = accounts.map(a => a.id)
const client = new Mastodon(
rootState.TimelineSpace.account.accessToken,
rootState.TimelineSpace.account.baseURL + '/api/v1'
)
return client.get(`/accounts/relationships`, {
id: ids
})
.then(res => {
commit('updateRelationships', res.data)
return res.data
})
}
}
}