1
0
mirror of synced 2025-02-23 20:53:20 +01:00

style: lint fix

This commit is contained in:
Juchan Roh 2023-02-04 20:41:11 +09:00
parent facbf56d2d
commit b71eea4560
5 changed files with 988 additions and 702 deletions

83
App.js

@ -3,12 +3,11 @@
* https://github.com/facebook/react-native * https://github.com/facebook/react-native
* *
* @format * @format
* @flow
*/ */
import React from 'react'; import React from 'react';
import { createAppContainer } from 'react-navigation'; import {createAppContainer} from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack'; import {createStackNavigator} from 'react-navigation-stack';
import MainScreen from './src/screen/MainScreen'; import MainScreen from './src/screen/MainScreen';
import CardEditScreen from './src/screen/CardEditScreen'; import CardEditScreen from './src/screen/CardEditScreen';
@ -18,58 +17,60 @@ import i18n from 'i18n-js';
import en from './src/locales/en'; import en from './src/locales/en';
import ko from './src/locales/ko'; import ko from './src/locales/ko';
const MainNavigator = createStackNavigator({ const MainNavigator = createStackNavigator(
Home: { {
screen: MainScreen, Home: {
navigationOptions: {headerShown: false} screen: MainScreen,
navigationOptions: {headerShown: false},
},
CardEditScreen: {
screen: CardEditScreen,
navigationOptions: {headerShown: false},
},
}, },
CardEditScreen: { {
screen: CardEditScreen, initialRouteName: 'Home',
navigationOptions: {headerShown: false}
}, },
},
{
initialRouteName: 'Home',
}
); );
const AppContainer = createAppContainer(MainNavigator); const AppContainer = createAppContainer(MainNavigator);
const setI18nConfig = () => { const setI18nConfig = () => {
const fallback = { languageTag: 'en' }; const fallback = {languageTag: 'en'};
const { languageTag } = RNLocalize.findBestAvailableLanguage(['en', 'ko']) || fallback; const {languageTag} =
RNLocalize.findBestAvailableLanguage(['en', 'ko']) || fallback;
i18n.translations = { i18n.translations = {
en, en,
ko, ko,
}; };
i18n.locale = languageTag; i18n.locale = languageTag;
}; };
export default class App extends React.Component{ export default class App extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
setI18nConfig(); setI18nConfig();
} }
componentDidMount() { componentDidMount() {
RNLocalize.addEventListener('change', this.handleLocalizationChange) RNLocalize.addEventListener('change', this.handleLocalizationChange);
} }
componentWillUnmount() { componentWillUnmount() {
RNLocalize.removeEventListener('change', this.handleLocalizationChange) RNLocalize.removeEventListener('change', this.handleLocalizationChange);
} }
handleLocalizationChange = () => { handleLocalizationChange = () => {
setI18nConfig(); setI18nConfig();
this.forceUpdate(); this.forceUpdate();
}; };
render(){ render() {
return ( return (
<> <>
<AppContainer/> <AppContainer />
</> </>
); );
} }
}; }

@ -1,39 +1,41 @@
export default { export default {
header_home: 'Home', header_home: 'Home',
header_add: 'Add', header_add: 'Add',
header_edit: 'Edit', header_edit: 'Edit',
main_empty_string: 'Touch + button on top right to add a card', main_empty_string: 'Touch + button on top right to add a card',
edit_random: 'Random Generate', edit_random: 'Random Generate',
edit_preview: 'Preview', edit_preview: 'Preview',
edit_sid_notice: 'SID is 16-digit hexadecimal number. Note that it is not a card number!', edit_sid_notice:
'SID is 16-digit hexadecimal number. Note that it is not a card number!',
edit_background: 'Background', edit_background: 'Background',
edit_background_empty: 'Touch here to select the background image', edit_background_empty: 'Touch here to select the background image',
edit_background_selected: 'The image has been selected', edit_background_selected: 'The image has been selected',
edit_name: 'Name', edit_name: 'Name',
alert_delete_title: 'Delete', alert_delete_title: 'Delete',
alert_delete_content: 'Do you want to delete this card?', alert_delete_content: 'Do you want to delete this card?',
alert_delete_yes: 'Yes', alert_delete_yes: 'Yes',
alert_delete_no: 'No', alert_delete_no: 'No',
alert_save_content: 'Card saved successfully.', alert_save_content: 'Card saved successfully.',
alert_save_yes: 'OK', alert_save_yes: 'OK',
alert_not_support_title: 'This device is not supported', alert_not_support_title: 'This device is not supported',
alert_not_support_content: 'This device does not have the feature to emulate card.', alert_not_support_content:
alert_not_support_yes: 'OK', 'This device does not have the feature to emulate card.',
alert_not_support_yes: 'OK',
alert_nfc_title: 'NFC is disabled', alert_nfc_title: 'NFC is disabled',
alert_nfc_content: 'NFC is required to emulate card. Please enable NFC in the settings and restart the app.', alert_nfc_content:
alert_nfc_yes: 'OK', 'NFC is required to emulate card. Please enable NFC in the settings and restart the app.',
alert_nfc_yes: 'OK',
card_touch_to_enable: 'Touch to enable', card_touch_to_enable: 'Touch to enable',
card_touch_to_disable: 'Touch to disable', card_touch_to_disable: 'Touch to disable',
card_delete: 'Delete', card_delete: 'Delete',
card_edit: 'Edit', card_edit: 'Edit',
} };

