Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#161224146] Refactor light identification #658

Merged
merged 7 commits into from
Oct 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ android {
}

dependencies {
compile project(':react-native-background-timer')
compile project(':instabug-reactnative')
compile project(':react-native-add-calendar-event')
compile project(':react-native-svg')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package it.teamdigitale.app.italiaapp;

import android.os.Bundle;
import android.view.WindowManager;
import com.facebook.react.ReactActivity;
import org.devio.rn.splashscreen.SplashScreen;

Expand All @@ -18,6 +19,8 @@ protected String getMainComponentName() {
// see https://github.com/crazycodeboy/react-native-splash-screen#third-stepplugin-configuration
@Override
protected void onCreate(Bundle savedInstanceState) {
// To avoid data leak disable preview of the window when application is in background
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,WindowManager.LayoutParams.FLAG_SECURE);
SplashScreen.show(this, R.style.SplashScreenTheme);
super.onCreate(savedInstanceState);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.learnium.RNDeviceInfo.RNDeviceInfo;
import com.lugg.ReactNativeConfig.ReactNativeConfigPackage;
import com.facebook.react.ReactApplication;
import com.ocetnik.timer.BackgroundTimerPackage;
import com.instabug.reactlibrary.RNInstabugReactnativePackage;
import com.vonovak.AddCalendarEventPackage;
import com.horcrux.svg.SvgPackage;
Expand Down Expand Up @@ -39,6 +40,7 @@ public boolean getUseDeveloperSupport() {
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new BackgroundTimerPackage(),
new RNInstabugReactnativePackage.Builder(BuildConfig.INSTABUG_TOKEN, MainApplication.this)
.setInvocationEvent("none")
.setPrimaryColor("#0073E6")
Expand Down
2 changes: 2 additions & 0 deletions android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
rootProject.name = 'ItaliaApp'
include ':react-native-background-timer'
project(':react-native-background-timer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-background-timer/android')
include ':instabug-reactnative'
project(':instabug-reactnative').projectDir = new File(rootProject.projectDir, '../node_modules/instabug-reactnative/android')
include ':react-native-add-calendar-event'
Expand Down
30 changes: 30 additions & 0 deletions ios/ItaliaApp/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,34 @@ - (void)application:(UIApplication *)application didReceiveLocalNotification:(UI
[RCTPushNotificationManager didReceiveLocalNotification:notification];
}

- (void)applicationWillResignActive:(UIApplication *)application {

// Fill screen with our own colour
UIView *colourView = [[UIView alloc]initWithFrame:self.window.frame];
colourView.backgroundColor = [UIColor whiteColor];
colourView.tag = 1234;
colourView.alpha = 0;
[self.window addSubview:colourView];
[self.window bringSubviewToFront:colourView];

// Fade in the view
[UIView animateWithDuration:0.5 animations:^{
colourView.alpha = 1;
}];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {

// Grab a reference to our coloured view
UIView *colourView = [self.window viewWithTag:1234];

// Fade away colour view from main view
[UIView animateWithDuration:0.5 animations:^{
colourView.alpha = 0;
} completion:^(BOOL finished) {
// Remove when finished fading
[colourView removeFromSuperview];
}];
}

@end
2 changes: 2 additions & 0 deletions ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ target 'ItaliaApp' do

pod 'react-native-add-calendar-event', :path => '../node_modules/react-native-add-calendar-event'

pod 'react-native-background-timer', :path => '../node_modules/react-native-background-timer'

end

# Fix a open bug in react-native-config
Expand Down
8 changes: 7 additions & 1 deletion ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ PODS:
- React/Core (= 0.55.4)
- react-native-add-calendar-event (2.1.0):
- React
- react-native-background-timer (2.0.1):
- React
- react-native-camera (1.2.0):
- React
- react-native-camera/RCT (= 1.2.0)
Expand Down Expand Up @@ -71,6 +73,7 @@ PODS:

DEPENDENCIES:
- react-native-add-calendar-event (from `../node_modules/react-native-add-calendar-event`)
- react-native-background-timer (from `../node_modules/react-native-background-timer`)
- react-native-camera (from `../node_modules/react-native-camera`)
- react-native-config (from `../node_modules/react-native-config`)
- react-native-mixpanel (from `../node_modules/react-native-mixpanel`)
Expand Down Expand Up @@ -106,6 +109,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native"
react-native-add-calendar-event:
:path: "../node_modules/react-native-add-calendar-event"
react-native-background-timer:
:path: "../node_modules/react-native-background-timer"
react-native-camera:
:path: "../node_modules/react-native-camera"
react-native-config:
Expand Down Expand Up @@ -135,6 +140,7 @@ SPEC CHECKSUMS:
Mixpanel: 3c3925c27f7a321d5978319a72f53f8f0885afc5
React: aa2040dbb6f317b95314968021bd2888816e03d5
react-native-add-calendar-event: e3415a2d8a782e06899be6fb59427199eba1ab82
react-native-background-timer: bb7a98c8e97fc7c290de2d423dd09ddb73dcbcbb
react-native-camera: 68ad5143d2d0636236d46c7de8d2a6455ca52a36
react-native-config: 408003951fd9d8b1dfd7ebf535f67c315f44d823
react-native-mixpanel: 0683bc3f3f8db8f9d79a8ba8584ee51030338a2f
Expand All @@ -148,6 +154,6 @@ SPEC CHECKSUMS:
RNVectorIcons: c0dbfbf6068fefa240c37b0f71bd03b45dddac44
yoga: a23273df0088bf7f2bb7e5d7b00044ea57a2a54a

PODFILE CHECKSUM: 3316adb921ccdc510910aca8601549f22fd3234e
PODFILE CHECKSUM: 7baf54ac28b13a0b19cb8d2964f16af6425333e3

COCOAPODS: 1.5.3
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"react": "16.3.1",
"react-native": "0.55.4",
"react-native-add-calendar-event": "^2.1.0",
"react-native-background-timer": "^2.0.1",
"react-native-camera": "1.2.0",
"react-native-config": "^0.11.2",
"react-native-device-info": "^0.22",
Expand Down Expand Up @@ -85,6 +86,7 @@
"@types/prettier": "^1.13.2",
"@types/react": "16.3.16",
"@types/react-native": "0.55.17",
"@types/react-native-background-timer": "^2.0.0",
"@types/react-native-fs": "^2.8.2",
"@types/react-native-i18n": "^2.0.0",
"@types/react-native-loading-spinner-overlay": "^0.5.1",
Expand Down
10 changes: 10 additions & 0 deletions patches/react-native-background-timer+2.0.1.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
patch-package
--- a/node_modules/react-native-background-timer/react-native-background-timer.podspec
+++ b/node_modules/react-native-background-timer/react-native-background-timer.podspec
@@ -19,4 +19,6 @@ Pod::Spec.new do |s|
s.preserve_paths = 'README.md', 'package.json', 'index.js'
s.source_files = 'ios/*.{h,m}'

+ s.dependency 'React'
+
end
201 changes: 201 additions & 0 deletions ts/IdentificationOverlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import { Button, Content, Text, View } from "native-base";
import * as React from "react";
import { Dimensions, StatusBar, StyleSheet } from "react-native";
import { connect } from "react-redux";

import Pinpad from "./components/Pinpad";
import BaseScreenComponent from "./components/screens/BaseScreenComponent";
import IconFont from "./components/ui/IconFont";
import TextWithIcon from "./components/ui/TextWithIcon";
import I18n from "./i18n";
import {
identificationCancel,
identificationFailure,
identificationPinReset,
identificationSuccess
} from "./store/actions/identification";
import { ReduxProps } from "./store/actions/types";
import { IdentificationState } from "./store/reducers/identification";
import { GlobalState } from "./store/reducers/types";

type ReduxMappedStateProps = {
identificationState: IdentificationState;
};

type Props = ReduxMappedStateProps & ReduxProps;

/**
* Type used in the local state to save the result of Pinpad PIN matching.
* State is "unstarted" if the user still need to insert the PIN.
* State is "failure" when the PIN inserted by the user do not match the
* stored one.
*/
type IdentificationByPinState = "unstarted" | "failure";

type State = {
identificationByPinState: IdentificationByPinState;
};

const contextualHelp = {
title: I18n.t("pin_login.unlock_screen.help.title"),
body: () => I18n.t("pin_login.unlock_screen.help.content")
};

const renderIdentificationByPinState = (
identificationByPinState: IdentificationByPinState
) => {
if (identificationByPinState === "failure") {
return (
<React.Fragment>
<View spacer={true} extralarge={true} />
<TextWithIcon danger={true}>
<IconFont name="io-close" color={"white"} />
<Text white={true}>{I18n.t("pin_login.pin.confirmInvalid")}</Text>
</TextWithIcon>
</React.Fragment>
);
}

return null;
};

const screenDimensions = Dimensions.get("screen");

const styles = StyleSheet.create({
wrapper: {
width: screenDimensions.width,
height: screenDimensions.height
}
});

/**
* A component used to identify the the user.
* The identification process can be activated calling a saga or dispatching the
* requestIdentification redux action.
*/
class IdentificationOverlay extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);

this.state = {
identificationByPinState: "unstarted"
};
}

public render() {
const { identificationState, dispatch } = this.props;

if (identificationState.kind !== "started") {
return null;
}

// The identification state is started we need to show the modal
const {
pin,
identificationCancelData,
identificationSuccessData
} = identificationState;

const { identificationByPinState } = this.state;

/**
* Create handlers merging default internal actions (to manage the identification state)
* with, if available, custom actions passed as props.
*/
const onIdentificationCancelHandler = () => {
if (identificationCancelData) {
dispatch(identificationCancelData.action);
}
dispatch(identificationCancel());
};

const onIdentificationSuccessHandler = () => {
if (identificationSuccessData) {
dispatch(identificationSuccessData.action);
}
dispatch(identificationSuccess());
};

const onIdentificationFailureHandler = () => {
dispatch(identificationFailure());
};

const onPinResetHandler = () => {
dispatch(identificationPinReset());
};

return (
<View style={styles.wrapper}>
<BaseScreenComponent primary={true} contextualHelp={contextualHelp}>
<StatusBar barStyle="light-content" />
<Content primary={true}>
<View spacer={true} extralarge={true} />
<Text white={true} alignCenter={true}>
{I18n.t("pin_login.pin.pinInfo")}
</Text>
<Pinpad
compareWithCode={pin as string}
activeColor={"white"}
inactiveColor={"white"}
onFulfill={(_: string, __: boolean) =>
this.onPinFullfill(
_,
__,
onIdentificationSuccessHandler,
onIdentificationFailureHandler
)
}
clearOnInvalid={true}
/>
{renderIdentificationByPinState(identificationByPinState)}
<View spacer={true} extralarge={true} />
<View>
{identificationCancelData !== undefined && (
<Button
block={true}
primary={true}
onPress={onIdentificationCancelHandler}
>
<Text>{identificationCancelData.label}</Text>
</Button>
)}
{identificationCancelData === undefined && (
<Button block={true} primary={true} onPress={onPinResetHandler}>
<Text>{I18n.t("pin_login.pin.reset.button")}</Text>
</Button>
)}
<View spacer={true} />
<Text white={true}>{I18n.t("pin_login.pin.reset.tip")}</Text>
</View>
</Content>
</BaseScreenComponent>
</View>
);
}

private onPinFullfill = (
_: string,
isValid: boolean,
onIdentificationSuccessHandler: () => void,
onIdentificationFailureHandler: () => void
) => {
if (isValid) {
this.setState({
identificationByPinState: "unstarted"
});
onIdentificationSuccessHandler();
} else {
this.setState({
identificationByPinState: "failure"
});

onIdentificationFailureHandler();
}
};
}

const mapStateToProps = (state: GlobalState): ReduxMappedStateProps => ({
identificationState: state.identification
});

export default connect(mapStateToProps)(IdentificationOverlay);
2 changes: 2 additions & 0 deletions ts/RootContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { initialiseInstabug } from "./boot/configureInstabug";
import configurePushNotifications from "./boot/configurePushNotification";
import ConnectionBar from "./components/ConnectionBar";
import VersionInfoOverlay from "./components/VersionInfoOverlay";
import IdentificationOverlay from "./IdentificationOverlay";
import Navigation from "./navigation";
import {
applicationChangeState,
Expand Down Expand Up @@ -140,6 +141,7 @@ class RootContainer extends React.PureComponent<Props> {
<StatusBar barStyle="dark-content" />
<ConnectionBar />
<VersionInfoOverlay />
<IdentificationOverlay />
<Navigation />
</Root>
);
Expand Down
Loading