fix social-app web icon
This commit is contained in:
@@ -81,8 +81,7 @@ index 231447b4f..a44b3da05 100644
|
||||
- 'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot'
|
||||
+ 'at://did:plc:6qyecktefllvenje24fcxnie/app.bsky.feed.generator/app'
|
||||
export const VIDEO_FEED_URI =
|
||||
- 'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/thevids'
|
||||
+ 'at://did:plc:6qyecktefllvenje24fcxnie/app.bsky.feed.generator/app'
|
||||
'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/thevids'
|
||||
export const STAGING_VIDEO_FEED_URI =
|
||||
'at://did:plc:yofh3kx63drvfljkibw5zuxo/app.bsky.feed.generator/thevids'
|
||||
export const VIDEO_FEED_URIS = [VIDEO_FEED_URI, STAGING_VIDEO_FEED_URI]
|
||||
@@ -147,7 +146,7 @@ diff --git a/src/state/queries/feed.ts b/src/state/queries/feed.ts
|
||||
index de1e92533..3d1566800 100644
|
||||
--- a/src/state/queries/feed.ts
|
||||
+++ b/src/state/queries/feed.ts
|
||||
@@ -201,14 +201,7 @@ export function useFeedSourceInfoQuery({uri}: {uri: string}) {
|
||||
@@ -201,14 +201,6 @@ export function useFeedSourceInfoQuery({uri}: {uri: string}) {
|
||||
// for the ones we know need it
|
||||
// -prf
|
||||
export const KNOWN_AUTHED_ONLY_FEEDS = [
|
||||
@@ -159,9 +158,8 @@ index de1e92533..3d1566800 100644
|
||||
- 'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/mutuals', // mutuals, by bluesky
|
||||
- 'at://did:plc:q6gjnaw2blty4crticxkmujt/app.bsky.feed.generator/my-followers', // followers, by jaz
|
||||
- 'at://did:plc:vpkhqolt662uhesyj6nxm7ys/app.bsky.feed.generator/followpics', // the gram, by why
|
||||
+ 'at://did:plc:6qyecktefllvenje24fcxnie/app.bsky.feed.generator/app', // app feed, by syu.is
|
||||
]
|
||||
|
||||
|
||||
type GetPopularFeedsOptions = {limit?: number; enabled?: boolean}
|
||||
diff --git a/src/state/queries/preferences/index.ts b/src/state/queries/preferences/index.ts
|
||||
index 0cf6ab546..399e592bc 100644
|
||||
@@ -216,3 +214,4 @@ index 620382175..928480da2 100644
|
||||
style={[a.text_md]}>
|
||||
Discover
|
||||
</InlineLinkText>{' '}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/src/screens/Settings/AboutSettings.tsx b/src/screens/Settings/AboutSettings.tsx
|
||||
index 6b8257b91..35202224b 100644
|
||||
index 6b8257b91..48ba7909e 100644
|
||||
--- a/src/screens/Settings/AboutSettings.tsx
|
||||
+++ b/src/screens/Settings/AboutSettings.tsx
|
||||
@@ -80,7 +80,7 @@ export function AboutSettingsScreen({}: Props) {
|
||||
@@ -21,26 +21,25 @@ index 6b8257b91..35202224b 100644
|
||||
<SettingsList.ItemIcon icon={NewspaperIcon} />
|
||||
<SettingsList.ItemText>
|
||||
diff --git a/src/screens/Takendown.tsx b/src/screens/Takendown.tsx
|
||||
index dd319a4c6..0e80f956a 100644
|
||||
index 77f219e55..53f5e0cc0 100644
|
||||
--- a/src/screens/Takendown.tsx
|
||||
+++ b/src/screens/Takendown.tsx
|
||||
@@ -223,11 +223,11 @@ export function Takendown() {
|
||||
@@ -217,10 +217,10 @@ export function Takendown() {
|
||||
<Trans>
|
||||
Your account was found to be in violation of the{' '}
|
||||
<InlineLinkText
|
||||
<SimpleInlineLinkText
|
||||
- label={_(msg`Bluesky Social Terms of Service`)}
|
||||
- to="https://bsky.social/about/support/tos"
|
||||
+ label={_(msg`syu.is Terms of Service`)}
|
||||
+ to="https://syu.is/about/support/tos"
|
||||
style={[a.text_md, a.leading_normal]}
|
||||
overridePresentation>
|
||||
style={[a.text_md, a.leading_normal]}>
|
||||
- Bluesky Social Terms of Service
|
||||
+ syu.is Terms of Service
|
||||
</InlineLinkText>
|
||||
</SimpleInlineLinkText>
|
||||
. You have been sent an email outlining the specific violation
|
||||
and suspension period, if applicable. You can appeal this
|
||||
diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx
|
||||
index e058e2883..0f583c915 100644
|
||||
index e058e2883..8daf41089 100644
|
||||
--- a/src/view/screens/Home.tsx
|
||||
+++ b/src/view/screens/Home.tsx
|
||||
@@ -1,23 +1,16 @@
|
||||
@@ -82,17 +81,42 @@ index e058e2883..0f583c915 100644
|
||||
import {CustomFeedEmptyState} from '#/view/com/posts/CustomFeedEmptyState'
|
||||
import {FollowingEmptyState} from '#/view/com/posts/FollowingEmptyState'
|
||||
import {FollowingEndOfFeed} from '#/view/com/posts/FollowingEndOfFeed'
|
||||
@@ -39,97 +28,60 @@ import {NoFeedsPinned} from '#/screens/Home/NoFeedsPinned'
|
||||
@@ -39,97 +28,90 @@ import {NoFeedsPinned} from '#/screens/Home/NoFeedsPinned'
|
||||
import * as Layout from '#/components/Layout'
|
||||
import {useDemoMode} from '#/storage/hooks/demo-mode'
|
||||
|
||||
+const DEFAULT_PINNED_FEEDS = [{
|
||||
+const SYU_IS_FEED_URI = 'at://did:plc:6qyecktefllvenje24fcxnie/app.bsky.feed.generator/app'
|
||||
+
|
||||
+const DEFAULT_PINNED_FEEDS: any[] = [{
|
||||
+ feedDescriptor: 'following',
|
||||
+ displayName: 'Following',
|
||||
+ id: 'following',
|
||||
+ uri: 'following',
|
||||
+ type: 'feed',
|
||||
+ savedFeed: undefined,
|
||||
+ pinned: true,
|
||||
+ route: { href: '/', name: 'Home', params: {} },
|
||||
+ cid: '',
|
||||
+ avatar: '',
|
||||
+ creatorDid: '',
|
||||
+ creatorHandle: '',
|
||||
+}, {
|
||||
+ feedDescriptor: `feedgen|${SYU_IS_FEED_URI}`,
|
||||
+ displayName: 'Feeds',
|
||||
+ id: SYU_IS_FEED_URI,
|
||||
+ uri: SYU_IS_FEED_URI,
|
||||
+ type: 'feed',
|
||||
+ savedFeed: {
|
||||
+ type: 'feed',
|
||||
+ value: SYU_IS_FEED_URI,
|
||||
+ pinned: true,
|
||||
+ },
|
||||
+ pinned: true,
|
||||
+ route: { href: '/', name: 'Home', params: {} },
|
||||
+ cid: '',
|
||||
+ avatar: '',
|
||||
+ creatorDid: '',
|
||||
+ creatorHandle: '',
|
||||
+}]
|
||||
+
|
||||
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home' | 'Start'>
|
||||
@@ -105,7 +129,12 @@ index e058e2883..0f583c915 100644
|
||||
+ const {data: pinnedFeedInfos} = usePinnedFeedsInfos()
|
||||
+
|
||||
+ const safePreferences = preferences || { feedViewPrefs: { lab_mergeFeedEnabled: false }, savedFeeds: [] } as any
|
||||
+ const safePinnedFeedInfos = pinnedFeedInfos || DEFAULT_PINNED_FEEDS
|
||||
+ // Use user's pinned feeds when logged in and available, otherwise use defaults
|
||||
+ const safePinnedFeedInfos = !currentAccount
|
||||
+ ? DEFAULT_PINNED_FEEDS.filter(f => f.feedDescriptor !== 'following')
|
||||
+ : (pinnedFeedInfos && pinnedFeedInfos.length > 0)
|
||||
+ ? pinnedFeedInfos
|
||||
+ : DEFAULT_PINNED_FEEDS
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isWeb && !currentAccount) {
|
||||
@@ -189,8 +218,7 @@ index e058e2883..0f583c915 100644
|
||||
- const maybeSelectedFeed: FeedDescriptor | undefined = allFeeds[selectedIndex]
|
||||
+ const maybeSelectedFeed = allFeeds[selectedIndex]
|
||||
const requestNotificationsPermission = useRequestNotificationsPermission()
|
||||
-
|
||||
+
|
||||
|
||||
useSetTitle(pinnedFeedInfos[selectedIndex]?.displayName)
|
||||
useOTAUpdates()
|
||||
-
|
||||
@@ -208,7 +236,7 @@ index e058e2883..0f583c915 100644
|
||||
if (selectedIndex !== lastPagerReportedIndexRef.current) {
|
||||
lastPagerReportedIndexRef.current = selectedIndex
|
||||
pagerRef.current?.setPage(selectedIndex)
|
||||
@@ -138,205 +90,43 @@ function HomeScreenReady({
|
||||
@@ -138,205 +120,43 @@ function HomeScreenReady({
|
||||
|
||||
const {hasSession} = useSession()
|
||||
const setMinimalShellMode = useSetMinimalShellMode()
|
||||
@@ -217,7 +245,8 @@ index e058e2883..0f583c915 100644
|
||||
- setMinimalShellMode(false)
|
||||
- }, [setMinimalShellMode]),
|
||||
- )
|
||||
-
|
||||
+ useFocusEffect(React.useCallback(() => { setMinimalShellMode(false) }, [setMinimalShellMode]))
|
||||
|
||||
- useFocusEffect(
|
||||
- useNonReactiveCallback(() => {
|
||||
- if (maybeSelectedFeed) {
|
||||
@@ -235,7 +264,13 @@ index e058e2883..0f583c915 100644
|
||||
- (index: number) => {
|
||||
- setMinimalShellMode(false)
|
||||
- const maybeFeed = allFeeds[index]
|
||||
-
|
||||
+ const onPageSelected = React.useCallback((index) => {
|
||||
+ setMinimalShellMode(false)
|
||||
+ const maybeFeed = allFeeds[index]
|
||||
+ lastPagerReportedIndexRef.current = index
|
||||
+ setSelectedFeed(maybeFeed)
|
||||
+ }, [setSelectedFeed, setMinimalShellMode, allFeeds])
|
||||
|
||||
- // Mutate the ref before setting state to avoid the imperative syncing effect
|
||||
- // above from starting a loop on Android when swiping back and forth.
|
||||
- lastPagerReportedIndexRef.current = index
|
||||
@@ -265,15 +300,6 @@ index e058e2883..0f583c915 100644
|
||||
- },
|
||||
- [setMinimalShellMode],
|
||||
- )
|
||||
+ useFocusEffect(React.useCallback(() => { setMinimalShellMode(false) }, [setMinimalShellMode]))
|
||||
+
|
||||
+ const onPageSelected = React.useCallback((index) => {
|
||||
+ setMinimalShellMode(false)
|
||||
+ const maybeFeed = allFeeds[index]
|
||||
+ lastPagerReportedIndexRef.current = index
|
||||
+ setSelectedFeed(maybeFeed)
|
||||
+ }, [setSelectedFeed, setMinimalShellMode, allFeeds])
|
||||
+
|
||||
+ const onPressSelected = React.useCallback(() => { emitSoftReset() }, [])
|
||||
+ const onPageScrollStateChanged = React.useCallback((state) => {
|
||||
+ 'worklet'
|
||||
@@ -281,7 +307,10 @@ index e058e2883..0f583c915 100644
|
||||
+ }, [setMinimalShellMode])
|
||||
|
||||
const [demoMode] = useDemoMode()
|
||||
-
|
||||
+ const renderTabBar = React.useCallback((props) => {
|
||||
+ return <HomeHeader key="FEEDS_TAB_BAR" {...props} testID="homeScreenFeedTabs" onPressSelected={onPressSelected} feeds={pinnedFeedInfos} />
|
||||
+ }, [onPressSelected, pinnedFeedInfos])
|
||||
|
||||
- const renderTabBar = React.useCallback(
|
||||
- (props: RenderTabBarFnProps) => {
|
||||
- if (demoMode) {
|
||||
@@ -312,11 +341,16 @@ index e058e2883..0f583c915 100644
|
||||
- const renderFollowingEmptyState = React.useCallback(() => {
|
||||
- return <FollowingEmptyState />
|
||||
- }, [])
|
||||
-
|
||||
+ const renderFollowingEmptyState = React.useCallback(() => <FollowingEmptyState />, [])
|
||||
+ const renderCustomFeedEmptyState = React.useCallback(() => <CustomFeedEmptyState />, [])
|
||||
|
||||
- const renderCustomFeedEmptyState = React.useCallback(() => {
|
||||
- return <CustomFeedEmptyState />
|
||||
- }, [])
|
||||
-
|
||||
+ const homeFeedParams = React.useMemo(() => ({
|
||||
+ mergeFeedEnabled: false, mergeFeedSources: []
|
||||
+ }), [preferences])
|
||||
|
||||
- const homeFeedParams = React.useMemo<FeedParams>(() => {
|
||||
- return {
|
||||
- mergeFeedEnabled: Boolean(preferences.feedViewPrefs.lab_mergeFeedEnabled),
|
||||
@@ -368,17 +402,6 @@ index e058e2883..0f583c915 100644
|
||||
- renderTabBar={renderTabBar}>
|
||||
- {pinnedFeedInfos.length ? (
|
||||
- pinnedFeedInfos.map((feedInfo, index) => {
|
||||
+ const renderTabBar = React.useCallback((props) => {
|
||||
+ return <HomeHeader key="FEEDS_TAB_BAR" {...props} testID="homeScreenFeedTabs" onPressSelected={onPressSelected} feeds={pinnedFeedInfos} />
|
||||
+ }, [onPressSelected, pinnedFeedInfos])
|
||||
+
|
||||
+ const renderFollowingEmptyState = React.useCallback(() => <FollowingEmptyState />, [])
|
||||
+ const renderCustomFeedEmptyState = React.useCallback(() => <CustomFeedEmptyState />, [])
|
||||
+
|
||||
+ const homeFeedParams = React.useMemo(() => ({
|
||||
+ mergeFeedEnabled: false, mergeFeedSources: []
|
||||
+ }), [preferences])
|
||||
+
|
||||
+ return (
|
||||
+ <Pager ref={pagerRef} testID="homeScreen" initialPage={selectedIndex} onPageSelected={onPageSelected} onPageScrollStateChanged={onPageScrollStateChanged} renderTabBar={renderTabBar}>
|
||||
+ {pinnedFeedInfos.map((feedInfo, index) => {
|
||||
@@ -447,7 +470,7 @@ index e058e2883..0f583c915 100644
|
||||
-})
|
||||
+const styles = StyleSheet.create({ loading: { height: '100%', alignContent: 'center', justifyContent: 'center', paddingBottom: 100 } })
|
||||
diff --git a/src/view/screens/PrivacyPolicy.tsx b/src/view/screens/PrivacyPolicy.tsx
|
||||
index a89eaadc4..228af4966 100644
|
||||
index a89eaadc4..1da393f03 100644
|
||||
--- a/src/view/screens/PrivacyPolicy.tsx
|
||||
+++ b/src/view/screens/PrivacyPolicy.tsx
|
||||
@@ -1,52 +1,13 @@
|
||||
@@ -509,7 +532,7 @@ index a89eaadc4..228af4966 100644
|
||||
)
|
||||
}
|
||||
diff --git a/src/view/screens/TermsOfService.tsx b/src/view/screens/TermsOfService.tsx
|
||||
index d843c713c..c0b34c886 100644
|
||||
index d843c713c..b81767bd5 100644
|
||||
--- a/src/view/screens/TermsOfService.tsx
|
||||
+++ b/src/view/screens/TermsOfService.tsx
|
||||
@@ -1,50 +1,13 @@
|
||||
|
||||
@@ -1,311 +1,8 @@
|
||||
diff --git a/src/components/dialogs/BirthDateSettings.tsx b/src/components/dialogs/BirthDateSettings.tsx
|
||||
index 9915d0a2d..4ae51215d 100644
|
||||
--- a/src/components/dialogs/BirthDateSettings.tsx
|
||||
+++ b/src/components/dialogs/BirthDateSettings.tsx
|
||||
@@ -163,7 +163,7 @@ function BirthdayInner({
|
||||
<Trans>
|
||||
You must be at least 13 years old to use Bluesky. Read our{' '}
|
||||
<SimpleInlineLinkText
|
||||
- to="https://bsky.social/about/support/tos"
|
||||
+ to="https://syu.is/about/support/tos"
|
||||
label={_(msg`Terms of Service`)}>
|
||||
Terms of Service
|
||||
</SimpleInlineLinkText>{' '}
|
||||
diff --git a/src/components/dialogs/ServerInput.tsx b/src/components/dialogs/ServerInput.tsx
|
||||
index d7c02bb9f..fda1dfe4a 100644
|
||||
--- a/src/components/dialogs/ServerInput.tsx
|
||||
+++ b/src/components/dialogs/ServerInput.tsx
|
||||
@@ -165,7 +165,7 @@ function DialogInner({
|
||||
<Trans>
|
||||
Bluesky is an open network where you can choose your own
|
||||
provider. If you're new here, we recommend sticking with the
|
||||
- default Bluesky Social option.
|
||||
+ default syu.is option.
|
||||
</Trans>
|
||||
</Admonition>
|
||||
</View>
|
||||
diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx
|
||||
index ed2a6cfb7..1dc7f9227 100644
|
||||
index f76147ccf..36b4d7de1 100644
|
||||
--- a/src/view/shell/Drawer.tsx
|
||||
+++ b/src/view/shell/Drawer.tsx
|
||||
@@ -1,60 +1,50 @@
|
||||
-import React, {type ComponentProps, type JSX} from 'react'
|
||||
-import {Linking, ScrollView, TouchableOpacity, View} from 'react-native'
|
||||
-import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
-import {msg, Plural, plural, Trans} from '@lingui/macro'
|
||||
-import {useLingui} from '@lingui/react'
|
||||
-import {StackActions, useNavigation} from '@react-navigation/native'
|
||||
-
|
||||
-import {useActorStatus} from '#/lib/actor-status'
|
||||
-import {FEEDBACK_FORM_URL, HELP_DESK_URL} from '#/lib/constants'
|
||||
-import {type PressableScale} from '#/lib/custom-animations/PressableScale'
|
||||
-import {useNavigationTabState} from '#/lib/hooks/useNavigationTabState'
|
||||
-import {getTabState, TabState} from '#/lib/routes/helpers'
|
||||
-import {type NavigationProp} from '#/lib/routes/types'
|
||||
-import {sanitizeHandle} from '#/lib/strings/handles'
|
||||
-import {colors} from '#/lib/styles'
|
||||
-import {isWeb} from '#/platform/detection'
|
||||
-import {emitSoftReset} from '#/state/events'
|
||||
-import {useKawaiiMode} from '#/state/preferences/kawaii'
|
||||
-import {useUnreadNotifications} from '#/state/queries/notifications/unread'
|
||||
-import {useProfileQuery} from '#/state/queries/profile'
|
||||
-import {type SessionAccount, useSession} from '#/state/session'
|
||||
-import {useSetDrawerOpen} from '#/state/shell'
|
||||
-import {formatCount} from '#/view/com/util/numeric/format'
|
||||
-import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||
-import {NavSignupCard} from '#/view/shell/NavSignupCard'
|
||||
-import {atoms as a, tokens, useTheme, web} from '#/alf'
|
||||
-import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
-import {Divider} from '#/components/Divider'
|
||||
+import React, { type ComponentProps, type JSX } from 'react'
|
||||
+import { Linking, ScrollView, TouchableOpacity, View } from 'react-native'
|
||||
+import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
+import { msg, Plural, plural, Trans } from '@lingui/macro'
|
||||
+import { useLingui } from '@lingui/react'
|
||||
+import { StackActions, useNavigation } from '@react-navigation/native'
|
||||
+
|
||||
+import { useActorStatus } from '#/lib/actor-status'
|
||||
+import { FEEDBACK_FORM_URL, HELP_DESK_URL } from '#/lib/constants'
|
||||
+import { type PressableScale } from '#/lib/custom-animations/PressableScale'
|
||||
+import { useNavigationTabState } from '#/lib/hooks/useNavigationTabState'
|
||||
+import { getTabState, TabState } from '#/lib/routes/helpers'
|
||||
+import { type NavigationProp } from '#/lib/routes/types'
|
||||
+import { sanitizeHandle } from '#/lib/strings/handles'
|
||||
+import { colors } from '#/lib/styles'
|
||||
+import { isWeb } from '#/platform/detection'
|
||||
+import { emitSoftReset } from '#/state/events'
|
||||
+import { useKawaiiMode } from '#/state/preferences/kawaii'
|
||||
+import { useUnreadNotifications } from '#/state/queries/notifications/unread'
|
||||
+import { useProfileQuery } from '#/state/queries/profile'
|
||||
+import { type SessionAccount, useSession } from '#/state/session'
|
||||
+import { useSetDrawerOpen } from '#/state/shell'
|
||||
+import { formatCount } from '#/view/com/util/numeric/format'
|
||||
+import { UserAvatar } from '#/view/com/util/UserAvatar'
|
||||
+import { NavSignupCard } from '#/view/shell/NavSignupCard'
|
||||
+import { atoms as a, tokens, useTheme, web } from '#/alf'
|
||||
+import { Button } from '#/components/Button'
|
||||
+import { Divider } from '#/components/Divider'
|
||||
import {
|
||||
Bell_Filled_Corner0_Rounded as BellFilled,
|
||||
Bell_Stroke2_Corner0_Rounded as Bell,
|
||||
} from '#/components/icons/Bell'
|
||||
-import {Bookmark, BookmarkFilled} from '#/components/icons/Bookmark'
|
||||
-import {BulletList_Stroke2_Corner0_Rounded as List} from '#/components/icons/BulletList'
|
||||
-import {
|
||||
- Hashtag_Filled_Corner0_Rounded as HashtagFilled,
|
||||
- Hashtag_Stroke2_Corner0_Rounded as Hashtag,
|
||||
-} from '#/components/icons/Hashtag'
|
||||
import {
|
||||
HomeOpen_Filled_Corner0_Rounded as HomeFilled,
|
||||
HomeOpen_Stoke2_Corner0_Rounded as Home,
|
||||
} from '#/components/icons/HomeOpen'
|
||||
-import {MagnifyingGlass_Filled_Stroke2_Corner0_Rounded as MagnifyingGlassFilled} from '#/components/icons/MagnifyingGlass'
|
||||
-import {MagnifyingGlass2_Stroke2_Corner0_Rounded as MagnifyingGlass} from '#/components/icons/MagnifyingGlass2'
|
||||
-import {
|
||||
- Message_Stroke2_Corner0_Rounded as Message,
|
||||
- Message_Stroke2_Corner0_Rounded_Filled as MessageFilled,
|
||||
-} from '#/components/icons/Message'
|
||||
-import {SettingsGear2_Stroke2_Corner0_Rounded as Settings} from '#/components/icons/SettingsGear2'
|
||||
+import { MagnifyingGlass_Filled_Stroke2_Corner0_Rounded as MagnifyingGlassFilled } from '#/components/icons/MagnifyingGlass'
|
||||
+import { MagnifyingGlass2_Stroke2_Corner0_Rounded as MagnifyingGlass } from '#/components/icons/MagnifyingGlass2'
|
||||
+import { SettingsGear2_Stroke2_Corner0_Rounded as Settings } from '#/components/icons/SettingsGear2'
|
||||
import {
|
||||
UserCircle_Filled_Corner0_Rounded as UserCircleFilled,
|
||||
UserCircle_Stroke2_Corner0_Rounded as UserCircle,
|
||||
} from '#/components/icons/UserCircle'
|
||||
-import {InlineLinkText} from '#/components/Link'
|
||||
-import {Text} from '#/components/Typography'
|
||||
-import {useSimpleVerificationState} from '#/components/verification'
|
||||
-import {VerificationCheck} from '#/components/verification/VerificationCheck'
|
||||
+import { InlineLinkText } from '#/components/Link'
|
||||
+import { Text } from '#/components/Typography'
|
||||
+import { useSimpleVerificationState } from '#/components/verification'
|
||||
+import { VerificationCheck } from '#/components/verification/VerificationCheck'
|
||||
|
||||
const iconWidth = 26
|
||||
|
||||
@@ -65,11 +55,11 @@ let DrawerProfileCard = ({
|
||||
account: SessionAccount
|
||||
onPressProfile: () => void
|
||||
}): React.ReactNode => {
|
||||
- const {_, i18n} = useLingui()
|
||||
+ const { _, i18n } = useLingui()
|
||||
const t = useTheme()
|
||||
- const {data: profile} = useProfileQuery({did: account.did})
|
||||
- const verification = useSimpleVerificationState({profile})
|
||||
- const {isActive: live} = useActorStatus(profile)
|
||||
+ const { data: profile } = useProfileQuery({ did: account.did })
|
||||
+ const verification = useSimpleVerificationState({ profile })
|
||||
+ const { isActive: live } = useActorStatus(profile)
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
@@ -81,7 +71,6 @@ let DrawerProfileCard = ({
|
||||
<UserAvatar
|
||||
size={52}
|
||||
avatar={profile?.avatar}
|
||||
- // See https://github.com/bluesky-social/social-app/pull/1801:
|
||||
usePlainRNImage={true}
|
||||
type={profile?.associated?.labeler ? 'labeler' : 'user'}
|
||||
live={live}
|
||||
@@ -140,9 +129,9 @@ let DrawerProfileCard = ({
|
||||
)
|
||||
}
|
||||
DrawerProfileCard = React.memo(DrawerProfileCard)
|
||||
-export {DrawerProfileCard}
|
||||
+export { DrawerProfileCard }
|
||||
|
||||
-let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
+let DrawerContent = ({ }: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
const t = useTheme()
|
||||
const insets = useSafeAreaInsets()
|
||||
const setDrawerOpen = useSetDrawerOpen()
|
||||
@@ -150,27 +139,20 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
const {
|
||||
isAtHome,
|
||||
isAtSearch,
|
||||
- isAtFeeds,
|
||||
- isAtBookmarks,
|
||||
isAtNotifications,
|
||||
isAtMyProfile,
|
||||
- isAtMessages,
|
||||
} = useNavigationTabState()
|
||||
- const {hasSession, currentAccount} = useSession()
|
||||
-
|
||||
- // events
|
||||
- // =
|
||||
+ const { hasSession, currentAccount } = useSession()
|
||||
|
||||
const onPressTab = React.useCallback(
|
||||
(tab: 'Home' | 'Search' | 'Messages' | 'Notifications' | 'MyProfile') => {
|
||||
const state = navigation.getState()
|
||||
setDrawerOpen(false)
|
||||
if (isWeb) {
|
||||
- // hack because we have flat navigator for web and MyProfile does not exist on the web navigator -ansh
|
||||
if (tab === 'MyProfile') {
|
||||
- navigation.navigate('Profile', {name: currentAccount!.handle})
|
||||
+ navigation.navigate('Profile', { name: currentAccount!.handle })
|
||||
} else {
|
||||
- // @ts-expect-error struggles with string unions, apparently
|
||||
+ // @ts-expect-error struggles with string unions
|
||||
navigation.navigate(tab)
|
||||
}
|
||||
} else {
|
||||
@@ -178,21 +160,11 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
if (tabState === TabState.InsideAtRoot) {
|
||||
emitSoftReset()
|
||||
} else if (tabState === TabState.Inside) {
|
||||
- // find the correct navigator in which to pop-to-top
|
||||
- const target = state.routes.find(route => route.name === `${tab}Tab`)
|
||||
- ?.state?.key
|
||||
+ const target = state.routes.find(route => route.name === `${tab}Tab`)?.state?.key
|
||||
if (target) {
|
||||
- // if we found it, trigger pop-to-top
|
||||
- navigation.dispatch({
|
||||
- ...StackActions.popToTop(),
|
||||
- target,
|
||||
- })
|
||||
+ navigation.dispatch({ ...StackActions.popToTop(), target })
|
||||
} else {
|
||||
- // fallback: reset navigation
|
||||
- navigation.reset({
|
||||
- index: 0,
|
||||
- routes: [{name: `${tab}Tab`}],
|
||||
- })
|
||||
+ navigation.reset({ index: 0, routes: [{ name: `${tab}Tab` }] })
|
||||
}
|
||||
} else {
|
||||
navigation.navigate(`${tab}Tab`)
|
||||
@@ -203,76 +175,21 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
)
|
||||
|
||||
const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab])
|
||||
-
|
||||
- const onPressSearch = React.useCallback(
|
||||
- () => onPressTab('Search'),
|
||||
- [onPressTab],
|
||||
- )
|
||||
-
|
||||
- const onPressMessages = React.useCallback(
|
||||
- () => onPressTab('Messages'),
|
||||
- [onPressTab],
|
||||
- )
|
||||
-
|
||||
- const onPressNotifications = React.useCallback(
|
||||
- () => onPressTab('Notifications'),
|
||||
- [onPressTab],
|
||||
- )
|
||||
-
|
||||
- const onPressProfile = React.useCallback(() => {
|
||||
- onPressTab('MyProfile')
|
||||
- }, [onPressTab])
|
||||
-
|
||||
- const onPressMyFeeds = React.useCallback(() => {
|
||||
- navigation.navigate('Feeds')
|
||||
- setDrawerOpen(false)
|
||||
- }, [navigation, setDrawerOpen])
|
||||
-
|
||||
- const onPressLists = React.useCallback(() => {
|
||||
- navigation.navigate('Lists')
|
||||
- setDrawerOpen(false)
|
||||
- }, [navigation, setDrawerOpen])
|
||||
-
|
||||
- const onPressBookmarks = React.useCallback(() => {
|
||||
- navigation.navigate('Bookmarks')
|
||||
- setDrawerOpen(false)
|
||||
- }, [navigation, setDrawerOpen])
|
||||
-
|
||||
+ const onPressSearch = React.useCallback(() => onPressTab('Search'), [onPressTab])
|
||||
+ const onPressNotifications = React.useCallback(() => onPressTab('Notifications'), [onPressTab])
|
||||
+ const onPressProfile = React.useCallback(() => { onPressTab('MyProfile') }, [onPressTab])
|
||||
const onPressSettings = React.useCallback(() => {
|
||||
navigation.navigate('Settings')
|
||||
setDrawerOpen(false)
|
||||
}, [navigation, setDrawerOpen])
|
||||
|
||||
- const onPressFeedback = React.useCallback(() => {
|
||||
- Linking.openURL(
|
||||
- FEEDBACK_FORM_URL({
|
||||
- email: currentAccount?.email,
|
||||
- handle: currentAccount?.handle,
|
||||
- }),
|
||||
- )
|
||||
- }, [currentAccount])
|
||||
-
|
||||
- const onPressHelp = React.useCallback(() => {
|
||||
- Linking.openURL(HELP_DESK_URL)
|
||||
- }, [])
|
||||
-
|
||||
- // rendering
|
||||
- // =
|
||||
-
|
||||
return (
|
||||
<View
|
||||
testID="drawer"
|
||||
style={[a.flex_1, a.border_r, t.atoms.bg, t.atoms.border_contrast_low]}>
|
||||
<ScrollView
|
||||
style={[a.flex_1]}
|
||||
- contentContainerStyle={[
|
||||
- {
|
||||
- paddingTop: Math.max(
|
||||
- insets.top + a.pt_xl.paddingTop,
|
||||
- a.pt_xl.paddingTop,
|
||||
- ),
|
||||
- },
|
||||
- ]}>
|
||||
+ contentContainerStyle={[{ paddingTop: Math.max(insets.top + a.pt_xl.paddingTop, a.pt_xl.paddingTop) }]}>
|
||||
<View style={[a.px_xl]}>
|
||||
{hasSession && currentAccount ? (
|
||||
<DrawerProfileCard
|
||||
@@ -284,7 +201,6 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
<NavSignupCard />
|
||||
</View>
|
||||
)}
|
||||
-
|
||||
<Divider style={[a.mt_xl, a.mb_sm]} />
|
||||
</View>
|
||||
|
||||
@@ -292,17 +208,10 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
@@ -292,17 +292,11 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
<>
|
||||
<SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} />
|
||||
<HomeMenuItem isActive={isAtHome} onPress={onPressHome} />
|
||||
@@ -314,7 +11,7 @@ index ed2a6cfb7..1dc7f9227 100644
|
||||
isActive={isAtNotifications}
|
||||
onPress={onPressNotifications}
|
||||
/>
|
||||
- <FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
|
||||
<FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
|
||||
- <ListsMenuItem onPress={onPressLists} />
|
||||
- <BookmarksMenuItem
|
||||
- isActive={isAtBookmarks}
|
||||
@@ -323,53 +20,10 @@ index ed2a6cfb7..1dc7f9227 100644
|
||||
<ProfileMenuItem
|
||||
isActive={isAtMyProfile}
|
||||
onPress={onPressProfile}
|
||||
@@ -312,7 +221,6 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
) : (
|
||||
<>
|
||||
<HomeMenuItem isActive={isAtHome} onPress={onPressHome} />
|
||||
- <FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
|
||||
<SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} />
|
||||
</>
|
||||
)}
|
||||
@@ -322,69 +230,11 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
<ExtraLinks />
|
||||
</View>
|
||||
</ScrollView>
|
||||
-
|
||||
- <DrawerFooter
|
||||
- onPressFeedback={onPressFeedback}
|
||||
- onPressHelp={onPressHelp}
|
||||
- />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
DrawerContent = React.memo(DrawerContent)
|
||||
-export {DrawerContent}
|
||||
-
|
||||
-let DrawerFooter = ({
|
||||
- onPressFeedback,
|
||||
- onPressHelp,
|
||||
-}: {
|
||||
- onPressFeedback: () => void
|
||||
- onPressHelp: () => void
|
||||
-}): React.ReactNode => {
|
||||
- const {_} = useLingui()
|
||||
- const insets = useSafeAreaInsets()
|
||||
- return (
|
||||
- <View
|
||||
- style={[
|
||||
- a.flex_row,
|
||||
- a.gap_sm,
|
||||
- a.flex_wrap,
|
||||
- a.pl_xl,
|
||||
- a.pt_md,
|
||||
- {
|
||||
- paddingBottom: Math.max(
|
||||
- insets.bottom + tokens.space.xs,
|
||||
- tokens.space.xl,
|
||||
- ),
|
||||
- },
|
||||
- ]}>
|
||||
@@ -357,17 +351,7 @@ let DrawerFooter = ({
|
||||
),
|
||||
},
|
||||
]}>
|
||||
- <Button
|
||||
- label={_(msg`Send feedback`)}
|
||||
- size="small"
|
||||
@@ -381,337 +35,22 @@ index ed2a6cfb7..1dc7f9227 100644
|
||||
- <Trans>Feedback</Trans>
|
||||
- </ButtonText>
|
||||
- </Button>
|
||||
- <Button
|
||||
- label={_(msg`Get help`)}
|
||||
- size="small"
|
||||
- variant="outline"
|
||||
- color="secondary"
|
||||
- onPress={onPressHelp}
|
||||
- style={{
|
||||
- backgroundColor: 'transparent',
|
||||
- }}>
|
||||
- <ButtonText>
|
||||
- <Trans>Help</Trans>
|
||||
- </ButtonText>
|
||||
- </Button>
|
||||
- </View>
|
||||
- )
|
||||
-}
|
||||
-DrawerFooter = React.memo(DrawerFooter)
|
||||
+export { DrawerContent }
|
||||
|
||||
interface MenuItemProps extends ComponentProps<typeof PressableScale> {
|
||||
icon: JSX.Element
|
||||
@@ -400,7 +250,7 @@ let SearchMenuItem = ({
|
||||
isActive: boolean
|
||||
onPress: () => void
|
||||
}): React.ReactNode => {
|
||||
- const {_} = useLingui()
|
||||
+ const { _ } = useLingui()
|
||||
const t = useTheme()
|
||||
return (
|
||||
<MenuItem
|
||||
@@ -426,7 +276,7 @@ let HomeMenuItem = ({
|
||||
isActive: boolean
|
||||
onPress: () => void
|
||||
}): React.ReactNode => {
|
||||
- const {_} = useLingui()
|
||||
+ const { _ } = useLingui()
|
||||
const t = useTheme()
|
||||
return (
|
||||
<MenuItem
|
||||
@@ -445,32 +295,6 @@ let HomeMenuItem = ({
|
||||
}
|
||||
HomeMenuItem = React.memo(HomeMenuItem)
|
||||
|
||||
-let ChatMenuItem = ({
|
||||
- isActive,
|
||||
- onPress,
|
||||
-}: {
|
||||
- isActive: boolean
|
||||
- onPress: () => void
|
||||
-}): React.ReactNode => {
|
||||
- const {_} = useLingui()
|
||||
- const t = useTheme()
|
||||
- return (
|
||||
- <MenuItem
|
||||
- icon={
|
||||
- isActive ? (
|
||||
- <MessageFilled style={[t.atoms.text]} width={iconWidth} />
|
||||
- ) : (
|
||||
- <Message style={[t.atoms.text]} width={iconWidth} />
|
||||
- )
|
||||
- }
|
||||
- label={_(msg`Chat`)}
|
||||
- bold={isActive}
|
||||
- onPress={onPress}
|
||||
- />
|
||||
- )
|
||||
-}
|
||||
-ChatMenuItem = React.memo(ChatMenuItem)
|
||||
-
|
||||
let NotificationsMenuItem = ({
|
||||
isActive,
|
||||
onPress,
|
||||
@@ -478,7 +302,7 @@ let NotificationsMenuItem = ({
|
||||
isActive: boolean
|
||||
onPress: () => void
|
||||
}): React.ReactNode => {
|
||||
- const {_} = useLingui()
|
||||
+ const { _ } = useLingui()
|
||||
const t = useTheme()
|
||||
const numUnreadNotifications = useUnreadNotifications()
|
||||
return (
|
||||
@@ -495,11 +319,11 @@ let NotificationsMenuItem = ({
|
||||
numUnreadNotifications === ''
|
||||
? ''
|
||||
: _(
|
||||
- msg`${plural(numUnreadNotifications ?? 0, {
|
||||
- one: '# unread item',
|
||||
- other: '# unread items',
|
||||
- })}` || '',
|
||||
- )
|
||||
+ msg`${plural(numUnreadNotifications ?? 0, {
|
||||
+ one: '# unread item',
|
||||
+ other: '# unread items',
|
||||
+ })}` || '',
|
||||
+ )
|
||||
}
|
||||
count={numUnreadNotifications}
|
||||
bold={isActive}
|
||||
@@ -509,72 +333,6 @@ let NotificationsMenuItem = ({
|
||||
}
|
||||
NotificationsMenuItem = React.memo(NotificationsMenuItem)
|
||||
|
||||
-let FeedsMenuItem = ({
|
||||
- isActive,
|
||||
- onPress,
|
||||
-}: {
|
||||
- isActive: boolean
|
||||
- onPress: () => void
|
||||
-}): React.ReactNode => {
|
||||
- const {_} = useLingui()
|
||||
- const t = useTheme()
|
||||
- return (
|
||||
- <MenuItem
|
||||
- icon={
|
||||
- isActive ? (
|
||||
- <HashtagFilled width={iconWidth} style={[t.atoms.text]} />
|
||||
- ) : (
|
||||
- <Hashtag width={iconWidth} style={[t.atoms.text]} />
|
||||
- )
|
||||
- }
|
||||
- label={_(msg`Feeds`)}
|
||||
- bold={isActive}
|
||||
- onPress={onPress}
|
||||
- />
|
||||
- )
|
||||
-}
|
||||
-FeedsMenuItem = React.memo(FeedsMenuItem)
|
||||
-
|
||||
-let ListsMenuItem = ({onPress}: {onPress: () => void}): React.ReactNode => {
|
||||
- const {_} = useLingui()
|
||||
- const t = useTheme()
|
||||
-
|
||||
- return (
|
||||
- <MenuItem
|
||||
- icon={<List style={[t.atoms.text]} width={iconWidth} />}
|
||||
- label={_(msg`Lists`)}
|
||||
- onPress={onPress}
|
||||
- />
|
||||
- )
|
||||
-}
|
||||
-ListsMenuItem = React.memo(ListsMenuItem)
|
||||
-
|
||||
-let BookmarksMenuItem = ({
|
||||
- isActive,
|
||||
- onPress,
|
||||
-}: {
|
||||
- isActive: boolean
|
||||
- onPress: () => void
|
||||
-}): React.ReactNode => {
|
||||
- const {_} = useLingui()
|
||||
- const t = useTheme()
|
||||
-
|
||||
- return (
|
||||
- <MenuItem
|
||||
- icon={
|
||||
- isActive ? (
|
||||
- <BookmarkFilled style={[t.atoms.text]} width={iconWidth} />
|
||||
- ) : (
|
||||
- <Bookmark style={[t.atoms.text]} width={iconWidth} />
|
||||
- )
|
||||
- }
|
||||
- label={_(msg({message: 'Saved', context: 'link to bookmarks screen'}))}
|
||||
- onPress={onPress}
|
||||
- />
|
||||
- )
|
||||
-}
|
||||
-BookmarksMenuItem = React.memo(BookmarksMenuItem)
|
||||
-
|
||||
let ProfileMenuItem = ({
|
||||
isActive,
|
||||
onPress,
|
||||
@@ -582,7 +340,7 @@ let ProfileMenuItem = ({
|
||||
isActive: boolean
|
||||
onPress: () => void
|
||||
}): React.ReactNode => {
|
||||
- const {_} = useLingui()
|
||||
+ const { _ } = useLingui()
|
||||
const t = useTheme()
|
||||
return (
|
||||
<MenuItem
|
||||
@@ -600,8 +358,8 @@ let ProfileMenuItem = ({
|
||||
}
|
||||
ProfileMenuItem = React.memo(ProfileMenuItem)
|
||||
|
||||
-let SettingsMenuItem = ({onPress}: {onPress: () => void}): React.ReactNode => {
|
||||
- const {_} = useLingui()
|
||||
+let SettingsMenuItem = ({ onPress }: { onPress: () => void }): React.ReactNode => {
|
||||
+ const { _ } = useLingui()
|
||||
const t = useTheme()
|
||||
return (
|
||||
<MenuItem
|
||||
@@ -613,7 +371,7 @@ let SettingsMenuItem = ({onPress}: {onPress: () => void}): React.ReactNode => {
|
||||
}
|
||||
SettingsMenuItem = React.memo(SettingsMenuItem)
|
||||
|
||||
-function MenuItem({icon, label, count, bold, onPress}: MenuItemProps) {
|
||||
+function MenuItem({ icon, label, count, bold, onPress }: MenuItemProps) {
|
||||
const t = useTheme()
|
||||
return (
|
||||
<Button
|
||||
@@ -621,7 +379,7 @@ function MenuItem({icon, label, count, bold, onPress}: MenuItemProps) {
|
||||
onPress={onPress}
|
||||
accessibilityRole="tab"
|
||||
label={label}>
|
||||
- {({hovered, pressed}) => (
|
||||
+ {({ hovered, pressed }) => (
|
||||
<View
|
||||
style={[
|
||||
a.flex_1,
|
||||
@@ -640,7 +398,7 @@ function MenuItem({icon, label, count, bold, onPress}: MenuItemProps) {
|
||||
a.absolute,
|
||||
a.inset_0,
|
||||
a.align_end,
|
||||
- {top: -4, right: a.gap_sm.gap * -1},
|
||||
+ { top: -4, right: a.gap_sm.gap * -1 },
|
||||
]}>
|
||||
<View
|
||||
style={[
|
||||
@@ -686,37 +444,26 @@ function MenuItem({icon, label, count, bold, onPress}: MenuItemProps) {
|
||||
}
|
||||
|
||||
function ExtraLinks() {
|
||||
- const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
- const kawaii = useKawaiiMode()
|
||||
+ const navigation = useNavigation<NavigationProp>()
|
||||
|
||||
return (
|
||||
<View style={[a.flex_col, a.gap_md, a.flex_wrap]}>
|
||||
- <InlineLinkText
|
||||
- style={[a.text_md]}
|
||||
- label={_(msg`Terms of Service`)}
|
||||
+{/* Feedback button removed for syu.is */}
|
||||
<Button
|
||||
label={_(msg`Get help`)}
|
||||
size="small"
|
||||
@@ -695,12 +679,12 @@ function ExtraLinks() {
|
||||
<InlineLinkText
|
||||
style={[a.text_md]}
|
||||
label={_(msg`Terms of Service`)}
|
||||
- to="https://bsky.social/about/support/tos">
|
||||
- <Trans>Terms of Service</Trans>
|
||||
- </InlineLinkText>
|
||||
- <InlineLinkText
|
||||
- style={[a.text_md]}
|
||||
+ to="https://syu.is/about/support/tos">
|
||||
<Trans>Terms of Service</Trans>
|
||||
</InlineLinkText>
|
||||
<InlineLinkText
|
||||
style={[a.text_md]}
|
||||
- to="https://bsky.social/about/support/privacy-policy"
|
||||
- label={_(msg`Privacy Policy`)}>
|
||||
- <Trans>Privacy Policy</Trans>
|
||||
- </InlineLinkText>
|
||||
- {kawaii && (
|
||||
- <Text style={t.atoms.text_contrast_medium}>
|
||||
- <Trans>
|
||||
- Logo by{' '}
|
||||
- <InlineLinkText
|
||||
- style={[a.text_md]}
|
||||
- to="/profile/sawaratsuki.bsky.social"
|
||||
- label="@sawaratsuki.bsky.social">
|
||||
- @sawaratsuki.bsky.social
|
||||
- </InlineLinkText>
|
||||
- </Trans>
|
||||
+ <TouchableOpacity onPress={() => Linking.openURL('https://syu.is/about/support/tos')}>
|
||||
+ <Text style={[a.text_md, t.atoms.text_contrast_medium]}>
|
||||
+ Terms of Service
|
||||
</Text>
|
||||
- )}
|
||||
+ </TouchableOpacity>
|
||||
+ <TouchableOpacity onPress={() => Linking.openURL('https://syu.is/about/support/privacy-policy')}>
|
||||
+ <Text style={[a.text_md, t.atoms.text_contrast_medium]}>
|
||||
+ Privacy Policy
|
||||
+ </Text>
|
||||
+ </TouchableOpacity>
|
||||
+ <TouchableOpacity onPress={() => navigation.navigate('License')}>
|
||||
+ <Text style={[a.text_md, t.atoms.text_contrast_medium]}>
|
||||
+ License
|
||||
+ </Text>
|
||||
+ </TouchableOpacity>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
diff --git a/src/view/shell/bottom-bar/BottomBar.tsx b/src/view/shell/bottom-bar/BottomBar.tsx
|
||||
index 779ebda68..bfd9b70fa 100644
|
||||
--- a/src/view/shell/bottom-bar/BottomBar.tsx
|
||||
+++ b/src/view/shell/bottom-bar/BottomBar.tsx
|
||||
@@ -198,38 +198,6 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
||||
accessibilityLabel={_(msg`Search`)}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
- <Btn
|
||||
- testID="bottomBarMessagesBtn"
|
||||
- icon={
|
||||
- isAtMessages ? (
|
||||
- <MessageFilled
|
||||
- width={iconWidth - 1}
|
||||
- style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
|
||||
- />
|
||||
- ) : (
|
||||
- <Message
|
||||
- width={iconWidth - 1}
|
||||
- style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
|
||||
- />
|
||||
- )
|
||||
- }
|
||||
- onPress={onPressMessages}
|
||||
- notificationCount={numUnreadMessages.numUnread}
|
||||
- hasNew={numUnreadMessages.hasNew}
|
||||
- accessible={true}
|
||||
- accessibilityRole="tab"
|
||||
- accessibilityLabel={_(msg`Chat`)}
|
||||
- accessibilityHint={
|
||||
- numUnreadMessages.count > 0
|
||||
- ? _(
|
||||
- msg`${plural(numUnreadMessages.numUnread ?? 0, {
|
||||
- one: '# unread item',
|
||||
- other: '# unread items',
|
||||
- })}` || '',
|
||||
- )
|
||||
- : ''
|
||||
- }
|
||||
- />
|
||||
<Btn
|
||||
testID="bottomBarNotificationsBtn"
|
||||
icon={
|
||||
diff --git a/src/view/shell/desktop/RightNav.tsx b/src/view/shell/desktop/RightNav.tsx
|
||||
index 1d097fc9a..1ad7026a2 100644
|
||||
--- a/src/view/shell/desktop/RightNav.tsx
|
||||
+++ b/src/view/shell/desktop/RightNav.tsx
|
||||
@@ -109,13 +109,13 @@ export function DesktopRightNav({routeName}: {routeName: string}) {
|
||||
</>
|
||||
)}
|
||||
<InlineLinkText
|
||||
- to="https://bsky.social/about/support/privacy-policy"
|
||||
+ to="https://syu.is/about/support/privacy-policy"
|
||||
label={_(msg`Privacy`)}>
|
||||
{_(msg`Privacy`)}
|
||||
</InlineLinkText>
|
||||
{' • '}
|
||||
<InlineLinkText
|
||||
- to="https://bsky.social/about/support/tos"
|
||||
+ to="https://syu.is/about/support/tos"
|
||||
label={_(msg`Terms`)}>
|
||||
{_(msg`Terms`)}
|
||||
</InlineLinkText>
|
||||
+ to="https://syu.is/about/support/privacy-policy"
|
||||
label={_(msg`Privacy Policy`)}>
|
||||
<Trans>Privacy Policy</Trans>
|
||||
</InlineLinkText>
|
||||
|
||||
@@ -4,119 +4,13 @@ index 6a00cfd23..f91decc08 100644
|
||||
+++ b/plugins/notificationsExtension/withNotificationsExtension.js
|
||||
@@ -10,7 +10,7 @@ const EXTENSION_NAME = 'BlueskyNSE'
|
||||
const EXTENSION_CONTROLLER_NAME = 'NotificationService'
|
||||
|
||||
|
||||
const withNotificationsExtension = config => {
|
||||
- const soundFiles = ['dm.aiff']
|
||||
+ const soundFiles = []
|
||||
|
||||
|
||||
return withPlugins(config, [
|
||||
// IOS
|
||||
diff --git a/src/ageAssurance/util.ts b/src/ageAssurance/util.ts
|
||||
index 104328330..c992a21de 100644
|
||||
--- a/src/ageAssurance/util.ts
|
||||
+++ b/src/ageAssurance/util.ts
|
||||
@@ -2,87 +2,32 @@ import {useMemo} from 'react'
|
||||
import {
|
||||
ageAssuranceRuleIDs as ids,
|
||||
type AppBskyAgeassuranceDefs,
|
||||
- getAgeAssuranceRegionConfig,
|
||||
} from '@atproto/api'
|
||||
-
|
||||
-import {getAge} from '#/lib/strings/time'
|
||||
-import {useAgeAssuranceDataContext} from '#/ageAssurance/data'
|
||||
import {AgeAssuranceAccess} from '#/ageAssurance/types'
|
||||
import {type Geolocation, useGeolocation} from '#/geolocation'
|
||||
+import {useAgeAssuranceDataContext} from '#/ageAssurance/data'
|
||||
|
||||
-const DEFAULT_MIN_AGE = 13
|
||||
-
|
||||
-/**
|
||||
- * Get age assurance region config based on geolocation, with fallback to
|
||||
- * app defaults if no region config is found.
|
||||
- *
|
||||
- * See {@link getAgeAssuranceRegionConfig} for the generic option, which can
|
||||
- * return undefined if the geolocation does not match any AA region.
|
||||
- */
|
||||
export function getAgeAssuranceRegionConfigWithFallback(
|
||||
config: AppBskyAgeassuranceDefs.Config,
|
||||
geolocation: Geolocation,
|
||||
): AppBskyAgeassuranceDefs.ConfigRegion {
|
||||
- const region = getAgeAssuranceRegionConfig(config, {
|
||||
- countryCode: geolocation.countryCode ?? '',
|
||||
- regionCode: geolocation.regionCode,
|
||||
- })
|
||||
-
|
||||
- return (
|
||||
- region || {
|
||||
- countryCode: '*',
|
||||
- regionCode: undefined,
|
||||
- rules: [
|
||||
- {
|
||||
- $type: ids.IfDeclaredOverAge,
|
||||
- age: DEFAULT_MIN_AGE,
|
||||
- access: AgeAssuranceAccess.Full,
|
||||
- },
|
||||
- {
|
||||
- $type: ids.Default,
|
||||
- access: AgeAssuranceAccess.None,
|
||||
- },
|
||||
- ],
|
||||
- }
|
||||
- )
|
||||
+ return {
|
||||
+ countryCode: '*',
|
||||
+ regionCode: undefined,
|
||||
+ rules: [{ $type: ids.Default, access: AgeAssuranceAccess.Full }],
|
||||
+ }
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Hook to get the age assurance region config based on current geolocation.
|
||||
- * Does not fall-back to our app defaults. If no config is found, returns
|
||||
- * undefined, which indicates no regional age assurance rules apply.
|
||||
- */
|
||||
export function useAgeAssuranceRegionConfig() {
|
||||
const geolocation = useGeolocation()
|
||||
const {config} = useAgeAssuranceDataContext()
|
||||
- return useMemo(() => {
|
||||
- if (!config) return
|
||||
- // use generic helper, we want to potentially return undefined
|
||||
- return getAgeAssuranceRegionConfig(config, {
|
||||
- countryCode: geolocation.countryCode ?? '',
|
||||
- regionCode: geolocation.regionCode,
|
||||
- })
|
||||
- }, [config, geolocation])
|
||||
+ return useMemo(() => ({
|
||||
+ countryCode: '*',
|
||||
+ regionCode: undefined,
|
||||
+ rules: [{ $type: ids.Default, access: AgeAssuranceAccess.Full }],
|
||||
+ }), [config, geolocation])
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Some users may have erroneously set their birth date to the current date
|
||||
- * if one wasn't set on their account. We previously didn't do validation on
|
||||
- * the bday dialog, and it defaulted to the current date. This bug _has_ been
|
||||
- * seen in production, so we need to check for it where possible.
|
||||
- */
|
||||
-export function isLegacyBirthdateBug(birthDate: string) {
|
||||
- return ['2025', '2024', '2023'].includes((birthDate || '').slice(0, 4))
|
||||
-}
|
||||
-
|
||||
-/**
|
||||
- * Returns whether the user is under the minimum age required to use the app.
|
||||
- * This applies to all regions.
|
||||
- */
|
||||
-export function isUserUnderMinimumAge(birthDate: string) {
|
||||
- return getAge(new Date(birthDate)) < DEFAULT_MIN_AGE
|
||||
-}
|
||||
-
|
||||
-export function isUserUnderAdultAge(birthDate: string) {
|
||||
- return getAge(new Date(birthDate)) < 18
|
||||
-}
|
||||
+export function isLegacyBirthdateBug(birthDate: string) { return false }
|
||||
+export function isUserUnderMinimumAge(birthDate: string) { return false }
|
||||
+export function isUserUnderAdultAge(birthDate: string) { return false }
|
||||
diff --git a/src/components/PolicyUpdateOverlay/updates/202508/index.tsx b/src/components/PolicyUpdateOverlay/updates/202508/index.tsx
|
||||
index 8365057e8..59c8506a2 100644
|
||||
--- a/src/components/PolicyUpdateOverlay/updates/202508/index.tsx
|
||||
|
||||
@@ -1,8 +1,35 @@
|
||||
diff --git a/src/screens/Settings/Settings.tsx b/src/screens/Settings/Settings.tsx
|
||||
index 1703036b5..42baa462c 100644
|
||||
index 6b0e184c0..42b609c9e 100644
|
||||
--- a/src/screens/Settings/Settings.tsx
|
||||
+++ b/src/screens/Settings/Settings.tsx
|
||||
@@ -231,16 +231,6 @@ export function SettingsScreen({}: Props) {
|
||||
@@ -203,24 +203,8 @@ export function SettingsScreen({}: Props) {
|
||||
<Trans>Notifications</Trans>
|
||||
</SettingsList.ItemText>
|
||||
</SettingsList.LinkItem>
|
||||
- <SettingsList.LinkItem
|
||||
- to="/settings/content-and-media"
|
||||
- label={_(msg`Content and media`)}>
|
||||
- <SettingsList.ItemIcon icon={WindowIcon} />
|
||||
- <SettingsList.ItemText>
|
||||
- <Trans>Content and media</Trans>
|
||||
- </SettingsList.ItemText>
|
||||
- </SettingsList.LinkItem>
|
||||
- {isNative && findContactsEnabled && (
|
||||
- <SettingsList.LinkItem
|
||||
- to="/settings/find-contacts"
|
||||
- label={_(msg`Find friends from contacts`)}>
|
||||
- <SettingsList.ItemIcon icon={ContactsIcon} />
|
||||
- <SettingsList.ItemText>
|
||||
- <Trans>Find friends from contacts</Trans>
|
||||
- </SettingsList.ItemText>
|
||||
- </SettingsList.LinkItem>
|
||||
- )}
|
||||
+{/* Content and media removed for syu.is */}
|
||||
+{/* Find friends from contacts removed for syu.is */}
|
||||
<SettingsList.LinkItem
|
||||
to="/settings/appearance"
|
||||
label={_(msg`Appearance`)}>
|
||||
@@ -245,16 +229,6 @@ export function SettingsScreen({}: Props) {
|
||||
<Trans>Languages</Trans>
|
||||
</SettingsList.ItemText>
|
||||
</SettingsList.LinkItem>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go
|
||||
index ec5261dee..c670cf75a 100644
|
||||
index 790f211ee..ec05a8bcd 100644
|
||||
--- a/bskyweb/cmd/bskyweb/server.go
|
||||
+++ b/bskyweb/cmd/bskyweb/server.go
|
||||
@@ -302,6 +302,12 @@ func serve(cctx *cli.Context) error {
|
||||
@@ -317,6 +317,12 @@ func serve(cctx *cli.Context) error {
|
||||
e.GET("/support/tos", server.WebGeneric)
|
||||
e.GET("/support/community-guidelines", server.WebGeneric)
|
||||
e.GET("/support/copyright", server.WebGeneric)
|
||||
@@ -15,9 +15,9 @@ index ec5261dee..c670cf75a 100644
|
||||
e.GET("/intent/compose", server.WebGeneric)
|
||||
e.GET("/intent/verify-email", server.WebGeneric)
|
||||
e.GET("/intent/age-assurance", server.WebGeneric)
|
||||
@@ -755,3 +761,33 @@ func (srv *Server) WebIpCC(c echo.Context) error {
|
||||
}
|
||||
return c.JSON(200, outResponse)
|
||||
@@ -825,3 +831,33 @@ func (srv *Server) serveSitemapRequest(c echo.Context, url, sitemapType string)
|
||||
|
||||
return nil
|
||||
}
|
||||
+
|
||||
+// Handler for About TOS page (syu.is specific)
|
||||
@@ -49,510 +49,3 @@ index ec5261dee..c670cf75a 100644
|
||||
+ data := srv.NewTemplateContext()
|
||||
+ return c.Render(http.StatusOK, "about-app.html", data)
|
||||
+}
|
||||
diff --git a/bskyweb/templates/about-app.html b/bskyweb/templates/about-app.html
|
||||
new file mode 100644
|
||||
index 000000000..000000002
|
||||
--- /dev/null
|
||||
+++ b/bskyweb/templates/about-app.html
|
||||
@@ -0,0 +1,135 @@
|
||||
+<!DOCTYPE html>
|
||||
+<html lang="ja">
|
||||
+<head>
|
||||
+ <meta charset="UTF-8">
|
||||
+ <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
+ <title>App Info - Aiat</title>
|
||||
+ <link rel="icon" type="image/png" href="{{ staticCDNHost }}/static/favicon.png">
|
||||
+ <style>
|
||||
+ * { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
+ body {
|
||||
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
||||
+ line-height: 1.6;
|
||||
+ color: #1a1a1a;
|
||||
+ background: #fff;
|
||||
+ padding: 20px;
|
||||
+ max-width: 800px;
|
||||
+ margin: 0 auto;
|
||||
+ }
|
||||
+ @media (prefers-color-scheme: dark) {
|
||||
+ body { background: #000; color: #e0e0e0; }
|
||||
+ a { color: #6bb3ff; }
|
||||
+ h1, h2, h3 { color: #fff; }
|
||||
+ .section { background: #1a1a1a; }
|
||||
+ .info-item { background: #2a2a2a; }
|
||||
+ }
|
||||
+ .header { margin-bottom: 32px; }
|
||||
+ .back-link { display: inline-block; margin-bottom: 16px; font-size: 14px; color: #0066cc; text-decoration: none; }
|
||||
+ .back-link:hover { text-decoration: underline; }
|
||||
+ .app-header { text-align: center; margin-bottom: 32px; }
|
||||
+ .app-icon { width: 80px; height: 80px; border-radius: 18px; margin-bottom: 12px; }
|
||||
+ .app-name { font-size: 24px; font-weight: bold; margin-bottom: 4px; }
|
||||
+ .app-version { font-size: 14px; color: #666; }
|
||||
+ .section { background: #f5f5f5; border-radius: 16px; padding: 20px; margin-bottom: 16px; }
|
||||
+ .section-title { font-size: 13px; font-weight: 600; color: #999; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 12px; }
|
||||
+ .description { font-size: 15px; line-height: 22px; }
|
||||
+ .info-grid { display: flex; flex-wrap: wrap; gap: 8px; }
|
||||
+ .info-item { flex: 1; min-width: 45%; text-align: center; background: #e8e8e8; border-radius: 12px; padding: 12px; }
|
||||
+ .info-label { font-size: 11px; color: #999; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }
|
||||
+ .info-value { font-size: 16px; font-weight: 600; }
|
||||
+ .developer-name { font-size: 18px; font-weight: 600; margin-bottom: 12px; }
|
||||
+ .link-row { display: flex; align-items: center; padding: 12px 0; border-top: 1px solid rgba(0,0,0,0.1); }
|
||||
+ .link-icon { font-size: 14px; font-weight: 600; color: #666; width: 70px; }
|
||||
+ .link-value { flex: 1; font-size: 14px; color: #0084ff; text-decoration: none; }
|
||||
+ .link-value:hover { text-decoration: underline; }
|
||||
+ .link-arrow { font-size: 16px; color: #ccc; }
|
||||
+ .bitcoin-row { display: flex; align-items: center; background: rgba(247, 147, 26, 0.08); border-radius: 12px; padding: 14px; gap: 10px; }
|
||||
+ .bitcoin-label { font-size: 18px; font-weight: 600; color: #f7931a; }
|
||||
+ .bitcoin-address { flex: 1; font-size: 11px; font-family: monospace; color: #666; word-break: break-all; }
|
||||
+ .copy-btn { font-size: 12px; color: #999; cursor: pointer; min-width: 50px; text-align: right; }
|
||||
+ .copy-btn:hover { color: #0084ff; }
|
||||
+ .footer { text-align: center; margin-top: 32px; padding-top: 20px; border-top: 1px solid #ddd; }
|
||||
+ .copyright { font-size: 12px; color: #999; }
|
||||
+ </style>
|
||||
+</head>
|
||||
+<body>
|
||||
+ <div class="header">
|
||||
+ <a href="/" class="back-link">← Back to syu.is</a>
|
||||
+ </div>
|
||||
+
|
||||
+ <div class="app-header">
|
||||
+ <img src="{{ staticCDNHost }}/static/favicon.png" alt="Aiat" class="app-icon">
|
||||
+ <div class="app-name">Aiat</div>
|
||||
+ <div class="app-version">v1.111.0</div>
|
||||
+ </div>
|
||||
+
|
||||
+ <div class="section">
|
||||
+ <p class="description">Aiat is a social networking application based on AT Protocol. Connect with your community on syu.is.</p>
|
||||
+ </div>
|
||||
+
|
||||
+ <div class="section">
|
||||
+ <div class="section-title">App Information</div>
|
||||
+ <div class="info-grid">
|
||||
+ <div class="info-item">
|
||||
+ <div class="info-label">Version</div>
|
||||
+ <div class="info-value">1.111.0</div>
|
||||
+ </div>
|
||||
+ <div class="info-item">
|
||||
+ <div class="info-label">Category</div>
|
||||
+ <div class="info-value">Social</div>
|
||||
+ </div>
|
||||
+ <div class="info-item">
|
||||
+ <div class="info-label">Supported OS</div>
|
||||
+ <div class="info-value">iOS 26.0+</div>
|
||||
+ </div>
|
||||
+ <div class="info-item">
|
||||
+ <div class="info-label">Price</div>
|
||||
+ <div class="info-value">Free</div>
|
||||
+ </div>
|
||||
+ </div>
|
||||
+ </div>
|
||||
+
|
||||
+ <div class="section">
|
||||
+ <div class="section-title">Developer</div>
|
||||
+ <div class="developer-name">syui</div>
|
||||
+ <div class="link-row">
|
||||
+ <span class="link-icon">GitHub</span>
|
||||
+ <a href="https://github.com/syui" class="link-value" target="_blank">github.com/syui</a>
|
||||
+ <span class="link-arrow">→</span>
|
||||
+ </div>
|
||||
+ <div class="link-row">
|
||||
+ <span class="link-icon">ATProto</span>
|
||||
+ <a href="https://syu.is/syui" class="link-value" target="_blank">syu.is/syui</a>
|
||||
+ <span class="link-arrow">→</span>
|
||||
+ </div>
|
||||
+ </div>
|
||||
+
|
||||
+ <div class="section">
|
||||
+ <div class="section-title">Bitcoin</div>
|
||||
+ <div class="bitcoin-row">
|
||||
+ <span class="bitcoin-label">₿</span>
|
||||
+ <span class="bitcoin-address" id="btc-address">3BqHXxraZyBapyNpJmniJDh9zqzuB8aoRr</span>
|
||||
+ <span class="copy-btn" onclick="copyBTC()">copy</span>
|
||||
+ </div>
|
||||
+ </div>
|
||||
+
|
||||
+ <div class="footer">
|
||||
+ <p class="copyright">© syui</p>
|
||||
+ </div>
|
||||
+
|
||||
+ <script>
|
||||
+ function copyBTC() {
|
||||
+ const addr = document.getElementById('btc-address').textContent;
|
||||
+ navigator.clipboard.writeText(addr).then(() => {
|
||||
+ const btn = document.querySelector('.copy-btn');
|
||||
+ btn.textContent = 'copied!';
|
||||
+ btn.style.color = '#4CAF50';
|
||||
+ setTimeout(() => {
|
||||
+ btn.textContent = 'copy';
|
||||
+ btn.style.color = '';
|
||||
+ }, 2000);
|
||||
+ });
|
||||
+ }
|
||||
+ </script>
|
||||
+</body>
|
||||
+</html>
|
||||
diff --git a/bskyweb/templates/about-license.html b/bskyweb/templates/about-license.html
|
||||
new file mode 100644
|
||||
index 000000000..000000003
|
||||
--- /dev/null
|
||||
+++ b/bskyweb/templates/about-license.html
|
||||
@@ -0,0 +1,66 @@
|
||||
+<!DOCTYPE html>
|
||||
+<html lang="ja">
|
||||
+<head>
|
||||
+ <meta charset="UTF-8">
|
||||
+ <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
+ <title>License - syu.is</title>
|
||||
+ <link rel="icon" type="image/png" href="{{ staticCDNHost }}/static/favicon.png">
|
||||
+ <style>
|
||||
+ * { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
+ body {
|
||||
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
||||
+ line-height: 1.6;
|
||||
+ color: #1a1a1a;
|
||||
+ background: #fff;
|
||||
+ padding: 20px;
|
||||
+ max-width: 800px;
|
||||
+ margin: 0 auto;
|
||||
+ }
|
||||
+ @media (prefers-color-scheme: dark) {
|
||||
+ body { background: #000; color: #e0e0e0; }
|
||||
+ a { color: #6bb3ff; }
|
||||
+ h1, h2, h3 { color: #fff; }
|
||||
+ }
|
||||
+ h1 { font-size: 28px; margin-bottom: 24px; padding-bottom: 12px; border-bottom: 1px solid #ddd; }
|
||||
+ h2 { font-size: 20px; margin: 24px 0 12px; }
|
||||
+ p { margin-bottom: 16px; }
|
||||
+ ul { margin: 0 0 16px 24px; }
|
||||
+ li { margin-bottom: 8px; }
|
||||
+ a { color: #0066cc; text-decoration: none; }
|
||||
+ a:hover { text-decoration: underline; }
|
||||
+ .header { margin-bottom: 32px; }
|
||||
+ .back-link { display: inline-block; margin-bottom: 16px; font-size: 14px; }
|
||||
+ .footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; font-size: 14px; color: #666; }
|
||||
+ pre { background: #f5f5f5; padding: 16px; border-radius: 8px; overflow-x: auto; font-size: 13px; }
|
||||
+ @media (prefers-color-scheme: dark) { pre { background: #1a1a1a; } }
|
||||
+ </style>
|
||||
+</head>
|
||||
+<body>
|
||||
+ <div class="header">
|
||||
+ <a href="/" class="back-link">← Back to syu.is</a>
|
||||
+ <h1>License</h1>
|
||||
+ </div>
|
||||
+
|
||||
+ <h2>Aiat (iOS/Android App)</h2>
|
||||
+ <p>This application is based on the Bluesky Social App, which is open source software.</p>
|
||||
+
|
||||
+ <h2>Open Source Licenses</h2>
|
||||
+ <p>This app uses the following open source software:</p>
|
||||
+
|
||||
+ <h3>Bluesky Social App</h3>
|
||||
+ <p>Licensed under the MIT License</p>
|
||||
+ <p><a href="https://github.com/bluesky-social/social-app" target="_blank">https://github.com/bluesky-social/social-app</a></p>
|
||||
+
|
||||
+ <h3>AT Protocol</h3>
|
||||
+ <p>Licensed under the MIT License / Apache 2.0</p>
|
||||
+ <p><a href="https://github.com/bluesky-social/atproto" target="_blank">https://github.com/bluesky-social/atproto</a></p>
|
||||
+
|
||||
+ <h2>Third Party Libraries</h2>
|
||||
+ <p>This application includes various third-party libraries, each with their own licenses. For a complete list, please see the application's source code repository.</p>
|
||||
+
|
||||
+ <div class="footer">
|
||||
+ <p>Last updated: 2025</p>
|
||||
+ <p>© syu.is</p>
|
||||
+ </div>
|
||||
+</body>
|
||||
+</html>
|
||||
diff --git a/bskyweb/templates/about-help.html b/bskyweb/templates/about-help.html
|
||||
new file mode 100644
|
||||
index 000000000..d37db25c5
|
||||
--- /dev/null
|
||||
+++ b/bskyweb/templates/about-help.html
|
||||
@@ -0,0 +1,91 @@
|
||||
+<!DOCTYPE html>
|
||||
+<html lang="ja">
|
||||
+<head>
|
||||
+ <meta charset="UTF-8">
|
||||
+ <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
+ <title>Help - syu.is</title>
|
||||
+ <link rel="icon" type="image/png" href="{{ staticCDNHost }}/static/favicon.png">
|
||||
+ <style>
|
||||
+ * { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
+ body {
|
||||
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
||||
+ line-height: 1.6;
|
||||
+ color: #1a1a1a;
|
||||
+ background: #fff;
|
||||
+ padding: 20px;
|
||||
+ max-width: 800px;
|
||||
+ margin: 0 auto;
|
||||
+ }
|
||||
+ @media (prefers-color-scheme: dark) {
|
||||
+ body { background: #000; color: #e0e0e0; }
|
||||
+ a { color: #6bb3ff; }
|
||||
+ h1, h2, h3 { color: #fff; }
|
||||
+ }
|
||||
+ h1 { font-size: 28px; margin-bottom: 24px; padding-bottom: 12px; border-bottom: 1px solid #ddd; }
|
||||
+ h2 { font-size: 20px; margin: 24px 0 12px; }
|
||||
+ h3 { font-size: 16px; margin: 16px 0 8px; }
|
||||
+ p { margin-bottom: 16px; }
|
||||
+ ul { margin: 0 0 16px 24px; }
|
||||
+ li { margin-bottom: 8px; }
|
||||
+ a { color: #0066cc; text-decoration: none; }
|
||||
+ a:hover { text-decoration: underline; }
|
||||
+ .header { margin-bottom: 32px; }
|
||||
+ .back-link { display: inline-block; margin-bottom: 16px; font-size: 14px; }
|
||||
+ .footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; font-size: 14px; color: #666; }
|
||||
+ .faq-item { margin-bottom: 24px; }
|
||||
+ .contact-box { background: #f5f5f5; padding: 20px; border-radius: 8px; margin: 20px 0; }
|
||||
+ @media (prefers-color-scheme: dark) {
|
||||
+ .contact-box { background: #1a1a1a; }
|
||||
+ }
|
||||
+ </style>
|
||||
+</head>
|
||||
+<body>
|
||||
+ <div class="header">
|
||||
+ <a href="/" class="back-link">← Back to syu.is</a>
|
||||
+ <h1>Help Center</h1>
|
||||
+ </div>
|
||||
+
|
||||
+ <h2>About syu.is</h2>
|
||||
+ <p>syu.is is a social networking service built on the AT Protocol (Authenticated Transfer Protocol). It allows users to share content, connect with others, and participate in a decentralized social network.</p>
|
||||
+
|
||||
+ <h2>Frequently Asked Questions</h2>
|
||||
+
|
||||
+ <div class="faq-item">
|
||||
+ <h3>What is the AT Protocol?</h3>
|
||||
+ <p>The AT Protocol is a decentralized social networking protocol that allows users to own their data and identity. It enables federation between different services while maintaining user control.</p>
|
||||
+ </div>
|
||||
+
|
||||
+ <div class="faq-item">
|
||||
+ <h3>How do I create an account?</h3>
|
||||
+ <p>You can create an account by downloading the app or visiting the website. You'll need to provide an email address and choose a username.</p>
|
||||
+ </div>
|
||||
+
|
||||
+ <div class="faq-item">
|
||||
+ <h3>How do I reset my password?</h3>
|
||||
+ <p>You can reset your password through the login screen by selecting "Forgot Password" and following the instructions sent to your email.</p>
|
||||
+ </div>
|
||||
+
|
||||
+ <div class="faq-item">
|
||||
+ <h3>How do I delete my account?</h3>
|
||||
+ <p>You can delete your account through Settings > Account. Please note that account deletion is permanent and cannot be undone.</p>
|
||||
+ </div>
|
||||
+
|
||||
+ <div class="faq-item">
|
||||
+ <h3>How do I report abuse or inappropriate content?</h3>
|
||||
+ <p>You can report content by using the report function available on each post. Our moderation team will review reports and take appropriate action.</p>
|
||||
+ </div>
|
||||
+
|
||||
+ <h2>Contact</h2>
|
||||
+ <div class="contact-box">
|
||||
+ <p>For additional support or questions:</p>
|
||||
+ <ul>
|
||||
+ <li>GitHub: <a href="https://github.com/syui" target="_blank">github.com/syui</a></li>
|
||||
+ </ul>
|
||||
+ </div>
|
||||
+
|
||||
+ <h2>Related Links</h2>
|
||||
+ <ul>
|
||||
+ <li><a href="/about/support/tos">Terms of Service</a></li>
|
||||
+ <li><a href="/about/support/privacy-policy">Privacy Policy</a></li>
|
||||
+ <li><a href="/about/support/license">License</a></li>
|
||||
+ <li><a href="/about/support/app">App Info</a></li>
|
||||
+ <li><a href="https://atproto.com" target="_blank">AT Protocol Documentation</a></li>
|
||||
+ </ul>
|
||||
+
|
||||
+ <div class="footer">
|
||||
+ <p>Last updated: 2025</p>
|
||||
+ <p>© syu.is</p>
|
||||
+ </div>
|
||||
+</body>
|
||||
+</html>
|
||||
diff --git a/bskyweb/templates/about-privacy.html b/bskyweb/templates/about-privacy.html
|
||||
new file mode 100644
|
||||
index 000000000..14a1168ad
|
||||
--- /dev/null
|
||||
+++ b/bskyweb/templates/about-privacy.html
|
||||
@@ -0,0 +1,83 @@
|
||||
+<!DOCTYPE html>
|
||||
+<html lang="ja">
|
||||
+<head>
|
||||
+ <meta charset="UTF-8">
|
||||
+ <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
+ <title>Privacy Policy - syu.is</title>
|
||||
+ <link rel="icon" type="image/png" href="{{ staticCDNHost }}/static/favicon.png">
|
||||
+ <style>
|
||||
+ * { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
+ body {
|
||||
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
||||
+ line-height: 1.6;
|
||||
+ color: #1a1a1a;
|
||||
+ background: #fff;
|
||||
+ padding: 20px;
|
||||
+ max-width: 800px;
|
||||
+ margin: 0 auto;
|
||||
+ }
|
||||
+ @media (prefers-color-scheme: dark) {
|
||||
+ body { background: #000; color: #e0e0e0; }
|
||||
+ a { color: #6bb3ff; }
|
||||
+ h1, h2, h3 { color: #fff; }
|
||||
+ }
|
||||
+ h1 { font-size: 28px; margin-bottom: 24px; padding-bottom: 12px; border-bottom: 1px solid #ddd; }
|
||||
+ h2 { font-size: 20px; margin: 24px 0 12px; }
|
||||
+ p { margin-bottom: 16px; }
|
||||
+ ul { margin: 0 0 16px 24px; }
|
||||
+ li { margin-bottom: 8px; }
|
||||
+ a { color: #0066cc; text-decoration: none; }
|
||||
+ a:hover { text-decoration: underline; }
|
||||
+ .header { margin-bottom: 32px; }
|
||||
+ .back-link { display: inline-block; margin-bottom: 16px; font-size: 14px; }
|
||||
+ .footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; font-size: 14px; color: #666; }
|
||||
+ </style>
|
||||
+</head>
|
||||
+<body>
|
||||
+ <div class="header">
|
||||
+ <a href="/" class="back-link">← Back to syu.is</a>
|
||||
+ <h1>Privacy Policy</h1>
|
||||
+ </div>
|
||||
+
|
||||
+ <h2>1. Introduction</h2>
|
||||
+ <p>This Privacy Policy explains how syu.is collects, uses, and protects your personal information when you use our service.</p>
|
||||
+
|
||||
+ <h2>2. Information We Collect</h2>
|
||||
+ <p>We collect the following types of information:</p>
|
||||
+ <ul>
|
||||
+ <li><strong>Account Information:</strong> Email address, username, and profile information you provide</li>
|
||||
+ <li><strong>Content:</strong> Posts, messages, and other content you create on the platform</li>
|
||||
+ <li><strong>Usage Data:</strong> Information about how you interact with our service</li>
|
||||
+ <li><strong>Device Information:</strong> Browser type, operating system, and device identifiers</li>
|
||||
+ </ul>
|
||||
+
|
||||
+ <h2>3. How We Use Your Information</h2>
|
||||
+ <p>We use your information to:</p>
|
||||
+ <ul>
|
||||
+ <li>Provide and maintain our service</li>
|
||||
+ <li>Improve and personalize your experience</li>
|
||||
+ <li>Communicate with you about the service</li>
|
||||
+ <li>Ensure security and prevent abuse</li>
|
||||
+ </ul>
|
||||
+
|
||||
+ <h2>4. Data Sharing</h2>
|
||||
+ <p>As part of the AT Protocol federation, your public content may be shared with other servers in the network. We do not sell your personal information to third parties.</p>
|
||||
+
|
||||
+ <h2>5. Data Security</h2>
|
||||
+ <p>We implement appropriate security measures to protect your personal information. However, no method of transmission over the Internet is 100% secure.</p>
|
||||
+
|
||||
+ <h2>6. Your Rights</h2>
|
||||
+ <p>You have the right to:</p>
|
||||
+ <ul>
|
||||
+ <li>Access your personal data</li>
|
||||
+ <li>Request correction of your data</li>
|
||||
+ <li>Request deletion of your account</li>
|
||||
+ <li>Export your data</li>
|
||||
+ </ul>
|
||||
+
|
||||
+ <h2>7. Cookies</h2>
|
||||
+ <p>We use cookies and similar technologies to maintain your session and improve your experience.</p>
|
||||
+
|
||||
+ <h2>8. Changes to This Policy</h2>
|
||||
+ <p>We may update this Privacy Policy from time to time. We will notify you of any significant changes.</p>
|
||||
+
|
||||
+ <h2>9. Contact</h2>
|
||||
+ <p>For privacy-related questions, please visit our <a href="/about/support/help">Help page</a>.</p>
|
||||
+
|
||||
+ <div class="footer">
|
||||
+ <p>Last updated: 2025</p>
|
||||
+ <p>© syu.is</p>
|
||||
+ </div>
|
||||
+</body>
|
||||
+</html>
|
||||
diff --git a/bskyweb/templates/about-tos.html b/bskyweb/templates/about-tos.html
|
||||
new file mode 100644
|
||||
index 000000000..db5d82f5c
|
||||
--- /dev/null
|
||||
+++ b/bskyweb/templates/about-tos.html
|
||||
@@ -0,0 +1,76 @@
|
||||
+<!DOCTYPE html>
|
||||
+<html lang="ja">
|
||||
+<head>
|
||||
+ <meta charset="UTF-8">
|
||||
+ <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
+ <title>Terms of Service - syu.is</title>
|
||||
+ <link rel="icon" type="image/png" href="{{ staticCDNHost }}/static/favicon.png">
|
||||
+ <style>
|
||||
+ * { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
+ body {
|
||||
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
||||
+ line-height: 1.6;
|
||||
+ color: #1a1a1a;
|
||||
+ background: #fff;
|
||||
+ padding: 20px;
|
||||
+ max-width: 800px;
|
||||
+ margin: 0 auto;
|
||||
+ }
|
||||
+ @media (prefers-color-scheme: dark) {
|
||||
+ body { background: #000; color: #e0e0e0; }
|
||||
+ a { color: #6bb3ff; }
|
||||
+ h1, h2, h3 { color: #fff; }
|
||||
+ }
|
||||
+ h1 { font-size: 28px; margin-bottom: 24px; padding-bottom: 12px; border-bottom: 1px solid #ddd; }
|
||||
+ h2 { font-size: 20px; margin: 24px 0 12px; }
|
||||
+ p { margin-bottom: 16px; }
|
||||
+ ul { margin: 0 0 16px 24px; }
|
||||
+ li { margin-bottom: 8px; }
|
||||
+ a { color: #0066cc; text-decoration: none; }
|
||||
+ a:hover { text-decoration: underline; }
|
||||
+ .header { margin-bottom: 32px; }
|
||||
+ .back-link { display: inline-block; margin-bottom: 16px; font-size: 14px; }
|
||||
+ .footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; font-size: 14px; color: #666; }
|
||||
+ </style>
|
||||
+</head>
|
||||
+<body>
|
||||
+ <div class="header">
|
||||
+ <a href="/" class="back-link">← Back to syu.is</a>
|
||||
+ <h1>Terms of Service</h1>
|
||||
+ </div>
|
||||
+
|
||||
+ <h2>1. Introduction</h2>
|
||||
+ <p>Welcome to syu.is. By using our service, you agree to these terms. Please read them carefully.</p>
|
||||
+
|
||||
+ <h2>2. Service Description</h2>
|
||||
+ <p>syu.is is a social networking service built on the AT Protocol. We provide a platform for users to share content and connect with others.</p>
|
||||
+
|
||||
+ <h2>3. User Responsibilities</h2>
|
||||
+ <p>As a user of syu.is, you agree to:</p>
|
||||
+ <ul>
|
||||
+ <li>Provide accurate information when creating an account</li>
|
||||
+ <li>Keep your account credentials secure</li>
|
||||
+ <li>Not use the service for illegal activities</li>
|
||||
+ <li>Respect other users and their content</li>
|
||||
+ <li>Comply with applicable laws and regulations</li>
|
||||
+ </ul>
|
||||
+
|
||||
+ <h2>4. Content Guidelines</h2>
|
||||
+ <p>Users are responsible for the content they post. Prohibited content includes:</p>
|
||||
+ <ul>
|
||||
+ <li>Illegal content</li>
|
||||
+ <li>Harassment or abuse</li>
|
||||
+ <li>Spam or misleading information</li>
|
||||
+ <li>Content that violates others' rights</li>
|
||||
+ </ul>
|
||||
+
|
||||
+ <h2>5. Privacy</h2>
|
||||
+ <p>Your privacy is important to us. Please review our <a href="/about/support/privacy-policy">Privacy Policy</a> to understand how we handle your data.</p>
|
||||
+
|
||||
+ <h2>6. Disclaimer</h2>
|
||||
+ <p>The service is provided "as is" without warranties of any kind. We are not liable for any damages arising from your use of the service.</p>
|
||||
+
|
||||
+ <h2>7. Changes to Terms</h2>
|
||||
+ <p>We may update these terms from time to time. Continued use of the service after changes constitutes acceptance of the new terms.</p>
|
||||
+
|
||||
+ <h2>8. Contact</h2>
|
||||
+ <p>For questions about these terms, please visit our <a href="/about/support/help">Help page</a>.</p>
|
||||
+
|
||||
+ <div class="footer">
|
||||
+ <p>Last updated: 2025</p>
|
||||
+ <p>© syu.is</p>
|
||||
+ </div>
|
||||
+</body>
|
||||
+</html>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
diff --git a/src/components/dialogs/ServerInput.tsx b/src/components/dialogs/ServerInput.tsx
|
||||
--- a/src/components/dialogs/ServerInput.tsx
|
||||
+++ b/src/components/dialogs/ServerInput.tsx
|
||||
@@ -144,9 +144,9 @@
|
||||
<SegmentedControl.Item
|
||||
testID="bskyServiceSelectBtn"
|
||||
value={BSKY_SERVICE}
|
||||
- label={_(msg`Bluesky`)}>
|
||||
+ label={_(msg`syu.is`)}>
|
||||
<SegmentedControl.ItemText>
|
||||
- {_(msg`Bluesky`)}
|
||||
+ {_(msg`syu.is`)}
|
||||
</SegmentedControl.ItemText>
|
||||
</SegmentedControl.Item>
|
||||
<SegmentedControl.Item
|
||||
71
ios/patching/032-social-app-ios-feed-loggedout.patch
Normal file
71
ios/patching/032-social-app-ios-feed-loggedout.patch
Normal file
@@ -0,0 +1,71 @@
|
||||
diff --git a/src/lib/api/feed/custom.ts b/src/lib/api/feed/custom.ts
|
||||
index 18bb8c8f0..bab286d7a 100644
|
||||
--- a/src/lib/api/feed/custom.ts
|
||||
+++ b/src/lib/api/feed/custom.ts
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
jsonStringToLex,
|
||||
} from '@atproto/api'
|
||||
|
||||
+import {PUBLIC_APPVIEW} from '#/lib/constants'
|
||||
import {
|
||||
getAppLanguageAsContentLanguage,
|
||||
getContentLanguages,
|
||||
@@ -12,6 +13,17 @@ import {
|
||||
import {type FeedAPI, type FeedAPIResponse} from './types'
|
||||
import {createBskyTopicsHeader, isBlueskyOwnedFeed} from './utils'
|
||||
|
||||
+// Check if the feed is hosted on syu.is network
|
||||
+function isSyuIsFeed(feedUri: string): boolean {
|
||||
+ return feedUri.includes('did:plc:6qyecktefllvenje24fcxnie') || feedUri.includes('syu.is')
|
||||
+}
|
||||
+
|
||||
+// Check if the agent is connected to syu.is
|
||||
+function isAgentOnSyuIs(agent: BskyAgent): boolean {
|
||||
+ const serviceUrl = agent.service?.toString() || ''
|
||||
+ return serviceUrl.includes('syu.is')
|
||||
+}
|
||||
+
|
||||
export class CustomFeedAPI implements FeedAPI {
|
||||
agent: BskyAgent
|
||||
params: GetCustomFeed.QueryParams
|
||||
@@ -54,8 +66,12 @@ export class CustomFeedAPI implements FeedAPI {
|
||||
const agent = this.agent
|
||||
const isBlueskyOwned = isBlueskyOwnedFeed(this.params.feed)
|
||||
|
||||
- const res = agent.did
|
||||
- ? await this.agent.app.bsky.feed.getFeed(
|
||||
+ // For syu.is feeds accessed from non-syu.is accounts, use PUBLIC_APPVIEW
|
||||
+ const needsPublicAppView = isSyuIsFeed(this.params.feed) && !isAgentOnSyuIs(agent)
|
||||
+
|
||||
+ const res = !agent.did || needsPublicAppView
|
||||
+ ? await loggedOutFetch({...this.params, cursor, limit})
|
||||
+ : await this.agent.app.bsky.feed.getFeed(
|
||||
{
|
||||
...this.params,
|
||||
cursor,
|
||||
@@ -70,7 +86,6 @@ export class CustomFeedAPI implements FeedAPI {
|
||||
},
|
||||
},
|
||||
)
|
||||
- : await loggedOutFetch({...this.params, cursor, limit})
|
||||
if (res.success) {
|
||||
// NOTE
|
||||
// some custom feeds fail to enforce the pagination limit
|
||||
@@ -120,7 +135,7 @@ async function loggedOutFetch({
|
||||
|
||||
// manually construct fetch call so we can add the `lang` cache-busting param
|
||||
let res = await fetch(
|
||||
- `https://api.bsky.app/xrpc/app.bsky.feed.getFeed?feed=${feed}${
|
||||
+ `${PUBLIC_APPVIEW}/xrpc/app.bsky.feed.getFeed?feed=${encodeURIComponent(feed)}${
|
||||
cursor ? `&cursor=${cursor}` : ''
|
||||
}&limit=${limit}&lang=${contentLangs}`,
|
||||
{
|
||||
@@ -140,7 +155,7 @@ async function loggedOutFetch({
|
||||
|
||||
// no data, try again with language headers removed
|
||||
res = await fetch(
|
||||
- `https://api.bsky.app/xrpc/app.bsky.feed.getFeed?feed=${feed}${
|
||||
+ `${PUBLIC_APPVIEW}/xrpc/app.bsky.feed.getFeed?feed=${encodeURIComponent(feed)}${
|
||||
cursor ? `&cursor=${cursor}` : ''
|
||||
}&limit=${limit}`,
|
||||
{method: 'GET', headers: {'Accept-Language': '', ...labelersHeader}},
|
||||
23
ios/patching/033-social-app-ios-hide-profile-tabs.patch
Normal file
23
ios/patching/033-social-app-ios-hide-profile-tabs.patch
Normal file
@@ -0,0 +1,23 @@
|
||||
diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx
|
||||
index 123456789..987654321 100644
|
||||
--- a/src/view/screens/Profile.tsx
|
||||
+++ b/src/view/screens/Profile.tsx
|
||||
@@ -218,13 +218,13 @@ function ProfileScreenLoaded({
|
||||
const showPostsTab = true
|
||||
const showRepliesTab = hasSession
|
||||
const showMediaTab = !hasLabeler
|
||||
- const showVideosTab = !hasLabeler
|
||||
+ const showVideosTab = false
|
||||
const showLikesTab = isMe
|
||||
const feedGenCount = profile.associated?.feedgens || 0
|
||||
- const showFeedsTab = isMe || feedGenCount > 0
|
||||
+ const showFeedsTab = feedGenCount > 0
|
||||
const starterPackCount = profile.associated?.starterPacks || 0
|
||||
- const showStarterPacksTab = isMe || starterPackCount > 0
|
||||
+ const showStarterPacksTab = false
|
||||
// subtract starterpack count from list count, since starterpacks are a type of list
|
||||
const listCount = (profile.associated?.lists || 0) - starterPackCount
|
||||
- const showListsTab = hasSession && (isMe || listCount > 0)
|
||||
+ const showListsTab = false
|
||||
|
||||
const sectionTitles = [
|
||||
28
ios/patching/036-social-app-ios-homeheader-loggedout.patch
Normal file
28
ios/patching/036-social-app-ios-homeheader-loggedout.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
diff --git a/src/view/com/home/HomeHeader.tsx b/src/view/com/home/HomeHeader.tsx
|
||||
--- a/src/view/com/home/HomeHeader.tsx
|
||||
+++ b/src/view/com/home/HomeHeader.tsx
|
||||
@@ -3,7 +3,6 @@ import {useNavigation} from '@react-navigation/native'
|
||||
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
import {type FeedSourceInfo} from '#/state/queries/feed'
|
||||
-import {useSession} from '#/state/session'
|
||||
import {type RenderTabBarFnProps} from '#/view/com/pager/Pager'
|
||||
import {TabBar} from '../pager/TabBar'
|
||||
import {HomeHeaderLayout} from './HomeHeaderLayout'
|
||||
@@ -16,17 +15,15 @@ export function HomeHeader(
|
||||
) {
|
||||
const {feeds, onSelect: onSelectProp} = props
|
||||
- const {hasSession} = useSession()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
|
||||
const hasPinnedCustom = React.useMemo<boolean>(() => {
|
||||
- if (!hasSession) return false
|
||||
return feeds.some(tab => {
|
||||
const isFollowing = tab.uri === 'following'
|
||||
return !isFollowing
|
||||
})
|
||||
- }, [feeds, hasSession])
|
||||
+ }, [feeds])
|
||||
|
||||
const items = React.useMemo(() => {
|
||||
const pinnedNames = feeds.map(f => f.displayName)
|
||||
13
ios/patching/037-social-app-ios-disable-contacts-nux.patch
Normal file
13
ios/patching/037-social-app-ios-disable-contacts-nux.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/src/components/dialogs/nuxs/index.tsx b/src/components/dialogs/nuxs/index.tsx
|
||||
index 63e11a7f4..70fa993cf 100644
|
||||
--- a/src/components/dialogs/nuxs/index.tsx
|
||||
+++ b/src/components/dialogs/nuxs/index.tsx
|
||||
@@ -46,7 +46,7 @@ const queuedNuxs: {
|
||||
enabled: ({currentProfile}) => {
|
||||
return (
|
||||
isNative &&
|
||||
- isExistingUserAsOf('2025-12-16T00:00:00.000Z', currentProfile.createdAt)
|
||||
+ isExistingUserAsOf('2099-12-16T00:00:00.000Z', currentProfile.createdAt)
|
||||
)
|
||||
},
|
||||
},
|
||||
310
ios/patching/AppInfo.tsx
Normal file
310
ios/patching/AppInfo.tsx
Normal file
@@ -0,0 +1,310 @@
|
||||
import React, {useState} from 'react'
|
||||
import {
|
||||
View,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Pressable,
|
||||
Image,
|
||||
} from 'react-native'
|
||||
import * as Clipboard from 'expo-clipboard'
|
||||
import * as WebBrowser from 'expo-web-browser'
|
||||
import {Trans} from '@lingui/macro'
|
||||
|
||||
import * as Layout from '#/components/Layout'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useSetTitle} from '#/lib/hooks/useSetTitle'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
|
||||
const APP_VERSION = '1.111.0'
|
||||
const APP_NAME = 'Aiat'
|
||||
const BITCOIN_ADDRESS = '3BqHXxraZyBapyNpJmniJDh9zqzuB8aoRr'
|
||||
|
||||
export function AppInfoScreen() {
|
||||
useSetTitle('App Info')
|
||||
const t = useTheme()
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const copyToClipboard = async (text: string) => {
|
||||
try {
|
||||
await Clipboard.setStringAsync(text)
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 2000)
|
||||
} catch (e) {
|
||||
console.log('Clipboard not available')
|
||||
}
|
||||
}
|
||||
|
||||
const openUrl = (url: string) => {
|
||||
WebBrowser.openBrowserAsync(url)
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout.Screen>
|
||||
<Layout.Header.Outer>
|
||||
<Layout.Header.BackButton />
|
||||
<Layout.Header.Content>
|
||||
<Layout.Header.TitleText>
|
||||
<Trans>App Info</Trans>
|
||||
</Layout.Header.TitleText>
|
||||
</Layout.Header.Content>
|
||||
<Layout.Header.Slot />
|
||||
</Layout.Header.Outer>
|
||||
<Layout.Content>
|
||||
<ScrollView
|
||||
style={[a.flex_1]}
|
||||
contentContainerStyle={[a.p_lg, a.pt_xl, a.pb_5xl]}>
|
||||
{/* App Header */}
|
||||
<View style={styles.appHeader}>
|
||||
<View style={[styles.appIconContainer, t.atoms.bg_contrast_25]}>
|
||||
<Image
|
||||
source={require('../../../assets/logo.png')}
|
||||
style={styles.appIcon}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
</View>
|
||||
<Text style={[styles.appName, t.atoms.text]}>
|
||||
{APP_NAME}
|
||||
</Text>
|
||||
<Text style={[styles.appVersion, t.atoms.text_contrast_medium]}>
|
||||
v{APP_VERSION}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Description Section */}
|
||||
<View style={[styles.section, t.atoms.bg_contrast_25]}>
|
||||
<Text style={[styles.description, t.atoms.text]}>
|
||||
{APP_NAME} is a social networking application based on AT Protocol.
|
||||
Connect with your community on syu.is.
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* App Information Section */}
|
||||
<View style={[styles.section, t.atoms.bg_contrast_25]}>
|
||||
<Text style={[styles.sectionTitle, t.atoms.text_contrast_medium]}>
|
||||
App Information
|
||||
</Text>
|
||||
<View style={styles.infoGrid}>
|
||||
<View style={[styles.infoItem, t.atoms.bg_contrast_50]}>
|
||||
<Text style={[styles.infoLabel, t.atoms.text_contrast_medium]}>
|
||||
Version
|
||||
</Text>
|
||||
<Text style={[styles.infoValue, t.atoms.text]}>
|
||||
{APP_VERSION}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={[styles.infoItem, t.atoms.bg_contrast_50]}>
|
||||
<Text style={[styles.infoLabel, t.atoms.text_contrast_medium]}>
|
||||
Category
|
||||
</Text>
|
||||
<Text style={[styles.infoValue, t.atoms.text]}>
|
||||
Social
|
||||
</Text>
|
||||
</View>
|
||||
<View style={[styles.infoItem, t.atoms.bg_contrast_50]}>
|
||||
<Text style={[styles.infoLabel, t.atoms.text_contrast_medium]}>
|
||||
Supported OS
|
||||
</Text>
|
||||
<Text style={[styles.infoValue, t.atoms.text]}>
|
||||
iOS 26.0+
|
||||
</Text>
|
||||
</View>
|
||||
<View style={[styles.infoItem, t.atoms.bg_contrast_50]}>
|
||||
<Text style={[styles.infoLabel, t.atoms.text_contrast_medium]}>
|
||||
Price
|
||||
</Text>
|
||||
<Text style={[styles.infoValue, t.atoms.text]}>
|
||||
Free
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Developer Section */}
|
||||
<View style={[styles.section, t.atoms.bg_contrast_25]}>
|
||||
<Text style={[styles.sectionTitle, t.atoms.text_contrast_medium]}>
|
||||
Developer
|
||||
</Text>
|
||||
<View style={styles.developerCard}>
|
||||
<Text style={[styles.developerName, t.atoms.text]}>syui</Text>
|
||||
</View>
|
||||
|
||||
<Pressable
|
||||
onPress={() => openUrl('https://git.syui.ai/syui')}
|
||||
style={[styles.linkRow, t.atoms.border_contrast_low]}>
|
||||
<Text style={[styles.linkIcon, t.atoms.text_contrast_medium]}>
|
||||
Git
|
||||
</Text>
|
||||
<Text style={[styles.linkValue, {color: '#0084ff'}]}>
|
||||
git.syui.ai/syui
|
||||
</Text>
|
||||
<Text style={[styles.linkArrow, t.atoms.text_contrast_low]}>→</Text>
|
||||
</Pressable>
|
||||
|
||||
<Pressable
|
||||
onPress={() => openUrl('https://syu.is/syui')}
|
||||
style={[styles.linkRow, t.atoms.border_contrast_low]}>
|
||||
<Text style={[styles.linkIcon, t.atoms.text_contrast_medium]}>
|
||||
ATProto
|
||||
</Text>
|
||||
<Text style={[styles.linkValue, {color: '#0084ff'}]}>
|
||||
syu.is/syui
|
||||
</Text>
|
||||
<Text style={[styles.linkArrow, t.atoms.text_contrast_low]}>→</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
{/* Bitcoin Section */}
|
||||
<View style={[styles.section, t.atoms.bg_contrast_25]}>
|
||||
<Text style={[styles.sectionTitle, t.atoms.text_contrast_medium]}>
|
||||
Bitcoin
|
||||
</Text>
|
||||
<Pressable
|
||||
onPress={() => copyToClipboard(BITCOIN_ADDRESS)}
|
||||
style={styles.bitcoinRow}>
|
||||
<Text style={styles.bitcoinLabel}>₿</Text>
|
||||
<Text style={[styles.bitcoinAddress, t.atoms.text_contrast_medium]}>
|
||||
{BITCOIN_ADDRESS}
|
||||
</Text>
|
||||
<Text style={[styles.copyHint, copied && styles.copiedHint]}>
|
||||
{copied ? 'copied!' : 'copy'}
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
{/* Copyright */}
|
||||
<View style={styles.copyright}>
|
||||
<Text style={[styles.copyrightText, t.atoms.text_contrast_low]}>
|
||||
© syui
|
||||
</Text>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</Layout.Content>
|
||||
</Layout.Screen>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
appHeader: {
|
||||
alignItems: 'center',
|
||||
marginBottom: 24,
|
||||
},
|
||||
appIconContainer: {
|
||||
width: 80,
|
||||
height: 80,
|
||||
borderRadius: 18,
|
||||
overflow: 'hidden',
|
||||
marginBottom: 12,
|
||||
},
|
||||
appIcon: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
appName: {
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
marginBottom: 4,
|
||||
},
|
||||
appVersion: {
|
||||
fontSize: 14,
|
||||
},
|
||||
section: {
|
||||
marginBottom: 16,
|
||||
borderRadius: 16,
|
||||
padding: 16,
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: 13,
|
||||
fontWeight: '600',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 0.5,
|
||||
marginBottom: 12,
|
||||
},
|
||||
description: {
|
||||
fontSize: 15,
|
||||
lineHeight: 22,
|
||||
},
|
||||
infoGrid: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
gap: 8,
|
||||
},
|
||||
infoItem: {
|
||||
flex: 1,
|
||||
minWidth: '45%',
|
||||
alignItems: 'center',
|
||||
borderRadius: 12,
|
||||
padding: 12,
|
||||
},
|
||||
infoLabel: {
|
||||
fontSize: 11,
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 0.5,
|
||||
marginBottom: 4,
|
||||
},
|
||||
infoValue: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
textAlign: 'center',
|
||||
},
|
||||
developerCard: {
|
||||
marginBottom: 12,
|
||||
},
|
||||
developerName: {
|
||||
fontSize: 18,
|
||||
fontWeight: '600',
|
||||
},
|
||||
linkRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingVertical: 12,
|
||||
borderTopWidth: 1,
|
||||
},
|
||||
linkIcon: {
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
width: 70,
|
||||
},
|
||||
linkValue: {
|
||||
flex: 1,
|
||||
fontSize: 14,
|
||||
},
|
||||
linkArrow: {
|
||||
fontSize: 16,
|
||||
},
|
||||
bitcoinRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'rgba(247, 147, 26, 0.08)',
|
||||
borderRadius: 12,
|
||||
padding: 14,
|
||||
gap: 10,
|
||||
},
|
||||
bitcoinLabel: {
|
||||
fontSize: 18,
|
||||
fontWeight: '600',
|
||||
color: '#f7931a',
|
||||
},
|
||||
bitcoinAddress: {
|
||||
flex: 1,
|
||||
fontSize: 11,
|
||||
fontFamily: 'monospace',
|
||||
},
|
||||
copyHint: {
|
||||
fontSize: 12,
|
||||
color: '#999999',
|
||||
minWidth: 50,
|
||||
textAlign: 'right',
|
||||
},
|
||||
copiedHint: {
|
||||
color: '#4CAF50',
|
||||
fontWeight: '600',
|
||||
},
|
||||
copyright: {
|
||||
alignItems: 'center',
|
||||
marginTop: 20,
|
||||
marginBottom: 20,
|
||||
},
|
||||
copyrightText: {
|
||||
fontSize: 12,
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user