@ -1,40 +1,40 @@
export default { export default {
header_home: '홈', header_home: '홈',
header_add: '카드 추가', header_add: '카드 추가',
header_edit: '카드 편집', header_edit: '카드 편집',
main_empty_string: '우측 상단의 +를 눌러 카드를 추가해주세요', main_empty_string: '우측 상단의 +를 눌러 카드를 추가해주세요',
edit_random: '랜덤 생성', edit_random: '랜덤 생성',
edit_preview: '미리보기', edit_preview: '미리보기',
edit_sid_notice: 'SID는 16진수 16자리 입니다. 카드 번호가 아님에 유의하세요!', edit_sid_notice: 'SID는 16진수 16자리 입니다. 카드 번호가 아님에 유의하세요!',
edit_background: '카드 배경', edit_background: '카드 배경',
edit_background_empty: '여기를 눌러 사진을 선택할 수 있습니다.', edit_background_empty: '여기를 눌러 사진을 선택할 수 있습니다.',
edit_background_selected: '사진이 선택되었습니다.', edit_background_selected: '사진이 선택되었습니다.',
edit_name: '카드 이름', edit_name: '카드 이름',
alert_delete_title: '삭제', alert_delete_title: '삭제',
alert_delete_content: '카드를 삭제하시겠습니까?', alert_delete_content: '카드를 삭제하시겠습니까?',
alert_delete_yes: '예', alert_delete_yes: '예',
alert_delete_no: '아니오', alert_delete_no: '아니오',
alert_save_content: '카드를 저장했습니다.', alert_save_content: '카드를 저장했습니다.',
alert_save_yes: '확인', alert_save_yes: '확인',
alert_not_support_title: '이 기기는 지원되지 않습니다.', alert_not_support_title: '이 기기는 지원되지 않습니다.',
alert_not_support_content: '이 기기는 카드를 에뮬레이션 하기 위해 필요한 기능을 가지고 있지 않습니다.', alert_not_support_content:
alert_not_support_yes: '확인', '이 기기는 카드를 에뮬레이션 하기 위해 필요한 기능을 가지고 있지 않습니다.',
alert_not_support_yes: '확인',
alert_nfc_title: 'NFC가 활성화 되어있지 않습니다.', alert_nfc_title: 'NFC가 활성화 되어있지 않습니다.',
alert_nfc_content: '카드를 에뮬레이션 하기 위해서 NFC가 필요합니다. 설정에서 NFC를 활성화하고 앱을 재실행해주세요.', alert_nfc_content:
alert_nfc_yes: '확인', '카드를 에뮬레이션 하기 위해서 NFC가 필요합니다. 설정에서 NFC를 활성화하고 앱을 재실행해주세요.',
alert_nfc_yes: '확인',
card_touch_to_enable: '터치하여 활성화',
card_touch_to_disable: '터치하여 비활성화',
card_delete: '삭제',
card_edit: '편집',
}
card_touch_to_enable: '터치하여 활성화',
card_touch_to_disable: '터치하여 비활성화',
card_delete: '삭제',
card_edit: '편집',
};

