Skip to content

Commit

Permalink
feat: ios - add share extension view
Browse files Browse the repository at this point in the history
  • Loading branch information
achorein committed Dec 11, 2024
1 parent 1ed12f3 commit 531d13e
Show file tree
Hide file tree
Showing 32 changed files with 9,157 additions and 105 deletions.
6 changes: 6 additions & 0 deletions example/ios-custom-view/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
plugins
metro.config.js
babel.config.js
android
ios
webpack.config.js
7 changes: 7 additions & 0 deletions example/ios-custom-view/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
root: true,
extends: ["universe/native"],
rules: {
"import/order": "off",
},
};
38 changes: 38 additions & 0 deletions example/ios-custom-view/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files

# dependencies
node_modules/

# Expo
.expo/
dist/
web-build/

# Native
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision

# Metro
.metro-health-check*

# debug
npm-debug.*
yarn-debug.*
yarn-error.*

# macOS
.DS_Store
*.pem

# local env files
.env*.local

# typescript
*.tsbuildinfo

/ios
/android
8 changes: 8 additions & 0 deletions example/ios-custom-view/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"trailingComma": "all",
"tabWidth": 2,
"semi": true,
"singleQuote": false,
"printWidth": 80,
"arrowParens": "always"
}
98 changes: 98 additions & 0 deletions example/ios-custom-view/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { Button, Image, StyleSheet, Text, View } from "react-native";

import { useShareIntent, ShareIntentFile } from "expo-share-intent";
import { Fragment } from "react";

export default function App() {
const { hasShareIntent, shareIntent, resetShareIntent, error } =
useShareIntent({
debug: true,
resetOnBackground: true,
});

return (
<View style={styles.container}>
<Image
source={require("./assets/icon.png")}
style={[styles.logo, styles.gap]}
/>
<Text style={[styles.gap, styles.bold]}>
{hasShareIntent ? "SHARE INTENT FOUND !" : "NO SHARE INTENT DETECTED"}
</Text>

{/* TEXT and URL */}
{!!shareIntent.text && <Text style={styles.gap}>{shareIntent.text}</Text>}
{!!shareIntent.meta?.title && (
<Text style={styles.gap}>{JSON.stringify(shareIntent.meta)}</Text>
)}

{/* FILES */}
{shareIntent?.files?.map((file) => (
<Fragment key={file.path}>
{file.mimeType.startsWith("image/") && (
<Image source={{ uri: file.path }} style={[styles.image]} />
)}
<FileMeta file={file} />
</Fragment>
))}

{/* FOOTER */}
{!!shareIntent && (
<Button onPress={() => resetShareIntent()} title="Reset" />
)}
<Text style={[styles.error]}>{error}</Text>
</View>
);
}

function FileMeta({ file }: { file: ShareIntentFile }) {
return (
<View style={[styles.gap, styles.meta]}>
<Text style={styles.bold}>{file.fileName}</Text>
<Text>
{file.mimeType} ({Math.round((file.size || 0) / 1024)}
ko)
</Text>
{file.width && (
<Text>
{file.width} x {file.height}
</Text>
)}
{file.duration && <Text>{file.duration}ms</Text>}
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
logo: {
width: 75,
height: 75,
resizeMode: "contain",
},
image: {
width: 300,
height: 200,
resizeMode: "contain",
// backgroundColor: "lightgray",
},
gap: {
marginBottom: 20,
},
bold: {
fontWeight: "bold",
},
meta: {
alignItems: "center",
justifyContent: "center",
},
error: {
color: "red",
marginTop: 20,
},
});
62 changes: 62 additions & 0 deletions example/ios-custom-view/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"expo": {
"name": "ExpoShareIntent Example",
"slug": "expo-share-intent-example",
"scheme": "exposhareintentexample",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"assetBundlePatterns": ["**/*"],
"plugins": [
[
"../../app.plugin.js",
{
"iosActivationRules": {
"NSExtensionActivationSupportsText": true,
"NSExtensionActivationSupportsWebURLWithMaxCount": 1,
"NSExtensionActivationSupportsWebPageWithMaxCount": 1,
"NSExtensionActivationSupportsImageWithMaxCount": 2,
"NSExtensionActivationSupportsMovieWithMaxCount": 1,
"NSExtensionActivationSupportsFileWithMaxCount": 1
},
"iosShareExtensionName": "ExpoShareIntent Example Extension",
"iosAppGroupIdentifier": "customgroup.expo.modules.exposhareintent.example",
"androidIntentFilters": ["text/*", "image/*", "video/*"],
"androidMultiIntentFilters": ["image/*"],
"experimentialIosCustomView": true,
"disableIOS": false,
"disableAndroid": false
}
],
["expo-updates"]
],
"ios": {
"supportsTablet": true,
"bundleIdentifier": "expo.modules.exposhareintent.example"
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#ffffff"
},
"package": "expo.modules.exposhareintent.example"
},
"extra": {
"eas": {
"projectId": "7a5b9f0b-c450-4c48-9e89-be9b6d6a2e98"
}
},
"runtimeVersion": {
"policy": "appVersion"
},
"updates": {
"url": "https://u.expo.dev/7a5b9f0b-c450-4c48-9e89-be9b6d6a2e98"
}
}
}
Binary file added example/ios-custom-view/assets/adaptive-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/ios-custom-view/assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/ios-custom-view/assets/splash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions example/ios-custom-view/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const path = require("path");
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: [
[
"module-resolver",
{
extensions: [".tsx", ".ts", ".js", ".json"],
alias: {
// For development, we want to alias the library to the source
"expo-share-intent": path.join(
__dirname,
"../..",
"src",
"index.ts",
),
},
},
],
],
};
};
22 changes: 22 additions & 0 deletions example/ios-custom-view/eas.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"cli": {
"version": ">= 7.6.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"channel": "development"
},
"preview": {
"distribution": "internal",
"channel": "preview"
},
"production": {
"channel": "production"
}
},
"submit": {
"production": {}
}
}
8 changes: 8 additions & 0 deletions example/ios-custom-view/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { registerRootComponent } from "expo";
import { addShareIntentCustomView } from "expo-share-intent";

