+
{profileProxy.created_by.handle}
-
+
Proxy
{isActive && (
- {profilePath && (
+ {address && (
+
+
+ )}
+
+ {profilePath && (
+
)}
-
+ {!address && }
)}
-
-
-
-
{
diff --git a/components/layout/sidebar/WebSidebarUser.tsx b/components/layout/sidebar/WebSidebarUser.tsx
index 6896b7a821..497223bcf7 100644
--- a/components/layout/sidebar/WebSidebarUser.tsx
+++ b/components/layout/sidebar/WebSidebarUser.tsx
@@ -7,9 +7,10 @@ import {
import { memo, useEffect, useRef, useState } from "react";
import { useClickAway } from "react-use";
import { getConnectionProfileIndicator } from "@/components/auth/connection-state-indicator";
+import { HeaderQRModal } from "@/components/header/share/HeaderShare";
import { useSeizeConnectContext } from "@/components/auth/SeizeConnectContext";
import HeaderUserConnect from "@/components/header/user/HeaderUserConnect";
-import HeaderUserProxyDropdown from "@/components/header/user/proxy/HeaderUserProxyDropdown";
+import HeaderUserMenuDropdown from "@/components/header/user/HeaderUserMenuDropdown";
import { resolveIpfsUrlSync } from "@/components/ipfs/IPFSContext";
import UserLevel from "@/components/user/utils/level/UserLevel";
import { DEFAULT_CONNECTED_PROFILE_FALLBACK_PFP } from "@/constants/constants";
@@ -17,6 +18,8 @@ import {
isAutoGeneratedHandle,
isEthereumAddress,
} from "@/helpers/AllowlistToolHelpers";
+import { useIsMobileDeviceStatus } from "@/hooks/isMobileDevice";
+import useCapacitor from "@/hooks/useCapacitor";
import { useIdentity } from "@/hooks/useIdentity";
interface WebSidebarUserProps {
@@ -30,6 +33,12 @@ function WebSidebarUser({
}: WebSidebarUserProps) {
const PROFILE_DOUBLE_ACTIVATE_DELAY_MS = 280;
const [showUserMenu, setShowUserMenu] = useState(false);
+ const [showShareModal, setShowShareModal] = useState(false);
+ const capacitor = useCapacitor();
+ const { isMobileDevice, isDeviceDetectionResolved } =
+ useIsMobileDeviceStatus();
+ const canUseDesktopShare =
+ !capacitor.isCapacitor && isDeviceDetectionResolved && !isMobileDevice;
const {
address,
seizeConnect,
@@ -144,8 +153,8 @@ function WebSidebarUser({
const hasUnreadOnOtherConnectedProfiles = connectedAccounts.some(
(account) =>
!account.isActive &&
- (connectedAccountUnreadNotifications[account.address.toLowerCase()] ?? 0) >
- 0
+ (connectedAccountUnreadNotifications?.[account.address.toLowerCase()] ??
+ 0) > 0
);
const switchToNextConnectedAccount = (): boolean => {
@@ -176,6 +185,11 @@ function WebSidebarUser({
setShowUserMenu((current) => !current);
};
+ const onOpenShare = () => {
+ setShowUserMenu(false);
+ setShowShareModal(true);
+ };
+
const onProfileActivate = () => {
if (profileClickTimeoutRef.current) {
clearTimeout(profileClickTimeoutRef.current);
@@ -268,13 +282,18 @@ function WebSidebarUser({
{showUserMenu && profile && (
- setShowUserMenu(false)}
+ onOpenShare={canUseDesktopShare ? onOpenShare : undefined}
/>
)}
+ setShowShareModal(false)}
+ />
);
}
diff --git a/components/nft-image/utils/arweave-fallback.ts b/components/nft-image/utils/arweave-fallback.ts
index a76b9414e1..c12c3079ac 100644
--- a/components/nft-image/utils/arweave-fallback.ts
+++ b/components/nft-image/utils/arweave-fallback.ts
@@ -1,28 +1,12 @@
import type React from "react";
-const ARWEAVE_GATEWAYS_PRIORITY: readonly string[] = [
+const ARWEAVE_GATEWAYS: readonly string[] = [
"arweave.net",
"gateway.arweave.net",
- "g8way.io",
-] as const;
-
-const ARWEAVE_GATEWAYS_LONG_TAIL: readonly string[] = [
- "arweave.org",
- "arweave.dev",
+ "gateway.ar.io",
"ar-io.net",
- "arweave.live",
- "arweave.surf",
- "arweave.team",
- "arweavetoday.com",
- "arweave.fyi",
- "arweave.guide",
] as const;
-const ARWEAVE_GATEWAYS: readonly string[] = dedupe([
- ...ARWEAVE_GATEWAYS_PRIORITY,
- ...ARWEAVE_GATEWAYS_LONG_TAIL,
-]);
-
function dedupe(list: readonly string[]): string[] {
return Array.from(new Set(list));
}
diff --git a/hooks/isMobileDevice.ts b/hooks/isMobileDevice.ts
index b35ebb6a9a..191e47f74f 100644
--- a/hooks/isMobileDevice.ts
+++ b/hooks/isMobileDevice.ts
@@ -2,17 +2,30 @@
import { useEffect, useState } from "react";
-export default function useIsMobileDevice() {
- const [isMobile, setIsMobile] = useState(false);
+const MOBILE_DEVICE_REGEX =
+ /Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i;
+
+const detectIsMobileDevice = (): boolean => {
+ const userAgent = typeof navigator === "undefined" ? "" : navigator.userAgent;
+ return MOBILE_DEVICE_REGEX.test(userAgent);
+};
+
+export function useIsMobileDeviceStatus() {
+ const [status, setStatus] = useState({
+ isMobileDevice: false,
+ isDeviceDetectionResolved: false,
+ });
useEffect(() => {
- const userAgent =
- typeof navigator === "undefined" ? "" : navigator.userAgent;
- const regex =
- /Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i;
- const mobile = regex.exec(userAgent) !== null;
- setIsMobile(mobile);
+ setStatus({
+ isMobileDevice: detectIsMobileDevice(),
+ isDeviceDetectionResolved: true,
+ });
}, []);
- return isMobile;
+ return status;
+}
+
+export default function useIsMobileDevice() {
+ return useIsMobileDeviceStatus().isMobileDevice;
}
diff --git a/package-lock.json b/package-lock.json
index 73c6480d2e..ac79bd804a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2423,6 +2423,29 @@
"node": ">=18"
}
},
+ "node_modules/@isaacs/balanced-match": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
+ "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/@isaacs/brace-expansion": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz",
+ "integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@isaacs/balanced-match": "^4.0.1"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
"node_modules/@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"dev": true,
@@ -14693,68 +14716,47 @@
}
},
"node_modules/eslint-plugin-sonarjs": {
- "version": "3.0.5",
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-3.0.7.tgz",
+ "integrity": "sha512-62jB20krIPvcwBLAyG3VVKa2ce2j2lL1yCb8Y0ylMRR/dLvCCTiQx8gQbXb+G81k1alPZ2/I3muZinqWQdBbzw==",
"dev": true,
"license": "LGPL-3.0-only",
"dependencies": {
- "@eslint-community/regexpp": "4.12.1",
+ "@eslint-community/regexpp": "4.12.2",
"builtin-modules": "3.3.0",
"bytes": "3.1.2",
"functional-red-black-tree": "1.0.1",
"jsx-ast-utils-x": "0.1.0",
"lodash.merge": "4.6.2",
- "minimatch": "9.0.5",
+ "minimatch": "10.1.2",
"scslre": "0.3.0",
- "semver": "7.7.2",
+ "semver": "7.7.4",
"typescript": ">=5"
},
"peerDependencies": {
"eslint": "^8.0.0 || ^9.0.0"
}
},
- "node_modules/eslint-plugin-sonarjs/node_modules/@eslint-community/regexpp": {
- "version": "4.12.1",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
- }
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/eslint-plugin-sonarjs/node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
"node_modules/eslint-plugin-sonarjs/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "version": "10.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.2.tgz",
+ "integrity": "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==",
"dev": true,
- "license": "ISC",
+ "license": "BlueOak-1.0.0",
"dependencies": {
- "brace-expansion": "^2.0.1"
+ "@isaacs/brace-expansion": "^5.0.1"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/eslint-plugin-sonarjs/node_modules/semver": {
- "version": "7.7.2",
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
"dev": true,
"license": "ISC",
"bin": {
@@ -16097,9 +16099,9 @@
}
},
"node_modules/hono": {
- "version": "4.12.3",
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.3.tgz",
- "integrity": "sha512-SFsVSjp8sj5UumXOOFlkZOG6XS9SJDKw0TbwFeV+AJ8xlST8kxK5Z/5EYa111UY8732lK2S/xB653ceuaoGwpg==",
+ "version": "4.12.5",
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.5.tgz",
+ "integrity": "sha512-3qq+FUBtlTHhtYxbxheZgY8NIFnkkC/MR8u5TTsr7YZ3wixryQ3cCwn3iZbg8p8B88iDBBAYSfZDS75t8MN7Vg==",
"license": "MIT",
"engines": {
"node": ">=16.9.0"
@@ -16287,7 +16289,9 @@
}
},
"node_modules/immutable": {
- "version": "5.1.4",
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz",
+ "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==",
"license": "MIT"
},
"node_modules/import-fresh": {