config-plugins
config-plugins copied to clipboard
Snapchat SnapKit config plugin
Library
https://www.npmjs.com/package/@snapchat/snap-kit-react-native
Summary
A Snapchat SnapKit config plugin would be great! Would allow us to use Snapchat's React Native package and it's forgo its complex setup process. (https://docs.snap.com/snap-kit/creative-kit/Tutorials/react-native#step-2-update-your-androidmanifestxml-file)
I already managed to get a config plugin sort of working. Can't figure out how to do step 3 (Step 3: Define Paths in Your res/xml/filre_paths.xml File) within the config plugin
Any existing examples?
import {
AndroidConfig,
createRunOncePlugin,
IOSConfig,
withXcodeProject,
withAppBuildGradle,
ConfigPlugin,
withStringsXml,
withProjectBuildGradle,
withAndroidManifest,
} from "@expo/config-plugins";
import {
createGeneratedHeaderComment,
MergeResults,
mergeContents,
removeGeneratedContents,
} from "@expo/config-plugins/build/utils/generateCode";
import { ExpoConfig } from "expo/config";
const { addMetaDataItemToMainApplication, getMainApplicationOrThrow } = AndroidConfig.Manifest;
// Fork of config-plugins mergeContents, but appends the contents to the end of the file. Taken from https://github.com/expo/expo/blob/master/packages/expo-camera/plugin/src/withCamera.ts
function appendContents({
src,
newSrc,
tag,
comment,
}: {
src: string;
newSrc: string;
tag: string;
comment: string;
}): MergeResults {
const header = createGeneratedHeaderComment(newSrc, tag, comment);
if (!src.includes(header)) {
// Ensure the old generated contents are removed.
const sanitizedTarget = removeGeneratedContents(src, tag);
const contentsToAdd = [
// @something
header,
// contents
newSrc,
// @end
`${comment} @generated end ${tag}`,
].join("\n");
return {
contents: sanitizedTarget ?? src + contentsToAdd,
didMerge: true,
didClear: !!sanitizedTarget,
};
}
return { contents: src, didClear: false, didMerge: false };
}
const pkg = require("@snapchat/snap-kit-react-native/package.json");
const addSnapkitImport = (src: string): MergeResults => {
return appendContents({
tag: "expo-snapkit-import",
src,
newSrc: `allprojects { repositories { maven { url "https://storage.googleapis.com/snap-kit-build/maven" } } }`,
comment: "//",
});
};
const withSnapkitGradle: ConfigPlugin = (config) => {
return withProjectBuildGradle(config, (config) => {
if (config.modResults.language === "groovy") {
config.modResults.contents = addSnapkitImport(config.modResults.contents).contents;
} else {
throw new Error(
"Cannot add Snapkit maven gradle because the project build.gradle is not groovy"
);
}
return config;
});
};
async function addMetaDataToAndroidManifest(
config: Pick<ExpoConfig, "android">,
androidManifest: AndroidConfig.Manifest.AndroidManifest
): Promise<AndroidConfig.Manifest.AndroidManifest> {
const name = "com.snapchat.kit.sdk.clientId";
const value = "{{YOUR API KEY HERE}}";
const mainApplication = getMainApplicationOrThrow(androidManifest); // Get the <application /> tag and assert if it doesn't exist.
addMetaDataItemToMainApplication(
mainApplication,
name, // value for `android:name`
value // value for `android:value`
);
return androidManifest;
}
const withCustomMetaData: ConfigPlugin = (config) => {
return withAndroidManifest(config, async (config) => {
// Modifiers can be async, but try to keep them fast.
config.modResults = await addMetaDataToAndroidManifest(config, config.modResults);
return config;
});
};
function addProviderToAndroidManifest(androidManifest: AndroidConfig.Manifest.AndroidManifest) {
const app = AndroidConfig.Manifest.getMainApplicationOrThrow(
androidManifest
) as AndroidConfig.Manifest.ManifestApplication & { provider?: any[] };
// Add the provider if it doesn't exist.
if (!app.provider) {
app.provider = [];
}
// if the provider doesn't have the FileProvider, add it.
if (
!app.provider.some((p) => p.$["android:name"] === "android.support.v4.content.FileProvider")
) {
// <provider android:authorities="${applicationId}.fileprovider" android:name="android.support.v4.content.FileProvider" android:exported="false" android:grantUriPermissions="true"><meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/></provider>
app.provider.push({
$: {
"android:name": "android.support.v4.content.FileProvider",
"android:authorities": "${applicationId}.fileprovider",
"android:exported": "false",
"android:grantUriPermissions": "true",
},
"meta-data": {
$: {
"android:name": "android.support.FILE_PROVIDER_PATHS",
"android:resource": "@xml/file_paths",
},
},
});
}
return androidManifest;
}
function withProvider(config: ExpoConfig) {
return withAndroidManifest(config, async (config) => {
config.modResults = addProviderToAndroidManifest(config.modResults);
return config;
});
}
function addPackageToQuery(androidManifest: AndroidConfig.Manifest.AndroidManifest) {
// <package android:name="com.snapchat.android" />
const packageToAdd = {
package: {
$: {
"android:name": "com.snapchat.android",
},
},
};
// @ts-ignore since queries does exist but Expo's types don't have it.
const queries = androidManifest.manifest.queries;
if (!queries) {
// @ts-ignore since queries does exist but Expo's types don't have it.
androidManifest.manifest.queries = [...packageToAdd];
} else {
// @ts-ignore since queries does exist but Expo's types don't have it.
// TODO: this will break if there are other <package> tags in the queries.
androidManifest.manifest.queries[0].package = {
$: { ...packageToAdd.package.$ },
};
}
return androidManifest;
}
function withPackage(config: ExpoConfig) {
return withAndroidManifest(config, async (config) => {
config.modResults = addPackageToQuery(config.modResults);
return config;
});
}
const withSnapchatSdk: ConfigPlugin = (config) => {
return withPackage((withCustomMetaData(withSnapkitGradle(config))));
// skipping withProvider as filePath was giving me issues.
// return withPackage(withProvider(withCustomMetaData(withSnapkitGradle(config))));
};
export default createRunOncePlugin(withSnapchatSdk, pkg.name, pkg.version);
I faced some problem while request access to the Snapchat camera kit and I didn't receive any response from Snapchat company, so what can I do to get the licenses to access the Snapchat camera kit, how can I solve this problem?
That is unrelated please mention that in Snapchat’s repo @yingyingbangbagng
@ansh were you able to add it using the plugins? Stuck on the same step
Yes I was.
On Fri, Mar 24, 2023 at 7:31 AM, Ayush Singh < @.*** > wrote:
@ ansh ( https://github.com/ansh ) were you able to add it using the plugins? Stuck on the same step
— Reply to this email directly, view it on GitHub ( https://github.com/expo/config-plugins/issues/153#issuecomment-1482899870 ) , or unsubscribe ( https://github.com/notifications/unsubscribe-auth/AB6T25L7ZU6IYYI6I5X3JYLW5WV3RANCNFSM6AAAAAAS2HFI6Q ). You are receiving this because you were mentioned. Message ID: <expo/config-plugins/issues/153/1482899870 @ github. com>
@ansh Could you guide me? Stuck on the part where I have to modify file_paths.xml using the config functions provided by expo