@extrawest/firebase-chat-list-component
Version:
React Firebase Chat List Component
238 lines (237 loc) • 9.76 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = __importStar(require("react"));
const styles_1 = require("@material-ui/core/styles");
const core_1 = require("@material-ui/core");
const react_final_form_hooks_1 = require("react-final-form-hooks");
const colorManipulator_1 = require("@material-ui/core/styles/colorManipulator");
const ios_inner_height_1 = __importDefault(require("ios-inner-height"));
const react_device_detect_1 = require("react-device-detect");
const Send_1 = __importDefault(require("@material-ui/icons/Send"));
const validator_1 = require("../../utils/validator");
const ChatScrollableList_1 = __importDefault(require("../ChatScrollableList"));
const ChatSkeleton_1 = __importDefault(require("../ChatSkeleton"));
const useIsResponsive_1 = require("../../hooks/useIsResponsive");
const useWindowSize_1 = require("../../hooks/useWindowSize");
const useStyles = styles_1.makeStyles((theme) => ({
chatSection: {
width: "100%",
height: "60vh",
maxHeight: 690,
maxWidth: 410,
borderRadius: 10,
borderTopRightRadius: 0,
borderTopLeftRadius: 0,
boxShadow: "none",
"& > div": {
maxHeight: 545,
position: "relative",
},
},
chatSectionModal: {
height: "calc(100% - 120px)",
marginBottom: 0,
background: theme.palette.common.white,
[theme.breakpoints.down("sm")]: {
height: "calc(100% - 110px)",
},
},
chatWrapper: {
maxWidth: 410,
position: "relative",
background: theme.palette.common.white,
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
},
messageArea: {
width: "100%",
overflowY: "auto",
margin: 0,
padding: "20px 10px",
"& .MuiListItem-root": {
position: "relative",
display: "flex",
flexWrap: "wrap",
flexDirection: "column",
"&.chatbox-sent": {
"& > .message-body": {
borderTopRightRadius: 0,
borderTopLeftRadius: 10,
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
backgroundColor: colorManipulator_1.fade("#29C797", 0.12),
marginLeft: "auto",
"& .MuiTypography-root": {
wordBreak: "break-word"
},
"&:after": {
width: 0,
height: 0,
content: "''",
top: 0,
right: -15,
position: "absolute",
borderStyle: "solid",
borderWidth: "15px 15px 0 0",
borderColor: `${colorManipulator_1.fade("#29C797", 0.12)} transparent transparent transparent`,
},
},
"& > .message-info": {
marginLeft: "auto",
},
},
"&.chatbox-received": {
"& > .message-body": {
borderTopLeftRadius: 0,
borderTopRightRadius: 10,
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
background: colorManipulator_1.fade(theme.palette.grey[900], 0.06),
marginRight: "auto",
"& .MuiTypography-root": {
wordBreak: "break-word"
},
"&:before": {
width: 0,
height: 0,
content: "''",
top: 0,
left: -15,
position: "absolute",
borderStyle: "solid",
borderWidth: "0 15px 15px 0",
borderColor: `transparent ${colorManipulator_1.fade(theme.palette.grey[900], 0.06)} transparent transparent`,
},
},
"& > .message-info": {
marginRight: "auto",
},
},
},
},
actions: {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
minHeight: 60,
boxShadow: "0px -5px 9px rgba(0, 0, 0, 0.12)",
padding: "0 12px",
position: "absolute",
bottom: 0,
left: 0,
right: 0,
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
background: theme.palette.common.white,
"& form": {
width: "100%",
},
[theme.breakpoints.down("sm")]: {
paddingTop: 0,
paddingBottom: 0,
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
},
},
sendMessageButton: {
padding: 0,
background: theme.palette.primary.main,
color: theme.palette.secondary.main,
width: 36,
height: 36,
},
chatFieldBox: {
marginBottom: 0,
"& .MuiOutlinedInput-notchedOutline": {
border: "none",
},
},
shareLocation: {
padding: 0,
},
form: {
padding: 0,
display: "flex",
justifyContent: "space-between",
alignItems: "flex-end",
},
actionsButton: {
height: 60,
width: 60,
display: "flex",
justifyContent: "center",
alignItems: "center",
},
}));
const ChatBox = ({ chatMessagePlaceholder, loading, handleSubmitMessage, messages, currentAuthUid }) => {
var _a;
const formActionsRef = react_1.useRef(null);
const classes = useStyles();
const isMobile = useIsResponsive_1.useIsResponsive("sm");
const onSubmit = (values, form) => {
handleSubmitMessage(values, form);
};
const validate = (values) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const errors = validator_1.validateRequire(values, ["message"], "");
return errors;
};
const { form, handleSubmit } = react_final_form_hooks_1.useForm({
onSubmit,
validate,
});
const message = react_final_form_hooks_1.useField("message", form);
const [, windowHeight] = useWindowSize_1.useWindowSize();
const height = isMobile ? react_device_detect_1.isIOS ? `${ios_inner_height_1.default()}px - 125px` : `${windowHeight}px - 115px` : "100%";
//dynamic height for chat messages and chat form
const style = {
height: `calc( ${height} - ${(_a = formActionsRef === null || formActionsRef === void 0 ? void 0 : formActionsRef.current) === null || _a === void 0 ? void 0 : _a.clientHeight}px)`,
};
const ref = react_1.useRef(null);
const scrollToBottom = () => {
var _a;
ref && ((_a = ref === null || ref === void 0 ? void 0 : ref.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ behavior: "smooth" }));
};
const hanldeSubmitByKeyPress = (event) => {
if ((event.ctrlKey || event.metaKey) &&
(event.keyCode === 13 || event.keyCode === 10)) {
handleSubmit();
}
};
react_1.useEffect(() => {
scrollToBottom();
}, []);
const allowedProps = { ref: formActionsRef };
return (react_1.default.createElement(core_1.Grid, { container: true },
react_1.default.createElement(core_1.Grid, { item: true, xs: 12, className: classes.chatWrapper, ref: ref },
loading ? (react_1.default.createElement(ChatSkeleton_1.default, null)) : (react_1.default.createElement(ChatScrollableList_1.default, { messages: messages, currentAuthId: currentAuthUid, className: classes.messageArea, style: style })),
react_1.default.createElement(core_1.Box, Object.assign({ className: classes.actions }, allowedProps),
react_1.default.createElement("form", { onSubmit: handleSubmit, className: classes.form },
react_1.default.createElement(core_1.TextField, Object.assign({}, message.input, { variant: "outlined", id: "chat-message", placeholder: chatMessagePlaceholder, multiline: true, rowsMax: 4, fullWidth: true, className: classes.chatFieldBox, onKeyUp: hanldeSubmitByKeyPress })),
react_1.default.createElement(core_1.Box, { className: classes.actionsButton },
react_1.default.createElement(core_1.IconButton, { type: "submit", className: classes.sendMessageButton },
react_1.default.createElement(Send_1.default, null))))))));
};
exports.default = ChatBox;