Skip to content

Commit

Permalink
feat: ios preprocessing page (url metadata)
Browse files Browse the repository at this point in the history
  • Loading branch information
achorein committed Dec 15, 2024
1 parent 5797447 commit 132ccb4
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 52 deletions.
34 changes: 18 additions & 16 deletions README.md

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions example/basic/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ const WebUrlComponent = ({ shareIntent }: { shareIntent: ShareIntent }) => {
source={
shareIntent.meta?.["og:image"]
? { uri: shareIntent.meta?.["og:image"] }
: require("./assets/icon.png")
: undefined
}
style={[styles.icon, styles.gap, { borderRadius: 5 }]}
/>
<View style={{ flexShrink: 1, padding: 5 }}>
<Text style={[styles.gap]}>{shareIntent.meta?.title || ""}</Text>
<Text style={[styles.gap]}>
{shareIntent.meta?.title || "<NO TITLE>"}
</Text>
<Text style={styles.gap}>{shareIntent.webUrl}</Text>
</View>
</View>
Expand Down
4 changes: 1 addition & 3 deletions example/basic/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@
"NSExtensionActivationSupportsFileWithMaxCount": 1
},
"iosShareExtensionName": "ExpoShareIntent Example Extension",
"iosAppGroupIdentifier": "customgroup.expo.modules.exposhareintent.example",
"androidIntentFilters": ["text/*", "image/*", "video/*"],
"androidMultiIntentFilters": ["image/*"],
"disableIOS": false,
"disableAndroid": false
"preprocessorInjectJS": "metas['og\\:image'] = metas['og\\:image'] || document.querySelector('img#main-image')?.getAttribute('src') || document.querySelector('img[data-old-hires]')?.getAttribute('data-old-hires');"
}
],
["expo-updates"]
Expand Down
6 changes: 4 additions & 2 deletions example/expo-router/app/shareintent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ const WebUrlComponent = ({ shareIntent }: { shareIntent: ShareIntentType }) => {
source={
shareIntent.meta?.["og:image"]
? { uri: shareIntent.meta?.["og:image"] }
: require("../assets/icon.png")
: undefined
}
style={[styles.icon, styles.gap, { borderRadius: 5 }]}
/>
<View style={{ flexShrink: 1, padding: 5 }}>
<Text style={[styles.gap]}>{shareIntent.meta?.title || ""}</Text>
<Text style={[styles.gap]}>
{shareIntent.meta?.title || "<NO TITLE>"}
</Text>
<Text style={styles.gap}>{shareIntent.webUrl}</Text>
</View>
</View>
Expand Down
6 changes: 4 additions & 2 deletions example/react-navigation/app/ShareIntentScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ const WebUrlComponent = ({ shareIntent }: { shareIntent: ShareIntent }) => {
source={
shareIntent.meta?.["og:image"]
? { uri: shareIntent.meta?.["og:image"] }
: require("../assets/icon.png")
: undefined
}
style={[styles.icon, styles.gap, { borderRadius: 5 }]}
/>
<View style={{ flexShrink: 1, padding: 5 }}>
<Text style={[styles.gap]}>{shareIntent.meta?.title || ""}</Text>
<Text style={[styles.gap]}>
{shareIntent.meta?.title || "<NO TITLE>"}
</Text>
<Text style={styles.gap}>{shareIntent.webUrl}</Text>
</View>
</View>
Expand Down
23 changes: 4 additions & 19 deletions plugin/src/ios/writeIosShareExtensionFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export async function writeShareExtensionFiles(
platformProjectRoot,
parameters,
);
const preprocessorContent = getPreprocessorContent();
const preprocessorContent = getPreprocessorContent(parameters);
await fs.promises.writeFile(preprocessorFilePath, preprocessorContent);
}

Expand Down Expand Up @@ -241,7 +241,8 @@ export function getPreprocessorFilePath(
);
}

