Add hashtag following button #244

Merged
floatingghost merged 1 commit from follow-hashtags into develop 2022-12-04 17:31:41 +00:00
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 TimelineQuickSettings from './timeline_quick_settings.vue'
import { debounce, throttle, keyBy } from 'lodash' import { debounce, throttle, keyBy } from 'lodash'
import { library } from '@fortawesome/fontawesome-svg-core' 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( library.add(
faCircleNotch, faCircleNotch,
faCog faCog,
faPlus,
faMinus
) )
const Timeline = { const Timeline = {
@ -90,6 +92,15 @@ const Timeline = {
}, },
showPanelNavShortcuts () { showPanelNavShortcuts () {
return this.$store.getters.mergedConfig.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 () { created () {
@ -118,6 +129,10 @@ const Timeline = {
} }
window.addEventListener('keydown', this.handleShortKey) window.addEventListener('keydown', this.handleShortKey)
setTimeout(this.determineVisibleStatuses, 250) setTimeout(this.determineVisibleStatuses, 250)
if (this.tag) {
this.$store.dispatch('getTag', this.tag)
}
}, },
unmounted () { unmounted () {
window.removeEventListener('scroll', this.handleScroll) window.removeEventListener('scroll', this.handleScroll)
@ -232,6 +247,12 @@ const Timeline = {
}, 200), }, 200),
handleVisibilityChange () { handleVisibilityChange () {
this.unfocused = document.hidden this.unfocused = document.hidden
},
followTag (tag) {
return this.$store.dispatch('followTag', tag)
},
unfollowTag (tag) {
return this.$store.dispatch('unfollowTag', tag)
} }
}, },
watch: { watch: {

View file

@ -21,6 +21,36 @@
{{ $t('timeline.up_to_date') }} {{ $t('timeline.up_to_date') }}
</div> </div>
<TimelineQuickSettings v-if="!embedded" /> <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>
<div :class="classes.body"> <div :class="classes.body">
<div <div

View file

@ -1055,7 +1055,9 @@
"show_new": "Show new", "show_new": "Show new",
"socket_broke": "Realtime connection lost: CloseEvent code {0}", "socket_broke": "Realtime connection lost: CloseEvent code {0}",
"socket_reconnected": "Realtime connection established", "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": { "toast": {
"no_translation_target_set": "No translation target language set - this may fail. Please set a target language in your settings." "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 announcementsModule from './modules/announcements.js'
import editStatusModule from './modules/editStatus.js' import editStatusModule from './modules/editStatus.js'
import statusHistoryModule from './modules/statusHistory.js' import statusHistoryModule from './modules/statusHistory.js'
import tagModule from './modules/tags.js'
import { createI18n } from 'vue-i18n' import { createI18n } from 'vue-i18n'
@ -96,7 +97,8 @@ const persistedStateOptions = {
postStatus: postStatusModule, postStatus: postStatusModule,
announcements: announcementsModule, announcements: announcementsModule,
editStatus: editStatusModule, editStatus: editStatusModule,
statusHistory: statusHistoryModule statusHistory: statusHistoryModule,
tags: tagModule
}, },
plugins, plugins,
strict: false // Socket modifies itself, let's ignore this for now. 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 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_URL = (name) => `/api/v1/akkoma/frontend_settings/pleroma-fe/${name}`
const AKKOMA_SETTING_PROFILE_LIST = `/api/v1/akkoma/frontend_settings/pleroma-fe` 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 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 = {} }) => { export const getMastodonSocketURI = ({ credentials, stream, args = {} }) => {
return Object.entries({ return Object.entries({
...(credentials ...(credentials
@ -1784,7 +1810,10 @@ const apiService = {
getReports, getReports,
updateReportStates, updateReportStates,
addNoteToReport, addNoteToReport,
deleteNoteFromReport deleteNoteFromReport,
getHashtag,
followHashtag,
unfollowHashtag
} }
export default apiService export default apiService