Browse Source

Split _chat_header from _chat

Add a refresh system for the Chat header based on the presences (and filtered by notifications)
Use also mouseover event to trigger the focus event
Fix an ERROR in ChatStates
pull/933/head
Timothée Jaussoin 6 years ago
parent
commit
ea2b70475c
  1. 2
      app/Contact.php
  2. 2
      app/widgets/AdminTest/admintest.js
  3. 86
      app/widgets/Chat/Chat.php
  4. 280
      app/widgets/Chat/_chat.tpl
  5. 11
      app/widgets/Chat/chat.js
  6. 2
      app/widgets/Dialog/dialog.js
  7. 2
      app/widgets/Draw/draw.js
  8. 2
      app/widgets/Drawer/drawer.js
  9. 2
      app/widgets/Login/login.js
  10. 11
      app/widgets/Notification/notification.js
  11. 2
      app/widgets/Preview/preview.js
  12. 39
      public/scripts/movim_base.js
  13. 2
      public/scripts/movim_tpl.js
  14. 3
      src/Movim/ChatStates.php

2
app/Contact.php

@ -228,7 +228,7 @@ class Contact extends Model
return explodeJid($this->id)['username'] ?? $this->id;
}
public function getJidAttribute(): string
public function getJidAttribute(): ?string
{
return $this->id;
}

2
app/widgets/AdminTest/admintest.js

