From b6ab63427e634d66ec43c5fa4089ef189c70a8c1 Mon Sep 17 00:00:00 2001 From: xiphiness Date: Thu, 29 Aug 2019 13:26:00 -0400 Subject: [PATCH 01/22] brand icons --- src/components/common/view/BrandIcon.js | 13 +++ src/components/identity/IdentityDataTable.js | 112 +++++++++++++++++++ src/components/profile/Profile.js | 17 ++- 3 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/components/common/view/BrandIcon.js create mode 100644 src/components/identity/IdentityDataTable.js diff --git a/src/components/common/view/BrandIcon.js b/src/components/common/view/BrandIcon.js new file mode 100644 index 0000000000..0eb5236cbe --- /dev/null +++ b/src/components/common/view/BrandIcon.js @@ -0,0 +1,13 @@ +import React from 'react' +import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome' +import { faFacebookSquare, faGithubSquare, faTwitterSquare } from '@fortawesome/free-brands-svg-icons' + +const icons = { + twitter: faTwitterSquare, + facebook: faFacebookSquare, + github: faGithubSquare, +} + +const BrandIcon = ({ name, ...props }) => + +export default BrandIcon diff --git a/src/components/identity/IdentityDataTable.js b/src/components/identity/IdentityDataTable.js new file mode 100644 index 0000000000..5bd668ae90 --- /dev/null +++ b/src/components/identity/IdentityDataTable.js @@ -0,0 +1,112 @@ +import React from 'react' + +import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view' +import { Text } from 'react-native' + +//import { Alert, Modal, Text, TouchableHighlight, View } from 'react-native' +import Icon from '../common/view/Icon' +import BrandIcon from '../common/view/BrandIcon' + +//import InputRounded from '../common/form/InputRounded' +import Section from '../common/layout/Section' + +import { withStyles } from '../../lib/styles' + +// class ModalExample extends Component { +// state = { +// modalVisible: false, +// } + +// setModalVisible(visible) { +// this.setState({ modalVisible: visible }) +// } + +// render() { +// return ( +// +// { +// Alert.alert('Modal has been closed.') +// }} +// > +// +// +// Hello World! + +// { +// this.setModalVisible(!this.state.modalVisible) +// }} +// > +// Hide Modal +// +// +// +// + +// { +// this.setModalVisible(true) +// }} +// > +// Show Modal +// +// +// ) +// } +// } + +const IdentityDataTable = ({ identity, errors: errorsProp, editable, theme, styles }) => { + const errors = errorsProp || {} + return ( + + + {Object.keys(identity).map(x => ( + + + {identity[x].username} + {editable && ( + delete identity[x]} + /> + )} + {errors.mobile && {errors.mobile}} + + ))} + + + ) +} + +const getStylesFromProps = ({ theme }) => { + return { + borderedBottomStyle: { + borderBottomColor: theme.colors.lightGray, + borderBottomWidth: 1, + }, + suffixIcon: { + alignItems: 'center', + display: 'flex', + height: 38, + justifyContent: 'center', + position: 'absolute', + right: 0, + top: 0, + width: 32, + zIndex: 1, + }, + errorMargin: { + marginTop: theme.sizes.default, + marginBottom: theme.sizes.default, + }, + } +} + +export default withStyles(getStylesFromProps)(IdentityDataTable) diff --git a/src/components/profile/Profile.js b/src/components/profile/Profile.js index 02e7aaec9d..5853e23b19 100644 --- a/src/components/profile/Profile.js +++ b/src/components/profile/Profile.js @@ -6,6 +6,7 @@ import { createStackNavigator } from '../appNavigation/stackNavigation' import { Section, UserAvatar, Wrapper } from '../common' import { withStyles } from '../../lib/styles' import userStorage from '../../lib/gundb/UserStorage' +import IdentityDataTable from '../identity/IdentityDataTable' import EditAvatar from './EditAvatar' import EditProfile from './EditProfile' import ProfileDataTable from './ProfileDataTable' @@ -15,10 +16,23 @@ import CircleButtonWrapper from './CircleButtonWrapper' const TITLE = 'Profile' +const ExampleIdentity = { + github: { + username: 'github username', + }, + twitter: { + username: 'twitter name', + }, + facebook: { + username: 'facebook name', + }, +} + const ProfileWrapper = props => { const store = GDStore.useStore() const profile = store.get('profile') const { screenProps, styles } = props + const editIdentities = false const handleAvatarPress = event => { event.stopPropagation() @@ -48,7 +62,8 @@ const ProfileWrapper = props => { style={[styles.iconRight]} /> - + + ) From a88c2ab7cb62c26638dfda1997acd60f069b8c56 Mon Sep 17 00:00:00 2001 From: xiphiness Date: Thu, 29 Aug 2019 13:26:51 -0400 Subject: [PATCH 02/22] package.json --- package.json | 4 ++++ 1 file changed, 4 insertions(+) mode change 100755 => 100644 package.json diff --git a/package.json b/package.json old mode 100755 new mode 100644 index 4c5c42e595..408a9da135 --- a/package.json +++ b/package.json @@ -54,6 +54,9 @@ "homepage": "https://gooddollar.org", "dependencies": { "@babel/preset-flow": "^7.0.0", + "@fortawesome/fontawesome-svg-core": "^1.2.22", + "@fortawesome/free-brands-svg-icons": "^5.10.2", + "@fortawesome/react-native-fontawesome": "^0.1.0", "@gooddollar/goodcontracts": "0.0.18", "@gooddollar/gun-appendonly": "^1.0.1", "@react-navigation/core": "^3.1.1", @@ -93,6 +96,7 @@ "react-native-qrcode-scanner": "^1.1.2", "react-native-recaptcha-v3": "0.0.16", "react-native-side-menu-gooddapp": "^2.0.2", + "react-native-svg": "^9.7.1", "react-native-vector-icons": "^6.6.0", "react-native-web": "^0.11.4", "react-native-web-webview": "^0.2.8", From 624941fb586c716321aa921dbcc61fabf97ad2e2 Mon Sep 17 00:00:00 2001 From: xiphiness Date: Thu, 29 Aug 2019 13:48:41 -0400 Subject: [PATCH 03/22] package-lock.json --- package-lock.json | 86 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1d2344492c..329bf2c2c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1872,6 +1872,36 @@ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.3.tgz", "integrity": "sha512-4zAPlpDEh2VwXswwr/t8xGNDGg8RQiPxtxZ3qQEXyQsBV39ptTdESCjuBvGze1nLMVrxmTIKmnO/nAV8Tqjjzg==" }, + "@fortawesome/fontawesome-common-types": { + "version": "0.2.22", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.22.tgz", + "integrity": "sha512-QmEuZsipX5/cR9JOg0fsTN4Yr/9lieYWM8AQpmRa0eIfeOcl/HLYoEa366BCGRSrgNJEexuvOgbq9jnJ22IY5g==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "1.2.22", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.22.tgz", + "integrity": "sha512-Q941E4x8UfnMH3308n0qrgoja+GoqyiV846JTLoCcCWAKokLKrixCkq6RDBs8r+TtAWaLUrBpI+JFxQNX/WNPQ==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.22" + } + }, + "@fortawesome/free-brands-svg-icons": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.10.2.tgz", + "integrity": "sha512-r5Dxr2h8f9bEI7F/gj/2v1OX9S6DMif9ZKR2VFQCSXHwahojLlOWnFILYsrjhzOISESkh6WDL9IOdkdbKM7KPw==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.22" + } + }, + "@fortawesome/react-native-fontawesome": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-native-fontawesome/-/react-native-fontawesome-0.1.0.tgz", + "integrity": "sha512-NVQmvAe/sKr9WSMSbJv9WZiUiWNOjPpGaprNFkUJOLh7tqogZd41G+5wQ7Z0H4jtgiJDm3RbVSX7DeUDZ8sf+A==", + "requires": { + "humps": "^2.0.1", + "prop-types": "^15.6.2" + } + }, "@gooddollar/goodcontracts": { "version": "0.0.18", "resolved": "https://registry.npmjs.org/@gooddollar/goodcontracts/-/goodcontracts-0.0.18.tgz", @@ -15663,7 +15693,7 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "optional": true }, @@ -15674,13 +15704,13 @@ }, "aproba": { "version": "1.2.0", - "resolved": false, + "resolved": "", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": false, + "resolved": "", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "optional": true, "requires": { @@ -15709,7 +15739,7 @@ }, "code-point-at": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "optional": true }, @@ -15720,7 +15750,7 @@ }, "console-control-strings": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "core-util-is": { @@ -15742,7 +15772,7 @@ }, "debug": { "version": "2.6.9", - "resolved": false, + "resolved": "", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "optional": true, "requires": { @@ -15756,13 +15786,13 @@ }, "delegates": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "optional": true }, @@ -15795,7 +15825,7 @@ }, "gauge": { "version": "2.7.4", - "resolved": false, + "resolved": "", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "optional": true, "requires": { @@ -15832,13 +15862,13 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": false, + "resolved": "", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "optional": true, "requires": { @@ -15882,7 +15912,7 @@ }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "optional": true, "requires": { @@ -15913,7 +15943,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": false, + "resolved": "", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "optional": true }, @@ -15935,7 +15965,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, + "resolved": "", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "optional": true, "requires": { @@ -15944,13 +15974,13 @@ }, "ms": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "optional": true }, "needle": { "version": "2.2.4", - "resolved": false, + "resolved": "", "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", "optional": true, "requires": { @@ -15979,7 +16009,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "optional": true, "requires": { @@ -16006,13 +16036,13 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": false, + "resolved": "", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "optional": true }, @@ -16061,13 +16091,13 @@ }, "safer-buffer": { "version": "2.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "optional": true }, "sax": { "version": "1.2.4", - "resolved": false, + "resolved": "", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "optional": true }, @@ -16078,7 +16108,7 @@ }, "set-blocking": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "optional": true }, @@ -16094,7 +16124,7 @@ }, "string-width": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "optional": true, "requires": { @@ -18064,6 +18094,11 @@ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, + "humps": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz", + "integrity": "sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao=" + }, "husky": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/husky/-/husky-1.3.1.tgz", @@ -32762,6 +32797,11 @@ "resolved": "https://registry.npmjs.org/react-native-status-bar-height/-/react-native-status-bar-height-2.3.1.tgz", "integrity": "sha512-m9nGKYfFn6ljF1abafzF5cFaD9JCzXwj7kNE9CuF+g0TgtItH70eY2uHaCV9moENTftqd5XIS3Cx0mf4WfistA==" }, + "react-native-svg": { + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-9.7.1.tgz", + "integrity": "sha512-Yr54SyLPCdovLCJ08V7syJUe1iKrTYG9V5wB08z6lh/9FdC2R9CtBnMyz83GDLKfzUONqqH9nN1l+o61CgD3tg==" + }, "react-native-vector-icons": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-6.6.0.tgz", From 7e7b0b1bb30e16269bcee9ea58fcda2e31186ac6 Mon Sep 17 00:00:00 2001 From: xiphiness Date: Thu, 29 Aug 2019 16:57:33 -0400 Subject: [PATCH 04/22] more identity --- src/components/identity/AddIdentity.js | 165 +++++++++++++++++++ src/components/identity/IdentityDataTable.js | 50 ------ 2 files changed, 165 insertions(+), 50 deletions(-) create mode 100644 src/components/identity/AddIdentity.js diff --git a/src/components/identity/AddIdentity.js b/src/components/identity/AddIdentity.js new file mode 100644 index 0000000000..c73dc0442a --- /dev/null +++ b/src/components/identity/AddIdentity.js @@ -0,0 +1,165 @@ +// @flow +import React, { useCallback, useEffect, useState } from 'react' +import debounce from 'lodash/debounce' +import isEqualWith from 'lodash/isEqualWith' +import isEqual from 'lodash/isEqual' +import { Text } from 'react-native' +import merge from 'lodash/merge' +import pickBy from 'lodash/pickBy' +import BrandIcon from '../common/view/BrandIcon' +import IdentityDataTable from '../identity/IdentityDataTable' +import GDStore from '../../lib/undux/GDStore' +import { useErrorDialog } from '../../lib/undux/utils/dialog' +import { withStyles } from '../../lib/styles' +import { SaveButton, Section, UserAvatar, Wrapper } from '../common' + +const TITLE = 'Add Identity' + +function filterObject(obj) { + return pickBy(obj, (v, k) => v !== undefined && v !== '') +} + +const supportedIdentities = ['github', 'twitter', 'facebook'] + +const IdentityView = name => ( + + Verify {name} account + + +) + +const arrayDiff = (a, b) => { + return a.filter(x => !b.includes(x)) +} + +const AddIdentity = ({ screenProps, theme, styles }) => { + const store = GDStore.useStore() + const storedIdentity = store.get('identity') + const [identity, setIdentity] = useState(storedIdentity) + const [saving, setSaving] = useState(false) + const [isValid, setIsValid] = useState(true) + const [isPristine, setIsPristine] = useState(true) + const [errors, setErrors] = useState({}) + const [showErrorDialog] = useErrorDialog() + + //initialize identity value for first time from storedidentity + useEffect(() => { + setIdentity(storeIdentity) + }, [isEqual(identity, {}) && storedIdentity]) + + const updateIdentity = async () => { + store.set('identity')(identity) + } + + useEffect(() => { + if (isEqual(storedIdentity, {})) { + updateIdentity() + } + }, []) + + const validate = useCallback( + debounce(async (identity, storedIdentity, setIsPristine, setErrors, setIsValid) => { + if (identity && identity.validate) { + try { + const pristine = isEqualWith(storedIdentity, identity, (x, y) => { + if (typeof x === 'function') { + return true + } + if (['string', 'number'].includes(typeof x)) { + return y && x.toString() === y.toString() + } + return undefined + }) + const { isValid, errors } = identity.validate() + + const { isValid: isValidIndex, errors: errorsIndex } = await userStorage.validateIdentity( + filterObject(identity) + ) + const valid = isValid && isValidIndex + + setErrors(merge(errors, errorsIndex)) + setIsValid(valid) + setIsPristine(pristine) + + return valid + } catch (e) { + log.error('validate identity failed', e, e.message) + showErrorDialog('Unexpected error while validating identity', e) + return false + } + } + return false + }, 500), + [] + ) + + const handleIdentityChange = newIdentity => { + if (saving) { + return + } + setIdentity(newIdentity) + } + + const handleSaveButton = async () => { + setSaving(true) + + // with flush triggers immediate call for the validation + if (!(await validate.flush())) { + setSaving(false) + return false + } + + //create identity only with updated/new fields so we don't resave data + const toupdate = pickBy(identity, (v, k) => { + if (typeof v === 'function') { + return true + } + if (storedIdentity[k] === undefined) { + return true + } + if (['string', 'number'].includes(typeof v)) { + return v.toString() !== storedIdentity[k].toString() + } + if (v !== storedIdentity[k]) { + return true + } + return false + }) + return userStorage + .setIdentity(toupdate, true) + .catch(err => { + log.error('Error saving identity', { err, toupdate }) + showErrorDialog('Unexpected error while saving identity', err) + return false + }) + .finally(_ => setSaving(false)) + } + + const onIdentitySaved = () => { + screenProps.pop() + } + + // Validate after saving identity state in order to show errors + useEffect(() => { + //need to pass parameters into memoized debounced method otherwise setX hooks wont work + validate(identity, storedIdentity, setIsPristine, setErrors, setIsValid) + }, [identity]) + + return ( + +
+ {arrayDiff(supportedIdentities, Object.keys(identity)).map(x => ( + + ))} +
+
+ ) +} + +AddIdentity.navigationOptions = { + title: TITLE, +} + +const getStylesFromProps = ({ theme }) => ({}) + +export default withStyles(getStylesFromProps)(AddIdentity) diff --git a/src/components/identity/IdentityDataTable.js b/src/components/identity/IdentityDataTable.js index 5bd668ae90..4edde5ec03 100644 --- a/src/components/identity/IdentityDataTable.js +++ b/src/components/identity/IdentityDataTable.js @@ -2,63 +2,13 @@ import React from 'react' import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view' import { Text } from 'react-native' - -//import { Alert, Modal, Text, TouchableHighlight, View } from 'react-native' import Icon from '../common/view/Icon' import BrandIcon from '../common/view/BrandIcon' -//import InputRounded from '../common/form/InputRounded' import Section from '../common/layout/Section' import { withStyles } from '../../lib/styles' -// class ModalExample extends Component { -// state = { -// modalVisible: false, -// } - -// setModalVisible(visible) { -// this.setState({ modalVisible: visible }) -// } - -// render() { -// return ( -// -// { -// Alert.alert('Modal has been closed.') -// }} -// > -// -// -// Hello World! - -// { -// this.setModalVisible(!this.state.modalVisible) -// }} -// > -// Hide Modal -// -// -// -// - -// { -// this.setModalVisible(true) -// }} -// > -// Show Modal -// -// -// ) -// } -// } - const IdentityDataTable = ({ identity, errors: errorsProp, editable, theme, styles }) => { const errors = errorsProp || {} return ( From dc4d0142b6b8a9f4599341a2b1497e3f2e8ab63f Mon Sep 17 00:00:00 2001 From: xiphiness Date: Thu, 29 Aug 2019 19:55:29 -0400 Subject: [PATCH 05/22] item menu --- src/components/identity/AddIdentity.js | 2 +- src/components/identity/AddIdentityMenu.js | 60 ++++++++++++++++++++ src/components/identity/IdentityDataTable.js | 12 ++-- 3 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 src/components/identity/AddIdentityMenu.js diff --git a/src/components/identity/AddIdentity.js b/src/components/identity/AddIdentity.js index c73dc0442a..933ac84dd8 100644 --- a/src/components/identity/AddIdentity.js +++ b/src/components/identity/AddIdentity.js @@ -7,11 +7,11 @@ import { Text } from 'react-native' import merge from 'lodash/merge' import pickBy from 'lodash/pickBy' import BrandIcon from '../common/view/BrandIcon' -import IdentityDataTable from '../identity/IdentityDataTable' import GDStore from '../../lib/undux/GDStore' import { useErrorDialog } from '../../lib/undux/utils/dialog' import { withStyles } from '../../lib/styles' import { SaveButton, Section, UserAvatar, Wrapper } from '../common' +import IdentityDataTable from './IdentityDataTable' const TITLE = 'Add Identity' diff --git a/src/components/identity/AddIdentityMenu.js b/src/components/identity/AddIdentityMenu.js new file mode 100644 index 0000000000..a0138e3aad --- /dev/null +++ b/src/components/identity/AddIdentityMenu.js @@ -0,0 +1,60 @@ +// @flow +import React from 'react' + +import { FlatList, Text, TouchableOpacity } from 'react-native' +import BrandIcon from '../common/view/BrandIcon' +import { withStyles } from '../../lib/styles' +import { Section, Wrapper } from '../common' +import GDStore from '../../lib/undux/GDStore' + +const TITLE = 'Add Identity' + +// function filterObject(obj) { +// return pickBy(obj, (v, k) => v !== undefined && v !== '') +// } + +const supportedIdentities = ['github', 'twitter', 'facebook'] + +const arrayDiff = (a, b) => { + return a.filter(x => !b.includes(x)) +} + +const IdentityView = ({ id, onPress }) => ( + + Verify {id} account + + +) + +const AddIdentityMenu = ({ screenProps, theme, styles }) => { + const store = GDStore.useStore() + const storedIdentity = store.get('identity') + const onPressItem = id => id + + const renderItem = ({ item }) => onPressItem(item)} /> + + const keyExtractor = (item, index) => item + + return ( + +
+ + + {arrayDiff(supportedIdentities, Object.keys(storedIdentity))} + +
+
+ ) +} + +AddIdentityMenu.navigationOptions = { + title: TITLE, +} + +const getStylesFromProps = ({ theme }) => ({}) + +export default withStyles(getStylesFromProps)(AddIdentityMenu) diff --git a/src/components/identity/IdentityDataTable.js b/src/components/identity/IdentityDataTable.js index 4edde5ec03..58345854a0 100644 --- a/src/components/identity/IdentityDataTable.js +++ b/src/components/identity/IdentityDataTable.js @@ -14,17 +14,17 @@ const IdentityDataTable = ({ identity, errors: errorsProp, editable, theme, styl return ( - {Object.keys(identity).map(x => ( - - - {identity[x].username} + {Object.keys(identity).map(id => ( + + + {identity[id].username} {editable && ( delete identity[x]} + onPress={() => delete identity[id]} /> )} {errors.mobile && {errors.mobile}} From 22cdb4c27284549d1eec0d5f18adf3ec490efcb3 Mon Sep 17 00:00:00 2001 From: xiphiness Date: Fri, 30 Aug 2019 15:00:09 -0400 Subject: [PATCH 06/22] style additemmenu --- src/components/common/form/InputRounded.js | 22 +++++++--- src/components/identity/AddIdentityMenu.js | 50 +++++++++++++++++----- src/components/profile/Profile.js | 9 +++- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/components/common/form/InputRounded.js b/src/components/common/form/InputRounded.js index 3e4902ddc9..a623e15852 100644 --- a/src/components/common/form/InputRounded.js +++ b/src/components/common/form/InputRounded.js @@ -3,6 +3,7 @@ import { TextInput, View } from 'react-native' import normalize from '../../../lib/utils/normalizeText' import { withStyles } from '../../../lib/styles' import Icon from '../view/Icon' +import BrandIcon from '../view/BrandIcon' import ErrorText from './ErrorText' /** @@ -13,7 +14,7 @@ import ErrorText from './ErrorText' * @param {React.Node} props.children * @returns {React.Node} */ -const InputRounded = ({ styles, theme, icon, iconSize, iconColor, error, onChange, ...inputProps }) => { +const InputRounded = ({ styles, theme, brand, icon, iconSize, iconColor, error, onChange, ...inputProps }) => { const handleChange = event => { onChange(event.target.value) } @@ -30,11 +31,20 @@ const InputRounded = ({ styles, theme, icon, iconSize, iconColor, error, onChang {...inputProps} /> - + {icon && !brand && ( + + )} + {!icon && brand && ( + + )} {!inputProps.disabled && } diff --git a/src/components/identity/AddIdentityMenu.js b/src/components/identity/AddIdentityMenu.js index a0138e3aad..83ba7f1772 100644 --- a/src/components/identity/AddIdentityMenu.js +++ b/src/components/identity/AddIdentityMenu.js @@ -1,10 +1,10 @@ // @flow import React from 'react' -import { FlatList, Text, TouchableOpacity } from 'react-native' -import BrandIcon from '../common/view/BrandIcon' +import { FlatList, TouchableOpacity } from 'react-native' import { withStyles } from '../../lib/styles' import { Section, Wrapper } from '../common' +import InputRounded from '../common/form/InputRounded' import GDStore from '../../lib/undux/GDStore' const TITLE = 'Add Identity' @@ -19,10 +19,17 @@ const arrayDiff = (a, b) => { return a.filter(x => !b.includes(x)) } -const IdentityView = ({ id, onPress }) => ( - - Verify {id} account - +const IdentityView = ({ id, onPress, style, theme }) => ( + + + + ) @@ -31,20 +38,21 @@ const AddIdentityMenu = ({ screenProps, theme, styles }) => { const storedIdentity = store.get('identity') const onPressItem = id => id - const renderItem = ({ item }) => onPressItem(item)} /> + const renderItem = ({ item }) => ( + onPressItem(item)} /> + ) const keyExtractor = (item, index) => item return ( -
+
- {arrayDiff(supportedIdentities, Object.keys(storedIdentity))}
@@ -55,6 +63,28 @@ AddIdentityMenu.navigationOptions = { title: TITLE, } -const getStylesFromProps = ({ theme }) => ({}) +const getStylesFromProps = ({ theme }) => { + return { + borderedBottomStyle: { + borderBottomColor: theme.colors.lightGray, + borderBottomWidth: 1, + }, + suffixIcon: { + alignItems: 'center', + display: 'flex', + height: 38, + justifyContent: 'center', + position: 'absolute', + right: 0, + top: 0, + width: 32, + zIndex: 1, + }, + errorMargin: { + marginTop: theme.sizes.default, + marginBottom: theme.sizes.default, + }, + } +} export default withStyles(getStylesFromProps)(AddIdentityMenu) diff --git a/src/components/profile/Profile.js b/src/components/profile/Profile.js index 5853e23b19..e091cddf7c 100644 --- a/src/components/profile/Profile.js +++ b/src/components/profile/Profile.js @@ -7,6 +7,7 @@ import { Section, UserAvatar, Wrapper } from '../common' import { withStyles } from '../../lib/styles' import userStorage from '../../lib/gundb/UserStorage' import IdentityDataTable from '../identity/IdentityDataTable' +import AddIdentityMenu from '../identity/AddIdentityMenu' import EditAvatar from './EditAvatar' import EditProfile from './EditProfile' import ProfileDataTable from './ProfileDataTable' @@ -64,6 +65,12 @@ const ProfileWrapper = props => { + screenProps.push('AddIdentityMenu')} + style={[styles.iconRight]} + />
) @@ -85,4 +92,4 @@ const getStylesFromProps = ({ theme }) => ({ const Profile = withStyles(getStylesFromProps)(ProfileWrapper) -export default createStackNavigator({ Profile, EditProfile, ProfilePrivacy, ViewAvatar, EditAvatar }) +export default createStackNavigator({ Profile, EditProfile, ProfilePrivacy, ViewAvatar, EditAvatar, AddIdentityMenu }) From f6f0239368f08f68659b0f3ee14f3832374a6d39 Mon Sep 17 00:00:00 2001 From: xiphiness Date: Fri, 30 Aug 2019 15:00:46 -0400 Subject: [PATCH 07/22] style additemmenu --- src/components/profile/EditProfile.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/profile/EditProfile.js b/src/components/profile/EditProfile.js index 5f8a5b80a6..656c39b4d1 100644 --- a/src/components/profile/EditProfile.js +++ b/src/components/profile/EditProfile.js @@ -6,6 +6,8 @@ import isEqual from 'lodash/isEqual' import merge from 'lodash/merge' import pickBy from 'lodash/pickBy' + +//import IdentityDataTable from '../identity/IdentityDataTable' import userStorage from '../../lib/gundb/UserStorage' import logger from '../../lib/logger/pino-logger' import GDStore from '../../lib/undux/GDStore' @@ -166,6 +168,14 @@ EditProfile.navigationOptions = { title: TITLE, } -const getStylesFromProps = ({ theme }) => ({}) +const getStylesFromProps = ({ theme }) => ({ + section: { + flexGrow: 1, + padding: theme.sizes.defaultDouble, + }, + iconRight: { + transform: [{ rotateY: '180deg' }], + }, +}) export default withStyles(getStylesFromProps)(EditProfile) From 2ddd48a397d9606edfe8de8c5f78351c62326ea6 Mon Sep 17 00:00:00 2001 From: xiphiness Date: Sat, 31 Aug 2019 14:45:17 -0400 Subject: [PATCH 08/22] addidentity views --- src/components/identity/AddIdentity.js | 221 ++++++++----------- src/components/identity/AddIdentityMenu.js | 23 +- src/components/identity/IdentityDataTable.js | 37 ++-- src/components/profile/EditProfile.js | 11 + src/components/profile/Profile.js | 14 +- 5 files changed, 146 insertions(+), 160 deletions(-) diff --git a/src/components/identity/AddIdentity.js b/src/components/identity/AddIdentity.js index 933ac84dd8..3f4abb3860 100644 --- a/src/components/identity/AddIdentity.js +++ b/src/components/identity/AddIdentity.js @@ -1,156 +1,101 @@ // @flow -import React, { useCallback, useEffect, useState } from 'react' -import debounce from 'lodash/debounce' -import isEqualWith from 'lodash/isEqualWith' -import isEqual from 'lodash/isEqual' -import { Text } from 'react-native' -import merge from 'lodash/merge' -import pickBy from 'lodash/pickBy' -import BrandIcon from '../common/view/BrandIcon' +import React from 'react' import GDStore from '../../lib/undux/GDStore' -import { useErrorDialog } from '../../lib/undux/utils/dialog' +import { SaveButton, Section, Wrapper } from '../common' +import InputRounded from '../common/form/InputRounded' +import { useScreenState } from '../appNavigation/stackNavigation' import { withStyles } from '../../lib/styles' -import { SaveButton, Section, UserAvatar, Wrapper } from '../common' -import IdentityDataTable from './IdentityDataTable' const TITLE = 'Add Identity' -function filterObject(obj) { - return pickBy(obj, (v, k) => v !== undefined && v !== '') -} - -const supportedIdentities = ['github', 'twitter', 'facebook'] - -const IdentityView = name => ( - - Verify {name} account - - -) - -const arrayDiff = (a, b) => { - return a.filter(x => !b.includes(x)) -} - const AddIdentity = ({ screenProps, theme, styles }) => { - const store = GDStore.useStore() - const storedIdentity = store.get('identity') - const [identity, setIdentity] = useState(storedIdentity) - const [saving, setSaving] = useState(false) - const [isValid, setIsValid] = useState(true) - const [isPristine, setIsPristine] = useState(true) - const [errors, setErrors] = useState({}) - const [showErrorDialog] = useErrorDialog() - //initialize identity value for first time from storedidentity - useEffect(() => { - setIdentity(storeIdentity) - }, [isEqual(identity, {}) && storedIdentity]) + // useEffect(() => { + // setIdentity(storeIdentity) + // }, [isEqual(identity, {}) && storedIdentity]) + + // const updateIdentity = async () => { + // store.set('identity')(identity) + // } + + // useEffect(() => { + // if (isEqual(storedIdentity, {})) { + // updateIdentity() + // } + // }, []) + + // const validate = useCallback( + // debounce(async (identity, storedIdentity, setIsPristine, setErrors, setIsValid) => { + // if (identity && identity.validate) { + // try { + // const pristine = isEqualWith(storedIdentity, identity, (x, y) => { + // if (typeof x === 'function') { + // return true + // } + // if (['string', 'number'].includes(typeof x)) { + // return y && x.toString() === y.toString() + // } + // return undefined + // }) + // const { isValid, errors } = identity.validate() + + // const { isValid: isValidIndex, errors: errorsIndex } = await userStorage.validateIdentity( + // filterObject(identity) + // ) + // const valid = isValid && isValidIndex + + // setErrors(merge(errors, errorsIndex)) + // setIsValid(valid) + // setIsPristine(pristine) + + // return valid + // } catch (e) { + // log.error('validate identity failed', e, e.message) + // showErrorDialog('Unexpected error while validating identity', e) + // return false + // } + // } + // return false + // }, 500), + // [] + // ) - const updateIdentity = async () => { - store.set('identity')(identity) - } + const store = GDStore.useStore() + const identity = store.get('identity') + const [screenState] = useScreenState(screenProps) - useEffect(() => { - if (isEqual(storedIdentity, {})) { - updateIdentity() - } - }, []) - - const validate = useCallback( - debounce(async (identity, storedIdentity, setIsPristine, setErrors, setIsValid) => { - if (identity && identity.validate) { - try { - const pristine = isEqualWith(storedIdentity, identity, (x, y) => { - if (typeof x === 'function') { - return true - } - if (['string', 'number'].includes(typeof x)) { - return y && x.toString() === y.toString() - } - return undefined - }) - const { isValid, errors } = identity.validate() - - const { isValid: isValidIndex, errors: errorsIndex } = await userStorage.validateIdentity( - filterObject(identity) - ) - const valid = isValid && isValidIndex - - setErrors(merge(errors, errorsIndex)) - setIsValid(valid) - setIsPristine(pristine) - - return valid - } catch (e) { - log.error('validate identity failed', e, e.message) - showErrorDialog('Unexpected error while validating identity', e) - return false - } - } - return false - }, 500), - [] - ) + const { name } = screenState - const handleIdentityChange = newIdentity => { - if (saving) { - return - } - setIdentity(newIdentity) + const handleIdentityChange = newUsername => { + identity[name] = { username: newUsername } } - const handleSaveButton = async () => { - setSaving(true) - - // with flush triggers immediate call for the validation - if (!(await validate.flush())) { - setSaving(false) - return false - } - - //create identity only with updated/new fields so we don't resave data - const toupdate = pickBy(identity, (v, k) => { - if (typeof v === 'function') { - return true - } - if (storedIdentity[k] === undefined) { - return true - } - if (['string', 'number'].includes(typeof v)) { - return v.toString() !== storedIdentity[k].toString() - } - if (v !== storedIdentity[k]) { - return true - } - return false - }) - return userStorage - .setIdentity(toupdate, true) - .catch(err => { - log.error('Error saving identity', { err, toupdate }) - showErrorDialog('Unexpected error while saving identity', err) - return false - }) - .finally(_ => setSaving(false)) + const handleSaveButton = () => { + store.set('identity')(identity) + return identity[name].username } const onIdentitySaved = () => { screenProps.pop() + return identity[name].username } - - // Validate after saving identity state in order to show errors - useEffect(() => { - //need to pass parameters into memoized debounced method otherwise setX hooks wont work - validate(identity, storedIdentity, setIsPristine, setErrors, setIsValid) - }, [identity]) - return ( -
- {arrayDiff(supportedIdentities, Object.keys(identity)).map(x => ( - - ))} +
+ + + + + +
) @@ -160,6 +105,14 @@ AddIdentity.navigationOptions = { title: TITLE, } -const getStylesFromProps = ({ theme }) => ({}) +const getStylesFromProps = ({ theme }) => ({ + section: { + flexGrow: 1, + padding: theme.sizes.defaultDouble, + }, + iconRight: { + transform: [{ rotateY: '180deg' }], + }, +}) export default withStyles(getStylesFromProps)(AddIdentity) diff --git a/src/components/identity/AddIdentityMenu.js b/src/components/identity/AddIdentityMenu.js index 83ba7f1772..1a6c7751b7 100644 --- a/src/components/identity/AddIdentityMenu.js +++ b/src/components/identity/AddIdentityMenu.js @@ -1,6 +1,5 @@ // @flow import React from 'react' - import { FlatList, TouchableOpacity } from 'react-native' import { withStyles } from '../../lib/styles' import { Section, Wrapper } from '../common' @@ -20,8 +19,8 @@ const arrayDiff = (a, b) => { } const IdentityView = ({ id, onPress, style, theme }) => ( - - + + ( const AddIdentityMenu = ({ screenProps, theme, styles }) => { const store = GDStore.useStore() const storedIdentity = store.get('identity') - const onPressItem = id => id - const renderItem = ({ item }) => ( - onPressItem(item)} /> - ) + const onAddIdentityPress = name => { + screenProps.push('AddIdentity', { name, theme, styles }) + } + + const renderItem = ({ item }) => { + return ( + onAddIdentityPress(item)} + /> + ) + } const keyExtractor = (item, index) => item diff --git a/src/components/identity/IdentityDataTable.js b/src/components/identity/IdentityDataTable.js index 58345854a0..651bdd02d6 100644 --- a/src/components/identity/IdentityDataTable.js +++ b/src/components/identity/IdentityDataTable.js @@ -9,27 +9,30 @@ import Section from '../common/layout/Section' import { withStyles } from '../../lib/styles' -const IdentityDataTable = ({ identity, errors: errorsProp, editable, theme, styles }) => { +const IdentityDataTable = ({ identity, errors: errorsProp, onChange, editable, theme, styles }) => { const errors = errorsProp || {} return ( - {Object.keys(identity).map(id => ( - - - {identity[id].username} - {editable && ( - delete identity[id]} - /> - )} - {errors.mobile && {errors.mobile}} - - ))} + {Object.keys(identity).map( + id => + identity[id] && ( + + + {identity[id].username} + {editable && ( + onChange(id)} + /> + )} + {errors.mobile && {errors.mobile}} + + ) + )} ) diff --git a/src/components/profile/EditProfile.js b/src/components/profile/EditProfile.js index 30abe59df0..b29494a5d7 100644 --- a/src/components/profile/EditProfile.js +++ b/src/components/profile/EditProfile.js @@ -14,6 +14,7 @@ import GDStore from '../../lib/undux/GDStore' import { useErrorDialog } from '../../lib/undux/utils/dialog' import { withStyles } from '../../lib/styles' import { SaveButton, Section, UserAvatar, Wrapper } from '../common' +import IdentityDataTable from '../identity/IdentityDataTable' import CameraButton from './CameraButton' import ProfileDataTable from './ProfileDataTable' @@ -34,6 +35,8 @@ const EditProfile = ({ screenProps, theme, styles }) => { const [isPristine, setIsPristine] = useState(true) const [errors, setErrors] = useState({}) const [showErrorDialog] = useErrorDialog() + const storedIdentity = store.get('identity') + const [identity, setIdentity] = useState(storedIdentity) //initialize profile value for first time from storedprofile useEffect(() => { @@ -95,6 +98,7 @@ const EditProfile = ({ screenProps, theme, styles }) => { } const handleSaveButton = async () => { + store.set('identity')(identity) setSaving(true) // with flush triggers immediate call for the validation @@ -133,6 +137,12 @@ const EditProfile = ({ screenProps, theme, styles }) => { screenProps.pop() } + const handleIdentityChange = name => { + const obj = { ...identity } + delete obj[name] + setIdentity(obj) + } + const handleAvatarPress = event => { event.stopPropagation() screenProps.push(`${profile.avatar ? 'View' : 'Edit'}Avatar`) @@ -159,6 +169,7 @@ const EditProfile = ({ screenProps, theme, styles }) => { +
) diff --git a/src/components/profile/Profile.js b/src/components/profile/Profile.js index e091cddf7c..83749c8159 100644 --- a/src/components/profile/Profile.js +++ b/src/components/profile/Profile.js @@ -8,6 +8,7 @@ import { withStyles } from '../../lib/styles' import userStorage from '../../lib/gundb/UserStorage' import IdentityDataTable from '../identity/IdentityDataTable' import AddIdentityMenu from '../identity/AddIdentityMenu' +import AddIdentity from '../identity/AddIdentity' import EditAvatar from './EditAvatar' import EditProfile from './EditProfile' import ProfileDataTable from './ProfileDataTable' @@ -32,6 +33,7 @@ const ExampleIdentity = { const ProfileWrapper = props => { const store = GDStore.useStore() const profile = store.get('profile') + const identity = store.get('identity') const { screenProps, styles } = props const editIdentities = false @@ -64,7 +66,7 @@ const ProfileWrapper = props => { />
- + ({ const Profile = withStyles(getStylesFromProps)(ProfileWrapper) -export default createStackNavigator({ Profile, EditProfile, ProfilePrivacy, ViewAvatar, EditAvatar, AddIdentityMenu }) +export default createStackNavigator({ + Profile, + EditProfile, + ProfilePrivacy, + ViewAvatar, + EditAvatar, + AddIdentityMenu, + AddIdentity, +}) From 873f28ab95dee4c9f3fc402e6727f748177f1251 Mon Sep 17 00:00:00 2001 From: xiphiness Date: Sun, 1 Sep 2019 17:52:40 -0400 Subject: [PATCH 09/22] editprofile state for identity --- src/components/profile/EditProfile.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/profile/EditProfile.js b/src/components/profile/EditProfile.js index b29494a5d7..50bfe3dfb5 100644 --- a/src/components/profile/EditProfile.js +++ b/src/components/profile/EditProfile.js @@ -77,7 +77,6 @@ const EditProfile = ({ screenProps, theme, styles }) => { setErrors(merge(errors, errorsIndex)) setIsValid(valid) setIsPristine(pristine) - return valid } catch (e) { log.error('validate profile failed', e.message, e) @@ -140,7 +139,10 @@ const EditProfile = ({ screenProps, theme, styles }) => { const handleIdentityChange = name => { const obj = { ...identity } delete obj[name] + console.log('identity changed') setIdentity(obj) + setIsPristine(false) + setIsValid(true) } const handleAvatarPress = event => { @@ -156,9 +158,16 @@ const EditProfile = ({ screenProps, theme, styles }) => { // Validate after saving profile state in order to show errors useEffect(() => { //need to pass parameters into memoized debounced method otherwise setX hooks wont work - validate(profile, storedProfile, setIsPristine, setErrors, setIsValid) + validate(profile, storedProfile, identity, storedIdentity, setIsPristine, setErrors, setIsValid) }, [profile]) + useEffect(() => { + console.log('identity triggered') + + //need to pass parameters into memoized debounced method otherwise setX hooks wont work + validate(profile, storedProfile, identity, storedIdentity, setIsPristine, setErrors, setIsValid) + }, [identity]) + return (
From 9c8c0d08bd4fa04ecb0df8202205cb6f19c31dd6 Mon Sep 17 00:00:00 2001 From: xiphiness Date: Sun, 1 Sep 2019 18:12:48 -0400 Subject: [PATCH 10/22] update add identity menu --- src/components/identity/AddIdentityMenu.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/components/identity/AddIdentityMenu.js b/src/components/identity/AddIdentityMenu.js index 1a6c7751b7..2669515f08 100644 --- a/src/components/identity/AddIdentityMenu.js +++ b/src/components/identity/AddIdentityMenu.js @@ -12,6 +12,14 @@ const TITLE = 'Add Identity' // return pickBy(obj, (v, k) => v !== undefined && v !== '') // } +/* +In Profile view, identities should have same style and be spaced appropriately with respect to the other account information. +Maybe a separator that notes the latter are identities, maybe not. +In EditProfile, identities should have the same style and be spaced appropriately as the above information, or not exist there at all. +In AddIdentity, double gray lines in add identity should be removed. Should maybe be more filled out, maybe add a header view. + +*/ + const supportedIdentities = ['github', 'twitter', 'facebook'] const arrayDiff = (a, b) => { From 47d334436869e2c9031de04855c6cf9590edd698 Mon Sep 17 00:00:00 2001 From: xiphiness Date: Sun, 1 Sep 2019 18:16:03 -0400 Subject: [PATCH 11/22] fix identitydatatable --- src/components/identity/IdentityDataTable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/identity/IdentityDataTable.js b/src/components/identity/IdentityDataTable.js index 651bdd02d6..886d854c4c 100644 --- a/src/components/identity/IdentityDataTable.js +++ b/src/components/identity/IdentityDataTable.js @@ -26,7 +26,7 @@ const IdentityDataTable = ({ identity, errors: errorsProp, onChange, editable, t name="close" size={28} style={styles.phoneIcon} - onPress={() => onChange(id)} + onPress={onChange ? () => onChange(id) : null} /> )} {errors.mobile && {errors.mobile}} From 4fb0e5aacb9e138db94863b9e91f5f011a3ff502 Mon Sep 17 00:00:00 2001 From: xiphiness Date: Sun, 1 Sep 2019 18:19:41 -0400 Subject: [PATCH 12/22] remove logging --- src/components/profile/EditProfile.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/profile/EditProfile.js b/src/components/profile/EditProfile.js index 50bfe3dfb5..3a518333d3 100644 --- a/src/components/profile/EditProfile.js +++ b/src/components/profile/EditProfile.js @@ -139,7 +139,6 @@ const EditProfile = ({ screenProps, theme, styles }) => { const handleIdentityChange = name => { const obj = { ...identity } delete obj[name] - console.log('identity changed') setIdentity(obj) setIsPristine(false) setIsValid(true) @@ -162,8 +161,6 @@ const EditProfile = ({ screenProps, theme, styles }) => { }, [profile]) useEffect(() => { - console.log('identity triggered') - //need to pass parameters into memoized debounced method otherwise setX hooks wont work validate(profile, storedProfile, identity, storedIdentity, setIsPristine, setErrors, setIsValid) }, [identity]) From 70c945411ccdb6250244e5a29997c0e8cd8bc31e Mon Sep 17 00:00:00 2001 From: xiphiness Date: Mon, 2 Sep 2019 20:04:29 -0400 Subject: [PATCH 13/22] photo, human verification --- .../identity/AddHumanVerification.js | 85 ++++++++++++++++++ src/components/identity/AddIdentityMenu.js | 13 +++ src/components/identity/IdentityDataTable.js | 22 +++-- src/components/identity/UploadPhoto.js | 87 +++++++++++++++++++ 4 files changed, 198 insertions(+), 9 deletions(-) create mode 100644 src/components/identity/AddHumanVerification.js create mode 100644 src/components/identity/UploadPhoto.js diff --git a/src/components/identity/AddHumanVerification.js b/src/components/identity/AddHumanVerification.js new file mode 100644 index 0000000000..fe176e9db2 --- /dev/null +++ b/src/components/identity/AddHumanVerification.js @@ -0,0 +1,85 @@ +// @flow +import React, { useState } from 'react' +import { withTheme } from 'react-native-paper' +import { TouchableOpacity } from 'react-native' +import InputRounded from '../common/form/InputRounded' +import { useWrappedUserStorage } from '../../lib/gundb/useWrappedStorage' +import { CustomButton, Section, Wrapper } from '../common' + +const TITLE = 'Upload Id' + +const AddHumanVerification = ({ screenProps, theme, styles }) => { + const wrappedUserStorage = useWrappedUserStorage() + const [, setAvatar] = useState() + const [changed, setChanged] = useState(false) + const [saving, setSaving] = useState(false) + + const saveAvatar = async () => { + setSaving(true) + + await wrappedUserStorage + setSaving(false) + screenProps.pop() + } + + const handleAvatarChange = avatar => { + setAvatar(avatar) + setChanged(true) + } + + const handleAvatarClose = () => { + setAvatar(null) + setChanged(true) + } + + const handleUploadPhoto = () => { + screenProps.push('UploadPhoto', { onChange: handleAvatarChange, onClose: handleAvatarClose }) + } + const handleTakePhoto = () => { + screenProps.push('FaceVerification') + } + + return ( + +
+ + + + + + + + + + + Upload or take a picture of yourself with {global.wallet.getAccountForType('gd').slice(1, 7)} and today{"'"} + s date written down on a piece of paper. + + +
+
+ ) +} + +AddHumanVerification.navigationOptions = { + title: TITLE, +} + +export default withTheme(AddHumanVerification) diff --git a/src/components/identity/AddIdentityMenu.js b/src/components/identity/AddIdentityMenu.js index 2669515f08..a5bd7f932c 100644 --- a/src/components/identity/AddIdentityMenu.js +++ b/src/components/identity/AddIdentityMenu.js @@ -61,6 +61,10 @@ const AddIdentityMenu = ({ screenProps, theme, styles }) => { const keyExtractor = (item, index) => item + const handleVerifyPhoto = () => { + screenProps.push('AddHumanVerification') + } + return (
@@ -70,6 +74,15 @@ const AddIdentityMenu = ({ screenProps, theme, styles }) => { keyExtractor={keyExtractor} renderItem={renderItem} /> + + +
diff --git a/src/components/identity/IdentityDataTable.js b/src/components/identity/IdentityDataTable.js index 886d854c4c..3defb49cbe 100644 --- a/src/components/identity/IdentityDataTable.js +++ b/src/components/identity/IdentityDataTable.js @@ -1,3 +1,4 @@ +// @flow import React from 'react' import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view' @@ -20,15 +21,18 @@ const IdentityDataTable = ({ identity, errors: errorsProp, onChange, editable, t {identity[id].username} - {editable && ( - onChange(id) : null} - /> - )} + {editable && + (onChange ? ( + onChange(id) : null} + /> + ) : ( + + ))} {errors.mobile && {errors.mobile}} ) diff --git a/src/components/identity/UploadPhoto.js b/src/components/identity/UploadPhoto.js new file mode 100644 index 0000000000..186a373cd8 --- /dev/null +++ b/src/components/identity/UploadPhoto.js @@ -0,0 +1,87 @@ +// @flow +import React from 'react' +import { View } from 'react-native' +import CreateAvatar from 'exif-react-avatar-edit' +import { getScreenHeight, getScreenWidth, isPortrait } from '../../lib/utils/Orientation' +import { Section, Wrapper } from '../common' + +import { withStyles } from '../../lib/styles' + +export type AvatarProps = { + profile: { + avatar: string, + fullName?: string, + }, + onChange?: any => mixed, + onClose?: any => mixed, + originalSize?: boolean, + editable?: boolean, + children?: React.Node, +} + +/** + * Touchable Users Avatar based on Avatar component + * @param {AvatarProps} props + * @param {Object} props.profile + * @param {string} props.profile.avatar + * @param {string} props.profile.fullName + * @param {any => mixed} props.onChange + * @param {any => mixed} props.onClose + * @param {boolean} props.editable + * @param {React.Node} props.children + * @returns {React.Node} + */ +const UploadPhoto = (props: AvatarProps) => { + const { profile, onChange, onClose, styles } = props + + const screenWidth = isPortrait() ? getScreenWidth() : getScreenHeight() + let cropSize = Math.min(screenWidth - 70, 320) + + return ( + +
+ + + + + +
+
+ ) +} + +const getStylesFromProps = ({ theme }) => ({ + avatar: { + flexDirection: 'row', + justifyContent: 'center', + }, + innerAvatar: { + alignItems: 'center', + flex: 1, + flexDirection: 'column', + }, + fullNameContainer: { + marginTop: theme.sizes.default, + }, + fullName: { + textAlign: 'left', + }, + cropContainer: { + flex: 1, + flexDirection: 'row', + justifyContent: 'center', + marginTop: theme.paddings.mainContainerPadding, + }, +}) + +export default withStyles(getStylesFromProps)(UploadPhoto) From 3c463c680af428747c5b44b616c3f70aef0cf8e2 Mon Sep 17 00:00:00 2001 From: xiphiness Date: Tue, 3 Sep 2019 02:49:07 -0400 Subject: [PATCH 14/22] semisemisemifinal views --- src/components/common/view/BrandIcon.js | 9 +- src/components/common/view/Icon/config.json | 20 ++++- src/components/dashboard/Dashboard.js | 1 - .../identity/AddHumanVerification.js | 8 +- src/components/identity/AddIdentityMenu.js | 45 ++++++---- src/components/identity/AddPhotoId.js | 84 +++++++++++++++++++ src/components/identity/IdentityDataTable.js | 35 ++++---- src/components/identity/UploadPhoto.js | 72 +++++++++++----- src/components/profile/Profile.js | 8 ++ src/lib/undux/GDStore.js | 2 + 10 files changed, 220 insertions(+), 64 deletions(-) mode change 100755 => 100644 src/components/common/view/Icon/config.json create mode 100644 src/components/identity/AddPhotoId.js diff --git a/src/components/common/view/BrandIcon.js b/src/components/common/view/BrandIcon.js index 0eb5236cbe..c13a145aed 100644 --- a/src/components/common/view/BrandIcon.js +++ b/src/components/common/view/BrandIcon.js @@ -1,11 +1,12 @@ import React from 'react' import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome' -import { faFacebookSquare, faGithubSquare, faTwitterSquare } from '@fortawesome/free-brands-svg-icons' +import { faFacebookSquare, faGithubSquare, faLinkedin, faTwitterSquare } from '@fortawesome/free-brands-svg-icons' const icons = { - twitter: faTwitterSquare, - facebook: faFacebookSquare, - github: faGithubSquare, + Twitter: faTwitterSquare, + Facebook: faFacebookSquare, + GitHub: faGithubSquare, + LinkedIn: faLinkedin, } const BrandIcon = ({ name, ...props }) => diff --git a/src/components/common/view/Icon/config.json b/src/components/common/view/Icon/config.json old mode 100755 new mode 100644 index 2cee593662..d9504ab225 --- a/src/components/common/view/Icon/config.json +++ b/src/components/common/view/Icon/config.json @@ -775,6 +775,24 @@ "search": [ "icons---settings---terms-of-use-–-1" ] + }, + { + "uid": "4743b088aa95d6f3b6b990e770d3b647", + "css": "facebook", + "code": 62216, + "src": "fontawesome" + }, + { + "uid": "0f6a2573a7b6df911ed199bb63717e27", + "css": "github", + "code": 61595, + "src": "fontawesome" + }, + { + "uid": "906348dc798a0d42715cc97c875e3ac6", + "css": "twitter", + "code": 62212, + "src": "fontawesome" } ] -} +} \ No newline at end of file diff --git a/src/components/dashboard/Dashboard.js b/src/components/dashboard/Dashboard.js index b11cb5ba3c..bd464336e5 100644 --- a/src/components/dashboard/Dashboard.js +++ b/src/components/dashboard/Dashboard.js @@ -1,6 +1,5 @@ // @flow import React, { useEffect, useState } from 'react' - import type { Store } from 'undux' import normalize from '../../lib/utils/normalizeText' import GDStore from '../../lib/undux/GDStore' diff --git a/src/components/identity/AddHumanVerification.js b/src/components/identity/AddHumanVerification.js index fe176e9db2..17c022675b 100644 --- a/src/components/identity/AddHumanVerification.js +++ b/src/components/identity/AddHumanVerification.js @@ -6,7 +6,7 @@ import InputRounded from '../common/form/InputRounded' import { useWrappedUserStorage } from '../../lib/gundb/useWrappedStorage' import { CustomButton, Section, Wrapper } from '../common' -const TITLE = 'Upload Id' +const TITLE = 'Upload personal photo' const AddHumanVerification = ({ screenProps, theme, styles }) => { const wrappedUserStorage = useWrappedUserStorage() @@ -33,7 +33,11 @@ const AddHumanVerification = ({ screenProps, theme, styles }) => { } const handleUploadPhoto = () => { - screenProps.push('UploadPhoto', { onChange: handleAvatarChange, onClose: handleAvatarClose }) + screenProps.push('UploadPhoto', { + photoType: 'humanPhoto', + onChange: handleAvatarChange, + onClose: handleAvatarClose, + }) } const handleTakePhoto = () => { screenProps.push('FaceVerification') diff --git a/src/components/identity/AddIdentityMenu.js b/src/components/identity/AddIdentityMenu.js index a5bd7f932c..81635ce447 100644 --- a/src/components/identity/AddIdentityMenu.js +++ b/src/components/identity/AddIdentityMenu.js @@ -12,15 +12,7 @@ const TITLE = 'Add Identity' // return pickBy(obj, (v, k) => v !== undefined && v !== '') // } -/* -In Profile view, identities should have same style and be spaced appropriately with respect to the other account information. -Maybe a separator that notes the latter are identities, maybe not. -In EditProfile, identities should have the same style and be spaced appropriately as the above information, or not exist there at all. -In AddIdentity, double gray lines in add identity should be removed. Should maybe be more filled out, maybe add a header view. - -*/ - -const supportedIdentities = ['github', 'twitter', 'facebook'] +const supportedIdentities = ['GitHub', 'Twitter', 'Facebook', 'LinkedIn'] const arrayDiff = (a, b) => { return a.filter(x => !b.includes(x)) @@ -43,6 +35,7 @@ const IdentityView = ({ id, onPress, style, theme }) => ( const AddIdentityMenu = ({ screenProps, theme, styles }) => { const store = GDStore.useStore() const storedIdentity = store.get('identity') + const identityPhotos = store.get('identityPhotos') const onAddIdentityPress = name => { screenProps.push('AddIdentity', { name, theme, styles }) @@ -64,6 +57,9 @@ const AddIdentityMenu = ({ screenProps, theme, styles }) => { const handleVerifyPhoto = () => { screenProps.push('AddHumanVerification') } + const handleVerifyPhotoId = () => { + screenProps.push('AddPhotoId') + } return ( @@ -74,15 +70,28 @@ const AddIdentityMenu = ({ screenProps, theme, styles }) => { keyExtractor={keyExtractor} renderItem={renderItem} /> - - - + {!identityPhotos.humanPhoto && ( + + + + )} + {!identityPhotos.photoId && ( + + + + )}
diff --git a/src/components/identity/AddPhotoId.js b/src/components/identity/AddPhotoId.js new file mode 100644 index 0000000000..f6f4b8e95b --- /dev/null +++ b/src/components/identity/AddPhotoId.js @@ -0,0 +1,84 @@ +// @flow +import React, { useState } from 'react' +import { withTheme } from 'react-native-paper' +import { TouchableOpacity } from 'react-native' +import InputRounded from '../common/form/InputRounded' +import { useWrappedUserStorage } from '../../lib/gundb/useWrappedStorage' +import { CustomButton, Section, Wrapper } from '../common' + +const TITLE = 'Upload Photo ID' + +const AddHumanVerification = ({ screenProps, theme, styles }) => { + const wrappedUserStorage = useWrappedUserStorage() + const [, setAvatar] = useState() + const [changed, setChanged] = useState(false) + const [saving, setSaving] = useState(false) + + const saveAvatar = async () => { + setSaving(true) + + await wrappedUserStorage + setSaving(false) + screenProps.pop() + } + + const handleAvatarChange = avatar => { + setAvatar(avatar) + setChanged(true) + } + + const handleAvatarClose = () => { + setAvatar(null) + setChanged(true) + } + + const handleUploadPhoto = () => { + screenProps.push('UploadPhoto', { photoType: 'photoId', onChange: handleAvatarChange, onClose: handleAvatarClose }) + } + const handleTakePhoto = () => { + screenProps.push('FaceVerification') + } + + return ( + +
+ + + + + + + + + + + Upload a picture of your photo id so we can verify you{"'"}re account. + + +
+
+ ) +} + +AddHumanVerification.navigationOptions = { + title: TITLE, +} + +export default withTheme(AddHumanVerification) diff --git a/src/components/identity/IdentityDataTable.js b/src/components/identity/IdentityDataTable.js index 3defb49cbe..0012cbef02 100644 --- a/src/components/identity/IdentityDataTable.js +++ b/src/components/identity/IdentityDataTable.js @@ -4,8 +4,7 @@ import React from 'react' import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view' import { Text } from 'react-native' import Icon from '../common/view/Icon' -import BrandIcon from '../common/view/BrandIcon' - +import InputRounded from '../common/form/InputRounded' import Section from '../common/layout/Section' import { withStyles } from '../../lib/styles' @@ -19,20 +18,23 @@ const IdentityDataTable = ({ identity, errors: errorsProp, onChange, editable, t id => identity[id] && ( - - {identity[id].username} - {editable && - (onChange ? ( - onChange(id) : null} - /> - ) : ( - - ))} + + {editable && ( + onChange(id) : null} + /> + )} {errors.mobile && {errors.mobile}} ) @@ -47,6 +49,7 @@ const getStylesFromProps = ({ theme }) => { borderedBottomStyle: { borderBottomColor: theme.colors.lightGray, borderBottomWidth: 1, + overflow: 'none', }, suffixIcon: { alignItems: 'center', diff --git a/src/components/identity/UploadPhoto.js b/src/components/identity/UploadPhoto.js index 186a373cd8..d6307a62ee 100644 --- a/src/components/identity/UploadPhoto.js +++ b/src/components/identity/UploadPhoto.js @@ -1,13 +1,16 @@ // @flow import React from 'react' -import { View } from 'react-native' import CreateAvatar from 'exif-react-avatar-edit' +import { View } from 'react-native' import { getScreenHeight, getScreenWidth, isPortrait } from '../../lib/utils/Orientation' -import { Section, Wrapper } from '../common' +import { CustomButton, Section, Wrapper } from '../common' +import GDStore from '../../lib/undux/GDStore' + +import { useScreenState } from '../appNavigation/stackNavigation' import { withStyles } from '../../lib/styles' -export type AvatarProps = { +export type UploadPhotoProps = { profile: { avatar: string, fullName?: string, @@ -20,8 +23,8 @@ export type AvatarProps = { } /** - * Touchable Users Avatar based on Avatar component - * @param {AvatarProps} props + * Touchable Users UploadPhoto based on UploadPhoto component + * @param {UploadPhotoProps} props * @param {Object} props.profile * @param {string} props.profile.avatar * @param {string} props.profile.fullName @@ -31,30 +34,50 @@ export type AvatarProps = { * @param {React.Node} props.children * @returns {React.Node} */ -const UploadPhoto = (props: AvatarProps) => { - const { profile, onChange, onClose, styles } = props +const UploadPhoto = (props: UploadPhotoProps) => { + const { screenProps, styles, theme } = props const screenWidth = isPortrait() ? getScreenWidth() : getScreenHeight() let cropSize = Math.min(screenWidth - 70, 320) + const store = GDStore.useStore() + const identity = store.get('identityPhotos') + const [screenState] = useScreenState(screenProps) + + const { photoType, onChange, onClose } = screenState + + const handlePhotoSubmit = () => { + identity[photoType] = { photo: null } + store.set('identityPhotos')(identity) + screenProps.pop() + screenProps.pop() + } + return (
- - - + + + + + - + + + + Submit + +
) @@ -65,7 +88,7 @@ const getStylesFromProps = ({ theme }) => ({ flexDirection: 'row', justifyContent: 'center', }, - innerAvatar: { + innerUploadPhoto: { alignItems: 'center', flex: 1, flexDirection: 'column', @@ -82,6 +105,11 @@ const getStylesFromProps = ({ theme }) => ({ justifyContent: 'center', marginTop: theme.paddings.mainContainerPadding, }, + section: { + paddingLeft: '1em', + paddingRight: '1em', + flex: 1, + }, }) export default withStyles(getStylesFromProps)(UploadPhoto) diff --git a/src/components/profile/Profile.js b/src/components/profile/Profile.js index 83749c8159..d9876d14f1 100644 --- a/src/components/profile/Profile.js +++ b/src/components/profile/Profile.js @@ -8,7 +8,11 @@ import { withStyles } from '../../lib/styles' import userStorage from '../../lib/gundb/UserStorage' import IdentityDataTable from '../identity/IdentityDataTable' import AddIdentityMenu from '../identity/AddIdentityMenu' +import UploadPhoto from '../identity/UploadPhoto' import AddIdentity from '../identity/AddIdentity' +import AddHumanVerification from '../identity/AddHumanVerification' +import AddPhotoId from '../identity/AddPhotoId' +import FaceRecognition from '../dashboard/FaceRecognition/FaceRecognition' import EditAvatar from './EditAvatar' import EditProfile from './EditProfile' import ProfileDataTable from './ProfileDataTable' @@ -102,4 +106,8 @@ export default createStackNavigator({ EditAvatar, AddIdentityMenu, AddIdentity, + FaceRecognition, + AddHumanVerification, + UploadPhoto, + AddPhotoId, }) diff --git a/src/lib/undux/GDStore.js b/src/lib/undux/GDStore.js index 3f194a4a1f..0b22707778 100644 --- a/src/lib/undux/GDStore.js +++ b/src/lib/undux/GDStore.js @@ -57,6 +57,8 @@ const initialState: State = { isLoggedInCitizen: false, isLoggedIn: false, profile: {}, + identity: {}, + identityPhotos: {}, privateProfile: {}, destinationPath: '', feeds: [], From eedb09efd5c9cb8805318f8f09aae2f6d475c68f Mon Sep 17 00:00:00 2001 From: xiphiness Date: Fri, 13 Sep 2019 16:08:13 -0400 Subject: [PATCH 15/22] update profile --- src/components/profile/EditProfile.js | 4 ++-- src/components/profile/Profile.js | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/profile/EditProfile.js b/src/components/profile/EditProfile.js index 3a518333d3..a1a5ae9152 100644 --- a/src/components/profile/EditProfile.js +++ b/src/components/profile/EditProfile.js @@ -157,12 +157,12 @@ const EditProfile = ({ screenProps, theme, styles }) => { // Validate after saving profile state in order to show errors useEffect(() => { //need to pass parameters into memoized debounced method otherwise setX hooks wont work - validate(profile, storedProfile, identity, storedIdentity, setIsPristine, setErrors, setIsValid) + validate(profile, storedProfile, setIsPristine, setErrors, setIsValid) }, [profile]) useEffect(() => { //need to pass parameters into memoized debounced method otherwise setX hooks wont work - validate(profile, storedProfile, identity, storedIdentity, setIsPristine, setErrors, setIsValid) + validate(profile, storedProfile, setIsPristine, setErrors, setIsValid) }, [identity]) return ( diff --git a/src/components/profile/Profile.js b/src/components/profile/Profile.js index be392e6966..d2fd2b2e09 100644 --- a/src/components/profile/Profile.js +++ b/src/components/profile/Profile.js @@ -4,7 +4,6 @@ import GDStore from '../../lib/undux/GDStore' import { createStackNavigator } from '../appNavigation/stackNavigation' import { Section, UserAvatar, Wrapper } from '../common' import { withStyles } from '../../lib/styles' -import userStorage from '../../lib/gundb/UserStorage' import IdentityDataTable from '../identity/IdentityDataTable' import AddIdentityMenu from '../identity/AddIdentityMenu' import UploadPhoto from '../identity/UploadPhoto' From ca50e8ea6ae736403a420ac8b0060191fdc8c69e Mon Sep 17 00:00:00 2001 From: xiphiness Date: Fri, 13 Sep 2019 16:37:50 -0400 Subject: [PATCH 16/22] add identity --- src/components/identity/AddIdentity.js | 61 +++++++++++++++++--------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/src/components/identity/AddIdentity.js b/src/components/identity/AddIdentity.js index 3f4abb3860..26920d8d3e 100644 --- a/src/components/identity/AddIdentity.js +++ b/src/components/identity/AddIdentity.js @@ -1,7 +1,9 @@ // @flow import React from 'react' -import GDStore from '../../lib/undux/GDStore' -import { SaveButton, Section, Wrapper } from '../common' +import { Clipboard, TouchableOpacity } from 'react-native' + +//import GDStore from '../../lib/undux/GDStore' +import { SaveButton, Section, Text, Wrapper } from '../common' import InputRounded from '../common/form/InputRounded' import { useScreenState } from '../appNavigation/stackNavigation' import { withStyles } from '../../lib/styles' @@ -60,41 +62,60 @@ const AddIdentity = ({ screenProps, theme, styles }) => { // [] // ) - const store = GDStore.useStore() - const identity = store.get('identity') + //const store = GDStore.useStore() + + //const identity = store.get('identity') const [screenState] = useScreenState(screenProps) const { name } = screenState + const verifyText = 'I am verifying my GoodDollar identity.' - const handleIdentityChange = newUsername => { - identity[name] = { username: newUsername } - } + // const handleIdentityChange = newUsername => { + // identity[name] = { username: newUsername } + // } - const handleSaveButton = () => { - store.set('identity')(identity) - return identity[name].username - } + // const handleSaveButton = () => { + // store.set('identity')(identity) + // return identity[name].username + // } - const onIdentitySaved = () => { - screenProps.pop() - return identity[name].username - } + // const onIdentitySaved = () => { + // screenProps.pop() + // return identity[name].username + // } return (
+ + Please make a {name} post with the following: + + + { + await Clipboard.setString(verifyText) + }} + > + + + undefined} + placeholder="Copy link to post here" /> - + screenProps.pop()} />
From c34f14949cbdb8537b2cb03d41eb67f0c542ad0d Mon Sep 17 00:00:00 2001 From: zakhap Date: Wed, 18 Sep 2019 22:19:20 -0400 Subject: [PATCH 17/22] Working through the GenericSocial Component as well as the ShareButton Component. These efforts are to minimize rewriting component structures in the syntax and style defined in the GoodDollar GitBook. More complete and better functioning components yet to come. --- src/components/identity/AddIdentityMenu.js | 2 +- src/components/identity/GenericSocial.js | 86 ++++++++++++++++++++++ src/components/identity/ShareButton.js | 31 ++++++++ src/components/profile/Profile.js | 2 + 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 src/components/identity/GenericSocial.js create mode 100644 src/components/identity/ShareButton.js diff --git a/src/components/identity/AddIdentityMenu.js b/src/components/identity/AddIdentityMenu.js index 81635ce447..78e4604761 100644 --- a/src/components/identity/AddIdentityMenu.js +++ b/src/components/identity/AddIdentityMenu.js @@ -38,7 +38,7 @@ const AddIdentityMenu = ({ screenProps, theme, styles }) => { const identityPhotos = store.get('identityPhotos') const onAddIdentityPress = name => { - screenProps.push('AddIdentity', { name, theme, styles }) + screenProps.push('GenericSocial', { name, theme, styles }) } const renderItem = ({ item }) => { diff --git a/src/components/identity/GenericSocial.js b/src/components/identity/GenericSocial.js new file mode 100644 index 0000000000..93263e0d9c --- /dev/null +++ b/src/components/identity/GenericSocial.js @@ -0,0 +1,86 @@ +// @flow +import React from 'react' +import { Clipboard, TouchableOpacity } from 'react-native' + +//import GDStore from '../../lib/undux/GDStore' +import { SaveButton, Section, Text, Wrapper } from '../common' +import InputRounded from '../common/form/InputRounded' + +// import InputText from '../common/form/InputText' +import { useScreenState } from '../appNavigation/stackNavigation' +import { withStyles } from '../../lib/styles' + +import ShareButton from './ShareButton' +GenericSocial + +const TITLE = 'Add Identity' + +const GenericSocial = ({ screenProps, theme, styles }) => { + const [screenState] = useScreenState(screenProps) + + const { name } = screenState + const verifyText = 'I am verifying my GoodDollar identity. 0xAb1235019238' + + return ( + +
+ + Please make a {name} post with the following (tap to copy to clipboard): + + + { + await Clipboard.setString(verifyText) + }} + > + + + + + + + + + + undefined} + placeholder="Copy link to post here" + /> + + + screenProps.pop()} /> + +
+
+ ) +} + +GenericSocial.navigationOptions = { + title: TITLE, +} + +const getStylesFromProps = ({ theme }) => ({ + section: {}, + + row: { + marginBottom: 15, + }, + + iconRight: {}, + + button: { + alignSelf: 'center', + }, +}) + +export default withStyles(getStylesFromProps)(GenericSocial) diff --git a/src/components/identity/ShareButton.js b/src/components/identity/ShareButton.js new file mode 100644 index 0000000000..9d0fbf4d0d --- /dev/null +++ b/src/components/identity/ShareButton.js @@ -0,0 +1,31 @@ +import React, { Component } from 'react' +import { Button, Share } from 'react-native' + +class ShareButton extends Component { + onShare = async () => { + try { + const result = await Share.share({ + message: 'THIS IS WHERE WE CAN PRELOAD THE COPYPASTA', + }) + + if (result.action === Share.sharedAction) { + if (result.activityType) { + // shared with activity type of result.activityType + } else { + // shared + // NOTHING + } + } else if (result.action === Share.dismissedAction) { + // dismissed + } + } catch (error) { + alert(error.message) + } + } + + render() { + return