Add hashtag following button (#244)
ci/woodpecker/push/woodpecker Pipeline was successful Details

Co-authored-by: FloatingGhost <hannah@coffee-and-dreams.uk>
Reviewed-on: AkkomaGang/pleroma-fe#244
This commit is contained in:
floatingghost 2022-12-04 17:31:41 +00:00
parent 105ecd3836
commit eb49295422
6 changed files with 126 additions and 5 deletions

View File

@ -6,11 +6,13 @@ import TimelineMenuTabs from '../timeline_menu_tabs/timeline_menu_tabs.vue'
import TimelineQuickSettings from './timeline_quick_settings.vue'
import { debounce, throttle, keyBy } from 'lodash'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faCircleNotch, faCog } from '@fortawesome/free-solid-svg-icons'
import { faCircleNotch, faCog, faPlus, faMinus } from '@fortawesome/free-solid-svg-icons'
library.add(
faCircleNotch,
faCog
faCog,
faPlus,
faMinus
)
const Timeline = {
@ -90,6 +92,15 @@ const Timeline = {
},
showPanelNavShortcuts () {
return this.$store.getters.mergedConfig.showPanelNavShortcuts
},
currentUser () {
return this.$store.state.users.currentUser
},
tagData () {
return this.$store.state.tags.tags[this.tag]
},
tagFollowed () {
return this.$store.state.tags.tags[this.tag]?.following
}
},
created () {
@ -118,6 +129,10 @@ const Timeline = {
}
window.addEventListener('keydown', this.handleShortKey)
setTimeout(this.determineVisibleStatuses, 250)
if (this.tag) {
this.$store.dispatch('getTag', this.tag)
}
},
unmounted () {
window.removeEventListener('scroll', this.handleScroll)
@ -232,6 +247,12 @@ const Timeline = {
}, 200),
handleVisibilityChange () {
this.unfocused = document.hidden
},
followTag (tag) {
return this.$store.dispatch('followTag', tag)
},
unfollowTag (tag) {
return this.$store.dispatch('unfollowTag', tag)
}
},
watch: {

View File

@ -21,6 +21,36 @@
{{ $t('timeline.up_to_date') }}
</div>
<TimelineQuickSettings v-if="!embedded" />
<div
v-if="currentUser && tag !== undefined && tagData && !tagFollowed"
class="followTag"
>
<button
class="button-default"
:title="$t('timeline.follow_tag')"
@click="followTag(tag)"
>
<FAIcon
size="sm"
icon="plus"
/>
</button>
</div>
<div
v-if="currentUser && tag !== undefined && tagData && tagFollowed"
class="followTag"
>
<button
class="button-default"
:title="$t('timeline.unfollow_tag')"
@click="unfollowTag(tag)"
>
<FAIcon
size="sm"
icon="minus"
/>
</button>
</div>
</div>
<div :class="classes.body">
<div

View File

@ -1055,7 +1055,9 @@
"show_new": "Show new",
"socket_broke": "Realtime connection lost: CloseEvent code {0}",
"socket_reconnected": "Realtime connection established",
"up_to_date": "Up-to-date"
"up_to_date": "Up-to-date",
"follow_tag": "Follow hashtag",
"unfollow_tag": "Unfollow hashtag"
},
"toast": {
"no_translation_target_set": "No translation target language set - this may fail. Please set a target language in your settings."

View File

@ -21,6 +21,7 @@ import postStatusModule from './modules/postStatus.js'
import announcementsModule from './modules/announcements.js'
import editStatusModule from './modules/editStatus.js'
import statusHistoryModule from './modules/statusHistory.js'
import tagModule from './modules/tags.js'
import { createI18n } from 'vue-i18n'
@ -96,7 +97,8 @@ const persistedStateOptions = {
postStatus: postStatusModule,
announcements: announcementsModule,
editStatus: editStatusModule,
statusHistory: statusHistoryModule
statusHistory: statusHistoryModule,
tags: tagModule
},
plugins,
strict: false // Socket modifies itself, let's ignore this for now.

37
src/modules/tags.js Normal file
View File

@ -0,0 +1,37 @@
import { merge } from 'lodash'
const tags = {
state: {
// Contains key = id, value = number of trackers for this poll
tags: {}
},
mutations: {
setTag (state, { name, data }) {
state.tags[name] = data
}
},
actions: {
getTag ({ rootState, commit }, tagName) {
return rootState.api.backendInteractor.getHashtag({ tag: tagName }).then(tag => {
commit('setTag', { name: tagName, data: tag })
return tag
})
},
followTag (store, tagName) {
return store.rootState.api.backendInteractor.followHashtag({ tag: tagName })
.then((resp) => {
store.commit('setTag', { name: tagName, data: resp })
return resp
})
},
unfollowTag ({ rootState, commit }, tag) {
return rootState.api.backendInteractor.unfollowHashtag({ tag })
.then((resp) => {
commit('setTag', { name: tag, data: resp })
return resp
})
}
}
}
export default tags

View File

@ -108,6 +108,9 @@ const PLEROMA_EDIT_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements
const PLEROMA_DELETE_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}`
const AKKOMA_SETTING_PROFILE_URL = (name) => `/api/v1/akkoma/frontend_settings/pleroma-fe/${name}`
const AKKOMA_SETTING_PROFILE_LIST = `/api/v1/akkoma/frontend_settings/pleroma-fe`
const MASTODON_TAG_URL = (name) => `/api/v1/tags/${name}`
const MASTODON_FOLLOW_TAG_URL = (name) => `/api/v1/tags/${name}/follow`
const MASTODON_UNFOLLOW_TAG_URL = (name) => `/api/v1/tags/${name}/unfollow`
const oldfetch = window.fetch
@ -1549,6 +1552,29 @@ const listSettingsProfiles = ({ credentials }) => {
})
}
const getHashtag = ({ tag, credentials }) => {
return promisedRequest({
url: MASTODON_TAG_URL(tag),
credentials
})
}
const followHashtag = ({ tag, credentials }) => {
return promisedRequest({
url: MASTODON_FOLLOW_TAG_URL(tag),
method: 'POST',
credentials
})
}
const unfollowHashtag = ({ tag, credentials }) => {
return promisedRequest({
url: MASTODON_UNFOLLOW_TAG_URL(tag),
method: 'POST',
credentials
})
}
export const getMastodonSocketURI = ({ credentials, stream, args = {} }) => {
return Object.entries({
...(credentials
@ -1784,7 +1810,10 @@ const apiService = {
getReports,
updateReportStates,
addNoteToReport,
deleteNoteFromReport
deleteNoteFromReport,
getHashtag,
followHashtag,
unfollowHashtag
}
export default apiService