Rocket.Chat.ReactNative/app/utils/review.js

98 lines
2.6 KiB
JavaScript
Raw Normal View History

[NEW] Passcode and biometric unlock (#2059) * Update expo libs * Configure expo-local-authentication * ScreenLockedView * Authenticate server change * Auth on app resume * localAuthentication util * Add servers.lastLocalAuthenticatedSession column * Save last session date on background * Use our own version of app state redux * Fix libs * Remove inactive * ScreenLockConfigView * Apply on saved data * Auto lock option label * Starting passcode * Basic passcode flow working * Change passcode * Check if biometry is enrolled * Use fork * Migration * Patch expo-local-authentication * Use async storage * Styling * Timer * Refactor * Lock orientation portrait when not on tablet * share extension * Deep linking * Share extension * Refactoring passcode * use state * Stash * Refactor * Change passcode * Animate dots on error * Matching passcodes * Shake * Remove lib * Delete button * Fade animation on modal * Refactoring * ItemInfo * I18n * I18n * Remove unnecessary prop * Save biometry column * Raise time to lock to 30 seconds * Vibrate on wrong confirmation passcode * Reset attempts and save last authentication on local passcode confirmation * Remove inline style * Save last auth * Fix header blink * Change function name * Fix android modal * Fix vibration permission * PasscodeEnter calls biometry * Passcode on the state * Biometry button on PasscodeEnter * Show whole passcode * Secure passcode * Save passcode with promise to prevent empty passcodes and immediately lock * Patch expo-local-authentication * I18n * Fix biometry being called every time * Blur screen on app inactive * Revert "Blur screen on app inactive" This reverts commit a4ce812934adcf6cf87eb1a92aec9283e2f26753. * Remove immediately because of how Activities work on Android * Pods * New layout * stash * Layout refactored * Fix icons * Force set passcode from server * Lint * Improve permission message * Forced passcode subtitle * Disable based on admin's choice * Require local authentication on login success * Refactor * Update tests * Update react-native-device-info to fix notch * Lint * Fix modal * Fix icons * Fix min auto lock time * Review * keep enabled on mobile * fix forced by admin when enable unlock with passcode * use DEFAULT_AUTO_LOCK when manual enable screenLock * fix check has passcode * request biometry on first password * reset auto time lock when disabled on server Co-authored-by: Djorkaeff Alexandre <djorkaeff.unb@gmail.com>
2020-05-08 17:04:37 +00:00
import { Alert, Linking } from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
2020-02-03 18:28:18 +00:00
import { isIOS } from './deviceInfo';
import I18n from '../i18n';
import { showErrorAlert } from './info';
import { STORE_REVIEW_LINK } from '../constants/links';
const store = isIOS ? 'App Store' : 'Play Store';
const reviewKey = 'reviewKey';
const reviewDelay = 2000;
const numberOfDays = 7;
const numberOfPositiveEvent = 5;
const daysBetween = (date1, date2) => {
const one_day = 1000 * 60 * 60 * 24;
const date1_ms = date1.getTime();
const date2_ms = date2.getTime();
const difference_ms = date2_ms - date1_ms;
return Math.round(difference_ms / one_day);
};
const onCancelPress = () => {
try {
const data = JSON.stringify({ doneReview: true });
return AsyncStorage.setItem(reviewKey, data);
} catch (e) {
// do nothing
}
};
export const onReviewPress = async() => {
await onCancelPress();
try {
const supported = await Linking.canOpenURL(STORE_REVIEW_LINK);
if (supported) {
Linking.openURL(STORE_REVIEW_LINK);
}
} catch (e) {
showErrorAlert(I18n.t('Review_app_unable_store', { store }));
}
};
const onAskMeLaterPress = () => {
try {
const data = JSON.stringify({ lastReview: new Date().getTime() });
return AsyncStorage.setItem(reviewKey, data);
} catch (e) {
// do nothing
}
};
const onReviewButton = { text: I18n.t('Review_app_yes'), onPress: onReviewPress };
const onAskMeLaterButton = { text: I18n.t('Review_app_later'), onPress: onAskMeLaterPress };
const onCancelButton = { text: I18n.t('Review_app_no'), onPress: onCancelPress };
const askReview = () => Alert.alert(
I18n.t('Review_app_title'),
I18n.t('Review_app_desc', { store }),
isIOS
? [onReviewButton, onAskMeLaterButton, onCancelButton]
: [onAskMeLaterButton, onCancelButton, onReviewButton],
{
cancelable: true,
onDismiss: onAskMeLaterPress
}
);
const tryReview = async() => {
const data = await AsyncStorage.getItem(reviewKey) || '{}';
const reviewData = JSON.parse(data);
const { lastReview = 0, doneReview = false } = reviewData;
const lastReviewDate = new Date(lastReview);
// if ask me later was pressed earlier, we can ask for review only after {{numberOfDays}} days
// if there's no review and it wasn't dismissed by the user
if (daysBetween(lastReviewDate, new Date()) >= numberOfDays && !doneReview) {
setTimeout(askReview, reviewDelay);
}
};
class ReviewApp {
positiveEventCount = 0;
pushPositiveEvent = () => {
if (this.positiveEventCount >= numberOfPositiveEvent) {
return;
}
this.positiveEventCount += 1;
if (this.positiveEventCount === numberOfPositiveEvent) {
tryReview();
}
}
}
export const Review = new ReviewApp();