Browse Source

Move the file message related logic to the Message model

Refactor the Stickers and File display and cleanup the related CSS
pull/1185/merge
Timothée Jaussoin 2 years ago
parent
commit
d0b4e2bffc
  1. 2
      CHANGELOG.md
  2. 37
      app/Message.php
  3. 56
      app/widgets/Chat/Chat.php
  4. 187
      app/widgets/Chat/chat.css
  5. 97
      app/widgets/Chat/chat.js
  6. 2
      app/widgets/ChatActions/ChatActions.php
  7. 4
      public/theme/css/color.css
  8. 4
      public/theme/css/fonts.css
  9. 84
      public/theme/css/listn.css

2
CHANGELOG.md

@ -6,6 +6,8 @@ v0.22.6 (trunk)
* Add the message menu in the Picture preview
* Move the info logic from the JS to the CSS
* Refactor and cleanup the info for stickers messages
* Move the file message related logic to the Message model
* Refactor the Stickers and File display and cleanup the related CSS
v0.22.5
---------------------------

37
app/Message.php

@ -101,6 +101,38 @@ class Message extends Model
$file['cleansize'] = humanSize((float)$file['size']);
}
if (
\array_key_exists('type', $file)
&& typeIsPicture($file['type'])
) {
$file['preview'] = [
'thumb' => protectPicture($file['uri']),
'url' => $file['uri'],
'picture' => true
];
}
$url = parse_url($file['uri']);
if (\array_key_exists('host', $url)) {
$file['host'] = $url['host'];
switch ($url['host']) {
case 'i.imgur.com':
$thumb = getImgurThumbnail($file['uri']);
if ($thumb) {
$file['preview'] = [
'url' => $file['uri'],
'thumb' => $thumb,
'picture' => true
];
}
break;
}
}
$file['id'] = hashId($file['uri']);
return $file;
}
@ -629,6 +661,11 @@ class Message extends Model
return ($this->user_id == $this->jidfrom);
}
public function isClassic(): bool
{
return in_array($this->type, ['chat', 'groupchat']);
}
public function retract()
{
$this->retracted = true;

56
app/widgets/Chat/Chat.php

@ -856,16 +856,18 @@ class Chat extends \Movim\Widget\Base
*/
public function ajaxHttpDaemonReply($mid)
{
$m = $this->user->messages()
$message = $this->user->messages()
->where('mid', $mid)
->first();
if (($m->isMuc() && $m->stanzaid)
|| (!$m->isMuc() && $m->messageid)
|| isset($m->thread)
if (
$message->isClassic()
&& (($message->isMuc() && $message->stanzaid)
|| (!$message->isMuc() && $message->messageid)
|| isset($message->thread))
) {
$view = $this->tpl();
$view->assign('message', $m);
$view->assign('message', $message);
$this->rpc('MovimTpl.fill', '#reply', $view->draw('_chat_reply'));
$this->rpc('Chat.focus');
}
@ -1145,7 +1147,6 @@ class Chat extends \Movim\Widget\Base
if ($unreadsCount > 0) {
$this->rpc('Chat.insertSeparator', $unreadsCount);
}
}
public function prepareMessage(&$message, $jid = null)
@ -1229,7 +1230,7 @@ class Chat extends \Movim\Widget\Base
if (
$emoji->isSingleEmoji()
&& !isset($message->html)
&& in_array($message->type, ['chat', 'groupchat'])
&& $message->isClassic()
) {
$message->sticker = [
'url' => $emoji->getLastSingleEmojiURL(),
@ -1242,47 +1243,6 @@ class Chat extends \Movim\Widget\Base
// Attached file
if (isset($message->file)) {
// We proxify pictures links even if they are advertized as small ones
if (
\array_key_exists('type', $message->file)
&& typeIsPicture($message->file['type'])
&& $message->file['size'] <= SMALL_PICTURE_LIMIT * 4
) {
$message->sticker = [
'thumb' => protectPicture($message->file['uri']),
'url' => $message->file['uri'],
'picture' => true
];
}
// Set an id for all the files
$file = $message->file;
$file['id'] = hashId($file['uri']);
$message->file = $file;
$url = parse_url($message->file['uri']);
// Other image websites
if (\array_key_exists('host', $url)) {
$file = $message->file;
$file['host'] = $url['host'];
$message->file = $file;
switch ($url['host']) {
case 'i.imgur.com':
$thumb = getImgurThumbnail($message->file['uri']);
if ($thumb) {
$message->sticker = [
'url' => $message->file['uri'],
'thumb' => $thumb,
'picture' => true
];
}
break;
}
}
// Build cards for the URIs
$uri = explodeXMPPURI($message->file['uri']);

187
app/widgets/Chat/chat.css

@ -298,50 +298,30 @@ main:not(.enabled) #chat_widget {
margin: 0;
}
#chat_widget li img:not(.emoji):not(.hfr) {
#chat_widget li img:not(.emoji) {
max-height: 30rem;
max-width: 100%;
display: block;
}
#chat_widget li div.bubble.sticker.file img.active:hover {
cursor: pointer;
}
#chat_widget li div.bubble.sticker img:not(.emoji):not(.hfr),
#chat_widget ul li div.bubble.file video {
border-radius: 0.75rem;
width: auto;
max-height: 150px;
}
#chat_widget ul li div.bubble.file video {
display: block;
max-height: 200px;
background-color: rgba(var(--movim-font), 0.15);
}
#chat_widget ul li div.bubble.file video:not(.gif) {
height: 200px;
max-width: 100%;
#chat_widget li img.active {
transition: opacity 0.1s ease-in-out;
}
li div.bubble.sticker.file img:not(.emoji):not(.hfr) {
max-height: 170px;
object-fit: cover;
transition: opacity 0.2s ease-in-out;
background-color: rgba(var(--movim-gray), 0.1);
background-image: url(/theme/img/broken_image.svg);
background-position: center;
background-repeat: no-repeat;
#chat_widget li img.active:hover {
cursor: pointer;
opacity: 0.6;
}
#chat_widget li.oppose div.bubble.sticker.file img:not(.emoji):not(.hfr) {
float: right;
#chat_widget li img.active:active {
opacity: 0.8;
}
#chat_widget li.oppose div.bubble.sticker.file img:not(.emoji):not(.hfr) + div.file {
clear: right;
#chat_widget li img.sticker {
max-height: 150px;
border-radius: 0.75rem;
margin-bottom: 3rem;
}
#chat_widget ul.list:after {
@ -432,43 +412,6 @@ li div.bubble.sticker.file img:not(.emoji):not(.hfr) {
border-radius: 0 3px 3px;
}
/* File preview */
div.file:not(.bubble) {
min-height: 2rem;
word-break: break-all;
margin-right: 5rem;
}
#chat_widget div.file:not(.bubble) a:not(.button) {
padding: 1rem 0;
}
#chat_widget div.file:not(.bubble) div:not(.audio_player) p {
max-width: 31rem;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
margin-bottom: -0.5rem;
}
#chat_widget div.file:not(.bubble) p ~ span.host:before {
content: '';
height: 0;
display: block;
}
#chat_widget div.file:not(.bubble) span.size:before {
content: '–';
margin: 0 0.75rem;
}
#chat_widget audio {
border-radius: 0.5rem;
width: 100%;
min-width: 23rem;
}
/* Parent */
#chat_widget div.parent {
@ -504,16 +447,31 @@ div.file:not(.bubble) {
white-space: pre-wrap;
}
/* Date element */
li div.bubble:after {
content: attr(data-publishedprepared);
line-height: 1.5rem;
right: 1rem;
bottom: 1rem;
position: absolute;
pointer-events: none;
}
li div.bubble.file:not(.audio):after {
right: 0;
bottom: 0.5rem;
}
/* Emojis */
#chat_widget .bubble ul.reactions {
margin-bottom: -0.25rem;
margin-right: 5rem;
display: flex;
}
#chat_widget .bubble:not(.file) ul.reactions {
margin-top: 0.25rem;
#chat_widget .bubble.file .reactions {
margin-right: 4.5rem;
margin-top: -2rem;
}
#chat_widget .bubble div span.reaction,
@ -563,7 +521,7 @@ div.file:not(.bubble) {
margin-right: -7rem;
}
#chat_widget .bubble:not(.sticker):not(.file) > div:last-child {
#chat_widget .bubble:not(.file) > div:last-child {
padding-right: 12rem;
}
@ -579,12 +537,12 @@ div.file:not(.bubble) {
display: inline-flex;
position: absolute;
left: 100%;
transform: translate(-0.75rem, -0.25rem);
transform: translate(-0.5rem, -0.5rem);
}
#chat_widget li .bubble.file div:hover ul.reactions:empty ~ span.reaction,
#chat_widget li .bubble.file div:not(.encrypted):hover span.reply {
transform: translate(-0.75rem, -7.25rem);
transform: translate(-0.5rem, -5.5rem);
}
#chat_widget li .bubble div:hover ul.reactions:not(:empty) ~ span.reply {
@ -610,28 +568,91 @@ div.file:not(.bubble) {
order: 0;
}
/* File element */
li .bubble.file {
margin-bottom: 1.5rem;
}
li .bubble.file div.file {
margin-bottom: 3rem;
}
li .bubble.file span.resource + div.file {
margin-top: 1rem;
}
li .bubble.file div.file img,
li .bubble.file div.file video {
display: block;
border-radius: 0.75rem;
width: auto;
max-height: 200px;
margin-bottom: 1rem;
}
li div.bubble.file div.file img {
max-height: 170px;
min-width: 12rem;
object-fit: cover;
transition: opacity 0.2s ease-in-out;
background-color: rgba(var(--movim-gray), 0.1);
background-image: url(/theme/img/broken_image.svg);
background-position: center;
background-repeat: no-repeat;
}
li div.bubble.file video {
max-height: 200px;
background-color: rgba(var(--movim-font), 0.15);
max-width: 100%;
}
li.oppose .bubble.file div.file img,
li.oppose .bubble.file div.file video {
display: block;
margin-right: 0;
margin-left: auto;
}
li .bubble.file div.file[data-type="image/gif"]:after {
color: white;
font-family: 'Material Icons';
text-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);
position: absolute;
font-size: 5rem;
line-height: 5rem;
content: "\e908";
top: 0;
left: 0.5rem;
display: block;
pointer-events: none;
}
/* Message Info */
#chat_widget .bubble .message span.info:after {
display: inline-block;
font-family: 'Material Icons';
vertical-align: middle;
}
#chat_widget .bubble.sticker .message p:before {
#chat_widget .bubble.file .message div.file:before {
display: inline-block;
position: absolute;
bottom: 1rem;
top: 1rem;
right: 1rem;
font-family: 'Material Icons';
color: white;
text-shadow: 0 0 1rem rgba(0, 0, 0, 0.85);
}
#chat_widget .bubble.sticker .message.delivered p:before,
#chat_widget .bubble.file .message.delivered div.file:before,
#chat_widget .bubble .message.delivered span.info:after {
content: '\e5ca';
}
#chat_widget .bubble.sticker .message.displayed p:before,
#chat_widget .bubble.file .message.displayed div.file:before,
#chat_widget .bubble .message.displayed span.info:after {
content: '\e877';
}
@ -640,7 +661,7 @@ div.file:not(.bubble) {
content: '\e897';
}
#chat_widget .bubble.sticker .message.edited.delivered p:before,
#chat_widget .bubble.file .message.edited.delivered div.file:before,
#chat_widget .bubble .message.edited.delivered span.info:after {
content: '\e3c9 \e5ca';
}
@ -649,7 +670,7 @@ div.file:not(.bubble) {
content: '\e897 \e5ca';
}
#chat_widget .bubble.sticker .message.edited.displayed p:before,
#chat_widget .bubble.file .message.edited.displayed div.file:before,
#chat_widget .bubble .message.edited.displayed span.info:after {
content: '\e3c9 \e877';
}
@ -658,7 +679,7 @@ div.file:not(.bubble) {
content: '\e897 \e877';
}
#chat_widget .bubble.sticker .message span.info:after {
#chat_widget .bubble.file .message span.info:after {
display: none;
}

