@atlaskit/renderer
Version:
Renderer component
107 lines (101 loc) • 6.47 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.EditorMediaClientProvider = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = _interopRequireWildcard(require("react"));
var _mediaClientReact = require("@atlaskit/media-client-react");
var _providerFactory = require("@atlaskit/editor-common/provider-factory");
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
var EditorMediaClientProvider = exports.EditorMediaClientProvider = function EditorMediaClientProvider(_ref) {
var children = _ref.children,
ssr = _ref.ssr;
var _useState = (0, _react.useState)(function () {
return (0, _expValEquals.expValEquals)('platform_editor_media_reliability_enhancements', 'isEnabled', true) ? ssr === null || ssr === void 0 ? void 0 : ssr.config : undefined;
}),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
mediaClientConfig = _useState2[0],
setMediaClientConfig = _useState2[1];
var providerFactory = (0, _providerFactory.useProviderFactory)();
var mediaProvider = (0, _providerFactory.useProviderLayout)('mediaProvider');
/**
* Whether this renderer has its own media provider and should never inherit
* the mediaClient from a parent renderer's context.
*
* We use providerFactory.hasProvider() rather and checking the mediaProvider
* state value, because useProviderLayout subscribes via useLayoutEffect —
* meaning mediaProvider state is always undefined on the first render, even
* if the ProviderFactory already has a provider registered. This would cause
* shouldSkipContext to be false on the first render, incorrectly allowing the
* inner renderer to inherit the outer renderer's MediaClientContext (which
* carries the wrong media token for this page).
*
* hasProvider() is synchronous and correct from render 1, closing that window.
*/
var shouldSkipContext = (0, _expValEquals.expValEquals)('platform_editor_media_reliability_enhancements', 'isEnabled', true) ? Boolean((ssr === null || ssr === void 0 ? void 0 : ssr.config) || providerFactory.hasProvider('mediaProvider') || mediaProvider) : Boolean((ssr === null || ssr === void 0 ? void 0 : ssr.config) || mediaProvider);
var contextMediaClient = (0, _react.useContext)(_mediaClientReact.MediaClientContext);
// MediaClientProvider currently requires a mediaClientConfig
// And inserting the MediaClientProvider will cause a re-render
// We should use MediaClientProvider once it no longer requires a config
var mediaClient = (0, _react.useMemo)(function () {
return mediaClientConfig ? (0, _mediaClientReact.getMediaClient)(mediaClientConfig) : undefined;
}, [mediaClientConfig]);
// Consumers can override the mediaClient for renderer,
// by not providing both SSR config and mediaProvider,
// and provide a top level mediaClient context
// This is useful for testing and creating examples.
// When the experiment is enabled, use useEffect instead of useLayoutEffect because:
// - For the ssr.config branch: useState is already initialised with ssr.config, so this
// effect is a no-op on first render — the "before paint" guarantee is irrelevant.
// - For the mediaProvider branch: the actual work happens inside a Promise callback which
// resolves asynchronously, so it can never run before paint regardless of which hook
// schedules it — useLayoutEffect's guarantee is equally irrelevant here.
// The legacy path keeps useLayoutEffect to preserve existing behaviour when the experiment is off.
//
// The two hooks below are mutually exclusive — only one runs per render — so there is no
// actual chaining of state updates at runtime. The lint rule cannot statically prove this.
(0, _react.useEffect)(function () {
if (!(0, _expValEquals.expValEquals)('platform_editor_media_reliability_enhancements', 'isEnabled', true)) {
return;
}
if (ssr !== null && ssr !== void 0 && ssr.config) {
// eslint-disable-next-line @atlassian/perf-linting/no-chain-state-updates
setMediaClientConfig(ssr.config);
} else if (mediaProvider) {
var cancelled = false;
// Cancellation flag prevents setMediaClientConfig from being called after
// unmount or when mediaProvider changes mid-flight (stale promise fix).
// No .catch() is needed — the media provider is not expected to reject,
// and a catch handler would be a no-op anyway.
mediaProvider.then(function (provider) {
if (!cancelled) {
setMediaClientConfig(provider.viewMediaClientConfig);
}
});
return function () {
cancelled = true;
};
}
}, [mediaProvider, ssr === null || ssr === void 0 ? void 0 : ssr.config]);
// Legacy path (experiment off): keep useLayoutEffect to preserve existing behaviour.
// remove this when clean up platform_editor_media_reliability_enhancements
(0, _react.useLayoutEffect)(function () {
if ((0, _expValEquals.expValEquals)('platform_editor_media_reliability_enhancements', 'isEnabled', true)) {
return;
}
if (ssr !== null && ssr !== void 0 && ssr.config) {
setMediaClientConfig(ssr.config);
} else if (mediaProvider) {
mediaProvider.then(function (provider) {
setMediaClientConfig(provider.viewMediaClientConfig);
});
}
}, [mediaProvider, ssr === null || ssr === void 0 ? void 0 : ssr.config]);
return /*#__PURE__*/_react.default.createElement(_mediaClientReact.MediaClientContext.Provider, {
value: shouldSkipContext ? mediaClient : contextMediaClient
}, children);
};