Icons and styling
BIN
Icon144.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
Icon48.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Icon512.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
Icon72.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
Icon96.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
@ -90,8 +90,8 @@ android {
|
||||
applicationId "net.cozic.joplin"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 22
|
||||
versionCode 24
|
||||
versionName "0.9.11"
|
||||
versionCode 26
|
||||
versionName "0.9.13"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 5.5 KiB |
@ -102,7 +102,7 @@ class ActionButtonComponent extends React.Component {
|
||||
}
|
||||
|
||||
let mainButton = this.props.mainButton ? this.props.mainButton : {};
|
||||
let mainIcon = mainButton.icon ? <Icon name={mainButton.icon} style={styles.actionButtonIcon} /> : <Text style={{fontSize: 20, color:"#ffffff"}}>+</Text>;
|
||||
let mainIcon = mainButton.icon ? <Icon name={mainButton.icon} style={styles.actionButtonIcon} /> : <Icon name="md-add" style={styles.actionButtonIcon} />
|
||||
|
||||
if (this.props.multiStates) {
|
||||
if (!this.props.buttons || !this.props.buttons.length) throw new Error('Multi-state button requires at least one state');
|
||||
|
@ -1,10 +1,11 @@
|
||||
import React, { Component } from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { globalStyle } from 'lib/components/global-style.js';
|
||||
|
||||
const styles_ = StyleSheet.create({
|
||||
screen: {
|
||||
flex: 1,
|
||||
backgroundColor: "#E9E9E9",
|
||||
backgroundColor: globalStyle.backgroundColor,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -2,13 +2,13 @@ import React, { Component } from 'react';
|
||||
import { StyleSheet, TouchableHighlight } from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/Ionicons';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
const styles = {
|
||||
checkboxIcon: {
|
||||
fontSize: 20,
|
||||
height: 22,
|
||||
marginRight: 10,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
class Checkbox extends Component {
|
||||
|
||||
@ -42,9 +42,19 @@ class Checkbox extends Component {
|
||||
style.justifyContent = 'center';
|
||||
style.alignItems = 'center';
|
||||
|
||||
const checkboxIconStyle = Object.assign({}, styles.checkboxIcon);
|
||||
if (style.color) checkboxIconStyle.color = style.color;
|
||||
|
||||
const thStyle = {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
};
|
||||
|
||||
if (style.display) thStyle.display = style.display;
|
||||
|
||||
return (
|
||||
<TouchableHighlight onPress={() => this.onPress()} style={style}>
|
||||
<Icon name={iconName} style={styles.checkboxIcon}/>
|
||||
<TouchableHighlight onPress={() => this.onPress()} style={thStyle}>
|
||||
<Icon name={iconName} style={checkboxIconStyle}/>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
|
17
ReactNativeClient/lib/components/global-style.js
Normal file
@ -0,0 +1,17 @@
|
||||
const globalStyle = {
|
||||
margin: 15, // No text and no interactive component should be within this margin
|
||||
backgroundColor: "#ffffff",
|
||||
color: "#555555",
|
||||
fontSize: 10,
|
||||
dividerColor: "#dddddd",
|
||||
|
||||
// For WebView - must correspond to the properties above
|
||||
htmlFontSize: '14px',
|
||||
htmlColor: 'black', // Note: CSS in WebView component only seem to work if the colour is written in full letters (so no hexadecimal)
|
||||
};
|
||||
|
||||
globalStyle.marginRight = globalStyle.margin;
|
||||
globalStyle.marginLeft = globalStyle.margin;
|
||||
globalStyle.htmlMarginLeft = ((globalStyle.marginLeft / 10) * 0.6).toFixed(2) + 'em';
|
||||
|
||||
export { globalStyle }
|
@ -1,12 +1,25 @@
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux'
|
||||
import { ListView, Text, TouchableHighlight, Switch, View } from 'react-native';
|
||||
import { ListView, Text, TouchableHighlight, Switch, View, StyleSheet } from 'react-native';
|
||||
import { Log } from 'lib/log.js';
|
||||
import { _ } from 'lib/locale.js';
|
||||
import { Checkbox } from 'lib/components/checkbox.js';
|
||||
import { reg } from 'lib/registry.js';
|
||||
import { Note } from 'lib/models/note.js';
|
||||
import { time } from 'lib/time-utils.js';
|
||||
import { globalStyle } from 'lib/components/global-style.js';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
listItem: {
|
||||
flexDirection: 'row',
|
||||
height: 40,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: globalStyle.dividerColor,
|
||||
alignItems: 'center',
|
||||
paddingLeft: globalStyle.marginLeft,
|
||||
backgroundColor: globalStyle.backgroundColor,
|
||||
},
|
||||
});
|
||||
|
||||
class ItemListComponent extends Component {
|
||||
|
||||
@ -53,15 +66,16 @@ class ItemListComponent extends Component {
|
||||
this.listView_itemLongPress(item.id);
|
||||
}
|
||||
|
||||
const checkboxStyle = {};
|
||||
const listItemStyle = { color: globalStyle.color };
|
||||
const checkboxStyle = Object.assign({}, listItemStyle);
|
||||
if (!Number(item.is_todo)) checkboxStyle.display = 'none';
|
||||
|
||||
const checkboxChecked = !!Number(item.todo_completed);
|
||||
|
||||
return (
|
||||
<TouchableHighlight onPress={onPress} onLongPress={onLongPress}>
|
||||
<View style={{flexDirection: 'row', paddingLeft: 10, paddingTop:5, paddingBottom:5 }}>
|
||||
<Checkbox style={checkboxStyle} checked={checkboxChecked} onChange={(checked) => { this.todoCheckbox_change(item.id, checked) }}/><Text>{item.title}</Text>
|
||||
<TouchableHighlight onPress={onPress} onLongPress={onLongPress} underlayColor="#0066FF">
|
||||
<View style={ styles.listItem }>
|
||||
<Checkbox style={checkboxStyle} checked={checkboxChecked} onChange={(checked) => { this.todoCheckbox_change(item.id, checked) }}/><Text style={listItemStyle}>{item.title}</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
|
@ -8,13 +8,30 @@ import { Setting } from 'lib/models/setting.js';
|
||||
import { FileApi } from 'lib/file-api.js';
|
||||
import { FileApiDriverOneDrive } from 'lib/file-api-driver-onedrive.js';
|
||||
import { reg } from 'lib/registry.js'
|
||||
import { globalStyle } from 'lib/components/global-style.js';
|
||||
|
||||
let styleObject = {
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
paddingLeft: globalStyle.marginLeft,
|
||||
paddingTop: 10,
|
||||
paddingBottom: 10,
|
||||
paddingRight: 0,
|
||||
backgroundColor: globalStyle.backgroundColor,
|
||||
alignItems: 'center',
|
||||
shadowColor: '#000000',
|
||||
elevation: 5,
|
||||
},
|
||||
folderPicker: {
|
||||
height: 30,
|
||||
flex:1,
|
||||
color: globalStyle.color,
|
||||
backgroundColor: globalStyle.backgroundColor,
|
||||
},
|
||||
divider: {
|
||||
marginVertical: 5,
|
||||
marginHorizontal: 2,
|
||||
borderBottomWidth: 1,
|
||||
borderColor: '#ccc'
|
||||
borderColor: globalStyle.dividerColor,
|
||||
backgroundColor: "#0000ff"
|
||||
},
|
||||
sideMenuButton: {
|
||||
flex: 1,
|
||||
@ -55,6 +72,31 @@ let styleObject = {
|
||||
fontWeight: 'bold',
|
||||
flex: 1,
|
||||
},
|
||||
contextMenuTrigger: {
|
||||
fontSize: 25,
|
||||
paddingRight: globalStyle.marginRight,
|
||||
color: globalStyle.color,
|
||||
},
|
||||
contextMenu: {
|
||||
backgroundColor: globalStyle.backgroundColor,
|
||||
},
|
||||
contextMenuItem: {
|
||||
backgroundColor: globalStyle.backgroundColor,
|
||||
},
|
||||
contextMenuItemText: {
|
||||
flex: 1,
|
||||
height: 40,
|
||||
textAlignVertical: 'center',
|
||||
paddingLeft: globalStyle.marginLeft,
|
||||
paddingRight: globalStyle.marginRight,
|
||||
color: globalStyle.color,
|
||||
backgroundColor: globalStyle.backgroundColor,
|
||||
},
|
||||
titleText: {
|
||||
flex: 1,
|
||||
marginLeft: 10,
|
||||
color: globalStyle.color,
|
||||
}
|
||||
};
|
||||
|
||||
styleObject.backButtonDisabled = Object.assign({}, styleObject.backButton, { backgroundColor: "#c6c6c6" });
|
||||
@ -131,8 +173,8 @@ class ScreenHeaderComponent extends Component {
|
||||
for (let i = 0; i < this.props.menuOptions.length; i++) {
|
||||
let o = this.props.menuOptions[i];
|
||||
menuOptionComponents.push(
|
||||
<MenuOption value={o.onPress} key={'menuOption_' + key++}>
|
||||
<Text>{o.title}</Text>
|
||||
<MenuOption value={o.onPress} key={'menuOption_' + key++} style={styles.contextMenuItem}>
|
||||
<Text style={styles.contextMenuItemText}>{o.title}</Text>
|
||||
</MenuOption>);
|
||||
}
|
||||
|
||||
@ -141,13 +183,13 @@ class ScreenHeaderComponent extends Component {
|
||||
}
|
||||
|
||||
menuOptionComponents.push(
|
||||
<MenuOption value={() => this.log_press()} key={'menuOption_' + key++}>
|
||||
<Text>{_('Log')}</Text>
|
||||
<MenuOption value={() => this.log_press()} key={'menuOption_' + key++} style={styles.contextMenuItem}>
|
||||
<Text style={styles.contextMenuItemText}>{_('Log')}</Text>
|
||||
</MenuOption>);
|
||||
|
||||
menuOptionComponents.push(
|
||||
<MenuOption value={() => this.status_press()} key={'menuOption_' + key++}>
|
||||
<Text>{_('Status')}</Text>
|
||||
<MenuOption value={() => this.status_press()} key={'menuOption_' + key++} style={styles.contextMenuItem}>
|
||||
<Text style={styles.contextMenuItemText}>{_('Status')}</Text>
|
||||
</MenuOption>);
|
||||
|
||||
const createTitleComponent = () => {
|
||||
@ -159,27 +201,27 @@ class ScreenHeaderComponent extends Component {
|
||||
items.push(<Picker.Item label={item.label} value={item.value} key={item.value}/>);
|
||||
}
|
||||
return (
|
||||
<Picker style={{height: 30, flex:1}} selectedValue={p.selectedValue} onValueChange={(itemValue, itemIndex) => { if (p.onValueChange) p.onValueChange(itemValue, itemIndex); }}>
|
||||
<Picker style={styles.folderPicker} selectedValue={p.selectedValue} onValueChange={(itemValue, itemIndex) => { if (p.onValueChange) p.onValueChange(itemValue, itemIndex); }}>
|
||||
{ items }
|
||||
</Picker>
|
||||
);
|
||||
} else {
|
||||
let title = 'title' in this.props && this.props.title !== null ? this.props.title : _(this.props.navState.routeName);
|
||||
return <Text style={{ flex:1, marginLeft: 10 }}>{title}</Text>
|
||||
return <Text style={styles.titleText}>{title}</Text>
|
||||
}
|
||||
}
|
||||
|
||||
const titleComp = createTitleComponent();
|
||||
|
||||
return (
|
||||
<View style={{ flexDirection: 'row', paddingLeft: 10, paddingTop: 10, paddingBottom: 10, paddingRight: 0, backgroundColor: '#ffffff', alignItems: 'center' }} >
|
||||
<View style={styles.container} >
|
||||
{ sideMenuButton(styles, () => this.sideMenuButton_press()) }
|
||||
{ backButton(styles, () => this.backButton_press(), !this.props.historyCanGoBack) }
|
||||
{ saveButton(styles, () => { if (this.props.onSaveButtonPress) this.props.onSaveButtonPress() }, this.props.saveButtonDisabled === true, this.props.showSaveButton === true) }
|
||||
{ titleComp }
|
||||
<Menu onSelect={(value) => this.menu_select(value)}>
|
||||
<Menu onSelect={(value) => this.menu_select(value)} style={styles.contextMenu}>
|
||||
<MenuTrigger>
|
||||
<Text style={{ fontSize: 25 }}> ⋮ </Text>
|
||||
<Text style={styles.contextMenuTrigger}> ⋮</Text>
|
||||
</MenuTrigger>
|
||||
<MenuOptions>
|
||||
{ menuOptionComponents }
|
||||
|
@ -16,11 +16,22 @@ import { reg } from 'lib/registry.js';
|
||||
import { BaseScreenComponent } from 'lib/components/base-screen.js';
|
||||
import { dialogs } from 'lib/dialogs.js';
|
||||
import { NotesScreenUtils } from 'lib/components/screens/notes-utils.js'
|
||||
import { globalStyle } from 'lib/components/global-style.js';
|
||||
import DialogBox from 'react-native-dialogbox';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
webView: {
|
||||
fontSize: 10,
|
||||
titleTextInput: {
|
||||
flex: 1,
|
||||
color: globalStyle.color,
|
||||
backgroundColor: globalStyle.backgroundColor,
|
||||
},
|
||||
bodyTextInput: {
|
||||
flex: 1,
|
||||
marginLeft: globalStyle.marginLeft,
|
||||
marginRight: globalStyle.marginRight,
|
||||
textAlignVertical: 'top',
|
||||
color: globalStyle.color,
|
||||
backgroundColor: globalStyle.backgroundColor,
|
||||
},
|
||||
});
|
||||
|
||||
@ -259,7 +270,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
return body;
|
||||
}
|
||||
|
||||
function markdownToHtml(body) {
|
||||
function markdownToHtml(body, style) {
|
||||
// https://necolas.github.io/normalize.css/
|
||||
const normalizeCss = `
|
||||
html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
|
||||
@ -267,10 +278,12 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}
|
||||
b,strong{font-weight:bolder}small{font-size:80%}img{border-style:none}
|
||||
`;
|
||||
|
||||
const css = `
|
||||
body {
|
||||
font-size: 16px;
|
||||
margin: 1em;
|
||||
font-size: ` + style.htmlFontSize + `;
|
||||
margin: ` + style.htmlMarginLeft + `;
|
||||
color: ` + style.htmlColor + `;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.2em;
|
||||
@ -291,7 +304,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
position: relative;
|
||||
top: 0.1em;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
color: ` + style.htmlColor + `;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
@ -327,9 +340,8 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
bodyComponent = (
|
||||
<View style={{flex:1}}>
|
||||
<WebView
|
||||
source={{ html: markdownToHtml(note.body) }}
|
||||
source={{ html: markdownToHtml(note.body, globalStyle) }}
|
||||
onMessage={(event) => {
|
||||
// 'checkboxclick_NOTICK_0'
|
||||
let msg = event.nativeEvent.data;
|
||||
if (msg.indexOf('checkboxclick_') === 0) {
|
||||
msg = msg.split('_');
|
||||
@ -347,7 +359,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
<TextInput
|
||||
autoCapitalize="sentences"
|
||||
autoFocus={true}
|
||||
style={{flex: 1, textAlignVertical: 'top', fontFamily: 'monospace'}}
|
||||
style={styles.bodyTextInput}
|
||||
multiline={true}
|
||||
value={note.body}
|
||||
onChangeText={(text) => this.body_changeText(text)}
|
||||
@ -387,6 +399,15 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
|
||||
if (showSaveButton) this.saveButtonHasBeenShown_ = true;
|
||||
|
||||
let titleContainerStyle = {
|
||||
flexDirection: 'row',
|
||||
paddingLeft: globalStyle.marginLeft,
|
||||
height: 40,
|
||||
borderBottomColor: globalStyle.dividerColor,
|
||||
borderBottomWidth: 1,
|
||||
};
|
||||
if (!isTodo) titleContainerStyle.paddingLeft -= 3; // Because the TextInput already includes a padding
|
||||
|
||||
return (
|
||||
<View style={this.styles().screen}>
|
||||
<ScreenHeader
|
||||
@ -423,8 +444,8 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
saveButtonDisabled={saveButtonDisabled}
|
||||
onSaveButtonPress={() => this.saveNoteButton_press()}
|
||||
/>
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
{ isTodo && <Checkbox checked={!!Number(note.todo_completed)} onChange={(checked) => { this.todoCheckbox_change(checked) }} /> }<TextInput autoCapitalize="sentences" style={{flex:1}} value={note.title} onChangeText={(text) => this.title_changeText(text)} />
|
||||
<View style={titleContainerStyle}>
|
||||
{ isTodo && <Checkbox checked={!!Number(note.todo_completed)} onChange={(checked) => { this.todoCheckbox_change(checked) }} /> }<TextInput underlineColorAndroid="#ffffff00" autoCapitalize="sentences" style={styles.titleTextInput} value={note.title} onChangeText={(text) => this.title_changeText(text)} />
|
||||
</View>
|
||||
{ bodyComponent }
|
||||
{ actionButtonComp }
|
||||
|
@ -7,6 +7,7 @@ import { NotesScreenUtils } from 'lib/components/screens/notes-utils.js'
|
||||
import { Synchronizer } from 'lib/synchronizer.js';
|
||||
import { reg } from 'lib/registry.js';
|
||||
import { _ } from 'lib/locale.js';
|
||||
import { globalStyle } from 'lib/components/global-style.js';
|
||||
|
||||
const React = require('react');
|
||||
const {
|
||||
@ -21,7 +22,7 @@ const { Component } = React;
|
||||
const styles = StyleSheet.create({
|
||||
menu: {
|
||||
flex: 1,
|
||||
backgroundColor: 'white',
|
||||
backgroundColor: globalStyle.backgroundColor,
|
||||
padding: 20,
|
||||
},
|
||||
name: {
|
||||
@ -37,15 +38,15 @@ const styles = StyleSheet.create({
|
||||
folderButton: {
|
||||
flex: 1,
|
||||
backgroundColor: "#0482E3",
|
||||
paddingLeft: 20,
|
||||
paddingRight: 20,
|
||||
paddingTop: 14,
|
||||
paddingBottom: 14,
|
||||
height: 36,
|
||||
marginBottom: 5,
|
||||
},
|
||||
folderButtonText: {
|
||||
color: "#ffffff",
|
||||
fontWeight: 'bold',
|
||||
textAlign: 'center',
|
||||
textAlignVertical: 'center',
|
||||
flex: 1,
|
||||
},
|
||||
button: {
|
||||
flex: 1,
|
||||
|
@ -1,7 +0,0 @@
|
||||
const styles = StyleSheet.create({
|
||||
webView: {
|
||||
fontSize: 10,
|
||||
},
|
||||
});
|
||||
|
||||
export { styles }
|