diff --git a/app.config.js b/app.config.js
index 57d4305865..4a44912289 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 580c6cc7c8..39eb3076d8 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 23fa10fb39..61e238081d 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'}],
]}>
{isNative && (
diff --git a/src/components/StarterPack/Wizard/WizardEditListDialog.tsx b/src/components/StarterPack/Wizard/WizardEditListDialog.tsx
index bf250ac354..cf755e1bcf 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' ? (
-
+ {btnType === 'checkbox' ? (
+
+ ) : !disabled ? (
+
+ ) : null}
)
}
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 (
void
@@ -170,6 +192,7 @@ export function WizardFeedCard({
return (
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 (
{
- 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({
) : items.length === 2 ? (
-
- {getName(items[initialNamesIndex])}{' '}
-
- and
+ You and
- {getName(items[state.currentStep === 'Profiles' ? 0 : 1])}{' '}
+ {getName(items[initialNamesIndex])}{' '}
are included in your starter pack
@@ -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 ''
}