feat: switches
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vocechat-web",
|
"name": "vocechat-web",
|
||||||
"version": "0.7.29",
|
"version": "0.7.30",
|
||||||
"homepage": "https://voce.chat",
|
"homepage": "https://voce.chat",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@metamask/onboarding": "^1.0.1",
|
"@metamask/onboarding": "^1.0.1",
|
||||||
|
|||||||
@@ -53,6 +53,12 @@
|
|||||||
"everyone": "Everyone",
|
"everyone": "Everyone",
|
||||||
"invite": "Invitation Link Only"
|
"invite": "Invitation Link Only"
|
||||||
},
|
},
|
||||||
|
"admin_create_group": {
|
||||||
|
"title": "Only Admins create group",
|
||||||
|
"desc": "If enabled, only admins can create group.",
|
||||||
|
"enable": "Enable",
|
||||||
|
"disable": "Disabled"
|
||||||
|
},
|
||||||
"guest_mode": {
|
"guest_mode": {
|
||||||
"title": "Guest Mode",
|
"title": "Guest Mode",
|
||||||
"desc": "If enabled, visitors will see public channels on this server.",
|
"desc": "If enabled, visitors will see public channels on this server.",
|
||||||
|
|||||||
@@ -24,8 +24,10 @@ const initialState: StoredServer = {
|
|||||||
show_user_online_status: false,
|
show_user_online_status: false,
|
||||||
webclient_auto_update: true,
|
webclient_auto_update: true,
|
||||||
contact_verification_enable: false,
|
contact_verification_enable: false,
|
||||||
|
only_admin_can_create_group: false,
|
||||||
chat_layout_mode: "Left",
|
chat_layout_mode: "Left",
|
||||||
loginConfig: null
|
loginConfig: null,
|
||||||
|
ext_setting: null
|
||||||
};
|
};
|
||||||
|
|
||||||
const serverSlice = createSlice({
|
const serverSlice = createSlice({
|
||||||
@@ -50,7 +52,9 @@ const serverSlice = createSlice({
|
|||||||
webclient_auto_update = true,
|
webclient_auto_update = true,
|
||||||
contact_verification_enable = false,
|
contact_verification_enable = false,
|
||||||
chat_layout_mode = "Left",
|
chat_layout_mode = "Left",
|
||||||
loginConfig = state.loginConfig || null
|
only_admin_can_create_group = false,
|
||||||
|
loginConfig = state.loginConfig || null,
|
||||||
|
ext_setting = null
|
||||||
} = action.payload || {};
|
} = action.payload || {};
|
||||||
return {
|
return {
|
||||||
version: state.version || version,
|
version: state.version || version,
|
||||||
@@ -62,8 +66,10 @@ const serverSlice = createSlice({
|
|||||||
show_user_online_status,
|
show_user_online_status,
|
||||||
webclient_auto_update,
|
webclient_auto_update,
|
||||||
contact_verification_enable,
|
contact_verification_enable,
|
||||||
|
only_admin_can_create_group,
|
||||||
chat_layout_mode,
|
chat_layout_mode,
|
||||||
loginConfig
|
loginConfig,
|
||||||
|
ext_setting
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
updateInfo(state, action: PayloadAction<Partial<StoredServer>>) {
|
updateInfo(state, action: PayloadAction<Partial<StoredServer>>) {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const Profile: FC<Props> = ({ uid, type = "embed", cid }) => {
|
|||||||
const { t } = useTranslation("member");
|
const { t } = useTranslation("member");
|
||||||
const { t: ct } = useTranslation();
|
const { t: ct } = useTranslation();
|
||||||
const {
|
const {
|
||||||
|
canDM,
|
||||||
canCopyEmail,
|
canCopyEmail,
|
||||||
copyEmail,
|
copyEmail,
|
||||||
startCall,
|
startCall,
|
||||||
@@ -36,7 +37,6 @@ const Profile: FC<Props> = ({ uid, type = "embed", cid }) => {
|
|||||||
canUpdateRole,
|
canUpdateRole,
|
||||||
updateRole
|
updateRole
|
||||||
} = useUserOperation({ uid, cid });
|
} = useUserOperation({ uid, cid });
|
||||||
|
|
||||||
const data = useAppSelector((store) => store.users.byId[uid], shallowEqual);
|
const data = useAppSelector((store) => store.users.byId[uid], shallowEqual);
|
||||||
if (!data) return null;
|
if (!data) return null;
|
||||||
// console.log("profile", data);
|
// console.log("profile", data);
|
||||||
@@ -54,6 +54,7 @@ const Profile: FC<Props> = ({ uid, type = "embed", cid }) => {
|
|||||||
`flex-center flex-col gap-1 z-[99] mt-20 select-none`,
|
`flex-center flex-col gap-1 z-[99] mt-20 select-none`,
|
||||||
isCard ? "p-4 w-[280px] bg-white dark:bg-gray-800 drop-shadow rounded-md" : "md:w-[432px]"
|
isCard ? "p-4 w-[280px] bg-white dark:bg-gray-800 drop-shadow rounded-md" : "md:w-[432px]"
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={containerClass}>
|
<div className={containerClass}>
|
||||||
<Avatar
|
<Avatar
|
||||||
@@ -64,80 +65,86 @@ const Profile: FC<Props> = ({ uid, type = "embed", cid }) => {
|
|||||||
name={name}
|
name={name}
|
||||||
/>
|
/>
|
||||||
<h2 className="text-lg select-text font-bold text-gray-900 dark:text-white">
|
<h2 className="text-lg select-text font-bold text-gray-900 dark:text-white">
|
||||||
{name} <span className="font-normal text-gray-500">#{uid}</span>
|
{name} {canDM && <span className="font-normal text-gray-500">#{uid}</span>}
|
||||||
</h2>
|
</h2>
|
||||||
<span className="text-sm text-gray-400 dark:text-gray-200 select-text">{email}</span>
|
{canCopyEmail && (
|
||||||
|
<span className="text-sm text-gray-400 dark:text-gray-200 select-text">{email}</span>
|
||||||
|
)}
|
||||||
{/* <p className="intro">{introduction}</p> */}
|
{/* <p className="intro">{introduction}</p> */}
|
||||||
<ul className={clsx("mt-6 flex flex-col md:flex-row items-center gap-2", isCard && "pb-0.5")}>
|
{canDM && (
|
||||||
<NavLink to={`/chat/dm/${uid}`}>
|
<ul
|
||||||
<li className={`${iconClass} icon chat`}>
|
className={clsx("mt-6 flex flex-col md:flex-row items-center gap-2", isCard && "pb-0.5")}
|
||||||
<IconMessage />
|
|
||||||
<span>{t("send_msg")}</span>
|
|
||||||
</li>
|
|
||||||
</NavLink>
|
|
||||||
{agoraEnabled && type == "embed" && (
|
|
||||||
<li role="button" onClick={startCall} className={`${iconClass} icon chat`}>
|
|
||||||
<IconCall className="fill-primary-400" />
|
|
||||||
<span>{t("call")}</span>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
<Tippy
|
|
||||||
disabled={!hasMore}
|
|
||||||
interactive
|
|
||||||
popperOptions={{ strategy: "fixed" }}
|
|
||||||
placement="right"
|
|
||||||
trigger="click"
|
|
||||||
hideOnClick={true}
|
|
||||||
content={
|
|
||||||
<ContextMenu
|
|
||||||
items={
|
|
||||||
[
|
|
||||||
agoraEnabled &&
|
|
||||||
type == "card" && {
|
|
||||||
title: t("call"),
|
|
||||||
handler: startCall
|
|
||||||
},
|
|
||||||
canCopyEmail && {
|
|
||||||
title: t("copy_email"),
|
|
||||||
handler: copyEmail
|
|
||||||
},
|
|
||||||
canUpdateRole && {
|
|
||||||
title: t("roles"),
|
|
||||||
handler: updateRole,
|
|
||||||
subs: [
|
|
||||||
{
|
|
||||||
title: t("set_normal"),
|
|
||||||
checked: !isAdmin,
|
|
||||||
handler: updateRole
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("set_admin"),
|
|
||||||
checked: isAdmin,
|
|
||||||
handler: updateRole
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
canRemoveFromChannel && {
|
|
||||||
title: t("remove_from_channel"),
|
|
||||||
danger: true,
|
|
||||||
handler: removeFromChannel
|
|
||||||
},
|
|
||||||
canRemoveFromServer && {
|
|
||||||
title: t("remove"),
|
|
||||||
handler: removeUser,
|
|
||||||
danger: true
|
|
||||||
}
|
|
||||||
].filter(Boolean) as Item[]
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<li className={`${iconClass} icon ${hasMore ? "" : "text-gray-500"}`}>
|
<NavLink to={`/chat/dm/${uid}`}>
|
||||||
<IconMore className={hasMore ? "fill-primary-500" : ""} />
|
<li className={`${iconClass} icon chat`}>
|
||||||
<span>{ct("more")}</span>
|
<IconMessage />
|
||||||
</li>
|
<span>{t("send_msg")}</span>
|
||||||
</Tippy>
|
</li>
|
||||||
</ul>
|
</NavLink>
|
||||||
|
{agoraEnabled && type == "embed" && (
|
||||||
|
<li role="button" onClick={startCall} className={`${iconClass} icon chat`}>
|
||||||
|
<IconCall className="fill-primary-400" />
|
||||||
|
<span>{t("call")}</span>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
<Tippy
|
||||||
|
disabled={!hasMore}
|
||||||
|
interactive
|
||||||
|
popperOptions={{ strategy: "fixed" }}
|
||||||
|
placement="right"
|
||||||
|
trigger="click"
|
||||||
|
hideOnClick={true}
|
||||||
|
content={
|
||||||
|
<ContextMenu
|
||||||
|
items={
|
||||||
|
[
|
||||||
|
agoraEnabled &&
|
||||||
|
type == "card" && {
|
||||||
|
title: t("call"),
|
||||||
|
handler: startCall
|
||||||
|
},
|
||||||
|
canCopyEmail && {
|
||||||
|
title: t("copy_email"),
|
||||||
|
handler: copyEmail
|
||||||
|
},
|
||||||
|
canUpdateRole && {
|
||||||
|
title: t("roles"),
|
||||||
|
handler: updateRole,
|
||||||
|
subs: [
|
||||||
|
{
|
||||||
|
title: t("set_normal"),
|
||||||
|
checked: !isAdmin,
|
||||||
|
handler: updateRole
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("set_admin"),
|
||||||
|
checked: isAdmin,
|
||||||
|
handler: updateRole
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
canRemoveFromChannel && {
|
||||||
|
title: t("remove_from_channel"),
|
||||||
|
danger: true,
|
||||||
|
handler: removeFromChannel
|
||||||
|
},
|
||||||
|
canRemoveFromServer && {
|
||||||
|
title: t("remove"),
|
||||||
|
handler: removeUser,
|
||||||
|
danger: true
|
||||||
|
}
|
||||||
|
].filter(Boolean) as Item[]
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<li className={`${iconClass} icon ${hasMore ? "" : "text-gray-500"}`}>
|
||||||
|
<IconMore className={hasMore ? "fill-primary-500" : ""} />
|
||||||
|
<span>{ct("more")}</span>
|
||||||
|
</li>
|
||||||
|
</Tippy>
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ type Props = {
|
|||||||
|
|
||||||
const SettingBlock = ({ title, desc, children }: Props) => {
|
const SettingBlock = ({ title, desc, children }: Props) => {
|
||||||
return (
|
return (
|
||||||
<div className="text-sm">
|
<div className="text-sm w-full">
|
||||||
<p className="text-gray-600 dark:text-gray-100 font-semibold">{title}</p>
|
<p className="text-gray-600 dark:text-gray-100 font-semibold">{title}</p>
|
||||||
<p className="flex justify-between w-full text-gray-400 mb-2 text-xs">{desc}</p>
|
<p className="flex justify-between w-full text-gray-400 mb-2 text-xs">{desc}</p>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ const useUserOperation = ({ uid, cid }: IProps) => {
|
|||||||
shallowEqual
|
shallowEqual
|
||||||
);
|
);
|
||||||
const loginUser = useAppSelector((store) => store.authData.user, shallowEqual);
|
const loginUser = useAppSelector((store) => store.authData.user, shallowEqual);
|
||||||
|
const { show_email = true, dm_to_member = true } = channel ?? {};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setPassedUid(uid ?? loginUser?.uid);
|
setPassedUid(uid ?? loginUser?.uid);
|
||||||
}, [uid, loginUser]);
|
}, [uid, loginUser]);
|
||||||
@@ -103,7 +103,7 @@ const useUserOperation = ({ uid, cid }: IProps) => {
|
|||||||
aside: "voice" as const
|
aside: "voice" as const
|
||||||
};
|
};
|
||||||
dispatch(updateDMVisibleAside(data));
|
dispatch(updateDMVisibleAside(data));
|
||||||
// 实时显示calling box
|
// 实时显示 calling box
|
||||||
if (!joinedAtThisContext) {
|
if (!joinedAtThisContext) {
|
||||||
dispatch(updateCallInfo({ from: loginUser?.uid ?? 0, to: uid, calling: false }));
|
dispatch(updateCallInfo({ from: loginUser?.uid ?? 0, to: uid, calling: false }));
|
||||||
}
|
}
|
||||||
@@ -160,8 +160,9 @@ const useUserOperation = ({ uid, cid }: IProps) => {
|
|||||||
startChat,
|
startChat,
|
||||||
removeFromChannel: handleRemoveFromChannel,
|
removeFromChannel: handleRemoveFromChannel,
|
||||||
canRemoveFromChannel,
|
canRemoveFromChannel,
|
||||||
canCopyEmail: !!user?.email,
|
canCopyEmail: !!user?.email && show_email,
|
||||||
copyEmail,
|
copyEmail,
|
||||||
|
canDM: dm_to_member,
|
||||||
startCall
|
startCall
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import OnlineStatus from "./OnlineStatus";
|
|||||||
import MessageSound from "./MessageSound";
|
import MessageSound from "./MessageSound";
|
||||||
import Server from "./Server";
|
import Server from "./Server";
|
||||||
import { shallowEqual } from "react-redux";
|
import { shallowEqual } from "react-redux";
|
||||||
|
import OnlyAdminCreateGroup from "./OnlyAdminCreateGroup";
|
||||||
|
|
||||||
export default function Overview() {
|
export default function Overview() {
|
||||||
const { t } = useTranslation("setting");
|
const { t } = useTranslation("setting");
|
||||||
@@ -53,6 +54,9 @@ export default function Overview() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</SettingBlock>
|
</SettingBlock>
|
||||||
|
{/* 只有 admin 能创建群组 */}
|
||||||
|
|
||||||
|
<OnlyAdminCreateGroup />
|
||||||
{/* 访客模式 */}
|
{/* 访客模式 */}
|
||||||
<SettingBlock title={t("overview.guest_mode.title")} desc={t("overview.guest_mode.desc")}>
|
<SettingBlock title={t("overview.guest_mode.title")} desc={t("overview.guest_mode.desc")}>
|
||||||
<StyledRadio
|
<StyledRadio
|
||||||
@@ -64,6 +68,7 @@ export default function Overview() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</SettingBlock>
|
</SettingBlock>
|
||||||
|
|
||||||
{/* 是否显示在线提示 */}
|
{/* 是否显示在线提示 */}
|
||||||
<OnlineStatus />
|
<OnlineStatus />
|
||||||
{/* 会话布局 */}
|
{/* 会话布局 */}
|
||||||
|
|||||||
@@ -1,144 +0,0 @@
|
|||||||
import { ChangeEvent, useEffect, useState } from "react";
|
|
||||||
import toast from "react-hot-toast";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
import {
|
|
||||||
useChangeChannelTypeMutation,
|
|
||||||
useGetChannelQuery,
|
|
||||||
useUpdateChannelMutation,
|
|
||||||
useUpdateIconMutation
|
|
||||||
} from "@/app/services/channel";
|
|
||||||
import { useAppSelector } from "@/app/store";
|
|
||||||
import { Channel } from "@/types/channel";
|
|
||||||
import AvatarUploader from "@/components/AvatarUploader";
|
|
||||||
import SaveTip from "@/components/SaveTip";
|
|
||||||
import Input from "@/components/styled/Input";
|
|
||||||
import Label from "@/components/styled/Label";
|
|
||||||
import Radio from "@/components/styled/Radio";
|
|
||||||
import Textarea from "@/components/styled/Textarea";
|
|
||||||
import IconChannel from "@/assets/icons/channel.svg";
|
|
||||||
import { shallowEqual } from "react-redux";
|
|
||||||
|
|
||||||
export default function Overview({ id = 0 }) {
|
|
||||||
const { t } = useTranslation("setting", { keyPrefix: "channel" });
|
|
||||||
const { t: ct } = useTranslation();
|
|
||||||
const loginUser = useAppSelector((store) => store.authData.user, shallowEqual);
|
|
||||||
const channel = useAppSelector((store) => store.channels.byId[id], shallowEqual);
|
|
||||||
const { data, refetch } = useGetChannelQuery(id);
|
|
||||||
const [changed, setChanged] = useState(false);
|
|
||||||
const [values, setValues] = useState<Channel>();
|
|
||||||
const [updateChannelIcon] = useUpdateIconMutation();
|
|
||||||
const [updateChannel, { isSuccess: updated }] = useUpdateChannelMutation();
|
|
||||||
const [changeChannelType, { isSuccess: changeTypeSuccess }] = useChangeChannelTypeMutation();
|
|
||||||
const handleUpdate = () => {
|
|
||||||
if (!values) return;
|
|
||||||
const { name, description } = values;
|
|
||||||
updateChannel({ id, name, description });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleChange = (evt: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
|
||||||
const newValue = evt.target.value;
|
|
||||||
const { type = "" } = evt.target.dataset;
|
|
||||||
setValues((prev) => {
|
|
||||||
if (!prev) return prev;
|
|
||||||
return { ...prev, [type]: newValue };
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateIcon = (image: File) => {
|
|
||||||
updateChannelIcon({ gid: id, image });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleReset = () => {
|
|
||||||
setValues(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (data) {
|
|
||||||
setValues(data);
|
|
||||||
}
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (data && values) {
|
|
||||||
const { name, description } = values;
|
|
||||||
const { name: oName, description: oDescription } = data;
|
|
||||||
if (oName !== name || oDescription !== description) {
|
|
||||||
setChanged(true);
|
|
||||||
} else {
|
|
||||||
setChanged(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [data, values]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (updated) {
|
|
||||||
toast.success(ct("tip.update"));
|
|
||||||
refetch();
|
|
||||||
}
|
|
||||||
}, [updated]);
|
|
||||||
useEffect(() => {
|
|
||||||
if (changeTypeSuccess) {
|
|
||||||
toast.success(ct("tip.update"));
|
|
||||||
}
|
|
||||||
}, [changeTypeSuccess]);
|
|
||||||
|
|
||||||
if (!values || !id || !channel) return null;
|
|
||||||
const { name, description } = values;
|
|
||||||
const readOnly = !loginUser?.is_admin && channel?.owner != loginUser?.uid;
|
|
||||||
const inputClass = `w-full flex flex-col items-start gap-2 relative`;
|
|
||||||
return (
|
|
||||||
<div className="relative w-[512px] flex flex-col gap-6 h-full">
|
|
||||||
<AvatarUploader type="channel" url={channel?.icon} name={name} uploadImage={updateIcon} />
|
|
||||||
<div className="flex flex-col gap-6 items-start">
|
|
||||||
<div className={"flex items-center gap-1"}>
|
|
||||||
<Label htmlFor="name">{t("id")}</Label>
|
|
||||||
<span className="text-gray-500">#{id}</span>
|
|
||||||
</div>
|
|
||||||
<div className={inputClass}>
|
|
||||||
<Label htmlFor="name">{t("name")}</Label>
|
|
||||||
<Input
|
|
||||||
disabled={readOnly}
|
|
||||||
className="!pl-8"
|
|
||||||
data-type="name"
|
|
||||||
onChange={handleChange}
|
|
||||||
value={name}
|
|
||||||
name="name"
|
|
||||||
id="name"
|
|
||||||
placeholder={t("name")}
|
|
||||||
/>
|
|
||||||
<IconChannel className="absolute bottom-2.5 left-2 dark:fill-gray-300" />
|
|
||||||
</div>
|
|
||||||
<div className={inputClass}>
|
|
||||||
<Label htmlFor="desc">{t("topic")}</Label>
|
|
||||||
<Textarea
|
|
||||||
disabled={readOnly}
|
|
||||||
data-type="description"
|
|
||||||
onChange={handleChange}
|
|
||||||
value={description ?? ""}
|
|
||||||
rows={4}
|
|
||||||
name="name"
|
|
||||||
id="name"
|
|
||||||
placeholder={t("topic_placeholder")}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{!readOnly && loginUser.is_admin && (
|
|
||||||
<div className={inputClass}>
|
|
||||||
<Label htmlFor="desc">{t("visibility")}</Label>
|
|
||||||
<Radio
|
|
||||||
options={[t("public"), t("private")]}
|
|
||||||
values={["true", "false"]}
|
|
||||||
value={String(channel.is_public)}
|
|
||||||
onChange={(v: string) => {
|
|
||||||
// console.log("wtff", typeof v, v);
|
|
||||||
changeChannelType({ is_public: v.toLowerCase() === "true", id });
|
|
||||||
// handleGuestToggle(v);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{changed && <SaveTip saveHandler={handleUpdate} resetHandler={handleReset} />}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
+20
-1
@@ -28,6 +28,12 @@ export interface Channel {
|
|||||||
is_public: boolean;
|
is_public: boolean;
|
||||||
avatar_updated_at: number;
|
avatar_updated_at: number;
|
||||||
pinned_messages: PinnedMessage[];
|
pinned_messages: PinnedMessage[];
|
||||||
|
// ext switches
|
||||||
|
show_email: boolean;
|
||||||
|
dm_to_member: boolean;
|
||||||
|
add_friend: boolean;
|
||||||
|
only_owner_can_send_msg: boolean;
|
||||||
|
ext_setting: null | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateChannelDTO {
|
export interface CreateChannelDTO {
|
||||||
@@ -37,7 +43,20 @@ export interface CreateChannelDTO {
|
|||||||
is_public: boolean;
|
is_public: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChannelDTO extends Partial<Pick<Channel, "owner" | "description" | "name">> {
|
export interface ChannelDTO
|
||||||
|
extends Partial<
|
||||||
|
Pick<
|
||||||
|
Channel,
|
||||||
|
| "owner"
|
||||||
|
| "description"
|
||||||
|
| "name"
|
||||||
|
| "show_email"
|
||||||
|
| "add_friend"
|
||||||
|
| "only_owner_can_send_msg"
|
||||||
|
| "dm_to_member"
|
||||||
|
| "ext_setting"
|
||||||
|
>
|
||||||
|
> {
|
||||||
id: number;
|
id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ export interface SystemCommon {
|
|||||||
contact_verification_enable?: boolean;
|
contact_verification_enable?: boolean;
|
||||||
chat_layout_mode?: ChatLayout;
|
chat_layout_mode?: ChatLayout;
|
||||||
max_file_expiry_mode?: MessageExpireMode;
|
max_file_expiry_mode?: MessageExpireMode;
|
||||||
|
only_admin_can_create_group: boolean;
|
||||||
|
ext_setting: null | string;
|
||||||
}
|
}
|
||||||
export interface GithubAuthConfig {
|
export interface GithubAuthConfig {
|
||||||
client_id?: string;
|
client_id?: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user