New cleaner design, with less borders and separators

Inspired by the new Gmail
This commit is contained in:
Bruno Lemos
2019-04-04 05:05:46 -03:00
parent c77858c2b6
commit 0ba065d0e4
29 changed files with 358 additions and 212 deletions

View File

@@ -2,6 +2,7 @@ import React from 'react'
import { Theme } from '@devhub/core'
import { darken, getLuminance, lighten } from 'polished'
import { Platform } from '../libs/platform'
import { themeColorFields } from '../utils/helpers/theme'
import { getSeparatorThemeColor } from './common/Separator'
import { useTheme } from './context/ThemeContext'
@@ -25,11 +26,20 @@ function getStyles(params: { theme: Theme }) {
outline-color: ${t.primaryBackgroundColor};
}
${
Platform.realOS === 'web'
? `a:hover, a:hover > *:not([class*='touchable']) {
text-decoration: underline;
}`
: ''
}
body {
${themeColorFields
.map(field => `--theme_${field}:${t[field]};`)
.join('\n')}
background-color:${t.backgroundColor};
color: ${t.foregroundColor};
}
`
}

View File

@@ -115,7 +115,7 @@ export function GitHubLoginButton(props: GitHubLoginButtonProps) {
function getStyles() {
const { isHovered, isPressing, theme } = cacheRef.current
const immediate = Platform.realOS === 'android'
const immediate = isHovered || Platform.realOS === 'android'
return {
config: { duration: immediate ? 0 : 100 },

View File

@@ -1,4 +1,3 @@
import { getLuminance } from 'polished'
import React from 'react'
import { isItemRead, ThemeColors } from '@devhub/core'
@@ -6,15 +5,15 @@ import { Separator } from '../../common/Separator'
import { useTheme } from '../../context/ThemeContext'
export function getCardItemSeparatorThemeColor(
backgroundColor: string,
isRead?: boolean,
_backgroundColor: string,
_isRead?: boolean,
): keyof ThemeColors {
const luminance = getLuminance(backgroundColor)
// const luminance = getLuminance(backgroundColor)
if (luminance <= 0.02)
return isRead ? 'backgroundColorLighther2' : 'backgroundColorLighther1'
// if (luminance <= 0.02)
// return isRead ? 'backgroundColorLess1' : 'backgroundColor'
return isRead ? 'backgroundColorDarker2' : 'backgroundColorDarker1'
return 'backgroundColor'
}
export function CardItemSeparator(props: any) {

View File

@@ -33,17 +33,10 @@ const styles = StyleSheet.create({
alignItems: 'center',
alignContent: 'center',
},
text: {
backgroundColor: 'transparent',
fontSize: 11,
lineHeight: 16,
opacity: 0.9,
},
})
export function CardSmallThing(props: CardSmallThingProps) {
const { backgroundColorTheme, icon, isRead, style, text, url } = props
const { backgroundColorTheme, icon, style, text, url } = props
const springAnimatedTheme = useCSSVariablesOrSpringAnimatedTheme()
@@ -51,13 +44,7 @@ export function CardSmallThing(props: CardSmallThingProps) {
if (!(hasText || icon)) return null
const springAnimatedTextStyles = [
styles.text,
{
color: isRead
? springAnimatedTheme.foregroundColorMuted50
: springAnimatedTheme.foregroundColor,
},
isRead && getCardStylesForTheme(springAnimatedTheme).mutedText,
getCardStylesForTheme(springAnimatedTheme).smallerMutedText,
]
return (

View File

@@ -120,6 +120,7 @@ export const CommitRow = React.memo((props: CommitRowProps) => {
numberOfLines={1}
style={[
getCardStylesForTheme(springAnimatedTheme).normalText,
cardStyles.smallText,
bold && cardStyles.boldText,
isRead && getCardStylesForTheme(springAnimatedTheme).mutedText,
]}

View File

@@ -234,10 +234,7 @@ export const IssueOrPullRequestRow = React.memo(
<SpringAnimatedText
style={[
getCardStylesForTheme(springAnimatedTheme)
.normalText,
cardStyles.smallText,
getCardStylesForTheme(springAnimatedTheme)
.mutedText,
.smallerMutedText,
]}
>
{byText}
@@ -259,7 +256,7 @@ export const IssueOrPullRequestRow = React.memo(
numberOfLines={1}
style={
getCardStylesForTheme(springAnimatedTheme)
.timestampText
.smallerMutedText
}
{...Platform.select({
web: { title: getFullDateText(createdAt) },

View File

@@ -116,7 +116,7 @@ export const cardStyles = StyleSheet.create({
},
boldText: {
fontWeight: '600',
fontWeight: '500',
},
})
@@ -126,7 +126,7 @@ export const getCardStylesForTheme = _.memoize(
usernameText: {
alignSelf: 'center',
lineHeight: 20,
fontWeight: '600',
fontWeight: '500',
color: theme.foregroundColor,
} as TextStyle,
@@ -136,6 +136,12 @@ export const getCardStylesForTheme = _.memoize(
color: theme.foregroundColorMuted50,
},
smallerMutedText: {
lineHeight: smallerTextSize + 1,
fontSize: smallerTextSize,
color: theme.foregroundColorMuted50,
},
commentText: {
color: theme.foregroundColor,
lineHeight: 20,

View File

@@ -7,9 +7,10 @@ import { Platform } from '../../libs/platform'
import { contentPadding } from '../../styles/variables'
import { tryFocus } from '../../utils/helpers/shared'
import { SpringAnimatedView } from '../animated/spring/SpringAnimatedView'
import { Separator, separatorTickSize } from '../common/Separator'
import { separatorThickSize } from '../common/Separator'
import { useColumnWidth } from '../context/ColumnWidthContext'
import { useAppLayout } from '../context/LayoutContext'
import { ColumnSeparator } from './ColumnSeparator'
export const columnMargin = contentPadding / 2
@@ -83,11 +84,19 @@ export const Column = React.memo(
]}
>
{!!renderSideSeparators && (
<Separator half horizontal={false} thick={sizename > '1-small'} />
<ColumnSeparator
half
horizontal={false}
thick={sizename > '1-small'}
/>
)}
<View style={{ flex: 1 }}>{children}</View>
{!!renderSideSeparators && (
<Separator half horizontal={false} thick={sizename > '1-small'} />
<ColumnSeparator
half
horizontal={false}
thick={sizename > '1-small'}
/>
)}
<SpringAnimatedView
@@ -98,8 +107,8 @@ export const Column = React.memo(
StyleSheet.absoluteFill,
{
borderWidth: 0,
borderRightWidth: Math.max(4, separatorTickSize),
borderLeftWidth: Math.max(4, separatorTickSize),
borderRightWidth: Math.max(4, separatorThickSize),
borderLeftWidth: Math.max(4, separatorThickSize),
borderColor: springAnimatedTheme.foregroundColorMuted50,
zIndex: 1000,
opacity: 0,

View File

@@ -1,4 +1,3 @@
import { getLuminance } from 'polished'
import React, { ReactNode } from 'react'
import { StyleProp, StyleSheet, View, ViewProps, ViewStyle } from 'react-native'
@@ -10,27 +9,41 @@ import { Separator } from '../common/Separator'
import { useTheme } from '../context/ThemeContext'
export function getColumnHeaderThemeColors(
backgroundColor: string,
): { normal: keyof ThemeColors; hover: keyof ThemeColors } {
const luminance = getLuminance(backgroundColor)
_backgroundColor?: string,
): {
normal: keyof ThemeColors
hover: keyof ThemeColors
selected: keyof ThemeColors
} {
// const luminance = getLuminance(backgroundColor)
if (luminance >= 0.5) {
return { normal: 'backgroundColorDarker1', hover: 'backgroundColorDarker2' }
}
// if (luminance >= 0.5) {
// return {
// normal: 'backgroundColor',
// hover: 'backgroundColorLess1',
// selected: 'backgroundColorLess2',
// }
// }
if (luminance <= 0.02) {
return { normal: 'backgroundColor', hover: 'backgroundColorLighther2' }
}
// if (luminance <= 0.02) {
// return {
// normal: 'backgroundColor',
// hover: 'backgroundColorLess2',
// selected: 'backgroundColorLess4',
// }
// }
return {
normal: 'backgroundColor',
hover: 'backgroundColorLighther1',
hover: 'backgroundColorLess2',
selected: 'backgroundColorLess3',
}
}
export interface ColumnHeaderProps extends ViewProps {
children?: ReactNode
maxWidth?: number
noPadding?: boolean
style?: StyleProp<ViewStyle>
}
@@ -42,7 +55,6 @@ const styles = StyleSheet.create({
alignSelf: 'stretch',
flexDirection: 'row',
height: columnHeaderHeight,
paddingHorizontal: contentPadding / 2,
},
})
@@ -50,7 +62,7 @@ export function ColumnHeader(props: ColumnHeaderProps) {
const springAnimatedTheme = useCSSVariablesOrSpringAnimatedTheme()
const theme = useTheme()
const { children, style, ...otherProps } = props
const { children, noPadding, style, ...otherProps } = props
return (
<SpringAnimatedSafeAreaView
@@ -64,7 +76,14 @@ export function ColumnHeader(props: ColumnHeaderProps) {
},
]}
>
<View {...otherProps} style={[styles.innerContainer, style]}>
<View
{...otherProps}
style={[
styles.innerContainer,
!noPadding && { paddingHorizontal: contentPadding / 2 },
style,
]}
>
{children}
</View>

View File

@@ -1,5 +1,5 @@
import { rgba } from 'polished'
import React, { useEffect, useRef } from 'react'
import React, { useCallback, useEffect, useRef } from 'react'
import { ImageStyle, StyleProp, TextStyle, View, ViewStyle } from 'react-native'
import { useSpring } from 'react-spring/native'
@@ -90,44 +90,12 @@ export const ColumnHeaderItem = React.memo((props: ColumnHeaderItemProps) => {
titleStyle,
} = props
const initialTheme = useTheme(theme => {
cacheRef.current.theme = theme
updateStyles()
})
const containerRef = useRef(null)
useHover(
enableBackgroundHover || enableForegroundHover ? containerRef : null,
isHovered => {
cacheRef.current.isHovered = isHovered
updateStyles()
},
)
const cacheRef = useRef({ isHovered: false, theme: initialTheme })
const [springAnimatedStyles, setSpringAnimatedStyles] = useSpring(getStyles)
useEffect(() => {
updateStyles()
}, [
backgroundColor,
disabled,
enableBackgroundHover,
enableForegroundHover,
forceHoverState,
foregroundColor,
hoverBackgroundThemeColor,
hoverForegroundThemeColor,
])
const _username = useReduxState(selectors.currentGitHubUsernameSelector)
function getStyles() {
const getStyles = useCallback(() => {
const { isHovered: _isHovered, theme } = cacheRef.current
const isHovered = (_isHovered || forceHoverState) && !disabled
const immediate =
isHovered ||
Platform.realOS === 'android' ||
!!(enableForegroundHover && !enableBackgroundHover)
@@ -144,11 +112,49 @@ export const ColumnHeaderItem = React.memo((props: ColumnHeaderItemProps) => {
: foregroundColor || theme.foregroundColor,
mutedForegroundColor: theme.foregroundColorMuted50,
}
}
}, [
backgroundColor,
disabled,
enableBackgroundHover,
enableForegroundHover,
forceHoverState,
foregroundColor,
hoverBackgroundThemeColor,
hoverForegroundThemeColor,
])
function updateStyles() {
const updateStyles = useCallback(() => {
setSpringAnimatedStyles(getStyles())
}
}, [getStyles])
const initialTheme = useTheme(
useCallback(
theme => {
cacheRef.current.theme = theme
updateStyles()
},
[updateStyles],
),
)
const containerRef = useRef(null)
useHover(
enableBackgroundHover || enableForegroundHover ? containerRef : null,
isHovered => {
cacheRef.current.isHovered = isHovered
updateStyles()
},
)
const cacheRef = useRef({ isHovered: false, theme: initialTheme })
const [springAnimatedStyles, setSpringAnimatedStyles] = useSpring(getStyles)
useEffect(() => {
updateStyles()
}, [updateStyles])
const _username = useReduxState(selectors.currentGitHubUsernameSelector)
const avatarProps = _avatarProps || {}
@@ -341,7 +347,6 @@ export const ColumnHeaderItem = React.memo((props: ColumnHeaderItemProps) => {
fontSize: 10,
textAlign: 'center',
},
style,
{ color: springAnimatedStyles.foregroundColor },
]}
numberOfLines={1}

View File

@@ -36,6 +36,7 @@ import { getSubjectTypeMetadata } from '../../utils/helpers/github/shared'
import { SpringAnimatedView } from '../animated/spring/SpringAnimatedView'
import { CardItemSeparator } from '../cards/partials/CardItemSeparator'
import { SpringAnimatedCheckbox } from '../common/Checkbox'
import { Separator } from '../common/Separator'
import { Spacer } from '../common/Spacer'
import { useAppLayout } from '../context/LayoutContext'
import { useTheme } from '../context/ThemeContext'
@@ -682,6 +683,8 @@ export const ColumnOptions = React.memo((props: ColumnOptionsProps) => {
})()}
</ScrollView>
<Separator horizontal />
<View
style={{
flexDirection: 'row',

View File

@@ -15,7 +15,6 @@ import { SpringAnimatedText } from '../animated/spring/SpringAnimatedText'
import { SpringAnimatedView } from '../animated/spring/SpringAnimatedView'
import { AccordionView } from '../common/AccordionView'
import { ConditionalWrap } from '../common/ConditionalWrap'
import { separatorSize } from '../common/Separator'
import { Spacer } from '../common/Spacer'
import {
TouchableOpacity,
@@ -91,7 +90,7 @@ export function ColumnOptionsRow(props: ColumnOptionsRowProps) {
function getStyles() {
const { isHovered, isPressing, theme } = cacheRef.current
const immediate = Platform.realOS === 'android'
const immediate = isHovered || Platform.realOS === 'android'
return {
config: { duration: immediate ? 0 : 100 },
@@ -111,10 +110,10 @@ export function ColumnOptionsRow(props: ColumnOptionsRowProps) {
<SpringAnimatedView
style={{
backgroundColor: springAnimatedStyles.backgroundColor,
borderWidth: 0,
borderColor: 'transparent',
borderBottomWidth: separatorSize,
borderBottomColor: springAnimatedTheme.backgroundColorLess1,
// borderWidth: 0,
// borderColor: 'transparent',
// borderBottomWidth: separatorSize,
// borderBottomColor: springAnimatedTheme.backgroundColorLess1,
}}
>
<ConditionalWrap

View File

@@ -0,0 +1,36 @@
import React from 'react'
import { AppViewMode, ThemeColors } from '@devhub/core'
import { useAppViewMode } from '../../hooks/use-app-view-mode'
import { Separator, SeparatorProps } from '../common/Separator'
import { useAppLayout } from '../context/LayoutContext'
import { useTheme } from '../context/ThemeContext'
export function getColumnCardBackgroundThemeColor(
_backgroundColor: string,
_appViewMode: AppViewMode,
): keyof ThemeColors {
return 'backgroundColor'
}
export interface ColumnSeparatorProps extends SeparatorProps {}
export function ColumnSeparator(props: ColumnSeparatorProps) {
const { appOrientation } = useAppLayout()
const { appViewMode } = useAppViewMode()
const theme = useTheme()
const horizontalSidebar = appOrientation === 'portrait'
return (
<Separator
backgroundThemeColor={getColumnCardBackgroundThemeColor(
theme.backgroundColor,
appViewMode,
)}
horizontal={horizontalSidebar}
thick={!horizontalSidebar}
{...props}
/>
)
}

View File

@@ -13,7 +13,7 @@ import { useEmitter } from '../../hooks/use-emitter'
import { useReduxState } from '../../hooks/use-redux-state'
import { bugsnag } from '../../libs/bugsnag'
import * as selectors from '../../redux/selectors'
import { separatorTickSize } from '../common/Separator'
import { separatorThickSize } from '../common/Separator'
import { useColumnWidth } from '../context/ColumnWidthContext'
import { useAppLayout } from '../context/LayoutContext'
@@ -113,7 +113,7 @@ export const Columns = React.memo((props: ColumnsProps) => {
style={[
styles.flatlist,
sizename > '1-small' && {
marginHorizontal: -separatorTickSize / 2,
marginHorizontal: -separatorThickSize / 2,
},
style,
]}

View File

@@ -12,7 +12,6 @@ import {
isNotificationPrivate,
ThemeColors,
} from '@devhub/core'
import { getLuminance } from 'polished'
import { useAppViewMode } from '../../hooks/use-app-view-mode'
import { useReduxAction } from '../../hooks/use-redux-action'
import { useReduxState } from '../../hooks/use-redux-state'
@@ -34,38 +33,32 @@ import { ColumnHeaderItem } from './ColumnHeaderItem'
import { ColumnOptionsRenderer } from './ColumnOptionsRenderer'
export function getColumnCardThemeColors(
backgroundColor: string,
_backgroundColor: string,
): {
column: keyof ThemeColors
unread: keyof ThemeColors
unread__hover: keyof ThemeColors
read: keyof ThemeColors
read__hover: keyof ThemeColors
} {
const luminance = getLuminance(backgroundColor)
// const luminance = getLuminance(backgroundColor)
if (luminance >= 0.5) {
return {
unread: 'backgroundColor',
unread__hover: 'backgroundColorLighther1',
read: 'backgroundColorDarker1',
read__hover: 'backgroundColorDarker2',
}
}
if (luminance <= 0.02) {
return {
unread: 'backgroundColorLighther2',
unread__hover: 'backgroundColorLighther4',
read: 'backgroundColor',
read__hover: 'backgroundColorDarker2',
}
}
// if (luminance <= 0.02) {
// return {
// column: 'backgroundColor',
// unread: 'backgroundColorLighther2',
// unread__hover: 'backgroundColorLighther4',
// read: 'backgroundColor',
// read__hover: 'backgroundColorLess3',
// }
// }
return {
unread: 'backgroundColorLighther1',
unread__hover: 'backgroundColorLighther2',
read: 'backgroundColor',
read__hover: 'backgroundColorDarker1',
column: 'backgroundColor',
unread: 'backgroundColorLighther2',
unread__hover: 'backgroundColorLighther3',
read: 'backgroundColorDarker1',
read__hover: 'backgroundColorDarker2',
}
}
@@ -109,12 +102,11 @@ export const EventOrNotificationColumn = React.memo(
useTheme(theme => {
if (!columnRef.current) return
const backgroundThemeColors = getColumnCardThemeColors(
theme.backgroundColor,
)
columnRef.current!.setNativeProps({
style: { backgroundColor: theme[backgroundThemeColors.read] },
style: {
backgroundColor:
theme[getColumnCardThemeColors(theme.backgroundColor).column],
},
})
})

View File

@@ -85,7 +85,7 @@ export const Button = React.memo((props: ButtonProps) => {
function getStyles() {
const { isHovered, isPressing, theme } = cacheRef.current
const immediate = Platform.realOS === 'android'
const immediate = isHovered || Platform.realOS === 'android'
return {
config: { duration: immediate ? 0 : 100 },

View File

@@ -23,11 +23,11 @@ const styles = StyleSheet.create({
alignSelf: 'stretch',
alignItems: 'center',
justifyContent: 'center',
padding: contentPadding / 2,
paddingHorizontal: contentPadding / 2,
paddingVertical: contentPadding / 4,
},
text: {
flexGrow: 1,
lineHeight: 14,
fontWeight: '500',
fontSize: smallTextSize,
textAlign: 'center',

View File

@@ -2,22 +2,20 @@ import React from 'react'
import { StyleSheet } from 'react-native'
import { ThemeColors } from '@devhub/core'
import { getLuminance } from 'polished'
import { useCSSVariablesOrSpringAnimatedTheme } from '../../hooks/use-css-variables-or-spring--animated-theme'
import { SpringAnimatedView } from '../animated/spring/SpringAnimatedView'
import { useTheme } from '../context/ThemeContext'
export const separatorSize = StyleSheet.hairlineWidth
export const separatorTickSize = 5
export const separatorThickSize = 5
export function getSeparatorThemeColor(
backgroundColor: string,
_backgroundColor: string,
): keyof ThemeColors {
const luminance = getLuminance(backgroundColor)
// const luminance = getLuminance(backgroundColor)
if (luminance <= 0.02) return 'backgroundColorLighther3'
if (luminance >= 0.5) return 'backgroundColorDarker3'
return 'backgroundColorDarker2'
// if (luminance <= 0.02) return 'backgroundColorLess2'
return 'backgroundColorLess1'
}
export interface SeparatorProps {
@@ -34,7 +32,7 @@ export function Separator(props: SeparatorProps) {
const theme = useTheme()
const springAnimatedTheme = useCSSVariablesOrSpringAnimatedTheme()
const size = (thick ? separatorTickSize : separatorSize) / (half ? 2 : 1)
const size = (thick ? separatorThickSize : separatorSize) / (half ? 2 : 1)
const themeField =
backgroundThemeColor || getSeparatorThemeColor(theme.backgroundColor)

View File

@@ -21,7 +21,10 @@ import {
sidebarSize,
} from '../../styles/variables'
import { SpringAnimatedSafeAreaView } from '../animated/spring/SpringAnimatedSafeAreaView'
import { getColumnHeaderThemeColors } from '../columns/ColumnHeader'
import {
ColumnHeader,
getColumnHeaderThemeColors,
} from '../columns/ColumnHeader'
import { ColumnHeaderItem } from '../columns/ColumnHeaderItem'
import { Avatar } from '../common/Avatar'
import { Link } from '../common/Link'
@@ -40,6 +43,13 @@ const styles = StyleSheet.create({
alignItems: 'center',
justifyContent: 'center',
},
itemContainerStyle__withLabel: {
width: undefined,
height: sidebarSize - contentPadding / 4,
marginTop: contentPadding / 4,
paddingBottom: contentPadding / 4,
},
})
export interface SidebarProps {
@@ -69,17 +79,35 @@ export const Sidebar = React.memo((props: SidebarProps) => {
const small = sizename === '1-small'
const large = sizename >= '3-large'
const enableBackgroundHover = !horizontal
const enableBackgroundHover = true
const showLabel = !!horizontal
const showFixedSettingsButton = !horizontal || columnIds.length >= 4
const highlightFocusedColumn = !small && appViewMode === 'single-column'
const highlightFocusedColumn =
appViewMode === 'single-column' && !currentOpenedModal
const itemContainerStyle = {
const itemContainerStyle: ViewStyle = {
width: sidebarSize,
height: sidebarSize,
marginBottom: 1,
height: horizontal
? sidebarSize
: columnHeaderItemContentBiggerSize + contentPadding * (3 / 2),
borderRadius: 0,
...(horizontal
? {
marginHorizontal: 1,
borderTopLeftRadius: sidebarSize / 2,
borderTopRightRadius: sidebarSize / 2,
}
: {
marginVertical: 1,
borderTopRightRadius: sidebarSize / 2,
borderBottomRightRadius: sidebarSize / 2,
}),
}
const SectionSpacer = horizontal
? () => null
: () => <Spacer height={contentPadding / 3} />
function isModalOpen(modalName: ModalPayload['name']) {
return !!modalStack && modalStack.some(m => m.name === modalName)
}
@@ -103,7 +131,7 @@ export const Sidebar = React.memo((props: SidebarProps) => {
}}
>
{!horizontal && (
<>
<ColumnHeader noPadding>
<ColumnHeaderItem
analyticsLabel={undefined}
hoverBackgroundThemeColor={
@@ -142,11 +170,11 @@ export const Sidebar = React.memo((props: SidebarProps) => {
/>
</Link>
</ColumnHeaderItem>
<Separator horizontal={!horizontal} />
</>
</ColumnHeader>
)}
<SectionSpacer />
<ScrollView
alwaysBounceHorizontal={false}
alwaysBounceVertical={false}
@@ -166,7 +194,10 @@ export const Sidebar = React.memo((props: SidebarProps) => {
<ColumnHeaderItem
analyticsLabel="sidebar_add"
hoverBackgroundThemeColor={
getColumnHeaderThemeColors(theme.backgroundColor).hover
isModalOpen('ADD_COLUMN')
? getColumnHeaderThemeColors(theme.backgroundColor)
.selected
: getColumnHeaderThemeColors(theme.backgroundColor).hover
}
enableBackgroundHover={enableBackgroundHover}
forceHoverState={isModalOpen('ADD_COLUMN')}
@@ -177,11 +208,12 @@ export const Sidebar = React.memo((props: SidebarProps) => {
size={columnHeaderItemContentBiggerSize}
style={[
styles.centerContainer,
!showLabel && itemContainerStyle,
itemContainerStyle,
showLabel && styles.itemContainerStyle__withLabel,
]}
/>
<Separator horizontal={!horizontal} />
{/* <Separator horizontal={!horizontal} /> */}
</>
) : null
) : (
@@ -207,7 +239,9 @@ export const Sidebar = React.memo((props: SidebarProps) => {
<ColumnHeaderItem
analyticsLabel="sidebar_settings"
hoverBackgroundThemeColor={
getColumnHeaderThemeColors(theme.backgroundColor).hover
isModalOpen('SETTINGS')
? getColumnHeaderThemeColors(theme.backgroundColor).selected
: getColumnHeaderThemeColors(theme.backgroundColor).hover
}
enableBackgroundHover={enableBackgroundHover}
forceHoverState={isModalOpen('SETTINGS')}
@@ -220,14 +254,24 @@ export const Sidebar = React.memo((props: SidebarProps) => {
}
showLabel={showLabel}
size={columnHeaderItemContentBiggerSize}
style={[styles.centerContainer, !showLabel && itemContainerStyle]}
style={[
styles.centerContainer,
itemContainerStyle,
showLabel && styles.itemContainerStyle__withLabel,
]}
/>
)}
</ScrollView>
<SectionSpacer />
<Separator horizontal={!horizontal} thick={false} />
<SectionSpacer />
{!small && (
<>
<Separator horizontal={!horizontal} />
{/* <Separator horizontal={!horizontal} /> */}
{!!large && (
<>
@@ -243,13 +287,14 @@ export const Sidebar = React.memo((props: SidebarProps) => {
onPress={() => replaceModal({ name: 'ADD_COLUMN' })}
style={[
styles.centerContainer,
!showLabel && itemContainerStyle,
itemContainerStyle,
showLabel && styles.itemContainerStyle__withLabel,
]}
showLabel={showLabel}
size={columnHeaderItemContentBiggerSize}
/>
<Separator horizontal={!horizontal} />
{/* <Separator horizontal={!horizontal} /> */}
</>
)}
</>
@@ -263,7 +308,9 @@ export const Sidebar = React.memo((props: SidebarProps) => {
<ColumnHeaderItem
analyticsLabel="sidebar_settings"
hoverBackgroundThemeColor={
getColumnHeaderThemeColors(theme.backgroundColor).hover
isModalOpen('SETTINGS')
? getColumnHeaderThemeColors(theme.backgroundColor).selected
: getColumnHeaderThemeColors(theme.backgroundColor).hover
}
enableBackgroundHover={enableBackgroundHover}
forceHoverState={isModalOpen('SETTINGS')}
@@ -276,13 +323,17 @@ export const Sidebar = React.memo((props: SidebarProps) => {
}
showLabel={showLabel}
size={columnHeaderItemContentBiggerSize}
style={[styles.centerContainer, !showLabel && itemContainerStyle]}
style={[
styles.centerContainer,
itemContainerStyle,
showLabel && styles.itemContainerStyle__withLabel,
]}
/>
)}
{large && (
<>
<Separator horizontal={!horizontal} />
{/* <Separator horizontal={!horizontal} /> */}
<ColumnHeaderItem
analyticsLabel={undefined}
@@ -292,7 +343,11 @@ export const Sidebar = React.memo((props: SidebarProps) => {
enableBackgroundHover={enableBackgroundHover}
noPadding
size={columnHeaderItemContentBiggerSize}
style={[styles.centerContainer, !showLabel && itemContainerStyle]}
style={[
styles.centerContainer,
itemContainerStyle,
showLabel && styles.itemContainerStyle__withLabel,
]}
>
<Link
analyticsLabel="sidebar_devhub_logo"
@@ -316,6 +371,8 @@ export const Sidebar = React.memo((props: SidebarProps) => {
{horizontal && (showFixedSettingsButton || large) && (
<Spacer width={contentPadding / 2} />
)}
<SectionSpacer />
</View>
</SpringAnimatedSafeAreaView>
)
@@ -362,7 +419,9 @@ const SidebarColumnItem = React.memo(
}}
forceHoverState={highlight}
hoverBackgroundThemeColor={
getColumnHeaderThemeColors(theme.backgroundColor).hover
highlight
? getColumnHeaderThemeColors(theme.backgroundColor).selected
: getColumnHeaderThemeColors(theme.backgroundColor).hover
}
enableBackgroundHover={enableBackgroundHover || highlight}
iconName={requestTypeIconAndData.icon}
@@ -380,7 +439,11 @@ const SidebarColumnItem = React.memo(
}}
showLabel={showLabel}
size={columnHeaderItemContentBiggerSize}
style={[styles.centerContainer, !showLabel && itemContainerStyle]}
style={[
styles.centerContainer,
itemContainerStyle,
showLabel && styles.itemContainerStyle__withLabel,
]}
/>
)
},

View File

@@ -26,7 +26,7 @@ import { fabSize } from '../common/FAB'
import { H2 } from '../common/H2'
import { HeaderMessage } from '../common/HeaderMessage'
import { Link } from '../common/Link'
import { separatorTickSize } from '../common/Separator'
import { separatorThickSize } from '../common/Separator'
import { Spacer } from '../common/Spacer'
import { SubHeader } from '../common/SubHeader'
import { useColumnWidth } from '../context/ColumnWidthContext'
@@ -213,7 +213,7 @@ function AddColumnModalItem({
function getStyles() {
const { isHovered, isPressing, theme } = cacheRef.current
const immediate = Platform.realOS === 'android'
const immediate = isHovered || Platform.realOS === 'android'
return {
config: { duration: immediate ? 0 : 100 },
@@ -311,7 +311,7 @@ export function AddColumnModal(props: AddColumnModalProps) {
const { sizename } = useAppLayout()
const outerSpacing = (3 / 4) * contentPadding
const availableWidth = columnWidth - 2 * separatorTickSize - 2 * outerSpacing
const availableWidth = columnWidth - 2 * separatorThickSize - 2 * outerSpacing
const hasReachedColumnLimit = columnIds.length >= constants.COLUMNS_LIMIT

View File

@@ -4,6 +4,7 @@ import { BackHandler, Dimensions, StyleSheet, View } from 'react-native'
import { ModalPayloadWithIndex } from '@devhub/core'
import { config, useTransition } from 'react-spring/native'
import { SettingsModal } from '../../components/modals/SettingsModal'
import { useAppViewMode } from '../../hooks/use-app-view-mode'
import { useCSSVariablesOrSpringAnimatedTheme } from '../../hooks/use-css-variables-or-spring--animated-theme'
import { usePrevious } from '../../hooks/use-previous'
import { useReduxAction } from '../../hooks/use-redux-action'
@@ -16,7 +17,12 @@ import * as selectors from '../../redux/selectors'
import { SpringAnimatedSafeAreaView } from '../animated/spring/SpringAnimatedSafeAreaView'
import { SpringAnimatedTouchableOpacity } from '../animated/spring/SpringAnimatedTouchableOpacity'
import { SpringAnimatedView } from '../animated/spring/SpringAnimatedView'
import { Separator, separatorTickSize } from '../common/Separator'
import { ColumnSeparator } from '../columns/ColumnSeparator'
import {
Separator,
separatorSize,
separatorThickSize,
} from '../common/Separator'
import { useColumnWidth } from '../context/ColumnWidthContext'
import { useAppLayout } from '../context/LayoutContext'
import { AddColumnDetailsModal } from './AddColumnDetailsModal'
@@ -67,6 +73,7 @@ export function ModalRenderer(props: ModalRendererProps) {
const { renderSeparator } = props
const { sizename } = useAppLayout()
const { appViewMode } = useAppViewMode()
const springAnimatedTheme = useCSSVariablesOrSpringAnimatedTheme()
const columnWidth = useColumnWidth()
@@ -106,7 +113,15 @@ export function ModalRenderer(props: ModalRendererProps) {
? true
: false)
const size = columnWidth + (renderSeparator ? separatorTickSize : 0)
const separatorMetadata =
appViewMode === 'multi-column'
? { Component: () => <ColumnSeparator />, size: separatorThickSize }
: {
Component: () => <Separator horizontal={false} thick={false} />,
size: separatorSize,
}
const size = columnWidth + (renderSeparator ? separatorMetadata.size : 0)
const overlayTransition = useTransition<boolean, any>(
currentOpenedModal && sizename > '1-small' ? [true] : [],
@@ -179,7 +194,7 @@ export function ModalRenderer(props: ModalRendererProps) {
from: { right: size },
enter: { right: 0 },
update: { right: 0 },
leave: { right: size + separatorTickSize },
leave: { right: size + separatorThickSize },
},
)
@@ -267,7 +282,7 @@ export function ModalRenderer(props: ModalRendererProps) {
...animatedStyle,
}}
>
<Separator thick />
<separatorMetadata.Component />
</SpringAnimatedView>
),
)}

View File

@@ -0,0 +1,7 @@
import { useState } from 'react'
export function useForceRerender() {
const [, setValue] = useState(false)
return () => setValue(value => !value)
}

View File

@@ -1,7 +1,8 @@
import { useEffect, useRef, useState } from 'react'
import { useCallback, useEffect, useRef } from 'react'
import { useReduxStore } from '../redux/context/ReduxStoreContext'
import { RootState } from '../redux/types'
import { useForceRerender } from './use-force-rerender'
export type ExtractSelector<S> = S extends (state: any) => infer R
? (state: RootState) => R
@@ -14,26 +15,26 @@ export function useReduxState<S extends (state: any) => any>(
callback?: (value: Result<S>) => void,
) {
const store = useReduxStore()
const cacheRef = useRef<Result<S>>(selector(store.getState()))
const forceRerender = useForceRerender()
const [result, setResult] = useState<Result<S>>(() =>
selector(store.getState()),
const resolve = useCallback(
(value: Result<S>) => {
if (cacheRef.current === value) return
cacheRef.current = value
if (callback) {
callback(value)
return
}
forceRerender()
},
[callback],
)
const cacheRef = useRef(result)
useEffect(() => {
if (callback) callback(result)
}, [])
useEffect(() => {
update()
return store.subscribe(() => {
update()
})
}, [store, selector])
function update() {
const update = useCallback(() => {
if (!selector) {
resolve(undefined as any)
return
@@ -41,20 +42,22 @@ export function useReduxState<S extends (state: any) => any>(
const newResult = selector(store.getState())
resolve(newResult)
}
}, [resolve, store, selector])
const resolve = (value: Result<S>) => {
if (cacheRef.current === value) return
useEffect(() => {
update()
cacheRef.current = value
return store.subscribe(() => {
update()
})
}, [store, update])
if (callback) {
callback(value)
return
}
useEffect(() => {
if (callback) callback(cacheRef.current)
setResult(value)
}
// TODO: investigate why [callback] causes some bugs,
// e.g. on single-column mode + toggle modal the sidebar bg gets broken
}, [])
return result
return cacheRef.current
}

View File

@@ -4,6 +4,7 @@ import React, { useCallback, useEffect, useMemo, useRef } from 'react'
import { Dimensions, StyleSheet, View } from 'react-native'
import url from 'url'
import { ColumnSeparator } from '../components/columns/ColumnSeparator'
import { ColumnsRenderer } from '../components/columns/ColumnsRenderer'
import { ConditionalWrap } from '../components/common/ConditionalWrap'
import { Screen } from '../components/common/Screen'
@@ -335,11 +336,11 @@ export const MainScreen = React.memo(() => {
zIndex={1000}
/>
<Separator
horizontal={horizontalSidebar}
thick={!horizontalSidebar}
zIndex={1000}
/>
{horizontalSidebar ? (
<Separator horizontal zIndex={1000} />
) : (
<ColumnSeparator zIndex={1000} />
)}
<ConditionalWrap
key="main-screen-content-container-conditional-wrap"

View File

@@ -26,10 +26,10 @@ export function createThemeFromColor(
const backgroundColor = color
const amount1 = luminance <= 0.02 ? 0.05 : 0.04
const amount2 = 2 * amount1
const amount3 = 3 * amount1
const amount4 = 4 * amount1
const amount1 = 0.03
const amount2 = 0.05
const amount3 = 0.07
const amount4 = 0.09
const backgroundColorDarker1 = darken(amount1, color)
const backgroundColorDarker2 = darken(amount2, color)

View File

@@ -1,3 +1,3 @@
import { createThemeFromColor } from './custom'
export const theme = createThemeFromColor('#000000', 'dark-black', 'Dark Black')
export const theme = createThemeFromColor('#111111', 'dark-black', 'Dark Black')

View File

@@ -1,7 +1,7 @@
import { createThemeFromColor } from './custom'
export const theme = createThemeFromColor(
'#F0F0F0',
'#F5F5F5',
'light-gray',
'Light Gray',

View File

@@ -1,7 +1,7 @@
import { createThemeFromColor } from './custom'
export const theme = createThemeFromColor(
'#FBFBFB',
'#FFFFFF',
'light-white',
'Light White',
{ primaryBackgroundColor: '#000000', primaryForegroundColor: '#FFFFFF' },

View File

@@ -34,10 +34,6 @@ body {
-moz-osx-font-smoothing: grayscale;
}
a:hover, a:hover > *:not([class*='touchable']) {
text-decoration: underline;
}
input:focus {
outline: none !important;
}