diff options
author | Hailey <me@haileyok.com> | 2024-06-24 10:24:39 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-24 10:24:39 -0700 |
commit | 77a512ae32eb1aae6be2b67779ffd9d8a1e28cb6 (patch) | |
tree | e9c9d792aecc478b89500ab85bfd6adfed2e4662 | |
parent | f769564edfea3ec6406c49ef639685d942e14e09 (diff) | |
download | voidsky-77a512ae32eb1aae6be2b67779ffd9d8a1e28cb6.tar.zst |
Couple of starter packs tweaks (#4604)
-rw-r--r-- | app.config.js | 4 | ||||
-rw-r--r-- | src/components/StarterPack/QrCodeDialog.tsx | 10 | ||||
-rw-r--r-- | src/components/StarterPack/ShareDialog.tsx | 23 | ||||
-rw-r--r-- | src/components/StarterPack/Wizard/WizardEditListDialog.tsx | 2 | ||||
-rw-r--r-- | src/components/StarterPack/Wizard/WizardListCard.tsx | 29 | ||||
-rw-r--r-- | src/screens/StarterPack/Wizard/StepFeeds.tsx | 13 | ||||
-rw-r--r-- | src/screens/StarterPack/Wizard/StepProfiles.tsx | 1 | ||||
-rw-r--r-- | src/screens/StarterPack/Wizard/index.tsx | 38 |
8 files changed, 57 insertions, 63 deletions
diff --git a/app.config.js b/app.config.js index 57d430586..4a4491228 100644 --- a/app.config.js +++ b/app.config.js @@ -45,9 +45,7 @@ module.exports = function (config) { 'appclips:bsky.app', 'appclips:go.bsky.app', // Allows App Clip to work when scanning QR codes // When testing local services, enter an ngrok (et al) domain here. It must use a standard HTTP/HTTPS port. - ...(IS_DEV || IS_TESTFLIGHT - ? ['appclips:sptesting.haileyok.com', 'applinks:sptesting.haileyok.com'] - : []), + ...(IS_DEV || IS_TESTFLIGHT ? [] : []), ] const UPDATES_CHANNEL = IS_TESTFLIGHT diff --git a/src/components/StarterPack/QrCodeDialog.tsx b/src/components/StarterPack/QrCodeDialog.tsx index 580c6cc7c..39eb3076d 100644 --- a/src/components/StarterPack/QrCodeDialog.tsx +++ b/src/components/StarterPack/QrCodeDialog.tsx @@ -1,16 +1,14 @@ import React from 'react' import {View} from 'react-native' import ViewShot from 'react-native-view-shot' -import * as FS from 'expo-file-system' import {requestMediaLibraryPermissionsAsync} from 'expo-image-picker' +import {createAssetAsync} from 'expo-media-library' import * as Sharing from 'expo-sharing' import {AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {nanoid} from 'nanoid/non-secure' import {logger} from '#/logger' -import {saveImageToMediaLibrary} from 'lib/media/manip' import {logEvent} from 'lib/statsig/statsig' import {isNative, isWeb} from 'platform/detection' import * as Toast from '#/view/com/util/Toast' @@ -65,13 +63,9 @@ export function QrCodeDialog({ return } - const filename = `${FS.documentDirectory}/${nanoid(12)}.png` - // Incase of a FS failure, don't crash the app try { - await FS.copyAsync({from: uri, to: filename}) - await saveImageToMediaLibrary({uri: filename}) - await FS.deleteAsync(filename) + await createAssetAsync(`file://${uri}`) } catch (e: unknown) { Toast.show(_(msg`An error occurred while saving the QR code!`)) logger.error('Failed to save QR code', {error: e}) diff --git a/src/components/StarterPack/ShareDialog.tsx b/src/components/StarterPack/ShareDialog.tsx index 23fa10fb3..61e238081 100644 --- a/src/components/StarterPack/ShareDialog.tsx +++ b/src/components/StarterPack/ShareDialog.tsx @@ -1,12 +1,10 @@ import React from 'react' import {View} from 'react-native' -import * as FS from 'expo-file-system' import {Image} from 'expo-image' import {requestMediaLibraryPermissionsAsync} from 'expo-image-picker' import {AppBskyGraphDefs} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {nanoid} from 'nanoid/non-secure' import {logger} from '#/logger' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' @@ -72,19 +70,8 @@ function ShareDialogInner({ return } - const cachePath = await Image.getCachePathAsync(imageUrl) - const filename = `${FS.documentDirectory}/${nanoid(12)}.png` - - if (!cachePath) { - Toast.show(_(msg`An error occurred while saving the image.`)) - return - } - try { - await FS.copyAsync({from: cachePath, to: filename}) - await saveImageToMediaLibrary({uri: filename}) - await FS.deleteAsync(filename) - + await saveImageToMediaLibrary({uri: imageUrl}) Toast.show(_(msg`Image saved to your camera roll!`)) control.close() } catch (e: unknown) { @@ -133,18 +120,18 @@ function ShareDialogInner({ isWeb && [a.gap_sm, a.flex_row_reverse, {marginLeft: 'auto'}], ]}> <Button - label="Share link" + label={isWeb ? _(msg`Copy link`) : _(msg`Share link`)} variant="solid" color="secondary" size="small" style={[isWeb && a.self_center]} onPress={onShareLink}> <ButtonText> - {isWeb ? <Trans>Copy Link</Trans> : <Trans>Share Link</Trans>} + {isWeb ? <Trans>Copy Link</Trans> : <Trans>Share link</Trans>} </ButtonText> </Button> <Button - label="Create QR code" + label={_(msg`Share QR code`)} variant="solid" color="secondary" size="small" @@ -155,7 +142,7 @@ function ShareDialogInner({ }) }}> <ButtonText> - <Trans>Create QR code</Trans> + <Trans>Share QR code</Trans> </ButtonText> </Button> {isNative && ( diff --git a/src/components/StarterPack/Wizard/WizardEditListDialog.tsx b/src/components/StarterPack/Wizard/WizardEditListDialog.tsx index bf250ac35..cf755e1bc 100644 --- a/src/components/StarterPack/Wizard/WizardEditListDialog.tsx +++ b/src/components/StarterPack/Wizard/WizardEditListDialog.tsx @@ -58,6 +58,7 @@ export function WizardEditListDialog({ state.currentStep === 'Profiles' ? ( <WizardProfileCard profile={item} + btnType="remove" state={state} dispatch={dispatch} moderationOpts={moderationOpts} @@ -65,6 +66,7 @@ export function WizardEditListDialog({ ) : ( <WizardFeedCard generator={item} + btnType="remove" state={state} dispatch={dispatch} moderationOpts={moderationOpts} diff --git a/src/components/StarterPack/Wizard/WizardListCard.tsx b/src/components/StarterPack/Wizard/WizardListCard.tsx index f1332011d..aa1b2cf9b 100644 --- a/src/components/StarterPack/Wizard/WizardListCard.tsx +++ b/src/components/StarterPack/Wizard/WizardListCard.tsx @@ -9,7 +9,7 @@ import { ModerationUI, } from '@atproto/api' import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs' -import {msg} from '@lingui/macro' +import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {DISCOVER_FEED_URI} from 'lib/constants' @@ -19,12 +19,14 @@ import {useSession} from 'state/session' import {UserAvatar} from 'view/com/util/UserAvatar' import {WizardAction, WizardState} from '#/screens/StarterPack/Wizard/State' import {atoms as a, useTheme} from '#/alf' +import {Button, ButtonText} from '#/components/Button' import * as Toggle from '#/components/forms/Toggle' import {Checkbox} from '#/components/forms/Toggle' import {Text} from '#/components/Typography' function WizardListCard({ type, + btnType, displayName, subtitle, onPress, @@ -34,6 +36,7 @@ function WizardListCard({ moderationUi, }: { type: 'user' | 'algo' + btnType: 'checkbox' | 'remove' profile?: AppBskyActorDefs.ProfileViewBasic feed?: AppBskyFeedDefs.GeneratorView displayName: string @@ -56,7 +59,7 @@ function WizardListCard({ : _(msg`Add ${displayName} to starter pack`) } value={included} - disabled={disabled} + disabled={btnType === 'remove' || disabled} onChange={onPress} style={[ a.flex_row, @@ -85,17 +88,33 @@ function WizardListCard({ {subtitle} </Text> </View> - <Checkbox /> + {btnType === 'checkbox' ? ( + <Checkbox /> + ) : !disabled ? ( + <Button + label={_(msg`Remove`)} + variant="solid" + color="secondary" + size="xsmall" + style={[a.self_center, {marginLeft: 'auto'}]} + onPress={onPress}> + <ButtonText> + <Trans>Remove</Trans> + </ButtonText> + </Button> + ) : null} </Toggle.Item> ) } export function WizardProfileCard({ + btnType, state, dispatch, profile, moderationOpts, }: { + btnType: 'checkbox' | 'remove' state: WizardState dispatch: (action: WizardAction) => void profile: AppBskyActorDefs.ProfileViewBasic @@ -127,6 +146,7 @@ export function WizardProfileCard({ return ( <WizardListCard type="user" + btnType={btnType} displayName={displayName} subtitle={`@${sanitizeHandle(profile.handle)}`} onPress={onPress} @@ -139,11 +159,13 @@ export function WizardProfileCard({ } export function WizardFeedCard({ + btnType, generator, state, dispatch, moderationOpts, }: { + btnType: 'checkbox' | 'remove' generator: GeneratorView state: WizardState dispatch: (action: WizardAction) => void @@ -170,6 +192,7 @@ export function WizardFeedCard({ return ( <WizardListCard type="algo" + btnType={btnType} displayName={sanitizeDisplayName(generator.displayName)} subtitle={`Feed by @${sanitizeHandle(generator.creator.handle)}`} onPress={onPress} diff --git a/src/screens/StarterPack/Wizard/StepFeeds.tsx b/src/screens/StarterPack/Wizard/StepFeeds.tsx index 6752a95db..fbd8e7389 100644 --- a/src/screens/StarterPack/Wizard/StepFeeds.tsx +++ b/src/screens/StarterPack/Wizard/StepFeeds.tsx @@ -40,12 +40,14 @@ export function StepFeeds({moderationOpts}: {moderationOpts: ModerationOpts}) { const {data: popularFeedsPages, fetchNextPage} = useGetPopularFeedsQuery({ limit: 30, }) - const popularFeeds = - popularFeedsPages?.pages - .flatMap(page => page.feeds) - .filter(f => !savedFeeds?.some(sf => sf?.uri === f.uri)) ?? [] + const popularFeeds = popularFeedsPages?.pages.flatMap(p => p.feeds) ?? [] - const suggestedFeeds = savedFeeds?.concat(popularFeeds) + const suggestedFeeds = + savedFeeds.length === 0 + ? popularFeeds + : savedFeeds.concat( + popularFeeds.filter(f => !savedFeeds.some(sf => sf.uri === f.uri)), + ) const {data: searchedFeeds, isLoading: isLoadingSearch} = useSearchPopularFeedsQuery({q: throttledQuery}) @@ -56,6 +58,7 @@ export function StepFeeds({moderationOpts}: {moderationOpts: ModerationOpts}) { return ( <WizardFeedCard generator={item} + btnType="checkbox" state={state} dispatch={dispatch} moderationOpts={moderationOpts} diff --git a/src/screens/StarterPack/Wizard/StepProfiles.tsx b/src/screens/StarterPack/Wizard/StepProfiles.tsx index 8fe7f52fe..f21b01d40 100644 --- a/src/screens/StarterPack/Wizard/StepProfiles.tsx +++ b/src/screens/StarterPack/Wizard/StepProfiles.tsx @@ -45,6 +45,7 @@ export function StepProfiles({ return ( <WizardProfileCard profile={item} + btnType="checkbox" state={state} dispatch={dispatch} moderationOpts={moderationOpts} diff --git a/src/screens/StarterPack/Wizard/index.tsx b/src/screens/StarterPack/Wizard/index.tsx index 7cee86f84..fd16fd20a 100644 --- a/src/screens/StarterPack/Wizard/index.tsx +++ b/src/screens/StarterPack/Wizard/index.tsx @@ -21,6 +21,7 @@ import {NativeStackScreenProps} from '@react-navigation/native-stack' import {logger} from '#/logger' import {HITSLOP_10} from 'lib/constants' +import {createSanitizedDisplayName} from 'lib/moderation/create-sanitized-display-name' import {CommonNavigatorParams, NavigationProp} from 'lib/routes/types' import {logEvent} from 'lib/statsig/statsig' import {sanitizeDisplayName} from 'lib/strings/display-names' @@ -170,15 +171,7 @@ function WizardInner({ ) const getDefaultName = () => { - let displayName - if ( - currentProfile?.displayName != null && - currentProfile?.displayName !== '' - ) { - displayName = sanitizeDisplayName(currentProfile.displayName) - } else { - displayName = sanitizeHandle(currentProfile!.handle) - } + const displayName = createSanitizedDisplayName(currentProfile!, true) return _(msg`${displayName}'s Starter Pack`).slice(0, 50) } @@ -191,16 +184,12 @@ function WizardInner({ nextBtn: _(msg`Next`), }, Profiles: { - header: _(msg`People`), + header: _(msg`Choose People`), nextBtn: _(msg`Next`), - subtitle: _( - msg`Add people to your starter pack that you think others will enjoy following`, - ), }, Feeds: { - header: _(msg`Feeds`), + header: _(msg`Choose Feeds`), nextBtn: state.feeds.length === 0 ? _(msg`Skip`) : _(msg`Finish`), - subtitle: _(msg`Some subtitle`), }, } const currUiStrings = wizardUiStrings[state.currentStep] @@ -254,8 +243,8 @@ function WizardInner({ dispatch({type: 'SetProcessing', processing: true}) if (currentStarterPack && currentListItems) { editStarterPack({ - name: state.name ?? getDefaultName(), - description: state.description, + name: state.name?.trim() || getDefaultName(), + description: state.description?.trim(), descriptionFacets: [], profiles: state.profiles, feeds: state.feeds, @@ -264,8 +253,8 @@ function WizardInner({ }) } else { createStarterPack({ - name: state.name ?? getDefaultName(), - description: state.description, + name: state.name?.trim() || getDefaultName(), + description: state.description?.trim(), descriptionFacets: [], profiles: state.profiles, feeds: state.feeds, @@ -483,13 +472,10 @@ function Footer({ </Trans> ) : items.length === 2 ? ( <Trans> - <Text style={[a.font_bold, textStyles]}> - {getName(items[initialNamesIndex])}{' '} - </Text> - and + <Text style={[a.font_bold, textStyles]}>You</Text> and <Text> </Text> <Text style={[a.font_bold, textStyles]}> - {getName(items[state.currentStep === 'Profiles' ? 0 : 1])}{' '} + {getName(items[initialNamesIndex])}{' '} </Text> are included in your starter pack </Trans> @@ -579,9 +565,9 @@ function Footer({ function getName(item: AppBskyActorDefs.ProfileViewBasic | GeneratorView) { if (typeof item.displayName === 'string') { - return enforceLen(sanitizeDisplayName(item.displayName), 16, true) + return enforceLen(sanitizeDisplayName(item.displayName), 28, true) } else if (typeof item.handle === 'string') { - return enforceLen(sanitizeHandle(item.handle), 16, true) + return enforceLen(sanitizeHandle(item.handle), 28, true) } return '' } |