@ -1,19 +1,19 @@
import React from 'react'; import React from 'react';
import { import {
View, View,
Text, Text,
StatusBar, StatusBar,
SafeAreaView, SafeAreaView,
ScrollView, ScrollView,
TouchableOpacity, TouchableOpacity,
Dimensions, Dimensions,
ImageBackground, ImageBackground,
findNodeHandle, findNodeHandle,
Alert, Alert,
StyleSheet, StyleSheet,
Image, Image,
KeyboardAvoidingView, KeyboardAvoidingView,
TextInput, TextInput,
} from 'react-native'; } from 'react-native';
import update from 'react-addons-update'; import update from 'react-addons-update';
import Icon from 'react-native-vector-icons/MaterialIcons'; import Icon from 'react-native-vector-icons/MaterialIcons';
@ -22,368 +22,547 @@ import CardConv from '../module/CardConv';
import i18n from 'i18n-js'; import i18n from 'i18n-js';
class CardPreview extends React.Component { class CardPreview extends React.Component {
render() { render() {
let cardContent = ( let cardContent = (
<View style={{flex: 1, backgroundColor:'rgba(0,0,0,0.3)', borderRadius:8}}> <View
<View style={{flex: 1,}}> style={{flex: 1, backgroundColor: 'rgba(0,0,0,0.3)', borderRadius: 8}}>
<TouchableOpacity style={{flex: 1}}> <View style={{flex: 1}}>
<Text style={{position: 'absolute', top: 20, left: 20, fontSize: 17, fontWeight:'bold', color:'#ffffff'}}> <TouchableOpacity style={{flex: 1}}>
{this.props.name} <Text
</Text> style={{
<View style={{flex: 1, justifyContent:'center', paddingTop: 20,}}> position: 'absolute',
<Text style={{paddingTop: 0, textAlign: 'center', alignSelf: 'center', color: '#E0E0E0', fontSize: 14 }}> top: 20,
{this.props.uid ? left: 20,
this.props.uid.substr(0,4)+'-'+this.props.uid.substr(4,4)+'-'+this.props.uid.substr(8,4)+'-'+this.props.uid.substr(12,4) fontSize: 17,
: '' fontWeight: 'bold',
} color: '#ffffff',
</Text> }}>
<Text style={{paddingTop: 8, textAlign: 'center', alignSelf: 'center', fontSize: 24, color:'#FAFAFA', fontWeight: '500', letterSpacing:-0.5}}> {this.props.name}
{i18n.t('card_touch_to_enable')} </Text>
</Text> <View style={{flex: 1, justifyContent: 'center', paddingTop: 20}}>
</View> <Text
</TouchableOpacity> style={{
</View> paddingTop: 0,
<View style={{height: 1, backgroundColor: '#FAFAFA'}}/> textAlign: 'center',
<View style={{height: 48, flexDirection: 'row'}}> alignSelf: 'center',
<TouchableOpacity style={{ color: '#E0E0E0',
flex: 1, fontSize: 14,
alignItems: 'center', }}>
justifyContent: 'center', {this.props.uid
}}> ? this.props.uid.substr(0, 4) +
<Text style={{fontSize: 14, color:'#FAFAFA'}}>{i18n.t('card_edit')}</Text> '-' +
</TouchableOpacity> this.props.uid.substr(4, 4) +
<View style={{width: 1, backgroundColor: '#FAFAFA'}}/> '-' +
<TouchableOpacity style={{ this.props.uid.substr(8, 4) +
flex: 1, '-' +
alignItems: 'center', this.props.uid.substr(12, 4)
justifyContent: 'center', : ''}
}}> </Text>
<Text style={{fontSize: 14, color:'#ffffff'}}>{i18n.t('card_delete')}</Text> <Text
</TouchableOpacity> style={{
</View> paddingTop: 8,
textAlign: 'center',
alignSelf: 'center',
fontSize: 24,
color: '#FAFAFA',
fontWeight: '500',
letterSpacing: -0.5,
}}>
{i18n.t('card_touch_to_enable')}
</Text>
</View> </View>
) </TouchableOpacity>
return ( </View>
<View style={[{ <View style={{height: 1, backgroundColor: '#FAFAFA'}} />
borderRadius: 8, <View style={{height: 48, flexDirection: 'row'}}>
height: this.props.cardHeight, <TouchableOpacity
marginTop: 16, style={{
justifyContent: 'center', flex: 1,
},]}> alignItems: 'center',
{this.props.image ? ( justifyContent: 'center',
<ImageBackground }}>
source={{uri: this.props.image}} <Text style={{fontSize: 14, color: '#FAFAFA'}}>
style={{ {i18n.t('card_edit')}
flex: 1, </Text>
resizeMode:'contain', </TouchableOpacity>
}} <View style={{width: 1, backgroundColor: '#FAFAFA'}} />
blurRadius={2} <TouchableOpacity
borderRadius={8}> style={{
{cardContent} flex: 1,
</ImageBackground> alignItems: 'center',
) : ( justifyContent: 'center',
<View }}>
style={{ <Text style={{fontSize: 14, color: '#ffffff'}}>
flex: 1, {i18n.t('card_delete')}
resizeMode:'contain', </Text>
backgroundColor: '#03A9F4', </TouchableOpacity>
}} </View>
blurRadius={2} </View>
borderRadius={8}> );
{cardContent} return (
</View> <View
)} style={[
</View> {
); borderRadius: 8,
} height: this.props.cardHeight,
marginTop: 16,
justifyContent: 'center',
},
]}>
{this.props.image ? (
<ImageBackground
source={{uri: this.props.image}}
style={{
flex: 1,
resizeMode: 'contain',
}}
blurRadius={2}
borderRadius={8}>
{cardContent}
</ImageBackground>
) : (
<View
style={{
flex: 1,
resizeMode: 'contain',
backgroundColor: '#03A9F4',
}}
blurRadius={2}
borderRadius={8}>
{cardContent}
</View>
)}
</View>
);
}
} }
class ETextInput extends React.Component { class ETextInput extends React.Component {
state = { state = {
focused: false, focused: false,
value: this.props.value ?? '', value: this.props.value ?? '',
}; };
onFocusCallback(){ onFocusCallback() {
this.setState({focused: true}); this.setState({focused: true});
if(typeof this.props.onFocus === 'function') if (typeof this.props.onFocus === 'function') {
this.props.onFocus(); this.props.onFocus();
} }
}
onBlurCallback(){ onBlurCallback() {
this.setState({focused: false}); this.setState({focused: false});
if(typeof this.props.onBlur === 'function') if (typeof this.props.onBlur === 'function') {
this.props.onBlur(); this.props.onBlur();
} }
}
onChangeTextCallback(text){ onChangeTextCallback(text) {
if(typeof this.props.filter === 'function') if (typeof this.props.filter === 'function') {
text = this.props.filter(text); text = this.props.filter(text);
if(typeof this.props.onChangeText === 'function')
this.props.onChangeText(text);
} }
if (typeof this.props.onChangeText === 'function') {
focus(){ this.props.onChangeText(text);
this.textInput.focus();
} }
}
render() { focus() {
return ( this.textInput.focus();
<View style={this.props.style}> }
<Text style={[{fontSize: 14,
color: this.props.error ? '#F44336' : this.state.focused ? '#03A9F4' : '#9E9E9E',
fontWeight: 'bold',
}, this.props.titleStyle]}>
{this.props.title}
</Text>
<TextInput render() {
style={[{fontSize: 17, paddingTop: 4,}, this.props.textStyle]} return (
value={this.props.value} <View style={this.props.style}>
onFocus={() => this.onFocusCallback()} <Text
onBlur={() => this.onBlurCallback()} style={[
onChangeText={text => this.onChangeTextCallback(text)} {
editable={this.props.editable} fontSize: 14,
maxLength={this.props.maxLength} color: this.props.error
autoCapitalize={this.props.autoCapitalize} ? '#F44336'
ref={ref => this.textInput = ref} : this.state.focused
> ? '#03A9F4'
</TextInput> : '#9E9E9E',
<View style={{ fontWeight: 'bold',
paddingTop: 2, },
height: this.state.focused ? 2 : 1, this.props.titleStyle,
backgroundColor: this.props.error ? '#F44336' : this.state.focused ? '#03A9F4' : '#9E9E9E', ]}>
opacity: this.props.editable ? 1 : 0.5, {this.props.title}
}}/> </Text>
</View>
) <TextInput
} style={[{fontSize: 17, paddingTop: 4}, this.props.textStyle]}
value={this.props.value}
onFocus={() => this.onFocusCallback()}
onBlur={() => this.onBlurCallback()}
onChangeText={text => this.onChangeTextCallback(text)}
editable={this.props.editable}
maxLength={this.props.maxLength}
autoCapitalize={this.props.autoCapitalize}
ref={ref => (this.textInput = ref)}
/>
<View
style={{
paddingTop: 2,
height: this.state.focused ? 2 : 1,
backgroundColor: this.props.error
? '#F44336'
: this.state.focused
? '#03A9F4'
: '#9E9E9E',
opacity: this.props.editable ? 1 : 0.5,
}}
/>
</View>
);
}
} }
class CardEditScreen extends React.Component { class CardEditScreen extends React.Component {
state = { state = {
name: this.props.navigation.getParam('name', ''), name: this.props.navigation.getParam('name', ''),
sidAll: this.props.navigation.getParam('sid', '02FE'), sidAll: this.props.navigation.getParam('sid', '02FE'),
sid2: '', sid2: '',
sid3: '', sid3: '',
sid4: '', sid4: '',
uid: '', uid: '',
sidError: false, sidError: false,
image: this.props.navigation.getParam('image', ''), image: this.props.navigation.getParam('image', ''),
index: this.props.navigation.getParam('index', null), // null 이면 카드 새로 생성 index: this.props.navigation.getParam('index', null), // null 이면 카드 새로 생성
mode: '', mode: '',
update: this.props.navigation.getParam('update', null), update: this.props.navigation.getParam('update', null),
cardFocused: 'false', cardFocused: 'false',
};
componentDidMount(): void {
let {height, width} = Dimensions.get('window');
function randomHex4Byte() {
let hexString = Math.min(
Math.floor(Math.random() * 65536),
65535,
).toString(16);
if (hexString.length < 4) {
hexString = '0'.repeat(4 - hexString.length) + hexString;
}
return hexString.toUpperCase();
} }
componentDidMount(): void { if (this.state.index === null) {
let {height, width} = (Dimensions.get('window')); this.setState(
{
function randomHex4Byte(){ mode: 'add',
let hexString = Math.min(Math.floor(Math.random() * 65536), 65535).toString(16); sid2: randomHex4Byte(),
sid3: randomHex4Byte(),
if(hexString.length < 4) sid4: randomHex4Byte(),
hexString = '0'.repeat(4 - hexString.length) + hexString; cardHeight: ((width - 48) * 53.98) / 85.6,
},
return hexString.toUpperCase(); () => this.updateSID(),
} );
} else {
this.setState(
if(this.state.index === null){ {
this.setState({mode: 'add', sid2: randomHex4Byte(), sid3: randomHex4Byte(), sid4: randomHex4Byte(), cardHeight: (width - 48) * 53.98 / 85.60,}, mode: 'edit',
() => this.updateSID()); sid2: this.state.sidAll.substr(4, 4),
} sid3: this.state.sidAll.substr(8, 4),
else{ sid4: this.state.sidAll.substr(12, 4),
this.setState({ cardHeight: ((width - 48) * 53.98) / 85.6,
mode: 'edit', },
sid2: this.state.sidAll.substr(4, 4), () => {
sid3: this.state.sidAll.substr(8, 4), this.updateSID();
sid4: this.state.sidAll.substr(12, 4), },
cardHeight: (width - 48) * 53.98 / 85.60, );
}, () => {
this.updateSID();
});
}
this.nameInput.focus();
} }
makeSid(){ this.nameInput.focus();
let sid = '02FE' + this.state.sid2 + this.state.sid3 + this.state.sid4; }
sid = sid.toUpperCase();
if(sid.length !== 16){
return '';
}
if(sid.replace(/[^0-9A-F]/g, '') !== sid){
return '';
}
return sid; makeSid() {
let sid = '02FE' + this.state.sid2 + this.state.sid3 + this.state.sid4;
sid = sid.toUpperCase();
if (sid.length !== 16) {
return '';
}
if (sid.replace(/[^0-9A-F]/g, '') !== sid) {
return '';
} }
async updateSID(){ return sid;
if(this.makeSid() !== ''){ }
let uid = await CardConv.convertSID(this.makeSid());
this.setState({uid: uid}); async updateSID() {
} if (this.makeSid() !== '') {
let uid = await CardConv.convertSID(this.makeSid());
this.setState({uid: uid});
}
}
saveCard() {
let sid = this.makeSid();
if (sid === '') {
this.setState({sidError: true});
return;
} }
saveCard(){ if (typeof this.state.update === 'function') {
let sid = this.makeSid(); this.state.update(
this.state.name,
sid,
this.state.index,
this.state.image,
this.props.navigation,
);
}
}
if(sid === ''){ setRandomSid() {
this.setState({sidError: true}); function randomHex4Byte() {
return ; let hexString = Math.min(
} Math.floor(Math.random() * 65536),
65535,
).toString(16);
if(typeof this.state.update === 'function'){ if (hexString.length < 4) {
this.state.update(this.state.name, sid, this.state.index, this.state.image, this.props.navigation); hexString = '0'.repeat(4 - hexString.length) + hexString;
} }
return hexString.toUpperCase();
} }
setRandomSid(){ this.setState(
function randomHex4Byte(){ {sid2: randomHex4Byte(), sid3: randomHex4Byte(), sid4: randomHex4Byte()},
let hexString = Math.min(Math.floor(Math.random() * 65536), 65535).toString(16); () => this.updateSID(),
);
}
if(hexString.length < 4) selectPhoto() {
hexString = '0'.repeat(4 - hexString.length) + hexString; ImagePicker.openPicker({
cropping: true,
width: 856,
height: 540,
mediaType: 'photo',
}).then(res => {
if (res && res.path) {
this.setState({image: res.path});
}
});
}
return hexString.toUpperCase(); render() {
} return (
<SafeAreaView style={{flex: 1, paddingTop: StatusBar.currentHeight}}>
<StatusBar
barStyle="dark-content"
translucent={true}
backgroundColor={'#ffffff'}
/>
<KeyboardAvoidingView style={{flex: 1}}>
<View
style={{
height: 48,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ffffff',
}}>
<View
style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text
style={{
fontSize: 17,
fontWeight: 'bold',
textAlignVertical: 'center',
}}>
{this.state.mode === 'add'
? i18n.t('header_add')
: i18n.t('header_edit')}
</Text>
this.setState({sid2: randomHex4Byte(), sid3: randomHex4Byte(), sid4: randomHex4Byte()}, () => this.updateSID()); <TouchableOpacity
} style={{
position: 'absolute',
top: 0,
bottom: 0,
right: 16,
alignItems: 'center',
justifyContent: 'center',
}}
onPress={() => this.saveCard()}>
<Icon name="save" size={26} color={'rgba(0,0,0,0.7)'} />
</TouchableOpacity>
</View>
</View>
<ScrollView style={{flex: 1, paddingHorizontal: 24, paddingTop: 16}}>
<ETextInput
title={i18n.t('edit_name')}
value={this.state.name}
onChangeText={text => this.setState({name: text})}
ref={ref => (this.nameInput = ref)}
/>
<TouchableOpacity onPress={() => this.selectPhoto()}>
<ETextInput
style={{marginTop: 24}}
title={i18n.t('edit_background')}
value={
this.state.image
? i18n.t('edit_background_selected')
: i18n.t('edit_background_empty')
}
editable={false}
/>
</TouchableOpacity>
selectPhoto(){ <View style={{marginTop: 24, flexDirection: 'row'}}>
ImagePicker.openPicker({ <ETextInput
cropping: true, title={'SID'}
width: 856, value={'02FE'}
height: 540, onChangeText={text => this.setState({sid: text})}
mediaType: 'photo', style={{flex: 1}}
}).then(res => { editable={false}
if(res && res.path){ error={this.state.sidError}
this.setState({image: res.path,}); textStyle={{textAlign: 'center'}}
} titleStyle={
}); this.state.sidError !== true &&
} this.state.sidFocus && {color: '#03A9F4'}
}
/>
<Text
style={{
width: 20,
marginTop: 24,
alignSelf: 'center',
textAlign: 'center',
color: '#9E9E9E',
fontSize: 14,
}}>
-
</Text>
<ETextInput
textStyle={{textAlign: 'center'}}
value={this.state.sid2}
onChangeText={text => {
this.setState({sid2: text}, () => this.updateSID());
if (text.length === 4) {
this.sid3Input.focus();
}
}}
style={{flex: 1}}
maxLength={4}
error={this.state.sidError}
onFocus={() => this.setState({sidFocus: true})}
onBlur={() => this.setState({sidFocus: false})}
autoCapitalize={'characters'}
ref={ref => (this.sid2Input = ref)}
editable={false}
/>
<Text
style={{
width: 20,
marginTop: 24,
alignSelf: 'center',
textAlign: 'center',
color: '#9E9E9E',
fontSize: 14,
}}>
-
</Text>
<ETextInput
textStyle={{textAlign: 'center'}}
value={this.state.sid3}
onChangeText={text => {
this.setState({sid3: text}, () => this.updateSID());
if (text.length === 4) {
this.sid4Input.focus();
}
}}
style={{flex: 1}}
maxLength={4}
error={this.state.sidError}
onFocus={() => this.setState({sidFocus: true})}
onBlur={() => this.setState({sidFocus: false})}
autoCapitalize={'characters'}
ref={ref => (this.sid3Input = ref)}
editable={false}
/>
<Text
style={{
width: 20,
marginTop: 24,
alignSelf: 'center',
textAlign: 'center',
color: '#9E9E9E',
fontSize: 14,
}}>
-
</Text>
<ETextInput
textStyle={{textAlign: 'center'}}
value={this.state.sid4}
onChangeText={text => {
this.setState({sid4: text}, () => this.updateSID());
this.updateSID();
}}
style={{flex: 1}}
error={this.state.sidError}
maxLength={4}
onFocus={() => this.setState({sidFocus: true})}
onBlur={() => this.setState({sidFocus: false})}
autoCapitalize={'characters'}
ref={ref => (this.sid4Input = ref)}
editable={false}
/>
</View>
<Text
style={{
marginTop: 8,
fontSize: 14,
letterSpacing: -0.4,
color: this.state.sidError ? '#F44336' : '#9E9E9E',
}}>
{i18n.t('edit_sid_notice')}
</Text>
<TouchableOpacity
style={{
marginTop: 24,
height: 48,
backgroundColor: '#03A9F4',
borderRadius: 8,
alignItems: 'center',
justifyContent: 'center',
}}
onPress={() => this.setRandomSid()}>
<Text style={{fontSize: 17, color: '#ffffff', fontWeight: '500'}}>
{i18n.t('edit_random')}
</Text>
</TouchableOpacity>
render() { <Text
return ( style={{
<SafeAreaView style={{flex: 1, paddingTop: StatusBar.currentHeight}}> fontSize: 14,
<StatusBar color: '#9E9E9E',
barStyle='dark-content' marginTop: 20,
translucent={true} fontWeight: 'bold',
backgroundColor={'#ffffff'} }}>
/> {i18n.t('edit_preview')}
<KeyboardAvoidingView style={{flex: 1,}}> </Text>
<View style={{ <CardPreview
height: 48, name={this.state.name}
flexDirection: 'row', uid={this.state.uid}
alignItems: 'center', image={this.state.image}
justifyContent: 'center', cardHeight={this.state.cardHeight ?? 0}
backgroundColor: '#ffffff' />
}}>
<View style={{flex: 1, alignItems: 'center',
justifyContent: 'center',}}>
<Text style={{
fontSize: 17,
fontWeight: 'bold',
textAlignVertical: 'center',
}}>
{this.state.mode === 'add' ? i18n.t('header_add') : i18n.t('header_edit')}
</Text>
<TouchableOpacity style={{ <View style={{height: 50}} />
position: 'absolute', </ScrollView>
top: 0, </KeyboardAvoidingView>
bottom: 0, </SafeAreaView>
right: 16, );
alignItems: 'center', }
justifyContent: 'center',
}} onPress={() => this.saveCard()}
>
<Icon name='save' size={26} color={'rgba(0,0,0,0.7)'}/>
</TouchableOpacity>
</View>
</View>
<ScrollView style={{flex: 1, paddingHorizontal: 24, paddingTop: 16,}}>
<ETextInput title={i18n.t('edit_name')} value={this.state.name} onChangeText={text => this.setState({name: text})} ref={ref => this.nameInput = ref}/>
<TouchableOpacity onPress={() => this.selectPhoto()}>
<ETextInput style={{marginTop: 24,}} title={i18n.t('edit_background')} value={this.state.image ? i18n.t('edit_background_selected') : i18n.t('edit_background_empty')} editable={false}/>
</TouchableOpacity>
<View style={{marginTop: 24, flexDirection: 'row'}}>
<ETextInput title={'SID'} value={'02FE'} onChangeText={text => this.setState({sid: text})}
style={{flex: 1,}}
editable={false}
error={this.state.sidError}
textStyle={{textAlign:'center',}}
titleStyle={this.state.sidError !== true && this.state.sidFocus && {color: '#03A9F4'}}
/>
<Text style={{width: 20, marginTop: 24, alignSelf: 'center', textAlign:'center', color: '#9E9E9E', fontSize: 14,}}>-</Text>
<ETextInput
textStyle={{textAlign:'center',}}
value={this.state.sid2}
onChangeText={text => {this.setState({sid2: text}, () => this.updateSID()); if(text.length === 4) this.sid3Input.focus(); }}
style={{flex: 1,}}
maxLength={4}
error={this.state.sidError}
onFocus={() => this.setState({sidFocus: true})}
onBlur={() => this.setState({sidFocus: false})}
autoCapitalize={'characters'}
ref={ref => this.sid2Input = ref}
editable={false}
/>
<Text style={{width: 20, marginTop: 24, alignSelf: 'center', textAlign:'center', color: '#9E9E9E', fontSize: 14,}}>-</Text>
<ETextInput
textStyle={{textAlign:'center',}}
value={this.state.sid3}
onChangeText={text => {this.setState({sid3: text}, () => this.updateSID()); if(text.length === 4) this.sid4Input.focus();}}
style={{flex: 1,}}
maxLength={4}
error={this.state.sidError}
onFocus={() => this.setState({sidFocus: true})}
onBlur={() => this.setState({sidFocus: false})}
autoCapitalize={'characters'}
ref={ref => this.sid3Input = ref}
editable={false}
/>
<Text style={{width: 20, marginTop: 24, alignSelf: 'center', textAlign:'center', color: '#9E9E9E', fontSize: 14,}}>-</Text>
<ETextInput
textStyle={{textAlign:'center',}}
value={this.state.sid4}
onChangeText={text => {this.setState({sid4: text}, () => this.updateSID()); this.updateSID();}}
style={{flex: 1,}}
error={this.state.sidError}
maxLength={4}
onFocus={() => this.setState({sidFocus: true})}
onBlur={() => this.setState({sidFocus: false})}
autoCapitalize={'characters'}
ref={ref => this.sid4Input = ref}
editable={false}
/>
</View>
<Text style={{marginTop: 8, fontSize: 14, letterSpacing: -0.4, color: this.state.sidError ? '#F44336' : '#9E9E9E'}}>
{i18n.t('edit_sid_notice')}
</Text>
<TouchableOpacity style={{marginTop: 24, height: 48, backgroundColor: '#03A9F4', borderRadius:8, alignItems:'center', justifyContent:'center',}}
onPress={() => this.setRandomSid()}
>
<Text style={{fontSize: 17, color: '#ffffff', fontWeight: '500'}}>{i18n.t('edit_random')}</Text>
</TouchableOpacity>
<Text style={{fontSize: 14, color: '#9E9E9E', marginTop: 20, fontWeight: 'bold'}}>{i18n.t('edit_preview')}</Text>
<CardPreview name={this.state.name} uid={this.state.uid} image={this.state.image} cardHeight={this.state.cardHeight ?? 0}/>
<View style={{height: 50}}/>
</ScrollView>
</KeyboardAvoidingView>
</SafeAreaView>
)
}
} }
export default CardEditScreen; export default CardEditScreen;

