@mui/material#PaletteColor TypeScript Examples
The following examples show how to use
@mui/material#PaletteColor.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Message.tsx From airmessage-web with Apache License 2.0 | 4 votes |
export default function Message(props: Props) {
//State
const [attachmentDataArray, setAttachmentDataArray] = useState<FileDownloadResult[]>([]);
const [dialogOpen, setDialogOpen] = useState<"error" | "rawError" | undefined>(undefined);
function closeDialog() {
setDialogOpen(undefined);
}
function openDialogError() {
setDialogOpen("error");
}
function openDialogRawError() {
setDialogOpen("rawError");
}
function copyRawErrorAndClose() {
navigator.clipboard.writeText(props.message.error!.detail!);
closeDialog();
}
//Getting the message information
const isOutgoing = props.message.sender === undefined;
const displayAvatar = !isOutgoing && !props.flow.anchorTop;
const displaySender = props.isGroupChat && displayAvatar;
const messageConfirmed = props.message.status !== MessageStatusCode.Unconfirmed;
//Building the message style
const theme = useTheme();
let colorPalette: PaletteColor;
if(isOutgoing) {
if(props.service === appleServiceAppleMessage) colorPalette = theme.palette.messageOutgoing;
else colorPalette = theme.palette.messageOutgoingTextMessage;
} else {
colorPalette = theme.palette.messageIncoming;
}
const messagePartPropsBase: Partial<MessagePartProps> = {
alignSelf: isOutgoing ? "flex-end" : "flex-start",
color: colorPalette.contrastText,
backgroundColor: colorPalette.main,
opacity: messageConfirmed ? opacityConfirmed : opacityUnconfirmed
};
//Splitting the modifiers for each message part
const stickerGroups = props.message.stickers.reduce((accumulator: {[index: number]: StickerItem[]}, item: StickerItem) => {
if(accumulator[item.messageIndex]) accumulator[item.messageIndex].push(item);
else accumulator[item.messageIndex] = [item];
return accumulator;
}, {});
const tapbackGroups = props.message.tapbacks.reduce((accumulator: {[index: number]: TapbackItem[]}, item: TapbackItem) => {
if(accumulator[item.messageIndex]) accumulator[item.messageIndex].push(item);
else accumulator[item.messageIndex] = [item];
return accumulator;
}, {});
//Adding the message text
const components: React.ReactNode[] = [];
if(props.message.text) {
const partProps: MessagePartProps = {
...messagePartPropsBase,
borderRadius: getBorderRadius(props.flow.anchorTop, props.flow.anchorBottom || props.message.attachments.length > 0, isOutgoing),
marginTop: 0
} as MessagePartProps;
const component = <MessageBubble key="messagetext" text={props.message.text!} index={0} partProps={partProps} stickers={stickerGroups[0]} tapbacks={tapbackGroups[0]} />;
components.push(component);
}
function onAttachmentData(attachmentIndex: number, shouldDownload: boolean, result: FileDownloadResult) {
if(shouldDownload) {
//Downloading the file
const attachment = props.message.attachments[attachmentIndex];
downloadArrayBuffer(result.data, result.downloadType ?? attachment.type, result.downloadName ?? attachment.name);
} else {
//Updating the data
const newArray = [...attachmentDataArray];
newArray[attachmentIndex] = result;
setAttachmentDataArray(newArray);
}
}
function downloadData(attachmentIndex: number, data: ArrayBuffer | Blob) {
const attachment = props.message.attachments[attachmentIndex];
if(data instanceof ArrayBuffer) {
downloadArrayBuffer(data, attachment.type, attachment.name);
} else {
downloadBlob(data, attachment.type, attachment.name);
}
}
/**
* Computes the file data to display to the user
*/
const getComputedFileData = useCallback((attachmentIndex: number): FileDisplayResult => {
const attachment = props.message.attachments[attachmentIndex];
const downloadData = attachmentDataArray[attachmentIndex];
if(downloadData === undefined) {
return {
data: attachment.data,
name: attachment.name,
type: attachment.type
};
} else return {
data: downloadData.data,
name: downloadData.downloadName ?? attachment.name,
type: downloadData.downloadType ?? attachment.type
};
}, [props.message.attachments, attachmentDataArray]);
//Adding the attachments
for(let i = 0; i < props.message.attachments.length; i++) {
const index = props.message.text ? i + 1 : i;
const attachment = props.message.attachments[i];
const partProps: MessagePartProps = {
...messagePartPropsBase,
borderRadius: getBorderRadius(props.flow.anchorTop || index > 0, props.flow.anchorBottom || i + 1 < props.message.attachments.length, isOutgoing),
marginTop: index > 0 ? marginLinked : undefined
} as MessagePartProps;
//Checking if the attachment has data
const attachmentData = getComputedFileData(i);
if(attachmentData.data !== undefined && isAttachmentPreviewable(attachmentData.type)) {
//Custom background color
const imagePartProps = {
...partProps,
backgroundColor: theme.palette.background.sidebar,
};
if(attachmentData.type.startsWith("image/")) {
components.push(<MessageAttachmentImage key={attachment.guid ?? attachment.localID} data={attachmentData.data} name={attachmentData.name} type={attachmentData.type} partProps={imagePartProps} stickers={stickerGroups[index]} tapbacks={tapbackGroups[index]} />);
}
} else {
//Adding a generic download attachment
components.push(<MessageAttachmentDownloadable
key={attachment.guid ?? attachment.localID}
data={attachmentData.data}
name={attachmentData.name}
type={attachmentData.type}
size={attachment.size}
guid={attachment.guid!}
onDataAvailable={(data) => onAttachmentData(i, !isAttachmentPreviewable(data.downloadType ?? attachment.type), data)}
onDataClicked={(data) => downloadData(i, data)}
partProps={partProps}
stickers={stickerGroups[index]}
tapbacks={tapbackGroups[index]} />);
}
}
const messageStyle: CSSProperties = {
marginTop: props.flow.anchorTop ? marginLinked : marginUnlinked,
};
//Initializing state
const [personData, setPersonData] = useState<PersonData | undefined>();
useEffect(() => {
if(!props.message.sender) return;
//Requesting contact data
findPerson(props.message.sender).then(setPersonData, console.warn);
}, [props.message.sender]);
//Building and returning the component
return (
<div className={styles.message} style={messageStyle}>
{props.flow.showDivider && <Typography className={styles.separator} variant="body2" color="textSecondary">{getTimeDivider(props.message.date)}</Typography>}
{displaySender && <Typography className={styles.labelSender} variant="caption" color="textSecondary">{personData?.name ?? props.message.sender}</Typography>}
<div className={styles.messageSplit}>
{<Avatar className={styles.avatar} src={personData?.avatar} style={displayAvatar ? {visibility: "visible", backgroundColor: colorFromContact(props.message.sender ?? "")} : {visibility: "hidden"}} />}
<div className={styles.messageParts}>
{components}
</div>
{props.message.progress && !props.message.error && <CircularProgress className={styles.messageProgress} size={24} variant={props.message.progress === -1 ? "indeterminate" : "determinate"} value={props.message.progress} />}
{props.message.error && <IconButton className={styles.messageError} style={{color: theme.palette.error.light}} size="small" onClick={openDialogError}>
<ErrorRounded />
</IconButton>}
<Dialog open={dialogOpen === "error"} onClose={closeDialog}>
<DialogTitle>Your message could not be sent</DialogTitle>
{props.message.error !== undefined && <React.Fragment>
<DialogContent>
<DialogContentText>{messageErrorToUserString(props.message.error!.code)}</DialogContentText>
</DialogContent>
<DialogActions>
{props.message.error!.detail && <Button onClick={openDialogRawError} color="primary">
Error details
</Button>}
<Button onClick={closeDialog} color="primary" autoFocus>
Dismiss
</Button>
</DialogActions>
</React.Fragment>}
</Dialog>
<Dialog open={dialogOpen === "rawError"} onClose={closeDialog}>
<DialogTitle>Error details</DialogTitle>
{props.message.error !== undefined && <React.Fragment>
<DialogContent>
<DialogContentText className={styles.rawErrorText}>{props.message.error.detail!}</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={copyRawErrorAndClose} color="primary">
Copy to clipboard
</Button>
<Button onClick={closeDialog} color="primary" autoFocus>
Dismiss
</Button>
</DialogActions>
</React.Fragment>}
</Dialog>
</div>
{props.showStatus && <Typography className={styles.labelStatus} variant="caption" color="textSecondary">{getStatusString(props.message)}</Typography>}
</div>
);
}