mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
Revert: Mobile: Add note bar (#6772)
Revert commit dfd95f8385
Due to UX issues.
Ref https://discourse.joplinapp.org/t/25775/30
This commit is contained in:
parent
afc34b44c8
commit
44e60bdda9
@ -954,12 +954,6 @@ packages/app-mobile/components/NoteEditor/SelectionFormatting.js.map
|
|||||||
packages/app-mobile/components/NoteEditor/types.d.ts
|
packages/app-mobile/components/NoteEditor/types.d.ts
|
||||||
packages/app-mobile/components/NoteEditor/types.js
|
packages/app-mobile/components/NoteEditor/types.js
|
||||||
packages/app-mobile/components/NoteEditor/types.js.map
|
packages/app-mobile/components/NoteEditor/types.js.map
|
||||||
packages/app-mobile/components/NotesBar.d.ts
|
|
||||||
packages/app-mobile/components/NotesBar.js
|
|
||||||
packages/app-mobile/components/NotesBar.js.map
|
|
||||||
packages/app-mobile/components/NotesBarListItem.d.ts
|
|
||||||
packages/app-mobile/components/NotesBarListItem.js
|
|
||||||
packages/app-mobile/components/NotesBarListItem.js.map
|
|
||||||
packages/app-mobile/components/ScreenHeader.d.ts
|
packages/app-mobile/components/ScreenHeader.d.ts
|
||||||
packages/app-mobile/components/ScreenHeader.js
|
packages/app-mobile/components/ScreenHeader.js
|
||||||
packages/app-mobile/components/ScreenHeader.js.map
|
packages/app-mobile/components/ScreenHeader.js.map
|
||||||
@ -969,18 +963,12 @@ packages/app-mobile/components/SelectDateTimeDialog.js.map
|
|||||||
packages/app-mobile/components/SideMenu.d.ts
|
packages/app-mobile/components/SideMenu.d.ts
|
||||||
packages/app-mobile/components/SideMenu.js
|
packages/app-mobile/components/SideMenu.js
|
||||||
packages/app-mobile/components/SideMenu.js.map
|
packages/app-mobile/components/SideMenu.js.map
|
||||||
packages/app-mobile/components/checkbox.d.ts
|
|
||||||
packages/app-mobile/components/checkbox.js
|
|
||||||
packages/app-mobile/components/checkbox.js.map
|
|
||||||
packages/app-mobile/components/getResponsiveValue.d.ts
|
packages/app-mobile/components/getResponsiveValue.d.ts
|
||||||
packages/app-mobile/components/getResponsiveValue.js
|
packages/app-mobile/components/getResponsiveValue.js
|
||||||
packages/app-mobile/components/getResponsiveValue.js.map
|
packages/app-mobile/components/getResponsiveValue.js.map
|
||||||
packages/app-mobile/components/getResponsiveValue.test.d.ts
|
packages/app-mobile/components/getResponsiveValue.test.d.ts
|
||||||
packages/app-mobile/components/getResponsiveValue.test.js
|
packages/app-mobile/components/getResponsiveValue.test.js
|
||||||
packages/app-mobile/components/getResponsiveValue.test.js.map
|
packages/app-mobile/components/getResponsiveValue.test.js.map
|
||||||
packages/app-mobile/components/global-style.d.ts
|
|
||||||
packages/app-mobile/components/global-style.js
|
|
||||||
packages/app-mobile/components/global-style.js.map
|
|
||||||
packages/app-mobile/components/screens/ConfigScreen.d.ts
|
packages/app-mobile/components/screens/ConfigScreen.d.ts
|
||||||
packages/app-mobile/components/screens/ConfigScreen.js
|
packages/app-mobile/components/screens/ConfigScreen.js
|
||||||
packages/app-mobile/components/screens/ConfigScreen.js.map
|
packages/app-mobile/components/screens/ConfigScreen.js.map
|
||||||
@ -993,12 +981,6 @@ packages/app-mobile/components/screens/UpgradeSyncTargetScreen.js.map
|
|||||||
packages/app-mobile/components/screens/encryption-config.d.ts
|
packages/app-mobile/components/screens/encryption-config.d.ts
|
||||||
packages/app-mobile/components/screens/encryption-config.js
|
packages/app-mobile/components/screens/encryption-config.js
|
||||||
packages/app-mobile/components/screens/encryption-config.js.map
|
packages/app-mobile/components/screens/encryption-config.js.map
|
||||||
packages/app-mobile/components/searchNotes.d.ts
|
|
||||||
packages/app-mobile/components/searchNotes.js
|
|
||||||
packages/app-mobile/components/searchNotes.js.map
|
|
||||||
packages/app-mobile/components/useStyles.d.ts
|
|
||||||
packages/app-mobile/components/useStyles.js
|
|
||||||
packages/app-mobile/components/useStyles.js.map
|
|
||||||
packages/app-mobile/gulpfile.d.ts
|
packages/app-mobile/gulpfile.d.ts
|
||||||
packages/app-mobile/gulpfile.js
|
packages/app-mobile/gulpfile.js
|
||||||
packages/app-mobile/gulpfile.js.map
|
packages/app-mobile/gulpfile.js.map
|
||||||
|
@ -29,7 +29,6 @@ module.exports = {
|
|||||||
|
|
||||||
// React Native variables
|
// React Native variables
|
||||||
'__DEV__': 'readonly',
|
'__DEV__': 'readonly',
|
||||||
'JSX': 'readonly',
|
|
||||||
|
|
||||||
// Clipper variables
|
// Clipper variables
|
||||||
'browserSupportsPromises_': true,
|
'browserSupportsPromises_': true,
|
||||||
|
18
.gitignore
vendored
18
.gitignore
vendored
@ -942,12 +942,6 @@ packages/app-mobile/components/NoteEditor/SelectionFormatting.js.map
|
|||||||
packages/app-mobile/components/NoteEditor/types.d.ts
|
packages/app-mobile/components/NoteEditor/types.d.ts
|
||||||
packages/app-mobile/components/NoteEditor/types.js
|
packages/app-mobile/components/NoteEditor/types.js
|
||||||
packages/app-mobile/components/NoteEditor/types.js.map
|
packages/app-mobile/components/NoteEditor/types.js.map
|
||||||
packages/app-mobile/components/NotesBar.d.ts
|
|
||||||
packages/app-mobile/components/NotesBar.js
|
|
||||||
packages/app-mobile/components/NotesBar.js.map
|
|
||||||
packages/app-mobile/components/NotesBarListItem.d.ts
|
|
||||||
packages/app-mobile/components/NotesBarListItem.js
|
|
||||||
packages/app-mobile/components/NotesBarListItem.js.map
|
|
||||||
packages/app-mobile/components/ScreenHeader.d.ts
|
packages/app-mobile/components/ScreenHeader.d.ts
|
||||||
packages/app-mobile/components/ScreenHeader.js
|
packages/app-mobile/components/ScreenHeader.js
|
||||||
packages/app-mobile/components/ScreenHeader.js.map
|
packages/app-mobile/components/ScreenHeader.js.map
|
||||||
@ -957,18 +951,12 @@ packages/app-mobile/components/SelectDateTimeDialog.js.map
|
|||||||
packages/app-mobile/components/SideMenu.d.ts
|
packages/app-mobile/components/SideMenu.d.ts
|
||||||
packages/app-mobile/components/SideMenu.js
|
packages/app-mobile/components/SideMenu.js
|
||||||
packages/app-mobile/components/SideMenu.js.map
|
packages/app-mobile/components/SideMenu.js.map
|
||||||
packages/app-mobile/components/checkbox.d.ts
|
|
||||||
packages/app-mobile/components/checkbox.js
|
|
||||||
packages/app-mobile/components/checkbox.js.map
|
|
||||||
packages/app-mobile/components/getResponsiveValue.d.ts
|
packages/app-mobile/components/getResponsiveValue.d.ts
|
||||||
packages/app-mobile/components/getResponsiveValue.js
|
packages/app-mobile/components/getResponsiveValue.js
|
||||||
packages/app-mobile/components/getResponsiveValue.js.map
|
packages/app-mobile/components/getResponsiveValue.js.map
|
||||||
packages/app-mobile/components/getResponsiveValue.test.d.ts
|
packages/app-mobile/components/getResponsiveValue.test.d.ts
|
||||||
packages/app-mobile/components/getResponsiveValue.test.js
|
packages/app-mobile/components/getResponsiveValue.test.js
|
||||||
packages/app-mobile/components/getResponsiveValue.test.js.map
|
packages/app-mobile/components/getResponsiveValue.test.js.map
|
||||||
packages/app-mobile/components/global-style.d.ts
|
|
||||||
packages/app-mobile/components/global-style.js
|
|
||||||
packages/app-mobile/components/global-style.js.map
|
|
||||||
packages/app-mobile/components/screens/ConfigScreen.d.ts
|
packages/app-mobile/components/screens/ConfigScreen.d.ts
|
||||||
packages/app-mobile/components/screens/ConfigScreen.js
|
packages/app-mobile/components/screens/ConfigScreen.js
|
||||||
packages/app-mobile/components/screens/ConfigScreen.js.map
|
packages/app-mobile/components/screens/ConfigScreen.js.map
|
||||||
@ -981,12 +969,6 @@ packages/app-mobile/components/screens/UpgradeSyncTargetScreen.js.map
|
|||||||
packages/app-mobile/components/screens/encryption-config.d.ts
|
packages/app-mobile/components/screens/encryption-config.d.ts
|
||||||
packages/app-mobile/components/screens/encryption-config.js
|
packages/app-mobile/components/screens/encryption-config.js
|
||||||
packages/app-mobile/components/screens/encryption-config.js.map
|
packages/app-mobile/components/screens/encryption-config.js.map
|
||||||
packages/app-mobile/components/searchNotes.d.ts
|
|
||||||
packages/app-mobile/components/searchNotes.js
|
|
||||||
packages/app-mobile/components/searchNotes.js.map
|
|
||||||
packages/app-mobile/components/useStyles.d.ts
|
|
||||||
packages/app-mobile/components/useStyles.js
|
|
||||||
packages/app-mobile/components/useStyles.js.map
|
|
||||||
packages/app-mobile/gulpfile.d.ts
|
packages/app-mobile/gulpfile.d.ts
|
||||||
packages/app-mobile/gulpfile.js
|
packages/app-mobile/gulpfile.js
|
||||||
packages/app-mobile/gulpfile.js.map
|
packages/app-mobile/gulpfile.js.map
|
||||||
|
@ -86,9 +86,5 @@
|
|||||||
"node-gyp": "^8.4.1",
|
"node-gyp": "^8.4.1",
|
||||||
"nodemon": "^2.0.9"
|
"nodemon": "^2.0.9"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@3.1.1",
|
"packageManager": "yarn@3.1.1"
|
||||||
"resolutions": {
|
|
||||||
"@types/react": "17.0.14",
|
|
||||||
"@types/react-dom": "17.0.14"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,293 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import { View, Text, TextInput, TouchableOpacity, FlatList, StyleSheet } from 'react-native';
|
|
||||||
import { State } from '@joplin/lib/reducer';
|
|
||||||
import { themeStyle } from './global-style';
|
|
||||||
const { connect } = require('react-redux');
|
|
||||||
const Icon = require('react-native-vector-icons/Ionicons').default;
|
|
||||||
const { _ } = require('@joplin/lib/locale');
|
|
||||||
import { Style } from './global-style';
|
|
||||||
import Note from '@joplin/lib/models/Note';
|
|
||||||
import NotesBarListItem from './NotesBarListItem';
|
|
||||||
import Folder from '@joplin/lib/models/Folder';
|
|
||||||
import searchNotes from './searchNotes';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
themeId: number;
|
|
||||||
notes: any[];
|
|
||||||
todoCheckbox_change: (checked: boolean)=> void;
|
|
||||||
selectedFolderId: string;
|
|
||||||
activeFolderId: string;
|
|
||||||
dispatch: any;
|
|
||||||
selectedNoteId: string;
|
|
||||||
settings: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
function NotesBarComponent(props: Props) {
|
|
||||||
|
|
||||||
const [query, setQuery] = React.useState<string>('');
|
|
||||||
const [notes, setNotes] = React.useState<any[]>(props.notes);
|
|
||||||
const theme: Style = React.useMemo(() => themeStyle(props.themeId), [props.themeId]);
|
|
||||||
|
|
||||||
const styles = (): Style => {
|
|
||||||
const styles: Style = {
|
|
||||||
container: {
|
|
||||||
flex: 1,
|
|
||||||
width: '100%',
|
|
||||||
backgroundColor: theme.backgroundColor3,
|
|
||||||
},
|
|
||||||
horizontalFlex: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
titleText: {
|
|
||||||
fontSize: 16,
|
|
||||||
},
|
|
||||||
closeIcon: {
|
|
||||||
fontSize: 30,
|
|
||||||
paddingTop: 8,
|
|
||||||
paddingBottom: 8,
|
|
||||||
paddingRight: theme.marginRight,
|
|
||||||
paddingLeft: theme.marginLeft,
|
|
||||||
},
|
|
||||||
top: {
|
|
||||||
color: theme.color,
|
|
||||||
},
|
|
||||||
topContainer: {
|
|
||||||
width: '100%',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
paddingLeft: theme.marginLeft,
|
|
||||||
},
|
|
||||||
padding: {
|
|
||||||
paddingLeft: theme.marginLeft,
|
|
||||||
paddingRight: theme.marginRight,
|
|
||||||
paddingTop: 12,
|
|
||||||
paddingBottom: 12,
|
|
||||||
},
|
|
||||||
titleIcon: {
|
|
||||||
fontSize: 22,
|
|
||||||
marginRight: 4,
|
|
||||||
},
|
|
||||||
divider: {
|
|
||||||
backgroundColor: theme.dividerColor,
|
|
||||||
height: 1,
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
nativeInput: {
|
|
||||||
fontSize: theme.fontSize,
|
|
||||||
flex: 1,
|
|
||||||
paddingRight: 8,
|
|
||||||
},
|
|
||||||
searchIcon: {
|
|
||||||
fontSize: 22,
|
|
||||||
},
|
|
||||||
searchInput: {
|
|
||||||
alignItems: 'center',
|
|
||||||
backgroundColor: theme.backgroundColor,
|
|
||||||
paddingLeft: 8,
|
|
||||||
borderRadius: 4,
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: theme.dividerColor,
|
|
||||||
height: 42,
|
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
button: {
|
|
||||||
height: 42,
|
|
||||||
width: 42,
|
|
||||||
backgroundColor: theme.color4,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
borderRadius: 4,
|
|
||||||
flex: 0.5,
|
|
||||||
marginLeft: 8,
|
|
||||||
},
|
|
||||||
buttonIcon: {
|
|
||||||
color: theme.backgroundColor,
|
|
||||||
fontSize: 22,
|
|
||||||
},
|
|
||||||
inputGroup: {
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return StyleSheet.create(styles);
|
|
||||||
};
|
|
||||||
|
|
||||||
const titleComp = (
|
|
||||||
<View style={[styles().title, styles().horizontalFlex]}>
|
|
||||||
<Icon name='md-document'style={[styles().top, styles().titleIcon]} />
|
|
||||||
<Text style={[styles().top, styles().titleText]}>{_('Notes')}</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
|
|
||||||
const dividerComp = (
|
|
||||||
<View style={styles().divider}></View>
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleNotesBarClose = () => {
|
|
||||||
props.dispatch({ type: 'NOTES_BAR_CLOSE' });
|
|
||||||
};
|
|
||||||
|
|
||||||
const closeButtonComp = (
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={handleNotesBarClose}
|
|
||||||
accessibilityLabel={_('Toggle note list')}
|
|
||||||
accessibilityRole="button"
|
|
||||||
>
|
|
||||||
<Icon name="close" style={[styles().top, styles().closeIcon]}/>
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderIconButton = (icon: JSX.Element, onPress: ()=> Promise<void>, label: string) => {
|
|
||||||
return (
|
|
||||||
<TouchableOpacity
|
|
||||||
style={styles().button}
|
|
||||||
activeOpacity={0.8}
|
|
||||||
onPress={onPress}
|
|
||||||
accessibilityLabel={label}
|
|
||||||
accessibilityRole="button"
|
|
||||||
>
|
|
||||||
{icon}
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const handleNewNote = async (isTodo: boolean) => {
|
|
||||||
let folderId = props.selectedFolderId !== Folder.conflictFolderId() ? props.selectedFolderId : null;
|
|
||||||
if (!folderId) folderId = props.activeFolderId;
|
|
||||||
|
|
||||||
props.dispatch({
|
|
||||||
type: 'NAV_BACK',
|
|
||||||
});
|
|
||||||
|
|
||||||
const newNote = await Note.save({
|
|
||||||
parent_id: folderId,
|
|
||||||
is_todo: isTodo ? 1 : 0,
|
|
||||||
}, { provisional: true });
|
|
||||||
|
|
||||||
props.dispatch({
|
|
||||||
type: 'NAV_GO',
|
|
||||||
routeName: 'Note',
|
|
||||||
noteId: newNote.id,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const addNoteButtonComp = renderIconButton(<Icon name='document-text-outline' style={styles().buttonIcon} />, () => handleNewNote(false), _('New note'));
|
|
||||||
const addTodoButtonComp = renderIconButton(<Icon name='checkbox-outline' style={styles().buttonIcon} />, () => handleNewNote(true), _('New to-do'));
|
|
||||||
|
|
||||||
const topComp = (
|
|
||||||
<View>
|
|
||||||
<View style={[styles().topContainer, styles().horizontalFlex]}>
|
|
||||||
{titleComp}
|
|
||||||
{closeButtonComp}
|
|
||||||
</View>
|
|
||||||
{dividerComp}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
|
|
||||||
const refreshSearch = async () => {
|
|
||||||
const notes = await searchNotes(query, props.settings['db.ftsEnabled'], props.dispatch);
|
|
||||||
setNotes(notes);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleQuerySubmit = async () => {
|
|
||||||
const trimmedQuery = query.trim();
|
|
||||||
|
|
||||||
if (!trimmedQuery) {
|
|
||||||
props.dispatch({
|
|
||||||
type: 'SEARCH_QUERY',
|
|
||||||
query: '',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
props.dispatch({
|
|
||||||
type: 'SEARCH_QUERY',
|
|
||||||
query: trimmedQuery,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setQuery(trimmedQuery);
|
|
||||||
await refreshSearch();
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchInputComp = (
|
|
||||||
<View style={[styles().horizontalFlex, styles().searchInput]}>
|
|
||||||
<Icon name='search' style={[styles().top, styles().searchIcon]}/>
|
|
||||||
|
|
||||||
<TextInput style={[styles().top, styles().nativeInput]} placeholder='Search' onChangeText={setQuery} value={query} onSubmitEditing={handleQuerySubmit} placeholderTextColor={theme.dividerColor} />
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
|
|
||||||
const inputGroupComp = (
|
|
||||||
<View style={{ width: '100%' }}>
|
|
||||||
<View style={[styles().padding, styles().horizontalFlex, styles().inputGroup]}>
|
|
||||||
{searchInputComp}
|
|
||||||
{addNoteButtonComp}
|
|
||||||
{addTodoButtonComp}
|
|
||||||
</View>
|
|
||||||
{dividerComp}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
|
|
||||||
let flatListRef: any = React.useRef(null);
|
|
||||||
|
|
||||||
const onRenderItem = React.useCallback(({ item }: { item: any }) => {
|
|
||||||
if (item.is_todo) {
|
|
||||||
return <NotesBarListItem note={item} todoCheckbox_change={props.todoCheckbox_change} />;
|
|
||||||
} else {
|
|
||||||
return <NotesBarListItem note={item} />;
|
|
||||||
}
|
|
||||||
}, [props.todoCheckbox_change]);
|
|
||||||
|
|
||||||
const NotesBarListComp = (
|
|
||||||
<FlatList
|
|
||||||
data={notes}
|
|
||||||
renderItem={onRenderItem}
|
|
||||||
keyExtractor={(item: any) => item.id}
|
|
||||||
getItemLayout={(data, index) => (
|
|
||||||
{
|
|
||||||
length: data.length,
|
|
||||||
offset: (theme.fontSize + styles().padding.paddingTop + styles().padding.paddingBottom) * index,
|
|
||||||
viewOffset: (theme.fontSize + styles().padding.paddingTop + styles().padding.paddingBottom),
|
|
||||||
index,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
ref={(ref: any) => { flatListRef = ref; }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
// Scroll the notesbar to selected note item after rendering
|
|
||||||
React.useEffect(() => {
|
|
||||||
const selectedItemIndex = notes.findIndex(item => item.id === props.selectedNoteId);
|
|
||||||
if (selectedItemIndex >= 0) {
|
|
||||||
flatListRef.scrollToIndex({ index: selectedItemIndex });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update the notesbar when a note item changes
|
|
||||||
React.useEffect(() => {
|
|
||||||
setNotes(props.notes);
|
|
||||||
}, [props.notes]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={styles().container}>
|
|
||||||
{topComp}
|
|
||||||
{inputGroupComp}
|
|
||||||
{ NotesBarListComp }
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const NotesBar = connect((state: State) => {
|
|
||||||
return {
|
|
||||||
themeId: state.settings.theme,
|
|
||||||
notes: state.notes,
|
|
||||||
activeFolderId: state.settings.activeFolderId,
|
|
||||||
selectedFolderId: state.selectedFolderId,
|
|
||||||
selectedNoteId: state.selectedNoteIds[0],
|
|
||||||
settings: state.settings,
|
|
||||||
};
|
|
||||||
})(NotesBarComponent);
|
|
||||||
|
|
||||||
export default NotesBar;
|
|
@ -1,132 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import Checkbox from './checkbox';
|
|
||||||
import Note from '@joplin/lib/models/Note';
|
|
||||||
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';
|
|
||||||
import { Style } from './global-style';
|
|
||||||
import { State } from '@joplin/lib/reducer';
|
|
||||||
const { connect } = require('react-redux');
|
|
||||||
const { _ } = require('@joplin/lib/locale');
|
|
||||||
import shim from '@joplin/lib/shim';
|
|
||||||
import { themeStyle } from './global-style';
|
|
||||||
|
|
||||||
|
|
||||||
interface NoteListProps {
|
|
||||||
note: any;
|
|
||||||
themeId: number;
|
|
||||||
todoCheckbox_change: (checked: boolean)=> void;
|
|
||||||
dispatch: Function;
|
|
||||||
selectedNoteId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const NotesBarListItemComponent = function(props: NoteListProps) {
|
|
||||||
const note = props.note ?? {};
|
|
||||||
const isTodo = !!Number(note.is_todo);
|
|
||||||
|
|
||||||
const styles = (): Style => {
|
|
||||||
const themeId = props.themeId;
|
|
||||||
const theme = themeStyle(themeId);
|
|
||||||
|
|
||||||
const styles: Style = {
|
|
||||||
horizontalFlex: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
},
|
|
||||||
padding: {
|
|
||||||
paddingLeft: theme.marginLeft,
|
|
||||||
paddingRight: theme.marginRight,
|
|
||||||
paddingTop: 12,
|
|
||||||
paddingBottom: 12,
|
|
||||||
},
|
|
||||||
button: {
|
|
||||||
height: 42,
|
|
||||||
width: 42,
|
|
||||||
backgroundColor: theme.color4,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
borderRadius: 4,
|
|
||||||
flex: 0.5,
|
|
||||||
marginLeft: 8,
|
|
||||||
},
|
|
||||||
itemText: {
|
|
||||||
fontSize: theme.fontSize,
|
|
||||||
color: theme.color,
|
|
||||||
paddingTop: 12,
|
|
||||||
paddingBottom: 12,
|
|
||||||
},
|
|
||||||
checkbox: {
|
|
||||||
paddingRight: 10,
|
|
||||||
paddingLeft: theme.marginLeft,
|
|
||||||
paddingTop: 12,
|
|
||||||
paddingBottom: 12,
|
|
||||||
color: theme.color,
|
|
||||||
},
|
|
||||||
selectedItem: props.selectedNoteId === note.id ? {
|
|
||||||
backgroundColor: theme.dividerColor,
|
|
||||||
} : null,
|
|
||||||
item: {
|
|
||||||
borderBottomWidth: 1,
|
|
||||||
borderColor: theme.dividerColor,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return StyleSheet.create(styles);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onTodoCheckboxChange = async (checked: boolean) => {
|
|
||||||
await props.todoCheckbox_change(checked);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onPress = async () => {
|
|
||||||
if (!note) return;
|
|
||||||
if (note.encryption_applied) return;
|
|
||||||
|
|
||||||
props.dispatch({
|
|
||||||
type: 'NAV_BACK',
|
|
||||||
});
|
|
||||||
|
|
||||||
shim.setTimeout(() => {
|
|
||||||
props.dispatch({
|
|
||||||
type: 'NAV_GO',
|
|
||||||
routeName: 'Note',
|
|
||||||
noteId: note.id,
|
|
||||||
});
|
|
||||||
}, 5);
|
|
||||||
};
|
|
||||||
|
|
||||||
const noteTitle = Note.displayTitle(note);
|
|
||||||
let item;
|
|
||||||
|
|
||||||
if (isTodo) {
|
|
||||||
item = (
|
|
||||||
<View>
|
|
||||||
<TouchableOpacity style={[styles().horizontalFlex, styles().item, styles().selectedItem]} onPress={onPress}>
|
|
||||||
<Checkbox
|
|
||||||
style={styles().checkbox}
|
|
||||||
checked={!!Number(note.todo_completed)}
|
|
||||||
onChange={(checked) => onTodoCheckboxChange(checked)}
|
|
||||||
accessibilityLabel={_('to-do: %s', noteTitle)}
|
|
||||||
/>
|
|
||||||
<Text style={styles().itemText}>{noteTitle}</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
item = (
|
|
||||||
<View>
|
|
||||||
<TouchableOpacity onPress={onPress} style={[styles().selectedItem, styles().item]}>
|
|
||||||
<Text style={[styles().itemText, styles().padding]}>{noteTitle}</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
};
|
|
||||||
|
|
||||||
const NotesBarListItem = connect((state: State) => {
|
|
||||||
return {
|
|
||||||
themeId: state.settings.theme,
|
|
||||||
selectedNoteId: state.selectedNoteIds[0],
|
|
||||||
};
|
|
||||||
})(NotesBarListItemComponent);
|
|
||||||
|
|
||||||
export default NotesBarListItem;
|
|
@ -1,93 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
const Component = React.Component;
|
|
||||||
const { View, TouchableHighlight } = require('react-native');
|
|
||||||
const Icon = require('react-native-vector-icons/Ionicons').default;
|
|
||||||
Icon.loadFont();
|
|
||||||
|
|
||||||
interface Style {
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
interface Props {
|
|
||||||
style: Style;
|
|
||||||
checked: boolean;
|
|
||||||
onChange: (checked: boolean)=> void;
|
|
||||||
accessibilityLabel?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface State {
|
|
||||||
checked: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles: Style = {
|
|
||||||
checkboxIcon: {
|
|
||||||
fontSize: 20,
|
|
||||||
height: 22,
|
|
||||||
// marginRight: 10,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
class Checkbox extends Component<Props, State> {
|
|
||||||
|
|
||||||
public constructor(props: Props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
checked: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public UNSAFE_componentWillMount() {
|
|
||||||
this.setState({ checked: this.props.checked });
|
|
||||||
}
|
|
||||||
|
|
||||||
public UNSAFE_componentWillReceiveProps(newProps: Props) {
|
|
||||||
if ('checked' in newProps) {
|
|
||||||
this.setState({ checked: newProps.checked });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private onPress() {
|
|
||||||
const newChecked = !this.state.checked;
|
|
||||||
this.setState({ checked: newChecked });
|
|
||||||
if (this.props.onChange) this.props.onChange(newChecked);
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
|
||||||
const iconName = this.state.checked ? 'md-checkbox-outline' : 'md-square-outline';
|
|
||||||
|
|
||||||
const style: Style = this.props.style ? Object.assign({}, this.props.style) : {};
|
|
||||||
style.justifyContent = 'center';
|
|
||||||
style.alignItems = 'center';
|
|
||||||
|
|
||||||
const checkboxIconStyle = Object.assign({}, styles.checkboxIcon);
|
|
||||||
if (style.color) checkboxIconStyle.color = style.color;
|
|
||||||
|
|
||||||
if (style.paddingTop) checkboxIconStyle.marginTop = style.paddingTop;
|
|
||||||
if (style.paddingBottom) checkboxIconStyle.marginBottom = style.paddingBottom;
|
|
||||||
if (style.paddingLeft) checkboxIconStyle.marginLeft = style.paddingLeft;
|
|
||||||
if (style.paddingRight) checkboxIconStyle.marginRight = style.paddingRight;
|
|
||||||
|
|
||||||
const thStyle = {
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
};
|
|
||||||
|
|
||||||
if (style && style.display === 'none') return <View />;
|
|
||||||
|
|
||||||
// if (style.display) thStyle.display = style.display;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TouchableHighlight
|
|
||||||
onPress={() => this.onPress()}
|
|
||||||
style={thStyle}
|
|
||||||
accessibilityRole="checkbox"
|
|
||||||
accessibilityState={{
|
|
||||||
checked: this.state.checked,
|
|
||||||
}}
|
|
||||||
accessibilityLabel={this.props.accessibilityLabel ?? ''}>
|
|
||||||
<Icon name={iconName} style={checkboxIconStyle} />
|
|
||||||
</TouchableHighlight>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Checkbox;
|
|
@ -1,115 +0,0 @@
|
|||||||
import Setting from '@joplin/lib/models/Setting';
|
|
||||||
const { Platform } = require('react-native');
|
|
||||||
import { themeById } from '@joplin/lib/theme';
|
|
||||||
|
|
||||||
export interface Style {
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Fonts {
|
|
||||||
[key: number]: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ThemeCache {
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseStyle = {
|
|
||||||
appearance: 'light',
|
|
||||||
fontSize: 16,
|
|
||||||
noteViewerFontSize: 16,
|
|
||||||
margin: 15, // No text and no interactive component should be within this margin
|
|
||||||
itemMarginTop: 10,
|
|
||||||
itemMarginBottom: 10,
|
|
||||||
fontSizeSmaller: 14,
|
|
||||||
disabledOpacity: 0.2,
|
|
||||||
lineHeight: '1.6em',
|
|
||||||
};
|
|
||||||
|
|
||||||
const themeCache_: ThemeCache = {};
|
|
||||||
|
|
||||||
function addExtraStyles(style: Style) {
|
|
||||||
style.marginRight = style.margin;
|
|
||||||
style.marginLeft = style.margin;
|
|
||||||
style.marginTop = style.margin;
|
|
||||||
style.marginBottom = style.margin;
|
|
||||||
|
|
||||||
style.icon = {
|
|
||||||
color: style.color,
|
|
||||||
fontSize: 30,
|
|
||||||
};
|
|
||||||
|
|
||||||
style.lineInput = {
|
|
||||||
color: style.color,
|
|
||||||
backgroundColor: style.backgroundColor,
|
|
||||||
borderBottomWidth: 1,
|
|
||||||
borderColor: style.dividerColor,
|
|
||||||
paddingBottom: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (Platform.OS === 'ios') {
|
|
||||||
delete style.lineInput.borderBottomWidth;
|
|
||||||
delete style.lineInput.borderColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
style.buttonRow = {
|
|
||||||
flexDirection: 'row',
|
|
||||||
borderTopWidth: 1,
|
|
||||||
borderTopColor: style.dividerColor,
|
|
||||||
paddingTop: 10,
|
|
||||||
};
|
|
||||||
|
|
||||||
style.normalText = {
|
|
||||||
color: style.color,
|
|
||||||
fontSize: style.fontSize,
|
|
||||||
};
|
|
||||||
|
|
||||||
style.urlText = {
|
|
||||||
color: style.urlColor,
|
|
||||||
fontSize: style.fontSize,
|
|
||||||
};
|
|
||||||
|
|
||||||
style.headerStyle = {
|
|
||||||
color: style.color,
|
|
||||||
fontSize: style.fontSize * 1.2,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
};
|
|
||||||
|
|
||||||
style.headerWrapperStyle = {
|
|
||||||
backgroundColor: style.headerBackgroundColor,
|
|
||||||
};
|
|
||||||
|
|
||||||
style.keyboardAppearance = style.appearance;
|
|
||||||
|
|
||||||
return style;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function editorFont(fontId?: number) {
|
|
||||||
// IMPORTANT: The font mapping must match the one in Setting.js
|
|
||||||
const fonts: Fonts = {
|
|
||||||
[Setting.FONT_DEFAULT]: null,
|
|
||||||
[Setting.FONT_MENLO]: 'Menlo',
|
|
||||||
[Setting.FONT_COURIER_NEW]: 'Courier New',
|
|
||||||
[Setting.FONT_AVENIR]: 'Avenir',
|
|
||||||
[Setting.FONT_MONOSPACE]: 'monospace',
|
|
||||||
};
|
|
||||||
if (!fontId) {
|
|
||||||
// console.warn('Editor font not set! Falling back to default font."');
|
|
||||||
fontId = Setting.FONT_DEFAULT;
|
|
||||||
}
|
|
||||||
return fonts[fontId];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function themeStyle(theme?: number) {
|
|
||||||
if (!theme) {
|
|
||||||
console.warn('Theme not set! Defaulting to Light theme.');
|
|
||||||
theme = Setting.THEME_LIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cacheKey = [theme].join('-');
|
|
||||||
if (themeCache_[cacheKey]) return themeCache_[cacheKey];
|
|
||||||
|
|
||||||
const output = Object.assign({}, baseStyle, themeById(theme));
|
|
||||||
themeCache_[cacheKey] = addExtraStyles(output);
|
|
||||||
return themeCache_[cacheKey];
|
|
||||||
}
|
|
@ -2,7 +2,7 @@ const React = require('react');
|
|||||||
const Component = React.Component;
|
const Component = React.Component;
|
||||||
const { connect } = require('react-redux');
|
const { connect } = require('react-redux');
|
||||||
const { Text, TouchableOpacity, View, StyleSheet } = require('react-native');
|
const { Text, TouchableOpacity, View, StyleSheet } = require('react-native');
|
||||||
const Checkbox = require('./checkbox.js').default;
|
const { Checkbox } = require('./checkbox.js');
|
||||||
const Note = require('@joplin/lib/models/Note').default;
|
const Note = require('@joplin/lib/models/Note').default;
|
||||||
const time = require('@joplin/lib/time').default;
|
const time = require('@joplin/lib/time').default;
|
||||||
const { themeStyle } = require('./global-style.js');
|
const { themeStyle } = require('./global-style.js');
|
||||||
|
@ -3,7 +3,6 @@ import uuid from '@joplin/lib/uuid';
|
|||||||
import Setting from '@joplin/lib/models/Setting';
|
import Setting from '@joplin/lib/models/Setting';
|
||||||
import shim from '@joplin/lib/shim';
|
import shim from '@joplin/lib/shim';
|
||||||
import UndoRedoService from '@joplin/lib/services/UndoRedoService';
|
import UndoRedoService from '@joplin/lib/services/UndoRedoService';
|
||||||
import { State } from '@joplin/lib/reducer';
|
|
||||||
import NoteBodyViewer from '../NoteBodyViewer/NoteBodyViewer';
|
import NoteBodyViewer from '../NoteBodyViewer/NoteBodyViewer';
|
||||||
import checkPermissions from '../../utils/checkPermissions';
|
import checkPermissions from '../../utils/checkPermissions';
|
||||||
import NoteEditor from '../NoteEditor/NoteEditor';
|
import NoteEditor from '../NoteEditor/NoteEditor';
|
||||||
@ -11,7 +10,7 @@ import { ChangeEvent, UndoRedoDepthChangeEvent } from '../NoteEditor/types';
|
|||||||
|
|
||||||
const FileViewer = require('react-native-file-viewer').default;
|
const FileViewer = require('react-native-file-viewer').default;
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
import { Platform, Keyboard, View, TextInput, StyleSheet, Linking, Image, Share, PermissionsAndroid, Animated, TouchableOpacity, Dimensions, PanResponder } from 'react-native';
|
const { Platform, Keyboard, View, TextInput, StyleSheet, Linking, Image, Share, PermissionsAndroid } = require('react-native');
|
||||||
const { connect } = require('react-redux');
|
const { connect } = require('react-redux');
|
||||||
// const { MarkdownEditor } = require('@joplin/lib/../MarkdownEditor/index.js');
|
// const { MarkdownEditor } = require('@joplin/lib/../MarkdownEditor/index.js');
|
||||||
const RNFS = require('react-native-fs');
|
const RNFS = require('react-native-fs');
|
||||||
@ -30,12 +29,12 @@ const mimeUtils = require('@joplin/lib/mime-utils.js').mime;
|
|||||||
import ScreenHeader from '../ScreenHeader';
|
import ScreenHeader from '../ScreenHeader';
|
||||||
const NoteTagsDialog = require('./NoteTagsDialog');
|
const NoteTagsDialog = require('./NoteTagsDialog');
|
||||||
import time from '@joplin/lib/time';
|
import time from '@joplin/lib/time';
|
||||||
import Checkbox from '../checkbox';
|
const { Checkbox } = require('../checkbox.js');
|
||||||
const { _ } = require('@joplin/lib/locale');
|
const { _ } = require('@joplin/lib/locale');
|
||||||
import { reg } from '@joplin/lib/registry';
|
import { reg } from '@joplin/lib/registry';
|
||||||
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
|
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
|
||||||
const { BaseScreenComponent } = require('../base-screen.js');
|
const { BaseScreenComponent } = require('../base-screen.js');
|
||||||
import { themeStyle, editorFont } from '../global-style';
|
const { themeStyle, editorFont } = require('../global-style.js');
|
||||||
const { dialogs } = require('../../utils/dialogs.js');
|
const { dialogs } = require('../../utils/dialogs.js');
|
||||||
const DialogBox = require('react-native-dialogbox').default;
|
const DialogBox = require('react-native-dialogbox').default;
|
||||||
const DocumentPicker = require('react-native-document-picker').default;
|
const DocumentPicker = require('react-native-document-picker').default;
|
||||||
@ -46,23 +45,20 @@ import { ImagePickerResponse } from 'react-native-image-picker';
|
|||||||
import SelectDateTimeDialog from '../SelectDateTimeDialog';
|
import SelectDateTimeDialog from '../SelectDateTimeDialog';
|
||||||
import ShareExtension from '../../utils/ShareExtension.js';
|
import ShareExtension from '../../utils/ShareExtension.js';
|
||||||
import CameraView from '../CameraView';
|
import CameraView from '../CameraView';
|
||||||
import NotesBar from '../NotesBar';
|
|
||||||
import { NoteEntity } from '@joplin/lib/services/database/types';
|
import { NoteEntity } from '@joplin/lib/services/database/types';
|
||||||
import Logger from '@joplin/lib/Logger';
|
import Logger from '@joplin/lib/Logger';
|
||||||
const urlUtils = require('@joplin/lib/urlUtils');
|
const urlUtils = require('@joplin/lib/urlUtils');
|
||||||
const Icon = require('react-native-vector-icons/Feather').default;
|
|
||||||
import getResponsiveValue from '../getResponsiveValue';
|
|
||||||
|
|
||||||
const emptyArray: any[] = [];
|
const emptyArray: any[] = [];
|
||||||
|
|
||||||
const logger = Logger.create('screens/Note');
|
const logger = Logger.create('screens/Note');
|
||||||
|
|
||||||
class NoteScreenComponent extends BaseScreenComponent {
|
class NoteScreenComponent extends BaseScreenComponent {
|
||||||
public static navigationOptions(): any {
|
static navigationOptions(): any {
|
||||||
return { header: null };
|
return { header: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
public constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
note: Note.new(),
|
note: Note.new(),
|
||||||
@ -91,9 +87,6 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
canUndo: false,
|
canUndo: false,
|
||||||
canRedo: false,
|
canRedo: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
notesBarWidth: this.getNotesBarWidth(),
|
|
||||||
isTablet: Dimensions.get('window').width >= 768,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.saveActionQueues_ = {};
|
this.saveActionQueues_ = {};
|
||||||
@ -205,7 +198,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
if (msg.indexOf('file://') === 0) {
|
if (msg.indexOf('file://') === 0) {
|
||||||
throw new Error(_('Links with protocol "%s" are not supported', 'file://'));
|
throw new Error(_('Links with protocol "%s" are not supported', 'file://'));
|
||||||
} else {
|
} else {
|
||||||
await Linking.openURL(msg);
|
Linking.openURL(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -246,8 +239,6 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
this.onBodyViewerCheckboxChange = this.onBodyViewerCheckboxChange.bind(this);
|
this.onBodyViewerCheckboxChange = this.onBodyViewerCheckboxChange.bind(this);
|
||||||
this.onBodyChange = this.onBodyChange.bind(this);
|
this.onBodyChange = this.onBodyChange.bind(this);
|
||||||
this.onUndoRedoDepthChange = this.onUndoRedoDepthChange.bind(this);
|
this.onUndoRedoDepthChange = this.onUndoRedoDepthChange.bind(this);
|
||||||
this.onNotesBarToggle = this.onNotesBarToggle.bind(this);
|
|
||||||
this.handleScreenWidthChange_ = this.handleScreenWidthChange_.bind(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private useEditorBeta(): boolean {
|
private useEditorBeta(): boolean {
|
||||||
@ -290,27 +281,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private getNotesBarWidth = () => {
|
screenHeader_undoButtonPress() {
|
||||||
const notesBarWidth = getResponsiveValue({
|
|
||||||
sm: 250,
|
|
||||||
md: 260,
|
|
||||||
lg: 270,
|
|
||||||
xl: 280,
|
|
||||||
xxl: 290,
|
|
||||||
});
|
|
||||||
|
|
||||||
return notesBarWidth;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update state that depends on the screen width when the screen width changes ( the device orientation changess)
|
|
||||||
private handleScreenWidthChange_() {
|
|
||||||
this.setState({
|
|
||||||
notesBarWidth: this.getNotesBarWidth(),
|
|
||||||
isTablet: Dimensions.get('window').width >= 768,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private screenHeader_undoButtonPress() {
|
|
||||||
if (this.useEditorBeta()) {
|
if (this.useEditorBeta()) {
|
||||||
this.editorRef.current.undo();
|
this.editorRef.current.undo();
|
||||||
} else {
|
} else {
|
||||||
@ -318,7 +289,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private screenHeader_redoButtonPress() {
|
screenHeader_redoButtonPress() {
|
||||||
if (this.useEditorBeta()) {
|
if (this.useEditorBeta()) {
|
||||||
this.editorRef.current.redo();
|
this.editorRef.current.redo();
|
||||||
} else {
|
} else {
|
||||||
@ -326,13 +297,13 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private undoState(noteBody: string = null) {
|
undoState(noteBody: string = null) {
|
||||||
return {
|
return {
|
||||||
body: noteBody === null ? this.state.note.body : noteBody,
|
body: noteBody === null ? this.state.note.body : noteBody,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private styles() {
|
styles() {
|
||||||
const themeId = this.props.themeId;
|
const themeId = this.props.themeId;
|
||||||
const theme = themeStyle(themeId);
|
const theme = themeStyle(themeId);
|
||||||
|
|
||||||
@ -351,7 +322,6 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
paddingLeft: theme.marginLeft,
|
paddingLeft: theme.marginLeft,
|
||||||
paddingRight: theme.marginRight,
|
paddingRight: theme.marginRight,
|
||||||
paddingBottom: Platform.OS === 'ios' ? 40 : 0,
|
|
||||||
|
|
||||||
// Add extra space to allow scrolling past end of document, and also to fix this:
|
// Add extra space to allow scrolling past end of document, and also to fix this:
|
||||||
// https://github.com/laurent22/joplin/issues/1437
|
// https://github.com/laurent22/joplin/issues/1437
|
||||||
@ -417,84 +387,17 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
paddingBottom: 10, // Added for iOS (Not needed for Android??)
|
paddingBottom: 10, // Added for iOS (Not needed for Android??)
|
||||||
};
|
};
|
||||||
|
|
||||||
styles.noteMainComp = {
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
position: 'relative',
|
|
||||||
};
|
|
||||||
|
|
||||||
styles.notesBarContainer = {
|
|
||||||
position: 'relative',
|
|
||||||
left: this.notesBarPosition,
|
|
||||||
top: 0,
|
|
||||||
width: this.state.notesBarWidth,
|
|
||||||
height: '100%',
|
|
||||||
};
|
|
||||||
|
|
||||||
styles.noteComp = {
|
|
||||||
position: 'relative',
|
|
||||||
top: 0,
|
|
||||||
left: this.notePosition,
|
|
||||||
width: this.noteWidth,
|
|
||||||
};
|
|
||||||
|
|
||||||
styles.noteActionButton = {
|
|
||||||
width: 54,
|
|
||||||
height: 54,
|
|
||||||
backgroundColor: theme.backgroundColor3,
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: theme.dividerColor,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
};
|
|
||||||
|
|
||||||
styles.noteActionButtonActive = {
|
|
||||||
...styles.noteActionButton,
|
|
||||||
borderWidth: 0,
|
|
||||||
backgroundColor: theme.color4,
|
|
||||||
};
|
|
||||||
|
|
||||||
styles.noteActionButton1 = {
|
|
||||||
borderBottomWidth: 0,
|
|
||||||
borderTopLeftRadius: 8,
|
|
||||||
borderTopRightRadius: 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
styles.noteActionButton2 = {
|
|
||||||
// Removing this temporarily till second noteAction is implemented
|
|
||||||
// borderBottomLeftRadius: 8,
|
|
||||||
// borderBottomRightRadius: 8,
|
|
||||||
borderRadius: 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
styles.noteActionButtonIcon = {
|
|
||||||
fontSize: 30,
|
|
||||||
color: theme.color,
|
|
||||||
};
|
|
||||||
|
|
||||||
styles.noteActionButtonIconActive = {
|
|
||||||
...styles.noteActionButtonIcon,
|
|
||||||
color: theme.backgroundColor,
|
|
||||||
};
|
|
||||||
|
|
||||||
styles.noteActionButtonGroup = {
|
|
||||||
position: 'absolute',
|
|
||||||
top: '8%',
|
|
||||||
right: '3%',
|
|
||||||
transform: [{ translateY: this.noteActionsPositionY }],
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.state.HACK_webviewLoadingState === 1) styles.titleTextInput.marginTop = 1;
|
if (this.state.HACK_webviewLoadingState === 1) styles.titleTextInput.marginTop = 1;
|
||||||
|
|
||||||
this.styles_[cacheKey] = StyleSheet.create(styles);
|
this.styles_[cacheKey] = StyleSheet.create(styles);
|
||||||
return this.styles_[cacheKey];
|
return this.styles_[cacheKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
private isModified() {
|
isModified() {
|
||||||
return shared.isModified(this);
|
return shared.isModified(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async requestGeoLocationPermissions() {
|
async requestGeoLocationPermissions() {
|
||||||
if (!Setting.value('trackLocation')) return;
|
if (!Setting.value('trackLocation')) return;
|
||||||
|
|
||||||
const response = await checkPermissions(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, {
|
const response = await checkPermissions(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, {
|
||||||
@ -511,7 +414,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async componentDidMount() {
|
async componentDidMount() {
|
||||||
BackButtonService.addHandler(this.backHandler);
|
BackButtonService.addHandler(this.backHandler);
|
||||||
NavService.addHandler(this.navHandler);
|
NavService.addHandler(this.navHandler);
|
||||||
|
|
||||||
@ -532,75 +435,13 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
// has already been granted, it doesn't slow down opening the note. If it hasn't
|
// has already been granted, it doesn't slow down opening the note. If it hasn't
|
||||||
// been granted, the popup will open anyway.
|
// been granted, the popup will open anyway.
|
||||||
void this.requestGeoLocationPermissions();
|
void this.requestGeoLocationPermissions();
|
||||||
|
|
||||||
this.unsubscribeScreenWidthChangeHandler_ = Dimensions.addEventListener('change', this.handleScreenWidthChange_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private animateNotesBarOpen = () => {
|
onMarkForDownload(event: any) {
|
||||||
Animated.parallel([
|
|
||||||
Animated.spring(
|
|
||||||
this.notesBarPosition,
|
|
||||||
{
|
|
||||||
toValue: 0,
|
|
||||||
useNativeDriver: false,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
Animated.spring(
|
|
||||||
this.notePosition,
|
|
||||||
{
|
|
||||||
toValue: 0,
|
|
||||||
useNativeDriver: false,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
Animated.spring(
|
|
||||||
this.noteWidth,
|
|
||||||
{
|
|
||||||
toValue: Dimensions.get('window').width - this.state.notesBarWidth,
|
|
||||||
useNativeDriver: false,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
]).start();
|
|
||||||
};
|
|
||||||
|
|
||||||
private animateNotesBarClose = () => {
|
|
||||||
Animated.parallel([
|
|
||||||
Animated.spring(
|
|
||||||
this.notesBarPosition,
|
|
||||||
{
|
|
||||||
toValue: -1 * this.state.notesBarWidth,
|
|
||||||
useNativeDriver: false,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
Animated.spring(
|
|
||||||
this.notePosition,
|
|
||||||
{
|
|
||||||
toValue: -1 * this.state.notesBarWidth,
|
|
||||||
useNativeDriver: false,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
Animated.spring(
|
|
||||||
this.noteWidth,
|
|
||||||
{
|
|
||||||
toValue: Dimensions.get('window').width,
|
|
||||||
useNativeDriver: false,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
]).start();
|
|
||||||
};
|
|
||||||
|
|
||||||
private onNotesBarToggle = async () => {
|
|
||||||
if (this.props.showNotesBar) {
|
|
||||||
this.props.dispatch({ type: 'NOTES_BAR_CLOSE' });
|
|
||||||
} else {
|
|
||||||
this.props.dispatch({ type: 'NOTES_BAR_OPEN' });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private onMarkForDownload(event: any) {
|
|
||||||
void ResourceFetcher.instance().markForDownload(event.resourceId);
|
void ResourceFetcher.instance().markForDownload(event.resourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidUpdate(prevProps: any) {
|
componentDidUpdate(prevProps: any) {
|
||||||
if (this.doFocusUpdate_) {
|
if (this.doFocusUpdate_) {
|
||||||
this.doFocusUpdate_ = false;
|
this.doFocusUpdate_ = false;
|
||||||
this.focusUpdate();
|
this.focusUpdate();
|
||||||
@ -612,17 +453,9 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
options: this.sideMenuOptions(),
|
options: this.sideMenuOptions(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.showNotesBar !== prevProps.showNotesBar) {
|
|
||||||
if (this.props.showNotesBar) {
|
|
||||||
this.animateNotesBarOpen();
|
|
||||||
} else {
|
|
||||||
this.animateNotesBarClose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
BackButtonService.removeHandler(this.backHandler);
|
BackButtonService.removeHandler(this.backHandler);
|
||||||
NavService.removeHandler(this.navHandler);
|
NavService.removeHandler(this.navHandler);
|
||||||
|
|
||||||
@ -637,34 +470,15 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
// It cannot theoretically be undefined, since componentDidMount should always be called before
|
// It cannot theoretically be undefined, since componentDidMount should always be called before
|
||||||
// componentWillUnmount, but with React Native the impossible often becomes possible.
|
// componentWillUnmount, but with React Native the impossible often becomes possible.
|
||||||
if (this.undoRedoService_) this.undoRedoService_.off('stackChange', this.undoRedoService_stackChange);
|
if (this.undoRedoService_) this.undoRedoService_.off('stackChange', this.undoRedoService_stackChange);
|
||||||
|
|
||||||
if (this.unsubscribeScreenWidthChangeHandler_) {
|
|
||||||
this.unsubscribeScreenWidthChangeHandler_.remove();
|
|
||||||
this.unsubscribeScreenWidthChangeHandler_ = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillMount() {
|
title_changeText(text: string) {
|
||||||
if (this.props.showNotesBar) {
|
|
||||||
this.notesBarPosition = new Animated.Value(0);
|
|
||||||
this.notePosition = new Animated.Value(0);
|
|
||||||
this.noteWidth = new Animated.Value(Dimensions.get('window').width - 250);
|
|
||||||
} else {
|
|
||||||
this.notesBarPosition = new Animated.Value(-1 * this.state.notesBarWidth);
|
|
||||||
this.notePosition = new Animated.Value(-1 * this.state.notesBarWidth);
|
|
||||||
this.noteWidth = new Animated.Value(Dimensions.get('window').width);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.noteActionsPositionY = new Animated.Value(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private title_changeText(text: string) {
|
|
||||||
shared.noteComponent_change(this, 'title', text);
|
shared.noteComponent_change(this, 'title', text);
|
||||||
this.setState({ newAndNoTitleChangeNoteId: null });
|
this.setState({ newAndNoTitleChangeNoteId: null });
|
||||||
this.scheduleSave();
|
this.scheduleSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
private body_changeText(text: string) {
|
body_changeText(text: string) {
|
||||||
if (!this.undoRedoService_.canUndo) {
|
if (!this.undoRedoService_.canUndo) {
|
||||||
this.undoRedoService_.push(this.undoState());
|
this.undoRedoService_.push(this.undoState());
|
||||||
} else {
|
} else {
|
||||||
@ -675,7 +489,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
this.scheduleSave();
|
this.scheduleSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
private body_selectionChange(event: any) {
|
body_selectionChange(event: any) {
|
||||||
if (this.useEditorBeta()) {
|
if (this.useEditorBeta()) {
|
||||||
this.selection = event.selection;
|
this.selection = event.selection;
|
||||||
} else {
|
} else {
|
||||||
@ -683,34 +497,34 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private makeSaveAction() {
|
makeSaveAction() {
|
||||||
return async () => {
|
return async () => {
|
||||||
return shared.saveNoteButton_press(this);
|
return shared.saveNoteButton_press(this);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private saveActionQueue(noteId: string) {
|
saveActionQueue(noteId: string) {
|
||||||
if (!this.saveActionQueues_[noteId]) {
|
if (!this.saveActionQueues_[noteId]) {
|
||||||
this.saveActionQueues_[noteId] = new AsyncActionQueue(500);
|
this.saveActionQueues_[noteId] = new AsyncActionQueue(500);
|
||||||
}
|
}
|
||||||
return this.saveActionQueues_[noteId];
|
return this.saveActionQueues_[noteId];
|
||||||
}
|
}
|
||||||
|
|
||||||
private scheduleSave() {
|
scheduleSave() {
|
||||||
this.saveActionQueue(this.state.note.id).push(this.makeSaveAction());
|
this.saveActionQueue(this.state.note.id).push(this.makeSaveAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
private async saveNoteButton_press(folderId: string = null) {
|
async saveNoteButton_press(folderId: string = null) {
|
||||||
await shared.saveNoteButton_press(this, folderId);
|
await shared.saveNoteButton_press(this, folderId);
|
||||||
|
|
||||||
Keyboard.dismiss();
|
Keyboard.dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async saveOneProperty(name: string, value: any) {
|
async saveOneProperty(name: string, value: any) {
|
||||||
await shared.saveOneProperty(this, name, value);
|
await shared.saveOneProperty(this, name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async deleteNote_onPress() {
|
async deleteNote_onPress() {
|
||||||
const note = this.state.note;
|
const note = this.state.note;
|
||||||
if (!note.id) return;
|
if (!note.id) return;
|
||||||
|
|
||||||
@ -743,7 +557,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async imageDimensions(uri: string) {
|
async imageDimensions(uri: string) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
Image.getSize(
|
Image.getSize(
|
||||||
uri,
|
uri,
|
||||||
@ -757,7 +571,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private showImagePicker(options: any) {
|
showImagePicker(options: any) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
ImagePicker.launchImageLibrary(options, (response: any) => {
|
ImagePicker.launchImageLibrary(options, (response: any) => {
|
||||||
resolve(response);
|
resolve(response);
|
||||||
@ -765,7 +579,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async resizeImage(localFilePath: string, targetPath: string, mimeType: string) {
|
async resizeImage(localFilePath: string, targetPath: string, mimeType: string) {
|
||||||
const maxSize = Resource.IMAGE_MAX_DIMENSION;
|
const maxSize = Resource.IMAGE_MAX_DIMENSION;
|
||||||
|
|
||||||
const dimensions: any = await this.imageDimensions(localFilePath);
|
const dimensions: any = await this.imageDimensions(localFilePath);
|
||||||
@ -814,7 +628,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async attachFile(pickerResponse: any, fileType: string) {
|
async attachFile(pickerResponse: any, fileType: string) {
|
||||||
if (!pickerResponse) {
|
if (!pickerResponse) {
|
||||||
// User has cancelled
|
// User has cancelled
|
||||||
return;
|
return;
|
||||||
@ -932,11 +746,11 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private takePhoto_onPress() {
|
takePhoto_onPress() {
|
||||||
this.setState({ showCamera: true });
|
this.setState({ showCamera: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
private cameraView_onPhoto(data: any) {
|
cameraView_onPhoto(data: any) {
|
||||||
void this.attachFile(
|
void this.attachFile(
|
||||||
{
|
{
|
||||||
uri: data.uri,
|
uri: data.uri,
|
||||||
@ -948,7 +762,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
this.setState({ showCamera: false });
|
this.setState({ showCamera: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
private cameraView_onCancel() {
|
cameraView_onCancel() {
|
||||||
this.setState({ showCamera: false });
|
this.setState({ showCamera: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -959,34 +773,34 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private toggleIsTodo_onPress() {
|
toggleIsTodo_onPress() {
|
||||||
shared.toggleIsTodo_onPress(this);
|
shared.toggleIsTodo_onPress(this);
|
||||||
|
|
||||||
this.scheduleSave();
|
this.scheduleSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
private tags_onPress() {
|
tags_onPress() {
|
||||||
if (!this.state.note || !this.state.note.id) return;
|
if (!this.state.note || !this.state.note.id) return;
|
||||||
|
|
||||||
this.setState({ noteTagDialogShown: true });
|
this.setState({ noteTagDialogShown: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async share_onPress() {
|
async share_onPress() {
|
||||||
await Share.share({
|
await Share.share({
|
||||||
message: `${this.state.note.title}\n\n${this.state.note.body}`,
|
message: `${this.state.note.title}\n\n${this.state.note.body}`,
|
||||||
title: this.state.note.title,
|
title: this.state.note.title,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private properties_onPress() {
|
properties_onPress() {
|
||||||
this.props.dispatch({ type: 'SIDE_MENU_OPEN' });
|
this.props.dispatch({ type: 'SIDE_MENU_OPEN' });
|
||||||
}
|
}
|
||||||
|
|
||||||
public setAlarm_onPress() {
|
setAlarm_onPress() {
|
||||||
this.setState({ alarmDialogShown: true });
|
this.setState({ alarmDialogShown: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async onAlarmDialogAccept(date: Date) {
|
async onAlarmDialogAccept(date: Date) {
|
||||||
const newNote = Object.assign({}, this.state.note);
|
const newNote = Object.assign({}, this.state.note);
|
||||||
newNote.todo_due = date ? date.getTime() : 0;
|
newNote.todo_due = date ? date.getTime() : 0;
|
||||||
|
|
||||||
@ -995,40 +809,40 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
this.setState({ alarmDialogShown: false });
|
this.setState({ alarmDialogShown: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
private onAlarmDialogReject() {
|
onAlarmDialogReject() {
|
||||||
this.setState({ alarmDialogShown: false });
|
this.setState({ alarmDialogShown: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async showOnMap_onPress() {
|
async showOnMap_onPress() {
|
||||||
if (!this.state.note.id) return;
|
if (!this.state.note.id) return;
|
||||||
|
|
||||||
const note = await Note.load(this.state.note.id);
|
const note = await Note.load(this.state.note.id);
|
||||||
try {
|
try {
|
||||||
const url = Note.geolocationUrl(note);
|
const url = Note.geolocationUrl(note);
|
||||||
await Linking.openURL(url);
|
Linking.openURL(url);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.props.dispatch({ type: 'SIDE_MENU_CLOSE' });
|
this.props.dispatch({ type: 'SIDE_MENU_CLOSE' });
|
||||||
await dialogs.error(this, error.message);
|
await dialogs.error(this, error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async showSource_onPress() {
|
async showSource_onPress() {
|
||||||
if (!this.state.note.id) return;
|
if (!this.state.note.id) return;
|
||||||
|
|
||||||
const note = await Note.load(this.state.note.id);
|
const note = await Note.load(this.state.note.id);
|
||||||
try {
|
try {
|
||||||
await Linking.openURL(note.source_url);
|
Linking.openURL(note.source_url);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await dialogs.error(this, error.message);
|
await dialogs.error(this, error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private copyMarkdownLink_onPress() {
|
copyMarkdownLink_onPress() {
|
||||||
const note = this.state.note;
|
const note = this.state.note;
|
||||||
Clipboard.setString(Note.markdownTag(note));
|
Clipboard.setString(Note.markdownTag(note));
|
||||||
}
|
}
|
||||||
|
|
||||||
private sideMenuOptions() {
|
sideMenuOptions() {
|
||||||
const note = this.state.note;
|
const note = this.state.note;
|
||||||
if (!note) return [];
|
if (!note) return [];
|
||||||
|
|
||||||
@ -1080,7 +894,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
if (buttonId === 'attachPhoto') void this.attachPhoto_onPress();
|
if (buttonId === 'attachPhoto') void this.attachPhoto_onPress();
|
||||||
}
|
}
|
||||||
|
|
||||||
private menuOptions() {
|
menuOptions() {
|
||||||
const note = this.state.note;
|
const note = this.state.note;
|
||||||
const isTodo = note && !!note.is_todo;
|
const isTodo = note && !!note.is_todo;
|
||||||
const isSaved = note && note.id;
|
const isSaved = note && note.id;
|
||||||
@ -1164,11 +978,11 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async todoCheckbox_change(checked: boolean) {
|
async todoCheckbox_change(checked: boolean) {
|
||||||
await this.saveOneProperty('todo_completed', checked ? time.unixMs() : 0);
|
await this.saveOneProperty('todo_completed', checked ? time.unixMs() : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public scheduleFocusUpdate() {
|
scheduleFocusUpdate() {
|
||||||
if (this.focusUpdateIID_) shim.clearTimeout(this.focusUpdateIID_);
|
if (this.focusUpdateIID_) shim.clearTimeout(this.focusUpdateIID_);
|
||||||
|
|
||||||
this.focusUpdateIID_ = shim.setTimeout(() => {
|
this.focusUpdateIID_ = shim.setTimeout(() => {
|
||||||
@ -1177,7 +991,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
private focusUpdate() {
|
focusUpdate() {
|
||||||
if (this.focusUpdateIID_) shim.clearTimeout(this.focusUpdateIID_);
|
if (this.focusUpdateIID_) shim.clearTimeout(this.focusUpdateIID_);
|
||||||
this.focusUpdateIID_ = null;
|
this.focusUpdateIID_ = null;
|
||||||
|
|
||||||
@ -1195,7 +1009,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
private async folderPickerOptions_valueChanged(itemValue: any) {
|
async folderPickerOptions_valueChanged(itemValue: any) {
|
||||||
const note = this.state.note;
|
const note = this.state.note;
|
||||||
const isProvisionalNote = this.props.provisionalNoteIds.includes(note.id);
|
const isProvisionalNote = this.props.provisionalNoteIds.includes(note.id);
|
||||||
|
|
||||||
@ -1216,7 +1030,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private folderPickerOptions() {
|
folderPickerOptions() {
|
||||||
const options = {
|
const options = {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
selectedFolderId: this.state.folder ? this.state.folder.id : null,
|
selectedFolderId: this.state.folder ? this.state.folder.id : null,
|
||||||
@ -1229,7 +1043,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
return this.folderPickerOptions_;
|
return this.folderPickerOptions_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private onBodyViewerLoadEnd() {
|
onBodyViewerLoadEnd() {
|
||||||
shim.setTimeout(() => {
|
shim.setTimeout(() => {
|
||||||
this.setState({ HACK_webviewLoadingState: 1 });
|
this.setState({ HACK_webviewLoadingState: 1 });
|
||||||
shim.setTimeout(() => {
|
shim.setTimeout(() => {
|
||||||
@ -1238,11 +1052,11 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
}, 5);
|
}, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onBodyViewerCheckboxChange(newBody: string) {
|
onBodyViewerCheckboxChange(newBody: string) {
|
||||||
void this.saveOneProperty('body', newBody);
|
void this.saveOneProperty('body', newBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
render() {
|
||||||
if (this.state.isLoading) {
|
if (this.state.isLoading) {
|
||||||
return (
|
return (
|
||||||
<View style={this.styles().screen}>
|
<View style={this.styles().screen}>
|
||||||
@ -1319,6 +1133,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
placeholderTextColor={theme.colorFaded}
|
placeholderTextColor={theme.colorFaded}
|
||||||
// need some extra padding for iOS so that the keyboard won't cover last line of the note
|
// need some extra padding for iOS so that the keyboard won't cover last line of the note
|
||||||
// see https://github.com/laurent22/joplin/issues/3607
|
// see https://github.com/laurent22/joplin/issues/3607
|
||||||
|
paddingBottom={ Platform.OS === 'ios' ? 40 : 0}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -1397,65 +1212,6 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
|
|
||||||
const noteTagDialog = !this.state.noteTagDialogShown ? null : <NoteTagsDialog onCloseRequested={this.noteTagDialog_closeRequested} />;
|
const noteTagDialog = !this.state.noteTagDialogShown ? null : <NoteTagsDialog onCloseRequested={this.noteTagDialog_closeRequested} />;
|
||||||
|
|
||||||
// Different styles for when the note actions are active or not
|
|
||||||
const notesBarToggleIconStyle = this.props.showNotesBar ? this.styles().noteActionButtonIconActive : this.styles().noteActionButtonIcon;
|
|
||||||
const notesBarToggleStyle = this.props.showNotesBar ? this.styles().noteActionButtonActive : this.styles().noteActionButton;
|
|
||||||
|
|
||||||
const handleNoteActionsDrag = (gestureState: any) => {
|
|
||||||
const minY = 160;
|
|
||||||
const maxY = 0.8 * Dimensions.get('window').height;
|
|
||||||
|
|
||||||
let newY = gestureState.moveY;
|
|
||||||
|
|
||||||
if (newY < minY) {
|
|
||||||
newY = minY;
|
|
||||||
} else if (newY > maxY) {
|
|
||||||
newY = maxY;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.noteActionsPositionY.setValue(newY - 162);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Pan responder that handles making the note actions draggable.
|
|
||||||
// The note actions need to be draggable, because they could
|
|
||||||
// potentially obstruct some portion of a note's content
|
|
||||||
const noteActionsDragResponder = PanResponder.create({
|
|
||||||
// Only start dragging after moving at least 10px — this prevents clicks from dragging instead
|
|
||||||
// of triggering onPress events
|
|
||||||
onMoveShouldSetPanResponder: (_evt, gestureState) => {
|
|
||||||
return Math.abs(gestureState.dx) > 10 || Math.abs(gestureState.dy) > 10;
|
|
||||||
},
|
|
||||||
onPanResponderMove: (_e: any, gestureState: any) => {
|
|
||||||
handleNoteActionsDrag(gestureState);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Note actions are the notesbar and split layout toggle button
|
|
||||||
const noteActionButtonGroupComp = (
|
|
||||||
<Animated.View style={this.styles().noteActionButtonGroup} {...noteActionsDragResponder.panHandlers} >
|
|
||||||
{/* Temporarily hiding the split layout button till it's implemented */}
|
|
||||||
{/* <TouchableOpacity style={[this.styles().noteActionButton, this.styles().noteActionButton1]} activeOpacity={0.7}>
|
|
||||||
<Icon name="columns" style={this.styles().noteActionButtonIcon} />
|
|
||||||
</TouchableOpacity> */}
|
|
||||||
<TouchableOpacity style={[notesBarToggleStyle, this.styles().noteActionButton2]} activeOpacity={0.7} onPress={this.onNotesBarToggle}>
|
|
||||||
<Icon name="list" style={notesBarToggleIconStyle} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
</Animated.View>
|
|
||||||
);
|
|
||||||
|
|
||||||
const noteMainComp = (
|
|
||||||
<View style={this.styles().noteMainComp}>
|
|
||||||
<Animated.View style={this.styles().notesBarContainer}>
|
|
||||||
<NotesBar todoCheckbox_change={this.todoCheckbox_change} />
|
|
||||||
</Animated.View>
|
|
||||||
<Animated.View style={this.styles().noteComp}>
|
|
||||||
{titleComp}
|
|
||||||
{bodyComponent}
|
|
||||||
</Animated.View>
|
|
||||||
{ this.state.isTablet && noteActionButtonGroupComp }
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={this.rootStyle(this.props.themeId).root}>
|
<View style={this.rootStyle(this.props.themeId).root}>
|
||||||
<ScreenHeader
|
<ScreenHeader
|
||||||
@ -1472,7 +1228,8 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
onUndoButtonPress={this.screenHeader_undoButtonPress}
|
onUndoButtonPress={this.screenHeader_undoButtonPress}
|
||||||
onRedoButtonPress={this.screenHeader_redoButtonPress}
|
onRedoButtonPress={this.screenHeader_redoButtonPress}
|
||||||
/>
|
/>
|
||||||
{noteMainComp}
|
{titleComp}
|
||||||
|
{bodyComponent}
|
||||||
{actionButtonComp}
|
{actionButtonComp}
|
||||||
|
|
||||||
<SelectDateTimeDialog themeId={this.props.themeId} shown={this.state.alarmDialogShown} date={dueDate} onAccept={this.onAlarmDialogAccept} onReject={this.onAlarmDialogReject} />
|
<SelectDateTimeDialog themeId={this.props.themeId} shown={this.state.alarmDialogShown} date={dueDate} onAccept={this.onAlarmDialogAccept} onReject={this.onAlarmDialogReject} />
|
||||||
@ -1488,7 +1245,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const NoteScreen = connect((state: State) => {
|
const NoteScreen = connect((state: any) => {
|
||||||
return {
|
return {
|
||||||
noteId: state.selectedNoteIds.length ? state.selectedNoteIds[0] : null,
|
noteId: state.selectedNoteIds.length ? state.selectedNoteIds[0] : null,
|
||||||
noteHash: state.selectedNoteHash,
|
noteHash: state.selectedNoteHash,
|
||||||
@ -1504,7 +1261,6 @@ const NoteScreen = connect((state: State) => {
|
|||||||
provisionalNoteIds: state.provisionalNoteIds,
|
provisionalNoteIds: state.provisionalNoteIds,
|
||||||
highlightedWords: state.highlightedWords,
|
highlightedWords: state.highlightedWords,
|
||||||
useEditorBeta: state.settings['editor.beta'],
|
useEditorBeta: state.settings['editor.beta'],
|
||||||
showNotesBar: state.showMobileNotesBar,
|
|
||||||
};
|
};
|
||||||
})(NoteScreenComponent);
|
})(NoteScreenComponent);
|
||||||
|
|
||||||
|
@ -5,12 +5,13 @@ const { connect } = require('react-redux');
|
|||||||
const { ScreenHeader } = require('../ScreenHeader');
|
const { ScreenHeader } = require('../ScreenHeader');
|
||||||
const Icon = require('react-native-vector-icons/Ionicons').default;
|
const Icon = require('react-native-vector-icons/Ionicons').default;
|
||||||
const { _ } = require('@joplin/lib/locale');
|
const { _ } = require('@joplin/lib/locale');
|
||||||
|
const Note = require('@joplin/lib/models/Note').default;
|
||||||
const { NoteItem } = require('../note-item.js');
|
const { NoteItem } = require('../note-item.js');
|
||||||
const { BaseScreenComponent } = require('../base-screen.js');
|
const { BaseScreenComponent } = require('../base-screen.js');
|
||||||
const { themeStyle } = require('../global-style.js');
|
const { themeStyle } = require('../global-style.js');
|
||||||
const DialogBox = require('react-native-dialogbox').default;
|
const DialogBox = require('react-native-dialogbox').default;
|
||||||
|
const SearchEngineUtils = require('@joplin/lib/services/searchengine/SearchEngineUtils').default;
|
||||||
const SearchEngine = require('@joplin/lib/services/searchengine/SearchEngine').default;
|
const SearchEngine = require('@joplin/lib/services/searchengine/SearchEngine').default;
|
||||||
import searchNotes from '../searchNotes';
|
|
||||||
|
|
||||||
Icon.loadFont();
|
Icon.loadFont();
|
||||||
|
|
||||||
@ -100,7 +101,25 @@ class SearchScreenComponent extends BaseScreenComponent {
|
|||||||
|
|
||||||
query = query === null ? this.state.query.trim : query.trim();
|
query = query === null ? this.state.query.trim : query.trim();
|
||||||
|
|
||||||
const notes = await searchNotes(query, this.props.settings['db.ftsEnabled'], this.props.dispatch);
|
let notes = [];
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
if (this.props.settings['db.ftsEnabled']) {
|
||||||
|
notes = await SearchEngineUtils.notesForQuery(query, true);
|
||||||
|
} else {
|
||||||
|
const p = query.split(' ');
|
||||||
|
const temp = [];
|
||||||
|
for (let i = 0; i < p.length; i++) {
|
||||||
|
const t = p[i].trim();
|
||||||
|
if (!t) continue;
|
||||||
|
temp.push(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
notes = await Note.previews(null, {
|
||||||
|
anywherePattern: `*${temp.join('*')}*`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.isMounted_) return;
|
if (!this.isMounted_) return;
|
||||||
|
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
import SearchEngineUtils from '@joplin/lib/services/searchengine/SearchEngineUtils';
|
|
||||||
import SearchEngine from '@joplin/lib/services/searchengine/SearchEngine';
|
|
||||||
import Note from '@joplin/lib/models/Note';
|
|
||||||
import { NoteEntity } from '@joplin/lib/services/database/types';
|
|
||||||
|
|
||||||
// Returns notes from a search query and sets highlighted words
|
|
||||||
// Be sure to use 'await' keyword or the function might not work properly
|
|
||||||
// Eg. await HandleNoteQuery();
|
|
||||||
|
|
||||||
const searchNotes = async (query: string, dbFtsEnabled: boolean, dispatch: (action: Object)=> void): Promise<NoteEntity[]> => {
|
|
||||||
let notes = [];
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
if (dbFtsEnabled) {
|
|
||||||
notes = await SearchEngineUtils.notesForQuery(query, true);
|
|
||||||
} else {
|
|
||||||
const p = query.split(' ');
|
|
||||||
const temp = [];
|
|
||||||
for (let i = 0; i < p.length; i++) {
|
|
||||||
const t = p[i].trim();
|
|
||||||
if (!t) continue;
|
|
||||||
temp.push(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
notes = await Note.previews(null, {
|
|
||||||
anywherePattern: `*${temp.join('*')}*`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const parsedQuery = await SearchEngine.instance().parseQuery(query);
|
|
||||||
const highlightedWords = SearchEngine.instance().allParsedQueryTerms(parsedQuery);
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: 'SET_HIGHLIGHTED',
|
|
||||||
words: highlightedWords,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return notes;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default searchNotes;
|
|
@ -1,12 +0,0 @@
|
|||||||
import { StyleSheet } from 'react-native';
|
|
||||||
import { Style } from './global-style';
|
|
||||||
import { themeStyle } from './global-style';
|
|
||||||
|
|
||||||
const useStyles = (stylingFunction: (theme: Style)=> Style, themeId?: number) => {
|
|
||||||
const theme = themeStyle(themeId);
|
|
||||||
const styles = stylingFunction(theme);
|
|
||||||
|
|
||||||
return StyleSheet.create(styles);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useStyles;
|
|
@ -229,7 +229,7 @@ PODS:
|
|||||||
- React
|
- React
|
||||||
- react-native-get-random-values (1.7.1):
|
- react-native-get-random-values (1.7.1):
|
||||||
- React-Core
|
- React-Core
|
||||||
- react-native-image-picker (2.3.4):
|
- react-native-image-picker (4.10.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
- react-native-image-resizer (1.4.5):
|
- react-native-image-resizer (1.4.5):
|
||||||
- React-Core
|
- React-Core
|
||||||
@ -533,7 +533,7 @@ SPEC CHECKSUMS:
|
|||||||
react-native-document-picker: 20f652c2402d3ddc81f396d8167c3bd978add4a2
|
react-native-document-picker: 20f652c2402d3ddc81f396d8167c3bd978add4a2
|
||||||
react-native-geolocation: c956aeb136625c23e0dce0467664af2c437888c9
|
react-native-geolocation: c956aeb136625c23e0dce0467664af2c437888c9
|
||||||
react-native-get-random-values: 2c4ff6b44cb71291dabe9a8ae87d3877dcf387da
|
react-native-get-random-values: 2c4ff6b44cb71291dabe9a8ae87d3877dcf387da
|
||||||
react-native-image-picker: c6d75c4ab2cf46f9289f341242b219cb3c1180d3
|
react-native-image-picker: 4bc9ed38c8be255b515d8c88babbaf74973f91a8
|
||||||
react-native-image-resizer: d9fb629a867335bdc13230ac2a58702bb8c8828f
|
react-native-image-resizer: d9fb629a867335bdc13230ac2a58702bb8c8828f
|
||||||
react-native-netinfo: 3d3769f0d65de15c83a9bf1346f8be71de5a24bf
|
react-native-netinfo: 3d3769f0d65de15c83a9bf1346f8be71de5a24bf
|
||||||
react-native-rsa-native: 1f6bba06dd02f0e652a66a384c75c270f7a0062f
|
react-native-rsa-native: 1f6bba06dd02f0e652a66a384c75c270f7a0062f
|
||||||
|
@ -15,9 +15,5 @@ module.exports = {
|
|||||||
|
|
||||||
testPathIgnorePatterns: ['<rootDir>/node_modules/'],
|
testPathIgnorePatterns: ['<rootDir>/node_modules/'],
|
||||||
|
|
||||||
'transformIgnorePatterns': [
|
|
||||||
'node_modules/(?!@codemirror)/',
|
|
||||||
],
|
|
||||||
|
|
||||||
slowTestThreshold: 40,
|
slowTestThreshold: 40,
|
||||||
};
|
};
|
||||||
|
@ -27,14 +27,11 @@
|
|||||||
"@react-native-community/netinfo": "^6.0.0",
|
"@react-native-community/netinfo": "^6.0.0",
|
||||||
"@react-native-community/push-notification-ios": "^1.6.0",
|
"@react-native-community/push-notification-ios": "^1.6.0",
|
||||||
"@react-native-community/slider": "^3.0.3",
|
"@react-native-community/slider": "^3.0.3",
|
||||||
"@types/react-test-renderer": "^18.0.0",
|
|
||||||
"assert-browserify": "^2.0.0",
|
"assert-browserify": "^2.0.0",
|
||||||
"buffer": "^5.0.8",
|
"buffer": "^5.0.8",
|
||||||
"constants-browserify": "^1.0.0",
|
"constants-browserify": "^1.0.0",
|
||||||
"crypto-browserify": "^3.12.0",
|
"crypto-browserify": "^3.12.0",
|
||||||
"events": "^3.2.0",
|
"events": "^3.2.0",
|
||||||
"jest": "^28.1.3",
|
|
||||||
"jest-environment-jsdom": "^28.1.3",
|
|
||||||
"joplin-rn-alarm-notification": "^1.0.5",
|
"joplin-rn-alarm-notification": "^1.0.5",
|
||||||
"jsc-android": "241213.1.0",
|
"jsc-android": "241213.1.0",
|
||||||
"md5": "^2.2.1",
|
"md5": "^2.2.1",
|
||||||
@ -92,21 +89,20 @@
|
|||||||
"@codemirror/view": "^6.0.0",
|
"@codemirror/view": "^6.0.0",
|
||||||
"@joplin/tools": "~2.9",
|
"@joplin/tools": "~2.9",
|
||||||
"@lezer/highlight": "^1.0.0",
|
"@lezer/highlight": "^1.0.0",
|
||||||
"@testing-library/react-native": "^11.0.0",
|
|
||||||
"@types/fs-extra": "^9.0.13",
|
"@types/fs-extra": "^9.0.13",
|
||||||
"@types/jest": "^28.1.3",
|
"@types/jest": "^28.1.3",
|
||||||
"@types/node": "^18.7.6",
|
|
||||||
"@types/react-native": "^0.64.4",
|
"@types/react-native": "^0.64.4",
|
||||||
"@types/react-redux": "^7.1.24",
|
"@types/react-redux": "^7.1.24",
|
||||||
"babel-plugin-module-resolver": "^4.1.0",
|
"babel-plugin-module-resolver": "^4.1.0",
|
||||||
"execa": "^4.0.0",
|
"execa": "^4.0.0",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
|
"jest": "^28.1.1",
|
||||||
|
"jest-environment-jsdom": "^28.1.3",
|
||||||
"jetifier": "^1.6.5",
|
"jetifier": "^1.6.5",
|
||||||
"jsdom": "^20.0.0",
|
"jsdom": "^20.0.0",
|
||||||
"metro-react-native-babel-preset": "^0.66.2",
|
"metro-react-native-babel-preset": "^0.66.2",
|
||||||
"nodemon": "^2.0.12",
|
"nodemon": "^2.0.12",
|
||||||
"react-test-renderer": "17.0.2",
|
|
||||||
"ts-jest": "^28.0.5",
|
"ts-jest": "^28.0.5",
|
||||||
"ts-loader": "^9.3.1",
|
"ts-loader": "^9.3.1",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
|
@ -64,7 +64,7 @@ const { SearchScreen } = require('./components/screens/search.js');
|
|||||||
const { OneDriveLoginScreen } = require('./components/screens/onedrive-login.js');
|
const { OneDriveLoginScreen } = require('./components/screens/onedrive-login.js');
|
||||||
import EncryptionConfigScreen from './components/screens/encryption-config';
|
import EncryptionConfigScreen from './components/screens/encryption-config';
|
||||||
const { DropboxLoginScreen } = require('./components/screens/dropbox-login.js');
|
const { DropboxLoginScreen } = require('./components/screens/dropbox-login.js');
|
||||||
import { MenuProvider } from 'react-native-popup-menu';
|
const { MenuContext } = require('react-native-popup-menu');
|
||||||
import SideMenu from './components/SideMenu';
|
import SideMenu from './components/SideMenu';
|
||||||
const { SideMenuContent } = require('./components/side-menu-content.js');
|
const { SideMenuContent } = require('./components/side-menu-content.js');
|
||||||
const { SideMenuContentNote } = require('./components/side-menu-content-note.js');
|
const { SideMenuContentNote } = require('./components/side-menu-content-note.js');
|
||||||
@ -75,7 +75,7 @@ const { FileApiDriverLocal } = require('@joplin/lib/file-api-driver-local');
|
|||||||
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
|
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
|
||||||
import SearchEngine from '@joplin/lib/services/searchengine/SearchEngine';
|
import SearchEngine from '@joplin/lib/services/searchengine/SearchEngine';
|
||||||
const WelcomeUtils = require('@joplin/lib/WelcomeUtils');
|
const WelcomeUtils = require('@joplin/lib/WelcomeUtils');
|
||||||
import { themeStyle } from './components/global-style';
|
const { themeStyle } = require('./components/global-style.js');
|
||||||
import SyncTargetRegistry from '@joplin/lib/SyncTargetRegistry';
|
import SyncTargetRegistry from '@joplin/lib/SyncTargetRegistry';
|
||||||
const SyncTargetFilesystem = require('@joplin/lib/SyncTargetFilesystem.js');
|
const SyncTargetFilesystem = require('@joplin/lib/SyncTargetFilesystem.js');
|
||||||
const SyncTargetNextcloud = require('@joplin/lib/SyncTargetNextcloud.js');
|
const SyncTargetNextcloud = require('@joplin/lib/SyncTargetNextcloud.js');
|
||||||
@ -378,17 +378,6 @@ const appReducer = (state = appDefaultState, action: any) => {
|
|||||||
newState.isOnMobileData = action.isOnMobileData;
|
newState.isOnMobileData = action.isOnMobileData;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'NOTES_BAR_OPEN':
|
|
||||||
|
|
||||||
newState = Object.assign({}, state);
|
|
||||||
newState.showMobileNotesBar = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'NOTES_BAR_CLOSE':
|
|
||||||
|
|
||||||
newState = Object.assign({}, state);
|
|
||||||
newState.showMobileNotesBar = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
error.message = `In reducer: ${error.message} Action: ${JSON.stringify(action)}`;
|
error.message = `In reducer: ${error.message} Action: ${JSON.stringify(action)}`;
|
||||||
@ -930,7 +919,7 @@ class AppComponent extends React.Component {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<StatusBar barStyle={statusBarStyle} />
|
<StatusBar barStyle={statusBarStyle} />
|
||||||
<MenuProvider style={{ flex: 1 }}>
|
<MenuContext style={{ flex: 1 }}>
|
||||||
<SafeAreaView style={{ flex: 0, backgroundColor: theme.backgroundColor2 }}/>
|
<SafeAreaView style={{ flex: 0, backgroundColor: theme.backgroundColor2 }}/>
|
||||||
<SafeAreaView style={{ flex: 1 }}>
|
<SafeAreaView style={{ flex: 1 }}>
|
||||||
<View style={{ flex: 1, backgroundColor: theme.backgroundColor }}>
|
<View style={{ flex: 1, backgroundColor: theme.backgroundColor }}>
|
||||||
@ -939,7 +928,7 @@ class AppComponent extends React.Component {
|
|||||||
<DropdownAlert ref={(ref: any) => this.dropdownAlert_ = ref} tapToCloseEnabled={true} />
|
<DropdownAlert ref={(ref: any) => this.dropdownAlert_ = ref} tapToCloseEnabled={true} />
|
||||||
<Animated.View pointerEvents='none' style={{ position: 'absolute', backgroundColor: 'black', opacity: this.state.sideMenuContentOpacity, width: '100%', height: '120%' }}/>
|
<Animated.View pointerEvents='none' style={{ position: 'absolute', backgroundColor: 'black', opacity: this.state.sideMenuContentOpacity, width: '100%', height: '120%' }}/>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
</MenuProvider>
|
</MenuContext>
|
||||||
</SideMenu>
|
</SideMenu>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
"tools/*.ts",
|
"tools/*.ts",
|
||||||
],
|
],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"types": ["jest", "node", "react-test-renderer"],
|
"types": ["jest", "node"]
|
||||||
"allowSyntheticDefaultImports": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,6 @@ export interface State {
|
|||||||
hasEncryptedItems: boolean;
|
hasEncryptedItems: boolean;
|
||||||
needApiAuth: boolean;
|
needApiAuth: boolean;
|
||||||
profileConfig: ProfileConfig;
|
profileConfig: ProfileConfig;
|
||||||
showMobileNotesBar: boolean;
|
|
||||||
|
|
||||||
// Extra reducer keys go here:
|
// Extra reducer keys go here:
|
||||||
pluginService: PluginServiceState;
|
pluginService: PluginServiceState;
|
||||||
@ -157,7 +156,6 @@ export const defaultState: State = {
|
|||||||
},
|
},
|
||||||
backwardHistoryNotes: [],
|
backwardHistoryNotes: [],
|
||||||
forwardHistoryNotes: [],
|
forwardHistoryNotes: [],
|
||||||
showMobileNotesBar: false,
|
|
||||||
// pluginsLegacy is the original plugin system, which eventually was used only for GotoAnything.
|
// pluginsLegacy is the original plugin system, which eventually was used only for GotoAnything.
|
||||||
// GotoAnything should be refactored to part of core and when it's done the pluginsLegacy key can
|
// GotoAnything should be refactored to part of core and when it's done the pluginsLegacy key can
|
||||||
// be removed. It was originally named "plugins", then renamed "pluginsLegacy" so as not to conflict
|
// be removed. It was originally named "plugins", then renamed "pluginsLegacy" so as not to conflict
|
||||||
|
@ -23,7 +23,7 @@ const themes: any = {
|
|||||||
[Setting.THEME_OLED_DARK]: theme_oledDark,
|
[Setting.THEME_OLED_DARK]: theme_oledDark,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function themeById(themeId: number) {
|
export function themeById(themeId: string) {
|
||||||
if (!themes[themeId]) throw new Error(`Invalid theme ID: ${themeId}`);
|
if (!themes[themeId]) throw new Error(`Invalid theme ID: ${themeId}`);
|
||||||
const output = Object.assign({}, themes[themeId]);
|
const output = Object.assign({}, themes[themeId]);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user