From 29aaf09a8b8b199b249cef9123673022fde11c4f Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Mon, 24 Jun 2024 23:15:11 +0100 Subject: [PATCH 01/10] Composer - replace threadgate modal with alf dialog (#4329) * replace threadgate modal with alf dialog * add accessibility to selectable * add aria * hide spinner once fetched * add `hasOpenDialogs` value to context * remove state * Rm loading state * Update the threadgate dialog button theming * Factor out the threadgate editor and add editing to post views * Mark messages for localization * Use colors from mute dialog * Remove unnecessary effect * Reset state on dialog dismiss * Clearer CTA * Fix bugs * Scope keyboard fix * Rm getAreDialogsActive (no longer needed) --------- Co-authored-by: Dan Abramov Co-authored-by: Paul Frazee --- src/components/Dialog/index.web.tsx | 5 +- src/components/WhoCanReply.tsx | 150 ++++++------ src/components/dialogs/EmbedConsent.tsx | 1 + src/components/dialogs/ThreadgateEditor.tsx | 218 ++++++++++++++++++ src/state/modals/index.tsx | 9 - .../com/composer/threadgate/ThreadgateBtn.tsx | 50 ++-- src/view/com/modals/Modal.tsx | 4 - src/view/com/modals/Modal.web.tsx | 3 - src/view/com/modals/Threadgate.tsx | 208 ----------------- 9 files changed, 334 insertions(+), 314 deletions(-) create mode 100644 src/components/dialogs/ThreadgateEditor.tsx delete mode 100644 src/view/com/modals/Threadgate.tsx diff --git a/src/components/Dialog/index.web.tsx b/src/components/Dialog/index.web.tsx index 35d807b4be..aff1842f77 100644 --- a/src/components/Dialog/index.web.tsx +++ b/src/components/Dialog/index.web.tsx @@ -88,7 +88,10 @@ export function Outer({ if (!isOpen) return function handler(e: KeyboardEvent) { - if (e.key === 'Escape') close() + if (e.key === 'Escape') { + e.stopPropagation() + close() + } } document.addEventListener('keydown', handler) diff --git a/src/components/WhoCanReply.tsx b/src/components/WhoCanReply.tsx index cd171a0a46..a73aae850b 100644 --- a/src/components/WhoCanReply.tsx +++ b/src/components/WhoCanReply.tsx @@ -17,7 +17,6 @@ import {HITSLOP_10} from '#/lib/constants' import {makeListLink, makeProfileLink} from '#/lib/routes/links' import {logger} from '#/logger' import {isNative} from '#/platform/detection' -import {useModalControls} from '#/state/modals' import {RQKEY_ROOT as POST_THREAD_RQKEY_ROOT} from '#/state/queries/post-thread' import { ThreadgateSetting, @@ -34,6 +33,7 @@ import {Earth_Stroke2_Corner0_Rounded as Earth} from '#/components/icons/Globe' import {Group3_Stroke2_Corner0_Rounded as Group} from '#/components/icons/Group' import {Text} from '#/components/Typography' import {TextLink} from '../view/com/util/Link' +import {ThreadgateEditorDialog} from './dialogs/ThreadgateEditor' import {PencilLine_Stroke2_Corner0_Rounded as PencilLine} from './icons/Pencil' interface WhoCanReplyProps { @@ -46,7 +46,15 @@ export function WhoCanReply({post, isThreadAuthor, style}: WhoCanReplyProps) { const {_} = useLingui() const t = useTheme() const infoDialogControl = useDialogControl() - const {settings, isRootPost, onPressEdit} = useWhoCanReply(post) + const editDialogControl = useDialogControl() + const agent = useAgent() + const queryClient = useQueryClient() + + const settings = React.useMemo( + () => threadgateViewToSettings(post.threadgate), + [post], + ) + const isRootPost = !('reply' in post.record) if (!isRootPost) { return null @@ -63,6 +71,55 @@ export function WhoCanReply({post, isThreadAuthor, style}: WhoCanReplyProps) { ? _(msg`Replies disabled`) : _(msg`Some people can reply`) + const onPressEdit = () => { + if (isNative && Keyboard.isVisible()) { + Keyboard.dismiss() + } + if (isThreadAuthor) { + editDialogControl.open() + } else { + infoDialogControl.open() + } + } + + const onEditConfirm = async (newSettings: ThreadgateSetting[]) => { + if (JSON.stringify(settings) === JSON.stringify(newSettings)) { + return + } + try { + if (newSettings.length) { + await createThreadgate(agent, post.uri, newSettings) + } else { + await agent.api.com.atproto.repo.deleteRecord({ + repo: agent.session!.did, + collection: 'app.bsky.feed.threadgate', + rkey: new AtUri(post.uri).rkey, + }) + } + await whenAppViewReady(agent, post.uri, res => { + const thread = res.data.thread + if (AppBskyFeedDefs.isThreadViewPost(thread)) { + const fetchedSettings = threadgateViewToSettings( + thread.post.threadgate, + ) + return JSON.stringify(fetchedSettings) === JSON.stringify(newSettings) + } + return false + }) + Toast.show(_(msg`Thread settings updated`)) + queryClient.invalidateQueries({ + queryKey: [POST_THREAD_RQKEY_ROOT], + }) + } catch (err) { + Toast.show( + _( + msg`There was an issue. Please check your internet connection and try again.`, + ), + ) + logger.error('Failed to edit threadgate', {message: err}) + } + } + return ( <> - + + {isThreadAuthor && ( + + )} ) } @@ -113,24 +181,31 @@ function Icon({ return } -export function WhoCanReplyDialog({ +function WhoCanReplyDialog({ control, post, + settings, }: { control: Dialog.DialogControlProps post: AppBskyFeedDefs.PostView + settings: ThreadgateSetting[] }) { return ( - + ) } -function WhoCanReplyDialogInner({post}: {post: AppBskyFeedDefs.PostView}) { +function WhoCanReplyDialogInner({ + post, + settings, +}: { + post: AppBskyFeedDefs.PostView + settings: ThreadgateSetting[] +}) { const {_} = useLingui() - const {settings} = useWhoCanReply(post) return ( , } -function useWhoCanReply(post: AppBskyFeedDefs.PostView) { - const agent = useAgent() - const queryClient = useQueryClient() - const {openModal} = useModalControls() - - const settings = React.useMemo( - () => threadgateViewToSettings(post.threadgate), - [post], - ) - const isRootPost = !('reply' in post.record) - - const onPressEdit = () => { - if (isNative && Keyboard.isVisible()) { - Keyboard.dismiss() - } - openModal({ - name: 'threadgate', - settings, - async onConfirm(newSettings: ThreadgateSetting[]) { - if (JSON.stringify(settings) === JSON.stringify(newSettings)) { - return - } - try { - if (newSettings.length) { - await createThreadgate(agent, post.uri, newSettings) - } else { - await agent.api.com.atproto.repo.deleteRecord({ - repo: agent.session!.did, - collection: 'app.bsky.feed.threadgate', - rkey: new AtUri(post.uri).rkey, - }) - } - await whenAppViewReady(agent, post.uri, res => { - const thread = res.data.thread - if (AppBskyFeedDefs.isThreadViewPost(thread)) { - const fetchedSettings = threadgateViewToSettings( - thread.post.threadgate, - ) - return ( - JSON.stringify(fetchedSettings) === JSON.stringify(newSettings) - ) - } - return false - }) - Toast.show('Thread settings updated') - queryClient.invalidateQueries({ - queryKey: [POST_THREAD_RQKEY_ROOT], - }) - } catch (err) { - Toast.show( - 'There was an issue. Please check your internet connection and try again.', - ) - logger.error('Failed to edit threadgate', {message: err}) - } - }, - }) - } - - return {settings, isRootPost, onPressEdit} -} - async function whenAppViewReady( agent: BskyAgent, uri: string, diff --git a/src/components/dialogs/EmbedConsent.tsx b/src/components/dialogs/EmbedConsent.tsx index c3fefd9f09..f7e6145975 100644 --- a/src/components/dialogs/EmbedConsent.tsx +++ b/src/components/dialogs/EmbedConsent.tsx @@ -113,6 +113,7 @@ export function EmbedConsentDialog({ + ) diff --git a/src/components/dialogs/ThreadgateEditor.tsx b/src/components/dialogs/ThreadgateEditor.tsx new file mode 100644 index 0000000000..75383764fc --- /dev/null +++ b/src/components/dialogs/ThreadgateEditor.tsx @@ -0,0 +1,218 @@ +import React from 'react' +import {StyleProp, View, ViewStyle} from 'react-native' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import isEqual from 'lodash.isequal' + +import {useMyListsQuery} from '#/state/queries/my-lists' +import {ThreadgateSetting} from '#/state/queries/threadgate' +import {atoms as a, useTheme} from '#/alf' +import {Button, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check' +import {Text} from '#/components/Typography' + +interface ThreadgateEditorDialogProps { + control: Dialog.DialogControlProps + threadgate: ThreadgateSetting[] + onChange?: (v: ThreadgateSetting[]) => void + onConfirm?: (v: ThreadgateSetting[]) => void +} + +export function ThreadgateEditorDialog({ + control, + threadgate, + onChange, + onConfirm, +}: ThreadgateEditorDialogProps) { + return ( + + + + + ) +} + +function DialogContent({ + seedThreadgate, + onChange, + onConfirm, +}: { + seedThreadgate: ThreadgateSetting[] + onChange?: (v: ThreadgateSetting[]) => void + onConfirm?: (v: ThreadgateSetting[]) => void +}) { + const {_} = useLingui() + const control = Dialog.useDialogContext() + const {data: lists} = useMyListsQuery('curate') + const [draft, setDraft] = React.useState(seedThreadgate) + + const [prevSeedThreadgate, setPrevSeedThreadgate] = + React.useState(seedThreadgate) + if (seedThreadgate !== prevSeedThreadgate) { + // New data flowed from above (e.g. due to update coming through). + setPrevSeedThreadgate(seedThreadgate) + setDraft(seedThreadgate) // Reset draft. + } + + function updateThreadgate(nextThreadgate: ThreadgateSetting[]) { + setDraft(nextThreadgate) + onChange?.(nextThreadgate) + } + + const onPressEverybody = () => { + updateThreadgate([]) + } + + const onPressNobody = () => { + updateThreadgate([{type: 'nobody'}]) + } + + const onPressAudience = (setting: ThreadgateSetting) => { + // remove nobody + let newSelected = draft.filter(v => v.type !== 'nobody') + // toggle + const i = newSelected.findIndex(v => isEqual(v, setting)) + if (i === -1) { + newSelected.push(setting) + } else { + newSelected.splice(i, 1) + } + updateThreadgate(newSelected) + } + + const doneLabel = onConfirm ? _(msg`Save`) : _(msg`Done`) + return ( + + + + Chose who can reply + + + Either choose "Everybody" or "Nobody" + + + + v.type === 'nobody')} + onPress={onPressNobody} + style={{flex: 1}} + /> + + + Or combine these options: + + + v.type === 'mention')} + onPress={() => onPressAudience({type: 'mention'})} + /> + v.type === 'following')} + onPress={() => onPressAudience({type: 'following'})} + /> + {lists && lists.length > 0 + ? lists.map(list => ( + v.type === 'list' && v.list === list.uri) + } + onPress={() => + onPressAudience({type: 'list', list: list.uri}) + } + /> + )) + : // No loading states to avoid jumps for the common case (no lists) + null} + + + + + + ) +} + +function Selectable({ + label, + isSelected, + onPress, + style, +}: { + label: string + isSelected: boolean + onPress: () => void + style?: StyleProp +}) { + const t = useTheme() + return ( + + ) +} diff --git a/src/state/modals/index.tsx b/src/state/modals/index.tsx index 685b10bd85..529dc55907 100644 --- a/src/state/modals/index.tsx +++ b/src/state/modals/index.tsx @@ -5,7 +5,6 @@ import {AppBskyActorDefs, AppBskyGraphDefs} from '@atproto/api' import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' import {GalleryModel} from '#/state/models/media/gallery' import {ImageModel} from '#/state/models/media/image' -import {ThreadgateSetting} from '../queries/threadgate' export interface EditProfileModal { name: 'edit-profile' @@ -67,13 +66,6 @@ export interface SelfLabelModal { onChange: (labels: string[]) => void } -export interface ThreadgateModal { - name: 'threadgate' - settings: ThreadgateSetting[] - onChange?: (settings: ThreadgateSetting[]) => void - onConfirm?: (settings: ThreadgateSetting[]) => void -} - export interface ChangeHandleModal { name: 'change-handle' onChanged: () => void @@ -149,7 +141,6 @@ export type Modal = | CropImageModal | EditImageModal | SelfLabelModal - | ThreadgateModal // Bluesky access | WaitlistModal diff --git a/src/view/com/composer/threadgate/ThreadgateBtn.tsx b/src/view/com/composer/threadgate/ThreadgateBtn.tsx index 2aefdfbbf3..6cf2eea2c4 100644 --- a/src/view/com/composer/threadgate/ThreadgateBtn.tsx +++ b/src/view/com/composer/threadgate/ThreadgateBtn.tsx @@ -5,11 +5,12 @@ import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {isNative} from '#/platform/detection' -import {useModalControls} from '#/state/modals' import {ThreadgateSetting} from '#/state/queries/threadgate' import {useAnalytics} from 'lib/analytics/analytics' import {atoms as a, useTheme} from '#/alf' import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {ThreadgateEditorDialog} from '#/components/dialogs/ThreadgateEditor' import {CircleBanSign_Stroke2_Corner0_Rounded as CircleBanSign} from '#/components/icons/CircleBanSign' import {Earth_Stroke2_Corner0_Rounded as Earth} from '#/components/icons/Globe' import {Group3_Stroke2_Corner0_Rounded as Group} from '#/components/icons/Group' @@ -26,18 +27,15 @@ export function ThreadgateBtn({ const {track} = useAnalytics() const {_} = useLingui() const t = useTheme() - const {openModal} = useModalControls() + const control = Dialog.useDialogControl() const onPress = () => { track('Composer:ThreadgateOpened') if (isNative && Keyboard.isVisible()) { Keyboard.dismiss() } - openModal({ - name: 'threadgate', - settings: threadgate, - onChange, - }) + + control.open() } const isEverybody = threadgate.length === 0 @@ -49,19 +47,29 @@ export function ThreadgateBtn({ : _(msg`Some people can reply`) return ( - - - + <> + + + + + ) } diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx index ecfe5806ef..3455e1cdf8 100644 --- a/src/view/com/modals/Modal.tsx +++ b/src/view/com/modals/Modal.tsx @@ -23,7 +23,6 @@ import * as PostLanguagesSettingsModal from './lang-settings/PostLanguagesSettin import * as LinkWarningModal from './LinkWarning' import * as ListAddUserModal from './ListAddRemoveUsers' import * as SelfLabelModal from './SelfLabel' -import * as ThreadgateModal from './Threadgate' import * as UserAddRemoveListsModal from './UserAddRemoveLists' import * as VerifyEmailModal from './VerifyEmail' @@ -76,9 +75,6 @@ export function ModalsContainer() { } else if (activeModal?.name === 'self-label') { snapPoints = SelfLabelModal.snapPoints element = - } else if (activeModal?.name === 'threadgate') { - snapPoints = ThreadgateModal.snapPoints - element = } else if (activeModal?.name === 'alt-text-image') { snapPoints = AltImageModal.snapPoints element = diff --git a/src/view/com/modals/Modal.web.tsx b/src/view/com/modals/Modal.web.tsx index 14ee99e576..c4bab6fb18 100644 --- a/src/view/com/modals/Modal.web.tsx +++ b/src/view/com/modals/Modal.web.tsx @@ -23,7 +23,6 @@ import * as PostLanguagesSettingsModal from './lang-settings/PostLanguagesSettin import * as LinkWarningModal from './LinkWarning' import * as ListAddUserModal from './ListAddRemoveUsers' import * as SelfLabelModal from './SelfLabel' -import * as ThreadgateModal from './Threadgate' import * as UserAddRemoveLists from './UserAddRemoveLists' import * as VerifyEmailModal from './VerifyEmail' @@ -84,8 +83,6 @@ function Modal({modal}: {modal: ModalIface}) { element = } else if (modal.name === 'self-label') { element = - } else if (modal.name === 'threadgate') { - element = } else if (modal.name === 'change-handle') { element = } else if (modal.name === 'invite-codes') { diff --git a/src/view/com/modals/Threadgate.tsx b/src/view/com/modals/Threadgate.tsx deleted file mode 100644 index 4a9a9e2ab5..0000000000 --- a/src/view/com/modals/Threadgate.tsx +++ /dev/null @@ -1,208 +0,0 @@ -import React, {useState} from 'react' -import { - Pressable, - StyleProp, - StyleSheet, - TouchableOpacity, - View, - ViewStyle, -} from 'react-native' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' -import isEqual from 'lodash.isequal' - -import {useModalControls} from '#/state/modals' -import {useMyListsQuery} from '#/state/queries/my-lists' -import {ThreadgateSetting} from '#/state/queries/threadgate' -import {usePalette} from 'lib/hooks/usePalette' -import {colors, s} from 'lib/styles' -import {isWeb} from 'platform/detection' -import {ScrollView} from 'view/com/modals/util' -import {Text} from '../util/text/Text' - -export const snapPoints = ['60%'] - -export function Component({ - settings, - onChange, - onConfirm, -}: { - settings: ThreadgateSetting[] - onChange?: (settings: ThreadgateSetting[]) => void - onConfirm?: (settings: ThreadgateSetting[]) => void -}) { - const pal = usePalette('default') - const {closeModal} = useModalControls() - const [selected, setSelected] = useState(settings) - const {_} = useLingui() - const {data: lists} = useMyListsQuery('curate') - - const onPressEverybody = () => { - setSelected([]) - onChange?.([]) - } - - const onPressNobody = () => { - setSelected([{type: 'nobody'}]) - onChange?.([{type: 'nobody'}]) - } - - const onPressAudience = (setting: ThreadgateSetting) => { - // remove nobody - let newSelected = selected.filter(v => v.type !== 'nobody') - // toggle - const i = newSelected.findIndex(v => isEqual(v, setting)) - if (i === -1) { - newSelected.push(setting) - } else { - newSelected.splice(i, 1) - } - setSelected(newSelected) - onChange?.(newSelected) - } - - return ( - - - - Who can reply - - - - - - Choose "Everybody" or "Nobody" - - - - v.type === 'nobody')} - onPress={onPressNobody} - style={{flex: 1}} - /> - - - Or combine these options: - - - v.type === 'mention')} - onPress={() => onPressAudience({type: 'mention'})} - /> - v.type === 'following')} - onPress={() => onPressAudience({type: 'following'})} - /> - {lists?.length - ? lists.map(list => ( - v.type === 'list' && v.list === list.uri, - ) - } - onPress={() => - onPressAudience({type: 'list', list: list.uri}) - } - /> - )) - : null} - - - - - { - closeModal() - onConfirm?.(selected) - }} - style={styles.btn} - accessibilityRole="button" - accessibilityLabel={_(msg({message: `Done`, context: 'action'}))} - accessibilityHint=""> - - Done - - - - - ) -} - -function Selectable({ - label, - isSelected, - onPress, - style, -}: { - label: string - isSelected: boolean - onPress: () => void - style?: StyleProp -}) { - const pal = usePalette(isSelected ? 'inverted' : 'default') - return ( - - - {label} - - {isSelected ? ( - - ) : null} - - ) -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - paddingBottom: isWeb ? 0 : 40, - }, - titleSection: { - paddingTop: isWeb ? 0 : 4, - }, - title: { - textAlign: 'center', - fontWeight: '600', - }, - description: { - textAlign: 'center', - paddingVertical: 16, - }, - selectable: { - flexDirection: 'row', - justifyContent: 'space-between', - paddingHorizontal: 18, - paddingVertical: 16, - borderWidth: 1, - borderRadius: 6, - }, - btn: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - borderRadius: 32, - padding: 14, - backgroundColor: colors.blue3, - }, - btnContainer: { - paddingTop: 20, - paddingHorizontal: 20, - }, -}) From ffb67397e7106dce1e05fe86af0d8db12a1991f3 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Mon, 24 Jun 2024 17:34:12 -0500 Subject: [PATCH 02/10] Newskie dialog tweaks (#4623) --- src/components/NewskieDialog.tsx | 55 ++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/components/NewskieDialog.tsx b/src/components/NewskieDialog.tsx index 6743a592ba..d456bd6dab 100644 --- a/src/components/NewskieDialog.tsx +++ b/src/components/NewskieDialog.tsx @@ -6,10 +6,10 @@ import {useLingui} from '@lingui/react' import {differenceInSeconds} from 'date-fns' import {useGetTimeAgo} from '#/lib/hooks/useTimeAgo' +import {isNative} from '#/platform/detection' import {useModerationOpts} from '#/state/preferences/moderation-opts' import {HITSLOP_10} from 'lib/constants' import {sanitizeDisplayName} from 'lib/strings/display-names' -import {isWeb} from 'platform/detection' import {atoms as a, useTheme} from '#/alf' import {Button, ButtonText} from '#/components/Button' import * as Dialog from '#/components/Dialog' @@ -70,19 +70,27 @@ export function NewskieDialog({ - + - - + + + + Say hello! - + {profile.joinedViaStarterPack ? ( {profileName} joined Bluesky using a starter pack{' '} @@ -116,18 +124,23 @@ export function NewskieDialog({ ) : null} - + + {isNative && ( + + )} + + From bce3338a0236cdce2ef620c1f344b077390df0f5 Mon Sep 17 00:00:00 2001 From: Hailey Date: Mon, 24 Jun 2024 15:43:52 -0700 Subject: [PATCH 03/10] use `.push` instead of `.concat` (#4624) --- src/screens/Onboarding/StepFinished.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/screens/Onboarding/StepFinished.tsx b/src/screens/Onboarding/StepFinished.tsx index c7a459659f..9613ce660d 100644 --- a/src/screens/Onboarding/StepFinished.tsx +++ b/src/screens/Onboarding/StepFinished.tsx @@ -110,8 +110,8 @@ export function StepFinished() { // Any starter pack feeds will be pinned _after_ the defaults if (starterPack && starterPack.feeds?.length) { - feedsToSave.concat( - starterPack.feeds.map(f => ({ + feedsToSave.push( + ...starterPack.feeds.map(f => ({ type: 'feed', value: f.uri, pinned: true, From 9e89ddeb1c6bd84594f5b9a9152cd0d9b974b9a8 Mon Sep 17 00:00:00 2001 From: Hailey Date: Mon, 24 Jun 2024 15:48:10 -0700 Subject: [PATCH 04/10] Wait for preferences before showing suggested feeds (#4618) --- src/screens/StarterPack/Wizard/StepFeeds.tsx | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/screens/StarterPack/Wizard/StepFeeds.tsx b/src/screens/StarterPack/Wizard/StepFeeds.tsx index 5170edc6ef..878d17ce01 100644 --- a/src/screens/StarterPack/Wizard/StepFeeds.tsx +++ b/src/screens/StarterPack/Wizard/StepFeeds.tsx @@ -32,7 +32,7 @@ export function StepFeeds({moderationOpts}: {moderationOpts: ModerationOpts}) { const throttledQuery = useThrottledValue(query, 500) const {screenReaderEnabled} = useA11y() - const {data: savedFeedsAndLists, isLoading: isLoadingSavedFeeds} = + const {data: savedFeedsAndLists, isFetchedAfterMount: isFetchedSavedFeeds} = useSavedFeeds() const savedFeeds = savedFeedsAndLists?.feeds .filter(f => f.type === 'feed' && f.view.uri !== DISCOVER_FEED_URI) @@ -46,15 +46,23 @@ export function StepFeeds({moderationOpts}: {moderationOpts: ModerationOpts}) { limit: 30, }) const popularFeeds = popularFeedsPages?.pages.flatMap(p => p.feeds) ?? [] - const suggestedFeeds = savedFeeds.concat( - popularFeeds.filter(f => !savedFeeds.some(sf => sf.uri === f.uri)), - ) + + // If we have saved feeds already loaded, display them immediately + // Then, when popular feeds have loaded we can concat them to the saved feeds + const suggestedFeeds = + savedFeeds || isFetchedSavedFeeds + ? popularFeeds + ? savedFeeds.concat( + popularFeeds.filter(f => !savedFeeds.some(sf => sf.uri === f.uri)), + ) + : savedFeeds + : undefined const {data: searchedFeeds, isFetching: isFetchingSearchedFeeds} = useSearchPopularFeedsQuery({q: throttledQuery}) const isLoading = - isLoadingSavedFeeds || isLoadingPopularFeeds || isFetchingSearchedFeeds + !isFetchedSavedFeeds || isLoadingPopularFeeds || isFetchingSearchedFeeds const renderItem = ({ item, From ed940c637edda3f7a39b2aefb242e30f8ad8c7ff Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Mon, 24 Jun 2024 16:03:32 -0700 Subject: [PATCH 05/10] Set up the global 'joined this week' (#4625) --- src/lib/constants.ts | 9 +++++ .../StarterPack/StarterPackLandingScreen.tsx | 38 +++++++++---------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/lib/constants.ts b/src/lib/constants.ts index e0b8998007..0efaed44dd 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -13,6 +13,15 @@ export const EMBED_SERVICE = 'https://embed.bsky.app' export const EMBED_SCRIPT = `${EMBED_SERVICE}/static/embed.js` export const BSKY_DOWNLOAD_URL = 'https://bsky.app/download' +// HACK +// Yes, this is exactly what it looks like. It's a hard-coded constant +// reflecting the number of new users in the last week. We don't have +// time to add a route to the servers for this so we're just going to hard +// code and update this number with each release until we can get the +// server route done. +// -prf +export const JOINED_THIS_WEEK = 37115 // as of June24 2024 + const BASE_FEEDBACK_FORM_URL = `${HELP_DESK_URL}/requests/new` export function FEEDBACK_FORM_URL({ email, diff --git a/src/screens/StarterPack/StarterPackLandingScreen.tsx b/src/screens/StarterPack/StarterPackLandingScreen.tsx index 1c9587a79e..cd4ca151a3 100644 --- a/src/screens/StarterPack/StarterPackLandingScreen.tsx +++ b/src/screens/StarterPack/StarterPackLandingScreen.tsx @@ -11,6 +11,7 @@ import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {JOINED_THIS_WEEK} from '#/lib/constants' import {isAndroidWeb} from 'lib/browser' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {createStarterPackGooglePlayUri} from 'lib/strings/starter-pack' @@ -21,6 +22,7 @@ import { useActiveStarterPack, useSetActiveStarterPack, } from 'state/shell/starter-pack' +import {formatCount} from '#/view/com/util/numeric/format' import {LoggedOutScreenState} from 'view/com/auth/LoggedOut' import {CenteredView} from 'view/com/util/Views' import {Logo} from 'view/icons/Logo' @@ -95,7 +97,7 @@ function LandingScreenLoaded({ setScreenState: (state: LoggedOutScreenState) => void moderationOpts: ModerationOpts }) { - const {record, creator, listItemsSample, feeds, joinedWeekCount} = starterPack + const {record, creator, listItemsSample, feeds} = starterPack const {_} = useLingui() const t = useTheme() const activeStarterPack = useActiveStarterPack() @@ -200,24 +202,22 @@ function LandingScreenLoaded({ Join Bluesky - {joinedWeekCount && joinedWeekCount >= 25 ? ( - - - - 123,659 joined this week - - - ) : null} + + + + {formatCount(JOINED_THIS_WEEK)} joined this week + + {Boolean(listItemsSample?.length) && ( From 51fca956699ab2b686d137a9604c755c6d42ac78 Mon Sep 17 00:00:00 2001 From: Hailey Date: Mon, 24 Jun 2024 16:04:34 -0700 Subject: [PATCH 06/10] add rich text facets to description (#4619) --- src/screens/StarterPack/StarterPackScreen.tsx | 17 +++++-- src/screens/StarterPack/Wizard/index.tsx | 2 - src/state/queries/starter-packs.ts | 50 +++++++++++++------ 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/screens/StarterPack/StarterPackScreen.tsx b/src/screens/StarterPack/StarterPackScreen.tsx index 46ce252364..d89bda1371 100644 --- a/src/screens/StarterPack/StarterPackScreen.tsx +++ b/src/screens/StarterPack/StarterPackScreen.tsx @@ -7,6 +7,7 @@ import { AppBskyGraphStarterpack, AtUri, ModerationOpts, + RichText as RichTextAPI, } from '@atproto/api' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {msg, Trans} from '@lingui/macro' @@ -52,6 +53,7 @@ import {Loader} from '#/components/Loader' import * as Menu from '#/components/Menu' import * as Prompt from '#/components/Prompt' import {ReportDialog, useReportDialogControl} from '#/components/ReportDialog' +import {RichText} from '#/components/RichText' import {FeedsList} from '#/components/StarterPack/Main/FeedsList' import {ProfilesList} from '#/components/StarterPack/Main/ProfilesList' import {QrCodeDialog} from '#/components/StarterPack/QrCodeDialog' @@ -280,6 +282,13 @@ function Header({ return null } + const richText = record.description + ? new RichTextAPI({ + text: record.description, + facets: record.descriptionFacets, + }) + : undefined + return ( <> - {record.description || joinedAllTimeCount >= 25 ? ( + {richText || joinedAllTimeCount >= 25 ? ( - {record.description ? ( - - {record.description} - + {richText ? ( + ) : null} {joinedAllTimeCount >= 25 ? ( diff --git a/src/screens/StarterPack/Wizard/index.tsx b/src/screens/StarterPack/Wizard/index.tsx index fd16fd20ae..b231e317e3 100644 --- a/src/screens/StarterPack/Wizard/index.tsx +++ b/src/screens/StarterPack/Wizard/index.tsx @@ -245,7 +245,6 @@ function WizardInner({ editStarterPack({ name: state.name?.trim() || getDefaultName(), description: state.description?.trim(), - descriptionFacets: [], profiles: state.profiles, feeds: state.feeds, currentStarterPack: currentStarterPack, @@ -255,7 +254,6 @@ function WizardInner({ createStarterPack({ name: state.name?.trim() || getDefaultName(), description: state.description?.trim(), - descriptionFacets: [], profiles: state.profiles, feeds: state.feeds, }) diff --git a/src/state/queries/starter-packs.ts b/src/state/queries/starter-packs.ts index 241bc6419c..ca7fa2d0ce 100644 --- a/src/state/queries/starter-packs.ts +++ b/src/state/queries/starter-packs.ts @@ -4,8 +4,10 @@ import { AppBskyGraphDefs, AppBskyGraphGetStarterPack, AppBskyGraphStarterpack, + AppBskyRichtextFacet, AtUri, BskyAgent, + RichText, } from '@atproto/api' import {StarterPackView} from '@atproto/api/dist/client/types/app/bsky/graph/defs' import { @@ -80,7 +82,6 @@ export async function invalidateStarterPack({ interface UseCreateStarterPackMutationParams { name: string description?: string - descriptionFacets: [] profiles: AppBskyActorDefs.ProfileViewBasic[] feeds?: AppBskyFeedDefs.GeneratorView[] } @@ -100,16 +101,33 @@ export function useCreateStarterPackMutation({ Error, UseCreateStarterPackMutationParams >({ - mutationFn: async params => { + mutationFn: async ({name, description, feeds, profiles}) => { + let descriptionFacets: AppBskyRichtextFacet.Main[] | undefined + if (description) { + const rt = new RichText({text: description}) + await rt.detectFacets(agent) + descriptionFacets = rt.facets + } + let listRes - listRes = await createStarterPackList({...params, agent}) + listRes = await createStarterPackList({ + name, + description, + profiles, + descriptionFacets, + agent, + }) + return await agent.app.bsky.graph.starterpack.create( { repo: agent.session?.did, }, { - ...params, + name, + description, + descriptionFacets, list: listRes?.uri, + feeds, createdAt: new Date().toISOString(), }, ) @@ -148,16 +166,20 @@ export function useEditStarterPackMutation({ currentListItems: AppBskyGraphDefs.ListItemView[] } >({ - mutationFn: async params => { - const { - name, - description, - descriptionFacets, - feeds, - profiles, - currentStarterPack, - currentListItems, - } = params + mutationFn: async ({ + name, + description, + feeds, + profiles, + currentStarterPack, + currentListItems, + }) => { + let descriptionFacets: AppBskyRichtextFacet.Main[] | undefined + if (description) { + const rt = new RichText({text: description}) + await rt.detectFacets(agent) + descriptionFacets = rt.facets + } if (!AppBskyGraphStarterpack.isRecord(currentStarterPack.record)) { throw new Error('Invalid starter pack') From d79891a8584001db81895dac483f40d45cfa4f87 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Mon, 24 Jun 2024 18:10:18 -0500 Subject: [PATCH 07/10] Disable clicks on profile cards on starter pack lander (#4621) --- src/screens/StarterPack/StarterPackLandingScreen.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/screens/StarterPack/StarterPackLandingScreen.tsx b/src/screens/StarterPack/StarterPackLandingScreen.tsx index cd4ca151a3..b781419efe 100644 --- a/src/screens/StarterPack/StarterPackLandingScreen.tsx +++ b/src/screens/StarterPack/StarterPackLandingScreen.tsx @@ -240,6 +240,7 @@ function LandingScreenLoaded({ a.px_md, a.border_t, t.atoms.border_contrast_low, + {pointerEvents: 'none'}, ]}> Date: Tue, 25 Jun 2024 01:28:03 +0200 Subject: [PATCH 08/10] Update catalan messages.po (#4388) * Update catalan messages.po Keeping it at 100% Check it please @jordimas @darccio @surfdude29 * Update src/locale/locales/ca/messages.po Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * Update src/locale/locales/ca/messages.po Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * Update messages.po apply @jordimas correction --------- Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> --- src/locale/locales/ca/messages.po | 88 +++++++++++++++---------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/locale/locales/ca/messages.po b/src/locale/locales/ca/messages.po index 93d004f00c..6ec1268338 100644 --- a/src/locale/locales/ca/messages.po +++ b/src/locale/locales/ca/messages.po @@ -18,7 +18,7 @@ msgstr "" #: src/screens/Messages/List/ChatListItem.tsx:120 msgid "(contains embedded content)" -msgstr "" +msgstr "(té contingut incrustat)" #: src/view/com/modals/VerifyEmail.tsx:150 msgid "(no email)" @@ -113,7 +113,7 @@ msgstr "" #: src/view/com/util/UserAvatar.tsx:419 msgid "{0}'s avatar" -msgstr "" +msgstr "Avatar de {0}" #: src/screens/StarterPack/Wizard/StepDetails.tsx:68 msgid "{0}'s favorite feeds and people - join me!" @@ -505,7 +505,7 @@ msgstr "Tots els canals que has desat, en un sol lloc." #: src/view/com/modals/AddAppPasswords.tsx:187 #: src/view/com/modals/AddAppPasswords.tsx:194 msgid "Allow access to your direct messages" -msgstr "" +msgstr "Permet l'accés als teus missatges directes" #: src/screens/Messages/Settings.tsx:61 #: src/screens/Messages/Settings.tsx:64 @@ -515,7 +515,7 @@ msgstr "" #: src/screens/Messages/Settings.tsx:62 #: src/screens/Messages/Settings.tsx:65 msgid "Allow new messages from" -msgstr "" +msgstr "Permet missatges nou de" #: src/screens/Login/ForgotPasswordForm.tsx:178 #: src/view/com/modals/ChangePassword.tsx:171 @@ -1039,7 +1039,7 @@ msgstr "Cancel·la la citació de la publicació" #: src/screens/Deactivated.tsx:155 msgid "Cancel reactivation and log out" -msgstr "" +msgstr "Cancel·la la reactivació i surt" #: src/view/com/modals/ListAddRemoveUsers.tsx:87 #: src/view/shell/desktop/Search.tsx:214 @@ -1118,7 +1118,7 @@ msgstr "Configuració del xat" #: src/screens/Messages/Settings.tsx:59 #: src/view/screens/Settings/index.tsx:647 msgid "Chat Settings" -msgstr "" +msgstr "Configuració del xat" #: src/components/dms/ConvoMenu.tsx:84 msgid "Chat unmuted" @@ -1221,11 +1221,11 @@ msgstr "clica aquí" #: src/view/com/modals/DeleteAccount.tsx:208 msgid "Click here for more information on deactivating your account" -msgstr "" +msgstr "Clica aquí per a més informació sobre desactivar el teu compte" #: src/view/com/modals/DeleteAccount.tsx:216 msgid "Click here for more information." -msgstr "" +msgstr "Clica aquí per a més informació." #: src/screens/Feeds/NoFollowingFeed.tsx:46 #~ msgid "Click here to add one." @@ -1325,7 +1325,7 @@ msgstr "Tanca la visualització de la imatge de la capçalera" #: src/view/com/notifications/FeedItem.tsx:226 msgid "Collapse list of users" -msgstr "" +msgstr "Plega la llista d'usuaris" #: src/view/com/notifications/FeedItem.tsx:426 msgid "Collapses list of users for a given notification" @@ -1744,11 +1744,11 @@ msgstr "Data de naixement" #: src/screens/Settings/components/DeactivateAccountDialog.tsx:73 #: src/view/screens/Settings/index.tsx:806 msgid "Deactivate account" -msgstr "" +msgstr "Desactiva el compte" #: src/view/screens/Settings/index.tsx:818 msgid "Deactivate my account" -msgstr "" +msgstr "Desactiva el meu compte" #: src/view/screens/Settings/index.tsx:873 msgid "Debug Moderation" @@ -2402,7 +2402,7 @@ msgstr "Expandeix el text alternatiu" #: src/view/com/notifications/FeedItem.tsx:227 msgid "Expand list of users" -msgstr "" +msgstr "Expandeix la llista d'usuaris" #: src/view/com/composer/ComposerReplyTo.tsx:82 #: src/view/com/composer/ComposerReplyTo.tsx:85 @@ -2679,7 +2679,7 @@ msgstr "Segueix {0}" #: src/view/com/posts/AviFollowButton.tsx:71 msgid "Follow {name}" -msgstr "" +msgstr "Segueix a {name}" #: src/view/com/profile/ProfileMenu.tsx:246 #: src/view/com/profile/ProfileMenu.tsx:257 @@ -2782,7 +2782,7 @@ msgstr "Seguint {0}" #: src/view/com/posts/AviFollowButton.tsx:53 msgid "Following {name}" -msgstr "" +msgstr "Seguint a {name}" #: src/view/screens/Settings/index.tsx:573 msgid "Following feed preferences" @@ -3145,7 +3145,7 @@ msgstr "Si vols canviar la contrasenya t'enviarem un codi per a verificar que aq #: src/screens/Settings/components/DeactivateAccountDialog.tsx:92 msgid "If you're trying to change your handle or email, do so before you deactivate." -msgstr "" +msgstr "Si vols canviar el teu identificador o el correu fes-ho abans de desactivar el compte." #: src/lib/moderation/useReportOptions.ts:38 msgid "Illegal and Urgent" @@ -3622,7 +3622,7 @@ msgstr "Registre" #: src/screens/Deactivated.tsx:214 #: src/screens/Deactivated.tsx:220 msgid "Log in or sign up" -msgstr "" +msgstr "Inicia sessió o registra't" #: src/screens/SignupQueued.tsx:155 #: src/screens/SignupQueued.tsx:158 @@ -4380,7 +4380,7 @@ msgstr "Obre" #: src/view/com/posts/AviFollowButton.tsx:89 msgid "Open {name} profile shortcut menu" -msgstr "" +msgstr "Obre el menú de drecera del perfil {name}" #: src/screens/Onboarding/StepProfile/index.tsx:277 msgid "Open avatar creator" @@ -4463,7 +4463,7 @@ msgstr "Obre la càmera del dispositiu" #: src/view/screens/Settings/index.tsx:639 msgid "Opens chat settings" -msgstr "" +msgstr "Obre la configuració del xat" #: src/view/com/composer/Prompt.tsx:27 msgid "Opens composer" @@ -4517,7 +4517,7 @@ msgstr "Obre la llista de codis d'invitació" #: src/view/screens/Settings/index.tsx:808 msgid "Opens modal for account deactivation confirmation" -msgstr "" +msgstr "Obre el modal per a la confirmació de la desactivació del compte" #: src/view/screens/Settings/index.tsx:830 msgid "Opens modal for account deletion confirmation. Requires email code" @@ -4604,7 +4604,7 @@ msgstr "Obre les preferències dels fils de debat" #: src/view/com/notifications/FeedItem.tsx:513 #: src/view/com/util/UserAvatar.tsx:422 msgid "Opens this profile" -msgstr "" +msgstr "Obre aquest perfil" #: src/view/com/util/forms/DropdownButton.tsx:293 msgid "Option {0} of {numItems}" @@ -4621,11 +4621,11 @@ msgstr "O combina aquestes opcions:" #: src/screens/Deactivated.tsx:211 msgid "Or, continue with another account." -msgstr "" +msgstr "O continua amb un altre compte." #: src/screens/Deactivated.tsx:194 msgid "Or, log into one of your other accounts." -msgstr "" +msgstr "O inicia sessió en un altre dels teus comptes." #: src/lib/moderation/useReportOptions.ts:27 msgid "Other" @@ -5067,7 +5067,7 @@ msgstr "Proporcions" #: src/screens/Deactivated.tsx:144 msgid "Reactivate your account" -msgstr "" +msgstr "Torna a activar el teu compte" #: src/components/dms/ReportDialog.tsx:174 msgid "Reason:" @@ -5129,7 +5129,7 @@ msgstr "Elimina el bàner" #: src/screens/Messages/Conversation/MessageInputEmbed.tsx:218 msgid "Remove embed" -msgstr "" +msgstr "Elimina l'incrustat" #: src/view/com/posts/FeedErrorMessage.tsx:168 #: src/view/com/posts/FeedShutdownMsg.tsx:113 @@ -5168,11 +5168,11 @@ msgstr "Elimina la paraula silenciada de la teva llista" #: src/view/screens/Search/Search.tsx:974 msgid "Remove profile" -msgstr "" +msgstr "Elimina el perfil" #: src/view/screens/Search/Search.tsx:976 msgid "Remove profile from search history" -msgstr "" +msgstr "Elimina el perfil de l'historial de cerca" #: src/view/com/util/post-embeds/QuoteEmbed.tsx:238 msgid "Remove quote" @@ -5868,7 +5868,7 @@ msgstr "Envia el missatge" #: src/components/dms/dialogs/ShareViaChatDialog.tsx:59 msgid "Send post to..." -msgstr "" +msgstr "Envia el missatge a..." #: src/components/dms/ReportDialog.tsx:234 #: src/components/dms/ReportDialog.tsx:237 @@ -5893,7 +5893,7 @@ msgstr "Envia un correu de verificació" #: src/view/com/util/forms/PostDropdownBtn.tsx:296 #: src/view/com/util/forms/PostDropdownBtn.tsx:299 msgid "Send via direct message" -msgstr "" +msgstr "Envia per missatge directe" #: src/view/com/modals/DeleteAccount.tsx:151 msgid "Sends email with confirmation code for account deletion" @@ -6143,7 +6143,7 @@ msgstr "Mostra seguidors semblants a {0}" #: src/view/com/post-thread/PostThreadShowHiddenReplies.tsx:23 msgid "Show hidden replies" -msgstr "" +msgstr "Mostra les respostes ocultes" #: src/view/com/util/forms/PostDropdownBtn.tsx:346 #: src/view/com/util/forms/PostDropdownBtn.tsx:348 @@ -6163,7 +6163,7 @@ msgstr "Mostra'n més com aquest" #: src/view/com/post-thread/PostThreadShowHiddenReplies.tsx:23 msgid "Show muted replies" -msgstr "" +msgstr "Mostra les respostes silenciades" #: src/view/screens/PreferencesFollowingFeed.tsx:257 msgid "Show Posts from My Feeds" @@ -6371,7 +6371,7 @@ msgstr "Alguna cosa ha fallat" #: src/screens/Deactivated.tsx:94 #: src/screens/Settings/components/DeactivateAccountDialog.tsx:59 msgid "Something went wrong, please try again" -msgstr "" +msgstr "Alguna cosa ha fallat, torna-ho a provar" #: src/components/ReportDialog/index.tsx:59 #: src/screens/Moderation/index.tsx:114 @@ -6715,7 +6715,7 @@ msgstr "Les condicions del servei han estat traslladades a" #: src/screens/Settings/components/DeactivateAccountDialog.tsx:86 msgid "There is no time limit for account deactivation, come back any time." -msgstr "" +msgstr "No hi ha límit de temps per a la desactivació del compte, torna quan vulguis." #: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:115 #: src/view/screens/ProfileFeed.tsx:542 @@ -7517,7 +7517,7 @@ msgstr "Veure l'avatar de {0}" #: src/view/com/notifications/FeedItem.tsx:234 msgid "View {0}'s profile" -msgstr "" +msgstr "Veure el perfil de {0}" #: src/components/ProfileHoverCard/index.web.tsx:430 msgid "View blocked user's profile" @@ -7682,7 +7682,7 @@ msgstr "" #: src/screens/Deactivated.tsx:128 msgid "Welcome back!" -msgstr "" +msgstr "Bentornat!" #: src/view/com/auth/onboarding/WelcomeMobile.tsx:48 #~ msgid "Welcome to <0>Bluesky" @@ -7808,7 +7808,7 @@ msgstr "Sí" #: src/screens/Settings/components/DeactivateAccountDialog.tsx:106 #: src/screens/Settings/components/DeactivateAccountDialog.tsx:108 msgid "Yes, deactivate" -msgstr "" +msgstr "Sí, desactiva'l" #: src/screens/StarterPack/StarterPackScreen.tsx:525 msgid "Yes, delete this starter pack" @@ -7816,7 +7816,7 @@ msgstr "" #: src/screens/Deactivated.tsx:150 msgid "Yes, reactivate my account" -msgstr "" +msgstr "Sí, torna a activar el meu compte" #: src/components/dms/MessageItem.tsx:188 msgid "Yesterday, {time}" @@ -7841,7 +7841,7 @@ msgstr "També pots descobrir nous canals personalitzats per a seguir." #: src/view/com/modals/DeleteAccount.tsx:202 msgid "You can also temporarily deactivate your account instead, and reactivate it at any time." -msgstr "" +msgstr "També pots desactivar el teu compte temporalment i reactivar-lo en qualsevol moment." #: src/view/com/auth/create/Step1.tsx:106 #~ msgid "You can change hosting providers at any time." @@ -7857,7 +7857,7 @@ msgstr "Pots canviar-ho quan vulguis." #: src/screens/Messages/Settings.tsx:111 msgid "You can continue ongoing conversations regardless of which setting you choose." -msgstr "" +msgstr "Pots continuar les converses en curs independentment de la configuració que triïs." #: src/screens/Login/index.tsx:158 #: src/screens/Login/PasswordUpdatedForm.tsx:33 @@ -7866,7 +7866,7 @@ msgstr "Ara pots iniciar sessió amb la nova contrasenya." #: src/screens/Deactivated.tsx:136 msgid "You can reactivate your account to continue logging in. Your profile and posts will be visible to other users." -msgstr "" +msgstr "Pots reactivar el teu compte per continuar iniciant la sessió. El teu perfil i les publicacions seran visibles per a altres usuaris." #: src/view/com/profile/ProfileFollowers.tsx:86 msgid "You do not have any followers." @@ -8025,7 +8025,7 @@ msgstr "Has d'escollir almenys un etiquetador per a un informe" #: src/screens/Deactivated.tsx:131 msgid "You previously deactivated @{0}." -msgstr "" +msgstr "Abans has desactivat @{0}." #: src/view/com/util/forms/PostDropdownBtn.tsx:174 msgid "You will no longer receive notifications for this thread" @@ -8045,11 +8045,11 @@ msgstr "Tu: {0}" #: src/screens/Messages/List/ChatListItem.tsx:143 msgid "You: {defaultEmbeddedContentMessage}" -msgstr "" +msgstr "Tu: {defaultEmbeddedContentMessage}" #: src/screens/Messages/List/ChatListItem.tsx:136 msgid "You: {short}" -msgstr "" +msgstr "Tu: {short}" #: src/screens/Signup/index.tsx:169 msgid "You'll follow the suggested users and feeds once you finish creating your account!" @@ -8084,7 +8084,7 @@ msgstr "Estàs a la cua" #: src/screens/Deactivated.tsx:89 #: src/screens/Settings/components/DeactivateAccountDialog.tsx:54 msgid "You're logged in with an App Password. Please log in with your main password to continue deactivating your account." -msgstr "" +msgstr "Has iniciat sessió amb una contrasenya d'aplicació. Inicia sessió amb la teva contrasenya principal per continuar la desactivació del teu compte." #: src/screens/Onboarding/StepFinished.tsx:228 msgid "You're ready to go!" @@ -8189,7 +8189,7 @@ msgstr "El teu perfil" #: src/screens/Settings/components/DeactivateAccountDialog.tsx:75 msgid "Your profile, posts, feeds, and lists will no longer be visible to other Bluesky users. You can reactivate your account at any time by logging in." -msgstr "" +msgstr "El teu perfil, publicacions, fonts i llistes ja no seran visibles per a altres usuaris de Bluesky. Pots reactivar el teu compte en qualsevol moment iniciant sessió." #: src/view/com/composer/Composer.tsx:365 msgid "Your reply has been published" From dc9e51dca19822bb1c0ae688d581bdb27ace6747 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Mon, 24 Jun 2024 16:31:07 -0700 Subject: [PATCH 09/10] Add borders around starter pack landing page when tablet or deskto (#4626) --- .../StarterPack/StarterPackLandingScreen.tsx | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/screens/StarterPack/StarterPackLandingScreen.tsx b/src/screens/StarterPack/StarterPackLandingScreen.tsx index b781419efe..a7bc451b7b 100644 --- a/src/screens/StarterPack/StarterPackLandingScreen.tsx +++ b/src/screens/StarterPack/StarterPackLandingScreen.tsx @@ -231,14 +231,21 @@ function LandingScreenLoaded({ )} - - {starterPack.listItemsSample?.slice(0, 8).map(item => ( + + {starterPack.listItemsSample?.slice(0, 8).map((item, i) => ( @@ -257,13 +264,21 @@ function LandingScreenLoaded({ You'll stay updated with these feeds - - {feeds?.map(feed => ( + + {feeds?.map((feed, i) => ( From 795fe7455b77c01fe6d9274c172e3e9c9ec1464e Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Mon, 24 Jun 2024 18:55:29 -0500 Subject: [PATCH 10/10] Clicky newsky androidy (#4627) * Clicky newsky androidy * tweak --------- Co-authored-by: Hailey --- src/screens/Profile/Header/Handle.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/screens/Profile/Header/Handle.tsx b/src/screens/Profile/Header/Handle.tsx index 268b7350f8..0344f1a234 100644 --- a/src/screens/Profile/Header/Handle.tsx +++ b/src/screens/Profile/Header/Handle.tsx @@ -5,7 +5,7 @@ import {Trans} from '@lingui/macro' import {Shadow} from '#/state/cache/types' import {isInvalidHandle} from 'lib/strings/handles' -import {isAndroid} from 'platform/detection' +import {isIOS} from 'platform/detection' import {atoms as a, useTheme, web} from '#/alf' import {NewskieDialog} from '#/components/NewskieDialog' import {Text} from '#/components/Typography' @@ -23,7 +23,7 @@ export function ProfileHeaderHandle({ return ( + pointerEvents={disableTaps ? 'none' : isIOS ? 'auto' : 'box-none'}> {profile.viewer?.followedBy && !blockHide ? (