@ermis-network/ermis-chat-react 1.0.0 → 1.0.2
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 +9 -0
- package/dist/index.cjs +752 -333
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +382 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +88 -1
- package/dist/index.d.ts +88 -1
- package/dist/index.mjs +691 -274
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/ChannelInfo/AddMemberModal.tsx +48 -174
- package/src/components/ChannelList.tsx +5 -0
- package/src/components/CreateChannelModal.tsx +274 -0
- package/src/components/UserPicker.tsx +377 -0
- package/src/index.ts +11 -0
- package/src/styles/_create-channel-modal.css +183 -0
- package/src/styles/_user-picker.css +268 -0
- package/src/styles/index.css +3 -0
- package/src/types.ts +100 -0
package/dist/index.mjs
CHANGED
|
@@ -652,6 +652,9 @@ function getLastMessagePreview(channel) {
|
|
|
652
652
|
const userMap = buildUserMap(channel.state);
|
|
653
653
|
return { text: parseSignalMessage(rawText, userMap), user: "" };
|
|
654
654
|
}
|
|
655
|
+
if (msgType === "sticker" || lastMsg.sticker_url) {
|
|
656
|
+
return { text: "Sticker", user: lastMsg.user?.name || lastMsg.user_id || "" };
|
|
657
|
+
}
|
|
655
658
|
let displayText = rawText;
|
|
656
659
|
if (!displayText && lastMsg.attachments && lastMsg.attachments.length > 0) {
|
|
657
660
|
const att = lastMsg.attachments[0];
|
|
@@ -4389,7 +4392,7 @@ var MessageInput = React24.memo(({
|
|
|
4389
4392
|
MessageInput.displayName = "MessageInput";
|
|
4390
4393
|
|
|
4391
4394
|
// src/components/ChannelInfo/ChannelInfo.tsx
|
|
4392
|
-
import
|
|
4395
|
+
import React37, { useState as useState33, useCallback as useCallback23 } from "react";
|
|
4393
4396
|
|
|
4394
4397
|
// src/components/ChannelInfo/ChannelInfoTabs.tsx
|
|
4395
4398
|
import React30, { useState as useState27, useEffect as useEffect23, useMemo as useMemo18, useCallback as useCallback18, useDeferredValue as useDeferredValue2 } from "react";
|
|
@@ -4925,37 +4928,49 @@ var DefaultChannelInfoTabs = React30.memo(({
|
|
|
4925
4928
|
});
|
|
4926
4929
|
|
|
4927
4930
|
// src/components/ChannelInfo/AddMemberModal.tsx
|
|
4928
|
-
import
|
|
4931
|
+
import { useState as useState29, useMemo as useMemo20, useCallback as useCallback20 } from "react";
|
|
4932
|
+
|
|
4933
|
+
// src/components/UserPicker.tsx
|
|
4934
|
+
import React31, { useState as useState28, useEffect as useEffect24, useMemo as useMemo19, useCallback as useCallback19, useRef as useRef14, useTransition } from "react";
|
|
4929
4935
|
import { VList as VList5 } from "virtua";
|
|
4930
4936
|
import { jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
4931
|
-
var
|
|
4932
|
-
var
|
|
4933
|
-
var
|
|
4937
|
+
var DEFAULT_PAGE_SIZE = 30;
|
|
4938
|
+
var SEARCH_DEBOUNCE_MS = 500;
|
|
4939
|
+
var LIST_STYLE = { height: "100%" };
|
|
4940
|
+
var CheckIcon = () => /* @__PURE__ */ jsx32("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx32("polyline", { points: "20 6 9 17 4 12" }) });
|
|
4934
4941
|
var DefaultUserItem = React31.memo(({
|
|
4935
4942
|
user,
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
"
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4943
|
+
selected,
|
|
4944
|
+
disabled,
|
|
4945
|
+
mode,
|
|
4946
|
+
onToggle,
|
|
4947
|
+
AvatarComponent
|
|
4948
|
+
}) => {
|
|
4949
|
+
const handleClick = useCallback19(() => {
|
|
4950
|
+
if (!disabled) onToggle(user);
|
|
4951
|
+
}, [disabled, onToggle, user]);
|
|
4952
|
+
const inputClass = [
|
|
4953
|
+
"ermis-user-picker__input",
|
|
4954
|
+
mode === "radio" ? "ermis-user-picker__input--radio" : "ermis-user-picker__input--checkbox",
|
|
4955
|
+
selected ? "ermis-user-picker__input--checked" : ""
|
|
4956
|
+
].join(" ");
|
|
4957
|
+
const itemClass = [
|
|
4958
|
+
"ermis-user-picker__item",
|
|
4959
|
+
selected ? "ermis-user-picker__item--selected" : "",
|
|
4960
|
+
disabled ? "ermis-user-picker__item--disabled" : ""
|
|
4961
|
+
].join(" ");
|
|
4962
|
+
const detail = user.email || user.phone || "";
|
|
4963
|
+
return /* @__PURE__ */ jsxs28("div", { className: itemClass, onClick: handleClick, role: "option", "aria-selected": selected, children: [
|
|
4964
|
+
/* @__PURE__ */ jsx32("div", { className: inputClass, children: selected && /* @__PURE__ */ jsx32(CheckIcon, {}) }),
|
|
4965
|
+
/* @__PURE__ */ jsx32(AvatarComponent, { image: user.avatar, name: user.name || user.id, size: 36 }),
|
|
4966
|
+
/* @__PURE__ */ jsxs28("div", { className: "ermis-user-picker__info", children: [
|
|
4967
|
+
/* @__PURE__ */ jsx32("span", { className: "ermis-user-picker__name", children: user.name || user.id }),
|
|
4968
|
+
detail && /* @__PURE__ */ jsx32("span", { className: "ermis-user-picker__detail", children: detail })
|
|
4969
|
+
] })
|
|
4970
|
+
] });
|
|
4971
|
+
});
|
|
4957
4972
|
DefaultUserItem.displayName = "DefaultUserItem";
|
|
4958
|
-
var DefaultSearchInput = ({ value, onChange, placeholder }) => /* @__PURE__ */ jsxs28("div", { className: "ermis-
|
|
4973
|
+
var DefaultSearchInput = ({ value, onChange, placeholder }) => /* @__PURE__ */ jsxs28("div", { className: "ermis-user-picker__search", children: [
|
|
4959
4974
|
/* @__PURE__ */ jsxs28("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
4960
4975
|
/* @__PURE__ */ jsx32("circle", { cx: "11", cy: "11", r: "8" }),
|
|
4961
4976
|
/* @__PURE__ */ jsx32("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })
|
|
@@ -4971,33 +4986,69 @@ var DefaultSearchInput = ({ value, onChange, placeholder }) => /* @__PURE__ */ j
|
|
|
4971
4986
|
}
|
|
4972
4987
|
)
|
|
4973
4988
|
] });
|
|
4974
|
-
var
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
onClose,
|
|
4989
|
+
var DefaultSelectedBox = React31.memo(({
|
|
4990
|
+
users,
|
|
4991
|
+
onRemove,
|
|
4978
4992
|
AvatarComponent,
|
|
4979
|
-
|
|
4993
|
+
emptyLabel
|
|
4994
|
+
}) => /* @__PURE__ */ jsxs28("div", { className: "ermis-user-picker__selected-box", children: [
|
|
4995
|
+
users.length === 0 && emptyLabel && /* @__PURE__ */ jsx32("span", { className: "ermis-user-picker__selected-empty", children: emptyLabel }),
|
|
4996
|
+
users.map((u) => /* @__PURE__ */ jsxs28("div", { className: "ermis-user-picker__chip", children: [
|
|
4997
|
+
/* @__PURE__ */ jsx32(AvatarComponent, { image: u.avatar, name: u.name || u.id, size: 20 }),
|
|
4998
|
+
/* @__PURE__ */ jsx32("span", { className: "ermis-user-picker__chip-name", children: u.name || u.id }),
|
|
4999
|
+
/* @__PURE__ */ jsx32(
|
|
5000
|
+
"button",
|
|
5001
|
+
{
|
|
5002
|
+
className: "ermis-user-picker__chip-remove",
|
|
5003
|
+
onClick: () => onRemove(u.id),
|
|
5004
|
+
"aria-label": `Remove ${u.name || u.id}`,
|
|
5005
|
+
children: /* @__PURE__ */ jsxs28("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
5006
|
+
/* @__PURE__ */ jsx32("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
5007
|
+
/* @__PURE__ */ jsx32("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
5008
|
+
] })
|
|
5009
|
+
}
|
|
5010
|
+
)
|
|
5011
|
+
] }, u.id))
|
|
5012
|
+
] }));
|
|
5013
|
+
DefaultSelectedBox.displayName = "DefaultSelectedBox";
|
|
5014
|
+
var UserPicker = ({
|
|
5015
|
+
mode,
|
|
5016
|
+
onSelectionChange,
|
|
5017
|
+
excludeUserIds,
|
|
5018
|
+
initialSelectedUsers,
|
|
5019
|
+
pageSize = DEFAULT_PAGE_SIZE,
|
|
5020
|
+
AvatarComponent = Avatar,
|
|
5021
|
+
UserItemComponent,
|
|
5022
|
+
SelectedBoxComponent,
|
|
5023
|
+
SearchInputComponent,
|
|
4980
5024
|
searchPlaceholder = "Search by name, email or phone...",
|
|
4981
5025
|
loadingText = "Loading users...",
|
|
4982
5026
|
emptyText = "No users found.",
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
addedLabel = "Added",
|
|
4986
|
-
UserItemComponent,
|
|
4987
|
-
SearchInputComponent
|
|
5027
|
+
loadingMoreText = "Loading more...",
|
|
5028
|
+
selectedEmptyLabel
|
|
4988
5029
|
}) => {
|
|
4989
5030
|
const { client } = useChatClient();
|
|
4990
|
-
const
|
|
5031
|
+
const currentUserId = client?.userID;
|
|
5032
|
+
const [allUsers, setAllUsers] = useState28([]);
|
|
5033
|
+
const [page, setPage] = useState28(1);
|
|
5034
|
+
const [hasMore, setHasMore] = useState28(true);
|
|
5035
|
+
const [loading, setLoading] = useState28(true);
|
|
5036
|
+
const [loadingMore, setLoadingMore] = useState28(false);
|
|
4991
5037
|
const [remoteUsers, setRemoteUsers] = useState28([]);
|
|
5038
|
+
const [isSearching, setIsSearching] = useState28(false);
|
|
4992
5039
|
const [searchInput, setSearchInput] = useState28("");
|
|
4993
5040
|
const [search, setSearch] = useState28("");
|
|
4994
5041
|
const [isPendingFilter, startTransition] = useTransition();
|
|
4995
|
-
const [
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
5042
|
+
const [selectedMap, setSelectedMap] = useState28(() => {
|
|
5043
|
+
const map = /* @__PURE__ */ new Map();
|
|
5044
|
+
initialSelectedUsers?.forEach((u) => map.set(u.id, u));
|
|
5045
|
+
return map;
|
|
5046
|
+
});
|
|
5047
|
+
const vlistRef = useRef14(null);
|
|
4999
5048
|
const UserRow = UserItemComponent || DefaultUserItem;
|
|
5000
5049
|
const SearchInput = SearchInputComponent || DefaultSearchInput;
|
|
5050
|
+
const SelectedBox = SelectedBoxComponent || DefaultSelectedBox;
|
|
5051
|
+
const excludeSet = useMemo19(() => new Set(excludeUserIds || []), [excludeUserIds]);
|
|
5001
5052
|
const handleSearchChange = useCallback19((e) => {
|
|
5002
5053
|
const val = e.target.value;
|
|
5003
5054
|
setSearchInput(val);
|
|
@@ -5010,12 +5061,15 @@ var AddMemberModal = ({
|
|
|
5010
5061
|
const fetchUsers = async () => {
|
|
5011
5062
|
if (!client) return;
|
|
5012
5063
|
try {
|
|
5013
|
-
|
|
5064
|
+
setLoading(true);
|
|
5065
|
+
const response = await client.queryUsers(String(pageSize), 1);
|
|
5014
5066
|
if (active && response.data) {
|
|
5015
|
-
|
|
5067
|
+
setAllUsers(response.data);
|
|
5068
|
+
setHasMore(response.data.length >= pageSize);
|
|
5069
|
+
setPage(1);
|
|
5016
5070
|
}
|
|
5017
5071
|
} catch (err) {
|
|
5018
|
-
console.error("Error fetching users:", err);
|
|
5072
|
+
console.error("[UserPicker] Error fetching users:", err);
|
|
5019
5073
|
} finally {
|
|
5020
5074
|
if (active) setLoading(false);
|
|
5021
5075
|
}
|
|
@@ -5024,17 +5078,38 @@ var AddMemberModal = ({
|
|
|
5024
5078
|
return () => {
|
|
5025
5079
|
active = false;
|
|
5026
5080
|
};
|
|
5027
|
-
}, [client]);
|
|
5081
|
+
}, [client, pageSize]);
|
|
5082
|
+
const loadMore = useCallback19(async () => {
|
|
5083
|
+
if (!client || loadingMore || !hasMore || search.trim()) return;
|
|
5084
|
+
const nextPage = page + 1;
|
|
5085
|
+
setLoadingMore(true);
|
|
5086
|
+
try {
|
|
5087
|
+
const response = await client.queryUsers(String(pageSize), nextPage);
|
|
5088
|
+
if (response.data) {
|
|
5089
|
+
setAllUsers((prev) => {
|
|
5090
|
+
const existingIds = new Set(prev.map((u) => u.id));
|
|
5091
|
+
const newUsers = response.data.filter((u) => !existingIds.has(u.id));
|
|
5092
|
+
return [...prev, ...newUsers];
|
|
5093
|
+
});
|
|
5094
|
+
setHasMore(response.data.length >= pageSize);
|
|
5095
|
+
setPage(nextPage);
|
|
5096
|
+
}
|
|
5097
|
+
} catch (err) {
|
|
5098
|
+
console.error("[UserPicker] Error loading more users:", err);
|
|
5099
|
+
} finally {
|
|
5100
|
+
setLoadingMore(false);
|
|
5101
|
+
}
|
|
5102
|
+
}, [client, loadingMore, hasMore, page, pageSize, search]);
|
|
5028
5103
|
const localFilteredUsers = useMemo19(() => {
|
|
5029
|
-
if (!search.trim()) return initialUsers;
|
|
5030
5104
|
const term = search.toLowerCase().trim();
|
|
5031
|
-
|
|
5105
|
+
if (!term) return allUsers;
|
|
5106
|
+
return allUsers.filter((u) => {
|
|
5107
|
+
const name = (u.name || "").toLowerCase();
|
|
5032
5108
|
const email = (u.email || "").toLowerCase();
|
|
5033
5109
|
const phone = (u.phone || "").toLowerCase();
|
|
5034
|
-
|
|
5035
|
-
return email.includes(term) || phone.includes(term) || name.includes(term);
|
|
5110
|
+
return name.includes(term) || email.includes(term) || phone.includes(term);
|
|
5036
5111
|
});
|
|
5037
|
-
}, [search,
|
|
5112
|
+
}, [search, allUsers]);
|
|
5038
5113
|
useEffect24(() => {
|
|
5039
5114
|
if (!search.trim() || localFilteredUsers.length > 0) {
|
|
5040
5115
|
setRemoteUsers([]);
|
|
@@ -5050,33 +5125,69 @@ var AddMemberModal = ({
|
|
|
5050
5125
|
setRemoteUsers(response.data);
|
|
5051
5126
|
}
|
|
5052
5127
|
} catch (err) {
|
|
5053
|
-
console.error("Error searching remote users:", err);
|
|
5128
|
+
console.error("[UserPicker] Error searching remote users:", err);
|
|
5054
5129
|
} finally {
|
|
5055
5130
|
if (!cancelled) setIsSearching(false);
|
|
5056
5131
|
}
|
|
5057
|
-
},
|
|
5132
|
+
}, SEARCH_DEBOUNCE_MS);
|
|
5058
5133
|
return () => {
|
|
5059
5134
|
cancelled = true;
|
|
5060
5135
|
clearTimeout(timer);
|
|
5061
5136
|
};
|
|
5062
|
-
}, [search, localFilteredUsers.length, client]);
|
|
5137
|
+
}, [search, localFilteredUsers.length, client, excludeSet]);
|
|
5063
5138
|
const usersToDisplay = search.trim() && localFilteredUsers.length === 0 ? remoteUsers : localFilteredUsers;
|
|
5064
5139
|
const isListLoading = loading || isSearching || isPendingFilter;
|
|
5065
|
-
const
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5140
|
+
const handleToggle = useCallback19((user) => {
|
|
5141
|
+
if (user.id === currentUserId || excludeSet.has(user.id)) return;
|
|
5142
|
+
setSelectedMap((prev) => {
|
|
5143
|
+
const next = new Map(prev);
|
|
5144
|
+
if (mode === "radio") {
|
|
5145
|
+
if (next.has(user.id)) {
|
|
5146
|
+
next.clear();
|
|
5147
|
+
} else {
|
|
5148
|
+
next.clear();
|
|
5149
|
+
next.set(user.id, user);
|
|
5150
|
+
}
|
|
5151
|
+
} else {
|
|
5152
|
+
if (next.has(user.id)) {
|
|
5153
|
+
next.delete(user.id);
|
|
5154
|
+
} else {
|
|
5155
|
+
next.set(user.id, user);
|
|
5156
|
+
}
|
|
5157
|
+
}
|
|
5158
|
+
return next;
|
|
5159
|
+
});
|
|
5160
|
+
}, [mode, currentUserId, excludeSet]);
|
|
5161
|
+
useEffect24(() => {
|
|
5162
|
+
onSelectionChange?.(Array.from(selectedMap.values()));
|
|
5163
|
+
}, [selectedMap, onSelectionChange]);
|
|
5164
|
+
const handleRemoveSelected = useCallback19((userId) => {
|
|
5165
|
+
setSelectedMap((prev) => {
|
|
5166
|
+
const next = new Map(prev);
|
|
5167
|
+
next.delete(userId);
|
|
5168
|
+
return next;
|
|
5169
|
+
});
|
|
5170
|
+
}, []);
|
|
5171
|
+
const handleScroll = useCallback19((offset) => {
|
|
5172
|
+
const el = vlistRef.current;
|
|
5173
|
+
if (!el) return;
|
|
5174
|
+
const scrollSize = el.scrollSize ?? 0;
|
|
5175
|
+
const viewportSize = el.viewportSize ?? 0;
|
|
5176
|
+
if (scrollSize > 0 && offset + viewportSize >= scrollSize - 50) {
|
|
5177
|
+
loadMore();
|
|
5077
5178
|
}
|
|
5078
|
-
}, [
|
|
5079
|
-
|
|
5179
|
+
}, [loadMore]);
|
|
5180
|
+
const selectedArr = useMemo19(() => Array.from(selectedMap.values()), [selectedMap]);
|
|
5181
|
+
return /* @__PURE__ */ jsxs28("div", { className: "ermis-user-picker", role: "listbox", "aria-multiselectable": mode === "checkbox", children: [
|
|
5182
|
+
mode === "checkbox" && /* @__PURE__ */ jsx32(
|
|
5183
|
+
SelectedBox,
|
|
5184
|
+
{
|
|
5185
|
+
users: selectedArr,
|
|
5186
|
+
onRemove: handleRemoveSelected,
|
|
5187
|
+
AvatarComponent,
|
|
5188
|
+
emptyLabel: selectedEmptyLabel
|
|
5189
|
+
}
|
|
5190
|
+
),
|
|
5080
5191
|
/* @__PURE__ */ jsx32(
|
|
5081
5192
|
SearchInput,
|
|
5082
5193
|
{
|
|
@@ -5085,28 +5196,101 @@ var AddMemberModal = ({
|
|
|
5085
5196
|
placeholder: searchPlaceholder
|
|
5086
5197
|
}
|
|
5087
5198
|
),
|
|
5088
|
-
/* @__PURE__ */ jsx32("div", { className: "ermis-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5199
|
+
/* @__PURE__ */ jsx32("div", { className: "ermis-user-picker__list", children: isListLoading ? /* @__PURE__ */ jsxs28("div", { className: "ermis-user-picker__loading", children: [
|
|
5200
|
+
/* @__PURE__ */ jsx32("span", { className: "ermis-user-picker__spinner" }),
|
|
5201
|
+
loadingText
|
|
5202
|
+
] }) : usersToDisplay.length === 0 ? /* @__PURE__ */ jsx32("div", { className: "ermis-user-picker__empty", children: emptyText }) : /* @__PURE__ */ jsxs28(VList5, { ref: vlistRef, style: LIST_STYLE, onScroll: handleScroll, children: [
|
|
5203
|
+
usersToDisplay.map((user) => /* @__PURE__ */ jsx32(
|
|
5204
|
+
UserRow,
|
|
5205
|
+
{
|
|
5206
|
+
user,
|
|
5207
|
+
selected: selectedMap.has(user.id),
|
|
5208
|
+
disabled: user.id === currentUserId || excludeSet.has(user.id),
|
|
5209
|
+
mode,
|
|
5210
|
+
onToggle: handleToggle,
|
|
5211
|
+
AvatarComponent
|
|
5212
|
+
},
|
|
5213
|
+
user.id
|
|
5214
|
+
)),
|
|
5215
|
+
loadingMore && /* @__PURE__ */ jsxs28("div", { className: "ermis-user-picker__load-more", children: [
|
|
5216
|
+
/* @__PURE__ */ jsx32("span", { className: "ermis-user-picker__spinner" }),
|
|
5217
|
+
loadingMoreText
|
|
5218
|
+
] })
|
|
5219
|
+
] }) })
|
|
5102
5220
|
] });
|
|
5103
5221
|
};
|
|
5222
|
+
UserPicker.displayName = "UserPicker";
|
|
5223
|
+
|
|
5224
|
+
// src/components/ChannelInfo/AddMemberModal.tsx
|
|
5225
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
5226
|
+
var AddMemberModal = ({
|
|
5227
|
+
channel,
|
|
5228
|
+
currentMembers,
|
|
5229
|
+
onClose,
|
|
5230
|
+
AvatarComponent = Avatar,
|
|
5231
|
+
title = "Add Member",
|
|
5232
|
+
searchPlaceholder = "Search by name, email or phone...",
|
|
5233
|
+
loadingText = "Loading users...",
|
|
5234
|
+
emptyText = "No users found.",
|
|
5235
|
+
addLabel = "Add",
|
|
5236
|
+
addingLabel = "Adding...",
|
|
5237
|
+
addedLabel = "Added",
|
|
5238
|
+
UserItemComponent,
|
|
5239
|
+
SearchInputComponent
|
|
5240
|
+
}) => {
|
|
5241
|
+
const [selectedUsers, setSelectedUsers] = useState29([]);
|
|
5242
|
+
const [isAdding, setIsAdding] = useState29(false);
|
|
5243
|
+
const excludeUserIds = useMemo20(
|
|
5244
|
+
() => currentMembers.map((m) => m.user_id),
|
|
5245
|
+
[currentMembers]
|
|
5246
|
+
);
|
|
5247
|
+
const handleSelectionChange = useCallback20((users) => {
|
|
5248
|
+
setSelectedUsers(users);
|
|
5249
|
+
}, []);
|
|
5250
|
+
const handleAdd = useCallback20(async () => {
|
|
5251
|
+
if (selectedUsers.length === 0 || isAdding) return;
|
|
5252
|
+
try {
|
|
5253
|
+
setIsAdding(true);
|
|
5254
|
+
await channel.addMembers(selectedUsers.map((u) => u.id));
|
|
5255
|
+
onClose();
|
|
5256
|
+
} catch (err) {
|
|
5257
|
+
console.error("Failed to add members:", err);
|
|
5258
|
+
} finally {
|
|
5259
|
+
setIsAdding(false);
|
|
5260
|
+
}
|
|
5261
|
+
}, [selectedUsers, isAdding, channel, onClose]);
|
|
5262
|
+
const footer = /* @__PURE__ */ jsx33(
|
|
5263
|
+
"button",
|
|
5264
|
+
{
|
|
5265
|
+
className: "ermis-modal-add-btn",
|
|
5266
|
+
onClick: handleAdd,
|
|
5267
|
+
disabled: selectedUsers.length === 0 || isAdding,
|
|
5268
|
+
children: isAdding ? addingLabel : `${addLabel} ${selectedUsers.length > 0 ? `(${selectedUsers.length})` : ""}`
|
|
5269
|
+
}
|
|
5270
|
+
);
|
|
5271
|
+
return /* @__PURE__ */ jsx33(Modal, { isOpen: true, onClose, title, maxWidth: "480px", footer, children: /* @__PURE__ */ jsx33(
|
|
5272
|
+
UserPicker,
|
|
5273
|
+
{
|
|
5274
|
+
mode: "checkbox",
|
|
5275
|
+
onSelectionChange: handleSelectionChange,
|
|
5276
|
+
excludeUserIds,
|
|
5277
|
+
pageSize: 30,
|
|
5278
|
+
AvatarComponent,
|
|
5279
|
+
UserItemComponent,
|
|
5280
|
+
SearchInputComponent,
|
|
5281
|
+
searchPlaceholder,
|
|
5282
|
+
loadingText,
|
|
5283
|
+
emptyText,
|
|
5284
|
+
selectedEmptyLabel: "Select users to add..."
|
|
5285
|
+
}
|
|
5286
|
+
) });
|
|
5287
|
+
};
|
|
5104
5288
|
|
|
5105
5289
|
// src/components/ChannelInfo/EditChannelModal.tsx
|
|
5106
|
-
import
|
|
5107
|
-
import { jsx as
|
|
5290
|
+
import React33, { useState as useState30, useRef as useRef15, useCallback as useCallback21, useEffect as useEffect25 } from "react";
|
|
5291
|
+
import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
5108
5292
|
var DEFAULT_MAX_IMAGE_SIZE = 5 * 1024 * 1024;
|
|
5109
|
-
var EditChannelModal =
|
|
5293
|
+
var EditChannelModal = React33.memo(({
|
|
5110
5294
|
channel,
|
|
5111
5295
|
onClose,
|
|
5112
5296
|
onSave,
|
|
@@ -5130,20 +5314,20 @@ var EditChannelModal = React32.memo(({
|
|
|
5130
5314
|
const originalDescription = channel.data?.description || "";
|
|
5131
5315
|
const originalPublic = Boolean(channel.data?.public);
|
|
5132
5316
|
const isTeamChannel = channel.type === "team";
|
|
5133
|
-
const [name, setName] =
|
|
5134
|
-
const [description, setDescription] =
|
|
5135
|
-
const [isPublic, setIsPublic] =
|
|
5136
|
-
const [previewUrl, setPreviewUrl] =
|
|
5137
|
-
const [selectedFile, setSelectedFile] =
|
|
5138
|
-
const [isSaving, setIsSaving] =
|
|
5139
|
-
const [error, setError] =
|
|
5140
|
-
const fileInputRef =
|
|
5317
|
+
const [name, setName] = useState30(originalName);
|
|
5318
|
+
const [description, setDescription] = useState30(originalDescription);
|
|
5319
|
+
const [isPublic, setIsPublic] = useState30(originalPublic);
|
|
5320
|
+
const [previewUrl, setPreviewUrl] = useState30(null);
|
|
5321
|
+
const [selectedFile, setSelectedFile] = useState30(null);
|
|
5322
|
+
const [isSaving, setIsSaving] = useState30(false);
|
|
5323
|
+
const [error, setError] = useState30(null);
|
|
5324
|
+
const fileInputRef = useRef15(null);
|
|
5141
5325
|
useEffect25(() => {
|
|
5142
5326
|
return () => {
|
|
5143
5327
|
if (previewUrl) URL.revokeObjectURL(previewUrl);
|
|
5144
5328
|
};
|
|
5145
5329
|
}, [previewUrl]);
|
|
5146
|
-
const handleFileSelect =
|
|
5330
|
+
const handleFileSelect = useCallback21((e) => {
|
|
5147
5331
|
const file = e.target.files?.[0];
|
|
5148
5332
|
if (!file) return;
|
|
5149
5333
|
if (!file.type.startsWith("image/")) {
|
|
@@ -5161,10 +5345,10 @@ var EditChannelModal = React32.memo(({
|
|
|
5161
5345
|
setSelectedFile(file);
|
|
5162
5346
|
e.target.value = "";
|
|
5163
5347
|
}, [maxImageSize, maxImageSizeError, previewUrl]);
|
|
5164
|
-
const handleAvatarClick =
|
|
5348
|
+
const handleAvatarClick = useCallback21(() => {
|
|
5165
5349
|
fileInputRef.current?.click();
|
|
5166
5350
|
}, []);
|
|
5167
|
-
const buildPayload =
|
|
5351
|
+
const buildPayload = useCallback21(() => {
|
|
5168
5352
|
const payload = {};
|
|
5169
5353
|
let hasChanges = false;
|
|
5170
5354
|
if (name.trim() !== originalName) {
|
|
@@ -5184,7 +5368,7 @@ var EditChannelModal = React32.memo(({
|
|
|
5184
5368
|
}
|
|
5185
5369
|
return hasChanges ? payload : null;
|
|
5186
5370
|
}, [name, description, isPublic, selectedFile, originalName, originalDescription, originalPublic, isTeamChannel]);
|
|
5187
|
-
const handleSave =
|
|
5371
|
+
const handleSave = useCallback21(async () => {
|
|
5188
5372
|
const payload = buildPayload();
|
|
5189
5373
|
if (!payload && !selectedFile) {
|
|
5190
5374
|
onClose();
|
|
@@ -5219,7 +5403,7 @@ var EditChannelModal = React32.memo(({
|
|
|
5219
5403
|
}, [buildPayload, selectedFile, onSave, channel, onClose]);
|
|
5220
5404
|
const displayImage = previewUrl || originalImage || void 0;
|
|
5221
5405
|
const footerContent = /* @__PURE__ */ jsxs29("div", { className: "ermis-channel-info__edit-footer-buttons", children: [
|
|
5222
|
-
/* @__PURE__ */
|
|
5406
|
+
/* @__PURE__ */ jsx34(
|
|
5223
5407
|
"button",
|
|
5224
5408
|
{
|
|
5225
5409
|
className: "ermis-channel-info__edit-btn ermis-channel-info__edit-btn--cancel",
|
|
@@ -5228,7 +5412,7 @@ var EditChannelModal = React32.memo(({
|
|
|
5228
5412
|
children: cancelLabel
|
|
5229
5413
|
}
|
|
5230
5414
|
),
|
|
5231
|
-
/* @__PURE__ */
|
|
5415
|
+
/* @__PURE__ */ jsx34(
|
|
5232
5416
|
"button",
|
|
5233
5417
|
{
|
|
5234
5418
|
className: "ermis-channel-info__edit-btn ermis-channel-info__edit-btn--save",
|
|
@@ -5238,7 +5422,7 @@ var EditChannelModal = React32.memo(({
|
|
|
5238
5422
|
}
|
|
5239
5423
|
)
|
|
5240
5424
|
] });
|
|
5241
|
-
return /* @__PURE__ */
|
|
5425
|
+
return /* @__PURE__ */ jsx34(
|
|
5242
5426
|
Modal,
|
|
5243
5427
|
{
|
|
5244
5428
|
isOpen: true,
|
|
@@ -5250,13 +5434,13 @@ var EditChannelModal = React32.memo(({
|
|
|
5250
5434
|
children: /* @__PURE__ */ jsxs29("div", { className: "ermis-channel-info__edit-body", children: [
|
|
5251
5435
|
/* @__PURE__ */ jsxs29("div", { className: "ermis-channel-info__edit-avatar-section", children: [
|
|
5252
5436
|
/* @__PURE__ */ jsxs29("div", { className: "ermis-channel-info__edit-avatar-wrap", onClick: handleAvatarClick, children: [
|
|
5253
|
-
/* @__PURE__ */
|
|
5254
|
-
/* @__PURE__ */
|
|
5255
|
-
/* @__PURE__ */
|
|
5256
|
-
/* @__PURE__ */
|
|
5437
|
+
/* @__PURE__ */ jsx34(AvatarComponent, { image: displayImage, name: name || originalName, size: 80 }),
|
|
5438
|
+
/* @__PURE__ */ jsx34("div", { className: "ermis-channel-info__edit-avatar-overlay", children: /* @__PURE__ */ jsxs29("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
5439
|
+
/* @__PURE__ */ jsx34("path", { d: "M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" }),
|
|
5440
|
+
/* @__PURE__ */ jsx34("circle", { cx: "12", cy: "13", r: "4" })
|
|
5257
5441
|
] }) })
|
|
5258
5442
|
] }),
|
|
5259
|
-
/* @__PURE__ */
|
|
5443
|
+
/* @__PURE__ */ jsx34(
|
|
5260
5444
|
"button",
|
|
5261
5445
|
{
|
|
5262
5446
|
className: "ermis-channel-info__edit-avatar-btn",
|
|
@@ -5266,7 +5450,7 @@ var EditChannelModal = React32.memo(({
|
|
|
5266
5450
|
children: changeAvatarLabel
|
|
5267
5451
|
}
|
|
5268
5452
|
),
|
|
5269
|
-
/* @__PURE__ */
|
|
5453
|
+
/* @__PURE__ */ jsx34(
|
|
5270
5454
|
"input",
|
|
5271
5455
|
{
|
|
5272
5456
|
ref: fileInputRef,
|
|
@@ -5279,8 +5463,8 @@ var EditChannelModal = React32.memo(({
|
|
|
5279
5463
|
)
|
|
5280
5464
|
] }),
|
|
5281
5465
|
/* @__PURE__ */ jsxs29("div", { className: "ermis-channel-info__edit-field", children: [
|
|
5282
|
-
/* @__PURE__ */
|
|
5283
|
-
/* @__PURE__ */
|
|
5466
|
+
/* @__PURE__ */ jsx34("label", { className: "ermis-channel-info__edit-label", children: nameLabel }),
|
|
5467
|
+
/* @__PURE__ */ jsx34(
|
|
5284
5468
|
"input",
|
|
5285
5469
|
{
|
|
5286
5470
|
className: "ermis-channel-info__edit-input",
|
|
@@ -5294,8 +5478,8 @@ var EditChannelModal = React32.memo(({
|
|
|
5294
5478
|
)
|
|
5295
5479
|
] }),
|
|
5296
5480
|
/* @__PURE__ */ jsxs29("div", { className: "ermis-channel-info__edit-field", children: [
|
|
5297
|
-
/* @__PURE__ */
|
|
5298
|
-
/* @__PURE__ */
|
|
5481
|
+
/* @__PURE__ */ jsx34("label", { className: "ermis-channel-info__edit-label", children: descriptionLabel }),
|
|
5482
|
+
/* @__PURE__ */ jsx34(
|
|
5299
5483
|
"textarea",
|
|
5300
5484
|
{
|
|
5301
5485
|
className: "ermis-channel-info__edit-textarea",
|
|
@@ -5309,8 +5493,8 @@ var EditChannelModal = React32.memo(({
|
|
|
5309
5493
|
)
|
|
5310
5494
|
] }),
|
|
5311
5495
|
isTeamChannel && /* @__PURE__ */ jsxs29("div", { className: "ermis-channel-info__edit-field ermis-channel-info__edit-field--toggle", children: [
|
|
5312
|
-
/* @__PURE__ */
|
|
5313
|
-
/* @__PURE__ */
|
|
5496
|
+
/* @__PURE__ */ jsx34("label", { className: "ermis-channel-info__edit-label", children: publicLabel }),
|
|
5497
|
+
/* @__PURE__ */ jsx34(
|
|
5314
5498
|
"button",
|
|
5315
5499
|
{
|
|
5316
5500
|
type: "button",
|
|
@@ -5319,15 +5503,15 @@ var EditChannelModal = React32.memo(({
|
|
|
5319
5503
|
className: `ermis-channel-info__edit-toggle ${isPublic ? "ermis-channel-info__edit-toggle--on" : ""}`,
|
|
5320
5504
|
onClick: () => setIsPublic((v) => !v),
|
|
5321
5505
|
disabled: isSaving,
|
|
5322
|
-
children: /* @__PURE__ */
|
|
5506
|
+
children: /* @__PURE__ */ jsx34("span", { className: "ermis-channel-info__edit-toggle-thumb" })
|
|
5323
5507
|
}
|
|
5324
5508
|
)
|
|
5325
5509
|
] }),
|
|
5326
5510
|
error && /* @__PURE__ */ jsxs29("div", { className: "ermis-channel-info__edit-error", children: [
|
|
5327
5511
|
/* @__PURE__ */ jsxs29("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
5328
|
-
/* @__PURE__ */
|
|
5329
|
-
/* @__PURE__ */
|
|
5330
|
-
/* @__PURE__ */
|
|
5512
|
+
/* @__PURE__ */ jsx34("circle", { cx: "12", cy: "12", r: "10" }),
|
|
5513
|
+
/* @__PURE__ */ jsx34("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
5514
|
+
/* @__PURE__ */ jsx34("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
|
|
5331
5515
|
] }),
|
|
5332
5516
|
error
|
|
5333
5517
|
] })
|
|
@@ -5338,12 +5522,12 @@ var EditChannelModal = React32.memo(({
|
|
|
5338
5522
|
EditChannelModal.displayName = "EditChannelModal";
|
|
5339
5523
|
|
|
5340
5524
|
// src/components/ChannelInfo/MessageSearchPanel.tsx
|
|
5341
|
-
import
|
|
5525
|
+
import React35, { useState as useState31, useEffect as useEffect27, useRef as useRef17, useCallback as useCallback22, useMemo as useMemo21 } from "react";
|
|
5342
5526
|
|
|
5343
5527
|
// src/components/Panel.tsx
|
|
5344
|
-
import
|
|
5345
|
-
import { jsx as
|
|
5346
|
-
var Panel =
|
|
5528
|
+
import React34, { useEffect as useEffect26, useRef as useRef16 } from "react";
|
|
5529
|
+
import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
5530
|
+
var Panel = React34.memo(({
|
|
5347
5531
|
isOpen,
|
|
5348
5532
|
onClose,
|
|
5349
5533
|
title,
|
|
@@ -5351,7 +5535,7 @@ var Panel = React33.memo(({
|
|
|
5351
5535
|
headerContent,
|
|
5352
5536
|
className
|
|
5353
5537
|
}) => {
|
|
5354
|
-
const panelRef =
|
|
5538
|
+
const panelRef = useRef16(null);
|
|
5355
5539
|
useEffect26(() => {
|
|
5356
5540
|
if (isOpen && panelRef.current) {
|
|
5357
5541
|
panelRef.current.focus();
|
|
@@ -5365,10 +5549,10 @@ var Panel = React33.memo(({
|
|
|
5365
5549
|
tabIndex: -1,
|
|
5366
5550
|
children: [
|
|
5367
5551
|
headerContent ? headerContent : /* @__PURE__ */ jsxs30("div", { className: "ermis-panel__header", children: [
|
|
5368
|
-
/* @__PURE__ */
|
|
5369
|
-
title && /* @__PURE__ */
|
|
5552
|
+
/* @__PURE__ */ jsx35("button", { className: "ermis-panel__back", onClick: onClose, "aria-label": "Back", children: /* @__PURE__ */ jsx35("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx35("polyline", { points: "15 18 9 12 15 6" }) }) }),
|
|
5553
|
+
title && /* @__PURE__ */ jsx35("h3", { className: "ermis-panel__title", children: title })
|
|
5370
5554
|
] }),
|
|
5371
|
-
/* @__PURE__ */
|
|
5555
|
+
/* @__PURE__ */ jsx35("div", { className: "ermis-panel__body", children })
|
|
5372
5556
|
]
|
|
5373
5557
|
}
|
|
5374
5558
|
);
|
|
@@ -5376,12 +5560,12 @@ var Panel = React33.memo(({
|
|
|
5376
5560
|
Panel.displayName = "Panel";
|
|
5377
5561
|
|
|
5378
5562
|
// src/components/ChannelInfo/MessageSearchPanel.tsx
|
|
5379
|
-
import { Fragment as Fragment7, jsx as
|
|
5563
|
+
import { Fragment as Fragment7, jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
5380
5564
|
var removeAccents = (str) => str.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
5381
|
-
var HighlightedText =
|
|
5382
|
-
if (!term.trim()) return /* @__PURE__ */
|
|
5565
|
+
var HighlightedText = React35.memo(({ text, term }) => {
|
|
5566
|
+
if (!term.trim()) return /* @__PURE__ */ jsx36(Fragment7, { children: text });
|
|
5383
5567
|
const cleanTerm = removeAccents(term).toLowerCase();
|
|
5384
|
-
if (!cleanTerm) return /* @__PURE__ */
|
|
5568
|
+
if (!cleanTerm) return /* @__PURE__ */ jsx36(Fragment7, { children: text });
|
|
5385
5569
|
const parts = [];
|
|
5386
5570
|
let currentIndex = 0;
|
|
5387
5571
|
const cleanText = removeAccents(text).toLowerCase();
|
|
@@ -5389,23 +5573,23 @@ var HighlightedText = React34.memo(({ text, term }) => {
|
|
|
5389
5573
|
const startMatch = cleanText.indexOf(cleanTerm, currentIndex);
|
|
5390
5574
|
if (startMatch === -1) {
|
|
5391
5575
|
if (currentIndex < text.length) {
|
|
5392
|
-
parts.push(/* @__PURE__ */
|
|
5576
|
+
parts.push(/* @__PURE__ */ jsx36("span", { children: text.slice(currentIndex) }, currentIndex));
|
|
5393
5577
|
}
|
|
5394
5578
|
break;
|
|
5395
5579
|
}
|
|
5396
5580
|
if (startMatch > currentIndex) {
|
|
5397
|
-
parts.push(/* @__PURE__ */
|
|
5581
|
+
parts.push(/* @__PURE__ */ jsx36("span", { children: text.slice(currentIndex, startMatch) }, `text-${currentIndex}`));
|
|
5398
5582
|
}
|
|
5399
5583
|
const endMatch = startMatch + cleanTerm.length;
|
|
5400
5584
|
parts.push(
|
|
5401
|
-
/* @__PURE__ */
|
|
5585
|
+
/* @__PURE__ */ jsx36("mark", { className: "ermis-search-panel__highlight", children: text.slice(startMatch, endMatch) }, `mark-${startMatch}`)
|
|
5402
5586
|
);
|
|
5403
5587
|
currentIndex = endMatch;
|
|
5404
5588
|
}
|
|
5405
|
-
return /* @__PURE__ */
|
|
5589
|
+
return /* @__PURE__ */ jsx36(Fragment7, { children: parts.length > 0 ? parts : text });
|
|
5406
5590
|
});
|
|
5407
5591
|
HighlightedText.displayName = "HighlightedText";
|
|
5408
|
-
var MessageSearchPanel =
|
|
5592
|
+
var MessageSearchPanel = React35.memo(({
|
|
5409
5593
|
isOpen,
|
|
5410
5594
|
onClose,
|
|
5411
5595
|
channel,
|
|
@@ -5417,16 +5601,16 @@ var MessageSearchPanel = React34.memo(({
|
|
|
5417
5601
|
debounceMs = 500
|
|
5418
5602
|
}) => {
|
|
5419
5603
|
const { setJumpToMessageId } = useChatClient();
|
|
5420
|
-
const [query, setQuery] =
|
|
5421
|
-
const [results, setResults] =
|
|
5422
|
-
const [loading, setLoading] =
|
|
5423
|
-
const [hasMore, setHasMore] =
|
|
5424
|
-
const [loadingMore, setLoadingMore] =
|
|
5425
|
-
const debounceRef =
|
|
5426
|
-
const scrollRef =
|
|
5427
|
-
const inputRef =
|
|
5428
|
-
const offsetRef =
|
|
5429
|
-
const queryRef =
|
|
5604
|
+
const [query, setQuery] = useState31("");
|
|
5605
|
+
const [results, setResults] = useState31([]);
|
|
5606
|
+
const [loading, setLoading] = useState31(false);
|
|
5607
|
+
const [hasMore, setHasMore] = useState31(false);
|
|
5608
|
+
const [loadingMore, setLoadingMore] = useState31(false);
|
|
5609
|
+
const debounceRef = useRef17(null);
|
|
5610
|
+
const scrollRef = useRef17(null);
|
|
5611
|
+
const inputRef = useRef17(null);
|
|
5612
|
+
const offsetRef = useRef17(0);
|
|
5613
|
+
const queryRef = useRef17("");
|
|
5430
5614
|
useEffect27(() => {
|
|
5431
5615
|
setQuery("");
|
|
5432
5616
|
setResults([]);
|
|
@@ -5441,7 +5625,7 @@ var MessageSearchPanel = React34.memo(({
|
|
|
5441
5625
|
setTimeout(() => inputRef.current?.focus(), 300);
|
|
5442
5626
|
}
|
|
5443
5627
|
}, [isOpen]);
|
|
5444
|
-
const handleInputChange =
|
|
5628
|
+
const handleInputChange = useCallback22((e) => {
|
|
5445
5629
|
const value = e.target.value;
|
|
5446
5630
|
setQuery(value);
|
|
5447
5631
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
@@ -5476,7 +5660,7 @@ var MessageSearchPanel = React34.memo(({
|
|
|
5476
5660
|
}
|
|
5477
5661
|
}, debounceMs);
|
|
5478
5662
|
}, [channel, debounceMs]);
|
|
5479
|
-
const handleLoadMore =
|
|
5663
|
+
const handleLoadMore = useCallback22(async () => {
|
|
5480
5664
|
if (loadingMore || !hasMore || !queryRef.current) return;
|
|
5481
5665
|
setLoadingMore(true);
|
|
5482
5666
|
const nextOffset = offsetRef.current + 25;
|
|
@@ -5495,7 +5679,7 @@ var MessageSearchPanel = React34.memo(({
|
|
|
5495
5679
|
setLoadingMore(false);
|
|
5496
5680
|
}
|
|
5497
5681
|
}, [channel, hasMore, loadingMore]);
|
|
5498
|
-
const handleScroll =
|
|
5682
|
+
const handleScroll = useCallback22(() => {
|
|
5499
5683
|
const el = scrollRef.current;
|
|
5500
5684
|
if (!el) return;
|
|
5501
5685
|
const threshold = 100;
|
|
@@ -5503,10 +5687,10 @@ var MessageSearchPanel = React34.memo(({
|
|
|
5503
5687
|
handleLoadMore();
|
|
5504
5688
|
}
|
|
5505
5689
|
}, [handleLoadMore]);
|
|
5506
|
-
const handleResultClick =
|
|
5690
|
+
const handleResultClick = useCallback22((messageId) => {
|
|
5507
5691
|
setJumpToMessageId(messageId);
|
|
5508
5692
|
}, [setJumpToMessageId]);
|
|
5509
|
-
const userMaps =
|
|
5693
|
+
const userMaps = useMemo21(() => {
|
|
5510
5694
|
const original = buildUserMap(channel.state);
|
|
5511
5695
|
const lower = {};
|
|
5512
5696
|
for (const [id, name] of Object.entries(original)) {
|
|
@@ -5515,12 +5699,12 @@ var MessageSearchPanel = React34.memo(({
|
|
|
5515
5699
|
return { original, lower };
|
|
5516
5700
|
}, [channel.state]);
|
|
5517
5701
|
return /* @__PURE__ */ jsxs31(Panel, { isOpen, onClose, title, className: "ermis-search-panel", children: [
|
|
5518
|
-
/* @__PURE__ */
|
|
5702
|
+
/* @__PURE__ */ jsx36("div", { className: "ermis-search-panel__search-box", children: /* @__PURE__ */ jsxs31("div", { className: "ermis-search-panel__input-wrap", children: [
|
|
5519
5703
|
/* @__PURE__ */ jsxs31("svg", { className: "ermis-search-panel__input-icon", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
5520
|
-
/* @__PURE__ */
|
|
5521
|
-
/* @__PURE__ */
|
|
5704
|
+
/* @__PURE__ */ jsx36("circle", { cx: "11", cy: "11", r: "8" }),
|
|
5705
|
+
/* @__PURE__ */ jsx36("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })
|
|
5522
5706
|
] }),
|
|
5523
|
-
/* @__PURE__ */
|
|
5707
|
+
/* @__PURE__ */ jsx36(
|
|
5524
5708
|
"input",
|
|
5525
5709
|
{
|
|
5526
5710
|
ref: inputRef,
|
|
@@ -5531,7 +5715,7 @@ var MessageSearchPanel = React34.memo(({
|
|
|
5531
5715
|
placeholder
|
|
5532
5716
|
}
|
|
5533
5717
|
),
|
|
5534
|
-
query && /* @__PURE__ */
|
|
5718
|
+
query && /* @__PURE__ */ jsx36(
|
|
5535
5719
|
"button",
|
|
5536
5720
|
{
|
|
5537
5721
|
className: "ermis-search-panel__input-clear",
|
|
@@ -5545,8 +5729,8 @@ var MessageSearchPanel = React34.memo(({
|
|
|
5545
5729
|
},
|
|
5546
5730
|
"aria-label": "Clear",
|
|
5547
5731
|
children: /* @__PURE__ */ jsxs31("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
5548
|
-
/* @__PURE__ */
|
|
5549
|
-
/* @__PURE__ */
|
|
5732
|
+
/* @__PURE__ */ jsx36("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
5733
|
+
/* @__PURE__ */ jsx36("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
5550
5734
|
] })
|
|
5551
5735
|
}
|
|
5552
5736
|
)
|
|
@@ -5560,16 +5744,16 @@ var MessageSearchPanel = React34.memo(({
|
|
|
5560
5744
|
children: [
|
|
5561
5745
|
!query.trim() && !loading && results.length === 0 && /* @__PURE__ */ jsxs31("div", { className: "ermis-search-panel__idle", children: [
|
|
5562
5746
|
/* @__PURE__ */ jsxs31("svg", { width: "40", height: "40", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
5563
|
-
/* @__PURE__ */
|
|
5564
|
-
/* @__PURE__ */
|
|
5747
|
+
/* @__PURE__ */ jsx36("circle", { cx: "11", cy: "11", r: "8" }),
|
|
5748
|
+
/* @__PURE__ */ jsx36("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })
|
|
5565
5749
|
] }),
|
|
5566
|
-
/* @__PURE__ */
|
|
5750
|
+
/* @__PURE__ */ jsx36("span", { children: placeholder })
|
|
5567
5751
|
] }),
|
|
5568
5752
|
loading && /* @__PURE__ */ jsxs31("div", { className: "ermis-search-panel__loading", children: [
|
|
5569
|
-
/* @__PURE__ */
|
|
5570
|
-
/* @__PURE__ */
|
|
5753
|
+
/* @__PURE__ */ jsx36("div", { className: "ermis-search-panel__spinner" }),
|
|
5754
|
+
/* @__PURE__ */ jsx36("span", { children: loadingText })
|
|
5571
5755
|
] }),
|
|
5572
|
-
!loading && query.trim() && results.length === 0 && /* @__PURE__ */
|
|
5756
|
+
!loading && query.trim() && results.length === 0 && /* @__PURE__ */ jsx36("div", { className: "ermis-search-panel__empty", children: /* @__PURE__ */ jsx36("span", { children: emptyText }) }),
|
|
5573
5757
|
!loading && results.map((msg) => {
|
|
5574
5758
|
let parsedText = "";
|
|
5575
5759
|
if (msg.text) {
|
|
@@ -5595,7 +5779,7 @@ var MessageSearchPanel = React34.memo(({
|
|
|
5595
5779
|
}
|
|
5596
5780
|
},
|
|
5597
5781
|
children: [
|
|
5598
|
-
/* @__PURE__ */
|
|
5782
|
+
/* @__PURE__ */ jsx36(
|
|
5599
5783
|
AvatarComponent,
|
|
5600
5784
|
{
|
|
5601
5785
|
image: msg.user?.avatar || msg.user?.image || msg.user?.avatar_url,
|
|
@@ -5605,18 +5789,18 @@ var MessageSearchPanel = React34.memo(({
|
|
|
5605
5789
|
),
|
|
5606
5790
|
/* @__PURE__ */ jsxs31("div", { className: "ermis-search-panel__result-body", children: [
|
|
5607
5791
|
/* @__PURE__ */ jsxs31("div", { className: "ermis-search-panel__result-meta", children: [
|
|
5608
|
-
/* @__PURE__ */
|
|
5609
|
-
/* @__PURE__ */
|
|
5792
|
+
/* @__PURE__ */ jsx36("span", { className: "ermis-search-panel__result-name", children: msg.user?.name || msg.user_id || "Unknown" }),
|
|
5793
|
+
/* @__PURE__ */ jsx36("span", { className: "ermis-search-panel__result-time", children: msg.created_at ? formatRelativeDate(msg.created_at) : "" })
|
|
5610
5794
|
] }),
|
|
5611
|
-
/* @__PURE__ */
|
|
5795
|
+
/* @__PURE__ */ jsx36("p", { className: "ermis-search-panel__result-text", children: parsedText ? /* @__PURE__ */ jsx36(HighlightedText, { text: parsedText, term: query }) : /* @__PURE__ */ jsx36("em", { children: "Attachment" }) })
|
|
5612
5796
|
] })
|
|
5613
5797
|
]
|
|
5614
5798
|
},
|
|
5615
5799
|
msg.id
|
|
5616
5800
|
);
|
|
5617
5801
|
}),
|
|
5618
|
-
!loading && !loadingMore && !hasMore && results.length > 0 && query.trim() && /* @__PURE__ */
|
|
5619
|
-
loadingMore && /* @__PURE__ */
|
|
5802
|
+
!loading && !loadingMore && !hasMore && results.length > 0 && query.trim() && /* @__PURE__ */ jsx36("div", { className: "ermis-search-panel__end-indicator", children: /* @__PURE__ */ jsx36("span", { children: emptyText }) }),
|
|
5803
|
+
loadingMore && /* @__PURE__ */ jsx36("div", { className: "ermis-search-panel__loading-more", children: /* @__PURE__ */ jsx36("div", { className: "ermis-search-panel__spinner ermis-search-panel__spinner--small" }) })
|
|
5620
5804
|
]
|
|
5621
5805
|
}
|
|
5622
5806
|
)
|
|
@@ -5625,9 +5809,9 @@ var MessageSearchPanel = React34.memo(({
|
|
|
5625
5809
|
MessageSearchPanel.displayName = "MessageSearchPanel";
|
|
5626
5810
|
|
|
5627
5811
|
// src/components/ChannelInfo/ChannelSettingsPanel.tsx
|
|
5628
|
-
import
|
|
5629
|
-
import { jsx as
|
|
5630
|
-
var ChannelSettingsPanel =
|
|
5812
|
+
import React36, { useState as useState32, useEffect as useEffect28 } from "react";
|
|
5813
|
+
import { jsx as jsx37, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
5814
|
+
var ChannelSettingsPanel = React36.memo(({
|
|
5631
5815
|
isOpen,
|
|
5632
5816
|
onClose,
|
|
5633
5817
|
channel,
|
|
@@ -5642,8 +5826,8 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
5642
5826
|
{ label: "1h", value: 36e5 }
|
|
5643
5827
|
]
|
|
5644
5828
|
}) => {
|
|
5645
|
-
const [slowMode, setSlowMode] =
|
|
5646
|
-
const [capabilities, setCapabilities] =
|
|
5829
|
+
const [slowMode, setSlowMode] = useState32(0);
|
|
5830
|
+
const [capabilities, setCapabilities] = useState32({
|
|
5647
5831
|
"send-message": true,
|
|
5648
5832
|
"send-links": true,
|
|
5649
5833
|
"update-own-message": true,
|
|
@@ -5653,10 +5837,10 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
5653
5837
|
"create-poll": true,
|
|
5654
5838
|
"vote-poll": true
|
|
5655
5839
|
});
|
|
5656
|
-
const [keywords, setKeywords] =
|
|
5657
|
-
const [newKeyword, setNewKeyword] =
|
|
5658
|
-
const [isSaving, setIsSaving] =
|
|
5659
|
-
const [error, setError] =
|
|
5840
|
+
const [keywords, setKeywords] = useState32([]);
|
|
5841
|
+
const [newKeyword, setNewKeyword] = useState32("");
|
|
5842
|
+
const [isSaving, setIsSaving] = useState32(false);
|
|
5843
|
+
const [error, setError] = useState32(null);
|
|
5660
5844
|
useEffect28(() => {
|
|
5661
5845
|
if (!channel) return;
|
|
5662
5846
|
const syncData = (dataToSync = channel.data) => {
|
|
@@ -5800,13 +5984,13 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
5800
5984
|
},
|
|
5801
5985
|
children: [
|
|
5802
5986
|
/* @__PURE__ */ jsxs32("div", { style: { display: "flex", alignItems: "center", marginBottom: "16px", gap: "8px" }, children: [
|
|
5803
|
-
/* @__PURE__ */
|
|
5804
|
-
/* @__PURE__ */
|
|
5987
|
+
/* @__PURE__ */ jsx37("div", { style: { background: "var(--ermis-color-primary-light)", padding: "4px", borderRadius: "8px", color: "var(--ermis-color-primary)" }, children: /* @__PURE__ */ jsx37("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx37("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }) }) }),
|
|
5988
|
+
/* @__PURE__ */ jsx37("h4", { style: { fontSize: "14px", color: "var(--ermis-text-primary)", fontWeight: 600, margin: 0 }, children: "Member Permissions" })
|
|
5805
5989
|
] }),
|
|
5806
5990
|
/* @__PURE__ */ jsxs32("div", { className: "ermis-settings-panel__field", style: { marginBottom: "16px" }, children: [
|
|
5807
|
-
/* @__PURE__ */
|
|
5991
|
+
/* @__PURE__ */ jsx37("label", { style: { display: "block", marginBottom: "6px", fontWeight: 500, fontSize: "12px", color: "var(--ermis-text-secondary)", textTransform: "uppercase", letterSpacing: "0.5px" }, children: "Slow Mode" }),
|
|
5808
5992
|
/* @__PURE__ */ jsxs32("div", { style: { position: "relative" }, children: [
|
|
5809
|
-
/* @__PURE__ */
|
|
5993
|
+
/* @__PURE__ */ jsx37(
|
|
5810
5994
|
"select",
|
|
5811
5995
|
{
|
|
5812
5996
|
value: slowMode,
|
|
@@ -5826,15 +6010,15 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
5826
6010
|
transition: "border-color 0.2s"
|
|
5827
6011
|
},
|
|
5828
6012
|
disabled: isSaving,
|
|
5829
|
-
children: slowModeOptions.map((opt) => /* @__PURE__ */
|
|
6013
|
+
children: slowModeOptions.map((opt) => /* @__PURE__ */ jsx37("option", { value: opt.value, children: opt.label }, opt.value))
|
|
5830
6014
|
}
|
|
5831
6015
|
),
|
|
5832
|
-
/* @__PURE__ */
|
|
6016
|
+
/* @__PURE__ */ jsx37("div", { style: { position: "absolute", right: "14px", top: "50%", transform: "translateY(-50%)", pointerEvents: "none", color: "var(--ermis-text-secondary)" }, children: /* @__PURE__ */ jsx37("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx37("polyline", { points: "6 9 12 15 18 9" }) }) })
|
|
5833
6017
|
] })
|
|
5834
6018
|
] }),
|
|
5835
6019
|
/* @__PURE__ */ jsxs32("div", { className: "ermis-settings-panel__toggles", style: { display: "flex", flexDirection: "column" }, children: [
|
|
5836
|
-
/* @__PURE__ */
|
|
5837
|
-
/* @__PURE__ */
|
|
6020
|
+
/* @__PURE__ */ jsx37("label", { style: { display: "block", marginBottom: "6px", fontWeight: 500, fontSize: "12px", color: "var(--ermis-text-secondary)", textTransform: "uppercase", letterSpacing: "0.5px" }, children: "Capabilities" }),
|
|
6021
|
+
/* @__PURE__ */ jsx37("div", { style: { background: "var(--ermis-bg-secondary)", borderRadius: "8px", overflow: "hidden", border: "1px solid var(--ermis-border-color)" }, children: Object.entries(capabilities).map(([key, value], index, arr) => /* @__PURE__ */ jsxs32(
|
|
5838
6022
|
"div",
|
|
5839
6023
|
{
|
|
5840
6024
|
style: {
|
|
@@ -5845,8 +6029,8 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
5845
6029
|
borderBottom: index < arr.length - 1 ? "1px solid var(--ermis-border-color)" : "none"
|
|
5846
6030
|
},
|
|
5847
6031
|
children: [
|
|
5848
|
-
/* @__PURE__ */
|
|
5849
|
-
/* @__PURE__ */
|
|
6032
|
+
/* @__PURE__ */ jsx37("span", { style: { fontSize: "14px", fontWeight: 500, color: "var(--ermis-text-primary)" }, children: key.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ") }),
|
|
6033
|
+
/* @__PURE__ */ jsx37(
|
|
5850
6034
|
"button",
|
|
5851
6035
|
{
|
|
5852
6036
|
type: "button",
|
|
@@ -5856,7 +6040,7 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
5856
6040
|
onClick: () => toggleCapability(key),
|
|
5857
6041
|
disabled: isSaving,
|
|
5858
6042
|
style: { transform: "scale(0.85)", transformOrigin: "right center" },
|
|
5859
|
-
children: /* @__PURE__ */
|
|
6043
|
+
children: /* @__PURE__ */ jsx37("span", { className: "ermis-channel-info__edit-toggle-thumb" })
|
|
5860
6044
|
}
|
|
5861
6045
|
)
|
|
5862
6046
|
]
|
|
@@ -5880,17 +6064,17 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
5880
6064
|
},
|
|
5881
6065
|
children: [
|
|
5882
6066
|
/* @__PURE__ */ jsxs32("div", { style: { display: "flex", alignItems: "center", marginBottom: "16px", gap: "8px" }, children: [
|
|
5883
|
-
/* @__PURE__ */
|
|
5884
|
-
/* @__PURE__ */
|
|
5885
|
-
/* @__PURE__ */
|
|
5886
|
-
/* @__PURE__ */
|
|
6067
|
+
/* @__PURE__ */ jsx37("div", { style: { background: "var(--ermis-color-danger-light)", padding: "4px", borderRadius: "8px", color: "var(--ermis-color-danger)" }, children: /* @__PURE__ */ jsxs32("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6068
|
+
/* @__PURE__ */ jsx37("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }),
|
|
6069
|
+
/* @__PURE__ */ jsx37("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
|
|
6070
|
+
/* @__PURE__ */ jsx37("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
|
|
5887
6071
|
] }) }),
|
|
5888
|
-
/* @__PURE__ */
|
|
6072
|
+
/* @__PURE__ */ jsx37("h4", { style: { fontSize: "14px", color: "var(--ermis-text-primary)", fontWeight: 600, margin: 0 }, children: "Content Moderation" })
|
|
5889
6073
|
] }),
|
|
5890
6074
|
/* @__PURE__ */ jsxs32("div", { className: "ermis-settings-panel__field", style: { marginBottom: "16px" }, children: [
|
|
5891
|
-
/* @__PURE__ */
|
|
6075
|
+
/* @__PURE__ */ jsx37("label", { style: { display: "block", marginBottom: "6px", fontWeight: 500, fontSize: "12px", color: "var(--ermis-text-secondary)", textTransform: "uppercase", letterSpacing: "0.5px" }, children: "Keyword Filtering" }),
|
|
5892
6076
|
/* @__PURE__ */ jsxs32("div", { style: { display: "flex", gap: "8px", position: "relative" }, children: [
|
|
5893
|
-
/* @__PURE__ */
|
|
6077
|
+
/* @__PURE__ */ jsx37(
|
|
5894
6078
|
"input",
|
|
5895
6079
|
{
|
|
5896
6080
|
type: "text",
|
|
@@ -5912,7 +6096,7 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
5912
6096
|
disabled: isSaving
|
|
5913
6097
|
}
|
|
5914
6098
|
),
|
|
5915
|
-
/* @__PURE__ */
|
|
6099
|
+
/* @__PURE__ */ jsx37(
|
|
5916
6100
|
"button",
|
|
5917
6101
|
{
|
|
5918
6102
|
type: "button",
|
|
@@ -5956,7 +6140,7 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
5956
6140
|
},
|
|
5957
6141
|
children: [
|
|
5958
6142
|
kw,
|
|
5959
|
-
/* @__PURE__ */
|
|
6143
|
+
/* @__PURE__ */ jsx37(
|
|
5960
6144
|
"button",
|
|
5961
6145
|
{
|
|
5962
6146
|
onClick: () => handeRemoveKeyword(kw),
|
|
@@ -5974,8 +6158,8 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
5974
6158
|
disabled: isSaving,
|
|
5975
6159
|
"aria-label": "Remove keyword",
|
|
5976
6160
|
children: /* @__PURE__ */ jsxs32("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
5977
|
-
/* @__PURE__ */
|
|
5978
|
-
/* @__PURE__ */
|
|
6161
|
+
/* @__PURE__ */ jsx37("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
6162
|
+
/* @__PURE__ */ jsx37("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
5979
6163
|
] })
|
|
5980
6164
|
}
|
|
5981
6165
|
)
|
|
@@ -5983,7 +6167,7 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
5983
6167
|
},
|
|
5984
6168
|
kw
|
|
5985
6169
|
)),
|
|
5986
|
-
keywords.length === 0 && /* @__PURE__ */
|
|
6170
|
+
keywords.length === 0 && /* @__PURE__ */ jsx37("span", { style: { fontSize: "14px", color: "var(--ermis-text-secondary)", padding: "6px 0", fontStyle: "italic" }, children: "No blacklisted keywords added." })
|
|
5987
6171
|
] })
|
|
5988
6172
|
]
|
|
5989
6173
|
}
|
|
@@ -6007,13 +6191,13 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
6007
6191
|
children: [
|
|
6008
6192
|
error && /* @__PURE__ */ jsxs32("div", { style: { color: "var(--ermis-color-danger)", fontSize: "13px", display: "flex", alignItems: "center", gap: "6px", fontWeight: 500 }, children: [
|
|
6009
6193
|
/* @__PURE__ */ jsxs32("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: [
|
|
6010
|
-
/* @__PURE__ */
|
|
6011
|
-
/* @__PURE__ */
|
|
6012
|
-
/* @__PURE__ */
|
|
6194
|
+
/* @__PURE__ */ jsx37("circle", { cx: "12", cy: "12", r: "10" }),
|
|
6195
|
+
/* @__PURE__ */ jsx37("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
6196
|
+
/* @__PURE__ */ jsx37("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
|
|
6013
6197
|
] }),
|
|
6014
6198
|
error
|
|
6015
6199
|
] }),
|
|
6016
|
-
/* @__PURE__ */
|
|
6200
|
+
/* @__PURE__ */ jsx37(
|
|
6017
6201
|
"button",
|
|
6018
6202
|
{
|
|
6019
6203
|
onClick: handleSave,
|
|
@@ -6033,7 +6217,7 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
6033
6217
|
boxShadow: isSaving || !isDirty ? "none" : "0 4px 12px rgba(0, 110, 255, 0.2)"
|
|
6034
6218
|
},
|
|
6035
6219
|
children: isSaving ? /* @__PURE__ */ jsxs32("span", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "8px" }, children: [
|
|
6036
|
-
/* @__PURE__ */
|
|
6220
|
+
/* @__PURE__ */ jsx37("svg", { className: "ermis-spinner", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", children: /* @__PURE__ */ jsx37("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) }),
|
|
6037
6221
|
"Saving..."
|
|
6038
6222
|
] }) : "Save Updates"
|
|
6039
6223
|
}
|
|
@@ -6046,40 +6230,40 @@ var ChannelSettingsPanel = React35.memo(({
|
|
|
6046
6230
|
ChannelSettingsPanel.displayName = "ChannelSettingsPanel";
|
|
6047
6231
|
|
|
6048
6232
|
// src/components/ChannelInfo/ChannelInfo.tsx
|
|
6049
|
-
import { Fragment as Fragment8, jsx as
|
|
6050
|
-
var DefaultChannelInfoHeader =
|
|
6233
|
+
import { Fragment as Fragment8, jsx as jsx38, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
6234
|
+
var DefaultChannelInfoHeader = React37.memo(({ title, onClose }) => {
|
|
6051
6235
|
return /* @__PURE__ */ jsxs33("div", { className: "ermis-channel-info__header", children: [
|
|
6052
|
-
/* @__PURE__ */
|
|
6053
|
-
onClose && /* @__PURE__ */
|
|
6236
|
+
/* @__PURE__ */ jsx38("h3", { className: "ermis-channel-info__title", children: title }),
|
|
6237
|
+
onClose && /* @__PURE__ */ jsx38("button", { className: "ermis-channel-info__close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx38("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx38("path", { d: "M18 6L6 18M6 6L18 18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
|
|
6054
6238
|
] });
|
|
6055
6239
|
});
|
|
6056
6240
|
DefaultChannelInfoHeader.displayName = "DefaultChannelInfoHeader";
|
|
6057
|
-
var DefaultChannelInfoCover =
|
|
6241
|
+
var DefaultChannelInfoCover = React37.memo(({ channelName, channelImage, channelDescription, AvatarComponent, canEdit, onEditClick, isPublic, isTeamChannel }) => {
|
|
6058
6242
|
return /* @__PURE__ */ jsxs33("div", { className: "ermis-channel-info__cover", children: [
|
|
6059
|
-
/* @__PURE__ */
|
|
6243
|
+
/* @__PURE__ */ jsx38(AvatarComponent, { image: channelImage, name: channelName, size: 80, className: "ermis-channel-info__avatar" }),
|
|
6060
6244
|
/* @__PURE__ */ jsxs33("div", { className: "ermis-channel-info__name-row", children: [
|
|
6061
|
-
/* @__PURE__ */
|
|
6062
|
-
canEdit && onEditClick && /* @__PURE__ */
|
|
6063
|
-
/* @__PURE__ */
|
|
6064
|
-
/* @__PURE__ */
|
|
6245
|
+
/* @__PURE__ */ jsx38("h2", { className: "ermis-channel-info__name", children: channelName }),
|
|
6246
|
+
canEdit && onEditClick && /* @__PURE__ */ jsx38("button", { className: "ermis-channel-info__cover-edit-btn", onClick: onEditClick, "aria-label": "Edit channel", children: /* @__PURE__ */ jsxs33("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6247
|
+
/* @__PURE__ */ jsx38("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
|
|
6248
|
+
/* @__PURE__ */ jsx38("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
|
|
6065
6249
|
] }) })
|
|
6066
6250
|
] }),
|
|
6067
6251
|
isTeamChannel && /* @__PURE__ */ jsxs33("span", { className: `ermis-channel-info__type-badge ${isPublic ? "ermis-channel-info__type-badge--public" : "ermis-channel-info__type-badge--private"}`, children: [
|
|
6068
6252
|
isPublic ? /* @__PURE__ */ jsxs33("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6069
|
-
/* @__PURE__ */
|
|
6070
|
-
/* @__PURE__ */
|
|
6071
|
-
/* @__PURE__ */
|
|
6253
|
+
/* @__PURE__ */ jsx38("circle", { cx: "12", cy: "12", r: "10" }),
|
|
6254
|
+
/* @__PURE__ */ jsx38("line", { x1: "2", y1: "12", x2: "22", y2: "12" }),
|
|
6255
|
+
/* @__PURE__ */ jsx38("path", { d: "M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" })
|
|
6072
6256
|
] }) : /* @__PURE__ */ jsxs33("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6073
|
-
/* @__PURE__ */
|
|
6074
|
-
/* @__PURE__ */
|
|
6257
|
+
/* @__PURE__ */ jsx38("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }),
|
|
6258
|
+
/* @__PURE__ */ jsx38("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
|
|
6075
6259
|
] }),
|
|
6076
6260
|
isPublic ? "Public" : "Private"
|
|
6077
6261
|
] }),
|
|
6078
|
-
channelDescription && /* @__PURE__ */
|
|
6262
|
+
channelDescription && /* @__PURE__ */ jsx38("p", { className: "ermis-channel-info__description", children: channelDescription })
|
|
6079
6263
|
] });
|
|
6080
6264
|
});
|
|
6081
6265
|
DefaultChannelInfoCover.displayName = "DefaultChannelInfoCover";
|
|
6082
|
-
var DefaultChannelInfoActions =
|
|
6266
|
+
var DefaultChannelInfoActions = React37.memo(({
|
|
6083
6267
|
onSearchClick,
|
|
6084
6268
|
onSettingsClick,
|
|
6085
6269
|
onLeaveChannel,
|
|
@@ -6098,50 +6282,50 @@ var DefaultChannelInfoActions = React36.memo(({
|
|
|
6098
6282
|
}) => {
|
|
6099
6283
|
return /* @__PURE__ */ jsxs33("div", { className: "ermis-channel-info__actions", children: [
|
|
6100
6284
|
/* @__PURE__ */ jsxs33("button", { className: "ermis-channel-info__action-btn", onClick: onSearchClick, disabled: isBlocked, children: [
|
|
6101
|
-
/* @__PURE__ */
|
|
6102
|
-
/* @__PURE__ */
|
|
6103
|
-
/* @__PURE__ */
|
|
6285
|
+
/* @__PURE__ */ jsx38("div", { className: "ermis-channel-info__action-icon", children: /* @__PURE__ */ jsxs33("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6286
|
+
/* @__PURE__ */ jsx38("circle", { cx: "11", cy: "11", r: "8" }),
|
|
6287
|
+
/* @__PURE__ */ jsx38("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })
|
|
6104
6288
|
] }) }),
|
|
6105
|
-
/* @__PURE__ */
|
|
6289
|
+
/* @__PURE__ */ jsx38("span", { children: searchLabel })
|
|
6106
6290
|
] }),
|
|
6107
6291
|
isTeamChannel && (currentUserRole === "owner" || currentUserRole === "moder") && /* @__PURE__ */ jsxs33("button", { className: "ermis-channel-info__action-btn", onClick: onSettingsClick, children: [
|
|
6108
|
-
/* @__PURE__ */
|
|
6109
|
-
/* @__PURE__ */
|
|
6110
|
-
/* @__PURE__ */
|
|
6292
|
+
/* @__PURE__ */ jsx38("div", { className: "ermis-channel-info__action-icon", children: /* @__PURE__ */ jsxs33("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6293
|
+
/* @__PURE__ */ jsx38("circle", { cx: "12", cy: "12", r: "3" }),
|
|
6294
|
+
/* @__PURE__ */ jsx38("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" })
|
|
6111
6295
|
] }) }),
|
|
6112
|
-
/* @__PURE__ */
|
|
6296
|
+
/* @__PURE__ */ jsx38("span", { children: settingsLabel })
|
|
6113
6297
|
] }),
|
|
6114
6298
|
isTeamChannel && (currentUserRole === "owner" ? /* @__PURE__ */ jsxs33("button", { className: "ermis-channel-info__action-btn ermis-channel-info__action-btn--danger", onClick: onDeleteChannel, children: [
|
|
6115
|
-
/* @__PURE__ */
|
|
6116
|
-
/* @__PURE__ */
|
|
6117
|
-
/* @__PURE__ */
|
|
6299
|
+
/* @__PURE__ */ jsx38("div", { className: "ermis-channel-info__action-icon", children: /* @__PURE__ */ jsxs33("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6300
|
+
/* @__PURE__ */ jsx38("polyline", { points: "3 6 5 6 21 6" }),
|
|
6301
|
+
/* @__PURE__ */ jsx38("path", { d: "M19 6V20a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
|
|
6118
6302
|
] }) }),
|
|
6119
|
-
/* @__PURE__ */
|
|
6303
|
+
/* @__PURE__ */ jsx38("span", { children: deleteLabel })
|
|
6120
6304
|
] }) : /* @__PURE__ */ jsxs33("button", { className: "ermis-channel-info__action-btn ermis-channel-info__action-btn--danger", onClick: onLeaveChannel, children: [
|
|
6121
|
-
/* @__PURE__ */
|
|
6122
|
-
/* @__PURE__ */
|
|
6123
|
-
/* @__PURE__ */
|
|
6124
|
-
/* @__PURE__ */
|
|
6305
|
+
/* @__PURE__ */ jsx38("div", { className: "ermis-channel-info__action-icon", children: /* @__PURE__ */ jsxs33("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6306
|
+
/* @__PURE__ */ jsx38("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
|
|
6307
|
+
/* @__PURE__ */ jsx38("polyline", { points: "16 17 21 12 16 7" }),
|
|
6308
|
+
/* @__PURE__ */ jsx38("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
|
|
6125
6309
|
] }) }),
|
|
6126
|
-
/* @__PURE__ */
|
|
6310
|
+
/* @__PURE__ */ jsx38("span", { children: leaveLabel })
|
|
6127
6311
|
] })),
|
|
6128
6312
|
!isTeamChannel && (isBlocked ? /* @__PURE__ */ jsxs33("button", { className: "ermis-channel-info__action-btn", onClick: onUnblockUser, children: [
|
|
6129
|
-
/* @__PURE__ */
|
|
6130
|
-
/* @__PURE__ */
|
|
6131
|
-
/* @__PURE__ */
|
|
6313
|
+
/* @__PURE__ */ jsx38("div", { className: "ermis-channel-info__action-icon", children: /* @__PURE__ */ jsxs33("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6314
|
+
/* @__PURE__ */ jsx38("circle", { cx: "12", cy: "12", r: "10" }),
|
|
6315
|
+
/* @__PURE__ */ jsx38("line", { x1: "4.93", y1: "4.93", x2: "19.07", y2: "19.07" })
|
|
6132
6316
|
] }) }),
|
|
6133
|
-
/* @__PURE__ */
|
|
6317
|
+
/* @__PURE__ */ jsx38("span", { children: unblockLabel })
|
|
6134
6318
|
] }) : /* @__PURE__ */ jsxs33("button", { className: "ermis-channel-info__action-btn ermis-channel-info__action-btn--danger", onClick: onBlockUser, children: [
|
|
6135
|
-
/* @__PURE__ */
|
|
6136
|
-
/* @__PURE__ */
|
|
6137
|
-
/* @__PURE__ */
|
|
6319
|
+
/* @__PURE__ */ jsx38("div", { className: "ermis-channel-info__action-icon", children: /* @__PURE__ */ jsxs33("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6320
|
+
/* @__PURE__ */ jsx38("circle", { cx: "12", cy: "12", r: "10" }),
|
|
6321
|
+
/* @__PURE__ */ jsx38("line", { x1: "4.93", y1: "4.93", x2: "19.07", y2: "19.07" })
|
|
6138
6322
|
] }) }),
|
|
6139
|
-
/* @__PURE__ */
|
|
6323
|
+
/* @__PURE__ */ jsx38("span", { children: blockLabel })
|
|
6140
6324
|
] }))
|
|
6141
6325
|
] });
|
|
6142
6326
|
});
|
|
6143
6327
|
DefaultChannelInfoActions.displayName = "DefaultChannelInfoActions";
|
|
6144
|
-
var ChannelInfo =
|
|
6328
|
+
var ChannelInfo = React37.memo((props) => {
|
|
6145
6329
|
const {
|
|
6146
6330
|
channel: channelProp,
|
|
6147
6331
|
className = "",
|
|
@@ -6211,7 +6395,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6211
6395
|
const currentUserId = client?.userID;
|
|
6212
6396
|
const currentUserRole = currentUserId ? channel?.state?.members?.[currentUserId]?.channel_role : void 0;
|
|
6213
6397
|
const isTeamChannel = channel?.type === "team";
|
|
6214
|
-
const handleDeleteChannel =
|
|
6398
|
+
const handleDeleteChannel = useCallback23(async () => {
|
|
6215
6399
|
if (onDeleteChannelProp) return onDeleteChannelProp();
|
|
6216
6400
|
if (!channel) return;
|
|
6217
6401
|
try {
|
|
@@ -6220,7 +6404,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6220
6404
|
console.error("Error deleting channel", e);
|
|
6221
6405
|
}
|
|
6222
6406
|
}, [channel, onDeleteChannelProp]);
|
|
6223
|
-
const handleLeaveChannel =
|
|
6407
|
+
const handleLeaveChannel = useCallback23(async () => {
|
|
6224
6408
|
if (onLeaveChannelProp) return onLeaveChannelProp();
|
|
6225
6409
|
if (!channel || !currentUserId) return;
|
|
6226
6410
|
try {
|
|
@@ -6229,7 +6413,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6229
6413
|
console.error("Error leaving channel", e);
|
|
6230
6414
|
}
|
|
6231
6415
|
}, [channel, currentUserId, onLeaveChannelProp]);
|
|
6232
|
-
const handleRemoveMember =
|
|
6416
|
+
const handleRemoveMember = useCallback23(async (memberId) => {
|
|
6233
6417
|
if (onRemoveMemberProp) return onRemoveMemberProp(memberId);
|
|
6234
6418
|
if (!channel) return;
|
|
6235
6419
|
try {
|
|
@@ -6238,7 +6422,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6238
6422
|
console.error("Error removing member", e);
|
|
6239
6423
|
}
|
|
6240
6424
|
}, [channel, onRemoveMemberProp]);
|
|
6241
|
-
const handleBanMember =
|
|
6425
|
+
const handleBanMember = useCallback23(async (memberId) => {
|
|
6242
6426
|
if (onBanMemberProp) return onBanMemberProp(memberId);
|
|
6243
6427
|
if (!channel) return;
|
|
6244
6428
|
try {
|
|
@@ -6247,7 +6431,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6247
6431
|
console.error("Error banning member", e);
|
|
6248
6432
|
}
|
|
6249
6433
|
}, [channel, onBanMemberProp]);
|
|
6250
|
-
const handleUnbanMember =
|
|
6434
|
+
const handleUnbanMember = useCallback23(async (memberId) => {
|
|
6251
6435
|
if (onUnbanMemberProp) return onUnbanMemberProp(memberId);
|
|
6252
6436
|
if (!channel) return;
|
|
6253
6437
|
try {
|
|
@@ -6256,7 +6440,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6256
6440
|
console.error("Error unbanning member", e);
|
|
6257
6441
|
}
|
|
6258
6442
|
}, [channel, onUnbanMemberProp]);
|
|
6259
|
-
const handlePromoteMember =
|
|
6443
|
+
const handlePromoteMember = useCallback23(async (memberId) => {
|
|
6260
6444
|
if (onPromoteMemberProp) return onPromoteMemberProp(memberId);
|
|
6261
6445
|
if (!channel) return;
|
|
6262
6446
|
try {
|
|
@@ -6265,7 +6449,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6265
6449
|
console.error("Error promoting member", e);
|
|
6266
6450
|
}
|
|
6267
6451
|
}, [channel, onPromoteMemberProp]);
|
|
6268
|
-
const handleDemoteMember =
|
|
6452
|
+
const handleDemoteMember = useCallback23(async (memberId) => {
|
|
6269
6453
|
if (onDemoteMemberProp) return onDemoteMemberProp(memberId);
|
|
6270
6454
|
if (!channel) return;
|
|
6271
6455
|
try {
|
|
@@ -6274,7 +6458,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6274
6458
|
console.error("Error demoting member", e);
|
|
6275
6459
|
}
|
|
6276
6460
|
}, [channel, onDemoteMemberProp]);
|
|
6277
|
-
const handleBlockUser =
|
|
6461
|
+
const handleBlockUser = useCallback23(async () => {
|
|
6278
6462
|
if (onBlockUserProp) return onBlockUserProp();
|
|
6279
6463
|
if (!channel) return;
|
|
6280
6464
|
try {
|
|
@@ -6283,7 +6467,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6283
6467
|
console.error("Error blocking user", e);
|
|
6284
6468
|
}
|
|
6285
6469
|
}, [channel, onBlockUserProp]);
|
|
6286
|
-
const handleUnblockUser =
|
|
6470
|
+
const handleUnblockUser = useCallback23(async () => {
|
|
6287
6471
|
if (onUnblockUserProp) return onUnblockUserProp();
|
|
6288
6472
|
if (!channel) return;
|
|
6289
6473
|
try {
|
|
@@ -6294,22 +6478,22 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6294
6478
|
}, [channel, onUnblockUserProp]);
|
|
6295
6479
|
const { members } = useChannelMembers(channel);
|
|
6296
6480
|
const { channelName, channelImage, channelDescription } = useChannelProfile(channel);
|
|
6297
|
-
const [showAddMemberModal, setShowAddMemberModal] =
|
|
6298
|
-
const [showEditChannelModal, setShowEditChannelModal] =
|
|
6299
|
-
const [showSearchPanel, setShowSearchPanel] =
|
|
6300
|
-
const [showSettingsPanel, setShowSettingsPanel] =
|
|
6481
|
+
const [showAddMemberModal, setShowAddMemberModal] = useState33(false);
|
|
6482
|
+
const [showEditChannelModal, setShowEditChannelModal] = useState33(false);
|
|
6483
|
+
const [showSearchPanel, setShowSearchPanel] = useState33(false);
|
|
6484
|
+
const [showSettingsPanel, setShowSettingsPanel] = useState33(false);
|
|
6301
6485
|
const canEditChannel = isTeamChannel && !isBanned && (currentUserRole === "owner" || currentUserRole === "moder");
|
|
6302
|
-
const handleEditChannelClick =
|
|
6486
|
+
const handleEditChannelClick = useCallback23(() => {
|
|
6303
6487
|
setShowEditChannelModal(true);
|
|
6304
6488
|
}, []);
|
|
6305
|
-
const handleAddMemberClick =
|
|
6489
|
+
const handleAddMemberClick = useCallback23(() => {
|
|
6306
6490
|
if (onAddMemberClick) return onAddMemberClick();
|
|
6307
6491
|
setShowAddMemberModal(true);
|
|
6308
6492
|
}, [onAddMemberClick]);
|
|
6309
6493
|
if (!channel) return null;
|
|
6310
6494
|
return /* @__PURE__ */ jsxs33("div", { className: `ermis-channel-info ${className}`.trim(), children: [
|
|
6311
|
-
/* @__PURE__ */
|
|
6312
|
-
/* @__PURE__ */
|
|
6495
|
+
/* @__PURE__ */ jsx38(HeaderComponent, { title, onClose }),
|
|
6496
|
+
/* @__PURE__ */ jsx38(
|
|
6313
6497
|
CoverComponent,
|
|
6314
6498
|
{
|
|
6315
6499
|
channelName,
|
|
@@ -6323,13 +6507,13 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6323
6507
|
}
|
|
6324
6508
|
),
|
|
6325
6509
|
isBanned ? /* @__PURE__ */ jsxs33("div", { className: "ermis-channel-info__banned-banner", children: [
|
|
6326
|
-
/* @__PURE__ */
|
|
6327
|
-
/* @__PURE__ */
|
|
6328
|
-
/* @__PURE__ */
|
|
6510
|
+
/* @__PURE__ */ jsx38("div", { className: "ermis-channel-info__banned-banner-icon", children: /* @__PURE__ */ jsxs33("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6511
|
+
/* @__PURE__ */ jsx38("circle", { cx: "12", cy: "12", r: "10" }),
|
|
6512
|
+
/* @__PURE__ */ jsx38("line", { x1: "4.93", y1: "4.93", x2: "19.07", y2: "19.07" })
|
|
6329
6513
|
] }) }),
|
|
6330
|
-
/* @__PURE__ */
|
|
6514
|
+
/* @__PURE__ */ jsx38("span", { className: "ermis-channel-info__banned-banner-text", children: "You have been blocked from this channel" })
|
|
6331
6515
|
] }) : /* @__PURE__ */ jsxs33(Fragment8, { children: [
|
|
6332
|
-
/* @__PURE__ */
|
|
6516
|
+
/* @__PURE__ */ jsx38(
|
|
6333
6517
|
ActionsComponent,
|
|
6334
6518
|
{
|
|
6335
6519
|
onSearchClick: () => setShowSearchPanel(true),
|
|
@@ -6349,7 +6533,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6349
6533
|
unblockLabel: actionsUnblockLabel
|
|
6350
6534
|
}
|
|
6351
6535
|
),
|
|
6352
|
-
/* @__PURE__ */
|
|
6536
|
+
/* @__PURE__ */ jsx38(
|
|
6353
6537
|
TabsComponent,
|
|
6354
6538
|
{
|
|
6355
6539
|
channel,
|
|
@@ -6375,7 +6559,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6375
6559
|
),
|
|
6376
6560
|
showAddMemberModal && /* @__PURE__ */ (() => {
|
|
6377
6561
|
const ModalComp = AddMemberModalComponent || AddMemberModal;
|
|
6378
|
-
return /* @__PURE__ */
|
|
6562
|
+
return /* @__PURE__ */ jsx38(
|
|
6379
6563
|
ModalComp,
|
|
6380
6564
|
{
|
|
6381
6565
|
channel,
|
|
@@ -6394,7 +6578,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6394
6578
|
})(),
|
|
6395
6579
|
showEditChannelModal && /* @__PURE__ */ (() => {
|
|
6396
6580
|
const EditComp = EditChannelModalComponent || EditChannelModal;
|
|
6397
|
-
return /* @__PURE__ */
|
|
6581
|
+
return /* @__PURE__ */ jsx38(
|
|
6398
6582
|
EditComp,
|
|
6399
6583
|
{
|
|
6400
6584
|
channel,
|
|
@@ -6418,7 +6602,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6418
6602
|
);
|
|
6419
6603
|
})()
|
|
6420
6604
|
] }),
|
|
6421
|
-
channel && showSearchPanel && /* @__PURE__ */
|
|
6605
|
+
channel && showSearchPanel && /* @__PURE__ */ jsx38(
|
|
6422
6606
|
MessageSearchPanel,
|
|
6423
6607
|
{
|
|
6424
6608
|
isOpen: showSearchPanel,
|
|
@@ -6427,7 +6611,7 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6427
6611
|
AvatarComponent
|
|
6428
6612
|
}
|
|
6429
6613
|
),
|
|
6430
|
-
channel && showSettingsPanel && /* @__PURE__ */
|
|
6614
|
+
channel && showSettingsPanel && /* @__PURE__ */ jsx38(
|
|
6431
6615
|
ChannelSettingsPanel,
|
|
6432
6616
|
{
|
|
6433
6617
|
isOpen: showSettingsPanel,
|
|
@@ -6438,6 +6622,237 @@ var ChannelInfo = React36.memo((props) => {
|
|
|
6438
6622
|
] });
|
|
6439
6623
|
});
|
|
6440
6624
|
ChannelInfo.displayName = "ChannelInfo";
|
|
6625
|
+
|
|
6626
|
+
// src/components/CreateChannelModal.tsx
|
|
6627
|
+
import { useState as useState34, useMemo as useMemo23, useCallback as useCallback24 } from "react";
|
|
6628
|
+
import { Fragment as Fragment9, jsx as jsx39, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
6629
|
+
var CreateChannelModal = ({
|
|
6630
|
+
isOpen,
|
|
6631
|
+
onClose,
|
|
6632
|
+
onSuccess,
|
|
6633
|
+
AvatarComponent = Avatar,
|
|
6634
|
+
UserItemComponent,
|
|
6635
|
+
title = "New Message",
|
|
6636
|
+
directTabLabel = "Direct",
|
|
6637
|
+
groupTabLabel = "Group",
|
|
6638
|
+
groupNameLabel = "Channel Name",
|
|
6639
|
+
groupNamePlaceholder = "Enter channel name (required)",
|
|
6640
|
+
groupDescriptionLabel = "Description",
|
|
6641
|
+
groupDescriptionPlaceholder = "Optional description",
|
|
6642
|
+
groupPublicLabel = "Public Channel",
|
|
6643
|
+
userSearchPlaceholder = "Search users...",
|
|
6644
|
+
cancelButtonLabel = "Cancel",
|
|
6645
|
+
createButtonLabel = "Create",
|
|
6646
|
+
creatingButtonLabel = "Creating..."
|
|
6647
|
+
}) => {
|
|
6648
|
+
const { client } = useChatClient();
|
|
6649
|
+
const currentUserId = client?.userID;
|
|
6650
|
+
const [tab, setTab] = useState34("messaging");
|
|
6651
|
+
const [step, setStep] = useState34(1);
|
|
6652
|
+
const [name, setName] = useState34("");
|
|
6653
|
+
const [description, setDescription] = useState34("");
|
|
6654
|
+
const [isPublic, setIsPublic] = useState34(false);
|
|
6655
|
+
const [selectedUsers, setSelectedUsers] = useState34([]);
|
|
6656
|
+
const [isCreating, setIsCreating] = useState34(false);
|
|
6657
|
+
const [error, setError] = useState34(null);
|
|
6658
|
+
const existingDirectUserIds = useMemo23(() => {
|
|
6659
|
+
if (!client || !currentUserId || tab !== "messaging") return [];
|
|
6660
|
+
const ids = /* @__PURE__ */ new Set();
|
|
6661
|
+
Object.values(client.activeChannels).forEach((channel) => {
|
|
6662
|
+
if (channel.type === "messaging" && channel.state?.members) {
|
|
6663
|
+
Object.keys(channel.state.members).forEach((uid) => {
|
|
6664
|
+
if (uid !== currentUserId) ids.add(uid);
|
|
6665
|
+
});
|
|
6666
|
+
}
|
|
6667
|
+
});
|
|
6668
|
+
return Array.from(ids);
|
|
6669
|
+
}, [client, currentUserId, tab]);
|
|
6670
|
+
const handleCreate = useCallback24(async () => {
|
|
6671
|
+
if (!client || !currentUserId || isCreating) return;
|
|
6672
|
+
if (selectedUsers.length === 0) {
|
|
6673
|
+
setError("Please select at least one user.");
|
|
6674
|
+
return;
|
|
6675
|
+
}
|
|
6676
|
+
if (tab === "team" && !name.trim()) {
|
|
6677
|
+
setError("Group name is required.");
|
|
6678
|
+
return;
|
|
6679
|
+
}
|
|
6680
|
+
setIsCreating(true);
|
|
6681
|
+
setError(null);
|
|
6682
|
+
try {
|
|
6683
|
+
let createdChannel;
|
|
6684
|
+
if (tab === "messaging") {
|
|
6685
|
+
const targetUserId = selectedUsers[0].id;
|
|
6686
|
+
createdChannel = client.channel("messaging", {
|
|
6687
|
+
members: [currentUserId, targetUserId]
|
|
6688
|
+
});
|
|
6689
|
+
await createdChannel.create();
|
|
6690
|
+
} else {
|
|
6691
|
+
const memberIds = selectedUsers.map((member) => member.id);
|
|
6692
|
+
if (!memberIds.includes(currentUserId)) {
|
|
6693
|
+
memberIds.push(currentUserId);
|
|
6694
|
+
}
|
|
6695
|
+
const payload = {
|
|
6696
|
+
name: name.trim(),
|
|
6697
|
+
members: memberIds,
|
|
6698
|
+
public: isPublic
|
|
6699
|
+
};
|
|
6700
|
+
if (description.trim()) {
|
|
6701
|
+
payload.description = description.trim();
|
|
6702
|
+
}
|
|
6703
|
+
createdChannel = client.channel("team", payload);
|
|
6704
|
+
await createdChannel.create();
|
|
6705
|
+
}
|
|
6706
|
+
if (onSuccess) {
|
|
6707
|
+
onSuccess(createdChannel);
|
|
6708
|
+
} else {
|
|
6709
|
+
onClose();
|
|
6710
|
+
}
|
|
6711
|
+
} catch (err) {
|
|
6712
|
+
setError(err?.message || "Failed to create channel");
|
|
6713
|
+
} finally {
|
|
6714
|
+
setIsCreating(false);
|
|
6715
|
+
}
|
|
6716
|
+
}, [client, currentUserId, isCreating, selectedUsers, tab, name, isPublic, description, onSuccess, onClose]);
|
|
6717
|
+
const isValid = useMemo23(() => {
|
|
6718
|
+
if (tab === "messaging" && selectedUsers.length === 0) return false;
|
|
6719
|
+
if (tab === "team" && step === 1 && !name.trim()) return false;
|
|
6720
|
+
if (tab === "team" && step === 2 && selectedUsers.length === 0) return false;
|
|
6721
|
+
return true;
|
|
6722
|
+
}, [selectedUsers, tab, name, step]);
|
|
6723
|
+
let footer;
|
|
6724
|
+
if (tab === "messaging") {
|
|
6725
|
+
footer = /* @__PURE__ */ jsxs34("div", { className: "ermis-create-channel__footer", children: [
|
|
6726
|
+
/* @__PURE__ */ jsx39("button", { className: "ermis-create-channel__btn ermis-create-channel__btn--cancel", onClick: onClose, disabled: isCreating, children: cancelButtonLabel }),
|
|
6727
|
+
/* @__PURE__ */ jsx39("button", { className: "ermis-create-channel__btn ermis-create-channel__btn--create", onClick: handleCreate, disabled: isCreating || !isValid, children: isCreating ? creatingButtonLabel : createButtonLabel })
|
|
6728
|
+
] });
|
|
6729
|
+
} else if (tab === "team" && step === 1) {
|
|
6730
|
+
footer = /* @__PURE__ */ jsxs34("div", { className: "ermis-create-channel__footer", children: [
|
|
6731
|
+
/* @__PURE__ */ jsx39("button", { className: "ermis-create-channel__btn ermis-create-channel__btn--cancel", onClick: onClose, disabled: isCreating, children: cancelButtonLabel }),
|
|
6732
|
+
/* @__PURE__ */ jsx39("button", { className: "ermis-create-channel__btn ermis-create-channel__btn--create", onClick: () => {
|
|
6733
|
+
setError(null);
|
|
6734
|
+
setStep(2);
|
|
6735
|
+
}, disabled: isCreating || !isValid, children: "Next" })
|
|
6736
|
+
] });
|
|
6737
|
+
} else if (tab === "team" && step === 2) {
|
|
6738
|
+
footer = /* @__PURE__ */ jsxs34("div", { className: "ermis-create-channel__footer", children: [
|
|
6739
|
+
/* @__PURE__ */ jsx39("button", { className: "ermis-create-channel__btn ermis-create-channel__btn--cancel", onClick: () => {
|
|
6740
|
+
setError(null);
|
|
6741
|
+
setStep(1);
|
|
6742
|
+
}, disabled: isCreating, children: "Back" }),
|
|
6743
|
+
/* @__PURE__ */ jsx39("button", { className: "ermis-create-channel__btn ermis-create-channel__btn--create", onClick: handleCreate, disabled: isCreating || !isValid, children: isCreating ? creatingButtonLabel : createButtonLabel })
|
|
6744
|
+
] });
|
|
6745
|
+
}
|
|
6746
|
+
return /* @__PURE__ */ jsx39(Modal, { isOpen, onClose: isCreating ? () => {
|
|
6747
|
+
} : onClose, title, maxWidth: "480px", footer, children: /* @__PURE__ */ jsxs34("div", { className: "ermis-create-channel__body", children: [
|
|
6748
|
+
/* @__PURE__ */ jsxs34("div", { className: "ermis-create-channel__tabs", children: [
|
|
6749
|
+
/* @__PURE__ */ jsx39(
|
|
6750
|
+
"button",
|
|
6751
|
+
{
|
|
6752
|
+
className: `ermis-create-channel__tab ${tab === "messaging" ? "ermis-create-channel__tab--active" : ""}`,
|
|
6753
|
+
onClick: () => {
|
|
6754
|
+
setTab("messaging");
|
|
6755
|
+
setStep(1);
|
|
6756
|
+
setSelectedUsers([]);
|
|
6757
|
+
setError(null);
|
|
6758
|
+
},
|
|
6759
|
+
disabled: isCreating,
|
|
6760
|
+
children: directTabLabel
|
|
6761
|
+
}
|
|
6762
|
+
),
|
|
6763
|
+
/* @__PURE__ */ jsx39(
|
|
6764
|
+
"button",
|
|
6765
|
+
{
|
|
6766
|
+
className: `ermis-create-channel__tab ${tab === "team" ? "ermis-create-channel__tab--active" : ""}`,
|
|
6767
|
+
onClick: () => {
|
|
6768
|
+
setTab("team");
|
|
6769
|
+
setStep(1);
|
|
6770
|
+
setSelectedUsers([]);
|
|
6771
|
+
setError(null);
|
|
6772
|
+
},
|
|
6773
|
+
disabled: isCreating,
|
|
6774
|
+
children: groupTabLabel
|
|
6775
|
+
}
|
|
6776
|
+
)
|
|
6777
|
+
] }),
|
|
6778
|
+
tab === "team" && step === 1 && /* @__PURE__ */ jsxs34(Fragment9, { children: [
|
|
6779
|
+
/* @__PURE__ */ jsxs34("div", { className: "ermis-create-channel__field", children: [
|
|
6780
|
+
/* @__PURE__ */ jsxs34("label", { className: "ermis-create-channel__label", children: [
|
|
6781
|
+
groupNameLabel,
|
|
6782
|
+
" ",
|
|
6783
|
+
/* @__PURE__ */ jsx39("span", { style: { color: "var(--ermis-error)" }, children: "*" })
|
|
6784
|
+
] }),
|
|
6785
|
+
/* @__PURE__ */ jsx39(
|
|
6786
|
+
"input",
|
|
6787
|
+
{
|
|
6788
|
+
className: "ermis-create-channel__input",
|
|
6789
|
+
value: name,
|
|
6790
|
+
onChange: (e) => setName(e.target.value),
|
|
6791
|
+
placeholder: groupNamePlaceholder,
|
|
6792
|
+
disabled: isCreating,
|
|
6793
|
+
maxLength: 100
|
|
6794
|
+
}
|
|
6795
|
+
)
|
|
6796
|
+
] }),
|
|
6797
|
+
/* @__PURE__ */ jsxs34("div", { className: "ermis-create-channel__field", children: [
|
|
6798
|
+
/* @__PURE__ */ jsx39("label", { className: "ermis-create-channel__label", children: groupDescriptionLabel }),
|
|
6799
|
+
/* @__PURE__ */ jsx39(
|
|
6800
|
+
"textarea",
|
|
6801
|
+
{
|
|
6802
|
+
className: "ermis-create-channel__textarea",
|
|
6803
|
+
value: description,
|
|
6804
|
+
onChange: (e) => setDescription(e.target.value),
|
|
6805
|
+
placeholder: groupDescriptionPlaceholder,
|
|
6806
|
+
disabled: isCreating,
|
|
6807
|
+
maxLength: 500,
|
|
6808
|
+
rows: 2
|
|
6809
|
+
}
|
|
6810
|
+
)
|
|
6811
|
+
] }),
|
|
6812
|
+
/* @__PURE__ */ jsxs34("div", { className: "ermis-create-channel__field ermis-create-channel__field--toggle", children: [
|
|
6813
|
+
/* @__PURE__ */ jsx39("label", { className: "ermis-create-channel__label", children: groupPublicLabel }),
|
|
6814
|
+
/* @__PURE__ */ jsx39(
|
|
6815
|
+
"button",
|
|
6816
|
+
{
|
|
6817
|
+
type: "button",
|
|
6818
|
+
role: "switch",
|
|
6819
|
+
"aria-checked": isPublic,
|
|
6820
|
+
className: `ermis-create-channel__toggle ${isPublic ? "ermis-create-channel__toggle--on" : ""}`,
|
|
6821
|
+
onClick: () => setIsPublic((v) => !v),
|
|
6822
|
+
disabled: isCreating,
|
|
6823
|
+
children: /* @__PURE__ */ jsx39("span", { className: "ermis-create-channel__toggle-thumb" })
|
|
6824
|
+
}
|
|
6825
|
+
)
|
|
6826
|
+
] })
|
|
6827
|
+
] }),
|
|
6828
|
+
(tab === "team" && step === 2 || tab === "messaging") && /* @__PURE__ */ jsxs34("div", { className: "ermis-create-channel__users", children: [
|
|
6829
|
+
/* @__PURE__ */ jsxs34("div", { className: "ermis-create-channel__users-title", children: [
|
|
6830
|
+
"Members ",
|
|
6831
|
+
/* @__PURE__ */ jsx39("span", { style: { color: "var(--ermis-error)" }, children: "*" })
|
|
6832
|
+
] }),
|
|
6833
|
+
/* @__PURE__ */ jsx39("div", { style: { height: tab === "team" ? "280px" : "400px", display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsx39(
|
|
6834
|
+
UserPicker,
|
|
6835
|
+
{
|
|
6836
|
+
mode: tab === "messaging" ? "radio" : "checkbox",
|
|
6837
|
+
onSelectionChange: setSelectedUsers,
|
|
6838
|
+
excludeUserIds: tab === "messaging" ? existingDirectUserIds : [],
|
|
6839
|
+
initialSelectedUsers: selectedUsers,
|
|
6840
|
+
AvatarComponent,
|
|
6841
|
+
UserItemComponent,
|
|
6842
|
+
searchPlaceholder: userSearchPlaceholder
|
|
6843
|
+
}
|
|
6844
|
+
) })
|
|
6845
|
+
] }),
|
|
6846
|
+
error && /* @__PURE__ */ jsxs34("div", { className: "ermis-create-channel__error", children: [
|
|
6847
|
+
/* @__PURE__ */ jsxs34("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6848
|
+
/* @__PURE__ */ jsx39("circle", { cx: "12", cy: "12", r: "10" }),
|
|
6849
|
+
/* @__PURE__ */ jsx39("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
6850
|
+
/* @__PURE__ */ jsx39("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
|
|
6851
|
+
] }),
|
|
6852
|
+
error
|
|
6853
|
+
] })
|
|
6854
|
+
] }) });
|
|
6855
|
+
};
|
|
6441
6856
|
export {
|
|
6442
6857
|
AttachmentList,
|
|
6443
6858
|
Avatar,
|
|
@@ -6447,6 +6862,7 @@ export {
|
|
|
6447
6862
|
ChannelItem,
|
|
6448
6863
|
ChannelList,
|
|
6449
6864
|
ChatProvider,
|
|
6865
|
+
CreateChannelModal,
|
|
6450
6866
|
DefaultChannelInfoActions,
|
|
6451
6867
|
DefaultChannelInfoCover,
|
|
6452
6868
|
DefaultChannelInfoHeader,
|
|
@@ -6474,6 +6890,7 @@ export {
|
|
|
6474
6890
|
SystemMessage,
|
|
6475
6891
|
SystemMessageItem,
|
|
6476
6892
|
TypingIndicator,
|
|
6893
|
+
UserPicker,
|
|
6477
6894
|
VirtualMessageList,
|
|
6478
6895
|
closeAllDropdowns,
|
|
6479
6896
|
dedupMessages,
|