Add ability to view status history for edited statuses

This commit is contained in:
Sean King 2022-06-20 22:52:08 -06:00 committed by Sol Fisher Romanoff
parent a0d2125421
commit c35b2b9c28
No known key found for this signature in database
GPG key ID: 9D3F2B64F2341B62
12 changed files with 187 additions and 14 deletions

View file

@ -12,6 +12,7 @@ import DesktopNav from './components/desktop_nav/desktop_nav.vue'
import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue'
import EditStatusModal from './components/edit_status_modal/edit_status_modal.vue'
import PostStatusModal from './components/post_status_modal/post_status_modal.vue'
import StatusHistoryModal from './components/status_history_modal/status_history_modal.vue'
import GlobalNoticeList from './components/global_notice_list/global_notice_list.vue'
import { windowWidth, windowHeight } from './services/window_utils/window_utils'
import { mapGetters } from 'vuex'
@ -35,6 +36,7 @@ export default {
UserReportingModal,
PostStatusModal,
EditStatusModal,
StatusHistoryModal,
GlobalNoticeList
},
data: () => ({

View file

@ -59,6 +59,7 @@
<UserReportingModal />
<PostStatusModal />
<EditStatusModal />
<StatusHistoryModal />
<SettingsModal />
<div id="modal" />
<GlobalNoticeList />

View file

@ -6,7 +6,8 @@ import {
faEyeSlash,
faThumbtack,
faShareAlt,
faExternalLinkAlt
faExternalLinkAlt,
faHistory
} from '@fortawesome/free-solid-svg-icons'
import {
faBookmark as faBookmarkReg,
@ -21,7 +22,8 @@ library.add(
faThumbtack,
faShareAlt,
faExternalLinkAlt,
faFlag
faFlag,
faHistory
)
const ExtraButtons = {
@ -84,6 +86,20 @@ const ExtraButtons = {
visibility: this.status.visibility,
statusContentType: data.content_type
}))
},
showStatusHistory () {
let originalStatus = {}
Object.assign(originalStatus, this.status)
delete originalStatus.attachments
delete originalStatus.created_at
delete originalStatus.emojis
delete originalStatus.text
delete originalStatus.raw_html
delete originalStatus.nsfw
delete originalStatus.poll
delete originalStatus.summary
delete originalStatus.summary_raw_html
this.$store.dispatch('openStatusHistoryModal', originalStatus)
}
},
computed: {
@ -104,6 +120,9 @@ const ExtraButtons = {
},
statusLink () {
return `${this.$store.state.instance.server}${this.$router.resolve({ name: 'conversation', params: { id: this.status.id } }).href}`
},
isEdited () {
return this.status.edited_at !== null
}
}
}

View file

@ -84,6 +84,17 @@
icon="pen"
/><span>{{ $t("status.edit") }}</span>
</button>
<button
v-if="isEdited"
class="button-default dropdown-item dropdown-item-icon"
@click.prevent="showStatusHistory"
@click="close"
>
<FAIcon
fixed-width
icon="history"
/><span>{{ $t("status.status_history") }}</span>
</button>
<button
v-if="canDelete"
class="button-default dropdown-item dropdown-item-icon"

View file

@ -0,0 +1,60 @@
import { get } from 'lodash'
import Modal from '../modal/modal.vue'
import Status from '../status/status.vue'
const StatusHistoryModal = {
components: {
Modal,
Status
},
data () {
return {
statuses: []
}
},
computed: {
modalActivated () {
return this.$store.state.statusHistory.modalActivated
},
params () {
return this.$store.state.statusHistory.params
},
statusId () {
return this.params.id
},
historyCount () {
return this.statuses.length
},
history () {
return this.statuses
}
},
watch: {
params (newVal, oldVal) {
const newStatusId = get(newVal, 'id') !== get(oldVal, 'id')
if (newStatusId) {
this.resetHistory()
}
if (newStatusId || get(newVal, 'edited_at') !== get(oldVal, 'edited_at')) {
this.fetchStatusHistory()
}
}
},
methods: {
resetHistory () {
this.statuses = []
},
fetchStatusHistory () {
this.$store.dispatch('fetchStatusHistory', this.params)
.then(data => {
this.statuses = data
})
},
closeModal () {
this.$store.dispatch('closeStatusHistoryModal')
}
}
}
export default StatusHistoryModal

