Compare commits

...

12 Commits

Author SHA1 Message Date
Samuel Newman f17418c131 use correct color for avi 2024-12-03 17:15:43 +00:00
Samuel Newman 84213eabcb theme entire profile 2024-12-03 17:15:43 +00:00
Samuel Newman a8ac790fb3 fix type error 2024-12-03 17:15:43 +00:00
Samuel Newman b77eec8079 made color much more subtle 2024-12-03 17:15:42 +00:00
Samuel Newman 6f7ee7efab dynamic rich text color 2024-12-03 17:15:42 +00:00
Samuel Newman f9ade07f81 fix missing prop 2024-12-03 17:15:42 +00:00
Samuel Newman db86b6048e rm custom scales 2024-12-03 17:15:42 +00:00
Samuel Newman 28c764e6ca remove useProfileTheme in favour of nesting main provider 2024-12-03 17:15:42 +00:00
Samuel Newman 72ecc4355c dark mode 2024-12-03 17:15:42 +00:00
Hailey 06fc413eab tweaks 2024-12-03 17:15:42 +00:00
Hailey 5335c8c2d4 two hundred 2024-12-03 17:15:42 +00:00
Hailey 5551549e13 remove default bg color from profile header 2024-12-03 17:15:42 +00:00
16 changed files with 341 additions and 172 deletions
+3
View File
@@ -156,6 +156,7 @@
"lodash.isequal": "^4.5.0",
"lodash.shuffle": "^4.2.0",
"lodash.throttle": "^4.1.1",
"mix-css-color": "^0.2.0",
"multiformats": "^13.1.0",
"nanoid": "^5.0.5",
"normalize-url": "^8.0.0",
@@ -200,6 +201,7 @@
"tippy.js": "^6.3.7",
"tlds": "^1.234.0",
"tldts": "^6.1.46",
"wcag-contrast": "^3.0.0",
"zeego": "^1.6.2",
"zod": "^3.20.2"
},
@@ -227,6 +229,7 @@
"@types/react-dom": "^18.2.18",
"@types/react-responsive": "^8.0.5",
"@types/react-test-renderer": "^17.0.1",
"@types/wcag-contrast": "^3.0.3",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"babel-jest": "^29.7.0",
+1 -1
View File
@@ -122,7 +122,7 @@ function InnerApp() {
}, [_])
return (
<Alf theme={theme}>
<Alf themeName={theme}>
<ThemeProvider theme={theme}>
<Splash isReady={isReady && hasCheckedReferrer}>
<RootSiblingParent>
+1 -1
View File
@@ -101,7 +101,7 @@ function InnerApp() {
if (!isReady || !hasCheckedReferrer) return null
return (
<Alf theme={theme}>
<Alf themeName={theme}>
<ThemeProvider theme={theme}>
<RootSiblingParent>
<VideoVolumeProvider>
+12 -3
View File
@@ -63,8 +63,12 @@ export const Context = React.createContext<Alf>({
export function ThemeProvider({
children,
theme: themeName,
}: React.PropsWithChildren<{theme: ThemeName}>) {
themeName,
theme,
}: React.PropsWithChildren<{
themeName: ThemeName
theme?: ReturnType<typeof createThemes>
}>) {
const [fontScale, setFontScale] = React.useState<Alf['fonts']['scale']>(() =>
getFontScale(),
)
@@ -74,6 +78,7 @@ export function ThemeProvider({
const setFontScaleAndPersist = React.useCallback<
Alf['fonts']['setFontScale']
>(
// eslint-disable-next-line @typescript-eslint/no-shadow
fontScale => {
setFontScale(fontScale)
persistFontScale(fontScale)
@@ -87,6 +92,7 @@ export function ThemeProvider({
const setFontFamilyAndPersist = React.useCallback<
Alf['fonts']['setFontFamily']
>(
// eslint-disable-next-line @typescript-eslint/no-shadow
fontFamily => {
setFontFamily(fontFamily)
persistFontFamily(fontFamily)
@@ -94,6 +100,9 @@ export function ThemeProvider({
[setFontFamily],
)
const themes = React.useMemo(() => {
if (theme) {
return theme
}
return createThemes({
hues: {
primary: BLUE_HUE,
@@ -101,7 +110,7 @@ export function ThemeProvider({
positive: GREEN_HUE,
},
})
}, [])
}, [theme])
const value = React.useMemo<Alf>(
() => ({
+14 -14
View File
@@ -8,13 +8,14 @@ import {useNavigation} from '@react-navigation/native'
import {NavigationProp} from '#/lib/routes/types'
import {toShortUrl} from '#/lib/strings/url-helpers'
import {isNative} from '#/platform/detection'
import {atoms as a, flatten, native, TextStyleProp, useTheme, web} from '#/alf'
import {atoms as a, flatten, native, TextStyleProp, web} from '#/alf'
import {isOnlyEmoji} from '#/alf/typography'
import {useInteractionState} from '#/components/hooks/useInteractionState'
import {InlineLinkText, LinkProps} from '#/components/Link'
import {ProfileHoverCard} from '#/components/ProfileHoverCard'
import {TagMenu, useTagMenuControl} from '#/components/TagMenu'
import {Text, TextProps} from '#/components/Typography'
import {useDynamicColor} from './hooks/useDynamicColor'
const WORD_WRAP = {wordWrap: 1}
@@ -29,6 +30,7 @@ export type RichTextProps = TextStyleProp &
onLinkPress?: LinkProps['onPress']
interactiveStyle?: TextStyle
emojiMultiplier?: number
dynamicColor?: boolean
}
export function RichText({
@@ -43,6 +45,7 @@ export function RichText({
onLinkPress,
interactiveStyle,
emojiMultiplier = 1.85,
dynamicColor = false,
}: RichTextProps) {
const richText = React.useMemo(
() =>
@@ -50,10 +53,13 @@ export function RichText({
[value],
)
const interactiveColor = useDynamicColor({enabled: dynamicColor})
const flattenedStyle = flatten(style)
const plainStyles = [a.leading_snug, flattenedStyle]
const interactiveStyles = [
a.leading_snug,
interactiveColor,
flatten(interactiveStyle),
flattenedStyle,
]
@@ -182,7 +188,6 @@ function RichTextTag({
selectable?: boolean
authorHandle?: string
} & TextStyleProp) {
const t = useTheme()
const {_} = useLingui()
const control = useTagMenuControl()
const {
@@ -224,22 +229,17 @@ function RichTextTag({
{...web({
onMouseEnter: onHoverIn,
onMouseLeave: onHoverOut,
onFocus: onFocus,
onBlur: onBlur,
})}
// @ts-ignore
onFocus={onFocus}
onBlur={onBlur}
style={[
web({
cursor: 'pointer',
}),
{color: t.palette.primary_500},
(hovered || focused) && {
...web({
web({cursor: 'pointer'}),
web(
(hovered || focused) && {
outline: 0,
textDecorationLine: 'underline',
textDecorationColor: t.palette.primary_500,
}),
},
},
),
style,
]}>
{text}
+1 -1
View File
@@ -76,7 +76,7 @@ export function MessageProfileButton({
accessibilityRole="button"
testID="dmBtn"
size="small"
color="secondary"
color="secondary_inverted"
variant="solid"
shape="round"
label={_(msg`Message ${profile.handle}`)}
+61
View File
@@ -0,0 +1,61 @@
import {useMemo} from 'react'
import {StyleProp, TextStyle} from 'react-native'
import mixColors from 'mix-css-color'
import {rgb as compareContrast} from 'wcag-contrast'
import {useTheme} from '#/alf'
export function useDynamicColor({enabled} = {enabled: false}) {
const t = useTheme()
const color = enabled
? getDynamicColor(t.name !== 'light', t.palette.primary_500)
: t.palette.primary_500
return useMemo(
() =>
({
color,
textDecorationColor: color,
} satisfies StyleProp<TextStyle>),
[color],
)
}
// the goal is to return a blue color that should be an acceptable constrast with
// the background color. the default blue is rgb(16, 131, 254)
// we want to color mix it with the background color
// and flip to whiteish if it's going to be unacceptable low contrast
const BASE_COLOR_LIGHT = 'rgb(16, 131, 254)'
const BASE_COLOR_DARK = 'rgb(32, 139, 254)'
function getDynamicColor(dark: boolean, themeColor: string) {
const baseColor = dark ? BASE_COLOR_DARK : BASE_COLOR_LIGHT
const blendedColor = mixColors(baseColor, themeColor, 75)
debugColorContrast(
blendedColor,
// for debug, we simulate the linear gradient on the profile
mixColors(themeColor, '#ffffff', 30),
)
let [h, s, l] = blendedColor.hsla
return `hsl(${h}, ${s}%, ${l * 1.1}%)`
}
function debugColorContrast(
foreground: ReturnType<typeof mixColors>,
background: ReturnType<typeof mixColors>,
) {
const score = getContrastScore(foreground, background)
console.log(
`%c ${score > 4.5 ? 'PASS' : 'FAIL'}: ${Math.trunc(score * 10) / 10} `,
`color: ${foreground.hex}; background: ${background.hex}`,
)
}
function getContrastScore(
foreground: ReturnType<typeof mixColors>,
background: ReturnType<typeof mixColors>,
) {
const [r1, g1, b1] = foreground.rgba
const [r2, g2, b2] = background.rgba
return compareContrast([r1, g1, b1], [r2, g2, b2])
}
@@ -49,6 +49,7 @@ interface Props {
moderationOpts: ModerationOpts
hideBackButton?: boolean
isPlaceholderProfile?: boolean
backgroundColor: string
}
let ProfileHeaderLabeler = ({
@@ -58,6 +59,7 @@ let ProfileHeaderLabeler = ({
moderationOpts,
hideBackButton = false,
isPlaceholderProfile,
backgroundColor,
}: Props): React.ReactNode => {
const profile: Shadow<AppBskyActorDefs.ProfileViewDetailed> =
useProfileShadow(profileUnshadowed)
@@ -168,7 +170,8 @@ let ProfileHeaderLabeler = ({
profile={profile}
moderation={moderation}
hideBackButton={hideBackButton}
isPlaceholderProfile={isPlaceholderProfile}>
isPlaceholderProfile={isPlaceholderProfile}
backgroundColor={backgroundColor}>
<View
style={[a.px_lg, a.pt_md, a.pb_sm]}
pointerEvents={isIOS ? 'auto' : 'box-none'}>
@@ -261,6 +264,7 @@ let ProfileHeaderLabeler = ({
value={descriptionRT}
enableTags
authorHandle={profile.handle}
dynamicColor
/>
</View>
) : undefined}
@@ -46,6 +46,7 @@ interface Props {
moderationOpts: ModerationOpts
hideBackButton?: boolean
isPlaceholderProfile?: boolean
backgroundColor: string
}
let ProfileHeaderStandard = ({
@@ -54,6 +55,7 @@ let ProfileHeaderStandard = ({
moderationOpts,
hideBackButton = false,
isPlaceholderProfile,
backgroundColor,
}: Props): React.ReactNode => {
const profile: Shadow<AppBskyActorDefs.ProfileViewDetailed> =
useProfileShadow(profileUnshadowed)
@@ -153,7 +155,8 @@ let ProfileHeaderStandard = ({
profile={profile}
moderation={moderation}
hideBackButton={hideBackButton}
isPlaceholderProfile={isPlaceholderProfile}>
isPlaceholderProfile={isPlaceholderProfile}
backgroundColor={backgroundColor}>
<View
style={[a.px_lg, a.pt_md, a.pb_sm, a.overflow_hidden]}
pointerEvents={isIOS ? 'auto' : 'box-none'}>
@@ -173,11 +176,10 @@ let ProfileHeaderStandard = ({
<Button
testID="profileHeaderEditProfileButton"
size="small"
color="secondary"
color="secondary_inverted"
variant="solid"
onPress={onPressEditProfile}
label={_(msg`Edit profile`)}
style={[a.rounded_full]}>
label={_(msg`Edit profile`)}>
<ButtonText>
<Trans>Edit Profile</Trans>
</ButtonText>
@@ -210,7 +212,9 @@ let ProfileHeaderStandard = ({
<Button
testID={profile.viewer?.following ? 'unfollowBtn' : 'followBtn'}
size="small"
color={profile.viewer?.following ? 'secondary' : 'primary'}
color={
profile.viewer?.following ? 'secondary_inverted' : 'primary'
}
variant="solid"
label={
profile.viewer?.following
+16 -2
View File
@@ -1,6 +1,7 @@
import React, {memo} from 'react'
import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native'
import {MeasuredDimensions, runOnJS, runOnUI} from 'react-native-reanimated'
import {LinearGradient} from 'expo-linear-gradient'
import {AppBskyActorDefs, ModerationDecision} from '@atproto/api'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg} from '@lingui/macro'
@@ -29,6 +30,7 @@ interface Props {
moderation: ModerationDecision
hideBackButton?: boolean
isPlaceholderProfile?: boolean
backgroundColor: string
}
let ProfileHeaderShell = ({
@@ -37,6 +39,7 @@ let ProfileHeaderShell = ({
moderation,
hideBackButton = false,
isPlaceholderProfile,
backgroundColor,
}: React.PropsWithChildren<Props>): React.ReactNode => {
const t = useTheme()
const {currentAccount} = useSession()
@@ -96,7 +99,18 @@ let ProfileHeaderShell = ({
)
return (
<View style={t.atoms.bg} pointerEvents={isIOS ? 'auto' : 'box-none'}>
<View pointerEvents={isIOS ? 'auto' : 'box-none'}>
<LinearGradient
key={t.name}
colors={[t.palette.primary_25, t.palette.primary_25, backgroundColor]}
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
<View
pointerEvents={isIOS ? 'auto' : 'box-none'}
style={[a.relative, {height: 150}]}>
@@ -162,7 +176,7 @@ let ProfileHeaderShell = ({
<View
style={[
t.atoms.bg,
{borderColor: t.atoms.bg.backgroundColor},
{borderColor: t.palette.primary_25},
styles.avi,
profile.associated?.labeler && styles.aviLabeler,
]}>
+1
View File
@@ -43,6 +43,7 @@ interface Props {
moderationOpts: ModerationOpts
hideBackButton?: boolean
isPlaceholderProfile?: boolean
backgroundColor: string
}
let ProfileHeader = (props: Props): React.ReactNode => {
+1 -1
View File
@@ -179,7 +179,7 @@ let ProfileMenu = ({
label={_(msg`More options`)}
hitSlop={HITSLOP_20}
variant="solid"
color="secondary"
color="secondary_inverted"
size="small"
shape="round">
<ButtonIcon icon={Ellipsis} size="sm" />
+1
View File
@@ -917,6 +917,7 @@ function MockAccountScreen({
profile={profile}
moderationOpts={moderationOpts}
descriptionRT={new RichText({text: profile.description as string})}
backgroundColor={t.atoms.bg.backgroundColor}
/>
</ScreenHider>
</View>
+161 -139
View File
@@ -44,7 +44,8 @@ import {CenteredView} from '#/view/com/util/Views'
import {ProfileHeader, ProfileHeaderLoading} from '#/screens/Profile/Header'
import {ProfileFeedSection} from '#/screens/Profile/Sections/Feed'
import {ProfileLabelsSection} from '#/screens/Profile/Sections/Labels'
import {web} from '#/alf'
import {ThemeProvider as Alf, useTheme, web} from '#/alf'
import {createThemes} from '#/alf/themes'
import * as Layout from '#/components/Layout'
import {ScreenHider} from '#/components/moderation/ScreenHider'
import {ProfileStarterPacks} from '#/components/StarterPack/ProfileStarterPacks'
@@ -341,6 +342,24 @@ function ProfileScreenLoaded({
// rendering
// =
const [hue, setHue] = React.useState(0)
React.useEffect(() => {
const id = setInterval(() => {
setHue(Math.random() * 360)
}, 5000)
return () => clearInterval(id)
}, [])
const t = useTheme()
const theme = createThemes({
hues: {
primary: hue,
negative: 0,
positive: 0,
},
})
const renderHeader = () => {
return (
<ExpoScrollForwarderView scrollViewTag={scrollViewTag}>
@@ -351,6 +370,7 @@ function ProfileScreenLoaded({
moderationOpts={moderationOpts}
hideBackButton={hideBackButton}
isPlaceholderProfile={showPlaceholder}
backgroundColor={t.atoms.bg.backgroundColor}
/>
</ExpoScrollForwarderView>
)
@@ -362,141 +382,143 @@ function ProfileScreenLoaded({
style={styles.container}
screenDescription={_(msg`profile`)}
modui={moderation.ui('profileView')}>
<PagerWithHeader
testID="profilePager"
isHeaderReady={!showPlaceholder}
items={sectionTitles}
onPageSelected={onPageSelected}
onCurrentPageSelected={onCurrentPageSelected}
renderHeader={renderHeader}
allowHeaderOverScroll>
{showFiltersTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileLabelsSection
ref={labelsSectionRef}
labelerInfo={labelerInfo}
labelerError={labelerError}
isLabelerLoading={isLabelerLoading}
moderationOpts={moderationOpts}
scrollElRef={scrollElRef as ListRef}
headerHeight={headerHeight}
isFocused={isFocused}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showListsTab && !!profile.associated?.labeler
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileLists
ref={listsSectionRef}
did={profile.did}
scrollElRef={scrollElRef as ListRef}
headerOffset={headerHeight}
enabled={isFocused}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showPostsTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileFeedSection
ref={postsSectionRef}
feed={`author|${profile.did}|posts_and_author_threads`}
headerHeight={headerHeight}
isFocused={isFocused}
scrollElRef={scrollElRef as ListRef}
ignoreFilterFor={profile.did}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showRepliesTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileFeedSection
ref={repliesSectionRef}
feed={`author|${profile.did}|posts_with_replies`}
headerHeight={headerHeight}
isFocused={isFocused}
scrollElRef={scrollElRef as ListRef}
ignoreFilterFor={profile.did}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showMediaTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileFeedSection
ref={mediaSectionRef}
feed={`author|${profile.did}|posts_with_media`}
headerHeight={headerHeight}
isFocused={isFocused}
scrollElRef={scrollElRef as ListRef}
ignoreFilterFor={profile.did}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showLikesTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileFeedSection
ref={likesSectionRef}
feed={`likes|${profile.did}`}
headerHeight={headerHeight}
isFocused={isFocused}
scrollElRef={scrollElRef as ListRef}
ignoreFilterFor={profile.did}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showFeedsTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileFeedgens
ref={feedsSectionRef}
did={profile.did}
scrollElRef={scrollElRef as ListRef}
headerOffset={headerHeight}
enabled={isFocused}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showStarterPacksTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileStarterPacks
ref={starterPacksSectionRef}
isMe={isMe}
starterPacksQuery={starterPacksQuery}
scrollElRef={scrollElRef as ListRef}
headerOffset={headerHeight}
enabled={isFocused}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showListsTab && !profile.associated?.labeler
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileLists
ref={listsSectionRef}
did={profile.did}
scrollElRef={scrollElRef as ListRef}
headerOffset={headerHeight}
enabled={isFocused}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
</PagerWithHeader>
{hasSession && (
<FAB
testID="composeFAB"
onPress={onPressCompose}
icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
accessibilityRole="button"
accessibilityLabel={_(msg`New post`)}
accessibilityHint=""
/>
)}
<Alf themeName={t.name} theme={theme}>
<PagerWithHeader
testID="profilePager"
isHeaderReady={!showPlaceholder}
items={sectionTitles}
onPageSelected={onPageSelected}
onCurrentPageSelected={onCurrentPageSelected}
renderHeader={renderHeader}
allowHeaderOverScroll>
{showFiltersTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileLabelsSection
ref={labelsSectionRef}
labelerInfo={labelerInfo}
labelerError={labelerError}
isLabelerLoading={isLabelerLoading}
moderationOpts={moderationOpts}
scrollElRef={scrollElRef as ListRef}
headerHeight={headerHeight}
isFocused={isFocused}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showListsTab && !!profile.associated?.labeler
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileLists
ref={listsSectionRef}
did={profile.did}
scrollElRef={scrollElRef as ListRef}
headerOffset={headerHeight}
enabled={isFocused}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showPostsTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileFeedSection
ref={postsSectionRef}
feed={`author|${profile.did}|posts_and_author_threads`}
headerHeight={headerHeight}
isFocused={isFocused}
scrollElRef={scrollElRef as ListRef}
ignoreFilterFor={profile.did}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showRepliesTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileFeedSection
ref={repliesSectionRef}
feed={`author|${profile.did}|posts_with_replies`}
headerHeight={headerHeight}
isFocused={isFocused}
scrollElRef={scrollElRef as ListRef}
ignoreFilterFor={profile.did}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showMediaTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileFeedSection
ref={mediaSectionRef}
feed={`author|${profile.did}|posts_with_media`}
headerHeight={headerHeight}
isFocused={isFocused}
scrollElRef={scrollElRef as ListRef}
ignoreFilterFor={profile.did}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showLikesTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileFeedSection
ref={likesSectionRef}
feed={`likes|${profile.did}`}
headerHeight={headerHeight}
isFocused={isFocused}
scrollElRef={scrollElRef as ListRef}
ignoreFilterFor={profile.did}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showFeedsTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileFeedgens
ref={feedsSectionRef}
did={profile.did}
scrollElRef={scrollElRef as ListRef}
headerOffset={headerHeight}
enabled={isFocused}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showStarterPacksTab
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileStarterPacks
ref={starterPacksSectionRef}
isMe={isMe}
starterPacksQuery={starterPacksQuery}
scrollElRef={scrollElRef as ListRef}
headerOffset={headerHeight}
enabled={isFocused}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
{showListsTab && !profile.associated?.labeler
? ({headerHeight, isFocused, scrollElRef}) => (
<ProfileLists
ref={listsSectionRef}
did={profile.did}
scrollElRef={scrollElRef as ListRef}
headerOffset={headerHeight}
enabled={isFocused}
setScrollViewTag={setScrollViewTag}
/>
)
: null}
</PagerWithHeader>
{hasSession && (
<FAB
testID="composeFAB"
onPress={onPressCompose}
icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
accessibilityRole="button"
accessibilityLabel={_(msg`New post`)}
accessibilityHint=""
/>
)}
</Alf>
</ScreenHider>
)
}
@@ -516,10 +538,10 @@ function useRichText(text: string): [RichTextAPI, boolean] {
let ignore = false
async function resolveRTFacets() {
// new each time
const resolvedRT = new RichTextAPI({text})
await resolvedRT.detectFacets(agent)
const newRT = new RichTextAPI({text})
await newRT.detectFacets(agent)
if (!ignore) {
setResolvedRT(resolvedRT)
setResolvedRT(newRT)
}
}
resolveRTFacets()
+3 -3
View File
@@ -104,13 +104,13 @@ function StorybookInner() {
<Settings />
<ThemeProvider theme="light">
<ThemeProvider themeName="light">
<Theming />
</ThemeProvider>
<ThemeProvider theme="dim">
<ThemeProvider themeName="dim">
<Theming />
</ThemeProvider>
<ThemeProvider theme="dark">
<ThemeProvider themeName="dark">
<Theming />
</ThemeProvider>
+51 -1
View File
@@ -7204,6 +7204,11 @@
resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz#60be8d21baab8c305132eb9cb912ed497852aadc"
integrity sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==
"@types/wcag-contrast@^3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/wcag-contrast/-/wcag-contrast-3.0.3.tgz#0b0339ab210b859eeee555b3fef58d293216905c"
integrity sha512-oprevfwJSLfpQK4KaWsRKJuNoebV76+xhmbXiWJGy+FkS34LpCgCMNIwRXWTb8xmmSxUE2ycFOYE7uyRVRm3LA==
"@types/ws@^8.5.5":
version "8.5.5"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb"
@@ -8871,7 +8876,7 @@ color-name@1.1.3:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@^1.0.0, color-name@~1.1.4:
color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
@@ -10314,6 +10319,11 @@ eslint@^8.19.0:
strip-ansi "^6.0.1"
text-table "^0.2.0"
esm@^3.0.84:
version "3.2.25"
resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10"
integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==
espree@^9.6.0, espree@^9.6.1:
version "9.6.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
@@ -11707,6 +11717,11 @@ hermes-profile-transformer@^0.0.6:
dependencies:
source-map "^0.7.3"
hex-rgb@^4.1.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/hex-rgb/-/hex-rgb-4.3.0.tgz#af5e974e83bb2fefe44d55182b004ec818c07776"
integrity sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==
history@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b"
@@ -14296,6 +14311,14 @@ minizlib@^2.1.1:
minipass "^3.0.0"
yallist "^4.0.0"
mix-css-color@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/mix-css-color/-/mix-css-color-0.2.0.tgz#413a2346effcb36a815b1d09bcbac12bcf3aac63"
integrity sha512-mZugANySFPE21tjELbQddhC6HAZNzqp7gDxmW8fJFURSWtJ0nuXU26dyrb/1AR6ZYxdEAtW2bbWT9QnRtI6Jzg==
dependencies:
parse-css-color "^0.1.2"
pure-color "^1.3.0"
mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
@@ -14931,6 +14954,14 @@ parent-module@^1.0.0:
dependencies:
callsites "^3.0.0"
parse-css-color@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/parse-css-color/-/parse-css-color-0.1.2.tgz#9d178f2d2b5eb7245c0deb22ea35046b79ff3f83"
integrity sha512-z7v/tf0edGsnlm9VONQtH+u/YVrdUqZXrSBzqM13scef8Abl2VyZfYsZaJoyb/AyY4SIxtoJChSQ4MURHfY3Sg==
dependencies:
color-name "^1.1.4"
hex-rgb "^4.1.0"
parse-json@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
@@ -15934,6 +15965,11 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
pure-color@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e"
integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA==
pure-rand@^6.0.0:
version "6.0.2"
resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.2.tgz#a9c2ddcae9b68d736a8163036f088a2781c8b306"
@@ -16655,6 +16691,13 @@ relateurl@^0.2.7:
resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==
relative-luminance@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/relative-luminance/-/relative-luminance-2.0.1.tgz#2babddf3a5a59673227d6f02e0f68e13989e3d13"
integrity sha512-wFuITNthJilFPwkK7gNJcULxXBcfFZvZORsvdvxeOdO44wCeZnuQkf3nFFzOR/dpJNxYsdRZJLsepWbyKhnMww==
dependencies:
esm "^3.0.84"
remove-trailing-slash@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz#be2285a59f39c74d1bce4f825950061915e3780d"
@@ -18763,6 +18806,13 @@ wbuf@^1.1.0, wbuf@^1.7.3:
dependencies:
minimalistic-assert "^1.0.0"
wcag-contrast@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/wcag-contrast/-/wcag-contrast-3.0.0.tgz#51c2df43f15162993006454b3362844205889efb"
integrity sha512-RWbpg/S7FOXDCwqC2oFhN/vh8dHzj0OS6dpyOSDHyQFSmqmR+lAUStV/ziTT1GzDqL9wol+nZQB4vCi5yEak+w==
dependencies:
relative-luminance "^2.0.0"
wcwidth@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"