diff --git a/package.json b/package.json
index 6c3f9586..abb712e6 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
"bugsnag-react-native": "^2.3.2",
"immutable": "^3.8.1",
"lodash": "^4.17.4",
+ "moment": "^2.18.1",
"react": "16.0.0-beta.5",
"react-native": "^0.48.4",
"react-native-keychain": "^1.2.1",
diff --git a/src/Styles.js b/src/Styles.js
index 2fa1d6de..e64b15f0 100644
--- a/src/Styles.js
+++ b/src/Styles.js
@@ -250,7 +250,7 @@ export default class GlobalStyles {
flexContainer: {
flex: 1,
- flexDirection: 'row',
+ flexDirection: 'column',
},
uiText: {
@@ -269,7 +269,6 @@ export default class GlobalStyles {
},
sectionHeader: {
- color: constants.mainDimColor,
fontSize: constants.mainTextFontSize - 4,
paddingLeft: constants.paddingLeft,
paddingBottom: 10,
@@ -278,7 +277,6 @@ export default class GlobalStyles {
},
sectionHeaderAndroid: {
- color: constants.mainDimColor,
fontSize: constants.mainTextFontSize - 2,
},
@@ -320,27 +318,27 @@ export default class GlobalStyles {
sectionedAccessoryTableCellLabel: {
fontSize: constants.mainTextFontSize,
color: constants.mainTextColor,
- paddingTop: 12,
+ // paddingTop: 12,
},
buttonCell: {
- paddingLeft: 0,
paddingTop: 0,
- minHeight: 45,
- flexGrow: 0,
+ paddingBottom: 0,
backgroundColor: constants.mainBackgroundColor,
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center'
},
buttonCellButton: {
textAlign: "center",
+ textAlignVertical: "center",
color: Platform.OS == "android" ? constants.mainTextColor : constants.mainTintColor,
fontSize: constants.mainTextFontSize,
- height: "100%",
- paddingTop: 13,
},
buttonCellButtonAndroid: {
- paddingTop: 11
+ // paddingTop: 11
},
buttonCellButtonLeft: {
diff --git a/src/app.js b/src/app.js
index d6a21422..f99cc2cb 100644
--- a/src/app.js
+++ b/src/app.js
@@ -7,7 +7,8 @@ import {
Platform,
StatusBar,
BackHandler,
- DeviceEventEmitter
+ DeviceEventEmitter,
+ NativeModules
} from 'react-native';
import {Navigation, ScreenVisibilityListener} from 'react-native-navigation';
@@ -18,7 +19,7 @@ import Auth from './lib/auth'
import GlobalStyles from "./Styles"
import Icons from "./Icons"
import OptionsState from "./OptionsState"
-
+var moment = require('moment/min/moment-with-locales.min.js');
import { Client } from 'bugsnag-react-native';
var _ = require('lodash');
@@ -52,16 +53,20 @@ export default class App {
this.readyObservers = [];
this.lockStatusObservers = [];
- this.optionsState = new OptionsState();
-
this._isAndroid = Platform.OS === "android";
+ // Configure Moment locale
+ moment.locale(this.getLocale());
+
+ // Initialize Options (sort by, filter, selected tags, etc)
+ this.optionsState = new OptionsState();
this.optionsState.addChangeObserver((options) => {
if(!this.loading) {
options.persist();
}
})
+ // Screen visibility listener
this.listener = new ScreenVisibilityListener({
willAppear: ({screen, startTime, endTime, commandType}) => {
// This handles authentication for the initial app launch. We wait for the Notes component to be ready
@@ -75,6 +80,7 @@ export default class App {
});
this.listener.register();
+ // Listen to sign out event
this.signoutObserver = Auth.getInstance().addEventObserver([Auth.DidSignOutEvent, Auth.WillSignInEvent], function(event){
if(event == Auth.DidSignOutEvent) {
this.optionsState.reset();
@@ -82,6 +88,14 @@ export default class App {
}.bind(this));
}
+ getLocale() {
+ if (Platform.OS === 'android') {
+ return NativeModules.I18nManager.localeIdentifier;
+ } else {
+ return NativeModules.SettingsManager.settings.AppleLocale.replace(/_/, '-');
+ }
+ }
+
handleAppStateChange = (nextAppState) => {
console.log("handleAppStateChange|App.js", nextAppState, "starting app?", this.isStartingApp);
@@ -376,3 +390,5 @@ export default class App {
this.startApp();
}
}
+
+export {moment}
diff --git a/src/components/ButtonCell.js b/src/components/ButtonCell.js
index 1a5848fb..d343a524 100644
--- a/src/components/ButtonCell.js
+++ b/src/components/ButtonCell.js
@@ -1,23 +1,24 @@
import React, { Component } from 'react';
-import {TouchableOpacity, Text} from 'react-native';
-
+import {TouchableHighlight, Text} from 'react-native';
+import SectionedTableCell from './SectionedTableCell'
import GlobalStyles from "../Styles"
-export default class ButtonCell extends Component {
+export default class ButtonCell extends SectionedTableCell {
rules() {
- var rules = [GlobalStyles.stylesForKey("buttonCellButton")];
+ var rules = super.rules().concat([GlobalStyles.stylesForKey("buttonCellButton")]);
if(this.props.leftAligned) { rules.push(GlobalStyles.styles().buttonCellButtonLeft) }
if(this.props.bold) { rules.push(GlobalStyles.styles().bold) }
if(this.props.disabled) { rules.push({color: "gray", opacity: 0.6}) }
+ if(this.props.maxHeight) { rules.push({maxHeight: this.props.maxHeight}) }
return rules;
}
render() {
return (
-
+
{this.props.title}
-
+
)
}
}
diff --git a/src/components/SectionedAccessoryTableCell.js b/src/components/SectionedAccessoryTableCell.js
index 6f8b3265..7f4eb9a6 100644
--- a/src/components/SectionedAccessoryTableCell.js
+++ b/src/components/SectionedAccessoryTableCell.js
@@ -48,7 +48,7 @@ export default class SectionedAccessoryTableCell extends SectionedTableCell {
if(Platform.OS == "android") {
iconSize -= 5;
- iconStyles.paddingTop = left ? 11 : 4;
+ iconStyles.paddingTop = left ? 12 : 4;
color = GlobalStyles.constants().mainDimColor;
}
@@ -65,8 +65,8 @@ export default class SectionedAccessoryTableCell extends SectionedTableCell {
var textStyles = [GlobalStyles.styles().sectionedAccessoryTableCellLabel];
if(this.props.leftAlignIcon) {
textStyles.push({
- position: "absolute",
- left: iconStyles.left + iconStyles.width + 12,
+ // position: "absolute",
+ left: iconStyles.left + iconStyles.width + 3,
top: 0
});
}
diff --git a/src/components/SectionedTableCell.js b/src/components/SectionedTableCell.js
index add6af06..a2e1b0a9 100644
--- a/src/components/SectionedTableCell.js
+++ b/src/components/SectionedTableCell.js
@@ -7,7 +7,6 @@ export default class SectionedTableCell extends Component {
rules() {
var rules = [GlobalStyles.styles().sectionedTableCell];
- if(this.props.buttonCell) { rules.push(GlobalStyles.styles().buttonCell); }
if(this.props.first) { rules.push(GlobalStyles.styles().sectionedTableCellFirst); }
if(this.props.textInputCell) {rules.push(GlobalStyles.styles().textInputCell); }
if(this.props.height) {rules.push({height: this.props.height})};
diff --git a/src/containers/ManageNote.js b/src/containers/ManageNote.js
index 47ecc8a0..21adaae0 100644
--- a/src/containers/ManageNote.js
+++ b/src/containers/ManageNote.js
@@ -31,28 +31,28 @@ export default class SortSection extends Component {
{this.onPress(pinAction.toLowerCase())}}
- first={true} text={pinAction} buttonCell={true}
+ first={true} text={pinAction}
leftAlignIcon={true}
/>
{this.onPress(archiveOption.toLowerCase())}}
- text={archiveOption} buttonCell={true}
+ text={archiveOption}
leftAlignIcon={true}
/>
{this.onPress("share")}}
- text={"Share"} buttonCell={true}
+ text={"Share"}
leftAlignIcon={true}
/>
{this.onPress("delete")}}
- text={"Delete"} buttonCell={true}
+ text={"Delete"}
leftAlignIcon={true}
/>
diff --git a/src/containers/account/AuthSection.js b/src/containers/account/AuthSection.js
index 47c6054a..97e63636 100644
--- a/src/containers/account/AuthSection.js
+++ b/src/containers/account/AuthSection.js
@@ -94,18 +94,12 @@ export default class AuthSection extends AbstractComponent {
}
-
- this.onSignInPress()} />
-
+ this.onSignInPress()} />
-
- this.onRegisterPress()} />
-
+ this.onRegisterPress()} />
{!this.state.showAdvanced &&
-
- this.showAdvanced()} />
-
+ this.showAdvanced()} />
}
diff --git a/src/containers/account/CompanySection.js b/src/containers/account/CompanySection.js
index d01bb368..77887ced 100644
--- a/src/containers/account/CompanySection.js
+++ b/src/containers/account/CompanySection.js
@@ -15,17 +15,11 @@ export default class CompanySection extends Component {
-
- this.props.onAction("feedback")} />
-
+ this.props.onAction("feedback")} />
-
- this.props.onAction("learn_more")} />
-
+ this.props.onAction("learn_more")} />
-
- this.props.onAction("privacy")} />
-
+ this.props.onAction("privacy")} />
);
diff --git a/src/containers/account/OptionsSection.js b/src/containers/account/OptionsSection.js
index c3efd726..32643c9d 100644
--- a/src/containers/account/OptionsSection.js
+++ b/src/containers/account/OptionsSection.js
@@ -16,14 +16,10 @@ export default class OptionsSection extends Component {
{this.props.signedIn &&
-
-
-
+
}
-
-
-
+
);
diff --git a/src/containers/account/PasscodeSection.js b/src/containers/account/PasscodeSection.js
index c04218b8..564118c4 100644
--- a/src/containers/account/PasscodeSection.js
+++ b/src/containers/account/PasscodeSection.js
@@ -71,13 +71,9 @@ export default class PasscodeSection extends Component {
-
-
-
+
-
-
-
+
{this.props.hasPasscode &&
diff --git a/src/containers/account/RegistrationConfirmSection.js b/src/containers/account/RegistrationConfirmSection.js
index 1d2a5130..7ca3bed6 100644
--- a/src/containers/account/RegistrationConfirmSection.js
+++ b/src/containers/account/RegistrationConfirmSection.js
@@ -49,15 +49,14 @@ export default class RegistrationConfirmSection extends Component {
/>
-
- this.onConfirmPress()} />
-
+ this.onConfirmPress()}
+ />
-
- this.onCancel()} />
-
+ this.onCancel()} />
diff --git a/src/containers/account/ThemesSection.js b/src/containers/account/ThemesSection.js
index 7af29fc5..51d7a2c1 100644
--- a/src/containers/account/ThemesSection.js
+++ b/src/containers/account/ThemesSection.js
@@ -24,7 +24,6 @@ export default class ThemesSection extends Component {
key={theme.uuid}
first={i == 0}
selected={() => {return theme.active}}
- buttonCell={true}
dimmed={theme.notAvailableOnMobile}
/>
)
@@ -34,7 +33,6 @@ export default class ThemesSection extends Component {
Linking.openURL("https://standardnotes.org/extensions")}
text={"More Themes"}
- buttonCell={true}
/>
}
diff --git a/src/models/api/item.js b/src/models/api/item.js
index b4181e08..47dd1fc5 100644
--- a/src/models/api/item.js
+++ b/src/models/api/item.js
@@ -1,4 +1,5 @@
import Crypto from "../../lib/crypto"
+import {moment} from "../../app"
var _ = require('lodash')
@@ -51,8 +52,8 @@ export default class Item {
_.merge(this, json);
if(this.created_at) {
- this.created_at = new Date(this.created_at);
- this.updated_at = new Date(this.updated_at);
+ this.created_at = moment(this.created_at);
+ this.updated_at = moment(this.updated_at);
} else {
this.created_at = new Date();
this.updated_at = new Date();
@@ -133,18 +134,21 @@ export default class Item {
return [];
}
- createdAt() {
- var date = this.created_at;
- var string = date.toLocaleDateString() + ", " + date.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
-
- return string;
+ createdAt(withTime) {
+ return this.dateToString(this.created_at, withTime);
}
updatedAt() {
- var date = this.updated_at;
- var string = date.toLocaleDateString() + ", " + date.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
+ return this.dateToString(this.updated_at, true);
+ }
- return string;
+ dateToString(date, withTime) {
+ if(withTime) {
+ return moment(date).format('lll')
+ } else {
+ return moment(date).format('l')
+ }
+ // return this.created_at.fromNow()
}
doNotEncrypt() {
diff --git a/src/screens/Authenticate.js b/src/screens/Authenticate.js
index bec35c19..d0c2a403 100644
--- a/src/screens/Authenticate.js
+++ b/src/screens/Authenticate.js
@@ -147,9 +147,7 @@ export default class Authenticate extends Abstract {
/>
-
- this.onUnlockPress()} />
-
+ this.onUnlockPress()} />
}
@@ -172,9 +170,7 @@ export default class Authenticate extends Abstract {
/>
-
- this.onSavePress()} />
-
+ this.onSavePress()} />
}
diff --git a/src/screens/Compose.js b/src/screens/Compose.js
index 5214151e..c66374b4 100644
--- a/src/screens/Compose.js
+++ b/src/screens/Compose.js
@@ -75,6 +75,10 @@ export default class Compose extends Abstract {
return;
}
+ if(!this.note.uuid) {
+ return;
+ }
+
var tagButton = {
title: "Manage",
id: 'tags',
@@ -162,6 +166,7 @@ export default class Compose extends Abstract {
if(!this.note.uuid) {
this.note.initUUID().then(function(){
this.save();
+ this.configureNavBar(true);
}.bind(this));
} else {
this.save();
diff --git a/src/screens/Filter.js b/src/screens/Filter.js
index 05d77962..e685eb8c 100644
--- a/src/screens/Filter.js
+++ b/src/screens/Filter.js
@@ -363,7 +363,6 @@ class TagsSection extends Component {
key={tag.uuid}
first={i == 0}
selected={() => {return root.state.selected.includes(tag.uuid)}}
- buttonCell={true}
/>
)
})}
@@ -394,7 +393,6 @@ class OptionsSection extends Component {
text={"Show only archived notes"}
first={true}
selected={() => {return this.props.archivedOnly}}
- buttonCell={true}
/>
@@ -431,7 +429,6 @@ class SortSection extends Component {
key={option.key}
first={i == 0}
selected={() => {return option.key == root.state.sortBy}}
- buttonCell={true}
/>
)
})}
diff --git a/src/screens/InputModal.js b/src/screens/InputModal.js
index ec3fbfa9..19eced85 100644
--- a/src/screens/InputModal.js
+++ b/src/screens/InputModal.js
@@ -21,8 +21,7 @@ export default class InputModal extends Abstract {
{
title: 'Cancel',
id: 'cancel',
- showAsAction: 'ifRoom',
- buttonColor: GlobalStyles.constants().mainTintColor,
+ showAsAction: 'ifRoom'
},
],
animated: false
@@ -37,6 +36,12 @@ export default class InputModal extends Abstract {
}
onSave = () => {
+ if(this.props.validate) {
+ if(!this.props.validate(this.state.text)) {
+ this.props.onError(this.state.text);
+ return;
+ }
+ }
this.props.onSave(this.state.text);
this.props.navigator.dismissModal({animationType: "slide-down"});
}
@@ -64,9 +69,7 @@ export default class InputModal extends Abstract {
/>
-
- this.onSave()} />
-
+ this.onSave()} />