diff --git a/src/lib/strformat.js b/src/lib/strformat.js
index efc341f3..eee1a37b 100644
--- a/src/lib/strformat.js
+++ b/src/lib/strformat.js
@@ -49,11 +49,16 @@ export function stringToColorHash(value) {
return hash;
}
+// User avatar letter color id.
+export function letterTileColorId(userId) {
+ return Math.abs(stringToColorHash(userId)) % 16;
+}
+
// Converts user or topic ID to a CSS color class. Ideally it should produce the same color value as Java version.
// params:
// - {string} id: user or topic ID
// - {boolean} light: light or dark version of the color.
// - {boolean} fg: foreground or background color.
export function idToColorClass(id, light, fg) {
- return (light ? 'lt-' : 'dk-') + (fg ? 'fg-' : 'bg-') + (Math.abs(stringToColorHash(id)) % 16);
+ return (light ? 'lt-' : 'dk-') + (fg ? 'fg-' : 'bg-') + letterTileColorId(id);
}
diff --git a/src/lib/utils.js b/src/lib/utils.js
index b5fce4e6..168ad323 100644
--- a/src/lib/utils.js
+++ b/src/lib/utils.js
@@ -2,13 +2,6 @@
import Tinode from 'tinode-sdk';
-import { stringToColorHash } from './strformat.js';
-
-// User avatar letter color id.
-export function letterTileColor(userId) {
- return Math.abs(stringToColorHash(userId)) % 16;
-}
-
// Make shortcut icon appear with a green dot + show unread count in title.
export function updateFavicon(count) {
const oldIcon = document.getElementById('shortcut-icon');
diff --git a/src/views/messages-view.jsx b/src/views/messages-view.jsx
index b8047b7e..752c1443 100644
--- a/src/views/messages-view.jsx
+++ b/src/views/messages-view.jsx
@@ -22,8 +22,8 @@ import { DEFAULT_P2P_ACCESS_MODE, IMAGE_PREVIEW_DIM, KEYPRESS_DELAY, MESSAGES_PA
import { SUPPORTED_IMAGE_FORMATS, blobToBase64, base64ToBlob, filePasted, fileToBase64,
imageScaled, makeImageUrl, fitImageSize } from '../lib/blob-helpers.js';
import HashNavigation from '../lib/navigation.js';
-import { bytesToHumanSize, shortDateFormat } from '../lib/strformat.js';
-import { sanitizeImageUrl, letterTileColor } from '../lib/utils.js';
+import { bytesToHumanSize, shortDateFormat, letterTileColorId } from '../lib/strformat.js';
+import { sanitizeImageUrl } from '../lib/utils.js';
// Run timer with this frequency (ms) for checking notification queue.
const NOTIFICATION_EXEC_INTERVAL = 300;
@@ -121,10 +121,22 @@ class MessagesView extends React.Component {
this.handleQuoteClick = this.handleQuoteClick.bind(this);
this.convertIntoThumbnails = this.convertIntoThumbnails.bind(this);
+ this.chatMessageRefs = {};
+ this.getOrCreateMessageRef = this.getOrCreateMessageRef.bind(this);
+
this.readNotificationQueue = [];
this.readNotificationTimer = null;
}
+ getOrCreateMessageRef(seqId) {
+ if (this.chatMessageRefs.hasOwnProperty(seqId)) {
+ return this.chatMessageRefs[seqId];
+ }
+ const ref = React.createRef();
+ this.chatMessageRefs[seqId] = ref;
+ return ref;
+ }
+
componentDidMount() {
// this.propsChange(this.props, this.state);
if (this.messagesScroller) {
@@ -868,7 +880,7 @@ class MessagesView extends React.Component {
}
this.convertIntoThumbnails(ents, 0, (success) => {
if (success) {
- const msg = Drafty.createQuote(header, cont, letterTileColor(thisFrom));
+ const msg = Drafty.createQuote(header, cont, letterTileColorId(thisFrom));
this.setState({reply: {content: msg, seq: m.seq}});
}
});
@@ -916,12 +928,11 @@ class MessagesView extends React.Component {
scale.call(this, b);
}
} else {
- //let saveThis = this;
const from = this.props.tinode.authorizeURL(sanitizeImageUrl(ex.data.ref));
fetch(from)
.then(e => e.blob())
.then((b) => {
- scale.call(saveThis, b);
+ scale.call(this, b);
});
return;
}
@@ -932,11 +943,14 @@ class MessagesView extends React.Component {
}
handleQuoteClick(replyToSeq) {
- const element = document.getElementById("msg-" + replyToSeq);
+ const ref = this.getOrCreateMessageRef(replyToSeq);
+ const element = ref.current;
if (element) {
element.scrollIntoView({block: "center", behavior: "smooth"});
element.style.backgroundColor = 'rgb(0, 0, 0, 0.4)';
setTimeout(() => { element.style.backgroundColor = ''; } , 1000);
+ } else {
+ console.error("Unresolved ref: seqId", replyToSeq);
}
}
@@ -1036,6 +1050,9 @@ class MessagesView extends React.Component {
chatBoxClass='chat-box';
}
+ // Ref for this chat message.
+ const ref = this.getOrCreateMessageRef(msg.seq);
+
messageNodes.push(