diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..6e87a00
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,13 @@
+# Editor configuration, see http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/App.js b/App.js
index 52f5fa9..aa0aeef 100644
--- a/App.js
+++ b/App.js
@@ -1,4 +1,3 @@
-import { StatusBar } from 'expo-status-bar';
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Text, View, StyleSheet } from 'react-native';
@@ -10,14 +9,14 @@ export default function App() {
const [data, setData] = useState([]);
- function fromHex(hex,str){
- try{
- str = decodeURIComponent(hex.replace(/(..)/g,'%$1'))
+ function fromHex(hex, str) {
+ try {
+ str = decodeURIComponent(hex.replace(/(..)/g, '%$1'))
str = JSON.parse(str)
setData(str)
setLoading(false)
}
- catch(e){
+ catch (e) {
return
//str = hex
//console.log('invalid hex input: ' + hex)
@@ -34,12 +33,12 @@ export default function App() {
body: JSON.stringify({
jsonrpc: '2.0',
method: 'f_transaction_json',
- params: {hash: transactions[tx].hash}
+ params: { hash: transactions[tx].hash }
})
})
- .then((response) => response.json())
- .then((json) => fromHex(json.result.tx.extra.substring(66)))
- .catch((error) => console.error(error))
+ .then((response) => response.json())
+ .then((json) => fromHex(json.result.tx.extra.substring(66)))
+ .catch((error) => console.error(error))
}
}
@@ -49,7 +48,7 @@ export default function App() {
body: JSON.stringify({
jsonrpc: '2.0',
method: 'f_block_json',
- params: {hash: blockHash}
+ params: { hash: blockHash }
})
})
.then((response) => response.json())
@@ -59,7 +58,7 @@ export default function App() {
const getBlockHashes = (blockCount) => {
let i;
- for (i = 0; i < 100; i++) {
+ for (i = 0; i < 100; i++) {
fetch(nodeURL, {
method: 'POST',
body: JSON.stringify({
@@ -86,12 +85,12 @@ export default function App() {
.then((response) => response.json())
.then((json) => getBlockHashes(json.result.count))
.catch((error) => console.error(error))
- //.finally(() => setLoading(false));
+ //.finally(() => setLoading(false));
}, []);
return (
- {isLoading ? : (
+ {isLoading ? : (
{JSON.stringify(data)}
)}
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 169c73b..ffdcd4b 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -123,7 +123,7 @@ def enableHermes = project.ext.react.get("enableHermes", false);
android {
compileSdkVersion rootProject.ext.compileSdkVersion
- compileOptions {
+ compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
diff --git a/android/build.gradle b/android/build.gradle
index 3338dcb..0b3a74a 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -4,7 +4,7 @@ def REACT_NATIVE_VERSION = new File(['node', '--print',"JSON.parse(require('fs')
buildscript {
ext {
buildToolsVersion = "28.0.3"
- minSdkVersion = 20
+ minSdkVersion = 21
compileSdkVersion = 31
targetSdkVersion = 33
supportLibVersion = "28.0.0"
diff --git a/package.json b/package.json
index 9ae2277..7c2783a 100644
--- a/package.json
+++ b/package.json
@@ -145,4 +145,4 @@
"vm": "vm-browserify",
"tls": false
}
-}
+}
\ No newline at end of file
diff --git a/src/App.js b/src/App.js
index 0935a0b..810549e 100644
--- a/src/App.js
+++ b/src/App.js
@@ -2,480 +2,471 @@
//
// Please see the included LICENSE file for more information.
-import Ionicons from 'react-native-vector-icons/Ionicons';
-import Entypo from 'react-native-vector-icons/Entypo';
import CustomIcon from './CustomIcon.js'
-import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
import React from 'react';
import { View, StatusBar } from 'react-native';
import {
- createStackNavigator, createAppContainer, createBottomTabNavigator,
- createSwitchNavigator
+ createStackNavigator, createAppContainer, createBottomTabNavigator,
+ createSwitchNavigator
} from 'react-navigation';
-
-import Config from './Config';
-
import { Themes } from './Themes';
import { Globals } from './Globals';
-import { MainScreen } from './MainScreen';
import { SplashScreen } from './SplashScreen';
import { DisclaimerScreen } from './DisclaimerScreen';
import { loadPreferencesFromDatabase, openDB } from './Database';
import { ChatScreen, ModifyPayeeScreen, RecipientsScreen, CallScreen } from './Recipients';
import { GroupChatScreen, ModifyGroupScreen, GroupsScreen, NewGroupScreen } from './Groups';
import { WalletOptionScreen, CreateWalletScreen } from './CreateScreen';
-import { TransactionsScreen, TransactionDetailsScreen } from './TransactionsScreen';
+
+import { MainScreen } from './MainScreen'
+import { TransactionsScreen, TransactionDetailsScreen } from './TransactionsScreen'
+import { SendTransactionScreen, QrScannerScreen, TransferScreen, ChoosePayeeScreen, NewPayeeScreen, ConfirmScreen } from './TransferScreen.js'
import {
- SetPinScreen, RequestPinScreen, ForgotPinScreen, RequestHardwareAuthScreen,
- ChooseAuthMethodScreen,
+ SetPinScreen, RequestPinScreen, ForgotPinScreen, RequestHardwareAuthScreen,
+ ChooseAuthMethodScreen,
} from './Authenticate';
import {
- SettingsScreen, SwapCurrencyScreen, ExportKeysScreen, LoggingScreen, FaqScreen,
- DisableDozeScreen, SwapNodeScreen, OptimizeScreen, SwapLanguageScreen, SwapAPIScreen
+ SettingsScreen, SwapCurrencyScreen, ExportKeysScreen, LoggingScreen, FaqScreen,
+ DisableDozeScreen, SwapNodeScreen, OptimizeScreen, SwapLanguageScreen, SwapAPIScreen
} from './SettingsScreen';
import {
- PickMonthScreen, PickBlockHeightScreen, PickExactBlockHeightScreen,
+ PickMonthScreen, PickBlockHeightScreen, PickExactBlockHeightScreen,
} from './ScanHeightScreen';
-import {
- TransferScreen, ChoosePayeeScreen, NewPayeeScreen, ConfirmScreen,
- QrScannerScreen, SendTransactionScreen,
-} from './TransferScreen';
+
import {
- ImportWalletScreen, ImportKeysOrSeedScreen, ImportSeedScreen,
- ImportKeysScreen,
+ ImportWalletScreen, ImportKeysOrSeedScreen, ImportSeedScreen,
+ ImportKeysScreen,
} from './ImportScreen';
/* Transactions screen and more info on transactions */
const TransactionNavigator = createStackNavigator(
- {
- Transactions: TransactionsScreen,
- TransactionDetails: TransactionDetailsScreen,
+ {
+ Transactions: TransactionsScreen,
+ TransactionDetails: TransactionDetailsScreen,
+ },
+ {
+ initialRouteName: 'Transactions',
+ headerLayoutPreset: 'center',
+ transitionConfig: () => ({
+ transitionSpec: {
+ duration: 0,
+ },
+ }),
+ defaultNavigationOptions: {
+ headerTitleStyle: {
+ fontWeight: 'bold',
+ color: 'Themes.darkMode.primaryColour',
+ },
+ headerTransparent: true,
+ headerTintColor: Themes.darkMode.primaryColour,
},
- {
- initialRouteName: 'Transactions',
- headerLayoutPreset: 'center',
- transitionConfig: () => ({
- transitionSpec: {
- duration: 0,
- },
- }),
- defaultNavigationOptions: {
- headerTitleStyle: {
- fontWeight: 'bold',
- color: 'Themes.darkMode.primaryColour',
- },
- headerTransparent: true,
- headerTintColor: Themes.darkMode.primaryColour,
- },
- }
+ }
);
TransactionNavigator.navigationOptions = ({ navigation, screenProps }) => ({
- tabBarOptions: {
- activeBackgroundColor: screenProps.theme.backgroundColour,
- inactiveBackgroundColor: screenProps.theme.backgroundColour,
- activeTintColor: screenProps.theme.primaryColour,
- inactiveTintColor: screenProps.theme.slightlyMoreVisibleColour,
- showLabel: false,
- style: {
- borderTopWidth: 0,
- height: 46,
- textAlignVertical: "bottom",
- backgroundColor: "#FF00FF",
- marginBottom: 5
- }
+ tabBarOptions: {
+ activeBackgroundColor: screenProps.theme.backgroundColour,
+ inactiveBackgroundColor: screenProps.theme.backgroundColour,
+ activeTintColor: screenProps.theme.primaryColour,
+ inactiveTintColor: screenProps.theme.slightlyMoreVisibleColour,
+ showLabel: false,
+ style: {
+ borderTopWidth: 0,
+ height: 46,
+ textAlignVertical: "bottom",
+ marginBottom: 5
}
+ }
});
const TransferNavigator = createStackNavigator(
- {
- Transfer: TransferScreen,
- ChoosePayee: ChoosePayeeScreen,
- NewPayee: NewPayeeScreen,
- Confirm: ConfirmScreen,
- QrScanner: QrScannerScreen,
- SendTransaction: SendTransactionScreen,
- RequestPin: RequestPinScreen,
- RequestHardwareAuth: RequestHardwareAuthScreen,
+ {
+ Transfer: TransferScreen,
+ ChoosePayee: ChoosePayeeScreen,
+ NewPayee: NewPayeeScreen,
+ Confirm: ConfirmScreen,
+ QrScanner: QrScannerScreen,
+ SendTransaction: SendTransactionScreen,
+ RequestPin: RequestPinScreen,
+ RequestHardwareAuth: RequestHardwareAuthScreen,
+ },
+ {
+ initialRouteName: 'ChoosePayee',
+ headerLayoutPreset: 'center',
+ transitionConfig: () => ({
+ transitionSpec: {
+ duration: 0,
+ },
+ }),
+ defaultNavigationOptions: {
+ headerTitleStyle: {
+ fontWeight: 'bold',
+ color: Themes.darkMode.primaryColour,
+ },
+ headerTransparent: true,
+ headerTintColor: Themes.darkMode.primaryColour,
},
- {
- initialRouteName: 'ChoosePayee',
- headerLayoutPreset: 'center',
- transitionConfig: () => ({
- transitionSpec: {
- duration: 0,
- },
- }),
- defaultNavigationOptions: {
- headerTitleStyle: {
- fontWeight: 'bold',
- color: Themes.darkMode.primaryColour,
- },
- headerTransparent: true,
- headerTintColor: Themes.darkMode.primaryColour,
- },
- }
+ }
);
TransferNavigator.navigationOptions = ({ navigation, screenProps }) => {
- return {
- tabBarVisible: navigation.state.index === 0, /* Only show tab bar on ChoosePayee */
- tabBarOptions: {
- activeBackgroundColor: screenProps.theme.backgroundColour,
- inactiveBackgroundColor: screenProps.theme.backgroundColour,
- activeTintColor: screenProps.theme.primaryColour,
- inactiveTintColor: screenProps.theme.slightlyMoreVisibleColour,
- showLabel: false,
- style: {
- borderTopWidth: 0,
- height: 46,
- textAlignVertical: "bottom",
- backgroundColor: "#FF00FF",
- marginBottom: 5
- }
- }
- };
+ return {
+ tabBarVisible: navigation.state.index === 0, /* Only show tab bar on ChoosePayee */
+ tabBarOptions: {
+ activeBackgroundColor: screenProps.theme.backgroundColour,
+ inactiveBackgroundColor: screenProps.theme.backgroundColour,
+ activeTintColor: screenProps.theme.primaryColour,
+ inactiveTintColor: screenProps.theme.slightlyMoreVisibleColour,
+ showLabel: false,
+ style: {
+ borderTopWidth: 0,
+ height: 46,
+ textAlignVertical: "bottom",
+ marginBottom: 5
+ }
+ }
+ };
};
const SettingsNavigator = createStackNavigator(
- {
- Settings: SettingsScreen,
- SwapCurrency: SwapCurrencyScreen,
- SwapNode: SwapNodeScreen,
- SwapLanguage: SwapLanguageScreen,
- ExportKeys: ExportKeysScreen,
- Logging: LoggingScreen,
- Faq: FaqScreen,
- DisableDoze: DisableDozeScreen,
- RequestPin: RequestPinScreen,
- ForgotPin: ForgotPinScreen,
- SetPin: SetPinScreen,
- ChooseAuthMethod: ChooseAuthMethodScreen,
- RequestHardwareAuth: RequestHardwareAuthScreen,
- Optimize: OptimizeScreen,
- SwapAPI: SwapAPIScreen
+ {
+ Settings: SettingsScreen,
+ SwapCurrency: SwapCurrencyScreen,
+ SwapNode: SwapNodeScreen,
+ SwapLanguage: SwapLanguageScreen,
+ ExportKeys: ExportKeysScreen,
+ Logging: LoggingScreen,
+ Faq: FaqScreen,
+ DisableDoze: DisableDozeScreen,
+ RequestPin: RequestPinScreen,
+ ForgotPin: ForgotPinScreen,
+ SetPin: SetPinScreen,
+ ChooseAuthMethod: ChooseAuthMethodScreen,
+ RequestHardwareAuth: RequestHardwareAuthScreen,
+ Optimize: OptimizeScreen,
+ SwapAPI: SwapAPIScreen
+ },
+ {
+ initialRouteName: 'Settings',
+ headerLayoutPreset: 'center',
+ transitionConfig: () => ({
+ transitionSpec: {
+ duration: 0,
+ },
+ }),
+ defaultNavigationOptions: {
+ headerTitleStyle: {
+ fontWeight: 'bold',
+ color: Themes.darkMode.primaryColour,
+ },
+ headerTransparent: true,
+ headerTintColor: Themes.darkMode.primaryColour,
},
- {
- initialRouteName: 'Settings',
- headerLayoutPreset: 'center',
- transitionConfig: () => ({
- transitionSpec: {
- duration: 0,
- },
- }),
- defaultNavigationOptions: {
- headerTitleStyle: {
- fontWeight: 'bold',
- color: Themes.darkMode.primaryColour,
- },
- headerTransparent: true,
- headerTintColor: Themes.darkMode.primaryColour,
- },
- }
+ }
);
SettingsNavigator.navigationOptions = ({ navigation, screenProps }) => ({
- tabBarOptions: {
- activeBackgroundColor: screenProps.theme.backgroundColour,
- inactiveBackgroundColor: screenProps.theme.backgroundColour,
- activeTintColor: screenProps.theme.primaryColour,
- inactiveTintColor: screenProps.theme.slightlyMoreVisibleColour,
- showLabel: false,
- style: {
- borderTopWidth: 0,
- height: 46,
- textAlignVertical: "bottom",
- backgroundColor: "#FF00FF",
- marginBottom: 5
- }
+ tabBarOptions: {
+ activeBackgroundColor: screenProps.theme.backgroundColour,
+ inactiveBackgroundColor: screenProps.theme.backgroundColour,
+ activeTintColor: screenProps.theme.primaryColour,
+ inactiveTintColor: screenProps.theme.slightlyMoreVisibleColour,
+ showLabel: false,
+ style: {
+ borderTopWidth: 0,
+ height: 46,
+ textAlignVertical: "bottom",
+ marginBottom: 5
}
+ }
});
const RecipientNavigator = createStackNavigator(
- {
- Recipients: RecipientsScreen,
- ModifyPayee: ModifyPayeeScreen,
- ChatScreen: ChatScreen,
- NewPayee: NewPayeeScreen,
- CallScreen: CallScreen
+ {
+ Recipients: RecipientsScreen,
+ ModifyPayee: ModifyPayeeScreen,
+ ChatScreen: ChatScreen,
+ NewPayee: NewPayeeScreen,
+ CallScreen: CallScreen
+ },
+ {
+ initialRouteName: '',
+ headerLayoutPreset: 'center',
+ transitionConfig: () => ({
+ transitionSpec: {
+ duration: 0,
+ },
+ }),
+ defaultNavigationOptions: {
+ headerTitleStyle: {
+ fontWeight: 'bold',
+ color: Themes.darkMode.primaryColour,
+ },
+ headerTransparent: true,
+ headerTintColor: Themes.darkMode.primaryColour,
},
- {
- initialRouteName: '',
- headerLayoutPreset: 'center',
- transitionConfig: () => ({
- transitionSpec: {
- duration: 0,
- },
- }),
- defaultNavigationOptions: {
- headerTitleStyle: {
- fontWeight: 'bold',
- color: Themes.darkMode.primaryColour,
- },
- headerTransparent: true,
- headerTintColor: Themes.darkMode.primaryColour,
- },
- }
+ }
);
RecipientNavigator.navigationOptions = ({ navigation, screenProps }) => ({
- tabBarOptions: {
- activeBackgroundColor: screenProps.theme.backgroundColour,
- inactiveBackgroundColor: screenProps.theme.backgroundColour,
- activeTintColor: screenProps.theme.primaryColour,
- inactiveTintColor: screenProps.theme.slightlyMoreVisibleColour,
- showLabel: false,
- style: {
- borderTopWidth: 0,
- height: 46,
- textAlignVertical: "bottom",
- backgroundColor: "#FF00FF",
- marginBottom: 5
- }
+ tabBarOptions: {
+ activeBackgroundColor: screenProps.theme.backgroundColour,
+ inactiveBackgroundColor: screenProps.theme.backgroundColour,
+ activeTintColor: screenProps.theme.primaryColour,
+ inactiveTintColor: screenProps.theme.slightlyMoreVisibleColour,
+ showLabel: false,
+ style: {
+ borderTopWidth: 0,
+ height: 46,
+ textAlignVertical: "bottom",
+ marginBottom: 5
}
+ }
});
const GroupsNavigator = createStackNavigator(
- {
- Groups: GroupsScreen,
- ModifyGroup: ModifyGroupScreen,
- GroupChatScreen: GroupChatScreen,
- NewGroup: NewGroupScreen,
+ {
+ Groups: GroupsScreen,
+ ModifyGroup: ModifyGroupScreen,
+ GroupChatScreen: GroupChatScreen,
+ NewGroup: NewGroupScreen,
+ },
+ {
+ initialRouteName: '',
+ headerLayoutPreset: 'center',
+ transitionConfig: () => ({
+ transitionSpec: {
+ duration: 0,
+ },
+ }),
+ defaultNavigationOptions: {
+ headerTitleStyle: {
+ fontWeight: 'bold',
+ color: Themes.darkMode.primaryColour,
+ },
+ headerTransparent: true,
+ headerTintColor: Themes.darkMode.primaryColour,
},
- {
- initialRouteName: '',
- headerLayoutPreset: 'center',
- transitionConfig: () => ({
- transitionSpec: {
- duration: 0,
- },
- }),
- defaultNavigationOptions: {
- headerTitleStyle: {
- fontWeight: 'bold',
- color: Themes.darkMode.primaryColour,
- },
- headerTransparent: true,
- headerTintColor: Themes.darkMode.primaryColour,
- },
- }
+ }
);
GroupsNavigator.navigationOptions = ({ navigation, screenProps }) => ({
- tabBarOptions: {
- activeBackgroundColor: screenProps.theme.backgroundColour,
- inactiveBackgroundColor: screenProps.theme.backgroundColour,
- activeTintColor: screenProps.theme.primaryColour,
- inactiveTintColor: screenProps.theme.slightlyMoreVisibleColour,
- showLabel: false,
- style: {
- borderTopWidth: 0,
- height: 46,
- textAlignVertical: "bottom",
- backgroundColor: "#FF00FF",
- marginBottom: 5
- }
+ tabBarOptions: {
+ activeBackgroundColor: screenProps.theme.backgroundColour,
+ inactiveBackgroundColor: screenProps.theme.backgroundColour,
+ activeTintColor: screenProps.theme.primaryColour,
+ inactiveTintColor: screenProps.theme.slightlyMoreVisibleColour,
+ showLabel: false,
+ style: {
+ borderTopWidth: 0,
+ height: 46,
+ textAlignVertical: "bottom",
+ marginBottom: 5
}
+ }
});
/* Main screen for a logged in wallet */
const HomeNavigator = createBottomTabNavigator(
- {
- Main: MainScreen,
- Transactions: TransactionNavigator,
- Transfer: TransferNavigator,
- Recipients: RecipientNavigator,
- Groups: GroupsNavigator,
- Settings: SettingsNavigator,
+ {
+ Main: MainScreen,
+ Transactions: TransactionNavigator,
+ Transfer: TransferNavigator,
+ Recipients: RecipientNavigator,
+ Groups: GroupsNavigator,
+ Settings: SettingsNavigator,
+ },
+ {
+ initialRouteName: 'Main',
+ tabBarOptions: {
+ activeBackgroundColor: Themes.darkMode.backgroundColour,
+ inactiveBackgroundColor: Themes.darkMode.backgroundColour,
+ activeTintColor: Themes.darkMode.primaryColour,
+ showLabel: false,
+ style: {
+ borderTopWidth: 0,
+ height: 46,
+ textAlignVertical: "bottom",
+ marginBottom: 5
+ }
+
},
- {
- initialRouteName: 'Main',
- tabBarOptions: {
- activeTintColor: "Themes.darkMode.primaryColour",
- showLabel: false,
- style: {
- borderTopWidth: 0,
- height: 46,
- textAlignVertical: "bottom",
- backgroundColor: "#FF00FF",
- marginBottom: 5
- }
-
- },
- defaultNavigationOptions: ({ navigation }) => ({
- tabBarIcon: ({focused, horizontal, tintColor}) => {
- const { routeName } = navigation.state;
-
- let iconName;
- let IconComponent;
-
- if (routeName === 'Main') {
- IconComponent = CustomIcon;
- iconName = 'profile';
- } else if (routeName === 'Transactions') {
- IconComponent = CustomIcon;
- iconName = 'wallet';
- } else if (routeName === 'Transfer') {
- IconComponent = CustomIcon;
- iconName = 'money-send';
- } else if (routeName === 'Recipients') {
- IconComponent = CustomIcon;
- iconName = 'message';
- } else if (routeName === 'Settings') {
- IconComponent = CustomIcon;
- iconName = 'setting-2';
- } else if (routeName === 'Groups') {
- IconComponent = CustomIcon;
- iconName = 'messages';
- }
-
- return ;
- },
- }),
- }
+ defaultNavigationOptions: ({ navigation }) => ({
+ tabBarIcon: ({ focused, horizontal, tintColor }) => {
+ const { routeName } = navigation.state;
+
+ let iconName;
+ let IconComponent;
+
+ if (routeName === 'Main') {
+ IconComponent = CustomIcon;
+ iconName = 'profile';
+ } else if (routeName === 'Transactions') {
+ IconComponent = CustomIcon;
+ iconName = 'wallet';
+ } else if (routeName === 'Transfer') {
+ IconComponent = CustomIcon;
+ iconName = 'money-send';
+ } else if (routeName === 'Recipients') {
+ IconComponent = CustomIcon;
+ iconName = 'message';
+ } else if (routeName === 'Settings') {
+ IconComponent = CustomIcon;
+ iconName = 'setting-2';
+ } else if (routeName === 'Groups') {
+ IconComponent = CustomIcon;
+ iconName = 'messages';
+ }
+
+ return ;
+ },
+ }),
+ }
);
+
+
/* Login or create/import a wallet */
const LoginNavigator = createStackNavigator(
- {
- /* Create a wallet */
- CreateWallet: CreateWalletScreen,
+ {
+ /* Create a wallet */
+ CreateWallet: CreateWalletScreen,
- /* Set a pin for the created wallet */
- SetPin: SetPinScreen,
+ /* Set a pin for the created wallet */
+ SetPin: SetPinScreen,
- /* Request the pin for an existing wallet */
- RequestPin: RequestPinScreen,
+ /* Request the pin for an existing wallet */
+ RequestPin: RequestPinScreen,
- /* Allow deleting the wallet if pin forgotten */
- ForgotPin: ForgotPinScreen,
+ /* Allow deleting the wallet if pin forgotten */
+ ForgotPin: ForgotPinScreen,
- /* Launcing screen */
- Splash: SplashScreen,
+ /* Launcing screen */
+ Splash: SplashScreen,
- /* Create a wallet, import a wallet */
- WalletOption: WalletOptionScreen,
+ /* Create a wallet, import a wallet */
+ WalletOption: WalletOptionScreen,
- /* Import a wallet */
- ImportWallet: ImportWalletScreen,
+ /* Import a wallet */
+ ImportWallet: ImportWalletScreen,
- /* Pick between seed or keys */
- ImportKeysOrSeed: ImportKeysOrSeedScreen,
+ /* Pick between seed or keys */
+ ImportKeysOrSeed: ImportKeysOrSeedScreen,
- /* Import with a mnemonic seed */
- ImportSeed: ImportSeedScreen,
+ /* Import with a mnemonic seed */
+ ImportSeed: ImportSeedScreen,
- /* Import with a set of keys */
- ImportKeys: ImportKeysScreen,
+ /* Import with a set of keys */
+ ImportKeys: ImportKeysScreen,
- /* Pick a month to start the wallet scanning from */
- PickMonth: PickMonthScreen,
+ /* Pick a month to start the wallet scanning from */
+ PickMonth: PickMonthScreen,
- /* Pick a block range to start the wallet scanning from */
- PickBlockHeight: PickBlockHeightScreen,
+ /* Pick a block range to start the wallet scanning from */
+ PickBlockHeight: PickBlockHeightScreen,
- /* Pick a specific height to start the wallet scanning from */
- PickExactBlockHeight: PickExactBlockHeightScreen,
+ /* Pick a specific height to start the wallet scanning from */
+ PickExactBlockHeight: PickExactBlockHeightScreen,
- /* Explain fee, I'm not responsible for anything, etc */
- Disclaimer: DisclaimerScreen,
+ /* Explain fee, I'm not responsible for anything, etc */
+ Disclaimer: DisclaimerScreen,
- /* Request authentication via fingerprint, touchid, etc */
- RequestHardwareAuth: RequestHardwareAuthScreen,
+ /* Request authentication via fingerprint, touchid, etc */
+ RequestHardwareAuth: RequestHardwareAuthScreen,
- /* Whether we should use pin, fingerprint, or no auth */
- ChooseAuthMethod: ChooseAuthMethodScreen,
+ /* Whether we should use pin, fingerprint, or no auth */
+ ChooseAuthMethod: ChooseAuthMethodScreen,
+ },
+ {
+ initialRouteName: 'Splash',
+ headerLayoutPreset: 'center',
+ defaultNavigationOptions: {
+ headerTitleStyle: {
+ fontWeight: 'bold',
+ color: Themes.darkMode.primaryColour,
+ },
+ headerTransparent: true,
+ headerTintColor: Themes.darkMode.primaryColour,
},
- {
- initialRouteName: 'Splash',
- headerLayoutPreset: 'center',
- defaultNavigationOptions: {
- headerTitleStyle: {
- fontWeight: 'bold',
- color: Themes.darkMode.primaryColour,
- },
- headerTransparent: true,
- headerTintColor: Themes.darkMode.primaryColour,
- },
- }
+ }
);
const AppContainer = createAppContainer(createSwitchNavigator(
- {
- Login: {
- screen: LoginNavigator,
- },
- Home: {
- screen: HomeNavigator,
- },
+ {
+ Login: {
+ screen: LoginNavigator,
},
- {
- initialRouteName: 'Login',
- }
+ Home: {
+ screen: HomeNavigator,
+ },
+ },
+ {
+ initialRouteName: 'Login',
+ }
));
/* TODO: Need to load preferences to set theme */
export default class App extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- loaded: false,
- screenProps: {
- theme: Themes[Globals.preferences.theme],
- },
- }
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ loaded: false,
+ screenProps: {
+ theme: Themes[Globals.preferences.theme],
+ },
+ }
+
+ this.init();
+ }
- this.init();
+ async init() {
+ await openDB();
+
+ const prefs = await loadPreferencesFromDatabase();
+
+ if (prefs !== undefined) {
+ Globals.preferences = prefs;
}
- async init() {
- await openDB();
+ console.log(Globals.preferences);
- const prefs = await loadPreferencesFromDatabase();
+ this.setState({
+ screenProps: {
+ theme: Themes[Globals.preferences.theme],
+ },
+ loaded: true,
+ });
- if (prefs !== undefined) {
- Globals.preferences = prefs;
+ Globals.updateTheme = () => {
+ this.setState({
+ screenProps: {
+ theme: Themes[Globals.preferences.theme],
}
-
- console.log(Globals.preferences);
-
- this.setState({
- screenProps: {
- theme: Themes[Globals.preferences.theme],
- },
- loaded: true,
- });
-
- Globals.updateTheme = () => {
- this.setState({
- screenProps: {
- theme: Themes[Globals.preferences.theme],
- }
- });
- };
- }
+ });
+ };
+ }
- render() {
- const loadedComponent = ;
- const notLoadedComponent = ;
+ render() {
+ const loadedComponent = ;
+ const notLoadedComponent = ;
- return(
-
-
- {this.state.loaded ? loadedComponent : notLoadedComponent}
-
- );
- }
+ return (
+
+
+ {this.state.loaded ? loadedComponent : notLoadedComponent}
+
+ );
+ }
}
diff --git a/src/Authenticate.js b/src/Authenticate.js
index a8778d6..efc68d7 100644
--- a/src/Authenticate.js
+++ b/src/Authenticate.js
@@ -30,329 +30,333 @@ import { withTranslation } from 'react-i18next';
/* Dummy component that redirects to pin auth or hardware auth as appropriate */
export async function Authenticate(navigation, subtitle, finishFunction, disableBack = false) {
- /* No auth, just go straight to the finish function */
- if (Globals.preferences.authenticationMethod === 'none') {
- finishFunction(navigation);
- return;
- }
-
- let route = 'RequestPin';
+ /* No auth, just go straight to the finish function */
+ if (Globals.preferences.authenticationMethod === 'none') {
+ finishFunction(navigation);
+ return;
+ }
- try {
- const sensorType = await FingerprintScanner.isSensorAvailable();
+ let route = 'RequestPin';
- /* User wants to use hardware authentication, and we have it available */
- if (Globals.preferences.authenticationMethod === 'hardware-auth') {
- route = 'RequestHardwareAuth';
- }
- } catch (err) {
- // No fingerprint sensor
- }
+ try {
+ const sensorType = await FingerprintScanner.isSensorAvailable();
- if (disableBack) {
- navigation.dispatch(
- navigateWithDisabledBack(route, {
- finishFunction,
- subtitle,
- }),
- );
- } else {
- navigation.navigate(route, {
- finishFunction,
- subtitle,
- });
+ /* User wants to use hardware authentication, and we have it available */
+ if (Globals.preferences.authenticationMethod === 'hardware-auth') {
+ route = 'RequestHardwareAuth';
}
+ } catch (err) {
+ // No fingerprint sensor
+ }
+
+ if (disableBack) {
+ navigation.dispatch(
+ navigateWithDisabledBack(route, {
+ finishFunction,
+ subtitle,
+ }),
+ );
+ } else {
+ navigation.navigate(route, {
+ finishFunction,
+ subtitle,
+ });
+ }
}
const authErrorToHumanError = new Map([
- ['AuthenticationNotMatch', 'Fingerprint does not match stored fingerprint.'],
- ['AuthenticationFailed', 'Fingerprint does not match stored fingerprint.'],
- ['UserCancel', 'Authentication was cancelled.'],
- ['UserFallback', 'Authentication was cancelled.'],
- ['SystemCancel', 'Authentication was cancelled by the system.'],
- ['PasscodeNotSet', 'No fingerprints have been registered.'],
- ['FingerprintScannerNotAvailable', 'This device does not support fingerprint scanning.'],
- ['FingerprintScannerNotEnrolled', 'No fingerprints have been registered.'],
- ['FingerprintScannerUnknownError', 'Failed to authenticate for an unknown reason.'],
- ['FingerprintScannerNotSupported', 'This device does not support fingerprint scanning.'],
- ['DeviceLocked', 'Authentication failed too many times.'],
+ ['AuthenticationNotMatch', 'Fingerprint does not match stored fingerprint.'],
+ ['AuthenticationFailed', 'Fingerprint does not match stored fingerprint.'],
+ ['UserCancel', 'Authentication was cancelled.'],
+ ['UserFallback', 'Authentication was cancelled.'],
+ ['SystemCancel', 'Authentication was cancelled by the system.'],
+ ['PasscodeNotSet', 'No fingerprints have been registered.'],
+ ['FingerprintScannerNotAvailable', 'This device does not support fingerprint scanning.'],
+ ['FingerprintScannerNotEnrolled', 'No fingerprints have been registered.'],
+ ['FingerprintScannerUnknownError', 'Failed to authenticate for an unknown reason.'],
+ ['FingerprintScannerNotSupported', 'This device does not support fingerprint scanning.'],
+ ['DeviceLocked', 'Authentication failed too many times.'],
]);
export class RequestHardwareAuthScreen extends React.Component {
- constructor(props) {
- super(props);
-
- this.onAuthAttempt = this.onAuthAttempt.bind(this);
- }
-
- componentDidMount() {
- this.auth();
+ constructor(props) {
+ super(props);
+
+ this.onAuthAttempt = this.onAuthAttempt.bind(this);
+ }
+
+ componentDidMount() {
+ this.auth();
+ }
+
+ componentWillUnmount() {
+ FingerprintScanner.release();
+ }
+
+ onAuthAttempt(error) {
+ const detailedError = authErrorToHumanError.get(error.name) || error.message;
+
+ const usePinInsteadErrors = [
+ 'UserCancel',
+ 'UserFallback',
+ 'SystemCancel',
+ 'PasscodeNotSet',
+ 'FingerprintScannerNotAvailable',
+ 'FingerprintScannerNotEnrolled',
+ 'FingerprintScannerUnknownError',
+ 'FingerprintScannerNotSupported',
+ 'DeviceLocked',
+ ];
+
+ /* Use pin instead of fingerprint scanner if a specific
+ type of error is thrown */
+ if (usePinInsteadErrors.includes(error.name)) {
+ Alert.alert(
+ 'Failed ' + this.props.navigation.state.params.subtitle,
+ `${detailedError} Please use PIN Auth instead.`,
+ [
+ {
+ text: 'OK', onPress: () => {
+ this.props.navigation.navigate('RequestPin', {
+ subtitle: this.props.navigation.state.params.subtitle,
+ finishFunction: this.props.navigation.state.params.finishFunction
+ })
+ }
+ },
+ ]
+ );
+ } else {
+ Alert.alert(
+ 'Failed ' + this.props.navigation.state.params.subtitle,
+ `Please try again (Error: ${detailedError})`,
+ [
+ {
+ text: 'OK', onPress: () => {
+ this.auth();
+ }
+ },
+ ]
+ );
}
+ }
- componentWillUnmount() {
- FingerprintScanner.release();
- }
+ async auth() {
+ try {
+ await FingerprintScanner.authenticate({
+ onAttempt: this.onAuthAttempt,
+ });
+
+ this.props.navigation.state.params.finishFunction(this.props.navigation);
+ } catch (error) {
+ this.onAuthAttempt(error);
+ };
+ }
+
+ render() {
+ return (
+
+ {Platform.OS === 'android' &&
+
+
+
+
+
+ Touch the fingerprint sensor {this.props.navigation.state.params.subtitle}
+
+
+
+
- onAuthAttempt(error) {
- const detailedError = authErrorToHumanError.get(error.name) || error.message;
-
- const usePinInsteadErrors = [
- 'UserCancel',
- 'UserFallback',
- 'SystemCancel',
- 'PasscodeNotSet',
- 'FingerprintScannerNotAvailable',
- 'FingerprintScannerNotEnrolled',
- 'FingerprintScannerUnknownError',
- 'FingerprintScannerNotSupported',
- 'DeviceLocked',
- ];
-
- /* Use pin instead of fingerprint scanner if a specific
- type of error is thrown */
- if (usePinInsteadErrors.includes(error.name)) {
- Alert.alert(
- 'Failed ' + this.props.navigation.state.params.subtitle,
- `${detailedError} Please use PIN Auth instead.`,
- [
- {text: 'OK', onPress: () => {
- this.props.navigation.navigate('RequestPin', {
- subtitle: this.props.navigation.state.params.subtitle,
- finishFunction: this.props.navigation.state.params.finishFunction
- })
- }},
- ]
- );
- } else {
- Alert.alert(
- 'Failed ' + this.props.navigation.state.params.subtitle,
- `Please try again (Error: ${detailedError})`,
- [
- {text: 'OK', onPress: () => {
- this.auth();
- }},
- ]
- );
+
+
+
}
- }
+
+ );
+ }
+}
- async auth() {
- try {
- await FingerprintScanner.authenticate({
- onAttempt: this.onAuthAttempt,
- });
+class ChooseAuthMethodScreenNoTranslation extends React.Component {
+ constructor(props) {
+ super(props);
- this.props.navigation.state.params.finishFunction(this.props.navigation);
- } catch(error) {
- this.onAuthAttempt(error);
- };
+ this.state = {
+ hardwareAuth: Globals.preferences.authenticationMethod === 'hardware-auth',
+ pinCode: Globals.preferences.authenticationMethod === 'pincode',
+ noAuth: Globals.preferences.authenticationMethod === 'none',
}
+ }
+
+ render() {
+ const { t } = this.props;
+ return (
+
+
+
+ {t('authenticateHow')}
+
+
+
+ {
+ this.setState({
+ hardwareAuth: value,
+ pinCode: value ? false : this.state.pinCode,
+ noAuth: value ? false : this.state.noAuth,
+ });
+ }}
+ style={{ marginRight: 15 }}
+ />
+
+
+
+ {t('useHardware')}
+
+
+
+
+
+ {
+ this.setState({
+ hardwareAuth: value ? false : this.state.hardwareAuth,
+ pinCode: value,
+ noAuth: value ? false : this.state.noAuth,
+ });
+ }}
+ style={{ marginRight: 15 }}
+ />
+
+
+
+ {t('usePinCode')}
+
+
- render() {
- return(
-
- {Platform.OS === 'android' &&
-
-
-
-
-
- Touch the fingerprint sensor {this.props.navigation.state.params.subtitle}
-
-
-
-
-
-
-
-
- }
+
+
+
+ {
+ this.setState({
+ hardwareAuth: value ? false : this.state.hardwareAuth,
+ pinCode: value ? false : this.state.pinCode,
+ noAuth: value
+ });
+ }}
+ style={{ marginRight: 15 }}
+ />
+
+
+
+ {t('noAuth')}
+
- );
- }
-}
-class ChooseAuthMethodScreenNoTranslation extends React.Component {
- constructor(props) {
- super(props);
+
- this.state = {
- hardwareAuth: Globals.preferences.authenticationMethod === 'hardware-auth',
- pinCode: Globals.preferences.authenticationMethod === 'pincode',
- noAuth: Globals.preferences.authenticationMethod === 'none',
- }
- }
+ {
+ (async () => {
+ let method = 'none';
- render() {
- const { t } = this.props;
- return(
-
-
-
- {t('authenticateHow')}
-
-
-
- {
- this.setState({
- hardwareAuth: value,
- pinCode: value ? false : this.state.pinCode,
- noAuth: value ? false : this.state.noAuth,
- });
- }}
- style={{ marginRight: 15 }}
- />
-
-
-
- {t('useHardware')}
-
-
-
-
-
- {
- this.setState({
- hardwareAuth: value ? false : this.state.hardwareAuth,
- pinCode: value,
- noAuth: value ? false : this.state.noAuth,
- });
- }}
- style={{ marginRight: 15 }}
- />
-
-
-
- {t('usePinCode')}
-
-
-
-
-
-
- {
- this.setState({
- hardwareAuth: value ? false : this.state.hardwareAuth,
- pinCode: value ? false : this.state.pinCode,
- noAuth: value
- });
- }}
- style={{ marginRight: 15 }}
- />
-
-
-
- {t('noAuth')}
-
-
-
-
-
- {
- (async() => {
- let method = 'none';
-
- if (this.state.hardwareAuth) {
- method = 'hardware-auth';
- } else if (this.state.pinCode) {
- method = 'pincode';
- }
-
- const havePincode = await hasUserSetPinCode();
- Globals.preferences.authenticationMethod = method;
-
-
- if (method === 'none') {
- await deleteUserPinCode();
- this.props.navigation.navigate(this.props.navigation.state.params.nextRoute);
- savePreferencesToDatabase(Globals.preferences);
- } else if (method == 'hardware-auth' && havePincode) {
- this.props.navigation.navigate(this.props.navigation.state.params.nextRoute);
- savePreferencesToDatabase(Globals.preferences);
- } else {
- this.props.navigation.navigate('SetPin', {
- nextRoute: this.props.navigation.state.params.nextRoute
- });
- }
- })();
- }}
- disabled={!(this.state.noAuth || this.state.pinCode || this.state.hardwareAuth)}
- {...this.props}
- />
-
-
- );
- }
+ if (this.state.hardwareAuth) {
+ method = 'hardware-auth';
+ } else if (this.state.pinCode) {
+ method = 'pincode';
+ }
+
+ const havePincode = await hasUserSetPinCode();
+ Globals.preferences.authenticationMethod = method;
+
+
+ if (method === 'none') {
+ await deleteUserPinCode();
+ this.props.navigation.navigate(this.props.navigation.state.params.nextRoute);
+ savePreferencesToDatabase(Globals.preferences);
+ } else if (method == 'hardware-auth' && havePincode) {
+ this.props.navigation.navigate(this.props.navigation.state.params.nextRoute);
+ savePreferencesToDatabase(Globals.preferences);
+ } else {
+ this.props.navigation.navigate('SetPin', {
+ nextRoute: this.props.navigation.state.params.nextRoute
+ });
+ }
+ })();
+ }}
+ disabled={!(this.state.noAuth || this.state.pinCode || this.state.hardwareAuth)}
+ {...this.props}
+ />
+
+
+ );
+ }
}
export const ChooseAuthMethodScreen = withTranslation()(ChooseAuthMethodScreenNoTranslation)
@@ -361,168 +365,168 @@ export const ChooseAuthMethodScreen = withTranslation()(ChooseAuthMethodScreenNo
* Enter a pin for the new wallet
*/
export class SetPinScreen extends React.Component {
- static navigationOptions = {
- title: '',
- }
-
- constructor(props) {
- super(props);
- }
-
- continue(pinCode) {
- /* Continue on to create or import a wallet */
- savePreferencesToDatabase(Globals.preferences);
- this.props.navigation.navigate(this.props.navigation.state.params.nextRoute);
- }
-
- render() {
- const subtitle = `to keep your ${Config.coinName} secure`;
-
- return(
-
- this.continue(pinCode)}
- subtitleChoose={subtitle}
- passwordLength={6}
- touchIDDisabled={true}
- colorPassword={this.props.screenProps.theme.primaryColour}
- stylePinCodeColorSubtitle={this.props.screenProps.theme.primaryColour}
- stylePinCodeColorTitle={this.props.screenProps.theme.primaryColour}
- stylePinCodeButtonNumber={this.props.screenProps.theme.pinCodeForegroundColour}
- numbersButtonOverlayColor={this.props.screenProps.theme.secondaryColour}
- stylePinCodeDeleteButtonColorShowUnderlay={this.props.screenProps.theme.primaryColour}
- stylePinCodeDeleteButtonColorHideUnderlay={this.props.screenProps.theme.primaryColour}
- colorCircleButtons={this.props.screenProps.theme.pinCodeBackgroundColour}
- />
-
- );
- }
+ static navigationOptions = {
+ title: '',
+ }
+
+ constructor(props) {
+ super(props);
+ }
+
+ continue(pinCode) {
+ /* Continue on to create or import a wallet */
+ savePreferencesToDatabase(Globals.preferences);
+ this.props.navigation.navigate(this.props.navigation.state.params.nextRoute);
+ }
+
+ render() {
+ const subtitle = `to keep your ${Config.coinName} secure`;
+
+ return (
+
+ this.continue(pinCode)}
+ subtitleChoose={subtitle}
+ passwordLength={6}
+ touchIDDisabled={true}
+ colorPassword={this.props.screenProps.theme.primaryColour}
+ stylePinCodeColorSubtitle={this.props.screenProps.theme.primaryColour}
+ stylePinCodeColorTitle={this.props.screenProps.theme.primaryColour}
+ stylePinCodeButtonNumber={this.props.screenProps.theme.pinCodeForegroundColour}
+ numbersButtonOverlayColor={this.props.screenProps.theme.secondaryColour}
+ stylePinCodeDeleteButtonColorShowUnderlay={this.props.screenProps.theme.primaryColour}
+ stylePinCodeDeleteButtonColorHideUnderlay={this.props.screenProps.theme.primaryColour}
+ colorCircleButtons={this.props.screenProps.theme.pinCodeBackgroundColour}
+ />
+
+ );
+ }
}
export class ForgotPinScreen extends React.Component {
- static navigationOptions = {
- title: '',
- }
-
- constructor(props) {
- super(props);
- }
-
- render() {
- return(
-
-
-
- Your account is encrypted with your pin, so unfortunately, if you have forgotten your pin, it cannot be recovered.
-
-
- However, you can delete your account if you wish to create a new one.
-
-
-
- {
- (async () => {
-
- Globals.reset();
- await resetPinCodeInternalStates();
-
- this.props.navigation.navigate('Splash');
-
- /* Can't use navigateWithDisabledBack between routes, but don't
- want to be able to go back to previous screen...
- Navigate to splash, then once on that route, reset the
- stack. */
- this.props.navigation.dispatch(navigateWithDisabledBack('Splash'));
- })();
- }}
- buttonStyle={{
- backgroundColor: 'red',
- height: 50,
- borderRadius: 0,
- }}
- {...this.props}
- />
-
- );
- }
+ static navigationOptions = {
+ title: '',
+ }
+
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ return (
+
+
+
+ Your account is encrypted with your pin, so unfortunately, if you have forgotten your pin, it cannot be recovered.
+
+
+ However, you can delete your account if you wish to create a new one.
+
+
+
+ {
+ (async () => {
+
+ Globals.reset();
+ await resetPinCodeInternalStates();
+
+ this.props.navigation.navigate('Splash');
+
+ /* Can't use navigateWithDisabledBack between routes, but don't
+ want to be able to go back to previous screen...
+ Navigate to splash, then once on that route, reset the
+ stack. */
+ this.props.navigation.dispatch(navigateWithDisabledBack('Splash'));
+ })();
+ }}
+ buttonStyle={{
+ backgroundColor: 'red',
+ height: 50,
+ borderRadius: 0,
+ }}
+ {...this.props}
+ />
+
+ );
+ }
}
/**
* Prompt for the stored pin to unlock the wallet
*/
export class RequestPinScreen extends React.Component {
- static navigationOptions = {
- title: '',
- }
-
- constructor(props) {
- super(props);
- }
-
- render() {
- return(
-
- {
- this.props.navigation.state.params.finishFunction(this.props.navigation);
- }}
- subtitleEnter={this.props.navigation.state.params.subtitle}
- passwordLength={6}
- touchIDDisabled={true}
- colorPassword={this.props.screenProps.theme.primaryColour}
- stylePinCodeColorSubtitle={this.props.screenProps.theme.primaryColour}
- stylePinCodeColorTitle={this.props.screenProps.theme.primaryColour}
- stylePinCodeButtonNumber={this.props.screenProps.theme.pinCodeForegroundColour}
- numbersButtonOverlayColor={this.props.screenProps.theme.secondaryColour}
- stylePinCodeDeleteButtonColorShowUnderlay={this.props.screenProps.theme.primaryColour}
- stylePinCodeDeleteButtonColorHideUnderlay={this.props.screenProps.theme.primaryColour}
- onClickButtonLockedPage={() => RNExitApp.exitApp()}
- colorCircleButtons={this.props.screenProps.theme.pinCodeBackgroundColour}
- />
-
-
- );
- }
+ static navigationOptions = {
+ title: '',
+ }
+
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ return (
+
+ {
+ this.props.navigation.state.params.finishFunction(this.props.navigation);
+ }}
+ subtitleEnter={this.props.navigation.state.params.subtitle}
+ passwordLength={6}
+ touchIDDisabled={true}
+ colorPassword={this.props.screenProps.theme.primaryColour}
+ stylePinCodeColorSubtitle={this.props.screenProps.theme.primaryColour}
+ stylePinCodeColorTitle={this.props.screenProps.theme.primaryColour}
+ stylePinCodeButtonNumber={this.props.screenProps.theme.pinCodeForegroundColour}
+ numbersButtonOverlayColor={this.props.screenProps.theme.secondaryColour}
+ stylePinCodeDeleteButtonColorShowUnderlay={this.props.screenProps.theme.primaryColour}
+ stylePinCodeDeleteButtonColorHideUnderlay={this.props.screenProps.theme.primaryColour}
+ onClickButtonLockedPage={() => RNExitApp.exitApp()}
+ colorCircleButtons={this.props.screenProps.theme.pinCodeBackgroundColour}
+ />
+
+
+ );
+ }
}
diff --git a/src/BackgroundSync.js b/src/BackgroundSync.js
index e13acc8..7aba910 100644
--- a/src/BackgroundSync.js
+++ b/src/BackgroundSync.js
@@ -9,188 +9,187 @@ import { AppState, Platform, PushNotificationIOS } from 'react-native';
import { WalletBackend, LogLevel } from 'kryptokrona-wallet-backend-js';
import PushNotification from 'react-native-push-notification';
-import {getMessage, cacheSync} from './HuginUtilities';
import NetInfo from '@react-native-community/netinfo';
import Config from './Config';
import { Globals } from './Globals';
-import { backgroundSyncMessages, sendNotification } from './MainScreen';
+import { backgroundSyncMessages, sendNotification } from './MainScreen'
-import { processBlockOutputs, makePostRequest } from './NativeCode';
+import { processBlockOutputs } from './NativeCode';
import {
- deleteKnownTransaction, saveToDatabase, haveWallet, loadWallet, openDB, loadPreferencesFromDatabase, loadPayeeDataFromDatabase, saveKnownTransaction
+ saveToDatabase, haveWallet, loadWallet, openDB, loadPreferencesFromDatabase
} from './Database';
export function initBackgroundSync() {
- BackgroundFetch.configure({
- minimumFetchInterval: 15, // <-- minutes (15 is minimum allowed)
- stopOnTerminate: false,
- startOnBoot: true,
- forceReload: false,
- enableHeadless: true,
- requiredNetworkType: BackgroundFetch.NETWORK_TYPE_ANY,
- }, async () => {
- await backgroundSync();
- }, (error) => {
- Globals.logger.addLogMessage("[js] RNBackgroundFetch failed to start: " + error.toString());
- });
+ BackgroundFetch.configure({
+ minimumFetchInterval: 15, // <-- minutes (15 is minimum allowed)
+ stopOnTerminate: false,
+ startOnBoot: true,
+ forceReload: false,
+ enableHeadless: true,
+ requiredNetworkType: BackgroundFetch.NETWORK_TYPE_ANY,
+ }, async () => {
+ await backgroundSync();
+ }, (error) => {
+ Globals.logger.addLogMessage("[js] RNBackgroundFetch failed to start: " + error.toString());
+ });
}
let State = {
- shouldStop: false,
- running: false,
- unsubscribe: () => {},
+ shouldStop: false,
+ running: false,
+ unsubscribe: () => { },
}
function onStateChange(state) {
- if (state !== 'background') {
- State.shouldStop = true;
- }
+ if (state !== 'background') {
+ State.shouldStop = true;
+ }
}
async function handleNetInfoChange({ type }) {
- if (Globals.preferences.limitData && type === 'cellular') {
- Globals.logger.addLogMessage("[Background Sync] Network connection changed to cellular, and we are limiting data. Stopping sync.");
- State.shouldStop = true;
- }
+ if (Globals.preferences.limitData && type === 'cellular') {
+ Globals.logger.addLogMessage("[Background Sync] Network connection changed to cellular, and we are limiting data. Stopping sync.");
+ State.shouldStop = true;
+ }
}
/**
* Check background syncing is all good and setup a few vars
*/
async function setupBackgroundSync() {
- /* Probably shouldn't happen... but check we're not already running. */
- if (State.running) {
- Globals.logger.addLogMessage('[Background Sync] Background sync already running. Not starting.');
- return false;
+ /* Probably shouldn't happen... but check we're not already running. */
+ if (State.running) {
+ Globals.logger.addLogMessage('[Background Sync] Background sync already running. Not starting.');
+ return false;
+ }
+
+ /* Not in the background, don't sync */
+ if (AppState.currentState !== 'background') {
+ Globals.logger.addLogMessage('[Background Sync] Background sync launched while in foreground. Not starting.');
+ return false;
+ }
+
+ /* Wallet not loaded yet. Probably launching from headlessJS */
+ if (Globals.wallet === undefined) {
+ const backgroundInitSuccess = await fromHeadlessJSInit();
+
+ if (!backgroundInitSuccess) {
+ return false;
}
+ }
- /* Not in the background, don't sync */
- if (AppState.currentState !== 'background') {
- Globals.logger.addLogMessage('[Background Sync] Background sync launched while in foreground. Not starting.');
- return false;
- }
+ const netInfo = await NetInfo.fetch();
- /* Wallet not loaded yet. Probably launching from headlessJS */
- if (Globals.wallet === undefined) {
- const backgroundInitSuccess = await fromHeadlessJSInit();
+ if (Globals.preferences.limitData && netInfo.type === 'cellular') {
+ Globals.logger.addLogMessage('[Background Sync] On mobile data. Not starting background sync.');
+ return false;
+ }
- if (!backgroundInitSuccess) {
- return false;
- }
- }
+ State.unsubscribe = NetInfo.addEventListener(handleNetInfoChange);
- const netInfo = await NetInfo.fetch();
+ AppState.addEventListener('change', onStateChange);
- if (Globals.preferences.limitData && netInfo.type === 'cellular') {
- Globals.logger.addLogMessage('[Background Sync] On mobile data. Not starting background sync.');
- return false;
- }
+ State.shouldStop = false;
- State.unsubscribe = NetInfo.addEventListener(handleNetInfoChange);
+ Globals.logger.addLogMessage('[Background Sync] Running background sync...');
- AppState.addEventListener('change', onStateChange);
-
- State.shouldStop = false;
-
- Globals.logger.addLogMessage('[Background Sync] Running background sync...');
-
- return true;
+ return true;
}
/**
* Complete the background syncing and pull down a few vars
*/
function finishBackgroundSync() {
- AppState.removeEventListener('change', onStateChange);
+ AppState.removeEventListener('change', onStateChange);
- State.unsubscribe();
+ State.unsubscribe();
- BackgroundFetch.finish(BackgroundFetch.FETCH_RESULT_NEW_DATA);
+ BackgroundFetch.finish(BackgroundFetch.FETCH_RESULT_NEW_DATA);
- State.running = false;
+ State.running = false;
- Globals.logger.addLogMessage('[Background Sync] Background sync complete.');
+ Globals.logger.addLogMessage('[Background Sync] Background sync complete.');
}
async function fromHeadlessJSInit() {
- /* See if user has previously made a wallet */
- const hasWallet = await haveWallet();
+ /* See if user has previously made a wallet */
+ const hasWallet = await haveWallet();
- if (!hasWallet) {
- Globals.logger.addLogMessage('[Background Sync] No wallet stored. Not starting background sync.');
- return false;
- }
+ if (!hasWallet) {
+ Globals.logger.addLogMessage('[Background Sync] No wallet stored. Not starting background sync.');
+ return false;
+ }
- await openDB();
+ await openDB();
- const prefs = await loadPreferencesFromDatabase();
+ const prefs = await loadPreferencesFromDatabase();
- if (prefs !== undefined) {
- Globals.preferences = prefs;
- }
+ if (prefs !== undefined) {
+ Globals.preferences = prefs;
+ }
- /* Load wallet data from DB */
- let [walletData, dbError] = await loadWallet();
+ /* Load wallet data from DB */
+ let [walletData, dbError] = await loadWallet();
- if (dbError) {
- Globals.logger.addLogMessage('[Background Sync] Failed to load wallet. Not starting background sync.');
- return false;
- }
+ if (dbError) {
+ Globals.logger.addLogMessage('[Background Sync] Failed to load wallet. Not starting background sync.');
+ return false;
+ }
- const [wallet, walletError] = await WalletBackend.loadWalletFromJSON(
- Globals.getDaemon(), walletData, Config
- );
+ const [wallet, walletError] = await WalletBackend.loadWalletFromJSON(
+ Globals.getDaemon(), walletData, Config
+ );
- if (walletError) {
- Globals.logger.addLogMessage('[Background Sync] Failed to load wallet. Not starting background sync.');
- return false;
- }
+ if (walletError) {
+ Globals.logger.addLogMessage('[Background Sync] Failed to load wallet. Not starting background sync.');
+ return false;
+ }
- Globals.wallet = wallet;
+ Globals.wallet = wallet;
- Globals.wallet.scanCoinbaseTransactions(Globals.preferences.scanCoinbaseTransactions);
- Globals.wallet.enableAutoOptimization(false);
+ Globals.wallet.scanCoinbaseTransactions(Globals.preferences.scanCoinbaseTransactions);
+ Globals.wallet.enableAutoOptimization(false);
- /* Remove any previously added listeners to pretend double notifications */
- Globals.wallet.removeAllListeners('incomingtx');
+ /* Remove any previously added listeners to pretend double notifications */
+ Globals.wallet.removeAllListeners('incomingtx');
- Globals.wallet.on('incomingtx', (transaction) => {
- sendNotification(transaction);
- });
+ Globals.wallet.on('incomingtx', (transaction) => {
+ sendNotification(transaction);
+ });
- Globals.wallet.setLoggerCallback((prettyMessage, message) => {
- Globals.logger.addLogMessage(message);
- });
+ Globals.wallet.setLoggerCallback((prettyMessage, message) => {
+ Globals.logger.addLogMessage(message);
+ });
- Globals.wallet.setLogLevel(LogLevel.DEBUG);
+ Globals.wallet.setLogLevel(LogLevel.DEBUG);
- /* Use our native C++ func to process blocks, provided we're on android */
- /* TODO: iOS support */
- if (Platform.OS === 'android') {
- Globals.wallet.setBlockOutputProcessFunc(processBlockOutputs);
- }
+ /* Use our native C++ func to process blocks, provided we're on android */
+ /* TODO: iOS support */
+ if (Platform.OS === 'android') {
+ Globals.wallet.setBlockOutputProcessFunc(processBlockOutputs);
+ }
- PushNotification.configure({
- onNotification: (notification) => {
- notification.finish(PushNotificationIOS.FetchResult.NoData);
- },
+ PushNotification.configure({
+ onNotification: (notification) => {
+ notification.finish(PushNotificationIOS.FetchResult.NoData);
+ },
- permissions: {
- alert: true,
- badge: true,
- sound: true,
- },
+ permissions: {
+ alert: true,
+ badge: true,
+ sound: true,
+ },
- popInitialNotification: true,
+ popInitialNotification: true,
- requestPermissions: true,
- });
+ requestPermissions: true,
+ });
- return true;
+ return true;
}
/**
@@ -198,63 +197,63 @@ async function fromHeadlessJSInit() {
* Note - don't use anything with setInterval here, it won't run in the background
*/
export async function backgroundSync() {
- if (!await setupBackgroundSync()) {
- BackgroundFetch.finish(BackgroundFetch.FETCH_RESULT_NO_DATA);
- return;
- } else {
- State.running = true;
- }
+ if (!await setupBackgroundSync()) {
+ BackgroundFetch.finish(BackgroundFetch.FETCH_RESULT_NO_DATA);
+ return;
+ } else {
+ State.running = true;
+ }
- const startTime = new Date();
+ const startTime = new Date();
- /* ios only allows 30 seconds of runtime. Android allows... infinite???
- Since we run every 15 minutes, just set it to 14 for android.
- Not exactly sure on this. */
- let allowedRunTime = Platform.OS === 'ios' ? 25 : (60 * 14);
+ /* ios only allows 30 seconds of runtime. Android allows... infinite???
+ Since we run every 15 minutes, just set it to 14 for android.
+ Not exactly sure on this. */
+ let allowedRunTime = Platform.OS === 'ios' ? 25 : (60 * 14);
- let secsRunning = 0;
+ let secsRunning = 0;
- /* Run for 25 seconds or until the app comes back to the foreground */
- while (!State.shouldStop && secsRunning < allowedRunTime) {
+ /* Run for 25 seconds or until the app comes back to the foreground */
+ while (!State.shouldStop && secsRunning < allowedRunTime) {
- await backgroundSyncMessages();
+ await backgroundSyncMessages();
- /* Update the daemon info */
- await Globals.wallet.internal().updateDaemonInfo();
+ /* Update the daemon info */
+ await Globals.wallet.internal().updateDaemonInfo();
- const [walletBlockCount, localDaemonBlockCount, networkBlockCount] = Globals.wallet.getSyncStatus();
+ const [walletBlockCount, localDaemonBlockCount, networkBlockCount] = Globals.wallet.getSyncStatus();
- /* Check if we're synced so we don't kill the users battery */
- if (walletBlockCount >= localDaemonBlockCount || walletBlockCount >= networkBlockCount) {
- Globals.logger.addLogMessage('[Background Sync] Wallet is synced. Stopping background sync.');
+ /* Check if we're synced so we don't kill the users battery */
+ if (walletBlockCount >= localDaemonBlockCount || walletBlockCount >= networkBlockCount) {
+ Globals.logger.addLogMessage('[Background Sync] Wallet is synced. Stopping background sync.');
- /* Save the wallet */
- saveToDatabase(Globals.wallet);
+ /* Save the wallet */
+ saveToDatabase(Globals.wallet);
- break;
- }
+ break;
+ }
- /* Process 1000 blocks */
- for (let i = 0; i < (1000 / Config.blocksPerTick); i++) {
- if (State.shouldStop) {
- break;
- }
+ /* Process 1000 blocks */
+ for (let i = 0; i < (1000 / Config.blocksPerTick); i++) {
+ if (State.shouldStop) {
+ break;
+ }
- const syncedBlocks = await Globals.wallet.internal().sync(false);
+ const syncedBlocks = await Globals.wallet.internal().sync(false);
- if (!syncedBlocks) {
- break;
- }
- }
+ if (!syncedBlocks) {
+ break;
+ }
+ }
- Globals.logger.addLogMessage('[Background Sync] Saving wallet in background.');
+ Globals.logger.addLogMessage('[Background Sync] Saving wallet in background.');
- /* Save the wallet */
- saveToDatabase(Globals.wallet);
+ /* Save the wallet */
+ saveToDatabase(Globals.wallet);
- /* Update our running time */
- secsRunning = (new Date() - startTime) / 1000;
- }
+ /* Update our running time */
+ secsRunning = (new Date() - startTime) / 1000;
+ }
- finishBackgroundSync();
+ finishBackgroundSync();
}
diff --git a/src/Boards.js b/src/Boards.js
index 905ba5c..6151a9f 100644
--- a/src/Boards.js
+++ b/src/Boards.js
@@ -4,24 +4,21 @@
import React from 'react';
import { checkText } from 'smile2emoji';
-import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
import GestureRecognizer from 'react-native-swipe-gestures';
import {
- Linking, Keyboard, KeyboardAvoidingView, View, Text, TextInput, ScrollView, FlatList, Platform, TouchableWithoutFeedback, Image
+ Linking, Keyboard, KeyboardAvoidingView, View, Text, TextInput, ScrollView, FlatList, Platform, TouchableWithoutFeedback, Image
} from 'react-native';
import Hyperlink from 'react-native-hyperlink'
import {
- validateAddresses, WalletErrorCode, validatePaymentID,
+ WalletErrorCode, validatePaymentID,
} from 'kryptokrona-wallet-backend-js';
-import { Button as RNEButton, Alert, Modal, TouchableOpacity} from 'react-native';
+import { Modal, TouchableOpacity } from 'react-native';
import { Button, Input, Icon } from 'react-native-elements';
-import Config from './Config';
import ListItem from './ListItem';
-import List from './ListContainer';
import { Styles } from './Styles';
@@ -36,31 +33,29 @@ import 'moment/locale/zh-cn';
import 'moment/locale/nb';
import { Globals } from './Globals';
-import { Hr, BottomButton, CopyButton } from './SharedComponents';
-import {intToRGB, hashCode, get_avatar, sendBoardsMessage, getBoardColors} from './HuginUtilities';
+import { get_avatar, sendBoardsMessage, getBoardColors } from './HuginUtilities';
-import {toastPopUp} from './Utilities';
import { getBoardsMessage, saveBoardsMessage, getReplies, getBoardSubscriptions, subscribeToBoard, markBoardsMessageAsRead, saveToDatabase, getBoardsMessages, getLatestMessages, removeMessage, markConversationAsRead, loadPayeeDataFromDatabase, removeBoard, getBoardRecommendations } from './Database';
import './i18n.js';
import { withTranslation } from 'react-i18next';
-import {AutoGrowingTextInput} from 'react-native-autogrow-textinput';
+import { AutoGrowingTextInput } from 'react-native-autogrow-textinput';
-String.prototype.hashCode = function() {
- var hash = 0;
- if (this.length == 0) {
- return hash;
- }
- for (var i = 0; i < this.length; i++) {
- var char = this.charCodeAt(i);
- hash = ((hash<<5)-hash)+char;
- hash = hash & hash; // Convert to 32bit integer
- }
+String.prototype.hashCode = function () {
+ var hash = 0;
+ if (this.length == 0) {
return hash;
+ }
+ for (var i = 0; i < this.length; i++) {
+ var char = this.charCodeAt(i);
+ hash = ((hash << 5) - hash) + char;
+ hash = hash & hash; // Convert to 32bit integer
+ }
+ return hash;
}
const markMessagesAsRead = async (this_messages) => {
@@ -72,7 +67,7 @@ const markMessagesAsRead = async (this_messages) => {
let this_msg = this_messages[i];
if (!this_msg) { continue };
let this_hash = this_msg.hash;
- if(!this_msg.read) {
+ if (!this_msg.read) {
await markBoardsMessageAsRead(this_hash);
this_messages[i].unread = 0;
}
@@ -86,1194 +81,1194 @@ const markMessagesAsRead = async (this_messages) => {
export class BoardsHomeScreenNoTranslation extends React.Component {
- constructor(props) {
- super(props);
-
- let board = this.props.navigation.state.params;
- console.log(board);
-
- if (board == undefined) {
- board = 'Home';
- } else {
- board = board.board;
- }
- console.log(board);
-
- this.state = {
- messages: Globals.boardsMessages,
- index: 0,
- board: board,
- modalVisible: false,
- editingBoards: false,
- isSubscribedToBoard: false,
- messageModalVisible: false,
- activePost: {
- "message": "",
- "address": "",
- "signature": "",
- "board": "",
- "timestamp": "",
- "nickname": "",
- "reply": "0",
- "hash": "",
- "sent": 0,
- "read": 0
- }
- }
-
- Globals.updateBoardsFunctions.push(() => {
- this.setState({
- messages: Globals.boardsMessages,
- boardssubscriptions: [{board: 'Home', key: 0}].concat(Globals.boardsSubscriptions)
- })
- });
+ constructor(props) {
+ super(props);
+
+ let board = this.props.navigation.state.params;
+ console.log(board);
+
+ if (board == undefined) {
+ board = 'Home';
+ } else {
+ board = board.board;
+ }
+ console.log(board);
+
+ this.state = {
+ messages: Globals.boardsMessages,
+ index: 0,
+ board: board,
+ modalVisible: false,
+ editingBoards: false,
+ isSubscribedToBoard: false,
+ messageModalVisible: false,
+ activePost: {
+ "message": "",
+ "address": "",
+ "signature": "",
+ "board": "",
+ "timestamp": "",
+ "nickname": "",
+ "reply": "0",
+ "hash": "",
+ "sent": 0,
+ "read": 0
+ }
}
- async componentDidMount() {
+ Globals.updateBoardsFunctions.push(() => {
+ this.setState({
+ messages: Globals.boardsMessages,
+ boardssubscriptions: [{ board: 'Home', key: 0 }].concat(Globals.boardsSubscriptions)
+ })
+ });
+ }
- const this_messages = await getBoardsMessages(this.state.board);
+ async componentDidMount() {
- const boardsSubscriptions = [{board: 'Home', key: 0}].concat(Globals.boardsSubscriptions);
+ const this_messages = await getBoardsMessages(this.state.board);
- const boardsRecommendationsItems = await getBoardRecommendations();
+ const boardsSubscriptions = [{ board: 'Home', key: 0 }].concat(Globals.boardsSubscriptions);
- this.setState({
- messages: this_messages,
- boardssubscriptions: boardsSubscriptions,
- isSubscribedToBoard: true,
- boardsRecommendationsItems: boardsRecommendationsItems
- });
+ const boardsRecommendationsItems = await getBoardRecommendations();
- Globals.activeChat = this.state.address;
+ this.setState({
+ messages: this_messages,
+ boardssubscriptions: boardsSubscriptions,
+ isSubscribedToBoard: true,
+ boardsRecommendationsItems: boardsRecommendationsItems
+ });
+ Globals.activeChat = this.state.address;
- let i = 0;
- markMessagesAsRead(this_messages);
+ let i = 0;
- console.log(this_messages);
+ markMessagesAsRead(this_messages);
- this.state.messages = this_messages;
+ console.log(this_messages);
- this.setState({
- messages: this_messages
- });
+ this.state.messages = this_messages;
+ this.setState({
+ messages: this_messages
+ });
- }
- setModalVisible = (visible) => {
- this.setState({ modalVisible: visible });
- }
+ }
- setMessageModalVisible = (visible) => {
- this.setState({ messageModalVisible: visible });
- }
+ setModalVisible = (visible) => {
+ this.setState({ modalVisible: visible });
+ }
- setActivePost = (item) => {
- this.setState({ activePost: item });
- }
+ setMessageModalVisible = (visible) => {
+ this.setState({ messageModalVisible: visible });
+ }
- setEditingMode = (editing) => {
- this.setState({ editingBoards: editing })
- }
+ setActivePost = (item) => {
+ this.setState({ activePost: item });
+ }
- render() {
+ setEditingMode = (editing) => {
+ this.setState({ editingBoards: editing })
+ }
- const { modalVisible, messageModalVisible, editingBoards, activePost } = this.state;
+ render() {
- const isSubscribedTo = (board) => {
+ const { modalVisible, messageModalVisible, editingBoards, activePost } = this.state;
- if (!boardsSubscriptionsItems) {
- return;
- }
+ const isSubscribedTo = (board) => {
- let sub = boardsSubscriptionsItems.filter(item => {return item.board == board});
+ if (!boardsSubscriptionsItems) {
+ return;
+ }
- const result = sub.length > 0 ? true : false;
+ let sub = boardsSubscriptionsItems.filter(item => { return item.board == board });
- return result;
+ const result = sub.length > 0 ? true : false;
- }
+ return result;
- const sendTip = (address, hash, name) => {
- console.log(name);
- const url = `xkr://?address=${address}&paymentid=${hash}&istip=true&name=${name}`;
- this.setMessageModalVisible(false);
- Linking.openURL(url);
- }
+ }
- const submitReply = async (text) => {
+ const sendTip = (address, hash, name) => {
+ console.log(name);
+ const url = `xkr://?address=${address}&paymentid=${hash}&istip=true&name=${name}`;
+ this.setMessageModalVisible(false);
+ Linking.openURL(url);
+ }
- Keyboard.dismiss();
+ const submitReply = async (text) => {
- let updated_messages = await getBoardsMessages(this.state.board);
- if (!updated_messages) {
- updated_messages = [];
- }
- let temp_timestamp = parseInt(Date.now() / 1000);
+ Keyboard.dismiss();
- updated_messages.unshift({
- board: this.state.activePost.board,
- address: Globals.wallet.getPrimaryAddress(),
- message: checkText(text),
- timestamp: temp_timestamp,
- hash: temp_timestamp.toString(),
- read: 1,
- nickname: Globals.preferences.nickname,
- reply: this.state.activePost.hash,
- op: this.state.activePost
- });
+ let updated_messages = await getBoardsMessages(this.state.board);
+ if (!updated_messages) {
+ updated_messages = [];
+ }
+ let temp_timestamp = parseInt(Date.now() / 1000);
+
+ updated_messages.unshift({
+ board: this.state.activePost.board,
+ address: Globals.wallet.getPrimaryAddress(),
+ message: checkText(text),
+ timestamp: temp_timestamp,
+ hash: temp_timestamp.toString(),
+ read: 1,
+ nickname: Globals.preferences.nickname,
+ reply: this.state.activePost.hash,
+ op: this.state.activePost
+ });
+
+ this.setState({
+ messages: updated_messages,
+ messageHasLength: false,
+ message: ''
+ });
+
+ this.replyinput._textInput.clear();
+
+ this.setState({ replyHasLength: this.state.reply.length > 0 });
+
+ let success = await sendBoardsMessage(checkText(text), this.state.activePost.board, this.state.activePost.hash);
+
+
+ // await removeMessage(temp_timestamp);
+ if (success.success) {
+ console.log(success);
+ await saveBoardsMessage(
+ checkText(text),
+ Globals.wallet.getPrimaryAddress(),
+ '',
+ this.state.activePost.board,
+ temp_timestamp,
+ Globals.preferences.nickname,
+ this.state.activePost.hash,
+ success.transactionHash,
+ '1',
+ false);
+ // let updated_replies = this.state.replies;
+
+ // updated_replies.unshift({
+ // message: checkText(text),
+ // address: Globals.wallet.getPrimaryAddress(),
+ // signature: '',
+ // board: this.state.activePost.board,
+ // timestamp: temp_timestamp.toString(),
+ // nickname: Globals.preferences.nickname,
+ // reply: this.state.activePost.hash,
+ // hash: success.transactionHash,
+ // sent: 0,
+ // read: 1
+ //
+ // });
+ // console.log(updated_replies);
+ // this.state.replies = updated_replies;
+ // console.log(this.state.replies);
+ this.state.replies = await getReplies(this.state.activePost.hash);
+ // this.state.input.current.clear();
+ } else {
+ updated_messages = await getBoardsMessages(this.state.board);
this.setState({
messages: updated_messages,
- messageHasLength: false,
- message: ''
- });
-
- this.replyinput._textInput.clear();
-
- this.setState({replyHasLength: this.state.reply.length > 0});
-
- let success = await sendBoardsMessage(checkText(text), this.state.activePost.board, this.state.activePost.hash);
-
-
- // await removeMessage(temp_timestamp);
- if (success.success) {
- console.log(success);
- await saveBoardsMessage(
- checkText(text),
- Globals.wallet.getPrimaryAddress(),
- '',
- this.state.activePost.board,
- temp_timestamp,
- Globals.preferences.nickname,
- this.state.activePost.hash,
- success.transactionHash,
- '1',
- false);
- // let updated_replies = this.state.replies;
-
- // updated_replies.unshift({
- // message: checkText(text),
- // address: Globals.wallet.getPrimaryAddress(),
- // signature: '',
- // board: this.state.activePost.board,
- // timestamp: temp_timestamp.toString(),
- // nickname: Globals.preferences.nickname,
- // reply: this.state.activePost.hash,
- // hash: success.transactionHash,
- // sent: 0,
- // read: 1
- //
- // });
- // console.log(updated_replies);
- // this.state.replies = updated_replies;
- // console.log(this.state.replies);
- this.state.replies = await getReplies(this.state.activePost.hash);
- // this.state.input.current.clear();
- } else {
- updated_messages = await getBoardsMessages(this.state.board);
-
- this.setState({
- messages: updated_messages,
- messageHasLength: true
- })
-
- }
+ messageHasLength: true
+ })
+
}
+ }
- const submitMessage = async (text) => {
-
- Keyboard.dismiss();
-
- let updated_messages = await getBoardsMessages(this.state.board);
- if (!updated_messages) {
- updated_messages = [];
- }
- let temp_timestamp = parseInt(Date.now() / 1000);
- updated_messages.unshift({
- board: this.state.board,
- address: Globals.wallet.getPrimaryAddress(),
- message: checkText(text),
- timestamp: temp_timestamp,
- hash: temp_timestamp.toString(),
- read: 1,
- nickname: Globals.preferences.nickname
- });
+ const submitMessage = async (text) => {
- this.setState({
- messages: updated_messages,
- messageHasLength: false,
- message: ''
- });
+ Keyboard.dismiss();
- this.input._textInput.clear();
+ let updated_messages = await getBoardsMessages(this.state.board);
+ if (!updated_messages) {
+ updated_messages = [];
+ }
+ let temp_timestamp = parseInt(Date.now() / 1000);
+ updated_messages.unshift({
+ board: this.state.board,
+ address: Globals.wallet.getPrimaryAddress(),
+ message: checkText(text),
+ timestamp: temp_timestamp,
+ hash: temp_timestamp.toString(),
+ read: 1,
+ nickname: Globals.preferences.nickname
+ });
- this.setState({messageHasLength: this.state.message.length > 0});
+ this.setState({
+ messages: updated_messages,
+ messageHasLength: false,
+ message: ''
+ });
- let success = await sendBoardsMessage(checkText(text), this.state.board, this.state.paymentID);
+ this.input._textInput.clear();
+ this.setState({ messageHasLength: this.state.message.length > 0 });
- // await removeMessage(temp_timestamp);
- if (success.success) {
+ let success = await sendBoardsMessage(checkText(text), this.state.board, this.state.paymentID);
- // this.state.input.current.clear();
- } else {
- updated_messages = await getBoardsMessages(this.state.board);
+ // await removeMessage(temp_timestamp);
+ if (success.success) {
- this.setState({
- messages: updated_messages,
- messageHasLength: true
- })
- }
- }
+ // this.state.input.current.clear();
+ } else {
+ updated_messages = await getBoardsMessages(this.state.board);
- const getBoard = async (board) => {
- const updated_subscriptions = await getBoardSubscriptions();
this.setState({
- messages: Globals.boardsMessages,
- boardssubscriptions: [{board: 'Home', key: 0}].concat(updated_subscriptions)
+ messages: updated_messages,
+ messageHasLength: true
})
- const board_messages = await getBoardsMessages(board);
- markMessagesAsRead(board_messages);
- Globals.activeBoard = board;
- this.setModalVisible(false);
- this.setState({
- board: board,
- messages: board_messages
- });
- }
- const deleteBoard = async (board) => {
- let newBoardsSubscriptions = this.state.boardssubscriptions;
- newBoardsSubscriptions = newBoardsSubscriptions.filter(item => { return item.board != board});
- removeBoard(board);
- this.setState({
- boardssubscriptions: newBoardsSubscriptions
- });
- }
+ }
+ }
+ const getBoard = async (board) => {
+ const updated_subscriptions = await getBoardSubscriptions();
+ this.setState({
+ messages: Globals.boardsMessages,
+ boardssubscriptions: [{ board: 'Home', key: 0 }].concat(updated_subscriptions)
+ })
+ const board_messages = await getBoardsMessages(board);
+ markMessagesAsRead(board_messages);
+ Globals.activeBoard = board;
+ this.setModalVisible(false);
+ this.setState({
+ board: board,
+ messages: board_messages
+ });
+ }
- const { t } = this.props;
- const messages = this.state.messages;
+ const deleteBoard = async (board) => {
+ let newBoardsSubscriptions = this.state.boardssubscriptions;
+ newBoardsSubscriptions = newBoardsSubscriptions.filter(item => { return item.board != board });
+ removeBoard(board);
+ this.setState({
+ boardssubscriptions: newBoardsSubscriptions
+ });
+ }
- const boardsSubscriptionsItems = this.state.boardssubscriptions;
- const boardsRecommendationsItems = this.state.boardsRecommendationsItems;
- const board = this.state.board;
- this.state.isSubscribedToBoard = isSubscribedTo(this.state.board);
- const noMessagesComponent =
-
+ const { t } = this.props;
+ const messages = this.state.messages;
+
+ const boardsSubscriptionsItems = this.state.boardssubscriptions;
+ const boardsRecommendationsItems = this.state.boardsRecommendationsItems;
+
+ const board = this.state.board;
+ this.state.isSubscribedToBoard = isSubscribedTo(this.state.board);
+ const noMessagesComponent =
+
+
+
+ {t('noMessages')}
+
+ ;
+
+ const newMessageIndicator =
+ ;
+
+ const items =
+
+ item.hash}
+ renderItem={({ item }) => (
+
+
+ {item.reply && item.reply != 0 &&
+ Replying to {item.op.nickname}
+ }
+
+
+
-
- {t('noMessages')}
-
- ;
-
- const newMessageIndicator =
- ;
-
- const items =
-
- item.hash}
- renderItem={({item}) => (
-
-
- {item.reply && item.reply != 0 &&
- Replying to {item.op.nickname}
- }
-
-
-
-
-
-
- {item.nickname ? item.nickname : 'Anonymous'}
-
-
-
- {board == 'Home' &&
-
-
-
- {item.board}
-
-
-
- }
-
-
- }
- subtitle={{item.message + "\n"}{item.timestamp}{item.read == '1' ? false : {newMessageIndicator}}}
- subtitleStyle={{
- fontFamily: "Montserrat-Regular",
- overflow: 'hidden'
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontFamily: 'Montserrat-SemiBold'
- }}showsVerticalScrollIndicator={false}
- subtitleStyle={{
- color: this.props.screenProps.theme.slightlyMoreVisibleColour,
- fontFamily: 'Montserrat-Regular'
- }}
- onPress={async () => {
-
-
-
- if (item.reply && item.reply != 0) {
- this.state.replies = await getReplies(item.reply);
- const op = await getBoardsMessage(item.reply);
- if (op.length == 0) {
- return;
- }
- this.setActivePost(op[0]);
-
- } else {
- this.state.replies = await getReplies(item.hash);
- this.setActivePost(item);
-
- }
-
- this.setMessageModalVisible(true);
-
-
- // let messages = await getBoardsMessages(board);
- //
- // this.setState({
- // board: item.board,
- // messages: messages
- // });
- // this.props.navigation.navigate(
- // 'ChatScreen', {
- // payee: item,
- // }
- // );
- // await markBoardMessageAsRead(item.address);
- // Globals.payees = await loadPayeeDataFromDatabase();
- // this.setState({
- // payees: Globals.payees
- // });
- }}
- />
- )}
+
- ;
-
- const messageComponent =
-
+
+ {item.nickname ? item.nickname : 'Anonymous'}
+
+
+
+ {board == 'Home' &&
+
+
- {items}
+ {item.board}
+
- ;
+
+ }
+
+
+ }
+ subtitle={{item.message + "\n"}{item.timestamp}{item.read == '1' ? false : {newMessageIndicator}}}
+ subtitleStyle={{
+ fontFamily: "Montserrat-Regular",
+ overflow: 'hidden'
+ }}
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontFamily: 'Montserrat-SemiBold'
+ }} showsVerticalScrollIndicator={false}
+ subtitleStyle={{
+ color: this.props.screenProps.theme.slightlyMoreVisibleColour,
+ fontFamily: 'Montserrat-Regular'
+ }}
+ onPress={async () => {
- const boardsSubscriptions =
-
- item.board}
- style={{backgroundColor: 'transparent'}}
- renderItem={({item}) => (
-
-
- {runes(item.board)[0].toUpperCase()}
-
-
- :
-
-
- X
-
-
-
- }
- rightIcon={item.unread ? {item.unread} : <>>}
-
- showsVerticalScrollIndicator={false}
- onPress={async () => {
- !editingBoards || item.board == 'Home' ?
- getBoard(item.board)
- :
- deleteBoard(item.board)
-
- }}
- />
- )}
- />
- ;
-
- const storyStyle = {
- borderRadius: 25,
- width: 60,
- height: 60,
- backgroundColor: 'white',
- marginRight: 10,
- flexDirection:'row'
- };
-
- const storyTextStyle = [Styles.centeredText, {
- fontSize: 30,
- lineHeight: 58,
- width: 60,
- fontFamily: 'Montserrat-Bold',
- color: 'white',
- flex: 1,
- flexWrap: 'wrap'
- }];
-
- const unread_counter_style = {
- borderRadius: 15,
- minWidth: 28,
- height: 28,
- backgroundColor: 'red',
- color: 'white',
- padding: 4,
- borderWidth: 5
- };
-
- const unread_counter_text_style = {
- fontSize: 14,
- lineHeight: 14,
- fontFamily: 'Montserrat-Bold',
- color: 'white',
- textAlign: 'center'
- };
-
- const modalStyle = {
- height: '100%',
- marginTop: 50,
- backgroundColor: '#272527',
- borderTopRightRadius: 50,
- borderTopLeftRadius: 50,
- padding: 25,
- alignItems: "center",
- shadowColor: "#000",
- shadowOffset: {
- width: 0,
- height: 2
- },
- shadowOpacity: 0.25,
- shadowRadius: 4,
- elevation: 5
- };
-
- const boardsStories =
-
-
- {boardsSubscriptionsItems != undefined && boardsSubscriptionsItems.map(function(item, i){
- return { getBoard(item.board) }} style={[storyStyle, {backgroundColor: getBoardColors(item.board)}]}>{runes(item.board)[0].toUpperCase()}{item.board}{item.unread ? {item.unread} : <>>};
- })
- }
-
- ;
-
- const boardsRecommendations =
-
- {t('boardsRecommendations')}
-
- {boardsRecommendationsItems != undefined && boardsRecommendationsItems.map(function(item, i){
- return { getBoard(item.board) }} style={[storyStyle, {backgroundColor: getBoardColors(item.board)}]}>{runes(item.board)[0].toUpperCase()}{item.board};
- })
+
+ if (item.reply && item.reply != 0) {
+ this.state.replies = await getReplies(item.reply);
+ const op = await getBoardsMessage(item.reply);
+ if (op.length == 0) {
+ return;
+ }
+ this.setActivePost(op[0]);
+
+ } else {
+ this.state.replies = await getReplies(item.hash);
+ this.setActivePost(item);
+
}
-
- ;
-
- const boardsSubscriptionsComponent =
-
+ )}
+ />
+ ;
+
+ const messageComponent =
+
+
+ {items}
+
+ ;
+
+
+ const boardsSubscriptions =
+
+ item.board}
+ style={{ backgroundColor: 'transparent' }}
+ renderItem={({ item }) => (
+
+
+ {runes(item.board)[0].toUpperCase()}
+
+
+ :
+
+
+ X
+
- {boardsSubscriptions}
+
+ }
+ rightIcon={item.unread ? {item.unread} : <>>}
- ;
+ showsVerticalScrollIndicator={false}
+ onPress={async () => {
+ !editingBoards || item.board == 'Home' ?
+ getBoard(item.board)
+ :
+ deleteBoard(item.board)
- const messageInput =
-
- { this.input = input }}
- style={{
- color: this.props.screenProps.theme.primaryColour,
- fontFamily: 'Montserrat-Regular',
- fontSize: 15,
- width: '100%',
- height: '100%',
- padding: 15,
-
- }}
- maxLength={512}
- placeholder={"✏️ " + t('typeMessageHere')}
- placeholderTextColor={'#ffffff'}
- onSubmitEditing={async (e) => {
- e.preventDefault();
- // return;
- // submitMessage(this.state.message);
- // this.setState({message: '', messageHasLength: false});
- }}
- onChangeText={(text) => {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- this.state.message = text;
- this.setState({messageHasLength: this.state.message.length > 0});
- }}
- errorMessage={this.props.error}
/>
- ;
+ )}
+ />
+ ;
+
+ const storyStyle = {
+ borderRadius: 25,
+ width: 60,
+ height: 60,
+ backgroundColor: 'white',
+ marginRight: 10,
+ flexDirection: 'row'
+ };
+
+ const storyTextStyle = [Styles.centeredText, {
+ fontSize: 30,
+ lineHeight: 58,
+ width: 60,
+ fontFamily: 'Montserrat-Bold',
+ color: 'white',
+ flex: 1,
+ flexWrap: 'wrap'
+ }];
+
+ const unread_counter_style = {
+ borderRadius: 15,
+ minWidth: 28,
+ height: 28,
+ backgroundColor: 'red',
+ color: 'white',
+ padding: 4,
+ borderWidth: 5
+ };
+
+ const unread_counter_text_style = {
+ fontSize: 14,
+ lineHeight: 14,
+ fontFamily: 'Montserrat-Bold',
+ color: 'white',
+ textAlign: 'center'
+ };
+
+ const modalStyle = {
+ height: '100%',
+ marginTop: 50,
+ backgroundColor: '#272527',
+ borderTopRightRadius: 50,
+ borderTopLeftRadius: 50,
+ padding: 25,
+ alignItems: "center",
+ shadowColor: "#000",
+ shadowOffset: {
+ width: 0,
+ height: 2
+ },
+ shadowOpacity: 0.25,
+ shadowRadius: 4,
+ elevation: 5
+ };
+
+ const boardsStories =
+
+
+ {boardsSubscriptionsItems != undefined && boardsSubscriptionsItems.map(function (item, i) {
+ return { getBoard(item.board) }} style={[storyStyle, { backgroundColor: getBoardColors(item.board) }]}>{runes(item.board)[0].toUpperCase()}{item.board}{item.unread ? {item.unread} : <>>};
+ })
+ }
+
+ ;
+
+ const boardsRecommendations =
+
+ {t('boardsRecommendations')}
+
+ {boardsRecommendationsItems != undefined && boardsRecommendationsItems.map(function (item, i) {
+ return { getBoard(item.board) }} style={[storyStyle, { backgroundColor: getBoardColors(item.board) }]}>{runes(item.board)[0].toUpperCase()}{item.board};
+ })
+ }
+
+ ;
+
+ const boardsSubscriptionsComponent =
+
+
+ {boardsSubscriptions}
+
+ ;
+
+ const messageInput =
+
+ { this.input = input }}
+ style={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontFamily: 'Montserrat-Regular',
+ fontSize: 15,
+ width: '100%',
+ height: '100%',
+ padding: 15,
+
+ }}
+ maxLength={512}
+ placeholder={"✏️ " + t('typeMessageHere')}
+ placeholderTextColor={'#ffffff'}
+ onSubmitEditing={async (e) => {
+ e.preventDefault();
+ // return;
+ // submitMessage(this.state.message);
+ // this.setState({message: '', messageHasLength: false});
+ }}
+ onChangeText={(text) => {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ this.state.message = text;
+ this.setState({ messageHasLength: this.state.message.length > 0 });
+ }}
+ errorMessage={this.props.error}
+ />
+ ;
+
+ const replyInput =
+
+ { this.replyinput = input }}
+ style={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontFamily: 'Montserrat-Regular',
+ fontSize: 15,
+ width: '100%',
+ height: '100%',
+ padding: 15,
+
+ }}
+ maxLength={512}
+ placeholder={"✏️ " + t('typeMessageHere')}
+ placeholderTextColor={'#ffffff'}
+ onSubmitEditing={async (e) => {
+ e.preventDefault();
+ // return;
+ // submitMessage(this.state.message);
+ // this.setState({message: '', messageHasLength: false});
+ }}
+ onChangeText={(text) => {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ this.state.reply = text;
+ this.setState({ replyHasLength: this.state.reply.length > 0 });
+ }}
+ errorMessage={this.props.error}
+ />
+ ;
+
+ return (
+
+
+ {
+ this.setModalVisible(true)
+ }}
+ >
+
- const replyInput =
-
- { this.replyinput = input }}
- style={{
- color: this.props.screenProps.theme.primaryColour,
- fontFamily: 'Montserrat-Regular',
- fontSize: 15,
- width: '100%',
- height: '100%',
- padding: 15,
- }}
- maxLength={512}
- placeholder={"✏️ " + t('typeMessageHere')}
- placeholderTextColor={'#ffffff'}
- onSubmitEditing={async (e) => {
- e.preventDefault();
- // return;
- // submitMessage(this.state.message);
- // this.setState({message: '', messageHasLength: false});
- }}
- onChangeText={(text) => {
- if (this.props.onChange) {
- this.props.onChange(text);
+
+
+ {t('boardsTitle')}
+
+
+ {!this.state.isSubscribedToBoard &&
+ {
+ if (isSubscribedTo(board)) {
+ return;
}
- this.state.reply = text;
- this.setState({replyHasLength: this.state.reply.length > 0});
- }}
- errorMessage={this.props.error}
- />
- ;
+ this.setState({ isSubscribedToBoard: true });
+ subscribeToBoard(board, 0);
+ const subs = this.state.boardssubscriptions;
+ subs.push({ board: board, key: 0 });
+ this.state.boardssubscriptions = subs;
+ this.state.boardsRecommendationsItems = await getBoardRecommendations();
+ }}
+ >
+
+
+ ➕ {t('subscribe')}
+
+
+
+ }
+
+
+
- return(
-
+
+
+
+
+
+
+ {this.state.board == 'Home' && boardsSubscriptionsItems != undefined && boardsSubscriptionsItems.length > 1 && boardsStories}
+
+ {this.state.board == 'Home' && boardsSubscriptionsItems != undefined && boardsSubscriptionsItems.length < 2 && boardsRecommendations}
+
+ {this.state.board && this.state.board != 'Home' &&
+ {messageInput}
+
+ {this.state.messageHasLength &&
+
+ {
+ submitMessage(this.state.message);
+ this.setState({ message: '', messageHasLength: false });
+ }}
+ >
- {
- this.setModalVisible(true)
- }}
+
+ {t('send')}
+
+
+
+
+ }
+
+ }
+
+ this.setModalVisible(false)}
+ >
+
+ {
+ this.setModalVisible(!modalVisible);
+ }}
+ >
+
+
+ {t('myBoards')}
+
+
+
-
+ { this.boardinput = boardinput }}
+ style={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontFamily: 'Montserrat-Regular',
+ fontSize: 15,
+ paddingTop: 2,
+ paddingBottom: 6
+ }}
+ maxLength={20}
+ placeholder={"➕ " + t('subscribe')}
+ placeholderTextColor={'#ffffff'}
+ onSubmitEditing={async (e) => {
+ e.preventDefault();
+ subscribeToBoard(this.state.boardinput, 0);
-
- {t('boardsTitle')}
-
+ const subs = this.state.boardssubscriptions;
+ subs.push({ board: this.state.boardinput, key: 0 });
+
+ this.state.boardssubscriptions = subs;
+ this.setModalVisible(!modalVisible);
+
+ getBoard(this.state.boardinput);
+ // return;
+ // submitMessage(this.state.message);
+ // this.setState({message: '', messageHasLength: false});
+ }}
+ onChangeText={(text) => {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ this.state.boardinput = text;
+ }}
+ errorMessage={this.props.error}
+ />
+
+
+
+ {boardsSubscriptionsComponent}
+
+
+
+
+
+
+
+
+
+ {boardsRecommendationsItems != undefined && boardsRecommendations}
+
+
+
+
+
+
+ this.setMessageModalVisible(false)}
+ >
+
+ {
+ this.setMessageModalVisible(!messageModalVisible);
+ }}
+ >
+
+
- {!this.state.isSubscribedToBoard &&
- {
- if ( isSubscribedTo(board) ) {
- return;
- }
- this.setState({isSubscribedToBoard: true});
- subscribeToBoard(board, 0);
- const subs = this.state.boardssubscriptions;
- subs.push({board: board,key: 0});
- this.state.boardssubscriptions = subs;
- this.state.boardsRecommendationsItems = await getBoardRecommendations();
- }}
- >
-
-
- ➕ {t('subscribe')}
-
-
-
- }
+
+
+
+
+
+
+ {this.state.activePost.nickname ? this.state.activePost.nickname : 'Anonymous'}
+
+
+ {board == 'Home' &&
+
-
+ }}>
- {board}
-
+ {this.state.activePost.board}
+
+
+ }
-
-
+
+
+
+
+ {this.state.activePost.message + "\n"}
+ {this.state.activePost.timestamp}
- {this.state.board == 'Home' && boardsSubscriptionsItems != undefined && boardsSubscriptionsItems.length > 1 && boardsStories}
- {this.state.board == 'Home' && boardsSubscriptionsItems != undefined && boardsSubscriptionsItems.length < 2 && boardsRecommendations}
+
+
- {this.state.board && this.state.board != 'Home' &&
- {messageInput}
-
- {this.state.messageHasLength &&
-
- {
- submitMessage(this.state.message);
- this.setState({message: '', messageHasLength: false});
- }}
- >
-
-
- {t('send')}
-
-
-
+ }}>
- }
+ {replyInput}
- }
+ {this.state.replyHasLength &&
- this.setModalVisible(false) }
- >
-
- {
- this.setModalVisible(!modalVisible);
+ {
+ submitReply(this.state.reply);
+ this.setState({ reply: '', replyHasLength: false });
}}
>
-
-
- {t('myBoards')}
-
-
-
- { this.boardinput = boardinput }}
- style={{
- color: this.props.screenProps.theme.primaryColour,
- fontFamily: 'Montserrat-Regular',
- fontSize: 15,
- paddingTop: 2,
- paddingBottom: 6
-
- }}
- maxLength={20}
- placeholder={ "➕ " + t('subscribe')}
- placeholderTextColor={'#ffffff'}
- onSubmitEditing={async (e) => {
- e.preventDefault();
-
- subscribeToBoard(this.state.boardinput, 0);
-
- const subs = this.state.boardssubscriptions;
- subs.push({board: this.state.boardinput,key: 0});
-
- this.state.boardssubscriptions = subs;
- this.setModalVisible(!modalVisible);
-
- getBoard(this.state.boardinput);
- // return;
- // submitMessage(this.state.message);
- // this.setState({message: '', messageHasLength: false});
- }}
- onChangeText={(text) => {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- this.state.boardinput = text;
- }}
- errorMessage={this.props.error}
- />
-
-
-
- { boardsSubscriptionsComponent }
-
-
-
-
-
-
-
-
-
- {boardsRecommendationsItems != undefined && boardsRecommendations}
-
-
-
-
-
-
- this.setMessageModalVisible(false) }
- >
-
- {
- this.setMessageModalVisible(!messageModalVisible);
- }}
- >
-
-
-
-
-
+
-
-
-
-
-
- {this.state.activePost.nickname ? this.state.activePost.nickname : 'Anonymous'}
-
-
- {board == 'Home' &&
-
-
-
-
- {this.state.activePost.board}
-
-
-
- }
-
-
-
-
-
-
- {this.state.activePost.message + "\n"}
- {this.state.activePost.timestamp}
-
-
-
+ {t('send')}
+
+
-
-
- {replyInput}
-
- {this.state.replyHasLength &&
-
- {
- submitReply(this.state.reply);
- this.setState({reply: '', replyHasLength: false});
- }}
- >
-
-
- {t('send')}
-
-
-
+ }
- }
+
-
-
-
-
- {this.state.board == 'Home' &&
-
-
-
-
+
+
+ {this.state.board == 'Home' &&
+
+
+
+
-
-
+
+
-
+
- {this.state.replies && this.state.replies.map((item,i) => {
- return
-
+ {this.state.replies && this.state.replies.map((item, i) => {
+ return
+
-
-
-
+
+ {item.nickname ? item.nickname : 'Anonymous'}
-
+ }}>{item.nickname ? item.nickname : 'Anonymous'}
+
- {item.message}{item.timestamp}
-
- } ) }
-
+ {item.message}{item.timestamp}
+ })}
+
-
-
-
-
-
+
+
+
+
+
-
- {this.state.messages.length > 0 ? messageComponent : noMessagesComponent}
+
-
-
-
- );
- }
+ {this.state.messages.length > 0 ? messageComponent : noMessagesComponent}
+
+
+
+
+ );
+ }
}
export const BoardsHomeScreen = withTranslation()(BoardsHomeScreenNoTranslation)
function isPaymentIDValid(paymentID) {
- let errorMessage = '';
+ let errorMessage = '';
- if (paymentID === '') {
- return [true, errorMessage];
- }
+ if (paymentID === '') {
+ return [true, errorMessage];
+ }
- if (paymentID === undefined || paymentID === null) {
- return [false, errorMessage];
- }
+ if (paymentID === undefined || paymentID === null) {
+ return [false, errorMessage];
+ }
- const paymentIDError = validatePaymentID(paymentID);
+ const paymentIDError = validatePaymentID(paymentID);
- if (paymentIDError.errorCode !== WalletErrorCode.SUCCESS) {
- errorMessage = paymentIDError.toString();
+ if (paymentIDError.errorCode !== WalletErrorCode.SUCCESS) {
+ errorMessage = paymentIDError.toString();
- return [false, errorMessage];
- }
+ return [false, errorMessage];
+ }
- return [true, errorMessage];
+ return [true, errorMessage];
}
diff --git a/src/CreateScreen.js b/src/CreateScreen.js
index e1b65c6..ca52dac 100644
--- a/src/CreateScreen.js
+++ b/src/CreateScreen.js
@@ -5,7 +5,7 @@
import React from 'react';
import {
- View, Text, Button, Image,
+ View, Text, Button,
} from 'react-native';
import { WalletBackend } from 'kryptokrona-wallet-backend-js';
@@ -16,23 +16,21 @@ import { Styles } from './Styles';
import { Globals } from './Globals';
import { saveToDatabase, savePreferencesToDatabase } from './Database';
import { XKRLogo } from './XKRLogo';
-import { updateCoinPrice } from './Currency';
-import { navigateWithDisabledBack } from './Utilities';
import { BottomButton, SeedComponent } from './SharedComponents';
import { getBestNode } from './HuginUtilities';
import './i18n.js';
import { withTranslation } from 'react-i18next';
let changeNode = async () => {
-
- const node = await getBestNode();
-
- Globals.preferences.node = node.url + ':' + node.port + ':' + node.ssl;
-
- await savePreferencesToDatabase(Globals.preferences);
-
- Globals.wallet.swapNode(Globals.getDaemon());
-
+
+ const node = await getBestNode();
+
+ Globals.preferences.node = node.url + ':' + node.port + ':' + node.ssl;
+
+ await savePreferencesToDatabase(Globals.preferences);
+
+ Globals.wallet.swapNode(Globals.getDaemon());
+
}
@@ -40,58 +38,58 @@ let changeNode = async () => {
* Create or import a wallet
*/
class WalletOptionScreenNoTranslation extends React.Component {
- static navigationOptions = {
- header: null,
- };
-
- constructor(props) {
- super(props);
- }
-
- render() {
- const { t } = this.props;
- return(
-
-
-
-
- Hugin Messenger {'\n'}
-
-
- {t('welcomeMessage')}
-
-
-
-
-
-
-
-
-
- );
- }
+ static navigationOptions = {
+ header: null,
+ };
+
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ const { t } = this.props;
+ return (
+
+
+
+
+ Hugin Messenger {'\n'}
+
+
+ {t('welcomeMessage')}
+
+
+
+
+
+
+
+
+
+ );
+ }
}
export const WalletOptionScreen = withTranslation()(WalletOptionScreenNoTranslation)
@@ -100,82 +98,82 @@ export const WalletOptionScreen = withTranslation()(WalletOptionScreenNoTranslat
* Create a new wallet
*/
class CreateWalletScreenNoTranslation extends React.Component {
- static navigationOptions = {
- title: 'Create',
- header: null,
- };
+ static navigationOptions = {
+ title: 'Create',
+ header: null,
+ };
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- this.state = {
- seed: '',
- }
- };
+ this.state = {
+ seed: '',
+ }
+ };
- async componentDidMount() {
+ async componentDidMount() {
- Globals.wallet = await WalletBackend.createWallet(Globals.getDaemon(), Config);
+ Globals.wallet = await WalletBackend.createWallet(Globals.getDaemon(), Config);
- const [ seed ] = await Globals.wallet.getMnemonicSeed();
+ const [seed] = await Globals.wallet.getMnemonicSeed();
- changeNode();
+ changeNode();
- this.setState({
- seed,
- });
+ this.setState({
+ seed,
+ });
- /* Save wallet in DB */
- saveToDatabase(Globals.wallet);
+ /* Save wallet in DB */
+ saveToDatabase(Globals.wallet);
- }
+ }
- render() {
- const { t } = this.props;
- return(
-
-
-
- {t('walletCreated')}
-
-
-
- {t('walletCreatedSubtitle')}
-
-
-
- {t('walletCreatedSubtitleSubtitle')}
-
-
-
-
-
-
-
-
-
-
- {this.state.seed !== '' && }
-
- this.props.navigation.navigate('Home')}
- {...this.props}
- />
-
-
-
- );
- }
+ render() {
+ const { t } = this.props;
+ return (
+
+
+
+ {t('walletCreated')}
+
+
+
+ {t('walletCreatedSubtitle')}
+
+
+
+ {t('walletCreatedSubtitleSubtitle')}
+
+
+
+
+
+
+
+
+
+
+ {this.state.seed !== '' && }
+
+ this.props.navigation.navigate('Home')}
+ {...this.props}
+ />
+
+
+
+ );
+ }
}
export const CreateWalletScreen = withTranslation()(CreateWalletScreenNoTranslation)
diff --git a/src/Database.js b/src/Database.js
index 64a8239..9f25496 100644
--- a/src/Database.js
+++ b/src/Database.js
@@ -9,7 +9,6 @@ import * as _ from 'lodash';
import { AsyncStorage } from 'react-native';
import Config from './Config';
-import Constants from './Constants';
import { Globals } from './Globals';
@@ -21,139 +20,139 @@ let database;
const databaseRowLimit = 1024 * 512;
export async function deleteDB() {
- try {
- await setHaveWallet(false);
+ try {
+ await setHaveWallet(false);
- await SQLite.deleteDatabase({
- name: 'data.DB',
- location: 'default',
- });
- } catch (err) {
- Globals.logger.addLogMessage(err);
- }
+ await SQLite.deleteDatabase({
+ name: 'data.DB',
+ location: 'default',
+ });
+ } catch (err) {
+ Globals.logger.addLogMessage(err);
+ }
}
/* https://stackoverflow.com/a/29202760/8737306 */
function chunkString(string, size) {
- const numChunks = Math.ceil(string.length / size);
- const chunks = new Array(numChunks);
+ const numChunks = Math.ceil(string.length / size);
+ const chunks = new Array(numChunks);
- for (let i = 0, o = 0; i < numChunks; i++, o += size) {
- chunks[i] = string.substr(o, size);
- }
+ for (let i = 0, o = 0; i < numChunks; i++, o += size) {
+ chunks[i] = string.substr(o, size);
+ }
- return chunks;
+ return chunks;
}
async function saveWallet(wallet) {
- /* Split into chunks of 512kb */
- const chunks = chunkString(wallet, databaseRowLimit);
+ /* Split into chunks of 512kb */
+ const chunks = chunkString(wallet, databaseRowLimit);
- await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM wallet`
- );
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `DELETE FROM wallet`
+ );
- for (let i = 0; i < chunks.length; i++) {
- tx.executeSql(
- `INSERT INTO wallet
+ for (let i = 0; i < chunks.length; i++) {
+ tx.executeSql(
+ `INSERT INTO wallet
(id, json)
VALUES
(?, ?)`,
- [ i, chunks[i] ]
- );
- }
- });
+ [i, chunks[i]]
+ );
+ }
+ });
}
export async function loadWallet() {
- try {
- let [data] = await database.executeSql(
- `SELECT
+ try {
+ let [data] = await database.executeSql(
+ `SELECT
LENGTH(json) AS jsonLength
FROM
wallet`
- );
+ );
- if (data && data.rows && data.rows.length === 1) {
- const len = data.rows.item(0).jsonLength;
- let result = '';
+ if (data && data.rows && data.rows.length === 1) {
+ const len = data.rows.item(0).jsonLength;
+ let result = '';
- if (len > databaseRowLimit) {
- for (let i = 1; i <= len; i += databaseRowLimit) {
- const [chunk] = await database.executeSql(
- `SELECT
+ if (len > databaseRowLimit) {
+ for (let i = 1; i <= len; i += databaseRowLimit) {
+ const [chunk] = await database.executeSql(
+ `SELECT
SUBSTR(json, ?, ?) AS data
FROM
wallet`,
- [
- i,
- databaseRowLimit
- ]
- );
-
- if (chunk && chunk.rows && chunk.rows.length === 1) {
- result += chunk.rows.item(0).data;
- }
- }
+ [
+ i,
+ databaseRowLimit
+ ]
+ );
- return [ result, undefined ];
- }
+ if (chunk && chunk.rows && chunk.rows.length === 1) {
+ result += chunk.rows.item(0).data;
+ }
}
- [data] = await database.executeSql(
- `SELECT
+ return [result, undefined];
+ }
+ }
+
+ [data] = await database.executeSql(
+ `SELECT
json
FROM
wallet
ORDER BY
id ASC`
- );
+ );
- if (data && data.rows && data.rows.length >= 1) {
- const len = data.rows.length;
+ if (data && data.rows && data.rows.length >= 1) {
+ const len = data.rows.length;
- let result = '';
+ let result = '';
- for (let i = 0; i < len; i++) {
- result += data.rows.item(i).json;
- }
+ for (let i = 0; i < len; i++) {
+ result += data.rows.item(i).json;
+ }
- return [ result, undefined ];
- }
- } catch (err) {
- return [ undefined, err ];
+ return [result, undefined];
}
+ } catch (err) {
+ return [undefined, err];
+ }
- return [ undefined, 'Wallet not found in database!' ];
+ return [undefined, 'Wallet not found in database!'];
}
/* Create the tables if we haven't made them already */
async function createTables(DB) {
- const [dbVersionData] = await DB.executeSql(
- `PRAGMA user_version`,
- );
+ const [dbVersionData] = await DB.executeSql(
+ `PRAGMA user_version`,
+ );
- let dbVersion = 0;
+ let dbVersion = 0;
- if (dbVersionData && dbVersionData.rows && dbVersionData.rows.length >= 1) {
- dbVersion = dbVersionData.rows.item(0).user_version;
- }
+ if (dbVersionData && dbVersionData.rows && dbVersionData.rows.length >= 1) {
+ dbVersion = dbVersionData.rows.item(0).user_version;
+ }
- await DB.transaction((tx) => {
+ await DB.transaction((tx) => {
- /* We get JSON out from our wallet backend, and load JSON in from our
- wallet backend - it's a little ugly, but it's faster to just read/write
- json to the DB rather than structuring it. */
- tx.executeSql(
- `CREATE TABLE IF NOT EXISTS wallet (
+ /* We get JSON out from our wallet backend, and load JSON in from our
+ wallet backend - it's a little ugly, but it's faster to just read/write
+ json to the DB rather than structuring it. */
+ tx.executeSql(
+ `CREATE TABLE IF NOT EXISTS wallet (
id INTEGER PRIMARY KEY,
json TEXT
)`
- );
+ );
- tx.executeSql(
- `CREATE TABLE IF NOT EXISTS preferences (
+ tx.executeSql(
+ `CREATE TABLE IF NOT EXISTS preferences (
id INTEGER PRIMARY KEY,
currency TEXT,
notificationsenabled BOOLEAN,
@@ -168,53 +167,53 @@ async function createTables(DB) {
autopickcache TEXT default "true",
websocketenabled TEXT default "true"
)`
- );
+ );
- /* Add new columns */
- if (dbVersion === 0) {
- tx.executeSql(
- `ALTER TABLE
+ /* Add new columns */
+ if (dbVersion === 0) {
+ tx.executeSql(
+ `ALTER TABLE
preferences
ADD
autooptimize BOOLEAN`
- );
+ );
- tx.executeSql(
- `ALTER TABLE
+ tx.executeSql(
+ `ALTER TABLE
preferences
ADD
authmethod TEXT`
- );
- }
+ );
+ }
- if (dbVersion === 0 || dbVersion === 1) {
- tx.executeSql(
- `ALTER TABLE
+ if (dbVersion === 0 || dbVersion === 1) {
+ tx.executeSql(
+ `ALTER TABLE
preferences
ADD
node TEXT`
- );
- }
+ );
+ }
- if (dbVersion === 2) {
- tx.executeSql(
- `ALTER TABLE
+ if (dbVersion === 2) {
+ tx.executeSql(
+ `ALTER TABLE
message_db
ADD
read BOOLEAN default 1`
- );
- }
+ );
+ }
- tx.executeSql(
- `CREATE TABLE IF NOT EXISTS payees (
+ tx.executeSql(
+ `CREATE TABLE IF NOT EXISTS payees (
nickname TEXT,
address TEXT,
paymentid TEXT
)`
- );
+ );
- tx.executeSql(
- `CREATE TABLE IF NOT EXISTS message_db (
+ tx.executeSql(
+ `CREATE TABLE IF NOT EXISTS message_db (
conversation TEXT,
type TEXT,
message TEXT,
@@ -222,21 +221,21 @@ async function createTables(DB) {
read BOOLEAN default 1,
UNIQUE (timestamp)
)`
- );
+ );
- tx.executeSql(
- `CREATE TABLE IF NOT EXISTS privateboards (
+ tx.executeSql(
+ `CREATE TABLE IF NOT EXISTS privateboards (
name TEXT,
key TEXT,
latestmessage INT default 0,
UNIQUE (key)
)`
- );
+ );
-
- tx.executeSql(
- `CREATE TABLE IF NOT EXISTS privateboards_messages_db (
+
+ tx.executeSql(
+ `CREATE TABLE IF NOT EXISTS privateboards_messages_db (
board TEXT,
nickname TEXT,
address TEXT,
@@ -249,12 +248,12 @@ async function createTables(DB) {
replies INT default 0,
UNIQUE (timestamp)
)`
- );
+ );
- tx.executeSql(
- `CREATE TABLE IF NOT EXISTS boards_message_db (
+ tx.executeSql(
+ `CREATE TABLE IF NOT EXISTS boards_message_db (
address TEXT,
message TEXT,
signature TEXT,
@@ -266,7 +265,7 @@ async function createTables(DB) {
sent BOOLEAN,
read BOOLEAN default 1
)`
- );
+ );
tx.executeSql(
`CREATE TABLE IF NOT EXISTS sync_status (
@@ -274,109 +273,109 @@ async function createTables(DB) {
lastSyncGroup INT default 0,
lastSyncDM INT default 0
)`
- );
+ );
- tx.executeSql(
- `CREATE TABLE IF NOT EXISTS boards_subscriptions (
+ tx.executeSql(
+ `CREATE TABLE IF NOT EXISTS boards_subscriptions (
board TEXT,
key TEXT,
latest_message INT default 0
)`
- );
+ );
- tx.executeSql(
- `CREATE TABLE IF NOT EXISTS knownTXs (
+ tx.executeSql(
+ `CREATE TABLE IF NOT EXISTS knownTXs (
hash TEXT,
timestamp TEXT,
UNIQUE (hash)
)`
- );
+ );
- tx.executeSql(
- `CREATE TABLE IF NOT EXISTS transactiondetails (
+ tx.executeSql(
+ `CREATE TABLE IF NOT EXISTS transactiondetails (
hash TEXT,
memo TEXT,
address TEXT,
payee TEXT
)`
- );
+ );
- /* Enter initial wallet value that we're going to overwrite later via
- primary key, provided it doesn't already exist */
- tx.executeSql(
- `INSERT OR IGNORE INTO wallet
+ /* Enter initial wallet value that we're going to overwrite later via
+ primary key, provided it doesn't already exist */
+ tx.executeSql(
+ `INSERT OR IGNORE INTO wallet
(id, json)
VALUES
(0, '')`
- );
+ );
- if (dbVersion === 3) {
- tx.executeSql(
- `ALTER TABLE
+ if (dbVersion === 3) {
+ tx.executeSql(
+ `ALTER TABLE
preferences
ADD
nickname TEXT default 'Anonymous'`
- );
- }
+ );
+ }
- if (dbVersion === 4) {
+ if (dbVersion === 4) {
- tx.executeSql(
- `ALTER TABLE
+ tx.executeSql(
+ `ALTER TABLE
boards_subscriptions
ADD
latest_message INT default 0`);
- }
- console.log('dbVersion', dbVersion);
- if (dbVersion === 6) {
+ }
+ console.log('dbVersion', dbVersion);
+ if (dbVersion === 6) {
- tx.executeSql(
- `ALTER TABLE
+ tx.executeSql(
+ `ALTER TABLE
privateboards_messages_db
ADD
reply TEXT default ''`);
- tx.executeSql(
- `ALTER TABLE
+ tx.executeSql(
+ `ALTER TABLE
privateboards_messages_db
ADD
hash TEXT default ''`);
-
- }
- if (dbVersion === 7) {
- tx.executeSql(
- `ALTER TABLE
+ }
+
+ if (dbVersion === 7) {
+ tx.executeSql(
+ `ALTER TABLE
preferences
ADD
cache TEXT default '${Config.defaultCache}'`
- );
- tx.executeSql(
- `ALTER TABLE
+ );
+ tx.executeSql(
+ `ALTER TABLE
preferences
ADD
cacheenabled text default "true"`
- );
+ );
- tx.executeSql(
- `ALTER TABLE
+ tx.executeSql(
+ `ALTER TABLE
preferences
ADD
autopickcache text default "true"`
- );
+ );
- tx.executeSql(
- `ALTER TABLE
+ tx.executeSql(
+ `ALTER TABLE
preferences
ADD
websocketenabled text default "true"`
- );
-
+ );
+
- tx.executeSql(
- `CREATE TABLE IF NOT EXISTS privateboards_messages_db2 (
+ tx.executeSql(
+ `CREATE TABLE IF NOT EXISTS privateboards_messages_db2 (
board TEXT,
nickname TEXT,
address TEXT,
@@ -388,15 +387,15 @@ async function createTables(DB) {
reply TEXT,
UNIQUE (timestamp)
)`
- );
+ );
- tx.executeSql(
- `REPLACE INTO privateboards_messages_db2 SELECT * FROM privateboards_messages_db`
- );
+ tx.executeSql(
+ `REPLACE INTO privateboards_messages_db2 SELECT * FROM privateboards_messages_db`
+ );
- tx.executeSql(
- `CREATE TABLE IF NOT EXISTS privateboards_messages_db (
+ tx.executeSql(
+ `CREATE TABLE IF NOT EXISTS privateboards_messages_db (
board TEXT,
nickname TEXT,
address TEXT,
@@ -408,31 +407,31 @@ async function createTables(DB) {
reply TEXT,
UNIQUE (timestamp)
)`
- );
+ );
- tx.executeSql(
- `REPLACE INTO privateboards_messages_db SELECT * FROM privateboards_messages_db2`
- );
+ tx.executeSql(
+ `REPLACE INTO privateboards_messages_db SELECT * FROM privateboards_messages_db2`
+ );
- tx.executeSql(
- `DROP TABLE privateboards_messages_db2`
- );
+ tx.executeSql(
+ `DROP TABLE privateboards_messages_db2`
+ );
- }
+ }
- if (dbVersion === 8) {
- tx.executeSql(
- `ALTER TABLE
+ if (dbVersion === 8) {
+ tx.executeSql(
+ `ALTER TABLE
privateboards_messages_db
ADD
replies INT default 0`
- );
- }
+ );
+ }
- /* Setup default preference values */
- tx.executeSql(
- `INSERT OR IGNORE INTO preferences (
+ /* Setup default preference values */
+ tx.executeSql(
+ `INSERT OR IGNORE INTO preferences (
id,
currency,
notificationsenabled,
@@ -458,15 +457,15 @@ async function createTables(DB) {
?,
'Anonymous'
)`,
- [
- Config.defaultDaemon.getConnectionString(),
- ],
- );
+ [
+ Config.defaultDaemon.getConnectionString(),
+ ],
+ );
- /* Set new auto optimize column if not assigned yet */
- if (dbVersion === 0) {
- tx.executeSql(
- `UPDATE
+ /* Set new auto optimize column if not assigned yet */
+ if (dbVersion === 0) {
+ tx.executeSql(
+ `UPDATE
preferences
SET
autooptimize = 1,
@@ -474,25 +473,25 @@ async function createTables(DB) {
node = ?
WHERE
id = 0`,
- [
- Config.defaultDaemon.getConnectionString(),
- ],
- );
- } else if (dbVersion === 1) {
- tx.executeSql(
- `UPDATE
+ [
+ Config.defaultDaemon.getConnectionString(),
+ ],
+ );
+ } else if (dbVersion === 1) {
+ tx.executeSql(
+ `UPDATE
preferences
SET
node = ?
WHERE
id = 0`,
- [
- Config.defaultDaemon.getConnectionString(),
- ],
- );
- }
- // Remove old messages
- tx.executeSql(`
+ [
+ Config.defaultDaemon.getConnectionString(),
+ ],
+ );
+ }
+ // Remove old messages
+ tx.executeSql(`
DELETE FROM privateboards_messages_db
WHERE rowid IN (
SELECT rowid
@@ -505,30 +504,31 @@ async function createTables(DB) {
)
`);
- tx.executeSql(
- `PRAGMA user_version = 9`
- );
- });
+ tx.executeSql(
+ `PRAGMA user_version = 9`
+ );
+ });
}
export async function openDB() {
- try {
- database = await SQLite.openDatabase({
- name: 'data.DB',
- location: 'default',
- });
+ try {
+ database = await SQLite.openDatabase({
+ name: 'data.DB',
+ location: 'default',
+ });
- await createTables(database);
- } catch (err) {
- Globals.logger.addLogMessage('Failed to open DB: ' + err);
- }
+ await createTables(database);
+ } catch (err) {
+ Globals.logger.addLogMessage('Failed to open DB: ' + err);
+ }
}
export async function savePreferencesToDatabase(preferences) {
- await database.transaction((tx) => {
- tx.executeSql(
- `UPDATE
+ console.log('-----', { preferences })
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `UPDATE
preferences
SET
currency = ?,
@@ -548,30 +548,30 @@ export async function savePreferencesToDatabase(preferences) {
websocketenabled = ?
WHERE
id = 0`,
- [
- preferences.currency,
- preferences.notificationsEnabled ? 1 : 0,
- preferences.scanCoinbaseTransactions ? 1 : 0,
- preferences.limitData ? 1 : 0,
- preferences.theme,
- preferences.authConfirmation ? 1 : 0,
- preferences.autoOptimize ? 1 : 0,
- preferences.authenticationMethod,
- preferences.node,
- preferences.language,
- preferences.nickname,
- preferences.cache,
- preferences.cacheEnabled,
- preferences.autoPickCache,
- preferences.websocketEnabled
- ]
- );
- });
+ [
+ preferences.currency,
+ preferences.notificationsEnabled ? 1 : 0,
+ preferences.scanCoinbaseTransactions ? 1 : 0,
+ preferences.limitData ? 1 : 0,
+ preferences.theme,
+ preferences.authConfirmation ? 1 : 0,
+ preferences.autoOptimize ? 1 : 0,
+ preferences.authenticationMethod,
+ preferences.node,
+ preferences.language,
+ preferences.nickname,
+ preferences.cache,
+ preferences.cacheEnabled,
+ preferences.autoPickCache,
+ preferences.websocketEnabled
+ ]
+ );
+ });
}
export async function loadPreferencesFromDatabase() {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
currency,
notificationsenabled,
scancoinbasetransactions,
@@ -591,51 +591,51 @@ export async function loadPreferencesFromDatabase() {
preferences
WHERE
id = 0`,
- );
+ );
- if (data && data.rows && data.rows.length >= 1) {
- const item = data.rows.item(0);
-
- return {
- currency: item.currency,
- notificationsEnabled: item.notificationsenabled === 1,
- scanCoinbaseTransactions: item.scancoinbasetransactions === 1,
- limitData: item.limitdata === 1,
- theme: item.theme,
- authConfirmation: item.pinconfirmation === 1,
- autoOptimize: item.autooptimize === 1,
- authenticationMethod: item.authmethod,
- node: item.node,
- language: item.language,
- nickname: item.nickname,
- cache: item.cache,
- cacheEnabled: item.cacheenabled,
- autoPickCache: item.autopickcache,
- websocketEnabled: item.websocketenabled
- }
+ if (data && data.rows && data.rows.length >= 1) {
+ const item = data.rows.item(0);
+
+ return {
+ currency: item.currency,
+ notificationsEnabled: item.notificationsenabled === 1,
+ scanCoinbaseTransactions: item.scancoinbasetransactions === 1,
+ limitData: item.limitdata === 1,
+ theme: item.theme,
+ authConfirmation: item.pinconfirmation === 1,
+ autoOptimize: item.autooptimize === 1,
+ authenticationMethod: item.authmethod,
+ node: item.node,
+ language: item.language,
+ nickname: item.nickname,
+ cache: item.cache,
+ cacheEnabled: item.cacheenabled,
+ autoPickCache: item.autopickcache,
+ websocketEnabled: item.websocketenabled
}
+ }
- return undefined;
+ return undefined;
}
-export async function saveMessage(conversation, type, message, timestamp, read=0) {
+export async function saveMessage(conversation, type, message, timestamp, read = 0) {
console.log('Saving message', conversation, type, message, timestamp, read);
await database.transaction((tx) => {
- tx.executeSql(
- `REPLACE INTO message_db
+ tx.executeSql(
+ `REPLACE INTO message_db
(conversation, type, message, timestamp, read)
VALUES
(?, ?, ?, ?, ?)`,
- [
- conversation,
- type,
- message,
- timestamp,
- read
- ]
- );
+ [
+ conversation,
+ type,
+ message,
+ timestamp,
+ read
+ ]
+ );
});
Globals.updateMessages();
@@ -715,72 +715,72 @@ export async function getLastSync() {
export async function updateMessage(temp_timestamp, type) {
- console.log('Updating message', temp_timestamp, type);
-
- await database.transaction((tx) => {
- tx.executeSql(
- `UPDATE message_db
+ console.log('Updating message', temp_timestamp, type);
+
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `UPDATE message_db
SET type = ?
WHERE timestamp = ?`,
- [
- type,
- temp_timestamp
- ]
- );
- });
-
- Globals.updateMessages();
-
- }
+ [
+ type,
+ temp_timestamp
+ ]
+ );
+ });
- export async function updateGroupMessage(temp_timestamp, type, hash) {
+ Globals.updateMessages();
- console.log('Updating group message', temp_timestamp, type, hash);
+}
- await database.transaction((tx) => {
- tx.executeSql(
- `UPDATE privateboards_messages_db
+export async function updateGroupMessage(temp_timestamp, type, hash) {
+
+ console.log('Updating group message', temp_timestamp, type, hash);
+
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `UPDATE privateboards_messages_db
SET type = ?, hash = ?
WHERE timestamp = ?`,
- [
- type,
- hash,
- temp_timestamp
- ]
- );
- });
-
- Globals.updateGroups();
-
- }
+ [
+ type,
+ hash,
+ temp_timestamp
+ ]
+ );
+ });
-export async function saveKnownTransaction(txhash) {
+ Globals.updateGroups();
+
+}
+
+export async function saveKnownTransaction(txhash) {
console.log('Saving known pool tx ', txhash);
const timestamp = Date.now();
await database.transaction((tx) => {
- tx.executeSql(
- `REPLACE INTO knownTXs
+ tx.executeSql(
+ `REPLACE INTO knownTXs
(hash, timestamp)
VALUES
(?, ?)`,
- [
- txhash, timestamp
- ]
- );
+ [
+ txhash, timestamp
+ ]
+ );
});
}
export function emptyKnownTXs() {
- database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM knownTXs`
- );
- });
+ database.transaction((tx) => {
+ tx.executeSql(
+ `DELETE FROM knownTXs`
+ );
+ });
}
@@ -794,14 +794,14 @@ export async function getKnownTransactions() {
if (data && data.rows && data.rows.length) {
- const knownTXs = [];
+ const knownTXs = [];
- for (let i = 0; i < data.rows.length; i++) {
+ for (let i = 0; i < data.rows.length; i++) {
- knownTXs.push(data.rows.item(i).hash);
+ knownTXs.push(data.rows.item(i).hash);
- }
- return knownTXs;
+ }
+ return knownTXs;
} else {
return [];
@@ -813,7 +813,7 @@ export async function deleteKnownTransaction(txhash) {
console.log('Deleting known pool tx ', txhash);
- const oldest_timestamp_allowed = Date.now() - (60*60*24*1000);
+ const oldest_timestamp_allowed = Date.now() - (60 * 60 * 24 * 1000);
await database.transaction((tx) => {
tx.executeSql(
@@ -824,9 +824,9 @@ export async function deleteKnownTransaction(txhash) {
OR
timestamp < ?
`,
- [ txhash, oldest_timestamp_allowed ]
- );
-});
+ [txhash, oldest_timestamp_allowed]
+ );
+ });
}
@@ -838,74 +838,74 @@ export async function saveGroupMessage(group, type, message, timestamp, nickname
console.log('Saving group message', group, type, message, timestamp, nickname, address, read);
await database.transaction((tx) => {
- tx.executeSql(
- `REPLACE INTO privateboards_messages_db
+ tx.executeSql(
+ `REPLACE INTO privateboards_messages_db
(board, type, message, timestamp, nickname, address, read, reply, hash)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?)`,
- [
- group,
- type,
- message,
- timestamp,
- nickname,
- address,
- read,
- reply,
- hash
- ]
- );
+ [
+ group,
+ type,
+ message,
+ timestamp,
+ nickname,
+ address,
+ read,
+ reply,
+ hash
+ ]
+ );
});
-
+
if (reply) {
-
- await database.transaction((tx) => {
- tx.executeSql(
- `UPDATE privateboards_messages_db
+
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `UPDATE privateboards_messages_db
SET replies = replies + ?
WHERE hash = ?`,
- [1, reply]
- );
-
- });
-
- }
+ [1, reply]
+ );
- Globals.updateGroups();
+ });
+
+ }
+
+ Globals.updateGroups();
}
-export async function saveBoardsMessage(message, address, signature, board, timestamp, nickname, reply, hash, sent, silent=false) {
+export async function saveBoardsMessage(message, address, signature, board, timestamp, nickname, reply, hash, sent, silent = false) {
-let fromMyself = address == Globals.wallet.getPrimaryAddress();
+ let fromMyself = address == Globals.wallet.getPrimaryAddress();
await database.transaction((tx) => {
- tx.executeSql(
- `REPLACE INTO boards_message_db
+ tx.executeSql(
+ `REPLACE INTO boards_message_db
(message, address, signature, board, timestamp, nickname, reply, hash, sent, read)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
- [
- message, address, signature, board, timestamp, nickname, reply, hash, sent, fromMyself ? 1 : 0
- ]
- );
+ [
+ message, address, signature, board, timestamp, nickname, reply, hash, sent, fromMyself ? 1 : 0
+ ]
+ );
});
console.log(silent);
await database.transaction((tx) => {
- tx.executeSql(
- ` UPDATE
+ tx.executeSql(
+ ` UPDATE
boards_subscriptions
SET
latest_message = ?
WHERE
board = ?`,
- [
- timestamp, board
- ]
- );
+ [
+ timestamp, board
+ ]
+ );
});
if (!silent) {
@@ -919,13 +919,13 @@ export async function removeMessage(timestamp) {
console.log('Removing message ', timestamp);
await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM
+ tx.executeSql(
+ `DELETE FROM
message_db
WHERE
timestamp = ?`,
- [ timestamp ]
- );
+ [timestamp]
+ );
});
Globals.updateMessages();
@@ -934,38 +934,38 @@ export async function removeMessage(timestamp) {
export async function removeGroupMessage(timestamp) {
- console.log('Removing message ', timestamp);
-
- await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM
+ console.log('Removing message ', timestamp);
+
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `DELETE FROM
privateboards_messages_db
WHERE
timestamp = ?`,
- [ timestamp ]
- );
- });
-
- Globals.updateMessages();
-
- }
+ [timestamp]
+ );
+ });
+
+ Globals.updateMessages();
+
+}
export async function saveOutgoingMessage(message) {
await database.transaction((tx) => {
- tx.executeSql(
- `INSERT INTO message_db
+ tx.executeSql(
+ `INSERT INTO message_db
(conversation, type, message, timestamp, read)
VALUES
(?, ?, ?, ?, ?)`,
- [
- message.to,
- 'sent',
- message.msg,
- message.t,
- true
- ]
- );
+ [
+ message.to,
+ 'sent',
+ message.msg,
+ message.t,
+ true
+ ]
+ );
});
}
@@ -973,7 +973,7 @@ export async function saveOutgoingMessage(message) {
export async function markConversationAsRead(conversation) {
await database.transaction((tx) => {
- tx.executeSql(
+ tx.executeSql(
`UPDATE
message_db
SET
@@ -983,19 +983,19 @@ export async function markConversationAsRead(conversation) {
[
conversation
],
- );
+ );
-});
+ });
-Globals.unreadMessages = await getUnreadMessages();
-Globals.updateMessages()
+ Globals.unreadMessages = await getUnreadMessages();
+ Globals.updateMessages()
}
export async function markGroupConversationAsRead(group) {
await database.transaction((tx) => {
- tx.executeSql(
+ tx.executeSql(
`UPDATE
privateboards_messages_db
SET
@@ -1005,12 +1005,12 @@ export async function markGroupConversationAsRead(group) {
[
group
],
- );
+ );
-});
+ });
-Globals.unreadMessages = await getUnreadMessages();
-Globals.updateGroups();
+ Globals.unreadMessages = await getUnreadMessages();
+ Globals.updateGroups();
}
@@ -1020,7 +1020,7 @@ export async function markBoardsMessageAsRead(hash) {
console.log('Marking ' + hash + ' as read.');
await database.transaction((tx) => {
- tx.executeSql(
+ tx.executeSql(
`UPDATE
boards_message_db
SET
@@ -1030,270 +1030,270 @@ export async function markBoardsMessageAsRead(hash) {
[
hash
],
- );
+ );
-});
+ });
-Globals.unreadMessages = await getUnreadMessages();
+ Globals.unreadMessages = await getUnreadMessages();
}
export async function savePayeeToDatabase(payee) {
- await database.transaction((tx) => {
- tx.executeSql(
- `INSERT INTO payees
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `INSERT INTO payees
(nickname, address, paymentid)
VALUES
(?, ?, ?)`,
- [
- payee.nickname,
- payee.address,
- payee.paymentID,
- ]
- );
- });
+ [
+ payee.nickname,
+ payee.address,
+ payee.paymentID,
+ ]
+ );
+ });
}
export async function removePayeeFromDatabase(nickname, removeMessages) {
- await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `DELETE FROM
payees
WHERE
nickname = ?`,
- [ nickname ]
- );
- });
- if (removeMessages) {
- //console.log('Removing messages for', address);
+ [nickname]
+ );
+ });
+ if (removeMessages) {
+ //console.log('Removing messages for', address);
await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM
+ tx.executeSql(
+ `DELETE FROM
message_db
WHERE
conversation = ?`,
- [ address ]
- );
+ [address]
+ );
})
}
}
export async function saveGroupToDatabase(group) {
- await database.transaction((tx) => {
- tx.executeSql(
- `INSERT INTO privateboards
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `INSERT INTO privateboards
(name, key, latestmessage)
VALUES
(?, ?, ?)`,
- [ group.group, group.key, Date.now() ]
- );
- });
+ [group.group, group.key, Date.now()]
+ );
+ });
}
export async function removeGroupFromDatabase(key, removeMessages) {
- await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `DELETE FROM
privateboards
WHERE
key = ?`,
- [ key ]
- );
- });
- if (removeMessages) {
- //console.log('Removing messages for', address);
+ [key]
+ );
+ });
+ if (removeMessages) {
+ //console.log('Removing messages for', address);
await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM
+ tx.executeSql(
+ `DELETE FROM
privateboards_messages_db
WHERE
board = ?`,
- [ key ]
- );
+ [key]
+ );
})
}
}
export async function removeMessages() {
- await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM message_db`
- );
- });
- await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM payees`
- );
- });
- await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM boards_message_db`
- );
- });
- await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM boards_subscriptions`
- );
- });
- await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM privateboards_message_db`
- );
- });
- await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM privateboards`
- );
- });
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `DELETE FROM message_db`
+ );
+ });
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `DELETE FROM payees`
+ );
+ });
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `DELETE FROM boards_message_db`
+ );
+ });
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `DELETE FROM boards_subscriptions`
+ );
+ });
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `DELETE FROM privateboards_message_db`
+ );
+ });
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `DELETE FROM privateboards`
+ );
+ });
}
export async function getGroupKey(group) {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
key
FROM
privateboards
WHERE
name = ${group}`
- );
-
- if (data && data.rows && data.rows.length) {
+ );
- const res = [];
- const payees = data.rows.raw();
+ if (data && data.rows && data.rows.length) {
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
+ const res = [];
+ const payees = data.rows.raw();
- if (item.key) {
- return item.key;
- } else {
- return false;
- }
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ if (item.key) {
+ return item.key;
+ } else {
+ return false;
+ }
- }
- } else {
- return false;
}
+
+ } else {
+ return false;
+ }
}
export async function getGroupName(key) {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
*
FROM
privateboards
WHERE
key = "${key}"`
- );
+ );
- if (data && data.rows && data.rows.length) {
+ if (data && data.rows && data.rows.length) {
- const res = [];
+ const res = [];
- for (let i = 0; i < data.rows.length; i++) {
-
- const item = data.rows.item(i);
- console.log(item);
- if (item.name) {
- return item.name;
- } else {
- return false;
- }
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ console.log(item);
+ if (item.name) {
+ return item.name;
+ } else {
+ return false;
+ }
- }
- } else {
- return false;
}
+
+ } else {
+ return false;
+ }
}
export async function loadGroupsDataFromDatabase() {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
name,
key,
latestmessage
FROM
privateboards`
- );
-
- if (data && data.rows && data.rows.length) {
-
- const res = [];
- const groups = data.rows.raw();
-
- let latestMessages = await getLatestGroupMessages();
- let unreads = await getUnreadsPerGroup();
+ );
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
- const latestMessage = latestMessages.filter(m => m.group == item.key);
- res.push({
- group: item.name,
- key: item.key,
- lastMessage: latestMessage.length ? latestMessage[0].message : false,
- lastMessageNickname: latestMessage.length ? latestMessage[0].nickname : false,
- lastMessageTimestamp: latestMessage.length ? latestMessage[0].timestamp : 0,
- read: latestMessage.length ? latestMessage[0].read : true,
- unreads: unreads[item.key]
- })
+ if (data && data.rows && data.rows.length) {
- }
+ const res = [];
+ const groups = data.rows.raw();
+
+ let latestMessages = await getLatestGroupMessages();
+ let unreads = await getUnreadsPerGroup();
+
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ const latestMessage = latestMessages.filter(m => m.group == item.key);
+ res.push({
+ group: item.name,
+ key: item.key,
+ lastMessage: latestMessage.length ? latestMessage[0].message : false,
+ lastMessageNickname: latestMessage.length ? latestMessage[0].nickname : false,
+ lastMessageTimestamp: latestMessage.length ? latestMessage[0].timestamp : 0,
+ read: latestMessage.length ? latestMessage[0].read : true,
+ unreads: unreads[item.key]
+ })
- return res.sort((a, b) => b.lastMessageTimestamp - a.lastMessageTimestamp)
}
+ return res.sort((a, b) => b.lastMessageTimestamp - a.lastMessageTimestamp)
+ }
- return [];
+
+ return [];
}
export async function loadPayeeDataFromDatabase() {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
nickname,
address,
paymentid
FROM
payees`
- );
-
- if (data && data.rows && data.rows.length) {
-
- const res = [];
- const payees = data.rows.raw();
-
- let latestMessages = await getLatestMessages();
- let unreads = await getUnreadsPerRecipient();
-
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
- const latestMessage = latestMessages.filter(m => m.conversation == item.address);
+ );
- res.push({
- nickname: item.nickname,
- address: item.address,
- paymentID: item.paymentid,
- lastMessage: latestMessage.length && item.paymentid ? latestMessage[0].message : false,
- lastMessageTimestamp: latestMessage.length && item.paymentid ? latestMessage[0].timestamp : 0,
- read: latestMessage.length && item.paymentid ? latestMessage[0].read : true,
- unreads: unreads[item.address]
- })
- }
+ if (data && data.rows && data.rows.length) {
- return res.sort((a, b) => b.lastMessageTimestamp - a.lastMessageTimestamp)
+ const res = [];
+ const payees = data.rows.raw();
+
+ let latestMessages = await getLatestMessages();
+ let unreads = await getUnreadsPerRecipient();
+
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ const latestMessage = latestMessages.filter(m => m.conversation == item.address);
+
+ res.push({
+ nickname: item.nickname,
+ address: item.address,
+ paymentID: item.paymentid,
+ lastMessage: latestMessage.length && item.paymentid ? latestMessage[0].message : false,
+ lastMessageTimestamp: latestMessage.length && item.paymentid ? latestMessage[0].timestamp : 0,
+ read: latestMessage.length && item.paymentid ? latestMessage[0].read : true,
+ unreads: unreads[item.address]
+ })
}
- return undefined;
+ return res.sort((a, b) => b.lastMessageTimestamp - a.lastMessageTimestamp)
+ }
+
+ return undefined;
}
export async function getLatestGroupMessages() {
- const [data] = await database.executeSql(
- `
+ const [data] = await database.executeSql(
+ `
SELECT *
FROM privateboards_messages_db D
WHERE timestamp = (SELECT MAX(timestamp) FROM privateboards_messages_db WHERE board = D.board AND reply = '')
@@ -1302,32 +1302,32 @@ export async function getLatestGroupMessages() {
ASC
`);
- if (data && data.rows && data.rows.length) {
- const res = [];
-
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
- res.push({
- group: item.board,
- nickname: item.nickname,
- message: item.message,
- timestamp: item.timestamp,
- read: item.read,
- reply: item.reply,
- hash: item.hash,
-
- });
- }
- console.log(res);
- return res;
+ if (data && data.rows && data.rows.length) {
+ const res = [];
+
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ res.push({
+ group: item.board,
+ nickname: item.nickname,
+ message: item.message,
+ timestamp: item.timestamp,
+ read: item.read,
+ reply: item.reply,
+ hash: item.hash,
+
+ });
}
+ console.log(res);
+ return res;
+ }
- return [];
+ return [];
}
export async function getLatestMessages() {
- const [data] = await database.executeSql(
- `
+ const [data] = await database.executeSql(
+ `
SELECT *
FROM message_db D
WHERE timestamp = (SELECT MAX(timestamp) FROM message_db WHERE conversation = D.conversation)
@@ -1336,30 +1336,30 @@ export async function getLatestMessages() {
ASC
`);
- if (data && data.rows && data.rows.length) {
- const res = [];
-
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
- res.push({
- conversation: item.conversation,
- type: item.type,
- message: item.message,
- timestamp: item.timestamp,
- read: item.read
- });
- }
-
- return res;
+ if (data && data.rows && data.rows.length) {
+ const res = [];
+
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ res.push({
+ conversation: item.conversation,
+ type: item.type,
+ message: item.message,
+ timestamp: item.timestamp,
+ read: item.read
+ });
}
- return [];
+ return res;
+ }
+
+ return [];
}
-export async function getMessages(conversation=false, limit=25) {
+export async function getMessages(conversation = false, limit = 25) {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
conversation,
type,
message,
@@ -1371,94 +1371,118 @@ export async function getMessages(conversation=false, limit=25) {
timestamp
DESC
LIMIT ${limit}`
- );
+ );
- const [count] = await database.executeSql(
- `
+ const [count] = await database.executeSql(
+ `
SELECT COUNT(*) FROM message_db ${conversation ? 'WHERE conversation = "' + conversation + '"' : ''}
`
- );
-
- let count_raw = 0;
-
- if (count && count.rows && count.rows.length) {
- console.log(count);
- const res = [];
+ );
- for (let i = 0; i < count.rows.length; i++) {
+ let count_raw = 0;
- const item = count.rows.item(i);
+ if (count && count.rows && count.rows.length) {
+ console.log(count);
+ const res = [];
- count_raw = item['COUNT(*)'];
+ for (let i = 0; i < count.rows.length; i++) {
- }
- };
+ const item = count.rows.item(i);
- if (data && data.rows && data.rows.length) {
+ count_raw = item['COUNT(*)'];
- const res = [];
+ }
+ };
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
- res.push({
- conversation: item.conversation,
- type: item.type,
- message: item.message,
- timestamp: item.timestamp,
- count: count_raw
- });
- }
+ if (data && data.rows && data.rows.length) {
- return res.reverse();
+ const res = [];
+
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ res.push({
+ conversation: item.conversation,
+ type: item.type,
+ message: item.message,
+ timestamp: item.timestamp,
+ count: count_raw
+ });
}
- return undefined;
+ return res.reverse();
+ }
+
+ return undefined;
}
-export async function getGroupMessages(group=false, limit=25) {
+export async function getGroupMessages(group = false, limit = 25) {
- const stack = new Error().stack;
- const callerInfo = stack.split('\n');
+ const stack = new Error().stack;
+ const callerInfo = stack.split('\n');
- if (limit < 25) limit = 25;
+ if (limit < 25) limit = 25;
- const starttime = Date.now();
+ const starttime = Date.now();
- const [data] = await database.executeSql(
- `
- SELECT
+ const [data] = await database.executeSql(
+ `
+ SELECT
*
- FROM
+ FROM
privateboards_messages_db
${group ? 'WHERE board = "' + group + '"' : ''}
- ORDER BY
+ ORDER BY
timestamp DESC
LIMIT ${limit}`
- );
+ );
- const [count] = await database.executeSql(
- `
+ const [count] = await database.executeSql(
+ `
SELECT COUNT(*) FROM privateboards_messages_db ${group ? ' WHERE board = "' + group + '"' : ''}
`
- );
+ );
- let count_raw = 0;
+ let count_raw = 0;
- if (count && count.rows && count.rows.length) {
+ if (count && count.rows && count.rows.length) {
- const res = [];
+ const res = [];
- for (let i = 0; i < count.rows.length; i++) {
+ for (let i = 0; i < count.rows.length; i++) {
- const item = count.rows.item(i);
+ const item = count.rows.item(i);
- count_raw = item['COUNT(*)'];
+ count_raw = item['COUNT(*)'];
- }
- };
+ }
+ };
- if (data && data.rows && data.rows.length) {
- const res = [];
+ if (data && data.rows && data.rows.length) {
+ const res = [];
+
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+
+ thisMessage = {
+ nickname: item.nickname,
+ type: item.type,
+ message: item.message,
+ timestamp: item.timestamp,
+ group: item.board,
+ address: item.address,
+ hash: item.hash,
+ reply: item.reply,
+ replies: item.replies,
+ count: count_raw,
+ };
+
+ if (thisMessage.reply != '') {
+ const thisOP = await getGroupsMessage(thisMessage.reply);
+ if (thisOP) {
+ thisMessage.replyNickname = thisOP.nickname;
+ thisMessage.replyMessage = thisOP.message;
+ }
+ }
for (let i = 0; i < data.rows.length; i++) {
const item = data.rows.item(i);
@@ -1488,20 +1512,20 @@ export async function getGroupMessages(group=false, limit=25) {
res.push(thisMessage);
- }
- console.log(res);
- return res.reverse();
- } else {
- console.log('No message le found!');
}
+ console.log(res);
+ return res.reverse();
+ } else {
+ console.log('No message le found!');
+ }
- return [];
+ return [];
}
export async function getHistory(conversation) {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
conversation,
type,
message,
@@ -1515,16 +1539,16 @@ export async function getHistory(conversation) {
DESC
LIMIT
1`
- );
+ );
- if (data && data.rows && data.rows.length) {
- if (( Date.now() - data.rows.item(0).timestamp ) > 24*60*60*1000 ) {
- return false; // Return false if latest message is more than 24h old, because we want to renew contactability
- }
- return true;
- } else {
- return false;
+ if (data && data.rows && data.rows.length) {
+ if ((Date.now() - data.rows.item(0).timestamp) > 24 * 60 * 60 * 1000) {
+ return false; // Return false if latest message is more than 24h old, because we want to renew contactability
}
+ return true;
+ } else {
+ return false;
+ }
}
@@ -1536,8 +1560,8 @@ export async function getReplies(post) {
return [];
}
- const [data] = await database.executeSql(
- `SELECT *
+ const [data] = await database.executeSql(
+ `SELECT *
FROM
privateboards_messages_db WHERE reply = "${post}"
ORDER BY
@@ -1545,27 +1569,27 @@ export async function getReplies(post) {
ASC
LIMIT
20`
- );
-
- console.log('Got ' + data.rows.length + " board messages");
- if (data && data.rows && data.rows.length) {
- const res = [];
+ );
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
- console.log(item);
- res.push({
- message: item.message,
- address: item.address,
- board: item.board,
- timestamp: item.timestamp,
- nickname: item.nickname,
- reply: item.reply,
- type: item.type,
- read: item.read
- });
- const [reply_data] = await database.executeSql(
- `SELECT *
+ console.log('Got ' + data.rows.length + " board messages");
+ if (data && data.rows && data.rows.length) {
+ const res = [];
+
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ console.log(item);
+ res.push({
+ message: item.message,
+ address: item.address,
+ board: item.board,
+ timestamp: item.timestamp,
+ nickname: item.nickname,
+ reply: item.reply,
+ type: item.type,
+ read: item.read
+ });
+ const [reply_data] = await database.executeSql(
+ `SELECT *
FROM
privateboards_messages_db WHERE reply = "${item.hash}"
ORDER BY
@@ -1573,41 +1597,41 @@ export async function getReplies(post) {
ASC
LIMIT
20`
- );
-
- // Secondary replies ("replies on replies")
- if (reply_data && reply_data.rows && reply_data.rows.length) {
- const res = [];
-
- for (let i = 0; i < reply_data.rows.length; i++) {
-
- const item = reply_data.rows.item(i);
- res.push({
- message: item.message,
- address: item.address,
- board: item.board,
- timestamp: item.timestamp,
- nickname: item.nickname,
- reply: item.reply,
- type: item.type,
- read: item.read
- });
+ );
- }
- }
+ // Secondary replies ("replies on replies")
+ if (reply_data && reply_data.rows && reply_data.rows.length) {
+ const res = [];
+
+ for (let i = 0; i < reply_data.rows.length; i++) {
+
+ const item = reply_data.rows.item(i);
+ res.push({
+ message: item.message,
+ address: item.address,
+ board: item.board,
+ timestamp: item.timestamp,
+ nickname: item.nickname,
+ reply: item.reply,
+ type: item.type,
+ read: item.read
+ });
}
+ }
- return res;
}
- return [];
+ return res;
+ }
+
+ return [];
}
-export async function getBoardsMessages(board='Home') {
+export async function getBoardsMessages(board = 'Home') {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
message,
address,
signature,
@@ -1625,73 +1649,73 @@ export async function getBoardsMessages(board='Home') {
DESC
LIMIT
20`
- );
- console.log('Got ' + data.rows.length + " board messages");
- if (data && data.rows && data.rows.length) {
- const res = [];
-
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
- console.log(item);
-
- let json = {
- message: item.message,
- address: item.address,
- signature: item.signature,
- board: item.board,
- timestamp: item.timestamp,
- nickname: item.nickname,
- reply: item.reply,
- hash: item.hash,
- sent: item.sent,
- read: item.read
- };
-
- if (item.reply && item.reply != '0') {
- const reply = await getBoardsMessage(item.reply);
- if (reply.length != 0) {
- json.op = reply[0];
- } else {
- json.op = {nickname: 'Unknown'}
- }
-
- }
-
- res.push(json);
+ );
+ console.log('Got ' + data.rows.length + " board messages");
+ if (data && data.rows && data.rows.length) {
+ const res = [];
+
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ console.log(item);
+
+ let json = {
+ message: item.message,
+ address: item.address,
+ signature: item.signature,
+ board: item.board,
+ timestamp: item.timestamp,
+ nickname: item.nickname,
+ reply: item.reply,
+ hash: item.hash,
+ sent: item.sent,
+ read: item.read
+ };
+
+ if (item.reply && item.reply != '0') {
+ const reply = await getBoardsMessage(item.reply);
+ if (reply.length != 0) {
+ json.op = reply[0];
+ } else {
+ json.op = { nickname: 'Unknown' }
}
- return res;
+ }
+
+ res.push(json);
}
- return [];
+ return res;
+ }
+
+ return [];
}
export async function getGroupsMessage(hash) {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
*
FROM
privateboards_messages_db WHERE hash = '${hash}'`
- );
-
- if (data && data.rows && data.rows.length) {
- const res = [];
+ );
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
- return item;
- }
+ if (data && data.rows && data.rows.length) {
+ const res = [];
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ return item;
}
- return false;
+ }
+
+ return false;
}
export async function getBoardRecommendations() {
- const [data] = await database.executeSql(
- `
+ const [data] = await database.executeSql(
+ `
SELECT board, COUNT(*) as count
FROM boards_message_db
WHERE board is not null AND board is not 'Home' AND board is not '' AND board not in (select board from boards_subscriptions)
@@ -1702,31 +1726,31 @@ export async function getBoardRecommendations() {
LIMIT
20
`
- );
-
- console.log('Got ' + data.rows.length + " board messages");
- if (data && data.rows && data.rows.length) {
- const res = [];
-
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
- console.log(item);
- res.push({
- board: item.board,
- count: item.count
- });
- }
+ );
- return res;
+ console.log('Got ' + data.rows.length + " board messages");
+ if (data && data.rows && data.rows.length) {
+ const res = [];
+
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ console.log(item);
+ res.push({
+ board: item.board,
+ count: item.count
+ });
}
- return [];
+ return res;
+ }
+
+ return [];
}
async function getUnreadBoardMessages(board) {
const [data] = await database.executeSql(
- `
+ `
SELECT COUNT(*)
FROM boards_message_db
WHERE
@@ -1747,7 +1771,7 @@ export async function getUnreadMessages() {
let unread_messages = {};
const [data_groups] = await database.executeSql(
- `
+ `
SELECT COUNT(*)
FROM privateboards_messages_db
WHERE
@@ -1760,7 +1784,7 @@ export async function getUnreadMessages() {
}
const [data_pms] = await database.executeSql(
- `
+ `
SELECT COUNT(*)
FROM message_db
WHERE
@@ -1779,80 +1803,80 @@ export async function getUnreadMessages() {
export async function getUnreadsPerGroup() {
- console.log('Getting unreads grouped..');
-
- let unread_messages = {};
+ console.log('Getting unreads grouped..');
- const [data_groups] = await database.executeSql(
- `
+ let unread_messages = {};
+
+ const [data_groups] = await database.executeSql(
+ `
SELECT board, COUNT(*)
FROM privateboards_messages_db
WHERE read != "1"
GROUP BY board;
`
- );
+ );
- console.log(data_groups);
+ console.log(data_groups);
- const unreads = {};
+ const unreads = {};
-
-
- if (data_groups && data_groups.rows && data_groups.rows.length) {
- for (let i = 0; i < data_groups.rows.length; i++) {
- const item = data_groups.rows.item(i);
- console.log(item);
- unreads[item.board] = item['COUNT(*)'];
+ if (data_groups && data_groups.rows && data_groups.rows.length) {
+
+ for (let i = 0; i < data_groups.rows.length; i++) {
+
+ const item = data_groups.rows.item(i);
+ console.log(item);
+ unreads[item.board] = item['COUNT(*)'];
- }
}
-
- return unreads;
-
}
- export async function getUnreadsPerRecipient() {
+ return unreads;
- console.log('Getting unreads for recipients..');
+}
- let unread_messages = {};
+export async function getUnreadsPerRecipient() {
- const [data_unreads] = await database.executeSql(
- `
+ console.log('Getting unreads for recipients..');
+
+ let unread_messages = {};
+
+ const [data_unreads] = await database.executeSql(
+ `
SELECT conversation, COUNT(*)
FROM message_db
WHERE read != "1"
GROUP BY conversation;
`
- );
+ );
- const unreads = {};
+ const unreads = {};
- if (data_unreads && data_unreads.rows && data_unreads.rows.length) {
+ if (data_unreads && data_unreads.rows && data_unreads.rows.length) {
- for (let i = 0; i < data_unreads.rows.length; i++) {
+ for (let i = 0; i < data_unreads.rows.length; i++) {
- const item = data_unreads.rows.item(i);
- console.log(item);
- unreads[item.conversation] = item['COUNT(*)'];
+ const item = data_unreads.rows.item(i);
+ console.log(item);
+ unreads[item.conversation] = item['COUNT(*)'];
- }
}
+ }
- return unreads;
+ return unreads;
+
+}
- }
-
export async function getBoardSubscriptions() {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
board,
key,
latest_message
@@ -1862,59 +1886,59 @@ export async function getBoardSubscriptions() {
latest_message
DESC
`
- );
- console.log('Got ' + data.rows.length + " board messages");
- if (data && data.rows && data.rows.length) {
- const res = [];
-
- for (let i = 0; i < data.rows.length; i++) {
+ );
+ console.log('Got ' + data.rows.length + " board messages");
+ if (data && data.rows && data.rows.length) {
+ const res = [];
- const item = data.rows.item(i);
+ for (let i = 0; i < data.rows.length; i++) {
- const unread_messages = await getUnreadBoardMessages(item.board);
+ const item = data.rows.item(i);
- res.push({
- board: item.board,
- key: item.key,
- unread: unread_messages
- });
- }
- console.log(res);
- return res;
+ const unread_messages = await getUnreadBoardMessages(item.board);
+ res.push({
+ board: item.board,
+ key: item.key,
+ unread: unread_messages
+ });
}
+ console.log(res);
+ return res;
- return [];
+ }
+
+ return [];
}
export async function subscribeToBoard(board, key) {
- await database.transaction((tx) => {
- tx.executeSql(
- `REPLACE INTO boards_subscriptions
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `REPLACE INTO boards_subscriptions
(board, key)
VALUES
(?, ?)`,
- [
- board,
- key
- ]
- );
- });
+ [
+ board,
+ key
+ ]
+ );
+ });
}
export async function subscribeToGroup(group, key) {
- await database.transaction((tx) => {
- tx.executeSql(
- `REPLACE INTO privateboards
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `REPLACE INTO privateboards
(name, key)
VALUES
(?, ?)`,
- [group, key]
- );
- });
+ [group, key]
+ );
+ });
}
@@ -1922,21 +1946,21 @@ export async function removeBoard(board) {
await database.transaction((tx) => {
- tx.executeSql(
- `DELETE FROM
+ tx.executeSql(
+ `DELETE FROM
boards_subscriptions
WHERE
board = ?`,
- [ board ]
- );
+ [board]
+ );
});
}
export async function getLatestGroupMessage() {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
timestamp
FROM
privateboards_messages_db
@@ -1945,26 +1969,26 @@ export async function getLatestGroupMessage() {
DESC
LIMIT
1`
- );
-
- let timestamp = 0;
- if (data && data.rows && data.rows.length) {
+ );
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
- timestamp = item.timestamp;
- return timestamp;
- }
+ let timestamp = 0;
+ if (data && data.rows && data.rows.length) {
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ timestamp = item.timestamp;
+ return timestamp;
}
- return timestamp;
+
+ }
+ return timestamp;
}
export async function getLatestMessage() {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
timestamp
FROM
message_db
@@ -1973,25 +1997,25 @@ export async function getLatestMessage() {
DESC
LIMIT
1`
- );
-
- let timestamp = 0;
- if (data && data.rows && data.rows.length) {
+ );
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
- timestamp = item.timestamp;
- return timestamp;
- }
+ let timestamp = 0;
+ if (data && data.rows && data.rows.length) {
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ timestamp = item.timestamp;
+ return timestamp;
}
- return timestamp;
+
+ }
+ return timestamp;
}
export async function messageExists(timestamp) {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
conversation,
type,
message,
@@ -2001,18 +2025,18 @@ export async function messageExists(timestamp) {
WHERE
timestamp = ${timestamp}
`
- );
- if (data && data.rows && data.rows.length) {
- return true;
- } else {
- return false;
- }
+ );
+ if (data && data.rows && data.rows.length) {
+ return true;
+ } else {
+ return false;
+ }
}
export async function groupMessageExists(timestamp) {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
board,
type,
message,
@@ -2022,108 +2046,108 @@ export async function groupMessageExists(timestamp) {
WHERE
timestamp = ${timestamp}
`
- );
- if (data && data.rows && data.rows.length) {
- return true;
- } else {
- return false;
- }
+ );
+ if (data && data.rows && data.rows.length) {
+ return true;
+ } else {
+ return false;
+ }
}
export async function boardsMessageExists(hash) {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
timestamp
FROM
boards_message_db
WHERE
hash = ?
`, [hash]
- );
- if (data && data.rows && data.rows.length) {
- return true;
- } else {
- return false;
- }
+ );
+ if (data && data.rows && data.rows.length) {
+ return true;
+ } else {
+ return false;
+ }
}
export async function saveToDatabase(wallet) {
- try {
- await saveWallet(wallet.toJSONString());
- await setHaveWallet(true);
- } catch (err) {
- Globals.logger.addLogMessage('Err saving wallet: ' + err);
- };
+ try {
+ await saveWallet(wallet.toJSONString());
+ await setHaveWallet(true);
+ } catch (err) {
+ Globals.logger.addLogMessage('Err saving wallet: ' + err);
+ };
}
export async function haveWallet() {
- try {
- const value = await AsyncStorage.getItem(Config.coinName + 'HaveWallet');
-
- if (value !== null) {
- return value === 'true';
- }
+ try {
+ const value = await AsyncStorage.getItem(Config.coinName + 'HaveWallet');
- return false;
- } catch (error) {
- Globals.logger.addLogMessage('Error determining if we have data: ' + error);
- return false;
+ if (value !== null) {
+ return value === 'true';
}
+
+ return false;
+ } catch (error) {
+ Globals.logger.addLogMessage('Error determining if we have data: ' + error);
+ return false;
+ }
}
export async function setHaveWallet(haveWallet) {
- try {
- await AsyncStorage.setItem(Config.coinName + 'HaveWallet', haveWallet.toString());
- } catch (error) {
- Globals.logger.addLogMessage('Failed to save have wallet status: ' + error);
- }
+ try {
+ await AsyncStorage.setItem(Config.coinName + 'HaveWallet', haveWallet.toString());
+ } catch (error) {
+ Globals.logger.addLogMessage('Failed to save have wallet status: ' + error);
+ }
}
export async function saveTransactionDetailsToDatabase(txDetails) {
- await database.transaction((tx) => {
- tx.executeSql(
- `INSERT INTO transactiondetails
+ await database.transaction((tx) => {
+ tx.executeSql(
+ `INSERT INTO transactiondetails
(hash, memo, address, payee)
VALUES
(?, ?, ?, ?)`,
- [
- txDetails.hash,
- txDetails.memo,
- txDetails.address,
- txDetails.payee
- ]
- );
- });
+ [
+ txDetails.hash,
+ txDetails.memo,
+ txDetails.address,
+ txDetails.payee
+ ]
+ );
+ });
}
export async function loadTransactionDetailsFromDatabase() {
- const [data] = await database.executeSql(
- `SELECT
+ const [data] = await database.executeSql(
+ `SELECT
hash,
memo,
address,
payee
FROM
transactiondetails`
- );
-
- if (data && data.rows && data.rows.length) {
- const res = [];
-
- for (let i = 0; i < data.rows.length; i++) {
- const item = data.rows.item(i);
- res.push({
- hash: item.hash,
- memo: item.memo,
- address: item.address,
- payee: item.payee,
- });
- }
+ );
- return res;
+ if (data && data.rows && data.rows.length) {
+ const res = [];
+
+ for (let i = 0; i < data.rows.length; i++) {
+ const item = data.rows.item(i);
+ res.push({
+ hash: item.hash,
+ memo: item.memo,
+ address: item.address,
+ payee: item.payee,
+ });
}
- return undefined;
+ return res;
+ }
+
+ return undefined;
}
diff --git a/src/DisclaimerScreen.js b/src/DisclaimerScreen.js
index 4750c4d..c71bbe4 100644
--- a/src/DisclaimerScreen.js
+++ b/src/DisclaimerScreen.js
@@ -8,135 +8,134 @@ import { View, Text, Switch } from 'react-native';
import Config from './Config';
-import { Styles } from './Styles';
import { BottomButton } from './SharedComponents';
import './i18n.js';
import { withTranslation } from 'react-i18next';
class DisclaimerScreenNoTranslation extends React.Component {
- static navigationOptions = {
- title: '',
- };
-
- constructor(props) {
- super(props);
-
- this.state = {
- feeAccepted: Config.devFeePercentage > 0 ? false : true,
- keyOwnershipAccepted: false,
- warrantyAccepted: false,
- }
- }
+ static navigationOptions = {
+ title: '',
+ };
+
+ constructor(props) {
+ super(props);
- confirm() {
- this.props.navigation.navigate('WalletOption');
+ this.state = {
+ feeAccepted: Config.devFeePercentage > 0 ? false : true,
+ keyOwnershipAccepted: false,
+ warrantyAccepted: false,
}
+ }
+
+ confirm() {
+ this.props.navigation.navigate('WalletOption');
+ }
+
+ render() {
+ const { t } = this.props;
+ return (
+
+
+
+ {t('disclaimer')}
+
+
+ {Config.devFeePercentage > 0 &&
+ {
+ this.setState({
+ feeAccepted: value
+ });
+ }}
+ style={{ marginRight: 15 }}
+ />
+
+
+
+ I understand that the fee for sending transactions is {Config.devFeePercentage}%.
+
+
+ }
+
+
+ {
+ this.setState({
+ keyOwnershipAccepted: value
+ });
+ }}
+ style={{ marginRight: 15 }}
+ />
+
+
+
+ {t('privateKeyWarning')}
+
+
- render() {
- const { t } = this.props;
- return(
-
-
-
- {t('disclaimer')}
-
-
- {Config.devFeePercentage > 0 &&
- {
- this.setState({
- feeAccepted: value
- });
- }}
- style={{ marginRight: 15 }}
- />
-
-
-
- I understand that the fee for sending transactions is {Config.devFeePercentage}%.
-
-
- }
-
-
- {
- this.setState({
- keyOwnershipAccepted: value
- });
- }}
- style={{ marginRight: 15 }}
- />
-
-
-
- {t('privateKeyWarning')}
-
-
-
-
-
-
- {
- this.setState({
- warrantyAccepted: value
- });
- }}
- style={{ marginRight: 15 }}
- />
-
-
-
- {t('warrantyWarning')}
-
-
-
-
-
- {
- this.props.navigation.navigate('ChooseAuthMethod', { nextRoute: this.props.navigation.state.params.nextRoute })
- }}
- disabled={!this.state.feeAccepted || !this.state.keyOwnershipAccepted || !this.state.warrantyAccepted}
- {...this.props}
- />
-
+
+
+
+ {
+ this.setState({
+ warrantyAccepted: value
+ });
+ }}
+ style={{ marginRight: 15 }}
+ />
+
+
+
+ {t('warrantyWarning')}
+
- );
- }
+
+
+
+ {
+ this.props.navigation.navigate('ChooseAuthMethod', { nextRoute: this.props.navigation.state.params.nextRoute })
+ }}
+ disabled={!this.state.feeAccepted || !this.state.keyOwnershipAccepted || !this.state.warrantyAccepted}
+ {...this.props}
+ />
+
+
+ );
+ }
}
export const DisclaimerScreen = withTranslation()(DisclaimerScreenNoTranslation)
diff --git a/src/Globals.js b/src/Globals.js
index 8b017b9..836eae9 100644
--- a/src/Globals.js
+++ b/src/Globals.js
@@ -18,7 +18,6 @@ import { getLastSync, setHaveWallet, openDB, deleteDB, getKnownTransactions, get
loadTransactionDetailsFromDatabase, saveTransactionDetailsToDatabase, removeGroupFromDatabase, getMessages, getLatestMessages, getBoardsMessages, getBoardSubscriptions, loadGroupsDataFromDatabase } from './Database';
import Config from './Config';
import { Logger } from './Logger';
-import { getCoinPriceFromAPI } from './Currency';
import { makePostRequest } from './NativeCode';
import { getMessage, sendNotifications, resyncMessage24h } from './HuginUtilities';
import offline_node_list from './nodes.json';
@@ -26,424 +25,421 @@ import offline_cache_list from './nodes.json';
import offline_groups_list from './groups.json';
class globals {
- constructor() {
- /* Can't really pass wallet between tab screens, and need it everywhere */
- this.wallet = undefined;
+ constructor() {
+ /* Can't really pass wallet between tab screens, and need it everywhere */
+ this.wallet = undefined;
- /* Need to be able to cancel the background saving if we make a new wallet */
- this.backgroundSaveTimer = undefined;
+ /* Need to be able to cancel the background saving if we make a new wallet */
+ this.backgroundSaveTimer = undefined;
- /* Want to cache this so we don't have to keep loading from DB/internet */
- this.coinPrice = 0;
+ /* Want to cache this so we don't have to keep loading from DB/internet */
+ this.coinPrice = 0;
- this.syncingMessages = false;
+ this.syncingMessages = false;
- this.syncingMessagesCount = 0;
+ this.syncingMessagesCount = 0;
- this.syncSkips = 0;
+ this.syncSkips = 0;
- /* Preferences loaded from DB */
- this.preferences = {
- currency: 'usd',
- notificationsEnabled: true,
- scanCoinbaseTransactions: false,
- limitData: false,
- theme: 'darkMode',
- authConfirmation: false,
- autoOptimize: false,
- authenticationMethod: 'hardware-auth',
- node: Config.defaultDaemon.getConnectionString(),
- language: 'en',
- cache: Config.defaultCache,
- cacheEnabled: 'true',
- autoPickCache: 'true',
- websocketEnabled: 'true',
- nickname: 'Anonymous'
- };
+ /* Preferences loaded from DB */
+ this.preferences = {
+ currency: 'usd',
+ notificationsEnabled: true,
+ scanCoinbaseTransactions: false,
+ limitData: false,
+ theme: 'darkMode',
+ authConfirmation: false,
+ autoOptimize: false,
+ authenticationMethod: 'hardware-auth',
+ node: Config.defaultDaemon.getConnectionString(),
+ language: 'en',
+ cache: Config.defaultCache,
+ cacheEnabled: 'true',
+ autoPickCache: 'true',
+ websocketEnabled: 'true',
+ nickname: 'Anonymous'
+ };
- /* People in our address book */
- this.payees = [];
+ /* People in our address book */
+ this.payees = [];
- this.groups = [];
+ this.groups = [];
- this.logger = new Logger();
+ this.logger = new Logger();
- this.updatePayeeFunctions = [];
+ this.updatePayeeFunctions = [];
- this.updateGroupsFunctions = [];
+ this.updateGroupsFunctions = [];
- this.updateChatFunctions = [];
+ this.updateChatFunctions = [];
- this.updateCallFunctions = [];
+ this.updateCallFunctions = [];
- this.updateBoardsFunctions = [];
+ this.updateBoardsFunctions = [];
- /* Mapping of tx hash to address sent, payee name, memo */
- this.transactionDetails = [];
+ /* Mapping of tx hash to address sent, payee name, memo */
+ this.transactionDetails = [];
- this.daemons = [];
+ this.daemons = [];
- this.caches = [];
+ this.caches = [];
- this.standardGroups = [];
+ this.standardGroups = [];
- this.messages = [];
+ this.messages = [];
- this.boardsMessages = [];
+ this.boardsMessages = [];
- this.groupMessages = [];
+ this.groupMessages = [];
- this.knownTXs = [];
+ this.knownTXs = [];
- this.activeChat = '';
+ this.activeChat = '';
- this.activeGroup = '';
+ this.activeGroup = '';
- this.language = 'en-US';
+ this.language = 'en-US';
- this.fromChat = false;
+ this.fromChat = false;
- this.unreadMessages = {boards: 0, groups: 0, pms: 0};
+ this.unreadMessages = { boards: 0, groups: 0, pms: 0 };
- this.sdp_answer = '';
+ this.sdp_answer = '';
- this.calls = [];
+ this.calls = [];
- this.stream = false;
+ this.stream = false;
- this.localWebcamOn = false;
-
- this.localMicOn = false;
+ this.localWebcamOn = false;
- this.speakerOn = true;
+ this.localMicOn = false;
- this.notificationQueue = [];
+ this.speakerOn = true;
- this.lastMessageTimestamp = Date.now() - (24 * 60 * 60 * 1000);
+ this.notificationQueue = [];
- this.lastDMTimestamp = Date.now() - (24 * 60 * 60 * 1000);
+ this.lastMessageTimestamp = Date.now() - (24 * 60 * 60 * 1000);
- this.webSocketStatus = 'offline';
+ this.lastDMTimestamp = Date.now() - (24 * 60 * 60 * 1000);
- this.socket = undefined;
+ this.webSocketStatus = 'offline';
- this.initalSyncOccurred = false;
+ this.socket = undefined;
- this.websockets = 0;
+ this.initalSyncOccurred = false;
- this.APIOnline;
+ this.websockets = 0;
- this.messagesLoaded = 0;
+ this.APIOnline;
- this.lastSyncEvent = Date.now();
+ this.messagesLoaded = 0;
- this.navigation = undefined;
+ this.lastSyncEvent = Date.now();
- }
+ this.navigation = undefined;
- async reset() {
- this.wallet = undefined;
- this.pinCode = undefined;
- this.backgroundSaveTimer = undefined;
- this.logger = new Logger();
- this.payees = [];
- this.groups = [];
- //removeMessages();
-
- await deleteDB();
- await openDB();
- await setHaveWallet(false);
- await deleteUserPinCode();
- Globals.initGlobals();
+ }
- }
+ async reset() {
+ this.wallet = undefined;
+ this.pinCode = undefined;
+ this.backgroundSaveTimer = undefined;
+ this.logger = new Logger();
+ this.payees = [];
+ this.groups = [];
+ //removeMessages();
- addTransactionDetails(txDetails) {
- Globals.transactionDetails.push(txDetails);
- saveTransactionDetailsToDatabase(txDetails);
- }
+ await deleteDB();
+ await openDB();
+ await setHaveWallet(false);
+ await deleteUserPinCode();
+ Globals.initGlobals();
- addPayee(payee) {
- Globals.payees.push(payee);
- savePayeeToDatabase(payee);
- this.update();
- this.updateMessages();
- }
+ }
- removePayee(nickname, removeMessages) {
- _.remove(Globals.payees, (item) => item.nickname === nickname);
- removePayeeFromDatabase(nickname, removeMessages);
- this.update();
- }
+ addTransactionDetails(txDetails) {
+ Globals.transactionDetails.push(txDetails);
+ saveTransactionDetailsToDatabase(txDetails);
+ }
- update() {
- Globals.updatePayeeFunctions.forEach((f) => {
- f();
- });
- }
+ addPayee(payee) {
+ Globals.payees.push(payee);
+ savePayeeToDatabase(payee);
+ this.update();
+ this.updateMessages();
+ }
updateGroupsFunction() {
- console.log('UPDATING GROUPS', Globals.updateGroupsFunctions.length);
- console.log('UPDATING GROUPS', Globals.updateGroupsFunctions.length);
- console.log('UPDATING GROUPS', Globals.updateGroupsFunctions);
- console.log('UPDATING GROUPS', Globals.updateGroupsFunctions);
Globals.updateGroupsFunctions.forEach((f) => {
f();
});
}
+ update() {
+ Globals.updatePayeeFunctions.forEach((f) => {
+ f();
+ });
+ }
- addGroup(group) {
- if (Globals.groups.some((g) => g.key == group.key)) {
- console.log('Group already exists!');
- return;
- }
- Globals.groups.push(group);
- saveGroupToDatabase(group);
- this.updateGroups();
- resyncMessage24h();
- }
+ updateGroupsFunction() {
+ Globals.updateGroupsFunctions.forEach((f) => {
+ f();
+ });
+ }
- async removeGroup(key, removeMessages) {
- Globals.groups = Globals.groups.filter((item) => item.key != key);
- await removeGroupFromDatabase(key, removeMessages);
- console.log('Group removed from DB');
- this.updateGroups();
+
+ addGroup(group) {
+ if (Globals.groups.some((g) => g.key == group.key)) {
+ console.log('Group already exists!');
+ return;
}
+ Globals.groups.push(group);
+ saveGroupToDatabase(group);
+ this.updateGroups();
+ resyncMessage24h();
+ }
+ async removeGroup(key, removeMessages) {
+ Globals.groups = Globals.groups.filter((item) => item.key != key);
+ await removeGroupFromDatabase(key, removeMessages);
+ console.log('Group removed from DB');
+ this.updateGroups();
+ }
- async updateGroups() {
- const groups = await loadGroupsDataFromDatabase();
+ async updateGroups() {
- if (groups !== undefined) {
- Globals.groups = groups;
- }
+ // this.groupMessages = await getGroupMessages();
+ this.updateGroupsFunction();
- // this.groupMessages = await getGroupMessages();
- this.updateGroupsFunction();
+ if (groups !== undefined) {
+ Globals.groups = groups;
+ }
- }
+ this.groupMessages = await getGroupMessages();
+ this.updateGroupsFunction();
- async updateMessages() {
- this.messages = await getMessages();
- this.updateChat();
- let payees = await loadPayeeDataFromDatabase();
+ }
- if (payees !== undefined) {
- Globals.payees = payees;
- }
-
- this.update();
+ async updateMessages() {
+ this.messages = await getMessages();
+ this.updateChat();
+ let payees = await loadPayeeDataFromDatabase();
+ if (payees !== undefined) {
+ Globals.payees = payees;
}
- async updateBoardsMessages() {
- console.log(Globals.activeBoard);
- if (Globals.activeBoard != '') {
- this.boardsMessages = await getBoardsMessages(this.activeBoard);
- } else if (Globals.activeBoard == 'Home' || Globals.activeBoard == '') {
- this.boardsMessages = await getBoardsMessages();
- }
- Globals.boardsSubscriptions = await getBoardSubscriptions();
- this.updateBoards();
+ this.update();
- }
+ }
- //
- // updateKnownTXs() {
- //
- // }
-
- updateChat() {
- console.log('updateChat');
- Globals.updateChatFunctions.forEach((f) => {
- f();
- });
+ async updateBoardsMessages() {
+ console.log(Globals.activeBoard);
+ if (Globals.activeBoard != '') {
+ this.boardsMessages = await getBoardsMessages(this.activeBoard);
+ } else if (Globals.activeBoard == 'Home' || Globals.activeBoard == '') {
+ this.boardsMessages = await getBoardsMessages();
}
-
- updateCall() {
- console.log('updateCall');
- Globals.updateCallFunctions.forEach((f) => {
- f();
- });
- }
-
- updateBoards() {
- console.log('updateChat');
- Globals.updateBoardsFunctions.forEach((f) => {
- f();
- });
+ Globals.boardsSubscriptions = await getBoardSubscriptions();
+ this.updateBoards();
+
+ }
+
+ //
+ // updateKnownTXs() {
+ //
+ // }
+
+ updateChat() {
+ console.log('updateChat');
+ Globals.updateChatFunctions.forEach((f) => {
+ f();
+ });
+ }
+
+ updateCall() {
+ console.log('updateCall');
+ Globals.updateCallFunctions.forEach((f) => {
+ f();
+ });
+ }
+
+ updateBoards() {
+ console.log('updateChat');
+ Globals.updateBoardsFunctions.forEach((f) => {
+ f();
+ });
+ }
+
+ getDaemon() {
+ const [host, port, ssl] = this.preferences.node.split(':');
+
+ let ssl_formatted = false;
+ if (ssl == 'true') {
+ ssl_formatted = true;
}
- getDaemon() {
- const [ host, port, ssl ] = this.preferences.node.split(':');
-
- let ssl_formatted = false;
- if (ssl == 'true') {
- ssl_formatted = true;
- }
-
- const daemon = new Daemon(host, Number(port), false, ssl_formatted);
+ const daemon = new Daemon(host, Number(port), false, ssl_formatted);
- if (Platform.OS === 'android') {
- /* Override with our native makePostRequest implementation which can
- actually cancel requests part way through */
- daemon.makePostRequest = makePostRequest;
- }
-
- return daemon;
+ if (Platform.OS === 'android') {
+ /* Override with our native makePostRequest implementation which can
+ actually cancel requests part way through */
+ daemon.makePostRequest = makePostRequest;
}
- async updateNodeList() {
- let i = 0;
- while (Config.nodeListURLs.length > i) {
- try {
- const data = await request({
- json: true,
- method: 'GET',
- timeout: Config.requestTimeout,
- url: Config.nodeListURLs[i],
- });
-
- if (data.nodes) {
- this.daemons = data.nodes;
- this.caches = data.apis;
- return;
- }
- } catch (error) {
- console.log(offline_node_list);
- this.logger.addLogMessage('Failed to get node list from API: ' + error.toString());
+ return daemon;
+ }
+
+ async updateNodeList() {
+ let i = 0;
+ while (Config.nodeListURLs.length > i) {
+ try {
+ const data = await request({
+ json: true,
+ method: 'GET',
+ timeout: Config.requestTimeout,
+ url: Config.nodeListURLs[i],
+ });
+
+ if (data.nodes) {
+ this.daemons = data.nodes;
+ this.caches = data.apis;
+ return;
}
- i++;
+ } catch (error) {
+ console.log(offline_node_list);
+ this.logger.addLogMessage('Failed to get node list from API: ' + error.toString());
+ }
+ i++;
}
this.daemons = offline_node_list.nodes;
this.caches = offline_node_list.apis;
+ }
+
+ async updateGroupsList() {
+ try {
+ const data = await request({
+ json: true,
+ method: 'GET',
+ timeout: Config.requestTimeout,
+ url: Config.groupsListURL,
+ });
+ console.log(data);
+ if (data.apis) {
+ this.standardGroups = data.groups;
+ } else {
+ this.standardGroups = offline_groups_list.groups;
+ }
+ } catch (error) {
+ console.log(offline_cache_list);
+ this.logger.addLogMessage('Failed to get groups list from API: ' + error.toString());
+ this.standardGroups = offline_groups_list.groups;
}
-
- async updateGroupsList() {
- try {
- const data = await request({
- json: true,
- method: 'GET',
- timeout: Config.requestTimeout,
- url: Config.groupsListURL,
- });
- console.log(data);
- if (data.apis) {
- this.standardGroups = data.groups;
- } else {
- this.standardGroups = offline_groups_list.groups;
- }
- } catch (error) {
- console.log(offline_cache_list);
- this.logger.addLogMessage('Failed to get groups list from API: ' + error.toString());
- this.standardGroups = offline_groups_list.groups;
- }
- }
+ }
}
export let Globals = new globals();
function updateConnection(connection) {
- if (Globals.preferences.limitData && connection.type === 'cellular') {
- Globals.wallet.stop();
- } else {
- Globals.wallet.enableAutoOptimization(false);
- Globals.wallet.start();
- }
+ if (Globals.preferences.limitData && connection.type === 'cellular') {
+ Globals.wallet.stop();
+ } else {
+ Globals.wallet.enableAutoOptimization(false);
+ Globals.wallet.start();
+ }
}
/* Note... you probably don't want to await this function. Can block for a while
if no internet. */
- export async function startWebsocket() {
+export async function startWebsocket() {
- if (Globals.websockets || Globals.preferences.websocketEnabled != 'true') return;
-
- if (Globals.preferences.cacheEnabled != "true") return;
- const socketURL = Globals.preferences.cache.replace(/^http:\/\//, 'ws://').replace(/^https:\/\//, 'wss://')+'/ws';
- Globals.socket = new WebSocket(socketURL);
+ if (Globals.websockets || Globals.preferences.websocketEnabled != 'true') return;
- // Open connection wit Cache
- Globals.socket.onopen = () => {
- Globals.websockets++;
- console.log(`Connected 🤖`)
- Globals.logger.addLogMessage('Connected to WebSocket 🤖');
- Globals.webSocketStatus = 'online';
+ if (Globals.preferences.cacheEnabled != "true") return;
+ const socketURL = Globals.preferences.cache.replace(/^http:\/\//, 'ws://').replace(/^https:\/\//, 'wss://') + '/ws';
+ Globals.socket = new WebSocket(socketURL);
- }
+ // Open connection wit Cache
+ Globals.socket.onopen = () => {
+ Globals.websockets++;
+ console.log(`Connected 🤖`)
+ Globals.logger.addLogMessage('Connected to WebSocket 🤖');
+ Globals.webSocketStatus = 'online';
- Globals.socket.onclose = (e) => {
- if (Globals.websockets > 0) Globals.websockets--;
-
- Globals.webSocketStatus = 'offline';
- Globals.logger.addLogMessage('Disconnected from WebSocket 🤖');
- startWebsocket();
- }
+ }
-// Listen for messages
- Globals.socket.onmessage = async (e) => {
- Globals.logger.addLogMessage('Received WebSocket Message!');
- let data = e.data
- Globals.logger.addLogMessage(data);
+ Globals.socket.onclose = (e) => {
+ if (Globals.websockets > 0) Globals.websockets--;
- try {
+ Globals.webSocketStatus = 'offline';
+ Globals.logger.addLogMessage('Disconnected from WebSocket 🤖');
+ startWebsocket();
+ }
- let json = JSON.parse(data)
- await getMessage(json, json.hash, Globals.navigation);
- sendNotifications();
+ // Listen for messages
+ Globals.socket.onmessage = async (e) => {
+ Globals.logger.addLogMessage('Received WebSocket Message!');
+ let data = e.data
+ Globals.logger.addLogMessage(data);
- } catch (err) {
- console.log(err)
- }
+ try {
+ let json = JSON.parse(data)
+ await getMessage(json, json.hash, Globals.navigation);
+ sendNotifications();
+
+ } catch (err) {
+ console.log(err)
}
- }
+
+ }
+}
export async function initGlobals() {
- const payees = await loadPayeeDataFromDatabase();
+ const payees = await loadPayeeDataFromDatabase();
- if (payees !== undefined) {
- Globals.payees = payees;
- }
+ if (payees !== undefined) {
+ Globals.payees = payees;
+ }
- Globals.knownTXs = await getKnownTransactions();
+ Globals.knownTXs = await getKnownTransactions();
- const groups = await loadGroupsDataFromDatabase();
+ const groups = await loadGroupsDataFromDatabase();
- Globals.groups = groups;
+ Globals.groups = groups;
- Globals.boardsSubscriptions = await getBoardSubscriptions();
+ Globals.boardsSubscriptions = await getBoardSubscriptions();
- Globals.unreadMessages = await getUnreadMessages();
+ Globals.unreadMessages = await getUnreadMessages();
- const transactionDetails = await loadTransactionDetailsFromDatabase();
+ const transactionDetails = await loadTransactionDetailsFromDatabase();
- if (transactionDetails !== undefined) {
- Globals.transactionDetails = transactionDetails;
- }
+ if (transactionDetails !== undefined) {
+ Globals.transactionDetails = transactionDetails;
+ }
- const netInfo = await NetInfo.fetch();
-
- /* Start syncing */
- if ((Globals.preferences.limitData && netInfo.type === 'cellular')) {
- Alert.alert(
- 'Not Syncing',
- 'You enabled data limits, and are on a limited connection. Not starting sync.',
- [
- {text: 'OK'},
- ]
- );
- } else {
- Globals.wallet.enableAutoOptimization(false);
- Globals.wallet.start();
- }
+ const netInfo = await NetInfo.fetch();
+
+ /* Start syncing */
+ if ((Globals.preferences.limitData && netInfo.type === 'cellular')) {
+ Alert.alert(
+ 'Not Syncing',
+ 'You enabled data limits, and are on a limited connection. Not starting sync.',
+ [
+ { text: 'OK' },
+ ]
+ );
+ } else {
+ Globals.wallet.enableAutoOptimization(false);
+ Globals.wallet.start();
+ }
- await Globals.updateNodeList();
- await Globals.updateGroupsList();
+ await Globals.updateNodeList();
+ await Globals.updateGroupsList();
let lastSync = await getLastSync();
diff --git a/src/Groups.js b/src/Groups.js
index 6d2bc0c..2d21fdf 100644
--- a/src/Groups.js
+++ b/src/Groups.js
@@ -8,813 +8,724 @@ import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
const runes = require('runes');
import {
- Linking, ActivityIndicator, Keyboard, KeyboardAvoidingView, View, Text, TextInput, ScrollView, FlatList, Platform, TouchableOpacity, TouchableWithoutFeedback, Image
+ Linking, ActivityIndicator, Keyboard, KeyboardAvoidingView, View, Text, ScrollView, FlatList, Platform, TouchableOpacity, TouchableWithoutFeedback, Image
} from 'react-native';
import { StackActions } from 'react-navigation';
import {
- validateAddresses, WalletErrorCode, validatePaymentID,
+ validateAddresses, WalletErrorCode, validatePaymentID,
} from 'kryptokrona-wallet-backend-js';
import { Button as RNEButton, Alert, Modal } from 'react-native';
-import { Button, Input, Icon } from 'react-native-elements';
-
+import { Button } from 'react-native-elements';
import Config from './Config';
import ListItem from './ListItem';
-import List from './ListContainer';
-
import { Styles, unread_counter_style, unread_counter_text_style } from './Styles';
-
import Moment from 'react-moment';
-
import 'moment/locale/de';
import 'moment/locale/sv';
import 'moment/locale/tr';
import 'moment/locale/zh-cn';
import 'moment/locale/nb';
-
import CustomIcon from './CustomIcon.js'
-
import { Globals } from './Globals';
-import { Hr, BottomButton, CopyButton } from './SharedComponents';
-
-
-import {intToRGB, hashCode, get_avatar, sendGroupsMessage, createGroup, getBoardColors} from './HuginUtilities';
-
-import {toastPopUp} from './Utilities';
-
-import { getGroupsMessage, loadGroupsDataFromDatabase, subscribeToGroup, markGroupConversationAsRead, getGroupMessages, getReplies, saveGroupMessage, removeGroupMessage} from './Database';
-
+import { BottomButton, CopyButton } from './SharedComponents';
+import { get_avatar, sendGroupsMessage, createGroup, getBoardColors } from './HuginUtilities';
+import { getGroupsMessage, loadGroupsDataFromDatabase, markGroupConversationAsRead, getGroupMessages, getReplies, saveGroupMessage, removeGroupMessage } from './Database';
import './i18n.js';
import { withTranslation } from 'react-i18next';
-
-import {AutoGrowingTextInput} from 'react-native-autogrow-textinput';
-
+import { AutoGrowingTextInput } from 'react-native-autogrow-textinput';
import InvertibleScrollView from 'react-native-invertible-scroll-view';
import GestureRecognizer from 'react-native-swipe-gestures';
-
import Hyperlink from 'react-native-hyperlink'
+import { ScreenLayout, ScreenHeader, TextField, InputField } from './components';
-String.prototype.hashCode = function() {
- var hash = 0;
- if (this.length == 0) {
- return hash;
- }
- for (var i = 0; i < this.length; i++) {
- var char = this.charCodeAt(i);
- hash = ((hash<<5)-hash)+char;
- hash = hash & hash; // Convert to 32bit integer
- }
+String.prototype.hashCode = function () {
+ var hash = 0;
+ if (this.length == 0) {
return hash;
+ }
+ for (var i = 0; i < this.length; i++) {
+ var char = this.charCodeAt(i);
+ hash = ((hash << 5) - hash) + char;
+ hash = hash & hash; // Convert to 32bit integer
+ }
+ return hash;
}
export class GroupsScreenNoTranslation extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- this.state = {
- groups: Globals.groups,
- index: 0,
- }
-
- Globals.updateGroupsFunctions.push(() => {
- this.setState(prevState => ({
- groups: Globals.groups,
- index: prevState.index + 1,
- }))
- });
+ this.state = {
+ groups: Globals.groups,
+ index: 0,
}
- render() {
- const { t } = this.props;
- let groups = this.state.groups;
- let uniqueGroups = [];
- groups.forEach((element) => {
- if (!uniqueGroups.includes(element)) {
- uniqueGroups.push(element);
- }
- });
- let standardGroups = Globals.standardGroups;
+ Globals.updateGroupsFunctions.push(() => {
+ this.setState(prevState => ({
+ groups: Globals.groups,
+ index: prevState.index + 1,
+ }))
+ });
+ }
+
+ render() {
+ const { t } = this.props;
+ let groups = this.state.groups;
+ let uniqueGroups = [];
+ groups.forEach((element) => {
+ if (!uniqueGroups.includes(element)) {
+ uniqueGroups.push(element);
+ }
+ });
+ let standardGroups = Globals.standardGroups;
- console.log(standardGroups);
+ console.log(standardGroups);
- standardGroups = standardGroups.filter(a => !this.state.groups.map(b=>b.key).includes(a.key));
+ standardGroups = standardGroups.filter(a => !this.state.groups.map(b => b.key).includes(a.key));
- const storyStyle = {
- borderRadius: 25,
- width: 60,
- height: 60,
- backgroundColor: 'white',
- marginRight: 10,
- flexDirection:'row'
- };
+ const storyStyle = {
+ borderRadius: 25,
+ width: 60,
+ height: 60,
+ backgroundColor: 'white',
+ marginRight: 10,
+ flexDirection: 'row'
+ };
- const storyTextStyle = [Styles.centeredText, {
- fontSize: 30,
- lineHeight: 58,
- width: 60,
- fontFamily: 'Montserrat-Bold',
- color: 'white',
- flex: 1,
- flexWrap: 'wrap'
- }];
+ const storyTextStyle = [Styles.centeredText, {
+ fontSize: 30,
+ lineHeight: 58,
+ width: 60,
+ fontFamily: 'Montserrat-Bold',
+ color: 'white',
+ flex: 1,
+ flexWrap: 'wrap'
+ }];
+
+ const addGroup = (g) => {
+ const group = {
+ group: g.name,
+ key: g.key
+ };
- const addGroup = (g) => {
- const group = {
- group: g.name,
- key: g.key
- };
+ /* Add payee to global payee store */
+ Globals.addGroup(group);
- /* Add payee to global payee store */
- Globals.addGroup(group);
+ this.props.navigation.dispatch(StackActions.popToTop());
+ this.props.navigation.navigate(
+ 'GroupChatScreen', {
+ group: group,
+ });
+ }
- this.props.navigation.dispatch(StackActions.popToTop());
- this.props.navigation.navigate(
+ const boardsRecommendations =
+
+ {t('groupsRecommendations')}
+
+ {standardGroups?.length > 0 && standardGroups.map(function (item, i) {
+ return
+ { addGroup(item) }} style={[storyStyle, { backgroundColor: getBoardColors(item.key) }]}>
+ {runes(item.name)[0].toUpperCase()}
+
+ {item.name}
+ ;
+ })
+ }
+
+ ;
+
+ const noGroupsComponent =
+
+
+ {t('emptyAddressBook')}
+
+ ;
+
+ const groupsComponent =
+
+ item.key}
+ renderItem={({ item }) => (
+ {item.lastMessageNickname ? item.lastMessageNickname : t('Anonymous')}{item.lastMessage}{"\n"}{item.lastMessageTimestamp / 1000} : t('noMessages')}
+ chevron={item.read == '1' ? false : {item.unreads}}
+ leftIcon={
+
+ //
+ //
+ // {item.nickname[0].toUpperCase()}
+ //
+ //
+ //
+ }
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontFamily: 'Montserrat-SemiBold'
+ }} showsVerticalScrollIndicator={false}
+ subtitleStyle={{
+ color: this.props.screenProps.theme.slightlyMoreVisibleColour,
+ fontFamily: 'Montserrat-Regular'
+ }}
+ onPress={async () => {
+ this.props.navigation.navigate(
'GroupChatScreen', {
- group: group,
+ group: item,
+ }
+ );
+ // await markGroupConversationAsRead(item.key);
+ Globals.groups = await loadGroupsDataFromDatabase();
+ this.setState({
+ groups: Globals.groups
+ });
+ }}
+ />
+ )}
+ />
+ ;
+
+ return (
+
+
+
+ {t('groups')}
+
+ {
+ Globals.fromChat = true;
+ this.props.navigation.navigate('NewGroup', {
+ finishFunction: (item) => {
+ this.props.navigation.navigate(
+ 'GroupChatScreen', {
+ group: item,
});
-
-
-
- }
-
- const boardsRecommendations =
-
- {t('groupsRecommendations')}
-
- {standardGroups != undefined && standardGroups.map(function(item, i){
- return { addGroup(item) }} style={[storyStyle, {backgroundColor: getBoardColors(item.key)}]}>{runes(item.name)[0].toUpperCase()}{item.name};
- })
- }
-
- ;
-
- const noGroupsComponent =
-
-
-
- {t('emptyAddressBook')}
-
- ;
-
- const newMessageIndicator =
- ;
-
- const groupsComponent =
-
- item.key}
- renderItem={({item}) => (
- {item.lastMessageNickname ? item.lastMessageNickname : t('Anonymous')}{item.lastMessage}{"\n"}{item.lastMessageTimestamp/1000} : t('noMessages')}
- chevron={item.read == '1' ? false : {item.unreads} }
- leftIcon={
-
- //
- //
- // {item.nickname[0].toUpperCase()}
- //
- //
- //
- }
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontFamily: 'Montserrat-SemiBold'
- }}showsVerticalScrollIndicator={false}
- subtitleStyle={{
- color: this.props.screenProps.theme.slightlyMoreVisibleColour,
- fontFamily: 'Montserrat-Regular'
- }}
- onPress={async () => {
- this.props.navigation.navigate(
- 'GroupChatScreen', {
- group: item,
- }
- );
- // await markGroupConversationAsRead(item.key);
- Globals.groups = await loadGroupsDataFromDatabase();
- console.log(Globals.groups);
- this.setState({
- groups: Globals.groups
- });
- }}
- />
- )}
- />
- ;
-
- return(
-
-
- {
- const newGroup = await createGroup();
- Globals.fromChat = true;
- this.props.navigation.navigate('NewGroup', {
- finishFunction: (item) => {
- this.props.navigation.navigate(
- 'GroupChatScreen', {
- group: item,
- });
- }
- })
- }}
- >
-
-
- {t('groups')}
-
-
-
-
-
-
-
-
-
-
-
-
- {this.state.groups.length > 0 ? groupsComponent : noGroupsComponent}
-
- {standardGroups.length ? boardsRecommendations : <>>}
-
-
-
-
- );
- }
+ }
+ })
+ }}
+ >
+
+
+
+
+ {this.state.groups.length > 0 ? groupsComponent : noGroupsComponent}
+ {standardGroups.length > 0 && boardsRecommendations}
+
+
+ );
+ }
}
export const GroupsScreen = withTranslation()(GroupsScreenNoTranslation)
function isPaymentIDValid(paymentID) {
- let errorMessage = '';
+ let errorMessage = '';
- if (paymentID === '') {
- return [true, errorMessage];
- }
+ if (paymentID === '') {
+ return [true, errorMessage];
+ }
- if (paymentID === undefined || paymentID === null) {
- return [false, errorMessage];
- }
+ if (paymentID === undefined || paymentID === null) {
+ return [false, errorMessage];
+ }
- const paymentIDError = validatePaymentID(paymentID);
+ const paymentIDError = validatePaymentID(paymentID);
- if (paymentIDError.errorCode !== WalletErrorCode.SUCCESS) {
- errorMessage = paymentIDError.toString();
+ if (paymentIDError.errorCode !== WalletErrorCode.SUCCESS) {
+ errorMessage = paymentIDError.toString();
- return [false, errorMessage];
- }
+ return [false, errorMessage];
+ }
- return [true, errorMessage];
+ return [true, errorMessage];
}
function validGroupName(group) {
- let errorMessage = '';
-
- if (Globals.groups.some((groups) => groups.group === group)) {
- errorMessage = `A group with the name ${group} already exists.`;
- return [false, errorMessage];
- }
-
- if (group === '' || group === undefined || group === null) {
- return [false, errorMessage];
- }
-
- /* Disable payment ID and wipe input if integrated address */
- // if (address.length === Config.integratedAddressLength) {
- // await this.setState({
- // paymentID: '',
- // paymentIDEnabled: false,
- // });
- // } else {
- // this.setState({
- // paymentIDEnabled: true,
- // });
- // }
- return [true, errorMessage];
+ let errorMessage = '';
+
+ if (Globals.groups.some((groups) => groups.group === group)) {
+ errorMessage = `A group with the name ${group} already exists.`;
+ return [false, errorMessage];
+ }
+
+ if (group === '' || group === undefined || group === null) {
+ return [false, errorMessage];
+ }
+
+ /* Disable payment ID and wipe input if integrated address */
+ // if (address.length === Config.integratedAddressLength) {
+ // await this.setState({
+ // paymentID: '',
+ // paymentIDEnabled: false,
+ // });
+ // } else {
+ // this.setState({
+ // paymentIDEnabled: true,
+ // });
+ // }
+ return [true, errorMessage];
}
function isAddressValid(address) {
- let errorMessage = '';
+ let errorMessage = '';
- if (address === '' || address === undefined || address === null) {
- errorMessage = 'Address cannot be blank.';
- return [false, errorMessage];
- }
+ if (address === '' || address === undefined || address === null) {
+ errorMessage = 'Address cannot be blank.';
+ return [false, errorMessage];
+ }
- const addressError = validateAddresses([address], true, Config);
+ const addressError = validateAddresses([address], true, Config);
- if (addressError.errorCode !== WalletErrorCode.SUCCESS) {
- errorMessage = addressError.toString();
- return [false, errorMessage];
- }
+ if (addressError.errorCode !== WalletErrorCode.SUCCESS) {
+ errorMessage = addressError.toString();
+ return [false, errorMessage];
+ }
- return [true, errorMessage];
+ return [true, errorMessage];
}
class ModifyGroup extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- return(
- {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- }}
- errorMessage={this.props.error}
- />
- );
- }
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ return (
+ {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ }}
+ errorMessage={this.props.error}
+ />
+ );
+ }
}
-class ModifyNickname extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- return(
- {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- }}
- errorMessage={this.props.error}
- />
- );
- }
-}
+// class ModifyNickname extends React.Component {
+// constructor(props) {
+// super(props);
+// }
+
+// render() {
+// return (
+// {
+// if (this.props.onChange) {
+// this.props.onChange(text);
+// }
+// }}
+// errorMessage={this.props.error}
+// />
+// );
+// }
+// }
export class ModifyGroupScreenNoTranslation extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- const { group, key } = this.props.navigation.state.params.group;
+ const { group, key } = this.props.navigation.state.params.group;
- this.state = {
- group,
- key,
+ this.state = {
+ group,
+ key,
- initialGroup: group,
+ initialGroup: group,
- modifyGroup: false,
+ modifyGroup: false,
- newGroup: group,
+ newGroup: group,
- groupError: '',
+ groupError: '',
- groupValid: true
- }
+ groupValid: true
}
+ }
+
+ render() {
+ const { t } = this.props;
+ // const group = this.state.group;
+ const editableGroup = !Globals.standardGroups.some((rec) => rec.key == this.state.key);
+ return (
+
+
+
+ {this.state.group + t('details')}
+
+
+
+
+
+
- render() {
- const { t } = this.props;
- const group = this.state.group;
- const editableGroup = !Globals.standardGroups.some((rec) => rec.key == this.state.key);
- return(
+
+
+
+
+
+
+
+
+
+
-
-
- {this.state.group + t('details')}
-
-
+
+ {'Groupname'}
+
+ {editableGroup &&
+
+ {!this.state.modifyGroup &&
+
+
-
+ {this.state.group}
+
-
+
-
+ }
-
-
-
- {'Groupname'}
-
- {editableGroup &&
-
+
- {!this.state.modifyGroup &&
+
+ {this.state.modifyGroup ?
+ {
-
+ const [valid, error] = validGroupName(text);
-
- {this.state.group}
-
+ const shared = {
+ group: text,
+ groupError: error,
+ groupValid: valid,
+ };
-
+ if (valid) {
+ this.setState({
+ newGroup: text,
+ ...shared,
+ });
+ } else {
+ this.setState(shared);
+ }
+ }}
+ {...this.props}
+ />
+ :
+
+ {this.state.address}
+
+ }
+
+
+
+
+ {'Group key'}
+
+
+
- }
+
+ {this.state.key}
+
-
+
+
-
- {this.state.modifyGroup ?
- {
-
- const [valid, error] = validGroupName(text);
-
- const shared = {
- group: text,
- groupError: error,
- groupValid: valid,
- };
-
- if (valid) {
- this.setState({
- newGroup: text,
- ...shared,
- });
- } else {
- this.setState(shared);
- }
- }}
- {...this.props}
- />
- :
-
- {this.state.address}
-
- }
-
+
+ {editableGroup &&
+
+
+ {
+ await Globals.removeGroup(this.state.key, false);
-
-
-
- {'Group key'}
-
-
-
-
-
- {this.state.key}
-
-
-
-
+ Globals.addGroup({
+ group: this.state.newGroup,
+ key: this.state.key
+ });
-
- {editableGroup &&
-
-
-
- {
- await Globals.removeGroup(this.state.key, false);
-
- Globals.addGroup({
- group: this.state.newGroup,
- key: this.state.key
- });
-
- this.setState({
- groups: Globals.groups,
- group: this.state.newGroup
- });
-
- this.props.navigation.goBack();
- }}
- color={this.props.screenProps.theme.primaryColour}
- disabled={!this.state.groupValid}
- />
-
-
- }
-
-
- {
- Alert.alert(
- t('remove'),
- t('removeWarning'),
- [
- { text: t('remove'), onPress: () => {
- Globals.removeGroup(this.state.key, true);
- this.setState({
- groups: Globals.groups
- });
- this.props.navigation.pop(2);
- }},
- { text: t('cancel'), style: 'cancel'},
- ],
- );
- }}
- color='#DD3344'
- />
-
-
+ this.setState({
+ groups: Globals.groups,
+ group: this.state.newGroup
+ });
+
+ this.props.navigation.goBack();
+ }}
+ color={this.props.screenProps.theme.primaryColour}
+ disabled={!this.state.groupValid}
+ />
- );
- }
+
+ }
+
+
+ {
+ Alert.alert(
+ t('remove'),
+ t('removeWarning'),
+ [
+ {
+ text: t('remove'), onPress: () => {
+ Globals.removeGroup(this.state.key, true);
+ this.setState({
+ groups: Globals.groups
+ });
+ this.props.navigation.pop(2);
+ }
+ },
+ { text: t('cancel'), style: 'cancel' },
+ ],
+ );
+ }}
+ color='#DD3344'
+ />
+
+
+
+ );
+ }
}
export const ModifyGroupScreen = withTranslation()(ModifyGroupScreenNoTranslation)
export class GroupChatScreenNoTranslation extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- const { group, key } = this.props.navigation.state.params.group;
+ const { group, key } = this.props.navigation.state.params.group;
- this.state = {
- group,
- key,
+ this.state = {
+ group,
+ key,
- initialGroupName: group,
+ initialGroupName: group,
- modifyGroupName: false,
+ modifyGroupName: false,
- newGroupName: group,
+ newGroupName: group,
- groupNameError: '',
+ groupNameError: '',
- input: React.createRef(),
+ input: React.createRef(),
- groupNameValid: true,
+ groupNameValid: true,
- sending: false,
-
- messages: [],
- message: "",
- messageHasLength: false,
- messageModalVisible: false,
- activePost: {
- "message": "",
- "address": "",
- "group": "",
- "timestamp": "",
- "nickname": "",
- "reply": "0",
- "hash": "",
- "sent": 0,
- "read": 0
- }
- }
+ sending: false,
+ messages: [],
+ message: "",
+ messageHasLength: false,
+ messageModalVisible: false,
+ activePost: {
+ "message": "",
+ "address": "",
+ "group": "",
+ "timestamp": "",
+ "nickname": "",
+ "reply": "0",
+ "hash": "",
+ "sent": 0,
+ "read": 0
+ }
}
- async componentDidMount() {
+ }
- markGroupConversationAsRead(this.state.key);
+ async componentDidMount() {
+
+ markGroupConversationAsRead(this.state.key);
- let messages = await getGroupMessages(this.state.key, 25);
Globals.updateGroupsFunctions.push(async () => {
this.setState({
@@ -822,467 +733,476 @@ export class GroupChatScreenNoTranslation extends React.Component {
})
});
- if (!messages) {
- messages = [];
- }
+ Globals.updateGroupsFunctions.push(async () => {
+ this.setState({
+ messages: await getGroupMessages(this.state.key, Globals.messagesLoaded + 1)
+ })
+ });
- this.setState({
- messages: messages
- });
+ if (!messages) {
+ messages = [];
+ }
+
+ this.setState({
+ messages: messages
+ });
- Globals.messagesLoaded = messages.length;
+ Globals.messagesLoaded = messages.length;
+ Globals.activeGroup = this.state.key;
+
+ this.focusSubscription = this.props.navigation.addListener(
+ 'willFocus',
+ () => {
+ markGroupConversationAsRead(this.state.key);
Globals.activeGroup = this.state.key;
+ }
+ );
+ this.blurSubscription = this.props.navigation.addListener(
+ 'willBlur',
+ () => {
+ Globals.activeGroup = '';
+ }
+ );
- this.focusSubscription = this.props.navigation.addListener(
- 'willFocus',
- () => {
- markGroupConversationAsRead(this.state.key);
- Globals.activeGroup = this.state.key;
- }
- );
- this.blurSubscription = this.props.navigation.addListener(
- 'willBlur',
- () => {
- Globals.activeGroup = '';
- }
- );
+ }
- }
+ async componentWillUnmount() {
- async componentWillUnmount() {
+ Globals.activeGroup = '';
+ Globals.updateGroupsFunctions.pop();
- Globals.activeGroup = '';
- Globals.updateGroupsFunctions.pop();
+ }
- }
+ setActivePost = (item) => {
+ this.setState({ activePost: item });
+ }
- setActivePost = (item) => {
- this.setState({ activePost: item });
- }
+ setMessageModalVisible = (visible) => {
+ this.setState({ messageModalVisible: visible });
+ }
- setMessageModalVisible = (visible) => {
- this.setState({ messageModalVisible: visible });
- }
+ render() {
- render() {
+ const { t } = this.props;
- const { t } = this.props;
+ const { messageModalVisible, activePost } = this.state;
- const { messageModalVisible, activePost } = this.state;
+ const items = [];
- const items = [];
+ for (message in this.state.messages) {
- for (message in this.state.messages) {
+ if (this.state.key == this.state.messages[message].group) {
- if (this.state.key == this.state.messages[message].group){
+ let timestamp = this.state.messages[message].timestamp / 1000;
+ let thisMessage = this.state.messages[message];
- let timestamp = this.state.messages[message].timestamp / 1000;
- let thisMessage = this.state.messages[message];
+ items.push(
+ {
- items.push(
- {
+ console.log(thisMessage);
- console.log(thisMessage);
+ this.state.replies = await getReplies(thisMessage.hash);
+ this.setActivePost(thisMessage);
- this.state.replies = await getReplies(thisMessage.hash);
- this.setActivePost(thisMessage);
+ this.setMessageModalVisible(true);
- this.setMessageModalVisible(true);
+ }}>
+
+
+ {thisMessage.type == 'processing' && }
+ {thisMessage.type == 'failed' && { removeGroupMessage(thisMessage.timestamp); submitMessage(thisMessage.message) }}>Message failed to send. Tap here to try again.}
+ {thisMessage.replyMessage &&
+ {
+ console.log(thisMessage);
+ this.state.replies = await getReplies(thisMessage.reply);
+
+ this.setActivePost(await getGroupsMessage(thisMessage.reply));
+
+ this.setMessageModalVisible(true);
}}>
-
-
- {thisMessage.type == 'processing' && }
- {thisMessage.type == 'failed' && {removeGroupMessage(thisMessage.timestamp); submitMessage(thisMessage.message)}}>Message failed to send. Tap here to try again.}
- {thisMessage.replyMessage &&
- {
- console.log(thisMessage);
- this.state.replies = await getReplies(thisMessage.reply);
-
- this.setActivePost(await getGroupsMessage(thisMessage.reply));
-
- this.setMessageModalVisible(true);
-
- }}>
-
-
- {thisMessage.replyNickname ? thisMessage.replyNickname : t('Anonymous')}
-
- {thisMessage.replyMessage}
-
-
- }
-
-
-
-
+
+ {thisMessage.replyNickname ? thisMessage.replyNickname : t('Anonymous')}
+
+ {thisMessage.replyMessage}
+
+
+ }
+
+
+
+ {thisMessage.nickname ? thisMessage.nickname : t('Anonymous')}
-
-
- {thisMessage.message}
-
- {timestamp}
- {thisMessage.replies > 0 && {thisMessage.replies} }
-
+ }}>{thisMessage.nickname ? thisMessage.nickname : t('Anonymous')}
+
-
+
+ {thisMessage.message}
+
+ {timestamp}
+ {thisMessage.replies > 0 && {thisMessage.replies}}
+
+
+
- )
- // } else {
- // items.push({this.state.messages[message].message}{timestamp})
- // }
+ )
+ // } else {
+ // items.push({this.state.messages[message].message}{timestamp})
+ // }
- }
- }
+ }
+ }
- const modalStyle = {
- height: '100%',
- marginTop: 50,
- marginLeft: 10,
- marginRight: 10,
- backgroundColor: this.props.screenProps.theme.backgroundEmphasis,
- borderWidth: 1,
- borderColor: this.props.screenProps.theme.borderColour,
- borderTopRightRadius: 20,
- borderTopLeftRadius: 20,
- padding: 25,
- alignItems: "center",
- shadowColor: "#000",
- shadowOffset: {
- width: 0,
- height: 2
- },
- shadowOpacity: 0.25,
- shadowRadius: 4,
- elevation: 5
- };
+ const modalStyle = {
+ height: '100%',
+ marginTop: 50,
+ marginLeft: 10,
+ marginRight: 10,
+ backgroundColor: this.props.screenProps.theme.backgroundEmphasis,
+ borderWidth: 1,
+ borderColor: this.props.screenProps.theme.borderColour,
+ borderTopRightRadius: 20,
+ borderTopLeftRadius: 20,
+ padding: 25,
+ alignItems: "center",
+ shadowColor: "#000",
+ shadowOffset: {
+ width: 0,
+ height: 2
+ },
+ shadowOpacity: 0.25,
+ shadowRadius: 4,
+ elevation: 5
+ };
- const replyInput =
-
- { this.replyinput = input }}
- style={{
- color: this.props.screenProps.theme.primaryColour,
- fontFamily: 'Montserrat-Regular',
- fontSize: 15,
- width: '100%',
- height: '100%',
- padding: 15,
+ const replyInput =
+
+ { this.replyinput = input }}
+ style={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontFamily: 'Montserrat-Regular',
+ fontSize: 15,
+ width: '100%',
+ height: '100%',
+ padding: 15,
+
+ }}
+ maxLength={512}
+ placeholder={"✏️ " + t('typeMessageHere')}
+ placeholderTextColor={'#ffffff'}
+ onSubmitEditing={async (e) => {
+ e.preventDefault();
+ // return;
+ // submitMessage(this.state.message);
+ // this.setState({message: '', messageHasLength: false});
+ }}
+ onChangeText={(text) => {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ this.state.reply = text;
+ this.setState({ replyHasLength: this.state.reply.length > 0 });
+ }}
+ errorMessage={this.props.error}
+ />
+ ;
+
+ const sendTip = (address, hash, name) => {
+ const url = `xkr://?address=${address}&paymentid=${hash}&istip=true&name=${name}`;
+ this.setMessageModalVisible(false);
+ Linking.openURL(url);
+ }
- }}
- maxLength={512}
- placeholder={"✏️ " + t('typeMessageHere')}
- placeholderTextColor={'#ffffff'}
- onSubmitEditing={async (e) => {
- e.preventDefault();
- // return;
- // submitMessage(this.state.message);
- // this.setState({message: '', messageHasLength: false});
- }}
- onChangeText={(text) => {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- this.state.reply = text;
- this.setState({replyHasLength: this.state.reply.length > 0});
- }}
- errorMessage={this.props.error}
- />
- ;
+ const submitReply = async (text) => {
- const sendTip = (address, hash, name) => {
- const url = `xkr://?address=${address}&paymentid=${hash}&istip=true&name=${name}`;
- this.setMessageModalVisible(false);
- Linking.openURL(url);
- }
+ Keyboard.dismiss();
+ this.setState({ reply: '', replyHasLength: false, replying: false });
- const submitReply = async (text) => {
-
- Keyboard.dismiss();
- this.setState({reply: '', replyHasLength: false, replying: false});
+ submitMessage(text, this.state.activePost.hash);
- submitMessage(text, this.state.activePost.hash);
+ }
- }
+ const submitMessage = async (text, reply = false) => {
- const submitMessage = async (text, reply=false) => {
+ Keyboard.dismiss();
+ this.state.input.current._textInput.clear();
- Keyboard.dismiss();
- this.state.input.current._textInput.clear();
+ let temp_timestamp = Date.now();
- let temp_timestamp = Date.now();
-
- saveGroupMessage(this.state.key, 'processing', checkText(text), temp_timestamp, Globals.preferences.nickname, Globals.wallet.getPrimaryAddress(), reply ? reply : '', temp_timestamp);
+ saveGroupMessage(this.state.key, 'processing', checkText(text), temp_timestamp, Globals.preferences.nickname, Globals.wallet.getPrimaryAddress(), reply ? reply : '', temp_timestamp);
- let updated_messages = await getGroupMessages(this.state.key, this.state.messages.length);
- if (!updated_messages) {
- updated_messages = [];
- }
+ let updated_messages = await getGroupMessages(this.state.key, this.state.messages.length);
+ if (!updated_messages) {
+ updated_messages = [];
+ }
- this.setState({
- messages: updated_messages,
- messageHasLength: false,
- sending: true
- });
+ this.setState({
+ messages: updated_messages,
+ messageHasLength: false,
+ sending: true
+ });
- Globals.messagesLoaded = updated_messages.length;
+ Globals.messagesLoaded = updated_messages.length;
- this.setState({messageHasLength: this.state.message.length > 0});
- this.scrollView.scrollTo({y: 0, animated: true});
- await sendGroupsMessage(checkText(text), this.state.key, temp_timestamp, reply);
- this.scrollView.scrollTo({y: 0, animated: true});
+ this.setState({ messageHasLength: this.state.message.length > 0 });
+ this.scrollView.scrollTo({ y: 0, animated: true });
+ await sendGroupsMessage(checkText(text), this.state.key, temp_timestamp, reply);
+ this.scrollView.scrollTo({ y: 0, animated: true });
- if(reply) {
- replies = await getReplies(this.state.activePost.hash);
- this.setState({replies: replies});
- }
+ if (reply) {
+ replies = await getReplies(this.state.activePost.hash);
+ this.setState({ replies: replies });
+ }
- }
+ }
- return(
+ return (
+
+
+
+
+
+ {
+ this.props.navigation.navigate(
+ 'ModifyGroup', {
+ group: this.props.navigation.state.params.group,
+ }
+ );
+ }} style={{ fontSize: 18, color: this.props.screenProps.theme.primaryColour, fontFamily: 'Montserrat-SemiBold' }}>
+ {this.state.group}
+
+
+
+
+
+
+
+
+ { this.scrollView = ref }}
+ >
+
+
+
+ {items}
+
+
+
+ {!this.state.sending && this.state.messages?.length > 0 && this.state.messages[0]?.count != this.state.messages?.length && this.state.messages?.length >= 25 &&
+
-
- {
+ console.log('Loading:', this.state.messages.length + 25)
+ let updated_messages = await getGroupMessages(this.state.key, this.state.messages.length + 25);
+ Globals.messagesLoaded = updated_messages.length;
+ this.setState({
+ messages: updated_messages,
+ messageHasLength: false
+ });
}}>
-
-
- {
- this.props.navigation.navigate(
- 'ModifyGroup', {
- group: this.props.navigation.state.params.group,
- }
- );
- }} style={{ fontSize: 18, color: this.props.screenProps.theme.primaryColour, fontFamily: 'Montserrat-SemiBold' }}>
- {this.state.group}
-
-
-
-
-
+ {t('loadMore')}
- {this.scrollView = ref}}
- >
-
-
-
- {items}
+
-
+
+
- {!this.state.sending && this.state.messages?.length > 0 && this.state.messages[0]?.count != this.state.messages?.length && this.state.messages?.length >= 25 &&
-
- {
- console.log('Loading:' , this.state.messages.length + 25)
- let updated_messages = await getGroupMessages(this.state.key, this.state.messages.length + 25);
- Globals.messagesLoaded = updated_messages.length;
- this.setState({
- messages: updated_messages,
- messageHasLength: false
- });
- }}>
-
+ }
- {t('loadMore')}
+
-
+
+
+
-
-
-
+ }}
+ maxLength={512}
+ placeholder={t('typeMessageHere')}
+ placeholderTextColor={'#ffffff'}
+ onSubmitEditing={async (e) => {
+ e.preventDefault();
+ // return;
+ // submitMessage(this.state.message);
+ // this.setState({message: '', messageHasLength: false});
+ }}
+ onChangeText={(text) => {
+ if (this.props.onChange) {
+ this.props.onChange(text);
}
+ this.state.message = text;
+ this.setState({ messageHasLength: this.state.message.length > 0 });
+ }}
+ errorMessage={this.props.error}
+ />
+
+ {this.state.messageHasLength &&
+
+
+
+ } onPress={() => {
+ this.props.navigation.navigate('Recipients', this.props.navigation);
+ }}>
+ {unreadPrivateMessages ? (
+ {unreadPrivateMessages}
+ ) : null}
+
+ {t('messagesTitle')}
+
+
+
+ }
-
-
-
-
-
- );
- }
+
+
+
+
+
+ );
+ }
}
+export const MainScreen = withTranslation()(MainScreenNoTranslation);
+
/* Display address, and QR code */
class AddressComponent extends React.PureComponent {
- constructor(props) {
- super(props);
-
- this.state = {
- address: Globals.wallet.getPrimaryAddress(),
- };
- }
+ constructor(props) {
+ super(props);
+ this.state = {
+ address: Globals.wallet.getPrimaryAddress(),
+ };
+ }
- render() {
- const { t } = this.props;
-
- return(
-
-
- {t('paymentAddress')}
-
- {
- Clipboard.setString(this.state.address);
- toastPopUp(this.state.address + t('copied'));
- }
- }
- >
- {this.state.address}
-
-
-
- {t('messageKey')}
-
-
- {
- Clipboard.setString(Buffer.from(getKeyPair().publicKey).toString('hex'));
- toastPopUp(Buffer.from(getKeyPair().publicKey).toString('hex') + t('copied'));
- }
- } numberOfLines={2} style={[Styles.centeredText, {
- color: this.props.screenProps.theme.primaryColour,
- width: 215,
- fontSize: 15,
- marginTop: 0,
- marginBottom: 5,
- marginRight: 20,
- marginLeft: 20,
- fontFamily: 'Montserrat-Regular'
- }]}>
- {Buffer.from(getKeyPair().publicKey).toString('hex')}
-
-
-
-
- );
- }
+ render() {
+ const { t } = this.props;
+
+ return (
+
+
+ {t('paymentAddress')}
+
+ {
+ Clipboard.setString(this.state.address);
+ toastPopUp(this.state.address + t('copied'));
+ }
+ }
+ >
+ {this.state.address}
+
+
+
+ {t('messageKey')}
+
+
+ {
+ Clipboard.setString(Buffer.from(getKeyPair().publicKey).toString('hex'));
+ toastPopUp(Buffer.from(getKeyPair().publicKey).toString('hex') + t('copied'));
+ }
+ } numberOfLines={2} style={[Styles.centeredText, {
+ color: this.props.screenProps.theme.primaryColour,
+ width: 215,
+ fontSize: 15,
+ marginTop: 0,
+ marginBottom: 5,
+ marginRight: 20,
+ marginLeft: 20,
+ fontFamily: 'Montserrat-Regular'
+ }]}>
+ {Buffer.from(getKeyPair().publicKey).toString('hex')}
+
+
+ );
+ }
}
const AddressComponentWithTranslation = withTranslation()(AddressComponent)
@@ -768,122 +656,107 @@ const AddressComponentWithTranslation = withTranslation()(AddressComponent)
* Balance component at top of screen
*/
class BalanceComponentNoTranslation extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- this.state = {
- expandedBalance: false,
- };
+ this.state = {
+ expandedBalance: false,
+ };
- this.balanceRef = (ref) => this.balance = ref;
- this.valueRef = (ref) => this.value = ref;
- }
+ this.balanceRef = (ref) => this.balance = ref;
+ this.valueRef = (ref) => this.value = ref;
+ }
- componentWillMount() {
- }
+ componentWillMount() {
+ }
- componentDidMount() {
+ componentDidMount() {
- let flipFlop = false;
+ let flipFlop = false;
- }
+ }
- componentWillReceiveProps(nextProps) {
- if (nextProps.unlockedBalance !== this.props.unlockedBalance ||
- nextProps.lockedBalance !== this.props.lockedBalance) {
- }
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.unlockedBalance !== this.props.unlockedBalance ||
+ nextProps.lockedBalance !== this.props.lockedBalance) {
}
+ }
- render() {
- const {t} = this.props;
- const hasBalance = (this.props.unlockedBalance + this.props.lockedBalance > 0) ? true : false;
- const compactBalance =
-
-
-
- {prettyPrintAmountMainScreen(this.props.unlockedBalance)}
-
- ;
-
- const lockedBalance =
-
- this.setState({
- expandedBalance: !this.state.expandedBalance
- })}>
- {prettyPrintAmount(this.props.lockedBalance, Config).slice(0,-4)}
-
- ;
-
- const unlockedBalance =
-
- this.setState({
- expandedBalance: !this.props.expandedBalance
- })}>
- {prettyPrintAmount(this.props.unlockedBalance, Config).slice(0,-4)}
-
- ;
-
- const expandedBalance =
- {unlockedBalance}
- {lockedBalance}
- ;
-
-
- const OpenURLButton = () => {
- const handlePress = useCallback(async () => {
-
- // Opening the link with some app, if the URL scheme is "http" the web link should be opened
- // by some browser in the mobile
- await Linking.openURL('https://kryptokrona.org/en/faucet?address=' + this.props.address);
-
- });
- if (false) {
- return ;
- } else {
- return ;
- }
- };
-
- // const interpolateColor = this.animatedValue.interpolate({
- // inputRange: [0, 32, 64, 96, 128, 160, 192, 224],
- // outputRange:['#5f86f2','#a65ff2','#f25fd0','#f25f61','#f2cb5f','#abf25f','#5ff281','#5ff2f0']
- // });
-
-
-
- return(
-
- {/*
-
-
- {this.state.expandedBalance ? expandedBalance : compactBalance}
-
-
- {parseInt(this.props.lockedBalance) > 0 &&
- + {prettyPrintAmount(this.props.lockedBalance, Config).slice(0,-4)}}
-
+ render() {
+ const { t } = this.props;
+ const hasBalance = (this.props.unlockedBalance + this.props.lockedBalance > 0) ? true : false;
+ const compactBalance =
+
+
+
+ {prettyPrintAmountMainScreen(this.props.unlockedBalance)}
+ ;
+
+ const lockedBalance =
+
+ this.setState({
+ expandedBalance: !this.state.expandedBalance
+ })}>
+ {prettyPrintAmount(this.props.lockedBalance, Config).slice(0, -4)}
+
+ ;
+
+ const unlockedBalance =
+
+ this.setState({
+ expandedBalance: !this.props.expandedBalance
+ })}>
+ {prettyPrintAmount(this.props.unlockedBalance, Config).slice(0, -4)}
+
+ ;
+
+ const expandedBalance =
+ {unlockedBalance}
+ {lockedBalance}
+ ;
+
+
+ const OpenURLButton = () => {
+ const handlePress = useCallback(async () => {
+
+ // Opening the link with some app, if the URL scheme is "http" the web link should be opened
+ // by some browser in the mobile
+ await Linking.openURL('https://kryptokrona.org/en/faucet?address=' + this.props.address);
-
-
- {hasBalance &&
- {this.props.coinValue}
- }
-
-
- );
- }
+ });
+ // Should this be used?
+ if (false) {
+ // return ;
+ } else {
+ // return ;
+ }
+ };
+
+ return (
+
+
+ {this.state.expandedBalance ? expandedBalance : compactBalance}
+
+ {parseInt(this.props.lockedBalance) > 0 &&
+ + {prettyPrintAmount(this.props.lockedBalance, Config).slice(0, -4)}}
+ {/* */}
+ {hasBalance &&
+ {this.props.coinValue}
+ }
+
+ );
+ }
}
const BalanceComponent = withTranslation()(BalanceComponentNoTranslation)
@@ -893,105 +766,105 @@ const BalanceComponent = withTranslation()(BalanceComponentNoTranslation)
* Sync status at bottom of screen
*/
class SyncComponent extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- const [walletHeight, localHeight, networkHeight] = Globals.wallet.getSyncStatus();
+ const [walletHeight, localHeight, networkHeight] = Globals.wallet.getSyncStatus();
- this.state = {
- walletHeight,
- localHeight,
- networkHeight,
- progress: 0,
- percent: '0.00',
- };
+ this.state = {
+ walletHeight,
+ localHeight,
+ networkHeight,
+ progress: 0,
+ percent: '0.00',
+ };
- this.updateSyncStatus = this.updateSyncStatus.bind(this);
+ this.updateSyncStatus = this.updateSyncStatus.bind(this);
- this.syncRef = (ref) => this.sync = ref;
- }
+ this.syncRef = (ref) => this.sync = ref;
+ }
- updateSyncStatus(walletHeight, localHeight, networkHeight) {
- /* Since we update the network height in intervals, and we update wallet
- height by syncing, occasionaly wallet height is > network height.
- Fix that here. */
- if (walletHeight > networkHeight && networkHeight !== 0 && networkHeight + 10 > walletHeight) {
- networkHeight = walletHeight;
- }
+ updateSyncStatus(walletHeight, localHeight, networkHeight) {
+ /* Since we update the network height in intervals, and we update wallet
+ height by syncing, occasionaly wallet height is > network height.
+ Fix that here. */
+ if (walletHeight > networkHeight && networkHeight !== 0 && networkHeight + 10 > walletHeight) {
+ networkHeight = walletHeight;
+ }
- /* Don't divide by zero */
- let progress = networkHeight === 0 ? 100 : walletHeight / networkHeight;
+ /* Don't divide by zero */
+ let progress = networkHeight === 0 ? 100 : walletHeight / networkHeight;
- if (progress > 1) {
- progress = 1;
- }
+ if (progress > 1) {
+ progress = 1;
+ }
- let percent = 100 * progress;
+ let percent = 100 * progress;
- /* Prevent bar looking full when it's not */
- if (progress > 0.97 && progress < 1) {
- progress = 0.97;
- }
+ /* Prevent bar looking full when it's not */
+ if (progress > 0.97 && progress < 1) {
+ progress = 0.97;
+ }
- /* Prevent 100% when just under */
- if (percent > 99.99 && percent < 100) {
- percent = 99.99;
- } else if (percent > 100) {
- percent = 100;
- }
+ /* Prevent 100% when just under */
+ if (percent > 99.99 && percent < 100) {
+ percent = 99.99;
+ } else if (percent > 100) {
+ percent = 100;
+ }
- const justSynced = progress === 1 && this.state.progress !== 1;
+ const justSynced = progress === 1 && this.state.progress !== 1;
- this.setState({
- walletHeight,
- localHeight,
- networkHeight,
- progress,
- percent: percent.toFixed(2),
- }, () => { if (justSynced) { this.sync.bounce(800) } });
- }
+ this.setState({
+ walletHeight,
+ localHeight,
+ networkHeight,
+ progress,
+ percent: percent.toFixed(2),
+ }, () => { if (justSynced) { this.sync.bounce(800) } });
+ }
- componentDidMount() {
- Globals.wallet.on('heightchange', this.updateSyncStatus);
- }
+ componentDidMount() {
+ Globals.wallet.on('heightchange', this.updateSyncStatus);
+ }
- componentWillUnmount() {
- if (Globals.wallet) {
- Globals.wallet.removeListener('heightchange', this.updateSyncStatus);
- }
+ componentWillUnmount() {
+ if (Globals.wallet) {
+ Globals.wallet.removeListener('heightchange', this.updateSyncStatus);
}
+ }
- render() {
- return(
-
-
- {this.state.walletHeight} / {this.state.networkHeight} - {this.state.percent}%
-
-
-
- );
- }
+ render() {
+ return (
+
+
+ {this.state.walletHeight} / {this.state.networkHeight} - {this.state.percent}%
+
+
+
+ );
+ }
}
/**
* Save wallet in background
*/
async function backgroundSave() {
- Globals.logger.addLogMessage('Saving wallet...');
+ Globals.logger.addLogMessage('Saving wallet...');
- try {
- await saveToDatabase(Globals.wallet);
- Globals.logger.addLogMessage('Save complete.');
- } catch (err) {
- Globals.logger.addLogMessage('Failed to background save: ' + err);
- }
+ try {
+ await saveToDatabase(Globals.wallet);
+ Globals.logger.addLogMessage('Save complete.');
+ } catch (err) {
+ Globals.logger.addLogMessage('Failed to background save: ' + err);
+ }
}
async function checkIfStuck() {
@@ -1002,11 +875,11 @@ async function checkIfStuck() {
return;
}
- if ( walletHeight == 0) {
+ if (walletHeight == 0) {
Globals.stuckTicks ? Globals.stuckTicks += 1 : Globals.stuckTicks = 1;
if (Globals.stuckTicks > 3) {
- Globals.wallet.rewind(networkHeight-100);
+ Globals.wallet.rewind(networkHeight - 100);
}
} else {
@@ -1022,29 +895,29 @@ export async function backgroundSyncMessages(navigation) {
Globals.logger.addLogMessage('[Message sync] Starting message synchronization routine.');
- const syncingHasStalled = (Date.now() - Globals.lastSyncEvent > 1000 * 60 );
+ const syncingHasStalled = (Date.now() - Globals.lastSyncEvent > 1000 * 60);
- if (syncingHasStalled ) Globals.syncingMessages = false;
+ if (syncingHasStalled) Globals.syncingMessages = false;
- // Add check if websocket // cache is working
- if (Globals.preferences.cacheEnabled == "true") {
+ // Add check if websocket // cache is working
+ if (Globals.preferences.cacheEnabled == "true") {
- try {
- const cacheURL = `${Globals.preferences.cache}/api/v1/info`;
- console.log('trying to get ', cacheURL);
- const resp = await fetch(cacheURL, {
- method: 'GET'
- }, 3000);
- if (!resp.ok) {
- Globals.APIOnline = false;
- } else {
- Globals.APIOnline = true;
- }
- } catch (e) {
- console.log(e);
+ try {
+ const cacheURL = `${Globals.preferences.cache}/api/v1/info`;
+ console.log('trying to get ', cacheURL);
+ const resp = await fetch(cacheURL, {
+ method: 'GET'
+ }, 3000);
+ if (!resp.ok) {
Globals.APIOnline = false;
- }
+ } else {
+ Globals.APIOnline = true;
+ }
+ } catch (e) {
+ console.log(e);
+ Globals.APIOnline = false;
}
+ }
Globals.logger.addLogMessage('[Message sync] API is connected: ' + Globals.APIOnline);
@@ -1055,7 +928,7 @@ export async function backgroundSyncMessages(navigation) {
if (Globals.webSocketStatus == 'online' && Globals.preferences.websocketEnabled == 'true') return;
}
- Globals.syncSkips = 0;
+ Globals.syncSkips = 0;
if (Globals.syncingMessages) {
Globals.logger.addLogMessage('[Message sync] Another synchronization process is already running. Aborting.');
@@ -1083,21 +956,21 @@ export async function backgroundSyncMessages(navigation) {
}
-
+
try {
Globals.logger.addLogMessage('Syncing messages from node.. 💌');
-
- const daemonInfo = Globals.wallet.getDaemonConnectionInfo();
- let knownTXs = await getKnownTransactions();
- let nodeURL = `${daemonInfo.ssl ? 'https://' : 'http://'}${daemonInfo.host}:${daemonInfo.port}`;
- fetch(nodeURL + "/get_pool_changes_lite", {
- method: 'POST',
- body: JSON.stringify({
- knownTxsIds: knownTXs
- })
+
+ const daemonInfo = Globals.wallet.getDaemonConnectionInfo();
+ let knownTXs = await getKnownTransactions();
+ let nodeURL = `${daemonInfo.ssl ? 'https://' : 'http://'}${daemonInfo.host}:${daemonInfo.port}`;
+ fetch(nodeURL + "/get_pool_changes_lite", {
+ method: 'POST',
+ body: JSON.stringify({
+ knownTxsIds: knownTXs
})
+ })
.then((response) => response.json())
.then(async (json) => {
@@ -1119,38 +992,38 @@ export async function backgroundSyncMessages(navigation) {
Globals.lastSyncEvent = Date.now();
- let thisExtra = transactions[transaction]["transactionPrefixInfo.txPrefix"].extra;
+ let thisExtra = transactions[transaction]["transactionPrefixInfo.txPrefix"].extra;
- let thisHash = transactions[transaction]["transactionPrefixInfo.txHash"];
+ let thisHash = transactions[transaction]["transactionPrefixInfo.txHash"];
- if (Globals.knownTXs.indexOf(thisHash) != -1) continue;
+ if (Globals.knownTXs.indexOf(thisHash) != -1) continue;
- if (thisExtra.length > 66) {
+ if (thisExtra.length > 66) {
-
- try {
+
+ try {
let message = await getMessage(thisExtra, thisHash, navigation);
- } catch (err) {
+ } catch (err) {
console.log(err);
+ }
+ saveKnownTransaction(thisHash);
+ if (Globals.knownTXs.indexOf(thisHash) === -1) Globals.knownTXs.push(thisHash);
+
+ } else {
+ saveKnownTransaction(thisHash);
+ if (Globals.knownTXs.indexOf(thisHash) === -1) Globals.knownTXs.push(thisHash);
+ continue;
}
- saveKnownTransaction(thisHash);
- if (Globals.knownTXs.indexOf(thisHash) === -1) Globals.knownTXs.push(thisHash);
- } else {
- saveKnownTransaction(thisHash);
- if (Globals.knownTXs.indexOf(thisHash) === -1) Globals.knownTXs.push(thisHash);
+
+ } catch (err) {
continue;
}
-
- } catch (err) {
- continue;
- }
-
}
Globals.logger.addLogMessage(`Found ${Globals.notificationQueue.length} messages.. 💌`);
-
+
sendNotifications();
Globals.initalSyncOccurred = true;
Globals.syncingMessages = false;
@@ -1159,10 +1032,10 @@ export async function backgroundSyncMessages(navigation) {
});
-} catch (err) {
- console.log('Message sync failed: ', err);
- Globals.syncingMessages = false;
-}
+ } catch (err) {
+ console.log('Message sync failed: ', err);
+ Globals.syncingMessages = false;
+ }
}
diff --git a/src/ProgressBar.js b/src/ProgressBar.js
index b5112b4..d60bfe2 100644
--- a/src/ProgressBar.js
+++ b/src/ProgressBar.js
@@ -4,61 +4,59 @@
import React from 'react';
-import { Animated, StyleSheet, View, Easing } from 'react-native';
-
-import Config from './Config';
+import { Animated, View, Easing } from 'react-native';
export class ProgressBar extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- progress: new Animated.Value(this.props.initialProgress || 0),
- };
- }
-
- componentDidUpdate(prevProps, prevState) {
- if (this.props.progress >= 0 && this.props.progress != prevProps.progress) {
- this.update();
- }
- }
-
- render() {
- const width = this.props.style.width || 300;
+ constructor(props) {
+ super(props);
- var fillWidth = this.state.progress.interpolate({
- inputRange: [0, 1],
- outputRange: [0, 1 * width],
- });
-
- return(
-
-
-
- );
- }
+ this.state = {
+ progress: new Animated.Value(this.props.initialProgress || 0),
+ };
+ }
- update() {
- Animated.timing(this.state.progress, {
- easing: Easing.inOut(Easing.ease),
- duration: 500,
- toValue: this.props.progress,
- }).start();
+ componentDidUpdate(prevProps, prevState) {
+ if (this.props.progress >= 0 && this.props.progress != prevProps.progress) {
+ this.update();
}
+ }
+
+ render() {
+ const width = this.props.style.width || 300;
+
+ var fillWidth = this.state.progress.interpolate({
+ inputRange: [0, 1],
+ outputRange: [0, 1 * width],
+ });
+
+ return (
+
+
+
+ );
+ }
+
+ update() {
+ Animated.timing(this.state.progress, {
+ easing: Easing.inOut(Easing.ease),
+ duration: 500,
+ toValue: this.props.progress,
+ }).start();
+ }
}
diff --git a/src/Recipients.js b/src/Recipients.js
index 20ff523..f10da26 100644
--- a/src/Recipients.js
+++ b/src/Recipients.js
@@ -4,35 +4,32 @@
import React from 'react';
import { checkText } from 'smile2emoji';
-import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
import {
- ActivityIndicator, Picker, Keyboard, KeyboardAvoidingView, View, Text, TextInput, ScrollView, FlatList, Platform, TouchableOpacity, Image
+ ActivityIndicator, Keyboard, KeyboardAvoidingView, View, Text, ScrollView, FlatList, Platform, TouchableOpacity, Image
} from 'react-native';
import {
- mediaDevices,
- RTCPeerConnection,
- RTCView,
- RTCIceCandidate,
- RTCSessionDescription,
- } from 'react-native-webrtc';
+ mediaDevices,
+ RTCPeerConnection,
+ RTCView,
+
+} from 'react-native-webrtc';
import { parse_sdp, expand_sdp_offer, expand_sdp_answer } from './SDPParser';
import {
- validateAddresses, WalletErrorCode, validatePaymentID,
+ validateAddresses, WalletErrorCode, validatePaymentID,
} from 'kryptokrona-wallet-backend-js';
import { Button as RNEButton, Alert } from 'react-native';
-import { Button, Input, Icon } from 'react-native-elements';
+import { Button, Icon } from 'react-native-elements';
import Config from './Config';
import ListItem from './ListItem';
-import List from './ListContainer';
-import { Styles, unread_counter_style, unread_counter_text_style } from './Styles';
+import { unread_counter_style, unread_counter_text_style } from './Styles';
import Moment from 'react-moment';
@@ -43,1636 +40,1532 @@ import 'moment/locale/zh-cn';
import 'moment/locale/nb';
import { Globals } from './Globals';
-import { Hr, BottomButton, CopyButton } from './SharedComponents';
+import { CopyButton } from './SharedComponents';
-import {intToRGB, hashCode, get_avatar, sendMessage} from './HuginUtilities';
+import { get_avatar, sendMessage } from './HuginUtilities';
-import {toastPopUp} from './Utilities';
+import { toastPopUp } from './Utilities';
-import { saveMessage, getMessages, getLatestMessages, removeMessage, markConversationAsRead, loadPayeeDataFromDatabase } from './Database';
+import { saveMessage, getMessages, removeMessage, markConversationAsRead, loadPayeeDataFromDatabase } from './Database';
import './i18n.js';
import { withTranslation } from 'react-i18next';
-import {AutoGrowingTextInput} from 'react-native-autogrow-textinput';
+import { AutoGrowingTextInput } from 'react-native-autogrow-textinput';
import CustomIcon from './CustomIcon.js'
+import { InputField, Button as ButtonComponent, TextField, ScreenLayout, ScreenHeader } from './components';
import InvertibleScrollView from 'react-native-invertible-scroll-view';
import InCallManager from 'react-native-incall-manager';
-String.prototype.hashCode = function() {
- var hash = 0;
- if (this.length == 0) {
- return hash;
- }
- for (var i = 0; i < this.length; i++) {
- var char = this.charCodeAt(i);
- hash = ((hash<<5)-hash)+char;
- hash = hash & hash; // Convert to 32bit integer
- }
+String.prototype.hashCode = function () {
+ var hash = 0;
+ if (this.length == 0) {
return hash;
+ }
+ for (var i = 0; i < this.length; i++) {
+ var char = this.charCodeAt(i);
+ hash = ((hash << 5) - hash) + char;
+ hash = hash & hash; // Convert to 32bit integer
+ }
+ return hash;
}
export class RecipientsScreenNoTranslation extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- payees: Globals.payees.filter(item => item.paymentID.length > 0),
- index: 0,
- }
+ constructor(props) {
+ super(props);
- Globals.updatePayeeFunctions.push(() => {
- this.setState(prevState => ({
- payees: Globals.payees.filter(item => item.paymentID.length > 0),
- index: prevState.index + 1,
- }))
- });
+ this.state = {
+ payees: Globals.payees.filter(item => item.paymentID.length > 0),
+ index: 0,
}
- render() {
- const { t } = this.props;
- let payees = this.state.payees;
- let uniquePayees = [];
- payees.forEach((element) => {
- if (!uniquePayees.includes(element)) {
- uniquePayees.push(element);
- }
- });
- payees = uniquePayees;
- const noPayeesComponent =
-
+ Globals.updatePayeeFunctions.push(() => {
+ this.setState(prevState => ({
+ payees: Globals.payees.filter(item => item.paymentID.length > 0),
+ index: prevState.index + 1,
+ }))
+ });
+ }
-
- {t('emptyAddressBook')}
-
- ;
-
- const newMessageIndicator =
- ;
-
- const addressBookComponent =
-
- item.nickname}
- renderItem={({item}) => (
- {item.lastMessage}{"\n"}{item.lastMessageTimestamp/1000} : t('noMessages')}
- subtitleStyle={{
- fontFamily: "Montserrat-Regular"
- }}
- chevron={item.read == '1' ? false : {item.unreads} }
- leftIcon={
-
- //
- //
- // {item.nickname[0].toUpperCase()}
- //
- //
- //
- }
- rightIcon={
- Globals.calls.find(call => call.contact == item.paymentID) ?
-
- {
- this.props.navigation.navigate(
- 'CallScreen', {
- payee: item,
- // sdp: 'wtfdoe'
- }
- );
- }} style={{ textAlign: 'right', textTransform: 'uppercase', fontSize: 12, color: this.props.screenProps.theme.backgroundColour, fontFamily: 'Montserrat-SemiBold' }}>
- {t('inCall')}
-
-
- :
- <>>
- }
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontFamily: 'Montserrat-SemiBold'
- }}showsVerticalScrollIndicator={false}
- subtitleStyle={{
- color: this.props.screenProps.theme.slightlyMoreVisibleColour,
- fontFamily: 'Montserrat-Regular'
- }}
- onPress={async () => {
- this.props.navigation.navigate(
- 'ChatScreen', {
- payee: item,
- }
- );
- await markConversationAsRead(item.address);
- Globals.payees = await loadPayeeDataFromDatabase();
- this.setState({
- payees: Globals.payees.filter(item => item.paymentID.length > 0)
- });
- }}
- />
- )}
- />
- ;
-
- return(
-
-
+ render() {
+ const { t } = this.props;
+ let payees = this.state.payees;
+ let uniquePayees = [];
+ payees.forEach((element) => {
+ if (!uniquePayees.includes(element)) {
+ uniquePayees.push(element);
+ }
+ });
+ payees = uniquePayees;
+ const noPayeesComponent =
+
+
+ {t('emptyAddressBook')}
+
+ ;
+
+ const newMessageIndicator =
+ ;
+
+ const addressBookComponent =
+
+ item.nickname}
+ renderItem={({ item }) => (
+ {item.lastMessage}{"\n"}{item.lastMessageTimestamp / 1000} : t('noMessages')}
+ subtitleStyle={{
+ fontFamily: "Montserrat-Regular",
+ color: this.props.screenProps.theme.slightlyMoreVisibleColour,
+ }}
+ chevron={item.read == '1' ? false : {item.unreads}}
+ leftIcon={
+
+ //
+ //
+ // {item.nickname[0].toUpperCase()}
+ //
+ //
+ //
+ }
+ rightIcon={
+ Globals.calls.find(call => call.contact == item.paymentID) ?
+
+ {
+ this.props.navigation.navigate(
+ 'CallScreen', {
+ payee: item,
+ // sdp: 'wtfdoe'
+ }
+ );
+ }} style={{ textAlign: 'right', textTransform: 'uppercase', fontSize: 12, color: this.props.screenProps.theme.backgroundColour, fontFamily: 'Montserrat-SemiBold' }}>
+ {t('inCall')}
+
-
-
- {t('messagesTitle')}
-
-
-
-
- {
- Globals.fromChat = true;
- this.props.navigation.navigate('NewPayee', {
- finishFunction: (item) => {
- this.props.navigation.navigate(
- 'ChatScreen', {
- payee: item,
- });
- }
- })
- }}
- >
-
-
- {t('addNewRecipient')}
-
-
-
-
-
-
-
- {this.state.payees?.length > 0 ? addressBookComponent : noPayeesComponent}
-
-
-
-
- );
- }
+ :
+ <>>
+ }
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontFamily: 'Montserrat-SemiBold'
+ }}
+ showsVerticalScrollIndicator={false}
+ onPress={async () => {
+ this.props.navigation.navigate(
+ 'ChatScreen', {
+ payee: item,
+ }
+ );
+ await markConversationAsRead(item.address);
+ Globals.payees = await loadPayeeDataFromDatabase();
+ this.setState({
+ payees: Globals.payees.filter(item => item.paymentID.length > 0)
+ });
+ }}
+ />
+ )}
+ />
+ ;
+
+ return (
+
+
+ {t('messagesTitle')}
+
+
+ }
+ onPress={() => {
+ Globals.fromChat = true;
+ this.props.navigation.navigate('NewPayee', {
+ finishFunction: (item) => {
+ this.props.navigation.navigate(
+ 'ChatScreen', {
+ payee: item,
+ });
+ }
+ })
+ }}
+ >
+
+ {t('addNewRecipient')}
+
+
+
+
+ {this.state.payees?.length > 0 ? addressBookComponent : noPayeesComponent}
+
+
+ );
+ }
}
export const RecipientsScreen = withTranslation()(RecipientsScreenNoTranslation)
function isPaymentIDValid(paymentID) {
- let errorMessage = '';
+ let errorMessage = '';
- if (paymentID === '') {
- return [true, errorMessage];
- }
+ if (paymentID === '') {
+ return [true, errorMessage];
+ }
- if (paymentID === undefined || paymentID === null) {
- return [false, errorMessage];
- }
+ if (paymentID === undefined || paymentID === null) {
+ return [false, errorMessage];
+ }
- const paymentIDError = validatePaymentID(paymentID);
+ const paymentIDError = validatePaymentID(paymentID);
- if (paymentIDError.errorCode !== WalletErrorCode.SUCCESS) {
- errorMessage = paymentIDError.toString();
+ if (paymentIDError.errorCode !== WalletErrorCode.SUCCESS) {
+ errorMessage = paymentIDError.toString();
- return [false, errorMessage];
- }
+ return [false, errorMessage];
+ }
- return [true, errorMessage];
+ return [true, errorMessage];
}
class ModifyPaymentID extends React.Component {
- constructor(props) {
- super(props);
- }
+ constructor(props) {
+ super(props);
- render() {
- return(
- {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- }}
- errorMessage={this.props.error}
- editable={!this.props.disabled}
- placeholder={this.props.disabled ? 'Disabled when using an integrated address' : ''}
- />
- );
- }
+ }
+
+ render() {
+ return (
+ {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ }}
+ errorMessage={this.props.error}
+ editable={false}
+ placeholder={this.props.disabled ? 'Disabled when using an integrated address' : ''}
+ />
+ );
+ }
}
function isAddressValid(address) {
- let errorMessage = '';
+ let errorMessage = '';
- if (address === '' || address === undefined || address === null) {
- errorMessage = 'Address cannot be blank.';
- return [false, errorMessage];
- }
+ if (address === '' || address === undefined || address === null) {
+ errorMessage = 'Address cannot be blank.';
+ return [false, errorMessage];
+ }
- const addressError = validateAddresses([address], true, Config);
+ const addressError = validateAddresses([address], true, Config);
- if (addressError.errorCode !== WalletErrorCode.SUCCESS) {
- errorMessage = addressError.toString();
- return [false, errorMessage];
- }
+ if (addressError.errorCode !== WalletErrorCode.SUCCESS) {
+ errorMessage = addressError.toString();
+ return [false, errorMessage];
+ }
- return [true, errorMessage];
+ return [true, errorMessage];
}
class ModifyAddress extends React.Component {
- constructor(props) {
- super(props);
- }
+ constructor(props) {
+ super(props);
+ }
- render() {
- return(
- {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- }}
- errorMessage={this.props.error}
- />
- );
- }
+ render() {
+ return (
+ {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ }}
+ errorMessage={this.props.error}
+ />
+ );
+ }
}
function isNicknameValid(nickname, initialNickname) {
- let errorMessage = '';
+ let errorMessage = '';
- if (nickname === '' || nickname === undefined || nickname === null) {
- errorMessage = 'Name cannot be blank.';
- return [false, errorMessage];
- }
+ if (nickname === '' || nickname === undefined || nickname === null) {
+ errorMessage = 'Name cannot be blank.';
+ return [false, errorMessage];
+ }
- if (Globals.payees.some((payee) => payee.nickname === nickname) && nickname != initialNickname) {
- errorMessage = `A payee with the name ${nickname} already exists.`;
+ if (Globals.payees.some((payee) => payee.nickname === nickname) && nickname != initialNickname) {
+ errorMessage = `A payee with the name ${nickname} already exists.`;
- return [false, errorMessage];
- }
+ return [false, errorMessage];
+ }
- return [true, errorMessage];
+ return [true, errorMessage];
}
-class ModifyNickname extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- return(
- {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- }}
- errorMessage={this.props.error}
- />
- );
- }
-}
+// class ModifyNickname extends React.Component {
+// constructor(props) {
+// super(props);
+// }
+
+// render() {
+// return (
+// {
+// if (this.props.onChange) {
+// this.props.onChange(text);
+// }
+// }}
+// errorMessage={this.props.error}
+// />
+// );
+// }
+// }
export class ModifyPayeeScreenNoTranslation extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- const { address, nickname, paymentID } = this.props.navigation.state.params.payee;
+ const { address, nickname, paymentID } = this.props.navigation.state.params.payee;
- console.log(address, paymentID);
+ console.log(address, paymentID);
- this.state = {
- address,
- nickname,
- paymentID,
+ this.state = {
+ address,
+ nickname,
+ paymentID,
- initialAddress: address,
- initialNickname: nickname,
- initialPaymentID: paymentID,
+ initialAddress: address,
+ initialNickname: nickname,
+ initialPaymentID: paymentID,
- modifyAddress: false,
- modifyNickname: false,
- modifyPaymentID: false,
+ modifyAddress: false,
+ modifyNickname: false,
+ modifyPaymentID: false,
- newAddress: address,
- newNickname: nickname,
- newPaymentID: paymentID,
+ newAddress: address,
+ newNickname: nickname,
+ newPaymentID: paymentID,
- addressError: '',
- nicknameError: '',
- paymentIDError: '',
+ addressError: '',
+ nicknameError: '',
+ paymentIDError: '',
- paymentIDEnabled: address.length !== Config.integratedAddressLength,
+ paymentIDEnabled: address.length !== Config.integratedAddressLength,
- addressValid: true,
- nicknameValid: true,
- paymentIDValid: true,
- }
+ addressValid: true,
+ nicknameValid: true,
+ paymentIDValid: true,
}
+ }
- componentDidMount() {
- this.focusSubscription = this.props.navigation.addListener(
- 'willFocus',
- () => {
- const { address, nickname, paymentID } = Globals.payees.filter(payee => payee.address == this.state.address)[0];
- this.setState({
- nickname: nickname,
- address: address,
- paymentID: paymentID
- })
- }
- );
- }
+ componentDidMount() {
+ this.focusSubscription = this.props.navigation.addListener(
+ 'willFocus',
+ () => {
+ const { address, nickname, paymentID } = Globals.payees.filter(payee => payee.address == this.state.address)[0];
+ this.setState({
+ nickname: nickname,
+ address: address,
+ paymentID: paymentID
+ })
+ }
+ );
+ }
- render() {
- const { t } = this.props;
- return(
+ render() {
+ const { t } = this.props;
+ return (
+
+
+
+ {this.state.nickname + t('details')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
- {this.state.nickname + t('details')}
-
-
+
+ {t('name')}
+
+
+ {
+ this.setState({
+ modifyNickname: !this.state.modifyNickname,
+ });
+ }}
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontSize: 13
+ }}
+ type="clear"
+ />
+
+
+
+
+ {this.state.modifyNickname ?
+ {
+ const [valid, error] = isNicknameValid(text, this.state.initialNickname);
-
-
-
-
-
-
-
-
+ const shared = {
+ nickname: text,
+ nicknameError: error,
+ nicknameValid: valid,
+ };
-
+ if (valid) {
+ this.setState({
+ newNickname: text,
+ ...shared,
+ });
+ } else {
+ this.setState(shared);
+ }
+ }}
+ />
+ :
+
+ {this.state.nickname}
+
+ }
+
-
+
+
+
+ {t('address')}
+
+
+ {
+ this.setState({
+ modifyAddress: !this.state.modifyAddress,
+ });
+ }}
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontSize: 13
+ }}
+ type="clear"
+ />
+
+
+
+
+ {this.state.modifyAddress ?
+ {
+ const [valid, error] = isAddressValid(text);
-
-
-
-
- {t('name')}
-
-
- {
- this.setState({
- modifyNickname: !this.state.modifyNickname,
- });
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 13
- }}
- type="clear"
- />
-
-
-
-
- {this.state.modifyNickname ?
- {
- const [valid, error] = isNicknameValid(text, this.state.initialNickname);
-
- const shared = {
- nickname: text,
- nicknameError: error,
- nicknameValid: valid,
- };
-
- if (valid) {
- this.setState({
- newNickname: text,
- ...shared,
- });
- } else {
- this.setState(shared);
- }
- }}
- {...this.props}
- />
- :
-
- {this.state.nickname}
-
- }
-
-
-
-
-
- {t('address')}
-
-
- {
- this.setState({
- modifyAddress: !this.state.modifyAddress,
- });
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 13
- }}
- type="clear"
- />
-
-
-
-
- {this.state.modifyAddress ?
- {
- const [valid, error] = isAddressValid(text);
-
- const shared = {
- address: text,
- addressError: error,
- addressValid: valid,
-
- /* Disable and reset payment ID if integrated address */
- paymentID: text.length === Config.integratedAddressLength ? '' : this.state.paymentID,
- paymentIDError: text.length === Config.integratedAddressLength ? '' : this.state.paymentIDError,
- paymentIDValid: text.length === Config.integratedAddressLength ? true : this.state.paymentIDValid,
- paymentIDEnabled: text.length !== Config.integratedAddressLength,
- };
-
- if (valid) {
- this.setState({
- newAddress: text,
- ...shared,
- });
- } else {
- this.setState(shared);
- }
- }}
- {...this.props}
- />
- :
-
- {this.state.address}
-
- }
-
-
-
-
-
- {t('messageKey')}
-
-
- {
- this.setState({
- modifyPaymentID: !this.state.modifyPaymentID,
- });
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 13,
- }}
- type="clear"
- />
-
-
-
-
- {this.state.modifyPaymentID ?
- {
- const [valid, error] = isPaymentIDValid(text);
-
- const shared = {
- paymentID: text,
- paymentIDError: error,
- paymentIDValid: valid,
- };
-
- if (valid) {
- this.setState({
- newPaymentID: text,
- ...shared,
- });
- } else {
- this.setState(shared);
- }
- }}
- disabled={!this.state.paymentIDEnabled}
- {...this.props}
- />
- :
-
- {this.state.paymentID || 'None'}
-
- }
-
-
+ const shared = {
+ address: text,
+ addressError: error,
+ addressValid: valid,
-
-
- {
- Globals.removePayee(this.state.initialNickname, false);
-
- Globals.addPayee({
- address: this.state.newAddress,
- nickname: this.state.newNickname,
- paymentID: this.state.newPaymentID,
- lastMessage: this.state.lastMessage,
- });
- this.setState({
- payees: Globals.payees
- });
- this.props.navigation.goBack();
- }}
- color={this.props.screenProps.theme.primaryColour}
- disabled={!this.state.addressValid || !this.state.nicknameValid || !this.state.paymentIDValid}
- />
-
-
+ /* Disable and reset payment ID if integrated address */
+ paymentID: text.length === Config.integratedAddressLength ? '' : this.state.paymentID,
+ paymentIDError: text.length === Config.integratedAddressLength ? '' : this.state.paymentIDError,
+ paymentIDValid: text.length === Config.integratedAddressLength ? true : this.state.paymentIDValid,
+ paymentIDEnabled: text.length !== Config.integratedAddressLength,
+ };
-
-
- {
- Alert.alert(
- t('remove'),
- t('removeWarning'),
- [
- { text: t('remove'), onPress: () => {
- Globals.removePayee(this.state.initialNickname, true);
- this.setState({
- payees: Globals.payees
- });
- this.props.navigation.pop(2);
- }},
- { text: t('cancel'), style: 'cancel'},
- ],
- );
- }}
- color='#DD3344'
- />
-
-
+ if (valid) {
+ this.setState({
+ newAddress: text,
+ ...shared,
+ });
+ } else {
+ this.setState(shared);
+ }
+ }}
+ />
+ :
+
+ {this.state.address}
+
+ }
+
+
+
+
+
+ {t('messageKey')}
+
+
+ {
+ this.setState({
+ modifyPaymentID: !this.state.modifyPaymentID,
+ });
+ }}
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontSize: 13,
+ }}
+ type="clear"
+ />
- );
- }
+
+
+
+ {this.state.modifyPaymentID ?
+ {
+ const [valid, error] = isPaymentIDValid(text);
+
+ const shared = {
+ paymentID: text,
+ paymentIDError: error,
+ paymentIDValid: valid,
+ };
+
+ if (valid) {
+ this.setState({
+ newPaymentID: text,
+ ...shared,
+ });
+ } else {
+ this.setState(shared);
+ }
+ }}
+ editable={this.state.paymentIDEnabled}
+ />
+ :
+
+ {this.state.paymentID || 'None'}
+
+ }
+
+
+
+
+
+ {
+ Globals.removePayee(this.state.initialNickname, false);
+
+ Globals.addPayee({
+ address: this.state.newAddress,
+ nickname: this.state.newNickname,
+ paymentID: this.state.newPaymentID,
+ lastMessage: this.state.lastMessage,
+ });
+ this.setState({
+ payees: Globals.payees
+ });
+ this.props.navigation.goBack();
+ }}
+ color={this.props.screenProps.theme.primaryColour}
+ disabled={!this.state.addressValid || !this.state.nicknameValid || !this.state.paymentIDValid}
+ />
+
+
+
+
+
+ {
+ Alert.alert(
+ t('remove'),
+ t('removeWarning'),
+ [
+ {
+ text: t('remove'), onPress: () => {
+ Globals.removePayee(this.state.initialNickname, true);
+ this.setState({
+ payees: Globals.payees
+ });
+ this.props.navigation.pop(2);
+ }
+ },
+ { text: t('cancel'), style: 'cancel' },
+ ],
+ );
+ }}
+ color='#DD3344'
+ />
+
+
+
+ );
+ }
}
export const ModifyPayeeScreen = withTranslation()(ModifyPayeeScreenNoTranslation)
export class ChatScreenNoTranslation extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- const { address, nickname, paymentID } = this.props.navigation.state.params.payee;
+ const { address, nickname, paymentID } = this.props.navigation.state.params.payee;
- this.state = {
- address,
- nickname,
- paymentID,
+ this.state = {
+ address,
+ nickname,
+ paymentID,
- initialAddress: address,
- initialNickname: nickname,
- initialPaymentID: paymentID,
+ initialAddress: address,
+ initialNickname: nickname,
+ initialPaymentID: paymentID,
- modifyAddress: false,
- modifyNickname: false,
- modifyPaymentID: false,
+ modifyAddress: false,
+ modifyNickname: false,
+ modifyPaymentID: false,
- newAddress: address,
- newNickname: nickname,
- newPaymentID: paymentID,
+ newAddress: address,
+ newNickname: nickname,
+ newPaymentID: paymentID,
- addressError: '',
- nicknameError: '',
- paymentIDError: '',
+ addressError: '',
+ nicknameError: '',
+ paymentIDError: '',
- paymentIDEnabled: address.length !== Config.integratedAddressLength,
- input: React.createRef(),
- addressValid: true,
- nicknameValid: true,
- paymentIDValid: true,
+ paymentIDEnabled: address.length !== Config.integratedAddressLength,
+ input: React.createRef(),
+ addressValid: true,
+ nicknameValid: true,
+ paymentIDValid: true,
- messages: [],
- message: "",
- messageHasLength: false,
+ messages: [],
+ message: "",
+ messageHasLength: false,
- }
+ }
- Globals.updateChatFunctions.push(async () => {
- this.setState({
- messages: await getMessages(this.state.address)
- })
- });
+ Globals.updateChatFunctions.push(async () => {
+ this.setState({
+ messages: await getMessages(this.state.address)
+ })
+ });
- }
+ }
- async componentDidMount() {
+ async componentDidMount() {
- const messages = await getMessages(this.state.address);
- markConversationAsRead(this.state.address);
+ const messages = await getMessages(this.state.address);
+ markConversationAsRead(this.state.address);
- console.log('messages', messages);
+ console.log('messages', messages);
- this.setState({
- messages: messages
- });
+ this.setState({
+ messages: messages
+ });
+
+ Globals.activeChat = this.state.address;
+ this.focusSubscription = this.props.navigation.addListener(
+ 'willFocus',
+ () => {
+ markConversationAsRead(this.state.address);
Globals.activeChat = this.state.address;
+ const { address, nickname, paymentID } = Globals.payees.filter(payee => payee.address == this.state.address)[0];
+ this.setState({
+ nickname: nickname,
+ address: address,
+ paymentID: paymentID
+ })
+ }
+ );
- this.focusSubscription = this.props.navigation.addListener(
- 'willFocus',
- () => {
- markConversationAsRead(this.state.address);
- Globals.activeChat = this.state.address;
- const { address, nickname, paymentID } = Globals.payees.filter(payee => payee.address == this.state.address)[0];
- this.setState({
- nickname: nickname,
- address: address,
- paymentID: paymentID
- })
- }
- );
+ this.blurSubscription = this.props.navigation.addListener(
+ 'willBlur',
+ () => {
+ Globals.activeChat = '';
+ }
+ );
- this.blurSubscription = this.props.navigation.addListener(
- 'willBlur',
- () => {
- Globals.activeChat = '';
- }
- );
+ }
- }
+ async componentWillUnmount() {
- async componentWillUnmount() {
+ Globals.activeChat = '';
+ this.focusSubscription();
- Globals.activeChat = '';
- this.focusSubscription();
+ }
- }
+ render() {
- render() {
+ const { t } = this.props;
- const { t } = this.props;
+ const submitMessage = async (text) => {
- const submitMessage = async (text) => {
+ Keyboard.dismiss();
+ this.state.input.current._textInput.clear();
- Keyboard.dismiss();
- this.state.input.current._textInput.clear();
+ this.setState({ messageHasLength: this.state.message.length > 0 });
- this.setState({messageHasLength: this.state.message.length > 0});
+ let temp_timestamp = Date.now();
- let temp_timestamp = Date.now();
+ await saveMessage(this.state.address, 'processing', text, temp_timestamp, 1);
- await saveMessage(this.state.address, 'processing', text, temp_timestamp, 1);
+ let updated_messages = await getMessages(this.state.address);
+ if (!updated_messages) {
+ updated_messages = [];
+ }
- let updated_messages = await getMessages(this.state.address);
- if (!updated_messages) {
- updated_messages = [];
- }
+ this.setState({
+ messages: updated_messages,
+ messageHasLength: false
+ });
+ this.scrollView.scrollTo({ y: 0, animated: true });
+ await sendMessage(checkText(text), this.state.address, this.state.paymentID, temp_timestamp);
+ this.scrollView.scrollTo({ y: 0, animated: true });
+ }
- this.setState({
- messages: updated_messages,
- messageHasLength: false
- });
- this.scrollView.scrollTo({y: 0, animated: true});
- await sendMessage(checkText(text), this.state.address, this.state.paymentID, temp_timestamp);
- this.scrollView.scrollTo({y: 0, animated: true});
- }
-
- const items = [];
-
- for (message in this.state.messages) {
- let timestamp = this.state.messages[message].timestamp / 1000;
- let this_timestamp = this.state.messages[message].timestamp;
- let this_message = this.state.messages[message].message;
- if (this.state.messages[message].type == 'received'){
- items.push({this.state.messages[message].message}{timestamp})
- } else {
- items.push(
-
-
- {this.state.messages[message].type == 'processing' && }
- {this.state.messages[message].type == 'failed' && {removeMessage(this_timestamp); submitMessage(this_message)}}>Message failed to send. Tap here to try again.}
-
- {this.state.messages[message].message}
-
-
- {timestamp}
-
- )
- }
+ const items = [];
+
+ for (message in this.state.messages) {
+ let timestamp = this.state.messages[message].timestamp / 1000;
+ let this_timestamp = this.state.messages[message].timestamp;
+ let this_message = this.state.messages[message].message;
+ if (this.state.messages[message].type == 'received') {
+ items.push({this.state.messages[message].message}{timestamp})
+ } else {
+ items.push(
+
+
+ {this.state.messages[message].type == 'processing' && }
+ {this.state.messages[message].type == 'failed' && { removeMessage(this_timestamp); submitMessage(this_message) }}>Message failed to send. Tap here to try again.}
+
+ {this.state.messages[message].message}
+
+
+ {timestamp}
+
+ )
+ }
- }
+ }
- return(
-
+ return (
+
-
-
-
-
- {
- this.props.navigation.navigate(
- 'ModifyPayee', {
- payee: this.props.navigation.state.params.payee,
- }
- );
- }} style={{ marginTop: 10, fontSize: 18, color: this.props.screenProps.theme.primaryColour, fontFamily: 'Montserrat-SemiBold' }}>
- {this.state.nickname}
-
-
-
- {
- this.props.navigation.navigate(
- 'CallScreen', {
- payee: this.props.navigation.state.params.payee,
- // sdp: 'wtfdoe'
- }
- );
- }} style={{ textAlign: 'right', textTransform: 'uppercase', fontSize: 12, color: this.props.screenProps.theme.backgroundColour, fontFamily: 'Montserrat-SemiBold' }}>
- {Globals.calls.find(call => call.contact == this.props.navigation.state.params.payee.paymentID) ? t('inCall') : t('call')}
-
-
-
-
-
-
+
+
+
+
+ {
+ this.props.navigation.navigate(
+ 'ModifyPayee', {
+ payee: this.props.navigation.state.params.payee,
+ }
+ );
+ }} style={{ fontSize: 18, color: this.props.screenProps.theme.primaryColour, fontFamily: 'Montserrat-SemiBold' }}>
+ {this.state.nickname}
+
+
+
+ {
+ this.props.navigation.navigate(
+ 'CallScreen', {
+ payee: this.props.navigation.state.params.payee,
+ // sdp: 'wtfdoe'
+ }
+ );
+ }} style={{ textAlign: 'right', textTransform: 'uppercase', fontSize: 12, color: this.props.screenProps.theme.backgroundColour, fontFamily: 'Montserrat-SemiBold' }}>
+ {Globals.calls.find(call => call.contact == this.props.navigation.state.params.payee.paymentID) ? t('inCall') : t('call')}
+
- {this.scrollView = ref}}
- >
-
-
-
- {items}
+
-
+
+
- {this.state.messages?.length > 0 && this.state.messages[0]?.count != this.state.messages?.length && this.state.messages[0]?.count > 25 && this.state.messages?.length > 24 &&
-
- { this.scrollView = ref }}
+ >
+
+
+ {items}
+
+
+ {this.state.messages?.length > 0 && this.state.messages[0]?.count != this.state.messages?.length && this.state.messages[0]?.count > 25 && this.state.messages?.length > 24 &&
+
+ {
- let updated_messages = await getMessages(this.state.address, this.state.messages?.length + 25);
- this.setState({
+ let updated_messages = await getMessages(this.state.address, this.state.messages?.length + 25);
+ this.setState({
messages: updated_messages,
messageHasLength: false
- });
+ });
}}>
-
-
- {t('loadMore')}
-
-
-
-
-
-
-
- }
-
+
+ {t('loadMore')}
+
-
+
+
-
-
- {
- e.preventDefault();
- // return;
- // submitMessage(this.state.message);
- // this.setState({message: '', messageHasLength: false});
- }}
- onChangeText={(text) => {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- this.state.message = text;
- this.setState({messageHasLength: this.state.message.length > 0});
- }}
- errorMessage={this.props.error}
- />
-
- {this.state.messageHasLength &&
- {
- submitMessage(this.state.message);
- this.setState({message: '', messageHasLength: false});
- }}
- titleStyle={{
+ }
- }}
- type="clear"
- />
+
+
+
+
+ {
+ e.preventDefault();
+ // return;
+ // submitMessage(this.state.message);
+ // this.setState({message: '', messageHasLength: false});
+ }}
+ onChangeText={(text) => {
+ if (this.props.onChange) {
+ this.props.onChange(text);
}
+ this.state.message = text;
+ this.setState({ messageHasLength: this.state.message.length > 0 });
+ }}
+ errorMessage={this.props.error}
+ />
+
+ {this.state.messageHasLength &&
+
+ {
+ submitMessage(this.state.message);
+ this.setState({ message: '', messageHasLength: false });
+ }}
+ titleStyle={{
+
+ }}
+ type="clear"
+ />
+ }
-
-
- );
- }
+
+
+
+ );
+ }
}
export const ChatScreen = withTranslation()(ChatScreenNoTranslation)
function startPeer() {
- const peer = new RTCPeerConnection( {
- iceServers: [
- {
+ const peer = new RTCPeerConnection({
+ iceServers: [
+ {
urls: [
- 'stun:stun1.l.google.com:19302',
- 'stun:global.stun.twilio.com:3478'
+ 'stun:stun1.l.google.com:19302',
+ 'stun:global.stun.twilio.com:3478'
]
- }
+ }
],
iceTransportPolicy: "all",
sdpSemantics: 'unified-plan',
trickle: false
- });
+ });
- return peer;
+ return peer;
}
async function initWebRTC(contactKey) {
- let isFront = false;
- let videoSourceId;
+ let isFront = false;
+ let videoSourceId;
- return new Promise((resolve, reject) => {
+ return new Promise((resolve, reject) => {
let new_peer;
let data_peer;
if (!Globals.stream) {
- mediaDevices.enumerateDevices().then(sourceInfos => {
+ mediaDevices.enumerateDevices().then(sourceInfos => {
- for (let i = 0; i < sourceInfos.length; i++) {
- const sourceInfo = sourceInfos[i];
- if (
- sourceInfo.kind == 'videoinput' &&
- sourceInfo.facing == (isFront ? 'user' : 'environment')
- ) {
- videoSourceId = sourceInfo.deviceId;
- }
- }
- });
+ for (let i = 0; i < sourceInfos.length; i++) {
+ const sourceInfo = sourceInfos[i];
+ if (
+ sourceInfo.kind == 'videoinput' &&
+ sourceInfo.facing == (isFront ? 'user' : 'environment')
+ ) {
+ videoSourceId = sourceInfo.deviceId;
+ }
+ }
+ });
- mediaDevices
+ mediaDevices
.getUserMedia({
- audio: {
+ audio: {
googNoiseSuppression: true
- },
- video: true,
+ },
+ video: true,
})
.then(stream => {
-
- Globals.stream = stream;
- Globals.localWebcamOn = true;
- Globals.localMicOn = true;
- new_peer = startPeer();
- data_peer = startPeer()
- new_peer.addStream(Globals.stream);
- Globals.calls.push({channel: data_peer, peer: new_peer, status: 'disconnected', contact: contactKey});
- resolve(true);
+
+ Globals.stream = stream;
+ Globals.localWebcamOn = true;
+ Globals.localMicOn = true;
+ new_peer = startPeer();
+ data_peer = startPeer()
+ new_peer.addStream(Globals.stream);
+ Globals.calls.push({ channel: data_peer, peer: new_peer, status: 'disconnected', contact: contactKey });
+ resolve(true);
})
.catch(error => {
- // Log error
- console.log(error);
- reject(false);
+ // Log error
+ console.log(error);
+ reject(false);
});
} else {
- new_peer = startPeer();
- data_peer = startPeer()
- new_peer.addStream(Globals.stream);
- Globals.calls.push({channel: data_peer, peer: new_peer, status: 'disconnected', contact: contactKey});
- resolve(true);
+ new_peer = startPeer();
+ data_peer = startPeer()
+ new_peer.addStream(Globals.stream);
+ Globals.calls.push({ channel: data_peer, peer: new_peer, status: 'disconnected', contact: contactKey });
+ resolve(true);
}
-});
+ });
}
export class CallScreenNoTranslation extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- const { address, nickname, paymentID } = this.props.navigation.state.params.payee;
+ const { address, nickname, paymentID } = this.props.navigation.state.params.payee;
- const sdp = this.props.navigation.state.params.sdp ? this.props.navigation.state.params.sdp : undefined;
- const activeCall = Globals.calls.find(call => call?.contact == paymentID);
- this.state = {
- address,
- nickname,
- paymentID,
- sdp,
- activeCall };
+ const sdp = this.props.navigation.state.params.sdp ? this.props.navigation.state.params.sdp : undefined;
+ const activeCall = Globals.calls.find(call => call?.contact == paymentID);
+ this.state = {
+ address,
+ nickname,
+ paymentID,
+ sdp,
+ activeCall
+ };
- }
+ }
- async componentDidMount() {
+ async componentDidMount() {
- if (!this.state.activeCall) {
- console.log('Initating WebRTC');
- const initiated = await initWebRTC(this.state.paymentID);
+ if (!this.state.activeCall) {
+ console.log('Initating WebRTC');
+ const initiated = await initWebRTC(this.state.paymentID);
- this.state.activeCall = Globals.calls.find(call => call.contact == this.state.paymentID);
+ this.state.activeCall = Globals.calls.find(call => call.contact == this.state.paymentID);
- if (initiated) {
- this.setState({stream: Globals.stream})
-
- console.log('set state!')
- this.state.activeCall.peer.onicecandidate = event => {
+ if (initiated) {
+ this.setState({ stream: Globals.stream })
- // Add event handlers for ice candidate event
-
- };
-
- } else {
- toastPopUp('Failed to start WebRTC');
- }
+ console.log('set state!')
+ this.state.activeCall.peer.onicecandidate = event => {
- } else {
+ // Add event handlers for ice candidate event
- this.setState(
- {
- callStatus: this.state.activeCall.status,
- remoteStream: this.state.activeCall.remoteStream,
- stream: Globals.stream,
- options: this.state.activeCall.options
- }
- );
+ };
- }
+ } else {
+ toastPopUp('Failed to start WebRTC');
+ }
+ } else {
- this.state.activeCall.peer.onaddstream = event => {
- // Got stream
- this.state.activeCall.remoteStream = event.stream;
- this.setState({remoteStream: event.stream});
- };
+ this.setState(
+ {
+ callStatus: this.state.activeCall.status,
+ remoteStream: this.state.activeCall.remoteStream,
+ stream: Globals.stream,
+ options: this.state.activeCall.options
+ }
+ );
- this.state.activeCall.peer.onconnectionstatechange = (ev) => {
+ }
- try {
- console.log('Connection change');
- this.state.activeCall.status = this.state.activeCall.peer.connectionState;
- this.setState({callStatus: this.state.activeCall.peer.connectionState});
+ this.state.activeCall.peer.onaddstream = event => {
+ // Got stream
+ this.state.activeCall.remoteStream = event.stream;
+ this.setState({ remoteStream: event.stream });
+ };
- if(this.state.activeCall.peer.connectionState == 'disconnected') {
- this.disconnectCall();
- }
- if(this.state.activeCall.peer.connectionState == 'connected') {
- InCallManager.stopRingback();
- }
- } catch (err) {
- this.disconnectCall();
- }
+ this.state.activeCall.peer.onconnectionstatechange = (ev) => {
- }
-
- // setup stream listening
+ try {
- let callStatus = this.state.activeCall.status;
+ console.log('Connection change');
+ this.state.activeCall.status = this.state.activeCall.peer.connectionState;
+ this.setState({ callStatus: this.state.activeCall.peer.connectionState });
- if (callStatus == 'new' || !callStatus) {
- callStatus = 'disconnected';
+ if (this.state.activeCall.peer.connectionState == 'disconnected') {
+ this.disconnectCall();
}
-
- if (this.state.sdp && callStatus == 'disconnected') {
- InCallManager.start({ media: 'audio/video', auto: true});
- InCallManager.startRingtone('_BUNDLE_');
+ if (this.state.activeCall.peer.connectionState == 'connected') {
+ InCallManager.stopRingback();
}
+ } catch (err) {
+ this.disconnectCall();
+ }
- const localWebcamOn = Globals.localWebcamOn;
+ }
- const localMicOn = Globals.localMicOn;
+ // setup stream listening
- const speakerOn = Globals.speakerOn;
+ let callStatus = this.state.activeCall.status;
- this.setState({selectedValue: 'video', callStatus: callStatus, localMicOn: localMicOn, localWebcamOn: localWebcamOn, speakerOn: speakerOn})
+ if (callStatus == 'new' || !callStatus) {
+ callStatus = 'disconnected';
+ }
+ if (this.state.sdp && callStatus == 'disconnected') {
+ InCallManager.start({ media: 'audio/video', auto: true });
+ InCallManager.startRingtone('_BUNDLE_');
}
- async componentWillUnmount() {
+ const localWebcamOn = Globals.localWebcamOn;
+ const localMicOn = Globals.localMicOn;
- if (this.state.callStatus == 'disconnected') {
- this.state.activeCall.peer.close();
+ const speakerOn = Globals.speakerOn;
- Globals.calls.splice(Globals.calls.indexOf(this.state.activeCall), 1);
+ this.setState({ selectedValue: 'video', callStatus: callStatus, localMicOn: localMicOn, localWebcamOn: localWebcamOn, speakerOn: speakerOn })
- if(!Globals.calls?.length) {
+ }
- Globals.stream.getTracks().forEach(function(track) {
- track.stop();
- });
- Globals.stream = false;
- }
+ async componentWillUnmount() {
- }
-
- }
+ if (this.state.callStatus == 'disconnected') {
+ this.state.activeCall.peer.close();
- async checkPeerIceState() {
+ Globals.calls.splice(Globals.calls.indexOf(this.state.activeCall), 1);
- await new Promise((resolve) => {
+ if (!Globals.calls?.length) {
- if (this.state.activeCall.peer.iceGatheringState === 'complete') {
- resolve();
- } else {
- this.state.activeCall.peer.addEventListener('icegatheringstatechange', () => {
- if (this.state.activeCall.peer.iceGatheringState === 'complete') {
- resolve();
- }
- });
- }
- });
+ Globals.stream.getTracks().forEach(function (track) {
+ track.stop();
+ });
+ Globals.stream = false;
+ }
}
- async signal(type, data) {
-
- let sessionDescription
- if (type === "new") {
- sessionDescription = await this.state.activeCall.peer.createOffer();
-
- } else if (type === "incoming") {
-
- await this.state.activeCall.peer.setRemoteDescription(data);
+ }
- sessionDescription = await this.state.activeCall.peer.createAnswer();
- }
-
- //Set local sdp
- await this.state.activeCall.peer.setLocalDescription(sessionDescription);
-
- await new Promise((resolve) => {
- if (this.state.activeCall.peer.iceGatheringState === 'complete') {
- resolve();
- } else {
- this.state.activeCall.peer.addEventListener('icegatheringstatechange', () => {
- if (this.state.activeCall.peer.iceGatheringState === 'complete') {
- resolve();
- }
- });
- }
- });
+ async checkPeerIceState() {
- //Set Answer/Offer
- if (type === "new") sessionDescription = await this.state.activeCall.peer.createOffer();
- if (type === "incoming") {
- await this.state.activeCall.peer.setRemoteDescription(data);
- sessionDescription = await this.state.activeCall.peer.createAnswer();
- }
+ await new Promise((resolve) => {
- let message = {
- type: sessionDescription.type,
- data: sessionDescription
- }
+ if (this.state.activeCall.peer.iceGatheringState === 'complete') {
+ resolve();
+ } else {
+ this.state.activeCall.peer.addEventListener('icegatheringstatechange', () => {
+ if (this.state.activeCall.peer.iceGatheringState === 'complete') {
+ resolve();
+ }
+ });
+ }
+ });
+
+ }
+
+ async signal(type, data) {
+
+ let sessionDescription
- this.sendDataMessage(message)
+ if (type === "new") {
+ sessionDescription = await this.state.activeCall.peer.createOffer();
+
+ } else if (type === "incoming") {
+
+ await this.state.activeCall.peer.setRemoteDescription(data);
+
+ sessionDescription = await this.state.activeCall.peer.createAnswer();
}
- async sendDataMessage(message) {
- this.state.dataChannel.send(JSON.stringify(message))
+ //Set local sdp
+ await this.state.activeCall.peer.setLocalDescription(sessionDescription);
+
+ await new Promise((resolve) => {
+ if (this.state.activeCall.peer.iceGatheringState === 'complete') {
+ resolve();
+ } else {
+ this.state.activeCall.peer.addEventListener('icegatheringstatechange', () => {
+ if (this.state.activeCall.peer.iceGatheringState === 'complete') {
+ resolve();
+ }
+ });
+ }
+ });
+
+ //Set Answer/Offer
+ if (type === "new") sessionDescription = await this.state.activeCall.peer.createOffer();
+ if (type === "incoming") {
+ await this.state.activeCall.peer.setRemoteDescription(data);
+ sessionDescription = await this.state.activeCall.peer.createAnswer();
}
- async dataMessage(data) {
- let message
- try {
- message = JSON.parse(data)
- } catch(err) {
- Globals.logger.addLogMessage('[DataChannel] Error parsing data channel message: ' + data);
- return
- }
- Globals.logger.addLogMessage('[DataChannel] incoming: ' + JSON.stringify(message));
- const incomingCall = this.checkIncomingCall(message)
- if (incomingCall) return
-
- //Here we can receive data messages etc..
+ let message = {
+ type: sessionDescription.type,
+ data: sessionDescription
}
- async checkIncomingCall(incoming) {
- if (incoming.type === "offer") {
- //Incoming offer
- this.signal("incoming", incoming.data)
-
- }else if (incoming.data.type === "renegotiate") {
- //Peer2 needs a new offer. Signal a new one
- this.signal("new", null)
- }
- else if (incoming.type === "answer") {
- //Got answer
- this.state.activeCall.peer.setRemoteDescription(incoming.data);
- } else {
- //Not SDP, probably a message
- return false
- }
+ this.sendDataMessage(message)
+ }
+
+ async sendDataMessage(message) {
+ this.state.dataChannel.send(JSON.stringify(message))
+ }
- return true
+ async dataMessage(data) {
+ let message
+ try {
+ message = JSON.parse(data)
+ } catch (err) {
+ Globals.logger.addLogMessage('[DataChannel] Error parsing data channel message: ' + data);
+ return
}
+ Globals.logger.addLogMessage('[DataChannel] incoming: ' + JSON.stringify(message));
+ const incomingCall = this.checkIncomingCall(message)
+ if (incomingCall) return
- async startCall() {
+ //Here we can receive data messages etc..
+ }
- InCallManager.start({ media: 'audio/video', auto: true, ringback: '_DTMF_'});
- InCallManager.setSpeakerphoneOn(this.state.speakerOn);
-
+ async checkIncomingCall(incoming) {
+ if (incoming.type === "offer") {
+ //Incoming offer
+ this.signal("incoming", incoming.data)
- this.state.activeCall.status = 'waiting';
- this.setState({callStatus: 'waiting'});
- let data_channel = await this.state.activeCall.peer.createDataChannel('HuginDataChannel');
- let channel = await this.state.activeCall.channel.createDataChannel('DataChannel');
- this.setState({dataChannel: channel});
+ } else if (incoming.data.type === "renegotiate") {
+ //Peer2 needs a new offer. Signal a new one
+ this.signal("new", null)
+ }
+ else if (incoming.type === "answer") {
+ //Got answer
+ this.state.activeCall.peer.setRemoteDescription(incoming.data);
+ } else {
+ //Not SDP, probably a message
+ return false
+ }
- channel.addEventListener("open", (event) => {
- //Create new offer to send via data channel
- this.signal("new", null)
- });
+ return true
+ }
- channel.addEventListener("message", (event) => {this.dataMessage(event.data)});
+ async startCall() {
- let sessionDescription = await this.state.activeCall.channel.createOffer();
-
- await this.state.activeCall.channel.setLocalDescription(sessionDescription);
+ InCallManager.start({ media: 'audio/video', auto: true, ringback: '_DTMF_' });
+ InCallManager.setSpeakerphoneOn(this.state.speakerOn);
- await new Promise((resolve) => {
- if (this.state.activeCall.channel.iceGatheringState === 'complete') {
- resolve();
- } else {
- this.state.activeCall.channel.addEventListener('icegatheringstatechange', () => {
- if (this.state.activeCall.channel.iceGatheringState === 'complete') {
- resolve();
- }
- });
- }
- });
-
- sessionDescription = await this.state.activeCall.channel.createOffer();
-
- Globals.logger.addLogMessage('[Calls] SDP generated: ' + sessionDescription.sdp);
-
- await this.state.activeCall.channel.setLocalDescription(sessionDescription);
-
- let parsed_sdp = parse_sdp(sessionDescription);
-
- let parsed_data = 'Δ' + parsed_sdp;
-
- const reparsed_sdp = expand_sdp_offer(parsed_data);
-
- console.log('Data channel sdp reparsed: ' + reparsed_sdp);
- let receiver = this.state.address;
-
- let messageKey = this.state.paymentID;
- const temp_timestamp = Date.now();
- await saveMessage(receiver, 'processing', 'Call started', temp_timestam, 1);
- const result = await sendMessage(parsed_data, receiver, messageKey, temp_timestamp);
- console.log(result);
- if (!result.success) {
- toastPopUp('Failed to send call! Check your balance and try again.');
- }
-
- }
- async answerCall() {
+ this.state.activeCall.status = 'waiting';
+ this.setState({ callStatus: 'waiting' });
+ let data_channel = await this.state.activeCall.peer.createDataChannel('HuginDataChannel');
+ let channel = await this.state.activeCall.channel.createDataChannel('DataChannel');
+ this.setState({ dataChannel: channel });
- InCallManager.stop();
- InCallManager.start({media: 'audio/video', ringback: '_DTMF_'});
- InCallManager.setSpeakerphoneOn(this.state.speakerOn);
+ channel.addEventListener("open", (event) => {
+ //Create new offer to send via data channel
+ this.signal("new", null)
+ });
+
+ channel.addEventListener("message", (event) => { this.dataMessage(event.data) });
- this.state.activeCall.status = 'connecting';
- this.setState({callStatus: 'connecting'});
-
-
- let channel = await this.state.activeCall.channel.createDataChannel('DataChannel');
- channel.addEventListener("message", (event) => {this.dataMessage(event.data)});
- this.setState({dataChannel: channel});
+ let sessionDescription = await this.state.activeCall.channel.createOffer();
- const parsed_sdp = expand_sdp_offer(this.state.sdp);
+ await this.state.activeCall.channel.setLocalDescription(sessionDescription);
- await this.state.activeCall.channel.setRemoteDescription(parsed_sdp);
-
- let answer = await this.state.activeCall.channel.createAnswer();
+ await new Promise((resolve) => {
+ if (this.state.activeCall.channel.iceGatheringState === 'complete') {
+ resolve();
+ } else {
+ this.state.activeCall.channel.addEventListener('icegatheringstatechange', () => {
+ if (this.state.activeCall.channel.iceGatheringState === 'complete') {
+ resolve();
+ }
+ });
+ }
+ });
- await this.state.activeCall.channel.setLocalDescription(answer);
+ sessionDescription = await this.state.activeCall.channel.createOffer();
- await new Promise((resolve) => {
+ Globals.logger.addLogMessage('[Calls] SDP generated: ' + sessionDescription.sdp);
- if (this.state.activeCall.channel.iceGatheringState === 'complete') {
- resolve();
- } else {
- this.state.activeCall.channel.addEventListener('icegatheringstatechange', () => {
- if (this.state.activeCall.channel.iceGatheringState === 'complete') {
- resolve();
- }
- });
- }
- });
+ await this.state.activeCall.channel.setLocalDescription(sessionDescription);
- await this.state.activeCall.channel.setRemoteDescription(parsed_sdp);
+ let parsed_sdp = parse_sdp(sessionDescription);
- answer = await this.state.activeCall.channel.createAnswer();
+ let parsed_data = 'Δ' + parsed_sdp;
- await this.state.activeCall.channel.setLocalDescription(answer);
+ const reparsed_sdp = expand_sdp_offer(parsed_data);
- Globals.logger.addLogMessage('[Calls] SDP generated: ' + answer.sdp);
+ console.log('Data channel sdp reparsed: ' + reparsed_sdp);
+ let receiver = this.state.address;
- const parsed_answer = 'δ' + parse_sdp(answer, true);
+ let messageKey = this.state.paymentID;
+ const temp_timestamp = Date.now();
+ await saveMessage(receiver, 'processing', 'Call started', temp_timestam, 1);
+ const result = await sendMessage(parsed_data, receiver, messageKey, temp_timestamp);
+ console.log(result);
+ if (!result.success) {
+ toastPopUp('Failed to send call! Check your balance and try again.');
+ }
- const reparsed_answer = expand_sdp_answer(parsed_answer);
+ }
- const receiver = this.state.address;
-
- const messageKey = this.state.paymentID;
+ async answerCall() {
- const temp_timestamp = Date.now();
- await saveMessage(receiver, 'processing', 'Call answered', temp_timestamp,1);
- const result = await sendMessage(parsed_answer, receiver, messageKey, temp_timestamp);
+ InCallManager.stop();
+ InCallManager.start({ media: 'audio/video', ringback: '_DTMF_' });
+ InCallManager.setSpeakerphoneOn(this.state.speakerOn);
- }
+ this.state.activeCall.status = 'connecting';
+ this.setState({ callStatus: 'connecting' });
- async disconnectCall() {
- const { t } = this.props;
+ let channel = await this.state.activeCall.channel.createDataChannel('DataChannel');
+ channel.addEventListener("message", (event) => { this.dataMessage(event.data) });
+ this.setState({ dataChannel: channel });
- InCallManager.stop();
+ const parsed_sdp = expand_sdp_offer(this.state.sdp);
- this.state.activeCall.peer.close();
+ await this.state.activeCall.channel.setRemoteDescription(parsed_sdp);
- this.state.activeCall.channel.close();
+ let answer = await this.state.activeCall.channel.createAnswer();
- this.setState({activeCall: null});
-
- this.props.navigation.goBack();
+ await this.state.activeCall.channel.setLocalDescription(answer);
- Globals.calls.splice(Globals.calls.indexOf(this.state.activeCall), 1);
- if(!Globals.calls.length) {
- Globals.stream.getTracks().forEach(function(track) {
- track.stop();
- });
- Globals.stream = false;
- }
- toastPopUp(t('callTerminated'))
+ await new Promise((resolve) => {
+
+ if (this.state.activeCall.channel.iceGatheringState === 'complete') {
+ resolve();
+ } else {
+ this.state.activeCall.channel.addEventListener('icegatheringstatechange', () => {
+ if (this.state.activeCall.channel.iceGatheringState === 'complete') {
+ resolve();
+ }
+ });
+ }
+ });
+
+ await this.state.activeCall.channel.setRemoteDescription(parsed_sdp);
+
+ answer = await this.state.activeCall.channel.createAnswer();
+
+ await this.state.activeCall.channel.setLocalDescription(answer);
+
+ Globals.logger.addLogMessage('[Calls] SDP generated: ' + answer.sdp);
+
+ const parsed_answer = 'δ' + parse_sdp(answer, true);
+
+ const reparsed_answer = expand_sdp_answer(parsed_answer);
+
+ const receiver = this.state.address;
+
+ const messageKey = this.state.paymentID;
+
+ const temp_timestamp = Date.now();
+ await saveMessage(receiver, 'processing', 'Call answered', temp_timestamp, 1);
+ const result = await sendMessage(parsed_answer, receiver, messageKey, temp_timestamp);
+
+ }
+
+ async disconnectCall() {
+
+ const { t } = this.props;
+
+ InCallManager.stop();
+ this.state.activeCall.peer.close();
+
+ this.state.activeCall.channel.close();
+
+ this.setState({ activeCall: null });
+
+ this.props.navigation.goBack();
+
+ Globals.calls.splice(Globals.calls.indexOf(this.state.activeCall), 1);
+ if (!Globals.calls.length) {
+ Globals.stream.getTracks().forEach(function (track) {
+ track.stop();
+ });
+ Globals.stream = false;
}
+ toastPopUp(t('callTerminated'))
- // Switch Camera
+ }
+
+ // Switch Camera
switchCamera() {
this.state.stream.getVideoTracks().forEach((track) => {
track._switchCamera();
@@ -1682,384 +1575,382 @@ export class CallScreenNoTranslation extends React.Component {
// Enable/Disable Camera
toggleCamera() {
this.state.localWebcamOn ? Globals.localWebcamOn = false : Globals.localWebcamOn = true;
- this.state.localWebcamOn ? this.setState({localWebcamOn: false}) : this.setState({localWebcamOn: true});
+ this.state.localWebcamOn ? this.setState({ localWebcamOn: false }) : this.setState({ localWebcamOn: true });
this.state.stream.getVideoTracks().forEach((track) => {
this.state.localWebcamOn ? (track.enabled = false) : (track.enabled = true);
});
}
// Enable/Disable Mic
- toggleMic() {
+ toggleMic() {
this.state.localMicOn ? Globals.localMicOn = false : Globals.localMicOn = true;
- this.state.localMicOn ? this.setState({localMicOn: false}) : this.setState({localMicOn: true});
+ this.state.localMicOn ? this.setState({ localMicOn: false }) : this.setState({ localMicOn: true });
this.state.stream.getAudioTracks().forEach((track) => {
- this.state.localMicOn ? (track.enabled = false) : (track.enabled = true);
+ this.state.localMicOn ? (track.enabled = false) : (track.enabled = true);
});
- }
+ }
- toggleSpeaker() {
- this.state.speakerOn ? InCallManager.setSpeakerphoneOn(false) : InCallManager.setSpeakerphoneOn(true);
- this.setState({speakerOn: !this.state.speakerOn});
- Globals.speakerOn = !Globals.speakerOn;
- this.state.speakerOn ? Globals.speakerOn = false : Globals.speakerOn = true;
- }
+ toggleSpeaker() {
+ this.state.speakerOn ? InCallManager.setSpeakerphoneOn(false) : InCallManager.setSpeakerphoneOn(true);
+ this.setState({ speakerOn: !this.state.speakerOn });
+ Globals.speakerOn = !Globals.speakerOn;
+ this.state.speakerOn ? Globals.speakerOn = false : Globals.speakerOn = true;
+ }
- // Switch Camera
+ // Switch Camera
switchCamera() {
this.state.stream.getVideoTracks().forEach((track) => {
track._switchCamera();
});
}
- render() {
+ render() {
- markConversationAsRead(this.state.address);
+ markConversationAsRead(this.state.address);
- const { t } = this.props;
+ const { t } = this.props;
- const items = [];
+ const items = [];
- const preCallStyleUser = {
- position: 'absolute',
- width: '100%',
- height: '100%',
- }
- const postCallStyleUser = {
- position: 'absolute',
- width: 150,
- height: 110,
- bottom: 90,
- left: '7.5%'
+ const preCallStyleUser = {
+ position: 'absolute',
+ width: '100%',
+ height: '100%',
+ }
+ const postCallStyleUser = {
+ position: 'absolute',
+ width: 150,
+ height: 110,
+ bottom: 90,
+ left: '7.5%'
+ }
+
+
+ for (message in this.state.messages) {
+ if (this.state.address == this.state.messages[message].conversation) {
+ let timestamp = this.state.messages[message].timestamp / 1000;
+ if (this.state.messages[message].type == 'received') {
+ items.push({this.state.messages[message].message}{timestamp})
+ } else {
+ items.push({this.state.messages[message].message}{timestamp})
}
-
- for (message in this.state.messages) {
- if (this.state.address == this.state.messages[message].conversation){
- let timestamp = this.state.messages[message].timestamp / 1000;
- if (this.state.messages[message].type == 'received'){
- items.push({this.state.messages[message].message}{timestamp})
- } else {
- items.push({this.state.messages[message].message}{timestamp})
- }
+ }
+ }
- }
- }
+ return (
+
- return(
+
+
+
+ {
+ this.props.navigation.navigate(
+ 'ModifyPayee', {
+ payee: this.props.navigation.state.params.payee,
+ }
+ );
+ }} style={{ fontSize: 18, color: this.props.screenProps.theme.primaryColour, fontFamily: 'Montserrat-SemiBold' }}>
+ {this.state.nickname}
+
+
+
+
+
+
+
+
+ {(this.state.callStatus != 'connected') &&
+
+
+
+ {this.state.stream && this.state.localWebcamOn &&
+
+ }
+ {Globals.preferences.nickname}
+
+ {(!this.state.localMicOn || !this.state.localWebcamOn) &&
+
+ {!this.state.localMicOn &&
+
+ }
+ {!this.state.localMicOn && !this.state.localWebcamOn &&
+
+ }
+ {!this.state.localWebcamOn &&
+
+ }
+
+ }
-
-
-
- {
- this.props.navigation.navigate(
- 'ModifyPayee', {
- payee: this.props.navigation.state.params.payee,
- }
- );
- }} style={{ fontSize: 18, color: this.props.screenProps.theme.primaryColour, fontFamily: 'Montserrat-SemiBold' }}>
- {this.state.nickname}
-
-
-
+
-
+ }
-
-
- {(this.state.callStatus != 'connected') &&
-
-
+ {this.state.callStatus == 'connected' &&
+ <>
+
- { this.state.stream && this.state.localWebcamOn &&
-
- }
-
- {Globals.preferences.nickname}
-
- {(!this.state.localMicOn || !this.state.localWebcamOn) &&
-
- {!this.state.localMicOn &&
-
- }
- {!this.state.localMicOn && !this.state.localWebcamOn &&
-
- }
- {!this.state.localWebcamOn &&
-
- }
-
- }
-
-
-
+ style={{ width: 150, height: 150, position: 'absolute', left: 75, top: 35 }}
+ source={{ uri: get_avatar(this.state.address, 150) }}
+ />
+ {this.state.remoteStream &&
+
}
-
- { this.state.callStatus == 'connected' &&
- <>
-
+ {this.state.nickname}
+
+
+
+
-
- { this.state.remoteStream &&
-
- }
-
- {this.state.nickname}
-
+ borderColor: '#252525',
+ }]
+ }>
+
+ {this.state.stream && this.state.localWebcamOn &&
+
+ }
+
+ {Globals.preferences.nickname}
+
+ {(!this.state.localMicOn || !this.state.localWebcamOn) &&
+
+ {!this.state.localMicOn &&
+
+ }
+ {!this.state.localMicOn && !this.state.localWebcamOn &&
+
+ }
+ {!this.state.localWebcamOn &&
+
+ }
+ }
-
-
- { this.state.stream && this.state.localWebcamOn &&
-
- }
-
- {Globals.preferences.nickname}
-
- {(!this.state.localMicOn || !this.state.localWebcamOn) &&
-
- {!this.state.localMicOn &&
-
- }
- {!this.state.localMicOn && !this.state.localWebcamOn &&
-
- }
- {!this.state.localWebcamOn &&
-
- }
-
- }
+
+ >
-
- >
-
}
-
+
{this.state.stream &&
-
-
- {this.state.localWebcamOn ?
- {this.toggleCamera()}}>
-
+
+
+ {this.state.localWebcamOn ?
+ { this.toggleCamera() }}>
+
- :
- {this.toggleCamera()}}>
-
+ :
+ { this.toggleCamera() }}>
+
- }
-
- {this.switchCamera()}}>
-
-
-
- {this.state.localMicOn ?
- {this.toggleMic()}}>
-
+ }
+
+ { this.switchCamera() }}>
+
+
+
+ {this.state.localMicOn ?
+ { this.toggleMic() }}>
+
- :
- {this.toggleMic()}}>
-
+ :
+ { this.toggleMic() }}>
+
- }
+ }
- {this.state.speakerOn ?
- { this.toggleSpeaker() }}>
-
+ {this.state.speakerOn ?
+ { this.toggleSpeaker() }}>
+
- :
- { this.toggleSpeaker() }}>
-
+ :
+ { this.toggleSpeaker() }}>
+
- }
-
- {this.state.callStatus == 'disconnected' && !this.state.sdp &&
- {this.startCall()}}>
-
-
-
+ }
+
+ {this.state.callStatus == 'disconnected' && !this.state.sdp &&
+ { this.startCall() }}>
+
- }
-
- { this.state.sdp && this.state.callStatus == 'disconnected' &&
- {this.answerCall()}}>
-
-
- }
-
- { this.state.callStatus != 'disconnected' && this.state.callStatus != 'failed' &&
-
- {this.disconnectCall()}}>
-
+ }
+
+ {this.state.sdp && this.state.callStatus == 'disconnected' &&
+ { this.answerCall() }}>
+
-
- }
-
-
+ }
+
+ {this.state.callStatus != 'disconnected' && this.state.callStatus != 'failed' &&
+
+ { this.disconnectCall() }}>
+
+
+
+ }
+
+
}
-
- { this.state.callStatus != 'connected' &&
-
- { this.state.sdp && this.state.callStatus == 'disconnected' &&
- {this.state.nickname + t('isCalling')}
- }
- { this.state.stream && !this.state.sdp && this.state.callStatus == 'disconnected' &&
- {t('tapToCall') + ' ' + this.state.nickname + '.'}
- }
- { !this.state.stream &&
- {t('noRecordAccess')}
- }
- { this.state.callStatus == 'waiting' &&
- <>{t('waitingForAnswer')}>
- }
- { this.state.callStatus == 'connecting' &&
- <>{t('connecting')}>
- }
- {/* { this.state.callStatus == 'connected' &&
+
+ {this.state.callStatus != 'connected' &&
+
+ {this.state.sdp && this.state.callStatus == 'disconnected' &&
+ {this.state.nickname + t('isCalling')}
+ }
+ {this.state.stream && !this.state.sdp && this.state.callStatus == 'disconnected' &&
+ {t('tapToCall') + ' ' + this.state.nickname + '.'}
+ }
+ {!this.state.stream &&
+ {t('noRecordAccess')}
+ }
+ {this.state.callStatus == 'waiting' &&
+ <>{t('waitingForAnswer')}>
+ }
+ {this.state.callStatus == 'connecting' &&
+ <>{t('connecting')}>
+ }
+ {/* { this.state.callStatus == 'connected' &&
{"Connected"}
} */}
- }
+ }
-
- );
- }
+
+ );
+ }
}
export const CallScreen = withTranslation()(CallScreenNoTranslation)
diff --git a/src/Recipients0.js b/src/Recipients0.js
index d931c76..5761759 100644
--- a/src/Recipients0.js
+++ b/src/Recipients0.js
@@ -7,11 +7,11 @@ import { checkText } from 'smile2emoji';
import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
import {
- View, Text, ScrollView, FlatList, Platform, TouchableWithoutFeedback, Image
+ View, Text, ScrollView, FlatList, TouchableWithoutFeedback, Image
} from 'react-native';
import {
- validateAddresses, WalletErrorCode, validatePaymentID,
+ validateAddresses, WalletErrorCode, validatePaymentID,
} from 'kryptokrona-wallet-backend-js';
import { Button as RNEButton, Alert } from 'react-native';
@@ -22,772 +22,758 @@ import Config from './Config';
import ListItem from './ListItem';
import List from './ListContainer';
-import { Styles } from './Styles';
import Moment from 'react-moment';
import { Globals } from './Globals';
-import { Hr, BottomButton, CopyButton } from './SharedComponents';
+import { CopyButton } from './SharedComponents';
-import {intToRGB, hashCode, get_avatar, sendMessage} from './HuginUtilities';
+import { get_avatar, sendMessage } from './HuginUtilities';
-import {toastPopUp} from './Utilities';
-import { saveToDatabase, getMessages } from './Database';
+import { getMessages } from './Database';
-String.prototype.hashCode = function() {
- var hash = 0;
- if (this.length == 0) {
- return hash;
- }
- for (var i = 0; i < this.length; i++) {
- var char = this.charCodeAt(i);
- hash = ((hash<<5)-hash)+char;
- hash = hash & hash; // Convert to 32bit integer
- }
+String.prototype.hashCode = function () {
+ var hash = 0;
+ if (this.length == 0) {
return hash;
+ }
+ for (var i = 0; i < this.length; i++) {
+ var char = this.charCodeAt(i);
+ hash = ((hash << 5) - hash) + char;
+ hash = hash & hash; // Convert to 32bit integer
+ }
+ return hash;
}
export class RecipientsScreen extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- payees: Globals.payees,
- index: 0,
- }
+ constructor(props) {
+ super(props);
- Globals.updatePayeeFunctions.push(() => {
- this.setState(prevState => ({
- payees: Globals.payees,
- index: prevState.index + 1,
- }))
- });
+ this.state = {
+ payees: Globals.payees,
+ index: 0,
}
- render() {
- const noPayeesComponent =
-
-
-
- Your address book is empty! Add a new recipient above to populate it.
-
- ;
-
-
- const addressBookComponent =
-
- item.nickname}
- renderItem={({item}) => (
-
- //
- //
- // {item.nickname[0].toUpperCase()}
- //
- //
- //
- }
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontFamily: 'Montserrat-SemiBold'
- }}
- subtitleStyle={{
- color: this.props.screenProps.theme.slightlyMoreVisibleColour,
- fontFamily: 'Montserrat-Regular'
- }}
- onPress={() => {
- this.props.navigation.navigate(
- 'ChatScreen', {
- payee: item,
- }
- );
- }}
- />
- )}
- />
-
;
-
- return(
+ Globals.updatePayeeFunctions.push(() => {
+ this.setState(prevState => ({
+ payees: Globals.payees,
+ index: prevState.index + 1,
+ }))
+ });
+ }
+
+ render() {
+ const noPayeesComponent =
+
+
+
+ Your address book is empty! Add a new recipient above to populate it.
+
+ ;
+
+
+ const addressBookComponent =
+
+ item.nickname}
+ renderItem={({ item }) => (
+
+ //
+ //
+ // {item.nickname[0].toUpperCase()}
+ //
+ //
+ //
+ }
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontFamily: 'Montserrat-SemiBold'
+ }}
+ subtitleStyle={{
+ color: this.props.screenProps.theme.slightlyMoreVisibleColour,
+ fontFamily: 'Montserrat-Regular'
+ }}
+ onPress={() => {
+ this.props.navigation.navigate(
+ 'ChatScreen', {
+ payee: item,
+ }
+ );
+ }}
+ />
+ )}
+ />
+
;
+
+ return (
+
+
+ {
+ this.props.navigation.navigate('NewPayee', {
+ finishFunction: () => {
+ this.props.navigation.navigate('Recipients');
+ }
+ })
+ }}
+ >
-
- {
- this.props.navigation.navigate('NewPayee', {
- finishFunction: () => {
- this.props.navigation.navigate('Recipients');
- }
- })
- }}
- >
-
-
-
-
-
-
- Add a new recipient
-
-
-
-
-
-
-
- Chats
-
-
- {this.state.payees.length > 0 ? addressBookComponent : noPayeesComponent}
-
-
-
+
+
+
+
+
+ Add a new recipient
+
- );
- }
+
+
+
+
+
+ Chats
+
+
+ {this.state.payees.length > 0 ? addressBookComponent : noPayeesComponent}
+
+
+
+
+ );
+ }
}
function isPaymentIDValid(paymentID) {
- let errorMessage = '';
+ let errorMessage = '';
- if (paymentID === '') {
- return [true, errorMessage];
- }
+ if (paymentID === '') {
+ return [true, errorMessage];
+ }
- if (paymentID === undefined || paymentID === null) {
- return [false, errorMessage];
- }
+ if (paymentID === undefined || paymentID === null) {
+ return [false, errorMessage];
+ }
- const paymentIDError = validatePaymentID(paymentID);
+ const paymentIDError = validatePaymentID(paymentID);
- if (paymentIDError.errorCode !== WalletErrorCode.SUCCESS) {
- errorMessage = paymentIDError.toString();
+ if (paymentIDError.errorCode !== WalletErrorCode.SUCCESS) {
+ errorMessage = paymentIDError.toString();
- return [false, errorMessage];
- }
+ return [false, errorMessage];
+ }
- return [true, errorMessage];
+ return [true, errorMessage];
}
class ModifyPaymentID extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- return(
- {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- }}
- errorMessage={this.props.error}
- editable={!this.props.disabled}
- placeholder={this.props.disabled ? 'Disabled when using an integrated address' : ''}
- />
- );
- }
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ return (
+ {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ }}
+ errorMessage={this.props.error}
+ editable={!this.props.disabled}
+ placeholder={this.props.disabled ? 'Disabled when using an integrated address' : ''}
+ />
+ );
+ }
}
function isAddressValid(address) {
- let errorMessage = '';
+ let errorMessage = '';
- if (address === '' || address === undefined || address === null) {
- errorMessage = 'Address cannot be blank.';
- return [false, errorMessage];
- }
+ if (address === '' || address === undefined || address === null) {
+ errorMessage = 'Address cannot be blank.';
+ return [false, errorMessage];
+ }
- const addressError = validateAddresses([address], true, Config);
+ const addressError = validateAddresses([address], true, Config);
- if (addressError.errorCode !== WalletErrorCode.SUCCESS) {
- errorMessage = addressError.toString();
- return [false, errorMessage];
- }
+ if (addressError.errorCode !== WalletErrorCode.SUCCESS) {
+ errorMessage = addressError.toString();
+ return [false, errorMessage];
+ }
- return [true, errorMessage];
+ return [true, errorMessage];
}
class ModifyAddress extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- return(
- {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- }}
- errorMessage={this.props.error}
- />
- );
- }
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ return (
+ {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ }}
+ errorMessage={this.props.error}
+ />
+ );
+ }
}
function isNicknameValid(nickname, initialNickname) {
- let errorMessage = '';
+ let errorMessage = '';
- if (nickname === '' || nickname === undefined || nickname === null) {
- errorMessage = 'Name cannot be blank.';
- return [false, errorMessage];
- }
+ if (nickname === '' || nickname === undefined || nickname === null) {
+ errorMessage = 'Name cannot be blank.';
+ return [false, errorMessage];
+ }
- if (Globals.payees.some((payee) => payee.nickname === nickname) && nickname != initialNickname) {
- errorMessage = `A payee with the name ${nickname} already exists.`;
+ if (Globals.payees.some((payee) => payee.nickname === nickname) && nickname != initialNickname) {
+ errorMessage = `A payee with the name ${nickname} already exists.`;
- return [false, errorMessage];
- }
+ return [false, errorMessage];
+ }
- return [true, errorMessage];
+ return [true, errorMessage];
}
class ModifyNickname extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- return(
- {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- }}
- errorMessage={this.props.error}
- />
- );
- }
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ return (
+ {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ }}
+ errorMessage={this.props.error}
+ />
+ );
+ }
}
export class ModifyPayeeScreen extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- const { address, nickname, paymentID } = this.props.navigation.state.params.payee;
+ const { address, nickname, paymentID } = this.props.navigation.state.params.payee;
- this.state = {
- address,
- nickname,
- paymentID,
+ this.state = {
+ address,
+ nickname,
+ paymentID,
- initialAddress: address,
- initialNickname: nickname,
- initialPaymentID: paymentID,
+ initialAddress: address,
+ initialNickname: nickname,
+ initialPaymentID: paymentID,
- modifyAddress: false,
- modifyNickname: false,
- modifyPaymentID: false,
+ modifyAddress: false,
+ modifyNickname: false,
+ modifyPaymentID: false,
- newAddress: address,
- newNickname: nickname,
- newPaymentID: paymentID,
+ newAddress: address,
+ newNickname: nickname,
+ newPaymentID: paymentID,
- addressError: '',
- nicknameError: '',
- paymentIDError: '',
+ addressError: '',
+ nicknameError: '',
+ paymentIDError: '',
- paymentIDEnabled: address.length !== Config.integratedAddressLength,
+ paymentIDEnabled: address.length !== Config.integratedAddressLength,
- addressValid: true,
- nicknameValid: true,
- paymentIDValid: true,
- }
+ addressValid: true,
+ nicknameValid: true,
+ paymentIDValid: true,
}
+ }
+
+ render() {
+ return (
+
+
+
+ {this.state.nickname}'s details
+
+
+
+
+
+
- render() {
- return(
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name
+
+
+ {
+ this.setState({
+ modifyNickname: !this.state.modifyNickname,
+ });
+ }}
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontSize: 13
+ }}
+ type="clear"
+ />
+
+
+
+
+ {this.state.modifyNickname ?
+ {
+ const [valid, error] = isNicknameValid(text, this.state.initialNickname);
+
+ const shared = {
+ nickname: text,
+ nicknameError: error,
+ nicknameValid: valid,
+ };
+
+ if (valid) {
+ this.setState({
+ newNickname: text,
+ ...shared,
+ });
+ } else {
+ this.setState(shared);
+ }
+ }}
+ {...this.props}
+ />
+ :
+
+ {this.state.nickname}
+
+ }
+
+
+
-
-
- {this.state.nickname}'s details
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Name
-
-
- {
- this.setState({
- modifyNickname: !this.state.modifyNickname,
- });
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 13
- }}
- type="clear"
- />
-
-
-
-
- {this.state.modifyNickname ?
- {
- const [valid, error] = isNicknameValid(text, this.state.initialNickname);
-
- const shared = {
- nickname: text,
- nicknameError: error,
- nicknameValid: valid,
- };
-
- if (valid) {
- this.setState({
- newNickname: text,
- ...shared,
- });
- } else {
- this.setState(shared);
- }
- }}
- {...this.props}
- />
- :
-
- {this.state.nickname}
-
- }
-
-
-
-
-
- Address
-
-
- {
- this.setState({
- modifyAddress: !this.state.modifyAddress,
- });
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 13
- }}
- type="clear"
- />
-
-
-
-
- {this.state.modifyAddress ?
- {
- const [valid, error] = isAddressValid(text);
-
- const shared = {
- address: text,
- addressError: error,
- addressValid: valid,
-
- /* Disable and reset payment ID if integrated address */
- paymentID: text.length === Config.integratedAddressLength ? '' : this.state.paymentID,
- paymentIDError: text.length === Config.integratedAddressLength ? '' : this.state.paymentIDError,
- paymentIDValid: text.length === Config.integratedAddressLength ? true : this.state.paymentIDValid,
- paymentIDEnabled: text.length !== Config.integratedAddressLength,
- };
-
- if (valid) {
- this.setState({
- newAddress: text,
- ...shared,
- });
- } else {
- this.setState(shared);
- }
- }}
- {...this.props}
- />
- :
-
- {this.state.address}
-
- }
-
-
-
-
-
- Payment ID
-
-
- {
- this.setState({
- modifyPaymentID: !this.state.modifyPaymentID,
- });
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 13,
- }}
- type="clear"
- />
-
-
-
-
- {this.state.modifyPaymentID ?
- {
- const [valid, error] = isPaymentIDValid(text);
-
- const shared = {
- paymentID: text,
- paymentIDError: error,
- paymentIDValid: valid,
- };
-
- if (valid) {
- this.setState({
- newPaymentID: text,
- ...shared,
- });
- } else {
- this.setState(shared);
- }
- }}
- disabled={!this.state.paymentIDEnabled}
- {...this.props}
- />
- :
-
- {this.state.paymentID || 'None'}
-
- }
-
-
-
-
-
- {
- Globals.removePayee(this.state.initialAddress, false);
-
- Globals.addPayee({
- address: this.state.newAddress,
- nickname: this.state.newNickname,
- paymentID: this.state.newPaymentID,
- lastMessage: this.state.lastMessage,
- });
- console.log(Globals.payees);
- this.setState({
- payees: Globals.payees
- });
- this.props.navigation.goBack();
- }}
- color={this.props.screenProps.theme.primaryColour}
- disabled={!this.state.addressValid || !this.state.nicknameValid || !this.state.paymentIDValid}
- />
-
-
-
-
-
- {
- Alert.alert(
- 'Delete Recipient?',
- 'Are you sure you want to delete this recipient?',
- [
- { text: 'Delete', onPress: () => {
- console.log('initialAddress', this.state.initialAddress);
- Globals.removePayee(this.state.initialAddress, true);
- this.props.navigation.pop(2);
- }},
- { text: 'Cancel', style: 'cancel'},
- ],
- );
- }}
- color='#DD3344'
- />
-
-
+
+ Address
+
+
+ {
+ this.setState({
+ modifyAddress: !this.state.modifyAddress,
+ });
+ }}
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontSize: 13
+ }}
+ type="clear"
+ />
- );
- }
+
+
+
+ {this.state.modifyAddress ?
+ {
+ const [valid, error] = isAddressValid(text);
+
+ const shared = {
+ address: text,
+ addressError: error,
+ addressValid: valid,
+
+ /* Disable and reset payment ID if integrated address */
+ paymentID: text.length === Config.integratedAddressLength ? '' : this.state.paymentID,
+ paymentIDError: text.length === Config.integratedAddressLength ? '' : this.state.paymentIDError,
+ paymentIDValid: text.length === Config.integratedAddressLength ? true : this.state.paymentIDValid,
+ paymentIDEnabled: text.length !== Config.integratedAddressLength,
+ };
+
+ if (valid) {
+ this.setState({
+ newAddress: text,
+ ...shared,
+ });
+ } else {
+ this.setState(shared);
+ }
+ }}
+ {...this.props}
+ />
+ :
+
+ {this.state.address}
+
+ }
+
+
+
+
+
+ Payment ID
+
+
+ {
+ this.setState({
+ modifyPaymentID: !this.state.modifyPaymentID,
+ });
+ }}
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontSize: 13,
+ }}
+ type="clear"
+ />
+
+
+
+
+ {this.state.modifyPaymentID ?
+ {
+ const [valid, error] = isPaymentIDValid(text);
+
+ const shared = {
+ paymentID: text,
+ paymentIDError: error,
+ paymentIDValid: valid,
+ };
+
+ if (valid) {
+ this.setState({
+ newPaymentID: text,
+ ...shared,
+ });
+ } else {
+ this.setState(shared);
+ }
+ }}
+ disabled={!this.state.paymentIDEnabled}
+ {...this.props}
+ />
+ :
+
+ {this.state.paymentID || 'None'}
+
+ }
+
+
+
+
+
+ {
+ Globals.removePayee(this.state.initialAddress, false);
+
+ Globals.addPayee({
+ address: this.state.newAddress,
+ nickname: this.state.newNickname,
+ paymentID: this.state.newPaymentID,
+ lastMessage: this.state.lastMessage,
+ });
+ console.log(Globals.payees);
+ this.setState({
+ payees: Globals.payees
+ });
+ this.props.navigation.goBack();
+ }}
+ color={this.props.screenProps.theme.primaryColour}
+ disabled={!this.state.addressValid || !this.state.nicknameValid || !this.state.paymentIDValid}
+ />
+
+
+
+
+
+ {
+ Alert.alert(
+ 'Delete Recipient?',
+ 'Are you sure you want to delete this recipient?',
+ [
+ {
+ text: 'Delete', onPress: () => {
+ console.log('initialAddress', this.state.initialAddress);
+ Globals.removePayee(this.state.initialAddress, true);
+ this.props.navigation.pop(2);
+ }
+ },
+ { text: 'Cancel', style: 'cancel' },
+ ],
+ );
+ }}
+ color='#DD3344'
+ />
+
+
+
+ );
+ }
}
//
// export class MessageBubble extends React.Component {
@@ -812,190 +798,190 @@ export class ModifyPayeeScreen extends React.Component {
export class ChatScreen extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- const { address, nickname, paymentID } = this.props.navigation.state.params.payee;
+ const { address, nickname, paymentID } = this.props.navigation.state.params.payee;
- this.state = {
- address,
- nickname,
- paymentID,
+ this.state = {
+ address,
+ nickname,
+ paymentID,
- initialAddress: address,
- initialNickname: nickname,
- initialPaymentID: paymentID,
+ initialAddress: address,
+ initialNickname: nickname,
+ initialPaymentID: paymentID,
- modifyAddress: false,
- modifyNickname: false,
- modifyPaymentID: false,
+ modifyAddress: false,
+ modifyNickname: false,
+ modifyPaymentID: false,
- newAddress: address,
- newNickname: nickname,
- newPaymentID: paymentID,
+ newAddress: address,
+ newNickname: nickname,
+ newPaymentID: paymentID,
- addressError: '',
- nicknameError: '',
- paymentIDError: '',
+ addressError: '',
+ nicknameError: '',
+ paymentIDError: '',
- paymentIDEnabled: address.length !== Config.integratedAddressLength,
- input: React.createRef(),
- addressValid: true,
- nicknameValid: true,
- paymentIDValid: true,
-
- messages: []
- }
-
-
- Globals.updateChatFunctions.push(() => {
- console.log('Updatemessages');
- this.setState({
- messages: Globals.messages
- })
- });
+ paymentIDEnabled: address.length !== Config.integratedAddressLength,
+ input: React.createRef(),
+ addressValid: true,
+ nicknameValid: true,
+ paymentIDValid: true,
+ messages: []
}
- async componentDidMount() {
-
- const messages = await getMessages();
- console.log(messages);
+ Globals.updateChatFunctions.push(() => {
+ console.log('Updatemessages');
+ this.setState({
+ messages: Globals.messages
+ })
+ });
- this.setState({
- messages: messages
- });
+ }
- }
+ async componentDidMount() {
- render() {
+ const messages = await getMessages();
- const items = [];
+ console.log(messages);
- for (message in this.state.messages) {
- if (this.state.address == this.state.messages[message].conversation){
- let timestamp = this.state.messages[message].timestamp / 1000;
- if (this.state.messages[message].type == 'received'){
- items.push({this.state.messages[message].message}{timestamp})
- } else {
- items.push({this.state.messages[message].message}{timestamp})
- }
+ this.setState({
+ messages: messages
+ });
- }
- }
+ }
+ render() {
- return(
-
+ const items = [];
-
-
-
- {
- Globals.logger.addLogMessage("pressed");
- this.props.navigation.navigate(
- 'ModifyPayee', {
- payee: this.props.navigation.state.params.payee,
- }
- );
- }} style={{ fontSize: 18, color: this.props.screenProps.theme.primaryColour, fontFamily: 'Montserrat-SemiBold' }}>
- {this.state.nickname}
-
-
-
-
-
-
-
-
- {this.scrollView = ref}}
- onContentSizeChange={() => this.scrollView.scrollToEnd({animated: true})}
- >
-
- {items}
-
-
-
-
-
- {
- // if (this.props.onChange) {
- // this.props.onChange(text);
- // }
- let text = e.nativeEvent.text;
- // toastPopUp('Sending message: ' + text + " to " + this.state.address + " with msg key " + this.state.paymentID);
- let success = await sendMessage(checkText(text), this.state.address, this.state.paymentID);
- if (success) {
- let updated_messages = await getMessages();
-
- this.setState({
- messages: updated_messages
- })
- this.state.input.current.clear();
- }
- }}
- onChangeText={(text) => {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- }}
- errorMessage={this.props.error}
- />
+ for (message in this.state.messages) {
+ if (this.state.address == this.state.messages[message].conversation) {
+ let timestamp = this.state.messages[message].timestamp / 1000;
+ if (this.state.messages[message].type == 'received') {
+ items.push({this.state.messages[message].message}{timestamp})
+ } else {
+ items.push({this.state.messages[message].message}{timestamp})
+ }
-
-
- );
+ }
}
+
+
+ return (
+
+
+
+
+
+ {
+ Globals.logger.addLogMessage("pressed");
+ this.props.navigation.navigate(
+ 'ModifyPayee', {
+ payee: this.props.navigation.state.params.payee,
+ }
+ );
+ }} style={{ fontSize: 18, color: this.props.screenProps.theme.primaryColour, fontFamily: 'Montserrat-SemiBold' }}>
+ {this.state.nickname}
+
+
+
+
+
+
+
+
+ { this.scrollView = ref }}
+ onContentSizeChange={() => this.scrollView.scrollToEnd({ animated: true })}
+ >
+
+ {items}
+
+
+
+
+
+ {
+ // if (this.props.onChange) {
+ // this.props.onChange(text);
+ // }
+ let text = e.nativeEvent.text;
+ // toastPopUp('Sending message: ' + text + " to " + this.state.address + " with msg key " + this.state.paymentID);
+ let success = await sendMessage(checkText(text), this.state.address, this.state.paymentID);
+ if (success) {
+ let updated_messages = await getMessages();
+
+ this.setState({
+ messages: updated_messages
+ })
+ this.state.input.current.clear();
+ }
+ }}
+ onChangeText={(text) => {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ }}
+ errorMessage={this.props.error}
+ />
+
+
+
+ );
+ }
}
diff --git a/src/SettingsScreen.js b/src/SettingsScreen.js
index 0425536..824553a 100644
--- a/src/SettingsScreen.js
+++ b/src/SettingsScreen.js
@@ -7,12 +7,10 @@ import * as Animatable from 'react-native-animatable';
import CustomIcon from './CustomIcon.js'
import React from 'react';
-import TextTicker from 'react-native-text-ticker';
import { optimizeMessages, getBestNode, getBestCache, resyncMessage24h } from './HuginUtilities';
import Entypo from 'react-native-vector-icons/Entypo';
import Ionicons from 'react-native-vector-icons/Ionicons';
import AntDesign from 'react-native-vector-icons/AntDesign';
-import FontAwesome from 'react-native-vector-icons/FontAwesome5';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
@@ -24,1915 +22,1790 @@ import fetch from './fetchWithTimeout'
import PushNotification from 'react-native-push-notification';
import {
- Button, View, FlatList, Alert, Text, Linking, ScrollView, Platform, NativeModules,
- AppState, RefreshControl, useColorScheme, Switch
+ Button, View, FlatList, Alert, Text, Linking, ScrollView, Platform, NativeModules,
+ AppState, RefreshControl, Switch
} from 'react-native';
import NetInfo from "@react-native-community/netinfo";
-import { prettyPrintAmount, Daemon, WalletErrorCode } from 'kryptokrona-wallet-backend-js';
+import { WalletErrorCode } from 'kryptokrona-wallet-backend-js';
import Config from './Config';
import ListItem from './ListItem';
import List from './ListContainer';
import Constants from './Constants';
-import { Styles } from './Styles';
import { Globals } from './Globals';
import { Authenticate } from './Authenticate';
import { SeedComponent, CopyButton } from './SharedComponents';
-import { savePreferencesToDatabase, setHaveWallet, emptyKnownTXs } from './Database';
+import { savePreferencesToDatabase, setHaveWallet } from './Database';
import {
- navigateWithDisabledBack, toastPopUp, getArrivalTime,
+ navigateWithDisabledBack, toastPopUp, getArrivalTime,
} from './Utilities';
+import { ScreenHeader, ScreenLayout } from './components';
export class FaqScreen extends React.Component {
- static navigationOptions = {
- title: 'FAQ',
- };
-
- constructor(props) {
- super(props);
- }
-
- render() {
- let arrivalTime = getArrivalTime(['minutes', 'seconds']);
- /* Chop the '!' off the end */
- arrivalTime = arrivalTime.substr(0, arrivalTime.length - 1);
-
- return (
-
-
-
- • Background Syncing
-
-
-
- The wallet does support background syncing, however, it may take some time before you notice this.{'\n\n'}
- Every 15 minutes, a background sync event is fired. (This is a limitation of the mobile platform){'\n\n'}
- After that, background syncing will continue for {Platform.OS === 'ios' ? '30 seconds' : '14 minutes'}, until the next background sync event is fired.{'\n\n'}
- However, depending upon your phone model, battery, and OS, these background syncs may occur later than expected, or not at all.{'\n\n'}
- To help the background syncing to fire a lot more regularly, ensure you have disabled doze mode.{' '}
- this.props.navigation.navigate('DisableDoze')}
- >
- Click this link
-
- {' '}for instructions on this.{'\n\n'}
- For further information, see{' '}
- Linking.openURL('https://dontkillmyapp.com/').catch((err) => Globals.logger.addLogMessage('Failed to open url: ' + err))}
- >
- https://dontkillmyapp.com/
-
-
-
-
- • Importing a wallet faster
-
-
-
- Sadly, phones are quite slow at syncing the blockchain, due to being less powerful than desktops.{'\n\n'}
- If you are wanting to import a wallet, there are a few ways we can speed this up.{'\n\n'}
- The easiest way is to sync your wallet on your PC, make a new wallet on your phone, and send all the funds to that wallet.{'\n\n'}
- If you want to keep the same address, then the process is a little more complicated.{'\n\n'}
- Send all your funds to yourself. You may need to optimize your wallet first, to do it all in one transaction.{'\n\n'}
- Note down the block height you sent the funds. Then, import your wallet, and choose 'Pick an exact block height' when importing.{'\n\n'}
- Finally, enter the block height that you sent all your funds to yourself. You should now see your full balance in your mobile wallet.
-
-
-
- • My balance disappeared
-
-
-
- If you can no longer see your balance or sync status, you probably accidentally tapped the QR code.{'\n\n'}
- Tap it again and your balance should reappear.{'\n\n'}
- This is intentional, so you can let someone scan your QR code, without revealing how much {Config.coinName} you have.
-
-
-
- • Why is my balance locked?
-
-
-
- When you send a transaction, part of your balance gets locked.{'\n\n'}
- This is because your balance is comprised of multiple 'chunks' of {Config.coinName}.{'\n\n'}
- It's similar to buying something with a $10 note, and getting back some change from the cashier.{'\n\n'}
- Don't worry, your balance should unlock once the transaction confirms. (Normally in {arrivalTime})
-
-
-
- • What is Auto Optimization?
-
-
-
- Auto Optimization, whenever necessary, sends fusion transactions, to keep your wallet optimized.
- As mentioned above, your wallet is comprised of multiple 'chunks' of {Config.coinName}.{'\n\n'}
- Optimizing combines the chunks into fewer, larger ones. This enables you to fit more funds in one transaction.{'\n\n'}
- This process will result in your balance occasionally being locked - this should only last for a few minutes
- while the fusion transactions get added to a block, depending on how unoptimized your wallet is.
-
-
-
-
- );
- }
+ static navigationOptions = {
+ title: 'FAQ',
+ };
+
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ let arrivalTime = getArrivalTime(['minutes', 'seconds']);
+ /* Chop the '!' off the end */
+ arrivalTime = arrivalTime.substr(0, arrivalTime.length - 1);
+
+ return (
+
+
+
+ • Background Syncing
+
+
+
+ The wallet does support background syncing, however, it may take some time before you notice this.{'\n\n'}
+ Every 15 minutes, a background sync event is fired. (This is a limitation of the mobile platform){'\n\n'}
+ After that, background syncing will continue for {Platform.OS === 'ios' ? '30 seconds' : '14 minutes'}, until the next background sync event is fired.{'\n\n'}
+ However, depending upon your phone model, battery, and OS, these background syncs may occur later than expected, or not at all.{'\n\n'}
+ To help the background syncing to fire a lot more regularly, ensure you have disabled doze mode.{' '}
+ this.props.navigation.navigate('DisableDoze')}
+ >
+ Click this link
+
+ {' '}for instructions on this.{'\n\n'}
+ For further information, see{' '}
+ Linking.openURL('https://dontkillmyapp.com/').catch((err) => Globals.logger.addLogMessage('Failed to open url: ' + err))}
+ >
+ https://dontkillmyapp.com/
+
+
+
+
+ • Importing a wallet faster
+
+
+
+ Sadly, phones are quite slow at syncing the blockchain, due to being less powerful than desktops.{'\n\n'}
+ If you are wanting to import a wallet, there are a few ways we can speed this up.{'\n\n'}
+ The easiest way is to sync your wallet on your PC, make a new wallet on your phone, and send all the funds to that wallet.{'\n\n'}
+ If you want to keep the same address, then the process is a little more complicated.{'\n\n'}
+ Send all your funds to yourself. You may need to optimize your wallet first, to do it all in one transaction.{'\n\n'}
+ Note down the block height you sent the funds. Then, import your wallet, and choose 'Pick an exact block height' when importing.{'\n\n'}
+ Finally, enter the block height that you sent all your funds to yourself. You should now see your full balance in your mobile wallet.
+
+
+
+ • My balance disappeared
+
+
+
+ If you can no longer see your balance or sync status, you probably accidentally tapped the QR code.{'\n\n'}
+ Tap it again and your balance should reappear.{'\n\n'}
+ This is intentional, so you can let someone scan your QR code, without revealing how much {Config.coinName} you have.
+
+
+
+ • Why is my balance locked?
+
+
+
+ When you send a transaction, part of your balance gets locked.{'\n\n'}
+ This is because your balance is comprised of multiple 'chunks' of {Config.coinName}.{'\n\n'}
+ It's similar to buying something with a $10 note, and getting back some change from the cashier.{'\n\n'}
+ Don't worry, your balance should unlock once the transaction confirms. (Normally in {arrivalTime})
+
+
+
+ • What is Auto Optimization?
+
+
+
+ Auto Optimization, whenever necessary, sends fusion transactions, to keep your wallet optimized.
+ As mentioned above, your wallet is comprised of multiple 'chunks' of {Config.coinName}.{'\n\n'}
+ Optimizing combines the chunks into fewer, larger ones. This enables you to fit more funds in one transaction.{'\n\n'}
+ This process will result in your balance occasionally being locked - this should only last for a few minutes
+ while the fusion transactions get added to a block, depending on how unoptimized your wallet is.
+
+
+
+
+ );
+ }
}
export class DisableDozeScreenNoTranslation extends React.Component {
- static navigationOptions = {
- title: 'Disable Doze',
- };
-
- constructor(props) {
- super(props);
-
- this.updateDozeStatus = this.updateDozeStatus.bind(this);
-
- this.state = {
- dozeDisabled: false
- }
- }
+ static navigationOptions = {
+ title: 'Disable Doze',
+ };
- async updateDozeStatus() {
- const dozeDisabled = await NativeModules.TurtleCoin.isDozeDisabled();
+ constructor(props) {
+ super(props);
- this.setState({
- dozeDisabled,
- });
- }
+ this.updateDozeStatus = this.updateDozeStatus.bind(this);
- componentDidMount() {
- this.updateDozeStatus();
- AppState.addEventListener('change', this.updateDozeStatus);
+ this.state = {
+ dozeDisabled: false
}
+ }
- render() {
- let arrivalTime = getArrivalTime(['minutes', 'seconds']);
- /* Chop the '!' off the end */
- arrivalTime = arrivalTime.substr(0, arrivalTime.length - 1);
-
- const { t } = this.props;
-
- return (
-
-
-
- {this.state.dozeDisabled
- ? t('dozeDisabled')
- : t('dozeEnabled')}
-
+ async updateDozeStatus() {
+ const dozeDisabled = await NativeModules.TurtleCoin.isDozeDisabled();
-
-
- {t('disableDozeText').replace(/{Config.appName}/g, Config.appName).replace(/{\n\n}/g, '\n\n')}
-
- NativeModules.TurtleCoin.navigateToBatteryOptimizationScreen()}
- >
- {t('openBatteryMenu')}
-
-
-
-
- );
- }
+ this.setState({
+ dozeDisabled,
+ });
+ }
+
+ componentDidMount() {
+ this.updateDozeStatus();
+ AppState.addEventListener('change', this.updateDozeStatus);
+ }
+
+ render() {
+ let arrivalTime = getArrivalTime(['minutes', 'seconds']);
+ /* Chop the '!' off the end */
+ arrivalTime = arrivalTime.substr(0, arrivalTime.length - 1);
+
+ const { t } = this.props;
+
+ return (
+
+
+
+ {this.state.dozeDisabled
+ ? t('dozeDisabled')
+ : t('dozeEnabled')}
+
+
+
+
+ {t('disableDozeText').replace(/{Config.appName}/g, Config.appName).replace(/{\n\n}/g, '\n\n')}
+
+ NativeModules.TurtleCoin.navigateToBatteryOptimizationScreen()}
+ >
+ {t('openBatteryMenu')}
+
+
+
+
+ );
+ }
}
export const DisableDozeScreen = withTranslation()(DisableDozeScreenNoTranslation)
export class LoggingScreen extends React.Component {
- static navigationOptions = {
- title: 'Logs',
- };
-
- constructor(props) {
- super(props);
-
- this.state = {
- logs: Globals.logger.getLogs(),
- }
- }
-
- tick() {
- this.setState({
- logs: Globals.logger.getLogs(),
- });
- }
+ static navigationOptions = {
+ title: 'Logs',
+ };
- componentDidMount() {
- this.interval = setInterval(() => this.tick(), 10000);
- }
+ constructor(props) {
+ super(props);
- componentWillUnmount() {
- clearInterval(this.interval);
+ this.state = {
+ logs: Globals.logger.getLogs(),
}
+ }
- render() {
- return (
-
- this.scrollView = ref}
- onContentSizeChange={(contentWidth, contentHeight) => {
- this.scrollView.scrollToEnd({ animated: true });
- }}
- style={{
- marginTop: 50,
- marginBottom: 100,
- marginHorizontal: 10,
- backgroundColor: this.props.screenProps.theme.backgroundColour,
- }}
- >
- {this.state.logs.map((value, index) => {
- return (
-
- {value}
-
- );
- })}
-
-
-
-
-
- );
- }
+ tick() {
+ this.setState({
+ logs: Globals.logger.getLogs(),
+ });
+ }
+
+ componentDidMount() {
+ this.interval = setInterval(() => this.tick(), 10000);
+ }
+
+ componentWillUnmount() {
+ clearInterval(this.interval);
+ }
+
+ render() {
+ return (
+
+ this.scrollView = ref}
+ onContentSizeChange={(contentWidth, contentHeight) => {
+ this.scrollView.scrollToEnd({ animated: true });
+ }}
+ style={{
+ marginTop: 50,
+ marginBottom: 100,
+ marginHorizontal: 10,
+ backgroundColor: this.props.screenProps.theme.backgroundColour,
+ }}
+ >
+ {this.state.logs.map((value, index) => {
+ return (
+
+ {value}
+
+ );
+ })}
+
+
+
+
+
+ );
+ }
}
export class ExportKeysScreen extends React.Component {
- static navigationOptions = {
- title: '',
- };
+ static navigationOptions = {
+ title: '',
+ };
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- const [privateSpendKey, privateViewKey] = Globals.wallet.getPrimaryAddressPrivateKeys();
+ const [privateSpendKey, privateViewKey] = Globals.wallet.getPrimaryAddressPrivateKeys();
- this.state = {
- privateSpendKey,
- privateViewKey,
- }
+ this.state = {
+ privateSpendKey,
+ privateViewKey,
}
+ }
- async componentDidMount() {
- const [mnemonicSeed, error] = await Globals.wallet.getMnemonicSeed();
+ async componentDidMount() {
+ const [mnemonicSeed, error] = await Globals.wallet.getMnemonicSeed();
- this.setState({
- mnemonicSeed,
- });
- }
-
- render() {
- const noSeedComponent =
-
- Your wallet isn't a mnemonic seed capable wallet. Not to worry though, your
- private keys will work just as well for restoring your wallet.
- ;
-
- const seedComponent =
- ;
-
- return (
+ this.setState({
+ mnemonicSeed,
+ });
+ }
+
+ render() {
+ const noSeedComponent =
+
+ Your wallet isn't a mnemonic seed capable wallet. Not to worry though, your
+ private keys will work just as well for restoring your wallet.
+ ;
+
+ const seedComponent =
+ ;
+
+ return (
+
+
+
+
+ Mnemonic Seed:
+
+
+ {this.state.mnemonicSeed === undefined ? noSeedComponent : seedComponent}
+
+
+
+
+ Private Spend Key:
+
-
-
-
- Mnemonic Seed:
-
-
- {this.state.mnemonicSeed === undefined ? noSeedComponent : seedComponent}
-
-
-
-
- Private Spend Key:
-
-
-
- {this.state.privateSpendKey}
-
+
+ {this.state.privateSpendKey}
+
-
+
-
-
-
-
-
-
- Private View Key:
-
-
-
- {this.state.privateViewKey}
-
+
+
+
+
+
+
+ Private View Key:
+
+
+
+ {this.state.privateViewKey}
+
-
+
-
+
-
-
-
- );
- }
+
+
+
+ );
+ }
}
export class SwapCurrencyScreen extends React.Component {
- static navigationOptions = {
- title: '',
- };
+ static navigationOptions = {
+ title: '',
+ };
+
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ return (
+
+
+ item.ticker}
+ renderItem={({ item }) => (
+
+
+ {item.symbol}
+
+
+ }
+ titleStyle={{
+ color: this.props.screenProps.theme.slightlyMoreVisibleColour,
+ }}
+ subtitleStyle={{
+ color: this.props.screenProps.theme.slightlyMoreVisibleColour,
+ }}
+ onPress={() => {
+ Globals.preferences.currency = item.ticker;
- constructor(props) {
- super(props);
- }
+ savePreferencesToDatabase(Globals.preferences);
- render() {
- return (
-
-
- item.ticker}
- renderItem={({ item }) => (
-
-
- {item.symbol}
-
-
- }
- titleStyle={{
- color: this.props.screenProps.theme.slightlyMoreVisibleColour,
- }}
- subtitleStyle={{
- color: this.props.screenProps.theme.slightlyMoreVisibleColour,
- }}
- onPress={() => {
- Globals.preferences.currency = item.ticker;
-
- savePreferencesToDatabase(Globals.preferences);
-
- /* Reset this stack to be on the settings screen */
- this.props.navigation.dispatch(navigateWithDisabledBack('Settings'));
-
- /* And go back to the main screen. */
- this.props.navigation.navigate('Main', { reloadBalance: true });
- }}
- />
- )}
- />
-
-
- );
- }
+ /* Reset this stack to be on the settings screen */
+ this.props.navigation.dispatch(navigateWithDisabledBack('Settings'));
+
+ /* And go back to the main screen. */
+ this.props.navigation.navigate('Main', { reloadBalance: true });
+ }}
+ />
+ )}
+ />
+
+
+ );
+ }
}
export class SwapLanguageScreen extends React.Component {
- static navigationOptions = {
- title: 'Language',
- };
+ static navigationOptions = {
+ title: 'Language',
+ };
+
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ return (
+
+
+ item.langCode}
+ renderItem={({ item }) => (
+
+
+ {item.flag}
+
+
+ }
+ titleStyle={{
+ color: this.props.screenProps.theme.slightlyMoreVisibleColour,
+ }}
+ subtitleStyle={{
+ color: this.props.screenProps.theme.slightlyMoreVisibleColour,
+ }}
+ onPress={() => {
+ Globals.preferences.language = item.langCode;
- constructor(props) {
- super(props);
- }
+ savePreferencesToDatabase(Globals.preferences);
- render() {
- return (
-
-
- item.langCode}
- renderItem={({ item }) => (
-
-
- {item.flag}
-
-
- }
- titleStyle={{
- color: this.props.screenProps.theme.slightlyMoreVisibleColour,
- }}
- subtitleStyle={{
- color: this.props.screenProps.theme.slightlyMoreVisibleColour,
- }}
- onPress={() => {
- Globals.preferences.language = item.langCode;
-
- savePreferencesToDatabase(Globals.preferences);
-
- /* Reset this stack to be on the settings screen */
- this.props.navigation.dispatch(navigateWithDisabledBack('Settings'));
-
- /* And go back to the main screen. */
- this.props.navigation.navigate('Main', { reloadBalance: true });
- }}
- />
- )}
- />
-
-
- );
- }
+ /* Reset this stack to be on the settings screen */
+ this.props.navigation.dispatch(navigateWithDisabledBack('Settings'));
+
+ /* And go back to the main screen. */
+ this.props.navigation.navigate('Main', { reloadBalance: true });
+ }}
+ />
+ )}
+ />
+
+
+ );
+ }
}
class SwapNodeScreenNoTranslation extends React.Component {
- static navigationOptions = {
- title: 'Available Nodes'
- };
+ static navigationOptions = {
+ title: 'Available Nodes'
+ };
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- this.refresh = this.refresh.bind(this);
- this.swapNode = this.swapNode.bind(this);
+ this.refresh = this.refresh.bind(this);
+ this.swapNode = this.swapNode.bind(this);
- console.log('Globals.daemons', Globals.daemons);
+ console.log('Globals.daemons', Globals.daemons);
- this.state = {
- /* Sort by online nodes, then uptime (highest first), then fee
- * (lowest first), then name */
- nodes: Globals.daemons,
+ this.state = {
+ /* Sort by online nodes, then uptime (highest first), then fee
+ * (lowest first), then name */
+ nodes: Globals.daemons,
- selectedNode: Globals.preferences.node,
+ selectedNode: Globals.preferences.node,
- forceUpdate: 0,
+ forceUpdate: 0,
- refreshing: false
- };
- }
+ refreshing: false
+ };
+ }
- async refresh() {
- this.setState({
- refreshing: true,
- });
-
- await Globals.updateNodeList();
-
- // Create an array to store all fetch promises
- const fetchPromises = [];
-
- for (const node of Globals.daemons) {
- const nodeURL = `${node.ssl ? 'https://' : 'http://'}${node.url}:${node.port}/info`;
- const fetchPromise = fetch(nodeURL, { method: 'GET' })
- .then(response => {
- node.online = true;
- this.setState({
- nodes: Globals.daemons,
- forceUpdate: this.state.forceUpdate + 1,
- });
- })
- .catch(error => {
- // Handle errors here
- node.online = false;
- this.setState({
- nodes: Globals.daemons,
- forceUpdate: this.state.forceUpdate + 1,
- });
- });
- fetchPromises.push(fetchPromise);
- }
-
- // Wait for all fetch promises to resolve
- await Promise.all(fetchPromises);
-
- this.setState({
- refreshing: false,
+ async refresh() {
+ this.setState({
+ refreshing: true,
+ });
+
+ await Globals.updateNodeList();
+
+ // Create an array to store all fetch promises
+ const fetchPromises = [];
+
+ for (const node of Globals.daemons) {
+ const nodeURL = `${node.ssl ? 'https://' : 'http://'}${node.url}:${node.port}/info`;
+ const fetchPromise = fetch(nodeURL, { method: 'GET' })
+ .then(response => {
+ node.online = true;
+ this.setState({
+ nodes: Globals.daemons,
+ forceUpdate: this.state.forceUpdate + 1,
+ });
+ })
+ .catch(error => {
+ // Handle errors here
+ node.online = false;
+ this.setState({
nodes: Globals.daemons,
forceUpdate: this.state.forceUpdate + 1,
+ });
});
+ fetchPromises.push(fetchPromise);
}
- async swapNode(node) {
- toastPopUp(i18next.t('swappingNode'));
-
-
- Globals.preferences.node = node.url + ':' + node.port + ':' + node.ssl;
+ // Wait for all fetch promises to resolve
+ await Promise.all(fetchPromises);
- this.setState((prevState) => ({
- selectedNode: Globals.preferences.node,
- forceUpdate: prevState.forceUpdate + 1,
- }));
-
- savePreferencesToDatabase(Globals.preferences);
-
- await Globals.wallet.swapNode(Globals.getDaemon());
+ this.setState({
+ refreshing: false,
+ nodes: Globals.daemons,
+ forceUpdate: this.state.forceUpdate + 1,
+ });
+ }
+
+ async swapNode(node) {
+ toastPopUp(i18next.t('swappingNode'));
+
+
+ Globals.preferences.node = node.url + ':' + node.port + ':' + node.ssl;
+
+ this.setState((prevState) => ({
+ selectedNode: Globals.preferences.node,
+ forceUpdate: prevState.forceUpdate + 1,
+ }));
+
+ savePreferencesToDatabase(Globals.preferences);
+
+ await Globals.wallet.swapNode(Globals.getDaemon());
+
+ toastPopUp(i18next.t('nodeSwapped'));
+ }
+
+ render() {
+
+ const { t } = this.props;
+ return (
+
+
+ }
+ >
+
+
+
+ {t('useCustomNode')}
+
+
+ {t('customNodeFormat')}
+
+
+ {
+ // if (this.props.onChange) {
+ // this.props.onChange(text);
+ // }
+ let text = e.nativeEvent.text;
+ text = text.split(':');
+ let node = { url: text[0], port: text[1], ssl: text[2] };
+
+ this.swapNode(node);
+ // toastPopUp('Sending message: ' + text + " to " + this.state.address + " with msg key " + this.state.paymentID);
+ // let updated_messages = await getMessages();
+ // let temp_timestamp = Date.now();
+ // updated_messages.push({
+ // conversation: this.state.address,
+ // type: 'sent',
+ // message: checkText(text),
+ // timestamp: temp_timestamp
+ // });
+ //
+ // this.setState({
+ // messages: updated_messages
+ // })
+ // this.state.input.current.clear();
+ //
+ // let success = await sendMessage(checkText(text), this.state.address, this.state.paymentID);
+ // await removeMessage(temp_timestamp);
+ // if (success) {
+ // let updated_messages = await getMessages();
+ //
+ // this.setState({
+ // messages: updated_messages
+ // })
+ // // this.state.input.current.clear();
+ // }
+ }}
+ onChangeText={(text) => {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ }}
+ errorMessage={this.props.error}
+ />
+
+ {t('or')}
+
+
+ {
+ const best_node = await getBestNode();
+ console.log('getBestNode', best_node);
+ this.setState({
+ node: best_node,
+ });
+ this.swapNode(best_node);
+ }}
+ color={this.props.screenProps.theme.buttonColour}
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontSize: 13
+ }}
+ type="clear"
+ />
- toastPopUp(i18next.t('nodeSwapped'));
- }
+
- render() {
+ {this.state.nodes.length > 0 ?
- const { t } = this.props;
- return (
-
-
- }
- >
-
-
-
- {t('useCustomNode')}
-
-
- {t('customNodeFormat')}
-
-
- {
- // if (this.props.onChange) {
- // this.props.onChange(text);
- // }
- let text = e.nativeEvent.text;
- text = text.split(':');
- let node = { url: text[0], port: text[1], ssl: text[2] };
-
- this.swapNode(node);
- // toastPopUp('Sending message: ' + text + " to " + this.state.address + " with msg key " + this.state.paymentID);
- // let updated_messages = await getMessages();
- // let temp_timestamp = Date.now();
- // updated_messages.push({
- // conversation: this.state.address,
- // type: 'sent',
- // message: checkText(text),
- // timestamp: temp_timestamp
- // });
- //
- // this.setState({
- // messages: updated_messages
- // })
- // this.state.input.current.clear();
- //
- // let success = await sendMessage(checkText(text), this.state.address, this.state.paymentID);
- // await removeMessage(temp_timestamp);
- // if (success) {
- // let updated_messages = await getMessages();
- //
- // this.setState({
- // messages: updated_messages
- // })
- // // this.state.input.current.clear();
- // }
- }}
- onChangeText={(text) => {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- }}
- errorMessage={this.props.error}
- />
-
- {t('or')}
-
-
- {
- const best_node = await getBestNode();
- console.log('getBestNode', best_node);
- this.setState({
- node: best_node,
- });
- this.swapNode(best_node);
- }}
- color={this.props.screenProps.theme.buttonColour}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 13
- }}
- type="clear"
- />
-
-
-
- {this.state.nodes.length > 0 ?
-
-
-
- {t('pickNodeList')}
-
-
- {t('pullToCheck')}
-
- item.url + item.port}
- renderItem={({ item }) => (
-
-
:
-
-
- }
- titleStyle={{
- color: this.state.selectedNode === item.url + ':' + item.port + ":" + item.ssl
- ? this.props.screenProps.theme.primaryColour
- : this.props.screenProps.theme.slightlyMoreVisibleColour,
- }}
- subtitleStyle={{
- color: this.state.selectedNode === item.url + ':' + item.port + ":" + item.ssl
- ? this.props.screenProps.theme.primaryColour
- : this.props.screenProps.theme.slightlyMoreVisibleColour,
- }}
- onPress={async () => {
- if (!item.online) {
- Alert.alert(
- 'Use offline node?',
- 'Are you sure you want to attempt to connect to a node which is reporting as offline?',
- [
- {
- text: 'Yes', onPress: () => {
- this.swapNode(item);
- }
- },
- { text: 'Cancel', style: 'cancel' },
- ],
- );
- } else {
- this.swapNode(item);
- }
- }}
- />
- )}
- />
- :
+
+ {t('pickNodeList')}
+
+
+ {t('pullToCheck')}
+
+ item.url + item.port}
+ renderItem={({ item }) => (
+
+ :
-
- {t('noNodes')}
-
}
-
-
+ titleStyle={{
+ color: this.state.selectedNode === item.url + ':' + item.port + ":" + item.ssl
+ ? this.props.screenProps.theme.primaryColour
+ : this.props.screenProps.theme.slightlyMoreVisibleColour,
+ }}
+ subtitleStyle={{
+ color: this.state.selectedNode === item.url + ':' + item.port + ":" + item.ssl
+ ? this.props.screenProps.theme.primaryColour
+ : this.props.screenProps.theme.slightlyMoreVisibleColour,
+ }}
+ onPress={async () => {
+ if (!item.online) {
+ Alert.alert(
+ 'Use offline node?',
+ 'Are you sure you want to attempt to connect to a node which is reporting as offline?',
+ [
+ {
+ text: 'Yes', onPress: () => {
+ this.swapNode(item);
+ }
+ },
+ { text: 'Cancel', style: 'cancel' },
+ ],
+ );
+ } else {
+ this.swapNode(item);
+ }
+ }}
+ />
+ )}
+ />
+ :
+
+
+ {t('noNodes')}
+
- );
- }
+ }
+
+
+
+ );
+ }
}
export const SwapNodeScreen = withTranslation()(SwapNodeScreenNoTranslation)
class SwapAPIScreenNoTranslation extends React.Component {
- static navigationOptions = {
- title: 'Available APIs'
- };
+ static navigationOptions = {
+ title: 'Available APIs'
+ };
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- this.refresh = this.refresh.bind(this);
- this.swapAPI = this.swapAPI.bind(this);
+ this.refresh = this.refresh.bind(this);
+ this.swapAPI = this.swapAPI.bind(this);
- console.log(Globals.preferences.cache);
- console.log(Globals.preferences);
+ console.log(Globals.preferences.cache);
+ console.log(Globals.preferences);
- this.state = {
- /* Sort by online nodes, then uptime (highest first), then fee
- * (lowest first), then name */
- apis: Globals.caches,
+ this.state = {
+ /* Sort by online nodes, then uptime (highest first), then fee
+ * (lowest first), then name */
+ apis: Globals.caches,
- selectedAPI: Globals.preferences.cache ? Globals.preferences.cache : Config.defaultCache,
+ selectedAPI: Globals.preferences.cache ? Globals.preferences.cache : Config.defaultCache,
- forceUpdate: 0,
+ forceUpdate: 0,
- refreshing: false,
+ refreshing: false,
- enabled: Globals.preferences?.cacheEnabled == "true" ? true : false,
+ enabled: Globals.preferences?.cacheEnabled == "true" ? true : false,
- autoPickCache: Globals.preferences?.autoPickCache == "true" ? true : false,
+ autoPickCache: Globals.preferences?.autoPickCache == "true" ? true : false,
- websocketEnabled: Globals.preferences?.websocketEnabled == "true" ? true : false
+ websocketEnabled: Globals.preferences?.websocketEnabled == "true" ? true : false
- };
- }
+ };
+ }
- async componentDidMount() {
- await Globals.updateNodeList();
- this.setState({ apis: Globals.caches });
- console.log(this.state);
- }
+ async componentDidMount() {
+ await Globals.updateNodeList();
+ this.setState({ apis: Globals.caches });
+ console.log(this.state);
+ }
- async refresh() {
- this.setState({
- refreshing: true,
- });
-
- await Globals.updateNodeList();
-
- // Create an array to store all fetch promises
- const fetchPromises = [];
-
- for (api in Globals.caches) {
-
- let this_api = Globals.caches[api];
- let nodeURL = this_api.url + '/api/v1/info';;
- const fetchPromise = fetch(nodeURL, { method: 'GET' })
- .then(response => {
- this_api.online = true;
- this.setState({
- apis: Globals.caches,
- forceUpdate: this.state.forceUpdate + 1,
- });
- })
- .catch(error => {
- // Handle errors here
- this_api.online = false;
- this.setState({
- apis: Globals.caches,
- forceUpdate: this.state.forceUpdate + 1,
- });
- });
- fetchPromises.push(fetchPromise);
- }
-
- // Wait for all fetch promises to resolve
- await Promise.all(fetchPromises);
-
- this.setState({
- refreshing: false,
+ async refresh() {
+ this.setState({
+ refreshing: true,
+ });
+
+ await Globals.updateNodeList();
+
+ // Create an array to store all fetch promises
+ const fetchPromises = [];
+
+ for (api in Globals.caches) {
+
+ let this_api = Globals.caches[api];
+ let nodeURL = this_api.url + '/api/v1/info';;
+ const fetchPromise = fetch(nodeURL, { method: 'GET' })
+ .then(response => {
+ this_api.online = true;
+ this.setState({
+ apis: Globals.caches,
+ forceUpdate: this.state.forceUpdate + 1,
+ });
+ })
+ .catch(error => {
+ // Handle errors here
+ this_api.online = false;
+ this.setState({
apis: Globals.caches,
forceUpdate: this.state.forceUpdate + 1,
+ });
});
+ fetchPromises.push(fetchPromise);
}
- async swapAPI(node) {
- toastPopUp(i18next.t('swappingAPI'));
+ // Wait for all fetch promises to resolve
+ await Promise.all(fetchPromises);
+ this.setState({
+ refreshing: false,
+ apis: Globals.caches,
+ forceUpdate: this.state.forceUpdate + 1,
+ });
+ }
- Globals.preferences.cache = node.url;
+ async swapAPI(node) {
+ toastPopUp(i18next.t('swappingAPI'));
- this.setState((prevState) => ({
- selectedAPI: Globals.preferences.cache,
- forceUpdate: prevState.forceUpdate + 1,
- }));
- savePreferencesToDatabase(Globals.preferences);
+ Globals.preferences.cache = node.url;
- toastPopUp(i18next.t('APISwapped'));
- }
+ this.setState((prevState) => ({
+ selectedAPI: Globals.preferences.cache,
+ forceUpdate: prevState.forceUpdate + 1,
+ }));
- render() {
+ savePreferencesToDatabase(Globals.preferences);
- const { t } = this.props;
- return (
-
+ toastPopUp(i18next.t('APISwapped'));
+ }
-
-
- {
- this.setState({
- enabled: value
- });
- console.log(value);
- if (value) {
- Globals.preferences.cacheEnabled = 'true';
- } else {
- Globals.preferences.cacheEnabled = 'false';
- Globals.APIOnline = false;
- }
- savePreferencesToDatabase(Globals.preferences);
- }}
- style={{ marginRight: 15 }}
- />
-
- {t('enableAPI')}
-
-
+ render() {
+
+ const { t } = this.props;
+ return (
+
+
+
+ {
+ this.setState({
+ enabled: value
+ });
+ console.log(value);
+ if (value) {
+ Globals.preferences.cacheEnabled = 'true';
+ } else {
+ Globals.preferences.cacheEnabled = 'false';
+ Globals.APIOnline = false;
+ }
+ savePreferencesToDatabase(Globals.preferences);
+ }}
+ style={{ marginRight: 15 }}
+ />
+
+ {t('enableAPI')}
+
+
+
+ {this.state.enabled &&
+ <>
+
+
+ {
+ this.setState({
+ autoPickCache: value
+ });
+ console.log(value);
+ if (value) {
+ Globals.preferences.autoPickCache = 'true';
+ } else {
+ Globals.preferences.autoPickCache = 'false';
+ }
+ savePreferencesToDatabase(Globals.preferences);
+ }}
+ style={{ marginRight: 15 }}
+ />
+
+ {t('autoPickAPI')}
+
+
- {this.state.enabled &&
- <>
-
-
- {
- this.setState({
- autoPickCache: value
- });
- console.log(value);
- if (value) {
- Globals.preferences.autoPickCache = 'true';
- } else {
- Globals.preferences.autoPickCache = 'false';
- }
- savePreferencesToDatabase(Globals.preferences);
- }}
- style={{ marginRight: 15 }}
- />
-
- {t('autoPickAPI')}
-
-
+
+
+ {
+ this.setState({
+ websocketEnabled: value
+ });
+ console.log(value);
+ if (value) {
+ Globals.preferences.websocketEnabled = 'true';
+ } else {
+ Globals.preferences.websocketEnabled = 'false';
+ }
+ savePreferencesToDatabase(Globals.preferences);
+ }}
+ style={{ marginRight: 15 }}
+ />
+
+ {t('enableWebsocket')}
+
+
-
-
- {
- this.setState({
- websocketEnabled: value
- });
- console.log(value);
- if (value) {
- Globals.preferences.websocketEnabled = 'true';
- } else {
- Globals.preferences.websocketEnabled = 'false';
- }
- savePreferencesToDatabase(Globals.preferences);
- }}
- style={{ marginRight: 15 }}
- />
-
- {t('enableWebsocket')}
-
-
+ >
+ }
+ {this.state.enabled &&
+
+
+ }
+ >
+
+
+
+ {t('useCustomAPI')}
+
+
+ {t('customAPIFormat')}
+
- >
- }
- {this.state.enabled &&
-
-
- }
- >
+ {
-
-
- {t('useCustomAPI')}
-
-
- {t('customAPIFormat')}
-
-
- {
-
- let text = e.nativeEvent.text;
- let api = { url: text };
-
- this.swapAPI(api);
-
- }}
- onChangeText={(text) => {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- }}
- errorMessage={this.props.error}
- />
-
- {t('or')}
-
-
- {
- const best_api = await getBestCache();
- this.setState({
- api: best_api,
- });
- this.swapAPI(best_api);
- }}
- color={this.props.screenProps.theme.buttonColour}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 13
- }}
- type="clear"
- />
+ let text = e.nativeEvent.text;
+ let api = { url: text };
-
+ this.swapAPI(api);
+
+ }}
+ onChangeText={(text) => {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ }}
+ errorMessage={this.props.error}
+ />
+
+ {t('or')}
+
+
+ {
+ const best_api = await getBestCache();
+ this.setState({
+ api: best_api,
+ });
+ this.swapAPI(best_api);
+ }}
+ color={this.props.screenProps.theme.buttonColour}
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontSize: 13
+ }}
+ type="clear"
+ />
+
+
+
+ {this.state.apis.length > 0 ?
+
+
+ 0 ?
-
-
-
- {t('pickAPIList')}
-
-
- {t('pullToCheck')}
-
- item.url}
- renderItem={({ item }) => (
-
-
:
-
-
- }
- titleStyle={{
- color: this.state.selectedAPI === item.url
- ? this.props.screenProps.theme.primaryColour
- : this.props.screenProps.theme.slightlyMoreVisibleColour,
- }}
- subtitleStyle={{
- color: this.state.selectedAPI === item.url
- ? this.props.screenProps.theme.primaryColour
- : this.props.screenProps.theme.slightlyMoreVisibleColour,
- }}
- onPress={async () => {
- if (!item.online) {
- Alert.alert(
- 'Use offline API?',
- 'Are you sure you want to attempt to connect to a API which is reporting as offline?',
- [
- {
- text: 'Yes', onPress: () => {
- this.swapAPI(item);
- }
- },
- { text: 'Cancel', style: 'cancel' },
- ],
- );
- } else {
- this.swapAPI(item);
- }
- }}
- />
- )}
- />
- :
-
-
- {t('noAPIs')}
-
-
+ }}>
+ {t('pickAPIList')}
+
+
+ {t('pullToCheck')}
+
+ item.url}
+ renderItem={({ item }) => (
+
+ :
+
+
+ }
+ titleStyle={{
+ color: this.state.selectedAPI === item.url
+ ? this.props.screenProps.theme.primaryColour
+ : this.props.screenProps.theme.slightlyMoreVisibleColour,
+ }}
+ subtitleStyle={{
+ color: this.state.selectedAPI === item.url
+ ? this.props.screenProps.theme.primaryColour
+ : this.props.screenProps.theme.slightlyMoreVisibleColour,
+ }}
+ onPress={async () => {
+ if (!item.online) {
+ Alert.alert(
+ 'Use offline API?',
+ 'Are you sure you want to attempt to connect to a API which is reporting as offline?',
+ [
+ {
+ text: 'Yes', onPress: () => {
+ this.swapAPI(item);
+ }
+ },
+ { text: 'Cancel', style: 'cancel' },
+ ],
+ );
+ } else {
+ this.swapAPI(item);
}
+ }}
+ />
+ )}
+ />
+ :
+
+
+ {t('noAPIs')}
+
+
+ }
-
+
- }
-
-
- );
- }
+ }
+
+
+ );
+ }
}
export const SwapAPIScreen = withTranslation()(SwapAPIScreenNoTranslation)
export class OptimizeScreen extends React.Component {
- static navigationOptions = ({ navigation, screenProps }) => ({
- title: 'Optimize Wallet',
- });
-
- constructor(props) {
- super(props);
+ static navigationOptions = ({ navigation, screenProps }) => ({
+ title: 'Optimize Wallet',
+ });
- this.state = {
- sent: 0,
- completed: false,
- fullyOptimized: false,
- };
+ constructor(props) {
+ super(props);
- this.optimize();
- }
+ this.state = {
+ sent: 0,
+ completed: false,
+ fullyOptimized: false,
+ };
- async optimize() {
- let failCount = 0;
+ this.optimize();
+ }
- while (true) {
- const result = await Globals.wallet.sendFusionTransactionBasic();
+ async optimize() {
+ let failCount = 0;
- console.log(result.error);
+ while (true) {
+ const result = await Globals.wallet.sendFusionTransactionBasic();
- if (result.success) {
- this.setState((prevState) => {
- return {
- sent: prevState.sent + 1,
- };
- });
+ console.log(result.error);
- failCount = 0;
- } else {
- console.log(result.error.errorCode);
+ if (result.success) {
+ this.setState((prevState) => {
+ return {
+ sent: prevState.sent + 1,
+ };
+ });
- if (result.error.errorCode === WalletErrorCode.FULLY_OPTIMIZED) {
- this.setState({
- completed: true,
- fullyOptimized: true,
- });
+ failCount = 0;
+ } else {
+ console.log(result.error.errorCode);
- return;
- }
+ if (result.error.errorCode === WalletErrorCode.FULLY_OPTIMIZED) {
+ this.setState({
+ completed: true,
+ fullyOptimized: true,
+ });
- if (failCount > 5) {
- this.setState({
- completed: true,
- error: result.error.toString(),
- });
+ return;
+ }
- return;
- }
+ if (failCount > 5) {
+ this.setState({
+ completed: true,
+ error: result.error.toString(),
+ });
- failCount++;
- }
+ return;
}
- }
- render() {
- return (
-
-
- {!this.state.completed &&
- Optimizing wallet, please wait...
- }
-
- {this.state.sent > 0 && !this.state.completed &&
- {`Sent ${this.state.sent} fusion transaction${this.state.sent >= 2 ? 's' : ''}.`}
- }
-
- {this.state.sent > 0 && this.state.completed &&
- {`${this.state.sent} fusion transaction${this.state.sent >= 2 ? 's were' : ' was'} sent. It may take some time for ${this.state.sent >= 2 ? 'them' : 'it'} to be included in a block. Once this is complete, your balance will unlock for spending.`}
- }
-
- {this.state.completed && this.state.fullyOptimized &&
- {this.state.sent > 0 ? 'Your wallet is now fully optimized!' : 'Wow, your wallet is already fully optimized! Nice!'}
- }
-
- {this.state.completed && !this.state.fullyOptimized &&
- {`We were not able to completely optimize your wallet. Error sending fusion transaction: ${this.state.error}`}
- }
-
-
- );
+ failCount++;
+ }
}
+ }
+
+ render() {
+ return (
+
+
+ {!this.state.completed &&
+ Optimizing wallet, please wait...
+ }
+
+ {this.state.sent > 0 && !this.state.completed &&
+ {`Sent ${this.state.sent} fusion transaction${this.state.sent >= 2 ? 's' : ''}.`}
+ }
+
+ {this.state.sent > 0 && this.state.completed &&
+ {`${this.state.sent} fusion transaction${this.state.sent >= 2 ? 's were' : ' was'} sent. It may take some time for ${this.state.sent >= 2 ? 'them' : 'it'} to be included in a block. Once this is complete, your balance will unlock for spending.`}
+ }
+
+ {this.state.completed && this.state.fullyOptimized &&
+ {this.state.sent > 0 ? 'Your wallet is now fully optimized!' : 'Wow, your wallet is already fully optimized! Nice!'}
+ }
+
+ {this.state.completed && !this.state.fullyOptimized &&
+ {`We were not able to completely optimize your wallet. Error sending fusion transaction: ${this.state.error}`}
+ }
+
+
+ );
+ }
}
/**
* Fuck w/ stuff
*/
export class SettingsScreenNoTranslation extends React.Component {
- static navigationOptions = ({ navigation, screenProps }) => ({
- title: 'Settings',
- header: null,
- });
-
- constructor(props) {
- super(props);
-
- this.state = {
- notifsEnabled: Globals.preferences.notificationsEnabled,
- scanCoinbase: Globals.preferences.scanCoinbaseTransactions,
- limitData: Globals.preferences.limitData,
- darkMode: Globals.preferences.theme === 'darkMode',
- authConfirmation: Globals.preferences.authConfirmation,
- autoOptimize: Globals.preferences.autoOptimize,
- language: Globals.preferences.language
- }
+ static navigationOptions = ({ navigation, screenProps }) => ({
+ title: 'Settings',
+ header: null,
+ });
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ notifsEnabled: Globals.preferences.notificationsEnabled,
+ scanCoinbase: Globals.preferences.scanCoinbaseTransactions,
+ limitData: Globals.preferences.limitData,
+ darkMode: Globals.preferences.theme === 'darkMode',
+ authConfirmation: Globals.preferences.authConfirmation,
+ autoOptimize: Globals.preferences.autoOptimize,
+ language: Globals.preferences.language
}
+ }
- render() {
- let getColor = (item) => {
- switch (item.title) {
-
- default:
- return this.props.screenProps.theme.foregroundColour
+ render() {
+ const { t } = this.props;
+ let getColor = (item) => {
+ switch (item.title) {
+ default:
+ return this.props.screenProps.theme.foregroundColour
+ }
+ }
- }
+ return (
+
+
+ {t('settingsTitle')}
+
+
+ {
+ if (Globals.preferences.authConfirmation) {
+ Authenticate(
+ this.props.navigation,
+ 'to backup your keys',
+ () => {
+ this.props.navigation.dispatch(navigateWithDisabledBack('Settings'));
+ this.props.navigation.navigate('ExportKeys');
+ }
+ );
+ } else {
+ this.props.navigation.navigate('ExportKeys');
+ }
+ },
+ },
+ {
+ title: t('viewLogs'),
+ description: t('viewLogsDescr'),
+ icon: {
+ iconName: 'note-text',
+ IconType: MaterialCommunityIcons,
+ },
+ onClick: () => {
+ this.props.navigation.navigate('Logging');
+ },
+ },
+ {
+ title: t('backgroundSyncing'),
+ description: t('backgroundSyncingDescr'),
+ icon: {
+ iconName: 'battery-charging',
+ IconType: MaterialCommunityIcons,
+ },
+ onClick: () => {
+ this.props.navigation.navigate('DisableDoze');
+ }
+ },
+ {
+ title: t('swapNode'),
+ description: t('swapNodeDescr'),
+ icon: {
+ iconName: 'ios-swap',
+ IconType: Ionicons,
+ },
+ onClick: () => {
+ this.props.navigation.navigate('SwapNode')
+ },
+ },
+ {
+ title: t('swapAPI'),
+ description: t('swapAPIDescr'),
+ icon: {
+ iconName: 'ios-swap',
+ IconType: Ionicons,
+ },
+ onClick: () => {
+ this.props.navigation.navigate('SwapAPI')
+ },
+ },
+ {
+ title: t('limitData'),
+ description: t('limitDataDescr'),
+ icon: {
+ iconName: this.state.limitData ? 'signal-off' : 'signal',
+ IconType: MaterialCommunityIcons,
+ },
+ onClick: async () => {
+ Globals.preferences.limitData = !Globals.preferences.limitData;
+
+ this.setState({
+ limitData: Globals.preferences.limitData,
+ });
+
+ const netInfo = await NetInfo.fetch();
+
+ if (Globals.preferences.limitData && netInfo.type === 'cellular') {
+ Globals.wallet.stop();
+ } else {
+ Globals.wallet.enableAutoOptimization(false);
+ Globals.wallet.start();
+ }
+
+ toastPopUp(Globals.preferences.limitData ? t('dataLimitOn') : t('dataLimitOff'));
+ savePreferencesToDatabase(Globals.preferences);
+ },
+ checkbox: true,
+ checked: this.state.limitData,
+ },
+ {
+ title: t('enablePin'),
+ description: t('enablePinDescr'),
+ icon: {
+ iconName: 'security',
+ IconType: MaterialCommunityIcons,
+ },
+ onClick: () => {
+ /* Require pin to disable */
+ if (Globals.preferences.authConfirmation) {
+ Authenticate(
+ this.props.navigation,
+ 'to disable PIN/Fingerprint confirmation',
+ () => {
+ Globals.preferences.authConfirmation = !Globals.preferences.authConfirmation;
+
+ this.props.navigation.navigate('Settings');
+
+ savePreferencesToDatabase(Globals.preferences);
+
+ this.setState({
+ authConfirmation: Globals.preferences.authConfirmation,
+ });
+ }
+ );
+ } else {
+ Globals.preferences.authConfirmation = !Globals.preferences.authConfirmation;
- }
- const { t } = this.props;
- return (
-
-
- {t('settingsTitle')}
-
-
- {
- // this.props.navigation.navigate('Faq');
- // },
- // },
- // {
- // title: 'Language',
- // description: 'Change language',
- // icon: {
- // iconName: 'earth',
- // IconType: MaterialCommunityIcons,
- // },
- // onClick: () => {
- // this.props.navigation.navigate('SwapLanguage');
- // }
- // },
- {
- title: t('backupKeys'),
- description: t('backupKeysDescr'),
- icon: {
- iconName: 'key-change',
- IconType: MaterialCommunityIcons,
- },
- onClick: () => {
- if (Globals.preferences.authConfirmation) {
- Authenticate(
- this.props.navigation,
- 'to backup your keys',
- () => {
- this.props.navigation.dispatch(navigateWithDisabledBack('Settings'));
- this.props.navigation.navigate('ExportKeys');
- }
- );
- } else {
- this.props.navigation.navigate('ExportKeys');
- }
- },
- },
- {
- title: t('viewLogs'),
- description: t('viewLogsDescr'),
- icon: {
- iconName: 'note-text',
- IconType: MaterialCommunityIcons,
- },
- onClick: () => {
- this.props.navigation.navigate('Logging');
- },
- },
- // {
- // title: t('rewindWallet'),
- // description: t('rewindWalletDescr'),
- // icon: {
- // iconName: 'md-rewind',
- // IconType: Ionicons,
- // },
- // onClick: () => {
- // if (Globals.preferences.authConfirmation) {
- // Authenticate(
- // this.props.navigation,
- // 'to rewind your wallet',
- // () => {
- // this.props.navigation.navigate('Settings');
- // rewindWallet(this.props.navigation);
- // }
- // );
- // } else {
- // rewindWallet(this.props.navigation);
- // }
- // },
- // },
- {
- title: t('backgroundSyncing'),
- description: t('backgroundSyncingDescr'),
- icon: {
- iconName: 'battery-charging',
- IconType: MaterialCommunityIcons,
- },
- onClick: () => {
- this.props.navigation.navigate('DisableDoze');
- }
- },
- {
- title: t('swapNode'),
- description: t('swapNodeDescr'),
- icon: {
- iconName: 'ios-swap',
- IconType: Ionicons,
- },
- onClick: () => {
- this.props.navigation.navigate('SwapNode')
- },
- },
- {
- title: t('swapAPI'),
- description: t('swapAPIDescr'),
- icon: {
- iconName: 'ios-swap',
- IconType: Ionicons,
- },
- onClick: () => {
- this.props.navigation.navigate('SwapAPI')
- },
- },
- // {
- // title: t('swapCurrency'),
- // description: t('swapCurrencyDescr'),
- // icon: {
- // iconName: 'currency-usd',
- // IconType: MaterialCommunityIcons,
- // },
- // onClick: () => { this.props.navigation.navigate('SwapCurrency') },
- // },
- {
- title: t('limitData'),
- description: t('limitDataDescr'),
- icon: {
- iconName: this.state.limitData ? 'signal-off' : 'signal',
- IconType: MaterialCommunityIcons,
- },
- onClick: async () => {
- Globals.preferences.limitData = !Globals.preferences.limitData;
-
- this.setState({
- limitData: Globals.preferences.limitData,
- });
-
- const netInfo = await NetInfo.fetch();
-
- if (Globals.preferences.limitData && netInfo.type === 'cellular') {
- Globals.wallet.stop();
- } else {
- Globals.wallet.enableAutoOptimization(false);
- Globals.wallet.start();
- }
-
- toastPopUp(Globals.preferences.limitData ? t('dataLimitOn') : t('dataLimitOff'));
- savePreferencesToDatabase(Globals.preferences);
- },
- checkbox: true,
- checked: this.state.limitData,
- },
- // {
- // title: 'Enable dark mode',
- // description: 'Swap between light and dark mode',
- // icon: {
- // iconName: this.state.darkMode ? 'light-down' : 'light-up',
- // IconType: Entypo,
- // },
- // onClick: () => {
- // const newTheme = Globals.preferences.theme === 'darkMode' ? 'lightMode' : 'darkMode';
- //
- // Globals.preferences.theme = newTheme;
- //
- // this.setState({
- // darkMode: Globals.preferences.theme === 'darkMode',
- // });
- //
- // /* Need to use a callback to setState() the
- // theme prop which is passed down to all
- // our components */
- // if (Globals.updateTheme) {
- // Globals.updateTheme();
- // Globals.update();
- // }
- //
- // toastPopUp(Globals.preferences.theme === 'darkMode' ? 'Dark mode enabled' : 'Light mode enabled');
- // savePreferencesToDatabase(Globals.preferences);
- // },
- // checkbox: true,
- // checked: this.state.darkMode,
- // },
- {
- title: t('enablePin'),
- description: t('enablePinDescr'),
- icon: {
- iconName: 'security',
- IconType: MaterialCommunityIcons,
- },
- onClick: () => {
- /* Require pin to disable */
- if (Globals.preferences.authConfirmation) {
- Authenticate(
- this.props.navigation,
- 'to disable PIN/Fingerprint confirmation',
- () => {
- Globals.preferences.authConfirmation = !Globals.preferences.authConfirmation;
-
- this.props.navigation.navigate('Settings');
-
- savePreferencesToDatabase(Globals.preferences);
-
- this.setState({
- authConfirmation: Globals.preferences.authConfirmation,
- });
- }
- );
- } else {
- Globals.preferences.authConfirmation = !Globals.preferences.authConfirmation;
-
- this.setState({
- authConfirmation: Globals.preferences.authConfirmation,
- });
-
- toastPopUp(Globals.preferences.authConfirmation ? t('pinOn') : t('pinOff'));
- savePreferencesToDatabase(Globals.preferences);
- this.props.navigation.navigate('ChooseAuthMethod', {
- nextRoute: 'Settings',
- });
-
- }
- },
- checkbox: true,
- checked: this.state.authConfirmation,
- },
- {
- title: t('changeLoginMethod'),
- description: t('changeLoginMethodDescr'),
- icon: {
- iconName: 'security',
- IconType: MaterialCommunityIcons,
- },
- onClick: () => {
- this.props.navigation.navigate('ChooseAuthMethod', {
- nextRoute: 'Settings',
- });
- },
- },
- {
- title: t('enableNotifications'),
- description: t('enableNotificationsDescr'),
- icon: {
- iconName: 'ios-notifications',
- IconType: Ionicons,
- },
- onClick: () => {
- Globals.preferences.notificationsEnabled = !Globals.preferences.notificationsEnabled;
-
- this.setState({
- notifsEnabled: Globals.preferences.notificationsEnabled,
- });
- toastPopUp(Globals.preferences.notificationsEnabled ? t('notifsOn') : t('notifsOff'));
- if (Globals.preferences.notificationsEnabled) {
- PushNotification.localNotification({
- title: 'Test notification',
- message: 'Notification\'s are enabled!',
- data: ''
- });
- }
- savePreferencesToDatabase(Globals.preferences);
- },
- checkbox: true,
- checked: this.state.notifsEnabled,
- },
- {
- title: t('scanCoinbase'),
- description: t('scanCoinbaseDescr'),
- icon: {
- iconName: 'pickaxe',
- IconType: MaterialCommunityIcons,
- },
- onClick: () => {
- Globals.preferences.scanCoinbaseTransactions = !Globals.preferences.scanCoinbaseTransactions;
-
- this.setState({
- scanCoinbase: Globals.preferences.scanCoinbaseTransactions,
- });
-
- Globals.wallet.scanCoinbaseTransactions(Globals.preferences.scanCoinbaseTransactions);
- toastPopUp(Globals.preferences.scanCoinbaseTransactions ? t('coinbaseOn') : t('coinbaseOff'));
- savePreferencesToDatabase(Globals.preferences);
- },
- checkbox: true,
- checked: this.state.scanCoinbase,
- },
- {
- title: t('manualOptimization'),
- description: t('manualOptimizationDescr'),
- icon: {
- iconName: 'refresh',
- IconType: SimpleLineIcons,
- },
- onClick: async () => {
- // optimizeWallet(this.props.navigation);
- const result = await optimizeMessages(10, true);
- if (result === true) {
- toastPopUp(i18next.t('optimizationComplete'));
- } else if (result === false) {
- toastPopUp(i18next.t('optimizationFailed'));
- } else if (result == 1) {
- toastPopUp(i18next.t('alreadyOptimizing'));
- } else {
- toastPopUp(i18next.t('cancelOptimize').replace(/{inputs.length}/g, result));
- }
- },
+ this.setState({
+ authConfirmation: Globals.preferences.authConfirmation,
+ });
- },
- {
- title: t('resyncWallet'),
- description: t('resyncWalletDescr'),
- icon: {
- iconName: 'ios-refresh',
- IconType: Ionicons,
- },
- onClick: () => {
- if (Globals.preferences.authConfirmation) {
- Authenticate(
- this.props.navigation,
- 'to resync your wallet',
- () => {
- this.props.navigation.navigate('Settings');
- resetWallet(this.props.navigation);
- }
- );
- } else {
- resetWallet(this.props.navigation);
- }
- },
- },
- {
- title: t('clearKnownMessages'),
- description: t('clearKnownMessagesDescr'),
- icon: {
- iconName: 'messages',
- IconType: CustomIcon,
- },
- onClick: () => {
-
- resyncMessage24h();
- toastPopUp('Resyncing messages from the past 24hrs..')
-
- },
- },
- {
- title: t('deleteWallet'),
- description: t('deleteWalletDescr'),
- icon: {
- iconName: 'delete',
- IconType: AntDesign,
- },
- onClick: () => {
- if (Globals.preferences.authConfirmation) {
- Authenticate(
- this.props.navigation,
- 'to delete your wallet',
- () => {
- this.props.navigation.navigate('Settings');
- deleteWallet(this.props.navigation)
- }
- );
- } else {
- deleteWallet(this.props.navigation)
- }
- },
- },
- {
- title: `View ${Config.appName} on ${Platform.OS === 'ios' ? 'the App Store' : 'Google Play'}`,
- description: 'Leave a rating or send the link to your friends',
- icon: {
- iconName: Platform.OS === 'ios' ? 'app-store' : 'google-play',
- IconType: Entypo,
- },
- onClick: () => {
- const link = Platform.OS === 'ios' ? Config.appStoreLink : Config.googlePlayLink;
-
- Linking.openURL(link)
- .catch((err) => Globals.logger.addLogMessage('Failed to open url: ' + err));
- },
- },
- {
- title: `Find ${Config.appName} on Github`,
- description: 'View the source code and give feedback',
- icon: {
- iconName: 'github',
- IconType: AntDesign,
- },
- onClick: () => {
- Linking.openURL(Config.repoLink)
- .catch((err) => Globals.logger.addLogMessage('Failed to open url: ' + err))
- },
- },
- {
- title: Config.appName,
- description: Config.appVersion,
- icon: {
- iconName: 'info',
- IconType: SimpleLineIcons,
- },
- onClick: () => { },
- },
- ]}
- keyExtractor={item => item.title}
- renderItem={({ item }) => (
-
-
-
- }
- rightIcon={item.checkbox &&
-
-
-
- }
- onPress={item.onClick}
- />
- )}
- />
-
-
- );
- }
+ toastPopUp(Globals.preferences.authConfirmation ? t('pinOn') : t('pinOff'));
+ savePreferencesToDatabase(Globals.preferences);
+ this.props.navigation.navigate('ChooseAuthMethod', {
+ nextRoute: 'Settings',
+ });
+
+ }
+ },
+ checkbox: true,
+ checked: this.state.authConfirmation,
+ },
+ {
+ title: t('changeLoginMethod'),
+ description: t('changeLoginMethodDescr'),
+ icon: {
+ iconName: 'security',
+ IconType: MaterialCommunityIcons,
+ },
+ onClick: () => {
+ this.props.navigation.navigate('ChooseAuthMethod', {
+ nextRoute: 'Settings',
+ });
+ },
+ },
+ {
+ title: t('enableNotifications'),
+ description: t('enableNotificationsDescr'),
+ icon: {
+ iconName: 'ios-notifications',
+ IconType: Ionicons,
+ },
+ onClick: () => {
+ Globals.preferences.notificationsEnabled = !Globals.preferences.notificationsEnabled;
+
+ this.setState({
+ notifsEnabled: Globals.preferences.notificationsEnabled,
+ });
+ toastPopUp(Globals.preferences.notificationsEnabled ? t('notifsOn') : t('notifsOff'));
+ if (Globals.preferences.notificationsEnabled) {
+ PushNotification.localNotification({
+ title: 'Test notification',
+ message: 'Notification\'s are enabled!',
+ data: ''
+ });
+ }
+ savePreferencesToDatabase(Globals.preferences);
+ },
+ checkbox: true,
+ checked: this.state.notifsEnabled,
+ },
+ {
+ title: t('scanCoinbase'),
+ description: t('scanCoinbaseDescr'),
+ icon: {
+ iconName: 'pickaxe',
+ IconType: MaterialCommunityIcons,
+ },
+ onClick: () => {
+ Globals.preferences.scanCoinbaseTransactions = !Globals.preferences.scanCoinbaseTransactions;
+
+ this.setState({
+ scanCoinbase: Globals.preferences.scanCoinbaseTransactions,
+ });
+
+ Globals.wallet.scanCoinbaseTransactions(Globals.preferences.scanCoinbaseTransactions);
+ toastPopUp(Globals.preferences.scanCoinbaseTransactions ? t('coinbaseOn') : t('coinbaseOff'));
+ savePreferencesToDatabase(Globals.preferences);
+ },
+ checkbox: true,
+ checked: this.state.scanCoinbase,
+ },
+ {
+ title: t('manualOptimization'),
+ description: t('manualOptimizationDescr'),
+ icon: {
+ iconName: 'refresh',
+ IconType: SimpleLineIcons,
+ },
+ onClick: async () => {
+ // optimizeWallet(this.props.navigation);
+ const result = await optimizeMessages(10, true);
+ if (result === true) {
+ toastPopUp(i18next.t('optimizationComplete'));
+ } else if (result === false) {
+ toastPopUp(i18next.t('optimizationFailed'));
+ } else if (result == 1) {
+ toastPopUp(i18next.t('alreadyOptimizing'));
+ } else {
+ toastPopUp(i18next.t('cancelOptimize').replace(/{inputs.length}/g, result));
+ }
+ },
+
+ },
+ {
+ title: t('resyncWallet'),
+ description: t('resyncWalletDescr'),
+ icon: {
+ iconName: 'ios-refresh',
+ IconType: Ionicons,
+ },
+ onClick: () => {
+ if (Globals.preferences.authConfirmation) {
+ Authenticate(
+ this.props.navigation,
+ 'to resync your wallet',
+ () => {
+ this.props.navigation.navigate('Settings');
+ resetWallet(this.props.navigation);
+ }
+ );
+ } else {
+ resetWallet(this.props.navigation);
+ }
+ },
+ },
+ {
+ title: t('clearKnownMessages'),
+ description: t('clearKnownMessagesDescr'),
+ icon: {
+ iconName: 'messages',
+ IconType: CustomIcon,
+ },
+ onClick: () => {
+
+ resyncMessage24h();
+ toastPopUp('Resyncing messages from the past 24hrs..')
+
+ },
+ },
+ {
+ title: t('deleteWallet'),
+ description: t('deleteWalletDescr'),
+ icon: {
+ iconName: 'delete',
+ IconType: AntDesign,
+ },
+ onClick: () => {
+ if (Globals.preferences.authConfirmation) {
+ Authenticate(
+ this.props.navigation,
+ 'to delete your wallet',
+ () => {
+ this.props.navigation.navigate('Settings');
+ deleteWallet(this.props.navigation)
+ }
+ );
+ } else {
+ deleteWallet(this.props.navigation)
+ }
+ },
+ },
+ {
+ title: `View ${Config.appName} on ${Platform.OS === 'ios' ? 'the App Store' : 'Google Play'}`,
+ description: 'Leave a rating or send the link to your friends',
+ icon: {
+ iconName: Platform.OS === 'ios' ? 'app-store' : 'google-play',
+ IconType: Entypo,
+ },
+ onClick: () => {
+ const link = Platform.OS === 'ios' ? Config.appStoreLink : Config.googlePlayLink;
+
+ Linking.openURL(link)
+ .catch((err) => Globals.logger.addLogMessage('Failed to open url: ' + err));
+ },
+ },
+ {
+ title: `Find ${Config.appName} on Github`,
+ description: 'View the source code and give feedback',
+ icon: {
+ iconName: 'github',
+ IconType: AntDesign,
+ },
+ onClick: () => {
+ Linking.openURL(Config.repoLink)
+ .catch((err) => Globals.logger.addLogMessage('Failed to open url: ' + err))
+ },
+ },
+ {
+ title: Config.appName,
+ description: Config.appVersion,
+ icon: {
+ iconName: 'info',
+ IconType: SimpleLineIcons,
+ },
+ onClick: () => { },
+ },
+ ]}
+ keyExtractor={item => item.title}
+ renderItem={({ item }) => (
+
+
+
+ }
+ rightIcon={item.checkbox &&
+
+
+
+ }
+ onPress={item.onClick}
+ />
+ )}
+ />
+
+
+ );
+ }
}
export const SettingsScreen = withTranslation()(SettingsScreenNoTranslation)
@@ -1943,111 +1816,111 @@ export const SettingsScreen = withTranslation()(SettingsScreenNoTranslation)
*
*/
function deleteWallet(navigation) {
- Alert.alert(
- i18next.t('deleteWarningPromptTitle'),
- i18next.t('deleteWarningSubtitle'),
- [
- {
- text: i18next.t('delete'), onPress: () => {
- (async () => {
- /* Disabling saving */
- clearInterval(Globals.backgroundSaveTimer);
+ Alert.alert(
+ i18next.t('deleteWarningPromptTitle'),
+ i18next.t('deleteWarningSubtitle'),
+ [
+ {
+ text: i18next.t('delete'), onPress: () => {
+ (async () => {
+ /* Disabling saving */
+ clearInterval(Globals.backgroundSaveTimer);
- clearInterval(Globals.backgroundSyncMessagesTimer);
+ clearInterval(Globals.backgroundSyncMessagesTimer);
- Globals.syncingMessages = false;
+ Globals.syncingMessages = false;
- Globals.backgroundSyncMessagesTimer = undefined;
+ Globals.backgroundSyncMessagesTimer = undefined;
- await setHaveWallet(false);
+ await setHaveWallet(false);
- Globals.wallet.stop();
+ Globals.wallet.stop();
- Globals.reset();
+ Globals.reset();
- /* And head back to the wallet choose screen */
- navigation.navigate('Login');
- })();
- }
- },
- { text: i18next.t('cancel'), style: 'cancel' },
- ],
- );
+ /* And head back to the wallet choose screen */
+ navigation.navigate('Login');
+ })();
+ }
+ },
+ { text: i18next.t('cancel'), style: 'cancel' },
+ ],
+ );
}
function resetWallet(navigation) {
- Alert.alert(
- i18next.t('resyncTitle'),
- i18next.t('resyncSubtitle'),
- [
- {
- text: i18next.t('resync'), onPress: () => {
- Globals.wallet.rescan();
- toastPopUp(i18next.t('resyncNotif'));
- navigation.navigate('Main', { reloadBalance: true });
- }
- },
- { text: i18next.t('cancel'), style: 'cancel' },
- ],
- );
+ Alert.alert(
+ i18next.t('resyncTitle'),
+ i18next.t('resyncSubtitle'),
+ [
+ {
+ text: i18next.t('resync'), onPress: () => {
+ Globals.wallet.rescan();
+ toastPopUp(i18next.t('resyncNotif'));
+ navigation.navigate('Main', { reloadBalance: true });
+ }
+ },
+ { text: i18next.t('cancel'), style: 'cancel' },
+ ],
+ );
}
function rewindWallet(navigation) {
- Alert.alert(
- i18next.t('rewindTitle'),
- i18next.t('rewindSubtitle'),
- [
- {
- text: i18next.t('rewind'), onPress: () => {
- const [walletBlockCount] = Globals.wallet.getSyncStatus();
-
- let rewindHeight = walletBlockCount;
-
- if (walletBlockCount > 5000) {
- rewindHeight = walletBlockCount - 5000;
- }
+ Alert.alert(
+ i18next.t('rewindTitle'),
+ i18next.t('rewindSubtitle'),
+ [
+ {
+ text: i18next.t('rewind'), onPress: () => {
+ const [walletBlockCount] = Globals.wallet.getSyncStatus();
- Globals.wallet.rewind(rewindHeight);
+ let rewindHeight = walletBlockCount;
- toastPopUp(i18next.t('rewindNotif'));
- navigation.navigate('Main', { reloadBalance: true });
- }
- },
- { text: i18next.t('cancel'), style: 'cancel' },
- ],
- );
+ if (walletBlockCount > 5000) {
+ rewindHeight = walletBlockCount - 5000;
+ }
+
+ Globals.wallet.rewind(rewindHeight);
+
+ toastPopUp(i18next.t('rewindNotif'));
+ navigation.navigate('Main', { reloadBalance: true });
+ }
+ },
+ { text: i18next.t('cancel'), style: 'cancel' },
+ ],
+ );
}
function recoverWallet(navigation) {
- Alert.alert(
- i18next.t('recoverWalletTitle'),
- i18next.t('recoverWalletDescr'),
- [
- {
- text: i18next.t('ok'), onPress: () => {
- const [walletBlockCount] = Globals.wallet.getSyncStatus();
- Globals.wallet.reset(walletBlockCount - 1);
-
- toastPopUp('Wallet recovery initiated');
- navigation.navigate('Main', { reloadBalance: true });
- }
- },
- { text: i18next.t('cancel'), style: 'cancel' },
- ],
- );
+ Alert.alert(
+ i18next.t('recoverWalletTitle'),
+ i18next.t('recoverWalletDescr'),
+ [
+ {
+ text: i18next.t('ok'), onPress: () => {
+ const [walletBlockCount] = Globals.wallet.getSyncStatus();
+ Globals.wallet.reset(walletBlockCount - 1);
+
+ toastPopUp('Wallet recovery initiated');
+ navigation.navigate('Main', { reloadBalance: true });
+ }
+ },
+ { text: i18next.t('cancel'), style: 'cancel' },
+ ],
+ );
}
function optimizeWallet(navigation) {
- Alert.alert(
- 'Optimize Wallet?',
- 'Are you sure you want to attempt to optimize your wallet? This may lock your funds for some time.',
- [
- {
- text: 'Optimize', onPress: () => {
- navigation.navigate('Optimize');
- }
- },
- { text: 'Cancel', style: 'cancel' },
- ],
- );
+ Alert.alert(
+ 'Optimize Wallet?',
+ 'Are you sure you want to attempt to optimize your wallet? This may lock your funds for some time.',
+ [
+ {
+ text: 'Optimize', onPress: () => {
+ navigation.navigate('Optimize');
+ }
+ },
+ { text: 'Cancel', style: 'cancel' },
+ ],
+ );
}
diff --git a/src/SharedComponents.js b/src/SharedComponents.js
index 5b3d953..4ad8c7e 100644
--- a/src/SharedComponents.js
+++ b/src/SharedComponents.js
@@ -9,8 +9,6 @@ import React from 'react';
import { Platform, View, Clipboard, Text } from 'react-native';
import { Button } from 'react-native-elements';
-import Icon from 'react-native-vector-icons/dist/FontAwesome';
-import Config from './Config';
import { Styles } from './Styles';
import { toastPopUp } from './Utilities';
@@ -20,233 +18,233 @@ import './i18n.js';
import { withTranslation } from 'react-i18next';
export class TextFixedWidth extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- const fontFamily = Platform.OS === 'ios' ? 'Courier' : 'monospace'
-
- return (
-
- {this.props.children}
-
- );
- }
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ const fontFamily = Platform.OS === 'ios' ? 'Courier' : 'monospace'
+
+ return (
+
+ {this.props.children}
+
+ );
+ }
}
/**
* Display the seed in a nice way
*/
export class SeedComponent extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- const split = this.props.seed.split(' ');
- const lines = _.chunk(split, 5);
-
- return(
-
-
-
- {lines[0].join(' ')}
-
-
- {lines[1].join(' ')}
-
-
- {lines[2].join(' ')}
-
-
- {lines[3].join(' ')}
-
-
- {lines[4].join(' ')}
-
-
-
-
- );
- }
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ const split = this.props.seed.split(' ');
+ const lines = _.chunk(split, 5);
+
+ return (
+
+
+
+ {lines[0].join(' ')}
+
+
+ {lines[1].join(' ')}
+
+
+ {lines[2].join(' ')}
+
+
+ {lines[3].join(' ')}
+
+
+ {lines[4].join(' ')}
+
+
+
+
+ );
+ }
}
/**
* Copy the data to clipboard
*/
export class CopyButtonNoTranslation extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- const { t } = this.props;
- return(
-
- {
- Clipboard.setString(this.props.data);
- toastPopUp(this.props.name + t('copied'));
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- textDecorationLine: 'none',
- marginTop: -3
- }}
- type='clear'
- />
-
- );
- }
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ const { t } = this.props;
+ return (
+
+ {
+ Clipboard.setString(this.props.data);
+ toastPopUp(this.props.name + t('copied'));
+ }}
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ textDecorationLine: 'none',
+ marginTop: -3
+ }}
+ type='clear'
+ />
+
+ );
+ }
}
export const CopyButton = withTranslation()(CopyButtonNoTranslation)
export class Hr extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- width: this.props.width || '90%',
- };
- }
-
- render() {
- return(
-
- );
- }
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ width: this.props.width || '90%',
+ };
+ }
+
+ render() {
+ return (
+
+ );
+ }
}
export class BottomButton extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- return(
-
-
-
- );
- }
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ return (
+
+
+
+ );
+ }
}
export class OR extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- return(
-
-
-
-
- OR
-
-
-
-
- );
- }
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ return (
+
+
+
+
+ OR
+
+
+
+
+ );
+ }
}
export class OneLineText extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- if (!this.props.style || !this.props.style.fontSize) {
- throw new Error('Fontsize property is mandatory!');
- }
-
- if (this.props.style.fontSize === 0) {
- throw new Error('Font size cannot be zero!');
- }
-
- this.multiplier = this.props.multiplier || 20;
+ if (!this.props.style || !this.props.style.fontSize) {
+ throw new Error('Fontsize property is mandatory!');
}
- calculateFontSize(fontSize, text) {
- if (text.length === 0) {
- return fontSize;
- }
+ if (this.props.style.fontSize === 0) {
+ throw new Error('Font size cannot be zero!');
+ }
- /* Get a decent guess of the right font size to use to fit on one line */
- let maxFontSize = Math.round(((1 / text.length) / fontSize) * this.multiplier * 1000);
+ this.multiplier = this.props.multiplier || 20;
+ }
- return Math.min(maxFontSize, fontSize);
+ calculateFontSize(fontSize, text) {
+ if (text.length === 0) {
+ return fontSize;
}
- render() {
- return(
-
- {this.props.children}
-
- );
- }
+ /* Get a decent guess of the right font size to use to fit on one line */
+ let maxFontSize = Math.round(((1 / text.length) / fontSize) * this.multiplier * 1000);
+
+ return Math.min(maxFontSize, fontSize);
+ }
+
+ render() {
+ return (
+
+ {this.props.children}
+
+ );
+ }
}
diff --git a/src/Spinner.js b/src/Spinner.js
index 5332d01..93a819f 100644
--- a/src/Spinner.js
+++ b/src/Spinner.js
@@ -4,67 +4,67 @@
import React from 'react';
-import { Animated, Image, Text } from 'react-native';
+import { Animated, Image } from 'react-native';
export class Spinner extends React.Component {
- constructor(props) {
- super(props);
- this.animation = new Animated.Value(0);
- }
-
-
- componentWillMount() {
- this.animatedValue = new Animated.Value(0);
- }
+ constructor(props) {
+ super(props);
+ this.animation = new Animated.Value(0);
+ }
- componentDidMount() {
- let flipFlop = false;
+ componentWillMount() {
+ this.animatedValue = new Animated.Value(0);
+ }
- let keepAnimating = () => {
+ componentDidMount() {
- Animated.timing(this.animatedValue, {
- toValue: flipFlop ? 0 : 224,
- duration: 3000
- }).start(() => {
- flipFlop = flipFlop ? false : true;
- keepAnimating();
- });
+ let flipFlop = false;
- }
+ let keepAnimating = () => {
- Animated.timing(this.animatedValue, {
- toValue: 224,
- duration: 3000
- }).start(() => {
- keepAnimating();
-
- });
-
- Animated.loop(
- Animated.timing(this.animation, {toValue: 1, duration: 100000, useNativeDriver: true})
- ).start();
+ Animated.timing(this.animatedValue, {
+ toValue: flipFlop ? 0 : 224,
+ duration: 3000
+ }).start(() => {
+ flipFlop = flipFlop ? false : true;
+ keepAnimating();
+ });
}
- render() {
- const rotation = this.animation.interpolate({
- inputRange: [0, 1],
- outputRange: ['0deg', '0deg']
- });
-
- const interpolateColor = this.animatedValue.interpolate({
- inputRange: [0, 32, 64, 96, 128, 160, 192, 224],
- outputRange:['#5f86f2','#a65ff2','#f25fd0','#f25f61','#f2cb5f','#abf25f','#5ff281','#5ff2f0']
- });
-
- return(
-
-
-
- );
- }
+ Animated.timing(this.animatedValue, {
+ toValue: 224,
+ duration: 3000
+ }).start(() => {
+ keepAnimating();
+
+ });
+
+ Animated.loop(
+ Animated.timing(this.animation, { toValue: 1, duration: 100000, useNativeDriver: true })
+ ).start();
+
+ }
+
+ render() {
+ const rotation = this.animation.interpolate({
+ inputRange: [0, 1],
+ outputRange: ['0deg', '0deg']
+ });
+
+ const interpolateColor = this.animatedValue.interpolate({
+ inputRange: [0, 32, 64, 96, 128, 160, 192, 224],
+ outputRange: ['#5f86f2', '#a65ff2', '#f25fd0', '#f25f61', '#f2cb5f', '#abf25f', '#5ff281', '#5ff2f0']
+ });
+
+ return (
+
+
+
+ );
+ }
}
diff --git a/src/SplashScreen.js b/src/SplashScreen.js
index b0e64ca..c4e0a05 100644
--- a/src/SplashScreen.js
+++ b/src/SplashScreen.js
@@ -6,61 +6,59 @@ import React from 'react';
import { WalletBackend } from 'kryptokrona-wallet-backend-js';
-import { Animated, View, Alert } from 'react-native';
+import { View, Alert } from 'react-native';
import Config from './Config';
import { Globals } from './Globals';
-import { Spinner } from './Spinner';
-import { FadeView } from './FadeView';
import { Authenticate } from './Authenticate';
import { haveWallet, loadWallet } from './Database';
import { delay, navigateWithDisabledBack } from './Utilities';
import { XKRLogo } from './XKRLogo';
function fail(msg) {
- Globals.logger.addLogMessage(msg);
-
- Alert.alert(
- 'Failed to open wallet',
- msg,
- [
- {text: 'OK'},
- ]
- );
+ Globals.logger.addLogMessage(msg);
+
+ Alert.alert(
+ 'Failed to open wallet',
+ msg,
+ [
+ { text: 'OK' },
+ ]
+ );
}
/**
* Called once the pin has been correctly been entered
*/
async function tryLoadWallet(navigation) {
- (async () => {
- /* Wallet already loaded, probably from previous launch, then
- sending app to background. */
- if (Globals.wallet !== undefined) {
- navigation.navigate('Home');
- return;
- }
-
- /* Load wallet data from DB */
- let [walletData, dbError] = await loadWallet();
-
- if (dbError) {
- await fail(dbError);
- return;
- }
-
- const [wallet, walletError] = await WalletBackend.loadWalletFromJSON(
- Globals.getDaemon(), walletData, Config
- );
+ (async () => {
+ /* Wallet already loaded, probably from previous launch, then
+ sending app to background. */
+ if (Globals.wallet !== undefined) {
+ navigation.navigate('Home');
+ return;
+ }
- if (walletError) {
- await fail('Error loading wallet: ' + walletError);
- } else {
- Globals.wallet = wallet;
- navigation.navigate('Home');
- }
- })();
+ /* Load wallet data from DB */
+ let [walletData, dbError] = await loadWallet();
+
+ if (dbError) {
+ await fail(dbError);
+ return;
+ }
+
+ const [wallet, walletError] = await WalletBackend.loadWalletFromJSON(
+ Globals.getDaemon(), walletData, Config
+ );
+
+ if (walletError) {
+ await fail('Error loading wallet: ' + walletError);
+ } else {
+ Globals.wallet = wallet;
+ navigation.navigate('Home');
+ }
+ })();
}
/**
@@ -68,60 +66,60 @@ async function tryLoadWallet(navigation) {
* Otherwise, go to the create/import screen
*/
export class SplashScreen extends React.Component {
- static navigationOptions = {
- header: null,
- };
-
- constructor(props) {
- super(props);
-
- (async () => {
- /* See if user has previously made a wallet */
- const hasWallet = await haveWallet();
-
- /* Above operation takes some time. Loading animation is pretty ugly
- if it only stays for 0.5 seconds, and too slow if we don't have
- any animation at all..
- This way it looks nice, even if delaying interaction by a couple
- of seconds */
- await delay(2000);
-
- /* Get the pin, or show disclaimer then create a wallet if no pin */
- if (hasWallet) {
- Authenticate(
- this.props.navigation,
- 'to unlock your account',
- tryLoadWallet,
- true
- );
- } else {
- this.props.navigation.dispatch(
- navigateWithDisabledBack('WalletOption'),
- );
- }
- })();
- }
+ static navigationOptions = {
+ header: null,
+ };
+
+ constructor(props) {
+ super(props);
+
+ (async () => {
+ /* See if user has previously made a wallet */
+ const hasWallet = await haveWallet();
+
+ /* Above operation takes some time. Loading animation is pretty ugly
+ if it only stays for 0.5 seconds, and too slow if we don't have
+ any animation at all..
+ This way it looks nice, even if delaying interaction by a couple
+ of seconds */
+ await delay(2000);
+
+ /* Get the pin, or show disclaimer then create a wallet if no pin */
+ if (hasWallet) {
+ Authenticate(
+ this.props.navigation,
+ 'to unlock your account',
+ tryLoadWallet,
+ true
+ );
+ } else {
+ this.props.navigation.dispatch(
+ navigateWithDisabledBack('WalletOption'),
+ );
+ }
+ })();
+ }
- componentWillMount() {
+ componentWillMount() {
- }
+ }
- componentDidMount() {
+ componentDidMount() {
- }
+ }
- render() {
+ render() {
- return(
- /* Fade in a spinner logo */
-
+ return (
+ /* Fade in a spinner logo */
+
-
+
-
- );
- }
+
+ );
+ }
}
diff --git a/src/Styles.js b/src/Styles.js
index 9105793..bf52509 100644
--- a/src/Styles.js
+++ b/src/Styles.js
@@ -5,73 +5,71 @@
import { StyleSheet } from 'react-native';
export const Styles = StyleSheet.create({
- logo: {
- resizeMode: 'contain',
- width: 300,
- height: 300
+ logo: {
+ resizeMode: 'contain',
+ width: 300,
+ height: 300
+ },
+ buttonContainer: {
+ borderRadius: 10,
+ padding: 10,
+ shadowColor: '#000000',
+ shadowOffset: {
+ width: 0,
+ height: 3
},
- buttonContainer: {
- borderRadius: 10,
- padding: 10,
- shadowColor: '#000000',
- shadowOffset: {
- width: 0,
- height: 3
- },
- shadowRadius: 10,
- shadowOpacity: 0.25
- },
- centeredText: {
- alignItems: 'center',
- justifyContent: 'center',
- textAlign: 'center',
- },
- alignBottom: {
- position: 'relative',
- alignItems: 'stretch',
- justifyContent: 'center',
- width: '100%',
- bottom: 0,
- }
+ shadowRadius: 10,
+ shadowOpacity: 0.25
+ },
+ centeredText: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ textAlign: 'center',
+ },
+ alignBottom: {
+ position: 'relative',
+ alignItems: 'stretch',
+ justifyContent: 'center',
+ width: '100%',
+ bottom: 0,
+ }
});
export const unread_counter_style = {
- borderRadius: 15,
- minWidth: 28,
- height: 28,
- backgroundColor: 'red',
- color: 'white',
- padding: 4,
- borderWidth: 5,
- marginTop: -10,
- marginRight: -10
- };
+ borderRadius: 15,
+ borderWidth: 5,
+ minWidth: 28,
+ height: 28,
+ backgroundColor: 'red',
+ color: 'white',
+ padding: 4,
+};
- export const unread_counter_text_style = {
- fontSize: 14,
- lineHeight: 14,
- fontFamily: 'Montserrat-Bold',
- color: 'white',
- textAlign: 'center'
- };
+export const unread_counter_text_style = {
+ fontSize: 14,
+ lineHeight: 14,
+ fontFamily: 'Montserrat-Bold',
+ color: 'white',
+ textAlign: 'center'
+};
export const legacyRNElementsColors = {
- primary: "#9E9E9E",
- primary1: "#4d86f7",
- primary2: "#6296f9",
- secondary: "#8F0CE8",
- secondary2: "#00B233",
- secondary3: "#00FF48",
- grey0: "#393e42",
- grey1: "#43484d",
- grey2: "#5e6977",
- grey3: "#86939e",
- grey4: "#bdc6cf",
- grey5: "#e1e8ee",
- dkGreyBg: "#232323",
- greyOutline: "#bbb",
- searchBg: "#303337",
- disabled: "#dadee0",
- white: "#ffffff",
- error: "#ff190c",
+ primary: "#9E9E9E",
+ primary1: "#4d86f7",
+ primary2: "#6296f9",
+ secondary: "#8F0CE8",
+ secondary2: "#00B233",
+ secondary3: "#00FF48",
+ grey0: "#393e42",
+ grey1: "#43484d",
+ grey2: "#5e6977",
+ grey3: "#86939e",
+ grey4: "#bdc6cf",
+ grey5: "#e1e8ee",
+ dkGreyBg: "#232323",
+ greyOutline: "#bbb",
+ searchBg: "#303337",
+ disabled: "#dadee0",
+ white: "#ffffff",
+ error: "#ff190c",
};
diff --git a/src/TransactionsScreen.js b/src/TransactionsScreen.js
index 7d42775..0583aab 100644
--- a/src/TransactionsScreen.js
+++ b/src/TransactionsScreen.js
@@ -12,7 +12,7 @@ import { Header } from 'react-native-elements';
import { View, Text, FlatList, Button, Linking, ScrollView, Image } from 'react-native';
import { prettyPrintAmount } from 'kryptokrona-wallet-backend-js';
-import {intToRGB, hashCode, get_avatar, getBoardColors} from './HuginUtilities';
+import { get_avatar, getBoardColors } from './HuginUtilities';
import Config from './Config';
import ListItem from './ListItem';
import List from './ListContainer';
@@ -21,285 +21,274 @@ import Constants from './Constants';
import { Styles } from './Styles';
import { Globals } from './Globals';
import { coinsToFiat } from './Currency';
-import { prettyPrintUnixTimestamp, prettyPrintDate, prettyPrintDate2 } from './Utilities';
+import { prettyPrintUnixTimestamp, prettyPrintDate2 } from './Utilities';
import { getBoardsMessage, boardsMessageExists } from './Database'
-import './i18n.js';
+import './i18n';
import { withTranslation } from 'react-i18next';
-class ItemDescription extends React.Component {
- constructor(props) {
- super(props);
+import { Card, TextField, ScreenLayout, ScreenHeader } from './components';
- this.state = {
- fontSize: this.props.fontSize || 20,
- }
- }
+class ItemDescription extends React.Component {
+ constructor(props) {
+ super(props);
- render() {
- return(
-
-
- {this.props.title}
-
-
-
- {this.props.item}
-
-
- )
+ this.state = {
+ fontSize: this.props.fontSize || 20,
}
+ }
+
+ render() {
+ return (
+
+
+ {this.props.title}
+
+
+ {this.props.item}
+
+
+ )
+ }
}
-export class TransactionDetailsScreenNoTranslation extends React.Component {
- static navigationOptions = {
- title: 'Transaction Details',
- };
-
- constructor(props) {
- super(props);
-
- const tx = props.navigation.state.params.transaction;
-
- const txDetails = Globals.transactionDetails.find((x) => x.hash === tx.hash);
-
- if (txDetails && txDetails.memo === '') {
- txDetails.memo = undefined;
- }
-
- this.state = {
- transaction: tx,
- amount: Math.abs(tx.totalAmount()) - (tx.totalAmount() > 0 ? 0 : tx.fee),
- complete: tx.timestamp !== 0,
- coinValue: '0',
- address: txDetails ? txDetails.address : undefined,
- payee: txDetails && txDetails.payee != '' ? txDetails.payee : undefined,
- memo: txDetails ? txDetails.memo : undefined,
- tipTo: null
- };
-
- (async () => {
-
- const isTip = await boardsMessageExists(this.state.transaction.paymentID);
- console.log(isTip);
- if (isTip) {
- const tipTo = await getBoardsMessage(this.state.transaction.paymentID);
- console.log(tipTo);
- this.setState({
- tipTo: tipTo
- })
- }
-
- const coinValue = await coinsToFiat(
- this.state.amount,
- Globals.preferences.currency,
- );
-
- this.setState({
- coinValue,
- });
- })();
- }
-
- render() {
- const { t } = this.props;
- const tipTo = this.state.tipTo;
- return(
-
-
-
- 0 ? t('received') : t('sent')}
- item={this.state.complete ? prettyPrintUnixTimestamp(this.state.transaction.timestamp) : prettyPrintDate2(Date.now()/1000)}
- {...this.props}
- />
-
- {this.state.payee && }
-
-
-
- {this.state.transaction.totalAmount() < 0 && }
-
-
-
- {this.state.memo && this.state.memo !== '' && }
-
- {this.state.address && }
-
-
-
- {this.state.complete && }
-
-
-
- {this.state.transaction.paymentID !== '' && }
-
- {tipTo && this.state.transaction.paymentID !== '' &&
- <>
-
- {'This payment was sent as a tip for the post below:'}
-
-
-
-
-
-
+class TransactionDetailsScreenNoTranslation extends React.Component {
+ static navigationOptions = {
+ title: 'Transaction Details',
+ };
-
-
- {tipTo[0].nickname ? tipTo[0].nickname : 'Anonymous'}
-
-
+ constructor(props) {
+ super(props);
-
-
-
+ const tx = props.navigation.state.params.transaction;
- {tipTo[0].board}
-
-
-
-
+ const txDetails = Globals.transactionDetails.find((x) => x.hash === tx.hash);
+ if (txDetails && txDetails.memo === '') {
+ txDetails.memo = undefined;
+ }
+ this.state = {
+ transaction: tx,
+ amount: Math.abs(tx.totalAmount()) - (tx.totalAmount() > 0 ? 0 : tx.fee),
+ complete: tx.timestamp !== 0,
+ coinValue: '0',
+ address: txDetails ? txDetails.address : undefined,
+ payee: txDetails && txDetails.payee != '' ? txDetails.payee : undefined,
+ memo: txDetails ? txDetails.memo : undefined,
+ tipTo: null
+ };
-
-
+ (async () => {
+ const isTip = await boardsMessageExists(this.state.transaction.paymentID);
+ console.log(isTip);
+ if (isTip) {
+ const tipTo = await getBoardsMessage(this.state.transaction.paymentID);
+ console.log(tipTo);
+ this.setState({
+ tipTo: tipTo
+ })
+ }
+
+ const coinValue = await coinsToFiat(
+ this.state.amount,
+ Globals.preferences.currency,
+ );
+
+ this.setState({
+ coinValue,
+ });
+ })();
+ }
+
+ render() {
+ const { t } = this.props;
+ const tipTo = this.state.tipTo;
+ return (
+
+
+
+ 0 ? t('received') : t('sent')}
+ item={this.state.complete ? prettyPrintUnixTimestamp(this.state.transaction.timestamp) : prettyPrintDate2(Date.now() / 1000)}
+ {...this.props}
+ />
- {tipTo[0].message + "\n"}
+ {this.state.payee && }
+
+ {this.state.transaction.totalAmount() < 0 && }
-
-
- >}
+
+ {this.state.memo && this.state.memo !== '' && }
+
+ {this.state.address && }
+
+
+ {this.state.complete && }
-
+
- {this.state.complete &&
- {
- Linking.openURL(Config.explorerBaseURL + this.state.transaction.hash)
- .catch((err) => Globals.logger.addLogMessage('Failed to open url: ' + err));
- }}
- color={this.props.screenProps.theme.buttonColour}
- />
- }
+ {this.state.transaction.paymentID !== '' && }
+
+ {tipTo && this.state.transaction.paymentID !== '' &&
+ <>
+
+ {'This payment was sent as a tip for the post below:'}
+
-
- );
- }
+
+
+
+
+
+
+
+ {tipTo[0].nickname ? tipTo[0].nickname : 'Anonymous'}
+
+
+
+
+
+
+
+ {tipTo[0].board}
+
+
+
+
+
+ {tipTo[0].message + "\n"}
+
+
+ >
+ }
+
+ {this.state.complete &&
+ {
+ Linking.openURL(Config.explorerBaseURL + this.state.transaction.hash)
+ .catch((err) => Globals.logger.addLogMessage('Failed to open url: ' + err));
+ }}
+ color={this.props.screenProps.theme.buttonColour}
+ />
+ }
+
+
+ );
+ }
}
export const TransactionDetailsScreen = withTranslation()(TransactionDetailsScreenNoTranslation)
@@ -307,271 +296,254 @@ export const TransactionDetailsScreen = withTranslation()(TransactionDetailsScre
/**
* List of transactions sent + received
*/
-export class TransactionsScreenNoTranslation extends React.Component {
- static navigationOptions = {
- title: 'Transactions',
- header: null
- };
+class TransactionsScreenNoTranslation extends React.Component {
+ static navigationOptions = {
+ title: 'Transactions',
+ header: null
+ };
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- const [walletHeight, localHeight, networkHeight] = Globals.wallet.getSyncStatus();
+ const [walletHeight, localHeight, networkHeight] = Globals.wallet.getSyncStatus();
- /* Don't display fusions, and display newest first */
+ /* Don't display fusions, and display newest first */
- this.state = {
- walletHeight,
- networkHeight,
- pageNum: 0,
- numTransactions: 0
- };
+ this.state = {
+ walletHeight,
+ networkHeight,
+ pageNum: 0,
+ numTransactions: 0
+ };
- /* Only update transactions list when transaction is sent/received.
- With lots of transactions, it can be very inefficient to constantly
- refetch. */
- Globals.wallet.on('transaction', () => {
- this.updateTransactions();
- });
+ /* Only update transactions list when transaction is sent/received.
+ With lots of transactions, it can be very inefficient to constantly
+ refetch. */
+ Globals.wallet.on('transaction', () => {
+ this.updateTransactions();
+ });
- /* When we create a transaction, it is in pending state, which we
- want to display. The on('transaction') will be triggered when it
- gets scanned by the wallet, updating it to confirmed. */
- Globals.wallet.on('createdtx', () => {
- this.updateTransactions();
- });
+ /* When we create a transaction, it is in pending state, which we
+ want to display. The on('transaction') will be triggered when it
+ gets scanned by the wallet, updating it to confirmed. */
+ Globals.wallet.on('createdtx', () => {
+ this.updateTransactions();
+ });
- this.changePage = this.changePage.bind(this);
- }
+ this.changePage = this.changePage.bind(this);
+ }
- async componentDidMount() {
+ async componentDidMount() {
- const all_transactions = await Globals.wallet.getTransactions();
+ const all_transactions = await Globals.wallet.getTransactions();
- const filtered_transactions = all_transactions.filter(tx => {
- return tx.totalAmount() > 1 || tx.totalAmount() < -10000;
- });
- const transactions = filtered_transactions.slice(0, Constants.numTransactionsPerPage);
- const numTransactions = filtered_transactions.length; //await Globals.wallet.getNumTransactions();
+ const filtered_transactions = all_transactions.filter(tx => {
+ return tx.totalAmount() > 1 || tx.totalAmount() < -10000;
+ });
+ const transactions = filtered_transactions.slice(0, Constants.numTransactionsPerPage);
+ const numTransactions = filtered_transactions.length; //await Globals.wallet.getNumTransactions();
- this.setState({
- numTransactions,
- transactions,
- });
+ this.setState({
+ numTransactions,
+ transactions,
+ });
- this.interval = setInterval(() => this.tick(), 10000);
- }
+ this.interval = setInterval(() => this.tick(), 10000);
+ }
- async updateTransactions() {
+ async updateTransactions() {
- const all_transactions = await Globals.wallet.getTransactions();
+ const all_transactions = await Globals.wallet.getTransactions();
- let transactions_filtered = all_transactions.filter(tx => {
- return tx.totalAmount() > 1 || tx.totalAmount() < -10000;
- })
+ let transactions_filtered = all_transactions.filter(tx => {
+ return tx.totalAmount() > 1 || tx.totalAmount() < -10000;
+ })
- const transactions = transactions_filtered.slice(this.state.pageNum * Constants.numTransactionsPerPage, Constants.numTransactionsPerPage + (this.state.pageNum * Constants.numTransactionsPerPage) );
+ const transactions = transactions_filtered.slice(this.state.pageNum * Constants.numTransactionsPerPage, Constants.numTransactionsPerPage + (this.state.pageNum * Constants.numTransactionsPerPage));
- this.setState({
- numTransactions: transactions_filtered.length,
- transactions,
- });
- }
+ this.setState({
+ numTransactions: transactions_filtered.length,
+ transactions,
+ });
+ }
- async tick() {
- const numTransactions = await Globals.wallet.getNumTransactions();
+ async tick() {
+ const numTransactions = await Globals.wallet.getNumTransactions();
- /* If we have no transactions, update the heights, to display the
- not sent / not synced msg */
- if (numTransactions === 0) {
- const [walletHeight, localHeight, networkHeight] = Globals.wallet.getSyncStatus();
+ /* If we have no transactions, update the heights, to display the
+ not sent / not synced msg */
+ if (numTransactions === 0) {
+ const [walletHeight, localHeight, networkHeight] = Globals.wallet.getSyncStatus();
- this.setState({
- walletHeight,
- networkHeight,
- });
- }
+ this.setState({
+ walletHeight,
+ networkHeight,
+ });
}
+ }
- componentWillUnmount() {
- clearInterval(this.interval);
- }
+ componentWillUnmount() {
+ clearInterval(this.interval);
+ }
- changePage(pageNum) {
- if (pageNum < 0 || pageNum >= Math.ceil(this.state.numTransactions / Constants.numTransactionsPerPage) + 1) {
- return
- }
-
- this.setState({
- pageNum,
- }, this.updateTransactions);
+ changePage(pageNum) {
+ if (pageNum < 0 || pageNum >= Math.ceil(this.state.numTransactions / Constants.numTransactionsPerPage) + 1) {
+ return
}
- render() {
- const { t } = this.props;
-
- const syncedMsg = this.state.walletHeight + 10 >= this.state.networkHeight ?
- ''
- : t('notSyncedMessage');
-
- const noTransactions =
-
-
- {t('noTxMessage')}
- {syncedMsg}
-
- ;
-
- return(
- this.state.numTransactions === 0 ?
- noTransactions
- :
- );
- }
+ this.setState({
+ pageNum,
+ }, this.updateTransactions);
+ }
+
+ render() {
+ const { t } = this.props;
+ const syncedMsg = this.state.walletHeight + 10 >= this.state.networkHeight ?
+ ''
+ : t('notSyncedMessage');
+
+ return (
+
+
+ {t('transactionHistory')}
+
+ {this.state.numTransactions === 0 && (
+
+
+ {t('noTxMessage')}
+
+
+ {syncedMsg}
+
+
+ )}
+
+ {this.state.numTransactions > 0 && (
+
+ )}
+
+ );
+ }
}
export const TransactionsScreen = withTranslation()(TransactionsScreenNoTranslation)
class TransactionListNoTranslation extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- index: 0,
- }
- }
-
- getIconName(transaction) {
- if (transaction.totalAmount() >= 0) {
- return 'ios-arrow-dropleft';
- }
+ constructor(props) {
+ super(props);
- return 'ios-arrow-dropright';
+ this.state = {
+ index: 0,
}
+ }
- getIconColour(transaction) {
- if (transaction.totalAmount() >= 0) {
- /* Intentionally using the TurtleCoin green here, instead of the
- theme colour - we want green/red, not to change based on theme */
- return '#40C18E';
- }
-
- return 'red';
+ getIconName(transaction) {
+ if (transaction.totalAmount() >= 0) {
+ return 'ios-arrow-dropleft';
}
- /* Dumb hack because the flatlist won't re-render when we change the theme
- otherwise */
- componentWillReceiveProps(nextProps) {
- this.setState(prevState => ({
- index: prevState.index + 1,
- }));
- }
+ return 'ios-arrow-dropright';
+ }
- getMaxPage() {
- return Math.ceil(this.props.numTransactions / Constants.numTransactionsPerPage);
+ getIconColour(transaction) {
+ if (transaction.totalAmount() >= 0) {
+ /* Intentionally using the TurtleCoin green here, instead of the
+ theme colour - we want green/red, not to change based on theme */
+ return '#40C18E';
}
- render() {
- const { t } = this.props;
- return(
-
-
-
- {t('transactionHistory')}
-
-
- {
- if (this.props.pageNum <= 0) {
- return;
- }
-
- this.props.changePage(this.props.pageNum - 1);
- }
- }}
- centerComponent={{
- text: `${t('page')} ${this.props.pageNum + 1} / ${this.getMaxPage()}`,
- style: {
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 16,
- fontFamily: 'Montserrat-SemiBold'
- }
- }}
- rightComponent={{
- icon: 'navigate-next',
- color: this.props.pageNum === this.getMaxPage() - 1 ? this.props.screenProps.theme.notVeryVisibleColour : this.props.screenProps.theme.primaryColour,
- onPress: () => {
- if (this.props.pageNum >= this.getMaxPage() - 1) {
- return;
- }
-
- this.props.changePage(this.props.pageNum + 1);
- }
- }}
- backgroundColor={this.props.screenProps.theme.backgroundColour}
- />
-
-
- item.hash}
- renderItem={({item}) => (
-
- 0 ? 0 : item.fee), Config)}
- subtitle={item.timestamp === 0 ? t('processing') + prettyPrintDate2(Date.now() / 1000) : t('completed') + prettyPrintDate2(item.timestamp)}
- leftIcon={
-
-
-
- }
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontFamily: 'Montserrat-SemiBold'
- }}
- subtitleStyle={{
- color: this.props.screenProps.theme.slightlyMoreVisibleColour,
- fontFamily: 'Montserrat-Regular'
- }}
- onPress={() => this.props.navigation.navigate('TransactionDetails', { transaction: item })}
- />
-
- )}
- />
-
-
- )
- }
+ return 'red';
+ }
+
+ /* Dumb hack because the flatlist won't re-render when we change the theme
+ otherwise */
+ componentWillReceiveProps(nextProps) {
+ this.setState(prevState => ({
+ index: prevState.index + 1,
+ }));
+ }
+
+ getMaxPage() {
+ return Math.ceil(this.props.numTransactions / Constants.numTransactionsPerPage);
+ }
+
+ render() {
+ const { t } = this.props;
+ return (
+ <>
+ {
+ if (this.props.pageNum <= 0) {
+ return;
+ }
+
+ this.props.changePage(this.props.pageNum - 1);
+ }
+ }}
+ centerComponent={{
+ text: `${t('page')} ${this.props.pageNum + 1} / ${this.getMaxPage()}`,
+ style: {
+ color: this.props.screenProps.theme.primaryColour,
+ fontSize: 16,
+ fontFamily: 'Montserrat-SemiBold'
+ }
+ }}
+ rightComponent={{
+ icon: 'navigate-next',
+ color: this.props.pageNum === this.getMaxPage() - 1 ? this.props.screenProps.theme.notVeryVisibleColour : this.props.screenProps.theme.primaryColour,
+ onPress: () => {
+ if (this.props.pageNum >= this.getMaxPage() - 1) {
+ return;
+ }
+
+ this.props.changePage(this.props.pageNum + 1);
+ }
+ }}
+ backgroundColor={this.props.screenProps.theme.backgroundColour} />
+ item.hash}
+ renderItem={({ item }) => (
+
+ 0 ? 0 : item.fee), Config)}
+ subtitle={item.timestamp === 0 ? t('processing') + prettyPrintDate2(Date.now() / 1000) : t('completed') + prettyPrintDate2(item.timestamp)}
+ leftIcon={
+
+ }
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontFamily: 'Montserrat-SemiBold'
+ }}
+ subtitleStyle={{
+ color: this.props.screenProps.theme.slightlyMoreVisibleColour,
+ fontFamily: 'Montserrat-Regular'
+ }}
+ onPress={() => this.props.navigation.navigate('TransactionDetails', { transaction: item })} />
+ )} />
+
+ >
+ )
+ }
}
export const TransactionList = withTranslation()(TransactionListNoTranslation)
diff --git a/src/TransferScreen.js b/src/TransferScreen.js
index 7c065a8..2c8ef42 100644
--- a/src/TransferScreen.js
+++ b/src/TransferScreen.js
@@ -7,7 +7,6 @@ import React from 'react';
import * as Animatable from 'react-native-animatable';
import AntDesign from 'react-native-vector-icons/AntDesign';
-import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
import QRCodeScanner from 'react-native-qrcode-scanner';
@@ -16,32 +15,30 @@ import TextTicker from 'react-native-text-ticker';
import { HeaderButtons, HeaderButton, Item } from 'react-navigation-header-buttons';
import { HeaderBackButton, StackActions } from 'react-navigation';
-import {get_avatar} from './HuginUtilities'
+import { get_avatar } from './HuginUtilities'
import {
- validateAddresses, WalletErrorCode, validatePaymentID, prettyPrintAmount,
+ validateAddresses, WalletErrorCode, validatePaymentID, prettyPrintAmount,
} from 'kryptokrona-wallet-backend-js';
import {
- Alert, View, Text, TextInput, TouchableWithoutFeedback, TouchableOpacity, FlatList, Platform,
- ScrollView, Clipboard, Image
+ Alert, View, Text, FlatList, Platform,
+ ScrollView, Clipboard, Image
} from 'react-native';
-import { Input, Button } from 'react-native-elements';
+import { Input } from 'react-native-elements';
import Config from './Config';
import ListItem from './ListItem';
-import List from './ListContainer';
import Constants from './Constants'
-import { Styles } from './Styles';
import { Globals } from './Globals';
import { Authenticate } from './Authenticate';
-import { Hr, BottomButton } from './SharedComponents';
-import { removeFee, toAtomic, fromAtomic, addFee } from './Fee';
+import { BottomButton } from './SharedComponents';
+import { toAtomic, fromAtomic } from './Fee';
import {
- getArrivalTime, navigateWithDisabledBack, delay, toastPopUp, handleURI,
- validAmount,
+ getArrivalTime, navigateWithDisabledBack, delay, toastPopUp, handleURI,
+ validAmount,
} from './Utilities';
import Identicon from 'identicon.js';
@@ -49,8 +46,9 @@ import Identicon from 'identicon.js';
import CustomIcon from './CustomIcon.js'
import './i18n.js';
+import i18next from './i18n.js';
import { withTranslation } from 'react-i18next';
-import i18next from './i18n';
+import { TextField, InputField, Button, ScreenLayout, ScreenHeader, Card } from './components';
const intToRGB = (int) => {
@@ -71,1583 +69,1362 @@ const intToRGB = (int) => {
}
-String.prototype.hashCode = function() {
- var hash = 0;
- if (this.length == 0) {
- return hash;
- }
- for (var i = 0; i < this.length; i++) {
- var char = this.charCodeAt(i);
- hash = ((hash<<5)-hash)+char;
- hash = hash & hash; // Convert to 32bit integer
- }
+String.prototype.hashCode = function () {
+ var hash = 0;
+ if (this.length == 0) {
return hash;
+ }
+ for (var i = 0; i < this.length; i++) {
+ var char = this.charCodeAt(i);
+ hash = ((hash << 5) - hash) + char;
+ hash = hash & hash; // Convert to 32bit integer
+ }
+ return hash;
}
const hashCode = (str) => {
- let hash = Math.abs(str.hashCode())*0.007812499538;
- return Math.floor(hash);
+ let hash = Math.abs(str.hashCode()) * 0.007812499538;
+ return Math.floor(hash);
}
export class QrScannerScreen extends React.Component {
- constructor(props) {
- super(props);
- }
-
- render() {
- return(
-
- {
- // this.props.navigation.goBack();
-
- this.props.navigation.state.params.setAddress(code.data);
- }}
- cameraProps={{captureAudio: false}}
- />
-
- );
- }
-}
-
-class AmountInput extends React.Component {
- constructor(props) {
- super(props);
- }
+ constructor(props) {
+ super(props);
+ }
- render() {
- return(
-
- {Config.ticker}
-
- }
- keyboardType={'number-pad'}
- inputStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: this.props.fontSize || 30,
- marginLeft: 5
- }}
- errorMessage={this.props.errorMessage}
- value={this.props.value}
- onChangeText={(text) => this.props.onChangeText(text)}
- />
- );
- }
+ render() {
+ return (
+
+ {
+ // this.props.navigation.goBack();
+ this.props.navigation.state.params.setAddress(code.data);
+ }}
+ cameraProps={{ captureAudio: false }}
+ />
+
+ );
+ }
}
const CrossIcon = passMeFurther => (
-
+
);
class CrossButton extends React.Component {
- constructor(props) {
- super(props);
- }
+ constructor(props) {
+ super(props);
+ }
- render() {
- return(
-
- - {
- this.props.navigation.dispatch(StackActions.popToTop());
- this.props.navigation.navigate('Main');
- }}
- buttonWrapperStyle={{ marginRight: 10 }}
- />
-
- );
- }
+ render() {
+ return (
+
+ - {
+ this.props.navigation.dispatch(StackActions.popToTop());
+ this.props.navigation.navigate('Main');
+ }}
+ buttonWrapperStyle={{ marginRight: 10 }}
+ />
+
+ );
+ }
}
/**
* Send a transaction
*/
export class TransferScreenNoTranslation extends React.Component {
- static navigationOptions = ({ navigation, screenProps }) => {
- return {
- title: '',
- headerRight: (
-
- ),
- }
- };
-
- constructor(props) {
- super(props);
-
- this.state = {
- errMsg: '',
- continueEnabled: false,
- sendAll: false,
- amountFontSize: 30,
- unlockedBalance: 0,
- lockedBalance: 0,
- unlockedBalanceHuman: 0,
- }
+ static navigationOptions = ({ navigation, screenProps }) => {
+ return {
+ title: '',
+ headerRight: (
+
+ ),
}
+ };
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ errMsg: '',
+ continueEnabled: false,
+ sendAll: false,
+ amountFontSize: 30,
+ unlockedBalance: 0,
+ lockedBalance: 0,
+ unlockedBalanceHuman: 0,
+ }
+ }
- async componentDidMount() {
- const [unlockedBalance, lockedBalance] = await Globals.wallet.getBalance();
+ async componentDidMount() {
+ const [unlockedBalance, lockedBalance] = await Globals.wallet.getBalance();
- this.setState({
- unlockedBalance,
- lockedBalance,
- unlockedBalanceHuman: fromAtomic(unlockedBalance),
- });
+ this.setState({
+ unlockedBalance,
+ lockedBalance,
+ unlockedBalanceHuman: fromAtomic(unlockedBalance),
+ });
- this.interval = setInterval(() => this.tick(), 10000);
- }
+ this.interval = setInterval(() => this.tick(), 10000);
+ }
- async tick() {
- const [unlockedBalance, lockedBalance] = await Globals.wallet.getBalance();
+ async tick() {
+ const [unlockedBalance, lockedBalance] = await Globals.wallet.getBalance();
+
+ this.setState({
+ unlockedBalance,
+ lockedBalance,
+ unlockedBalanceHuman: fromAtomic(unlockedBalance),
+ });
+ }
+ checkErrors(amount) {
+ if (this.state.sendAll) {
+ if (this.state.unlockedBalance > 1) {
this.setState({
- unlockedBalance,
- lockedBalance,
- unlockedBalanceHuman: fromAtomic(unlockedBalance),
+ continueEnabled: true,
+ amountAtomic: this.state.unlockedBalance,
+ errMsg: '',
});
+ } else {
+ this.setState({
+ continueEnabled: false,
+ errMsg: 'Not enough funds available!',
+ });
+ }
+ } else {
+ const [valid, error] = validAmount(amount, this.state.unlockedBalance);
+
+ this.setState({
+ continueEnabled: valid,
+ errMsg: error,
+ });
}
+ }
- checkErrors(amount) {
- if (this.state.sendAll) {
- if (this.state.unlockedBalance > 1) {
- this.setState({
- continueEnabled: true,
- amountAtomic: this.state.unlockedBalance,
- errMsg: '',
- });
- } else {
- this.setState({
- continueEnabled: false,
- errMsg: 'Not enough funds available!',
- });
- }
- } else {
- const [valid, error] = validAmount(amount, this.state.unlockedBalance);
-
- this.setState({
- continueEnabled: valid,
- errMsg: error,
- });
- }
- }
+ componentWillUnmount() {
+ clearInterval(this.interval);
+ }
- componentWillUnmount() {
- clearInterval(this.interval);
- }
- render() {
- const { t } = this.props;
- // const otherCoinValue = toString(this.state.amount * Globals.coinPrice);
- // console.log('otherCoinValue', otherCoinValue);
- // const otherCoin = Constants.currencies.filter( c => {return c.ticker == Globals.preferences.currency});
- // const otherCoinFormatting = otherCoin.symbolLocation == 'prefix' ? otherCoin.symbol + otherCoinValue : otherCoinValue + otherCoin.symbol + " ";
- // console.log('otherCoinFormatting', otherCoinFormatting);
- const otherCoinAmount = (this.state.amount * Globals.coinPrice).toFixed(2);
- const otherCoin = Constants.currencies.filter( c => {return c.ticker == Globals.preferences.currency})[0];
- const otherCoinFormatting = otherCoinAmount ? otherCoin.symbol + otherCoinAmount : false;
-
- return(
-
-
-
- {t('transferTitle').replace('{name}', this.props.navigation.state.params.payee.nickname)}
-
-
- {
- this.setState({
- amount: text,
- amountAtomic: toAtomic(text),
- sendAll: false,
- amountFontSize: 30,
- }, () => {
- this.checkErrors(this.state.amount);
- });
- }}
- errorMessage={this.state.errMsg}
- {...this.props}
- />
-
-
- {otherCoinAmount > 0 &&
-
-
- {otherCoinFormatting}
-
-
- }
-{/*
- {
- this.setState({
- amount: ((this.state.unlockedBalance / 100000)).toFixed(5),
- amountAtomic: this.state.unlockedBalance,
- sendAll: true
- }, () => {
- this.checkErrors(this.state.amount);
- });
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- }}
- type="clear"
- /> */}
-
-
-
-
- {t('shouldArriveIn')} {getArrivalTime([t('minute'), t('second')])}
-
-
- {
- this.props.navigation.navigate(
- 'Confirm', {
- payee: this.props.navigation.state.params.payee,
- sendAll: this.state.sendAll,
- amount: this.state.amountAtomic,
- }
- );
- }}
- disabled={!this.state.continueEnabled}
- {...this.props}
- />
-
-
-
- );
- }
+ render() {
+ const { t } = this.props;
+ // const otherCoinValue = toString(this.state.amount * Globals.coinPrice);
+ // console.log('otherCoinValue', otherCoinValue);
+ // const otherCoin = Constants.currencies.filter( c => {return c.ticker == Globals.preferences.currency});
+ // const otherCoinFormatting = otherCoin.symbolLocation == 'prefix' ? otherCoin.symbol + otherCoinValue : otherCoinValue + otherCoin.symbol + " ";
+ // console.log('otherCoinFormatting', otherCoinFormatting);
+ const otherCoinAmount = (this.state.amount * Globals.coinPrice).toFixed(2);
+ const otherCoin = Constants.currencies.filter(c => { return c.ticker == Globals.preferences.currency })[0];
+ const otherCoinFormatting = otherCoinAmount ? otherCoin.symbol + otherCoinAmount : false;
+
+ return (
+
+
+ {t('transferTitle').replace('{name}', this.props.navigation.state.params.payee.nickname)}
+
+
+ {
+ this.setState({
+ amount: text,
+ amountAtomic: toAtomic(text),
+ sendAll: false,
+ amountFontSize: 30,
+ }, () => {
+ this.checkErrors(this.state.amount);
+ });
+ }}
+ rightIcon={
+
+ {Config.ticker}
+
+ }
+ keyboardType={'number-pad'}
+ errorMessage={this.state.errMsg}
+ />
+ {otherCoinAmount > 0 &&
+
+ {otherCoinFormatting}
+
+ }
+
+ {
+ this.setState({
+ amount: ((this.state.unlockedBalance / 100000)).toFixed(5),
+ amountAtomic: this.state.unlockedBalance,
+ sendAll: true
+ }, () => {
+ this.checkErrors(this.state.amount);
+ });
+ }}
+ type="clear"
+ >
+ {t('sendMaxButton')}
+
+ {
+ this.props.navigation.navigate(
+ 'Confirm', {
+ payee: this.props.navigation.state.params.payee,
+ sendAll: this.state.sendAll,
+ amount: this.state.amountAtomic,
+ }
+ );
+ }}
+ disabled={!this.state.continueEnabled}
+ >
+
+ {t('continue')}
+
+
+
+
+
+
+ {t('shouldArriveIn')} {getArrivalTime([t('minute'), t('second')])}
+
+
+ );
+ }
}
export const TransferScreen = withTranslation()(TransferScreenNoTranslation)
class AddressBook extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {
- payees: Globals.payees,
- index: 0,
- };
-
- Globals.updatePayeeFunctions.push(() => {
- this.setState(prevState => ({
- payees: Globals.payees,
- index: prevState.index + 1,
- }))
- });
- }
-
- render() {
- const payees = this.state.payees;
- function get_avatar(hash) {
- // Displays a fixed identicon until user adds new contact address in the input field
- if (hash.length < 15) {
- hash = 'SEKReYanL2qEQF2HA8tu9wTpKBqoCA8TNb2mNRL5ZDyeFpxsoGNgBto3s3KJtt5PPrRH36tF7DBEJdjUn5v8eaESN2T5DPgRLVY';
- }
- // Get custom color scheme based on address
- let rgb = intToRGB(hashCode(hash));
-
- // Options for avatar
- var options = {
- foreground: [rgb.red, rgb.green, rgb.blue, 255], // rgba black
- background: [parseInt(rgb.red/10), parseInt(rgb.green/10), parseInt(rgb.blue/10), 0], // rgba white
- margin: 0.2, // 20% margin
- size: 50, // 420px square
- format: 'png' // use SVG instead of PNG
- };
-
- // create a base64 encoded SVG
- return 'data:image/png;base64,' + new Identicon(hash, options).toString();
- }
+ constructor(props) {
+ super(props);
+ this.state = {
+ payees: Globals.payees,
+ index: 0,
+ };
- return(
+ Globals.updatePayeeFunctions.push(() => {
+ this.setState(prevState => ({
+ payees: Globals.payees,
+ index: prevState.index + 1,
+ }))
+ });
+ }
-
- item.nickname}
- renderItem={({item}) => (
-
- }
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontFamily: 'Montserrat-SemiBold'
- }}
- subtitleStyle={{
- color: this.props.screenProps.theme.slightlyMoreVisibleColour,
- fontFamily: 'Montserrat-Regular'
- }}
- onLongPress={() => {
- Alert.alert(
- i18next.t('deleteContactWarning'),
- `${item.nickname} (${item.address})`,
- [
- {
- text: i18next.t('delete'), onPress: () => {
- (async () => {
- /* Disabling saving */
-
- Globals.removePayee(item.nickname, true);
- this.setState({
- payees: Globals.payees
- });
-
- })();
- }
- },
- { text: i18next.t('cancel'), style: 'cancel' },
- ],
- );
- }}
- delayLongPress={1500}
- onPress={() => {
- this.props.navigation.navigate(
- 'Transfer', {
- payee: item,
- }
- );
- }}
- />
- )}
- />
-
- );
+ render() {
+ const payees = this.state.payees;
+ function get_avatar(hash) {
+ // Displays a fixed identicon until user adds new contact address in the input field
+ if (hash.length < 15) {
+ hash = 'SEKReYanL2qEQF2HA8tu9wTpKBqoCA8TNb2mNRL5ZDyeFpxsoGNgBto3s3KJtt5PPrRH36tF7DBEJdjUn5v8eaESN2T5DPgRLVY';
+ }
+ // Get custom color scheme based on address
+ let rgb = intToRGB(hashCode(hash));
+
+ // Options for avatar
+ var options = {
+ foreground: [rgb.red, rgb.green, rgb.blue, 255], // rgba black
+ background: [parseInt(rgb.red / 10), parseInt(rgb.green / 10), parseInt(rgb.blue / 10), 0], // rgba white
+ margin: 0.2, // 20% margin
+ size: 50, // 420px square
+ format: 'png' // use SVG instead of PNG
+ };
+
+ // create a base64 encoded SVG
+ return 'data:image/png;base64,' + new Identicon(hash, options).toString();
}
-}
-class ExistingPayeesNoTranslation extends React.Component {
- constructor(props) {
- super(props);
- }
- render() {
- const { t } = this.props;
- const noPayeesComponent =
-
-
- {t('emptyAddressBook')}
-
-
+ return (
+
+
+ item.nickname}
+ renderItem={({ item }) => (
+
+ }
+ titleStyle={{
+ color: this.props.screenProps.theme.primaryColour,
+ fontFamily: 'Montserrat-SemiBold'
+ }}
+ subtitleStyle={{
+ color: this.props.screenProps.theme.slightlyMoreVisibleColour,
+ fontFamily: 'Montserrat-Regular'
+ }}
+ onLongPress={() => {
+ Alert.alert(
+ i18next.t('deleteContactWarning'),
+ `${item.nickname} (${item.address})`,
+ [
+ {
+ text: i18next.t('delete'), onPress: () => {
+ (async () => {
+ /* Disabling saving */
+
+ Globals.removePayee(item.nickname, true);
+ this.setState({
+ payees: Globals.payees
+ });
+
+ })();
+ }
+ },
+ { text: i18next.t('cancel'), style: 'cancel' },
+ ],
+ );
+ }}
+ delayLongPress={1500}
+ onPress={() => {
+ this.props.navigation.navigate(
+ 'Transfer', {
+ payee: item,
+ }
+ );
+ }}
+ />
+ )}
+ />
+
+ );
+ }
+}
- return(
-
-
+class ExistingPayeesNoTranslation extends React.Component {
+ constructor(props) {
+ super(props);
+ }
- {Globals.payees.length > 0 ? : noPayeesComponent}
-
-
- );
- }
+ render() {
+ const { t } = this.props;
+ const noPayeesComponent =
+
+
+ {t('emptyAddressBook')}
+
+
+
+ return (
+
+ {Globals.payees.length > 0 ? : noPayeesComponent}
+
+ );
+ }
}
const ExistingPayees = withTranslation()(ExistingPayeesNoTranslation)
export class NewPayeeScreenNoTranslation extends React.Component {
- static navigationOptions = ({ navigation }) => {
- return {
- headerRight: (
-
- ),
- }
+ static navigationOptions = ({ navigation }) => {
+ return {
+ headerRight: (
+
+ ),
+ }
+ };
+
+ constructor(props) {
+ super(props);
+
+ const address = this.props.navigation.getParam('address', '');
+ const paymentID = this.props.navigation.getParam('paymentID', '');
+
+ this.state = {
+ nickname: '',
+ address,
+ paymentID,
+ paymentIDEnabled: address.length !== Config.integratedAddressLength,
+ addressError: '',
+ paymentIDError: '',
+ nicknameError: '',
};
- constructor(props) {
- super(props);
-
- const address = this.props.navigation.getParam('address', '');
- const paymentID = this.props.navigation.getParam('paymentID', '');
-
- this.state = {
- nickname: '',
- address,
- paymentID,
- paymentIDEnabled: address.length !== Config.integratedAddressLength,
- addressError: '',
- paymentIDError: '',
- nicknameError: '',
- };
- }
+ this.onContinuePress = this.onContinuePress.bind(this);
- setAddressFromQrCode(address) {
- this.setState({
- address,
- }, () => this.checkErrors());
- }
+ }
- async validAddress(address) {
- let errorMessage = '';
+ setAddressFromQrCode(address) {
+ this.setState({
+ address,
+ }, () => this.checkErrors());
+ }
- if (Globals.payees.some((payee) => payee.address === address)) {
- errorMessage = `A payee with the address ${address} already exists.`;
- return [false, errorMessage];
- }
+ async validAddress(address) {
+ let errorMessage = '';
- if (address === '' || address === undefined || address === null) {
- return [false, errorMessage];
- }
- /* Disable payment ID and wipe input if integrated address */
- if (address.length === Config.integratedAddressLength) {
- await this.setState({
- paymentID: '',
- paymentIDEnabled: false,
- });
- } else {
- this.setState({
- paymentIDEnabled: true,
- });
- }
+ if (Globals.payees.some((payee) => payee.address === address)) {
+ errorMessage = `A payee with the address ${address} already exists.`;
+ return [false, errorMessage];
+ }
+
+ if (address === '' || address === undefined || address === null) {
+ return [false, errorMessage];
+ }
- if (address.length === 163) {
- // Hugin address
+ /* Disable payment ID and wipe input if integrated address */
+ if (address.length === Config.integratedAddressLength) {
+ await this.setState({
+ paymentID: '',
+ paymentIDEnabled: false,
+ });
+ } else {
+ this.setState({
+ paymentIDEnabled: true,
+ });
+ }
- await this.setState({
- address: address.substring(0,99),
- paymentID: address.substring(99),
- paymentIDEnabled: true
- });
- address = address.substring(0,99);
- }
- const addressError = await validateAddresses([address], true, Config);
+ if (address.length === 163) {
+ // Hugin address
- if (addressError.errorCode !== WalletErrorCode.SUCCESS) {
- errorMessage = addressError.toString();
+ await this.setState({
+ address: address.substring(0, 99),
+ paymentID: address.substring(99),
+ paymentIDEnabled: true
+ });
+ address = address.substring(0, 99);
+ }
+ const addressError = await validateAddresses([address], true, Config);
- return [false, errorMessage];
- }
+ if (addressError.errorCode !== WalletErrorCode.SUCCESS) {
+ errorMessage = addressError.toString();
- return [true, errorMessage];
+ return [false, errorMessage];
}
- validPaymentID(paymentID) {
- let errorMessage = '';
+ return [true, errorMessage];
+ }
- if (paymentID === '') {
- return [true, errorMessage];
- }
+ validPaymentID(paymentID) {
+ let errorMessage = '';
- if (paymentID === undefined || paymentID === null) {
- return [false, errorMessage];
- }
+ if (paymentID === '') {
+ return [true, errorMessage];
+ }
- const paymentIDError = validatePaymentID(paymentID);
+ if (paymentID === undefined || paymentID === null) {
+ return [false, errorMessage];
+ }
- if (paymentIDError.errorCode !== WalletErrorCode.SUCCESS) {
- errorMessage = paymentIDError.toString();
+ const paymentIDError = validatePaymentID(paymentID);
- return [false, errorMessage];
- }
+ if (paymentIDError.errorCode !== WalletErrorCode.SUCCESS) {
+ errorMessage = paymentIDError.toString();
- return [true, errorMessage];
+ return [false, errorMessage];
}
- validNickname(nickname) {
- let errorMessage = '';
+ return [true, errorMessage];
+ }
- if (nickname === '' || nickname === undefined || nickname === null) {
- return [false, errorMessage];
- }
+ validNickname(nickname) {
+ let errorMessage = '';
- if (Globals.payees.some((payee) => payee.nickname === nickname)) {
- errorMessage = `A payee with the name ${nickname} already exists.`;
- return [false, errorMessage];
- }
+ if (nickname === '' || nickname === undefined || nickname === null) {
+ return [false, errorMessage];
+ }
- return [true, errorMessage];
+ if (Globals.payees.some((payee) => payee.nickname === nickname)) {
+ errorMessage = `A payee with the name ${nickname} already exists.`;
+ return [false, errorMessage];
}
- checkErrors() {
- (async() => {
+ return [true, errorMessage];
+ }
+
+ checkErrors() {
+ (async () => {
- const [addressValid, addressError] = await this.validAddress(this.state.address);
- const [paymentIDValid, paymentIDError] = this.validPaymentID(this.state.paymentID);
- const [nicknameValid, nicknameError] = this.validNickname(this.state.nickname);
+ const [addressValid, addressError] = await this.validAddress(this.state.address);
+ const [paymentIDValid, paymentIDError] = this.validPaymentID(this.state.paymentID);
+ const [nicknameValid, nicknameError] = this.validNickname(this.state.nickname);
- this.setState({
- continueEnabled: addressValid && paymentIDValid && nicknameValid,
- addressError,
- paymentIDError,
- nicknameError,
- });
+ this.setState({
+ continueEnabled: addressValid && paymentIDValid && nicknameValid,
+ addressError,
+ paymentIDError,
+ nicknameError,
+ });
- })();
- }
+ })();
+ }
- render() {
- const { t } = this.props;
- return(
-
-
-
- {t('newContact')}
-
-
-
-
-
- {
- this.setState({
- nickname: text,
- }, () => this.checkErrors());
- }}
- errorMessage={this.state.nicknameError}
- />
-
- {
- this.setState({
- address: text,
- }, () => this.checkErrors());
- }}
- errorMessage={this.state.addressError}
- />
- {this.state.address != '' &&
- {
- this.setState({
- paymentID: text
- }, () => this.checkErrors());
- }}
- editable={this.state.paymentIDEnabled}
- errorMessage={this.state.paymentIDError}
- />
- }
-
-
- {
- const func = (data) => {
- if (data.startsWith(Config.uriPrefix)) {
- handleURI(data, this.props.navigation);
- } else {
- this.setState({
- address: data,
- // paymentID: data.substring(99),
- }, () => this.checkErrors());
- }
- };
-
- this.props.navigation.navigate('QrScanner', {
- setAddress: func
- });
- }}
- >
-
-
- {t('scanQR')}
-
-
-
- {
- const payee = {
- nickname: this.state.nickname,
- address: this.state.address,
- paymentID: this.state.paymentID,
- };
-
- /* Add payee to global payee store */
- Globals.addPayee(payee);
-
- const finishFunction = Globals.fromChat; // = this.props.navigation.getParam('finishFunction', undefined);
-
- if (finishFunction) {
- Globals.fromChat = false;
- this.props.navigation.dispatch(StackActions.popToTop());
- this.props.navigation.navigate(
- 'ChatScreen', {
- payee: payee,
- });
-
- return;
-
- } else {
- const amount = this.props.navigation.getParam('amount', undefined);
-
- /* Already have an amount, don't need to go to transfer screen */
- if (amount) {
- this.props.navigation.navigate(
- 'Confirm', {
- payee,
- amount,
- }
- );
-
- } else {
- this.props.navigation.navigate(
- 'Transfer', {
- payee,
- }
- );
- }
- }
- }}
- disabled={!this.state.continueEnabled}
- {...this.props}
- />
-
-
- );
+ onContinuePress = () => {
+ const payee = {
+ nickname: this.state.nickname,
+ address: this.state.address,
+ paymentID: this.state.paymentID,
+ };
+
+ Globals.addPayee(payee);
+
+ const finishFunction = Globals.fromChat;
+
+ if (finishFunction) {
+ Globals.fromChat = false;
+ this.props.navigation.dispatch(StackActions.popToTop());
+ this.props.navigation.navigate('ChatScreen', { payee });
+ } else {
+ const amount = this.props.navigation.getParam('amount', undefined);
+ if (amount) {
+ this.props.navigation.navigate('Confirm', { payee, amount });
+ } else {
+ this.props.navigation.navigate('Transfer', { payee });
+ }
}
+ }
+
+ render() {
+ const { t } = this.props;
+
+ return (
+
+
+ {t('newContact')}
+
+
+
+ {
+ this.setState({
+ nickname: text,
+ }, () => this.checkErrors());
+ }}
+ errorMessage={this.state.nicknameError}
+ />
+
+ {
+ this.setState({
+ address: text,
+ }, () => this.checkErrors());
+ }}
+ errorMessage={this.state.addressError}
+ />
+ {/* {this.state.address != '' &&
+ {
+ this.setState({
+ paymentID: text
+ }, () => this.checkErrors());
+ }}
+ editable={this.state.paymentIDEnabled}
+ errorMessage={this.state.paymentIDError}
+ />
+ } */}
+
+
+ }
+ onPress={() => {
+ const func = (data) => {
+ if (data.startsWith(Config.uriPrefix)) {
+ handleURI(data, this.props.navigation);
+ } else {
+ this.setState({
+ address: data,
+ // paymentID: data.substring(99),
+ }, () => this.checkErrors());
+ }
+ };
+
+ this.props.navigation.navigate('QrScanner', {
+ setAddress: func
+ });
+ }}
+ >
+
+ {t('scanQR')}
+
+
+
+
+ {t('continue')}
+
+
+
+
+ );
+ }
}
export const NewPayeeScreen = withTranslation()(NewPayeeScreenNoTranslation)
class ModifyMemo extends React.Component {
- constructor(props) {
- super(props);
- }
+ constructor(props) {
+ super(props);
+ }
- render() {
- return(
- {
- if (this.props.onChange) {
- this.props.onChange(text);
- }
- }}
- />
- );
- }
+ render() {
+ return (
+ {
+ if (this.props.onChange) {
+ this.props.onChange(text);
+ }
+ }}
+ />
+ );
+ }
}
export class ConfirmScreenNoTranslation extends React.Component {
- static navigationOptions = ({ navigation }) => {
- return {
- headerRight: (
-
- ),
- }
+ static navigationOptions = ({ navigation }) => {
+ return {
+ headerRight: (
+
+ ),
+ }
+ };
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
};
+ }
- constructor(props) {
- super(props);
+ async componentDidMount() {
+ const [unlockedBalance, lockedBalance] = await Globals.wallet.getBalance();
- this.state = {
- };
- }
+ const { payee, amount, sendAll } = this.props.navigation.state.params;
- async componentDidMount() {
- const [unlockedBalance, lockedBalance] = await Globals.wallet.getBalance();
+ const fullAmount = sendAll ? unlockedBalance : amount;
- const { payee, amount, sendAll } = this.props.navigation.state.params;
+ const devFee = Math.floor((fullAmount * Config.devFeePercentage) / 100);
- const fullAmount = sendAll ? unlockedBalance : amount;
+ const [feeAddress, nodeFee] = Globals.wallet.getNodeFee();
- const devFee = Math.floor((fullAmount * Config.devFeePercentage) / 100);
+ this.setState({
+ memo: '',
+ modifyMemo: false,
+ preparedTransaction: false,
+ haveError: false,
+ payee,
+ amount,
+ sendAll,
+ unlockedBalance,
+ devFee,
+ nodeFee,
+ });
- const [feeAddress, nodeFee] = Globals.wallet.getNodeFee();
+ this.prepareTransaction();
+ }
- this.setState({
- memo: '',
- modifyMemo: false,
- preparedTransaction: false,
- haveError: false,
- payee,
- amount,
- sendAll,
- unlockedBalance,
- devFee,
- nodeFee,
- });
+ async prepareTransaction() {
+ const payments = [];
+
+ /* User payment */
+ if (this.state.sendAll) {
+ payments.push([
+ this.state.payee.address,
+ 1, /* Amount does not matter for sendAll destination */
+ ]);
+ } else {
+ payments.push([
+ this.state.payee.address,
+ this.state.amount,
+ ]);
+ }
- this.prepareTransaction();
+ if (this.state.devFee > 0) {
+ /* Dev payment */
+ payments.push([
+ Config.devFeeAddress,
+ this.state.devFee,
+ ]);
}
- async prepareTransaction() {
- const payments = [];
-
- /* User payment */
- if (this.state.sendAll) {
- payments.push([
- this.state.payee.address,
- 1, /* Amount does not matter for sendAll destination */
- ]);
- } else {
- payments.push([
- this.state.payee.address,
- this.state.amount,
- ]);
+ // let [new_address, error] = await Globals.wallet.addSubWallet();
+
+ const result = await Globals.wallet.sendTransactionAdvanced(
+ payments, // destinations,
+ 3, // mixin
+ { fixedFee: 1000, isFixedFee: true }, // fee
+ this.state.payee.paymentID,
+ undefined, // subWalletsToTakeFrom
+ undefined, // changeAddress
+ false, // relayToNetwork
+ this.state.sendAll,
+ );
+
+ if (result.success) {
+ let actualAmount = this.state.amount;
+ for (const input of result.preparedTransaction.inputs) {
+ }
+ if (this.state.sendAll) {
+ let transactionSum = 0;
+
+ /* We could just get the sum by calling getBalance.. but it's
+ * possibly just changed. Safest to iterate over prepared
+ * transaction and calculate it. */
+ for (const input of result.preparedTransaction.inputs) {
+ transactionSum += input.input.amount;
}
- if (this.state.devFee > 0) {
- /* Dev payment */
- payments.push([
- Config.devFeeAddress,
- this.state.devFee,
- ]);
- }
+ actualAmount = transactionSum
+ - result.fee
+ - this.state.devFee
+ - this.state.nodeFee;
+ }
+
+ this.setState({
+ preparedTransaction: true,
+ haveError: false,
+ fee: result.fee,
+ hash: result.transactionHash,
+ recipientAmount: actualAmount,
+ feeTotal: result.fee + this.state.devFee + this.state.nodeFee,
+ });
+ } else {
+ this.setState({
+ preparedTransaction: true,
+ haveError: true,
+ error: result.error,
+ });
+ }
+ }
- // let [new_address, error] = await Globals.wallet.addSubWallet();
-
- const result = await Globals.wallet.sendTransactionAdvanced(
- payments, // destinations,
- 3, // mixin
- {fixedFee: 1000, isFixedFee: true}, // fee
- this.state.payee.paymentID,
- undefined, // subWalletsToTakeFrom
- undefined, // changeAddress
- false, // relayToNetwork
- this.state.sendAll,
- );
-
- if (result.success) {
- let actualAmount = this.state.amount;
- for (const input of result.preparedTransaction.inputs) {
- }
- if (this.state.sendAll) {
- let transactionSum = 0;
-
- /* We could just get the sum by calling getBalance.. but it's
- * possibly just changed. Safest to iterate over prepared
- * transaction and calculate it. */
- for (const input of result.preparedTransaction.inputs) {
- transactionSum += input.input.amount;
- }
+ preparingScreen(t) {
+ return (
+
+
+ {t('estimating')}
+
+
+ );
+ }
- actualAmount = transactionSum
- - result.fee
- - this.state.devFee
- - this.state.nodeFee;
- }
+ errorScreen() {
+ let errorMessage = this.state.error.toString();
- this.setState({
- preparedTransaction: true,
- haveError: false,
- fee: result.fee,
- hash: result.transactionHash,
- recipientAmount: actualAmount,
- feeTotal: result.fee + this.state.devFee + this.state.nodeFee,
- });
- } else {
- this.setState({
- preparedTransaction: true,
- haveError: true,
- error: result.error,
- });
- }
+ if (this.state.error.errorCode === WalletErrorCode.NOT_ENOUGH_BALANCE) {
+ if (this.state.sendAll) {
+ errorMessage = 'Unfortunately, your balance is too low to cover the network fee required to send your funds.';
+ } else {
+ errorMessage = 'Not enough balance to cover amount including fees!\n' +
+ 'Either reduce the amount you are sending, or use the "send all" option to send the max possible.\n\n';
+ }
}
- preparingScreen(t) {
- return(
+ return (
+
+
+ Estimating fee and preparing transaction failed!
+
+
+
+ {errorMessage}
+
+
+ );
+ }
+
+ confirmScreen(t) {
+ return (
+
+
+
+ {t('reviewTitle')}
+
+
+
+
+
+
+
+ {prettyPrintAmount(this.state.recipientAmount, Config)}{' '}
+
+ will reach{' '}
+
+ {this.state.payee.nickname}'s{' '}
+
+ account, in {getArrivalTime([t('minute'), t('second')])}
+
+
-
+
+ {t('notes')}
+
+
+ {
+ this.setState({
+ modifyMemo: !this.state.modifyMemo,
+ });
+ }}
+ type="clear"
>
- {t('estimating')}
-
+ {t('change')}
+
+
- );
- }
- errorScreen() {
- let errorMessage = this.state.error.toString();
-
- if (this.state.error.errorCode === WalletErrorCode.NOT_ENOUGH_BALANCE) {
- if (this.state.sendAll) {
- errorMessage = 'Unfortunately, your balance is too low to cover the network fee required to send your funds.';
- } else {
- errorMessage = 'Not enough balance to cover amount including fees!\n' +
- 'Either reduce the amount you are sending, or use the "send all" option to send the max possible.\n\n';
+
+
+
+
+ {this.state.modifyMemo ?
+ {
+ this.setState({
+ memo: text,
+ })
+ }}
+ {...this.props}
+ />
+ :
+
+ {this.state.memo === '' ? t('none') : this.state.memo}
+
}
- }
+
- return(
+
-
- Estimating fee and preparing transaction failed!
-
-
-
- {errorMessage}
-
+
+ {this.state.payee.nickname}{t('details')}
+
+
+ {
+ this.props.navigation.navigate('ChoosePayee');
+ }}
+ // titleStyle={{
+ // color: this.props.screenProps.theme.primaryColour,
+ // fontSize: 13
+ // }}
+ // type="clear"
+ >
+ {t('change')}
+
- );
- }
-
- confirmScreen(t) {
- return(
-
-
-
- {t('reviewTitle')}
-
-
-
-
-
-
- {prettyPrintAmount(this.state.recipientAmount, Config)}{' '}
-
- will reach{' '}
-
- {this.state.payee.nickname}'s{' '}
-
- account, in {getArrivalTime([t('minute'), t('second')])}
-
-
-
-
-
- {t('notes')}
-
-
- {
- this.setState({
- modifyMemo: !this.state.modifyMemo,
- });
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 13
- }}
- type="clear"
- />
-
-
-
-
-
-
-
- {this.state.modifyMemo ?
- {
- this.setState({
- memo: text,
- })
- }}
- {...this.props}
- />
- :
-
- {this.state.memo === '' ? t('none') : this.state.memo}
-
- }
-
-
-
-
-
- {this.state.payee.nickname}{t('details')}
-
-
- {
- this.props.navigation.navigate('ChoosePayee');
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 13
- }}
- type="clear"
- />
-
-
-
-
-
- {t('address')}
-
-
-
- {this.state.payee.address}
-
-
- {this.state.payee.paymentID !== '' &&
-
-
- {t('paymentID')}
-
-
-
- {this.state.payee.paymentID}
-
- }
-
-
-
- {t('transferDetails')}
-
-
- {
- this.props.navigation.navigate(
- 'Transfer', {
- payee: this.state.payee,
- }
- );
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 13
- }}
- type="clear"
- />
-
-
-
-
-
- {t('sendAmountLabel')}
-
-
-
- {prettyPrintAmount(this.state.sendAll ? this.state.unlockedBalance : this.state.recipientAmount + this.state.feeTotal, Config)}
-
-
-
- {this.state.payee.nickname} {t('gets')}
-
-
-
- {prettyPrintAmount(this.state.recipientAmount, Config)}
-
-
-
- {t('fee')}
-
-
-
- {prettyPrintAmount(this.state.fee, Config)}
-
-
- {this.state.devFee > 0 &&
-
-
- Developer fee
-
-
-
- {prettyPrintAmount(this.state.devFee, Config)}
-
- }
-
- {this.state.nodeFee > 0 &&
-
-
- {t('nodeFee')}
-
-
-
- {prettyPrintAmount(this.state.nodeFee, Config)}
-
- }
-
-
-
- Total fee
-
-
-
- {prettyPrintAmount(this.state.feeTotal, Config)}
-
-
-
-
-
- {
- const params = {
- amount: this.state.recipientAmount,
- address: this.state.payee.address,
- paymentID: this.state.payee.paymentID,
- nickname: this.state.payee.nickname,
- memo: this.state.memo,
- hash: this.state.hash,
- };
-
- if (Globals.preferences.authConfirmation) {
- /* Verify they have the correct pin, then send the actual TX */
- Authenticate(
- this.props.navigation,
- 'to confirm the transaction',
- () => {
- this.props.navigation.dispatch(navigateWithDisabledBack('ChoosePayee'));
- this.props.navigation.navigate('SendTransaction', {...params});
- }
- );
- } else {
- /* Reset this stack to be on the transfer screen */
- this.props.navigation.dispatch(navigateWithDisabledBack('ChoosePayee'));
-
- /* Then send the actual transaction */
- this.props.navigation.navigate('SendTransaction', {...params});
- }
- }}
- {...this.props}
- />
-
- );
- }
+
- render() {
- const { t } = this.props;
- return(
-
- { this.state.preparedTransaction
- ? this.state.haveError
- ? this.errorScreen(t)
- : this.confirmScreen(t)
- : this.preparingScreen(t) }
-
- );
- }
-}
+
+ {t('address')}
+
-export const ConfirmScreen = withTranslation()(ConfirmScreenNoTranslation)
+
+ {this.state.payee.address}
+
-export class ChoosePayeeScreenNoTranslation extends React.Component {
- constructor(props) {
- super(props);
- }
+ {this.state.payee.paymentID !== '' &&
+
+
+ {t('paymentID')}
+
- static navigationOptions = ({ navigation, screenProps }) => {
- return {
- headerLeft: (
- { navigation.navigate('Main') }}
- />
- ),
- headerRight: (
-
- ),
- }
- };
+
+ {this.state.payee.paymentID}
+
+ }
- render() {
- const { t } = this.props;
- return(
-
-
- {t('sendToWho')}
-
-
+
+ {t('transferDetails')}
+
+
+ {
+ this.props.navigation.navigate(
+ 'Transfer', {
+ payee: this.state.payee,
+ }
+ );
+ }}
+ // titleStyle={{
+ // color: this.props.screenProps.theme.primaryColour,
+ // fontSize: 13
+ // }}
+ type="clear"
+ />
+
+
-
+
+ {t('sendAmountLabel')}
+
- this.props.navigation.navigate('NewPayee')}
- >
-
-
- {t('addNewRecipient')}
-
-
-
-
-
-
- );
- }
-}
+
+ {prettyPrintAmount(this.state.sendAll ? this.state.unlockedBalance : this.state.recipientAmount + this.state.feeTotal, Config)}
+
-export const ChoosePayeeScreen = withTranslation()(ChoosePayeeScreenNoTranslation)
+
+ {this.state.payee.nickname} {t('gets')}
+
-export class SendTransactionScreenNoTranslation extends React.Component {
- static navigationOptions = {
- header: null,
- }
+
+ {prettyPrintAmount(this.state.recipientAmount, Config)}
+
- constructor(props) {
- super(props);
-
- this.state = {
- txInfo: 'Sending transaction, please wait...',
- errMsg: '',
- hash: this.props.navigation.state.params.hash,
- amount: this.props.navigation.state.params.amount,
- address: this.props.navigation.state.params.address,
- nickname: this.props.navigation.state.params.nickname,
- memo: this.props.navigation.state.params.memo,
- homeEnabled: false,
- sent: false,
- }
+
+ {t('fee')}
+
- /* Send the tx in the background (it's async) */
- this.sendTransaction();
- }
+
+ {prettyPrintAmount(this.state.fee, Config)}
+
- async sendTransaction() {
- /* Wait for UI to load before blocking thread */
- await delay(500);
-
- const result = await Globals.wallet.sendPreparedTransaction(
- this.state.hash,
- );
-
- if (!result.success) {
- /* TODO: Optionally allow retries in case of network error? */
- Globals.wallet.deletePreparedTransaction(this.state.hash);
-
- this.setState({
- errMsg: result.error.toString(),
- homeEnabled: true,
- });
- } else {
- this.setState({
- homeEnabled: true,
- sent: true,
- });
-
- Globals.addTransactionDetails({
- hash: this.state.hash,
- memo: this.state.memo,
- address: this.state.address,
- payee: this.state.nickname,
- });
- }
- }
+ {this.state.devFee > 0 &&
+
+
+ Developer fee
+
- render() {
- const { t } = this.props;
- const sending =
-
-
- {t('sendingMsg')}
-
- ;
+
+ {prettyPrintAmount(this.state.devFee, Config)}
+
+ }
- const fail =
-
-
- {t('failedMsg')}
-
+ {this.state.nodeFee > 0 &&
+
+
+ {t('nodeFee')}
+
-
- {this.state.errMsg}
+
+ {prettyPrintAmount(this.state.nodeFee, Config)}
- ;
+ }
- const success =
-
- {t('completeMsg')}
-
-
-
-
- {prettyPrintAmount(this.state.amount, Config)}{' '}
-
- was sent to{' '}
-
- {this.state.nickname}'s{' '}
-
- account.
-
+
+ Total fee
+
-
- {t('transactionHash')}
-
+
+ {prettyPrintAmount(this.state.feeTotal, Config)}
+
+
+
+
+
+ {
+ const params = {
+ amount: this.state.recipientAmount,
+ address: this.state.payee.address,
+ paymentID: this.state.payee.paymentID,
+ nickname: this.state.payee.nickname,
+ memo: this.state.memo,
+ hash: this.state.hash,
+ };
+
+ if (Globals.preferences.authConfirmation) {
+ /* Verify they have the correct pin, then send the actual TX */
+ Authenticate(
+ this.props.navigation,
+ 'to confirm the transaction',
+ () => {
+ this.props.navigation.dispatch(navigateWithDisabledBack('ChoosePayee'));
+ this.props.navigation.navigate('SendTransaction', { ...params });
+ }
+ );
+ } else {
+ /* Reset this stack to be on the transfer screen */
+ this.props.navigation.dispatch(navigateWithDisabledBack('ChoosePayee'));
-
- {this.state.hash}
-
+ /* Then send the actual transaction */
+ this.props.navigation.navigate('SendTransaction', { ...params });
+ }
+ }}
+ {...this.props}
+ />
+
+ );
+ }
- {
- Clipboard.setString(this.state.hash);
- toastPopUp(t('copied'));
- }}
- titleStyle={{
- color: this.props.screenProps.theme.primaryColour,
- fontSize: 13
- }}
- type="clear"
- />
+ render() {
+ const { t } = this.props;
+ return (
+
+ {this.state.preparedTransaction
+ ? this.state.haveError
+ ? this.errorScreen(t)
+ : this.confirmScreen(t)
+ : this.preparingScreen(t)}
+
+ );
+ }
+}
- ;
+export const ConfirmScreen = withTranslation()(ConfirmScreenNoTranslation)
- return(
-
-
- {this.state.sent ? success : this.state.errMsg === '' ? sending : fail}
-
-
- {
- this.props.navigation.dispatch(navigateWithDisabledBack('ChoosePayee'));
- this.props.navigation.navigate('Main');
- }}
- disabled={!this.state.homeEnabled}
- {...this.props}
- />
-
- );
+export class ChoosePayeeScreenNoTranslation extends React.Component {
+ constructor(props) {
+ super(props);
+ }
+
+ static navigationOptions = ({ navigation, screenProps }) => {
+ return {
+ headerLeft: (
+ { navigation.navigate('Main') }}
+ />
+ ),
+ headerRight: (
+
+ ),
}
+ };
+
+ render() {
+ const { t } = this.props;
+ return (
+
+
+ {t('sendToWho')}
+
+
+ this.props.navigation.navigate('NewPayee')}
+ icon={}
+ >
+
+ {t('addNewRecipient')}
+
+
+
+
+
+ );
+ }
+}
+
+export const ChoosePayeeScreen = withTranslation()(ChoosePayeeScreenNoTranslation)
+
+export class SendTransactionScreenNoTranslation extends React.Component {
+ static navigationOptions = {
+ header: null,
+ }
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ txInfo: 'Sending transaction, please wait...',
+ errMsg: '',
+ hash: this.props.navigation.state.params.hash,
+ amount: this.props.navigation.state.params.amount,
+ address: this.props.navigation.state.params.address,
+ nickname: this.props.navigation.state.params.nickname,
+ memo: this.props.navigation.state.params.memo,
+ homeEnabled: false,
+ sent: false,
+ }
+
+ /* Send the tx in the background (it's async) */
+ this.sendTransaction();
+ }
+
+ async sendTransaction() {
+ /* Wait for UI to load before blocking thread */
+ await delay(500);
+
+ const result = await Globals.wallet.sendPreparedTransaction(
+ this.state.hash,
+ );
+
+ if (!result.success) {
+ /* TODO: Optionally allow retries in case of network error? */
+ Globals.wallet.deletePreparedTransaction(this.state.hash);
+
+ this.setState({
+ errMsg: result.error.toString(),
+ homeEnabled: true,
+ });
+ } else {
+ this.setState({
+ homeEnabled: true,
+ sent: true,
+ });
+
+ Globals.addTransactionDetails({
+ hash: this.state.hash,
+ memo: this.state.memo,
+ address: this.state.address,
+ payee: this.state.nickname,
+ });
+ }
+ }
+
+ render() {
+ const { t } = this.props;
+ const sending =
+
+
+ {t('sendingMsg')}
+
+ ;
+
+ const fail =
+
+
+ {t('failedMsg')}
+
+
+
+ {this.state.errMsg}
+
+ ;
+
+ const success =
+
+
+ {t('completeMsg')}
+
+
+
+
+ {prettyPrintAmount(this.state.amount, Config)}{' '}
+
+ was sent to{' '}
+
+ {this.state.nickname}'s{' '}
+
+ account.
+
+
+
+ {t('transactionHash')}
+
+
+
+ {this.state.hash}
+
+ {
+ Clipboard.setString(this.state.hash);
+ toastPopUp(t('copied'));
+ }}
+ // titleStyle={{
+ // color: this.props.screenProps.theme.primaryColour,
+ // fontSize: 13
+ // }}
+ type="clear"
+ >{t('copy')}
+
+ ;
+
+ return (
+
+
+ {this.state.sent ? success : this.state.errMsg === '' ? sending : fail}
+
+
+ {
+ this.props.navigation.dispatch(navigateWithDisabledBack('ChoosePayee'));
+ this.props.navigation.navigate('Main');
+ }}
+ disabled={!this.state.homeEnabled}
+ {...this.props}
+ />
+
+ );
+ }
}
export const SendTransactionScreen = withTranslation()(SendTransactionScreenNoTranslation)
diff --git a/src/Utilities.js b/src/Utilities.js
index 952f51f..727d3d2 100644
--- a/src/Utilities.js
+++ b/src/Utilities.js
@@ -19,7 +19,7 @@ import { Text, Platform, ToastAndroid, Alert } from 'react-native';
import { StackActions, NavigationActions } from 'react-navigation';
import {
- validateAddresses, WalletErrorCode, validatePaymentID, prettyPrintAmount,
+ validateAddresses, WalletErrorCode, validatePaymentID,
} from 'kryptokrona-wallet-backend-js';
import * as Qs from 'query-string';
@@ -28,43 +28,43 @@ import Config from './Config';
import { Globals } from './Globals';
-import { addFee, toAtomic } from './Fee';
+import { toAtomic } from './Fee';
-export function delay(ms: number) {
- return new Promise((resolve) => setTimeout(resolve, ms));
+export function delay(ms) {
+ return new Promise((resolve) => setTimeout(resolve, ms));
}
export function toastPopUp(message, short = true) {
- /* IOS doesn't have toast support */
- /* TODO */
- if (Platform.OS === 'ios') {
- return;
- }
+ /* IOS doesn't have toast support */
+ /* TODO */
+ if (Platform.OS === 'ios') {
+ return;
+ }
- ToastAndroid.show(message, short ? ToastAndroid.SHORT : ToastAndroid.LONG);
+ ToastAndroid.show(message, short ? ToastAndroid.SHORT : ToastAndroid.LONG);
}
/* Navigate to a route, resetting the stack, so the user cannot go back.
We want to do this so when we go from the splash screen to the menu screen,
the user can't return, and get stuck there. */
export function navigateWithDisabledBack(route, routeParams) {
- return StackActions.reset({
- index: 0,
- actions: [
- NavigationActions.navigate({
- routeName: route,
- params: routeParams,
- }),
- ]
- });
+ return StackActions.reset({
+ index: 0,
+ actions: [
+ NavigationActions.navigate({
+ routeName: route,
+ params: routeParams,
+ }),
+ ]
+ });
}
export function prettyPrintUnixTimestamp(timestamp) {
- return {timestamp}
+ return {timestamp}
}
export function prettyPrintDate2(timestamp) {
- let date = new Date(timestamp*1000);
+ let date = new Date(timestamp * 1000);
return date.toLocaleString(Globals.language);
@@ -72,321 +72,321 @@ export function prettyPrintDate2(timestamp) {
}
export function prettyPrintDate(date) {
- if (date === undefined) {
- date = moment();
- }
+ if (date === undefined) {
+ date = moment();
+ }
- if (moment().year() === date.year()) {
- return date.format('D MMM, HH:mm');
- }
+ if (moment().year() === date.year()) {
+ return date.format('D MMM, HH:mm');
+ }
- return date.format('D MMM, YYYY HH:mm');
+ return date.format('D MMM, YYYY HH:mm');
}
/**
* Gets the approximate height of the blockchain, based on the launch timestamp
*/
export function getApproximateBlockHeight(date) {
- const difference = (date - Config.chainLaunchTimestamp) / 1000;
+ const difference = (date - Config.chainLaunchTimestamp) / 1000;
- let blockHeight = Math.floor(difference / 90);
+ let blockHeight = Math.floor(difference / 90);
- if (blockHeight < 0) {
- blockHeight = 0;
- }
+ if (blockHeight < 0) {
+ blockHeight = 0;
+ }
- return blockHeight;
+ return blockHeight;
}
/**
* Converts a date to a scan height. Note, takes a moment date.
*/
export function dateToScanHeight(date) {
- let jsDate = date.toDate();
- const now = new Date();
+ let jsDate = date.toDate();
+ const now = new Date();
- if (jsDate > now) {
- jsDate = now;
- }
+ if (jsDate > now) {
+ jsDate = now;
+ }
- return getApproximateBlockHeight(jsDate);
+ return getApproximateBlockHeight(jsDate);
}
export function getArrivalTime(timeUnitTranslation) {
- const minutes = Config.blockTargetTime >= 60;
+ const minutes = Config.blockTargetTime >= 60;
- if (minutes) {
- return Math.ceil(Config.blockTargetTime / 60) + ' ' + timeUnitTranslation[0];
- } else {
- return Config.blockTargetTime + ' ' + timeUnitTranslation[1];
- }
+ if (minutes) {
+ return Math.ceil(Config.blockTargetTime / 60) + ' ' + timeUnitTranslation[0];
+ } else {
+ return Config.blockTargetTime + ' ' + timeUnitTranslation[1];
+ }
}
export async function handleURI(data, navigation) {
console.log(data);
- if (data.url ) {
-
- const params = Qs.parse(data.url.replace('xkr://', ''));
+ if (data.url) {
- if(params.board != undefined) {
+ const params = Qs.parse(data.url.replace('xkr://', ''));
- console.log(params.board);
+ if (params.board != undefined) {
- navigation.navigate(
- 'BoardsHome', {
- board: params.board
- });
+ console.log(params.board);
+ navigation.navigate(
+ 'BoardsHome', {
+ board: params.board
+ });
- return;
- } else if (params.group != undefined) {
- // To do: Separate between a new group and a notification call
+ return;
+ } else if (params.group != undefined) {
- const group_object = Globals.groups.filter(group => {
- return group.key == params.group;
- })
+ // To do: Separate between a new group and a notification call
- console.log(group_object[0]);
+ const group_object = Globals.groups.filter(group => {
+ return group.key == params.group;
+ })
- navigation.navigate(
- 'GroupChatScreen', {
- group: {group: group_object[0].group, key: group_object[0].key}
- });
+ console.log(group_object[0]);
- return;
+ navigation.navigate(
+ 'GroupChatScreen', {
+ group: { group: group_object[0].group, key: group_object[0].key }
+ });
- }
+ return;
- if(params.istip != undefined) {
+ }
- const newPayee = {
- nickname: params.name,
- address: params.address,
- paymentID: params.paymentid
- }
+ if (params.istip != undefined) {
- console.log(newPayee);
- const result = {
- payee: newPayee,
- suggestedAction: 'Transfer',
- valid: true,
- };
-
- console.log(params);
- console.log(result);
- if (!result.valid) {
- Alert.alert(
- 'Cannot send transaction',
- result.error,
- [
- {text: 'OK'},
- ]
- );
- } else {
-
- /* Hop into the transfer stack */
- navigation.navigate('ChoosePayee');
- // navigation.navigate('Recipients');
- /* Then navigate to the nested route, if needed */
- navigation.navigate('Transfer', {...result});
- return;
- }
+ const newPayee = {
+ nickname: params.name,
+ address: params.address,
+ paymentID: params.paymentid
}
- const address = params.address;
- const name = params.name;
+ console.log(newPayee);
+ const result = {
+ payee: newPayee,
+ suggestedAction: 'Transfer',
+ valid: true,
+ };
+
+ console.log(params);
+ console.log(result);
+ if (!result.valid) {
+ Alert.alert(
+ 'Cannot send transaction',
+ result.error,
+ [
+ { text: 'OK' },
+ ]
+ );
+ } else {
- if (name == undefined) {
- handleURI(data.url);
+ /* Hop into the transfer stack */
+ navigation.navigate('ChoosePayee');
+ // navigation.navigate('Recipients');
+ /* Then navigate to the nested route, if needed */
+ navigation.navigate('Transfer', { ...result });
return;
}
+ }
- const paymentID = params.paymentID;
-
- navigation.navigate(
- 'ChatScreen', {
- payee: {address: address, nickname: name, paymentID: paymentID},
- });
+ const address = params.address;
+ const name = params.name;
- } else if (!data.startsWith('xkr://SEKR')) {
+ if (name == undefined) {
+ handleURI(data.url);
return;
}
- const result = await parseURI(data);
+ const paymentID = params.paymentID;
- if (!result.valid) {
- Alert.alert(
- 'Cannot send transaction',
- result.error,
- [
- {text: 'OK'},
- ]
- );
- } else {
+ navigation.navigate(
+ 'ChatScreen', {
+ payee: { address: address, nickname: name, paymentID: paymentID },
+ });
- /* Hop into the transfer stack */
- navigation.navigate('ChoosePayee');
- // navigation.navigate('Recipients');
- /* Then navigate to the nested route, if needed */
- navigation.navigate(result.suggestedAction, {...result});
- }
+ } else if (!data.startsWith('xkr://SEKR')) {
+ return;
+ }
+
+ const result = await parseURI(data);
+
+ if (!result.valid) {
+ Alert.alert(
+ 'Cannot send transaction',
+ result.error,
+ [
+ { text: 'OK' },
+ ]
+ );
+ } else {
+
+ /* Hop into the transfer stack */
+ navigation.navigate('ChoosePayee');
+ // navigation.navigate('Recipients');
+ /* Then navigate to the nested route, if needed */
+ navigation.navigate(result.suggestedAction, { ...result });
+ }
}
export async function parseURI(qrData) {
- /* It's a URI, try and get the data from it */
- if (qrData.startsWith(Config.uriPrefix)) {
- /* Remove the turtlecoin:// prefix */
- let data = qrData.replace(Config.uriPrefix, '');
- let index = data.indexOf('?');
-
- /* Doesn't have any params */
- if (index === -1) {
- index = data.length;
- }
-
- const address = data.substr(0, index);
- const params = Qs.parse(data.substr(index));
-
- console.log(params);
- console.log(address);
- const amount = params.amount;
- const name = params.name;
- let paymentID = params.paymentid;
-
- if (paymentID) {
- const pidError = validatePaymentID(paymentID);
-
- /* Payment ID isn't valid. */
- if (pidError.errorCode !== WalletErrorCode.SUCCESS) {
- return {
- valid: false,
- error: 'QR Code is invalid',
- };
- }
-
- /* Both integrated address and payment ID given */
- if (address.length === Config.integratedAddressLength && paymentID.length !== 0) {
- return {
- valid: false,
- error: 'QR Code is invalid',
- };
- }
- }
-
- const addressError = await validateAddresses([address], true, Config);
-
-
- /* Address isn't valid */
- if (addressError.errorCode !== WalletErrorCode.SUCCESS) {
- return {
- valid: false,
- error: 'QR Code is invalid',
- };
- }
-
- const amountAtomic = Number(amount);
-
- /* No name, need to pick one.. */
- if (!name) {
- return {
- paymentID: paymentID || '',
- address,
- // amount: !isNaN(amountAtomic) ? amountAtomic : undefined,
- suggestedAction: 'NewPayee',
- valid: true,
- }
- }
-
- const newPayee = {
- nickname: name,
- address: address,
- paymentID: paymentID || '',
- }
-
- const existingPayee = Globals.payees.find((p) => p.nickname === name);
-
- /* Payee exists already */
- if (existingPayee) {
- /* New payee doesn't match existing payee, get them to enter a new name */
- if (existingPayee.address !== newPayee.address ||
- existingPayee.paymentID !== newPayee.paymentID) {
- return {
- paymentID: paymentID || '',
- address,
- amount: amountAtomic,
- suggestedAction: 'NewPayee',
- valid: true,
- };
- }
- /* Save payee to database for later use */
- } else {
- Globals.addPayee(newPayee);
- }
-
- if (!amount) {
- return {
- payee: newPayee,
- suggestedAction: 'Transfer',
- valid: true,
- };
- } else {
- return {
- payee: newPayee,
- amount: amountAtomic,
- suggestedAction: 'Confirm',
- valid: true,
- };
- }
- /* It's a standard address, try and parse it (or something else) */
- } else {
- const addressError = validateAddresses([qrData], true, Config);
+ /* It's a URI, try and get the data from it */
+ if (qrData.startsWith(Config.uriPrefix)) {
+ /* Remove the turtlecoin:// prefix */
+ let data = qrData.replace(Config.uriPrefix, '');
+ let index = data.indexOf('?');
+
+ /* Doesn't have any params */
+ if (index === -1) {
+ index = data.length;
+ }
+
+ const address = data.substr(0, index);
+ const params = Qs.parse(data.substr(index));
+
+ console.log(params);
+ console.log(address);
+ const amount = params.amount;
+ const name = params.name;
+ let paymentID = params.paymentid;
- if (addressError.errorCode !== WalletErrorCode.SUCCESS) {
- return {
- valid: false,
- error: 'QR code is invalid',
- };
- }
+ if (paymentID) {
+ const pidError = validatePaymentID(paymentID);
+ /* Payment ID isn't valid. */
+ if (pidError.errorCode !== WalletErrorCode.SUCCESS) {
return {
- valid: true,
- address: qrData,
- suggestedAction: 'NewPayee',
- }
+ valid: false,
+ error: 'QR Code is invalid',
+ };
+ }
+
+ /* Both integrated address and payment ID given */
+ if (address.length === Config.integratedAddressLength && paymentID.length !== 0) {
+ return {
+ valid: false,
+ error: 'QR Code is invalid',
+ };
+ }
}
-}
-export function validAmount(amount, unlockedBalance) {
- if (amount === '' || amount === undefined || amount === null) {
- return [false, ''];
+ const addressError = await validateAddresses([address], true, Config);
+
+
+ /* Address isn't valid */
+ if (addressError.errorCode !== WalletErrorCode.SUCCESS) {
+ return {
+ valid: false,
+ error: 'QR Code is invalid',
+ };
+ }
+
+ const amountAtomic = Number(amount);
+
+ /* No name, need to pick one.. */
+ if (!name) {
+ return {
+ paymentID: paymentID || '',
+ address,
+ // amount: !isNaN(amountAtomic) ? amountAtomic : undefined,
+ suggestedAction: 'NewPayee',
+ valid: true,
+ }
}
- /* Remove commas in input */
- amount = amount.replace(/,/g, '');
+ const newPayee = {
+ nickname: name,
+ address: address,
+ paymentID: paymentID || '',
+ }
- let numAmount = Number(amount);
+ const existingPayee = Globals.payees.find((p) => p.nickname === name);
- if (isNaN(numAmount)) {
- return [false, 'Amount is not a number!'];
+ /* Payee exists already */
+ if (existingPayee) {
+ /* New payee doesn't match existing payee, get them to enter a new name */
+ if (existingPayee.address !== newPayee.address ||
+ existingPayee.paymentID !== newPayee.paymentID) {
+ return {
+ paymentID: paymentID || '',
+ address,
+ amount: amountAtomic,
+ suggestedAction: 'NewPayee',
+ valid: true,
+ };
+ }
+ /* Save payee to database for later use */
+ } else {
+ Globals.addPayee(newPayee);
}
- /* Remove fractional component and convert to atomic */
- numAmount = Math.floor(toAtomic(numAmount));
+ if (!amount) {
+ return {
+ payee: newPayee,
+ suggestedAction: 'Transfer',
+ valid: true,
+ };
+ } else {
+ return {
+ payee: newPayee,
+ amount: amountAtomic,
+ suggestedAction: 'Confirm',
+ valid: true,
+ };
+ }
+ /* It's a standard address, try and parse it (or something else) */
+ } else {
+ const addressError = validateAddresses([qrData], true, Config);
- /* Must be above min send */
- if (numAmount < 1) {
- return [false, 'Amount is below minimum send!'];
+ if (addressError.errorCode !== WalletErrorCode.SUCCESS) {
+ return {
+ valid: false,
+ error: 'QR code is invalid',
+ };
}
- if (numAmount > unlockedBalance) {
- return [false, 'Not enough funds available!'];
+ return {
+ valid: true,
+ address: qrData,
+ suggestedAction: 'NewPayee',
}
+ }
+}
+
+export function validAmount(amount, unlockedBalance) {
+ if (amount === '' || amount === undefined || amount === null) {
+ return [false, ''];
+ }
+
+ /* Remove commas in input */
+ amount = amount.replace(/,/g, '');
+
+ let numAmount = Number(amount);
+
+ if (isNaN(numAmount)) {
+ return [false, 'Amount is not a number!'];
+ }
+
+ /* Remove fractional component and convert to atomic */
+ numAmount = Math.floor(toAtomic(numAmount));
+
+ /* Must be above min send */
+ if (numAmount < 1) {
+ return [false, 'Amount is below minimum send!'];
+ }
+
+ if (numAmount > unlockedBalance) {
+ return [false, 'Not enough funds available!'];
+ }
- return [true, ''];
+ return [true, ''];
}
export function prettyPrintAmountMainScreen(amount) {
@@ -402,7 +402,7 @@ export function prettyPrintAmountMainScreen(amount) {
amount = amount;
} else {
// Between 1K & 100K XKR
- amount = amount.toString().split('.')[0] = amount.toString().slice(0,-3);
+ amount = amount.toString().split('.')[0] = amount.toString().slice(0, -3);
}
return amount;
}
diff --git a/src/components/button.js b/src/components/button.js
new file mode 100644
index 0000000..9c3379a
--- /dev/null
+++ b/src/components/button.js
@@ -0,0 +1,43 @@
+import React from "react";
+import { StyleSheet, TouchableOpacity } from "react-native";
+
+import { Themes } from "../Themes";
+
+export class Button extends React.Component {
+
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ const { children, onPress, backgroundColor: mBackgroundColor, borderColor: mBorderColor, color: mColor, style, icon, disabled, primary } = this.props;
+ const backgroundColor = mBackgroundColor ?? Themes.darkMode.backgroundEmphasis;
+ const borderColor = mBorderColor ?? primary ? Themes.darkMode.primaryColour : Themes.darkMode.borderColour;
+ const color = mColor ?? Themes.darkMode.primaryColour;
+
+ if (!onPress || !children) {
+ return null;
+ }
+
+ return (
+
+ {icon}
+ {children}
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flexDirection: 'row',
+ borderRadius: 15,
+ borderWidth: 1,
+ padding: 12,
+ marginVertical: 4,
+ // overflow: 'hidden',
+ alignItems: 'center',
+ flex: 1,
+ minHeight: 50
+ }
+});
diff --git a/src/components/card.js b/src/components/card.js
new file mode 100644
index 0000000..b79e1ec
--- /dev/null
+++ b/src/components/card.js
@@ -0,0 +1,39 @@
+
+import React from 'react';
+
+import { StyleSheet, View } from 'react-native';
+import { Themes } from '../Themes';
+
+export class Card extends React.Component {
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ const { children, centered, flexDirection: mFlexDirection, backgroundColor: mBackgroundColor, borderColor: mBorderColor } = this.props;
+ const flexDirection = mFlexDirection ?? 'column';
+ const backgroundColor = mBackgroundColor ?? Themes.darkMode.backgroundEmphasis;
+ const borderColor = mBorderColor ?? Themes.darkMode.borderColour;
+ const alignItems = centered && 'center';
+
+ if (!children) {
+ return null;
+ }
+
+ return (
+
+ {children}
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ width: '100%',
+ borderRadius: 15,
+ borderWidth: 1,
+ padding: 12,
+ margin: 4,
+ }
+});
diff --git a/src/components/index.js b/src/components/index.js
new file mode 100644
index 0000000..1c63c27
--- /dev/null
+++ b/src/components/index.js
@@ -0,0 +1,7 @@
+
+export * from './button'
+export * from './card'
+export * from './input'
+export * from './screen-header'
+export * from './screen-layout'
+export * from './text-field'
diff --git a/src/components/input.js b/src/components/input.js
new file mode 100644
index 0000000..5815bb1
--- /dev/null
+++ b/src/components/input.js
@@ -0,0 +1,75 @@
+
+import React from 'react';
+import { Themes } from '../Themes';
+import { StyleSheet } from 'react-native';
+
+import { Input } from 'react-native-elements';
+
+export class InputField extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ value: props.value,
+ };
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ width: '100%',
+ marginBottom: 15,
+ marginHorizontal: 0,
+ fontFamily: 'Montserrat-Regular',
+ },
+ input: {
+ borderRadius: 15,
+ fontSize: 14,
+ marginLeft: 5,
+ fontFamily: 'Montserrat-SemiBold',
+ },
+ label: {
+ fontFamily: 'Montserrat-Regular',
+ fontSize: 12,
+ marginBottom: 5,
+ marginRight: 2,
+ },
+ inputContainer: {
+ width: '100%',
+ borderWidth: 0,
+ borderRadius: 15,
+ backgroundColor: "rgba(0,0,0,0.2)",
+ borderColor: 'transparent'
+ }
+});
diff --git a/src/components/screen-header.js b/src/components/screen-header.js
new file mode 100644
index 0000000..1ad7b13
--- /dev/null
+++ b/src/components/screen-header.js
@@ -0,0 +1,37 @@
+import React from "react";
+
+import { StyleSheet, View, Text } from "react-native";
+
+import { Themes } from "../Themes";
+
+export class ScreenHeader extends React.Component {
+
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ const { children, style } = this.props;
+
+ const color = Themes.darkMode.primaryColour;
+
+ return children && (
+
+ {children}
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ padding: 12,
+ fontFamily: "Montserrat-SemiBold",
+ marginVertical: 16
+ },
+ text: {
+ fontSize: 24,
+ fontFamily: "Montserrat-SemiBold",
+ flexShrink: 1
+ }
+});
diff --git a/src/components/screen-layout.js b/src/components/screen-layout.js
new file mode 100644
index 0000000..a6c20ea
--- /dev/null
+++ b/src/components/screen-layout.js
@@ -0,0 +1,29 @@
+import React from "react";
+
+import { StyleSheet, View } from "react-native";
+import { Themes } from "../Themes";
+
+export class ScreenLayout extends React.Component {
+
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
+ const { children, style } = this.props;
+ return (
+
+ {children}
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Themes.darkMode.backgroundColour,
+ padding: 12,
+ alignItems: 'stretch'
+ }
+});
diff --git a/src/components/text-field.js b/src/components/text-field.js
new file mode 100644
index 0000000..ce11348
--- /dev/null
+++ b/src/components/text-field.js
@@ -0,0 +1,29 @@
+import React from "react";
+import { StyleSheet, Text } from "react-native";
+import { Themes } from "../Themes";
+
+export class TextField extends React.Component {
+
+ constructor(props) {
+ super(props);
+ }
+ render() {
+ const { children, style, color: mColor, centered } = this.props;
+ const color = mColor ?? Themes.darkMode.primaryColour;
+
+ return {children};
+
+ }
+}
+
+const styles = StyleSheet.create({
+ text: {
+ fontSize: 14,
+ fontFamily: 'Montserrat-Bold',
+ flexShrink: 1
+ },
+ centered: {
+ textAlign: 'center',
+ width: '100%'
+ }
+});
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 3a3ea39..e40aeb4 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -3,8 +3,8 @@
messageKey: "Message key",
copy: "Copy",
copied: " copied",
- noTxMessage: "You don\'t have any transactions yet 😥",
- notSyncedMessage: "\n\n Your wallet is still syncing, please wait..",
+ noTxMessage: "You don't have any transactions yet 😥",
+ notSyncedMessage: "Your wallet is still syncing, please wait..",
emptyAddressBook: "Your address book is empty! Add a new recipient above to populate it.",
messagesTitle: "Private Messages",
sendToWho: "Send transaction",
@@ -199,4 +199,4 @@
clearKnownMessagesDescr: "This will resync all messages from the past 24h",
alreadyOptimizing: "Already optimizing. Please wait until the ongoing optimization completes.",
deleteContactWarning: "Are you sure you want to delete this contact?"
-}
+}
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index ace2592..af1a000 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5045,10 +5045,10 @@ kryptokrona-utils@^1.3.8:
optionalDependencies:
"@ledgerhq/hw-transport-node-hid" "^5.22.0"
-kryptokrona-wallet-backend-js@2.5.1:
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/kryptokrona-wallet-backend-js/-/kryptokrona-wallet-backend-js-2.5.1.tgz#c361121e0c8a05250ba7bb8481a6f300b13a1526"
- integrity sha512-bjOShLXCLKljrCGtvo+Og0hVHd9J3sUwunHK7D509DNVTb/QtvTnX/sspxOGZ9oZ8uetDvylEC1nloUYdJqlnA==
+kryptokrona-wallet-backend-js@^2.5.5:
+ version "2.5.5"
+ resolved "https://registry.yarnpkg.com/kryptokrona-wallet-backend-js/-/kryptokrona-wallet-backend-js-2.5.5.tgz#7a804b11b521383d3cd1e2aeda4a38abd5cff075"
+ integrity sha512-QQNZ4/R7ieuNt0XTOXYS59QbQiFq0uYdcCRSZkBgqJ+Of0sC3EKLNH9moJPZgAvjrnuipCvymA4uvga7JbqiIw==
dependencies:
kryptokrona-utils "^1.3.8"
lodash "^4.17.15"
@@ -6976,6 +6976,11 @@ react-native-hyperlink@^0.0.19:
linkify-it "^2.2.0"
mdurl "^1.0.0"
+react-native-incall-manager@4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/react-native-incall-manager/-/react-native-incall-manager-4.1.0.tgz#38601a2796932c0d815654f4c838722a2207bf56"
+ integrity sha512-v1c+XOGu5VudY5//E3i5xiaRA9v6RvevMzZ4RumLqI+hte+4XslB2z6HSek2FF0EmAnY1rCn4ckiwgkTI1Tmtw==
+
react-native-invertible-scroll-view@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/react-native-invertible-scroll-view/-/react-native-invertible-scroll-view-2.0.0.tgz#799ee99eeac17600e35418dce288ba8b99ab8cd7"