Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions app/components/status/StatusScheduledCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<script setup lang="ts">
import type { mastodon } from 'masto'

const { item } = defineProps<{
item: mastodon.v1.ScheduledStatus
}>()

const emit = defineEmits<{ (e: 'deleted', id: string): void }>()

const scheduledAt = useFormattedDateTime(item.scheduledAt)
const timeAgoOptions = useTimeAgoOptions(true)
const timeago = useTimeAgo(() => item.scheduledAt, timeAgoOptions)

// mastodon.v1.ScheduledStatus does not have account information so we use the current login user
const account = currentUser.value!.account

async function handleDelete() {
const confirmDelete = await openConfirmDialog({
title: $t('confirm.delete_posts.title'),
description: $t('confirm.delete_posts.description'),
confirm: $t('confirm.delete_posts.confirm'),
cancel: $t('confirm.delete_posts.cancel'),
})
if (confirmDelete.choice !== 'confirm')
return

try {
await useMastoClient().v1.scheduledStatuses.$select(item.id).remove()
emit('deleted', item.id)
}
catch (e) {
console.error(e)
}
}
</script>

<template>
<article relative flex gap-3 p-4 border-b border-base>
<div>
<AccountHoverWrapper :account="account">
<AccountBigAvatar :account="account" />
</AccountHoverWrapper>
</div>

<div flex="~ col 1" min-w-0>
<div flex items-center space-x-1>
<AccountHoverWrapper :account="account">
<StatusAccountDetails :account="account" />
</AccountHoverWrapper>
<div flex-auto />
<div text-sm text-secondary flex="~ row nowrap" whitespace-nowrap>
<CommonTooltip :content="scheduledAt">
<time :datetime="item.scheduledAt" :title="item.scheduledAt">
{{ timeago }}
</time>
</CommonTooltip>
</div>
<button
p-1
rounded-full
text-secondary
hover:text-red
:title="$t('menu.delete')"
@click="handleDelete"
>
<div i-ri:delete-bin-line w-5 h-5 />
</button>
</div>

<div v-if="item.params.text" mt2>
<p v-html="item.params.text" />
</div>

<div v-if="item.mediaAttachments?.length" mt2 flex flex-wrap gap-2>
<img
v-for="media in item.mediaAttachments"
:key="media.id"
:src="(media.previewUrl || media.url) ?? undefined"
max-w-xs
rounded
:alt="media.description ?? undefined"
>
</div>
</div>
</article>
</template>
49 changes: 1 addition & 48 deletions app/components/timeline/TimelineScheduledPosts.vue
Original file line number Diff line number Diff line change
@@ -1,54 +1,7 @@
<script setup lang="ts">
import type { mastodon } from 'masto'

const paginator = useMastoClient().v1.scheduledStatuses.list()

function preprocess(items: (mastodon.v1.ScheduledStatus | mastodon.v1.Status)[]): mastodon.v1.Status[] {
const scheduledStatuses = items.filter(item => 'scheduledAt' in item) as mastodon.v1.ScheduledStatus[]
return scheduledStatuses.map((scheduledStatus) => {
return ({
...scheduledStatus.params,
id: scheduledStatus.id,
uri: '',
url: '',
content: scheduledStatus.params.text || '',
account: currentUser.value!.account,
createdAt: scheduledStatus.scheduledAt,
editedAt: scheduledStatus.scheduledAt,
reblog: null,
reblogged: false,
reblogsCount: 0,
favouritesCount: 0,
repliesCount: 0,
emojis: [],
tags: [],
mentions: [],
attachments: scheduledStatus.mediaAttachments || [],
card: null,
poll: null,
pinned: false,
bookmarked: false,
favourited: false,
filtered: [],
sensitive: scheduledStatus.params.sensitive || false,
spoilerText: scheduledStatus.params.spoilerText || '',
visibility: scheduledStatus.params.visibility || 'public',
inReplyToId: scheduledStatus.params.inReplyToId || null,
inReplyToAccountId: null,
muted: false,
mediaAttachments: scheduledStatus.mediaAttachments || [],
application: { name: '' },
quotesCount: 0,
quoteApproval: {
automatic: [],
manual: [],
currentUser: 'unknown',
},
})
})
}
</script>

<template>
<TimelineScheduledPostsPaginator end-message="common.no_scheduled_posts" :paginator="paginator" :preprocess="preprocess" />
<TimelineScheduledPostsPaginator end-message="common.no_scheduled_posts" :paginator="paginator" />
</template>
23 changes: 16 additions & 7 deletions app/components/timeline/TimelineScheduledPostsPaginator.vue
Original file line number Diff line number Diff line change
@@ -1,47 +1,56 @@
<script setup lang="ts">
import type { CommonPaginator } from '#components'
import type { mastodon } from 'masto'
import type { ComponentExposed } from 'vue-component-type-helpers'
// @ts-expect-error missing types
import { DynamicScrollerItem } from 'vue-virtual-scroller'

import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'

const { account, buffer = 10, endMessage = true } = defineProps<{
paginator: mastodon.Paginator<mastodon.v1.ScheduledStatus[], mastodon.DefaultPaginationParams>
stream?: mastodon.streaming.Subscription
context?: mastodon.v2.FilterContext
account?: mastodon.v1.Account
preprocess?: (items: (mastodon.v1.ScheduledStatus | mastodon.v1.Status)[]) => mastodon.v1.Status[]
buffer?: number
endMessage?: boolean | string
}>()

const { formatNumber } = useHumanReadableNumber()
const virtualScroller = usePreferences('experimentalVirtualScroller')

type PaginatorRef = ComponentExposed<typeof CommonPaginator>
const paginatorRef = ref<PaginatorRef>()

const showOriginSite = computed(() =>
account && account.id !== currentUser.value?.account.id && getServerName(account) !== currentServer.value,
)
</script>

<template>
<CommonPaginator v-bind="{ paginator, stream, preprocess, buffer, endMessage }" :virtual-scroller="virtualScroller">
<CommonPaginator
ref="paginatorRef"
v-bind="{ paginator, stream, buffer, endMessage }"
:virtual-scroller="virtualScroller"
>
<template #updater="{ number, update }">
<button id="elk_show_new_items" py-4 border="b base" flex="~ col" p-3 w-full text-primary font-bold @click="update">
{{ $t('timeline.show_new_items', number, { named: { v: formatNumber(number) } }) }}
</button>
</template>
<template #default="{ item, older, newer, active }">
<template #default="{ item, active }">
<component
:is="virtualScroller ? DynamicScrollerItem : 'article'"
:item="item"
:active="active"
>
<StatusCard
:status="item" :context="context" :older="older" :newer="newer" :account="account"
:actions="false" :disable-link="true"
<StatusScheduledCard
:item="item"
@deleted="paginatorRef?.removeEntry($event)"
/>
</component>
</template>
<template v-if="context === 'account' " #done="{ items }">
<template v-if="context === 'account'" #done="{ items }">
<div
v-if="showOriginSite || items.length === 0"
p5 text-secondary text-center flex flex-col items-center gap1
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@
"simple-git-hooks": "^2.13.1",
"typescript": "^5.4.4",
"vitest": "4.0.18",
"vue-component-type-helpers": "^3.2.5",
"vue-tsc": "^2.1.6"
},
"resolutions": {
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading