diff --git a/assets/_locales/en/messages.json b/assets/_locales/en/messages.json index 23b246dbc..3782aa83e 100644 --- a/assets/_locales/en/messages.json +++ b/assets/_locales/en/messages.json @@ -324,7 +324,7 @@ "description": "Remove app button" }, "removeAppNote": { - "message": "This will remove all permissions from the app and disconnect it from ArConnect.", + "message": "Remove all permissions and disconnect the app from ArConnect.", "description": "Remove app note paragraph" }, "remove": { @@ -517,6 +517,10 @@ } } }, + "copied_address_2": { + "message": "address copied", + "description": "Address copy notification 2" + }, "cannot_edit_with_ans": { "message": "Cannot edit nickname. Wallet already has an ANS label.", "description": "Explainer for disabled edits for wallets with ANS profiles" @@ -542,7 +546,7 @@ "description": "Password input placeholder" }, "enter_password_again": { - "message": "Re-enter your passwor...", + "message": "Re-enter your password...", "description": "Re-enter password input placeholder" }, "passwords_match": { diff --git a/package.json b/package.json index 756e72c9d..36e44b254 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "arconnect", "displayName": "ArConnect", - "version": "1.8.0", + "version": "1.9.0", "description": "__MSG_extensionDescription__", "author": "th8ta", "packageManager": "yarn@1.22.18", @@ -47,7 +47,7 @@ ] }, "dependencies": { - "@arconnect/components": "^0.2.8", + "@arconnect/components": "^0.3.7", "@arconnect/keystone-sdk": "^0.0.5", "@arconnect/warp-dre": "^0.0.1", "@arconnect/webext-bridge": "^5.0.6", diff --git a/src/components/IconButton.tsx b/src/components/IconButton.tsx index f8e4275ca..75701096a 100644 --- a/src/components/IconButton.tsx +++ b/src/components/IconButton.tsx @@ -1,9 +1,11 @@ import styled, { css, keyframes } from "styled-components"; -import { Button } from "@arconnect/components"; +import { ButtonV2 } from "@arconnect/components"; -export const IconButton = styled(Button)` +export const IconButton = styled(ButtonV2)` padding: 1.2rem; transition: all 0.23s ease-in-out; + height: 52px; + width: 100px; `; export const RefreshButton = styled(IconButton)<{ refreshing: boolean }>` diff --git a/src/components/Recipient.tsx b/src/components/Recipient.tsx index ced01456f..5ffcba51c 100644 --- a/src/components/Recipient.tsx +++ b/src/components/Recipient.tsx @@ -1,4 +1,10 @@ -import { useInput, Text, Button, Input } from "@arconnect/components"; +import { + useInput, + Text, + ButtonV2, + ListItem, + InputV2 +} from "@arconnect/components"; import { ChevronDownIcon, ChevronUpIcon } from "@iconicicons/react"; import { useStorage } from "@plasmohq/storage/hook"; import { useMemo, useState } from "react"; @@ -125,9 +131,8 @@ export default function Recipient({ onClick, onClose }: RecipientProps) { return ( <> - - + setShow(!show)}> @@ -175,28 +179,21 @@ export default function Recipient({ onClick, onClose }: RecipientProps) { {letter} {filteredAndGroupedContacts[letter].map((contact) => ( - { onClick({ contact, address: contact.address }); onClose(); }} - > - {contact.profileIcon ? ( - - ) : ( - - {generateProfileIcon(contact?.name || contact.address)} - - )} - -
- {contact?.name} - - {formatAddress(contact.address)} - -
-
+ /> ))} ))} diff --git a/src/components/arlocal/InputWrapper.tsx b/src/components/arlocal/InputWrapper.tsx index 44ca0a171..c6475a8f7 100644 --- a/src/components/arlocal/InputWrapper.tsx +++ b/src/components/arlocal/InputWrapper.tsx @@ -1,5 +1,5 @@ import { IconButton } from "~components/IconButton"; -import { Button } from "@arconnect/components"; +import { ButtonV2 } from "@arconnect/components"; import styled from "styled-components"; export const InputWithBtn = styled.div` @@ -7,10 +7,9 @@ export const InputWithBtn = styled.div` align-items: flex-end; gap: 0.8rem; - ${Button} { + ${ButtonV2} { padding-top: 0.9rem; padding-bottom: 0.9rem; - border-radius: 18px; } ${IconButton} { diff --git a/src/components/arlocal/Mint.tsx b/src/components/arlocal/Mint.tsx index 129c7e6ea..25e70ad39 100644 --- a/src/components/arlocal/Mint.tsx +++ b/src/components/arlocal/Mint.tsx @@ -1,6 +1,6 @@ import { - Button, - Input, + ButtonV2 as Button, + InputV2 as Input, Text, useInput, useToasts @@ -70,7 +70,7 @@ export default function Mint({ arweave }: Props) { fullWidth /> - diff --git a/src/components/arlocal/Transaction.tsx b/src/components/arlocal/Transaction.tsx index db11419a6..aaeb1f6b8 100644 --- a/src/components/arlocal/Transaction.tsx +++ b/src/components/arlocal/Transaction.tsx @@ -9,8 +9,8 @@ import { readFileBinary } from "~utils/file"; import { useRef, useState } from "react"; import { unlock } from "~wallets/auth"; import { - Button, - Input, + ButtonV2 as Button, + InputV2 as Input, Spacer, useInput, Text, @@ -289,7 +289,7 @@ export default function Transaction({ arweave }: Props) { secondary onClick={() => setTags((val) => val.filter((_, j) => j !== i))} > - + Trash diff --git a/src/components/arlocal/Tutorial.tsx b/src/components/arlocal/Tutorial.tsx index 79ec5d5b2..a095e9222 100644 --- a/src/components/arlocal/Tutorial.tsx +++ b/src/components/arlocal/Tutorial.tsx @@ -1,4 +1,9 @@ -import { Input, type InputStatus, Spacer, Text } from "@arconnect/components"; +import { + InputV2 as Input, + type InputStatus, + Spacer, + Text +} from "@arconnect/components"; import { InputWithBtn, InputWrapper } from "./InputWrapper"; import { IconButton } from "~components/IconButton"; import { CopyIcon } from "@iconicicons/react"; diff --git a/src/components/dashboard/Applications.tsx b/src/components/dashboard/Applications.tsx index f7690160d..c2efbc0e0 100644 --- a/src/components/dashboard/Applications.tsx +++ b/src/components/dashboard/Applications.tsx @@ -82,11 +82,12 @@ export default function Applications() { return ( - + + + {apps.filter(filterSearchResults).map((app, i) => ( @@ -117,6 +118,15 @@ const Wrapper = styled.div` position: relative; `; +const SearchWrapper = styled.div` + position: sticky; + top: 0; + left: 0; + right: 0; + z-index: 20; + background-color: rgb(${(props) => props.theme.cardBackground}); +`; + const NoAppsText = styled(Text)` text-align: center; padding-top: 0.5rem; diff --git a/src/components/dashboard/Contacts.tsx b/src/components/dashboard/Contacts.tsx index 071764295..25d7d1dc9 100644 --- a/src/components/dashboard/Contacts.tsx +++ b/src/components/dashboard/Contacts.tsx @@ -1,4 +1,4 @@ -import { Spacer, useInput } from "@arconnect/components"; +import { ButtonV2, Spacer, useInput } from "@arconnect/components"; import React, { useState, useEffect, useMemo } from "react"; import { useStorage } from "@plasmohq/storage/hook"; import { ExtensionStorage } from "~utils/storage"; @@ -8,7 +8,6 @@ import { useLocation, useRoute } from "wouter"; import browser from "webextension-polyfill"; import SearchInput from "./SearchInput"; import styled from "styled-components"; -import { IconButton } from "~components/IconButton"; import { formatAddress } from "~utils/format"; import { multiSort } from "~utils/multi_sort"; import { enrichContact } from "~contacts/hooks"; @@ -200,21 +199,16 @@ const LetterHeader = styled.div` const SearchWrapper = styled.div` position: sticky; display: grid; - gap: 5px; + gap: 8px; top: 0; left: 0; right: 0; z-index: 20; grid-template-columns: auto auto; + background-color: rgb(${(props) => props.theme.cardBackground}); `; -const AddContactButton = styled(IconButton).attrs({ - secondary: true -})` - background: linear-gradient( - 0deg, - rgba(${(props) => props.theme.theme}, 0.2), - rgba(${(props) => props.theme.theme}, 0.2) - ), - rgb(${(props) => props.theme.background}); +const AddContactButton = styled(ButtonV2)` + width: 100%; + height: 100%; `; diff --git a/src/components/dashboard/Reset.tsx b/src/components/dashboard/Reset.tsx index 962d20171..606dde608 100644 --- a/src/components/dashboard/Reset.tsx +++ b/src/components/dashboard/Reset.tsx @@ -1,15 +1,17 @@ import { Text, Spacer, - Button, + ButtonV2, useModal, - Modal, - useToasts + ModalV2, + useToasts, + type DisplayTheme } from "@arconnect/components"; import { ExtensionStorage } from "~utils/storage"; import { TrashIcon } from "@iconicicons/react"; import browser from "webextension-polyfill"; import styled from "styled-components"; +import { useTheme } from "~utils/theme"; export default function Reset() { // reset modal @@ -18,6 +20,8 @@ export default function Reset() { // toasts const { setToast } = useToasts(); + const theme = useTheme(); + // reset ArConnect async function reset() { try { @@ -58,23 +62,28 @@ export default function Reset() { {browser.i18n.getMessage("irreversible_action")} - resetModal.setOpen(true)}> - + resetModal.setOpen(true)} + > + {browser.i18n.getMessage("reset")} - + {browser.i18n.getMessage("confirm")} + + } > {browser.i18n.getMessage("reset")} {browser.i18n.getMessage("setting_reset_description")} - - {browser.i18n.getMessage("confirm")} - - + ); } @@ -83,15 +92,16 @@ const Warning = styled(Text)` color: #ff0000; `; -const ResetButton = styled(Button).attrs({ +const ResetButton = styled(ButtonV2).attrs({ secondary: true, fullWidth: true -})` - background-color: rgba(255, 0, 0, 0.2); - color: #ff0000; +})<{ displayTheme: DisplayTheme }>` + background-color: ${(props) => props.theme.delete}; + border: 1.5px solid ${(props) => props.theme.fail}; + color: #ffffff; - &:hover:not(:active):not(:disabled) { - box-shadow: 0 0 0 0.19rem rgb(255, 0, 0, 0.2); + &:hover { + background-color: ${(props) => props.theme.secondaryDelete}; } `; diff --git a/src/components/dashboard/SearchInput.tsx b/src/components/dashboard/SearchInput.tsx index 60dece140..938dd18fc 100644 --- a/src/components/dashboard/SearchInput.tsx +++ b/src/components/dashboard/SearchInput.tsx @@ -1,5 +1,4 @@ -import { setting_element_padding } from "./list/BaseElement"; -import { SearchIcon } from "@iconicicons/react"; +import { InputV2 } from "@arconnect/components"; import type { HTMLProps } from "react"; import styled from "styled-components"; @@ -8,23 +7,13 @@ export default function SearchInput( ) { return ( - - + ); } const Wrapper = styled.div` position: ${(props) => (props.sticky ? "sticky" : "relative")}; - background: linear-gradient( - 0deg, - rgba(${(props) => props.theme.cardBorder}, 0.7), - rgba(${(props) => props.theme.cardBorder}, 0.7) - ), - rgb(${(props) => props.theme.background}); - border-radius: 20px; - overflow: hidden; - z-index: 10; ${(props) => props.sticky @@ -33,43 +22,7 @@ const Wrapper = styled.div` left: 0; right: 0; ` - : ""} - - &:focus-within svg { - color: rgb(${(props) => props.theme.theme}); - } -`; - -const Input = styled.input.attrs({ - type: "text" -})` - margin: 0; - outline: none; - border: none; - background-color: transparent; - padding: calc(${setting_element_padding} * 3 / 2) ${setting_element_padding}; - padding-left: calc(${setting_element_padding} * 3 / 2); - width: calc(100% - ${setting_element_padding} * 2); - color: rgb(${(props) => props.theme.theme}); - font-size: 1rem; - font-weight: 500; - transition: all 0.23s ease-in-out; - - &::placeholder { - color: rgb(${(props) => props.theme.secondaryText}); - } -`; - -const InputSearchIcon = styled(SearchIcon)` - position: absolute; - top: 50%; - right: ${setting_element_padding}; - font-size: 1.25rem; - width: 1em; - height: 1em; - color: rgb(${(props) => props.theme.secondaryText}); - transition: all 0.23s ease-in-out; - transform: translate(-50%, -50%); + : ""}; `; interface Props { diff --git a/src/components/dashboard/Setting.tsx b/src/components/dashboard/Setting.tsx index 7eb1bb3d3..edf180fc0 100644 --- a/src/components/dashboard/Setting.tsx +++ b/src/components/dashboard/Setting.tsx @@ -1,4 +1,4 @@ -import { Input, Spacer, Text, useInput } from "@arconnect/components"; +import { InputV2, Spacer, Text, useInput } from "@arconnect/components"; import { setting_element_padding } from "./list/BaseElement"; import PermissionCheckbox from "~components/auth/PermissionCheckbox"; import type SettingType from "~settings/setting"; @@ -78,7 +78,7 @@ export default function Setting({ setting }: Props) { case "number": case "string": return ( - 6 && ( <> - + + + )} @@ -182,3 +183,12 @@ export const RadioItem = styled.div` ); } `; + +const SearchWrapper = styled.div` + position: sticky; + top: 0; + left: 0; + right: 0; + z-index: 20; + background-color: rgb(${(props) => props.theme.cardBackground}); +`; diff --git a/src/components/dashboard/SignSettings.tsx b/src/components/dashboard/SignSettings.tsx index 09786c4e3..e51be7070 100644 --- a/src/components/dashboard/SignSettings.tsx +++ b/src/components/dashboard/SignSettings.tsx @@ -1,6 +1,6 @@ import { useState, useEffect } from "react"; import PermissionCheckbox from "~components/auth/PermissionCheckbox"; -import { Input, Spacer, Text } from "@arconnect/components"; +import { InputV2, Spacer, Text } from "@arconnect/components"; import browser from "webextension-polyfill"; import styled from "styled-components"; import { ExtensionStorage } from "~utils/storage"; @@ -77,7 +77,7 @@ export default function SignSettings() { - - + ); } diff --git a/src/components/dashboard/Wallets.tsx b/src/components/dashboard/Wallets.tsx index 56129b427..53f6c2dc7 100644 --- a/src/components/dashboard/Wallets.tsx +++ b/src/components/dashboard/Wallets.tsx @@ -1,7 +1,6 @@ import { concatGatewayURL } from "~gateways/utils"; -import { Spacer, useInput } from "@arconnect/components"; +import { ButtonV2, Spacer, useInput } from "@arconnect/components"; import { useEffect, useMemo, useState } from "react"; -import { IconButton } from "~components/IconButton"; import { useStorage } from "@plasmohq/storage/hook"; import { type AnsUser, getAnsProfile } from "~lib/ans"; import { ExtensionStorage } from "~utils/storage"; @@ -156,22 +155,18 @@ const Wrapper = styled.div` const SearchWrapper = styled.div` position: sticky; display: grid; - gap: 1rem; + gap: 8px; top: 0; left: 0; right: 0; z-index: 20; grid-template-columns: auto auto; + background-color: rgb(${(props) => props.theme.cardBackground}); `; -const AddWalletButton = styled(IconButton).attrs({ - secondary: true +const AddWalletButton = styled(ButtonV2).attrs({ + secondary: false })` - background: linear-gradient( - 0deg, - rgba(${(props) => props.theme.theme}, 0.2), - rgba(${(props) => props.theme.theme}, 0.2) - ), - rgb(${(props) => props.theme.background}); - padding: 0 0.25rem !important; + width: 100%; + height: 100%; `; diff --git a/src/components/dashboard/list/AppListItem.tsx b/src/components/dashboard/list/AppListItem.tsx index 962dae3d0..c7617b2a3 100644 --- a/src/components/dashboard/list/AppListItem.tsx +++ b/src/components/dashboard/list/AppListItem.tsx @@ -1,6 +1,6 @@ +import { ListItem, ListItemIcon, ListItemImg } from "@arconnect/components"; import { GridIcon } from "@iconicicons/react"; import type { HTMLProps } from "react"; -import BaseElement, { SettingImage, SettingIcon } from "./BaseElement"; export default function AppListItem({ name, @@ -10,9 +10,9 @@ export default function AppListItem({ ...props }: Props & HTMLProps) { return ( - - {(icon && ) || } - + + {(icon && ) || } + ); } diff --git a/src/components/dashboard/list/ContactListItem.tsx b/src/components/dashboard/list/ContactListItem.tsx index d688e34b1..c11112342 100644 --- a/src/components/dashboard/list/ContactListItem.tsx +++ b/src/components/dashboard/list/ContactListItem.tsx @@ -1,7 +1,7 @@ +import { ListItem, ListItemIcon } from "@arconnect/components"; +import { User01 } from "@untitled-ui/icons-react"; import type { HTMLProps } from "react"; -import BaseElement, { SettingIcon } from "./BaseElement"; import styled from "styled-components"; -import { User01 } from "@untitled-ui/icons-react"; export default function ContactListItem({ name, @@ -14,7 +14,7 @@ export default function ContactListItem({ {/* @ts-ignore */} - {!profileIcon && } + {!profileIcon && } ); @@ -56,7 +56,7 @@ const ContactWrapper = styled.div<{ active: boolean }>` } `; -const Contact = styled(BaseElement)` +const Contact = styled(ListItem)` &:hover { background-color: transparent; } diff --git a/src/components/dashboard/list/SettingListItem.tsx b/src/components/dashboard/list/SettingListItem.tsx index 29b352ad5..493619841 100644 --- a/src/components/dashboard/list/SettingListItem.tsx +++ b/src/components/dashboard/list/SettingListItem.tsx @@ -1,7 +1,7 @@ +import { ListItem, ListItemIcon } from "@arconnect/components"; import type { Icon } from "~settings/setting"; -import type { HTMLProps } from "react"; -import BaseElement, { SettingIcon } from "./BaseElement"; import browser from "webextension-polyfill"; +import type { HTMLProps } from "react"; export default function SettingListItem({ displayName, @@ -11,14 +11,14 @@ export default function SettingListItem({ ...props }: Props & HTMLProps) { return ( - - - + + ); } diff --git a/src/components/dashboard/list/TokenListItem.tsx b/src/components/dashboard/list/TokenListItem.tsx index b900cadfc..de04fce60 100644 --- a/src/components/dashboard/list/TokenListItem.tsx +++ b/src/components/dashboard/list/TokenListItem.tsx @@ -2,12 +2,12 @@ import { DREContract, DRENode, NODES } from "@arconnect/warp-dre"; import { loadTokenLogo, type Token } from "~tokens/token"; import { Reorder, useDragControls } from "framer-motion"; import { useEffect, useMemo, useState } from "react"; +import { ListItem } from "@arconnect/components"; import { formatAddress } from "~utils/format"; import { getDreForToken } from "~tokens"; import { useTheme } from "~utils/theme"; import { useLocation } from "wouter"; import * as viewblock from "~lib/viewblock"; -import BaseElement from "./BaseElement"; import styled from "styled-components"; import { useGateway } from "~gateways/wayfinder"; import { concatGatewayURL } from "~gateways/utils"; @@ -81,7 +81,7 @@ export default function TokenListItem({ token, active, ao, onClick }: Props) { dragControls={dragControls} onClick={handleClick} > - @@ -94,7 +94,7 @@ export default function TokenListItem({ token, active, ao, onClick }: Props) { dragControls={!ao ? dragControls : null} > - + ); } diff --git a/src/components/dashboard/list/WalletListItem.tsx b/src/components/dashboard/list/WalletListItem.tsx index d461b4a44..96f4920b9 100644 --- a/src/components/dashboard/list/WalletListItem.tsx +++ b/src/components/dashboard/list/WalletListItem.tsx @@ -6,8 +6,8 @@ import { formatAddress } from "~utils/format"; import type { StoredWallet } from "~wallets"; import HardwareWalletIcon from "~components/hardware/HardwareWalletIcon"; import keystoneLogo from "url:/assets/hardware/keystone.png"; -import BaseElement, { SettingIcon } from "./BaseElement"; import { svgie } from "~utils/svgies"; +import { ListItem, ListItemIcon } from "@arconnect/components"; export default function WalletListItem({ wallet, @@ -36,7 +36,7 @@ export default function WalletListItem({ dragListener={false} dragControls={dragControls} > - - {!avatar && !svgieAvatar && } + {!avatar && !svgieAvatar && } {wallet.type === "hardware" && wallet.api === "keystone" && ( )} - + ); } diff --git a/src/components/dashboard/subsettings/AddContact.tsx b/src/components/dashboard/subsettings/AddContact.tsx index 2f4b0ab32..0348edae6 100644 --- a/src/components/dashboard/subsettings/AddContact.tsx +++ b/src/components/dashboard/subsettings/AddContact.tsx @@ -16,8 +16,8 @@ import { Title } from "./ContactSettings"; import { - Button, - Modal, + ButtonV2, + ModalV2, Spacer, useModal, useToasts @@ -33,6 +33,7 @@ import styled from "styled-components"; import { useLocation } from "wouter"; import copy from "copy-to-clipboard"; import { gql } from "~gateways/api"; +import { useTheme } from "~utils/theme"; export default function AddContact() { // contacts @@ -50,6 +51,7 @@ export default function AddContact() { instance: ExtensionStorage }); + const theme = useTheme(); const { setToast } = useToasts(); const [location] = useLocation(); const address = location.split("=")[1]; @@ -342,26 +344,39 @@ export default function AddContact() { <>
- + removeContactModal.setOpen(true)} + displayTheme={theme} > {browser.i18n.getMessage("remove_contact")}
- + removeContactModal.setOpen(false)} + > + {browser.i18n.getMessage("no")} + + + {browser.i18n.getMessage("yes")} + + + } > {browser.i18n.getMessage("remove_contact")} @@ -370,19 +385,8 @@ export default function AddContact() { {browser.i18n.getMessage("remove_contact_question")} - - - - - + + ); diff --git a/src/components/dashboard/subsettings/AddToken.tsx b/src/components/dashboard/subsettings/AddToken.tsx index 859b51d5c..8f386dac9 100644 --- a/src/components/dashboard/subsettings/AddToken.tsx +++ b/src/components/dashboard/subsettings/AddToken.tsx @@ -1,5 +1,12 @@ -import { Input, Label, useInput, useToasts } from "@arconnect/components"; -import { Button, Select, Spacer, Text } from "@arconnect/components"; +import { + ButtonV2, + InputV2, + SelectV2 as Select, + Spacer, + Text, + useInput, + useToasts +} from "@arconnect/components"; import browser from "webextension-polyfill"; import { useEffect, useState } from "react"; import { useAo, type TokenInfo, useAoTokens } from "~tokens/aoTokens/ao"; @@ -148,7 +155,7 @@ export default function AddToken() { )} - )} - + ); } diff --git a/src/components/dashboard/subsettings/AddWallet.tsx b/src/components/dashboard/subsettings/AddWallet.tsx index 33454320b..9c9cf5577 100644 --- a/src/components/dashboard/subsettings/AddWallet.tsx +++ b/src/components/dashboard/subsettings/AddWallet.tsx @@ -6,12 +6,12 @@ import { useEffect, useState } from "react"; import { useLocation } from "wouter"; import { addWallet } from "~wallets"; import { - Button, - Input, Text, useInput, Spacer, - useToasts + useToasts, + ButtonV2, + InputV2 } from "@arconnect/components"; import BackupWalletPage from "~components/welcome/generate/BackupWalletPage"; import KeystoneButton from "~components/hardware/KeystoneButton"; @@ -227,7 +227,7 @@ export default function AddWallet() { )} - - + {browser.i18n.getMessage("or").toUpperCase()} - + ); diff --git a/src/components/dashboard/subsettings/AppSettings.tsx b/src/components/dashboard/subsettings/AppSettings.tsx index a3f5ba8fa..b9aa01e65 100644 --- a/src/components/dashboard/subsettings/AppSettings.tsx +++ b/src/components/dashboard/subsettings/AppSettings.tsx @@ -9,13 +9,13 @@ import PermissionCheckbox, { } from "~components/auth/PermissionCheckbox"; import { removeApp } from "~applications"; import { - Button, - Input, - Modal, - Select, + ButtonV2, + InputV2, + ModalV2, + SelectV2, Spacer, Text, - Tooltip, + TooltipV2, useInput, useModal, useToasts @@ -168,7 +168,10 @@ export default function AppSettings({ app, showTitle = false }: Props) { {": "} {arweave.ar.winstonToAr(spent)} {" AR "} - + updateSettings((val) => ({ @@ -183,7 +186,7 @@ export default function AppSettings({ app, showTitle = false }: Props) { > {browser.i18n.getMessage("reset")} - + @@ -206,16 +209,19 @@ export default function AppSettings({ app, showTitle = false }: Props) { )) || arweave.ar.winstonToAr(limit)} {" AR "} - + setEditingLimit((val) => !val)} /> - + {browser.i18n.getMessage("gateway")} - + {editingCustom && ( <> - - + Save )} {browser.i18n.getMessage("bundlrNode")} - updateSettings((val) => ({ @@ -290,14 +296,13 @@ export default function AppSettings({ app, showTitle = false }: Props) { placeholder="https://node2.bundlr.network" /> - + - - + + removeModal.setOpen(false)}> + {browser.i18n.getMessage("cancel")} + + removeApp(app.url)}> + {browser.i18n.getMessage("remove")} + + + } > {browser.i18n.getMessage("removeApp")} {browser.i18n.getMessage("removeAppNote")} - - - - + ); } diff --git a/src/components/dashboard/subsettings/ContactSettings.tsx b/src/components/dashboard/subsettings/ContactSettings.tsx index 33409c20a..b08f9ac07 100644 --- a/src/components/dashboard/subsettings/ContactSettings.tsx +++ b/src/components/dashboard/subsettings/ContactSettings.tsx @@ -1,28 +1,30 @@ import { Text, - Button, - Input, + ButtonV2, + InputV2, Loading, - Modal, - Select, + ModalV2, + SelectV2, Spacer, - Tooltip, + TooltipV2, useModal, - useToasts + useToasts, + type DisplayTheme } from "@arconnect/components"; -import { CheckIcon, CopyIcon } from "@iconicicons/react"; import { useState, useEffect, type MouseEventHandler, useMemo } from "react"; +import { Edit02, Share04, Upload01 } from "@untitled-ui/icons-react"; +import { uploadUserAvatar, getUserAvatar } from "~lib/avatar"; +import { CheckIcon, CopyIcon } from "@iconicicons/react"; +import { EventType, trackEvent } from "~utils/analytics"; import { useStorage } from "@plasmohq/storage/hook"; import { ExtensionStorage } from "~utils/storage"; -import styled from "styled-components"; import browser from "webextension-polyfill"; -import { Edit02, Share04, Upload01 } from "@untitled-ui/icons-react"; -import { useLocation } from "wouter"; -import { uploadUserAvatar, getUserAvatar } from "~lib/avatar"; import { getAllArNSNames } from "~lib/arns"; -import copy from "copy-to-clipboard"; -import { EventType, trackEvent } from "~utils/analytics"; +import { useTheme } from "~utils/theme"; +import styled from "styled-components"; import { svgie } from "~utils/svgies"; +import { useLocation } from "wouter"; +import copy from "copy-to-clipboard"; export default function ContactSettings({ address }: Props) { // contacts @@ -35,6 +37,7 @@ export default function ContactSettings({ address }: Props) { ); const { setToast } = useToasts(); + const theme = useTheme(); const [editable, setEditable] = useState(false); const [contact, setContact] = useState({ @@ -328,9 +331,8 @@ export default function ContactSettings({ address }: Props) { {contact.name && {browser.i18n.getMessage("name")}} {editable ? ( - {!editable && ( - @@ -358,14 +360,13 @@ export default function ContactSettings({ address }: Props) { as={copied ? CheckIcon : CopyIcon} onClick={copyAddress} /> - + )} {editable ? ( -
- + removeContactModal.setOpen(true)} + displayTheme={theme} > {browser.i18n.getMessage("remove_contact")}
- + removeContactModal.setOpen(false)} + > + {browser.i18n.getMessage("no")} + + + {browser.i18n.getMessage("yes")} + + + } > {browser.i18n.getMessage("remove_contact")} @@ -419,19 +432,8 @@ export default function ContactSettings({ address }: Props) { {browser.i18n.getMessage("remove_contact_question")} - - - - - + + )} @@ -482,7 +484,7 @@ export const Footer = styled.div` display: flex; flex-direction: column; gap: 10px; - padding-top: 10px; + padding: 10px 0px; `; export const CenterText = styled(Text)` @@ -525,15 +527,16 @@ const EditIcon = styled(Edit02)` cursor: pointer; `; -export const RemoveContact = styled(Button)` - background-color: #ea433580; - color: #ea4335; - border: 2px solid #ea433580; - transition: all 0.29s ease-in-out; - height: 46.79px; +export const RemoveContact = styled(ButtonV2)<{ displayTheme: DisplayTheme }>` + // props.theme.delete + background-color: ${(props) => + props.displayTheme === "light" ? "#F58080" : "#8C1A1A"}; + border: 1.5px solid ${(props) => props.theme.fail}; + color: #ffffff; &:hover { - transform: scale(1.02); + background-color: ${(props) => + props.displayTheme === "light" ? "#F58080" : "#C51A1A"}; } `; @@ -561,7 +564,7 @@ export const InputWrapper = styled.div` margin-bottom: 10px; `; -export const SelectInput = styled(Select)` +export const SelectInput = styled(SelectV2)` height: 53px; padding: 10px 20px 10px 20px; color: #b9b9b9; @@ -572,7 +575,7 @@ export const SelectInput = styled(Select)` } `; -export const ContactInput = styled(Input)` +export const ContactInput = styled(InputV2)` height: 33px; padding: 10px 20px 10px 20px; color: #b9b9b9; diff --git a/src/components/dashboard/subsettings/TokenSettings.tsx b/src/components/dashboard/subsettings/TokenSettings.tsx index 61942adb1..e694ab3c2 100644 --- a/src/components/dashboard/subsettings/TokenSettings.tsx +++ b/src/components/dashboard/subsettings/TokenSettings.tsx @@ -1,9 +1,9 @@ import { - Button, - Select, + ButtonV2, + SelectV2, Spacer, Text, - Tooltip, + TooltipV2, useToasts } from "@arconnect/components"; import type { Token, TokenType } from "~tokens/token"; @@ -83,7 +83,7 @@ export default function TokenSettings({ id }: Props) { Symbol: {token.ticker} Address: {token.id} - + { copy(token.id); @@ -96,16 +96,15 @@ export default function TokenSettings({ id }: Props) { }); }} /> - + ) : (
- {/* Existing UI for regular tokens */} {token.name} - + {token.gateway && }
)} - + ); } diff --git a/src/components/dashboard/subsettings/WalletSettings.tsx b/src/components/dashboard/subsettings/WalletSettings.tsx index 492d8c082..604ca2062 100644 --- a/src/components/dashboard/subsettings/WalletSettings.tsx +++ b/src/components/dashboard/subsettings/WalletSettings.tsx @@ -1,20 +1,15 @@ import { - Button, - Input, - Modal, + ButtonV2, + InputV2, + ModalV2, Spacer, Text, - Tooltip, + TooltipV2, useInput, useModal, useToasts } from "@arconnect/components"; -import { - CheckIcon, - CopyIcon, - DownloadIcon, - TrashIcon -} from "@iconicicons/react"; +import { CopyIcon, DownloadIcon, TrashIcon } from "@iconicicons/react"; import { InputWithBtn, InputWrapper } from "~components/arlocal/InputWrapper"; import { removeWallet, type StoredWallet } from "~wallets"; import { useEffect, useMemo, useState } from "react"; @@ -171,7 +166,7 @@ export default function WalletSettings({ address }: Props) { {ansLabel || wallet.nickname} {wallet.type === "hardware" && ( - - + )} {wallet.address} - + { copy(wallet.address); @@ -199,7 +197,7 @@ export default function WalletSettings({ address }: Props) { }); }} /> - + {browser.i18n.getMessage("edit_wallet_name")} {!!ansLabel && ( @@ -207,7 +205,7 @@ export default function WalletSettings({ address }: Props) { )} - - - + + Save
- + - +
- + removeModal.setOpen(false)} + > + {browser.i18n.getMessage("cancel")} + + { + try { + await removeWallet(address); + setToast({ + type: "success", + content: browser.i18n.getMessage( + "removed_wallet_notification" + ), + duration: 2000 + }); + } catch (e) { + console.log("Error removing wallet", e); + setToast({ + type: "error", + content: browser.i18n.getMessage( + "remove_wallet_error_notification" + ), + duration: 2000 + }); + } + }} + > + {browser.i18n.getMessage("confirm")} + + + } > - + {browser.i18n.getMessage("remove_wallet_modal_title")} - + + {browser.i18n.getMessage("remove_wallet_modal_content")} - - - - - + + {browser.i18n.getMessage("export")} + + } > {browser.i18n.getMessage("export_wallet_modal_title")} - - - - + + ); } @@ -366,6 +370,12 @@ const Warning = styled(Text)` color: rgb(255, 0, 0, 0.6); `; +const ButtonWrapper = styled.div` + display: flex; + flex-direction: row; + gap: 10px; +`; + interface Props { address: string; } diff --git a/src/components/hardware/KeystoneButton.tsx b/src/components/hardware/KeystoneButton.tsx index d95d6f746..00786c8fe 100644 --- a/src/components/hardware/KeystoneButton.tsx +++ b/src/components/hardware/KeystoneButton.tsx @@ -10,7 +10,7 @@ import { } from "~components/auth/CustomGatewayWarning"; import { useState } from "react"; import { - Button, + ButtonV2, Modal, Spacer, Text, @@ -84,10 +84,15 @@ export default function KeystoneButton({ onSuccess }: Props) { return ( <> - + { - window.open(window.location.href.split("#")[0] + "?expanded=true"); - }; - // is the popup open in a tab const [isExpanded, setExpanded] = useState(false); @@ -103,6 +107,9 @@ export default function WalletHeader() { // wallet nickname for copy const [displayName, setDisplayName] = useState(""); + // wallet address for copy + const [address, setAddress] = useState(""); + // wallet name const walletName = useMemo(() => { if (!ansProfile?.label) { @@ -110,6 +117,7 @@ export default function WalletHeader() { let name = wallet?.nickname || "Wallet"; const address = wallet?.address && formatAddress(wallet?.address, 4); + setAddress(address); if (/^Account \d+$/.test(name)) { name = address; } @@ -220,69 +228,73 @@ export default function WalletHeader() { - {displayName} + + + {displayName} + +
{address}
+
- - - - - - - - browser.tabs.create({ - url: `https://viewblock.io/arweave/address/${activeAddress}` - }) - } - /> - - - browser.tabs.create({ - url: browser.runtime.getURL("tabs/dashboard.html") - }) - } + as={copied ? CheckIcon : CopyIcon} + onClick={copyAddress} + style={{ width: "23.5px", height: "23.5px" }} /> - - {!isExpanded && ( - - - - )} - + + + + { setNewNotifications(false); push("/notifications"); }} - style={{ width: "17px", height: "17px" }} + style={{ + width: "20px", + height: "20px", + paddingLeft: "4px", + marginRight: "2px" + }} /> {newNotifications && } - + { e.stopPropagation(); setAppDataOpen(true); }} > - + + + + { + e.stopPropagation(); + setMenuOpen(!menuOpen); + }} + > + + + + {appDataOpen && ( {(!!activeAppData && ( - } - + )) || ( @@ -334,8 +346,7 @@ export default function WalletHeader() { )) || ( <> - - + +
+ {browser.i18n.getMessage("disconnect")} +
+
)} @@ -380,6 +400,45 @@ export default function WalletHeader() { /> )} setOpen(false)} /> + setMenuOpen(false)} + menuItems={[ + { + icon: , + title: "Contacts", + route: () => + browser.tabs.create({ + url: browser.runtime.getURL("tabs/dashboard.html#/contacts") + }) + }, + { + icon: , + title: "Viewblock", + route: () => + browser.tabs.create({ + url: `https://viewblock.io/arweave/address/${activeAddress}` + }) + }, + { + icon: , + title: "Settings", + route: () => + browser.tabs.create({ + url: browser.runtime.getURL("tabs/dashboard.html") + }) + }, + { + icon: , + title: "Expand view", + route: () => { + window.open( + window.location.href.split("#")[0] + "?expanded=true" + ); + } + } + ]} + /> ); } @@ -392,7 +451,7 @@ const Wrapper = styled(Section)<{ display: flex; align-items: center; justify-content: space-between; - padding: 1.475rem 20px 0.775rem calc(20px - 0.9rem); + padding: 15px; z-index: 100; top: 0; left: 0; @@ -409,20 +468,42 @@ const Wrapper = styled(Section)<{ transition: all 0.23s ease-in-out; `; -const avatarSize = "1.425rem"; +const WalletName = styled.div` + display: flex; + flex-direction: column; +`; const AddressContainer = styled.div` display: flex; align-items: center; `; +const MenuDots = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: 24px; + height: 24px; + margin-left: 0px; + border-radius: 0.55rem; + transition: transform 0.06s ease-in-out, background-color 0.17s ease-in-out; + + &:hover { + background-color: rgba(${(props) => props.theme.theme}, 0.1); + } + + &:active { + background-color: rgba(${(props) => props.theme.theme}, 0.15); + transform: scale(0.96); + } +`; + const Wallet = styled.div` cursor: pointer; display: flex; align-items: center; gap: 0.64rem; - padding: 0.65rem 0.9rem; - padding-right: 0.75rem; + padding: 3px 5px; border-radius: 0.55rem; transition: transform 0.06s ease-in-out, background-color 0.17s ease-in-out; @@ -445,6 +526,14 @@ const Wallet = styled.div` } `; +const Address = styled.div` + color: ${(props) => props.theme.secondaryTextv2}; + font-size: 10px; + line-height: 10px; +`; + +const avatarSize = "1.425rem"; + export const Avatar = styled(Squircle)` position: relative; width: ${avatarSize}; @@ -491,8 +580,8 @@ const ExpandArrow = styled(ChevronDownIcon)<{ open: boolean }>` const Notifier = styled.div` position: absolute; - right: -1.5px; - top: 0; + right: 1.3px; + top: 0.7px; width: 8px; height: 8px; border-radius: 100%; @@ -500,24 +589,23 @@ const Notifier = styled.div` border: 1px solid rgb(${(props) => props.theme.background}); `; -const AppAction = styled.div` - position: relative; - display: flex; -`; - const AppOnline = styled.div<{ online: boolean }>` position: absolute; - right: 0; - bottom: 0; + right: 3px; + bottom: 2px; width: 8px; height: 8px; border-radius: 100%; - background-color: rgb( - ${(props) => (props.online ? "0, 230, 0" : "154, 154, 167")} - ); + background-color: ${(props) => + props.online ? props.theme.success : "rgb(154, 154, 167)"}; border: 1px solid rgb(${(props) => props.theme.background}); `; +const AppAction = styled.div` + position: relative; + display: flex; +`; + const Action = styled(CopyIcon)` cursor: pointer; font-size: 1.25rem; @@ -539,7 +627,6 @@ const WalletActions = styled.div` position: relative; display: flex; align-items: center; - gap: 0.34rem; `; const AppInfoWrapper = styled(motion.div).attrs({ diff --git a/src/components/popup/WalletMenu.tsx b/src/components/popup/WalletMenu.tsx new file mode 100644 index 000000000..8afa43d84 --- /dev/null +++ b/src/components/popup/WalletMenu.tsx @@ -0,0 +1,142 @@ +import { motion, AnimatePresence, type Variants } from "framer-motion"; +import styled from "styled-components"; + +export default function WalletMenu({ open, close, menuItems }: Props) { + return ( + + {open && ( + + { + e.stopPropagation(); + e.preventDefault(); + }} + > + {menuItems.map((item, i) => ( + { + item.route(); + close(); + }} + > + {item.icon} + {item.title} + + ))} + + + )} + + ); +} + +export const popoverAnimation: Variants = { + closed: { + scale: 0.4, + opacity: 0, + transition: { + type: "spring", + duration: 0.4 + } + }, + open: { + scale: 1, + opacity: 1, + transition: { + type: "spring", + duration: 0.4, + delayChildren: 0.2, + staggerChildren: 0.05 + } + } +}; + +const MenuPopover = styled(motion.div).attrs({ + initial: "closed", + animate: "open", + exit: "closed" +})` + position: absolute; + top: calc(100% - 20px); + right: 12px; + z-index: 110; + cursor: default; +`; + +const walletAnimation = { + open: { + opacity: 1, + y: 0, + transition: { + type: "spring", + stiffness: 300, + damping: 24 + } + }, + closed: { + opacity: 0, + y: 20, + transition: { + duration: 0.2 + } + } +}; + +const MenuItem = styled(motion.div).attrs<{ open: boolean }>((props) => ({ + variants: walletAnimation, + animate: props.open ? "open" : "closed" +}))<{ open: boolean }>` + display: flex; + align-items: flex-start; + justify-content: flex-start; + padding: 8px 12px; + gap: 10px; + align-self: stretch; + color: ${(props) => props.theme.primaryTextv2}; + transition: background-color 0.23s ease-in-out; + cursor: pointer; + + &:hover { + background-color: rgb( + ${(props) => props.theme.theme}, + ${(props) => (props.theme.displayTheme === "light" ? "0.1" : "0.05")} + ); + } + + &:active { + transform: scale(0.975) !important; + } +`; + +const MenuCard = styled.div` + width: 139px; + min-width: 139px; + display: flex; + padding: 4px 0px; + flex-direction: column; + align-items: flex-start; + background-color: ${(props) => props.theme.backgroundv2}; + border-radius: 10px; + border: 1.5px solid ${(props) => props.theme.primary}; + box-shadow: 0px 4px 20px 0px rgba(0, 0, 0, 0.4); +`; + +const MenuTitle = styled.div` + display: flex; + height: 100%; + margin: auto 0; +`; + +interface Props { + open: boolean; + close: () => any; + menuItems: MenuItem[]; +} + +export interface MenuItem { + icon: JSX.Element; + title: string; + route: () => any; +} diff --git a/src/components/popup/WalletSwitcher.tsx b/src/components/popup/WalletSwitcher.tsx index 44e30b44e..7f41150fd 100644 --- a/src/components/popup/WalletSwitcher.tsx +++ b/src/components/popup/WalletSwitcher.tsx @@ -1,10 +1,10 @@ import { EditIcon, PlusIcon, WalletIcon } from "@iconicicons/react"; import { - Button, + ButtonV2, Card, Section, Text, - Tooltip, + TooltipV2, useToasts } from "@arconnect/components"; import { concatGatewayURL } from "~gateways/utils"; @@ -217,10 +217,13 @@ export default function WalletSwitcher({ }) } > - + {browser.i18n.getMessage("add_wallet")} - + browser.tabs.create({ @@ -230,7 +233,7 @@ export default function WalletSwitcher({ }) } /> - + )} @@ -269,7 +272,7 @@ const SwitcherPopover = styled(motion.div).attrs({ })<{ exactTop?: boolean }>` position: absolute; top: ${(props) => (props.exactTop ? "100%" : "calc(100% - 1.05rem)")}; - left: 0; + left: -5px; right: 0; z-index: 110; cursor: default; @@ -406,12 +409,9 @@ const ActionBar = styled.div` background-color: rgb(${(props) => props.theme.cardBackground}); `; -const AddWalletButton = styled(Button).attrs({ - fullWidth: true, - small: true -})` - padding: 0.72rem 0; -`; +const AddWalletButton = styled(ButtonV2).attrs({ + fullWidth: true +})``; const EditButton = styled(EditIcon)` font-size: 1.5rem; diff --git a/src/components/popup/home/Balance.tsx b/src/components/popup/home/Balance.tsx index ace0bb793..596768e0f 100644 --- a/src/components/popup/home/Balance.tsx +++ b/src/components/popup/home/Balance.tsx @@ -2,7 +2,7 @@ import { formatTokenBalance, formatFiatBalance } from "~tokens/currency"; import Application, { type AppInfo } from "~applications/application"; import { gql } from "~gateways/api"; import Graph, { GraphText } from "~components/popup/Graph"; -import { Loading, Tooltip } from "@arconnect/components"; +import { Loading, TooltipV2 } from "@arconnect/components"; import { useEffect, useMemo, useState, type HTMLProps } from "react"; import { useStorage } from "@plasmohq/storage/hook"; import { ExtensionStorage } from "~utils/storage"; @@ -148,19 +148,23 @@ export default function Balance() { " " + currency.toUpperCase()} - setHideBalance((val) => !val)} as={hideBalance ? EyeOffIcon : EyeIcon} /> - - + + - + diff --git a/src/components/popup/home/NoBalance.tsx b/src/components/popup/home/NoBalance.tsx index b635719ca..ba7d325f0 100644 --- a/src/components/popup/home/NoBalance.tsx +++ b/src/components/popup/home/NoBalance.tsx @@ -1,10 +1,10 @@ -import { Button, ButtonV2, Section, Text } from "@arconnect/components"; +import { ButtonV2, Section, Text } from "@arconnect/components"; import { ArrowRightIcon } from "@iconicicons/react"; import { useHistory } from "~utils/hash_router"; import noBalanceArt from "url:/assets/ar/no_funds.png"; import browser from "webextension-polyfill"; import styled from "styled-components"; -import BuyButton from "./BuyButton"; +// import BuyButton from "./BuyButton"; export default function NoBalance() { const [push] = useHistory(); diff --git a/src/routes/auth/connect.tsx b/src/routes/auth/connect.tsx index bdd94313d..2edef12ba 100644 --- a/src/routes/auth/connect.tsx +++ b/src/routes/auth/connect.tsx @@ -1,19 +1,16 @@ import { - Button, + ButtonV2, Card, Checkbox, - Input, + InputV2, + LabelV2, Section, Spacer, Text, useInput, useToasts } from "@arconnect/components"; -import { - getMissingPermissions, - permissionData, - type PermissionType -} from "~applications/permissions"; +import { permissionData, type PermissionType } from "~applications/permissions"; import { replyToAuthRequest, useAuthParams, useAuthUtils } from "~utils/auth"; import { CloseLayer } from "~components/popup/WalletHeader"; import type { AppInfo } from "~applications/application"; @@ -194,7 +191,7 @@ export default function Connect() { {page === "unlock" && (
- + {browser.i18n.getMessage("wallet")} -
- + - +
); @@ -299,10 +296,10 @@ const WalletSelectWrapper = styled.div` `; const SelectIcon = styled(ChevronDownIcon)` - font-size: 1.25rem; - width: 1em; - height: 1em; - color: rgb(${(props) => props.theme.theme}); + font-size: 1rem; + width: 1.375rem; + height: 1.375 rem; + color: ${(props) => props.theme.primaryTextv2}; transition: all 0.23s ease-in-out; `; @@ -313,25 +310,34 @@ const WalletSelect = styled(Card)<{ open: boolean }>` justify-content: space-between; cursor: pointer; background-color: transparent; - padding: 0.75rem 1.25rem; - border-radius: 18px; + padding: 0.844rem 0.9375rem; + border: 1.5px solid ${(props) => props.theme.inputField}; + border-radius: 10px; transition: all 0.23s ease-in-out; - ${(props) => - props.open - ? `border-color: rgba(${props.theme.theme}, .5); box-shadow: 0 0 0 1px rgba(${props.theme.theme}, .5);` - : ""} - ${SelectIcon} { transform: ${(props) => (props.open ? "rotate(180deg)" : "rotate(0)")}; } + + &:focus-within, + &: hover { + ${(props) => "border: 1.5px solid " + props.theme.primaryTextv2}; + } + + &:active { + border-color: ${(props) => props.theme.inputField}; + color: rgb(${(props) => props.theme.theme}); + } `; const Address = styled(Text).attrs({ - noMargin: true + noMargin: true, + title: false })` - font-size: 1.2rem; - color: rgb(${(props) => props.theme.theme}); + font-size: 16px; + line-height: 22px; + font-weight: 500; + color: ${(props) => props.theme.primaryTextv2}; `; const ContentWrapper = styled.div` diff --git a/src/routes/popup/index.tsx b/src/routes/popup/index.tsx index bb25d27b0..457b2486d 100644 --- a/src/routes/popup/index.tsx +++ b/src/routes/popup/index.tsx @@ -2,18 +2,15 @@ import { useStorage } from "@plasmohq/storage/hook"; import { ExtensionStorage } from "~utils/storage"; import { useEffect, useMemo, useState } from "react"; import Collectibles from "~components/popup/home/Collectibles"; -import AnalyticsConsent from "~components/popup/home/AnalyticsConsent"; import WalletHeader from "~components/popup/WalletHeader"; import NoBalance from "~components/popup/home/NoBalance"; import Balance from "~components/popup/home/Balance"; -import BuyButton from "~components/popup/home/BuyButton"; +// import BuyButton from "~components/popup/home/BuyButton"; import Tokens from "~components/popup/home/Tokens"; import { AnnouncementPopup } from "./announcement"; -import Arweave from "arweave"; import { getDecryptionKey, isExpired } from "~wallets/auth"; import { useHistory } from "~utils/hash_router"; import { trackEvent, EventType, trackPage, PageType } from "~utils/analytics"; -import { findGateway } from "~gateways/wayfinder"; import styled from "styled-components"; import { useTokens } from "~tokens"; import { useAoTokens } from "~tokens/aoTokens/ao"; diff --git a/src/routes/popup/receive.tsx b/src/routes/popup/receive.tsx index ddb5a7115..ee405f047 100644 --- a/src/routes/popup/receive.tsx +++ b/src/routes/popup/receive.tsx @@ -1,16 +1,22 @@ -import { Button, Section, Tooltip } from "@arconnect/components"; -import { CopyIcon, ShareIcon } from "@iconicicons/react"; +import { + ButtonV2, + Section, + TooltipV2, + useToasts, + type DisplayTheme +} from "@arconnect/components"; import { useStorage } from "@plasmohq/storage/hook"; import { ExtensionStorage } from "~utils/storage"; +import { CheckIcon, CopyIcon } from "@iconicicons/react"; import { formatAddress } from "~utils/format"; import { QRCodeSVG } from "qrcode.react"; import browser from "webextension-polyfill"; -import Head from "~components/popup/Head"; import styled from "styled-components"; import copy from "copy-to-clipboard"; -import { useEffect } from "react"; +import { useEffect, type MouseEventHandler, useState } from "react"; import { PageType, trackPage } from "~utils/analytics"; import HeadV2 from "~components/popup/HeadV2"; +import { useTheme } from "~utils/theme"; export default function Receive() { // active address @@ -18,42 +24,58 @@ export default function Receive() { key: "active_address", instance: ExtensionStorage }); + const [copied, setCopied] = useState(false); //segment useEffect(() => { trackPage(PageType.RECEIVE); }, []); + const theme = useTheme(); + const { setToast } = useToasts(); + + const copyAddress: MouseEventHandler = (e) => { + e.stopPropagation(); + copy(activeAddress); + setCopied(true); + setTimeout(() => setCopied(false), 1000); + setToast({ + type: "success", + duration: 2000, + content: `${formatAddress(activeAddress, 3)} ${browser.i18n.getMessage( + "copied_address_2" + )}` + }); + }; + return (
- - {formatAddress(activeAddress ?? "", 6)} - - copy(activeAddress)} /> - -
-
- - - -
-
- -
+ +
+ + + +
+
+ + {formatAddress(activeAddress ?? "", 6)} + + + + +
+
); } @@ -61,26 +83,26 @@ export default function Receive() { const Wrapper = styled.div` display: flex; flex-direction: column; - justify-content: space-between; + justify-content: space-around; height: calc(100vh - 72px); `; -const AddressField = styled.div` +const ContentWrapper = styled.div` + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; +`; + +const AddressField = styled(ButtonV2)` display: flex; align-items: center; - gap: 0.45rem; - font-size: 0.9rem; + gap: 5px; font-weight: 500; - padding: 0.45rem 0.8rem; - border-radius: 18px; - margin: 0 auto; - background-color: rgb(${(props) => props.theme.theme}); - color: #fff; - width: max-content; `; -const CopyButton = styled(CopyIcon)` - font-size: 0.9rem; +const CopyAction = styled(CopyIcon)` + font-size: 1.25rem; width: 1em; height: 1em; color: #fff; @@ -88,18 +110,21 @@ const CopyButton = styled(CopyIcon)` transition: all 0.23s ease-in-out; &:hover { - opacity: 0.86; + opacity: 0.85; } &:active { - transform: scale(0.9); + transform: scale(0.92); } `; -const QRCodeWrapper = styled.div` - width: max-content; - margin: 0 auto; - background-color: rgb(${(props) => props.theme.theme}); - border-radius: 24px; - padding: 1.35rem; +const QRCodeWrapper = styled.div<{ displayTheme: DisplayTheme }>` + display: flex; + justify-content: center; + align-items: center; + width: max-content%; + background-color: ${(props) => + props.theme.displayTheme === "light" ? "#7866D3" : "#8E7BEA"}; + border-radius: 21.44px; + padding: 25.83px 0px; `; diff --git a/src/routes/popup/send/confirm.tsx b/src/routes/popup/send/confirm.tsx index eb0cd93f5..941992a69 100644 --- a/src/routes/popup/send/confirm.tsx +++ b/src/routes/popup/send/confirm.tsx @@ -1,5 +1,5 @@ import { - Input, + InputV2, Spacer, Text, useInput, @@ -16,7 +16,6 @@ import { useStorage } from "@plasmohq/storage/hook"; import { ExtensionStorage, TempTransactionStorage, - TRANSFER_TX_STORAGE, type RawStoredTransfer } from "~utils/storage"; import { useEffect, useMemo, useState } from "react"; @@ -24,11 +23,7 @@ import { useTokens } from "~tokens"; import { findGateway } from "~gateways/wayfinder"; import Arweave from "arweave"; import { useHistory } from "~utils/hash_router"; -import { - defaultGateway, - fallbackGateway, - type Gateway -} from "~gateways/gateway"; +import { fallbackGateway, type Gateway } from "~gateways/gateway"; import AnimatedQRScanner from "~components/hardware/AnimatedQRScanner"; import AnimatedQRPlayer from "~components/hardware/AnimatedQRPlayer"; import { getActiveKeyfile, getActiveWallet, type StoredWallet } from "~wallets"; @@ -41,7 +36,6 @@ import type { JWKInterface } from "arbundles"; import { AutoContactPic, generateProfileIcon, - type Contact, ProfilePicture } from "~components/Recipient"; import { fractionedToBalance } from "~tokens/currency"; @@ -95,7 +89,6 @@ export default function Confirm({ tokenID, qty }: Props) { const ao = useAo(); - const tokens = useTokens(); const [activeAddress] = useStorage({ key: "active_address", instance: ExtensionStorage @@ -691,14 +684,13 @@ export default function Confirm({ tokenID, qty }: Props) { {browser.i18n.getMessage("sign_enter_password")} - )} diff --git a/src/routes/popup/send/index.tsx b/src/routes/popup/send/index.tsx index 428c98a9e..9bf997a28 100644 --- a/src/routes/popup/send/index.tsx +++ b/src/routes/popup/send/index.tsx @@ -3,21 +3,19 @@ import { useState, useEffect, useMemo } from "react"; import styled, { css } from "styled-components"; import { Button, - Input, + ButtonV2, + InputV2, Section, Spacer, Text, - Tooltip, useInput } from "@arconnect/components"; import browser from "webextension-polyfill"; -import Head from "~components/popup/Head"; import * as viewblock from "~lib/viewblock"; import { ArrowUpRightIcon, ChevronDownIcon, - ChevronRightIcon, - RefreshIcon + ChevronRightIcon } from "@iconicicons/react"; import Token, { ArToken, @@ -411,6 +409,7 @@ export default function Send({ id }: Props) { { setShowSlider(!showSlider); @@ -435,7 +434,6 @@ export default function Send({ id }: Props) { {!!price && ( - + USD/ {token.ticker.toUpperCase()} @@ -470,7 +464,6 @@ export default function Send({ id }: Props) { )} setQty(max.toString())} > Max @@ -500,7 +493,6 @@ export default function Send({ id }: Props) { {!uToken && ( - {browser.i18n.getMessage("next")} - - + + {showTokenSelector && ( @@ -640,22 +632,46 @@ const RecipientAmountWrapper = styled.div` gap: 7px; `; -const MaxButton = styled(Button)<{ altColor?: string }>` +const MaxButton = styled.button<{ altColor?: string }>` + position: absolute; + right: 8px; + top: -3px; + display: flex; + text-align: center; + align-items: center; + justify-content: center; + outline: none; + font-size: 13.28px; + gap: 0.3rem; + width: 37px !important; + height: 28px !important; border-radius: 3px; padding: 5px; + border: 0px; + cursor: pointer; color: ${(props) => (props.altColor ? "#b9b9b9" : props.theme.theme)}; background-color: ${(props) => props.altColor ? props.altColor : props.theme.theme}; font-weight: 400; + box-shadow: 0 0 0 0 rgba(${(props) => props.theme.theme}); `; -const CurrencyButton = styled(Button)` +const CurrencyButton = styled.button` + position: absolute; + right: 56px; font-weight: 400; background-color: transparent; border-radius: 4px; gap: 0; display: flex; padding: 2px; + font-size: 13.28px; + cursor: pointer; + text-align: center; + align-items: center; + justify-content: center; + outline: none; + border: 0px; `; const Wrapper = styled.div<{ showOverlay: boolean }>` @@ -692,25 +708,8 @@ interface Props { type QtyMode = "fiat" | "token"; -const QuantitySection = styled.div<{ qtyMode: QtyMode; invalidValue: boolean }>` - position: relative; - display: flex; - justify-content: center; - align-items: center; - gap: ${(props) => (props.qtyMode === "token" ? "0.65rem" : "0")}; - height: ${defaulQtytSize + "rem"}; - - input, - p { - color: rgb( - ${(props) => (props.invalidValue ? "255, 0, 0" : props.theme.theme)} - ); - transition: color 0.23s ease-in-out; - } -`; - // Make this dynamic -export const SendButton = styled(Button)<{ alternate?: boolean }>` +export const SendButton = styled(ButtonV2)<{ alternate?: boolean }>` background-color: ${(props) => props.alternate && "rgb(171, 154, 255, 0.15)"}; border: 1px solid rgba(171, 154, 255, 0.15); border-radius: 10px; @@ -724,15 +723,23 @@ export const SendButton = styled(Button)<{ alternate?: boolean }>` &:hover:not(:active):not(:disabled) { box-shadow: 0 0 0 0.075rem rgba(${(props) => props.theme.theme}, 0.5); + background-color: none; } `; -export const SendInput = styled(Input)<{ error?: boolean }>` +export const SendInput = styled(InputV2)<{ error?: boolean }>` color: ${(props) => (props.error ? "red" : "#b9b9b9")}; background-color: rgba(171, 154, 255, 0.15); font-weight: 400; font-size: 1rem; padding: 10px; + + // remove counter + &::-webkit-outer-spin-button, + &::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } `; const InputIcons = styled.div` diff --git a/src/routes/popup/transaction/[id].tsx b/src/routes/popup/transaction/[id].tsx index 74081d04b..a8552d865 100644 --- a/src/routes/popup/transaction/[id].tsx +++ b/src/routes/popup/transaction/[id].tsx @@ -1,6 +1,6 @@ import { formatFiatBalance, formatTokenBalance } from "~tokens/currency"; import { AnimatePresence, type Variants, motion } from "framer-motion"; -import { Button, Section, Spacer, Text } from "@arconnect/components"; +import { Section, Spacer, Text } from "@arconnect/components"; import type { GQLNodeInterface } from "ar-gql/dist/faces"; import { useEffect, useMemo, useState } from "react"; import { useGateway } from "~gateways/wayfinder"; @@ -534,7 +534,7 @@ export default function Transaction({ id: rawId, gw, message }: Props) { }} > {ao.isAo ? "ao Scanner" : "Viewblock"} - +
diff --git a/src/routes/popup/unlock.tsx b/src/routes/popup/unlock.tsx index e5909a4f5..9be1234f0 100644 --- a/src/routes/popup/unlock.tsx +++ b/src/routes/popup/unlock.tsx @@ -9,8 +9,8 @@ import browser from "webextension-polyfill"; import { updatePassword } from "~wallets"; import Head from "~components/popup/Head"; import { - Button, - Input, + ButtonV2, + InputV2, Section, Spacer, Text, @@ -140,7 +140,7 @@ export default function Unlock() { )} - - -
- +
); diff --git a/src/routes/welcome/generate/backup.tsx b/src/routes/welcome/generate/backup.tsx index 567affbc7..846ea7233 100644 --- a/src/routes/welcome/generate/backup.tsx +++ b/src/routes/welcome/generate/backup.tsx @@ -1,4 +1,4 @@ -import { Button, Spacer, Text } from "@arconnect/components"; +import { ButtonV2, Spacer, Text } from "@arconnect/components"; import { useLocation, useRoute } from "wouter"; import { useContext, useEffect, useState } from "react"; import { WalletContext } from "../setup"; @@ -55,7 +55,7 @@ export default function Backup() { {browser.i18n.getMessage("copySeed")} - + ); } diff --git a/src/routes/welcome/generate/confirm.tsx b/src/routes/welcome/generate/confirm.tsx index bc3025c8e..96a4d46ab 100644 --- a/src/routes/welcome/generate/confirm.tsx +++ b/src/routes/welcome/generate/confirm.tsx @@ -1,4 +1,4 @@ -import { Button, Spacer, Text, useToasts } from "@arconnect/components"; +import { ButtonV2, Spacer, Text, useToasts } from "@arconnect/components"; import { ArrowRightIcon } from "@iconicicons/react"; import { useLocation, useRoute } from "wouter"; import { useContext, useEffect, useState } from "react"; @@ -89,10 +89,10 @@ export default function Confirm() { preFill={preFill} /> - + + ); } diff --git a/src/routes/welcome/generate/done.tsx b/src/routes/welcome/generate/done.tsx index a18053e4d..8e75bda54 100644 --- a/src/routes/welcome/generate/done.tsx +++ b/src/routes/welcome/generate/done.tsx @@ -1,4 +1,4 @@ -import { Button, Checkbox, Spacer, Text } from "@arconnect/components"; +import { ButtonV2, Checkbox, Spacer, Text } from "@arconnect/components"; import { PasswordContext, WalletContext } from "../setup"; import { type AnsUser, getAnsProfile } from "~lib/ans"; import { formatAddress } from "~utils/format"; @@ -89,9 +89,9 @@ export default function Done() { {browser.i18n.getMessage("analytics_title")} - + ); } diff --git a/src/routes/welcome/gettingStarted.tsx b/src/routes/welcome/gettingStarted.tsx index 812861f64..cd74a1541 100644 --- a/src/routes/welcome/gettingStarted.tsx +++ b/src/routes/welcome/gettingStarted.tsx @@ -1,6 +1,6 @@ import { AnimatePresence, type Variants, motion } from "framer-motion"; import { useCallback, useState } from "react"; -import { Button, Card } from "@arconnect/components"; +import { ButtonV2, Card } from "@arconnect/components"; import { CheckIcon } from "@iconicicons/react"; import browser from "webextension-polyfill"; @@ -71,9 +71,9 @@ export default function GettingStarted({ page }) { /> ))} - + navigate(page + 1)}> + {browser.i18n.getMessage(page + 1 < 4 ? "next" : "done")} + diff --git a/src/routes/welcome/index.tsx b/src/routes/welcome/index.tsx index 4344c08be..0f46518c0 100644 --- a/src/routes/welcome/index.tsx +++ b/src/routes/welcome/index.tsx @@ -1,5 +1,5 @@ import { ExtensionStorage, OLD_STORAGE_NAME } from "~utils/storage"; -import { Button, Spacer, Text } from "@arconnect/components"; +import { ButtonV2, Spacer, Text } from "@arconnect/components"; import { ArrowRightIcon, KeyIcon } from "@iconicicons/react"; import Screenshots from "~components/welcome/Screenshots"; import { AnimatePresence, motion } from "framer-motion"; @@ -86,7 +86,7 @@ export default function Home() { }} > {browser.i18n.getMessage("get_me_started")} - + {browser.i18n.getMessage("have_wallet")} - + {migrationAvailable && ( @@ -212,7 +212,7 @@ const ButtonsWrapper = styled.div` gap: 0.75rem; `; -const WelcomeButton = styled(Button)` +const WelcomeButton = styled(ButtonV2)` padding-left: 0; padding-right: 0; width: calc(100% - 0.75rem * 1); diff --git a/src/routes/welcome/load/done.tsx b/src/routes/welcome/load/done.tsx index 133bbfae3..345afb62e 100644 --- a/src/routes/welcome/load/done.tsx +++ b/src/routes/welcome/load/done.tsx @@ -1,4 +1,4 @@ -import { Button, Checkbox, Spacer, Text } from "@arconnect/components"; +import { ButtonV2, Checkbox, Spacer, Text } from "@arconnect/components"; import { PageType, trackPage } from "~utils/analytics"; import { useStorage } from "@plasmohq/storage/hook"; import { ExtensionStorage } from "~utils/storage"; @@ -55,9 +55,9 @@ export default function Done() { {browser.i18n.getMessage("analytics_title")} - + ); } diff --git a/src/routes/welcome/load/password.tsx b/src/routes/welcome/load/password.tsx index ab67e79aa..f04eb8f95 100644 --- a/src/routes/welcome/load/password.tsx +++ b/src/routes/welcome/load/password.tsx @@ -8,8 +8,8 @@ import { useContext, useMemo, useEffect } from "react"; import browser from "webextension-polyfill"; import { PasswordContext } from "../setup"; import { - Button, - Input, + ButtonV2, + InputV2, Spacer, Text, useInput, @@ -83,7 +83,7 @@ export default function Password() { {browser.i18n.getMessage("create_password_paragraph")} - - - + + ); } diff --git a/src/routes/welcome/load/theme.tsx b/src/routes/welcome/load/theme.tsx index e1c833962..e1492747b 100644 --- a/src/routes/welcome/load/theme.tsx +++ b/src/routes/welcome/load/theme.tsx @@ -1,4 +1,4 @@ -import { Button, Spacer, Text } from "@arconnect/components"; +import { ButtonV2, Spacer, Text } from "@arconnect/components"; import { useLocation, useRoute } from "wouter"; import { ArrowRightIcon, @@ -47,15 +47,15 @@ export default function Theme() { {browser.i18n.getMessage("system_theme")} - + + ); } diff --git a/src/routes/welcome/load/wallets.tsx b/src/routes/welcome/load/wallets.tsx index 4f2632f1f..04f34d313 100644 --- a/src/routes/welcome/load/wallets.tsx +++ b/src/routes/welcome/load/wallets.tsx @@ -9,8 +9,8 @@ import { useStorage } from "@plasmohq/storage/hook"; import { useLocation, useRoute } from "wouter"; import { PasswordContext } from "../setup"; import { - Button, - Modal, + ButtonV2, + ModalV2, Spacer, Text, useModal, @@ -191,13 +191,51 @@ export default function Wallets() { - - + + + { + try { + // add migrated wallets + await addWallet(walletsToMigrate, password); + + // confirmation toast + setToast({ + type: "info", + content: browser.i18n.getMessage("migration_confirmation"), + duration: 2200 + }); + migrationModal.setOpen(false); + + // TODO: + // remove old storage + // await ExtensionStorage.remove(OLD_STORAGE_NAME); + } catch {} + }} + > + {browser.i18n.getMessage("migrate")} + + + { + migrationModal.setOpen(false); + setMigrationCancelled(true); + }} + > + {browser.i18n.getMessage("cancel")} + + + } > {browser.i18n.getMessage("migration_available")} @@ -205,42 +243,8 @@ export default function Wallets() { {browser.i18n.getMessage("migration_available_paragraph")} - - - - + ); } diff --git a/src/routes/welcome/start/index.tsx b/src/routes/welcome/start/index.tsx index 7bad56a38..329b59f70 100644 --- a/src/routes/welcome/start/index.tsx +++ b/src/routes/welcome/start/index.tsx @@ -1,4 +1,4 @@ -import { Button, Spacer, Text } from "@arconnect/components"; +import { ButtonV2, Spacer, Text } from "@arconnect/components"; import { ArrowRightIcon } from "@iconicicons/react"; import { useLocation, useRoute } from "wouter"; import { motion } from "framer-motion"; @@ -33,11 +33,6 @@ export default function Start() { return ( - - - {browser.i18n.getMessage(activePage.title)} @@ -59,15 +54,24 @@ export default function Start() { )} - + + + setLocation(page === 3 ? "/generate/1" : `/start/${page + 1}`) + } + > + {browser.i18n.getMessage("next")} + + + setLocation("/generate/1")} + > + {browser.i18n.getMessage("skip")} + + {Array(3) @@ -158,10 +162,10 @@ const Page = styled.span<{ active?: boolean }>` transition: all 0.23s ease-in-out; `; -const Skip = styled.div` - position: absolute; - top: 3rem; - right: 3rem; +const ButtonWrapper = styled.div` + display: flex; + flex-direction: column; + gap: 8px; `; interface PageInterface { diff --git a/src/tabs/arlocal.tsx b/src/tabs/arlocal.tsx index 1663c86d8..bc1ce21a6 100644 --- a/src/tabs/arlocal.tsx +++ b/src/tabs/arlocal.tsx @@ -8,8 +8,8 @@ import { ExtensionStorage } from "~utils/storage"; import { RefreshIcon } from "@iconicicons/react"; import { useNoWallets } from "~wallets"; import { - Button, - Input, + ButtonV2 as Button, + InputV2 as Input, Provider, Spacer, useInput, diff --git a/yarn.lock b/yarn.lock index 19a01946a..1c2b10527 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,14 +15,14 @@ resolved "https://registry.yarnpkg.com/@apocentre/alias-sampling/-/alias-sampling-0.5.3.tgz#897ff181b48ad7b2bcb4ecf29400214888244f08" integrity sha512-7UDWIIF9hIeJqfKXkNIzkVandlwLf1FWTSdrb9iXvOP8oF544JRXQjCbiTmCv2c9n44n/FIWtehhBfNuAx2CZA== -"@arconnect/components@^0.2.8": - version "0.2.8" - resolved "https://registry.yarnpkg.com/@arconnect/components/-/components-0.2.8.tgz#ed400223da5a8682da69262712e56f4663b605ed" - integrity sha512-CM8clY8LGr7PBjhhg+2ynI83OqRJSJspyC2xltZh9D/vcN24deFalWcgOFRIQOYMCYQZKZPcCt+oRm2lDi/IvA== +"@arconnect/components@^0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@arconnect/components/-/components-0.3.7.tgz#1f4b077885304e3e438e0fe2dd1d51ba88cec212" + integrity sha512-vNrWcmk+MoAeRVfSRagq1txL5sRcx863Zlm+Li7sxwgwkw6xqCRvGl8pso+KVcEObBHcNdZQ6E44pE680ttGSQ== dependencies: "@iconicicons/react" "^1.5.1" axios "^1.6.7" - framer-motion "^10.5.0" + framer-motion "^7.5.3" nanoid "^4.0.1" uuid "^9.0.1" @@ -6571,15 +6571,6 @@ formidable@^1.2.2: resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.6.tgz#d2a51d60162bbc9b4a055d8457a7c75315d1a168" integrity sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ== -framer-motion@^10.5.0: - version "10.18.0" - resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-10.18.0.tgz#1f4fc51403996ea7170af885bd44a7079d255950" - integrity sha512-oGlDh1Q1XqYPksuTD/usb0I70hq95OUzmL9+6Zd+Hs4XV0oaISBa/UUMSjYiq6m8EUF32132mOJ8xVZS+I0S6w== - dependencies: - tslib "^2.4.0" - optionalDependencies: - "@emotion/is-prop-valid" "^0.8.2" - framer-motion@^7.5.3: version "7.5.3" resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-7.5.3.tgz#a1de7d6c4abbf7333619d4a6c8df74c12240be43"