View file

@ -0,0 +1,46 @@
<template>
<Modal
v-if="modalActivated"
class="status-history-modal-view"
@backdropClicked="closeModal"
>
<div class="status-history-modal-panel panel">
<div class="panel-heading">
{{ $t('status.status_history') }} ({{ historyCount }})
</div>
<div class="panel-body">
<div
v-if="historyCount > 0"
class="history-body"
>
<status
v-for="status in history"
:key="status.id"
:statusoid="status"
:isPreview="true"
class="conversation-status status-fadein panel-body"
/>
</div>
</div>
</div>
</Modal>
</template>
<script src="./status_history_modal.js"></script>
<style lang="scss">
.modal-view.status-history-modal-view {
align-items: flex-start;
}
.status-history-modal-panel {
flex-shrink: 0;
margin-top: 25%;
margin-bottom: 2em;
width: 100%;
max-width: 700px;
@media (orientation: landscape) {
margin-top: 8%;
}
}
</style>

View file

@ -841,7 +841,8 @@
"ancestor_follow_with_icon": "{icon} {text}",
"show_all_conversation_with_icon": "{icon} {text}",
"show_all_conversation": "Show full conversation ({numStatus} other status) | Show full conversation ({numStatus} other statuses)",
"show_only_conversation_under_this": "Only show replies to this status"
"show_only_conversation_under_this": "Only show replies to this status",
"status_history": "Status history"
},
"user_card": {
"approve": "Approve",

View file

@ -20,6 +20,7 @@ import pollsModule from './modules/polls.js'
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 { createI18n } from 'vue-i18n'
@ -83,7 +84,8 @@ const persistedStateOptions = {
polls: pollsModule,
postStatus: postStatusModule,
announcements: announcementsModule,
editStatus: editStatusModule
editStatus: editStatusModule,
statusHistory: statusHistoryModule
},
plugins,
strict: false // Socket modifies itself, let's ignore this for now.

View file

@ -0,0 +1,25 @@
const statusHistory = {
state: {
params: {},
modalActivated: false
},
mutations: {
openStatusHistoryModal (state, params) {
state.params = params
state.modalActivated = true
},
closeStatusHistoryModal (state) {
state.modalActivated = false
}
},
actions: {
openStatusHistoryModal ({ commit }, params) {
commit('openStatusHistoryModal', params)
},
closeStatusHistoryModal ({ commit }) {
commit('closeStatusHistoryModal')
}
}
}
export default statusHistory

View file

@ -607,6 +607,9 @@ const statuses = {
fetchStatusSource ({ rootState, dispatch }, status) {
return apiService.fetchStatusSource({ id: status.id, credentials: rootState.users.currentUser.credentials })
},
fetchStatusHistory ({ rootState, dispatch }, status) {
return apiService.fetchStatusHistory({ status })
},
deleteStatus ({ rootState, commit }, status) {
commit('setDeleted', { status })
apiService.deleteStatus({ id: status.id, credentials: rootState.users.currentUser.credentials })

View file

@ -524,17 +524,16 @@ const fetchStatusSource = ({ id, credentials }) => {
.then((data) => parseSource(data))
}
const fetchStatusHistory = ({ id, credentials }) => {
let url = MASTODON_STATUS_HISTORY_URL(id)
return fetch(url, { headers: authHeaders(credentials) })
const fetchStatusHistory = ({ status, credentials }) => {
let url = MASTODON_STATUS_HISTORY_URL(status.id)
return promisedRequest({ url, credentials })
.then((data) => {
if (data.ok) {
return data
}
throw new Error('Error fetching history', data)
data.reverse()
return data.map((item) => {
item.originalStatus = status
return parseStatus(item)
})
})
.then((data) => data.json())
.then((data) => parseStatus(data))
}
const tagUser = ({ tag, credentials, user }) => {

View file

@ -273,7 +273,7 @@ export const parseStatus = (data) => {
output.tags = data.tags
output.is_edited = data.edited_at !== null
output.edited_at = data.edited_at
if (data.pleroma) {
const { pleroma } = data
@ -383,6 +383,10 @@ export const parseStatus = (data) => {
output.favoritedBy = []
output.rebloggedBy = []
if (data.hasOwnProperty('originalStatus')) {
Object.assign(output, data.originalStatus)
}
return output
}