This commit is contained in:
Samuel Newman
2025-05-10 00:06:06 +03:00
committed by GitHub
parent 2e80fa3dac
commit a0bd804262
45 changed files with 2021 additions and 451 deletions
+51
View File
@@ -0,0 +1,51 @@
import {useMemo} from 'react'
import {
type $Typed,
type AppBskyActorDefs,
type AppBskyEmbedExternal,
} from '@atproto/api'
import {isAfter, parseISO} from 'date-fns'
import {useMaybeProfileShadow} from '#/state/cache/profile-shadow'
import {useTickEveryMinute} from '#/state/shell'
import {temp__canBeLive, temp__isStatusValid} from '#/components/live/temp'
import type * as bsky from '#/types/bsky'
export function useActorStatus(actor?: bsky.profile.AnyProfileView) {
const shadowed = useMaybeProfileShadow(actor)
const tick = useTickEveryMinute()
return useMemo(() => {
tick! // revalidate every minute
if (
shadowed &&
temp__canBeLive(shadowed) &&
'status' in shadowed &&
shadowed.status &&
temp__isStatusValid(shadowed.status) &&
isStatusStillActive(shadowed.status.expiresAt)
) {
return {
isActive: true,
status: 'app.bsky.actor.status#live',
embed: shadowed.status.embed as $Typed<AppBskyEmbedExternal.View>, // temp_isStatusValid asserts this
expiresAt: shadowed.status.expiresAt!, // isStatusStillActive asserts this
record: shadowed.status.record,
} satisfies AppBskyActorDefs.StatusView
} else {
return {
status: '',
isActive: false,
record: {},
} satisfies AppBskyActorDefs.StatusView
}
}, [shadowed, tick])
}
export function isStatusStillActive(timeStr: string | undefined) {
if (!timeStr) return false
const now = new Date()
const expiry = parseISO(timeStr)
return isAfter(expiry, now)
}
+7 -7
View File
@@ -1,10 +1,10 @@
import {
AppBskyFeedDefs,
AppBskyGraphDefs,
ComAtprotoRepoStrongRef,
type AppBskyFeedDefs,
type AppBskyGraphDefs,
type ComAtprotoRepoStrongRef,
} from '@atproto/api'
import {AtUri} from '@atproto/api'
import {BskyAgent} from '@atproto/api'
import {type BskyAgent} from '@atproto/api'
import {POST_IMG_MAX} from '#/lib/constants'
import {getLinkMeta} from '#/lib/link-meta/link-meta'
@@ -22,9 +22,9 @@ import {
isBskyStartUrl,
isShortLink,
} from '#/lib/strings/url-helpers'
import {ComposerImage} from '#/state/gallery'
import {type ComposerImage} from '#/state/gallery'
import {createComposerImage} from '#/state/gallery'
import {Gif} from '#/state/queries/tenor'
import {type Gif} from '#/state/queries/tenor'
import {createGIFDescription} from '../gif-alt-text'
import {convertBskyAppUrlIfNeeded, makeRecordUri} from '../strings/url-helpers'
@@ -213,7 +213,7 @@ async function resolveExternal(
}
}
async function imageToThumb(
export async function imageToThumb(
imageUri: string,
): Promise<ComposerImage | undefined> {
try {
+1
View File
@@ -31,6 +31,7 @@ export const DISCOVER_DEBUG_DIDS: Record<string, true> = {
'did:plc:3jpt2mvvsumj2r7eqk4gzzjz': true, // esb.lol
'did:plc:vjug55kidv6sye7ykr5faxxn': true, // emilyliu.me
'did:plc:tgqseeot47ymot4zro244fj3': true, // iwsmith.bsky.social
'did:plc:2dzyut5lxna5ljiaasgeuffz': true, // mrnuma.bsky.social
}
const BASE_FEEDBACK_FORM_URL = `${HELP_DESK_URL}/requests/new`
+30
View File
@@ -372,3 +372,33 @@ export function getServiceAuthAudFromUrl(url: string | URL): string | null {
}
return `did:web:${hostname}`
}
// passes URL.parse, and has a TLD etc
export function definitelyUrl(maybeUrl: string) {
try {
if (maybeUrl.endsWith('.')) return null
// Prepend 'https://' if the input doesn't start with a protocol
if (!maybeUrl.startsWith('https://') && !maybeUrl.startsWith('http://')) {
maybeUrl = 'https://' + maybeUrl
}
const url = new URL(maybeUrl)
// Extract the hostname and split it into labels
const hostname = url.hostname
const labels = hostname.split('.')
// Ensure there are at least two labels (e.g., 'example' and 'com')
if (labels.length < 2) return null
const tld = labels[labels.length - 1]
// Check that the TLD is at least two characters long and contains only letters
if (!/^[a-z]{2,}$/i.test(tld)) return null
return url.toString()
} catch {
return null
}
}