a51fc8e434
* Bump SDK * Use consistent type in profile query * Omit from constraint for profile shadow * Replace isRecord with isValidRecord in QuoteEmbed * Omit type from constraint for old ProfileCard * Omit type from constraint in profile queries where appropriate * Use correct type for update profile mutation * Conslidate and fix check for isValidRecord in Post.tsx * Replace isRecord with isValidRecord in PostThreadItem * Remove redundant cast in PostThreadFollowBtn * Ignore errors in DebugMod screen * Use matching type in ProfileFollows screen * Use matching type in ProfileFollowers screen * Migrate to isValidRecord in PostFeedItem * Use matching type if PostRepostedBy * Omit type from constraint in avatar props * Use matching types in NotificationFeedItem * Todo * Use isValidRecord in NotfyFeedItem * Improve MediaPreview types * Migrate another isValidRecord in NotificationFeedItem * Migrate to isValidView in queries/util * Migrate to isValidRecord in threadgate/util * Fix types in threadgates * Fix up types in starter-packs queries * Todo * Specify exact types in search-posts * Use internal type util to align types * Ditto last * Migrate postgate/index * Specify exact types in post-thread * Use correct type in post-quotes * FIX potential bug in post-thread * Use correct type in post-feed * Add correct type guards to notifications/feed * Migrate a guard in notifications/util * Migrate guard in Wizard/State * [@next] Profile handling, migrate `ProfileCard` (#7347) * Introduce new utils for profiles, migrate old ProfileCard * Rename, reorg * Add parseEmbed utils * Expand AnyProfileView to include chat profile view, update post shadow to reflect this * Cast for perf reasons * Tighten up types now that we have AnyProfileView * Add fastIsType util * Use `assertDid` Co-authored-by: Matthieu Sieben <matthieusieben@users.noreply.github.com> * Use util types * Comment * Use fastIsType where no validation was happening before * suggestions (#7382) * suggestions * Revert unneeded changes --------- Co-authored-by: Eric Bailey <git@esb.lol> * Use new util * Rename to dangerousIsType * Convert object shape * Use dangerous util * Use dangerous util * Use dangerous util, we can trust post records * Use dangerous util * Use AnyProfileVIew * Convert object shape * Clean up handling * Patch moderateProfile to accept known profile views, to discuss * Add AnyStarterPackView and related, implement in first usage * Remove validation, fix type, fix ref * Migrate over list-conversations * Clarify intent behind precacheProfile and its unstable query cache * Clean up unstable profile cache * Fix types during label creation in PwiOptOut (#7346) * Tighten types in queries/list * Chat: use correct profile views * Chat: fix log type check * Chat: construct lexically correct shape, even though it's only internal usage * Chat: use correct profile types * Chat: fix type check in logs * Starter: use correct profile types * Starter: use correct profile types * Starter: tighten types to match lex * Any profile type will work in blocked-and-muted * Use dangerous util * Use dangerousIsType * Update new ProfileCard to use AnyProfileView * Use dangerousIsType * Remove outdated todo * Use correct profile type * Use correct profile types * Tighten up types * Use dangerousIsType * Chat: more type fixes * Remove unused file * Add a few utils * Remove unused file * Ignore feedPost.__source * Clean up types, leave validation in critical path * Use dangerousIstype * Use ANyProfileView * Use isValidRecord * Use dangerousIsType * Fix types in ListCard * Fix FeedInterstitials types * Fix types in FeedCard * Fix types in dms ReportDialog * Fix types in SearchablePeopleList * Fix bad type in composer opts * Starter: ok these need to be loose too * Clarify docs Co-authored-by: Matthieu Sieben <matthieusieben@users.noreply.github.com> * Less code Co-authored-by: Matthieu Sieben <matthieusieben@users.noreply.github.com> * Use package exports Co-authored-by: Matthieu Sieben <matthieusieben@users.noreply.github.com> * Use package exports * Bump sdk, update $Typed imports * Format * Format * Fix weird TS error * Remove patch * Beter name * It's memo, can validate * Tighten up parseEmbed, dogfood * Bump sdk * Use asPredicate * Loosen types a bit * use asPredicate * Fix types * Use asPredicate * Use asPredicate * Use asPredicate * Clean up upsertProfile types * Use asPredicate * Use Un util * Fix types * Use new AnyProfileView * Use dangerousIsType * Use asPredicate * Use asPredicate * Add fallback content-type to pass typecheck * Clean up upsertProfile types * Align types * Use dangerousIsType * Use dangerousIsType * Use asPredicate * Align types * Convert findLast * Align types * Just ignore type errors and use findLast * Rename atproto -> bsky * Add validate util * Fix type error * Loosen types * Export post * rename atp bsky * Remove unused code * minor changes * Bump deps * Fix types * Tighten back up loose check * Tighten back up loose check * Fix small bug * Update comment * Revert change --------- Co-authored-by: Matthieu Sieben <matthieusieben@users.noreply.github.com> Co-authored-by: Matthieu Sieben <matthieu.sieben@gmail.com>
214 lines
5.4 KiB
TypeScript
214 lines
5.4 KiB
TypeScript
import {Keyboard, View} from 'react-native'
|
|
import {
|
|
AppBskyActorDefs,
|
|
AppBskyFeedDefs,
|
|
moderateFeedGenerator,
|
|
moderateProfile,
|
|
ModerationOpts,
|
|
ModerationUI,
|
|
} from '@atproto/api'
|
|
import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs'
|
|
import {msg, Trans} from '@lingui/macro'
|
|
import {useLingui} from '@lingui/react'
|
|
|
|
import {DISCOVER_FEED_URI, STARTER_PACK_MAX_SIZE} from '#/lib/constants'
|
|
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
|
import {useSession} from '#/state/session'
|
|
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
|
import {WizardAction, WizardState} from '#/screens/StarterPack/Wizard/State'
|
|
import {atoms as a, useTheme} from '#/alf'
|
|
import {Button, ButtonText} from '#/components/Button'
|
|
import * as Toggle from '#/components/forms/Toggle'
|
|
import {Checkbox} from '#/components/forms/Toggle'
|
|
import {Text} from '#/components/Typography'
|
|
import * as bsky from '#/types/bsky'
|
|
|
|
function WizardListCard({
|
|
type,
|
|
btnType,
|
|
displayName,
|
|
subtitle,
|
|
onPress,
|
|
avatar,
|
|
included,
|
|
disabled,
|
|
moderationUi,
|
|
}: {
|
|
type: 'user' | 'algo'
|
|
btnType: 'checkbox' | 'remove'
|
|
profile?: AppBskyActorDefs.ProfileViewBasic
|
|
feed?: AppBskyFeedDefs.GeneratorView
|
|
displayName: string
|
|
subtitle: string
|
|
onPress: () => void
|
|
avatar?: string
|
|
included?: boolean
|
|
disabled?: boolean
|
|
moderationUi: ModerationUI
|
|
}) {
|
|
const t = useTheme()
|
|
const {_} = useLingui()
|
|
|
|
return (
|
|
<Toggle.Item
|
|
name={type === 'user' ? _(msg`Person toggle`) : _(msg`Feed toggle`)}
|
|
label={
|
|
included
|
|
? _(msg`Remove ${displayName} from starter pack`)
|
|
: _(msg`Add ${displayName} to starter pack`)
|
|
}
|
|
value={included}
|
|
disabled={btnType === 'remove' || disabled}
|
|
onChange={onPress}
|
|
style={[
|
|
a.flex_row,
|
|
a.align_center,
|
|
a.px_lg,
|
|
a.py_md,
|
|
a.gap_md,
|
|
a.border_b,
|
|
t.atoms.border_contrast_low,
|
|
]}>
|
|
<UserAvatar
|
|
size={45}
|
|
avatar={avatar}
|
|
moderation={moderationUi}
|
|
type={type}
|
|
/>
|
|
<View style={[a.flex_1, a.gap_2xs]}>
|
|
<Text
|
|
emoji
|
|
style={[
|
|
a.flex_1,
|
|
a.font_bold,
|
|
a.text_md,
|
|
a.leading_tight,
|
|
a.self_start,
|
|
]}
|
|
numberOfLines={1}>
|
|
{displayName}
|
|
</Text>
|
|
<Text
|
|
style={[a.flex_1, a.leading_tight, t.atoms.text_contrast_medium]}
|
|
numberOfLines={1}>
|
|
{subtitle}
|
|
</Text>
|
|
</View>
|
|
{btnType === 'checkbox' ? (
|
|
<Checkbox />
|
|
) : !disabled ? (
|
|
<Button
|
|
label={_(msg`Remove`)}
|
|
variant="solid"
|
|
color="secondary"
|
|
size="small"
|
|
style={[a.self_center, {marginLeft: 'auto'}]}
|
|
onPress={onPress}>
|
|
<ButtonText>
|
|
<Trans>Remove</Trans>
|
|
</ButtonText>
|
|
</Button>
|
|
) : null}
|
|
</Toggle.Item>
|
|
)
|
|
}
|
|
|
|
export function WizardProfileCard({
|
|
btnType,
|
|
state,
|
|
dispatch,
|
|
profile,
|
|
moderationOpts,
|
|
}: {
|
|
btnType: 'checkbox' | 'remove'
|
|
state: WizardState
|
|
dispatch: (action: WizardAction) => void
|
|
profile: bsky.profile.AnyProfileView
|
|
moderationOpts: ModerationOpts
|
|
}) {
|
|
const {currentAccount} = useSession()
|
|
|
|
const isMe = profile.did === currentAccount?.did
|
|
const included = isMe || state.profiles.some(p => p.did === profile.did)
|
|
const disabled =
|
|
isMe || (!included && state.profiles.length >= STARTER_PACK_MAX_SIZE - 1)
|
|
const moderationUi = moderateProfile(profile, moderationOpts).ui('avatar')
|
|
const displayName = profile.displayName
|
|
? sanitizeDisplayName(profile.displayName)
|
|
: `@${sanitizeHandle(profile.handle)}`
|
|
|
|
const onPress = () => {
|
|
if (disabled) return
|
|
|
|
Keyboard.dismiss()
|
|
if (profile.did === currentAccount?.did) return
|
|
|
|
if (!included) {
|
|
dispatch({type: 'AddProfile', profile})
|
|
} else {
|
|
dispatch({type: 'RemoveProfile', profileDid: profile.did})
|
|
}
|
|
}
|
|
|
|
return (
|
|
<WizardListCard
|
|
type="user"
|
|
btnType={btnType}
|
|
displayName={displayName}
|
|
subtitle={`@${sanitizeHandle(profile.handle)}`}
|
|
onPress={onPress}
|
|
avatar={profile.avatar}
|
|
included={included}
|
|
disabled={disabled}
|
|
moderationUi={moderationUi}
|
|
/>
|
|
)
|
|
}
|
|
|
|
export function WizardFeedCard({
|
|
btnType,
|
|
generator,
|
|
state,
|
|
dispatch,
|
|
moderationOpts,
|
|
}: {
|
|
btnType: 'checkbox' | 'remove'
|
|
generator: GeneratorView
|
|
state: WizardState
|
|
dispatch: (action: WizardAction) => void
|
|
moderationOpts: ModerationOpts
|
|
}) {
|
|
const isDiscover = generator.uri === DISCOVER_FEED_URI
|
|
const included = isDiscover || state.feeds.some(f => f.uri === generator.uri)
|
|
const disabled = isDiscover || (!included && state.feeds.length >= 3)
|
|
const moderationUi = moderateFeedGenerator(generator, moderationOpts).ui(
|
|
'avatar',
|
|
)
|
|
|
|
const onPress = () => {
|
|
if (disabled) return
|
|
|
|
Keyboard.dismiss()
|
|
if (included) {
|
|
dispatch({type: 'RemoveFeed', feedUri: generator.uri})
|
|
} else {
|
|
dispatch({type: 'AddFeed', feed: generator})
|
|
}
|
|
}
|
|
|
|
return (
|
|
<WizardListCard
|
|
type="algo"
|
|
btnType={btnType}
|
|
displayName={sanitizeDisplayName(generator.displayName)}
|
|
subtitle={`Feed by @${sanitizeHandle(generator.creator.handle)}`}
|
|
onPress={onPress}
|
|
avatar={generator.avatar}
|
|
included={included}
|
|
disabled={disabled}
|
|
moderationUi={moderationUi}
|
|
/>
|
|
)
|
|
}
|