Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pending status for outgoing XMPP messages #244

Merged
merged 6 commits into from
Aug 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[![Build Status](https://travis-ci.com/67P/hyperchannel.svg?branch=master)](https://travis-ci.org/67P/hyperchannel)
[![devDependency Status](https://david-dm.org/67P/hyperchannel/dev-status.svg)](https://david-dm.org/67P/hyperchannel#info=devDependencies)
[![Code Climate](https://img.shields.io/codeclimate/maintainability/67P/hyperchannel.svg)](https://codeclimate.com/github/67P/hyperchannel)
[![devDependency Status](https://david-dm.org/67P/hyperchannel/dev-status.svg)](https://david-dm.org/67P/hyperchannel#info=devDependencies)

# Hyperchannel (pre-alpha!)

Expand Down
4 changes: 4 additions & 0 deletions app/components/message-chat/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ export default class MessageChatComponent extends Component {
return htmlSafe(out);
}

get pendingClass () {
return this.args.message.pending ? 'text-gray-500' : '';
}

@action
usernameClick (username) {
this.args.onUsernameClick(username);
Expand Down
13 changes: 7 additions & 6 deletions app/components/message-chat/template.hbs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
<div class="chat-message">
<span class="chat-message__username"
data-username={{@message.nickname}}
onclick={{fn this.usernameClick @message.nickname}}>
<div class="chat-message break-words">
<span data-username={{@message.nickname}}
onclick={{fn this.usernameClick @message.nickname}}
class="mr-1 font-bold {{this.pendingClass}}" >
{{@message.nickname}}:
</span>

<time class="chat-message__date" datetime={{this.datetime}} title={{this.dateTitle}}>
<time datetime={{this.datetime}} title={{this.dateTitle}}
class="block float-right text-sm text-gray-300" >
{{moment-format @message.date "HH:mm"}}
</time>

<span class="chat-message__message">
<span class="{{this.pendingClass}}">
{{this.formattedContent}}
</span>
</div>
22 changes: 15 additions & 7 deletions app/controllers/base_channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { alias } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import { isPresent } from '@ember/utils';
import { tracked } from '@glimmer/tracking';
import Channel from 'hyperchannel/models/channel';
import Message from 'hyperchannel/models/message';

export default class BaseChannelController extends Controller {
Expand All @@ -16,14 +17,23 @@ export default class BaseChannelController extends Controller {

@alias('application.showChannelMenu') showChannelMenu;

createMessage (message, type) {
return new Message({
createMessage (content, type) {
const message = new Message({
type: type,
date: new Date(),
// TODO nickname per channel
nickname: this.model.account.nickname,
content: message
content: content
});

// We only receive our own message from XMPP MUCs (but not DMs)
// TODO implement message carbons or another way of verifying sent status
if (this.model.protocol === 'XMPP' &&
(this.model instanceof Channel)) {
message.pending = true;
}

return message;
}

@computed('router.currentRouteName')
Expand Down Expand Up @@ -57,12 +67,10 @@ export default class BaseChannelController extends Controller {
sendMessage (newMessage) {
const message = this.createMessage(newMessage, 'message-chat');

this.coms.transferMessage(
this.model,
message.content
);
this.coms.transferMessage(this.model, message.content);

this.model.addMessage(message);

this.newMessage = null;
}

Expand Down
12 changes: 12 additions & 0 deletions app/models/base_channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,18 @@ export default class BaseChannel {
}
}

confirmPendingMessage (content) {
const message = this.messages.filterBy('pending')
.findBy('content', content);

if (isPresent(message)) {
message.pending = false;
return true;
} else {
return false;
}
}

addUser(username) {
if (!this.userList.includes(username)) {
this.userList.pushObject(username);
Expand Down
1 change: 1 addition & 0 deletions app/models/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default class Message {
@tracked date = null;
@tracked nickname = null;
@tracked content = null;
@tracked pending = null;

constructor (props) {
Object.assign(this, props);
Expand Down
13 changes: 9 additions & 4 deletions app/services/sockethub-xmpp.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,17 @@ export default class SockethubXmppService extends Service {
if (isEmpty(message.object.content)) return;

const channel = this.findOrCreateChannelForMessage(message);
const channelMessage = channelMessageFromSockethubObject(message);

// TODO should check for message and update sent status if exists
if (channelMessage.nickname !== channel.account.nickname) {
channel.addMessage(channelMessage);
// TODO implement message carbons
// https://xmpp.org/extensions/xep-0280.html
if (message.actor.displayName &&
(message.actor.displayName === channel.account.nickname)) {
const pendingConfirmed = channel.confirmPendingMessage(message.object.content);
if (pendingConfirmed) return;
}

const channelMessage = channelMessageFromSockethubObject(message);
channel.addMessage(channelMessage);
}

/**
Expand Down
25 changes: 0 additions & 25 deletions app/styles/components/message-chat.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,31 +42,6 @@
font-style: italic;
}

&__date {
display: block;
float: right;
font-size: 12px;
color: #ccc;
}

&__username {
margin-right: 0.2em;
font-weight: bold;

// &[data-username=raucao] {
// background: url(/img/avatar-sk.png) 0 2px no-repeat;
// }
// &[data-username=silverbucket] {
// background: url(/img/avatar-sb.png) 0 2px no-repeat;
// }
// &[data-username=galfert] {
// background: url(/img/avatar-ga.jpeg) 0 2px no-repeat;
// }
}

&__message {
}

a {
text-decoration: underline;
color: #339;
Expand Down
1 change: 1 addition & 0 deletions tests/fixtures/accounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export const ircAccount = new IrcAccount({
});

export const xmppAccount = new XmppAccount({
nickname: 'jimmy',
username: 'jimmy@kosmos.org'
});
30 changes: 30 additions & 0 deletions tests/unit/services/sockethub-xmpp-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import Channel from 'hyperchannel/models/channel';
import Message from 'hyperchannel/models/message';
import { xmppAccount } from '../../fixtures/accounts';

module('Unit | Service | sockethub xmpp', function(hooks) {
Expand Down Expand Up @@ -99,6 +100,35 @@ module('Unit | Service | sockethub xmpp', function(hooks) {
assert.equal(channel.messages.lastObject.content, 'hello world');
});

test('#addMessageToChannel updates pending status when receiving an outgoing message', function(assert) {
const channel = new Channel({ account: xmppAccount, name: 'kosmos-dev@kosmos.chat' });
const outgoingMessage = new Message({
type: 'message-chat',
date: new Date(),
nickname: 'jimmy',
content: 'yo, gang!',
pending: true
});
channel.messages.pushObject(outgoingMessage);

const comsService = this.owner.factoryFor('service:coms').create({
accounts: [ xmppAccount ], channels: [ channel ]
});
const service = this.owner.factoryFor('service:sockethub-xmpp').create({ coms: comsService });

const message = {
actor: { '@id': 'kosmos-dev@kosmos.chat/jimmy', '@type': 'person', displayName: 'jimmy' },
target: { '@id': 'kosmos-dev@kosmos.chat', '@type': 'room' },
object: { '@type': 'message', content: 'yo, gang!' }
};

service.addMessageToChannel(message);

assert.equal(channel.messages.filterBy('nickname', 'jimmy').length, 1);
assert.equal(channel.messages.lastObject.content, 'yo, gang!');
assert.notOk(channel.messages.lastObject.pending);
});

test('#createUserChannel', function(assert) {
const comsService = this.owner.factoryFor('service:coms').create({
accounts: [ xmppAccount ]
Expand Down