diff --git a/assets/icons/bubbleQuestion_stroke2_corner0_rounded.svg b/assets/icons/bubbleQuestion_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..0bfcc48a0e
--- /dev/null
+++ b/assets/icons/bubbleQuestion_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
diff --git a/assets/icons/filter_stroke2_corner0_rounded.svg b/assets/icons/filter_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..1fbcfc5711
--- /dev/null
+++ b/assets/icons/filter_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
diff --git a/assets/icons/speakerVolumeFull_stroke2_corner0_rounded.svg b/assets/icons/speakerVolumeFull_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..81357a12e3
--- /dev/null
+++ b/assets/icons/speakerVolumeFull_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
diff --git a/assets/icons/trash_stroke2_corner0_rounded.svg b/assets/icons/trash_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..d4b32f81fe
--- /dev/null
+++ b/assets/icons/trash_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
diff --git a/assets/icons/warning_stroke2_corner0_rounded.svg b/assets/icons/warning_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..d5b6f13d5f
--- /dev/null
+++ b/assets/icons/warning_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
diff --git a/bskyweb/templates/base.html b/bskyweb/templates/base.html
index 55447552ea..c7c5ec0f0b 100644
--- a/bskyweb/templates/base.html
+++ b/bskyweb/templates/base.html
@@ -43,6 +43,9 @@
height: calc(100% + env(safe-area-inset-top));
scrollbar-gutter: stable both-edges;
}
+ html, body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
+ }
/* Buttons and inputs have a font set by UA, so we'll have to reset that */
button, input, textarea {
diff --git a/index.web.js b/index.web.js
index 4dee831cda..9623734512 100644
--- a/index.web.js
+++ b/index.web.js
@@ -1,3 +1,5 @@
+import '#/platform/markBundleStartTime'
+
import '#/platform/polyfills'
import {registerRootComponent} from 'expo'
import {doPolyfill} from '#/lib/api/api-polyfill'
diff --git a/src/Navigation.tsx b/src/Navigation.tsx
index b30f8f9822..8a9f69b5de 100644
--- a/src/Navigation.tsx
+++ b/src/Navigation.tsx
@@ -78,6 +78,7 @@ import {createNativeStackNavigatorWithAuth} from './view/shell/createNativeStack
import {msg} from '@lingui/macro'
import {i18n, MessageDescriptor} from '@lingui/core'
import HashtagScreen from '#/screens/Hashtag'
+import {logEvent} from './lib/statsig/statsig'
const navigationRef = createNavigationContainerRef()
@@ -649,11 +650,14 @@ function logModuleInitTime() {
return
}
didInit = true
+
const initMs = Math.round(
// @ts-ignore Emitted by Metro in the bundle prelude
performance.now() - global.__BUNDLE_START_TIME__,
)
console.log(`Time to first paint: ${initMs} ms`)
+ logEvent('init', initMs)
+
if (__DEV__) {
// This log is noisy, so keep false committed
const shouldLog = false
diff --git a/src/components/Button.tsx b/src/components/Button.tsx
index 5361be963a..d3bf73cc3e 100644
--- a/src/components/Button.tsx
+++ b/src/components/Button.tsx
@@ -27,7 +27,7 @@ export type ButtonColor =
| 'gradient_sunset'
| 'gradient_nordic'
| 'gradient_bonfire'
-export type ButtonSize = 'tiny' | 'small' | 'large'
+export type ButtonSize = 'tiny' | 'small' | 'medium' | 'large'
export type ButtonShape = 'round' | 'square' | 'default'
export type VariantProps = {
/**
@@ -274,6 +274,8 @@ export function Button({
if (shape === 'default') {
if (size === 'large') {
baseStyles.push({paddingVertical: 15}, a.px_2xl, a.rounded_sm, a.gap_md)
+ } else if (size === 'medium') {
+ baseStyles.push({paddingVertical: 12}, a.px_2xl, a.rounded_sm, a.gap_md)
} else if (size === 'small') {
baseStyles.push({paddingVertical: 9}, a.px_lg, a.rounded_sm, a.gap_sm)
} else if (size === 'tiny') {
diff --git a/src/components/Dialog/context.ts b/src/components/Dialog/context.ts
index 9b571e8e9c..859f8edd77 100644
--- a/src/components/Dialog/context.ts
+++ b/src/components/Dialog/context.ts
@@ -21,8 +21,7 @@ export function useDialogControl(): DialogOuterProps['control'] {
open: () => {},
close: () => {},
})
- const {activeDialogs, openDialogs} = useDialogStateContext()
- const isOpen = openDialogs.includes(id)
+ const {activeDialogs} = useDialogStateContext()
React.useEffect(() => {
activeDialogs.current.set(id, control)
@@ -36,7 +35,6 @@ export function useDialogControl(): DialogOuterProps['control'] {
() => ({
id,
ref: control,
- isOpen,
open: () => {
control.current.open()
},
@@ -44,6 +42,6 @@ export function useDialogControl(): DialogOuterProps['control'] {
control.current.close(cb)
},
}),
- [id, control, isOpen],
+ [id, control],
)
}
diff --git a/src/components/Dialog/types.ts b/src/components/Dialog/types.ts
index fa9398fe05..4fc60ec394 100644
--- a/src/components/Dialog/types.ts
+++ b/src/components/Dialog/types.ts
@@ -22,7 +22,7 @@ export type DialogControlRefProps = {
export type DialogControlProps = DialogControlRefProps & {
id: string
ref: React.RefObject
- isOpen: boolean
+ isOpen?: boolean
}
export type DialogContextProps = {
diff --git a/src/components/Menu/index.web.tsx b/src/components/Menu/index.web.tsx
index ca2e40566d..054e51b01e 100644
--- a/src/components/Menu/index.web.tsx
+++ b/src/components/Menu/index.web.tsx
@@ -92,10 +92,8 @@ export function Trigger({children, label, style}: TriggerProps) {
accessibilityLabel={label}
onFocus={onFocus}
onBlur={onBlur}
- style={flatten([style, web({outline: 0})])}
- onPointerDown={() => {
- control.open()
- }}
+ style={flatten([style, focused && web({outline: 0})])}
+ onPointerDown={() => control.open()}
{...web({
onMouseEnter,
onMouseLeave,
@@ -131,6 +129,7 @@ export function Outer({children}: React.PropsWithChildren<{}>) {
{children}
+ {/* Disabled until we can fix positioning
) {
.backgroundColor
}
/>
+ */}
)
diff --git a/src/components/Prompt.tsx b/src/components/Prompt.tsx
index 8e55bd8347..3b245c440f 100644
--- a/src/components/Prompt.tsx
+++ b/src/components/Prompt.tsx
@@ -3,7 +3,7 @@ import {View, PressableProps} from 'react-native'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
-import {useTheme, atoms as a} from '#/alf'
+import {useTheme, atoms as a, useBreakpoints} from '#/alf'
import {Text} from '#/components/Typography'
import {Button} from '#/components/Button'
@@ -25,6 +25,7 @@ export function Outer({
}: React.PropsWithChildren<{
control: Dialog.DialogOuterProps['control']
}>) {
+ const {gtMobile} = useBreakpoints()
const titleId = React.useId()
const descriptionId = React.useId()
@@ -38,12 +39,12 @@ export function Outer({
-
+ style={[gtMobile ? {width: 'auto', maxWidth: 400} : a.w_full]}>
{children}
-
+
)
@@ -71,8 +72,16 @@ export function Description({children}: React.PropsWithChildren<{}>) {
}
export function Actions({children}: React.PropsWithChildren<{}>) {
+ const {gtMobile} = useBreakpoints()
+
return (
-
+
{children}
)
@@ -82,12 +91,13 @@ export function Cancel({
children,
}: React.PropsWithChildren<{onPress?: PressableProps['onPress']}>) {
const {_} = useLingui()
+ const {gtMobile} = useBreakpoints()
const {close} = Dialog.useDialogContext()
return (
)}
- {!uiState.inviteCode && uiState.isInviteCodeRequired ? (
-
-
- Don't have an invite code?{' '}
-
-
-
-
- Join the waitlist.
-
-
-
-
- ) : (
+ {!uiState.isInviteCodeRequired || uiState.inviteCode ? (
<>
)}
>
- )}
+ ) : undefined}
>
)}
diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx
index 8da91c75cf..100444ff58 100644
--- a/src/view/com/modals/Modal.tsx
+++ b/src/view/com/modals/Modal.tsx
@@ -20,7 +20,6 @@ import * as ReportModal from './report/Modal'
import * as AppealLabelModal from './AppealLabel'
import * as DeleteAccountModal from './DeleteAccount'
import * as ChangeHandleModal from './ChangeHandle'
-import * as WaitlistModal from './Waitlist'
import * as InviteCodesModal from './InviteCodes'
import * as AddAppPassword from './AddAppPasswords'
import * as ContentFilteringSettingsModal from './ContentFilteringSettings'
@@ -109,9 +108,6 @@ export function ModalsContainer() {
} else if (activeModal?.name === 'change-handle') {
snapPoints = ChangeHandleModal.snapPoints
element =
- } else if (activeModal?.name === 'waitlist') {
- snapPoints = WaitlistModal.snapPoints
- element =
} else if (activeModal?.name === 'invite-codes') {
snapPoints = InviteCodesModal.snapPoints
element =
diff --git a/src/view/com/modals/Modal.web.tsx b/src/view/com/modals/Modal.web.tsx
index 97a60be913..0ced894a17 100644
--- a/src/view/com/modals/Modal.web.tsx
+++ b/src/view/com/modals/Modal.web.tsx
@@ -22,7 +22,6 @@ import * as CropImageModal from './crop-image/CropImage.web'
import * as AltTextImageModal from './AltImage'
import * as EditImageModal from './EditImage'
import * as ChangeHandleModal from './ChangeHandle'
-import * as WaitlistModal from './Waitlist'
import * as InviteCodesModal from './InviteCodes'
import * as AddAppPassword from './AddAppPasswords'
import * as ContentFilteringSettingsModal from './ContentFilteringSettings'
@@ -105,8 +104,6 @@ function Modal({modal}: {modal: ModalIface}) {
element =
} else if (modal.name === 'change-handle') {
element =
- } else if (modal.name === 'waitlist') {
- element =
} else if (modal.name === 'invite-codes') {
element =
} else if (modal.name === 'add-app-password') {
diff --git a/src/view/com/modals/Waitlist.tsx b/src/view/com/modals/Waitlist.tsx
deleted file mode 100644
index 263dd27a2f..0000000000
--- a/src/view/com/modals/Waitlist.tsx
+++ /dev/null
@@ -1,190 +0,0 @@
-import React from 'react'
-import {
- ActivityIndicator,
- StyleSheet,
- TouchableOpacity,
- View,
-} from 'react-native'
-import {TextInput} from './util'
-import {
- FontAwesomeIcon,
- FontAwesomeIconStyle,
-} from '@fortawesome/react-native-fontawesome'
-import LinearGradient from 'react-native-linear-gradient'
-import {Text} from '../util/text/Text'
-import {s, gradients} from 'lib/styles'
-import {usePalette} from 'lib/hooks/usePalette'
-import {useTheme} from 'lib/ThemeContext'
-import {ErrorMessage} from '../util/error/ErrorMessage'
-import {cleanError} from 'lib/strings/errors'
-import {Trans, msg} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-import {useModalControls} from '#/state/modals'
-
-export const snapPoints = ['80%']
-
-export function Component({}: {}) {
- const pal = usePalette('default')
- const theme = useTheme()
- const {_} = useLingui()
- const {closeModal} = useModalControls()
- const [email, setEmail] = React.useState('')
- const [isEmailSent, setIsEmailSent] = React.useState(false)
- const [isProcessing, setIsProcessing] = React.useState(false)
- const [error, setError] = React.useState('')
-
- const onPressSignup = async () => {
- setError('')
- setIsProcessing(true)
- try {
- const res = await fetch('https://bsky.app/api/waitlist', {
- method: 'POST',
- headers: {'Content-Type': 'application/json'},
- body: JSON.stringify({email}),
- })
- const resBody = await res.json()
- if (resBody.success) {
- setIsEmailSent(true)
- } else {
- setError(
- resBody.error ||
- _(msg`Something went wrong. Check your email and try again.`),
- )
- }
- } catch (e: any) {
- setError(cleanError(e))
- }
- setIsProcessing(false)
- }
- const onCancel = () => {
- closeModal()
- }
-
- return (
-
-
-
- Join the waitlist
-
-
-
- Bluesky uses invites to build a healthier community. If you don't
- know anybody with an invite, you can sign up for the waitlist and
- we'll send one soon.
-
-
-
- {error ? (
-
-
-
- ) : undefined}
- {isProcessing ? (
-
-
-
- ) : isEmailSent ? (
-
-
-
-
- Your email has been saved! We'll be in touch soon.
-
-
-
- ) : (
- <>
-
-
-
- Join Waitlist
-
-
-
-
-
- Cancel
-
-
- >
- )}
-
-
- )
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- innerContainer: {
- paddingBottom: 20,
- },
- title: {
- textAlign: 'center',
- marginTop: 12,
- marginBottom: 12,
- },
- description: {
- textAlign: 'center',
- paddingHorizontal: 22,
- marginBottom: 10,
- },
- textInput: {
- borderWidth: 1,
- borderRadius: 6,
- paddingHorizontal: 16,
- paddingVertical: 12,
- fontSize: 20,
- marginHorizontal: 20,
- },
- btn: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'center',
- borderRadius: 32,
- padding: 14,
- marginHorizontal: 20,
- },
- error: {
- borderRadius: 6,
- marginHorizontal: 20,
- marginBottom: 20,
- },
-})
diff --git a/src/view/com/util/EventStopper.tsx b/src/view/com/util/EventStopper.tsx
index e743e89bbe..8f5f5cf54d 100644
--- a/src/view/com/util/EventStopper.tsx
+++ b/src/view/com/util/EventStopper.tsx
@@ -8,7 +8,14 @@ import {View, ViewStyle} from 'react-native'
export function EventStopper({
children,
style,
-}: React.PropsWithChildren<{style?: ViewStyle | ViewStyle[]}>) {
+ onKeyDown = true,
+}: React.PropsWithChildren<{
+ style?: ViewStyle | ViewStyle[]
+ /**
+ * Default `true`. Set to `false` to allow onKeyDown to propagate
+ */
+ onKeyDown?: boolean
+}>) {
const stop = (e: any) => {
e.stopPropagation()
}
@@ -18,7 +25,7 @@ export function EventStopper({
onTouchEnd={stop}
// @ts-ignore web only -prf
onClick={stop}
- onKeyDown={stop}
+ onKeyDown={onKeyDown ? stop : undefined}
style={style}>
{children}
diff --git a/src/view/com/util/forms/PostDropdownBtn.tsx b/src/view/com/util/forms/PostDropdownBtn.tsx
index 09850a7f54..6f2ae55b2c 100644
--- a/src/view/com/util/forms/PostDropdownBtn.tsx
+++ b/src/view/com/util/forms/PostDropdownBtn.tsx
@@ -1,5 +1,11 @@
import React, {memo} from 'react'
-import {StyleProp, View, ViewStyle} from 'react-native'
+import {
+ StyleProp,
+ ViewStyle,
+ Pressable,
+ View,
+ PressableProps,
+} from 'react-native'
import Clipboard from '@react-native-clipboard/clipboard'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {useNavigation} from '@react-navigation/native'
@@ -12,10 +18,6 @@ import {
import {toShareUrl} from 'lib/strings/url-helpers'
import {useTheme} from 'lib/ThemeContext'
import {shareUrl} from 'lib/sharing'
-import {
- NativeDropdown,
- DropdownItem as NativeDropdownItem,
-} from './NativeDropdown'
import * as Toast from '../Toast'
import {EventStopper} from '../EventStopper'
import {useModalControls} from '#/state/modals'
@@ -36,6 +38,19 @@ import {isWeb} from '#/platform/detection'
import {richTextToString} from '#/lib/strings/rich-text-helpers'
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
+import {atoms as a, useTheme as useAlf, web} from '#/alf'
+import * as Menu from '#/components/Menu'
+import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard'
+import {Filter_Stroke2_Corner0_Rounded as Filter} from '#/components/icons/Filter'
+import {ArrowOutOfBox_Stroke2_Corner0_Rounded as Share} from '#/components/icons/ArrowOutOfBox'
+import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash'
+import {Mute_Stroke2_Corner0_Rounded as Mute} from '#/components/icons/Mute'
+import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as Unmute} from '#/components/icons/Speaker'
+import {BubbleQuestion_Stroke2_Corner0_Rounded as Translate} from '#/components/icons/Bubble'
+import {Warning_Stroke2_Corner0_Rounded as Warning} from '#/components/icons/Warning'
+import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
+import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
+
let PostDropdownBtn = ({
testID,
postAuthor,
@@ -45,6 +60,7 @@ let PostDropdownBtn = ({
richText,
style,
showAppealLabelItem,
+ hitSlop,
}: {
testID: string
postAuthor: AppBskyActorDefs.ProfileViewBasic
@@ -54,9 +70,11 @@ let PostDropdownBtn = ({
richText: RichTextAPI
style?: StyleProp
showAppealLabelItem?: boolean
+ hitSlop?: PressableProps['hitSlop']
}): React.ReactNode => {
const {hasSession, currentAccount} = useSession()
const theme = useTheme()
+ const alf = useAlf()
const {_} = useLingui()
const defaultCtrlColor = theme.palette.default.postCtrl
const {openModal} = useModalControls()
@@ -151,173 +169,189 @@ let PostDropdownBtn = ({
hidePost({uri: postUri})
}, [postUri, hidePost])
- const dropdownItems: NativeDropdownItem[] = [
- {
- label: _(msg`Translate`),
- onPress() {
- onOpenTranslate()
- },
- testID: 'postDropdownTranslateBtn',
- icon: {
- ios: {
- name: 'character.book.closed',
- },
- android: 'ic_menu_sort_alphabetically',
- web: 'language',
- },
- },
- {
- label: _(msg`Copy post text`),
- onPress() {
- onCopyPostText()
- },
- testID: 'postDropdownCopyTextBtn',
- icon: {
- ios: {
- name: 'doc.on.doc',
- },
- android: 'ic_menu_edit',
- web: ['far', 'paste'],
- },
- },
- {
- label: isWeb ? _(msg`Copy link to post`) : _(msg`Share`),
- onPress() {
- const url = toShareUrl(href)
- shareUrl(url)
- },
- testID: 'postDropdownShareBtn',
- icon: {
- ios: {
- name: 'square.and.arrow.up',
- },
- android: 'ic_menu_share',
- web: 'share',
- },
- },
- hasSession && {
- label: 'separator',
- },
- hasSession && {
- label: isThreadMuted ? _(msg`Unmute thread`) : _(msg`Mute thread`),
- onPress() {
- onToggleThreadMute()
- },
- testID: 'postDropdownMuteThreadBtn',
- icon: {
- ios: {
- name: 'speaker.slash',
- },
- android: 'ic_lock_silent_mode',
- web: 'comment-slash',
- },
- },
- hasSession && {
- label: _(msg`Mute words & tags`),
- onPress() {
- mutedWordsDialogControl.open()
- },
- testID: 'postDropdownMuteWordsBtn',
- icon: {
- ios: {
- name: 'speaker.slash',
- },
- android: 'ic_lock_silent_mode',
- web: 'filter',
- },
- },
- hasSession &&
- !isAuthor &&
- !isPostHidden && {
- label: _(msg`Hide post`),
- onPress() {
- openModal({
- name: 'confirm',
- title: _(msg`Hide this post?`),
- message: _(msg`This will hide this post from your feeds.`),
- onPressConfirm: onHidePost,
- })
- },
- testID: 'postDropdownHideBtn',
- icon: {
- ios: {
- name: 'eye.slash',
- },
- android: 'ic_menu_delete',
- web: ['far', 'eye-slash'],
- },
- },
- {
- label: 'separator',
- },
- !isAuthor &&
- hasSession && {
- label: _(msg`Report post`),
- onPress() {
- openModal({
- name: 'report',
- uri: postUri,
- cid: postCid,
- })
- },
- testID: 'postDropdownReportBtn',
- icon: {
- ios: {
- name: 'exclamationmark.triangle',
- },
- android: 'ic_menu_report_image',
- web: 'circle-exclamation',
- },
- },
- isAuthor && {
- label: _(msg`Delete post`),
- onPress() {
- openModal({
- name: 'confirm',
- title: _(msg`Delete this post?`),
- message: _(msg`Are you sure? This cannot be undone.`),
- onPressConfirm: onDeletePost,
- })
- },
- testID: 'postDropdownDeleteBtn',
- icon: {
- ios: {
- name: 'trash',
- },
- android: 'ic_menu_delete',
- web: ['far', 'trash-can'],
- },
- },
- showAppealLabelItem && {
- label: 'separator',
- },
- showAppealLabelItem && {
- label: _(msg`Appeal content warning`),
- onPress() {
- openModal({name: 'appeal-label', uri: postUri, cid: postCid})
- },
- testID: 'postDropdownAppealBtn',
- icon: {
- ios: {
- name: 'exclamationmark.triangle',
- },
- android: 'ic_menu_report_image',
- web: 'circle-exclamation',
- },
- },
- ].filter(Boolean) as NativeDropdownItem[]
-
return (
-
-
-
-
-
-
+
+
+
+ {({props, state}) => {
+ const styles = [
+ style,
+ a.rounded_full,
+ (state.hovered || state.focused || state.pressed) && [
+ web({outline: 0}),
+ alf.atoms.bg_contrast_25,
+ ],
+ ]
+ return isWeb ? (
+
+
+
+ ) : (
+
+
+
+ )
+ }}
+
+
+
+
+
+ {_(msg`Translate`)}
+
+
+
+
+ {_(msg`Copy post text`)}
+
+
+
+ {
+ const url = toShareUrl(href)
+ shareUrl(url)
+ }}>
+
+ {isWeb ? _(msg`Copy link to post`) : _(msg`Share`)}
+
+
+
+
+
+ {hasSession && (
+ <>
+
+
+
+
+
+ {isThreadMuted
+ ? _(msg`Unmute thread`)
+ : _(msg`Mute thread`)}
+
+
+
+
+ mutedWordsDialogControl.open()}>
+ {_(msg`Mute words & tags`)}
+
+
+
+ {!isAuthor && !isPostHidden && (
+ {
+ openModal({
+ name: 'confirm',
+ title: _(msg`Hide this post?`),
+ message: _(
+ msg`This will hide this post from your feeds.`,
+ ),
+ onPressConfirm: onHidePost,
+ })
+ }}>
+ {_(msg`Hide post`)}
+
+
+ )}
+
+ >
+ )}
+
+
+
+
+ {!isAuthor && (
+ {
+ openModal({
+ name: 'report',
+ uri: postUri,
+ cid: postCid,
+ })
+ }}>
+ {_(msg`Report post`)}
+
+
+ )}
+
+ {isAuthor && (
+ {
+ openModal({
+ name: 'confirm',
+ title: _(msg`Delete this post?`),
+ message: _(msg`Are you sure? This cannot be undone.`),
+ onPressConfirm: onDeletePost,
+ })
+ }}>
+ {_(msg`Delete post`)}
+
+
+ )}
+
+ {showAppealLabelItem && (
+ <>
+
+
+ {
+ openModal({
+ name: 'appeal-label',
+ uri: postUri,
+ cid: postCid,
+ })
+ }}>
+
+ {_(msg`Appeal content warning`)}
+
+
+
+ >
+ )}
+
+
+
)
}
diff --git a/src/view/com/util/post-ctrls/PostCtrls.tsx b/src/view/com/util/post-ctrls/PostCtrls.tsx
index bd21ddda2f..1e26eeccee 100644
--- a/src/view/com/util/post-ctrls/PostCtrls.tsx
+++ b/src/view/com/util/post-ctrls/PostCtrls.tsx
@@ -212,9 +212,7 @@ let PostCtrls = ({
style={[styles.btn]}
onPress={onShare}
accessibilityRole="button"
- accessibilityLabel={`${
- post.viewer?.like ? _(msg`Unlike`) : _(msg`Like`)
- } (${post.likeCount} ${pluralize(post.likeCount || 0, 'like')})`}
+ accessibilityLabel={`${_(msg`Share`)}`}
accessibilityHint=""
hitSlop={big ? HITSLOP_20 : HITSLOP_10}>
@@ -231,6 +229,7 @@ let PostCtrls = ({
richText={richText}
showAppealLabelItem={showAppealLabelItem}
style={styles.btnPad}
+ hitSlop={big ? HITSLOP_20 : HITSLOP_10}
/>
diff --git a/src/view/shell/index.tsx b/src/view/shell/index.tsx
index bdba791741..76a7f8fb3a 100644
--- a/src/view/shell/index.tsx
+++ b/src/view/shell/index.tsx
@@ -30,7 +30,8 @@ import {useCloseAnyActiveElement} from '#/state/util'
import * as notifications from 'lib/notifications/notifications'
import {Outlet as PortalOutlet} from '#/components/Portal'
import {MutedWordsDialog} from '#/components/dialogs/MutedWords'
-import {useDialogStateContext} from '#/state/dialogs'
+import {useDialogStateContext} from 'state/dialogs'
+import Animated from 'react-native-reanimated'
function ShellInner() {
const isDrawerOpen = useIsDrawerOpen()
@@ -54,9 +55,9 @@ function ShellInner() {
const canGoBack = useNavigationState(state => !isStateAtTabRoot(state))
const {hasSession, currentAccount} = useSession()
const closeAnyActiveElement = useCloseAnyActiveElement()
+ const {importantForAccessibility} = useDialogStateContext()
// start undefined
const currentAccountDid = React.useRef(undefined)
- const {openDialogs} = useDialogStateContext()
React.useEffect(() => {
let listener = {remove() {}}
@@ -80,19 +81,9 @@ function ShellInner() {
}
}, [currentAccount])
- /**
- * The counterpart to `accessibilityViewIsModal` for Android. This property
- * applies to the parent of all non-modal views, and prevents TalkBack from
- * navigating within content beneath an open dialog.
- *
- * @see https://reactnative.dev/docs/accessibility#importantforaccessibility-android
- */
- const importantForAccessibility =
- openDialogs.length > 0 ? 'no-hide-descendants' : undefined
-
return (
<>
-
@@ -106,7 +97,7 @@ function ShellInner() {
-
+
diff --git a/web/index.html b/web/index.html
index b6e01ba4c2..de0abfc91b 100644
--- a/web/index.html
+++ b/web/index.html
@@ -47,6 +47,9 @@
height: calc(100% + env(safe-area-inset-top));
scrollbar-gutter: stable both-edges;
}
+ html, body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
+ }
/* Buttons and inputs have a font set by UA, so we'll have to reset that */
button, input, textarea {