export function getPreprocessorContent() {
export function getPreprocessorContent(parameters: Parameters) {
const injection = parameters.preprocessorInjectJS || "";
return `class ShareExtensionPreprocessor {
run({ completionFunction }) {
// Extract meta tags and image sources from the document
Expand All @@ -260,23 +261,7 @@ export function getPreprocessorContent() {
}
}
if (!metas["og:image"]) {
const mainImage = document.querySelector("img#main-image");
if (mainImage) {
const src = mainImage.getAttribute("src");
if (src) {
metas["og:image"] = src;
}
}
const oldHiresImage = document.querySelector("img[data-old-hires]");
if (oldHiresImage) {
const oldHires = oldHiresImage.getAttribute("data-old-hires");
if (oldHires) {
metas["og:image"] = oldHires;
}
}
}
${injection}
// Call the completion function with the extracted data
completionFunction({
Expand Down
1 change: 1 addition & 0 deletions plugin/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type Parameters = {
androidIntentFilters?: ("text/*" | "image/*" | "video/*" | "*/*")[];
androidMultiIntentFilters?: ("image/*" | "video/*" | "*/*")[];
disableExperimental?: boolean;
preprocessorInjectJS?: string;
disableAndroid?: boolean;
disableIOS?: boolean;
};
5 changes: 3 additions & 2 deletions src/ExpoShareIntentModule.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ export type ShareIntentOptions = {
onResetShareIntent?: () => void;
};

export type ShareIntentMeta = Record<string, string> & {
export type ShareIntentMeta = Record<string, string | undefined> & {
title?: string;
};

/**
* Base type for what shared content is common between both platforms.
*/
interface BaseShareIntent {
meta?: ShareIntentMeta;
meta?: ShareIntentMeta | null;
text?: string | null;
}

Expand All @@ -74,6 +74,7 @@ export interface AndroidShareIntent extends BaseShareIntent {
*/
export interface IosShareIntent extends BaseShareIntent {
files?: IosShareIntentFile[];
weburls?: { url: string; meta: string }[];
type: "media" | "file" | "text" | "weburl";
}

Expand Down
24 changes: 18 additions & 6 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,33 @@ export const getShareExtensionKey = (options?: ShareIntentOptions) => {
// 3: "file",
// };

export function parseJson<T>(
value: string,
defaultValue: T | null = null,
): T | null {
try {
return JSON.parse(value) as T;
} catch (e) {
console.debug(e);
return defaultValue;
}
}

export const parseShareIntent = (
value: string | AndroidShareIntent,
options: ShareIntentOptions,
): ShareIntent => {
let result = SHAREINTENT_DEFAULTVALUE;
if (!value) return result;
let shareIntent;
let shareIntent: IosShareIntent | AndroidShareIntent | null;
// ios native module send a raw string of the json, try to parse it
if (typeof value === "string") {
shareIntent = JSON.parse(value) as IosShareIntent; // iOS
shareIntent = parseJson<IosShareIntent>(value); // iOS
} else {
shareIntent = value; // Android
}

if (shareIntent.text) {
if (shareIntent?.text) {
// Try to find the webURL in the SharedIntent text
const webUrl =
shareIntent.text.match(
Expand All @@ -86,13 +98,13 @@ export const parseShareIntent = (
title: shareIntent.meta?.title ?? undefined,
},
};
} else if (shareIntent.weburls?.length) {
const weburl = shareIntent.weburls[0];
} else if ((shareIntent as IosShareIntent)?.weburls?.length) {
const weburl = (shareIntent as IosShareIntent).weburls![0];
result = {
...SHAREINTENT_DEFAULTVALUE,
type: "weburl",
webUrl: weburl.url,
meta: JSON.parse(weburl.meta),
meta: parseJson<Record<string, string>>(weburl.meta, {}),
};
} else {
// Ensure we got a valid file. some array value are emply
Expand Down

0 comments on commit 132ccb4

Please sign in to comment.