Chat: Add pending message container and display

Additional logic for reducer + array manips

Removing multi-array mutation and comments

Adding comments and working logic.

Fix sigil showing for pending from same aut

Pending messages persist upon circle change

Scaffolding message pending injection

Additional logic for reducer + array manips

Removing multi-array mutation and comments

Adding comments and working logic.

Fix sigil showing for pending from same aut

Pending messages persist upon circle change

Reworking pending boolean logic.

Data structure changed to Map

Checking correct scope of prop, removing dev TODO

Rebase mistake.
This commit is contained in:
Matilde Park 2019-08-20 16:05:16 -04:00 committed by Matilde Park
parent 768c07a3f6
commit 3219e18019
10 changed files with 76 additions and 11 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import _ from 'lodash';
import { uuid } from '/lib/util';
import { store } from '/store';
class UrbitApi {
setAuthTokens(authTokens) {
@ -35,6 +37,18 @@ class UrbitApi {
this.action("hall", "hall-action", data);
}
addPendingMessage(data) {
let pendingMap = store.state.pendingMessages;
if (pendingMap.has(data.aud[0])) {
pendingMap.get(data.aud[0]).push(data)
} else {
pendingMap.set(data.aud[0], [data])
}
store.setState({
pendingMessages: pendingMap
});
}
chat(lis) {
this.action("chat", "chat-action", {
actions: {

View File

@ -20,6 +20,8 @@ export class ChatScreen extends Component {
scrollLocked: false,
};
this.pendingQueue = props.pendingMessages;
this.hasAskedForMessages = false;
this.onScroll = this.onScroll.bind(this);
@ -183,6 +185,18 @@ export class ChatScreen extends Component {
let config = props.configs[state.station] || {};
let messages = props.messages.slice(0);
// Pending messages get pinned to the bottom of the messages queue.
let pendingInRoom =
(this.pendingQueue.has(this.state.station))
? this.pendingQueue.get(this.state.station) : [];
pendingInRoom.map(function(value) {
return value.pending = true;
})
messages = messages.concat(pendingInRoom);
let lastMsgNum = (messages.length > 0) ?
messages[messages.length - 1].num : 0;
@ -195,22 +209,38 @@ export class ChatScreen extends Component {
let chatMessages = reversedMessages.map((msg, i) => {
// Render sigil if previous message is not by the same sender
let gamAut = ['gam', 'aut'];
// Local messages don't have a 'gam' prop, so look for the top level if it doesn't exist.
let aut = msg.aut ? msg.aut : null;
// No gamAut? Return top level author for the same sender check.
let renderSigil =
_.get(reversedMessages[i + 1], gamAut) !== _.get(msg, gamAut);
_.get(reversedMessages[i + 1], gamAut) !== _.get(msg, gamAut, aut);
// More padding top if previous message is not by the same sender
let paddingTop = renderSigil;
// More padding bot if next message is not by the same sender
let paddingBot =
_.get(reversedMessages[i - 1], gamAut) !== _.get(msg, gamAut);
_.get(reversedMessages[i - 1], gamAut) !== _.get(msg, gamAut, aut);
// Non-local ships don't have pending props.
if (!msg.pending) {
var pending = false;
}
// Non-local ships don't have pending props.
if (!pending) {
var pending = false;
}
return (
<Message
key={msg.gam.uid}
msg={msg.gam}
key={msg.gam ? msg.gam.uid : msg.uid}
msg={msg.gam ? msg.gam : msg}
renderSigil={renderSigil}
paddingTop={paddingTop}
paddingBot={paddingBot} />
paddingBot={paddingBot}
pending={!!pending}/>
);
});

View File

@ -263,6 +263,8 @@ export class ChatInput extends Component {
)
};
props.api.addPendingMessage(message);
props.api.hall(
{
convey: [message]

View File

@ -171,7 +171,7 @@ export class Message extends Component {
render() {
const { props } = this;
let pending = !!props.msg.pending ? ' o-80' : '';
let pending = !!props.msg.pending ? ' o-40' : '';
let datestamp = moment.unix(props.msg.wen / 1000).format('LL');
let paddingTop = props.paddingTop ? 'pt3' : '';

View File

@ -158,6 +158,7 @@ export class Root extends Component {
api={api}
configs={configs}
messages={messages}
pendingMessages={state.pendingMessages}
peers={state.peers}
subscription={subscription}
{...props}

View File

@ -61,4 +61,3 @@ export function dateToDa(d, mil) {
export function deSig(ship) {
return ship.replace('~', '');
}

View File

@ -6,6 +6,7 @@ export class UpdateReducer {
let data = _.get(json, 'update', false);
if (data) {
this.reduceInbox(_.get(data, 'inbox', false), state);
this.reducePending(_.get(data, 'message', false), state);
this.reduceMessage(_.get(data, 'message', false), state);
this.reduceMessages(_.get(data, 'messages', false), state);
this.reduceConfig(_.get(data, 'config', false), state);
@ -29,6 +30,23 @@ export class UpdateReducer {
}
}
reducePending(message, state) {
if (message && (state.pendingMessages.has(message.envelope.gam.aud[0]))) {
for (let pendingMessage of state.pendingMessages.get(message.envelope.gam.aud[0])) {
// Does the incoming message match a pending one?
if (message.envelope.gam.uid === pendingMessage.uid) {
// Mutating the pendingMessages array.
let pendingMessageMap = state.pendingMessages;
let matchedMessage = pendingMessageMap.get(pendingMessage.aud[0]).indexOf(pendingMessage);
pendingMessageMap.get(pendingMessage.aud[0]).splice(matchedMessage, 1);
state.pendingMessages = pendingMessageMap;
}
}
}
}
reduceMessages(msgs, state) {
if (msgs) {

View File

@ -11,7 +11,8 @@ class Store {
configs: {},
circles: [],
peers: {},
spinner: false
spinner: false,
pendingMessages: new Map([])
};
this.initialReducer = new InitialReducer();