mirror of
https://github.com/zhigang1992/devhub.git
synced 2026-06-17 19:25:38 +08:00
Scroll to column
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
"bugsnag-js": "^4.7.3",
|
||||
"bugsnag-react": "^1.1.1",
|
||||
"bugsnag-react-native": "^2.12.2",
|
||||
"fbemitter": "^2.1.1",
|
||||
"gravatar": "^1.6.0",
|
||||
"hoist-non-react-statics": "^3.1.0",
|
||||
"immer": "^1.7.4",
|
||||
@@ -38,6 +39,7 @@
|
||||
"reselect": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fbemitter": "^2.0.32",
|
||||
"@types/gravatar": "^1.4.28",
|
||||
"@types/hoist-non-react-statics": "^3.0.1",
|
||||
"@types/jest": "^23.3.9",
|
||||
|
||||
@@ -2,7 +2,6 @@ import React, { PureComponent, StrictMode } from 'react'
|
||||
import { Provider as ReduxProvider } from 'react-redux'
|
||||
import { PersistGate } from 'redux-persist/integration/react'
|
||||
|
||||
import { bugsnagClient, initBugsnag } from '../libs/bugsnag'
|
||||
import { AppNavigator } from '../navigation/AppNavigator'
|
||||
import { configureStore } from '../redux/store'
|
||||
import { AppGlobalStyles } from './AppGlobalStyles'
|
||||
@@ -11,9 +10,6 @@ import { ThemeProvider } from './context/ThemeContext'
|
||||
|
||||
const { persistor, store } = configureStore()
|
||||
|
||||
initBugsnag('231f337f6090422c611017d3dab3d32e')
|
||||
bugsnagClient.config.notifyReleaseStages = ['production']
|
||||
|
||||
// TODO: Enable StrictMode after react-redux fixes it
|
||||
// @see https://github.com/reduxjs/react-redux/issues/897
|
||||
// @see https://github.com/reduxjs/react-redux/issues/890
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import React, { PureComponent, ReactNode } from 'react'
|
||||
import { StyleProp, StyleSheet, View, ViewProps, ViewStyle } from 'react-native'
|
||||
|
||||
import { EventSubscription } from 'fbemitter'
|
||||
import { Platform } from '../../libs/platform'
|
||||
import { emitter } from '../../setup'
|
||||
import * as colors from '../../styles/colors'
|
||||
import { contentPadding } from '../../styles/variables'
|
||||
import { DimensionsConsumer } from '../context/DimensionsContext'
|
||||
import { ThemeConsumer } from '../context/ThemeContext'
|
||||
@@ -11,12 +14,17 @@ export const columnMargin = contentPadding / 2
|
||||
|
||||
export interface ColumnProps extends ViewProps {
|
||||
children?: ReactNode
|
||||
columnId: string
|
||||
maxWidth?: number
|
||||
minWidth?: number
|
||||
pagingEnabled?: boolean
|
||||
style?: StyleProp<ViewStyle>
|
||||
}
|
||||
|
||||
export interface ColumnState {
|
||||
showFocusBorder?: boolean
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
height: '100%',
|
||||
@@ -38,9 +46,45 @@ export class Column extends PureComponent<ColumnProps> {
|
||||
minWidth: 320,
|
||||
}
|
||||
|
||||
state = {
|
||||
showFocusBorder: false,
|
||||
}
|
||||
|
||||
focusOnColumnListener?: EventSubscription
|
||||
|
||||
componentDidMount() {
|
||||
this.focusOnColumnListener = emitter.addListener(
|
||||
'FOCUS_ON_COLUMN',
|
||||
this.handleColumnFocusRequest,
|
||||
)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.focusOnColumnListener) this.focusOnColumnListener.remove()
|
||||
}
|
||||
|
||||
handleColumnFocusRequest = ({
|
||||
columnId,
|
||||
highlight,
|
||||
}: {
|
||||
columnId: string
|
||||
highlight?: boolean
|
||||
}) => {
|
||||
if (!(columnId && columnId === this.props.columnId)) return
|
||||
if (!highlight) return
|
||||
|
||||
this.setState({ showFocusBorder: true }, () => {
|
||||
setTimeout(() => {
|
||||
this.setState({ showFocusBorder: false })
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { showFocusBorder } = this.state
|
||||
const {
|
||||
children,
|
||||
columnId,
|
||||
maxWidth,
|
||||
minWidth,
|
||||
pagingEnabled,
|
||||
@@ -49,7 +93,7 @@ export class Column extends PureComponent<ColumnProps> {
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<ThemeConsumer>
|
||||
<ThemeConsumer key={`column-inner-${columnId}`}>
|
||||
{({ theme }) => (
|
||||
<DimensionsConsumer>
|
||||
{({ width }) => (
|
||||
@@ -73,6 +117,18 @@ export class Column extends PureComponent<ColumnProps> {
|
||||
]}
|
||||
>
|
||||
{children}
|
||||
|
||||
{!!showFocusBorder && (
|
||||
<View
|
||||
style={{
|
||||
...StyleSheet.absoluteFillObject,
|
||||
borderWidth: 0,
|
||||
borderRightWidth: 4,
|
||||
borderLeftWidth: 4,
|
||||
borderColor: theme.foregroundColorTransparent50,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</DimensionsConsumer>
|
||||
|
||||
@@ -26,11 +26,7 @@ import { ThemeConsumer } from '../context/ThemeContext'
|
||||
export const columnHeaderItemContentSize = 20
|
||||
|
||||
export interface ColumnHeaderItemProps {
|
||||
avatarDetails?: {
|
||||
owner: string
|
||||
repo?: string
|
||||
}
|
||||
avatarShape?: AvatarProps['shape']
|
||||
avatarProps?: Partial<AvatarProps>
|
||||
avatarStyle?: StyleProp<ImageStyle>
|
||||
iconName?: GitHubIcon
|
||||
iconStyle?: StyleProp<TextStyle>
|
||||
@@ -90,9 +86,7 @@ class ColumnHeaderItemComponent extends PureComponent<
|
||||
|
||||
render() {
|
||||
const {
|
||||
avatarDetails,
|
||||
avatarShape,
|
||||
avatarStyle,
|
||||
avatarProps: _avatarProps,
|
||||
iconName,
|
||||
iconStyle,
|
||||
subtitle,
|
||||
@@ -102,12 +96,13 @@ class ColumnHeaderItemComponent extends PureComponent<
|
||||
username: _username,
|
||||
} = this.props
|
||||
|
||||
const avatarProps = _avatarProps || {}
|
||||
|
||||
const username =
|
||||
_username &&
|
||||
avatarDetails &&
|
||||
avatarDetails.owner &&
|
||||
!(_username.toLowerCase() === avatarDetails.owner.toLowerCase())
|
||||
? avatarDetails.owner
|
||||
avatarProps.username &&
|
||||
!(_username.toLowerCase() === avatarProps.username.toLowerCase())
|
||||
? avatarProps.username
|
||||
: undefined
|
||||
|
||||
const smallAvatarSpacing = 5
|
||||
@@ -153,8 +148,7 @@ class ColumnHeaderItemComponent extends PureComponent<
|
||||
}}
|
||||
isBot={false}
|
||||
linkURL=""
|
||||
repo={avatarDetails && avatarDetails.repo}
|
||||
shape={avatarShape}
|
||||
{...avatarProps}
|
||||
style={[
|
||||
{
|
||||
position: 'absolute',
|
||||
@@ -163,7 +157,7 @@ class ColumnHeaderItemComponent extends PureComponent<
|
||||
width: 10,
|
||||
height: 10,
|
||||
},
|
||||
avatarStyle,
|
||||
avatarProps.style,
|
||||
]}
|
||||
username={username}
|
||||
/>
|
||||
@@ -174,14 +168,13 @@ class ColumnHeaderItemComponent extends PureComponent<
|
||||
<Avatar
|
||||
isBot={false}
|
||||
linkURL=""
|
||||
repo={avatarDetails && avatarDetails.repo}
|
||||
shape={avatarShape}
|
||||
{...avatarProps}
|
||||
style={[
|
||||
{
|
||||
width: columnHeaderItemContentSize,
|
||||
height: columnHeaderItemContentSize,
|
||||
},
|
||||
avatarStyle,
|
||||
avatarProps.style,
|
||||
]}
|
||||
username={username}
|
||||
/>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { EventSubscription } from 'fbemitter'
|
||||
import React, { PureComponent } from 'react'
|
||||
import {
|
||||
FlatList,
|
||||
@@ -7,6 +8,7 @@ import {
|
||||
ViewStyle,
|
||||
} from 'react-native'
|
||||
|
||||
import { emitter } from '../../setup'
|
||||
import { Column, Omit } from '../../types'
|
||||
import { DimensionsConsumer } from '../context/DimensionsContext'
|
||||
import { EventColumn } from './EventColumn'
|
||||
@@ -26,9 +28,42 @@ const styles = StyleSheet.create({
|
||||
})
|
||||
|
||||
export class Columns extends PureComponent<ColumnsProps> {
|
||||
flatListRef = React.createRef<FlatList<Column>>()
|
||||
focusOnColumnListener?: EventSubscription
|
||||
pagingEnabled: boolean = true
|
||||
swipeable: boolean = false
|
||||
|
||||
componentDidMount() {
|
||||
this.focusOnColumnListener = emitter.addListener(
|
||||
'FOCUS_ON_COLUMN',
|
||||
this.handleColumnFocusRequest,
|
||||
)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.focusOnColumnListener) this.focusOnColumnListener.remove()
|
||||
}
|
||||
|
||||
handleColumnFocusRequest = ({
|
||||
animated,
|
||||
columnIndex,
|
||||
}: {
|
||||
columnId: string
|
||||
columnIndex: number
|
||||
animated?: boolean
|
||||
highlight?: boolean
|
||||
}) => {
|
||||
if (!this.flatListRef.current) return
|
||||
if (!(this.props.data && this.props.data!.length)) return
|
||||
|
||||
if (columnIndex >= 0 && columnIndex < this.props.data.length) {
|
||||
this.flatListRef.current.scrollToIndex({
|
||||
animated,
|
||||
index: columnIndex,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
keyExtractor(column: Column) {
|
||||
return `column-container-${column.id}`
|
||||
}
|
||||
@@ -79,6 +114,7 @@ export class Columns extends PureComponent<ColumnsProps> {
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
ref={this.flatListRef}
|
||||
key="columns-flat-list"
|
||||
bounces={!this.swipeable}
|
||||
className="snap-container"
|
||||
|
||||
@@ -53,11 +53,12 @@ export class EventColumnComponent extends PureComponent<
|
||||
return (
|
||||
<Column
|
||||
key={`event-column-${this.props.column.id}-inner`}
|
||||
columnId={this.props.column.id}
|
||||
pagingEnabled={pagingEnabled}
|
||||
>
|
||||
<ColumnHeader>
|
||||
<ColumnHeaderItem
|
||||
avatarDetails={requestTypeIconAndData.avatarDetails}
|
||||
avatarProps={requestTypeIconAndData.avatarProps}
|
||||
iconName={requestTypeIconAndData.icon}
|
||||
subtitle={requestTypeIconAndData.subtitle}
|
||||
title={requestTypeIconAndData.title}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { ColumnHeader } from './ColumnHeader'
|
||||
import { ColumnHeaderItem, ColumnHeaderItemProps } from './ColumnHeaderItem'
|
||||
|
||||
export interface ModalColumnProps extends ColumnHeaderItemProps {
|
||||
columnId: string
|
||||
minWidth?: number
|
||||
maxWidth?: number
|
||||
}
|
||||
@@ -50,6 +51,7 @@ class ModalColumnComponent extends PureComponent<
|
||||
|
||||
return (
|
||||
<Column
|
||||
columnId={this.props.columnId}
|
||||
style={[
|
||||
{
|
||||
zIndex: 100,
|
||||
|
||||
@@ -51,6 +51,7 @@ class NotificationColumnComponent extends PureComponent<
|
||||
return (
|
||||
<Column
|
||||
key={`notification-column-${this.props.column.id}-inner`}
|
||||
columnId={this.props.column.id}
|
||||
pagingEnabled={pagingEnabled}
|
||||
>
|
||||
<ColumnHeader>
|
||||
|
||||
@@ -10,11 +10,13 @@ import {
|
||||
import { fixURL } from '../../utils/helpers/github/url'
|
||||
import { getRepositoryURL, getUserURL } from '../cards/partials/rows/helpers'
|
||||
import { ThemeConsumer } from '../context/ThemeContext'
|
||||
import { ConditionalWrap } from './ConditionalWrap'
|
||||
import { ImageWithLoading, ImageWithLoadingProps } from './ImageWithLoading'
|
||||
import { Link } from './Link'
|
||||
|
||||
export interface AvatarProps extends Partial<ImageWithLoadingProps> {
|
||||
avatarURL?: string
|
||||
disableLink?: boolean
|
||||
email?: string
|
||||
hitSlop?: TouchableOpacityProps['hitSlop']
|
||||
isBot?: boolean
|
||||
@@ -31,6 +33,7 @@ export const size = avatarSize
|
||||
|
||||
export const Avatar: SFC<AvatarProps> = ({
|
||||
avatarURL: _avatarURL,
|
||||
disableLink,
|
||||
email,
|
||||
hitSlop,
|
||||
isBot: _isBot,
|
||||
@@ -57,20 +60,26 @@ export const Avatar: SFC<AvatarProps> = ({
|
||||
|
||||
if (!uri) return null
|
||||
|
||||
const linkUri = disableLink
|
||||
? undefined
|
||||
: linkURL
|
||||
? fixURL(linkURL)
|
||||
: username
|
||||
? repo
|
||||
? getRepositoryURL(username, repo)
|
||||
: getUserURL(username, { isBot })
|
||||
: undefined
|
||||
|
||||
return (
|
||||
<ThemeConsumer>
|
||||
{({ theme }) => (
|
||||
<Link
|
||||
hitSlop={hitSlop}
|
||||
href={
|
||||
linkURL
|
||||
? fixURL(linkURL)
|
||||
: username
|
||||
? repo
|
||||
? getRepositoryURL(username, repo)
|
||||
: getUserURL(username, { isBot })
|
||||
: undefined
|
||||
}
|
||||
<ConditionalWrap
|
||||
condition={!!linkUri}
|
||||
wrap={children => (
|
||||
<Link hitSlop={hitSlop} href={linkUri}>
|
||||
{children}
|
||||
</Link>
|
||||
)}
|
||||
>
|
||||
<ImageWithLoading
|
||||
{...props}
|
||||
@@ -92,7 +101,7 @@ export const Avatar: SFC<AvatarProps> = ({
|
||||
style,
|
||||
]}
|
||||
/>
|
||||
</Link>
|
||||
</ConditionalWrap>
|
||||
)}
|
||||
</ThemeConsumer>
|
||||
)
|
||||
|
||||
@@ -10,6 +10,7 @@ import { connect } from 'react-redux'
|
||||
|
||||
import * as actions from '../../redux/actions'
|
||||
import * as selectors from '../../redux/selectors'
|
||||
import { emitter } from '../../setup'
|
||||
import { ExtractPropsFromConnector } from '../../types'
|
||||
import { getColumnHeaderDetails } from '../../utils/helpers/github/events'
|
||||
import { columnHeaderHeight } from '../columns/ColumnHeader'
|
||||
@@ -40,6 +41,7 @@ const connectToStore = connect(
|
||||
|
||||
return {
|
||||
columns: selectors.columnsSelector(state),
|
||||
currentOpenedModal: selectors.currentOpenedModal(state),
|
||||
username: (user && user.login) || '',
|
||||
}
|
||||
},
|
||||
@@ -81,8 +83,8 @@ class SidebarComponent extends PureComponent<
|
||||
<View
|
||||
style={[
|
||||
styles.centerContainer,
|
||||
squareStyle,
|
||||
{
|
||||
...squareStyle,
|
||||
backgroundColor: theme.backgroundColorLess08,
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: theme.backgroundColorDarker08,
|
||||
@@ -100,7 +102,14 @@ class SidebarComponent extends PureComponent<
|
||||
{!small && (
|
||||
<TouchableOpacity
|
||||
onPress={() => replaceModal({ name: 'ADD_COLUMN' })}
|
||||
style={[styles.centerContainer, squareStyle]}
|
||||
style={[
|
||||
styles.centerContainer,
|
||||
squareStyle,
|
||||
{
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: theme.backgroundColorDarker08,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<ColumnHeaderItem iconName="plus" />
|
||||
</TouchableOpacity>
|
||||
@@ -125,15 +134,26 @@ class SidebarComponent extends PureComponent<
|
||||
)
|
||||
|
||||
return (
|
||||
<View
|
||||
key={`sidebar-column-${index}`}
|
||||
<TouchableOpacity
|
||||
key={`sidebar-column-${column.id}`}
|
||||
style={[styles.centerContainer, squareStyle]}
|
||||
onPress={() => {
|
||||
emitter.emit('FOCUS_ON_COLUMN', {
|
||||
animated: !small || !this.props.currentOpenedModal,
|
||||
columnId: column.id,
|
||||
columnIndex: index,
|
||||
highlight: !small,
|
||||
})
|
||||
}}
|
||||
>
|
||||
<ColumnHeaderItem
|
||||
avatarDetails={requestTypeIconAndData.avatarDetails}
|
||||
avatarProps={{
|
||||
...requestTypeIconAndData.avatarProps,
|
||||
disableLink: true,
|
||||
}}
|
||||
iconName={requestTypeIconAndData.icon}
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
})}
|
||||
|
||||
|
||||
@@ -205,7 +205,11 @@ class AddColumnDetailsModalComponent extends PureComponent<
|
||||
const { icon, name, paramList } = this.props
|
||||
|
||||
return (
|
||||
<ModalColumn iconName="plus" title="Add Column">
|
||||
<ModalColumn
|
||||
columnId="add-column-details-modal"
|
||||
iconName="plus"
|
||||
title="Add Column"
|
||||
>
|
||||
<Spacer height={contentPadding} />
|
||||
|
||||
<View
|
||||
|
||||
@@ -133,7 +133,11 @@ class AddColumnModalComponent extends PureComponent<
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ModalColumn iconName="plus" title="Add Column">
|
||||
<ModalColumn
|
||||
columnId="add-column-modal"
|
||||
iconName="plus"
|
||||
title="Add Column"
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
|
||||
@@ -24,7 +24,11 @@ class SettingsModalComponent extends PureComponent<
|
||||
> {
|
||||
render() {
|
||||
return (
|
||||
<ModalColumn iconName="gear" title="Preferences">
|
||||
<ModalColumn
|
||||
columnId="preferences-modal"
|
||||
iconName="gear"
|
||||
title="Preferences"
|
||||
>
|
||||
<ScrollView
|
||||
style={{ flex: 1 }}
|
||||
contentContainerStyle={{ padding: contentPadding }}
|
||||
|
||||
@@ -4,9 +4,9 @@ import React from 'react'
|
||||
|
||||
export * from 'bugsnag-react-native'
|
||||
|
||||
export let bugsnagClient: InstanceType<typeof Bugsnag>
|
||||
export let ErrorBoundary: React.ComponentType<any>
|
||||
export let ErrorBoundary: React.ComponentType<any> = React.Fragment
|
||||
|
||||
let bugsnagClient: InstanceType<typeof Bugsnag>
|
||||
export function initBugsnag(apiKey: string) {
|
||||
bugsnagClient = new Bugsnag(apiKey)
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ import React from 'react'
|
||||
|
||||
export * from 'bugsnag-js'
|
||||
|
||||
export let bugsnagClient: ReturnType<typeof bugsnag>
|
||||
export let ErrorBoundary: React.ComponentType<any>
|
||||
export let ErrorBoundary: React.ComponentType<any> = React.Fragment
|
||||
|
||||
let bugsnagClient: ReturnType<typeof bugsnag>
|
||||
export function initBugsnag(apiKey: string) {
|
||||
bugsnagClient = bugsnag(apiKey)
|
||||
;(bugsnagClient as any).apiKey = apiKey
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { all, put, select, takeLatest } from 'redux-saga/effects'
|
||||
|
||||
import { delay } from 'redux-saga'
|
||||
import { emitter } from '../../setup'
|
||||
import { Column, ExtractActionFromActionCreator } from '../../types'
|
||||
import { guid } from '../../utils/helpers/shared'
|
||||
import * as actions from '../actions'
|
||||
@@ -41,6 +43,38 @@ function* onLoginSuccess(
|
||||
if (!columns) yield put(actions.replaceColumns(getDefaultColumns(username)))
|
||||
}
|
||||
|
||||
export function* columnsSagas() {
|
||||
yield all([yield takeLatest('LOGIN_SUCCESS', onLoginSuccess)])
|
||||
function* onAddColumn(
|
||||
action: ExtractActionFromActionCreator<typeof actions.addColumn>,
|
||||
) {
|
||||
const columnId = action.payload.id
|
||||
|
||||
const columns: Column[] | undefined = yield select(selectors.columnsSelector)
|
||||
const columnIndex = columns && columns.findIndex(c => c.id === columnId)
|
||||
|
||||
yield delay(300)
|
||||
emitter.emit('FOCUS_ON_COLUMN', {
|
||||
animated: true,
|
||||
columnId,
|
||||
columnIndex,
|
||||
highlight: true,
|
||||
})
|
||||
}
|
||||
|
||||
function onMoveColumn(
|
||||
action: ExtractActionFromActionCreator<typeof actions.moveColumn>,
|
||||
) {
|
||||
emitter.emit('FOCUS_ON_COLUMN', {
|
||||
animated: true,
|
||||
columnId: action.payload.id,
|
||||
columnIndex: action.payload.index,
|
||||
highlight: true,
|
||||
})
|
||||
}
|
||||
|
||||
export function* columnsSagas() {
|
||||
yield all([
|
||||
yield takeLatest('LOGIN_SUCCESS', onLoginSuccess),
|
||||
yield takeLatest('ADD_COLUMN', onAddColumn),
|
||||
yield takeLatest('MOVE_COLUMN', onMoveColumn),
|
||||
])
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { EventSubscription } from 'fbemitter'
|
||||
import hoistNonReactStatics from 'hoist-non-react-statics'
|
||||
import React, { PureComponent } from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import { Dimensions, StyleSheet, View } from 'react-native'
|
||||
import {
|
||||
NavigationScreenProps,
|
||||
NavigationStackScreenOptions,
|
||||
@@ -16,6 +17,7 @@ import { ModalRenderer } from '../components/modals/ModalRenderer'
|
||||
import { ColumnsContainer } from '../containers/ColumnsContainer'
|
||||
import * as actions from '../redux/actions'
|
||||
import * as selectors from '../redux/selectors'
|
||||
import { emitter } from '../setup'
|
||||
import { contentPadding } from '../styles/variables'
|
||||
import { ExtractPropsFromConnector } from '../types'
|
||||
|
||||
@@ -34,6 +36,7 @@ const connectToStore = connect(
|
||||
currentOpenedModal: selectors.currentOpenedModal(state),
|
||||
}),
|
||||
{
|
||||
closeAllModals: actions.closeAllModals,
|
||||
replaceModal: actions.replaceModal,
|
||||
},
|
||||
)
|
||||
@@ -45,6 +48,28 @@ class MainScreenComponent extends PureComponent<
|
||||
header: null,
|
||||
}
|
||||
|
||||
focusOnColumnListener?: EventSubscription
|
||||
|
||||
componentDidMount() {
|
||||
this.focusOnColumnListener = emitter.addListener(
|
||||
'FOCUS_ON_COLUMN',
|
||||
this.handleColumnFocusRequest,
|
||||
)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.focusOnColumnListener) this.focusOnColumnListener.remove()
|
||||
}
|
||||
|
||||
handleColumnFocusRequest = () => {
|
||||
if (
|
||||
this.props.currentOpenedModal &&
|
||||
Dimensions.get('window').width <= 420
|
||||
) {
|
||||
this.props.closeAllModals()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { currentOpenedModal, replaceModal } = this.props
|
||||
|
||||
|
||||
8
packages/shared/src/setup.ts
Normal file
8
packages/shared/src/setup.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { EventEmitter } from 'fbemitter'
|
||||
|
||||
import { initBugsnag } from './libs/bugsnag'
|
||||
|
||||
export const emitter = new EventEmitter()
|
||||
|
||||
export const bugsnagClient = initBugsnag('231f337f6090422c611017d3dab3d32e')
|
||||
bugsnagClient.config.notifyReleaseStages = ['production']
|
||||
@@ -22,9 +22,9 @@ import {
|
||||
export function getColumnHeaderDetails(
|
||||
column: Column,
|
||||
): {
|
||||
avatarDetails?: {
|
||||
owner: string
|
||||
avatarProps?: {
|
||||
repo?: string
|
||||
username: string
|
||||
}
|
||||
icon: GitHubIcon
|
||||
repoIsKnown: boolean
|
||||
@@ -36,7 +36,7 @@ export function getColumnHeaderDetails(
|
||||
switch (column.subtype) {
|
||||
case 'ORG_PUBLIC_EVENTS': {
|
||||
return {
|
||||
avatarDetails: { owner: column.params.org },
|
||||
avatarProps: { username: column.params.org },
|
||||
icon: 'organization',
|
||||
repoIsKnown: false,
|
||||
subtitle: 'Activity',
|
||||
@@ -53,9 +53,9 @@ export function getColumnHeaderDetails(
|
||||
}
|
||||
case 'REPO_EVENTS': {
|
||||
return {
|
||||
avatarDetails: {
|
||||
owner: column.params.owner,
|
||||
avatarProps: {
|
||||
repo: column.params.repo,
|
||||
username: column.params.owner,
|
||||
},
|
||||
icon: 'repo',
|
||||
repoIsKnown: true,
|
||||
@@ -65,9 +65,9 @@ export function getColumnHeaderDetails(
|
||||
}
|
||||
case 'REPO_NETWORK_EVENTS': {
|
||||
return {
|
||||
avatarDetails: {
|
||||
owner: column.params.owner,
|
||||
avatarProps: {
|
||||
repo: column.params.repo,
|
||||
username: column.params.owner,
|
||||
},
|
||||
icon: 'repo',
|
||||
repoIsKnown: true,
|
||||
@@ -77,7 +77,7 @@ export function getColumnHeaderDetails(
|
||||
}
|
||||
case 'USER_EVENTS': {
|
||||
return {
|
||||
avatarDetails: { owner: column.params.username },
|
||||
avatarProps: { username: column.params.username },
|
||||
icon: 'person',
|
||||
repoIsKnown: false,
|
||||
subtitle: 'Activity',
|
||||
@@ -86,7 +86,7 @@ export function getColumnHeaderDetails(
|
||||
}
|
||||
case 'USER_ORG_EVENTS': {
|
||||
return {
|
||||
avatarDetails: { owner: column.params.org },
|
||||
avatarProps: { username: column.params.org },
|
||||
icon: 'organization',
|
||||
repoIsKnown: false,
|
||||
subtitle: 'Activity',
|
||||
@@ -95,7 +95,7 @@ export function getColumnHeaderDetails(
|
||||
}
|
||||
case 'USER_PUBLIC_EVENTS': {
|
||||
return {
|
||||
avatarDetails: { owner: column.params.username },
|
||||
avatarProps: { username: column.params.username },
|
||||
icon: 'person',
|
||||
repoIsKnown: false,
|
||||
subtitle: 'Activity',
|
||||
@@ -105,7 +105,7 @@ export function getColumnHeaderDetails(
|
||||
case 'USER_RECEIVED_EVENTS':
|
||||
case 'USER_RECEIVED_PUBLIC_EVENTS': {
|
||||
return {
|
||||
avatarDetails: { owner: column.params.username },
|
||||
avatarProps: { username: column.params.username },
|
||||
icon: 'home',
|
||||
repoIsKnown: false,
|
||||
subtitle: 'Dashboard',
|
||||
|
||||
14
yarn.lock
14
yarn.lock
@@ -969,6 +969,11 @@
|
||||
"@svgr/core" "^2.4.1"
|
||||
loader-utils "^1.1.0"
|
||||
|
||||
"@types/fbemitter@^2.0.32":
|
||||
version "2.0.32"
|
||||
resolved "http://registry.npmjs.org/@types/fbemitter/-/fbemitter-2.0.32.tgz#8ed204da0f54e9c8eaec31b1eec91e25132d082c"
|
||||
integrity sha1-jtIE2g9U6cjq7DGx7skeJRMtCCw=
|
||||
|
||||
"@types/gravatar@^1.4.28":
|
||||
version "1.4.28"
|
||||
resolved "http://registry.npmjs.org/@types/gravatar/-/gravatar-1.4.28.tgz#a83527c354b3bce265ef489facfbed34971f9b16"
|
||||
@@ -4764,6 +4769,13 @@ fb-watchman@^2.0.0:
|
||||
dependencies:
|
||||
bser "^2.0.0"
|
||||
|
||||
fbemitter@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.npmjs.org/fbemitter/-/fbemitter-2.1.1.tgz#523e14fdaf5248805bb02f62efc33be703f51865"
|
||||
integrity sha1-Uj4U/a9SSIBbsC9i78M75wP1GGU=
|
||||
dependencies:
|
||||
fbjs "^0.8.4"
|
||||
|
||||
fbjs-css-vars@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.1.tgz#836d876e887d702f45610f5ebd2fbeef649527fc"
|
||||
@@ -4785,7 +4797,7 @@ fbjs-scripts@^0.8.1:
|
||||
semver "^5.1.0"
|
||||
through2 "^2.0.0"
|
||||
|
||||
fbjs@^0.8.0, fbjs@^0.8.16, fbjs@^0.8.9:
|
||||
fbjs@^0.8.0, fbjs@^0.8.16, fbjs@^0.8.4, fbjs@^0.8.9:
|
||||
version "0.8.17"
|
||||
resolved "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
|
||||
integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=
|
||||
|
||||
Reference in New Issue
Block a user