221 lines
6.3 KiB
TypeScript
221 lines
6.3 KiB
TypeScript
import {
|
|
Avatar,
|
|
Box,
|
|
Dialog,
|
|
DialogActions,
|
|
DialogContent,
|
|
DialogTitle,
|
|
Grid2 as Grid,
|
|
IconButton,
|
|
ListItemIcon,
|
|
ListItemText,
|
|
Menu,
|
|
MenuItem,
|
|
Theme,
|
|
Typography
|
|
} from "@mui/material";
|
|
import { MoreVert, Person, Delete as DeleteIcon, } from "@mui/icons-material";
|
|
import moment from "moment-timezone";
|
|
import { useGlobalState, useNoteAPI, useSnackbar } from "providers";
|
|
import React, { useState } from "react";
|
|
import { pond } from "protobuf-ts/pond";
|
|
import { red } from "@mui/material/colors";
|
|
import { makeStyles } from "@mui/styles";
|
|
import CancelSubmit from "common/CancelSubmit";
|
|
import { getThemeType } from "theme/themeType";
|
|
|
|
interface Props {
|
|
index: number;
|
|
chat: pond.Chat;
|
|
attachments?: pond.FileReference[];
|
|
removeNoteMethod: (index: number) => void;
|
|
}
|
|
const useStyles = makeStyles((theme: Theme) => ({
|
|
red: {
|
|
color: red["500"]
|
|
},
|
|
oddGrid: {
|
|
backgroundColor: theme.palette.background.paper,
|
|
padding: theme.spacing(1)
|
|
},
|
|
evenGrid: {
|
|
backgroundColor: getThemeType() === "light" ? theme.palette.background.default : undefined,
|
|
padding: theme.spacing(1)
|
|
},
|
|
userAvatar: {
|
|
width: 36,
|
|
height: 36,
|
|
marginLeft: theme.spacing(1),
|
|
marginRight: theme.spacing(2),
|
|
}
|
|
}))
|
|
|
|
/**
|
|
* Takes in a note and renders it
|
|
* handles deleting of the note
|
|
* @param props Note object
|
|
*/
|
|
export default function ChatMessage(props: Props) {
|
|
const classes = useStyles();
|
|
const [{ user }] = useGlobalState();
|
|
const noteAPI = useNoteAPI();
|
|
const { openSnack } = useSnackbar();
|
|
const [dialog, setDialog] = useState(false);
|
|
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
|
|
|
const avatar = props.chat.profile?.avatar
|
|
const name = props.chat.profile?.name
|
|
const timestamp = props.chat.note?.settings?.timestamp ? props.chat.note?.settings?.timestamp : undefined
|
|
|
|
const generatePermissions = () => {
|
|
let perms: pond.Permission[] = []
|
|
if (Array.isArray(props.chat.permissions)) {
|
|
perms = props.chat.permissions.map((perm: unknown) => {
|
|
const mappedPerm = pond.Permission[perm as keyof typeof pond.Permission];
|
|
return mappedPerm; // Return null for invalid keys
|
|
}).filter(Boolean); // Optionally filter out any null values
|
|
if (user.id() === props.chat.profile?.id) {
|
|
perms = [
|
|
pond.Permission.PERMISSION_READ,
|
|
pond.Permission.PERMISSION_WRITE
|
|
]
|
|
}
|
|
} else {
|
|
// console.error("data.permissions is not an array or does not exist");
|
|
if (user.id() === props.chat.profile?.id) {
|
|
perms = [
|
|
pond.Permission.PERMISSION_READ,
|
|
pond.Permission.PERMISSION_WRITE
|
|
]
|
|
} else {
|
|
perms = [];
|
|
}
|
|
}
|
|
return perms
|
|
}
|
|
const permissions = generatePermissions()
|
|
|
|
const deleteMessage = () => {
|
|
if (!props.chat?.note?.settings) return
|
|
setAnchorEl(null);
|
|
noteAPI
|
|
.removeNote(props.chat.note.settings.key)
|
|
.then(_resp => {
|
|
openSnack("Message Deleted");
|
|
props.removeNoteMethod(props.index);
|
|
})
|
|
.catch(_err => {
|
|
openSnack("Failed to delete Message");
|
|
});
|
|
closeDialog();
|
|
};
|
|
|
|
const openDialog = () => {
|
|
setDialog(true);
|
|
};
|
|
|
|
const closeDialog = () => {
|
|
setDialog(false);
|
|
};
|
|
|
|
const messageMenu = () => {
|
|
return (
|
|
<Menu
|
|
id="groupMenu"
|
|
anchorEl={anchorEl}
|
|
open={Boolean(anchorEl)}
|
|
onClose={() => setAnchorEl(null)}
|
|
keepMounted
|
|
>
|
|
<MenuItem dense onClick={openDialog}>
|
|
<ListItemIcon>
|
|
<DeleteIcon className={classes.red} />
|
|
</ListItemIcon>
|
|
<ListItemText>Delete Message</ListItemText>
|
|
</MenuItem>
|
|
</Menu>
|
|
);
|
|
};
|
|
|
|
const deleteDialog = () => {
|
|
return (
|
|
<Dialog open={dialog} onClose={closeDialog}>
|
|
<DialogTitle>Delete Message?</DialogTitle>
|
|
<DialogContent>Are you sure you wish to delete this message</DialogContent>
|
|
<DialogActions>
|
|
<CancelSubmit
|
|
onCancel={closeDialog}
|
|
onSubmit={deleteMessage}
|
|
submitText="Delete"
|
|
/>
|
|
</DialogActions>
|
|
</Dialog>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<Box style={{ width: "100%" }}>
|
|
<Grid
|
|
wrap="nowrap"
|
|
container
|
|
direction="row"
|
|
alignItems="center"
|
|
className={props.index % 2 === 0 ? classes.oddGrid : classes.evenGrid}>
|
|
<Grid>
|
|
{avatar ? (
|
|
<Avatar alt={name} src={avatar} className={classes.userAvatar}>
|
|
{!avatar && name}
|
|
</Avatar>
|
|
) : (
|
|
<Avatar alt={name} className={classes.userAvatar}>
|
|
<Person />
|
|
</Avatar>
|
|
)}
|
|
</Grid>
|
|
<Grid container direction="column" justifyContent="space-between" size={{ xs:10 }} >
|
|
<Grid container direction="row" alignContent={"center"} spacing={1} >
|
|
<Grid>
|
|
<Typography color="textPrimary">
|
|
{name}
|
|
</Typography>
|
|
</Grid>
|
|
<Grid justifyContent={"center"}>
|
|
<Typography variant="caption" color="textSecondary">
|
|
{moment.unix(timestamp ? timestamp/1000: 0)
|
|
.tz(user.settings.timezone ? user.settings.timezone : "Canada/Central")
|
|
.format("MMMM Do YYYY, h:mm:ss a")}
|
|
</Typography>
|
|
</Grid>
|
|
</Grid>
|
|
<Grid size={{ xs: 12 }}>
|
|
<Typography variant="body2" whiteSpace={"pre-line"}>
|
|
{props.chat.note?.settings?.content}
|
|
</Typography>
|
|
{/*load files and display attached images below the message */}
|
|
</Grid>
|
|
</Grid>
|
|
<Grid padding={1}>
|
|
{/* delete button */}
|
|
{permissions.includes(pond.Permission.PERMISSION_WRITE) ? (
|
|
<IconButton
|
|
onClick={(event: React.MouseEvent<HTMLButtonElement>) =>
|
|
setAnchorEl(event.currentTarget)
|
|
}>
|
|
<MoreVert />
|
|
</IconButton>
|
|
) : (
|
|
// <span>
|
|
// <Tooltip title="No permissions to edit or delete" disableInteractive>
|
|
<IconButton disabled>
|
|
<MoreVert />
|
|
</IconButton>
|
|
// </Tooltip>
|
|
// </span>
|
|
)}
|
|
</Grid>
|
|
</Grid>
|
|
{deleteDialog()}
|
|
{messageMenu()}
|
|
</Box>
|
|
);
|
|
}
|