diff --git a/.eslintrc.js b/.eslintrc.js index 3abaf112e37..68200c09a3c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -119,7 +119,7 @@ module.exports = { 'eslint-comments/no-unused-disable': 0, 'react-native/no-color-literals': 2, 'react-native/no-inline-styles': 2, - 'react-native/no-unused-styles': 2, + 'react-native/no-unused-styles': 0, 'react-native/split-platform-components': 2, 'react/jsx-boolean-value': 2, 'react/jsx-key': 1, diff --git a/android/app/build.gradle b/android/app/build.gradle index 7f376ee1742..ad7c9defdbb 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -160,8 +160,8 @@ android { applicationId "io.metamask" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 834 - versionName "4.2.2" + versionCode 846 + versionName "4.3.3" multiDexEnabled true testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy "minReactNative", "minReactNative46" diff --git a/android/app/src/main/res/drawable-night/diamond.png b/android/app/src/main/res/drawable-night/diamond.png new file mode 100644 index 00000000000..af56996f55d Binary files /dev/null and b/android/app/src/main/res/drawable-night/diamond.png differ diff --git a/android/app/src/main/res/drawable/background_splash.xml b/android/app/src/main/res/drawable/background_splash.xml index bad31bfda6a..4306930e9c3 100644 --- a/android/app/src/main/res/drawable/background_splash.xml +++ b/android/app/src/main/res/drawable/background_splash.xml @@ -2,7 +2,7 @@ + android:drawable="@color/theme"/> + android:layout_height="match_parent" android:background="@color/theme"> diff --git a/android/app/src/main/res/values-night/booleans.xml b/android/app/src/main/res/values-night/booleans.xml new file mode 100644 index 00000000000..0c4442defd9 --- /dev/null +++ b/android/app/src/main/res/values-night/booleans.xml @@ -0,0 +1,4 @@ + + + false + diff --git a/android/app/src/main/res/values-night/colors.xml b/android/app/src/main/res/values-night/colors.xml new file mode 100644 index 00000000000..4483fb4874b --- /dev/null +++ b/android/app/src/main/res/values-night/colors.xml @@ -0,0 +1,7 @@ + + + #151719 + #FFFFFF + #000000 + #EBEBED + diff --git a/android/app/src/main/res/values/booleans.xml b/android/app/src/main/res/values/booleans.xml new file mode 100644 index 00000000000..7b6c18b8c44 --- /dev/null +++ b/android/app/src/main/res/values/booleans.xml @@ -0,0 +1,4 @@ + + + true + diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index 9c78943dbfe..0dc4d5454dc 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -1,5 +1,7 @@ - #FFFFFF + #FFFFFF + #000000 + #000000 #EBEBED diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index 475bc2e0cf6..28a1d507e55 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -1,22 +1,21 @@ - - diff --git a/app/__mocks__/react-native-view-shot.js b/app/__mocks__/react-native-view-shot.js new file mode 100644 index 00000000000..0ae90852a55 --- /dev/null +++ b/app/__mocks__/react-native-view-shot.js @@ -0,0 +1,6 @@ +export default { + captureScreen: jest.fn().mockImplementation(() => { + // eslint-disable-next-line no-console + console.log('capture screen'); + }), +}; diff --git a/app/actions/user/index.js b/app/actions/user/index.js index a42ecebac20..084720d0100 100644 --- a/app/actions/user/index.js +++ b/app/actions/user/index.js @@ -83,6 +83,13 @@ export function logOut() { }; } +export function setAppTheme(theme) { + return { + type: 'SET_APP_THEME', + payload: { theme }, + }; +} + /** * Temporary action to control auth flow * diff --git a/app/animations/wordmark-dark.json b/app/animations/wordmark-dark.json new file mode 100644 index 00000000000..3cac9c0869c --- /dev/null +++ b/app/animations/wordmark-dark.json @@ -0,0 +1,1302 @@ +{ + "v": "5.5.1", + "fr": 30, + "ip": 0, + "op": 50, + "w": 1125, + "h": 160, + "nm": "wordmark 2", + "ddd": 0, + "assets": [], + "layers": [ + { + "ddd": 0, + "ind": 1, + "ty": 4, + "nm": "Metamask", + "sr": 1, + "ks": { + "o": { "a": 0, "k": 100, "ix": 11 }, + "r": { "a": 0, "k": 0, "ix": 10 }, + "p": { + "a": 1, + "k": [ + { + "i": { "x": 0, "y": 1 }, + "o": { "x": 0, "y": 0 }, + "t": 11, + "s": [562.5, 251.444, 0], + "e": [562.5, 79.444, 0], + "to": [0, -28.667, 0], + "ti": [0, 28.667, 0] + }, + { "t": 31 } + ], + "ix": 2 + }, + "a": { "a": 0, "k": [574.5, 1301.444, 0], "ix": 1 }, + "s": { "a": 0, "k": [100, 100, 100], "ix": 6 } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [0.652, 0.652], + [0, 0], + [-0.326, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.326], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.326], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [-0.326, -0.652], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [-0.326, -0.326], + [0, 0], + [0.326, -0.326], + [0, 0], + [-0.326, 0], + [0, 0], + [-0.326, 0.326], + [0, 0], + [0, -0.326], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.652], + [0, 0], + [0, 0], + [0, 0], + [0.652, 0] + ], + "v": [ + [521.144, 145.744], + [459.171, 81.487], + [459.171, 80.509], + [514.947, 22.776], + [514.621, 21.797], + [491.789, 21.797], + [491.462, 22.123], + [444.167, 71.376], + [443.189, 71.05], + [443.189, 22.45], + [442.536, 21.797], + [424.597, 21.797], + [423.944, 22.45], + [423.944, 146.396], + [424.597, 147.048], + [442.536, 147.048], + [443.189, 146.396], + [443.189, 91.599], + [444.167, 91.272], + [497.66, 146.722], + [497.986, 147.048], + [520.818, 147.048] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, + "o": { "a": 0, "k": 100, "ix": 5 }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [0, 0], "ix": 2 }, + "a": { "a": 0, "k": [0, 0], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [1035.222, 1302.423], "ix": 2 }, + "a": { "a": 0, "k": [472.722, 84.423], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Layer 8", + "np": 1, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [0, 0.326], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, 0], + [0, -0.326], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, -0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.326], + [0, 0], + [-0.326, 0], + [0, 0], + [0, -0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.326], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.326], + [0, 0], + [-0.326, 0.326] + ], + "v": [ + [-337.022, 128.783], + [-337.022, 90.294], + [-336.37, 89.642], + [-288.748, 89.642], + [-288.096, 88.989], + [-288.096, 73.659], + [-288.748, 73.007], + [-336.37, 73.007], + [-337.022, 72.354], + [-337.022, 39.084], + [-336.37, 38.432], + [-282.225, 38.432], + [-281.572, 37.78], + [-281.572, 22.45], + [-282.225, 21.797], + [-337.022, 21.797], + [-355.614, 21.797], + [-356.266, 22.45], + [-356.266, 38.432], + [-356.266, 72.68], + [-356.266, 89.315], + [-356.266, 129.109], + [-356.266, 146.07], + [-355.614, 146.722], + [-337.022, 146.722], + [-279.615, 146.722], + [-278.963, 146.07], + [-278.963, 129.761], + [-279.615, 129.109], + [-336.37, 129.109] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, + "o": { "a": 0, "k": 100, "ix": 5 }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [0, 0], "ix": 2 }, + "a": { "a": 0, "k": [0, 0], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [244.885, 1302.26], "ix": 2 }, + "a": { "a": 0, "k": [-317.615, 84.26], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Layer 7", + "np": 1, + "cix": 2, + "bm": 0, + "ix": 2, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [0, 0.326], + [0, 0], + [-0.326, -0.652], + [0, 0], + [0.326, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0.326, -0.652], + [0, 0], + [0, 0.326], + [0, 0], + [-0.326, -0.326] + ], + "v": [ + [192.686, 92.251], + [205.733, 43.977], + [207.038, 43.977], + [220.085, 92.251], + [219.433, 93.23], + [193.339, 93.23] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ind": 1, + "ty": "sh", + "ix": 2, + "ks": { + "a": 0, + "k": { + "i": [ + [-0.326, 0], + [0, 0], + [0, 0.652], + [0, 0], + [0.326, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.326], + [0, 0], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, 0] + ], + "v": [ + [235.741, 147.048], + [252.05, 147.048], + [252.702, 146.07], + [218.78, 21.797], + [218.128, 21.471], + [211.931, 21.471], + [200.841, 21.471], + [194.643, 21.471], + [193.991, 21.797], + [160.395, 146.07], + [161.047, 147.048], + [177.356, 147.048], + [178.008, 146.722], + [187.794, 110.517], + [188.446, 110.191], + [224.651, 110.191], + [225.304, 110.517], + [235.089, 146.722] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 2", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, + "o": { "a": 0, "k": 100, "ix": 5 }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [0, 0], "ix": 2 }, + "a": { "a": 0, "k": [0, 0], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [769.049, 1302.26], "ix": 2 }, + "a": { "a": 0, "k": [206.549, 84.26], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Layer 6", + "np": 1, + "cix": 2, + "bm": 0, + "ix": 3, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [0, 0.326], + [0, 0], + [-0.326, -0.652], + [0, 0], + [0.326, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0.326, -0.652], + [0, 0], + [0, 0.326], + [0, 0], + [-0.326, -0.326] + ], + "v": [ + [-85.541, 92.251], + [-72.494, 43.977], + [-71.189, 43.977], + [-58.142, 92.251], + [-58.795, 93.23], + [-84.889, 93.23] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ind": 1, + "ty": "sh", + "ix": 2, + "ks": { + "a": 0, + "k": { + "i": [ + [-0.326, 0], + [0, 0], + [0, 0.652], + [0, 0], + [0.326, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.326], + [0, 0], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.326], + [0, 0], + [0.326, 0], + [0, 0], + [-0.326, 0] + ], + "v": [ + [-42.486, 147.048], + [-26.177, 147.048], + [-25.525, 146.07], + [-59.447, 21.797], + [-60.099, 21.471], + [-66.297, 21.471], + [-77.387, 21.471], + [-83.258, 21.471], + [-83.91, 21.797], + [-117.506, 146.07], + [-116.854, 147.048], + [-100.545, 147.048], + [-99.893, 146.722], + [-90.107, 110.517], + [-89.455, 110.191], + [-53.25, 110.191], + [-52.597, 110.517], + [-42.812, 146.722] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 2", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, + "o": { "a": 0, "k": 100, "ix": 5 }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [0, 0], "ix": 2 }, + "a": { "a": 0, "k": [0, 0], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [490.984, 1302.26], "ix": 2 }, + "a": { "a": 0, "k": [-71.515, 84.26], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Layer 5", + "np": 1, + "cix": 2, + "bm": 0, + "ix": 4, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [0.326, 0], + [0, 0], + [0, 0], + [0, 0], + [0, -0.326], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0, 0], + [0, 0.326], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, 0], + [0.326, 0], + [0, 0], + [0.326, -0.326] + ], + "v": [ + [-148.167, 21.797], + [-181.763, 21.797], + [-199.702, 21.797], + [-232.972, 21.797], + [-233.624, 22.45], + [-233.624, 37.78], + [-232.972, 38.432], + [-200.355, 38.432], + [-200.355, 146.07], + [-199.702, 146.722], + [-181.763, 146.722], + [-181.11, 146.07], + [-181.11, 38.432], + [-148.493, 38.432], + [-147.84, 37.78], + [-147.84, 22.45] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, + "o": { "a": 0, "k": 100, "ix": 5 }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [0, 0], "ix": 2 }, + "a": { "a": 0, "k": [0, 0], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [371.835, 1302.26], "ix": 2 }, + "a": { "a": 0, "k": [-190.665, 84.26], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Layer 4", + "np": 1, + "cix": 2, + "bm": 0, + "ix": 5, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0.326, 0.652], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.326], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [-0.326, -0.652], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, -0.979], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0] + ], + "o": [ + [-0.326, 0], + [0, 0], + [-0.326, 0.652], + [0, 0], + [0, -0.326], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.652], + [0, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, 0], + [0.326, -0.652], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.326], + [0, 0] + ], + "v": [ + [82.765, 21.797], + [82.113, 22.123], + [67.435, 70.723], + [66.13, 70.723], + [51.452, 22.123], + [50.8, 21.797], + [23.401, 21.797], + [22.749, 22.45], + [22.749, 146.396], + [23.401, 147.048], + [41.341, 147.048], + [41.993, 146.396], + [41.993, 52.131], + [43.298, 51.805], + [58.302, 100.732], + [59.281, 103.993], + [59.933, 104.319], + [73.632, 104.319], + [74.285, 103.993], + [75.263, 100.732], + [90.267, 51.805], + [91.572, 52.131], + [91.572, 146.396], + [92.224, 147.048], + [110.164, 147.048], + [110.816, 146.396], + [110.816, 22.45], + [110.164, 21.797] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, + "o": { "a": 0, "k": 100, "ix": 5 }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [0, 0], "ix": 2 }, + "a": { "a": 0, "k": [0, 0], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [629.283, 1302.423], "ix": 2 }, + "a": { "a": 0, "k": [66.783, 84.423], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Layer 3", + "np": 1, + "cix": 2, + "bm": 0, + "ix": 6, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0.326, 0.652], + [0, 0], + [0.326, 0], + [0, 0], + [0, 0], + [0, 0], + [0, -0.326], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [-0.326, -0.652], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, -0.652], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0] + ], + "o": [ + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [-0.326, 0.652], + [0, 0], + [0, -0.326], + [0, 0], + [0, 0], + [0, 0], + [-0.326, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.652], + [0, 0], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, 0], + [0, -0.652], + [0, 0], + [0, 0.326], + [0, 0], + [0.326, 0], + [0, 0], + [0, -0.326], + [0, 0] + ], + "v": [ + [-420.849, 21.797], + [-429.003, 21.797], + [-437.81, 21.797], + [-438.462, 22.123], + [-453.14, 70.723], + [-454.445, 70.723], + [-468.797, 22.123], + [-469.449, 21.797], + [-478.256, 21.797], + [-486.084, 21.797], + [-496.848, 21.797], + [-497.5, 22.45], + [-497.5, 146.396], + [-496.848, 147.048], + [-478.908, 147.048], + [-478.256, 146.396], + [-478.256, 52.131], + [-476.951, 51.805], + [-461.947, 100.732], + [-460.968, 103.993], + [-460.316, 104.319], + [-446.617, 104.319], + [-445.964, 103.993], + [-444.986, 100.732], + [-429.982, 51.805], + [-429.003, 52.131], + [-429.003, 146.396], + [-428.351, 147.048], + [-410.411, 147.048], + [-409.759, 146.396], + [-409.759, 22.45], + [-410.411, 21.797] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, + "o": { "a": 0, "k": 100, "ix": 5 }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [0, 0], "ix": 2 }, + "a": { "a": 0, "k": [0, 0], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [108.871, 1302.423], "ix": 2 }, + "a": { "a": 0, "k": [-453.629, 84.423], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Layer 2", + "np": 1, + "cix": 2, + "bm": 0, + "ix": 7, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [12.721, 8.154], + [7.828, 4.24], + [4.24, 3.588], + [-7.828, 5.219], + [-1.957, -15.004], + [-0.326, 0], + [0, 0], + [0, 0.326], + [7.176, 5.545], + [8.481, 0], + [-23.485, -14.678], + [-8.154, -4.893], + [3.588, -7.176], + [8.154, 0.326], + [2.283, 7.828], + [0, 1.305], + [0.326, 0], + [0, 0], + [0, -0.326], + [-8.807, -6.523], + [-9.459, 0], + [-2.609, 14.352] + ], + "o": [ + [-7.176, -4.893], + [-4.893, -2.609], + [-7.176, -5.871], + [11.09, -7.176], + [0, 0.326], + [0, 0], + [0.326, 0], + [-0.978, -10.438], + [-6.85, -5.219], + [-43.707, 0], + [2.609, 1.631], + [8.154, 5.219], + [-3.262, 6.85], + [-9.133, -0.326], + [-0.326, -1.305], + [0, -0.326], + [0, 0], + [-0.326, 0], + [0, 13.047], + [8.154, 6.197], + [24.463, 0], + [1.957, -13.699] + ], + "v": [ + [357.405, 84.749], + [334.246, 72.028], + [319.895, 63.221], + [321.852, 40.063], + [352.838, 51.805], + [353.491, 52.458], + [370.126, 52.458], + [370.778, 51.805], + [358.709, 27.342], + [335.225, 19.188], + [311.088, 80.183], + [345.01, 98.448], + [352.186, 119.976], + [332.289, 130.74], + [313.697, 117.366], + [313.045, 112.148], + [312.393, 111.495], + [294.453, 111.495], + [293.801, 112.148], + [305.869, 138.894], + [332.615, 147.701], + [372.409, 119.324] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { "a": 0, "k": [1, 1, 1, 1], "ix": 4 }, + "o": { "a": 0, "k": 100, "ix": 5 }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [0, 0], "ix": 2 }, + "a": { "a": 0, "k": [0, 0], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [895.832, 1301.444], "ix": 2 }, + "a": { "a": 0, "k": [333.332, 83.444], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Layer 1", + "np": 1, + "cix": 2, + "bm": 0, + "ix": 8, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 90, + "st": 0, + "bm": 0 + } + ], + "markers": [{ "tm": 95, "cm": "1", "dr": 0 }] +} diff --git a/app/animations/wordmark.json b/app/animations/wordmark-light.json similarity index 98% rename from app/animations/wordmark.json rename to app/animations/wordmark-light.json index 0991b8d914b..045f4d575b5 100644 --- a/app/animations/wordmark.json +++ b/app/animations/wordmark-light.json @@ -362,7 +362,14 @@ "ks": { "a": 0, "k": { - "i": [[0, 0.326], [0, 0], [-0.326, -0.652], [0, 0], [0.326, 0], [0, 0]], + "i": [ + [0, 0.326], + [0, 0], + [-0.326, -0.652], + [0, 0], + [0.326, 0], + [0, 0] + ], "o": [ [0, 0], [0.326, -0.652], @@ -525,7 +532,14 @@ "ks": { "a": 0, "k": { - "i": [[0, 0.326], [0, 0], [-0.326, -0.652], [0, 0], [0.326, 0], [0, 0]], + "i": [ + [0, 0.326], + [0, 0], + [-0.326, -0.652], + [0, 0], + [0.326, 0], + [0, 0] + ], "o": [ [0, 0], [0.326, -0.652], diff --git a/app/components/Base/Alert.stories.tsx b/app/components/Base/Alert.stories.tsx index 5abfe49f48f..de7a612ee86 100644 --- a/app/components/Base/Alert.stories.tsx +++ b/app/components/Base/Alert.stories.tsx @@ -6,14 +6,13 @@ import { text, boolean, select } from '@storybook/addon-knobs'; import Alert, { AlertType } from './Alert'; import Text from './Text'; -import { colors, fontStyles } from ' ../../../styles/common'; +import { fontStyles } from ' ../../../styles/common'; import EvilIcons from 'react-native-vector-icons/EvilIcons'; const styles = { alertIcon: { fontSize: 20, ...fontStyles.bold, - color: colors.yellow, marginRight: 6, }, }; diff --git a/app/components/Base/Alert.tsx b/app/components/Base/Alert.tsx index 943dd69ea1f..377856f3ab0 100644 --- a/app/components/Base/Alert.tsx +++ b/app/components/Base/Alert.tsx @@ -10,8 +10,8 @@ import { TextStyle, } from 'react-native'; import IonicIcon from 'react-native-vector-icons/Ionicons'; -import { colors } from '../../styles/common'; import CustomText from './Text'; +import { useAppThemeFromContext, mockTheme } from '../../util/theme'; // TODO: Convert into typescript and correctly type optionals const Text = CustomText as any; @@ -32,43 +32,47 @@ interface Props { children?: ReactNode; } -const styles = StyleSheet.create({ - base: { - paddingHorizontal: 12, - paddingVertical: 8, - borderWidth: 1, - borderRadius: 8, - flexDirection: 'row', - }, - baseSmall: { - paddingVertical: 8, - }, - info: { - backgroundColor: colors.blue100, - borderColor: colors.blue, - }, - warning: { - backgroundColor: colors.yellow100, - borderColor: colors.yellowWarningBorder, - }, - error: { - backgroundColor: colors.red000, - borderColor: colors.red, - }, - closeIcon: { - color: colors.black, - }, - baseTextStyle: { fontSize: 14, flex: 1, lineHeight: 17 }, - textInfo: { color: colors.blue }, - textWarning: { color: colors.black }, - textError: { color: colors.red }, - textIconStyle: { marginRight: 12 }, - iconWrapper: { - alignItems: 'center', - }, -}); +const createStyles = (colors: any) => + StyleSheet.create({ + base: { + paddingHorizontal: 12, + paddingVertical: 8, + borderWidth: 1, + borderRadius: 8, + flexDirection: 'row', + }, + baseSmall: { + paddingVertical: 8, + }, + info: { + backgroundColor: colors.primary.muted, + borderColor: colors.primary.default, + }, + warning: { + backgroundColor: colors.warning.muted, + borderColor: colors.warning.default, + }, + error: { + backgroundColor: colors.error.muted, + borderColor: colors.error.default, + }, + closeIcon: { + color: colors.text.default, + }, + baseTextStyle: { fontSize: 14, flex: 1, lineHeight: 17 }, + textInfo: { color: colors.text.default }, + textWarning: { color: colors.text.default }, + textError: { color: colors.text.default }, + textIconStyle: { marginRight: 12 }, + iconWrapper: { + alignItems: 'center', + }, + }); -const getAlertStyles: (alertType: AlertType) => [StyleProp, StyleProp] = (alertType) => { +const getAlertStyles: ( + alertType: AlertType, + styles: StyleSheet.NamedStyles +) => [StyleProp, StyleProp] = (alertType, styles) => { switch (alertType) { case AlertType.Warning: { return [styles.warning, { ...styles.textWarning, ...styles.baseTextStyle }]; @@ -85,8 +89,10 @@ const getAlertStyles: (alertType: AlertType) => [StyleProp, StyleProp const Alert = ({ type = AlertType.Info, small, renderIcon, style, onPress, onDismiss, children, ...props }: Props) => { const Wrapper: React.ComponentClass = onPress ? TouchableOpacity : View; + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); - const [wrapperStyle, textStyle] = getAlertStyles(type); + const [wrapperStyle, textStyle] = getAlertStyles(type, styles); return ( diff --git a/app/components/Base/DetailsModal.js b/app/components/Base/DetailsModal.js index 929dee118bf..3d04c727b58 100644 --- a/app/components/Base/DetailsModal.js +++ b/app/components/Base/DetailsModal.js @@ -2,82 +2,119 @@ import React from 'react'; import PropTypes from 'prop-types'; import { View, StyleSheet, TouchableOpacity } from 'react-native'; import Ionicons from 'react-native-vector-icons/Ionicons'; -import { colors, fontStyles } from '../../styles/common'; - +import { fontStyles } from '../../styles/common'; import Text from './Text'; +import { useAppThemeFromContext, mockTheme } from '../../util/theme'; + +const createStyles = (colors) => + StyleSheet.create({ + modalContainer: { + width: '100%', + backgroundColor: colors.background.default, + borderRadius: 10, + }, + modalView: { + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + }, + header: { + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + flexDirection: 'row', + paddingHorizontal: 16, + }, + title: { + flex: 1, + textAlign: 'center', + fontSize: 18, + marginVertical: 12, + marginHorizontal: 24, + color: colors.text.default, + ...fontStyles.bold, + }, + closeIcon: { paddingTop: 4, position: 'absolute', right: 16 }, + body: { + paddingHorizontal: 15, + }, + section: { + paddingVertical: 16, + flexDirection: 'row', + }, + sectionBorderBottom: { + borderBottomColor: colors.border.muted, + borderBottomWidth: 1, + }, + column: { + flex: 1, + }, + columnEnd: { + alignItems: 'flex-end', + }, + sectionTitle: { + ...fontStyles.normal, + fontSize: 10, + color: colors.text.alternative, + marginBottom: 8, + }, + }); +const DetailsModal = ({ children }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); -const styles = StyleSheet.create({ - modalContainer: { - width: '100%', - backgroundColor: colors.white, - borderRadius: 10, - }, - modalView: { - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - }, - header: { - borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - flexDirection: 'row', - paddingHorizontal: 16, - }, - title: { - flex: 1, - textAlign: 'center', - fontSize: 18, - marginVertical: 12, - marginHorizontal: 24, - color: colors.fontPrimary, - ...fontStyles.bold, - }, - closeIcon: { paddingTop: 4, position: 'absolute', right: 16 }, - body: { - paddingHorizontal: 15, - }, - section: { - paddingVertical: 16, - flexDirection: 'row', - }, - sectionBorderBottom: { - borderBottomColor: colors.grey100, - borderBottomWidth: 1, - }, - column: { - flex: 1, - }, - columnEnd: { - alignItems: 'flex-end', - }, - sectionTitle: { - ...fontStyles.normal, - fontSize: 10, - color: colors.grey500, - marginBottom: 8, - }, -}); -const DetailsModal = ({ children }) => ( - - {children} - -); + return ( + + {children} + + ); +}; -const DetailsModalHeader = ({ style, ...props }) => ; -const DetailsModalTitle = ({ style, ...props }) => ; -const DetailsModalCloseIcon = ({ style, ...props }) => ( - - - -); -const DetailsModalBody = ({ style, ...props }) => ; -const DetailsModalSection = ({ style, borderBottom, ...props }) => ( - -); -const DetailsModalSectionTitle = ({ style, ...props }) => ; -const DetailsModalColumn = ({ style, end, ...props }) => ( - -); +const DetailsModalHeader = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ; +}; +const DetailsModalTitle = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ; +}; +const DetailsModalCloseIcon = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + + + ); +}; +const DetailsModalBody = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ; +}; +const DetailsModalSection = ({ style, borderBottom, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ; +}; +const DetailsModalSectionTitle = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ; +}; +const DetailsModalColumn = ({ style, end, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ; +}; DetailsModal.Header = DetailsModalHeader; DetailsModal.Title = DetailsModalTitle; diff --git a/app/components/Base/HorizontalSelector/index.js b/app/components/Base/HorizontalSelector/index.js index c455827667b..76d9adf2184 100644 --- a/app/components/Base/HorizontalSelector/index.js +++ b/app/components/Base/HorizontalSelector/index.js @@ -2,106 +2,110 @@ import React, { Fragment, useCallback, useMemo } from 'react'; import PropTypes from 'prop-types'; import { View, StyleSheet, TouchableOpacity } from 'react-native'; import Text from '../Text'; -import { colors } from '../../../styles/common'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; const INNER_CIRCLE_SCALE = 0.445; const OPTION_WIDTH = 110; -const styles = StyleSheet.create({ - selector: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-around', - alignItems: 'center', - }, - labels: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-around', - alignItems: 'flex-start', - }, - option: { - width: OPTION_WIDTH, - display: 'flex', - alignItems: 'center', - flex: 0, - flexDirection: 'column', - }, - circle: (size) => ({ - width: size, - height: size, - flexShrink: 0, - flexGrow: 0, - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - borderWidth: 2, - borderRadius: 9999, - borderColor: colors.grey200, - }), - circleSelected: { - borderColor: colors.blue, - }, - circleError: { - borderColor: colors.red, - }, - circleDisabled: { - opacity: 0.4, - }, - innerCircle: (size) => ({ - width: size * INNER_CIRCLE_SCALE, - height: size * INNER_CIRCLE_SCALE, - flexShrink: 0, - flexGrow: 0, - backgroundColor: colors.blue, - borderRadius: 999, - }), - innerCircleError: { - backgroundColor: colors.red, - }, - verticalLine: { - marginTop: 2, - marginBottom: -1, - width: 0, - height: 4, - borderLeftWidth: 1, - borderColor: colors.grey200, - }, - topVerticalLine: { - marginTop: 0, - marginBottom: 2, - width: 0, - height: 4, - borderLeftWidth: 1, - borderColor: colors.blue, - }, - line: { - alignItems: 'center', - flexDirection: 'row', - justifyContent: 'space-around', - width: '100%', - marginBottom: 2, - }, - lineHolder: { - flexDirection: 'row', - alignItems: 'center', - borderWidth: 0, - }, - lineFill: { - flex: 1, - }, - lineVisible: { - borderTopWidth: 1, - borderColor: colors.grey200, - }, - circleHitSlop: { - top: 0, - bottom: 20, - left: 0, - right: 0, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + selector: { + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-around', + alignItems: 'center', + }, + labels: { + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-around', + alignItems: 'flex-start', + }, + option: { + width: OPTION_WIDTH, + display: 'flex', + alignItems: 'center', + flex: 0, + flexDirection: 'column', + }, + circle: (size) => ({ + width: size, + height: size, + flexShrink: 0, + flexGrow: 0, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + borderWidth: 2, + borderRadius: 9999, + borderColor: colors.border.muted, + }), + circleSelected: { + borderColor: colors.primary.default, + }, + circleError: { + borderColor: colors.error.default, + }, + circleDisabled: { + opacity: 0.4, + }, + innerCircle: (size) => ({ + width: size * INNER_CIRCLE_SCALE, + height: size * INNER_CIRCLE_SCALE, + flexShrink: 0, + flexGrow: 0, + backgroundColor: colors.primary.default, + borderRadius: 999, + }), + innerCircleError: { + backgroundColor: colors.error.default, + }, + verticalLine: { + marginTop: 2, + marginBottom: -1, + width: 0, + height: 4, + borderLeftWidth: 1, + borderColor: colors.border.muted, + }, + topVerticalLine: { + marginTop: 0, + marginBottom: 2, + width: 0, + height: 4, + borderLeftWidth: 1, + borderColor: colors.primary.default, + }, + line: { + alignItems: 'center', + flexDirection: 'row', + justifyContent: 'space-around', + width: '100%', + marginBottom: 2, + }, + lineHolder: { + flexDirection: 'row', + alignItems: 'center', + borderWidth: 0, + }, + lineFill: { + flex: 1, + }, + lineVisible: { + borderTopWidth: 1, + borderColor: colors.border.muted, + }, + circleHitSlop: { + top: 0, + bottom: 20, + left: 0, + right: 0, + }, + }); function Circle({ size = 22, selected, disabled, error }) { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ( onPress(name), [name, onPress]); return ; } @@ -141,7 +147,10 @@ Option.propTypes = { }; function HorizontalSelector({ options = [], selected, circleSize, onPress, disabled, ...props }) { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const hasTopLabels = useMemo(() => options.some((option) => option.topLabel), [options]); + return ( {hasTopLabels && ( diff --git a/app/components/Base/Keypad/components.js b/app/components/Base/Keypad/components.js index ae9ac7831a3..7ad25dd3131 100644 --- a/app/components/Base/Keypad/components.js +++ b/app/components/Base/Keypad/components.js @@ -3,53 +3,73 @@ import PropTypes from 'prop-types'; import { View, StyleSheet, TouchableOpacity } from 'react-native'; import IonicIcon from 'react-native-vector-icons/Ionicons'; import Device from '../../../util/device'; - import Text from '../Text'; -import { colors } from '../../../styles/common'; - -const styles = StyleSheet.create({ - keypad: { - paddingHorizontal: 25, - }, - keypadRow: { - flexDirection: 'row', - justifyContent: 'space-around', - }, - keypadButton: { - paddingHorizontal: 20, - paddingVertical: Device.isMediumDevice() ? (Device.isIphone5() ? 4 : 8) : 12, - flex: 1, - justifyContent: 'center', - alignItems: 'center', - }, - keypadButtonText: { - color: colors.black, - textAlign: 'center', - fontSize: 30, - }, - deleteIcon: { - fontSize: 25, - marginTop: 5, - }, -}); - -const KeypadContainer = (props) => ; -const KeypadRow = (props) => ; -const KeypadButton = ({ children, ...props }) => ( - - {children} - -); +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; + +const createStyles = (colors) => + StyleSheet.create({ + keypad: { + paddingHorizontal: 25, + }, + keypadRow: { + flexDirection: 'row', + justifyContent: 'space-around', + }, + keypadButton: { + paddingHorizontal: 20, + paddingVertical: Device.isMediumDevice() ? (Device.isIphone5() ? 4 : 8) : 12, + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + keypadButtonText: { + color: colors.text.default, + textAlign: 'center', + fontSize: 30, + }, + deleteIcon: { + fontSize: 25, + marginTop: 5, + }, + }); + +const KeypadContainer = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ; +}; +const KeypadRow = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ; +}; +const KeypadButton = ({ children, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + {children} + + ); +}; KeypadButton.propTypes = { children: PropTypes.node, }; -const KeypadDeleteButton = (props) => ( - - - -); +const KeypadDeleteButton = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + + + ); +}; const Keypad = KeypadContainer; Keypad.Row = KeypadRow; diff --git a/app/components/Base/ListItem.js b/app/components/Base/ListItem.js index 9474712d6af..9dec4fd3efa 100644 --- a/app/components/Base/ListItem.js +++ b/app/components/Base/ListItem.js @@ -1,69 +1,110 @@ import React from 'react'; import PropTypes from 'prop-types'; import { StyleSheet, View } from 'react-native'; -// import Device from '../../util/device'; -import { colors, fontStyles } from '../../styles/common'; +import { fontStyles } from '../../styles/common'; import Text from './Text'; +import { useAppThemeFromContext, mockTheme } from '../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - padding: 15, - // TODO(wachunei): check if this can be removed without breaking anything - // minHeight: Device.isIos() ? 55 : 100 - }, - date: { - color: colors.fontSecondary, - fontSize: 12, - marginBottom: 10, - ...fontStyles.normal, - }, - content: { - flexDirection: 'row', - alignItems: 'center', - }, - actions: { - flexDirection: 'row', - paddingTop: 10, - paddingLeft: 40, - }, - icon: { - flexDirection: 'row', - alignItems: 'center', - }, - body: { - flex: 1, - marginLeft: 15, - }, - amounts: { - flex: 0.6, - alignItems: 'flex-end', - }, - title: { - fontSize: 15, - color: colors.fontPrimary, - }, - amount: { - fontSize: 15, - color: colors.fontPrimary, - }, - fiatAmount: { - fontSize: 12, - color: colors.fontSecondary, - textTransform: 'uppercase', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + padding: 15, + // TODO(wachunei): check if this can be removed without breaking anything + // minHeight: Device.isIos() ? 55 : 100 + }, + date: { + color: colors.text.default, + fontSize: 12, + marginBottom: 10, + ...fontStyles.normal, + }, + content: { + flexDirection: 'row', + alignItems: 'center', + }, + actions: { + flexDirection: 'row', + paddingTop: 10, + paddingLeft: 40, + }, + icon: { + flexDirection: 'row', + alignItems: 'center', + }, + body: { + flex: 1, + marginLeft: 15, + }, + amounts: { + flex: 0.6, + alignItems: 'flex-end', + }, + title: { + fontSize: 15, + color: colors.text.default, + }, + amount: { + fontSize: 15, + color: colors.text.default, + }, + fiatAmount: { + fontSize: 12, + color: colors.text.alternative, + textTransform: 'uppercase', + }, + }); -const ListItem = ({ style, ...props }) => ; +const ListItem = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ; +}; -const ListItemDate = ({ style, ...props }) => ; -const ListItemContent = ({ style, ...props }) => ; -const ListItemActions = ({ style, ...props }) => ; -const ListItemIcon = ({ style, ...props }) => ; -const ListItemBody = ({ style, ...props }) => ; -const ListItemTitle = ({ style, ...props }) => ; -const ListItemAmounts = ({ style, ...props }) => ; -const ListItemAmount = ({ style, ...props }) => ; -const ListItemFiatAmount = ({ style, ...props }) => ; +const ListItemDate = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ; +}; +const ListItemContent = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ; +}; +const ListItemActions = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ; +}; +const ListItemIcon = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ; +}; +const ListItemBody = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ; +}; +const ListItemTitle = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ; +}; +const ListItemAmounts = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ; +}; +const ListItemAmount = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ; +}; +const ListItemFiatAmount = ({ style, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ; +}; ListItem.Date = ListItemDate; ListItem.Content = ListItemContent; diff --git a/app/components/Base/ListItem.stories.js b/app/components/Base/ListItem.stories.js index dee147d0c2f..951ebb78a42 100644 --- a/app/components/Base/ListItem.stories.js +++ b/app/components/Base/ListItem.stories.js @@ -8,7 +8,6 @@ import FontAwesome from 'react-native-vector-icons/FontAwesome'; import ListItem from './ListItem'; import Text from './Text'; -import { colors } from '../../styles/common'; const exampleItems = [ { @@ -71,7 +70,6 @@ storiesOf('Base / ListItem', module) diff --git a/app/components/Base/ModalDragger.js b/app/components/Base/ModalDragger.js index 38c55250545..bdaf8ddf10f 100644 --- a/app/components/Base/ModalDragger.js +++ b/app/components/Base/ModalDragger.js @@ -1,31 +1,34 @@ import React from 'react'; import PropTypes from 'prop-types'; import { StyleSheet, View } from 'react-native'; -import { colors } from '../../styles/common'; -import Device from '../../util/device'; +import { useAppThemeFromContext, mockTheme } from '../../util/theme'; +import { colors as importedColors } from '../../styles/common'; -const styles = StyleSheet.create({ - draggerWrapper: { - width: '100%', - height: 33, - alignItems: 'center', - justifyContent: 'center', - borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - }, - borderless: { - borderColor: colors.transparent, - }, - dragger: { - width: 48, - height: 5, - borderRadius: 4, - backgroundColor: colors.grey400, - opacity: Device.isAndroid() ? 0.6 : 0.5, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + draggerWrapper: { + width: '100%', + height: 33, + alignItems: 'center', + justifyContent: 'center', + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + }, + borderless: { + borderColor: importedColors.transparent, + }, + dragger: { + width: 48, + height: 5, + borderRadius: 4, + backgroundColor: colors.border.default, + }, + }); function ModalDragger({ borderless }) { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ( diff --git a/app/components/Base/RangeInput.js b/app/components/Base/RangeInput.js index 7e2ff10bb7c..351bff316ba 100644 --- a/app/components/Base/RangeInput.js +++ b/app/components/Base/RangeInput.js @@ -1,87 +1,91 @@ import React, { useCallback, useRef, useEffect, useState } from 'react'; import { View, TextInput, StyleSheet, TouchableOpacity } from 'react-native'; -import { colors } from '../../styles/common'; import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome'; import Text from './Text'; import PropTypes from 'prop-types'; import BigNumber from 'bignumber.js'; +import { useAppThemeFromContext, mockTheme } from '../../util/theme'; -const styles = StyleSheet.create({ - labelContainer: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - marginBottom: 14, - }, - rangeInputContainer: (error) => ({ - borderColor: error ? colors.red : colors.grey200, - borderWidth: 1, - borderRadius: 6, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - height: 42, - }), - input: (error) => ({ - height: 38, - minWidth: 10, - paddingRight: 6, - color: error ? colors.red : colors.black, - }), - buttonContainerLeft: { - marginLeft: 17, - flex: 1, - }, - buttonContainerRight: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'flex-end', - marginRight: 17, - flex: 1, - }, - button: { - borderRadius: 100, - borderWidth: 2, - borderColor: colors.blue, - height: 20, - width: 20, - alignItems: 'center', - justifyContent: 'center', - }, - buttonText: { - paddingTop: 1, - paddingLeft: 0.5, - color: colors.blue, - }, - hitSlop: { - top: 10, - left: 10, - bottom: 10, - right: 10, - }, - inputContainer: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - }, - errorContainer: { - marginTop: 8, - color: colors.red, - flexDirection: 'row', - alignItems: 'center', - }, - errorIcon: { - paddingRight: 4, - color: colors.red, - }, - conversionEstimation: { - paddingLeft: 2, - marginRight: 14, - flex: 1, - textAlign: 'center', - fontSize: 11, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + labelContainer: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginBottom: 14, + }, + rangeInputContainer: (error) => ({ + borderColor: error ? colors.error.default : colors.border.default, + borderWidth: 1, + borderRadius: 6, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + height: 42, + }), + input: (error) => ({ + height: 38, + minWidth: 10, + paddingRight: 6, + color: error ? colors.error.default : colors.text.default, + }), + buttonContainerLeft: { + marginLeft: 17, + flex: 1, + }, + buttonContainerRight: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'flex-end', + marginRight: 17, + flex: 1, + }, + button: { + borderRadius: 100, + borderWidth: 2, + borderColor: colors.primary.default, + height: 20, + width: 20, + alignItems: 'center', + justifyContent: 'center', + }, + buttonText: { + paddingTop: 1, + paddingLeft: 0.5, + color: colors.primary.default, + }, + hitSlop: { + top: 10, + left: 10, + bottom: 10, + right: 10, + }, + inputContainer: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + errorContainer: { + marginTop: 8, + color: colors.error.default, + flexDirection: 'row', + alignItems: 'center', + }, + errorText: { + color: colors.text.default, + }, + errorIcon: { + paddingRight: 4, + color: colors.error.default, + }, + conversionEstimation: { + paddingLeft: 2, + marginRight: 14, + flex: 1, + textAlign: 'center', + fontSize: 11, + }, + }); const RangeInput = ({ leftLabelComponent, @@ -98,6 +102,9 @@ const RangeInput = ({ }) => { const textInput = useRef(null); const [errorState, setErrorState] = useState(); + const { colors, themeAppearance } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + const handleClickUnit = useCallback(() => { textInput?.current?.focus?.(); }, []); @@ -178,6 +185,7 @@ const RangeInput = ({ value={value} keyboardType="numeric" ref={textInput} + keyboardAppearance={themeAppearance} /> {!!unit && ( @@ -197,7 +205,7 @@ const RangeInput = ({ {hasError && ( - + {error || errorState} diff --git a/app/components/Base/RemoteImage/__snapshots__/index.test.tsx.snap b/app/components/Base/RemoteImage/__snapshots__/index.test.tsx.snap index 50c11d50f66..5e880170d2e 100644 --- a/app/components/Base/RemoteImage/__snapshots__/index.test.tsx.snap +++ b/app/components/Base/RemoteImage/__snapshots__/index.test.tsx.snap @@ -28,7 +28,7 @@ exports[`RemoteImage should render svg correctly 1`] = ` style={Object {}} > { // Avoid using this component with animated SVG @@ -42,7 +43,7 @@ const RemoteImage = (props) => { return ( - + ); diff --git a/app/components/Base/SelectorButton.js b/app/components/Base/SelectorButton.js index 1660eef818d..2f16e5ff904 100644 --- a/app/components/Base/SelectorButton.js +++ b/app/components/Base/SelectorButton.js @@ -2,27 +2,31 @@ import React from 'react'; import PropTypes from 'prop-types'; import { View, StyleSheet, TouchableOpacity } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; -import { colors } from '../../styles/common'; +import { useAppThemeFromContext, mockTheme } from '../../util/theme'; -const styles = StyleSheet.create({ - container: { - backgroundColor: colors.grey000, - paddingVertical: 8, - paddingHorizontal: 10, - borderRadius: 100, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - }, - caretDown: { - textAlign: 'right', - color: colors.grey500, - marginLeft: 10, - marginRight: 5, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + container: { + backgroundColor: colors.background.alternative, + paddingVertical: 8, + paddingHorizontal: 10, + borderRadius: 100, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + caretDown: { + textAlign: 'right', + color: colors.text.alternative, + marginLeft: 10, + marginRight: 5, + }, + }); function SelectorButton({ onPress, disabled, children, ...props }) { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ( diff --git a/app/components/Base/StatusText.js b/app/components/Base/StatusText.js index 8af81a449da..3ef9fae4b2f 100644 --- a/app/components/Base/StatusText.js +++ b/app/components/Base/StatusText.js @@ -1,10 +1,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import Text from './Text'; -import { colors } from '../../styles/common'; import { StyleSheet } from 'react-native'; import { FIAT_ORDER_STATES } from '../../constants/on-ramp'; import { strings } from '../../../locales/i18n'; +import { useAppThemeFromContext, mockTheme } from '../../util/theme'; const styles = StyleSheet.create({ status: { @@ -15,8 +15,14 @@ const styles = StyleSheet.create({ }); export const ConfirmedText = (props) => ; -export const PendingText = (props) => ; -export const FailedText = (props) => ; +export const PendingText = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + return ; +}; +export const FailedText = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + return ; +}; function StatusText({ status, context, ...props }) { switch (status) { diff --git a/app/components/Base/Summary.js b/app/components/Base/Summary.js index 908a4ae0a3a..1f5f098550a 100644 --- a/app/components/Base/Summary.js +++ b/app/components/Base/Summary.js @@ -1,45 +1,61 @@ import React from 'react'; import PropTypes from 'prop-types'; import { View, StyleSheet } from 'react-native'; -import { colors } from '../../styles/common'; +import { useAppThemeFromContext, mockTheme } from '../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - borderWidth: 1, - borderColor: colors.grey050, - borderRadius: 8, - padding: 16, - }, - row: { - flexDirection: 'row', - justifyContent: 'space-between', - marginVertical: 3, - }, - rowEnd: { - justifyContent: 'flex-end', - }, - rowLast: { - marginBottom: 0, - marginTop: 3, - }, - col: { - flexDirection: 'row', - flex: 1, - flexWrap: 'wrap', - }, - separator: { - borderBottomWidth: 1, - borderBottomColor: colors.grey050, - marginVertical: 6, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + borderWidth: 1, + borderColor: colors.border.muted, + borderRadius: 8, + padding: 16, + }, + row: { + flexDirection: 'row', + justifyContent: 'space-between', + marginVertical: 3, + }, + rowEnd: { + justifyContent: 'flex-end', + }, + rowLast: { + marginBottom: 0, + marginTop: 3, + }, + col: { + flexDirection: 'row', + flex: 1, + flexWrap: 'wrap', + }, + separator: { + borderBottomWidth: 1, + borderBottomColor: colors.border.muted, + marginVertical: 6, + }, + }); -const Summary = ({ style, ...props }) => ; -const SummaryRow = ({ style, end, last, ...props }) => ( - -); -const SummaryCol = ({ style, end, ...props }) => ; -const SummarySeparator = ({ style, ...props }) => ; +const useGetStyles = () => { + const { colors } = useAppThemeFromContext() || mockTheme; + return createStyles(colors); +}; + +const Summary = ({ style, ...props }) => { + const styles = useGetStyles(); + return ; +}; +const SummaryRow = ({ style, end, last, ...props }) => { + const styles = useGetStyles(); + return ; +}; +const SummaryCol = ({ style, end, ...props }) => { + const styles = useGetStyles(); + return ; +}; +const SummarySeparator = ({ style, ...props }) => { + const styles = useGetStyles(); + return ; +}; Summary.Row = SummaryRow; Summary.Col = SummaryCol; diff --git a/app/components/Base/TabBar.js b/app/components/Base/TabBar.js index 9835fb886c7..9e16f6f5682 100644 --- a/app/components/Base/TabBar.js +++ b/app/components/Base/TabBar.js @@ -1,30 +1,34 @@ import React from 'react'; import { StyleSheet } from 'react-native'; import DefaultTabBar from 'react-native-scrollable-tab-view/DefaultTabBar'; +import { fontStyles } from '../../styles/common'; +import { useAppThemeFromContext, mockTheme } from '../../util/theme'; -import { colors, fontStyles } from '../../styles/common'; - -const styles = StyleSheet.create({ - tabUnderlineStyle: { - height: 2, - backgroundColor: colors.blue, - }, - tabStyle: { - paddingVertical: 8, - }, - textStyle: { - ...fontStyles.normal, - fontSize: 14, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + tabUnderlineStyle: { + height: 2, + backgroundColor: colors.primary.default, + }, + tabStyle: { + paddingVertical: 8, + }, + textStyle: { + ...fontStyles.normal, + fontSize: 14, + }, + }); function TabBar({ ...props }) { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ( + StyleSheet.create({ + text: { + ...fontStyles.normal, + color: colors.text.default, + marginVertical: 2, + fontSize: 14, + }, + centered: { + textAlign: 'center', + }, + right: { + textAlign: 'right', + }, + red: { + color: colors.error.default, + }, + orange: { + color: colors.secondary.default, + }, + black: { + color: colors.text.default, + }, + bold: fontStyles.bold, + blue: { + color: colors.primary.default, + }, + green: { + color: colors.success.default, + }, + grey: { + color: colors.text.alternative, + }, + primary: { + color: colors.text.default, + }, + small: { + fontSize: 12, + }, + big: { + fontSize: 16, + }, + upper: { + textTransform: 'uppercase', + }, + disclaimer: { + fontStyle: 'italic', + letterSpacing: 0.15, + }, + modal: { + color: colors.text.default, + fontSize: 16, + lineHeight: 22.4, // 1.4 * fontSize + }, + infoModal: { + lineHeight: 20, + marginVertical: 6, + }, + link: { + color: colors.primary.default, + }, + strikethrough: { + textDecorationLine: 'line-through', + }, + underline: { + textDecorationLine: 'underline', + }, + noMargin: { + marginVertical: 0, + }, + }); const Text = ({ reset, @@ -98,36 +100,41 @@ const Text = ({ style: externalStyle, noMargin, ...props -}) => ( - -); +}) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const style = createStyles(colors); + + return ( + + ); +}; Text.defaultProps = { reset: false, diff --git a/app/components/Base/Title.js b/app/components/Base/Title.js index d33bb5f34de..43aaa6272a7 100644 --- a/app/components/Base/Title.js +++ b/app/components/Base/Title.js @@ -1,27 +1,32 @@ import React from 'react'; import PropTypes from 'prop-types'; import { StyleSheet } from 'react-native'; -import { fontStyles, colors } from '../../styles/common'; +import { fontStyles } from '../../styles/common'; import Text from './Text.js'; +import { useAppThemeFromContext, mockTheme } from '../../util/theme'; -const style = StyleSheet.create({ - text: { - fontSize: 18, - marginVertical: 3, - color: colors.fontPrimary, - ...fontStyles.bold, - }, - hero: { - fontSize: 22, - }, - centered: { - textAlign: 'center', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + text: { + fontSize: 18, + marginVertical: 3, + color: colors.text.default, + ...fontStyles.bold, + }, + hero: { + fontSize: 22, + }, + centered: { + textAlign: 'center', + }, + }); -const Title = ({ centered, hero, style: externalStyle, ...props }) => ( - -); +const Title = ({ centered, hero, style: externalStyle, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const style = createStyles(colors); + + return ; +}; Title.defaultProps = { centered: false, diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js index f295aa09561..b0c502d6add 100644 --- a/app/components/Nav/App/index.js +++ b/app/components/Nav/App/index.js @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { NavigationContainer, CommonActions } from '@react-navigation/native'; -import { Animated, StyleSheet, View } from 'react-native'; +import { Animated } from 'react-native'; import { createStackNavigator } from '@react-navigation/stack'; import AsyncStorage from '@react-native-community/async-storage'; import Login from '../../Views/Login'; @@ -35,10 +35,7 @@ import { getVersion } from 'react-native-device-info'; import { checkedAuth } from '../../../actions/user'; import { setCurrentRoute } from '../../../actions/navigation'; import { findRouteNameFromNavigatorState } from '../../../util/general'; - -const styles = StyleSheet.create({ - fill: { flex: 1 }, -}); +import { ThemeContext, useAppTheme } from '../../../util/theme'; const Stack = createStackNavigator(); /** @@ -254,11 +251,15 @@ const App = ({ userLoggedIn }) => { return null; }; + const theme = useAppTheme(); + return ( // do not render unless a route is defined (route && ( - + { routingInstrumentation.registerNavigationContainer(navigator); @@ -282,7 +283,7 @@ const App = ({ userLoggedIn }) => { {renderSplash()} - + )) || null ); diff --git a/app/components/Nav/Main/MainNavigator.js b/app/components/Nav/Main/MainNavigator.js index f6584cdb454..4e4996c5e0c 100644 --- a/app/components/Nav/Main/MainNavigator.js +++ b/app/components/Nav/Main/MainNavigator.js @@ -25,7 +25,6 @@ import WalletConnectSessions from '../../Views/WalletConnectSessions'; import OfflineMode from '../../Views/OfflineMode'; import QrScanner from '../../Views/QRScanner'; import LockScreen from '../../Views/LockScreen'; -import ChoosePasswordSimple from '../../Views/ChoosePasswordSimple'; import EnterPasswordSimple from '../../Views/EnterPasswordSimple'; import ChoosePassword from '../../Views/ChoosePassword'; import ResetPassword from '../../Views/ResetPassword'; @@ -51,6 +50,8 @@ import GasEducationCarousel from '../../Views/GasEducationCarousel'; import CollectiblesDetails from '../../UI/CollectibleModal'; import OptinMetrics from '../../UI/OptinMetrics'; import Drawer from '../../UI/Drawer'; +import ThemeSettings from '../../Views/ThemeSettings'; +import { colors as importedColors } from '../../../styles/common'; const Stack = createStackNavigator(); const Tab = createBottomTabNavigator(); @@ -132,8 +133,8 @@ const Webview = () => ( ); -const SettingsView = () => ( - +const SettingsFlow = () => ( + ( component={WalletConnectSessions} options={WalletConnectSessions.navigationOptions} /> - ( ); +const SettingsModalStack = () => ( + + + + +); + const ImportPrivateKeyView = () => ( ( component={CollectiblesDetails} options={{ //Refer to - https://reactnavigation.org/docs/stack-navigator/#animations - cardStyle: { backgroundColor: 'transparent' }, + cardStyle: { backgroundColor: importedColors.transparent }, cardStyleInterpolator: () => ({ overlayStyle: { opacity: 0, @@ -335,7 +342,7 @@ const MainNavigator = () => ( /> - + diff --git a/app/components/Nav/Main/RootRPCMethodsUI.js b/app/components/Nav/Main/RootRPCMethodsUI.js index c07c17b5447..922f3e9b3e2 100644 --- a/app/components/Nav/Main/RootRPCMethodsUI.js +++ b/app/components/Nav/Main/RootRPCMethodsUI.js @@ -45,6 +45,7 @@ import BigNumber from 'bignumber.js'; import { getTokenList } from '../../../reducers/tokens'; import { toLowerCaseEquals } from '../../../util/general'; import { ApprovalTypes } from '../../../core/RPCMethods/RPCMethodMiddleware'; +import { mockTheme, useAppThemeFromContext } from '../../../util/theme'; const hstInterface = new ethers.utils.Interface(abi); @@ -55,6 +56,7 @@ const styles = StyleSheet.create({ }, }); const RootRPCMethodsUI = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; const [showPendingApproval, setShowPendingApproval] = useState(false); const [signMessageParams, setSignMessageParams] = useState({ data: '' }); const [signType, setSignType] = useState(false); @@ -331,7 +333,8 @@ const RootRPCMethodsUI = (props) => { animationIn="slideInUp" animationOut="slideOutDown" style={styles.bottomModal} - backdropOpacity={0.7} + backdropColor={colors.overlay.default} + backdropOpacity={1} animationInTiming={600} animationOutTiming={600} onBackdropPress={onSignAction} @@ -398,7 +401,8 @@ const RootRPCMethodsUI = (props) => { animationIn="slideInUp" animationOut="slideOutDown" style={styles.bottomModal} - backdropOpacity={0.7} + backdropColor={colors.overlay.default} + backdropOpacity={1} animationInTiming={300} animationOutTiming={300} onSwipeComplete={onWalletConnectSessionRejected} @@ -459,7 +463,8 @@ const RootRPCMethodsUI = (props) => { animationIn="slideInUp" animationOut="slideOutDown" style={styles.bottomModal} - backdropOpacity={0.7} + backdropColor={colors.overlay.default} + backdropOpacity={1} animationInTiming={300} animationOutTiming={300} onSwipeComplete={onAddCustomNetworkReject} @@ -493,7 +498,8 @@ const RootRPCMethodsUI = (props) => { animationIn="slideInUp" animationOut="slideOutDown" style={styles.bottomModal} - backdropOpacity={0.7} + backdropColor={colors.overlay.default} + backdropOpacity={1} animationInTiming={300} animationOutTiming={300} onSwipeComplete={onSwitchCustomNetworkReject} @@ -535,7 +541,8 @@ const RootRPCMethodsUI = (props) => { animationIn="slideInUp" animationOut="slideOutDown" style={styles.bottomModal} - backdropOpacity={0.7} + backdropColor={colors.overlay.default} + backdropOpacity={1} animationInTiming={300} animationOutTiming={300} onSwipeComplete={onAccountsReject} @@ -566,7 +573,8 @@ const RootRPCMethodsUI = (props) => { animationIn="slideInUp" animationOut="slideOutDown" style={styles.bottomModal} - backdropOpacity={0.7} + backdropColor={colors.overlay.default} + backdropOpacity={1} animationInTiming={600} animationOutTiming={600} onBackdropPress={onCancelWatchAsset} diff --git a/app/components/Nav/Main/index.js b/app/components/Nav/Main/index.js index 5de91aa7d5f..65627a14cf7 100644 --- a/app/components/Nav/Main/index.js +++ b/app/components/Nav/Main/index.js @@ -17,7 +17,6 @@ import Engine from '../../../core/Engine'; import AppConstants from '../../../core/AppConstants'; import PushNotification from 'react-native-push-notification'; import I18n from '../../../../locales/i18n'; -import { colors } from '../../../styles/common'; import LockManager from '../../../core/LockManager'; import FadeOutOverlay from '../../UI/FadeOutOverlay'; import Device from '../../../util/device'; @@ -41,27 +40,33 @@ import { setInfuraAvailabilityBlocked, setInfuraAvailabilityNotBlocked } from '. import { createStackNavigator } from '@react-navigation/stack'; import ReviewModal from '../../UI/ReviewModal'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; import RootRPCMethodsUI from './RootRPCMethodsUI'; import usePrevious from '../../hooks/usePrevious'; +import { colors as importedColors } from '../../../styles/common'; const Stack = createStackNavigator(); -const styles = StyleSheet.create({ - flex: { - flex: 1, - }, - loader: { - backgroundColor: colors.white, - flex: 1, - justifyContent: 'center', - alignItems: 'center', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + flex: { + flex: 1, + }, + loader: { + backgroundColor: colors.background.default, + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + }); + const Main = (props) => { const [connected, setConnected] = useState(true); const [forceReload, setForceReload] = useState(false); const [showRemindLaterModal, setShowRemindLaterModal] = useState(false); const [skipCheckbox, setSkipCheckbox] = useState(false); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const backgroundMode = useRef(false); const locale = useRef(I18n.locale); @@ -257,7 +262,6 @@ const Main = (props) => { onCancel={skipAccountModalSecureNow} onConfirm={skipAccountModalSkip} skipCheckbox={skipCheckbox} - onPress={skipAccountModalSkip} toggleSkipCheckbox={toggleSkipCheckbox} /> @@ -339,7 +343,7 @@ const MainFlow = () => ( diff --git a/app/components/UI/AccountApproval/index.js b/app/components/UI/AccountApproval/index.js index 280bda51492..14fc964fc64 100644 --- a/app/components/UI/AccountApproval/index.js +++ b/app/components/UI/AccountApproval/index.js @@ -6,57 +6,60 @@ import { StyleSheet, Text, View, InteractionManager } from 'react-native'; import TransactionHeader from '../TransactionHeader'; import AccountInfoCard from '../AccountInfoCard'; import { strings } from '../../../../locales/i18n'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import Device from '../../../util/device'; import NotificationManager from '../../../core/NotificationManager'; import AnalyticsV2 from '../../../util/analyticsV2'; import URL from 'url-parse'; +import { ThemeContext, mockTheme } from '../../../util/theme'; import { ACCOUNT_APROVAL_MODAL_CONTAINER_ID, CANCEL_BUTTON_ID } from '../../../constants/test-ids'; -const styles = StyleSheet.create({ - root: { - backgroundColor: colors.white, - paddingTop: 24, - borderTopLeftRadius: 20, - borderTopRightRadius: 20, - minHeight: 200, - paddingBottom: Device.isIphoneX() ? 20 : 0, - }, - accountCardWrapper: { - paddingHorizontal: 24, - }, - intro: { - ...fontStyles.bold, - textAlign: 'center', - color: colors.fontPrimary, - fontSize: Device.isSmallDevice() ? 16 : 20, - marginBottom: 8, - marginTop: 16, - }, - warning: { - ...fontStyles.thin, - color: colors.fontPrimary, - paddingHorizontal: 24, - marginBottom: 16, - fontSize: 14, - width: '100%', - textAlign: 'center', - }, - actionContainer: { - flex: 0, - flexDirection: 'row', - paddingVertical: 16, - paddingHorizontal: 24, - }, - button: { - flex: 1, - }, - cancel: { - marginRight: 8, - }, - confirm: { - marginLeft: 8, - }, -}); + +const createStyles = (colors) => + StyleSheet.create({ + root: { + backgroundColor: colors.background.default, + paddingTop: 24, + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + minHeight: 200, + paddingBottom: Device.isIphoneX() ? 20 : 0, + }, + accountCardWrapper: { + paddingHorizontal: 24, + }, + intro: { + ...fontStyles.bold, + textAlign: 'center', + color: colors.text.default, + fontSize: Device.isSmallDevice() ? 16 : 20, + marginBottom: 8, + marginTop: 16, + }, + warning: { + ...fontStyles.thin, + color: colors.text.default, + paddingHorizontal: 24, + marginBottom: 16, + fontSize: 14, + width: '100%', + textAlign: 'center', + }, + actionContainer: { + flex: 0, + flexDirection: 'row', + paddingVertical: 16, + paddingHorizontal: 24, + }, + button: { + flex: 1, + }, + cancel: { + marginRight: 8, + }, + confirm: { + marginLeft: 8, + }, + }); /** * Account access approval component @@ -180,6 +183,9 @@ class AccountApproval extends PureComponent { render = () => { const { currentPageInformation } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -218,4 +224,6 @@ const mapStateToProps = (state) => ({ chainId: state.engine.backgroundState.NetworkController.provider.chainId, }); +AccountApproval.contextType = ThemeContext; + export default connect(mapStateToProps)(AccountApproval); diff --git a/app/components/UI/AccountInfoCard/index.js b/app/components/UI/AccountInfoCard/index.js index 2bf00bc4cc8..07d63b71b8a 100644 --- a/app/components/UI/AccountInfoCard/index.js +++ b/app/components/UI/AccountInfoCard/index.js @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { StyleSheet, View, Text } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { renderFromWei, weiToFiat, hexToBN } from '../../../util/number'; import Identicon from '../Identicon'; import { strings } from '../../../../locales/i18n'; @@ -9,50 +9,52 @@ import { connect } from 'react-redux'; import { renderAccountName, renderShortAddress } from '../../../util/address'; import { getTicker } from '../../../util/transactions'; import Device from '../../../util/device'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - accountInformation: { - flexDirection: 'row', - justifyContent: 'flex-start', - borderWidth: 1, - borderColor: colors.grey200, - borderRadius: 10, - padding: 16, - }, - identicon: { - marginRight: 8, - }, - accountInfoRow: { - flexGrow: 1, - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'flex-start', - }, - accountNameAndAddress: { - width: '100%', - flexDirection: 'row', - justifyContent: 'flex-start', - }, - accountName: { - maxWidth: Device.isMediumDevice() ? '35%' : '45%', - ...fontStyles.bold, - fontSize: 16, - marginRight: 2, - color: colors.black, - }, - accountAddress: { - flexGrow: 1, - ...fontStyles.bold, - fontSize: 16, - color: colors.black, - }, - balanceText: { - ...fontStyles.thin, - fontSize: 14, - alignSelf: 'flex-start', - color: colors.black, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + accountInformation: { + flexDirection: 'row', + justifyContent: 'flex-start', + borderWidth: 1, + borderColor: colors.border.default, + borderRadius: 10, + padding: 16, + }, + identicon: { + marginRight: 8, + }, + accountInfoRow: { + flexGrow: 1, + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'flex-start', + }, + accountNameAndAddress: { + width: '100%', + flexDirection: 'row', + justifyContent: 'flex-start', + }, + accountName: { + maxWidth: Device.isMediumDevice() ? '35%' : '45%', + ...fontStyles.bold, + fontSize: 16, + marginRight: 2, + color: colors.text.default, + }, + accountAddress: { + flexGrow: 1, + ...fontStyles.bold, + fontSize: 16, + color: colors.text.default, + }, + balanceText: { + ...fontStyles.thin, + fontSize: 14, + alignSelf: 'flex-start', + color: colors.text.default, + }, + }); class AccountInfoCard extends PureComponent { static propTypes = { @@ -89,6 +91,9 @@ class AccountInfoCard extends PureComponent { render() { const { accounts, selectedAddress, identities, conversionRate, currentCurrency, operation, ticker } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + const weiBalance = hexToBN(accounts[selectedAddress].balance); const balance = `(${renderFromWei(weiBalance)} ${getTicker(ticker)})`; const accountLabel = renderAccountName(selectedAddress, identities); @@ -126,4 +131,6 @@ const mapStateToProps = (state) => ({ ticker: state.engine.backgroundState.NetworkController.provider.ticker, }); +AccountInfoCard.contextType = ThemeContext; + export default connect(mapStateToProps)(AccountInfoCard); diff --git a/app/components/UI/AccountInput/__snapshots__/index.test.tsx.snap b/app/components/UI/AccountInput/__snapshots__/index.test.tsx.snap deleted file mode 100644 index f69b4b14871..00000000000 --- a/app/components/UI/AccountInput/__snapshots__/index.test.tsx.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AccountInput should render correctly 1`] = ``; diff --git a/app/components/UI/AccountInput/index.js b/app/components/UI/AccountInput/index.js deleted file mode 100644 index 3710064c4b8..00000000000 --- a/app/components/UI/AccountInput/index.js +++ /dev/null @@ -1,426 +0,0 @@ -import React, { PureComponent } from 'react'; -import Icon from 'react-native-vector-icons/FontAwesome'; -import Identicon from '../Identicon'; -import PropTypes from 'prop-types'; -import { ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View, Keyboard } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; -import { connect } from 'react-redux'; -import { renderShortAddress, isENS } from '../../../util/address'; -import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; -import ElevatedView from 'react-native-elevated-view'; -import ENS from 'ethjs-ens'; -import networkMap from 'ethjs-ens/lib/network-map.json'; -import Engine from '../../../core/Engine'; -import { strings } from '../../../../locales/i18n'; -import { isValidAddress } from 'ethereumjs-util'; -import Device from '../../../util/device'; -import EthereumAddress from '../EthereumAddress'; -import AppConstants from '../../../core/AppConstants'; - -const styles = StyleSheet.create({ - root: { - flex: 1, - }, - arrow: { - color: colors.grey100, - position: 'absolute', - right: 10, - top: Device.isAndroid() ? 14 : 12, - }, - componentContainer: { - maxHeight: Device.isAndroid() ? 175 : 200, - borderRadius: 4, - flex: 1, - }, - input: { - ...fontStyles.bold, - backgroundColor: colors.white, - marginRight: 24, - paddingLeft: 0, - minWidth: Device.isSmallDevice() ? 100 : 120, - }, - qrCodeButton: { - minHeight: 50, - paddingRight: 8, - paddingLeft: 12, - paddingTop: 2, - flexDirection: 'row', - alignItems: 'center', - }, - accountContainer: { - flexDirection: 'row', - backgroundColor: colors.white, - borderColor: colors.grey100, - borderRadius: 4, - borderWidth: 1, - }, - toContainer: { - flexDirection: 'column', - }, - inputContainer: { - fontSize: 16, - paddingLeft: 8, - flexDirection: 'row', - alignItems: 'center', - marginRight: 48, - }, - option: { - flexDirection: 'row', - paddingBottom: 4, - paddingLeft: 8, - paddingRight: 10, - paddingTop: 8, - }, - address: { - ...fontStyles.normal, - fontSize: 16, - }, - accountWithoutName: { - marginTop: 4, - }, - name: { - flex: 1, - ...fontStyles.bold, - fontSize: 16, - marginBottom: 4, - }, - icon: { - paddingRight: 8, - paddingLeft: 6, - paddingTop: 1.5, - }, - optionList: { - backgroundColor: colors.white, - borderColor: colors.grey100, - borderRadius: 4, - borderWidth: 1, - paddingBottom: 12, - paddingTop: 12, - width: '100%', - top: 0, - left: 0, - right: 0, - }, - content: { - flex: 1, - paddingLeft: 8, - }, - ensAddress: { - fontSize: 10, - top: Device.isAndroid() ? -16 : 0, - paddingLeft: Device.isAndroid() ? 4 : 0, - }, -}); - -/** - * ComboBox form component allowing address input with auto-completion based on - * the current keychain's accounts - */ -class AccountInput extends PureComponent { - static propTypes = { - /** - * List of accounts from the PreferencesController - */ - accounts: PropTypes.object, - /** - * Callback triggered when the address changes - */ - onChange: PropTypes.func, - /** - * Callback triggered when the input is focused - */ - onFocus: PropTypes.func, - /** - * Callback triggered when the input is blurred - */ - onBlur: PropTypes.func, - /** - * Placeholder text to show inside this input - */ - placeholder: PropTypes.string, - /** - * react-navigation object used for switching between screens - */ - navigation: PropTypes.object, - /** - * Value of this underlying input - */ - address: PropTypes.string, - /** - * Value of this underlying input - */ - ensRecipient: PropTypes.string, - /** - * Network id - */ - network: PropTypes.string, - /** - * Network id - */ - updateToAddressError: PropTypes.func, - /** - * Callback to open accounts dropdown - */ - openAccountSelect: PropTypes.func, - /** - * Whether accounts dropdown is opened - */ - isOpen: PropTypes.bool, - /** - * Map representing the address book - */ - addressBook: PropTypes.object, - /** - * Callback close all drowpdowns - */ - closeDropdowns: PropTypes.func, - }; - - state = { - address: undefined, - ensRecipient: undefined, - value: undefined, - inputEnabled: Device.isIos(), - }; - - componentDidMount = async () => { - const { provider } = Engine.context.NetworkController; - const { address, network, ensRecipient } = this.props; - - const networkHasEnsSupport = this.getNetworkEnsSupport(); - if (networkHasEnsSupport) { - this.ens = new ENS({ provider, network }); - } - if (ensRecipient) { - this.setState({ value: ensRecipient, ensRecipient, address }, () => { - // If we have an ENS name predefined - // We need to resolve it - this.onBlur(); - }); - } else if (address) { - this.setState({ value: address, address }); - } - - // Workaround https://github.com/facebook/react-native/issues/9958 - !this.state.inputEnabled && - setTimeout(() => { - this.setState({ inputEnabled: true }); - }, 100); - }; - - isEnsName = (recipient) => { - if (!isENS(recipient)) { - this.setState({ ensRecipient: undefined }); - return false; - } - return true; - }; - - lookupEnsName = async (recipient) => { - const { address } = this.state; - try { - const resolvedAddress = await this.ens.lookup(recipient.trim()); - if (address !== AppConstants.ZERO_ADDRESS && isValidAddress(resolvedAddress)) { - this.setState({ address: resolvedAddress, ensRecipient: recipient }); - return true; - } - throw new Error(strings('transaction.no_address_for_ens')); - } catch (error) { - this.props.updateToAddressError && this.props.updateToAddressError(error.message); - return false; - } - }; - - onFocus = () => { - const { onFocus, isOpen, openAccountSelect } = this.props; - openAccountSelect && openAccountSelect(!isOpen); - onFocus && onFocus(); - }; - - onBlur = async () => { - const { value } = this.state; - const { onBlur } = this.props; - const isEnsName = this.isEnsName(value) && (await this.lookupEnsName(value)); - if (isEnsName) { - onBlur && onBlur(this.state.address, value); - } else { - this.setState({ address: value, ensRecipient: undefined }); - onBlur && onBlur(value, undefined); - } - }; - - selectAccount(account) { - Keyboard.dismiss(); - this.onChange(account.address); - const { openAccountSelect } = this.props; - openAccountSelect && openAccountSelect(false); - } - - getNetworkEnsSupport = () => { - const { network } = this.props; - return Boolean(networkMap[network]); - }; - - renderAccountName(name) { - if (name !== '') { - return ( - - - {name} - - - ); - } - - return ; - } - - renderOption(account, onPress) { - return ( - - - - - - {this.renderAccountName(account.name)} - - - - - - ); - } - - getVisibleOptions = (value) => { - const { accounts, addressBook, network } = this.props; - const allAddresses = { ...addressBook[network], ...accounts }; - - if (typeof value !== 'undefined' && value.toString().length > 0) { - // If it's a valid address we don't show any suggestion - if (isValidAddress(value)) { - return allAddresses; - } - - const filteredAddresses = {}; - Object.keys(allAddresses).forEach((address) => { - if ( - address.toLowerCase().indexOf(value.toLowerCase()) !== -1 || - (allAddresses[address].name && - allAddresses[address].name.toLowerCase().indexOf(value.toLowerCase()) !== -1) - ) { - filteredAddresses[address] = allAddresses[address]; - } - }); - - if (filteredAddresses.length > 0) { - return filteredAddresses; - } - } - return allAddresses; - }; - - renderOptionList() { - const visibleOptions = this.getVisibleOptions(this.state.value); - return ( - - - - {Object.keys(visibleOptions).map((address) => - this.renderOption(visibleOptions[address], () => { - this.selectAccount(visibleOptions[address]); - }) - )} - - - - ); - } - - onChange = async (value) => { - const { onChange, openAccountSelect } = this.props; - this.setState({ - value, - }); - - const filteredAccounts = this.getVisibleOptions(value); - openAccountSelect && openAccountSelect(Object.keys(filteredAccounts).length > 0); - onChange && onChange(value); - }; - - onInputFocus = () => { - const { openAccountSelect } = this.props; - openAccountSelect && openAccountSelect(true); - }; - - scan = () => { - const { openAccountSelect, closeDropdowns } = this.props; - openAccountSelect && openAccountSelect(false); - this.setState({ isOpen: false }); - this.props.navigation.navigate('QRScanner', { - onScanSuccess: (meta) => { - if (meta.target_address) { - this.onChange(meta.target_address); - closeDropdowns && closeDropdowns(); - } - }, - }); - }; - - closeDropdown = () => { - // nice to have - }; - - render = () => { - const { value, ensRecipient, address } = this.state; - const { placeholder, isOpen } = this.props; - return ( - - - - - - - - - - {!!ensRecipient && {renderShortAddress(address)}} - - - - - - - {isOpen && this.renderOptionList()} - - ); - }; -} - -const mapStateToProps = (state) => ({ - addressBook: state.engine.backgroundState.AddressBookController.addressBook, - accounts: state.engine.backgroundState.PreferencesController.identities, - activeAddress: state.engine.backgroundState.PreferencesController.activeAddress, - network: state.engine.backgroundState.NetworkController.network, -}); - -export default connect(mapStateToProps)(AccountInput); diff --git a/app/components/UI/AccountInput/index.test.tsx b/app/components/UI/AccountInput/index.test.tsx deleted file mode 100644 index 9a595c1a4f1..00000000000 --- a/app/components/UI/AccountInput/index.test.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import AccountInput from './'; -import configureMockStore from 'redux-mock-store'; -import { Provider } from 'react-redux'; -import { shallow } from 'enzyme'; - -const mockStore = configureMockStore(); -const store = mockStore({}); - -describe('AccountInput', () => { - it('should render correctly', () => { - const wrapper = shallow( - - - - ); - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/app/components/UI/AccountList/AccountElement/index.js b/app/components/UI/AccountList/AccountElement/index.js index 66ada80a18f..33c61205680 100644 --- a/app/components/UI/AccountList/AccountElement/index.js +++ b/app/components/UI/AccountList/AccountElement/index.js @@ -2,81 +2,83 @@ import React, { PureComponent } from 'react'; import Identicon from '../../Identicon'; import PropTypes from 'prop-types'; import { TouchableOpacity, StyleSheet, Text, View } from 'react-native'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles } from '../../../../styles/common'; import { renderFromWei } from '../../../../util/number'; import { getTicker } from '../../../../util/transactions'; import { isDefaultAccountName } from '../../../../util/ENSUtils'; import { strings } from '../../../../../locales/i18n'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; import { connect } from 'react-redux'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; const EMPTY = '0x0'; const BALANCE_KEY = 'balance'; -const styles = StyleSheet.create({ - account: { - borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - flexDirection: 'row', - paddingHorizontal: 20, - paddingVertical: 20, - height: 80, - }, - disabledAccount: { - opacity: 0.5, - }, - accountInfo: { - marginLeft: 15, - marginRight: 0, - flex: 1, - flexDirection: 'row', - }, - accountLabel: { - fontSize: 18, - color: colors.fontPrimary, - ...fontStyles.normal, - }, - accountBalanceWrapper: { - display: 'flex', - flexDirection: 'row', - }, - accountBalance: { - paddingTop: 5, - fontSize: 12, - color: colors.fontSecondary, - ...fontStyles.normal, - }, - accountBalanceError: { - color: colors.fontError, - marginLeft: 4, - }, - importedView: { - flex: 0.5, - alignItems: 'center', - marginTop: 2, - }, - accountMain: { - flex: 1, - flexDirection: 'column', - }, - selectedWrapper: { - flex: 0.2, - alignItems: 'flex-end', - }, - importedText: { - color: colors.grey400, - fontSize: 10, - ...fontStyles.bold, - }, - importedWrapper: { - width: 73, - paddingHorizontal: 10, - paddingVertical: 3, - borderRadius: 10, - borderWidth: 1, - borderColor: colors.grey400, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + account: { + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + flexDirection: 'row', + paddingHorizontal: 20, + paddingVertical: 20, + height: 80, + }, + disabledAccount: { + opacity: 0.5, + }, + accountInfo: { + marginLeft: 15, + marginRight: 0, + flex: 1, + flexDirection: 'row', + }, + accountLabel: { + fontSize: 18, + color: colors.text.default, + ...fontStyles.normal, + }, + accountBalanceWrapper: { + display: 'flex', + flexDirection: 'row', + }, + accountBalance: { + paddingTop: 5, + fontSize: 12, + color: colors.text.alternative, + ...fontStyles.normal, + }, + accountBalanceError: { + color: colors.error.default, + marginLeft: 4, + }, + importedView: { + flex: 0.5, + alignItems: 'center', + marginTop: 2, + }, + accountMain: { + flex: 1, + flexDirection: 'column', + }, + selectedWrapper: { + flex: 0.2, + alignItems: 'flex-end', + }, + importedText: { + color: colors.text.alternative, + fontSize: 10, + ...fontStyles.bold, + }, + importedWrapper: { + width: 73, + paddingHorizontal: 10, + paddingVertical: 3, + borderRadius: 10, + borderWidth: 1, + borderColor: colors.icon.default, + }, + }); /** * View that renders specific account element in AccountList @@ -121,7 +123,10 @@ class AccountElement extends PureComponent { render() { const { disabled, updatedBalanceFromStore, ticker } = this.props; const { address, name, ens, isSelected, isImported, balanceError } = this.props.item; - const selected = isSelected ? : null; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + const selected = isSelected ? : null; const imported = isImported ? ( @@ -187,4 +192,6 @@ const mapStateToProps = ( }; }; +AccountElement.contextType = ThemeContext; + export default connect(mapStateToProps)(AccountElement); diff --git a/app/components/UI/AccountList/index.js b/app/components/UI/AccountList/index.js index ad97525dc87..9adf0876ee6 100644 --- a/app/components/UI/AccountList/index.js +++ b/app/components/UI/AccountList/index.js @@ -12,7 +12,7 @@ import { View, SafeAreaView, } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import Device from '../../../util/device'; import { strings } from '../../../../locales/i18n'; import { toChecksumAddress } from 'ethereumjs-util'; @@ -23,53 +23,54 @@ import { ANALYTICS_EVENT_OPTS } from '../../../util/analytics'; import { doENSReverseLookup } from '../../../util/ENSUtils'; import AccountElement from './AccountElement'; import { connect } from 'react-redux'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - borderTopLeftRadius: 10, - borderTopRightRadius: 10, - minHeight: 450, - }, - titleWrapper: { - width: '100%', - height: 33, - alignItems: 'center', - justifyContent: 'center', - borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - }, - dragger: { - width: 48, - height: 5, - borderRadius: 4, - backgroundColor: colors.grey400, - opacity: Device.isAndroid() ? 0.6 : 0.5, - }, - accountsWrapper: { - flex: 1, - }, - footer: { - height: Device.isIphoneX() ? 140 : 110, - paddingBottom: Device.isIphoneX() ? 30 : 0, - justifyContent: 'center', - flexDirection: 'column', - alignItems: 'center', - }, - btnText: { - fontSize: 14, - color: colors.blue, - ...fontStyles.normal, - }, - footerButton: { - width: '100%', - height: 55, - alignItems: 'center', - justifyContent: 'center', - borderTopWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + borderTopLeftRadius: 10, + borderTopRightRadius: 10, + minHeight: 450, + }, + titleWrapper: { + width: '100%', + height: 33, + alignItems: 'center', + justifyContent: 'center', + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + }, + dragger: { + width: 48, + height: 5, + borderRadius: 4, + backgroundColor: colors.border.default, + }, + accountsWrapper: { + flex: 1, + }, + footer: { + height: Device.isIphoneX() ? 140 : 110, + paddingBottom: Device.isIphoneX() ? 30 : 0, + justifyContent: 'center', + flexDirection: 'column', + alignItems: 'center', + }, + btnText: { + fontSize: 14, + color: colors.primary.default, + ...fontStyles.normal, + }, + footerButton: { + width: '100%', + height: 55, + alignItems: 'center', + justifyContent: 'center', + borderTopWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + }, + }); /** * View that contains the list of all the available accounts @@ -353,6 +354,9 @@ class AccountList extends PureComponent { render() { const { orderedAccounts } = this.state; const { enableAccountsAddition } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -375,7 +379,7 @@ class AccountList extends PureComponent { onPress={this.addAccount} > {this.state.loading ? ( - + ) : ( {strings('accounts.create_new_account')} )} @@ -394,6 +398,8 @@ class AccountList extends PureComponent { } } +AccountList.contextType = ThemeContext; + const mapStateToProps = (state) => ({ accounts: state.engine.backgroundState.AccountTrackerController.accounts, thirdPartyApiMode: state.privacy.thirdPartyApiMode, diff --git a/app/components/UI/AccountOverview/index.js b/app/components/UI/AccountOverview/index.js index 0ec46780901..bc23d6e2be3 100644 --- a/app/components/UI/AccountOverview/index.js +++ b/app/components/UI/AccountOverview/index.js @@ -26,78 +26,81 @@ import { isSwapsAllowed } from '../Swaps/utils'; import Identicon from '../Identicon'; import AssetActionButton from '../AssetActionButton'; import EthereumAddress from '../EthereumAddress'; -import { colors, fontStyles, baseStyles } from '../../../styles/common'; +import { fontStyles, baseStyles } from '../../../styles/common'; import { allowedToBuy } from '../FiatOrders'; import AssetSwapButton from '../Swaps/components/AssetSwapButton'; import ClipboardManager from '../../../core/ClipboardManager'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - scrollView: { - backgroundColor: colors.white, - }, - wrapper: { - paddingTop: 20, - paddingHorizontal: 20, - paddingBottom: 0, - alignItems: 'center', - }, - info: { - justifyContent: 'center', - alignItems: 'center', - textAlign: 'center', - }, - data: { - textAlign: 'center', - paddingTop: 7, - }, - label: { - fontSize: 24, - textAlign: 'center', - ...fontStyles.normal, - }, - labelInput: { - marginBottom: Device.isAndroid() ? -10 : 0, - }, - addressWrapper: { - backgroundColor: colors.blue000, - borderRadius: 40, - marginTop: 20, - marginBottom: 20, - paddingVertical: 7, - paddingHorizontal: 15, - }, - address: { - fontSize: 12, - color: colors.grey400, - ...fontStyles.normal, - letterSpacing: 0.8, - }, - amountFiat: { - fontSize: 12, - paddingTop: 5, - color: colors.fontSecondary, - ...fontStyles.normal, - }, - identiconBorder: { - borderRadius: 80, - borderWidth: 2, - padding: 2, - borderColor: colors.blue, - }, - onboardingWizardLabel: { - borderWidth: 2, - borderRadius: 4, - paddingVertical: Device.isIos() ? 2 : -4, - paddingHorizontal: Device.isIos() ? 5 : 5, - top: Device.isIos() ? 0 : -2, - }, - actions: { - flex: 1, - justifyContent: 'center', - alignItems: 'flex-start', - flexDirection: 'row', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + scrollView: { + backgroundColor: colors.background.default, + }, + wrapper: { + paddingTop: 20, + paddingHorizontal: 20, + paddingBottom: 0, + alignItems: 'center', + }, + info: { + justifyContent: 'center', + alignItems: 'center', + textAlign: 'center', + }, + data: { + textAlign: 'center', + paddingTop: 7, + }, + label: { + fontSize: 24, + textAlign: 'center', + ...fontStyles.normal, + color: colors.text.default, + }, + labelInput: { + marginBottom: Device.isAndroid() ? -10 : 0, + }, + addressWrapper: { + backgroundColor: colors.primary.muted, + borderRadius: 40, + marginTop: 20, + marginBottom: 20, + paddingVertical: 7, + paddingHorizontal: 15, + }, + address: { + fontSize: 12, + color: colors.text.default, + ...fontStyles.normal, + letterSpacing: 0.8, + }, + amountFiat: { + fontSize: 12, + paddingTop: 5, + color: colors.text.alternative, + ...fontStyles.normal, + }, + identiconBorder: { + borderRadius: 80, + borderWidth: 2, + padding: 2, + borderColor: colors.primary.default, + }, + onboardingWizardLabel: { + borderWidth: 2, + borderRadius: 4, + paddingVertical: Device.isIos() ? 2 : -4, + paddingHorizontal: Device.isIos() ? 5 : 5, + top: Device.isIos() ? 0 : -2, + }, + actions: { + flex: 1, + justifyContent: 'center', + alignItems: 'flex-start', + flexDirection: 'row', + }, + }); /** * View that's part of the component @@ -302,6 +305,9 @@ class AccountOverview extends PureComponent { chainId, swapsIsLive, } = this.props; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance || 'light'; + const styles = createStyles(colors); const fiatBalance = `${renderFiat(Engine.getTotalFiatAccountBalance(), currentCurrency)}`; @@ -333,7 +339,9 @@ class AccountOverview extends PureComponent { styles.label, styles.labelInput, styles.onboardingWizardLabel, - onboardingWizard ? { borderColor: colors.blue } : { borderColor: colors.white }, + onboardingWizard + ? { borderColor: colors.primary.default } + : { borderColor: colors.background.default }, ]} editable={accountLabelEditable} onChangeText={this.onAccountLabelChange} @@ -347,6 +355,8 @@ class AccountOverview extends PureComponent { autoCapitalize={'none'} autoCorrect={false} numberOfLines={1} + placeholderTextColor={colors.text.muted} + keyboardAppearance={themeAppearance} /> ) : ( @@ -355,8 +365,8 @@ class AccountOverview extends PureComponent { styles.label, styles.onboardingWizardLabel, onboardingWizard - ? { borderColor: colors.blue } - : { borderColor: colors.white }, + ? { borderColor: colors.primary.default } + : { borderColor: colors.background.default }, ]} numberOfLines={1} testID={'edit-account-label'} @@ -424,4 +434,6 @@ const mapDispatchToProps = (dispatch) => ({ toggleReceiveModal: (asset) => dispatch(toggleReceiveModal(asset)), }); +AccountOverview.contextType = ThemeContext; + export default connect(mapStateToProps, mapDispatchToProps)(AccountOverview); diff --git a/app/components/UI/AccountSelect/__snapshots__/index.test.tsx.snap b/app/components/UI/AccountSelect/__snapshots__/index.test.tsx.snap deleted file mode 100644 index b92f86f85ee..00000000000 --- a/app/components/UI/AccountSelect/__snapshots__/index.test.tsx.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AccountSelect should render correctly 1`] = ``; diff --git a/app/components/UI/AccountSelect/index.js b/app/components/UI/AccountSelect/index.js deleted file mode 100644 index eb36bcc3262..00000000000 --- a/app/components/UI/AccountSelect/index.js +++ /dev/null @@ -1,227 +0,0 @@ -import React, { PureComponent } from 'react'; -import Identicon from '../Identicon'; -import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; -import PropTypes from 'prop-types'; -import { StyleSheet, Text, TouchableOpacity, View, ScrollView } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; -import { connect } from 'react-redux'; -import { hexToBN, weiToFiat, renderFromWei } from '../../../util/number'; -import { getTicker } from '../../../util/transactions'; -import { safeToChecksumAddress } from '../../../util/address'; - -const styles = StyleSheet.create({ - root: { - flex: 1, - }, - componentContainer: { - position: 'absolute', - zIndex: 100, - width: '100%', - marginTop: 75, - maxHeight: 200, - borderColor: colors.grey100, - borderRadius: 4, - borderWidth: 1, - elevation: 11, - }, - activeOption: { - backgroundColor: colors.white, - borderColor: colors.grey100, - borderRadius: 4, - borderWidth: 1, - position: 'relative', - }, - option: { - flexDirection: 'row', - paddingHorizontal: 10, - paddingVertical: 8, - }, - info: { - ...fontStyles.normal, - fontSize: 12, - lineHeight: 16, - }, - name: { - ...fontStyles.bold, - fontSize: 16, - marginBottom: 4, - }, - icon: { - paddingRight: 8, - paddingLeft: 2, - paddingTop: 1.5, - }, - content: { - flex: 1, - paddingHorizontal: 8, - }, - arrow: { - color: colors.grey100, - position: 'absolute', - right: 10, - top: 25, - }, - optionList: { - backgroundColor: colors.white, - borderColor: colors.grey100, - borderRadius: 4, - borderWidth: 1, - paddingBottom: 12, - paddingTop: 10, - top: 0, - left: 0, - right: 0, - elevation: 10, - width: '100%', - }, -}); - -/** - * PureComponent that renders a select element populated with accounts from the current keychain - */ -class AccountSelect extends PureComponent { - static propTypes = { - /** - * List of accounts from the AccountTrackerController - */ - accounts: PropTypes.object, - /** - * List of accounts from the PreferencesController - */ - identities: PropTypes.object, - /** - * Address of the currently-active account from the PreferencesController - */ - selectedAddress: PropTypes.string, - /** - * ETH-to-current currency conversion rate from CurrencyRateController - */ - conversionRate: PropTypes.number, - /** - * Currency code for currently-selected currency from CurrencyRateController - */ - currentCurrency: PropTypes.string, - /** - * Whether selectable dropdown is enabled or not - */ - enabled: PropTypes.bool, - /** - * Callback triggered when a new address is selected - */ - onChange: PropTypes.func, - /** - * Address of the currently-selected account - */ - value: PropTypes.string, - /** - * Callback to open accounts dropdown - */ - openAccountSelect: PropTypes.func, - /** - * Whether accounts dropdown is opened - */ - isOpen: PropTypes.bool, - /** - * Primary currency, either ETH or Fiat - */ - primaryCurrency: PropTypes.string, - /** - * Current provider ticker - */ - ticker: PropTypes.string, - }; - - static defaultProps = { - enabled: true, - }; - - componentDidMount() { - const { onChange, selectedAddress } = this.props; - onChange && onChange(selectedAddress); - } - - renderActiveOption() { - const { selectedAddress, accounts, identities, value, isOpen, openAccountSelect } = this.props; - const targetAddress = safeToChecksumAddress(value) || selectedAddress; - const account = { ...identities[targetAddress], ...accounts[targetAddress] }; - return ( - - {this.props.enabled && } - {this.renderOption(account, () => { - openAccountSelect && openAccountSelect(!isOpen); - })} - - ); - } - - renderOption(account, onPress) { - const { conversionRate, currentCurrency, primaryCurrency, ticker } = this.props; - const balance = hexToBN(account.balance); - - // render balances according to selected 'primaryCurrency' - let mainBalance, secondaryBalance; - if (primaryCurrency === 'ETH') { - mainBalance = `${renderFromWei(balance)} ${getTicker(ticker)}`; - secondaryBalance = weiToFiat(balance, conversionRate, currentCurrency); - } else { - mainBalance = weiToFiat(balance, conversionRate, currentCurrency); - secondaryBalance = `${renderFromWei(balance)} ${getTicker(ticker)}`; - } - - return ( - - - - - - - {account.name} - - {mainBalance} - {!!secondaryBalance && {secondaryBalance}} - - - ); - } - - renderOptionList() { - const { accounts, identities, onChange, openAccountSelect } = this.props; - return ( - - - {Object.keys(identities).map((address) => - this.renderOption({ ...identities[address], ...accounts[address] }, () => { - this.setState({ value: address }); - openAccountSelect && openAccountSelect(true); - onChange && onChange(address); - }) - )} - - - ); - } - - render = () => ( - - {this.renderActiveOption()} - {this.props.isOpen && this.props.enabled && this.renderOptionList()} - - ); -} - -const mapStateToProps = (state) => ({ - accounts: state.engine.backgroundState.AccountTrackerController.accounts, - conversionRate: state.engine.backgroundState.CurrencyRateController.conversionRate, - identities: state.engine.backgroundState.PreferencesController.identities, - currentCurrency: state.engine.backgroundState.CurrencyRateController.currentCurrency, - selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress, - primaryCurrency: state.settings.primaryCurrency, - ticker: state.engine.backgroundState.NetworkController.provider.ticker, -}); - -export default connect(mapStateToProps)(AccountSelect); diff --git a/app/components/UI/AccountSelect/index.test.tsx b/app/components/UI/AccountSelect/index.test.tsx deleted file mode 100644 index e319cfc2efb..00000000000 --- a/app/components/UI/AccountSelect/index.test.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import AccountSelect from './'; -import configureMockStore from 'redux-mock-store'; -import { Provider } from 'react-redux'; -import { shallow } from 'enzyme'; - -const mockStore = configureMockStore(); -const store = mockStore({}); - -describe('AccountSelect', () => { - it('should render correctly', () => { - const wrapper = shallow( - - - - ); - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/app/components/UI/ActionModal/ActionContent/index.js b/app/components/UI/ActionModal/ActionContent/index.js index 06f9f79202d..d0e54424476 100644 --- a/app/components/UI/ActionModal/ActionContent/index.js +++ b/app/components/UI/ActionModal/ActionContent/index.js @@ -1,44 +1,45 @@ import React from 'react'; import PropTypes from 'prop-types'; import { StyleSheet, View } from 'react-native'; -import { colors } from '../../../../styles/common'; import StyledButton from '../../StyledButton'; import { strings } from '../../../../../locales/i18n'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - viewWrapper: { - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - marginHorizontal: 24, - }, - viewContainer: { - width: '100%', - backgroundColor: colors.white, - borderRadius: 10, - }, - actionHorizontalContainer: { - flexDirection: 'row', - padding: 16, - borderTopWidth: 1, - borderTopColor: colors.grey200, - }, - actionVerticalContainer: { - flexDirection: 'column', - paddingHorizontal: 16, - paddingVertical: 8, - }, - childrenContainer: { - flexDirection: 'row', - alignItems: 'center', - }, - button: { - margin: 8, - }, - buttonHorizontal: { - flex: 1, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + viewWrapper: { + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + marginHorizontal: 24, + }, + viewContainer: { + width: '100%', + backgroundColor: colors.background.default, + borderRadius: 10, + }, + actionHorizontalContainer: { + flexDirection: 'row', + padding: 16, + borderTopWidth: 1, + borderTopColor: colors.border.muted, + }, + actionVerticalContainer: { + flexDirection: 'column', + paddingHorizontal: 16, + paddingVertical: 8, + }, + childrenContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + button: { + margin: 8, + }, + buttonHorizontal: { + flex: 1, + }, + }); /** * View that renders the content of an action modal @@ -65,6 +66,9 @@ export default function ActionContent({ childrenContainerStyle, verticalButtons, }) { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ( diff --git a/app/components/UI/ActionModal/__snapshots__/index.test.tsx.snap b/app/components/UI/ActionModal/__snapshots__/index.test.tsx.snap index b55b1e169b0..04225725dad 100644 --- a/app/components/UI/ActionModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/ActionModal/__snapshots__/index.test.tsx.snap @@ -7,8 +7,8 @@ exports[`ActionModal should render correctly 1`] = ` animationOut="slideOutDown" animationOutTiming={300} avoidKeyboard={true} - backdropColor="black" - backdropOpacity={0.7} + backdropColor="#00000099" + backdropOpacity={1} backdropTransitionInTiming={300} backdropTransitionOutTiming={300} coverScreen={true} diff --git a/app/components/UI/ActionModal/index.js b/app/components/UI/ActionModal/index.js index 62a7106c7f2..85a857ceb3f 100644 --- a/app/components/UI/ActionModal/index.js +++ b/app/components/UI/ActionModal/index.js @@ -4,6 +4,7 @@ import { StyleSheet } from 'react-native'; import Modal from 'react-native-modal'; import { strings } from '../../../../locales/i18n'; import ActionContent from './ActionContent'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; const styles = StyleSheet.create({ modal: { @@ -39,6 +40,8 @@ export default function ActionModal({ propagateSwipe, cancelButtonDisabled, }) { + const { colors } = useAppThemeFromContext() || mockTheme; + return ( - {confirmed ? : confirmText} + {confirmed ? ( + + ) : ( + confirmText + )} )} diff --git a/app/components/UI/AddCustomCollectible/index.tsx b/app/components/UI/AddCustomCollectible/index.tsx index 1ae72e28511..eb5965a7d9d 100644 --- a/app/components/UI/AddCustomCollectible/index.tsx +++ b/app/components/UI/AddCustomCollectible/index.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import { useSelector } from 'react-redux'; import { Alert, Text, TextInput, View, StyleSheet } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import Engine from '../../../core/Engine'; import { strings } from '../../../../locales/i18n'; import { isValidAddress } from 'ethereumjs-util'; @@ -9,32 +9,36 @@ import ActionView from '../ActionView'; import { isSmartContractAddress } from '../../../util/transactions'; import Device from '../../../util/device'; import AnalyticsV2 from '../../../util/analyticsV2'; - -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - }, - rowWrapper: { - padding: 20, - }, - rowTitleText: { - paddingBottom: 3, - ...(fontStyles.normal as any), - }, - textInput: { - borderWidth: 1, - borderRadius: 4, - borderColor: colors.grey100, - padding: 16, - ...(fontStyles.normal as any), - }, - warningText: { - marginTop: 15, - color: colors.red, - ...(fontStyles.normal as any), - }, -}); +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; + +const createStyles = (colors: any) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + rowWrapper: { + padding: 20, + }, + rowTitleText: { + paddingBottom: 3, + ...(fontStyles.normal as any), + color: colors.text.default, + }, + textInput: { + borderWidth: 1, + borderRadius: 4, + borderColor: colors.border.default, + padding: 16, + ...(fontStyles.normal as any), + color: colors.text.default, + }, + warningText: { + marginTop: 15, + color: colors.error.default, + ...(fontStyles.normal as any), + }, + }); interface AddCustomCollectibleProps { navigation?: any; @@ -51,6 +55,8 @@ const AddCustomCollectible = ({ navigation, collectibleContract }: AddCustomColl const [warningTokenId, setWarningTokenId] = useState(''); const [inputWidth, setInputWidth] = useState(Device.isAndroid() ? '99%' : undefined); const assetTokenIdInput = React.createRef() as any; + const { colors, themeAppearance } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const selectedAddress = useSelector( (state: any) => state.engine.backgroundState.PreferencesController.selectedAddress @@ -187,12 +193,13 @@ const AddCustomCollectible = ({ navigation, collectibleContract }: AddCustomColl {warningAddress} @@ -211,7 +218,8 @@ const AddCustomCollectible = ({ navigation, collectibleContract }: AddCustomColl onSubmitEditing={addCollectible} returnKeyType={'done'} placeholder={strings('collectible.id_placeholder')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} + keyboardAppearance={themeAppearance} /> {warningTokenId} diff --git a/app/components/UI/AddCustomNetwork/__snapshots__/index.test.tsx.snap b/app/components/UI/AddCustomNetwork/__snapshots__/index.test.tsx.snap index 7d82f7e0e3d..1cfe7872351 100644 --- a/app/components/UI/AddCustomNetwork/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/AddCustomNetwork/__snapshots__/index.test.tsx.snap @@ -152,7 +152,7 @@ exports[`AddCustomNetwork should render correctly 1`] = ` + StyleSheet.create({ + root: { + backgroundColor: colors.background.default, + paddingTop: 24, + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + minHeight: 200, + paddingBottom: Device.isIphoneX() ? 20 : 0, + }, + accountCardWrapper: { + borderWidth: 1, + borderColor: colors.border.default, + borderRadius: 10, + padding: 16, + margin: 24, + }, + intro: { + fontSize: Device.isSmallDevice() ? 18 : 24, + marginBottom: 16, + marginTop: 16, + marginRight: 24, + marginLeft: 24, + }, + warning: { + paddingHorizontal: 24, + fontSize: 13, + width: '100%', + paddingBottom: 12, + }, + warningSubtext: { + lineHeight: 20, + paddingHorizontal: 24, + fontSize: 13, + width: '100%', + }, + actionContainer: { + flex: 0, + flexDirection: 'row', + padding: 24, + }, + button: { + flex: 1, + }, + cancel: { + marginRight: 8, + }, + confirm: { + marginLeft: 8, + }, + actionTouchable: { + flexDirection: 'column', + alignItems: 'center', + }, + viewDetailsText: { + fontSize: 12, + lineHeight: 16, + }, + textSection: { + flexDirection: 'row', + paddingBottom: 7, + }, + textSectionLast: { + flexDirection: 'row', + }, + networkInfoTitle: { + paddingRight: 10, + }, + networkInfoValue: { + flex: 1, + fontSize: 13, + }, + detailsBackButton: { + height: 24, + width: 24, + justifyContent: 'space-around', + alignItems: 'center', + textAlign: 'center', + padding: 24, + }, + detailsBackIcon: { + width: 24, + height: 24, + color: colors.text.default, + textAlign: 'center', + }, + detailsContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + flexAux: { + flex: 1, + }, + alertContainer: { + marginHorizontal: 24, + marginBottom: 16, + }, + alertIcon: { + fontSize: 20, + ...fontStyles.bold, + color: colors.warning.default, + marginRight: 6, + }, + alertText: { + lineHeight: 18, + color: colors.text.default, + }, + }); /** * Account access approval component */ const AddCustomNetwork = ({ customNetworkInformation, currentPageInformation, onCancel, onConfirm }) => { const [viewDetails, setViewDetails] = useState(false); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); /** * Calls onConfirm callback and analytics to track connect confirmed event @@ -241,7 +246,7 @@ const AddCustomNetwork = ({ customNetworkInformation, currentPageInformation, on renderIcon={() => } > - + {alertText} {'\n'} diff --git a/app/components/UI/AddCustomToken/__snapshots__/index.test.tsx.snap b/app/components/UI/AddCustomToken/__snapshots__/index.test.tsx.snap index 40e966cac68..7a20949d583 100644 --- a/app/components/UI/AddCustomToken/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/AddCustomToken/__snapshots__/index.test.tsx.snap @@ -40,7 +40,7 @@ exports[`AddCustomToken should render correctly 1`] = ` onPress={[Function]} style={ Object { - "color": "#037dd6", + "color": "#037DD6", } } suppressHighlighting={true} @@ -61,6 +61,7 @@ exports[`AddCustomToken should render correctly 1`] = ` + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + rowWrapper: { + padding: 20, + }, + textInput: { + borderWidth: 1, + borderRadius: 4, + borderColor: colors.border.default, + padding: 16, + ...fontStyles.normal, + color: colors.text.default, + }, + inputLabel: { + ...fontStyles.normal, + color: colors.text.default, + }, + warningText: { + marginTop: 15, + color: colors.error.default, + ...fontStyles.normal, + }, + warningContainer: { marginHorizontal: 20, marginTop: 20, paddingRight: 0 }, + warningLink: { color: colors.primary.default }, + }); /** * Copmonent that provides ability to add custom tokens. @@ -191,36 +198,45 @@ export default class AddCustomToken extends PureComponent { current && current.focus(); }; - renderWarning = () => ( - - {strings('add_asset.warning_body_description')} - { - // TODO: This functionality exists in a bunch of other places. We need to unify this into a utils function - this.props.navigation.navigate('Webview', { - screen: 'SimpleWebview', - params: { - url: AppConstants.URLS.SECURITY, - title: strings('add_asset.security_tips'), - }, - }); - }} - style={styles.warningLink} - testID={'add-asset-warning-message'} - > - {strings('add_asset.warning_link')} - - - } - /> - ); + renderWarning = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + {strings('add_asset.warning_body_description')} + { + // TODO: This functionality exists in a bunch of other places. We need to unify this into a utils function + this.props.navigation.navigate('Webview', { + screen: 'SimpleWebview', + params: { + url: AppConstants.URLS.SECURITY, + title: strings('add_asset.security_tips'), + }, + }); + }} + style={styles.warningLink} + testID={'add-asset-warning-message'} + > + {strings('add_asset.warning_link')} + + + } + /> + ); + }; render = () => { const { address, symbol, decimals } = this.state; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance || 'light'; + const styles = createStyles(colors); + return ( {this.renderWarning()} - {strings('token.token_address')} + {strings('token.token_address')} {this.state.warningAddress} - {strings('token.token_symbol')} + {strings('token.token_symbol')} {this.state.warningSymbol} - {strings('token.token_precision')} + {strings('token.token_precision')} {this.state.warningDecimals} @@ -294,3 +313,5 @@ export default class AddCustomToken extends PureComponent { ); }; } + +AddCustomToken.contextType = ThemeContext; diff --git a/app/components/UI/AnimatedSpinner/__snapshots__/index.test.tsx.snap b/app/components/UI/AnimatedSpinner/__snapshots__/index.test.tsx.snap index 9febbfdac24..6569b9ede44 100644 --- a/app/components/UI/AnimatedSpinner/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/AnimatedSpinner/__snapshots__/index.test.tsx.snap @@ -4,7 +4,7 @@ exports[`AnimatedSpinner should render correctly 1`] = ` + StyleSheet.create({ + view: { + position: 'relative', + height: Device.isAndroid() ? 41.5 : 40, + width: Device.isAndroid() ? 41.5 : 40, + top: Device.isAndroid() ? -6 : -5.5, + left: Device.isAndroid() ? -6 : -5.5, + }, + static: { + borderWidth: 3.5, + borderColor: colors.primary.default, + borderRadius: 64, + width: 36, + height: 36, + }, + }); export default class AnimatedSpinner extends PureComponent { spinValue = new Animated.Value(0); @@ -67,6 +68,8 @@ export default class AnimatedSpinner extends PureComponent { }; render() { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); const spin = this.spinValue.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '360deg'], @@ -75,9 +78,11 @@ export default class AnimatedSpinner extends PureComponent { return ( - + ); } } + +AnimatedSpinner.contextType = ThemeContext; diff --git a/app/components/UI/AnimatedTransactionModal/index.js b/app/components/UI/AnimatedTransactionModal/index.js index 1a57d1f2c67..199f1ddc967 100644 --- a/app/components/UI/AnimatedTransactionModal/index.js +++ b/app/components/UI/AnimatedTransactionModal/index.js @@ -1,26 +1,27 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { StyleSheet, Animated, Easing } from 'react-native'; -import { colors } from '../../../styles/common'; import Device from '../../../util/device'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - root: { - backgroundColor: colors.white, - minHeight: 200, - borderTopLeftRadius: 20, - borderTopRightRadius: 20, - paddingBottom: Device.isIphoneX() ? 24 : 0, - }, - transactionEdit: { - position: 'absolute', - width: '100%', - height: '100%', - }, - transactionReview: { - paddingTop: 24, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + root: { + backgroundColor: colors.background.default, + minHeight: 200, + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + paddingBottom: Device.isIphoneX() ? 24 : 0, + }, + transactionEdit: { + position: 'absolute', + width: '100%', + height: '100%', + }, + transactionReview: { + paddingTop: 24, + }, + }); //This is a placeholder to represent the custom gas modal. //TODO this custom gas modal needs to be removed from the animated tx modal. @@ -198,6 +199,8 @@ class AnimatedTransactionModal extends PureComponent { toAdvancedFrom, } = this.state; const { ready, children } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); const components = React.Children.toArray(children); let gasTransformStyle; let modalTransformStyle; @@ -259,4 +262,6 @@ class AnimatedTransactionModal extends PureComponent { }; } +AnimatedTransactionModal.contextType = ThemeContext; + export default AnimatedTransactionModal; diff --git a/app/components/UI/ApproveTransactionReview/AddNickname/index.tsx b/app/components/UI/ApproveTransactionReview/AddNickname/index.tsx index 36a81d2e01a..e8222aadbc0 100644 --- a/app/components/UI/ApproveTransactionReview/AddNickname/index.tsx +++ b/app/components/UI/ApproveTransactionReview/AddNickname/index.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { SafeAreaView, View, StyleSheet, TextInput, TouchableOpacity } from 'react-native'; import AntDesignIcon from 'react-native-vector-icons/AntDesign'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles } from '../../../../styles/common'; import EthereumAddress from '../../EthereumAddress'; import Engine from '../../../../core/Engine'; import AnalyticsV2 from '../../../../util/analyticsV2'; @@ -19,82 +19,86 @@ import { showAlert } from '../../../../actions/alert'; import ClipboardManager from '../../../../core/ClipboardManager'; import Header from '../AddNickNameHeader'; import ShowBlockExplorer from '../ShowBlockExplorer'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: colors.white, - }, - headerWrapper: { - position: 'relative', - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - marginHorizontal: 15, - marginVertical: 5, - paddingVertical: 10, - }, - icon: { - position: 'absolute', - right: 0, - padding: 10, - }, - headerText: { - color: colors.black, - textAlign: 'center', - fontSize: 15, - }, - addressWrapperPrimary: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - marginBottom: 10, - }, - addressWrapper: { - backgroundColor: colors.blue100, - flexDirection: 'row', - alignItems: 'center', - borderRadius: 40, - paddingVertical: 10, - paddingHorizontal: 15, - width: '90%', - }, - address: { - fontSize: 12, - color: colors.grey400, - letterSpacing: 0.8, - marginLeft: 10, - }, - label: { - fontSize: 14, - paddingVertical: 12, - color: colors.fontPrimary, - }, - input: { - ...fontStyles.normal, - fontSize: 12, - borderColor: colors.grey200, - borderRadius: 5, - borderWidth: 2, - padding: 10, - flexDirection: 'row', - alignItems: 'center', - }, - bodyWrapper: { - marginHorizontal: 20, - marginBottom: 'auto', - }, - updateButton: { - marginHorizontal: 20, - }, - addressIdenticon: { - alignItems: 'center', - marginVertical: 10, - }, - actionIcon: { - color: colors.blue, - }, -}); +const createStyles = (colors: any) => + StyleSheet.create({ + container: { + flex: 1, + backgroundColor: colors.background.default, + }, + headerWrapper: { + position: 'relative', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + marginHorizontal: 15, + marginVertical: 5, + paddingVertical: 10, + }, + icon: { + position: 'absolute', + right: 0, + padding: 10, + color: colors.icon.default, + }, + headerText: { + color: colors.text.default, + textAlign: 'center', + fontSize: 15, + }, + addressWrapperPrimary: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginBottom: 10, + }, + addressWrapper: { + backgroundColor: colors.primary.muted, + flexDirection: 'row', + alignItems: 'center', + borderRadius: 40, + paddingVertical: 10, + paddingHorizontal: 15, + width: '90%', + }, + address: { + fontSize: 12, + color: colors.text.default, + letterSpacing: 0.8, + marginLeft: 10, + }, + label: { + fontSize: 14, + paddingVertical: 12, + color: colors.text.default, + }, + input: { + ...fontStyles.normal, + fontSize: 12, + borderColor: colors.border.default, + borderRadius: 5, + borderWidth: 2, + padding: 10, + flexDirection: 'row', + alignItems: 'center', + color: colors.text.default, + }, + bodyWrapper: { + marginHorizontal: 20, + marginBottom: 'auto', + }, + updateButton: { + marginHorizontal: 20, + }, + addressIdenticon: { + alignItems: 'center', + marginVertical: 10, + }, + actionIcon: { + color: colors.primary.default, + }, + }); interface AddNicknameProps { onUpdateContractNickname: () => void; @@ -136,6 +140,8 @@ const AddNickname = (props: AddNicknameProps) => { const [newNickname, setNewNickname] = useState(nickname); const [isBlockExplorerVisible, setIsBlockExplorerVisible] = useState(false); const [showFullAddress, setShowFullAddress] = useState(false); + const { colors, themeAppearance } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const copyContractAddress = async () => { await ClipboardManager.setString(contractAddress); @@ -202,7 +208,7 @@ const AddNickname = (props: AddNicknameProps) => { onPress={copyContractAddress} onLongPress={showFullAddressModal} > - + { autoCorrect={false} onChangeText={setNewNickname} placeholder={strings('nickname.name_placeholder')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} spellCheck={false} numberOfLines={1} style={styles.input} value={newNickname} testID={'contract-name-input'} + keyboardAppearance={themeAppearance} /> diff --git a/app/components/UI/ApproveTransactionReview/EditPermission/index.js b/app/components/UI/ApproveTransactionReview/EditPermission/index.js index 5ce70af7a90..cd5ab3142f2 100644 --- a/app/components/UI/ApproveTransactionReview/EditPermission/index.js +++ b/app/components/UI/ApproveTransactionReview/EditPermission/index.js @@ -1,99 +1,103 @@ import React, { useCallback, useMemo, useState } from 'react'; import PropTypes from 'prop-types'; import { View, StyleSheet, TouchableOpacity, TextInput } from 'react-native'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles } from '../../../../styles/common'; import Text from '../../../Base/Text'; import StyledButton from '../../StyledButton'; import { strings } from '../../../../../locales/i18n'; import ConnectHeader from '../../ConnectHeader'; import Device from '../../../../util/device'; import ErrorMessage from '../../../Views/SendFlow/ErrorMessage'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; export const MINIMUM_VALUE = '1'; -const styles = StyleSheet.create({ - wrapper: { - paddingHorizontal: 24, - paddingTop: 24, - paddingBottom: Device.isIphoneX() ? 48 : 24, - backgroundColor: colors.white, - borderTopRightRadius: 20, - borderTopLeftRadius: 20, - }, - sectionExplanationText: { - ...fontStyles.normal, - fontSize: 12, - color: colors.grey500, - marginVertical: 6, - }, - option: { - flexDirection: 'row', - marginVertical: 8, - }, - errorMessageWrapper: { - marginVertical: 6, - }, - optionText: { - ...fontStyles.normal, - fontSize: 14, - lineHeight: 20, - }, - touchableOption: { - flexDirection: 'row', - }, - selectedCircle: { - width: 8, - height: 8, - borderRadius: 8 / 2, - margin: 3, - backgroundColor: colors.blue, - }, - outSelectedCircle: { - width: 18, - height: 18, - borderRadius: 18 / 2, - borderWidth: 2, - borderColor: colors.blue, - }, - circle: { - width: 18, - height: 18, - borderRadius: 18 / 2, - backgroundColor: colors.white, - opacity: 1, - borderWidth: 2, - borderColor: colors.grey200, - }, - input: { - padding: 12, - borderColor: colors.grey200, - borderRadius: 10, - borderWidth: 2, - }, - spendLimitContent: { - marginLeft: 8, - flex: 1, - }, - spendLimitTitle: { - ...fontStyles.bold, - color: colors.black, - fontSize: 14, - lineHeight: 20, - marginBottom: 8, - }, - spendLimitSubtitle: { - ...fontStyles.normal, - fontSize: 12, - lineHeight: 18, - color: colors.grey500, - }, - textBlue: { - color: colors.blue, - }, - textBlack: { - color: colors.black, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + paddingHorizontal: 24, + paddingTop: 24, + paddingBottom: Device.isIphoneX() ? 48 : 24, + backgroundColor: colors.background.default, + borderTopRightRadius: 20, + borderTopLeftRadius: 20, + }, + sectionExplanationText: { + ...fontStyles.normal, + fontSize: 12, + color: colors.text.alternative, + marginVertical: 6, + }, + option: { + flexDirection: 'row', + marginVertical: 8, + }, + errorMessageWrapper: { + marginVertical: 6, + }, + optionText: { + ...fontStyles.normal, + fontSize: 14, + lineHeight: 20, + color: colors.text.default, + }, + touchableOption: { + flexDirection: 'row', + }, + selectedCircle: { + width: 8, + height: 8, + borderRadius: 8 / 2, + margin: 3, + backgroundColor: colors.primary.default, + }, + outSelectedCircle: { + width: 18, + height: 18, + borderRadius: 18 / 2, + borderWidth: 2, + borderColor: colors.primary.default, + }, + circle: { + width: 18, + height: 18, + borderRadius: 18 / 2, + backgroundColor: colors.background.default, + opacity: 1, + borderWidth: 2, + borderColor: colors.border.default, + }, + input: { + padding: 12, + borderColor: colors.border.default, + borderRadius: 10, + borderWidth: 2, + color: colors.text.default, + }, + spendLimitContent: { + marginLeft: 8, + flex: 1, + }, + spendLimitTitle: { + ...fontStyles.bold, + color: colors.text.default, + fontSize: 14, + lineHeight: 20, + marginBottom: 8, + }, + spendLimitSubtitle: { + ...fontStyles.normal, + fontSize: 12, + lineHeight: 18, + color: colors.text.alternative, + }, + textBlue: { + color: colors.primary.default, + }, + textBlack: { + color: colors.text.default, + }, + }); function EditPermission({ host, @@ -109,6 +113,8 @@ function EditPermission({ toggleEditPermission, }) { const [initialState] = useState({ spendLimitUnlimitedSelected, spendLimitCustomValue }); + const { colors, themeAppearance } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const displayErrorMessage = useMemo( () => !spendLimitUnlimitedSelected && Number(minimumSpendLimit) > spendLimitCustomValue, @@ -208,13 +214,14 @@ function EditPermission({ autoCorrect={false} onChangeText={onSpendLimitCustomValueChange} placeholder={`100 ${tokenSymbol}`} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} spellCheck={false} style={styles.input} value={spendLimitCustomValue} numberOfLines={1} onFocus={onPressSpendLimitCustomSelected} returnKeyType={'done'} + keyboardAppearance={themeAppearance} /> {displayErrorMessage && ( diff --git a/app/components/UI/ApproveTransactionReview/index.js b/app/components/UI/ApproveTransactionReview/index.js index 67886e1cea7..aa806758eb7 100644 --- a/app/components/UI/ApproveTransactionReview/index.js +++ b/app/components/UI/ApproveTransactionReview/index.js @@ -3,7 +3,7 @@ import { StyleSheet, View, TouchableOpacity, InteractionManager, Linking } from import ActionView from '../../UI/ActionView'; import PropTypes from 'prop-types'; import { getApproveNavbar } from '../../UI/Navbar'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { connect } from 'react-redux'; import { getHost } from '../../../util/browser'; import { safeToChecksumAddress, renderShortAddress } from '../../../util/address'; @@ -44,115 +44,117 @@ import Text from '../../Base/Text'; import { getTokenList } from '../../../reducers/tokens'; import TransactionReviewEIP1559 from '../../UI/TransactionReview/TransactionReviewEIP1559'; import ClipboardManager from '../../../core/ClipboardManager'; +import { ThemeContext, mockTheme } from '../../../util/theme'; const { hexToBN } = util; -const styles = StyleSheet.create({ - section: { - minWidth: '100%', - width: '100%', - paddingVertical: 10, - }, - title: { - ...fontStyles.bold, - fontSize: scaling.scale(24), - textAlign: 'center', - color: colors.black, - lineHeight: 34, - marginVertical: 8, - paddingHorizontal: 16, - }, - explanation: { - ...fontStyles.normal, - fontSize: 14, - textAlign: 'center', - color: colors.black, - lineHeight: 20, - paddingHorizontal: 16, - }, - editPermissionText: { - ...fontStyles.bold, - color: colors.blue, - fontSize: 12, - lineHeight: 20, - textAlign: 'center', - marginVertical: 10, - borderWidth: 1, - borderRadius: 20, - borderColor: colors.blue, - paddingVertical: 8, - paddingHorizontal: 16, - }, - viewDetailsText: { - ...fontStyles.normal, - color: colors.blue, - fontSize: 12, - lineHeight: 16, - marginTop: 8, - textAlign: 'center', - }, - actionTouchable: { - flexDirection: 'column', - alignItems: 'center', - }, - addressWrapper: { - backgroundColor: colors.blue000, - flexDirection: 'row', - alignItems: 'center', - borderRadius: 40, - paddingHorizontal: 10, - paddingVertical: 5, - }, - address: { - fontSize: 13, - marginHorizontal: 8, - color: colors.blue700, - ...fontStyles.normal, - maxWidth: 120, - }, - errorWrapper: { - marginTop: 12, - paddingHorizontal: 10, - paddingVertical: 8, - backgroundColor: colors.red000, - borderColor: colors.red, - borderRadius: 8, - borderWidth: 1, - justifyContent: 'center', - alignItems: 'center', - }, - error: { - color: colors.red, - fontSize: 12, - lineHeight: 16, - ...fontStyles.normal, - textAlign: 'center', - }, - underline: { - textDecorationLine: 'underline', - ...fontStyles.bold, - }, - actionViewWrapper: { - height: Device.isMediumDevice() ? 200 : 280, - }, - paddingHorizontal: { - paddingHorizontal: 16, - }, - contactWrapper: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - marginVertical: 15, - }, - nickname: { - ...fontStyles.normal, - textAlign: 'center', - color: colors.blue500, - marginBottom: 10, - }, - actionIcon: { - color: colors.blue, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + section: { + minWidth: '100%', + width: '100%', + paddingVertical: 10, + }, + title: { + ...fontStyles.bold, + fontSize: scaling.scale(24), + textAlign: 'center', + color: colors.text.default, + lineHeight: 34, + marginVertical: 16, + paddingHorizontal: 16, + }, + explanation: { + ...fontStyles.normal, + fontSize: 14, + textAlign: 'center', + color: colors.text.default, + lineHeight: 20, + paddingHorizontal: 16, + }, + editPermissionText: { + ...fontStyles.bold, + color: colors.primary.default, + fontSize: 12, + lineHeight: 20, + textAlign: 'center', + marginVertical: 10, + borderWidth: 1, + borderRadius: 20, + borderColor: colors.primary.default, + paddingVertical: 8, + paddingHorizontal: 16, + }, + viewDetailsText: { + ...fontStyles.normal, + color: colors.primary.default, + fontSize: 12, + lineHeight: 16, + marginTop: 8, + textAlign: 'center', + }, + actionTouchable: { + flexDirection: 'column', + alignItems: 'center', + }, + addressWrapper: { + backgroundColor: colors.primary.muted, + flexDirection: 'row', + alignItems: 'center', + borderRadius: 40, + paddingHorizontal: 10, + paddingVertical: 5, + }, + address: { + fontSize: 13, + marginHorizontal: 8, + color: colors.text.default, + ...fontStyles.normal, + maxWidth: 120, + }, + errorWrapper: { + marginTop: 12, + paddingHorizontal: 10, + paddingVertical: 8, + backgroundColor: colors.error.muted, + borderColor: colors.error.default, + borderRadius: 8, + borderWidth: 1, + justifyContent: 'center', + alignItems: 'center', + }, + error: { + color: colors.text.default, + fontSize: 12, + lineHeight: 16, + ...fontStyles.normal, + textAlign: 'center', + }, + underline: { + textDecorationLine: 'underline', + ...fontStyles.bold, + }, + actionViewWrapper: { + height: Device.isMediumDevice() ? 200 : 280, + }, + paddingHorizontal: { + paddingHorizontal: 16, + }, + contactWrapper: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + marginVertical: 15, + }, + nickname: { + ...fontStyles.normal, + textAlign: 'center', + color: colors.primary.default, + marginBottom: 10, + }, + actionIcon: { + color: colors.primary.default, + }, + }); const { ORIGIN_DEEPLINK, ORIGIN_QR_CODE } = AppConstants.DEEPLINKS; @@ -533,13 +535,15 @@ class ApproveTransactionReview extends PureComponent { ); }; - toggleDisplay = () => { - this.props.onUpdateContractNickname(); + getStyles = () => { + const colors = this.context.colors || mockTheme.colors; + return createStyles(colors); }; + toggleDisplay = () => this.props.onUpdateContractNickname(); + renderDetails = () => { const { host, tokenSymbol, spenderAddress } = this.state; - const { primaryCurrency, gasError, @@ -557,6 +561,7 @@ class ApproveTransactionReview extends PureComponent { gasEstimationReady, transactionConfirmed, } = this.props; + const styles = this.getStyles(); const is_main_net = isMainNet(network); const originIsDeeplink = origin === ORIGIN_DEEPLINK || origin === ORIGIN_QR_CODE; const errorPress = is_main_net ? this.buyEth : this.gotoFaucet; @@ -611,7 +616,7 @@ class ApproveTransactionReview extends PureComponent { type={'short'} /> )} - + @@ -626,80 +631,78 @@ class ApproveTransactionReview extends PureComponent { onConfirmPress={this.onConfirmPress} confirmDisabled={Boolean(gasError) || transactionConfirmed} > - - - - - {showFeeMarket ? ( - - ) : ( - - )} - - {gasError && ( - - - - {gasError} + + + + {showFeeMarket ? ( + + ) : ( + + )} + + {gasError && ( + + + + {gasError} + + {/* only show buy more on mainnet */} + {over && is_main_net && ( + + {errorLinkText} - {/* only show buy more on mainnet */} - {over && is_main_net && ( - - {errorLinkText} - - )} - - - )} - {!gasError && ( - - - - {strings('spend_limit_edition.view_details')} - - + )} - )} - + + )} + {!gasError && ( + + + + {strings('spend_limit_edition.view_details')} + + + + )} @@ -812,4 +815,6 @@ const mapDispatchToProps = (dispatch) => ({ showAlert: (config) => dispatch(showAlert(config)), }); +ApproveTransactionReview.contextType = ThemeContext; + export default connect(mapStateToProps, mapDispatchToProps)(withNavigation(ApproveTransactionReview)); diff --git a/app/components/UI/AssetActionButton/__snapshots__/index.test.tsx.snap b/app/components/UI/AssetActionButton/__snapshots__/index.test.tsx.snap index f32cc2e1f1b..4f3bf672f40 100644 --- a/app/components/UI/AssetActionButton/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/AssetActionButton/__snapshots__/index.test.tsx.snap @@ -19,7 +19,7 @@ exports[`AssetActionButtons should render correctly 1`] = ` style={ Object { "alignContent": "center", - "backgroundColor": "#037dd6", + "backgroundColor": "#037DD6", "borderRadius": 18, "height": 36, "justifyContent": "center", @@ -47,7 +47,7 @@ exports[`AssetActionButtons should render correctly 1`] = ` strikethrough={false} style={ Object { - "color": "#037dd6", + "color": "#037DD6", "fontSize": 14, "marginTop": 8, } @@ -77,7 +77,7 @@ exports[`AssetActionButtons should render type add correctly 1`] = ` style={ Object { "alignContent": "center", - "backgroundColor": "#037dd6", + "backgroundColor": "#037DD6", "borderRadius": 18, "height": 36, "justifyContent": "center", @@ -94,7 +94,7 @@ exports[`AssetActionButtons should render type add correctly 1`] = ` style={ Object { "alignContent": "center", - "color": "#FFFFFF", + "color": "#FCFCFC", "justifyContent": "center", "textAlign": "center", } @@ -119,7 +119,7 @@ exports[`AssetActionButtons should render type add correctly 1`] = ` strikethrough={false} style={ Object { - "color": "#037dd6", + "color": "#037DD6", "fontSize": 14, "marginTop": 8, } @@ -149,7 +149,7 @@ exports[`AssetActionButtons should render type information correctly 1`] = ` style={ Object { "alignContent": "center", - "backgroundColor": "#037dd6", + "backgroundColor": "#037DD6", "borderRadius": 18, "height": 36, "justifyContent": "center", @@ -166,7 +166,7 @@ exports[`AssetActionButtons should render type information correctly 1`] = ` style={ Object { "alignContent": "center", - "color": "#FFFFFF", + "color": "#FCFCFC", "justifyContent": "center", "textAlign": "center", } @@ -191,7 +191,7 @@ exports[`AssetActionButtons should render type information correctly 1`] = ` strikethrough={false} style={ Object { - "color": "#037dd6", + "color": "#037DD6", "fontSize": 14, "marginTop": 8, } @@ -221,7 +221,7 @@ exports[`AssetActionButtons should render type receive correctly 1`] = ` style={ Object { "alignContent": "center", - "backgroundColor": "#037dd6", + "backgroundColor": "#037DD6", "borderRadius": 18, "height": 36, "justifyContent": "center", @@ -233,14 +233,14 @@ exports[`AssetActionButtons should render type receive correctly 1`] = ` > + StyleSheet.create({ + button: { + flexShrink: 1, + marginHorizontal: 0, + justifyContent: 'center', + alignItems: 'center', + minWidth: 60, + }, + disabledButton: { + opacity: 0.5, + }, + buttonIconWrapper: { + width: 36, + height: 36, + borderRadius: 18, + paddingTop: Device.isAndroid() ? 2 : 4, + paddingLeft: 1, + justifyContent: 'center', + alignContent: 'center', + backgroundColor: colors.primary.default, + }, + buttonIcon: { + justifyContent: 'center', + alignContent: 'center', + textAlign: 'center', + color: colors.primary.inverse, + }, + buttonText: { + marginTop: 8, + color: colors.primary.default, + fontSize: 14, + }, + receive: { + right: Device.isIos() ? 1 : 0, + bottom: 1, + transform: [{ rotate: '90deg' }], + }, + swapsIcon: { + right: Device.isAndroid() ? 1 : 0, + bottom: Device.isAndroid() ? 1 : 0, + }, + buyIcon: { + right: Device.isAndroid() ? 0.5 : 0, + bottom: Device.isAndroid() ? 1 : 2, + }, + }); -function getIcon(type) { - switch (type) { - case 'send': { - return ; - } - case 'receive': { - return ( - - ); - } - case 'add': { - return ; - } - case 'information': { - return ; - } - case 'swap': { - return ; - } - case 'buy': { - return ; - } - default: { - return null; +function AssetActionButton({ onPress, icon, label, disabled }) { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + const getIcon = (type) => { + switch (type) { + case 'send': { + return ; + } + case 'receive': { + return ( + + ); + } + case 'add': { + return ; + } + case 'information': { + return ; + } + case 'swap': { + return ; + } + case 'buy': { + return ; + } + default: { + return null; + } } - } -} + }; -function AssetActionButton({ onPress, icon, label, disabled }) { return ( + StyleSheet.create({ + itemWrapper: { + flex: 1, + flexDirection: 'row', + paddingHorizontal: 15, + paddingVertical: 10, + borderBottomWidth: StyleSheet.hairlineWidth, + borderBottomColor: colors.border.muted, + }, + arrow: { + flex: 1, + alignSelf: 'flex-end', + }, + arrowIcon: { + marginTop: 16, + }, + }); /** * Customizable view to render assets in lists @@ -57,6 +58,9 @@ export default class AssetElement extends PureComponent { render = () => { const { children } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( {children} - + ); }; } + +AssetElement.contextType = ThemeContext; diff --git a/app/components/UI/AssetIcon/__snapshots__/index.test.tsx.snap b/app/components/UI/AssetIcon/__snapshots__/index.test.tsx.snap index 03c3c9954a5..df7e8f4fa07 100644 --- a/app/components/UI/AssetIcon/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/AssetIcon/__snapshots__/index.test.tsx.snap @@ -5,7 +5,7 @@ exports[`AssetIcon should render correctly 1`] = ` fadeIn={true} placeholderStyle={ Object { - "backgroundColor": "#FFFFFF", + "backgroundColor": "#F2F4F6", } } source={ diff --git a/app/components/UI/AssetIcon/index.tsx b/app/components/UI/AssetIcon/index.tsx index 79fd8421fbc..15cdcc4f794 100644 --- a/app/components/UI/AssetIcon/index.tsx +++ b/app/components/UI/AssetIcon/index.tsx @@ -2,8 +2,8 @@ import React, { memo } from 'react'; import { ImageStyle, StyleSheet, StyleProp, ImageSourcePropType } from 'react-native'; import isUrl from 'is-url'; import RemoteImage from '../../Base/RemoteImage'; -import { colors } from '../../../styles/common'; import staticLogos from 'images/static-logos'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; interface Props { /** @@ -20,22 +20,26 @@ interface Props { customStyle?: StyleProp; } -const styles = StyleSheet.create({ - logo: { - width: 50, - height: 50, - borderRadius: 25, - overflow: 'hidden', - }, - placeholder: { backgroundColor: colors.white }, -}); +const createStyles = (colors: any) => + StyleSheet.create({ + logo: { + width: 50, + height: 50, + borderRadius: 25, + overflow: 'hidden', + }, + placeholder: { backgroundColor: colors.background.alternative }, + }); /** * PureComponent that provides an asset icon dependent on OS. */ // eslint-disable-next-line react/display-name const AssetIcon = memo((props: Props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); if (!props.logo) return null; + const style = [styles.logo, props.customStyle]; const isImageUrl = isUrl(props.logo) || props.logo.substr(0, 4) === 'ipfs'; const source: ImageSourcePropType = isImageUrl ? { uri: props.logo } : (staticLogos as any)[props.logo]; diff --git a/app/components/UI/AssetOverview/index.js b/app/components/UI/AssetOverview/index.js index 972203192c9..da033ef9655 100644 --- a/app/components/UI/AssetOverview/index.js +++ b/app/components/UI/AssetOverview/index.js @@ -6,7 +6,7 @@ import AssetIcon from '../AssetIcon'; import Identicon from '../Identicon'; import AssetActionButton from '../AssetActionButton'; import AppConstants from '../../../core/AppConstants'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import { toggleReceiveModal } from '../../../actions/modals'; import { connect } from 'react-redux'; @@ -25,66 +25,68 @@ import { ANALYTICS_EVENT_OPTS } from '../../../util/analytics'; import { allowedToBuy } from '../FiatOrders'; import AssetSwapButton from '../Swaps/components/AssetSwapButton'; import NetworkMainAssetLogo from '../NetworkMainAssetLogo'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - flex: 1, - padding: 20, - borderBottomWidth: StyleSheet.hairlineWidth, - borderBottomColor: colors.grey100, - alignContent: 'center', - alignItems: 'center', - paddingBottom: 30, - }, - assetLogo: { - marginTop: 15, - alignItems: 'center', - justifyContent: 'center', - borderRadius: 10, - marginBottom: 10, - }, - ethLogo: { - width: 70, - height: 70, - }, - balance: { - alignItems: 'center', - marginTop: 10, - marginBottom: 20, - }, - amount: { - fontSize: 30, - color: colors.fontPrimary, - ...fontStyles.normal, - textTransform: 'uppercase', - }, - amountFiat: { - fontSize: 18, - color: colors.fontSecondary, - ...fontStyles.light, - textTransform: 'uppercase', - }, - actions: { - flex: 1, - justifyContent: 'center', - alignItems: 'flex-start', - flexDirection: 'row', - }, - warning: { - borderRadius: 8, - color: colors.black, - ...fontStyles.normal, - fontSize: 14, - lineHeight: 20, - borderWidth: 1, - borderColor: colors.yellow, - backgroundColor: colors.yellow100, - padding: 20, - }, - warningLinks: { - color: colors.blue, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + flex: 1, + padding: 20, + borderBottomWidth: StyleSheet.hairlineWidth, + borderBottomColor: colors.border.muted, + alignContent: 'center', + alignItems: 'center', + paddingBottom: 30, + }, + assetLogo: { + marginTop: 15, + alignItems: 'center', + justifyContent: 'center', + borderRadius: 10, + marginBottom: 10, + }, + ethLogo: { + width: 70, + height: 70, + }, + balance: { + alignItems: 'center', + marginTop: 10, + marginBottom: 20, + }, + amount: { + fontSize: 30, + color: colors.text.default, + ...fontStyles.normal, + textTransform: 'uppercase', + }, + amountFiat: { + fontSize: 18, + color: colors.text.alternative, + ...fontStyles.light, + textTransform: 'uppercase', + }, + actions: { + flex: 1, + justifyContent: 'center', + alignItems: 'flex-start', + flexDirection: 'row', + }, + warning: { + borderRadius: 8, + color: colors.text.default, + ...fontStyles.normal, + fontSize: 14, + lineHeight: 20, + borderWidth: 1, + borderColor: colors.warning.default, + backgroundColor: colors.warning.muted, + padding: 20, + }, + warningLinks: { + color: colors.primary.default, + }, + }); /** * View that displays the information of a specific asset (Token or ETH) @@ -210,6 +212,9 @@ class AssetOverview extends PureComponent { tokenList, asset: { address, isETH }, } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + if (isETH) { return ; } @@ -231,6 +236,8 @@ class AssetOverview extends PureComponent { const { asset: { symbol }, } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); const supportArticleUrl = 'https://metamask.zendesk.com/hc/en-us/articles/360028059272-What-to-do-when-your-balance-of-ETH-and-or-ERC20-tokens-is-incorrect-inaccurate'; @@ -259,6 +266,9 @@ class AssetOverview extends PureComponent { swapsIsLive, swapsTokens, } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + let mainBalance, secondaryBalance; const itemAddress = safeToChecksumAddress(address); let balance, balanceFiat; @@ -350,4 +360,6 @@ const mapDispatchToProps = (dispatch) => ({ newAssetTransaction: (selectedAsset) => dispatch(newAssetTransaction(selectedAsset)), }); +AssetOverview.contextType = ThemeContext; + export default connect(mapStateToProps, mapDispatchToProps)(AssetOverview); diff --git a/app/components/UI/AssetSearch/index.tsx b/app/components/UI/AssetSearch/index.tsx index f5549bce2ac..b9f9df359b3 100644 --- a/app/components/UI/AssetSearch/index.tsx +++ b/app/components/UI/AssetSearch/index.tsx @@ -1,6 +1,6 @@ import React, { memo, useEffect, useState, useCallback } from 'react'; import { TextInput, View, StyleSheet } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import Fuse from 'fuse.js'; import Icon from 'react-native-vector-icons/FontAwesome'; @@ -8,26 +8,31 @@ import { toLowerCaseEquals } from '../../../util/general'; import { useSelector } from 'react-redux'; import { getTokenListArray } from '../../../reducers/tokens'; import { TokenListToken } from '@metamask/controllers'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - searchSection: { - margin: 20, - marginBottom: 0, - flex: 1, - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - borderWidth: 1, - borderRadius: 4, - borderColor: colors.grey100, - }, - textInput: { - ...fontStyles.normal, - } as StyleSheet.NamedStyles, - icon: { - padding: 16, - }, -}); +const createStyles = (colors: any) => + StyleSheet.create({ + searchSection: { + margin: 20, + marginBottom: 0, + flex: 1, + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + borderWidth: 1, + borderRadius: 4, + borderColor: colors.border.default, + color: colors.text.default, + }, + textInput: { + ...fontStyles.normal, + color: colors.text.default, + } as StyleSheet.NamedStyles, + icon: { + padding: 16, + color: colors.icon.default, + }, + }); const fuse = new Fuse([], { shouldSort: true, @@ -59,6 +64,8 @@ const AssetSearch = memo(({ onSearch, onFocus, onBlur }: Props) => { const [searchQuery, setSearchQuery] = useState(''); const [inputDimensions, setInputDimensions] = useState('85%'); const tokenList = useSelector(getTokenListArray); + const { colors, themeAppearance } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); useEffect(() => { setTimeout(() => { @@ -91,9 +98,10 @@ const AssetSearch = memo(({ onSearch, onFocus, onBlur }: Props) => { onFocus={onFocus} onBlur={onBlur} placeholder={strings('token.search_tokens_placeholder')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} onChangeText={handleSearch} testID={'input-search-asset'} + keyboardAppearance={themeAppearance} /> ); diff --git a/app/components/UI/BackupAlert/index.js b/app/components/UI/BackupAlert/index.js index 7da661d827c..7255c0d17c5 100644 --- a/app/components/UI/BackupAlert/index.js +++ b/app/components/UI/BackupAlert/index.js @@ -4,67 +4,72 @@ import PropTypes from 'prop-types'; import EvilIcons from 'react-native-vector-icons/EvilIcons'; import ElevatedView from 'react-native-elevated-view'; import { strings } from '../../../../locales/i18n'; -import { colors, fontStyles, baseStyles } from '../../../styles/common'; +import { fontStyles, baseStyles } from '../../../styles/common'; import Device from '../../../util/device'; import { connect } from 'react-redux'; import { backUpSeedphraseAlertNotVisible } from '../../../actions/user'; import { findRouteNameFromNavigatorState } from '../../../util/general'; import AnalyticsV2 from '../../../util/analyticsV2'; +import { ThemeContext, mockTheme } from '../../../util/theme'; const BROWSER_ROUTE = 'BrowserView'; -const styles = StyleSheet.create({ - backupAlertWrapper: { - flex: 1, - backgroundColor: colors.orange000, - borderColor: colors.yellow300, - borderWidth: 1, - position: 'absolute', - left: 16, - right: 16, - borderRadius: 8, - padding: 14, - }, - backupAlertIconWrapper: { - marginRight: 10, - }, - backupAlertIcon: { - fontSize: 22, - ...fontStyles.bold, - color: colors.black, - }, - backupAlertTitle: { - fontSize: 14, - marginBottom: 14, - color: colors.black, - ...fontStyles.bold, - }, - backupAlertMessage: { - fontSize: 12, - color: colors.blue, - marginLeft: 14, - flex: 1, - textAlign: 'right', - ...fontStyles.normal, - }, - touchableView: { - flexDirection: 'row', - }, - modalViewInBrowserView: { - bottom: Device.isIphoneX() ? 90 : 80, - }, - modalViewNotInBrowserView: { - bottom: Device.isIphoneX() ? 20 : 10, - }, - buttonsWrapper: { - flexDirection: 'row-reverse', - alignContent: 'flex-end', - flex: 1, - }, - dismissButton: { - flex: 1, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + container: { + backgroundColor: colors.background.default, + position: 'absolute', + left: 16, + right: 16, + borderRadius: 8, + borderColor: colors.warning.default, + borderWidth: 1, + }, + backupAlertWrapper: { + flex: 1, + backgroundColor: colors.warning.muted, + padding: 14, + }, + backupAlertIconWrapper: { + marginRight: 10, + }, + backupAlertIcon: { + fontSize: 22, + ...fontStyles.bold, + color: colors.text.default, + }, + backupAlertTitle: { + fontSize: 14, + marginBottom: 14, + color: colors.text.default, + ...fontStyles.bold, + }, + backupAlertMessage: { + fontSize: 12, + color: colors.primary.default, + marginLeft: 14, + flex: 1, + textAlign: 'right', + ...fontStyles.normal, + }, + touchableView: { + flexDirection: 'row', + }, + modalViewInBrowserView: { + bottom: Device.isIphoneX() ? 90 : 80, + }, + modalViewNotInBrowserView: { + bottom: Device.isIphoneX() ? 20 : 10, + }, + buttonsWrapper: { + flexDirection: 'row-reverse', + alignContent: 'flex-end', + flex: 1, + }, + dismissButton: { + flex: 1, + }, + }); const BLOCKED_LIST = [ 'ImportPrivateKey', @@ -151,32 +156,37 @@ class BackupAlert extends PureComponent { render() { const { seedphraseBackedUp, backUpSeedphraseVisible } = this.props; const { inBrowserView, blockedView } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + if (seedphraseBackedUp || blockedView || !backUpSeedphraseVisible) return null; return ( - - - - - - {strings('backup_alert.title')} - - - - {strings('backup_alert.right_button')} - - - - - {strings('backup_alert.left_button')} - - + + + + + + + {strings('backup_alert.title')} + + + + {strings('backup_alert.right_button')} + + + + + {strings('backup_alert.left_button')} + + + @@ -194,4 +204,6 @@ const mapDispatchToProps = (dispatch) => ({ backUpSeedphraseAlertNotVisible: () => dispatch(backUpSeedphraseAlertNotVisible()), }); +BackupAlert.contextType = ThemeContext; + export default connect(mapStateToProps, mapDispatchToProps)(BackupAlert); diff --git a/app/components/UI/BiometryButton/__snapshots__/index.test.tsx.snap b/app/components/UI/BiometryButton/__snapshots__/index.test.tsx.snap index a7a712f4332..d72a57a99c5 100644 --- a/app/components/UI/BiometryButton/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/BiometryButton/__snapshots__/index.test.tsx.snap @@ -13,7 +13,7 @@ exports[`BiometryButton should render correctly 1`] = ` > + StyleSheet.create({ + fixCenterIcon: { + marginBottom: -3, + }, + image: { + height: 24, + width: 24, + tintColor: colors.text.default, + }, + hitSlop: { + top: 10, + left: 10, + bottom: 10, + right: 10, + }, + }); const iosFaceId = require('../../../images/ios-face-id.png'); const androidFaceRecognition = require('../../../images/android-face-recognition.png'); const androidIris = require('../../../images/android-iris.png'); -const renderIcon = (type) => { - if (Platform.OS === 'ios') { - if (type === 'TouchID') - return ; - if (type === 'FaceID') return ; - } +const BiometryButton = ({ onPress, hidden, type }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); - if (Platform.OS === 'android') { - if (type === 'Fingerprint') - return ; - if (type === 'Face') return ; - if (type === 'Iris') return ; - } + const renderIcon = (type) => { + if (Platform.OS === 'ios') { + if (type === 'TouchID') + return ( + + ); + if (type === 'FaceID') return ; + } - return ; -}; + if (Platform.OS === 'android') { + if (type === 'Fingerprint') + return ( + + ); + if (type === 'Face') return ; + if (type === 'Iris') return ; + } + + return ; + }; -const BiometryButton = ({ onPress, hidden, type }) => { if (hidden) return null; return ( diff --git a/app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap b/app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap index 8f606c5be76..5045530afea 100644 --- a/app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap @@ -7,8 +7,8 @@ exports[`BlockingActionModal should render correctly 1`] = ` animationOut="slideOutDown" animationOutTiming={300} avoidKeyboard={false} - backdropColor="black" - backdropOpacity={0.7} + backdropColor="#00000099" + backdropOpacity={1} backdropTransitionInTiming={300} backdropTransitionOutTiming={300} coverScreen={true} diff --git a/app/components/UI/BlockingActionModal/index.js b/app/components/UI/BlockingActionModal/index.js index 5b02a05a9aa..e6e986700b9 100644 --- a/app/components/UI/BlockingActionModal/index.js +++ b/app/components/UI/BlockingActionModal/index.js @@ -2,34 +2,39 @@ import React from 'react'; import PropTypes from 'prop-types'; import { ActivityIndicator, StyleSheet, View } from 'react-native'; import Modal from 'react-native-modal'; -import { colors, baseStyles } from '../../../styles/common'; +import { baseStyles } from '../../../styles/common'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - modal: { - margin: 0, - width: '100%', - }, - modalView: { - justifyContent: 'center', - alignItems: 'center', - alignSelf: 'center', - backgroundColor: colors.white, - width: '90%', - borderRadius: 6, - minHeight: 200, - padding: 15, - }, - loader: { - marginTop: 30, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + modal: { + margin: 0, + width: '100%', + }, + modalView: { + justifyContent: 'center', + alignItems: 'center', + alignSelf: 'center', + backgroundColor: colors.background.default, + width: '90%', + borderRadius: 6, + minHeight: 200, + padding: 15, + }, + loader: { + marginTop: 30, + }, + }); /** * View that renders an action modal */ export default function BlockingActionModal({ children, modalVisible, isLoadingAction }) { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ( - + {children} diff --git a/app/components/UI/BrowserBottomBar/__snapshots__/index.test.tsx.snap b/app/components/UI/BrowserBottomBar/__snapshots__/index.test.tsx.snap index 50166277800..252992cd9b4 100644 --- a/app/components/UI/BrowserBottomBar/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/BrowserBottomBar/__snapshots__/index.test.tsx.snap @@ -5,8 +5,8 @@ exports[`BrowserBottomBar should render correctly 1`] = ` elevation={11} style={ Object { - "backgroundColor": "#f2f3f4", - "borderColor": "#bbc0c5", + "backgroundColor": "#FFFFFF", + "borderColor": "#D6D9DC", "borderTopWidth": 0.5, "flex": 0, "flexDirection": "row", @@ -39,7 +39,7 @@ exports[`BrowserBottomBar should render correctly 1`] = ` style={ Array [ Object { - "color": "#6a737d", + "color": "#6A737D", "height": 24, "textAlign": "center", "width": 24, @@ -73,13 +73,13 @@ exports[`BrowserBottomBar should render correctly 1`] = ` style={ Array [ Object { - "color": "#6a737d", + "color": "#6A737D", "height": 24, "textAlign": "center", "width": 24, }, Object { - "color": "#d6d9dc", + "color": "#BBC0C5", }, ] } @@ -107,7 +107,7 @@ exports[`BrowserBottomBar should render correctly 1`] = ` size={24} style={ Object { - "color": "#6a737d", + "color": "#6A737D", "height": 24, "textAlign": "center", "width": 24, @@ -163,7 +163,7 @@ exports[`BrowserBottomBar should render correctly 1`] = ` size={22} style={ Object { - "color": "#6a737d", + "color": "#6A737D", "height": 24, "textAlign": "center", "width": 24, @@ -193,7 +193,7 @@ exports[`BrowserBottomBar should render correctly 1`] = ` size={22} style={ Object { - "color": "#6a737d", + "color": "#6A737D", "height": 24, "textAlign": "center", "width": 24, diff --git a/app/components/UI/BrowserBottomBar/index.js b/app/components/UI/BrowserBottomBar/index.js index 254c60660ed..a2b0769d3c0 100644 --- a/app/components/UI/BrowserBottomBar/index.js +++ b/app/components/UI/BrowserBottomBar/index.js @@ -9,49 +9,50 @@ import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons'; import FeatherIcons from 'react-native-vector-icons/Feather'; import AnalyticsV2 from '../../../util/analyticsV2'; import Device from '../../../util/device'; -import { colors } from '../../../styles/common'; +import { ThemeContext, mockTheme } from '../../../util/theme'; const HOME_INDICATOR_HEIGHT = 18; const defaultBottomBarPadding = 0; -const styles = StyleSheet.create({ - bottomBar: { - backgroundColor: Device.isAndroid() ? colors.white : colors.grey000, - flexDirection: 'row', - paddingBottom: - Device.isIphoneX() && Device.isIos() - ? defaultBottomBarPadding + HOME_INDICATOR_HEIGHT - : defaultBottomBarPadding, - flex: 0, - borderTopWidth: Device.isAndroid() ? 0 : StyleSheet.hairlineWidth, - borderColor: colors.grey200, - justifyContent: 'space-between', - }, - iconButton: { - height: 24, - width: 24, - justifyContent: 'space-around', - alignItems: 'center', - textAlign: 'center', - flex: 1, - paddingTop: 30, - paddingBottom: 30, - }, - tabIcon: { - marginTop: 0, - width: 24, - height: 24, - }, - disabledIcon: { - color: colors.grey100, - }, - icon: { - width: 24, - height: 24, - color: colors.grey500, - textAlign: 'center', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + bottomBar: { + backgroundColor: colors.background.default, + flexDirection: 'row', + paddingBottom: + Device.isIphoneX() && Device.isIos() + ? defaultBottomBarPadding + HOME_INDICATOR_HEIGHT + : defaultBottomBarPadding, + flex: 0, + borderTopWidth: Device.isAndroid() ? 0 : StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + justifyContent: 'space-between', + }, + iconButton: { + height: 24, + width: 24, + justifyContent: 'space-around', + alignItems: 'center', + textAlign: 'center', + flex: 1, + paddingTop: 30, + paddingBottom: 30, + }, + tabIcon: { + marginTop: 0, + width: 24, + height: 24, + }, + disabledIcon: { + color: colors.icon.muted, + }, + icon: { + width: 24, + height: 24, + color: colors.icon.default, + textAlign: 'center', + }, + }); /** * Browser bottom bar that contains icons for navigatio @@ -110,6 +111,8 @@ export default class BrowserBottomBar extends PureComponent { render() { const { canGoBack, goBack, canGoForward, goForward, showTabs, goHome, showUrlModal, toggleOptions } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); const onSearchPress = () => { showUrlModal(); @@ -171,3 +174,5 @@ export default class BrowserBottomBar extends PureComponent { ); } } + +BrowserBottomBar.contextType = ThemeContext; diff --git a/app/components/UI/Button/__snapshots__/index.test.tsx.snap b/app/components/UI/Button/__snapshots__/index.test.tsx.snap index cd39d46d0e9..b07f369221d 100644 --- a/app/components/UI/Button/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/Button/__snapshots__/index.test.tsx.snap @@ -6,7 +6,7 @@ exports[`Button should render correctly 1`] = ` Array [ Object { "alignItems": "center", - "backgroundColor": "#037dd6", + "backgroundColor": "#037DD6", "borderRadius": 4, "flex": 1, "height": 40, diff --git a/app/components/UI/Button/index.js b/app/components/UI/Button/index.js index 6ae7654b48c..08f810aab9b 100644 --- a/app/components/UI/Button/index.js +++ b/app/components/UI/Button/index.js @@ -2,30 +2,36 @@ import React from 'react'; import PropTypes from 'prop-types'; import { ViewPropTypes, StyleSheet } from 'react-native'; import GenericButton from '../GenericButton'; // eslint-disable-line import/no-unresolved -import { colors } from '../../../styles/common'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - button: { - flex: 1, - alignItems: 'center', - justifyContent: 'center', - backgroundColor: colors.blue, - paddingVertical: 10, - paddingHorizontal: 15, - height: 40, - borderRadius: 4, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + button: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + backgroundColor: colors.primary.default, + paddingVertical: 10, + paddingHorizontal: 15, + height: 40, + borderRadius: 4, + }, + }); /** * UI component that wraps GenericButton * which renders the appropiate UI elements for each platform (android & iOS) */ -const Button = (props) => ( - - {props.children} - -); +const Button = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + {props.children} + + ); +}; Button.propTypes = { /** diff --git a/app/components/UI/ButtonReveal/index.tsx b/app/components/UI/ButtonReveal/index.tsx index 181a52278d5..eb27a74176b 100644 --- a/app/components/UI/ButtonReveal/index.tsx +++ b/app/components/UI/ButtonReveal/index.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { StyleSheet, View, Text, TouchableOpacity } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome5'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import Svg, { Circle } from 'react-native-svg'; import Animated, { useSharedValue, @@ -14,6 +14,7 @@ import Animated, { Extrapolate, runOnUI, } from 'react-native-reanimated'; +import { mockTheme, useAppThemeFromContext } from '../../../util/theme'; const AnimatedCircle = Animated.createAnimatedComponent(Circle); const radius = 14; @@ -23,58 +24,59 @@ const innerRadius = radius - strokeWidth / 2; const circumference = 2 * Math.PI * innerRadius; const animationDuration = 1200; -const styles = StyleSheet.create({ - container: { - backgroundColor: colors.blue, - alignItems: 'center', - justifyContent: 'center', - flexDirection: 'row', - paddingVertical: 12, - paddingHorizontal: 24, - borderRadius: 99, - }, - progressContainer: { - height: radius * 2, - width: radius * 2, - marginRight: 12, - }, - absoluteFillWithCenter: { - ...StyleSheet.absoluteFillObject, - alignItems: 'center', - justifyContent: 'center', - }, - absoluteFill: { - ...StyleSheet.absoluteFillObject, - }, - preCompletedContainerStyle: { - ...StyleSheet.absoluteFillObject, - borderRadius: radius, - backgroundColor: colors.blue, - }, - outerCircle: { - ...StyleSheet.absoluteFillObject, - borderRadius: radius, - backgroundColor: colors.white, - }, - innerCircle: { - flex: 1, - borderRadius: radius - strokeWidth, - margin: strokeWidth, - backgroundColor: colors.blue, - }, - label: { - color: colors.white, - fontSize: 18, - ...(fontStyles.normal as any), - }, - animatedCircle: { - transform: [ - { - rotate: '-90deg', - }, - ], - }, -}); +const createStyles = (colors: any) => + StyleSheet.create({ + container: { + backgroundColor: colors.primary.default, + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'row', + paddingVertical: 12, + paddingHorizontal: 24, + borderRadius: 99, + }, + progressContainer: { + height: radius * 2, + width: radius * 2, + marginRight: 12, + }, + absoluteFillWithCenter: { + ...StyleSheet.absoluteFillObject, + alignItems: 'center', + justifyContent: 'center', + }, + absoluteFill: { + ...StyleSheet.absoluteFillObject, + }, + preCompletedContainerStyle: { + ...StyleSheet.absoluteFillObject, + borderRadius: radius, + backgroundColor: colors.primary.default, + }, + outerCircle: { + ...StyleSheet.absoluteFillObject, + borderRadius: radius, + backgroundColor: colors.primary.inverse, + }, + innerCircle: { + flex: 1, + borderRadius: radius - strokeWidth, + margin: strokeWidth, + backgroundColor: colors.primary.default, + }, + label: { + color: colors.primary.inverse, + fontSize: 18, + ...(fontStyles.normal as any), + }, + animatedCircle: { + transform: [ + { + rotate: '-90deg', + }, + ], + }, + }); interface Props { onLongPress: () => void; @@ -92,6 +94,9 @@ const ButtonReveal = ({ onLongPress, label }: Props) => { const progressContainerOpacity = useSharedValue(1); // Value for scaling down the progress container const postCompleteControl = useSharedValue(0); + // Colors + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); // Animate SVG via props const animatedProps = useAnimatedProps(() => ({ @@ -205,7 +210,7 @@ const ButtonReveal = ({ onLongPress, label }: Props) => { - + ); @@ -213,14 +218,14 @@ const ButtonReveal = ({ onLongPress, label }: Props) => { const renderPreCompletedContent = () => ( - + @@ -231,7 +236,7 @@ const ButtonReveal = ({ onLongPress, label }: Props) => { cx={radius} cy={radius} r={innerRadius} - stroke={colors.white} + stroke={colors.primary.inverse} strokeWidth={strokeWidth} strokeLinecap={'round'} strokeDasharray={`${circumference} ${circumference}`} diff --git a/app/components/UI/CollectibleContractElement/index.js b/app/components/UI/CollectibleContractElement/index.js index c6b3bc64685..23d4fa1606a 100644 --- a/app/components/UI/CollectibleContractElement/index.js +++ b/app/components/UI/CollectibleContractElement/index.js @@ -2,7 +2,7 @@ import React, { useEffect, useState, useCallback, useRef } from 'react'; import PropTypes from 'prop-types'; import { StyleSheet, View, TouchableOpacity, Alert } from 'react-native'; import { connect } from 'react-redux'; -import { colors, fontStyles } from '../../../styles/common'; +import { colors as importedColors, fontStyles } from '../../../styles/common'; import CollectibleMedia from '../CollectibleMedia'; import Icon from 'react-native-vector-icons/Ionicons'; import Device from '../../../util/device'; @@ -13,57 +13,60 @@ import { strings } from '../../../../locales/i18n'; import Engine from '../../../core/Engine'; import { removeFavoriteCollectible } from '../../../actions/collectibles'; import { collectibleContractsSelector } from '../../../reducers/collectibles'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; const DEVICE_WIDTH = Device.getDeviceWidth(); const COLLECTIBLE_WIDTH = (DEVICE_WIDTH - 30 - 16) / 3; -const styles = StyleSheet.create({ - itemWrapper: { - paddingHorizontal: 15, - paddingBottom: 16, - }, - collectibleContractIcon: { width: 30, height: 30 }, - collectibleContractIconContainer: { marginHorizontal: 8, borderRadius: 30 }, - titleContainer: { - flex: 1, - flexDirection: 'row', - }, - verticalAlignedContainer: { - flexDirection: 'row', - alignItems: 'center', - }, - titleText: { - fontSize: 18, - color: colors.black, - ...fontStyles.normal, - }, - collectibleIcon: { - width: COLLECTIBLE_WIDTH, - height: COLLECTIBLE_WIDTH, - }, - collectibleInTheMiddle: { - marginHorizontal: 8, - }, - collectiblesRowContainer: { - flex: 1, - flexDirection: 'row', - marginTop: 15, - }, - collectibleBox: { - flex: 1, - flexDirection: 'row', - }, - favoritesLogoWrapper: { - flex: 1, - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - backgroundColor: colors.yellow, - width: 32, - height: 32, - borderRadius: 16, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + itemWrapper: { + paddingHorizontal: 15, + paddingBottom: 16, + }, + collectibleContractIcon: { width: 30, height: 30 }, + collectibleContractIconContainer: { marginHorizontal: 8, borderRadius: 30 }, + titleContainer: { + flex: 1, + flexDirection: 'row', + }, + verticalAlignedContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + titleText: { + fontSize: 18, + color: colors.text.default, + ...fontStyles.normal, + }, + collectibleIcon: { + width: COLLECTIBLE_WIDTH, + height: COLLECTIBLE_WIDTH, + }, + collectibleInTheMiddle: { + marginHorizontal: 8, + }, + collectiblesRowContainer: { + flex: 1, + flexDirection: 'row', + marginTop: 15, + }, + collectibleBox: { + flex: 1, + flexDirection: 'row', + }, + favoritesLogoWrapper: { + flex: 1, + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + // This yellow doesn't change colors between themes + backgroundColor: importedColors.yellow, + width: 32, + height: 32, + borderRadius: 16, + }, + }); const splitIntoSubArrays = (array, count) => { const newArray = []; @@ -90,6 +93,8 @@ function CollectibleContractElement({ const [collectiblesVisible, setCollectiblesVisible] = useState(propsCollectiblesVisible); const actionSheetRef = useRef(); const longPressedCollectible = useRef(null); + const { colors, themeAppearance } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const toggleCollectibles = useCallback(() => { setCollectiblesVisible(!collectiblesVisible); @@ -152,7 +157,7 @@ function CollectibleContractElement({ ); }, - [asset.favorites, collectibleContracts, onPressCollectible, onLongPressCollectible] + [asset.favorites, collectibleContracts, onPressCollectible, onLongPressCollectible, styles] ); useEffect(() => { @@ -167,7 +172,7 @@ function CollectibleContractElement({ @@ -184,7 +189,7 @@ function CollectibleContractElement({ /> ) : ( - + )} @@ -211,6 +216,7 @@ function CollectibleContractElement({ destructiveButtonIndex={1} // eslint-disable-next-line react/jsx-no-bind onPress={handleMenuAction} + theme={themeAppearance} /> ); diff --git a/app/components/UI/CollectibleContractInformation/index.js b/app/components/UI/CollectibleContractInformation/index.js index 8fa0f3e73b7..84b657bfc8a 100644 --- a/app/components/UI/CollectibleContractInformation/index.js +++ b/app/components/UI/CollectibleContractInformation/index.js @@ -10,98 +10,101 @@ import { InteractionManager, Image, } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import Device from '../../../util/device'; import { connect } from 'react-redux'; import { isMainNet } from '../../../util/networks'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - borderRadius: 10, - minHeight: 450, - }, - titleWrapper: { - borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - }, - title: { - textAlign: 'center', - fontSize: 18, - marginVertical: 12, - marginHorizontal: 20, - color: colors.fontPrimary, - ...fontStyles.bold, - }, - label: { - marginTop: 0, - borderColor: colors.grey100, - ...fontStyles.bold, - }, - informationWrapper: { - flex: 1, - paddingHorizontal: 20, - }, - content: { - fontSize: 16, - color: colors.grey400, - paddingTop: 10, - ...fontStyles.normal, - }, - address: { - fontSize: 12, - }, - row: { - marginVertical: 10, - }, - footer: { - borderTopWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - height: 60, - justifyContent: 'center', - flexDirection: 'row', - alignItems: 'center', - }, - footerButton: { - flex: 1, - alignContent: 'center', - alignItems: 'center', - justifyContent: 'center', - height: 60, - }, - closeButton: { - fontSize: 16, - color: colors.blue, - ...fontStyles.normal, - }, - opensea: { - fontSize: 8, - textAlignVertical: 'center', - paddingRight: 5, - marginTop: Device.isAndroid() ? -2 : 4, - color: colors.fontSecondary, - ...fontStyles.light, - }, - credits: { - flex: 1, - flexDirection: 'row', - alignItems: 'center', - textAlign: 'center', - }, - openSeaLogo: { - width: 80, - height: 20, - resizeMode: 'contain', - }, - creditsView: { - alignItems: 'center', - marginTop: 15, - }, - creditsElements: { - flexDirection: 'row', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + borderRadius: 10, + minHeight: 450, + }, + titleWrapper: { + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + }, + title: { + textAlign: 'center', + fontSize: 18, + marginVertical: 12, + marginHorizontal: 20, + color: colors.text.default, + ...fontStyles.bold, + }, + label: { + marginTop: 0, + borderColor: colors.border.muted, + ...fontStyles.bold, + color: colors.text.default, + }, + informationWrapper: { + flex: 1, + paddingHorizontal: 20, + }, + content: { + fontSize: 16, + color: colors.text.alternative, + paddingTop: 10, + ...fontStyles.normal, + }, + address: { + fontSize: 12, + }, + row: { + marginVertical: 10, + }, + footer: { + borderTopWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + height: 60, + justifyContent: 'center', + flexDirection: 'row', + alignItems: 'center', + }, + footerButton: { + flex: 1, + alignContent: 'center', + alignItems: 'center', + justifyContent: 'center', + height: 60, + }, + closeButton: { + fontSize: 16, + color: colors.primary.default, + ...fontStyles.normal, + }, + opensea: { + fontSize: 8, + textAlignVertical: 'center', + paddingRight: 5, + marginTop: Device.isAndroid() ? -2 : 4, + color: colors.text.alternative, + ...fontStyles.light, + }, + credits: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + textAlign: 'center', + }, + openSeaLogo: { + width: 80, + height: 20, + resizeMode: 'contain', + }, + creditsView: { + alignItems: 'center', + marginTop: 15, + }, + creditsElements: { + flexDirection: 'row', + }, + }); const openSeaLogo = require('../../../images/opensea-logo-flat-colored-blue.png'); // eslint-disable-line @@ -152,6 +155,8 @@ class CollectibleContractInformation extends PureComponent { collectibleContract: { name, description, totalSupply, address }, network, } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); const is_main_net = isMainNet(network); return ( @@ -204,4 +209,6 @@ const mapStateToProps = (state) => ({ network: state.engine.backgroundState.NetworkController, }); +CollectibleContractInformation.contextType = ThemeContext; + export default connect(mapStateToProps)(CollectibleContractInformation); diff --git a/app/components/UI/CollectibleContractOverview/index.js b/app/components/UI/CollectibleContractOverview/index.js index 97283d2bf0f..e0eb15c920d 100644 --- a/app/components/UI/CollectibleContractOverview/index.js +++ b/app/components/UI/CollectibleContractOverview/index.js @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import { StyleSheet, Text, View } from 'react-native'; import PropTypes from 'prop-types'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import CollectibleMedia from '../CollectibleMedia'; import AssetActionButton from '../AssetActionButton'; @@ -12,39 +12,41 @@ import collectiblesTransferInformation from '../../../util/collectibles-transfer import { newAssetTransaction } from '../../../actions/transaction'; import { toLowerCaseEquals } from '../../../util/general'; import { collectiblesSelector } from '../../../reducers/collectibles'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - flex: 1, - paddingHorizontal: 20, - borderBottomWidth: StyleSheet.hairlineWidth, - borderBottomColor: colors.grey100, - alignContent: 'center', - alignItems: 'center', - paddingBottom: 30, - }, - assetLogo: { - marginTop: 20, - }, - information: { - flex: 1, - flexDirection: 'row', - marginTop: 10, - marginBottom: 20, - }, - name: { - fontSize: 30, - textAlign: 'center', - color: colors.fontPrimary, - ...fontStyles.normal, - }, - actions: { - width: Device.isSmallDevice() ? '65%' : '50%', - justifyContent: 'space-around', - alignItems: 'flex-start', - flexDirection: 'row', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + flex: 1, + paddingHorizontal: 20, + borderBottomWidth: StyleSheet.hairlineWidth, + borderBottomColor: colors.border.muted, + alignContent: 'center', + alignItems: 'center', + paddingBottom: 30, + }, + assetLogo: { + marginTop: 20, + }, + information: { + flex: 1, + flexDirection: 'row', + marginTop: 10, + marginBottom: 20, + }, + name: { + fontSize: 30, + textAlign: 'center', + color: colors.text.default, + ...fontStyles.normal, + }, + actions: { + width: Device.isSmallDevice() ? '65%' : '50%', + justifyContent: 'space-around', + alignItems: 'flex-start', + flexDirection: 'row', + }, + }); /** * View that displays a specific collectible contract @@ -107,6 +109,8 @@ class CollectibleContractOverview extends PureComponent { collectibleContract: { name, address }, ownerOf, } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); const lowerAddress = address.toLowerCase(); const leftActionButtonText = lowerAddress in collectiblesTransferInformation @@ -149,4 +153,6 @@ const mapDispatchToProps = (dispatch) => ({ newAssetTransaction: (selectedAsset) => dispatch(newAssetTransaction(selectedAsset)), }); +CollectibleContractOverview.contextType = ThemeContext; + export default connect(mapStateToProps, mapDispatchToProps)(CollectibleContractOverview); diff --git a/app/components/UI/CollectibleContracts/index.js b/app/components/UI/CollectibleContracts/index.js index 849403432e7..c83afdee230 100644 --- a/app/components/UI/CollectibleContracts/index.js +++ b/app/components/UI/CollectibleContracts/index.js @@ -2,7 +2,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import PropTypes from 'prop-types'; import { TouchableOpacity, StyleSheet, View, InteractionManager, Image } from 'react-native'; import { connect } from 'react-redux'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import Engine from '../../../core/Engine'; import CollectibleContractElement from '../CollectibleContractElement'; @@ -21,57 +21,60 @@ import { toLowerCaseEquals } from '../../../util/general'; import { compareTokenIds } from '../../../util/tokens'; import CollectibleDetectionModal from '../CollectibleDetectionModal'; import { isMainNet } from '../../../util/networks'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - minHeight: 500, - marginTop: 16, - }, - emptyView: { - justifyContent: 'center', - alignItems: 'center', - marginTop: 10, - }, - add: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - }, - addText: { - fontSize: 14, - color: colors.blue, - ...fontStyles.normal, - }, - footer: { - flex: 1, - paddingBottom: 30, - alignItems: 'center', - marginTop: 24, - }, - emptyContainer: { - flex: 1, - marginBottom: 18, - justifyContent: 'center', - alignItems: 'center', - }, - emptyImageContainer: { - width: 76, - height: 76, - marginTop: 30, - marginBottom: 12, - }, - emptyTitleText: { - fontSize: 24, - color: colors.grey200, - }, - emptyText: { - color: colors.greyAssetVisibility, - marginBottom: 8, - fontSize: 14, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + minHeight: 500, + marginTop: 16, + }, + emptyView: { + justifyContent: 'center', + alignItems: 'center', + marginTop: 10, + }, + add: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + addText: { + fontSize: 14, + color: colors.primary.default, + ...fontStyles.normal, + }, + footer: { + flex: 1, + paddingBottom: 30, + alignItems: 'center', + marginTop: 24, + }, + emptyContainer: { + flex: 1, + marginBottom: 18, + justifyContent: 'center', + alignItems: 'center', + }, + emptyImageContainer: { + width: 76, + height: 76, + marginTop: 30, + marginBottom: 12, + tintColor: colors.icon.default, + }, + emptyTitleText: { + fontSize: 24, + color: colors.text.alternative, + }, + emptyText: { + color: colors.text.alternative, + marginBottom: 8, + fontSize: 14, + }, + }); /** * View that renders a list of CollectibleContract @@ -89,6 +92,8 @@ const CollectibleContracts = ({ setNftDetectionDismissed, nftDetectionDismissed, }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const [isAddNFTEnabled, setIsAddNFTEnabled] = useState(true); const onItemPress = useCallback( diff --git a/app/components/UI/CollectibleDetectionModal/index.tsx b/app/components/UI/CollectibleDetectionModal/index.tsx index a1cd1b3db69..606419682e8 100644 --- a/app/components/UI/CollectibleDetectionModal/index.tsx +++ b/app/components/UI/CollectibleDetectionModal/index.tsx @@ -25,9 +25,12 @@ interface Props { const CollectibleDetectionModal = ({ onDismiss, navigation }: Props) => { const goToSecuritySettings = () => { navigation.navigate('SettingsView', { - screen: 'SecuritySettings', + screen: 'SettingsFlow', params: { - scrollToBottom: true, + screen: 'SecuritySettings', + params: { + scrollToBottom: true, + }, }, }); }; diff --git a/app/components/UI/CollectibleMedia/__snapshots__/index.test.tsx.snap b/app/components/UI/CollectibleMedia/__snapshots__/index.test.tsx.snap index d523f9a4eb7..1956178f72f 100644 --- a/app/components/UI/CollectibleMedia/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/CollectibleMedia/__snapshots__/index.test.tsx.snap @@ -15,7 +15,7 @@ exports[`CollectibleMedia should render correctly 1`] = ` Array [ Object { "alignItems": "center", - "backgroundColor": "#d6d9dc", + "backgroundColor": "#F2F4F6", "borderRadius": 8, "justifyContent": "center", }, diff --git a/app/components/UI/CollectibleMedia/index.js b/app/components/UI/CollectibleMedia/index.js index c9db97732dd..90fa3a04ec9 100644 --- a/app/components/UI/CollectibleMedia/index.js +++ b/app/components/UI/CollectibleMedia/index.js @@ -3,62 +3,65 @@ import PropTypes from 'prop-types'; import { StyleSheet, View, ViewPropTypes } from 'react-native'; import RemoteImage from '../../Base/RemoteImage'; import MediaPlayer from '../../Views/MediaPlayer'; -import { colors } from '../../../styles/common'; import scaling from '../../../util/scaling'; import Text from '../../Base/Text'; import Device from '../../../util/device'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; const MEDIA_WIDTH_MARGIN = Device.isMediumDevice() ? 32 : 0; -const styles = StyleSheet.create({ - container(backgroundColor) { - return { - flex: 0, +const createStyles = (colors) => + StyleSheet.create({ + container(backgroundColor) { + return { + flex: 0, + borderRadius: 12, + backgroundColor: `#${backgroundColor}`, + }; + }, + tinyImage: { + width: 32, + height: 32, + }, + smallImage: { + width: 50, + height: 50, + }, + bigImage: { + height: 260, + width: 260, + }, + cover: { + height: scaling.scale(Device.getDeviceWidth() - MEDIA_WIDTH_MARGIN, { baseModel: 2 }), + }, + image: { borderRadius: 12, - backgroundColor: `#${backgroundColor}`, - }; - }, - tinyImage: { - width: 32, - height: 32, - }, - smallImage: { - width: 50, - height: 50, - }, - bigImage: { - height: 260, - width: 260, - }, - cover: { - height: scaling.scale(Device.getDeviceWidth() - MEDIA_WIDTH_MARGIN, { baseModel: 2 }), - }, - image: { - borderRadius: 12, - }, - textContainer: { - alignItems: 'center', - justifyContent: 'center', - backgroundColor: colors.grey100, - borderRadius: 8, - }, - textWrapper: { - textAlign: 'center', - }, - textWrapperIcon: { - textAlign: 'center', - fontSize: 18, - }, - mediaPlayer: { - minHeight: 10, - }, -}); + }, + textContainer: { + alignItems: 'center', + justifyContent: 'center', + backgroundColor: colors.background.alternative, + borderRadius: 8, + }, + textWrapper: { + textAlign: 'center', + }, + textWrapperIcon: { + textAlign: 'center', + fontSize: 18, + }, + mediaPlayer: { + minHeight: 10, + }, + }); /** * View that renders an ERC-721 Token image */ export default function CollectibleMedia({ collectible, renderAnimation, style, tiny, small, big, cover, onClose }) { const [sourceUri, setSourceUri] = useState(null); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const fallback = () => setSourceUri(null); @@ -116,7 +119,7 @@ export default function CollectibleMedia({ collectible, renderAnimation, style, ); - }, [collectible, sourceUri, onClose, renderAnimation, style, tiny, small, big, cover]); + }, [collectible, sourceUri, onClose, renderAnimation, style, tiny, small, big, cover, styles]); return {renderMedia()}; } diff --git a/app/components/UI/CollectibleMediaReproductor/index.js b/app/components/UI/CollectibleMediaReproductor/index.js index 68c5b94c9b0..e4ef17b5593 100644 --- a/app/components/UI/CollectibleMediaReproductor/index.js +++ b/app/components/UI/CollectibleMediaReproductor/index.js @@ -3,8 +3,8 @@ import PropTypes from 'prop-types'; import { StyleSheet, View } from 'react-native'; import RemoteImage from '../../Base/RemoteImage'; import Identicon from '../Identicon'; -import { colors } from '../../../styles/common'; import MediaPlayer from '../../Views/MediaPlayer'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; const styles = StyleSheet.create({ listWrapper: { @@ -34,6 +34,7 @@ const styles = StyleSheet.create({ * View that renders an ERC-721 Token image */ export default function CollectibleMediaPlayer({ collectible, renderFull, containerStyle, iconStyle }) { + const { colors } = useAppThemeFromContext() || mockTheme; const [fallbackImage, setFallbackImage] = useState(null); const fallback = () => { @@ -55,7 +56,7 @@ export default function CollectibleMediaPlayer({ collectible, renderFull, contai + StyleSheet.create({ + wrapper: { + flex: 0, + backgroundColor: colors.background.default, + borderTopEndRadius: 8, + borderTopStartRadius: 8, + }, + generalContainer: { + paddingHorizontal: 16, + }, + information: { + paddingTop: HAS_NOTCH ? 24 : VERTICAL_ALIGNMENT, + }, + row: { + paddingVertical: 6, + }, + name: { + fontSize: Device.isSmallDevice() ? 16 : 24, + marginBottom: 3, + }, + userContainer: { + flexDirection: 'row', + paddingBottom: 16, + }, + userImage: { + width: 38, + height: 38, + borderRadius: 100, + marginRight: 8, + }, + buttonContainer: { + flexDirection: 'row', + marginTop: VERTICAL_ALIGNMENT, + }, + button: { + alignItems: 'center', + justifyContent: 'center', + borderWidth: 1.5, + }, + iconButtons: { + width: 54, + height: 54, + }, + leftButton: { + marginRight: 16, + }, + collectibleInfoContainer: { + flexDirection: 'row', + marginHorizontal: 16, + marginBottom: 8, + }, + collectibleInfoKey: { + paddingRight: 10, + }, + collectibleDescription: { + lineHeight: 22, + }, + userInfoContainer: { + justifyContent: 'center', + }, + titleWrapper: { + width: '100%', + alignItems: 'center', + justifyContent: 'center', + paddingVertical: VERTICAL_ALIGNMENT, + }, + dragger: { + width: 48, + height: 5, + borderRadius: 4, + backgroundColor: colors.border.default, + }, + scrollableDescription: { + maxHeight: Device.getDeviceHeight() / 5, + }, + description: { + marginTop: 8, + }, + }); /** * View that displays the information of a specific ERC-721 Token @@ -128,6 +130,8 @@ const CollectibleOverview = ({ const [position, setPosition] = useState(0); const positionAnimated = useRef(new Animated.Value(0)).current; const scrollViewRef = useRef(null); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const translationHeight = useMemo( () => wrapperHeight - headerHeight - ANIMATION_OFFSET, @@ -140,29 +144,32 @@ const CollectibleOverview = ({ return collectible?.description?.length > maxLength; }, [collectible.description]); - const renderCollectibleInfoRow = useCallback((key, value, onPress) => { - if (!value) return null; - return ( - - - {key} - - - {value} - - - ); - }, []); + const renderCollectibleInfoRow = useCallback( + (key, value, onPress) => { + if (!value) return null; + return ( + + + {key} + + + {value} + + + ); + }, + [styles] + ); const renderCollectibleInfo = () => [ renderCollectibleInfoRow(strings('collectible.collectible_token_standard'), collectible?.standard), @@ -287,7 +294,7 @@ const CollectibleOverview = ({ diff --git a/app/components/UI/Collectibles/__snapshots__/index.test.tsx.snap b/app/components/UI/Collectibles/__snapshots__/index.test.tsx.snap index f95a386c50c..6929e44e20b 100644 --- a/app/components/UI/Collectibles/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/Collectibles/__snapshots__/index.test.tsx.snap @@ -13,7 +13,13 @@ exports[`Collectibles should render correctly 1`] = ` } > @@ -30,7 +36,7 @@ exports[`Collectibles should render correctly 1`] = ` + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + emptyView: { + backgroundColor: colors.background.default, + justifyContent: 'center', + alignItems: 'center', + marginTop: 50, + }, + text: { + fontSize: 20, + color: colors.text.muted, + ...fontStyles.normal, + }, + itemWrapper: { + flex: 1, + flexDirection: 'row', + }, + rows: { + flex: 1, + marginLeft: 20, + marginTop: 6, + }, + name: { + fontSize: 16, + color: colors.text.default, + ...fontStyles.normal, + }, + tokenId: { + fontSize: 12, + marginTop: 4, + marginRight: 8, + color: colors.text.alternative, + ...fontStyles.normal, + }, + }); /** * View that renders a list of Collectibles @@ -80,13 +82,26 @@ export default class Collectibles extends PureComponent { longPressedCollectible = null; - renderEmpty = () => ( - }> - - {strings('wallet.no_collectibles')} - - - ); + renderEmpty = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + } + > + + {strings('wallet.no_collectibles')} + + + ); + }; onItemPress = (collectible) => { this.props.navigation.navigate('CollectibleView', { @@ -140,20 +155,25 @@ export default class Collectibles extends PureComponent { keyExtractor = (item) => `${item.address}_${item.tokenId}`; - renderItem = ({ item }) => ( - - - - - {item.name} - - {strings('unit.token_id')} - {item.tokenId} - + renderItem = ({ item }) => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + + + + {item.name} + + {strings('unit.token_id')} + {item.tokenId} + + - - - ); + + ); + }; renderCollectiblesList() { const { collectibles } = this.props; @@ -170,6 +190,10 @@ export default class Collectibles extends PureComponent { render() { const { collectibles } = this.props; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance; + const styles = createStyles(colors); + return ( {collectibles && collectibles.length ? this.renderCollectiblesList() : this.renderEmpty()} @@ -181,8 +205,11 @@ export default class Collectibles extends PureComponent { destructiveButtonIndex={1} // eslint-disable-next-line react/jsx-no-bind onPress={this.handleMenuAction} + theme={themeAppearance} /> ); } } + +Collectibles.contextType = ThemeContext; diff --git a/app/components/UI/ConnectHeader/index.js b/app/components/UI/ConnectHeader/index.js index d0cc545738a..7a944c2c045 100644 --- a/app/components/UI/ConnectHeader/index.js +++ b/app/components/UI/ConnectHeader/index.js @@ -2,28 +2,30 @@ import React, { Component } from 'react'; import { View, StyleSheet, Text, TouchableOpacity } from 'react-native'; import PropTypes from 'prop-types'; import IonicIcon from 'react-native-vector-icons/Ionicons'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - header: { - width: '100%', - position: 'relative', - paddingBottom: 20, - }, - title: { - ...fontStyles.bold, - color: colors.black, - fontSize: 14, - textAlign: 'center', - paddingVertical: 12, - }, - back: { - position: 'absolute', - zIndex: 1, - paddingVertical: 10, - paddingRight: 10, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + header: { + width: '100%', + position: 'relative', + paddingBottom: 20, + }, + title: { + ...fontStyles.bold, + color: colors.text.default, + fontSize: 14, + textAlign: 'center', + paddingVertical: 12, + }, + back: { + position: 'absolute', + zIndex: 1, + paddingVertical: 10, + paddingRight: 10, + }, + }); class ConnectHeader extends Component { static propTypes = { @@ -33,10 +35,13 @@ class ConnectHeader extends Component { render() { const { title, action } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( - + {title} @@ -44,4 +49,6 @@ class ConnectHeader extends Component { } } +ConnectHeader.contextType = ThemeContext; + export default ConnectHeader; diff --git a/app/components/UI/CustomAlert/__snapshots__/index.test.tsx.snap b/app/components/UI/CustomAlert/__snapshots__/index.test.tsx.snap index 7bf6b00b6f6..eddaa51a6ff 100644 --- a/app/components/UI/CustomAlert/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/CustomAlert/__snapshots__/index.test.tsx.snap @@ -7,8 +7,8 @@ exports[`CustomAlert should render correctly 1`] = ` animationOut="slideOutDown" animationOutTiming={300} avoidKeyboard={false} - backdropColor="black" - backdropOpacity={0.7} + backdropColor="#00000099" + backdropOpacity={1} backdropTransitionInTiming={300} backdropTransitionOutTiming={300} coverScreen={true} diff --git a/app/components/UI/CustomAlert/index.js b/app/components/UI/CustomAlert/index.js index 986ae8fce08..370ea1c68ed 100644 --- a/app/components/UI/CustomAlert/index.js +++ b/app/components/UI/CustomAlert/index.js @@ -3,38 +3,40 @@ import { ViewPropTypes, StyleSheet, View, Text } from 'react-native'; import PropTypes from 'prop-types'; import Modal from 'react-native-modal'; import StyledButton from '../StyledButton'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - modal: { - padding: 20, - }, - content: { - backgroundColor: colors.white, - borderRadius: 16, - }, - header: { - paddingVertical: 15, - height: 130, - alignItems: 'center', - borderTopEndRadius: 16, - borderTopLeftRadius: 16, - }, - body: { - paddingVertical: 20, - paddingHorizontal: 35, - }, - title: { - textAlign: 'center', - fontSize: 16, - ...fontStyles.bold, - marginBottom: 15, - }, - footer: { - padding: 20, - paddingTop: 10, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + modal: { + padding: 20, + }, + content: { + backgroundColor: colors.background.default, + borderRadius: 16, + }, + header: { + paddingVertical: 15, + height: 130, + alignItems: 'center', + borderTopEndRadius: 16, + borderTopLeftRadius: 16, + }, + body: { + paddingVertical: 20, + paddingHorizontal: 35, + }, + title: { + textAlign: 'center', + fontSize: 16, + ...fontStyles.bold, + marginBottom: 15, + }, + footer: { + padding: 20, + paddingTop: 10, + }, + }); /** /* PureComponent that renders our custom alerts, which contains @@ -89,12 +91,17 @@ export default class CustomAlert extends PureComponent { }; render() { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( {this.props.headerContent} @@ -112,3 +119,5 @@ export default class CustomAlert extends PureComponent { ); } } + +CustomAlert.contextType = ThemeContext; diff --git a/app/components/UI/CustomNonce/__snapshots__/index.test.tsx.snap b/app/components/UI/CustomNonce/__snapshots__/index.test.tsx.snap index 976f0640338..204f23b8303 100644 --- a/app/components/UI/CustomNonce/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/CustomNonce/__snapshots__/index.test.tsx.snap @@ -4,7 +4,7 @@ exports[`CustomNonce should render correctly 1`] = ` + StyleSheet.create({ + customNonce: { + marginTop: 10, + marginHorizontal: 24, + borderWidth: 1, + borderColor: colors.border.default, + borderRadius: 8, + paddingVertical: 14, + paddingHorizontal: 16, + display: 'flex', + flexDirection: 'row', + }, + nonceNumber: { + marginLeft: 'auto', + }, + }); -const CustomNonce = ({ nonce, onNonceEdit }) => ( - - - {strings('transaction.custom_nonce')} - - - {' '} - {strings('transaction.edit')} - - - {nonce} - - -); +const CustomNonce = ({ nonce, onNonceEdit }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + + {strings('transaction.custom_nonce')} + + + {' '} + {strings('transaction.edit')} + + + {nonce} + + + ); +}; CustomNonce.propTypes = { /** diff --git a/app/components/UI/CustomNonceModal/__snapshots__/index.test.tsx.snap b/app/components/UI/CustomNonceModal/__snapshots__/index.test.tsx.snap index cf0de621278..8515cc6a74c 100644 --- a/app/components/UI/CustomNonceModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/CustomNonceModal/__snapshots__/index.test.tsx.snap @@ -7,8 +7,8 @@ exports[`CustomNonceModal should render correctly 1`] = ` animationOut="slideOutDown" animationOutTiming={600} avoidKeyboard={false} - backdropColor="black" - backdropOpacity={0.7} + backdropColor="#00000099" + backdropOpacity={1} backdropTransitionInTiming={300} backdropTransitionOutTiming={300} coverScreen={true} @@ -98,7 +98,7 @@ exports[`CustomNonceModal should render correctly 1`] = ` strikethrough={false} style={ Object { - "color": "#24292E", + "color": "#24272A", "fontSize": 14, } } @@ -122,17 +122,18 @@ exports[`CustomNonceModal should render correctly 1`] = ` autoCapitalize="none" autoCorrect={false} editable={true} + keyboardAppearance="light" keyboardType="numeric" numberOfLines={1} onChangeText={[Function]} onSubmitEditing={[Function]} placeholder="26" - placeholderTextColor="#d6d9dc" + placeholderTextColor="#BBC0C5" showSoftInputOnFocus={false} spellCheck={false} style={ Object { - "color": "#24292E", + "color": "#24272A", "fontFamily": "EuclidCircularB-Bold", "fontSize": 36, "fontWeight": "600", @@ -161,7 +162,7 @@ exports[`CustomNonceModal should render correctly 1`] = ` strikethrough={false} style={ Object { - "color": "#6a737d", + "color": "#535A61", "fontSize": 14, "marginBottom": 10, } @@ -216,7 +217,7 @@ exports[`CustomNonceModal should render correctly 1`] = ` size={64} style={ Object { - "color": "#037dd6", + "color": "#037DD6", } } /> @@ -235,7 +236,7 @@ exports[`CustomNonceModal should render correctly 1`] = ` size={64} style={ Object { - "color": "#037dd6", + "color": "#037DD6", } } /> @@ -251,7 +252,7 @@ exports[`CustomNonceModal should render correctly 1`] = ` + StyleSheet.create({ + bottomModal: { + justifyContent: 'flex-end', + margin: 0, + }, + keyboardAwareWrapper: { + flex: 1, + justifyContent: 'flex-end', + }, + modal: { + minHeight: 200, + backgroundColor: colors.background.default, + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + }, + modalContainer: { + margin: 24, + }, + title: { + fontSize: 14, + color: colors.text.default, + }, + nonceInput: { + width: 80, + fontSize: 36, + ...fontStyles.bold, + color: colors.text.default, + textAlign: 'center', + marginHorizontal: 24, + }, + desc: { + color: colors.text.default, + fontSize: 12, + lineHeight: 16, + marginVertical: 10, + }, + nonceInputContainer: { + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + alignSelf: 'center', + marginVertical: 10, + }, + incrementDecrementNonceContainer: { + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + alignSelf: 'center', + }, + currentSuggested: { + fontSize: 14, + color: colors.text.alternative, + marginBottom: 10, + }, + nonceWarning: { + borderWidth: 1, + borderColor: colors.warning.default, + backgroundColor: colors.warning.muted, + padding: 16, + display: 'flex', + flexDirection: 'row', + borderRadius: 8, + marginTop: 10, + marginBottom: 16, + }, + nonceWarningText: { + color: colors.text.default, + fontSize: 12, + lineHeight: 16, + width: '100%', + flex: 1, + }, + descWarningContainer: { + height: 240, + }, + actionRow: { + flexDirection: 'row', + marginBottom: 15, + }, + actionButton: { + flex: 1, + marginHorizontal: 8, + }, + incrementHit: { + padding: 4, + }, + icon: { + flex: 0, + marginTop: 6, + paddingRight: 14, + }, + incrementDecrementIcon: { + color: colors.primary.default, + }, + }); const CustomModalNonce = ({ proposedNonce, nonceValue, close, save }) => { const [nonce, onChangeText] = React.useState(nonceValue); + const { colors, themeAppearance } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const incrementDecrementNonce = (decrement) => { let newValue = nonce; @@ -129,7 +133,8 @@ const CustomModalNonce = ({ proposedNonce, nonceValue, close, save }) => { animationIn="slideInUp" animationOut="slideOutDown" style={styles.bottomModal} - backdropOpacity={0.7} + backdropColor={colors.overlay.default} + backdropOpacity={1} animationInTiming={600} animationOutTiming={600} onBackdropPress={close} @@ -155,13 +160,14 @@ const CustomModalNonce = ({ proposedNonce, nonceValue, close, save }) => { autoCorrect={false} onChangeText={onChangeText} placeholder={String(proposedNonce)} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} spellCheck={false} editable style={styles.nonceInput} value={String(nonce)} numberOfLines={1} onSubmitEditing={saveAndClose} + keyboardAppearance={themeAppearance} /> @@ -183,7 +189,7 @@ const CustomModalNonce = ({ proposedNonce, nonceValue, close, save }) => { diff --git a/app/components/UI/Drawer/index.tsx b/app/components/UI/Drawer/index.tsx index d03f46b2b0a..a5934d0d8ec 100644 --- a/app/components/UI/Drawer/index.tsx +++ b/app/components/UI/Drawer/index.tsx @@ -17,11 +17,11 @@ import Animated, { Extrapolate, } from 'react-native-reanimated'; import { onGestureEvent, withSpring, clamp, timing } from 'react-native-redash/src/v1'; -import { colors } from '../../../styles/common'; import { useNavigation } from '@react-navigation/native'; const screenWidth = Dimensions.get('window').width; import DrawerView from '../DrawerView'; import styles from './styles'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; interface DrawerRef { dismissDrawer: () => void; @@ -39,6 +39,7 @@ const Drawer = forwardRef((props, ref) => { const visibleOffset = 0; const navigation = useNavigation(); const safeAreaInsets = useSafeAreaInsets(); + const { colors } = useAppThemeFromContext() || mockTheme; // Animation config const animationConfig: Omit = { @@ -99,7 +100,7 @@ const Drawer = forwardRef((props, ref) => { const animatedStyles: StyleSheet.NamedStyles = useMemo(() => { return { overlayBackground: { - backgroundColor: colors.overlay, + backgroundColor: colors.overlay.default, ...styles.absoluteFill, opacity: interpolateNode(translateX, { inputRange: [hiddenOffset + 1, visibleOffset], @@ -131,7 +132,7 @@ const Drawer = forwardRef((props, ref) => { ...StyleSheet.absoluteFillObject, }, }; - }, [hiddenOffset, visibleOffset, translateX, safeAreaInsets]); + }, [hiddenOffset, visibleOffset, translateX, safeAreaInsets, colors]); // Declarative logic that animates overlay useCode( diff --git a/app/components/UI/DrawerView/index.js b/app/components/UI/DrawerView/index.js index b6dd86a2b0a..27e36ed002e 100644 --- a/app/components/UI/DrawerView/index.js +++ b/app/components/UI/DrawerView/index.js @@ -6,7 +6,7 @@ import Share from 'react-native-share'; import Icon from 'react-native-vector-icons/FontAwesome'; import FeatherIcon from 'react-native-vector-icons/Feather'; import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { hasBlockExplorer, findBlockExplorerForRpc, getBlockExplorerName } from '../../../util/networks'; import Identicon from '../Identicon'; import StyledButton from '../StyledButton'; @@ -45,221 +45,237 @@ import { collectiblesSelector } from '../../../reducers/collectibles'; import { getCurrentRoute } from '../../../reducers/navigation'; import { ScrollView } from 'react-native-gesture-handler'; import { isZero } from '../../../util/lodash'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - flex: 1, - width: 315, - backgroundColor: colors.white, - }, - header: { - paddingTop: Device.isIphoneX() ? 60 : 24, - backgroundColor: colors.grey000, - height: Device.isIphoneX() ? 110 : 74, - flexDirection: 'column', - paddingBottom: 0, - }, - metamaskLogo: { - flexDirection: 'row', - flex: 1, - marginTop: Device.isAndroid() ? 0 : 12, - marginLeft: 15, - paddingTop: Device.isAndroid() ? 10 : 0, - }, - metamaskFox: { - height: 27, - width: 27, - marginRight: 15, - }, - metamaskName: { - marginTop: 4, - width: 90, - height: 18, - }, - account: { - flex: 1, - backgroundColor: colors.grey000, - }, - accountBgOverlay: { - borderBottomColor: colors.grey100, - borderBottomWidth: 1, - padding: 17, - }, - identiconWrapper: { - marginBottom: 12, - width: 56, - height: 56, - }, - identiconBorder: { - borderRadius: 96, - borderWidth: 2, - padding: 2, - borderColor: colors.blue, - }, - accountNameWrapper: { - flexDirection: 'row', - paddingRight: 17, - }, - accountName: { - fontSize: 20, - lineHeight: 24, - marginBottom: 5, - color: colors.fontPrimary, - ...fontStyles.normal, - }, - caretDown: { - textAlign: 'right', - marginLeft: 7, - marginTop: 3, - fontSize: 18, - color: colors.fontPrimary, - }, - accountBalance: { - fontSize: 14, - lineHeight: 17, - marginBottom: 5, - color: colors.fontPrimary, - ...fontStyles.normal, - }, - accountAddress: { - fontSize: 12, - lineHeight: 17, - color: colors.fontSecondary, - ...fontStyles.normal, - }, - buttons: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - borderBottomColor: colors.grey100, - borderBottomWidth: 1, - padding: 15, - }, - button: { - flex: 1, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - borderRadius: 30, - borderWidth: 1.5, - }, - leftButton: { - marginRight: 5, - }, - rightButton: { - marginLeft: 5, - }, - buttonText: { - paddingLeft: 8, - fontSize: 15, - color: colors.blue, - ...fontStyles.normal, - }, - buttonContent: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - }, - buttonIcon: { - marginTop: 0, - }, - buttonReceive: { - transform: [{ rotate: '90deg' }], - }, - menu: {}, - noTopBorder: { - borderTopWidth: 0, - }, - menuSection: { - borderTopWidth: 1, - borderColor: colors.grey100, - paddingVertical: 10, - }, - menuItem: { - flex: 1, - flexDirection: 'row', - paddingVertical: 9, - paddingLeft: 17, - }, - selectedRoute: { - backgroundColor: colors.blue000, - marginRight: 10, - borderTopRightRadius: 20, - borderBottomRightRadius: 20, - }, - selectedName: { - color: colors.blue, - }, - menuItemName: { - flex: 1, - paddingHorizontal: 15, - paddingTop: 2, - fontSize: 16, - color: colors.grey400, - ...fontStyles.normal, - }, - menuItemWarningText: { - color: colors.red, - fontSize: 12, - ...fontStyles.normal, - }, - noIcon: { - paddingLeft: 0, - }, - menuItemIconImage: { - width: 22, - height: 22, - }, - bottomModal: { - justifyContent: 'flex-end', - margin: 0, - }, - importedWrapper: { - marginTop: 10, - width: 73, - paddingHorizontal: 10, - paddingVertical: 3, - borderRadius: 10, - borderWidth: 1, - borderColor: colors.grey400, - }, - importedText: { - color: colors.grey400, - fontSize: 10, - ...fontStyles.bold, - }, - protectWalletContainer: { - backgroundColor: colors.white, - paddingTop: 24, - borderTopLeftRadius: 20, - borderTopRightRadius: 20, - paddingVertical: 16, - paddingBottom: Device.isIphoneX() ? 20 : 0, - paddingHorizontal: 40, - }, - protectWalletIconContainer: { - alignSelf: 'center', - width: 56, - height: 56, - borderRadius: 28, - backgroundColor: colors.red000, - borderColor: colors.red, - borderWidth: 1, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - }, - protectWalletIcon: { alignSelf: 'center', color: colors.red }, - protectWalletTitle: { textAlign: 'center', fontSize: 18, marginVertical: 8, ...fontStyles.bold }, - protectWalletContent: { - textAlign: 'center', - fontSize: 14, - marginVertical: 8, - justifyContent: 'center', - ...fontStyles.normal, - }, - protectWalletButtonWrapper: { marginVertical: 8 }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + flex: 1, + width: 315, + backgroundColor: colors.background.default, + }, + header: { + paddingTop: Device.isIphoneX() ? 60 : 24, + backgroundColor: colors.background.alternative, + height: Device.isIphoneX() ? 110 : 74, + flexDirection: 'column', + paddingBottom: 0, + }, + metamaskLogo: { + flexDirection: 'row', + flex: 1, + marginTop: Device.isAndroid() ? 0 : 12, + marginLeft: 15, + paddingTop: Device.isAndroid() ? 10 : 0, + }, + metamaskFox: { + height: 27, + width: 27, + marginRight: 15, + }, + metamaskName: { + marginTop: 4, + width: 90, + height: 18, + tintColor: colors.text.default, + }, + account: { + flex: 1, + backgroundColor: colors.background.alternative, + }, + accountBgOverlay: { + borderBottomColor: colors.border.muted, + borderBottomWidth: 1, + padding: 17, + }, + identiconWrapper: { + marginBottom: 12, + width: 56, + height: 56, + }, + identiconBorder: { + borderRadius: 96, + borderWidth: 2, + padding: 2, + borderColor: colors.primary.default, + }, + accountNameWrapper: { + flexDirection: 'row', + paddingRight: 17, + }, + accountName: { + fontSize: 20, + lineHeight: 24, + marginBottom: 5, + color: colors.text.default, + ...fontStyles.normal, + }, + caretDown: { + textAlign: 'right', + marginLeft: 7, + marginTop: 3, + fontSize: 18, + color: colors.icon.default, + }, + accountBalance: { + fontSize: 14, + lineHeight: 17, + marginBottom: 5, + color: colors.text.default, + ...fontStyles.normal, + }, + accountAddress: { + fontSize: 12, + lineHeight: 17, + color: colors.text.alternative, + ...fontStyles.normal, + }, + buttons: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + borderBottomColor: colors.border.muted, + borderBottomWidth: 1, + padding: 15, + }, + button: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + borderRadius: 30, + borderWidth: 1.5, + }, + leftButton: { + marginRight: 5, + }, + rightButton: { + marginLeft: 5, + }, + buttonText: { + paddingLeft: 8, + fontSize: 15, + color: colors.primary.default, + ...fontStyles.normal, + }, + buttonContent: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + buttonIcon: { + marginTop: 0, + }, + buttonReceive: { + transform: [{ rotate: '90deg' }], + }, + menu: {}, + noTopBorder: { + borderTopWidth: 0, + }, + menuSection: { + borderTopWidth: 1, + borderColor: colors.border.muted, + paddingVertical: 10, + }, + menuItem: { + flex: 1, + flexDirection: 'row', + paddingVertical: 9, + paddingLeft: 17, + }, + selectedRoute: { + backgroundColor: colors.primary.muted, + marginRight: 10, + borderTopRightRadius: 20, + borderBottomRightRadius: 20, + }, + selectedName: { + color: colors.primary.default, + }, + menuItemName: { + flex: 1, + paddingHorizontal: 15, + paddingTop: 2, + fontSize: 16, + color: colors.text.alternative, + ...fontStyles.normal, + }, + menuItemWarningText: { + color: colors.text.default, + fontSize: 12, + ...fontStyles.normal, + }, + noIcon: { + paddingLeft: 0, + }, + menuItemIconImage: { + width: 22, + height: 22, + tintColor: colors.icon.default, + }, + selectedMenuItemIconImage: { + width: 22, + height: 22, + tintColor: colors.primary.default, + }, + bottomModal: { + justifyContent: 'flex-end', + margin: 0, + }, + importedWrapper: { + marginTop: 10, + width: 73, + paddingHorizontal: 10, + paddingVertical: 3, + borderRadius: 10, + borderWidth: 1, + color: colors.icon.default, + }, + importedText: { + color: colors.icon.default, + fontSize: 10, + ...fontStyles.bold, + }, + protectWalletContainer: { + backgroundColor: colors.background.default, + paddingTop: 24, + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + paddingVertical: 16, + paddingBottom: Device.isIphoneX() ? 20 : 0, + paddingHorizontal: 40, + }, + protectWalletIconContainer: { + alignSelf: 'center', + width: 56, + height: 56, + borderRadius: 28, + backgroundColor: colors.error.muted, + borderColor: colors.error.default, + borderWidth: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + protectWalletIcon: { alignSelf: 'center', color: colors.error.default }, + protectWalletTitle: { + textAlign: 'center', + fontSize: 18, + marginVertical: 8, + ...fontStyles.bold, + color: colors.text.default, + }, + protectWalletContent: { + textAlign: 'center', + fontSize: 14, + marginVertical: 8, + justifyContent: 'center', + ...fontStyles.normal, + color: colors.text.default, + }, + protectWalletButtonWrapper: { marginVertical: 8 }, + }); const metamask_name = require('../../../images/metamask-name.png'); // eslint-disable-line const metamask_fox = require('../../../images/fox.png'); // eslint-disable-line @@ -696,35 +712,53 @@ class DrawerView extends PureComponent { }; getIcon(name, size) { - return ; + const colors = this.context.colors || mockTheme.colors; + + return ; } getFeatherIcon(name, size) { - return ; + const colors = this.context.colors || mockTheme.colors; + + return ; } getMaterialIcon(name, size) { - return ; + const colors = this.context.colors || mockTheme.colors; + + return ; } getImageIcon(name) { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ; } getSelectedIcon(name, size) { - return ; + const colors = this.context.colors || mockTheme.colors; + + return ; } getSelectedFeatherIcon(name, size) { - return ; + const colors = this.context.colors || mockTheme.colors; + + return ; } getSelectedMaterialIcon(name, size) { - return ; + const colors = this.context.colors || mockTheme.colors; + + return ; } getSelectedImageIcon(name) { - return ; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ; } getSections = () => { @@ -867,34 +901,40 @@ class DrawerView extends PureComponent { }); }; - renderProtectModal = () => ( - - - - - - {strings('protect_your_wallet_modal.title')} - - {!this.props.passwordSet - ? strings('protect_your_wallet_modal.body_for_password') - : strings('protect_your_wallet_modal.body_for_seedphrase')} - - - - {strings('protect_your_wallet_modal.button')} - + renderProtectModal = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + + + + + {strings('protect_your_wallet_modal.title')} + + {!this.props.passwordSet + ? strings('protect_your_wallet_modal.body_for_password') + : strings('protect_your_wallet_modal.body_for_seedphrase')} + + + + {strings('protect_your_wallet_modal.button')} + + - - - ); + + ); + }; render() { const { @@ -908,6 +948,8 @@ class DrawerView extends PureComponent { seedphraseBackedUp, currentRoute, } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); const { invalidCustomNetwork, @@ -990,7 +1032,7 @@ class DrawerView extends PureComponent { {strings('drawer.send_button')} @@ -1006,7 +1048,7 @@ class DrawerView extends PureComponent { {strings('drawer.receive_button')} @@ -1084,6 +1126,8 @@ class DrawerView extends PureComponent { onSwipeComplete={this.toggleNetworksModal} swipeDirection={'down'} propagateSwipe + backdropColor={colors.overlay.default} + backdropOpacity={1} > - + ({ logOut: () => dispatch(logOut()), }); +DrawerView.contextType = ThemeContext; + export default connect(mapStateToProps, mapDispatchToProps)(DrawerView); diff --git a/app/components/UI/EditGasFee1559/__snapshots__/index.test.tsx.snap b/app/components/UI/EditGasFee1559/__snapshots__/index.test.tsx.snap index b27109658f9..ca1ef8a3751 100644 --- a/app/components/UI/EditGasFee1559/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/EditGasFee1559/__snapshots__/index.test.tsx.snap @@ -38,7 +38,7 @@ exports[`EditGasFee1559 should render correctly 1`] = ` @@ -360,7 +360,7 @@ exports[`EditGasFee1559 should render correctly 1`] = ` size={14} style={ Object { - "color": "#bbc0c5", + "color": "#BBC0C5", } } /> @@ -430,7 +430,7 @@ exports[`EditGasFee1559 should render correctly 1`] = ` size={14} style={ Object { - "color": "#bbc0c5", + "color": "#BBC0C5", } } /> @@ -548,7 +548,7 @@ exports[`EditGasFee1559 should render correctly 1`] = ` size={14} style={ Object { - "color": "#bbc0c5", + "color": "#BBC0C5", } } /> diff --git a/app/components/UI/EditGasFee1559/index.js b/app/components/UI/EditGasFee1559/index.js index 6d93fd804c7..89072cba69a 100644 --- a/app/components/UI/EditGasFee1559/index.js +++ b/app/components/UI/EditGasFee1559/index.js @@ -6,7 +6,6 @@ import Text from '../../Base/Text'; import StyledButton from '../StyledButton'; import RangeInput from '../../Base/RangeInput'; import MaterialCommunityIcon from 'react-native-vector-icons/MaterialCommunityIcons'; -import { colors } from '../../../styles/common'; import InfoModal from '../Swaps/components/InfoModal'; import Icon from 'react-native-vector-icons/Ionicons'; import { strings } from '../../../../locales/i18n'; @@ -21,118 +20,121 @@ import AnalyticsV2 from '../../../util/analyticsV2'; import TimeEstimateInfoModal from '../TimeEstimateInfoModal'; import useModalHandler from '../../Base/hooks/useModalHandler'; import AppConstants from '../../../core/AppConstants'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; const GAS_LIMIT_INCREMENT = new BigNumber(1000); const GAS_INCREMENT = new BigNumber(1); const GAS_LIMIT_MIN = new BigNumber(21000); const GAS_MIN = new BigNumber(0); -const styles = StyleSheet.create({ - root: { - backgroundColor: colors.white, - borderTopLeftRadius: 20, - borderTopRightRadius: 20, - minHeight: 200, - maxHeight: '95%', - paddingTop: 24, - paddingBottom: Device.isIphoneX() ? 32 : 24, - }, - wrapper: { - paddingHorizontal: 24, - }, - customGasHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - width: '100%', - paddingBottom: 20, - }, - newGasFeeHeader: { - flexDirection: 'row', - alignItems: 'center', - width: '100%', - justifyContent: 'center', - }, - headerContainer: { - alignItems: 'center', - marginBottom: 22, - }, - headerText: { - fontSize: 48, - flex: 1, - textAlign: 'center', - }, - headerTitle: { - flexDirection: 'row', - }, - saveButton: { - marginBottom: 20, - }, - labelTextContainer: { - flexDirection: 'row', - alignItems: 'center', - }, - hitSlop: { - top: 10, - left: 10, - bottom: 10, - right: 10, - }, - labelInfo: { - color: colors.grey200, - }, - advancedOptionsContainer: { - marginTop: 25, - marginBottom: 30, - }, - advancedOptionsInputsContainer: { - marginTop: 14, - }, - rangeInputContainer: { - marginBottom: 20, - }, - advancedOptionsButton: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - }, - advancedOptionsIcon: { - paddingTop: 1, - marginLeft: 5, - }, - learnMoreLabels: { - marginTop: 9, - }, - /* Add when the learn more link is ready +const createStyles = (colors) => + StyleSheet.create({ + root: { + backgroundColor: colors.background.default, + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + minHeight: 200, + maxHeight: '95%', + paddingTop: 24, + paddingBottom: Device.isIphoneX() ? 32 : 24, + }, + wrapper: { + paddingHorizontal: 24, + }, + customGasHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + width: '100%', + paddingBottom: 20, + }, + newGasFeeHeader: { + flexDirection: 'row', + alignItems: 'center', + width: '100%', + justifyContent: 'center', + }, + headerContainer: { + alignItems: 'center', + marginBottom: 22, + }, + headerText: { + fontSize: 48, + flex: 1, + textAlign: 'center', + }, + headerTitle: { + flexDirection: 'row', + }, + saveButton: { + marginBottom: 20, + }, + labelTextContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + hitSlop: { + top: 10, + left: 10, + bottom: 10, + right: 10, + }, + labelInfo: { + color: colors.text.muted, + }, + advancedOptionsContainer: { + marginTop: 25, + marginBottom: 30, + }, + advancedOptionsInputsContainer: { + marginTop: 14, + }, + rangeInputContainer: { + marginBottom: 20, + }, + advancedOptionsButton: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + advancedOptionsIcon: { + paddingTop: 1, + marginLeft: 5, + }, + learnMoreLabels: { + marginTop: 9, + }, + /* Add when the learn more link is ready learnMoreLink: { marginTop: 14 },*/ - warningTextContainer: { - lineHeight: 20, - paddingLeft: 4, - flex: 1, - }, - warningText: { - lineHeight: 20, - flex: 1, - }, - warningContainer: { - marginBottom: 20, - }, - dappEditGasContainer: { - marginVertical: 20, - }, - subheader: { - marginBottom: 6, - }, - learnMoreModal: { - maxHeight: Device.getDeviceHeight() * 0.7, - }, - redInfo: { - marginLeft: 2, - color: colors.red, - }, -}); + warningTextContainer: { + lineHeight: 20, + paddingLeft: 4, + flex: 1, + }, + warningText: { + lineHeight: 20, + flex: 1, + color: colors.text.default, + }, + warningContainer: { + marginBottom: 20, + }, + dappEditGasContainer: { + marginVertical: 20, + }, + subheader: { + marginBottom: 6, + }, + learnMoreModal: { + maxHeight: Device.getDeviceHeight() * 0.7, + }, + redInfo: { + marginLeft: 2, + color: colors.error.default, + }, + }); const EditGasFee1559 = ({ selected, @@ -179,6 +181,8 @@ const EditGasFee1559 = ({ const [showInputs, setShowInputs] = useState(!dappSuggestedGas); const [isVisibleTimeEstimateInfoModal, , showTimeEstimateInfoModal, hideTimeEstimateInfoModal] = useModalHandler(false); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const getAnalyticsParams = useCallback(() => { try { @@ -501,7 +505,9 @@ const EditGasFee1559 = ({ } + renderIcon={() => ( + + )} style={styles.warningContainer} > {() => ( @@ -515,7 +521,7 @@ const EditGasFee1559 = ({ ); return warning; - }, [warning]); + }, [warning, styles, colors]); const renderError = useMemo(() => { if (!error) return null; @@ -524,7 +530,9 @@ const EditGasFee1559 = ({ } + renderIcon={() => ( + + )} style={styles.warningContainer} > {() => ( @@ -538,7 +546,7 @@ const EditGasFee1559 = ({ ); return error; - }, [error]); + }, [error, styles, colors]); const renderDisplayTitle = useMemo(() => { if (updateOption) @@ -556,12 +564,12 @@ const EditGasFee1559 = ({ - + {renderDisplayTitle} - + {updateOption && ( diff --git a/app/components/UI/EditGasFeeLegacy/__snapshots__/index.test.tsx.snap b/app/components/UI/EditGasFeeLegacy/__snapshots__/index.test.tsx.snap index b2ceba577af..2df390e1dce 100644 --- a/app/components/UI/EditGasFeeLegacy/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/EditGasFeeLegacy/__snapshots__/index.test.tsx.snap @@ -38,7 +38,7 @@ exports[`EditGasFeeLegacy should render correctly 1`] = ` @@ -262,7 +262,7 @@ exports[`EditGasFeeLegacy should render correctly 1`] = ` size={14} style={ Object { - "color": "#bbc0c5", + "color": "#BBC0C5", } } /> @@ -332,7 +332,7 @@ exports[`EditGasFeeLegacy should render correctly 1`] = ` size={14} style={ Object { - "color": "#bbc0c5", + "color": "#BBC0C5", } } /> diff --git a/app/components/UI/EditGasFeeLegacy/index.js b/app/components/UI/EditGasFeeLegacy/index.js index f8eee9a194d..2b99e5a10bc 100644 --- a/app/components/UI/EditGasFeeLegacy/index.js +++ b/app/components/UI/EditGasFeeLegacy/index.js @@ -8,7 +8,6 @@ import Text from '../../Base/Text'; import StyledButton from '../StyledButton'; import RangeInput from '../../Base/RangeInput'; import MaterialCommunityIcon from 'react-native-vector-icons/MaterialCommunityIcons'; -import { colors } from '../../../styles/common'; import InfoModal from '../Swaps/components/InfoModal'; import Icon from 'react-native-vector-icons/Ionicons'; import { strings } from '../../../../locales/i18n'; @@ -19,86 +18,89 @@ import { isMainnetByChainId } from '../../../util/networks'; import FadeAnimationView from '../FadeAnimationView'; import AnalyticsV2 from '../../../util/analyticsV2'; import AppConstants from '../../../core/AppConstants'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; const GAS_LIMIT_INCREMENT = new BigNumber(1000); const GAS_PRICE_INCREMENT = new BigNumber(1); const GAS_LIMIT_MIN = new BigNumber(21000); const GAS_PRICE_MIN = new BigNumber(0); -const styles = StyleSheet.create({ - root: { - backgroundColor: colors.white, - borderTopLeftRadius: 20, - borderTopRightRadius: 20, - minHeight: 200, - maxHeight: '95%', - paddingTop: 24, - paddingBottom: Device.isIphoneX() ? 32 : 24, - }, - wrapper: { - paddingHorizontal: 24, - }, - customGasHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - width: '100%', - paddingBottom: 20, - }, - headerContainer: { - alignItems: 'center', - marginBottom: 22, - }, - headerText: { - fontSize: 48, - }, - headerTitle: { - flexDirection: 'row', - }, - headerTitleSide: { - flex: 1, - }, - labelTextContainer: { - flexDirection: 'row', - alignItems: 'center', - }, - hitSlop: { - top: 10, - left: 10, - bottom: 10, - right: 10, - }, - labelInfo: { - color: colors.grey200, - }, - advancedOptionsContainer: { - marginTop: 25, - marginBottom: 30, - }, - advancedOptionsInputsContainer: { - marginTop: 14, - }, - rangeInputContainer: { - marginBottom: 20, - }, - advancedOptionsButton: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - }, - advancedOptionsIcon: { - paddingTop: 1, - marginLeft: 5, - }, - warningTextContainer: { - paddingLeft: 4, - lineHeight: 20, - textAlign: 'center', - }, - warningText: { - lineHeight: 20, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + root: { + backgroundColor: colors.background.default, + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + minHeight: 200, + maxHeight: '95%', + paddingTop: 24, + paddingBottom: Device.isIphoneX() ? 32 : 24, + }, + wrapper: { + paddingHorizontal: 24, + }, + customGasHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + width: '100%', + paddingBottom: 20, + }, + headerContainer: { + alignItems: 'center', + marginBottom: 22, + }, + headerText: { + fontSize: 48, + }, + headerTitle: { + flexDirection: 'row', + }, + headerTitleSide: { + flex: 1, + }, + labelTextContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + hitSlop: { + top: 10, + left: 10, + bottom: 10, + right: 10, + }, + labelInfo: { + color: colors.text.muted, + }, + advancedOptionsContainer: { + marginTop: 25, + marginBottom: 30, + }, + advancedOptionsInputsContainer: { + marginTop: 14, + }, + rangeInputContainer: { + marginBottom: 20, + }, + advancedOptionsButton: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + advancedOptionsIcon: { + paddingTop: 1, + marginLeft: 5, + }, + warningTextContainer: { + paddingLeft: 4, + lineHeight: 20, + textAlign: 'center', + }, + warningText: { + lineHeight: 20, + color: colors.text.default, + }, + }); const EditGasFeeLegacy = ({ selected, @@ -130,6 +132,8 @@ const EditGasFeeLegacy = ({ const [showAdvancedOptions, setShowAdvancedOptions] = useState(!selected || onlyAdvanced); const [selectedOption, setSelectedOption] = useState(selected); const [gasPriceError, setGasPriceError] = useState(); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const getAnalyticsParams = useCallback(() => { try { @@ -243,7 +247,9 @@ const EditGasFeeLegacy = ({ } + renderIcon={() => ( + + )} style={styles.warningContainer} > {() => ( @@ -257,7 +263,7 @@ const EditGasFeeLegacy = ({ ); return warning; - }, [warning]); + }, [warning, styles, colors]); const renderError = useMemo(() => { if (!error) return null; @@ -266,7 +272,9 @@ const EditGasFeeLegacy = ({ } + renderIcon={() => ( + + )} style={styles.warningContainer} > {() => ( @@ -280,7 +288,7 @@ const EditGasFeeLegacy = ({ ); return error; - }, [error]); + }, [error, styles, colors]); const isMainnet = isMainnetByChainId(chainId); const nativeCurrencySelected = primaryCurrency === 'ETH' || !isMainnet; @@ -303,12 +311,12 @@ const EditGasFeeLegacy = ({ - + {strings('transaction.edit_network_fee')} - + {renderWarning} diff --git a/app/components/UI/FadeOutOverlay/index.js b/app/components/UI/FadeOutOverlay/index.js index cf8d67ef044..a34f40dba05 100644 --- a/app/components/UI/FadeOutOverlay/index.js +++ b/app/components/UI/FadeOutOverlay/index.js @@ -1,19 +1,20 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { Animated, StyleSheet } from 'react-native'; -import { colors } from '../../../styles/common'; import Device from '../../../util/device'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - view: { - backgroundColor: colors.white, - position: 'absolute', - top: 0, - bottom: 0, - left: 0, - right: 0, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + view: { + backgroundColor: colors.background.default, + position: 'absolute', + top: 0, + bottom: 0, + left: 0, + right: 0, + }, + }); /** * View that is displayed to first time (new) users @@ -42,11 +43,16 @@ export default class FadeOutOverlay extends PureComponent { } render() { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + if (this.state.done) return null; return ; } } +FadeOutOverlay.contextType = ThemeContext; + FadeOutOverlay.defaultProps = { style: null, duration: Device.isAndroid() ? 300 : 300, diff --git a/app/components/UI/FiatOrders/PaymentMethodApplePay/index.js b/app/components/UI/FiatOrders/PaymentMethodApplePay/index.js index 50cb883496a..586f71f3427 100644 --- a/app/components/UI/FiatOrders/PaymentMethodApplePay/index.js +++ b/app/components/UI/FiatOrders/PaymentMethodApplePay/index.js @@ -29,107 +29,127 @@ import CountrySelector from '../components/CountrySelector'; import Keypad, { KEYS } from '../../../Base/Keypad'; import Text from '../../../Base/Text'; import StyledButton from '../../StyledButton'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles, colors as importedColors } from '../../../../styles/common'; import { protectWalletModalVisible } from '../../../../actions/user'; import { addFiatOrder, fiatOrdersCountrySelector, setFiatOrdersCountry } from '../../../../reducers/fiatOrders'; +import { useAppThemeFromContext, mockTheme, useAssetFromTheme } from '../../../../util/theme'; //* styles and components */ -const styles = StyleSheet.create({ - screen: { - flexGrow: 1, - justifyContent: 'space-between', - }, - selectors: { - flexDirection: 'row', - marginTop: Device.isIphone5() ? 12 : 18, - marginHorizontal: 25, - justifyContent: 'space-between', - alignItems: 'center', - }, - spacer: { - minWidth: 8, - }, - amountContainer: { - margin: Device.isIphone5() ? 0 : 12, - padding: Device.isMediumDevice() ? (Device.isIphone5() ? 5 : 10) : 15, - alignItems: 'center', - justifyContent: 'center', - }, - amount: { - ...fontStyles.light, - color: colors.black, - fontSize: Device.isIphone5() ? 48 : 48, - height: Device.isIphone5() ? 50 : 60, - }, - amountDescription: { - minHeight: 22, - }, - amountError: { - color: colors.red, - }, - content: { - flexGrow: 1, - justifyContent: 'space-around', - }, - quickAmounts: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-around', - marginHorizontal: 70, - }, - quickAmount: { - borderRadius: 18, - borderColor: colors.grey200, - borderWidth: 1, - paddingVertical: 5, - paddingHorizontal: 8, - alignItems: 'center', - minWidth: 49, - }, - quickAmountPlaceholder: { - backgroundColor: colors.grey000, - borderColor: colors.grey000, - }, - quickAmountSelected: { - backgroundColor: colors.blue, - borderColor: colors.blue, - }, - quickAmountSelectedText: { - color: colors.white, - }, - buttonContainer: { - paddingBottom: 20, - }, - applePayButton: { - backgroundColor: colors.black, - padding: 10, - margin: Device.isIphone5() ? 5 : 10, - marginHorizontal: 25, - alignItems: 'center', - }, - applePayButtonText: { - color: colors.white, - }, - applePayButtonContentDisabled: { - opacity: 0.6, - }, - applePayLogo: { - marginLeft: 4, - }, +const createStyles = (colors) => + StyleSheet.create({ + screen: { + flexGrow: 1, + justifyContent: 'space-between', + backgroundColor: colors.background.default, + }, + selectors: { + flexDirection: 'row', + marginTop: Device.isIphone5() ? 12 : 18, + marginHorizontal: 25, + justifyContent: 'space-between', + alignItems: 'center', + }, + spacer: { + minWidth: 8, + }, + amountContainer: { + margin: Device.isIphone5() ? 0 : 12, + padding: Device.isMediumDevice() ? (Device.isIphone5() ? 5 : 10) : 15, + alignItems: 'center', + justifyContent: 'center', + }, + amount: { + ...fontStyles.light, + color: colors.text.default, + fontSize: Device.isIphone5() ? 48 : 48, + height: Device.isIphone5() ? 50 : 60, + }, + amountDescription: { + minHeight: 22, + }, + amountError: { + color: colors.error.default, + }, + content: { + flexGrow: 1, + justifyContent: 'space-around', + }, + quickAmounts: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-around', + marginHorizontal: 70, + }, + quickAmount: { + borderRadius: 18, + borderColor: colors.border.default, + borderWidth: 1, + paddingVertical: 5, + paddingHorizontal: 8, + alignItems: 'center', + minWidth: 49, + }, + quickAmountPlaceholder: { + backgroundColor: colors.background.alternative, + borderColor: colors.background.alternative, + }, + quickAmountSelected: { + backgroundColor: colors.primary.default, + borderColor: colors.primary.default, + }, + quickAmountSelectedText: { + color: colors.primary.inverse, + }, + buttonContainer: { + paddingBottom: 20, + }, + applePayButton: { + padding: 10, + margin: Device.isIphone5() ? 5 : 10, + marginHorizontal: 25, + alignItems: 'center', + }, + applePayButtonContentDisabled: { + opacity: 0.6, + }, + applePayLogo: { + marginLeft: 4, + }, + }); + +const applePayButtonStylesLight = StyleSheet.create({ + applePayButtonText: { color: importedColors.white }, + applePayButton: { backgroundColor: importedColors.black }, +}); + +const applePayButtonStylesDark = StyleSheet.create({ + applePayButtonText: { color: importedColors.black }, + applePayButton: { backgroundColor: importedColors.white }, }); /* eslint-disable import/no-commonjs */ -const ApplePayLogo = require('../../../../images/ApplePayLogo.png'); -const ApplePay = ({ disabled }) => ( - -); +const ApplePayLogoLight = require('../../../../images/ApplePayLogo-light.png'); +const ApplePayLogoDark = require('../../../../images/ApplePayLogo-dark.png'); + +const ApplePay = ({ disabled }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + const applePayLogo = useAssetFromTheme(ApplePayLogoLight, ApplePayLogoDark); + + return ( + + ); +}; ApplePay.propTypes = { disabled: PropTypes.bool, }; const QuickAmount = ({ amount, current, currencySymbol, placeholder, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + if (placeholder) { return ( @@ -180,6 +200,10 @@ function PaymentMethodApplePay({ }) { const navigation = useNavigation(); const [amount, setAmount] = useState('0'); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + const appleButtonColors = useAssetFromTheme(applePayButtonStylesLight, applePayButtonStylesDark); + const { symbol: currencySymbol, decimalSeparator, @@ -329,6 +353,29 @@ function PaymentMethodApplePay({ [selectedCurrency] ); + useEffect(() => { + navigation.setOptions( + getPaymentMethodApplePayNavbar( + navigation, + () => { + InteractionManager.runAfterInteractions(() => { + AnalyticsV2.trackEvent(AnalyticsV2.ANALYTICS_EVENTS.ONRAMP_PURCHASE_EXITED, { + payment_rails: PAYMENT_RAILS.APPLE_PAY, + payment_category: PAYMENT_CATEGORY.CARD_PAYMENT, + 'on-ramp_provider': FIAT_ORDER_PROVIDERS.WYRE_APPLE_PAY, + }); + }); + }, + () => { + InteractionManager.runAfterInteractions(() => { + AnalyticsV2.trackEvent(AnalyticsV2.ANALYTICS_EVENTS.ONRAMP_CLOSED); + }); + }, + colors + ) + ); + }, [navigation, colors]); + useEffect(() => { setAmount('0'); }, [selectedCurrency]); @@ -416,13 +463,16 @@ function PaymentMethodApplePay({ {strings('fiat_on_ramp.buy_with')} @@ -498,25 +548,6 @@ PaymentMethodApplePay.propTypes = { protectWalletModalVisible: PropTypes.func, }; -PaymentMethodApplePay.navigationOptions = ({ navigation }) => - getPaymentMethodApplePayNavbar( - navigation, - () => { - InteractionManager.runAfterInteractions(() => { - AnalyticsV2.trackEvent(AnalyticsV2.ANALYTICS_EVENTS.ONRAMP_PURCHASE_EXITED, { - payment_rails: PAYMENT_RAILS.APPLE_PAY, - payment_category: PAYMENT_CATEGORY.CARD_PAYMENT, - 'on-ramp_provider': FIAT_ORDER_PROVIDERS.WYRE_APPLE_PAY, - }); - }); - }, - () => { - InteractionManager.runAfterInteractions(() => { - AnalyticsV2.trackEvent(AnalyticsV2.ANALYTICS_EVENTS.ONRAMP_CLOSED); - }); - } - ); - const mapStateToProps = (state) => ({ lockTime: state.settings.lockTime, selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress, diff --git a/app/components/UI/FiatOrders/PaymentMethodSelector/index.android.js b/app/components/UI/FiatOrders/PaymentMethodSelector/index.android.js index 812b1a11161..d82a9be4a67 100644 --- a/app/components/UI/FiatOrders/PaymentMethodSelector/index.android.js +++ b/app/components/UI/FiatOrders/PaymentMethodSelector/index.android.js @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useEffect } from 'react'; import { InteractionManager } from 'react-native'; import PropTypes from 'prop-types'; import { useNavigation } from '@react-navigation/native'; @@ -18,6 +18,7 @@ import Title from '../components/Title'; import TransakPaymentMethod from './transak'; import { setGasEducationCarouselSeen } from '../../../../actions/user'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; function PaymentMethodSelectorView({ selectedAddress, @@ -29,6 +30,21 @@ function PaymentMethodSelectorView({ }) { const navigation = useNavigation(); const transakURL = useTransakFlowURL(selectedAddress, chainId); + const { colors } = useAppThemeFromContext() || mockTheme; + + useEffect(() => { + navigation.setOptions( + getPaymentSelectorMethodNavbar( + navigation, + () => { + InteractionManager.runAfterInteractions(() => { + AnalyticsV2.trackEvent(AnalyticsV2.ANALYTICS_EVENTS.ONRAMP_CLOSED); + }); + }, + colors + ) + ); + }, [navigation, colors]); const onPressTransak = useCallback(() => { const goToTransakFlow = () => @@ -74,13 +90,6 @@ PaymentMethodSelectorView.propTypes = { setGasEducationCarouselSeen: PropTypes.func, }; -PaymentMethodSelectorView.navigationOptions = ({ navigation }) => - getPaymentSelectorMethodNavbar(navigation, () => { - InteractionManager.runAfterInteractions(() => { - AnalyticsV2.trackEvent(AnalyticsV2.ANALYTICS_EVENTS.ONRAMP_CLOSED); - }); - }); - const mapStateToProps = (state) => ({ selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress, chainId: state.engine.backgroundState.NetworkController.provider.chainId, diff --git a/app/components/UI/FiatOrders/PaymentMethodSelector/index.ios.js b/app/components/UI/FiatOrders/PaymentMethodSelector/index.ios.js index 6a1346de569..92cd4fd15a5 100644 --- a/app/components/UI/FiatOrders/PaymentMethodSelector/index.ios.js +++ b/app/components/UI/FiatOrders/PaymentMethodSelector/index.ios.js @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useEffect } from 'react'; import { InteractionManager } from 'react-native'; import PropTypes from 'prop-types'; import { useNavigation } from '@react-navigation/native'; @@ -24,6 +24,7 @@ import SubHeader from '../components/SubHeader'; import TransakPaymentMethod from './transak'; import WyreApplePayPaymentMethod from './wyreApplePay'; import { setGasEducationCarouselSeen } from '../../../../actions/user'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; function PaymentMethodSelectorView({ selectedAddress, @@ -35,6 +36,21 @@ function PaymentMethodSelectorView({ }) { const navigation = useNavigation(); const transakURL = useTransakFlowURL(selectedAddress, chainId); + const { colors } = useAppThemeFromContext() || mockTheme; + + useEffect(() => { + navigation.setOptions( + getPaymentSelectorMethodNavbar( + navigation, + () => { + InteractionManager.runAfterInteractions(() => { + AnalyticsV2.trackEvent(AnalyticsV2.ANALYTICS_EVENTS.ONRAMP_CLOSED); + }); + }, + colors + ) + ); + }, [navigation, colors]); const onPressWyreApplePay = useCallback(() => { const goToApplePay = () => navigation.navigate('PaymentMethodApplePay'); @@ -121,13 +137,6 @@ PaymentMethodSelectorView.propTypes = { setGasEducationCarouselSeen: PropTypes.func, }; -PaymentMethodSelectorView.navigationOptions = ({ navigation }) => - getPaymentSelectorMethodNavbar(navigation, () => { - InteractionManager.runAfterInteractions(() => { - AnalyticsV2.trackEvent(AnalyticsV2.ANALYTICS_EVENTS.ONRAMP_CLOSED); - }); - }); - const mapStateToProps = (state) => ({ selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress, chainId: state.engine.backgroundState.NetworkController.provider.chainId, diff --git a/app/components/UI/FiatOrders/PaymentMethodSelector/wyreApplePay.js b/app/components/UI/FiatOrders/PaymentMethodSelector/wyreApplePay.js index f09686cafa7..6f691b682e9 100644 --- a/app/components/UI/FiatOrders/PaymentMethodSelector/wyreApplePay.js +++ b/app/components/UI/FiatOrders/PaymentMethodSelector/wyreApplePay.js @@ -11,6 +11,7 @@ import Text from '../../../Base/Text'; import Title from '../components/Title'; import useModalHandler from '../../../Base/hooks/useModalHandler'; import { ScrollView } from 'react-native-gesture-handler'; +import { useAssetFromTheme } from '../../../../util/theme'; const styles = StyleSheet.create({ title: { @@ -34,12 +35,20 @@ const styles = StyleSheet.create({ }); /* eslint-disable import/no-commonjs */ -const ApplePayMarkIcon = require('../../../../images/ApplePayMark.png'); -const WyreLogoIcon = require('../../../../images/WyreLogo.png'); +const ApplePayMarkLightIcon = require('../../../../images/ApplePayMark-light.png'); +const ApplePayMarkDarkIcon = require('../../../../images/ApplePayMark-dark.png'); +const WyreLogoLightIcon = require('../../../../images/WyreLogo-light.png'); +const WyreLogoDarkIcon = require('../../../../images/WyreLogo-dark.png'); /* eslint-enable import/no-commonjs */ -const ApplePayMark = () => ; -const WyreLogo = () => ; +const ApplePayMark = () => { + const applePayMarkIcon = useAssetFromTheme(ApplePayMarkLightIcon, ApplePayMarkDarkIcon); + return ; +}; +const WyreLogo = () => { + const wyreLogoIcon = useAssetFromTheme(WyreLogoLightIcon, WyreLogoDarkIcon); + return ; +}; const WyreApplePayPaymentMethod = ({ onPress }) => { const navigation = useNavigation(); @@ -62,8 +71,9 @@ const WyreApplePayPaymentMethod = ({ onPress }) => { - {strings('fiat_on_ramp.wyre_countries')} + {strings('fiat_on_ramp.wyre_countries')} + diff --git a/app/components/UI/FiatOrders/TransakWebView/index.js b/app/components/UI/FiatOrders/TransakWebView/index.js index c9f0cabce97..799111645ce 100644 --- a/app/components/UI/FiatOrders/TransakWebView/index.js +++ b/app/components/UI/FiatOrders/TransakWebView/index.js @@ -22,19 +22,9 @@ import { } from '../../../../constants/on-ramp'; import Engine from '../../../../core/Engine'; import { toLowerCaseEquals } from '../../../../util/general'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; class TransakWebView extends PureComponent { - static navigationOptions = ({ navigation, route }) => - getTransakWebviewNavbar(navigation, route, () => { - InteractionManager.runAfterInteractions(() => { - AnalyticsV2.trackEvent(AnalyticsV2.ANALYTICS_EVENTS.ONRAMP_PURCHASE_EXITED, { - payment_rails: PAYMENT_RAILS.MULTIPLE, - payment_category: PAYMENT_CATEGORY.MULTIPLE, - 'on-ramp_provider': FIAT_ORDER_PROVIDERS.TRANSAK, - }); - }); - }); - static propTypes = { navigation: PropTypes.object, /** @@ -55,6 +45,35 @@ class TransakWebView extends PureComponent { route: PropTypes.object, }; + updateNavBar = () => { + const { navigation, route } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + getTransakWebviewNavbar( + navigation, + route, + () => { + InteractionManager.runAfterInteractions(() => { + AnalyticsV2.trackEvent(AnalyticsV2.ANALYTICS_EVENTS.ONRAMP_PURCHASE_EXITED, { + payment_rails: PAYMENT_RAILS.MULTIPLE, + payment_category: PAYMENT_CATEGORY.MULTIPLE, + 'on-ramp_provider': FIAT_ORDER_PROVIDERS.TRANSAK, + }); + }); + }, + colors + ) + ); + }; + + componentDidMount = () => { + this.updateNavBar(); + }; + + componentDidUpdate = () => { + this.updateNavBar(); + }; + addTokenToTokensController = async (symbol, chainId) => { const { TokensController } = Engine.context; if (NETWORK_NATIVE_SYMBOL[chainId] !== symbol) { @@ -112,6 +131,8 @@ class TransakWebView extends PureComponent { } } +TransakWebView.contextType = ThemeContext; + const mapStateToProps = (state) => ({ network: state.engine.backgroundState.NetworkController.network, }); diff --git a/app/components/UI/FiatOrders/components/CountrySelectorModal.js b/app/components/UI/FiatOrders/components/CountrySelectorModal.js index 4ea4c2d8833..4a23ad5f2d3 100644 --- a/app/components/UI/FiatOrders/components/CountrySelectorModal.js +++ b/app/components/UI/FiatOrders/components/CountrySelectorModal.js @@ -19,63 +19,69 @@ import { strings } from '../../../../../locales/i18n'; import Text from '../../../Base/Text'; import ListItem from '../../../Base/ListItem'; import ModalDragger from '../../../Base/ModalDragger'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles } from '../../../../styles/common'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - modal: { - margin: 0, - justifyContent: 'flex-end', - }, - modalView: { - backgroundColor: colors.white, - borderTopLeftRadius: 10, - borderTopRightRadius: 10, - }, - inputWrapper: { - flexDirection: 'row', - alignItems: 'center', - marginHorizontal: 30, - marginVertical: 10, - paddingVertical: Device.isAndroid() ? 0 : 10, - paddingHorizontal: 5, - borderRadius: 5, - borderWidth: 1, - borderColor: colors.grey100, - }, - searchIcon: { - marginHorizontal: 8, - }, - input: { - ...fontStyles.normal, - flex: 1, - }, - modalTitle: { - marginTop: Device.isIphone5() ? 10 : 15, - marginBottom: Device.isIphone5() ? 5 : 5, - marginHorizontal: 36, - }, - resultsView: { - height: Device.isSmallDevice() ? 130 : 250, - marginTop: 10, - }, - resultRow: { - borderTopWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - paddingHorizontal: 20, - }, - flag: { - fontSize: 24, - }, - emptyList: { - marginVertical: 10, - marginHorizontal: 30, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + modal: { + margin: 0, + justifyContent: 'flex-end', + }, + modalView: { + backgroundColor: colors.background.default, + borderTopLeftRadius: 10, + borderTopRightRadius: 10, + }, + inputWrapper: { + flexDirection: 'row', + alignItems: 'center', + marginHorizontal: 30, + marginVertical: 10, + paddingVertical: Device.isAndroid() ? 0 : 10, + paddingHorizontal: 5, + borderRadius: 5, + borderWidth: 1, + borderColor: colors.border.default, + }, + searchIcon: { + marginHorizontal: 8, + color: colors.icon.muted, + }, + input: { + ...fontStyles.normal, + flex: 1, + color: colors.text.default, + }, + modalTitle: { + marginTop: Device.isIphone5() ? 10 : 15, + marginBottom: Device.isIphone5() ? 5 : 5, + marginHorizontal: 36, + }, + resultsView: { + height: Device.isSmallDevice() ? 130 : 250, + marginTop: 10, + }, + resultRow: { + borderTopWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + paddingHorizontal: 20, + }, + flag: { + fontSize: 24, + }, + emptyList: { + marginVertical: 10, + marginHorizontal: 30, + }, + }); function CountrySelectorModal({ isVisible, dismiss, countries, onItemPress }) { const searchInput = useRef(null); const list = useRef(); const [searchString, setSearchString] = useState(''); + const { colors, themeAppearance } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const countriesFuse = useMemo( () => @@ -118,7 +124,7 @@ function CountrySelectorModal({ isVisible, dismiss, countries, onItemPress }) { ), - [onItemPress] + [onItemPress, styles] ); const renderEmptyList = useMemo( @@ -127,7 +133,7 @@ function CountrySelectorModal({ isVisible, dismiss, countries, onItemPress }) { {strings('fiat_on_ramp.no_countries_result', { searchString })} ), - [searchString] + [searchString, styles] ); return ( @@ -141,6 +147,8 @@ function CountrySelectorModal({ isVisible, dismiss, countries, onItemPress }) { avoidKeyboard onModalHide={() => setSearchString('')} style={styles.modal} + backdropColor={colors.overlay.default} + backdropOpacity={1} > @@ -159,9 +167,10 @@ function CountrySelectorModal({ isVisible, dismiss, countries, onItemPress }) { ref={searchInput} style={styles.input} placeholder={strings('fiat_on_ramp.search_country')} - placeholderTextColor={colors.grey500} + placeholderTextColor={colors.text.muted} value={searchString} onChangeText={handleSearchTextChange} + keyboardAppearance={themeAppearance} /> diff --git a/app/components/UI/FiatOrders/components/InfoIcon.js b/app/components/UI/FiatOrders/components/InfoIcon.js index e5ad4424fb2..daae6dc8737 100644 --- a/app/components/UI/FiatOrders/components/InfoIcon.js +++ b/app/components/UI/FiatOrders/components/InfoIcon.js @@ -1,19 +1,10 @@ import React from 'react'; -import { StyleSheet } from 'react-native'; import IonicIcon from 'react-native-vector-icons/Ionicons'; import Device from '../../../../util/device'; -import { colors } from '../../../../styles/common'; - -const styles = StyleSheet.create({ - icon: { - color: colors.grey200, - }, -}); const InfoIcon = (props) => ( diff --git a/app/components/UI/FiatOrders/components/PaymentMethod/Modal.js b/app/components/UI/FiatOrders/components/PaymentMethod/Modal.js index a5658f2a359..d4f64536d12 100644 --- a/app/components/UI/FiatOrders/components/PaymentMethod/Modal.js +++ b/app/components/UI/FiatOrders/components/PaymentMethod/Modal.js @@ -4,94 +4,107 @@ import { StyleSheet, View, TouchableOpacity, ScrollView, SafeAreaView } from 're import Modal from 'react-native-modal'; import IonicIcon from 'react-native-vector-icons/Ionicons'; import { strings } from '../../../../../../locales/i18n'; - import Title from '../Title'; -import { colors } from '../../../../../styles/common'; +import { colors as importedColors } from '../../../../../styles/common'; import StyledButton from '../../../StyledButton'; import Device from '../../../../../util/device'; +import { useAppThemeFromContext, mockTheme } from '../../../../../util/theme'; -const styles = StyleSheet.create({ - modalView: { - backgroundColor: colors.white, - justifyContent: 'center', - alignItems: 'center', - marginVertical: 50, - borderRadius: 10, - shadowColor: colors.black, - shadowOffset: { - width: 0, - height: 5, +const createStyles = (colors) => + StyleSheet.create({ + modalView: { + backgroundColor: colors.background.default, + justifyContent: 'center', + alignItems: 'center', + marginVertical: 50, + borderRadius: 10, + shadowColor: importedColors.black, + shadowOffset: { + width: 0, + height: 5, + }, + shadowOpacity: 0.36, + shadowRadius: 6.68, + elevation: 11, + }, + modal: { + margin: 0, + width: '100%', + padding: Device.isIphone5() ? 15 : 25, + }, + title: { + width: '100%', + paddingVertical: 15, + paddingHorizontal: 20, + paddingBottom: 5, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + }, + closeIcon: { + color: colors.text.default, + }, + body: { + width: '100%', + paddingVertical: 5, + paddingHorizontal: 20, + }, + action: { + width: '100%', + alignItems: 'center', + marginTop: 15, + paddingVertical: 15, + paddingHorizontal: 20, + borderTopWidth: 1, + borderTopColor: colors.border.muted, }, - shadowOpacity: 0.36, - shadowRadius: 6.68, - elevation: 11, - }, - modal: { - margin: 0, - width: '100%', - padding: Device.isIphone5() ? 15 : 25, - }, - title: { - width: '100%', - paddingVertical: 15, - paddingHorizontal: 20, - paddingBottom: 5, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - }, - closeIcon: { - color: colors.black, - }, - body: { - width: '100%', - paddingVertical: 5, - paddingHorizontal: 20, - }, - action: { - width: '100%', - alignItems: 'center', - marginTop: 15, - paddingVertical: 15, - paddingHorizontal: 20, - borderTopWidth: 1, - borderTopColor: colors.grey100, - }, - button: { - width: '50%', - }, -}); + button: { + width: '50%', + }, + }); + +const CloseIcon = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); -const CloseIcon = (props) => ; + return ; +}; -const PaymentMethodModal = ({ isVisible, title, dismiss, children }) => ( - - - - {title} - - - - - - true}>{children} - - - - {strings('fiat_on_ramp.purchase_method_modal_close')} - - - - -); +const PaymentMethodModal = ({ isVisible, title, dismiss, children }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + + + {title} + + + + + + true}>{children} + + + + {strings('fiat_on_ramp.purchase_method_modal_close')} + + + + + ); +}; PaymentMethodModal.propTypes = { isVisible: PropTypes.bool, diff --git a/app/components/UI/FiatOrders/components/PaymentMethod/index.js b/app/components/UI/FiatOrders/components/PaymentMethod/index.js index 001bca9dea0..56b9ff9f46d 100644 --- a/app/components/UI/FiatOrders/components/PaymentMethod/index.js +++ b/app/components/UI/FiatOrders/components/PaymentMethod/index.js @@ -1,61 +1,66 @@ import React from 'react'; import PropTypes from 'prop-types'; import { TouchableOpacity, View, StyleSheet } from 'react-native'; -import { colors, fontStyles } from '../../../../../styles/common'; +import { fontStyles } from '../../../../../styles/common'; import Text from '../../../../Base/Text'; import InfoIcon from '../InfoIcon'; import Modal from './Modal'; import Device from '../../../../../util/device'; +import { useAppThemeFromContext, mockTheme } from '../../../../../util/theme'; -const style = StyleSheet.create({ - container: { - borderWidth: 1, - borderRadius: 8, - borderColor: colors.blue, - paddingVertical: 15, - paddingHorizontal: 20, - marginHorizontal: Device.isIphone5() ? 15 : 25, - marginVertical: 12, - }, - title: { - flexDirection: 'row', - width: '100%', - justifyContent: 'space-between', - }, - badgeWrapper: { - position: 'absolute', - alignItems: 'center', - top: -14, - left: 0, - right: 0, - }, - badge: { - fontSize: 12, - paddingVertical: 4, - paddingHorizontal: 8, - backgroundColor: colors.blue, - color: colors.white, - margin: 0, - borderRadius: 12, - overflow: 'hidden', - ...fontStyles.bold, - }, - details: {}, - infoIconLine: { - alignItems: 'center', - flexDirection: 'row', - flexWrap: 'wrap', - }, - infoIcon: { - margin: 5, - color: colors.grey200, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + container: { + borderWidth: 1, + borderRadius: 8, + borderColor: colors.primary.default, + paddingVertical: 15, + paddingHorizontal: 20, + marginHorizontal: Device.isIphone5() ? 15 : 25, + marginVertical: 12, + }, + title: { + flexDirection: 'row', + width: '100%', + justifyContent: 'space-between', + }, + badgeWrapper: { + position: 'absolute', + alignItems: 'center', + top: -14, + left: 0, + right: 0, + }, + badge: { + fontSize: 12, + paddingVertical: 4, + paddingHorizontal: 8, + backgroundColor: colors.primary.default, + color: colors.primary.inverse, + margin: 0, + borderRadius: 12, + overflow: 'hidden', + ...fontStyles.bold, + }, + details: {}, + infoIconLine: { + alignItems: 'center', + flexDirection: 'row', + flexWrap: 'wrap', + }, + infoIcon: { + margin: 5, + color: colors.icon.muted, + }, + }); -const PaymentMethod = ({ onPress, ...props }) => ( - -); +const PaymentMethod = ({ onPress, ...props }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const style = createStyles(colors); + + return ; +}; PaymentMethod.propTypes = { onPress: PropTypes.func, @@ -67,17 +72,42 @@ PaymentMethod.defaultProps = { children: undefined, }; -const Badge = (props) => ( - - - -); +const Badge = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const style = createStyles(colors); -const Title = (props) => ; -const Content = (props) => ; -const Details = (props) => ; -const InfoIconLine = (props) => ; -const PaymentMethodInfoIcon = (props) => ; + return ( + + + + ); +}; + +const Title = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const style = createStyles(colors); + return ; +}; +const Content = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const style = createStyles(colors); + return ; +}; +const Details = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const style = createStyles(colors); + return ; +}; +const InfoIconLine = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const style = createStyles(colors); + return ; +}; +const PaymentMethodInfoIcon = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const style = createStyles(colors); + return ; +}; PaymentMethod.Badge = Badge; PaymentMethod.Title = Title; diff --git a/app/components/UI/FiatOrders/components/ScreenView.js b/app/components/UI/FiatOrders/components/ScreenView.js index fecb1938cd1..c4305dff539 100644 --- a/app/components/UI/FiatOrders/components/ScreenView.js +++ b/app/components/UI/FiatOrders/components/ScreenView.js @@ -1,18 +1,24 @@ import React from 'react'; import { SafeAreaView, StyleSheet, ScrollView } from 'react-native'; -import { colors } from '../../../../styles/common'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + }); -const ScreenView = (props) => ( - - - -); +const ScreenView = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + + + ); +}; export default ScreenView; diff --git a/app/components/UI/Fox/index.js b/app/components/UI/Fox/index.js index 3af67e92c4e..c9215b98f89 100644 --- a/app/components/UI/Fox/index.js +++ b/app/components/UI/Fox/index.js @@ -2,20 +2,41 @@ import React, { forwardRef } from 'react'; import PropTypes from 'prop-types'; import { StyleSheet } from 'react-native'; import { WebView } from 'react-native-webview'; +import { mockTheme, useAppThemeFromContext } from '../../../util/theme'; +import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'; -const styles = StyleSheet.create({ - webView: { - flex: 1, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + webView: { + flex: 1, + backgroundColor: colors.background.default, + }, + }); function Fox({ style, customStyle, customContent = '', forwardedRef, ...props }) { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + const opacityControl = useSharedValue(0); + + /* eslint-disable-next-line */ + const webViewStyle = useAnimatedStyle(() => { + return { + opacity: opacityControl.value, + }; + }); + + const showWebView = () => { + opacityControl.value = withTiming(1, { duration: 500 }); + }; + return ( - + @@ -1502,12 +1523,13 @@ function Fox({ style, customStyle, customContent = '', forwardedRef, ...props }) `, - }} - javaScriptEnabled - bounces={false} - scrollEnabled={false} - {...props} - /> + }} + javaScriptEnabled + bounces={false} + scrollEnabled={false} + {...props} + /> + ); } diff --git a/app/components/UI/FoxScreen/index.js b/app/components/UI/FoxScreen/index.js index 4c9c904c85e..1b60fffd537 100644 --- a/app/components/UI/FoxScreen/index.js +++ b/app/components/UI/FoxScreen/index.js @@ -1,24 +1,25 @@ import React, { PureComponent } from 'react'; import { View, Image, StyleSheet } from 'react-native'; -import { colors } from '../../../styles/common'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - flex: 1, - backgroundColor: colors.white, - alignItems: 'center', - justifyContent: 'center', - position: 'absolute', - top: 0, - bottom: 0, - left: 0, - right: 0, - }, - image: { - width: 100, - height: 100, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + flex: 1, + backgroundColor: colors.background.default, + alignItems: 'center', + justifyContent: 'center', + position: 'absolute', + top: 0, + bottom: 0, + left: 0, + right: 0, + }, + image: { + width: 100, + height: 100, + }, + }); const foxImage = require('../../../images/fox.png'); // eslint-disable-line import/no-commonjs @@ -27,9 +28,16 @@ const foxImage = require('../../../images/fox.png'); // eslint-disable-line impo * in the middle of the screen */ export default class FoxScreen extends PureComponent { - render = () => ( - - - - ); + render = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + + + ); + }; } + +FoxScreen.contextType = ThemeContext; diff --git a/app/components/UI/GlobalAlert/index.js b/app/components/UI/GlobalAlert/index.js index 25fd1208dd6..015e1c00bc5 100644 --- a/app/components/UI/GlobalAlert/index.js +++ b/app/components/UI/GlobalAlert/index.js @@ -4,35 +4,37 @@ import Modal from 'react-native-modal'; import { StyleSheet, View, Text } from 'react-native'; import { dismissAlert } from '../../../actions/alert'; import { connect } from 'react-redux'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import Icon from 'react-native-vector-icons/FontAwesome'; import ElevatedView from 'react-native-elevated-view'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - modal: { - margin: 0, - width: '100%', - }, - copyAlert: (width) => ({ - width: width || 180, - backgroundColor: colors.darkAlert, - padding: 20, - paddingTop: 30, - alignSelf: 'center', - alignItems: 'center', - justifyContent: 'center', - borderRadius: 8, - }), - copyAlertIcon: { - marginBottom: 20, - }, - copyAlertText: { - textAlign: 'center', - color: colors.white, - fontSize: 16, - ...fontStyles.normal, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + modal: { + margin: 0, + width: '100%', + }, + copyAlert: (width) => ({ + width: width || 180, + backgroundColor: colors.overlay.alternative, + padding: 20, + paddingTop: 30, + alignSelf: 'center', + alignItems: 'center', + justifyContent: 'center', + borderRadius: 8, + }), + copyAlertIcon: { + marginBottom: 20, + }, + copyAlertText: { + textAlign: 'center', + color: colors.overlay.inverse, + fontSize: 16, + ...fontStyles.normal, + }, + }); /** * Wrapper component for a global alert @@ -83,17 +85,29 @@ class GlobalAlert extends PureComponent { } } - renderClipboardAlert = () => ( - - - - - {this.props.data && this.props.data.msg} - - ); + getStyles = () => { + const colors = this.context.colors || mockTheme.colors; + return createStyles(colors); + }; + + renderClipboardAlert = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = this.getStyles(colors); + + return ( + + + + + {this.props.data && this.props.data.msg} + + ); + }; render = () => { const { content, isVisible } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = this.getStyles(colors); return ( ({ dismissAlert: () => dispatch(dismissAlert()), }); +GlobalAlert.contextType = ThemeContext; + export default connect(mapStateToProps, mapDispatchToProps)(GlobalAlert); diff --git a/app/components/UI/HintModal/__snapshots__/index.test.tsx.snap b/app/components/UI/HintModal/__snapshots__/index.test.tsx.snap index cca1b6895b9..9c6281c09c3 100644 --- a/app/components/UI/HintModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/HintModal/__snapshots__/index.test.tsx.snap @@ -44,7 +44,7 @@ exports[`HintModal should render correctly 1`] = ` + StyleSheet.create({ + hintWrapper: { + alignSelf: 'center', + backgroundColor: colors.background.default, + borderRadius: 16, + padding: 24, + }, + hintHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 16, + }, + recovery: { + fontSize: 18, + ...fontStyles.bold, + color: colors.text.default, + }, + leaveHint: { + fontSize: 14, + ...fontStyles.regular, + color: colors.text.default, + marginBottom: 16, + }, + noSeedphrase: { + fontSize: 14, + ...fontStyles.regular, + color: colors.error.default, + marginBottom: 16, + }, + hintInput: { + borderRadius: 6, + borderWidth: 1, + borderColor: colors.border.default, + padding: 16, + minHeight: 76, + paddingTop: 16, + color: colors.text.default, + }, + dismissButton: { + color: colors.text.default, + }, + }); -const HintModal = ({ onCancel, onConfirm, modalVisible, onRequestClose, value, onChangeText }) => ( - - - - - {strings('manual_backup_step_3.recovery_hint')} - - - +const HintModal = ({ onCancel, onConfirm, modalVisible, onRequestClose, value, onChangeText }) => { + const { colors, themeAppearance } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + + + + {strings('manual_backup_step_3.recovery_hint')} + + + + + {strings('manual_backup_step_3.leave_hint')} + {strings('manual_backup_step_3.no_seedphrase')} + - {strings('manual_backup_step_3.leave_hint')} - {strings('manual_backup_step_3.no_seedphrase')} - - - - -); + + + ); +}; const propTypes = { onCancel: PropTypes.func.isRequired, diff --git a/app/components/UI/Identicon/index.js b/app/components/UI/Identicon/index.js index 62890da7eaa..de6c9d7231f 100644 --- a/app/components/UI/Identicon/index.js +++ b/app/components/UI/Identicon/index.js @@ -3,9 +3,9 @@ import PropTypes from 'prop-types'; import { Image, View, ViewPropTypes } from 'react-native'; import { toDataUrl } from '../../../util/blockies.js'; import FadeIn from 'react-native-fade-in-image'; -import { colors } from '../../../styles/common.js'; import Jazzicon from 'react-native-jazzicon'; import { connect } from 'react-redux'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; /** * UI component that renders an Identicon @@ -16,6 +16,7 @@ import { connect } from 'react-redux'; // eslint-disable-next-line react/display-name const Identicon = React.memo((props) => { const { diameter, address, customStyle, noFadeIn, useBlockieIcon } = props; + const { colors } = useAppThemeFromContext() || mockTheme; if (!address) return null; const uri = useBlockieIcon && toDataUrl(address); @@ -40,7 +41,7 @@ const Identicon = React.memo((props) => { if (noFadeIn) { return image; } - return {image}; + return {image}; }); Identicon.propTypes = { diff --git a/app/components/UI/InvalidCustomNetworkAlert/__snapshots__/index.test.tsx.snap b/app/components/UI/InvalidCustomNetworkAlert/__snapshots__/index.test.tsx.snap index 236ebca9ba8..0c159dad38e 100644 --- a/app/components/UI/InvalidCustomNetworkAlert/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/InvalidCustomNetworkAlert/__snapshots__/index.test.tsx.snap @@ -17,14 +17,14 @@ exports[`InvalidCustomNetworkAlert should render correctly 1`] = ` style={ Object { "borderBottomWidth": 0.5, - "borderColor": "#d6d9dc", + "borderColor": "#D6D9DC", } } > diff --git a/app/components/UI/InvalidCustomNetworkAlert/index.js b/app/components/UI/InvalidCustomNetworkAlert/index.js index 986772f28dd..eba390761e5 100644 --- a/app/components/UI/InvalidCustomNetworkAlert/index.js +++ b/app/components/UI/InvalidCustomNetworkAlert/index.js @@ -1,59 +1,69 @@ import React from 'react'; import { StyleSheet, Text, View, SafeAreaView } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import StyledButton from '../StyledButton'; import PropTypes from 'prop-types'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - borderRadius: 10, - padding: 20, - }, - titleWrapper: { - borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - }, - title: { - textAlign: 'center', - fontSize: 17, - marginVertical: 12, - marginHorizontal: 20, - color: colors.fontPrimary, - ...fontStyles.bold, - }, - textWrapper: { - marginTop: 20, - marginBottom: 40, - }, - text: { - textAlign: 'center', - fontSize: 15, - lineHeight: 20, - marginBottom: 20, - ...fontStyles.normal, - }, - hint: { - textAlign: 'center', - fontSize: 15, - lineHeight: 20, - ...fontStyles.normal, - }, - link: { - color: colors.blue, - }, - button: { - marginBottom: 10, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + borderRadius: 10, + padding: 20, + }, + titleWrapper: { + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + }, + title: { + textAlign: 'center', + fontSize: 17, + marginVertical: 12, + marginHorizontal: 20, + color: colors.text.default, + ...fontStyles.bold, + }, + textWrapper: { + marginTop: 20, + marginBottom: 40, + }, + text: { + textAlign: 'center', + fontSize: 15, + lineHeight: 20, + marginBottom: 20, + ...fontStyles.normal, + color: colors.text.default, + }, + hint: { + textAlign: 'center', + fontSize: 15, + lineHeight: 20, + ...fontStyles.normal, + color: colors.text.default, + }, + link: { + color: colors.primary.default, + }, + button: { + marginBottom: 10, + }, + }); const InvalidCustomNetworkAlert = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + const closeModal = () => props.onClose(); const goToEditNetwork = () => { closeModal(); - props.navigation.navigate('SettingsView', { screen: 'NetworkSettings', params: { network: props.network } }); + props.navigation.navigate('SettingsView', { + screen: 'SettingsFlow', + params: { screen: 'NetworkSettings', params: { network: props.network } }, + }); }; const openLink = () => { diff --git a/app/components/UI/MessageSign/__snapshots__/index.test.tsx.snap b/app/components/UI/MessageSign/__snapshots__/index.test.tsx.snap index befb2011162..d3cb2d0218c 100644 --- a/app/components/UI/MessageSign/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/MessageSign/__snapshots__/index.test.tsx.snap @@ -23,6 +23,11 @@ exports[`MessageSign should render correctly 1`] = ` > message diff --git a/app/components/UI/MessageSign/index.js b/app/components/UI/MessageSign/index.js index 6b339f7c6bd..4ae55564162 100644 --- a/app/components/UI/MessageSign/index.js +++ b/app/components/UI/MessageSign/index.js @@ -10,17 +10,23 @@ import { strings } from '../../../../locales/i18n'; import { WALLET_CONNECT_ORIGIN } from '../../../util/walletconnect'; import URL from 'url-parse'; import AnalyticsV2 from '../../../util/analyticsV2'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - expandedMessage: { - textAlign: 'center', - ...fontStyles.regular, - fontSize: 14, - }, - messageWrapper: { - marginBottom: 4, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + expandedMessage: { + textAlign: 'center', + ...fontStyles.regular, + fontSize: 14, + color: colors.text.default, + }, + messageText: { + color: colors.text.default, + }, + messageWrapper: { + marginBottom: 4, + }, + }); /** * Component that supports eth_sign @@ -128,20 +134,28 @@ export default class MessageSign extends PureComponent { this.props.onConfirm(); }; + getStyles = () => { + const colors = this.context.colors || mockTheme.colors; + return createStyles(colors); + }; + renderMessageText = () => { const { messageParams, showExpandedMessage } = this.props; const { truncateMessage } = this.state; + const styles = this.getStyles(); let messageText; if (showExpandedMessage) { messageText = {messageParams.data}; } else { messageText = truncateMessage ? ( - + {messageParams.data} ) : ( - {messageParams.data} + + {messageParams.data} + ); } return messageText; @@ -157,6 +171,8 @@ export default class MessageSign extends PureComponent { render() { const { currentPageInformation, navigation, showExpandedMessage, toggleExpandedMessage } = this.props; + const styles = this.getStyles(); + const rootView = showExpandedMessage ? ( + StyleSheet.create({ + main: { + ...StyleSheet.absoluteFillObject, + backgroundColor: colors.background.default, + }, + metamaskName: { + marginTop: 10, + height: 25, + width: 170, + alignSelf: 'center', + alignItems: 'center', + justifyContent: 'center', + }, + logoWrapper: { + paddingTop: 50, + marginTop: Dimensions.get('window').height / 2 - LOGO_SIZE / 2 - LOGO_PADDING, + height: LOGO_SIZE + LOGO_PADDING * 2, + }, + foxAndName: { + alignSelf: 'center', + alignItems: 'center', + justifyContent: 'center', + }, + animation: { + width: 110, + height: 110, + alignSelf: 'center', + alignItems: 'center', + justifyContent: 'center', + }, + fox: { + width: 110, + height: 110, + alignSelf: 'center', + alignItems: 'center', + justifyContent: 'center', + }, + }); const MetaMaskAnimation = ({ opacity, @@ -57,31 +61,37 @@ const MetaMaskAnimation = ({ animation: any; animationName: any; onAnimationFinish: () => void; -}): JSX.Element => ( - - - - - - +}): JSX.Element => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + const wordmark = useAssetFromTheme(wordmarkLight, wordmarkDark); + + return ( + + + + + + + - - - -); + + + ); +}; MetaMaskAnimation.propTypes = { opacity: PropTypes.object, diff --git a/app/components/UI/Navbar/index.js b/app/components/UI/Navbar/index.js index 9748efb4479..38d332e7c22 100644 --- a/app/components/UI/Navbar/index.js +++ b/app/components/UI/Navbar/index.js @@ -5,7 +5,7 @@ import ModalNavbarTitle from '../ModalNavbarTitle'; import AccountRightButton from '../AccountRightButton'; import NavbarBrowserTitle from '../NavbarBrowserTitle'; import { Alert, Text, TouchableOpacity, View, StyleSheet, Image, Keyboard, InteractionManager } from 'react-native'; -import { fontStyles, colors } from '../../../styles/common'; +import { fontStyles, colors as importedColors } from '../../../styles/common'; import IonicIcon from 'react-native-vector-icons/Ionicons'; import AntIcon from 'react-native-vector-icons/AntDesign'; import EvilIcons from 'react-native-vector-icons/EvilIcons'; @@ -36,10 +36,6 @@ const trackEventWithParameters = (event, params) => { }; const styles = StyleSheet.create({ - headerStyle: { - shadowColor: colors.transparent, - elevation: 0, - }, metamaskName: { width: 122, height: 15, @@ -49,9 +45,6 @@ const styles = StyleSheet.create({ height: 40, marginRight: 10, }, - backIcon: { - color: colors.blue, - }, backIconIOS: { marginHorizontal: 4, marginTop: -4, @@ -79,14 +72,6 @@ const styles = StyleSheet.create({ paddingRight: Device.isAndroid() ? 22 : 18, marginTop: 5, }, - infoIcon: { - color: colors.blue, - }, - closeButtonText: { - color: colors.blue, - fontSize: 14, - ...fontStyles.normal, - }, browserRightButton: { flex: 1, marginRight: Device.isAndroid() ? 10 : 0, @@ -107,13 +92,6 @@ const styles = StyleSheet.create({ metamaskNameWrapper: { marginLeft: Device.isAndroid() ? 20 : 0, }, - centeredTitle: { - fontSize: 20, - color: colors.fontPrimary, - textAlign: 'center', - ...fontStyles.normal, - alignItems: 'center', - }, }); const metamask_name = require('../../../images/metamask-name.png'); // eslint-disable-line @@ -128,7 +106,18 @@ const metamask_fox = require('../../../images/fox.png'); // eslint-disable-line * @param {bool} disableNetwork - Boolean that specifies if the network can be changed, defaults to false * @returns {Object} - Corresponding navbar options containing headerTitle, headerLeft, headerTruncatedBackTitle and headerRight */ -export default function getNavbarOptions(title, disableNetwork = false, drawerRef) { +export default function getNavbarOptions(title, disableNetwork = false, drawerRef, themeColors) { + const innerStyles = StyleSheet.create({ + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + headerIcon: { + color: themeColors.primary.default, + }, + }); + function onPress() { Keyboard.dismiss(); drawerRef.current?.showDrawer?.(); @@ -142,11 +131,13 @@ export default function getNavbarOptions(title, disableNetwork = false, drawerRe ), headerRight: () => , + headerStyle: innerStyles.headerStyle, + headerTintColor: themeColors.primary.default, }; } @@ -158,22 +149,32 @@ export default function getNavbarOptions(title, disableNetwork = false, drawerRe * @param {Object} navigation - Navigation object required to push new views * @returns {Object} - Corresponding navbar options containing title and headerTitleStyle */ -export function getNavigationOptionsTitle(title, navigation, isFullScreenModal) { +export function getNavigationOptionsTitle(title, navigation, isFullScreenModal, themeColors) { + const innerStyles = StyleSheet.create({ + headerTitleStyle: { + fontSize: 20, + color: themeColors.text.default, + ...fontStyles.normal, + }, + headerIcon: { + color: themeColors.primary.default, + }, + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + }); function navigationPop() { navigation.pop(); } return { title, - headerTitleStyle: { - fontSize: 20, - color: colors.fontPrimary, - ...fontStyles.normal, - }, - headerTintColor: colors.blue, + headerTitleStyle: innerStyles.headerTitleStyle, headerRight: () => isFullScreenModal ? ( - + ) : null, headerLeft: () => @@ -182,10 +183,12 @@ export function getNavigationOptionsTitle(title, navigation, isFullScreenModal) ), + headerStyle: innerStyles.headerStyle, + headerTintColor: themeColors.primary.default, }; } @@ -197,7 +200,27 @@ export function getNavigationOptionsTitle(title, navigation, isFullScreenModal) * @param {Object} navigation - Navigation object required to push new views * @returns {Object} - Corresponding navbar options */ -export function getEditableOptions(title, navigation, route) { +export function getEditableOptions(title, navigation, route, themeColors) { + const innerStyles = StyleSheet.create({ + headerTitleStyle: { + fontSize: 20, + color: themeColors.text.default, + ...fontStyles.normal, + }, + headerIcon: { + color: themeColors.primary.default, + }, + headerButtonText: { + color: themeColors.primary.default, + fontSize: 14, + ...fontStyles.normal, + }, + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + }); function navigationPop() { navigation.pop(); } @@ -206,31 +229,28 @@ export function getEditableOptions(title, navigation, route) { const addMode = route.params?.mode === 'add'; return { title, - headerTitleStyle: { - fontSize: 20, - color: colors.fontPrimary, - ...fontStyles.normal, - }, - headerTintColor: colors.blue, + headerTitleStyle: innerStyles.headerTitleStyle, headerLeft: () => ( ), headerRight: () => !addMode ? ( - + {editMode ? strings('address_book.edit') : strings('address_book.cancel')} ) : ( ), + headerStyle: innerStyles.headerStyle, + headerTintColor: themeColors.primary.default, }; } @@ -242,16 +262,27 @@ export function getEditableOptions(title, navigation, route) { * @param {Object} navigation - Navigation object required to push new views * @returns {Object} - Corresponding navbar options containing title, headerLeft and headerRight */ -export function getPaymentRequestOptionsTitle(title, navigation, route) { +export function getPaymentRequestOptionsTitle(title, navigation, route, themeColors) { const goBack = route.params?.dispatch; - return { - title, + const innerStyles = StyleSheet.create({ headerTitleStyle: { fontSize: 20, - color: colors.fontPrimary, + color: themeColors.text.default, ...fontStyles.normal, }, - headerTintColor: colors.blue, + headerIcon: { + color: themeColors.primary.default, + }, + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + }); + + return { + title, + headerTitleStyle: innerStyles.headerTitleStyle, headerLeft: () => goBack ? ( // eslint-disable-next-line react/jsx-no-bind @@ -263,7 +294,7 @@ export function getPaymentRequestOptionsTitle(title, navigation, route) { ) : ( @@ -272,9 +303,11 @@ export function getPaymentRequestOptionsTitle(title, navigation, route) { headerRight: () => ( // eslint-disable-next-line react/jsx-no-bind navigation.pop()} style={styles.closeButton}> - + ), + headerStyle: innerStyles.headerStyle, + headerTintColor: themeColors.primary.default, }; } @@ -284,16 +317,21 @@ export function getPaymentRequestOptionsTitle(title, navigation, route) { * * @returns {Object} - Corresponding navbar options containing title, and headerRight */ -export function getPaymentRequestSuccessOptionsTitle(navigation) { - return { +export function getPaymentRequestSuccessOptionsTitle(navigation, themeColors) { + const innerStyles = StyleSheet.create({ headerStyle: { - shadowColor: colors.transparent, + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, elevation: 0, - backgroundColor: colors.white, - borderBottomWidth: 0, }, + headerIcon: { + color: themeColors.primary.default, + }, + }); + + return { + headerStyle: innerStyles.headerStyle, title: null, - headerTintColor: colors.blue, headerLeft: () => , headerRight: () => ( - + ), + headerTintColor: themeColors.primary.default, }; } @@ -315,7 +354,19 @@ export function getPaymentRequestSuccessOptionsTitle(navigation) { * @param {string} title - Title in string format * @returns {Object} - Corresponding navbar options containing title and headerTitleStyle */ -export function getTransactionOptionsTitle(_title, navigation, route) { +export function getTransactionOptionsTitle(_title, navigation, route, themeColors) { + const innerStyles = StyleSheet.create({ + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + headerButtonText: { + color: themeColors.primary.default, + fontSize: 14, + ...fontStyles.normal, + }, + }); const transactionMode = route.params?.mode ?? ''; const { name } = route; const leftText = transactionMode === 'edit' ? strings('transaction.cancel') : strings('transaction.edit'); @@ -325,6 +376,7 @@ export function getTransactionOptionsTitle(_title, navigation, route) { const rightAction = () => navigation.pop(); const rightText = strings('transaction.cancel'); const title = transactionMode === 'edit' ? 'transaction.edit' : _title; + return { headerTitle: () => , headerLeft: () => @@ -337,7 +389,11 @@ export function getTransactionOptionsTitle(_title, navigation, route) { testID={'confirm-txn-edit-button'} > {leftText} @@ -349,11 +405,13 @@ export function getTransactionOptionsTitle(_title, navigation, route) { name === 'Send' ? ( // eslint-disable-next-line react/jsx-no-bind - {rightText} + {rightText} ) : ( ), + headerStyle: innerStyles.headerStyle, + headerTintColor: themeColors.primary.default, }; } @@ -372,9 +430,21 @@ export function getApproveNavbar(title) { * @param {string} title - Title in string format * @returns {Object} - Corresponding navbar options containing title and headerTitleStyle */ -export function getSendFlowTitle(title, navigation, route) { +export function getSendFlowTitle(title, navigation, route, themeColors) { + const innerStyles = StyleSheet.create({ + headerButtonText: { + color: themeColors.primary.default, + fontSize: 14, + ...fontStyles.normal, + }, + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + }); const rightAction = () => { - const providerType = route.params?.providerType ?? ''; + const providerType = route?.params?.providerType ?? ''; trackEventWithParameters(ANALYTICS_EVENT_OPTS.SEND_FLOW_CANCEL, { view: title.split('.')[1], network: providerType, @@ -392,18 +462,19 @@ export function getSendFlowTitle(title, navigation, route) { headerRight: () => ( // eslint-disable-next-line react/jsx-no-bind - {strings('transaction.cancel')} + {strings('transaction.cancel')} ), headerLeft: () => canGoBack ? ( // eslint-disable-next-line react/jsx-no-bind - {strings('transaction.back')} + {strings('transaction.back')} ) : ( ), + headerStyle: innerStyles.headerStyle, }; } @@ -415,7 +486,18 @@ export function getSendFlowTitle(title, navigation, route) { * @param {Object} navigation - Navigation object required to push new views * @returns {Object} - Corresponding navbar options containing headerTitle, headerLeft and headerRight */ -export function getBrowserViewNavbarOptions(navigation, route, drawerRef) { +export function getBrowserViewNavbarOptions(navigation, route, drawerRef, themeColors) { + const innerStyles = StyleSheet.create({ + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + headerIcon: { + color: themeColors.primary.default, + }, + }); + const url = route.params?.url ?? ''; let host = null; let isHttps = false; @@ -452,7 +534,7 @@ export function getBrowserViewNavbarOptions(navigation, route, drawerRef) { ), @@ -472,6 +554,7 @@ export function getBrowserViewNavbarOptions(navigation, route, drawerRef) { ), + headerStyle: innerStyles.headerStyle, }; } @@ -495,24 +578,32 @@ export function getModalNavbarOptions(title) { * * @returns {Object} - Corresponding navbar options containing headerTitle, headerTitle and headerTitle */ -export function getOnboardingNavbarOptions(navigation, route, { headerLeft } = {}) { +export function getOnboardingNavbarOptions(route, { headerLeft } = {}, themeColors) { const headerLeftHide = headerLeft || route.params?.headerLeft; - - return { + const innerStyles = StyleSheet.create({ headerStyle: { - shadowColor: colors.transparent, + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, elevation: 0, - backgroundColor: colors.white, - borderBottomWidth: 0, }, + metamaskName: { + width: 122, + height: 15, + tintColor: themeColors.text.default, + }, + }); + + return { + headerStyle: innerStyles.headerStyle, headerTitle: () => ( - + ), headerBackTitle: strings('navigation.back'), headerRight: () => , headerLeft: headerLeftHide, + headerTintColor: themeColors.primary.default, }; } @@ -521,16 +612,28 @@ export function getOnboardingNavbarOptions(navigation, route, { headerLeft } = { * * @returns {Object} - Corresponding navbar options containing headerTitle */ -export function getTransparentOnboardingNavbarOptions() { +export function getTransparentOnboardingNavbarOptions(themeColors) { + const innerStyles = StyleSheet.create({ + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + metamaskName: { + width: 122, + height: 15, + tintColor: themeColors.text.default, + }, + }); return { headerTitle: () => ( - + ), headerLeft: () => , headerRight: () => , - headerStyle: styles.headerStyle, + headerStyle: innerStyles.headerStyle, }; } @@ -539,16 +642,29 @@ export function getTransparentOnboardingNavbarOptions() { * * @returns {Object} - Corresponding navbar options containing headerTitle and a back button */ -export function getTransparentBackOnboardingNavbarOptions() { +export function getTransparentBackOnboardingNavbarOptions(themeColors) { + const innerStyles = StyleSheet.create({ + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + metamaskName: { + width: 122, + height: 15, + tintColor: themeColors.text.default, + }, + }); return { headerTitle: () => ( - + ), headerBackTitle: strings('navigation.back'), headerRight: () => , - headerStyle: styles.headerStyle, + headerStyle: innerStyles.headerStyle, + headerTintColor: themeColors.primary.default, }; } @@ -558,15 +674,23 @@ export function getTransparentBackOnboardingNavbarOptions() { * * @returns {Object} - Corresponding navbar options containing headerLeft */ -export function getOptinMetricsNavbarOptions() { - return { +export function getOptinMetricsNavbarOptions(themeColors) { + const innerStyles = StyleSheet.create({ headerStyle: { - shadowColor: colors.transparent, + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, elevation: 0, - backgroundColor: colors.white, - borderBottomWidth: 0, height: 100, }, + metamaskName: { + width: 122, + height: 15, + tintColor: themeColors.text.default, + }, + }); + + return { + headerStyle: innerStyles.headerStyle, title: null, headerLeft: () => ( @@ -574,10 +698,11 @@ export function getOptinMetricsNavbarOptions() { - + ), + headerTintColor: themeColors.primary.default, }; } /** @@ -586,26 +711,45 @@ export function getOptinMetricsNavbarOptions() { * * @returns {Object} - Corresponding navbar options containing headerTitle, headerTitle and headerTitle */ -export function getClosableNavigationOptions(title, backButtonText, navigation) { +export function getClosableNavigationOptions(title, backButtonText, navigation, themeColors) { + const innerStyles = StyleSheet.create({ + headerButtonText: { + color: themeColors.primary.default, + fontSize: 14, + ...fontStyles.normal, + }, + headerIcon: { + color: themeColors.primary.default, + }, + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + headerTitleStyle: { + fontSize: 20, + ...fontStyles.normal, + color: themeColors.text.default, + }, + }); function navigationPop() { navigation.pop(); } return { title, - headerTitleStyle: { - fontSize: 20, - ...fontStyles.normal, - }, + headerTitleStyle: innerStyles.headerTitleStyle, headerLeft: () => Device.isIos() ? ( - {backButtonText} + {backButtonText} ) : ( - + ), + headerStyle: innerStyles.headerStyle, + headerTintColor: themeColors.primary.default, }; } @@ -627,7 +771,18 @@ export function getOfflineModalNavbar() { * * @returns {Object} - Corresponding navbar options containing headerTitle, headerTitle and headerTitle */ -export function getWalletNavbarOptions(title, navigation, drawerRef) { +export function getWalletNavbarOptions(title, navigation, drawerRef, themeColors) { + const innerStyles = StyleSheet.create({ + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + headerIcon: { + color: themeColors.primary.default, + }, + }); + const onScanSuccess = (data, content) => { if (data.private_key) { Alert.alert( @@ -684,7 +839,7 @@ export function getWalletNavbarOptions(title, navigation, drawerRef) { ), @@ -694,9 +849,11 @@ export function getWalletNavbarOptions(title, navigation, drawerRef) { // eslint-disable-next-line onPress={openQRScanner} > - + ), + headerStyle: innerStyles.headerStyle, + headerTintColor: themeColors.primary.default, }; } @@ -708,7 +865,17 @@ export function getWalletNavbarOptions(title, navigation, drawerRef) { * @param {Object} navigation - Navigation object required to push new views * @returns {Object} - Corresponding navbar options containing headerTitle and headerTitle */ -export function getNetworkNavbarOptions(title, translate, navigation) { +export function getNetworkNavbarOptions(title, translate, navigation, themeColors) { + const innerStyles = StyleSheet.create({ + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + headerIcon: { + color: themeColors.primary.default, + }, + }); return { headerTitle: () => , headerLeft: () => ( @@ -717,11 +884,12 @@ export function getNetworkNavbarOptions(title, translate, navigation) { ), headerRight: () => , + headerStyle: innerStyles.headerStyle, }; } @@ -730,39 +898,75 @@ export function getNetworkNavbarOptions(title, translate, navigation) { * * @returns {Object} - Corresponding navbar options containing headerTitle and headerTitle */ -export function getWebviewNavbar(navigation, route) { +export function getWebviewNavbar(navigation, route, themeColors) { + const innerStyles = StyleSheet.create({ + headerTitleStyle: { + fontSize: 20, + color: themeColors.text.default, + textAlign: 'center', + ...fontStyles.normal, + alignItems: 'center', + }, + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + headerIcon: { + color: themeColors.primary.default, + }, + }); + const title = route.params?.title ?? ''; const share = route.params?.dispatch; return { - headerTitle: () => {title}, + headerTitle: () => {title}, headerLeft: () => Device.isAndroid() ? ( // eslint-disable-next-line react/jsx-no-bind navigation.pop()} style={styles.backButton}> - + ) : ( // eslint-disable-next-line react/jsx-no-bind navigation.pop()} style={styles.backButton}> - + ), headerRight: () => Device.isAndroid() ? ( - + ) : ( - + ), + headerStyle: innerStyles.headerStyle, }; } -export function getPaymentSelectorMethodNavbar(navigation, onPop) { +export function getPaymentSelectorMethodNavbar(navigation, onPop, themeColors) { + const innerStyles = StyleSheet.create({ + headerButtonText: { + color: themeColors.primary.default, + }, + headerTitleStyle: { + fontSize: 20, + color: themeColors.text.default, + textAlign: 'center', + ...fontStyles.normal, + alignItems: 'center', + }, + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + }); return { - headerTitle: () => {strings('fiat_on_ramp.purchase_method')}, + headerTitle: () => {strings('fiat_on_ramp.purchase_method')}, headerLeft: () => , headerRight: () => ( // eslint-disable-next-line react/jsx-no-bind @@ -773,20 +977,35 @@ export function getPaymentSelectorMethodNavbar(navigation, onPop) { }} style={styles.closeButton} > - {strings('navigation.cancel')} + {strings('navigation.cancel')} ), + headerStyle: innerStyles.headerStyle, }; } -export function getPaymentMethodApplePayNavbar(navigation, onPop, onExit) { - return { - title: strings('fiat_on_ramp.amount_to_buy'), +export function getPaymentMethodApplePayNavbar(navigation, onPop, onExit, themeColors) { + const innerStyles = StyleSheet.create({ headerTitleStyle: { fontSize: 20, - color: colors.fontPrimary, + color: themeColors.text.default, ...fontStyles.normal, }, + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + headerButtonText: { + color: themeColors.primary.default, + }, + headerIcon: { + color: themeColors.primary.default, + }, + }); + return { + title: strings('fiat_on_ramp.amount_to_buy'), + headerTitleStyle: innerStyles.headerTitleStyle, headerRight: () => ( // eslint-disable-next-line react/jsx-no-bind - {strings('navigation.cancel')} + {strings('navigation.cancel')} ), headerLeft: () => @@ -809,7 +1028,7 @@ export function getPaymentMethodApplePayNavbar(navigation, onPop, onExit) { }} style={styles.backButton} > - + ) : ( // eslint-disable-next-line react/jsx-no-bind @@ -820,21 +1039,34 @@ export function getPaymentMethodApplePayNavbar(navigation, onPop, onExit) { }} style={styles.closeButton} > - {strings('navigation.back')} + {strings('navigation.back')} ), + headerStyle: innerStyles.headerStyle, }; } -export function getTransakWebviewNavbar(navigation, route, onPop) { - const title = route.params?.title ?? ''; - return { - title, +export function getTransakWebviewNavbar(navigation, route, onPop, themeColors) { + const innerStyles = StyleSheet.create({ headerTitleStyle: { fontSize: 20, - color: colors.fontPrimary, + color: themeColors.text.default, ...fontStyles.normal, }, + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + headerIcon: { + color: themeColors.primary.default, + }, + }); + + const title = route.params?.title ?? ''; + return { + title, + headerTitleStyle: innerStyles.headerTitleStyle, headerLeft: () => Device.isAndroid() ? ( // eslint-disable-next-line react/jsx-no-bind @@ -845,7 +1077,7 @@ export function getTransakWebviewNavbar(navigation, route, onPop) { }} style={styles.backButton} > - + ) : ( // eslint-disable-next-line react/jsx-no-bind @@ -856,13 +1088,27 @@ export function getTransakWebviewNavbar(navigation, route, onPop) { }} style={styles.backButton} > - + ), + headerStyle: innerStyles.headerStyle, + headerTintColor: themeColors.primary.default, }; } -export function getSwapsAmountNavbar(navigation, route) { +export function getSwapsAmountNavbar(navigation, route, themeColors) { + const innerStyles = StyleSheet.create({ + headerButtonText: { + color: themeColors.primary.default, + fontSize: 14, + ...fontStyles.normal, + }, + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + }); const title = route.params?.title ?? 'Swap'; return { headerTitle: () => , @@ -870,12 +1116,28 @@ export function getSwapsAmountNavbar(navigation, route) { headerRight: () => ( // eslint-disable-next-line react/jsx-no-bind navigation.dangerouslyGetParent()?.pop()} style={styles.closeButton}> - {strings('navigation.cancel')} + {strings('navigation.cancel')} ), + headerStyle: innerStyles.headerStyle, }; } -export function getSwapsQuotesNavbar(navigation, route) { +export function getSwapsQuotesNavbar(navigation, route, themeColors) { + const innerStyles = StyleSheet.create({ + headerButtonText: { + color: themeColors.primary.default, + fontSize: 14, + ...fontStyles.normal, + }, + headerIcon: { + color: themeColors.primary.default, + }, + headerStyle: { + backgroundColor: themeColors.background.default, + shadowColor: importedColors.transparent, + elevation: 0, + }, + }); const title = route.params?.title ?? 'Swap'; const leftActionText = route.params?.leftAction ?? strings('navigation.back'); @@ -915,19 +1177,20 @@ export function getSwapsQuotesNavbar(navigation, route) { Device.isAndroid() ? ( // eslint-disable-next-line react/jsx-no-bind - + ) : ( // eslint-disable-next-line react/jsx-no-bind - {leftActionText} + {leftActionText} ), headerRight: () => ( // eslint-disable-next-line react/jsx-no-bind - {strings('navigation.cancel')} + {strings('navigation.cancel')} ), + headerStyle: innerStyles.headerStyle, }; } diff --git a/app/components/UI/NavbarBrowserTitle/index.js b/app/components/UI/NavbarBrowserTitle/index.js index a199595ae21..5d4f41ef4be 100644 --- a/app/components/UI/NavbarBrowserTitle/index.js +++ b/app/components/UI/NavbarBrowserTitle/index.js @@ -2,58 +2,62 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { TouchableOpacity, View, StyleSheet, Text, Image } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import Networks from '../../../util/networks'; import Icon from 'react-native-vector-icons/FontAwesome'; import Device from '../../../util/device'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - alignItems: 'center', - flex: 1, - }, - network: { - flexDirection: 'row', - marginBottom: 5, - }, - networkName: { - fontSize: 11, - lineHeight: 11, - color: colors.fontSecondary, - ...fontStyles.normal, - }, - networkIcon: { - marginTop: 3, - width: 5, - height: 5, - borderRadius: 100, - marginRight: 5, - }, - currentUrlWrapper: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - flex: 1, - marginBottom: Device.isAndroid() ? 5 : 0, - }, - lockIcon: { - marginTop: 2, - marginLeft: 10, - }, - currentUrl: { - ...fontStyles.normal, - fontSize: 14, - textAlign: 'center', - }, - currentUrlAndroid: { - maxWidth: '60%', - }, - siteIcon: { - width: 16, - height: 16, - marginRight: 4, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + alignItems: 'center', + flex: 1, + }, + network: { + flexDirection: 'row', + marginBottom: 5, + }, + networkName: { + fontSize: 11, + lineHeight: 11, + color: colors.text.default, + ...fontStyles.normal, + }, + networkIcon: { + marginTop: 3, + width: 5, + height: 5, + borderRadius: 100, + marginRight: 5, + }, + currentUrlWrapper: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + flex: 1, + marginBottom: Device.isAndroid() ? 5 : 0, + }, + lockIcon: { + marginTop: 2, + marginLeft: 10, + color: colors.text.default, + }, + currentUrl: { + ...fontStyles.normal, + fontSize: 14, + textAlign: 'center', + color: colors.text.default, + }, + currentUrlAndroid: { + maxWidth: '60%', + }, + siteIcon: { + width: 16, + height: 16, + marginRight: 4, + }, + }); /** * UI PureComponent that renders inside the navbar @@ -114,8 +118,11 @@ class NavbarBrowserTitle extends PureComponent { render = () => { const { https, network, hostname, error, icon } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); const color = (Networks[network.provider.type] && Networks[network.provider.type].color) || null; const name = this.getNetworkName(network); + return ( @@ -130,7 +137,7 @@ class NavbarBrowserTitle extends PureComponent { {https && !error ? : null} - + {name} @@ -142,4 +149,6 @@ class NavbarBrowserTitle extends PureComponent { const mapStateToProps = (state) => ({ network: state.engine.backgroundState.NetworkController }); +NavbarBrowserTitle.contextType = ThemeContext; + export default connect(mapStateToProps)(NavbarBrowserTitle); diff --git a/app/components/UI/NavbarTitle/index.js b/app/components/UI/NavbarTitle/index.js index 4cfc7f6496d..1090d71f253 100644 --- a/app/components/UI/NavbarTitle/index.js +++ b/app/components/UI/NavbarTitle/index.js @@ -2,43 +2,45 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { TouchableOpacity, View, StyleSheet, Text } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles, colors as importedColors } from '../../../styles/common'; import Networks from '../../../util/networks'; import { toggleNetworkModal } from '../../../actions/modals'; import { strings } from '../../../../locales/i18n'; import Device from '../../../util/device'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - alignItems: 'center', - flex: 1, - }, - network: { - flexDirection: 'row', - }, - networkName: { - fontSize: 11, - color: colors.grey400, - ...fontStyles.normal, - }, - networkIcon: { - width: 5, - height: 5, - borderRadius: 100, - marginRight: 5, - marginTop: Device.isIos() ? 4 : 5, - }, - title: { - fontSize: 18, - ...fontStyles.normal, - color: colors.black, - }, - otherNetworkIcon: { - backgroundColor: colors.transparent, - borderColor: colors.grey100, - borderWidth: 1, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + alignItems: 'center', + flex: 1, + }, + network: { + flexDirection: 'row', + }, + networkName: { + fontSize: 11, + color: colors.text.alternative, + ...fontStyles.normal, + }, + networkIcon: { + width: 5, + height: 5, + borderRadius: 100, + marginRight: 5, + marginTop: Device.isIos() ? 4 : 5, + }, + title: { + fontSize: 18, + ...fontStyles.normal, + color: colors.text.default, + }, + otherNetworkIcon: { + backgroundColor: importedColors.transparent, + borderColor: colors.border.default, + borderWidth: 1, + }, + }); /** * UI PureComponent that renders inside the navbar @@ -90,6 +92,8 @@ class NavbarTitle extends PureComponent { const { network, title, translate } = this.props; let name = null; const color = (Networks[network.provider.type] && Networks[network.provider.type].color) || null; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); if (network.provider.nickname) { name = network.provider.nickname; @@ -124,6 +128,8 @@ class NavbarTitle extends PureComponent { }; } +NavbarTitle.contextType = ThemeContext; + const mapStateToProps = (state) => ({ network: state.engine.backgroundState.NetworkController, }); diff --git a/app/components/UI/NetworkList/index.js b/app/components/UI/NetworkList/index.js index bbc5de84f61..cff79e6e5c2 100644 --- a/app/components/UI/NetworkList/index.js +++ b/app/components/UI/NetworkList/index.js @@ -3,114 +3,116 @@ import Engine from '../../../core/Engine'; import PropTypes from 'prop-types'; import Icon from 'react-native-vector-icons/FontAwesome'; import { ScrollView, TouchableOpacity, StyleSheet, Text, View, SafeAreaView } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; +import { colors as importedColors, fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import Networks, { getAllNetworks, isSafeChainId } from '../../../util/networks'; import { connect } from 'react-redux'; import AnalyticsV2 from '../../../util/analyticsV2'; import { MAINNET, RPC } from '../../../constants/network'; +import { ThemeContext, mockTheme } from '../../../util/theme'; import { NETWORK_LIST_MODAL_CONTAINER_ID, OTHER_NETWORK_LIST_ID, NETWORK_SCROLL_ID } from '../../../constants/test-ids'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - borderRadius: 10, - minHeight: 450, - }, - titleWrapper: { - borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - }, - title: { - textAlign: 'center', - fontSize: 18, - marginVertical: 12, - marginHorizontal: 20, - color: colors.fontPrimary, - ...fontStyles.bold, - }, - otherNetworksHeader: { - marginTop: 0, - borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - }, - otherNetworksText: { - textAlign: 'left', - fontSize: 13, - marginVertical: 12, - marginHorizontal: 20, - color: colors.fontPrimary, - ...fontStyles.bold, - }, - networksWrapper: { - flex: 1, - }, - network: { - borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - flexDirection: 'row', - paddingHorizontal: 20, - paddingVertical: 20, - paddingLeft: 45, - }, - mainnet: { - borderBottomWidth: 0, - flexDirection: 'column', - }, - networkInfo: { - marginLeft: 15, - flex: 1, - }, - networkLabel: { - fontSize: 16, - color: colors.fontPrimary, - ...fontStyles.normal, - }, - footer: { - borderTopWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - height: 60, - justifyContent: 'center', - flexDirection: 'row', - alignItems: 'center', - }, - footerButton: { - flex: 1, - alignContent: 'center', - alignItems: 'center', - justifyContent: 'center', - height: 60, - }, - closeButton: { - fontSize: 16, - color: colors.blue, - ...fontStyles.normal, - }, - networkIcon: { - width: 15, - height: 15, - borderRadius: 100, - marginTop: 3, - }, - networkWrapper: { - flex: 0, - flexDirection: 'row', - }, - selected: { - position: 'absolute', - marginLeft: 20, - marginTop: 20, - }, - mainnetSelected: { - marginLeft: -30, - marginTop: 3, - }, - otherNetworkIcon: { - backgroundColor: colors.transparent, - borderColor: colors.grey100, - borderWidth: 2, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + borderRadius: 10, + minHeight: 450, + }, + titleWrapper: { + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + }, + title: { + textAlign: 'center', + fontSize: 18, + marginVertical: 12, + marginHorizontal: 20, + color: colors.text.default, + ...fontStyles.bold, + }, + otherNetworksHeader: { + marginTop: 0, + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + }, + otherNetworksText: { + textAlign: 'left', + fontSize: 13, + marginVertical: 12, + marginHorizontal: 20, + color: colors.text.default, + ...fontStyles.bold, + }, + networksWrapper: { + flex: 1, + }, + network: { + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + flexDirection: 'row', + paddingHorizontal: 20, + paddingVertical: 20, + paddingLeft: 45, + }, + mainnet: { + borderBottomWidth: 0, + flexDirection: 'column', + }, + networkInfo: { + marginLeft: 15, + flex: 1, + }, + networkLabel: { + fontSize: 16, + color: colors.text.default, + ...fontStyles.normal, + }, + footer: { + borderTopWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + height: 60, + justifyContent: 'center', + flexDirection: 'row', + alignItems: 'center', + }, + footerButton: { + flex: 1, + alignContent: 'center', + alignItems: 'center', + justifyContent: 'center', + height: 60, + }, + closeButton: { + fontSize: 16, + color: colors.primary.default, + ...fontStyles.normal, + }, + networkIcon: { + width: 15, + height: 15, + borderRadius: 100, + marginTop: 3, + }, + networkWrapper: { + flex: 0, + flexDirection: 'row', + }, + selected: { + position: 'absolute', + marginLeft: 20, + marginTop: 20, + }, + mainnetSelected: { + marginLeft: -30, + marginTop: 3, + }, + otherNetworkIcon: { + backgroundColor: importedColors.transparent, + borderColor: colors.border.muted, + borderWidth: 2, + }, + }); /** * View that contains the list of all the available networks @@ -197,39 +199,52 @@ export class NetworkList extends PureComponent { this.props.onClose(false); }; - networkElement = (selected, onPress, name, color, i, network) => ( - onPress(network)} // eslint-disable-line - > - {selected} - - - - {name} - - - - ); + getStyles = () => { + const colors = this.context.colors || mockTheme.colors; + return createStyles(colors); + }; + + networkElement = (selected, onPress, name, color, i, network) => { + const styles = this.getStyles(); + + return ( + onPress(network)} // eslint-disable-line + > + {selected} + + + + {name} + + + + ); + }; renderOtherNetworks = () => { const { provider } = this.props; + const colors = this.context.colors || mockTheme.colors; + return this.getOtherNetworks().map((network, i) => { const { color, name } = Networks[network]; const selected = - provider.type === network ? : null; + provider.type === network ? : null; return this.networkElement(selected, this.onNetworkChange, name, color, i, network); }); }; renderRpcNetworks = () => { const { frequentRpcList, provider } = this.props; + const colors = this.context.colors || mockTheme.colors; + return frequentRpcList.map(({ nickname, rpcUrl }, i) => { const { color, name } = { name: nickname || rpcUrl, color: null }; const selected = provider.rpcTarget === rpcUrl && provider.type === RPC ? ( - + ) : null; return this.networkElement(selected, this.onSetRpcTarget, name, color, i, rpcUrl); }); @@ -237,8 +252,10 @@ export class NetworkList extends PureComponent { renderMainnet() { const { provider } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = this.getStyles(); const isMainnet = - provider.type === MAINNET ? : null; + provider.type === MAINNET ? : null; const { color: mainnetColor, name: mainnetName } = Networks.mainnet; return ( @@ -261,30 +278,34 @@ export class NetworkList extends PureComponent { ); } - render = () => ( - - - - {strings('networks.title')} - - - - {this.renderMainnet()} - - - {strings('networks.other_networks')} + render = () => { + const styles = this.getStyles(); + + return ( + + + + {strings('networks.title')} - {this.renderOtherNetworks()} - {this.renderRpcNetworks()} - - - - {strings('networks.close')} - - - - ); + + {this.renderMainnet()} + + + {strings('networks.other_networks')} + + + {this.renderOtherNetworks()} + {this.renderRpcNetworks()} + + + + {strings('networks.close')} + + + + ); + }; } const mapStateToProps = (state) => ({ @@ -293,4 +314,6 @@ const mapStateToProps = (state) => ({ thirdPartyApiMode: state.privacy.thirdPartyApiMode, }); +NetworkList.contextType = ThemeContext; + export default connect(mapStateToProps)(NetworkList); diff --git a/app/components/UI/Notification/BaseNotification/index.js b/app/components/UI/Notification/BaseNotification/index.js index b80ab3ea66a..207e672ca38 100644 --- a/app/components/UI/Notification/BaseNotification/index.js +++ b/app/components/UI/Notification/BaseNotification/index.js @@ -1,58 +1,65 @@ import React from 'react'; import { TouchableOpacity, StyleSheet, View } from 'react-native'; import PropTypes from 'prop-types'; -import { colors, fontStyles, baseStyles } from '../../../../styles/common'; +import { fontStyles, baseStyles } from '../../../../styles/common'; import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'; import AnimatedSpinner from '../../AnimatedSpinner'; import { strings } from '../../../../../locales/i18n'; import IonicIcon from 'react-native-vector-icons/Ionicons'; import AntIcon from 'react-native-vector-icons/AntDesign'; import Text from '../../../Base/Text'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - defaultFlashFloating: { - backgroundColor: colors.normalAlert, - padding: 16, - marginHorizontal: 16, - flexDirection: 'row', - borderRadius: 8, - }, - flashLabel: { - flex: 1, - flexDirection: 'column', - color: colors.white, - }, - flashText: { - flex: 1, - fontSize: 12, - lineHeight: 18, - color: colors.white, - }, - flashTitle: { - flex: 1, - fontSize: 14, - marginBottom: 2, - lineHeight: 18, - color: colors.white, - ...fontStyles.bold, - }, - flashIcon: { - marginRight: 15, - }, - closeTouchable: { - flex: 0.1, - flexDirection: 'column', - alignItems: 'flex-end', - }, - closeIcon: { - flex: 1, - color: colors.white, - alignItems: 'flex-start', - marginTop: -8, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + floatingBackground: { + backgroundColor: colors.background.default, + marginHorizontal: 16, + borderRadius: 8, + }, + defaultFlashFloating: { + backgroundColor: colors.overlay.alternative, + padding: 16, + flexDirection: 'row', + flex: 1, + borderRadius: 8, + }, + flashLabel: { + flex: 1, + flexDirection: 'column', + color: colors.overlay.inverse, + }, + flashText: { + flex: 1, + fontSize: 12, + lineHeight: 18, + color: colors.overlay.inverse, + }, + flashTitle: { + flex: 1, + fontSize: 14, + marginBottom: 2, + lineHeight: 18, + color: colors.overlay.inverse, + ...fontStyles.bold, + }, + flashIcon: { + marginRight: 15, + }, + closeTouchable: { + flex: 0.1, + flexDirection: 'column', + alignItems: 'flex-end', + }, + closeIcon: { + flex: 1, + color: colors.overlay.inverse, + alignItems: 'flex-start', + marginTop: -8, + }, + }); -const getIcon = (status) => { +const getIcon = (status, colors, styles) => { switch (status) { case 'pending': case 'pending_withdrawal': @@ -64,14 +71,21 @@ const getIcon = (status) => { case 'success': case 'received': case 'received_payment': - return ; + return ; case 'cancelled': case 'error': - return ; + return ( + + ); case 'simple_notification_rejected': - return ; + return ; case 'simple_notification': - return ; + return ; } }; @@ -122,31 +136,40 @@ const BaseNotification = ({ onPress, onHide, autoDismiss, -}) => ( - - - {getIcon(status)} - - - {!title ? getTitle(status, data) : title} - - {!description ? getDescription(status, data) : description} - - - {autoDismiss && ( - - - - )} +}) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + + + {getIcon(status, colors, styles)} + + + {!title ? getTitle(status, data) : title} + + + {!description ? getDescription(status, data) : description} + + + + {autoDismiss && ( + + + + )} + + - - -); + + ); +}; BaseNotification.propTypes = { status: PropTypes.string, diff --git a/app/components/UI/Notification/SimpleNotification/index.js b/app/components/UI/Notification/SimpleNotification/index.js index 0ff29a8088f..a8c193be086 100644 --- a/app/components/UI/Notification/SimpleNotification/index.js +++ b/app/components/UI/Notification/SimpleNotification/index.js @@ -5,17 +5,24 @@ import Animated from 'react-native-reanimated'; import BaseNotification from './../BaseNotification'; import Device from '../../../../util/device'; import ElevatedView from 'react-native-elevated-view'; +import { colors as importedColors } from '../../../../styles/common'; const styles = StyleSheet.create({ modalTypeViewBrowser: { bottom: Device.isIphoneX() ? 70 : 60, }, - notificationContainer: { + elevatedView: { position: 'absolute', left: 0, right: 0, bottom: 0, paddingBottom: Device.isIphoneX() ? 20 : 10, + backgroundColor: importedColors.transparent, + }, + notificationContainer: { + flex: 0.1, + flexDirection: 'row', + alignItems: 'flex-end', }, }); @@ -28,7 +35,7 @@ function SimpleNotification({ isInBrowserView, notificationAnimated, hideCurrent { transform: [{ translateY: notificationAnimated }] }, ]} > - + + StyleSheet.create({ + absoluteFill: { + ...StyleSheet.absoluteFillObject, + }, + titleWrapper: { + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.default, + flexDirection: 'row', + }, + title: { + flex: 1, + textAlign: 'center', + fontSize: 18, + marginVertical: 12, + marginHorizontal: 24, + color: colors.text.default, + ...fontStyles.bold, + }, + notification: { + position: 'absolute', + bottom: 0, + paddingBottom: Device.isIphoneX() ? 20 : 10, + left: 0, + right: 0, + backgroundColor: importedColors.transparent, + }, + modalTypeViewBrowser: { + bottom: Device.isIphoneX() ? 70 : 60, + }, + closeIcon: { + paddingTop: 4, + position: 'absolute', + right: 16, + }, + modalsContainer: { + position: 'absolute', + left: 0, + top: 0, + bottom: 0, + width: '200%', + flexDirection: 'row', + backgroundColor: colors.overlay.default, + }, + modalOverlay: { + justifyContent: 'center', + alignItems: 'center', + flex: 1, + }, + modalContainer: { + width: '90%', + borderRadius: 10, + backgroundColor: colors.background.default, + }, + elevatedView: { + backgroundColor: importedColors.transparent, + }, + }); function TransactionNotification(props) { const { @@ -113,6 +107,9 @@ function TransactionNotification(props) { const actionXAnimated = useRef(new Animated.Value(0)).current; const detailsAnimated = useRef(new Animated.Value(0)).current; + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + const detailsFadeIn = useCallback(async () => { setTransactionDetailsIsVisible(true); setTimeout(() => animatedTimingStart(detailsAnimated, 1), 500); @@ -221,21 +218,35 @@ function TransactionNotification(props) { useEffect(() => onCloseNotification(), [onCloseNotification]); return ( - + + + + + + {transactionDetailsIsVisible && ( - + @@ -260,16 +271,14 @@ function TransactionNotification(props) { /> - - + )} - - - - + ); } diff --git a/app/components/UI/OnboardingProgress/index.js b/app/components/UI/OnboardingProgress/index.js index 972e81705dc..81b36a9bd3b 100644 --- a/app/components/UI/OnboardingProgress/index.js +++ b/app/components/UI/OnboardingProgress/index.js @@ -1,7 +1,8 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import StepIndicator from 'react-native-step-indicator'; +import { ThemeContext, mockTheme } from '../../../util/theme'; const strokeWidth = 2; @@ -21,38 +22,39 @@ export default class OnboardingProgress extends PureComponent { steps: PropTypes.array.isRequired, }; - customStyles = { - stepIndicatorSize: 20, - currentStepIndicatorSize: 20, - separatorStrokeWidth: strokeWidth, - separatorFinishedColor: colors.blue, - separatorUnFinishedColor: colors.grey100, - currentStepStrokeWidth: strokeWidth, - stepStrokeCurrentColor: colors.blue, - stepStrokeWidth: strokeWidth, - stepStrokeFinishedColor: colors.blue, - stepStrokeUnFinishedColor: colors.grey100, - stepIndicatorFinishedColor: colors.blue, - stepIndicatorUnFinishedColor: colors.white, - stepIndicatorCurrentColor: colors.white, - stepIndicatorLabelFontSize: 9, - currentStepIndicatorLabelFontSize: 9, - stepIndicatorLabelCurrentColor: colors.blue, - stepIndicatorLabelFinishedColor: colors.white, - stepIndicatorLabelUnFinishedColor: colors.grey100, - labelColor: colors.grey100, - stepIndicatorLabelFontFamily: fontStyles.normal.fontFamily, - labelFontFamily: fontStyles.normal.fontFamily, - labelSize: 10, - currentStepLabelColor: colors.blue, - finishedStepLabelColor: colors.blue, - }; - render() { const { currentStep, steps } = this.props; + const colors = this.context.colors || mockTheme.colors; + const customStyles = { + stepIndicatorSize: 20, + currentStepIndicatorSize: 20, + separatorStrokeWidth: strokeWidth, + separatorFinishedColor: colors.primary.default, + separatorUnFinishedColor: colors.text.muted, + currentStepStrokeWidth: strokeWidth, + stepStrokeCurrentColor: colors.primary.default, + stepStrokeWidth: strokeWidth, + stepStrokeFinishedColor: colors.primary.default, + stepStrokeUnFinishedColor: colors.text.muted, + stepIndicatorFinishedColor: colors.primary.default, + stepIndicatorUnFinishedColor: colors.background.default, + stepIndicatorCurrentColor: colors.background.default, + stepIndicatorLabelFontSize: 9, + currentStepIndicatorLabelFontSize: 9, + stepIndicatorLabelCurrentColor: colors.text.default, + stepIndicatorLabelFinishedColor: colors.primary.inverse, + stepIndicatorLabelUnFinishedColor: colors.text.muted, + labelColor: colors.text.muted, + stepIndicatorLabelFontFamily: fontStyles.normal.fontFamily, + labelFontFamily: fontStyles.normal.fontFamily, + labelSize: 10, + currentStepLabelColor: colors.primary.default, + finishedStepLabelColor: colors.primary.default, + }; + return ( + StyleSheet.create({ + flex: { + flex: 1, + backgroundColor: colors.background.default, + }, + wrapper: { + top: 0, + bottom: 0, + left: 0, + right: 0, + position: 'absolute', + borderTopWidth: 0, + flex: 1, + width: null, + height: null, + }, + }); const images = { - a: require('../../../images/welcome-bg1.jpg'), // eslint-disable-line - b: require('../../../images/welcome-bg2.jpg'), // eslint-disable-line - c: require('../../../images/welcome-bg3.jpg'), // eslint-disable-line - d: require('../../../images/welcome-bg4.jpg'), // eslint-disable-line + a: require('../../../images/welcome-bg1.png'), // eslint-disable-line + b: require('../../../images/welcome-bg2.png'), // eslint-disable-line + c: require('../../../images/welcome-bg3.png'), // eslint-disable-line + d: require('../../../images/welcome-bg4.png'), // eslint-disable-line carousel: null, }; -const OnboardingScreenWithBg = (props) => ( - - - {props.children} - - -); +const OnboardingScreenWithBg = (props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + + {props.children} + + + ); +}; OnboardingScreenWithBg.propTypes = { /** diff --git a/app/components/UI/OnboardingWizard/Coachmark/__snapshots__/index.test.tsx.snap b/app/components/UI/OnboardingWizard/Coachmark/__snapshots__/index.test.tsx.snap index 6e98275f674..03e63b21545 100644 --- a/app/components/UI/OnboardingWizard/Coachmark/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/OnboardingWizard/Coachmark/__snapshots__/index.test.tsx.snap @@ -25,7 +25,7 @@ exports[`Coachmark should render correctly 1`] = ` style={ Object { "backgroundColor": "transparent", - "borderBottomColor": "#037dd6", + "borderBottomColor": "#037DD6", "borderBottomWidth": 12, "borderLeftColor": "transparent", "borderLeftWidth": 15, @@ -43,7 +43,7 @@ exports[`Coachmark should render correctly 1`] = ` style={ Array [ Object { - "backgroundColor": "#037dd6", + "backgroundColor": "#037DD6", "borderRadius": 8, "padding": 18, }, @@ -51,18 +51,12 @@ exports[`Coachmark should render correctly 1`] = ` ] } > - + Back @@ -122,7 +116,7 @@ exports[`Coachmark should render correctly 1`] = ` style={ Array [ Object { - "backgroundColor": "#FFFFFF", + "backgroundColor": "#FCFCFC", "borderRadius": 3, "height": 6, "margin": 3, @@ -140,7 +134,7 @@ exports[`Coachmark should render correctly 1`] = ` style={ Array [ Object { - "backgroundColor": "#FFFFFF", + "backgroundColor": "#FCFCFC", "borderRadius": 3, "height": 6, "margin": 3, @@ -156,7 +150,7 @@ exports[`Coachmark should render correctly 1`] = ` style={ Array [ Object { - "backgroundColor": "#FFFFFF", + "backgroundColor": "#FCFCFC", "borderRadius": 3, "height": 6, "margin": 3, @@ -172,7 +166,7 @@ exports[`Coachmark should render correctly 1`] = ` style={ Array [ Object { - "backgroundColor": "#FFFFFF", + "backgroundColor": "#FCFCFC", "borderRadius": 3, "height": 6, "margin": 3, @@ -188,7 +182,7 @@ exports[`Coachmark should render correctly 1`] = ` style={ Array [ Object { - "backgroundColor": "#FFFFFF", + "backgroundColor": "#FCFCFC", "borderRadius": 3, "height": 6, "margin": 3, @@ -224,7 +218,7 @@ exports[`Coachmark should render correctly 1`] = ` "opacity": 0.6, } } - type="normal" + type="inverse" > Got it! diff --git a/app/components/UI/OnboardingWizard/Coachmark/index.js b/app/components/UI/OnboardingWizard/Coachmark/index.js index f1880168fb6..472077636c0 100644 --- a/app/components/UI/OnboardingWizard/Coachmark/index.js +++ b/app/components/UI/OnboardingWizard/Coachmark/index.js @@ -1,115 +1,117 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { Animated, View, Text, StyleSheet } from 'react-native'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles, colors as importedColors } from '../../../../styles/common'; import StyledButton from '../../StyledButton'; import { strings } from '../../../../../locales/i18n'; import onboardingStyles from './../styles'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - coachmark: { - backgroundColor: colors.blue, - borderRadius: 8, - padding: 18, - }, - progress: { - flexDirection: 'row', - justifyContent: 'space-between', - }, - actions: { - flexDirection: 'column', - }, - actionButton: { - width: '100%', - marginTop: 10, - }, - title: { - ...fontStyles.bold, - color: colors.white, - fontSize: 18, - alignSelf: 'center', - }, - triangle: { - width: 0, - height: 0, - backgroundColor: colors.transparent, - borderStyle: 'solid', - borderLeftWidth: 15, - borderRightWidth: 15, - borderBottomWidth: 12, - borderLeftColor: colors.transparent, - borderRightColor: colors.transparent, - borderBottomColor: colors.blue, - position: 'absolute', - }, - triangleDown: { - width: 0, - height: 0, - backgroundColor: colors.transparent, - borderStyle: 'solid', - borderLeftWidth: 15, - borderRightWidth: 15, - borderTopWidth: 12, - borderLeftColor: colors.transparent, - borderRightColor: colors.transparent, - borderTopColor: colors.blue, - position: 'absolute', - }, - progressButton: { - width: 75, - height: 45, - padding: 5, - }, - leftProgessButton: { - left: 0, - }, - rightProgessButton: { - right: 0, - }, - topCenter: { - marginBottom: 10, - bottom: -2, - alignItems: 'center', - }, - topLeft: { - marginBottom: 10, - bottom: -2, - alignItems: 'flex-start', - marginLeft: 30, - }, - topLeftCorner: { - marginBottom: 10, - bottom: -2, - alignItems: 'flex-start', - marginLeft: 12, - }, - bottomCenter: { - marginBottom: 10, - top: -2, - alignItems: 'center', - }, - bottomLeft: { - marginBottom: 10, - top: -2, - alignItems: 'flex-start', - marginLeft: 30, - }, - circle: { - width: 6, - height: 6, - borderRadius: 6 / 2, - backgroundColor: colors.white, - opacity: 0.4, - margin: 3, - }, - solidCircle: { - opacity: 1, - }, - progessContainer: { - flexDirection: 'row', - alignSelf: 'center', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + coachmark: { + backgroundColor: colors.primary.default, + borderRadius: 8, + padding: 18, + }, + progress: { + flexDirection: 'row', + justifyContent: 'space-between', + }, + actions: { + flexDirection: 'column', + }, + actionButton: { + width: '100%', + marginTop: 10, + }, + title: { + ...fontStyles.bold, + color: colors.primary.inverse, + fontSize: 18, + alignSelf: 'center', + }, + triangle: { + width: 0, + height: 0, + backgroundColor: importedColors.transparent, + borderStyle: 'solid', + borderLeftWidth: 15, + borderRightWidth: 15, + borderBottomWidth: 12, + borderLeftColor: importedColors.transparent, + borderRightColor: importedColors.transparent, + borderBottomColor: colors.primary.default, + position: 'absolute', + }, + triangleDown: { + width: 0, + height: 0, + backgroundColor: importedColors.transparent, + borderStyle: 'solid', + borderLeftWidth: 15, + borderRightWidth: 15, + borderTopWidth: 12, + borderLeftColor: importedColors.transparent, + borderRightColor: importedColors.transparent, + borderTopColor: colors.primary.default, + position: 'absolute', + }, + progressButton: { + width: 75, + height: 45, + padding: 5, + }, + leftProgessButton: { + left: 0, + }, + rightProgessButton: { + right: 0, + }, + topCenter: { + marginBottom: 10, + bottom: -2, + alignItems: 'center', + }, + topLeft: { + marginBottom: 10, + bottom: -2, + alignItems: 'flex-start', + marginLeft: 30, + }, + topLeftCorner: { + marginBottom: 10, + bottom: -2, + alignItems: 'flex-start', + marginLeft: 12, + }, + bottomCenter: { + marginBottom: 10, + top: -2, + alignItems: 'center', + }, + bottomLeft: { + marginBottom: 10, + top: -2, + alignItems: 'flex-start', + marginLeft: 30, + }, + circle: { + width: 6, + height: 6, + borderRadius: 6 / 2, + backgroundColor: colors.primary.inverse, + opacity: 0.4, + margin: 3, + }, + solidCircle: { + opacity: 1, + }, + progessContainer: { + flexDirection: 'row', + alignSelf: 'center', + }, + }); export default class Coachmark extends PureComponent { static propTypes = { @@ -195,6 +197,11 @@ export default class Coachmark extends PureComponent { onBack && onBack(); }; + getStyles = () => { + const colors = this.context.colors || mockTheme.colors; + return createStyles(colors); + }; + /** * Gets top indicator style according to 'topIndicatorPosition' * @@ -202,6 +209,8 @@ export default class Coachmark extends PureComponent { * @returns {Object} - Corresponding style object */ getIndicatorStyle = (topIndicatorPosition) => { + const styles = this.getStyles(); + const positions = { topCenter: styles.topCenter, topLeft: styles.topLeft, @@ -218,6 +227,8 @@ export default class Coachmark extends PureComponent { * @returns {Object} - Corresponding style object */ getBotttomIndicatorStyle = (bottomIndicatorPosition) => { + const styles = this.getStyles(); + const positions = { bottomCenter: styles.bottomCenter, bottomLeft: styles.bottomLeft, @@ -233,11 +244,13 @@ export default class Coachmark extends PureComponent { */ renderProgressButtons = () => { const { currentStep } = this.props; + const styles = this.getStyles(); + return ( {strings('onboarding_wizard.coachmark.progress_back')} @@ -250,7 +263,7 @@ export default class Coachmark extends PureComponent { {strings('onboarding_wizard.coachmark.progress_next')} @@ -264,31 +277,37 @@ export default class Coachmark extends PureComponent { * * @returns {Object} - Corresponding view object */ - renderActionButtons = () => ( - - - {strings('onboarding_wizard.coachmark.action_back')} - - - {strings('onboarding_wizard.coachmark.action_next')} - - - ); + renderActionButtons = () => { + const styles = this.getStyles(); + + return ( + + + {strings('onboarding_wizard.coachmark.action_back')} + + + {strings('onboarding_wizard.coachmark.action_next')} + + + ); + }; render() { const { content, title, topIndicatorPosition, bottomIndicatorPosition, action } = this.props; const style = this.props.style || {}; const coachmarkStyle = this.props.coachmarkStyle || {}; + const styles = this.getStyles(); + return ( {topIndicatorPosition && ( @@ -312,3 +331,5 @@ export default class Coachmark extends PureComponent { ); } } + +Coachmark.contextType = ThemeContext; diff --git a/app/components/UI/OnboardingWizard/Step1/index.js b/app/components/UI/OnboardingWizard/Step1/index.js index 74b8f84e1a0..b760f4984a1 100644 --- a/app/components/UI/OnboardingWizard/Step1/index.js +++ b/app/components/UI/OnboardingWizard/Step1/index.js @@ -9,6 +9,7 @@ import { strings } from '../../../../../locales/i18n'; import onboardingStyles from './../styles'; import AnalyticsV2 from '../../../../util/analyticsV2'; import { ONBOARDING_WIZARD_STEP_DESCRIPTION } from '../../../../util/analytics'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; const styles = StyleSheet.create({ main: { @@ -63,12 +64,17 @@ class Step1 extends PureComponent { /** * Returns content for this step */ - content = () => ( - - {strings('onboarding_wizard.step1.content1')} - {strings('onboarding_wizard.step1.content2')} - - ); + content = () => { + const colors = this.context.colors || mockTheme.colors; + const dynamicOnboardingStyles = onboardingStyles(colors); + + return ( + + {strings('onboarding_wizard.step1.content1')} + {strings('onboarding_wizard.step1.content2')} + + ); + }; render() { return ( @@ -92,4 +98,6 @@ const mapDispatchToProps = (dispatch) => ({ setOnboardingWizardStep: (step) => dispatch(setOnboardingWizardStep(step)), }); +Step1.contextType = ThemeContext; + export default connect(null, mapDispatchToProps)(Step1); diff --git a/app/components/UI/OnboardingWizard/Step2/index.js b/app/components/UI/OnboardingWizard/Step2/index.js index 7732e3177bd..f9abeebded9 100644 --- a/app/components/UI/OnboardingWizard/Step2/index.js +++ b/app/components/UI/OnboardingWizard/Step2/index.js @@ -8,6 +8,7 @@ import { strings } from '../../../../../locales/i18n'; import onboardingStyles from './../styles'; import AnalyticsV2 from '../../../../util/analyticsV2'; import { ONBOARDING_WIZARD_STEP_DESCRIPTION } from '../../../../util/analytics'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; const INDICATOR_HEIGHT = 10; const styles = StyleSheet.create({ @@ -77,19 +78,30 @@ class Step2 extends PureComponent { }); }; + getOnboardingStyles = () => { + const colors = this.context.colors || mockTheme.colors; + return onboardingStyles(colors); + }; + /** * Returns content for this step */ - content = () => ( - - - {strings('onboarding_wizard.step2.content1')} - - {strings('onboarding_wizard.step2.content2')} - - ); + content = () => { + const dynamicOnboardingStyles = this.getOnboardingStyles(); + + return ( + + + {strings('onboarding_wizard.step2.content1')} + + {strings('onboarding_wizard.step2.content2')} + + ); + }; render() { + const dynamicOnboardingStyles = this.getOnboardingStyles(); + return ( @@ -98,7 +110,7 @@ class Step2 extends PureComponent { content={this.content()} onNext={this.onNext} onBack={this.onBack} - style={onboardingStyles.coachmark} + style={dynamicOnboardingStyles.coachmark} topIndicatorPosition={'topCenter'} currentStep={1} /> @@ -112,4 +124,6 @@ const mapDispatchToProps = (dispatch) => ({ setOnboardingWizardStep: (step) => dispatch(setOnboardingWizardStep(step)), }); +Step2.contextType = ThemeContext; + export default connect(null, mapDispatchToProps)(Step2); diff --git a/app/components/UI/OnboardingWizard/Step3/index.js b/app/components/UI/OnboardingWizard/Step3/index.js index fe3f4ffe777..6ee2e16e1f8 100644 --- a/app/components/UI/OnboardingWizard/Step3/index.js +++ b/app/components/UI/OnboardingWizard/Step3/index.js @@ -4,13 +4,14 @@ import { connect } from 'react-redux'; import { Text, View, StyleSheet, Dimensions } from 'react-native'; import Coachmark from '../Coachmark'; import setOnboardingWizardStep from '../../../../actions/wizard'; -import { colors, fontStyles } from '../../../../styles/common'; +import { colors as importedColors, fontStyles } from '../../../../styles/common'; import AccountOverview from '../../AccountOverview'; import { strings } from '../../../../../locales/i18n'; import onboardingStyles from './../styles'; import Device from '../../../../util/device'; import AnalyticsV2 from '../../../../util/analyticsV2'; import { ONBOARDING_WIZARD_STEP_DESCRIPTION } from '../../../../util/analytics'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; const styles = StyleSheet.create({ main: { @@ -26,7 +27,7 @@ const styles = StyleSheet.create({ flex: 1, width: Dimensions.get('window').width, alignItems: 'center', - backgroundColor: colors.transparent, + backgroundColor: importedColors.transparent, }, }); @@ -127,26 +128,37 @@ class Step3 extends PureComponent { }); }; + getOnboardingStyles = () => { + const colors = this.context.colors || mockTheme.colors; + return onboardingStyles(colors); + }; + /** * Returns content for this step */ - content = () => ( - - - {strings('onboarding_wizard.step3.content1')} - - - {strings('onboarding_wizard.step3.content2')} - {strings('onboarding_wizard.step3.content3')} - - - ); + content = () => { + const dynamicOnboardingStyles = this.getOnboardingStyles(); + + return ( + + + {strings('onboarding_wizard.step3.content1')} + + + {strings('onboarding_wizard.step3.content2')} + {strings('onboarding_wizard.step3.content3')} + + + ); + }; render() { const { selectedAddress, identities, accounts, currentCurrency } = this.props; const account = { address: selectedAddress, ...identities[selectedAddress], ...accounts[selectedAddress] }; const { coachmarkTopReady, viewTopReady } = this.state; + const dynamicOnboardingStyles = this.getOnboardingStyles(); if (!coachmarkTopReady || !viewTopReady) return null; + return ( @@ -158,7 +170,7 @@ class Step3 extends PureComponent { content={this.content()} onNext={this.onNext} onBack={this.onBack} - style={onboardingStyles.coachmark} + style={dynamicOnboardingStyles.coachmark} topIndicatorPosition={'topCenter'} currentStep={2} /> @@ -179,4 +191,6 @@ const mapDispatchToProps = (dispatch) => ({ setOnboardingWizardStep: (step) => dispatch(setOnboardingWizardStep(step)), }); +Step3.contextType = ThemeContext; + export default connect(mapStateToProps, mapDispatchToProps)(Step3); diff --git a/app/components/UI/OnboardingWizard/Step4/index.js b/app/components/UI/OnboardingWizard/Step4/index.js index a201a6ee62d..6ebe43c63be 100644 --- a/app/components/UI/OnboardingWizard/Step4/index.js +++ b/app/components/UI/OnboardingWizard/Step4/index.js @@ -6,10 +6,11 @@ import Coachmark from '../Coachmark'; import setOnboardingWizardStep from '../../../../actions/wizard'; import { strings } from '../../../../../locales/i18n'; import onboardingStyles from './../styles'; -import { fontStyles, colors } from '../../../../styles/common'; +import { fontStyles, colors as importedColors } from '../../../../styles/common'; import AnalyticsV2 from '../../../../util/analyticsV2'; import { ONBOARDING_WIZARD_STEP_DESCRIPTION } from '../../../../util/analytics'; import { DrawerContext } from '../../../../components/Nav/Main/MainNavigator'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; const styles = StyleSheet.create({ main: { @@ -22,7 +23,7 @@ const styles = StyleSheet.create({ right: 0, }, hamburger: { - backgroundColor: colors.transparent, + backgroundColor: importedColors.transparent, height: 50, width: 50, }, @@ -35,6 +36,8 @@ const Step4 = (props) => { const { coachmarkRef, setOnboardingWizardStep } = props; const [viewTop, setViewTop] = useState(0); const { drawerRef } = useContext(DrawerContext); + const { colors } = useAppThemeFromContext() || mockTheme; + const dynamicOnboardingStyles = onboardingStyles(colors); /** * Sets coachmark top position getting AccountOverview component ref from Wallet @@ -82,12 +85,12 @@ const Step4 = (props) => { * Returns content for this step */ const content = () => ( - - + + {strings('onboarding_wizard.step4.content1')} {strings('onboarding_wizard.step4.content2')} - {strings('onboarding_wizard.step4.content3')} + {strings('onboarding_wizard.step4.content3')} ); @@ -108,7 +111,7 @@ const Step4 = (props) => { content={content()} onNext={onNext} onBack={onBack} - style={onboardingStyles.coachmarkLeft} + style={dynamicOnboardingStyles.coachmarkLeft} topIndicatorPosition={'topLeftCorner'} currentStep={3} /> diff --git a/app/components/UI/OnboardingWizard/Step5/index.js b/app/components/UI/OnboardingWizard/Step5/index.js index 48cc7cddaed..b081d8e2642 100644 --- a/app/components/UI/OnboardingWizard/Step5/index.js +++ b/app/components/UI/OnboardingWizard/Step5/index.js @@ -2,7 +2,7 @@ import React, { useContext, useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { View, Text, StyleSheet, Dimensions } from 'react-native'; -import { colors } from '../../../../styles/common'; +import { colors as importedColors } from '../../../../styles/common'; import Coachmark from '../Coachmark'; import setOnboardingWizardStep from '../../../../actions/wizard'; import { strings } from '../../../../../locales/i18n'; @@ -11,6 +11,7 @@ import Device from '../../../../util/device'; import AnalyticsV2 from '../../../../util/analyticsV2'; import { ONBOARDING_WIZARD_STEP_DESCRIPTION } from '../../../../util/analytics'; import { DrawerContext } from '../../../../components/Nav/Main/MainNavigator'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; const INDICATOR_HEIGHT = 10; const DRAWER_WIDTH = 315; @@ -18,7 +19,7 @@ const WIDTH = Dimensions.get('window').width; const styles = StyleSheet.create({ main: { flex: 1, - backgroundColor: colors.transparent, + backgroundColor: importedColors.transparent, }, some: { marginLeft: 24, @@ -37,6 +38,8 @@ const Step5 = (props) => { const [coachmarkTop, setCoachmarkTop] = useState(0); const [coachmarkBottom, setCoachmarkBottom] = useState(0); const { drawerRef } = useContext(DrawerContext); + const { colors } = useAppThemeFromContext() || mockTheme; + const dynamicOnboardingStyles = onboardingStyles(colors); /** * If component ref defined, calculate its position and position coachmark accordingly @@ -97,8 +100,8 @@ const Step5 = (props) => { * Returns content for this step */ const content = () => ( - - + + {strings('onboarding_wizard.step5.content1')} diff --git a/app/components/UI/OnboardingWizard/Step6/index.js b/app/components/UI/OnboardingWizard/Step6/index.js index 5e557864d0d..76f0f482d76 100644 --- a/app/components/UI/OnboardingWizard/Step6/index.js +++ b/app/components/UI/OnboardingWizard/Step6/index.js @@ -10,6 +10,7 @@ import Device from '../../../../util/device'; import AnalyticsV2 from '../../../../util/analyticsV2'; import { ONBOARDING_WIZARD_STEP_DESCRIPTION } from '../../../../util/analytics'; import { DrawerContext } from '../../../../components/Nav/Main/MainNavigator'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; const styles = StyleSheet.create({ main: { @@ -28,6 +29,8 @@ const Step6 = (props) => { const [ready, setReady] = useState(false); const [coachmarkTop, setCoachmarkTop] = useState(0); const { drawerRef } = useContext(DrawerContext); + const { colors } = useAppThemeFromContext() || mockTheme; + const dynamicOnboardingStyles = onboardingStyles(colors); /** * If component ref defined, calculate its position and position coachmark accordingly @@ -68,8 +71,8 @@ const Step6 = (props) => { * Returns content for this step */ const content = () => ( - - + + {strings('onboarding_wizard.step6.content')} @@ -85,7 +88,7 @@ const Step6 = (props) => { content={content()} onNext={triggerOnClose} onBack={onBack} - style={onboardingStyles.coachmark} + style={dynamicOnboardingStyles.coachmark} topIndicatorPosition={'topCenter'} onClose={onClose} currentStep={5} diff --git a/app/components/UI/OnboardingWizard/index.js b/app/components/UI/OnboardingWizard/index.js index 959f0ce8560..d1d5ec0a932 100644 --- a/app/components/UI/OnboardingWizard/index.js +++ b/app/components/UI/OnboardingWizard/index.js @@ -1,7 +1,7 @@ import React, { useContext } from 'react'; import PropTypes from 'prop-types'; import { TouchableOpacity, View, StyleSheet, Text, Dimensions, InteractionManager } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; +import { colors as importedColors, fontStyles } from '../../../styles/common'; import { connect } from 'react-redux'; import Step1 from './Step1'; import Step2 from './Step2'; @@ -19,58 +19,59 @@ import { ONBOARDING_WIZARD_STEP_DESCRIPTION } from '../../../util/analytics'; import { ONBOARDING_WIZARD, EXPLORED } from '../../../constants/storage'; import AnalyticsV2 from '../../../util/analyticsV2'; import { DrawerContext } from '../../../components/Nav/Main/MainNavigator'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; const MIN_HEIGHT = Dimensions.get('window').height; -const styles = StyleSheet.create({ - root: { - top: 0, - bottom: 0, - left: 0, - right: 0, - flex: 1, - margin: 0, - position: 'absolute', - backgroundColor: colors.transparent, - }, - main: { - flex: 1, - backgroundColor: colors.transparent, - }, - smallSkipWrapper: { - alignItems: 'center', - alignSelf: 'center', - bottom: Device.isIos() ? 30 : 35, - }, - largeSkipWrapper: { - alignItems: 'center', - alignSelf: 'center', - bottom: Device.isIos() && Device.isIphoneX() ? 98 : 66, - }, - skip: { - height: 30, - borderRadius: 30, - backgroundColor: colors.white, - alignItems: 'center', - }, - androidElevated: { - width: 120, - borderRadius: 30, - }, - iosTouchable: { - width: 120, - }, - skipTextWrapper: { - flex: 1, - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - }, - skipText: { - ...fontStyles.normal, - fontSize: 12, - color: colors.blue, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + root: { + top: 0, + bottom: 0, + left: 0, + right: 0, + flex: 1, + margin: 0, + position: 'absolute', + backgroundColor: importedColors.transparent, + }, + main: { + flex: 1, + backgroundColor: importedColors.transparent, + }, + smallSkipWrapper: { + alignItems: 'center', + alignSelf: 'center', + bottom: Device.isIos() ? 30 : 35, + }, + largeSkipWrapper: { + alignItems: 'center', + alignSelf: 'center', + bottom: Device.isIos() && Device.isIphoneX() ? 98 : 66, + }, + skipButtonContainer: { + height: 30, + width: 120, + borderRadius: 15, + backgroundColor: colors.background.default, + }, + skipButton: { + backgroundColor: colors.background.default, + alignItems: 'center', + justifyContent: 'center', + }, + androidElevated: { + width: 120, + borderRadius: 30, + }, + iosTouchable: { + width: 120, + }, + skipText: { + ...fontStyles.normal, + fontSize: 12, + color: colors.primary.default, + }, + }); const OnboardingWizard = (props) => { const { @@ -80,6 +81,8 @@ const OnboardingWizard = (props) => { coachmarkRef, } = props; const { drawerRef } = useContext(DrawerContext); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); /** * Close onboarding wizard setting step to 0 and closing drawer @@ -140,16 +143,14 @@ const OnboardingWizard = (props) => { elevation={10} style={[ Device.isSmallDevice() ? styles.smallSkipWrapper : styles.largeSkipWrapper, - Device.isIos() ? {} : styles.androidElevated, + styles.skipButtonContainer, ]} > - - {strings('onboarding_wizard.skip_tutorial')} - + {strings('onboarding_wizard.skip_tutorial')} )} diff --git a/app/components/UI/OnboardingWizard/styles.js b/app/components/UI/OnboardingWizard/styles.js index 79a0d1f8e55..f5f13dae0d5 100644 --- a/app/components/UI/OnboardingWizard/styles.js +++ b/app/components/UI/OnboardingWizard/styles.js @@ -1,34 +1,35 @@ import { StyleSheet } from 'react-native'; -import { fontStyles, colors } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import Device from '../../../util/device'; const SMALL_DEVICE = Device.isSmallDevice(); -export default StyleSheet.create({ - container: { - flex: 1, - }, - welcome: { - fontSize: 20, - }, - content: { - ...fontStyles.normal, - color: colors.white, - fontSize: 14, - textAlign: 'center', - marginBottom: SMALL_DEVICE ? 5 : 20, - }, - titleContainer: { - marginBottom: SMALL_DEVICE ? -10 : 0, - }, - contentContainer: { - marginTop: 20, - }, - coachmark: { - marginHorizontal: SMALL_DEVICE ? 25 : 45, - }, - coachmarkLeft: { - marginLeft: SMALL_DEVICE ? 5 : 10, - marginRight: SMALL_DEVICE ? 45 : 85, - }, -}); +export default (colors) => + StyleSheet.create({ + container: { + flex: 1, + }, + welcome: { + fontSize: 20, + }, + content: { + ...fontStyles.normal, + color: colors.primary.inverse, + fontSize: 14, + textAlign: 'center', + marginBottom: SMALL_DEVICE ? 5 : 20, + }, + titleContainer: { + marginBottom: SMALL_DEVICE ? -10 : 0, + }, + contentContainer: { + marginTop: 20, + }, + coachmark: { + marginHorizontal: SMALL_DEVICE ? 25 : 45, + }, + coachmarkLeft: { + marginLeft: SMALL_DEVICE ? 5 : 10, + marginRight: SMALL_DEVICE ? 45 : 85, + }, + }); diff --git a/app/components/UI/OptinMetrics/index.js b/app/components/UI/OptinMetrics/index.js index 181c88183fa..c569e694657 100644 --- a/app/components/UI/OptinMetrics/index.js +++ b/app/components/UI/OptinMetrics/index.js @@ -11,7 +11,7 @@ import { InteractionManager, } from 'react-native'; import PropTypes from 'prop-types'; -import { baseStyles, fontStyles, colors } from '../../../styles/common'; +import { baseStyles, fontStyles } from '../../../styles/common'; import Entypo from 'react-native-vector-icons/Entypo'; import { getOptinMetricsNavbarOptions } from '../Navbar'; import { strings } from '../../../../locales/i18n'; @@ -24,79 +24,79 @@ import { ONBOARDING_WIZARD, METRICS_OPT_IN, DENIED, AGREED } from '../../../cons import AppConstants from '../../../core/AppConstants'; import AnalyticsV2 from '../../../util/analyticsV2'; import DefaultPreference from 'react-native-default-preference'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - root: { - ...baseStyles.flexGrow, - backgroundColor: colors.white, - }, - checkIcon: { - color: colors.green500, - }, - crossIcon: { - color: colors.red, - }, - icon: { - marginRight: 5, - }, - action: { - flex: 0, - flexDirection: 'row', - paddingVertical: 10, - alignItems: 'center', - }, - title: { - ...fontStyles.bold, - color: colors.black, - fontSize: 22, - }, - description: { - ...fontStyles.normal, - color: colors.black, - flex: 1, - }, - content: { - ...fontStyles.normal, - fontSize: 14, - color: colors.black, - paddingVertical: 10, - }, - wrapper: { - marginHorizontal: 20, - }, - privacyPolicy: { - ...fontStyles.normal, - fontSize: 14, - color: colors.grey400, - marginTop: 10, - }, - link: { - textDecorationLine: 'underline', - }, - actionContainer: { - marginTop: 10, - flex: 0, - flexDirection: 'row', - padding: 16, - bottom: 0, - }, - button: { - flex: 1, - }, - cancel: { - marginRight: 8, - }, - confirm: { - marginLeft: 8, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + root: { + ...baseStyles.flexGrow, + backgroundColor: colors.background.default, + }, + checkIcon: { + color: colors.success.default, + }, + crossIcon: { + color: colors.error.default, + }, + icon: { + marginRight: 5, + }, + action: { + flex: 0, + flexDirection: 'row', + paddingVertical: 10, + alignItems: 'center', + }, + title: { + ...fontStyles.bold, + color: colors.text.default, + fontSize: 22, + }, + description: { + ...fontStyles.normal, + color: colors.text.default, + flex: 1, + }, + content: { + ...fontStyles.normal, + fontSize: 14, + color: colors.text.default, + paddingVertical: 10, + }, + wrapper: { + marginHorizontal: 20, + }, + privacyPolicy: { + ...fontStyles.normal, + fontSize: 14, + color: colors.text.muted, + marginTop: 10, + }, + link: { + textDecorationLine: 'underline', + }, + actionContainer: { + marginTop: 10, + flex: 0, + flexDirection: 'row', + padding: 16, + bottom: 0, + }, + button: { + flex: 1, + }, + cancel: { + marginRight: 8, + }, + confirm: { + marginLeft: 8, + }, + }); /** * View that is displayed in the flow to agree to metrics */ class OptinMetrics extends PureComponent { - static navigationOptions = () => getOptinMetricsNavbarOptions(); - static propTypes = { /** /* navigation object required to push and pop other views @@ -125,11 +125,22 @@ class OptinMetrics extends PureComponent { description: strings(`privacy_policy.action_description_${value}`), })); + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions(getOptinMetricsNavbarOptions(colors)); + }; + componentDidMount() { + this.updateNavBar(); Analytics.enable(); BackHandler.addEventListener('hardwareBackPress', this.handleBackPress); } + componentDidUpdate = () => { + this.updateNavBar(); + }; + componentWillUnmount() { BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress); } @@ -166,16 +177,21 @@ class OptinMetrics extends PureComponent { * @param {object} - Object containing action and description to be rendered * @param {number} i - Index key */ - renderAction = ({ action, description }, i) => ( - - {action === 0 ? ( - - ) : ( - - )} - {description} - - ); + renderAction = ({ action, description }, i) => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + {action === 0 ? ( + + ) : ( + + )} + {description} + + ); + }; /** * Track the event of opt in or opt out. @@ -243,17 +259,25 @@ class OptinMetrics extends PureComponent { * * @returns - Touchable opacity object to render with privacy policy information */ - renderPrivacyPolicy = () => ( - - - {strings('privacy_policy.description') + ' '} - {strings('privacy_policy.here')} - {strings('unit.point')} - - - ); + renderPrivacyPolicy = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + + {strings('privacy_policy.description') + ' '} + {strings('privacy_policy.here')} + {strings('unit.point')} + + + ); + }; render() { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -289,6 +313,8 @@ class OptinMetrics extends PureComponent { } } +OptinMetrics.contextType = ThemeContext; + const mapStateToProps = (state) => ({ events: state.onboarding.events, }); diff --git a/app/components/UI/Pager/__snapshots__/index.test.tsx.snap b/app/components/UI/Pager/__snapshots__/index.test.tsx.snap deleted file mode 100644 index 1dde9a6864e..00000000000 --- a/app/components/UI/Pager/__snapshots__/index.test.tsx.snap +++ /dev/null @@ -1,29 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Pager should render correctly 1`] = ` - - - -`; diff --git a/app/components/UI/Pager/index.js b/app/components/UI/Pager/index.js deleted file mode 100644 index c777689c1f0..00000000000 --- a/app/components/UI/Pager/index.js +++ /dev/null @@ -1,56 +0,0 @@ -import React, { PureComponent } from 'react'; -import { Dimensions, View, StyleSheet } from 'react-native'; -import PropTypes from 'prop-types'; -import { colors } from '../../../styles/common'; - -const defaultMargin = 4; - -const styles = StyleSheet.create({ - wrapper: { - width: Dimensions.get('window').width, - flexDirection: 'row', - }, - page: { - height: 7, - backgroundColor: colors.grey100, - marginRight: defaultMargin, - }, - selected: { - backgroundColor: colors.blue, - }, -}); - -export default class Pager extends PureComponent { - static propTypes = { - /** - * Number of pages - */ - pages: PropTypes.number, - /** - * The number of the selected page (1 index based) - */ - selected: PropTypes.number, - }; - - render() { - const width = Dimensions.get('window').width; - const pageWidth = (width - defaultMargin * (this.props.pages - 1)) / this.props.pages; - - return ( - - {Array(this.props.pages) - .fill(0) - .map((_, i) => ( - = i + 1 ? styles.selected : null, - ]} - /> - ))} - - ); - } -} diff --git a/app/components/UI/Pager/index.test.tsx b/app/components/UI/Pager/index.test.tsx deleted file mode 100644 index f3c77a411c3..00000000000 --- a/app/components/UI/Pager/index.test.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import { shallow } from 'enzyme'; -import Pager from './'; - -describe('Pager', () => { - it('should render correctly', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/app/components/UI/PaymentRequest/AssetList/index.tsx b/app/components/UI/PaymentRequest/AssetList/index.tsx index 4320e0ef0ae..b4dd1968901 100644 --- a/app/components/UI/PaymentRequest/AssetList/index.tsx +++ b/app/components/UI/PaymentRequest/AssetList/index.tsx @@ -2,50 +2,54 @@ import React, { useCallback } from 'react'; import { Text, View, StyleSheet } from 'react-native'; import StyledButton from '../../StyledButton'; import AssetIcon from '../../AssetIcon'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles } from '../../../../styles/common'; import Identicon from '../../Identicon'; import NetworkMainAssetLogo from '../../NetworkMainAssetLogo'; import { useSelector } from 'react-redux'; import { getTokenList } from '../../../../reducers/tokens'; import { toChecksumAddress } from 'ethereumjs-util'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - item: { - borderWidth: 1, - borderColor: colors.grey100, - padding: 8, - marginBottom: 8, - borderRadius: 8, - }, - assetListElement: { - flex: 1, - flexDirection: 'row', - alignItems: 'flex-start', - }, - text: { - ...(fontStyles.normal as any), - }, - textSymbol: { - ...fontStyles.normal, - paddingBottom: 4, - fontSize: 16, - } as any, - assetInfo: { - flex: 1, - flexDirection: 'column', - alignSelf: 'center', - padding: 4, - }, - assetIcon: { - flexDirection: 'column', - alignSelf: 'center', - marginRight: 12, - }, - ethLogo: { - width: 50, - height: 50, - }, -}); +const createStyles = (colors: any) => + StyleSheet.create({ + item: { + borderWidth: 1, + borderColor: colors.border.default, + padding: 8, + marginBottom: 8, + borderRadius: 8, + }, + assetListElement: { + flex: 1, + flexDirection: 'row', + alignItems: 'flex-start', + }, + text: { + ...(fontStyles.normal as any), + color: colors.text.default, + }, + textSymbol: { + ...fontStyles.normal, + paddingBottom: 4, + fontSize: 16, + color: colors.text.default, + } as any, + assetInfo: { + flex: 1, + flexDirection: 'column', + alignSelf: 'center', + padding: 4, + }, + assetIcon: { + flexDirection: 'column', + alignSelf: 'center', + marginRight: 12, + }, + ethLogo: { + width: 50, + height: 50, + }, + }); interface Props { /** @@ -64,6 +68,8 @@ interface Props { const AssetList = ({ searchResults, handleSelectAsset, emptyMessage }: Props) => { const tokenList = useSelector(getTokenList); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); /** * Render logo according to asset. Could be ETH, Identicon or contractMap logo @@ -83,7 +89,7 @@ const AssetList = ({ searchResults, handleSelectAsset, emptyMessage }: Props) => } return ; }, - [tokenList] + [tokenList, styles] ); return ( diff --git a/app/components/UI/PaymentRequest/index.js b/app/components/UI/PaymentRequest/index.js index 5e2579dbb98..2bca5999421 100644 --- a/app/components/UI/PaymentRequest/index.js +++ b/app/components/UI/PaymentRequest/index.js @@ -10,7 +10,7 @@ import { InteractionManager, } from 'react-native'; import { connect } from 'react-redux'; -import { colors, fontStyles, baseStyles } from '../../../styles/common'; +import { fontStyles, baseStyles } from '../../../styles/common'; import { getPaymentRequestOptionsTitle } from '../../UI/Navbar'; import FeatherIcon from 'react-native-vector-icons/Feather'; import Fuse from 'fuse.js'; @@ -41,150 +41,162 @@ import { getTicker } from '../../../util/transactions'; import { toLowerCaseEquals } from '../../../util/general'; import { getTokenListArray } from '../../../reducers/tokens'; import { utils as ethersUtils } from 'ethers'; +import { ThemeContext, mockTheme } from '../../../util/theme'; const KEYBOARD_OFFSET = 120; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - }, - contentWrapper: { - paddingTop: 24, - paddingHorizontal: 24, - }, - title: { - ...fontStyles.normal, - fontSize: 16, - }, - searchWrapper: { - marginVertical: 8, - }, - searchInput: { - marginHorizontal: 0, - paddingTop: Device.isAndroid() ? 12 : 2, - borderRadius: 8, - paddingHorizontal: 38, - fontSize: 16, - backgroundColor: colors.white, - height: 40, - width: '100%', - color: colors.grey400, - borderColor: colors.grey100, - borderWidth: 1, - ...fontStyles.normal, - }, - searchIcon: { - position: 'absolute', - textAlignVertical: 'center', - marginTop: Device.isAndroid() ? 9 : 10, - marginLeft: 12, - }, - input: { - ...fontStyles.normal, - backgroundColor: colors.white, - borderWidth: 0, - fontSize: 24, - paddingBottom: 0, - paddingRight: 0, - paddingLeft: 0, - paddingTop: 0, - }, - eth: { - ...fontStyles.normal, - fontSize: 24, - paddingTop: Device.isAndroid() ? 3 : 0, - paddingLeft: 10, - textTransform: 'uppercase', - }, - fiatValue: { - ...fontStyles.normal, - fontSize: 18, - }, - split: { - flex: 1, - flexDirection: 'row', - }, - ethContainer: { - flex: 1, - flexDirection: 'row', - paddingLeft: 6, - paddingRight: 10, - }, - container: { - flex: 1, - flexDirection: 'row', - paddingRight: 10, - paddingVertical: 10, - paddingLeft: 14, - position: 'relative', - backgroundColor: colors.white, - borderColor: colors.grey100, - borderRadius: 4, - borderWidth: 1, - }, - amounts: { - maxWidth: '70%', - }, - switchContainer: { - flex: 1, - flexDirection: 'column', - alignSelf: 'center', - right: 0, - }, - switchTouchable: { - flexDirection: 'row', - alignSelf: 'flex-end', - right: 0, - }, - enterAmountWrapper: { - flex: 1, - flexDirection: 'column', - }, - button: { - marginBottom: 16, - }, - buttonsWrapper: { - flex: 1, - flexDirection: 'row', - alignSelf: 'center', - }, - buttonsContainer: { - flex: 1, - flexDirection: 'column', - alignSelf: 'flex-end', - }, - scrollViewContainer: { - flexGrow: 1, - }, - errorWrapper: { - backgroundColor: colors.red000, - borderRadius: 4, - marginTop: 8, - }, - errorText: { - color: colors.fontError, - alignSelf: 'center', - }, - assetsWrapper: { - marginTop: 16, - }, - assetsTitle: { - ...fontStyles.normal, - fontSize: 16, - marginBottom: 8, - }, - secondaryAmount: { - flexDirection: 'row', - }, - currencySymbol: { - ...fontStyles.normal, - fontSize: 24, - }, - currencySymbolSmall: { - ...fontStyles.normal, - fontSize: 18, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + contentWrapper: { + paddingTop: 24, + paddingHorizontal: 24, + }, + title: { + ...fontStyles.normal, + fontSize: 16, + color: colors.text.default, + }, + amountWrapper: { + marginVertical: 8, + }, + searchWrapper: { + marginVertical: 8, + borderColor: colors.border.default, + borderWidth: 1, + borderRadius: 8, + flexDirection: 'row', + backgroundColor: colors.background.default, + }, + searchInput: { + paddingTop: Device.isAndroid() ? 12 : 0, + paddingLeft: 8, + fontSize: 16, + height: 40, + flex: 1, + color: colors.text.default, + ...fontStyles.normal, + }, + searchIcon: { + textAlignVertical: 'center', + marginLeft: 12, + alignSelf: 'center', + }, + clearButton: { paddingHorizontal: 12, justifyContent: 'center' }, + input: { + ...fontStyles.normal, + backgroundColor: colors.background.default, + borderWidth: 0, + fontSize: 24, + paddingBottom: 0, + paddingRight: 0, + paddingLeft: 0, + paddingTop: 0, + color: colors.text.default, + }, + eth: { + ...fontStyles.normal, + fontSize: 24, + paddingTop: Device.isAndroid() ? 3 : 0, + paddingLeft: 10, + textTransform: 'uppercase', + color: colors.text.default, + }, + fiatValue: { + ...fontStyles.normal, + fontSize: 18, + color: colors.text.default, + }, + split: { + flex: 1, + flexDirection: 'row', + }, + ethContainer: { + flex: 1, + flexDirection: 'row', + paddingLeft: 6, + paddingRight: 10, + }, + container: { + flex: 1, + flexDirection: 'row', + paddingRight: 10, + paddingVertical: 10, + paddingLeft: 14, + position: 'relative', + backgroundColor: colors.background.default, + borderColor: colors.border.default, + borderRadius: 4, + borderWidth: 1, + }, + amounts: { + maxWidth: '70%', + }, + switchContainer: { + flex: 1, + flexDirection: 'column', + alignSelf: 'center', + right: 0, + }, + switchTouchable: { + flexDirection: 'row', + alignSelf: 'flex-end', + right: 0, + }, + enterAmountWrapper: { + flex: 1, + flexDirection: 'column', + }, + button: { + marginBottom: 16, + }, + buttonsWrapper: { + flex: 1, + flexDirection: 'row', + alignSelf: 'center', + }, + buttonsContainer: { + flex: 1, + flexDirection: 'column', + alignSelf: 'flex-end', + }, + scrollViewContainer: { + flexGrow: 1, + }, + errorWrapper: { + backgroundColor: colors.error.muted, + borderRadius: 4, + marginTop: 8, + }, + errorText: { + color: colors.text.default, + alignSelf: 'center', + }, + assetsWrapper: { + marginTop: 16, + }, + assetsTitle: { + ...fontStyles.normal, + fontSize: 16, + marginBottom: 8, + color: colors.text.default, + }, + secondaryAmount: { + flexDirection: 'row', + }, + currencySymbol: { + ...fontStyles.normal, + fontSize: 24, + color: colors.text.default, + }, + currencySymbolSmall: { + ...fontStyles.normal, + fontSize: 18, + color: colors.text.default, + }, + }); const fuse = new Fuse([], { shouldSort: true, @@ -223,9 +235,6 @@ const MODE_AMOUNT = 'amount'; * View to generate a payment request link */ class PaymentRequest extends PureComponent { - static navigationOptions = ({ navigation, route }) => - getPaymentRequestOptionsTitle(strings('payment_request.title'), navigation, route); - static propTypes = { /** * Object that represents the navigator @@ -274,6 +283,7 @@ class PaymentRequest extends PureComponent { }; amountInput = React.createRef(); + searchInput = React.createRef(); state = { searchInputValue: '', @@ -289,11 +299,20 @@ class PaymentRequest extends PureComponent { inputWidth: { width: '99%' }, }; + updateNavBar = () => { + const { navigation, route } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + getPaymentRequestOptionsTitle(strings('payment_request.title'), navigation, route, colors) + ); + }; + /** * Set chainId, internalPrimaryCurrency and receiveAssets, if there is an asset set to this payment request chose it automatically, to state */ componentDidMount = () => { const { primaryCurrency, route, tokenList } = this.props; + this.updateNavBar(); const receiveAsset = route?.params?.receiveAsset; this.setState({ internalPrimaryCurrency: primaryCurrency, @@ -308,6 +327,7 @@ class PaymentRequest extends PureComponent { }; componentDidUpdate = () => { + this.updateNavBar(); InteractionManager.runAfterInteractions(() => { this.amountInput.current && this.amountInput.current.focus(); }); @@ -357,6 +377,12 @@ class PaymentRequest extends PureComponent { this.setState({ searchInputValue, results }); }; + /** Clear search input and focus */ + clearSearchInput = () => { + this.setState({ searchInputValue: '' }); + this.searchInput.current?.focus?.(); + }; + /** * Renders a view that allows user to select assets to build the payment request * Either top picks and user's assets are available to select @@ -365,6 +391,9 @@ class PaymentRequest extends PureComponent { const { tokens, chainId, ticker, tokenList } = this.props; const { inputWidth } = this.state; let results; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance || 'light'; + const styles = createStyles(colors); if (chainId === '1') { results = this.state.searchInputValue ? this.state.results : defaultAssets; @@ -386,27 +415,27 @@ class PaymentRequest extends PureComponent { {chainId === '1' && ( + - + {this.state.searchInputValue ? ( + + + + ) : null} )} @@ -585,6 +614,10 @@ class PaymentRequest extends PureComponent { const currencySymbol = currencySymbols[currentCurrency]; const exchangeRate = selectedAsset && selectedAsset.address && contractExchangeRates[selectedAsset.address]; let switchable = true; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance || 'light'; + const styles = createStyles(colors); + if (!conversionRate) { switchable = false; } else if (selectedAsset.symbol !== 'ETH' && !exchangeRate) { @@ -595,7 +628,7 @@ class PaymentRequest extends PureComponent { {strings('payment_request.enter_amount')} - + @@ -610,13 +643,14 @@ class PaymentRequest extends PureComponent { numberOfLines={1} onChangeText={this.updateAmount} placeholder={strings('payment_request.amount_placeholder')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} spellCheck={false} style={styles.input} value={amount} onSubmitEditing={this.onNext} ref={this.amountInput} testID={'request-amount-input'} + keyboardAppearance={themeAppearance} /> {symbol} @@ -640,10 +674,9 @@ class PaymentRequest extends PureComponent { style={styles.switchTouchable} > @@ -683,6 +716,9 @@ class PaymentRequest extends PureComponent { render() { const { mode } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( ({ conversionRate: state.engine.backgroundState.CurrencyRateController.conversionRate, currentCurrency: state.engine.backgroundState.CurrencyRateController.currentCurrency, diff --git a/app/components/UI/PaymentRequestSuccess/index.js b/app/components/UI/PaymentRequestSuccess/index.js index 2693362610f..5ecede02810 100644 --- a/app/components/UI/PaymentRequestSuccess/index.js +++ b/app/components/UI/PaymentRequestSuccess/index.js @@ -10,7 +10,7 @@ import { TouchableOpacity, } from 'react-native'; import { connect } from 'react-redux'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { getPaymentRequestSuccessOptionsTitle } from '../../UI/Navbar'; import PropTypes from 'prop-types'; import EvilIcons from 'react-native-vector-icons/EvilIcons'; @@ -27,137 +27,144 @@ import Device from '../../../util/device'; import { strings } from '../../../../locales/i18n'; import { protectWalletModalVisible } from '../../../actions/user'; import ClipboardManager from '../../../core/ClipboardManager'; +import { ThemeContext, mockTheme } from '../../../util/theme'; const isIos = Device.isIos(); -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - }, - contentWrapper: { - padding: 24, - }, - button: { - marginBottom: 16, - }, - titleText: { - ...fontStyles.bold, - fontSize: 24, - marginVertical: 16, - alignSelf: 'center', - }, - descriptionText: { - ...fontStyles.normal, - fontSize: 14, - alignSelf: 'center', - textAlign: 'center', - marginVertical: 8, - }, - linkText: { - ...fontStyles.normal, - fontSize: 14, - color: colors.blue, - alignSelf: 'center', - textAlign: 'center', - marginVertical: 16, - }, - buttonsWrapper: { - flex: 1, - flexDirection: 'row', - alignSelf: 'center', - }, - buttonsContainer: { - flex: 1, - flexDirection: 'column', - alignSelf: 'flex-end', - }, - scrollViewContainer: { - flexGrow: 1, - }, - icon: { - color: colors.blue, - marginBottom: 16, - }, - blueIcon: { - color: colors.white, - }, - iconWrapper: { - alignItems: 'center', - }, - buttonText: { - ...fontStyles.bold, - color: colors.blue, - fontSize: 14, - marginLeft: 8, - }, - blueButtonText: { - ...fontStyles.bold, - color: colors.white, - fontSize: 14, - marginLeft: 8, - }, - buttonContent: { - flexDirection: 'row', - alignSelf: 'center', - }, - buttonIconWrapper: { - flexDirection: 'column', - alignSelf: 'center', - }, - buttonTextWrapper: { - flexDirection: 'column', - alignSelf: 'center', - }, - detailsWrapper: { - padding: 10, - alignItems: 'center', - }, - addressTitle: { - fontSize: 16, - ...fontStyles.normal, - }, - informationWrapper: { - paddingHorizontal: 40, - }, - linkWrapper: { - paddingHorizontal: 24, - }, - titleQr: { - flexDirection: 'row', - alignItems: 'center', - marginBottom: isIos ? 8 : 10, - }, - closeIcon: { - right: isIos ? -20 : -40, - alignItems: 'center', - paddingHorizontal: 10, - }, - qrCode: { - marginBottom: 16, - alignItems: 'center', - justifyContent: 'center', - paddingHorizontal: 36, - paddingBottom: 24, - paddingTop: 16, - backgroundColor: colors.grey000, - borderRadius: 8, - }, - qrCodeWrapper: { - borderColor: colors.grey300, - borderRadius: 8, - borderWidth: 1, - padding: 15, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + contentWrapper: { + padding: 24, + }, + button: { + marginBottom: 16, + }, + titleText: { + ...fontStyles.bold, + fontSize: 24, + marginVertical: 16, + alignSelf: 'center', + color: colors.text.default, + }, + descriptionText: { + ...fontStyles.normal, + fontSize: 14, + alignSelf: 'center', + textAlign: 'center', + marginVertical: 8, + color: colors.text.default, + }, + linkText: { + ...fontStyles.normal, + fontSize: 14, + color: colors.primary.default, + alignSelf: 'center', + textAlign: 'center', + marginVertical: 16, + }, + buttonsWrapper: { + flex: 1, + flexDirection: 'row', + alignSelf: 'center', + }, + buttonsContainer: { + flex: 1, + flexDirection: 'column', + alignSelf: 'flex-end', + }, + scrollViewContainer: { + flexGrow: 1, + }, + icon: { + color: colors.primary.default, + marginBottom: 16, + }, + blueIcon: { + color: colors.primary.inverse, + }, + iconWrapper: { + alignItems: 'center', + }, + buttonText: { + ...fontStyles.bold, + color: colors.primary.default, + fontSize: 14, + marginLeft: 8, + }, + blueButtonText: { + ...fontStyles.bold, + color: colors.primary.inverse, + fontSize: 14, + marginLeft: 8, + }, + buttonContent: { + flexDirection: 'row', + alignSelf: 'center', + }, + buttonIconWrapper: { + flexDirection: 'column', + alignSelf: 'center', + }, + buttonTextWrapper: { + flexDirection: 'column', + alignSelf: 'center', + }, + detailsWrapper: { + padding: 10, + alignItems: 'center', + }, + addressTitle: { + fontSize: 16, + ...fontStyles.normal, + color: colors.text.default, + }, + informationWrapper: { + paddingHorizontal: 40, + }, + linkWrapper: { + paddingHorizontal: 24, + }, + titleQr: { + flexDirection: 'row', + alignItems: 'center', + marginBottom: isIos ? 8 : 10, + }, + closeIcon: { + right: isIos ? -20 : -40, + alignItems: 'center', + paddingHorizontal: 10, + }, + qrCode: { + marginBottom: 16, + alignItems: 'center', + justifyContent: 'center', + paddingHorizontal: 36, + paddingBottom: 24, + paddingTop: 16, + backgroundColor: colors.background.default, + borderRadius: 8, + }, + qrCodeWrapper: { + borderColor: colors.border.default, + borderRadius: 8, + borderWidth: 1, + padding: 15, + }, + }); /** * View to interact with a previously generated payment request link */ class PaymentRequestSuccess extends PureComponent { - static navigationOptions = ({ navigation }) => getPaymentRequestSuccessOptionsTitle(navigation); - static propTypes = { + /** + * Navigation object + */ + navigation: PropTypes.object, /** * Object that represents the current route info like params passed to it */ @@ -180,11 +187,18 @@ class PaymentRequestSuccess extends PureComponent { qrModalVisible: false, }; + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions(getPaymentRequestSuccessOptionsTitle(navigation, colors)); + }; + /** * Sets payment request link, amount and symbol of the asset to state */ componentDidMount = () => { const { route } = this.props; + this.updateNavBar(); const link = route?.params?.link ?? ''; const qrLink = route?.params?.qrLink ?? ''; const amount = route?.params?.amount ?? ''; @@ -192,6 +206,10 @@ class PaymentRequestSuccess extends PureComponent { this.setState({ link, qrLink, amount, symbol }); }; + componentDidUpdate = () => { + this.updateNavBar(); + }; + componentWillUnmount = () => { this.props.protectWalletModalVisible(); }; @@ -240,6 +258,9 @@ class PaymentRequestSuccess extends PureComponent { render() { const { link, amount, symbol, qrModalVisible } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -267,7 +288,7 @@ class PaymentRequestSuccess extends PureComponent { > - + @@ -284,7 +305,7 @@ class PaymentRequestSuccess extends PureComponent { > - + {strings('payment_request.qr_code')} @@ -313,6 +334,8 @@ class PaymentRequestSuccess extends PureComponent { onSwipeComplete={this.closeQRModal} swipeDirection={'down'} propagateSwipe + backdropColor={colors.overlay.default} + backdropOpacity={1} > @@ -324,11 +347,16 @@ class PaymentRequestSuccess extends PureComponent { onPress={this.closeQRModal} testID={'payment-request-qrcode-close-button'} > - + - + @@ -338,6 +366,8 @@ class PaymentRequestSuccess extends PureComponent { } } +PaymentRequestSuccess.contextType = ThemeContext; + const mapDispatchToProps = (dispatch) => ({ showAlert: (config) => dispatch(showAlert(config)), protectWalletModalVisible: () => dispatch(protectWalletModalVisible()), diff --git a/app/components/UI/PersonalSign/__snapshots__/index.test.tsx.snap b/app/components/UI/PersonalSign/__snapshots__/index.test.tsx.snap index d707a55f633..8ad1fb3a619 100644 --- a/app/components/UI/PersonalSign/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/PersonalSign/__snapshots__/index.test.tsx.snap @@ -22,13 +22,18 @@ exports[`PersonalSign should render correctly 1`] = ` > + StyleSheet.create({ + messageText: { + fontSize: 14, + color: colors.text.default, + ...fontStyles.normal, + textAlign: 'center', + }, + messageTextColor: { + color: colors.text.default, + }, + textLeft: { + textAlign: 'left', + }, + messageWrapper: { + marginBottom: 4, + }, + }); /** * Component that supports personal_sign @@ -134,9 +139,16 @@ export default class PersonalSign extends PureComponent { this.props.onConfirm(); }; + getStyles = () => { + const colors = this.context.colors || mockTheme.colors; + return createStyles(colors); + }; + renderMessageText = () => { const { messageParams, showExpandedMessage } = this.props; const { truncateMessage } = this.state; + const styles = this.getStyles(); + const textChild = util .hexToText(messageParams.data) .split('\n') @@ -151,11 +163,13 @@ export default class PersonalSign extends PureComponent { messageText = textChild; } else { messageText = truncateMessage ? ( - + {textChild} ) : ( - {textChild} + + {textChild} + ); } return messageText; @@ -171,6 +185,8 @@ export default class PersonalSign extends PureComponent { render() { const { currentPageInformation, toggleExpandedMessage, showExpandedMessage } = this.props; + const styles = this.getStyles(); + const rootView = showExpandedMessage ? ( + StyleSheet.create({ + warningIcon: { + color: colors.error.default, + marginRight: 10, + }, + phishingModalWrapper: { + paddingHorizontal: 20, + justifyContent: 'center', + }, + phishingModalContent: { + height: 495, + borderRadius: 4, + backgroundColor: colors.background.default, + }, + phishingModalTitle: { + ...fontStyles.bold, + color: colors.error.default, + textAlign: 'center', + }, + phishingModalHeader: { + backgroundColor: colors.background.default, + paddingVertical: 20, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + phishingModalInfo: { + backgroundColor: colors.background.alternative, + paddingTop: 20, + paddingHorizontal: 20, + }, + phishingModalInfoContent: { + paddingBottom: 20, + }, + phishingText: { + ...fontStyles.normal, + fontSize: 11, + color: colors.text.default, + marginBottom: 15, + }, + link: { + textDecorationColor: colors.text.default, + textDecorationLine: 'underline', + }, + bold: { + ...fontStyles.bold, + }, + phishingFooter: { + marginTop: 10, + alignItems: 'flex-end', + }, + backToSafetyContainer: { + borderWidth: 0, + padding: 10, + }, + backToSafetyText: { + color: colors.error.default, + fontSize: 12, + }, + foxImage: { + alignSelf: 'center', + width: 48, + height: 48, + marginBottom: -15, + zIndex: 99999, + }, + }); const foxImage = require('../../../images/fox.png'); // eslint-disable-line import/no-commonjs @@ -106,6 +108,8 @@ export default class PhishingModal extends PureComponent { }; render() { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); const urlObj = new URL(this.props.fullUrl); const host = urlObj.hostname; @@ -166,3 +170,5 @@ export default class PhishingModal extends PureComponent { ); } } + +PhishingModal.contextType = ThemeContext; diff --git a/app/components/UI/ProtectYourWalletModal/index.js b/app/components/UI/ProtectYourWalletModal/index.js index 5eae21139f9..c6af9c6a482 100644 --- a/app/components/UI/ProtectYourWalletModal/index.js +++ b/app/components/UI/ProtectYourWalletModal/index.js @@ -2,63 +2,66 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { StyleSheet, View, Text, Image, TouchableOpacity, InteractionManager } from 'react-native'; import ActionModal from '../ActionModal'; -import { fontStyles, colors } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { connect } from 'react-redux'; import { protectWalletModalNotVisible } from '../../../actions/user'; import Icon from 'react-native-vector-icons/FontAwesome'; import { strings } from '../../../../locales/i18n'; import scaling from '../../../util/scaling'; import AnalyticsV2 from '../../../util/analyticsV2'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const protectWalletImage = require('../../../images/protect-wallet.jpg'); // eslint-disable-line +const protectWalletImage = require('../../../images/explain-backup-seedphrase.png'); // eslint-disable-line -const styles = StyleSheet.create({ - wrapper: { - marginTop: 24, - marginHorizontal: 24, - flex: 1, - }, - title: { - ...fontStyles.bold, - color: colors.black, - textAlign: 'center', - fontSize: 20, - flex: 1, - }, - imageWrapper: { flexDirection: 'column', alignItems: 'center', marginBottom: 12, marginTop: 30 }, - image: { - width: scaling.scale(135, { baseModel: 1 }), - height: scaling.scale(160, { baseModel: 1 }), - }, - text: { - ...fontStyles.normal, - color: colors.black, - textAlign: 'center', - fontSize: 14, - marginBottom: 24, - }, - closeIcon: { - padding: 5, - }, - learnMoreText: { - textAlign: 'center', - ...fontStyles.normal, - color: colors.blue, - marginBottom: 14, - fontSize: 14, - }, - modalXIcon: { - fontSize: 16, - }, - titleWrapper: { - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - }, - auxCenter: { - width: 26, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + marginTop: 24, + marginHorizontal: 24, + flex: 1, + }, + title: { + ...fontStyles.bold, + color: colors.text.default, + textAlign: 'center', + fontSize: 20, + flex: 1, + }, + imageWrapper: { flexDirection: 'column', alignItems: 'center', marginBottom: 12, marginTop: 30 }, + image: { + width: scaling.scale(135, { baseModel: 1 }), + height: scaling.scale(160, { baseModel: 1 }), + }, + text: { + ...fontStyles.normal, + color: colors.text.default, + textAlign: 'center', + fontSize: 14, + marginBottom: 24, + }, + closeIcon: { + padding: 5, + }, + learnMoreText: { + textAlign: 'center', + ...fontStyles.normal, + color: colors.primary.default, + marginBottom: 14, + fontSize: 14, + }, + modalXIcon: { + fontSize: 16, + color: colors.text.default, + }, + titleWrapper: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + }, + auxCenter: { + width: 26, + }, + }); /** * View that renders an action modal @@ -116,6 +119,9 @@ class ProtectYourWalletModal extends PureComponent { }; render() { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( ({ protectWalletModalNotVisible: (enable) => dispatch(protectWalletModalNotVisible()), }); +ProtectYourWalletModal.contextType = ThemeContext; + export default connect(mapStateToProps, mapDispatchToProps)(ProtectYourWalletModal); diff --git a/app/components/UI/Radio/__snapshots__/index.test.tsx.snap b/app/components/UI/Radio/__snapshots__/index.test.tsx.snap deleted file mode 100644 index 5c966d12af6..00000000000 --- a/app/components/UI/Radio/__snapshots__/index.test.tsx.snap +++ /dev/null @@ -1,36 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Radio should render correctly 1`] = ` - - - -`; - -exports[`Radio should render correctly when selected 1`] = ` - - - -`; diff --git a/app/components/UI/Radio/index.js b/app/components/UI/Radio/index.js deleted file mode 100644 index 03de8e9f3ff..00000000000 --- a/app/components/UI/Radio/index.js +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Svg, { Circle } from 'react-native-svg'; -import { colors } from '../../../../app/styles/common'; - -const Radio = ({ selected }) => ( - - {selected ? ( - - ) : ( - - )} - -); - -Radio.propTypes = { - selected: PropTypes.bool, -}; - -export default Radio; diff --git a/app/components/UI/Radio/index.test.tsx b/app/components/UI/Radio/index.test.tsx deleted file mode 100644 index 0769b014b5a..00000000000 --- a/app/components/UI/Radio/index.test.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import { shallow } from 'enzyme'; -import Radio from './'; - -describe('Radio', () => { - it('should render correctly', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); - it('should render correctly when selected', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/app/components/UI/ReceiveRequest/index.js b/app/components/UI/ReceiveRequest/index.js index 7741c45eabf..49e01b787ec 100644 --- a/app/components/UI/ReceiveRequest/index.js +++ b/app/components/UI/ReceiveRequest/index.js @@ -20,7 +20,7 @@ import { showAlert } from '../../../actions/alert'; import { toggleReceiveModal } from '../../../actions/modals'; import { protectWalletModalVisible } from '../../../actions/user'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import Text from '../../Base/Text'; import ModalHandler from '../../Base/ModalHandler'; import ModalDragger from '../../Base/ModalDragger'; @@ -29,57 +29,59 @@ import EthereumAddress from '../EthereumAddress'; import GlobalAlert from '../GlobalAlert'; import StyledButton from '../StyledButton'; import ClipboardManager from '../../../core/ClipboardManager'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - borderTopLeftRadius: 10, - borderTopRightRadius: 10, - }, - body: { - alignItems: 'center', - paddingHorizontal: 15, - }, - qrWrapper: { - margin: 15, - }, - addressWrapper: { - flexDirection: 'row', - alignItems: 'center', - margin: 15, - padding: 9, - paddingHorizontal: 15, - backgroundColor: colors.grey000, - borderRadius: 30, - }, - copyButton: { - backgroundColor: colors.grey050, - color: colors.fontPrimary, - borderRadius: 12, - overflow: 'hidden', - paddingVertical: 3, - paddingHorizontal: 6, - marginHorizontal: 6, - }, - actionRow: { - flexDirection: 'row', - marginBottom: 15, - }, - actionButton: { - flex: 1, - marginHorizontal: 8, - }, - title: { - ...fontStyles.normal, - color: colors.fontPrimary, - fontSize: 18, - flexDirection: 'row', - alignSelf: 'center', - }, - titleWrapper: { - marginTop: 10, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + borderTopLeftRadius: 10, + borderTopRightRadius: 10, + }, + body: { + alignItems: 'center', + paddingHorizontal: 15, + }, + qrWrapper: { + margin: 15, + }, + addressWrapper: { + flexDirection: 'row', + alignItems: 'center', + margin: 15, + padding: 9, + paddingHorizontal: 15, + backgroundColor: colors.background.alternative, + borderRadius: 30, + }, + copyButton: { + backgroundColor: colors.icon.muted, + color: colors.text.default, + borderRadius: 12, + overflow: 'hidden', + paddingVertical: 3, + paddingHorizontal: 6, + marginHorizontal: 6, + }, + actionRow: { + flexDirection: 'row', + marginBottom: 15, + }, + actionButton: { + flex: 1, + marginHorizontal: 8, + }, + title: { + ...fontStyles.normal, + color: colors.text.default, + fontSize: 18, + flexDirection: 'row', + alignSelf: 'center', + }, + titleWrapper: { + marginTop: 10, + }, + }); /** * PureComponent that renders receive options @@ -219,6 +221,9 @@ class ReceiveRequest extends PureComponent { }; render() { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -244,6 +249,8 @@ class ReceiveRequest extends PureComponent { this.closeQrModal(toggleModal)} /> @@ -278,7 +287,7 @@ class ReceiveRequest extends PureComponent { @@ -305,6 +314,8 @@ class ReceiveRequest extends PureComponent { } } +ReceiveRequest.contextType = ThemeContext; + const mapStateToProps = (state) => ({ network: state.engine.backgroundState.NetworkController.network, ticker: state.engine.backgroundState.NetworkController.provider.ticker, diff --git a/app/components/UI/ReusableModal/index.tsx b/app/components/UI/ReusableModal/index.tsx index b4a01dbdb4a..486d4b51b66 100644 --- a/app/components/UI/ReusableModal/index.tsx +++ b/app/components/UI/ReusableModal/index.tsx @@ -18,7 +18,8 @@ import Animated, { set, } from 'react-native-reanimated'; import { onGestureEvent, withSpring, clamp, timing } from 'react-native-redash/src/v1'; -import styles from './styles'; +import createStyles from './styles'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; const screenHeight = Dimensions.get('window').height; type DismissModal = () => void; @@ -41,6 +42,8 @@ const ReusableModal = forwardRef((props, ref) => { const navigation = useNavigation(); const safeAreaInsets = useSafeAreaInsets(); const trigger = useRef(); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); // Animation config const animationConfig: Omit = { @@ -187,7 +190,7 @@ const ReusableModal = forwardRef((props, ref) => { const renderOverlay = useCallback(() => { return ; - }, [animatedStyles]); + }, [animatedStyles, styles]); const renderContent = useCallback(() => { return ( diff --git a/app/components/UI/ReusableModal/styles.ts b/app/components/UI/ReusableModal/styles.ts index ab5c511617e..e5408ea1f48 100644 --- a/app/components/UI/ReusableModal/styles.ts +++ b/app/components/UI/ReusableModal/styles.ts @@ -1,15 +1,15 @@ import { StyleSheet } from 'react-native'; -import { colors } from '../../../styles/common'; -export default StyleSheet.create({ - container: { - flex: 1, - }, - overlayBackground: { - backgroundColor: colors.overlay, - ...StyleSheet.absoluteFillObject, - }, - fill: { - flex: 1, - }, -}); +export default (colors: any) => + StyleSheet.create({ + container: { + flex: 1, + }, + overlayBackground: { + backgroundColor: colors.overlay.default, + ...StyleSheet.absoluteFillObject, + }, + fill: { + flex: 1, + }, + }); diff --git a/app/components/UI/ReviewModal/index.tsx b/app/components/UI/ReviewModal/index.tsx index f4fbadc0876..6e694cbf526 100644 --- a/app/components/UI/ReviewModal/index.tsx +++ b/app/components/UI/ReviewModal/index.tsx @@ -2,12 +2,12 @@ import React, { useCallback, useRef, useState } from 'react'; import { View, Image, Text, TouchableOpacity, LayoutAnimation } from 'react-native'; import ReusableModal, { ReusableModalRef } from '../ReusableModal'; import Icon from 'react-native-vector-icons/Feather'; -import { colors } from '../../../styles/common'; import { useNavigation } from '@react-navigation/native'; import AppConstants from '../../../core/AppConstants'; import { strings } from '../../../../locales/i18n'; import ReviewManager from '../../../core/ReviewManager'; -import styles from './styles'; +import { createStyles } from './styles'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; interface HelpOption { label: string; @@ -36,6 +36,8 @@ const ReviewModal = () => { const navigation = useNavigation(); const modalRef = useRef(null); const [showHelpOptions, setShowHelpOptions] = useState(false); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); const dismissModal = (cb?: () => void) => modalRef?.current?.dismissModal(cb); @@ -103,7 +105,7 @@ const ReviewModal = () => { })} ), - [openUrl] + [openUrl, styles] ); const renderContent = () => { @@ -122,7 +124,7 @@ const ReviewModal = () => { hitSlop={{ top: 12, right: 12, bottom: 12, left: 12 }} onPress={triggerClose} > - + diff --git a/app/components/UI/ReviewModal/styles.ts b/app/components/UI/ReviewModal/styles.ts index f2730cb6d4c..82786e3c0ce 100644 --- a/app/components/UI/ReviewModal/styles.ts +++ b/app/components/UI/ReviewModal/styles.ts @@ -1,44 +1,45 @@ +/* eslint-disable import/prefer-default-export */ import { StyleSheet } from 'react-native'; -import { colors } from '../../../styles/common'; -export default StyleSheet.create({ - screen: { justifyContent: 'center', paddingHorizontal: 24 }, - modal: { - backgroundColor: colors.white, - alignItems: 'center', - borderRadius: 8, - paddingVertical: 36, - }, - contentContainer: { - alignItems: 'center', - }, - optionsContainer: { flexDirection: 'row', marginTop: 14 }, - option: { alignItems: 'center', paddingHorizontal: 14 }, - optionIcon: { fontSize: 24 }, - optionLabel: { fontSize: 14, fontFamily: 'EuclidCircularB-Regular', color: colors.blue }, - helpOption: { marginVertical: 12 }, - optionLabelRed: { color: colors.fontError }, - fox: { height: 44, width: 44, marginBottom: 12 }, - questionLabel: { - fontSize: 18, - paddingHorizontal: 30, - fontFamily: 'EuclidCircularB-Bold', - textAlign: 'center', - color: colors.black, - lineHeight: 26, - }, - description: { - fontSize: 14, - fontFamily: 'EuclidCircularB-Regular', - color: colors.greyAssetVisibility, - textAlign: 'center', - lineHeight: 20, - paddingHorizontal: 30, - marginBottom: 12, - marginTop: 6, - }, - contactLabel: { - color: colors.blue, - }, - closeButton: { position: 'absolute', right: 16, top: 16 }, -}); +export const createStyles = (colors: any) => + StyleSheet.create({ + screen: { justifyContent: 'center', paddingHorizontal: 24 }, + modal: { + backgroundColor: colors.background.default, + alignItems: 'center', + borderRadius: 8, + paddingVertical: 36, + }, + contentContainer: { + alignItems: 'center', + }, + optionsContainer: { flexDirection: 'row', marginTop: 14 }, + option: { alignItems: 'center', paddingHorizontal: 14 }, + optionIcon: { fontSize: 24 }, + optionLabel: { fontSize: 14, fontFamily: 'EuclidCircularB-Regular', color: colors.primary.default }, + helpOption: { marginVertical: 12 }, + optionLabelRed: { color: colors.error.default }, + fox: { height: 44, width: 44, marginBottom: 12 }, + questionLabel: { + fontSize: 18, + paddingHorizontal: 30, + fontFamily: 'EuclidCircularB-Bold', + textAlign: 'center', + color: colors.text.default, + lineHeight: 26, + }, + description: { + fontSize: 14, + fontFamily: 'EuclidCircularB-Regular', + color: colors.text.alternative, + textAlign: 'center', + lineHeight: 20, + paddingHorizontal: 30, + marginBottom: 12, + marginTop: 6, + }, + contactLabel: { + color: colors.primary.default, + }, + closeButton: { position: 'absolute', right: 16, top: 16 }, + }); diff --git a/app/components/UI/Screen/index.js b/app/components/UI/Screen/index.js index eefac8a6698..98a3523acef 100644 --- a/app/components/UI/Screen/index.js +++ b/app/components/UI/Screen/index.js @@ -1,8 +1,8 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; -import { SafeAreaView, StatusBar, View } from 'react-native'; -import { colors, baseStyles } from '../../../styles/common'; -import Device from '../../../util/device'; +import { SafeAreaView, View } from 'react-native'; +import { baseStyles } from '../../../styles/common'; + /** * Base view component providing consistent styling meant to wrap other views */ @@ -14,13 +14,6 @@ export default class Screen extends PureComponent { children: PropTypes.node, }; - componentDidMount() { - StatusBar.setBarStyle('dark-content', true); - if (Device.isAndroid()) { - StatusBar.setBackgroundColor(colors.grey100); - } - } - render() { return ( diff --git a/app/components/UI/SearchTokenAutocomplete/index.tsx b/app/components/UI/SearchTokenAutocomplete/index.tsx index 21cd7276544..985e9a4da72 100644 --- a/app/components/UI/SearchTokenAutocomplete/index.tsx +++ b/app/components/UI/SearchTokenAutocomplete/index.tsx @@ -1,6 +1,5 @@ import React, { useCallback, useState } from 'react'; import { View, StyleSheet, InteractionManager, Text, LayoutAnimation } from 'react-native'; -import { colors } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import ActionView from '../ActionView'; import AssetSearch from '../AssetSearch'; @@ -11,20 +10,22 @@ import Alert, { AlertType } from '../../Base/Alert'; import FontAwesome from 'react-native-vector-icons/FontAwesome'; import { useSelector } from 'react-redux'; import { MAINNET } from '../../../constants/network'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - }, - tokenDetectionBanner: { marginHorizontal: 20, marginTop: 20, paddingRight: 0 }, - tokenDetectionDescription: { color: colors.black }, - tokenDetectionLink: { color: colors.blue }, - tokenDetectionIcon: { - paddingTop: 4, - paddingRight: 8, - }, -}); +const createStyles = (colors: any) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + tokenDetectionBanner: { marginHorizontal: 20, marginTop: 20, paddingRight: 0 }, + tokenDetectionDescription: { color: colors.text.default }, + tokenDetectionLink: { color: colors.primary.default }, + tokenDetectionIcon: { + paddingTop: 4, + paddingRight: 8, + }, + }); interface Props { /** @@ -42,6 +43,9 @@ const SearchTokenAutocomplete = ({ navigation }: Props) => { const [selectedAsset, setSelectedAsset] = useState({}); const [isSearchFocused, setIsSearchFocused] = useState(false); const { address, symbol, decimals } = selectedAsset as any; + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + const isTokenDetectionEnabled = useSelector( (state: any) => !state.engine.backgroundState.PreferencesController.useStaticTokenList ); @@ -120,7 +124,7 @@ const SearchTokenAutocomplete = ({ navigation }: Props) => { )} @@ -131,9 +135,12 @@ const SearchTokenAutocomplete = ({ navigation }: Props) => { suppressHighlighting onPress={() => { navigation.navigate('SettingsView', { - screen: 'ExperimentalSettings', + screen: 'SettingsFlow', params: { - isFullScreenModal: true, + screen: 'ExperimentalSettings', + params: { + isFullScreenModal: true, + }, }, }); }} @@ -144,7 +151,7 @@ const SearchTokenAutocomplete = ({ navigation }: Props) => { ); - }, [navigation, isSearchFocused, isTokenDetectionEnabled, isMainnet]); + }, [navigation, isSearchFocused, isTokenDetectionEnabled, isMainnet, colors, styles]); return ( diff --git a/app/components/UI/SeedphraseModal/__snapshots__/index.test.tsx.snap b/app/components/UI/SeedphraseModal/__snapshots__/index.test.tsx.snap index 20a4a23836c..5501ca637df 100644 --- a/app/components/UI/SeedphraseModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/SeedphraseModal/__snapshots__/index.test.tsx.snap @@ -48,7 +48,7 @@ exports[`SeedphraseModal should render correctly 1`] = ` + StyleSheet.create({ + whatIsSeedphraseTitle: { + flex: 1, + fontSize: 18, + color: colors.text.default, + textAlign: 'center', + ...fontStyles.bold, + }, + modalNoBorder: { + borderTopWidth: 0, + }, + modalContainer: { + flex: 1, + padding: 27, + flexDirection: 'column', + }, + modalXButton: { + padding: 5, + alignItems: 'flex-end', + }, + titleContainer: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + marginBottom: 16, + }, + auxCenterView: { + width: 26, + }, + explanationText: { + fontSize: 14, + marginTop: 16, + textAlign: 'center', + ...fontStyles.normal, + color: colors.text.default, + lineHeight: 20, + }, + modalXIcon: { + fontSize: 16, + color: colors.text.default, + }, + }); -const SeedphraseModal = ({ showWhatIsSeedphraseModal, hideWhatIsSeedphrase }) => ( - - - - - - {strings('account_backup_step_1.what_is_seedphrase_title')} - - - - - - - {strings('account_backup_step_1.what_is_seedphrase_text_1')} - {strings('account_backup_step_1.what_is_seedphrase_text_2')} - {strings('account_backup_step_1.what_is_seedphrase_text_3')} +const SeedphraseModal = ({ showWhatIsSeedphraseModal, hideWhatIsSeedphrase }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + + + + + {strings('account_backup_step_1.what_is_seedphrase_title')} + + + + + + + + {strings('account_backup_step_1.what_is_seedphrase_text_1')} + + + {strings('account_backup_step_1.what_is_seedphrase_text_2')} + + + {strings('account_backup_step_1.what_is_seedphrase_text_3')} + + - - -); + + ); +}; SeedphraseModal.propTypes = { /** diff --git a/app/components/UI/SelectComponent/__snapshots__/index.test.tsx.snap b/app/components/UI/SelectComponent/__snapshots__/index.test.tsx.snap index 6ba59e2214c..c5476ff34d4 100644 --- a/app/components/UI/SelectComponent/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/SelectComponent/__snapshots__/index.test.tsx.snap @@ -30,7 +30,7 @@ exports[`SelectComponent should render correctly 1`] = ` style={ Object { "alignSelf": "flex-start", - "color": "#000000", + "color": "#24272A", "flex": 1, "fontFamily": "EuclidCircularB-Regular", "fontSize": 14, @@ -43,7 +43,7 @@ exports[`SelectComponent should render correctly 1`] = ` /> @@ -171,6 +172,7 @@ exports[`SelectComponent should render correctly 1`] = ` numberOfLines={1} style={ Object { + "color": "#24272A", "flex": 1, "fontFamily": "EuclidCircularB-Regular", "fontSize": 14, @@ -190,7 +192,7 @@ exports[`SelectComponent should render correctly 1`] = ` "flexDirection": "row", "height": 35, "paddingHorizontal": 15, - "paddingVertical": 4, + "paddingVertical": 5, } } > @@ -198,6 +200,7 @@ exports[`SelectComponent should render correctly 1`] = ` numberOfLines={1} style={ Object { + "color": "#24272A", "flex": 1, "fontFamily": "EuclidCircularB-Regular", "fontSize": 14, diff --git a/app/components/UI/SelectComponent/index.js b/app/components/UI/SelectComponent/index.js index a3c5ddd3a0e..78b9923cd67 100644 --- a/app/components/UI/SelectComponent/index.js +++ b/app/components/UI/SelectComponent/index.js @@ -1,86 +1,88 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { ScrollView, StyleSheet, Text, View, TouchableOpacity } from 'react-native'; -import { Picker } from '@react-native-community/picker'; -import { fontStyles, colors, baseStyles } from '../../../styles/common'; +import { fontStyles, baseStyles } from '../../../styles/common'; import Icon from 'react-native-vector-icons/MaterialIcons'; import Modal from 'react-native-modal'; import dismissKeyboard from 'react-native/Libraries/Utilities/dismissKeyboard'; import IconCheck from 'react-native-vector-icons/MaterialCommunityIcons'; import Device from '../../../util/device'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const PickerItem = Picker.Item; const ROW_HEIGHT = 35; -const styles = StyleSheet.create({ - dropdown: { - flexDirection: 'row', - }, - iconDropdown: { - marginTop: 7, - height: 25, - justifyContent: 'flex-end', - textAlign: 'right', - marginRight: 10, - }, - selectedOption: { - flex: 1, - alignSelf: 'flex-start', - color: colors.fontPrimary, - fontSize: 14, - paddingHorizontal: 15, - paddingTop: 10, - paddingBottom: 10, - ...fontStyles.normal, - }, - accesoryBar: { - width: '100%', - paddingTop: 5, - height: 50, - borderBottomColor: colors.grey100, - borderBottomWidth: 1, - }, - label: { - textAlign: 'center', - flex: 1, - paddingVertical: 10, - fontSize: 17, - ...fontStyles.bold, - }, - modal: { - margin: 0, - width: '100%', - padding: 60, - }, - modalView: { - backgroundColor: colors.white, - justifyContent: 'center', - alignItems: 'center', - borderRadius: 10, - }, - list: { - width: '100%', - }, - optionButton: { - paddingHorizontal: 15, - paddingVertical: 4, - flexDirection: 'row', - height: ROW_HEIGHT, - }, - optionLabel: { - paddingVertical: 10, - flex: 1, - fontSize: 14, - ...fontStyles.normal, - }, - icon: { - paddingHorizontal: 10, - marginTop: 5, - }, - listWrapper: { - flex: 1, - paddingBottom: 10, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + dropdown: { + flexDirection: 'row', + }, + iconDropdown: { + marginTop: 7, + height: 25, + justifyContent: 'flex-end', + textAlign: 'right', + marginRight: 10, + }, + selectedOption: { + flex: 1, + alignSelf: 'flex-start', + color: colors.text.default, + fontSize: 14, + paddingHorizontal: 15, + paddingTop: 10, + paddingBottom: 10, + ...fontStyles.normal, + }, + accesoryBar: { + width: '100%', + paddingTop: 5, + height: 50, + borderBottomColor: colors.border.muted, + borderBottomWidth: 1, + }, + label: { + textAlign: 'center', + flex: 1, + paddingVertical: 10, + fontSize: 17, + ...fontStyles.bold, + color: colors.text.default, + }, + modal: { + margin: 0, + width: '100%', + padding: 60, + }, + modalView: { + backgroundColor: colors.background.default, + justifyContent: 'center', + alignItems: 'center', + borderRadius: 10, + }, + list: { + width: '100%', + }, + optionButton: { + paddingHorizontal: 15, + paddingVertical: 5, + flexDirection: 'row', + height: Device.isIos() ? ROW_HEIGHT : undefined, + }, + optionLabel: { + paddingVertical: 10, + flex: 1, + fontSize: 14, + ...fontStyles.normal, + color: colors.text.default, + }, + icon: { + paddingHorizontal: 10, + marginTop: 5, + }, + listWrapper: { + flex: 1, + paddingBottom: 10, + }, + }); export default class SelectComponent extends PureComponent { static propTypes = { @@ -154,73 +156,69 @@ export default class SelectComponent extends PureComponent { return ''; }; - renderAndroid = () => ( - - - {this.props.options - /** - * Select value always comes first - */ - .sort((a, b) => - a.value === this.props.selectedValue || a.value < b.value ? -1 : a.value > b.value ? 1 : 0 - ) - .map((option) => ( - - ))} - - - ); + renderDropdownSelector = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); - renderIOS = () => ( - - - - - {this.getSelectedValue()} - - - - - - - - {this.props.label} + return ( + + + + + {this.getSelectedValue()} + + - - - {this.props.options.map((option) => ( - this.onValueChange(option.value)} - style={styles.optionButton} - key={option.key} - > - - {option.label} - - {this.props.selectedValue === option.value ? ( - - ) : null} - - ))} + + + + + {this.props.label} - - - - - ); + + + {this.props.options.map((option) => ( + this.onValueChange(option.value)} + style={styles.optionButton} + key={option.key} + > + + {option.label} + + {this.props.selectedValue === option.value ? ( + + ) : null} + + ))} + + + + + + ); + }; - render = () => ( - {Device.isAndroid() ? this.renderAndroid() : this.renderIOS()} - ); + render = () => {this.renderDropdownSelector()}; } + +SelectComponent.contextType = ThemeContext; diff --git a/app/components/UI/SettingsDrawer/index.js b/app/components/UI/SettingsDrawer/index.js index 8159af70d05..957f98d1291 100644 --- a/app/components/UI/SettingsDrawer/index.js +++ b/app/components/UI/SettingsDrawer/index.js @@ -1,59 +1,61 @@ import React from 'react'; import { Text, View, StyleSheet, TouchableOpacity } from 'react-native'; import PropTypes from 'prop-types'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import Icon from 'react-native-vector-icons/FontAwesome'; import SettingsNotification from '../SettingsNotification'; import { strings } from '../../../../locales/i18n'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - root: { - backgroundColor: colors.white, - borderBottomColor: colors.grey000, - borderBottomWidth: 1, - flexDirection: 'row', - minHeight: 100, - paddingVertical: 18, - }, - content: { - flex: 1, - }, - title: { - ...fontStyles.normal, - color: colors.fontPrimary, - fontSize: 20, - marginBottom: 8, - }, - description: { - ...fontStyles.normal, - color: colors.grey500, - fontSize: 14, - lineHeight: 20, - paddingRight: 8, - }, - action: { - flex: 0, - paddingHorizontal: 16, - }, - icon: { - bottom: 8, - color: colors.grey400, - left: 4, - position: 'relative', - }, - noBorder: { - borderBottomWidth: 0, - }, - warning: { - alignSelf: 'flex-start', - marginTop: 20, - }, - menuItemWarningText: { - color: colors.red, - fontSize: 12, - ...fontStyles.normal, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + root: { + backgroundColor: colors.background.default, + borderBottomColor: colors.border.muted, + borderBottomWidth: 1, + flexDirection: 'row', + minHeight: 100, + paddingVertical: 18, + }, + content: { + flex: 1, + }, + title: { + ...fontStyles.normal, + color: colors.text.default, + fontSize: 20, + marginBottom: 8, + }, + description: { + ...fontStyles.normal, + color: colors.text.alternative, + fontSize: 14, + lineHeight: 20, + paddingRight: 8, + }, + action: { + flex: 0, + paddingHorizontal: 16, + }, + icon: { + bottom: 8, + color: colors.icon.muted, + left: 4, + position: 'relative', + }, + noBorder: { + borderBottomWidth: 0, + }, + warning: { + alignSelf: 'flex-start', + marginTop: 20, + }, + menuItemWarningText: { + color: colors.text.default, + fontSize: 12, + ...fontStyles.normal, + }, + }); const propTypes = { title: PropTypes.string, @@ -79,26 +81,31 @@ const defaultProps = { onPress: undefined, }; -const SettingsDrawer = ({ title, description, noBorder, onPress, warning }) => ( - - - - {title} - {description} - - {warning ? ( - - {strings('drawer.settings_warning')} - - ) : null} +const SettingsDrawer = ({ title, description, noBorder, onPress, warning }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + + + {title} + {description} + + {warning ? ( + + {strings('drawer.settings_warning')} + + ) : null} + + + + - - - - - -); + + ); +}; SettingsDrawer.propTypes = propTypes; SettingsDrawer.defaultProps = defaultProps; diff --git a/app/components/UI/SettingsNotification/__snapshots__/index.test.tsx.snap b/app/components/UI/SettingsNotification/__snapshots__/index.test.tsx.snap index ca4eebfc575..247a114e171 100644 --- a/app/components/UI/SettingsNotification/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/SettingsNotification/__snapshots__/index.test.tsx.snap @@ -35,7 +35,7 @@ exports[`SettingsNotification should render correctly as warning 1`] = ` "width": "100%", }, Object { - "backgroundColor": "#fcf2f3", + "backgroundColor": "#D73A4919", }, ] } diff --git a/app/components/UI/SettingsNotification/index.js b/app/components/UI/SettingsNotification/index.js index 797e5985603..7408e48415e 100644 --- a/app/components/UI/SettingsNotification/index.js +++ b/app/components/UI/SettingsNotification/index.js @@ -3,42 +3,53 @@ import PropTypes from 'prop-types'; import { View, StyleSheet } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'; -import { colors } from '../../../styles/common'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - menuItemWarning: { - flex: 1, - alignSelf: 'center', - justifyContent: 'flex-end', - flexDirection: 'row', - marginRight: 24, - }, - wrapper: { - padding: 12, - borderRadius: 10, - display: 'flex', - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - width: '100%', - marginTop: 10, - }, - icon: { - marginRight: 4, - }, - red: { - backgroundColor: colors.red000, - }, - normal: { - backgroundColor: colors.grey000, - }, - check: { - color: colors.green500, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + menuItemWarning: { + flex: 1, + alignSelf: 'center', + justifyContent: 'flex-end', + flexDirection: 'row', + marginRight: 24, + }, + wrapper: { + padding: 12, + borderRadius: 10, + display: 'flex', + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + width: '100%', + marginTop: 10, + }, + icon: { + marginRight: 4, + }, + red: { + backgroundColor: colors.error.muted, + }, + normal: { + backgroundColor: colors.background.alternative, + }, + check: { + color: colors.success.default, + }, + }); -const WarningIcon = () => ; -const CheckIcon = () => ; +const WarningIcon = () => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ; +}; +const CheckIcon = () => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ; +}; const propTypes = { style: PropTypes.object, @@ -53,17 +64,22 @@ const defaultProps = { isHighlighted: false, }; -const SettingsNotification = ({ style, isWarning, isNotification, children }) => ( - - {isWarning ? : } - {children} - -); +const SettingsNotification = ({ style, isWarning, isNotification, children }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + {isWarning ? : } + {children} + + ); +}; SettingsNotification.propTypes = propTypes; SettingsNotification.defaultProps = defaultProps; diff --git a/app/components/UI/SignatureRequest/ExpandedMessage/__snapshots__/index.test.tsx.snap b/app/components/UI/SignatureRequest/ExpandedMessage/__snapshots__/index.test.tsx.snap index 3f26fff213d..41a096e2c05 100644 --- a/app/components/UI/SignatureRequest/ExpandedMessage/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/SignatureRequest/ExpandedMessage/__snapshots__/index.test.tsx.snap @@ -30,7 +30,7 @@ exports[`ExpandedMessage should render correctly 1`] = ` size={30} style={ Object { - "color": "#bbc0c5", + "color": "#BBC0C5", "flex": 1, } } @@ -38,6 +38,7 @@ exports[`ExpandedMessage should render correctly 1`] = ` + StyleSheet.create({ + expandedRoot: { + backgroundColor: colors.background.default, + minHeight: Device.isIos() ? '70%' : '80%', + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + padding: 24, + paddingBottom: Device.isIphoneX() ? 44 : 24, + }, - expandedMessageHeader: { - width: '100%', - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 20, - }, - arrowIcon: { - ...baseStyles.flexGrow, - color: colors.grey200, - }, - iconHidden: { - ...baseStyles.flexGrow, - }, - messageLabelTextExpanded: { - ...baseStyles.flexGrow, - textAlign: 'center', - ...fontStyles.bold, - fontSize: 16, - }, - messageIntroWrapper: { - alignItems: 'center', - marginBottom: 20, - }, - domainLogo: { - width: 40, - height: 40, - borderRadius: 20, - marginBottom: 20, - }, - messageFromLabel: { - textAlign: 'center', - ...fontStyles.bold, - fontSize: 16, - }, - scrollView: { - ...baseStyles.flexGrow, - }, -}); + expandedMessageHeader: { + width: '100%', + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 20, + }, + arrowIcon: { + ...baseStyles.flexGrow, + color: colors.icon.muted, + }, + iconHidden: { + ...baseStyles.flexGrow, + }, + messageLabelTextExpanded: { + ...baseStyles.flexGrow, + textAlign: 'center', + ...fontStyles.bold, + fontSize: 16, + color: colors.text.default, + }, + messageIntroWrapper: { + alignItems: 'center', + marginBottom: 20, + }, + domainLogo: { + width: 40, + height: 40, + borderRadius: 20, + marginBottom: 20, + }, + messageFromLabel: { + textAlign: 'center', + ...fontStyles.bold, + fontSize: 16, + color: colors.text.default, + }, + scrollView: { + ...baseStyles.flexGrow, + }, + }); /** * Component that supports eth_signTypedData and eth_signTypedData_v3 @@ -81,6 +85,9 @@ export default class ExpandedMessage extends PureComponent { const { currentPageInformation, renderMessage, toggleExpandedMessage } = this.props; const url = currentPageInformation.url; const title = getHost(url); + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -103,3 +110,5 @@ export default class ExpandedMessage extends PureComponent { ); } } + +ExpandedMessage.contextType = ThemeContext; diff --git a/app/components/UI/SignatureRequest/index.js b/app/components/UI/SignatureRequest/index.js index 8f375a28a06..b5944730431 100644 --- a/app/components/UI/SignatureRequest/index.js +++ b/app/components/UI/SignatureRequest/index.js @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { StyleSheet, View, Text, TouchableOpacity } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { getHost } from '../../../util/browser'; import { strings } from '../../../../locales/i18n'; import { connect } from 'react-redux'; @@ -14,89 +14,93 @@ import WarningMessage from '../../Views/SendFlow/WarningMessage'; import Device from '../../../util/device'; import Analytics from '../../../core/Analytics'; import { ANALYTICS_EVENT_OPTS } from '../../../util/analytics'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - root: { - backgroundColor: colors.white, - paddingTop: 24, - minHeight: '90%', - borderTopLeftRadius: 20, - borderTopRightRadius: 20, - paddingBottom: Device.isIphoneX() ? 20 : 0, - }, - expandedHeight2: { - minHeight: '90%', - }, - expandedHeight1: { - minHeight: '90%', - }, - signingInformation: { - alignItems: 'center', - marginVertical: 24, - }, - domainLogo: { - width: 40, - height: 40, - marginRight: 8, - borderRadius: 20, - }, - messageColumn: { - width: '75%', - justifyContent: 'space-between', - }, - warningLink: { - ...fontStyles.normal, - color: colors.blue, - textAlign: 'center', - paddingHorizontal: 10, - paddingBottom: 10, - textDecorationLine: 'underline', - }, - signText: { - ...fontStyles.bold, - fontSize: 20, - textAlign: 'center', - }, - messageLabelText: { - ...fontStyles.bold, - fontSize: 16, - marginBottom: 4, - }, - readMore: { - color: colors.blue, - fontSize: 14, - ...fontStyles.bold, - }, - warningWrapper: { - width: '100%', - paddingHorizontal: 24, - paddingTop: 24, - }, - actionViewChild: { - paddingHorizontal: 24, - }, - accountInfoCardWrapper: { - marginBottom: 20, - width: '100%', - }, - children: { - alignSelf: 'center', - flexDirection: 'row', - justifyContent: 'flex-start', - width: '100%', - borderWidth: 1, - borderColor: colors.grey200, - borderRadius: 10, - padding: 16, - }, - arrowIconWrapper: { - flexGrow: 1, - alignItems: 'flex-end', - }, - arrowIcon: { - color: colors.grey200, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + root: { + backgroundColor: colors.background.default, + paddingTop: 24, + minHeight: '90%', + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + paddingBottom: Device.isIphoneX() ? 20 : 0, + }, + expandedHeight2: { + minHeight: '90%', + }, + expandedHeight1: { + minHeight: '90%', + }, + signingInformation: { + alignItems: 'center', + marginVertical: 24, + }, + domainLogo: { + width: 40, + height: 40, + marginRight: 8, + borderRadius: 20, + }, + messageColumn: { + width: '75%', + justifyContent: 'space-between', + }, + warningLink: { + ...fontStyles.normal, + color: colors.primary.default, + textAlign: 'center', + paddingHorizontal: 10, + paddingBottom: 10, + textDecorationLine: 'underline', + }, + signText: { + ...fontStyles.bold, + fontSize: 20, + textAlign: 'center', + color: colors.text.default, + }, + messageLabelText: { + ...fontStyles.bold, + fontSize: 16, + marginBottom: 4, + color: colors.text.default, + }, + readMore: { + color: colors.primary.default, + fontSize: 14, + ...fontStyles.bold, + }, + warningWrapper: { + width: '100%', + paddingHorizontal: 24, + paddingTop: 24, + }, + actionViewChild: { + paddingHorizontal: 24, + }, + accountInfoCardWrapper: { + marginBottom: 20, + width: '100%', + }, + children: { + alignSelf: 'center', + flexDirection: 'row', + justifyContent: 'flex-start', + width: '100%', + borderWidth: 1, + borderColor: colors.border.default, + borderRadius: 10, + padding: 16, + }, + arrowIconWrapper: { + flexGrow: 1, + alignItems: 'flex-end', + }, + arrowIcon: { + color: colors.icon.muted, + }, + }); /** * PureComponent that renders scrollable content inside signature request user interface @@ -191,16 +195,26 @@ class SignatureRequest extends PureComponent { }); }; - renderWarning = () => ( - - {strings('signature_request.eth_sign_warning')} - {` `} - {strings('signature_request.learn_more')} - - ); + getStyles = () => { + const colors = this.context.colors || mockTheme.colors; + return createStyles(colors); + }; + + renderWarning = () => { + const styles = this.getStyles(); + + return ( + + {strings('signature_request.eth_sign_warning')} + {` `} + {strings('signature_request.learn_more')} + + ); + }; renderActionViewChildren = () => { const { children, currentPageInformation, truncateMessage, toggleExpandedMessage } = this.props; + const styles = this.getStyles(); const url = currentPageInformation.url; const title = getHost(url); const arrowIcon = truncateMessage ? this.renderArrowIcon() : null; @@ -224,15 +238,21 @@ class SignatureRequest extends PureComponent { ); }; - renderArrowIcon = () => ( - - - - ); + renderArrowIcon = () => { + const styles = this.getStyles(); + + return ( + + + + ); + }; render() { const { showWarning, currentPageInformation, type } = this.props; let expandedHeight; + const styles = this.getStyles(); + if (Device.isMediumDevice()) { expandedHeight = styles.expandedHeight2; if (type === 'ethSign') { @@ -272,4 +292,6 @@ const mapStateToProps = (state) => ({ networkType: state.engine.backgroundState.NetworkController.provider.type, }); +SignatureRequest.contextType = ThemeContext; + export default connect(mapStateToProps)(SignatureRequest); diff --git a/app/components/UI/SkipAccountSecurityModal/__snapshots__/index.test.tsx.snap b/app/components/UI/SkipAccountSecurityModal/__snapshots__/index.test.tsx.snap index 59198508484..501df30c39a 100644 --- a/app/components/UI/SkipAccountSecurityModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/SkipAccountSecurityModal/__snapshots__/index.test.tsx.snap @@ -43,7 +43,6 @@ exports[`HintModal should render correctly 1`] = ` style={ Object { "alignItems": "flex-end", - "flex": 1, } } > @@ -53,6 +52,7 @@ exports[`HintModal should render correctly 1`] = ` size={12} style={ Object { + "color": "#24272A", "fontSize": 16, } } @@ -73,7 +73,7 @@ exports[`HintModal should render correctly 1`] = ` + StyleSheet.create({ + imageWarning: { + alignSelf: 'center', + color: colors.error.default, + }, + modalNoBorder: { + borderTopWidth: 0, + }, + skipTitle: { + fontSize: 24, + marginTop: 12, + marginBottom: 16, + color: colors.text.default, + textAlign: 'center', + ...fontStyles.bold, + }, + skipModalContainer: { + flex: 1, + margin: 24, + flexDirection: 'column', + }, + skipModalXButton: { + alignItems: 'flex-end', + }, + skipModalXIcon: { + fontSize: 16, + color: colors.text.default, + }, + skipModalActionButtons: { + flexDirection: 'row', + alignItems: 'flex-start', + }, + skipModalCheckbox: { + height: 18, + width: 18, + marginRight: 12, + marginTop: 3, + }, + skipModalText: { + flex: 1, + ...fontStyles.normal, + lineHeight: 20, + fontSize: 14, + paddingHorizontal: 10, + color: colors.text.default, + }, + }); -const SkipAccountSecurityModal = ({ modalVisible, onConfirm, onCancel, onPress, toggleSkipCheckbox, skipCheckbox }) => ( - - - - - - - {strings('account_backup_step_1.skip_title')} - - { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + return ( + + + {onPress && ( + + + + )} + - - {strings('account_backup_step_1.skip_check')} - + {strings('account_backup_step_1.skip_title')} + + + + {strings('account_backup_step_1.skip_check')} + + - - -); + + ); +}; const propTypes = { modalVisible: PropTypes.bool.isRequired, onConfirm: PropTypes.func.isRequired, onCancel: PropTypes.func.isRequired, - onPress: PropTypes.func.isRequired, + onPress: PropTypes.func, toggleSkipCheckbox: PropTypes.func.isRequired, skipCheckbox: PropTypes.bool.isRequired, }; diff --git a/app/components/UI/SliderButton/__snapshots__/index.test.tsx.snap b/app/components/UI/SliderButton/__snapshots__/index.test.tsx.snap index 1758291b99a..2a8f1e30772 100644 --- a/app/components/UI/SliderButton/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/SliderButton/__snapshots__/index.test.tsx.snap @@ -7,7 +7,7 @@ exports[`SliderButton should render correctly 1`] = ` Array [ Object { "elevation": 0, - "shadowColor": "#75C4FD", + "shadowColor": "#037DD6", "shadowOffset": Object { "height": 3, "width": 0, @@ -23,7 +23,7 @@ exports[`SliderButton should render correctly 1`] = ` style={ Object { "alignItems": "center", - "backgroundColor": "#0074C8", + "backgroundColor": "#0260A4", "borderRadius": 60, "height": 60, "justifyContent": "center", @@ -86,7 +86,7 @@ exports[`SliderButton should render correctly 1`] = ` gray shadow - }, - disabledContainer: { - opacity: 0.66, - }, - slider: { - position: 'absolute', - width: DIAMETER, - height: DIAMETER, - borderRadius: DIAMETER, - borderWidth: MARGIN, - borderColor: colors.blue600, - backgroundColor: colors.white, - }, - trackBack: { - position: 'relative', - overflow: 'hidden', - width: '100%', - height: DIAMETER, - justifyContent: 'center', - alignItems: 'center', - borderRadius: DIAMETER, - backgroundColor: colors.blue700, - }, - trackBackGradient: { - position: 'absolute', - width: '100%', - height: '100%', - }, - trackBackGradientPressed: { - opacity: 0.66, - }, - trackBackShine: { - position: 'absolute', - height: '200%', - left: 0, - }, - trackFront: { - position: 'absolute', - overflow: 'hidden', - height: '100%', - borderRadius: DIAMETER, - }, +const createStyles = (colors) => + StyleSheet.create({ + container: { + shadowRadius: 8, + shadowOpacity: 0.5, + shadowColor: colors.primary.default, + shadowOffset: { width: 0, height: 3 }, + elevation: 0, // shadow colors not supported on Android. nothing > gray shadow + }, + disabledContainer: { + opacity: 0.66, + }, + slider: { + position: 'absolute', + width: DIAMETER, + height: DIAMETER, + borderRadius: DIAMETER, + borderWidth: MARGIN, + borderColor: colors.primary.alternative, + backgroundColor: colors.primary.inverse, + }, + trackBack: { + position: 'relative', + overflow: 'hidden', + width: '100%', + height: DIAMETER, + justifyContent: 'center', + alignItems: 'center', + borderRadius: DIAMETER, + backgroundColor: colors.primary.alternative, + }, + trackBackGradient: { + position: 'absolute', + width: '100%', + height: '100%', + }, + trackBackGradientPressed: { + opacity: 0.66, + }, + trackBackShine: { + position: 'absolute', + height: '200%', + left: 0, + }, + trackFront: { + position: 'absolute', + overflow: 'hidden', + height: '100%', + borderRadius: DIAMETER, + }, - textFrontContainer: { - position: 'absolute', - width: '100%', - height: '100%', - justifyContent: 'center', - alignItems: 'center', - }, - textBack: { - ...fontStyles.normal, - color: colors.white, - fontSize: 16, - }, - textFront: { - ...fontStyles.normal, - color: colors.white, - fontSize: 16, - }, -}); + textFrontContainer: { + position: 'absolute', + width: '100%', + height: '100%', + justifyContent: 'center', + alignItems: 'center', + }, + textBack: { + ...fontStyles.normal, + color: colors.primary.inverse, + fontSize: 16, + }, + textFront: { + ...fontStyles.normal, + color: colors.primary.inverse, + fontSize: 16, + }, + }); function SliderButton({ incompleteText, completeText, onComplete, disabled, onSwipeChange }) { const [componentWidth, setComponentWidth] = useState(0); @@ -95,6 +97,9 @@ function SliderButton({ incompleteText, completeText, onComplete, disabled, onSw const onCompleteCallback = useRef(onComplete); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + const handleIsPressed = useCallback( (isPressed) => { onSwipeChange?.(isPressed); @@ -127,7 +132,7 @@ function SliderButton({ incompleteText, completeText, onComplete, disabled, onSw const sliderCompletedOpacity = completion.interpolate({ inputRange: [0, 1], outputRange: [1, 0] }); const trackFrontBackgroundColor = completion.interpolate({ inputRange: [0, 1], - outputRange: [colors.blue600, colors.success], + outputRange: [colors.primary.alternative, colors.success.default], }); useEffect(() => { diff --git a/app/components/UI/SlippageSlider/__snapshots__/index.test.tsx.snap b/app/components/UI/SlippageSlider/__snapshots__/index.test.tsx.snap index 1307399c9d6..51cd65c7866 100644 --- a/app/components/UI/SlippageSlider/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/SlippageSlider/__snapshots__/index.test.tsx.snap @@ -6,7 +6,7 @@ exports[`SlippageSlider should render correctly 1`] = ` style={ Array [ Object { - "height": 69, + "height": 76, "justifyContent": "center", "position": "relative", }, @@ -33,8 +33,8 @@ exports[`SlippageSlider should render correctly 1`] = ` style={ Object { "alignItems": "center", - "backgroundColor": "#eaf6ff", - "borderColor": "#eaf6ff", + "backgroundColor": "#037DD619", + "borderColor": "#037DD619", "borderRadius": 9, "borderWidth": 2, "flexDirection": "row", @@ -137,56 +137,47 @@ exports[`SlippageSlider should render correctly 1`] = ` /> - + + + diff --git a/app/components/UI/SlippageSlider/index.js b/app/components/UI/SlippageSlider/index.js index b243cace285..976f4a84eb4 100644 --- a/app/components/UI/SlippageSlider/index.js +++ b/app/components/UI/SlippageSlider/index.js @@ -1,7 +1,9 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { View, Animated, PanResponder, StyleSheet, Text, Image } from 'react-native'; import PropTypes from 'prop-types'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles, colors as importedColors } from '../../../styles/common'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; +import Svg, { Path } from 'react-native-svg'; /* eslint-disable import/no-commonjs */ const SlippageSliderBgImg = require('../../../images/slippage-slider-bg.png'); @@ -10,96 +12,89 @@ const SlippageSliderBgImg = require('../../../images/slippage-slider-bg.png'); const DIAMETER = 30; const TRACK_PADDING = 2; const TICK_DIAMETER = 5; -const TOOLTIP_HEIGHT = 29; -const TAIL_WIDTH = 10; +const TOOLTIP_HEIGHT = 36; +const TOOLTIP_WIDTH = 40; const COMPONENT_HEIGHT = DIAMETER + TOOLTIP_HEIGHT + 10; -const styles = StyleSheet.create({ - root: { - position: 'relative', - justifyContent: 'center', - height: COMPONENT_HEIGHT, - }, - rootDisabled: { - opacity: 0.5, - }, - slider: { - position: 'absolute', - width: DIAMETER, - height: DIAMETER, - borderRadius: DIAMETER, - borderWidth: 1, - borderColor: colors.white, - bottom: 0, - shadowColor: colors.black, - shadowOffset: { - width: 0, - height: 0, +const createStyles = (colors) => + StyleSheet.create({ + root: { + position: 'relative', + justifyContent: 'center', + height: COMPONENT_HEIGHT, }, - shadowOpacity: 0.18, - shadowRadius: 14, - }, - trackBackContainer: { - position: 'absolute', - paddingHorizontal: DIAMETER / 2 - 2 * TRACK_PADDING, - bottom: DIAMETER / 2 - (TICK_DIAMETER + 2 * TRACK_PADDING) / 2, - }, - trackBack: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - height: TICK_DIAMETER + 2 * TRACK_PADDING, - backgroundColor: colors.blue000, - borderRadius: TICK_DIAMETER + 2 * TRACK_PADDING, - borderWidth: TRACK_PADDING, - borderColor: colors.blue000, - }, - tick: { - height: TICK_DIAMETER, - width: TICK_DIAMETER, - borderRadius: TICK_DIAMETER, - backgroundColor: colors.spinnerColor, - opacity: 0.5, - }, - trackFront: { - position: 'absolute', - overflow: 'hidden', - bottom: DIAMETER / 2 - (TICK_DIAMETER + 2 * TRACK_PADDING) / 2, - left: DIAMETER / 2 - 2 * TRACK_PADDING, - height: TICK_DIAMETER + 2 * TRACK_PADDING, - borderRadius: TICK_DIAMETER + 2 * TRACK_PADDING, - }, - tooltipContainer: { - position: 'absolute', - justifyContent: 'center', - alignItems: 'center', - backgroundColor: colors.grey700, - padding: 5, - borderRadius: 8, - minHeight: TOOLTIP_HEIGHT, - minWidth: 40, - top: 0, - }, - tooltipTail: { - position: 'absolute', - left: 0, - right: 0, - bottom: -5, - width: TAIL_WIDTH, - height: TAIL_WIDTH, - backgroundColor: colors.grey700, - transform: [{ rotate: '45deg' }], - }, - tooltipText: { - ...fontStyles.normal, - color: colors.white, - fontSize: 12, - }, -}); + rootDisabled: { + opacity: 0.5, + }, + slider: { + position: 'absolute', + width: DIAMETER, + height: DIAMETER, + borderRadius: DIAMETER, + borderWidth: 1, + borderColor: colors.background.default, + bottom: 0, + shadowColor: importedColors.black, + shadowOffset: { + width: 0, + height: 0, + }, + shadowOpacity: 0.18, + shadowRadius: 14, + }, + trackBackContainer: { + position: 'absolute', + paddingHorizontal: DIAMETER / 2 - 2 * TRACK_PADDING, + bottom: DIAMETER / 2 - (TICK_DIAMETER + 2 * TRACK_PADDING) / 2, + }, + trackBack: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + height: TICK_DIAMETER + 2 * TRACK_PADDING, + backgroundColor: colors.primary.muted, + borderRadius: TICK_DIAMETER + 2 * TRACK_PADDING, + borderWidth: TRACK_PADDING, + borderColor: colors.primary.muted, + }, + tick: { + height: TICK_DIAMETER, + width: TICK_DIAMETER, + borderRadius: TICK_DIAMETER, + backgroundColor: colors.primary.default, + opacity: 0.5, + }, + trackFront: { + position: 'absolute', + overflow: 'hidden', + bottom: DIAMETER / 2 - (TICK_DIAMETER + 2 * TRACK_PADDING) / 2, + left: DIAMETER / 2 - 2 * TRACK_PADDING, + height: TICK_DIAMETER + 2 * TRACK_PADDING, + borderRadius: TICK_DIAMETER + 2 * TRACK_PADDING, + }, + tooltipContainer: { + position: 'absolute', + justifyContent: 'center', + alignItems: 'center', + minHeight: TOOLTIP_HEIGHT, + minWidth: TOOLTIP_WIDTH, + top: 4, + }, + tooltipText: { + ...StyleSheet.absoluteFillObject, + textAlign: 'center', + ...fontStyles.normal, + color: colors.overlay.inverse, + paddingTop: 6, + fontSize: 12, + }, + }); const setAnimatedValue = (animatedValue, value) => animatedValue.setValue(value); const SlippageSlider = ({ range, increment, onChange, value, formatTooltipText, disabled, changeOnRelease }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); /* Reusable/truncated references to the range prop values */ const [r0, r1] = useMemo(() => range, [range]); const fullRange = useMemo(() => r1 - r0, [r0, r1]); @@ -107,7 +102,6 @@ const SlippageSlider = ({ range, increment, onChange, value, formatTooltipText, /* Layout State */ const [trackWidth, setTrackWidth] = useState(0); - const [tooltipWidth, setTooltipWidth] = useState(0); const [componentWidth, setComponentWidth] = useState(0); /* State */ @@ -126,7 +120,7 @@ const SlippageSlider = ({ range, increment, onChange, value, formatTooltipText, const sliderColor = sliderPosition.interpolate({ inputRange: [0, trackWidth], - outputRange: [colors.spinnerColor, colors.red], + outputRange: [colors.primary.default, colors.error.default], extrapolate: 'clamp', }); @@ -222,11 +216,17 @@ const SlippageSlider = ({ range, increment, onChange, value, formatTooltipText, setTooltipWidth(e.nativeEvent.layout.width)} > - + + + {formatTooltipText(displayValue)} { const { type } = this.props; - const { fontStyle, containerStyle } = getStyles(type); + const colors = this.context.colors || mockTheme.colors; + const { fontStyle, containerStyle } = getStyles(type, colors); const touchableProps = {}; const containerStyles = [ ...containerStyle, @@ -113,3 +115,5 @@ export default class StyledButton extends PureComponent { ); }; } + +StyledButton.contextType = ThemeContext; diff --git a/app/components/UI/StyledButton/index.ios.js b/app/components/UI/StyledButton/index.ios.js index 9ac6142e1b5..58d108610ab 100644 --- a/app/components/UI/StyledButton/index.ios.js +++ b/app/components/UI/StyledButton/index.ios.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { ViewPropTypes, Text } from 'react-native'; import Button from 'react-native-button'; import getStyles from './styledButtonStyles'; +import { ThemeContext, mockTheme } from '../../../util/theme'; /** * UI component that renders a styled button @@ -64,7 +65,8 @@ export default class StyledButton extends PureComponent { render = () => { const { type, onPress, onPressOut, style, children, disabled, styleDisabled, testID, disabledContainerStyle } = this.props; - const { fontStyle, containerStyle } = getStyles(type); + const colors = this.context.colors || mockTheme.colors; + const { fontStyle, containerStyle } = getStyles(type, colors); return ( + {this.renderSwitch()} + + {!!this.state.error && ( + + {this.state.error} + + )} + + + {this.state.loading ? ( + + ) : ( + strings('login.unlock_button') + )} + + + + + {strings('login.go_back')} + + - - - - - - ); + + + + + ); + }; } +Login.contextType = ThemeContext; + const mapStateToProps = (state) => ({ selectedAddress: state.engine.backgroundState.PreferencesController?.selectedAddress, initialScreen: state.user.initialScreen, diff --git a/app/components/Views/ManualBackupStep1/__snapshots__/index.test.tsx.snap b/app/components/Views/ManualBackupStep1/__snapshots__/index.test.tsx.snap index 6207a9e99ba..90e7a1da1d0 100644 --- a/app/components/Views/ManualBackupStep1/__snapshots__/index.test.tsx.snap +++ b/app/components/Views/ManualBackupStep1/__snapshots__/index.test.tsx.snap @@ -1,587 +1,26 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ManualBackupStep1 should render correctly 1`] = ` - - - - - - - - Write down your Secret Recovery Phrase - - - - This is your Secret Recovery Phrase. Write it down on a paper and keep it in a safe place. You'll be asked to re-enter this phrase (in order) on the next step. - - - - - - - 1. abstract - - - - - 2. accident - - - - - 3. acoustic - - - - - 4. announce - - - - - 5. artefact - - - - - 6. attitude - - - - - - - 7. bachelor - - - - - 8. broccoli - - - - - 9. business - - - - - 10. category - - - - - 11. champion - - - - - 12. cinnamon - - - - - - - - - Tap to reveal your Secret Recovery Phrase - - - Make sure no one is watching your screen. - - - - View - - - - - - - - +/> `; diff --git a/app/components/Views/ManualBackupStep1/index.js b/app/components/Views/ManualBackupStep1/index.js index aee704c8e96..fd065fdaa4d 100644 --- a/app/components/Views/ManualBackupStep1/index.js +++ b/app/components/Views/ManualBackupStep1/index.js @@ -8,10 +8,11 @@ import { InteractionManager, TextInput, KeyboardAvoidingView, - TouchableOpacity, + Appearance, } from 'react-native'; import PropTypes from 'prop-types'; -import { colors, fontStyles, baseStyles } from '../../../styles/common'; +import { connect } from 'react-redux'; +import { fontStyles, baseStyles } from '../../../styles/common'; import StyledButton from '../../UI/StyledButton'; import OnboardingProgress from '../../UI/OnboardingProgress'; import { strings } from '../../../../locales/i18n'; @@ -31,193 +32,192 @@ import { WRONG_PASSWORD_ERROR, } from '../../../constants/onboarding'; import AnalyticsV2 from '../../../util/analyticsV2'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - mainWrapper: { - backgroundColor: colors.white, - flex: 1, - }, - wrapper: { - flex: 1, - paddingHorizontal: 32, - }, - onBoardingWrapper: { - paddingHorizontal: 20, - }, - loader: { - backgroundColor: colors.white, - flex: 1, - minHeight: 300, - justifyContent: 'center', - alignItems: 'center', - }, - action: { - fontSize: 18, - marginVertical: 16, - color: colors.fontPrimary, - justifyContent: 'center', - textAlign: 'center', - ...fontStyles.bold, - }, - infoWrapper: { - marginBottom: 16, - justifyContent: 'center', - }, - info: { - fontSize: 14, - color: colors.fontPrimary, - textAlign: 'center', - ...fontStyles.normal, - paddingHorizontal: 6, - }, - seedPhraseConcealer: { - position: 'absolute', - width: '100%', - height: '100%', - backgroundColor: colors.grey700, - opacity: 0.7, - alignItems: 'center', - borderRadius: 8, - paddingHorizontal: 24, - paddingVertical: 45, - }, - touchableOpacity: { - position: 'absolute', - width: '100%', - height: '100%', - borderRadius: 8, - }, - blurView: { - position: 'absolute', - top: 0, - left: 0, - bottom: 0, - right: 0, - borderRadius: 8, - }, - icon: { - width: 24, - height: 24, - color: colors.white, - textAlign: 'center', - marginBottom: 32, - }, - reveal: { - fontSize: Device.isMediumDevice() ? 13 : 16, - ...fontStyles.bold, - color: colors.white, - lineHeight: 22, - marginBottom: 8, - textAlign: 'center', - }, - watching: { - fontSize: Device.isMediumDevice() ? 10 : 12, - color: colors.white, - lineHeight: 17, - marginBottom: 32, - textAlign: 'center', - }, - viewButtonContainer: { - width: 155, - padding: 12, - }, - seedPhraseWrapper: { - backgroundColor: colors.white, - borderRadius: 8, - flexDirection: 'row', - borderColor: colors.grey100, - borderWidth: 1, - marginBottom: 64, - minHeight: 275, - }, - wordColumn: { - flex: 1, - alignItems: 'center', - paddingHorizontal: Device.isMediumDevice() ? 18 : 24, - paddingVertical: 18, - justifyContent: 'space-between', - }, - wordWrapper: { - flexDirection: 'row', - }, - word: { - paddingHorizontal: 8, - paddingVertical: 6, - fontSize: 14, - color: colors.fontPrimary, - backgroundColor: colors.white, - borderColor: colors.blue, - borderWidth: 1, - borderRadius: 13, - textAlign: 'center', - textAlignVertical: 'center', - lineHeight: 14, - flex: 1, - }, - confirmPasswordWrapper: { - flex: 1, - padding: 30, - paddingTop: 0, - }, - passwordRequiredContent: { - marginBottom: 20, - }, - content: { - alignItems: 'flex-start', - }, - title: { - fontSize: 32, - marginTop: 20, - marginBottom: 10, - color: colors.fontPrimary, - justifyContent: 'center', - textAlign: 'left', - ...fontStyles.normal, - }, - text: { - marginBottom: 10, - marginTop: 20, - justifyContent: 'center', - }, - label: { - fontSize: 16, - lineHeight: 23, - color: colors.fontPrimary, - textAlign: 'left', - ...fontStyles.normal, - }, - buttonWrapper: { - flex: 1, - marginTop: 20, - justifyContent: 'flex-end', - }, - input: { - borderWidth: 2, - borderRadius: 5, - width: '100%', - borderColor: colors.grey000, - padding: 10, - height: 40, - }, - warningMessageText: { - paddingVertical: 10, - color: colors.red, - ...fontStyles.normal, - }, - keyboardAvoidingView: { - flex: 1, - flexDirection: 'row', - alignSelf: 'center', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + mainWrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + wrapper: { + flex: 1, + paddingHorizontal: 32, + }, + onBoardingWrapper: { + paddingHorizontal: 20, + }, + loader: { + backgroundColor: colors.background.default, + flex: 1, + minHeight: 300, + justifyContent: 'center', + alignItems: 'center', + }, + action: { + fontSize: 18, + marginVertical: 16, + color: colors.text.default, + justifyContent: 'center', + textAlign: 'center', + ...fontStyles.bold, + }, + infoWrapper: { + marginBottom: 16, + justifyContent: 'center', + }, + info: { + fontSize: 14, + color: colors.text.default, + textAlign: 'center', + ...fontStyles.normal, + paddingHorizontal: 6, + }, + seedPhraseConcealerContainer: { + position: 'absolute', + width: '100%', + height: '100%', + borderRadius: 8, + }, + seedPhraseConcealer: { + position: 'absolute', + width: '100%', + height: '100%', + backgroundColor: colors.overlay.alternative, + alignItems: 'center', + borderRadius: 8, + paddingHorizontal: 24, + paddingVertical: 45, + }, + blurView: { + position: 'absolute', + top: 0, + left: 0, + bottom: 0, + right: 0, + borderRadius: 8, + }, + icon: { + width: 24, + height: 24, + color: colors.overlay.inverse, + textAlign: 'center', + marginBottom: 32, + }, + reveal: { + fontSize: Device.isMediumDevice() ? 13 : 16, + ...fontStyles.bold, + color: colors.overlay.inverse, + lineHeight: 22, + marginBottom: 8, + textAlign: 'center', + }, + watching: { + fontSize: Device.isMediumDevice() ? 10 : 12, + color: colors.overlay.inverse, + lineHeight: 17, + marginBottom: 32, + textAlign: 'center', + }, + viewButtonContainer: { + width: 155, + padding: 12, + }, + seedPhraseWrapper: { + backgroundColor: colors.background.default, + borderRadius: 8, + flexDirection: 'row', + borderColor: colors.border.default, + borderWidth: 1, + marginBottom: 64, + minHeight: 275, + }, + wordColumn: { + flex: 1, + alignItems: 'center', + paddingHorizontal: Device.isMediumDevice() ? 18 : 24, + paddingVertical: 18, + justifyContent: 'space-between', + }, + wordWrapper: { + flexDirection: 'row', + }, + word: { + paddingHorizontal: 8, + paddingVertical: 6, + fontSize: 14, + color: colors.text.default, + backgroundColor: colors.background.default, + borderColor: colors.primary.default, + borderWidth: 1, + borderRadius: 13, + textAlign: 'center', + textAlignVertical: 'center', + lineHeight: 14, + flex: 1, + }, + confirmPasswordWrapper: { + flex: 1, + padding: 30, + paddingTop: 0, + }, + passwordRequiredContent: { + marginBottom: 20, + }, + content: { + alignItems: 'flex-start', + }, + title: { + fontSize: 32, + marginTop: 20, + marginBottom: 10, + color: colors.text.default, + justifyContent: 'center', + textAlign: 'left', + ...fontStyles.normal, + }, + text: { + marginBottom: 10, + marginTop: 20, + justifyContent: 'center', + }, + label: { + fontSize: 16, + lineHeight: 23, + color: colors.text.default, + textAlign: 'left', + ...fontStyles.normal, + }, + buttonWrapper: { + flex: 1, + marginTop: 20, + justifyContent: 'flex-end', + }, + input: { + borderWidth: 2, + borderRadius: 5, + width: '100%', + borderColor: colors.border.default, + padding: 10, + height: 40, + }, + warningMessageText: { + paddingVertical: 10, + color: colors.error.default, + ...fontStyles.normal, + }, + keyboardAvoidingView: { + flex: 1, + flexDirection: 'row', + alignSelf: 'center', + }, + }); /** * View that's shown during the second step of * the backup seed phrase flow */ -export default class ManualBackupStep1 extends PureComponent { - static navigationOptions = ({ navigation, route }) => getOnboardingNavbarOptions(navigation, route); - +class ManualBackupStep1 extends PureComponent { static propTypes = { /** /* navigation object required to push and pop other views @@ -227,6 +227,10 @@ export default class ManualBackupStep1 extends PureComponent { * Object that represents the current route info like params passed to it */ route: PropTypes.object, + /** + * Theme that app is set to + */ + appTheme: PropTypes.string, }; steps = MANUAL_BACKUP_STEPS; @@ -240,7 +244,14 @@ export default class ManualBackupStep1 extends PureComponent { view: SEED_PHRASE, }; + updateNavBar = () => { + const { route, navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions(getOnboardingNavbarOptions(route, {}, colors)); + }; + async componentDidMount() { + this.updateNavBar(); this.words = this.props.route.params?.words ?? []; if (!this.words.length) { @@ -259,6 +270,10 @@ export default class ManualBackupStep1 extends PureComponent { InteractionManager.runAfterInteractions(() => PreventScreenshot.forbid()); } + componentDidUpdate = () => { + this.updateNavBar(); + }; + onPasswordChange = (password) => { this.setState({ password }); }; @@ -303,37 +318,71 @@ export default class ManualBackupStep1 extends PureComponent { this.tryUnlockWithPassword(password); }; - renderLoader = () => ( - - - - ); + renderLoader = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + + + ); + }; + + getBlurType = () => { + const { appTheme } = this.props; + let blurType = 'light'; + switch (appTheme) { + case 'light': + blurType = 'light'; + break; + case 'dark': + blurType = 'dark'; + break; + case 'os': + blurType = Appearance.getColorScheme(); + break; + default: + blurType = 'light'; + } + return blurType; + }; + + renderSeedPhraseConcealer = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + const blurType = this.getBlurType(); - renderSeedPhraseConcealer = () => ( - - - - - - {strings('manual_backup_step_1.reveal')} - {strings('manual_backup_step_1.watching')} - - - {strings('manual_backup_step_1.view')} - + return ( + + + + + + {strings('manual_backup_step_1.reveal')} + {strings('manual_backup_step_1.watching')} + + + {strings('manual_backup_step_1.view')} + + - - - ); + + ); + }; renderConfirmPassword() { const { warningIncorrectPassword } = this.state; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance || 'light'; + const styles = createStyles(colors); + return ( @@ -346,11 +395,12 @@ export default class ManualBackupStep1 extends PureComponent { {warningIncorrectPassword && ( {warningIncorrectPassword} @@ -376,6 +426,9 @@ export default class ManualBackupStep1 extends PureComponent { const words = this.words || []; const wordLength = words.length; const half = wordLength / 2 || 6; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -425,3 +481,11 @@ export default class ManualBackupStep1 extends PureComponent { ); } } + +const mapStateToProps = (state) => ({ + appTheme: state.user.appTheme, +}); + +ManualBackupStep1.contextType = ThemeContext; + +export default connect(mapStateToProps)(ManualBackupStep1); diff --git a/app/components/Views/ManualBackupStep1/index.test.tsx b/app/components/Views/ManualBackupStep1/index.test.tsx index 3da4a404d90..ce2665a5023 100644 --- a/app/components/Views/ManualBackupStep1/index.test.tsx +++ b/app/components/Views/ManualBackupStep1/index.test.tsx @@ -1,30 +1,41 @@ import React from 'react'; import { shallow } from 'enzyme'; +import { Provider } from 'react-redux'; +import configureMockStore from 'redux-mock-store'; import ManualBackupStep1 from './'; +import { AppThemeKey } from '../../../util/theme/models'; + +const mockStore = configureMockStore(); +const initialState = { + user: { appTheme: AppThemeKey.light }, +}; +const store = mockStore(initialState); describe('ManualBackupStep1', () => { it('should render correctly', () => { const wrapper = shallow( - + + + ); expect(wrapper).toMatchSnapshot(); }); diff --git a/app/components/Views/ManualBackupStep2/index.js b/app/components/Views/ManualBackupStep2/index.js index 020810438dd..f2fa7fe9b9c 100644 --- a/app/components/Views/ManualBackupStep2/index.js +++ b/app/components/Views/ManualBackupStep2/index.js @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import { InteractionManager, Alert, Text, TouchableOpacity, View, SafeAreaView, StyleSheet } from 'react-native'; import PropTypes from 'prop-types'; import OnboardingProgress from '../../UI/OnboardingProgress'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import ActionView from '../../UI/ActionView'; import { strings } from '../../../../locales/i18n'; import { connect } from 'react-redux'; @@ -11,147 +11,150 @@ import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'; import Device from '../../../util/device'; import { getOnboardingNavbarOptions } from '../../UI/Navbar'; import AnalyticsV2 from '../../../util/analyticsV2'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - mainWrapper: { - backgroundColor: colors.white, - flex: 1, - }, - wrapper: { - flex: 1, - paddingHorizontal: 32, - }, - onBoardingWrapper: { - paddingHorizontal: 20, - }, - action: { - fontSize: 18, - marginBottom: 16, - color: colors.fontPrimary, - justifyContent: 'center', - textAlign: 'center', - ...fontStyles.bold, - }, - infoWrapper: { - marginBottom: 16, - justifyContent: 'center', - }, - info: { - fontSize: 16, - color: colors.fontPrimary, - textAlign: 'center', - ...fontStyles.normal, - paddingHorizontal: 6, - }, - seedPhraseWrapper: { - backgroundColor: colors.white, - borderRadius: 8, - flexDirection: 'row', - justifyContent: 'space-between', - borderColor: colors.grey100, - borderWidth: 1, - marginBottom: 24, - }, - seedPhraseWrapperComplete: { - borderColor: colors.green500, - }, - seedPhraseWrapperError: { - borderColor: colors.red, - }, - colLeft: { - paddingTop: 18, - paddingLeft: 27, - paddingBottom: 4, - alignItems: 'flex-start', - }, - colRight: { - paddingTop: 18, - paddingRight: 27, - paddingBottom: 4, - alignItems: 'flex-end', - }, - wordBoxWrapper: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 14, - }, - wordWrapper: { - paddingHorizontal: 8, - paddingVertical: 6, - width: Device.isMediumDevice() ? 75 : 95, - backgroundColor: colors.white, - borderColor: colors.grey050, - borderWidth: 1, - borderRadius: 34, - borderStyle: 'dashed', - marginLeft: 4, - }, - word: { - fontSize: 14, - color: colors.fontPrimary, - lineHeight: 14, - textAlign: 'center', - }, - selectableWord: { - paddingHorizontal: 8, - paddingVertical: 6, - color: colors.fontPrimary, - width: 95, - backgroundColor: colors.white, - borderColor: colors.blue, - borderWidth: 1, - marginBottom: 6, - borderRadius: 13, - textAlign: 'center', - }, - selectableWordText: { - textAlign: 'center', - fontSize: 14, - lineHeight: 14, - color: colors.black, - }, - words: { - flexDirection: 'row', - flexWrap: 'wrap', - justifyContent: Device.isMediumDevice() ? 'space-around' : 'space-between', - }, - successRow: { - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - }, - successText: { - fontSize: 12, - color: colors.green500, - marginLeft: 4, - }, - selectedWord: { - backgroundColor: colors.grey400, - borderWidth: 1, - borderColor: colors.grey400, - }, - selectedWordText: { - color: colors.white, - }, - currentWord: { - borderWidth: 1, - borderColor: colors.blue, - }, - confirmedWord: { - borderWidth: 1, - borderColor: colors.blue, - borderStyle: 'solid', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + mainWrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + wrapper: { + flex: 1, + paddingHorizontal: 32, + }, + onBoardingWrapper: { + paddingHorizontal: 20, + }, + action: { + fontSize: 18, + marginBottom: 16, + color: colors.text.default, + justifyContent: 'center', + textAlign: 'center', + ...fontStyles.bold, + }, + infoWrapper: { + marginBottom: 16, + justifyContent: 'center', + }, + info: { + fontSize: 16, + color: colors.text.default, + textAlign: 'center', + ...fontStyles.normal, + paddingHorizontal: 6, + }, + seedPhraseWrapper: { + backgroundColor: colors.background.default, + borderRadius: 8, + flexDirection: 'row', + justifyContent: 'space-between', + borderColor: colors.border.default, + borderWidth: 1, + marginBottom: 24, + }, + seedPhraseWrapperComplete: { + borderColor: colors.success.default, + }, + seedPhraseWrapperError: { + borderColor: colors.error.default, + }, + colLeft: { + paddingTop: 18, + paddingLeft: 27, + paddingBottom: 4, + alignItems: 'flex-start', + }, + colRight: { + paddingTop: 18, + paddingRight: 27, + paddingBottom: 4, + alignItems: 'flex-end', + }, + wordBoxWrapper: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 14, + }, + wordWrapper: { + paddingHorizontal: 8, + paddingVertical: 6, + width: Device.isMediumDevice() ? 75 : 95, + backgroundColor: colors.background.default, + borderColor: colors.border.default, + borderWidth: 1, + borderRadius: 34, + borderStyle: 'dashed', + marginLeft: 4, + }, + word: { + fontSize: 14, + color: colors.text.default, + lineHeight: 14, + textAlign: 'center', + }, + selectableWord: { + paddingHorizontal: 8, + paddingVertical: 6, + color: colors.text.default, + width: 95, + backgroundColor: colors.background.default, + borderColor: colors.primary.default, + borderWidth: 1, + marginBottom: 6, + borderRadius: 13, + textAlign: 'center', + }, + selectableWordText: { + textAlign: 'center', + fontSize: 14, + lineHeight: 14, + color: colors.text.default, + }, + words: { + flexDirection: 'row', + flexWrap: 'wrap', + justifyContent: Device.isMediumDevice() ? 'space-around' : 'space-between', + }, + successRow: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + }, + successText: { + fontSize: 12, + color: colors.success.default, + marginLeft: 4, + }, + selectedWord: { + backgroundColor: colors.icon.muted, + borderWidth: 1, + borderColor: colors.icon.muted, + }, + selectedWordText: { + color: colors.text.default, + }, + currentWord: { + borderWidth: 1, + borderColor: colors.primary.default, + }, + confirmedWord: { + borderWidth: 1, + borderColor: colors.primary.default, + borderStyle: 'solid', + }, + wordBoxIndex: { + color: colors.text.default, + }, + }); /** * View that's shown during the fifth step of * the backup seed phrase flow */ class ManualBackupStep2 extends PureComponent { - static navigationOptions = ({ navigation, route }) => getOnboardingNavbarOptions(navigation, route); - static propTypes = { /** /* navigation object required to push and pop other views @@ -187,6 +190,12 @@ class ManualBackupStep2 extends PureComponent { currentStep: 2, }; + updateNavBar = () => { + const { route, navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions(getOnboardingNavbarOptions(route, {}, colors)); + }; + componentDidMount = () => { const { route } = this.props; const words = route.params?.words ?? []; @@ -198,6 +207,10 @@ class ManualBackupStep2 extends PureComponent { ); }; + componentDidUpdate = () => { + this.updateNavBar(); + }; + createWordsDictionary = () => { const dict = {}; this.words.forEach((word, i) => { @@ -277,6 +290,9 @@ class ManualBackupStep2 extends PureComponent { renderWords = () => { const { wordsDict } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( {Object.keys(wordsDict).map((key, i) => this.renderWordSelectableBox(key, i))} @@ -284,18 +300,26 @@ class ManualBackupStep2 extends PureComponent { ); }; - renderSuccess = () => ( - - - {strings('manual_backup_step_2.success')} - - ); + renderSuccess = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + + {strings('manual_backup_step_2.success')} + + ); + }; renderWordBox = (word, i) => { const { currentIndex, confirmedWords } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( - {i + 1}. + {i + 1}. { @@ -317,6 +341,9 @@ class ManualBackupStep2 extends PureComponent { const { wordsDict } = this.state; const [word] = key.split(','); const selected = wordsDict[key].currentPosition !== undefined; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -374,6 +404,8 @@ class ManualBackupStep2 extends PureComponent { }; } +ManualBackupStep2.contextType = ThemeContext; + const mapDispatchToProps = (dispatch) => ({ seedphraseBackedUp: () => dispatch(seedphraseBackedUp()), }); diff --git a/app/components/Views/ManualBackupStep3/index.js b/app/components/Views/ManualBackupStep3/index.js index d26adb0db9e..f3a3662c797 100644 --- a/app/components/Views/ManualBackupStep3/index.js +++ b/app/components/Views/ManualBackupStep3/index.js @@ -11,7 +11,7 @@ import { } from 'react-native'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import Emoji from 'react-native-emoji'; import AsyncStorage from '@react-native-community/async-storage'; import OnboardingProgress from '../../UI/OnboardingProgress'; @@ -26,55 +26,57 @@ import { getTransparentOnboardingNavbarOptions } from '../../UI/Navbar'; import { ONBOARDING_WIZARD, SEED_PHRASE_HINTS } from '../../../constants/storage'; import AnalyticsV2 from '../../../util/analyticsV2'; import DefaultPreference from 'react-native-default-preference'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - mainWrapper: { - backgroundColor: colors.white, - flex: 1, - }, - actionView: { - paddingTop: 40, - }, - wrapper: { - flex: 1, - paddingHorizontal: 50, - }, - onBoardingWrapper: { - paddingHorizontal: 20, - }, - congratulations: { - fontSize: Device.isMediumDevice() ? 28 : 32, - marginBottom: 12, - color: colors.fontPrimary, - justifyContent: 'center', - textAlign: 'center', - ...fontStyles.bold, - }, - baseText: { - fontSize: 16, - color: colors.fontPrimary, - textAlign: 'center', - ...fontStyles.normal, - }, - successText: { - marginBottom: 32, - }, - hintText: { - marginBottom: 26, - color: colors.blue, - }, - learnText: { - color: colors.blue, - }, - recoverText: { - marginBottom: 26, - }, - emoji: { - textAlign: 'center', - fontSize: 65, - marginBottom: 16, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + mainWrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + actionView: { + paddingTop: 40, + }, + wrapper: { + flex: 1, + paddingHorizontal: 50, + }, + onBoardingWrapper: { + paddingHorizontal: 20, + }, + congratulations: { + fontSize: Device.isMediumDevice() ? 28 : 32, + marginBottom: 12, + color: colors.text.default, + justifyContent: 'center', + textAlign: 'center', + ...fontStyles.bold, + }, + baseText: { + fontSize: 16, + color: colors.text.default, + textAlign: 'center', + ...fontStyles.normal, + }, + successText: { + marginBottom: 32, + }, + hintText: { + marginBottom: 26, + color: colors.primary.default, + }, + learnText: { + color: colors.primary.default, + }, + recoverText: { + marginBottom: 26, + }, + emoji: { + textAlign: 'center', + fontSize: 65, + marginBottom: 16, + }, + }); const hardwareBackPress = () => ({}); const HARDWARE_BACK_PRESS = 'hardwareBackPress'; @@ -84,8 +86,6 @@ const HARDWARE_BACK_PRESS = 'hardwareBackPress'; * the backup seed phrase flow */ class ManualBackupStep3 extends PureComponent { - static navigationOptions = ({ navigation }) => getTransparentOnboardingNavbarOptions(navigation); - constructor(props) { super(props); this.steps = props.route.params?.steps; @@ -108,11 +108,18 @@ class ManualBackupStep3 extends PureComponent { route: PropTypes.object, }; + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions(getTransparentOnboardingNavbarOptions(colors)); + }; + componentWillUnmount = () => { BackHandler.removeEventListener(HARDWARE_BACK_PRESS, hardwareBackPress); }; componentDidMount = async () => { + this.updateNavBar(); const currentSeedphraseHints = await AsyncStorage.getItem(SEED_PHRASE_HINTS); const parsedHints = currentSeedphraseHints && JSON.parse(currentSeedphraseHints); const manualBackup = parsedHints?.manualBackup; @@ -125,6 +132,10 @@ class ManualBackupStep3 extends PureComponent { BackHandler.addEventListener(HARDWARE_BACK_PRESS, hardwareBackPress); }; + componentDidUpdate = () => { + this.updateNavBar(); + }; + toggleHint = () => { this.setState((state) => ({ showHint: !state.showHint })); }; @@ -189,6 +200,9 @@ class ManualBackupStep3 extends PureComponent { }; render() { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -233,6 +247,8 @@ class ManualBackupStep3 extends PureComponent { } } +ManualBackupStep3.contextType = ThemeContext; + const mapDispatchToProps = (dispatch) => ({ showAlert: (config) => dispatch(showAlert(config)), }); diff --git a/app/components/Views/MediaPlayer/AndroidMediaPlayer.js b/app/components/Views/MediaPlayer/AndroidMediaPlayer.js index bd268518a5b..5cf6a623779 100644 --- a/app/components/Views/MediaPlayer/AndroidMediaPlayer.js +++ b/app/components/Views/MediaPlayer/AndroidMediaPlayer.js @@ -16,131 +16,133 @@ import { } from 'react-native'; import FA5Icon from 'react-native-vector-icons/FontAwesome5'; import AntIcon from 'react-native-vector-icons/AntDesign'; -import { baseStyles, colors } from '../../../styles/common'; - -const styles = StyleSheet.create({ - playerContainer: { - flex: 0, - overflow: 'hidden', - zIndex: 99999, - elevation: 99999, - }, - playerVideo: { - flex: 1, - overflow: 'hidden', - position: 'absolute', - top: 0, - right: 0, - bottom: 0, - left: 0, - backgroundColor: colors.black, - borderRadius: 12, - }, - errorContainer: { - top: 0, - right: 0, - bottom: 0, - left: 0, - justifyContent: 'center', - alignItems: 'center', - }, - errorIcon: { - marginBottom: 16, - }, - errorText: {}, - loaderContainer: { - top: 0, - right: 0, - bottom: 0, - left: 0, - alignItems: 'center', - justifyContent: 'center', - }, - controlsRow: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - }, - controlsColumn: { - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'space-between', - }, - controlsControl: { - padding: 14, - }, - controlsTop: { - flex: 1, - justifyContent: 'flex-start', - padding: 4, - }, - controlsBottom: { - flex: 1, - justifyContent: 'flex-end', - padding: 4, - }, - controlsTopControlGroup: { - alignSelf: 'flex-end', - alignItems: 'center', - justifyContent: 'space-between', - }, - controlsBottomControlGroup: { - alignSelf: 'stretch', - alignItems: 'center', - justifyContent: 'space-between', - }, - controlsPlayPause: { - left: 1, - }, - controlsMuteUnmute: { - left: -1, - top: -1, - width: '110%', - }, - seekbarContainer: { - alignSelf: 'stretch', - height: 44, - marginLeft: 20, - marginRight: 20, - }, - seekbarTrack: { - height: 1, - position: 'relative', - top: 20, - width: '100%', - }, - seekbarFill: { - height: 4, - width: '100%', - borderRadius: 2, - backgroundColor: colors.white, - }, - seekbarPermanentFill: { - width: '100%', - backgroundColor: colors.grey400, - }, - seekbarHandle: { - marginLeft: -10, - height: 28, - width: 28, - }, - seekbarCircle: { - borderRadius: 14, - top: 14, - height: 14, - width: 14, - }, - actionButton: { - width: 44, - height: 44, - backgroundColor: colors.greytransparent100, - borderRadius: 8, - }, - actionSeeker: { - flex: 1, - marginHorizontal: 8, - }, -}); +import { baseStyles, colors as importedColors } from '../../../styles/common'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; + +const createStyles = (colors) => + StyleSheet.create({ + playerContainer: { + flex: 0, + overflow: 'hidden', + zIndex: 99999, + elevation: 99999, + }, + playerVideo: { + flex: 1, + overflow: 'hidden', + position: 'absolute', + top: 0, + right: 0, + bottom: 0, + left: 0, + backgroundColor: colors.background.alternative, + borderRadius: 12, + }, + errorContainer: { + top: 0, + right: 0, + bottom: 0, + left: 0, + justifyContent: 'center', + alignItems: 'center', + }, + errorIcon: { + marginBottom: 16, + }, + errorText: {}, + loaderContainer: { + top: 0, + right: 0, + bottom: 0, + left: 0, + alignItems: 'center', + justifyContent: 'center', + }, + controlsRow: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + }, + controlsColumn: { + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'space-between', + }, + controlsControl: { + padding: 14, + }, + controlsTop: { + flex: 1, + justifyContent: 'flex-start', + padding: 4, + }, + controlsBottom: { + flex: 1, + justifyContent: 'flex-end', + padding: 4, + }, + controlsTopControlGroup: { + alignSelf: 'flex-end', + alignItems: 'center', + justifyContent: 'space-between', + }, + controlsBottomControlGroup: { + alignSelf: 'stretch', + alignItems: 'center', + justifyContent: 'space-between', + }, + controlsPlayPause: { + left: 1, + }, + controlsMuteUnmute: { + left: -1, + top: -1, + width: '110%', + }, + seekbarContainer: { + alignSelf: 'stretch', + height: 44, + marginLeft: 20, + marginRight: 20, + }, + seekbarTrack: { + height: 1, + position: 'relative', + top: 20, + width: '100%', + }, + seekbarFill: { + height: 4, + width: '100%', + borderRadius: 2, + backgroundColor: importedColors.white, + }, + seekbarPermanentFill: { + width: '100%', + backgroundColor: importedColors.blackTransparent, + }, + seekbarHandle: { + marginLeft: -10, + height: 28, + width: 28, + }, + seekbarCircle: { + borderRadius: 14, + top: 14, + height: 14, + width: 14, + }, + actionButton: { + width: 44, + height: 44, + backgroundColor: importedColors.blackTransparent, + borderRadius: 8, + }, + actionSeeker: { + flex: 1, + marginHorizontal: 8, + }, + }); export default function VideoPlayer({ controlsAnimationTiming, @@ -173,6 +175,9 @@ export default function VideoPlayer({ const controlsTimeout = useRef(); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + const animations = { bottomControl: { marginBottom: useRef(new Animated.Value(0)).current, @@ -405,20 +410,23 @@ export default function VideoPlayer({ ] ); - const renderControl = (children, callback, style = {}) => ( - - {children} - + const renderControl = useCallback( + (children, callback, style = {}) => ( + + {children} + + ), + [styles] ); const renderMuteUnmuteControl = useCallback( () => renderControl( - , + , toggleMuted, styles.controlsMuteUnmute ), - [muted, toggleMuted] + [muted, toggleMuted, styles, renderControl] ); const onLayoutSeekerWidth = useCallback((event) => setSeekerWidth(event.nativeEvent.layout.width), []); @@ -444,21 +452,24 @@ export default function VideoPlayer({ - + ), - [seekerPosition, seekPanResponder.panHandlers, seekerFillWidth, onLayoutSeekerWidth] + [seekerPosition, seekPanResponder.panHandlers, seekerFillWidth, onLayoutSeekerWidth, styles] ); const renderPlayPause = useCallback( () => renderControl( - , + , togglePlayPause, styles.controlsPlayPause ), - [paused, togglePlayPause] + [paused, togglePlayPause, styles, renderControl] ); const renderLoader = useCallback(() => { @@ -479,7 +490,7 @@ export default function VideoPlayer({ /> ); - }, [loading, animations.loader.rotate]); + }, [loading, animations.loader.rotate, styles]); const renderError = () => { if (!error) return; @@ -494,8 +505,8 @@ export default function VideoPlayer({ }; const renderClose = useCallback( - () => renderControl(, onClose, {}), - [onClose] + () => renderControl(, onClose, {}), + [onClose, renderControl] ); const renderTopControls = () => ( diff --git a/app/components/Views/MediaPlayer/Loader.js b/app/components/Views/MediaPlayer/Loader.js index a8ab5e827ec..0afca582079 100644 --- a/app/components/Views/MediaPlayer/Loader.js +++ b/app/components/Views/MediaPlayer/Loader.js @@ -1,50 +1,55 @@ import React from 'react'; import PropTypes from 'prop-types'; import { View, StyleSheet, ActivityIndicator, TouchableOpacity } from 'react-native'; -import { colors } from '../../../styles/common'; import Text from '../../Base/Text'; import FA5Icon from 'react-native-vector-icons/FontAwesome5'; import AntIcon from 'react-native-vector-icons/AntDesign'; import { strings } from '../../../../locales/i18n'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - container: { - flex: 1, - borderRadius: 12, - backgroundColor: colors.grey100, - }, - content: { - flex: 1, - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - }, - item: { - marginVertical: 5, - }, - text: { - fontSize: 16, - }, - closeButton: { - alignSelf: 'flex-end', - padding: 14, - width: 44, - height: 44, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + container: { + flex: 1, + borderRadius: 12, + backgroundColor: colors.background.default, + }, + content: { + flex: 1, + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + }, + item: { + marginVertical: 5, + }, + text: { + fontSize: 16, + color: colors.text.default, + }, + closeButton: { + alignSelf: 'flex-end', + padding: 14, + width: 44, + height: 44, + }, + }); function Loader({ error, onClose }) { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ( - + {error ? ( - + ) : ( - + )} diff --git a/app/components/Views/OfflineMode/index.js b/app/components/Views/OfflineMode/index.js index 52b6dd53612..7ebc22b24a8 100644 --- a/app/components/Views/OfflineMode/index.js +++ b/app/components/Views/OfflineMode/index.js @@ -3,7 +3,7 @@ import React from 'react'; import { SafeAreaView, Image, View, StyleSheet } from 'react-native'; import Text from '../../Base/Text'; import NetInfo from '@react-native-community/netinfo'; -import { baseStyles, colors, fontStyles } from '../../../styles/common'; +import { baseStyles, fontStyles } from '../../../styles/common'; import PropTypes from 'prop-types'; import { strings } from '../../../../locales/i18n'; import StyledButton from '../../UI/StyledButton'; @@ -13,42 +13,48 @@ import Device from '../../../util/device'; import AppConstants from '../../../core/AppConstants'; import { connect } from 'react-redux'; import { getInfuraBlockedSelector } from '../../../reducers/infuraAvailability'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - container: { - flex: 1, - }, - frame: { - width: 200, - height: 200, - alignSelf: 'center', - marginTop: 60, - }, - content: { - flex: 1, - marginHorizontal: 18, - justifyContent: 'center', - marginVertical: 30, - }, - title: { - fontSize: 18, - color: colors.fontPrimary, - marginBottom: 10, - ...fontStyles.bold, - }, - text: { - fontSize: 12, - color: colors.fontPrimary, - ...fontStyles.normal, - }, - buttonContainer: { - marginHorizontal: 18, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + container: { + flex: 1, + backgroundColor: colors.background.default, + }, + frame: { + width: 200, + height: 200, + alignSelf: 'center', + marginTop: 60, + }, + content: { + flex: 1, + marginHorizontal: 18, + justifyContent: 'center', + marginVertical: 30, + }, + title: { + fontSize: 18, + color: colors.text.default, + marginBottom: 10, + ...fontStyles.bold, + }, + text: { + fontSize: 12, + color: colors.text.default, + ...fontStyles.normal, + }, + buttonContainer: { + marginHorizontal: 18, + }, + }); const astronautImage = require('../../../images/astronaut.png'); // eslint-disable-line import/no-commonjs const OfflineMode = ({ navigation, infuraBlocked }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + const netinfo = NetInfo.useNetInfo(); const tryAgain = () => { diff --git a/app/components/Views/Onboarding/index.js b/app/components/Views/Onboarding/index.js index 16ae2931bd1..ae6de193636 100644 --- a/app/components/Views/Onboarding/index.js +++ b/app/components/Views/Onboarding/index.js @@ -13,7 +13,7 @@ import { } from 'react-native'; import AsyncStorage from '@react-native-community/async-storage'; import StyledButton from '../../UI/StyledButton'; -import { colors, fontStyles, baseStyles } from '../../../styles/common'; +import { fontStyles, baseStyles, colors as importedColors } from '../../../styles/common'; import OnboardingScreenWithBg from '../../UI/OnboardingScreenWithBg'; import { strings } from '../../../../locales/i18n'; import Button from 'react-native-button'; @@ -30,112 +30,109 @@ import BaseNotification from '../../UI/Notification/BaseNotification'; import Animated, { EasingNode } from 'react-native-reanimated'; import ElevatedView from 'react-native-elevated-view'; import { loadingSet, loadingUnset } from '../../../actions/user'; -import AnimatedFox from 'react-native-animated-fox'; import PreventScreenshot from '../../../core/PreventScreenshot'; import WarningExistingUserModal from '../../UI/WarningExistingUserModal'; import { PREVIOUS_SCREEN, ONBOARDING } from '../../../constants/navigation'; import { EXISTING_USER, METRICS_OPT_IN } from '../../../constants/storage'; import AnalyticsV2 from '../../../util/analyticsV2'; import DefaultPreference from 'react-native-default-preference'; +import { ThemeContext, mockTheme } from '../../../util/theme'; +import AnimatedFox from 'react-native-animated-fox'; const PUB_KEY = process.env.MM_PUBNUB_PUB_KEY; -const styles = StyleSheet.create({ - scroll: { - flex: 1, - }, - wrapper: { - flex: 1, - alignItems: 'center', - paddingVertical: 30, - }, - foxWrapper: { - width: Device.isIos() ? 90 : 45, - height: Device.isIos() ? 90 : 45, - marginVertical: 20, - }, - image: { - alignSelf: 'center', - width: Device.isIos() ? 90 : 45, - height: Device.isIos() ? 90 : 45, - }, - termsAndConditions: { - paddingBottom: 30, - }, - title: { - fontSize: 24, - color: colors.fontPrimary, - ...fontStyles.bold, - textAlign: 'center', - }, - ctas: { - flex: 1, - position: 'relative', - }, - footer: { - marginTop: -20, - marginBottom: 20, - }, - login: { - fontSize: 18, - color: colors.blue, - ...fontStyles.normal, - }, - buttonDescription: { - ...fontStyles.normal, - fontSize: 14, - textAlign: 'center', - marginBottom: 16, - color: colors.fontPrimary, - lineHeight: 20, - }, - importWrapper: { - marginVertical: 24, - }, - createWrapper: { - flex: 1, - justifyContent: 'flex-end', - marginBottom: 24, - }, - buttonWrapper: { - marginBottom: 16, - }, - loader: { - marginTop: 180, - justifyContent: 'center', - textAlign: 'center', - }, - loadingText: { - marginTop: 30, - fontSize: 14, - textAlign: 'center', - color: colors.fontPrimary, - ...fontStyles.normal, - }, - modalTypeView: { - position: 'absolute', - bottom: 0, - paddingBottom: Device.isIphoneX() ? 20 : 10, - left: 0, - right: 0, - backgroundColor: colors.transparent, - }, - notificationContainer: { - flex: 0.1, - flexDirection: 'row', - alignItems: 'flex-end', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + scroll: { + flex: 1, + }, + wrapper: { + flex: 1, + alignItems: 'center', + paddingVertical: 30, + }, + foxWrapper: { + width: Device.isIos() ? 90 : 45, + height: Device.isIos() ? 90 : 45, + marginVertical: 20, + }, + image: { + alignSelf: 'center', + width: Device.isIos() ? 90 : 45, + height: Device.isIos() ? 90 : 45, + }, + termsAndConditions: { + paddingBottom: 30, + }, + title: { + fontSize: 24, + color: colors.text.default, + ...fontStyles.bold, + textAlign: 'center', + }, + ctas: { + flex: 1, + position: 'relative', + }, + footer: { + marginTop: -20, + marginBottom: 20, + }, + login: { + fontSize: 18, + color: colors.primary.default, + ...fontStyles.normal, + }, + buttonDescription: { + ...fontStyles.normal, + fontSize: 14, + textAlign: 'center', + marginBottom: 16, + color: colors.text.default, + lineHeight: 20, + }, + importWrapper: { + marginVertical: 24, + }, + createWrapper: { + flex: 1, + justifyContent: 'flex-end', + marginBottom: 24, + }, + buttonWrapper: { + marginBottom: 16, + }, + loader: { + marginTop: 180, + justifyContent: 'center', + textAlign: 'center', + }, + loadingText: { + marginTop: 30, + fontSize: 14, + textAlign: 'center', + color: colors.text.default, + ...fontStyles.normal, + }, + modalTypeView: { + position: 'absolute', + bottom: 0, + paddingBottom: Device.isIphoneX() ? 20 : 10, + left: 0, + right: 0, + backgroundColor: importedColors.transparent, + }, + notificationContainer: { + flex: 0.1, + flexDirection: 'row', + alignItems: 'flex-end', + }, + }); /** * View that is displayed to first time (new) users */ class Onboarding extends PureComponent { - static navigationOptions = ({ navigation, route }) => - route.params?.delete - ? getTransparentOnboardingNavbarOptions(navigation) - : getTransparentBackOnboardingNavbarOptions(navigation); - static propTypes = { /** * The navigator object @@ -217,7 +214,18 @@ class Onboarding extends PureComponent { BackHandler.addEventListener('hardwareBackPress', hardwareBackPress); }; + updateNavBar = () => { + const { route, navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + route.params?.delete + ? getTransparentOnboardingNavbarOptions(colors) + : getTransparentBackOnboardingNavbarOptions(colors) + ); + }; + componentDidMount() { + this.updateNavBar(); this.mounted = true; this.checkIfExistingUser(); InteractionManager.runAfterInteractions(() => { @@ -239,6 +247,10 @@ class Onboarding extends PureComponent { InteractionManager.runAfterInteractions(PreventScreenshot.allow); } + componentDidUpdate = () => { + this.updateNavBar(); + }; + async checkIfExistingUser() { const existingUser = await AsyncStorage.getItem(EXISTING_USER); if (existingUser !== null) { @@ -368,16 +380,24 @@ class Onboarding extends PureComponent { this.setState({ warningModalVisible: !warningModalVisible }); }; - renderLoader = () => ( - - - - {this.props.loadingMsg} + renderLoader = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + + + {this.props.loadingMsg} + - - ); + ); + }; renderContent() { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -410,12 +430,7 @@ class Onboarding extends PureComponent { )} - + {strings('onboarding.start_exploring_now')} @@ -425,6 +440,9 @@ class Onboarding extends PureComponent { } handleSimpleNotification = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + if (!this.props.route.params?.delete) return; return ( @@ -459,7 +479,7 @@ class Onboarding extends PureComponent { resizeMethod={'auto'} /> ) : ( - + )} )} @@ -492,6 +512,8 @@ class Onboarding extends PureComponent { } } +Onboarding.contextType = ThemeContext; + const mapStateToProps = (state) => ({ accounts: state.engine.backgroundState.AccountTrackerController.accounts, passwordSet: state.user.passwordSet, diff --git a/app/components/Views/OnboardingCarousel/index.js b/app/components/Views/OnboardingCarousel/index.js index 2fc5c9753e3..6f1039c398b 100644 --- a/app/components/Views/OnboardingCarousel/index.js +++ b/app/components/Views/OnboardingCarousel/index.js @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { Text, View, ScrollView, StyleSheet, Image, Dimensions, InteractionManager } from 'react-native'; import StyledButton from '../../UI/StyledButton'; -import { colors, fontStyles, baseStyles } from '../../../styles/common'; +import { fontStyles, baseStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import FadeOutOverlay from '../../UI/FadeOutOverlay'; import ScrollableTabView from 'react-native-scrollable-tab-view'; @@ -14,6 +14,7 @@ import { connect } from 'react-redux'; import AnalyticsV2, { ANALYTICS_EVENTS_V2 } from '../../../util/analyticsV2'; import DefaultPreference from 'react-native-default-preference'; import { METRICS_OPT_IN } from '../../../constants/storage'; +import { ThemeContext, mockTheme } from '../../../util/theme'; const IMAGE_3_RATIO = 215 / 315; const IMAGE_2_RATIO = 222 / 239; @@ -22,83 +23,84 @@ const DEVICE_WIDTH = Dimensions.get('window').width; const IMG_PADDING = Device.isIphoneX() ? 100 : Device.isIphone5S() ? 180 : 220; -const styles = StyleSheet.create({ - scroll: { - flexGrow: 1, - }, - wrapper: { - paddingVertical: 30, - flex: 1, - }, - title: { - fontSize: 24, - marginBottom: 12, - color: colors.fontPrimary, - justifyContent: 'center', - textAlign: 'center', - ...fontStyles.bold, - }, - subtitle: { - fontSize: 14, - lineHeight: 19, - marginTop: 12, - marginBottom: 25, - color: colors.grey500, - justifyContent: 'center', - textAlign: 'center', - ...fontStyles.normal, - }, - ctas: { - paddingHorizontal: 40, - paddingBottom: Device.isIphoneX() ? 40 : 20, - flexDirection: 'column', - }, - ctaWrapper: { - justifyContent: 'flex-end', - }, - carouselImage: {}, - // eslint-disable-next-line react-native/no-unused-styles - carouselImage1: { - marginTop: 30, - width: DEVICE_WIDTH - IMG_PADDING, - height: (DEVICE_WIDTH - IMG_PADDING) * IMAGE_1_RATIO, - }, - // eslint-disable-next-line react-native/no-unused-styles - carouselImage2: { - width: DEVICE_WIDTH - IMG_PADDING, - height: (DEVICE_WIDTH - IMG_PADDING) * IMAGE_2_RATIO, - }, - // eslint-disable-next-line react-native/no-unused-styles - carouselImage3: { - width: DEVICE_WIDTH - 60, - height: (DEVICE_WIDTH - 60) * IMAGE_3_RATIO, - }, - carouselImageWrapper: { - flex: 1, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - }, - circle: { - width: 8, - height: 8, - borderRadius: 8 / 2, - backgroundColor: colors.grey500, - opacity: 0.4, - marginHorizontal: 8, - }, - solidCircle: { - opacity: 1, - }, - progessContainer: { - flexDirection: 'row', - alignSelf: 'center', - marginVertical: 36, - }, - tab: { - marginHorizontal: 30, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + scroll: { + flexGrow: 1, + }, + wrapper: { + paddingVertical: 30, + flex: 1, + }, + title: { + fontSize: 24, + marginBottom: 12, + color: colors.text.default, + justifyContent: 'center', + textAlign: 'center', + ...fontStyles.bold, + }, + subtitle: { + fontSize: 14, + lineHeight: 19, + marginTop: 12, + marginBottom: 25, + color: colors.text.alternative, + justifyContent: 'center', + textAlign: 'center', + ...fontStyles.normal, + }, + ctas: { + paddingHorizontal: 40, + paddingBottom: Device.isIphoneX() ? 40 : 20, + flexDirection: 'column', + }, + ctaWrapper: { + justifyContent: 'flex-end', + }, + carouselImage: {}, + // eslint-disable-next-line react-native/no-unused-styles + carouselImage1: { + marginTop: 30, + width: DEVICE_WIDTH - IMG_PADDING, + height: (DEVICE_WIDTH - IMG_PADDING) * IMAGE_1_RATIO, + }, + // eslint-disable-next-line react-native/no-unused-styles + carouselImage2: { + width: DEVICE_WIDTH - IMG_PADDING, + height: (DEVICE_WIDTH - IMG_PADDING) * IMAGE_2_RATIO, + }, + // eslint-disable-next-line react-native/no-unused-styles + carouselImage3: { + width: DEVICE_WIDTH - 60, + height: (DEVICE_WIDTH - 60) * IMAGE_3_RATIO, + }, + carouselImageWrapper: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + circle: { + width: 8, + height: 8, + borderRadius: 8 / 2, + backgroundColor: colors.icon.default, + opacity: 0.4, + marginHorizontal: 8, + }, + solidCircle: { + opacity: 1, + }, + progessContainer: { + flexDirection: 'row', + alignSelf: 'center', + marginVertical: 36, + }, + tab: { + marginHorizontal: 30, + }, + }); const onboarding_carousel_1 = require('../../../images/onboarding-carousel-1.png'); // eslint-disable-line const onboarding_carousel_2 = require('../../../images/onboarding-carousel-2.png'); // eslint-disable-line @@ -110,8 +112,6 @@ const carousel_images = [onboarding_carousel_1, onboarding_carousel_2, onboardin * View that is displayed to first time (new) users */ class OnboardingCarousel extends PureComponent { - static navigationOptions = ({ navigation }) => getTransparentOnboardingNavbarOptions(navigation); - static propTypes = { /** * The navigator object @@ -152,12 +152,25 @@ class OnboardingCarousel extends PureComponent { }); }; + updateNavBar = () => { + const colors = this.context.colors || mockTheme.colors; + this.props.navigation.setOptions(getTransparentOnboardingNavbarOptions(colors)); + }; + componentDidMount = () => { + this.updateNavBar(); this.trackEvent(ANALYTICS_EVENTS_V2.ONBOARDING_WELCOME_MESSAGE_VIEWED); }; + componentDidUpdate = () => { + this.updateNavBar(); + }; + render() { const { currentTab } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -219,6 +232,8 @@ class OnboardingCarousel extends PureComponent { } } +OnboardingCarousel.contextType = ThemeContext; + const mapDispatchToProps = (dispatch) => ({ saveOnboardingEvent: (...eventArgs) => dispatch(saveOnboardingEvent(eventArgs)), }); diff --git a/app/components/Views/PickComponent/__snapshots__/index.test.tsx.snap b/app/components/Views/PickComponent/__snapshots__/index.test.tsx.snap index 2ab36706f71..a1f7db4e934 100644 --- a/app/components/Views/PickComponent/__snapshots__/index.test.tsx.snap +++ b/app/components/Views/PickComponent/__snapshots__/index.test.tsx.snap @@ -29,7 +29,7 @@ exports[`PickComponent should render correctly 1`] = ` style={ Object { "backgroundColor": "#FFFFFF", - "borderColor": "#9fa6ae", + "borderColor": "#BBC0C5", "borderRadius": 6, "borderWidth": 2, "height": 12, @@ -43,6 +43,7 @@ exports[`PickComponent should render correctly 1`] = ` + StyleSheet.create({ + root: { + ...baseStyles.flexGrow, + flexDirection: 'row', + }, + circle: { + width: 12, + height: 12, + borderRadius: 12 / 2, + backgroundColor: colors.background.default, + opacity: 1, + margin: 2, + borderWidth: 2, + borderColor: colors.border.default, + marginRight: 6, + }, + option: { + flex: 1, + }, + touchableOption: { + flex: 1, + flexDirection: 'row', + }, + optionText: { + ...fontStyles.normal, + color: colors.text.default, + }, + selectedCircle: { + width: 12, + height: 12, + borderRadius: 12 / 2, + backgroundColor: colors.primary.default, + opacity: 1, + margin: 2, + marginRight: 6, + }, + }); /** * Componets that allows to select clicking two options @@ -83,6 +86,9 @@ export default class PickComponent extends PureComponent { render = () => { const { selectedValue, valueFirst, valueSecond, textFirst, textSecond } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -101,3 +107,5 @@ export default class PickComponent extends PureComponent { ); }; } + +PickComponent.contextType = ThemeContext; diff --git a/app/components/Views/QRScanner/__snapshots__/index.test.tsx.snap b/app/components/Views/QRScanner/__snapshots__/index.test.tsx.snap index c970febdffd..db8c6f2feb1 100644 --- a/app/components/Views/QRScanner/__snapshots__/index.test.tsx.snap +++ b/app/components/Views/QRScanner/__snapshots__/index.test.tsx.snap @@ -109,7 +109,7 @@ exports[`QrScanner should render correctly 1`] = ` > diff --git a/app/components/Views/QRScanner/index.tsx b/app/components/Views/QRScanner/index.tsx index d26d1572c12..36e48291484 100644 --- a/app/components/Views/QRScanner/index.tsx +++ b/app/components/Views/QRScanner/index.tsx @@ -5,7 +5,7 @@ import React, { useRef, useCallback } from 'react'; import { InteractionManager, SafeAreaView, Image, Text, TouchableOpacity, View, StyleSheet, Alert } from 'react-native'; import { RNCamera } from 'react-native-camera'; -import { colors } from '../../../styles/common'; +import { colors as importedColors } from '../../../styles/common'; import Icon from 'react-native-vector-icons/Ionicons'; import { parse } from 'eth-url-parser'; import { strings } from '../../../../locales/i18n'; @@ -18,7 +18,7 @@ import Engine from '../../../core/Engine'; const styles = StyleSheet.create({ container: { flex: 1, - backgroundColor: colors.black, + backgroundColor: importedColors.black, }, preview: { flex: 1, @@ -43,7 +43,7 @@ const styles = StyleSheet.create({ text: { flex: 1, fontSize: 17, - color: colors.white, + color: importedColors.white, textAlign: 'center', justifyContent: 'center', marginTop: 100, @@ -215,7 +215,7 @@ const QRScanner = ({ navigation, route }: Props) => { > - + {strings('qr_scanner.scanning')} diff --git a/app/components/Views/ResetPassword/index.js b/app/components/Views/ResetPassword/index.js index 1dbf0e17ca8..69772d39230 100644 --- a/app/components/Views/ResetPassword/index.js +++ b/app/components/Views/ResetPassword/index.js @@ -16,7 +16,6 @@ import { } from 'react-native'; // eslint-disable-next-line import/no-unresolved import CheckBox from '@react-native-community/checkbox'; -import AnimatedFox from 'react-native-animated-fox'; import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; import AsyncStorage from '@react-native-community/async-storage'; import { connect } from 'react-redux'; @@ -25,7 +24,7 @@ import { setLockTime } from '../../../actions/settings'; import StyledButton from '../../UI/StyledButton'; import Engine from '../../../core/Engine'; import Device from '../../../util/device'; -import { colors, fontStyles, baseStyles } from '../../../styles/common'; +import { fontStyles, baseStyles, colors as importedColors } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import { getNavigationOptionsTitle } from '../../UI/Navbar'; import SecureKeychain from '../../../core/SecureKeychain'; @@ -38,211 +37,216 @@ import { EXISTING_USER, TRUE, BIOMETRY_CHOICE_DISABLED } from '../../../constant import { getPasswordStrengthWord, passwordRequirementsMet } from '../../../util/password'; import NotificationManager from '../../../core/NotificationManager'; import { syncPrefs } from '../../../util/sync'; +import { ThemeContext, mockTheme } from '../../../util/theme'; +import AnimatedFox from 'react-native-animated-fox'; -const styles = StyleSheet.create({ - mainWrapper: { - backgroundColor: colors.white, - flex: 1, - }, - scrollviewWrapper: { - flexGrow: 1, - }, - confirm_title: { - fontSize: 32, - marginTop: 10, - marginBottom: 10, - color: colors.fontPrimary, - justifyContent: 'center', - textAlign: 'left', - ...fontStyles.normal, - }, - confirm_input: { - borderWidth: 2, - borderRadius: 5, - width: '100%', - borderColor: colors.grey000, - padding: 10, - height: 40, - }, - confirm_label: { - fontSize: 16, - lineHeight: 23, - color: colors.fontPrimary, - textAlign: 'left', - ...fontStyles.normal, - }, - wrapper: { - flex: 1, - marginBottom: 10, - }, - scrollableWrapper: { - flex: 1, - paddingHorizontal: 32, - }, - keyboardScrollableWrapper: { - flexGrow: 1, - }, - loadingWrapper: { - paddingHorizontal: 40, - paddingBottom: 30, - alignItems: 'center', - flex: 1, - }, - foxWrapper: { - width: Device.isIos() ? 90 : 80, - height: Device.isIos() ? 90 : 80, - marginTop: 30, - marginBottom: 30, - }, - image: { - alignSelf: 'center', - width: 80, - height: 80, - }, - passwordRequiredContent: { - marginBottom: 20, - }, - content: { - alignItems: 'flex-start', - }, - title: { - fontSize: 24, - marginTop: 20, - marginBottom: 20, - color: colors.fontPrimary, - justifyContent: 'center', - textAlign: 'center', - width: '100%', - ...fontStyles.normal, - }, - subtitle: { - fontSize: 16, - lineHeight: 23, - color: colors.fontPrimary, - textAlign: 'center', - ...fontStyles.normal, - }, - text: { - marginBottom: 10, - justifyContent: 'center', - ...fontStyles.normal, - }, - checkboxContainer: { - marginTop: 10, - marginHorizontal: 10, - flex: 1, - alignItems: 'center', - justifyContent: 'center', - flexDirection: 'row', - }, - checkbox: { - width: 18, - height: 18, - margin: 10, - marginTop: -5, - }, - label: { - ...fontStyles.normal, - fontSize: 14, - color: colors.black, - paddingHorizontal: 10, - lineHeight: 18, - }, - learnMore: { - color: colors.blue, - textDecorationLine: 'underline', - textDecorationColor: colors.blue, - }, - field: { - position: 'relative', - }, - input: { - borderWidth: 1, - borderColor: colors.grey500, - padding: 10, - borderRadius: 6, - fontSize: 14, - height: 50, - ...fontStyles.normal, - }, - ctaWrapper: { - flex: 1, - marginTop: 20, - paddingHorizontal: 10, - }, - errorMsg: { - color: colors.red, - ...fontStyles.normal, - }, - biometrics: { - position: 'relative', - marginTop: 20, - marginBottom: 30, - }, - biometryLabel: { - fontSize: 14, - color: colors.fontPrimary, - position: 'absolute', - top: 0, - left: 0, - }, - biometrySwitch: { - position: 'absolute', - top: 0, - right: 0, - }, - hintLabel: { - height: 20, - marginTop: 14, - fontSize: 12, - color: colors.grey450, - textAlign: 'left', - ...fontStyles.normal, - }, - showPassword: { - position: 'absolute', - top: 0, - right: 0, - }, - // eslint-disable-next-line react-native/no-unused-styles - strength_weak: { - color: colors.red, - }, - // eslint-disable-next-line react-native/no-unused-styles - strength_good: { - color: colors.blue, - }, - // eslint-disable-next-line react-native/no-unused-styles - strength_strong: { - color: colors.green300, - }, - showMatchingPasswords: { - position: 'absolute', - top: 50, - right: 17, - alignSelf: 'flex-end', - }, - confirmPasswordWrapper: { - flex: 1, - padding: 30, - paddingTop: 0, - }, - buttonWrapper: { - flex: 1, - marginTop: 20, - justifyContent: 'flex-end', - }, - warningMessageText: { - paddingVertical: 10, - color: colors.red, - ...fontStyles.normal, - }, - keyboardAvoidingView: { - flex: 1, - flexDirection: 'row', - alignSelf: 'center', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + mainWrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + scrollviewWrapper: { + flexGrow: 1, + }, + confirm_title: { + fontSize: 32, + marginTop: 10, + marginBottom: 10, + color: colors.text.default, + justifyContent: 'center', + textAlign: 'left', + ...fontStyles.normal, + }, + confirm_input: { + borderWidth: 2, + borderRadius: 5, + width: '100%', + borderColor: colors.border.default, + padding: 10, + height: 40, + color: colors.text.default, + }, + confirm_label: { + fontSize: 16, + lineHeight: 23, + color: colors.text.default, + textAlign: 'left', + ...fontStyles.normal, + }, + wrapper: { + flex: 1, + marginBottom: 10, + }, + scrollableWrapper: { + flex: 1, + paddingHorizontal: 32, + }, + keyboardScrollableWrapper: { + flexGrow: 1, + }, + loadingWrapper: { + paddingHorizontal: 40, + paddingBottom: 30, + alignItems: 'center', + flex: 1, + }, + foxWrapper: { + width: Device.isIos() ? 90 : 80, + height: Device.isIos() ? 90 : 80, + marginTop: 30, + marginBottom: 30, + }, + image: { + alignSelf: 'center', + width: 80, + height: 80, + }, + passwordRequiredContent: { + marginBottom: 20, + }, + content: { + alignItems: 'flex-start', + }, + title: { + fontSize: 24, + marginTop: 20, + marginBottom: 20, + color: colors.text.default, + justifyContent: 'center', + textAlign: 'center', + width: '100%', + ...fontStyles.normal, + }, + subtitle: { + fontSize: 16, + lineHeight: 23, + color: colors.text.default, + textAlign: 'center', + ...fontStyles.normal, + }, + text: { + marginBottom: 10, + justifyContent: 'center', + ...fontStyles.normal, + }, + checkboxContainer: { + marginTop: 10, + marginHorizontal: 10, + flex: 1, + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'row', + }, + checkbox: { + width: 18, + height: 18, + margin: 10, + marginTop: -5, + }, + label: { + ...fontStyles.normal, + fontSize: 14, + color: colors.text.default, + paddingHorizontal: 10, + lineHeight: 18, + }, + learnMore: { + color: colors.primary.default, + textDecorationLine: 'underline', + textDecorationColor: colors.primary.default, + }, + field: { + position: 'relative', + }, + input: { + borderWidth: 1, + borderColor: colors.border.default, + padding: 10, + borderRadius: 6, + fontSize: 14, + height: 50, + ...fontStyles.normal, + color: colors.text.default, + }, + ctaWrapper: { + flex: 1, + marginTop: 20, + paddingHorizontal: 10, + }, + errorMsg: { + color: colors.error.default, + ...fontStyles.normal, + }, + biometrics: { + position: 'relative', + marginTop: 20, + marginBottom: 30, + }, + biometryLabel: { + fontSize: 14, + color: colors.text.default, + position: 'absolute', + top: 0, + left: 0, + }, + biometrySwitch: { + position: 'absolute', + top: 0, + right: 0, + }, + hintLabel: { + height: 20, + marginTop: 14, + fontSize: 12, + color: colors.text.default, + textAlign: 'left', + ...fontStyles.normal, + }, + showPassword: { + position: 'absolute', + top: 0, + right: 0, + }, + // eslint-disable-next-line react-native/no-unused-styles + strength_weak: { + color: colors.error.default, + }, + // eslint-disable-next-line react-native/no-unused-styles + strength_good: { + color: colors.primary.default, + }, + // eslint-disable-next-line react-native/no-unused-styles + strength_strong: { + color: colors.success.default, + }, + showMatchingPasswords: { + position: 'absolute', + top: 50, + right: 17, + alignSelf: 'flex-end', + }, + confirmPasswordWrapper: { + flex: 1, + padding: 30, + paddingTop: 0, + }, + buttonWrapper: { + flex: 1, + marginTop: 20, + justifyContent: 'flex-end', + }, + warningMessageText: { + paddingVertical: 10, + color: colors.error.default, + ...fontStyles.normal, + }, + keyboardAvoidingView: { + flex: 1, + flexDirection: 'row', + alignSelf: 'center', + }, + }); const PASSCODE_NOT_SET_ERROR = 'Error: Passcode not set.'; const RESET_PASSWORD = 'reset_password'; @@ -252,9 +256,6 @@ const CONFIRM_PASSWORD = 'confirm_password'; * View where users can set their password for the first time */ class ResetPassword extends PureComponent { - static navigationOptions = ({ navigation }) => - getNavigationOptionsTitle(strings('password_reset.change_password'), navigation); - static propTypes = { /** * The navigator object @@ -300,7 +301,16 @@ class ResetPassword extends PureComponent { confirmPasswordInput = React.createRef(); + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + getNavigationOptionsTitle(strings('password_reset.change_password'), navigation, false, colors) + ); + }; + async componentDidMount() { + this.updateNavBar(); const biometryType = await SecureKeychain.getSupportedBiometryType(); const state = { view: CONFIRM_PASSWORD }; @@ -319,6 +329,7 @@ class ResetPassword extends PureComponent { } componentDidUpdate(prevProps, prevState) { + this.updateNavBar(); const prevLoading = prevState.loading; const { loading } = this.state; const { navigation } = this.props; @@ -491,6 +502,9 @@ class ResetPassword extends PureComponent { renderSwitch = () => { const { biometryType, rememberMe, biometryChoice } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( {biometryType ? ( @@ -503,8 +517,9 @@ class ResetPassword extends PureComponent { onValueChange={this.updateBiometryChoice} // eslint-disable-line react/jsx-no-bind value={biometryChoice} style={styles.biometrySwitch} - trackColor={Device.isIos() ? { true: colors.green300, false: colors.grey300 } : null} - ios_backgroundColor={colors.grey300} + trackColor={{ true: colors.primary.default, false: colors.border.muted }} + thumbColor={importedColors.white} + ios_backgroundColor={colors.border.muted} /> @@ -515,8 +530,9 @@ class ResetPassword extends PureComponent { onValueChange={(rememberMe) => this.setState({ rememberMe })} // eslint-disable-line react/jsx-no-bind value={rememberMe} style={styles.biometrySwitch} - trackColor={Device.isIos() ? { true: colors.green300, false: colors.grey300 } : null} - ios_backgroundColor={colors.grey300} + trackColor={{ true: colors.primary.default, false: colors.border.muted }} + thumbColor={importedColors.white} + ios_backgroundColor={colors.border.muted} /> )} @@ -575,16 +591,25 @@ class ResetPassword extends PureComponent { }); }; - renderLoader = () => ( - - - - ); + renderLoader = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + + + ); + }; setConfirmPassword = (val) => this.setState({ confirmPassword: val }); renderConfirmPassword() { const { warningIncorrectPassword } = this.state; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance || 'light'; + const styles = createStyles(colors); + return ( @@ -599,11 +624,12 @@ class ResetPassword extends PureComponent { {warningIncorrectPassword && ( {warningIncorrectPassword} @@ -628,6 +654,9 @@ class ResetPassword extends PureComponent { renderResetPassword() { const { isSelected, inputWidth, password, passwordStrength, confirmPassword, secureTextEntry, error, loading } = this.state; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance || 'light'; + const styles = createStyles(colors); const passwordsMatch = password !== '' && password === confirmPassword; const canSubmit = passwordsMatch && isSelected; const previousScreen = this.props.route.params?.[PREVIOUS_SCREEN]; @@ -645,10 +674,10 @@ class ResetPassword extends PureComponent { resizeMethod={'auto'} /> ) : ( - + )} - + {strings( previousScreen === ONBOARDING @@ -683,10 +712,12 @@ class ResetPassword extends PureComponent { onChangeText={this.onPasswordChange} secureTextEntry={secureTextEntry} placeholder="" + placeholderTextColor={colors.text.muted} testID="input-password" onSubmitEditing={this.jumpToConfirmPassword} returnKeyType="next" autoCapitalize="none" + keyboardAppearance={themeAppearance} /> {(password !== '' && ( @@ -707,15 +738,16 @@ class ResetPassword extends PureComponent { onChangeText={this.setConfirmPassword} secureTextEntry={secureTextEntry} placeholder={''} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} testID={'input-password-confirm'} onSubmitEditing={this.onPressCreate} returnKeyType={'done'} autoCapitalize="none" + keyboardAppearance={themeAppearance} /> {passwordsMatch ? ( - + ) : null} @@ -728,7 +760,7 @@ class ResetPassword extends PureComponent { value={isSelected} onValueChange={this.setSelection} style={styles.checkbox} - tintColors={{ true: colors.blue }} + tintColors={{ true: colors.primary.default, false: colors.border.default }} boxType="square" testID={'password-understand-box'} /> @@ -762,6 +794,9 @@ class ResetPassword extends PureComponent { render() { const { view, ready } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + if (!ready) return this.renderLoader(); return ( @@ -777,6 +812,8 @@ class ResetPassword extends PureComponent { } } +ResetPassword.contextType = ThemeContext; + const mapStateToProps = (state) => ({ selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress, }); diff --git a/app/components/Views/RevealPrivateCredential/index.js b/app/components/Views/RevealPrivateCredential/index.js index 3c28c43cc6b..d270770187a 100644 --- a/app/components/Views/RevealPrivateCredential/index.js +++ b/app/components/Views/RevealPrivateCredential/index.js @@ -18,7 +18,6 @@ import QRCode from 'react-native-qrcode-svg'; import ScrollableTabView, { DefaultTabBar } from 'react-native-scrollable-tab-view'; import Icon from 'react-native-vector-icons/FontAwesome5'; import { connect } from 'react-redux'; - import ActionView from '../../UI/ActionView'; import ButtonReveal from '../../UI/ButtonReveal'; import { getNavigationOptionsTitle } from '../../UI/Navbar'; @@ -26,126 +25,133 @@ import InfoModal from '../../UI/Swaps/components/InfoModal'; import { showAlert } from '../../../actions/alert'; import { BIOMETRY_CHOICE } from '../../../constants/storage'; import ClipboardManager from '../../../core/ClipboardManager'; +import { ThemeContext, mockTheme } from '../../../util/theme'; import Engine from '../../../core/Engine'; import PreventScreenshot from '../../../core/PreventScreenshot'; import SecureKeychain from '../../../core/SecureKeychain'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import AnalyticsV2 from '../../../util/analyticsV2'; import Device from '../../../util/device'; import { strings } from '../../../../locales/i18n'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - }, - normalText: { - ...fontStyles.normal, - }, - seedPhrase: { - backgroundColor: colors.white, - marginTop: 10, - paddingBottom: 20, - paddingLeft: 20, - paddingRight: 20, - fontSize: 20, - textAlign: 'center', - color: colors.black, - ...fontStyles.normal, - }, - seedPhraseView: { - borderRadius: 10, - borderWidth: 1, - borderColor: colors.grey400, - marginTop: 10, - alignItems: 'center', - }, - privateCredentialAction: { - flex: 1, - alignItems: 'center', - justifyContent: 'center', - borderColor: colors.blue, - borderWidth: 1, - borderRadius: 20, - width: '90%', - paddingVertical: 10, - marginBottom: 15, - }, - rowWrapper: { - padding: 20, - }, - warningWrapper: { - backgroundColor: colors.red000, - margin: 20, - marginTop: 10, - borderRadius: 8, - borderWidth: 1, - borderColor: colors.red100, - }, - warningRowWrapper: { - flex: 1, - flexDirection: 'row', - alignItems: 'flex-start', - padding: 8, - }, - warningText: { - marginTop: 10, - color: colors.red, - ...fontStyles.normal, - }, - input: { - borderWidth: 2, - borderRadius: 5, - borderColor: colors.grey000, - padding: 10, - }, - icon: { - color: colors.red, - }, - blueText: { - color: colors.blue, - }, - link: { - top: 2.5, - }, - warningMessageText: { - marginLeft: 10, - marginRight: 40, - ...fontStyles.normal, - }, - enterPassword: { - marginBottom: 10, - ...fontStyles.bold, - }, - boldText: { - ...fontStyles.bold, - }, - tabContent: { - padding: 20, - }, - qrCodeWrapper: { - marginTop: 20, - flex: 1, - alignItems: 'center', - justifyContent: 'center', - }, - tabUnderlineStyle: { - height: 2, - backgroundColor: colors.blue, - }, - tabStyle: { - paddingBottom: 0, - backgroundColor: colors.beige, - }, - textStyle: { - fontSize: 12, - letterSpacing: 0.5, - ...fontStyles.bold, - }, - revealModalText: { - marginBottom: 20, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + normalText: { + color: colors.text.default, + ...fontStyles.normal, + }, + seedPhrase: { + backgroundColor: colors.background.default, + marginTop: 10, + paddingBottom: 20, + paddingLeft: 20, + paddingRight: 20, + fontSize: 20, + textAlign: 'center', + color: colors.text.default, + ...fontStyles.normal, + }, + seedPhraseView: { + borderRadius: 10, + borderWidth: 1, + borderColor: colors.border.default, + marginTop: 10, + alignItems: 'center', + }, + privateCredentialAction: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + borderColor: colors.primary.default, + borderWidth: 1, + borderRadius: 20, + width: '90%', + paddingVertical: 10, + marginBottom: 15, + }, + rowWrapper: { + padding: 20, + }, + warningWrapper: { + backgroundColor: colors.error.muted, + margin: 20, + marginTop: 10, + borderRadius: 8, + borderWidth: 1, + borderColor: colors.error.default, + }, + warningRowWrapper: { + flex: 1, + flexDirection: 'row', + alignContent: 'center', + alignItems: 'center', + }, + warningText: { + marginTop: 10, + color: colors.error.default, + ...fontStyles.normal, + }, + input: { + borderWidth: 2, + borderRadius: 5, + borderColor: colors.border.default, + padding: 10, + color: colors.text.default, + }, + icon: { + margin: 10, + color: colors.error.default, + }, + blueText: { + color: colors.primary.default, + }, + link: { + top: 2.5, + }, + warningMessageText: { + marginLeft: 10, + marginRight: 40, + ...fontStyles.normal, + color: colors.text.default, + }, + enterPassword: { + marginBottom: 15, + color: colors.text.default, + }, + boldText: { + color: colors.text.default, + ...fontStyles.bold, + }, + tabContent: { + padding: 20, + }, + qrCodeWrapper: { + marginTop: 20, + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + tabUnderlineStyle: { + height: 2, + backgroundColor: colors.primary.default, + }, + tabStyle: { + paddingBottom: 0, + backgroundColor: colors.background.default, + }, + textStyle: { + fontSize: 12, + letterSpacing: 0.5, + ...fontStyles.bold, + }, + revealModalText: { + marginBottom: 20, + }, + }); const WRONG_PASSWORD_ERROR = 'error: Invalid password'; const PRIVATE_KEY = 'private_key'; @@ -170,12 +176,6 @@ class RevealPrivateCredential extends PureComponent { isModalVisible: false, }; - static navigationOptions = ({ navigation, route }) => - getNavigationOptionsTitle( - strings(`reveal_credential.${route.params?.privateCredentialName ?? ''}_title`), - navigation - ); - static propTypes = { /** /* navigation object required to push new views @@ -207,7 +207,22 @@ class RevealPrivateCredential extends PureComponent { route: PropTypes.object, }; + updateNavBar = () => { + const { navigation, route } = this.props; + const colors = this.context.colors || mockTheme.colors; + + navigation.setOptions( + getNavigationOptionsTitle( + strings(`reveal_credential.${route.params?.privateCredentialName ?? ''}_title`), + navigation, + false, + colors + ) + ); + }; + async componentDidMount() { + this.updateNavBar(); // Try to use biometrics to unloc // (if available) const biometryType = await SecureKeychain.getSupportedBiometryType(); @@ -227,6 +242,10 @@ class RevealPrivateCredential extends PureComponent { }); } + componentDidUpdate = () => { + this.updateNavBar(); + }; + componentWillUnmount = () => { InteractionManager.runAfterInteractions(() => { PreventScreenshot.allow(); @@ -317,7 +336,14 @@ class RevealPrivateCredential extends PureComponent { }); }; - revearlSRP = () => { + getStyles = () => { + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance || 'light'; + const styles = createStyles(colors); + return { colors, styles, themeAppearance }; + }; + + revealSRP = () => { const { password } = this.state; this.tryUnlockWithPassword(password); @@ -328,12 +354,14 @@ class RevealPrivateCredential extends PureComponent { }; renderTabBar() { + const { styles, colors } = this.getStyles(); + return ( @@ -342,9 +370,10 @@ class RevealPrivateCredential extends PureComponent { renderTabView(privateCredentialName) { const { clipboardPrivateCredential } = this.state; + const { styles, colors, themeAppearance } = this.getStyles(); return ( - + this.renderTabBar()}> {strings(`reveal_credential.${privateCredentialName}`)} @@ -356,6 +385,8 @@ class RevealPrivateCredential extends PureComponent { style={styles.seedPhrase} editable={false} testID={'private-credential-text'} + placeholderTextColor={colors.text.muted} + keyboardAppearance={themeAppearance} /> - + @@ -376,6 +412,7 @@ class RevealPrivateCredential extends PureComponent { } renderPasswordEntry() { + const { styles, colors, themeAppearance } = this.getStyles(); return ( <> {strings('reveal_credential.enter_password')} @@ -383,10 +420,11 @@ class RevealPrivateCredential extends PureComponent { style={styles.input} testID={'private-credential-password-text-input'} placeholder={'Password'} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} onChangeText={this.onPasswordChange} secureTextEntry onSubmitEditing={this.tryUnlock} + keyboardAppearance={themeAppearance} /> {this.state.warningIncorrectPassword} @@ -404,6 +442,7 @@ class RevealPrivateCredential extends PureComponent { }; renderModal() { + const { styles } = this.getStyles(); return ( } @@ -433,6 +472,7 @@ class RevealPrivateCredential extends PureComponent { } renderSRPExplaination() { + const { styles } = this.getStyles(); return ( {strings('reveal_credential.seed_phrase_explanation')[0]} @@ -456,6 +496,7 @@ class RevealPrivateCredential extends PureComponent { } renderWarning(privateCredentialName) { + const { styles } = this.getStyles(); return ( @@ -481,6 +522,7 @@ class RevealPrivateCredential extends PureComponent { const { unlocked, isUserUnlocked, password } = this.state; const privateCredentialName = this.props.privateCredentialName || this.props.route.params.privateCredentialName; const isPrivateKeyReveal = privateCredentialName === PRIVATE_KEY; + const { styles } = this.getStyles(); return ( @@ -518,6 +560,8 @@ class RevealPrivateCredential extends PureComponent { }; } +RevealPrivateCredential.contextType = ThemeContext; + const mapStateToProps = (state) => ({ selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress, passwordSet: state.user.passwordSet, diff --git a/app/components/Views/Send/index.js b/app/components/Views/Send/index.js index ad2e5e8b0f8..2bbc1abcd7a 100644 --- a/app/components/Views/Send/index.js +++ b/app/components/Views/Send/index.js @@ -1,7 +1,6 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { InteractionManager, ActivityIndicator, Alert, StyleSheet, View } from 'react-native'; -import { colors } from '../../../styles/common'; import Engine from '../../../core/Engine'; import EditAmount from '../../Views/SendFlow/Amount'; import ConfirmSend from '../../Views/SendFlow/Confirm'; @@ -29,30 +28,30 @@ import { MAINNET } from '../../../constants/network'; import BigNumber from 'bignumber.js'; import { WalletDevice } from '@metamask/controllers/'; import { getTokenList } from '../../../reducers/tokens'; +import { ThemeContext, mockTheme } from '../../../util/theme'; const REVIEW = 'review'; const EDIT = 'edit'; const SEND = 'Send'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - }, - loader: { - backgroundColor: colors.white, - flex: 1, - justifyContent: 'center', - alignItems: 'center', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + loader: { + backgroundColor: colors.background.default, + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + }); /** * View that wraps the wraps the "Send" screen */ class Send extends PureComponent { - static navigationOptions = ({ navigation, route }) => getTransactionOptionsTitle('send.confirm', navigation, route); - static propTypes = { /** * Object that represents the navigator @@ -164,6 +163,12 @@ class Send extends PureComponent { } } + updateNavBar = () => { + const colors = this.context.colors || mockTheme.colors; + const { navigation, route } = this.props; + navigation.setOptions(getTransactionOptionsTitle('send.confirm', navigation, route, colors)); + }; + /** * Sets state mounted to true, resets transaction and check for deeplinks */ @@ -175,6 +180,7 @@ class Send extends PureComponent { dappTransactionModalVisible, toggleDappTransactionModal, } = this.props; + this.updateNavBar(); navigation && navigation.setParams({ mode: REVIEW, @@ -208,6 +214,7 @@ class Send extends PureComponent { contractBalances, navigation, } = this.props; + this.updateNavBar(); if (prevRoute && route) { const prevTxMeta = prevRoute.params?.txMeta; const currentTxMeta = route.params?.txMeta; @@ -604,7 +611,13 @@ class Send extends PureComponent { changeToReviewMode = () => this.onModeChange(REVIEW); + getStyles = () => { + const colors = this.context.colors || mockTheme.colors; + return createStyles(colors); + }; + renderLoader() { + const styles = this.getStyles(); return ( @@ -626,9 +639,12 @@ class Send extends PureComponent { } } - render = () => ( - {this.state.ready ? this.renderModeComponent() : this.renderLoader()} - ); + render = () => { + const styles = this.getStyles(); + return ( + {this.state.ready ? this.renderModeComponent() : this.renderLoader()} + ); + }; } const mapStateToProps = (state) => ({ @@ -653,4 +669,6 @@ const mapDispatchToProps = (dispatch) => ({ toggleDappTransactionModal: () => dispatch(toggleDappTransactionModal()), }); +Send.contextType = ThemeContext; + export default connect(mapStateToProps, mapDispatchToProps)(Send); diff --git a/app/components/Views/SendFlow/AddressElement/index.js b/app/components/Views/SendFlow/AddressElement/index.js index 95884810d31..a96cf6d8bd5 100644 --- a/app/components/Views/SendFlow/AddressElement/index.js +++ b/app/components/Views/SendFlow/AddressElement/index.js @@ -2,38 +2,40 @@ import React, { PureComponent } from 'react'; import { renderShortAddress } from '../../../../util/address'; import { StyleSheet, View, Text, TouchableOpacity } from 'react-native'; import Identicon from '../../../UI/Identicon'; -import { fontStyles, colors } from '../../../../styles/common'; +import { fontStyles } from '../../../../styles/common'; import PropTypes from 'prop-types'; import { doENSReverseLookup } from '../../../../util/ENSUtils'; import { connect } from 'react-redux'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - addressElementWrapper: { - padding: 16, - flexDirection: 'row', - alignItems: 'center', - borderBottomWidth: 1, - borderBottomColor: colors.grey050, - }, - addressElementInformation: { - flex: 1, - flexDirection: 'column', - }, - addressIdenticon: { - paddingRight: 16, - }, - addressTextNickname: { - ...fontStyles.normal, - flex: 1, - color: colors.black, - fontSize: 14, - }, - addressTextAddress: { - ...fontStyles.normal, - fontSize: 12, - color: colors.grey500, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + addressElementWrapper: { + padding: 16, + flexDirection: 'row', + alignItems: 'center', + borderBottomWidth: 1, + borderBottomColor: colors.border.muted, + }, + addressElementInformation: { + flex: 1, + flexDirection: 'column', + }, + addressIdenticon: { + paddingRight: 16, + }, + addressTextNickname: { + ...fontStyles.normal, + flex: 1, + color: colors.text.default, + fontSize: 14, + }, + addressTextAddress: { + ...fontStyles.normal, + fontSize: 12, + color: colors.text.alternative, + }, + }); class AddressElement extends PureComponent { static propTypes = { @@ -78,6 +80,9 @@ class AddressElement extends PureComponent { const { name, address } = this.state; const primaryLabel = name && name[0] !== ' ' ? name : renderShortAddress(address); const secondaryLabel = name && name[0] !== ' ' && renderShortAddress(address); + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( onAccountPress(address)} @@ -103,6 +108,8 @@ class AddressElement extends PureComponent { }; } +AddressElement.contextType = ThemeContext; + const mapStateToProps = (state) => ({ network: state.engine.backgroundState.NetworkController.network, }); diff --git a/app/components/Views/SendFlow/AddressInputs/index.js b/app/components/Views/SendFlow/AddressInputs/index.js index 2bf36eec096..701d47a5e22 100644 --- a/app/components/Views/SendFlow/AddressInputs/index.js +++ b/app/components/Views/SendFlow/AddressInputs/index.js @@ -1,6 +1,6 @@ import React from 'react'; import { StyleSheet, View, TextInput, TouchableOpacity } from 'react-native'; -import { colors, fontStyles, baseStyles } from '../../../../styles/common'; +import { fontStyles, baseStyles } from '../../../../styles/common'; import AntIcon from 'react-native-vector-icons/AntDesign'; import FontAwesome from 'react-native-vector-icons/FontAwesome'; import PropTypes from 'prop-types'; @@ -9,127 +9,134 @@ import { renderShortAddress } from '../../../../util/address'; import { strings } from '../../../../../locales/i18n'; import Text from '../../../Base/Text'; import { hasZeroWidthPoints } from '../../../../util/validators'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - flexDirection: 'row', - marginHorizontal: 8, - }, - selectWrapper: { - flex: 1, - marginLeft: 8, - paddingHorizontal: 10, - minHeight: 52, - flexDirection: 'row', - borderWidth: 1, - borderRadius: 8, - marginVertical: 8, - }, - inputWrapper: { - flex: 1, - marginLeft: 8, - padding: 10, - minHeight: 52, - flexDirection: 'row', - borderWidth: 1, - borderRadius: 8, - marginTop: 8, - }, - input: { - flex: 1, - flexDirection: 'row', - alignItems: 'center', - }, - identiconWrapper: { - flexDirection: 'row', - alignItems: 'center', - }, - addressToInformation: { - flex: 1, - flexDirection: 'row', - alignItems: 'center', - position: 'relative', - }, - exclamation: { - backgroundColor: colors.white, - borderRadius: 12, - position: 'absolute', - bottom: 8, - left: 20, - }, - address: { - flexDirection: 'column', - alignItems: 'flex-start', - marginHorizontal: 8, - }, - addressWrapper: { flexDirection: 'row' }, - textAddress: { - ...fontStyles.normal, - color: colors.black, - fontSize: 14, - }, - textBalance: { - ...fontStyles.normal, - fontSize: 12, - color: colors.grey500, - }, - label: { - flexDirection: 'row', - alignItems: 'center', - width: '15%', - }, - labelText: { - ...fontStyles.normal, - color: colors.black, - fontSize: 16, - }, - textInput: { - ...fontStyles.normal, - paddingLeft: 0, - paddingRight: 8, - width: '100%', - }, - scanIcon: { - flexDirection: 'column', - alignItems: 'center', - }, - iconOpaque: { - color: colors.grey500, - }, - iconHighlighted: { - color: colors.blue, - }, - borderOpaque: { - borderColor: colors.grey100, - }, - borderHighlighted: { - borderColor: colors.blue, - }, - iconWrapper: { - flexDirection: 'row', - alignItems: 'center', - }, - dropdownIconWrapper: { - height: 23, - width: 23, - }, - dropdownIcon: { - alignSelf: 'center', - }, - checkIconWrapper: { - flexDirection: 'row', - alignItems: 'center', - }, - checkAddress: { - flex: 0.9, - // maxWidth: '90%' - }, - toInputWrapper: { - flexDirection: 'row', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + flexDirection: 'row', + marginHorizontal: 8, + }, + selectWrapper: { + flex: 1, + marginLeft: 8, + paddingHorizontal: 10, + minHeight: 52, + flexDirection: 'row', + borderWidth: 1, + borderRadius: 8, + marginVertical: 8, + }, + inputWrapper: { + flex: 1, + marginLeft: 8, + padding: 10, + minHeight: 52, + flexDirection: 'row', + borderWidth: 1, + borderRadius: 8, + marginTop: 8, + borderColor: colors.border.default, + }, + input: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + }, + identiconWrapper: { + flexDirection: 'row', + alignItems: 'center', + }, + addressToInformation: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + position: 'relative', + }, + exclamation: { + backgroundColor: colors.background.default, + borderRadius: 12, + position: 'absolute', + bottom: 8, + left: 20, + }, + address: { + flexDirection: 'column', + alignItems: 'flex-start', + marginHorizontal: 8, + }, + addressWrapper: { flexDirection: 'row' }, + textAddress: { + ...fontStyles.normal, + color: colors.text.default, + fontSize: 14, + }, + textBalance: { + ...fontStyles.normal, + fontSize: 12, + color: colors.text.alternative, + }, + label: { + flexDirection: 'row', + alignItems: 'center', + width: '15%', + }, + labelText: { + ...fontStyles.normal, + color: colors.text.default, + fontSize: 16, + }, + textInput: { + ...fontStyles.normal, + paddingLeft: 0, + paddingRight: 8, + width: '100%', + color: colors.text.default, + }, + scanIcon: { + flexDirection: 'column', + alignItems: 'center', + }, + iconOpaque: { + color: colors.icon.default, + }, + iconHighlighted: { + color: colors.primary.default, + }, + borderOpaque: { + borderColor: colors.border.default, + }, + borderHighlighted: { + borderColor: colors.primary.default, + }, + iconWrapper: { + flexDirection: 'row', + alignItems: 'center', + }, + dropdownIconWrapper: { + height: 23, + width: 23, + }, + dropdownIcon: { + alignSelf: 'center', + }, + checkIconWrapper: { + flexDirection: 'row', + alignItems: 'center', + }, + checkAddress: { + flex: 0.9, + // maxWidth: '90%' + }, + toInputWrapper: { + flexDirection: 'row', + }, + }); const AddressName = ({ toAddressName, confusableCollection = [] }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + if (confusableCollection.length) { const texts = toAddressName.split('').map((char, index) => { // if text has a confusable highlight it red @@ -183,6 +190,9 @@ export const AddressTo = (props) => { confusableCollection, displayExclamation, } = props; + const { colors, themeAppearance } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ( @@ -197,7 +207,7 @@ export const AddressTo = (props) => { autoCorrect={false} onChangeText={onToSelectedAddressChange} placeholder={strings('transactions.address_to_placeholder')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} spellCheck={false} style={[styles.textInput, inputWidth]} numberOfLines={1} @@ -206,6 +216,7 @@ export const AddressTo = (props) => { onSubmitEditing={onSubmit} value={toSelectedAddress} testID={'txn-to-address-input'} + keyboardAppearance={themeAppearance} /> {!!onScan && ( @@ -224,7 +235,7 @@ export const AddressTo = (props) => { {displayExclamation && ( - + )} @@ -243,7 +254,7 @@ export const AddressTo = (props) => { {renderShortAddress(toSelectedAddress)} - + @@ -326,6 +337,9 @@ AddressTo.propTypes = { export const AddressFrom = (props) => { const { highlighted, onPressIcon, fromAccountName, fromAccountBalance, fromAccountAddress } = props; + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + return ( diff --git a/app/components/Views/SendFlow/AddressList/index.js b/app/components/Views/SendFlow/AddressList/index.js index 822c5f50ccf..2cda324a179 100644 --- a/app/components/Views/SendFlow/AddressList/index.js +++ b/app/components/Views/SendFlow/AddressList/index.js @@ -1,59 +1,66 @@ import React, { PureComponent } from 'react'; import { StyleSheet, View, Text, TouchableOpacity, ScrollView, ActivityIndicator } from 'react-native'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles } from '../../../../styles/common'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import Fuse from 'fuse.js'; import { isSmartContractAddress } from '../../../../util/transactions'; import { strings } from '../../../../../locales/i18n'; import AddressElement from '../AddressElement'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - root: { - flex: 1, - backgroundColor: colors.white, - }, - messageText: { - ...fontStyles.normal, - color: colors.blue, - fontSize: 16, - textAlign: 'center', - }, - messageLeft: { - textAlign: 'left', - }, - myAccountsWrapper: { - flexGrow: 1, - }, - myAccountsTouchable: { - borderBottomWidth: 1, - borderBottomColor: colors.grey050, - padding: 16, - }, - labelElementWrapper: { - backgroundColor: colors.grey000, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - borderBottomWidth: 1, - borderBottomColor: colors.grey050, - padding: 8, - }, - labelElementInitialText: { - textTransform: 'uppercase', - }, - labelElementText: { - ...fontStyles.normal, - fontSize: 12, - marginHorizontal: 8, - color: colors.grey600, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + root: { + flex: 1, + backgroundColor: colors.background.default, + }, + messageText: { + ...fontStyles.normal, + color: colors.primary.default, + fontSize: 16, + textAlign: 'center', + }, + messageLeft: { + textAlign: 'left', + }, + myAccountsWrapper: { + flexGrow: 1, + }, + myAccountsTouchable: { + borderBottomWidth: 1, + borderBottomColor: colors.border.muted, + padding: 16, + }, + labelElementWrapper: { + backgroundColor: colors.background.default, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + borderBottomWidth: 1, + borderBottomColor: colors.border.muted, + padding: 8, + }, + labelElementInitialText: { + textTransform: 'uppercase', + }, + labelElementText: { + ...fontStyles.normal, + fontSize: 12, + marginHorizontal: 8, + color: colors.text.alternative, + }, + activityIndicator: { + color: colors.icon.default, + }, + }); -const LabelElement = (label, checkingForSmartContracts, showLoading) => ( +const LabelElement = (styles, label, checkingForSmartContracts = false, showLoading = false) => ( 1 ? {} : styles.labelElementInitialText]}>{label} - {showLoading && checkingForSmartContracts && } + {showLoading && checkingForSmartContracts && ( + + )} ); /** @@ -196,6 +203,9 @@ class AddressList extends PureComponent { renderMyAccounts = () => { const { identities, onAccountPress, inputSearch, onAccountLongPress } = this.props; const { myAccountsOpened } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + if (inputSearch) return; return !myAccountsOpened ? ( { const { onAccountPress, onAccountLongPress } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); if (typeof element === 'string') { - return LabelElement(element); + return LabelElement(styles, element); } const key = element.address + element.name; @@ -245,13 +257,14 @@ class AddressList extends PureComponent { renderRecents = () => { const { recents, identities, addressBook, network, onAccountPress, onAccountLongPress, inputSearch } = this.props; - const networkAddressBook = addressBook[network] || {}; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); if (!recents.length || inputSearch) return; return ( <> - {LabelElement(strings('address_book.recents'), this.state.checkingForSmartContracts, 'showLoading')} + {LabelElement(styles, strings('address_book.recents'), this.state.checkingForSmartContracts, true)} {recents .filter((recent) => recent != null) .map((address, index) => ( @@ -270,6 +283,8 @@ class AddressList extends PureComponent { render = () => { const { contactElements } = this.state; const { onlyRenderAddressBook } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); const sendFlowContacts = []; contactElements.filter((element) => { @@ -299,6 +314,8 @@ class AddressList extends PureComponent { }; } +AddressList.contextType = ThemeContext; + const mapStateToProps = (state) => ({ recents: state.recents, addressBook: state.engine.backgroundState.AddressBookController.addressBook, diff --git a/app/components/Views/SendFlow/Amount/index.js b/app/components/Views/SendFlow/Amount/index.js index 6b1e4b36dee..c33c00dc7d7 100644 --- a/app/components/Views/SendFlow/Amount/index.js +++ b/app/components/Views/SendFlow/Amount/index.js @@ -1,5 +1,5 @@ import React, { PureComponent } from 'react'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles } from '../../../../styles/common'; import { StyleSheet, Text, @@ -59,242 +59,243 @@ import { decGWEIToHexWEI } from '../../../../util/conversions'; import AppConstants from '../../../../core/AppConstants'; import { collectibleContractsSelector, collectiblesSelector } from '../../../../reducers/collectibles'; import { gte } from '../../../../util/lodash'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; const { hexToBN, BNToHex } = util; const KEYBOARD_OFFSET = Device.isSmallDevice() ? 80 : 120; -const styles = StyleSheet.create({ - wrapper: { - flex: 1, - backgroundColor: colors.white, - }, - scrollWrapper: { - marginBottom: 60, - }, - buttonNextWrapper: { - flex: 1, - flexDirection: 'row', - alignItems: 'flex-end', - }, - buttonNext: { - flex: 1, - marginHorizontal: 24, - }, - inputWrapper: { - flex: 1, - marginTop: 30, - marginHorizontal: 24, - }, - actionsWrapper: { - flexDirection: 'row', - }, - action: { - flex: 1, - alignItems: 'center', - }, - actionBorder: { - flex: 0.8, - }, - actionDropdown: { - ...fontStyles.normal, - backgroundColor: colors.blue, - paddingHorizontal: 16, - paddingVertical: 2, - borderRadius: 100, - flexDirection: 'row', - alignItems: 'center', - }, - textDropdown: { - ...fontStyles.normal, - fontSize: 14, - color: colors.white, - paddingVertical: 2, - }, - iconDropdown: { - paddingLeft: 10, - }, - maxText: { - ...fontStyles.normal, - fontSize: 12, - color: colors.blue, - alignSelf: 'flex-end', - textTransform: 'uppercase', - }, - actionMax: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'flex-end', - }, - actionMaxTouchable: {}, - inputContainerWrapper: { - marginVertical: 16, - alignItems: 'center', - }, - inputContainer: { - flexDirection: 'row', - }, - inputCurrencyText: { - ...fontStyles.normal, - fontWeight: fontStyles.light.fontWeight, - color: colors.black, - fontSize: 44, - marginRight: 8, - paddingVertical: Device.isIos() ? 0 : 8, - justifyContent: 'center', - alignItems: 'center', - textTransform: 'uppercase', - }, - textInput: { - ...fontStyles.normal, - fontWeight: fontStyles.light.fontWeight, - fontSize: 44, - textAlign: 'center', - color: colors.black, - }, - switch: { - flex: 1, - marginTop: Device.isIos() ? 0 : 2, - }, - actionSwitch: { - paddingHorizontal: 8, - paddingVertical: 2, - borderRadius: 8, - flexDirection: 'row', - borderColor: colors.grey500, - borderWidth: 1, - right: -2, - }, - textSwitch: { - ...fontStyles.normal, - fontSize: 14, - color: colors.grey500, - textTransform: 'uppercase', - }, - switchWrapper: { - flexDirection: 'row', - alignItems: 'center', - }, - bottomModal: { - justifyContent: 'flex-end', - margin: 0, - }, - tokenImage: { - width: 36, - height: 36, - overflow: 'hidden', - }, - assetElementWrapper: { - height: 70, - backgroundColor: colors.white, - borderWidth: 1, - borderColor: colors.grey000, - flexDirection: 'row', - alignItems: 'center', - paddingHorizontal: 24, - }, - assetElement: { - flexDirection: 'row', - flex: 1, - }, - assetsModalWrapper: { - backgroundColor: colors.white, - borderTopLeftRadius: 10, - borderTopRightRadius: 10, - height: 450, - }, - titleWrapper: { - width: '100%', - height: 33, - alignItems: 'center', - justifyContent: 'center', - borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: colors.grey100, - }, - dragger: { - width: 48, - height: 5, - borderRadius: 4, - backgroundColor: colors.grey400, - opacity: Device.isAndroid() ? 0.6 : 0.5, - }, - textAssetTitle: { - ...fontStyles.normal, - fontSize: 18, - }, - assetInformationWrapper: { - flex: 1, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - marginLeft: 16, - }, - assetBalanceWrapper: { - flexDirection: 'column', - }, - textAssetBalance: { - ...fontStyles.normal, - fontSize: 18, - textAlign: 'right', - }, - textAssetFiat: { - ...fontStyles.normal, - fontSize: 12, - color: colors.grey500, - textAlign: 'right', - textTransform: 'uppercase', - }, - errorMessageWrapper: { - marginVertical: 16, - }, - CollectibleMedia: { - width: 120, - height: 120, - }, - collectibleName: { - ...fontStyles.normal, - fontSize: 32, - color: colors.grey500, - textAlign: 'center', - }, - collectibleId: { - ...fontStyles.normal, - fontSize: 14, - color: colors.grey500, - marginTop: 8, - textAlign: 'center', - }, - collectibleInputWrapper: { - margin: 24, - }, - collectibleInputImageWrapper: { - flexDirection: 'column', - alignItems: 'center', - }, - collectibleInputInformationWrapper: { - marginTop: 12, - }, - nextActionWrapper: { - flex: 1, - marginBottom: 16, - }, - balanceWrapper: { - marginVertical: 16, - }, - balanceText: { - ...fontStyles.normal, - alignSelf: 'center', - fontSize: 12, - lineHeight: 16, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + flex: 1, + backgroundColor: colors.background.default, + }, + scrollWrapper: { + marginBottom: 60, + }, + buttonNextWrapper: { + flex: 1, + flexDirection: 'row', + alignItems: 'flex-end', + }, + buttonNext: { + flex: 1, + marginHorizontal: 24, + }, + inputWrapper: { + flex: 1, + marginTop: 30, + marginHorizontal: 24, + }, + actionsWrapper: { + flexDirection: 'row', + }, + action: { + flex: 1, + alignItems: 'center', + }, + actionBorder: { + flex: 0.8, + }, + actionDropdown: { + ...fontStyles.normal, + backgroundColor: colors.primary.default, + paddingHorizontal: 16, + paddingVertical: 2, + borderRadius: 100, + flexDirection: 'row', + alignItems: 'center', + }, + textDropdown: { + ...fontStyles.normal, + fontSize: 14, + color: colors.primary.inverse, + paddingVertical: 2, + }, + iconDropdown: { + paddingLeft: 10, + }, + maxText: { + ...fontStyles.normal, + fontSize: 12, + color: colors.primary.default, + alignSelf: 'flex-end', + textTransform: 'uppercase', + }, + actionMax: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'flex-end', + }, + actionMaxTouchable: {}, + inputContainerWrapper: { + marginVertical: 16, + alignItems: 'center', + }, + inputContainer: { + flexDirection: 'row', + }, + inputCurrencyText: { + ...fontStyles.normal, + fontWeight: fontStyles.light.fontWeight, + color: colors.text.default, + fontSize: 44, + marginRight: 8, + paddingVertical: Device.isIos() ? 0 : 8, + justifyContent: 'center', + alignItems: 'center', + textTransform: 'uppercase', + }, + textInput: { + ...fontStyles.normal, + fontWeight: fontStyles.light.fontWeight, + fontSize: 44, + textAlign: 'center', + color: colors.text.default, + }, + switch: { + flex: 1, + marginTop: Device.isIos() ? 0 : 2, + }, + actionSwitch: { + paddingHorizontal: 8, + paddingVertical: 2, + borderRadius: 8, + flexDirection: 'row', + borderColor: colors.text.alternative, + borderWidth: 1, + right: -2, + }, + textSwitch: { + ...fontStyles.normal, + fontSize: 14, + color: colors.text.alternative, + textTransform: 'uppercase', + }, + switchWrapper: { + flexDirection: 'row', + alignItems: 'center', + }, + bottomModal: { + justifyContent: 'flex-end', + margin: 0, + }, + tokenImage: { + width: 36, + height: 36, + overflow: 'hidden', + }, + assetElementWrapper: { + height: 70, + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + flexDirection: 'row', + alignItems: 'center', + paddingHorizontal: 24, + }, + assetElement: { + flexDirection: 'row', + flex: 1, + }, + assetsModalWrapper: { + backgroundColor: colors.background.default, + borderTopLeftRadius: 10, + borderTopRightRadius: 10, + height: 450, + }, + titleWrapper: { + width: '100%', + height: 33, + alignItems: 'center', + justifyContent: 'center', + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + }, + dragger: { + width: 48, + height: 5, + borderRadius: 4, + backgroundColor: colors.border.default, + }, + textAssetTitle: { + ...fontStyles.normal, + fontSize: 18, + color: colors.text.default, + }, + assetInformationWrapper: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginLeft: 16, + }, + assetBalanceWrapper: { + flexDirection: 'column', + }, + textAssetBalance: { + ...fontStyles.normal, + fontSize: 18, + textAlign: 'right', + color: colors.text.default, + }, + textAssetFiat: { + ...fontStyles.normal, + fontSize: 12, + color: colors.text.alternative, + textAlign: 'right', + textTransform: 'uppercase', + }, + errorMessageWrapper: { + marginVertical: 16, + }, + CollectibleMedia: { + width: 120, + height: 120, + }, + collectibleName: { + ...fontStyles.normal, + fontSize: 32, + color: colors.text.alternative, + textAlign: 'center', + }, + collectibleId: { + ...fontStyles.normal, + fontSize: 14, + color: colors.text.alternative, + marginTop: 8, + textAlign: 'center', + }, + collectibleInputWrapper: { + margin: 24, + }, + collectibleInputImageWrapper: { + flexDirection: 'column', + alignItems: 'center', + }, + collectibleInputInformationWrapper: { + marginTop: 12, + }, + nextActionWrapper: { + flex: 1, + marginBottom: 16, + }, + balanceWrapper: { + marginVertical: 16, + }, + balanceText: { + ...fontStyles.normal, + alignSelf: 'center', + fontSize: 12, + lineHeight: 16, + color: colors.text.default, + }, + }); /** * View that wraps the wraps the "Send" screen */ class Amount extends PureComponent { - static navigationOptions = ({ navigation, route }) => getSendFlowTitle('send.amount', navigation, route); - static propTypes = { /** * Map of accounts to information objects including balances @@ -328,6 +329,10 @@ class Amount extends PureComponent { * Object that represents the navigator */ navigation: PropTypes.object, + /** + * Object that contains navigation props + */ + route: PropTypes.object, /** * A string that represents the selected address */ @@ -397,6 +402,12 @@ class Amount extends PureComponent { tokens = []; collectibles = []; + updateNavBar = () => { + const { navigation, route } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions(getSendFlowTitle('send.amount', navigation, route, colors)); + }; + componentDidMount = async () => { const { tokens, @@ -408,6 +419,7 @@ class Amount extends PureComponent { isPaymentRequest, } = this.props; // For analytics + this.updateNavBar(); navigation.setParams({ providerType, isPaymentRequest }); this.tokens = [getEther(ticker), ...tokens]; @@ -451,6 +463,10 @@ class Amount extends PureComponent { }); }; + componentDidUpdate = () => { + this.updateNavBar(); + }; + /** * Method to validate collectible ownership. * @@ -808,6 +824,9 @@ class Amount extends PureComponent { this.props; let balance, balanceFiat; const { address, decimals, symbol } = token; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + if (token.isETH) { balance = renderFromWei(accounts[selectedAddress].balance); balanceFiat = weiToFiat(hexToBN(accounts[selectedAddress].balance), conversionRate, currentCurrency); @@ -844,6 +863,9 @@ class Amount extends PureComponent { renderCollectible = (collectible, index) => { const { name } = collectible; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( { const { assetsModalVisible } = this.state; const tradableCollectibles = this.collectibles.filter(({ standard }) => standard === 'ERC721'); + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); return ( @@ -938,6 +964,10 @@ class Amount extends PureComponent { currentBalance, } = this.state; const { currentCurrency } = this.props; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance || 'light'; + const styles = createStyles(colors); + return ( @@ -952,7 +982,9 @@ class Amount extends PureComponent { onChangeText={this.onInputChange} keyboardType={'numeric'} placeholder={'0'} + placeholderTextColor={colors.text.muted} testID={'txn-amount-input'} + keyboardAppearance={themeAppearance} /> @@ -967,7 +999,7 @@ class Amount extends PureComponent { @@ -990,6 +1022,9 @@ class Amount extends PureComponent { renderCollectibleInput = () => { const { amountError } = this.state; const { selectedAsset } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -1019,6 +1054,8 @@ class Amount extends PureComponent { selectedAsset, transactionState: { isPaymentRequest }, } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); return ( @@ -1039,7 +1076,7 @@ class Amount extends PureComponent { @@ -1085,6 +1122,8 @@ class Amount extends PureComponent { }; } +Amount.contextType = ThemeContext; + const mapStateToProps = (state, ownProps) => ({ accounts: state.engine.backgroundState.AccountTrackerController.accounts, contractBalances: state.engine.backgroundState.TokenBalancesController.contractBalances, diff --git a/app/components/Views/SendFlow/Confirm/index.js b/app/components/Views/SendFlow/Confirm/index.js index ed12d6618e8..81d71c64eea 100644 --- a/app/components/Views/SendFlow/Confirm/index.js +++ b/app/components/Views/SendFlow/Confirm/index.js @@ -1,5 +1,5 @@ import React, { PureComponent } from 'react'; -import { colors, baseStyles, fontStyles } from '../../../../styles/common'; +import { baseStyles, fontStyles } from '../../../../styles/common'; import { InteractionManager, StyleSheet, @@ -62,6 +62,7 @@ import EditGasFee1559 from '../../../UI/EditGasFee1559'; import EditGasFeeLegacy from '../../../UI/EditGasFeeLegacy'; import CustomNonce from '../../../UI/CustomNonce'; import AppConstants from '../../../../core/AppConstants'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; const EDIT = 'edit'; const EDIT_NONCE = 'edit_nonce'; @@ -77,158 +78,164 @@ const EMPTY_LEGACY_TRANSACTION_DATA = { const { hexToBN, BNToHex } = util; -const styles = StyleSheet.create({ - wrapper: { - flex: 1, - backgroundColor: colors.white, - }, - inputWrapper: { - flex: 0, - borderBottomWidth: 1, - borderBottomColor: colors.grey050, - paddingHorizontal: 8, - }, - amountWrapper: { - flexDirection: 'column', - margin: 24, - }, - textAmountLabel: { - ...fontStyles.normal, - fontSize: 14, - textAlign: 'center', - color: colors.grey500, - textTransform: 'uppercase', - marginVertical: 3, - }, - textAmount: { - ...fontStyles.normal, - fontWeight: fontStyles.light.fontWeight, - color: colors.black, - fontSize: 44, - textAlign: 'center', - }, - buttonNext: { - flex: 1, - marginHorizontal: 24, - alignSelf: 'flex-end', - }, - buttonNextWrapper: { - flexDirection: 'row', - alignItems: 'flex-end', - marginBottom: 16, - }, - actionTouchable: { - padding: 12, - }, - actionText: { - ...fontStyles.normal, - color: colors.blue, - fontSize: 14, - alignSelf: 'center', - }, - actionsWrapper: { - margin: 24, - }, - CollectibleMediaWrapper: { - flexDirection: 'column', - alignItems: 'center', - margin: 16, - }, - collectibleName: { - ...fontStyles.normal, - fontSize: 18, - color: colors.black, - textAlign: 'center', - }, - collectibleTokenId: { - ...fontStyles.normal, - fontSize: 12, - color: colors.grey500, - marginTop: 8, - textAlign: 'center', - }, - CollectibleMedia: { - height: 120, - width: 120, - }, - qrCode: { - marginBottom: 16, - paddingHorizontal: 36, - paddingBottom: 24, - paddingTop: 16, - backgroundColor: colors.grey000, - borderRadius: 8, - width: '100%', - }, - hexDataWrapper: { - padding: 10, - alignItems: 'center', - }, - addressTitle: { - ...fontStyles.bold, - color: colors.black, - alignItems: 'center', - justifyContent: 'center', - textAlign: 'center', - fontSize: 16, - marginBottom: 16, - }, - hexDataClose: { - zIndex: 999, - position: 'absolute', - top: 12, - right: 20, - }, - hexDataText: { - textAlign: 'justify', - }, - bottomModal: { - justifyContent: 'flex-end', - margin: 0, - }, - keyboardAwareWrapper: { - flex: 1, - justifyContent: 'flex-end', - }, - errorWrapper: { - marginHorizontal: 24, - marginTop: 12, - paddingHorizontal: 10, - paddingVertical: 8, - backgroundColor: colors.red000, - borderColor: colors.red, - borderRadius: 8, - borderWidth: 1, - justifyContent: 'center', - alignItems: 'center', - }, - error: { - color: colors.red, - fontSize: 12, - lineHeight: 16, - ...fontStyles.normal, - textAlign: 'center', - }, - underline: { - textDecorationLine: 'underline', - ...fontStyles.bold, - }, - text: { - lineHeight: 20, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + flex: 1, + backgroundColor: colors.background.default, + }, + inputWrapper: { + flex: 0, + borderBottomWidth: 1, + borderBottomColor: colors.border.default, + paddingHorizontal: 8, + }, + amountWrapper: { + flexDirection: 'column', + margin: 24, + }, + textAmountLabel: { + ...fontStyles.normal, + fontSize: 14, + textAlign: 'center', + color: colors.text.alternative, + textTransform: 'uppercase', + marginVertical: 3, + }, + textAmount: { + ...fontStyles.normal, + fontWeight: fontStyles.light.fontWeight, + color: colors.text.default, + fontSize: 44, + textAlign: 'center', + }, + buttonNext: { + flex: 1, + marginHorizontal: 24, + alignSelf: 'flex-end', + }, + buttonNextWrapper: { + flexDirection: 'row', + alignItems: 'flex-end', + marginBottom: 16, + }, + actionTouchable: { + padding: 12, + }, + actionText: { + ...fontStyles.normal, + color: colors.primary.default, + fontSize: 14, + alignSelf: 'center', + }, + actionsWrapper: { + margin: 24, + }, + CollectibleMediaWrapper: { + flexDirection: 'column', + alignItems: 'center', + margin: 16, + }, + collectibleName: { + ...fontStyles.normal, + fontSize: 18, + color: colors.text.default, + textAlign: 'center', + }, + collectibleTokenId: { + ...fontStyles.normal, + fontSize: 12, + color: colors.text.alternative, + marginTop: 8, + textAlign: 'center', + }, + CollectibleMedia: { + height: 120, + width: 120, + }, + qrCode: { + marginBottom: 16, + paddingHorizontal: 36, + paddingBottom: 24, + paddingTop: 16, + backgroundColor: colors.background.default, + borderRadius: 8, + width: '100%', + }, + hexDataWrapper: { + padding: 10, + alignItems: 'center', + borderRadius: 10, + backgroundColor: colors.background.default, + }, + addressTitle: { + ...fontStyles.bold, + color: colors.text.default, + alignItems: 'center', + justifyContent: 'center', + textAlign: 'center', + fontSize: 16, + marginBottom: 16, + }, + hexDataClose: { + zIndex: 999, + position: 'absolute', + top: 12, + right: 20, + }, + hexDataText: { + textAlign: 'justify', + }, + bottomModal: { + justifyContent: 'flex-end', + margin: 0, + }, + keyboardAwareWrapper: { + flex: 1, + justifyContent: 'flex-end', + }, + errorWrapper: { + marginHorizontal: 24, + marginTop: 12, + paddingHorizontal: 10, + paddingVertical: 8, + backgroundColor: colors.error.muted, + borderColor: colors.error.default, + borderRadius: 8, + borderWidth: 1, + justifyContent: 'center', + alignItems: 'center', + }, + error: { + color: colors.text.default, + fontSize: 12, + lineHeight: 16, + ...fontStyles.normal, + textAlign: 'center', + }, + underline: { + textDecorationLine: 'underline', + ...fontStyles.bold, + }, + text: { + lineHeight: 20, + color: colors.text.default, + }, + }); /** * View that wraps the wraps the "Send" screen */ class Confirm extends PureComponent { - static navigationOptions = ({ navigation, route }) => getSendFlowTitle('send.confirm', navigation, route); - static propTypes = { /** * Object that represents the navigator */ navigation: PropTypes.object, + /** + * Object that contains navigation props + */ + route: PropTypes.object, /** * Map of accounts to information objects including balances */ @@ -417,12 +424,19 @@ class Confirm extends PureComponent { toggleWarningModal = () => this.setState((state) => ({ warningModalVisible: !state.warningModalVisible })); + updateNavBar = () => { + const { navigation, route } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions(getSendFlowTitle('send.confirm', navigation, route, colors)); + }; + componentWillUnmount = () => { const { GasFeeController } = Engine.context; GasFeeController.stopPolling(this.state.pollToken); }; componentDidMount = async () => { + this.updateNavBar(); this.getGasLimit(); const { GasFeeController } = Engine.context; @@ -447,6 +461,7 @@ class Confirm extends PureComponent { contractBalances, selectedAsset, } = this.props; + this.updateNavBar(); const { errorMessage, fromSelectedAddress } = this.state; const valueChanged = prevProps.transactionState.transaction.value !== value; @@ -937,6 +952,8 @@ class Confirm extends PureComponent { renderCustomGasModalEIP1559 = () => { const { primaryCurrency, chainId, gasFeeEstimates } = this.props; const { EIP1559TransactionDataTemp, gasSelected, isAnimating, animateOnChange } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); return ( { const { primaryCurrency, chainId, gasEstimateType, gasFeeEstimates } = this.props; const { LegacyTransactionDataTemp, gasSelected, isAnimating, animateOnChange } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( { const { hexDataModalVisible } = this.state; const { data } = this.props.transactionState.transaction; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( - + {strings('transaction.hex_data')} @@ -1069,6 +1096,8 @@ class Confirm extends PureComponent { renderFromAccountModal = () => { const { identities, keyrings, ticker } = this.props; const { fromAccountModalVisible, fromSelectedAddress } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); return ( {transactionConfirmed ? ( - + ) : ( strings('transaction.send') )} @@ -1353,6 +1386,8 @@ class Confirm extends PureComponent { }; } +Confirm.contextType = ThemeContext; + const mapStateToProps = (state) => ({ accounts: state.engine.backgroundState.AccountTrackerController.accounts, addressBook: state.engine.backgroundState.AddressBookController?.addressBook, diff --git a/app/components/Views/SendFlow/SendTo/index.js b/app/components/Views/SendFlow/SendTo/index.js index 392f59c5e48..b39e1439fcd 100644 --- a/app/components/Views/SendFlow/SendTo/index.js +++ b/app/components/Views/SendFlow/SendTo/index.js @@ -1,5 +1,5 @@ import React, { PureComponent } from 'react'; -import { colors, fontStyles, baseStyles } from '../../../../styles/common'; +import { fontStyles, baseStyles } from '../../../../styles/common'; import { getSendFlowTitle } from '../../../UI/Navbar'; import AddressList from './../AddressList'; import PropTypes from 'prop-types'; @@ -31,135 +31,134 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import { collectConfusables, hasZeroWidthPoints } from '../../../../util/validators'; import { SafeAreaView } from 'react-native-safe-area-context'; import addRecent from '../../../../actions/recents'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; import { ADD_ADDRESS_MODAL_CONTAINER_ID, ENTER_ALIAS_INPUT_BOX_ID } from '../../../../constants/test-ids'; const { hexToBN } = util; -const styles = StyleSheet.create({ - wrapper: { - flex: 1, - backgroundColor: colors.white, - }, - imputWrapper: { - flex: 0, - borderBottomWidth: 1, - borderBottomColor: colors.grey050, - paddingHorizontal: 8, - }, - bottomModal: { - justifyContent: 'flex-end', - margin: 0, - }, - myAccountsText: { - ...fontStyles.normal, - color: colors.blue, - fontSize: 16, - alignSelf: 'center', - }, - myAccountsTouchable: { - padding: 28, - }, - addToAddressBookRoot: { - flex: 1, - padding: 24, - }, - addToAddressBookWrapper: { - flexDirection: 'row', - alignItems: 'center', - }, - addTextTitle: { - ...fontStyles.normal, - fontSize: 24, - color: colors.black, - marginBottom: 24, - }, - addTextSubtitle: { - ...fontStyles.normal, - fontSize: 16, - color: colors.grey600, - marginBottom: 24, - }, - addTextInput: { - ...fontStyles.normal, - color: colors.black, - fontSize: 20, - }, - addInputWrapper: { - flexDirection: 'row', - borderWidth: 1, - borderRadius: 8, - borderColor: colors.grey050, - height: 50, - width: '100%', - }, - input: { - flex: 1, - flexDirection: 'row', - alignItems: 'center', - marginHorizontal: 6, - width: '100%', - }, - nextActionWrapper: { - flex: 1, - marginBottom: 16, - }, - buttonNextWrapper: { - flexDirection: 'row', - alignItems: 'flex-end', - }, - buttonNext: { - flex: 1, - marginHorizontal: 24, - }, - addressErrorWrapper: { - margin: 16, - }, - footerContainer: { - flex: 1, - justifyContent: 'flex-end', - }, - warningContainer: { - marginTop: 20, - marginHorizontal: 24, - marginBottom: 32, - }, - buyEth: { - color: colors.black, - textDecorationLine: 'underline', - }, - confusabeError: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - margin: 16, - padding: 16, - borderWidth: 1, - borderColor: colors.red, - backgroundColor: colors.red000, - borderRadius: 8, - }, - confusabeWarning: { - borderColor: colors.yellow, - backgroundColor: colors.yellow100, - }, - confusableTitle: { - marginTop: -3, - color: colors.red, - ...fontStyles.bold, - fontSize: 14, - }, - confusableMsg: { - color: colors.red, - fontSize: 12, - lineHeight: 16, - paddingRight: 10, - }, - black: { - color: colors.black, - }, - warningIcon: { - marginRight: 8, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + flex: 1, + backgroundColor: colors.background.default, + }, + imputWrapper: { + flex: 0, + borderBottomWidth: 1, + borderBottomColor: colors.border.muted, + paddingHorizontal: 8, + }, + bottomModal: { + justifyContent: 'flex-end', + margin: 0, + }, + myAccountsText: { + ...fontStyles.normal, + color: colors.primary.default, + fontSize: 16, + alignSelf: 'center', + }, + myAccountsTouchable: { + padding: 28, + }, + addToAddressBookRoot: { + flex: 1, + padding: 24, + }, + addToAddressBookWrapper: { + flexDirection: 'row', + alignItems: 'center', + }, + addTextTitle: { + ...fontStyles.normal, + fontSize: 24, + color: colors.text.default, + marginBottom: 24, + }, + addTextSubtitle: { + ...fontStyles.normal, + fontSize: 16, + color: colors.text.alternative, + marginBottom: 24, + }, + addTextInput: { + ...fontStyles.normal, + color: colors.text.default, + fontSize: 20, + }, + addInputWrapper: { + flexDirection: 'row', + borderWidth: 1, + borderRadius: 8, + borderColor: colors.border.default, + height: 50, + width: '100%', + }, + input: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + marginHorizontal: 6, + width: '100%', + }, + nextActionWrapper: { + flex: 1, + marginBottom: 16, + }, + buttonNextWrapper: { + flexDirection: 'row', + alignItems: 'flex-end', + }, + buttonNext: { + flex: 1, + marginHorizontal: 24, + }, + addressErrorWrapper: { + margin: 16, + }, + footerContainer: { + flex: 1, + justifyContent: 'flex-end', + }, + warningContainer: { + marginTop: 20, + marginHorizontal: 24, + marginBottom: 32, + }, + buyEth: { + color: colors.primary.default, + textDecorationLine: 'underline', + }, + confusabeError: { + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-between', + margin: 16, + padding: 16, + borderWidth: 1, + borderColor: colors.error.default, + backgroundColor: colors.error.muted, + borderRadius: 8, + }, + confusabeWarning: { + borderColor: colors.warning.default, + backgroundColor: colors.warning.muted, + }, + confusableTitle: { + marginTop: -3, + color: colors.text.default, + ...fontStyles.bold, + fontSize: 14, + }, + confusableMsg: { + color: colors.text.default, + fontSize: 12, + lineHeight: 16, + paddingRight: 10, + }, + warningIcon: { + marginRight: 8, + }, + }); const dummy = () => true; @@ -167,8 +166,6 @@ const dummy = () => true; * View that wraps the wraps the "Send" screen */ class SendFlow extends PureComponent { - static navigationOptions = ({ navigation, route }) => getSendFlowTitle('send.send_to', navigation, route); - static propTypes = { /** * Map of accounts to information objects including balances @@ -249,6 +246,12 @@ class SendFlow extends PureComponent { inputWidth: { width: '99%' }, }; + updateNavBar = () => { + const { navigation, route } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions(getSendFlowTitle('send.send_to', navigation, route, colors)); + }; + componentDidMount = async () => { const { addressBook, @@ -262,6 +265,7 @@ class SendFlow extends PureComponent { isPaymentRequest, } = this.props; const { fromAccountName } = this.state; + this.updateNavBar(); // For analytics navigation.setParams({ providerType, isPaymentRequest }); const networkAddressBook = addressBook[network] || {}; @@ -289,6 +293,10 @@ class SendFlow extends PureComponent { } }; + componentDidUpdate = () => { + this.updateNavBar(); + }; + toggleFromAccountModal = () => { const { fromAccountModalVisible } = this.state; this.setState({ fromAccountModalVisible: !fromAccountModalVisible }); @@ -467,6 +475,10 @@ class SendFlow extends PureComponent { renderAddToAddressBookModal = () => { const { addToAddressBookModalVisible, alias } = this.state; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance || 'light'; + const styles = createStyles(colors); + return ( @@ -514,6 +527,9 @@ class SendFlow extends PureComponent { renderFromAccountModal = () => { const { identities, keyrings, ticker } = this.props; const { fromAccountModalVisible, fromSelectedAddress } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + if (!allowedToBuy(this.props.network)) { return null; } @@ -586,6 +607,8 @@ class SendFlow extends PureComponent { isOnlyWarning, confusableCollection, } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); const checksummedAddress = toSelectedAddress && toChecksumAddress(toSelectedAddress); const existingContact = checksummedAddress && addressBook[network] && addressBook[network][checksummedAddress]; @@ -643,15 +666,15 @@ class SendFlow extends PureComponent { - + {strings('transaction.confusable_title')} - + {strings('transaction.confusable_msg')} @@ -708,6 +731,8 @@ class SendFlow extends PureComponent { }; } +SendFlow.contextType = ThemeContext; + const mapStateToProps = (state) => ({ accounts: state.engine.backgroundState.AccountTrackerController.accounts, addressBook: state.engine.backgroundState.AddressBookController.addressBook, diff --git a/app/components/Views/SendFlow/WarningMessage/index.tsx b/app/components/Views/SendFlow/WarningMessage/index.tsx index 514b2259c4f..7ee2418284d 100644 --- a/app/components/Views/SendFlow/WarningMessage/index.tsx +++ b/app/components/Views/SendFlow/WarningMessage/index.tsx @@ -1,8 +1,8 @@ import React, { ReactNode } from 'react'; import { StyleProp, StyleSheet, ViewStyle } from 'react-native'; -import { colors } from '../../../../styles/common'; import FontAwesome from 'react-native-vector-icons/FontAwesome'; import Alert, { AlertType } from '../../../Base/Alert'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; interface Props { /** @@ -19,16 +19,20 @@ const styles = StyleSheet.create({ }, }); -const WarningMessage = ({ warningMessage, style }: Props) => ( - ( - - )} - > - {warningMessage} - -); +const WarningMessage = ({ warningMessage, style }: Props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + + return ( + ( + + )} + > + {warningMessage} + + ); +}; export default WarningMessage; diff --git a/app/components/Views/Settings/AdvancedSettings/index.js b/app/components/Views/Settings/AdvancedSettings/index.js index 0bc574df567..af553c453fc 100644 --- a/app/components/Views/Settings/AdvancedSettings/index.js +++ b/app/components/Views/Settings/AdvancedSettings/index.js @@ -6,7 +6,7 @@ import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view import ActionModal from '../../../UI/ActionModal'; import Engine from '../../../../core/Engine'; import StyledButton from '../../../UI/StyledButton'; -import { colors, fontStyles, baseStyles } from '../../../../styles/common'; +import { fontStyles, baseStyles, colors as importedColors } from '../../../../styles/common'; import { getNavigationOptionsTitle } from '../../../UI/Navbar'; import { setShowCustomNonce, setShowHexData } from '../../../../actions/settings'; import { strings } from '../../../../../locales/i18n'; @@ -20,76 +20,81 @@ import ipfsGateways from '../../../../util/ipfs-gateways.json'; import SelectComponent from '../../../UI/SelectComponent'; import { timeoutFetch } from '../../../../util/general'; import Device from '../../../../util/device'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; const HASH_TO_TEST = 'Qmaisz6NMhDB51cCvNWa1GMS7LU1pAxdF4Ld6Ft9kZEP2a'; const HASH_STRING = 'Hello from IPFS Gateway Checker'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - padding: 24, - paddingBottom: 48, - }, - title: { - ...fontStyles.normal, - color: colors.fontPrimary, - fontSize: 20, - lineHeight: 20, - paddingTop: 4, - marginTop: -4, - }, - desc: { - ...fontStyles.normal, - color: colors.grey500, - fontSize: 14, - lineHeight: 20, - marginTop: 12, - }, - marginTop: { - marginTop: 18, - }, - setting: { - marginTop: 50, - }, - firstSetting: { - marginTop: 0, - }, - modalView: { - alignItems: 'center', - flex: 1, - flexDirection: 'column', - justifyContent: 'center', - padding: 20, - }, - modalText: { - ...fontStyles.normal, - fontSize: 16, - textAlign: 'center', - color: colors.black, - }, - modalTitle: { - ...fontStyles.bold, - fontSize: 24, - textAlign: 'center', - marginBottom: 20, - color: colors.black, - }, - picker: { - borderColor: colors.grey200, - borderRadius: 5, - borderWidth: 2, - marginTop: 16, - }, - inner: { - paddingBottom: 48, - }, - ipfsGatewayLoadingWrapper: { - height: 37, - alignItems: 'center', - justifyContent: 'center', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + padding: 24, + paddingBottom: 48, + }, + title: { + ...fontStyles.normal, + color: colors.text.default, + fontSize: 20, + lineHeight: 20, + paddingTop: 4, + marginTop: -4, + }, + desc: { + ...fontStyles.normal, + color: colors.text.alternative, + fontSize: 14, + lineHeight: 20, + marginTop: 12, + }, + marginTop: { + marginTop: 18, + }, + switch: { + alignSelf: 'flex-start', + }, + setting: { + marginTop: 50, + }, + firstSetting: { + marginTop: 0, + }, + modalView: { + alignItems: 'center', + flex: 1, + flexDirection: 'column', + justifyContent: 'center', + padding: 20, + }, + modalText: { + ...fontStyles.normal, + fontSize: 16, + textAlign: 'center', + color: colors.text.default, + }, + modalTitle: { + ...fontStyles.bold, + fontSize: 24, + textAlign: 'center', + marginBottom: 20, + color: colors.text.default, + }, + picker: { + borderColor: colors.border.default, + borderRadius: 5, + borderWidth: 2, + marginTop: 16, + }, + inner: { + paddingBottom: 48, + }, + ipfsGatewayLoadingWrapper: { + height: 37, + alignItems: 'center', + justifyContent: 'center', + }, + }); /** * Main view for app configurations @@ -126,9 +131,6 @@ class AdvancedSettings extends PureComponent { fullState: PropTypes.object, }; - static navigationOptions = ({ navigation }) => - getNavigationOptionsTitle(strings('app_settings.advanced_title'), navigation); - state = { resetModalVisible: false, inputWidth: Device.isAndroid() ? '99%' : undefined, @@ -136,7 +138,16 @@ class AdvancedSettings extends PureComponent { gotAvailableGateways: false, }; + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + getNavigationOptionsTitle(strings('app_settings.advanced_title'), navigation, false, colors) + ); + }; + componentDidMount = async () => { + this.updateNavBar(); await this.handleAvailableIpfsGateways(); this.mounted = true; // Workaround https://github.com/facebook/react-native/issues/9958 @@ -146,6 +157,10 @@ class AdvancedSettings extends PureComponent { }, 100); }; + componentDidUpdate = () => { + this.updateNavBar(); + }; + componentWillUnmount = () => { this.mounted = false; }; @@ -235,6 +250,9 @@ class AdvancedSettings extends PureComponent { render = () => { const { showHexData, showCustomNonce, setShowHexData, setShowCustomNonce, ipfsGateway } = this.props; const { resetModalVisible, onlineIpfsGateways } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -293,8 +311,10 @@ class AdvancedSettings extends PureComponent { @@ -305,8 +325,10 @@ class AdvancedSettings extends PureComponent { @@ -328,6 +350,8 @@ class AdvancedSettings extends PureComponent { }; } +AdvancedSettings.contextType = ThemeContext; + const mapStateToProps = (state) => ({ ipfsGateway: state.engine.backgroundState.PreferencesController.ipfsGateway, showHexData: state.settings.showHexData, diff --git a/app/components/Views/Settings/AppInformation/index.js b/app/components/Views/Settings/AppInformation/index.js index 2588612dd06..576d7415b6e 100644 --- a/app/components/Views/Settings/AppInformation/index.js +++ b/app/components/Views/Settings/AppInformation/index.js @@ -10,62 +10,65 @@ import { TouchableOpacity, } from 'react-native'; import { getApplicationName, getVersion, getBuildNumber } from 'react-native-device-info'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles } from '../../../../styles/common'; import PropTypes from 'prop-types'; import { strings } from '../../../../../locales/i18n'; import { getNavigationOptionsTitle } from '../../../UI/Navbar'; import AppConstants from '../../../../core/AppConstants'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - }, - wrapperContent: { - paddingLeft: 24, - paddingRight: 24, - paddingVertical: 24, - }, - title: { - fontSize: 18, - textAlign: 'left', - marginBottom: 20, - ...fontStyles.normal, - }, - link: { - fontSize: 18, - textAlign: 'left', - marginBottom: 20, - ...fontStyles.normal, - color: colors.blue, - }, - division: { - borderBottomColor: colors.grey400, - borderBottomWidth: 1, - width: '30%', - marginBottom: 20, - }, - image: { - width: 100, - height: 100, - }, - logoWrapper: { - flex: 1, - backgroundColor: colors.white, - alignItems: 'center', - justifyContent: 'center', - top: 20, - marginBottom: 40, - }, - versionInfo: { - marginTop: 20, - fontSize: 18, - textAlign: 'left', - marginBottom: 20, - color: colors.fontSecondary, - ...fontStyles.normal, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + wrapperContent: { + paddingLeft: 24, + paddingRight: 24, + paddingVertical: 24, + }, + title: { + fontSize: 18, + textAlign: 'left', + marginBottom: 20, + ...fontStyles.normal, + color: colors.text.default, + }, + link: { + fontSize: 18, + textAlign: 'left', + marginBottom: 20, + ...fontStyles.normal, + color: colors.primary.default, + }, + division: { + borderBottomColor: colors.border.muted, + borderBottomWidth: 1, + width: '30%', + marginBottom: 20, + }, + image: { + width: 100, + height: 100, + }, + logoWrapper: { + flex: 1, + backgroundColor: colors.background.default, + alignItems: 'center', + justifyContent: 'center', + top: 20, + marginBottom: 40, + }, + versionInfo: { + marginTop: 20, + fontSize: 18, + textAlign: 'left', + marginBottom: 20, + color: colors.text.alternative, + ...fontStyles.normal, + }, + }); const foxImage = require('../../../../images/fox.png'); // eslint-disable-line import/no-commonjs @@ -73,9 +76,6 @@ const foxImage = require('../../../../images/fox.png'); // eslint-disable-line i * View that contains app information */ export default class AppInformation extends PureComponent { - static navigationOptions = ({ navigation }) => - getNavigationOptionsTitle(strings('app_settings.info_title'), navigation); - static propTypes = { /** /* navigation object required to push new views @@ -87,13 +87,24 @@ export default class AppInformation extends PureComponent { appInfo: '', }; + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions(getNavigationOptionsTitle(strings('app_settings.info_title'), navigation, false, colors)); + }; + componentDidMount = async () => { + this.updateNavBar(); const appName = await getApplicationName(); const appVersion = await getVersion(); const buildNumber = await getBuildNumber(); this.setState({ appInfo: `${appName} v${appVersion} (${buildNumber})` }); }; + componentDidUpdate = () => { + this.updateNavBar(); + }; + goTo = (url, title) => { InteractionManager.runAfterInteractions(() => { this.props.navigation.navigate('Webview', { @@ -136,38 +147,45 @@ export default class AppInformation extends PureComponent { this.goTo(url, strings('drawer.metamask_support')); }; - render = () => ( - - - - - {this.state.appInfo} - - {strings('app_information.links')} - - - {strings('app_information.privacy_policy')} - - - {strings('app_information.terms_of_use')} - - - {strings('app_information.attributions')} - - - - - - {strings('app_information.support_center')} - - - {strings('app_information.web_site')} - - - {strings('app_information.contact_us')} - - - - - ); + render = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + + + + {this.state.appInfo} + + {strings('app_information.links')} + + + {strings('app_information.privacy_policy')} + + + {strings('app_information.terms_of_use')} + + + {strings('app_information.attributions')} + + + + + + {strings('app_information.support_center')} + + + {strings('app_information.web_site')} + + + {strings('app_information.contact_us')} + + + + + ); + }; } + +AppInformation.contextType = ThemeContext; diff --git a/app/components/Views/Settings/Contacts/ContactForm/index.js b/app/components/Views/Settings/Contacts/ContactForm/index.js index f416840d256..d735645d35f 100644 --- a/app/components/Views/Settings/Contacts/ContactForm/index.js +++ b/app/components/Views/Settings/Contacts/ContactForm/index.js @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import { Platform, SafeAreaView, StyleSheet, TextInput, View, Text, TouchableOpacity } from 'react-native'; -import { colors, fontStyles } from '../../../../../styles/common'; +import { fontStyles } from '../../../../../styles/common'; import PropTypes from 'prop-types'; import { getEditableOptions } from '../../../../UI/Navbar'; import StyledButton from '../../../../UI/StyledButton'; @@ -14,75 +14,80 @@ import { isENS, renderShortAddress } from '../../../../../util/address'; import ErrorMessage from '../../../SendFlow/ErrorMessage'; import AntIcon from 'react-native-vector-icons/AntDesign'; import ActionSheet from 'react-native-actionsheet'; +import { ThemeContext, mockTheme } from '../../../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - flexDirection: 'column', - }, - scrollWrapper: { - flex: 1, - paddingVertical: 12, - }, - input: { - ...fontStyles.normal, - flex: 1, - fontSize: 12, - borderColor: colors.grey200, - borderRadius: 5, - borderWidth: 2, - padding: 10, - flexDirection: 'row', - alignItems: 'center', - }, - resolvedInput: { - ...fontStyles.normal, - fontSize: 10, - }, - informationWrapper: { - flex: 1, - paddingHorizontal: 24, - }, - label: { - fontSize: 14, - paddingVertical: 12, - color: colors.fontPrimary, - ...fontStyles.bold, - }, - buttonsWrapper: { - marginVertical: 12, - flexDirection: 'row', - alignSelf: 'flex-end', - }, - buttonsContainer: { - flex: 1, - flexDirection: 'column', - alignSelf: 'flex-end', - }, - scanIcon: { - flexDirection: 'column', - alignItems: 'center', - }, - iconWrapper: { - alignItems: 'flex-end', - }, - textInput: { - ...fontStyles.normal, - padding: 0, - color: colors.black, - }, - inputWrapper: { - flex: 1, - flexDirection: 'column', - }, - textInputDisaled: { - borderColor: colors.transparent, - }, - actionButton: { - marginVertical: 4, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + flexDirection: 'column', + }, + scrollWrapper: { + flex: 1, + paddingVertical: 12, + }, + input: { + ...fontStyles.normal, + flex: 1, + fontSize: 12, + borderColor: colors.border.default, + borderRadius: 5, + borderWidth: 2, + padding: 10, + flexDirection: 'row', + alignItems: 'center', + color: colors.text.default, + }, + resolvedInput: { + ...fontStyles.normal, + fontSize: 10, + color: colors.text.default, + }, + informationWrapper: { + flex: 1, + paddingHorizontal: 24, + }, + label: { + fontSize: 14, + paddingVertical: 12, + color: colors.text.default, + ...fontStyles.bold, + }, + buttonsWrapper: { + marginVertical: 12, + flexDirection: 'row', + alignSelf: 'flex-end', + }, + buttonsContainer: { + flex: 1, + flexDirection: 'column', + alignSelf: 'flex-end', + }, + scanIcon: { + flexDirection: 'column', + alignItems: 'center', + }, + iconWrapper: { + alignItems: 'flex-end', + }, + textInput: { + ...fontStyles.normal, + padding: 0, + paddingRight: 8, + color: colors.text.default, + }, + inputWrapper: { + flex: 1, + flexDirection: 'column', + }, + textInputDisaled: { + borderColor: colors.transparent, + }, + actionButton: { + marginVertical: 4, + }, + }); const ADD = 'add'; const EDIT = 'edit'; @@ -91,9 +96,6 @@ const EDIT = 'edit'; * View that contains app information */ class ContactForm extends PureComponent { - static navigationOptions = ({ navigation, route }) => - getEditableOptions(strings(`address_book.${route.params?.mode ?? ADD}_contact_title`), navigation, route); - static propTypes = { /** * Object that represents the navigator @@ -133,9 +135,23 @@ class ContactForm extends PureComponent { addressInput = React.createRef(); memoInput = React.createRef(); + updateNavBar = () => { + const { navigation, route } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + getEditableOptions( + strings(`address_book.${route.params?.mode ?? ADD}_contact_title`), + navigation, + route, + colors + ) + ); + }; + componentDidMount = () => { const { mode } = this.state; const { navigation } = this.props; + this.updateNavBar(); // Workaround https://github.com/facebook/react-native/issues/9958 this.state.inputWidth && setTimeout(() => { @@ -151,6 +167,10 @@ class ContactForm extends PureComponent { } }; + componentDidUpdate = () => { + this.updateNavBar(); + }; + onEdit = () => { const { navigation } = this.props; const { editable } = this.state; @@ -254,6 +274,10 @@ class ContactForm extends PureComponent { render = () => { const { address, addressError, toEnsName, name, mode, addressReady, memo, editable, inputWidth } = this.state; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance || 'light'; + const styles = createStyles(colors); + return ( @@ -265,7 +289,7 @@ class ContactForm extends PureComponent { autoCorrect={false} onChangeText={this.onChangeName} placeholder={strings('address_book.nickname')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} spellCheck={false} numberOfLines={1} style={[ @@ -276,6 +300,7 @@ class ContactForm extends PureComponent { value={name} onSubmitEditing={this.jumpToAddressInput} testID={'contact-name-input'} + keyboardAppearance={themeAppearance} /> {strings('address_book.address')} @@ -287,7 +312,7 @@ class ContactForm extends PureComponent { autoCorrect={false} onChangeText={this.onChangeAddress} placeholder={strings('address_book.add_input_placeholder')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} spellCheck={false} numberOfLines={1} style={[styles.textInput, inputWidth ? { width: inputWidth } : {}]} @@ -295,13 +320,19 @@ class ContactForm extends PureComponent { ref={this.addressInput} onSubmitEditing={this.jumpToMemoInput} testID={'contact-address-input'} + keyboardAppearance={themeAppearance} /> {toEnsName && {renderShortAddress(address)}} {editable && ( - + )} @@ -316,13 +347,14 @@ class ContactForm extends PureComponent { autoCorrect={false} onChangeText={this.onChangeMemo} placeholder={strings('address_book.memo')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} spellCheck={false} numberOfLines={1} style={[styles.textInput, inputWidth ? { width: inputWidth } : {}]} value={memo} ref={this.memoInput} testID={'contact-memo-input'} + keyboardAppearance={themeAppearance} /> @@ -366,6 +398,7 @@ class ContactForm extends PureComponent { destructiveButtonIndex={0} // eslint-disable-next-line react/jsx-no-bind onPress={(index) => (index === 0 ? this.deleteContact() : null)} + theme={themeAppearance} /> @@ -373,6 +406,8 @@ class ContactForm extends PureComponent { }; } +ContactForm.contextType = ThemeContext; + const mapStateToProps = (state) => ({ addressBook: state.engine.backgroundState.AddressBookController.addressBook, identities: state.engine.backgroundState.PreferencesController.identities, diff --git a/app/components/Views/Settings/Contacts/index.js b/app/components/Views/Settings/Contacts/index.js index f6e4562a4b7..ad6f9c1b3cb 100644 --- a/app/components/Views/Settings/Contacts/index.js +++ b/app/components/Views/Settings/Contacts/index.js @@ -1,6 +1,5 @@ import React, { PureComponent } from 'react'; import { SafeAreaView, StyleSheet } from 'react-native'; -import { colors } from '../../../../styles/common'; import PropTypes from 'prop-types'; import { strings } from '../../../../../locales/i18n'; import { getNavigationOptionsTitle } from '../../../UI/Navbar'; @@ -9,17 +8,19 @@ import AddressList from '../../SendFlow/AddressList'; import StyledButton from '../../../UI/StyledButton'; import Engine from '../../../../core/Engine'; import ActionSheet from 'react-native-actionsheet'; - -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - }, - addContact: { - marginHorizontal: 24, - marginBottom: 16, - }, -}); +import { ThemeContext, mockTheme } from '../../../../util/theme'; + +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + addContact: { + marginHorizontal: 24, + marginBottom: 16, + }, + }); const EDIT = 'edit'; const ADD = 'add'; @@ -28,9 +29,6 @@ const ADD = 'add'; * View that contains app information */ class Contacts extends PureComponent { - static navigationOptions = ({ navigation }) => - getNavigationOptionsTitle(strings('app_settings.contacts_title'), navigation); - static propTypes = { /** * Map representing the address book @@ -53,7 +51,20 @@ class Contacts extends PureComponent { actionSheet; contactAddressToRemove; + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + getNavigationOptionsTitle(strings('app_settings.contacts_title'), navigation, false, colors) + ); + }; + + componentDidMount = () => { + this.updateNavBar(); + }; + componentDidUpdate = (prevProps) => { + this.updateNavBar(); const { network } = this.props; if ( prevProps.addressBook && @@ -96,16 +107,16 @@ class Contacts extends PureComponent { this.props.navigation.navigate('ContactForm', { mode: ADD }); }; - goToEditContact = () => { - this.props.navigation.navigate('ContactsEdit'); - }; - createActionSheetRef = (ref) => { this.actionSheet = ref; }; render = () => { const { reloadAddressList } = this.state; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance; + const styles = createStyles(colors); + return ( (index === 0 ? this.deleteContact() : null)} + theme={themeAppearance} /> ); }; } +Contacts.contextType = ThemeContext; + const mapStateToProps = (state) => ({ addressBook: state.engine.backgroundState.AddressBookController.addressBook, network: state.engine.backgroundState.NetworkController.network, diff --git a/app/components/Views/Settings/ExperimentalSettings/index.tsx b/app/components/Views/Settings/ExperimentalSettings/index.tsx index cd54194cf6f..c5ee0964e8a 100644 --- a/app/components/Views/Settings/ExperimentalSettings/index.tsx +++ b/app/components/Views/Settings/ExperimentalSettings/index.tsx @@ -1,47 +1,49 @@ import React, { useCallback, useEffect } from 'react'; import { StyleSheet, Text, ScrollView, View, Switch, InteractionManager } from 'react-native'; import StyledButton from '../../../UI/StyledButton'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles, colors as importedColors } from '../../../../styles/common'; import { getNavigationOptionsTitle } from '../../../UI/Navbar'; import { strings } from '../../../../../locales/i18n'; -import Device from '../../../../util/device'; import Engine from '../../../../core/Engine'; import { useSelector } from 'react-redux'; import { MAINNET } from '../../../../constants/network'; import AnalyticsV2 from '../../../../util/analyticsV2'; +import { useAppThemeFromContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - padding: 24, - paddingBottom: 48, - }, - title: { - ...(fontStyles.normal as any), - color: colors.fontPrimary, - fontSize: 20, - lineHeight: 20, - paddingTop: 4, - marginTop: -4, - }, - desc: { - ...(fontStyles.normal as any), - color: colors.grey500, - fontSize: 14, - lineHeight: 20, - marginTop: 12, - }, - setting: { - marginVertical: 18, - }, - clearHistoryConfirm: { - marginTop: 18, - }, - switchElement: { - marginTop: 18, - }, -}); +const createStyles = (colors: any) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + padding: 24, + paddingBottom: 48, + }, + title: { + ...(fontStyles.normal as any), + color: colors.text.default, + fontSize: 20, + lineHeight: 20, + paddingTop: 4, + marginTop: -4, + }, + desc: { + ...(fontStyles.normal as any), + color: colors.text.alternative, + fontSize: 14, + lineHeight: 20, + marginTop: 12, + }, + setting: { + marginVertical: 18, + }, + clearHistoryConfirm: { + marginTop: 18, + }, + switchElement: { + marginTop: 18, + alignItems: 'flex-start', + }, + }); interface Props { /** @@ -67,14 +69,22 @@ const ExperimentalSettings = ({ navigation, route }: Props) => { ); const chainId = useSelector((state: any) => state.engine.backgroundState.NetworkController.provider.chainId); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + useEffect( () => { navigation.setOptions( - getNavigationOptionsTitle(strings('app_settings.experimental_title'), navigation, isFullScreenModal) + getNavigationOptionsTitle( + strings('app_settings.experimental_title'), + navigation, + isFullScreenModal, + colors + ) ); }, // eslint-disable-next-line react-hooks/exhaustive-deps - [] + [colors] ); const goToWalletConnectSessions = useCallback(() => { @@ -106,13 +116,14 @@ const ExperimentalSettings = ({ navigation, route }: Props) => { ) : null, - [isTokenDetectionEnabled, toggleTokenDetection, isMainnet] + [isTokenDetectionEnabled, toggleTokenDetection, isMainnet, colors, styles] ); return ( diff --git a/app/components/Views/Settings/GeneralSettings/index.js b/app/components/Views/Settings/GeneralSettings/index.js index 697c3585845..91a95f82b17 100644 --- a/app/components/Views/Settings/GeneralSettings/index.js +++ b/app/components/Views/Settings/GeneralSettings/index.js @@ -7,7 +7,7 @@ import Engine from '../../../../core/Engine'; import I18n, { strings, getLanguages, setLocale } from '../../../../../locales/i18n'; import SelectComponent from '../../../UI/SelectComponent'; import infuraCurrencies from '../../../../util/infura-conversion.json'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles, colors as importedColors } from '../../../../styles/common'; import { getNavigationOptionsTitle } from '../../../UI/Navbar'; import { setSearchEngine, @@ -17,8 +17,10 @@ import { } from '../../../../actions/settings'; import PickComponent from '../../PickComponent'; import { toDataUrl } from '../../../../util/blockies.js'; -import Device from '../../../../util/device'; import Jazzicon from 'react-native-jazzicon'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; +// import { AppThemeKey } from '../../../../util/theme/models'; +// import StyledButton from '../../../UI/StyledButton'; const diameter = 40; const spacing = 8; @@ -33,86 +35,91 @@ const infuraCurrencyOptions = sortedCurrencies.map(({ quote: { code, name } }) = value: code, })); -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - padding: 24, - zIndex: 99999999999999, - }, - title: { - ...fontStyles.normal, - color: colors.fontPrimary, - fontSize: 20, - lineHeight: 20, - paddingTop: 4, - marginTop: -4, - }, - desc: { - ...fontStyles.normal, - color: colors.grey500, - fontSize: 14, - lineHeight: 20, - marginTop: 12, - }, - marginTop: { - marginTop: 18, - }, - picker: { - borderColor: colors.grey200, - borderRadius: 5, - borderWidth: 2, - marginTop: 16, - }, - simplePicker: { - marginTop: 16, - }, - setting: { - marginTop: 50, - }, - firstSetting: { - marginTop: 0, - }, - inner: { - paddingBottom: 48, - }, - identicon_container: { - marginVertical: 16, - display: 'flex', - flexDirection: 'row', - }, - identicon_row: { - width: '50%', - alignItems: 'center', - flexDirection: 'row', - }, - identicon_type: { - ...fontStyles.bold, - fontSize: 14, - marginHorizontal: 10, - }, - blockie: { - height: diameter, - width: diameter, - borderRadius: diameter / 2, - }, - border: { - height: diameter + spacing, - width: diameter + spacing, - borderRadius: (diameter + spacing) / 2, - backgroundColor: colors.white, - borderWidth: 2, - borderColor: colors.white, - alignItems: 'center', - justifyContent: 'center', - }, - selected: { - borderColor: colors.blue, - }, - selected_text: { - color: colors.black, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + padding: 24, + zIndex: 99999999999999, + }, + title: { + ...fontStyles.normal, + color: colors.text.default, + fontSize: 20, + lineHeight: 20, + paddingTop: 4, + marginTop: -4, + }, + desc: { + ...fontStyles.normal, + color: colors.text.alternative, + fontSize: 14, + lineHeight: 20, + marginTop: 12, + }, + marginTop: { + marginTop: 18, + }, + picker: { + borderColor: colors.border.default, + borderRadius: 5, + borderWidth: 2, + marginTop: 16, + }, + simplePicker: { + marginTop: 16, + }, + setting: { + marginTop: 50, + }, + switch: { + alignSelf: 'flex-start', + }, + firstSetting: { + marginTop: 0, + }, + inner: { + paddingBottom: 100, + }, + identicon_container: { + marginVertical: 16, + display: 'flex', + flexDirection: 'row', + }, + identicon_row: { + width: '50%', + alignItems: 'center', + flexDirection: 'row', + }, + identicon_type: { + ...fontStyles.bold, + fontSize: 14, + marginHorizontal: 10, + color: colors.text.default, + }, + blockie: { + height: diameter, + width: diameter, + borderRadius: diameter / 2, + }, + border: { + height: diameter + spacing, + width: diameter + spacing, + borderRadius: (diameter + spacing) / 2, + backgroundColor: colors.background.default, + borderWidth: 2, + borderColor: colors.background.default, + alignItems: 'center', + justifyContent: 'center', + }, + selected: { + borderColor: colors.primary.default, + }, + selected_text: { + color: colors.text.default, + }, + }); /** * Main view for general app configurations @@ -163,11 +170,12 @@ class Settings extends PureComponent { * Called to toggle zero balance token display */ setHideZeroBalanceTokens: PropTypes.func, + /** + * App theme + */ + // appTheme: PropTypes.string, }; - static navigationOptions = ({ navigation }) => - getNavigationOptionsTitle(strings('app_settings.general_title'), navigation); - state = { currentLanguage: I18n.locale.substr(0, 2), languages: {}, @@ -197,7 +205,16 @@ class Settings extends PureComponent { this.props.setHideZeroBalanceTokens(toggleHideZeroBalanceTokens); }; + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + getNavigationOptionsTitle(strings('app_settings.general_title'), navigation, false, colors) + ); + }; + componentDidMount = () => { + this.updateNavBar(); const languages = getLanguages(); this.setState({ languages }); this.languageOptions = Object.keys(languages).map((key) => ({ value: key, label: languages[key], key })); @@ -211,6 +228,38 @@ class Settings extends PureComponent { ]; }; + componentDidUpdate = () => { + this.updateNavBar(); + }; + + // TODO - Reintroduce once we enable manual theme settings + // goToThemeSettings = () => { + // const { navigation } = this.props; + // navigation.navigate('ThemeSettings'); + // }; + + // renderThemeSettingsSection = () => { + // const { appTheme } = this.props; + // const colors = this.context.colors || mockTheme.colors; + // const styles = createStyles(colors); + + // return ( + // + // + // + // {strings('app_settings.theme_title', { + // theme: strings(`app_settings.theme_${AppThemeKey[appTheme]}`), + // })} + // + // {strings('app_settings.theme_description')} + // + // {strings('app_settings.theme_button_text')} + // + // + // + // ); + // }; + render() { const { currentCurrency, @@ -220,6 +269,9 @@ class Settings extends PureComponent { selectedAddress, hideZeroBalanceTokens, } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -286,8 +338,10 @@ class Settings extends PureComponent { @@ -313,12 +367,15 @@ class Settings extends PureComponent { + {/* {this.renderThemeSettingsSection()} */} ); } } +Settings.contextType = ThemeContext; + const mapStateToProps = (state) => ({ currentCurrency: state.engine.backgroundState.CurrencyRateController.currentCurrency, searchEngine: state.settings.searchEngine, @@ -326,6 +383,7 @@ const mapStateToProps = (state) => ({ useBlockieIcon: state.settings.useBlockieIcon, selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress, hideZeroBalanceTokens: state.settings.hideZeroBalanceTokens, + // appTheme: state.user.appTheme, }); const mapDispatchToProps = (dispatch) => ({ diff --git a/app/components/Views/Settings/GeneralSettings/index.test.tsx b/app/components/Views/Settings/GeneralSettings/index.test.tsx index 9d662d191b1..768c6a66901 100644 --- a/app/components/Views/Settings/GeneralSettings/index.test.tsx +++ b/app/components/Views/Settings/GeneralSettings/index.test.tsx @@ -3,6 +3,7 @@ import { shallow } from 'enzyme'; import GeneralSettings from './'; import configureMockStore from 'redux-mock-store'; import { Provider } from 'react-redux'; +import { AppThemeKey } from '../../../../util/theme/models'; const mockStore = configureMockStore(); const initialState = { @@ -20,6 +21,7 @@ const initialState = { PreferencesController: { selectedAddress: '0x0' }, }, }, + user: { appTheme: AppThemeKey.light }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js b/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js index 0bfddd3384c..8cb0919a067 100644 --- a/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js +++ b/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React, { PureComponent } from 'react'; import { StyleSheet, Text, View, TextInput, SafeAreaView } from 'react-native'; import { connect } from 'react-redux'; -import { colors, fontStyles } from '../../../../../styles/common'; +import { fontStyles } from '../../../../../styles/common'; import { getNavigationOptionsTitle } from '../../../../UI/Navbar'; import { strings } from '../../../../../../locales/i18n'; import Networks, { isprivateConnection, getAllNetworks, isSafeChainId } from '../../../../../util/networks'; @@ -18,68 +18,71 @@ import Logger from '../../../../../util/Logger'; import { isPrefixedFormattedHexString } from '../../../../../util/number'; import AppConstants from '../../../../../core/AppConstants'; import AnalyticsV2 from '../../../../../util/analyticsV2'; - -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - flexDirection: 'column', - }, - informationWrapper: { - flex: 1, - paddingHorizontal: 24, - }, - scrollWrapper: { - flex: 1, - paddingVertical: 12, - }, - input: { - ...fontStyles.normal, - borderColor: colors.grey200, - borderRadius: 5, - borderWidth: 2, - padding: 10, - }, - warningText: { - ...fontStyles.normal, - color: colors.red, - marginTop: 4, - paddingLeft: 2, - paddingRight: 4, - }, - warningContainer: { - marginTop: 4, - flexGrow: 1, - flexShrink: 1, - }, - label: { - fontSize: 14, - paddingVertical: 12, - color: colors.fontPrimary, - ...fontStyles.bold, - }, - title: { - fontSize: 20, - paddingVertical: 12, - color: colors.fontPrimary, - ...fontStyles.bold, - }, - desc: { - fontSize: 14, - color: colors.fontPrimary, - ...fontStyles.normal, - }, - buttonsWrapper: { - marginVertical: 12, - flexDirection: 'row', - alignSelf: 'flex-end', - }, - buttonsContainer: { - flex: 1, - flexDirection: 'column', - alignSelf: 'flex-end', - }, -}); +import { ThemeContext, mockTheme } from '../../../../../util/theme'; + +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + flexDirection: 'column', + }, + informationWrapper: { + flex: 1, + paddingHorizontal: 24, + }, + scrollWrapper: { + flex: 1, + paddingVertical: 12, + }, + input: { + ...fontStyles.normal, + borderColor: colors.border.default, + borderRadius: 5, + borderWidth: 2, + padding: 10, + color: colors.text.default, + }, + warningText: { + ...fontStyles.normal, + color: colors.error.default, + marginTop: 4, + paddingLeft: 2, + paddingRight: 4, + }, + warningContainer: { + marginTop: 4, + flexGrow: 1, + flexShrink: 1, + }, + label: { + fontSize: 14, + paddingVertical: 12, + color: colors.text.default, + ...fontStyles.bold, + }, + title: { + fontSize: 20, + paddingVertical: 12, + color: colors.text.default, + ...fontStyles.bold, + }, + desc: { + fontSize: 14, + color: colors.text.default, + ...fontStyles.normal, + }, + buttonsWrapper: { + marginVertical: 12, + flexDirection: 'row', + alignSelf: 'flex-end', + }, + buttonsContainer: { + flex: 1, + flexDirection: 'column', + alignSelf: 'flex-end', + }, + }); const allNetworks = getAllNetworks(); const allNetworksblockExplorerUrl = `https://api.infura.io/v1/jsonrpc/`; @@ -102,9 +105,6 @@ class NetworkSettings extends PureComponent { route: PropTypes.object, }; - static navigationOptions = ({ navigation }) => - getNavigationOptionsTitle(strings('app_settings.networks_title'), navigation); - state = { rpcUrl: undefined, blockExplorerUrl: undefined, @@ -129,7 +129,16 @@ class NetworkSettings extends PureComponent { getOtherNetworks = () => allNetworks.slice(1); + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + getNavigationOptionsTitle(strings('app_settings.networks_title'), navigation, false, colors) + ); + }; + componentDidMount = () => { + this.updateNavBar(); const { route, frequentRpcList } = this.props; const network = route.params?.network; let blockExplorerUrl, chainId, nickname, ticker, editable, rpcUrl; @@ -164,6 +173,10 @@ class NetworkSettings extends PureComponent { }, 100); }; + componentDidUpdate = () => { + this.updateNavBar(); + }; + /** * Attempts to convert the given chainId to a decimal string, for display * purposes. @@ -472,6 +485,10 @@ class NetworkSettings extends PureComponent { enableAction, inputWidth, } = this.state; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance || 'light'; + const styles = createStyles(colors); + return ( @@ -492,9 +509,10 @@ class NetworkSettings extends PureComponent { editable={editable} onChangeText={this.onNicknameChange} placeholder={strings('app_settings.network_name_placeholder')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} onSubmitEditing={this.jumpToRpcURL} testID={'input-network-name'} + keyboardAppearance={themeAppearance} /> {strings('app_settings.network_rpc_url_label')} @@ -508,9 +526,10 @@ class NetworkSettings extends PureComponent { onChangeText={this.onRpcUrlChange} onBlur={this.validateRpcUrl} placeholder={strings('app_settings.network_rpc_placeholder')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} onSubmitEditing={this.jumpToChainId} testID={'input-rpc-url'} + keyboardAppearance={themeAppearance} /> {warningRpcUrl && ( @@ -529,10 +548,11 @@ class NetworkSettings extends PureComponent { onChangeText={this.onChainIDChange} onBlur={this.validateChainId} placeholder={strings('app_settings.network_chain_id_placeholder')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} onSubmitEditing={this.jumpToSymbol} keyboardType={'numbers-and-punctuation'} testID={'input-chain-id'} + keyboardAppearance={themeAppearance} /> {warningChainId ? ( @@ -550,9 +570,10 @@ class NetworkSettings extends PureComponent { editable={editable} onChangeText={this.onTickerChange} placeholder={strings('app_settings.network_symbol_placeholder')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} onSubmitEditing={this.jumpBlockExplorerURL} testID={'input-network-symbol'} + keyboardAppearance={themeAppearance} /> {strings('app_settings.network_block_explorer_label')} @@ -565,8 +586,9 @@ class NetworkSettings extends PureComponent { editable={editable} onChangeText={this.onBlockExplorerUrlChange} placeholder={strings('app_settings.network_block_explorer_placeholder')} - placeholderTextColor={colors.grey100} + placeholderTextColor={colors.text.muted} onSubmitEditing={this.addRpcUrl} + keyboardAppearance={themeAppearance} /> {(addMode || editable) && ( @@ -592,6 +614,8 @@ class NetworkSettings extends PureComponent { } } +NetworkSettings.contextType = ThemeContext; + const mapStateToProps = (state) => ({ frequentRpcList: state.engine.backgroundState.PreferencesController.frequentRpcList, }); diff --git a/app/components/Views/Settings/NetworksSettings/index.js b/app/components/Views/Settings/NetworksSettings/index.js index b82aafab1b7..7b8aa6cc332 100644 --- a/app/components/Views/Settings/NetworksSettings/index.js +++ b/app/components/Views/Settings/NetworksSettings/index.js @@ -3,57 +3,59 @@ import React, { PureComponent } from 'react'; import { StyleSheet, Text, ScrollView, TouchableOpacity, View } from 'react-native'; import { connect } from 'react-redux'; import ActionSheet from 'react-native-actionsheet'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles } from '../../../../styles/common'; import { getNavigationOptionsTitle } from '../../../UI/Navbar'; import { strings } from '../../../../../locales/i18n'; import Networks, { getAllNetworks } from '../../../../util/networks'; import StyledButton from '../../../UI/StyledButton'; import Engine from '../../../../core/Engine'; import { MAINNET, RPC } from '../../../../constants/network'; +import { ThemeContext, mockTheme } from '../../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - paddingVertical: 12, - paddingHorizontal: 24, - marginBottom: 24, - }, - networkIcon: { - width: 15, - height: 15, - borderRadius: 100, - marginTop: 2, - marginRight: 16, - }, - otherNetworkIcon: { - width: 15, - height: 15, - borderRadius: 100, - marginTop: 2, - backgroundColor: colors.grey100, - }, - network: { - flex: 1, - flexDirection: 'row', - paddingVertical: 12, - }, - networkWrapper: { - flex: 0, - flexDirection: 'row', - }, - networkLabel: { - fontSize: 16, - color: colors.fontPrimary, - ...fontStyles.normal, - }, - sectionLabel: { - fontSize: 14, - paddingVertical: 12, - color: colors.fontPrimary, - ...fontStyles.bold, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + paddingVertical: 12, + paddingHorizontal: 24, + paddingBottom: 36, + }, + networkIcon: { + width: 15, + height: 15, + borderRadius: 100, + marginTop: 2, + marginRight: 16, + }, + otherNetworkIcon: { + width: 15, + height: 15, + borderRadius: 100, + marginTop: 2, + backgroundColor: colors.icon.muted, + }, + network: { + flex: 1, + flexDirection: 'row', + paddingVertical: 12, + }, + networkWrapper: { + flex: 0, + flexDirection: 'row', + }, + networkLabel: { + fontSize: 16, + color: colors.text.default, + ...fontStyles.normal, + }, + sectionLabel: { + fontSize: 14, + paddingVertical: 12, + color: colors.text.default, + ...fontStyles.bold, + }, + }); /** * Main view for app configurations @@ -81,11 +83,24 @@ class NetworksSettings extends PureComponent { actionSheet = null; networkToRemove = null; - static navigationOptions = ({ navigation }) => - getNavigationOptionsTitle(strings('app_settings.networks_title'), navigation); - state = {}; + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + getNavigationOptionsTitle(strings('app_settings.networks_title'), navigation, false, colors) + ); + }; + + componentDidMount = () => { + this.updateNavBar(); + }; + + componentDidUpdate = () => { + this.updateNavBar(); + }; + getOtherNetworks = () => getAllNetworks().slice(1); onPress = (network) => { @@ -130,6 +145,9 @@ class NetworksSettings extends PureComponent { onActionSheetPress = (index) => (index === 0 ? this.removeNetwork() : null); networkElement(name, color, i, network, isCustomRPC) { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( { const { frequentRpcList } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + if (frequentRpcList.length > 0) { return ( @@ -177,6 +198,9 @@ class NetworksSettings extends PureComponent { renderMainnet() { const { color: mainnetColor, name: mainnetName } = Networks.mainnet; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -219,12 +247,15 @@ class NetworksSettings extends PureComponent { cancelButtonIndex={1} destructiveButtonIndex={0} onPress={this.onActionSheetPress} + theme={themeAppearance} /> ); } } +NetworksSettings.contextType = ThemeContext; + const mapStateToProps = (state) => ({ provider: state.engine.backgroundState.NetworkController.provider, frequentRpcList: state.engine.backgroundState.PreferencesController.frequentRpcList, diff --git a/app/components/Views/Settings/SecuritySettings/index.js b/app/components/Views/Settings/SecuritySettings/index.js index fd728bdbc1d..d7cd060e00c 100644 --- a/app/components/Views/Settings/SecuritySettings/index.js +++ b/app/components/Views/Settings/SecuritySettings/index.js @@ -23,7 +23,7 @@ import StyledButton from '../../../UI/StyledButton'; import SettingsNotification from '../../../UI/SettingsNotification'; import { clearHistory } from '../../../../actions/browser'; import { clearHosts, setPrivacyMode, setThirdPartyApiMode } from '../../../../actions/privacy'; -import { colors, fontStyles } from '../../../../styles/common'; +import { fontStyles, colors as importedColors } from '../../../../styles/common'; import Logger from '../../../../util/Logger'; import Device from '../../../../util/device'; import { getNavigationOptionsTitle } from '../../../UI/Navbar'; @@ -48,126 +48,143 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import HintModal from '../../../UI/HintModal'; import AnalyticsV2, { trackErrorAsAnalytics } from '../../../../util/analyticsV2'; import SeedPhraseVideo from '../../../UI/SeedPhraseVideo'; +import { useAppThemeFromContext, mockTheme, ThemeContext } from '../../../../util/theme'; const isIos = Device.isIos(); const LEARN_MORE_URL = 'https://metamask.zendesk.com/hc/en-us/articles/360015489591-Basic-Safety-and-Security-Tips-for-MetaMask'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - padding: 24, - paddingBottom: 48, - }, - title: { - ...fontStyles.normal, - color: colors.fontPrimary, - fontSize: 20, - lineHeight: 20, - paddingTop: 4, - marginTop: -4, - }, - bump: { - marginBottom: 10, - }, - heading: { - fontSize: 24, - lineHeight: 30, - marginBottom: 24, - }, - desc: { - ...fontStyles.normal, - color: colors.grey500, - fontSize: 14, - lineHeight: 20, - marginTop: 12, - }, - learnMore: { - ...fontStyles.normal, - color: colors.blue, - fontSize: 14, - lineHeight: 20, - }, - switchElement: { - marginTop: 18, - }, - setting: { - marginTop: 50, - }, - firstSetting: { - marginTop: 0, - }, - modalView: { - alignItems: 'center', - flex: 1, - flexDirection: 'column', - justifyContent: 'center', - padding: 20, - }, - modalText: { - ...fontStyles.normal, - fontSize: 18, - textAlign: 'center', - }, - modalTitle: { - ...fontStyles.bold, - fontSize: 22, - textAlign: 'center', - marginBottom: 20, - }, - confirm: { - marginTop: 18, - }, - protect: { - flexDirection: 'row', - justifyContent: 'space-between', - }, - col: { - width: '100%', - }, - inner: { - paddingBottom: 112, - }, - picker: { - borderColor: colors.grey200, - borderRadius: 5, - borderWidth: 2, - marginTop: 16, - }, - loader: { - flex: 1, - alignItems: 'center', - justifyContent: 'center', - }, - warningText: { - color: colors.black, - fontSize: 12, - flex: 1, - ...fontStyles.normal, - }, - warningTextRed: { - color: colors.red, - }, - warningTextGreen: { - color: colors.black, - }, - warningBold: { - ...fontStyles.bold, - color: colors.blue, - }, - viewHint: { - padding: 5, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + padding: 24, + paddingBottom: 48, + }, + title: { + ...fontStyles.normal, + color: colors.text.default, + fontSize: 20, + lineHeight: 20, + paddingTop: 4, + marginTop: -4, + }, + bump: { + marginBottom: 10, + }, + heading: { + fontSize: 24, + lineHeight: 30, + marginBottom: 24, + }, + desc: { + ...fontStyles.normal, + color: colors.text.alternative, + fontSize: 14, + lineHeight: 20, + marginTop: 12, + }, + learnMore: { + ...fontStyles.normal, + color: colors.primary.default, + fontSize: 14, + lineHeight: 20, + }, + switchElement: { + marginTop: 18, + alignSelf: 'flex-start', + }, + setting: { + marginTop: 50, + }, + firstSetting: { + marginTop: 0, + }, + modalView: { + alignItems: 'center', + flex: 1, + flexDirection: 'column', + justifyContent: 'center', + padding: 20, + }, + modalText: { + ...fontStyles.normal, + fontSize: 18, + textAlign: 'center', + color: colors.text.default, + }, + modalTitle: { + ...fontStyles.bold, + fontSize: 22, + textAlign: 'center', + marginBottom: 20, + color: colors.text.default, + }, + confirm: { + marginTop: 18, + }, + protect: { + flexDirection: 'row', + justifyContent: 'space-between', + }, + col: { + width: '48%', + }, + inner: { + paddingBottom: 112, + }, + picker: { + borderColor: colors.border.default, + borderRadius: 5, + borderWidth: 2, + marginTop: 16, + }, + loader: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + warningText: { + color: colors.text.default, + fontSize: 12, + flex: 1, + ...fontStyles.normal, + }, + warningTextRed: { + color: colors.text.default, + }, + warningTextGreen: { + color: colors.text.default, + }, + warningBold: { + ...fontStyles.bold, + color: colors.primary.default, + }, + viewHint: { + padding: 5, + }, + switch: { + alignSelf: 'flex-start', + }, + }); + +const Heading = ({ children, first }) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); -const Heading = ({ children, first }) => ( - - {children} - -); + return ( + + {children} + + ); +}; -const WarningIcon = () => ; +const WarningIcon = () => { + const { colors } = useAppThemeFromContext() || mockTheme; + + return ; +}; Heading.propTypes = { children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]), @@ -262,9 +279,6 @@ class Settings extends PureComponent { type: PropTypes.string, }; - static navigationOptions = ({ navigation }) => - getNavigationOptionsTitle(strings('app_settings.security_title'), navigation); - state = { approvalModalVisible: false, biometryChoice: null, @@ -322,7 +336,16 @@ class Settings extends PureComponent { scrollView = undefined; + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + getNavigationOptionsTitle(strings('app_settings.security_title'), navigation, false, colors) + ); + }; + componentDidMount = async () => { + this.updateNavBar(); const biometryType = await SecureKeychain.getSupportedBiometryType(); const analyticsEnabled = Analytics.getEnabled(); const currentSeedphraseHints = await AsyncStorage.getItem(SEED_PHRASE_HINTS); @@ -355,6 +378,10 @@ class Settings extends PureComponent { if (this.props.route?.params?.scrollToBottom) this.scrollView?.scrollToEnd({ animated: true }); }; + componentDidUpdate = async () => { + this.updateNavBar(); + }; + onSingInWithBiometrics = async (enabled) => { this.setState({ loading: true }, async () => { let credentials; @@ -558,6 +585,11 @@ class Settings extends PureComponent { handleChangeText = (text) => this.setState({ hintText: text }); + getStyles = () => { + const colors = this.context.colors || mockTheme.colors; + return { colors, styles: createStyles(colors) }; + }; + renderHint = () => { const { showHint, hintText } = this.state; return ( @@ -577,6 +609,7 @@ class Settings extends PureComponent { renderProtectYourWalletSection = () => { const { seedphraseBackedUp } = this.props; const { hintText } = this.state; + const { styles } = this.getStyles(); return ( @@ -629,83 +662,100 @@ class Settings extends PureComponent { {strings('app_settings.back_up_now')} ) : ( - - - {strings('reveal_credential.seed_phrase_title')} - - + + {strings('reveal_credential.seed_phrase_title')} + )} ); }; - renderPasswordSection = () => ( - - {strings('password_reset.password_title')} - {strings('password_reset.password_desc')} - - {strings('password_reset.change_password')} - - - ); + renderPasswordSection = () => { + const { styles } = this.getStyles(); + return ( + + {strings('password_reset.password_title')} + {strings('password_reset.password_desc')} + + {strings('password_reset.change_password')} + + + ); + }; - renderAutoLockSection = () => ( - - {strings('app_settings.auto_lock')} - {strings('app_settings.auto_lock_desc')} - - {this.autolockOptions && ( - - )} + renderAutoLockSection = () => { + const { styles } = this.getStyles(); + return ( + + {strings('app_settings.auto_lock')} + {strings('app_settings.auto_lock_desc')} + + {this.autolockOptions && ( + + )} + - - ); + ); + }; - renderBiometricOptionsSection = () => ( - - {strings(`biometrics.enable_${this.state.biometryType.toLowerCase()}`)} - - + renderBiometricOptionsSection = () => { + const { styles, colors } = this.getStyles(); + return ( + + + {strings(`biometrics.enable_${this.state.biometryType.toLowerCase()}`)} + + + + - - ); + ); + }; - renderDevicePasscodeSection = () => ( - - - {isIos - ? strings(`biometrics.enable_device_passcode_ios`) - : strings(`biometrics.enable_device_passcode_android`)} - - - + renderDevicePasscodeSection = () => { + const { styles, colors } = this.getStyles(); + return ( + + + {isIos + ? strings(`biometrics.enable_device_passcode_ios`) + : strings(`biometrics.enable_device_passcode_android`)} + + + + - - ); + ); + }; renderPrivateKeySection = () => { const { accounts, identities, selectedAddress } = this.props; const account = { address: selectedAddress, ...identities[selectedAddress], ...accounts[selectedAddress] }; + const { styles } = this.getStyles(); return ( @@ -726,6 +776,7 @@ class Settings extends PureComponent { renderClearPrivacySection = () => { const { approvedHosts } = this.props; + const { styles } = this.getStyles(); return ( @@ -745,6 +796,7 @@ class Settings extends PureComponent { renderClearBrowserHistorySection = () => { const { browserHistory } = this.props; + const { styles } = this.getStyles(); return ( @@ -762,18 +814,22 @@ class Settings extends PureComponent { ); }; - renderClearCookiesSection = () => ( - - {strings('app_settings.clear_browser_cookies_desc')} - {strings('app_settings.clear_cookies_desc')} - - {strings('app_settings.clear_browser_cookies_desc')} - - - ); + renderClearCookiesSection = () => { + const { styles } = this.getStyles(); + return ( + + {strings('app_settings.clear_browser_cookies_desc')} + {strings('app_settings.clear_cookies_desc')} + + {strings('app_settings.clear_browser_cookies_desc')} + + + ); + }; renderPrivacyModeSection = () => { const { privacyMode } = this.props; + const { styles, colors } = this.getStyles(); return ( @@ -783,8 +839,10 @@ class Settings extends PureComponent { @@ -793,6 +851,7 @@ class Settings extends PureComponent { renderMetaMetricsSection = () => { const { analyticsEnabled } = this.state; + const { styles, colors } = this.getStyles(); return ( @@ -802,8 +861,10 @@ class Settings extends PureComponent { @@ -813,6 +874,7 @@ class Settings extends PureComponent { renderThirdPartySection = () => { const { thirdPartyApiMode } = this.props; + const { styles, colors } = this.getStyles(); return ( @@ -822,8 +884,10 @@ class Settings extends PureComponent { @@ -832,6 +896,7 @@ class Settings extends PureComponent { renderApprovalModal = () => { const { approvalModalVisible } = this.state; + const { styles } = this.getStyles(); return ( { const { browserHistoryModalVisible } = this.state; + const { styles } = this.getStyles(); return ( { const { cookiesModalVisible } = this.state; + const { styles } = this.getStyles(); return ( { const { openSeaEnabled, useCollectibleDetection } = this.props; + const { styles, colors } = this.getStyles(); return ( <> @@ -902,8 +970,10 @@ class Settings extends PureComponent { @@ -914,8 +984,10 @@ class Settings extends PureComponent { @@ -926,6 +998,7 @@ class Settings extends PureComponent { render = () => { const { biometryType, biometryChoice, loading } = this.state; + const { styles } = this.getStyles(); if (loading) return ( @@ -968,6 +1041,8 @@ class Settings extends PureComponent { }; } +Settings.contextType = ThemeContext; + const mapStateToProps = (state) => ({ approvedHosts: state.privacy.approvedHosts, browserHistory: state.browser.history, diff --git a/app/components/Views/Settings/index.js b/app/components/Views/Settings/index.js index 3e60f84ef84..1d159d147f6 100644 --- a/app/components/Views/Settings/index.js +++ b/app/components/Views/Settings/index.js @@ -2,29 +2,27 @@ import PropTypes from 'prop-types'; import React, { PureComponent } from 'react'; import { StyleSheet, ScrollView, InteractionManager } from 'react-native'; import SettingsDrawer from '../../UI/SettingsDrawer'; -import { colors } from '../../../styles/common'; import { getClosableNavigationOptions } from '../../UI/Navbar'; import { strings } from '../../../../locales/i18n'; import Analytics from '../../../core/Analytics'; import { ANALYTICS_EVENT_OPTS } from '../../../util/analytics'; import { connect } from 'react-redux'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - paddingLeft: 18, - zIndex: 99999999999999, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + paddingLeft: 18, + zIndex: 99999999999999, + }, + }); /** * Main view for app configurations */ class Settings extends PureComponent { - static navigationOptions = ({ navigation }) => - getClosableNavigationOptions(strings('app_settings.title'), strings('navigation.close'), navigation); - static propTypes = { /** /* navigation object required to push new views @@ -37,6 +35,22 @@ class Settings extends PureComponent { seedphraseBackedUp: PropTypes.bool, }; + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + getClosableNavigationOptions(strings('app_settings.title'), strings('navigation.close'), navigation, colors) + ); + }; + + componentDidMount = () => { + this.updateNavBar(); + }; + + componentDidUpdate = () => { + this.updateNavBar(); + }; + onPressGeneral = () => { InteractionManager.runAfterInteractions(() => Analytics.trackEvent(ANALYTICS_EVENT_OPTS.SETTINGS_GENERAL)); this.props.navigation.navigate('GeneralSettings'); @@ -74,6 +88,9 @@ class Settings extends PureComponent { render = () => { const { seedphraseBackedUp } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( ({ seedphraseBackedUp: state.user.seedphraseBackedUp, }); diff --git a/app/components/Views/SimpleWebview/index.js b/app/components/Views/SimpleWebview/index.js index 0bc151f5588..18e47e41011 100644 --- a/app/components/Views/SimpleWebview/index.js +++ b/app/components/Views/SimpleWebview/index.js @@ -6,10 +6,9 @@ import { getWebviewNavbar } from '../../UI/Navbar'; import Share from 'react-native-share'; // eslint-disable-line import/default import Logger from '../../../util/Logger'; import { baseStyles } from '../../../styles/common'; +import { ThemeContext, mockTheme } from '../../../util/theme'; export default class SimpleWebview extends PureComponent { - static navigationOptions = ({ navigation, route }) => getWebviewNavbar(navigation, route); - static propTypes = { /** * react-navigation object used to switch between screens @@ -21,11 +20,22 @@ export default class SimpleWebview extends PureComponent { route: PropTypes.object, }; + updateNavBar = () => { + const { navigation, route } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions(getWebviewNavbar(navigation, route, colors)); + }; + componentDidMount = () => { const { navigation } = this.props; + this.updateNavBar(); navigation && navigation.setParams({ dispatch: this.share }); }; + componentDidUpdate = () => { + this.updateNavBar(); + }; + share = () => { const { route } = this.props; const url = route.params?.url; @@ -49,3 +59,5 @@ export default class SimpleWebview extends PureComponent { } } } + +SimpleWebview.contextType = ThemeContext; diff --git a/app/components/Views/SimpleWebview/index.test.tsx b/app/components/Views/SimpleWebview/index.test.tsx index 4abd4233f06..0fa1a0038a1 100644 --- a/app/components/Views/SimpleWebview/index.test.tsx +++ b/app/components/Views/SimpleWebview/index.test.tsx @@ -10,6 +10,7 @@ describe('SimpleWebview', () => { setParams: () => { (''); }, + setOptions: () => null, }} route={{ params: { url: 'https://etherscan.io', title: 'etherscan' } }} /> diff --git a/app/components/Views/SyncWithExtensionSuccess/index.js b/app/components/Views/SyncWithExtensionSuccess/index.js index 0aca0fe681d..d59718079c0 100644 --- a/app/components/Views/SyncWithExtensionSuccess/index.js +++ b/app/components/Views/SyncWithExtensionSuccess/index.js @@ -61,22 +61,19 @@ const styles = StyleSheet.create({ }, passwordTipContainer: { padding: 16, - backgroundColor: colors.blue000, + borderWidth: 1, - borderColor: colors.blue200, borderRadius: 8, marginTop: 29, }, passwordTipText: { fontSize: 12, lineHeight: 17, - color: colors.blue600, }, learnMoreText: { marginTop: 29, textAlign: 'center', fontSize: 16, - color: colors.blue, ...fontStyles.normal, }, buttonContainer: { diff --git a/app/components/Views/TermsAndConditions/index.js b/app/components/Views/TermsAndConditions/index.js index 28865a8ac6d..147d10236e1 100644 --- a/app/components/Views/TermsAndConditions/index.js +++ b/app/components/Views/TermsAndConditions/index.js @@ -1,21 +1,23 @@ import React, { PureComponent } from 'react'; import { Text, StyleSheet, TouchableOpacity } from 'react-native'; import PropTypes from 'prop-types'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import AppConstants from '../../../core/AppConstants'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - text: { - ...fontStyles.normal, - color: colors.grey500, - textAlign: 'center', - fontSize: 10, - }, - link: { - textDecorationLine: 'underline', - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + text: { + ...fontStyles.normal, + color: colors.text.alternative, + textAlign: 'center', + fontSize: 10, + }, + link: { + textDecorationLine: 'underline', + }, + }); /** * View that is displayed in the flow to agree terms and conditions @@ -40,6 +42,9 @@ export default class TermsAndConditions extends PureComponent { }; render() { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return ( @@ -50,3 +55,5 @@ export default class TermsAndConditions extends PureComponent { ); } } + +TermsAndConditions.contextType = ThemeContext; diff --git a/app/components/Views/ThemeSettings/index.tsx b/app/components/Views/ThemeSettings/index.tsx new file mode 100644 index 00000000000..c0941a4de73 --- /dev/null +++ b/app/components/Views/ThemeSettings/index.tsx @@ -0,0 +1,103 @@ +import React, { useCallback, useRef } from 'react'; +import { StyleSheet, View, Text, TouchableOpacity } from 'react-native'; +import ReusableModal, { ReusableModalRef } from '../../UI/ReusableModal'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; +import { useDispatch, useSelector } from 'react-redux'; +import { AppThemeKey } from '../../../util/theme/models'; +import { setAppTheme } from '../../../actions/user'; +import { useSafeAreaInsets } from 'react-native-safe-area-context'; +import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; +import { fontStyles } from '../../../styles/common'; +import { strings } from '../../../../locales/i18n'; + +const createStyles = (colors: any, safeAreaPaddingBottom: number) => + StyleSheet.create({ + screen: { justifyContent: 'flex-end' }, + sheet: { + backgroundColor: colors.background.default, + borderTopLeftRadius: 10, + borderTopRightRadius: 10, + paddingBottom: safeAreaPaddingBottom + 16, + }, + notch: { + width: 48, + height: 5, + borderRadius: 4, + backgroundColor: colors.border.default, + marginBottom: 24, + marginTop: 16, + alignSelf: 'center', + }, + option: { + height: 60, + borderTopWidth: StyleSheet.hairlineWidth, + borderColor: colors.border.muted, + }, + optionButton: { + flex: 1, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: 16, + }, + optionLabel: { + color: colors.text.default, + fontSize: 16, + fontFamily: fontStyles.normal.fontFamily, + }, + }); + +const ThemeSettings = () => { + const safeAreaInsets = useSafeAreaInsets(); + const modalRef = useRef(null); + const dispatch = useDispatch(); + const triggerSetAppTheme = (theme: AppThemeKey) => dispatch(setAppTheme(theme)); + const appTheme: AppThemeKey = useSelector((state: any) => state.user.appTheme); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors, safeAreaInsets.bottom); + + /* eslint-disable-next-line */ + const renderThemeOptions = useCallback(() => { + return ( + + {Object.keys(AppThemeKey).map((themeKeyId) => { + const key = `${themeKeyId}-theme`; + const selectedThemeKey = AppThemeKey[themeKeyId as AppThemeKey]; + const selectedIcon = + appTheme === selectedThemeKey ? ( + + ) : null; + + return ( + + { + triggerSetAppTheme(selectedThemeKey); + modalRef.current?.dismissModal(); + }} + style={styles.optionButton} + > + + {strings(`app_settings.theme_${selectedThemeKey}`)} + + {selectedIcon} + + + ); + })} + + ); + /* eslint-disable-next-line */ + }, [appTheme, styles, colors]); + + return ( + + + + {renderThemeOptions()} + + + ); +}; + +export default ThemeSettings; diff --git a/app/components/Views/TransactionSummary/index.js b/app/components/Views/TransactionSummary/index.js index bba16c410aa..dbde3c3139c 100644 --- a/app/components/Views/TransactionSummary/index.js +++ b/app/components/Views/TransactionSummary/index.js @@ -1,18 +1,19 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { StyleSheet, View, ActivityIndicator, TouchableOpacity } from 'react-native'; -import { colors } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import { TRANSACTION_TYPES } from '../../../util/transactions'; import Summary from '../../Base/Summary'; import Text from '../../Base/Text'; +import { ThemeContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - loader: { - backgroundColor: colors.white, - height: 10, - }, -}); +const createStyles = (colors) => + StyleSheet.create({ + loader: { + backgroundColor: colors.background.default, + height: 10, + }, + }); export default class TransactionSummary extends PureComponent { static propTypes = { @@ -27,6 +28,9 @@ export default class TransactionSummary extends PureComponent { renderIfGastEstimationReady = (children) => { const { gasEstimationReady } = this.props; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return !gasEstimationReady ? ( @@ -132,3 +136,5 @@ export default class TransactionSummary extends PureComponent { ); }; } + +TransactionSummary.contextType = ThemeContext; diff --git a/app/components/Views/Wallet/index.tsx b/app/components/Views/Wallet/index.tsx index ea1347da503..957b3e25990 100644 --- a/app/components/Views/Wallet/index.tsx +++ b/app/components/Views/Wallet/index.tsx @@ -3,7 +3,7 @@ import { RefreshControl, ScrollView, InteractionManager, ActivityIndicator, Styl import { useSelector } from 'react-redux'; import ScrollableTabView from 'react-native-scrollable-tab-view'; import DefaultTabBar from 'react-native-scrollable-tab-view/DefaultTabBar'; -import { colors, fontStyles, baseStyles } from '../../../styles/common'; +import { fontStyles, baseStyles } from '../../../styles/common'; import AccountOverview from '../../UI/AccountOverview'; import Tokens from '../../UI/Tokens'; import { getWalletNavbarOptions } from '../../UI/Navbar'; @@ -17,31 +17,33 @@ import { getTicker } from '../../../util/transactions'; import OnboardingWizard from '../../UI/OnboardingWizard'; import ErrorBoundary from '../ErrorBoundary'; import { DrawerContext } from '../../Nav/Main/MainNavigator'; +import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; -const styles = StyleSheet.create({ - wrapper: { - flex: 1, - backgroundColor: colors.white, - }, - tabUnderlineStyle: { - height: 2, - backgroundColor: colors.blue, - }, - tabStyle: { - paddingBottom: 0, - }, - textStyle: { - fontSize: 12, - letterSpacing: 0.5, - ...(fontStyles.bold as any), - }, - loader: { - backgroundColor: colors.white, - flex: 1, - justifyContent: 'center', - alignItems: 'center', - }, -}); +const createStyles = (colors: any) => + StyleSheet.create({ + wrapper: { + flex: 1, + backgroundColor: colors.background.default, + }, + tabUnderlineStyle: { + height: 2, + backgroundColor: colors.primary.default, + }, + tabStyle: { + paddingBottom: 0, + }, + textStyle: { + fontSize: 12, + letterSpacing: 0.5, + ...(fontStyles.bold as any), + }, + loader: { + backgroundColor: colors.background.default, + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + }); /** * Main view for the wallet @@ -50,6 +52,8 @@ const Wallet = ({ navigation }: any) => { const { drawerRef } = useContext(DrawerContext); const [refreshing, setRefreshing] = useState(false); const accountOverviewRef = useRef(null); + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); /** * Map of accounts to information objects including balances */ @@ -89,9 +93,10 @@ const Wallet = ({ navigation }: any) => { */ const wizardStep = useSelector((state: any) => state.wizard.step); + const { colors: themeColors } = useAppThemeFromContext() || mockTheme; + useEffect( () => { - navigation.setOptions(getWalletNavbarOptions('wallet.title', navigation, drawerRef)); requestAnimationFrame(async () => { const { TokenDetectionController, CollectibleDetectionController, AccountTrackerController } = Engine.context as any; @@ -104,6 +109,11 @@ const Wallet = ({ navigation }: any) => { [navigation] ); + useEffect(() => { + navigation.setOptions(getWalletNavbarOptions('wallet.title', navigation, drawerRef, themeColors)); + /* eslint-disable-next-line */ + }, [navigation, themeColors]); + const onRefresh = useCallback(async () => { requestAnimationFrame(async () => { setRefreshing(true); @@ -130,14 +140,14 @@ const Wallet = ({ navigation }: any) => { () => ( ), - [] + [styles, colors] ); const onChangeTab = useCallback((obj) => { @@ -213,6 +223,7 @@ const Wallet = ({ navigation }: any) => { selectedAddress, ticker, tokens, + styles, ]); const renderLoader = useCallback( @@ -221,7 +232,7 @@ const Wallet = ({ navigation }: any) => { ), - [] + [styles] ); /** @@ -240,7 +251,14 @@ const Wallet = ({ navigation }: any) => { } + refreshControl={ + + } > {selectedAddress ? renderContent() : renderLoader()} diff --git a/app/components/Views/WalletConnectSessions/index.js b/app/components/Views/WalletConnectSessions/index.js index 64a8464c00c..86ba9476114 100644 --- a/app/components/Views/WalletConnectSessions/index.js +++ b/app/components/Views/WalletConnectSessions/index.js @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import { Alert, ScrollView, SafeAreaView, StyleSheet, View, Text, TouchableOpacity } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import { getNavigationOptionsTitle } from '../../UI/Navbar'; import WebsiteIcon from '../../UI/WebsiteIcon'; @@ -9,64 +9,67 @@ import ActionSheet from 'react-native-actionsheet'; import WalletConnect from '../../../core/WalletConnect'; import Logger from '../../../util/Logger'; import { WALLETCONNECT_SESSIONS } from '../../../constants/storage'; - -const styles = StyleSheet.create({ - wrapper: { - backgroundColor: colors.white, - flex: 1, - }, - scrollviewContent: { - paddingTop: 20, - }, - websiteIcon: { - width: 44, - height: 44, - }, - row: { - flexDirection: 'row', - paddingVertical: 10, - paddingHorizontal: 20, - borderBottomColor: colors.grey000, - borderBottomWidth: 1, - }, - info: { - marginLeft: 20, - flex: 1, - }, - name: { - ...fontStyles.bold, - fontSize: 16, - marginBottom: 10, - }, - desc: { - marginBottom: 10, - ...fontStyles.normal, - fontSize: 12, - }, - url: { - marginBottom: 10, - ...fontStyles.normal, - fontSize: 12, - color: colors.fontSecondary, - }, - emptyWrapper: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - }, - emptyText: { - ...fontStyles.normal, - fontSize: 16, - }, -}); +import { ThemeContext, mockTheme } from '../../../util/theme'; +import PropTypes from 'prop-types'; + +const createStyles = (colors) => + StyleSheet.create({ + wrapper: { + backgroundColor: colors.background.default, + flex: 1, + }, + scrollviewContent: { + paddingTop: 20, + }, + websiteIcon: { + width: 44, + height: 44, + }, + row: { + flexDirection: 'row', + paddingVertical: 10, + paddingHorizontal: 20, + borderBottomColor: colors.border.muted, + borderBottomWidth: 1, + }, + info: { + marginLeft: 20, + flex: 1, + }, + name: { + ...fontStyles.bold, + fontSize: 16, + marginBottom: 10, + color: colors.text.default, + }, + desc: { + marginBottom: 10, + ...fontStyles.normal, + fontSize: 12, + color: colors.text.alternative, + }, + url: { + marginBottom: 10, + ...fontStyles.normal, + fontSize: 12, + color: colors.text.alternative, + }, + emptyWrapper: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + emptyText: { + ...fontStyles.normal, + fontSize: 16, + color: colors.text.default, + }, + }); /** * View that displays all the active WalletConnect Sessions */ export default class WalletConnectSessions extends PureComponent { - static navigationOptions = ({ navigation }) => - getNavigationOptionsTitle(strings(`experimental_settings.wallet_connect_dapps`), navigation); - state = { sessions: [], }; @@ -75,10 +78,23 @@ export default class WalletConnectSessions extends PureComponent { sessionToRemove = null; + updateNavBar = () => { + const { navigation } = this.props; + const colors = this.context.colors || mockTheme.colors; + navigation.setOptions( + getNavigationOptionsTitle(strings('experimental_settings.wallet_connect_dapps'), navigation, false, colors) + ); + }; + componentDidMount() { + this.updateNavBar(); this.loadSessions(); } + componentDidUpdate = () => { + this.updateNavBar(); + }; + loadSessions = async () => { let sessions = []; const sessionData = await AsyncStorage.getItem(WALLETCONNECT_SESSIONS); @@ -90,6 +106,9 @@ export default class WalletConnectSessions extends PureComponent { renderDesc = (meta) => { const { description } = meta; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + if (description) { return {meta.description}; } @@ -122,6 +141,9 @@ export default class WalletConnectSessions extends PureComponent { renderSessions = () => { const { sessions } = this.state; + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + return sessions.map((session) => ( ( - - {strings('walletconnect_sessions.no_active_sessions')} - - ); + renderEmpty = () => { + const colors = this.context.colors || mockTheme.colors; + const styles = createStyles(colors); + + return ( + + {strings('walletconnect_sessions.no_active_sessions')} + + ); + }; render = () => { const { ready, sessions } = this.state; if (!ready) return null; + const colors = this.context.colors || mockTheme.colors; + const themeAppearance = this.context.themeAppearance; + const styles = createStyles(colors); return ( @@ -162,8 +192,18 @@ export default class WalletConnectSessions extends PureComponent { cancelButtonIndex={1} destructiveButtonIndex={0} onPress={this.onActionSheetPress} + theme={themeAppearance} /> ); }; } + +WalletConnectSessions.contextType = ThemeContext; + +WalletConnectSessions.propTypes = { + /** + * Navigation object + */ + navigation: PropTypes.object, +}; diff --git a/app/components/Views/WalletConnectSessions/index.test.tsx b/app/components/Views/WalletConnectSessions/index.test.tsx index 5df63ba5303..7876f538f9a 100644 --- a/app/components/Views/WalletConnectSessions/index.test.tsx +++ b/app/components/Views/WalletConnectSessions/index.test.tsx @@ -4,7 +4,7 @@ import WalletConnectSessions from './'; describe('WalletConnectSessions', () => { it('should render correctly', () => { - const wrapper = shallow(); + const wrapper = shallow( null }} />); expect(wrapper).toMatchSnapshot(); }); diff --git a/app/core/Analytics.js b/app/core/Analytics.js index c4ee6fa50f3..38ca5c88777 100644 --- a/app/core/Analytics.js +++ b/app/core/Analytics.js @@ -1,17 +1,18 @@ 'use strict'; import { METRICS_OPT_IN, AGREED, DENIED } from '../constants/storage'; +import { Appearance, NativeModules } from 'react-native'; import AUTHENTICATION_TYPE from '../constants/userProperties'; -import { NativeModules } from 'react-native'; import DefaultPreference from 'react-native-default-preference'; import Logger from '../util/Logger'; import { ANALYTICS_EVENTS_V2 } from '../util/analyticsV2'; -import Engine from './Engine'; +import { store } from '../store'; const RCTAnalytics = NativeModules.Analytics; const USER_PROFILE_PROPERTY = { ENABLE_OPENSEA_API: 'Enable OpenSea API', NFT_AUTODETECTION: 'NFT Autodetection', + THEME: 'Theme', ON: 'ON', OFF: 'OFF', @@ -54,15 +55,21 @@ class Analytics { * Set the user profile state for current user to mixpanel */ _setUserProfileProperties = () => { - const state = Engine.context.PreferencesController.internalState; + const reduxState = store.getState(); + const preferencesController = reduxState?.engine?.backgroundState?.PreferencesController; + const appTheme = reduxState?.user?.appTheme; + // This will return either "light" or "dark" + const appThemeStyle = appTheme === 'os' ? Appearance.getColorScheme() : appTheme; + RCTAnalytics.setUserProfileProperty( USER_PROFILE_PROPERTY.ENABLE_OPENSEA_API, - state?.openSeaEnabled ? USER_PROFILE_PROPERTY.ON : USER_PROFILE_PROPERTY.OFF + preferencesController?.openSeaEnabled ? USER_PROFILE_PROPERTY.ON : USER_PROFILE_PROPERTY.OFF ); RCTAnalytics.setUserProfileProperty( USER_PROFILE_PROPERTY.NFT_AUTODETECTION, - state?.useCollectibleDetection ? USER_PROFILE_PROPERTY.ON : USER_PROFILE_PROPERTY.OFF + preferencesController?.useCollectibleDetection ? USER_PROFILE_PROPERTY.ON : USER_PROFILE_PROPERTY.OFF ); + RCTAnalytics.setUserProfileProperty(USER_PROFILE_PROPERTY.THEME, appThemeStyle); }; /** diff --git a/app/images/ApplePayLogo-dark.png b/app/images/ApplePayLogo-dark.png new file mode 100644 index 00000000000..0414f9db261 Binary files /dev/null and b/app/images/ApplePayLogo-dark.png differ diff --git a/app/images/ApplePayLogo-dark@2x.png b/app/images/ApplePayLogo-dark@2x.png new file mode 100644 index 00000000000..b92d85bab10 Binary files /dev/null and b/app/images/ApplePayLogo-dark@2x.png differ diff --git a/app/images/ApplePayLogo-dark@3x.png b/app/images/ApplePayLogo-dark@3x.png new file mode 100644 index 00000000000..f344d6d853e Binary files /dev/null and b/app/images/ApplePayLogo-dark@3x.png differ diff --git a/app/images/ApplePayLogo-light.png b/app/images/ApplePayLogo-light.png new file mode 100644 index 00000000000..41f8a5462ad Binary files /dev/null and b/app/images/ApplePayLogo-light.png differ diff --git a/app/images/ApplePayLogo-light@2x.png b/app/images/ApplePayLogo-light@2x.png new file mode 100644 index 00000000000..9e594e1bc8b Binary files /dev/null and b/app/images/ApplePayLogo-light@2x.png differ diff --git a/app/images/ApplePayLogo-light@3x.png b/app/images/ApplePayLogo-light@3x.png new file mode 100644 index 00000000000..bc5c92e7c8b Binary files /dev/null and b/app/images/ApplePayLogo-light@3x.png differ diff --git a/app/images/ApplePayLogo.png b/app/images/ApplePayLogo.png deleted file mode 100644 index 11c3645aca5..00000000000 Binary files a/app/images/ApplePayLogo.png and /dev/null differ diff --git a/app/images/ApplePayLogo@2x.png b/app/images/ApplePayLogo@2x.png deleted file mode 100644 index d6bdc0ee12d..00000000000 Binary files a/app/images/ApplePayLogo@2x.png and /dev/null differ diff --git a/app/images/ApplePayLogo@3x.png b/app/images/ApplePayLogo@3x.png deleted file mode 100644 index e961c8306ec..00000000000 Binary files a/app/images/ApplePayLogo@3x.png and /dev/null differ diff --git a/app/images/ApplePayMark-dark.png b/app/images/ApplePayMark-dark.png new file mode 100644 index 00000000000..16f0a474b94 Binary files /dev/null and b/app/images/ApplePayMark-dark.png differ diff --git a/app/images/ApplePayMark-dark@2x.png b/app/images/ApplePayMark-dark@2x.png new file mode 100644 index 00000000000..1bfe4390b20 Binary files /dev/null and b/app/images/ApplePayMark-dark@2x.png differ diff --git a/app/images/ApplePayMark-dark@3x.png b/app/images/ApplePayMark-dark@3x.png new file mode 100644 index 00000000000..a4ae31cee50 Binary files /dev/null and b/app/images/ApplePayMark-dark@3x.png differ diff --git a/app/images/ApplePayMark-light.png b/app/images/ApplePayMark-light.png new file mode 100644 index 00000000000..e120799de32 Binary files /dev/null and b/app/images/ApplePayMark-light.png differ diff --git a/app/images/ApplePayMark-light@2x.png b/app/images/ApplePayMark-light@2x.png new file mode 100644 index 00000000000..f4511f4041e Binary files /dev/null and b/app/images/ApplePayMark-light@2x.png differ diff --git a/app/images/ApplePayMark-light@3x.png b/app/images/ApplePayMark-light@3x.png new file mode 100644 index 00000000000..5215f50d42f Binary files /dev/null and b/app/images/ApplePayMark-light@3x.png differ diff --git a/app/images/WyreLogo-dark.png b/app/images/WyreLogo-dark.png new file mode 100644 index 00000000000..f48842f8bce Binary files /dev/null and b/app/images/WyreLogo-dark.png differ diff --git a/app/images/WyreLogo-dark@2x.png b/app/images/WyreLogo-dark@2x.png new file mode 100644 index 00000000000..7c46308a956 Binary files /dev/null and b/app/images/WyreLogo-dark@2x.png differ diff --git a/app/images/WyreLogo-dark@3x.png b/app/images/WyreLogo-dark@3x.png new file mode 100644 index 00000000000..2d1b6fbe2c7 Binary files /dev/null and b/app/images/WyreLogo-dark@3x.png differ diff --git a/app/images/WyreLogo-light.png b/app/images/WyreLogo-light.png new file mode 100644 index 00000000000..793b75f526e Binary files /dev/null and b/app/images/WyreLogo-light.png differ diff --git a/app/images/WyreLogo-light@2x.png b/app/images/WyreLogo-light@2x.png new file mode 100644 index 00000000000..654f2876634 Binary files /dev/null and b/app/images/WyreLogo-light@2x.png differ diff --git a/app/images/WyreLogo-light@3x.png b/app/images/WyreLogo-light@3x.png new file mode 100644 index 00000000000..86b5eb18d2b Binary files /dev/null and b/app/images/WyreLogo-light@3x.png differ diff --git a/app/images/WyreLogo.png b/app/images/WyreLogo.png deleted file mode 100644 index f3beeb2abc8..00000000000 Binary files a/app/images/WyreLogo.png and /dev/null differ diff --git a/app/images/WyreLogo@2x.png b/app/images/WyreLogo@2x.png deleted file mode 100644 index b8e89f15fe5..00000000000 Binary files a/app/images/WyreLogo@2x.png and /dev/null differ diff --git a/app/images/WyreLogo@3x.png b/app/images/WyreLogo@3x.png deleted file mode 100644 index 37e70d31726..00000000000 Binary files a/app/images/WyreLogo@3x.png and /dev/null differ diff --git a/app/images/no-nfts-placeholder.png b/app/images/no-nfts-placeholder.png index 291b13e5fac..ea729ba0409 100644 Binary files a/app/images/no-nfts-placeholder.png and b/app/images/no-nfts-placeholder.png differ diff --git a/app/images/protect-wallet.jpg b/app/images/protect-wallet.jpg deleted file mode 100644 index 0253ea1fa8b..00000000000 Binary files a/app/images/protect-wallet.jpg and /dev/null differ diff --git a/app/images/swaps_aggs-dark.png b/app/images/swaps_aggs-dark.png new file mode 100644 index 00000000000..b13d6cbd461 Binary files /dev/null and b/app/images/swaps_aggs-dark.png differ diff --git a/app/images/swaps_aggs-dark@2x.png b/app/images/swaps_aggs-dark@2x.png new file mode 100644 index 00000000000..245a657973c Binary files /dev/null and b/app/images/swaps_aggs-dark@2x.png differ diff --git a/app/images/swaps_aggs-dark@3x.png b/app/images/swaps_aggs-dark@3x.png new file mode 100644 index 00000000000..8a94cdf40b1 Binary files /dev/null and b/app/images/swaps_aggs-dark@3x.png differ diff --git a/app/images/swaps_aggs.png b/app/images/swaps_aggs-light.png similarity index 100% rename from app/images/swaps_aggs.png rename to app/images/swaps_aggs-light.png diff --git a/app/images/swaps_aggs@2x.png b/app/images/swaps_aggs-light@2x.png similarity index 100% rename from app/images/swaps_aggs@2x.png rename to app/images/swaps_aggs-light@2x.png diff --git a/app/images/swaps_aggs@3x.png b/app/images/swaps_aggs-light@3x.png similarity index 100% rename from app/images/swaps_aggs@3x.png rename to app/images/swaps_aggs-light@3x.png diff --git a/app/images/welcome-bg1.jpg b/app/images/welcome-bg1.jpg deleted file mode 100644 index 76664e541b6..00000000000 Binary files a/app/images/welcome-bg1.jpg and /dev/null differ diff --git a/app/images/welcome-bg1.png b/app/images/welcome-bg1.png new file mode 100644 index 00000000000..e26afd0e8d9 Binary files /dev/null and b/app/images/welcome-bg1.png differ diff --git a/app/images/welcome-bg1@2x.jpg b/app/images/welcome-bg1@2x.jpg deleted file mode 100644 index 0b6698fa20d..00000000000 Binary files a/app/images/welcome-bg1@2x.jpg and /dev/null differ diff --git a/app/images/welcome-bg1@2x.png b/app/images/welcome-bg1@2x.png new file mode 100644 index 00000000000..87266362dfb Binary files /dev/null and b/app/images/welcome-bg1@2x.png differ diff --git a/app/images/welcome-bg1@3x.jpg b/app/images/welcome-bg1@3x.jpg deleted file mode 100644 index 54ac2d33b07..00000000000 Binary files a/app/images/welcome-bg1@3x.jpg and /dev/null differ diff --git a/app/images/welcome-bg1@3x.png b/app/images/welcome-bg1@3x.png new file mode 100644 index 00000000000..4d0ac51bfaf Binary files /dev/null and b/app/images/welcome-bg1@3x.png differ diff --git a/app/images/welcome-bg2.jpg b/app/images/welcome-bg2.jpg deleted file mode 100644 index 6afe1c22a02..00000000000 Binary files a/app/images/welcome-bg2.jpg and /dev/null differ diff --git a/app/images/welcome-bg2.png b/app/images/welcome-bg2.png new file mode 100644 index 00000000000..384b019e959 Binary files /dev/null and b/app/images/welcome-bg2.png differ diff --git a/app/images/welcome-bg2@2x.jpg b/app/images/welcome-bg2@2x.jpg deleted file mode 100644 index be34c99c264..00000000000 Binary files a/app/images/welcome-bg2@2x.jpg and /dev/null differ diff --git a/app/images/welcome-bg2@2x.png b/app/images/welcome-bg2@2x.png new file mode 100644 index 00000000000..bdf5f97f27c Binary files /dev/null and b/app/images/welcome-bg2@2x.png differ diff --git a/app/images/welcome-bg2@3x.jpg b/app/images/welcome-bg2@3x.jpg deleted file mode 100644 index 877abd5628b..00000000000 Binary files a/app/images/welcome-bg2@3x.jpg and /dev/null differ diff --git a/app/images/welcome-bg2@3x.png b/app/images/welcome-bg2@3x.png new file mode 100644 index 00000000000..d6a01293b96 Binary files /dev/null and b/app/images/welcome-bg2@3x.png differ diff --git a/app/images/welcome-bg3.jpg b/app/images/welcome-bg3.jpg deleted file mode 100755 index 00921793c63..00000000000 Binary files a/app/images/welcome-bg3.jpg and /dev/null differ diff --git a/app/images/welcome-bg3.png b/app/images/welcome-bg3.png new file mode 100644 index 00000000000..0d652f093b4 Binary files /dev/null and b/app/images/welcome-bg3.png differ diff --git a/app/images/welcome-bg3@2x.jpg b/app/images/welcome-bg3@2x.jpg deleted file mode 100755 index 32c5120afef..00000000000 Binary files a/app/images/welcome-bg3@2x.jpg and /dev/null differ diff --git a/app/images/welcome-bg3@2x.png b/app/images/welcome-bg3@2x.png new file mode 100644 index 00000000000..2a439c17b69 Binary files /dev/null and b/app/images/welcome-bg3@2x.png differ diff --git a/app/images/welcome-bg3@3x.jpg b/app/images/welcome-bg3@3x.jpg deleted file mode 100755 index d447453956e..00000000000 Binary files a/app/images/welcome-bg3@3x.jpg and /dev/null differ diff --git a/app/images/welcome-bg3@3x.png b/app/images/welcome-bg3@3x.png new file mode 100644 index 00000000000..0249fe77dad Binary files /dev/null and b/app/images/welcome-bg3@3x.png differ diff --git a/app/images/welcome-bg4.jpg b/app/images/welcome-bg4.jpg deleted file mode 100755 index a1d39d10068..00000000000 Binary files a/app/images/welcome-bg4.jpg and /dev/null differ diff --git a/app/images/welcome-bg4.png b/app/images/welcome-bg4.png new file mode 100644 index 00000000000..430bc042142 Binary files /dev/null and b/app/images/welcome-bg4.png differ diff --git a/app/images/welcome-bg4@2x.jpg b/app/images/welcome-bg4@2x.jpg deleted file mode 100755 index 5f0292d4a21..00000000000 Binary files a/app/images/welcome-bg4@2x.jpg and /dev/null differ diff --git a/app/images/welcome-bg4@2x.png b/app/images/welcome-bg4@2x.png new file mode 100644 index 00000000000..aaaf43d30d3 Binary files /dev/null and b/app/images/welcome-bg4@2x.png differ diff --git a/app/images/welcome-bg4@3x.jpg b/app/images/welcome-bg4@3x.jpg deleted file mode 100755 index 28612b74191..00000000000 Binary files a/app/images/welcome-bg4@3x.jpg and /dev/null differ diff --git a/app/images/welcome-bg4@3x.png b/app/images/welcome-bg4@3x.png new file mode 100644 index 00000000000..1a94477dd9a Binary files /dev/null and b/app/images/welcome-bg4@3x.png differ diff --git a/app/reducers/user/index.js b/app/reducers/user/index.js index e6f42568fee..2b6b162ae44 100644 --- a/app/reducers/user/index.js +++ b/app/reducers/user/index.js @@ -1,3 +1,5 @@ +import { AppThemeKey } from '../../util/theme/models'; + const initialState = { loadingMsg: '', loadingSet: false, @@ -10,6 +12,7 @@ const initialState = { userLoggedIn: false, isAuthChecked: false, initialScreen: '', + appTheme: AppThemeKey.os, }; const userReducer = (state = initialState, action) => { @@ -96,6 +99,11 @@ const userReducer = (state = initialState, action) => { ...state, nftDetectionDismissed: true, }; + case 'SET_APP_THEME': + return { + ...state, + appTheme: action.payload.theme, + }; default: return state; } diff --git a/app/styles/common.js b/app/styles/common.js index 19d92f559c2..a004e834306 100644 --- a/app/styles/common.js +++ b/app/styles/common.js @@ -6,64 +6,12 @@ * Map of color names to HEX values */ export const colors = { - fontPrimary: '#000000', - fontSecondary: '#777777', - fontTertiary: '#AAAAAA', - fontError: '#D73A49', - fontWarning: '#f66a0a', - primaryFox: '#f66a0a', black: '#24292E', + blackTransparent: 'rgba(0, 0, 0, 0.5)', white: '#FFFFFF', - white100: '#F9FAFB', - greyAssetVisibility: '#6A737D', - grey450: '#8E8E93', - grey700: '#3C3F42', - grey600: '#5B5D67', - grey500: '#6a737d', - grey400: '#848c96', - grey300: '#9fa6ae', - grey200: '#bbc0c5', - grey100: '#d6d9dc', - grey050: '#D8D8D8', - grey000: '#f2f3f4', - greytransparent: 'rgba(36, 41, 46, 0.6)', - greytransparent100: 'rgba(115, 115, 115, 0.5)', - grey: '#333333', - red: '#D73A49', - red000: '#fcf2f3', - red100: '#efaeae', - blue: '#037dd6', - blue100: '#EAF6FF', - blue000: '#eaf6ff', - blue200: '#75C4FD', - blue500: '#1097FB', - blue600: '#0260A4', - blue700: '#0074C8', - green600: '#1e7e34', - green500: '#28a745', - green400: '#28A745', - green300: '#86e29b', - green200: '#afecbd', - green100: '#e6f9ea', yellow: '#FFD33D', - yellowWarningBorder: '#FADF83', - yellowWarningIcon: '#F8C000', - yellow700: '#705700', - yellow200: '#ffe281', - yellow300: '#FFD33D', - yellow100: '#fffcdb', - orange: '#f66a0a', - orange300: '#faa66c', - orange000: '#fef5ef', - spinnerColor: '#037DD6', - success: '#219E37', - dimmed: '#00000080', transparent: 'transparent', - lightOverlay: 'rgba(0,0,0,.2)', - overlay: 'rgba(0,0,0,.5)', - darkAlert: 'rgba(0,0,0,.75)', - normalAlert: 'rgba(55,55,55,.97)', - spinnerBackground: `rgba(185, 156, 171, 0.396)`, + shadow: '#6a737d', }; /** diff --git a/app/util/networks/index.js b/app/util/networks/index.js index 6e23ee3656c..90afb779e27 100644 --- a/app/util/networks/index.js +++ b/app/util/networks/index.js @@ -1,4 +1,3 @@ -import { colors } from '../../styles/common'; import URL from 'url-parse'; import AppConstants from '../../core/AppConstants'; import { MAINNET, ROPSTEN, KOVAN, RINKEBY, GOERLI, RPC } from '../../../app/constants/network'; @@ -67,7 +66,7 @@ const NetworkList = { [RPC]: { name: 'Private Network', shortName: 'Private', - color: colors.grey000, + color: '#f2f3f4', networkType: 'rpc', }, }; diff --git a/app/util/theme/index.ts b/app/util/theme/index.ts new file mode 100644 index 00000000000..6bde06e700a --- /dev/null +++ b/app/util/theme/index.ts @@ -0,0 +1,112 @@ +import React, { useContext } from 'react'; +import { useColorScheme, StatusBar, ColorSchemeName } from 'react-native'; +import { Colors, AppThemeKey, Theme } from './models'; +import { useSelector } from 'react-redux'; +import { colors as colorTheme } from '@metamask/design-tokens'; +import Device from '../device'; + +/** + * This is needed to make our unit tests pass since Enzyme doesn't support contextType + * TODO: Convert classes into functional components and remove contextType + */ +export const mockTheme = { colors: colorTheme.light, themeAppearance: 'light' }; + +export const ThemeContext = React.createContext(undefined); + +/** + * Utility function for getting asset from theme (Class components) + * + * @param appTheme Theme from app + * @param osColorScheme Theme from OS + * @param light Light asset + * @param dark Dark asset + * @returns + */ +export const getAssetFromTheme = (appTheme: AppThemeKey, osColorScheme: ColorSchemeName, light: any, dark: any) => { + let asset = light; + switch (appTheme) { + case AppThemeKey.light: + asset = light; + break; + case AppThemeKey.dark: + asset = dark; + break; + case AppThemeKey.os: + asset = osColorScheme === 'dark' ? dark : light; + break; + default: + asset = light; + } + return asset; +}; + +/* eslint-disable import/prefer-default-export */ +export const useAppTheme = (): Theme => { + const osThemeName = useColorScheme(); + const appTheme: AppThemeKey = useSelector((state: any) => state.user.appTheme); + const themeAppearance = getAssetFromTheme(appTheme, osThemeName, AppThemeKey.light, AppThemeKey.dark); + let colors: Colors; + + const setDarkStatusBar = () => { + StatusBar.setBarStyle('light-content', true); + Device.isAndroid() && StatusBar.setBackgroundColor(colorTheme.dark.background.default); + }; + + const setLightStatusBar = () => { + StatusBar.setBarStyle('dark-content', true); + Device.isAndroid() && StatusBar.setBackgroundColor(colorTheme.light.background.default); + }; + + switch (appTheme) { + /* eslint-disable no-fallthrough */ + case AppThemeKey.os: { + if (osThemeName === AppThemeKey.light) { + colors = colorTheme.light; + setLightStatusBar(); + break; + } else if (osThemeName === AppThemeKey.dark) { + colors = colorTheme.dark; + setDarkStatusBar(); + break; + } else { + // Cover cases where OS returns undefined + colors = colorTheme.light; + setLightStatusBar(); + } + } + case AppThemeKey.light: + colors = colorTheme.light; + setLightStatusBar(); + break; + case AppThemeKey.dark: + colors = colorTheme.dark; + setDarkStatusBar(); + break; + default: + // Default uses light theme + colors = colorTheme.light; + setLightStatusBar(); + } + + return { colors, themeAppearance }; +}; + +export const useAppThemeFromContext = (): Theme => { + const theme = useContext(ThemeContext); + return theme; +}; + +/** + * Hook that returns asset based on theme (Functional components) + * + * @param light Light asset + * @param dark Dark asset + * @returns Asset based on theme + */ +export const useAssetFromTheme = (light: any, dark: any) => { + const osColorScheme = useColorScheme(); + const appTheme = useSelector((state: any) => state.user.appTheme); + const asset = getAssetFromTheme(appTheme, osColorScheme, light, dark); + + return asset; +}; diff --git a/app/util/theme/models.ts b/app/util/theme/models.ts new file mode 100644 index 00000000000..aa5cbfd82d1 --- /dev/null +++ b/app/util/theme/models.ts @@ -0,0 +1,12 @@ +// TODO: This should probably be defined from @metamask/design-token library +export type Colors = any; + +export enum AppThemeKey { + os = 'os', + light = 'light', + dark = 'dark', +} +export interface Theme { + colors: Colors; + themeAppearance: AppThemeKey.light | AppThemeKey.dark; +} diff --git a/bitrise.yml b/bitrise.yml index 17d69125c33..36daec98af7 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -323,10 +323,10 @@ app: PROJECT_LOCATION_IOS: ios - opts: is_expand: false - VERSION_NAME: 4.2.2 + VERSION_NAME: 4.3.3 - opts: is_expand: false - VERSION_NUMBER: 834 + VERSION_NUMBER: 846 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/e2e/pages/Drawer/Browser.js b/e2e/pages/Drawer/Browser.js index 49e842da4ae..25961ea3507 100644 --- a/e2e/pages/Drawer/Browser.js +++ b/e2e/pages/Drawer/Browser.js @@ -5,7 +5,7 @@ export const BROWSER_SCREEN_ID = 'browser-screen'; const ANDROID_BROWSER_WEBVIEW_ID = 'browser-webview'; const ADD_BOOKMARKS_SCREEN_ID = 'add-bookmark-screen'; const ADD_BOOKMARKS_BUTTON_ID = 'add-bookmark-confirm-button'; -const ANDROID_CLEAR_INPUT_BUTTON_ID = 'android-cancel-url-button'; +const ANDROID_CLEAR_INPUT_BUTTON_ID = 'cancel-url-button'; const BOTTOM_NAVIGATION_SEARCH_BAR_ID = 'search-button'; const HOME_BUTTON_ID = 'home-button'; const GO_BACK_BUTTON_ID = 'go-back-button'; diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index ad201c2d333..48dbca2baf0 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -43,6 +43,7 @@ 813214A2220E40C7BBB5ED9E /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A783D1CD7D27456796FE2E1B /* Roboto-Bold.ttf */; }; 887E75FB64A54509A08D6C50 /* Roboto-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E020F42F788744B3BCE17F05 /* Roboto-LightItalic.ttf */; }; 8DEB44A7E7EF48E1B3298910 /* EuclidCircularB-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = CE0434C5FB7C4C6F9FEBDCE2 /* EuclidCircularB-Medium.otf */; }; + B0EF7FA927BD16EA00D48B4E /* ThemeColors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B0EF7FA827BD16EA00D48B4E /* ThemeColors.xcassets */; }; BF39E5BAE0F34F9091FF6AC0 /* EuclidCircularB-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = A8DE9C5BC0714D648276E123 /* EuclidCircularB-Semibold.otf */; }; CD13D926E1E84D9ABFE672C0 /* Roboto-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 3E2492C67CF345CABD7B8601 /* Roboto-BlackItalic.ttf */; }; D171C39A8BD44DBEB6B68480 /* EuclidCircularB-MediumItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 42CBA652072F4BE2A8B815C1 /* EuclidCircularB-MediumItalic.otf */; }; @@ -216,6 +217,7 @@ A98029A3662F4C1391489A6B /* EuclidCircularB-Light.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "EuclidCircularB-Light.otf"; path = "../app/fonts/EuclidCircularB-Light.otf"; sourceTree = ""; }; A98DB430A7DA47EFB97EDF8B /* FontAwesome5_Solid.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Solid.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf"; sourceTree = ""; }; AA9EDF17249955C7005D89EE /* MetaMaskDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = MetaMaskDebug.entitlements; path = MetaMask/MetaMaskDebug.entitlements; sourceTree = ""; }; + B0EF7FA827BD16EA00D48B4E /* ThemeColors.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = ThemeColors.xcassets; sourceTree = ""; }; BB8BA2D3C0354D6090B56A8A /* Roboto-Light.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Light.ttf"; path = "../app/fonts/Roboto-Light.ttf"; sourceTree = ""; }; BF485CDA047B4D52852B87F5 /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = ""; }; C752564A28B44392AEE16BD5 /* Roboto-Medium.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Medium.ttf"; path = "../app/fonts/Roboto-Medium.ttf"; sourceTree = ""; }; @@ -288,6 +290,7 @@ 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, 13B07FB71A68108700A75B9A /* main.m */, FE3C9A2458A1416290DEDAD4 /* branch.json */, + B0EF7FA827BD16EA00D48B4E /* ThemeColors.xcassets */, ); name = MetaMask; sourceTree = ""; @@ -637,6 +640,7 @@ 158B063B211A72F500DF3C74 /* InpageBridgeWeb3.js in Resources */, 15D158ED210BD912006982B5 /* Metamask.ttf in Resources */, 48AD4B0AABCB447B99B85DC4 /* Roboto-Black.ttf in Resources */, + B0EF7FA927BD16EA00D48B4E /* ThemeColors.xcassets in Resources */, CD13D926E1E84D9ABFE672C0 /* Roboto-BlackItalic.ttf in Resources */, 813214A2220E40C7BBB5ED9E /* Roboto-Bold.ttf in Resources */, 15AD28AA21B7CFDC005DEB23 /* debug.xcconfig in Resources */, @@ -817,7 +821,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 834; + CURRENT_PROJECT_VERSION = 846; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -853,7 +857,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 4.2.2; + MARKETING_VERSION = 4.3.3; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", @@ -884,7 +888,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 834; + CURRENT_PROJECT_VERSION = 846; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; FRAMEWORK_SEARCH_PATHS = ( @@ -919,7 +923,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 4.2.2; + MARKETING_VERSION = 4.3.3; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "$(inherited)", diff --git a/ios/MetaMask/AppDelegate.m b/ios/MetaMask/AppDelegate.m index df39ac72992..234ebe30b11 100644 --- a/ios/MetaMask/AppDelegate.m +++ b/ios/MetaMask/AppDelegate.m @@ -46,7 +46,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( - rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; + rootView.backgroundColor = [UIColor colorNamed:@"ThemeColors"]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [UIViewController new]; diff --git a/ios/MetaMask/Base.lproj/LaunchScreen.xib b/ios/MetaMask/Base.lproj/LaunchScreen.xib index 0ce36f3be1d..d67e644ea79 100644 --- a/ios/MetaMask/Base.lproj/LaunchScreen.xib +++ b/ios/MetaMask/Base.lproj/LaunchScreen.xib @@ -1,23 +1,27 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/MetaMask/Info.plist b/ios/MetaMask/Info.plist index 17628f3edbd..27393ee4a72 100644 --- a/ios/MetaMask/Info.plist +++ b/ios/MetaMask/Info.plist @@ -112,10 +112,8 @@ UIInterfaceOrientationPortrait - UIUserInterfaceStyle - Light UIViewControllerBasedStatusBarAppearance - + branch_key $(MM_BRANCH_KEY_LIVE) fox_code diff --git a/ios/Podfile.lock b/ios/Podfile.lock index f3cc4c324db..0a72d217703 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -416,7 +416,7 @@ PODS: - React-Core - RNCMaskedView (0.2.6): - React-Core - - RNCPicker (1.8.1): + - RNCPicker (2.2.1): - React-Core - RNDefaultPreference (1.4.3): - React @@ -564,7 +564,7 @@ DEPENDENCIES: - "RNCCheckbox (from `../node_modules/@react-native-community/checkbox`)" - "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)" - "RNCMaskedView (from `../node_modules/@react-native-masked-view/masked-view`)" - - "RNCPicker (from `../node_modules/@react-native-community/picker`)" + - "RNCPicker (from `../node_modules/@react-native-picker/picker`)" - RNDefaultPreference (from `../node_modules/react-native-default-preference`) - RNDeviceInfo (from `../node_modules/react-native-device-info`) - RNFS (from `../node_modules/react-native-fs`) @@ -714,7 +714,7 @@ EXTERNAL SOURCES: RNCMaskedView: :path: "../node_modules/@react-native-masked-view/masked-view" RNCPicker: - :path: "../node_modules/@react-native-community/picker" + :path: "../node_modules/@react-native-picker/picker" RNDefaultPreference: :path: "../node_modules/react-native-default-preference" RNDeviceInfo: @@ -819,7 +819,7 @@ SPEC CHECKSUMS: RNCCheckbox: 357578d3b42652c78ee9a1bb9bcfc3195af6e161 RNCClipboard: ddd4d291537f1667209c9c405aaa4307297e252e RNCMaskedView: c298b644a10c0c142055b3ae24d83879ecb13ccd - RNCPicker: 914b557e20b3b8317b084aca9ff4b4edb95f61e4 + RNCPicker: cb57c823d5ce8d2d0b5dfb45ad97b737260dc59e RNDefaultPreference: 2f8d6d54230edbd78708ada8d63bb275e5a8415b RNDeviceInfo: 8d3a29207835f972bce883723882980143270d55 RNFS: 3ab21fa6c56d65566d1fb26c2228e2b6132e5e32 diff --git a/ios/ThemeColors.xcassets/Contents.json b/ios/ThemeColors.xcassets/Contents.json new file mode 100644 index 00000000000..73c00596a7f --- /dev/null +++ b/ios/ThemeColors.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/ThemeColors.xcassets/ThemeColors.colorset/Contents.json b/ios/ThemeColors.xcassets/ThemeColors.colorset/Contents.json new file mode 100644 index 00000000000..3b271270bee --- /dev/null +++ b/ios/ThemeColors.xcassets/ThemeColors.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0.098", + "green" : "0.090", + "red" : "0.082" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/locales/languages/en.json b/locales/languages/en.json index 5b9105a4d0e..098b0e1d04e 100644 --- a/locales/languages/en.json +++ b/locales/languages/en.json @@ -551,6 +551,12 @@ "hide_zero_balance_tokens_desc": "Prevents tokens with no balance from displaying in your token listing.", "token_detection_title": "Enhanced Token Detection", "token_detection_description": "We use third-party APIs to detect and display new tokens sent to your wallet. Turn off if you don’t want the app to pull data from those services.", + "theme_button_text": "Change Theme", + "theme_title": "Theme ({{theme}})", + "theme_description": "Change your app appearance by setting the theme.", + "theme_os": "System", + "theme_light": "Light", + "theme_dark": "Dark", "network_exists": "This network has already been added." }, "app_information": { diff --git a/package.json b/package.json index 2ad1258e0a3..777d7eba08c 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,7 @@ "dependencies": { "@exodus/react-native-payments": "git+https://github.com/MetaMask/react-native-payments.git#dbc8cbbed570892d2fea5e3d183bf243e062c1e5", "@metamask/contract-metadata": "^1.30.0", + "@metamask/design-tokens": "1.4.2", "@metamask/controllers": "26.0.0", "@metamask/etherscan-link": "^2.0.0", "@metamask/swaps-controller": "^6.6.0", @@ -106,9 +107,9 @@ "@react-native-community/checkbox": "^0.4.2", "@react-native-community/cookies": "^5.0.1", "@react-native-community/netinfo": "6.0.0", - "@react-native-community/picker": "^1.8.1", "@react-native-community/viewpager": "3.3.1", "@react-native-masked-view/masked-view": "^0.2.6", + "@react-native-picker/picker": "^2.2.1", "@react-navigation/bottom-tabs": "^5.11.11", "@react-navigation/compat": "^5.3.20", "@react-navigation/native": "^5.9.4", diff --git a/patches/@metamask+design-tokens+1.4.2.patch b/patches/@metamask+design-tokens+1.4.2.patch new file mode 100644 index 00000000000..077bccbf643 --- /dev/null +++ b/patches/@metamask+design-tokens+1.4.2.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/@metamask/design-tokens/dist/colors/index.js b/node_modules/@metamask/design-tokens/dist/colors/index.js +index 3cbf2e9..751ef0a 100644 +--- a/node_modules/@metamask/design-tokens/dist/colors/index.js ++++ b/node_modules/@metamask/design-tokens/dist/colors/index.js +@@ -98,7 +98,7 @@ const colors = { + disabled: '#1098FC80', + }, + secondary: { +- default: '##F8883', ++ default: '#F8883B', + alternative: '#FAA66C', + muted: '#F8883B26', + inverse: '#FCFCFC', diff --git a/patches/react-native-actionsheet+2.4.2.patch b/patches/react-native-actionsheet+2.4.2.patch new file mode 100644 index 00000000000..9ab6aaab7b4 --- /dev/null +++ b/patches/react-native-actionsheet+2.4.2.patch @@ -0,0 +1,223 @@ +diff --git a/node_modules/react-native-actionsheet/lib/ActionSheetCustom.js b/node_modules/react-native-actionsheet/lib/ActionSheetCustom.js +index 7446a82..71a0fca 100644 +--- a/node_modules/react-native-actionsheet/lib/ActionSheetCustom.js ++++ b/node_modules/react-native-actionsheet/lib/ActionSheetCustom.js +@@ -1,7 +1,7 @@ + import React from 'react' +-import { Text, View, Dimensions, Modal, TouchableHighlight, Animated, ScrollView, Easing } from 'react-native' ++import { Text, View, Dimensions, Modal, TouchableOpacity, Animated, ScrollView, Easing } from 'react-native' + import * as utils from './utils' +-import styles2 from './styles' ++import getStyles from './styles' + + const WARN_COLOR = '#FF3B30' + const MAX_HEIGHT = Dimensions.get('window').height * 0.7 +@@ -9,10 +9,10 @@ const MAX_HEIGHT = Dimensions.get('window').height * 0.7 + class ActionSheet extends React.Component { + static defaultProps = { + tintColor: '#007AFF', +- buttonUnderlayColor: '#F4F4F4', + onPress: () => {}, + styles: {}, +- useNativeDriver: true ++ useNativeDriver: true, ++ theme: 'light' + } + + constructor (props) { +@@ -30,8 +30,9 @@ class ActionSheet extends React.Component { + } + + get styles () { +- const { styles } = this.props ++ const { styles, theme } = this.props + const obj = {} ++ const styles2 = getStyles(theme) + Object.keys(styles2).forEach((key) => { + const arr = [styles2[key]] + if (styles[key]) { +@@ -87,7 +88,7 @@ class ActionSheet extends React.Component { + * box size: height, marginTop, marginBottom + */ + _calculateHeight (props) { +- const styles = this.styles ++ const styles = this.styles; + + const getHeight = (name) => { + const style = styles[name][styles[name].length - 1] +@@ -154,21 +155,20 @@ class ActionSheet extends React.Component { + + _createButton (title, index) { + const styles = this.styles +- const { buttonUnderlayColor, cancelButtonIndex, destructiveButtonIndex, tintColor } = this.props ++ const { cancelButtonIndex, destructiveButtonIndex, tintColor } = this.props + const fontColor = destructiveButtonIndex === index ? WARN_COLOR : tintColor + const buttonBoxStyle = cancelButtonIndex === index ? styles.cancelButtonBox : styles.buttonBox + return ( +- this.hide(index)} + > + {React.isValidElement(title) ? title : ( + {title} + )} +- ++ + ) + } + +diff --git a/node_modules/react-native-actionsheet/lib/options.js b/node_modules/react-native-actionsheet/lib/options.js +index 7f7d230..1e01339 100644 +--- a/node_modules/react-native-actionsheet/lib/options.js ++++ b/node_modules/react-native-actionsheet/lib/options.js +@@ -48,5 +48,11 @@ export default [ + * @example + * (buttonIndex) => if (buttonIndex === 1) { // do something } + */ +- 'onPress' ++ 'onPress', ++ ++ /** ++ * App theme - 'light' | 'dark' ++ * @type string ++ */ ++ 'theme', + ] +diff --git a/node_modules/react-native-actionsheet/lib/styles.js b/node_modules/react-native-actionsheet/lib/styles.js +index 52ae1b2..e0a18bf 100644 +--- a/node_modules/react-native-actionsheet/lib/styles.js ++++ b/node_modules/react-native-actionsheet/lib/styles.js +@@ -1,62 +1,70 @@ + import { StyleSheet } from 'react-native' + export const hairlineWidth = StyleSheet.hairlineWidth +-export default { +- overlay: { +- position: 'absolute', +- top: 0, +- right: 0, +- bottom: 0, +- left: 0, +- opacity: 0.4, +- backgroundColor: '#000' +- }, +- wrapper: { +- flex: 1, +- flexDirection: 'row' +- }, +- body: { +- flex: 1, +- alignSelf: 'flex-end', +- backgroundColor: '#e5e5e5' +- }, +- titleBox: { +- height: 40, +- alignItems: 'center', +- justifyContent: 'center', +- backgroundColor: '#fff' +- }, +- titleText: { +- color: '#757575', +- fontSize: 14 +- }, +- messageBox: { +- height: 30, +- paddingLeft: 10, +- paddingRight: 10, +- paddingBottom: 10, +- alignItems: 'center', +- justifyContent: 'center', +- backgroundColor: '#fff' +- }, +- messageText: { +- color: '#9a9a9a', +- fontSize: 12 +- }, +- buttonBox: { +- height: 50, +- marginTop: hairlineWidth, +- alignItems: 'center', +- justifyContent: 'center', +- backgroundColor: '#fff' +- }, +- buttonText: { +- fontSize: 18 +- }, +- cancelButtonBox: { +- height: 50, +- marginTop: 6, +- alignItems: 'center', +- justifyContent: 'center', +- backgroundColor: '#fff' ++export default function(theme) { ++ const isDarkMode = theme === 'dark'; ++ const backgroundDefault = isDarkMode ? '#141618' : '#ffffff'; ++ const backgroundAlternative = isDarkMode ? '#24272A' : '#F2F4F6'; ++ const textDefault = isDarkMode ? '#ffffff' : '#24272A'; ++ const textAlternative = isDarkMode ? '#FAFBFC' : '#535A61'; ++ const overlay = isDarkMode ? '#FFFFFF66' : '#00000099'; ++ return { ++ overlay: { ++ position: 'absolute', ++ top: 0, ++ right: 0, ++ bottom: 0, ++ left: 0, ++ opacity: 0.7, ++ backgroundColor: overlay ++ }, ++ wrapper: { ++ flex: 1, ++ flexDirection: 'row' ++ }, ++ body: { ++ flex: 1, ++ alignSelf: 'flex-end', ++ backgroundColor: backgroundAlternative ++ }, ++ titleBox: { ++ height: 40, ++ alignItems: 'center', ++ justifyContent: 'center', ++ backgroundColor: backgroundDefault ++ }, ++ titleText: { ++ color: textDefault, ++ fontSize: 14 ++ }, ++ messageBox: { ++ height: 30, ++ paddingLeft: 10, ++ paddingRight: 10, ++ paddingBottom: 10, ++ alignItems: 'center', ++ justifyContent: 'center', ++ backgroundColor: backgroundDefault ++ }, ++ messageText: { ++ color: textAlternative, ++ fontSize: 12 ++ }, ++ buttonBox: { ++ height: 50, ++ marginTop: hairlineWidth, ++ alignItems: 'center', ++ justifyContent: 'center', ++ backgroundColor: backgroundDefault ++ }, ++ buttonText: { ++ fontSize: 18 ++ }, ++ cancelButtonBox: { ++ height: 50, ++ marginTop: 6, ++ alignItems: 'center', ++ justifyContent: 'center', ++ backgroundColor: backgroundDefault ++ } + } + } diff --git a/patches/react-native-animated-fox+2.0.1.patch b/patches/react-native-animated-fox+2.0.1.patch new file mode 100644 index 00000000000..d4b5b143950 --- /dev/null +++ b/patches/react-native-animated-fox+2.0.1.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/react-native-animated-fox/index.js b/node_modules/react-native-animated-fox/index.js +index ef01ddb..c71bdcb 100644 +--- a/node_modules/react-native-animated-fox/index.js ++++ b/node_modules/react-native-animated-fox/index.js +@@ -69,7 +69,7 @@ class AnimatedFox extends PureComponent { + } + + body{ +- background: white; ++ background: ${this.props.bgColor}; + text-align: center; + color: white; + font-family: roboto; diff --git a/yarn.lock b/yarn.lock index 524d1e345ff..4dad6663240 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2198,6 +2198,11 @@ web3 "^0.20.7" web3-provider-engine "^16.0.3" +"@metamask/design-tokens@1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@metamask/design-tokens/-/design-tokens-1.4.2.tgz#023030f3eca181b10bf89c5813a9656f4e7e2852" + integrity sha512-kS63Tx+WOUloBTz4pDDG3DcisoXwaT+06/a2KTSDI0n1t3IQPLo1FCMsijqtYWFPfAI06tWOjtaslpFTB+dsAg== + "@metamask/eslint-config-typescript@^7.0.0": version "7.0.1" resolved "https://registry.yarnpkg.com/@metamask/eslint-config-typescript/-/eslint-config-typescript-7.0.1.tgz#e013f7f0505741b9321cab21351136f651abbba6" @@ -2499,11 +2504,6 @@ resolved "https://registry.yarnpkg.com/@react-native-community/netinfo/-/netinfo-6.0.0.tgz#2a4d7190b508dd0c2293656c9c1aa068f6f60a71" integrity sha512-Z9M8VGcF2IZVOo2x+oUStvpCW/8HjIRi4+iQCu5n+PhC7OqCQX58KYAzdBr///alIfRXiu6oMb+lK+rXQH1FvQ== -"@react-native-community/picker@^1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@react-native-community/picker/-/picker-1.8.1.tgz#94f14f0aad98fa7592967b941be97deec95c3805" - integrity sha512-Sj9DzX1CSnmYiuEQ5fQhExoo4XjSKoZkqLPAAybycq6RHtCuWppf+eJXRMCOJki25BlKSSt+qVqg0fIe//ujNQ== - "@react-native-community/viewpager@3.3.1": version "3.3.1" resolved "https://registry.yarnpkg.com/@react-native-community/viewpager/-/viewpager-3.3.1.tgz#c2c530fb99653252a4272c8cf1bb85dbd1edf57d" @@ -2519,6 +2519,11 @@ resolved "https://registry.yarnpkg.com/@react-native-masked-view/masked-view/-/masked-view-0.2.6.tgz#b26c52d5db3ad0926b13deea79c69620966a9221" integrity sha512-303CxmetUmgiX9NSUxatZkNh9qTYYdiM8xkGf9I3Uj20U3eGY3M78ljeNQ4UVCJA+FNGS5nC1dtS9GjIqvB4dg== +"@react-native-picker/picker@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@react-native-picker/picker/-/picker-2.2.1.tgz#32b9f540d8e88a73d8856f73cca88251cecb9614" + integrity sha512-EC7yv22QLHlTfnbC1ez9IUdXTOh1W31x96Oir0PfskSGFFJMWWdLTg4VrcE2DsGLzbfjjkBk123c173vf2a5MQ== + "@react-native/assets@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@react-native/assets/-/assets-1.0.0.tgz#c6f9bf63d274bafc8e970628de24986b30a55c8e"