mirror of
https://github.com/d0zingcat/BroadcastChannel.git
synced 2026-05-28 15:09:55 +00:00
feat: init
This commit is contained in:
135
src/components/header.astro
Normal file
135
src/components/header.astro
Normal file
@@ -0,0 +1,135 @@
|
||||
---
|
||||
import { getEnv } from '../lib/env'
|
||||
import voidFile from '../assets/void.png'
|
||||
import rss from '../assets/rss.svg'
|
||||
import podcast from '../assets/podcast.svg'
|
||||
import twitter from '../assets/twitter.svg'
|
||||
import github from '../assets/github.svg'
|
||||
import discord from '../assets/discord.svg'
|
||||
import telegram from '../assets/telegram.svg'
|
||||
|
||||
const { SITE_URL } = Astro.locals
|
||||
const { channel } = Astro.props
|
||||
|
||||
const PODCASRT = getEnv(import.meta.env, Astro, 'PODCASRT')
|
||||
const TWITTER = getEnv(import.meta.env, Astro, 'TWITTER')
|
||||
const GITHUB = getEnv(import.meta.env, Astro, 'GITHUB')
|
||||
const TELEGRAM = getEnv(import.meta.env, Astro, 'TELEGRAM')
|
||||
const DISCORD = getEnv(import.meta.env, Astro, 'DISCORD')
|
||||
|
||||
const staticProxy = getEnv(import.meta.env, Astro, 'STATIC_PROXY') ?? '/static/'
|
||||
---
|
||||
|
||||
<div id="header">
|
||||
<a href={SITE_URL} title={channel?.title}>
|
||||
<img
|
||||
src={channel?.avatar?.startsWith('http')
|
||||
? staticProxy + channel?.avatar
|
||||
: voidFile.src}
|
||||
alt={channel?.title}
|
||||
class="header-avatar"
|
||||
/>
|
||||
</a>
|
||||
<div class="header-title">
|
||||
<a href={SITE_URL} class="site-title" title={channel?.title}>
|
||||
{channel?.title}
|
||||
</a>
|
||||
</div>
|
||||
<div class="header-icons">
|
||||
<a
|
||||
href={`${SITE_URL}rss.xml`}
|
||||
target="_blank"
|
||||
rel="alternate"
|
||||
type="application/rss+xml"
|
||||
title="RSS Feed"
|
||||
>
|
||||
<img {...rss} alt="RSS" class="social-icon" width="1em" />
|
||||
</a>
|
||||
|
||||
{
|
||||
PODCASRT && (
|
||||
<a href={PODCASRT} target="_blank" title="Podcast">
|
||||
<img {...podcast} alt="Podcast" class="social-icon" width="1em" />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
TWITTER && TWITTER.length > 0 && (
|
||||
<a
|
||||
href={`https://twitter.com/${TWITTER}`}
|
||||
title="Twitter"
|
||||
target="_blank"
|
||||
>
|
||||
<img
|
||||
{...twitter}
|
||||
alt={`twitter.com/${TWITTER}`}
|
||||
class="social-icon"
|
||||
width="1em"
|
||||
/>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
GITHUB && GITHUB.length > 0 && (
|
||||
<a href={`https://github.com/${GITHUB}`} title="Github" target="_blank">
|
||||
<img
|
||||
{...github}
|
||||
alt={`github.com/${GITHUB}`}
|
||||
class="social-icon"
|
||||
width="1em"
|
||||
/>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
TELEGRAM && TELEGRAM.length > 0 && (
|
||||
<a href={`https://t.me/${TELEGRAM}`} title="Telegram" target="_blank">
|
||||
<img
|
||||
{...telegram}
|
||||
alt={`t.me/${TELEGRAM}`}
|
||||
class="social-icon"
|
||||
width="1em"
|
||||
/>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
DISCORD && DISCORD.length > 0 && (
|
||||
<a href={DISCORD} title="Discord" target="_blank">
|
||||
<img
|
||||
{...discord}
|
||||
alt="Discord Invite"
|
||||
class="social-icon"
|
||||
width="1em"
|
||||
/>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{
|
||||
channel?.description && channel?.description.length > 0 && (
|
||||
<div class="text-box" id="site-intro">
|
||||
{channel?.description}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
<style>
|
||||
#site-intro {
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
|
||||
.social-icon {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.header-icons {
|
||||
gap: 2px;
|
||||
}
|
||||
</style>
|
||||
177
src/components/item.astro
Normal file
177
src/components/item.astro
Normal file
@@ -0,0 +1,177 @@
|
||||
---
|
||||
import dayjs from '../lib/dayjs'
|
||||
import { getEnv } from '../lib/env'
|
||||
|
||||
const locale = getEnv(import.meta.env, Astro, 'LOCALE')
|
||||
const timezone = getEnv(import.meta.env, Astro, 'TIMEZONE')
|
||||
|
||||
locale && dayjs.locale(locale)
|
||||
|
||||
const { SITE_URL } = Astro.locals
|
||||
const { post } = Astro.props
|
||||
|
||||
const datetime = dayjs(post.datetime).tz(timezone)
|
||||
const timeago = datetime.isBefore(dayjs().subtract(1, 'w'))
|
||||
? datetime.format('HH:mm · ll · ddd')
|
||||
: datetime.fromNow()
|
||||
---
|
||||
|
||||
<div class="item" style={{ 'view-transition-name': `post-${post.id}` }}>
|
||||
<div class="time-box">
|
||||
<div class="dot"></div>
|
||||
<div class="time">
|
||||
<a
|
||||
href={`${SITE_URL}posts/${post.id}`}
|
||||
title={post.datetime}
|
||||
class="item-link">{timeago}</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
post.content.length > 0 && (
|
||||
<div class={`text-box content`} set:html={post.content} />
|
||||
)
|
||||
}
|
||||
{
|
||||
post.tags.length > 0 && (
|
||||
<div
|
||||
class="tag-box"
|
||||
style={post.content.length === 0 ? 'padding-top: 30px;' : ''}
|
||||
>
|
||||
<div class="tag-icon" />
|
||||
{post.tags.map((tag) => (
|
||||
<a href={`/search/%23${tag}`} title={tag} class="tag">
|
||||
{tag}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.content {
|
||||
word-break: break-word;
|
||||
}
|
||||
.content :global(img) {
|
||||
width: calc(100% - var(--box-margin));
|
||||
}
|
||||
.content :global(.tgme_widget_message_link_preview) {
|
||||
margin-top: 16px;
|
||||
display: none;
|
||||
|
||||
.link_preview_site_name,
|
||||
.link_preview_title,
|
||||
.link_preview_description {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.content
|
||||
:global(.tgme_widget_message_link_preview):has(.link_preview_site_name) {
|
||||
display: block;
|
||||
background: var(--cell-background-color);
|
||||
border-left: 3px solid var(--highlight-color);
|
||||
padding: 6px;
|
||||
padding-left: 10px;
|
||||
border-radius: var(--box-border-radius);
|
||||
|
||||
.link_preview_title {
|
||||
display: block;
|
||||
font-size: 1em;
|
||||
font-weight: bolder;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.link_preview_description {
|
||||
display: block;
|
||||
font-size: 0.8em;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
.content :global(.tgme_widget_message_video) {
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
|
||||
.content :global(.tgme_widget_message_link_preview):has(.link_preview_image) {
|
||||
display: flex;
|
||||
position: relative;
|
||||
border: none;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
|
||||
.link_preview_image {
|
||||
aspect-ratio: 1200 / 630;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.link_preview_site_name {
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: var(--box-margin);
|
||||
left: var(--box-margin);
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
background-color: rgba(0, 0, 0, 0.66);
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
line-height: 1.5;
|
||||
border-radius: var(--box-border-radius);
|
||||
text-overflow: ellipsis;
|
||||
max-width: calc(100% - 28px);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.link_preview_title,
|
||||
.link_preview_description {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.content :global(blockquote) {
|
||||
margin: 16px 0;
|
||||
font-size: 0.8em;
|
||||
background: var(--cell-background-color);
|
||||
border-left: 3px solid var(--highlight-color);
|
||||
padding: 6px;
|
||||
padding-left: 10px;
|
||||
border-radius: var(--box-border-radius);
|
||||
}
|
||||
|
||||
.content :global(.tgme_widget_message_sticker) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.item :global(.content):has(.tgme_widget_message_user_photo) {
|
||||
display: flex;
|
||||
|
||||
.tgme_widget_message_user_photo {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.content :global(.tgme_widget_message_voice) {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.content :global(.tgme_widget_message_poll_options) {
|
||||
display: block;
|
||||
|
||||
.tgme_widget_message_poll_option_percent {
|
||||
float: left;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.content :global(.tgme_widget_message_location_wrap) {
|
||||
display: block;
|
||||
.tgme_widget_message_location {
|
||||
padding-top: 50%;
|
||||
background: no-repeat center;
|
||||
background-size: cover;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
49
src/components/list.astro
Normal file
49
src/components/list.astro
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
import Layout from '../layouts/base.astro'
|
||||
import Header from '../components/header.astro'
|
||||
import Item from '../components/item.astro'
|
||||
|
||||
const { SITE_URL } = Astro.locals
|
||||
const { channel, before = true, after = true } = Astro.props
|
||||
const posts = channel.posts ?? []
|
||||
|
||||
const beforeCursor = posts[posts.length - 1]?.id
|
||||
const afterCursor = posts[0]?.id
|
||||
// const cursor = +Astro.params.cursor
|
||||
---
|
||||
|
||||
<Layout channel={channel} id="main-container">
|
||||
<slot name="header">
|
||||
<Header channel={channel} />
|
||||
</slot>
|
||||
<div class="items">
|
||||
{posts.map((post) => <Item post={post} />)}
|
||||
</div>
|
||||
|
||||
<div class="pages-container">
|
||||
{
|
||||
before && beforeCursor > 20 ? (
|
||||
<a
|
||||
href={`${SITE_URL}before/${beforeCursor}`}
|
||||
title="Before"
|
||||
class="page"
|
||||
>
|
||||
Before
|
||||
</a>
|
||||
) : (
|
||||
<span class="page-placeholder"> </span>
|
||||
)
|
||||
}
|
||||
|
||||
<div class="pages-info"></div>
|
||||
{
|
||||
after && afterCursor ? (
|
||||
<a href={`${SITE_URL}after/${afterCursor}`} title="After" class="page">
|
||||
After
|
||||
</a>
|
||||
) : (
|
||||
<span class="page-placeholder"> </span>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</Layout>
|
||||
Reference in New Issue
Block a user