import App from "./App";

addShareIntentCustomView({ logoSource: require("./assets/icon.png") });

registerRootComponent(App);
29 changes: 29 additions & 0 deletions example/ios-custom-view/metro.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("expo/metro-config");
const path = require("path");

const config = getDefaultConfig(__dirname);

// npm v7+ will install ../node_modules/react-native because of peerDependencies.
// To prevent the incompatible react-native bewtween ./node_modules/react-native and ../node_modules/react-native,
// excludes the one from the parent folder when bundling.
config.resolver.blockList = [
...Array.from(config.resolver.blockList ?? []),
new RegExp(path.resolve("../..", "node_modules", "react-native")),
];

config.resolver.nodeModulesPaths = [
path.resolve(__dirname, "./node_modules"),
path.resolve(__dirname, "../../node_modules"),
];

config.watchFolders = [path.resolve(__dirname, "../..")];

config.transformer.getTransformOptions = async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
});

module.exports = config;
49 changes: 49 additions & 0 deletions example/ios-custom-view/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"name": "expo-share-intent-example",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "expo start",
"android": "expo run:android",
"ios": "expo run:ios",
"web": "expo start --web",
"prebuild": "expo prebuild --no-install",
"clean": "yarn prebuild --clean",
"test": "CI=1 expo install --check",
"test:fix": "expo install --fix",
"doctor": "npx --yes expo-doctor@latest",
"lint": "eslint .",
"postinstall": "patch-package",
"open:ios": "open -a \"Xcode\" ios",
"open:android": "open -a \"Android Studio\" android"
},
"dependencies": {
"@expo/metro-runtime": "~3.2.3",
"expo": "~51.0.39",
"expo-dev-client": "~4.0.29",
"expo-splash-screen": "~0.27.7",
"expo-status-bar": "~1.12.1",
"expo-updates": "~0.25.26",
"patch-package": "^8.0.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.74.5",
"react-native-web": "~0.19.10"
},
"devDependencies": {
"@babel/core": "^7.24.0",
"@expo/cli": "^0.18.30",
"@types/react": "~18.2.79",
"babel-plugin-module-resolver": "^5.0.0",
"eslint": "^8.50.0",
"eslint-config-universe": "^12.0.0",
"prettier": "^3.0.3",
"typescript": "~5.3.3"
},
"private": true,
"expo": {
"autolinking": {
"nativeModulesDir": "../.."
}
}
}
14 changes: 14 additions & 0 deletions example/ios-custom-view/patches/xcode+3.0.1.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
diff --git a/node_modules/xcode/lib/pbxProject.js b/node_modules/xcode/lib/pbxProject.js
index 068548a..b478056 100644
--- a/node_modules/xcode/lib/pbxProject.js
+++ b/node_modules/xcode/lib/pbxProject.js
@@ -1678,8 +1678,7 @@ function correctForFrameworksPath(file, project) {

function correctForPath(file, project, group) {
var r_group_dir = new RegExp('^' + group + '[\\\\/]');
-
- if (project.pbxGroupByName(group).path)
+ if (project.pbxGroupByName(group)&&project.pbxGroupByName(group).path)
file.path = file.path.replace(r_group_dir, '');

return file;
10 changes: 10 additions & 0 deletions example/ios-custom-view/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
"paths": {
"expo-share-intent": ["../../src/index"],
"expo-share-intent/*": ["../../src/*"]
}
}
}
Loading

0 comments on commit 531d13e

Please sign in to comment.