Skip to content
Commits on Source (4)
......@@ -11,7 +11,6 @@ import React, {
} from 'react';
import {
Observer,
Provider,
} from 'mobx-react/native'; // import from mobx-react/native instead of mobx-react fix test
......@@ -24,10 +23,10 @@ import {
Linking,
Text,
Alert,
Clipboard
Clipboard,
} from 'react-native';
import FlashMessage from "react-native-flash-message";
import FlashMessage from 'react-native-flash-message';
import KeychainModalScreen from './src/keychain/KeychainModalScreen';
import BlockchainTransactionModalScreen from './src/blockchain/transaction-modal/BlockchainTransactionModalScreen';
......@@ -35,7 +34,7 @@ import NavigationStack from './src/navigation/NavigationStack';
import stores from './AppStores';
import './AppErrors';
import './src/common/services/socket.service';
// import pushService from './src/common/services/push.service'; //TODO: fix for 0.61
import pushService from './src/common/services/push.service'; //TODO: fix for 0.61
import mindsService from './src/common/services/minds.service';
import featureService from './src/common/services/features.service';
import receiveShare from './src/common/services/receive-share.service';
......@@ -43,9 +42,9 @@ import sessionService from './src/common/services/session.service';
import deeplinkService from './src/common/services/deeplinks-router.service';
import badgeService from './src/common/services/badge.service';
import authService from './src/auth/AuthService';
import NotificationsService from "./src/notifications/NotificationsService";
import NotificationsService from './src/notifications/NotificationsService';
import getMaches from './src/common/helpers/getMatches';
import {CODE_PUSH_TOKEN, GOOGLE_PLAY_STORE} from './src/config/Config';
import { GOOGLE_PLAY_STORE } from './src/config/Config';
import updateService from './src/common/services/update.service';
import ErrorBoundary from './src/common/components/ErrorBoundary';
import { CommonStyle as CS } from './src/styles/Common';
......@@ -64,7 +63,7 @@ import apiService from './src/common/services/api.service';
let deepLinkUrl = '';
// init push service
//pushService.init(); //TODO: fix for 0.61
pushService.init(); //TODO: fix for 0.61
// fire sqlite init
sqliteStorageProviderService.get();
......@@ -90,7 +89,7 @@ sessionService.onLogin(async () => {
// register device token into backend on login
// pushService.registerToken(); //TODO: fix for 0.61
pushService.registerToken();
// get onboarding progress
const onboarding = results[1];
......@@ -118,7 +117,7 @@ sessionService.onLogin(async () => {
}
// handle initial notifications (if the app is opened by tap on one)
// pushService.handleInitialNotification(); //TODO: fix for 0.61
pushService.handleInitialNotification();
// handle shared
receiveShare.handle();
......
......@@ -135,6 +135,7 @@ android {
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode Integer.parseInt(project.versionCode)
versionName project.versionName
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60"
}
signingConfigs {
debug {
......@@ -197,7 +198,7 @@ dependencies {
implementation project(':tipsi-stripe')
// implementation project(':react-native-notifications')
implementation project(':reactnativenotifications')
implementation project(':rn-apk')
......
......@@ -7,7 +7,8 @@ import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.bitgo.randombytes.RandomBytesPackage;
// import com.wix.reactnativenotifications.RNNotificationsPackage;
import com.wix.reactnativenotifications.RNNotificationsPackage;
import com.minds.crypto.CryptoPackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
......@@ -31,6 +32,7 @@ public class MainApplication extends Application implements ShareApplication, Re
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new RNNotificationsPackage(this.getApplication()));
return packages;
}
......
......@@ -17,6 +17,8 @@ include ':react-native-video-exoplayer'
project(':react-native-video-exoplayer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android')
include ':react-native-exception-handler'
project(':react-native-exception-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-exception-handler/android')
include ':reactnativenotifications'
project(':reactnativenotifications').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-notifications/android/app')
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
......@@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
#import "RNNotifications.h"
#import "AppDelegate.h"
#import <React/RCTBridge.h>
......@@ -28,6 +29,7 @@
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
[RNNotifications startMonitorNotifications];
return YES;
}
......@@ -54,4 +56,14 @@
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
// Required to register for notifications
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[RNNotifications didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
[RNNotifications didFailToRegisterForRemoteNotificationsWithError:error];
}
@end
module.exports = {
dependencies: {
'react-native-notifications': {
platforms: {
android: null
},
},
'tipsi-stripe': {
platforms: {
ios: null, // disable ios platform, other platforms will still autolink if provided
......
import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';
import {
PanGestureHandler,
State,
PinchGestureHandler,
} from 'react-native-gesture-handler';
import Animated, { Easing } from 'react-native-reanimated';
const {
set,
cond,
eq,
or,
add,
sub,
min,
max,
multiply,
divide,
lessThan,
decay,
timing,
diff,
not,
abs,
startClock,
stopClock,
clockRunning,
Value,
Clock,
event,
} = Animated;
function scaleDiff(value) {
const tmp = new Value(1);
const prev = new Value(1);
return [set(tmp, divide(value, prev)), set(prev, value), tmp];
}
function dragDiff(value, updating) {
const tmp = new Value(0);
const prev = new Value(0);
return cond(
updating,
[set(tmp, sub(value, prev)), set(prev, value), tmp],
set(prev, 0)
);
}
// returns linear friction coeff. When `value` is 0 coeff is 1 (no friction), then
// it grows linearly until it reaches `MAX_FRICTION` when `value` is equal
// to `MAX_VALUE`
function friction(value) {
const MAX_FRICTION = 5;
const MAX_VALUE = 100;
return max(
1,
min(MAX_FRICTION, add(1, multiply(value, (MAX_FRICTION - 1) / MAX_VALUE)))
);
}
function speed(value) {
const clock = new Clock();
const dt = diff(clock);
return cond(lessThan(dt, 1), 0, multiply(1000, divide(diff(value), dt)));
}
const MIN_SCALE = 1;
const MAX_SCALE = 3;
function scaleRest(value) {
return cond(
lessThan(value, MIN_SCALE),
MIN_SCALE,
cond(lessThan(MAX_SCALE, value), MAX_SCALE, value)
);
}
function scaleFriction(value, rest, delta) {
const MAX_FRICTION = 20;
const MAX_VALUE = 0.5;
const res = multiply(value, delta);
const howFar = abs(sub(rest, value));
const friction = max(
1,
min(MAX_FRICTION, add(1, multiply(howFar, (MAX_FRICTION - 1) / MAX_VALUE)))
);
return cond(
lessThan(0, howFar),
multiply(value, add(1, divide(add(delta, -1), friction))),
res
);
}
function runTiming(clock, value, dest, startStopClock = true) {
const state = {
finished: new Value(0),
position: new Value(0),
frameTime: new Value(0),
time: new Value(0),
};
const config = {
toValue: new Value(0),
duration: 300,
easing: Easing.inOut(Easing.cubic),
};
return [
cond(clockRunning(clock), 0, [
set(state.finished, 0),
set(state.frameTime, 0),
set(state.time, 0),
set(state.position, value),
set(config.toValue, dest),
startStopClock && startClock(clock),
]),
timing(clock, state, config),
cond(state.finished, startStopClock && stopClock(clock)),
state.position,
];
}
function runDecay(clock, value, velocity) {
const state = {
finished: new Value(0),
velocity: new Value(0),
position: new Value(0),
time: new Value(0),
};
const config = { deceleration: 0.99 };
return [
cond(clockRunning(clock), 0, [
set(state.finished, 0),
set(state.velocity, velocity),
set(state.position, value),
set(state.time, 0),
startClock(clock),
]),
set(state.position, value),
decay(clock, state, config),
cond(state.finished, stopClock(clock)),
state.position,
];
}
function bouncyPinch(
value,
gesture,
gestureActive,
focalX,
displacementX,
focalY,
displacementY
) {
const clock = new Clock();
const delta = scaleDiff(gesture);
const rest = scaleRest(value);
const focalXRest = cond(
lessThan(value, 1),
0,
sub(displacementX, multiply(focalX, add(-1, divide(rest, value))))
);
const focalYRest = cond(
lessThan(value, 1),
0,
sub(displacementY, multiply(focalY, add(-1, divide(rest, value))))
);
const nextScale = new Value(1);
return cond(
[delta, gestureActive],
[
stopClock(clock),
set(nextScale, scaleFriction(value, rest, delta)),
set(
displacementX,
sub(displacementX, multiply(focalX, add(-1, divide(nextScale, value))))
),
set(
displacementY,
sub(displacementY, multiply(focalY, add(-1, divide(nextScale, value))))
),
nextScale,
],
cond(
or(clockRunning(clock), not(eq(rest, value))),
[
set(displacementX, runTiming(clock, displacementX, focalXRest, false)),
set(displacementY, runTiming(clock, displacementY, focalYRest, false)),
runTiming(clock, value, rest),
],
value
)
);
}
function bouncy(
value,
gestureDiv,
gestureActive,
lowerBound,
upperBound,
friction
) {
const timingClock = new Clock();
const decayClock = new Clock();
const velocity = speed(value);
// did value go beyond the limits (lower, upper)
const isOutOfBounds = or(
lessThan(value, lowerBound),
lessThan(upperBound, value)
);
// position to snap to (upper or lower is beyond or the current value elsewhere)
const rest = cond(
lessThan(value, lowerBound),
lowerBound,
cond(lessThan(upperBound, value), upperBound, value)
);
// how much the value exceeds the bounds, this is used to calculate friction
const outOfBounds = abs(sub(rest, value));
return cond(
[gestureDiv, velocity, gestureActive],
[
stopClock(timingClock),
stopClock(decayClock),
add(value, divide(gestureDiv, friction(outOfBounds))),
],
cond(
or(clockRunning(timingClock), isOutOfBounds),
[stopClock(decayClock), runTiming(timingClock, value, rest)],
cond(
or(clockRunning(decayClock), lessThan(5, abs(velocity))),
runDecay(decayClock, value, velocity),
value
)
)
);
}
/**
* Image Viewer
*/
export default class ImageViewer extends Component {
pinchRef = React.createRef();
panRef = React.createRef();
constructor(props) {
super(props);
// DECLARE TRANSX
const panTransX = new Value(0);
const panTransY = new Value(0);
// PINCH
const pinchScale = new Value(1);
const pinchFocalX = new Value(0);
const pinchFocalY = new Value(0);
const pinchState = new Value(-1);
this._onPinchEvent = event([
{
nativeEvent: {
state: pinchState,
scale: pinchScale,
focalX: pinchFocalX,
focalY: pinchFocalY,
},
},
]);
// SCALE
const scale = new Value(1);
const pinchActive = eq(pinchState, State.ACTIVE);
this._focalDisplacementX = new Value(0);
const relativeFocalX = sub(
pinchFocalX,
add(panTransX, this._focalDisplacementX)
);
this._focalDisplacementY = new Value(0);
const relativeFocalY = sub(
pinchFocalY,
add(panTransY, this._focalDisplacementY)
);
this._scale = set(
scale,
bouncyPinch(
scale,
pinchScale,
pinchActive,
relativeFocalX,
this._focalDisplacementX,
relativeFocalY,
this._focalDisplacementY
)
);
// PAN
const dragX = new Value(0);
const dragY = new Value(0);
const panState = new Value(-1);
this._onPanEvent = event([
{
nativeEvent: {
translationX: dragX,
translationY: dragY,
state: panState,
},
},
]);
const panActive = eq(panState, State.ACTIVE);
const panFriction = value => friction(value);
// X
const panUpX = cond(
lessThan(this._scale, 1),
0,
multiply(-1, this._focalDisplacementX)
);
const panLowX = add(panUpX, multiply(-this.props.width, add(max(1, this._scale), -1)));
this._panTransX = set(
panTransX,
bouncy(
panTransX,
dragDiff(dragX, panActive),
or(panActive, pinchActive),
panLowX,
panUpX,
panFriction
)
);
// Y
const panUpY = cond(
lessThan(this._scale, 1),
0,
multiply(-1, this._focalDisplacementY)
);
const panLowY = add(
panUpY,
multiply(-this.props.height, add(max(1, this._scale), -1))
);
this._panTransY = set(
panTransY,
bouncy(
panTransY,
dragDiff(dragY, panActive),
or(panActive, pinchActive),
panLowY,
panUpY,
panFriction
)
);
}
render() {
// The below two animated values makes it so that scale appears to be done
// from the top left corner of the image view instead of its center. This
// is required for the "scale focal point" math to work correctly
const scaleTopLeftFixX = divide(multiply(this.props.width, add(this._scale, -1)), 2);
const scaleTopLeftFixY = divide(multiply(this.props.height, add(this._scale, -1)), 2);
return (
<View style={styles.wrapper}>
<PinchGestureHandler
ref={this.pinchRef}
simultaneousHandlers={this.panRef}
onGestureEvent={this._onPinchEvent}
onHandlerStateChange={this._onPinchEvent}>
<Animated.View>
<PanGestureHandler
ref={this.panRef}
minDist={10}
avgTouches
simultaneousHandlers={this.pinchRef}
onGestureEvent={this._onPanEvent}
onHandlerStateChange={this._onPanEvent}>
<Animated.Image
style={[
styles.image,
{height: this.props.height, width: this.props.width},
{
transform: [
{ translateX: this._panTransX },
{ translateY: this._panTransY },
{ translateX: this._focalDisplacementX },
{ translateY: this._focalDisplacementY },
{ translateX: scaleTopLeftFixX },
{ translateY: scaleTopLeftFixY },
{ scale: this._scale },
],
},
]}
resizeMode="stretch"
source={this.props.source}
/>
</PanGestureHandler>
</Animated.View>
</PinchGestureHandler>
</View>
);
}
}
const styles = StyleSheet.create({
wrapper: {
// overflow: 'hidden',
},
image: {
backgroundColor: 'black',
},
});
......@@ -307,7 +307,7 @@ export default class MediaView extends Component {
this.openLink();
} else {
const source = this.props.entity.getThumbSource('xlarge');
this.props.navigation.push('ViewImage', { source });
this.props.navigation.push('ViewImage', { source, entity: this.props.entity });
}
}
......
......@@ -45,7 +45,15 @@ export default class IosPlatfom extends AbstractPlatform {
/**
* Handle the notification that open the app
*/
handleInitialNotification() {
async handleInitialNotification() {
try {
const notification = await NotificationsIOS.getInitialNotification();
if (notification && this.onInitialNotification) {
this.onInitialNotification(notification);
}
} catch (err) {
logService.exception('[PushService]', err);
}
}
/**
......@@ -81,6 +89,6 @@ export default class IosPlatfom extends AbstractPlatform {
// code: 3010,
// localizedDescription: 'remote notifications are not supported in the simulator'
// }
logService.exception(error);
logService.error(error.localizedDescription);
}
}
\ No newline at end of file
}
......@@ -86,10 +86,26 @@ export default class DiscoveryScreen extends Component {
}
}
/**
* constructor
*/
constructor(props) {
super(props);
this.props.discovery.init();
const params = this.props.navigation.state.params;
if (params && params.type) {
this.props.discovery.filters.setType(params.type);
}
this.tileError = i18n.t('error');
}
/**
* On component will mount
*/
componentWillMount() {
componentDidMount() {
// load data on enter
this.disposeEnter = this.props.navigation.addListener('didFocus', (s) => {
setTimeout(() => {
......@@ -103,15 +119,6 @@ export default class DiscoveryScreen extends Component {
this.setState({active: false});
}, 50);
});
this.props.discovery.init();
const params = this.props.navigation.state.params;
if (params && params.type) {
this.props.discovery.filters.setType(params.type);
}
this.tileError = i18n.t('error');
}
/**
......
......@@ -4,19 +4,18 @@ import React, {
import {
View,
Dimensions,
Image,
StatusBar,
StyleSheet,
Dimensions,
Platform,
} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import PhotoView from 'react-native-photo-view';
// import PhotoView from 'react-native-photo-view';
import { CommonStyle } from '../styles/Common';
import testID from '../common/helpers/testID';
import ImageViewer from '../common/components/ImageViewer';
/**
* Full screen image viewer
......@@ -24,21 +23,30 @@ import testID from '../common/helpers/testID';
export default class ViewImageScreen extends Component {
static navigationOptions = ({ navigation }) => ({
header: (
<View style={styles.header}>
<Icon
size={36}
name="ios-close"
onPress={() => navigation.goBack()}
style={styles.iconclose}
{...testID('Go back button')}
/>
</View>
),
transitionConfig: {
isModal: true
}
})
});
constructor(props) {
super(props);
const custom_data = this.props.navigation.state.params.entity.custom_data;
const width = Dimensions.get('window').width;
let height = 300;
if (custom_data && custom_data[0].height && custom_data[0].height != '0') {
let ratio = custom_data[0].height / custom_data[0].width;
height = width * ratio;
}
this.state = {
width,
height,
};
}
getSource() {
return this.props.navigation.state.params.source;
......@@ -49,12 +57,13 @@ export default class ViewImageScreen extends Component {
const source = this.getSource();
return (
<PhotoView
source={source}
minimumZoomScale={1}
maximumZoomScale={3}
androidScaleType="fitCenter"
style={[CommonStyle.flexContainer, CommonStyle.backgroundBlack]} />
<View style={[CommonStyle.flexContainerCenter, CommonStyle.alignCenter, CommonStyle.backgroundBlack]}>
<ImageViewer
source={source}
width={this.state.width}
height={this.state.height}
/>
</View>
)
}
}
......
......@@ -7548,6 +7548,13 @@ react-native-modal@^11.0.2, react-native-modal@^11.4.0:
prop-types "^15.6.2"
react-native-animatable "^1.3.1"
react-native-notifications@Minds/react-native-notifications.git:
version "2.0.6"
resolved "https://codeload.github.com/Minds/react-native-notifications/tar.gz/333e376f866a805f250cc68706d97ace503b948a"
dependencies:
core-js "^1.0.0"
uuid "^2.0.3"
react-native-phone-input@thegamenicorus/react-native-phone-input#6ab1a91a09ddd4272fe85e30ecedf092f0fcb1a7:
version "0.1.10"
resolved "https://codeload.github.com/thegamenicorus/react-native-phone-input/tar.gz/6ab1a91a09ddd4272fe85e30ecedf092f0fcb1a7"
......@@ -9207,6 +9214,11 @@ uuid@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac"
uuid@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
integrity sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=
uuid@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
......