Преглед на файлове

Migrate react native paper to version 5

Fixes: https://github.com/lesspass/lesspass/issues/677
tags/mobile-v9.7.3
Guillaume Vincent преди 1 година
родител
ревизия
0d4453bb29
променени са 25 файла, в които са добавени 1152 реда и са изтрити 782 реда
  1. +3
    -4
      mobile/android/app/build.gradle
  2. +4
    -4
      mobile/android/app/src/main/res/values-night/colors.xml
  3. +4
    -4
      mobile/android/app/src/main/res/values/colors.xml
  4. +2
    -2
      mobile/ios/LessPass.xcodeproj/project.pbxproj
  5. +26
    -26
      mobile/package.json
  6. +6
    -4
      mobile/src/AppContainer.js
  7. +29
    -11
      mobile/src/auth/DeleteMyAccountModal.js
  8. +12
    -13
      mobile/src/auth/SignInScreen.js
  9. +6
    -5
      mobile/src/auth/SignOutScreen.js
  10. +70
    -86
      mobile/src/auth/SignUpScreen.js
  11. +2
    -1
      mobile/src/auth/authActions.js
  12. +1
    -1
      mobile/src/errors/Errors.js
  13. +3
    -2
      mobile/src/help/HelpScreen.js
  14. +19
    -9
      mobile/src/password/Counter.js
  15. +1
    -1
      mobile/src/password/Options.js
  16. +4
    -6
      mobile/src/password/PasswordGeneratorScreen.js
  17. +32
    -38
      mobile/src/password/TouchId.js
  18. +0
    -4
      mobile/src/profiles/ProfilesScreen.js
  19. +0
    -1
      mobile/src/settings/SettingsScreen.js
  20. +2
    -11
      mobile/src/ui/Styles.js
  21. +16
    -18
      mobile/src/ui/TextInput.js
  22. +0
    -62
      mobile/src/ui/Theme.js
  23. +126
    -0
      mobile/src/ui/Theme.ts
  24. +1
    -1
      mobile/src/version.json
  25. +783
    -468
      mobile/yarn.lock

+ 3
- 4
mobile/android/app/build.gradle Целия файл

@@ -147,8 +147,8 @@ android {
applicationId "com.lesspass.android"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 9007002
versionName "9.7.2"
versionCode 9007003
versionName "9.7.3"
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()

if (isNewArchitectureEnabled()) {
@@ -257,9 +257,8 @@ android {
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
defaultConfig.versionCode * 1000 + versionCodes.get(abi)
defaultConfig.versionCode * 100 + versionCodes.get(abi)
}

}
}
}


+ 4
- 4
mobile/android/app/src/main/res/values-night/colors.xml Целия файл

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="statusBarColor">#2E2E2E</color>
<color name="colorPrimary">#F3F3F3</color>
<color name="backgroundColor">#4D4D4D</color>
<color name="navigationBarColor">#2E2E2E</color>
<color name="statusBarColor">#1b1b1f</color>
<color name="colorPrimary">#bfc2ff</color>
<color name="backgroundColor">#46464f</color>
<color name="navigationBarColor">#1b1b1f</color>
</resources>

+ 4
- 4
mobile/android/app/src/main/res/values/colors.xml Целия файл

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="statusBarColor">#FFFFFF</color>
<color name="colorPrimary">#2E2E2E</color>
<color name="backgroundColor">#F3F3F3</color>
<color name="navigationBarColor">#FFFFFF</color>
<color name="statusBarColor">#fffbff</color>
<color name="colorPrimary">#4951c3</color>
<color name="backgroundColor">#e4e1ec</color>
<color name="navigationBarColor">#fffbff</color>
</resources>

+ 2
- 2
mobile/ios/LessPass.xcodeproj/project.pbxproj Целия файл

@@ -529,7 +529,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 9.7.2;
MARKETING_VERSION = 9.7.3;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -557,7 +557,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 9.7.2;
MARKETING_VERSION = 9.7.3;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",


+ 26
- 26
mobile/package.json Целия файл

@@ -1,6 +1,6 @@
{
"name": "lesspass-mobile",
"version": "9.7.2",
"version": "9.7.3",
"description": "LessPass mobile application",
"license": "(MPL-2.0 OR GPL-3.0)",
"author": "Guillaume Vincent <guillaume@oslab.fr>",
@@ -21,47 +21,47 @@
},
"dependencies": {
"@react-native-community/async-storage": "^1.12.1",
"@react-navigation/bottom-tabs": "^6.4.0",
"@react-navigation/native": "^6.0.13",
"@react-navigation/native-stack": "^6.9.1",
"@react-navigation/stack": "^6.3.2",
"axios": "^0.27.2",
"fuzzysort": "^2.0.1",
"@react-navigation/bottom-tabs": "^6.5.2",
"@react-navigation/native": "^6.1.1",
"@react-navigation/native-stack": "^6.9.7",
"@react-navigation/stack": "^6.3.10",
"axios": "^1.2.1",
"fuzzysort": "^2.0.4",
"lesspass-fingerprint": "^9.1.9",
"lesspass-render-password": "^9.1.9",
"lodash": "^4.17.21",
"react": "18.2.0",
"react-native": "0.70.6",
"react-native-gesture-handler": "^2.7.1",
"react-native-gesture-handler": "^2.8.0",
"react-native-keychain": "^8.1.1",
"react-native-paper": "^4.12.5",
"react-native-paper": "^5.1.0",
"react-native-safe-area-context": "^4.4.1",
"react-native-screens": "^3.18.2",
"react-native-touch-id": "^4.4.1",
"react-native-touch-id": "https://github.com/lesspass/react-native-touch-id",
"react-native-vector-icons": "^9.2.0",
"react-redux": "^8.0.4",
"react-redux": "^8.0.5",
"redux": "^4.2.0",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.4.1"
"redux-thunk": "^2.4.2"
},
"devDependencies": {
"@babel/core": "^7.19.6",
"@babel/runtime": "^7.12.5",
"@react-native-community/eslint-config": "^3.1.0",
"@tsconfig/react-native": "^2.0.2",
"@types/jest": "^29.2.0",
"@types/react-native": "^0.70.6",
"@babel/core": "^7.20.7",
"@babel/runtime": "^7.20.7",
"@react-native-community/eslint-config": "^3.2.0",
"@tsconfig/react-native": "^2.0.3",
"@types/jest": "^29.2.4",
"@types/react-native": "^0.70.8",
"@types/react-test-renderer": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.40.1",
"@typescript-eslint/parser": "^5.40.1",
"babel-jest": "^29.2.1",
"eslint": "^8.25.0",
"jest": "^29.2.1",
"metro-react-native-babel-preset": "0.73.2",
"prettier": "^2.7.1",
"@typescript-eslint/eslint-plugin": "^5.47.0",
"@typescript-eslint/parser": "^5.47.0",
"babel-jest": "^29.3.1",
"eslint": "^8.30.0",
"jest": "^29.3.1",
"metro-react-native-babel-preset": "0.73.6",
"prettier": "^2.8.1",
"react-native-version": "^4.0.0",
"react-test-renderer": "18.2.0",
"typescript": "^4.8.3"
"typescript": "^4.9.4"
},
"jest": {
"preset": "react-native",


+ 6
- 4
mobile/src/AppContainer.js Целия файл

@@ -12,18 +12,20 @@ import routes from "./routes";
import { getPasswordProfiles } from "./password/profilesActions";
import { refreshTokens, signOut } from "./auth/authActions";
import ProfilesScreen from "./profiles/ProfilesScreen";
import { SafeAreaView, useColorScheme } from "react-native";
import { SafeAreaView } from "react-native";
import Errors from "./errors/Errors";
import Header from "./header/Header";
import Styles from "./ui/Styles";
import { useTheme } from "react-native-paper";
import { getReactNavigationTheme } from "./ui/Theme";

const Tab = createBottomTabNavigator();

export default function App() {
const colorScheme = useColorScheme();
const { isAuthenticated } = useSelector((state) => state.auth);
const dispatch = useDispatch();
const theme = useTheme();

useEffect(() => {
if (isAuthenticated) {
dispatch(refreshTokens())
@@ -37,12 +39,12 @@ export default function App() {
});
}
}, [isAuthenticated, dispatch]);
const reactNavigationTheme = getReactNavigationTheme(colorScheme);
const reactNavigationTheme = getReactNavigationTheme(theme);
return (
<SafeAreaView
style={{
...Styles.container,
backgroundColor: reactNavigationTheme.colors.card,
backgroundColor: theme.colors.background,
}}
>
<Header />


+ 29
- 11
mobile/src/auth/DeleteMyAccountModal.js Целия файл

@@ -11,8 +11,14 @@ export default function DeleteMyAccountModal({ onDeleteConfirmed }) {
return (
<View>
<Portal>
<Dialog onDismiss={() => setShowModal(false)} visible={showModal}>
<Dialog.Title style={{ color: theme.colors.red }}>
<Dialog
onDismiss={() => {
setMasterPassword("");
setShowModal(false);
}}
visible={showModal}
>
<Dialog.Title style={{ color: theme.colors.error }}>
Delete my account
</Dialog.Title>
<Dialog.ScrollArea style={{ maxHeight: 170, paddingHorizontal: 0 }}>
@@ -22,38 +28,50 @@ export default function DeleteMyAccountModal({ onDeleteConfirmed }) {
masterPassword={masterPassword}
onChangeText={setMasterPassword}
/>
<Text style={{ color: theme.colors.red }}>
<Text style={{ color: theme.colors.error }}>
Enter your master password to delete your account. Warning! this
action is irreversible.
</Text>
</View>
</Dialog.ScrollArea>
<Dialog.Actions>
<Button primary onPress={() => setShowModal(false)}>
<Button
primary
onPress={() => {
setMasterPassword("");
setShowModal(false);
}}
>
Cancel
</Button>
<Button
disabled={!masterPassword}
primary
disabled={!masterPassword}
mode="contained"
style={{
borderColor: theme.colors.error,
}}
buttonColor={theme.colors.error}
onPress={() => {
setShowModal(false);
onDeleteConfirmed(masterPassword);
}}
>
<Text style={{ color: theme.colors.red }}>Delete my account</Text>
Delete my account
</Button>
</Dialog.Actions>
</Dialog>
</Portal>
<Button
compact
mode="outlined"
style={{ marginTop: 10, color: theme.colors.red }}
mode="contained"
style={{
borderColor: theme.colors.error,
}}
buttonColor={theme.colors.error}
onPress={() => {
setShowModal(true);
}}
>
<Text style={{ color: theme.colors.red }}>Delete my account</Text>
Delete my account
</Button>
</View>
);


+ 12
- 13
mobile/src/auth/SignInScreen.js Целия файл

@@ -8,7 +8,7 @@ import {
TouchableWithoutFeedback,
Keyboard,
} from "react-native";
import { Text, Button, Title } from "react-native-paper";
import { Text, Button, Title, useTheme } from "react-native-paper";
import MasterPassword from "../password/MasterPassword";
import TextInput from "../ui/TextInput";
import Styles from "../ui/Styles";
@@ -23,9 +23,10 @@ export default function SignInScreen() {
const [isLoading, setIsLoading] = useState(false);
const navigation = useNavigation();
const dispatch = useDispatch();
const settings = useSelector((state) => state.settings);
const { encryptMasterPassword } = settings;

const theme = useTheme();
const encryptMasterPassword = useSelector(
(state) => state.settings.encryptMasterPassword
);
return (
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
@@ -33,7 +34,7 @@ export default function SignInScreen() {
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<ScrollView contentContainerStyle={Styles.innerContainer}>
<Title>Connect to Lesspass Database</Title>
<Title style={Styles.title}>Connect to Lesspass Database</Title>
<TextInput
mode="outlined"
label="Email"
@@ -47,10 +48,12 @@ export default function SignInScreen() {
onChangeText={(password) => setPassword(password)}
/>
<Button
compact
icon={"account-circle"}
mode="contained"
style={Styles.loginSignInButton}
style={{
marginTop: 10,
marginBottom: 30,
}}
disabled={isEmpty(email) || isEmpty(password) || isLoading}
onPress={() => {
setIsLoading(true);
@@ -78,15 +81,11 @@ export default function SignInScreen() {
>
Sign In
</Button>
<Text>Don't have an account?</Text>
<Button
compact
icon="account-circle"
mode="outlined"
style={Styles.loginSignUpButton}
mode="text"
onPress={() => navigation.navigate(routes.SIGN_UP)}
>
Sign Up
Don't have an account? Sign Up
</Button>
</ScrollView>
</TouchableWithoutFeedback>


+ 6
- 5
mobile/src/auth/SignOutScreen.js Целия файл

@@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react";
import { ScrollView, Text } from "react-native";
import { ScrollView } from "react-native";
import { useDispatch } from "react-redux";
import { deleteMyAccount, getCurrentUser, signOut } from "./authActions";
import Styles from "../ui/Styles";
@@ -24,10 +24,11 @@ const SignOutScreen = ({ navigation }) => {
<Title style={{ marginBottom: 10 }}>My Account</Title>
<Paragraph>Email: {email}</Paragraph>
<Button
compact
icon="account-circle"
mode="outlined"
style={Styles.loginSignUpButton}
mode="contained"
style={{
marginTop: 10
}}
onPress={() => {
dispatch(signOut());
navigation.navigate(routes.PASSWORD_GENERATOR);
@@ -36,7 +37,7 @@ const SignOutScreen = ({ navigation }) => {
Sign out
</Button>
<Title
style={{ marginTop: 50, marginBottom: 10, color: theme.colors.red }}
style={{ marginTop: 60, marginBottom: 10, color: theme.colors.error }}
>
Danger zone
</Title>


+ 70
- 86
mobile/src/auth/SignUpScreen.js Целия файл

@@ -1,5 +1,4 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import React, { useState } from "react";
import {
KeyboardAvoidingView,
ScrollView,
@@ -7,7 +6,7 @@ import {
TouchableWithoutFeedback,
Keyboard,
} from "react-native";
import { Text, Button, Title } from "react-native-paper";
import { Button, Title, useTheme } from "react-native-paper";
import MasterPassword from "../password/MasterPassword";
import TextInput from "../ui/TextInput";
import Styles from "../ui/Styles";
@@ -15,97 +14,82 @@ import { addError } from "../errors/errorsActions";
import { signUp } from "./authActions";
import { isEmpty } from "lodash";
import routes from "../routes";
import { useNavigation } from "@react-navigation/native";
import { useDispatch, useSelector } from "react-redux";

export class SignUpScreen extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
isLoading: false,
};
}
export default function SignUpScreen() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [isLoading, setIsLoading] = useState(false);
const navigation = useNavigation();
const dispatch = useDispatch();
const theme = useTheme();
const encryptMasterPassword = useSelector(
(state) => state.settings.encryptMasterPassword
);

render() {
const { email, password, isLoading } = this.state;
const { navigation, settings, addError, signUp } = this.props;
const { encryptMasterPassword } = settings;

return (
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={Styles.container}
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<ScrollView contentContainerStyle={Styles.innerContainer}>
<Title style={Styles.title}>Create an account</Title>
<TextInput
mode="outlined"
label="Email"
value={email}
onChangeText={(text) => this.setState({ email: text.trim() })}
/>
<MasterPassword
label={encryptMasterPassword ? "Master Password" : "Password"}
masterPassword={password}
hideFingerprint={!encryptMasterPassword}
onChangeText={(password) => this.setState({ password })}
/>
<Button
compact
icon="account-circle"
mode="contained"
style={Styles.loginSignInButton}
disabled={isEmpty(email) || isEmpty(password) || isLoading}
onPress={() => {
this.setState({ isLoading: true });
return (
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={Styles.container}
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<ScrollView contentContainerStyle={Styles.innerContainer}>
<Title style={Styles.title}>Create an account</Title>
<TextInput
mode="outlined"
label="Email"
value={email}
onChangeText={setEmail}
/>
<MasterPassword
label={encryptMasterPassword ? "Master Password" : "Password"}
masterPassword={password}
hideFingerprint={!encryptMasterPassword}
onChangeText={setPassword}
/>
<Button
icon="account-circle"
mode="contained"
style={{
marginTop: 10,
marginBottom: 30,
}}
disabled={isEmpty(email) || isEmpty(password) || isLoading}
onPress={() => {
setIsLoading(true);
dispatch(
signUp(
{
email,
email: email.trim(),
password,
},
encryptMasterPassword
)
.then(() => navigation.navigate(routes.PASSWORD_GENERATOR))
.catch(() => {
this.setState({ isLoading: false });
)
.then(() => navigation.navigate(routes.PASSWORD_GENERATOR))
.catch(() => {
dispatch(
addError(
"Unable to sign up. Try in a few minutes or contact an administrator."
);
});
}}
>
Sign Up
</Button>
<Text>Already have an account?</Text>
<Button
compact
icon="account-circle"
mode="outlined"
style={Styles.loginSignUpButton}
onPress={() => navigation.navigate(routes.SIGN_IN)}
>
Sign In
</Button>
</ScrollView>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
}
}

function mapStateToProps(state) {
return {
settings: state.settings,
};
)
);
})
.finally(() => {
setIsLoading(false);
});
}}
>
Sign Up
</Button>
<Button
mode="text"
onPress={() => navigation.navigate(routes.SIGN_IN)}
>
Already have an account? Sign In
</Button>
</ScrollView>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
}

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

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

+ 2
- 1
mobile/src/auth/authActions.js Целия файл

@@ -79,7 +79,8 @@ export function refreshTokens() {
.post(`${settings.baseURL}/auth/jwt/refresh/`, {
refresh: auth.refreshToken,
})
.then((response) => dispatch(setJWT(response.data)));
.then((response) => dispatch(setJWT(response.data)))
.catch(console.log);
};
}



+ 1
- 1
mobile/src/errors/Errors.js Целия файл

@@ -13,7 +13,7 @@ export default function Errors() {
<Snackbar
key={error.id}
visible={true}
style={{ backgroundColor: theme.colors.red }}
style={{ backgroundColor: theme.colors.error }}
onDismiss={() => dispatch(deleteError(error))}
action={{
label: "x",


+ 3
- 2
mobile/src/help/HelpScreen.js Целия файл

@@ -1,9 +1,10 @@
import React from "react";
import { ScrollView, Image, Linking, View } from "react-native";
import { Title, Subheading, Paragraph, Button } from "react-native-paper";
import { Title, Subheading, Paragraph, Button, useTheme } from "react-native-paper";
import Styles from "../ui/Styles";

export default function HelpScreen() {
const theme = useTheme()
return (
<ScrollView contentContainerStyle={Styles.innerContainer}>
<Title style={Styles.title}>Help</Title>
@@ -82,7 +83,7 @@ export default function HelpScreen() {
marginTop: 10,
}}
>
send us an email
Send us an email
</Button>
</ScrollView>
);


+ 19
- 9
mobile/src/password/Counter.js Целия файл

@@ -19,8 +19,8 @@ export default function Counter({
setIsValid(false);
}
}, [value]);
const color = isValid ? theme.colors.placeholder : theme.colors.red;
const colorAccent = isValid ? theme.colors.accent : theme.colors.red;
const color = isValid ? theme.colors.primary : theme.colors.error;
const borderColor = isValid ? theme.colors.outline : theme.colors.error;
return (
<View {...props}>
<Text
@@ -37,10 +37,6 @@ export default function Counter({
justifyContent: "center",
alignItems: "center",
height: 26,
borderWidth: 1,
borderColor: colorAccent,
borderRadius: theme.roundness,
backgroundColor: colorAccent,
}}
>
<TouchableOpacity
@@ -50,6 +46,11 @@ export default function Counter({
alignSelf: "stretch",
paddingVertical: 6,
paddingHorizontal: 16,
backgroundColor: isValid
? theme.colors.primary
: theme.colors.error,
borderTopLeftRadius: 5 * theme.roundness,
borderBottomLeftRadius: 5 * theme.roundness,
}}
onPress={() => setValue(value - 1)}
>
@@ -57,7 +58,7 @@ export default function Counter({
size={12}
name="minus"
style={{
color: theme.colors.background,
color: isValid ? theme.colors.onPrimary : theme.colors.onError,
}}
/>
</TouchableOpacity>
@@ -65,7 +66,11 @@ export default function Counter({
style={{
justifyContent: "center",
alignItems: "center",
backgroundColor: theme.colors.background,
borderWidth: 0,
borderTopWidth: 1,
borderTopColor: borderColor,
borderBottomWidth: 1,
borderBottomColor: borderColor,
}}
>
<TextInput
@@ -104,6 +109,11 @@ export default function Counter({
alignSelf: "stretch",
paddingVertical: 6,
paddingHorizontal: 16,
backgroundColor: isValid
? theme.colors.primary
: theme.colors.error,
borderTopRightRadius: 5 * theme.roundness,
borderBottomRightRadius: 5 * theme.roundness,
}}
onPress={() => setValue(value + 1)}
>
@@ -111,7 +121,7 @@ export default function Counter({
size={12}
name="plus"
style={{
color: theme.colors.background,
color: isValid ? theme.colors.onPrimary : theme.colors.onError,
}}
/>
</TouchableOpacity>


+ 1
- 1
mobile/src/password/Options.js Целия файл

@@ -6,7 +6,7 @@ import { areOptionsValid } from "./validations";
export default function Options({ options, onOptionsChange, style }) {
const [isValid, setIsvalid] = useState(true);
const theme = useTheme();
const color = isValid ? theme.colors.placeholder : theme.colors.red;
const color = isValid ? theme.colors.secondary : theme.colors.error;

useEffect(() => {
if (areOptionsValid(options)) {


+ 4
- 6
mobile/src/password/PasswordGeneratorScreen.js Целия файл

@@ -96,13 +96,11 @@ export default function PasswordGeneratorScreen() {
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<ScrollView contentContainerStyle={Styles.innerContainer}>
<TextInput
mode="outlined"
label="Site"
value={state.site}
onChangeText={(site) => setState((state) => ({ ...state, site }))}
/>
<TextInput
mode="outlined"
label="Login"
value={state.login}
onChangeText={(login) => setState((state) => ({ ...state, login }))}
@@ -199,7 +197,7 @@ export default function PasswordGeneratorScreen() {
style={{ marginRight: 10, marginBottom: 10 }}
icon="refresh"
>
clear
CLEAR
</Button>
{state.password && state.copyPasswordAfterGeneration === false && (
<Button
@@ -223,7 +221,7 @@ export default function PasswordGeneratorScreen() {
icon="eye"
style={{ marginRight: 10, marginBottom: 10 }}
>
{seePassword ? "hide" : "show"}
{seePassword ? "HIDE" : "SHOW"}
</Button>
)}
{state.password && auth.isAuthenticated ? (
@@ -242,7 +240,7 @@ export default function PasswordGeneratorScreen() {
icon="content-save"
style={{ marginRight: 10, marginBottom: 10 }}
>
Save
SAVE
</Button>
) : (
<Button
@@ -259,7 +257,7 @@ export default function PasswordGeneratorScreen() {
icon="content-save"
style={{ marginRight: 10, marginBottom: 10 }}
>
Update
UPDATE
</Button>
)
) : null}


+ 32
- 38
mobile/src/password/TouchId.js Целия файл

@@ -1,44 +1,38 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import React from "react";
import { useSelector } from "react-redux";
import TouchID from "react-native-touch-id";
import { View } from "react-native";
import { IconButton } from "react-native-paper";
import { IconButton, useTheme } from "react-native-paper";
import Styles from "../ui/Styles";
import { getGenericPassword } from "react-native-keychain";

export class TouchId extends Component {
getMasterPasswordSavedLocally = () => {
const { onChangeText } = this.props;
TouchID.authenticate()
.then(() => {
return getGenericPassword().then((credentials) => {
if (credentials) {
onChangeText(credentials.password);
}
});
})
.catch(console.log);
};

render() {
const { settings } = this.props;
const { keepMasterPasswordLocally = false } = settings;
if (!keepMasterPasswordLocally) return null;
return (
<View style={Styles.fingerprint}>
<IconButton
icon="fingerprint"
onPress={() => this.getMasterPasswordSavedLocally()}
/>
</View>
);
}
}

function mapStateToProps(state) {
return {
settings: state.settings,
};
export default function TouchId({ onChangeText }) {
const theme = useTheme();
const keepMasterPasswordLocally = useSelector(
(state) => state.settings.keepMasterPasswordLocally
);
if (!keepMasterPasswordLocally) return null;
return (
<View style={Styles.fingerprint}>
<IconButton
icon="fingerprint"
onPress={() => {
TouchID.authenticate("Get master password saved locally", {
imageColor: theme.colors.primary,
imageErrorColor: theme.colors.error,
cancelTextColor: theme.colors.onPrimary,
cancelButtonColor: theme.colors.primary
})
.then(() =>
getGenericPassword().then((credentials) => {
if (credentials) {
onChangeText(credentials.password);
}
})
)
.catch(console.log);
}}
/>
</View>
);
}

export default connect(mapStateToProps)(TouchId);

+ 0
- 4
mobile/src/profiles/ProfilesScreen.js Целия файл

@@ -109,8 +109,6 @@ export default function ProfilesScreen() {
description={
"There is no password profile that matches this search."
}
titleStyle={{ color: theme.colors.primary }}
descriptionStyle={{ color: theme.colors.primary }}
/>
) : (
sortByNewestFirst(results).map((profile) => (
@@ -123,8 +121,6 @@ export default function ProfilesScreen() {
setQuery("");
navigation.navigate(routes.PASSWORD_GENERATOR);
}}
titleStyle={{ color: theme.colors.primary }}
descriptionStyle={{ color: theme.colors.primary }}
right={(props) => (
<IconButton
{...props}


+ 0
- 1
mobile/src/settings/SettingsScreen.js Целия файл

@@ -175,7 +175,6 @@ export class SettingsScreen extends Component {
/>
<Divider />
<List.Item title={`LessPass version: ${version}`} />
<Divider />
</List.Section>
</ScrollView>
);


+ 2
- 11
mobile/src/ui/Styles.js Целия файл

@@ -17,11 +17,9 @@ export default StyleSheet.create({
},
fingerprint: {
position: "absolute",
right: 3,
top: 0,
right: 0,
top: 6,
bottom: 0,
justifyContent: "center",
alignItems: "center",
zIndex: 4,
},
switch: {
@@ -31,11 +29,4 @@ export default StyleSheet.create({
paddingVertical: 8,
paddingHorizontal: 10,
},
loginSignInButton: {
marginTop: 10,
marginBottom: 30,
},
loginSignUpButton: {
marginTop: 10,
},
});

+ 16
- 18
mobile/src/ui/TextInput.js Целия файл

@@ -1,21 +1,19 @@
import React, { Component } from "react";
import React from "react";
import { View } from "react-native";
import { TextInput } from "react-native-paper";
import styles from "./Styles";
import { TextInput, useTheme } from "react-native-paper";

export default class Input extends Component {
render() {
const { showError = false, errorText, ...props } = this.props;
return (
<View>
<TextInput
autoCapitalize="none"
autoCorrect={false}
style={styles.input}
mode="outlined"
{...props}
/>
</View>
);
}
export default function Input({ showError = false, errorText, ...props }) {
const theme = useTheme();
return (
<TextInput
autoCapitalize="none"
autoCorrect={false}
outlineStyle={{
borderRadius: 5 * theme.roundness,
}}
style={{marginBottom:5}}
mode="outlined"
{...props}
/>
);
}

+ 0
- 62
mobile/src/ui/Theme.js Целия файл

@@ -1,62 +0,0 @@
import { DefaultTheme } from "react-native-paper";
import {
DefaultTheme as DefaultThemeReactNavigation,
DarkTheme as DarkThemeReactNavigation,
} from "@react-navigation/native";

export function getReactNavigationTheme(colorScheme) {
const isDarkTheme = colorScheme === "dark";
if (isDarkTheme) {
return {
...DarkThemeReactNavigation,
dark: isDarkTheme,
colors: {
...DarkThemeReactNavigation.colors,
card: "#2E2E2E",
primary: "#F3F3F3",
text: "#F3F3F3",
border: "#2E2E2E",
background: "#4D4D4D",
},
};
}
return {
...DefaultThemeReactNavigation,
dark: isDarkTheme,
colors: {
...DefaultThemeReactNavigation.colors,
card: "#FFFFFF",
text: "#4D4D4D",
primary: "#2E2E2E",
},
};
}

export function getTheme(colorScheme) {
const isDarkTheme = colorScheme === "dark";
if (isDarkTheme) {
return {
...DefaultTheme,
dark: isDarkTheme,
colors: {
...DefaultTheme.colors,
primary: "#F3F3F3",
accent: "#DEDEDE",
text: "#F3F3F3",
placeholder: "#DEDEDE",
background: "#4D4D4D",
red: "#f32c1e",
},
};
}
return {
...DefaultTheme,
dark: isDarkTheme,
colors: {
...DefaultTheme.colors,
primary: "#2E2E2E",
accent: "#2E2E2E",
red: "#f32c1e",
},
};
}

+ 126
- 0
mobile/src/ui/Theme.ts Целия файл

@@ -0,0 +1,126 @@
import { DefaultTheme, MD3Theme } from "react-native-paper";
import {
DefaultTheme as DefaultThemeReactNavigation,
DarkTheme as DarkThemeReactNavigation,
Theme,
} from "@react-navigation/native";

export function getReactNavigationTheme(theme: MD3Theme): Theme {
const reactNativeTheme = theme.dark
? DarkThemeReactNavigation
: DefaultThemeReactNavigation;
return {
...reactNativeTheme,
dark: theme.dark,
colors: {
...reactNativeTheme.colors,
text: theme.colors.secondary,
primary: theme.colors.primary,
card: theme.colors.background,
},
};
}

export function getTheme(colorScheme: string | undefined | null): MD3Theme {
const isDarkTheme = typeof colorScheme === "string" && colorScheme === "dark";
if (isDarkTheme) {
return {
...DefaultTheme,
dark: isDarkTheme,
mode: "adaptive",
roundness: 1,
colors: {
...DefaultTheme.colors,
primary: "#bfc2ff",
onPrimary: "#141994",
primaryContainer: "#3037aa",
onPrimaryContainer: "#e0e0ff",
secondary: "#c5c4dd",
onSecondary: "#2e2f42",
secondaryContainer: "#444559",
onSecondaryContainer: "#e1e0f9",
tertiary: "#e8b9d5",
onTertiary: "#46263b",
tertiaryContainer: "#5e3c52",
onTertiaryContainer: "#ffd8ee",
error: "#ffb4ab",
onError: "#690005",
errorContainer: "#93000a",
onErrorContainer: "#ffb4ab",
background: "#1b1b1f",
onBackground: "#e5e1e6",
surface: "#1b1b1f",
onSurface: "#e5e1e6",
surfaceVariant: "#46464f",
onSurfaceVariant: "#c7c5d0",
outline: "#918f9a",
outlineVariant: "#46464f",
shadow: "#000000",
scrim: "#000000",
inverseSurface: "#e5e1e6",
inverseOnSurface: "#303034",
inversePrimary: "#4951c3",
elevation: {
level0: "transparent",
level1: "#23232a",
level2: "#282831",
level3: "#2d2d38",
level4: "#2f2f3a",
level5: "#32323e",
},
surfaceDisabled: "#e5e1e6ff",
onSurfaceDisabled: "#e5e1e6ff",
backdrop: "#303038ff",
},
};
}
return {
...DefaultTheme,
dark: isDarkTheme,
mode: "adaptive",
roundness: 1,
colors: {
...DefaultTheme.colors,
primary: "#4951c3",
onPrimary: "#ffffff",
primaryContainer: "#e0e0ff",
onPrimaryContainer: "#00006e",
secondary: "#5c5d72",
onSecondary: "#ffffff",
secondaryContainer: "#e1e0f9",
onSecondaryContainer: "#191a2c",
tertiary: "#78536b",
onTertiary: "#ffffff",
tertiaryContainer: "#ffd8ee",
onTertiaryContainer: "#2e1126",
error: "#ba1a1a",
onError: "#ffffff",
errorContainer: "#ffdad6",
onErrorContainer: "#410002",
background: "#fffbff",
onBackground: "#1b1b1f",
surface: "#fffbff",
onSurface: "#1b1b1f",
surfaceVariant: "#e4e1ec",
onSurfaceVariant: "#46464f",
outline: "#777680",
outlineVariant: "#c7c5d0",
shadow: "#000000",
scrim: "#000000",
inverseSurface: "#303034",
inverseOnSurface: "#f3eff4",
inversePrimary: "#bfc2ff",
elevation: {
level0: "transparent",
level1: "#f6f3fc",
level2: "#f0edfa",
level3: "#ebe8f8",
level4: "#e9e7f8",
level5: "#e6e3f7",
},
surfaceDisabled: "#1b1b1f1e",
onSurfaceDisabled: "#1b1b1f60",
backdrop: "#30303866",
},
};
}

+ 1
- 1
mobile/src/version.json Целия файл

@@ -1,3 +1,3 @@
{
"version": "9.7.2"
"version": "9.7.3"
}

+ 783
- 468
mobile/yarn.lock
Файловите разлики са ограничени, защото са твърде много
Целия файл


Зареждане…
Отказ
Запис