Files
discord-decomp/modules/activities/native/EmbeddedActivityWebView.tsx
T
2026-11-01 12:12:55 +02:00

486 lines
19 KiB
TypeScript

// Metro module 10662 (f10663).
import _slicedToArray from "../../../_bundle/_slicedToArray";
import { useContext, useState, useMemo, useEffect, useRef, useCallback } from "react";
import { Linking } from "react-native";
import DeveloperActivityShelfStore from "../DeveloperActivityShelfStore";
import { ActivityPlatform, DISALLOWED_NAVIGATION_ERROR_CLOSE_ACTIVITY } from "../Constants";
import { ComponentActions, AnalyticEvents } from "../../../Constants";
import { createStyles } from "../../../design/components/Styles/native/createStyles";
import Logger from "../../debug/Logger";
import { isIOS } from "../../../utils/PlatformUtils";
import { WebViewContext } from "./WebViewContext";
import { v4 } from "../../../_bundle/Module514";
import * as _Module6759 from "../../../_bundle/Module6759";
import { getWebViewProxy } from "../../../_bundle/Module6759";
import { ComponentDispatch } from "../../../utils/ComponentDispatchUtils";
import useStableSafeAreaInsets_native, { getStableSafeAreaInsets } from "../../safe_area/useStableSafeAreaInsets.native";
import { getConstants } from "../../../utils/native/ClientInfoUtils";
import getIFrameSandboxAttributes from "../utils/getIFrameSandboxAttributes";
import createWebviewHtmlFile, { createInjectedJavascriptForIOS } from "./createWebviewHtmlFile";
import AnalyticsUtils from "../../../utils/AnalyticsUtils";
import { useStateFromStores } from "../../../_bundle/defaultAreStatesEqual";
import AlertActionCreators from "../../../actions/AlertActionCreators";
import { intl, t } from "../../../intl/index.native";
import { HTTP } from "../../../_bundle/sendRequest";
import escapeStringRegexp from "../../../_bundle/escapeStringRegexp";
import URLUtils from "../../../utils/URLUtils";
import getPostMessageJavaScript from "./getPostMessageJavaScript";
import WebViewPostMessageTransport from "../../rpc/native/server/transports/WebViewPostMessageTransport";
import usePrevious from "../../../hooks/usePrevious";
import ChannelRTCActionCreators from "../../../actions/ChannelRTCActionCreators";
import EmbeddedActivitiesNativeManager from "./EmbeddedActivitiesNativeManager";
import { HermesBuiltin } from "../../../_hermes/prelude";
function $mk118866($env) {
return (a0) => `^${escapeStringRegexp(a0).replace(/\\\*/g, ".*")}`;
}
let BaseActivityWebView, useStyles, c7159_15, c7159_16;
let env7159 = {};
const getSafeArea = function getSafeArea(a0, a1) {
return a0 != null ? a0.disable ? 0 : a0.override != null ? Math.max(0, a0.override) : a0.offset != null ? Math.max(0, a1 + a0.offset) : a1 : a1;
};
BaseActivityWebView = function BaseActivityWebView(props) {
let state2, state3, setState, memo, setState2, c18170_22, iFrameSandboxAttributes, iFrameUri, ref, stateFromStores, c18170_27, c18170_28, setState3, state4, setState4, c18170_32, ref2, callback;
const { hasFrameId: hasFrameId2, getOrCreateFrameId: getOrCreateFrameId2, releaseFrameId: releaseFrameId2, hasInvalidUrlError, setHasInvalidUrlError, hadInvalidUrlError, deepLinkQueryParams = {}, activityUrl, applicationId, queryParams, onActivityCrash, onLoadError, allowPopups, referrerPolicy, isPipOrGridMode, webViewKey, ignoreSilentHardwareSwitch = true, safeAreasConfig, channelId, guildId, activitySessionId } = props;
state2 = void 0;
state3 = void 0;
setState = void 0;
memo = void 0;
setState2 = void 0;
c18170_22 = void 0;
iFrameSandboxAttributes = void 0;
iFrameUri = void 0;
ref = void 0;
stateFromStores = void 0;
c18170_27 = void 0;
c18170_28 = void 0;
setState3 = void 0;
state4 = void 0;
setState4 = void 0;
c18170_32 = void 0;
ref2 = void 0;
callback = void 0;
const styles = useStyles();
const context = useContext(WebViewContext);
const [state] = useState(() => hasFrameId2());
state2 = _slicedToArray(useState(() => webViewKey != null ? getOrCreateFrameId2() : v4()), 1)[0];
[state3, setState] = useState(null);
memo = useMemo(() => webViewKey != null ? getWebViewProxy(webViewKey) : void 0, [webViewKey]);
let state5;
[state5, setState2] = useState(null);
useEffect(() => {
let r1 = state;
if (state) {
r1 = webViewKey != null;
}
if (!r1) {
ComponentDispatch.dispatch(ComponentActions.IFRAME_MOUNT, {
id: state2
});
}
}, [state, state2, webViewKey]);
useEffect(() => () => {
if (webViewKey == null) {
ComponentDispatch.dispatch(ComponentActions.IFRAME_UNMOUNT, {
id: state2
});
}
}, [webViewKey, state2]);
const stableSafeAreaInsets_native = useStableSafeAreaInsets_native();
c18170_22 = stableSafeAreaInsets_native;
const r89 = {
...queryParams,
...deepLinkQueryParams,
frame_id: state2,
platform: ActivityPlatform.MOBILE,
mobile_app_version: getConstants().Version
};
iFrameSandboxAttributes = getIFrameSandboxAttributes({
allowPopups
});
iFrameUri = `${activityUrl}?${new URLSearchParams(r89)}`;
ref = useRef(safeAreasConfig);
useEffect(() => {
let _loadHtml2 = function _loadHtml() {
const r9 = async () => {
let c31585_5;
c31585_5 = void 0;
const stableSafeAreaInsets = getStableSafeAreaInsets();
const current = ref.current;
const left3 = current?.left;
let left = stableSafeAreaInsets?.left;
if (left == null) {
left = 0;
}
const insets = {
left: getSafeArea(left3, left),
right: null,
top: null,
bottom: null
};
const right3 = current?.right;
let right = stableSafeAreaInsets?.right;
if (right == null) {
right = 0;
}
insets.right = getSafeArea(right3, right);
const top3 = current?.top;
let top = stableSafeAreaInsets?.top;
if (top == null) {
top = 0;
}
insets.top = getSafeArea(top3, top);
const bottom3 = current?.bottom;
let bottom = stableSafeAreaInsets?.bottom;
if (bottom == null) {
bottom = 0;
}
insets.bottom = getSafeArea(bottom3, bottom);
let c32018_0 = await createWebviewHtmlFile({
iFrameUri,
iFrameSandboxAttributes,
referrerPolicy,
insets,
messageForDisallowedNavigationError: c7159_16 ? void 0 : DISALLOWED_NAVIGATION_ERROR_CLOSE_ACTIVITY
});
if (c32018_0 != null) {
(0, setState2)(c32018_0);
} else {
(0, onLoadError)();
}
};
_loadHtml2 = r9;
return r9.apply(this, arguments);
};
(function loadHtml() {
return _loadHtml2.apply(this, arguments);
})();
}, [iFrameUri, iFrameSandboxAttributes, onLoadError, referrerPolicy]);
const callback2 = useCallback((a0) => {
c7159_15.warn(`activity WebView error for appId ${applicationId}. ${JSON.stringify(a0.nativeEvent)}`);
}, [applicationId]);
const callback3 = useCallback((a0) => {
c7159_15.warn(`activity WebView render process gone for appId ${applicationId}. ${JSON.stringify(a0.nativeEvent)}`);
}, [applicationId]);
const callback4 = useCallback(() => {
c7159_15.warn(`activity WebView content process terminated for appId ${applicationId}`);
AnalyticsUtils.track(AnalyticEvents.ACTIVITY_WEB_VIEW_CONTENT_PROCESS_TERMINATED, {
application_id: applicationId,
channel_id: channelId,
guild_id: guildId,
activity_session_id: activitySessionId
});
ComponentDispatch.dispatch(ComponentActions.IFRAME_UNMOUNT, {
id: state2
});
releaseFrameId2();
if (memo != null) {
memo.releaseWebView();
}
onActivityCrash();
}, [applicationId, channelId, guildId, activitySessionId, state2, releaseFrameId2, memo, onActivityCrash]);
stateFromStores = useStateFromStores([DeveloperActivityShelfStore], () => DeveloperActivityShelfStore.getUseActivityUrlOverride());
useEffect(() => {
try {
setState(new URL(iFrameUri));
} catch (r11) {
if (!stateFromStores) {
throw r11;
}
setHasInvalidUrlError(true);
}
}, [iFrameUri, stateFromStores, setHasInvalidUrlError]);
useEffect(() => {
if (hadInvalidUrlError ? !hadInvalidUrlError : hasInvalidUrlError) {
AlertActionCreators.show({
title: intl.string(t.PtobXW),
body: intl.string(t["55iAUT"]),
confirmText: intl.string(t.BddRzS)
});
}
}, [hadInvalidUrlError, hasInvalidUrlError]);
c18170_27 = null;
const r4 = state3 != null;
let uri = null;
if (r4) {
const r151 = c7159_16 ? `file://${state5}` : `${state3.origin}/${state2}/activity.html`;
c18170_27 = r151;
uri = r151;
}
c18170_28 = c7159_16;
let state6;
[state6, setState3] = useState(false);
[state4, setState4] = useState([]);
useEffect(() => {
if (c18170_28) {
let c26784_0, _fetchAndParseCSP2;
const parseCsp2 = function parseCsp(a0, a1) {
const r7 = a1.match(a0);
return r7 !== null && r7.length >= 2 ? r7[1].split(" ").filter((item) => !c26784_0.includes(item)) : [];
};
_fetchAndParseCSP2 = function _fetchAndParseCSP() {
const r9 = async () => {
let c31586_2;
let env32019;
c31586_2 = void 0;
const r9 = env32019 = {
$parent: env7159
};
let c31586_1 = r9;
env32019[0] = void 0;
env32019[1] = void 0;
env32019[2] = void 0;
const r31 = `https://${applicationId}.discordsays.com`;
env32019[0] = r31;
env32019[1] = (await HTTP.get({
url: `${r31}/.discord/csp`,
rejectWithError: false
})).headers["content-security-policy"];
const r63 = ["about:blank", "file://*", env32019[0]];
let c31586_0 = 3;
c31586_0 = HermesBuiltin.arraySpread(r63, parseCsp2(/frame-src (.*?);/, env32019[1]), c31586_0);
c31586_0 = HermesBuiltin.arraySpread(r63, parseCsp2(/child-src (.*?);/, env32019[1]), c31586_0);
env32019[2] = r63;
setState4(env32019[2].map($mk118866(env7159)));
(0, setState3)(true);
};
_fetchAndParseCSP2 = r9;
return r9.apply(this, arguments);
};
c26784_0 = ["'self'"];
(function fetchAndParseCSP() {
return _fetchAndParseCSP2.apply(this, arguments);
})();
}
}, [applicationId, c7159_16]);
const callback5 = useCallback((a0) => {
const mainDocumentURL = a0.mainDocumentURL;
if (c18170_27 != null && mainDocumentURL != null && mainDocumentURL !== c18170_27) {
Linking.openURL(a0.url);
return false;
}
for (const item of state4) {
if (!new RegExp(item).test(a0.url)) {
continue;
}
return true;
}
let r43 = DeveloperActivityShelfStore.getActivityUrlOverride();
if (r43 == null) {
r43 = "";
}
const r44 = URLUtils.toURLSafe(r43);
const r49 = URLUtils.toURLSafe(a0.url);
return r44 != null && r49 != null && r44.origin + r44.pathname === r49.origin + r49.pathname;
}, [uri, state4]);
const r3 = uri != null && state3 != null && state5 != null;
c18170_32 = r3;
ref2 = useRef(null);
callback = useCallback((a0) => {
const current = ref2.current;
if (current != null) {
current.injectJavaScript(getPostMessageJavaScript(a0));
}
}, []);
const r183 = [webViewKey, , ,];
const origin = state3?.origin;
L89: {
const r185 = (a0) => {
if (webViewKey == null) {
const r7 = JSON.parse(a0.nativeEvent.data);
if (typeof r7 === "object" ? state3?.origin != null : typeof r7 === "object") {
WebViewPostMessageTransport.handleMessage(r7, state3?.origin, callback);
}
}
};
r183[1] = origin;
r183[2] = callback;
const callback6 = useCallback(r185, r183);
useEffect(() => {
if (c18170_32 && memo != null) {
let _tryInjectJavaScript2 = function _tryInjectJavaScript() {
const r9 = async () => {
let left2, right2, top2, bottom2;
let c31587_7 = 0;
let c32020_0;
L40: {
try {
c32020_0 = void 0;
if (memo != null) {
const r18 = isPipOrGridMode ? {
top: 0,
bottom: 0,
left: 0,
right: 0
} : c18170_22;
const left3 = safeAreasConfig?.left;
const left4 = r18?.left;
left2 = left4;
if (left4 == null) {
left2 = 0;
}
const insets = {
left: getSafeArea(left3, left2),
right: null,
top: null,
bottom: null
};
const right3 = safeAreasConfig?.right;
const right4 = r18?.right;
right2 = right4;
if (right4 == null) {
right2 = 0;
}
insets.right = getSafeArea(right3, right2);
const top3 = safeAreasConfig?.top;
top2 = r18?.top;
if (top2 == null) {
top2 = 0;
}
insets.top = getSafeArea(top3, top2);
const bottom3 = safeAreasConfig?.bottom;
const bottom4 = r18?.bottom;
bottom2 = bottom4;
if (bottom4 == null) {
bottom2 = 0;
}
insets.bottom = getSafeArea(bottom3, bottom2);
const r58 = {
type: "safeAreaUpdateEvent",
data: {
insets
}
};
c32020_0 = r58;
c31587_7 = 1;
await memo.injectJavaScript(getPostMessageJavaScript(r58));
c31587_7 = 0;
break L40;
}
} catch ($e) {
let r7 = $e;
if (c31587_7 !== 0) {
while (true) {
try {
c31587_7 = 0;
if (ref2.current == null) {
break L40;
}
callback(getPostMessageJavaScript(c32020_0));
break L40;
} catch ($e) {
r7 = $e;
if (c31587_7 === 0) {
break;
}
}
}
}
throw r7;
}
return void 0;
}
};
_tryInjectJavaScript2 = r9;
return r9.apply(this, arguments);
};
(function tryInjectJavaScript() {
return _tryInjectJavaScript2.apply(this, arguments);
})();
}
}, [stableSafeAreaInsets_native, isPipOrGridMode, r3, memo, callback, safeAreasConfig]);
if (uri != null && state3 != null) {
if (c7159_16 && state6 === false) {
break L89;
}
const left3 = safeAreasConfig?.left;
let r194 = stableSafeAreaInsets_native?.left;
if (r194 == null) {
r194 = 0;
}
const left4 = left3 != null ? left3.disable ? 0 : left3.override != null ? Math.max(0, left3.override) : left3.offset != null ? Math.max(0, r194 + left3.offset) : r194 : r194;
const right3 = safeAreasConfig?.right;
let r213 = stableSafeAreaInsets_native?.right;
if (r213 == null) {
r213 = 0;
}
const right4 = right3 != null ? right3.disable ? 0 : right3.override != null ? Math.max(0, right3.override) : right3.offset != null ? Math.max(0, r213 + right3.offset) : r213 : r213;
const top3 = safeAreasConfig?.top;
let r231 = stableSafeAreaInsets_native?.top;
if (r231 == null) {
r231 = 0;
}
const top4 = top3 != null ? top3.disable ? 0 : top3.override != null ? Math.max(0, top3.override) : top3.offset != null ? Math.max(0, r231 + top3.offset) : r231 : r231;
const bottom3 = safeAreasConfig?.bottom;
let r249 = stableSafeAreaInsets_native?.bottom;
if (r249 == null) {
r249 = 0;
}
const bottom4 = bottom3 != null ? bottom3.disable ? 0 : bottom3.override != null ? Math.max(0, bottom3.override) : bottom3.offset != null ? Math.max(0, r249 + bottom3.offset) : r249 : r249;
const injectedJavaScript = c7159_16 ? createInjectedJavascriptForIOS({
left: left4,
right: right4,
top: top4,
bottom: bottom4
}) : void 0;
return state5 == null ? null : <_Module6759.WebView style={styles.webView} ref={ref2} source={{
uri
}} androidAssetLoaderConfig={{
domain: state3.port === "" ? state3.host : `${state3.hostname}:${state3.port}`,
httpAllowed: state3.protocol === "http:",
pathHandlers: [{
type: "internal",
path: `/${state2}/`,
directory: state5.substring(0, state5.lastIndexOf("/"))
}]
}} originWhitelist={["*"]} overScrollMode="never" scrollEnabled={false} cacheEnabled onError={callback2} onContentProcessDidTerminate={callback4} onRenderProcessGone={callback3} webViewKey={webViewKey} temporaryParentNodeTag={context} messagingWithWebViewKeyEnabled={webViewKey != null} onMessage={callback6} allowFileAccess={c7159_16} injectedJavaScript={injectedJavaScript} injectedJavaScriptForMainFrameOnly={false} onShouldStartLoadWithRequest={c7159_16 ? callback5 : void 0} mediaPlaybackRequiresUserAction={false} ignoreSilentHardwareSwitch={ignoreSilentHardwareSwitch} allowsInlineMediaPlayback minimumFontSize={1} bounces={false} allowsProtectedMedia />;
}
}
return null;
};
useStyles = createStyles({
webView: {
backgroundColor: "transparent"
}
});
c7159_15 = new Logger("EmbeddedActivityWebView");
c7159_16 = isIOS();
export default function EmbeddedActivityWebView(props) {
const { channelId: channelId2, currentEmbeddedActivity, applicationId: applicationId2, ...props2 } = props;
const [state, setHasInvalidUrlError2] = useState(false);
const previous = usePrevious(state);
const state5 = state;
let c18171_4 = previous;
const deepLinkQueryParams = {};
if (currentEmbeddedActivity != null) {
if (currentEmbeddedActivity.customId != null) {
deepLinkQueryParams.custom_id = currentEmbeddedActivity.customId;
}
if (currentEmbeddedActivity.referrerId != null) {
deepLinkQueryParams.referrer_id = currentEmbeddedActivity.referrerId;
}
}
useEffect(() => {
if (c18171_4 ? !c18171_4 : state5) {
if (channelId2 != null) {
ChannelRTCActionCreators.selectParticipant(channelId2, null);
}
EmbeddedActivitiesNativeManager.leaveActivity({
location: currentEmbeddedActivity?.location,
applicationId: applicationId2,
showFeedback: false
});
}
}, [state5, previous, channelId2, applicationId2, currentEmbeddedActivity]);
return <BaseActivityWebView hasFrameId={() => EmbeddedActivitiesNativeManager.hasFrameId()} getOrCreateFrameId={() => EmbeddedActivitiesNativeManager.getOrCreateFrameId()} releaseFrameId={() => EmbeddedActivitiesNativeManager.releaseFrameId()} hasInvalidUrlError={state5} setHasInvalidUrlError={setHasInvalidUrlError2} hadInvalidUrlError={previous} deepLinkQueryParams={deepLinkQueryParams} applicationId={applicationId2} channelId={channelId2} {...props2} />;
};
export { BaseActivityWebView };
export function useHasInvalidUrlErrorState() {
const r5 = _slicedToArray(useState(false), 2);
const hasInvalidUrlError2 = r5[0];
return {
hasInvalidUrlError: hasInvalidUrlError2,
setHasInvalidUrlError: r5[1],
hadInvalidUrlError: usePrevious(hasInvalidUrlError2)
};
}