From ad1d7cdebd33603cb7c303adeb56735bc79564cf Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Thu, 27 Nov 2025 19:31:19 +0200 Subject: [PATCH] add basic settings screen --- .../contacts_stroke2_corner2_rounded.svg | 1 + bskyweb/cmd/bskyweb/server.go | 1 + src/Navigation.tsx | 17 ++++-- src/components/icons/Contacts.tsx | 5 ++ src/lib/routes/types.ts | 1 + src/routes.ts | 1 + src/screens/Settings/Settings.tsx | 9 +++ src/screens/Settings/SyncContactsSettings.tsx | 56 +++++++++++++++++++ 8 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 assets/icons/contacts_stroke2_corner2_rounded.svg create mode 100644 src/components/icons/Contacts.tsx create mode 100644 src/screens/Settings/SyncContactsSettings.tsx diff --git a/assets/icons/contacts_stroke2_corner2_rounded.svg b/assets/icons/contacts_stroke2_corner2_rounded.svg new file mode 100644 index 0000000000..d7ba9a150b --- /dev/null +++ b/assets/icons/contacts_stroke2_corner2_rounded.svg @@ -0,0 +1 @@ + diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go index 790f211eed..7d78b0fee3 100644 --- a/bskyweb/cmd/bskyweb/server.go +++ b/bskyweb/cmd/bskyweb/server.go @@ -308,6 +308,7 @@ func serve(cctx *cli.Context) error { e.GET("/settings/notifications/reposts-on-reposts", server.WebGeneric) e.GET("/settings/notifications/activity", server.WebGeneric) e.GET("/settings/notifications/miscellaneous", server.WebGeneric) + e.GET("/settings/sync-contacts", server.WebGeneric) e.GET("/settings/app-icon", server.WebGeneric) e.GET("/sys/debug", server.WebGeneric) e.GET("/sys/debug-mod", server.WebGeneric) diff --git a/src/Navigation.tsx b/src/Navigation.tsx index fa33a9d56c..1282e7d378 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -18,7 +18,9 @@ import { } from '@react-navigation/native' import {timeout} from '#/lib/async/timeout' +import {useAccountSwitcher} from '#/lib/hooks/useAccountSwitcher' import {useColorSchemeStyle} from '#/lib/hooks/useColorSchemeStyle' +import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' import { getNotificationPayload, type NotificationPayload, @@ -45,10 +47,12 @@ import {logger} from '#/logger' import {isNative, isWeb} from '#/platform/detection' import {useUnreadNotifications} from '#/state/queries/notifications/unread' import {useSession} from '#/state/session' +import {useLoggedOutViewControls} from '#/state/shell/logged-out' import { shouldRequestEmailConfirmation, snoozeEmailConfirmationPrompt, } from '#/state/shell/reminders' +import {useCloseAllActiveElements} from '#/state/util' import {CommunityGuidelinesScreen} from '#/view/screens/CommunityGuidelines' import {CopyrightPolicyScreen} from '#/view/screens/CopyrightPolicy' import {DebugModScreen} from '#/view/screens/DebugMod' @@ -119,6 +123,7 @@ import {RepostNotificationSettingsScreen} from '#/screens/Settings/NotificationS import {RepostsOnRepostsNotificationSettingsScreen} from '#/screens/Settings/NotificationSettings/RepostsOnRepostsNotificationSettings' import {PrivacyAndSecuritySettingsScreen} from '#/screens/Settings/PrivacyAndSecuritySettings' import {SettingsScreen} from '#/screens/Settings/Settings' +import {SyncContactsSettingsScreen} from '#/screens/Settings/SyncContactsSettings' import {ThreadPreferencesScreen} from '#/screens/Settings/ThreadPreferences' import { StarterPackScreen, @@ -134,10 +139,6 @@ import { } from '#/components/dialogs/EmailDialog' import {router} from '#/routes' import {Referrer} from '../modules/expo-bluesky-swiss-army' -import {useAccountSwitcher} from './lib/hooks/useAccountSwitcher' -import {useNonReactiveCallback} from './lib/hooks/useNonReactiveCallback' -import {useLoggedOutViewControls} from './state/shell/logged-out' -import {useCloseAllActiveElements} from './state/util' const navigationRef = createNavigationContainerRef() @@ -416,6 +417,14 @@ function commonScreens(Stack: typeof Flat, unreadCountLabel?: string) { requireAuth: true, }} /> + SyncContactsSettingsScreen} + options={{ + title: title(msg`Sync contacts`), + requireAuth: true, + }} + /> NotificationSettingsScreen} diff --git a/src/components/icons/Contacts.tsx b/src/components/icons/Contacts.tsx new file mode 100644 index 0000000000..4467a396d5 --- /dev/null +++ b/src/components/icons/Contacts.tsx @@ -0,0 +1,5 @@ +import {createSinglePathSVG} from './TEMPLATE' + +export const Contacts_Stroke2_Corner2_Rounded = createSinglePathSVG({ + path: 'M7 4a1 1 0 0 0-1 1v12.05q.243-.05.5-.05H18V4H7Zm5 7c.894 0 1.57.188 2.068.513.445.29.683.647.806.937l.046.12c.285.836-.43 1.43-1.03 1.43h-3.78c-.6 0-1.315-.594-1.03-1.43l.046-.12c.123-.29.361-.647.806-.937C10.43 11.188 11.106 11 12 11Zm0-4a1.75 1.75 0 1 1 0 3.5A1.75 1.75 0 0 1 12 7Zm8 11a1 1 0 0 1-1 1H6.5a.5.5 0 0 0 0 1H19a1 1 0 1 1 0 2H6.5A2.5 2.5 0 0 1 4 19.5V5a3 3 0 0 1 3-3h11a2 2 0 0 1 2 2v14Z', +}) diff --git a/src/lib/routes/types.ts b/src/lib/routes/types.ts index c315a83418..ceeef7389e 100644 --- a/src/lib/routes/types.ts +++ b/src/lib/routes/types.ts @@ -67,6 +67,7 @@ export type CommonNavigatorParams = { InterestsSettings: undefined AboutSettings: undefined AppIconSettings: undefined + SyncContactsSettings: undefined Search: {q?: string; tab?: 'user' | 'profile' | 'feed'} Hashtag: {tag: string; author?: string} Topic: {topic: string} diff --git a/src/routes.ts b/src/routes.ts index 1ed913bb29..5afed2c965 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -69,6 +69,7 @@ export const router = new Router({ '/settings/notifications/reposts-on-reposts', ActivityNotificationSettings: '/settings/notifications/activity', MiscellaneousNotificationSettings: '/settings/notifications/miscellaneous', + SyncContactsSettings: '/settings/sync-contacts', // support Support: '/support', PrivacyPolicy: '/support/privacy', diff --git a/src/screens/Settings/Settings.tsx b/src/screens/Settings/Settings.tsx index 1703036b51..351a469aab 100644 --- a/src/screens/Settings/Settings.tsx +++ b/src/screens/Settings/Settings.tsx @@ -45,6 +45,7 @@ import {BubbleInfo_Stroke2_Corner2_Rounded as BubbleInfoIcon} from '#/components import {ChevronTop_Stroke2_Corner0_Rounded as ChevronUpIcon} from '#/components/icons/Chevron' import {CircleQuestion_Stroke2_Corner2_Rounded as CircleQuestionIcon} from '#/components/icons/CircleQuestion' import {CodeBrackets_Stroke2_Corner2_Rounded as CodeBracketsIcon} from '#/components/icons/CodeBrackets' +import {Contacts_Stroke2_Corner2_Rounded as ContactsIcon} from '#/components/icons/Contacts' import {DotGrid_Stroke2_Corner0_Rounded as DotsHorizontal} from '#/components/icons/DotGrid' import {Earth_Stroke2_Corner2_Rounded as EarthIcon} from '#/components/icons/Globe' import {Lock_Stroke2_Corner2_Rounded as LockIcon} from '#/components/icons/Lock' @@ -207,6 +208,14 @@ export function SettingsScreen({}: Props) { Content and media + + + + Sync contacts + + diff --git a/src/screens/Settings/SyncContactsSettings.tsx b/src/screens/Settings/SyncContactsSettings.tsx new file mode 100644 index 0000000000..cb8cd8b418 --- /dev/null +++ b/src/screens/Settings/SyncContactsSettings.tsx @@ -0,0 +1,56 @@ +import {Trans} from '@lingui/macro' + +import { + type AllNavigatorParams, + type NativeStackScreenProps, +} from '#/lib/routes/types' +import {atoms as a, useTheme} from '#/alf' +import {Contacts_Stroke2_Corner2_Rounded as SyncContactsIcon} from '#/components/icons/Contacts' +import * as Layout from '#/components/Layout' +import {InlineLinkText} from '#/components/Link' +import {Text} from '#/components/Typography' +import * as SettingsList from './components/SettingsList' + +type Props = NativeStackScreenProps +export function SyncContactsSettingsScreen({}: Props) { + const t = useTheme() + + return ( + + + + + + Sync contacts + + + + + + + + + + Sync Contacts + + + + + + Contacts from your address book will be uploaded to Bluesky on + an ongoing basis to help connect you with your friends and + personalize content, such as making suggestions for you and + others. Turning off syncing will not remove previously uploaded + contacts.{' '} + + TODO: Add learn more link + + + + + + + + ) +}