Skip to content

Commit

Permalink
Merge pull request #581 from arconnectio/fix/placeholder-issue
Browse files Browse the repository at this point in the history
fix: resolve issue with placeholder & related code
  • Loading branch information
nicholaswma authored Dec 17, 2024
2 parents f7dd3c1 + 5de1076 commit b51f41c
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 58 deletions.
4 changes: 2 additions & 2 deletions src/components/HeadAuth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ export const HeadAuth: React.FC<HeadAuthProps> = ({
fallbackName ||
new URL(url).hostname.split(".").slice(-2).join("."),
logo: appInfo.logo || fallbackLogo,
type: appLogoPlaceholder.type,
placeholder: appLogoPlaceholder.placeholder
type: appLogoPlaceholder?.type,
placeholder: appLogoPlaceholder?.placeholder
});
}

Expand Down
12 changes: 2 additions & 10 deletions src/components/dashboard/Reset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import {
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";
import { resetStorage } from "~utils/storage.utils";

export function ResetDashboardView() {
// reset modal
Expand All @@ -25,15 +25,7 @@ export function ResetDashboardView() {
// reset ArConnect
async function reset() {
try {
// get all keys
const allStoredKeys = Object.keys(
(await browser.storage.local.get(null)) || {}
);

// remove all keys
await Promise.allSettled(
allStoredKeys.map((key) => ExtensionStorage.remove(key))
);
await resetStorage();

// close window
window.top.close();
Expand Down
38 changes: 30 additions & 8 deletions src/components/hardware/HardwareWalletTheme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import {
ARCONNECT_DARK_THEME,
ARCONNECT_LIGHT_THEME,
Provider as ThemeProvider,
type ArconnectTheme
type ArconnectTheme,
type DisplayTheme
} from "@arconnect/components";

const ARCONNECT_THEME_BACKGROUND_COLOR = "ARCONNECT_THEME_BACKGROUND_COLOR";
const ARCONNECT_THEME_TEXT_COLOR = "ARCONNECT_THEME_TEXT_COLOR";
import {
ARCONNECT_THEME_BACKGROUND_COLOR,
ARCONNECT_THEME_TEXT_COLOR
} from "~utils/storage.utils";

/**
* Modify the theme if the active wallet is a hardware wallet. We transform the
Expand Down Expand Up @@ -54,19 +56,27 @@ export function ArConnectThemeProvider({ children }: PropsWithChildren<{}>) {
theme === "dark" ? ARCONNECT_DARK_THEME : ARCONNECT_LIGHT_THEME
)}
>
<ThemeBackgroundObserver />
<ThemeBackgroundObserver theme={theme} />

{children}
</ThemeProvider>
);
}

export function ThemeBackgroundObserver() {
interface ThemeBackgroundObserverProps {
theme?: DisplayTheme;
}

export function ThemeBackgroundObserver({
theme
}: ThemeBackgroundObserverProps) {
const styledComponentsTheme = useStyledComponentsTheme();
const backgroundColor = styledComponentsTheme.background;
const textColor = styledComponentsTheme.primaryText;

useEffect(() => {
if (!theme) return;

let formattedBackgroundColor = "";

if (backgroundColor.length === 3 || backgroundColor.length === 6) {
Expand All @@ -82,10 +92,17 @@ export function ThemeBackgroundObserver() {
ARCONNECT_THEME_BACKGROUND_COLOR,
formattedBackgroundColor
);

document.documentElement.style.setProperty(
"--backgroundColor",
formattedBackgroundColor
);
}
}, [backgroundColor]);
}, [theme, backgroundColor]);

useEffect(() => {
if (!theme) return;

let formattedTextColor = "";

if (textColor.length === 3 || textColor.length === 6) {
Expand All @@ -98,8 +115,13 @@ export function ThemeBackgroundObserver() {

if (formattedTextColor) {
localStorage.setItem(ARCONNECT_THEME_TEXT_COLOR, formattedTextColor);

document.documentElement.style.setProperty(
"--textColor",
formattedTextColor
);
}
}, [textColor]);
}, [theme, textColor]);

return null;
}
2 changes: 1 addition & 1 deletion src/components/popup/HeadV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export default function HeadV2({
const hardwareApi = useHardwareApi();

const appName = appInfo?.name;
const appIconPlaceholderText = appInfo.placeholder;
const appIconPlaceholderText = appInfo?.placeholder;

const SquircleWrapper = onAppInfoClick ? ButtonSquircle : React.Fragment;

Expand Down
51 changes: 32 additions & 19 deletions src/utils/auth/auth.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,19 @@ export async function createAuthPopup(
moduleAppData: ModuleAppData
) {
const unlock = await popupMutex.lock();
const wallets = await getWallets();

// TODO: What about getActiveAddress()?
const [activeAddress, wallets] = await Promise.all([
getActiveAddress(),
getWallets()
]);

if (wallets.length === 0) {
const hasWallets = activeAddress && wallets.length > 0;

if (!hasWallets) {
openOrSelectWelcomePage(true);

unlock();

throw new Error(ERR_MSG_NO_WALLETS_ADDED);
}

Expand All @@ -149,22 +155,29 @@ export async function createAuthPopup(
);
}

if (!popupWindowTab) {
// TODO: To center this, the injected tab should send the center or dimensions of the screen:

const window = await browser.windows.create({
url: `${browser.runtime.getURL("tabs/auth.html")}#/`,
focused: true,
type: "popup",
width: 385,
height: 720
});

setPopupTabID(window.tabs[0].id);
} else {
log(LOG_GROUP.AUTH, "reusePopupTabID =", POPUP_TAB_ID);

await browser.windows.update(popupWindowTab.windowId, { focused: true });
try {
if (!popupWindowTab) {
// TODO: To center this, the injected tab should send the center or dimensions of the screen:

const window = await browser.windows.create({
url: `${browser.runtime.getURL("tabs/auth.html")}#/`,
focused: true,
type: "popup",
width: 385,
height: 720
});

setPopupTabID(window.tabs[0].id);
} else {
log(LOG_GROUP.AUTH, "reusePopupTabID =", POPUP_TAB_ID);

await browser.windows.update(popupWindowTab.windowId, { focused: true });
}
} catch (err) {
console.warn(
`Could not ${popupWindowTab ? "focus" : "open"} "tabs/auth.html":`,
err
);
}

let authID: string | undefined;
Expand Down
28 changes: 28 additions & 0 deletions src/utils/storage.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import browser from "webextension-polyfill";
import { ExtensionStorage } from "~utils/storage";

export const ARCONNECT_THEME_BACKGROUND_COLOR =
"ARCONNECT_THEME_BACKGROUND_COLOR";
export const ARCONNECT_THEME_TEXT_COLOR = "ARCONNECT_THEME_TEXT_COLOR";

/**
* Clear all storage keys except for gateways.
*/
export async function resetStorage() {
if (typeof localStorage !== "undefined") {
localStorage.removeItem(ARCONNECT_THEME_BACKGROUND_COLOR);
localStorage.removeItem(ARCONNECT_THEME_TEXT_COLOR);
}

try {
// get all keys except gateways
const allStoredKeys = Object.keys(
(await browser.storage.local.get(null)) || {}
).filter((key) => key !== "gateways");

// remove all keys except gateways
await Promise.allSettled(
allStoredKeys.map((key) => ExtensionStorage.remove(key))
);
} catch {}
}
21 changes: 20 additions & 1 deletion src/utils/urls/getAppIconPlaceholder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
import type { AppLogoInfo } from "~applications/application";
import { isGateway } from "./isGateway";

/**
* Ensures a URL has a valid HTTP/HTTPS protocol prefix.
* If no protocol is present, HTTPS is added as the default.
*
* @param url - The URL string to normalize
* @returns The URL with a valid protocol prefix
*/
function ensureUrlProtocol(url: string): string {
try {
const hasProtocol = /^https?:\/\//i.test(url);
return hasProtocol ? url : `https://${url}`;
} catch {
return url;
}
}

/**
* Generates a logo placeholder based on the base domain.
* If the URL is a gateway (determined by a GET call), it uses the first two letters of the subdomain.
Expand All @@ -11,6 +28,7 @@ export async function generateLogoPlaceholder(
url: string
): Promise<AppLogoInfo | undefined> {
try {
url = ensureUrlProtocol(url);
const { hostname } = new URL(url);

const parts = hostname.split(".");
Expand All @@ -21,7 +39,8 @@ export async function generateLogoPlaceholder(
parts.length > 1 ? parts.slice(1).join(".") : null;

const isGatewayUrl =
!!candidateGatewayUrl && (await isGateway(candidateGatewayUrl));
!!candidateGatewayUrl &&
(await isGateway(ensureUrlProtocol(candidateGatewayUrl)));

if (isGatewayUrl) {
// For gateways, take the first two letters of the first subdomain
Expand Down
10 changes: 5 additions & 5 deletions src/utils/wallets/wallets.provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,17 @@ export function WalletsProvider({

let walletStatus: WalletStatus = "noWallets";

if (hasWallets && decryptionKey) {
walletStatus = "unlocked";
} else if (!decryptionKey) {
walletStatus = "locked";
if (hasWallets) {
walletStatus = decryptionKey ? "unlocked" : "locked";
} else if (redirectToWelcome) {
// This should only happen when opening the regular popup, but not for the auth popup, as the
// `createAuthPopup` will open the welcome page directly, instead of the popup, if needed:

openOrSelectWelcomePage(true);
await openOrSelectWelcomePage(true);

window.top.close();

return;
}

setWalletsContextState({
Expand Down
14 changes: 2 additions & 12 deletions src/wallets/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import type { JWKInterface } from "arweave/node/lib/wallet";
import { useStorage } from "@plasmohq/storage/hook";
import { ExtensionStorage } from "~utils/storage";
import type { HardwareWallet } from "./hardware";
import { useEffect, useState } from "react";
import browser from "webextension-polyfill";
import Arweave from "arweave/web/common";
import {
Expand All @@ -24,6 +22,7 @@ import {
import type { ModuleAppData } from "~api/background/background-modules";
import { isNotCancelError } from "~utils/assertions";
import { log, LOG_GROUP } from "~utils/log/log.utils";
import { resetStorage } from "~utils/storage.utils";

/**
* Locally stored wallet
Expand Down Expand Up @@ -112,16 +111,7 @@ export async function openOrSelectWelcomePage(force = false) {

// Make sure we clear any stored value from previous installations before
// opening the welcome page to onboard the user:

// get all keys
const allStoredKeys = Object.keys(
(await browser.storage.local.get(null)) || {}
);

// remove all keys
await Promise.allSettled(
allStoredKeys.map((key) => ExtensionStorage.remove(key))
);
await resetStorage();

const url = browser.runtime.getURL("tabs/welcome.html");
const welcomePageTabs = await browser.tabs.query({ url });
Expand Down

0 comments on commit b51f41c

Please sign in to comment.