mirror of
https://github.com/timepill/timepill-app.git
synced 2025-04-30 09:59:31 +08:00
1. 日记本“新增”按钮
2. 创建日记本页面(未完成) 3. 试用react-native-datepicker,用于选择日记本过期时间 - ios下月份显示英文,暂时没有配置项可以显示数字 - 安卓下界面良好
This commit is contained in:
parent
912cf0cabb
commit
0a7175a277
8 changed files with 333 additions and 1 deletions
|
@ -5,4 +5,14 @@
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="SpinnerDatePickerDialog" parent="android:Theme.Material.Light.Dialog">
|
||||||
|
<item name="android:datePickerStyle">@style/MyDatePicker</item>
|
||||||
|
<item name="android:colorAccent">#2196f3</item>
|
||||||
|
<item name="android:colorControlNormal">#2196f3</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="MyDatePicker" parent="android:Widget.Material.DatePicker">
|
||||||
|
<item name="android:datePickerMode">spinner</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -10821,6 +10821,14 @@
|
||||||
"resolved": "http://registry.npm.taobao.org/react-native-actionsheet-api/download/react-native-actionsheet-api-1.0.4.tgz",
|
"resolved": "http://registry.npm.taobao.org/react-native-actionsheet-api/download/react-native-actionsheet-api-1.0.4.tgz",
|
||||||
"integrity": "sha1-AGJeOeRdy8KnERKB/xUDl+5ZUbI="
|
"integrity": "sha1-AGJeOeRdy8KnERKB/xUDl+5ZUbI="
|
||||||
},
|
},
|
||||||
|
"react-native-datepicker": {
|
||||||
|
"version": "1.7.2",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/react-native-datepicker/download/react-native-datepicker-1.7.2.tgz",
|
||||||
|
"integrity": "sha1-WNCCJZGgrJsyq6CCZQIioO4pZp0=",
|
||||||
|
"requires": {
|
||||||
|
"moment": "^2.22.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-native-device-info": {
|
"react-native-device-info": {
|
||||||
"version": "1.6.1",
|
"version": "1.6.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/react-native-device-info/download/react-native-device-info-1.6.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/react-native-device-info/download/react-native-device-info-1.6.1.tgz",
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
"react": "16.8.3",
|
"react": "16.8.3",
|
||||||
"react-native": "0.59.5",
|
"react-native": "0.59.5",
|
||||||
"react-native-actionsheet-api": "^1.0.4",
|
"react-native-actionsheet-api": "^1.0.4",
|
||||||
|
"react-native-datepicker": "^1.7.2",
|
||||||
"react-native-device-info": "^1.6.1",
|
"react-native-device-info": "^1.6.1",
|
||||||
"react-native-elements": "^0.19.0",
|
"react-native-elements": "^0.19.0",
|
||||||
"react-native-iphone-x-helper": "^1.0.2",
|
"react-native-iphone-x-helper": "^1.0.2",
|
||||||
|
|
82
src/component/dateInput.js
Normal file
82
src/component/dateInput.js
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {StyleSheet, Text, View, InteractionManager} from 'react-native';
|
||||||
|
import {Navigation} from 'react-native-navigation';
|
||||||
|
import DatePicker from 'react-native-datepicker'
|
||||||
|
|
||||||
|
|
||||||
|
function now() {
|
||||||
|
const d = new Date();
|
||||||
|
const localTime = d.getTime();
|
||||||
|
const localOffset = d.getTimezoneOffset() * 60000;
|
||||||
|
const utc = localTime + localOffset;
|
||||||
|
const offset = 8; //东 8 区
|
||||||
|
const beijingTime = utc + (3600000 * offset);
|
||||||
|
|
||||||
|
return new Date(beijingTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class DateInput extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.updateDate();
|
||||||
|
this.state = {
|
||||||
|
date: this.formatDate(this.nowDate)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
InteractionManager.runAfterInteractions(() => {
|
||||||
|
this.updateDate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDate() {
|
||||||
|
this.nowDate = now();
|
||||||
|
let nowMSec = this.nowDate.getTime();
|
||||||
|
|
||||||
|
let minExpiredMSec = 7 * 24 * 3600000; // at least 7 days to expire
|
||||||
|
let minExpiredDate = new Date(nowMSec + minExpiredMSec);
|
||||||
|
this.minDate = this.formatDate(minExpiredDate);
|
||||||
|
|
||||||
|
let maxExpiredMSec = 3650 * 24 * 3600000; // at most 10 years to expire
|
||||||
|
let maxExpireDate = new Date(nowMSec + maxExpiredMSec);
|
||||||
|
this.maxDate = this.formatDate(maxExpireDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
formatDate(date) {
|
||||||
|
let year = date.getFullYear();
|
||||||
|
let month = date.getMonth() + 1;
|
||||||
|
let day = date.getDate();
|
||||||
|
|
||||||
|
return year + '-' + month + '-' + day;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDate() {
|
||||||
|
return this.state.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<DatePicker mode="date" format="YYYY-MM-DD" showIcon={false}
|
||||||
|
style={this.props.style}
|
||||||
|
customStyles={this.props.customStyles}
|
||||||
|
|
||||||
|
confirmBtnText="确认"
|
||||||
|
cancelBtnText="取消"
|
||||||
|
|
||||||
|
placeholder="过期日期"
|
||||||
|
minDate={this.minDate}
|
||||||
|
maxDate={this.maxDate}
|
||||||
|
date={this.state.date}
|
||||||
|
|
||||||
|
onDateChange={(date) => {
|
||||||
|
this.setState({date: date})
|
||||||
|
}}
|
||||||
|
|
||||||
|
androidMode={'spinner'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
44
src/component/notebook/notebookAdd.js
Normal file
44
src/component/notebook/notebookAdd.js
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {View, StyleSheet, Text, TouchableOpacity} from 'react-native';
|
||||||
|
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||||
|
|
||||||
|
import Color from '../../style/color'
|
||||||
|
|
||||||
|
|
||||||
|
export default class NotebookAdd extends Component {
|
||||||
|
|
||||||
|
_defaultOnPress() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<TouchableOpacity activeOpacity={0.7} onPress={
|
||||||
|
this.props.onPress ? this.props.onPress : this._defaultOnPress.bind(this)
|
||||||
|
}>
|
||||||
|
<View style={localStyle.box}>
|
||||||
|
<Ionicons name="md-add" size={48} color={Color.inactiveText} />
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const localStyle = StyleSheet.create({
|
||||||
|
box: {
|
||||||
|
flex: 1,
|
||||||
|
width: 140,
|
||||||
|
shadowColor: '#444',
|
||||||
|
shadowOpacity: 0.1,
|
||||||
|
shadowOffset: {
|
||||||
|
width: 0,
|
||||||
|
height: 0
|
||||||
|
},
|
||||||
|
elevation: 1,
|
||||||
|
backgroundColor: "#eee",
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
margin: 3,
|
||||||
|
marginBottom: 15
|
||||||
|
}
|
||||||
|
});
|
|
@ -12,6 +12,7 @@ import {Navigation} from 'react-native-navigation';
|
||||||
|
|
||||||
import Api from '../../util/api';
|
import Api from '../../util/api';
|
||||||
import Notebook from './notebook'
|
import Notebook from './notebook'
|
||||||
|
import NotebookAdd from './notebookAdd'
|
||||||
|
|
||||||
|
|
||||||
export default class NotebookList extends Component {
|
export default class NotebookList extends Component {
|
||||||
|
@ -59,6 +60,17 @@ export default class NotebookList extends Component {
|
||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onAddPress() {
|
||||||
|
Navigation.push(this.props.componentId, {
|
||||||
|
component: {
|
||||||
|
name: 'NotebookAdd',
|
||||||
|
passProps: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
_onNotebookPress(notebook) {
|
_onNotebookPress(notebook) {
|
||||||
Navigation.push(this.props.componentId, {
|
Navigation.push(this.props.componentId, {
|
||||||
component: {
|
component: {
|
||||||
|
@ -85,6 +97,10 @@ export default class NotebookList extends Component {
|
||||||
let user = this.state.user;
|
let user = this.state.user;
|
||||||
(user ? Api.getUserNotebooks(user.id) : Api.getSelfNotebooks())
|
(user ? Api.getUserNotebooks(user.id) : Api.getSelfNotebooks())
|
||||||
.then(notebooks => {
|
.then(notebooks => {
|
||||||
|
if(!user) {
|
||||||
|
notebooks.unshift({id: 'new'});
|
||||||
|
}
|
||||||
|
|
||||||
let groups = this.createGroup(notebooks, this.itemsPerRow);
|
let groups = this.createGroup(notebooks, this.itemsPerRow);
|
||||||
this.setState({
|
this.setState({
|
||||||
notebooks: groups
|
notebooks: groups
|
||||||
|
@ -95,6 +111,16 @@ export default class NotebookList extends Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_renderAdd() {
|
||||||
|
return (<NotebookAdd key='new'
|
||||||
|
onPress={() => this._onAddPress()}>
|
||||||
|
</NotebookAdd>);
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderPlaceHolder() {
|
||||||
|
return <View key="placeholder" style={{width: 140}} />;
|
||||||
|
}
|
||||||
|
|
||||||
_renderItem(notebook) {
|
_renderItem(notebook) {
|
||||||
return notebook ? (
|
return notebook ? (
|
||||||
<TouchableOpacity key={notebook.id} activeOpacity={0.7}
|
<TouchableOpacity key={notebook.id} activeOpacity={0.7}
|
||||||
|
@ -113,11 +139,18 @@ export default class NotebookList extends Component {
|
||||||
data={this.state.notebooks}
|
data={this.state.notebooks}
|
||||||
|
|
||||||
keyExtractor={(item, index) => {
|
keyExtractor={(item, index) => {
|
||||||
return item[0].id.toString()
|
return item[0].id.toString();
|
||||||
}}
|
}}
|
||||||
|
|
||||||
renderItem={({item}) => {
|
renderItem={({item}) => {
|
||||||
let row = item.map((notebook) => {
|
let row = item.map((notebook) => {
|
||||||
|
if(!notebook) {
|
||||||
|
return this._renderPlaceHolder();
|
||||||
|
|
||||||
|
} else if(notebook.id == 'new') {
|
||||||
|
return this._renderAdd();
|
||||||
|
}
|
||||||
|
|
||||||
return this._renderItem(notebook);
|
return this._renderItem(notebook);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
153
src/page/NotebookAddPage.js
Normal file
153
src/page/NotebookAddPage.js
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {StyleSheet, Text, View, ScrollView, Switch, TextInput, TouchableOpacity} from 'react-native';
|
||||||
|
import {Navigation} from 'react-native-navigation';
|
||||||
|
|
||||||
|
import Color from '../style/color';
|
||||||
|
import {Icon} from '../style/icon';
|
||||||
|
import Api from '../util/api';
|
||||||
|
|
||||||
|
import DateInput from '../component/dateInput'
|
||||||
|
|
||||||
|
|
||||||
|
export default class NotebookAddPage extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
Navigation.events().bindComponent(this);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
notebook: props.notebook,
|
||||||
|
|
||||||
|
subject: '',
|
||||||
|
isPublic: false,
|
||||||
|
dateString: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static options(passProps) {
|
||||||
|
return {
|
||||||
|
topBar: {
|
||||||
|
title: {
|
||||||
|
text: '创建日记本'
|
||||||
|
},
|
||||||
|
rightButtons: [{
|
||||||
|
id: 'save',
|
||||||
|
icon: Icon.navButtonSave
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
bottomTabs: {
|
||||||
|
visible: false,
|
||||||
|
|
||||||
|
// hide bottom tab for android
|
||||||
|
drawBehind: true,
|
||||||
|
animate: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
navigationButtonPressed({buttonId}) {
|
||||||
|
console.log('date string:', this.dateInput.getDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={localStyle.wrap}>
|
||||||
|
|
||||||
|
<View style={localStyle.group}>
|
||||||
|
<View style={localStyle.item}>
|
||||||
|
<TextInput style={localStyle.subject}
|
||||||
|
underlineColorAndroid='transparent'
|
||||||
|
selectionColor={Color.primary}
|
||||||
|
autoCorrect={false}
|
||||||
|
|
||||||
|
placeholder="主题"
|
||||||
|
value={this.state.subject}
|
||||||
|
|
||||||
|
onChangeText={(text) => this.setState({subject: text})}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={localStyle.line} />
|
||||||
|
|
||||||
|
<View>
|
||||||
|
<View style={localStyle.item}>
|
||||||
|
<DateInput ref={(r) => {this.dateInput = r}}
|
||||||
|
style={localStyle.datePickerStyle}
|
||||||
|
customStyles={customDatePickerStyle}>
|
||||||
|
</DateInput>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={localStyle.line} />
|
||||||
|
|
||||||
|
<View style={localStyle.item}>
|
||||||
|
<Text style={localStyle.title}>公开日记本</Text>
|
||||||
|
<Switch value={this.state.isPublic}
|
||||||
|
onValueChange={(v) => this.setState({isPublic: v})}
|
||||||
|
trackColor={Api.IS_ANDROID ? Color.textSelect : null}
|
||||||
|
thumbColor={Api.IS_ANDROID && this.state.isPublic ? Color.light : null}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const localStyle = StyleSheet.create({
|
||||||
|
wrap: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#EFEFF4'
|
||||||
|
},
|
||||||
|
group: {
|
||||||
|
marginTop: 30,
|
||||||
|
backgroundColor: 'white',
|
||||||
|
borderTopWidth: StyleSheet.hairlineWidth,
|
||||||
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||||
|
borderColor: '#c8c7cc'
|
||||||
|
},
|
||||||
|
item: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
paddingHorizontal: 15,
|
||||||
|
height: 45
|
||||||
|
},
|
||||||
|
subject: {
|
||||||
|
flex: 1,
|
||||||
|
fontSize: 16,
|
||||||
|
height: '100%',
|
||||||
|
padding: 0
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: '#222'
|
||||||
|
},
|
||||||
|
line: {
|
||||||
|
marginLeft: 15,
|
||||||
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||||
|
borderColor: '#c8c7cc'
|
||||||
|
},
|
||||||
|
datePickerStyle: {
|
||||||
|
flex: 1,
|
||||||
|
padding: 0,
|
||||||
|
height: '100%',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const customDatePickerStyle = StyleSheet.create({
|
||||||
|
dateInput: {
|
||||||
|
height: 45,
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
borderWidth: 0
|
||||||
|
},
|
||||||
|
placeholderText: {
|
||||||
|
fontSize: 16
|
||||||
|
},
|
||||||
|
dateText: {
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ DiaryDetail: require("./DiaryDetailPage.js").default,
|
||||||
Follow: require("./FollowPage.js").default,
|
Follow: require("./FollowPage.js").default,
|
||||||
FollowUser: require("./FollowUserPage.js").default,
|
FollowUser: require("./FollowUserPage.js").default,
|
||||||
Home: require("./HomePage.js").default,
|
Home: require("./HomePage.js").default,
|
||||||
|
NotebookAdd: require("./NotebookAddPage.js").default,
|
||||||
NotebookDetail: require("./NotebookDetailPage.js").default,
|
NotebookDetail: require("./NotebookDetailPage.js").default,
|
||||||
NotificationHistory: require("./NotificationHistoryPage.js").default,
|
NotificationHistory: require("./NotificationHistoryPage.js").default,
|
||||||
Notification: require("./NotificationPage.js").default,
|
Notification: require("./NotificationPage.js").default,
|
||||||
|
|
Loading…
Reference in a new issue