move fast & break things. chat improvements

This commit is contained in:
Martti Malmi 2021-02-04 13:30:03 +02:00
parent c7ddc72b8d
commit effc3c08b0
2 changed files with 90 additions and 93 deletions

View File

@ -224,8 +224,9 @@ function processMessage(chatId, msg, info) {
msg.info = info;
msg.selfAuthored = info.selfAuthored;
msg.timeStr = msg.time;
msg.time = new Date(msg.time);
chat.sortedMessages.push(msg);
State.local.get('chats').get(chatId).get('msgs').get(msg.timeStr).put(msg);
msg.time = new Date(msg.time);
if (!info.selfAuthored && msg.time > (chat.myLastSeenTime || -Infinity)) {
if (window.location.hash !== '#/chat/' + chatId || document.visibilityState !== 'visible') {
Notifications.changeChatUnseenCount(chatId, 1);

View File

@ -10,17 +10,19 @@ import Session from '../Session.js';
import Notifications from '../Notifications.js';
import ChatList from './ChatList.js';
import NewChat from './NewChat.js';
import ScrollWindow from '../lib/ScrollWindow.js';
const caretDownSvg = html`
<svg x="0px" y="0px"
width="451.847px" height="451.847px" viewBox="0 0 451.847 451.847" style="enable-background:new 0 0 451.847 451.847;">
width="451.847px" height="451.847px" viewBox="0 0 451.847 451.847" style="enable-background:new 0 0 451.847 451.847;">
<g>
<path fill="currentColor" d="M225.923,354.706c-8.098,0-16.195-3.092-22.369-9.263L9.27,151.157c-12.359-12.359-12.359-32.397,0-44.751
c12.354-12.354,32.388-12.354,44.748,0l171.905,171.915l171.906-171.909c12.359-12.354,32.391-12.354,44.744,0
c12.365,12.354,12.365,32.392,0,44.751L248.292,345.449C242.115,351.621,234.018,354.706,225.923,354.706z"/>
<path fill="currentColor" d="M225.923,354.706c-8.098,0-16.195-3.092-22.369-9.263L9.27,151.157c-12.359-12.359-12.359-32.397,0-44.751
c12.354-12.354,32.388-12.354,44.748,0l171.905,171.915l171.906-171.909c12.359-12.354,32.391-12.354,44.744,0
c12.365,12.354,12.365,32.392,0,44.751L248.292,345.449C242.115,351.621,234.018,354.706,225.923,354.706z"/>
</g>
</svg>
`;
const size = 50;
function copyMyChatLinkClicked(e) {
Helpers.copyToClipboard(Session.getMyChatLink());
@ -40,62 +42,68 @@ const subscribedToMsgs = {};
class ChatView extends Component {
constructor() {
super();
this.activeChat = null;
this.eventListeners = [];
this.eventListeners = {};
}
componentDidMount() {
State.local.get('activeRoute').on((activeRouteId, a, b, eve) => {
this.eventListeners.push(eve);
if (activeRouteId.indexOf('/chat/') !== 0 || !Session.getKey()) return;
this.activeChat && chats[this.activeChat] && chats[this.activeChat].setTyping(false);
this.activeChat = activeRouteId && activeRouteId.replace('/chat/new', '').replace('/chat/', '');
this.setState({sortedMessages: chats[this.activeChat] && chats[this.activeChat].sortedMessages || []});
if (!(this.props.id && this.props.id.length > 20)) return;
this.unsubscribe();
this.sortedMessages = [];
this.setState({sortedMessages: this.sortedMessages});
const update = () => {
const chat = chats[this.activeChat];
if (!chat) return;
Notifications.changeChatUnseenCount(this.activeChat, 0);
this.iv = null;
const go = () => {
const chat = chats[this.props.id];
if (chat) {
clearInterval(this.iv)
this.subscribeToMsgs(this.props.id);
Notifications.changeChatUnseenCount(this.props.id, 0);
chat.setMyMsgsLastSeenTime();
Helpers.scrollToMessageListBottom();
chat.setMyMsgsLastSeenTime();
}
}
this.iv = setInterval(go, 3000);
if (this.activeChat && (this.activeChat === 'public' || this.activeChat.length > 20) && !subscribedToMsgs[this.activeChat]) {
const iv = setInterval(() => {
if (chats[this.activeChat]) {
clearInterval(iv);
this.subscribeToMsgs(this.activeChat);
chats[this.activeChat].sortedMessages.sort((a, b) => a.time - b.time);
this.setState({sortedMessages: chats[this.activeChat].sortedMessages});
} else {
if (this.activeChat.length > 40) { // exclude UUIDs
newChat(this.activeChat);
}
}
update();
}, 1000);
subscribedToMsgs[this.activeChat] = true;
update();
}
State.local.get('chats').get(this.props.id).get('msgDraft').once(m => $('.new-msg').val(m));
const node = State.local.get('chats').get(this.props.id).get('msgs');
this.scroller = new ScrollWindow(node, {size, onChange: sortedMessages => {
this.setState({sortedMessages})}
});
}
componentDidUpdate(prevProps) {
const chat = chats[this.props.id];
if (prevProps.id !== this.props.id) {
this.componentDidMount();
} else {
Helpers.scrollToMessageListBottom();
$('.msg-content img').off('load').on('load', () => Helpers.scrollToMessageListBottom());
if (chat && !chat.uuid) {
if ($('.msg.our').length && !$('.msg.their').length && !chat.theirMsgsLastSeenTime) {
$('#not-seen-by-them').slideDown();
} else {
$('#not-seen-by-them').slideUp();
}
}
}
}
unsubscribe() {
clearInterval(this.iv);
this.scroller && this.scroller.unsubscribe();
Object.values(this.eventListeners).forEach(e => e.off());
this.eventListeners = {};
}
componentWillUnmount() {
this.eventListeners.forEach(e => e.off());
this.unsubscribe();
}
subscribeToMsgs(pub) {
subscribedToMsgs[pub] = true;
const limitedUpdate = _.debounce(() => {
chats[pub].sortedMessages.sort((a, b) => a.time - b.time);
this.setState({sortedMessages: chats[pub].sortedMessages});
}, 200);
chats[pub].getMessages((msg, info) => {
processMessage(pub, msg, info);
if (window.location.hash.replace('#/chat/', '') === pub) {
limitedUpdate();
}
});
}
@ -132,68 +140,56 @@ class ChatView extends Component {
this.messageViewScrollHandler();
}
componentDidUpdate() {
const chat = chats[this.activeChat];
Helpers.scrollToMessageListBottom();
$('.msg-content img').off('load').on('load', () => Helpers.scrollToMessageListBottom());
if (chat && !chat.uuid) {
if ($('.msg.our').length && !$('.msg.their').length && !chat.theirMsgsLastSeenTime) {
$('#not-seen-by-them').slideDown();
} else {
$('#not-seen-by-them').slideUp();
}
}
this.activeChat && State.local.get('chats').get(this.activeChat).get('msgDraft').once(m => $('.new-msg').val(m));
}
render() {
const now = new Date();
const nowStr = now.toLocaleDateString();
let previousDateStr;
let previousFrom;
const msgListContent = [];
if (chats[this.activeChat] && this.state.sortedMessages) {
Object.values(chats[this.activeChat].sortedMessages).forEach(msg => {
const date = typeof msg.time === 'string' ? new Date(msg.time) : msg.time;
if (date) {
const dateStr = date.toLocaleDateString();
if (dateStr !== previousDateStr) {
var separatorText = iris.util.getDaySeparatorText(date, dateStr, now, nowStr);
msgListContent.push(html`<div class="day-separator">${t(separatorText)}</div>`);
}
previousDateStr = dateStr;
this.state.sortedMessages && Object.values(this.state.sortedMessages).forEach(msg => {
const date = typeof msg.time === 'string' ? new Date(msg.time) : msg.time;
if (date) {
const dateStr = date.toLocaleDateString();
if (dateStr !== previousDateStr) {
var separatorText = iris.util.getDaySeparatorText(date, dateStr, now, nowStr);
msgListContent.push(html`<div class="day-separator">${t(separatorText)}</div>`);
}
previousDateStr = dateStr;
}
const from = msg.info.from;
let showName = false;
if (previousFrom && (from !== previousFrom)) {
msgListContent.push(html`<div class="from-separator"/>`);
showName = true;
}
previousFrom = from;
msgListContent.push(html`<${Message} ...${msg} showName=${showName} key=${msg.time} chatId=${this.activeChat}/>`);
});
}
const from = msg.info && msg.info.from;
let showName = false;
if (previousFrom && (from !== previousFrom)) {
msgListContent.push(html`<div class="from-separator"/>`);
showName = true;
}
previousFrom = from;
msgListContent.push(html`
<${Message} ...${msg} showName=${showName} key=${msg.time} chatId=${this.props.id}/>
`);
});
return html`
<div id="chat-view">
<${ChatList} class=${this.props.id ? 'hidden-xs' : ''}/>
<div id="chat-main" class=${this.props.id ? '' : 'hidden-xs'}>
${this.props.id && this.props.id.length > 20 ? html`<div class="main-view" id="message-view" onScroll=${e => this.onMessageViewScroll(e)}>
<div id="message-list">${msgListContent}</div>
<div id="attachment-preview" class="attachment-preview" style="display:none"></div>
</div>` : html`<${NewChat}/>`}
${this.activeChat ? html`
<div id="scroll-down-btn" style="display:none;" onClick=${() => Helpers.scrollToMessageListBottom()}>${caretDownSvg}</div>
<div id="not-seen-by-them" style="display: none">
<p dangerouslySetInnerHTML=${{ __html: t('if_other_person_doesnt_see_message') }}></p>
<p><button onClick=${e => copyMyChatLinkClicked(e)}>${t('copy_your_invite_link')}</button></p>
</div>
<div class="chat-message-form"><${MessageForm} activeChat=${this.activeChat}/></div>
`: ''}
</div>
</div>`;
<div id="chat-view">
<${ChatList} class=${this.props.id ? 'hidden-xs' : ''}/>
<div id="chat-main" class=${this.props.id ? '' : 'hidden-xs'}>
${this.props.id && this.props.id.length > 20 ? html`
<div class="main-view" id="message-view" onScroll=${e => this.onMessageViewScroll(e)}>
<div id="message-list">${msgListContent}</div>
<div id="attachment-preview" class="attachment-preview" style="display:none"></div>
</div>` : html`<${NewChat}/>`
}
${this.props.id ? html`
<div id="scroll-down-btn" style="display:none;" onClick=${() => Helpers.scrollToMessageListBottom()}>${caretDownSvg}</div>
<div id="not-seen-by-them" style="display: none">
<p dangerouslySetInnerHTML=${{ __html: t('if_other_person_doesnt_see_message') }}></p>
<p><button onClick=${e => copyMyChatLinkClicked(e)}>${t('copy_your_invite_link')}</button></p>
</div>
<div class="chat-message-form"><${MessageForm} activeChat=${this.props.id}/></div>
`: ''}
</div>
</div>`;
}
}
export default ChatView;