From 706a7e0aaa37f4fdb1a3cc23b815a5cee7d2d865 Mon Sep 17 00:00:00 2001 From: aforge Date: Thu, 28 Apr 2022 22:00:11 -0700 Subject: [PATCH] Remaining code review items. --- package-lock.json | 37 +++++++++++++++++++++++++++++++++--- package.json | 3 ++- src/views/info-view.jsx | 6 +++--- src/views/messages-view.jsx | 10 +++------- src/views/tinode-web.jsx | 14 +++++--------- src/widgets/call-panel.jsx | 16 ++++++++-------- src/widgets/chat-message.jsx | 4 ++-- src/widgets/contact.jsx | 4 ++-- 8 files changed, 59 insertions(+), 35 deletions(-) diff --git a/package-lock.json b/package-lock.json index 600b7aa9..b221de77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tinode-webapp", - "version": "0.20.0-alpha1", + "version": "0.18.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "tinode-webapp", - "version": "0.20.0-alpha1", + "version": "0.18.3", "license": "Apache-2.0", "dependencies": { "firebase": "^9.6.7", @@ -15,7 +15,8 @@ "react-dom": "^17.0.2", "react-intl": "^5.20.2", "react-intl-formatted-duration": "^4.0.0", - "tinode-sdk": "^0.18.3" + "tinode-sdk": "^0.18.3", + "webrtc-adapter": "^8.1.1" }, "devDependencies": { "@babel/core": "^7.14.5", @@ -6277,6 +6278,11 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/sdp": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sdp/-/sdp-3.0.3.tgz", + "integrity": "sha512-8EkfckS+XZQaPLyChu4ey7PghrdcraCVNpJe2Gfdi2ON1ylQ7OasuKX+b37R9slnRChwIAiQgt+oj8xXGD8x+A==" + }, "node_modules/selenium-webdriver": { "version": "4.0.0-rc-1", "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.0.0-rc-1.tgz", @@ -6936,6 +6942,18 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/webrtc-adapter": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-8.1.1.tgz", + "integrity": "sha512-1yXevP7TeZGmklEXkvQVrZp3fOSJlLeXNGCA7NovQokxgP3/e2T3EVGL0eKU87S9vKppWjvRWqnJeSANEspOBg==", + "dependencies": { + "sdp": "^3.0.2" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=3.10.0" + } + }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -11757,6 +11775,11 @@ "ajv-keywords": "^3.5.2" } }, + "sdp": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sdp/-/sdp-3.0.3.tgz", + "integrity": "sha512-8EkfckS+XZQaPLyChu4ey7PghrdcraCVNpJe2Gfdi2ON1ylQ7OasuKX+b37R9slnRChwIAiQgt+oj8xXGD8x+A==" + }, "selenium-webdriver": { "version": "4.0.0-rc-1", "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.0.0-rc-1.tgz", @@ -12231,6 +12254,14 @@ "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true }, + "webrtc-adapter": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-8.1.1.tgz", + "integrity": "sha512-1yXevP7TeZGmklEXkvQVrZp3fOSJlLeXNGCA7NovQokxgP3/e2T3EVGL0eKU87S9vKppWjvRWqnJeSANEspOBg==", + "requires": { + "sdp": "^3.0.2" + } + }, "websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", diff --git a/package.json b/package.json index 003dc314..417b43fe 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,8 @@ "react-dom": "^17.0.2", "react-intl": "^5.20.2", "react-intl-formatted-duration": "^4.0.0", - "tinode-sdk": "^0.20.0-alpha1" + "tinode-sdk": "^0.20.0-alpha1", + "webrtc-adapter": "^8.1.1" }, "devDependencies": { "@babel/core": "^7.14.5", diff --git a/src/views/info-view.jsx b/src/views/info-view.jsx index 14be31b5..4a7110c9 100644 --- a/src/views/info-view.jsx +++ b/src/views/info-view.jsx @@ -202,11 +202,11 @@ class InfoView extends React.Component { deleter: acs && acs.isDeleter(), muted: acs && acs.isMuted(), - fullName: clipStr(topic.public ? topic.public.fn : undefined, MAX_TITLE_LENGTH), - description: clipStr(topic.public ? topic.public.note : undefined, MAX_TOPIC_DESCRIPTION_LENGTH), + fullName: clipStr(topic.public && topic.public.fn, MAX_TITLE_LENGTH), + description: clipStr(topic.public && topic.public.note, MAX_TOPIC_DESCRIPTION_LENGTH), avatar: makeImageUrl(topic.public ? topic.public.photo : null), trustedBadges: badges, - private: clipStr(topic.private ? topic.private.comment : null, MAX_TITLE_LENGTH), + private: clipStr(topic.private && topic.private.comment, MAX_TITLE_LENGTH), archived: topic.isArchived(), address: topic.name, groupTopic: topic.isGroupType(), diff --git a/src/views/messages-view.jsx b/src/views/messages-view.jsx index cf7dd4cc..a869c97b 100644 --- a/src/views/messages-view.jsx +++ b/src/views/messages-view.jsx @@ -310,9 +310,7 @@ class MessagesView extends React.Component { }); if (nextProps.callTopic == topic.name && shouldPresentCallPanel(nextProps.callState)) { - Object.assign(nextState, { - rtcPanel: nextProps.callTopic, - }); + nextState.rtcPanel = nextProps.callTopic; } } else { // Invalid topic. @@ -330,9 +328,7 @@ class MessagesView extends React.Component { // We are still in same topic. Show the call panel if necessary. if (nextProps.callTopic == prevState.topic && !prevState.rtcPanel && shouldPresentCallPanel(nextProps.callState)) { - Object.assign(nextState, { - rtcPanel: nextProps.callTopic, - }); + nextState.rtcPanel = nextProps.callTopic; } } @@ -1149,7 +1145,7 @@ class MessagesView extends React.Component { } let duration; if (msg.head && isVideoCall(msg.head.mime)) { - topic.messageVersions(msg, (cur, before, unused1, unused2) => { + topic.messageVersions(msg, (cur, before) => { if (cur.content == 'finished' && before.content == 'accepted') { duration = msg.ts - before.ts; } diff --git a/src/views/tinode-web.jsx b/src/views/tinode-web.jsx index f762989d..bb31b7ad 100644 --- a/src/views/tinode-web.jsx +++ b/src/views/tinode-web.jsx @@ -1304,15 +1304,11 @@ class TinodeWeb extends React.Component { // If the current URl contains the old topic name, replace it with new. // Update the name of the selected topic first so the navigator doen't clear // the state. - const newTopic = {topicSelected: newName}; - this.setState(...nextState, ...newTopic, () => { - HashNavigation.navigateTo(HashNavigation.setUrlTopic('', newName)); - }); - } else { - this.setState(nextState, () => { - HashNavigation.navigateTo(HashNavigation.setUrlTopic('', newName)); - }); + nextState.topicSelected = newName; } + this.setState(nextState, _ => { + HashNavigation.navigateTo(HashNavigation.setUrlTopic('', newName)); + }); } handleTopicUpdateRequest(topicName, pub, priv, defacs) { @@ -1814,7 +1810,7 @@ class TinodeWeb extends React.Component { case 'accept': console.log('TinodeWeb: received accept msg ', info); // If another my session has accepted the call. - if (info.topic == 'me' && info.from == this.state.myUserId) { + if (Tinode.isMeTopicName(info.topic) && this.tinode.isMe(info.from)) { this.setState({ callTopic: null, callState: CALL_STATE_NONE, diff --git a/src/widgets/call-panel.jsx b/src/widgets/call-panel.jsx index 610309cc..ea6336f2 100644 --- a/src/widgets/call-panel.jsx +++ b/src/widgets/call-panel.jsx @@ -149,15 +149,15 @@ export default class CallPanel extends React.PureComponent { this.state.pc.setRemoteDescription(desc).catch(this.reportError); } - reportError(errMessage) { - console.log(`Error ${errMessage.name}: ${errMessage.message}`); + reportError(err) { + this.props.onError(err.message, 'err'); } handleNegotiationNeededEvent() { this.state.pc.createOffer().then(offer => { return this.state.pc.setLocalDescription(offer); }) - .then(() => { + .then(_ => { this.props.onSendOffer(this.props.topic.name, this.props.seq, this.state.pc.localDescription.toJSON()); }) .catch(this.reportError); @@ -196,16 +196,17 @@ export default class CallPanel extends React.PureComponent { } handleTrackEvent(event) { + // Remote video becomes available. this.remoteRef.current.srcObject = event.streams[0]; - // Make sure we redraw the UI properly. + // Make sure we display the title (peer's name) over the remote video. this.forceUpdate(); } handleGetUserMediaError(e) { switch(e.name) { case 'NotFoundError': - console.log("Unable to open your call because no camera and/or microphone" + - "were found."); + // Cannot start the call b/c no camera and/or microphone found. + this.reportError(e); break; case 'SecurityError': case 'PermissionDeniedError': @@ -304,7 +305,7 @@ export default class CallPanel extends React.PureComponent { } track.enabled = !track.enabled; }); - // Make sure we redraw the UI properly. + // Make sure we redraw the mute/unmute icons (e.g. mic -> mic_off). this.forceUpdate(); } @@ -373,7 +374,6 @@ export default class CallPanel extends React.PureComponent { - ); diff --git a/src/widgets/chat-message.jsx b/src/widgets/chat-message.jsx index 0b66eff3..35d53d05 100644 --- a/src/widgets/chat-message.jsx +++ b/src/widgets/chat-message.jsx @@ -155,8 +155,8 @@ class BaseChatMessage extends React.PureComponent { defaultMessage="Incoming Call" description="Incoming call label" /> : ; - const isCallDropped = this.props.content == "disconnected"; - content = <>{direction}{text} + const isCallDropped = this.props.content == 'disconnected'; + content = <>{direction}{text} { !isCallDropped && this.props.duration ? [' (', , ')'] : null} diff --git a/src/widgets/contact.jsx b/src/widgets/contact.jsx index 2802aac1..babadf4d 100644 --- a/src/widgets/contact.jsx +++ b/src/widgets/contact.jsx @@ -71,8 +71,8 @@ class Contact extends React.Component { // The this.props.preview contains alreay shortened Drafty or string. let preview; if (this.props.previewIsVideoCall) { - preview = <>{this.props.previewIsResponse ? 'call_received' : 'call_made'} - video_call; + preview = <>{this.props.previewIsResponse ? 'call_received' : 'call_made'} + video_call; } else if (typeof this.props.preview == 'string') { preview = this.props.preview; } else if (Drafty.isValid(this.props.preview)) {