Commit 942d102e authored by Sébastien Blin's avatar Sébastien Blin Committed by Andreas Traczyk

chatview: add invitation top bar when necessary

Change-Id: I70d3e10746ed8aa68b351e6d9e03516b82fab3b3
Gitlab: #420Reviewed-by: Andreas Traczyk's avatarAndreas Traczyk <andreas.traczyk@savoirfairelinux.com>
parent 9b1b7d44
......@@ -29,6 +29,7 @@
#include <QComboBox>
#include <QWebEngineScript>
#include <algorithm>
#include <memory>
#include "qrencode.h"
......@@ -764,6 +765,12 @@ CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx)
auto contactUri = currentConversation->participants.front();
try {
auto& contact = accInfo->contactModel->getContact(contactUri);
auto bestName = Utils::bestNameForConversation(*currentConversation, *convModel);
ui->messageView->setInvitation(
(contact.profileInfo.type == lrc::api::profile::Type::PENDING),
bestName,
accInfo->contactModel->getContactProfileId(contact.profileInfo.uri)
);
if (!contact.profileInfo.avatar.empty()) {
ui->messageView->setSenderImage(
accInfo->contactModel->getContactProfileId(contactUri),
......
......@@ -2,7 +2,7 @@
* Copyright (C) 2017-2018 by Savoir-faire Linux *
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
* Author: Alexandre Viau <alexandre.viau@savoirfairelinux.com> *
* Author: Sbastien Blin <sebastien.blin@savoirfairelinux.com> *
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> *
* Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com> *
* *
* This program is free software; you can redistribute it and/or modify *
......@@ -213,10 +213,10 @@ MessageWebView::setSenderImage(const std::string& sender,
}
void
MessageWebView::setInvitation(bool show, const std::string& contactUri)
MessageWebView::setInvitation(bool show, const std::string& contactUri, const std::string& contactId)
{
QString s = QString::fromLatin1(show ? "showInvitation(\"%1\")" : "showInvitation()")
.arg(QString(contactUri.c_str()));
QString s = QString::fromLatin1(show ? "showInvitation(\"%1\", \"%2\")" : "showInvitation()")
.arg(QString(contactUri.c_str())).arg(QString(contactId.c_str()));
page()->runJavaScript(s, QWebEngineScript::MainWorld);
}
......@@ -228,6 +228,13 @@ MessageWebView::hideMessages()
}
// JS bridging incoming
Q_INVOKABLE int
PrivateBridging::log(const QString& arg)
{
qDebug() << "JS log: " << arg;
return 0;
}
Q_INVOKABLE int
PrivateBridging::deleteInteraction(const QString& arg)
{
......@@ -342,8 +349,37 @@ PrivateBridging::sendFile()
}
Q_INVOKABLE int
PrivateBridging::log(const QString& arg)
PrivateBridging::acceptInvitation()
{
qDebug() << "JS log: " << arg;
try {
auto convUid = LRCInstance::getSelectedConvUid();
LRCInstance::getCurrentConversationModel()->makePermanent(convUid);
} catch (...) {
qDebug() << "JS bridging - exception during acceptInvitation";
}
return 0;
}
Q_INVOKABLE int
PrivateBridging::refuseInvitation()
{
try {
auto convUid = LRCInstance::getSelectedConvUid();
LRCInstance::getCurrentConversationModel()->removeConversation(convUid, false);
} catch (...) {
qDebug() << "JS bridging - exception during refuseInvitation";
}
return 0;
}
Q_INVOKABLE int
PrivateBridging::blockConversation()
{
try {
auto convUid = LRCInstance::getSelectedConvUid();
LRCInstance::getCurrentConversationModel()->removeConversation(convUid, true);
} catch (...) {
qDebug() << "JS bridging - exception during blockConversation";
}
return 0;
}
\ No newline at end of file
}
......@@ -39,7 +39,9 @@ public:
Q_INVOKABLE int sendMessage(const QString & arg);
Q_INVOKABLE int sendFile();
Q_INVOKABLE int log(const QString& arg);
Q_INVOKABLE int acceptInvitation();
Q_INVOKABLE int refuseInvitation();
Q_INVOKABLE int blockConversation();
};
class MessageWebView : public QWebEngineView
......@@ -68,7 +70,7 @@ public:
lrc::api::interaction::Info> interactions);
void setSenderImage(const std::string& sender,
const std::string& senderImage);
void setInvitation(bool show, const std::string& contactUri);
void setInvitation(bool show, const std::string& contactUri, const std::string& contactId);
void hideMessages();
private slots:
......
......@@ -3,6 +3,10 @@
:root {
/* color definitions */
--jami-light-blue: rgba(59, 193, 211, 0.3);
--jami-green: #219d55;
--jami-green-hover: #1f8b4c;
--jami-red: #dc2719;
--jami-red-hover: #b02e2c;
/* main properties */
/* --bg-color: #f2f2f2; same as macOS client */
--bg-color: #ffffff; /* same as macOS client */
......@@ -17,11 +21,12 @@
--action-icon-color: #00;
--deactivated-icon-color: #bebebe;
--action-icon-hover-color: #ededed;
--action-critical-icon-hover-color: rgba(211, 77, 59, 0.3); /* complementary color of ring light blue */
--action-critical-icon-hover-color: rgba(211, 77, 59, 0.3); /* complementary color of jami light blue */
--action-critical-icon-press-color: rgba(211, 77, 59, 0.5);
--action-critical-icon-color: #4E1300;
--non-action-icon-color: #212121;
--action-icon-press-color: rgba(212, 212, 212, 1.0);
--invite-hover-color: white;
/* hairline properties */
--hairline-color: #f0f0f0;
--hairline-thickness: 2px;
......@@ -189,66 +194,60 @@ body {
/** Invitation bar */
#invitation {
visibility: hidden;
background: var(--jami-light-blue);
position: absolute;
width: 100%;
/* hairline */
border-bottom: var(--hairline-thickness) solid var(--hairline-color);
visibility: hidden;
background: var(--bg-color);
position: absolute;
width: 100%;
padding-bottom: 10px;
/* hairline */
border-bottom: var(--hairline-thickness) solid var(--hairline-color);
}
#invitation #actions {
margin: 10px;
list-style: none;
display: flex;
align-items: center;
justify-content: center;
/* enable selection (it is globally disabled in the body) */
-webkit-user-select: auto;
}
#invitation #invite_header {
margin: 10px;
list-style: none;
display: flex;
align-items: center;
justify-content: center;
#invitation #text h1 {
font-size: 1.5em;
}
/* enable selection (it is globally disabled in the body) */
-webkit-user-select: auto;
}
#invitation #text {
text-align: center;
width: 90%;
margin: auto;
margin-top: 10px;
font-size: 0.8em;
/* enable selection (it is globally disabled in the body) */
-webkit-user-select: auto;
}
#invitation .sender_image {
width: 50px;
height: 50px;
}
.invitation-button,
.flat-button {
margin: 5px;
border: 0;
border-radius: 5px;
transition: all 0.3s ease;
color: #f9f9f9;
padding: 10px 20px 10px 20px;
vertical-align: middle;
cursor: pointer;
#invitation #actions {
margin-right: auto;
margin-left: auto;
list-style: none;
display: flex;
align-items: center;
justify-content: center;
/* enable selection (it is globally disabled in the body) */
-webkit-user-select: auto;
}
.button-green {
background: #27ae60;
#invitation #actions div {
display: flex;
align-items: center;
justify-content: center;
margin-right: 5px;
margin-left: 5px;
}
.button-green:hover {
background: #1f8b4c;
}
#invitation #text {
text-align: center;
font-size: 0.8em;
.button-red {
background: #dc3a37;
/* enable selection (it is globally disabled in the body) */
-webkit-user-select: auto;
}
.button-red:hover {
background: #b02e2c;
}
/** Messaging bar */
#sendMessage {
......@@ -423,6 +422,8 @@ a:hover {
.sender_image {
border-radius: 50%;
margin: 8px 10px 0px 10px;
width: 35px;
height: 35px;
}
.message_out .message_wrapper {
......@@ -613,6 +614,13 @@ input[type=checkbox] {
/* Buttons */
.flat-button {
border: 0;
border-radius: 5px;
transition: all 0.3s ease;
color: #f9f9f9;
padding: 10px 20px 10px 20px;
vertical-align: middle;
cursor: pointer;
flex: 1;
padding: 0;
}
......@@ -693,35 +701,69 @@ input[type=checkbox] {
flex-wrap: wrap;
}
.invite-btn-red {
transition: background-color 0.5s ease;
}
.invite-btn-red:hover {
background: var(--jami-red);
}
.invite-btn-red svg {
fill: var(--jami-red);
transition: fill 0.5s ease;
}
.invite-btn-red:hover svg {
fill: var(--invite-hover-color);
}
.invite-btn-green {
transition: background-color 0.5s ease;
}
.invite-btn-green:hover {
background: var(--jami-green);
}
.invite-btn-green svg {
fill: var(--jami-green);
transition: fill 0.5s ease;
}
.invite-btn-green:hover svg {
fill: var(--invite-hover-color);
}
.accept, .refuse {
border-radius: 50%;
cursor: pointer;
}
.accept svg,
.refuse svg {
padding: 8px;
width: 24px;
height: 24px;
}
.accept svg,
.refuse svg {
padding: 8px;
width: 24px;
height: 24px;
}
.accept {
fill: #219d55;
fill: var(--jami-green);
}
.accept:hover {
fill: white;
background: #219d55;
}
.accept:hover {
fill: var(--invite-hover-color);
background: var(--jami-green-hover);
}
.refuse {
fill: #dc2719;
fill: var(--jami-red);
}
.refuse:hover {
fill: white;
background: #dc2719;
}
.refuse:hover {
fill: var(--invite-hover-color);
background: var(--jami-red-hover);
}
.message_type_data_transfer .text {
text-align: left;
......
......@@ -12,12 +12,29 @@
<body>
<div class="navbar-wrapper">
<div id="invitation">
<div id="text">
<div id="invite_header">
<span id="invite_image"></span>
<div id="text"></div>
</div>
<div id="actions">
<div id="accept-btn" class="invitation-button button-green" onclick="acceptInvitation()">Accept</div>
<div id="refuse-btn" class="invitation-button button-red" onclick="refuseInvitation()">Refuse</div>
<div id="block-btn" class="invitation-button button-red" onclick="blockConversation()">Block</div>
<div id="accept-btn" class="nav-button action-button invite-btn-green" onclick="acceptInvitation()" title="Accept">
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M15 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm-9-2V7H4v3H1v2h3v3h2v-3h3v-2H6zm9 4c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />
</svg>
</div>
<div id="refuse-btn" class="nav-button action-button invite-btn-red" onclick="refuseInvitation()" title="Refuse">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path fill="none" d="M0 0h24v24H0V0z" />
<path d="M18.3 5.71c-.39-.39-1.02-.39-1.41 0L12 10.59 7.11 5.7c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L10.59 12 5.7 16.89c-.39.39-.39 1.02 0 1.41.39.39 1.02.39 1.41 0L12 13.41l4.89 4.89c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L13.41 12l4.89-4.89c.38-.38.38-1.02 0-1.4z" />
</svg>
</div>
<div id="block-btn" class="nav-button action-button invite-btn-red" onclick="blockConversation()" title="Block">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4 13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 4.42-3.58 8-8 8z" />
</svg>
</div>
</div>
</div>
</div>
......
......@@ -28,6 +28,7 @@ var historyBuffer = []
const messageBar = document.getElementById("sendMessage")
const messageBarInput = document.getElementById("message")
const invitation = document.getElementById("invitation")
const inviteImage = document.getElementById("invite_image")
const invitationText = document.getElementById("text")
var messages = document.getElementById("messages")
......@@ -125,19 +126,25 @@ function back_to_bottom() {
* Otherwise, invitation div is updated.
*
* @param contactAlias
* @param contactId
*/
/* exported showInvitation */
function showInvitation(contactAlias) {
function showInvitation(contactAlias, contactId) {
if (!contactAlias) {
if (hasInvitation) {
hasInvitation = false
invitation.style.visibility = ""
}
} else {
if (!inviteImage.classList.contains('sender_image')) {
inviteImage.classList.add('sender_image');
}
if (!inviteImage.classList.contains(`sender_image_${contactId}`)) {
inviteImage.classList.add(`sender_image_${contactId}`);
}
hasInvitation = true
invitationText.innerHTML = "<h1>" + contactAlias + " sends you an invitation</h1>"
+ "Do you want to add them to the conversations list?<br>"
+ "Note: you can automatically accept this invitation by sending a message."
invitationText.innerHTML = "<b>" + contactAlias + " is not in your contacts</b><br/>"
+ "Note: you can automatically accept this invitation by sending a message."
invitation.style.visibility = "visible"
}
}
......@@ -255,6 +262,19 @@ function sendMessage()
}
}
/* exported acceptInvitation */
function acceptInvitation() {
window.jsbridge.acceptInvitation()
}
/* exported refuseInvitation */
function refuseInvitation() {
window.jsbridge.refuseInvitation()
}
/* exported blockConversation */
function blockConversation() {
window.jsbridge.blockConversation()
}
/* exported sendFile */
function sendFile()
{
......@@ -1499,6 +1519,6 @@ function setSenderImage(set_sender_image_object)
style.type = "text/css"
style.id = sender_image_id
style.innerHTML = "." + sender_image_id + " {content: url(data:image/png;base64," + sender_image + ");height: 32px;width: 32px;}"
style.innerHTML = "." + sender_image_id + " {content: url(data:image/png;base64," + sender_image + ");}"
document.head.appendChild(style)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment