about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/api/api-polyfill.ts2
-rw-r--r--src/lib/api/feed-manip.ts41
-rw-r--r--src/lib/hooks/useTimer.ts2
-rw-r--r--src/state/models/content/list-membership.ts25
-rw-r--r--src/state/models/content/list.ts39
-rw-r--r--src/state/models/discovery/foafs.ts16
-rw-r--r--src/state/models/feeds/post.ts2
-rw-r--r--src/state/models/lists/lists-list.ts13
-rw-r--r--src/state/models/ui/shell.ts12
-rw-r--r--src/view/com/composer/useExternalLinkFetch.ts5
-rw-r--r--src/view/com/lightbox/Lightbox.tsx12
-rw-r--r--src/view/com/modals/CreateOrEditMuteList.tsx8
-rw-r--r--src/view/com/modals/ListAddRemoveUser.tsx2
-rw-r--r--src/view/com/profile/ProfileCard.tsx6
-rw-r--r--src/view/com/profile/ProfileHeader.tsx4
-rw-r--r--src/view/com/util/BlurView.web.tsx1
-rw-r--r--src/view/com/util/Html.tsx28
-rw-r--r--src/view/com/util/UserInfoText.tsx4
-rw-r--r--src/view/screens/Settings.tsx13
-rw-r--r--src/view/shell/desktop/LeftNav.tsx6
20 files changed, 160 insertions, 81 deletions
diff --git a/src/lib/api/api-polyfill.ts b/src/lib/api/api-polyfill.ts
index 7c38625a2..ea1d97598 100644
--- a/src/lib/api/api-polyfill.ts
+++ b/src/lib/api/api-polyfill.ts
@@ -11,7 +11,7 @@ export function doPolyfill() {
 interface FetchHandlerResponse {
   status: number
   headers: Record<string, string>
-  body: ArrayBuffer | undefined
+  body: any
 }
 
 async function fetchHandler(
diff --git a/src/lib/api/feed-manip.ts b/src/lib/api/feed-manip.ts
index 035b36096..f2500c4f7 100644
--- a/src/lib/api/feed-manip.ts
+++ b/src/lib/api/feed-manip.ts
@@ -74,9 +74,12 @@ export class FeedViewPostsSlice {
   }
 
   flattenReplyParent() {
-    if (this.items[0].reply?.parent) {
-      this.isFlattenedReply = true
-      this.items.splice(0, 0, {post: this.items[0].reply?.parent})
+    if (this.items[0].reply) {
+      const reply = this.items[0].reply
+      if (AppBskyFeedDefs.isPostView(reply.parent)) {
+        this.isFlattenedReply = true
+        this.items.splice(0, 0, {post: reply.parent})
+      }
     }
   }
 }
@@ -130,16 +133,17 @@ export class FeedTuner {
 
     // turn non-threads with reply parents into threads
     for (const slice of slices) {
-      if (
-        !slice.isThread &&
-        !slice.items[0].reason &&
-        slice.items[0].reply?.parent &&
-        !this.seenUris.has(slice.items[0].reply?.parent.uri) &&
-        !soonToBeSeenUris.has(slice.items[0].reply?.parent.uri)
-      ) {
-        const uri = slice.items[0].reply?.parent.uri
-        slice.flattenReplyParent()
-        soonToBeSeenUris.add(uri)
+      if (!slice.isThread && !slice.items[0].reason && slice.items[0].reply) {
+        const reply = slice.items[0].reply
+        if (
+          AppBskyFeedDefs.isPostView(reply.parent) &&
+          !this.seenUris.has(reply.parent.uri) &&
+          !soonToBeSeenUris.has(reply.parent.uri)
+        ) {
+          const uri = reply.parent.uri
+          slice.flattenReplyParent()
+          soonToBeSeenUris.add(uri)
+        }
       }
     }
 
@@ -231,7 +235,12 @@ export class FeedTuner {
 }
 
 function getSelfReplyUri(item: FeedViewPost): string | undefined {
-  return item.reply?.parent.author.did === item.post.author.did
-    ? item.reply?.parent.uri
-    : undefined
+  if (item.reply) {
+    if (AppBskyFeedDefs.isPostView(item.reply.parent)) {
+      return item.reply.parent.author.did === item.post.author.did
+        ? item.reply.parent.uri
+        : undefined
+    }
+  }
+  return undefined
 }
diff --git a/src/lib/hooks/useTimer.ts b/src/lib/hooks/useTimer.ts
index bf3ecc07f..b14a9f24f 100644
--- a/src/lib/hooks/useTimer.ts
+++ b/src/lib/hooks/useTimer.ts
@@ -4,7 +4,7 @@ import * as React from 'react'
  * Helper hook to run persistent timers on views
  */
 export function useTimer(time: number, handler: () => void) {
-  const timer = React.useRef(undefined)
+  const timer = React.useRef<undefined | NodeJS.Timeout>(undefined)
 
   // function to restart the timer
   const reset = React.useCallback(() => {
diff --git a/src/state/models/content/list-membership.ts b/src/state/models/content/list-membership.ts
index b4af4472b..20d9b60af 100644
--- a/src/state/models/content/list-membership.ts
+++ b/src/state/models/content/list-membership.ts
@@ -9,6 +9,16 @@ interface Membership {
   value: AppBskyGraphListitem.Record
 }
 
+interface ListitemRecord {
+  uri: string
+  value: AppBskyGraphListitem.Record
+}
+
+interface ListitemListResponse {
+  cursor?: string
+  records: ListitemRecord[]
+}
+
 export class ListMembershipModel {
   // data
   memberships: Membership[] = []
@@ -32,13 +42,14 @@ export class ListMembershipModel {
     // it needs to be replaced with server side list membership queries
     // -prf
     let cursor
-    let records = []
+    let records: ListitemRecord[] = []
     for (let i = 0; i < 100; i++) {
-      const res = await this.rootStore.agent.app.bsky.graph.listitem.list({
-        repo: this.rootStore.me.did,
-        cursor,
-        limit: PAGE_SIZE,
-      })
+      const res: ListitemListResponse =
+        await this.rootStore.agent.app.bsky.graph.listitem.list({
+          repo: this.rootStore.me.did,
+          cursor,
+          limit: PAGE_SIZE,
+        })
       records = records.concat(
         res.records.filter(record => record.value.subject === this.subject),
       )
@@ -99,7 +110,7 @@ export class ListMembershipModel {
     })
   }
 
-  async updateTo(uris: string) {
+  async updateTo(uris: string[]) {
     for (const uri of uris) {
       await this.add(uri)
     }
diff --git a/src/state/models/content/list.ts b/src/state/models/content/list.ts
index 673ee9430..3913d3e62 100644
--- a/src/state/models/content/list.ts
+++ b/src/state/models/content/list.ts
@@ -4,6 +4,7 @@ import {
   AppBskyGraphGetList as GetList,
   AppBskyGraphDefs as GraphDefs,
   AppBskyGraphList,
+  AppBskyGraphListitem,
 } from '@atproto/api'
 import {Image as RNImage} from 'react-native-image-crop-picker'
 import {RootStoreModel} from '../root-store'
@@ -13,6 +14,16 @@ import {bundleAsync} from 'lib/async/bundle'
 
 const PAGE_SIZE = 30
 
+interface ListitemRecord {
+  uri: string
+  value: AppBskyGraphListitem.Record
+}
+
+interface ListitemListResponse {
+  cursor?: string
+  records: ListitemRecord[]
+}
+
 export class ListModel {
   // state
   isLoading = false
@@ -33,7 +44,7 @@ export class ListModel {
       name,
       description,
       avatar,
-    }: {name: string; description: string; avatar: RNImage | undefined},
+    }: {name: string; description: string; avatar: RNImage | null | undefined},
   ) {
     const record: AppBskyGraphList.Record = {
       purpose: 'app.bsky.graph.defs#modlist',
@@ -124,6 +135,9 @@ export class ListModel {
     description: string
     avatar: RNImage | null | undefined
   }) {
+    if (!this.list) {
+      return
+    }
     if (!this.isOwner) {
       throw new Error('Cannot edit this list')
     }
@@ -157,15 +171,20 @@ export class ListModel {
   }
 
   async delete() {
+    if (!this.list) {
+      return
+    }
+
     // fetch all the listitem records that belong to this list
     let cursor
-    let records = []
+    let records: ListitemRecord[] = []
     for (let i = 0; i < 100; i++) {
-      const res = await this.rootStore.agent.app.bsky.graph.listitem.list({
-        repo: this.rootStore.me.did,
-        cursor,
-        limit: PAGE_SIZE,
-      })
+      const res: ListitemListResponse =
+        await this.rootStore.agent.app.bsky.graph.listitem.list({
+          repo: this.rootStore.me.did,
+          cursor,
+          limit: PAGE_SIZE,
+        })
       records = records.concat(
         res.records.filter(record => record.value.list === this.uri),
       )
@@ -193,6 +212,9 @@ export class ListModel {
   }
 
   async subscribe() {
+    if (!this.list) {
+      return
+    }
     await this.rootStore.agent.app.bsky.graph.muteActorList({
       list: this.list.uri,
     })
@@ -200,6 +222,9 @@ export class ListModel {
   }
 
   async unsubscribe() {
+    if (!this.list) {
+      return
+    }
     await this.rootStore.agent.app.bsky.graph.unmuteActorList({
       list: this.list.uri,
     })
diff --git a/src/state/models/discovery/foafs.ts b/src/state/models/discovery/foafs.ts
index f6e3157b7..4bbd32807 100644
--- a/src/state/models/discovery/foafs.ts
+++ b/src/state/models/discovery/foafs.ts
@@ -1,4 +1,7 @@
-import {AppBskyActorDefs} from '@atproto/api'
+import {
+  AppBskyActorDefs,
+  AppBskyGraphGetFollows as GetFollows,
+} from '@atproto/api'
 import {makeAutoObservable, runInAction} from 'mobx'
 import sampleSize from 'lodash.samplesize'
 import {bundleAsync} from 'lib/async/bundle'
@@ -43,11 +46,12 @@ export class FoafsModel {
       {
         let cursor
         for (let i = 0; i < 10; i++) {
-          const res = await this.rootStore.agent.getFollows({
-            actor: this.rootStore.me.did,
-            cursor,
-            limit: 100,
-          })
+          const res: GetFollows.Response =
+            await this.rootStore.agent.getFollows({
+              actor: this.rootStore.me.did,
+              cursor,
+              limit: 100,
+            })
           this.rootStore.me.follows.hydrateProfiles(res.data.follows)
           if (!res.data.cursor) {
             break
diff --git a/src/state/models/feeds/post.ts b/src/state/models/feeds/post.ts
index 0c411d448..18a90ee82 100644
--- a/src/state/models/feeds/post.ts
+++ b/src/state/models/feeds/post.ts
@@ -67,7 +67,7 @@ export class PostsFeedItemModel {
   }
 
   get rootUri(): string {
-    if (this.reply?.root.uri) {
+    if (typeof this.reply?.root.uri === 'string') {
       return this.reply.root.uri
     }
     return this.post.uri
diff --git a/src/state/models/lists/lists-list.ts b/src/state/models/lists/lists-list.ts
index 309ab0e03..6618c3bf6 100644
--- a/src/state/models/lists/lists-list.ts
+++ b/src/state/models/lists/lists-list.ts
@@ -61,7 +61,7 @@ export class ListsListModel {
     }
     this._xLoading(replace)
     try {
-      let res
+      let res: GetLists.Response
       if (this.source === 'my-modlists') {
         res = {
           success: true,
@@ -170,7 +170,7 @@ async function fetchAllUserLists(
 
   let cursor
   for (let i = 0; i < 100; i++) {
-    const res = await store.agent.app.bsky.graph.getLists({
+    const res: GetLists.Response = await store.agent.app.bsky.graph.getLists({
       actor: did,
       cursor,
       limit: 50,
@@ -199,10 +199,11 @@ async function fetchAllMyMuteLists(
 
   let cursor
   for (let i = 0; i < 100; i++) {
-    const res = await store.agent.app.bsky.graph.getListMutes({
-      cursor,
-      limit: 50,
-    })
+    const res: GetListMutes.Response =
+      await store.agent.app.bsky.graph.getListMutes({
+        cursor,
+        limit: 50,
+      })
     cursor = res.data.cursor
     acc.data.lists = acc.data.lists.concat(res.data.lists)
     if (!cursor) {
diff --git a/src/state/models/ui/shell.ts b/src/state/models/ui/shell.ts
index a77ffbdfb..3853f2395 100644
--- a/src/state/models/ui/shell.ts
+++ b/src/state/models/ui/shell.ts
@@ -8,6 +8,12 @@ import {ImageModel} from '../media/image'
 import {ListModel} from '../content/list'
 import {GalleryModel} from '../media/gallery'
 
+export type ColorMode = 'system' | 'light' | 'dark'
+
+export function isColorMode(v: unknown): v is ColorMode {
+  return v === 'system' || v === 'light' || v === 'dark'
+}
+
 export interface ConfirmModal {
   name: 'confirm'
   title: string
@@ -189,7 +195,7 @@ export interface ComposerOpts {
 }
 
 export class ShellUiModel {
-  colorMode = 'system'
+  colorMode: ColorMode = 'system'
   minimalShellMode = false
   isDrawerOpen = false
   isDrawerSwipeDisabled = false
@@ -216,13 +222,13 @@ export class ShellUiModel {
 
   hydrate(v: unknown) {
     if (isObj(v)) {
-      if (hasProp(v, 'colorMode') && typeof v.colorMode === 'string') {
+      if (hasProp(v, 'colorMode') && isColorMode(v.colorMode)) {
         this.colorMode = v.colorMode
       }
     }
   }
 
-  setColorMode(mode: string) {
+  setColorMode(mode: ColorMode) {
     this.colorMode = mode
   }
 
diff --git a/src/view/com/composer/useExternalLinkFetch.ts b/src/view/com/composer/useExternalLinkFetch.ts
index 8d3b8cac2..91f4da059 100644
--- a/src/view/com/composer/useExternalLinkFetch.ts
+++ b/src/view/com/composer/useExternalLinkFetch.ts
@@ -1,5 +1,6 @@
 import {useState, useEffect} from 'react'
 import {useStores} from 'state/index'
+import {ImageModel} from 'state/models/media/image'
 import * as apilib from 'lib/api/index'
 import {getLinkMeta} from 'lib/link-meta/link-meta'
 import {getPostAsQuote, getFeedAsEmbed} from 'lib/link-meta/bsky'
@@ -90,7 +91,9 @@ export function useExternalLinkFetch({
           setExtLink({
             ...extLink,
             isLoading: false, // done
-            localThumb,
+            localThumb: localThumb
+              ? new ImageModel(store, localThumb)
+              : undefined,
           })
         })
       return cleanup
diff --git a/src/view/com/lightbox/Lightbox.tsx b/src/view/com/lightbox/Lightbox.tsx
index c4bc88cf1..18440c55d 100644
--- a/src/view/com/lightbox/Lightbox.tsx
+++ b/src/view/com/lightbox/Lightbox.tsx
@@ -27,14 +27,14 @@ export const Lightbox = observer(function Lightbox() {
       }
 
       let altText = ''
-      let uri
+      let uri = ''
       if (lightbox.name === 'images') {
-        const opts = store.shell.activeLightbox as models.ImagesLightbox
+        const opts = lightbox as models.ImagesLightbox
         uri = opts.images[imageIndex].uri
-        altText = opts.images[imageIndex].alt
-      } else if (store.shell.activeLightbox.name === 'profile-image') {
-        const opts = store.shell.activeLightbox as models.ProfileImageLightbox
-        uri = opts.profileView.avatar
+        altText = opts.images[imageIndex].alt || ''
+      } else if (lightbox.name === 'profile-image') {
+        const opts = lightbox as models.ProfileImageLightbox
+        uri = opts.profileView.avatar || ''
       }
 
       return (
diff --git a/src/view/com/modals/CreateOrEditMuteList.tsx b/src/view/com/modals/CreateOrEditMuteList.tsx
index 736deae74..5e5130b3c 100644
--- a/src/view/com/modals/CreateOrEditMuteList.tsx
+++ b/src/view/com/modals/CreateOrEditMuteList.tsx
@@ -44,11 +44,11 @@ export function Component({
   const {track} = useAnalytics()
 
   const [isProcessing, setProcessing] = useState<boolean>(false)
-  const [name, setName] = useState<string>(list?.list.name || '')
+  const [name, setName] = useState<string>(list?.list?.name || '')
   const [description, setDescription] = useState<string>(
-    list?.list.description || '',
+    list?.list?.description || '',
   )
-  const [avatar, setAvatar] = useState<string | undefined>(list?.list.avatar)
+  const [avatar, setAvatar] = useState<string | undefined>(list?.list?.avatar)
   const [newAvatar, setNewAvatar] = useState<RNImage | undefined | null>()
 
   const onPressCancel = useCallback(() => {
@@ -59,7 +59,7 @@ export function Component({
     async (img: RNImage | null) => {
       if (!img) {
         setNewAvatar(null)
-        setAvatar(null)
+        setAvatar(undefined)
         return
       }
       track('CreateMuteList:AvatarSelected')
diff --git a/src/view/com/modals/ListAddRemoveUser.tsx b/src/view/com/modals/ListAddRemoveUser.tsx
index 91fe67c17..e1677d25c 100644
--- a/src/view/com/modals/ListAddRemoveUser.tsx
+++ b/src/view/com/modals/ListAddRemoveUser.tsx
@@ -36,7 +36,7 @@ export const Component = observer(
     const pal = usePalette('default')
     const palPrimary = usePalette('primary')
     const palInverted = usePalette('inverted')
-    const [selected, setSelected] = React.useState([])
+    const [selected, setSelected] = React.useState<string[]>([])
 
     const listsList: ListsListModel = React.useMemo(
       () => new ListsListModel(store, store.me.did),
diff --git a/src/view/com/profile/ProfileCard.tsx b/src/view/com/profile/ProfileCard.tsx
index 42c4edef5..50b9f199c 100644
--- a/src/view/com/profile/ProfileCard.tsx
+++ b/src/view/com/profile/ProfileCard.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import * as React from 'react'
 import {StyleSheet, View} from 'react-native'
 import {observer} from 'mobx-react-lite'
 import {AppBskyActorDefs} from '@atproto/api'
@@ -32,7 +32,9 @@ export const ProfileCard = observer(
     noBorder?: boolean
     followers?: AppBskyActorDefs.ProfileView[] | undefined
     overrideModeration?: boolean
-    renderButton?: (profile: AppBskyActorDefs.ProfileViewBasic) => JSX.Element
+    renderButton?: (
+      profile: AppBskyActorDefs.ProfileViewBasic,
+    ) => React.ReactNode
   }) => {
     const store = useStores()
     const pal = usePalette('default')
diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx
index 9b4df0989..46a6bb235 100644
--- a/src/view/com/profile/ProfileHeader.tsx
+++ b/src/view/com/profile/ProfileHeader.tsx
@@ -587,9 +587,9 @@ const styles = StyleSheet.create({
   // Word wrapping appears fine on
   // mobile but overflows on desktop
   handle: isNative
-    ? undefined
+    ? {}
     : {
-        // eslint-disable-next-line
+        // @ts-ignore web only -prf
         wordBreak: 'break-all',
       },
 
diff --git a/src/view/com/util/BlurView.web.tsx b/src/view/com/util/BlurView.web.tsx
index 5267e6ade..d1fb4665f 100644
--- a/src/view/com/util/BlurView.web.tsx
+++ b/src/view/com/util/BlurView.web.tsx
@@ -15,6 +15,7 @@ export const BlurView = ({
 }: React.PropsWithChildren<BlurViewProps>) => {
   // @ts-ignore using an RNW-specific attribute here -prf
   let blur = `blur(${blurAmount || 10}px`
+  // @ts-ignore using an RNW-specific attribute here -prf
   style = addStyle(style, {backdropFilter: blur, WebkitBackdropFilter: blur})
   if (blurType === 'dark') {
     style = addStyle(style, styles.dark)
diff --git a/src/view/com/util/Html.tsx b/src/view/com/util/Html.tsx
index dbf24a83a..8d3f29fb0 100644
--- a/src/view/com/util/Html.tsx
+++ b/src/view/com/util/Html.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import * as React from 'react'
 import {StyleSheet, View} from 'react-native'
 import {usePalette} from 'lib/hooks/usePalette'
 import {Text} from './text/Text'
@@ -10,6 +10,15 @@ import {isDesktopWeb} from 'platform/detection'
  * DSL. See for instance /locale/en/privacy-policy.tsx
  */
 
+interface IsChildProps {
+  isChild?: boolean
+}
+
+// type ReactNodeWithIsChildProp =
+//   | React.ReactElement<IsChildProps>
+//   | React.ReactElement<IsChildProps>[]
+//   | React.ReactNode
+
 export function H1({children}: React.PropsWithChildren<{}>) {
   const pal = usePalette('default')
   return (
@@ -55,10 +64,7 @@ export function P({children}: React.PropsWithChildren<{}>) {
   )
 }
 
-export function UL({
-  children,
-  isChild,
-}: React.PropsWithChildren<{isChild: boolean}>) {
+export function UL({children, isChild}: React.PropsWithChildren<IsChildProps>) {
   return (
     <View style={[styles.ul, isChild && styles.ulChild]}>
       {markChildProps(children)}
@@ -66,10 +72,7 @@ export function UL({
   )
 }
 
-export function OL({
-  children,
-  isChild,
-}: React.PropsWithChildren<{isChild: boolean}>) {
+export function OL({children, isChild}: React.PropsWithChildren<IsChildProps>) {
   return (
     <View style={[styles.ol, isChild && styles.olChild]}>
       {markChildProps(children)}
@@ -122,10 +125,13 @@ export function EM({children}: React.PropsWithChildren<{}>) {
   )
 }
 
-function markChildProps(children) {
+function markChildProps(children: React.ReactNode) {
   return React.Children.map(children, child => {
     if (React.isValidElement(child)) {
-      return React.cloneElement(child, {isChild: true})
+      return React.cloneElement<IsChildProps>(
+        child as React.ReactElement<IsChildProps>,
+        {isChild: true},
+      )
     }
     return child
   })
diff --git a/src/view/com/util/UserInfoText.tsx b/src/view/com/util/UserInfoText.tsx
index b8f6e082e..b737b2b1e 100644
--- a/src/view/com/util/UserInfoText.tsx
+++ b/src/view/com/util/UserInfoText.tsx
@@ -70,7 +70,9 @@ export function UserInfoText({
         numberOfLines={1}
         href={`/profile/${profile.handle}`}
         text={`${prefix || ''}${sanitizeDisplayName(
-          profile[attr] || profile.handle,
+          typeof profile[attr] === 'string' && profile[attr]
+            ? (profile[attr] as string)
+            : profile.handle,
         )}`}
       />
     )
diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx
index 428822339..798893855 100644
--- a/src/view/screens/Settings.tsx
+++ b/src/view/screens/Settings.tsx
@@ -38,6 +38,7 @@ import {NavigationProp} from 'lib/routes/types'
 import {isDesktopWeb} from 'platform/detection'
 import {pluralize} from 'lib/strings/helpers'
 import {formatCount} from 'view/com/util/numeric/format'
+import {isColorMode} from 'state/models/ui/shell'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'>
 export const SettingsScreen = withAuthRequired(
@@ -299,20 +300,26 @@ export const SettingsScreen = withAuthRequired(
                 value="system"
                 label="System"
                 left
-                onChange={(v: string) => store.shell.setColorMode(v)}
+                onChange={(v: string) =>
+                  store.shell.setColorMode(isColorMode(v) ? v : 'system')
+                }
               />
               <SelectableBtn
                 current={store.shell.colorMode}
                 value="light"
                 label="Light"
-                onChange={(v: string) => store.shell.setColorMode(v)}
+                onChange={(v: string) =>
+                  store.shell.setColorMode(isColorMode(v) ? v : 'system')
+                }
               />
               <SelectableBtn
                 current={store.shell.colorMode}
                 value="dark"
                 label="Dark"
                 right
-                onChange={(v: string) => store.shell.setColorMode(v)}
+                onChange={(v: string) =>
+                  store.shell.setColorMode(isColorMode(v) ? v : 'system')
+                }
               />
             </View>
           </View>
diff --git a/src/view/shell/desktop/LeftNav.tsx b/src/view/shell/desktop/LeftNav.tsx
index 8c701ea4e..9f047418b 100644
--- a/src/view/shell/desktop/LeftNav.tsx
+++ b/src/view/shell/desktop/LeftNav.tsx
@@ -34,7 +34,7 @@ import {
   SatelliteDishIconSolid,
 } from 'lib/icons'
 import {getCurrentRoute, isTab, isStateAtTabRoot} from 'lib/routes/helpers'
-import {NavigationProp} from 'lib/routes/types'
+import {NavigationProp, CommonNavigatorParams} from 'lib/routes/types'
 import {router} from '../../../routes'
 
 const ProfileCard = observer(() => {
@@ -100,7 +100,8 @@ const NavItem = observer(
     let isCurrent =
       currentRouteInfo.name === 'Profile'
         ? isTab(currentRouteInfo.name, pathName) &&
-          currentRouteInfo.params.name === store.me.handle
+          (currentRouteInfo.params as CommonNavigatorParams['Profile']).name ===
+            store.me.handle
         : isTab(currentRouteInfo.name, pathName)
     const {onPress} = useLinkProps({to: href})
     const onPressWrapped = React.useCallback(
@@ -122,6 +123,7 @@ const NavItem = observer(
       <PressableWithHover
         style={styles.navItemWrapper}
         hoverStyle={pal.viewLight}
+        // @ts-ignore the function signature differs on web -prf
         onPress={onPressWrapped}
         // @ts-ignore web only -prf
         href={href}