mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 23:19:40 +01:00
fix sidebar navigation
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import {Dimensions, View} from 'react-native';
|
||||
import {GestureHandlerRootView} from 'react-native-gesture-handler';
|
||||
import ScrollableTabView from 'react-native-scrollable-tab-view';
|
||||
import ContextMenu from './src/components/ContextMenu';
|
||||
import {DialogManager} from './src/components/DialogManager';
|
||||
import {DummyText} from './src/components/DummyText';
|
||||
import {Menu} from './src/components/Menu';
|
||||
import SideMenu from './src/components/SideMenu/SideMenu';
|
||||
import {Toast} from './src/components/Toast';
|
||||
import {NavigationStack} from './src/navigation/Drawer';
|
||||
import {NavigatorStack} from './src/navigation/NavigatorStack';
|
||||
import {useTracked} from './src/provider';
|
||||
import {Actions} from './src/provider/Actions';
|
||||
@@ -24,7 +25,7 @@ import {
|
||||
eOpenFullscreenEditor,
|
||||
eOpenSideMenu,
|
||||
} from './src/utils/Events';
|
||||
import {editorRef, sideMenuRef, tabBarRef} from './src/utils/Refs';
|
||||
import {editorRef, tabBarRef} from './src/utils/Refs';
|
||||
import {EditorWrapper} from './src/views/Editor/EditorWrapper';
|
||||
import {getIntent, getNote, post} from './src/views/Editor/Functions';
|
||||
|
||||
@@ -34,7 +35,7 @@ let layoutTimer = null;
|
||||
|
||||
const onChangeTab = async (obj) => {
|
||||
if (obj.i === 1) {
|
||||
sideMenuRef.current?.setGestureEnabled(false);
|
||||
eSendEvent(eCloseSideMenu);
|
||||
if (getIntent()) return;
|
||||
movedAway = false;
|
||||
if (!editing.currentlyEditing || !getNote()) {
|
||||
@@ -47,7 +48,7 @@ const onChangeTab = async (obj) => {
|
||||
editing.currentlyEditing = false;
|
||||
post('blur');
|
||||
}
|
||||
sideMenuRef.current?.setGestureEnabled(true);
|
||||
eSendEvent(eOpenSideMenu);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -57,7 +58,7 @@ export const RootView = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppStack />
|
||||
<NavigationStack component={AppStack} />
|
||||
<Toast />
|
||||
<ContextMenu />
|
||||
<DummyText />
|
||||
@@ -66,6 +67,18 @@ export const RootView = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const getDefaultDrawerWidth = ({height, width}) => {
|
||||
const smallerAxisSize = Math.min(height, width);
|
||||
const isLandscape = width > height;
|
||||
const isTablet = smallerAxisSize >= 600;
|
||||
const appBarHeight = Platform.OS === 'ios' ? (isLandscape ? 32 : 44) : 56;
|
||||
const maxWidth = isTablet ? 320 : 280;
|
||||
|
||||
return Math.min(smallerAxisSize - appBarHeight, maxWidth);
|
||||
};
|
||||
|
||||
const GestureHandlerWrapper = GestureHandlerRootView ?? View;
|
||||
|
||||
const AppStack = React.memo(
|
||||
() => {
|
||||
const [state, dispatch] = useTracked();
|
||||
@@ -117,9 +130,8 @@ const AppStack = React.memo(
|
||||
let size = event?.nativeEvent?.layout;
|
||||
if (!size || (size.width === dimensions.width && mode !== null)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
layoutTimer = setTimeout(async () => {
|
||||
eSendEvent(eCloseSideMenu);
|
||||
setDimensions({
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
@@ -131,7 +143,6 @@ const AppStack = React.memo(
|
||||
|
||||
if (DDS.isLargeTablet()) {
|
||||
setMode('tablet');
|
||||
sideMenuRef.current?.setGestureEnabled(false);
|
||||
dispatch({type: Actions.DEVICE_MODE, state: 'tablet'});
|
||||
dispatch({type: Actions.FULLSCREEN, state: false});
|
||||
editorRef.current?.setNativeProps({
|
||||
@@ -146,7 +157,7 @@ const AppStack = React.memo(
|
||||
setMode('smallTablet');
|
||||
dispatch({type: Actions.DEVICE_MODE, state: 'smallTablet'});
|
||||
dispatch({type: Actions.FULLSCREEN, state: false});
|
||||
sideMenuRef.current?.setGestureEnabled(false);
|
||||
|
||||
editorRef.current?.setNativeProps({
|
||||
style: {
|
||||
position: 'relative',
|
||||
@@ -160,7 +171,7 @@ const AppStack = React.memo(
|
||||
tabBarRef.current?.goToPage(1);
|
||||
}
|
||||
} else {
|
||||
sideMenuRef.current?.setGestureEnabled(true);
|
||||
eSendEvent(eOpenSideMenu);
|
||||
setMode('mobile');
|
||||
dispatch({type: Actions.DEVICE_MODE, state: 'mobile'});
|
||||
dispatch({type: Actions.FULLSCREEN, state: false});
|
||||
@@ -182,99 +193,88 @@ const AppStack = React.memo(
|
||||
};
|
||||
|
||||
return (
|
||||
<SideMenu
|
||||
ref={sideMenuRef}
|
||||
containerStyle={{
|
||||
backgroundColor: colors.bg,
|
||||
<ScrollableTabView
|
||||
ref={tabBarRef}
|
||||
style={{
|
||||
zIndex: 1,
|
||||
}}
|
||||
menu={mode === 'mobile' ? <Menu /> : null}>
|
||||
<ScrollableTabView
|
||||
ref={tabBarRef}
|
||||
style={{
|
||||
zIndex: 1,
|
||||
}}
|
||||
initialPage={0}
|
||||
prerenderingSiblingsNumber={Infinity}
|
||||
onChangeTab={onChangeTab}
|
||||
renderTabBar={() => <></>}>
|
||||
{mode && mode !== 'tablet' && (
|
||||
initialPage={0}
|
||||
prerenderingSiblingsNumber={Infinity}
|
||||
onChangeTab={onChangeTab}
|
||||
renderTabBar={() => <></>}>
|
||||
{mode && mode !== 'tablet' && (
|
||||
<View
|
||||
style={{
|
||||
width: dimensions.width,
|
||||
height: '100%',
|
||||
borderRightColor: colors.nav,
|
||||
borderRightWidth: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
}}>
|
||||
{mode && mode === 'smallTablet' && (
|
||||
<View
|
||||
style={{
|
||||
height: '100%',
|
||||
width: dimensions.width * 0.35,
|
||||
}}>
|
||||
<Menu />
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View
|
||||
style={{
|
||||
width: dimensions.width,
|
||||
height: '100%',
|
||||
width:
|
||||
mode === 'mobile'
|
||||
? dimensions.width
|
||||
: dimensions.width * 0.65,
|
||||
}}>
|
||||
<NavigatorStack />
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
flexDirection: 'row',
|
||||
backgroundColor: colors.bg,
|
||||
}}
|
||||
onLayout={_onLayout}>
|
||||
{mode && mode === 'tablet' && (
|
||||
<View
|
||||
style={{
|
||||
width: dimensions.width * 0.45,
|
||||
height: '100%',
|
||||
borderRightColor: colors.nav,
|
||||
borderRightWidth: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
}}>
|
||||
{mode && mode === 'smallTablet' && (
|
||||
<View
|
||||
style={{
|
||||
height: '100%',
|
||||
width: dimensions.width * 0.35,
|
||||
}}>
|
||||
<Menu />
|
||||
</View>
|
||||
)}
|
||||
<View
|
||||
style={{
|
||||
height: '100%',
|
||||
width: dimensions.width * 0.15,
|
||||
}}>
|
||||
<Menu />
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
height: '100%',
|
||||
width:
|
||||
mode === 'mobile'
|
||||
? dimensions.width
|
||||
: dimensions.width * 0.65,
|
||||
width: dimensions.width * 0.3,
|
||||
}}>
|
||||
<NavigatorStack />
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
flexDirection: 'row',
|
||||
backgroundColor: colors.bg,
|
||||
}}
|
||||
onLayout={_onLayout}>
|
||||
{mode && mode === 'tablet' && (
|
||||
<View
|
||||
style={{
|
||||
width: dimensions.width * 0.45,
|
||||
height: '100%',
|
||||
borderRightColor: colors.nav,
|
||||
borderRightWidth: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
}}>
|
||||
<View
|
||||
style={{
|
||||
height: '100%',
|
||||
width: dimensions.width * 0.15,
|
||||
}}>
|
||||
<Menu />
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
height: '100%',
|
||||
width: dimensions.width * 0.3,
|
||||
}}>
|
||||
<NavigatorStack />
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
{mode && <EditorWrapper dimensions={dimensions} />}
|
||||
</View>
|
||||
</ScrollableTabView>
|
||||
</SideMenu>
|
||||
{mode && <EditorWrapper dimensions={dimensions} />}
|
||||
</View>
|
||||
</ScrollableTabView>
|
||||
);
|
||||
},
|
||||
() => true,
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import React from 'react';
|
||||
import {useTracked} from '../../provider';
|
||||
import {DDS} from '../../services/DeviceDetection';
|
||||
import { useTracked } from '../../provider';
|
||||
import NavigationService from '../../services/Navigation';
|
||||
import {sideMenuRef} from '../../utils/Refs';
|
||||
import {SIZE} from '../../utils/SizeUtils';
|
||||
import {ActionIcon} from '../ActionIcon';
|
||||
import { SIZE } from '../../utils/SizeUtils';
|
||||
import { ActionIcon } from '../ActionIcon';
|
||||
|
||||
export const HeaderLeftMenu = () => {
|
||||
const [state] = useTracked();
|
||||
@@ -12,7 +10,7 @@ export const HeaderLeftMenu = () => {
|
||||
|
||||
const onLeftButtonPress = () => {
|
||||
if (headerMenuState) {
|
||||
sideMenuRef.current?.openMenu(true);
|
||||
NavigationService.openDrawer()
|
||||
return;
|
||||
}
|
||||
NavigationService.goBack();
|
||||
|
||||
@@ -46,7 +46,7 @@ export const ColorSection = ({noTextMode}) => {
|
||||
|
||||
NavigationService.navigate('NotesPage', params);
|
||||
eSendEvent(refreshNotesPage, params);
|
||||
sideMenuRef.current?.openMenu(false);
|
||||
NavigationService.closeDrawer()
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -35,7 +35,7 @@ export const MenuListItem = ({item, index, noTextMode, ignore, testID}) => {
|
||||
NavigationService.navigate(item.name);
|
||||
}
|
||||
if (item.close) {
|
||||
sideMenuRef.current?.openMenu(false)
|
||||
NavigationService.closeDrawer()
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ export const TagsSection = () => {
|
||||
});
|
||||
NavigationService.navigate('NotesPage', params);
|
||||
eSendEvent(refreshNotesPage, params);
|
||||
sideMenuRef.current?.openMenu(false)
|
||||
NavigationService.closeDrawer()
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,320 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import {
|
||||
Dimensions,
|
||||
PanResponder,
|
||||
TouchableWithoutFeedback,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import Animated, {Easing} from 'react-native-reanimated';
|
||||
import styles from './styles';
|
||||
|
||||
const deviceScreen = Dimensions.get('window');
|
||||
const barrierForward = deviceScreen.width / 5;
|
||||
|
||||
function shouldOpenMenu(dx) {
|
||||
return dx > barrierForward;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {SideMenu.propTypes} propTypes
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {propTypes} props
|
||||
* @extends {React.Component<propTypes, {}>}}
|
||||
*/
|
||||
export default class SideMenu extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.prevLeft = 0;
|
||||
this.isOpen = !!props.isOpen;
|
||||
this.isGestureEnabled = true;
|
||||
this.overlay;
|
||||
this.opacity = new Animated.Value(0);
|
||||
|
||||
const initialMenuPositionMultiplier =
|
||||
props.menuPosition === 'right' ? -1 : 1;
|
||||
const openOffsetMenuPercentage = props.openMenuOffset / deviceScreen.width;
|
||||
const hiddenMenuOffsetPercentage =
|
||||
props.hiddenMenuOffset / deviceScreen.width;
|
||||
const left = new Animated.Value(
|
||||
props.isOpen
|
||||
? props.openMenuOffset * initialMenuPositionMultiplier
|
||||
: props.hiddenMenuOffset,
|
||||
);
|
||||
|
||||
this.onLayoutChange = this.onLayoutChange.bind(this);
|
||||
this.onStartShouldSetResponderCapture = props.onStartShouldSetResponderCapture.bind(
|
||||
this,
|
||||
);
|
||||
this.onMoveShouldSetPanResponder = this.handleMoveShouldSetPanResponder.bind(
|
||||
this,
|
||||
);
|
||||
this.onPanResponderMove = this.handlePanResponderMove.bind(this);
|
||||
this.onPanResponderRelease = this.handlePanResponderEnd.bind(this);
|
||||
this.onPanResponderTerminate = this.handlePanResponderEnd.bind(this);
|
||||
|
||||
this.state = {
|
||||
width: deviceScreen.width,
|
||||
height: deviceScreen.height,
|
||||
openOffsetMenuPercentage,
|
||||
openMenuOffset: deviceScreen.width * openOffsetMenuPercentage,
|
||||
hiddenMenuOffsetPercentage,
|
||||
hiddenMenuOffset: deviceScreen.width * hiddenMenuOffsetPercentage,
|
||||
left,
|
||||
};
|
||||
}
|
||||
|
||||
onLayoutChange(e) {
|
||||
const {width, height} = e.nativeEvent.layout;
|
||||
const openMenuOffset = width * this.state.openOffsetMenuPercentage;
|
||||
const hiddenMenuOffset = width * this.state.hiddenMenuOffsetPercentage;
|
||||
this.setState({width, height, openMenuOffset, hiddenMenuOffset});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content view. This view will be rendered over menu
|
||||
* @return {React.Component}
|
||||
*/
|
||||
getContentView() {
|
||||
//let overlay = null;
|
||||
|
||||
const {width, height} = this.state;
|
||||
const ref = (sideMenu) => (this.sideMenu = sideMenu);
|
||||
const style = [
|
||||
styles.frontView,
|
||||
{width, height},
|
||||
this.props.animationStyle(this.state.left),
|
||||
this.props.containerStyle,
|
||||
];
|
||||
|
||||
return (
|
||||
<Animated.View style={style} ref={ref} {...this.responder.panHandlers}>
|
||||
{this.props.children}
|
||||
|
||||
<TouchableWithoutFeedback onPress={() => this.openMenu(false)}>
|
||||
<Animated.View
|
||||
ref={(ref) => (this.overlay = ref)}
|
||||
onTouchStart={() => {}}
|
||||
style={{
|
||||
display: 'none',
|
||||
position: 'relative',
|
||||
top: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: 'black',
|
||||
opacity: this.opacity,
|
||||
zIndex: 1,
|
||||
}}
|
||||
/>
|
||||
</TouchableWithoutFeedback>
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
|
||||
changeOpacity(opacity) {
|
||||
if (opacity === 0.5) {
|
||||
this.overlay.setNativeProps({
|
||||
style: {
|
||||
display: 'flex',
|
||||
position: 'absolute',
|
||||
zIndex: 999,
|
||||
},
|
||||
});
|
||||
}
|
||||
Animated.timing(this.opacity, {
|
||||
toValue: opacity,
|
||||
duration: 200,
|
||||
easing: Easing.inOut(Easing.ease),
|
||||
}).start(() => {
|
||||
if (opacity < 0.5) {
|
||||
this.overlay.setNativeProps({
|
||||
style: {
|
||||
display: 'none',
|
||||
position: 'relative',
|
||||
zIndex: -1,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
moveLeft(offset) {
|
||||
const newOffset = this.menuPositionMultiplier() * offset;
|
||||
Animated.timing(this.state.left, {
|
||||
toValue: newOffset,
|
||||
duration: 200,
|
||||
easing: Easing.elastic(0.5),
|
||||
}).start();
|
||||
this.prevLeft = newOffset;
|
||||
}
|
||||
|
||||
menuPositionMultiplier() {
|
||||
return this.props.menuPosition === 'right' ? -1 : 1;
|
||||
}
|
||||
|
||||
handlePanResponderMove(e, gestureState) {
|
||||
if (this.state.left.__getValue() * this.menuPositionMultiplier() >= 0) {
|
||||
let newLeft = this.prevLeft + gestureState.dx;
|
||||
if (newLeft >= this.props.openMenuOffset || newLeft < 0) return;
|
||||
if (
|
||||
!this.props.bounceBackOnOverdraw &&
|
||||
Math.abs(newLeft) > this.state.openMenuOffset
|
||||
) {
|
||||
newLeft = this.menuPositionMultiplier() * this.state.openMenuOffset;
|
||||
}
|
||||
this.state.left.setValue(newLeft);
|
||||
this.props.onMove(newLeft);
|
||||
let o = newLeft / this.props.openMenuOffset;
|
||||
this.opacity.setValue(o * 0.5);
|
||||
|
||||
this.overlay.setNativeProps({
|
||||
style: {
|
||||
display: 'flex',
|
||||
position: 'absolute',
|
||||
zIndex: 999,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handlePanResponderEnd(e, gestureState) {
|
||||
const offsetLeft =
|
||||
this.menuPositionMultiplier() *
|
||||
(this.state.left.__getValue() + gestureState.dx);
|
||||
|
||||
this.openMenu(shouldOpenMenu(offsetLeft));
|
||||
}
|
||||
|
||||
handleMoveShouldSetPanResponder(e, gestureState) {
|
||||
if (this.gesturesAreEnabled()) {
|
||||
const x = Math.round(Math.abs(gestureState.dx));
|
||||
const y = Math.round(Math.abs(gestureState.dy));
|
||||
|
||||
const touchMoved = x > this.props.toleranceX && y < this.props.toleranceY;
|
||||
|
||||
if (this.isOpen) {
|
||||
return touchMoved;
|
||||
}
|
||||
|
||||
const withinEdgeHitWidth =
|
||||
this.props.menuPosition === 'right'
|
||||
? gestureState.moveX > deviceScreen.width - this.props.edgeHitWidth
|
||||
: gestureState.moveX < this.props.edgeHitWidth;
|
||||
|
||||
const swipingToOpen = this.menuPositionMultiplier() * gestureState.dx > 0;
|
||||
return withinEdgeHitWidth && touchMoved && swipingToOpen;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
openMenu(isOpen) {
|
||||
const {hiddenMenuOffset, openMenuOffset} = this.state;
|
||||
this.changeOpacity(isOpen ? 0.5 : 0);
|
||||
this.moveLeft(isOpen ? openMenuOffset : hiddenMenuOffset);
|
||||
|
||||
this.isOpen = isOpen;
|
||||
|
||||
this.forceUpdate();
|
||||
this.props.onChange(isOpen);
|
||||
}
|
||||
|
||||
setGestureEnabled(enabled) {
|
||||
this.isGestureEnabled = enabled;
|
||||
}
|
||||
|
||||
gesturesAreEnabled() {
|
||||
return this.isGestureEnabled;
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.responder = PanResponder.create({
|
||||
onStartShouldSetResponderCapture: this.onStartShouldSetResponderCapture,
|
||||
onMoveShouldSetPanResponder: this.onMoveShouldSetPanResponder,
|
||||
onPanResponderMove: this.onPanResponderMove,
|
||||
onPanResponderRelease: this.onPanResponderRelease,
|
||||
onPanResponderTerminate: this.onPanResponderTerminate,
|
||||
});
|
||||
}
|
||||
|
||||
_getOverlayViewRef = (data) => {
|
||||
//this.overlayViewRef = data.ref;
|
||||
};
|
||||
|
||||
render() {
|
||||
const boundryStyle =
|
||||
this.props.menuPosition === 'right'
|
||||
? {left: this.state.width - this.state.openMenuOffset}
|
||||
: {right: this.state.width - this.state.openMenuOffset};
|
||||
|
||||
const menu = (
|
||||
<View style={[styles.menu, boundryStyle]}>
|
||||
{this.props.isFullscreen ? null : this.props.menu}
|
||||
</View>
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.container} onLayout={this.onLayoutChange}>
|
||||
{menu}
|
||||
|
||||
{this.getContentView()}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SideMenu.propTypes = {
|
||||
edgeHitWidth: PropTypes.number,
|
||||
toleranceX: PropTypes.number,
|
||||
toleranceY: PropTypes.number,
|
||||
menuPosition: PropTypes.oneOf(['left', 'right']),
|
||||
onChange: PropTypes.func,
|
||||
onMove: PropTypes.func,
|
||||
children: PropTypes.node,
|
||||
menu: PropTypes.node,
|
||||
openMenuOffset: PropTypes.number,
|
||||
hiddenMenuOffset: PropTypes.number,
|
||||
animationStyle: PropTypes.func,
|
||||
disableGestures: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]),
|
||||
animationFunction: PropTypes.func,
|
||||
onStartShouldSetResponderCapture: PropTypes.func,
|
||||
isOpen: PropTypes.bool,
|
||||
bounceBackOnOverdraw: PropTypes.bool,
|
||||
autoClosing: PropTypes.bool,
|
||||
};
|
||||
|
||||
SideMenu.defaultProps = {
|
||||
toleranceY: 10,
|
||||
toleranceX: 10,
|
||||
edgeHitWidth: 60,
|
||||
children: null,
|
||||
menu: null,
|
||||
openMenuOffset: deviceScreen.width * (2 / 3),
|
||||
disableGestures: false,
|
||||
menuPosition: 'left',
|
||||
hiddenMenuOffset: 0,
|
||||
onMove: () => {},
|
||||
onStartShouldSetResponderCapture: () => true,
|
||||
onChange: () => {},
|
||||
onSliding: () => {},
|
||||
animationStyle: (value) => ({
|
||||
transform: [
|
||||
{
|
||||
translateX: value,
|
||||
},
|
||||
],
|
||||
}),
|
||||
animationFunction: (prop, value) =>
|
||||
Animated.timing(prop, {
|
||||
toValue: value,
|
||||
duration: 300,
|
||||
easing: Easing.elastic(0.5),
|
||||
}),
|
||||
isOpen: false,
|
||||
bounceBackOnOverdraw: true,
|
||||
autoClosing: true,
|
||||
};
|
||||
@@ -1,34 +0,0 @@
|
||||
// @flow
|
||||
|
||||
import {StyleSheet} from 'react-native';
|
||||
|
||||
const absoluteStretch = {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
};
|
||||
|
||||
export default StyleSheet.create({
|
||||
container: {
|
||||
...absoluteStretch,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
menu: {
|
||||
...absoluteStretch,
|
||||
},
|
||||
frontView: {
|
||||
flex: 1,
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
backgroundColor: 'transparent',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
overlay: {
|
||||
...absoluteStretch,
|
||||
backgroundColor: 'black',
|
||||
opacity: 0,
|
||||
},
|
||||
});
|
||||
57
apps/mobile/src/navigation/Drawer.js
Normal file
57
apps/mobile/src/navigation/Drawer.js
Normal file
@@ -0,0 +1,57 @@
|
||||
import {createDrawerNavigator} from '@react-navigation/drawer';
|
||||
import {NavigationContainer} from '@react-navigation/native';
|
||||
import * as React from 'react';
|
||||
import {Menu} from '../components/Menu';
|
||||
import {useTracked} from '../provider';
|
||||
import {eSubscribeEvent, eUnSubscribeEvent} from '../services/EventManager';
|
||||
import {eCloseSideMenu, eOpenSideMenu} from '../utils/Events';
|
||||
import {sideMenuRef} from '../utils/Refs';
|
||||
import {NavigatorStack} from './NavigatorStack';
|
||||
|
||||
const Drawer = createDrawerNavigator();
|
||||
|
||||
export const NavigationStack = ({component = NavigatorStack}) => {
|
||||
const [state] = useTracked();
|
||||
const {deviceMode} = state;
|
||||
const [locked, setLocked] = React.useState(false);
|
||||
|
||||
const setGestureDisabled = () => {
|
||||
setLocked(true);
|
||||
};
|
||||
|
||||
const setGestureEnabled = () => {
|
||||
setLocked(false);
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
eSubscribeEvent(eOpenSideMenu, setGestureEnabled);
|
||||
eSubscribeEvent(eCloseSideMenu, setGestureDisabled);
|
||||
return () => {
|
||||
eUnSubscribeEvent(eOpenSideMenu, setGestureEnabled);
|
||||
eUnSubscribeEvent(eCloseSideMenu, setGestureDisabled);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<NavigationContainer ref={sideMenuRef}>
|
||||
<Drawer.Navigator
|
||||
screenOptions={{
|
||||
swipeEnabled: locked || deviceMode !== 'mobile' ? false : true,
|
||||
gestureEnabled: locked || deviceMode !== 'mobile' ? false : true,
|
||||
}}
|
||||
drawerStyle={{
|
||||
width: deviceMode !== 'mobile' ? 0 : '65%',
|
||||
}}
|
||||
edgeWidth={200}
|
||||
drawerType="slide"
|
||||
drawerContent={deviceMode !== 'mobile' ? () => <></> : DrawerComponent}
|
||||
initialRouteName="Main">
|
||||
<Drawer.Screen name="Main" component={component} />
|
||||
</Drawer.Navigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const DrawerComponent = () => {
|
||||
return <Menu />;
|
||||
};
|
||||
@@ -13,10 +13,10 @@ function push(...args) {
|
||||
}
|
||||
|
||||
function openDrawer() {
|
||||
//sideMenuRef.current?.dispatch(DrawerActions.openDrawer());
|
||||
sideMenuRef.current?.dispatch(DrawerActions.openDrawer());
|
||||
}
|
||||
function closeDrawer() {
|
||||
// sideMenuRef.current?.dispatch(DrawerActions.closeDrawer());
|
||||
sideMenuRef.current?.dispatch(DrawerActions.closeDrawer());
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
604
apps/mobile/src/views/Home/ls.js
Normal file
604
apps/mobile/src/views/Home/ls.js
Normal file
@@ -0,0 +1,604 @@
|
||||
export const delta_data = {
|
||||
type: 'delta',
|
||||
data: [
|
||||
{insert: 'Today, former '},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#663366',
|
||||
link:
|
||||
'https://en.wikipedia.org/wiki/Vice_President_of_the_United_States',
|
||||
},
|
||||
insert: 'Vice President of the United States',
|
||||
},
|
||||
{insert: ' '},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#0b0080',
|
||||
link: 'https://en.wikinews.org/wiki/Joe_Biden',
|
||||
},
|
||||
insert: 'Joe Biden',
|
||||
},
|
||||
{insert: ' was projected by multiple media outlets to have surpassed 270 '},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#663366',
|
||||
link: 'https://en.wikipedia.org/wiki/United_States_Electoral_College',
|
||||
},
|
||||
insert: 'electoral college',
|
||||
},
|
||||
{insert: ' delegate total and therefore become the 46th '},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#0b0080',
|
||||
link: 'https://en.wikinews.org/wiki/President_of_the_United_States',
|
||||
},
|
||||
insert: 'President of the United States',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
' elect.\nHis running mate, Kamala Harris, would become the first female and first African- and Asian-American vice president.\nAt around 11:25am ',
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#663366',
|
||||
link:
|
||||
'https://en.wikipedia.org/wiki/Eastern_Standard_Time_(North_America)',
|
||||
},
|
||||
insert: 'US east coast time',
|
||||
},
|
||||
{insert: ' (1625 '},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#663366',
|
||||
link: 'https://en.wikipedia.org/wiki/UTC',
|
||||
},
|
||||
insert: 'UTC',
|
||||
},
|
||||
{insert: '), the '},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#0b0080',
|
||||
link: 'https://en.wikinews.org/wiki/Associated_Press',
|
||||
},
|
||||
insert: 'Associated Press',
|
||||
},
|
||||
{insert: ' (AP) called the election for Biden, as did '},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#0b0080',
|
||||
link: 'https://en.wikinews.org/wiki/NBC_News',
|
||||
},
|
||||
insert: 'NBC News',
|
||||
},
|
||||
{insert: ', when Biden was declared to have won '},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#0b0080',
|
||||
link: 'https://en.wikinews.org/wiki/Pennsylvania',
|
||||
},
|
||||
insert: 'Pennsylvania',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
"'s 20 electoral college votes. Later in the day, the AP and NBC News also called ",
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#0b0080',
|
||||
link: 'https://en.wikinews.org/wiki/Nevada',
|
||||
},
|
||||
insert: 'Nevada',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
" for Biden, giving him an additional six electoral college votes, for a total by NBC's reckoning of 279 electoral votes to President ",
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#0b0080',
|
||||
link: 'https://en.wikinews.org/wiki/Donald_Trump',
|
||||
},
|
||||
insert: 'Donald Trump',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
"'s 214, or 290 electoral votes by AP's reckoning.\nElectoral college results map when the election was called for Biden.",
|
||||
},
|
||||
{
|
||||
attributes: {height: '128', width: '220'},
|
||||
insert: {
|
||||
image:
|
||||
'https://upload.wikimedia.org/wikinews/en/thumb/3/38/ElectoralCollege2020_with_results_for_Wikinews_11072020.svg/220px-ElectoralCollege2020_with_results_for_Wikinews_11072020.svg.png',
|
||||
},
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n'},
|
||||
{insert: 'Image: '},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#663366',
|
||||
link: 'https://commons.wikimedia.org/wiki/user:Kingofthedead',
|
||||
},
|
||||
insert: 'Kingofthedead',
|
||||
},
|
||||
{insert: '.'},
|
||||
{attributes: {align: 'center'}, insert: '\n'},
|
||||
{
|
||||
insert:
|
||||
'Biden said in a statement, "I am honored and humbled by the trust the American people have placed in me and in Vice President-elect Harris". He added, "With the campaign over, it\'s time to put the anger and the harsh rhetoric behind us and come together as a nation. It\'s time for America to unite. And to heal [...] We are the United States of America. And there\'s nothing we can\'t do, if we do it together."\nPresident Trump has yet to concede, saying earlier in the morning before the call for Biden, "I WON THIS ELECTION, BY A LOT!" on ',
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#0b0080',
|
||||
link: 'https://en.wikinews.org/wiki/Twitter',
|
||||
},
|
||||
insert: 'Twitter',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
". Following the announcement of Biden's win, Trump issued a statement at ",
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#663366',
|
||||
link:
|
||||
'https://en.wikipedia.org/wiki/Trump_National_Golf_Club_Washington,_D.C.',
|
||||
},
|
||||
insert: 'his golf club',
|
||||
},
|
||||
{insert: ' outside '},
|
||||
{
|
||||
attributes: {
|
||||
background: 'initial',
|
||||
color: '#0b0080',
|
||||
link: 'https://en.wikinews.org/wiki/Washington,_D.C.',
|
||||
},
|
||||
insert: 'Washington, D.C.',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
' saying, "The simple fact is this election is far from over. Joe Biden has not been certified as the winner of any states, let alone any of the highly contested states headed for mandatory recounts, or states where our campaign has valid and legitimate legal challenges that could determine the ultimate victor". The lack of a concession from Trump has no legal standing.\n\nJoseph Robinette Biden Jr. was elected the 46th president of the United States on Saturday, promising to restore political normalcy and a spirit of national unity to confront raging health and economic crises, and making Donald J. Trump a one-term president after four years of tumult in the White House.\nMr. Biden’s victory amounted to a repudiation of Mr. Trump by millions of voters exhausted with his divisive conduct and chaotic administration, and was delivered by an unlikely alliance of women, people of color, old and young voters and a sliver of disaffected Republicans. Mr. Trump is only the third ',
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
color: '#326891',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/11/upshot/election-red-blue-economic-divide.html',
|
||||
},
|
||||
insert: 'elected',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
' president since World War II to lose re-election, and the first in more than a quarter-century.\nThe result also provided a history-making moment for Mr. Biden’s running mate, Senator Kamala Harris of California, who will become the first woman to serve as vice president.\nWith his triumph, Mr. Biden, who turns 78 later this month, fulfilled his decades-long ambition in his third bid for the White House, becoming the oldest person elected president. A pillar of Washington who was first elected amid the Watergate scandal, and who prefers political consensus over combat, Mr. Biden will lead a nation and a Democratic Party that have become far more ideological since his arrival in the capital in 1973.\nADVERTISEMENT',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/07/us/politics/biden-election.html#after-story-ad-1',
|
||||
},
|
||||
insert: 'Continue reading the main story',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n\n'},
|
||||
{
|
||||
insert:
|
||||
'He offered a mainstream Democratic agenda, yet it was less his policy platform than his biography to which many voters gravitated. Seeking the nation’s highest office a half-century after his first campaign, Mr. Biden — a candidate in the late autumn of his career — presented his life of setback and recovery to voters as a parable for a wounded country.\nAppearing Saturday night before supporters at a drive-in rally in Wilmington, Del., and speaking against the din of enthusiastic honking, Mr. Biden claimed the presidency and called on the country to reunite after what he described as a toxic political interlude.\n',
|
||||
},
|
||||
{attributes: {bold: true}, insert: 'Thanks for reading The Times.'},
|
||||
{attributes: {align: 'center', list: 'bullet'}, insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
bold: true,
|
||||
color: '#326891',
|
||||
link: 'https://www.nytimes.com/subscription?campaignId=9L9L9',
|
||||
},
|
||||
insert: 'Subscribe to The Times',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n'},
|
||||
{
|
||||
insert:
|
||||
'“Let this grim era of demonization in America begin to end here and now,” he said.\nWithout addressing Mr. Trump, the president-elect spoke directly to the president’s supporters and said he recognized their disappointment. “I’ve lost a couple of times myself,” he recalled of his past failures to win the presidency, before adding: “Now let’s give each other a chance.”\nIn a statement earlier in the day, Mr. Trump insisted “this election is far from over” and vowed that his campaign would “start prosecuting our case in court” but offered no details.\nMr. Biden’s victory, which came 48 years to the day after he was first elected to the United States Senate, set off jubilant celebrations in Democratic-leaning cities. In Washington, people streamed into the streets near the White House and cheered as cars bearing American flags drove by honking.\nEditors’ Picks',
|
||||
},
|
||||
{attributes: {header: 2}, insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/08/arts/television/saturday-night-live-dave-chappelle.html?action=click&algo=als_engaged1_desk_filter&block=editors_picks_recirc&fellback=false&imp_id=151568062&impression_id=7263ff30-2713-11eb-ac57-f7fb164a26ff&index=0&pgtype=Article®ion=ccolumn&req_id=989100184&surface=home-featured&action=click&module=editorContent&pgtype=Article®ion=CompanionColumn&contentCollection=Trending',
|
||||
},
|
||||
insert: {
|
||||
image:
|
||||
'https://static01.nyt.com/images/2020/11/09/arts/08snl-dave-chappelle/08snl-dave-chappelle-square640.jpg?quality=75&auto=webp&disable=upscale&width=350',
|
||||
},
|
||||
},
|
||||
{insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/08/arts/television/saturday-night-live-dave-chappelle.html?action=click&algo=als_engaged1_desk_filter&block=editors_picks_recirc&fellback=false&imp_id=151568062&impression_id=7263ff30-2713-11eb-ac57-f7fb164a26ff&index=0&pgtype=Article®ion=ccolumn&req_id=989100184&surface=home-featured&action=click&module=editorContent&pgtype=Article®ion=CompanionColumn&contentCollection=Trending',
|
||||
},
|
||||
insert: '‘Saturday Night Live’ Sends Off Trump With a Ballad',
|
||||
},
|
||||
{attributes: {header: 3}, insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/13/us/murder-hornets-us.html?action=click&algo=als_engaged1_desk_filter&block=editors_picks_recirc&fellback=false&imp_id=183138092&impression_id=7263ff31-2713-11eb-ac57-f7fb164a26ff&index=1&pgtype=Article®ion=ccolumn&req_id=989100184&surface=home-featured&action=click&module=editorContent&pgtype=Article®ion=CompanionColumn&contentCollection=Trending',
|
||||
},
|
||||
insert: {
|
||||
image:
|
||||
'https://static01.nyt.com/images/2020/11/12/multimedia/12xp-murder-hornets-dead/12xp-murder-hornets-dead-square640-v2.jpg?quality=75&auto=webp&disable=upscale&width=350',
|
||||
},
|
||||
},
|
||||
{insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/13/us/murder-hornets-us.html?action=click&algo=als_engaged1_desk_filter&block=editors_picks_recirc&fellback=false&imp_id=183138092&impression_id=7263ff31-2713-11eb-ac57-f7fb164a26ff&index=1&pgtype=Article®ion=ccolumn&req_id=989100184&surface=home-featured&action=click&module=editorContent&pgtype=Article®ion=CompanionColumn&contentCollection=Trending',
|
||||
},
|
||||
insert:
|
||||
'Scientists Destroyed a Nest of Murder Hornets. Here’s What They Learned.',
|
||||
},
|
||||
{attributes: {header: 3}, insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/08/sports/football/nfl-results.html?action=click&algo=als_engaged1_desk_filter&block=editors_picks_recirc&fellback=false&imp_id=588258951&impression_id=7263ff32-2713-11eb-ac57-f7fb164a26ff&index=2&pgtype=Article®ion=ccolumn&req_id=989100184&surface=home-featured&action=click&module=editorContent&pgtype=Article®ion=CompanionColumn&contentCollection=Trending',
|
||||
},
|
||||
insert: {
|
||||
image:
|
||||
'https://static01.nyt.com/images/2020/11/08/sports/08nfl-wwl-top/08nfl-wwl-top-square640-v2.jpg?quality=75&auto=webp&disable=upscale&width=350',
|
||||
},
|
||||
},
|
||||
{insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/08/sports/football/nfl-results.html?action=click&algo=als_engaged1_desk_filter&block=editors_picks_recirc&fellback=false&imp_id=588258951&impression_id=7263ff32-2713-11eb-ac57-f7fb164a26ff&index=2&pgtype=Article®ion=ccolumn&req_id=989100184&surface=home-featured&action=click&module=editorContent&pgtype=Article®ion=CompanionColumn&contentCollection=Trending',
|
||||
},
|
||||
insert: 'What We Learned From Week 9 of the N.F.L. Season',
|
||||
},
|
||||
{attributes: {header: 3}, insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/07/us/politics/biden-election.html?action=click&module=editorContent&pgtype=Article®ion=CompanionColumn&contentCollection=Trending#after-pp_edpick',
|
||||
},
|
||||
insert: 'Continue reading the main story',
|
||||
},
|
||||
{insert: '\n\nADVERTISEMENT'},
|
||||
{attributes: {align: 'center'}, insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/07/us/politics/biden-election.html#after-story-ad-2',
|
||||
},
|
||||
insert: 'Continue reading the main story',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n\n\n'},
|
||||
{
|
||||
insert:
|
||||
'The race, which concluded after four tense days of vote-counting in a handful of battlegrounds, was a singular referendum on Mr. Trump in a way no president’s re-election has been in modern times. He coveted the attention, and voters who either adored him or loathed him were eager to render judgment on his tenure. From the beginning to the end of the race, Mr. Biden made the president’s character central to his campaign.\nThis unrelenting focus propelled Mr. Biden to victory in historically Democratic strongholds in the industrial Midwest',
|
||||
},
|
||||
{attributes: {italic: true, bold: true}, insert: ' '},
|
||||
{
|
||||
insert:
|
||||
'with Mr. Biden forging a coalition of suburbanites and big-city residents to claim at least three',
|
||||
},
|
||||
{attributes: {bold: true}, insert: ' '},
|
||||
{
|
||||
insert:
|
||||
'states his party lost in 2016. With ballots still being counted in several states, Mr. Biden was leading Mr. Trump in the popular vote by more than four million votes.\nYet even as they turned Mr. Trump out of office, voters sent a more uncertain message about the left-of-center platform Mr. Biden ran on as Democrats lost seats in the House and made only modest gains in the Senate. The divided judgment — a rare example of ticket splitting in partisan times — demonstrated that, for many voters, their disdain for the president was as personal as it was political.\nEven in defeat, though, Mr. Trump demonstrated his enduring appeal to many white voters and his intense popularity in rural areas, underscoring the deep national divisions that Mr. Biden has vowed to heal.\nIn his address Saturday, Mr. Biden saluted Black voters, recalling how they revived his campaign at “its lowest ebb,” back in February, and vowed to honor their loyalty. He said the voters had made clear they wanted both parties “to cooperate in their interest” and said he’d reach out to Republicans and Democrats alike.\n',
|
||||
},
|
||||
{
|
||||
insert: {
|
||||
image:
|
||||
'https://static01.nyt.com/images/2020/11/06/us/politics/06bidenwins-trump/06bidenwins-trump-articleLarge.jpg?quality=75&auto=webp&disable=upscale',
|
||||
},
|
||||
},
|
||||
{insert: '\n\nImage\n\n'},
|
||||
{
|
||||
attributes: {
|
||||
alt:
|
||||
'President Trump was the first incumbent president to lose his re-election bid in more than a quarter-century.',
|
||||
},
|
||||
insert: {
|
||||
image:
|
||||
'https://static01.nyt.com/images/2020/11/06/us/politics/06bidenwins-trump/06bidenwins-trump-articleLarge.jpg?quality=75&auto=webp&disable=upscale',
|
||||
},
|
||||
},
|
||||
{
|
||||
insert:
|
||||
'\n\nPresident Trump was the first incumbent president to lose his re-election bid in more than a quarter-century.',
|
||||
},
|
||||
{attributes: {color: '#888888'}, insert: 'Credit...'},
|
||||
{insert: '\n\n'},
|
||||
{attributes: {color: '#888888'}, insert: 'Doug Mills/The New York Times'},
|
||||
{
|
||||
insert:
|
||||
'\n\nThe outcome of the race came into focus slowly as states and municipalities grappled with the legal and logistical challenges of voting in the midst of the coronavirus pandemic. With an enormous backlog of early and mail-in votes, some states reported their totals in a halting fashion that in the early hours of Wednesday painted a misleadingly rosy picture for Mr. Trump.\nADVERTISEMENT',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/07/us/politics/biden-election.html#after-story-ad-3',
|
||||
},
|
||||
insert: 'Continue reading the main story',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n\n\n'},
|
||||
{
|
||||
insert:
|
||||
'But as the big cities of the Midwest and West began to report their totals, the advantage in the race shifted the electoral map in Mr. Biden’s favor. By Wednesday afternoon, the former vice president had rebuilt much of the so-called blue wall in the Midwest, reclaiming the historically Democratic battlegrounds of Wisconsin and Michigan that Mr. Trump carried four years ago. And on Saturday, with troves of ballots coming in from Philadelphia and Pittsburgh, he took back Pennsylvania as well.\nWhile Mr. Biden stopped short of claiming victory as the week unfolded, he appeared several times in his home state, Delaware, to express confidence that he could win, while urging patience as the nation awaited the results. Even as he sought to claim something of an electoral mandate, noting that he had earned more in the popular vote than any other candidate in history, Mr. Biden struck a tone of reconciliation.\nIt would soon be time, he said, “to unite, to heal, to come together as a nation.”\nIn the days after the election, Mr. Biden and his party faced a barrage of attacks from Mr. Trump. The president falsely claimed in a middle-of-the-night appearance at the White House on Wednesday that he had won the race and that Democrats were conjuring fraudulent votes to undermine him, a theme he renewed on Thursday evening in grievance-filled remarks conjuring up, with no evidence, a conspiracy to steal votes from him.\nThe president’s campaign aides adopted a tone of brash defiance as swing states fell to Mr. Biden, promising a flurry of legal action. But while Mr. Trump’s ire had the potential to foment political divisions, there was ',
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
color: '#326891',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/06/us/politics/trump-election-voter-fraud.html',
|
||||
},
|
||||
insert: 'no indication that he could succeed',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
' with his seemingly improvisational legal strategy.\nThrough it all, the coronavirus and its ravages on the country hung over the election and shaped the choice for voters. Facing an electorate already fatigued by his aberrant conduct, the president effectively sealed his defeat by minimizing a pandemic that has created simultaneous health and economic crises.\nBeginning with the outbreak of the virus in the country at the start of the year, through his own diagnosis last month and up to the last hours of the election, he ',
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
color: '#326891',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/07/18/us/politics/trump-coronavirus-response-failure-leadership.html',
|
||||
},
|
||||
insert: 'disregarded his medical advisers and public opinion',
|
||||
},
|
||||
{insert: ' even as '},
|
||||
{
|
||||
attributes: {
|
||||
color: '#326891',
|
||||
link:
|
||||
'https://www.nytimes.com/interactive/2020/us/coronavirus-us-cases.html',
|
||||
},
|
||||
insert: 'over 230,000 people',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
' in the United States perished.\nMr. Biden, by contrast, sought to channel the dismay of those appalled by Mr. Trump’s ',
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
color: '#326891',
|
||||
link: 'https://www.nytimes.com/2020/10/02/us/politics/trump-covid.html',
|
||||
},
|
||||
insert: 'mismanagement of the pandemic',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
'. He offered himself as a safe harbor for a broad array of Americans, promising to guide the nation out of what he called the “dark winter” of the outbreak, rather than delivering a visionary message with bright ideological themes.\nADVERTISEMENT',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/07/us/politics/biden-election.html#after-story-ad-4',
|
||||
},
|
||||
insert: 'Continue reading the main story',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n\n\n'},
|
||||
{
|
||||
insert:
|
||||
'While the president ridiculed mask-wearing and insisted on continuing his large rallies, ',
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
color: '#326891',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/10/31/us/politics/stanford-study-infections-trump-rallies.html',
|
||||
},
|
||||
insert: 'endangering',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
' his own staff members and supporters, Mr. Biden and Ms. Harris campaigned with caution, avoiding indoor events, insisting on social distancing and always wearing masks.\n',
|
||||
},
|
||||
{
|
||||
insert: {
|
||||
image:
|
||||
'https://static01.nyt.com/images/2020/11/04/us/politics/04bidenwinsHFO-f2/merlin_179504964_10f3acc1-675d-4cfc-9b0c-eed89bbb60ed-articleLarge.jpg?quality=75&auto=webp&disable=upscale',
|
||||
},
|
||||
},
|
||||
{insert: '\n\nImage\n\n'},
|
||||
{
|
||||
attributes: {
|
||||
alt:
|
||||
'Ms. Harris, a senator from California will be the first woman to serve as vice president.',
|
||||
},
|
||||
insert: {
|
||||
image:
|
||||
'https://static01.nyt.com/images/2020/11/04/us/politics/04bidenwinsHFO-f2/merlin_179504964_10f3acc1-675d-4cfc-9b0c-eed89bbb60ed-articleLarge.jpg?quality=75&auto=webp&disable=upscale',
|
||||
},
|
||||
},
|
||||
{
|
||||
insert:
|
||||
'\n\nMs. Harris, a senator from California will be the first woman to serve as vice president.',
|
||||
},
|
||||
{attributes: {color: '#888888'}, insert: 'Credit...'},
|
||||
{insert: '\n\n'},
|
||||
{
|
||||
attributes: {color: '#888888'},
|
||||
insert: 'Michelle V. Agins/The New York Times',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
'\n\nConvinced that he could win back the industrial Northern states that swung to Mr. Trump four years ago, Mr. Biden focused his energy on Michigan, Wisconsin and Pennsylvania. Mr. Biden triumphed in those states on the strength of overwhelming support from women, who voted in large numbers to repudiate Mr. Trump despite his last-minute pleas to “suburban housewives,” as he called them.\nMany of the women who decided the president’s fate were politically moderate college-educated suburbanites, who made their presence felt as an electoral force first in the 2018 midterm elections, when a historic wave of female candidates and voters served as the driving force behind the Democratic sweep to power in the House.\nEven aside from the pandemic, the 2020 campaign unfolded against a backdrop of national tumult unequaled in recent history, including the House’s vote to impeach the president less than a year ago, a national wave of protests over racial injustice last spring, spasms of civil unrest throughout the summer, the death of a Supreme Court justice in September and the hospitalization of Mr. Trump in October.\nAlong the way, Mr. Trump played to his conservative base, seeking to divide the nation over race and cultural flash points. He encouraged those fears, and the underlying social divisions that fostered them. And for months he sought to sow doubt over the legitimacy of the political process.\nMr. Biden, in response, offered a message of healing that appealed to Americans from far left to center right. He made common cause by promising relief from the unceasing invective and dishonesty of Mr. Trump’s presidency.\nADVERTISEMENT',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/07/us/politics/biden-election.html#after-story-ad-5',
|
||||
},
|
||||
insert: 'Continue reading the main story',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n\n\n'},
|
||||
{
|
||||
insert:
|
||||
'The former vice president also sought to demonstrate his differences with the president with his selection of Ms. Harris, 56, whose presence on the ticket as the daughter of Indian and Jamaican immigrants stood in stark contrast to Mr. Trump’s relentless scapegoating of migrants and members of racial-minority groups.\nMr. Biden will be only the second Catholic to attain the presidency, along with John F. Kennedy.\n',
|
||||
},
|
||||
{
|
||||
insert: {
|
||||
image:
|
||||
'https://static01.nyt.com/images/2020/11/04/us/politics/04bidenwinsHFO-f5/merlin_179592678_1d772458-b4e8-4070-a5be-6aa41b163c76-articleLarge.jpg?quality=75&auto=webp&disable=upscale',
|
||||
},
|
||||
},
|
||||
{insert: '\n\nImage\n\n'},
|
||||
{
|
||||
attributes: {
|
||||
alt:
|
||||
'Mr. Biden’s election represented the culmination of nearly four years of activism in opposition to Mr. Trump.',
|
||||
},
|
||||
insert: {
|
||||
image:
|
||||
'https://static01.nyt.com/images/2020/11/04/us/politics/04bidenwinsHFO-f5/merlin_179592678_1d772458-b4e8-4070-a5be-6aa41b163c76-articleLarge.jpg?quality=75&auto=webp&disable=upscale',
|
||||
},
|
||||
},
|
||||
{
|
||||
insert:
|
||||
'\n\nMr. Biden’s election represented the culmination of nearly four years of activism in opposition to Mr. Trump.',
|
||||
},
|
||||
{attributes: {color: '#888888'}, insert: 'Credit...'},
|
||||
{insert: '\n\n'},
|
||||
{
|
||||
attributes: {color: '#888888'},
|
||||
insert: 'Kenny Holston for The New York Times',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
'\n\nIn an era when political differences have metastasized into tribal warfare, at least 74 million voters turned to a figure who has become known as the ',
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
color: '#326891',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/06/11/us/politics/joe-biden-funeral-speech.html',
|
||||
},
|
||||
insert: 'eulogist in chief',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
' for his empathy and friendships with Republicans and Democrats alike.\nIn a sign of how much Mr. Trump alienated traditional Republicans, a number of prominent members of the party ',
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
color: '#326891',
|
||||
link:
|
||||
'https://www.nytimes.com/article/republicans-voting-for-biden-not-trump.html',
|
||||
},
|
||||
insert: 'endorsed Mr. Biden’s candidacy',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
', including Cindy McCain, the widow of former Senator John McCain; the party’s other two presidential nominees this century, George W. Bush and Mitt Romney, declined to endorse Mr. Trump.\nYet for all his lofty language about uniting the country, Mr. Biden was a halting candidate who ran a cautious campaign, determined to ensure that the election became a referendum on Mr. Trump. The former vice president fully returned to the campaign trail only around Labor Day, and for weeks he limited his appearances to one state every other day or so. He went west of the Central time zone just once during the general election.\nAs he prepares to take the oath, he will return to Washington confronting a daunting set of crises. Mr. Biden will be pressed to swiftly secure and distribute a safe vaccine for the coronavirus, revive an economy that may be in even more dire shape in January than it is now, and address racial justice and policing issues that this year prompted some of the largest protests in American history.\nAnd he will do so with a Congress that is far more polarized than the Senate he left over a decade ago, with many Republicans having embraced Mr. Trump’s nativist brand of populism and Democrats increasingly responsive to an energized left. If Mr. Biden cannot bridge that divide as president and elicit some cooperation from the G.O.P., he will face immense pressure from his party’s progressive wing to abandon conciliation for a posture of combat.\nADVERTISEMENT',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/07/us/politics/biden-election.html#after-story-ad-6',
|
||||
},
|
||||
insert: 'Continue reading the main story',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n\n\n'},
|
||||
{insert: 'Mr. Biden has '},
|
||||
{
|
||||
attributes: {
|
||||
color: '#326891',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/08/20/us/politics/biden-congress.html',
|
||||
},
|
||||
insert: 'held out hope',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
' about working with Republican lawmakers while declining to support his party’s most ambitious goals, like single-payer health care and the Green New Deal; he has resisted structural changes such as ',
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
color: '#326891',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/10/22/us/politics/biden-supreme-court-packing.html',
|
||||
},
|
||||
insert: 'adding justices to the Supreme Court',
|
||||
},
|
||||
{
|
||||
insert:
|
||||
'.\nThis irked his party’s base but made it difficult for Republicans, from Mr. Trump down the ballot, to portray him as an extremist. Mr. Biden was largely absent from the appeals of G.O.P. candidates, who instead used their advertising to insist that the Democratic Party would be in the hands of more polarizing figures on the left such as Senator Bernie Sanders.\nUnlike the last two Democrats who defeated incumbents after voters tired of Republican leadership, Jimmy Carter and Bill Clinton, Mr. Biden will not arrive in the capital as a youthful outsider. Instead, he will fill out a Democratic leadership triumvirate, which includes Speaker Nancy Pelosi and Senator Chuck Schumer, of lawmakers who are 70 or older.\nMr. Biden alluded to himself during the campaign as a transitional figure who would bring the country out of a crisis and then make way for a new generation. But he has privately rejected suggestions that he commit to serving just a single term, viewing that as an instant guarantee of lame-duck status.\n',
|
||||
},
|
||||
{
|
||||
insert: {
|
||||
image:
|
||||
'https://static01.nyt.com/images/2020/11/04/us/politics/04bidenwinsHFO-f4-sub/merlin_179394966_fe8d015e-36d3-48f3-aa62-e9f6f1eb81fe-articleLarge.jpg?quality=75&auto=webp&disable=upscale',
|
||||
},
|
||||
},
|
||||
{insert: '\n\nImage\n\n'},
|
||||
{
|
||||
attributes: {
|
||||
alt:
|
||||
'As the big cities of the Midwest and West began to report their totals, places like Detroit began to shift the balance of the electoral map in Mr. Biden’s favor.',
|
||||
},
|
||||
insert: {
|
||||
image:
|
||||
'https://static01.nyt.com/images/2020/11/04/us/politics/04bidenwinsHFO-f4-sub/merlin_179394966_fe8d015e-36d3-48f3-aa62-e9f6f1eb81fe-articleLarge.jpg?quality=75&auto=webp&disable=upscale',
|
||||
},
|
||||
},
|
||||
{
|
||||
insert:
|
||||
'\n\nAs the big cities of the Midwest and West began to report their totals, places like Detroit began to shift the balance of the electoral map in Mr. Biden’s favor.',
|
||||
},
|
||||
{attributes: {color: '#888888'}, insert: 'Credit...'},
|
||||
{insert: '\n\n'},
|
||||
{attributes: {color: '#888888'}, insert: 'Erin Schaff/The New York Times'},
|
||||
{
|
||||
insert:
|
||||
'\n\nOne of the most significant tests of Mr. Biden’s presidency will be in how he navigates the widening divisions in his party.\nHe may enjoy a honeymoon, though, because of both the scale of the problems he is grappling with and the president he defeated.\nADVERTISEMENT',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n'},
|
||||
{
|
||||
attributes: {
|
||||
color: 'black',
|
||||
link:
|
||||
'https://www.nytimes.com/2020/11/07/us/politics/biden-election.html#after-story-ad-7',
|
||||
},
|
||||
insert: 'Continue reading the main story',
|
||||
},
|
||||
{attributes: {align: 'center'}, insert: '\n\n\n'},
|
||||
{
|
||||
insert:
|
||||
'This election represented the culmination of nearly four years of activism organized around opposing Mr. Trump, a movement that began with the Women’s March the day after his inauguration. Indeed, Mr. Biden’s election appeared less the unique achievement of a political standard-bearer than the apex of a political wave touched off by the 2016 election — one that Mr. Biden rode more than he directed it.\nBut Mr. Trump’s job approval rating never hit 50 percent and, when the coronavirus spread nationwide and Mr. Biden effectively claimed the Democratic nomination in March, the president’s hopes of running with a booming economy and against a far-left opponent evaporated at once.\nStill, many Democrats were nervous and some Republicans were defiantly optimistic going into the election, both still gripped by Mr. Trump’s shocker four years ago. And well into the night Tuesday, it seemed as if the president might be able to do it again. But four days later, after a year of trial in America and four turbulent years of the Trump administration, victory was in hand for Mr. Biden.\n\n',
|
||||
},
|
||||
],
|
||||
};
|
||||
Reference in New Issue
Block a user