Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add web layout components

+99 -26
+1 -1
public/index.html
··· 10 10 /* These styles disable body scrolling if you are using <ScrollView> */ 11 11 body { overflow: hidden; } 12 12 /* These styles make the root element full-height */ 13 - #root { display:flex; height:100%; } 13 + #app-root { display:flex; height:100%; } 14 14 15 15 /* These styles are for src/view/com/modals/WebModal */ 16 16 div[data-modal-overlay] {
+6 -5
src/view/com/post-thread/PostThread.tsx
··· 1 1 import React, {useRef} from 'react' 2 2 import {observer} from 'mobx-react-lite' 3 - import {ActivityIndicator, FlatList, View} from 'react-native' 3 + import {ActivityIndicator, View} from 'react-native' 4 + import {CenteredView, FlatList} from '../util/Views' 4 5 import { 5 6 PostThreadViewModel, 6 7 PostThreadViewPostModel, ··· 50 51 // = 51 52 if ((view.isLoading && !view.isRefreshing) || view.params.uri !== uri) { 52 53 return ( 53 - <View> 54 + <CenteredView> 54 55 <ActivityIndicator /> 55 - </View> 56 + </CenteredView> 56 57 ) 57 58 } 58 59 ··· 60 61 // = 61 62 if (view.hasError) { 62 63 return ( 63 - <View> 64 + <CenteredView> 64 65 <ErrorMessage message={view.error} onPressTryAgain={onRefresh} /> 65 - </View> 66 + </CenteredView> 66 67 ) 67 68 } 68 69
+11 -6
src/view/com/posts/Feed.tsx
··· 3 3 import { 4 4 ActivityIndicator, 5 5 View, 6 - FlatList, 7 6 StyleProp, 8 7 StyleSheet, 9 8 ViewStyle, 10 9 } from 'react-native' 10 + import {CenteredView, FlatList} from '../util/Views' 11 11 import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' 12 12 import {EmptyState} from '../util/EmptyState' 13 13 import {ErrorMessage} from '../util/error/ErrorMessage' ··· 86 86 ) 87 87 return ( 88 88 <View testID={testID} style={style}> 89 - {!data && <PromptButtons onPressCompose={onPressCompose} />} 90 - {feed.isLoading && !data && <PostFeedLoadingPlaceholder />} 91 - {feed.hasError && ( 92 - <ErrorMessage message={feed.error} onPressTryAgain={onPressTryAgain} /> 93 - )} 89 + <CenteredView> 90 + {!data && <PromptButtons onPressCompose={onPressCompose} />} 91 + {feed.isLoading && !data && <PostFeedLoadingPlaceholder />} 92 + {feed.hasError && ( 93 + <ErrorMessage 94 + message={feed.error} 95 + onPressTryAgain={onPressTryAgain} 96 + /> 97 + )} 98 + </CenteredView> 94 99 {feed.hasLoaded && data && ( 95 100 <FlatList 96 101 ref={scrollElRef}
+1
src/view/com/util/Views.tsx
··· 1 + export {View as CenteredView, FlatList, ScrollView} from 'react-native'
+70
src/view/com/util/Views.web.tsx
··· 1 + /** 2 + * In the Web build, we center all content so that it mirrors the 3 + * mobile experience (a single narrow column). We then place a UI 4 + * shell around the content if you're in desktop. 5 + * 6 + * Because scrolling is handled by components deep in the hierarchy, 7 + * we can't just wrap the top-level element with a max width. The 8 + * centering has to be done at the ScrollView. 9 + * 10 + * These components wrap the RN ScrollView-based components to provide 11 + * consistent layout. It also provides <CenteredView> for views that 12 + * need to match layout but which aren't scrolled. 13 + */ 14 + 15 + import React from 'react' 16 + import { 17 + FlatList as RNFlatList, 18 + FlatListProps, 19 + ScrollView as RNScrollView, 20 + ScrollViewProps, 21 + StyleSheet, 22 + StyleProp, 23 + View, 24 + ViewProps, 25 + } from 'react-native' 26 + 27 + export function CenteredView({ 28 + style, 29 + ...props 30 + }: React.PropsWithChildren<ViewProps>) { 31 + style = addStyle(style, styles.container) 32 + return <View style={style} {...props} /> 33 + } 34 + 35 + export function FlatList<ItemT>({ 36 + contentContainerStyle, 37 + ...props 38 + }: React.PropsWithChildren<FlatListProps<ItemT>>) { 39 + contentContainerStyle = addStyle(contentContainerStyle, styles.container) 40 + return <RNFlatList contentContainerStyle={contentContainerStyle} {...props} /> 41 + } 42 + 43 + export function ScrollView({ 44 + contentContainerStyle, 45 + ...props 46 + }: React.PropsWithChildren<ScrollViewProps>) { 47 + contentContainerStyle = addStyle(contentContainerStyle, styles.container) 48 + return ( 49 + <RNScrollView contentContainerStyle={contentContainerStyle} {...props} /> 50 + ) 51 + } 52 + 53 + function addStyle<T>( 54 + base: StyleProp<T>, 55 + addedStyle: StyleProp<T>, 56 + ): StyleProp<T> { 57 + if (Array.isArray(base)) { 58 + return base.concat([addedStyle]) 59 + } 60 + return [base, addedStyle] 61 + } 62 + 63 + const styles = StyleSheet.create({ 64 + container: { 65 + width: '100%', 66 + maxWidth: 600, 67 + marginLeft: 'auto', 68 + marginRight: 'auto', 69 + }, 70 + })
+10 -14
src/view/shell/web/index.tsx
··· 18 18 if (!store.session.hasSession) { 19 19 return ( 20 20 <View style={styles.outerContainer}> 21 - <View style={styles.innerContainer}> 22 - <Login /> 23 - </View> 21 + <Login /> 24 22 </View> 25 23 ) 26 24 } 27 25 28 26 return ( 29 27 <View style={[styles.outerContainer, pal.view]}> 30 - <View style={styles.innerContainer}> 31 - {screenRenderDesc.screens.map(({Com, navIdx, params, key, current}) => ( 32 - <View 33 - key={key} 34 - style={[s.h100pct, current ? styles.visible : styles.hidden]}> 35 - <ErrorBoundary> 36 - <Com params={params} navIdx={navIdx} visible={current} /> 37 - </ErrorBoundary> 38 - </View> 39 - ))} 40 - </View> 28 + {screenRenderDesc.screens.map(({Com, navIdx, params, key, current}) => ( 29 + <View 30 + key={key} 31 + style={[s.h100pct, current ? styles.visible : styles.hidden]}> 32 + <ErrorBoundary> 33 + <Com params={params} navIdx={navIdx} visible={current} /> 34 + </ErrorBoundary> 35 + </View> 36 + ))} 41 37 </View> 42 38 ) 43 39 // TODO