97
app/widgets/Chat/chat.js

@ -606,7 +606,7 @@ var Chat = {
discussion.onscroll = function () {
if (this.scrollTop < 1
&& discussion.querySelectorAll('ul li div.bubble p').length >= Chat.pagination && Chat.currentDateTime) {
&& discussion.querySelectorAll('li div.bubble p').length >= Chat.pagination && Chat.currentDateTime) {
Chat_ajaxGetHistory(
Chat.getTextarea().dataset.jid,
Chat.currentDateTime,
@ -804,7 +804,7 @@ var Chat = {
);
},
setMessagePressBehaviour: function () {
document.querySelectorAll('#chat_widget ul li div.bubble:not(.sticker):not(.file) > div.message').forEach(message => {
document.querySelectorAll('#chat_widget li div.bubble:not(.file) > div.message').forEach(message => {
message.onmousedown = function (e) {
setTimeout(() => {
if (e.button == 0
@ -818,7 +818,7 @@ var Chat = {
}
});
document.querySelectorAll('#chat_widget ul li div.bubble.file > div.message').forEach(message => {
document.querySelectorAll('#chat_widget li div.bubble.file > div.message').forEach(message => {
if (card = message.querySelector('ul.list.card > li > div')) {
card.onclick = function (e) {
ChatActions_ajaxShowMessageDialog(message.dataset.mid);
@ -1063,27 +1063,6 @@ var Chat = {
p.innerHTML = data.body;
}
if (data.sticker != null && data.retracted == false) {
bubble.querySelector('div.bubble').classList.add('sticker');
p.appendChild(Chat.getStickerHtml(data));
if (data.file != null) {
p.dataset.type = data.file.type;
p.classList.add('previewable');
}
}
if (data.file != null && data.card === undefined && data.file.type !== 'xmpp' && data.retracted == false) {
bubble.querySelector('div.bubble').classList.add('file');
// Ugly fix to clear the paragraph if the file contains a similar link
if (p.querySelector('a') && p.querySelector('a').href == data.file.uri) {
p.querySelector('a').remove();
}
p.appendChild(Chat.getFileHtml(data.file, data.sticker));
}
if (data.replaceid) {
msg.classList.add('edited');
}
@ -1109,6 +1088,21 @@ var Chat = {
msg.appendChild(resourceSpan);
}
if (data.sticker != null && data.retracted == false) {
bubble.querySelector('div.bubble').classList.add('file');
p.appendChild(Chat.getStickerHtml(data));
} else if (data.file != null && data.card === undefined && data.file.type !== 'xmpp' && data.retracted == false) {
bubble.querySelector('div.bubble').classList.add('file');
// Ugly fix to clear the paragraph if the file contains a similar link
if (p.querySelector('a') && p.querySelector('a').href == data.file.uri) {
p.querySelector('a').remove();
}
msg.appendChild(Chat.getFileHtml(data.file, data));
}
if (data.published) {
info.title = data.published;
}
@ -1170,7 +1164,7 @@ var Chat = {
}
if (data.sticker != null && data.retracted == false) {
msg.parentElement.classList.add('sticker');
msg.parentElement.classList.add('sticker', 'file');
} else {
msg.parentElement.classList.remove('sticker');
}
@ -1274,6 +1268,8 @@ var Chat = {
},
getStickerHtml: function (data) {
var img = document.createElement('img');
img.classList.add('sticker');
if (data.sticker.url) {
if (data.sticker.thumb) {
img.setAttribute('src', data.sticker.thumb);
@ -1289,15 +1285,6 @@ var Chat = {
}
}
if (data.sticker.title) {
img.title = data.sticker.title;
}
if (data.sticker.picture) {
img.classList.add('active');
img.setAttribute('onclick', 'Preview_ajaxHttpShow("' + data.sticker.url + '", ' + data.mid + ')');
}
return img;
},
getCardHtml: function (card) {
@ -1311,11 +1298,42 @@ var Chat = {
return ul;
},
getFileHtml: function (file, sticker) {
getFileHtml: function (file, data) {
var div = document.createElement('div');
div.setAttribute('class', 'file');
if (file.name) {
div.dataset.type = file.type;
if (file.preview) {
var img = document.createElement('img');
if (file.preview.url) {
if (file.preview.thumb) {
img.setAttribute('src', file.preview.thumb);
} else {
img.setAttribute('src', file.preview.url);
}
if (file.preview.width) img.setAttribute('width', file.preview.width);
if (file.preview.height) {
img.setAttribute('height', file.preview.height);
} else {
img.setAttribute('height', '170');
}
}
if (file.preview.title) {
img.title = file.preview.title;
}
if (file.preview.picture) {
img.classList.add('active');
img.setAttribute('onclick', 'Preview_ajaxHttpShow("' + file.preview.url + '", ' + data.mid + ')');
}
div.appendChild(img);
}
if (file.type == 'audio/ogg' || file.type == 'audio/opus' || file.type == 'audio/mpeg') {
div.appendChild(Chat.getAudioPlayer(file));
} else if (file.type == 'video/webm' || file.type == 'video/mp4') {
@ -1328,7 +1346,7 @@ var Chat = {
return div;
}
var a = document.createElement('a');
/*var a = document.createElement('a');
if (sticker == null) {
var link = document.createElement('p');
@ -1336,13 +1354,14 @@ var Chat = {
link.setAttribute('title', file.name);
a.appendChild(link);
}
a.setAttribute('href', file.uri);
a.setAttribute('target', '_blank');
a.setAttribute('rel', 'noopener');
div.appendChild(a);
div.appendChild(a);*/
if (file.host) {
/*if (file.host) {
var host = document.createElement('span');
host.innerHTML = file.host;
host.setAttribute('class', 'host');
@ -1356,7 +1375,7 @@ var Chat = {
span.setAttribute('class', 'size');
a.appendChild(span);
}
}*/
}
return div;

2
app/widgets/ChatActions/ChatActions.php

@ -59,7 +59,7 @@ class ChatActions extends \Movim\Widget\Base
->where('mid', $mid)
->first();
if ($message && in_array($message->type, ['chat', 'groupchat'])) {
if ($message && $message->isClassic()) {
$view = $this->tpl();
$view->assign('message', $message);

4
public/theme/css/color.css

@ -46,7 +46,7 @@ ul.list li span.control.divided:before {
}
label, span.info,
ul li div.bubble:after,
li div.bubble:after,
table tr th {
color: rgba(var(--movim-font), 0.54);
}
@ -106,7 +106,7 @@ span.icon span.counter.alt {
.button.indigo, .icon.indigo, span.resource.indigo { color: var(--p-indigo); }
.button.blue, .icon.blue , span.resource.blue { color: var(--p-blue); }
.button.green, .icon.green , span.resource.green { color: var(--p-green); }
ul li div.bubble.moderator:after,
li div.bubble.moderator:after,
ul li div > p > span.moderator,
.button.orange, .icon.orange, span.resource.orange { color: var(--p-orange); }
.button.yellow, .icon.yellow, span.resource.yellow { color: #FBC02D; }

4
public/theme/css/fonts.css

@ -26,7 +26,3 @@ ul.list p + p .emoji {
height: 5rem;
margin: 0;
}
.hfr {
display: inline-block;
}

84
public/theme/css/listn.css

@ -72,7 +72,7 @@ ul.list li>span.bubble.active:hover {
}
ul.list li>span:not(.bubble).active:hover,
ul.list li div.bubble:not(.sticker):not(.file):hover {
ul.list li div.bubble:not(.file):hover {
cursor: pointer;
background-color: rgba(var(--movim-element-action), 0.1);
}
@ -91,7 +91,7 @@ ul.list li>span.bubble.active:active {
}
ul.list li>span:not(.bubble).active:active,
ul.list li div.bubble:not(.sticker):not(.file):active {
ul.list li div.bubble:not(.file):active {
cursor: pointer;
background-color: rgba(var(--movim-element-action), 0.2);
}
@ -236,7 +236,7 @@ ul.list li>div>p>span.second.sticked {
}
ul.list li>div>p>span.info,
ul li div.bubble:after {
li div.bubble:after {
float: right;
font-size: 1.5rem;
margin-left: 0.5rem;
@ -380,7 +380,7 @@ ul.tabs>li.active {
/* Bubble */
ul li div.bubble {
li div.bubble {
position: relative;
box-sizing: border-box;
display: block;
@ -392,12 +392,12 @@ ul li div.bubble {
transition: background 0.3s ease, box-shadow 0.3s ease;
}
ul li div.bubble div[dir="rtl"] {
li div.bubble div[dir="rtl"] {
text-align: right;
}
ul li div.bubble:not(.sticker):not(.file),
ul li div.bubble.file div.audio_player {
li div.bubble:not(.file),
li div.bubble.file div.audio_player {
padding: 1rem 1rem 1rem 1.5rem;
border-radius: 0 1rem 1rem;
line-height: 2.75rem;
@ -405,21 +405,20 @@ ul li div.bubble.file div.audio_player {
margin-bottom: 1.5rem;
}
ul li div.bubble.sticker,
ul li div.bubble.file {
margin-bottom: 1rem;
li div.bubble.file div.audio_player {
margin-bottom: 3rem;
}
ul li div.bubble ul.card p:not(.line):not(:last-child) {
li div.bubble ul.card p:not(.line):not(:last-child) {
display: block;
}
ul li div.bubble ul.card p:last-child {
li div.bubble ul.card p:last-child {
white-space: inherit;
display: block;
}
ul li div.bubble p {
li div.bubble p {
overflow: hidden;
display: inline;
max-width: 100%;
@ -431,31 +430,31 @@ ul li div.bubble p {
position: relative;
}
ul li div.bubble p:empty {
li div.bubble p:empty {
display: none;
}
ul li div.bubble:not(.file) p {
li div.bubble:not(.file) p {
margin-right: 1rem;
}
ul li div.bubble p.retracted,
ul li div.bubble p.encrypted {
li div.bubble p.retracted,
li div.bubble p.encrypted {
opacity: 0.5;
}
ul li div.bubble p.previewable {
li div.bubble p.previewable {
display: block;
min-width: 0;
margin-bottom: 0.5rem;
}
ul li div.bubble p.code {
li div.bubble p.code {
display: inline-block;
margin: 0;
}
ul li div.bubble span.resource {
li div.bubble span.resource {
display: none;
}
@ -464,16 +463,12 @@ ul li:not(.oppose):not(.sequel) div.bubble div:first-child span.resource {
line-height: 2.5rem;
}
ul li.oppose div.bubble.file {
word-break: break-all;
}
ul li div.bubble:not(.sticker):not(.file),
ul li div.bubble.file div.audio_player {
li div.bubble:not(.file),
li div.bubble.file div.audio_player {
background-color: rgb(var(--movim-background-main));
}
ul li.oppose div.bubble:not(.sticker):not(.file),
ul li.oppose div.bubble:not(.file),
ul li.oppose div.bubble.file div.audio_player {
background-color: rgba(var(--movim-background-main), 0.5);
border-color: rgba(var(--movim-background-main), 0.5);
@ -481,36 +476,15 @@ ul li.oppose div.bubble.file div.audio_player {
padding: 1rem 1rem 1rem 1.5rem;
}
ul li div.bubble.file div.audio_player,
ul li.oppose div.bubble.file div.audio_player {
padding: 0.5rem;
margin-bottom: 0.25rem;
}
ul li div.bubble p i.icon {
li div.bubble p i.icon {
margin-right: 0.25rem;
}
ul li div.bubble:after {
content: attr(data-publishedprepared);
line-height: 1.5rem;
right: 1rem;
bottom: 1rem;
position: absolute;
pointer-events: none;
}
ul li div.bubble.sticker:after,
ul li div.bubble.file:after {
right: 0;
bottom: 0;
}
ul li .quote {
font-style: italic;
}
ul li div.bubble:not(.sticker):not(.file):before {
li div.bubble:not(.file):before {
content: "";
position: absolute;
top: 0;
@ -525,17 +499,17 @@ ul li div.bubble:not(.sticker):not(.file):before {
transition: background-color 0.3s ease;
}
ul li div.bubble:not(.sticker):not(.file):hover:before,
ul li.oppose div.bubble:not(.sticker):not(.file):hover:before {
li div.bubble:not(.file):hover:before,
ul li.oppose div.bubble:not(.file):hover:before {
background-color: rgba(var(--movim-element-action), 0.1);
}
ul li div.bubble:not(.sticker):not(.file):active:before,
ul li.oppose div.bubble:not(.sticker):not(.file):active:before {
li div.bubble:not(.file):active:before,
ul li.oppose div.bubble:not(.file):active:before {
background-color: rgba(var(--movim-element-action), 0.2);
}
ul li.oppose div.bubble:not(.sticker):not(.file):before {
ul li.oppose div.bubble:not(.file):before {
left: initial;
right: -1.6rem;
background-color: rgba(var(--movim-background-main), 0.5);

Loading…
Cancel
Save