diff --git a/.depcheckrc b/.depcheckrc index 3c8ac7c4b8..3059028df2 100644 --- a/.depcheckrc +++ b/.depcheckrc @@ -33,7 +33,9 @@ "expo-splash-screen", "electron-store", "redux-persist-electron-storage", - "@axelar-network/axelarjs-types" + "@axelar-network/axelarjs-types", + "@react-native-clipboard/clipboard", + "react-native-fs" ], "ignorePatterns": [ "/cache", diff --git a/metro.config.js b/metro.config.js index 442a75bd74..6fb3d756b1 100644 --- a/metro.config.js +++ b/metro.config.js @@ -29,6 +29,16 @@ module.exports = (() => { type: "empty", }; } + if ( + platform === "web" && + ["react-native-fs", "@react-native-clipboard/clipboard"].includes( + moduleName, + ) + ) { + return { + type: "empty", + }; + } //TODO: remove after electron renderer fix if ( platform === "web" && diff --git a/package.json b/package.json index dd7c7d1431..774dc30bde 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build:web": "expo export -p web", "lint": "npx tsx packages/scripts/paralint", "lint-fix": "eslint --cache --ext .js,.jsx,.ts,.tsx . --fix", - "unused-exports": "ts-unused-exports ./tsconfig.json --excludePathsFromReport=\"packages/api;packages/contracts-clients;packages/evm-contracts-clients;packages/screens/RiotGame/RiotGameBridgeScreen.tsx;packages/components/socialFeed/RichText/inline-toolbar;app.config.js;weshd;./App.tsx;.*\\.web|.electron|.native|.d.ts\"", + "unused-exports": "ts-unused-exports ./tsconfig.json --excludePathsFromReport=\"packages/api;packages/contracts-clients;packages/evm-contracts-clients;packages/screens/RiotGame/RiotGameBridgeScreen.tsx;packages/components/socialFeed/RichText/inline-toolbar;app.config.js;weshd;./App.tsx;packages/modules/FileSystem/index.ts;.*\\.web|.electron|.native|.d.ts\"", "validate-networks": "tsx packages/scripts/validateNetworks.ts", "postinstall": "patch-package" }, @@ -55,6 +55,7 @@ "@pinata/sdk": "^2.1.0", "@react-native-anywhere/polyfill-base64": "^0.0.1-alpha.0", "@react-native-async-storage/async-storage": "1.21.0", + "@react-native-clipboard/clipboard": "^1.13.2", "@react-native-community/slider": "4.4.2", "@react-native-masked-view/masked-view": "0.3.0", "@react-navigation/drawer": "^6.6.6", @@ -80,6 +81,7 @@ "expo-barcode-scanner": "~12.9.2", "expo-clipboard": "~5.0.1", "expo-document-picker": "~11.10.1", + "expo-file-system": "~16.0.6", "expo-font": "~11.10.2", "expo-linear-gradient": "~12.7.1", "expo-optimize": "^0.2.20", @@ -107,6 +109,7 @@ "react-native-confetti-cannon": "^1.5.2", "react-native-countdown-component": "^2.7.1", "react-native-drax": "^0.10.2", + "react-native-fs": "^2.20.0", "react-native-gesture-handler": "~2.14.0", "react-native-get-random-values": "~1.8.0", "react-native-heroicons": "^3.2.0", diff --git a/packages/components/CopyToClipboard.tsx b/packages/components/CopyToClipboard.tsx index d9b1765cf5..f2f7936fe8 100644 --- a/packages/components/CopyToClipboard.tsx +++ b/packages/components/CopyToClipboard.tsx @@ -1,4 +1,3 @@ -import * as Clipboard from "expo-clipboard"; import React from "react"; import { TouchableOpacity } from "react-native"; @@ -9,10 +8,12 @@ import copySVG from "../../assets/icons/copy.svg"; import { useFeedbacks } from "../context/FeedbacksProvider"; import { neutral22 } from "../utils/style/colors"; +import Clipboard from "@/modules/Clipboard"; + export const useCopyToClipboard = () => { const { setToastSuccess } = useFeedbacks(); - const copyToClipboard = (text: string, successText?: string) => { + const copyToClipboard = async (text: string, successText?: string) => { setToastSuccess({ title: successText || "Copied", message: "", diff --git a/packages/components/CopyToClipboardIcon.tsx b/packages/components/CopyToClipboardIcon.tsx index d58166f4b6..4d4f09714f 100644 --- a/packages/components/CopyToClipboardIcon.tsx +++ b/packages/components/CopyToClipboardIcon.tsx @@ -1,4 +1,3 @@ -import * as Clipboard from "expo-clipboard"; import React from "react"; import { TouchableOpacity } from "react-native"; @@ -8,6 +7,8 @@ import copySVG from "../../assets/icons/copy.svg"; import { useFeedbacks } from "../context/FeedbacksProvider"; import { neutral22 } from "../utils/style/colors"; +import Clipboard from "@/modules/Clipboard"; + export const CopyToClipboardIcon: React.FC<{ text: string; squaresBackgroundColor?: string; diff --git a/packages/components/collections/CollectionHeader.tsx b/packages/components/collections/CollectionHeader.tsx index d7cb1efb1b..95e6fc46c9 100644 --- a/packages/components/collections/CollectionHeader.tsx +++ b/packages/components/collections/CollectionHeader.tsx @@ -1,4 +1,3 @@ -import * as Clipboard from "expo-clipboard"; import React from "react"; import { View, Platform, Linking } from "react-native"; @@ -26,6 +25,8 @@ import { SortButton } from "../sorts/SortButton"; import { SpacerRow } from "../spacer"; import { Tabs } from "../tabs/Tabs"; +import Clipboard from "@/modules/Clipboard"; + // All the screen content before the Flatlist used to display NFTs export const CollectionHeader: React.FC<{ collectionId: string; diff --git a/packages/modules/Clipboard/index.native.ts b/packages/modules/Clipboard/index.native.ts new file mode 100644 index 0000000000..fc24eedbdb --- /dev/null +++ b/packages/modules/Clipboard/index.native.ts @@ -0,0 +1,16 @@ +import * as ExpoClipboard from "expo-clipboard"; +import Constants from "expo-constants"; +const isRunningInExpoGo = Constants.appOwnership === "expo"; + +let Clipboard; + +if (isRunningInExpoGo) { + Clipboard = ExpoClipboard; +} else { + const moduleName = "@react-native-clipboard/clipboard"; + Clipboard = require(moduleName).default; + Clipboard.setStringAsync = Clipboard.setString; + Clipboard.getStringAsync = Clipboard.getString; +} + +export default Clipboard; diff --git a/packages/modules/Clipboard/index.ts b/packages/modules/Clipboard/index.ts new file mode 100644 index 0000000000..e8527c6ce1 --- /dev/null +++ b/packages/modules/Clipboard/index.ts @@ -0,0 +1,3 @@ +import * as Clipboard from "expo-clipboard"; + +export default Clipboard; diff --git a/packages/modules/FileSystem/index.native.ts b/packages/modules/FileSystem/index.native.ts new file mode 100644 index 0000000000..17db92bb27 --- /dev/null +++ b/packages/modules/FileSystem/index.native.ts @@ -0,0 +1,23 @@ +import Constants from "expo-constants"; +import * as ExpoFileSystem from "expo-file-system"; + +const isRunningInExpoGo = Constants.appOwnership === "expo"; + +let FileSystem = ExpoFileSystem; + +if (isRunningInExpoGo) { + FileSystem = ExpoFileSystem; +} else { + const moduleName = "react-native-fs"; + const RNFS = require(moduleName); + //TODO: patch other expo file system functions + FileSystem = { + ...ExpoFileSystem, + readAsStringAsync: async (uri, options) => { + console.log("here test"); + return await RNFS.readFile(uri, options?.encoding); + }, + }; +} + +export default FileSystem; diff --git a/packages/modules/FileSystem/index.ts b/packages/modules/FileSystem/index.ts new file mode 100644 index 0000000000..182f111170 --- /dev/null +++ b/packages/modules/FileSystem/index.ts @@ -0,0 +1,3 @@ +import * as FileSystem from "expo-file-system"; + +export default FileSystem; diff --git a/packages/screens/Message/components/ChatHeader.tsx b/packages/screens/Message/components/ChatHeader.tsx index 20b23b2837..4a06d18dbe 100644 --- a/packages/screens/Message/components/ChatHeader.tsx +++ b/packages/screens/Message/components/ChatHeader.tsx @@ -1,4 +1,3 @@ -import * as Clipboard from "expo-clipboard"; import React, { useState } from "react"; import { View, TouchableOpacity } from "react-native"; import { useDispatch } from "react-redux"; @@ -27,6 +26,8 @@ import { getConversationName } from "../../../weshnet/messageHelpers"; import { createMultiMemberShareableLink } from "../../../weshnet/services"; import { bytesFromString } from "../../../weshnet/utils"; +import Clipboard from "@/modules/Clipboard"; + interface ChatHeaderProps { searchInput: string; setSearchInput: (input: string) => void; diff --git a/packages/screens/Message/components/MessagePopup.tsx b/packages/screens/Message/components/MessagePopup.tsx index 4390812245..01f8c6bbab 100644 --- a/packages/screens/Message/components/MessagePopup.tsx +++ b/packages/screens/Message/components/MessagePopup.tsx @@ -1,4 +1,3 @@ -import * as Clipboard from "expo-clipboard"; import React from "react"; import { View, TouchableOpacity } from "react-native"; @@ -14,6 +13,8 @@ import { neutralA3 } from "../../../utils/style/colors"; import { fontSemibold13 } from "../../../utils/style/fonts"; import { layout } from "../../../utils/style/layout"; +import Clipboard from "@/modules/Clipboard"; + interface MessagePopupProps { message: string; onReply: () => void; diff --git a/packages/screens/WalletManager/WalletItem.tsx b/packages/screens/WalletManager/WalletItem.tsx index 47977f74fb..b8883c1cd2 100644 --- a/packages/screens/WalletManager/WalletItem.tsx +++ b/packages/screens/WalletManager/WalletItem.tsx @@ -1,4 +1,3 @@ -import * as Clipboard from "expo-clipboard"; import React, { useMemo, useState } from "react"; import { View, @@ -30,6 +29,8 @@ import { useAppDispatch } from "../../store/store"; import { neutral33, neutral77 } from "../../utils/style/colors"; import { modalMarginPadding } from "../../utils/style/modals"; +import Clipboard from "@/modules/Clipboard"; + interface WalletItemProps { item: Wallet; zIndex?: number; diff --git a/yarn.lock b/yarn.lock index 556020af5f..d321fbb506 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5187,6 +5187,16 @@ __metadata: languageName: node linkType: hard +"@react-native-clipboard/clipboard@npm:^1.13.2": + version: 1.13.2 + resolution: "@react-native-clipboard/clipboard@npm:1.13.2" + peerDependencies: + react: ">=16.0" + react-native: ">=0.57.0" + checksum: e26a2b92ff4cd8f5cc1bd5ae784fa7b2d9437d7801abf9a09bf34ddb450bb5e898256e1793f22543ef0576710dab99fa6ccf693364a04f1334acc6eccd64b497 + languageName: node + linkType: hard + "@react-native-community/cli-clean@npm:12.3.0": version: 12.3.0 resolution: "@react-native-community/cli-clean@npm:12.3.0" @@ -16553,6 +16563,22 @@ __metadata: languageName: node linkType: hard +"react-native-fs@npm:^2.20.0": + version: 2.20.0 + resolution: "react-native-fs@npm:2.20.0" + dependencies: + base-64: ^0.1.0 + utf8: ^3.0.0 + peerDependencies: + react-native: "*" + react-native-windows: "*" + peerDependenciesMeta: + react-native-windows: + optional: true + checksum: 0be9bb9a5c13b501d0a3006efc3aa5c0b5b211456ee04718297f4e522532f3527f1daa220bd67d3b82d819ed8fdab8f64b7d6e0d7b768c1fd1d8ec9122d94316 + languageName: node + linkType: hard + "react-native-gesture-handler@npm:~2.14.0": version: 2.14.1 resolution: "react-native-gesture-handler@npm:2.14.1" @@ -18931,6 +18957,7 @@ __metadata: "@pinata/sdk": ^2.1.0 "@react-native-anywhere/polyfill-base64": ^0.0.1-alpha.0 "@react-native-async-storage/async-storage": 1.21.0 + "@react-native-clipboard/clipboard": ^1.13.2 "@react-native-community/slider": 4.4.2 "@react-native-masked-view/masked-view": 0.3.0 "@react-navigation/drawer": ^6.6.6 @@ -18974,6 +19001,7 @@ __metadata: expo-dev-client: ~3.3.8 expo-doctor: ^1.1.3 expo-document-picker: ~11.10.1 + expo-file-system: ~16.0.6 expo-font: ~11.10.2 expo-linear-gradient: ~12.7.1 expo-optimize: ^0.2.20 @@ -19004,6 +19032,7 @@ __metadata: react-native-confetti-cannon: ^1.5.2 react-native-countdown-component: ^2.7.1 react-native-drax: ^0.10.2 + react-native-fs: ^2.20.0 react-native-gesture-handler: ~2.14.0 react-native-get-random-values: ~1.8.0 react-native-heroicons: ^3.2.0 @@ -19810,6 +19839,13 @@ __metadata: languageName: node linkType: hard +"utf8@npm:^3.0.0": + version: 3.0.0 + resolution: "utf8@npm:3.0.0" + checksum: cb89a69ad9ab393e3eae9b25305b3ff08bebca9adc839191a34f90777eb2942f86a96369d2839925fea58f8f722f7e27031d697f10f5f39690f8c5047303e62d + languageName: node + linkType: hard + "util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2"