@realtimexsco/live-chat 1.4.14 → 1.4.16
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/README.md +5 -3
- package/dist/index.cjs +169 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +169 -87
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +18 -7
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -560,8 +560,8 @@ interface ChatFeatures {
|
|
|
560
560
|
/** Show video call button in header (default: `true`) */
|
|
561
561
|
showVideoCall?: boolean;
|
|
562
562
|
/**
|
|
563
|
-
*
|
|
564
|
-
*
|
|
563
|
+
* @deprecated Call permission gates from effective settings now apply the same
|
|
564
|
+
* in DM and group chats. Buttons stay visible; use showPhoneCall/showVideoCall to hide.
|
|
565
565
|
*/
|
|
566
566
|
hideCallActionsInGroupChats?: boolean;
|
|
567
567
|
/** Called when user taps voice call */
|
package/dist/index.d.ts
CHANGED
|
@@ -560,8 +560,8 @@ interface ChatFeatures {
|
|
|
560
560
|
/** Show video call button in header (default: `true`) */
|
|
561
561
|
showVideoCall?: boolean;
|
|
562
562
|
/**
|
|
563
|
-
*
|
|
564
|
-
*
|
|
563
|
+
* @deprecated Call permission gates from effective settings now apply the same
|
|
564
|
+
* in DM and group chats. Buttons stay visible; use showPhoneCall/showVideoCall to hide.
|
|
565
565
|
*/
|
|
566
566
|
hideCallActionsInGroupChats?: boolean;
|
|
567
567
|
/** Called when user taps voice call */
|
package/dist/index.mjs
CHANGED
|
@@ -6878,8 +6878,21 @@ function AdminPermissionTooltip({
|
|
|
6878
6878
|
if (!disabled || !message) {
|
|
6879
6879
|
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
6880
6880
|
}
|
|
6881
|
+
const gatedChildren = React3__default.Children.map(children, (child) => {
|
|
6882
|
+
if (!React3__default.isValidElement(child)) return child;
|
|
6883
|
+
return React3__default.cloneElement(child, {
|
|
6884
|
+
className: cn(child.props.className, "pointer-events-none")
|
|
6885
|
+
});
|
|
6886
|
+
});
|
|
6881
6887
|
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
6882
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
6888
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
6889
|
+
"span",
|
|
6890
|
+
{
|
|
6891
|
+
className: cn("inline-flex cursor-not-allowed", className),
|
|
6892
|
+
tabIndex: 0,
|
|
6893
|
+
children: gatedChildren
|
|
6894
|
+
}
|
|
6895
|
+
) }),
|
|
6883
6896
|
/* @__PURE__ */ jsx(TooltipContent, { side, className: "max-w-[240px] text-xs", children: message })
|
|
6884
6897
|
] });
|
|
6885
6898
|
}
|
|
@@ -7292,9 +7305,34 @@ var PushNotificationToggle = ({
|
|
|
7292
7305
|
children
|
|
7293
7306
|
}) => {
|
|
7294
7307
|
const push = usePushNotifications();
|
|
7295
|
-
const { getPushNotificationGate } = useEffectiveSettingsOptional();
|
|
7308
|
+
const { loading: settingsLoading, getPushNotificationGate } = useEffectiveSettingsOptional();
|
|
7296
7309
|
const adminGate = getPushNotificationGate();
|
|
7297
7310
|
const [isToggling, setIsToggling] = useState(false);
|
|
7311
|
+
const isBootstrapping = push.loading || settingsLoading;
|
|
7312
|
+
if (isBootstrapping && !push.supported) {
|
|
7313
|
+
return /* @__PURE__ */ jsxs(
|
|
7314
|
+
"div",
|
|
7315
|
+
{
|
|
7316
|
+
className: cn(
|
|
7317
|
+
"flex items-center justify-between gap-4 rounded-xl border border-(--chat-border) bg-(--chat-surface) px-4 py-3",
|
|
7318
|
+
className
|
|
7319
|
+
),
|
|
7320
|
+
children: [
|
|
7321
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
|
|
7322
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-(--chat-text)", children: label }),
|
|
7323
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-(--chat-muted)", children: "Loading\u2026" })
|
|
7324
|
+
] }),
|
|
7325
|
+
/* @__PURE__ */ jsx(
|
|
7326
|
+
Loader2,
|
|
7327
|
+
{
|
|
7328
|
+
className: "size-5 shrink-0 animate-spin text-(--chat-theme)",
|
|
7329
|
+
"aria-label": "Loading push notification settings"
|
|
7330
|
+
}
|
|
7331
|
+
)
|
|
7332
|
+
]
|
|
7333
|
+
}
|
|
7334
|
+
);
|
|
7335
|
+
}
|
|
7298
7336
|
if (!push.supported) {
|
|
7299
7337
|
return null;
|
|
7300
7338
|
}
|
|
@@ -7302,8 +7340,8 @@ var PushNotificationToggle = ({
|
|
|
7302
7340
|
const permissionBlocked = push.permission === "denied";
|
|
7303
7341
|
const adminBlocked = !adminGate.enabled;
|
|
7304
7342
|
const notConfigured = !push.configured;
|
|
7305
|
-
const showLoader = isToggling;
|
|
7306
|
-
const isDisabled = showLoader || permissionBlocked || push.loading || adminBlocked || notConfigured;
|
|
7343
|
+
const showLoader = isToggling || isBootstrapping;
|
|
7344
|
+
const isDisabled = showLoader || permissionBlocked || push.loading || settingsLoading || adminBlocked || notConfigured;
|
|
7307
7345
|
const handleChange = async (checked) => {
|
|
7308
7346
|
if (adminBlocked || notConfigured) return;
|
|
7309
7347
|
setIsToggling(true);
|
|
@@ -8975,14 +9013,12 @@ var DefaultHeaderCallActions = ({
|
|
|
8975
9013
|
onVideoCall,
|
|
8976
9014
|
className
|
|
8977
9015
|
}) => {
|
|
8978
|
-
const { components, slotClassName
|
|
9016
|
+
const { components, slotClassName } = useChatCustomizationOptional();
|
|
8979
9017
|
const { getAudioCallGate, getVideoCallGate } = useEffectiveSettingsOptional();
|
|
8980
9018
|
const PhoneSlot = components.PhoneCallButton;
|
|
8981
9019
|
const VideoSlot = components.VideoCallButton;
|
|
8982
|
-
const hideInGroups = features.hideCallActionsInGroupChats ?? false;
|
|
8983
9020
|
const audioGate = getAudioCallGate();
|
|
8984
9021
|
const videoGate = getVideoCallGate();
|
|
8985
|
-
if (hideInGroups && activeChannel.isGroup) return null;
|
|
8986
9022
|
if (!showPhoneCall && !showVideoCall) return null;
|
|
8987
9023
|
const phoneEnabled = showPhoneCall && audioGate.enabled;
|
|
8988
9024
|
const videoEnabled = showVideoCall && videoGate.enabled;
|
|
@@ -8992,6 +9028,7 @@ var DefaultHeaderCallActions = ({
|
|
|
8992
9028
|
{
|
|
8993
9029
|
disabled: !audioGate.enabled,
|
|
8994
9030
|
message: audioGate.disabledReason,
|
|
9031
|
+
side: "bottom",
|
|
8995
9032
|
children: /* @__PURE__ */ jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsx(
|
|
8996
9033
|
PhoneSlot,
|
|
8997
9034
|
{
|
|
@@ -9001,7 +9038,7 @@ var DefaultHeaderCallActions = ({
|
|
|
9001
9038
|
className: cn(
|
|
9002
9039
|
className,
|
|
9003
9040
|
slotClassName("phoneCallButton"),
|
|
9004
|
-
!audioGate.enabled && "
|
|
9041
|
+
!audioGate.enabled && "opacity-40"
|
|
9005
9042
|
)
|
|
9006
9043
|
}
|
|
9007
9044
|
) })
|
|
@@ -9011,6 +9048,7 @@ var DefaultHeaderCallActions = ({
|
|
|
9011
9048
|
{
|
|
9012
9049
|
disabled: !audioGate.enabled,
|
|
9013
9050
|
message: audioGate.disabledReason,
|
|
9051
|
+
side: "bottom",
|
|
9014
9052
|
children: /* @__PURE__ */ jsx(
|
|
9015
9053
|
Button,
|
|
9016
9054
|
{
|
|
@@ -9030,6 +9068,7 @@ var DefaultHeaderCallActions = ({
|
|
|
9030
9068
|
{
|
|
9031
9069
|
disabled: !videoGate.enabled,
|
|
9032
9070
|
message: videoGate.disabledReason,
|
|
9071
|
+
side: "bottom",
|
|
9033
9072
|
children: /* @__PURE__ */ jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsx(
|
|
9034
9073
|
VideoSlot,
|
|
9035
9074
|
{
|
|
@@ -9039,7 +9078,7 @@ var DefaultHeaderCallActions = ({
|
|
|
9039
9078
|
className: cn(
|
|
9040
9079
|
className,
|
|
9041
9080
|
slotClassName("videoCallButton"),
|
|
9042
|
-
!videoGate.enabled && "
|
|
9081
|
+
!videoGate.enabled && "opacity-40"
|
|
9043
9082
|
)
|
|
9044
9083
|
}
|
|
9045
9084
|
) })
|
|
@@ -9049,6 +9088,7 @@ var DefaultHeaderCallActions = ({
|
|
|
9049
9088
|
{
|
|
9050
9089
|
disabled: !videoGate.enabled,
|
|
9051
9090
|
message: videoGate.disabledReason,
|
|
9091
|
+
side: "bottom",
|
|
9052
9092
|
children: /* @__PURE__ */ jsx(
|
|
9053
9093
|
Button,
|
|
9054
9094
|
{
|
|
@@ -9066,16 +9106,13 @@ var DefaultHeaderCallActions = ({
|
|
|
9066
9106
|
] });
|
|
9067
9107
|
};
|
|
9068
9108
|
var HeaderCallActions = (props) => {
|
|
9069
|
-
const { components, slotClassName
|
|
9109
|
+
const { components, slotClassName } = useChatCustomizationOptional();
|
|
9070
9110
|
const Custom = components.HeaderCallActions;
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
if (!showPhoneCall && !showVideoCall) return null;
|
|
9077
|
-
}
|
|
9078
|
-
return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-0.5", slotClassName("headerCallActions")), children: Custom ? /* @__PURE__ */ jsx(Custom, { ...props }) : /* @__PURE__ */ jsx(DefaultHeaderCallActions, { ...props }) });
|
|
9111
|
+
const showPhoneCall = props.showPhoneCall ?? true;
|
|
9112
|
+
const showVideoCall = props.showVideoCall ?? true;
|
|
9113
|
+
if (!showPhoneCall && !showVideoCall) return null;
|
|
9114
|
+
const useCustom = Custom != null && Custom !== HeaderCallActions;
|
|
9115
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-0.5", slotClassName("headerCallActions")), children: useCustom ? /* @__PURE__ */ jsx(Custom, { ...props }) : /* @__PURE__ */ jsx(DefaultHeaderCallActions, { ...props }) });
|
|
9079
9116
|
};
|
|
9080
9117
|
var HeaderCallActions_default = HeaderCallActions;
|
|
9081
9118
|
function OptionsMenuItem({
|
|
@@ -12894,9 +12931,91 @@ init_useStore();
|
|
|
12894
12931
|
|
|
12895
12932
|
// src/hooks/useGroupInfo.ts
|
|
12896
12933
|
init_useStore();
|
|
12934
|
+
|
|
12935
|
+
// src/lib/effective-settings.helpers.ts
|
|
12936
|
+
function minutesToMs(minutes) {
|
|
12937
|
+
return Math.max(0, minutes) * 60 * 1e3;
|
|
12938
|
+
}
|
|
12939
|
+
function getEditWindowMs(timers, isGroup) {
|
|
12940
|
+
return minutesToMs(isGroup ? timers.groupEditMinutes : timers.dmEditMinutes);
|
|
12941
|
+
}
|
|
12942
|
+
function getDeleteWindowMs(timers, isGroup) {
|
|
12943
|
+
return minutesToMs(
|
|
12944
|
+
isGroup ? timers.groupDeleteMinutes : timers.dmDeleteMinutes
|
|
12945
|
+
);
|
|
12946
|
+
}
|
|
12947
|
+
function isWithinWindow(createdAt, windowMs) {
|
|
12948
|
+
if (!createdAt) return false;
|
|
12949
|
+
const date = new Date(createdAt);
|
|
12950
|
+
if (isNaN(date.getTime())) return false;
|
|
12951
|
+
const diff = Date.now() - date.getTime();
|
|
12952
|
+
return diff >= 0 && diff < windowMs;
|
|
12953
|
+
}
|
|
12954
|
+
function isWithinMessageEditWindow(createdAt, timers, isGroup) {
|
|
12955
|
+
return isWithinWindow(createdAt, getEditWindowMs(timers, isGroup));
|
|
12956
|
+
}
|
|
12957
|
+
function isWithinMessageDeleteWindow(createdAt, timers, isGroup) {
|
|
12958
|
+
return isWithinWindow(createdAt, getDeleteWindowMs(timers, isGroup));
|
|
12959
|
+
}
|
|
12960
|
+
function allowsAllMimeTypes(allowedMimeTypes) {
|
|
12961
|
+
return allowedMimeTypes.some((pattern) => {
|
|
12962
|
+
const normalized = pattern.trim().toLowerCase();
|
|
12963
|
+
return normalized === "*" || normalized === "*/*";
|
|
12964
|
+
});
|
|
12965
|
+
}
|
|
12966
|
+
function matchesAllowedMimeType(fileType, allowedMimeTypes) {
|
|
12967
|
+
if (!allowedMimeTypes.length) return false;
|
|
12968
|
+
if (allowsAllMimeTypes(allowedMimeTypes)) return true;
|
|
12969
|
+
const mime = (fileType || "application/octet-stream").toLowerCase();
|
|
12970
|
+
return allowedMimeTypes.some((pattern) => {
|
|
12971
|
+
const normalized = pattern.trim().toLowerCase();
|
|
12972
|
+
if (!normalized) return false;
|
|
12973
|
+
if (normalized.endsWith("/*")) {
|
|
12974
|
+
const prefix = normalized.slice(0, -1);
|
|
12975
|
+
return mime.startsWith(prefix);
|
|
12976
|
+
}
|
|
12977
|
+
return mime === normalized;
|
|
12978
|
+
});
|
|
12979
|
+
}
|
|
12980
|
+
function buildAcceptFromMimeTypes(allowedMimeTypes) {
|
|
12981
|
+
if (allowsAllMimeTypes(allowedMimeTypes)) return "";
|
|
12982
|
+
return allowedMimeTypes.map((type) => type.trim()).filter(Boolean).join(",");
|
|
12983
|
+
}
|
|
12984
|
+
function formatFileSizeMB(sizeBytes) {
|
|
12985
|
+
return `${(sizeBytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
12986
|
+
}
|
|
12987
|
+
var GROUP_PERMISSION_KEYS = [
|
|
12988
|
+
"onlyAdminCanSendMessage",
|
|
12989
|
+
"onlyAdminCanEditInfo",
|
|
12990
|
+
"senderCanEditMessage",
|
|
12991
|
+
"allowMemberAdd",
|
|
12992
|
+
"allowMemberRemove",
|
|
12993
|
+
"moderationEnabled"
|
|
12994
|
+
];
|
|
12995
|
+
function resolveGroupPermissions(conversationPermissions, defaults, locked = []) {
|
|
12996
|
+
const next = { ...defaults };
|
|
12997
|
+
if (conversationPermissions) {
|
|
12998
|
+
for (const key of GROUP_PERMISSION_KEYS) {
|
|
12999
|
+
const value = conversationPermissions[key];
|
|
13000
|
+
if (typeof value === "boolean") {
|
|
13001
|
+
next[key] = value;
|
|
13002
|
+
}
|
|
13003
|
+
}
|
|
13004
|
+
}
|
|
13005
|
+
for (const key of locked) {
|
|
13006
|
+
if (GROUP_PERMISSION_KEYS.includes(String(key))) {
|
|
13007
|
+
const typedKey = key;
|
|
13008
|
+
next[typedKey] = defaults[typedKey];
|
|
13009
|
+
}
|
|
13010
|
+
}
|
|
13011
|
+
return next;
|
|
13012
|
+
}
|
|
13013
|
+
|
|
13014
|
+
// src/hooks/useGroupInfo.ts
|
|
12897
13015
|
var useGroupInfo = (conversationId) => {
|
|
12898
13016
|
const conversationInfos = useStore((s) => s.conversationInfos);
|
|
12899
13017
|
const loggedUserDetails = useStore((s) => s.loggedUserDetails);
|
|
13018
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
12900
13019
|
const info = conversationId ? conversationInfos[conversationId] : null;
|
|
12901
13020
|
const isAdmin = useMemo(() => {
|
|
12902
13021
|
if (!info || !loggedUserDetails) return false;
|
|
@@ -12912,7 +13031,14 @@ var useGroupInfo = (conversationId) => {
|
|
|
12912
13031
|
}
|
|
12913
13032
|
return String(ownerId) === String(loggedUserDetails._id);
|
|
12914
13033
|
}, [info, loggedUserDetails]);
|
|
12915
|
-
const permissions =
|
|
13034
|
+
const permissions = useMemo(() => {
|
|
13035
|
+
if (!info) return null;
|
|
13036
|
+
return resolveGroupPermissions(
|
|
13037
|
+
info.groupPermissions,
|
|
13038
|
+
settings.groupPolicy.defaults,
|
|
13039
|
+
settings.groupPolicy.locked
|
|
13040
|
+
);
|
|
13041
|
+
}, [info, settings.groupPolicy.defaults, settings.groupPolicy.locked]);
|
|
12916
13042
|
const userPermissions = useMemo(() => {
|
|
12917
13043
|
return {
|
|
12918
13044
|
canSendMessage: isOwner || isAdmin || !permissions?.onlyAdminCanSendMessage,
|
|
@@ -12920,7 +13046,6 @@ var useGroupInfo = (conversationId) => {
|
|
|
12920
13046
|
canAddMember: isOwner || !!permissions?.allowMemberAdd,
|
|
12921
13047
|
canRemoveMember: isOwner || !!permissions?.allowMemberRemove,
|
|
12922
13048
|
canEditMessage: isOwner || isAdmin || !!permissions?.senderCanEditMessage
|
|
12923
|
-
// You can add more derived permissions here as needed
|
|
12924
13049
|
};
|
|
12925
13050
|
}, [isOwner, isAdmin, permissions]);
|
|
12926
13051
|
return {
|
|
@@ -13347,14 +13472,20 @@ var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo
|
|
|
13347
13472
|
const [permissions, setPermissions] = useState(null);
|
|
13348
13473
|
const [isSaving, setIsSaving] = useState(false);
|
|
13349
13474
|
useEffect(() => {
|
|
13350
|
-
if (
|
|
13351
|
-
|
|
13352
|
-
|
|
13353
|
-
|
|
13354
|
-
|
|
13355
|
-
|
|
13356
|
-
|
|
13357
|
-
|
|
13475
|
+
if (!isOpen) return;
|
|
13476
|
+
setPermissions(
|
|
13477
|
+
resolveGroupPermissions(
|
|
13478
|
+
conversationInfo?.groupPermissions,
|
|
13479
|
+
settings.groupPolicy.defaults,
|
|
13480
|
+
settings.groupPolicy.locked
|
|
13481
|
+
)
|
|
13482
|
+
);
|
|
13483
|
+
}, [
|
|
13484
|
+
isOpen,
|
|
13485
|
+
conversationInfo?.groupPermissions,
|
|
13486
|
+
settings.groupPolicy.defaults,
|
|
13487
|
+
settings.groupPolicy.locked
|
|
13488
|
+
]);
|
|
13358
13489
|
if (!conversationId || !permissions) return null;
|
|
13359
13490
|
const handleToggle = (key) => {
|
|
13360
13491
|
if (isGroupPermissionLocked(key)) return;
|
|
@@ -13364,7 +13495,12 @@ var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo
|
|
|
13364
13495
|
if (!conversationId || !permissions) return;
|
|
13365
13496
|
setIsSaving(true);
|
|
13366
13497
|
try {
|
|
13367
|
-
|
|
13498
|
+
const payload = resolveGroupPermissions(
|
|
13499
|
+
permissions,
|
|
13500
|
+
settings.groupPolicy.defaults,
|
|
13501
|
+
settings.groupPolicy.locked
|
|
13502
|
+
);
|
|
13503
|
+
await updateGroupPermissions(conversationId, payload);
|
|
13368
13504
|
onOpenChange(false);
|
|
13369
13505
|
} finally {
|
|
13370
13506
|
setIsSaving(false);
|
|
@@ -13374,8 +13510,8 @@ var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo
|
|
|
13374
13510
|
{ key: "onlyAdminCanSendMessage", label: "Only Admin Can Send Message", desc: "Restricts message sending to group administrators only." },
|
|
13375
13511
|
{ key: "onlyAdminCanEditInfo", label: "Only Admin Can Edit Info", desc: "Only admins can change group name, description, and avatar." },
|
|
13376
13512
|
{ key: "senderCanEditMessage", label: "Sender Can Edit Message", desc: "Allows users to edit their own sent messages." },
|
|
13377
|
-
{ key: "allowMemberAdd", label: "
|
|
13378
|
-
{ key: "allowMemberRemove", label: "
|
|
13513
|
+
{ key: "allowMemberAdd", label: "Allow Members to Add", desc: "Allows group members to add new participants." },
|
|
13514
|
+
{ key: "allowMemberRemove", label: "Allow Members to Remove", desc: "Allows group members to remove other participants." },
|
|
13379
13515
|
{ key: "moderationEnabled", label: "Moderation Enabled", desc: "Enables advanced message moderation features." }
|
|
13380
13516
|
];
|
|
13381
13517
|
return /* @__PURE__ */ jsx(Sheet, { open: isOpen, onOpenChange, children: /* @__PURE__ */ jsxs(ChatSheetContent, { showCloseButton: true, className: "sm:max-w-[380px]", children: [
|
|
@@ -13391,6 +13527,7 @@ var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo
|
|
|
13391
13527
|
/* @__PURE__ */ jsx("h3", { className: "mb-1 px-0.5 text-[10px] font-semibold uppercase tracking-wide text-(--chat-muted)", children: "Permissions" }),
|
|
13392
13528
|
/* @__PURE__ */ jsx("div", { className: "rounded-lg border border-(--chat-border) px-3", children: permissionItems.map((item, index) => {
|
|
13393
13529
|
const locked = isGroupPermissionLocked(item.key);
|
|
13530
|
+
const checked = permissions[item.key];
|
|
13394
13531
|
return /* @__PURE__ */ jsxs(
|
|
13395
13532
|
"div",
|
|
13396
13533
|
{
|
|
@@ -13415,7 +13552,7 @@ var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo
|
|
|
13415
13552
|
size: "sm",
|
|
13416
13553
|
className: "mt-0.5 shrink-0 data-[state=checked]:bg-(--chat-theme) data-[state=unchecked]:bg-(--chat-border)",
|
|
13417
13554
|
disabled: locked,
|
|
13418
|
-
checked
|
|
13555
|
+
checked,
|
|
13419
13556
|
onCheckedChange: () => handleToggle(item.key)
|
|
13420
13557
|
}
|
|
13421
13558
|
)
|
|
@@ -14959,61 +15096,6 @@ function resolveForwardItems(selectedKeys, messages) {
|
|
|
14959
15096
|
|
|
14960
15097
|
// src/chat/lib/chat-edit-window.ts
|
|
14961
15098
|
init_settings_types();
|
|
14962
|
-
|
|
14963
|
-
// src/lib/effective-settings.helpers.ts
|
|
14964
|
-
function minutesToMs(minutes) {
|
|
14965
|
-
return Math.max(0, minutes) * 60 * 1e3;
|
|
14966
|
-
}
|
|
14967
|
-
function getEditWindowMs(timers, isGroup) {
|
|
14968
|
-
return minutesToMs(isGroup ? timers.groupEditMinutes : timers.dmEditMinutes);
|
|
14969
|
-
}
|
|
14970
|
-
function getDeleteWindowMs(timers, isGroup) {
|
|
14971
|
-
return minutesToMs(
|
|
14972
|
-
isGroup ? timers.groupDeleteMinutes : timers.dmDeleteMinutes
|
|
14973
|
-
);
|
|
14974
|
-
}
|
|
14975
|
-
function isWithinWindow(createdAt, windowMs) {
|
|
14976
|
-
if (!createdAt) return false;
|
|
14977
|
-
const date = new Date(createdAt);
|
|
14978
|
-
if (isNaN(date.getTime())) return false;
|
|
14979
|
-
const diff = Date.now() - date.getTime();
|
|
14980
|
-
return diff >= 0 && diff < windowMs;
|
|
14981
|
-
}
|
|
14982
|
-
function isWithinMessageEditWindow(createdAt, timers, isGroup) {
|
|
14983
|
-
return isWithinWindow(createdAt, getEditWindowMs(timers, isGroup));
|
|
14984
|
-
}
|
|
14985
|
-
function isWithinMessageDeleteWindow(createdAt, timers, isGroup) {
|
|
14986
|
-
return isWithinWindow(createdAt, getDeleteWindowMs(timers, isGroup));
|
|
14987
|
-
}
|
|
14988
|
-
function allowsAllMimeTypes(allowedMimeTypes) {
|
|
14989
|
-
return allowedMimeTypes.some((pattern) => {
|
|
14990
|
-
const normalized = pattern.trim().toLowerCase();
|
|
14991
|
-
return normalized === "*" || normalized === "*/*";
|
|
14992
|
-
});
|
|
14993
|
-
}
|
|
14994
|
-
function matchesAllowedMimeType(fileType, allowedMimeTypes) {
|
|
14995
|
-
if (!allowedMimeTypes.length) return false;
|
|
14996
|
-
if (allowsAllMimeTypes(allowedMimeTypes)) return true;
|
|
14997
|
-
const mime = (fileType || "application/octet-stream").toLowerCase();
|
|
14998
|
-
return allowedMimeTypes.some((pattern) => {
|
|
14999
|
-
const normalized = pattern.trim().toLowerCase();
|
|
15000
|
-
if (!normalized) return false;
|
|
15001
|
-
if (normalized.endsWith("/*")) {
|
|
15002
|
-
const prefix = normalized.slice(0, -1);
|
|
15003
|
-
return mime.startsWith(prefix);
|
|
15004
|
-
}
|
|
15005
|
-
return mime === normalized;
|
|
15006
|
-
});
|
|
15007
|
-
}
|
|
15008
|
-
function buildAcceptFromMimeTypes(allowedMimeTypes) {
|
|
15009
|
-
if (allowsAllMimeTypes(allowedMimeTypes)) return "";
|
|
15010
|
-
return allowedMimeTypes.map((type) => type.trim()).filter(Boolean).join(",");
|
|
15011
|
-
}
|
|
15012
|
-
function formatFileSizeMB(sizeBytes) {
|
|
15013
|
-
return `${(sizeBytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
15014
|
-
}
|
|
15015
|
-
|
|
15016
|
-
// src/chat/lib/chat-edit-window.ts
|
|
15017
15099
|
var FALLBACK_TIMERS = DEFAULT_EFFECTIVE_SETTINGS.messageTimers;
|
|
15018
15100
|
function isWithinMessageEditWindow2(createdAt, isGroup, timers = FALLBACK_TIMERS) {
|
|
15019
15101
|
return isWithinMessageEditWindow(createdAt, timers, isGroup);
|