浏览代码

Migrate to react native 0.62.2 and react-navigation 5

pull/521/head
Guillaume Vincent 4 年前
父节点
当前提交
b81b62709a
共有 36 个文件被更改,包括 3242 次插入2860 次删除
  1. +3
    -4
      mobile/.flowconfig
  2. +2
    -1
      mobile/.gitattributes
  3. +1
    -8
      mobile/App.js
  4. +27
    -2
      mobile/android/app/build.gradle
  5. +8
    -0
      mobile/android/app/src/debug/AndroidManifest.xml
  6. +72
    -0
      mobile/android/app/src/debug/java/com/lesspass/android/ReactNativeFlipper.java
  7. +2
    -1
      mobile/android/app/src/main/AndroidManifest.xml
  8. +12
    -6
      mobile/android/app/src/main/java/com/lesspass/android/MainApplication.java
  9. +2
    -2
      mobile/android/build.gradle
  10. +7
    -0
      mobile/android/gradle.properties
  11. +1
    -1
      mobile/android/gradle/wrapper/gradle-wrapper.properties
  12. +3
    -3
      mobile/android/gradlew
  13. +2
    -43
      mobile/ios/LessPass.xcodeproj/xcshareddata/xcschemes/LessPass-tvOS.xcscheme
  14. +2
    -43
      mobile/ios/LessPass.xcodeproj/xcshareddata/xcschemes/LessPass.xcscheme
  15. +0
    -7
      mobile/ios/LessPass/AppDelegate.h
  16. +23
    -7
      mobile/ios/LessPass/AppDelegate.m
  17. +0
    -7
      mobile/ios/LessPass/main.m
  18. +0
    -8
      mobile/ios/LessPassTests/LessPassTests.m
  19. +55
    -4
      mobile/ios/Podfile
  20. +26
    -21
      mobile/package.json
  21. +61
    -78
      mobile/src/AppContainer.js
  22. +0
    -31
      mobile/src/auth/AuthLoadingScreen.js
  23. +0
    -16
      mobile/src/auth/AuthStack.js
  24. +15
    -0
      mobile/src/auth/AuthStackScreen.js
  25. +12
    -18
      mobile/src/auth/SignInScreen.js
  26. +33
    -33
      mobile/src/auth/SignOutScreen.js
  27. +3
    -2
      mobile/src/auth/SignUpScreen.js
  28. +3
    -2
      mobile/src/auth/authReducer.js
  29. +9
    -7
      mobile/src/auth/authReducer.test.js
  30. +33
    -34
      mobile/src/help/HelpScreen.js
  31. +9
    -14
      mobile/src/password/Options.js
  32. +1
    -2
      mobile/src/password/PasswordGeneratorScreen.js
  33. +11
    -0
      mobile/src/routes.js
  34. +1
    -18
      mobile/src/settings/SettingsScreen.js
  35. +10
    -0
      mobile/src/ui/LoadingScreen.js
  36. +2793
    -2437
      mobile/yarn.lock

+ 3
- 4
mobile/.flowconfig 查看文件

@@ -21,7 +21,7 @@ node_modules/warning/.*
[include]

[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/interface.js
node_modules/react-native/flow/

[options]
@@ -36,9 +36,8 @@ module.file_ext=.ios.js

munge_underscores=true

module.name_mapper='^react-native$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/react-native/react-native-implementation'
module.name_mapper='^react-native/\(.*\)$' -> '<PROJECT_ROOT>/node_modules/react-native/\1'
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/Image/RelativeImageStub'
module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/Image/RelativeImageStub'

suppress_type=$FlowIssue
suppress_type=$FlowFixMe
@@ -72,4 +71,4 @@ untyped-import
untyped-type-import

[version]
^0.105.0
^0.113.0

+ 2
- 1
mobile/.gitattributes 查看文件

@@ -1 +1,2 @@
*.pbxproj -text
# specific for windows script files
*.bat text eol=crlf

+ 1
- 8
mobile/App.js 查看文件

@@ -1,11 +1,4 @@
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/

import "react-native-gesture-handler";
import React from "react";
import { Provider } from "react-redux";
import { Provider as PaperProvider } from "react-native-paper";


+ 27
- 2
mobile/android/app/build.gradle 查看文件

@@ -15,7 +15,9 @@ import com.android.build.OutputFile
* // the name of the generated asset file containing your JS bundle
* bundleAssetName: "index.android.bundle",
*
* // the entry file for bundle generation
* // the entry file for bundle generation. If none specified and
* // "index.android.js" exists, it will be used. Otherwise "index.js" is
* // default. Can be overridden with ENTRY_FILE environment variable.
* entryFile: "index.android.js",
*
* // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format
@@ -85,7 +87,6 @@ project.ext.vectoricons = [
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"

project.ext.react = [
entryFile: "index.js",
enableHermes: false, // clean and rebuild if changing
]

@@ -177,6 +178,14 @@ android {
signingConfig signingConfigs.release
}
}

packagingOptions {
pickFirst "lib/armeabi-v7a/libc++_shared.so"
pickFirst "lib/arm64-v8a/libc++_shared.so"
pickFirst "lib/x86/libc++_shared.so"
pickFirst "lib/x86_64/libc++_shared.so"
}

// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
@@ -195,7 +204,23 @@ android {

dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules

implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"

debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
}

debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}

debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}

implementation "com.madgag.spongycastle:core:1.58.0.0"
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";


+ 8
- 0
mobile/android/app/src/debug/AndroidManifest.xml 查看文件

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" />
</manifest>

+ 72
- 0
mobile/android/app/src/debug/java/com/lesspass/android/ReactNativeFlipper.java 查看文件

@@ -0,0 +1,72 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/
package com.lesspass.android;

import android.content.Context;
import com.facebook.flipper.android.AndroidFlipperClient;
import com.facebook.flipper.android.utils.FlipperUtils;
import com.facebook.flipper.core.FlipperClient;
import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
import com.facebook.flipper.plugins.inspector.DescriptorMapping;
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.network.NetworkingModule;
import okhttp3.OkHttpClient;

public class ReactNativeFlipper {
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
if (FlipperUtils.shouldEnableFlipper(context)) {
final FlipperClient client = AndroidFlipperClient.getInstance(context);

client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
client.addPlugin(new ReactFlipperPlugin());
client.addPlugin(new DatabasesFlipperPlugin(context));
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
client.addPlugin(CrashReporterPlugin.getInstance());

NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
NetworkingModule.setCustomClientBuilder(
new NetworkingModule.CustomClientBuilder() {
@Override
public void apply(OkHttpClient.Builder builder) {
builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
}
});
client.addPlugin(networkFlipperPlugin);
client.start();

// Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
// Hence we run if after all native modules have been initialized
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (reactContext == null) {
reactInstanceManager.addReactInstanceEventListener(
new ReactInstanceManager.ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext reactContext) {
reactInstanceManager.removeReactInstanceEventListener(this);
reactContext.runOnNativeModulesQueueThread(
new Runnable() {
@Override
public void run() {
client.addPlugin(new FrescoFlipperPlugin());
}
});
}
});
} else {
client.addPlugin(new FrescoFlipperPlugin());
}
}
}
}

+ 2
- 1
mobile/android/app/src/main/AndroidManifest.xml 查看文件

@@ -19,7 +19,8 @@
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />


+ 12
- 6
mobile/android/app/src/main/java/com/lesspass/android/MainApplication.java 查看文件

@@ -4,6 +4,7 @@ import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
@@ -42,23 +43,28 @@ public class MainApplication extends Application implements ReactApplication {
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this); // Remove this line if you don't want Flipper enabled
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}

/**
* Loads Flipper in React Native templates.
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* @param context
* @param reactInstanceManager
*/
private static void initializeFlipper(Context context) {
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper");
aClass.getMethod("initializeFlipper", Context.class).invoke(null, context);
Class<?> aClass = Class.forName("com.lesspass.android.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
@@ -70,4 +76,4 @@ public class MainApplication extends Application implements ReactApplication {
}
}
}
}
}

+ 2
- 2
mobile/android/build.gradle 查看文件

@@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath("com.android.tools.build:gradle:3.4.2")
classpath("com.android.tools.build:gradle:3.5.2")

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -28,7 +28,7 @@ allprojects {

google()
jcenter()
maven { url 'https://jitpack.io' }
maven { url 'https://www.jitpack.io' }
}
}



+ 7
- 0
mobile/android/gradle.properties 查看文件

@@ -17,5 +17,12 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true

# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.33.1

+ 1
- 1
mobile/android/gradle/wrapper/gradle-wrapper.properties 查看文件

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

+ 3
- 3
mobile/android/gradlew 查看文件

@@ -7,7 +7,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
@@ -125,8 +125,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`


+ 2
- 43
mobile/ios/LessPass.xcodeproj/xcshareddata/xcschemes/LessPass-tvOS.xcscheme 查看文件

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0940"
LastUpgradeVersion = "1130"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
@@ -14,40 +14,12 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D2A28121D9B038B00D4039D"
BuildableName = "libReact.a"
BlueprintName = "React-tvOS"
ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
BuildableName = "LessPass-tvOS.app"
BlueprintName = "LessPass-tvOS"
ReferencedContainer = "container:LessPass.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E48F1E0B4A5D006451C7"
BuildableName = "LessPass-tvOSTests.xctest"
BlueprintName = "LessPass-tvOSTests"
ReferencedContainer = "container:LessPass.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
@@ -67,17 +39,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
BuildableName = "LessPass-tvOS.app"
BlueprintName = "LessPass-tvOS"
ReferencedContainer = "container:LessPass.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -99,8 +60,6 @@
ReferencedContainer = "container:LessPass.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"


+ 2
- 43
mobile/ios/LessPass.xcodeproj/xcshareddata/xcschemes/LessPass.xcscheme 查看文件

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0940"
LastUpgradeVersion = "1130"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
@@ -14,40 +14,12 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
BuildableName = "libReact.a"
BlueprintName = "React"
ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "LessPass.app"
BlueprintName = "LessPass"
ReferencedContainer = "container:LessPass.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
BuildableName = "LessPassTests.xctest"
BlueprintName = "LessPassTests"
ReferencedContainer = "container:LessPass.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
@@ -67,17 +39,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "LessPass.app"
BlueprintName = "LessPass"
ReferencedContainer = "container:LessPass.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -99,8 +60,6 @@
ReferencedContainer = "container:LessPass.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"


+ 0
- 7
mobile/ios/LessPass/AppDelegate.h 查看文件

@@ -1,10 +1,3 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>



+ 23
- 7
mobile/ios/LessPass/AppDelegate.m 查看文件

@@ -1,20 +1,36 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

#if DEBUG
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>

static void InitializeFlipper(UIApplication *application) {
FlipperClient *client = [FlipperClient sharedClient];
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
[client addPlugin:[FlipperKitReactPlugin new]];
[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
[client start];
}
#endif

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if DEBUG
InitializeFlipper(application);
#endif

RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"LessPass"


+ 0
- 7
mobile/ios/LessPass/main.m 查看文件

@@ -1,10 +1,3 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import <UIKit/UIKit.h>

#import "AppDelegate.h"


+ 0
- 8
mobile/ios/LessPassTests/LessPassTests.m 查看文件

@@ -1,10 +1,3 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>

@@ -59,7 +52,6 @@
return NO;
}];
}
#ifdef DEBUG
RCTSetLogFunction(RCTDefaultLogFunction);
#endif


+ 55
- 4
mobile/ios/Podfile 查看文件

@@ -1,6 +1,49 @@
platform :ios, '9.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

def add_flipper_pods!(versions = {})
versions['Flipper'] ||= '~> 0.33.1'
versions['DoubleConversion'] ||= '1.1.7'
versions['Flipper-Folly'] ||= '~> 2.1'
versions['Flipper-Glog'] ||= '0.3.6'
versions['Flipper-PeerTalk'] ||= '~> 0.0.4'
versions['Flipper-RSocket'] ||= '~> 1.0'

pod 'FlipperKit', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configuration => 'Debug'

# List all transitive dependencies for FlipperKit pods
# to avoid them being linked in Release builds
pod 'Flipper', versions['Flipper'], :configuration => 'Debug'
pod 'Flipper-DoubleConversion', versions['DoubleConversion'], :configuration => 'Debug'
pod 'Flipper-Folly', versions['Flipper-Folly'], :configuration => 'Debug'
pod 'Flipper-Glog', versions['Flipper-Glog'], :configuration => 'Debug'
pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configuration => 'Debug'
pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configuration => 'Debug'
pod 'FlipperKit/Core', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/CppBridge', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FBDefines', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configuration => 'Debug'
pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
end

# Post Install processing for Flipper
def flipper_post_install(installer)
installer.pods_project.targets.each do |target|
if target.name == 'YogaKit'
target.build_configurations.each do |config|
config.build_settings['SWIFT_VERSION'] = '4.1'
end
end
end
end

target 'LessPass' do
# Pods for LessPass
pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
@@ -26,20 +69,29 @@ target 'LessPass' do
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon"
pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true

pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'

target 'LessPassTests' do
inherit! :search_paths
inherit! :complete
# Pods for testing
end

use_native_modules!

# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable these next few lines.
add_flipper_pods!
post_install do |installer|
flipper_post_install(installer)
end
end

target 'LessPass-tvOS' do
@@ -49,5 +101,4 @@ target 'LessPass-tvOS' do
inherit! :search_paths
# Pods for testing
end

end

+ 26
- 21
mobile/package.json 查看文件

@@ -18,37 +18,42 @@
"postinstall": "node ./scripts/postInstall.js"
},
"dependencies": {
"@react-native-community/async-storage": "^1.6.2",
"axios": "^0.19.0",
"@react-native-community/async-storage": "^1.9.0",
"@react-native-community/masked-view": "^0.1.9",
"@react-navigation/bottom-tabs": "^5.2.6",
"@react-navigation/material-bottom-tabs": "^5.1.8",
"@react-navigation/native": "^5.1.5",
"@react-navigation/stack": "^5.2.10",
"axios": "^0.19.2",
"fuse.js": "^3.4.5",
"lesspass-fingerprint": "latest",
"lesspass-render-password": "latest",
"lesspass-fingerprint": "^9.1.4",
"lesspass-render-password": "^9.1.4",
"lodash": "^4.17.15",
"memoize-one": "^5.1.1",
"react": "16.9.0",
"react-native": "0.61.2",
"react-native-gesture-handler": "^1.4.1",
"react": "16.11.0",
"react-native": "0.62.2",
"react-native-gesture-handler": "^1.6.1",
"react-native-keychain": "^4.0.1",
"react-native-paper": "^3.0.0",
"react-native-paper": "^3.8.0",
"react-native-reanimated": "^1.8.0",
"react-native-safe-area-context": "^0.7.3",
"react-native-screens": "^2.4.0",
"react-native-touch-id": "^4.4.1",
"react-native-vector-icons": "^6.6.0",
"react-navigation": "^4.0.10",
"react-navigation-material-bottom-tabs": "^2.1.3",
"react-navigation-stack": "^1.10.2",
"react-redux": "^7.1.1",
"redux": "^4.0.4",
"react-redux": "^7.2.0",
"redux": "^4.0.5",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"@babel/core": "^7.6.4",
"@babel/runtime": "^7.6.3",
"@react-native-community/eslint-config": "^0.0.5",
"babel-jest": "^24.9.0",
"eslint": "^6.5.1",
"jest": "^24.9.0",
"metro-react-native-babel-preset": "^0.56.0",
"react-test-renderer": "16.9.0"
"@babel/core": "^7.9.0",
"@babel/runtime": "^7.9.2",
"@react-native-community/eslint-config": "^1.0.0",
"babel-jest": "^25.3.0",
"eslint": "^6.8.0",
"jest": "^25.3.0",
"metro-react-native-babel-preset": "^0.59.0",
"react-test-renderer": "16.13.1"
},
"jest": {
"preset": "react-native"


+ 61
- 78
mobile/src/AppContainer.js 查看文件

@@ -1,86 +1,69 @@
import React from "react";
import { createMaterialBottomTabNavigator } from "react-navigation-material-bottom-tabs";
import * as React from "react";
import { useSelector } from "react-redux";
import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import Icon from "react-native-vector-icons/FontAwesome";
import { createAppContainer, createSwitchNavigator } from "react-navigation";
import AuthStack from "./auth/AuthStack";
import AuthLoadingScreen from "./auth/AuthLoadingScreen";
import HelpScreen from "./help/HelpScreen";
import Theme from "./ui/Theme";
import LoadingScreen from "./ui/LoadingScreen";
import PasswordGeneratorScreen from "./password/PasswordGeneratorScreen";
import SettingsScreen from "./settings/SettingsScreen";
import Theme from "./ui/Theme";

const commonTabs = {
PasswordGenerator: {
screen: PasswordGeneratorScreen,
navigationOptions: {
title: "LessPass",
tabBarIcon: ({ tintColor }) => (
<Icon size={20} name="user-secret" style={{ color: tintColor }} />
)
}
},
Settings: {
screen: SettingsScreen,
navigationOptions: {
title: "Settings",
tabBarIcon: ({ tintColor }) => (
<Icon size={20} name="cogs" style={{ color: tintColor }} />
)
}
},
Help: {
screen: HelpScreen,
navigationOptions: {
title: "Help",
tabBarIcon: ({ tintColor }) => (
<Icon size={20} name="question" style={{ color: tintColor }} />
)
}
}
};
import HelpScreen from "./help/HelpScreen";
import AuthStackScreen from "./auth/AuthStackScreen";
import SignOutScreen from "./auth/SignOutScreen";
import routes from "./routes";

const tabOptions = {
initialRouteName: "PasswordGenerator",
activeTintColor: Theme.colors.white,
inactiveTintColor: Theme.colors.lightBlue,
barStyle: { backgroundColor: Theme.colors.primary },
labeled: true
};
const Tab = createBottomTabNavigator();

const AppNavigator = createMaterialBottomTabNavigator(
{
...commonTabs
},
tabOptions
);
function App() {
const auth = useSelector((state) => state.auth);

const AuthNavigator = createMaterialBottomTabNavigator(
{
...commonTabs,
SignIn: {
screen: AuthStack,
navigationOptions: {
title: "Sign In",
tabBarIcon: ({ tintColor }) => (
<Icon size={20} name="user" style={{ color: tintColor }} />
)
}
}
},
tabOptions
);
if (auth.isLoading) {
return <LoadingScreen />;
}

const AppContainer = createAppContainer(
createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppNavigator,
Auth: AuthNavigator
},
{
initialRouteName: "AuthLoading"
}
)
);
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ color, size }) => {
let iconName;
if (route.name === routes.PASSWORD_GENERATOR) {
iconName = "user-secret";
} else if (route.name === routes.SETTINGS) {
iconName = "cogs";
} else if (route.name === routes.HELP) {
iconName = "question";
} else if (route.name === routes.AUTH_STACK) {
iconName = "user";
} else if (route.name === routes.SIGN_OUT) {
iconName = "user";
}
return (
<Icon size={size} name={iconName} style={{ color: color }} />
);
},
})}
tabBarOptions={{
activeTintColor: Theme.colors.white,
activeBackgroundColor: Theme.colors.primary,
inactiveTintColor: Theme.colors.lightBlue,
inactiveBackgroundColor: Theme.colors.primary,
}}
>
<Tab.Screen
name={routes.PASSWORD_GENERATOR}
component={PasswordGeneratorScreen}
/>
<Tab.Screen name={routes.SETTINGS} component={SettingsScreen} />
<Tab.Screen name={routes.HELP} component={HelpScreen} />
{auth.jwt == null ? (
<Tab.Screen name={routes.AUTH_STACK} component={AuthStackScreen} />
) : (
<Tab.Screen name={routes.SIGN_OUT} component={SignOutScreen} />
)}
</Tab.Navigator>
</NavigationContainer>
);
}

export default AppContainer;
export default App;

+ 0
- 31
mobile/src/auth/AuthLoadingScreen.js 查看文件

@@ -1,31 +0,0 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { ActivityIndicator, View } from "react-native";

class AuthLoadingScreen extends Component {
constructor(props) {
super(props);
this._bootstrapAsync();
}

_bootstrapAsync = async () => {
const { navigation, auth } = this.props;
navigation.navigate(auth.jwt ? "App" : "Auth");
};

render() {
return (
<View style={{ flex: 1, justifyContent: "center" }}>
<ActivityIndicator size="large" color="#ffffff" />
</View>
);
}
}

function mapStateToProps(state) {
return {
auth: state.auth
};
}

export default connect(mapStateToProps)(AuthLoadingScreen);

+ 0
- 16
mobile/src/auth/AuthStack.js 查看文件

@@ -1,16 +0,0 @@
import { createStackNavigator } from "react-navigation-stack";
import SignInScreen from "./SignInScreen";
import SignUpScreen from "./SignUpScreen";

const AuthStack = createStackNavigator(
{
SignIn: SignInScreen,
SignUp: SignUpScreen
},
{
initialRouteName: "SignIn",
headerMode: "none"
}
);

export default AuthStack;

+ 15
- 0
mobile/src/auth/AuthStackScreen.js 查看文件

@@ -0,0 +1,15 @@
import React from "react";
import { createStackNavigator } from "@react-navigation/stack";
import SignInScreen from "./SignInScreen";
import SignUpScreen from "./SignUpScreen";

const AuthStack = createStackNavigator();

const AuthStackScreen = () => (
<AuthStack.Navigator headerMode="none">
<AuthStack.Screen name="SignIn" component={SignInScreen} />
<AuthStack.Screen name="SignUp" component={SignUpScreen} />
</AuthStack.Navigator>
);

export default AuthStackScreen;

+ 12
- 18
mobile/src/auth/SignInScreen.js 查看文件

@@ -8,6 +8,7 @@ import TextInput from "../ui/TextInput";
import Styles from "../ui/Styles";
import { addError } from "../errors/errorsActions";
import { signIn } from "./authActions";
import routes from "../routes";

export class SignInScreen extends Component {
constructor(props) {
@@ -15,7 +16,7 @@ export class SignInScreen extends Component {
this.state = {
email: "",
password: "",
isLoading: false
isLoading: false,
};
}

@@ -35,17 +36,13 @@ export class SignInScreen extends Component {
mode="outlined"
label="Email"
value={email}
onChangeText={text => this.setState({ email: text.trim() })}
onChangeText={(text) => this.setState({ email: text.trim() })}
/>
<MasterPassword
label={
encryptMasterPassword
? "Master Password"
: "Password"
}
label={encryptMasterPassword ? "Master Password" : "Password"}
masterPassword={password}
hideFingerprint={!encryptMasterPassword}
onChangeText={password => this.setState({ password })}
onChangeText={(password) => this.setState({ password })}
/>
<Button
compact
@@ -58,11 +55,11 @@ export class SignInScreen extends Component {
signIn(
{
email,
password
password,
},
encryptMasterPassword
)
.then(() => navigation.navigate("App"))
.then(() => navigation.navigate(routes.PASSWORD_GENERATOR))
.catch(() => {
this.setState({ isLoading: false });
let errorMessage =
@@ -83,7 +80,7 @@ export class SignInScreen extends Component {
icon="account-circle"
mode="outlined"
style={Styles.loginSignUpButton}
onPress={() => navigation.navigate("SignUp")}
onPress={() => navigation.navigate(routes.SIGN_UP)}
>
Sign Up
</Button>
@@ -95,19 +92,16 @@ export class SignInScreen extends Component {

function mapStateToProps(state) {
return {
settings: state.settings
settings: state.settings,
};
}

function mapDispatchToProps(dispatch) {
return {
addError: message => dispatch(addError(message)),
addError: (message) => dispatch(addError(message)),
signIn: (credentials, encryptMasterPassword) =>
dispatch(signIn(credentials, encryptMasterPassword))
dispatch(signIn(credentials, encryptMasterPassword)),
};
}

export default connect(
mapStateToProps,
mapDispatchToProps
)(SignInScreen);
export default connect(mapStateToProps, mapDispatchToProps)(SignInScreen);

+ 33
- 33
mobile/src/auth/SignOutScreen.js 查看文件

@@ -1,36 +1,36 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { View, Text } from "react-native";
import React from "react";
import { ScrollView } from "react-native";
import { useDispatch } from "react-redux";
import { signOut } from "./authActions";
import Styles from "../ui/Styles";
import { Title, Button } from "react-native-paper";
import routes from "../routes";

class SignOutScreen extends Component {
constructor(props) {
super(props);
this._signOut();
}
const SignOutScreen = ({ navigation }) => {
const dispatch = useDispatch();
return (
<ScrollView
style={{
flex: 1,
paddingTop: 20,
paddingHorizontal: 10,
}}
>
<Title style={{ marginBottom: 10 }}>Sign Out</Title>
<Button
compact
icon="account-circle"
mode="outlined"
style={Styles.loginSignUpButton}
onPress={() => {
dispatch(signOut());
navigation.navigate(routes.PASSWORD_GENERATOR);
}}
>
Sign out
</Button>
</ScrollView>
);
};

_signOut = async () => {
const { navigation, signOut } = this.props;
signOut();
navigation.navigate("Auth");
};

render() {
return (
<View>
<Text>Signing out</Text>
</View>
);
}
}

function mapDispatchToProps(dispatch) {
return {
signOut: () => dispatch(signOut())
};
}

export default connect(
null,
mapDispatchToProps
)(SignOutScreen);
export default SignOutScreen;

+ 3
- 2
mobile/src/auth/SignUpScreen.js 查看文件

@@ -8,6 +8,7 @@ import Styles from "../ui/Styles";
import { addError } from "../errors/errorsActions";
import { signUp } from "./authActions";
import { isEmpty } from "lodash";
import routes from "../routes";

export class SignUpScreen extends Component {
constructor(props) {
@@ -57,7 +58,7 @@ export class SignUpScreen extends Component {
},
encryptMasterPassword
)
.then(() => navigation.navigate("App"))
.then(() => navigation.navigate(routes.PASSWORD_GENERATOR))
.catch(error => {
this.setState({ isLoading: false });
addError(
@@ -74,7 +75,7 @@ export class SignUpScreen extends Component {
icon="account-circle"
mode="outlined"
style={Styles.loginSignUpButton}
onPress={() => navigation.navigate("SignIn")}
onPress={() => navigation.navigate(routes.SIGN_IN)}
>
Sign In
</Button>


+ 3
- 2
mobile/src/auth/authReducer.js 查看文件

@@ -1,8 +1,9 @@
const initialState = {
jwt: null
jwt: null,
isLoading: false,
};

export default function(state = initialState, action) {
export default function (state = initialState, action) {
switch (action.type) {
case "SET_JWT":
return { ...state, jwt: action.jwt };


+ 9
- 7
mobile/src/auth/authReducer.test.js 查看文件

@@ -3,36 +3,38 @@ import reducer from "./authReducer";
describe("auth reducer", () => {
it("should return the initial state", () => {
expect(reducer(undefined, {})).toEqual({
jwt: null
jwt: null,
isLoading: false,
});
});
it("SET_JWT", () => {
expect(
reducer(
{
jwt: null
jwt: null,
},
{
type: "SET_JWT",
jwt: "jwt"
jwt: "jwt",
}
)
).toEqual({
jwt: "jwt"
jwt: "jwt",
});
});
it("CLEAR_JWT", () => {
expect(
reducer(
{
jwt: "jwt"
jwt: "jwt",
},
{
type: "CLEAR_JWT"
type: "CLEAR_JWT",
}
)
).toEqual({
jwt: null
jwt: null,
isLoading: false,
});
});
});

+ 33
- 34
mobile/src/help/HelpScreen.js 查看文件

@@ -10,17 +10,17 @@ export default class HelpScreen extends Component {
style={{
flex: 1,
paddingTop: 20,
paddingHorizontal: 10
paddingHorizontal: 10,
}}
>
<Title style={{ marginBottom: 10 }}>LessPass</Title>
<Subheading>How does it work?</Subheading>
<Paragraph style={{ marginBottom: 20 }}>
LessPass is a password manager that doesn't store any data. It computes
a unique password using a site, login and a master password. You don't
need to sync a password vault across every device because LessPass works
offline! It will always generate the same password as long as those three
parameters don't change.
LessPass is a password manager that doesn't store any data. It
computes a unique password using a site, login and a master password.
You don't need to sync a password vault across every device because
LessPass works offline! It will always generate the same password as
long as those three parameters don't change.
</Paragraph>
<Subheading>Master password emoticons</Subheading>
<Image source={require("./fingerprint.png")} />
@@ -29,55 +29,54 @@ export default class HelpScreen extends Component {
The emoticons on the right let you verify that you typed in the right
master password. You will have to wait a second or so before the final
emoticons appear (the delay is for security; if the emoticons were
shown instantly, a shoulder-peeker could derive your password based
on the series of displayed emoticons).
shown instantly, a shoulder-peeker could derive your password based on
the series of displayed emoticons).
</Paragraph>
<Subheading>Options</Subheading>
<Image
source={require("./options.png")}
style={{
width: 360,
height: 102
height: 102,
}}
/>
<Paragraph style={{ marginBottom: 20 }}>
Sometimes sites have specific password rules. For instance, some banks
only accept passwords made of digits. LessPass lets you set parameters for
the generated password (the so called "password profile"). The counter in
particular allows you to generate a new password without having to change
your master password.
only accept passwords made of digits. LessPass lets you set parameters
for the generated password (the so called "password profile"). The
counter in particular allows you to generate a new password without
having to change your master password.
</Paragraph>
<Subheading>Sign In</Subheading>
<Paragraph style={{ marginBottom: 10 }}>
By default, LessPass works offline and doesn't send any data over the
network. For convenience, there's an optional connected mode. This mode
allows you to store the profiles necessary to generate your passwords on
our (or alternatively your own) LessPass server. This is especially useful
if many of your passwords are not based on the default profile (length of
16 characters, all characters allowed). As a password profile does neither
include the master password nor the generated password, there is no
critical information sent to the server.
network. For convenience, there's an optional connected mode. This
mode allows you to store the profiles necessary to generate your
passwords on our (or alternatively your own) LessPass server. This is
especially useful if many of your passwords are not based on the
default profile (length of 16 characters, all characters allowed). As
a password profile does neither include the master password nor the
generated password, there is no critical information sent to the
server.
</Paragraph>
<Paragraph style={{ marginBottom: 20 }}>
The sign-in form asks for your master password. By default, it is used to
generate a password for your LessPass account in the same way as for any other
site. This means the master password itself is never sent to our servers.
If for any reason you don't want to use such a LessPass-generated password
for your LessPass account, you can disable this in the settings.
The sign-in form asks for your master password. By default, it is used
to generate a password for your LessPass account in the same way as
for any other site. This means the master password itself is never
sent to our servers. If for any reason you don't want to use such a
LessPass-generated password for your LessPass account, you can disable
this in the settings.
</Paragraph>
<Subheading>Self-hosted LessPass Database</Subheading>
<Paragraph style={{ marginBottom: 20 }}>
If you are using a self-hosted LessPass database, you can change the base
url in the settings to point to your own server.
</Paragraph>
<Subheading>Sign Out</Subheading>
<Paragraph style={{ marginBottom: 20 }}>
You can sign out using the Sign Out button in the settings.
If you are using a self-hosted LessPass database, you can change the
base url in the settings to point to your own server.
</Paragraph>
<Subheading>Support</Subheading>
<Paragraph>
Still need some help? No problem, you can send us an email at
contact@lesspass.com. You can write your email in English or French.
Still need some help? Or you have an idea on how to improve LessPass.
You can send us an email at contact@lesspass.com. You can write your
email in English or French.
</Paragraph>
<Button
mode="contained"
@@ -87,7 +86,7 @@ export default class HelpScreen extends Component {
style={{
marginTop: 10,
marginBottom: 60,
backgroundColor: Theme.colors.blue
backgroundColor: Theme.colors.blue,
}}
>
send us an email


+ 9
- 14
mobile/src/password/Options.js 查看文件

@@ -5,10 +5,10 @@ import { Checkbox } from "react-native-paper";

export default class Options extends Component {
state = {
isValid: true
isValid: true,
};

checkOptionsAreValid = options => {
checkOptionsAreValid = (options) => {
const { areOptionsValid } = this.props;
if (areOptionsValid(options)) {
this.setState({ isValid: true });
@@ -29,16 +29,13 @@ export default class Options extends Component {
style={{
...style,
flexDirection: "row",
justifyContent: "space-between"
justifyContent: "space-between",
}}
>
<View
style={{
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
paddingRight: 32,
marginLeft: -6
}}
>
<Checkbox
@@ -47,7 +44,7 @@ export default class Options extends Component {
onPress={() => {
const newOptions = {
...options,
lowercase: !options.lowercase
lowercase: !options.lowercase,
};
this.checkOptionsAreValid(newOptions);
onOptionsChange(newOptions);
@@ -60,7 +57,6 @@ export default class Options extends Component {
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
paddingRight: 32
}}
>
<Checkbox
@@ -69,7 +65,7 @@ export default class Options extends Component {
onPress={() => {
const newOptions = {
...options,
uppercase: !options.uppercase
uppercase: !options.uppercase,
};
this.checkOptionsAreValid(newOptions);
onOptionsChange(newOptions);
@@ -82,7 +78,6 @@ export default class Options extends Component {
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
paddingRight: 32
}}
>
<Checkbox
@@ -91,7 +86,7 @@ export default class Options extends Component {
onPress={() => {
const newOptions = {
...options,
digits: !options.digits
digits: !options.digits,
};
this.checkOptionsAreValid(newOptions);
onOptionsChange(newOptions);
@@ -102,8 +97,8 @@ export default class Options extends Component {
<View
style={{
flexDirection: "row",
justifyContent: "center",
alignItems: "center"
justifyContent: "flex-end",
alignItems: "center",
}}
>
<Checkbox
@@ -112,7 +107,7 @@ export default class Options extends Component {
onPress={() => {
const newOptions = {
...options,
symbols: !options.symbols
symbols: !options.symbols,
};
this.checkOptionsAreValid(newOptions);
onOptionsChange(newOptions);


+ 1
- 2
mobile/src/password/PasswordGeneratorScreen.js 查看文件

@@ -37,11 +37,10 @@ export class PasswordGeneratorScreen extends Component {
}

componentDidMount() {
const { auth, getPasswordProfiles, signOut, navigation } = this.props;
const { auth, getPasswordProfiles, signOut } = this.props;
if (auth.jwt) {
getPasswordProfiles().catch(() => {
signOut();
navigation.navigate("Auth");
});
}
}


+ 11
- 0
mobile/src/routes.js 查看文件

@@ -0,0 +1,11 @@
const routes = {
PASSWORD_GENERATOR: "LessPass",
SETTINGS: "Settings",
HELP: "Help",
AUTH_STACK: "Sign In",
SIGN_IN: "Sign In",
SIGN_UP: "Sign Up",
SIGN_OUT: "My account",
};

export default routes;

+ 1
- 18
mobile/src/settings/SettingsScreen.js 查看文件

@@ -5,11 +5,9 @@ import { Divider, List } from "react-native-paper";
import TouchID from "react-native-touch-id";
import { setGenericPassword } from "react-native-keychain";
import { setSettings } from "./settingsActions";
import { signOut } from "../auth/authActions";
import TextInputModal from "./TextInputModal";
import Switch from "../ui/Switch";
import KeepMasterPasswordOption from "./KeepMasterPasswordOption";
import Theme from "../ui/Theme";
import { version } from "../version.json";

export class SettingsScreen extends Component {
@@ -28,15 +26,9 @@ export class SettingsScreen extends Component {
.catch(error => console.log(error));
}

_signOut = async () => {
const { navigation, signOut } = this.props;
signOut();
navigation.navigate("Auth");
};

render() {
const { fingerprintIsSupported } = this.state;
const { auth, settings, setSettings } = this.props;
const { settings, setSettings } = this.props;
const {
keepMasterPasswordLocally,
lesspassDatabaseDefaultUrl,
@@ -163,13 +155,6 @@ export class SettingsScreen extends Component {
</React.Fragment>
)}
<List.Section title="APPLICATION">
{auth.jwt ? (
<List.Item
theme={{ colors: { text: Theme.colors.red } }}
title="Sign out"
onPress={this._signOut}
/>
) : null}
<List.Item title={`LessPass version: ${version}`} />
</List.Section>
<Divider />
@@ -180,7 +165,6 @@ export class SettingsScreen extends Component {

function mapStateToProps(state) {
return {
auth: state.auth,
settings: state.settings
};
}
@@ -188,7 +172,6 @@ function mapStateToProps(state) {
function mapDispatchToProps(dispatch) {
return {
setSettings: settings => dispatch(setSettings(settings)),
signOut: () => dispatch(signOut())
};
}



+ 10
- 0
mobile/src/ui/LoadingScreen.js 查看文件

@@ -0,0 +1,10 @@
import React from "react";
import { ActivityIndicator, View } from "react-native";

const LoadingScreen = () => (
<View style={{ flex: 1, justifyContent: "center" }}>
<ActivityIndicator size="large" color="#ffffff" />
</View>
);

export default LoadingScreen;

+ 2793
- 2437
mobile/yarn.lock
文件差异内容过多而无法显示
查看文件


正在加载...
取消
保存