1
0
mirror of synced 2025-01-30 19:43:44 +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
View File

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

View File

@ -1,39 +1,41 @@
export default {
header_home: 'Home',
header_add: 'Add',
header_edit: 'Edit',
header_home: 'Home',
header_add: 'Add',
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_preview: 'Preview',
edit_sid_notice: 'SID is 16-digit hexadecimal number. Note that it is not a card number!',
edit_random: 'Random Generate',
edit_preview: 'Preview',
edit_sid_notice:
'SID is 16-digit hexadecimal number. Note that it is not a card number!',
edit_background: 'Background',
edit_background_empty: 'Touch here to select the background image',
edit_background_selected: 'The image has been selected',
edit_background: 'Background',
edit_background_empty: 'Touch here to select the background image',
edit_background_selected: 'The image has been selected',
edit_name: 'Name',
edit_name: 'Name',
alert_delete_title: 'Delete',
alert_delete_content: 'Do you want to delete this card?',
alert_delete_yes: 'Yes',
alert_delete_no: 'No',
alert_delete_title: 'Delete',
alert_delete_content: 'Do you want to delete this card?',
alert_delete_yes: 'Yes',
alert_delete_no: 'No',
alert_save_content: 'Card saved successfully.',
alert_save_yes: 'OK',
alert_save_content: 'Card saved successfully.',
alert_save_yes: 'OK',
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_yes: 'OK',
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_yes: 'OK',
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_yes: 'OK',
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_yes: 'OK',
card_touch_to_enable: 'Touch to enable',
card_touch_to_disable: 'Touch to disable',
card_delete: 'Delete',
card_edit: 'Edit',
}
card_touch_to_enable: 'Touch to enable',
card_touch_to_disable: 'Touch to disable',
card_delete: 'Delete',
card_edit: 'Edit',
};

View File

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

View File

