Re-implement status detail
This commit is contained in:
parent
88575a0a47
commit
c9d43714e9
|
@ -14,7 +14,9 @@
|
||||||
</div>
|
</div>
|
||||||
</el-main>
|
</el-main>
|
||||||
</el-container>
|
</el-container>
|
||||||
<div class="detail">detail</div>
|
<el-aside class="detail" v-if="detail">
|
||||||
|
<Detail />
|
||||||
|
</el-aside>
|
||||||
<modals></modals>
|
<modals></modals>
|
||||||
<receive-drop v-show="droppableVisible"></receive-drop>
|
<receive-drop v-show="droppableVisible"></receive-drop>
|
||||||
</template>
|
</template>
|
||||||
|
@ -29,7 +31,7 @@ import HeaderMenu from './TimelineSpace/HeaderMenu.vue'
|
||||||
import Contents from './TimelineSpace/Contents.vue'
|
import Contents from './TimelineSpace/Contents.vue'
|
||||||
import Compose from './TimelineSpace/Compose.vue'
|
import Compose from './TimelineSpace/Compose.vue'
|
||||||
import Modals from './TimelineSpace/Modals.vue'
|
import Modals from './TimelineSpace/Modals.vue'
|
||||||
import SideBar from './TimelineSpace/Contents/SideBar.vue'
|
import Detail from './TimelineSpace/Detail.vue'
|
||||||
import Mousetrap from 'mousetrap'
|
import Mousetrap from 'mousetrap'
|
||||||
import ReceiveDrop from './TimelineSpace/ReceiveDrop.vue'
|
import ReceiveDrop from './TimelineSpace/ReceiveDrop.vue'
|
||||||
import { AccountLoadError } from '@/errors/load'
|
import { AccountLoadError } from '@/errors/load'
|
||||||
|
@ -45,7 +47,7 @@ import { ACTION_TYPES as NEW_TOOT_ACTION } from '@/store/TimelineSpace/Modals/Ne
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'timeline-space',
|
name: 'timeline-space',
|
||||||
components: { SideMenu, HeaderMenu, Modals, Contents, ReceiveDrop, Compose, SideBar },
|
components: { SideMenu, HeaderMenu, Modals, Contents, ReceiveDrop, Compose, Detail },
|
||||||
setup() {
|
setup() {
|
||||||
const space = 'TimelineSpace'
|
const space = 'TimelineSpace'
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
@ -57,9 +59,7 @@ export default defineComponent({
|
||||||
const contentsRef = ref<HTMLElement | null>(null)
|
const contentsRef = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
const loading = computed(() => store.state.TimelineSpace.loading)
|
const loading = computed(() => store.state.TimelineSpace.loading)
|
||||||
const collapse = computed(() => store.state.TimelineSpace.SideMenu.collapse)
|
const detail = computed(() => route.query.detail?.toString() === 'true')
|
||||||
// const modalOpened = computed(() => store.getters[`TimelineSpace/Modals/modalOpened`])
|
|
||||||
// const shortcutEnabled = computed(() => !modalOpened.value)
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
store.dispatch(`TimelineSpace/Contents/SideBar/${SIDEBAR_ACTION.CLOSE}`)
|
store.dispatch(`TimelineSpace/Contents/SideBar/${SIDEBAR_ACTION.CLOSE}`)
|
||||||
|
@ -167,10 +167,10 @@ export default defineComponent({
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loading,
|
loading,
|
||||||
collapse,
|
|
||||||
droppableVisible,
|
droppableVisible,
|
||||||
composeResized,
|
composeResized,
|
||||||
contentsRef
|
contentsRef,
|
||||||
|
detail
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -183,6 +183,7 @@ export default defineComponent({
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
height: auto;
|
||||||
border-bottom: 1px solid var(--theme-border-color);
|
border-bottom: 1px solid var(--theme-border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
<template>
|
||||||
|
<el-container>
|
||||||
|
<el-header class="header-wrapper">
|
||||||
|
<div class="header">
|
||||||
|
<div>
|
||||||
|
<el-button class="header-action" link @click="back">
|
||||||
|
<font-awesome-icon icon="chevron-left" />
|
||||||
|
Back
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-button class="header-action" link @click="close">
|
||||||
|
<font-awesome-icon icon="xmark" />
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
<el-main class="main">
|
||||||
|
<Status v-if="target() === 'status'" />
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
import Status from './Detail/Status.vue'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Detail',
|
||||||
|
components: { Status },
|
||||||
|
setup() {
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
router.push({
|
||||||
|
query: {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const back = () => {
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = () => {
|
||||||
|
if (route.query.status_id?.toString()) {
|
||||||
|
return 'status'
|
||||||
|
} else if (route.query.account_id?.toString()) {
|
||||||
|
return 'account'
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
close,
|
||||||
|
back,
|
||||||
|
target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.header-wrapper {
|
||||||
|
height: auto;
|
||||||
|
border-bottom: 1px solid var(--theme-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 0;
|
||||||
|
line-height: 32px;
|
||||||
|
|
||||||
|
.header-action {
|
||||||
|
color: var(--theme-secondary-color);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,131 @@
|
||||||
|
<template>
|
||||||
|
<div class="status-detail">
|
||||||
|
<div class="ancestors" v-for="mes in ancestors" :key="mes.id">
|
||||||
|
<Toot
|
||||||
|
v-if="account.account && account.server"
|
||||||
|
:message="mes"
|
||||||
|
:overlaid="modalOpened"
|
||||||
|
:account="account.account"
|
||||||
|
:server="account.server"
|
||||||
|
@update="updateStatus"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="original-status">
|
||||||
|
<Toot
|
||||||
|
v-if="status !== null && account.account && account.server"
|
||||||
|
:message="status"
|
||||||
|
:overlaid="modalOpened"
|
||||||
|
:account="account.account"
|
||||||
|
:server="account.server"
|
||||||
|
@update="updateStatus"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="descendants" v-for="mes in descendants" :key="mes.id">
|
||||||
|
<Toot
|
||||||
|
v-if="account.account && account.server"
|
||||||
|
:message="mes"
|
||||||
|
:overlaid="modalOpened"
|
||||||
|
:account="account.account"
|
||||||
|
:server="account.server"
|
||||||
|
@update="updateStatus"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, onMounted, computed, reactive, watch } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import generator, { MegalodonInterface, Entity } from 'megalodon'
|
||||||
|
import Toot from '@/components/organisms/Toot.vue'
|
||||||
|
import { useStore } from '@/store'
|
||||||
|
import { MyWindow } from '~/src/types/global'
|
||||||
|
import { LocalAccount } from '~/src/types/localAccount'
|
||||||
|
import { LocalServer } from '~/src/types/localServer'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Status',
|
||||||
|
components: { Toot },
|
||||||
|
setup() {
|
||||||
|
const win = (window as any) as MyWindow
|
||||||
|
const store = useStore()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const client = ref<MegalodonInterface | null>(null)
|
||||||
|
const id = computed(() => parseInt(route.params.id as string))
|
||||||
|
const statusId = computed(() => route.query.status_id?.toString())
|
||||||
|
const userAgent = computed(() => store.state.App.userAgent)
|
||||||
|
const status = ref<Entity.Status | null>(null)
|
||||||
|
const ancestors = ref<Array<Entity.Status>>([])
|
||||||
|
const descendants = ref<Array<Entity.Status>>([])
|
||||||
|
const account = reactive<{ account: LocalAccount | null; server: LocalServer | null }>({
|
||||||
|
account: null,
|
||||||
|
server: null
|
||||||
|
})
|
||||||
|
const modalOpened = computed(() => store.getters[`TimelineSpace/Modals/modalOpened`])
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const [a, s]: [LocalAccount, LocalServer] = await win.ipcRenderer.invoke('get-local-account', id.value)
|
||||||
|
account.account = a
|
||||||
|
account.server = s
|
||||||
|
const c = generator(s.sns, s.baseURL, a.accessToken, userAgent.value)
|
||||||
|
client.value = c
|
||||||
|
|
||||||
|
if (statusId.value) {
|
||||||
|
const s = await c.getStatus(statusId.value)
|
||||||
|
status.value = s.data
|
||||||
|
const res = await c.getStatusContext(statusId.value)
|
||||||
|
ancestors.value = res.data.ancestors
|
||||||
|
descendants.value = res.data.descendants
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(statusId, async current => {
|
||||||
|
if (client.value && current) {
|
||||||
|
const s = await client.value.getStatus(current)
|
||||||
|
status.value = s.data
|
||||||
|
const res = await client.value.getStatusContext(current)
|
||||||
|
ancestors.value = res.data.ancestors
|
||||||
|
descendants.value = res.data.descendants
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const update = (target: Entity.Status, s: Entity.Status) => {
|
||||||
|
if (target.id === s.id) {
|
||||||
|
return s
|
||||||
|
} else if (target.reblog !== null && target.reblog.id == s.id) {
|
||||||
|
return Object.assign(target, { reblog: s })
|
||||||
|
} else {
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateStatus = (s: Entity.Status) => {
|
||||||
|
if (status.value) {
|
||||||
|
status.value = update(status.value, s)
|
||||||
|
}
|
||||||
|
ancestors.value = ancestors.value.map(anc => update(anc, s))
|
||||||
|
descendants.value = descendants.value.map(des => update(des, s))
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
account,
|
||||||
|
status,
|
||||||
|
ancestors,
|
||||||
|
descendants,
|
||||||
|
updateStatus,
|
||||||
|
modalOpened
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.status-detail {
|
||||||
|
.original-status {
|
||||||
|
.status {
|
||||||
|
background-color: var(--theme-selected-background-color);
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -483,9 +483,7 @@ export default defineComponent({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const openDetail = (message: Entity.Status) => {
|
const openDetail = (message: Entity.Status) => {
|
||||||
store.dispatch(`TimelineSpace/Contents/SideBar/${SIDEBAR_ACTION.OPEN_TOOT_COMPONENT}`)
|
router.push({ query: { detail: 'true', status_id: message.id } })
|
||||||
store.dispatch(`TimelineSpace/Contents/SideBar/TootDetail/${DETAIL_ACTION.CHANGE_TOOT}`, message)
|
|
||||||
store.commit(`TimelineSpace/Contents/SideBar/${SIDEBAR_MUTATION.CHANGE_OPEN_SIDEBAR}`, true)
|
|
||||||
}
|
}
|
||||||
const openBrowser = (message: Entity.Status) => {
|
const openBrowser = (message: Entity.Status) => {
|
||||||
;(window as any).shell.openExternal(message.url)
|
;(window as any).shell.openExternal(message.url)
|
||||||
|
|
Loading…
Reference in New Issue