Skip to content

Commit

Permalink
Only show edit icon is chain admin
Browse files Browse the repository at this point in the history
  • Loading branch information
lil5 committed May 13, 2024
1 parent 0616c54 commit 75303e5
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 42 deletions.
90 changes: 52 additions & 38 deletions app/src/components/Chat/ChatWindow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@ import { IsChainAdmin, MmData, StoreContext } from "../../stores/Store";
import ChatInput, { SendingMsgState } from "./ChatInput";
import { Channel } from "@mattermost/types/channels";
import { IonActionSheet, IonAlert, IonIcon, useIonAlert } from "@ionic/react";
import { addOutline } from "ionicons/icons";
import { addOutline, build as buildFilled } from "ionicons/icons";
import { useTranslation } from "react-i18next";
import { IonAlertCustomEvent } from "@ionic/core";
import { PostList } from "@mattermost/types/posts";
import { User } from "../../api/types";
import ChatPost from "./ChatPost";
import { useIntersectionObserver } from "@uidotdev/usehooks";
import { useContext, useEffect, useRef, useState } from "react";
import { useContext, useEffect, useMemo, useRef, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
import { useLongPress } from "use-long-press";
import { c } from "vitest/dist/reporters-5f784f42";

interface Props {
channels: Channel[];
Expand All @@ -22,7 +21,7 @@ interface Props {
authUser: User;
onCreateChannel: (n: string) => void;
onSelectChannel: (c: Channel) => void;
onRenameChannel: (n: string) => void;
onRenameChannel: (c: Channel, n: string) => void;
onDeleteChannel: () => void;
onScrollTop: (topPostId: string) => void;
onSendMessage: (msg: string, callback: Function) => Promise<void>;
Expand All @@ -31,7 +30,7 @@ interface Props {
// This follows the controller / view component pattern
export default function ChatWindow(props: Props) {
const { t } = useTranslation();
const { isChainAdmin } = useContext(StoreContext);
const { isChainAdmin, chain } = useContext(StoreContext);
const slowTriggerScrollTop = useDebouncedCallback(() => {
const lastPostId = props.postList.order.at(-1);
if (lastPostId) {
Expand All @@ -54,14 +53,23 @@ export default function ChatWindow(props: Props) {
}
}, [entry?.isIntersecting]);

const chainChannels = useMemo(() => {
if (!chain || !chain.chat_room_ids) return [];
console.log("chainChannels", props.channels);
return props.channels
.filter((c) => chain.chat_room_ids?.includes(c.id))
.sort((a, b) => (a.create_at > b.create_at ? 1 : 0));
}, [props.channels, chain]);

function onCreateChannelSubmit(e: IonAlertCustomEvent<any>) {
if (e?.detail?.role === "submit" && e.detail?.data?.values?.name) {
props.onCreateChannel(e.detail.data.values.name);
}
}

function onRenameChannelSubmit(name: string) {
props.onRenameChannel(name);
if (!props.selectedChannel) return;
props.onRenameChannel(props.selectedChannel, name);
}

function onDeleteChannelSubmit() {
Expand Down Expand Up @@ -106,8 +114,8 @@ export default function ChatWindow(props: Props) {
],
});
} else if (value == "rename") {
const handler = (newChannelName: string) => {
onRenameChannelSubmit(newChannelName);
const handler = (e: { newChannelName: string }) => {
onRenameChannelSubmit(e.newChannelName);
};
presentAlert({
header: "Rename chat room?",
Expand All @@ -123,7 +131,7 @@ export default function ChatWindow(props: Props) {
],
inputs: [
{
placeholder: props.selectedChannel?.name,
placeholder: props.selectedChannel?.display_name,
name: "newChannelName",
},
],
Expand All @@ -134,42 +142,48 @@ export default function ChatWindow(props: Props) {
return (
<div className="tw-relative tw-h-full tw-flex tw-flex-col">
<div className="tw-shrink-0 w-full tw-flex tw-px-2 tw-gap-1 tw-overflow-y-auto tw-bg-[#f4f1f9]">
{props.channels?.map((cr, i) => {
{chainChannels.map((cr, i) => {
const initials = cr.display_name
.split(" ")
.map((word) => word[0])
.join("");
const isSelected = cr.id === props.selectedChannel?.id;
return (
<div>
{isSelected ? (
<button
className="tw-p-2 tw-flex tw-flex-col tw-items-center tw-bg-light"
key={cr.id}
{...longPressChannel(isSelected)}
>
<div className="tw-font-bold tw-w-12 tw-h-12 tw-rounded-full tw-bg-purple-shade tw-flex tw-items-center tw-justify-center tw-ring tw-ring-transparent group-hover:tw-ring-purple tw-transition-colors">
{initials}
</div>
<div className="tw-text-xs tw-text-center tw-truncate tw-max-w-[3.5rem] tw-font-bold">
{cr.display_name}
</div>
</button>
) : (
<button
className="tw-p-2 tw-flex tw-flex-col tw-items-center tw-group"
key={cr.id}
onClick={() => props.onSelectChannel(cr)}
>
<div className="tw-font-bold tw-w-12 tw-h-12 tw-rounded-full tw-bg-purple-shade tw-flex tw-items-center tw-justify-center tw-ring tw-ring-transparent group-hover:tw-ring-purple tw-transition-colors">
{initials}
</div>
<div className="tw-text-xs tw-text-center tw-truncate tw-max-w-[3.5rem]">
{cr.display_name}
</div>
</button>
<button
className={"tw-p-2 tw-flex tw-flex-col tw-items-center tw-group".concat(
isSelected ? " tw-bg-light" : "",
)}
</div>
key={cr.id}
{...(isSelected
? isChainAdmin
? longPressChannel(isSelected)
: {}
: {
onClick: () => props.onSelectChannel(cr),
})}
>
<div
className={"tw-relative tw-font-bold tw-w-12 tw-h-12 tw-rounded-full tw-bg-purple-shade tw-flex tw-items-center tw-justify-center tw-ring group-hover:tw-ring-purple tw-transition-colors".concat(
isSelected
? " tw-ring-purple tw-ring-1"
: " tw-ring-transparent",
)}
>
<span>{initials}</span>
{isSelected && isChainAdmin ? (
<div className="tw-absolute tw-bottom-0 tw-right-0 tw-bg-light-shade tw-z-10 tw-w-6 tw-h-6 tw-rounded-full -tw-m-1 tw-flex tw-justify-center tw-items-center">
<IonIcon icon={buildFilled} size="xs" color="dark" />
</div>
) : null}
</div>
<div
className={"tw-text-xs tw-text-center tw-truncate tw-max-w-[3.5rem]".concat(
isSelected ? " tw-font-bold" : "",
)}
>
{cr.display_name}
</div>
</button>
);
})}
{isChainAdmin ? (
Expand Down
19 changes: 15 additions & 4 deletions app/src/pages/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ type WebSocketMessagePosted = WebSocketMessage<{
// This follows the controller / view component pattern
export default function Chat() {
const { t } = useTranslation();
const { chain, mmData, setMmData, isThemeDefault } = useContext(StoreContext);
const { chain, setChain, mmData, setMmData, isThemeDefault } =
useContext(StoreContext);

const [mmWsClient, setMmWsClient] = useState<WebSocketClient | null>(null);
const [channels, setChannels] = useState<Channel[]>([]);
Expand Down Expand Up @@ -163,25 +164,35 @@ export default function Chat() {
...(chain.chat_room_ids || []),
id,
]);
const _channel = _channels.find((c) => c.id == id) || null;

setChannels(_channels);
const _channel = _channels.at(-1) || null;
setSelectedChannel(_channel);
// update chain object from server to update chain.room_ids value
await setChain(chain.uid, authUser);
if (!_channel) return;
reqPostList(mmClient, _channel, "");
} catch (err) {
console.error(err);
}
}

async function onRenameChannel(name: string) {
async function onRenameChannel(channel: Channel, name: string) {
if (!chain || !mmClient) {
if (!chain) console.error("chain not found");
if (!mmClient) console.error("mmClient not found");
return;
}
try {
console.info("Updating channel name", name);
// Update channel name
channel.display_name = name;
await mmClient.updateChannel(channel);
const _channels = await getChannels(
mmClient,
mmData,
chain?.chat_room_ids || [],
);
setChannels(_channels);
} catch (err) {
console.error(err);
}
Expand Down
26 changes: 26 additions & 0 deletions server/internal/controllers/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,32 @@ func ChatCreateChannel(c *gin.Context) {
})
}

func ChatDeleteChannel(c *gin.Context) {
db := getDB(c)

var body struct {
ChainUID string `json:"chain_uid" binding:"required,uuid"`
ChannelID string `json:"channel_id" binding:"required"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.AbortWithError(http.StatusBadRequest, err)
return
}

ok, _, chain := auth.Authenticate(c, db, auth.AuthState3AdminChainUser, body.ChainUID)
if !ok {
return
}

err := services.ChatDeleteChannel(db, c.Request.Context(), chain, body.ChannelID)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}

c.Status(http.StatusOK)
}

func ChatJoinChannels(c *gin.Context) {
db := getDB(c)

Expand Down
16 changes: 16 additions & 0 deletions server/internal/services/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,22 @@ func ChatCreateChannel(db *gorm.DB, ctx context.Context, chain *models.Chain, mm
return newChannel, nil
}

func ChatDeleteChannel(db *gorm.DB, ctx context.Context, chain *models.Chain, mmChannelID string) error {
_, err := app.ChatClient.DeleteChannel(ctx, mmChannelID)
if err != nil {
return err
}

chain.ChatRoomIDs = lo.Filter(chain.ChatRoomIDs, func(roomID string, _ int) bool {
return roomID != mmChannelID
})
err = chain.SaveChannelIDs(db)
if err != nil {
return err
}
return nil
}

func chatChannelAddUser(ctx context.Context, mmChannelId string, mmUserId string, setRoleAdmin bool) error {
member, _, err := app.ChatClient.AddChannelMember(ctx, mmChannelId, mmUserId)
if err != nil {
Expand Down

0 comments on commit 75303e5

Please sign in to comment.