mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 23:19:40 +01:00
add JumpToDialog
This commit is contained in:
@@ -44,7 +44,8 @@ import {TEMPLATE_DELETE, TEMPLATE_PERMANANT_DELETE} from './Templates';
|
||||
import {hexToRGBA} from "../../utils/ColorUtils";
|
||||
import {DDS} from "../../services/DeviceDetection";
|
||||
import ResultDialog from '../ResultDialog';
|
||||
import Index from "../SortDialog";
|
||||
import SortDialog from "../SortDialog";
|
||||
import JumpToDialog from '../JumpToDialog';
|
||||
|
||||
export class DialogManager extends Component {
|
||||
constructor(props) {
|
||||
@@ -369,7 +370,8 @@ export class DialogManager extends Component {
|
||||
<ResultDialog/>
|
||||
<VaultDialog colors={colors} />
|
||||
<MoveNoteDialog colors={colors} />
|
||||
<Index colors={colors} />
|
||||
<SortDialog colors={colors} />
|
||||
<JumpToDialog/>
|
||||
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,36 +1,48 @@
|
||||
import React from 'react';
|
||||
import {useTracked} from '../../provider';
|
||||
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
|
||||
import {Text, TouchableOpacity} from "react-native";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import {eSendEvent} from "../../services/EventManager";
|
||||
import {eOpenSortDialog} from "../../utils/Events";
|
||||
import {SIZE, WEIGHT} from '../../utils/SizeUtils';
|
||||
import {Text, TouchableOpacity} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import {eSendEvent} from '../../services/EventManager';
|
||||
import {eOpenSortDialog} from '../../utils/Events';
|
||||
|
||||
export const HeaderMenu = () => {
|
||||
const [state,] = useTracked();
|
||||
const {colors,settings} = state;
|
||||
const [state] = useTracked();
|
||||
const {colors, settings} = state;
|
||||
|
||||
|
||||
return <TouchableOpacity
|
||||
onPress={() => {
|
||||
eSendEvent(eOpenSortDialog);
|
||||
}}
|
||||
activeOpacity={1}
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
eSendEvent(eOpenSortDialog);
|
||||
}}
|
||||
activeOpacity={1}
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
}}>
|
||||
<Text
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
fontSize: SIZE.xs + 1,
|
||||
fontFamily: WEIGHT.regular,
|
||||
color: colors.pri,
|
||||
marginRight: 5,
|
||||
height: 30,
|
||||
textAlignVertical: 'bottom',
|
||||
}}>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: SIZE.xs + 1,
|
||||
fontFamily: WEIGHT.regular,
|
||||
color: colors.pri,
|
||||
marginRight: 5
|
||||
}}>
|
||||
{settings.sort.slice(0,1).toUpperCase() + settings.sort.slice(1,settings.sort.length)}
|
||||
</Text>
|
||||
<Icon color={colors.pri}
|
||||
name={settings.sortOrder === "asc" ? "sort-ascending" : "sort-descending"}
|
||||
size={SIZE.md}/>
|
||||
{settings.sort.slice(0, 1).toUpperCase() +
|
||||
settings.sort.slice(1, settings.sort.length)}
|
||||
</Text>
|
||||
<Icon
|
||||
color={colors.pri}
|
||||
name={
|
||||
settings.sortOrder === 'asc' ? 'sort-ascending' : 'sort-descending'
|
||||
}
|
||||
style={{
|
||||
textAlignVertical: 'bottom',
|
||||
height: 30,
|
||||
}}
|
||||
size={SIZE.md}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
121
apps/mobile/src/components/JumpToDialog/index.js
Normal file
121
apps/mobile/src/components/JumpToDialog/index.js
Normal file
@@ -0,0 +1,121 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { ScrollView, Text, View } from 'react-native';
|
||||
import BaseDialog from '../../components/Dialog/base-dialog';
|
||||
import { PressableButton } from '../../components/PressableButton';
|
||||
import Seperator from '../../components/Seperator';
|
||||
import { useTracked } from '../../provider';
|
||||
import { DDS } from '../../services/DeviceDetection';
|
||||
import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/EventManager';
|
||||
import { getElevation } from '../../utils';
|
||||
import {
|
||||
eCloseJumpToDialog,
|
||||
eOpenJumpToDialog
|
||||
} from '../../utils/Events';
|
||||
import { SIZE, WEIGHT } from '../../utils/SizeUtils';
|
||||
import Paragraph from '../Typography/Paragraph';
|
||||
|
||||
const JumpToDialog = () => {
|
||||
const [state] = useTracked();
|
||||
const {notes, colors, settings} = state;
|
||||
const [visible,setVisible] = useState(false)
|
||||
|
||||
useEffect(() => {});
|
||||
console.log(notes.filter((i) => i.type === 'header'));
|
||||
|
||||
const onPress = (item, index) => {
|
||||
let offset = 30 * index;
|
||||
let ind = notes.findIndex(
|
||||
(i) => i.title === item.title && i.type === 'header',
|
||||
);
|
||||
ind = ind + 1;
|
||||
ind = ind - (index + 1);
|
||||
offset = offset + ind * 100;
|
||||
scrollRef.current?.scrollToOffset(0, index === 0 ? 0 : offset + 50, true);
|
||||
close();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
eSubscribeEvent(eOpenJumpToDialog, open);
|
||||
eSubscribeEvent(eCloseJumpToDialog, close);
|
||||
|
||||
return () => {
|
||||
eUnSubscribeEvent(eOpenJumpToDialog, open);
|
||||
eUnSubscribeEvent(eCloseJumpToDialog, close);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const open = () => {
|
||||
setVisible(true);
|
||||
};
|
||||
|
||||
const close = () => {
|
||||
setVisible(false);
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
<BaseDialog onRequestClose={close} visible={visible}>
|
||||
<View
|
||||
style={{
|
||||
...getElevation(5),
|
||||
width: DDS.isTab ? 500 : '80%',
|
||||
backgroundColor: colors.bg,
|
||||
zIndex: 100,
|
||||
bottom: 20,
|
||||
maxHeight: '65%',
|
||||
borderRadius: 5,
|
||||
alignSelf: 'center',
|
||||
padding: 10,
|
||||
}}>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: SIZE.xl,
|
||||
fontFamily: WEIGHT.bold,
|
||||
color: colors.heading,
|
||||
alignSelf: 'center',
|
||||
}}>
|
||||
{settings.sort.slice(0, 1).toUpperCase() +
|
||||
settings.sort.slice(1, settings.sort.length)}
|
||||
</Text>
|
||||
<Seperator />
|
||||
<ScrollView
|
||||
style={{
|
||||
maxHeight: '100%',
|
||||
}}>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
alignSelf: 'center',
|
||||
justifyContent: 'center',
|
||||
}}>
|
||||
{notes
|
||||
.filter((i) => i.type === 'header')
|
||||
.map((item, index) => (
|
||||
<PressableButton
|
||||
onPress={() => onPress(item, index)}
|
||||
selectedColor={colors.nav}
|
||||
customStyle={{
|
||||
minWidth: '20%',
|
||||
maxWidth: '46%',
|
||||
width: null,
|
||||
padding: 15,
|
||||
margin: 5,
|
||||
}}>
|
||||
<Paragraph
|
||||
size={SIZE.xs}
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
}}>
|
||||
{item.title}
|
||||
</Paragraph>
|
||||
</PressableButton>
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</BaseDialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default JumpToDialog
|
||||
@@ -1,402 +1,417 @@
|
||||
import React, {useCallback, useEffect, useMemo, useState} from 'react';
|
||||
import {Platform, RefreshControl, StyleSheet, Text, useWindowDimensions, View,} from 'react-native';
|
||||
import {initialWindowMetrics, useSafeAreaInsets} from 'react-native-safe-area-context';
|
||||
import {
|
||||
Platform,
|
||||
RefreshControl,
|
||||
StyleSheet,
|
||||
Text,
|
||||
useWindowDimensions,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import {DataProvider, LayoutProvider, RecyclerListView} from 'recyclerlistview';
|
||||
import {useTracked} from '../../provider';
|
||||
import {Actions} from '../../provider/Actions';
|
||||
import {eSendEvent, ToastEvent} from '../../services/EventManager';
|
||||
import {eClearSearch, eOpenLoginDialog, eScrollEvent} from '../../utils/Events';
|
||||
import {eClearSearch, eOpenJumpToDialog, eOpenLoginDialog, eScrollEvent} from '../../utils/Events';
|
||||
import {PressableButton} from '../PressableButton';
|
||||
import {COLORS_NOTE} from '../../utils/Colors';
|
||||
import {SIZE, WEIGHT} from '../../utils/SizeUtils';
|
||||
import {db} from '../../utils/DB';
|
||||
import {HeaderMenu} from "../Header/HeaderMenu";
|
||||
import {HeaderMenu} from '../Header/HeaderMenu';
|
||||
|
||||
const header = {
|
||||
type: 'MAIN_HEADER',
|
||||
type: 'MAIN_HEADER',
|
||||
};
|
||||
|
||||
const SimpleList = ({
|
||||
data,
|
||||
type,
|
||||
placeholder,
|
||||
RenderItem,
|
||||
focused,
|
||||
customRefresh,
|
||||
customRefreshing,
|
||||
refreshCallback,
|
||||
sortMenuButton
|
||||
}) => {
|
||||
const [state, dispatch] = useTracked();
|
||||
const {colors, selectionMode, messageBoardState} = state;
|
||||
const searchResults = {...state.searchResults};
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [dataProvider, setDataProvider] = useState(
|
||||
new DataProvider((r1, r2) => {
|
||||
return r1 !== r2;
|
||||
}),
|
||||
);
|
||||
const {width, fontScale} = useWindowDimensions();
|
||||
const insets = useSafeAreaInsets();
|
||||
data,
|
||||
type,
|
||||
placeholder,
|
||||
RenderItem,
|
||||
focused,
|
||||
customRefresh,
|
||||
customRefreshing,
|
||||
refreshCallback,
|
||||
sortMenuButton,
|
||||
scrollRef,
|
||||
jumpToDialog
|
||||
}) => {
|
||||
const [state, dispatch] = useTracked();
|
||||
const {colors, selectionMode, messageBoardState} = state;
|
||||
const searchResults = {...state.searchResults};
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [dataProvider, setDataProvider] = useState(
|
||||
new DataProvider((r1, r2) => {
|
||||
return r1 !== r2;
|
||||
}),
|
||||
);
|
||||
const {width, fontScale} = useWindowDimensions();
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
const listData = data;
|
||||
const dataType = type;
|
||||
const _onScroll = (event) => {
|
||||
if (!event) return;
|
||||
let y = event.nativeEvent.contentOffset.y;
|
||||
eSendEvent(eScrollEvent, y);
|
||||
};
|
||||
const listData = data;
|
||||
const dataType = type;
|
||||
const _onScroll = (event) => {
|
||||
if (!event) return;
|
||||
let y = event.nativeEvent.contentOffset.y;
|
||||
eSendEvent(eScrollEvent, y);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
loadData();
|
||||
}, [listData]);
|
||||
useEffect(() => {
|
||||
loadData();
|
||||
}, [listData]);
|
||||
|
||||
const loadData = () => {
|
||||
let mainData =
|
||||
searchResults.type === type &&
|
||||
focused() &&
|
||||
searchResults.results.length > 0
|
||||
? searchResults.results
|
||||
: listData;
|
||||
const loadData = () => {
|
||||
let mainData =
|
||||
searchResults.type === type &&
|
||||
focused() &&
|
||||
searchResults.results.length > 0
|
||||
? searchResults.results
|
||||
: listData;
|
||||
|
||||
let d = [header, ...mainData];
|
||||
setDataProvider(dataProvider.cloneWithRows(d));
|
||||
};
|
||||
let d = [header, ...mainData];
|
||||
setDataProvider(dataProvider.cloneWithRows(d));
|
||||
};
|
||||
|
||||
const RenderSectionHeader = ({item,index}) => (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
width: "100%",
|
||||
justifyContent: "space-between",
|
||||
paddingHorizontal: 12,
|
||||
marginTop: 10,
|
||||
height: 25,
|
||||
}}
|
||||
>
|
||||
|
||||
<Text
|
||||
style={[
|
||||
{
|
||||
color: colors.accent,
|
||||
},
|
||||
styles.sectionHeader,
|
||||
]}>
|
||||
{item.title}
|
||||
</Text>
|
||||
{
|
||||
index === 1 && sortMenuButton? <HeaderMenu/> : null
|
||||
const RenderSectionHeader = ({item, index}) => (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
width: '100%',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: 12,
|
||||
height: 30,
|
||||
}}>
|
||||
<Text
|
||||
onPress={() => {
|
||||
console.log('clicekd');
|
||||
if (jumpToDialog) {
|
||||
eSendEvent(eOpenJumpToDialog);
|
||||
}
|
||||
</View>
|
||||
);
|
||||
}}
|
||||
style={[
|
||||
styles.sectionHeader,
|
||||
{
|
||||
color: colors.accent,
|
||||
height:30,
|
||||
minWidth:60,
|
||||
textAlignVertical:"bottom"
|
||||
},
|
||||
]}>
|
||||
{item.title}
|
||||
</Text>
|
||||
{index === 1 && sortMenuButton ? <HeaderMenu /> : null}
|
||||
</View>
|
||||
);
|
||||
|
||||
const _onRefresh = useCallback(async () => {
|
||||
if (Platform.OS === 'ios') {
|
||||
dispatch({
|
||||
type: Actions.SYNCING,
|
||||
syncing: true,
|
||||
});
|
||||
} else {
|
||||
setRefreshing(true);
|
||||
}
|
||||
try {
|
||||
let user = await db.user.get();
|
||||
dispatch({type: Actions.USER, user: user});
|
||||
await db.sync();
|
||||
ToastEvent.show('Sync Complete', 'success');
|
||||
} catch (e) {
|
||||
ToastEvent.show(
|
||||
'You must login to sync.',
|
||||
'error',
|
||||
'global',
|
||||
5000,
|
||||
() => {
|
||||
eSendEvent(eOpenLoginDialog);
|
||||
},
|
||||
'Login',
|
||||
);
|
||||
} finally {
|
||||
if (Platform.OS === 'ios') {
|
||||
dispatch({
|
||||
type: Actions.SYNCING,
|
||||
syncing: false,
|
||||
});
|
||||
} else {
|
||||
setRefreshing(false);
|
||||
}
|
||||
if (refreshCallback) {
|
||||
refreshCallback();
|
||||
}
|
||||
}
|
||||
dispatch({type: Actions.ALL});
|
||||
}, []);
|
||||
|
||||
const _ListEmptyComponent = (
|
||||
<View
|
||||
style={[
|
||||
{
|
||||
backgroundColor: colors.bg,
|
||||
},
|
||||
styles.emptyList,
|
||||
]}>
|
||||
<>{placeholder}</>
|
||||
</View>
|
||||
);
|
||||
|
||||
const _layoutProvider = new LayoutProvider(
|
||||
(index) => {
|
||||
return dataProvider.getDataForIndex(index).type;
|
||||
const _onRefresh = useCallback(async () => {
|
||||
if (Platform.OS === 'ios') {
|
||||
dispatch({
|
||||
type: Actions.SYNCING,
|
||||
syncing: true,
|
||||
});
|
||||
} else {
|
||||
setRefreshing(true);
|
||||
}
|
||||
try {
|
||||
let user = await db.user.get();
|
||||
dispatch({type: Actions.USER, user: user});
|
||||
await db.sync();
|
||||
ToastEvent.show('Sync Complete', 'success');
|
||||
} catch (e) {
|
||||
ToastEvent.show(
|
||||
'You must login to sync.',
|
||||
'error',
|
||||
'global',
|
||||
5000,
|
||||
() => {
|
||||
eSendEvent(eOpenLoginDialog);
|
||||
},
|
||||
(type, dim) => {
|
||||
switch (type) {
|
||||
case 'note':
|
||||
dim.width = width;
|
||||
dim.height = 100 * fontScale;
|
||||
break;
|
||||
case 'notebook':
|
||||
dim.width = width;
|
||||
dim.height = 110 * fontScale;
|
||||
break;
|
||||
case 'trash':
|
||||
dim.width = width;
|
||||
dim.height = 110 * fontScale;
|
||||
break;
|
||||
case 'topic':
|
||||
dim.width = width;
|
||||
dim.height = 80 * fontScale;
|
||||
break;
|
||||
case 'tag':
|
||||
dim.width = width;
|
||||
dim.height = 80 * fontScale;
|
||||
break;
|
||||
case 'header':
|
||||
dim.width = width;
|
||||
dim.height = 30 * fontScale;
|
||||
break;
|
||||
case 'MAIN_HEADER':
|
||||
dim.width = width;
|
||||
dim.height =
|
||||
!messageBoardState.visible || !listData[0] || selectionMode
|
||||
? 0
|
||||
: 40 * fontScale;
|
||||
break;
|
||||
default:
|
||||
dim.width = width;
|
||||
dim.height = 0;
|
||||
}
|
||||
'Login',
|
||||
);
|
||||
} finally {
|
||||
if (Platform.OS === 'ios') {
|
||||
dispatch({
|
||||
type: Actions.SYNCING,
|
||||
syncing: false,
|
||||
});
|
||||
} else {
|
||||
setRefreshing(false);
|
||||
}
|
||||
if (refreshCallback) {
|
||||
refreshCallback();
|
||||
}
|
||||
}
|
||||
dispatch({type: Actions.ALL});
|
||||
}, []);
|
||||
|
||||
const _ListEmptyComponent = (
|
||||
<View
|
||||
style={[
|
||||
{
|
||||
backgroundColor: colors.bg,
|
||||
},
|
||||
);
|
||||
styles.emptyList,
|
||||
]}>
|
||||
<>{placeholder}</>
|
||||
</View>
|
||||
);
|
||||
|
||||
const _renderRow = (type, data, index) => {
|
||||
const _layoutProvider = new LayoutProvider(
|
||||
(index) => {
|
||||
return dataProvider.getDataForIndex(index).type;
|
||||
},
|
||||
(type, dim) => {
|
||||
switch (type) {
|
||||
case 'note':
|
||||
dim.width = width;
|
||||
dim.height = 100 * fontScale;
|
||||
break;
|
||||
case 'notebook':
|
||||
dim.width = width;
|
||||
dim.height = 110 * fontScale;
|
||||
break;
|
||||
case 'trash':
|
||||
dim.width = width;
|
||||
dim.height = 110 * fontScale;
|
||||
break;
|
||||
case 'topic':
|
||||
dim.width = width;
|
||||
dim.height = 80 * fontScale;
|
||||
break;
|
||||
case 'tag':
|
||||
dim.width = width;
|
||||
dim.height = 80 * fontScale;
|
||||
break;
|
||||
case 'header':
|
||||
dim.width = width;
|
||||
dim.height = 30 * fontScale;
|
||||
break;
|
||||
case 'MAIN_HEADER':
|
||||
dim.width = width;
|
||||
dim.height =
|
||||
!messageBoardState.visible || !listData[0] || selectionMode
|
||||
? 0
|
||||
: 40 * fontScale;
|
||||
break;
|
||||
default:
|
||||
dim.width = width;
|
||||
dim.height = 0;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
switch (type) {
|
||||
case 'note':
|
||||
return <RenderItem item={data} pinned={data.pinned} index={index}/>;
|
||||
case 'notebook':
|
||||
return <RenderItem item={data} pinned={data.pinned} index={index}/>;
|
||||
case 'MAIN_HEADER':
|
||||
return <ListHeaderComponent type={dataType} index={index} data={listData}/>;
|
||||
case 'header':
|
||||
return <RenderSectionHeader item={data} index={index}/>;
|
||||
default:
|
||||
return <RenderItem item={data} index={index}/>;
|
||||
}
|
||||
const _renderRow = (type, data, index) => {
|
||||
switch (type) {
|
||||
case 'note':
|
||||
return <RenderItem item={data} pinned={data.pinned} index={index} />;
|
||||
case 'notebook':
|
||||
return <RenderItem item={data} pinned={data.pinned} index={index} />;
|
||||
case 'MAIN_HEADER':
|
||||
return (
|
||||
<ListHeaderComponent type={dataType} index={index} data={listData} />
|
||||
);
|
||||
case 'header':
|
||||
return <RenderSectionHeader item={data} index={index} />;
|
||||
default:
|
||||
return <RenderItem item={data} index={index} />;
|
||||
}
|
||||
};
|
||||
|
||||
const listStyle = useMemo(() => {
|
||||
return {
|
||||
height: '100%',
|
||||
backgroundColor: colors.bg,
|
||||
width: '100%',
|
||||
paddingTop:
|
||||
Platform.OS === 'ios'
|
||||
? listData[0] && !selectionMode
|
||||
? 130
|
||||
: 130 - 60
|
||||
: listData[0] && !selectionMode
|
||||
? 155 - insets.top
|
||||
: 155 - insets.top - 60,
|
||||
};
|
||||
}, [selectionMode, listData, colors, insets]);
|
||||
|
||||
const listStyle = useMemo(() => {
|
||||
return {
|
||||
height: '100%',
|
||||
backgroundColor: colors.bg,
|
||||
width: '100%',
|
||||
paddingTop:
|
||||
Platform.OS === 'ios'
|
||||
? listData[0] && !selectionMode
|
||||
? 130
|
||||
: 130 - 60
|
||||
: listData[0] && !selectionMode
|
||||
? 155 - insets.top
|
||||
: (155 - insets.top) - 60,
|
||||
};
|
||||
}, [selectionMode, listData, colors,insets]);
|
||||
|
||||
return !listData || listData.length === 0 || !dataProvider ? (
|
||||
_ListEmptyComponent
|
||||
) : (
|
||||
<RecyclerListView
|
||||
layoutProvider={_layoutProvider}
|
||||
dataProvider={dataProvider}
|
||||
rowRenderer={_renderRow}
|
||||
onScroll={_onScroll}
|
||||
renderFooter={() => <View style={{height: 400}}/>}
|
||||
scrollViewProps={{
|
||||
refreshControl: (
|
||||
<RefreshControl
|
||||
tintColor={colors.accent}
|
||||
colors={[colors.accent]}
|
||||
progressViewOffset={150}
|
||||
onRefresh={customRefresh ? customRefresh : _onRefresh}
|
||||
refreshing={customRefresh ? customRefreshing : refreshing}
|
||||
/>
|
||||
),
|
||||
contentContainerStyle: {
|
||||
width: '100%',
|
||||
alignSelf: 'center',
|
||||
minHeight: '100%',
|
||||
},
|
||||
}}
|
||||
style={listStyle}
|
||||
/>
|
||||
);
|
||||
return !listData || listData.length === 0 || !dataProvider ? (
|
||||
_ListEmptyComponent
|
||||
) : (
|
||||
<RecyclerListView
|
||||
ref={scrollRef}
|
||||
layoutProvider={_layoutProvider}
|
||||
dataProvider={dataProvider}
|
||||
rowRenderer={_renderRow}
|
||||
onScroll={_onScroll}
|
||||
renderFooter={() => <View style={{height: 400}} />}
|
||||
scrollViewProps={{
|
||||
refreshControl: (
|
||||
<RefreshControl
|
||||
tintColor={colors.accent}
|
||||
colors={[colors.accent]}
|
||||
progressViewOffset={150}
|
||||
onRefresh={customRefresh ? customRefresh : _onRefresh}
|
||||
refreshing={customRefresh ? customRefreshing : refreshing}
|
||||
/>
|
||||
),
|
||||
contentContainerStyle: {
|
||||
width: '100%',
|
||||
alignSelf: 'center',
|
||||
minHeight: '100%',
|
||||
},
|
||||
}}
|
||||
style={listStyle}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default SimpleList;
|
||||
|
||||
const SearchHeader = () => {
|
||||
const [state] = useTracked();
|
||||
const {colors} = state;
|
||||
const searchResults = {...state.searchResults};
|
||||
const [state] = useTracked();
|
||||
const {colors} = state;
|
||||
const searchResults = {...state.searchResults};
|
||||
|
||||
return (
|
||||
<View style={styles.searchHeader}>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: WEIGHT.bold,
|
||||
color: colors.accent,
|
||||
fontSize: SIZE.xs,
|
||||
}}>
|
||||
Showing Results for {searchResults.keyword}
|
||||
</Text>
|
||||
<Text
|
||||
onPress={() => {
|
||||
eSendEvent(eClearSearch);
|
||||
}}
|
||||
style={{
|
||||
fontFamily: WEIGHT.regular,
|
||||
color: colors.errorText,
|
||||
fontSize: SIZE.xs,
|
||||
}}>
|
||||
Clear
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
return (
|
||||
<View style={styles.searchHeader}>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: WEIGHT.bold,
|
||||
color: colors.accent,
|
||||
fontSize: SIZE.xs,
|
||||
}}>
|
||||
Showing Results for {searchResults.keyword}
|
||||
</Text>
|
||||
<Text
|
||||
onPress={() => {
|
||||
eSendEvent(eClearSearch);
|
||||
}}
|
||||
style={{
|
||||
fontFamily: WEIGHT.regular,
|
||||
color: colors.errorText,
|
||||
fontSize: SIZE.xs,
|
||||
}}>
|
||||
Clear
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const MessageCard = ({data}) => {
|
||||
const [state] = useTracked();
|
||||
const {colors, selectionMode, currentScreen, messageBoardState} = state;
|
||||
const [state] = useTracked();
|
||||
const {colors, selectionMode, currentScreen, messageBoardState} = state;
|
||||
|
||||
return (
|
||||
<View>
|
||||
{!messageBoardState.visible || !data[0] || selectionMode ? null : (
|
||||
<PressableButton
|
||||
onPress={messageBoardState.onPress}
|
||||
color={
|
||||
COLORS_NOTE[currentScreen]
|
||||
? COLORS_NOTE[currentScreen]
|
||||
: colors.shade
|
||||
}
|
||||
selectedColor={
|
||||
COLORS_NOTE[currentScreen]
|
||||
? COLORS_NOTE[currentScreen]
|
||||
: colors.accent
|
||||
}
|
||||
alpha={!colors.night ? -0.02 : 0.1}
|
||||
opacity={0.12}
|
||||
customStyle={styles.loginCard}>
|
||||
<View
|
||||
style={{
|
||||
width: 25,
|
||||
backgroundColor: COLORS_NOTE[currentScreen]
|
||||
? COLORS_NOTE[currentScreen]
|
||||
: colors.accent,
|
||||
height: 25,
|
||||
borderRadius: 100,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}>
|
||||
<Icon
|
||||
style={styles.loginIcon}
|
||||
name={messageBoardState.icon}
|
||||
color="white"
|
||||
size={SIZE.xs}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
marginLeft: 10,
|
||||
}}>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: WEIGHT.regular,
|
||||
color: colors.icon,
|
||||
fontSize: SIZE.xxs - 1,
|
||||
}}>
|
||||
{messageBoardState.message}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color: COLORS_NOTE[currentScreen]
|
||||
? COLORS_NOTE[currentScreen]
|
||||
: colors.accent,
|
||||
fontSize: SIZE.xxs,
|
||||
}}>
|
||||
{messageBoardState.actionText}
|
||||
</Text>
|
||||
</View>
|
||||
</PressableButton>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
return (
|
||||
<View>
|
||||
{!messageBoardState.visible || !data[0] || selectionMode ? null : (
|
||||
<PressableButton
|
||||
onPress={messageBoardState.onPress}
|
||||
color={
|
||||
COLORS_NOTE[currentScreen]
|
||||
? COLORS_NOTE[currentScreen]
|
||||
: colors.shade
|
||||
}
|
||||
selectedColor={
|
||||
COLORS_NOTE[currentScreen]
|
||||
? COLORS_NOTE[currentScreen]
|
||||
: colors.accent
|
||||
}
|
||||
alpha={!colors.night ? -0.02 : 0.1}
|
||||
opacity={0.12}
|
||||
customStyle={styles.loginCard}>
|
||||
<View
|
||||
style={{
|
||||
width: 25,
|
||||
backgroundColor: COLORS_NOTE[currentScreen]
|
||||
? COLORS_NOTE[currentScreen]
|
||||
: colors.accent,
|
||||
height: 25,
|
||||
borderRadius: 100,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}>
|
||||
<Icon
|
||||
style={styles.loginIcon}
|
||||
name={messageBoardState.icon}
|
||||
color="white"
|
||||
size={SIZE.xs}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
marginLeft: 10,
|
||||
}}>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: WEIGHT.regular,
|
||||
color: colors.icon,
|
||||
fontSize: SIZE.xxs - 1,
|
||||
}}>
|
||||
{messageBoardState.message}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
color: COLORS_NOTE[currentScreen]
|
||||
? COLORS_NOTE[currentScreen]
|
||||
: colors.accent,
|
||||
fontSize: SIZE.xxs,
|
||||
}}>
|
||||
{messageBoardState.actionText}
|
||||
</Text>
|
||||
</View>
|
||||
</PressableButton>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const ListHeaderComponent = ({type, data}) => {
|
||||
const [state] = useTracked();
|
||||
const searchResults = {...state.searchResults};
|
||||
const [state] = useTracked();
|
||||
const searchResults = {...state.searchResults};
|
||||
|
||||
return searchResults.type === type && searchResults.results.length > 0 ? (
|
||||
<SearchHeader/>
|
||||
) : (
|
||||
<MessageCard type={type} data={data}/>
|
||||
);
|
||||
return searchResults.type === type && searchResults.results.length > 0 ? (
|
||||
<SearchHeader />
|
||||
) : (
|
||||
<MessageCard type={type} data={data} />
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
loginCard: {
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
paddingHorizontal: 12,
|
||||
alignSelf: 'center',
|
||||
height: 40,
|
||||
borderRadius: 0,
|
||||
position: 'relative',
|
||||
},
|
||||
loginIcon: {
|
||||
textAlign: 'center',
|
||||
textAlignVertical: 'center',
|
||||
},
|
||||
searchHeader: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: 12,
|
||||
height: 40,
|
||||
},
|
||||
sectionHeader: {
|
||||
fontFamily: WEIGHT.bold,
|
||||
fontSize: SIZE.xs + 1,
|
||||
alignSelf: 'center',
|
||||
textAlignVertical: 'center',
|
||||
},
|
||||
emptyList: {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
alignSelf: 'center',
|
||||
justifyContent: 'center',
|
||||
opacity: 1,
|
||||
},
|
||||
loginCard: {
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
paddingHorizontal: 12,
|
||||
alignSelf: 'center',
|
||||
height: 40,
|
||||
borderRadius: 0,
|
||||
position: 'relative',
|
||||
},
|
||||
loginIcon: {
|
||||
textAlign: 'center',
|
||||
textAlignVertical: 'center',
|
||||
},
|
||||
searchHeader: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: 12,
|
||||
height: 40,
|
||||
},
|
||||
sectionHeader: {
|
||||
fontFamily: WEIGHT.bold,
|
||||
fontSize: SIZE.xs + 1,
|
||||
alignSelf: 'center',
|
||||
textAlignVertical: 'center',
|
||||
},
|
||||
emptyList: {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
alignSelf: 'center',
|
||||
justifyContent: 'center',
|
||||
opacity: 1,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -18,7 +18,7 @@ import Seperator from "../Seperator";
|
||||
|
||||
const actionSheet = createRef();
|
||||
|
||||
class Index extends React.Component {
|
||||
class SortDialog extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@@ -172,4 +172,4 @@ class Index extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default Index;
|
||||
export default SortDialog;
|
||||
|
||||
35
apps/mobile/src/components/Typography/Paragraph.js
Normal file
35
apps/mobile/src/components/Typography/Paragraph.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import {Text} from 'react-native';
|
||||
import {useTracked} from '../../provider';
|
||||
import {SIZE, WEIGHT} from '../../utils/SizeUtils';
|
||||
|
||||
/**
|
||||
*
|
||||
* @typedef {import('react-native').TextProps} TextType
|
||||
* @typedef {Object} restTypes
|
||||
* @property {string} color color
|
||||
* @property {number} size color
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* @param {TextType | restTypes} props all props
|
||||
*/
|
||||
const Paragraph = ({color, size, style, ...restProps}) => {
|
||||
const [state] = useTracked();
|
||||
const {colors} = state;
|
||||
|
||||
return (
|
||||
<Text
|
||||
{...restProps}
|
||||
style={[
|
||||
{
|
||||
fontFamily: WEIGHT.regular,
|
||||
fontSize: size || SIZE.xs + 1,
|
||||
color: color || colors.pri,
|
||||
},
|
||||
style,
|
||||
]}></Text>
|
||||
);
|
||||
};
|
||||
|
||||
export default Paragraph
|
||||
@@ -117,3 +117,6 @@ export const eCloseResultDialog = '558';
|
||||
|
||||
export const eOpenSortDialog = '559';
|
||||
export const eCloseSortDialog = '560';
|
||||
|
||||
export const eOpenJumpToDialog = '561';
|
||||
export const eCloseJumpToDialog = '562';
|
||||
@@ -1,19 +1,22 @@
|
||||
import React, {useCallback, useEffect} from 'react';
|
||||
import {ContainerBottomButton} from '../../components/Container/ContainerBottomButton';
|
||||
import {Placeholder} from '../../components/ListPlaceholders';
|
||||
import React, { createRef, useCallback, useEffect } from 'react';
|
||||
import { ContainerBottomButton } from '../../components/Container/ContainerBottomButton';
|
||||
import { Placeholder } from '../../components/ListPlaceholders';
|
||||
import SimpleList from '../../components/SimpleList';
|
||||
import {NoteItemWrapper} from '../../components/SimpleList/NoteItemWrapper';
|
||||
import {useTracked} from '../../provider';
|
||||
import {Actions} from '../../provider/Actions';
|
||||
import {eSendEvent} from '../../services/EventManager';
|
||||
import { NoteItemWrapper } from '../../components/SimpleList/NoteItemWrapper';
|
||||
import { useTracked } from '../../provider';
|
||||
import { Actions } from '../../provider/Actions';
|
||||
import { DDS } from '../../services/DeviceDetection';
|
||||
import { eSendEvent } from '../../services/EventManager';
|
||||
import { sortSettings } from '../../utils';
|
||||
import { openEditorAnimation } from '../../utils/Animations';
|
||||
import {
|
||||
eOnLoadNote,
|
||||
|
||||
eScrollEvent,
|
||||
eUpdateSearchState,
|
||||
eUpdateSearchState
|
||||
} from '../../utils/Events';
|
||||
import {openEditorAnimation} from '../../utils/Animations';
|
||||
import {DDS} from '../../services/DeviceDetection';
|
||||
import {sortSettings} from "../../utils";
|
||||
|
||||
const scrollRef = createRef();
|
||||
|
||||
export const Home = ({navigation}) => {
|
||||
const [state, dispatch] = useTracked();
|
||||
@@ -87,6 +90,7 @@ export const Home = ({navigation}) => {
|
||||
<>
|
||||
<SimpleList
|
||||
data={notes}
|
||||
scrollRef={scrollRef}
|
||||
type="notes"
|
||||
isHome={true}
|
||||
pinned={true}
|
||||
@@ -95,6 +99,7 @@ export const Home = ({navigation}) => {
|
||||
RenderItem={NoteItemWrapper}
|
||||
placeholder={<Placeholder type="notes" />}
|
||||
placeholderText={`Notes you write appear here`}
|
||||
jumpToDialog={true}
|
||||
/>
|
||||
|
||||
<ContainerBottomButton
|
||||
@@ -106,3 +111,5 @@ export const Home = ({navigation}) => {
|
||||
};
|
||||
|
||||
export default Home;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user