Resolve all remaining lint issues (#88)
* Rework 'navIdx' variables from number arrays to strings to avoid equality-check failures in react hooks * Resolve all remaining lint issues * Fix tests * Use node v18 in gh action test
This commit is contained in:
parent
3a90114f3a
commit
f36c956536
60 changed files with 478 additions and 482 deletions
|
@ -297,7 +297,7 @@ export const ComposePost = observer(function ComposePost({
|
|||
)
|
||||
}
|
||||
})
|
||||
}, [text, pal.link])
|
||||
}, [text, pal.link, pal.text])
|
||||
|
||||
return (
|
||||
<KeyboardAvoidingView
|
||||
|
@ -393,7 +393,7 @@ export const ComposePost = observer(function ComposePost({
|
|||
ref={textInput}
|
||||
multiline
|
||||
scrollEnabled
|
||||
onChangeText={(text: string) => onChangeText(text)}
|
||||
onChangeText={(str: string) => onChangeText(str)}
|
||||
onPaste={onPaste}
|
||||
placeholder={selectTextInputPlaceholder}
|
||||
placeholderTextColor={pal.colors.textLight}
|
||||
|
@ -475,7 +475,7 @@ export const ComposePost = observer(function ComposePost({
|
|||
)
|
||||
})
|
||||
|
||||
const atPrefixRegex = /@([a-z0-9\.]*)$/i
|
||||
const atPrefixRegex = /@([a-z0-9.]*)$/i
|
||||
function extractTextAutocompletePrefix(text: string) {
|
||||
const match = atPrefixRegex.exec(text)
|
||||
if (match) {
|
||||
|
|
|
@ -39,7 +39,7 @@ export const SuggestedFollows = observer(
|
|||
// Using default import (React.use...) instead of named import (use...) to be able to mock store's data in jest environment
|
||||
const view = React.useMemo<SuggestedActorsViewModel>(
|
||||
() => new SuggestedActorsViewModel(store),
|
||||
[],
|
||||
[store],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -54,7 +54,7 @@ export const SuggestedFollows = observer(
|
|||
if (!view.isLoading && !view.hasError && !view.hasContent) {
|
||||
onNoSuggestions?.()
|
||||
}
|
||||
}, [view, view.isLoading, view.hasError, view.hasContent])
|
||||
}, [view, view.isLoading, view.hasError, view.hasContent, onNoSuggestions])
|
||||
|
||||
const onPressTryAgain = () =>
|
||||
view
|
||||
|
@ -128,7 +128,7 @@ export const SuggestedFollows = observer(
|
|||
keyExtractor={item => item._reactKey}
|
||||
renderItem={renderItem}
|
||||
style={s.flex1}
|
||||
contentContainerStyle={{paddingBottom: 200}}
|
||||
contentContainerStyle={s.contentContainer}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
|
|
|
@ -207,12 +207,7 @@ const ChooseAccountForm = ({
|
|||
style={[pal.borderDark, styles.group]}
|
||||
onPress={() => onSelectAccount(undefined)}>
|
||||
<View style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
|
||||
<View style={s.p10}>
|
||||
<View
|
||||
style={[pal.btn, {width: 30, height: 30, borderRadius: 15}]}
|
||||
/>
|
||||
</View>
|
||||
<Text style={styles.accountText}>
|
||||
<Text style={[styles.accountText, styles.accountTextOther]}>
|
||||
<Text type="lg" style={pal.text}>
|
||||
Other account
|
||||
</Text>
|
||||
|
@ -556,7 +551,7 @@ const ForgotPasswordForm = ({
|
|||
{!serviceDescription || isProcessing ? (
|
||||
<ActivityIndicator />
|
||||
) : !email ? (
|
||||
<Text type="xl-bold" style={[pal.link, s.pr5, {opacity: 0.5}]}>
|
||||
<Text type="xl-bold" style={[pal.link, s.pr5, styles.dimmed]}>
|
||||
Next
|
||||
</Text>
|
||||
) : (
|
||||
|
@ -691,7 +686,7 @@ const SetNewPasswordForm = ({
|
|||
{isProcessing ? (
|
||||
<ActivityIndicator />
|
||||
) : !resetCode || !password ? (
|
||||
<Text type="xl-bold" style={[pal.link, s.pr5, {opacity: 0.5}]}>
|
||||
<Text type="xl-bold" style={[pal.link, s.pr5, styles.dimmed]}>
|
||||
Next
|
||||
</Text>
|
||||
) : (
|
||||
|
@ -810,6 +805,9 @@ const styles = StyleSheet.create({
|
|||
alignItems: 'baseline',
|
||||
paddingVertical: 10,
|
||||
},
|
||||
accountTextOther: {
|
||||
paddingLeft: 12,
|
||||
},
|
||||
error: {
|
||||
backgroundColor: colors.red4,
|
||||
flexDirection: 'row',
|
||||
|
@ -832,4 +830,5 @@ const styles = StyleSheet.create({
|
|||
justifyContent: 'center',
|
||||
marginRight: 5,
|
||||
},
|
||||
dimmed: {opacity: 0.5},
|
||||
})
|
||||
|
|
|
@ -121,7 +121,7 @@ export function Component({
|
|||
</View>
|
||||
</View>
|
||||
{error !== '' && (
|
||||
<View style={{marginTop: 20}}>
|
||||
<View style={styles.errorContainer}>
|
||||
<ErrorMessage message={error} />
|
||||
</View>
|
||||
)}
|
||||
|
@ -231,4 +231,5 @@ const styles = StyleSheet.create({
|
|||
marginBottom: 36,
|
||||
marginHorizontal: -14,
|
||||
},
|
||||
errorContainer: {marginTop: 20},
|
||||
})
|
||||
|
|
|
@ -56,7 +56,7 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
|
|||
</View>
|
||||
<View style={styles.group}>
|
||||
<Text style={styles.label}>Other service</Text>
|
||||
<View style={{flexDirection: 'row'}}>
|
||||
<View style={s.flexRow}>
|
||||
<BottomSheetTextInput
|
||||
testID="customServerTextInput"
|
||||
style={styles.textInput}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import React from 'react'
|
||||
import {observer} from 'mobx-react-lite'
|
||||
import {View, FlatList} from 'react-native'
|
||||
import {FlatList, StyleSheet, View} from 'react-native'
|
||||
import {NotificationsViewModel} from '../../../state/models/notifications-view'
|
||||
import {FeedItem} from './FeedItem'
|
||||
import {NotificationFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {EmptyState} from '../util/EmptyState'
|
||||
import {OnScrollCb} from '../../lib/hooks/useOnMainScroll'
|
||||
import {s} from '../../lib/styles'
|
||||
|
||||
const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
|
||||
|
||||
|
@ -29,7 +30,7 @@ export const Feed = observer(function Feed({
|
|||
<EmptyState
|
||||
icon="bell"
|
||||
message="No notifications yet!"
|
||||
style={{paddingVertical: 40}}
|
||||
style={styles.emptyState}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -58,14 +59,10 @@ export const Feed = observer(function Feed({
|
|||
}
|
||||
}
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
<View style={s.h100pct}>
|
||||
{view.isLoading && !data && <NotificationFeedLoadingPlaceholder />}
|
||||
{view.hasError && (
|
||||
<ErrorMessage
|
||||
message={view.error}
|
||||
style={{margin: 6}}
|
||||
onPressTryAgain={onPressTryAgain}
|
||||
/>
|
||||
<ErrorMessage message={view.error} onPressTryAgain={onPressTryAgain} />
|
||||
)}
|
||||
{data && (
|
||||
<FlatList
|
||||
|
@ -76,9 +73,13 @@ export const Feed = observer(function Feed({
|
|||
onRefresh={onRefresh}
|
||||
onEndReached={onEndReached}
|
||||
onScroll={onScroll}
|
||||
contentContainerStyle={{paddingBottom: 200}}
|
||||
contentContainerStyle={s.contentContainer}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
})
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
emptyState: {paddingVertical: 40},
|
||||
})
|
||||
|
|
|
@ -19,14 +19,13 @@ import {TABS_ENABLED} from '../../../build-flags'
|
|||
const Intro = () => (
|
||||
<View style={styles.explainer}>
|
||||
<Text
|
||||
style={[
|
||||
styles.explainerHeading,
|
||||
s.normal,
|
||||
{lineHeight: 60, paddingTop: 50, paddingBottom: 50},
|
||||
]}>
|
||||
Welcome to <Text style={[s.bold, s.blue3, {fontSize: 56}]}>Bluesky</Text>
|
||||
style={[styles.explainerHeading, s.normal, styles.explainerHeadingIntro]}>
|
||||
Welcome to{' '}
|
||||
<Text style={[s.bold, s.blue3, styles.explainerHeadingBrand]}>
|
||||
Bluesky
|
||||
</Text>
|
||||
</Text>
|
||||
<Text style={[styles.explainerDesc, {fontSize: 24}]}>
|
||||
<Text style={[styles.explainerDesc, styles.explainerDescIntro]}>
|
||||
This is an early beta. Your feedback is appreciated!
|
||||
</Text>
|
||||
</View>
|
||||
|
@ -161,11 +160,18 @@ const styles = StyleSheet.create({
|
|||
textAlign: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
explainerHeadingIntro: {
|
||||
lineHeight: 60,
|
||||
paddingTop: 50,
|
||||
paddingBottom: 50,
|
||||
},
|
||||
explainerHeadingBrand: {fontSize: 56},
|
||||
explainerDesc: {
|
||||
fontSize: 18,
|
||||
textAlign: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
explainerDescIntro: {fontSize: 24},
|
||||
explainerImg: {
|
||||
resizeMode: 'contain',
|
||||
maxWidth: '100%',
|
||||
|
|
|
@ -53,11 +53,7 @@ export const PostRepostedBy = observer(function PostRepostedBy({
|
|||
if (view.hasError) {
|
||||
return (
|
||||
<View>
|
||||
<ErrorMessage
|
||||
message={view.error}
|
||||
style={{margin: 6}}
|
||||
onPressTryAgain={onRefresh}
|
||||
/>
|
||||
<ErrorMessage message={view.error} onPressTryAgain={onRefresh} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
} from '../../../state/models/post-thread-view'
|
||||
import {PostThreadItem} from './PostThreadItem'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {s} from '../../lib/styles'
|
||||
|
||||
export const PostThread = observer(function PostThread({
|
||||
uri,
|
||||
|
@ -60,11 +61,7 @@ export const PostThread = observer(function PostThread({
|
|||
if (view.hasError) {
|
||||
return (
|
||||
<View>
|
||||
<ErrorMessage
|
||||
message={view.error}
|
||||
style={{margin: 6}}
|
||||
onPressTryAgain={onRefresh}
|
||||
/>
|
||||
<ErrorMessage message={view.error} onPressTryAgain={onRefresh} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
@ -84,8 +81,8 @@ export const PostThread = observer(function PostThread({
|
|||
onRefresh={onRefresh}
|
||||
onLayout={onLayout}
|
||||
onScrollToIndexFailed={onScrollToIndexFailed}
|
||||
style={{flex: 1}}
|
||||
contentContainerStyle={{paddingBottom: 200}}
|
||||
style={s.h100pct}
|
||||
contentContainerStyle={s.contentContainer}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
|
|
@ -80,7 +80,7 @@ export const PostThreadItem = observer(function PostThreadItem({
|
|||
.catch(e => store.log.error('Failed to toggle upvote', e))
|
||||
}
|
||||
const onCopyPostText = () => {
|
||||
Clipboard.setString(record.text)
|
||||
Clipboard.setString(record?.text || '')
|
||||
Toast.show('Copied to clipboard')
|
||||
}
|
||||
const onDeletePost = () => {
|
||||
|
@ -131,8 +131,8 @@ export const PostThreadItem = observer(function PostThreadItem({
|
|||
</Link>
|
||||
</View>
|
||||
<View style={styles.layoutContent}>
|
||||
<View style={[styles.meta, {paddingTop: 5, paddingBottom: 0}]}>
|
||||
<View style={{flexDirection: 'row', alignItems: 'baseline'}}>
|
||||
<View style={[styles.meta, styles.metaExpandedLine1]}>
|
||||
<View style={[s.flexRow, s.alignBaseline]}>
|
||||
<Link
|
||||
style={styles.metaItem}
|
||||
href={authorHref}
|
||||
|
@ -305,10 +305,8 @@ export const PostThreadItem = observer(function PostThreadItem({
|
|||
lineHeight={1.3}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<View style={{height: 5}} />
|
||||
)}
|
||||
<PostEmbeds embed={item.post.embed} style={{marginBottom: 10}} />
|
||||
) : undefined}
|
||||
<PostEmbeds embed={item.post.embed} style={s.mb10} />
|
||||
<PostCtrls
|
||||
itemHref={itemHref}
|
||||
itemTitle={itemTitle}
|
||||
|
@ -389,6 +387,10 @@ const styles = StyleSheet.create({
|
|||
paddingTop: 2,
|
||||
paddingBottom: 2,
|
||||
},
|
||||
metaExpandedLine1: {
|
||||
paddingTop: 5,
|
||||
paddingBottom: 0,
|
||||
},
|
||||
metaItem: {
|
||||
paddingRight: 5,
|
||||
maxWidth: 240,
|
||||
|
|
|
@ -48,11 +48,7 @@ export const PostVotedBy = observer(function PostVotedBy({
|
|||
if (view.hasError) {
|
||||
return (
|
||||
<View>
|
||||
<ErrorMessage
|
||||
message={view.error}
|
||||
style={{margin: 6}}
|
||||
onPressTryAgain={onRefresh}
|
||||
/>
|
||||
<ErrorMessage message={view.error} onPressTryAgain={onRefresh} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ export const Post = observer(function Post({
|
|||
timestamp={item.post.indexedAt}
|
||||
/>
|
||||
{replyAuthorDid !== '' && (
|
||||
<View style={[s.flexRow, s.mb2, {alignItems: 'center'}]}>
|
||||
<View style={[s.flexRow, s.mb2, s.alignCenter]}>
|
||||
<FontAwesomeIcon
|
||||
icon="reply"
|
||||
size={9}
|
||||
|
@ -187,10 +187,8 @@ export const Post = observer(function Post({
|
|||
lineHeight={1.3}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<View style={{height: 5}} />
|
||||
)}
|
||||
<PostEmbeds embed={item.post.embed} style={{marginBottom: 10}} />
|
||||
) : undefined}
|
||||
<PostEmbeds embed={item.post.embed} style={s.mb10} />
|
||||
<PostCtrls
|
||||
itemHref={itemHref}
|
||||
itemTitle={itemTitle}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, {useState, useEffect} from 'react'
|
||||
import {observer} from 'mobx-react-lite'
|
||||
import {View} from 'react-native'
|
||||
import {StyleSheet, View} from 'react-native'
|
||||
import {LoadingPlaceholder} from '../util/LoadingPlaceholder'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {Text} from '../util/text/Text'
|
||||
|
@ -31,9 +31,9 @@ export const PostText = observer(function PostText({
|
|||
if (!model || model.isLoading || model.uri !== uri) {
|
||||
return (
|
||||
<View>
|
||||
<LoadingPlaceholder width="100%" height={8} style={{marginTop: 6}} />
|
||||
<LoadingPlaceholder width="100%" height={8} style={{marginTop: 6}} />
|
||||
<LoadingPlaceholder width={100} height={8} style={{marginTop: 6}} />
|
||||
<LoadingPlaceholder width="100%" height={8} style={styles.mt6} />
|
||||
<LoadingPlaceholder width="100%" height={8} style={styles.mt6} />
|
||||
<LoadingPlaceholder width={100} height={8} style={styles.mt6} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
@ -56,3 +56,7 @@ export const PostText = observer(function PostText({
|
|||
</View>
|
||||
)
|
||||
})
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
mt6: {marginTop: 6},
|
||||
})
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
View,
|
||||
FlatList,
|
||||
StyleProp,
|
||||
StyleSheet,
|
||||
ViewStyle,
|
||||
} from 'react-native'
|
||||
import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
|
||||
|
@ -14,6 +15,7 @@ import {FeedModel} from '../../../state/models/feed-view'
|
|||
import {FeedItem} from './FeedItem'
|
||||
import {PromptButtons} from './PromptButtons'
|
||||
import {OnScrollCb} from '../../lib/hooks/useOnMainScroll'
|
||||
import {s} from '../../lib/styles'
|
||||
|
||||
const COMPOSE_PROMPT_ITEM = {_reactKey: '__prompt__'}
|
||||
const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
|
||||
|
@ -47,7 +49,7 @@ export const Feed = observer(function Feed({
|
|||
<EmptyState
|
||||
icon="bars"
|
||||
message="This feed is empty!"
|
||||
style={{paddingVertical: 40}}
|
||||
style={styles.emptyState}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
|
@ -76,7 +78,7 @@ export const Feed = observer(function Feed({
|
|||
}
|
||||
const FeedFooter = () =>
|
||||
feed.isLoading ? (
|
||||
<View style={{paddingTop: 20}}>
|
||||
<View style={styles.feedFooter}>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
) : (
|
||||
|
@ -87,11 +89,7 @@ export const Feed = observer(function Feed({
|
|||
{!data && <PromptButtons onPressCompose={onPressCompose} />}
|
||||
{feed.isLoading && !data && <PostFeedLoadingPlaceholder />}
|
||||
{feed.hasError && (
|
||||
<ErrorMessage
|
||||
message={feed.error}
|
||||
style={{margin: 6}}
|
||||
onPressTryAgain={onPressTryAgain}
|
||||
/>
|
||||
<ErrorMessage message={feed.error} onPressTryAgain={onPressTryAgain} />
|
||||
)}
|
||||
{feed.hasLoaded && data && (
|
||||
<FlatList
|
||||
|
@ -101,7 +99,7 @@ export const Feed = observer(function Feed({
|
|||
renderItem={renderItem}
|
||||
ListFooterComponent={FeedFooter}
|
||||
refreshing={feed.isRefreshing}
|
||||
contentContainerStyle={{paddingBottom: 100}}
|
||||
contentContainerStyle={s.contentContainer}
|
||||
onScroll={onScroll}
|
||||
onRefresh={onRefresh}
|
||||
onEndReached={onEndReached}
|
||||
|
@ -110,3 +108,8 @@ export const Feed = observer(function Feed({
|
|||
</View>
|
||||
)
|
||||
})
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
feedFooter: {paddingTop: 20},
|
||||
emptyState: {paddingVertical: 40},
|
||||
})
|
||||
|
|
|
@ -124,7 +124,7 @@ export const FeedItem = observer(function ({
|
|||
style={[
|
||||
styles.bottomReplyLine,
|
||||
{borderColor: pal.colors.replyLine},
|
||||
isNoTop ? {top: 64} : undefined,
|
||||
isNoTop ? styles.bottomReplyLineNoTop : undefined,
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
|
@ -163,7 +163,7 @@ export const FeedItem = observer(function ({
|
|||
timestamp={item.post.indexedAt}
|
||||
/>
|
||||
{!isChild && replyAuthorDid !== '' && (
|
||||
<View style={[s.flexRow, s.mb2, {alignItems: 'center'}]}>
|
||||
<View style={[s.flexRow, s.mb2, s.alignCenter]}>
|
||||
<FontAwesomeIcon
|
||||
icon="reply"
|
||||
size={9}
|
||||
|
@ -195,9 +195,7 @@ export const FeedItem = observer(function ({
|
|||
lineHeight={1.3}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<View style={{height: 5}} />
|
||||
)}
|
||||
) : undefined}
|
||||
{item.post.embed ? (
|
||||
<PostEmbeds embed={item.post.embed} style={styles.embed} />
|
||||
) : null}
|
||||
|
@ -281,6 +279,7 @@ const styles = StyleSheet.create({
|
|||
bottom: 0,
|
||||
borderLeftWidth: 2,
|
||||
},
|
||||
bottomReplyLineNoTop: {top: 64},
|
||||
includeReason: {
|
||||
flexDirection: 'row',
|
||||
paddingLeft: 50,
|
||||
|
|
|
@ -54,11 +54,7 @@ export const ProfileFollowers = observer(function ProfileFollowers({
|
|||
if (view.hasError) {
|
||||
return (
|
||||
<View>
|
||||
<ErrorMessage
|
||||
message={view.error}
|
||||
style={{margin: 6}}
|
||||
onPressTryAgain={onRefresh}
|
||||
/>
|
||||
<ErrorMessage message={view.error} onPressTryAgain={onRefresh} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -54,11 +54,7 @@ export const ProfileFollows = observer(function ProfileFollows({
|
|||
if (view.hasError) {
|
||||
return (
|
||||
<View>
|
||||
<ErrorMessage
|
||||
message={view.error}
|
||||
style={{margin: 6}}
|
||||
onPressTryAgain={onRefresh}
|
||||
/>
|
||||
<ErrorMessage message={view.error} onPressTryAgain={onRefresh} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -100,22 +100,14 @@ export const ProfileHeader = observer(function ProfileHeader({
|
|||
<LoadingPlaceholder width="100%" height={120} />
|
||||
<View
|
||||
style={[pal.view, {borderColor: pal.colors.background}, styles.avi]}>
|
||||
<LoadingPlaceholder
|
||||
width={80}
|
||||
height={80}
|
||||
style={{borderRadius: 40}}
|
||||
/>
|
||||
<LoadingPlaceholder width={80} height={80} style={styles.br40} />
|
||||
</View>
|
||||
<View style={styles.content}>
|
||||
<View style={[styles.buttonsLine]}>
|
||||
<LoadingPlaceholder
|
||||
width={100}
|
||||
height={31}
|
||||
style={{borderRadius: 50}}
|
||||
/>
|
||||
<LoadingPlaceholder width={100} height={31} style={styles.br50} />
|
||||
</View>
|
||||
<View style={styles.displayNameLine}>
|
||||
<Text type="title-xl" style={[pal.text, {lineHeight: 38}]}>
|
||||
<Text type="title-xl" style={[pal.text, styles.title]}>
|
||||
{view.displayName || view.handle}
|
||||
</Text>
|
||||
</View>
|
||||
|
@ -208,7 +200,7 @@ export const ProfileHeader = observer(function ProfileHeader({
|
|||
) : undefined}
|
||||
</View>
|
||||
<View style={styles.displayNameLine}>
|
||||
<Text type="title-xl" style={[pal.text, {lineHeight: 38}]}>
|
||||
<Text type="title-xl" style={[pal.text, styles.title]}>
|
||||
{view.displayName || view.handle}
|
||||
</Text>
|
||||
</View>
|
||||
|
@ -349,6 +341,7 @@ const styles = StyleSheet.create({
|
|||
// paddingLeft: 86,
|
||||
// marginBottom: 14,
|
||||
},
|
||||
title: {lineHeight: 38},
|
||||
|
||||
handleLine: {
|
||||
flexDirection: 'row',
|
||||
|
@ -369,4 +362,7 @@ const styles = StyleSheet.create({
|
|||
alignItems: 'center',
|
||||
marginBottom: 5,
|
||||
},
|
||||
|
||||
br40: {borderRadius: 40},
|
||||
br50: {borderRadius: 50},
|
||||
})
|
||||
|
|
|
@ -57,7 +57,7 @@ export const Link = observer(function Link({
|
|||
)
|
||||
})
|
||||
|
||||
export const TextLink = observer(function Link({
|
||||
export const TextLink = observer(function TextLink({
|
||||
type = 'md',
|
||||
style,
|
||||
href,
|
||||
|
|
|
@ -19,23 +19,15 @@ export function LoadingPlaceholder({
|
|||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.loadingPlaceholder,
|
||||
{
|
||||
width,
|
||||
height,
|
||||
backgroundColor: theme.palette.default.backgroundLight,
|
||||
borderRadius: 6,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
style,
|
||||
]}>
|
||||
<View
|
||||
style={{
|
||||
width,
|
||||
height,
|
||||
backgroundColor: theme.palette.default.backgroundLight,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -137,6 +129,9 @@ export function NotificationFeedLoadingPlaceholder() {
|
|||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
loadingPlaceholder: {
|
||||
borderRadius: 6,
|
||||
},
|
||||
post: {
|
||||
flexDirection: 'row',
|
||||
padding: 10,
|
||||
|
|
|
@ -128,10 +128,7 @@ export function PostCtrls(opts: PostCtrlsOpts) {
|
|||
hitSlop={HITSLOP}
|
||||
onPress={opts.onPressReply}>
|
||||
<CommentBottomArrow
|
||||
style={[
|
||||
defaultCtrlColor,
|
||||
opts.big ? {marginTop: 2} : {marginTop: 1},
|
||||
]}
|
||||
style={[defaultCtrlColor, opts.big ? s.mt2 : styles.mt1]}
|
||||
strokeWidth={3}
|
||||
size={opts.big ? 20 : 15}
|
||||
/>
|
||||
|
@ -181,10 +178,7 @@ export function PostCtrls(opts: PostCtrlsOpts) {
|
|||
/>
|
||||
) : (
|
||||
<HeartIcon
|
||||
style={[
|
||||
defaultCtrlColor,
|
||||
opts.big ? {marginTop: 1} : undefined,
|
||||
]}
|
||||
style={[defaultCtrlColor, opts.big ? styles.mt1 : undefined]}
|
||||
strokeWidth={3}
|
||||
size={opts.big ? 20 : 16}
|
||||
/>
|
||||
|
@ -244,4 +238,7 @@ const styles = StyleSheet.create({
|
|||
ctrlIconUpvoted: {
|
||||
color: colors.red3,
|
||||
},
|
||||
mt1: {
|
||||
marginTop: 1,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -67,7 +67,7 @@ export function PostEmbeds({
|
|||
<AutoSizedImage
|
||||
uri={embed.images[0].thumb}
|
||||
onPress={() => openLightbox(0)}
|
||||
containerStyle={{borderRadius: 8}}
|
||||
containerStyle={styles.singleImage}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
|
@ -120,6 +120,9 @@ const styles = StyleSheet.create({
|
|||
imagesContainer: {
|
||||
marginTop: 4,
|
||||
},
|
||||
singleImage: {
|
||||
borderRadius: 8,
|
||||
},
|
||||
extOuter: {
|
||||
borderWidth: 1,
|
||||
borderRadius: 8,
|
||||
|
|
|
@ -41,7 +41,7 @@ export function Selector({
|
|||
width: middle.width,
|
||||
}
|
||||
return [left, middle, right]
|
||||
}, [selectedIndex, items, itemLayouts])
|
||||
}, [selectedIndex, itemLayouts])
|
||||
|
||||
const underlineStyle = {
|
||||
backgroundColor: pal.colors.text,
|
||||
|
|
|
@ -62,8 +62,8 @@ export function UserAvatar({
|
|||
])
|
||||
}, [onSelectNewAvatar])
|
||||
|
||||
const renderSvg = (size: number, initials: string) => (
|
||||
<Svg width={size} height={size} viewBox="0 0 100 100">
|
||||
const renderSvg = (svgSize: number, svgInitials: string) => (
|
||||
<Svg width={svgSize} height={svgSize} viewBox="0 0 100 100">
|
||||
<Defs>
|
||||
<LinearGradient id="grad" x1="0" y1="0" x2="1" y2="1">
|
||||
<Stop offset="0" stopColor={gradients.blue.start} stopOpacity="1" />
|
||||
|
@ -78,7 +78,7 @@ export function UserAvatar({
|
|||
x="50"
|
||||
y="67"
|
||||
textAnchor="middle">
|
||||
{initials}
|
||||
{svgInitials}
|
||||
</Text>
|
||||
</Svg>
|
||||
)
|
||||
|
@ -88,7 +88,11 @@ export function UserAvatar({
|
|||
<TouchableOpacity onPress={handleEditAvatar}>
|
||||
{avatar ? (
|
||||
<Image
|
||||
style={{width: size, height: size, borderRadius: (size / 2) | 0}}
|
||||
style={{
|
||||
width: size,
|
||||
height: size,
|
||||
borderRadius: Math.floor(size / 2),
|
||||
}}
|
||||
source={{uri: avatar}}
|
||||
/>
|
||||
) : (
|
||||
|
@ -104,7 +108,7 @@ export function UserAvatar({
|
|||
</TouchableOpacity>
|
||||
) : avatar ? (
|
||||
<Image
|
||||
style={{width: size, height: size, borderRadius: (size / 2) | 0}}
|
||||
style={{width: size, height: size, borderRadius: Math.floor(size / 2)}}
|
||||
resizeMode="stretch"
|
||||
source={{uri: avatar}}
|
||||
/>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, {useState, useEffect} from 'react'
|
||||
import {AppBskyActorGetProfile as GetProfile} from '@atproto/api'
|
||||
import {StyleProp, TextStyle} from 'react-native'
|
||||
import {StyleProp, StyleSheet, TextStyle} from 'react-native'
|
||||
import {Link} from './Link'
|
||||
import {Text} from './text/Text'
|
||||
import {LoadingPlaceholder} from './LoadingPlaceholder'
|
||||
|
@ -53,7 +53,7 @@ export function UserInfoText({
|
|||
return () => {
|
||||
aborted = true
|
||||
}
|
||||
}, [did, store.api.app.bsky])
|
||||
}, [did, store.profiles])
|
||||
|
||||
let inner
|
||||
if (didFail) {
|
||||
|
@ -73,7 +73,7 @@ export function UserInfoText({
|
|||
<LoadingPlaceholder
|
||||
width={80}
|
||||
height={8}
|
||||
style={{position: 'relative', top: 1, left: 2}}
|
||||
style={styles.loadingPlaceholder}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -91,3 +91,7 @@ export function UserInfoText({
|
|||
|
||||
return inner
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
loadingPlaceholder: {position: 'relative', top: 1, left: 2},
|
||||
})
|
||||
|
|
|
@ -11,8 +11,8 @@ import {UserAvatar} from './UserAvatar'
|
|||
import {Text} from './text/Text'
|
||||
import {MagnifyingGlassIcon} from '../../lib/icons'
|
||||
import {useStores} from '../../../state'
|
||||
import {useTheme} from '../../lib/ThemeContext'
|
||||
import {usePalette} from '../../lib/hooks/usePalette'
|
||||
import {colors} from '../../lib/styles'
|
||||
|
||||
const HITSLOP = {left: 10, top: 10, right: 10, bottom: 10}
|
||||
const BACK_HITSLOP = {left: 10, top: 10, right: 30, bottom: 10}
|
||||
|
@ -26,7 +26,6 @@ export const ViewHeader = observer(function ViewHeader({
|
|||
subtitle?: string
|
||||
canGoBack?: boolean
|
||||
}) {
|
||||
const theme = useTheme()
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const onPressBack = () => {
|
||||
|
@ -52,12 +51,12 @@ export const ViewHeader = observer(function ViewHeader({
|
|||
testID="viewHeaderBackOrMenuBtn"
|
||||
onPress={canGoBack ? onPressBack : onPressMenu}
|
||||
hitSlop={BACK_HITSLOP}
|
||||
style={canGoBack ? styles.backIcon : styles.backIconWide}>
|
||||
style={canGoBack ? styles.backBtn : styles.backBtnWide}>
|
||||
{canGoBack ? (
|
||||
<FontAwesomeIcon
|
||||
size={18}
|
||||
icon="angle-left"
|
||||
style={[{marginTop: 6}, pal.text]}
|
||||
style={[styles.backIcon, pal.text]}
|
||||
/>
|
||||
) : (
|
||||
<UserAvatar
|
||||
|
@ -96,13 +95,10 @@ export const ViewHeader = observer(function ViewHeader({
|
|||
<FontAwesomeIcon icon="signal" style={pal.text} size={16} />
|
||||
<FontAwesomeIcon
|
||||
icon="x"
|
||||
style={{
|
||||
backgroundColor: pal.colors.background,
|
||||
color: theme.palette.error.background,
|
||||
position: 'absolute',
|
||||
right: 7,
|
||||
bottom: 7,
|
||||
}}
|
||||
style={[
|
||||
styles.littleXIcon,
|
||||
{backgroundColor: pal.colors.background},
|
||||
]}
|
||||
size={8}
|
||||
/>
|
||||
</>
|
||||
|
@ -136,15 +132,18 @@ const styles = StyleSheet.create({
|
|||
fontWeight: 'normal',
|
||||
},
|
||||
|
||||
backIcon: {
|
||||
backBtn: {
|
||||
width: 30,
|
||||
height: 30,
|
||||
},
|
||||
backIconWide: {
|
||||
backBtnWide: {
|
||||
width: 40,
|
||||
height: 30,
|
||||
marginLeft: 6,
|
||||
},
|
||||
backIcon: {
|
||||
marginTop: 6,
|
||||
},
|
||||
btn: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
|
@ -154,4 +153,10 @@ const styles = StyleSheet.create({
|
|||
borderRadius: 20,
|
||||
marginLeft: 4,
|
||||
},
|
||||
littleXIcon: {
|
||||
color: colors.red3,
|
||||
position: 'absolute',
|
||||
right: 7,
|
||||
bottom: 7,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -5,6 +5,7 @@ import {HorzSwipe} from './gestures/HorzSwipe'
|
|||
import {useAnimatedValue} from '../../lib/hooks/useAnimatedValue'
|
||||
import {OnScrollCb} from '../../lib/hooks/useOnMainScroll'
|
||||
import {clamp} from '../../../lib/numbers'
|
||||
import {s} from '../../lib/styles'
|
||||
|
||||
const HEADER_ITEM = {_reactKey: '__header__'}
|
||||
const SELECTOR_ITEM = {_reactKey: '__selector__'}
|
||||
|
@ -54,7 +55,7 @@ export function ViewSelector({
|
|||
setSelectedIndex(clamp(index, 0, sections.length))
|
||||
useEffect(() => {
|
||||
onSelectView?.(selectedIndex)
|
||||
}, [selectedIndex])
|
||||
}, [selectedIndex, onSelectView])
|
||||
|
||||
// rendering
|
||||
// =
|
||||
|
@ -98,7 +99,7 @@ export function ViewSelector({
|
|||
onScroll={onScroll}
|
||||
onRefresh={onRefresh}
|
||||
onEndReached={onEndReached}
|
||||
contentContainerStyle={{paddingBottom: 200}}
|
||||
contentContainerStyle={s.contentContainer}
|
||||
/>
|
||||
</HorzSwipe>
|
||||
)
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, {useState} from 'react'
|
|||
import {View} from 'react-native'
|
||||
import {RadioButton} from './RadioButton'
|
||||
import {ButtonType} from './Button'
|
||||
import {s} from '../../../lib/styles'
|
||||
|
||||
export interface RadioGroupItem {
|
||||
label: string
|
||||
|
@ -29,7 +30,7 @@ export function RadioGroup({
|
|||
{items.map((item, i) => (
|
||||
<RadioButton
|
||||
key={item.key}
|
||||
style={i !== 0 ? {marginTop: 2} : undefined}
|
||||
style={i !== 0 ? s.mt2 : undefined}
|
||||
type={type}
|
||||
label={item.label}
|
||||
isSelected={item.key === selection}
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
View,
|
||||
} from 'react-native'
|
||||
import {clamp} from 'lodash'
|
||||
import {s} from '../../../lib/styles'
|
||||
|
||||
interface Props {
|
||||
panX: Animated.Value
|
||||
|
@ -111,7 +112,9 @@ export function HorzSwipe({
|
|||
(Math.abs(gestureState.dx) > swipeDistanceThreshold / 4 ||
|
||||
Math.abs(gestureState.vx) > swipeVelocityThreshold)
|
||||
) {
|
||||
const final = ((gestureState.dx / Math.abs(gestureState.dx)) * -1) | 0
|
||||
const final = Math.floor(
|
||||
(gestureState.dx / Math.abs(gestureState.dx)) * -1,
|
||||
)
|
||||
Animated.timing(panX, {
|
||||
toValue: final,
|
||||
duration: 100,
|
||||
|
@ -144,7 +147,7 @@ export function HorzSwipe({
|
|||
})
|
||||
|
||||
return (
|
||||
<View {...panResponder.panHandlers} style={{flex: 1}}>
|
||||
<View {...panResponder.panHandlers} style={s.h100pct}>
|
||||
{children}
|
||||
</View>
|
||||
)
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
View,
|
||||
} from 'react-native'
|
||||
import {clamp} from 'lodash'
|
||||
import {s} from '../../../lib/styles'
|
||||
|
||||
export enum Dir {
|
||||
None,
|
||||
|
@ -294,7 +295,7 @@ export function SwipeAndZoom({
|
|||
})
|
||||
|
||||
return (
|
||||
<View {...panResponder.panHandlers} style={{flex: 1}}>
|
||||
<View {...panResponder.panHandlers} style={s.h100pct}>
|
||||
{children}
|
||||
</View>
|
||||
)
|
||||
|
|
|
@ -47,9 +47,9 @@ export function AutoSizedImage({
|
|||
setImgInfo({width, height})
|
||||
}
|
||||
},
|
||||
(error: any) => {
|
||||
(err: any) => {
|
||||
if (!aborted) {
|
||||
setError(String(error))
|
||||
setError(String(err))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
@ -105,7 +105,7 @@ function ImageLayoutGridInner({
|
|||
<TouchableWithoutFeedback onPress={() => onPress?.(1)}>
|
||||
<Image source={{uri: uris[1]}} style={size1} />
|
||||
</TouchableWithoutFeedback>
|
||||
<View style={{height: 5}} />
|
||||
<View style={styles.hSpace} />
|
||||
<TouchableWithoutFeedback onPress={() => onPress?.(2)}>
|
||||
<Image source={{uri: uris[2]}} style={size1} />
|
||||
</TouchableWithoutFeedback>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue