Merge branch 'chore/merge-back-release' into 'main'

Merge back from release -> main

See merge request bloodyhealth/drip!476
This commit is contained in:
Sofiya Tepikin
2022-08-15 18:55:36 +00:00
15 changed files with 127 additions and 128 deletions
+6 -6
View File
@@ -12,7 +12,7 @@ import AppStatusBar from './common/app-status-bar'
import License from './License'
import PasswordPrompt from './password-prompt'
import store from "../store"
import store from '../store'
export default class AppWrapper extends Component {
constructor() {
@@ -51,7 +51,7 @@ export default class AppWrapper extends Component {
enableShowLicenseAgreement = () => {
this.setState({
shouldShowLicenseAgreement: true,
isCheckingLicenseAgreement: false
isCheckingLicenseAgreement: false,
})
}
@@ -62,7 +62,7 @@ export default class AppWrapper extends Component {
enableShowApp = () => {
this.setState({
shouldShowApp: true,
shouldShowPasswordPrompt: false
shouldShowPasswordPrompt: false,
})
}
@@ -79,11 +79,11 @@ export default class AppWrapper extends Component {
if (isCheckingLicenseAgreement) {
initialView = <AppLoadingView />
} else if (shouldShowLicenseAgreement) {
initialView = <License setLicense={this.disableShowLicenseAgreement}/>
initialView = <License setLicense={this.disableShowLicenseAgreement} />
} else if (shouldShowPasswordPrompt) {
initialView = <PasswordPrompt enableShowApp={this.enableShowApp} />
} else if (shouldShowApp) {
initialView = <App />
initialView = <App restartApp={() => this.checkDbPasswordSet()} />
}
return (
@@ -100,5 +100,5 @@ export default class AppWrapper extends Component {
const styles = StyleSheet.create({
container: {
flex: 1,
}
},
})
+12 -15
View File
@@ -17,12 +17,12 @@ import setupNotifications from '../lib/notifications'
import { getCycleDay, closeDb } from '../db'
class App extends Component {
static propTypes = {
date: PropTypes.string,
navigation: PropTypes.object.isRequired,
navigate: PropTypes.func,
goBack: PropTypes.func,
restartApp: PropTypes.func,
}
constructor(props) {
@@ -54,7 +54,7 @@ class App extends Component {
}
render() {
const { date, navigation, goBack } = this.props
const { date, navigation, goBack, restartApp } = this.props
const { currentPage } = navigation
if (!currentPage) {
@@ -80,8 +80,8 @@ class App extends Component {
return (
<View style={styles.container}>
<Header { ...headerProps } />
<Page { ...pageProps } />
<Header {...headerProps} />
<Page {...pageProps} restartApp={restartApp} />
<Menu />
</View>
)
@@ -90,25 +90,22 @@ class App extends Component {
const styles = StyleSheet.create({
container: {
flex: 1
}
flex: 1,
},
})
const mapStateToProps = (state) => {
return({
return {
date: getDate(state),
navigation: getNavigation(state)
})
navigation: getNavigation(state),
}
}
const mapDispatchToProps = (dispatch) => {
return({
return {
navigate: (page) => dispatch(navigate(page)),
goBack: () => dispatch(goBack()),
})
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(App)
export default connect(mapStateToProps, mapDispatchToProps)(App)
+12 -4
View File
@@ -1,4 +1,5 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Button from '../../common/button'
@@ -8,6 +9,10 @@ import showBackUpReminder from './show-backup-reminder'
import settings from '../../../i18n/en/settings'
export default class CreatePassword extends Component {
static propTypes = {
changeEncryptionAndRestart: PropTypes.func,
}
constructor() {
super()
@@ -23,7 +28,7 @@ export default class CreatePassword extends Component {
showBackUpReminder(this.toggleSettingPassword, () => {})
}
render () {
render() {
const { isSettingPassword } = this.state
const labels = settings.passwordSettings
@@ -34,8 +39,11 @@ export default class CreatePassword extends Component {
</Button>
)
} else {
return <EnterNewPassword />
return (
<EnterNewPassword
changeEncryptionAndRestart={this.props.changeEncryptionAndRestart}
/>
)
}
}
}
}
+4 -8
View File
@@ -4,13 +4,13 @@ import PropTypes from 'prop-types'
import Button from '../../common/button'
import ConfirmWithPassword from '../common/confirm-with-password'
import { changeEncryptionAndRestartApp } from '../../../db'
import labels from '../../../i18n/en/settings'
export default class DeletePassword extends Component {
static propTypes = {
onStartDelete: PropTypes.func,
onCancelDelete: PropTypes.func
onCancelDelete: PropTypes.func,
changeEncryptionAndRestart: PropTypes.func,
}
constructor() {
@@ -24,10 +24,6 @@ export default class DeletePassword extends Component {
this.props.onStartDelete()
}
startDeletePassword = async () => {
await changeEncryptionAndRestartApp()
}
cancelConfirmationWithPassword = () => {
this.setState({ enteringCurrentPassword: false })
this.props.onCancelDelete()
@@ -39,7 +35,7 @@ export default class DeletePassword extends Component {
if (enteringCurrentPassword) {
return (
<ConfirmWithPassword
onSuccess={this.startDeletePassword}
onSuccess={this.props.changeEncryptionAndRestart}
onCancel={this.cancelConfirmationWithPassword}
/>
)
@@ -51,4 +47,4 @@ export default class DeletePassword extends Component {
</Button>
)
}
}
}
@@ -1,20 +1,23 @@
import React, { Component } from 'react'
import { StyleSheet } from 'react-native'
import nodejs from 'nodejs-mobile-react-native'
import PropTypes from 'prop-types'
import AppText from '../../common/app-text'
import AppTextInput from '../../common/app-text-input'
import Button from '../../common/button'
import { requestHash, changeEncryptionAndRestartApp } from '../../../db'
import { requestHash } from '../../../db'
import { Colors, Spacing } from '../../../styles'
import settings from '../../../i18n/en/settings'
const LISTENER_TYPE = 'create-or-change-pw'
export default class EnterNewPassword extends Component {
constructor() {
static propTypes = {
changeEncryptionAndRestart: PropTypes.func,
}
constructor(props) {
super()
this.state = {
password: '',
@@ -23,13 +26,16 @@ export default class EnterNewPassword extends Component {
}
nodejs.channel.addListener(
LISTENER_TYPE,
changeEncryptionAndRestartApp,
props.changeEncryptionAndRestart,
this
)
}
componentWillUnmount() {
nodejs.channel.removeListener(LISTENER_TYPE, changeEncryptionAndRestartApp)
nodejs.channel.removeListener(
LISTENER_TYPE,
this.props.changeEncryptionAndRestart
)
}
savePassword = () => {
@@ -52,15 +58,12 @@ export default class EnterNewPassword extends Component {
this.setState({ passwordConfirmation })
}
render () {
const {
password,
passwordConfirmation,
shouldShowErrorMessage
} = this.state
render() {
const { password, passwordConfirmation, shouldShowErrorMessage } =
this.state
const labels = settings.passwordSettings
const isButtonActive =
(password.length > 0) && (passwordConfirmation.length > 0)
password.length > 0 && passwordConfirmation.length > 0
return (
<React.Fragment>
@@ -80,10 +83,14 @@ export default class EnterNewPassword extends Component {
value={passwordConfirmation}
secureTextEntry={true}
/>
{shouldShowErrorMessage &&
{shouldShowErrorMessage && (
<AppText style={styles.error}>{labels.passwordsDontMatch}</AppText>
}
<Button isCTA={isButtonActive} onPress={this.savePassword}>
)}
<Button
isCTA={isButtonActive}
disabled={!isButtonActive}
onPress={this.savePassword}
>
{labels.savePassword}
</Button>
</React.Fragment>
@@ -94,6 +101,6 @@ export default class EnterNewPassword extends Component {
const styles = StyleSheet.create({
error: {
color: Colors.orange,
marginTop: Spacing.base
}
})
marginTop: Spacing.base,
},
})
+44 -22
View File
@@ -1,4 +1,10 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { navigate } from '../../../slices/navigation'
import { changeDbEncryption } from '../../../db'
import AppPage from '../../common/app-page'
import AppText from '../../common/app-text'
@@ -11,14 +17,18 @@ import DeletePassword from './delete'
import { hasEncryptionObservable } from '../../../local-storage'
import labels from '../../../i18n/en/settings'
export default class PasswordSetting extends Component {
class PasswordSetting extends Component {
static propTypes = {
navigate: PropTypes.func,
restartApp: PropTypes.func,
}
constructor(props) {
super(props)
this.state = {
isPasswordSet: hasEncryptionObservable.value,
isChangingPassword: false,
isDeletingPassword: false
isDeletingPassword: false,
}
}
@@ -38,19 +48,17 @@ export default class PasswordSetting extends Component {
this.setState({ isDeletingPassword: false })
}
changeEncryptionAndRestart = async (hash) => {
await changeDbEncryption(hash)
await this.props.restartApp()
this.props.navigate('Home')
}
render() {
const { isPasswordSet, isChangingPassword, isDeletingPassword } = this.state
const {
isPasswordSet,
isChangingPassword,
isDeletingPassword,
} = this.state
const {
title,
explainerEnabled,
explainerDisabled
} = labels.passwordSettings
const { title, explainerEnabled, explainerDisabled } =
labels.passwordSettings
return (
<AppPage>
@@ -59,19 +67,25 @@ export default class PasswordSetting extends Component {
{isPasswordSet ? explainerEnabled : explainerDisabled}
</AppText>
{!isPasswordSet && <CreatePassword/>}
{(isPasswordSet && !isDeletingPassword) && (
<ChangePassword
onStartChange = {this.onChangingPassword}
onCancelChange = {this.onCancelChangingPassword}
{!isPasswordSet && (
<CreatePassword
changeEncryptionAndRestart={this.changeEncryptionAndRestart}
/>
)}
{(isPasswordSet && !isChangingPassword) && (
{isPasswordSet && !isDeletingPassword && (
<ChangePassword
onStartChange={this.onChangingPassword}
onCancelChange={this.onCancelChangingPassword}
changeEncryptionAndRestart={this.changeEncryptionAndRestart}
/>
)}
{isPasswordSet && !isChangingPassword && (
<DeletePassword
onStartDelete = {this.onDeletingPassword}
onCancelDelete = {this.onCancelDeletingPassword}
onStartDelete={this.onDeletingPassword}
onCancelDelete={this.onCancelDeletingPassword}
changeEncryptionAndRestart={this.changeEncryptionAndRestart}
/>
)}
</Segment>
@@ -79,3 +93,11 @@ export default class PasswordSetting extends Component {
)
}
}
const mapDispatchToProps = (dispatch) => {
return {
navigate: (page) => dispatch(navigate(page)),
}
}
export default connect(null, mapDispatchToProps)(PasswordSetting)
+13 -11
View File
@@ -12,7 +12,8 @@ import settings from '../../../i18n/en/settings'
export default class ChangePassword extends Component {
static propTypes = {
onStartChange: PropTypes.func,
onCancelChange: PropTypes.func
onCancelChange: PropTypes.func,
changeEncryptionAndRestart: PropTypes.func,
}
constructor() {
@@ -21,7 +22,7 @@ export default class ChangePassword extends Component {
this.state = {
currentPassword: null,
enteringCurrentPassword: false,
enteringNewPassword: false
enteringNewPassword: false,
}
}
@@ -41,7 +42,7 @@ export default class ChangePassword extends Component {
this.setState({
currentPassword: null,
enteringNewPassword: true,
enteringCurrentPassword: false
enteringCurrentPassword: false,
})
}
@@ -49,17 +50,14 @@ export default class ChangePassword extends Component {
this.setState({
currentPassword: null,
enteringNewPassword: false,
enteringCurrentPassword: false
enteringCurrentPassword: false,
})
this.props.onCancelChange()
}
render() {
const {
enteringCurrentPassword,
enteringNewPassword,
currentPassword
} = this.state
const { enteringCurrentPassword, enteringNewPassword, currentPassword } =
this.state
const labels = settings.passwordSettings
const isPasswordSet = currentPassword !== null
@@ -73,7 +71,11 @@ export default class ChangePassword extends Component {
}
if (enteringNewPassword) {
return <EnterNewPassword />
return (
<EnterNewPassword
changeEncryptionAndRestart={this.props.changeEncryptionAndRestart}
/>
)
}
return (
@@ -86,4 +88,4 @@ export default class ChangePassword extends Component {
</Button>
)
}
}
}
+2 -9
View File
@@ -2,7 +2,6 @@ import Realm from 'realm'
import { LocalDate, ChronoUnit } from '@js-joda/core'
import nodejs from 'nodejs-mobile-react-native'
import fs from 'react-native-fs'
import { restartApp } from './restart-app'
import schemas from './schemas'
import cycleModule from '../lib/cycle'
@@ -195,7 +194,7 @@ export function requestHash(type, pw) {
)
}
export async function changeEncryptionAndRestartApp(hash) {
export async function changeDbEncryption(hash) {
let key
if (hash) key = hashToInt8Array(hash)
const defaultPath = db.path
@@ -205,16 +204,10 @@ export async function changeEncryptionAndRestartApp(hash) {
const copyPath = dir.join('/')
const exists = await fs.exists(copyPath)
if (exists) await fs.unlink(copyPath)
// for some reason, realm complains if we give it a key with value undefined
if (key) {
db.writeCopyTo(copyPath, key)
} else {
db.writeCopyTo(copyPath)
}
db.writeCopyTo({ path: copyPath, encryptionKey: key })
db.close()
await fs.unlink(defaultPath)
await fs.moveFile(copyPath, defaultPath)
restartApp()
}
export function isDbEmpty() {
-5
View File
@@ -1,5 +0,0 @@
// Current version of react-native-restart doesn't work with our ios setup
// therefore we have a fork and use different libraries on the platforms
import restart from 'react-native-restart'
export const restartApp = restart.Restart
-11
View File
@@ -1,11 +0,0 @@
// Current version of react-native-restart doesn't work with our ios setup
// therefore we have a fork and use different libraries on the platforms
import RNExitApp from 'react-native-exit-app-v2'
import { Alert } from 'react-native'
export const restartApp = () => {
Alert.alert('Closing app', 'App is shutting down. Please restart.')
setTimeout(() => {
RNExitApp.exitApp()
}, 3000)
}
+1 -1
View File
@@ -17,7 +17,7 @@
"settings": {
"license": {
"title": "drip. an open-source cycle tracking app",
"text": "Copyright (C) {{currentYear}} Heart of Code e.V.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: https://www.gnu.org/licenses/gpl-3.0.html\n\nYou can contact us at drip@mailbox.org."
"text": "Copyright (C) {{currentYear}} Heart of Code e.V.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: https://www.gnu.org/licenses/gpl-3.0.html."
},
"privacyPolicy": {
"title": "Privacy Policy",
+2 -2
View File
@@ -897,7 +897,7 @@
"\"${PODS_ROOT}/../../node_modules/realm/vendor/realm-ios\"",
"$(inherited)",
);
MARKETING_VERSION = 1.2208.2;
MARKETING_VERSION = 1.2208.11;
OTHER_LDFLAGS = (
"-ObjC",
"-lc++",
@@ -980,7 +980,7 @@
"\"${PODS_ROOT}/../../node_modules/realm/vendor/realm-ios\"",
"$(inherited)",
);
MARKETING_VERSION = 1.2208.2;
MARKETING_VERSION = 1.2208.11;
OTHER_LDFLAGS = (
"-ObjC",
"-lc++",
+4 -2
View File
@@ -22,6 +22,8 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
@@ -81,9 +83,9 @@
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
</dict>
</plist>
+1 -11
View File
@@ -1,6 +1,6 @@
{
"name": "drip.",
"version": "1.2208.2",
"version": "1.2208.11",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -15384,11 +15384,6 @@
"resolved": "https://registry.npmjs.org/react-native-document-picker/-/react-native-document-picker-4.3.0.tgz",
"integrity": "sha512-ygcY0ijlVuhxzdWnhqd917yMUFT9FF0b4CM81LWoY4/bpQYz5PGUdRAdh25kS0VA+cEUYNL2iI7OpHXq00epPA=="
},
"react-native-exit-app-v2": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/react-native-exit-app-v2/-/react-native-exit-app-v2-1.2.2.tgz",
"integrity": "sha512-RWCfmus7h99M1aONqBnWG3g3TFRzKsmok6cLAuqN5NVQAxpcgzbJZgAryA/ADpmBrBP5EIJnCBFo64ApQGOZPw=="
},
"react-native-fs": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.20.0.tgz",
@@ -15423,11 +15418,6 @@
"@react-native-community/push-notification-ios": "^1.0.1"
}
},
"react-native-restart": {
"version": "0.0.24",
"resolved": "https://registry.npmjs.org/react-native-restart/-/react-native-restart-0.0.24.tgz",
"integrity": "sha512-pvJNU3NwQk6bCG2gOWcQpZ4IxhtELB0K9gzmtixfsaTFbW1UXXHkJNjk1kHazcbH5hrD7QbUkR63fsAVh8X4VQ=="
},
"react-native-share": {
"version": "3.8.5",
"resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-3.8.5.tgz",
+1 -3
View File
@@ -1,6 +1,6 @@
{
"name": "drip.",
"version": "1.2208.2",
"version": "1.2208.11",
"contributors": [
"Julia Friesel <julia.friesel@gmail.com>",
"Marie Kochsiek",
@@ -46,12 +46,10 @@
"react-native": "0.62.0",
"react-native-calendars": "^1.1287.0",
"react-native-document-picker": "^4.2.0",
"react-native-exit-app-v2": "^1.2.2",
"react-native-fs": "^2.20.0",
"react-native-hyperlink": "0.0.19",
"react-native-modal-datetime-picker": "8.0.0",
"react-native-push-notification": "3.2.1",
"react-native-restart": "0.0.24",
"react-native-share": "^3.0.0",
"react-native-simple-toast": "^1.1.3",
"react-native-size-matters": "^0.4.0",