diff --git a/src/view/screens/License.tsx b/src/view/screens/License.tsx
new file mode 100644
index 000000000..f98cd6afc
--- /dev/null
+++ b/src/view/screens/License.tsx
@@ -0,0 +1,86 @@
+import React from 'react'
+import { ScrollView } from 'react-native'
+import * as Layout from '#/components/Layout'
+import {useSetTitle} from '#/lib/hooks/useSetTitle'
+import {atoms as a, useTheme} from '#/alf'
+import {Text} from '#/components/Typography'
+
+export function LicenseScreen() {
+ useSetTitle('License')
+ const t = useTheme()
+
+ return (
+
+
+ License
+
+
+ This application is based on Bluesky Social App.
+
+
+
+ https://github.com/bluesky-social/social-app
+
+
+ MIT License
+
+
+ Copyright (c) 2022-2025 Bluesky PBC
+
+
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+
+ 日本語訳(参考)
+
+
+ 本ソフトウェアおよび関連文書ファイル(以下「ソフトウェア」)のコピーを取得する
+ すべての人に対し、ソフトウェアを無制限に扱うことを無償で許可します。これには、
+ ソフトウェアのコピーを使用、複製、変更、結合、公開、配布、サブライセンス、
+ および/または販売する権利、ならびにソフトウェアを提供する相手にそうした行為を
+ 許可する権利が含まれますが、これらに限定されません。
+
+
+
+ 上記の著作権表示および本許諾表示を、ソフトウェアのすべてのコピーまたは
+ 重要な部分に記載するものとします。
+
+
+
+ ソフトウェアは「現状のまま」で提供され、明示黙示を問わず、商品性、特定目的への
+ 適合性、および権利非侵害についての保証を含む、いかなる種類の保証もなされません。
+ いかなる場合においても、作者または著作権者は、契約行為、不法行為、またはそれ以外で
+ あろうと、ソフトウェアに起因または関連し、あるいはソフトウェアの使用または
+ その他の扱いによって生じる一切の請求、損害、その他の義務について責任を負わないものとします。
+
+
+
+ Original License: https://github.com/bluesky-social/social-app/blob/main/LICENSE
+
+
+
+ )
+}
diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx
index ed2a6cfb7..0eba4edc4 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 (
): 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 (
+ contentContainerStyle={[{ paddingTop: Math.max(insets.top + a.pt_xl.paddingTop, a.pt_xl.paddingTop) }]}>
{hasSession && currentAccount ? (
): React.ReactNode => {
)}
-
@@ -292,17 +208,10 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
<>
-
-
-
-
): React.ReactNode => {
) : (
<>
-
>
)}
@@ -322,69 +230,11 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
-
-
)
}
DrawerContent = React.memo(DrawerContent)
-export {DrawerContent}
-
-let DrawerFooter = ({
- onPressFeedback,
- onPressHelp,
-}: {
- onPressFeedback: () => void
- onPressHelp: () => void
-}): React.ReactNode => {
- const {_} = useLingui()
- const insets = useSafeAreaInsets()
- return (
-
-
-
-
- )
-}
-DrawerFooter = React.memo(DrawerFooter)
+export { DrawerContent }
interface MenuItemProps extends ComponentProps {
icon: JSX.Element
@@ -400,7 +250,7 @@ let SearchMenuItem = ({
isActive: boolean
onPress: () => void
}): React.ReactNode => {
- const {_} = useLingui()
+ const { _ } = useLingui()
const t = useTheme()
return (