Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into left-nav-desktop
Browse files Browse the repository at this point in the history
* origin/main:
  Adjust line height to not cut off emoji (#5496)
  Emoji in account list (#5497)
  Make the counter more rounded (#5083)
  add emoji prop to composer reply to text (#5495)
  Fix banner height in edit profile modal (#5494)
  Messages list - make avatars link to profile (#5484)
  Add back empty placeholder (#5489)
  Filter errors that get sent to Sentry (#5247)
  Add language filtering UI to search (#5459)
  • Loading branch information
estrattonbailey committed Sep 26, 2024
2 parents 84a36e3 + 1895ae2 commit 1e3cea4
Show file tree
Hide file tree
Showing 17 changed files with 498 additions and 194 deletions.
14 changes: 7 additions & 7 deletions __tests__/lib/errors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ describe('isNetworkError', () => {
]
const outputs = [true, false, false, true]

it('correctly distinguishes network errors', () => {
for (let i = 0; i < inputs.length; i++) {
const input = inputs[i]
const result = isNetworkError(input)
expect(result).toEqual(outputs[i])
}
})
for (let i = 0; i < inputs.length; i++) {
const input = inputs[i]
const output = outputs[i]
it(`correctly distinguishes network errors for ${input}`, () => {
expect(isNetworkError(input)).toEqual(output)
})
}
})
3 changes: 3 additions & 0 deletions src/alf/themes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ export function createThemes({
} as const

const light: Theme = {
scheme: 'light',
name: 'light',
palette: lightPalette,
atoms: {
Expand Down Expand Up @@ -390,6 +391,7 @@ export function createThemes({
}

const dark: Theme = {
scheme: 'dark',
name: 'dark',
palette: darkPalette,
atoms: {
Expand Down Expand Up @@ -479,6 +481,7 @@ export function createThemes({

const dim: Theme = {
...dark,
scheme: 'dark',
name: 'dim',
palette: dimPalette,
atoms: {
Expand Down
1 change: 1 addition & 0 deletions src/alf/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ export type ThemedAtoms = {
}
}
export type Theme = {
scheme: 'light' | 'dark' // for library support
name: ThemeName
palette: Palette
atoms: ThemedAtoms
Expand Down
6 changes: 4 additions & 2 deletions src/components/AccountList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,12 @@ function AccountItem({
<UserAvatar avatar={profile?.avatar} size={24} />
</View>
<Text style={[a.align_baseline, a.flex_1, a.flex_row, a.py_sm]}>
<Text style={[a.font_bold]}>
<Text emoji style={[a.font_bold]}>
{profile?.displayName || account.handle}{' '}
</Text>
<Text style={[t.atoms.text_contrast_medium]}>{account.handle}</Text>
<Text emoji style={[t.atoms.text_contrast_medium]}>
{account.handle}
</Text>
</Text>
{isCurrentAccount ? (
<Check
Expand Down
23 changes: 16 additions & 7 deletions src/components/forms/TextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ export function createInput(Component: typeof TextInput) {
placeholder,
value,
onChangeText,
onFocus,
onBlur,
isInvalid,
inputRef,
style,
Expand Down Expand Up @@ -173,8 +175,14 @@ export function createInput(Component: typeof TextInput) {
ref={refs}
value={value}
onChangeText={onChangeText}
onFocus={ctx.onFocus}
onBlur={ctx.onBlur}
onFocus={e => {
ctx.onFocus()
onFocus?.(e)
}}
onBlur={e => {
ctx.onBlur()
onBlur?.(e)
}}
placeholder={placeholder || label}
placeholderTextColor={t.palette.contrast_500}
keyboardAppearance={t.name === 'light' ? 'light' : 'dark'}
Expand All @@ -188,22 +196,23 @@ export function createInput(Component: typeof TextInput) {
a.px_xs,
{
// paddingVertical doesn't work w/multiline - esb
paddingTop: 14,
paddingBottom: 14,
paddingTop: 12,
paddingBottom: 13,
lineHeight: a.text_md.fontSize * 1.1875,
textAlignVertical: rest.multiline ? 'top' : undefined,
minHeight: rest.multiline ? 80 : undefined,
minWidth: 0,
},
// fix for autofill styles covering border
web({
paddingTop: 12,
paddingBottom: 12,
paddingTop: 10,
paddingBottom: 11,
marginTop: 2,
marginBottom: 2,
}),
android({
paddingBottom: 16,
paddingTop: 8,
paddingBottom: 8,
}),
style,
]}
Expand Down
18 changes: 13 additions & 5 deletions src/lib/strings/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,19 @@ export function cleanError(str: any): string {
return str
}

const NETWORK_ERRORS = [
'Abort',
'Network request failed',
'Failed to fetch',
'Load failed',
]

export function isNetworkError(e: unknown) {
const str = String(e)
return (
str.includes('Abort') ||
str.includes('Network request failed') ||
str.includes('Failed to fetch')
)
for (const err of NETWORK_ERRORS) {
if (str.includes(err)) {
return true
}
}
return false
}
10 changes: 8 additions & 2 deletions src/logger/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import format from 'date-fns/format'
import {nanoid} from 'nanoid/non-secure'

import {Sentry} from '#/logger/sentry'
import * as env from '#/env'
import {isNetworkError} from '#/lib/strings/errors'
import {DebugContext} from '#/logger/debugContext'
import {add} from '#/logger/logDump'
import {Sentry} from '#/logger/sentry'
import * as env from '#/env'

export enum LogLevel {
Debug = 'debug',
Expand Down Expand Up @@ -160,6 +161,11 @@ export const sentryTransport: Transport = (
timestamp: timestamp / 1000, // Sentry expects seconds
})

// We don't want to send any network errors to sentry
if (isNetworkError(message)) {
return
}

/**
* Send all higher levels with `captureMessage`, with appropriate severity
* level
Expand Down
25 changes: 18 additions & 7 deletions src/screens/Messages/List/ChatListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ import {useProfileShadow} from '#/state/cache/profile-shadow'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useSession} from '#/state/session'
import {TimeElapsed} from '#/view/com/util/TimeElapsed'
import {UserAvatar} from '#/view/com/util/UserAvatar'
import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
import * as tokens from '#/alf/tokens'
import {ConvoMenu} from '#/components/dms/ConvoMenu'
import {Bell2Off_Filled_Corner0_Rounded as BellStroke} from '#/components/icons/Bell2'
import {Link} from '#/components/Link'
Expand Down Expand Up @@ -203,6 +204,19 @@ function ChatListItemReady({
onFocus={onFocus}
onBlur={onMouseLeave}
style={[a.relative]}>
<View
style={[
a.z_10,
a.absolute,
{top: tokens.space.md, left: tokens.space.lg},
]}>
<PreviewableUserAvatar
profile={profile}
size={52}
moderation={moderation.ui('avatar')}
/>
</View>

<Link
to={`/messages/${convo.id}`}
label={displayName}
Expand Down Expand Up @@ -236,11 +250,8 @@ function ChatListItemReady({
(hovered || pressed || focused) && t.atoms.bg_contrast_25,
t.atoms.border_contrast_low,
]}>
<UserAvatar
avatar={profile.avatar}
size={52}
moderation={moderation.ui('avatar')}
/>
{/* Avatar goes here */}
<View style={{width: 52, height: 52}} />

<View style={[a.flex_1, a.justify_center, web({paddingRight: 45})]}>
<View style={[a.w_full, a.flex_row, a.align_end, a.pb_2xs]}>
Expand Down Expand Up @@ -357,7 +368,7 @@ function ChatListItemReady({
a.self_end,
a.justify_center,
{
right: a.px_lg.paddingRight,
right: tokens.space.lg,
opacity: !gtMobile || showActions || menuControl.isOpen ? 1 : 0,
},
]}
Expand Down
43 changes: 43 additions & 0 deletions src/screens/Search/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {describe, expect, it} from '@jest/globals'

import {parseSearchQuery} from '#/screens/Search/utils'

describe(`parseSearchQuery`, () => {
const tests = [
{
input: `bluesky`,
output: {query: `bluesky`, params: {}},
},
{
input: `bluesky from:esb.lol`,
output: {query: `bluesky`, params: {from: `esb.lol`}},
},
{
input: `bluesky "from:esb.lol"`,
output: {query: `bluesky "from:esb.lol"`, params: {}},
},
{
input: `bluesky mentions:@esb.lol`,
output: {query: `bluesky`, params: {mentions: `@esb.lol`}},
},
{
input: `bluesky since:2021-01-01:00:00:00`,
output: {query: `bluesky`, params: {since: `2021-01-01:00:00:00`}},
},
{
input: `bluesky lang:"en"`,
output: {query: `bluesky`, params: {lang: `en`}},
},
{
input: `bluesky "literal" lang:en "from:invalid"`,
output: {query: `bluesky "literal" "from:invalid"`, params: {lang: `en`}},
},
]

it.each(tests)(
`$input -> $output.query $output.params`,
({input, output}) => {
expect(parseSearchQuery(input)).toEqual(output)
},
)
})
43 changes: 43 additions & 0 deletions src/screens/Search/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export type Params = Record<string, string>

export function parseSearchQuery(rawQuery: string) {
let base = rawQuery
const rawLiterals = rawQuery.match(/[^:\w\d]".+?"/gi) || []

// remove literals from base
for (const literal of rawLiterals) {
base = base.replace(literal.trim(), '')
}

// find remaining params in base
const rawParams = base.match(/[a-z]+:[a-z-\.@\d:"]+/gi) || []

for (const param of rawParams) {
base = base.replace(param, '')
}

base = base.trim()

const params = rawParams.reduce((params, param) => {
const [name, ...value] = param.split(/:/)
params[name] = value.join(':').replace(/"/g, '') // dates can contain additional colons
return params
}, {} as Params)
const literals = rawLiterals.map(l => String(l).trim())

return {
query: [base, literals.join(' ')].filter(Boolean).join(' '),
params,
}
}

export function makeSearchQuery(query: string, params: Params) {
return [
query,
Object.entries(params)
.map(([name, value]) => `${name}:${value}`)
.join(' '),
]
.filter(Boolean)
.join(' ')
}
17 changes: 9 additions & 8 deletions src/view/com/composer/ComposerReplyTo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import {
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'

import {sanitizeDisplayName} from 'lib/strings/display-names'
import {sanitizeHandle} from 'lib/strings/handles'
import {ComposerOptsPostRef} from 'state/shell/composer'
import {QuoteEmbed} from 'view/com/util/post-embeds/QuoteEmbed'
import {Text} from 'view/com/util/text/Text'
import {PreviewableUserAvatar} from 'view/com/util/UserAvatar'
import {sanitizeDisplayName} from '#/lib/strings/display-names'
import {sanitizeHandle} from '#/lib/strings/handles'
import {ComposerOptsPostRef} from '#/state/shell/composer'
import {QuoteEmbed} from '#/view/com/util/post-embeds/QuoteEmbed'
import {Text} from '#/view/com/util/text/Text'
import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
import {atoms as a, useTheme} from '#/alf'

export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
Expand Down Expand Up @@ -91,7 +91,7 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
type={replyTo.author.associated?.labeler ? 'labeler' : 'user'}
/>
<View style={styles.replyToPost}>
<Text type="xl-medium" style={t.atoms.text} numberOfLines={1}>
<Text type="xl-medium" style={t.atoms.text} numberOfLines={1} emoji>
{sanitizeDisplayName(
replyTo.author.displayName || sanitizeHandle(replyTo.author.handle),
)}
Expand All @@ -101,7 +101,8 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
<Text
type="post-text"
style={t.atoms.text}
numberOfLines={!showFull ? 6 : undefined}>
numberOfLines={!showFull ? 6 : undefined}
emoji>
{replyTo.text}
</Text>
</View>
Expand Down
8 changes: 4 additions & 4 deletions src/view/com/modals/EditProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ import {logger} from '#/logger'
import {isWeb} from '#/platform/detection'
import {useModalControls} from '#/state/modals'
import {useProfileUpdateMutation} from '#/state/queries/profile'
import {Text} from '#/view/com/util/text/Text'
import * as Toast from '#/view/com/util/Toast'
import {EditableUserAvatar} from '#/view/com/util/UserAvatar'
import {UserBanner} from '#/view/com/util/UserBanner'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {Text} from '../util/text/Text'
import * as Toast from '../util/Toast'
import {EditableUserAvatar} from '../util/UserAvatar'
import {UserBanner} from '../util/UserBanner'

const AnimatedTouchableOpacity =
Animated.createAnimatedComponent(TouchableOpacity)
Expand Down
Loading

0 comments on commit 1e3cea4

Please sign in to comment.