diff --git a/assets/gif/coins/bitcoin/kiss.gif b/assets/gif/coins/bitcoin/kiss.gif new file mode 100644 index 000000000..8649f857d Binary files /dev/null and b/assets/gif/coins/bitcoin/kiss.gif differ diff --git a/assets/gif/coins/bitcoin/plain.gif b/assets/gif/coins/bitcoin/plain.gif new file mode 100644 index 000000000..5f3680219 Binary files /dev/null and b/assets/gif/coins/bitcoin/plain.gif differ diff --git a/assets/gif/coins/bitcoincash/kiss.gif b/assets/gif/coins/bitcoincash/kiss.gif new file mode 100644 index 000000000..bbd5924b1 Binary files /dev/null and b/assets/gif/coins/bitcoincash/kiss.gif differ diff --git a/assets/gif/coins/bitcoincash/plain.gif b/assets/gif/coins/bitcoincash/plain.gif new file mode 100644 index 000000000..4c8d29c77 Binary files /dev/null and b/assets/gif/coins/bitcoincash/plain.gif differ diff --git a/assets/gif/coins/dogecoin/kiss.gif b/assets/gif/coins/dogecoin/kiss.gif new file mode 100644 index 000000000..d0f1ffba4 Binary files /dev/null and b/assets/gif/coins/dogecoin/kiss.gif differ diff --git a/assets/gif/coins/dogecoin/plain.gif b/assets/gif/coins/dogecoin/plain.gif new file mode 100644 index 000000000..9ce1fbb7a Binary files /dev/null and b/assets/gif/coins/dogecoin/plain.gif differ diff --git a/assets/gif/coins/epicCash/kiss.gif b/assets/gif/coins/epicCash/kiss.gif new file mode 100644 index 000000000..ef8f27fab Binary files /dev/null and b/assets/gif/coins/epicCash/kiss.gif differ diff --git a/assets/gif/coins/epicCash/plain.gif b/assets/gif/coins/epicCash/plain.gif new file mode 100644 index 000000000..4a05889af Binary files /dev/null and b/assets/gif/coins/epicCash/plain.gif differ diff --git a/assets/gif/coins/ethereum/kiss.gif b/assets/gif/coins/ethereum/kiss.gif new file mode 100644 index 000000000..712834662 Binary files /dev/null and b/assets/gif/coins/ethereum/kiss.gif differ diff --git a/assets/gif/coins/ethereum/plain.gif b/assets/gif/coins/ethereum/plain.gif new file mode 100644 index 000000000..0da0eeb64 Binary files /dev/null and b/assets/gif/coins/ethereum/plain.gif differ diff --git a/assets/gif/coins/firo/kiss.gif b/assets/gif/coins/firo/kiss.gif new file mode 100644 index 000000000..0225077db Binary files /dev/null and b/assets/gif/coins/firo/kiss.gif differ diff --git a/assets/gif/coins/firo/plain.gif b/assets/gif/coins/firo/plain.gif new file mode 100644 index 000000000..3d2f9b620 Binary files /dev/null and b/assets/gif/coins/firo/plain.gif differ diff --git a/assets/gif/coins/litecoin/kiss.gif b/assets/gif/coins/litecoin/kiss.gif new file mode 100644 index 000000000..68272d06d Binary files /dev/null and b/assets/gif/coins/litecoin/kiss.gif differ diff --git a/assets/gif/coins/litecoin/plain.gif b/assets/gif/coins/litecoin/plain.gif new file mode 100644 index 000000000..5c12d94bf Binary files /dev/null and b/assets/gif/coins/litecoin/plain.gif differ diff --git a/assets/gif/coins/monero/kiss.gif b/assets/gif/coins/monero/kiss.gif new file mode 100644 index 000000000..b54fb2096 Binary files /dev/null and b/assets/gif/coins/monero/kiss.gif differ diff --git a/assets/gif/coins/monero/plain.gif b/assets/gif/coins/monero/plain.gif new file mode 100644 index 000000000..5090eefc2 Binary files /dev/null and b/assets/gif/coins/monero/plain.gif differ diff --git a/assets/gif/coins/namecoin/kiss.gif b/assets/gif/coins/namecoin/kiss.gif new file mode 100644 index 000000000..10b74b356 Binary files /dev/null and b/assets/gif/coins/namecoin/kiss.gif differ diff --git a/assets/gif/coins/namecoin/plain.gif b/assets/gif/coins/namecoin/plain.gif new file mode 100644 index 000000000..954fa0046 Binary files /dev/null and b/assets/gif/coins/namecoin/plain.gif differ diff --git a/assets/gif/coins/particl/kiss.gif b/assets/gif/coins/particl/kiss.gif new file mode 100644 index 000000000..0cc80c1c8 Binary files /dev/null and b/assets/gif/coins/particl/kiss.gif differ diff --git a/assets/gif/coins/particl/plain.gif b/assets/gif/coins/particl/plain.gif new file mode 100644 index 000000000..99d36ef9c Binary files /dev/null and b/assets/gif/coins/particl/plain.gif differ diff --git a/assets/gif/coins/wownero/kiss.gif b/assets/gif/coins/wownero/kiss.gif new file mode 100644 index 000000000..16c1c1fdc Binary files /dev/null and b/assets/gif/coins/wownero/kiss.gif differ diff --git a/assets/gif/coins/wownero/plain.gif b/assets/gif/coins/wownero/plain.gif new file mode 100644 index 000000000..0c30a857f Binary files /dev/null and b/assets/gif/coins/wownero/plain.gif differ diff --git a/assets/images/ethereum2.svg b/assets/images/ethereum2.svg deleted file mode 100644 index df9a44d1e..000000000 --- a/assets/images/ethereum2.svg +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/images/oceanBreeze/stack.png b/assets/images/oceanBreeze/stack.png deleted file mode 100644 index b59af1608..000000000 Binary files a/assets/images/oceanBreeze/stack.png and /dev/null differ diff --git a/assets/images/unclaimed.png b/assets/images/unclaimed.png deleted file mode 100644 index f99d4ab2a..000000000 Binary files a/assets/images/unclaimed.png and /dev/null differ diff --git a/assets/lottie/test.json b/assets/lottie/test.json deleted file mode 100644 index a8130f1da..000000000 --- a/assets/lottie/test.json +++ /dev/null @@ -1 +0,0 @@ -{"v":"4.8.0","meta":{"g":"LottieFiles AE ","a":"","k":"","d":"","tc":""},"fr":25,"ip":0,"op":75,"w":600,"h":600,"nm":"stack-test-1","ddd":0,"assets":[{"id":"image_0","w":171,"h":171,"u":"","p":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKsAAACrCAYAAAAZ6GwZAAAOSklEQVR4Xu2d309TWxbHd+ttEQaQqxgqcvlZDTRQwAASFCmQKgnWufwFlxcJmZdx/AeGm0xmHubF+zZvM/4F4w1PxgfBGKPEGIYXeZmouZFIUvUSGVFa25tF2juF29Jzzl7rnL3PWU2MD9177X2++9PDOmutvY9P8IcV0EQBnybz5GmyAoJhZQi0UYBh1WapeKIMKzOgjQIMqzZLxRNlWJkBbRRgWLVZKp4ow8oMaKMAw6rNUvFEGVZmQBsFGFZtloonyrAyA9oowLBqs1Q8UYaVGdBGAYZVm6XiiTKszIA2CjCs2iwVT5RhZQa0UYBh1WapeKIMKzOgjQIMqzZLxRNlWJkBbRRgWLVZKp4ow8oMaKMAw6rNUvFEGVZmQBsFGFZtloonyrAyA9oowLBqs1Q8UYaVkIHFxcWYEOJbIUSfEGKsYKhXPp9vVQixlEql7szMzLwknIZrTDOsBEu5uLgIgN4SQrQYNH87nU4vMLSHq8WwGqTJSLObN29eDYVCfwuHw92BQMBIl1/bZLPZLZ/PdyudTt+amZn52VRnjzRmWBEWen5+vlUI8deGhoYrAwMDxyVNvspmswvXrl37l6Qd13VnWCWWdHZ2ti4YDN4QQvzp1KlTaQRQC2ez7Pf7b0xPT4Nvyx8h+DBhqxRcv359Fv5sCyGO1dbWJsfGxuqt2irTD/zZG+waMKym+Zqfn49lMhmAtDffeXJyUlRVVZm2ZbRD3p9NJBILRvu4sR27AQZXFfzSTCYDfmRhCEqEQqHNwcHBBoNmZJu9EkLcSCQSd2QN6difYS2zauCXVlRULGSz2T8Wazo2NiZqa2vtXntP+rMM6yGYzc3NwZ9deIA6VqyZ3+/fmZ6errSb1ILxfsjFZz0R6mJYi5A2NzdnKKhfXV39enx8/LSDsArwZ/1+/8LVq1fBj3b1h2EtWN7cwxPcTff5paUIaGtre9Xd3W00S0UNEvizs4lEYol6IKfsM6xCiNzDE0D6nZmFUAzW/NSX0+n0rBtTt56GtSCo/2czkObbKgprfnqu82c9C2thUN8KqNCnqanpdX9/v6M+62FzB38WHhDdkrr1HKw5vxTipdK+pgoPWAZ/aP/JxWe19mc9A2upoL7BxS7a7OjRo5vxeNyuhIDMVPf6+ny+H1OpFKRutayfdT2sOb8UwjqmHp6MkpFIJIw2Vand9zqWIroa1nJBfQx6HMpgSU9dR3/WlbDmHp4gFCXtl5ajorOz8/2ZM2e+LtdO4e+XhRALOsRnXQWr2aA+BkB1dXU/jY6OfoNhy2Ebym+tcQWsVoP6WHBMTU0Js9tYsMbGtKP61hqtYZUN6mMtdCQS+dTR0XEUy54CdpTcWqMtrBhBfSwoAoHAh6mpqRosewrZUaoUUTtYMYP6mFAMDg5CITamSZVsKbG1RhtYKYL6mDQEg8HtK1euVGPaVMmWCltrlIeVOqiPCURvb+9Oc3Ozk8XYmJdTypZjW2uUhbXg4alkpb4dK2NmDL/f//ny5csVbogMGLhu2/1ZJWG1M6hvYFFMNTl58uTW8PBw0W0wpgzp09i2UkSlYHUiqE/BhAtDWYfKZNfWGiVghYenL1++3PL5fL+ngMcJmy6PDhzmz5JtrXEcVjuKTZyAFXa+jo6OVjqwTduJyz04JsnWGsdgVTVeirnSHgcWpET1Z22HVadQFBa4HglpFZULsxTRVljn5uYgDAWle156Wt5bxObm5mRvby/V4W1YvytKO9Jba2yBtdhhZpSqqGq7srIy2d/fX3/ixAlVp0g9r9uJRGLW6iCksLrxKd+q0IX96uvr9+6ylCcPYswT0QZKAoEEVvBLnz9//o/3799ffPPmTXpnZ6c6lUqdCAQCbysrK7dDodBXra2tp1tb4cBo737C4fBWOBw+5uKMF2pqFh3WqqqqP6TT6b/s7u6W3epRUVGxdf78+WBnZ6fb8+klf5GBQGArEokE3VRTQFXEjQkr3CZ/c36pkfsmQBuPx481NjYaae7KNjU1NZs9PT0NLvBnybbHYMEK73mCAxSknvJDodCb8fHxUE2NG+uYjf3G4HDivr6+Bg1dA/KNhxiwwh0VXtIgBWrhUkaj0c1z5841BINBYyvsslaQTGhvb9/t6upC05RKIsw4ark5YsAKoP56vn65AY1+Dwt28eJF4XV/tq+v75jCOxBsPSxDFlaImf3TKIBW2lVVVW1OTEw0eNmfhbfBDA4OKhPqcuoYIllY4cwk8oMkAPKmpqb/jo6OdnjZn21pafnQ1dVV46A/6+iBxTKwwlHm/7Zyt7Tax+/3/y8SiSQHBgZaPOzPfurp6cnaGeqyq161HBcysMJhZ0XfYFJuUNnvIbkwPDwsurq6PJu3tDF1i1o5JbP2MrBCqMrQ2fsyEzysb21t7at4PN7igtikZYkIU7ckNamWL1TydZjwOhslQivNzc0/TUxMfONh1+Bje3t7Cil1i5oilYHzYF+ZO2sWcyKytsCf7e7u3h4eHtbmcF/Zaz7YXyZ1q8K5AOX0cA2s+QsFfzYWi1W2tbXRvUy1nKoOfw+pW0iqmNhSo8SJK+Vkk4HVtrBVuYso9n1dXd3rycnJ0172Zw2kbslTpFbWrlQfGVgdf8AyIsTZs2dfj4yMnPawP7vT0dHh7+zsrCjQS8lTAsutp+thBQHAnx0YGNiNRCJfexVa8GfD4XAgHA7/Xcf3CcA6ysAKe6ksveys3C+I6nuv1s++fftW3L9/f/Pdu3fw8Al/+iFNrt0bW2RgtT2DhQXx8ePHN0dGRlxfb7C7uyuWlpY2X758WSxC8kNu86Y2b9SWgRVKA19gAeSEndbW1s1YLObKUsTV1dX3T58+PZrJZA7bhQFvIIS/kFq8UVsGVuCLpDzQTnD9fv/HaDSaGhoaUiLBIXvtGxsb4t69e1ufP382cz1726RzBfSyUyDrLwurY/UB2IqAP3vp0qWArvHZDx8+AKTJZDIpczbBjzlolfRnZWHV3hU4CD34s+Pj49rshQK/9NmzZ5tra2uYmbvvc66BUv6sLKyw1lrEW83eiXWIz66vr+88fPhQlPFLzV56vv3eG7Vzm0Ct2kDthwGrtlGBckrC1pqhoSFfNBpV6rVB4JcuLS0lt7e3Zf7kl7v8/PfK+LMYsLriQeuwlVNlqzj4pcvLy8mNjQ07ID0oieP+LBasMSHEfaM/VV3bQe1oPB6vt3trDfilq6urW2tra19lMpnfOagfuAbwUA3/bPdnsWAF/e4IIVxzcvVhQNi5VRz80idPnuyaDEVR8ww1rxCfhUNNbPtgwlqXS+GZie/ZdqHYAx05cuTThQsXslRbxcEvffToUT5Fij19LHt7VVt2xWcxYQUBXPuwVWp1q6urk7FYrB5rq3iZFCkWZNh2buegJY3PYsMKImhX4IKxco2NjcmxsTEpf3ZlZQX80kAmk9GxcJzcn6WAFdYefJnvMCDQyQaUIkaj0TScomKmFPHFixcfHzx4kFLML7UqPZk/SwWrZ4GFCzdaigihqLt376rul1qFFvxZSCpA/QjKhxJWmKBragesqF2qFBH80sePHyfX19ediJdauRSZPuDPArTSoS5qWOEiodAXoPVElKDYqhaWIq6trX1aWVnJEqVIZaCi7Jv3Z+F5xvLHDlhhcpYPGrZ8ZYp1hFLEQCDgFr/UqrqQuoWzfC197II1Pzm4y8Kvy5bD3Cwpwp2oFJDemWA3rCAEJA/Ah9Hm1exUq+cRu2h7vpyANb9G4BqAL+uJFK1HwCy8zL3jMTGzW07Cmr8wKIIBaNFPz/YgICpcMsrDVLELUQHWQn/W01EDFUiTnANamEp1WAv9Wa3OI5BcYDd0R08A6ABroT9r6Z1ablh5ja5h73jMXHko+bRVcgOKXSz4swAth7rIUTA1AHnRik531oNz9eyr300hZE9jW8oBdYY1789CQsGR9xjYw4HSozi+cVB1N6DY6kG6DqIGjr7PQGmscCenzJZsHWHNLwXsSgBo2Z/FhbPQmlKHXegMa15UcA04dYsLrOPbrnX3WQ9bDkjdArSe252Ay6hAT5Fizs8Nd9ZCPSDUBdCyP2uOEi2OvnQbrPkl4lJE47BKl+4ZH0qupVthzYe6wJfl1G1xRmxJkcrhub+3m2HNXymXIu5fc1tTpAyrNQW8XopIVrpnbTnM9/LCnfWgKl5M3ZKW7pnHzloPL8Ka92e9kLq19Swqawga7+VVWAv9WTeWIpKdimIcLfyWXoc1r6ibShGVSpFiIsuw7ldT59StkilShhVTgd/agq3iUCCjS+rW8dI92uX4v3W+s5ZWWvVSRGVK9xhWuxQoP46KqVttUqTl5TXegu+sxrRS5RQZtNNNjF22Wq0YVnPr4VQpotKle+YktN6aYbWmnV2pW+1TpNbkLd6LYZVTkzJ164oUqZy8+3szrPJqgj+LmbrVrnRPXkJjFhhWYzoZaSV7YLK2pXtGxMFow7BiqLjfhtnUrSOnm+BfNr1FhpVOYyOpW8dON6G7bDrLDCudtmC5VOrWMylSTHkZVkw1S9vKp27hf4gg2PqCXnsukX4UhpVeYx4BSQGGFUlINkOvAMNKrzGPgKQAw4okJJuhV4BhpdeYR0BSgGFFEpLN0CvAsNJrzCMgKcCwIgnJZugVYFjpNeYRkBRgWJGEZDP0CjCs9BrzCEgKMKxIQrIZegUYVnqNeQQkBRhWJCHZDL0CDCu9xjwCkgIMK5KQbIZeAYaVXmMeAUkBhhVJSDZDrwDDSq8xj4CkAMOKJCSboVeAYaXXmEdAUoBhRRKSzdArwLDSa8wjICnAsCIJyWboFWBY6TXmEZAUYFiRhGQz9AowrPQa8whICjCsSEKyGXoFGFZ6jXkEJAUYViQh2Qy9AgwrvcY8ApICvwBH7cTZ9uA+jwAAAABJRU5ErkJggg==","e":1}],"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"stack-icon.ai","cl":"ai","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[306,304,0],"to":[0,4,0],"ti":[0,4.167,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":26,"s":[306,328,0],"to":[0,-4.167,0],"ti":[0,4,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":50,"s":[306,279,0],"to":[0,-4,0],"ti":[0,-4.167,0]},{"t":75,"s":[306,304,0]}],"ix":2,"x":"var $bm_rt;\n$bm_rt = transform.position;"},"a":{"a":0,"k":[85.5,85.5,0],"ix":1},"s":{"a":0,"k":[269.591,269.591,100],"ix":6}},"ao":0,"ip":0,"op":750,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/assets/svg/chanstheme.svg b/assets/svg/chanstheme.svg new file mode 100644 index 000000000..0a94d5f57 --- /dev/null +++ b/assets/svg/chanstheme.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/svg/fruitSorbet/persona-easy-1.png b/assets/svg/fruitSorbet/persona-easy-1.png deleted file mode 100644 index f2dd39e2f..000000000 Binary files a/assets/svg/fruitSorbet/persona-easy-1.png and /dev/null differ diff --git a/assets/svg/fruitSorbet/persona-incognito-1.png b/assets/svg/fruitSorbet/persona-incognito-1.png deleted file mode 100644 index 16465fcff..000000000 Binary files a/assets/svg/fruitSorbet/persona-incognito-1.png and /dev/null differ diff --git a/assets/svg/list-ul.svg b/assets/svg/list-ul.svg new file mode 100644 index 000000000..f5cef4eae --- /dev/null +++ b/assets/svg/list-ul.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svg/oceanBreeze/persona-easy-1.png b/assets/svg/oceanBreeze/persona-easy-1.png deleted file mode 100644 index 20cafb519..000000000 Binary files a/assets/svg/oceanBreeze/persona-easy-1.png and /dev/null differ diff --git a/assets/svg/oceanBreeze/persona-easy-1.svg b/assets/svg/oceanBreeze/persona-easy-1.svg deleted file mode 100644 index f21e19345..000000000 --- a/assets/svg/oceanBreeze/persona-easy-1.svg +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/svg/oceanBreeze/persona-incognito-1.png b/assets/svg/oceanBreeze/persona-incognito-1.png deleted file mode 100644 index 8453cfa76..000000000 Binary files a/assets/svg/oceanBreeze/persona-incognito-1.png and /dev/null differ diff --git a/assets/svg/oceanBreeze/persona-incognito-1.svg b/assets/svg/oceanBreeze/persona-incognito-1.svg deleted file mode 100644 index a8037e997..000000000 --- a/assets/svg/oceanBreeze/persona-incognito-1.svg +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/svg/oledBlack/persona-easy-1.svg b/assets/svg/oledBlack/persona-easy-1.svg deleted file mode 100644 index 1e15b8dab..000000000 --- a/assets/svg/oledBlack/persona-easy-1.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assets/svg/oledBlack/persona-incognito-1.svg b/assets/svg/oledBlack/persona-incognito-1.svg deleted file mode 100644 index c31c285b1..000000000 --- a/assets/svg/oledBlack/persona-incognito-1.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assets/svg/dark/bell-new.svg b/assets/svg/themed/dark/bell-new.svg similarity index 100% rename from assets/svg/dark/bell-new.svg rename to assets/svg/themed/dark/bell-new.svg diff --git a/assets/images/dark/bitcoin.svg b/assets/svg/themed/dark/bitcoin.svg similarity index 100% rename from assets/images/dark/bitcoin.svg rename to assets/svg/themed/dark/bitcoin.svg diff --git a/assets/images/dark/bitcoincash.svg b/assets/svg/themed/dark/bitcoincash.svg similarity index 100% rename from assets/images/dark/bitcoincash.svg rename to assets/svg/themed/dark/bitcoincash.svg diff --git a/assets/svg/dark/buy-coins-icon.svg b/assets/svg/themed/dark/buy-coins-icon.svg similarity index 100% rename from assets/svg/dark/buy-coins-icon.svg rename to assets/svg/themed/dark/buy-coins-icon.svg diff --git a/assets/images/dark/doge.svg b/assets/svg/themed/dark/doge.svg similarity index 100% rename from assets/images/dark/doge.svg rename to assets/svg/themed/dark/doge.svg diff --git a/assets/images/dark/epic-cash.svg b/assets/svg/themed/dark/epic-cash.svg similarity index 100% rename from assets/images/dark/epic-cash.svg rename to assets/svg/themed/dark/epic-cash.svg diff --git a/assets/svg/dark/exchange-2.svg b/assets/svg/themed/dark/exchange-2.svg similarity index 100% rename from assets/svg/dark/exchange-2.svg rename to assets/svg/themed/dark/exchange-2.svg diff --git a/assets/images/dark/firo.svg b/assets/svg/themed/dark/firo.svg similarity index 100% rename from assets/images/dark/firo.svg rename to assets/svg/themed/dark/firo.svg diff --git a/assets/images/dark/litecoin.svg b/assets/svg/themed/dark/litecoin.svg similarity index 100% rename from assets/images/dark/litecoin.svg rename to assets/svg/themed/dark/litecoin.svg diff --git a/assets/images/dark/monero.svg b/assets/svg/themed/dark/monero.svg similarity index 100% rename from assets/images/dark/monero.svg rename to assets/svg/themed/dark/monero.svg diff --git a/assets/images/dark/namecoin.svg b/assets/svg/themed/dark/namecoin.svg similarity index 100% rename from assets/images/dark/namecoin.svg rename to assets/svg/themed/dark/namecoin.svg diff --git a/assets/images/dark/particl.svg b/assets/svg/themed/dark/particl.svg similarity index 100% rename from assets/images/dark/particl.svg rename to assets/svg/themed/dark/particl.svg diff --git a/assets/svg/dark/persona-easy-1.svg b/assets/svg/themed/dark/persona-easy-1.svg similarity index 100% rename from assets/svg/dark/persona-easy-1.svg rename to assets/svg/themed/dark/persona-easy-1.svg diff --git a/assets/svg/dark/persona-incognito-1.svg b/assets/svg/themed/dark/persona-incognito-1.svg similarity index 100% rename from assets/svg/dark/persona-incognito-1.svg rename to assets/svg/themed/dark/persona-incognito-1.svg diff --git a/assets/svg/dark/stack-icon1.svg b/assets/svg/themed/dark/stack-icon1.svg similarity index 100% rename from assets/svg/dark/stack-icon1.svg rename to assets/svg/themed/dark/stack-icon1.svg diff --git a/assets/images/dark/stack.svg b/assets/svg/themed/dark/stack.svg similarity index 100% rename from assets/images/dark/stack.svg rename to assets/svg/themed/dark/stack.svg index 22dce4736..94929475d 100644 --- a/assets/images/dark/stack.svg +++ b/assets/svg/themed/dark/stack.svg @@ -1,4 +1,10 @@ + + + + + + @@ -106,10 +112,4 @@ - - - - - - diff --git a/assets/svg/dark/tx-exchange-icon-failed.svg b/assets/svg/themed/dark/tx-exchange-icon-failed.svg similarity index 100% rename from assets/svg/dark/tx-exchange-icon-failed.svg rename to assets/svg/themed/dark/tx-exchange-icon-failed.svg diff --git a/assets/svg/dark/tx-exchange-icon-pending.svg b/assets/svg/themed/dark/tx-exchange-icon-pending.svg similarity index 100% rename from assets/svg/dark/tx-exchange-icon-pending.svg rename to assets/svg/themed/dark/tx-exchange-icon-pending.svg diff --git a/assets/svg/dark/tx-exchange-icon.svg b/assets/svg/themed/dark/tx-exchange-icon.svg similarity index 100% rename from assets/svg/dark/tx-exchange-icon.svg rename to assets/svg/themed/dark/tx-exchange-icon.svg diff --git a/assets/svg/dark/tx-icon-receive-failed.svg b/assets/svg/themed/dark/tx-icon-receive-failed.svg similarity index 100% rename from assets/svg/dark/tx-icon-receive-failed.svg rename to assets/svg/themed/dark/tx-icon-receive-failed.svg diff --git a/assets/svg/dark/tx-icon-receive-pending.svg b/assets/svg/themed/dark/tx-icon-receive-pending.svg similarity index 100% rename from assets/svg/dark/tx-icon-receive-pending.svg rename to assets/svg/themed/dark/tx-icon-receive-pending.svg diff --git a/assets/svg/dark/tx-icon-receive.svg b/assets/svg/themed/dark/tx-icon-receive.svg similarity index 100% rename from assets/svg/dark/tx-icon-receive.svg rename to assets/svg/themed/dark/tx-icon-receive.svg diff --git a/assets/svg/dark/tx-icon-send-failed.svg b/assets/svg/themed/dark/tx-icon-send-failed.svg similarity index 100% rename from assets/svg/dark/tx-icon-send-failed.svg rename to assets/svg/themed/dark/tx-icon-send-failed.svg diff --git a/assets/svg/dark/tx-icon-send-pending.svg b/assets/svg/themed/dark/tx-icon-send-pending.svg similarity index 100% rename from assets/svg/dark/tx-icon-send-pending.svg rename to assets/svg/themed/dark/tx-icon-send-pending.svg diff --git a/assets/svg/dark/tx-icon-send.svg b/assets/svg/themed/dark/tx-icon-send.svg similarity index 100% rename from assets/svg/dark/tx-icon-send.svg rename to assets/svg/themed/dark/tx-icon-send.svg diff --git a/assets/images/dark/wownero.svg b/assets/svg/themed/dark/wownero.svg similarity index 100% rename from assets/images/dark/wownero.svg rename to assets/svg/themed/dark/wownero.svg diff --git a/assets/svg/forest/bell-new.svg b/assets/svg/themed/forest/bell-new.svg similarity index 100% rename from assets/svg/forest/bell-new.svg rename to assets/svg/themed/forest/bell-new.svg diff --git a/assets/svg/forest/bg.svg b/assets/svg/themed/forest/bg.svg similarity index 100% rename from assets/svg/forest/bg.svg rename to assets/svg/themed/forest/bg.svg diff --git a/assets/images/forest/bitcoin.svg b/assets/svg/themed/forest/bitcoin.svg similarity index 100% rename from assets/images/forest/bitcoin.svg rename to assets/svg/themed/forest/bitcoin.svg diff --git a/assets/images/forest/bitcoincash.svg b/assets/svg/themed/forest/bitcoincash.svg similarity index 100% rename from assets/images/forest/bitcoincash.svg rename to assets/svg/themed/forest/bitcoincash.svg diff --git a/assets/svg/forest/buy-coins-icon.svg b/assets/svg/themed/forest/buy-coins-icon.svg similarity index 100% rename from assets/svg/forest/buy-coins-icon.svg rename to assets/svg/themed/forest/buy-coins-icon.svg diff --git a/assets/images/forest/doge.svg b/assets/svg/themed/forest/doge.svg similarity index 100% rename from assets/images/forest/doge.svg rename to assets/svg/themed/forest/doge.svg diff --git a/assets/images/forest/epic-cash.svg b/assets/svg/themed/forest/epic-cash.svg similarity index 100% rename from assets/images/forest/epic-cash.svg rename to assets/svg/themed/forest/epic-cash.svg diff --git a/assets/images/forest/ethereum.svg b/assets/svg/themed/forest/ethereum.svg similarity index 100% rename from assets/images/forest/ethereum.svg rename to assets/svg/themed/forest/ethereum.svg diff --git a/assets/svg/forest/exchange-2.svg b/assets/svg/themed/forest/exchange-2.svg similarity index 100% rename from assets/svg/forest/exchange-2.svg rename to assets/svg/themed/forest/exchange-2.svg diff --git a/assets/images/forest/firo.svg b/assets/svg/themed/forest/firo.svg similarity index 100% rename from assets/images/forest/firo.svg rename to assets/svg/themed/forest/firo.svg diff --git a/assets/images/forest/litecoin.svg b/assets/svg/themed/forest/litecoin.svg similarity index 100% rename from assets/images/forest/litecoin.svg rename to assets/svg/themed/forest/litecoin.svg diff --git a/assets/images/forest/monero.svg b/assets/svg/themed/forest/monero.svg similarity index 100% rename from assets/images/forest/monero.svg rename to assets/svg/themed/forest/monero.svg diff --git a/assets/images/forest/namecoin.svg b/assets/svg/themed/forest/namecoin.svg similarity index 100% rename from assets/images/forest/namecoin.svg rename to assets/svg/themed/forest/namecoin.svg diff --git a/assets/images/forest/particl.svg b/assets/svg/themed/forest/particl.svg similarity index 100% rename from assets/images/forest/particl.svg rename to assets/svg/themed/forest/particl.svg diff --git a/assets/svg/forest/persona-easy-1.svg b/assets/svg/themed/forest/persona-easy-1.svg similarity index 100% rename from assets/svg/forest/persona-easy-1.svg rename to assets/svg/themed/forest/persona-easy-1.svg diff --git a/assets/svg/forest/persona-incognito-1.svg b/assets/svg/themed/forest/persona-incognito-1.svg similarity index 100% rename from assets/svg/forest/persona-incognito-1.svg rename to assets/svg/themed/forest/persona-incognito-1.svg diff --git a/assets/svg/forest/stack-icon1.svg b/assets/svg/themed/forest/stack-icon1.svg similarity index 100% rename from assets/svg/forest/stack-icon1.svg rename to assets/svg/themed/forest/stack-icon1.svg diff --git a/assets/images/forest/stack.svg b/assets/svg/themed/forest/stack.svg similarity index 100% rename from assets/images/forest/stack.svg rename to assets/svg/themed/forest/stack.svg diff --git a/assets/svg/forest/tx-exchange-icon-failed.svg b/assets/svg/themed/forest/tx-exchange-icon-failed.svg similarity index 100% rename from assets/svg/forest/tx-exchange-icon-failed.svg rename to assets/svg/themed/forest/tx-exchange-icon-failed.svg diff --git a/assets/svg/forest/tx-exchange-icon-pending.svg b/assets/svg/themed/forest/tx-exchange-icon-pending.svg similarity index 100% rename from assets/svg/forest/tx-exchange-icon-pending.svg rename to assets/svg/themed/forest/tx-exchange-icon-pending.svg diff --git a/assets/svg/forest/tx-exchange-icon.svg b/assets/svg/themed/forest/tx-exchange-icon.svg similarity index 100% rename from assets/svg/forest/tx-exchange-icon.svg rename to assets/svg/themed/forest/tx-exchange-icon.svg diff --git a/assets/svg/forest/tx-icon-receive-failed.svg b/assets/svg/themed/forest/tx-icon-receive-failed.svg similarity index 100% rename from assets/svg/forest/tx-icon-receive-failed.svg rename to assets/svg/themed/forest/tx-icon-receive-failed.svg diff --git a/assets/svg/forest/tx-icon-receive-pending.svg b/assets/svg/themed/forest/tx-icon-receive-pending.svg similarity index 100% rename from assets/svg/forest/tx-icon-receive-pending.svg rename to assets/svg/themed/forest/tx-icon-receive-pending.svg diff --git a/assets/svg/forest/tx-icon-receive.svg b/assets/svg/themed/forest/tx-icon-receive.svg similarity index 100% rename from assets/svg/forest/tx-icon-receive.svg rename to assets/svg/themed/forest/tx-icon-receive.svg diff --git a/assets/svg/forest/tx-icon-send-failed.svg b/assets/svg/themed/forest/tx-icon-send-failed.svg similarity index 100% rename from assets/svg/forest/tx-icon-send-failed.svg rename to assets/svg/themed/forest/tx-icon-send-failed.svg diff --git a/assets/svg/forest/tx-icon-send-pending.svg b/assets/svg/themed/forest/tx-icon-send-pending.svg similarity index 100% rename from assets/svg/forest/tx-icon-send-pending.svg rename to assets/svg/themed/forest/tx-icon-send-pending.svg diff --git a/assets/svg/forest/tx-icon-send.svg b/assets/svg/themed/forest/tx-icon-send.svg similarity index 100% rename from assets/svg/forest/tx-icon-send.svg rename to assets/svg/themed/forest/tx-icon-send.svg diff --git a/assets/images/forest/wownero.svg b/assets/svg/themed/forest/wownero.svg similarity index 100% rename from assets/images/forest/wownero.svg rename to assets/svg/themed/forest/wownero.svg diff --git a/assets/svg/fruitSorbet/bell-new.svg b/assets/svg/themed/fruitSorbet/bell-new.svg similarity index 100% rename from assets/svg/fruitSorbet/bell-new.svg rename to assets/svg/themed/fruitSorbet/bell-new.svg diff --git a/assets/svg/fruitSorbet/bg.svg b/assets/svg/themed/fruitSorbet/bg.svg similarity index 100% rename from assets/svg/fruitSorbet/bg.svg rename to assets/svg/themed/fruitSorbet/bg.svg diff --git a/assets/images/fruitSorbet/bitcoin.svg b/assets/svg/themed/fruitSorbet/bitcoin.svg similarity index 100% rename from assets/images/fruitSorbet/bitcoin.svg rename to assets/svg/themed/fruitSorbet/bitcoin.svg diff --git a/assets/images/fruitSorbet/bitcoincash.svg b/assets/svg/themed/fruitSorbet/bitcoincash.svg similarity index 100% rename from assets/images/fruitSorbet/bitcoincash.svg rename to assets/svg/themed/fruitSorbet/bitcoincash.svg diff --git a/assets/svg/fruitSorbet/buy-coins-icon.svg b/assets/svg/themed/fruitSorbet/buy-coins-icon.svg similarity index 100% rename from assets/svg/fruitSorbet/buy-coins-icon.svg rename to assets/svg/themed/fruitSorbet/buy-coins-icon.svg diff --git a/assets/images/fruitSorbet/doge.svg b/assets/svg/themed/fruitSorbet/doge.svg similarity index 100% rename from assets/images/fruitSorbet/doge.svg rename to assets/svg/themed/fruitSorbet/doge.svg diff --git a/assets/images/fruitSorbet/epic-cash.svg b/assets/svg/themed/fruitSorbet/epic-cash.svg similarity index 100% rename from assets/images/fruitSorbet/epic-cash.svg rename to assets/svg/themed/fruitSorbet/epic-cash.svg diff --git a/assets/svg/fruitSorbet/exchange-2.svg b/assets/svg/themed/fruitSorbet/exchange-2.svg similarity index 100% rename from assets/svg/fruitSorbet/exchange-2.svg rename to assets/svg/themed/fruitSorbet/exchange-2.svg diff --git a/assets/images/fruitSorbet/firo.svg b/assets/svg/themed/fruitSorbet/firo.svg similarity index 100% rename from assets/images/fruitSorbet/firo.svg rename to assets/svg/themed/fruitSorbet/firo.svg diff --git a/assets/images/fruitSorbet/litecoin.svg b/assets/svg/themed/fruitSorbet/litecoin.svg similarity index 100% rename from assets/images/fruitSorbet/litecoin.svg rename to assets/svg/themed/fruitSorbet/litecoin.svg diff --git a/assets/images/fruitSorbet/monero.svg b/assets/svg/themed/fruitSorbet/monero.svg similarity index 100% rename from assets/images/fruitSorbet/monero.svg rename to assets/svg/themed/fruitSorbet/monero.svg diff --git a/assets/images/fruitSorbet/namecoin.svg b/assets/svg/themed/fruitSorbet/namecoin.svg similarity index 100% rename from assets/images/fruitSorbet/namecoin.svg rename to assets/svg/themed/fruitSorbet/namecoin.svg diff --git a/assets/images/fruitSorbet/particl.svg b/assets/svg/themed/fruitSorbet/particl.svg similarity index 100% rename from assets/images/fruitSorbet/particl.svg rename to assets/svg/themed/fruitSorbet/particl.svg diff --git a/assets/svg/themed/fruitSorbet/persona-easy-1.svg b/assets/svg/themed/fruitSorbet/persona-easy-1.svg new file mode 100644 index 000000000..041c775fb --- /dev/null +++ b/assets/svg/themed/fruitSorbet/persona-easy-1.svg @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/themed/fruitSorbet/persona-incognito-1.svg b/assets/svg/themed/fruitSorbet/persona-incognito-1.svg new file mode 100644 index 000000000..6602556f9 --- /dev/null +++ b/assets/svg/themed/fruitSorbet/persona-incognito-1.svg @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/fruitSorbet/stack-icon1.svg b/assets/svg/themed/fruitSorbet/stack-icon1.svg similarity index 100% rename from assets/svg/fruitSorbet/stack-icon1.svg rename to assets/svg/themed/fruitSorbet/stack-icon1.svg diff --git a/assets/images/fruitSorbet/stack.svg b/assets/svg/themed/fruitSorbet/stack.svg similarity index 100% rename from assets/images/fruitSorbet/stack.svg rename to assets/svg/themed/fruitSorbet/stack.svg diff --git a/assets/svg/fruitSorbet/tx-exchange-icon-failed.svg b/assets/svg/themed/fruitSorbet/tx-exchange-icon-failed.svg similarity index 100% rename from assets/svg/fruitSorbet/tx-exchange-icon-failed.svg rename to assets/svg/themed/fruitSorbet/tx-exchange-icon-failed.svg diff --git a/assets/svg/fruitSorbet/tx-exchange-icon-pending.svg b/assets/svg/themed/fruitSorbet/tx-exchange-icon-pending.svg similarity index 100% rename from assets/svg/fruitSorbet/tx-exchange-icon-pending.svg rename to assets/svg/themed/fruitSorbet/tx-exchange-icon-pending.svg diff --git a/assets/svg/fruitSorbet/tx-exchange-icon.svg b/assets/svg/themed/fruitSorbet/tx-exchange-icon.svg similarity index 100% rename from assets/svg/fruitSorbet/tx-exchange-icon.svg rename to assets/svg/themed/fruitSorbet/tx-exchange-icon.svg diff --git a/assets/svg/fruitSorbet/tx-icon-receive-failed.svg b/assets/svg/themed/fruitSorbet/tx-icon-receive-failed.svg similarity index 100% rename from assets/svg/fruitSorbet/tx-icon-receive-failed.svg rename to assets/svg/themed/fruitSorbet/tx-icon-receive-failed.svg diff --git a/assets/svg/fruitSorbet/tx-icon-receive-pending.svg b/assets/svg/themed/fruitSorbet/tx-icon-receive-pending.svg similarity index 100% rename from assets/svg/fruitSorbet/tx-icon-receive-pending.svg rename to assets/svg/themed/fruitSorbet/tx-icon-receive-pending.svg diff --git a/assets/svg/fruitSorbet/tx-icon-receive.svg b/assets/svg/themed/fruitSorbet/tx-icon-receive.svg similarity index 100% rename from assets/svg/fruitSorbet/tx-icon-receive.svg rename to assets/svg/themed/fruitSorbet/tx-icon-receive.svg diff --git a/assets/svg/fruitSorbet/tx-icon-send-failed.svg b/assets/svg/themed/fruitSorbet/tx-icon-send-failed.svg similarity index 100% rename from assets/svg/fruitSorbet/tx-icon-send-failed.svg rename to assets/svg/themed/fruitSorbet/tx-icon-send-failed.svg diff --git a/assets/svg/fruitSorbet/tx-icon-send-pending.svg b/assets/svg/themed/fruitSorbet/tx-icon-send-pending.svg similarity index 100% rename from assets/svg/fruitSorbet/tx-icon-send-pending.svg rename to assets/svg/themed/fruitSorbet/tx-icon-send-pending.svg diff --git a/assets/svg/fruitSorbet/tx-icon-send.svg b/assets/svg/themed/fruitSorbet/tx-icon-send.svg similarity index 100% rename from assets/svg/fruitSorbet/tx-icon-send.svg rename to assets/svg/themed/fruitSorbet/tx-icon-send.svg diff --git a/assets/images/fruitSorbet/wownero.svg b/assets/svg/themed/fruitSorbet/wownero.svg similarity index 100% rename from assets/images/fruitSorbet/wownero.svg rename to assets/svg/themed/fruitSorbet/wownero.svg diff --git a/assets/svg/light/bell-new.svg b/assets/svg/themed/light/bell-new.svg similarity index 100% rename from assets/svg/light/bell-new.svg rename to assets/svg/themed/light/bell-new.svg diff --git a/assets/images/light/bitcoin.svg b/assets/svg/themed/light/bitcoin.svg similarity index 100% rename from assets/images/light/bitcoin.svg rename to assets/svg/themed/light/bitcoin.svg diff --git a/assets/images/light/bitcoincash.svg b/assets/svg/themed/light/bitcoincash.svg similarity index 100% rename from assets/images/light/bitcoincash.svg rename to assets/svg/themed/light/bitcoincash.svg diff --git a/assets/svg/light/buy-coins-icon.svg b/assets/svg/themed/light/buy-coins-icon.svg similarity index 100% rename from assets/svg/light/buy-coins-icon.svg rename to assets/svg/themed/light/buy-coins-icon.svg diff --git a/assets/images/light/doge.svg b/assets/svg/themed/light/doge.svg similarity index 100% rename from assets/images/light/doge.svg rename to assets/svg/themed/light/doge.svg diff --git a/assets/images/light/epic-cash.svg b/assets/svg/themed/light/epic-cash.svg similarity index 100% rename from assets/images/light/epic-cash.svg rename to assets/svg/themed/light/epic-cash.svg diff --git a/assets/svg/light/exchange-2.svg b/assets/svg/themed/light/exchange-2.svg similarity index 100% rename from assets/svg/light/exchange-2.svg rename to assets/svg/themed/light/exchange-2.svg diff --git a/assets/images/light/firo.svg b/assets/svg/themed/light/firo.svg similarity index 100% rename from assets/images/light/firo.svg rename to assets/svg/themed/light/firo.svg diff --git a/assets/images/light/litecoin.svg b/assets/svg/themed/light/litecoin.svg similarity index 100% rename from assets/images/light/litecoin.svg rename to assets/svg/themed/light/litecoin.svg diff --git a/assets/images/light/monero.svg b/assets/svg/themed/light/monero.svg similarity index 100% rename from assets/images/light/monero.svg rename to assets/svg/themed/light/monero.svg diff --git a/assets/images/light/namecoin.svg b/assets/svg/themed/light/namecoin.svg similarity index 100% rename from assets/images/light/namecoin.svg rename to assets/svg/themed/light/namecoin.svg diff --git a/assets/images/light/particl.svg b/assets/svg/themed/light/particl.svg similarity index 100% rename from assets/images/light/particl.svg rename to assets/svg/themed/light/particl.svg diff --git a/assets/svg/fruitSorbet/persona-easy-1.svg b/assets/svg/themed/light/persona-easy-1.svg similarity index 100% rename from assets/svg/fruitSorbet/persona-easy-1.svg rename to assets/svg/themed/light/persona-easy-1.svg diff --git a/assets/svg/fruitSorbet/persona-incognito-1.svg b/assets/svg/themed/light/persona-incognito-1.svg similarity index 100% rename from assets/svg/fruitSorbet/persona-incognito-1.svg rename to assets/svg/themed/light/persona-incognito-1.svg diff --git a/assets/svg/light/stack-icon1.svg b/assets/svg/themed/light/stack-icon1.svg similarity index 100% rename from assets/svg/light/stack-icon1.svg rename to assets/svg/themed/light/stack-icon1.svg diff --git a/assets/images/light/stack.svg b/assets/svg/themed/light/stack.svg similarity index 100% rename from assets/images/light/stack.svg rename to assets/svg/themed/light/stack.svg index 22dce4736..94929475d 100644 --- a/assets/images/light/stack.svg +++ b/assets/svg/themed/light/stack.svg @@ -1,4 +1,10 @@ + + + + + + @@ -106,10 +112,4 @@ - - - - - - diff --git a/assets/svg/light/tx-exchange-icon-failed.svg b/assets/svg/themed/light/tx-exchange-icon-failed.svg similarity index 100% rename from assets/svg/light/tx-exchange-icon-failed.svg rename to assets/svg/themed/light/tx-exchange-icon-failed.svg diff --git a/assets/svg/light/tx-exchange-icon-pending.svg b/assets/svg/themed/light/tx-exchange-icon-pending.svg similarity index 100% rename from assets/svg/light/tx-exchange-icon-pending.svg rename to assets/svg/themed/light/tx-exchange-icon-pending.svg diff --git a/assets/svg/light/tx-exchange-icon.svg b/assets/svg/themed/light/tx-exchange-icon.svg similarity index 100% rename from assets/svg/light/tx-exchange-icon.svg rename to assets/svg/themed/light/tx-exchange-icon.svg diff --git a/assets/svg/light/tx-icon-receive-failed.svg b/assets/svg/themed/light/tx-icon-receive-failed.svg similarity index 100% rename from assets/svg/light/tx-icon-receive-failed.svg rename to assets/svg/themed/light/tx-icon-receive-failed.svg diff --git a/assets/svg/light/tx-icon-receive-pending.svg b/assets/svg/themed/light/tx-icon-receive-pending.svg similarity index 100% rename from assets/svg/light/tx-icon-receive-pending.svg rename to assets/svg/themed/light/tx-icon-receive-pending.svg diff --git a/assets/svg/light/tx-icon-receive.svg b/assets/svg/themed/light/tx-icon-receive.svg similarity index 100% rename from assets/svg/light/tx-icon-receive.svg rename to assets/svg/themed/light/tx-icon-receive.svg diff --git a/assets/svg/light/tx-icon-send-failed.svg b/assets/svg/themed/light/tx-icon-send-failed.svg similarity index 100% rename from assets/svg/light/tx-icon-send-failed.svg rename to assets/svg/themed/light/tx-icon-send-failed.svg diff --git a/assets/svg/light/tx-icon-send-pending.svg b/assets/svg/themed/light/tx-icon-send-pending.svg similarity index 100% rename from assets/svg/light/tx-icon-send-pending.svg rename to assets/svg/themed/light/tx-icon-send-pending.svg diff --git a/assets/svg/light/tx-icon-send.svg b/assets/svg/themed/light/tx-icon-send.svg similarity index 100% rename from assets/svg/light/tx-icon-send.svg rename to assets/svg/themed/light/tx-icon-send.svg diff --git a/assets/images/light/wownero.svg b/assets/svg/themed/light/wownero.svg similarity index 100% rename from assets/images/light/wownero.svg rename to assets/svg/themed/light/wownero.svg diff --git a/assets/svg/oceanBreeze/bell-new.svg b/assets/svg/themed/oceanBreeze/bell-new.svg similarity index 100% rename from assets/svg/oceanBreeze/bell-new.svg rename to assets/svg/themed/oceanBreeze/bell-new.svg diff --git a/assets/svg/oceanBreeze/bg.svg b/assets/svg/themed/oceanBreeze/bg.svg similarity index 100% rename from assets/svg/oceanBreeze/bg.svg rename to assets/svg/themed/oceanBreeze/bg.svg diff --git a/assets/images/oceanBreeze/bitcoin.svg b/assets/svg/themed/oceanBreeze/bitcoin.svg similarity index 100% rename from assets/images/oceanBreeze/bitcoin.svg rename to assets/svg/themed/oceanBreeze/bitcoin.svg diff --git a/assets/images/oceanBreeze/bitcoincash.svg b/assets/svg/themed/oceanBreeze/bitcoincash.svg similarity index 100% rename from assets/images/oceanBreeze/bitcoincash.svg rename to assets/svg/themed/oceanBreeze/bitcoincash.svg diff --git a/assets/svg/oceanBreeze/buy-coins-icon.svg b/assets/svg/themed/oceanBreeze/buy-coins-icon.svg similarity index 100% rename from assets/svg/oceanBreeze/buy-coins-icon.svg rename to assets/svg/themed/oceanBreeze/buy-coins-icon.svg diff --git a/assets/images/oceanBreeze/doge.svg b/assets/svg/themed/oceanBreeze/doge.svg similarity index 100% rename from assets/images/oceanBreeze/doge.svg rename to assets/svg/themed/oceanBreeze/doge.svg diff --git a/assets/images/oceanBreeze/epic-cash.svg b/assets/svg/themed/oceanBreeze/epic-cash.svg similarity index 100% rename from assets/images/oceanBreeze/epic-cash.svg rename to assets/svg/themed/oceanBreeze/epic-cash.svg diff --git a/assets/svg/oceanBreeze/exchange-2.svg b/assets/svg/themed/oceanBreeze/exchange-2.svg similarity index 100% rename from assets/svg/oceanBreeze/exchange-2.svg rename to assets/svg/themed/oceanBreeze/exchange-2.svg diff --git a/assets/images/oceanBreeze/firo.svg b/assets/svg/themed/oceanBreeze/firo.svg similarity index 100% rename from assets/images/oceanBreeze/firo.svg rename to assets/svg/themed/oceanBreeze/firo.svg diff --git a/assets/images/oceanBreeze/litecoin.svg b/assets/svg/themed/oceanBreeze/litecoin.svg similarity index 100% rename from assets/images/oceanBreeze/litecoin.svg rename to assets/svg/themed/oceanBreeze/litecoin.svg diff --git a/assets/images/oceanBreeze/monero.svg b/assets/svg/themed/oceanBreeze/monero.svg similarity index 100% rename from assets/images/oceanBreeze/monero.svg rename to assets/svg/themed/oceanBreeze/monero.svg diff --git a/assets/images/oceanBreeze/namecoin.svg b/assets/svg/themed/oceanBreeze/namecoin.svg similarity index 100% rename from assets/images/oceanBreeze/namecoin.svg rename to assets/svg/themed/oceanBreeze/namecoin.svg diff --git a/assets/images/oceanBreeze/particl.svg b/assets/svg/themed/oceanBreeze/particl.svg similarity index 100% rename from assets/images/oceanBreeze/particl.svg rename to assets/svg/themed/oceanBreeze/particl.svg diff --git a/assets/svg/themed/oceanBreeze/persona-easy-1.svg b/assets/svg/themed/oceanBreeze/persona-easy-1.svg new file mode 100644 index 000000000..760b6a852 --- /dev/null +++ b/assets/svg/themed/oceanBreeze/persona-easy-1.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/themed/oceanBreeze/persona-incognito-1.svg b/assets/svg/themed/oceanBreeze/persona-incognito-1.svg new file mode 100644 index 000000000..d1160b221 --- /dev/null +++ b/assets/svg/themed/oceanBreeze/persona-incognito-1.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/oceanBreeze/stack-icon1.svg b/assets/svg/themed/oceanBreeze/stack-icon1.svg similarity index 100% rename from assets/svg/oceanBreeze/stack-icon1.svg rename to assets/svg/themed/oceanBreeze/stack-icon1.svg diff --git a/assets/images/oceanBreeze/stack.svg b/assets/svg/themed/oceanBreeze/stack.svg similarity index 100% rename from assets/images/oceanBreeze/stack.svg rename to assets/svg/themed/oceanBreeze/stack.svg diff --git a/assets/svg/oceanBreeze/tx-exchange-icon-failed.svg b/assets/svg/themed/oceanBreeze/tx-exchange-icon-failed.svg similarity index 100% rename from assets/svg/oceanBreeze/tx-exchange-icon-failed.svg rename to assets/svg/themed/oceanBreeze/tx-exchange-icon-failed.svg diff --git a/assets/svg/oceanBreeze/tx-exchange-icon-pending.svg b/assets/svg/themed/oceanBreeze/tx-exchange-icon-pending.svg similarity index 100% rename from assets/svg/oceanBreeze/tx-exchange-icon-pending.svg rename to assets/svg/themed/oceanBreeze/tx-exchange-icon-pending.svg diff --git a/assets/svg/oceanBreeze/tx-exchange-icon.svg b/assets/svg/themed/oceanBreeze/tx-exchange-icon.svg similarity index 100% rename from assets/svg/oceanBreeze/tx-exchange-icon.svg rename to assets/svg/themed/oceanBreeze/tx-exchange-icon.svg diff --git a/assets/svg/oceanBreeze/tx-icon-receive-failed.svg b/assets/svg/themed/oceanBreeze/tx-icon-receive-failed.svg similarity index 100% rename from assets/svg/oceanBreeze/tx-icon-receive-failed.svg rename to assets/svg/themed/oceanBreeze/tx-icon-receive-failed.svg diff --git a/assets/svg/oceanBreeze/tx-icon-receive-pending.svg b/assets/svg/themed/oceanBreeze/tx-icon-receive-pending.svg similarity index 100% rename from assets/svg/oceanBreeze/tx-icon-receive-pending.svg rename to assets/svg/themed/oceanBreeze/tx-icon-receive-pending.svg diff --git a/assets/svg/oceanBreeze/tx-icon-receive.svg b/assets/svg/themed/oceanBreeze/tx-icon-receive.svg similarity index 100% rename from assets/svg/oceanBreeze/tx-icon-receive.svg rename to assets/svg/themed/oceanBreeze/tx-icon-receive.svg diff --git a/assets/svg/oceanBreeze/tx-icon-send-failed.svg b/assets/svg/themed/oceanBreeze/tx-icon-send-failed.svg similarity index 100% rename from assets/svg/oceanBreeze/tx-icon-send-failed.svg rename to assets/svg/themed/oceanBreeze/tx-icon-send-failed.svg diff --git a/assets/svg/oceanBreeze/tx-icon-send-pending.svg b/assets/svg/themed/oceanBreeze/tx-icon-send-pending.svg similarity index 100% rename from assets/svg/oceanBreeze/tx-icon-send-pending.svg rename to assets/svg/themed/oceanBreeze/tx-icon-send-pending.svg diff --git a/assets/svg/oceanBreeze/tx-icon-send.svg b/assets/svg/themed/oceanBreeze/tx-icon-send.svg similarity index 100% rename from assets/svg/oceanBreeze/tx-icon-send.svg rename to assets/svg/themed/oceanBreeze/tx-icon-send.svg diff --git a/assets/images/oceanBreeze/wownero.svg b/assets/svg/themed/oceanBreeze/wownero.svg similarity index 100% rename from assets/images/oceanBreeze/wownero.svg rename to assets/svg/themed/oceanBreeze/wownero.svg diff --git a/assets/svg/oledBlack/bell-new.svg b/assets/svg/themed/oledBlack/bell-new.svg similarity index 100% rename from assets/svg/oledBlack/bell-new.svg rename to assets/svg/themed/oledBlack/bell-new.svg diff --git a/assets/images/oledBlack/bitcoin.svg b/assets/svg/themed/oledBlack/bitcoin.svg similarity index 100% rename from assets/images/oledBlack/bitcoin.svg rename to assets/svg/themed/oledBlack/bitcoin.svg diff --git a/assets/images/oledBlack/bitcoincash.svg b/assets/svg/themed/oledBlack/bitcoincash.svg similarity index 100% rename from assets/images/oledBlack/bitcoincash.svg rename to assets/svg/themed/oledBlack/bitcoincash.svg diff --git a/assets/svg/oledBlack/buy-coins-icon.svg b/assets/svg/themed/oledBlack/buy-coins-icon.svg similarity index 100% rename from assets/svg/oledBlack/buy-coins-icon.svg rename to assets/svg/themed/oledBlack/buy-coins-icon.svg diff --git a/assets/images/oledBlack/doge.svg b/assets/svg/themed/oledBlack/doge.svg similarity index 100% rename from assets/images/oledBlack/doge.svg rename to assets/svg/themed/oledBlack/doge.svg diff --git a/assets/images/oledBlack/epic-cash.svg b/assets/svg/themed/oledBlack/epic-cash.svg similarity index 100% rename from assets/images/oledBlack/epic-cash.svg rename to assets/svg/themed/oledBlack/epic-cash.svg diff --git a/assets/svg/oledBlack/exchange-2.svg b/assets/svg/themed/oledBlack/exchange-2.svg similarity index 100% rename from assets/svg/oledBlack/exchange-2.svg rename to assets/svg/themed/oledBlack/exchange-2.svg diff --git a/assets/images/oledBlack/firo.svg b/assets/svg/themed/oledBlack/firo.svg similarity index 100% rename from assets/images/oledBlack/firo.svg rename to assets/svg/themed/oledBlack/firo.svg diff --git a/assets/images/oledBlack/litecoin.svg b/assets/svg/themed/oledBlack/litecoin.svg similarity index 100% rename from assets/images/oledBlack/litecoin.svg rename to assets/svg/themed/oledBlack/litecoin.svg diff --git a/assets/images/oledBlack/monero.svg b/assets/svg/themed/oledBlack/monero.svg similarity index 100% rename from assets/images/oledBlack/monero.svg rename to assets/svg/themed/oledBlack/monero.svg diff --git a/assets/images/oledBlack/namecoin.svg b/assets/svg/themed/oledBlack/namecoin.svg similarity index 100% rename from assets/images/oledBlack/namecoin.svg rename to assets/svg/themed/oledBlack/namecoin.svg diff --git a/assets/images/oledBlack/particl.svg b/assets/svg/themed/oledBlack/particl.svg similarity index 100% rename from assets/images/oledBlack/particl.svg rename to assets/svg/themed/oledBlack/particl.svg diff --git a/assets/svg/light/persona-easy-1.svg b/assets/svg/themed/oledBlack/persona-easy-1.svg similarity index 100% rename from assets/svg/light/persona-easy-1.svg rename to assets/svg/themed/oledBlack/persona-easy-1.svg diff --git a/assets/svg/light/persona-incognito-1.svg b/assets/svg/themed/oledBlack/persona-incognito-1.svg similarity index 100% rename from assets/svg/light/persona-incognito-1.svg rename to assets/svg/themed/oledBlack/persona-incognito-1.svg diff --git a/assets/svg/oledBlack/stack-icon1.svg b/assets/svg/themed/oledBlack/stack-icon1.svg similarity index 100% rename from assets/svg/oledBlack/stack-icon1.svg rename to assets/svg/themed/oledBlack/stack-icon1.svg diff --git a/assets/images/oledBlack/stack.svg b/assets/svg/themed/oledBlack/stack.svg similarity index 100% rename from assets/images/oledBlack/stack.svg rename to assets/svg/themed/oledBlack/stack.svg index 22dce4736..94929475d 100644 --- a/assets/images/oledBlack/stack.svg +++ b/assets/svg/themed/oledBlack/stack.svg @@ -1,4 +1,10 @@ + + + + + + @@ -106,10 +112,4 @@ - - - - - - diff --git a/assets/svg/oledBlack/tx-exchange-icon-failed.svg b/assets/svg/themed/oledBlack/tx-exchange-icon-failed.svg similarity index 100% rename from assets/svg/oledBlack/tx-exchange-icon-failed.svg rename to assets/svg/themed/oledBlack/tx-exchange-icon-failed.svg diff --git a/assets/svg/oledBlack/tx-exchange-icon-pending.svg b/assets/svg/themed/oledBlack/tx-exchange-icon-pending.svg similarity index 100% rename from assets/svg/oledBlack/tx-exchange-icon-pending.svg rename to assets/svg/themed/oledBlack/tx-exchange-icon-pending.svg diff --git a/assets/svg/oledBlack/tx-exchange-icon.svg b/assets/svg/themed/oledBlack/tx-exchange-icon.svg similarity index 100% rename from assets/svg/oledBlack/tx-exchange-icon.svg rename to assets/svg/themed/oledBlack/tx-exchange-icon.svg diff --git a/assets/svg/oledBlack/tx-icon-receive-failed.svg b/assets/svg/themed/oledBlack/tx-icon-receive-failed.svg similarity index 100% rename from assets/svg/oledBlack/tx-icon-receive-failed.svg rename to assets/svg/themed/oledBlack/tx-icon-receive-failed.svg diff --git a/assets/svg/oledBlack/tx-icon-receive-pending.svg b/assets/svg/themed/oledBlack/tx-icon-receive-pending.svg similarity index 100% rename from assets/svg/oledBlack/tx-icon-receive-pending.svg rename to assets/svg/themed/oledBlack/tx-icon-receive-pending.svg diff --git a/assets/svg/oledBlack/tx-icon-receive.svg b/assets/svg/themed/oledBlack/tx-icon-receive.svg similarity index 100% rename from assets/svg/oledBlack/tx-icon-receive.svg rename to assets/svg/themed/oledBlack/tx-icon-receive.svg diff --git a/assets/svg/oledBlack/tx-icon-send-failed.svg b/assets/svg/themed/oledBlack/tx-icon-send-failed.svg similarity index 100% rename from assets/svg/oledBlack/tx-icon-send-failed.svg rename to assets/svg/themed/oledBlack/tx-icon-send-failed.svg diff --git a/assets/svg/oledBlack/tx-icon-send-pending.svg b/assets/svg/themed/oledBlack/tx-icon-send-pending.svg similarity index 100% rename from assets/svg/oledBlack/tx-icon-send-pending.svg rename to assets/svg/themed/oledBlack/tx-icon-send-pending.svg diff --git a/assets/svg/oledBlack/tx-icon-send.svg b/assets/svg/themed/oledBlack/tx-icon-send.svg similarity index 100% rename from assets/svg/oledBlack/tx-icon-send.svg rename to assets/svg/themed/oledBlack/tx-icon-send.svg diff --git a/assets/images/oledBlack/wownero.svg b/assets/svg/themed/oledBlack/wownero.svg similarity index 100% rename from assets/images/oledBlack/wownero.svg rename to assets/svg/themed/oledBlack/wownero.svg diff --git a/assets/svg/unclaimed.svg b/assets/svg/unclaimed.svg new file mode 100644 index 000000000..a6ff2213d --- /dev/null +++ b/assets/svg/unclaimed.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/db/main_db.dart b/lib/db/main_db.dart index 1cd78f951..1fb672d34 100644 --- a/lib/db/main_db.dart +++ b/lib/db/main_db.dart @@ -1,9 +1,15 @@ +import 'package:decimal/decimal.dart'; +import 'package:flutter_native_splash/cli_commands.dart'; import 'package:isar/isar.dart'; import 'package:stackwallet/exceptions/main_db/main_db_exception.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/stack_file_system.dart'; import 'package:tuple/tuple.dart'; +part 'queries/queries.dart'; + class MainDB { MainDB._(); static MainDB? _instance; diff --git a/lib/db/queries/queries.dart b/lib/db/queries/queries.dart new file mode 100644 index 000000000..2995de06d --- /dev/null +++ b/lib/db/queries/queries.dart @@ -0,0 +1,182 @@ +part of 'package:stackwallet/db/main_db.dart'; + +enum CCFilter { + all, + available, + frozen; + + @override + String toString() { + if (this == all) { + return "Show $name outputs"; + } + + return "${name.capitalize()} outputs"; + } +} + +enum CCSortDescriptor { + age, + address, + value; + + @override + String toString() { + return name.capitalize(); + } +} + +extension MainDBQueries on MainDB { + List queryUTXOsSync({ + required String walletId, + required CCFilter filter, + required CCSortDescriptor sort, + required String searchTerm, + required Coin coin, + }) { + var preSort = getUTXOs(walletId).filter().group((q) { + final qq = q.group( + (q) => q.usedIsNull().or().usedEqualTo(false), + ); + switch (filter) { + case CCFilter.frozen: + return qq.and().isBlockedEqualTo(true); + case CCFilter.available: + return qq.and().isBlockedEqualTo(false); + case CCFilter.all: + return qq; + } + }); + + if (searchTerm.isNotEmpty) { + preSort = preSort.and().group( + (q) { + var qq = q.addressContains(searchTerm, caseSensitive: false); + + qq = qq.or().nameContains(searchTerm, caseSensitive: false); + qq = qq.or().group( + (q) => q + .isBlockedEqualTo(true) + .and() + .blockedReasonContains(searchTerm, caseSensitive: false), + ); + + qq = qq.or().txidContains(searchTerm, caseSensitive: false); + qq = qq.or().blockHashContains(searchTerm, caseSensitive: false); + + final maybeDecimal = Decimal.tryParse(searchTerm); + if (maybeDecimal != null) { + qq = qq.or().valueEqualTo( + Format.decimalAmountToSatoshis( + maybeDecimal, + coin, + ), + ); + } + + final maybeInt = int.tryParse(searchTerm); + if (maybeInt != null) { + qq = qq.or().valueEqualTo(maybeInt); + } + + return qq; + }, + ); + } + + final List ids; + switch (sort) { + case CCSortDescriptor.age: + ids = preSort.sortByBlockHeight().idProperty().findAllSync(); + break; + case CCSortDescriptor.address: + ids = preSort.sortByAddress().idProperty().findAllSync(); + break; + case CCSortDescriptor.value: + ids = preSort.sortByValueDesc().idProperty().findAllSync(); + break; + } + return ids; + } + + Map> queryUTXOsGroupedByAddressSync({ + required String walletId, + required CCFilter filter, + required CCSortDescriptor sort, + required String searchTerm, + required Coin coin, + }) { + var preSort = getUTXOs(walletId).filter().group((q) { + final qq = q.group( + (q) => q.usedIsNull().or().usedEqualTo(false), + ); + switch (filter) { + case CCFilter.frozen: + return qq.and().isBlockedEqualTo(true); + case CCFilter.available: + return qq.and().isBlockedEqualTo(false); + case CCFilter.all: + return qq; + } + }); + + if (searchTerm.isNotEmpty) { + preSort = preSort.and().group( + (q) { + var qq = q.addressContains(searchTerm, caseSensitive: false); + + qq = qq.or().nameContains(searchTerm, caseSensitive: false); + qq = qq.or().group( + (q) => q + .isBlockedEqualTo(true) + .and() + .blockedReasonContains(searchTerm, caseSensitive: false), + ); + + qq = qq.or().txidContains(searchTerm, caseSensitive: false); + qq = qq.or().blockHashContains(searchTerm, caseSensitive: false); + + final maybeDecimal = Decimal.tryParse(searchTerm); + if (maybeDecimal != null) { + qq = qq.or().valueEqualTo( + Format.decimalAmountToSatoshis( + maybeDecimal, + coin, + ), + ); + } + + final maybeInt = int.tryParse(searchTerm); + if (maybeInt != null) { + qq = qq.or().valueEqualTo(maybeInt); + } + + return qq; + }, + ); + } + + final List utxos; + switch (sort) { + case CCSortDescriptor.age: + utxos = preSort.sortByBlockHeight().findAllSync(); + break; + case CCSortDescriptor.address: + utxos = preSort.sortByAddress().findAllSync(); + break; + case CCSortDescriptor.value: + utxos = preSort.sortByValueDesc().findAllSync(); + break; + } + + final Map> results = {}; + for (final utxo in utxos) { + if (results[utxo.address!] == null) { + results[utxo.address!] = []; + } + results[utxo.address!]!.add(utxo.id); + } + + return results; + } +} diff --git a/lib/main.dart b/lib/main.dart index 8612d2f7e..d34eb455f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:cw_core/node.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_libmonero/monero/monero.dart'; @@ -56,6 +57,7 @@ import 'package:stackwallet/utilities/enums/backup_frequency_type.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/stack_file_system.dart'; +import 'package:stackwallet/utilities/theme/chan_colors.dart'; import 'package:stackwallet/utilities/theme/color_theme.dart'; import 'package:stackwallet/utilities/theme/dark_colors.dart'; import 'package:stackwallet/utilities/theme/forest_colors.dart'; @@ -91,7 +93,7 @@ void main() async { setWindowMaxSize(Size.infinite); final screenHeight = screen?.frame.height; - if (screenHeight != null) { + if (screenHeight != null && !kDebugMode) { // starting to height be 3/4 screen height or 900, whichever is smaller final height = min(screenHeight * 0.75, 900); setWindowFrame( @@ -352,6 +354,9 @@ class _MaterialAppWithThemeState extends ConsumerState case "forest": colorTheme = ForestColors(); break; + case "chan": + colorTheme = ChanColors(); + break; case "light": default: colorTheme = LightColors(); @@ -524,7 +529,7 @@ class _MaterialAppWithThemeState extends ConsumerState theme: ThemeData( extensions: [colorScheme], highlightColor: colorScheme.highlight, - brightness: Brightness.light, + brightness: colorScheme.brightness, fontFamily: GoogleFonts.inter().fontFamily, unselectedWidgetColor: colorScheme.radioButtonBorderDisabled, // textTheme: GoogleFonts.interTextTheme().copyWith( diff --git a/lib/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart b/lib/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart index 7108b35be..85d5beb74 100644 --- a/lib/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart @@ -61,7 +61,10 @@ class CreateOrRestoreWalletView extends StatelessWidget { ), CoinImage( coin: coin, - isDesktop: isDesktop, + width: + isDesktop ? 324 : MediaQuery.of(context).size.width / 1.6, + height: + isDesktop ? null : MediaQuery.of(context).size.width / 1.6, ), const SizedBox( height: 32, @@ -99,7 +102,12 @@ class CreateOrRestoreWalletView extends StatelessWidget { children: [ CoinImage( coin: coin, - isDesktop: isDesktop, + width: isDesktop + ? 324 + : MediaQuery.of(context).size.width / 1.6, + height: isDesktop + ? null + : MediaQuery.of(context).size.width / 1.6, ), const Spacer( flex: 2, diff --git a/lib/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart b/lib/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart index 874580faa..fb282d9ca 100644 --- a/lib/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart +++ b/lib/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart @@ -3,22 +3,40 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/theme/color_theme.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; class CoinImage extends ConsumerWidget { const CoinImage({ Key? key, required this.coin, - required this.isDesktop, + this.width, + this.height, }) : super(key: key); final Coin coin; - final bool isDesktop; + final double? width; + final double? height; @override Widget build(BuildContext context, WidgetRef ref) { - return SvgPicture.asset( - Assets.svg.imageFor(coin: coin, context: context), - width: isDesktop ? 324 : MediaQuery.of(context).size.width / 1.6, - ); + if (Theme.of(context).extension()!.themeType == + ThemeType.chan) { + return SizedBox( + width: width, + height: height, + child: Image( + image: AssetImage( + Assets.gif.plain(coin), + ), + ), + ); + } else { + return SvgPicture.asset( + Assets.svg.imageFor(coin: coin, context: context), + width: width, + height: height, + ); + } } } diff --git a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart index e699db58e..6a3f28318 100644 --- a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart +++ b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart @@ -2,8 +2,8 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; +import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart'; import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart'; import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart'; @@ -166,9 +166,10 @@ class _NameYourWalletViewState extends ConsumerState { flex: 1, ), if (!isDesktop) - SvgPicture.asset( - Assets.svg.imageFor(coin: coin, context: context), + CoinImage( + coin: coin, height: 100, + width: 100, ), SizedBox( height: isDesktop ? 0 : 16, diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart index fcb932e56..a83fa5bd2 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_rounded_date_picker/flutter_rounded_date_picker.dart'; import 'package:flutter_svg/svg.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart'; import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/mobile_mnemonic_length_selector.dart'; import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/restore_from_date_picker.dart'; import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/restore_options_next_button.dart'; @@ -282,9 +283,10 @@ class _RestoreOptionsViewState extends ConsumerState { flex: isDesktop ? 10 : 1, ), if (!isDesktop) - SvgPicture.asset( - Assets.svg.imageFor(coin: coin, context: context), + CoinImage( + coin: coin, height: 100, + width: 100, ), SizedBox( height: isDesktop ? 0 : 16, diff --git a/lib/pages/coin_control/coin_control_view.dart b/lib/pages/coin_control/coin_control_view.dart index 5457a8c86..0eeff1089 100644 --- a/lib/pages/coin_control/coin_control_view.dart +++ b/lib/pages/coin_control/coin_control_view.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:isar/isar.dart'; import 'package:stackwallet/db/main_db.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; @@ -9,20 +10,27 @@ import 'package:stackwallet/pages/coin_control/utxo_card.dart'; import 'package:stackwallet/pages/coin_control/utxo_details_view.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/services/mixins/coin_control_interface.dart'; +import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/app_bar_field.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/custom_buttons/dropdown_button.dart'; import 'package:stackwallet/widgets/desktop/primary_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/expandable2.dart'; import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:stackwallet/widgets/toggle.dart'; import 'package:tuple/tuple.dart'; +import '../../widgets/animated_widgets/rotate_icon.dart'; +import '../../widgets/rounded_container.dart'; + enum CoinControlViewType { manage, use; @@ -49,8 +57,17 @@ class CoinControlView extends ConsumerStatefulWidget { } class _CoinControlViewState extends ConsumerState { + final searchController = TextEditingController(); + final searchFocus = FocusNode(); + + bool _isSearching = false; bool _showBlocked = false; + CCSortDescriptor _sort = CCSortDescriptor.age; + + Map>? _map; + List? _list; + final Set _selectedAvailable = {}; final Set _selectedBlocked = {}; @@ -67,9 +84,21 @@ class _CoinControlViewState extends ConsumerState { if (widget.selectedUTXOs != null) { _selectedAvailable.addAll(widget.selectedUTXOs!); } + searchController.addListener(() { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + setState(() {}); + }); + }); super.initState(); } + @override + void dispose() { + searchController.dispose(); + searchFocus.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); @@ -94,16 +123,29 @@ class _CoinControlViewState extends ConsumerState { ), ); - final ids = MainDB.instance - .getUTXOs(widget.walletId) - .filter() - .isBlockedEqualTo(_showBlocked) - .and() - .group( - (q) => q.usedIsNull().or().usedEqualTo(false), - ) - .idProperty() - .findAllSync(); + if (_sort == CCSortDescriptor.address && !_isSearching) { + _list = null; + _map = MainDB.instance.queryUTXOsGroupedByAddressSync( + walletId: widget.walletId, + filter: CCFilter.all, + sort: _sort, + searchTerm: "", + coin: coin, + ); + } else { + _map = null; + _list = MainDB.instance.queryUTXOsSync( + walletId: widget.walletId, + filter: _isSearching + ? CCFilter.all + : _showBlocked + ? CCFilter.frozen + : CCFilter.available, + sort: _sort, + searchTerm: _isSearching ? searchController.text : "", + coin: coin, + ); + } return WillPopScope( onWillPop: () async { @@ -117,36 +159,105 @@ class _CoinControlViewState extends ConsumerState { backgroundColor: Theme.of(context).extension()!.background, appBar: AppBar( - leading: widget.type == CoinControlViewType.use && - _selectedAvailable.isNotEmpty - ? AppBarIconButton( - icon: XIcon( - width: 24, - height: 24, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - ), - onPressed: () { - setState(() { - _selectedAvailable.clear(); - }); - }, + automaticallyImplyLeading: false, + leading: _isSearching + ? null + : widget.type == CoinControlViewType.use && + _selectedAvailable.isNotEmpty + ? AppBarIconButton( + icon: XIcon( + width: 24, + height: 24, + color: Theme.of(context) + .extension()! + .topNavIconPrimary, + ), + onPressed: () { + setState(() { + _selectedAvailable.clear(); + }); + }, + ) + : AppBarBackButton( + onPressed: () { + unawaited(_refreshBalance()); + Navigator.of(context).pop( + widget.type == CoinControlViewType.use + ? _selectedAvailable + : null); + }, + ), + title: _isSearching + ? AppBarSearchField( + controller: searchController, + focusNode: searchFocus, ) - : AppBarBackButton( - onPressed: () { - unawaited(_refreshBalance()); - Navigator.of(context).pop( - widget.type == CoinControlViewType.use - ? _selectedAvailable - : null); - }, + : Text( + "Coin control", + style: STextStyles.navBarTitle(context), ), - title: Text( - "Coin control", - style: STextStyles.navBarTitle(context), - ), titleSpacing: 0, + actions: _isSearching + ? [ + AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + size: 36, + icon: SvgPicture.asset( + Assets.svg.x, + width: 20, + height: 20, + color: Theme.of(context) + .extension()! + .topNavIconPrimary, + ), + onPressed: () { + // show search + setState(() { + _isSearching = false; + }); + }, + ), + ), + ] + : [ + AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + size: 36, + icon: SvgPicture.asset( + Assets.svg.search, + width: 20, + height: 20, + color: Theme.of(context) + .extension()! + .topNavIconPrimary, + ), + onPressed: () { + // show search + setState(() { + _isSearching = true; + }); + }, + ), + ), + AspectRatio( + aspectRatio: 1, + child: JDropdownIconButton( + mobileAppBar: true, + groupValue: _sort, + items: CCSortDescriptor.values.toSet(), + onSelectionChanged: (CCSortDescriptor? newValue) { + if (newValue != null && newValue != _sort) { + setState(() { + _sort = newValue; + }); + } + }, + displayPrefix: "Sort by", + ), + ), + ], ), body: SafeArea( child: Column( @@ -161,109 +272,328 @@ class _CoinControlViewState extends ConsumerState { const SizedBox( height: 10, ), - RoundedWhiteContainer( - child: Text( - "This option allows you to control, freeze, and utilize " - "outputs at your discretion. Tap the output circle to " - "select.", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ), - ), - const SizedBox( - height: 10, - ), - SizedBox( - height: 48, - child: Toggle( - key: UniqueKey(), - onColor: Theme.of(context) - .extension()! - .popupBG, - onText: "Available outputs", - offColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, - offText: "Frozen outputs", - isOn: _showBlocked, - onValueChanged: (value) { - setState(() { - _showBlocked = value; - }); - }, - decoration: BoxDecoration( - color: Colors.transparent, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + if (!_isSearching) + RoundedWhiteContainer( + child: Text( + "This option allows you to control, freeze, and utilize " + "outputs at your discretion. Tap the output circle to " + "select.", + style: STextStyles.w500_14(context).copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, ), ), ), - ), - const SizedBox( - height: 10, - ), - Expanded( - child: ListView.separated( - itemCount: ids.length, - separatorBuilder: (context, _) => const SizedBox( - height: 10, - ), - itemBuilder: (context, index) { - final utxo = MainDB.instance.isar.utxos - .where() - .idEqualTo(ids[index]) - .findFirstSync()!; - - final isSelected = _showBlocked - ? _selectedBlocked.contains(utxo) - : _selectedAvailable.contains(utxo); - - return UtxoCard( - key: Key( - "${utxo.walletId}_${utxo.id}_$isSelected"), - walletId: widget.walletId, - utxo: utxo, - canSelect: widget.type == - CoinControlViewType.manage || - (widget.type == CoinControlViewType.use && - !_showBlocked && - utxo.isConfirmed( - currentChainHeight, - coin.requiredConfirmations, - )), - initialSelectedState: isSelected, - onSelectedChanged: (value) { - if (value) { - _showBlocked - ? _selectedBlocked.add(utxo) - : _selectedAvailable.add(utxo); - } else { - _showBlocked - ? _selectedBlocked.remove(utxo) - : _selectedAvailable.remove(utxo); - } - setState(() {}); - }, - onPressed: () async { - final result = - await Navigator.of(context).pushNamed( - UtxoDetailsView.routeName, - arguments: Tuple2( - utxo.id, - widget.walletId, - ), - ); - if (mounted && result == "refresh") { - setState(() {}); - } - }, - ); - }, + if (!_isSearching) + const SizedBox( + height: 10, ), - ), + if (!(_isSearching || _map != null)) + SizedBox( + height: 48, + child: Toggle( + key: UniqueKey(), + onColor: Theme.of(context) + .extension()! + .popupBG, + onText: "Available outputs", + offColor: Theme.of(context) + .extension()! + .textFieldDefaultBG, + offText: "Frozen outputs", + isOn: _showBlocked, + onValueChanged: (value) { + setState(() { + _showBlocked = value; + }); + }, + decoration: BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + ), + if (!_isSearching) + const SizedBox( + height: 10, + ), + if (_isSearching) + Expanded( + child: ListView.separated( + itemCount: _list!.length, + separatorBuilder: (context, _) => const SizedBox( + height: 10, + ), + itemBuilder: (context, index) { + final utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(_list![index]) + .findFirstSync()!; + + final isSelected = + _selectedBlocked.contains(utxo) || + _selectedAvailable.contains(utxo); + + return UtxoCard( + key: Key( + "${utxo.walletId}_${utxo.id}_$isSelected"), + walletId: widget.walletId, + utxo: utxo, + canSelect: widget.type == + CoinControlViewType.manage || + (widget.type == CoinControlViewType.use && + !utxo.isBlocked && + utxo.isConfirmed( + currentChainHeight, + coin.requiredConfirmations, + )), + initialSelectedState: isSelected, + onSelectedChanged: (value) { + if (value) { + utxo.isBlocked + ? _selectedBlocked.add(utxo) + : _selectedAvailable.add(utxo); + } else { + utxo.isBlocked + ? _selectedBlocked.remove(utxo) + : _selectedAvailable.remove(utxo); + } + setState(() {}); + }, + onPressed: () async { + final result = + await Navigator.of(context).pushNamed( + UtxoDetailsView.routeName, + arguments: Tuple2( + utxo.id, + widget.walletId, + ), + ); + if (mounted && result == "refresh") { + setState(() {}); + } + }, + ); + }, + ), + ), + if (!_isSearching) + _list != null + ? Expanded( + child: ListView.separated( + itemCount: _list!.length, + separatorBuilder: (context, _) => + const SizedBox( + height: 10, + ), + itemBuilder: (context, index) { + final utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(_list![index]) + .findFirstSync()!; + + final isSelected = _showBlocked + ? _selectedBlocked.contains(utxo) + : _selectedAvailable.contains(utxo); + + return UtxoCard( + key: Key( + "${utxo.walletId}_${utxo.id}_$isSelected"), + walletId: widget.walletId, + utxo: utxo, + canSelect: widget.type == + CoinControlViewType.manage || + (widget.type == + CoinControlViewType.use && + !_showBlocked && + utxo.isConfirmed( + currentChainHeight, + coin.requiredConfirmations, + )), + initialSelectedState: isSelected, + onSelectedChanged: (value) { + if (value) { + _showBlocked + ? _selectedBlocked.add(utxo) + : _selectedAvailable.add(utxo); + } else { + _showBlocked + ? _selectedBlocked.remove(utxo) + : _selectedAvailable + .remove(utxo); + } + setState(() {}); + }, + onPressed: () async { + final result = + await Navigator.of(context) + .pushNamed( + UtxoDetailsView.routeName, + arguments: Tuple2( + utxo.id, + widget.walletId, + ), + ); + if (mounted && result == "refresh") { + setState(() {}); + } + }, + ); + }, + ), + ) + : Expanded( + child: ListView.separated( + itemCount: _map!.entries.length, + separatorBuilder: (context, _) => + const SizedBox( + height: 10, + ), + itemBuilder: (context, index) { + final entry = + _map!.entries.elementAt(index); + final _controller = + RotateIconController(); + + return Expandable2( + border: Theme.of(context) + .extension()! + .backgroundAppBar, + background: Theme.of(context) + .extension()! + .popupBG, + animationDurationMultiplier: + 0.2 * entry.value.length, + onExpandWillChange: (state) { + if (state == + Expandable2State.expanded) { + _controller.forward?.call(); + } else { + _controller.reverse?.call(); + } + }, + header: RoundedContainer( + padding: const EdgeInsets.all(14), + color: Colors.transparent, + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + entry.key, + style: + STextStyles.w600_14( + context), + ), + const SizedBox( + height: 2, + ), + Text( + "${entry.value.length} " + "output${entry.value.length > 1 ? "s" : ""}", + style: + STextStyles.w500_12( + context) + .copyWith( + color: Theme.of(context) + .extension< + StackColors>()! + .textSubtitle1, + ), + ), + ], + ), + ), + RotateIcon( + animationDurationMultiplier: + 0.2 * entry.value.length, + icon: SvgPicture.asset( + Assets.svg.chevronDown, + width: 14, + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + curve: Curves.easeInOut, + controller: _controller, + ), + ], + ), + ), + children: entry.value.map( + (id) { + final utxo = MainDB + .instance.isar.utxos + .where() + .idEqualTo(id) + .findFirstSync()!; + + final isSelected = _selectedBlocked + .contains(utxo) || + _selectedAvailable + .contains(utxo); + + return UtxoCard( + key: Key( + "${utxo.walletId}_${utxo.id}_$isSelected"), + walletId: widget.walletId, + utxo: utxo, + canSelect: widget.type == + CoinControlViewType + .manage || + (widget.type == + CoinControlViewType + .use && + !utxo.isBlocked && + utxo.isConfirmed( + currentChainHeight, + coin.requiredConfirmations, + )), + initialSelectedState: isSelected, + onSelectedChanged: (value) { + if (value) { + utxo.isBlocked + ? _selectedBlocked + .add(utxo) + : _selectedAvailable + .add(utxo); + } else { + utxo.isBlocked + ? _selectedBlocked + .remove(utxo) + : _selectedAvailable + .remove(utxo); + } + setState(() {}); + }, + onPressed: () async { + final result = + await Navigator.of(context) + .pushNamed( + UtxoDetailsView.routeName, + arguments: Tuple2( + utxo.id, + widget.walletId, + ), + ); + if (mounted && + result == "refresh") { + setState(() {}); + } + }, + ); + }, + ).toList(), + ); + }, + ), + ), ], ), ), @@ -420,6 +750,9 @@ class _CoinControlViewState extends ConsumerState { label: "Use coins", enabled: _selectedAvailable.isNotEmpty, onPressed: () async { + if (searchFocus.hasFocus) { + searchFocus.unfocus(); + } Navigator.of(context).pop( _selectedAvailable, ); diff --git a/lib/pages/coin_control/utxo_details_view.dart b/lib/pages/coin_control/utxo_details_view.dart index 180cae39d..e4b31c63d 100644 --- a/lib/pages/coin_control/utxo_details_view.dart +++ b/lib/pages/coin_control/utxo_details_view.dart @@ -5,6 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:isar/isar.dart'; import 'package:stackwallet/db/main_db.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart'; +import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_details_view.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/format.dart'; @@ -16,8 +17,11 @@ import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/custom_buttons/simple_copy_button.dart'; import 'package:stackwallet/widgets/custom_buttons/simple_edit_button.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; -import 'package:stackwallet/widgets/rounded_white_container.dart'; +import 'package:stackwallet/widgets/icon_widgets/utxo_status_icon.dart'; +import 'package:stackwallet/widgets/rounded_container.dart'; class UtxoDetailsView extends ConsumerStatefulWidget { const UtxoDetailsView({ @@ -36,7 +40,7 @@ class UtxoDetailsView extends ConsumerStatefulWidget { } class _UtxoDetailsViewState extends ConsumerState { - static const double _spacing = 12; + final isDesktop = Util.isDesktop; late Stream streamUTXO; UTXO? utxo; @@ -94,7 +98,7 @@ class _UtxoDetailsViewState extends ConsumerState { ); return ConditionalParent( - condition: !Util.isDesktop, + condition: !isDesktop, builder: (child) => Background( child: Scaffold( backgroundColor: @@ -130,233 +134,235 @@ class _UtxoDetailsViewState extends ConsumerState { ), ), child: StreamBuilder( - stream: streamUTXO, - builder: (context, snapshot) { - if (snapshot.hasData) { - utxo = snapshot.data!; - } - - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox( - height: 10, - ), - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "${Format.satoshisToAmount( - utxo!.value, - coin: coin, - ).toStringAsFixed( - coin.decimals, - )} ${coin.ticker}", - style: STextStyles.pageTitleH2(context), - ), - Text( - utxo!.isBlocked - ? "Frozen" - : confirmed - ? "Available" - : "Unconfirmed", - style: STextStyles.w500_14(context).copyWith( - color: utxo!.isBlocked - ? const Color(0xFF7FA2D4) // todo theme - : confirmed - ? Theme.of(context) - .extension()! - .accentColorGreen - : Theme.of(context) - .extension()! - .accentColorYellow, - ), - ), - ], - ), - ), - const SizedBox( - height: _spacing, - ), - RoundedWhiteContainer( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Label", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ), - SimpleEditButton( - editValue: utxo!.name, - editLabel: "label", - onValueChanged: (newName) { - MainDB.instance.putUTXO( - utxo!.copyWith( - name: newName, - ), - ); - }, - ), - ], - ), - const SizedBox( - height: 4, - ), - Text( - utxo!.name, - style: STextStyles.w500_14(context), - ), - ], - ), - ), - const SizedBox( - height: _spacing, - ), - RoundedWhiteContainer( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Address", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ), - SimpleCopyButton( - data: utxo!.address!, - ), - ], - ), - const SizedBox( - height: 4, - ), - Text( - utxo!.address!, - style: STextStyles.w500_14(context), - ), - ], - ), - ), - if (label != null && label!.value.isNotEmpty) - const SizedBox( - height: _spacing, - ), - if (label != null && label!.value.isNotEmpty) - RoundedWhiteContainer( + stream: streamUTXO, + builder: (context, snapshot) { + if (snapshot.hasData) { + utxo = snapshot.data!; + } + return ConditionalParent( + condition: isDesktop, + builder: (child) { + return DesktopDialog( + maxHeight: double.infinity, child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Address label", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Output details", + style: STextStyles.desktopH3(context), ), ), - SimpleCopyButton( - data: label!.value, + DesktopDialogCloseButton( + onPressedOverride: () { + Navigator.of(context) + .pop(_popWithRefresh ? "refresh" : null); + }, ), ], ), - const SizedBox( - height: 4, - ), - Text( - label!.value, - style: STextStyles.w500_14(context), + IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + top: 10, + ), + child: Column( + children: [ + IntrinsicHeight( + child: RoundedContainer( + padding: EdgeInsets.zero, + color: Colors.transparent, + borderColor: Theme.of(context) + .extension()! + .textFieldDefaultBG, + child: child, + ), + ), + const SizedBox( + height: 20, + ), + SecondaryButton( + buttonHeight: ButtonHeight.l, + label: utxo!.isBlocked ? "Unfreeze" : "Freeze", + onPressed: _toggleFreeze, + ), + ], + ), + ), ), ], ), - ), - const SizedBox( - height: _spacing, - ), - RoundedWhiteContainer( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + ); + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (!isDesktop) + const SizedBox( + height: 10, + ), + RoundedContainer( + padding: const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, + child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Transaction ID", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), + Row( + children: [ + if (isDesktop) + UTXOStatusIcon( + blocked: utxo!.isBlocked, + status: confirmed + ? UTXOStatusIconStatus.confirmed + : UTXOStatusIconStatus.unconfirmed, + background: Theme.of(context) + .extension()! + .popupBG, + selected: false, + width: 32, + height: 32, + ), + if (isDesktop) + const SizedBox( + width: 16, + ), + Text( + "${Format.satoshisToAmount( + utxo!.value, + coin: coin, + ).toStringAsFixed( + coin.decimals, + )} ${coin.ticker}", + style: STextStyles.pageTitleH2(context), + ), + ], ), - SimpleCopyButton( - data: utxo!.txid, + Text( + utxo!.isBlocked + ? "Frozen" + : confirmed + ? "Available" + : "Unconfirmed", + style: STextStyles.w500_14(context).copyWith( + color: utxo!.isBlocked + ? const Color(0xFF7FA2D4) // todo theme + : confirmed + ? Theme.of(context) + .extension()! + .accentColorGreen + : Theme.of(context) + .extension()! + .accentColorYellow, + ), ), ], ), - const SizedBox( - height: 4, + ), + const _Div(), + RoundedContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Label", + style: STextStyles.w500_14(context).copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + SimpleEditButton( + editValue: utxo!.name, + editLabel: "label", + onValueChanged: (newName) { + MainDB.instance.putUTXO( + utxo!.copyWith( + name: newName, + ), + ); + }, + ), + ], + ), + const SizedBox( + height: 4, + ), + Text( + utxo!.name, + style: STextStyles.w500_14(context), + ), + ], ), - Text( - utxo!.txid, - style: STextStyles.w500_14(context), + ), + const _Div(), + RoundedContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Address", + style: STextStyles.w500_14(context).copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + isDesktop + ? IconCopyButton( + data: utxo!.address!, + ) + : SimpleCopyButton( + data: utxo!.address!, + ), + ], + ), + const SizedBox( + height: 4, + ), + Text( + utxo!.address!, + style: STextStyles.w500_14(context), + ), + ], ), - ], - ), - ), - const SizedBox( - height: _spacing, - ), - RoundedWhiteContainer( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Confirmations", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ), - const SizedBox( - height: 4, - ), - Text( - "${utxo!.getConfirmations(currentHeight)}", - style: STextStyles.w500_14(context), - ), - ], - ), - ), - const SizedBox( - height: _spacing, - ), - if (utxo!.isBlocked) - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( + ), + if (label != null && label!.value.isNotEmpty) const _Div(), + if (label != null && label!.value.isNotEmpty) + RoundedContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -365,53 +371,195 @@ class _UtxoDetailsViewState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Freeze reason", + "Address label", style: STextStyles.w500_14(context).copyWith( color: Theme.of(context) .extension()! .textSubtitle1, ), ), - SimpleEditButton( - editValue: utxo!.blockedReason ?? "", - editLabel: "freeze reason", - onValueChanged: (newReason) { - MainDB.instance.putUTXO( - utxo!.copyWith( - blockedReason: newReason, + isDesktop + ? IconCopyButton( + data: utxo!.address!, + ) + : SimpleCopyButton( + data: label!.value, ), - ); - }, - ), ], ), const SizedBox( height: 4, ), Text( - utxo!.blockedReason ?? "", + label!.value, style: STextStyles.w500_14(context), ), ], ), ), - const SizedBox( - height: _spacing, + const _Div(), + RoundedContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Transaction ID", + style: STextStyles.w500_14(context).copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + isDesktop + ? IconCopyButton( + data: utxo!.address!, + ) + : SimpleCopyButton( + data: utxo!.txid, + ), + ], + ), + const SizedBox( + height: 4, + ), + Text( + utxo!.txid, + style: STextStyles.w500_14(context), + ), + ], ), - ], - ), - const Spacer(), - SecondaryButton( - label: utxo!.isBlocked ? "Unfreeze" : "Freeze", - onPressed: _toggleFreeze, + ), + const _Div(), + RoundedContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Confirmations", + style: STextStyles.w500_14(context).copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + const SizedBox( + height: 4, + ), + Text( + "${utxo!.getConfirmations(currentHeight)}", + style: STextStyles.w500_14(context), + ), + ], + ), + ), + if (utxo!.isBlocked) const _Div(), + if (utxo!.isBlocked) + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of(context) + .extension()! + .popupBG, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Freeze reason", + style: + STextStyles.w500_14(context).copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + SimpleEditButton( + editValue: utxo!.blockedReason ?? "", + editLabel: "freeze reason", + onValueChanged: (newReason) { + MainDB.instance.putUTXO( + utxo!.copyWith( + blockedReason: newReason, + ), + ); + }, + ), + ], + ), + const SizedBox( + height: 4, + ), + Text( + utxo!.blockedReason ?? "", + style: STextStyles.w500_14(context), + ), + ], + ), + ), + if (!isDesktop) const _Div(), + ], + ), + if (!isDesktop) const Spacer(), + if (!isDesktop) + SecondaryButton( + label: utxo!.isBlocked ? "Unfreeze" : "Freeze", + onPressed: _toggleFreeze, + ), + if (!isDesktop) + const SizedBox( + height: 16, + ), + ], ), - const SizedBox( - height: 16, - ), - ], - ); - }, - ), + ); + }), ); } } + +class _Div extends StatelessWidget { + const _Div({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + if (Util.isDesktop) { + return Container( + width: double.infinity, + height: 1.0, + color: Theme.of(context).extension()!.textFieldDefaultBG, + ); + } else { + return const SizedBox( + height: 12, + ); + } + } +} diff --git a/lib/pages/exchange_view/confirm_change_now_send.dart b/lib/pages/exchange_view/confirm_change_now_send.dart index 808a0417f..23712f0fd 100644 --- a/lib/pages/exchange_view/confirm_change_now_send.dart +++ b/lib/pages/exchange_view/confirm_change_now_send.dart @@ -64,33 +64,49 @@ class _ConfirmChangeNowSendViewState final isDesktop = Util.isDesktop; Future _attemptSend(BuildContext context) async { + final manager = + ref.read(walletsChangeNotifierProvider).getManager(walletId); unawaited( showDialog( context: context, useSafeArea: false, barrierDismissible: false, builder: (context) { - return const SendingTransactionDialog(); + return SendingTransactionDialog( + coin: manager.coin, + ); }, ), ); + final time = Future.delayed( + const Duration( + milliseconds: 2500, + ), + ); + + late String txid; + Future txidFuture; + final String note = transactionInfo["note"] as String? ?? ""; - final manager = - ref.read(walletsChangeNotifierProvider).getManager(walletId); try { - late final String txid; - if (widget.shouldSendPublicFiroFunds == true) { - txid = await (manager.wallet as FiroWallet) + txidFuture = (manager.wallet as FiroWallet) .confirmSendPublic(txData: transactionInfo); } else { - txid = await manager.confirmSend(txData: transactionInfo); + txidFuture = manager.confirmSend(txData: transactionInfo); } unawaited(manager.refresh()); + final results = await Future.wait([ + txidFuture, + time, + ]); + + txid = results.first as String; + // save note await ref .read(notesServiceChangeNotifierProvider(walletId)) diff --git a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart index 1d32b4811..30d40f008 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart @@ -536,24 +536,34 @@ class _Step4ViewState extends ConsumerState { try { bool wasCancelled = false; - unawaited(showDialog( - context: context, - useSafeArea: false, - barrierDismissible: false, - builder: (context) { - return BuildingTransactionDialog( - onCancel: () { - wasCancelled = true; + unawaited( + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: false, + builder: (context) { + return BuildingTransactionDialog( + coin: manager.coin, + onCancel: () { + wasCancelled = true; - Navigator.of(context) - .pop(); - }, - ); - }, - )); + Navigator.of(context) + .pop(); + }, + ); + }, + ), + ); - final txData = - await manager.prepareSend( + final time = + Future.delayed( + const Duration( + milliseconds: 2500, + ), + ); + + final txDataFuture = + manager.prepareSend( address: address, satoshiAmount: amount, args: { @@ -563,6 +573,15 @@ class _Step4ViewState extends ConsumerState { }, ); + final results = + await Future.wait([ + txDataFuture, + time, + ]); + + final txData = results.last + as Map; + if (!wasCancelled) { // pop building dialog diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart index 41df723da..780a88d92 100644 --- a/lib/pages/exchange_view/send_from_view.dart +++ b/lib/pages/exchange_view/send_from_view.dart @@ -240,6 +240,7 @@ class _SendFromCardState extends ConsumerState { ), ), child: BuildingTransactionDialog( + coin: manager.coin, onCancel: () { wasCancelled = true; @@ -251,11 +252,18 @@ class _SendFromCardState extends ConsumerState { ), ); - late Map txData; + final time = Future.delayed( + const Duration( + milliseconds: 2500, + ), + ); + + Map txData; + Future> txDataFuture; // if not firo then do normal send if (shouldSendPublicFiroFunds == null) { - txData = await manager.prepareSend( + txDataFuture = manager.prepareSend( address: address, satoshiAmount: _amount, args: { @@ -267,7 +275,7 @@ class _SendFromCardState extends ConsumerState { final firoWallet = manager.wallet as FiroWallet; // otherwise do firo send based on balance selected if (shouldSendPublicFiroFunds) { - txData = await firoWallet.prepareSendPublic( + txDataFuture = firoWallet.prepareSendPublic( address: address, satoshiAmount: _amount, args: { @@ -276,7 +284,7 @@ class _SendFromCardState extends ConsumerState { }, ); } else { - txData = await firoWallet.prepareSend( + txDataFuture = firoWallet.prepareSend( address: address, satoshiAmount: _amount, args: { @@ -287,6 +295,13 @@ class _SendFromCardState extends ConsumerState { } } + final results = await Future.wait([ + txDataFuture, + time, + ]); + + txData = results.first as Map; + if (!wasCancelled) { // pop building dialog diff --git a/lib/pages/intro_view.dart b/lib/pages/intro_view.dart index 65990d64d..0883a5405 100644 --- a/lib/pages/intro_view.dart +++ b/lib/pages/intro_view.dart @@ -52,10 +52,10 @@ class _IntroViewState extends State { constraints: const BoxConstraints( maxWidth: 300, ), - child: Image( - image: AssetImage( - Assets.png.stack(context), - ), + child: SvgPicture.asset( + Assets.svg.stack(context), + width: isDesktop ? 324 : 266, + height: isDesktop ? 324 : 266, ), ), ), diff --git a/lib/pages/paynym/paynym_claim_view.dart b/lib/pages/paynym/paynym_claim_view.dart index 326983a78..8a66aa26d 100644 --- a/lib/pages/paynym/paynym_claim_view.dart +++ b/lib/pages/paynym/paynym_claim_view.dart @@ -117,7 +117,7 @@ class _PaynymClaimViewState extends ConsumerState { ), Image( image: AssetImage( - Assets.png.unclaimedPaynym, + Assets.svg.unclaimedPaynym, ), width: MediaQuery.of(context).size.width / 2, ), diff --git a/lib/pages/pinpad_views/lock_screen_view.dart b/lib/pages/pinpad_views/lock_screen_view.dart index 25ba910ff..2b9b12b79 100644 --- a/lib/pages/pinpad_views/lock_screen_view.dart +++ b/lib/pages/pinpad_views/lock_screen_view.dart @@ -14,7 +14,6 @@ import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/biometrics.dart'; import 'package:stackwallet/utilities/constants.dart'; -import 'package:stackwallet/utilities/enums/flush_bar_type.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; @@ -130,6 +129,14 @@ class _LockscreenViewState extends ConsumerState { } } + @override + void didChangeDependencies() { + if (widget.isInitialAppLogin) { + unawaited(Assets.precache(context)); + } + super.didChangeDependencies(); + } + @override void initState() { _shakeController = ShakeController(); diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index 8ad9f90fc..ac7e41592 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -9,6 +9,7 @@ import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart'; import 'package:stackwallet/pages/send_view/sub_widgets/sending_transaction_dialog.dart'; import 'package:stackwallet/pages/wallet_view/wallet_view.dart'; +import 'package:stackwallet/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart'; @@ -74,40 +75,58 @@ class _ConfirmTransactionViewState late final TextEditingController noteController; Future _attemptSend(BuildContext context) async { + final manager = + ref.read(walletsChangeNotifierProvider).getManager(walletId); unawaited( showDialog( context: context, useSafeArea: false, barrierDismissible: false, builder: (context) { - return const SendingTransactionDialog(); + return SendingTransactionDialog( + coin: manager.coin, + ); }, ), ); + final time = Future.delayed( + const Duration( + milliseconds: 2500, + ), + ); + + late String txid; + Future txidFuture; + final note = noteController.text; - final manager = - ref.read(walletsChangeNotifierProvider).getManager(walletId); try { - String txid; if (widget.isPaynymNotificationTransaction) { - txid = await (manager.wallet as PaynymWalletInterface) + txidFuture = (manager.wallet as PaynymWalletInterface) .broadcastNotificationTx(preparedTx: transactionInfo); } else if (widget.isPaynymTransaction) { - txid = await manager.confirmSend(txData: transactionInfo); + txidFuture = manager.confirmSend(txData: transactionInfo); } else { final coin = manager.coin; if ((coin == Coin.firo || coin == Coin.firoTestNet) && ref.read(publicPrivateBalanceStateProvider.state).state != "Private") { - txid = await (manager.wallet as FiroWallet) + txidFuture = (manager.wallet as FiroWallet) .confirmSendPublic(txData: transactionInfo); } else { - txid = await manager.confirmSend(txData: transactionInfo); + txidFuture = manager.confirmSend(txData: transactionInfo); } } + final results = await Future.wait([ + txidFuture, + time, + ]); + + txid = results.first as String; + ref.refresh(desktopUseUTXOs); + // save note await ref .read(notesServiceChangeNotifierProvider(walletId)) diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 823bbe5ba..c7c63bac7 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -431,6 +431,7 @@ class _SendViewState extends ConsumerState { barrierDismissible: false, builder: (context) { return BuildingTransactionDialog( + coin: manager.coin, onCancel: () { wasCancelled = true; @@ -442,7 +443,14 @@ class _SendViewState extends ConsumerState { ); } + final time = Future.delayed( + const Duration( + milliseconds: 2500, + ), + ); + Map txData; + Future> txDataFuture; if (isPaynymSend) { final wallet = manager.wallet as PaynymWalletInterface; @@ -451,7 +459,7 @@ class _SendViewState extends ConsumerState { wallet.networkType, ); final feeRate = ref.read(feeRateTypeStateProvider); - txData = await wallet.preparePaymentCodeSend( + txDataFuture = wallet.preparePaymentCodeSend( paymentCode: paymentCode, satoshiAmount: amount, args: { @@ -466,13 +474,13 @@ class _SendViewState extends ConsumerState { } else if ((coin == Coin.firo || coin == Coin.firoTestNet) && ref.read(publicPrivateBalanceStateProvider.state).state != "Private") { - txData = await (manager.wallet as FiroWallet).prepareSendPublic( + txDataFuture = (manager.wallet as FiroWallet).prepareSendPublic( address: _address!, satoshiAmount: amount, args: {"feeRate": ref.read(feeRateTypeStateProvider)}, ); } else { - txData = await manager.prepareSend( + txDataFuture = manager.prepareSend( address: _address!, satoshiAmount: amount, args: { @@ -486,6 +494,13 @@ class _SendViewState extends ConsumerState { ); } + final results = await Future.wait([ + txDataFuture, + time, + ]); + + txData = results.first as Map; + if (!wasCancelled && mounted) { // pop building dialog Navigator.of(context).pop(); @@ -846,9 +861,8 @@ class _SendViewState extends ConsumerState { locale: locale, decimalPlaces: 2, )} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", - style: STextStyles - .titleBold12_400( - context) + style: STextStyles.subtitle( + context) .copyWith( fontSize: 8, ), diff --git a/lib/pages/send_view/sub_widgets/building_transaction_dialog.dart b/lib/pages/send_view/sub_widgets/building_transaction_dialog.dart index 6750e1b4c..6915493d5 100644 --- a/lib/pages/send_view/sub_widgets/building_transaction_dialog.dart +++ b/lib/pages/send_view/sub_widgets/building_transaction_dialog.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/color_theme.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; @@ -11,9 +13,11 @@ class BuildingTransactionDialog extends StatefulWidget { const BuildingTransactionDialog({ Key? key, required this.onCancel, + required this.coin, }) : super(key: key); final VoidCallback onCancel; + final Coin coin; @override State createState() => _RestoringDialogState(); @@ -25,6 +29,7 @@ class _RestoringDialogState extends State late Animation _spinAnimation; late final VoidCallback onCancel; + @override void initState() { onCancel = widget.onCancel; @@ -63,16 +68,25 @@ class _RestoringDialogState extends State const SizedBox( height: 40, ), - RotationTransition( - turns: _spinAnimation, - child: SvgPicture.asset( - Assets.svg.arrowRotate, - color: - Theme.of(context).extension()!.accentColorDark, - width: 24, - height: 24, + if (Theme.of(context).extension()!.themeType == + ThemeType.chan) + Image( + image: AssetImage( + Assets.gif.kiss(widget.coin), + ), + ), + if (Theme.of(context).extension()!.themeType != + ThemeType.chan) + RotationTransition( + turns: _spinAnimation, + child: SvgPicture.asset( + Assets.svg.arrowRotate, + color: + Theme.of(context).extension()!.accentColorDark, + width: 24, + height: 24, + ), ), - ), const SizedBox( height: 40, ), @@ -90,34 +104,76 @@ class _RestoringDialogState extends State onWillPop: () async { return false; }, - child: StackDialog( - title: "Generating transaction", - // // TODO get message from design team - // message: "", - icon: RotationTransition( - turns: _spinAnimation, - child: SvgPicture.asset( - Assets.svg.arrowRotate, - color: - Theme.of(context).extension()!.accentColorDark, - width: 24, - height: 24, - ), - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Cancel", - style: STextStyles.itemSubtitle12(context), - ), - onPressed: () { - Navigator.of(context).pop(); - onCancel.call(); - }, - ), - ), + child: Theme.of(context).extension()!.themeType == + ThemeType.chan + ? StackDialogBase( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, + children: [ + Image( + image: AssetImage( + Assets.gif.kiss(widget.coin), + ), + ), + Text( + "Generating transaction", + textAlign: TextAlign.center, + style: STextStyles.pageTitleH2(context), + ), + const SizedBox( + height: 32, + ), + Row( + children: [ + const Spacer(), + Expanded( + child: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Cancel", + style: STextStyles.itemSubtitle12(context), + ), + onPressed: () { + Navigator.of(context).pop(); + onCancel.call(); + }, + ), + ) + ], + ), + ], + ), + ) + : StackDialog( + title: "Generating transaction", + icon: RotationTransition( + turns: _spinAnimation, + child: SvgPicture.asset( + Assets.svg.arrowRotate, + color: Theme.of(context) + .extension()! + .accentColorDark, + width: 24, + height: 24, + ), + ), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Cancel", + style: STextStyles.itemSubtitle12(context), + ), + onPressed: () { + Navigator.of(context).pop(); + onCancel.call(); + }, + ), + ), ); } } diff --git a/lib/pages/send_view/sub_widgets/sending_transaction_dialog.dart b/lib/pages/send_view/sub_widgets/sending_transaction_dialog.dart index e5c86fe2e..3d9928c34 100644 --- a/lib/pages/send_view/sub_widgets/sending_transaction_dialog.dart +++ b/lib/pages/send_view/sub_widgets/sending_transaction_dialog.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/color_theme.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; @@ -10,8 +12,11 @@ import 'package:stackwallet/widgets/stack_dialog.dart'; class SendingTransactionDialog extends StatefulWidget { const SendingTransactionDialog({ Key? key, + required this.coin, }) : super(key: key); + final Coin coin; + @override State createState() => _RestoringDialogState(); } @@ -60,17 +65,24 @@ class _RestoringDialogState extends State const SizedBox( height: 40, ), - RotationTransition( - turns: _spinAnimation, - child: SvgPicture.asset( - Assets.svg.arrowRotate, - color: Theme.of(context) - .extension()! - .accentColorDark, - width: 24, - height: 24, - ), - ), + Theme.of(context).extension()!.themeType == + ThemeType.chan + ? Image( + image: AssetImage( + Assets.gif.kiss(widget.coin), + ), + ) + : RotationTransition( + turns: _spinAnimation, + child: SvgPicture.asset( + Assets.svg.arrowRotate, + color: Theme.of(context) + .extension()! + .accentColorDark, + width: 24, + height: 24, + ), + ), ], ), ), @@ -80,21 +92,43 @@ class _RestoringDialogState extends State onWillPop: () async { return false; }, - child: StackDialog( - title: "Sending transaction", - // // TODO get message from design team - // message: "", - icon: RotationTransition( - turns: _spinAnimation, - child: SvgPicture.asset( - Assets.svg.arrowRotate, - color: - Theme.of(context).extension()!.accentColorDark, - width: 24, - height: 24, - ), - ), - ), + child: Theme.of(context).extension()!.themeType == + ThemeType.chan + ? StackDialogBase( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, + children: [ + Image( + image: AssetImage( + Assets.gif.kiss(widget.coin), + ), + ), + Text( + "Sending transaction", + textAlign: TextAlign.center, + style: STextStyles.pageTitleH2(context), + ), + const SizedBox( + height: 32, + ), + ], + ), + ) + : StackDialog( + title: "Sending transaction", + icon: RotationTransition( + turns: _spinAnimation, + child: SvgPicture.asset( + Assets.svg.arrowRotate, + color: Theme.of(context) + .extension()! + .accentColorDark, + width: 24, + height: 24, + ), + ), + ), ); } } diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart b/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart index d25a650e3..04642b98f 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart @@ -3,15 +3,10 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/hive/db.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/ui/color_theme_provider.dart'; +import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/color_theme.dart'; -import 'package:stackwallet/utilities/theme/dark_colors.dart'; -import 'package:stackwallet/utilities/theme/forest_colors.dart'; -import 'package:stackwallet/utilities/theme/fruit_sorbet_colors.dart'; -import 'package:stackwallet/utilities/theme/light_colors.dart'; -import 'package:stackwallet/utilities/theme/ocean_breeze_colors.dart'; -import 'package:stackwallet/utilities/theme/oled_black_colors.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; @@ -23,23 +18,6 @@ class AppearanceSettingsView extends ConsumerWidget { static const String routeName = "/appearanceSettings"; - String chooseThemeType(ThemeType type) { - switch (type) { - case ThemeType.light: - return "Light theme"; - case ThemeType.dark: - return "Dark theme"; - case ThemeType.oceanBreeze: - return "Ocean theme"; - case ThemeType.oledBlack: - return "Oled Black theme"; - case ThemeType.fruitSorbet: - return "Fruit Sorbet theme"; - case ThemeType.forest: - return "Forest theme"; - } - } - @override Widget build(BuildContext context, WidgetRef ref) { return Background( @@ -173,516 +151,115 @@ class AppearanceSettingsView extends ConsumerWidget { } } -class ThemeOptionsView extends ConsumerStatefulWidget { - const ThemeOptionsView({ - Key? key, - }) : super(key: key); +class ThemeOptionsView extends ConsumerWidget { + const ThemeOptionsView({Key? key}) : super(key: key); @override - ConsumerState createState() => _ThemeOptionsView(); -} - -class _ThemeOptionsView extends ConsumerState { - late String _selectedTheme; - - @override - void initState() { - _selectedTheme = - DB.instance.get(boxName: DB.boxNameTheme, key: "colorScheme") - as String? ?? - "light"; - - super.initState(); - } - - @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { return Column( children: [ - MaterialButton( - splashColor: Colors.transparent, - hoverColor: Colors.transparent, - padding: const EdgeInsets.all(0), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.light.name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - LightColors(), - ); - - setState(() { - _selectedTheme = "light"; - }); - }, - child: SizedBox( - width: 200, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - SizedBox( - width: 10, - height: 10, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: "light", - groupValue: _selectedTheme, - onChanged: (newValue) { - if (newValue is String && newValue == "light") { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.light.name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - LightColors(), - ); - - setState(() { - _selectedTheme = "light"; - }); - } - }, - ), - ), - const SizedBox( - width: 14, - ), - Text( - "Light", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark2, - ), - ), - ], + for (int i = 0; i < (2 * ThemeType.values.length) - 1; i++) + (i % 2 == 1) + ? const SizedBox( + height: 10, + ) + : ThemeOption( + onPressed: () { + DB.instance.put( + boxName: DB.boxNameTheme, + key: "colorScheme", + value: ThemeType.values[i ~/ 2].name, + ); + ref.read(colorThemeProvider.state).state = + StackColors.fromStackColorTheme( + ThemeType.values[i ~/ 2].colorTheme, + ); + Assets.precache(context); + }, + onChanged: (newValue) { + if (newValue == ThemeType.values[i ~/ 2]) { + DB.instance.put( + boxName: DB.boxNameTheme, + key: "colorScheme", + value: ThemeType.values[i ~/ 2].name, + ); + ref.read(colorThemeProvider.state).state = + StackColors.fromStackColorTheme( + ThemeType.values[i ~/ 2].colorTheme, + ); + Assets.precache(context); + } + }, + value: ThemeType.values[i ~/ 2], + groupValue: + Theme.of(context).extension()!.themeType, ), - ], - ), - ), - ), - const SizedBox( - height: 10, - ), - MaterialButton( - splashColor: Colors.transparent, - hoverColor: Colors.transparent, - padding: const EdgeInsets.all(0), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.dark.name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - DarkColors(), - ); - - setState(() { - _selectedTheme = "dark"; - }); - }, - child: SizedBox( - width: 200, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - SizedBox( - width: 10, - height: 10, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: "dark", - groupValue: _selectedTheme, - onChanged: (newValue) { - if (newValue is String && newValue == "dark") { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.dark.name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - DarkColors(), - ); - - setState(() { - _selectedTheme = "dark"; - }); - } - }, - ), - ), - const SizedBox( - width: 14, - ), - Text( - "Dark", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark2, - ), - ), - ], - ), - ], - ), - ), - ), - const SizedBox( - height: 10, - ), - MaterialButton( - splashColor: Colors.transparent, - hoverColor: Colors.transparent, - padding: const EdgeInsets.all(0), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.oceanBreeze.name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - OceanBreezeColors(), - ); - - setState(() { - _selectedTheme = "oceanBreeze"; - }); - }, - child: SizedBox( - width: 200, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - SizedBox( - width: 10, - height: 10, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: "oceanBreeze", - groupValue: _selectedTheme, - onChanged: (newValue) { - if (newValue is String && newValue == "oceanBreeze") { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.oceanBreeze.name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - OceanBreezeColors(), - ); - - setState(() { - _selectedTheme = "oceanBreeze"; - }); - } - }, - ), - ), - const SizedBox( - width: 14, - ), - Text( - "Ocean Breeze", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark2, - ), - ), - ], - ), - ], - ), - ), - ), - const SizedBox( - height: 10, - ), - MaterialButton( - splashColor: Colors.transparent, - hoverColor: Colors.transparent, - padding: const EdgeInsets.all(0), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.oledBlack.name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - OledBlackColors(), - ); - - setState(() { - _selectedTheme = "oledBlack"; - }); - }, - child: SizedBox( - width: 200, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - SizedBox( - width: 10, - height: 10, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: "oledBlack", - groupValue: _selectedTheme, - onChanged: (newValue) { - if (newValue is String && newValue == "oledBlack") { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.oledBlack.name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - OledBlackColors(), - ); - - setState(() { - _selectedTheme = "oledBlack"; - }); - } - }, - ), - ), - const SizedBox( - width: 14, - ), - Text( - "OLED Black", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark2, - ), - ), - ], - ), - ], - ), - ), - ), - const SizedBox( - height: 10, - ), - MaterialButton( - splashColor: Colors.transparent, - hoverColor: Colors.transparent, - padding: const EdgeInsets.all(0), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.fruitSorbet.name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - FruitSorbetColors(), - ); - - setState(() { - _selectedTheme = "fruitSorbet"; - }); - }, - child: SizedBox( - width: 200, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - SizedBox( - width: 10, - height: 10, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: "fruitSorbet", - groupValue: _selectedTheme, - onChanged: (newValue) { - if (newValue is String && newValue == "fruitSorbet") { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.fruitSorbet.name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - FruitSorbetColors(), - ); - - setState(() { - _selectedTheme = "fruitSorbet"; - }); - } - }, - ), - ), - const SizedBox( - width: 14, - ), - Text( - "Fruit Sorbet", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark2, - ), - ), - ], - ), - ], - ), - ), - ), - const SizedBox( - height: 10, - ), - MaterialButton( - splashColor: Colors.transparent, - hoverColor: Colors.transparent, - padding: const EdgeInsets.all(0), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.forest.name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - ForestColors(), - ); - - setState(() { - _selectedTheme = "forest"; - }); - }, - child: SizedBox( - width: 200, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - SizedBox( - width: 10, - height: 10, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: "forest", - groupValue: _selectedTheme, - onChanged: (newValue) { - if (newValue is String && newValue == "forest") { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.forest.name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - ForestColors(), - ); - - setState(() { - _selectedTheme = "forest"; - }); - } - }, - ), - ), - const SizedBox( - width: 14, - ), - Text( - "Forest", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark2, - ), - ), - ], - ), - ], - ), - ), - ), ], ); } } + +class ThemeOption extends StatelessWidget { + const ThemeOption( + {Key? key, + required this.onPressed, + required this.onChanged, + required this.value, + required this.groupValue}) + : super(key: key); + + final VoidCallback onPressed; + final void Function(Object?) onChanged; + final ThemeType value; + final ThemeType groupValue; + + @override + Widget build(BuildContext context) { + return MaterialButton( + splashColor: Colors.transparent, + hoverColor: Colors.transparent, + padding: const EdgeInsets.all(0), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: onPressed, + child: SizedBox( + width: 200, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + SizedBox( + width: 10, + height: 10, + child: Radio( + activeColor: Theme.of(context) + .extension()! + .radioButtonIconEnabled, + value: value, + groupValue: groupValue, + onChanged: onChanged, + ), + ), + const SizedBox( + width: 14, + ), + Text( + value.prettyName, + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of(context).extension()!.textDark2, + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/settings_views/global_settings_view/hidden_settings.dart b/lib/pages/settings_views/global_settings_view/hidden_settings.dart index 3d16e20b4..55afd845e 100644 --- a/lib/pages/settings_views/global_settings_view/hidden_settings.dart +++ b/lib/pages/settings_views/global_settings_view/hidden_settings.dart @@ -57,11 +57,15 @@ class HiddenSettings extends StatelessWidget { .read(notificationsProvider) .delete(notifs[0], true); - unawaited(showFloatingFlushBar( - type: FlushBarType.success, - message: "Notification history deleted", - context: context, - )); + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.success, + message: "Notification history deleted", + context: context, + ), + ); + } }, child: RoundedWhiteContainer( child: Text( @@ -112,11 +116,15 @@ class HiddenSettings extends StatelessWidget { .read(debugServiceProvider) .deleteAllLogs(); - unawaited(showFloatingFlushBar( - type: FlushBarType.success, - message: "Debug Logs deleted", - context: context, - )); + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.success, + message: "Debug Logs deleted", + context: context, + ), + ); + } }, child: RoundedWhiteContainer( child: Text( @@ -217,9 +225,9 @@ class HiddenSettings extends StatelessWidget { // builder: (_) { // return StackDialogBase( // child: SizedBox( - // width: 200, + // width: 300, // child: Lottie.asset( - // Assets.lottie.test2, + // Assets.lottie.plain(Coin.bitcoincash), // ), // ), // ); @@ -230,8 +238,9 @@ class HiddenSettings extends StatelessWidget { // child: Text( // "Lottie test", // style: STextStyles.button(context).copyWith( - // color: Theme.of(context).extension()!.accentColorDark - // ), + // color: Theme.of(context) + // .extension()! + // .accentColorDark), // ), // ), // ), diff --git a/lib/pages/stack_privacy_calls.dart b/lib/pages/stack_privacy_calls.dart index b2c77dc5e..8dc98a23d 100644 --- a/lib/pages/stack_privacy_calls.dart +++ b/lib/pages/stack_privacy_calls.dart @@ -12,7 +12,6 @@ import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/text_styles.dart'; -import 'package:stackwallet/utilities/theme/color_theme.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; @@ -22,8 +21,6 @@ import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart'; import 'package:stackwallet/widgets/desktop/primary_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; -import '../providers/ui/color_theme_provider.dart'; - class StackPrivacyCalls extends ConsumerStatefulWidget { const StackPrivacyCalls({ Key? key, @@ -42,13 +39,11 @@ class _StackPrivacyCalls extends ConsumerState { late final bool isDesktop; late bool isEasy; late bool infoToggle; - late final bool usePNG; @override void initState() { isDesktop = Util.isDesktop; isEasy = ref.read(prefsChangeNotifierProvider).externalCalls; - usePNG = ref.read(colorThemeProvider.state).state == "fruitSorbet"; infoToggle = isEasy; super.initState(); } @@ -300,16 +295,10 @@ class _PrivacyToggleState extends ConsumerState { late bool externalCallsEnabled; late final bool isDesktop; - late final bool isSorbet; - late final bool isOcean; @override void initState() { isDesktop = Util.isDesktop; - isSorbet = ref.read(colorThemeProvider.state).state.themeType == - ThemeType.fruitSorbet; - isOcean = ref.read(colorThemeProvider.state).state.themeType == - ThemeType.oceanBreeze; // initial toggle state externalCallsEnabled = widget.externalCallsEnabled; super.initState(); @@ -357,17 +346,11 @@ class _PrivacyToggleState extends ConsumerState { // const SizedBox( // height: 10, // ), - (isSorbet) - ? Image.asset( - Assets.png.personaEasy(context), - width: 140, - height: 140, - ) - : SvgPicture.asset( - Assets.svg.personaEasy(context), - width: 140, - height: 140, - ), + SvgPicture.asset( + Assets.svg.personaEasy(context), + width: 140, + height: 140, + ), // if (isDesktop) // const SizedBox( // height: 12, @@ -468,17 +451,11 @@ class _PrivacyToggleState extends ConsumerState { const SizedBox( height: 10, ), - (isSorbet) - ? Image.asset( - Assets.png.personaIncognito(context), - width: 140, - height: 140, - ) - : SvgPicture.asset( - Assets.svg.personaIncognito(context), - width: 140, - height: 140, - ), + SvgPicture.asset( + Assets.svg.personaIncognito(context), + width: 140, + height: 140, + ), if (isDesktop) const SizedBox( height: 12, diff --git a/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart b/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart index 7686bc3ab..de9d95f7e 100644 --- a/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart +++ b/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart @@ -1,7 +1,9 @@ import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/providers/providers.dart'; +import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart'; import 'package:stackwallet/providers/wallet/wallet_balance_toggle_state_provider.dart'; import 'package:stackwallet/services/coins/firo/firo_wallet.dart'; import 'package:stackwallet/utilities/constants.dart'; @@ -10,6 +12,13 @@ import 'package:stackwallet/utilities/enums/wallet_balance_toggle_state.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +enum _BalanceType { + available, + full, + privateAvailable, + privateFull; +} + class WalletBalanceToggleSheet extends ConsumerWidget { const WalletBalanceToggleSheet({ Key? key, @@ -25,21 +34,31 @@ class WalletBalanceToggleSheet extends ConsumerWidget { final coin = ref.watch(walletsChangeNotifierProvider .select((value) => value.getManager(walletId).coin)); - Future? totalBalanceFuture; - Future? availableBalanceFuture; + final balance = ref.watch(walletsChangeNotifierProvider + .select((value) => value.getManager(walletId).balance)); + + _BalanceType _bal = + ref.watch(walletBalanceToggleStateProvider.state).state == + WalletBalanceToggleState.available + ? _BalanceType.available + : _BalanceType.full; + + Balance? balanceSecondary; if (coin == Coin.firo || coin == Coin.firoTestNet) { - final firoWallet = ref - .watch(walletsChangeNotifierProvider - .select((value) => value.getManager(walletId))) - .wallet as FiroWallet; - totalBalanceFuture = Future(() => firoWallet.balance.getSpendable()); - availableBalanceFuture = - Future(() => firoWallet.balancePrivate.getSpendable()); - } else { - final manager = ref.watch(walletsChangeNotifierProvider - .select((value) => value.getManager(walletId))); - totalBalanceFuture = Future(() => manager.balance.getTotal()); - availableBalanceFuture = Future(() => manager.balance.getSpendable()); + balanceSecondary = ref + .watch( + walletsChangeNotifierProvider.select( + (value) => value.getManager(walletId).wallet as FiroWallet?, + ), + ) + ?.balancePrivate; + + if (ref.watch(publicPrivateBalanceStateProvider.state).state == + "Private") { + _bal = _bal == _BalanceType.available + ? _BalanceType.privateAvailable + : _BalanceType.privateFull; + } } return Container( @@ -90,271 +109,103 @@ class WalletBalanceToggleSheet extends ConsumerWidget { const SizedBox( height: 24, ), - RawMaterialButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), + BalanceSelector( + title: "Available balance", + coin: coin, + balance: balance.getSpendable(), onPressed: () { - final state = - ref.read(walletBalanceToggleStateProvider.state).state; - if (state != WalletBalanceToggleState.available) { - ref.read(walletBalanceToggleStateProvider.state).state = - WalletBalanceToggleState.available; - } + ref.read(walletBalanceToggleStateProvider.state).state = + WalletBalanceToggleState.available; + ref.read(publicPrivateBalanceStateProvider.state).state = + "Public"; Navigator.of(context).pop(); }, - child: Container( - color: Colors.transparent, - padding: const EdgeInsets.all(8), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: WalletBalanceToggleState.available, - groupValue: ref - .watch(walletBalanceToggleStateProvider.state) - .state, - onChanged: (_) { - ref - .read(walletBalanceToggleStateProvider.state) - .state = WalletBalanceToggleState.available; - Navigator.of(context).pop(); - }, - ), - ), - const SizedBox( - width: 12, - ), - if (coin != Coin.firo && coin != Coin.firoTestNet) - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Available balance", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 2, - ), - FutureBuilder( - future: availableBalanceFuture, - builder: (fbContext, - AsyncSnapshot snapshot) { - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData && - snapshot.data != null) { - return Text( - "${snapshot.data!.toStringAsFixed(Constants.decimalPlacesForCoin(coin))} ${coin.ticker}", - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ); - } else { - return Text( - "", - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ); - } - }), - ], - ), - if (coin == Coin.firo || coin == Coin.firoTestNet) - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Private balance", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 2, - ), - FutureBuilder( - future: availableBalanceFuture, - builder: (fbContext, - AsyncSnapshot snapshot) { - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData && - snapshot.data != null) { - return Text( - "${snapshot.data!.toStringAsFixed(Constants.decimalPlacesForCoin(coin))} ${coin.ticker}", - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ); - } else { - return Text( - "", - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ); - } - }), - ], - ), - ], - ), - ), + onChanged: (_) { + ref.read(walletBalanceToggleStateProvider.state).state = + WalletBalanceToggleState.available; + ref.read(publicPrivateBalanceStateProvider.state).state = + "Public"; + Navigator.of(context).pop(); + }, + value: _BalanceType.available, + groupValue: _bal, ), + if (balanceSecondary != null) + const SizedBox( + height: 12, + ), + if (balanceSecondary != null) + BalanceSelector( + title: "Available private balance", + coin: coin, + balance: balanceSecondary.getSpendable(), + onPressed: () { + ref.read(walletBalanceToggleStateProvider.state).state = + WalletBalanceToggleState.available; + ref.read(publicPrivateBalanceStateProvider.state).state = + "Private"; + Navigator.of(context).pop(); + }, + onChanged: (_) { + ref.read(walletBalanceToggleStateProvider.state).state = + WalletBalanceToggleState.available; + ref.read(publicPrivateBalanceStateProvider.state).state = + "Private"; + Navigator.of(context).pop(); + }, + value: _BalanceType.privateAvailable, + groupValue: _bal, + ), const SizedBox( height: 12, ), - RawMaterialButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), + BalanceSelector( + title: "Full balance", + coin: coin, + balance: balance.getTotal(), onPressed: () { - final state = - ref.read(walletBalanceToggleStateProvider.state).state; - if (state != WalletBalanceToggleState.full) { - ref.read(walletBalanceToggleStateProvider.state).state = - WalletBalanceToggleState.full; - } + ref.read(walletBalanceToggleStateProvider.state).state = + WalletBalanceToggleState.full; + ref.read(publicPrivateBalanceStateProvider.state).state = + "Public"; Navigator.of(context).pop(); }, - child: Container( - color: Colors.transparent, - padding: const EdgeInsets.all(8), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: WalletBalanceToggleState.full, - groupValue: ref - .watch(walletBalanceToggleStateProvider.state) - .state, - onChanged: (_) { - ref - .read(walletBalanceToggleStateProvider.state) - .state = WalletBalanceToggleState.full; - Navigator.of(context).pop(); - }, - ), - ), - const SizedBox( - width: 12, - ), - if (coin != Coin.firo && coin != Coin.firoTestNet) - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Full balance", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 2, - ), - FutureBuilder( - future: totalBalanceFuture, - builder: (fbContext, - AsyncSnapshot snapshot) { - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData && - snapshot.data != null) { - return Text( - "${snapshot.data!.toStringAsFixed(Constants.decimalPlacesForCoin(coin))} ${coin.ticker}", - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ); - } else { - return Text( - "", - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ); - } - }), - ], - ), - if (coin == Coin.firo || coin == Coin.firoTestNet) - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Public balance", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 2, - ), - FutureBuilder( - future: totalBalanceFuture, - builder: (fbContext, - AsyncSnapshot snapshot) { - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData && - snapshot.data != null) { - return Text( - "${snapshot.data!.toStringAsFixed(Constants.decimalPlacesForCoin(coin))} ${coin.ticker}", - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ); - } else { - return Text( - "", - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ); - } - }), - ], - ), - ], - ), - ), + onChanged: (_) { + ref.read(walletBalanceToggleStateProvider.state).state = + WalletBalanceToggleState.full; + ref.read(publicPrivateBalanceStateProvider.state).state = + "Public"; + Navigator.of(context).pop(); + }, + value: _BalanceType.full, + groupValue: _bal, ), + if (balanceSecondary != null) + const SizedBox( + height: 12, + ), + if (balanceSecondary != null) + BalanceSelector( + title: "Full private balance", + coin: coin, + balance: balanceSecondary.getTotal(), + onPressed: () { + ref.read(walletBalanceToggleStateProvider.state).state = + WalletBalanceToggleState.full; + ref.read(publicPrivateBalanceStateProvider.state).state = + "Private"; + Navigator.of(context).pop(); + }, + onChanged: (_) { + ref.read(walletBalanceToggleStateProvider.state).state = + WalletBalanceToggleState.full; + ref.read(publicPrivateBalanceStateProvider.state).state = + "Private"; + Navigator.of(context).pop(); + }, + value: _BalanceType.privateFull, + groupValue: _bal, + ), const SizedBox( height: 40, ), @@ -365,3 +216,80 @@ class WalletBalanceToggleSheet extends ConsumerWidget { ); } } + +class BalanceSelector extends StatelessWidget { + const BalanceSelector({ + Key? key, + required this.title, + required this.coin, + required this.balance, + required this.onPressed, + required this.onChanged, + required this.value, + required this.groupValue, + }) : super(key: key); + + final String title; + final Coin coin; + final Decimal balance; + final VoidCallback onPressed; + final void Function(T?) onChanged; + final T value; + final T? groupValue; + + @override + Widget build(BuildContext context) { + return RawMaterialButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: onPressed, + child: Container( + color: Colors.transparent, + padding: const EdgeInsets.all(8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 20, + height: 20, + child: Radio( + activeColor: Theme.of(context) + .extension()! + .radioButtonIconEnabled, + value: value, + groupValue: groupValue, + onChanged: onChanged, + ), + ), + const SizedBox( + width: 12, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: STextStyles.titleBold12(context), + ), + const SizedBox( + height: 2, + ), + Text( + "${balance.toStringAsFixed(Constants.decimalPlacesForCoin(coin))} ${coin.ticker}", + style: STextStyles.itemSubtitle12(context).copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ) + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart b/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart index 4580cd44e..6339692f5 100644 --- a/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart +++ b/lib/pages/wallet_view/sub_widgets/wallet_summary_info.dart @@ -19,6 +19,8 @@ import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import '../../../providers/wallet/public_private_balance_state_provider.dart'; + class WalletSummaryInfo extends ConsumerStatefulWidget { const WalletSummaryInfo({ Key? key, @@ -92,19 +94,26 @@ class _WalletSummaryInfoState extends ConsumerState { ref.watch(walletBalanceToggleStateProvider.state).state == WalletBalanceToggleState.available; - final Decimal totalBalance; - final Decimal availableBalance; + final Decimal balanceToShow; + String title; + if (coin == Coin.firo || coin == Coin.firoTestNet) { + final _showPrivate = + ref.watch(publicPrivateBalanceStateProvider.state).state == "Private"; + final firoWallet = ref.watch(walletsChangeNotifierProvider.select( (value) => value.getManager(widget.walletId).wallet)) as FiroWallet; - totalBalance = firoWallet.balance.getSpendable(); - availableBalance = firoWallet.balancePrivate.getSpendable(); - } else { - totalBalance = balance.getTotal(); - availableBalance = balance.getSpendable(); - } - final balanceToShow = _showAvailable ? availableBalance : totalBalance; + final bal = _showPrivate ? firoWallet.balancePrivate : firoWallet.balance; + + balanceToShow = _showAvailable ? bal.getSpendable() : bal.getTotal(); + title = _showAvailable ? "Available" : "Full"; + title += _showPrivate ? " private balance" : " public balance"; + } else { + balanceToShow = + _showAvailable ? balance.getSpendable() : balance.getTotal(); + title = _showAvailable ? "Available balance" : "Full balance"; + } return Row( children: [ @@ -116,24 +125,14 @@ class _WalletSummaryInfoState extends ConsumerState { onTap: showSheet, child: Row( children: [ - if (coin == Coin.firo || coin == Coin.firoTestNet) - Text( - "${_showAvailable ? "Private" : "Public"} Balance", - style: STextStyles.subtitle500(context).copyWith( - color: Theme.of(context) - .extension()! - .textFavoriteCard, - ), - ), - if (coin != Coin.firo && coin != Coin.firoTestNet) - Text( - "${_showAvailable ? "Available" : "Full"} Balance", - style: STextStyles.subtitle500(context).copyWith( - color: Theme.of(context) - .extension()! - .textFavoriteCard, - ), + Text( + title, + style: STextStyles.subtitle500(context).copyWith( + color: Theme.of(context) + .extension()! + .textFavoriteCard, ), + ), const SizedBox( width: 4, ), diff --git a/lib/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart b/lib/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart new file mode 100644 index 000000000..d0ba9ecbd --- /dev/null +++ b/lib/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart @@ -0,0 +1,581 @@ +import 'package:decimal/decimal.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:isar/isar.dart'; +import 'package:stackwallet/db/main_db.dart'; +import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart'; +import 'package:stackwallet/pages_desktop_specific/coin_control/utxo_row.dart'; +import 'package:stackwallet/providers/global/wallets_provider.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/format.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/animated_widgets/rotate_icon.dart'; +import 'package:stackwallet/widgets/conditional_parent.dart'; +import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/custom_buttons/dropdown_button.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/expandable2.dart'; +import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; +import 'package:stackwallet/widgets/rounded_container.dart'; +import 'package:stackwallet/widgets/stack_text_field.dart'; +import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/widgets/toggle.dart'; + +final desktopUseUTXOs = StateProvider((ref) => {}); + +class DesktopCoinControlUseDialog extends ConsumerStatefulWidget { + const DesktopCoinControlUseDialog({ + Key? key, + required this.walletId, + this.amountToSend, + }) : super(key: key); + + final String walletId; + final Decimal? amountToSend; + + @override + ConsumerState createState() => + _DesktopCoinControlUseDialogState(); +} + +class _DesktopCoinControlUseDialogState + extends ConsumerState { + late final TextEditingController _searchController; + late final Coin coin; + final searchFieldFocusNode = FocusNode(); + + final Set _selectedUTXOsData = {}; + final Set _selectedUTXOs = {}; + + Map>? _map; + List? _list; + + String _searchString = ""; + + CCFilter _filter = CCFilter.available; + CCSortDescriptor _sort = CCSortDescriptor.age; + + bool selectedChanged(Set newSelected) { + if (ref.read(desktopUseUTXOs).length != newSelected.length) return true; + return !ref.read(desktopUseUTXOs).containsAll(newSelected); + } + + @override + void initState() { + _searchController = TextEditingController(); + coin = ref + .read(walletsChangeNotifierProvider) + .getManager(widget.walletId) + .coin; + + for (final utxo in ref.read(desktopUseUTXOs)) { + final data = UtxoRowData(utxo.id, true); + _selectedUTXOs.add(utxo); + _selectedUTXOsData.add(data); + } + + super.initState(); + } + + @override + void dispose() { + _searchController.dispose(); + searchFieldFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + + if (_sort == CCSortDescriptor.address) { + _list = null; + _map = MainDB.instance.queryUTXOsGroupedByAddressSync( + walletId: widget.walletId, + filter: _filter, + sort: _sort, + searchTerm: _searchString, + coin: coin, + ); + } else { + _map = null; + _list = MainDB.instance.queryUTXOsSync( + walletId: widget.walletId, + filter: _filter, + sort: _sort, + searchTerm: _searchString, + coin: coin, + ); + } + + final selectedSum = Format.satoshisToAmount( + _selectedUTXOs + .map((e) => e.value) + .fold(0, (value, element) => value += element), + coin: coin, + ); + + final enableApply = widget.amountToSend == null + ? selectedChanged(_selectedUTXOs) + : selectedChanged(_selectedUTXOs) && + widget.amountToSend! <= selectedSum; + + return DesktopDialog( + maxWidth: 700, + maxHeight: MediaQuery.of(context).size.height - 128, + child: Column( + children: [ + Row( + children: [ + const AppBarBackButton( + size: 40, + iconSize: 24, + ), + Text( + "Coin control", + style: STextStyles.desktopH3(context), + ), + ], + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Column( + children: [ + RoundedContainer( + color: Colors.transparent, + borderColor: Theme.of(context) + .extension()! + .textFieldDefaultBG, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "This option allows you to control, freeze, and utilize " + "outputs at your discretion.", + style: + STextStyles.desktopTextExtraExtraSmall(context), + ), + ], + ), + ), + const SizedBox( + height: 16, + ), + Row( + children: [ + Expanded( + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: false, + enableSuggestions: false, + controller: _searchController, + focusNode: searchFieldFocusNode, + onChanged: (value) { + setState(() { + _searchString = value; + }); + }, + style: STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ), + decoration: standardInputDecoration( + "Search...", + searchFieldFocusNode, + context, + desktopMed: true, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 18, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 20, + height: 20, + ), + ), + suffixIcon: _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchString = ""; + }); + }, + ), + ], + ), + ), + ) + : null, + ), + ), + ), + ), + const SizedBox( + width: 16, + ), + SizedBox( + height: 56, + width: 240, + child: Toggle( + isOn: _filter == CCFilter.frozen, + onColor: Theme.of(context) + .extension()! + .rateTypeToggleDesktopColorOn, + offColor: Theme.of(context) + .extension()! + .rateTypeToggleDesktopColorOff, + onIcon: Assets.svg.coinControl.unBlocked, + onText: "Available", + offIcon: Assets.svg.coinControl.blocked, + offText: "Frozen", + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onValueChanged: (value) { + setState(() { + if (value) { + _filter = CCFilter.frozen; + } else { + _filter = CCFilter.available; + } + }); + }, + ), + ), + const SizedBox( + width: 16, + ), + JDropdownIconButton( + redrawOnScreenSizeChanged: true, + groupValue: _sort, + items: CCSortDescriptor.values.toSet(), + onSelectionChanged: (CCSortDescriptor? newValue) { + if (newValue != null && newValue != _sort) { + setState(() { + _sort = newValue; + }); + } + }, + displayPrefix: "Sort by", + ) + ], + ), + const SizedBox( + height: 16, + ), + Expanded( + child: _list != null + ? ListView.separated( + shrinkWrap: true, + primary: false, + itemCount: _list!.length, + separatorBuilder: (context, _) => const SizedBox( + height: 10, + ), + itemBuilder: (context, index) { + final utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(_list![index]) + .findFirstSync()!; + final data = UtxoRowData(utxo.id, false); + data.selected = _selectedUTXOsData.contains(data); + + return UtxoRow( + key: Key( + "${utxo.walletId}_${utxo.id}_${utxo.isBlocked}"), + data: data, + compact: true, + walletId: widget.walletId, + onSelectionChanged: (value) { + setState(() { + if (data.selected) { + _selectedUTXOsData.add(value); + _selectedUTXOs.add(utxo); + } else { + _selectedUTXOsData.remove(value); + _selectedUTXOs.remove(utxo); + } + }); + }, + ); + }, + ) + : ListView.separated( + itemCount: _map!.entries.length, + separatorBuilder: (context, _) => const SizedBox( + height: 10, + ), + itemBuilder: (context, index) { + final entry = _map!.entries.elementAt(index); + final _controller = RotateIconController(); + + return Expandable2( + border: Theme.of(context) + .extension()! + .backgroundAppBar, + background: Theme.of(context) + .extension()! + .popupBG, + animationDurationMultiplier: + 0.2 * entry.value.length, + onExpandWillChange: (state) { + if (state == Expandable2State.expanded) { + _controller.forward?.call(); + } else { + _controller.reverse?.call(); + } + }, + header: RoundedContainer( + padding: const EdgeInsets.all(20), + color: Colors.transparent, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.iconFor(coin: coin), + width: 24, + height: 24, + ), + const SizedBox( + width: 12, + ), + Expanded( + flex: 3, + child: Text( + entry.key, + style: STextStyles.w600_14(context), + ), + ), + Expanded( + child: Text( + "${entry.value.length} " + "output${entry.value.length > 1 ? "s" : ""}", + style: STextStyles + .desktopTextExtraExtraSmall( + context), + ), + ), + RotateIcon( + animationDurationMultiplier: + 0.2 * entry.value.length, + icon: SvgPicture.asset( + Assets.svg.chevronDown, + width: 14, + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + curve: Curves.easeInOut, + controller: _controller, + ), + ], + ), + ), + children: entry.value.map( + (id) { + final utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(id) + .findFirstSync()!; + final data = UtxoRowData(utxo.id, false); + data.selected = + _selectedUTXOsData.contains(data); + + return UtxoRow( + key: Key( + "${utxo.walletId}_${utxo.id}_${utxo.isBlocked}"), + data: data, + compact: true, + compactWithBorder: false, + raiseOnSelected: false, + walletId: widget.walletId, + onSelectionChanged: (value) { + setState(() { + if (data.selected) { + _selectedUTXOsData.add(value); + _selectedUTXOs.add(utxo); + } else { + _selectedUTXOsData.remove(value); + _selectedUTXOs.remove(utxo); + } + }); + }, + ); + }, + ).toList(), + ); + }, + ), + ), + const SizedBox( + height: 16, + ), + RoundedContainer( + color: Theme.of(context) + .extension()! + .textFieldDefaultBG, + padding: EdgeInsets.zero, + child: ConditionalParent( + condition: widget.amountToSend != null, + builder: (child) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + child, + Container( + height: 1.2, + color: Theme.of(context) + .extension()! + .popupBG, + ), + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Amount to send", + style: + STextStyles.desktopTextExtraExtraSmall( + context) + .copyWith( + color: Theme.of(context) + .extension()! + .textDark, + ), + ), + Text( + "${widget.amountToSend!.toStringAsFixed( + coin.decimals, + )}" + " ${coin.ticker}", + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: Theme.of(context) + .extension()! + .textDark, + ), + ), + ], + ), + ), + ], + ); + }, + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Selected amount", + style: STextStyles.desktopTextExtraExtraSmall( + context) + .copyWith( + color: Theme.of(context) + .extension()! + .textDark, + ), + ), + Text( + "${selectedSum.toStringAsFixed( + coin.decimals, + )} ${coin.ticker}", + style: STextStyles.desktopTextExtraExtraSmall( + context) + .copyWith( + color: widget.amountToSend == null + ? Theme.of(context) + .extension()! + .textDark + : selectedSum < widget.amountToSend! + ? Theme.of(context) + .extension()! + .accentColorRed + : Theme.of(context) + .extension()! + .accentColorGreen, + ), + ), + ], + ), + ), + ), + ), + const SizedBox( + height: 16, + ), + Row( + children: [ + Expanded( + child: SecondaryButton( + enabled: _selectedUTXOsData.isNotEmpty, + buttonHeight: ButtonHeight.l, + label: _selectedUTXOsData.isEmpty + ? "Clear selection" + : "Clear selection (${_selectedUTXOsData.length})", + onPressed: () { + setState(() { + _selectedUTXOsData.clear(); + _selectedUTXOs.clear(); + }); + }, + ), + ), + const SizedBox( + width: 20, + ), + Expanded( + child: PrimaryButton( + enabled: enableApply, + buttonHeight: ButtonHeight.l, + label: "Apply", + onPressed: () { + ref.read(desktopUseUTXOs.state).state = + _selectedUTXOs; + + Navigator.of(context, rootNavigator: true).pop(); + }, + ), + ), + ], + ), + const SizedBox( + height: 16, + ), + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages_desktop_specific/coin_control/desktop_coin_control_view.dart b/lib/pages_desktop_specific/coin_control/desktop_coin_control_view.dart new file mode 100644 index 000000000..cf27cc80e --- /dev/null +++ b/lib/pages_desktop_specific/coin_control/desktop_coin_control_view.dart @@ -0,0 +1,420 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:isar/isar.dart'; +import 'package:stackwallet/db/main_db.dart'; +import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart'; +import 'package:stackwallet/pages_desktop_specific/coin_control/freeze_button.dart'; +import 'package:stackwallet/pages_desktop_specific/coin_control/utxo_row.dart'; +import 'package:stackwallet/providers/global/wallets_provider.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/animated_widgets/rotate_icon.dart'; +import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/custom_buttons/dropdown_button.dart'; +import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart'; +import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/expandable2.dart'; +import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; +import 'package:stackwallet/widgets/rounded_container.dart'; +import 'package:stackwallet/widgets/stack_text_field.dart'; +import 'package:stackwallet/widgets/textfield_icon_button.dart'; + +class DesktopCoinControlView extends ConsumerStatefulWidget { + const DesktopCoinControlView({ + Key? key, + required this.walletId, + }) : super(key: key); + + static const String routeName = "/desktopCoinControl"; + + final String walletId; + + @override + ConsumerState createState() => + _DesktopCoinControlViewState(); +} + +class _DesktopCoinControlViewState + extends ConsumerState { + late final TextEditingController _searchController; + late final Coin coin; + final searchFieldFocusNode = FocusNode(); + + final Set _selectedUTXOs = {}; + + Map>? _map; + List? _list; + + String _searchString = ""; + + CCFilter _filter = CCFilter.all; + CCSortDescriptor _sort = CCSortDescriptor.age; + + @override + void initState() { + _searchController = TextEditingController(); + coin = ref + .read(walletsChangeNotifierProvider) + .getManager(widget.walletId) + .coin; + super.initState(); + } + + @override + void dispose() { + _searchController.dispose(); + searchFieldFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + + if (_sort == CCSortDescriptor.address) { + _list = null; + _map = MainDB.instance.queryUTXOsGroupedByAddressSync( + walletId: widget.walletId, + filter: _filter, + sort: _sort, + searchTerm: _searchString, + coin: coin, + ); + } else { + _map = null; + _list = MainDB.instance.queryUTXOsSync( + walletId: widget.walletId, + filter: _filter, + sort: _sort, + searchTerm: _searchString, + coin: coin, + ); + } + + return DesktopScaffold( + appBar: DesktopAppBar( + background: Theme.of(context).extension()!.popupBG, + leading: Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox( + width: 32, + ), + AppBarIconButton( + size: 32, + color: Theme.of(context) + .extension()! + .textFieldDefaultBG, + shadows: const [], + icon: SvgPicture.asset( + Assets.svg.arrowLeft, + width: 18, + height: 18, + color: Theme.of(context) + .extension()! + .topNavIconPrimary, + ), + onPressed: Navigator.of(context).pop, + ), + const SizedBox( + width: 18, + ), + SvgPicture.asset( + Assets.svg.coinControl.gamePad, + width: 32, + height: 32, + color: + Theme.of(context).extension()!.textSubtitle1, + ), + const SizedBox( + width: 12, + ), + Text( + "Coin control", + style: STextStyles.desktopH3(context), + ), + ], + ), + ), + useSpacers: false, + isCompactHeight: true, + ), + body: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: Row( + children: [ + Expanded( + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: false, + enableSuggestions: false, + controller: _searchController, + focusNode: searchFieldFocusNode, + onChanged: (value) { + setState(() { + _searchString = value; + }); + }, + style: + STextStyles.desktopTextExtraSmall(context).copyWith( + color: Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ), + decoration: standardInputDecoration( + "Search...", + searchFieldFocusNode, + context, + desktopMed: true, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 18, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 20, + height: 20, + ), + ), + suffixIcon: _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchString = ""; + }); + }, + ), + ], + ), + ), + ) + : null, + ), + ), + ), + ), + const SizedBox( + width: 24, + ), + AnimatedCrossFade( + firstChild: JDropdownButton( + redrawOnScreenSizeChanged: true, + showIcon: true, + width: 200, + items: CCFilter.values.toSet(), + groupValue: _filter, + onSelectionChanged: (CCFilter? newValue) { + if (newValue != null && newValue != _filter) { + setState(() { + _filter = newValue; + }); + } + }, + ), + secondChild: FreezeButton( + key: Key("${_selectedUTXOs.length}"), + selectedUTXOs: _selectedUTXOs, + ), + crossFadeState: _selectedUTXOs.isEmpty + ? CrossFadeState.showFirst + : CrossFadeState.showSecond, + duration: const Duration( + milliseconds: 200, + ), + ), + const SizedBox( + width: 24, + ), + AnimatedCrossFade( + firstChild: JDropdownButton( + redrawOnScreenSizeChanged: true, + label: "Sort by...", + width: 200, + groupValue: _sort, + items: CCSortDescriptor.values.toSet(), + onSelectionChanged: (CCSortDescriptor? newValue) { + if (newValue != null && newValue != _sort) { + setState(() { + _sort = newValue; + }); + } + }, + ), + secondChild: SecondaryButton( + buttonHeight: ButtonHeight.l, + width: 200, + label: "Clear selection (${_selectedUTXOs.length})", + onPressed: () => setState(() => _selectedUTXOs.clear()), + ), + crossFadeState: _selectedUTXOs.isEmpty + ? CrossFadeState.showFirst + : CrossFadeState.showSecond, + duration: const Duration( + milliseconds: 200, + ), + ), + ], + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 24, + ), + child: _list != null + ? ListView.separated( + itemCount: _list!.length, + separatorBuilder: (context, _) => const SizedBox( + height: 10, + ), + itemBuilder: (context, index) { + final utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(_list![index]) + .findFirstSync()!; + final data = UtxoRowData(utxo.id, false); + data.selected = _selectedUTXOs.contains(data); + + return UtxoRow( + key: Key( + "${utxo.walletId}_${utxo.id}_${utxo.isBlocked}"), + data: data, + walletId: widget.walletId, + onSelectionChanged: (value) { + setState(() { + if (data.selected) { + _selectedUTXOs.add(value); + } else { + _selectedUTXOs.remove(value); + } + }); + }, + ); + }, + ) + : ListView.separated( + itemCount: _map!.entries.length, + separatorBuilder: (context, _) => const SizedBox( + height: 10, + ), + itemBuilder: (context, index) { + final entry = _map!.entries.elementAt(index); + final _controller = RotateIconController(); + + return Expandable2( + border: Theme.of(context) + .extension()! + .backgroundAppBar, + background: Theme.of(context) + .extension()! + .popupBG, + animationDurationMultiplier: 0.2 * entry.value.length, + onExpandWillChange: (state) { + if (state == Expandable2State.expanded) { + _controller.forward?.call(); + } else { + _controller.reverse?.call(); + } + }, + header: RoundedContainer( + padding: const EdgeInsets.all(20), + color: Colors.transparent, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.iconFor(coin: coin), + width: 24, + height: 24, + ), + const SizedBox( + width: 12, + ), + Expanded( + child: Text( + entry.key, + style: STextStyles.w600_14(context), + ), + ), + Expanded( + child: Text( + "${entry.value.length} " + "output${entry.value.length > 1 ? "s" : ""}", + style: + STextStyles.desktopTextExtraExtraSmall( + context), + ), + ), + RotateIcon( + animationDurationMultiplier: + 0.2 * entry.value.length, + icon: SvgPicture.asset( + Assets.svg.chevronDown, + width: 14, + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + curve: Curves.easeInOut, + controller: _controller, + ), + ], + ), + ), + children: entry.value.map( + (id) { + final utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(id) + .findFirstSync()!; + final data = UtxoRowData(utxo.id, false); + data.selected = _selectedUTXOs.contains(data); + + return UtxoRow( + key: Key( + "${utxo.walletId}_${utxo.id}_${utxo.isBlocked}"), + data: data, + walletId: widget.walletId, + raiseOnSelected: false, + onSelectionChanged: (value) { + setState(() { + if (data.selected) { + _selectedUTXOs.add(value); + } else { + _selectedUTXOs.remove(value); + } + }); + }, + ); + }, + ).toList(), + ); + }, + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages_desktop_specific/coin_control/freeze_button.dart b/lib/pages_desktop_specific/coin_control/freeze_button.dart new file mode 100644 index 000000000..f50e4661e --- /dev/null +++ b/lib/pages_desktop_specific/coin_control/freeze_button.dart @@ -0,0 +1,117 @@ +import 'package:async/async.dart'; +import 'package:flutter/material.dart'; +import 'package:isar/isar.dart'; +import 'package:stackwallet/db/main_db.dart'; +import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart'; +import 'package:stackwallet/pages_desktop_specific/coin_control/utxo_row.dart'; +import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; + +class FreezeButton extends StatefulWidget { + const FreezeButton({ + Key? key, + required this.selectedUTXOs, + }) : super(key: key); + + final Set selectedUTXOs; + + @override + State createState() => _FreezeButtonState(); +} + +class _FreezeButtonState extends State { + String _freezeLabelCache = "Freeze"; + + String _freezeLabel(Set dataSet) { + if (dataSet.isEmpty) return _freezeLabelCache; + + bool hasUnblocked = false; + for (final data in dataSet) { + if (!MainDB.instance.isar.utxos + .where() + .idEqualTo(data.utxoId) + .findFirstSync()! + .isBlocked) { + hasUnblocked = true; + break; + } + } + _freezeLabelCache = hasUnblocked ? "Freeze" : "Unfreeze"; + return _freezeLabelCache; + } + + Future _onFreezeStateButtonPressed() async { + List utxosToUpdate = []; + switch (_freezeLabelCache) { + case "Freeze": + for (final e in widget.selectedUTXOs) { + final utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(e.utxoId) + .findFirstSync()!; + if (!utxo.isBlocked) { + utxosToUpdate.add(utxo.copyWith(isBlocked: true)); + } + } + break; + + case "Unfreeze": + for (final e in widget.selectedUTXOs) { + final utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(e.utxoId) + .findFirstSync()!; + if (utxo.isBlocked) { + utxosToUpdate.add(utxo.copyWith(isBlocked: false)); + } + } + break; + + default: + Logging.instance.log( + "Unknown utxo method name found in $runtimeType", + level: LogLevel.Fatal, + ); + return; + } + + // final update utxo set in db + if (utxosToUpdate.isNotEmpty) { + await MainDB.instance.putUTXOs(utxosToUpdate); + } + } + + late Stream bigStream; + + @override + void initState() { + List> streams = []; + for (final data in widget.selectedUTXOs) { + final stream = MainDB.instance.watchUTXO(id: data.utxoId); + + streams.add(stream); + } + + bigStream = StreamGroup.merge(streams); + bigStream.listen((event) { + if (mounted) { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + setState(() {}); + }); + } + }); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + return PrimaryButton( + buttonHeight: ButtonHeight.l, + width: 200, + label: _freezeLabel(widget.selectedUTXOs), + onPressed: _onFreezeStateButtonPressed, + ); + } +} diff --git a/lib/pages_desktop_specific/coin_control/utxo_row.dart b/lib/pages_desktop_specific/coin_control/utxo_row.dart new file mode 100644 index 000000000..e5ddf2f06 --- /dev/null +++ b/lib/pages_desktop_specific/coin_control/utxo_row.dart @@ -0,0 +1,214 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:isar/isar.dart'; +import 'package:stackwallet/db/main_db.dart'; +import 'package:stackwallet/models/isar/models/isar_models.dart'; +import 'package:stackwallet/pages/coin_control/utxo_details_view.dart'; +import 'package:stackwallet/providers/global/wallets_provider.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/format.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/conditional_parent.dart'; +import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/icon_widgets/utxo_status_icon.dart'; +import 'package:stackwallet/widgets/rounded_container.dart'; + +class UtxoRowData { + UtxoRowData(this.utxoId, this.selected); + + Id utxoId; + bool selected; + + @override + String toString() { + return "selected=$selected: $utxoId"; + } + + @override + bool operator ==(Object other) { + return other is UtxoRowData && other.utxoId == utxoId; + } + + @override + int get hashCode => Object.hashAll([utxoId.hashCode]); +} + +class UtxoRow extends ConsumerStatefulWidget { + const UtxoRow({ + Key? key, + required this.data, + required this.walletId, + this.onSelectionChanged, + this.compact = false, + this.compactWithBorder = true, + this.raiseOnSelected = true, + }) : super(key: key); + + final String walletId; + final UtxoRowData data; + final void Function(UtxoRowData)? onSelectionChanged; + final bool compact; + final bool compactWithBorder; + final bool raiseOnSelected; + + @override + ConsumerState createState() => _UtxoRowState(); +} + +class _UtxoRowState extends ConsumerState { + late Stream stream; + late UTXO utxo; + + void _details() async { + await showDialog( + context: context, + builder: (context) => UtxoDetailsView( + utxoId: utxo.id, + walletId: widget.walletId, + ), + ); + } + + @override + void initState() { + utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(widget.data.utxoId) + .findFirstSync()!; + + stream = MainDB.instance.watchUTXO(id: utxo.id); + super.initState(); + } + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + + final coin = ref.watch(walletsChangeNotifierProvider + .select((value) => value.getManager(widget.walletId).coin)); + + final currentChainHeight = ref.watch(walletsChangeNotifierProvider + .select((value) => value.getManager(widget.walletId).currentHeight)); + + return StreamBuilder( + stream: stream, + builder: (context, snapshot) { + if (snapshot.hasData) { + utxo = snapshot.data!; + } + + return RoundedContainer( + borderColor: widget.compact && widget.compactWithBorder + ? Theme.of(context).extension()!.textFieldDefaultBG + : null, + color: Theme.of(context).extension()!.popupBG, + boxShadow: widget.data.selected && widget.raiseOnSelected + ? [ + Theme.of(context).extension()!.standardBoxShadow, + ] + : null, + child: Row( + children: [ + if (!(widget.compact && utxo.isBlocked)) + Checkbox( + value: widget.data.selected, + onChanged: (value) { + setState(() { + widget.data.selected = value!; + }); + widget.onSelectionChanged?.call(widget.data); + }, + ), + if (!(widget.compact && utxo.isBlocked)) + const SizedBox( + width: 10, + ), + UTXOStatusIcon( + blocked: utxo.isBlocked, + status: utxo.isConfirmed( + currentChainHeight, + coin.requiredConfirmations, + ) + ? UTXOStatusIconStatus.confirmed + : UTXOStatusIconStatus.unconfirmed, + background: Theme.of(context).extension()!.popupBG, + selected: false, + width: 32, + height: 32, + ), + const SizedBox( + width: 10, + ), + if (!widget.compact) + Text( + "${Format.satoshisToAmount( + utxo.value, + coin: coin, + ).toStringAsFixed(coin.decimals)} ${coin.ticker}", + textAlign: TextAlign.right, + style: STextStyles.w600_14(context), + ), + if (!widget.compact) + const SizedBox( + width: 10, + ), + Expanded( + child: ConditionalParent( + condition: widget.compact, + builder: (child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "${Format.satoshisToAmount( + utxo.value, + coin: coin, + ).toStringAsFixed(coin.decimals)} ${coin.ticker}", + textAlign: TextAlign.right, + style: STextStyles.w600_14(context), + ), + const SizedBox( + height: 2, + ), + child, + ], + ); + }, + child: Text( + utxo.name.isNotEmpty + ? utxo.name + : utxo.address ?? utxo.txid, + textAlign: + widget.compact ? TextAlign.left : TextAlign.center, + style: STextStyles.w500_12(context).copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + ), + ), + const SizedBox( + width: 10, + ), + widget.compact + ? CustomTextButton( + text: "Details", + onTap: _details, + ) + : SecondaryButton( + width: 120, + buttonHeight: ButtonHeight.xs, + label: "Details", + onPressed: _details, + ), + ], + ), + ); + }, + ); + } +} diff --git a/lib/pages_desktop_specific/desktop_home_view.dart b/lib/pages_desktop_specific/desktop_home_view.dart index e9092fe2d..fa7076572 100644 --- a/lib/pages_desktop_specific/desktop_home_view.dart +++ b/lib/pages_desktop_specific/desktop_home_view.dart @@ -89,10 +89,11 @@ class _DesktopHomeViewState extends ConsumerState { ), }; - DesktopMenuItemId prev = DesktopMenuItemId.myStack; - void onMenuSelectionWillChange(DesktopMenuItemId newKey) { - if (prev == DesktopMenuItemId.myStack && prev == newKey) { + // handle logging out of active wallet + if (ref.read(prevDesktopMenuItemProvider.state).state == + DesktopMenuItemId.myStack && + ref.read(prevDesktopMenuItemProvider.state).state == newKey) { Navigator.of(myStackViewNavKey.currentContext!) .popUntil(ModalRoute.withName(MyStackView.routeName)); if (ref.read(currentWalletIdProvider.state).state != null) { @@ -111,7 +112,7 @@ class _DesktopHomeViewState extends ConsumerState { ref.read(managerProvider.notifier).isActiveWallet = false; } } - prev = newKey; + ref.read(prevDesktopMenuItemProvider.state).state = newKey; // check for unread notifications and refresh provider before // showing notifications view diff --git a/lib/pages_desktop_specific/desktop_menu_item.dart b/lib/pages_desktop_specific/desktop_menu_item.dart index 3e2fa015c..5a00bbe95 100644 --- a/lib/pages_desktop_specific/desktop_menu_item.dart +++ b/lib/pages_desktop_specific/desktop_menu_item.dart @@ -61,7 +61,7 @@ class DesktopBuyIcon extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return SvgPicture.asset( - Assets.svg.buyDesktop, + Assets.svg.buy(context), width: 20, height: 20, color: DesktopMenuItemId.buy == diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart index ec3b1b3ec..f5b120871 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart @@ -1,47 +1,32 @@ import 'dart:async'; -import 'package:decimal/decimal.dart'; import 'package:event_bus/event_bus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:stackwallet/notifications/show_flush_bar.dart'; -import 'package:stackwallet/pages/paynym/paynym_claim_view.dart'; -import 'package:stackwallet/pages/paynym/paynym_home_view.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart'; +import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/my_wallet.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/network_info_button.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/recent_desktop_transactions.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_keys_button.dart'; import 'package:stackwallet/providers/global/auto_swb_service_provider.dart'; -import 'package:stackwallet/providers/global/paynym_api_provider.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/ui/transaction_filter_provider.dart'; -import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart'; -import 'package:stackwallet/services/coins/firo/firo_wallet.dart'; import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/global_event_bus.dart'; -import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/backup_frequency_type.dart'; -import 'package:stackwallet/utilities/enums/coin_enum.dart'; -import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; -import 'package:stackwallet/utilities/logger.dart'; -import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/custom_loading_overlay.dart'; import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart'; -import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart'; -import 'package:stackwallet/widgets/desktop/primary_button.dart'; -import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/hover_text_field.dart'; -import 'package:stackwallet/widgets/loading_indicator.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; /// [eventBus] should only be set during testing @@ -92,162 +77,6 @@ class _DesktopWalletViewState extends ConsumerState { ref.read(managerProvider.notifier).isActiveWallet = false; } - Future attemptAnonymize() async { - final managerProvider = ref - .read(walletsChangeNotifierProvider) - .getManagerProvider(widget.walletId); - - bool shouldPop = false; - unawaited( - showDialog( - context: context, - builder: (context) => WillPopScope( - child: const CustomLoadingOverlay( - message: "Anonymizing balance", - eventBus: null, - ), - onWillPop: () async => shouldPop, - ), - ), - ); - final firoWallet = ref.read(managerProvider).wallet as FiroWallet; - - final publicBalance = await firoWallet.availablePublicBalance(); - if (publicBalance <= Decimal.zero) { - shouldPop = true; - if (mounted) { - Navigator.of(context, rootNavigator: true).pop(); - Navigator.of(context).popUntil( - ModalRoute.withName(DesktopWalletView.routeName), - ); - unawaited( - showFloatingFlushBar( - type: FlushBarType.info, - message: "No funds available to anonymize!", - context: context, - ), - ); - } - return; - } - - try { - await firoWallet.anonymizeAllPublicFunds(); - shouldPop = true; - if (mounted) { - Navigator.of(context, rootNavigator: true).pop(); - Navigator.of(context).popUntil( - ModalRoute.withName(DesktopWalletView.routeName), - ); - unawaited( - showFloatingFlushBar( - type: FlushBarType.success, - message: "Anonymize transaction submitted", - context: context, - ), - ); - } - } catch (e) { - shouldPop = true; - if (mounted) { - Navigator.of(context, rootNavigator: true).pop(); - Navigator.of(context).popUntil( - ModalRoute.withName(DesktopWalletView.routeName), - ); - await showDialog( - context: context, - builder: (_) => DesktopDialog( - maxWidth: 400, - maxHeight: 300, - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Anonymize all failed", - style: STextStyles.desktopH3(context), - ), - const Spacer( - flex: 1, - ), - Text( - "Reason: $e", - style: STextStyles.desktopTextSmall(context), - ), - const Spacer( - flex: 2, - ), - Row( - children: [ - const Spacer(), - const SizedBox( - width: 16, - ), - Expanded( - child: PrimaryButton( - label: "Ok", - buttonHeight: ButtonHeight.l, - onPressed: - Navigator.of(context, rootNavigator: true).pop, - ), - ), - ], - ) - ], - ), - ), - ), - ); - } - } - } - - Future onPaynymButtonPressed() async { - unawaited( - showDialog( - context: context, - builder: (context) => const LoadingIndicator( - width: 100, - ), - ), - ); - - final manager = - ref.read(walletsChangeNotifierProvider).getManager(widget.walletId); - - final wallet = manager.wallet as PaynymWalletInterface; - - final code = - await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(manager.coin)); - - final account = await ref.read(paynymAPIProvider).nym(code.toString()); - - Logging.instance.log( - "my nym account: $account", - level: LogLevel.Info, - ); - - if (mounted) { - Navigator.of(context, rootNavigator: true).pop(); - - // check if account exists and for matching code to see if claimed - if (account.value != null && account.value!.codes.first.claimed) { - ref.read(myPaynymAccountStateProvider.state).state = account.value!; - - await Navigator.of(context).pushNamed( - PaynymHomeView.routeName, - arguments: widget.walletId, - ); - } else { - await Navigator.of(context).pushNamed( - PaynymClaimView.routeName, - arguments: widget.walletId, - ); - } - } - } - @override void initState() { controller = TextEditingController(); @@ -411,122 +240,15 @@ class _DesktopWalletViewState extends ConsumerState { ), DesktopWalletSummary( walletId: widget.walletId, - managerProvider: managerProvider, initialSyncStatus: ref.watch(managerProvider .select((value) => value.isRefreshing)) ? WalletSyncStatus.syncing : WalletSyncStatus.synced, ), const Spacer(), - if (coin == Coin.firo) const SizedBox(width: 10), - if (coin == Coin.firo) - SecondaryButton( - width: 180, - buttonHeight: ButtonHeight.l, - label: "Anonymize funds", - onPressed: () async { - await showDialog( - context: context, - barrierDismissible: false, - builder: (context) => DesktopDialog( - maxWidth: 500, - maxHeight: 210, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, vertical: 20), - child: Column( - children: [ - Text( - "Attention!", - style: STextStyles.desktopH2(context), - ), - const SizedBox(height: 16), - Text( - "You're about to anonymize all of your public funds.", - style: - STextStyles.desktopTextSmall(context), - ), - const SizedBox(height: 32), - Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - SecondaryButton( - width: 200, - buttonHeight: ButtonHeight.l, - label: "Cancel", - onPressed: () { - Navigator.of(context).pop(); - }, - ), - const SizedBox(width: 20), - PrimaryButton( - width: 200, - buttonHeight: ButtonHeight.l, - label: "Continue", - onPressed: () { - Navigator.of(context).pop(); - - unawaited(attemptAnonymize()); - }, - ) - ], - ), - ], - ), - ), - ), - ); - }, - ), - if (ref.watch(walletsChangeNotifierProvider.select( - (value) => value - .getManager(widget.walletId) - .hasPaynymSupport))) - SecondaryButton( - label: "PayNym", - width: 160, - buttonHeight: ButtonHeight.l, - icon: SvgPicture.asset( - Assets.svg.user, - height: 20, - width: 20, - color: Theme.of(context) - .extension()! - .buttonTextSecondary, - ), - onPressed: onPaynymButtonPressed, - ), - // if (coin == Coin.firo) const SizedBox(width: 16), - // SecondaryButton( - // width: 180, - // buttonHeight: ButtonHeight.l, - // onPressed: () { - // _onExchangePressed(context); - // }, - // label: "Swap", - // icon: Container( - // width: 24, - // height: 24, - // decoration: BoxDecoration( - // borderRadius: BorderRadius.circular(24), - // color: Theme.of(context) - // .extension()! - // .buttonBackPrimary - // .withOpacity(0.2), - // ), - // child: Center( - // child: SvgPicture.asset( - // Assets.svg.arrowRotate2, - // width: 14, - // height: 14, - // color: Theme.of(context) - // .extension()! - // .buttonTextSecondary, - // ), - // ), - // ), - // ), + DesktopWalletFeatures( + walletId: widget.walletId, + ), ], ), ), diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart index 9c890b223..474c1a077 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart @@ -4,6 +4,7 @@ import 'package:stackwallet/providers/wallet/wallet_balance_toggle_state_provide import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/wallet_balance_toggle_state.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; class DesktopBalanceToggleButton extends ConsumerWidget { @@ -18,7 +19,7 @@ class DesktopBalanceToggleButton extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return SizedBox( height: 22, - width: 22, + width: 80, child: MaterialButton( color: Theme.of(context).extension()!.buttonBackSecondary, splashColor: Theme.of(context).extension()!.highlight, @@ -43,10 +44,63 @@ class DesktopBalanceToggleButton extends ConsumerWidget { Constants.size.circularBorderRadius, ), ), + child: Center( + child: FittedBox( + child: Text( + ref.watch(walletBalanceToggleStateProvider.state).state == + WalletBalanceToggleState.available + ? "AVAILABLE" + : "FULL", + style: STextStyles.w500_10(context), + ), + ), + ), + ), + ); + } +} + +class DesktopPrivateBalanceToggleButton extends ConsumerWidget { + const DesktopPrivateBalanceToggleButton({ + Key? key, + this.onPressed, + }) : super(key: key); + + final VoidCallback? onPressed; + + @override + Widget build(BuildContext context, WidgetRef ref) { + return SizedBox( + height: 22, + width: 22, + child: MaterialButton( + color: Theme.of(context).extension()!.buttonBackSecondary, + splashColor: Theme.of(context).extension()!.highlight, + onPressed: () { + if (ref.read(walletPrivateBalanceToggleStateProvider.state).state == + WalletBalanceToggleState.available) { + ref.read(walletPrivateBalanceToggleStateProvider.state).state = + WalletBalanceToggleState.full; + } else { + ref.read(walletPrivateBalanceToggleStateProvider.state).state = + WalletBalanceToggleState.available; + } + onPressed?.call(); + }, + elevation: 0, + highlightElevation: 0, + hoverElevation: 0, + padding: EdgeInsets.zero, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), child: Center( child: Image( image: AssetImage( - ref.watch(walletBalanceToggleStateProvider.state).state == + ref.watch(walletPrivateBalanceToggleStateProvider.state).state == WalletBalanceToggleState.available ? Assets.png.glassesHidden : Assets.png.glasses, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart index 1fc322062..97375f2e7 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart @@ -13,6 +13,7 @@ import 'package:stackwallet/models/send_view_auto_fill_data.dart'; import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart'; import 'package:stackwallet/pages/send_view/sub_widgets/building_transaction_dialog.dart'; import 'package:stackwallet/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart'; +import 'package:stackwallet/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart'; @@ -44,6 +45,7 @@ import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/icon_widgets/addressbook_icon.dart'; import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart'; import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; +import 'package:stackwallet/widgets/rounded_container.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; @@ -120,128 +122,142 @@ class _DesktopSendState extends ConsumerState { Format.decimalAmountToSatoshis(manager.balance.getSpendable(), coin); } - // confirm send all - if (amount == availableBalance) { - final bool? shouldSendAll = await showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return DesktopDialog( - maxWidth: 450, - maxHeight: double.infinity, - child: Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 32, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Confirm send all", - style: STextStyles.desktopH3(context), - ), - const DesktopDialogCloseButton(), - ], - ), - const SizedBox( - height: 12, - ), - Padding( - padding: const EdgeInsets.only( - right: 32, - ), - child: Text( - "You are about to send your entire balance. Would you like to continue?", - textAlign: TextAlign.left, - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - fontSize: 18, - ), - ), - ), - const SizedBox( - height: 40, - ), - Padding( - padding: const EdgeInsets.only( - right: 32, - ), - child: Row( - children: [ - Expanded( - child: SecondaryButton( - buttonHeight: ButtonHeight.l, - label: "Cancel", - onPressed: () { - Navigator.of(context).pop(false); - }, - ), - ), - const SizedBox( - width: 16, - ), - Expanded( - child: PrimaryButton( - buttonHeight: ButtonHeight.l, - label: "Yes", - onPressed: () { - Navigator.of(context).pop(true); + final coinControlEnabled = + ref.read(prefsChangeNotifierProvider).enableCoinControl; - setState(() { - sendToController.text = ""; - cryptoAmountController.text = ""; - baseAmountController.text = ""; - }); - }, - ), + if (!(manager.hasCoinControlSupport && coinControlEnabled) || + (manager.hasCoinControlSupport && + coinControlEnabled && + ref.read(desktopUseUTXOs).isEmpty)) { + // confirm send all + if (amount == availableBalance) { + final bool? shouldSendAll = await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return DesktopDialog( + maxWidth: 450, + maxHeight: double.infinity, + child: Padding( + padding: const EdgeInsets.only( + left: 32, + bottom: 32, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Confirm send all", + style: STextStyles.desktopH3(context), ), + const DesktopDialogCloseButton(), ], ), - ), - ], + const SizedBox( + height: 12, + ), + Padding( + padding: const EdgeInsets.only( + right: 32, + ), + child: Text( + "You are about to send your entire balance. Would you like to continue?", + textAlign: TextAlign.left, + style: STextStyles.desktopTextExtraExtraSmall(context) + .copyWith( + fontSize: 18, + ), + ), + ), + const SizedBox( + height: 40, + ), + Padding( + padding: const EdgeInsets.only( + right: 32, + ), + child: Row( + children: [ + Expanded( + child: SecondaryButton( + buttonHeight: ButtonHeight.l, + label: "Cancel", + onPressed: () { + Navigator.of(context).pop(false); + }, + ), + ), + const SizedBox( + width: 16, + ), + Expanded( + child: PrimaryButton( + buttonHeight: ButtonHeight.l, + label: "Yes", + onPressed: () { + Navigator.of(context).pop(true); + }, + ), + ), + ], + ), + ), + ], + ), ), - ), - ); - }, - ); + ); + }, + ); - if (shouldSendAll == null || shouldSendAll == false) { - // cancel preview - return; + if (shouldSendAll == null || shouldSendAll == false) { + // cancel preview + return; + } } } try { bool wasCancelled = false; - unawaited(showDialog( - context: context, - useSafeArea: false, - barrierDismissible: false, - builder: (context) { - return DesktopDialog( - maxWidth: 400, - maxHeight: double.infinity, - child: Padding( - padding: const EdgeInsets.all(32), - child: BuildingTransactionDialog( - onCancel: () { - wasCancelled = true; + if (mounted) { + unawaited( + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: false, + builder: (context) { + return DesktopDialog( + maxWidth: 400, + maxHeight: double.infinity, + child: Padding( + padding: const EdgeInsets.all(32), + child: BuildingTransactionDialog( + coin: manager.coin, + onCancel: () { + wasCancelled = true; - Navigator.of(context).pop(); - }, - ), - ), - ); - }, - )); + Navigator.of(context).pop(); + }, + ), + ), + ); + }, + ), + ); + } + + final time = Future.delayed( + const Duration( + milliseconds: 2500, + ), + ); Map txData; + Future> txDataFuture; if (isPaynymSend) { final wallet = manager.wallet as PaynymWalletInterface; @@ -250,27 +266,55 @@ class _DesktopSendState extends ConsumerState { wallet.networkType, ); final feeRate = ref.read(feeRateTypeStateProvider); - txData = await wallet.preparePaymentCodeSend( + txDataFuture = wallet.preparePaymentCodeSend( paymentCode: paymentCode, satoshiAmount: amount, - args: {"feeRate": feeRate}, + args: { + "feeRate": feeRate, + "UTXOs": (manager.hasCoinControlSupport && + coinControlEnabled && + ref.read(desktopUseUTXOs).isNotEmpty) + ? ref.read(desktopUseUTXOs) + : null, + }, ); } else if ((coin == Coin.firo || coin == Coin.firoTestNet) && ref.read(publicPrivateBalanceStateProvider.state).state != "Private") { - txData = await (manager.wallet as FiroWallet).prepareSendPublic( + txDataFuture = (manager.wallet as FiroWallet).prepareSendPublic( address: _address!, satoshiAmount: amount, - args: {"feeRate": ref.read(feeRateTypeStateProvider)}, + args: { + "feeRate": ref.read(feeRateTypeStateProvider), + "UTXOs": (manager.hasCoinControlSupport && + coinControlEnabled && + ref.read(desktopUseUTXOs).isNotEmpty) + ? ref.read(desktopUseUTXOs) + : null, + }, ); } else { - txData = await manager.prepareSend( + txDataFuture = manager.prepareSend( address: _address!, satoshiAmount: amount, - args: {"feeRate": ref.read(feeRateTypeStateProvider)}, + args: { + "feeRate": ref.read(feeRateTypeStateProvider), + "UTXOs": (manager.hasCoinControlSupport && + coinControlEnabled && + ref.read(desktopUseUTXOs).isNotEmpty) + ? ref.read(desktopUseUTXOs) + : null, + }, ); } + final results = await Future.wait([ + txDataFuture, + time, + ]); + + txData = results.first as Map; + if (!wasCancelled && mounted) { if (isPaynymSend) { txData["paynymAccountLite"] = widget.accountLite!; @@ -666,6 +710,16 @@ class _DesktopSendState extends ConsumerState { } } + void _showDesktopCoinControl() async { + await showDialog( + context: context, + builder: (context) => DesktopCoinControlUseDialog( + walletId: widget.walletId, + amountToSend: _amountToSend, + ), + ); + } + @override void initState() { WidgetsBinding.instance.addPostFrameCallback((_) { @@ -763,6 +817,17 @@ class _DesktopSendState extends ConsumerState { }); } + final showCoinControl = ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.enableCoinControl, + ), + ) && + ref.watch( + provider.select( + (value) => value.hasCoinControlSupport, + ), + ); + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -1039,6 +1104,31 @@ class _DesktopSendState extends ConsumerState { ), ), ), + if (showCoinControl) + const SizedBox( + height: 10, + ), + if (showCoinControl) + RoundedContainer( + color: Colors.transparent, + borderColor: + Theme.of(context).extension()!.textFieldDefaultBG, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Coin control", + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + CustomTextButton( + text: ref.watch(desktopUseUTXOs.state).state.isEmpty + ? "Select coins" + : "Selected coins (${ref.watch(desktopUseUTXOs.state).state.length})", + onTap: _showDesktopCoinControl, + ), + ], + ), + ), const SizedBox( height: 20, ), diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart new file mode 100644 index 000000000..5b1c3edce --- /dev/null +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart @@ -0,0 +1,374 @@ +import 'dart:async'; + +import 'package:decimal/decimal.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/notifications/show_flush_bar.dart'; +import 'package:stackwallet/pages/paynym/paynym_claim_view.dart'; +import 'package:stackwallet/pages/paynym/paynym_home_view.dart'; +import 'package:stackwallet/pages_desktop_specific/coin_control/desktop_coin_control_view.dart'; +import 'package:stackwallet/pages_desktop_specific/desktop_menu.dart'; +import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart'; +import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart'; +import 'package:stackwallet/providers/desktop/current_desktop_menu_item.dart'; +import 'package:stackwallet/providers/global/paynym_api_provider.dart'; +import 'package:stackwallet/providers/providers.dart'; +import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart'; +import 'package:stackwallet/services/coins/firo/firo_wallet.dart'; +import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart'; +import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/custom_loading_overlay.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/loading_indicator.dart'; + +class DesktopWalletFeatures extends ConsumerStatefulWidget { + const DesktopWalletFeatures({ + Key? key, + required this.walletId, + }) : super(key: key); + + final String walletId; + + @override + ConsumerState createState() => + _DesktopWalletFeaturesState(); +} + +class _DesktopWalletFeaturesState extends ConsumerState { + static const double buttonWidth = 120; + + Future _onSwapPressed() async { + ref.read(currentDesktopMenuItemProvider.state).state = + DesktopMenuItemId.exchange; + ref.read(prevDesktopMenuItemProvider.state).state = + DesktopMenuItemId.exchange; + } + + Future _onBuyPressed() async { + ref.read(currentDesktopMenuItemProvider.state).state = + DesktopMenuItemId.buy; + ref.read(prevDesktopMenuItemProvider.state).state = DesktopMenuItemId.buy; + } + + Future _onMorePressed() async { + await showDialog( + context: context, + builder: (_) => MoreFeaturesDialog( + walletId: widget.walletId, + onPaynymPressed: _onPaynymPressed, + onCoinControlPressed: _onCoinControlPressed, + onAnonymizeAllPressed: _onAnonymizeAllPressed, + onWhirlpoolPressed: _onWhirlpoolPressed, + ), + ); + } + + void _onWhirlpoolPressed() { + Navigator.of(context, rootNavigator: true).pop(); + } + + void _onCoinControlPressed() { + Navigator.of(context, rootNavigator: true).pop(); + + Navigator.of(context).pushNamed( + DesktopCoinControlView.routeName, + arguments: widget.walletId, + ); + } + + Future _onAnonymizeAllPressed() async { + Navigator.of(context, rootNavigator: true).pop(); + await showDialog( + context: context, + barrierDismissible: false, + builder: (context) => DesktopDialog( + maxWidth: 500, + maxHeight: 210, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 20), + child: Column( + children: [ + Text( + "Attention!", + style: STextStyles.desktopH2(context), + ), + const SizedBox(height: 16), + Text( + "You're about to anonymize all of your public funds.", + style: STextStyles.desktopTextSmall(context), + ), + const SizedBox(height: 32), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SecondaryButton( + width: 200, + buttonHeight: ButtonHeight.l, + label: "Cancel", + onPressed: () { + Navigator.of(context).pop(); + }, + ), + const SizedBox(width: 20), + PrimaryButton( + width: 200, + buttonHeight: ButtonHeight.l, + label: "Continue", + onPressed: () { + Navigator.of(context).pop(); + + unawaited( + _attemptAnonymize(), + ); + }, + ) + ], + ), + ], + ), + ), + ), + ); + } + + Future _attemptAnonymize() async { + final managerProvider = ref + .read(walletsChangeNotifierProvider) + .getManagerProvider(widget.walletId); + + bool shouldPop = false; + unawaited( + showDialog( + context: context, + builder: (context) => WillPopScope( + child: const CustomLoadingOverlay( + message: "Anonymizing balance", + eventBus: null, + ), + onWillPop: () async => shouldPop, + ), + ), + ); + final firoWallet = ref.read(managerProvider).wallet as FiroWallet; + + final publicBalance = firoWallet.availablePublicBalance(); + if (publicBalance <= Decimal.zero) { + shouldPop = true; + if (context.mounted) { + Navigator.of(context, rootNavigator: true).pop(); + Navigator.of(context).popUntil( + ModalRoute.withName(DesktopWalletView.routeName), + ); + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: "No funds available to anonymize!", + context: context, + ), + ); + } + return; + } + + try { + await firoWallet.anonymizeAllPublicFunds(); + shouldPop = true; + if (context.mounted) { + Navigator.of(context, rootNavigator: true).pop(); + Navigator.of(context).popUntil( + ModalRoute.withName(DesktopWalletView.routeName), + ); + unawaited( + showFloatingFlushBar( + type: FlushBarType.success, + message: "Anonymize transaction submitted", + context: context, + ), + ); + } + } catch (e) { + shouldPop = true; + if (context.mounted) { + Navigator.of(context, rootNavigator: true).pop(); + Navigator.of(context).popUntil( + ModalRoute.withName(DesktopWalletView.routeName), + ); + await showDialog( + context: context, + builder: (_) => DesktopDialog( + maxWidth: 400, + maxHeight: 300, + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Anonymize all failed", + style: STextStyles.desktopH3(context), + ), + const Spacer( + flex: 1, + ), + Text( + "Reason: $e", + style: STextStyles.desktopTextSmall(context), + ), + const Spacer( + flex: 2, + ), + Row( + children: [ + const Spacer(), + const SizedBox( + width: 16, + ), + Expanded( + child: PrimaryButton( + label: "Ok", + buttonHeight: ButtonHeight.l, + onPressed: + Navigator.of(context, rootNavigator: true).pop, + ), + ), + ], + ) + ], + ), + ), + ), + ); + } + } + } + + Future _onPaynymPressed() async { + Navigator.of(context, rootNavigator: true).pop(); + + unawaited( + showDialog( + context: context, + builder: (context) { + return const LoadingIndicator( + width: 100, + ); + }, + ), + ); + + final manager = + ref.read(walletsChangeNotifierProvider).getManager(widget.walletId); + + final wallet = manager.wallet as PaynymWalletInterface; + + final code = + await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(manager.coin)); + + final account = await ref.read(paynymAPIProvider).nym(code.toString()); + + Logging.instance.log( + "my nym account: $account", + level: LogLevel.Info, + ); + + if (context.mounted) { + Navigator.of(context, rootNavigator: true).pop(); + + // check if account exists and for matching code to see if claimed + if (account.value != null && account.value!.codes.first.claimed) { + ref.read(myPaynymAccountStateProvider.state).state = account.value!; + + await Navigator.of(context).pushNamed( + PaynymHomeView.routeName, + arguments: widget.walletId, + ); + } else { + await Navigator.of(context).pushNamed( + PaynymClaimView.routeName, + arguments: widget.walletId, + ); + } + } + } + + @override + Widget build(BuildContext context) { + final manager = ref.watch( + walletsChangeNotifierProvider.select( + (value) => value.getManager(widget.walletId), + ), + ); + + final showMore = manager.hasPaynymSupport || + manager.hasCoinControlSupport || + manager.coin == Coin.firo || + manager.coin == Coin.firoTestNet || + manager.hasWhirlpoolSupport; + + return Row( + children: [ + if (Constants.enableExchange) + SecondaryButton( + label: "Swap", + width: buttonWidth, + buttonHeight: ButtonHeight.l, + icon: SvgPicture.asset( + Assets.svg.arrowRotate, + height: 20, + width: 20, + color: Theme.of(context) + .extension()! + .buttonTextSecondary, + ), + onPressed: () => _onSwapPressed(), + ), + if (Constants.enableExchange) + const SizedBox( + width: 16, + ), + if (Constants.enableExchange) + SecondaryButton( + label: "Buy", + width: buttonWidth, + buttonHeight: ButtonHeight.l, + icon: SvgPicture.asset( + Assets.svg.buy(context), + height: 20, + width: 20, + color: Theme.of(context) + .extension()! + .buttonTextSecondary, + ), + onPressed: () => _onBuyPressed(), + ), + if (showMore) + const SizedBox( + width: 16, + ), + SecondaryButton( + label: "More", + width: buttonWidth, + buttonHeight: ButtonHeight.l, + icon: SvgPicture.asset( + Assets.svg.bars, + height: 20, + width: 20, + color: + Theme.of(context).extension()!.buttonTextSecondary, + ), + onPressed: () => _onMorePressed(), + ), + ], + ); + } +} diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart index f56e2160a..4d30ebc60 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart @@ -1,207 +1,154 @@ import 'package:decimal/decimal.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/pages/wallet_view/sub_widgets/wallet_refresh_button.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/wallet/wallet_balance_toggle_state_provider.dart'; import 'package:stackwallet/services/coins/firo/firo_wallet.dart'; -import 'package:stackwallet/services/coins/manager.dart'; import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/wallet_balance_toggle_state.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; -import 'package:stackwallet/widgets/animated_text.dart'; -class DesktopWalletSummary extends StatefulWidget { +class DesktopWalletSummary extends ConsumerStatefulWidget { const DesktopWalletSummary({ Key? key, required this.walletId, - required this.managerProvider, required this.initialSyncStatus, }) : super(key: key); final String walletId; - final ChangeNotifierProvider managerProvider; final WalletSyncStatus initialSyncStatus; @override - State createState() => _WDesktopWalletSummaryState(); + ConsumerState createState() => + _WDesktopWalletSummaryState(); } -class _WDesktopWalletSummaryState extends State { +class _WDesktopWalletSummaryState extends ConsumerState { late final String walletId; - late final ChangeNotifierProvider managerProvider; - - Decimal? _balanceTotalCached; - Decimal? _balanceCached; @override void initState() { walletId = widget.walletId; - managerProvider = widget.managerProvider; super.initState(); } @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); + + final externalCalls = ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.externalCalls, + ), + ); + final coin = ref.watch( + walletsChangeNotifierProvider.select( + (value) => value.getManager(widget.walletId).coin, + ), + ); + final locale = ref.watch( + localeServiceChangeNotifierProvider.select((value) => value.locale)); + + final baseCurrency = ref + .watch(prefsChangeNotifierProvider.select((value) => value.currency)); + + final priceTuple = ref.watch(priceAnd24hChangeNotifierProvider + .select((value) => value.getPrice(coin))); + + final _showAvailable = + ref.watch(walletBalanceToggleStateProvider.state).state == + WalletBalanceToggleState.available; + + Balance balance = ref.watch(walletsChangeNotifierProvider + .select((value) => value.getManager(walletId).balance)); + + Decimal balanceToShow; + if (coin == Coin.firo || coin == Coin.firoTestNet) { + Balance? balanceSecondary = ref + .watch( + walletsChangeNotifierProvider.select( + (value) => + value.getManager(widget.walletId).wallet as FiroWallet?, + ), + ) + ?.balancePrivate; + final showPrivate = + ref.watch(walletPrivateBalanceToggleStateProvider.state).state == + WalletBalanceToggleState.available; + + if (_showAvailable) { + balanceToShow = showPrivate + ? balanceSecondary!.getSpendable() + : balance.getSpendable(); + } else { + balanceToShow = + showPrivate ? balanceSecondary!.getTotal() : balance.getTotal(); + } + } else { + if (_showAvailable) { + balanceToShow = balance.getSpendable(); + } else { + balanceToShow = balance.getTotal(); + } + } + return Consumer( builder: (context, ref, __) { - final Coin coin = - ref.watch(managerProvider.select((value) => value.coin)); return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Consumer( - builder: (_, ref, __) { - final externalCalls = ref.watch(prefsChangeNotifierProvider - .select((value) => value.externalCalls)); - - Future? totalBalanceFuture; - Future? availableBalanceFuture; - if (coin == Coin.firo || coin == Coin.firoTestNet) { - final firoWallet = ref.watch( - managerProvider.select((value) => value.wallet)) - as FiroWallet; - totalBalanceFuture = - Future(() => firoWallet.balance.getSpendable()); - availableBalanceFuture = Future( - () => firoWallet.balancePrivate.getSpendable()); - } else { - final manager = ref.watch(walletsChangeNotifierProvider - .select((value) => value.getManager(walletId))); - totalBalanceFuture = - Future(() => manager.balance.getTotal()); - availableBalanceFuture = - Future(() => manager.balance.getSpendable()); - } - - final locale = ref.watch(localeServiceChangeNotifierProvider - .select((value) => value.locale)); - - final baseCurrency = ref.watch(prefsChangeNotifierProvider - .select((value) => value.currency)); - - final priceTuple = ref.watch( - priceAnd24hChangeNotifierProvider - .select((value) => value.getPrice(coin))); - - final _showAvailable = ref - .watch(walletBalanceToggleStateProvider.state) - .state == - WalletBalanceToggleState.available; - - return FutureBuilder( - future: _showAvailable - ? availableBalanceFuture - : totalBalanceFuture, - builder: (fbContext, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData && - snapshot.data != null) { - if (_showAvailable) { - _balanceCached = snapshot.data!; - } else { - _balanceTotalCached = snapshot.data!; - } - } - Decimal? balanceToShow = _showAvailable - ? _balanceCached - : _balanceTotalCached; - - if (balanceToShow != null) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - FittedBox( - fit: BoxFit.scaleDown, - child: Text( - "${Format.localizedStringAsFixed( - value: balanceToShow, - locale: locale, - decimalPlaces: 8, - )} ${coin.ticker}", - style: STextStyles.desktopH3(context), - ), - ), - if (externalCalls) - Text( - "${Format.localizedStringAsFixed( - value: priceTuple.item1 * balanceToShow, - locale: locale, - decimalPlaces: 2, - )} $baseCurrency", - style: - STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ), - ], - ); - } else { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AnimatedText( - stringsToLoopThrough: const [ - "Loading balance ", - "Loading balance. ", - "Loading balance.. ", - "Loading balance..." - ], - style: STextStyles.desktopH3(context).copyWith( - fontSize: 24, - color: Theme.of(context) - .extension()! - .textDark, - ), - ), - if (externalCalls) - AnimatedText( - stringsToLoopThrough: const [ - "Loading balance ", - "Loading balance. ", - "Loading balance.. ", - "Loading balance..." - ], - style: - STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ), - ], - ); - } - }, - ); - }, + FittedBox( + fit: BoxFit.scaleDown, + child: Text( + "${Format.localizedStringAsFixed( + value: balanceToShow, + locale: locale, + decimalPlaces: 8, + )} ${coin.ticker}", + style: STextStyles.desktopH3(context), + ), ), + if (externalCalls) + Text( + "${Format.localizedStringAsFixed( + value: priceTuple.item1 * balanceToShow, + locale: locale, + decimalPlaces: 2, + )} $baseCurrency", + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), ], ), - if (coin == Coin.firo || coin == Coin.firoTestNet) - const SizedBox( - width: 8, - ), - if (coin == Coin.firo || coin == Coin.firoTestNet) - const DesktopBalanceToggleButton(), const SizedBox( width: 8, ), WalletRefreshButton( walletId: walletId, initialSyncStatus: widget.initialSyncStatus, - ) + ), + if (coin == Coin.firo || coin == Coin.firoTestNet) + const SizedBox( + width: 8, + ), + if (coin == Coin.firo || coin == Coin.firoTestNet) + const DesktopPrivateBalanceToggleButton(), + const SizedBox( + width: 8, + ), + const DesktopBalanceToggleButton(), ], ); }, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart new file mode 100644 index 000000000..b94eccb54 --- /dev/null +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart @@ -0,0 +1,175 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/providers/global/prefs_provider.dart'; +import 'package:stackwallet/providers/global/wallets_provider.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; +import 'package:stackwallet/widgets/rounded_container.dart'; + +class MoreFeaturesDialog extends ConsumerStatefulWidget { + const MoreFeaturesDialog({ + Key? key, + required this.walletId, + required this.onPaynymPressed, + required this.onCoinControlPressed, + required this.onAnonymizeAllPressed, + required this.onWhirlpoolPressed, + }) : super(key: key); + + final String walletId; + final VoidCallback? onPaynymPressed; + final VoidCallback? onCoinControlPressed; + final VoidCallback? onAnonymizeAllPressed; + final VoidCallback? onWhirlpoolPressed; + + @override + ConsumerState createState() => _MoreFeaturesDialogState(); +} + +class _MoreFeaturesDialogState extends ConsumerState { + @override + Widget build(BuildContext context) { + final manager = ref.watch( + walletsChangeNotifierProvider.select( + (value) => value.getManager(widget.walletId), + ), + ); + + final coinControlPrefEnabled = ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.enableCoinControl, + ), + ); + + return DesktopDialog( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 32, + ), + child: Text( + "More features", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + if (manager.coin == Coin.firo || manager.coin == Coin.firoTestNet) + _MoreFeaturesItem( + label: "Anonymize funds", + detail: "Anonymize funds", + iconAsset: Assets.svg.anonymize, + onPressed: () => widget.onAnonymizeAllPressed?.call(), + ), + if (manager.hasWhirlpoolSupport) + _MoreFeaturesItem( + label: "Whirlpool", + detail: "Powerful Bitcoin privacy enhancer", + iconAsset: Assets.svg.whirlPool, + onPressed: () => widget.onWhirlpoolPressed?.call(), + ), + if (manager.hasCoinControlSupport && coinControlPrefEnabled) + _MoreFeaturesItem( + label: "Coin control", + detail: "Control, freeze, and utilize outputs at your discretion", + iconAsset: Assets.svg.coinControl.gamePad, + onPressed: () => widget.onCoinControlPressed?.call(), + ), + if (manager.hasPaynymSupport) + _MoreFeaturesItem( + label: "PayNym", + detail: "Increased address privacy using BIP47", + iconAsset: Assets.svg.robotHead, + onPressed: () => widget.onPaynymPressed?.call(), + ), + const SizedBox( + height: 28, + ), + ], + ), + ); + } +} + +class _MoreFeaturesItem extends StatelessWidget { + const _MoreFeaturesItem({ + Key? key, + required this.label, + required this.detail, + required this.iconAsset, + this.onPressed, + }) : super(key: key); + + static const double iconSizeBG = 46; + static const double iconSize = 24; + + final String label; + final String detail; + final String iconAsset; + final VoidCallback? onPressed; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 6, + horizontal: 32, + ), + child: RoundedContainer( + color: Colors.transparent, + borderColor: + Theme.of(context).extension()!.textFieldDefaultBG, + onPressed: onPressed, + child: Row( + children: [ + RoundedContainer( + padding: const EdgeInsets.all(0), + color: + Theme.of(context).extension()!.settingsIconBack, + width: iconSizeBG, + height: iconSizeBG, + radiusMultiplier: iconSizeBG, + child: Center( + child: SvgPicture.asset( + iconAsset, + width: iconSize, + height: iconSize, + color: Theme.of(context) + .extension()! + .settingsIconIcon, + ), + ), + ), + const SizedBox( + width: 16, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: STextStyles.w600_20(context), + ), + Text( + detail, + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages_desktop_specific/password/desktop_login_view.dart b/lib/pages_desktop_specific/password/desktop_login_view.dart index 05ad2d2ad..65632144a 100644 --- a/lib/pages_desktop_specific/password/desktop_login_view.dart +++ b/lib/pages_desktop_specific/password/desktop_login_view.dart @@ -119,14 +119,23 @@ class _DesktopLoginViewState extends ConsumerState { await Future.delayed(const Duration(seconds: 1)); - await showFloatingFlushBar( - type: FlushBarType.warning, - message: e.toString(), - context: context, - ); + if (mounted) { + await showFloatingFlushBar( + type: FlushBarType.warning, + message: e.toString(), + context: context, + ); + } } } + @override + void didChangeDependencies() { + unawaited(Assets.precache(context)); + + super.didChangeDependencies(); + } + @override void initState() { passwordController = TextEditingController(); diff --git a/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/advanced_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/advanced_settings.dart index e041bcb21..796c139f4 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/advanced_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/advanced_settings.dart @@ -110,6 +110,44 @@ class _AdvancedSettings extends ConsumerState { thickness: 0.5, ), ), + Padding( + padding: const EdgeInsets.all(10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Enable coin control", + style: STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textDark), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider + .select((value) => value.enableCoinControl), + ), + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .enableCoinControl = newValue; + }, + ), + ), + ], + ), + ), + const Padding( + padding: EdgeInsets.all(10.0), + child: Divider( + thickness: 0.5, + ), + ), /// TODO: Make a dialog popup Consumer(builder: (_, ref, __) { diff --git a/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/stack_privacy_dialog.dart b/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/stack_privacy_dialog.dart index 2f8d09e77..9045e0006 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/stack_privacy_dialog.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/stack_privacy_dialog.dart @@ -10,7 +10,6 @@ import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/text_styles.dart'; -import 'package:stackwallet/utilities/theme/color_theme.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; @@ -19,8 +18,6 @@ import 'package:stackwallet/widgets/desktop/primary_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; -import '../../../../providers/ui/color_theme_provider.dart'; - class StackPrivacyDialog extends ConsumerStatefulWidget { const StackPrivacyDialog({Key? key}) : super(key: key); @@ -215,16 +212,10 @@ class _PrivacyToggleState extends ConsumerState { late bool externalCallsEnabled; late final bool isDesktop; - late final bool isSorbet; - late final bool isOcean; @override void initState() { isDesktop = Util.isDesktop; - isSorbet = ref.read(colorThemeProvider.state).state.themeType == - ThemeType.fruitSorbet; - isOcean = ref.read(colorThemeProvider.state).state.themeType == - ThemeType.oceanBreeze; // initial toggle state externalCallsEnabled = widget.externalCallsEnabled; super.initState(); @@ -273,17 +264,11 @@ class _PrivacyToggleState extends ConsumerState { const SizedBox( height: 10, ), - (isSorbet) - ? Image.asset( - Assets.png.personaEasy(context), - width: 120, - height: 120, - ) - : SvgPicture.asset( - Assets.svg.personaEasy(context), - width: 120, - height: 120, - ), + SvgPicture.asset( + Assets.svg.personaEasy(context), + width: 120, + height: 120, + ), if (isDesktop) const SizedBox( height: 12, @@ -385,17 +370,11 @@ class _PrivacyToggleState extends ConsumerState { const SizedBox( height: 10, ), - (isSorbet) - ? Image.asset( - Assets.png.personaIncognito(context), - width: 120, - height: 120, - ) - : SvgPicture.asset( - Assets.svg.personaIncognito(context), - width: 120, - height: 120, - ), + SvgPicture.asset( + Assets.svg.personaIncognito(context), + width: 120, + height: 120, + ), if (isDesktop) const SizedBox( height: 12, diff --git a/lib/pages_desktop_specific/settings/settings_menu/appearance_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/appearance_settings.dart index ebe94ed12..a23ad962a 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/appearance_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/appearance_settings.dart @@ -135,8 +135,8 @@ class _AppearanceOptionSettings ], ), ), - Padding( - padding: EdgeInsets.all(10), + const Padding( + padding: EdgeInsets.all(2), child: ThemeToggle(), ), ], @@ -174,6 +174,8 @@ class _ThemeToggle extends ConsumerState { return Assets.svg.themeFruit; case ThemeType.forest: return Assets.svg.themeForest; + case ThemeType.chan: + return Assets.svg.themeChan; } } @@ -184,100 +186,95 @@ class _ThemeToggle extends ConsumerState { runSpacing: 16, children: [ for (int i = 0; i < ThemeType.values.length; i++) - Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (i > 0) - const SizedBox( - width: 10, - ), - MouseRegion( - cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: () { - if (ref.read(colorThemeProvider.state).state.themeType != - ThemeType.values[i]) { - DB.instance.put( - boxName: DB.boxNameTheme, - key: "colorScheme", - value: ThemeType.values[i].name, - ); - ref.read(colorThemeProvider.state).state = - StackColors.fromStackColorTheme( - ThemeType.values[i].colorTheme); - } - }, - child: Container( - width: 200, - color: Colors.transparent, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - decoration: BoxDecoration( - border: Border.all( - width: 2.5, - color: ref - .read(colorThemeProvider.state) - .state - .themeType == - ThemeType.values[i] - ? Theme.of(context) - .extension()! - .infoItemIcons - : Theme.of(context) - .extension()! - .popupBG, - ), - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + Padding( + padding: const EdgeInsets.all(8.0), + child: MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () { + if (ref.read(colorThemeProvider.state).state.themeType != + ThemeType.values[i]) { + DB.instance.put( + boxName: DB.boxNameTheme, + key: "colorScheme", + value: ThemeType.values[i].name, + ); + ref.read(colorThemeProvider.state).state = + StackColors.fromStackColorTheme( + ThemeType.values[i].colorTheme); + } + }, + child: Container( + width: 200, + color: Colors.transparent, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + decoration: BoxDecoration( + border: Border.all( + width: 2.5, + color: ref + .read(colorThemeProvider.state) + .state + .themeType == + ThemeType.values[i] + ? Theme.of(context) + .extension()! + .infoItemIcons + : Theme.of(context) + .extension()! + .popupBG, ), - child: SvgPicture.asset( - assetNameFor(ThemeType.values[i]), + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), ), - const SizedBox( - height: 12, + child: SvgPicture.asset( + assetNameFor(ThemeType.values[i]), + height: 160, ), - Row( - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: ThemeType.values[i], - groupValue: ref - .read(colorThemeProvider.state) - .state - .themeType, - onChanged: (_) {}, - ), + ), + const SizedBox( + height: 12, + ), + Row( + children: [ + SizedBox( + width: 20, + height: 20, + child: Radio( + activeColor: Theme.of(context) + .extension()! + .radioButtonIconEnabled, + value: ThemeType.values[i], + groupValue: ref + .read(colorThemeProvider.state) + .state + .themeType, + onChanged: (_) {}, ), - const SizedBox( - width: 14, + ), + const SizedBox( + width: 14, + ), + Text( + ThemeType.values[i].prettyName, + style: STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textDark, ), - Text( - ThemeType.values[i].prettyName, - style: STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ), - ), - ], - ), - ], - ), + ), + ], + ), + ], ), ), - ) - ], - ), + ), + ), + ) ], ); } diff --git a/lib/providers/desktop/current_desktop_menu_item.dart b/lib/providers/desktop/current_desktop_menu_item.dart index 85ac7c46b..a9d3b17e1 100644 --- a/lib/providers/desktop/current_desktop_menu_item.dart +++ b/lib/providers/desktop/current_desktop_menu_item.dart @@ -3,3 +3,6 @@ import 'package:stackwallet/pages_desktop_specific/desktop_menu.dart'; final currentDesktopMenuItemProvider = StateProvider((ref) => DesktopMenuItemId.myStack); + +final prevDesktopMenuItemProvider = + StateProvider((ref) => DesktopMenuItemId.myStack); diff --git a/lib/providers/wallet/wallet_balance_toggle_state_provider.dart b/lib/providers/wallet/wallet_balance_toggle_state_provider.dart index 35d85a6cf..477f4fb03 100644 --- a/lib/providers/wallet/wallet_balance_toggle_state_provider.dart +++ b/lib/providers/wallet/wallet_balance_toggle_state_provider.dart @@ -4,3 +4,7 @@ import 'package:stackwallet/utilities/enums/wallet_balance_toggle_state.dart'; final walletBalanceToggleStateProvider = StateProvider.autoDispose( (ref) => WalletBalanceToggleState.full); + +final walletPrivateBalanceToggleStateProvider = + StateProvider.autoDispose( + (ref) => WalletBalanceToggleState.full); diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 9e0efabfb..64fd1e010 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -98,6 +98,7 @@ import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_sear import 'package:stackwallet/pages/wallet_view/wallet_view.dart'; import 'package:stackwallet/pages/wallets_view/wallets_view.dart'; import 'package:stackwallet/pages_desktop_specific/address_book_view/desktop_address_book.dart'; +import 'package:stackwallet/pages_desktop_specific/coin_control/desktop_coin_control_view.dart'; // import 'package:stackwallet/pages_desktop_specific/desktop_exchange/desktop_all_buys_view.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_buy/desktop_buy_view.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_exchange/desktop_all_trades_view.dart'; @@ -1287,6 +1288,20 @@ class RouteGenerator { } return _routeError("${settings.name} invalid args: ${args.toString()}"); + case DesktopCoinControlView.routeName: + if (args is String) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => DesktopCoinControlView( + walletId: args, + ), + settings: RouteSettings( + name: settings.name, + ), + ); + } + return _routeError("${settings.name} invalid args: ${args.toString()}"); + case BackupRestoreSettings.routeName: return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, diff --git a/lib/services/coins/manager.dart b/lib/services/coins/manager.dart index 38dc938b3..38516f872 100644 --- a/lib/services/coins/manager.dart +++ b/lib/services/coins/manager.dart @@ -232,6 +232,8 @@ class Manager with ChangeNotifier { bool get hasCoinControlSupport => _currentWallet is CoinControlInterface; + bool get hasWhirlpoolSupport => false; + int get rescanOnOpenVersion => DB.instance.get( boxName: DB.boxNameDBInfo, diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart index 7675d86c2..25c434fa0 100644 --- a/lib/utilities/assets.dart +++ b/lib/utilities/assets.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/theme/color_theme.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; abstract class Assets { static const svg = _SVG(); @@ -10,61 +12,107 @@ abstract class Assets { static const socials = _SOCIALS(); static const exchange = _EXCHANGE(); static const buy = _BUY(); + static const gif = _GIF(); + + static Future precache(BuildContext context) async { + final assets = [ + svg.iconFor(coin: Coin.dogecoin), + svg.stack(context), + svg.personaEasy(context), + svg.personaIncognito(context), + ...Coin.values.map( + (e) => svg.imageFor(context: context, coin: e), + ), + ]; + + if (Util.isDesktop) { + assets.add(svg.themeChan); + } + + final futures = assets.map( + (e) => precachePicture( + ExactAssetPicture( + SvgPicture.svgStringDecoderBuilder, + e, + ), + context), + ); + + await Future.wait(futures); + } } class _SOCIALS { const _SOCIALS(); - String get discord => "assets/svg/socials/discord.svg"; - String get reddit => "assets/svg/socials/reddit-alien-brands.svg"; - String get twitter => "assets/svg/socials/twitter-brands.svg"; - String get telegram => "assets/svg/socials/telegram-brands.svg"; + static const _path = "assets/svg/socials/"; + + String get discord => "${_path}discord.svg"; + String get reddit => "${_path}reddit-alien-brands.svg"; + String get twitter => "${_path}twitter-brands.svg"; + String get telegram => "${_path}telegram-brands.svg"; } class _EXCHANGE { const _EXCHANGE(); - String get changeNow => "assets/svg/exchange_icons/change_now_logo_1.svg"; - String get simpleSwap => "assets/svg/exchange_icons/simpleswap-icon.svg"; - String get majesticBankBlue => "assets/svg/exchange_icons/mb_blue.svg"; - String get majesticBankGreen => "assets/svg/exchange_icons/mb_green.svg"; + static const _path = "assets/svg/exchange_icons/"; + + String get changeNow => "${_path}change_now_logo_1.svg"; + String get simpleSwap => "${_path}simpleswap-icon.svg"; + String get majesticBankBlue => "${_path}mb_blue.svg"; + String get majesticBankGreen => "${_path}mb_green.svg"; } class _BUY { const _BUY(); - // TODO: switch this to something like - String buy(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/buy-coins-icon.svg"; - String simplexLogo(BuildContext context) { - return (Theme.of(context).extension()!.themeType == - ThemeType.dark || - Theme.of(context).extension()!.themeType == - ThemeType - .oledBlack) // TODO make sure this cover OLED black, too - ? "assets/svg/buy/Simplex-Nuvei-Logo-light.svg" - : "assets/svg/buy/Simplex-Nuvei-Logo.svg"; + switch (Theme.of(context).extension()!.themeType) { + case ThemeType.dark: + case ThemeType.oledBlack: + return "assets/svg/buy/Simplex-Nuvei-Logo-light.svg"; + + case ThemeType.fruitSorbet: + case ThemeType.forest: + case ThemeType.oceanBreeze: + case ThemeType.light: + case ThemeType.chan: + return "assets/svg/buy/Simplex-Nuvei-Logo.svg"; + } } } class _COIN_CONTROL { const _COIN_CONTROL(); - String get blocked => "assets/svg/coin_control/frozen.svg"; - String get unBlocked => "assets/svg/coin_control/unfrozen.svg"; - String get gamePad => "assets/svg/coin_control/gamepad.svg"; - String get selected => "assets/svg/coin_control/selected.svg"; + static const _path = "assets/svg/coin_control/"; + + String get blocked => "${_path}frozen.svg"; + String get unBlocked => "${_path}unfrozen.svg"; + String get gamePad => "${_path}gamepad.svg"; + String get selected => "${_path}selected.svg"; } class _SVG { const _SVG(); + static String _path(BuildContext context) { + switch (Theme.of(context).extension()!.themeType) { + // chan theme uses all the same assets as the light theme + case ThemeType.chan: + return "assets/svg/themed/${ThemeType.light.name}"; + default: + return "assets/svg/themed/${Theme.of(context).extension()!.themeType.name}"; + } + } + final coinControl = const _COIN_CONTROL(); String? background(BuildContext context) { switch (Theme.of(context).extension()!.themeType) { case ThemeType.light: + case ThemeType.chan: case ThemeType.dark: case ThemeType.oledBlack: return null; @@ -72,47 +120,41 @@ class _SVG { case ThemeType.oceanBreeze: case ThemeType.fruitSorbet: case ThemeType.forest: - return "assets/svg/${Theme.of(context).extension()!.themeType.name}/bg.svg"; + return "${_path(context)}/bg.svg"; } } - String bellNew(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/bell-new.svg"; - String stackIcon(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/stack-icon1.svg"; - String exchange(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/exchange-2.svg"; - String buy(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/buy-coins-icon.svg"; + String bellNew(BuildContext context) => "${_path(context)}/bell-new.svg"; + String stackIcon(BuildContext context) => "${_path(context)}/stack-icon1.svg"; + String exchange(BuildContext context) => "${_path(context)}/exchange-2.svg"; + String buy(BuildContext context) => "${_path(context)}/buy-coins-icon.svg"; String receive(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/tx-icon-receive.svg"; + "${_path(context)}/tx-icon-receive.svg"; String receivePending(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/tx-icon-receive-pending.svg"; + "${_path(context)}/tx-icon-receive-pending.svg"; String receiveCancelled(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/tx-icon-receive-failed.svg"; + "${_path(context)}/tx-icon-receive-failed.svg"; - String send(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/tx-icon-send.svg"; + String send(BuildContext context) => "${_path(context)}/tx-icon-send.svg"; String sendPending(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/tx-icon-send-pending.svg"; + "${_path(context)}/tx-icon-send-pending.svg"; String sendCancelled(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/tx-icon-send-failed.svg"; + "${_path(context)}/tx-icon-send-failed.svg"; String txExchange(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/tx-exchange-icon.svg"; + "${_path(context)}/tx-exchange-icon.svg"; String txExchangePending(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/tx-exchange-icon-pending.svg"; + "${_path(context)}/tx-exchange-icon-pending.svg"; String txExchangeFailed(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/tx-exchange-icon-failed.svg"; + "${_path(context)}/tx-exchange-icon-failed.svg"; String personaIncognito(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/persona-incognito-1.svg"; + "${_path(context)}/persona-incognito-1.svg"; String personaEasy(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/persona-easy-1.svg"; + "${_path(context)}/persona-easy-1.svg"; - String stack(BuildContext context) => - "assets/images/${Theme.of(context).extension()!.themeType.name}/stack.svg"; + String stack(BuildContext context) => "${_path(context)}/stack.svg"; String get themeFruit => "assets/svg/fruit-sorbet-theme.svg"; String get themeForest => "assets/svg/forest-theme.svg"; @@ -120,6 +162,7 @@ class _SVG { String get themeOcean => "assets/svg/ocean-breeze-theme.svg"; String get themeLight => "assets/svg/light-mode.svg"; String get themeDark => "assets/svg/dark-theme.svg"; + String get themeChan => "assets/svg/chanstheme.svg"; String get circleSliders => "assets/svg/configuration.svg"; String get circlePlus => "assets/svg/plus-circle.svg"; @@ -210,7 +253,6 @@ class _SVG { String get anonymizeFailed => "assets/svg/tx-icon-anonymize-failed.svg"; String get addressBookDesktop => "assets/svg/address-book-desktop.svg"; String get exchangeDesktop => "assets/svg/exchange-desktop.svg"; - String get buyDesktop => "assets/svg/light/buy-coins-icon.svg"; String get aboutDesktop => "assets/svg/about-desktop.svg"; String get walletDesktop => "assets/svg/wallet-desktop.svg"; String get exitDesktop => "assets/svg/exit-desktop.svg"; @@ -220,9 +262,22 @@ class _SVG { String get whirlPool => "assets/svg/whirlpool.svg"; String get fingerprint => "assets/svg/fingerprint.svg"; String get faceId => "assets/svg/faceid.svg"; - String get ellipse1 => "assets/svg/Ellipse-43.svg"; String get ellipse2 => "assets/svg/Ellipse-42.svg"; + String get chevronRight => "assets/svg/chevron-right.svg"; + String get minimize => "assets/svg/minimize.svg"; + String get walletFa => "assets/svg/wallet-fa.svg"; + String get exchange3 => "assets/svg/exchange-3.svg"; + String get messageQuestion => "assets/svg/message-question-1.svg"; + String get list => "assets/svg/list-ul.svg"; + String get unclaimedPaynym => "assets/svg/unclaimed.png"; + +// TODO provide proper assets + String get bitcoinTestnet => "assets/svg/coin_icons/Bitcoin.svg"; + String get bitcoincashTestnet => "assets/svg/coin_icons/Bitcoincash.svg"; + String get firoTestnet => "assets/svg/coin_icons/Firo.svg"; + String get dogecoinTestnet => "assets/svg/coin_icons/Dogecoin.svg"; + String get particlTestnet => "assets/svg/coin_icons/Particl.svg"; // small icons String get bitcoin => "assets/svg/coin_icons/Bitcoin.svg"; @@ -236,20 +291,6 @@ class _SVG { String get namecoin => "assets/svg/coin_icons/Namecoin.svg"; String get particl => "assets/svg/coin_icons/Particl.svg"; - String get chevronRight => "assets/svg/chevron-right.svg"; - String get minimize => "assets/svg/minimize.svg"; - String get walletFa => "assets/svg/wallet-fa.svg"; - String get exchange3 => "assets/svg/exchange-3.svg"; - String get messageQuestion => "assets/svg/message-question-1.svg"; - -// TODO provide proper assets - String get bitcoinTestnet => "assets/svg/coin_icons/Bitcoin.svg"; - String get bitcoincashTestnet => "assets/svg/coin_icons/Bitcoincash.svg"; - String get firoTestnet => "assets/svg/coin_icons/Firo.svg"; - String get dogecoinTestnet => "assets/svg/coin_icons/Dogecoin.svg"; - String get particlTestnet => - "assets/svg/coin_icons/Dogecoin.svg"; //TODO - Update icon to particl - String iconFor({required Coin coin}) { switch (coin) { case Coin.bitcoin: @@ -285,26 +326,20 @@ class _SVG { } // big icons - String bitcoinImage(BuildContext context) => - "assets/images/${Theme.of(context).extension()!.themeType.name}/bitcoin.svg"; + String bitcoinImage(BuildContext context) => "${_path(context)}/bitcoin.svg"; String bitcoincashImage(BuildContext context) => - "assets/images/${Theme.of(context).extension()!.themeType.name}/bitcoincash.svg"; - String dogecoinImage(BuildContext context) => - "assets/images/${Theme.of(context).extension()!.themeType.name}/doge.svg"; + "${_path(context)}/bitcoincash.svg"; + String dogecoinImage(BuildContext context) => "${_path(context)}/doge.svg"; String epicCashImage(BuildContext context) => - "assets/images/${Theme.of(context).extension()!.themeType.name}/epic-cash.svg"; - String firoImage(BuildContext context) => - "assets/images/${Theme.of(context).extension()!.themeType.name}/firo.svg"; + "${_path(context)}/epic-cash.svg"; + String firoImage(BuildContext context) => "${_path(context)}/firo.svg"; String litecoinImage(BuildContext context) => - "assets/images/${Theme.of(context).extension()!.themeType.name}/litecoin.svg"; - String moneroImage(BuildContext context) => - "assets/images/${Theme.of(context).extension()!.themeType.name}/monero.svg"; - String wowneroImage(BuildContext context) => - "assets/images/${Theme.of(context).extension()!.themeType.name}/wownero.svg"; + "${_path(context)}/litecoin.svg"; + String moneroImage(BuildContext context) => "${_path(context)}/monero.svg"; + String wowneroImage(BuildContext context) => "${_path(context)}/wownero.svg"; String namecoinImage(BuildContext context) => - "assets/images/${Theme.of(context).extension()!.themeType.name}/namecoin.svg"; - String particlImage(BuildContext context) => - "assets/images/${Theme.of(context).extension()!.themeType.name}/particl.svg"; + "${_path(context)}/namecoin.svg"; + String particlImage(BuildContext context) => "${_path(context)}/particl.svg"; String imageFor({required BuildContext context, required Coin coin}) { switch (coin) { @@ -344,75 +379,26 @@ class _SVG { class _PNG { const _PNG(); - String get unclaimedPaynym => "assets/images/unclaimed.png"; - String stack(BuildContext context) => - "assets/images/${Theme.of(context).extension()!.themeType.name}/stack.png"; String get splash => "assets/images/splash.png"; - // String monero(BuildContext context) => - // "assets/images/${Theme.of(context).extension()!.themeType.name}/monero.png"; - // String wownero(BuildContext context) => - // "assets/images/${Theme.of(context).extension()!.themeType.name}/wownero.png"; - // String firo(BuildContext context) => - // "assets/images/${Theme.of(context).extension()!.themeType.name}/firo.png"; - // String dogecoin(BuildContext context) => - // "assets/images/${Theme.of(context).extension()!.themeType.name}/doge.png"; - // String bitcoin(BuildContext context) => - // "assets/images/${Theme.of(context).extension()!.themeType.name}/bitcoin.png"; - // String litecoin(BuildContext context) => - // "assets/images/${Theme.of(context).extension()!.themeType.name}/litecoin.png"; - // String epicCash(BuildContext context) => - // "assets/images/${Theme.of(context).extension()!.themeType.name}/epic-cash.png"; - // String bitcoincash(BuildContext context) => - // "assets/images/${Theme.of(context).extension()!.themeType.name}/bitcoincash.png"; - // String namecoin(BuildContext context) => - // "assets/images/${Theme.of(context).extension()!.themeType.name}/namecoin.png"; - // String particl(BuildContext context) => - // "assets/images/${Theme.of(context).extension()!.themeType.name}/particl.png"; - - String personaIncognito(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/persona-incognito-1.png"; - String personaEasy(BuildContext context) => - "assets/svg/${Theme.of(context).extension()!.themeType.name}/persona-easy-1.png"; - String get glasses => "assets/images/glasses.png"; String get glassesHidden => "assets/images/glasses-hidden.png"; - - // String imageFor({required BuildContext context, required Coin coin}) { - // switch (coin) { - // case Coin.bitcoin: - // case Coin.bitcoinTestNet: - // return bitcoin(context); - // case Coin.litecoin: - // case Coin.litecoinTestNet: - // return litecoin(context); - // case Coin.bitcoincash: - // case Coin.bitcoincashTestnet: - // return bitcoincash(context); - // case Coin.dogecoin: - // case Coin.dogecoinTestNet: - // return dogecoin(context); - // case Coin.epicCash: - // return epicCash(context); - // case Coin.firo: - // return firo(context); - // case Coin.firoTestNet: - // return firo(context); - // case Coin.monero: - // return monero(context); - // case Coin.wownero: - // return wownero(context); - // case Coin.namecoin: - // return namecoin(context); - // case Coin.particl: - // return particl(context); - // } - // } } class _ANIMATIONS { const _ANIMATIONS(); - String get test => "assets/lottie/test.json"; String get test2 => "assets/lottie/test2.json"; } + +class _GIF { + const _GIF(); + + String plain(Coin coin) { + return "assets/gif/coins/${coin.mainNetVersion.name}/plain.gif"; + } + + String kiss(Coin coin) { + return "assets/gif/coins/${coin.mainNetVersion.name}/kiss.gif"; + } +} diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart index 0e8a010ab..3ab21ee7a 100644 --- a/lib/utilities/enums/coin_enum.dart +++ b/lib/utilities/enums/coin_enum.dart @@ -218,6 +218,37 @@ extension CoinExt on Coin { } } + Coin get mainNetVersion { + switch (this) { + case Coin.bitcoin: + case Coin.litecoin: + case Coin.bitcoincash: + case Coin.dogecoin: + case Coin.firo: + case Coin.namecoin: + case Coin.particl: + case Coin.epicCash: + case Coin.monero: + case Coin.wownero: + return this; + + case Coin.dogecoinTestNet: + return Coin.dogecoin; + + case Coin.bitcoinTestNet: + return Coin.bitcoin; + + case Coin.litecoinTestNet: + return Coin.litecoin; + + case Coin.bitcoincashTestnet: + return Coin.bitcoincash; + + case Coin.firoTestNet: + return Coin.firo; + } + } + int get requiredConfirmations { switch (this) { case Coin.bitcoin: diff --git a/lib/utilities/text_styles.dart b/lib/utilities/text_styles.dart index 6ff8cdaf1..27f49e060 100644 --- a/lib/utilities/text_styles.dart +++ b/lib/utilities/text_styles.dart @@ -9,78 +9,24 @@ class STextStyles { static TextStyle sectionLabelMedium12(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 14, - ); case ThemeType.forest: return GoogleFonts.inter( color: _theme(context).textDark3, fontWeight: FontWeight.w500, fontSize: 12, ); + default: + return GoogleFonts.inter( + color: _theme(context).textDark3, + fontWeight: FontWeight.w500, + fontSize: 14, + ); } } static TextStyle pageTitleH1(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 20, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 20, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 20, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 20, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 20, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w600, @@ -91,37 +37,7 @@ class STextStyles { static TextStyle pageTitleH2(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 18, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 18, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 18, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 18, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 18, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w600, @@ -132,37 +48,7 @@ class STextStyles { static TextStyle navBarTitle(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w600, @@ -173,119 +59,18 @@ class STextStyles { static TextStyle titleBold12(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w600, fontSize: 16, ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.forest: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - } - } - - static TextStyle titleBold12_400(BuildContext context) { - switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 16, - ); - case ThemeType.forest: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 16, - ); } } static TextStyle subtitle(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w400, @@ -296,37 +81,7 @@ class STextStyles { static TextStyle subtitle500(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -337,37 +92,7 @@ class STextStyles { static TextStyle subtitle600(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w600, @@ -378,37 +103,7 @@ class STextStyles { static TextStyle button(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimary, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimary, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimary, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimary, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimary, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).buttonTextPrimary, fontWeight: FontWeight.w500, @@ -419,37 +114,7 @@ class STextStyles { static TextStyle largeMedium14(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -460,37 +125,7 @@ class STextStyles { static TextStyle smallMed14(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark3, fontWeight: FontWeight.w500, @@ -501,37 +136,7 @@ class STextStyles { static TextStyle smallMed12(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark3, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark3, fontWeight: FontWeight.w500, @@ -542,37 +147,7 @@ class STextStyles { static TextStyle label(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textSubtitle1, fontWeight: FontWeight.w500, @@ -583,42 +158,7 @@ class STextStyles { static TextStyle labelExtraExtraSmall(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textFieldActiveSearchIconRight, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 14 / 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textFieldActiveSearchIconRight, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 14 / 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textFieldActiveSearchIconRight, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 14 / 14, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textFieldActiveSearchIconRight, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 14 / 14, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textFieldActiveSearchIconRight, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 14 / 14, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textFieldActiveSearchIconRight, fontWeight: FontWeight.w500, @@ -630,37 +170,7 @@ class STextStyles { static TextStyle label700(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w700, - fontSize: 12, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w700, - fontSize: 12, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w700, - fontSize: 12, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w700, - fontSize: 12, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w700, - fontSize: 12, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textSubtitle1, fontWeight: FontWeight.w700, @@ -671,37 +181,7 @@ class STextStyles { static TextStyle itemSubtitle(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).infoItemLabel, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).infoItemLabel, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).infoItemLabel, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).infoItemLabel, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).infoItemLabel, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).infoItemLabel, fontWeight: FontWeight.w500, @@ -712,78 +192,7 @@ class STextStyles { static TextStyle itemSubtitle12(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.forest: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - } - } - - static TextStyle itemSubtitle12_600(BuildContext context) { - switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -794,42 +203,7 @@ class STextStyles { static TextStyle fieldLabel(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textSubtitle2, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 1.5, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textSubtitle2, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 1.5, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textSubtitle2, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 1.5, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textSubtitle2, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 1.5, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textSubtitle2, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 1.5, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textSubtitle2, fontWeight: FontWeight.w500, @@ -841,42 +215,7 @@ class STextStyles { static TextStyle field(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 1.5, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 1.5, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 1.5, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 1.5, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 1.5, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -888,37 +227,7 @@ class STextStyles { static TextStyle baseXS(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 14, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 14, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 14, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w400, @@ -929,37 +238,7 @@ class STextStyles { static TextStyle link(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).accentColorRed, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).accentColorRed, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).accentColorRed, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).accentColorRed, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).accentColorRed, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).accentColorRed, fontWeight: FontWeight.w500, @@ -970,37 +249,13 @@ class STextStyles { static TextStyle link2(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).infoItemIcons, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).infoItemIcons, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).infoItemIcons, - fontWeight: FontWeight.w500, - fontSize: 14, - ); case ThemeType.oledBlack: return GoogleFonts.inter( color: _theme(context).checkboxBGChecked, fontWeight: FontWeight.w500, fontSize: 14, ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).infoItemIcons, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).infoItemIcons, fontWeight: FontWeight.w500, @@ -1011,37 +266,7 @@ class STextStyles { static TextStyle richLink(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).accentColorBlue, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).accentColorBlue, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).accentColorBlue, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).accentColorBlue, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).accentColorBlue, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).accentColorBlue, fontWeight: FontWeight.w500, @@ -1052,37 +277,7 @@ class STextStyles { static TextStyle w600_12(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 12, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 12, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 12, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 12, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 12, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w600, @@ -1093,37 +288,7 @@ class STextStyles { static TextStyle w600_14(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 14, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 14, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 14, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w600, @@ -1134,37 +299,7 @@ class STextStyles { static TextStyle w500_14(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 14, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -1175,37 +310,7 @@ class STextStyles { static TextStyle w500_12(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -1216,37 +321,7 @@ class STextStyles { static TextStyle w500_10(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -1255,39 +330,21 @@ class STextStyles { } } + static TextStyle w600_20(BuildContext context) { + switch (_theme(context).themeType) { + default: + return GoogleFonts.inter( + color: _theme(context).textDark, + fontWeight: FontWeight.w600, + fontSize: 20, + height: 30 / 20, + ); + } + } + static TextStyle syncPercent(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -1298,37 +355,13 @@ class STextStyles { static TextStyle buttonSmall(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 12, - ); case ThemeType.fruitSorbet: return GoogleFonts.inter( color: _theme(context).bottomNavIconIcon, fontWeight: FontWeight.w500, fontSize: 12, ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -1339,37 +372,7 @@ class STextStyles { static TextStyle errorSmall(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textError, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textError, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textError, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textError, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textError, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textError, fontWeight: FontWeight.w500, @@ -1380,37 +383,7 @@ class STextStyles { static TextStyle infoSmall(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 10, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textSubtitle1, fontWeight: FontWeight.w500, @@ -1423,42 +396,7 @@ class STextStyles { static TextStyle desktopH1(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 40, - height: 40 / 40, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 40, - height: 40 / 40, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 40, - height: 40 / 40, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 40, - height: 40 / 40, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 40, - height: 40 / 40, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w600, @@ -1470,42 +408,7 @@ class STextStyles { static TextStyle desktopH2(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 32, - height: 32 / 32, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 32, - height: 32 / 32, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 32, - height: 32 / 32, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 32, - height: 32 / 32, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 32, - height: 32 / 32, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w600, @@ -1517,42 +420,7 @@ class STextStyles { static TextStyle desktopH3(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 24, - height: 24 / 24, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 24, - height: 24 / 24, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 24, - height: 24 / 24, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 24, - height: 24 / 24, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 24, - height: 24 / 24, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w600, @@ -1564,42 +432,7 @@ class STextStyles { static TextStyle w500_24(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 24, - height: 24 / 24, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 24, - height: 24 / 24, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 24, - height: 24 / 24, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 24, - height: 24 / 24, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 24, - height: 24 / 24, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -1611,42 +444,7 @@ class STextStyles { static TextStyle desktopTextMedium(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -1658,42 +456,7 @@ class STextStyles { static TextStyle desktopTextMediumRegular(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w400, @@ -1705,42 +468,7 @@ class STextStyles { static TextStyle desktopSubtitleH2(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 20, - height: 28 / 20, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 20, - height: 28 / 20, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 20, - height: 28 / 20, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 20, - height: 28 / 20, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 20, - height: 28 / 20, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w400, @@ -1752,42 +480,7 @@ class STextStyles { static TextStyle desktopSubtitleH1(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 24, - height: 33 / 24, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 24, - height: 33 / 24, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 24, - height: 33 / 24, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 24, - height: 33 / 24, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w400, - fontSize: 24, - height: 33 / 24, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w400, @@ -1799,42 +492,7 @@ class STextStyles { static TextStyle desktopButtonEnabled(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimary, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimary, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimary, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimary, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimary, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).buttonTextPrimary, fontWeight: FontWeight.w500, @@ -1846,42 +504,7 @@ class STextStyles { static TextStyle desktopButtonDisabled(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).buttonTextPrimaryDisabled, fontWeight: FontWeight.w500, @@ -1893,42 +516,7 @@ class STextStyles { static TextStyle desktopButtonSecondaryEnabled(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondary, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondary, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondary, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondary, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondary, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).buttonTextSecondary, fontWeight: FontWeight.w500, @@ -1940,42 +528,7 @@ class STextStyles { static TextStyle desktopButtonSecondaryDisabled(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 26 / 20, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).buttonTextSecondaryDisabled, fontWeight: FontWeight.w500, @@ -1987,20 +540,6 @@ class STextStyles { static TextStyle desktopTextSmall(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 18, - height: 27 / 18, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 18, - height: 27 / 18, - ); case ThemeType.dark: return GoogleFonts.inter( color: _theme(context).buttonTextPrimaryDisabled, @@ -2008,21 +547,8 @@ class STextStyles { fontSize: 18, height: 27 / 18, ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 18, - height: 27 / 18, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 18, - height: 27 / 18, - ); - case ThemeType.forest: + + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -2034,27 +560,7 @@ class STextStyles { static TextStyle desktopTextSmallBold(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w700, - fontSize: 18, - height: 27 / 18, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w700, - fontSize: 18, - height: 27 / 18, - ); case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimaryDisabled, - fontWeight: FontWeight.w700, - fontSize: 18, - height: 27 / 18, - ); case ThemeType.oledBlack: return GoogleFonts.inter( color: _theme(context).buttonTextPrimaryDisabled, @@ -2062,14 +568,8 @@ class STextStyles { fontSize: 18, height: 27 / 18, ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w700, - fontSize: 18, - height: 27 / 18, - ); - case ThemeType.forest: + + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w700, @@ -2081,42 +581,7 @@ class STextStyles { static TextStyle desktopTextExtraSmall(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 24 / 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 24 / 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 24 / 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 24 / 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).buttonTextPrimaryDisabled, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 24 / 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).buttonTextPrimaryDisabled, fontWeight: FontWeight.w500, @@ -2128,42 +593,7 @@ class STextStyles { static TextStyle desktopTextExtraExtraSmall(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 21 / 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 21 / 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 21 / 14, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 21 / 14, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textSubtitle1, - fontWeight: FontWeight.w500, - fontSize: 14, - height: 21 / 14, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textSubtitle1, fontWeight: FontWeight.w500, @@ -2175,42 +605,7 @@ class STextStyles { static TextStyle desktopTextExtraExtraSmall600(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 14, - height: 21 / 14, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 14, - height: 21 / 14, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 14, - height: 21 / 14, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 14, - height: 21 / 14, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 14, - height: 21 / 14, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w600, @@ -2222,42 +617,7 @@ class STextStyles { static TextStyle desktopButtonSmallSecondaryEnabled(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondary, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 24 / 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondary, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 24 / 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondary, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 24 / 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondary, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 24 / 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).buttonTextSecondary, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 24 / 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).buttonTextSecondary, fontWeight: FontWeight.w500, @@ -2269,42 +629,7 @@ class STextStyles { static TextStyle desktopTextFieldLabel(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textSubtitle2, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textSubtitle2, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textSubtitle2, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textSubtitle2, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textSubtitle2, - fontWeight: FontWeight.w500, - fontSize: 20, - height: 30 / 20, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textSubtitle2, fontWeight: FontWeight.w500, @@ -2316,42 +641,7 @@ class STextStyles { static TextStyle desktopMenuItem(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark.withOpacity(0.8), - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark.withOpacity(0.8), - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark.withOpacity(0.8), - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark.withOpacity(0.8), - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark.withOpacity(0.8), - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark.withOpacity(0.8), fontWeight: FontWeight.w500, @@ -2363,42 +653,7 @@ class STextStyles { static TextStyle desktopMenuItemSelected(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -2410,42 +665,7 @@ class STextStyles { static TextStyle settingsMenuItem(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark.withOpacity(0.5), - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark.withOpacity(0.5), - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark.withOpacity(0.5), - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark.withOpacity(0.5), - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark.withOpacity(0.5), - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark.withOpacity(0.5), fontWeight: FontWeight.w500, @@ -2457,42 +677,7 @@ class STextStyles { static TextStyle settingsMenuItemSelected(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - color: _theme(context).textDark, - fontWeight: FontWeight.w500, - fontSize: 16, - height: 20.8 / 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( color: _theme(context).textDark, fontWeight: FontWeight.w500, @@ -2504,37 +689,7 @@ class STextStyles { static TextStyle stepIndicator(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.roboto( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 8, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.roboto( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 8, - ); - case ThemeType.dark: - return GoogleFonts.roboto( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 8, - ); - case ThemeType.oledBlack: - return GoogleFonts.roboto( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 8, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.roboto( - color: _theme(context).textDark, - fontWeight: FontWeight.w600, - fontSize: 8, - ); - case ThemeType.forest: + default: return GoogleFonts.roboto( color: _theme(context).textDark, fontWeight: FontWeight.w600, @@ -2545,37 +700,7 @@ class STextStyles { static TextStyle numberDefault(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.roboto( - color: _theme(context).numberTextDefault, - fontWeight: FontWeight.w400, - fontSize: 26, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.roboto( - color: _theme(context).numberTextDefault, - fontWeight: FontWeight.w400, - fontSize: 26, - ); - case ThemeType.dark: - return GoogleFonts.roboto( - color: _theme(context).numberTextDefault, - fontWeight: FontWeight.w400, - fontSize: 26, - ); - case ThemeType.oledBlack: - return GoogleFonts.roboto( - color: _theme(context).numberTextDefault, - fontWeight: FontWeight.w400, - fontSize: 26, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.roboto( - color: _theme(context).numberTextDefault, - fontWeight: FontWeight.w400, - fontSize: 26, - ); - case ThemeType.forest: + default: return GoogleFonts.roboto( color: _theme(context).numberTextDefault, fontWeight: FontWeight.w400, @@ -2586,42 +711,7 @@ class STextStyles { static TextStyle datePicker400(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - letterSpacing: 0.5, - color: _theme(context).accentColorDark, - fontWeight: FontWeight.w400, - fontSize: 12, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - letterSpacing: 0.5, - color: _theme(context).accentColorDark, - fontWeight: FontWeight.w400, - fontSize: 12, - ); - case ThemeType.dark: - return GoogleFonts.inter( - letterSpacing: 0.5, - color: _theme(context).accentColorDark, - fontWeight: FontWeight.w400, - fontSize: 12, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - letterSpacing: 0.5, - color: _theme(context).accentColorDark, - fontWeight: FontWeight.w400, - fontSize: 12, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - letterSpacing: 0.5, - color: _theme(context).accentColorDark, - fontWeight: FontWeight.w400, - fontSize: 12, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( letterSpacing: 0.5, color: _theme(context).accentColorDark, @@ -2633,42 +723,7 @@ class STextStyles { static TextStyle datePicker600(BuildContext context) { switch (_theme(context).themeType) { - case ThemeType.light: - return GoogleFonts.inter( - letterSpacing: 0.5, - color: _theme(context).accentColorDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.oceanBreeze: - return GoogleFonts.inter( - letterSpacing: 0.5, - color: _theme(context).accentColorDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.dark: - return GoogleFonts.inter( - letterSpacing: 0.5, - color: _theme(context).accentColorDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.oledBlack: - return GoogleFonts.inter( - letterSpacing: 0.5, - color: _theme(context).accentColorDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.fruitSorbet: - return GoogleFonts.inter( - letterSpacing: 0.5, - color: _theme(context).accentColorDark, - fontWeight: FontWeight.w600, - fontSize: 16, - ); - case ThemeType.forest: + default: return GoogleFonts.inter( letterSpacing: 0.5, color: _theme(context).accentColorDark, diff --git a/lib/utilities/theme/chan_colors.dart b/lib/utilities/theme/chan_colors.dart new file mode 100644 index 000000000..f9ea1bb54 --- /dev/null +++ b/lib/utilities/theme/chan_colors.dart @@ -0,0 +1,351 @@ +import 'package:flutter/material.dart'; +import 'package:stackwallet/utilities/theme/color_theme.dart'; + +class ChanColors extends StackColorTheme { + @override + ThemeType get themeType => ThemeType.chan; + @override + Brightness get brightness => Brightness.light; + + @override + Color get background => const Color(0xFFF7F7F7); + @override + Color get backgroundAppBar => background; + @override + Gradient? get gradientBackground => null; + + @override + Color get overlay => const Color(0xFF111215); + + @override + Color get accentColorBlue => const Color(0xFF0052DF); + @override + Color get accentColorGreen => const Color(0xFF4CC0A0); + @override + Color get accentColorYellow => const Color(0xFFF7D65D); + @override + Color get accentColorRed => const Color(0xFFD34E50); + @override + Color get accentColorOrange => const Color(0xFFFEA68D); + @override + Color get accentColorDark => const Color(0xFF232323); + + @override + Color get shadow => const Color(0x0F2D3132); + + @override + Color get textDark => const Color(0xFF232323); + @override + Color get textDark2 => const Color(0xFF414141); + @override + Color get textDark3 => const Color(0xFF747778); + @override + Color get textSubtitle1 => const Color(0xFF8E9192); + @override + Color get textSubtitle2 => const Color(0xFFA9ACAC); + @override + Color get textSubtitle3 => const Color(0xFFC4C7C7); + @override + Color get textSubtitle4 => const Color(0xFFE0E3E3); + @override + Color get textSubtitle5 => const Color(0xFFEEEFF1); + @override + Color get textSubtitle6 => const Color(0xFFF5F5F5); + @override + Color get textWhite => const Color(0xFFFFFFFF); + @override + Color get textFavoriteCard => const Color(0xFF232323); + @override + Color get textError => const Color(0xFF930006); + @override + Color get textRestore => overlay; + + // button background + @override + Color get buttonBackPrimary => const Color(0xFF232323); + @override + Color get buttonBackSecondary => const Color(0xFFE0E3E3); + @override + Color get buttonBackPrimaryDisabled => const Color(0xFFD7D7D7); + @override + Color get buttonBackSecondaryDisabled => const Color(0xFFF0F1F1); + @override + Color get buttonBackBorder => const Color(0xFF232323); + @override + Color get buttonBackBorderDisabled => const Color(0xFFB6B6B6); + @override + Color get buttonBackBorderSecondary => buttonBackSecondary; + @override + Color get buttonBackBorderSecondaryDisabled => buttonBackSecondaryDisabled; + + @override + Color get numberBackDefault => const Color(0xFFFFFFFF); + @override + Color get numpadBackDefault => const Color(0xFF232323); + @override + Color get bottomNavBack => const Color(0xFFFFFFFF); + + // button text/element + @override + Color get buttonTextPrimary => const Color(0xFFFFFFFF); + @override + Color get buttonTextSecondary => const Color(0xFF232323); + @override + Color get buttonTextPrimaryDisabled => const Color(0xFFF8F8F8); + @override + Color get buttonTextSecondaryDisabled => const Color(0xFFB7B7B7); + @override + Color get buttonTextBorder => const Color(0xFF232323); + @override + Color get buttonTextDisabled => const Color(0xFFB6B6B6); + @override + Color get buttonTextBorderless => const Color(0xFF0052DF); + @override + Color get buttonTextBorderlessDisabled => const Color(0xFFB6B6B6); + @override + Color get numberTextDefault => const Color(0xFF232323); + @override + Color get numpadTextDefault => const Color(0xFFFFFFFF); + @override + Color get bottomNavText => const Color(0xFF232323); + @override + Color get customTextButtonEnabledText => buttonTextBorderless; + @override + Color get customTextButtonDisabledText => textSubtitle1; + + // switch + @override + Color get switchBGOn => const Color(0xFF0052DF); + @override + Color get switchBGOff => const Color(0xFFD8E4FB); + @override + Color get switchBGDisabled => const Color(0xFFC5C6C9); + @override + Color get switchCircleOn => const Color(0xFFDAE2FF); + @override + Color get switchCircleOff => const Color(0xFFFBFCFF); + @override + Color get switchCircleDisabled => const Color(0xFFFBFCFF); + + // step indicator background + @override + Color get stepIndicatorBGCheck => const Color(0xFFD9E2FF); + @override + Color get stepIndicatorBGNumber => const Color(0xFFD9E2FF); + @override + Color get stepIndicatorBGInactive => const Color(0xFFCDCDCD); + @override + Color get stepIndicatorBGLines => const Color(0xFF0056D2); + @override + Color get stepIndicatorBGLinesInactive => const Color(0xFFCDCDCD); + @override + Color get stepIndicatorIconText => const Color(0xFF0056D2); + @override + Color get stepIndicatorIconNumber => const Color(0xFF0056D2); + @override + Color get stepIndicatorIconInactive => const Color(0xFFF7F7F7); + + // checkbox + @override + Color get checkboxBGChecked => const Color(0xFF0056D2); + @override + Color get checkboxBorderEmpty => const Color(0xFF8E9192); + @override + Color get checkboxBGDisabled => const Color(0xFFADC7EC); + @override + Color get checkboxIconChecked => const Color(0xFFFFFFFF); + @override + Color get checkboxIconDisabled => const Color(0xFFFFFFFF); + @override + Color get checkboxTextLabel => const Color(0xFF232323); + + // snack bar + @override + Color get snackBarBackSuccess => const Color(0xFFB9E9D4); + @override + Color get snackBarBackError => const Color(0xFFFFDAD4); + @override + Color get snackBarBackInfo => const Color(0xFFDAE2FF); + @override + Color get snackBarTextSuccess => const Color(0xFF006C4D); + @override + Color get snackBarTextError => const Color(0xFF930006); + @override + Color get snackBarTextInfo => const Color(0xFF002A78); + + // icons + @override + Color get bottomNavIconBack => const Color(0xFFA2A2A2); + @override + Color get bottomNavIconIcon => const Color(0xFF232323); + + @override + Color get topNavIconPrimary => const Color(0xFF232323); + @override + Color get topNavIconGreen => const Color(0xFF00A578); + @override + Color get topNavIconYellow => const Color(0xFFF4C517); + @override + Color get topNavIconRed => const Color(0xFFC00205); + + @override + Color get settingsIconBack => const Color(0xFFE0E3E3); + @override + Color get settingsIconIcon => const Color(0xFF232323); + @override + Color get settingsIconBack2 => const Color(0xFF94D6C4); + @override + Color get settingsIconElement => const Color(0xFF00A578); + + // text field + @override + Color get textFieldActiveBG => const Color(0xFFEEEFF1); + @override + Color get textFieldDefaultBG => const Color(0xFFEEEFF1); + @override + Color get textFieldErrorBG => const Color(0xFFFFDAD4); + @override + Color get textFieldSuccessBG => const Color(0xFFB9E9D4); + @override + Color get textFieldErrorBorder => textFieldErrorBG; + @override + Color get textFieldSuccessBorder => textFieldSuccessBG; + + @override + Color get textFieldActiveSearchIconLeft => const Color(0xFFA9ACAC); + @override + Color get textFieldDefaultSearchIconLeft => const Color(0xFFA9ACAC); + @override + Color get textFieldErrorSearchIconLeft => const Color(0xFF930006); + @override + Color get textFieldSuccessSearchIconLeft => const Color(0xFF006C4D); + + @override + Color get textFieldActiveText => const Color(0xFF232323); + @override + Color get textFieldDefaultText => const Color(0xFFA9ACAC); + @override + Color get textFieldErrorText => const Color(0xFF000000); + @override + Color get textFieldSuccessText => const Color(0xFF000000); + + @override + Color get textFieldActiveLabel => const Color(0xFFA9ACAC); + @override + Color get textFieldErrorLabel => const Color(0xFF930006); + @override + Color get textFieldSuccessLabel => const Color(0xFF006C4D); + + @override + Color get textFieldActiveSearchIconRight => const Color(0xFF747778); + @override + Color get textFieldDefaultSearchIconRight => const Color(0xFF747778); + @override + Color get textFieldErrorSearchIconRight => const Color(0xFF930006); + @override + Color get textFieldSuccessSearchIconRight => const Color(0xFF006C4D); + + // settings item level2 + @override + Color get settingsItem2ActiveBG => const Color(0xFFFFFFFF); + @override + Color get settingsItem2ActiveText => const Color(0xFF232323); + @override + Color get settingsItem2ActiveSub => const Color(0xFF8E9192); + + // radio buttons + @override + Color get radioButtonIconBorder => const Color(0xFF0056D2); + @override + Color get radioButtonIconBorderDisabled => const Color(0xFF8F909A); + @override + Color get radioButtonBorderEnabled => const Color(0xFF0056D2); + @override + Color get radioButtonBorderDisabled => const Color(0xFF8F909A); + @override + Color get radioButtonIconCircle => const Color(0xFF0056D2); + @override + Color get radioButtonIconEnabled => const Color(0xFF0056D2); + @override + Color get radioButtonTextEnabled => const Color(0xFF44464E); + @override + Color get radioButtonTextDisabled => const Color(0xFF44464E); + @override + Color get radioButtonLabelEnabled => const Color(0xFF8E9192); + @override + Color get radioButtonLabelDisabled => const Color(0xFF8E9192); + + // info text + @override + Color get infoItemBG => const Color(0xFFFFFFFF); + @override + Color get infoItemLabel => const Color(0xFF8E9192); + @override + Color get infoItemText => const Color(0xFF232323); + @override + Color get infoItemIcons => const Color(0xFF0056D2); + + // popup + @override + Color get popupBG => const Color(0xFFFFFFFF); + + // currency list + @override + Color get currencyListItemBG => const Color(0xFFF9F9FC); + + // bottom nav + @override + Color get stackWalletBG => const Color(0xFFFFFFFF); + @override + Color get stackWalletMid => const Color(0xFFFFFFFF); + @override + Color get stackWalletBottom => const Color(0xFF232323); + @override + Color get bottomNavShadow => const Color(0xFF282E33); + + @override + Color get favoriteStarActive => infoItemIcons; + @override + Color get favoriteStarInactive => textSubtitle3; + + @override + Color get splash => const Color(0x358E9192); + @override + Color get highlight => const Color(0x44A9ACAC); + @override + Color get warningForeground => textDark; + @override + Color get warningBackground => const Color(0xFFFFDAD3); + @override + Color get loadingOverlayTextColor => const Color(0xFFF7F7F7); + @override + Color get myStackContactIconBG => textFieldDefaultBG; + @override + Color get textConfirmTotalAmount => const Color(0xFF232323); + @override + Color get textSelectedWordTableItem => const Color(0xFF232323); + + //rate type toggle + @override + Color get rateTypeToggleColorOn => textFieldDefaultBG; + @override + Color get rateTypeToggleColorOff => popupBG; + @override + Color get rateTypeToggleDesktopColorOn => textFieldDefaultBG; + @override + Color get rateTypeToggleDesktopColorOff => buttonBackSecondary; + + @override + BoxShadow get standardBoxShadow => BoxShadow( + color: shadow, + spreadRadius: 3, + blurRadius: 4, + ); + + @override + BoxShadow? get homeViewButtonBarBoxShadow => BoxShadow( + color: shadow, + spreadRadius: 3, + blurRadius: 4, + ); +} diff --git a/lib/utilities/theme/color_theme.dart b/lib/utilities/theme/color_theme.dart index 713e186d1..f04a81932 100644 --- a/lib/utilities/theme/color_theme.dart +++ b/lib/utilities/theme/color_theme.dart @@ -7,7 +7,17 @@ import 'package:stackwallet/utilities/theme/light_colors.dart'; import 'package:stackwallet/utilities/theme/ocean_breeze_colors.dart'; import 'package:stackwallet/utilities/theme/oled_black_colors.dart'; -enum ThemeType { light, dark, oceanBreeze, oledBlack, fruitSorbet, forest } +import 'chan_colors.dart'; + +enum ThemeType { + light, + dark, + oceanBreeze, + oledBlack, + fruitSorbet, + forest, + chan; +} // adjust this file @@ -16,6 +26,8 @@ extension ThemeTypeExt on ThemeType { switch (this) { case ThemeType.light: return LightColors(); + case ThemeType.chan: + return ChanColors(); case ThemeType.dark: return DarkColors(); case ThemeType.oceanBreeze: @@ -33,6 +45,8 @@ extension ThemeTypeExt on ThemeType { switch (this) { case ThemeType.light: return "Light"; + case ThemeType.chan: + return "Crypto Chans"; case ThemeType.dark: return "Dark"; case ThemeType.oceanBreeze: @@ -49,6 +63,7 @@ extension ThemeTypeExt on ThemeType { abstract class StackColorTheme { ThemeType get themeType; + Brightness get brightness; Color get background; Color get backgroundAppBar; diff --git a/lib/utilities/theme/dark_colors.dart b/lib/utilities/theme/dark_colors.dart index e91c7d126..fbbf113ef 100644 --- a/lib/utilities/theme/dark_colors.dart +++ b/lib/utilities/theme/dark_colors.dart @@ -4,6 +4,8 @@ import 'package:stackwallet/utilities/theme/color_theme.dart'; class DarkColors extends StackColorTheme { @override ThemeType get themeType => ThemeType.dark; + @override + Brightness get brightness => Brightness.dark; @override Color get background => const Color(0xFF2A2D34); diff --git a/lib/utilities/theme/forest_colors.dart b/lib/utilities/theme/forest_colors.dart index 62e7f029a..d6854d6e8 100644 --- a/lib/utilities/theme/forest_colors.dart +++ b/lib/utilities/theme/forest_colors.dart @@ -4,6 +4,8 @@ import 'package:stackwallet/utilities/theme/color_theme.dart'; class ForestColors extends StackColorTheme { @override ThemeType get themeType => ThemeType.forest; + @override + Brightness get brightness => Brightness.light; @override Color get background => const Color(0xFFF3FAF5); diff --git a/lib/utilities/theme/fruit_sorbet_colors.dart b/lib/utilities/theme/fruit_sorbet_colors.dart index 548280933..a13985a93 100644 --- a/lib/utilities/theme/fruit_sorbet_colors.dart +++ b/lib/utilities/theme/fruit_sorbet_colors.dart @@ -4,6 +4,8 @@ import 'package:stackwallet/utilities/theme/color_theme.dart'; class FruitSorbetColors extends StackColorTheme { @override ThemeType get themeType => ThemeType.fruitSorbet; + @override + Brightness get brightness => Brightness.light; @override Color get background => Colors.transparent; diff --git a/lib/utilities/theme/light_colors.dart b/lib/utilities/theme/light_colors.dart index 8c9b4dcc5..b42f2dd9a 100644 --- a/lib/utilities/theme/light_colors.dart +++ b/lib/utilities/theme/light_colors.dart @@ -4,6 +4,8 @@ import 'package:stackwallet/utilities/theme/color_theme.dart'; class LightColors extends StackColorTheme { @override ThemeType get themeType => ThemeType.light; + @override + Brightness get brightness => Brightness.light; @override Color get background => const Color(0xFFF7F7F7); diff --git a/lib/utilities/theme/ocean_breeze_colors.dart b/lib/utilities/theme/ocean_breeze_colors.dart index 51831f2e5..9390c55b5 100644 --- a/lib/utilities/theme/ocean_breeze_colors.dart +++ b/lib/utilities/theme/ocean_breeze_colors.dart @@ -4,6 +4,8 @@ import 'package:stackwallet/utilities/theme/color_theme.dart'; class OceanBreezeColors extends StackColorTheme { @override ThemeType get themeType => ThemeType.oceanBreeze; + @override + Brightness get brightness => Brightness.light; @override Color get background => Colors.transparent; diff --git a/lib/utilities/theme/oled_black_colors.dart b/lib/utilities/theme/oled_black_colors.dart index 025f76f7d..71d4b2361 100644 --- a/lib/utilities/theme/oled_black_colors.dart +++ b/lib/utilities/theme/oled_black_colors.dart @@ -4,6 +4,8 @@ import 'package:stackwallet/utilities/theme/color_theme.dart'; class OledBlackColors extends StackColorTheme { @override ThemeType get themeType => ThemeType.oledBlack; + @override + Brightness get brightness => Brightness.dark; @override Color get background => const Color(0xFF000000); diff --git a/lib/utilities/theme/stack_colors.dart b/lib/utilities/theme/stack_colors.dart index d0ba2cd40..08614b8c5 100644 --- a/lib/utilities/theme/stack_colors.dart +++ b/lib/utilities/theme/stack_colors.dart @@ -4,6 +4,7 @@ import 'package:stackwallet/utilities/theme/color_theme.dart'; class StackColors extends ThemeExtension { final ThemeType themeType; + final Brightness brightness; final Color background; final Color backgroundAppBar; @@ -191,6 +192,7 @@ class StackColors extends ThemeExtension { StackColors({ required this.themeType, + required this.brightness, required this.background, required this.backgroundAppBar, required this.gradientBackground, @@ -340,6 +342,7 @@ class StackColors extends ThemeExtension { factory StackColors.fromStackColorTheme(StackColorTheme colorTheme) { return StackColors( themeType: colorTheme.themeType, + brightness: colorTheme.brightness, background: colorTheme.background, backgroundAppBar: colorTheme.backgroundAppBar, gradientBackground: colorTheme.gradientBackground, @@ -493,6 +496,7 @@ class StackColors extends ThemeExtension { @override ThemeExtension copyWith({ ThemeType? themeType, + Brightness? brightness, Color? background, Color? backgroundAppBar, Gradient? gradientBackground, @@ -640,6 +644,7 @@ class StackColors extends ThemeExtension { }) { return StackColors( themeType: themeType ?? this.themeType, + brightness: brightness ?? this.brightness, background: background ?? this.background, backgroundAppBar: backgroundAppBar ?? this.backgroundAppBar, gradientBackground: gradientBackground ?? this.gradientBackground, @@ -845,6 +850,7 @@ class StackColors extends ThemeExtension { return StackColors( themeType: other.themeType, + brightness: other.brightness, gradientBackground: other.gradientBackground, homeViewButtonBarBoxShadow: other.homeViewButtonBarBoxShadow, standardBoxShadow: other.standardBoxShadow, diff --git a/lib/widgets/app_bar_field.dart b/lib/widgets/app_bar_field.dart new file mode 100644 index 000000000..d579dc3db --- /dev/null +++ b/lib/widgets/app_bar_field.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; + +class AppBarSearchField extends StatefulWidget { + const AppBarSearchField({ + Key? key, + required this.controller, + this.focusNode, + }) : super(key: key); + + final TextEditingController? controller; + final FocusNode? focusNode; + + @override + State createState() => _AppBarSearchFieldState(); +} + +class _AppBarSearchFieldState extends State { + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + width: 16, + ), + Expanded( + child: TextField( + autofocus: true, + focusNode: widget.focusNode, + controller: widget.controller, + style: STextStyles.field(context), + decoration: InputDecoration( + fillColor: Colors.transparent, + hintText: "Search...", + hintStyle: STextStyles.fieldLabel(context), + border: InputBorder.none, + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + ), + ), + ), + ], + ); + } +} diff --git a/lib/widgets/background.dart b/lib/widgets/background.dart index a0ae868e3..ed74e36ff 100644 --- a/lib/widgets/background.dart +++ b/lib/widgets/background.dart @@ -20,14 +20,6 @@ class Background extends StatelessWidget { bool shouldPad = false; switch (Theme.of(context).extension()!.themeType) { - case ThemeType.light: - case ThemeType.dark: - case ThemeType.oledBlack: - color = Theme.of(context).extension()!.background; - break; - case ThemeType.forest: - color = Theme.of(context).extension()!.background; - break; case ThemeType.oceanBreeze: shouldPad = true; color = null; @@ -35,6 +27,9 @@ class Background extends StatelessWidget { case ThemeType.fruitSorbet: color = null; break; + default: + color = Theme.of(context).extension()!.background; + break; } final bgAsset = Assets.svg.background(context); diff --git a/lib/widgets/custom_buttons/dropdown_button.dart b/lib/widgets/custom_buttons/dropdown_button.dart new file mode 100644 index 000000000..d639ccf54 --- /dev/null +++ b/lib/widgets/custom_buttons/dropdown_button.dart @@ -0,0 +1,374 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/animated_widgets/rotate_icon.dart'; +import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; + +class JDropdownButton extends StatefulWidget { + const JDropdownButton({ + Key? key, + this.label, + required this.items, + this.width, + this.onSelectionChanged, + this.groupValue, + this.redrawOnScreenSizeChanged = false, + this.showIcon = false, + }) : super(key: key); + + final String? label; + final double? width; + final void Function(T?)? onSelectionChanged; + final T? groupValue; + final Set items; + final bool showIcon; + + /// setting this to true should be done carefully + final bool redrawOnScreenSizeChanged; + + @override + State> createState() => _JDropdownButtonState(); +} + +class _JDropdownButtonState extends State> { + final _key = GlobalKey(); + final _rotateIconController = RotateIconController(); + + bool _isOpen = false; + + OverlayEntry? _entry; + + void close() { + if (_isOpen) { + _rotateIconController.reverse?.call(); + _entry?.remove(); + _isOpen = false; + } + } + + void open() { + final size = (_key.currentContext!.findRenderObject() as RenderBox).size; + _entry = OverlayEntry( + builder: (_) { + final position = (_key.currentContext!.findRenderObject() as RenderBox) + .localToGlobal(Offset.zero); + + if (widget.redrawOnScreenSizeChanged) { + // trigger rebuild + MediaQuery.of(context).size; + } + + return GestureDetector( + onTap: close, + child: _JDropdownButtonMenu( + size: size, + position: position, + items: widget.items + .map( + (e) => _JDropdownButtonItem( + value: e, + groupValue: widget.groupValue, + onSelected: (T value) { + widget.onSelectionChanged?.call(value); + close(); + }, + ), + ) + .toList(), + ), + ); + }, + ); + _rotateIconController.forward?.call(); + Overlay.of(context, rootOverlay: true).insert(_entry!); + _isOpen = true; + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + if (widget.redrawOnScreenSizeChanged && _isOpen) { + WidgetsBinding.instance.addPostFrameCallback((_) { + _entry?.markNeedsBuild(); + }); + } + return SecondaryButton( + key: _key, + buttonHeight: ButtonHeight.l, + trailingIcon: widget.showIcon + ? RotateIcon( + icon: SvgPicture.asset( + Assets.svg.chevronDown, + width: 10, + color: Theme.of(context) + .extension()! + .buttonTextSecondary, + ), + curve: Curves.easeInOutCubic, + controller: _rotateIconController, + animationDurationMultiplier: 0.1, + ) + : null, + width: widget.width, + label: widget.label ?? widget.groupValue.toString(), + onPressed: _isOpen ? close : open, + ); + } +} + +class JDropdownIconButton extends StatefulWidget { + const JDropdownIconButton({ + Key? key, + required this.items, + required this.displayPrefix, + this.onSelectionChanged, + this.groupValue, + this.redrawOnScreenSizeChanged = false, + this.mobileAppBar = false, + }) : super(key: key); + + final String displayPrefix; + final void Function(T?)? onSelectionChanged; + final T? groupValue; + final Set items; + final bool mobileAppBar; + + /// setting this to true should be done carefully + final bool redrawOnScreenSizeChanged; + + @override + State> createState() => _JDropdownIconButtonState(); +} + +class _JDropdownIconButtonState extends State> { + final _key = GlobalKey(); + + bool _isOpen = false; + + OverlayEntry? _entry; + + void close() { + if (_isOpen) { + _entry?.remove(); + _isOpen = false; + } + } + + void open() { + final size = (_key.currentContext!.findRenderObject() as RenderBox).size; + _entry = OverlayEntry( + builder: (_) { + final position = (_key.currentContext!.findRenderObject() as RenderBox) + .localToGlobal(Offset.zero); + + if (widget.redrawOnScreenSizeChanged) { + // trigger rebuild + MediaQuery.of(context).size; + } + + return GestureDetector( + onTap: close, + child: _JDropdownButtonMenu( + size: Size(200, size.height), + position: Offset(position.dx - 144, position.dy), + items: widget.items + .map( + (e) => _JDropdownButtonItem( + value: e, + groupValue: widget.groupValue, + displayPrefix: widget.displayPrefix, + onSelected: (T value) { + widget.onSelectionChanged?.call(value); + close(); + }, + ), + ) + .toList(), + ), + ); + }, + ); + Overlay.of(context, rootOverlay: true).insert(_entry!); + _isOpen = true; + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + if (widget.redrawOnScreenSizeChanged && _isOpen) { + WidgetsBinding.instance.addPostFrameCallback((_) { + _entry?.markNeedsBuild(); + }); + } + + if (widget.mobileAppBar) { + return AppBarIconButton( + key: _key, + size: 36, + icon: SvgPicture.asset( + Assets.svg.list, + width: 20, + height: 20, + color: Theme.of(context).extension()!.topNavIconPrimary, + ), + onPressed: _isOpen ? close : open, + ); + } else { + return SizedBox( + key: _key, + height: 56, + width: 56, + child: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context) + ?.copyWith( + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + side: BorderSide( + color: Theme.of(context) + .extension()! + .buttonBackBorderSecondary, + width: 1, + ), + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + ), + onPressed: _isOpen ? close : open, + child: SvgPicture.asset( + Assets.svg.list, + width: 20, + height: 20, + ), + ), + ); + } + } +} + +// ============================================================================= + +class _JDropdownButtonMenu extends StatefulWidget { + const _JDropdownButtonMenu( + {Key? key, + required this.items, + required this.size, + required this.position}) + : super(key: key); + + final List<_JDropdownButtonItem> items; + final Size size; + final Offset position; + + @override + State<_JDropdownButtonMenu> createState() => _JDropdownButtonMenuState(); +} + +class _JDropdownButtonMenuState extends State<_JDropdownButtonMenu> { + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: Stack( + children: [ + Container( + color: Colors.black.withOpacity(0.2), + // child: widget.content, + ), + Positioned( + top: widget.size.height + widget.position.dy + 10, + left: widget.position.dx, + width: widget.size.width, + child: RoundedWhiteContainer( + padding: EdgeInsets.zero, + radiusMultiplier: 2.5, + boxShadow: [ + Theme.of(context).extension()!.standardBoxShadow, + ], + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox( + height: 20, + ), + ...widget.items, + const SizedBox( + height: 20, + ), + ], + ), + ), + ), + ], + ), + ); + } +} + +// ============================================================================= + +class _JDropdownButtonItem extends StatelessWidget { + const _JDropdownButtonItem({ + Key? key, + required this.value, + required this.groupValue, + required this.onSelected, + this.height = 53, + this.displayPrefix, + }) : super(key: key); + + final T value; + final T? groupValue; + final double height; + final void Function(T) onSelected; + final String? displayPrefix; + + @override + Widget build(BuildContext context) { + return RawMaterialButton( + fillColor: groupValue == value + ? Theme.of(context).extension()!.textFieldDefaultBG + : Colors.transparent, + elevation: 0, + focusElevation: 0, + hoverElevation: 0, + highlightElevation: 0, + disabledElevation: 0, + padding: EdgeInsets.zero, + onPressed: () => onSelected(value), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + displayPrefix == null + ? value.toString() + : "$displayPrefix ${value.toString().toLowerCase()}", + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: Theme.of(context).extension()!.textDark, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/widgets/custom_buttons/simple_edit_button.dart b/lib/widgets/custom_buttons/simple_edit_button.dart index af1c9259e..931de7aa4 100644 --- a/lib/widgets/custom_buttons/simple_edit_button.dart +++ b/lib/widgets/custom_buttons/simple_edit_button.dart @@ -4,8 +4,12 @@ import 'package:stackwallet/pages/generic/single_field_edit_view.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; import 'package:tuple/tuple.dart'; +import '../desktop/desktop_dialog.dart'; +import '../icon_widgets/pencil_icon.dart'; + class SimpleEditButton extends StatelessWidget { const SimpleEditButton({ Key? key, @@ -20,36 +24,78 @@ class SimpleEditButton extends StatelessWidget { @override Widget build(BuildContext context) { - return GestureDetector( - onTap: () async { - final result = await Navigator.of(context).pushNamed( - SingleFieldEditView.routeName, - arguments: Tuple2( - editValue, - editLabel, + if (Util.isDesktop) { + return SizedBox( + height: 26, + width: 26, + child: RawMaterialButton( + fillColor: + Theme.of(context).extension()!.buttonBackSecondary, + elevation: 0, + hoverElevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), ), - ); - if (result is String && result != editValue) { - onValueChanged(result); - } - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.pencil, - width: 10, - height: 10, - color: Theme.of(context).extension()!.infoItemIcons, + onPressed: () async { + final result = await showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: 360, + child: SingleFieldEditView( + initialValue: editValue, + label: editLabel, + ), + ); + }, + ); + if (result is String && result != editValue) { + onValueChanged(result); + } + }, + child: Padding( + padding: const EdgeInsets.all(5), + child: PencilIcon( + width: 16, + height: 16, + color: Theme.of(context).extension()!.textDark, + ), ), - const SizedBox( - width: 4, - ), - Text( - "Edit", - style: STextStyles.link2(context), - ), - ], - ), - ); + ), + ); + } else { + return GestureDetector( + onTap: () async { + final result = await Navigator.of(context).pushNamed( + SingleFieldEditView.routeName, + arguments: Tuple2( + editValue, + editLabel, + ), + ); + if (result is String && result != editValue) { + onValueChanged(result); + } + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.pencil, + width: 10, + height: 10, + color: Theme.of(context).extension()!.infoItemIcons, + ), + const SizedBox( + width: 4, + ), + Text( + "Edit", + style: STextStyles.link2(context), + ), + ], + ), + ); + } } } diff --git a/lib/widgets/desktop/secondary_button.dart b/lib/widgets/desktop/secondary_button.dart index 6b4e46221..5d1ba1970 100644 --- a/lib/widgets/desktop/secondary_button.dart +++ b/lib/widgets/desktop/secondary_button.dart @@ -13,6 +13,7 @@ class SecondaryButton extends StatelessWidget { this.height, this.label, this.icon, + this.trailingIcon, this.onPressed, this.enabled = true, this.buttonHeight, @@ -25,6 +26,7 @@ class SecondaryButton extends StatelessWidget { final VoidCallback? onPressed; final bool enabled; final Widget? icon; + final Widget? trailingIcon; final ButtonHeight? buttonHeight; final double iconSpacing; @@ -155,6 +157,7 @@ class SecondaryButton extends StatelessWidget { .getSecondaryDisabledButtonStyle(context), child: Row( mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ if (icon != null) icon!, if (icon != null && label != null) @@ -177,6 +180,11 @@ class SecondaryButton extends StatelessWidget { ), ], ), + if (trailingIcon != null) + SizedBox( + width: iconSpacing, + ), + if (trailingIcon != null) trailingIcon!, ], ), ), diff --git a/lib/widgets/expandable2.dart b/lib/widgets/expandable2.dart new file mode 100644 index 000000000..4439d83e6 --- /dev/null +++ b/lib/widgets/expandable2.dart @@ -0,0 +1,182 @@ +import 'package:flutter/material.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; + +enum Expandable2State { + collapsed, + expanded, +} + +class Expandable2Controller { + VoidCallback? toggle; + Expandable2State state = Expandable2State.collapsed; +} + +class Expandable2 extends StatefulWidget { + const Expandable2({ + Key? key, + required this.header, + required this.children, + this.background = Colors.white, + this.border = Colors.black, + this.animationController, + this.animation, + this.animationDurationMultiplier = 1.0, + this.onExpandWillChange, + this.onExpandChanged, + this.controller, + this.expandOverride, + }) : super(key: key); + + final Widget header; + final List children; + final Color background; + final Color border; + final AnimationController? animationController; + final Animation? animation; + final double animationDurationMultiplier; + final void Function(Expandable2State)? onExpandWillChange; + final void Function(Expandable2State)? onExpandChanged; + final Expandable2Controller? controller; + final VoidCallback? expandOverride; + + @override + State createState() => _Expandable2State(); +} + +class _Expandable2State extends State + with TickerProviderStateMixin { + final _key = GlobalKey(); + + late final AnimationController animationController; + late final Animation animation; + late final Duration duration; + late final Expandable2Controller? controller; + + Expandable2State _toggleState = Expandable2State.collapsed; + + void toggle() { + if (animation.isDismissed) { + _toggleState = Expandable2State.expanded; + widget.onExpandWillChange?.call(_toggleState); + animationController + .forward() + .then((_) => widget.onExpandChanged?.call(_toggleState)); + } else if (animation.isCompleted) { + _toggleState = Expandable2State.collapsed; + widget.onExpandWillChange?.call(_toggleState); + animationController + .reverse() + .then((_) => widget.onExpandChanged?.call(_toggleState)); + } + controller?.state = _toggleState; + setState(() {}); + } + + @override + void initState() { + controller = widget.controller; + controller?.toggle = toggle; + + duration = Duration( + milliseconds: (500 * widget.animationDurationMultiplier).toInt(), + ); + animationController = widget.animationController ?? + AnimationController( + vsync: this, + duration: duration, + ); + animation = widget.animation ?? + Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + curve: Curves.easeInOut, + parent: animationController, + ), + ); + super.initState(); + } + + double _top = 0; + + void getHeaderHeight() { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (_key.currentContext?.size?.height != null && + _top != _key.currentContext!.size!.height) { + setState(() { + _top = _key.currentContext!.size!.height; + }); + } + }); + } + + @override + void dispose() { + animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + getHeaderHeight(); + + return AnimatedContainer( + duration: duration, + decoration: _toggleState == Expandable2State.expanded + ? BoxDecoration( + color: widget.background, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + border: Border.all(color: widget.border), + boxShadow: [ + Theme.of(context).extension()!.standardBoxShadow, + ], + ) + : BoxDecoration( + color: widget.background, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + border: Border.all(color: widget.border), + ), + child: Stack( + children: [ + Padding( + padding: EdgeInsets.only(top: _top), + child: SizeTransition( + sizeFactor: animation, + axisAlignment: 1.0, + child: Column( + children: widget.children + .map( + (e) => Column( + children: [ + Container( + height: 1, + width: double.infinity, + color: widget.border, + ), + e, + ], + ), + ) + .toList(), + ), + ), + ), + MouseRegion( + key: _key, + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: widget.expandOverride ?? toggle, + child: Container( + color: Colors.transparent, + child: widget.header, + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/widgets/rounded_container.dart b/lib/widgets/rounded_container.dart index d689d9ca8..7f8456da8 100644 --- a/lib/widgets/rounded_container.dart +++ b/lib/widgets/rounded_container.dart @@ -1,5 +1,6 @@ -import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/widgets/conditional_parent.dart'; class RoundedContainer extends StatelessWidget { const RoundedContainer({ @@ -12,6 +13,7 @@ class RoundedContainer extends StatelessWidget { this.height, this.borderColor, this.boxShadow, + this.onPressed, }) : super(key: key); final Widget? child; @@ -22,24 +24,39 @@ class RoundedContainer extends StatelessWidget { final double? height; final Color? borderColor; final List? boxShadow; + final VoidCallback? onPressed; @override Widget build(BuildContext context) { - return Container( - width: width, - height: height, - decoration: BoxDecoration( - color: color, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius * radiusMultiplier, + return ConditionalParent( + condition: onPressed != null, + builder: (child) => RawMaterialButton( + padding: const EdgeInsets.all(0), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius * radiusMultiplier, + ), ), - border: borderColor == null ? null : Border.all(color: borderColor!), - boxShadow: boxShadow, - ), - child: Padding( - padding: padding, + onPressed: onPressed, child: child, ), + child: Container( + width: width, + height: height, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius * radiusMultiplier, + ), + border: borderColor == null ? null : Border.all(color: borderColor!), + boxShadow: boxShadow, + ), + child: Padding( + padding: padding, + child: child, + ), + ), ); } } diff --git a/lib/widgets/transaction_card.dart b/lib/widgets/transaction_card.dart index 77a76f116..e269ace4d 100644 --- a/lib/widgets/transaction_card.dart +++ b/lib/widgets/transaction_card.dart @@ -224,8 +224,7 @@ class _TransactionCardState extends ConsumerState { final amount = _transaction.amount; return Text( "$prefix${Format.satoshiAmountToPrettyString(amount, locale, coin)} ${coin.ticker}", - style: - STextStyles.itemSubtitle12_600(context), + style: STextStyles.itemSubtitle12(context), ); }, ), diff --git a/lib/widgets/wallet_navigation_bar/wallet_navigation_bar.dart b/lib/widgets/wallet_navigation_bar/wallet_navigation_bar.dart index 31e796eb9..d8f58450f 100644 --- a/lib/widgets/wallet_navigation_bar/wallet_navigation_bar.dart +++ b/lib/widgets/wallet_navigation_bar/wallet_navigation_bar.dart @@ -107,6 +107,7 @@ class _WalletNavigationBarState extends ConsumerState { ), ), Material( + color: Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( 1000, diff --git a/pubspec.lock b/pubspec.lock index 8b49567e4..fdf6de547 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -66,7 +66,7 @@ packages: source: hosted version: "1.4.0" async: - dependency: transitive + dependency: "direct main" description: name: async sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 diff --git a/pubspec.yaml b/pubspec.yaml index 9e4be9307..745d24b52 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: Stack Wallet # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.6.1+143 +version: 1.6.2+144 environment: sdk: ">=2.17.0 <3.0.0" @@ -141,6 +141,7 @@ dependencies: dropdown_button2: 1.7.2 string_validator: ^0.3.0 equatable: ^2.0.5 + async: ^2.10.0 dev_dependencies: flutter_test: @@ -206,9 +207,9 @@ flutter: - google_fonts/ - assets/svg/circle-check.svg - assets/svg/clipboard.svg - - assets/images/unclaimed.png - assets/images/glasses.png - assets/images/glasses-hidden.png + - assets/svg/unclaimed.svg - assets/svg/plus.svg - assets/svg/gear.svg - assets/svg/bell.svg @@ -303,38 +304,6 @@ flutter: - assets/svg/whirlpool.svg - assets/svg/fingerprint.svg - assets/svg/faceid.svg - # light theme coin - - assets/images/light/ - - # dark theme coin - - assets/images/dark/ - - # oled black theme coin - - assets/images/oledBlack/ - - # ocean breeze theme coin - - assets/images/oceanBreeze/ - - # fruit sorbet theme coin - - assets/images/fruitSorbet/ - - # forest theme coin - - assets/images/forest/ - - # coin icons - - assets/svg/coin_icons/ - - # coin control icons - - assets/svg/coin_control/ - - # lottie animations - - assets/lottie/test.json - - assets/lottie/test2.json - # socials - - assets/svg/socials/discord.svg - - assets/svg/socials/reddit-alien-brands.svg - - assets/svg/socials/twitter-brands.svg - - assets/svg/socials/telegram-brands.svg - assets/svg/chevron-right.svg - assets/svg/minimize.svg - assets/svg/wallet-fa.svg @@ -344,11 +313,20 @@ flutter: - assets/svg/box-auto.svg - assets/svg/framed-address-book.svg - assets/svg/framed-gear.svg + - assets/svg/list-ul.svg + + + # coin icons + - assets/svg/coin_icons/ + + # coin control icons + - assets/svg/coin_control/ + + # socials + - assets/svg/socials/ + # exchange icons - - assets/svg/exchange_icons/change_now_logo_1.svg - - assets/svg/exchange_icons/simpleswap-icon.svg - - assets/svg/exchange_icons/mb_green.svg - - assets/svg/exchange_icons/mb_blue.svg + - assets/svg/exchange_icons/ # theme selectors - assets/svg/dark-theme.svg @@ -357,28 +335,46 @@ flutter: - assets/svg/oled-black-theme.svg - assets/svg/fruit-sorbet-theme.svg - assets/svg/forest-theme.svg + - assets/svg/chanstheme.svg # light theme specific - - assets/svg/light/ + - assets/svg/themed/light/ # dark theme specific - - assets/svg/dark/ + - assets/svg/themed/dark/ # ocean theme specific - - assets/svg/oceanBreeze/ + - assets/svg/themed/oceanBreeze/ # OLED black theme specific - - assets/svg/oledBlack/ + - assets/svg/themed/oledBlack/ # fruit sorbet theme specific - - assets/svg/fruitSorbet/ + - assets/svg/themed/fruitSorbet/ # forest theme specific - - assets/svg/forest/ + - assets/svg/themed/forest/ # buy - - assets/svg/buy/Simplex-Nuvei-Logo.svg - - assets/svg/buy/Simplex-Nuvei-Logo-light.svg + - assets/svg/buy/ + + + # lottie animations + # basic + - assets/lottie/test2.json + + # coin gifs + - assets/gif/coins/bitcoin/ + - assets/gif/coins/bitcoincash/ + - assets/gif/coins/dogecoin/ + - assets/gif/coins/epicCash/ + - assets/gif/coins/ethereum/ + - assets/gif/coins/firo/ + - assets/gif/coins/litecoin/ + - assets/gif/coins/monero/ + - assets/gif/coins/namecoin/ + - assets/gif/coins/particl/ + - assets/gif/coins/wownero/ # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware.