diff --git a/locale/da/texts.po b/locale/da/texts.po index d5cb9eac0..c42056faa 100644 --- a/locale/da/texts.po +++ b/locale/da/texts.po @@ -61,7 +61,7 @@ msgstr "[Sidste] dddd [•] HH:mm" msgid "DD MMM YYYY [•] HH:mm" msgstr "DD MMM YYYY [•] HH:mm" -#: src/utils.js:159 +#: src/utils.js:160 msgid "Invalid address" msgstr "Ugyldig adresse" diff --git a/locale/pt-br/texts.po b/locale/pt-br/texts.po index dae12e7e5..c502c4226 100644 --- a/locale/pt-br/texts.po +++ b/locale/pt-br/texts.po @@ -61,7 +61,7 @@ msgstr "[Última] dddd [•] HH:mm" msgid "DD MMM YYYY [•] HH:mm" msgstr "DD MMM YYYY [•] HH:mm" -#: src/utils.js:159 +#: src/utils.js:160 msgid "Invalid address" msgstr "Endereço inválido" diff --git a/locale/ru-ru/texts.po b/locale/ru-ru/texts.po index d06c178fe..ae00bf6ee 100644 --- a/locale/ru-ru/texts.po +++ b/locale/ru-ru/texts.po @@ -62,7 +62,7 @@ msgstr "[Последний] dddd [•] HH:mm" msgid "DD MMM YYYY [•] HH:mm" msgstr "DD MMM YYYY [•] HH:mm" -#: src/utils.js:159 +#: src/utils.js:160 msgid "Invalid address" msgstr "Неправильный адрес" diff --git a/locale/texts.pot b/locale/texts.pot index ffc40232d..2cb15ab4b 100644 --- a/locale/texts.pot +++ b/locale/texts.pot @@ -52,7 +52,7 @@ msgstr "" msgid "DD MMM YYYY [•] HH:mm" msgstr "" -#: src/utils.js:159 +#: src/utils.js:160 msgid "Invalid address" msgstr "" diff --git a/src/components/EditInfoContainer.js b/src/components/EditInfoContainer.js new file mode 100644 index 000000000..202e49ccc --- /dev/null +++ b/src/components/EditInfoContainer.js @@ -0,0 +1,72 @@ +/** + * Copyright (c) Hathor Labs and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import { + StyleSheet, + View, + TouchableOpacity +} from 'react-native'; +import { COLORS } from '../styles/themes'; + +import { PenIcon } from './Icons/Pen.icon'; + +export const EditInfoContainer = ({ center, onPress, children }) => ( + + + + {children} + + + + + + +); + +const styles = StyleSheet.create({ + editInfoWrapperCentered: { + alignSelf: 'center', + }, + editInfoContainer: { + paddingVertical: 8, + paddingLeft: 8, + paddingRight: 40, + borderRadius: 8, + backgroundColor: COLORS.white, + }, + editInfoContainerCentered: { + paddingLeft: 40, + }, + alignCenter: { + alignItems: 'center', + }, + editIcon: { + position: 'absolute', + display: 'flex', + justifyContent: 'center', + top: 0, + right: 0, + bottom: 0, + width: 24, + height: '100%', + marginVertical: 8, + marginRight: 8, + }, +}); diff --git a/src/components/HathorHeader.js b/src/components/HathorHeader.js index 493a9e404..f6a174b2a 100644 --- a/src/components/HathorHeader.js +++ b/src/components/HathorHeader.js @@ -30,6 +30,9 @@ const HathorHeader = ({ const left = React.Children.toArray(children).find( (child) => child.type.displayName === HathorHeaderLeft.displayName ); + const central = React.Children.toArray(children).find( + (child) => child.type.displayName === HathorHeaderCentral.displayName + ); const right = React.Children.toArray(children).find( (child) => child.type.displayName === HathorHeaderRight.displayName ); @@ -40,6 +43,7 @@ const HathorHeader = ({ && ( {left} + {central} {right} )} @@ -70,10 +74,14 @@ const InnerWrapper = ({ children }) => ( const HathorHeaderLeft = ({ children }) => ({children}); HathorHeaderLeft.displayName = 'HathorHeaderLeft'; +const HathorHeaderCentral = ({ style, children }) => {children}; +HathorHeaderCentral.displayName = 'HathorHeaderCentral'; + const HathorHeaderRight = ({ children }) => {children}; HathorHeaderRight.displayName = 'HathorHeaderRight'; HathorHeader.Left = HathorHeaderLeft; +HathorHeader.Central = HathorHeaderCentral; HathorHeader.Right = HathorHeaderRight; const CancelButton = ({ onCancel }) => ( @@ -118,7 +126,7 @@ const RightComponent = ({ rightElement, onCancel }) => { const styles = StyleSheet.create({ wrapper: { - height: STYLE.headerHeight, + minHeight: STYLE.headerHeight, flexDirection: 'row', alignItems: 'flex-end', borderColor: COLORS.borderColor, diff --git a/src/components/ModalBase.js b/src/components/ModalBase.js new file mode 100644 index 000000000..2b24b7acf --- /dev/null +++ b/src/components/ModalBase.js @@ -0,0 +1,116 @@ +/** + * Copyright (c) Hathor Labs and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import { + StyleSheet, + View, + Text, +} from 'react-native'; +import Modal from 'react-native-modal'; + +import { COLORS } from '../styles/themes'; +import NewHathorButton from './NewHathorButton'; + +const ModalBase = ({ styleModal, styleWrapper, show, onDismiss, children }) => { + const hasChildren = children != null; + + const title = hasChildren && React.Children.toArray(children).find( + (child) => child.type.displayName === Title.displayName + ); + const body = hasChildren && React.Children.toArray(children).find( + (child) => child.type.displayName === Body.displayName + ); + const button = hasChildren && React.Children.toArray(children).find( + (child) => child.type.displayName === Button.displayName + ); + const discreteButton = hasChildren && React.Children.toArray(children).find( + (child) => child.type.displayName === DiscreteButton.displayName + ); + + return ( + + + {title && title} + {body && body} + {button && button} + {discreteButton && discreteButton} + + + ); +}; + +const Title = ({ children }) => ( + + + {children} + + +); +Title.displayName = 'ModalBaseTitle'; + +/** + * @param {Object} props + * @property {ReactNode} props.children + * @property {StyleProp} props.style + */ +const Body = ({ style, children }) => ( + + {children} + +); +Body.displayName = 'ModalBaseBody'; + +const Button = ({ title, disabled, secondary, danger, onPress }) => ( + +); +Button.displayName = 'ModalBaseButton'; + +const DiscreteButton = ({ title, onPress }) => ( + +); +DiscreteButton.displayName = 'ModalBaseDiscreteButton'; + +ModalBase.Title = Title; +ModalBase.Body = Body; +ModalBase.Button = Button; +ModalBase.DiscreteButton = DiscreteButton; + +const styles = StyleSheet.create({ + wrapper: { + borderRadius: 8, + paddingVertical: 24, + paddingHorizontal: 16, + backgroundColor: COLORS.white, + }, + titleWrapper: { + paddingBottom: 20, + }, + title: { + color: 'black', + fontSize: 18, + lineHeight: 20, + }, + discreteButton: { + marginTop: 8, + }, +}); + +export { ModalBase } diff --git a/src/components/NewHathorButton.js b/src/components/NewHathorButton.js index a1603e949..1afe5e5d1 100644 --- a/src/components/NewHathorButton.js +++ b/src/components/NewHathorButton.js @@ -21,6 +21,11 @@ const NewHathorButton = (props) => { textStyle.push(style.textDisabled); } + if (props.discrete) { + wrapperViewStyle.push(style.wrapperDiscrete); + textStyle.push(style.textDiscrete); + } + if (props.secondary) { wrapperViewStyle.push(style.wrapperSecondary); textStyle.push(style.textSecondary); @@ -34,6 +39,11 @@ const NewHathorButton = (props) => { } } + if (props.danger) { + wrapperViewStyle.push(style.wrapperSecondaryDanger); + textStyle.push(style.textSecondaryDanger); + } + return ( @@ -79,6 +89,14 @@ const style = StyleSheet.create({ wrapperSecondaryDisabled: { borderColor: COLORS.textColorShadow, }, + wrapperDiscrete: { + backgroundColor: COLORS.backgroundColor, + borderColor: COLORS.backgroundColor, + borderWidth: 1.5, + }, + wrapperSecondaryDanger: { + borderColor: COLORS.errorBgColor, + }, touchable: { flex: 1, flexDirection: 'row', @@ -101,6 +119,12 @@ const style = StyleSheet.create({ textDisabled: { color: COLORS.textColorShadow, }, + textDiscrete: { + color: COLORS.freeze300, + }, + textSecondaryDanger: { + color: COLORS.errorBgColor, + }, }); export default NewHathorButton; diff --git a/src/components/TextLabel.js b/src/components/TextLabel.js new file mode 100644 index 000000000..702e17d2d --- /dev/null +++ b/src/components/TextLabel.js @@ -0,0 +1,35 @@ +/** + * Copyright (c) Hathor Labs and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import { + StyleSheet, + Text, +} from 'react-native'; + +export const TextLabel = ({ pb8, bold, children }) => ( + {children} +); + +const styles = StyleSheet.create({ + textLabel: { + fontSize: 12, + lineHeight: 20, + color: 'hsla(0, 0%, 38%, 1)', + }, + pb8: { + paddingBottom: 8, + }, + bold: { + fontWeight: 'bold', + }, +}); diff --git a/src/components/TextValue.js b/src/components/TextValue.js new file mode 100644 index 000000000..952616385 --- /dev/null +++ b/src/components/TextValue.js @@ -0,0 +1,35 @@ +/** + * Copyright (c) Hathor Labs and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import { + StyleSheet, + Text, +} from 'react-native'; + +export const TextValue = ({ bold, pb4, children }) => ( + {children} +); + +const styles = StyleSheet.create({ + textValue: { + fontSize: 14, + lineHeight: 20, + color: 'black', + }, + pb4: { + paddingBottom: 4, + }, + bold: { + fontWeight: 'bold', + }, +}); diff --git a/src/utils.js b/src/utils.js index e950f1354..281c5d790 100644 --- a/src/utils.js +++ b/src/utils.js @@ -11,6 +11,7 @@ import React from 'react'; import { t } from 'ttag'; import { Linking, Platform, Text } from 'react-native'; import { getStatusBarHeight } from 'react-native-status-bar-height'; +import moment from 'moment'; import baseStyle from './styles/init'; import { KEYCHAIN_USER, NANO_CONTRACT_FEATURE_TOGGLE } from './constants'; import { STORE } from './store'; @@ -403,3 +404,12 @@ export const isPushNotificationAvailableForUser = (state) => ( export const getNanoContractFeatureToggle = (state) => ( state.featureToggles[NANO_CONTRACT_FEATURE_TOGGLE] ); + +/** + * Get timestamp in specific format. + * + * @param {number} timestamp + * + * @returns {string} formatted timestamp + */ +export const getTimestampFormat = (timestamp) => moment.unix(timestamp).format(t`DD MMM YYYY [•] HH:mm`)