@select-org/select-post-builder 1.1.1 → 1.1.3
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 +585 -351
- package/dist/post-builder.js +586 -352
- 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,6 +20770,79 @@ 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
20848
|
if (typeof window === "undefined" || typeof localStorage === "undefined" || !editor || editor.isEmpty)
|
|
@@ -21096,11 +21099,9 @@ var Progress$1 = React__namespace.forwardRef(
|
|
|
21096
21099
|
...progressProps
|
|
21097
21100
|
} = props;
|
|
21098
21101
|
if ((maxProp || maxProp === 0) && !isValidMaxNumber(maxProp)) {
|
|
21099
|
-
console.error(getInvalidMaxError(`${maxProp}`, "Progress"));
|
|
21100
21102
|
}
|
|
21101
21103
|
const max2 = isValidMaxNumber(maxProp) ? maxProp : DEFAULT_MAX;
|
|
21102
21104
|
if (valueProp !== null && !isValidValueNumber(valueProp, max2)) {
|
|
21103
|
-
console.error(getInvalidValueError(`${valueProp}`, "Progress"));
|
|
21104
21105
|
}
|
|
21105
21106
|
const value = isValidValueNumber(valueProp, max2) ? valueProp : null;
|
|
21106
21107
|
const valueLabel = isNumber(value) ? getValueLabel(value, max2) : void 0;
|
|
@@ -21420,13 +21421,7 @@ const createUpdateMarkByUidCommand = (markName) => {
|
|
|
21420
21421
|
state: state2,
|
|
21421
21422
|
dispatch
|
|
21422
21423
|
}) => {
|
|
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
21424
|
if (!dispatch) {
|
|
21429
|
-
console.log("No dispatch, returning false");
|
|
21430
21425
|
return false;
|
|
21431
21426
|
}
|
|
21432
21427
|
const { doc, schema } = state2;
|
|
@@ -21436,13 +21431,6 @@ const createUpdateMarkByUidCommand = (markName) => {
|
|
|
21436
21431
|
doc.descendants((node, pos) => {
|
|
21437
21432
|
if (node.isText && node.marks?.length) {
|
|
21438
21433
|
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
21434
|
if (mark.type.name === markName && mark.attrs.uid === uid) {
|
|
21447
21435
|
positions.push({
|
|
21448
21436
|
from: pos,
|
|
@@ -21450,33 +21438,21 @@ const createUpdateMarkByUidCommand = (markName) => {
|
|
|
21450
21438
|
mark
|
|
21451
21439
|
});
|
|
21452
21440
|
found2 = true;
|
|
21453
|
-
console.log("Found matching mark at:", { from: pos, to: pos + node.nodeSize });
|
|
21454
21441
|
}
|
|
21455
21442
|
});
|
|
21456
21443
|
}
|
|
21457
21444
|
});
|
|
21458
|
-
console.log("Total positions found:", positions.length);
|
|
21459
|
-
console.log("Positions:", positions);
|
|
21460
21445
|
if (found2) {
|
|
21461
21446
|
positions.forEach(({ from, to, mark }) => {
|
|
21462
21447
|
const newAttrs = { ...mark.attrs, ...attrs };
|
|
21463
21448
|
const markType = schema.marks[markName];
|
|
21464
|
-
console.log("Applying update:", { from, to, oldAttrs: mark.attrs, newAttrs });
|
|
21465
21449
|
if (markType) {
|
|
21466
|
-
console.log("Before removeMark - tr.doc:", tr.doc.toJSON());
|
|
21467
21450
|
tr = tr.removeMark(from, to, markType);
|
|
21468
|
-
console.log("After removeMark - tr.doc:", tr.doc.toJSON());
|
|
21469
21451
|
tr = tr.addMark(from, to, markType.create(newAttrs));
|
|
21470
|
-
console.log("After addMark - tr.doc:", tr.doc.toJSON());
|
|
21471
21452
|
}
|
|
21472
21453
|
});
|
|
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
21454
|
dispatch(tr);
|
|
21477
|
-
console.log("Transaction dispatched successfully");
|
|
21478
21455
|
}
|
|
21479
|
-
console.log("=== UPDATE MARK COMMAND END ===");
|
|
21480
21456
|
return found2;
|
|
21481
21457
|
};
|
|
21482
21458
|
};
|
|
@@ -22494,7 +22470,6 @@ let warnedAboutTextSelection = false;
|
|
|
22494
22470
|
function checkTextSelection($pos) {
|
|
22495
22471
|
if (!warnedAboutTextSelection && !$pos.parent.inlineContent) {
|
|
22496
22472
|
warnedAboutTextSelection = true;
|
|
22497
|
-
console["warn"]("TextSelection endpoint not pointing into a node with inline content (" + $pos.parent.type.name + ")");
|
|
22498
22473
|
}
|
|
22499
22474
|
}
|
|
22500
22475
|
class TextSelection extends Selection {
|
|
@@ -23219,7 +23194,6 @@ const PollCreator = ({ choices, onChange }) => {
|
|
|
23219
23194
|
const result = await fileStore.uploadImage(file);
|
|
23220
23195
|
return createPollMediaOption(result, startIndex + index2);
|
|
23221
23196
|
} catch (error) {
|
|
23222
|
-
console.error("Upload failed for", file.name, error);
|
|
23223
23197
|
return null;
|
|
23224
23198
|
}
|
|
23225
23199
|
});
|
|
@@ -23239,7 +23213,6 @@ const PollCreator = ({ choices, onChange }) => {
|
|
|
23239
23213
|
return final;
|
|
23240
23214
|
});
|
|
23241
23215
|
} catch (error) {
|
|
23242
|
-
console.error("Unexpected error during file upload:", error);
|
|
23243
23216
|
setInternalChoices((current) => {
|
|
23244
23217
|
const withoutPlaceholders = current.filter((c) => !isPlaceholder(c));
|
|
23245
23218
|
setTimeout(() => {
|
|
@@ -23272,7 +23245,6 @@ const PollCreator = ({ choices, onChange }) => {
|
|
|
23272
23245
|
return updated;
|
|
23273
23246
|
});
|
|
23274
23247
|
} catch (error) {
|
|
23275
|
-
console.error("URL upload failed:", error);
|
|
23276
23248
|
setInternalChoices((current) => {
|
|
23277
23249
|
const withoutPlaceholder = current.filter((c) => !isPlaceholder(c));
|
|
23278
23250
|
setTimeout(() => {
|
|
@@ -23813,7 +23785,6 @@ const LinkMarkView = ({ mark, editor }) => {
|
|
|
23813
23785
|
};
|
|
23814
23786
|
const handleUpdateLink = (link, text2, uid, previewPayload) => {
|
|
23815
23787
|
if (!editor.view) return;
|
|
23816
|
-
console.log("UPDATE LINK IN VIEW::", { text: text2 });
|
|
23817
23788
|
const newText = mark?.attrs?.isLinkMode ? link : text2 || link;
|
|
23818
23789
|
if (uid) {
|
|
23819
23790
|
editor.commands.updateLink(uid, { href: link, text: newText, previewPayload });
|
|
@@ -23873,25 +23844,66 @@ const LinkMarkView = ({ mark, editor }) => {
|
|
|
23873
23844
|
)
|
|
23874
23845
|
] });
|
|
23875
23846
|
};
|
|
23847
|
+
function isValidUrlFormat(text2) {
|
|
23848
|
+
return isValidUrl(normalizeUrl(text2.trim()));
|
|
23849
|
+
}
|
|
23876
23850
|
function doesPreviewExist(editor, uid) {
|
|
23877
|
-
|
|
23878
|
-
|
|
23879
|
-
|
|
23880
|
-
|
|
23881
|
-
|
|
23882
|
-
|
|
23883
|
-
|
|
23884
|
-
|
|
23851
|
+
if (!editor || !uid) {
|
|
23852
|
+
return false;
|
|
23853
|
+
}
|
|
23854
|
+
try {
|
|
23855
|
+
let exists = false;
|
|
23856
|
+
editor.state.doc.descendants((node) => {
|
|
23857
|
+
if (node && node.type && node.type.name === "linkPreview" && node.attrs?.uid === uid) {
|
|
23858
|
+
exists = true;
|
|
23859
|
+
return false;
|
|
23860
|
+
}
|
|
23861
|
+
});
|
|
23862
|
+
return exists;
|
|
23863
|
+
} catch (err) {
|
|
23864
|
+
return false;
|
|
23865
|
+
}
|
|
23885
23866
|
}
|
|
23886
23867
|
function findExistingPreview(editor) {
|
|
23887
|
-
|
|
23888
|
-
|
|
23889
|
-
|
|
23890
|
-
|
|
23891
|
-
|
|
23868
|
+
if (!editor) {
|
|
23869
|
+
return null;
|
|
23870
|
+
}
|
|
23871
|
+
try {
|
|
23872
|
+
let result = null;
|
|
23873
|
+
editor.state.doc.descendants((node, pos) => {
|
|
23874
|
+
if (node && node.type && node.type.name === "linkPreview") {
|
|
23875
|
+
result = { node, pos };
|
|
23876
|
+
return false;
|
|
23877
|
+
}
|
|
23878
|
+
});
|
|
23879
|
+
return result;
|
|
23880
|
+
} catch (err) {
|
|
23881
|
+
return null;
|
|
23882
|
+
}
|
|
23883
|
+
}
|
|
23884
|
+
function removePreviewByUid(editor, uid) {
|
|
23885
|
+
if (!editor || !uid) {
|
|
23886
|
+
return;
|
|
23887
|
+
}
|
|
23888
|
+
try {
|
|
23889
|
+
let previewPos = null;
|
|
23890
|
+
let previewSize = 0;
|
|
23891
|
+
editor.state.doc.descendants((node, pos) => {
|
|
23892
|
+
if (node && node.type && node.type.name === "linkPreview" && node.attrs?.uid === uid) {
|
|
23893
|
+
previewPos = pos;
|
|
23894
|
+
previewSize = node.nodeSize;
|
|
23895
|
+
return false;
|
|
23896
|
+
}
|
|
23897
|
+
});
|
|
23898
|
+
if (previewPos !== null && previewSize > 0) {
|
|
23899
|
+
const tr = editor.state.tr;
|
|
23900
|
+
if (tr) {
|
|
23901
|
+
tr.delete(previewPos, Number(previewPos) + previewSize);
|
|
23902
|
+
editor.view.dispatch(tr);
|
|
23903
|
+
}
|
|
23892
23904
|
}
|
|
23893
|
-
})
|
|
23894
|
-
|
|
23905
|
+
} catch (err) {
|
|
23906
|
+
}
|
|
23895
23907
|
}
|
|
23896
23908
|
function extractBestImage(metadata) {
|
|
23897
23909
|
return metadata?.image?.high_resolution ?? metadata?.image?.url ?? metadata?.image?.thumbnail ?? metadata?.image?.placeholder ?? null;
|
|
@@ -23916,6 +23928,76 @@ function collectAllLinkMarks(state2, linkMark) {
|
|
|
23916
23928
|
});
|
|
23917
23929
|
return links;
|
|
23918
23930
|
}
|
|
23931
|
+
function syncLinkHrefWithText(newState, linkMark, editor, singlePreviewMode, pluginState) {
|
|
23932
|
+
if (!newState || !linkMark || !editor || !pluginState) {
|
|
23933
|
+
return null;
|
|
23934
|
+
}
|
|
23935
|
+
let tr = null;
|
|
23936
|
+
let hasChanges = false;
|
|
23937
|
+
try {
|
|
23938
|
+
newState.doc.descendants((node, pos) => {
|
|
23939
|
+
if (!node || !node.isText || !node.marks?.length) return;
|
|
23940
|
+
node.marks.forEach((mark) => {
|
|
23941
|
+
if (!mark || !mark.type || !mark.attrs) return;
|
|
23942
|
+
if (mark.type === linkMark && mark.attrs?.uid) {
|
|
23943
|
+
const currentText = node.text || "";
|
|
23944
|
+
const currentHref = mark.attrs.href || "";
|
|
23945
|
+
if (currentText !== currentHref) {
|
|
23946
|
+
const isValidUrl2 = isValidUrlFormat(currentText);
|
|
23947
|
+
if (!tr) {
|
|
23948
|
+
tr = newState.tr;
|
|
23949
|
+
}
|
|
23950
|
+
if (!tr) {
|
|
23951
|
+
return;
|
|
23952
|
+
}
|
|
23953
|
+
if (isValidUrl2) {
|
|
23954
|
+
const newMark = linkMark.create({
|
|
23955
|
+
...mark.attrs,
|
|
23956
|
+
href: normalizeUrl(currentText)
|
|
23957
|
+
});
|
|
23958
|
+
if (!newMark) {
|
|
23959
|
+
return;
|
|
23960
|
+
}
|
|
23961
|
+
tr = tr.removeMark(pos, pos + node.nodeSize, linkMark);
|
|
23962
|
+
tr = tr.addMark(pos, pos + node.nodeSize, newMark);
|
|
23963
|
+
hasChanges = true;
|
|
23964
|
+
pluginState.processedLinks.delete(mark.attrs.uid);
|
|
23965
|
+
if (singlePreviewMode) {
|
|
23966
|
+
queueMicrotask(() => {
|
|
23967
|
+
try {
|
|
23968
|
+
const existingPreview = findExistingPreview(editor);
|
|
23969
|
+
if (existingPreview && mark.attrs?.uid) {
|
|
23970
|
+
}
|
|
23971
|
+
} catch (err) {
|
|
23972
|
+
}
|
|
23973
|
+
});
|
|
23974
|
+
} else {
|
|
23975
|
+
}
|
|
23976
|
+
} else {
|
|
23977
|
+
tr = tr.removeMark(pos, pos + node.nodeSize, linkMark);
|
|
23978
|
+
hasChanges = true;
|
|
23979
|
+
queueMicrotask(() => {
|
|
23980
|
+
try {
|
|
23981
|
+
if (mark.attrs?.uid) {
|
|
23982
|
+
removePreviewByUid(editor, mark.attrs.uid);
|
|
23983
|
+
}
|
|
23984
|
+
} catch (err) {
|
|
23985
|
+
}
|
|
23986
|
+
});
|
|
23987
|
+
if (mark.attrs?.uid) {
|
|
23988
|
+
pluginState.processedLinks.delete(mark.attrs.uid);
|
|
23989
|
+
pluginState.resolvingLinks.delete(mark.attrs.uid);
|
|
23990
|
+
}
|
|
23991
|
+
}
|
|
23992
|
+
}
|
|
23993
|
+
}
|
|
23994
|
+
});
|
|
23995
|
+
});
|
|
23996
|
+
} catch (err) {
|
|
23997
|
+
return null;
|
|
23998
|
+
}
|
|
23999
|
+
return hasChanges ? tr : null;
|
|
24000
|
+
}
|
|
23919
24001
|
function assignUidsToLinks(newState, linkMark) {
|
|
23920
24002
|
const newUids = /* @__PURE__ */ new Map();
|
|
23921
24003
|
let tr = null;
|
|
@@ -23925,11 +24007,6 @@ function assignUidsToLinks(newState, linkMark) {
|
|
|
23925
24007
|
node.marks.forEach((mark) => {
|
|
23926
24008
|
if (mark.type === linkMark && mark.attrs?.href && !mark.attrs.uid) {
|
|
23927
24009
|
const newUid = v4();
|
|
23928
|
-
console.log("🔧 Assigning UID to autolinked URL:", {
|
|
23929
|
-
href: mark.attrs.href,
|
|
23930
|
-
uid: newUid,
|
|
23931
|
-
pos
|
|
23932
|
-
});
|
|
23933
24010
|
const newMark = linkMark.create({
|
|
23934
24011
|
...mark.attrs,
|
|
23935
24012
|
uid: newUid
|
|
@@ -23956,25 +24033,14 @@ function resolveLinkAndHandlePreview(link, options, singlePreviewMode, pluginSta
|
|
|
23956
24033
|
const { api, editor } = options;
|
|
23957
24034
|
const mediaGroup = findByType(editor?.getJSON(), "mediaGroup");
|
|
23958
24035
|
if (!api) {
|
|
23959
|
-
console.warn("⚠️ No API provided to resolve link");
|
|
23960
24036
|
return;
|
|
23961
24037
|
}
|
|
23962
24038
|
if (singlePreviewMode && mediaGroup.length >= 1) return;
|
|
23963
24039
|
pluginState.resolvingLinks.add(link.uid);
|
|
23964
|
-
console.log("🌐 Resolving link metadata:", {
|
|
23965
|
-
uid: link.uid,
|
|
23966
|
-
href: link.href,
|
|
23967
|
-
singlePreviewMode
|
|
23968
|
-
});
|
|
23969
24040
|
api.resolveUrl(normalizeUrl(link.href)).then((metadata) => {
|
|
23970
24041
|
pluginState.resolvingLinks.delete(link.uid);
|
|
23971
24042
|
pluginState.processedLinks.add(link.uid);
|
|
23972
|
-
console.log("✅ Link metadata resolved:", {
|
|
23973
|
-
uid: link.uid,
|
|
23974
|
-
metadata
|
|
23975
|
-
});
|
|
23976
24043
|
if (!metadata) {
|
|
23977
|
-
console.warn("⚠️ No metadata returned for:", link.href);
|
|
23978
24044
|
return;
|
|
23979
24045
|
}
|
|
23980
24046
|
const previewData = {
|
|
@@ -23989,13 +24055,11 @@ function resolveLinkAndHandlePreview(link, options, singlePreviewMode, pluginSta
|
|
|
23989
24055
|
if (singlePreviewMode) {
|
|
23990
24056
|
const existingPreview = findExistingPreview(editor);
|
|
23991
24057
|
if (existingPreview) {
|
|
23992
|
-
console.log("🔄 Updating existing preview in single mode");
|
|
23993
24058
|
const { pos } = existingPreview;
|
|
23994
24059
|
const tr = editor.state.tr;
|
|
23995
24060
|
tr.setNodeMarkup(pos, void 0, previewData);
|
|
23996
24061
|
editor.view.dispatch(tr);
|
|
23997
24062
|
} else {
|
|
23998
|
-
console.log("➕ Creating first preview in single mode");
|
|
23999
24063
|
editor.commands.setLinkPreview(previewData);
|
|
24000
24064
|
}
|
|
24001
24065
|
editor.commands.updateLinkByUid(link.uid, {
|
|
@@ -24003,16 +24067,12 @@ function resolveLinkAndHandlePreview(link, options, singlePreviewMode, pluginSta
|
|
|
24003
24067
|
});
|
|
24004
24068
|
} else {
|
|
24005
24069
|
if (!doesPreviewExist(editor, link.uid)) {
|
|
24006
|
-
console.log("➕ Creating new preview in multi mode");
|
|
24007
24070
|
editor.chain().updateLinkByUid(link.uid, {
|
|
24008
24071
|
previewPayload: convertLinkMetaToPreviewItem(metadata)
|
|
24009
24072
|
}).setLinkPreview(previewData).run();
|
|
24010
|
-
} else {
|
|
24011
|
-
console.log("⏭️ Preview already exists, skipping");
|
|
24012
24073
|
}
|
|
24013
24074
|
}
|
|
24014
24075
|
}).catch((err) => {
|
|
24015
|
-
console.error("❌ Failed to resolve link:", err);
|
|
24016
24076
|
pluginState.resolvingLinks.delete(link.uid);
|
|
24017
24077
|
});
|
|
24018
24078
|
}
|
|
@@ -24022,10 +24082,6 @@ function createLinkAutoResolvePlugin(options, singlePreviewMode = false) {
|
|
|
24022
24082
|
key: pluginKey,
|
|
24023
24083
|
state: {
|
|
24024
24084
|
init() {
|
|
24025
|
-
console.log("🔌 LinkAutoResolve plugin initialized", {
|
|
24026
|
-
singlePreviewMode,
|
|
24027
|
-
hasApi: !!options.api
|
|
24028
|
-
});
|
|
24029
24085
|
return {
|
|
24030
24086
|
resolvingLinks: /* @__PURE__ */ new Set(),
|
|
24031
24087
|
processedLinks: /* @__PURE__ */ new Set()
|
|
@@ -24055,27 +24111,22 @@ function createLinkAutoResolvePlugin(options, singlePreviewMode = false) {
|
|
|
24055
24111
|
appendTransaction: (transactions, oldState, newState) => {
|
|
24056
24112
|
const linkMark = newState.schema.marks["customLink"];
|
|
24057
24113
|
if (!linkMark) {
|
|
24058
|
-
console.warn("⚠️ customLink mark not found in schema");
|
|
24059
24114
|
return null;
|
|
24060
24115
|
}
|
|
24061
24116
|
if (!transactions.some((tr) => tr.docChanged)) {
|
|
24062
24117
|
return null;
|
|
24063
24118
|
}
|
|
24064
|
-
console.log("📝 Document changed, checking for new links...");
|
|
24065
24119
|
const pluginState = pluginKey.getState(newState);
|
|
24120
|
+
if (!pluginState) {
|
|
24121
|
+
return null;
|
|
24122
|
+
}
|
|
24123
|
+
const syncTr = singlePreviewMode ? syncLinkHrefWithText(newState, linkMark, options.editor, singlePreviewMode, pluginState) : null;
|
|
24066
24124
|
const oldLinks = collectAllLinkMarks(oldState, linkMark);
|
|
24067
24125
|
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
24126
|
const { tr: uidTr, newUids } = assignUidsToLinks(newState, linkMark);
|
|
24075
24127
|
const linksToResolve = [];
|
|
24076
24128
|
newUids.forEach((linkData) => {
|
|
24077
24129
|
if (!pluginState.processedLinks.has(linkData.uid) && !pluginState.resolvingLinks.has(linkData.uid)) {
|
|
24078
|
-
console.log("🆕 New autolinked URL detected:", linkData);
|
|
24079
24130
|
linksToResolve.push(linkData);
|
|
24080
24131
|
}
|
|
24081
24132
|
});
|
|
@@ -24088,21 +24139,33 @@ function createLinkAutoResolvePlugin(options, singlePreviewMode = false) {
|
|
|
24088
24139
|
return;
|
|
24089
24140
|
}
|
|
24090
24141
|
if (!oldLinks.has(uid)) {
|
|
24091
|
-
console.log("🆕 New link detected (with UID):", linkData);
|
|
24092
24142
|
linksToResolve.push(linkData);
|
|
24093
24143
|
}
|
|
24094
24144
|
});
|
|
24095
24145
|
if (linksToResolve.length > 0) {
|
|
24096
|
-
console.log("🚀 Processing", linksToResolve.length, "new link(s)");
|
|
24097
24146
|
queueMicrotask(() => {
|
|
24098
24147
|
linksToResolve.forEach((link) => {
|
|
24099
24148
|
resolveLinkAndHandlePreview(link, options, singlePreviewMode, pluginState);
|
|
24100
24149
|
});
|
|
24101
24150
|
});
|
|
24102
|
-
} else {
|
|
24103
|
-
console.log("✓ No new links to process");
|
|
24104
24151
|
}
|
|
24105
|
-
|
|
24152
|
+
if (syncTr && uidTr) {
|
|
24153
|
+
try {
|
|
24154
|
+
uidTr.steps.forEach((step, i) => {
|
|
24155
|
+
if (step && syncTr) {
|
|
24156
|
+
syncTr.step(step);
|
|
24157
|
+
const map = uidTr.mapping.maps[i];
|
|
24158
|
+
if (map) {
|
|
24159
|
+
syncTr.mapping.appendMap(map);
|
|
24160
|
+
}
|
|
24161
|
+
}
|
|
24162
|
+
});
|
|
24163
|
+
return syncTr;
|
|
24164
|
+
} catch (err) {
|
|
24165
|
+
return syncTr;
|
|
24166
|
+
}
|
|
24167
|
+
}
|
|
24168
|
+
return syncTr ?? uidTr ?? null;
|
|
24106
24169
|
}
|
|
24107
24170
|
});
|
|
24108
24171
|
}
|
|
@@ -24198,7 +24261,6 @@ const CustomLink = Link__default.default.extend({
|
|
|
24198
24261
|
this?.options?.api?.resolveUrl(normalizeUrl(href))?.then((metadata) => {
|
|
24199
24262
|
if (metadata) {
|
|
24200
24263
|
const previewPayload = convertLinkMetaToPreviewItem(metadata);
|
|
24201
|
-
console.log({ href, text: text2 });
|
|
24202
24264
|
editor?.chain()?.updateLinkByUid(uid, { href, text: text2, previewPayload })?.updateLinkPreviewByUid(uid, {
|
|
24203
24265
|
// Now using correct UID
|
|
24204
24266
|
loading: false,
|
|
@@ -24257,7 +24319,6 @@ const CustomLink = Link__default.default.extend({
|
|
|
24257
24319
|
if (attrs.href) {
|
|
24258
24320
|
queueMicrotask(() => {
|
|
24259
24321
|
this.options.api?.resolveUrl(normalizeUrl(attrs.href))?.then((metadata) => {
|
|
24260
|
-
console.log({ metadata });
|
|
24261
24322
|
if (metadata) {
|
|
24262
24323
|
const previewPayload = convertLinkMetaToPreviewItem(metadata);
|
|
24263
24324
|
let linkPreviewExists = false;
|
|
@@ -24286,7 +24347,6 @@ const CustomLink = Link__default.default.extend({
|
|
|
24286
24347
|
editor.commands.deleteLinkPreviewByUid(uid);
|
|
24287
24348
|
}
|
|
24288
24349
|
}).catch((err) => {
|
|
24289
|
-
console.log("LINK UPDATE ERR::", { err });
|
|
24290
24350
|
editor.commands.deleteLinkPreviewByUid(uid);
|
|
24291
24351
|
});
|
|
24292
24352
|
});
|
|
@@ -24366,7 +24426,6 @@ const IframeView = ({
|
|
|
24366
24426
|
setPreviewData(previewPayload);
|
|
24367
24427
|
updateAttributes({ previewPayload });
|
|
24368
24428
|
}).catch((error) => {
|
|
24369
|
-
console.error("Failed to fetch preview:", error);
|
|
24370
24429
|
}).finally(() => {
|
|
24371
24430
|
});
|
|
24372
24431
|
}
|
|
@@ -24611,7 +24670,6 @@ const _createTrustedTypesPolicy = function _createTrustedTypesPolicy2(trustedTyp
|
|
|
24611
24670
|
}
|
|
24612
24671
|
});
|
|
24613
24672
|
} catch (_) {
|
|
24614
|
-
console.warn("TrustedTypes policy " + policyName + " could not be created.");
|
|
24615
24673
|
return null;
|
|
24616
24674
|
}
|
|
24617
24675
|
};
|
|
@@ -25448,7 +25506,6 @@ const configureDOMPurify = () => {
|
|
|
25448
25506
|
const element = node;
|
|
25449
25507
|
const src = element.getAttribute("src") || "";
|
|
25450
25508
|
if (!isAllowedDomain(src)) {
|
|
25451
|
-
console.warn("🚨 Blocked iframe from non-allowed domain:", src);
|
|
25452
25509
|
node.parentNode?.removeChild(node);
|
|
25453
25510
|
}
|
|
25454
25511
|
}
|
|
@@ -25460,7 +25517,6 @@ function sanitizeIframeHTML(html2) {
|
|
|
25460
25517
|
const config = configureDOMPurify();
|
|
25461
25518
|
const cleaned = purify.sanitize(html2, config);
|
|
25462
25519
|
if (!cleaned.includes("<iframe")) {
|
|
25463
|
-
console.warn("⚠️ No valid iframe found after sanitization");
|
|
25464
25520
|
return null;
|
|
25465
25521
|
}
|
|
25466
25522
|
const match = cleaned.match(/<iframe[^>]*src=["']([^"']+)["']/i);
|
|
@@ -25472,7 +25528,6 @@ function sanitizeIframeHTML(html2) {
|
|
|
25472
25528
|
}
|
|
25473
25529
|
return match[1];
|
|
25474
25530
|
} catch (error) {
|
|
25475
|
-
console.error("🚨 Error sanitizing iframe:", error);
|
|
25476
25531
|
return null;
|
|
25477
25532
|
} finally {
|
|
25478
25533
|
purify.removeAllHooks();
|
|
@@ -25510,7 +25565,6 @@ const createFinder = (regex) => {
|
|
|
25510
25565
|
match
|
|
25511
25566
|
});
|
|
25512
25567
|
}
|
|
25513
|
-
console.log({ match, matches });
|
|
25514
25568
|
return matches.length > 0 ? matches : null;
|
|
25515
25569
|
};
|
|
25516
25570
|
};
|
|
@@ -25562,11 +25616,9 @@ const Iframe = core.Node.create({
|
|
|
25562
25616
|
const iframeHTML = match[0];
|
|
25563
25617
|
const safeSrc = sanitizeIframeHTML(iframeHTML);
|
|
25564
25618
|
if (!safeSrc) {
|
|
25565
|
-
console.warn("🚨 Blocked unsafe iframe paste");
|
|
25566
25619
|
toast.error("🚨 Your pasted iframe is not safe to render");
|
|
25567
25620
|
return;
|
|
25568
25621
|
}
|
|
25569
|
-
console.log("✅ Safe iframe URL validated:", safeSrc);
|
|
25570
25622
|
const node = this.type.create({ src: safeSrc, previewPayload: null });
|
|
25571
25623
|
state2.tr.replaceRangeWith(range.from, range.to, node);
|
|
25572
25624
|
}
|
|
@@ -25577,7 +25629,6 @@ const Iframe = core.Node.create({
|
|
|
25577
25629
|
handler: ({ state: state2, range, match }) => {
|
|
25578
25630
|
const fullUrl = match[0];
|
|
25579
25631
|
const embedUrl = getEmbedUrl(fullUrl);
|
|
25580
|
-
console.log({ match, fullUrl, embedUrl });
|
|
25581
25632
|
if (!embedUrl) return;
|
|
25582
25633
|
const node = this.type.create({ src: embedUrl });
|
|
25583
25634
|
state2.tr.replaceRangeWith(range.from, range.to, node);
|
|
@@ -25623,10 +25674,9 @@ const handleUrlWithoutSelection = (editor, url, event, autoDetectMedia) => {
|
|
|
25623
25674
|
mediaType: MediaItemType.MEDIA_ITEM
|
|
25624
25675
|
});
|
|
25625
25676
|
}).catch(
|
|
25626
|
-
(e) =>
|
|
25677
|
+
(e) => void 0
|
|
25627
25678
|
);
|
|
25628
25679
|
}
|
|
25629
|
-
console.log("[SmartLinkPaste] Inserting as link node");
|
|
25630
25680
|
editor.chain().focus().insertLink({ href: normalizedUrl, text: url }).run();
|
|
25631
25681
|
return true;
|
|
25632
25682
|
};
|
|
@@ -25648,7 +25698,6 @@ const createPasteHandler = (editor, options) => {
|
|
|
25648
25698
|
return false;
|
|
25649
25699
|
}
|
|
25650
25700
|
const trimmedText = pasteText.trim();
|
|
25651
|
-
console.log("[SmartLinkPaste] Valid URL detected:", isEmbeddableUrl(trimmedText));
|
|
25652
25701
|
if (isEmbeddableUrl(trimmedText) && options?.autoEmbed) {
|
|
25653
25702
|
event.preventDefault();
|
|
25654
25703
|
return false;
|
|
@@ -25665,7 +25714,6 @@ const createPasteHandler = (editor, options) => {
|
|
|
25665
25714
|
options?.autoDetectMedia ?? true
|
|
25666
25715
|
);
|
|
25667
25716
|
} catch (error) {
|
|
25668
|
-
console.error("[SmartLinkPaste] Error:", error);
|
|
25669
25717
|
return false;
|
|
25670
25718
|
}
|
|
25671
25719
|
};
|
|
@@ -25677,10 +25725,8 @@ const createTransformHandler = (editor) => {
|
|
|
25677
25725
|
return slice;
|
|
25678
25726
|
}
|
|
25679
25727
|
try {
|
|
25680
|
-
console.log("[SmartLinkPaste] Transforming inline URLs in pasted content");
|
|
25681
25728
|
return transformUrlsInSlice(editor, slice);
|
|
25682
25729
|
} catch (error) {
|
|
25683
|
-
console.error("[SmartLinkPaste] Transform error:", error);
|
|
25684
25730
|
return slice;
|
|
25685
25731
|
}
|
|
25686
25732
|
};
|
|
@@ -25787,7 +25833,6 @@ const SmartMediaUpload = core.Extension.create({
|
|
|
25787
25833
|
const uid = v4();
|
|
25788
25834
|
const options = this.options;
|
|
25789
25835
|
if (!options.api) {
|
|
25790
|
-
console.error("API instance not provided to SmartMediaUpload");
|
|
25791
25836
|
return false;
|
|
25792
25837
|
}
|
|
25793
25838
|
if (isFileOrBlob(source)) {
|
|
@@ -25797,7 +25842,6 @@ const SmartMediaUpload = core.Extension.create({
|
|
|
25797
25842
|
options.allowedFileTypes
|
|
25798
25843
|
);
|
|
25799
25844
|
if (!validation.valid) {
|
|
25800
|
-
console.error("File validation failed:", validation.error);
|
|
25801
25845
|
options.onUploadError?.(uid, new Error(validation.error));
|
|
25802
25846
|
return false;
|
|
25803
25847
|
}
|
|
@@ -25881,7 +25925,6 @@ const SmartMediaUpload = core.Extension.create({
|
|
|
25881
25925
|
} else editor.commands.deleteMediaByUid(item.uid);
|
|
25882
25926
|
options.onUploadComplete?.(item.uid, hostedUrl);
|
|
25883
25927
|
} catch (error) {
|
|
25884
|
-
console.error("Upload failed:", error);
|
|
25885
25928
|
const blobUrl = this.storage.blobUrls.get(item.uid);
|
|
25886
25929
|
if (blobUrl) {
|
|
25887
25930
|
URL.revokeObjectURL(blobUrl);
|
|
@@ -25893,7 +25936,7 @@ const SmartMediaUpload = core.Extension.create({
|
|
|
25893
25936
|
this.storage.activeUploads--;
|
|
25894
25937
|
this.storage.processUploadQueue(editor);
|
|
25895
25938
|
}
|
|
25896
|
-
})().catch((err) =>
|
|
25939
|
+
})().catch((err) => void 0);
|
|
25897
25940
|
if (this.storage.uploadQueue.length > 0) {
|
|
25898
25941
|
this.storage.processUploadQueue(editor);
|
|
25899
25942
|
}
|
|
@@ -28593,7 +28636,6 @@ function getSuggestionOptions({
|
|
|
28593
28636
|
const text2 = editor.getText();
|
|
28594
28637
|
const trimmed = text2?.replace(WHITESPACE_REGEX, " ")?.trim();
|
|
28595
28638
|
const matchStartPosition = trimmed?.lastIndexOf(char);
|
|
28596
|
-
console.log({ matchStartPosition });
|
|
28597
28639
|
const nodeAfter = editor.view.state.selection.$to.nodeAfter;
|
|
28598
28640
|
const overrideSpace = nodeAfter?.text?.startsWith(" ");
|
|
28599
28641
|
if (overrideSpace) {
|
|
@@ -28707,7 +28749,6 @@ const Mention = core.Node.create({
|
|
|
28707
28749
|
renderHTML({ node, HTMLAttributes }) {
|
|
28708
28750
|
const suggestion2 = getSuggestionFromChar(this, node.attrs.mentionSuggestionChar);
|
|
28709
28751
|
if (this.options.renderLabel !== void 0) {
|
|
28710
|
-
console.warn("renderLabel is deprecated use renderText and renderHTML instead");
|
|
28711
28752
|
return [
|
|
28712
28753
|
"span",
|
|
28713
28754
|
core.mergeAttributes({ "data-type": this.name }, this.options.HTMLAttributes, HTMLAttributes),
|
|
@@ -28747,7 +28788,6 @@ const Mention = core.Node.create({
|
|
|
28747
28788
|
suggestion: getSuggestionFromChar(this, node.attrs.mentionSuggestionChar)
|
|
28748
28789
|
};
|
|
28749
28790
|
if (this.options.renderLabel !== void 0) {
|
|
28750
|
-
console.warn("renderLabel is deprecated use renderText and renderHTML instead");
|
|
28751
28791
|
return this.options.renderLabel(args);
|
|
28752
28792
|
}
|
|
28753
28793
|
return this.options.renderText(args);
|
|
@@ -29736,11 +29776,9 @@ const mentionService = (api, mfs, store) => {
|
|
|
29736
29776
|
const fetchMentions = async () => {
|
|
29737
29777
|
const params = store.getState().getMentionParams();
|
|
29738
29778
|
if (!params) {
|
|
29739
|
-
console.error("DEBUG MENTION SERVICE::", "No group id or post id has been provided");
|
|
29740
29779
|
return [];
|
|
29741
29780
|
}
|
|
29742
29781
|
const { groupId, postId } = params;
|
|
29743
|
-
console.log({ groupId, postId });
|
|
29744
29782
|
const response = postId ? await mfs.getRecommendationPost(groupId, postId, 0, 999) : await mfs.getRecommendationGroup(groupId, 0, 999);
|
|
29745
29783
|
return response.entries?.filter((item) => Boolean(item?.user_data))?.map(
|
|
29746
29784
|
(item) => ({
|
|
@@ -29759,7 +29797,6 @@ const mentionService = (api, mfs, store) => {
|
|
|
29759
29797
|
const { selectedGroupId, groupId } = store.getState();
|
|
29760
29798
|
const activeGroupId = selectedGroupId ?? groupId;
|
|
29761
29799
|
if (!activeGroupId) {
|
|
29762
|
-
console.warn("DEBUG HASHTAG SERVICE::", "No active group selected or provided");
|
|
29763
29800
|
return [];
|
|
29764
29801
|
}
|
|
29765
29802
|
const response = await api.fetchGroupConversations(999, 0);
|
|
@@ -29961,8 +29998,8 @@ const LinkPreviewExtended = ({
|
|
|
29961
29998
|
title,
|
|
29962
29999
|
description,
|
|
29963
30000
|
image,
|
|
29964
|
-
domain
|
|
29965
|
-
|
|
30001
|
+
domain,
|
|
30002
|
+
onClickDelete
|
|
29966
30003
|
}) => {
|
|
29967
30004
|
const safeDomain = React.useMemo(() => {
|
|
29968
30005
|
try {
|
|
@@ -29971,6 +30008,11 @@ const LinkPreviewExtended = ({
|
|
|
29971
30008
|
return "unknown";
|
|
29972
30009
|
}
|
|
29973
30010
|
}, [href, domain]);
|
|
30011
|
+
const handleDelete = (e) => {
|
|
30012
|
+
e.preventDefault();
|
|
30013
|
+
e.stopPropagation();
|
|
30014
|
+
onClickDelete();
|
|
30015
|
+
};
|
|
29974
30016
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29975
30017
|
"div",
|
|
29976
30018
|
{
|
|
@@ -29979,18 +30021,32 @@ const LinkPreviewExtended = ({
|
|
|
29979
30021
|
selected ? "ring-2 ring-blue-500 ring-offset-2 rounded-lg" : ""
|
|
29980
30022
|
),
|
|
29981
30023
|
children: [
|
|
29982
|
-
/* @__PURE__ */ jsxRuntime.
|
|
29983
|
-
|
|
29984
|
-
|
|
29985
|
-
|
|
29986
|
-
|
|
29987
|
-
|
|
29988
|
-
|
|
29989
|
-
/* @__PURE__ */ jsxRuntime.
|
|
29990
|
-
|
|
29991
|
-
|
|
29992
|
-
|
|
29993
|
-
|
|
30024
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 absolute z-50 right-3 top-3", children: [
|
|
30025
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
30026
|
+
ToolbarButton,
|
|
30027
|
+
{
|
|
30028
|
+
asChild: true,
|
|
30029
|
+
tooltip: "Visit Link",
|
|
30030
|
+
className: "cursor-pointer backdrop-blur-2xl size-6 shadow-none group-hover:bg-accent/70 group-hover:text-accent-foreground text-primary-send",
|
|
30031
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative", children: [
|
|
30032
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { href, target: "_blank", rel: "noopener noreferrer", className: "absolute inset-0" }),
|
|
30033
|
+
/* @__PURE__ */ jsxRuntime.jsx(ExternalLink, {})
|
|
30034
|
+
] })
|
|
30035
|
+
}
|
|
30036
|
+
),
|
|
30037
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
30038
|
+
ToolbarButton,
|
|
30039
|
+
{
|
|
30040
|
+
tooltip: "Remove Link Preview",
|
|
30041
|
+
onClick: handleDelete,
|
|
30042
|
+
"aria-label": "Delete link preview",
|
|
30043
|
+
type: "button",
|
|
30044
|
+
size: "icon",
|
|
30045
|
+
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",
|
|
30046
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Trash2, {})
|
|
30047
|
+
}
|
|
30048
|
+
)
|
|
30049
|
+
] }),
|
|
29994
30050
|
/* @__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
30051
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-80 w-full shrink-0 overflow-hidden bg-muted border-b", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
29996
30052
|
"img",
|
|
@@ -30111,7 +30167,6 @@ const LinkPreview = core.Node.create({
|
|
|
30111
30167
|
},
|
|
30112
30168
|
renderHTML({ node }) {
|
|
30113
30169
|
const { href, uid, title, description, image, domain } = node.attrs;
|
|
30114
|
-
console.log("INSIDE RENDER HTML::", { href, image });
|
|
30115
30170
|
if (!href) return ["div", {}];
|
|
30116
30171
|
const content = [
|
|
30117
30172
|
// Link overlay
|
|
@@ -30246,11 +30301,6 @@ const MediaGroupView = ({ node, editor }) => {
|
|
|
30246
30301
|
editor.commands.deleteMediaByUid(uid);
|
|
30247
30302
|
};
|
|
30248
30303
|
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
30304
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
30255
30305
|
react.NodeViewWrapper,
|
|
30256
30306
|
{
|
|
@@ -30352,14 +30402,12 @@ const createMediaModePlugin = () => {
|
|
|
30352
30402
|
child.marks.forEach((mark) => {
|
|
30353
30403
|
if (mark.type.name === "customLink" && mark.attrs.previewPayload) {
|
|
30354
30404
|
lastLinkPreviewData = mark.attrs.previewPayload;
|
|
30355
|
-
console.log("Found link with previewPayload:", lastLinkPreviewData);
|
|
30356
30405
|
}
|
|
30357
30406
|
});
|
|
30358
30407
|
}
|
|
30359
30408
|
});
|
|
30360
30409
|
}
|
|
30361
30410
|
});
|
|
30362
|
-
console.log("Cleanup check:", { modified, hasMediaGroup, lastLinkPreviewData });
|
|
30363
30411
|
if (modified && hasMediaGroup && lastLinkPreviewData) {
|
|
30364
30412
|
let hasLinkPreview = false;
|
|
30365
30413
|
tr.doc.forEach((node) => {
|
|
@@ -30367,10 +30415,6 @@ const createMediaModePlugin = () => {
|
|
|
30367
30415
|
hasLinkPreview = true;
|
|
30368
30416
|
}
|
|
30369
30417
|
});
|
|
30370
|
-
console.log("Creating linkPreview:", {
|
|
30371
|
-
hasLinkPreview,
|
|
30372
|
-
schemaHasLinkPreview: !!newState.schema.nodes.linkPreview
|
|
30373
|
-
});
|
|
30374
30418
|
if (!hasLinkPreview && newState.schema.nodes.linkPreview) {
|
|
30375
30419
|
const preview = lastLinkPreviewData;
|
|
30376
30420
|
const linkPreviewNode = newState.schema.nodes.linkPreview.create({
|
|
@@ -30381,7 +30425,6 @@ const createMediaModePlugin = () => {
|
|
|
30381
30425
|
image: preview.linkImage?.url ?? "",
|
|
30382
30426
|
variant: LinkPreviewType.Extended
|
|
30383
30427
|
});
|
|
30384
|
-
console.log("Inserting linkPreview node:", { lastLinkPreviewData, linkPreviewNode });
|
|
30385
30428
|
tr.insert(tr.doc.content.size, linkPreviewNode);
|
|
30386
30429
|
modified = true;
|
|
30387
30430
|
}
|
|
@@ -30441,7 +30484,6 @@ const createMediaModePlugin = () => {
|
|
|
30441
30484
|
}
|
|
30442
30485
|
const mediaNodes = updatedTopLevelMedia.map((m) => m.node);
|
|
30443
30486
|
if (mediaNodes.some((n) => !n || n.type.name !== "media")) {
|
|
30444
|
-
console.warn("Invalid media nodes detected, skipping group creation");
|
|
30445
30487
|
return null;
|
|
30446
30488
|
}
|
|
30447
30489
|
const mediaGroup = newState.schema.nodes.mediaGroup.create({}, mediaNodes);
|
|
@@ -30459,7 +30501,6 @@ const createMediaModePlugin = () => {
|
|
|
30459
30501
|
const $pos = tr.doc.resolve(endPos);
|
|
30460
30502
|
tr.setSelection(state.TextSelection.near($pos));
|
|
30461
30503
|
} catch (e) {
|
|
30462
|
-
console.warn("Could not set selection:", e);
|
|
30463
30504
|
}
|
|
30464
30505
|
}
|
|
30465
30506
|
tr.setMeta("addToHistory", false);
|
|
@@ -30467,7 +30508,6 @@ const createMediaModePlugin = () => {
|
|
|
30467
30508
|
}
|
|
30468
30509
|
return modified ? tr : null;
|
|
30469
30510
|
} catch (error) {
|
|
30470
|
-
console.error("MediaMode plugin error:", error);
|
|
30471
30511
|
return null;
|
|
30472
30512
|
} finally {
|
|
30473
30513
|
isProcessing = false;
|
|
@@ -30609,7 +30649,7 @@ const getMediaExtensions = ({ api, store, user }) => {
|
|
|
30609
30649
|
}),
|
|
30610
30650
|
LinkPreview.configure({
|
|
30611
30651
|
variant: LinkPreviewType.Extended,
|
|
30612
|
-
selectable: false,
|
|
30652
|
+
// selectable: false,
|
|
30613
30653
|
draggable: false
|
|
30614
30654
|
}),
|
|
30615
30655
|
getMentionExtension(core2, mfs, store),
|
|
@@ -30753,7 +30793,6 @@ const isLinkMarkWithPayload = (node) => isLinkMark(node) && Boolean(node?.attrs?
|
|
|
30753
30793
|
const getLinkItemsPayload = (json) => {
|
|
30754
30794
|
const links = find(json, (node) => isLinkMarkWithPayload(node));
|
|
30755
30795
|
const items = links?.at(-1);
|
|
30756
|
-
console.log("Link Items Payload::", { items });
|
|
30757
30796
|
return { items };
|
|
30758
30797
|
};
|
|
30759
30798
|
const getPollItemsPayload = (json) => {
|
|
@@ -30761,6 +30800,15 @@ const getPollItemsPayload = (json) => {
|
|
|
30761
30800
|
const items = poll[0].attrs?.choices;
|
|
30762
30801
|
return { items };
|
|
30763
30802
|
};
|
|
30803
|
+
const isValidItem = (item) => {
|
|
30804
|
+
if (!item) return false;
|
|
30805
|
+
const linkItem = item;
|
|
30806
|
+
const mediaItem = item;
|
|
30807
|
+
const isValidLinkItem = linkItem?.linkUrl;
|
|
30808
|
+
const mediaItemSources = mediaItem?.sources;
|
|
30809
|
+
const isValidMediaItem = mediaItemSources?.original?.url || mediaItemSources?.thumbnail?.url;
|
|
30810
|
+
return Boolean(isValidLinkItem || isValidMediaItem);
|
|
30811
|
+
};
|
|
30764
30812
|
const generateHtmlPostPayload = ({
|
|
30765
30813
|
editor,
|
|
30766
30814
|
sendCrossMention
|
|
@@ -30777,13 +30825,12 @@ const generateHtmlPostPayload = ({
|
|
|
30777
30825
|
(node) => node?.type === "text" && (node?.marks?.some((val) => val?.type !== "customLink") ?? true)
|
|
30778
30826
|
)?.at(0);
|
|
30779
30827
|
const isEmbedOnly = isOnlyContentNode(json, "iframe");
|
|
30780
|
-
const body = isEmbedOnly ? previewItemEmbed?.attrs?.previewPayload?.linkTitle ?? "" : secondaryText?.text ?? firstText?.text ?? "";
|
|
30781
|
-
console.log({ firstText });
|
|
30828
|
+
const body = isEmbedOnly ? previewItemEmbed?.attrs?.previewPayload?.linkTitle ?? previewItemEmbed?.attrs?.src ?? "" : secondaryText?.text ?? firstText?.text ?? "";
|
|
30782
30829
|
const items = [
|
|
30783
30830
|
previewItemMedia?.attrs?.payload,
|
|
30784
30831
|
previewItemEmbed?.attrs?.previewPayload,
|
|
30785
30832
|
linkPreviewItem
|
|
30786
|
-
]?.filter(
|
|
30833
|
+
]?.filter(isValidItem)?.filter((_, index2) => index2 === 0);
|
|
30787
30834
|
const htmlBody = html2;
|
|
30788
30835
|
return {
|
|
30789
30836
|
...commons,
|
|
@@ -30805,11 +30852,14 @@ const generateMediaPostPayload = ({
|
|
|
30805
30852
|
const { mentionData } = getMentionDataPayload(json);
|
|
30806
30853
|
const { items: mediaItems } = getMediaItemsPayload(json);
|
|
30807
30854
|
const { items: linkItems } = getLinkItemsPayload(json);
|
|
30855
|
+
const items = mediaItems?.length > 0 ? mediaItems : linkItems?.length > 0 ? linkItems : [];
|
|
30856
|
+
if (!body && mediaItems.length === 0)
|
|
30857
|
+
return { error: "Your post is empty. Add text or media to share your thoughts." };
|
|
30808
30858
|
return {
|
|
30809
30859
|
...commons,
|
|
30810
30860
|
type: mediaItems?.length > 0 ? NewPostType.NEW_POST_MEDIA : linkItems?.length > 0 ? NewPostType.NEW_POST_LINK : NewPostType.NEW_POST_MESSAGE,
|
|
30811
30861
|
body,
|
|
30812
|
-
items
|
|
30862
|
+
items,
|
|
30813
30863
|
mentionData,
|
|
30814
30864
|
sendCrossMention
|
|
30815
30865
|
};
|
|
@@ -30829,7 +30879,6 @@ const generatePollPostPayload = ({
|
|
|
30829
30879
|
option_id: index2 === 0 ? item.option_id : v4(),
|
|
30830
30880
|
option_color: OPTION_COLORS[index2 % OPTION_COLORS.length]
|
|
30831
30881
|
})) : items;
|
|
30832
|
-
console.log({ polls });
|
|
30833
30882
|
return {
|
|
30834
30883
|
...commons,
|
|
30835
30884
|
type: NewPostType.NEW_POST_POLL,
|
|
@@ -30866,6 +30915,7 @@ const PostBuilderEditorInstance = ({
|
|
|
30866
30915
|
const [isDragging, setIsDragging] = React.useState(false);
|
|
30867
30916
|
const { trackPublish } = usePostBuilderAnalytics();
|
|
30868
30917
|
const { clearContent } = usePersistence();
|
|
30918
|
+
useHostAnalyticsBridge();
|
|
30869
30919
|
const handleDragOver = (e) => {
|
|
30870
30920
|
e.preventDefault();
|
|
30871
30921
|
setIsDragging(true);
|
|
@@ -30885,10 +30935,24 @@ const PostBuilderEditorInstance = ({
|
|
|
30885
30935
|
const text2 = editor?.getText();
|
|
30886
30936
|
const payload = generateCreatePostPayload(editorTab, { editor, sendCrossMention });
|
|
30887
30937
|
const isPollType = payload?.type === NewPostType.NEW_POST_POLL;
|
|
30888
|
-
if (
|
|
30938
|
+
if (payload?.error) {
|
|
30939
|
+
toast.error(payload.error);
|
|
30940
|
+
return;
|
|
30941
|
+
}
|
|
30942
|
+
if (!payload?.postId) return;
|
|
30889
30943
|
if (isPollType && payload.items?.length === 0)
|
|
30890
30944
|
return toast.warning(`At least ${POLL_LIMITS.MIN} option is mandatory to create a poll post`);
|
|
30891
|
-
|
|
30945
|
+
if (typeof window !== "undefined") {
|
|
30946
|
+
window.dispatchEvent(
|
|
30947
|
+
new CustomEvent(PostBuilderEvents.POST_PUBLISH_ATTEMPTED, {
|
|
30948
|
+
detail: {
|
|
30949
|
+
postId: payload.postId,
|
|
30950
|
+
postType: payload.type
|
|
30951
|
+
}
|
|
30952
|
+
})
|
|
30953
|
+
);
|
|
30954
|
+
}
|
|
30955
|
+
trackPublish({ status: "attempted", postId: payload?.postId, postType: payload?.type });
|
|
30892
30956
|
onCreatePost?.({ payload, html: html2, json, text: text2 });
|
|
30893
30957
|
if (!clearOnSuccess) return;
|
|
30894
30958
|
clearContent();
|
|
@@ -31062,7 +31126,6 @@ class SessionManager {
|
|
|
31062
31126
|
}, SESSION_TIMEOUT_MS);
|
|
31063
31127
|
}
|
|
31064
31128
|
endSession(reason) {
|
|
31065
|
-
console.log({ reason });
|
|
31066
31129
|
if (this.inactivityTimer) {
|
|
31067
31130
|
clearTimeout(this.inactivityTimer);
|
|
31068
31131
|
}
|
|
@@ -31123,7 +31186,7 @@ function useAnalytics({ editorTab, config }) {
|
|
|
31123
31186
|
const featureTracker = React.useRef(new FeatureTracker()).current;
|
|
31124
31187
|
const logEvent = useAnalyticsLogEvent();
|
|
31125
31188
|
const trackEvent = React.useCallback(
|
|
31126
|
-
(name, properties
|
|
31189
|
+
({ name, properties }) => {
|
|
31127
31190
|
const fullConfig = { ...DEFAULT_CONFIG, ...config };
|
|
31128
31191
|
if (!fullConfig.enabled) return;
|
|
31129
31192
|
sessionManager.updateActivity();
|
|
@@ -31131,30 +31194,32 @@ function useAnalytics({ editorTab, config }) {
|
|
|
31131
31194
|
session_id: sessionManager.getSessionId(),
|
|
31132
31195
|
timestamp: Date.now(),
|
|
31133
31196
|
editor_type: editorTab,
|
|
31134
|
-
...properties
|
|
31197
|
+
...properties ?? {}
|
|
31135
31198
|
};
|
|
31136
|
-
|
|
31137
|
-
|
|
31138
|
-
}
|
|
31139
|
-
if (fullConfig.debug) {
|
|
31140
|
-
console.log("[Analytics]", name, enrichedProperties);
|
|
31141
|
-
}
|
|
31199
|
+
const cleanProps = pickBy(enrichedProperties, (value) => value != null);
|
|
31200
|
+
if (logEvent) logEvent(name, cleanProps);
|
|
31142
31201
|
},
|
|
31143
31202
|
[config, editorTab, logEvent, sessionManager]
|
|
31144
31203
|
);
|
|
31145
31204
|
React.useEffect(() => {
|
|
31146
31205
|
const sessionId = sessionManager.startSession();
|
|
31147
|
-
trackEvent(
|
|
31148
|
-
|
|
31149
|
-
|
|
31150
|
-
|
|
31206
|
+
trackEvent({
|
|
31207
|
+
name: ANALYTICS_EVENTS.SESSION.STARTED,
|
|
31208
|
+
properties: {
|
|
31209
|
+
session_id: sessionId,
|
|
31210
|
+
timestamp: Date.now(),
|
|
31211
|
+
editor_type: editorTab
|
|
31212
|
+
}
|
|
31151
31213
|
});
|
|
31152
31214
|
const handleUnload = () => {
|
|
31153
|
-
trackEvent(
|
|
31154
|
-
|
|
31155
|
-
|
|
31156
|
-
|
|
31157
|
-
|
|
31215
|
+
trackEvent({
|
|
31216
|
+
name: ANALYTICS_EVENTS.SESSION.COMPLETED,
|
|
31217
|
+
properties: {
|
|
31218
|
+
session_id: sessionManager.getSessionId(),
|
|
31219
|
+
timestamp: Date.now(),
|
|
31220
|
+
editor_type: editorTab,
|
|
31221
|
+
session_duration_ms: sessionManager.getSessionDuration()
|
|
31222
|
+
}
|
|
31158
31223
|
});
|
|
31159
31224
|
};
|
|
31160
31225
|
window.addEventListener("beforeunload", handleUnload);
|
|
@@ -31164,60 +31229,88 @@ function useAnalytics({ editorTab, config }) {
|
|
|
31164
31229
|
};
|
|
31165
31230
|
}, []);
|
|
31166
31231
|
const trackFeature = React.useCallback(
|
|
31167
|
-
(featureName) => {
|
|
31232
|
+
({ featureName }) => {
|
|
31168
31233
|
const { isFirstUse, usageCount } = featureTracker.trackUsage(featureName);
|
|
31169
|
-
trackEvent(
|
|
31170
|
-
|
|
31171
|
-
|
|
31172
|
-
|
|
31234
|
+
trackEvent({
|
|
31235
|
+
name: isFirstUse ? ANALYTICS_EVENTS.FEATURE.DISCOVERED : ANALYTICS_EVENTS.FEATURE.USED,
|
|
31236
|
+
properties: {
|
|
31237
|
+
feature_name: featureName,
|
|
31238
|
+
is_first_use: isFirstUse,
|
|
31239
|
+
usage_count: usageCount
|
|
31240
|
+
}
|
|
31173
31241
|
});
|
|
31174
31242
|
},
|
|
31175
31243
|
[trackEvent, featureTracker]
|
|
31176
31244
|
);
|
|
31177
31245
|
const trackPublish = React.useCallback(
|
|
31178
|
-
(status, data) => {
|
|
31246
|
+
({ status, data }) => {
|
|
31179
31247
|
const eventMap = {
|
|
31180
31248
|
attempted: ANALYTICS_EVENTS.PUBLISH.ATTEMPTED,
|
|
31181
31249
|
success: ANALYTICS_EVENTS.PUBLISH.SUCCESS,
|
|
31182
31250
|
failed: ANALYTICS_EVENTS.PUBLISH.FAILED
|
|
31183
31251
|
};
|
|
31184
|
-
|
|
31252
|
+
const properties = {
|
|
31185
31253
|
editor_type: editorTab,
|
|
31186
31254
|
session_duration_ms: sessionManager.getSessionDuration(),
|
|
31187
31255
|
...data
|
|
31256
|
+
};
|
|
31257
|
+
trackEvent({
|
|
31258
|
+
name: eventMap[status],
|
|
31259
|
+
properties
|
|
31188
31260
|
});
|
|
31189
31261
|
sessionManager.endSession("completed");
|
|
31190
31262
|
},
|
|
31191
31263
|
[trackEvent, editorTab, sessionManager]
|
|
31192
31264
|
);
|
|
31193
31265
|
const trackAbandon = React.useCallback(
|
|
31194
|
-
(
|
|
31195
|
-
|
|
31196
|
-
|
|
31197
|
-
|
|
31198
|
-
|
|
31199
|
-
|
|
31200
|
-
|
|
31266
|
+
({
|
|
31267
|
+
contentLength,
|
|
31268
|
+
hasUnsavedChanges,
|
|
31269
|
+
abandonReason,
|
|
31270
|
+
postType,
|
|
31271
|
+
userHistoryData
|
|
31272
|
+
}) => {
|
|
31273
|
+
trackEvent({
|
|
31274
|
+
name: ANALYTICS_EVENTS.SESSION.ABANDONED,
|
|
31275
|
+
properties: {
|
|
31276
|
+
session_duration_ms: sessionManager.getSessionDuration(),
|
|
31277
|
+
post_type: postType,
|
|
31278
|
+
content_length: contentLength,
|
|
31279
|
+
has_unsaved_changes: hasUnsavedChanges,
|
|
31280
|
+
abandon_reason: abandonReason,
|
|
31281
|
+
// Include user history if provided
|
|
31282
|
+
...userHistoryData && {
|
|
31283
|
+
previous_abandon_count: userHistoryData.previous_abandon_count,
|
|
31284
|
+
previous_publish_count: userHistoryData.previous_publish_count,
|
|
31285
|
+
time_since_last_publish_ms: userHistoryData.time_since_last_publish_ms,
|
|
31286
|
+
is_returning_user: userHistoryData.is_returning_user
|
|
31287
|
+
}
|
|
31288
|
+
}
|
|
31201
31289
|
});
|
|
31202
31290
|
sessionManager.endSession("abandoned");
|
|
31203
31291
|
},
|
|
31204
31292
|
[trackEvent, sessionManager]
|
|
31205
31293
|
);
|
|
31206
31294
|
const trackTabSwitch = React.useCallback(
|
|
31207
|
-
(oldTab, newTab) => {
|
|
31208
|
-
trackEvent(
|
|
31209
|
-
|
|
31210
|
-
|
|
31211
|
-
|
|
31295
|
+
({ oldTab, newTab }) => {
|
|
31296
|
+
trackEvent({
|
|
31297
|
+
name: ANALYTICS_EVENTS.EDITOR.FOCUSED,
|
|
31298
|
+
properties: {
|
|
31299
|
+
from_tab: oldTab,
|
|
31300
|
+
to_tab: newTab
|
|
31301
|
+
}
|
|
31212
31302
|
});
|
|
31213
31303
|
},
|
|
31214
|
-
[trackEvent
|
|
31304
|
+
[trackEvent]
|
|
31215
31305
|
);
|
|
31216
31306
|
const trackEditorFocus = React.useCallback(
|
|
31217
|
-
(context) => {
|
|
31218
|
-
trackEvent(
|
|
31219
|
-
|
|
31220
|
-
|
|
31307
|
+
({ context }) => {
|
|
31308
|
+
trackEvent({
|
|
31309
|
+
name: ANALYTICS_EVENTS.EDITOR.FOCUSED,
|
|
31310
|
+
properties: {
|
|
31311
|
+
context,
|
|
31312
|
+
editor_type: editorTab
|
|
31313
|
+
}
|
|
31221
31314
|
});
|
|
31222
31315
|
},
|
|
31223
31316
|
[trackEvent, editorTab]
|
|
@@ -31251,19 +31344,91 @@ function useAnalytics({ editorTab, config }) {
|
|
|
31251
31344
|
]
|
|
31252
31345
|
);
|
|
31253
31346
|
}
|
|
31347
|
+
const STORAGE_KEY = "pb_user_history";
|
|
31348
|
+
class UserHistoryTracker {
|
|
31349
|
+
history;
|
|
31350
|
+
constructor() {
|
|
31351
|
+
this.history = this.loadHistory();
|
|
31352
|
+
}
|
|
31353
|
+
loadHistory() {
|
|
31354
|
+
try {
|
|
31355
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
31356
|
+
if (stored) {
|
|
31357
|
+
return JSON.parse(stored);
|
|
31358
|
+
}
|
|
31359
|
+
} catch (error) {
|
|
31360
|
+
}
|
|
31361
|
+
return {
|
|
31362
|
+
previous_abandon_count: 0,
|
|
31363
|
+
previous_publish_count: 0,
|
|
31364
|
+
last_publish_timestamp: null,
|
|
31365
|
+
last_abandon_timestamp: null,
|
|
31366
|
+
first_session_timestamp: Date.now()
|
|
31367
|
+
};
|
|
31368
|
+
}
|
|
31369
|
+
saveHistory() {
|
|
31370
|
+
try {
|
|
31371
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.history));
|
|
31372
|
+
} catch (error) {
|
|
31373
|
+
}
|
|
31374
|
+
}
|
|
31375
|
+
/**
|
|
31376
|
+
* Record a successful publish
|
|
31377
|
+
*/
|
|
31378
|
+
recordPublish() {
|
|
31379
|
+
this.history.previous_publish_count += 1;
|
|
31380
|
+
this.history.last_publish_timestamp = Date.now();
|
|
31381
|
+
this.saveHistory();
|
|
31382
|
+
}
|
|
31383
|
+
/**
|
|
31384
|
+
* Record an abandonment
|
|
31385
|
+
*/
|
|
31386
|
+
recordAbandon() {
|
|
31387
|
+
this.history.previous_abandon_count += 1;
|
|
31388
|
+
this.history.last_abandon_timestamp = Date.now();
|
|
31389
|
+
this.saveHistory();
|
|
31390
|
+
}
|
|
31391
|
+
/**
|
|
31392
|
+
* Get current user history for analytics
|
|
31393
|
+
*/
|
|
31394
|
+
getHistory() {
|
|
31395
|
+
const now2 = Date.now();
|
|
31396
|
+
const daysSinceFirstSession = Math.floor(
|
|
31397
|
+
(now2 - this.history.first_session_timestamp) / (1e3 * 60 * 60 * 24)
|
|
31398
|
+
);
|
|
31399
|
+
return {
|
|
31400
|
+
previous_abandon_count: this.history.previous_abandon_count,
|
|
31401
|
+
previous_publish_count: this.history.previous_publish_count,
|
|
31402
|
+
time_since_last_publish_ms: this.history.last_publish_timestamp ? now2 - this.history.last_publish_timestamp : null,
|
|
31403
|
+
is_returning_user: daysSinceFirstSession > 0.5,
|
|
31404
|
+
days_since_first_session: daysSinceFirstSession
|
|
31405
|
+
};
|
|
31406
|
+
}
|
|
31407
|
+
/**
|
|
31408
|
+
* Clear history (for testing or user request)
|
|
31409
|
+
*/
|
|
31410
|
+
clearHistory() {
|
|
31411
|
+
localStorage.removeItem(STORAGE_KEY);
|
|
31412
|
+
this.history = {
|
|
31413
|
+
previous_abandon_count: 0,
|
|
31414
|
+
previous_publish_count: 0,
|
|
31415
|
+
last_publish_timestamp: null,
|
|
31416
|
+
last_abandon_timestamp: null,
|
|
31417
|
+
first_session_timestamp: Date.now()
|
|
31418
|
+
};
|
|
31419
|
+
}
|
|
31420
|
+
}
|
|
31254
31421
|
function useEditorAnalytics({
|
|
31255
31422
|
editor,
|
|
31256
31423
|
editorType,
|
|
31257
31424
|
context,
|
|
31258
31425
|
idleTimeout = 3e5,
|
|
31259
|
-
// 5 minutes
|
|
31260
31426
|
trackBlur = false
|
|
31261
|
-
// Default: don't track every blur
|
|
31262
31427
|
}) {
|
|
31263
31428
|
const analytics = useAnalytics({
|
|
31264
31429
|
editorTab: editorType,
|
|
31265
31430
|
config: {
|
|
31266
|
-
debug:
|
|
31431
|
+
debug: true,
|
|
31267
31432
|
enabled: true
|
|
31268
31433
|
}
|
|
31269
31434
|
});
|
|
@@ -31271,6 +31436,7 @@ function useEditorAnalytics({
|
|
|
31271
31436
|
const idleTimer = React.useRef();
|
|
31272
31437
|
const hasFocusedOnce = React.useRef(false);
|
|
31273
31438
|
const hasAbandonedSession = React.useRef(false);
|
|
31439
|
+
const userHistory = React.useRef(new UserHistoryTracker()).current;
|
|
31274
31440
|
const getEditorMetrics = React.useCallback(() => {
|
|
31275
31441
|
if (!editor) return null;
|
|
31276
31442
|
const json = editor.getJSON();
|
|
@@ -31310,7 +31476,6 @@ function useEditorAnalytics({
|
|
|
31310
31476
|
linkCount,
|
|
31311
31477
|
formattingFeatures: Array.from(formattingFeatures),
|
|
31312
31478
|
hasUnsavedChanges: editor.state.doc.content.size > 2,
|
|
31313
|
-
// Has content beyond empty doc
|
|
31314
31479
|
isEmpty: editor.isEmpty
|
|
31315
31480
|
};
|
|
31316
31481
|
}, [editor, analytics]);
|
|
@@ -31321,16 +31486,29 @@ function useEditorAnalytics({
|
|
|
31321
31486
|
idleTimer.current = setTimeout(() => {
|
|
31322
31487
|
const metrics = getEditorMetrics();
|
|
31323
31488
|
if (metrics && !metrics.isEmpty) {
|
|
31324
|
-
|
|
31489
|
+
const history = userHistory.getHistory();
|
|
31490
|
+
analytics.trackAbandon({
|
|
31491
|
+
contentLength: metrics.characterCount,
|
|
31492
|
+
hasUnsavedChanges: metrics.hasUnsavedChanges,
|
|
31493
|
+
abandonReason: "idle_timeout",
|
|
31494
|
+
postType: void 0,
|
|
31495
|
+
userHistoryData: {
|
|
31496
|
+
previous_abandon_count: history.previous_abandon_count,
|
|
31497
|
+
previous_publish_count: history.previous_publish_count,
|
|
31498
|
+
time_since_last_publish_ms: history.time_since_last_publish_ms,
|
|
31499
|
+
is_returning_user: history.is_returning_user
|
|
31500
|
+
}
|
|
31501
|
+
});
|
|
31502
|
+
userHistory.recordAbandon();
|
|
31325
31503
|
hasAbandonedSession.current = true;
|
|
31326
31504
|
}
|
|
31327
31505
|
}, idleTimeout);
|
|
31328
|
-
}, [editor, idleTimeout, analytics, getEditorMetrics]);
|
|
31506
|
+
}, [editor, idleTimeout, analytics, getEditorMetrics, userHistory]);
|
|
31329
31507
|
React.useEffect(() => {
|
|
31330
31508
|
if (!editor) return;
|
|
31331
31509
|
const handleFocus = () => {
|
|
31332
31510
|
if (!hasFocusedOnce.current) {
|
|
31333
|
-
analytics.trackEditorFocus(context);
|
|
31511
|
+
analytics.trackEditorFocus({ context });
|
|
31334
31512
|
hasFocusedOnce.current = true;
|
|
31335
31513
|
}
|
|
31336
31514
|
resetIdleTimer();
|
|
@@ -31341,9 +31519,12 @@ function useEditorAnalytics({
|
|
|
31341
31519
|
if (trackBlur) {
|
|
31342
31520
|
const metrics = getEditorMetrics();
|
|
31343
31521
|
if (metrics && !metrics.isEmpty) {
|
|
31344
|
-
analytics.trackEvent(
|
|
31345
|
-
|
|
31346
|
-
|
|
31522
|
+
analytics.trackEvent({
|
|
31523
|
+
name: ANALYTICS_EVENTS.EDITOR.BLURRED,
|
|
31524
|
+
properties: {
|
|
31525
|
+
content_length: metrics.characterCount,
|
|
31526
|
+
session_duration_ms: Date.now() - lastActivity.current
|
|
31527
|
+
}
|
|
31347
31528
|
});
|
|
31348
31529
|
}
|
|
31349
31530
|
}
|
|
@@ -31362,7 +31543,20 @@ function useEditorAnalytics({
|
|
|
31362
31543
|
if (hasAbandonedSession.current) return;
|
|
31363
31544
|
const metrics = getEditorMetrics();
|
|
31364
31545
|
if (metrics && !metrics.isEmpty) {
|
|
31365
|
-
|
|
31546
|
+
const history = userHistory.getHistory();
|
|
31547
|
+
analytics.trackAbandon({
|
|
31548
|
+
contentLength: metrics.characterCount,
|
|
31549
|
+
hasUnsavedChanges: metrics.hasUnsavedChanges,
|
|
31550
|
+
abandonReason: "navigation",
|
|
31551
|
+
postType: void 0,
|
|
31552
|
+
userHistoryData: {
|
|
31553
|
+
previous_abandon_count: history.previous_abandon_count,
|
|
31554
|
+
previous_publish_count: history.previous_publish_count,
|
|
31555
|
+
time_since_last_publish_ms: history.time_since_last_publish_ms,
|
|
31556
|
+
is_returning_user: history.is_returning_user
|
|
31557
|
+
}
|
|
31558
|
+
});
|
|
31559
|
+
userHistory.recordAbandon();
|
|
31366
31560
|
hasAbandonedSession.current = true;
|
|
31367
31561
|
}
|
|
31368
31562
|
};
|
|
@@ -31373,46 +31567,76 @@ function useEditorAnalytics({
|
|
|
31373
31567
|
clearTimeout(idleTimer.current);
|
|
31374
31568
|
}
|
|
31375
31569
|
};
|
|
31376
|
-
}, [editor, analytics, getEditorMetrics]);
|
|
31570
|
+
}, [editor, analytics, getEditorMetrics, userHistory]);
|
|
31377
31571
|
const trackFeature = React.useCallback(
|
|
31378
|
-
(featureName) => {
|
|
31379
|
-
analytics.trackFeature(featureName);
|
|
31572
|
+
({ featureName }) => {
|
|
31573
|
+
analytics.trackFeature({ featureName });
|
|
31380
31574
|
resetIdleTimer();
|
|
31381
31575
|
},
|
|
31382
31576
|
[analytics, resetIdleTimer]
|
|
31383
31577
|
);
|
|
31384
31578
|
const trackPublish = React.useCallback(
|
|
31385
|
-
(status, failureReason) => {
|
|
31579
|
+
({ sessionId, groupId, postId, status, failureReason, postType }) => {
|
|
31386
31580
|
const metrics = getEditorMetrics();
|
|
31387
31581
|
if (!metrics) return;
|
|
31388
|
-
|
|
31389
|
-
|
|
31390
|
-
|
|
31391
|
-
|
|
31392
|
-
|
|
31393
|
-
|
|
31394
|
-
|
|
31582
|
+
const history = userHistory.getHistory();
|
|
31583
|
+
analytics.trackPublish({
|
|
31584
|
+
status,
|
|
31585
|
+
data: {
|
|
31586
|
+
...sessionId ? { session_id: sessionId } : {},
|
|
31587
|
+
group_id: groupId,
|
|
31588
|
+
post_id: postId,
|
|
31589
|
+
post_type: postType,
|
|
31590
|
+
word_count: metrics.wordCount,
|
|
31591
|
+
character_count: metrics.characterCount,
|
|
31592
|
+
media_count: metrics.mediaCount,
|
|
31593
|
+
link_count: metrics.linkCount,
|
|
31594
|
+
formatting_features: metrics.formattingFeatures,
|
|
31595
|
+
failure_reason: failureReason,
|
|
31596
|
+
// Include user history
|
|
31597
|
+
previous_abandon_count: history.previous_abandon_count,
|
|
31598
|
+
previous_publish_count: history.previous_publish_count,
|
|
31599
|
+
time_since_last_publish_ms: history.time_since_last_publish_ms,
|
|
31600
|
+
is_returning_user: history.is_returning_user
|
|
31601
|
+
}
|
|
31395
31602
|
});
|
|
31396
31603
|
if (status === "success") {
|
|
31604
|
+
userHistory.recordPublish();
|
|
31397
31605
|
hasAbandonedSession.current = true;
|
|
31398
31606
|
}
|
|
31399
31607
|
},
|
|
31400
|
-
[analytics, getEditorMetrics]
|
|
31608
|
+
[analytics, getEditorMetrics, userHistory]
|
|
31401
31609
|
);
|
|
31402
31610
|
const trackExplicitAbandon = React.useCallback(() => {
|
|
31403
31611
|
if (hasAbandonedSession.current) return;
|
|
31404
31612
|
const metrics = getEditorMetrics();
|
|
31405
31613
|
if (metrics && !metrics.isEmpty) {
|
|
31406
|
-
|
|
31614
|
+
const history = userHistory.getHistory();
|
|
31615
|
+
analytics.trackAbandon({
|
|
31616
|
+
contentLength: metrics.characterCount,
|
|
31617
|
+
hasUnsavedChanges: metrics.hasUnsavedChanges,
|
|
31618
|
+
abandonReason: "user_closed",
|
|
31619
|
+
postType: void 0,
|
|
31620
|
+
userHistoryData: {
|
|
31621
|
+
previous_abandon_count: history.previous_abandon_count,
|
|
31622
|
+
previous_publish_count: history.previous_publish_count,
|
|
31623
|
+
time_since_last_publish_ms: history.time_since_last_publish_ms,
|
|
31624
|
+
is_returning_user: history.is_returning_user
|
|
31625
|
+
}
|
|
31626
|
+
});
|
|
31627
|
+
userHistory.recordAbandon();
|
|
31407
31628
|
hasAbandonedSession.current = true;
|
|
31408
31629
|
}
|
|
31409
|
-
}, [analytics, getEditorMetrics]);
|
|
31630
|
+
}, [analytics, getEditorMetrics, userHistory]);
|
|
31410
31631
|
return {
|
|
31411
31632
|
trackFeature,
|
|
31412
31633
|
trackPublish,
|
|
31413
31634
|
trackExplicitAbandon,
|
|
31414
31635
|
trackTabSwitch: analytics.trackTabSwitch,
|
|
31415
|
-
getEditorMetrics
|
|
31636
|
+
getEditorMetrics,
|
|
31637
|
+
// Expose user history for debugging
|
|
31638
|
+
getUserHistory: () => userHistory.getHistory(),
|
|
31639
|
+
currentSessionId: analytics.getSessionId()
|
|
31416
31640
|
};
|
|
31417
31641
|
}
|
|
31418
31642
|
const PostBuilderAnalyticsProvider = ({
|
|
@@ -31478,56 +31702,66 @@ const PostBuilderEditor = ({
|
|
|
31478
31702
|
isSubmitting,
|
|
31479
31703
|
clearOnSuccess
|
|
31480
31704
|
}
|
|
31481
|
-
) : (
|
|
31482
|
-
|
|
31483
|
-
|
|
31484
|
-
|
|
31485
|
-
|
|
31486
|
-
|
|
31487
|
-
|
|
31488
|
-
|
|
31489
|
-
|
|
31490
|
-
|
|
31491
|
-
|
|
31492
|
-
|
|
31493
|
-
|
|
31494
|
-
|
|
31495
|
-
|
|
31496
|
-
// </DialogClose>
|
|
31497
|
-
// </div>
|
|
31498
|
-
// )}
|
|
31499
|
-
// </DialogHeader>
|
|
31500
|
-
// <PostBuilderEditorInstance
|
|
31501
|
-
// editor={editor}
|
|
31502
|
-
// actions={actions}
|
|
31503
|
-
// editorTab={editorTab}
|
|
31504
|
-
// onSwitchEditor={setEditorTab}
|
|
31505
|
-
// isSubmitting={isSubmitting}
|
|
31506
|
-
// onCreatePost={onCreatePost}
|
|
31507
|
-
// clearOnSuccess={clearOnSuccess}
|
|
31508
|
-
// />
|
|
31509
|
-
// </DialogContent>
|
|
31510
|
-
// </Dialog>
|
|
31511
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "prose-blockquote: flex-1 flex flex-col space-y-3 max-w-full max-h-[calc(100dvh-7rem)]", children: [
|
|
31512
|
-
!hideGroupSelector && /* @__PURE__ */ jsxRuntime.jsx(GroupSelector, { user, store }),
|
|
31513
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
31514
|
-
PostBuilderEditorInstance,
|
|
31515
|
-
{
|
|
31516
|
-
editor,
|
|
31517
|
-
actions,
|
|
31518
|
-
editorTab,
|
|
31519
|
-
onSwitchEditor: setEditorTab,
|
|
31520
|
-
isSubmitting,
|
|
31521
|
-
onCreatePost,
|
|
31522
|
-
clearOnSuccess
|
|
31523
|
-
}
|
|
31524
|
-
)
|
|
31525
|
-
] })
|
|
31526
|
-
) }),
|
|
31705
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "prose-blockquote: flex-1 flex flex-col space-y-3 max-w-full max-h-[calc(100dvh-7rem)]", children: [
|
|
31706
|
+
!hideGroupSelector && /* @__PURE__ */ jsxRuntime.jsx(GroupSelector, { user, store }),
|
|
31707
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
31708
|
+
PostBuilderEditorInstance,
|
|
31709
|
+
{
|
|
31710
|
+
editor,
|
|
31711
|
+
actions,
|
|
31712
|
+
editorTab,
|
|
31713
|
+
onSwitchEditor: setEditorTab,
|
|
31714
|
+
isSubmitting,
|
|
31715
|
+
onCreatePost,
|
|
31716
|
+
clearOnSuccess
|
|
31717
|
+
}
|
|
31718
|
+
)
|
|
31719
|
+
] }) }),
|
|
31527
31720
|
/* @__PURE__ */ jsxRuntime.jsx(Toaster2, { position: "top-center" })
|
|
31528
31721
|
] })
|
|
31529
31722
|
}
|
|
31530
31723
|
);
|
|
31531
31724
|
};
|
|
31725
|
+
const PostBuilderProvider = ({
|
|
31726
|
+
children,
|
|
31727
|
+
apiBaseURL,
|
|
31728
|
+
authToken,
|
|
31729
|
+
toI18N,
|
|
31730
|
+
i18nKeys,
|
|
31731
|
+
logEvent
|
|
31732
|
+
}) => {
|
|
31733
|
+
const t = React.useCallback(
|
|
31734
|
+
(key, fallback) => {
|
|
31735
|
+
const message = toI18N(i18nKeys[key]);
|
|
31736
|
+
if (message) return message;
|
|
31737
|
+
return fallback || key;
|
|
31738
|
+
},
|
|
31739
|
+
[toI18N, i18nKeys]
|
|
31740
|
+
);
|
|
31741
|
+
const api = React.useMemo(() => {
|
|
31742
|
+
const core2 = new CoreApi(apiBaseURL.core, authToken, toI18N);
|
|
31743
|
+
const mfs = new MFSApi(apiBaseURL.mfs, authToken, toI18N);
|
|
31744
|
+
const fileStore = new FilestoreApi(apiBaseURL.fileStore, authToken, toI18N);
|
|
31745
|
+
core2.initApi();
|
|
31746
|
+
mfs.initApi();
|
|
31747
|
+
fileStore.initApi();
|
|
31748
|
+
return {
|
|
31749
|
+
core: core2,
|
|
31750
|
+
mfs,
|
|
31751
|
+
fileStore
|
|
31752
|
+
};
|
|
31753
|
+
}, [authToken, apiBaseURL, toI18N]);
|
|
31754
|
+
const value = React.useMemo(() => {
|
|
31755
|
+
return {
|
|
31756
|
+
authToken,
|
|
31757
|
+
t,
|
|
31758
|
+
i18nKeys,
|
|
31759
|
+
api,
|
|
31760
|
+
logEvent
|
|
31761
|
+
};
|
|
31762
|
+
}, [authToken, t, i18nKeys, api, logEvent]);
|
|
31763
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PostBuilderContext.Provider, { value, children });
|
|
31764
|
+
};
|
|
31532
31765
|
exports.PostBuilderEditor = PostBuilderEditor;
|
|
31766
|
+
exports.PostBuilderEvents = PostBuilderEvents;
|
|
31533
31767
|
exports.PostBuilderProvider = PostBuilderProvider;
|