@ -44,6 +44,6 @@ MovimWebsocket.attach(function() {
AdminTest.toggleConfiguration();
});
movim_add_onload(function() {
movimAddOnload(function() {
AdminTest.toggleConfiguration();
});

86
app/widgets/Chat/Chat.php

@ -32,6 +32,7 @@ class Chat extends \Movim\Widget\Base
$this->addcss('chat.css');
$this->registerEvent('carbons', 'onMessage');
$this->registerEvent('message', 'onMessage');
$this->registerEvent('presence', 'onPresence', 'chat');
$this->registerEvent('retracted', 'onRetracted');
$this->registerEvent('receiptack', 'onMessageReceipt');
$this->registerEvent('displayed', 'onMessage', 'chat');
@ -51,6 +52,17 @@ class Chat extends \Movim\Widget\Base
$this->registerEvent('notification_counter_clear', 'onNotificationCounterClear');
}
public function onPresence($packet)
{
if ($packet->content && $jid = $packet->content->jid) {
$arr = explode('|', (new Notification)->getCurrent());
if (isset($arr[1]) && $jid == $arr[1] && !$packet->content->muc) {
$this->ajaxGetHeader($jid);
}
}
}
public function onMessageReceipt($packet)
{
$this->onMessage($packet, false, true);
@ -251,6 +263,18 @@ class Chat extends \Movim\Widget\Base
$this->event('chat_counter', $this->user->unreads());
}
/**
* Get the header
*/
public function ajaxGetHeader($jid, $muc = false)
{
$this->rpc(
'MovimTpl.fill',
'#' . cleanupId($jid.'_header'),
$this->prepareHeader($jid, $muc)
);
}
/**
* @brief Get a discussion
* @param string $jid
@ -726,35 +750,9 @@ class Chat extends \Movim\Widget\Base
$view = $this->tpl();
$view->assign('jid', $jid);
$view->assign('muc', $muc);
$view->assign('smiley', $this->call('ajaxSmiley'));
$view->assign('emoji', prepareString('😀'));
$view->assign('muc', $muc);
$view->assign('anon', false);
$view->assign(
'info',
\App\Info::where('server', $this->user->session->host)
->where('node', '')
->first()
);
if ($muc) {
$view->assign('room', $jid);
$view->assign('conference', $this->user->session->conferences()
->where('conference', $jid)
->with('info')
->first());
$mucinfo = \App\Info::where('server', explodeJid($jid)['server'])
->where('node', '')
->first();
if ($mucinfo && !empty($mucinfo->abuseaddresses)) {
$view->assign('info', $mucinfo);
}
} else {
$view->assign('roster', $this->user->session->contacts()->where('jid', $jid)->first());
$view->assign('contact', \App\Contact::firstOrNew(['id' => $jid]));
}
return $view->draw('_chat');
}
@ -1079,6 +1077,40 @@ class Chat extends \Movim\Widget\Base
return $view->draw('_chat_reactions');
}
public function prepareHeader($jid, $muc = false)
{
$view = $this->tpl();
$view->assign('jid', $jid);
$view->assign('muc', $muc);
$view->assign(
'info',
\App\Info::where('server', $this->user->session->host)
->where('node', '')
->first()
);
$view->assign('anon', false);
if ($muc) {
$view->assign('conference', $this->user->session->conferences()
->where('conference', $jid)
->with('info')
->first());
$mucinfo = \App\Info::where('server', explodeJid($jid)['server'])
->where('node', '')
->first();
if ($mucinfo && !empty($mucinfo->abuseaddresses)) {
$view->assign('info', $mucinfo);
}
} else {
$view->assign('roster', $this->user->session->contacts()->where('jid', $jid)->first());
$view->assign('contact', \App\Contact::firstOrNew(['id' => $jid]));
}
return $view->draw('_chat_header');
}
public function prepareEmpty()
{
$view = $this->tpl();

280
app/widgets/Chat/_chat.tpl

@ -1,277 +1,7 @@
<header class="fixed">
{if="$muc"}
<ul class="list middle">
<li>
<span class="primary icon active"
{if="!$anon"}
onclick="Chat_ajaxGet()"
{/if}>
{if="!$anon"}
<i class="material-icons">arrow_back</i>
{else}
<i class="material-icons">comments</i>
{/if}
</span>
{if="$conference"}
{$curl = $conference->getPhoto()}
{/if}
{if="$curl"}
<span class="primary icon bubble color active {$conference->name|stringToColor}
{if="!$conference->connected"}disabled{/if}"
style="background-image: url({$curl});"
onclick="Rooms_ajaxShowSubject('{$room|echapJS}')">
{else}
<span class="primary icon bubble color active {$conference->name|stringToColor}
{if="!$conference->connected"}disabled{/if}"
onclick="Rooms_ajaxShowSubject('{$room|echapJS}')">
{autoescape="off"}
{$conference->name|firstLetterCapitalize|addEmojis}
{/autoescape}
{/if}
{if="$conference->connected"}
{$count = $conference->presences()->count()}
<span class="counter alt">
{if="$count > 99"}99+{else}{$count}{/if}
</span>
{/if}
</span>
{if="$conference && $conference->info && $conference->info->related"}
{$related = $conference->info->related}
<span
class="control icon active"
title="{$c->__('page.communities')} · {$related->name}"
onclick="MovimUtils.redirect('{$c->route('community', [$related->server, $related->node])}')">
<i class="material-icons">group_work</i>
</span>
{/if}
<span class="control icon show_context_menu active {if="!$conference->connected"}disabled{/if}">
<i class="material-icons">more_vert</i>
</span>
<div>
{if="$conference && $conference->name"}
<p class="line active" title="{$room|echapJS}" onclick="Rooms_ajaxShowSubject('{$room|echapJS}')">
{$conference->name}
</p>
{else}
<p class="line active" onclick="Rooms_ajaxShowSubject('{$room|echapJS}')">
{$room|echapJS}
</p>
{/if}
<p class="compose line" id="{$jid|cleanupId}-state"></p>
{if="$conference && !$conference->connected"}
<p>{$c->__('button.connecting')}…</p>
{elseif="$conference && $conference->subject"}
<p class="line active" title="{$conference->subject}" onclick="Rooms_ajaxShowSubject('{$room|echapJS}')">
{if="$conference->info && $conference->info->mucpublic"}
<span title="{$c->__('room.public_muc_text')}">
{$c->__('room.public_muc')} <i class="material-icons">wifi_tethering</i>
</span>
·
{/if}
{if="$conference->info && !$conference->info->mucsemianonymous"}
<span title="{$c->__('room.nonanonymous_muc_text')}">
{$c->__('room.nonanonymous_muc')} <i class="material-icons">face</i>
</span>
·
{/if}
{$conference->subject}
</p>
{else}
<p class="line active" id="{$jid|cleanupId}-state" onclick="Rooms_ajaxShowSubject('{$room|echapJS}')">
{if="$conference->info && $conference->info->mucpublic"}
<span title="{$c->__('room.public_muc_text')}">
{$c->__('room.public_muc')} <i class="material-icons">wifi_tethering</i>
</span>
·
{/if}
{if="$conference->info && !$conference->info->mucsemianonymous"}
<span title="{$c->__('room.nonanonymous_muc_text')}">
{$c->__('room.nonanonymous_muc')} <i class="material-icons">face</i>
</span>
·
{/if}
{$room|echapJS}
</p>
{/if}
</div>
</li>
</ul>
<ul class="list context_menu thin active">
{if="$conference->presence && !$anon"}
{if="$conference->presence->mucrole == 'moderator' || $conference->presence->mucaffiliation == 'owner'"}
<li class="subheader">
<span class="control icon">
<i class="material-icons">settings</i>
</span>
<div>
<p class="line">{$c->__('chatroom.administration')}</p>
</div>
</li>
{/if}
{if="$conference->presence->mucrole == 'moderator'"}
<li onclick="Rooms_ajaxGetAvatar('{$room|echapJS}')">
<div>
<p class="normal">{$c->__('page.avatar')}</p>
</div>
</li>
<li onclick="Rooms_ajaxGetSubject('{$room|echapJS}')">
<div>
<p class="normal">{$c->__('chatroom.subject')}</p>
</div>
</li>
{/if}
{if="$conference->presence->mucaffiliation == 'owner'"}
<li onclick="Chat_ajaxGetRoomConfig('{$room|echapJS}')">
<div>
<p class="normal">{$c->__('chatroom.administration')}</p>
</div>
</li>
<li class="divided" onclick="Rooms_ajaxAskDestroy('{$room|echapJS}')">
<div>
<p class="normal">{$c->__('button.destroy')}</p>
</div>
</li>
{/if}
{/if}
{if="!empty($info->abuseaddresses)"}
{$parsed = parse_url($info->abuseaddresses[0])}
{if="$parsed['scheme'] == 'xmpp'"}
{if="isset($parsed['query']) && $parsed['query'] == 'join'"}
<li onclick="MovimUtils.reload('{$c->route('chat', [$parsed['path'], 'room'])}')">
{else}
<li onclick="MovimUtils.reload('{$c->route('chat', $parsed['path'])}')">
{/if}
{else}
<li onclick="MovimUtils.reload('{$info->abuseaddresses[0]}')">
{/if}
<div>
<p class="normal">{$c->__('chat.report_abuse')}</p>
</div>
</li>
{/if}
<li class="divided" onclick="Rooms_ajaxAskInvite('{$room|echapJS}');">
<div>
<p class="normal">{$c->__('room.invite')}</p>
</div>
</li>
<li onclick="Rooms_ajaxAdd('{$room|echapJS}');">
<div>
<p class="normal">{$c->__('chatroom.config')}</p>
</div>
</li>
{if="!$anon"}
<li onclick="Rooms_ajaxRemoveConfirm('{$room|echapJS}')">
<div>
<p class="normal">{$c->__('button.delete')}</p>
</div>
</li>
{/if}
<li onclick="Rooms_ajaxExit('{$room|echapJS}'); {if="$anon"}Presence_ajaxLogout(){/if}">
<div>
<p class="normal">{$c->__('status.disconnect')}</p>
</div>
</li>
</span>
</ul>
{else}
<ul class="list middle fill">
<li id="chat_header">
<span onclick="Chat_ajaxGet()" class="primary icon active">
<i class="material-icons">arrow_back</i>
</span>
{$url = $contact->getPhoto()}
{if="$url"}
<span class="primary icon bubble active color
{if="$roster && $roster->presence"}status {$roster->presence->presencekey}{/if}"
onclick="ChatActions_ajaxGetContact('{$contact->jid|echapJS}')">
<img src="{$url}">
</span>
{else}
<span class="primary icon bubble active color
{$contact->jid|stringToColor}
{if="$roster && $roster->presence"}status {$roster->presence->presencekey}{/if}"
onclick="ChatActions_ajaxGetContact('{$contact->jid|echapJS}')">
{if="$roster"}
{$roster->truename|firstLetterCapitalize}
{else}
{$contact->truename|firstLetterCapitalize}
{/if}
</span>
{/if}
<span
title="{$c->__('button.close')}"
class="control icon active"
onclick="Chats_ajaxClose('{$jid|echapJS}', true);">
<i class="material-icons">close</i>
</span>
<span class="control icon show_context_menu active">
<i class="material-icons">more_vert</i>
</span>
<div>
<p class="line active" onclick="ChatActions_ajaxGetContact('{$contact->jid|echapJS}')">
{if="$roster"}
{$roster->truename}
{else}
{$contact->truename}
{/if}
</p>
<p class="compose line active" id="{$jid|cleanupId}-state" onclick="ChatActions_ajaxGetContact('{$contact->jid|echapJS}')"></p>
<p class="line active" onclick="ChatActions_ajaxGetContact('{$contact->jid|echapJS}')">{$contact->jid}</p>
</div>
</li>
</ul>
<ul class="list context_menu active">
{if="!$contact->isFromMuc()"}
<li onclick="MovimUtils.reload('{$c->route('contact', $contact->jid)}')">
<div>
<p class="normal">{$c->__('chat.profile')}</p>
</div>
</li>
{/if}
<li class="on_mobile" onclick="Chat.editPrevious()">
<div>
<p class="normal">{$c->__('chat.edit_previous')}</p>
</div>
</li>
<li onclick="Chat_ajaxClearHistory('{$contact->jid|echapJS}')">
<div>
<p class="normal">{$c->__('chat.clear')}</p>
</div>
</li>
{if="!empty($info->abuseaddresses)"}
{$parsed = parse_url($info->abuseaddresses[0])}
{if="$parsed['scheme'] == 'xmpp'"}
{if="isset($parsed['query']) && $parsed['query'] == 'join'"}
<li onclick="MovimUtils.reload('{$c->route('chat', [$parsed['path'], 'room'])}')">
{else}
<li onclick="MovimUtils.reload('{$c->route('chat', $parsed['path'])}')">
{/if}
{else}
<li onclick="MovimUtils.reload('{$info->abuseaddresses[0]}')">
{/if}
<div>
<p class="normal">{$c->__('chat.report_abuse')}</p>
</div>
</li>
{/if}
</ul>
{/if}
<header class="fixed" id="{$jid|cleanupId}-header">
{autoescape="off"}
{$c->prepareHeader($jid, $muc)}
{/autoescape}
</header>
<div id="{$jid|cleanupId}-discussion" class="contained {if="$muc"}muc{/if}" data-muc="{$muc}">
@ -292,7 +22,7 @@
<div class="chat_box">
<ul class="list thin fill">
<li class="emojis"></li>
<li class="{if="$muc && !$conference->connected"}disabled{/if}">
<li>
<span class="primary icon gray primary_action" onclick="Stickers_ajaxShow('{$jid}')">
<i class="material-icons">mood</i>
</span>

11
app/widgets/Chat/chat.js

@ -1049,6 +1049,15 @@ if (typeof Upload != 'undefined') {
});
}
movimAddFocus(function() {
if (MovimWebsocket.connection) {
var jid = MovimUtils.urlParts().params[0];
var room = (MovimUtils.urlParts().params[1] === 'room');
Chat_ajaxGetHeader(jid, room);
}
});
document.addEventListener('focus', function() {
var textarea = Chat.getTextarea();
if (textarea) textarea.focus();
@ -1058,7 +1067,7 @@ window.addEventListener('resize', function() {
Chat.scrollRestore();
});
movim_add_onload(function() {
movimAddOnload(function() {
Chat.touchEvents();
});

2
app/widgets/Dialog/dialog.js

@ -23,7 +23,7 @@ var Dialog = {
},
}
movim_add_onload(function() {
movimAddOnload(function() {
document.body.addEventListener('click', Dialog.toggle, false);
document.addEventListener('keydown', function(e) {
if (Dialog.filled()

2
app/widgets/Draw/draw.js

@ -428,4 +428,4 @@ Upload.progress((percent) => {
}
});
movim_add_onload(() => Draw_ajaxHttpGet());
movimAddOnload(() => Draw_ajaxHttpGet());

2
app/widgets/Drawer/drawer.js

@ -13,7 +13,7 @@ var Drawer = {
}
}
movim_add_onload(function() {
movimAddOnload(function() {
document.body.addEventListener('click', Drawer.toggle, false);
document.addEventListener('keydown', function(e) {
if (Drawer.filled()

2
app/widgets/Login/login.js

@ -82,7 +82,7 @@ MovimWebsocket.register(function()
}
});
movim_add_onload(function() {
movimAddOnload(function() {
// We had the autocomplete system
var login = document.querySelector('input#username');
login.addEventListener('input', function() {

11
app/widgets/Notification/notification.js

@ -189,6 +189,12 @@ var Notification = {
Android.showNotification(title, body, picture, action);
return;
}
},
focus : function() {
if (Notification.focused == false) {
Notification.focused = true;
Notification.current(Notification.notifs_key);
}
}
}
@ -214,9 +220,8 @@ if (typeof MovimWebsocket != 'undefined') {
Notification_ajaxCurrent('blurred');
});
window.addEventListener('focus', function() {
Notification.focused = true;
Notification.current(Notification.notifs_key);
movimAddFocus(function() {
Notification.focus();
});
});
}

2
app/widgets/Preview/preview.js

@ -1,4 +1,4 @@
movim_add_onload(function() {
movimAddOnload(function() {
document.addEventListener('keydown', function(e) {
if (document.querySelector('#preview').innerHTML != '' && e.keyCode == 27) {
Preview_ajaxHide();

39
public/scripts/movim_base.js

@ -5,17 +5,29 @@
*/
var onloaders = [];
var onfocused = [];
var isFocused = false;
/**
* @brief Adds a function to the onload event
* @param function func
*/
function movim_add_onload(func) {
function movimAddOnload(func) {
if (typeof(func) === "function") {
onloaders.push(func);
}
}
/**
* @brief Adds a function to focus event
* @param function func
*/
function movimAddFocus(func) {
if (typeof(func) === "function") {
onfocused.push(func);
}
}
/**
* @brief Function that is run once the page is loaded.
*/
@ -24,3 +36,28 @@ document.addEventListener("DOMContentLoaded", () => {
onloaders[i]();
}
});
/**
* The focus event doesn't seems to be triggered all the time ¯\_()_/¯
*/
window.addEventListener('mouseover', function() {
if (isFocused) return;
isFocused = true;
for (var i = 0; i < onfocused.length; i++) {
onfocused[i]();
}
});
window.addEventListener('focus', function() {
if (isFocused) return;
isFocused = true;
for (var i = 0; i < onfocused.length; i++) {
onfocused[i]();
}
});
window.addEventListener('blur', function() {
isFocused = false;
});

2
public/scripts/movim_tpl.js

@ -155,7 +155,7 @@ var MovimTpl = {
}
};
movim_add_onload(function() {
movimAddOnload(function() {
MovimTpl.touchEvents();
document.body.addEventListener('click', MovimTpl.toggleContextMenu, false);
});

3
src/Movim/ChatStates.php

@ -30,7 +30,8 @@ class ChatStates
if (array_key_exists($jid, $this->_composing)) {
if ($resource !== null) {
if (array_key_exists($resource, $this->_composing[$jid])
if (is_array($this->_composing[$jid])
&& array_key_exists($resource, $this->_composing[$jid])
&& $this->_composing[$jid][$resource] instanceof Timer) {
$loop->cancelTimer($this->_composing[$jid][$resource]);
unset($this->_composing[$jid][$resource]);

Loading…
Cancel
Save