Browse Source

修复ios h5录音失败的bug

xsx 1 year ago
parent
commit
ba439f28b3

+ 6 - 0
im-uniapp/App.vue

@@ -378,6 +378,12 @@ export default {
 		// 登录状态校验
 		let loginInfo = uni.getStorageSync("loginInfo")
 		this.refreshToken(loginInfo).then(() => {
+			// #ifdef H5
+			// 跳转到聊天页
+			uni.switchTab({
+				url: "/pages/chat/chat"
+			})
+			// #endif			
 			// 初始化
 			this.init();
 			this.closeSplashscreen(0);

+ 4 - 4
im-uniapp/common/recorder-app.js

@@ -3,6 +3,9 @@ import UNI_APP from '@/.env.js';
 const rc = uni.getRecorderManager();
 // 录音开始时间
 let startTime = null;
+let checkIsEnable = ()=>{
+	return true;
+}
 
 let start = () => {
 	return new Promise((resolve, reject) => {
@@ -20,10 +23,6 @@ let start = () => {
 	})
 }
 
-let pause = () => {
-	rc.stop();
-}
-
 let close = () => {
 	rc.stop();
 }
@@ -61,6 +60,7 @@ let upload = () => {
 }
 
 export {
+	checkIsEnable,
 	start,
 	close,
 	upload

+ 39 - 13
im-uniapp/common/recorder-h5.js

@@ -4,26 +4,39 @@ let rc = null;
 let duration = 0;
 let chunks = [];
 let stream = null;
+let startTime = null; 
+let checkIsEnable = () => {
+	if (origin.indexOf('https') === -1 && origin.indexOf('localhost') === -1 &&
+		origin.indexOf('127.0.0.1') === -1) {
+		uni.showToast({
+			title: '请在https环境中使用录音功能',
+			icon: 'error'
+		})
+		return false;
+	}
+	if (!navigator.mediaDevices || !window.MediaRecorder) {
+		uni.showToast({
+			title: '当前浏览器不支持录音',
+			icon: 'error'
+		})
+		return false;
+	}
+	return true;
+}
+
 let start = () => {
 	return navigator.mediaDevices.getUserMedia({ audio: true }).then(audioStream => {
-		const startTime = new Date().getTime();
+		console.log("start record")
+		startTime = new Date().getTime();
 		chunks = [];
 		stream = audioStream;
 		rc = new MediaRecorder(stream)
-		rc.ondataavailable = (e) => {
-			console.log("ondataavailable")
-			chunks.push(e.data)
-		}
-		rc.onstop = () => {
-			duration = (new Date().getTime() - startTime) / 1000;
-			console.log("时长:", duration)
-		}
 		rc.start()
 	})
-
 }
 
 let close = () => {
+	console.log("stream:", stream)
 	stream.getTracks().forEach((track) => {
 		track.stop()
 	})
@@ -33,11 +46,23 @@ let close = () => {
 
 let upload = () => {
 	return new Promise((resolve, reject) => {
-		setTimeout(() => {
+		rc.ondataavailable = (e) => {
+			console.log("ondataavailable:",e.data)
+			console.log("size:",e.data.size)
+			console.log("type:",e.data.type)
+			chunks.push(e.data)
+		}
+		rc.onstop = () => {
+			if(!chunks[0].size){
+				chunks = [];
+				return; 
+			}
+			duration = (new Date().getTime() - startTime) / 1000;
+			console.log("时长:", duration)
+			console.log("上传,chunks:", chunks.length)
 			const newbolb = new Blob(chunks, { 'type': 'audio/mpeg' });
 			const name = new Date().getDate() + '.mp3';
 			const file = new File([newbolb], name)
-			console.log("upload")
 			uni.uploadFile({
 				url: UNI_APP.BASE_URL + '/file/upload',
 				header: {
@@ -62,11 +87,12 @@ let upload = () => {
 					reject(e);
 				}
 			})
-		}, 100)
+		}
 	})
 }
 
 export {
+	checkIsEnable,
 	start,
 	close,
 	upload

+ 19 - 6
im-uniapp/components/chat-message-item/chat-message-item.vue

@@ -17,7 +17,7 @@
 				<view class="chat-msg-bottom">
 					<view v-if="msgInfo.type == $enums.MESSAGE_TYPE.TEXT">
 						<long-press-menu :items="menuItems" @select="onSelectMenu">
-							<rich-text class="chat-msg-text" :nodes="$emo.transform(msgInfo.content, 'emoji-normal')"></rich-text>
+							<rich-text class="chat-msg-text" :nodes="$emo.transform(msgInfo.content,'emoji-normal')"></rich-text>
 						</long-press-menu>
 					</view>
 					<view class="chat-msg-image" v-if="msgInfo.type == $enums.MESSAGE_TYPE.IMAGE">
@@ -65,12 +65,12 @@
 						</view>
 					</long-press-menu>
 					<view class="chat-msg-status" v-if="!isAction">
-						<text class="chat-readed" v-show="msgInfo.selfSend && !msgInfo.groupId
+						<text class="chat-readed" v-if="msgInfo.selfSend && !msgInfo.groupId
 							&& msgInfo.status == $enums.MESSAGE_STATUS.READED">已读</text>
-						<text class="chat-unread" v-show="msgInfo.selfSend && !msgInfo.groupId
+						<text class="chat-unread" v-if="msgInfo.selfSend && !msgInfo.groupId
 							&& msgInfo.status != $enums.MESSAGE_STATUS.READED">未读</text>
 					</view>
-					<view class="chat-receipt" v-show="msgInfo.receipt" @click="onShowReadedBox">
+					<view class="chat-receipt" v-if="msgInfo.receipt" @click="onShowReadedBox">
 						<text v-if="msgInfo.receiptOk" class="tool-icon iconfont icon-ok"></text>
 						<text v-else>{{ msgInfo.readedCount }}人已读</text>
 					</view>
@@ -125,14 +125,16 @@ export default {
 				this.innerAudioContext = uni.createInnerAudioContext();
 				let url = JSON.parse(this.msgInfo.content).url;
 				this.innerAudioContext.src = url;
-				console.log(url);
 				this.innerAudioContext.onEnded((e) => {
 					console.log('停止')
 					this.audioPlayState = "STOP"
+					this.emit();
 				})
 				this.innerAudioContext.onError((e) => {
+					this.audioPlayState = "STOP"
 					console.log("播放音频出错");
 					console.log(e)
+					this.emit();
 				});
 			}
 			if (this.audioPlayState == 'STOP') {
@@ -145,6 +147,7 @@ export default {
 				this.innerAudioContext.play();
 				this.audioPlayState = "PLAYING"
 			}
+			this.emit();
 		},
 		onSelectMenu(item) {
 			this.$emit(item.key.toLowerCase(), this.msgInfo);
@@ -158,6 +161,16 @@ export default {
 		},
 		onShowReadedBox() {
 			this.$refs.chatGroupReaded.open();
+		},
+		emit(){
+			this.$emit("audioStateChange",this.audioPlayState,this.msgInfo);
+		},
+		stopPlayAudio(){
+			if (this.innerAudioContext) {
+				this.innerAudioContext.stop();
+				this.innerAudioContext = null;
+				this.audioPlayState = "STOP"
+			}
 		}
 	},
 	computed: {
@@ -262,6 +275,7 @@ export default {
 			.chat-msg-bottom {
 				display: inline-block;
 				padding-right: 80rpx;
+				margin-top: 5rpx;
 
 				.chat-msg-text {
 					position: relative;
@@ -289,7 +303,6 @@ export default {
 						border-color: $im-bg transparent transparent;
 						overflow: hidden;
 						border-width: 18rpx;
-						//box-shadow: $im-box-shadow-dark;
 					}
 				}
 

+ 15 - 8
im-uniapp/components/chat-record/chat-record.vue

@@ -50,12 +50,14 @@ export default {
 			/* 用户第一次使用语音会唤醒录音权限请求,此时会导致@touchend失效,
 				一直处于录音状态,这里允许用户再次点击发送语音并结束录音 */
 			if (this.recording) {
-				this.onEndRecord();
 				return;
 			}
 			console.log("开始录音")
 			this.moveToCancel = false;
 			this.initRecordBar();
+			if(!this.$rc.checkIsEnable()){
+				return;
+			}
 			this.$rc.start().then(() => {
 				this.recording = true;
 				console.log("开始录音成功")
@@ -70,9 +72,12 @@ export default {
 			});
 		},
 		onEndRecord() {
+			if(!this.recording){
+				return;
+			}
 			this.recording = false;
 			// 停止计时
-			this.StopTimer();
+			this.stopTimer();
 			// 停止录音
 			this.$rc.close();
 			// 触屏位置是否移动到了取消区域
@@ -80,8 +85,8 @@ export default {
 				console.log("录音取消")
 				return;
 			}
-			// 小于1秒不发送
-			if (this.druation == 0) {
+			// 大于1秒才发送
+			if (this.druation <= 1) {
 				uni.showToast({
 					title: "说话时间太短",
 					icon: 'none'
@@ -95,13 +100,11 @@ export default {
 					title: e,
 					icon: 'none'
 				})
-			}).finally(() => {
-				this.$rc.close();
 			})
 		},
 		startTimer() {
 			this.druation = 0;
-			this.StopTimer();
+			this.stopTimer();
 			this.rcTimer = setInterval(() => {
 				this.druation++;
 				// 大于60s,直接结束
@@ -110,7 +113,7 @@ export default {
 				}
 			}, 1000)
 		},
-		StopTimer() {
+		stopTimer() {
 			this.rcTimer && clearInterval(this.rcTimer);
 			this.rcTimer = null;
 		},
@@ -134,6 +137,10 @@ export default {
 			}
 			return `录音时长:${this.druation}s`;
 		}
+	},
+	unmounted() {
+		this.stopTimer();
+		this.recording = false;
 	}
 
 }

+ 142 - 75
im-uniapp/pages/chat/chat-box.vue

@@ -6,10 +6,11 @@
 				<scroll-view class="scroll-box" scroll-y="true" upper-threshold="200" @scrolltoupper="onScrollToTop"
 					:scroll-into-view="'chat-item-' + scrollMsgIdx">
 					<view v-if="chat" v-for="(msgInfo, idx) in chat.messages" :key="idx">
-						<chat-message-item v-if="idx >= showMinIdx" :headImage="headImage(msgInfo)"
-							@call="onRtCall(msgInfo)" :showName="showName(msgInfo)" @recall="onRecallMessage"
-							@copy="onCopyMessage" @delete="onDeleteMessage" @longPressHead="onLongPressHead(msgInfo)"
-							@download="onDownloadFile" :id="'chat-item-' + idx" :msgInfo="msgInfo"
+						<chat-message-item :ref="'message'+msgInfo.id" v-if="idx >= showMinIdx"
+							:headImage="headImage(msgInfo)" @call="onRtCall(msgInfo)" :showName="showName(msgInfo)"
+							@recall="onRecallMessage" @delete="onDeleteMessage" @copy="onCopyMessage"
+							@longPressHead="onLongPressHead(msgInfo)" @download="onDownloadFile"
+							@audioStateChange="onAudioStateChange" :id="'chat-item-' + idx" :msgInfo="msgInfo"
 							:groupMembers="groupMembers">
 						</chat-message-item>
 					</view>
@@ -19,7 +20,7 @@
 				<view class="iconfont icon-at">:&nbsp;</view>
 				<scroll-view v-if="atUserIds.length > 0" class="chat-at-scroll-box" scroll-x="true" scroll-left="120">
 					<view class="chat-at-items">
-						<view v-for="m in atUserItems" class="chat-at-item">
+						<view v-for="m in atUserItems" class="chat-at-item" :key="m.userId">
 							<head-image :name="m.showNickName" :url="m.headImage" size="minier"></head-image>
 						</view>
 					</view>
@@ -31,24 +32,26 @@
 				<chat-record v-if="showRecord" class="chat-record" @send="onSendRecord"></chat-record>
 				<view v-else class="send-text">
 					<editor id="editor" class="send-text-area" :placeholder="isReceipt ? '[回执消息]' : ''"
-						:read-only="isReadOnly" @focus="onEditorFocus" @blur="onEditorBlur" @ready="onEditorReady"
-						@input="onTextInput">
+						:read-only="isReadOnly" @focus="onEditorFocus" @blur="onEditorBlur" @ready="onEditorReady" @input="onTextInput">
 					</editor>
-					<!-- <textarea class="send-text-area" v-model="sendText" auto-height :show-confirm-bar="false"
-						:placeholder="isReceipt ? '[回执消息]' : ''" :adjust-position="false" @confirm="sendTextMessage()"
-						@keyboardheightchange="onKeyboardheightchange" @input="onTextInput" confirm-type="send"
-						confirm-hold :hold-keyboard="true"></textarea> -->
 				</view>
 				<view v-if="chat && chat.type == 'GROUP'" class="iconfont icon-at" @click="openAtBox()"></view>
 				<view class="iconfont icon-icon_emoji" @click="onShowEmoChatTab()"></view>
 				<view v-if="isEmpty" class="iconfont icon-add" @click="onShowToolsChatTab()">
 				</view>
-				<button v-if="!isEmpty || atUserIds.length > 0" class="btn-send" type="primary"
+				<button v-if="!isEmpty || atUserIds.length" class="btn-send" type="primary"
 					@touchend.prevent="sendTextMessage()" size="mini">发送</button>
 			</view>
 		</view>
 		<view class="chat-tab-bar">
 			<view v-if="chatTabBox == 'tools'" class="chat-tools" :style="{height: keyboardHeight+'px'}">
+				<view class="chat-tools-item">
+					<file-upload ref="fileUpload" :onBefore="onUploadFileBefore" :onSuccess="onUploadFileSuccess"
+						:onError="onUploadFileFail">
+						<view class="tool-icon iconfont icon-folder"></view>
+					</file-upload>
+					<view class="tool-name">文件</view>
+				</view>
 				<view class="chat-tools-item">
 					<image-upload :maxCount="9" sourceType="album" :onBefore="onUploadImageBefore"
 						:onSuccess="onUploadImageSuccess" :onError="onUploadImageFail">
@@ -63,15 +66,6 @@
 					</image-upload>
 					<view class="tool-name">拍摄</view>
 				</view>
-
-				<view class="chat-tools-item">
-					<file-upload ref="fileUpload" :onBefore="onUploadFileBefore" :onSuccess="onUploadFileSuccess"
-						:onError="onUploadFileFail">
-						<view class="tool-icon iconfont icon-folder"></view>
-					</file-upload>
-					<view class="tool-name">文件</view>
-				</view>
-
 				<view class="chat-tools-item" @click="onRecorderInput()">
 					<view class="tool-icon iconfont icon-microphone"></view>
 					<view class="tool-name">语音消息</view>
@@ -131,8 +125,10 @@ export default {
 			scrollMsgIdx: 0, // 滚动条定位为到哪条消息
 			chatTabBox: 'none',
 			showRecord: false,
-			keyboardHeight: 300,
 			chatMainHeight: 0, // 聊天窗口高度
+			keyboardHeight: 290, // 键盘高度
+			windowHeight: 1000, // 窗口高度
+			initHeight: 1000, // h5初始高度
 			atUserIds: [],
 			needScrollToBottom: false, // 需要滚动到底部 
 			showMinIdx: 0, // 下标小于showMinIdx的消息不显示,否则可能很卡
@@ -142,7 +138,8 @@ export default {
 			editorCtx: null, // 编辑器上下文
 			isEmpty: true, // 编辑器是否为空
 			isFocus: false, // 编辑器是否焦点
-			isReadOnly: false // 编辑器是否只读
+			isReadOnly: false, // 编辑器是否只读
+			playingAudio: null // 当前正在播放的录音消息
 		}
 	},
 	methods: {
@@ -265,7 +262,6 @@ export default {
 		sendTextMessage() {
 			this.editorCtx.getContents({
 				success: (e) => {
-
 					// 清空编辑框数据
 					this.editorCtx.clear();
 					this.atUserIds = [];
@@ -275,7 +271,6 @@ export default {
 						this.showBannedTip();
 						return;
 					}
-
 					let sendText = this.isReceipt ? "【回执消息】" : "";
 					e.delta.ops.forEach((op) => {
 						if (op.insert.image) {
@@ -302,7 +297,6 @@ export default {
 					}
 					// 填充对方id
 					this.fillTargetId(msgInfo, this.chat.targetId);
-
 					this.sendMessageRequest(msgInfo).then((m) => {
 						m.selfSend = true;
 						this.chatStore.insertMessage(m, this.chat);
@@ -314,6 +308,7 @@ export default {
 					});
 				}
 			})
+
 		},
 		createAtText() {
 			let atText = "";
@@ -356,7 +351,6 @@ export default {
 			this.$nextTick(() => {
 				this.scrollMsgIdx = idx;
 			});
-
 		},
 		onShowEmoChatTab() {
 			this.showRecord = false;
@@ -538,7 +532,7 @@ export default {
 			uni.setClipboardData({
 				data: msgInfo.content,
 				success: () => {
-					uni.showToast({ title: '已复制', icon: 'none' });
+					uni.showToast({ title: '复制成功' });
 				},
 				fail: () => {
 					uni.showToast({ title: '复制失败', icon: 'none' });
@@ -575,7 +569,7 @@ export default {
 			// 防止滚动条定格在顶部,不能一直往上滚
 			this.scrollToMsgIdx(this.showMinIdx);
 			// #endif
-			// 多展示0条信息
+			// 多展示20条信息
 			this.showMinIdx = this.showMinIdx > 20 ? this.showMinIdx - 20 : 0;
 		},
 		onShowMore() {
@@ -607,6 +601,15 @@ export default {
 		onEditorBlur(e) {
 			this.isFocus = false;
 		},
+		onAudioStateChange(state, msgInfo) {
+			const playingAudio = this.$refs['message' + msgInfo.id][0]
+			if (state == 'PLAYING' && playingAudio != this.playingAudio) {
+				// 停止之前的录音
+				this.playingAudio && this.playingAudio.stopPlayAudio();
+				// 记录当前正在播放的消息
+				this.playingAudio = playingAudio;
+			}
+		},
 		loadReaded(fid) {
 			this.$http({
 				url: `/message/private/maxReadedId?friendId=${fid}`,
@@ -665,7 +668,7 @@ export default {
 			})
 		},
 		rpxTopx(rpx) {
-			// px转换成rpx
+			// rpx转换成px
 			let info = uni.getSystemInfoSync()
 			let px = info.windowWidth * rpx / 750;
 			return Math.floor(rpx);
@@ -696,30 +699,104 @@ export default {
 				})
 			}
 		},
+		reCalChatMainHeight() {
+			setTimeout(() => {
+				let h = this.windowHeight;
+				// 减去标题栏高度
+				h -= 50;
+				// 减去键盘高度
+				if (this.isShowKeyBoard || this.chatTabBox != 'none') {
+					console.log("减去键盘高度:", this.keyboardHeight)
+					h -= this.keyboardHeight;
+					this.scrollToBottom();
+				}
+				// #ifndef H5
+				// h5需要减去状态栏高度
+				h -= uni.getSystemInfoSync().statusBarHeight;
+				// #endif
+				this.chatMainHeight = h;
+				console.log("窗口高度:", this.chatMainHeight)
+				if (this.isShowKeyBoard || this.chatTabBox != 'none') {
+					this.scrollToBottom();
+				}
+				// ios浏览器键盘把页面顶起后,页面长度不会变化,这里把页面拉到顶部适配一下
+				// #ifdef H5
+				if (uni.getSystemInfoSync().platform == 'ios') {
+					// 不同手机需要的延时时间不一致,采用分段延时的方式处理
+					const delays = [50, 100, 500];
+					delays.forEach((delay) => {
+						setTimeout(() => {
+							uni.pageScrollTo({
+								scrollTop: 0,
+								duration: 10
+							});
+						}, delay);
+					})
+				}
+				// #endif
+			}, 30)
+		},
 		listenKeyBoard() {
+			// #ifdef H5	
+			const userAgent = navigator.userAgent;
+			const regex = /(macintosh|windows)/i;
+			if (regex.test(userAgent)) {
+				// 电脑端不需要弹出键盘
+				console.log("userAgent:", userAgent)
+				return;
+			}
+			if (uni.getSystemInfoSync().platform == 'ios') {
+				// ios h5实现键盘监听
+				window.addEventListener('focusin', this.focusInListener);
+				window.addEventListener('focusout', this.focusOutListener);
+			} else {
+				// 安卓h5实现键盘监听
+				let initHeight = window.innerHeight;
+				window.addEventListener('resize', this.resizeListener);
+			}
+			// #endif
+			// #ifndef H5
+			// app实现键盘监听
+			uni.onKeyboardHeightChange(this.keyBoardListener);
+			// #endif
+		},
+		unListenKeyboard() {
 			// #ifdef H5
-			// 由于H5无法触发TextArea的@keyboardheightchange事件,所以通过
-			// 监听屏幕高度变化来实现键盘监听
-			let initHeight = window.innerHeight;
-			window.addEventListener('resize', () => {
-				let keyboardHeight = initHeight - window.innerHeight;
-				this.isShowKeyBoard = keyboardHeight > 0;
-				if (this.isShowKeyBoard) {
-					this.keyboardHeight = keyboardHeight;
-				}
-				this.reCalChatMainHeight();
-			});
+			// 安卓h5实现键盘监听
+			window.removeEventListener('resize', this.resizeListener);
+			window.removeEventListener('focusin', this.focusInListener);
+			window.removeEventListener('focusout', this.focusOutListener);
 			// #endif
 			// #ifndef H5
-			uni.onKeyboardHeightChange((res) => {
-				this.isShowKeyBoard = res.height > 0;
-				if (this.isShowKeyBoard) {
-					this.keyboardHeight = res.height; // 获取并保存键盘高度
-				}
-				this.reCalChatMainHeight();
-			});
+			uni.offKeyboardHeightChange(this.keyBoardListener);
 			// #endif
 		},
+		keyBoardListener(res) {
+			this.isShowKeyBoard = res.height > 0;
+			if (this.isShowKeyBoard) {
+				this.keyboardHeight = res.height; // 获取并保存键盘高度
+			}
+			this.reCalChatMainHeight();
+		},
+		resizeListener() {
+			console.log("resize")
+			let keyboardHeight = this.initHeight - window.innerHeight;
+			this.isShowKeyBoard = keyboardHeight > 150;
+			if (this.isShowKeyBoard) {
+				this.keyboardHeight = keyboardHeight;
+			}
+			this.reCalChatMainHeight();
+		},
+		focusInListener() {
+			console.log("focusInListener")
+			this.isShowKeyBoard = true;
+			this.reCalChatMainHeight();
+		},
+		focusOutListener() {
+			console.log("focusOutListener")
+			this.isShowKeyBoard = false;
+			this.reCalChatMainHeight();
+		},
 		showBannedTip() {
 			let msgInfo = {
 				tmpId: this.generateId(),
@@ -736,29 +813,8 @@ export default {
 			}
 			this.chatStore.insertMessage(msgInfo, this.chat);
 		},
-		reCalChatMainHeight() {
-			const sysInfo = uni.getSystemInfoSync();
-			let h = sysInfo.windowHeight;
-			// 减去标题栏高度
-			h -= 50;
-			// #ifdef H5
-			// h5的sysInfo.windowHeight默认就已经减去键盘高度了
-			if (this.chatTabBox != 'none') {
-				h -= this.keyboardHeight;
-			}
-			// #endif
-			// #ifndef H5
-			// 减去状态栏高度
-			h -= sysInfo.statusBarHeight;
-			if (this.isShowKeyBoard || this.chatTabBox != 'none') {
-				h -= this.keyboardHeight;
-			}
-			// #endif
-			console.log("h:", h)
-			this.chatMainHeight = h;
-		},
 		generateId() {
-			// 生成临时id
+			// 生成临时id 
 			return String(new Date().getTime()) + String(Math.floor(Math.random() * 1000));
 		}
 	},
@@ -858,7 +914,20 @@ export default {
 		// 监听键盘高度
 		this.listenKeyBoard();
 		// 计算聊天窗口高度
-		this.$nextTick(() => this.reCalChatMainHeight())
+		this.$nextTick(() => {
+			this.windowHeight = uni.getSystemInfoSync().windowHeight;
+			this.reCalChatMainHeight()
+			// 兼容ios h5:禁止页面滚动
+			// #ifdef H5
+			this.initHeight = window.innerHeight;
+			document.body.addEventListener('touchmove', function(e) {
+				e.preventDefault();
+			}, { passive: false });
+			// #endif
+		});
+	},
+	onUnload() {
+		this.unListenKeyboard();
 	},
 	onShow() {
 		if (this.needScrollToBottom) {
@@ -870,14 +939,12 @@ export default {
 }
 </script>
 
-<style lang="scss" scoped>
+<style lang="scss">
 .chat-box {
 	$icon-color: rgba(0, 0, 0, 0.88);
 	position: relative;
 	background-color: #fafafa;
 
-
-
 	.header {
 		display: flex;
 		justify-content: center;
@@ -912,7 +979,7 @@ export default {
 		width: 100%;
 		display: flex;
 		flex-direction: column;
-		z-index: 9;
+		z-index: 2;
 
 		.chat-msg {
 			flex: 1;