Pinafore-Web-Client-Frontend/src/routes/_components/status/StatusToolbar.html

213 lines
6.6 KiB
HTML

<div class="status-toolbar {isStatusInOwnThread ? 'status-in-own-thread' : ''}" ref:node>
<IconButton
className="status-toolbar-reply-button"
label={replyLabel}
pressedLabel="{intl.closeReply}"
pressable={true}
pressed={replyShown}
href={replyIcon}
clickListener={false}
elementId={replyKey}
/>
<IconButton
label={reblogLabel}
pressedLabel="Unboost"
pressable={!reblogDisabled}
pressed={reblogged}
disabled={reblogDisabled}
href={reblogIcon}
clickListener={false}
elementId={reblogKey}
ref:reblogIcon
/>
<IconButton
label="{intl.favorite}"
pressedLabel="{intl.unfavorite}"
pressable={true}
pressed={favorited}
href="#fa-star"
clickListener={false}
elementId={favoriteKey}
ref:favoriteIcon
/>
<IconButton
label="{intl.moreOptions}"
href="#fa-ellipsis-h"
clickListener={false}
elementId={optionsKey}
/>
</div>
{#if enableShortcuts}
<Shortcut scope={shortcutScope} key="f" on:pressed="toggleFavorite()"/>
<Shortcut scope={shortcutScope} key="r" on:pressed="reply()"/>
<Shortcut scope={shortcutScope} key="b" on:pressed="reblog()"/>
{/if}
<style>
.status-toolbar {
grid-area: toolbar;
display: flex;
justify-content: space-between;
pointer-events: none;
}
.status-toolbar.status-in-own-thread {
margin-left: 63px; /* offset to align all toolbar items: 48px avatar + 15px margin-right */
}
@media (max-width: 767px) {
.status-toolbar.status-in-own-thread {
margin-left: 53px; /* offset to align all toolbar items: 48px avatar + 5px margin-right */
}
}
@media (max-width: 240px) {
:global(.status-toolbar .icon-button-svg) {
width: 20px;
height: 20px;
}
}
</style>
<script>
import IconButton from '../IconButton.html'
import Shortcut from '../shortcut/Shortcut.html'
import { store } from '../../_store/store'
import { registerClickDelegates } from '../../_utils/delegate'
import { setFavorited } from '../../_actions/favorite'
import { setReblogged } from '../../_actions/reblog'
import { importShowStatusOptionsDialog } from '../dialog/asyncDialogs/importShowStatusOptionsDialog.js'
import { updateProfileAndRelationship } from '../../_actions/accounts'
import { FAVORITE_ANIMATION, REBLOG_ANIMATION } from '../../_static/animations'
import { on } from '../../_utils/eventBus'
export default {
oncreate () {
const {
favoriteKey,
reblogKey,
replyKey,
optionsKey
} = this.get()
registerClickDelegates(this, {
[favoriteKey]: () => {
this.toggleFavorite()
return true
},
[reblogKey]: () => {
this.reblog()
return true
},
[replyKey]: () => {
this.reply()
return true
},
[optionsKey]: () => {
this.onOptionsClick()
return true
}
})
on('postedStatus', this, this.onPostedStatus)
},
components: {
IconButton,
Shortcut
},
store: () => store,
methods: {
toggleFavorite () {
const { originalStatusId, favorited } = this.get()
const newFavoritedValue = !favorited
/* no await */ setFavorited(originalStatusId, newFavoritedValue)
if (newFavoritedValue) {
this.refs.favoriteIcon.animate(FAVORITE_ANIMATION)
}
},
reblog () {
const { originalStatusId, reblogged } = this.get()
const newRebloggedValue = !reblogged
/* no await */ setReblogged(originalStatusId, newRebloggedValue)
if (newRebloggedValue) {
this.refs.reblogIcon.animate(REBLOG_ANIMATION)
}
},
reply () {
requestAnimationFrame(() => {
const { uuid } = this.get()
const { repliesShown } = this.store.get()
repliesShown[uuid] = !repliesShown[uuid]
this.store.set({ repliesShown })
this.fire('recalculateHeight')
})
},
async onOptionsClick () {
const { originalStatus, originalAccountId } = this.get()
const updateRelationshipPromise = updateProfileAndRelationship(originalAccountId)
const showStatusOptionsDialog = await importShowStatusOptionsDialog()
await updateRelationshipPromise
showStatusOptionsDialog(originalStatus)
},
onPostedStatus (realm, inReplyToUuid) {
const {
originalStatusId,
uuid
} = this.get()
if (realm !== originalStatusId ||
inReplyToUuid !== uuid) {
return
}
try {
// return status to the reply button after posting a reply
this.refs.node.querySelector('.status-toolbar-reply-button').focus({ preventScroll: true })
} catch (e) { /* ignore */ }
}
},
data: () => ({
favoriteAnimation: FAVORITE_ANIMATION,
reblogAnimation: REBLOG_ANIMATION
}),
computed: {
replyLabel: ({ inReplyToId }) => (
inReplyToId ? 'intl.replyToThread' : 'intl.reply'
),
replyIcon: ({ inReplyToId }) => inReplyToId ? '#fa-reply-all' : '#fa-reply',
reblogLabel: ({ visibility }) => {
switch (visibility) {
case 'private':
return 'intl.cannotReblogFollowersOnly'
case 'direct':
return 'intl.cannotReblogDirectMessage'
default:
return 'intl.reblog'
}
},
reblogIcon: ({ visibility }) => {
switch (visibility) {
case 'private':
return '#fa-lock'
case 'direct':
return '#fa-envelope'
default:
return '#fa-retweet'
}
},
reblogDisabled: ({ visibility }) => {
return visibility === 'private' || visibility === 'direct'
},
reblogged: ({ originalStatusId, $currentStatusModifications, originalStatus }) => {
if ($currentStatusModifications && originalStatusId in $currentStatusModifications.reblogs) {
return $currentStatusModifications.reblogs[originalStatusId]
}
return originalStatus.reblogged
},
favorited: ({ originalStatusId, $currentStatusModifications, originalStatus }) => {
if ($currentStatusModifications && originalStatusId in $currentStatusModifications.favorites) {
return $currentStatusModifications.favorites[originalStatusId]
}
return originalStatus.favourited
},
favoriteKey: ({ uuid }) => `fav-${uuid}`,
reblogKey: ({ uuid }) => `reblog-${uuid}`,
replyKey: ({ uuid }) => `reply-${uuid}`,
optionsKey: ({ uuid }) => `options-${uuid}`
}
}
</script>