@ -1,19 +1,19 @@
import React from 'react';
import {
View,
Text,
StatusBar,
SafeAreaView,
ScrollView,
TouchableOpacity,
Dimensions,
ImageBackground,
findNodeHandle,
Alert,
StyleSheet,
Image,
KeyboardAvoidingView,
TextInput,
View,
Text,
StatusBar,
SafeAreaView,
ScrollView,
TouchableOpacity,
Dimensions,
ImageBackground,
findNodeHandle,
Alert,
StyleSheet,
Image,
KeyboardAvoidingView,
TextInput,
} from 'react-native';
import update from 'react-addons-update';
import Icon from 'react-native-vector-icons/MaterialIcons';
@ -22,368 +22,547 @@ import CardConv from '../module/CardConv';
import i18n from 'i18n-js';
class CardPreview extends React.Component {
render() {
let cardContent = (
<View style={{flex: 1, backgroundColor:'rgba(0,0,0,0.3)', borderRadius:8}}>
<View style={{flex: 1,}}>
<TouchableOpacity style={{flex: 1}}>
<Text style={{position: 'absolute', top: 20, left: 20, fontSize: 17, fontWeight:'bold', color:'#ffffff'}}>
{this.props.name}
</Text>
<View style={{flex: 1, justifyContent:'center', paddingTop: 20,}}>
<Text style={{paddingTop: 0, textAlign: 'center', alignSelf: 'center', color: '#E0E0E0', fontSize: 14 }}>
{this.props.uid ?
this.props.uid.substr(0,4)+'-'+this.props.uid.substr(4,4)+'-'+this.props.uid.substr(8,4)+'-'+this.props.uid.substr(12,4)
: ''
}
</Text>
<Text style={{paddingTop: 8, textAlign: 'center', alignSelf: 'center', fontSize: 24, color:'#FAFAFA', fontWeight: '500', letterSpacing:-0.5}}>
{i18n.t('card_touch_to_enable')}
</Text>
</View>
</TouchableOpacity>
</View>
<View style={{height: 1, backgroundColor: '#FAFAFA'}}/>
<View style={{height: 48, flexDirection: 'row'}}>
<TouchableOpacity style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}>
<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',
}}>
<Text style={{fontSize: 14, color:'#ffffff'}}>{i18n.t('card_delete')}</Text>
</TouchableOpacity>
</View>
render() {
let cardContent = (
<View
style={{flex: 1, backgroundColor: 'rgba(0,0,0,0.3)', borderRadius: 8}}>
<View style={{flex: 1}}>
<TouchableOpacity style={{flex: 1}}>
<Text
style={{
position: 'absolute',
top: 20,
left: 20,
fontSize: 17,
fontWeight: 'bold',
color: '#ffffff',
}}>
{this.props.name}
</Text>
<View style={{flex: 1, justifyContent: 'center', paddingTop: 20}}>
<Text
style={{
paddingTop: 0,
textAlign: 'center',
alignSelf: 'center',
color: '#E0E0E0',
fontSize: 14,
}}>
{this.props.uid
? this.props.uid.substr(0, 4) +
'-' +
this.props.uid.substr(4, 4) +
'-' +
this.props.uid.substr(8, 4) +
'-' +
this.props.uid.substr(12, 4)
: ''}
</Text>
<Text
style={{
paddingTop: 8,
textAlign: 'center',
alignSelf: 'center',
fontSize: 24,
color: '#FAFAFA',
fontWeight: '500',
letterSpacing: -0.5,
}}>
{i18n.t('card_touch_to_enable')}
</Text>
</View>
)
return (
<View style={[{
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>
);
}
</TouchableOpacity>
</View>
<View style={{height: 1, backgroundColor: '#FAFAFA'}} />
<View style={{height: 48, flexDirection: 'row'}}>
<TouchableOpacity
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}>
<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',
}}>
<Text style={{fontSize: 14, color: '#ffffff'}}>
{i18n.t('card_delete')}
</Text>
</TouchableOpacity>
</View>
</View>
);
return (
<View
style={[
{
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 {
state = {
focused: false,
value: this.props.value ?? '',
};
state = {
focused: false,
value: this.props.value ?? '',
};
onFocusCallback(){
this.setState({focused: true});
if(typeof this.props.onFocus === 'function')
this.props.onFocus();
onFocusCallback() {
this.setState({focused: true});
if (typeof this.props.onFocus === 'function') {
this.props.onFocus();
}
}
onBlurCallback(){
this.setState({focused: false});
if(typeof this.props.onBlur === 'function')
this.props.onBlur();
onBlurCallback() {
this.setState({focused: false});
if (typeof this.props.onBlur === 'function') {
this.props.onBlur();
}
}
onChangeTextCallback(text){
if(typeof this.props.filter === 'function')
text = this.props.filter(text);
if(typeof this.props.onChangeText === 'function')
this.props.onChangeText(text);
onChangeTextCallback(text) {
if (typeof this.props.filter === 'function') {
text = this.props.filter(text);
}
focus(){
this.textInput.focus();
if (typeof this.props.onChangeText === 'function') {
this.props.onChangeText(text);
}
}
render() {
return (
<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>
focus() {
this.textInput.focus();
}
<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}
>
</TextInput>
<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>
)
}
render() {
return (
<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
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 {
state = {
name: this.props.navigation.getParam('name', ''),
sidAll: this.props.navigation.getParam('sid', '02FE'),
sid2: '',
sid3: '',
sid4: '',
uid: '',
sidError: false,
state = {
name: this.props.navigation.getParam('name', ''),
sidAll: this.props.navigation.getParam('sid', '02FE'),
sid2: '',
sid3: '',
sid4: '',
uid: '',
sidError: false,
image: this.props.navigation.getParam('image', ''),
index: this.props.navigation.getParam('index', null), // null 이면 카드 새로 생성
mode: '',
image: this.props.navigation.getParam('image', ''),
index: this.props.navigation.getParam('index', null), // null 이면 카드 새로 생성
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 {
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();
}
if(this.state.index === null){
this.setState({mode: 'add', sid2: randomHex4Byte(), sid3: randomHex4Byte(), sid4: randomHex4Byte(), cardHeight: (width - 48) * 53.98 / 85.60,},
() => this.updateSID());
}
else{
this.setState({
mode: 'edit',
sid2: this.state.sidAll.substr(4, 4),
sid3: this.state.sidAll.substr(8, 4),
sid4: this.state.sidAll.substr(12, 4),
cardHeight: (width - 48) * 53.98 / 85.60,
}, () => {
this.updateSID();
});
}
this.nameInput.focus();
if (this.state.index === null) {
this.setState(
{
mode: 'add',
sid2: randomHex4Byte(),
sid3: randomHex4Byte(),
sid4: randomHex4Byte(),
cardHeight: ((width - 48) * 53.98) / 85.6,
},
() => this.updateSID(),
);
} else {
this.setState(
{
mode: 'edit',
sid2: this.state.sidAll.substr(4, 4),
sid3: this.state.sidAll.substr(8, 4),
sid4: this.state.sidAll.substr(12, 4),
cardHeight: ((width - 48) * 53.98) / 85.6,
},
() => {
this.updateSID();
},
);
}
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 '';
}
this.nameInput.focus();
}
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(){
if(this.makeSid() !== ''){
let uid = await CardConv.convertSID(this.makeSid());
this.setState({uid: uid});
}
return sid;
}
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(){
let sid = this.makeSid();
if (typeof this.state.update === 'function') {
this.state.update(
this.state.name,
sid,
this.state.index,
this.state.image,
this.props.navigation,
);
}
}
if(sid === ''){
this.setState({sidError: true});
return ;
}
setRandomSid() {
function randomHex4Byte() {
let hexString = Math.min(
Math.floor(Math.random() * 65536),
65535,
).toString(16);
if(typeof this.state.update === 'function'){
this.state.update(this.state.name, sid, this.state.index, this.state.image, this.props.navigation);
}
if (hexString.length < 4) {
hexString = '0'.repeat(4 - hexString.length) + hexString;
}
return hexString.toUpperCase();
}
setRandomSid(){
function randomHex4Byte(){
let hexString = Math.min(Math.floor(Math.random() * 65536), 65535).toString(16);
this.setState(
{sid2: randomHex4Byte(), sid3: randomHex4Byte(), sid4: randomHex4Byte()},
() => this.updateSID(),
);
}
if(hexString.length < 4)
hexString = '0'.repeat(4 - hexString.length) + hexString;
selectPhoto() {
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(){
ImagePicker.openPicker({
cropping: true,
width: 856,
height: 540,
mediaType: 'photo',
}).then(res => {
if(res && res.path){
this.setState({image: res.path,});
}
});
}
<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>
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>
<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}
/>
<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>
<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>
)
}
<View style={{height: 50}} />
</ScrollView>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
}
export default CardEditScreen;

View File

@ -1,17 +1,17 @@
import React from 'react';
import {
View,
Text,
StatusBar,
SafeAreaView,
ScrollView,
TouchableOpacity,
Dimensions,
ImageBackground,
findNodeHandle,
Alert,
StyleSheet,
Image,
View,
Text,
StatusBar,
SafeAreaView,
ScrollView,
TouchableOpacity,
Dimensions,
ImageBackground,
findNodeHandle,
Alert,
StyleSheet,
Image,
} from 'react-native';
import update from 'react-addons-update';
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 i18n from 'i18n-js';
const RNFS = require('react-native-fs');
class Card extends React.Component {
async onPress() {
this.props.onPress(this.props.card, this.props.index);
async onPress() {
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(){
if(typeof this.props.disableCallback === 'function')
this.props.disableCallback(this.props.card, this.props.index);
}
render() {
let cardContent = (
<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() {
let cardContent = (
<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>
<View style={{flex: 1, justifyContent:'center', paddingTop: 20,}}>
<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)}
</Text>
<Text style={{paddingTop: 8, textAlign: 'center', alignSelf: 'center', fontSize: 24, color:'#FAFAFA', fontWeight: '500', letterSpacing:-0.5}}>
{this.props.card.enabled ? i18n.t('card_touch_to_disable') : i18n.t('card_touch_to_enable')}
</Text>
</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 style={{flex: 1, justifyContent: 'center', paddingTop: 20}}>
<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)}
</Text>
<Text
style={{
paddingTop: 8,
textAlign: 'center',
alignSelf: 'center',
fontSize: 24,
color: '#FAFAFA',
fontWeight: '500',
letterSpacing: -0.5,
}}>
{this.props.card.enabled
? i18n.t('card_touch_to_disable')
: i18n.t('card_touch_to_enable')}
</Text>
</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 (
<View style={[{
return (
<View
style={[
{
borderRadius: 8,
height: this.props.cardHeight,
marginTop: 24,
marginHorizontal: 24,
justifyContent: 'center',
},]}>
{this.props.card.image ? (
<ImageBackground
source={{uri: this.props.card.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>
);
}
},
]}>
{this.props.card.image ? (
<ImageBackground
source={{uri: this.props.card.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 MainScreen extends React.Component {
state = {
cards: [],
cardHeight: 1,
support: false,
};
state = {
cards: [],
cardHeight: 1,
support: false,
};
async loadCards(){
let cardsJson = await AsyncStorage.getItem('cards');
this.setState({cards: cardsJson ? JSON.parse(cardsJson) : []});
async loadCards() {
let cardsJson = await AsyncStorage.getItem('cards');
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(){
this.prevCard = null;
this.prevIndex = -1;
this.loadCards();
if (Hcef.support && Hcef.enabled) {
Hcef.disableService(); // 카드를 활성화하지 않았는데도 카드가 에뮬되는 이슈 방지
}
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')}]);
}
let {height, width} = Dimensions.get('window');
if(Hcef.support && Hcef.enabled){
Hcef.disableService(); // 카드를 활성화하지 않았는데도 카드가 에뮬되는 이슈 방지
}
this.setState({
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({
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(!Hcef.support || !Hcef.enabled) return;
if(card.enabled === true)
this.disable(card, index);
else
this.enable(card, index);
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));
},
);
}
async enable(card, index){
if(this.prevCard && this.prevCard.enabled) {
await this.disable(this.prevCard, this.prevIndex);
}
Alert.alert('', i18n.t('alert_save_content'), [
{
text: i18n.t('alert_save_yes'),
onPress: () => {
navigation.goBack();
},
},
]);
}
let ret = false;
let ret2 = false;
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),
);
},
);
},
},
]);
}
ret = await Hcef.setSID(card.sid);
if(ret){
ret2 = await Hcef.enableService();
}
render() {
let cardWidget = [];
if(ret && ret2){
this.prevCard = card;
this.prevCard.enabled = true;
this.prevIndex = index;
this.setState({cards: update(this.state.cards, { [index]: { enabled: { $set: true } }})});
}
}
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}
/>,
);
});
async disable(card, index){
if(card.enabled){
let ret = await Hcef.disableService();
if(ret){
card.enabled = false;
this.setState({cards: update(this.state.cards, { [index]: { enabled: { $set: false } }})});
return true;
}
}
return false;
}
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>
async cardListUpdate(name, sid, index, image, navigation){
let uid = await CardConv.convertSID(sid);
let internalPath = '';
<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>
if(image !== ''){
internalPath = RNFS.DocumentDirectoryPath + '/' + new Date().valueOf();
if(image.startsWith('file://')){
image = image.replace("file://",'');
}
await RNFS.copyFile(image, internalPath);
internalPath = 'file://' + internalPath;
}
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>
)
}
{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;