@ -1,17 +1,17 @@
import React from 'react'; import React from 'react';
import { import {
View, View,
Text, Text,
StatusBar, StatusBar,
SafeAreaView, SafeAreaView,
ScrollView, ScrollView,
TouchableOpacity, TouchableOpacity,
Dimensions, Dimensions,
ImageBackground, ImageBackground,
findNodeHandle, findNodeHandle,
Alert, Alert,
StyleSheet, StyleSheet,
Image, Image,
} from 'react-native'; } from 'react-native';
import update from 'react-addons-update'; import update from 'react-addons-update';
import Hcef from '../module/Hcef'; import Hcef from '../module/Hcef';
@ -20,293 +20,397 @@ import AsyncStorage from '@react-native-community/async-storage';
import Icon from 'react-native-vector-icons/MaterialIcons'; import Icon from 'react-native-vector-icons/MaterialIcons';
import i18n from 'i18n-js'; import i18n from 'i18n-js';
const RNFS = require('react-native-fs'); const RNFS = require('react-native-fs');
class Card extends React.Component { class Card extends React.Component {
async onPress() { async onPress() {
this.props.onPress(this.props.card, this.props.index); this.props.onPress(this.props.card, this.props.index);
}
async disable() {
if (typeof this.props.disableCallback === 'function') {
this.props.disableCallback(this.props.card, this.props.index);
} }
}
async disable(){ render() {
if(typeof this.props.disableCallback === 'function') let cardContent = (
this.props.disableCallback(this.props.card, this.props.index); <View
} style={{flex: 1, backgroundColor: 'rgba(0,0,0,0.3)', borderRadius: 8}}>
<View style={{flex: 1}}>
<TouchableOpacity style={{flex: 1}} onPress={this.onPress.bind(this)}>
<Text
style={{
position: 'absolute',
top: 20,
left: 20,
fontSize: 17,
fontWeight: 'bold',
color: '#ffffff',
}}>
{this.props.card.name}
</Text>
render() { <View style={{flex: 1, justifyContent: 'center', paddingTop: 20}}>
let cardContent = ( <Text
<View style={{flex: 1, backgroundColor:'rgba(0,0,0,0.3)', borderRadius:8}}> style={{
<View style={{flex: 1,}}> paddingTop: 0,
<TouchableOpacity style={{flex: 1}} onPress={this.onPress.bind(this)}> textAlign: 'center',
<Text style={{position: 'absolute', top: 20, left: 20, fontSize: 17, fontWeight:'bold', color:'#ffffff'}}> alignSelf: 'center',
{this.props.card.name} color: '#E0E0E0',
</Text> fontSize: 14,
}}>
<View style={{flex: 1, justifyContent:'center', paddingTop: 20,}}> {this.props.card.uid.substr(0, 4) +
<Text style={{paddingTop: 0, textAlign: 'center', alignSelf: 'center', color: '#E0E0E0', fontSize: 14 }}> '-' +
{this.props.card.uid.substr(0,4)+'-'+this.props.card.uid.substr(4,4)+'-'+this.props.card.uid.substr(8,4)+'-'+this.props.card.uid.substr(12,4)} this.props.card.uid.substr(4, 4) +
</Text> '-' +
<Text style={{paddingTop: 8, textAlign: 'center', alignSelf: 'center', fontSize: 24, color:'#FAFAFA', fontWeight: '500', letterSpacing:-0.5}}> this.props.card.uid.substr(8, 4) +
{this.props.card.enabled ? i18n.t('card_touch_to_disable') : i18n.t('card_touch_to_enable')} '-' +
</Text> this.props.card.uid.substr(12, 4)}
</View> </Text>
</TouchableOpacity> <Text
</View> style={{
<View style={{height: 1, backgroundColor: '#FAFAFA'}}/> paddingTop: 8,
<View style={{height: 48, flexDirection: 'row'}}> textAlign: 'center',
<TouchableOpacity style={{ alignSelf: 'center',
flex: 1, fontSize: 24,
alignItems: 'center', color: '#FAFAFA',
justifyContent: 'center', fontWeight: '500',
}} onPress={() => this.props.navigation.navigate('CardEditScreen', {name: this.props.card.name, sid: this.props.card.sid, image: this.props.card.image, index: this.props.index, update: this.props.update})}> letterSpacing: -0.5,
<Text style={{fontSize: 14, color:'#FAFAFA'}}>{i18n.t('card_edit')}</Text> }}>
</TouchableOpacity> {this.props.card.enabled
<View style={{width: 1, backgroundColor: '#FAFAFA'}}/> ? i18n.t('card_touch_to_disable')
<TouchableOpacity style={{ : i18n.t('card_touch_to_enable')}
flex: 1, </Text>
alignItems: 'center',
justifyContent: 'center',
}} onPress={() => this.props.delete(this.props.index)}>
<Text style={{fontSize: 14, color:'#ffffff'}}>{i18n.t('card_delete')}</Text>
</TouchableOpacity>
</View>
</View> </View>
); </TouchableOpacity>
</View>
<View style={{height: 1, backgroundColor: '#FAFAFA'}} />
<View style={{height: 48, flexDirection: 'row'}}>
<TouchableOpacity
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}
onPress={() =>
this.props.navigation.navigate('CardEditScreen', {
name: this.props.card.name,
sid: this.props.card.sid,
image: this.props.card.image,
index: this.props.index,
update: this.props.update,
})
}>
<Text style={{fontSize: 14, color: '#FAFAFA'}}>
{i18n.t('card_edit')}
</Text>
</TouchableOpacity>
<View style={{width: 1, backgroundColor: '#FAFAFA'}} />
<TouchableOpacity
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}
onPress={() => this.props.delete(this.props.index)}>
<Text style={{fontSize: 14, color: '#ffffff'}}>
{i18n.t('card_delete')}
</Text>
</TouchableOpacity>
</View>
</View>
);
return ( return (
<View style={[{ <View
style={[
{
borderRadius: 8, borderRadius: 8,
height: this.props.cardHeight, height: this.props.cardHeight,
marginTop: 24, marginTop: 24,
marginHorizontal: 24, marginHorizontal: 24,
justifyContent: 'center', justifyContent: 'center',
},]}> },
{this.props.card.image ? ( ]}>
<ImageBackground {this.props.card.image ? (
source={{uri: this.props.card.image}} <ImageBackground
style={{ source={{uri: this.props.card.image}}
flex: 1, style={{
resizeMode:'contain', flex: 1,
}} resizeMode: 'contain',
blurRadius={2} }}
borderRadius={8}> blurRadius={2}
{cardContent} borderRadius={8}>
</ImageBackground> {cardContent}
) : ( </ImageBackground>
<View ) : (
style={{ <View
flex: 1, style={{
resizeMode:'contain', flex: 1,
backgroundColor: '#03A9F4', resizeMode: 'contain',
}} backgroundColor: '#03A9F4',
blurRadius={2} }}
borderRadius={8}> blurRadius={2}
{cardContent} borderRadius={8}>
</View> {cardContent}
)} </View>
</View> )}
); </View>
} );
}
} }
class MainScreen extends React.Component { class MainScreen extends React.Component {
state = { state = {
cards: [], cards: [],
cardHeight: 1, cardHeight: 1,
support: false, support: false,
}; };
async loadCards(){ async loadCards() {
let cardsJson = await AsyncStorage.getItem('cards'); let cardsJson = await AsyncStorage.getItem('cards');
this.setState({cards: cardsJson ? JSON.parse(cardsJson) : []}); this.setState({cards: cardsJson ? JSON.parse(cardsJson) : []});
}
componentDidMount() {
this.prevCard = null;
this.prevIndex = -1;
this.loadCards();
if (Hcef.support !== true) {
Alert.alert(
i18n.t('alert_not_support_title'),
i18n.t('alert_not_support_content'),
[{text: i18n.t('alert_not_support_yes')}],
);
} else if (Hcef.enabled !== true) {
Alert.alert(i18n.t('alert_nfc_title'), i18n.t('alert_nfc_content'), [
{text: i18n.t('alert_nfc_yes')},
]);
} }
componentDidMount(){ if (Hcef.support && Hcef.enabled) {
this.prevCard = null; Hcef.disableService(); // 카드를 활성화하지 않았는데도 카드가 에뮬되는 이슈 방지
this.prevIndex = -1; }
this.loadCards();
if(Hcef.support !== true){ let {height, width} = Dimensions.get('window');
Alert.alert(i18n.t('alert_not_support_title'), i18n.t('alert_not_support_content'),
[{text: i18n.t('alert_not_support_yes')}]);
}
else if(Hcef.enabled !== true){
Alert.alert(i18n.t('alert_nfc_title'), i18n.t('alert_nfc_content'),
[{text: i18n.t('alert_nfc_yes')}]);
}
if(Hcef.support && Hcef.enabled){ this.setState({
Hcef.disableService(); // 카드를 활성화하지 않았는데도 카드가 에뮬되는 이슈 방지 cardHeight: ((width - 48) * 53.98) / 85.6,
} });
}
let {height, width} = (Dimensions.get('window')); async switch(card, index) {
if (!Hcef.support || !Hcef.enabled) {
return;
}
if (card.enabled === true) {
this.disable(card, index);
} else {
this.enable(card, index);
}
}
async enable(card, index) {
if (this.prevCard && this.prevCard.enabled) {
await this.disable(this.prevCard, this.prevIndex);
}
let ret = false;
let ret2 = false;
ret = await Hcef.setSID(card.sid);
if (ret) {
ret2 = await Hcef.enableService();
}
if (ret && ret2) {
this.prevCard = card;
this.prevCard.enabled = true;
this.prevIndex = index;
this.setState({
cards: update(this.state.cards, {[index]: {enabled: {$set: true}}}),
});
}
}
async disable(card, index) {
if (card.enabled) {
let ret = await Hcef.disableService();
if (ret) {
card.enabled = false;
this.setState({ this.setState({
cardHeight: (width - 48) * 53.98 / 85.60 cards: update(this.state.cards, {[index]: {enabled: {$set: false}}}),
}); });
return true;
}
}
return false;
}
async cardListUpdate(name, sid, index, image, navigation) {
let uid = await CardConv.convertSID(sid);
let internalPath = '';
if (image !== '') {
internalPath = RNFS.DocumentDirectoryPath + '/' + new Date().valueOf();
if (image.startsWith('file://')) {
image = image.replace('file://', '');
}
await RNFS.copyFile(image, internalPath);
internalPath = 'file://' + internalPath;
} }
async switch(card, index){ if (index === null) {
if(!Hcef.support || !Hcef.enabled) return; this.setState(
{
if(card.enabled === true) cards: update(this.state.cards, {
this.disable(card, index); $push: [{name: name, sid: sid, uid: uid, image: internalPath}],
else }),
this.enable(card, index); },
async () => {
await AsyncStorage.setItem('cards', JSON.stringify(this.state.cards));
},
);
} else {
this.setState(
{
cards: update(this.state.cards, {
[index]: {
name: {$set: name},
sid: {$set: sid},
uid: {$set: uid},
image: {$set: internalPath},
},
}),
},
async () => {
await AsyncStorage.setItem('cards', JSON.stringify(this.state.cards));
},
);
} }
async enable(card, index){ Alert.alert('', i18n.t('alert_save_content'), [
if(this.prevCard && this.prevCard.enabled) { {
await this.disable(this.prevCard, this.prevIndex); text: i18n.t('alert_save_yes'),
} onPress: () => {
navigation.goBack();
},
},
]);
}
let ret = false; cardListDelete(index) {
let ret2 = false; Alert.alert(i18n.t('alert_delete_title'), i18n.t('alert_delete_content'), [
{text: i18n.t('alert_delete_no')},
{
text: i18n.t('alert_delete_yes'),
onPress: () => {
if (this.state.cards[index].image !== '') {
RNFS.unlink(this.state.cards[index].image);
}
this.setState(
{
cards: update(this.state.cards, {
$splice: [[index, 1]],
}),
},
async () => {
await AsyncStorage.setItem(
'cards',
JSON.stringify(this.state.cards),
);
},
);
},
},
]);
}
ret = await Hcef.setSID(card.sid); render() {
if(ret){ let cardWidget = [];
ret2 = await Hcef.enableService();
}
if(ret && ret2){ this.state.cards.forEach((card, index) => {
this.prevCard = card; cardWidget.push(
this.prevCard.enabled = true; <Card
this.prevIndex = index; card={card}
this.setState({cards: update(this.state.cards, { [index]: { enabled: { $set: true } }})}); index={index}
} onPress={(card, index) => this.switch(card, index)}
} cardHeight={this.state.cardHeight}
disableCallback={(card, index) => this.disable(card, index)}
update={(name, sid, index, image, navigation) =>
this.cardListUpdate(name, sid, index, image, navigation)
}
delete={index => this.cardListDelete(index)}
navigation={this.props.navigation}
/>,
);
});
async disable(card, index){ return (
if(card.enabled){ <SafeAreaView style={{flex: 1, paddingTop: StatusBar.currentHeight}}>
let ret = await Hcef.disableService(); <StatusBar
if(ret){ barStyle="dark-content"
card.enabled = false; translucent={true}
this.setState({cards: update(this.state.cards, { [index]: { enabled: { $set: false } }})}); backgroundColor={'#ffffff'}
return true; />
} <View
} style={{
return false; height: 48,
} flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ffffff',
}}>
<View
style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text
style={{
fontSize: 17,
fontWeight: 'bold',
textAlignVertical: 'center',
}}>
{i18n.t('header_home')}
</Text>
async cardListUpdate(name, sid, index, image, navigation){ <TouchableOpacity
let uid = await CardConv.convertSID(sid); style={{
let internalPath = ''; position: 'absolute',
top: 0,
bottom: 0,
right: 12,
alignItems: 'center',
justifyContent: 'center',
}}
onPress={() =>
this.props.navigation.navigate('CardEditScreen', {
update: (name, sid, index, image, navigation) =>
this.cardListUpdate(name, sid, index, image, navigation),
})
}>
<Icon name="add" size={26} color={'rgba(0,0,0,0.7)'} />
</TouchableOpacity>
</View>
</View>
if(image !== ''){ {this.state.cards && this.state.cards.length > 0 ? (
internalPath = RNFS.DocumentDirectoryPath + '/' + new Date().valueOf(); <ScrollView style={{flex: 1}}>{cardWidget}</ScrollView>
) : (
if(image.startsWith('file://')){ <View
image = image.replace("file://",''); style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
} <Text style={{fontSize: 17, color: '#9E9E9E'}}>
{i18n.t('main_empty_string')}
await RNFS.copyFile(image, internalPath); </Text>
</View>
internalPath = 'file://' + internalPath; )}
} </SafeAreaView>
);
if(index === null){ }
this.setState({cards: update(this.state.cards, { $push: [{name: name, sid: sid, uid: uid, image: internalPath}]})},
async () => {
await AsyncStorage.setItem('cards', JSON.stringify(this.state.cards));
});
}
else{
this.setState({cards: update(this.state.cards, { [index]: { name: {$set: name}, sid: {$set: sid}, uid: {$set: uid}, image: {$set: internalPath} }})},
async () =>{
await AsyncStorage.setItem('cards', JSON.stringify(this.state.cards));
});
}
Alert.alert("", i18n.t('alert_save_content'),
[{text: i18n.t('alert_save_yes'), onPress: () => {navigation.goBack();}}]);
}
cardListDelete(index){
Alert.alert(i18n.t('alert_delete_title'),i18n.t('alert_delete_content')
, [
{text: i18n.t('alert_delete_no')},
{text: i18n.t('alert_delete_yes'), onPress: () => {
if(this.state.cards[index].image !== '' ){
RNFS.unlink(this.state.cards[index].image);
}
this.setState({
cards: update(this.state.cards, {
$splice: [[index, 1]]
})
}, async () => {
await AsyncStorage.setItem('cards', JSON.stringify(this.state.cards));
}
);
}}]
);
}
render() {
let cardWidget = [];
this.state.cards.forEach((card, index) => {
cardWidget.push(
<Card card={card} index={index}
onPress={(card, index) => this.switch(card, index)} cardHeight={this.state.cardHeight}
disableCallback={(card, index) => this.disable(card, index)}
update={(name, sid, index, image, navigation) => this.cardListUpdate(name, sid, index, image, navigation)}
delete={(index) => this.cardListDelete(index)}
navigation={this.props.navigation}
/>);
});
return (
<SafeAreaView style={{flex: 1, paddingTop: StatusBar.currentHeight}}>
<StatusBar
barStyle='dark-content'
translucent={true}
backgroundColor={'#ffffff'}
/>
<View style={{
height: 48,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ffffff',
}}>
<View style={{flex: 1, alignItems: 'center',
justifyContent: 'center',}}>
<Text style={{
fontSize: 17,
fontWeight: 'bold',
textAlignVertical: 'center',
}}>
{i18n.t('header_home')}
</Text>
<TouchableOpacity style={{
position: 'absolute',
top: 0,
bottom: 0,
right: 12,
alignItems: 'center',
justifyContent: 'center',
}} onPress={() => this.props.navigation.navigate('CardEditScreen',{ update:(name, sid, index, image, navigation) => this.cardListUpdate(name, sid, index, image, navigation)})}
>
<Icon name='add' size={26} color={'rgba(0,0,0,0.7)'}/>
</TouchableOpacity>
</View>
</View>
{this.state.cards && this.state.cards.length > 0 ? (
<ScrollView style={{flex: 1,}}>
{cardWidget}
</ScrollView>
) : (
<View style={{flex:1, justifyContent: 'center', alignItems:'center'}}>
<Text style={{fontSize: 17, color: '#9E9E9E', }}>{i18n.t('main_empty_string')}</Text>
</View>
)
}
</SafeAreaView>
)
}
} }
export default MainScreen; export default MainScreen;