@select-org/select-post-builder 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +51 -25
- package/dist/post-builder.cjs.js +576 -352
- package/dist/post-builder.js +577 -353
- package/package.json +1 -1
package/dist/post-builder.cjs.js
CHANGED
|
@@ -2083,19 +2083,12 @@ validators$1.transitional = function transitional(validator2, version, message)
|
|
|
2083
2083
|
}
|
|
2084
2084
|
if (version && !deprecatedWarnings[opt]) {
|
|
2085
2085
|
deprecatedWarnings[opt] = true;
|
|
2086
|
-
console.warn(
|
|
2087
|
-
formatMessage(
|
|
2088
|
-
opt,
|
|
2089
|
-
" has been deprecated since v" + version + " and will be removed in the near future"
|
|
2090
|
-
)
|
|
2091
|
-
);
|
|
2092
2086
|
}
|
|
2093
2087
|
return validator2 ? validator2(value, opt, opts) : true;
|
|
2094
2088
|
};
|
|
2095
2089
|
};
|
|
2096
2090
|
validators$1.spelling = function spelling(correctSpelling) {
|
|
2097
2091
|
return (value, opt) => {
|
|
2098
|
-
console.warn(`${opt} is likely a misspelling of ${correctSpelling}`);
|
|
2099
2092
|
return true;
|
|
2100
2093
|
};
|
|
2101
2094
|
};
|
|
@@ -3954,7 +3947,6 @@ const Toaster$1 = /* @__PURE__ */ React__namespace.default.forwardRef(function T
|
|
|
3954
3947
|
setActualTheme("light");
|
|
3955
3948
|
}
|
|
3956
3949
|
} catch (e) {
|
|
3957
|
-
console.error(e);
|
|
3958
3950
|
}
|
|
3959
3951
|
});
|
|
3960
3952
|
}
|
|
@@ -4622,46 +4614,6 @@ const useAnalyticsLogEvent = () => {
|
|
|
4622
4614
|
const { logEvent } = usePostBuilder();
|
|
4623
4615
|
return logEvent;
|
|
4624
4616
|
};
|
|
4625
|
-
const PostBuilderProvider = ({
|
|
4626
|
-
children,
|
|
4627
|
-
apiBaseURL,
|
|
4628
|
-
authToken,
|
|
4629
|
-
toI18N,
|
|
4630
|
-
i18nKeys,
|
|
4631
|
-
logEvent
|
|
4632
|
-
}) => {
|
|
4633
|
-
const t = React.useCallback(
|
|
4634
|
-
(key, fallback) => {
|
|
4635
|
-
const message = toI18N(i18nKeys[key]);
|
|
4636
|
-
if (message) return message;
|
|
4637
|
-
return fallback || key;
|
|
4638
|
-
},
|
|
4639
|
-
[toI18N, i18nKeys]
|
|
4640
|
-
);
|
|
4641
|
-
const api = React.useMemo(() => {
|
|
4642
|
-
const core2 = new CoreApi(apiBaseURL.core, authToken, toI18N);
|
|
4643
|
-
const mfs = new MFSApi(apiBaseURL.mfs, authToken, toI18N);
|
|
4644
|
-
const fileStore = new FilestoreApi(apiBaseURL.fileStore, authToken, toI18N);
|
|
4645
|
-
core2.initApi();
|
|
4646
|
-
mfs.initApi();
|
|
4647
|
-
fileStore.initApi();
|
|
4648
|
-
return {
|
|
4649
|
-
core: core2,
|
|
4650
|
-
mfs,
|
|
4651
|
-
fileStore
|
|
4652
|
-
};
|
|
4653
|
-
}, [authToken, apiBaseURL, toI18N]);
|
|
4654
|
-
const value = React.useMemo(() => {
|
|
4655
|
-
return {
|
|
4656
|
-
authToken,
|
|
4657
|
-
t,
|
|
4658
|
-
i18nKeys,
|
|
4659
|
-
api,
|
|
4660
|
-
logEvent
|
|
4661
|
-
};
|
|
4662
|
-
}, [authToken, t, i18nKeys, api, logEvent]);
|
|
4663
|
-
return /* @__PURE__ */ jsxRuntime.jsx(PostBuilderContext.Provider, { value, children });
|
|
4664
|
-
};
|
|
4665
4617
|
function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {
|
|
4666
4618
|
return function handleEvent(event) {
|
|
4667
4619
|
originalEventHandler?.(event);
|
|
@@ -5005,9 +4957,6 @@ function useControllableState({
|
|
|
5005
4957
|
if (wasControlled !== isControlled) {
|
|
5006
4958
|
const from = wasControlled ? "controlled" : "uncontrolled";
|
|
5007
4959
|
const to = isControlled ? "controlled" : "uncontrolled";
|
|
5008
|
-
console.warn(
|
|
5009
|
-
`${caller} is changing from ${from} to ${to}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`
|
|
5010
|
-
);
|
|
5011
4960
|
}
|
|
5012
4961
|
isControlledRef.current = isControlled;
|
|
5013
4962
|
}, [isControlled, caller]);
|
|
@@ -8612,7 +8561,7 @@ const EditorTypeTabs = ({ editorTab, onSwitchEditorTab }) => {
|
|
|
8612
8561
|
const { trackTabSwitch } = usePostBuilderAnalytics();
|
|
8613
8562
|
const handleSwitchTab = (newTab) => {
|
|
8614
8563
|
const oldTab = editorTab;
|
|
8615
|
-
trackTabSwitch(oldTab, newTab);
|
|
8564
|
+
trackTabSwitch({ oldTab, newTab });
|
|
8616
8565
|
onSwitchEditorTab(newTab);
|
|
8617
8566
|
};
|
|
8618
8567
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -11334,7 +11283,6 @@ var correctTargets = function(parent2, targets) {
|
|
|
11334
11283
|
if (correctedTarget && parent2.contains(correctedTarget)) {
|
|
11335
11284
|
return correctedTarget;
|
|
11336
11285
|
}
|
|
11337
|
-
console.error("aria-hidden", target, "in not contained inside", parent2, ". Doing nothing");
|
|
11338
11286
|
return null;
|
|
11339
11287
|
}).filter(function(x2) {
|
|
11340
11288
|
return Boolean(x2);
|
|
@@ -11383,7 +11331,6 @@ var applyAttributeToOthers = function(originalTarget, parentNode, markerName, co
|
|
|
11383
11331
|
node.setAttribute(controlAttribute, "true");
|
|
11384
11332
|
}
|
|
11385
11333
|
} catch (e) {
|
|
11386
|
-
console.error("aria-hidden: cannot operate on ", node, e);
|
|
11387
11334
|
}
|
|
11388
11335
|
}
|
|
11389
11336
|
});
|
|
@@ -14021,15 +13968,11 @@ function requireUseSyncExternalStoreShim_development() {
|
|
|
14021
13968
|
return x2 === y && (0 !== x2 || 1 / x2 === 1 / y) || x2 !== x2 && y !== y;
|
|
14022
13969
|
}
|
|
14023
13970
|
function useSyncExternalStore$2(subscribe2, getSnapshot) {
|
|
14024
|
-
didWarnOld18Alpha || void 0 === React2.startTransition || (didWarnOld18Alpha = true,
|
|
14025
|
-
"You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release."
|
|
14026
|
-
));
|
|
13971
|
+
didWarnOld18Alpha || void 0 === React2.startTransition || (didWarnOld18Alpha = true, void 0);
|
|
14027
13972
|
var value = getSnapshot();
|
|
14028
13973
|
if (!didWarnUncachedGetSnapshot) {
|
|
14029
13974
|
var cachedValue = getSnapshot();
|
|
14030
|
-
objectIs(value, cachedValue) || (
|
|
14031
|
-
"The result of getSnapshot should be cached to avoid an infinite loop"
|
|
14032
|
-
), didWarnUncachedGetSnapshot = true);
|
|
13975
|
+
objectIs(value, cachedValue) || (void 0, didWarnUncachedGetSnapshot = true);
|
|
14033
13976
|
}
|
|
14034
13977
|
cachedValue = useState({
|
|
14035
13978
|
inst: { value, getSnapshot }
|
|
@@ -14261,9 +14204,6 @@ const GroupSelector = ({ store }) => {
|
|
|
14261
14204
|
setGroups(response.entries ?? []);
|
|
14262
14205
|
}
|
|
14263
14206
|
} catch (error) {
|
|
14264
|
-
if (!cancelled) {
|
|
14265
|
-
console.error("Failed to fetch groups:", error);
|
|
14266
|
-
}
|
|
14267
14207
|
} finally {
|
|
14268
14208
|
if (!cancelled) {
|
|
14269
14209
|
setIsLoading(false);
|
|
@@ -14912,7 +14852,7 @@ const ToolbarButton = React.forwardRef(
|
|
|
14912
14852
|
const { trackFeature } = usePostBuilderAnalytics();
|
|
14913
14853
|
const handleClick = (e) => {
|
|
14914
14854
|
onClick?.(e);
|
|
14915
|
-
if (id) trackFeature(id);
|
|
14855
|
+
if (id) trackFeature({ featureName: id });
|
|
14916
14856
|
if (!editor) return;
|
|
14917
14857
|
requestAnimationFrame(editor?.chain()?.focus);
|
|
14918
14858
|
};
|
|
@@ -15216,7 +15156,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
|
|
|
15216
15156
|
React__namespace.useEffect(() => {
|
|
15217
15157
|
if (titleId) {
|
|
15218
15158
|
const hasTitle = document.getElementById(titleId);
|
|
15219
|
-
if (!hasTitle)
|
|
15159
|
+
if (!hasTitle) ;
|
|
15220
15160
|
}
|
|
15221
15161
|
}, [MESSAGE, titleId]);
|
|
15222
15162
|
return null;
|
|
@@ -15229,7 +15169,7 @@ var DescriptionWarning = ({ contentRef, descriptionId }) => {
|
|
|
15229
15169
|
const describedById = contentRef.current?.getAttribute("aria-describedby");
|
|
15230
15170
|
if (descriptionId && describedById) {
|
|
15231
15171
|
const hasDescription = document.getElementById(descriptionId);
|
|
15232
|
-
if (!hasDescription)
|
|
15172
|
+
if (!hasDescription) ;
|
|
15233
15173
|
}
|
|
15234
15174
|
}, [MESSAGE, contentRef, descriptionId]);
|
|
15235
15175
|
return null;
|
|
@@ -15615,7 +15555,6 @@ const InputGroupText = React.forwardRef(
|
|
|
15615
15555
|
InputGroupText.displayName = "InputGroupText";
|
|
15616
15556
|
const InputGroupInput = React.forwardRef(
|
|
15617
15557
|
({ className, ref: legacyRef, ...props }, ref) => {
|
|
15618
|
-
console.log({ legacyRef });
|
|
15619
15558
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15620
15559
|
Input,
|
|
15621
15560
|
{
|
|
@@ -16236,7 +16175,6 @@ const resolveUrlType = async (url) => {
|
|
|
16236
16175
|
if (mime?.startsWith("video/")) return { type: MediaNodeTypes.Video, src: url };
|
|
16237
16176
|
if (mime?.startsWith("audio/")) return { type: MediaNodeTypes.Audio, src: url };
|
|
16238
16177
|
} catch (error) {
|
|
16239
|
-
console.warn("HEAD request failed, falling back to mime detection:", error);
|
|
16240
16178
|
}
|
|
16241
16179
|
const ext = url.split(".").pop()?.toLowerCase();
|
|
16242
16180
|
if (ext) {
|
|
@@ -16375,11 +16313,9 @@ const LinkDecoratorModal = ({
|
|
|
16375
16313
|
setIsValid(isValid2);
|
|
16376
16314
|
};
|
|
16377
16315
|
const handleInsertLink = (link2, text22, uid2) => {
|
|
16378
|
-
console.log("HANDLE INSERT LINK::", { link: link2, text: text22 });
|
|
16379
16316
|
setIsLoading(true);
|
|
16380
16317
|
let metadata;
|
|
16381
|
-
core2?.resolveUrl(link2)?.then((res) => metadata = res)?.catch((err) =>
|
|
16382
|
-
console.log({ metadata });
|
|
16318
|
+
core2?.resolveUrl(link2)?.then((res) => metadata = res)?.catch((err) => void 0)?.finally(() => {
|
|
16383
16319
|
const previewPayload = convertLinkMetaToPreviewItem(metadata);
|
|
16384
16320
|
setIsLoading(false);
|
|
16385
16321
|
onInsertLink(link2, text22, uid2, previewPayload);
|
|
@@ -16391,12 +16327,10 @@ const LinkDecoratorModal = ({
|
|
|
16391
16327
|
e.preventDefault();
|
|
16392
16328
|
const isTextInput = textInputRef.current === e.target;
|
|
16393
16329
|
if (isTextInput || hideTextInput) return handleInsertLink(link, text2, uid ?? void 0);
|
|
16394
|
-
console.log("Enter", isTextInput);
|
|
16395
16330
|
textInputRef?.current?.focus();
|
|
16396
16331
|
}
|
|
16397
16332
|
};
|
|
16398
16333
|
React.useEffect(() => {
|
|
16399
|
-
console.log({ defaultValues });
|
|
16400
16334
|
if (!defaultValues?.link) return;
|
|
16401
16335
|
const isValid2 = isValidUrl(defaultValues?.link);
|
|
16402
16336
|
setIsValid(isValid2);
|
|
@@ -16405,7 +16339,6 @@ const LinkDecoratorModal = ({
|
|
|
16405
16339
|
setLink(defaultValues?.link ?? "");
|
|
16406
16340
|
setText(defaultValues?.text || "");
|
|
16407
16341
|
}, [defaultValues]);
|
|
16408
|
-
console.log("TEXT INSIDE LINK DECORATOR::", { isValid, text: text2 });
|
|
16409
16342
|
return /* @__PURE__ */ jsxRuntime.jsxs(Dialog, { open, onOpenChange: handleOpenChange, children: [
|
|
16410
16343
|
children ? /* @__PURE__ */ jsxRuntime.jsx(DialogTrigger, { asChild: true, children }) : null,
|
|
16411
16344
|
/* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "-translate-1/2", children: [
|
|
@@ -16590,10 +16523,8 @@ function parseThreshold(scrollThreshold) {
|
|
|
16590
16523
|
value: parseFloat(scrollThreshold)
|
|
16591
16524
|
};
|
|
16592
16525
|
}
|
|
16593
|
-
console.warn('scrollThreshold format is invalid. Valid formats: "120px", "50%"...');
|
|
16594
16526
|
return defaultThreshold;
|
|
16595
16527
|
}
|
|
16596
|
-
console.warn("scrollThreshold should be string or number");
|
|
16597
16528
|
return defaultThreshold;
|
|
16598
16529
|
}
|
|
16599
16530
|
var InfiniteScroll = (
|
|
@@ -16615,7 +16546,6 @@ var InfiniteScroll = (
|
|
|
16615
16546
|
return document.getElementById(_this.props.scrollableTarget);
|
|
16616
16547
|
}
|
|
16617
16548
|
if (_this.props.scrollableTarget === null) {
|
|
16618
|
-
console.warn("You are trying to pass scrollableTarget but it is null. This might\n happen because the element may not have been added to DOM yet.\n See https://github.com/ankeetmaini/react-infinite-scroll-component/issues/59 for more info.\n ");
|
|
16619
16549
|
}
|
|
16620
16550
|
return null;
|
|
16621
16551
|
};
|
|
@@ -16860,7 +16790,6 @@ function useMediaSearch(type) {
|
|
|
16860
16790
|
setItems((prev) => reset2 ? data : [...prev, ...data]);
|
|
16861
16791
|
}
|
|
16862
16792
|
} catch (error) {
|
|
16863
|
-
console.error("Error fetching images:", error);
|
|
16864
16793
|
pagination.setHasMore(false);
|
|
16865
16794
|
} finally {
|
|
16866
16795
|
pagination.setLoading(false);
|
|
@@ -16879,7 +16808,6 @@ function useMediaSearch(type) {
|
|
|
16879
16808
|
setItems((prev) => reset2 ? data : [...prev, ...data]);
|
|
16880
16809
|
}
|
|
16881
16810
|
} catch (error) {
|
|
16882
|
-
console.error("Error fetching gifs:", error);
|
|
16883
16811
|
pagination.setHasMore(false);
|
|
16884
16812
|
} finally {
|
|
16885
16813
|
pagination.setLoading(false);
|
|
@@ -18454,8 +18382,8 @@ function ImageSearchModal({
|
|
|
18454
18382
|
setSearchQuery("");
|
|
18455
18383
|
return;
|
|
18456
18384
|
}
|
|
18457
|
-
gifSearch.fetch(withInitialQuery).catch((err) =>
|
|
18458
|
-
imageSearch.fetch(withInitialQuery).catch((err) =>
|
|
18385
|
+
gifSearch.fetch(withInitialQuery).catch((err) => void 0);
|
|
18386
|
+
imageSearch.fetch(withInitialQuery).catch((err) => void 0);
|
|
18459
18387
|
};
|
|
18460
18388
|
const debouncedSearch = React.useMemo(
|
|
18461
18389
|
() => debounce$2(async (query) => {
|
|
@@ -18473,7 +18401,7 @@ function ImageSearchModal({
|
|
|
18473
18401
|
const handleSearch = React.useCallback(
|
|
18474
18402
|
(query) => {
|
|
18475
18403
|
setSearchQuery(query);
|
|
18476
|
-
debouncedSearch(query)?.catch((err) =>
|
|
18404
|
+
debouncedSearch(query)?.catch((err) => void 0);
|
|
18477
18405
|
},
|
|
18478
18406
|
[debouncedSearch]
|
|
18479
18407
|
);
|
|
@@ -20427,7 +20355,9 @@ const Toolbar = ({
|
|
|
20427
20355
|
};
|
|
20428
20356
|
const handleImageClick = (imageUrl, searchFrom) => {
|
|
20429
20357
|
if (searchFrom) {
|
|
20430
|
-
trackFeature(
|
|
20358
|
+
trackFeature({
|
|
20359
|
+
featureName: searchFrom === ImageSearchFrom.Gif ? "gif_search" : "image_search"
|
|
20360
|
+
});
|
|
20431
20361
|
}
|
|
20432
20362
|
editor?.commands.insertMediaWithUpload({
|
|
20433
20363
|
source: imageUrl,
|
|
@@ -20840,10 +20770,82 @@ const Toolbar = ({
|
|
|
20840
20770
|
] });
|
|
20841
20771
|
};
|
|
20842
20772
|
const VerticalSeparator = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-3 w-px bg-border" });
|
|
20773
|
+
var PostBuilderEvents = /* @__PURE__ */ ((PostBuilderEvents2) => {
|
|
20774
|
+
PostBuilderEvents2["POST_PUBLISH_ATTEMPTED"] = "select:post_publish_attempted";
|
|
20775
|
+
PostBuilderEvents2["POST_PUBLISH_SUCCESSFUL"] = "select:post_publish_success";
|
|
20776
|
+
PostBuilderEvents2["POST_PUBLISH_FAILED"] = "select:post_publish_failed";
|
|
20777
|
+
return PostBuilderEvents2;
|
|
20778
|
+
})(PostBuilderEvents || {});
|
|
20779
|
+
const useHostAnalyticsBridge = () => {
|
|
20780
|
+
const analytics = usePostBuilderAnalytics();
|
|
20781
|
+
const sessionIdRef = React.useRef(null);
|
|
20782
|
+
const processedRequestIds = React.useRef(/* @__PURE__ */ new Set());
|
|
20783
|
+
React.useEffect(() => {
|
|
20784
|
+
const onPublishSuccess = (e) => {
|
|
20785
|
+
const { postId, postType, groupId, failureReason } = e.detail;
|
|
20786
|
+
if (!postId || processedRequestIds.current.has(postId)) return;
|
|
20787
|
+
processedRequestIds.current.add(postId);
|
|
20788
|
+
analytics.trackPublish({
|
|
20789
|
+
sessionId: sessionIdRef.current ?? analytics.currentSessionId,
|
|
20790
|
+
status: "success",
|
|
20791
|
+
postId,
|
|
20792
|
+
groupId,
|
|
20793
|
+
postType,
|
|
20794
|
+
failureReason
|
|
20795
|
+
});
|
|
20796
|
+
sessionIdRef.current = null;
|
|
20797
|
+
};
|
|
20798
|
+
const onPublishFailed = (e) => {
|
|
20799
|
+
const { postId, postType, groupId, failureReason } = e.detail;
|
|
20800
|
+
if (!postId || processedRequestIds.current.has(postId)) return;
|
|
20801
|
+
processedRequestIds.current.add(postId);
|
|
20802
|
+
analytics.trackPublish({
|
|
20803
|
+
sessionId: sessionIdRef.current ?? analytics.currentSessionId,
|
|
20804
|
+
status: "failed",
|
|
20805
|
+
postId,
|
|
20806
|
+
groupId,
|
|
20807
|
+
postType,
|
|
20808
|
+
failureReason
|
|
20809
|
+
});
|
|
20810
|
+
sessionIdRef.current = null;
|
|
20811
|
+
};
|
|
20812
|
+
const lockSession = () => {
|
|
20813
|
+
if (!sessionIdRef.current) {
|
|
20814
|
+
sessionIdRef.current = analytics.currentSessionId;
|
|
20815
|
+
}
|
|
20816
|
+
};
|
|
20817
|
+
window.addEventListener(
|
|
20818
|
+
PostBuilderEvents.POST_PUBLISH_SUCCESSFUL,
|
|
20819
|
+
onPublishSuccess
|
|
20820
|
+
);
|
|
20821
|
+
window.addEventListener(
|
|
20822
|
+
PostBuilderEvents.POST_PUBLISH_FAILED,
|
|
20823
|
+
onPublishFailed
|
|
20824
|
+
);
|
|
20825
|
+
const handlePublishAttempt = () => lockSession();
|
|
20826
|
+
window.addEventListener(
|
|
20827
|
+
PostBuilderEvents.POST_PUBLISH_ATTEMPTED,
|
|
20828
|
+
handlePublishAttempt
|
|
20829
|
+
);
|
|
20830
|
+
return () => {
|
|
20831
|
+
window.removeEventListener(
|
|
20832
|
+
PostBuilderEvents.POST_PUBLISH_SUCCESSFUL,
|
|
20833
|
+
onPublishSuccess
|
|
20834
|
+
);
|
|
20835
|
+
window.removeEventListener(
|
|
20836
|
+
PostBuilderEvents.POST_PUBLISH_FAILED,
|
|
20837
|
+
onPublishFailed
|
|
20838
|
+
);
|
|
20839
|
+
window.removeEventListener(
|
|
20840
|
+
PostBuilderEvents.POST_PUBLISH_ATTEMPTED,
|
|
20841
|
+
handlePublishAttempt
|
|
20842
|
+
);
|
|
20843
|
+
};
|
|
20844
|
+
}, [analytics]);
|
|
20845
|
+
};
|
|
20843
20846
|
const usePersistence = () => {
|
|
20844
20847
|
const saveCurrentTabContent = (editorType, editor) => {
|
|
20845
|
-
if (typeof window === "undefined" || typeof localStorage === "undefined" || !editor
|
|
20846
|
-
return;
|
|
20848
|
+
if (typeof window === "undefined" || typeof localStorage === "undefined" || !editor) return;
|
|
20847
20849
|
const json = editor?.getJSON();
|
|
20848
20850
|
const filteredJson = filterNodes(json, (node) => !node?.attrs?.uploading);
|
|
20849
20851
|
if (filteredJson) {
|
|
@@ -21096,11 +21098,9 @@ var Progress$1 = React__namespace.forwardRef(
|
|
|
21096
21098
|
...progressProps
|
|
21097
21099
|
} = props;
|
|
21098
21100
|
if ((maxProp || maxProp === 0) && !isValidMaxNumber(maxProp)) {
|
|
21099
|
-
console.error(getInvalidMaxError(`${maxProp}`, "Progress"));
|
|
21100
21101
|
}
|
|
21101
21102
|
const max2 = isValidMaxNumber(maxProp) ? maxProp : DEFAULT_MAX;
|
|
21102
21103
|
if (valueProp !== null && !isValidValueNumber(valueProp, max2)) {
|
|
21103
|
-
console.error(getInvalidValueError(`${valueProp}`, "Progress"));
|
|
21104
21104
|
}
|
|
21105
21105
|
const value = isValidValueNumber(valueProp, max2) ? valueProp : null;
|
|
21106
21106
|
const valueLabel = isNumber(value) ? getValueLabel(value, max2) : void 0;
|
|
@@ -21420,13 +21420,7 @@ const createUpdateMarkByUidCommand = (markName) => {
|
|
|
21420
21420
|
state: state2,
|
|
21421
21421
|
dispatch
|
|
21422
21422
|
}) => {
|
|
21423
|
-
console.log("=== UPDATE MARK COMMAND START ===");
|
|
21424
|
-
console.log("markName:", markName);
|
|
21425
|
-
console.log("uid:", uid);
|
|
21426
|
-
console.log("attrs:", attrs);
|
|
21427
|
-
console.log("state.doc:", state2.doc.toJSON());
|
|
21428
21423
|
if (!dispatch) {
|
|
21429
|
-
console.log("No dispatch, returning false");
|
|
21430
21424
|
return false;
|
|
21431
21425
|
}
|
|
21432
21426
|
const { doc, schema } = state2;
|
|
@@ -21436,13 +21430,6 @@ const createUpdateMarkByUidCommand = (markName) => {
|
|
|
21436
21430
|
doc.descendants((node, pos) => {
|
|
21437
21431
|
if (node.isText && node.marks?.length) {
|
|
21438
21432
|
node.marks.forEach((mark) => {
|
|
21439
|
-
console.log("Checking mark:", {
|
|
21440
|
-
markType: mark.type.name,
|
|
21441
|
-
markUid: mark.attrs.uid,
|
|
21442
|
-
targetMarkName: markName,
|
|
21443
|
-
targetUid: uid,
|
|
21444
|
-
matches: mark.type.name === markName && mark.attrs.uid === uid
|
|
21445
|
-
});
|
|
21446
21433
|
if (mark.type.name === markName && mark.attrs.uid === uid) {
|
|
21447
21434
|
positions.push({
|
|
21448
21435
|
from: pos,
|
|
@@ -21450,33 +21437,21 @@ const createUpdateMarkByUidCommand = (markName) => {
|
|
|
21450
21437
|
mark
|
|
21451
21438
|
});
|
|
21452
21439
|
found2 = true;
|
|
21453
|
-
console.log("Found matching mark at:", { from: pos, to: pos + node.nodeSize });
|
|
21454
21440
|
}
|
|
21455
21441
|
});
|
|
21456
21442
|
}
|
|
21457
21443
|
});
|
|
21458
|
-
console.log("Total positions found:", positions.length);
|
|
21459
|
-
console.log("Positions:", positions);
|
|
21460
21444
|
if (found2) {
|
|
21461
21445
|
positions.forEach(({ from, to, mark }) => {
|
|
21462
21446
|
const newAttrs = { ...mark.attrs, ...attrs };
|
|
21463
21447
|
const markType = schema.marks[markName];
|
|
21464
|
-
console.log("Applying update:", { from, to, oldAttrs: mark.attrs, newAttrs });
|
|
21465
21448
|
if (markType) {
|
|
21466
|
-
console.log("Before removeMark - tr.doc:", tr.doc.toJSON());
|
|
21467
21449
|
tr = tr.removeMark(from, to, markType);
|
|
21468
|
-
console.log("After removeMark - tr.doc:", tr.doc.toJSON());
|
|
21469
21450
|
tr = tr.addMark(from, to, markType.create(newAttrs));
|
|
21470
|
-
console.log("After addMark - tr.doc:", tr.doc.toJSON());
|
|
21471
21451
|
}
|
|
21472
21452
|
});
|
|
21473
|
-
console.log("About to dispatch transaction");
|
|
21474
|
-
console.log("Final tr.doc:", tr.doc.toJSON());
|
|
21475
|
-
console.log("Original state.doc:", state2.doc.toJSON());
|
|
21476
21453
|
dispatch(tr);
|
|
21477
|
-
console.log("Transaction dispatched successfully");
|
|
21478
21454
|
}
|
|
21479
|
-
console.log("=== UPDATE MARK COMMAND END ===");
|
|
21480
21455
|
return found2;
|
|
21481
21456
|
};
|
|
21482
21457
|
};
|
|
@@ -22494,7 +22469,6 @@ let warnedAboutTextSelection = false;
|
|
|
22494
22469
|
function checkTextSelection($pos) {
|
|
22495
22470
|
if (!warnedAboutTextSelection && !$pos.parent.inlineContent) {
|
|
22496
22471
|
warnedAboutTextSelection = true;
|
|
22497
|
-
console["warn"]("TextSelection endpoint not pointing into a node with inline content (" + $pos.parent.type.name + ")");
|
|
22498
22472
|
}
|
|
22499
22473
|
}
|
|
22500
22474
|
class TextSelection extends Selection {
|
|
@@ -23219,7 +23193,6 @@ const PollCreator = ({ choices, onChange }) => {
|
|
|
23219
23193
|
const result = await fileStore.uploadImage(file);
|
|
23220
23194
|
return createPollMediaOption(result, startIndex + index2);
|
|
23221
23195
|
} catch (error) {
|
|
23222
|
-
console.error("Upload failed for", file.name, error);
|
|
23223
23196
|
return null;
|
|
23224
23197
|
}
|
|
23225
23198
|
});
|
|
@@ -23239,7 +23212,6 @@ const PollCreator = ({ choices, onChange }) => {
|
|
|
23239
23212
|
return final;
|
|
23240
23213
|
});
|
|
23241
23214
|
} catch (error) {
|
|
23242
|
-
console.error("Unexpected error during file upload:", error);
|
|
23243
23215
|
setInternalChoices((current) => {
|
|
23244
23216
|
const withoutPlaceholders = current.filter((c) => !isPlaceholder(c));
|
|
23245
23217
|
setTimeout(() => {
|
|
@@ -23272,7 +23244,6 @@ const PollCreator = ({ choices, onChange }) => {
|
|
|
23272
23244
|
return updated;
|
|
23273
23245
|
});
|
|
23274
23246
|
} catch (error) {
|
|
23275
|
-
console.error("URL upload failed:", error);
|
|
23276
23247
|
setInternalChoices((current) => {
|
|
23277
23248
|
const withoutPlaceholder = current.filter((c) => !isPlaceholder(c));
|
|
23278
23249
|
setTimeout(() => {
|
|
@@ -23813,7 +23784,6 @@ const LinkMarkView = ({ mark, editor }) => {
|
|
|
23813
23784
|
};
|
|
23814
23785
|
const handleUpdateLink = (link, text2, uid, previewPayload) => {
|
|
23815
23786
|
if (!editor.view) return;
|
|
23816
|
-
console.log("UPDATE LINK IN VIEW::", { text: text2 });
|
|
23817
23787
|
const newText = mark?.attrs?.isLinkMode ? link : text2 || link;
|
|
23818
23788
|
if (uid) {
|
|
23819
23789
|
editor.commands.updateLink(uid, { href: link, text: newText, previewPayload });
|
|
@@ -23873,25 +23843,66 @@ const LinkMarkView = ({ mark, editor }) => {
|
|
|
23873
23843
|
)
|
|
23874
23844
|
] });
|
|
23875
23845
|
};
|
|
23846
|
+
function isValidUrlFormat(text2) {
|
|
23847
|
+
return isValidUrl(normalizeUrl(text2.trim()));
|
|
23848
|
+
}
|
|
23876
23849
|
function doesPreviewExist(editor, uid) {
|
|
23877
|
-
|
|
23878
|
-
|
|
23879
|
-
|
|
23880
|
-
|
|
23881
|
-
|
|
23882
|
-
|
|
23883
|
-
|
|
23884
|
-
|
|
23850
|
+
if (!editor || !uid) {
|
|
23851
|
+
return false;
|
|
23852
|
+
}
|
|
23853
|
+
try {
|
|
23854
|
+
let exists = false;
|
|
23855
|
+
editor.state.doc.descendants((node) => {
|
|
23856
|
+
if (node && node.type && node.type.name === "linkPreview" && node.attrs?.uid === uid) {
|
|
23857
|
+
exists = true;
|
|
23858
|
+
return false;
|
|
23859
|
+
}
|
|
23860
|
+
});
|
|
23861
|
+
return exists;
|
|
23862
|
+
} catch (err) {
|
|
23863
|
+
return false;
|
|
23864
|
+
}
|
|
23885
23865
|
}
|
|
23886
23866
|
function findExistingPreview(editor) {
|
|
23887
|
-
|
|
23888
|
-
|
|
23889
|
-
|
|
23890
|
-
|
|
23891
|
-
|
|
23867
|
+
if (!editor) {
|
|
23868
|
+
return null;
|
|
23869
|
+
}
|
|
23870
|
+
try {
|
|
23871
|
+
let result = null;
|
|
23872
|
+
editor.state.doc.descendants((node, pos) => {
|
|
23873
|
+
if (node && node.type && node.type.name === "linkPreview") {
|
|
23874
|
+
result = { node, pos };
|
|
23875
|
+
return false;
|
|
23876
|
+
}
|
|
23877
|
+
});
|
|
23878
|
+
return result;
|
|
23879
|
+
} catch (err) {
|
|
23880
|
+
return null;
|
|
23881
|
+
}
|
|
23882
|
+
}
|
|
23883
|
+
function removePreviewByUid(editor, uid) {
|
|
23884
|
+
if (!editor || !uid) {
|
|
23885
|
+
return;
|
|
23886
|
+
}
|
|
23887
|
+
try {
|
|
23888
|
+
let previewPos = null;
|
|
23889
|
+
let previewSize = 0;
|
|
23890
|
+
editor.state.doc.descendants((node, pos) => {
|
|
23891
|
+
if (node && node.type && node.type.name === "linkPreview" && node.attrs?.uid === uid) {
|
|
23892
|
+
previewPos = pos;
|
|
23893
|
+
previewSize = node.nodeSize;
|
|
23894
|
+
return false;
|
|
23895
|
+
}
|
|
23896
|
+
});
|
|
23897
|
+
if (previewPos !== null && previewSize > 0) {
|
|
23898
|
+
const tr = editor.state.tr;
|
|
23899
|
+
if (tr) {
|
|
23900
|
+
tr.delete(previewPos, Number(previewPos) + previewSize);
|
|
23901
|
+
editor.view.dispatch(tr);
|
|
23902
|
+
}
|
|
23892
23903
|
}
|
|
23893
|
-
})
|
|
23894
|
-
|
|
23904
|
+
} catch (err) {
|
|
23905
|
+
}
|
|
23895
23906
|
}
|
|
23896
23907
|
function extractBestImage(metadata) {
|
|
23897
23908
|
return metadata?.image?.high_resolution ?? metadata?.image?.url ?? metadata?.image?.thumbnail ?? metadata?.image?.placeholder ?? null;
|
|
@@ -23916,6 +23927,76 @@ function collectAllLinkMarks(state2, linkMark) {
|
|
|
23916
23927
|
});
|
|
23917
23928
|
return links;
|
|
23918
23929
|
}
|
|
23930
|
+
function syncLinkHrefWithText(newState, linkMark, editor, singlePreviewMode, pluginState) {
|
|
23931
|
+
if (!newState || !linkMark || !editor || !pluginState) {
|
|
23932
|
+
return null;
|
|
23933
|
+
}
|
|
23934
|
+
let tr = null;
|
|
23935
|
+
let hasChanges = false;
|
|
23936
|
+
try {
|
|
23937
|
+
newState.doc.descendants((node, pos) => {
|
|
23938
|
+
if (!node || !node.isText || !node.marks?.length) return;
|
|
23939
|
+
node.marks.forEach((mark) => {
|
|
23940
|
+
if (!mark || !mark.type || !mark.attrs) return;
|
|
23941
|
+
if (mark.type === linkMark && mark.attrs?.uid) {
|
|
23942
|
+
const currentText = node.text || "";
|
|
23943
|
+
const currentHref = mark.attrs.href || "";
|
|
23944
|
+
if (currentText !== currentHref) {
|
|
23945
|
+
const isValidUrl2 = isValidUrlFormat(currentText);
|
|
23946
|
+
if (!tr) {
|
|
23947
|
+
tr = newState.tr;
|
|
23948
|
+
}
|
|
23949
|
+
if (!tr) {
|
|
23950
|
+
return;
|
|
23951
|
+
}
|
|
23952
|
+
if (isValidUrl2) {
|
|
23953
|
+
const newMark = linkMark.create({
|
|
23954
|
+
...mark.attrs,
|
|
23955
|
+
href: normalizeUrl(currentText)
|
|
23956
|
+
});
|
|
23957
|
+
if (!newMark) {
|
|
23958
|
+
return;
|
|
23959
|
+
}
|
|
23960
|
+
tr = tr.removeMark(pos, pos + node.nodeSize, linkMark);
|
|
23961
|
+
tr = tr.addMark(pos, pos + node.nodeSize, newMark);
|
|
23962
|
+
hasChanges = true;
|
|
23963
|
+
pluginState.processedLinks.delete(mark.attrs.uid);
|
|
23964
|
+
if (singlePreviewMode) {
|
|
23965
|
+
queueMicrotask(() => {
|
|
23966
|
+
try {
|
|
23967
|
+
const existingPreview = findExistingPreview(editor);
|
|
23968
|
+
if (existingPreview && mark.attrs?.uid) {
|
|
23969
|
+
}
|
|
23970
|
+
} catch (err) {
|
|
23971
|
+
}
|
|
23972
|
+
});
|
|
23973
|
+
} else {
|
|
23974
|
+
}
|
|
23975
|
+
} else {
|
|
23976
|
+
tr = tr.removeMark(pos, pos + node.nodeSize, linkMark);
|
|
23977
|
+
hasChanges = true;
|
|
23978
|
+
queueMicrotask(() => {
|
|
23979
|
+
try {
|
|
23980
|
+
if (mark.attrs?.uid) {
|
|
23981
|
+
removePreviewByUid(editor, mark.attrs.uid);
|
|
23982
|
+
}
|
|
23983
|
+
} catch (err) {
|
|
23984
|
+
}
|
|
23985
|
+
});
|
|
23986
|
+
if (mark.attrs?.uid) {
|
|
23987
|
+
pluginState.processedLinks.delete(mark.attrs.uid);
|
|
23988
|
+
pluginState.resolvingLinks.delete(mark.attrs.uid);
|
|
23989
|
+
}
|
|
23990
|
+
}
|
|
23991
|
+
}
|
|
23992
|
+
}
|
|
23993
|
+
});
|
|
23994
|
+
});
|
|
23995
|
+
} catch (err) {
|
|
23996
|
+
return null;
|
|
23997
|
+
}
|
|
23998
|
+
return hasChanges ? tr : null;
|
|
23999
|
+
}
|
|
23919
24000
|
function assignUidsToLinks(newState, linkMark) {
|
|
23920
24001
|
const newUids = /* @__PURE__ */ new Map();
|
|
23921
24002
|
let tr = null;
|
|
@@ -23925,11 +24006,6 @@ function assignUidsToLinks(newState, linkMark) {
|
|
|
23925
24006
|
node.marks.forEach((mark) => {
|
|
23926
24007
|
if (mark.type === linkMark && mark.attrs?.href && !mark.attrs.uid) {
|
|
23927
24008
|
const newUid = v4();
|
|
23928
|
-
console.log("🔧 Assigning UID to autolinked URL:", {
|
|
23929
|
-
href: mark.attrs.href,
|
|
23930
|
-
uid: newUid,
|
|
23931
|
-
pos
|
|
23932
|
-
});
|
|
23933
24009
|
const newMark = linkMark.create({
|
|
23934
24010
|
...mark.attrs,
|
|
23935
24011
|
uid: newUid
|
|
@@ -23956,25 +24032,14 @@ function resolveLinkAndHandlePreview(link, options, singlePreviewMode, pluginSta
|
|
|
23956
24032
|
const { api, editor } = options;
|
|
23957
24033
|
const mediaGroup = findByType(editor?.getJSON(), "mediaGroup");
|
|
23958
24034
|
if (!api) {
|
|
23959
|
-
console.warn("⚠️ No API provided to resolve link");
|
|
23960
24035
|
return;
|
|
23961
24036
|
}
|
|
23962
24037
|
if (singlePreviewMode && mediaGroup.length >= 1) return;
|
|
23963
24038
|
pluginState.resolvingLinks.add(link.uid);
|
|
23964
|
-
console.log("🌐 Resolving link metadata:", {
|
|
23965
|
-
uid: link.uid,
|
|
23966
|
-
href: link.href,
|
|
23967
|
-
singlePreviewMode
|
|
23968
|
-
});
|
|
23969
24039
|
api.resolveUrl(normalizeUrl(link.href)).then((metadata) => {
|
|
23970
24040
|
pluginState.resolvingLinks.delete(link.uid);
|
|
23971
24041
|
pluginState.processedLinks.add(link.uid);
|
|
23972
|
-
console.log("✅ Link metadata resolved:", {
|
|
23973
|
-
uid: link.uid,
|
|
23974
|
-
metadata
|
|
23975
|
-
});
|
|
23976
24042
|
if (!metadata) {
|
|
23977
|
-
console.warn("⚠️ No metadata returned for:", link.href);
|
|
23978
24043
|
return;
|
|
23979
24044
|
}
|
|
23980
24045
|
const previewData = {
|
|
@@ -23989,13 +24054,11 @@ function resolveLinkAndHandlePreview(link, options, singlePreviewMode, pluginSta
|
|
|
23989
24054
|
if (singlePreviewMode) {
|
|
23990
24055
|
const existingPreview = findExistingPreview(editor);
|
|
23991
24056
|
if (existingPreview) {
|
|
23992
|
-
console.log("🔄 Updating existing preview in single mode");
|
|
23993
24057
|
const { pos } = existingPreview;
|
|
23994
24058
|
const tr = editor.state.tr;
|
|
23995
24059
|
tr.setNodeMarkup(pos, void 0, previewData);
|
|
23996
24060
|
editor.view.dispatch(tr);
|
|
23997
24061
|
} else {
|
|
23998
|
-
console.log("➕ Creating first preview in single mode");
|
|
23999
24062
|
editor.commands.setLinkPreview(previewData);
|
|
24000
24063
|
}
|
|
24001
24064
|
editor.commands.updateLinkByUid(link.uid, {
|
|
@@ -24003,16 +24066,12 @@ function resolveLinkAndHandlePreview(link, options, singlePreviewMode, pluginSta
|
|
|
24003
24066
|
});
|
|
24004
24067
|
} else {
|
|
24005
24068
|
if (!doesPreviewExist(editor, link.uid)) {
|
|
24006
|
-
console.log("➕ Creating new preview in multi mode");
|
|
24007
24069
|
editor.chain().updateLinkByUid(link.uid, {
|
|
24008
24070
|
previewPayload: convertLinkMetaToPreviewItem(metadata)
|
|
24009
24071
|
}).setLinkPreview(previewData).run();
|
|
24010
|
-
} else {
|
|
24011
|
-
console.log("⏭️ Preview already exists, skipping");
|
|
24012
24072
|
}
|
|
24013
24073
|
}
|
|
24014
24074
|
}).catch((err) => {
|
|
24015
|
-
console.error("❌ Failed to resolve link:", err);
|
|
24016
24075
|
pluginState.resolvingLinks.delete(link.uid);
|
|
24017
24076
|
});
|
|
24018
24077
|
}
|
|
@@ -24022,10 +24081,6 @@ function createLinkAutoResolvePlugin(options, singlePreviewMode = false) {
|
|
|
24022
24081
|
key: pluginKey,
|
|
24023
24082
|
state: {
|
|
24024
24083
|
init() {
|
|
24025
|
-
console.log("🔌 LinkAutoResolve plugin initialized", {
|
|
24026
|
-
singlePreviewMode,
|
|
24027
|
-
hasApi: !!options.api
|
|
24028
|
-
});
|
|
24029
24084
|
return {
|
|
24030
24085
|
resolvingLinks: /* @__PURE__ */ new Set(),
|
|
24031
24086
|
processedLinks: /* @__PURE__ */ new Set()
|
|
@@ -24055,27 +24110,22 @@ function createLinkAutoResolvePlugin(options, singlePreviewMode = false) {
|
|
|
24055
24110
|
appendTransaction: (transactions, oldState, newState) => {
|
|
24056
24111
|
const linkMark = newState.schema.marks["customLink"];
|
|
24057
24112
|
if (!linkMark) {
|
|
24058
|
-
console.warn("⚠️ customLink mark not found in schema");
|
|
24059
24113
|
return null;
|
|
24060
24114
|
}
|
|
24061
24115
|
if (!transactions.some((tr) => tr.docChanged)) {
|
|
24062
24116
|
return null;
|
|
24063
24117
|
}
|
|
24064
|
-
console.log("📝 Document changed, checking for new links...");
|
|
24065
24118
|
const pluginState = pluginKey.getState(newState);
|
|
24119
|
+
if (!pluginState) {
|
|
24120
|
+
return null;
|
|
24121
|
+
}
|
|
24122
|
+
const syncTr = singlePreviewMode ? syncLinkHrefWithText(newState, linkMark, options.editor, singlePreviewMode, pluginState) : null;
|
|
24066
24123
|
const oldLinks = collectAllLinkMarks(oldState, linkMark);
|
|
24067
24124
|
const newLinks = collectAllLinkMarks(newState, linkMark);
|
|
24068
|
-
console.log("📊 Link count:", {
|
|
24069
|
-
old: oldLinks.size,
|
|
24070
|
-
new: newLinks.size,
|
|
24071
|
-
processed: pluginState.processedLinks.size,
|
|
24072
|
-
resolving: pluginState.resolvingLinks.size
|
|
24073
|
-
});
|
|
24074
24125
|
const { tr: uidTr, newUids } = assignUidsToLinks(newState, linkMark);
|
|
24075
24126
|
const linksToResolve = [];
|
|
24076
24127
|
newUids.forEach((linkData) => {
|
|
24077
24128
|
if (!pluginState.processedLinks.has(linkData.uid) && !pluginState.resolvingLinks.has(linkData.uid)) {
|
|
24078
|
-
console.log("🆕 New autolinked URL detected:", linkData);
|
|
24079
24129
|
linksToResolve.push(linkData);
|
|
24080
24130
|
}
|
|
24081
24131
|
});
|
|
@@ -24088,21 +24138,33 @@ function createLinkAutoResolvePlugin(options, singlePreviewMode = false) {
|
|
|
24088
24138
|
return;
|
|
24089
24139
|
}
|
|
24090
24140
|
if (!oldLinks.has(uid)) {
|
|
24091
|
-
console.log("🆕 New link detected (with UID):", linkData);
|
|
24092
24141
|
linksToResolve.push(linkData);
|
|
24093
24142
|
}
|
|
24094
24143
|
});
|
|
24095
24144
|
if (linksToResolve.length > 0) {
|
|
24096
|
-
console.log("🚀 Processing", linksToResolve.length, "new link(s)");
|
|
24097
24145
|
queueMicrotask(() => {
|
|
24098
24146
|
linksToResolve.forEach((link) => {
|
|
24099
24147
|
resolveLinkAndHandlePreview(link, options, singlePreviewMode, pluginState);
|
|
24100
24148
|
});
|
|
24101
24149
|
});
|
|
24102
|
-
} else {
|
|
24103
|
-
console.log("✓ No new links to process");
|
|
24104
24150
|
}
|
|
24105
|
-
|
|
24151
|
+
if (syncTr && uidTr) {
|
|
24152
|
+
try {
|
|
24153
|
+
uidTr.steps.forEach((step, i) => {
|
|
24154
|
+
if (step && syncTr) {
|
|
24155
|
+
syncTr.step(step);
|
|
24156
|
+
const map = uidTr.mapping.maps[i];
|
|
24157
|
+
if (map) {
|
|
24158
|
+
syncTr.mapping.appendMap(map);
|
|
24159
|
+
}
|
|
24160
|
+
}
|
|
24161
|
+
});
|
|
24162
|
+
return syncTr;
|
|
24163
|
+
} catch (err) {
|
|
24164
|
+
return syncTr;
|
|
24165
|
+
}
|
|
24166
|
+
}
|
|
24167
|
+
return syncTr ?? uidTr ?? null;
|
|
24106
24168
|
}
|
|
24107
24169
|
});
|
|
24108
24170
|
}
|
|
@@ -24198,7 +24260,6 @@ const CustomLink = Link__default.default.extend({
|
|
|
24198
24260
|
this?.options?.api?.resolveUrl(normalizeUrl(href))?.then((metadata) => {
|
|
24199
24261
|
if (metadata) {
|
|
24200
24262
|
const previewPayload = convertLinkMetaToPreviewItem(metadata);
|
|
24201
|
-
console.log({ href, text: text2 });
|
|
24202
24263
|
editor?.chain()?.updateLinkByUid(uid, { href, text: text2, previewPayload })?.updateLinkPreviewByUid(uid, {
|
|
24203
24264
|
// Now using correct UID
|
|
24204
24265
|
loading: false,
|
|
@@ -24257,7 +24318,6 @@ const CustomLink = Link__default.default.extend({
|
|
|
24257
24318
|
if (attrs.href) {
|
|
24258
24319
|
queueMicrotask(() => {
|
|
24259
24320
|
this.options.api?.resolveUrl(normalizeUrl(attrs.href))?.then((metadata) => {
|
|
24260
|
-
console.log({ metadata });
|
|
24261
24321
|
if (metadata) {
|
|
24262
24322
|
const previewPayload = convertLinkMetaToPreviewItem(metadata);
|
|
24263
24323
|
let linkPreviewExists = false;
|
|
@@ -24286,7 +24346,6 @@ const CustomLink = Link__default.default.extend({
|
|
|
24286
24346
|
editor.commands.deleteLinkPreviewByUid(uid);
|
|
24287
24347
|
}
|
|
24288
24348
|
}).catch((err) => {
|
|
24289
|
-
console.log("LINK UPDATE ERR::", { err });
|
|
24290
24349
|
editor.commands.deleteLinkPreviewByUid(uid);
|
|
24291
24350
|
});
|
|
24292
24351
|
});
|
|
@@ -24366,7 +24425,6 @@ const IframeView = ({
|
|
|
24366
24425
|
setPreviewData(previewPayload);
|
|
24367
24426
|
updateAttributes({ previewPayload });
|
|
24368
24427
|
}).catch((error) => {
|
|
24369
|
-
console.error("Failed to fetch preview:", error);
|
|
24370
24428
|
}).finally(() => {
|
|
24371
24429
|
});
|
|
24372
24430
|
}
|
|
@@ -24611,7 +24669,6 @@ const _createTrustedTypesPolicy = function _createTrustedTypesPolicy2(trustedTyp
|
|
|
24611
24669
|
}
|
|
24612
24670
|
});
|
|
24613
24671
|
} catch (_) {
|
|
24614
|
-
console.warn("TrustedTypes policy " + policyName + " could not be created.");
|
|
24615
24672
|
return null;
|
|
24616
24673
|
}
|
|
24617
24674
|
};
|
|
@@ -25448,7 +25505,6 @@ const configureDOMPurify = () => {
|
|
|
25448
25505
|
const element = node;
|
|
25449
25506
|
const src = element.getAttribute("src") || "";
|
|
25450
25507
|
if (!isAllowedDomain(src)) {
|
|
25451
|
-
console.warn("🚨 Blocked iframe from non-allowed domain:", src);
|
|
25452
25508
|
node.parentNode?.removeChild(node);
|
|
25453
25509
|
}
|
|
25454
25510
|
}
|
|
@@ -25460,7 +25516,6 @@ function sanitizeIframeHTML(html2) {
|
|
|
25460
25516
|
const config = configureDOMPurify();
|
|
25461
25517
|
const cleaned = purify.sanitize(html2, config);
|
|
25462
25518
|
if (!cleaned.includes("<iframe")) {
|
|
25463
|
-
console.warn("⚠️ No valid iframe found after sanitization");
|
|
25464
25519
|
return null;
|
|
25465
25520
|
}
|
|
25466
25521
|
const match = cleaned.match(/<iframe[^>]*src=["']([^"']+)["']/i);
|
|
@@ -25472,7 +25527,6 @@ function sanitizeIframeHTML(html2) {
|
|
|
25472
25527
|
}
|
|
25473
25528
|
return match[1];
|
|
25474
25529
|
} catch (error) {
|
|
25475
|
-
console.error("🚨 Error sanitizing iframe:", error);
|
|
25476
25530
|
return null;
|
|
25477
25531
|
} finally {
|
|
25478
25532
|
purify.removeAllHooks();
|
|
@@ -25510,7 +25564,6 @@ const createFinder = (regex) => {
|
|
|
25510
25564
|
match
|
|
25511
25565
|
});
|
|
25512
25566
|
}
|
|
25513
|
-
console.log({ match, matches });
|
|
25514
25567
|
return matches.length > 0 ? matches : null;
|
|
25515
25568
|
};
|
|
25516
25569
|
};
|
|
@@ -25562,11 +25615,9 @@ const Iframe = core.Node.create({
|
|
|
25562
25615
|
const iframeHTML = match[0];
|
|
25563
25616
|
const safeSrc = sanitizeIframeHTML(iframeHTML);
|
|
25564
25617
|
if (!safeSrc) {
|
|
25565
|
-
console.warn("🚨 Blocked unsafe iframe paste");
|
|
25566
25618
|
toast.error("🚨 Your pasted iframe is not safe to render");
|
|
25567
25619
|
return;
|
|
25568
25620
|
}
|
|
25569
|
-
console.log("✅ Safe iframe URL validated:", safeSrc);
|
|
25570
25621
|
const node = this.type.create({ src: safeSrc, previewPayload: null });
|
|
25571
25622
|
state2.tr.replaceRangeWith(range.from, range.to, node);
|
|
25572
25623
|
}
|
|
@@ -25577,7 +25628,6 @@ const Iframe = core.Node.create({
|
|
|
25577
25628
|
handler: ({ state: state2, range, match }) => {
|
|
25578
25629
|
const fullUrl = match[0];
|
|
25579
25630
|
const embedUrl = getEmbedUrl(fullUrl);
|
|
25580
|
-
console.log({ match, fullUrl, embedUrl });
|
|
25581
25631
|
if (!embedUrl) return;
|
|
25582
25632
|
const node = this.type.create({ src: embedUrl });
|
|
25583
25633
|
state2.tr.replaceRangeWith(range.from, range.to, node);
|
|
@@ -25623,10 +25673,9 @@ const handleUrlWithoutSelection = (editor, url, event, autoDetectMedia) => {
|
|
|
25623
25673
|
mediaType: MediaItemType.MEDIA_ITEM
|
|
25624
25674
|
});
|
|
25625
25675
|
}).catch(
|
|
25626
|
-
(e) =>
|
|
25676
|
+
(e) => void 0
|
|
25627
25677
|
);
|
|
25628
25678
|
}
|
|
25629
|
-
console.log("[SmartLinkPaste] Inserting as link node");
|
|
25630
25679
|
editor.chain().focus().insertLink({ href: normalizedUrl, text: url }).run();
|
|
25631
25680
|
return true;
|
|
25632
25681
|
};
|
|
@@ -25648,7 +25697,6 @@ const createPasteHandler = (editor, options) => {
|
|
|
25648
25697
|
return false;
|
|
25649
25698
|
}
|
|
25650
25699
|
const trimmedText = pasteText.trim();
|
|
25651
|
-
console.log("[SmartLinkPaste] Valid URL detected:", isEmbeddableUrl(trimmedText));
|
|
25652
25700
|
if (isEmbeddableUrl(trimmedText) && options?.autoEmbed) {
|
|
25653
25701
|
event.preventDefault();
|
|
25654
25702
|
return false;
|
|
@@ -25665,7 +25713,6 @@ const createPasteHandler = (editor, options) => {
|
|
|
25665
25713
|
options?.autoDetectMedia ?? true
|
|
25666
25714
|
);
|
|
25667
25715
|
} catch (error) {
|
|
25668
|
-
console.error("[SmartLinkPaste] Error:", error);
|
|
25669
25716
|
return false;
|
|
25670
25717
|
}
|
|
25671
25718
|
};
|
|
@@ -25677,10 +25724,8 @@ const createTransformHandler = (editor) => {
|
|
|
25677
25724
|
return slice;
|
|
25678
25725
|
}
|
|
25679
25726
|
try {
|
|
25680
|
-
console.log("[SmartLinkPaste] Transforming inline URLs in pasted content");
|
|
25681
25727
|
return transformUrlsInSlice(editor, slice);
|
|
25682
25728
|
} catch (error) {
|
|
25683
|
-
console.error("[SmartLinkPaste] Transform error:", error);
|
|
25684
25729
|
return slice;
|
|
25685
25730
|
}
|
|
25686
25731
|
};
|
|
@@ -25787,7 +25832,6 @@ const SmartMediaUpload = core.Extension.create({
|
|
|
25787
25832
|
const uid = v4();
|
|
25788
25833
|
const options = this.options;
|
|
25789
25834
|
if (!options.api) {
|
|
25790
|
-
console.error("API instance not provided to SmartMediaUpload");
|
|
25791
25835
|
return false;
|
|
25792
25836
|
}
|
|
25793
25837
|
if (isFileOrBlob(source)) {
|
|
@@ -25797,7 +25841,6 @@ const SmartMediaUpload = core.Extension.create({
|
|
|
25797
25841
|
options.allowedFileTypes
|
|
25798
25842
|
);
|
|
25799
25843
|
if (!validation.valid) {
|
|
25800
|
-
console.error("File validation failed:", validation.error);
|
|
25801
25844
|
options.onUploadError?.(uid, new Error(validation.error));
|
|
25802
25845
|
return false;
|
|
25803
25846
|
}
|
|
@@ -25881,7 +25924,6 @@ const SmartMediaUpload = core.Extension.create({
|
|
|
25881
25924
|
} else editor.commands.deleteMediaByUid(item.uid);
|
|
25882
25925
|
options.onUploadComplete?.(item.uid, hostedUrl);
|
|
25883
25926
|
} catch (error) {
|
|
25884
|
-
console.error("Upload failed:", error);
|
|
25885
25927
|
const blobUrl = this.storage.blobUrls.get(item.uid);
|
|
25886
25928
|
if (blobUrl) {
|
|
25887
25929
|
URL.revokeObjectURL(blobUrl);
|
|
@@ -25893,7 +25935,7 @@ const SmartMediaUpload = core.Extension.create({
|
|
|
25893
25935
|
this.storage.activeUploads--;
|
|
25894
25936
|
this.storage.processUploadQueue(editor);
|
|
25895
25937
|
}
|
|
25896
|
-
})().catch((err) =>
|
|
25938
|
+
})().catch((err) => void 0);
|
|
25897
25939
|
if (this.storage.uploadQueue.length > 0) {
|
|
25898
25940
|
this.storage.processUploadQueue(editor);
|
|
25899
25941
|
}
|
|
@@ -28593,7 +28635,6 @@ function getSuggestionOptions({
|
|
|
28593
28635
|
const text2 = editor.getText();
|
|
28594
28636
|
const trimmed = text2?.replace(WHITESPACE_REGEX, " ")?.trim();
|
|
28595
28637
|
const matchStartPosition = trimmed?.lastIndexOf(char);
|
|
28596
|
-
console.log({ matchStartPosition });
|
|
28597
28638
|
const nodeAfter = editor.view.state.selection.$to.nodeAfter;
|
|
28598
28639
|
const overrideSpace = nodeAfter?.text?.startsWith(" ");
|
|
28599
28640
|
if (overrideSpace) {
|
|
@@ -28707,7 +28748,6 @@ const Mention = core.Node.create({
|
|
|
28707
28748
|
renderHTML({ node, HTMLAttributes }) {
|
|
28708
28749
|
const suggestion2 = getSuggestionFromChar(this, node.attrs.mentionSuggestionChar);
|
|
28709
28750
|
if (this.options.renderLabel !== void 0) {
|
|
28710
|
-
console.warn("renderLabel is deprecated use renderText and renderHTML instead");
|
|
28711
28751
|
return [
|
|
28712
28752
|
"span",
|
|
28713
28753
|
core.mergeAttributes({ "data-type": this.name }, this.options.HTMLAttributes, HTMLAttributes),
|
|
@@ -28747,7 +28787,6 @@ const Mention = core.Node.create({
|
|
|
28747
28787
|
suggestion: getSuggestionFromChar(this, node.attrs.mentionSuggestionChar)
|
|
28748
28788
|
};
|
|
28749
28789
|
if (this.options.renderLabel !== void 0) {
|
|
28750
|
-
console.warn("renderLabel is deprecated use renderText and renderHTML instead");
|
|
28751
28790
|
return this.options.renderLabel(args);
|
|
28752
28791
|
}
|
|
28753
28792
|
return this.options.renderText(args);
|
|
@@ -29736,11 +29775,9 @@ const mentionService = (api, mfs, store) => {
|
|
|
29736
29775
|
const fetchMentions = async () => {
|
|
29737
29776
|
const params = store.getState().getMentionParams();
|
|
29738
29777
|
if (!params) {
|
|
29739
|
-
console.error("DEBUG MENTION SERVICE::", "No group id or post id has been provided");
|
|
29740
29778
|
return [];
|
|
29741
29779
|
}
|
|
29742
29780
|
const { groupId, postId } = params;
|
|
29743
|
-
console.log({ groupId, postId });
|
|
29744
29781
|
const response = postId ? await mfs.getRecommendationPost(groupId, postId, 0, 999) : await mfs.getRecommendationGroup(groupId, 0, 999);
|
|
29745
29782
|
return response.entries?.filter((item) => Boolean(item?.user_data))?.map(
|
|
29746
29783
|
(item) => ({
|
|
@@ -29759,7 +29796,6 @@ const mentionService = (api, mfs, store) => {
|
|
|
29759
29796
|
const { selectedGroupId, groupId } = store.getState();
|
|
29760
29797
|
const activeGroupId = selectedGroupId ?? groupId;
|
|
29761
29798
|
if (!activeGroupId) {
|
|
29762
|
-
console.warn("DEBUG HASHTAG SERVICE::", "No active group selected or provided");
|
|
29763
29799
|
return [];
|
|
29764
29800
|
}
|
|
29765
29801
|
const response = await api.fetchGroupConversations(999, 0);
|
|
@@ -29961,8 +29997,8 @@ const LinkPreviewExtended = ({
|
|
|
29961
29997
|
title,
|
|
29962
29998
|
description,
|
|
29963
29999
|
image,
|
|
29964
|
-
domain
|
|
29965
|
-
|
|
30000
|
+
domain,
|
|
30001
|
+
onClickDelete
|
|
29966
30002
|
}) => {
|
|
29967
30003
|
const safeDomain = React.useMemo(() => {
|
|
29968
30004
|
try {
|
|
@@ -29971,6 +30007,11 @@ const LinkPreviewExtended = ({
|
|
|
29971
30007
|
return "unknown";
|
|
29972
30008
|
}
|
|
29973
30009
|
}, [href, domain]);
|
|
30010
|
+
const handleDelete = (e) => {
|
|
30011
|
+
e.preventDefault();
|
|
30012
|
+
e.stopPropagation();
|
|
30013
|
+
onClickDelete();
|
|
30014
|
+
};
|
|
29974
30015
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29975
30016
|
"div",
|
|
29976
30017
|
{
|
|
@@ -29979,18 +30020,32 @@ const LinkPreviewExtended = ({
|
|
|
29979
30020
|
selected ? "ring-2 ring-blue-500 ring-offset-2 rounded-lg" : ""
|
|
29980
30021
|
),
|
|
29981
30022
|
children: [
|
|
29982
|
-
/* @__PURE__ */ jsxRuntime.
|
|
29983
|
-
|
|
29984
|
-
|
|
29985
|
-
|
|
29986
|
-
|
|
29987
|
-
|
|
29988
|
-
|
|
29989
|
-
/* @__PURE__ */ jsxRuntime.
|
|
29990
|
-
|
|
29991
|
-
|
|
29992
|
-
|
|
29993
|
-
|
|
30023
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 absolute z-50 right-3 top-3", children: [
|
|
30024
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
30025
|
+
ToolbarButton,
|
|
30026
|
+
{
|
|
30027
|
+
asChild: true,
|
|
30028
|
+
tooltip: "Visit Link",
|
|
30029
|
+
className: "cursor-pointer backdrop-blur-2xl size-6 shadow-none group-hover:bg-accent/70 group-hover:text-accent-foreground text-primary-send",
|
|
30030
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative", children: [
|
|
30031
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { href, target: "_blank", rel: "noopener noreferrer", className: "absolute inset-0" }),
|
|
30032
|
+
/* @__PURE__ */ jsxRuntime.jsx(ExternalLink, {})
|
|
30033
|
+
] })
|
|
30034
|
+
}
|
|
30035
|
+
),
|
|
30036
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
30037
|
+
ToolbarButton,
|
|
30038
|
+
{
|
|
30039
|
+
tooltip: "Remove Link Preview",
|
|
30040
|
+
onClick: handleDelete,
|
|
30041
|
+
"aria-label": "Delete link preview",
|
|
30042
|
+
type: "button",
|
|
30043
|
+
size: "icon",
|
|
30044
|
+
className: "cursor-pointer backdrop-blur-2xl size-6 shadow-none bg-transparent group-hover:bg-red-50/70 hover:bg-red-50 text-destructive hover:text-destructive",
|
|
30045
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Trash2, {})
|
|
30046
|
+
}
|
|
30047
|
+
)
|
|
30048
|
+
] }),
|
|
29994
30049
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-0 w-full", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group overflow-hidden flex flex-col rounded-lg border bg-accent/30 transition-all hover:border-foreground/20 hover:shadow-sm", children: [
|
|
29995
30050
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-80 w-full shrink-0 overflow-hidden bg-muted border-b", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
29996
30051
|
"img",
|
|
@@ -30111,7 +30166,6 @@ const LinkPreview = core.Node.create({
|
|
|
30111
30166
|
},
|
|
30112
30167
|
renderHTML({ node }) {
|
|
30113
30168
|
const { href, uid, title, description, image, domain } = node.attrs;
|
|
30114
|
-
console.log("INSIDE RENDER HTML::", { href, image });
|
|
30115
30169
|
if (!href) return ["div", {}];
|
|
30116
30170
|
const content = [
|
|
30117
30171
|
// Link overlay
|
|
@@ -30246,11 +30300,6 @@ const MediaGroupView = ({ node, editor }) => {
|
|
|
30246
30300
|
editor.commands.deleteMediaByUid(uid);
|
|
30247
30301
|
};
|
|
30248
30302
|
const mediaNodes = node?.content?.content || [];
|
|
30249
|
-
console.log("MediaGroupView render:", {
|
|
30250
|
-
contentSize: node?.content?.size,
|
|
30251
|
-
mediaCount: mediaNodes?.length,
|
|
30252
|
-
nodes: mediaNodes?.map((n) => ({ type: n?.type?.name, uid: n?.attrs?.uid }))
|
|
30253
|
-
});
|
|
30254
30303
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
30255
30304
|
react.NodeViewWrapper,
|
|
30256
30305
|
{
|
|
@@ -30352,14 +30401,12 @@ const createMediaModePlugin = () => {
|
|
|
30352
30401
|
child.marks.forEach((mark) => {
|
|
30353
30402
|
if (mark.type.name === "customLink" && mark.attrs.previewPayload) {
|
|
30354
30403
|
lastLinkPreviewData = mark.attrs.previewPayload;
|
|
30355
|
-
console.log("Found link with previewPayload:", lastLinkPreviewData);
|
|
30356
30404
|
}
|
|
30357
30405
|
});
|
|
30358
30406
|
}
|
|
30359
30407
|
});
|
|
30360
30408
|
}
|
|
30361
30409
|
});
|
|
30362
|
-
console.log("Cleanup check:", { modified, hasMediaGroup, lastLinkPreviewData });
|
|
30363
30410
|
if (modified && hasMediaGroup && lastLinkPreviewData) {
|
|
30364
30411
|
let hasLinkPreview = false;
|
|
30365
30412
|
tr.doc.forEach((node) => {
|
|
@@ -30367,10 +30414,6 @@ const createMediaModePlugin = () => {
|
|
|
30367
30414
|
hasLinkPreview = true;
|
|
30368
30415
|
}
|
|
30369
30416
|
});
|
|
30370
|
-
console.log("Creating linkPreview:", {
|
|
30371
|
-
hasLinkPreview,
|
|
30372
|
-
schemaHasLinkPreview: !!newState.schema.nodes.linkPreview
|
|
30373
|
-
});
|
|
30374
30417
|
if (!hasLinkPreview && newState.schema.nodes.linkPreview) {
|
|
30375
30418
|
const preview = lastLinkPreviewData;
|
|
30376
30419
|
const linkPreviewNode = newState.schema.nodes.linkPreview.create({
|
|
@@ -30381,7 +30424,6 @@ const createMediaModePlugin = () => {
|
|
|
30381
30424
|
image: preview.linkImage?.url ?? "",
|
|
30382
30425
|
variant: LinkPreviewType.Extended
|
|
30383
30426
|
});
|
|
30384
|
-
console.log("Inserting linkPreview node:", { lastLinkPreviewData, linkPreviewNode });
|
|
30385
30427
|
tr.insert(tr.doc.content.size, linkPreviewNode);
|
|
30386
30428
|
modified = true;
|
|
30387
30429
|
}
|
|
@@ -30441,7 +30483,6 @@ const createMediaModePlugin = () => {
|
|
|
30441
30483
|
}
|
|
30442
30484
|
const mediaNodes = updatedTopLevelMedia.map((m) => m.node);
|
|
30443
30485
|
if (mediaNodes.some((n) => !n || n.type.name !== "media")) {
|
|
30444
|
-
console.warn("Invalid media nodes detected, skipping group creation");
|
|
30445
30486
|
return null;
|
|
30446
30487
|
}
|
|
30447
30488
|
const mediaGroup = newState.schema.nodes.mediaGroup.create({}, mediaNodes);
|
|
@@ -30459,7 +30500,6 @@ const createMediaModePlugin = () => {
|
|
|
30459
30500
|
const $pos = tr.doc.resolve(endPos);
|
|
30460
30501
|
tr.setSelection(state.TextSelection.near($pos));
|
|
30461
30502
|
} catch (e) {
|
|
30462
|
-
console.warn("Could not set selection:", e);
|
|
30463
30503
|
}
|
|
30464
30504
|
}
|
|
30465
30505
|
tr.setMeta("addToHistory", false);
|
|
@@ -30467,7 +30507,6 @@ const createMediaModePlugin = () => {
|
|
|
30467
30507
|
}
|
|
30468
30508
|
return modified ? tr : null;
|
|
30469
30509
|
} catch (error) {
|
|
30470
|
-
console.error("MediaMode plugin error:", error);
|
|
30471
30510
|
return null;
|
|
30472
30511
|
} finally {
|
|
30473
30512
|
isProcessing = false;
|
|
@@ -30609,7 +30648,7 @@ const getMediaExtensions = ({ api, store, user }) => {
|
|
|
30609
30648
|
}),
|
|
30610
30649
|
LinkPreview.configure({
|
|
30611
30650
|
variant: LinkPreviewType.Extended,
|
|
30612
|
-
selectable: false,
|
|
30651
|
+
// selectable: false,
|
|
30613
30652
|
draggable: false
|
|
30614
30653
|
}),
|
|
30615
30654
|
getMentionExtension(core2, mfs, store),
|
|
@@ -30753,7 +30792,6 @@ const isLinkMarkWithPayload = (node) => isLinkMark(node) && Boolean(node?.attrs?
|
|
|
30753
30792
|
const getLinkItemsPayload = (json) => {
|
|
30754
30793
|
const links = find(json, (node) => isLinkMarkWithPayload(node));
|
|
30755
30794
|
const items = links?.at(-1);
|
|
30756
|
-
console.log("Link Items Payload::", { items });
|
|
30757
30795
|
return { items };
|
|
30758
30796
|
};
|
|
30759
30797
|
const getPollItemsPayload = (json) => {
|
|
@@ -30767,7 +30805,7 @@ const isValidItem = (item) => {
|
|
|
30767
30805
|
const mediaItem = item;
|
|
30768
30806
|
const isValidLinkItem = linkItem?.linkUrl;
|
|
30769
30807
|
const mediaItemSources = mediaItem?.sources;
|
|
30770
|
-
const isValidMediaItem = mediaItemSources?.original?.url || mediaItemSources?.thumbnail?.url
|
|
30808
|
+
const isValidMediaItem = mediaItemSources?.original?.url || mediaItemSources?.thumbnail?.url;
|
|
30771
30809
|
return Boolean(isValidLinkItem || isValidMediaItem);
|
|
30772
30810
|
};
|
|
30773
30811
|
const generateHtmlPostPayload = ({
|
|
@@ -30787,7 +30825,6 @@ const generateHtmlPostPayload = ({
|
|
|
30787
30825
|
)?.at(0);
|
|
30788
30826
|
const isEmbedOnly = isOnlyContentNode(json, "iframe");
|
|
30789
30827
|
const body = isEmbedOnly ? previewItemEmbed?.attrs?.previewPayload?.linkTitle ?? previewItemEmbed?.attrs?.src ?? "" : secondaryText?.text ?? firstText?.text ?? "";
|
|
30790
|
-
console.log({ firstText });
|
|
30791
30828
|
const items = [
|
|
30792
30829
|
previewItemMedia?.attrs?.payload,
|
|
30793
30830
|
previewItemEmbed?.attrs?.previewPayload,
|
|
@@ -30814,11 +30851,14 @@ const generateMediaPostPayload = ({
|
|
|
30814
30851
|
const { mentionData } = getMentionDataPayload(json);
|
|
30815
30852
|
const { items: mediaItems } = getMediaItemsPayload(json);
|
|
30816
30853
|
const { items: linkItems } = getLinkItemsPayload(json);
|
|
30854
|
+
const items = mediaItems?.length > 0 ? mediaItems : linkItems?.length > 0 ? linkItems : [];
|
|
30855
|
+
if (!body && mediaItems.length === 0)
|
|
30856
|
+
return { error: "Your post is empty. Add text or media to share your thoughts." };
|
|
30817
30857
|
return {
|
|
30818
30858
|
...commons,
|
|
30819
30859
|
type: mediaItems?.length > 0 ? NewPostType.NEW_POST_MEDIA : linkItems?.length > 0 ? NewPostType.NEW_POST_LINK : NewPostType.NEW_POST_MESSAGE,
|
|
30820
30860
|
body,
|
|
30821
|
-
items
|
|
30861
|
+
items,
|
|
30822
30862
|
mentionData,
|
|
30823
30863
|
sendCrossMention
|
|
30824
30864
|
};
|
|
@@ -30838,7 +30878,6 @@ const generatePollPostPayload = ({
|
|
|
30838
30878
|
option_id: index2 === 0 ? item.option_id : v4(),
|
|
30839
30879
|
option_color: OPTION_COLORS[index2 % OPTION_COLORS.length]
|
|
30840
30880
|
})) : items;
|
|
30841
|
-
console.log({ polls });
|
|
30842
30881
|
return {
|
|
30843
30882
|
...commons,
|
|
30844
30883
|
type: NewPostType.NEW_POST_POLL,
|
|
@@ -30875,6 +30914,7 @@ const PostBuilderEditorInstance = ({
|
|
|
30875
30914
|
const [isDragging, setIsDragging] = React.useState(false);
|
|
30876
30915
|
const { trackPublish } = usePostBuilderAnalytics();
|
|
30877
30916
|
const { clearContent } = usePersistence();
|
|
30917
|
+
useHostAnalyticsBridge();
|
|
30878
30918
|
const handleDragOver = (e) => {
|
|
30879
30919
|
e.preventDefault();
|
|
30880
30920
|
setIsDragging(true);
|
|
@@ -30894,10 +30934,24 @@ const PostBuilderEditorInstance = ({
|
|
|
30894
30934
|
const text2 = editor?.getText();
|
|
30895
30935
|
const payload = generateCreatePostPayload(editorTab, { editor, sendCrossMention });
|
|
30896
30936
|
const isPollType = payload?.type === NewPostType.NEW_POST_POLL;
|
|
30897
|
-
if (
|
|
30937
|
+
if (payload?.error) {
|
|
30938
|
+
toast.error(payload.error);
|
|
30939
|
+
return;
|
|
30940
|
+
}
|
|
30941
|
+
if (!payload?.postId) return;
|
|
30898
30942
|
if (isPollType && payload.items?.length === 0)
|
|
30899
30943
|
return toast.warning(`At least ${POLL_LIMITS.MIN} option is mandatory to create a poll post`);
|
|
30900
|
-
|
|
30944
|
+
if (typeof window !== "undefined") {
|
|
30945
|
+
window.dispatchEvent(
|
|
30946
|
+
new CustomEvent(PostBuilderEvents.POST_PUBLISH_ATTEMPTED, {
|
|
30947
|
+
detail: {
|
|
30948
|
+
postId: payload.postId,
|
|
30949
|
+
postType: payload.type
|
|
30950
|
+
}
|
|
30951
|
+
})
|
|
30952
|
+
);
|
|
30953
|
+
}
|
|
30954
|
+
trackPublish({ status: "attempted", postId: payload?.postId, postType: payload?.type });
|
|
30901
30955
|
onCreatePost?.({ payload, html: html2, json, text: text2 });
|
|
30902
30956
|
if (!clearOnSuccess) return;
|
|
30903
30957
|
clearContent();
|
|
@@ -31071,7 +31125,6 @@ class SessionManager {
|
|
|
31071
31125
|
}, SESSION_TIMEOUT_MS);
|
|
31072
31126
|
}
|
|
31073
31127
|
endSession(reason) {
|
|
31074
|
-
console.log({ reason });
|
|
31075
31128
|
if (this.inactivityTimer) {
|
|
31076
31129
|
clearTimeout(this.inactivityTimer);
|
|
31077
31130
|
}
|
|
@@ -31132,7 +31185,7 @@ function useAnalytics({ editorTab, config }) {
|
|
|
31132
31185
|
const featureTracker = React.useRef(new FeatureTracker()).current;
|
|
31133
31186
|
const logEvent = useAnalyticsLogEvent();
|
|
31134
31187
|
const trackEvent = React.useCallback(
|
|
31135
|
-
(name, properties
|
|
31188
|
+
({ name, properties }) => {
|
|
31136
31189
|
const fullConfig = { ...DEFAULT_CONFIG, ...config };
|
|
31137
31190
|
if (!fullConfig.enabled) return;
|
|
31138
31191
|
sessionManager.updateActivity();
|
|
@@ -31140,30 +31193,32 @@ function useAnalytics({ editorTab, config }) {
|
|
|
31140
31193
|
session_id: sessionManager.getSessionId(),
|
|
31141
31194
|
timestamp: Date.now(),
|
|
31142
31195
|
editor_type: editorTab,
|
|
31143
|
-
...properties
|
|
31196
|
+
...properties ?? {}
|
|
31144
31197
|
};
|
|
31145
|
-
|
|
31146
|
-
|
|
31147
|
-
}
|
|
31148
|
-
if (fullConfig.debug) {
|
|
31149
|
-
console.log("[Analytics]", name, enrichedProperties);
|
|
31150
|
-
}
|
|
31198
|
+
const cleanProps = pickBy(enrichedProperties, (value) => value != null);
|
|
31199
|
+
if (logEvent) logEvent(name, cleanProps);
|
|
31151
31200
|
},
|
|
31152
31201
|
[config, editorTab, logEvent, sessionManager]
|
|
31153
31202
|
);
|
|
31154
31203
|
React.useEffect(() => {
|
|
31155
31204
|
const sessionId = sessionManager.startSession();
|
|
31156
|
-
trackEvent(
|
|
31157
|
-
|
|
31158
|
-
|
|
31159
|
-
|
|
31205
|
+
trackEvent({
|
|
31206
|
+
name: ANALYTICS_EVENTS.SESSION.STARTED,
|
|
31207
|
+
properties: {
|
|
31208
|
+
session_id: sessionId,
|
|
31209
|
+
timestamp: Date.now(),
|
|
31210
|
+
editor_type: editorTab
|
|
31211
|
+
}
|
|
31160
31212
|
});
|
|
31161
31213
|
const handleUnload = () => {
|
|
31162
|
-
trackEvent(
|
|
31163
|
-
|
|
31164
|
-
|
|
31165
|
-
|
|
31166
|
-
|
|
31214
|
+
trackEvent({
|
|
31215
|
+
name: ANALYTICS_EVENTS.SESSION.COMPLETED,
|
|
31216
|
+
properties: {
|
|
31217
|
+
session_id: sessionManager.getSessionId(),
|
|
31218
|
+
timestamp: Date.now(),
|
|
31219
|
+
editor_type: editorTab,
|
|
31220
|
+
session_duration_ms: sessionManager.getSessionDuration()
|
|
31221
|
+
}
|
|
31167
31222
|
});
|
|
31168
31223
|
};
|
|
31169
31224
|
window.addEventListener("beforeunload", handleUnload);
|
|
@@ -31173,60 +31228,88 @@ function useAnalytics({ editorTab, config }) {
|
|
|
31173
31228
|
};
|
|
31174
31229
|
}, []);
|
|
31175
31230
|
const trackFeature = React.useCallback(
|
|
31176
|
-
(featureName) => {
|
|
31231
|
+
({ featureName }) => {
|
|
31177
31232
|
const { isFirstUse, usageCount } = featureTracker.trackUsage(featureName);
|
|
31178
|
-
trackEvent(
|
|
31179
|
-
|
|
31180
|
-
|
|
31181
|
-
|
|
31233
|
+
trackEvent({
|
|
31234
|
+
name: isFirstUse ? ANALYTICS_EVENTS.FEATURE.DISCOVERED : ANALYTICS_EVENTS.FEATURE.USED,
|
|
31235
|
+
properties: {
|
|
31236
|
+
feature_name: featureName,
|
|
31237
|
+
is_first_use: isFirstUse,
|
|
31238
|
+
usage_count: usageCount
|
|
31239
|
+
}
|
|
31182
31240
|
});
|
|
31183
31241
|
},
|
|
31184
31242
|
[trackEvent, featureTracker]
|
|
31185
31243
|
);
|
|
31186
31244
|
const trackPublish = React.useCallback(
|
|
31187
|
-
(status, data) => {
|
|
31245
|
+
({ status, data }) => {
|
|
31188
31246
|
const eventMap = {
|
|
31189
31247
|
attempted: ANALYTICS_EVENTS.PUBLISH.ATTEMPTED,
|
|
31190
31248
|
success: ANALYTICS_EVENTS.PUBLISH.SUCCESS,
|
|
31191
31249
|
failed: ANALYTICS_EVENTS.PUBLISH.FAILED
|
|
31192
31250
|
};
|
|
31193
|
-
|
|
31251
|
+
const properties = {
|
|
31194
31252
|
editor_type: editorTab,
|
|
31195
31253
|
session_duration_ms: sessionManager.getSessionDuration(),
|
|
31196
31254
|
...data
|
|
31255
|
+
};
|
|
31256
|
+
trackEvent({
|
|
31257
|
+
name: eventMap[status],
|
|
31258
|
+
properties
|
|
31197
31259
|
});
|
|
31198
31260
|
sessionManager.endSession("completed");
|
|
31199
31261
|
},
|
|
31200
31262
|
[trackEvent, editorTab, sessionManager]
|
|
31201
31263
|
);
|
|
31202
31264
|
const trackAbandon = React.useCallback(
|
|
31203
|
-
(
|
|
31204
|
-
|
|
31205
|
-
|
|
31206
|
-
|
|
31207
|
-
|
|
31208
|
-
|
|
31209
|
-
|
|
31265
|
+
({
|
|
31266
|
+
contentLength,
|
|
31267
|
+
hasUnsavedChanges,
|
|
31268
|
+
abandonReason,
|
|
31269
|
+
postType,
|
|
31270
|
+
userHistoryData
|
|
31271
|
+
}) => {
|
|
31272
|
+
trackEvent({
|
|
31273
|
+
name: ANALYTICS_EVENTS.SESSION.ABANDONED,
|
|
31274
|
+
properties: {
|
|
31275
|
+
session_duration_ms: sessionManager.getSessionDuration(),
|
|
31276
|
+
post_type: postType,
|
|
31277
|
+
content_length: contentLength,
|
|
31278
|
+
has_unsaved_changes: hasUnsavedChanges,
|
|
31279
|
+
abandon_reason: abandonReason,
|
|
31280
|
+
// Include user history if provided
|
|
31281
|
+
...userHistoryData && {
|
|
31282
|
+
previous_abandon_count: userHistoryData.previous_abandon_count,
|
|
31283
|
+
previous_publish_count: userHistoryData.previous_publish_count,
|
|
31284
|
+
time_since_last_publish_ms: userHistoryData.time_since_last_publish_ms,
|
|
31285
|
+
is_returning_user: userHistoryData.is_returning_user
|
|
31286
|
+
}
|
|
31287
|
+
}
|
|
31210
31288
|
});
|
|
31211
31289
|
sessionManager.endSession("abandoned");
|
|
31212
31290
|
},
|
|
31213
31291
|
[trackEvent, sessionManager]
|
|
31214
31292
|
);
|
|
31215
31293
|
const trackTabSwitch = React.useCallback(
|
|
31216
|
-
(oldTab, newTab) => {
|
|
31217
|
-
trackEvent(
|
|
31218
|
-
|
|
31219
|
-
|
|
31220
|
-
|
|
31294
|
+
({ oldTab, newTab }) => {
|
|
31295
|
+
trackEvent({
|
|
31296
|
+
name: ANALYTICS_EVENTS.EDITOR.FOCUSED,
|
|
31297
|
+
properties: {
|
|
31298
|
+
from_tab: oldTab,
|
|
31299
|
+
to_tab: newTab
|
|
31300
|
+
}
|
|
31221
31301
|
});
|
|
31222
31302
|
},
|
|
31223
|
-
[trackEvent
|
|
31303
|
+
[trackEvent]
|
|
31224
31304
|
);
|
|
31225
31305
|
const trackEditorFocus = React.useCallback(
|
|
31226
|
-
(context) => {
|
|
31227
|
-
trackEvent(
|
|
31228
|
-
|
|
31229
|
-
|
|
31306
|
+
({ context }) => {
|
|
31307
|
+
trackEvent({
|
|
31308
|
+
name: ANALYTICS_EVENTS.EDITOR.FOCUSED,
|
|
31309
|
+
properties: {
|
|
31310
|
+
context,
|
|
31311
|
+
editor_type: editorTab
|
|
31312
|
+
}
|
|
31230
31313
|
});
|
|
31231
31314
|
},
|
|
31232
31315
|
[trackEvent, editorTab]
|
|
@@ -31260,19 +31343,91 @@ function useAnalytics({ editorTab, config }) {
|
|
|
31260
31343
|
]
|
|
31261
31344
|
);
|
|
31262
31345
|
}
|
|
31346
|
+
const STORAGE_KEY = "pb_user_history";
|
|
31347
|
+
class UserHistoryTracker {
|
|
31348
|
+
history;
|
|
31349
|
+
constructor() {
|
|
31350
|
+
this.history = this.loadHistory();
|
|
31351
|
+
}
|
|
31352
|
+
loadHistory() {
|
|
31353
|
+
try {
|
|
31354
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
31355
|
+
if (stored) {
|
|
31356
|
+
return JSON.parse(stored);
|
|
31357
|
+
}
|
|
31358
|
+
} catch (error) {
|
|
31359
|
+
}
|
|
31360
|
+
return {
|
|
31361
|
+
previous_abandon_count: 0,
|
|
31362
|
+
previous_publish_count: 0,
|
|
31363
|
+
last_publish_timestamp: null,
|
|
31364
|
+
last_abandon_timestamp: null,
|
|
31365
|
+
first_session_timestamp: Date.now()
|
|
31366
|
+
};
|
|
31367
|
+
}
|
|
31368
|
+
saveHistory() {
|
|
31369
|
+
try {
|
|
31370
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.history));
|
|
31371
|
+
} catch (error) {
|
|
31372
|
+
}
|
|
31373
|
+
}
|
|
31374
|
+
/**
|
|
31375
|
+
* Record a successful publish
|
|
31376
|
+
*/
|
|
31377
|
+
recordPublish() {
|
|
31378
|
+
this.history.previous_publish_count += 1;
|
|
31379
|
+
this.history.last_publish_timestamp = Date.now();
|
|
31380
|
+
this.saveHistory();
|
|
31381
|
+
}
|
|
31382
|
+
/**
|
|
31383
|
+
* Record an abandonment
|
|
31384
|
+
*/
|
|
31385
|
+
recordAbandon() {
|
|
31386
|
+
this.history.previous_abandon_count += 1;
|
|
31387
|
+
this.history.last_abandon_timestamp = Date.now();
|
|
31388
|
+
this.saveHistory();
|
|
31389
|
+
}
|
|
31390
|
+
/**
|
|
31391
|
+
* Get current user history for analytics
|
|
31392
|
+
*/
|
|
31393
|
+
getHistory() {
|
|
31394
|
+
const now2 = Date.now();
|
|
31395
|
+
const daysSinceFirstSession = Math.floor(
|
|
31396
|
+
(now2 - this.history.first_session_timestamp) / (1e3 * 60 * 60 * 24)
|
|
31397
|
+
);
|
|
31398
|
+
return {
|
|
31399
|
+
previous_abandon_count: this.history.previous_abandon_count,
|
|
31400
|
+
previous_publish_count: this.history.previous_publish_count,
|
|
31401
|
+
time_since_last_publish_ms: this.history.last_publish_timestamp ? now2 - this.history.last_publish_timestamp : null,
|
|
31402
|
+
is_returning_user: daysSinceFirstSession > 0.5,
|
|
31403
|
+
days_since_first_session: daysSinceFirstSession
|
|
31404
|
+
};
|
|
31405
|
+
}
|
|
31406
|
+
/**
|
|
31407
|
+
* Clear history (for testing or user request)
|
|
31408
|
+
*/
|
|
31409
|
+
clearHistory() {
|
|
31410
|
+
localStorage.removeItem(STORAGE_KEY);
|
|
31411
|
+
this.history = {
|
|
31412
|
+
previous_abandon_count: 0,
|
|
31413
|
+
previous_publish_count: 0,
|
|
31414
|
+
last_publish_timestamp: null,
|
|
31415
|
+
last_abandon_timestamp: null,
|
|
31416
|
+
first_session_timestamp: Date.now()
|
|
31417
|
+
};
|
|
31418
|
+
}
|
|
31419
|
+
}
|
|
31263
31420
|
function useEditorAnalytics({
|
|
31264
31421
|
editor,
|
|
31265
31422
|
editorType,
|
|
31266
31423
|
context,
|
|
31267
31424
|
idleTimeout = 3e5,
|
|
31268
|
-
// 5 minutes
|
|
31269
31425
|
trackBlur = false
|
|
31270
|
-
// Default: don't track every blur
|
|
31271
31426
|
}) {
|
|
31272
31427
|
const analytics = useAnalytics({
|
|
31273
31428
|
editorTab: editorType,
|
|
31274
31429
|
config: {
|
|
31275
|
-
debug:
|
|
31430
|
+
debug: true,
|
|
31276
31431
|
enabled: true
|
|
31277
31432
|
}
|
|
31278
31433
|
});
|
|
@@ -31280,6 +31435,7 @@ function useEditorAnalytics({
|
|
|
31280
31435
|
const idleTimer = React.useRef();
|
|
31281
31436
|
const hasFocusedOnce = React.useRef(false);
|
|
31282
31437
|
const hasAbandonedSession = React.useRef(false);
|
|
31438
|
+
const userHistory = React.useRef(new UserHistoryTracker()).current;
|
|
31283
31439
|
const getEditorMetrics = React.useCallback(() => {
|
|
31284
31440
|
if (!editor) return null;
|
|
31285
31441
|
const json = editor.getJSON();
|
|
@@ -31319,7 +31475,6 @@ function useEditorAnalytics({
|
|
|
31319
31475
|
linkCount,
|
|
31320
31476
|
formattingFeatures: Array.from(formattingFeatures),
|
|
31321
31477
|
hasUnsavedChanges: editor.state.doc.content.size > 2,
|
|
31322
|
-
// Has content beyond empty doc
|
|
31323
31478
|
isEmpty: editor.isEmpty
|
|
31324
31479
|
};
|
|
31325
31480
|
}, [editor, analytics]);
|
|
@@ -31330,16 +31485,29 @@ function useEditorAnalytics({
|
|
|
31330
31485
|
idleTimer.current = setTimeout(() => {
|
|
31331
31486
|
const metrics = getEditorMetrics();
|
|
31332
31487
|
if (metrics && !metrics.isEmpty) {
|
|
31333
|
-
|
|
31488
|
+
const history = userHistory.getHistory();
|
|
31489
|
+
analytics.trackAbandon({
|
|
31490
|
+
contentLength: metrics.characterCount,
|
|
31491
|
+
hasUnsavedChanges: metrics.hasUnsavedChanges,
|
|
31492
|
+
abandonReason: "idle_timeout",
|
|
31493
|
+
postType: void 0,
|
|
31494
|
+
userHistoryData: {
|
|
31495
|
+
previous_abandon_count: history.previous_abandon_count,
|
|
31496
|
+
previous_publish_count: history.previous_publish_count,
|
|
31497
|
+
time_since_last_publish_ms: history.time_since_last_publish_ms,
|
|
31498
|
+
is_returning_user: history.is_returning_user
|
|
31499
|
+
}
|
|
31500
|
+
});
|
|
31501
|
+
userHistory.recordAbandon();
|
|
31334
31502
|
hasAbandonedSession.current = true;
|
|
31335
31503
|
}
|
|
31336
31504
|
}, idleTimeout);
|
|
31337
|
-
}, [editor, idleTimeout, analytics, getEditorMetrics]);
|
|
31505
|
+
}, [editor, idleTimeout, analytics, getEditorMetrics, userHistory]);
|
|
31338
31506
|
React.useEffect(() => {
|
|
31339
31507
|
if (!editor) return;
|
|
31340
31508
|
const handleFocus = () => {
|
|
31341
31509
|
if (!hasFocusedOnce.current) {
|
|
31342
|
-
analytics.trackEditorFocus(context);
|
|
31510
|
+
analytics.trackEditorFocus({ context });
|
|
31343
31511
|
hasFocusedOnce.current = true;
|
|
31344
31512
|
}
|
|
31345
31513
|
resetIdleTimer();
|
|
@@ -31350,9 +31518,12 @@ function useEditorAnalytics({
|
|
|
31350
31518
|
if (trackBlur) {
|
|
31351
31519
|
const metrics = getEditorMetrics();
|
|
31352
31520
|
if (metrics && !metrics.isEmpty) {
|
|
31353
|
-
analytics.trackEvent(
|
|
31354
|
-
|
|
31355
|
-
|
|
31521
|
+
analytics.trackEvent({
|
|
31522
|
+
name: ANALYTICS_EVENTS.EDITOR.BLURRED,
|
|
31523
|
+
properties: {
|
|
31524
|
+
content_length: metrics.characterCount,
|
|
31525
|
+
session_duration_ms: Date.now() - lastActivity.current
|
|
31526
|
+
}
|
|
31356
31527
|
});
|
|
31357
31528
|
}
|
|
31358
31529
|
}
|
|
@@ -31371,7 +31542,20 @@ function useEditorAnalytics({
|
|
|
31371
31542
|
if (hasAbandonedSession.current) return;
|
|
31372
31543
|
const metrics = getEditorMetrics();
|
|
31373
31544
|
if (metrics && !metrics.isEmpty) {
|
|
31374
|
-
|
|
31545
|
+
const history = userHistory.getHistory();
|
|
31546
|
+
analytics.trackAbandon({
|
|
31547
|
+
contentLength: metrics.characterCount,
|
|
31548
|
+
hasUnsavedChanges: metrics.hasUnsavedChanges,
|
|
31549
|
+
abandonReason: "navigation",
|
|
31550
|
+
postType: void 0,
|
|
31551
|
+
userHistoryData: {
|
|
31552
|
+
previous_abandon_count: history.previous_abandon_count,
|
|
31553
|
+
previous_publish_count: history.previous_publish_count,
|
|
31554
|
+
time_since_last_publish_ms: history.time_since_last_publish_ms,
|
|
31555
|
+
is_returning_user: history.is_returning_user
|
|
31556
|
+
}
|
|
31557
|
+
});
|
|
31558
|
+
userHistory.recordAbandon();
|
|
31375
31559
|
hasAbandonedSession.current = true;
|
|
31376
31560
|
}
|
|
31377
31561
|
};
|
|
@@ -31382,46 +31566,76 @@ function useEditorAnalytics({
|
|
|
31382
31566
|
clearTimeout(idleTimer.current);
|
|
31383
31567
|
}
|
|
31384
31568
|
};
|
|
31385
|
-
}, [editor, analytics, getEditorMetrics]);
|
|
31569
|
+
}, [editor, analytics, getEditorMetrics, userHistory]);
|
|
31386
31570
|
const trackFeature = React.useCallback(
|
|
31387
|
-
(featureName) => {
|
|
31388
|
-
analytics.trackFeature(featureName);
|
|
31571
|
+
({ featureName }) => {
|
|
31572
|
+
analytics.trackFeature({ featureName });
|
|
31389
31573
|
resetIdleTimer();
|
|
31390
31574
|
},
|
|
31391
31575
|
[analytics, resetIdleTimer]
|
|
31392
31576
|
);
|
|
31393
31577
|
const trackPublish = React.useCallback(
|
|
31394
|
-
(status, failureReason) => {
|
|
31578
|
+
({ sessionId, groupId, postId, status, failureReason, postType }) => {
|
|
31395
31579
|
const metrics = getEditorMetrics();
|
|
31396
31580
|
if (!metrics) return;
|
|
31397
|
-
|
|
31398
|
-
|
|
31399
|
-
|
|
31400
|
-
|
|
31401
|
-
|
|
31402
|
-
|
|
31403
|
-
|
|
31581
|
+
const history = userHistory.getHistory();
|
|
31582
|
+
analytics.trackPublish({
|
|
31583
|
+
status,
|
|
31584
|
+
data: {
|
|
31585
|
+
...sessionId ? { session_id: sessionId } : {},
|
|
31586
|
+
group_id: groupId,
|
|
31587
|
+
post_id: postId,
|
|
31588
|
+
post_type: postType,
|
|
31589
|
+
word_count: metrics.wordCount,
|
|
31590
|
+
character_count: metrics.characterCount,
|
|
31591
|
+
media_count: metrics.mediaCount,
|
|
31592
|
+
link_count: metrics.linkCount,
|
|
31593
|
+
formatting_features: metrics.formattingFeatures,
|
|
31594
|
+
failure_reason: failureReason,
|
|
31595
|
+
// Include user history
|
|
31596
|
+
previous_abandon_count: history.previous_abandon_count,
|
|
31597
|
+
previous_publish_count: history.previous_publish_count,
|
|
31598
|
+
time_since_last_publish_ms: history.time_since_last_publish_ms,
|
|
31599
|
+
is_returning_user: history.is_returning_user
|
|
31600
|
+
}
|
|
31404
31601
|
});
|
|
31405
31602
|
if (status === "success") {
|
|
31603
|
+
userHistory.recordPublish();
|
|
31406
31604
|
hasAbandonedSession.current = true;
|
|
31407
31605
|
}
|
|
31408
31606
|
},
|
|
31409
|
-
[analytics, getEditorMetrics]
|
|
31607
|
+
[analytics, getEditorMetrics, userHistory]
|
|
31410
31608
|
);
|
|
31411
31609
|
const trackExplicitAbandon = React.useCallback(() => {
|
|
31412
31610
|
if (hasAbandonedSession.current) return;
|
|
31413
31611
|
const metrics = getEditorMetrics();
|
|
31414
31612
|
if (metrics && !metrics.isEmpty) {
|
|
31415
|
-
|
|
31613
|
+
const history = userHistory.getHistory();
|
|
31614
|
+
analytics.trackAbandon({
|
|
31615
|
+
contentLength: metrics.characterCount,
|
|
31616
|
+
hasUnsavedChanges: metrics.hasUnsavedChanges,
|
|
31617
|
+
abandonReason: "user_closed",
|
|
31618
|
+
postType: void 0,
|
|
31619
|
+
userHistoryData: {
|
|
31620
|
+
previous_abandon_count: history.previous_abandon_count,
|
|
31621
|
+
previous_publish_count: history.previous_publish_count,
|
|
31622
|
+
time_since_last_publish_ms: history.time_since_last_publish_ms,
|
|
31623
|
+
is_returning_user: history.is_returning_user
|
|
31624
|
+
}
|
|
31625
|
+
});
|
|
31626
|
+
userHistory.recordAbandon();
|
|
31416
31627
|
hasAbandonedSession.current = true;
|
|
31417
31628
|
}
|
|
31418
|
-
}, [analytics, getEditorMetrics]);
|
|
31629
|
+
}, [analytics, getEditorMetrics, userHistory]);
|
|
31419
31630
|
return {
|
|
31420
31631
|
trackFeature,
|
|
31421
31632
|
trackPublish,
|
|
31422
31633
|
trackExplicitAbandon,
|
|
31423
31634
|
trackTabSwitch: analytics.trackTabSwitch,
|
|
31424
|
-
getEditorMetrics
|
|
31635
|
+
getEditorMetrics,
|
|
31636
|
+
// Expose user history for debugging
|
|
31637
|
+
getUserHistory: () => userHistory.getHistory(),
|
|
31638
|
+
currentSessionId: analytics.getSessionId()
|
|
31425
31639
|
};
|
|
31426
31640
|
}
|
|
31427
31641
|
const PostBuilderAnalyticsProvider = ({
|
|
@@ -31487,56 +31701,66 @@ const PostBuilderEditor = ({
|
|
|
31487
31701
|
isSubmitting,
|
|
31488
31702
|
clearOnSuccess
|
|
31489
31703
|
}
|
|
31490
|
-
) : (
|
|
31491
|
-
|
|
31492
|
-
|
|
31493
|
-
|
|
31494
|
-
|
|
31495
|
-
|
|
31496
|
-
|
|
31497
|
-
|
|
31498
|
-
|
|
31499
|
-
|
|
31500
|
-
|
|
31501
|
-
|
|
31502
|
-
|
|
31503
|
-
|
|
31504
|
-
|
|
31505
|
-
// </DialogClose>
|
|
31506
|
-
// </div>
|
|
31507
|
-
// )}
|
|
31508
|
-
// </DialogHeader>
|
|
31509
|
-
// <PostBuilderEditorInstance
|
|
31510
|
-
// editor={editor}
|
|
31511
|
-
// actions={actions}
|
|
31512
|
-
// editorTab={editorTab}
|
|
31513
|
-
// onSwitchEditor={setEditorTab}
|
|
31514
|
-
// isSubmitting={isSubmitting}
|
|
31515
|
-
// onCreatePost={onCreatePost}
|
|
31516
|
-
// clearOnSuccess={clearOnSuccess}
|
|
31517
|
-
// />
|
|
31518
|
-
// </DialogContent>
|
|
31519
|
-
// </Dialog>
|
|
31520
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "prose-blockquote: flex-1 flex flex-col space-y-3 max-w-full max-h-[calc(100dvh-7rem)]", children: [
|
|
31521
|
-
!hideGroupSelector && /* @__PURE__ */ jsxRuntime.jsx(GroupSelector, { user, store }),
|
|
31522
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
31523
|
-
PostBuilderEditorInstance,
|
|
31524
|
-
{
|
|
31525
|
-
editor,
|
|
31526
|
-
actions,
|
|
31527
|
-
editorTab,
|
|
31528
|
-
onSwitchEditor: setEditorTab,
|
|
31529
|
-
isSubmitting,
|
|
31530
|
-
onCreatePost,
|
|
31531
|
-
clearOnSuccess
|
|
31532
|
-
}
|
|
31533
|
-
)
|
|
31534
|
-
] })
|
|
31535
|
-
) }),
|
|
31704
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "prose-blockquote: flex-1 flex flex-col space-y-3 max-w-full max-h-[calc(100dvh-7rem)]", children: [
|
|
31705
|
+
!hideGroupSelector && /* @__PURE__ */ jsxRuntime.jsx(GroupSelector, { user, store }),
|
|
31706
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
31707
|
+
PostBuilderEditorInstance,
|
|
31708
|
+
{
|
|
31709
|
+
editor,
|
|
31710
|
+
actions,
|
|
31711
|
+
editorTab,
|
|
31712
|
+
onSwitchEditor: setEditorTab,
|
|
31713
|
+
isSubmitting,
|
|
31714
|
+
onCreatePost,
|
|
31715
|
+
clearOnSuccess
|
|
31716
|
+
}
|
|
31717
|
+
)
|
|
31718
|
+
] }) }),
|
|
31536
31719
|
/* @__PURE__ */ jsxRuntime.jsx(Toaster2, { position: "top-center" })
|
|
31537
31720
|
] })
|
|
31538
31721
|
}
|
|
31539
31722
|
);
|
|
31540
31723
|
};
|
|
31724
|
+
const PostBuilderProvider = ({
|
|
31725
|
+
children,
|
|
31726
|
+
apiBaseURL,
|
|
31727
|
+
authToken,
|
|
31728
|
+
toI18N,
|
|
31729
|
+
i18nKeys,
|
|
31730
|
+
logEvent
|
|
31731
|
+
}) => {
|
|
31732
|
+
const t = React.useCallback(
|
|
31733
|
+
(key, fallback) => {
|
|
31734
|
+
const message = toI18N(i18nKeys[key]);
|
|
31735
|
+
if (message) return message;
|
|
31736
|
+
return fallback || key;
|
|
31737
|
+
},
|
|
31738
|
+
[toI18N, i18nKeys]
|
|
31739
|
+
);
|
|
31740
|
+
const api = React.useMemo(() => {
|
|
31741
|
+
const core2 = new CoreApi(apiBaseURL.core, authToken, toI18N);
|
|
31742
|
+
const mfs = new MFSApi(apiBaseURL.mfs, authToken, toI18N);
|
|
31743
|
+
const fileStore = new FilestoreApi(apiBaseURL.fileStore, authToken, toI18N);
|
|
31744
|
+
core2.initApi();
|
|
31745
|
+
mfs.initApi();
|
|
31746
|
+
fileStore.initApi();
|
|
31747
|
+
return {
|
|
31748
|
+
core: core2,
|
|
31749
|
+
mfs,
|
|
31750
|
+
fileStore
|
|
31751
|
+
};
|
|
31752
|
+
}, [authToken, apiBaseURL, toI18N]);
|
|
31753
|
+
const value = React.useMemo(() => {
|
|
31754
|
+
return {
|
|
31755
|
+
authToken,
|
|
31756
|
+
t,
|
|
31757
|
+
i18nKeys,
|
|
31758
|
+
api,
|
|
31759
|
+
logEvent
|
|
31760
|
+
};
|
|
31761
|
+
}, [authToken, t, i18nKeys, api, logEvent]);
|
|
31762
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PostBuilderContext.Provider, { value, children });
|
|
31763
|
+
};
|
|
31541
31764
|
exports.PostBuilderEditor = PostBuilderEditor;
|
|
31765
|
+
exports.PostBuilderEvents = PostBuilderEvents;
|
|
31542
31766
|
exports.PostBuilderProvider = PostBuilderProvider;
|