Commit 58ee1460 authored by JC Brand's avatar JC Brand

Updates #1069

Highlight the currently open groupchat in the sidebar (in singleton mode).
parent a67fa6d4
......@@ -8277,14 +8277,25 @@ body.reset {
background-color: #eff4f7; }
#conversejs .list-container .items-list .available-chatroom:hover .remove-bookmark,
#conversejs .list-container .items-list .available-chatroom:hover .add-bookmark,
#conversejs .list-container .items-list .available-chatroom:hover .close-room,
#conversejs .list-container .items-list .available-chatroom:hover .room-info,
#conversejs .list-container .items-list .open-headline:hover .remove-bookmark,
#conversejs .list-container .items-list .open-headline:hover .add-bookmark,
#conversejs .list-container .items-list .open-headline:hover .close-room,
#conversejs .list-container .items-list .open-headline:hover .room-info,
#conversejs .list-container .items-list .open-chatroom:hover .remove-bookmark,
#conversejs .list-container .items-list .open-chatroom:hover .add-bookmark,
#conversejs .list-container .items-list .open-chatroom:hover .close-room,
#conversejs .list-container .items-list .open-chatroom:hover .room-info {
display: block !important; }
#conversejs .list-container .items-list .available-chatroom.open,
#conversejs .list-container .items-list .open-headline.open,
#conversejs .list-container .items-list .open-chatroom.open {
background-color: #578EA9; }
#conversejs .list-container .items-list .available-chatroom.open a,
#conversejs .list-container .items-list .open-headline.open a,
#conversejs .list-container .items-list .open-chatroom.open a {
color: white !important; }
#conversejs .list-container .items-list .available-chatroom.unread-msgs .msgs-indicator,
#conversejs .list-container .items-list .open-headline.unread-msgs .msgs-indicator,
#conversejs .list-container .items-list .open-chatroom.unread-msgs .msgs-indicator {
......@@ -8302,20 +8313,24 @@ body.reset {
#conversejs .list-container .items-list .open-headline a:hover,
#conversejs .list-container .items-list .open-chatroom a:hover {
color: #206485; }
#conversejs .list-container .items-list .available-chatroom a.remove-bookmark, #conversejs .list-container .items-list .available-chatroom a.add-bookmark, #conversejs .list-container .items-list .available-chatroom a.room-info,
#conversejs .list-container .items-list .available-chatroom a.remove-bookmark, #conversejs .list-container .items-list .available-chatroom a.add-bookmark, #conversejs .list-container .items-list .available-chatroom a.close-room, #conversejs .list-container .items-list .available-chatroom a.room-info,
#conversejs .list-container .items-list .open-headline a.remove-bookmark,
#conversejs .list-container .items-list .open-headline a.add-bookmark,
#conversejs .list-container .items-list .open-headline a.close-room,
#conversejs .list-container .items-list .open-headline a.room-info,
#conversejs .list-container .items-list .open-chatroom a.remove-bookmark,
#conversejs .list-container .items-list .open-chatroom a.add-bookmark,
#conversejs .list-container .items-list .open-chatroom a.close-room,
#conversejs .list-container .items-list .open-chatroom a.room-info {
display: none; }
#conversejs .list-container .items-list .available-chatroom a.remove-bookmark:before, #conversejs .list-container .items-list .available-chatroom a.add-bookmark:before, #conversejs .list-container .items-list .available-chatroom a.room-info:before,
#conversejs .list-container .items-list .available-chatroom a.remove-bookmark:before, #conversejs .list-container .items-list .available-chatroom a.add-bookmark:before, #conversejs .list-container .items-list .available-chatroom a.close-room:before, #conversejs .list-container .items-list .available-chatroom a.room-info:before,
#conversejs .list-container .items-list .open-headline a.remove-bookmark:before,
#conversejs .list-container .items-list .open-headline a.add-bookmark:before,
#conversejs .list-container .items-list .open-headline a.close-room:before,
#conversejs .list-container .items-list .open-headline a.room-info:before,
#conversejs .list-container .items-list .open-chatroom a.remove-bookmark:before,
#conversejs .list-container .items-list .open-chatroom a.add-bookmark:before,
#conversejs .list-container .items-list .open-chatroom a.close-room:before,
#conversejs .list-container .items-list .open-chatroom a.room-info:before {
font-size: 15px; }
#conversejs .list-container .items-list .available-chatroom a.open-room,
......@@ -8333,33 +8348,42 @@ body.reset {
width: 85%; }
#conversejs .list-container .items-list .available-chatroom .add-bookmark,
#conversejs .list-container .items-list .available-chatroom .remove-bookmark,
#conversejs .list-container .items-list .available-chatroom .remove-bookmark,
#conversejs .list-container .items-list .available-chatroom .close-room,
#conversejs .list-container .items-list .available-chatroom .room-info,
#conversejs .list-container .items-list .open-headline .add-bookmark,
#conversejs .list-container .items-list .open-headline .remove-bookmark,
#conversejs .list-container .items-list .open-headline .remove-bookmark,
#conversejs .list-container .items-list .open-headline .close-room,
#conversejs .list-container .items-list .open-headline .room-info,
#conversejs .list-container .items-list .open-chatroom .add-bookmark,
#conversejs .list-container .items-list .open-chatroom .remove-bookmark,
#conversejs .list-container .items-list .open-chatroom .remove-bookmark {
#conversejs .list-container .items-list .open-chatroom .close-room,
#conversejs .list-container .items-list .open-chatroom .room-info {
color: #A8ABA1; }
#conversejs .list-container .items-list .available-chatroom .add-bookmark.button-on,
#conversejs .list-container .items-list .available-chatroom .remove-bookmark.button-on,
#conversejs .list-container .items-list .available-chatroom .remove-bookmark.button-on,
#conversejs .list-container .items-list .available-chatroom .close-room.button-on,
#conversejs .list-container .items-list .available-chatroom .room-info.button-on,
#conversejs .list-container .items-list .open-headline .add-bookmark.button-on,
#conversejs .list-container .items-list .open-headline .remove-bookmark.button-on,
#conversejs .list-container .items-list .open-headline .remove-bookmark.button-on,
#conversejs .list-container .items-list .open-headline .close-room.button-on,
#conversejs .list-container .items-list .open-headline .room-info.button-on,
#conversejs .list-container .items-list .open-chatroom .add-bookmark.button-on,
#conversejs .list-container .items-list .open-chatroom .remove-bookmark.button-on,
#conversejs .list-container .items-list .open-chatroom .remove-bookmark.button-on {
#conversejs .list-container .items-list .open-chatroom .close-room.button-on,
#conversejs .list-container .items-list .open-chatroom .room-info.button-on {
color: #578EA9; }
#conversejs .list-container .items-list .available-chatroom .add-bookmark.button-on:hover,
#conversejs .list-container .items-list .available-chatroom .remove-bookmark.button-on:hover,
#conversejs .list-container .items-list .available-chatroom .remove-bookmark.button-on:hover,
#conversejs .list-container .items-list .available-chatroom .close-room.button-on:hover,
#conversejs .list-container .items-list .available-chatroom .room-info.button-on:hover,
#conversejs .list-container .items-list .open-headline .add-bookmark.button-on:hover,
#conversejs .list-container .items-list .open-headline .remove-bookmark.button-on:hover,
#conversejs .list-container .items-list .open-headline .remove-bookmark.button-on:hover,
#conversejs .list-container .items-list .open-headline .close-room.button-on:hover,
#conversejs .list-container .items-list .open-headline .room-info.button-on:hover,
#conversejs .list-container .items-list .open-chatroom .add-bookmark.button-on:hover,
#conversejs .list-container .items-list .open-chatroom .remove-bookmark.button-on:hover,
#conversejs .list-container .items-list .open-chatroom .remove-bookmark.button-on:hover {
#conversejs .list-container .items-list .open-chatroom .close-room.button-on:hover,
#conversejs .list-container .items-list .open-chatroom .room-info.button-on:hover {
color: #206485; }
#conversejs #converse-roster {
......
......@@ -71413,6 +71413,10 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
}
};
_converse.isSingleton = function () {
return _.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode);
};
_converse.router = new Backbone.Router();
_converse.initialize = function (settings, callback) {
......@@ -80671,7 +80675,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
*
* NB: These plugins need to have already been loaded via require.js.
*/
dependencies: ["converse-controlbox", "converse-muc", "converse-bookmarks"],
dependencies: ["converse-singleton", "converse-controlbox", "converse-muc", "converse-bookmarks"],
initialize() {
/* The initialize function gets called as soon as the plugin is
......@@ -80697,6 +80701,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
_converse.chatboxes.on('add', this.onChatBoxAdded, this);
_converse.chatboxes.on('change:hidden', this.onChatBoxChanged, this);
_converse.chatboxes.on('change:bookmarked', this.onChatBoxChanged, this);
_converse.chatboxes.on('change:name', this.onChatBoxChanged, this);
......@@ -80743,13 +80749,14 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
});
_converse.RoomsListElementView = Backbone.VDOMView.extend({
events: {
'click a.room-info': 'showRoomDetailsModal'
'click .room-info': 'showRoomDetailsModal'
},
initialize() {
this.model.on('destroy', this.remove, this);
this.model.on('remove', this.remove, this);
this.model.on('change:bookmarked', this.render, this);
this.model.on('change:hidden', this.render, this);
this.model.on('change:name', this.render, this);
this.model.on('change:num_unread', this.render, this);
this.model.on('change:num_unread_general', this.render, this);
......@@ -80762,6 +80769,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
// supported by the XMPP server. So we can use it
// as a check for support (other ways of checking are async).
'allow_bookmarks': _converse.allow_bookmarks && _converse.bookmarks,
'currently_open': _converse.isSingleton() && !this.model.get('hidden'),
'info_leave_room': __('Leave this groupchat'),
'info_remove_bookmark': __('Unbookmark this groupchat'),
'info_add_bookmark': __('Bookmark this groupchat'),
......@@ -83084,7 +83092,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
return true;
}
if (_.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode)) {
if (_converse.isSingleton()) {
const any_chats_visible = _converse.chatboxes.filter(cb => cb.get('id') != 'controlbox').filter(cb => !cb.get('hidden')).length > 0;
if (any_chats_visible) {
......@@ -83099,7 +83107,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
createChatBox(jid, attrs) {
/* Make sure new chat boxes are hidden by default. */
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
const _converse = this.__super__._converse;
if (_converse.isSingleton()) {
attrs = attrs || {};
attrs.hidden = true;
}
......@@ -83110,7 +83120,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
},
ChatBoxView: {
shouldShowOnTextMessage() {
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
const _converse = this.__super__._converse;
if (_converse.isSingleton()) {
return false;
} else {
return this.__super__.shouldShowOnTextMessage.apply(this, arguments);
......@@ -83122,7 +83134,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
* time. So before opening a chat, we make sure all other
* chats are hidden.
*/
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
const _converse = this.__super__._converse;
if (_converse.isSingleton()) {
_.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
this.model.set('hidden', false);
......@@ -83134,7 +83148,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
},
ChatRoomView: {
show(focus) {
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
const _converse = this.__super__._converse;
if (_converse.isSingleton()) {
_.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
this.model.set('hidden', false);
......@@ -86138,11 +86154,15 @@ var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./no
module.exports = function(o) {
var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
function print() { __p += __j.call(arguments, '') }
__p += '<!-- src/templates/rooms_list_item.html -->\n<div class="list-item controlbox-padded available-chatroom d-flex flex-row ';
__p += '<!-- src/templates/rooms_list_item.html -->\n<div class="list-item controlbox-padded available-chatroom d-flex flex-row\n ';
if (o.currently_open) { ;
__p += ' open ';
} ;
__p += '\n ';
if (o.num_unread_general) { ;
__p += ' unread-msgs ';
} ;
__p += '" data-room-jid="' +
__p += '"\n data-room-jid="' +
__e(o.jid) +
'">\n';
if (o.num_unread) { ;
......@@ -86156,15 +86176,9 @@ __e(o.jid) +
__e(o.open_title) +
'" href="#">' +
__e(o.name || o.jid) +
'</a>\n\n<a class="right close-room icon-leave"\n data-room-jid="' +
__e(o.jid) +
'"\n data-room-name="' +
__e(o.name || o.jid) +
'"\n title="' +
__e(o.info_leave_room) +
'" href="#">&nbsp;</a>\n\n';
'</a>\n\n';
if (o.allow_bookmarks) { ;
__p += '\n<a class="fa align-self-center ';
__p += '\n<a class="fa ';
if (o.bookmarked) { ;
__p += ' fa-bookmark remove-bookmark button-on ';
} else { ;
......@@ -86186,11 +86200,17 @@ __e(o.info_add_bookmark) +
} ;
__p += '"\n href="#">&nbsp;</a>\n';
} ;
__p += '\n<a class="room-info fa fa-info-circle align-self-center" data-room-jid="' +
__p += '\n<a class="room-info fa fa-info-circle" data-room-jid="' +
__e(o.jid) +
'"\n title="' +
__e(o.info_title) +
'" href="#">&nbsp;</a>\n</div>\n';
'" href="#">&nbsp;</a>\n\n<a class="fa fa-times close-room"\n data-room-jid="' +
__e(o.jid) +
'"\n data-room-name="' +
__e(o.name || o.jid) +
'"\n title="' +
__e(o.info_leave_room) +
'" href="#">&nbsp;</a>\n\n</div>\n';
return __p
};
......@@ -37,7 +37,7 @@
</div>
<div class="list-container rooms-list-container">
<div class="rooms-list items-list">
<div class="controlbox-padded list-item available-chatroom d-flex flex-row">
<div class="controlbox-padded list-item available-chatroom d-flex flex-row open">
<a class="open-room available-room w-100" data-room-jid="public@conference.test.com" title="Click to open this room" href="chatroom.html">Capulet's orchard</a>
<!-- <span class="badge badge-info msgs-indicator">1</span> -->
<a href="#"
......
......@@ -34,10 +34,17 @@
background-color: lighten($controlbox-head-color, 45%);
.remove-bookmark,
.add-bookmark,
.close-room,
.room-info {
display: block !important;
}
}
&.open {
background-color: $controlbox-head-color;
a {
color: white !important;
}
}
&.unread-msgs {
.msgs-indicator {
border-radius: 10%;
......@@ -55,6 +62,7 @@
}
&.remove-bookmark,
&.add-bookmark,
&.close-room,
&.room-info {
display: none;
&:before {
......@@ -75,7 +83,8 @@
}
.add-bookmark,
.remove-bookmark,
.remove-bookmark {
.close-room,
.room-info {
&.button-on {
color: $link-color;
&:hover {
......
......@@ -54,7 +54,38 @@
));
});
describe("A room shown in the groupchats list", function () {
describe("A groupchat shown in the groupchats list", function () {
it("is highlighted if its currently open", mock.initConverseWithPromises(
null, ['rosterGroupsFetched'],
{ whitelisted_plugins: ['converse-roomslist'],
allow_bookmarks: false // Makes testing easier, otherwise we
// have to mock stanza traffic.
}, function (done, _converse) {
spyOn(_converse, 'isSingleton').and.callFake(function () {
return true;
});
test_utils.openControlBox();
_converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'});
let room_els = _converse.rooms_list_view.el.querySelectorAll(".available-chatroom");
expect(room_els.length).toBe(1);
let item = room_els[0];
expect(u.hasClass('open', item)).toBe(true);
expect(item.textContent.trim()).toBe('coven@chat.shakespeare.lit');
_converse.api.rooms.open('balcony@chat.shakespeare.lit', {'nick': 'some1'});
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(2);
room_els = _converse.rooms_list_view.el.querySelectorAll(".available-chatroom.open");
expect(room_els.length).toBe(1);
item = room_els[0];
expect(item.textContent.trim()).toBe('balcony@chat.shakespeare.lit');
done();
}));
it("has an info icon which opens a details modal when clicked", mock.initConverseWithPromises(
null, ['rosterGroupsFetched'],
......
......@@ -295,6 +295,10 @@
}
};
_converse.isSingleton = function () {
return _.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode);
}
_converse.router = new Backbone.Router();
......
......@@ -33,7 +33,7 @@
*
* NB: These plugins need to have already been loaded via require.js.
*/
dependencies: ["converse-controlbox", "converse-muc", "converse-bookmarks"],
dependencies: ["converse-singleton", "converse-controlbox", "converse-muc", "converse-bookmarks"],
initialize () {
/* The initialize function gets called as soon as the plugin is
......@@ -58,6 +58,7 @@
this.browserStorage = new Backbone.BrowserStorage[_converse.storage](
b64_sha1(`converse.open-rooms-{_converse.bare_jid}`));
_converse.chatboxes.on('add', this.onChatBoxAdded, this);
_converse.chatboxes.on('change:hidden', this.onChatBoxChanged, this);
_converse.chatboxes.on('change:bookmarked', this.onChatBoxChanged, this);
_converse.chatboxes.on('change:name', this.onChatBoxChanged, this);
_converse.chatboxes.on('change:num_unread', this.onChatBoxChanged, this);
......@@ -98,13 +99,14 @@
_converse.RoomsListElementView = Backbone.VDOMView.extend({
events: {
'click a.room-info': 'showRoomDetailsModal'
'click .room-info': 'showRoomDetailsModal'
},
initialize () {
this.model.on('destroy', this.remove, this);
this.model.on('remove', this.remove, this);
this.model.on('change:bookmarked', this.render, this);
this.model.on('change:hidden', this.render, this);
this.model.on('change:name', this.render, this);
this.model.on('change:num_unread', this.render, this);
this.model.on('change:num_unread_general', this.render, this);
......@@ -118,6 +120,7 @@
// supported by the XMPP server. So we can use it
// as a check for support (other ways of checking are async).
'allow_bookmarks': _converse.allow_bookmarks && _converse.bookmarks,
'currently_open': _converse.isSingleton() && !this.model.get('hidden'),
'info_leave_room': __('Leave this groupchat'),
'info_remove_bookmark': __('Unbookmark this groupchat'),
'info_add_bookmark': __('Bookmark this groupchat'),
......
......@@ -50,7 +50,7 @@
if (chatbox.get('id') === 'controlbox') {
return true;
}
if (_.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode)) {
if (_converse.isSingleton()) {
const any_chats_visible = _converse.chatboxes
.filter((cb) => cb.get('id') != 'controlbox')
.filter((cb) => !cb.get('hidden')).length > 0;
......@@ -67,7 +67,8 @@
createChatBox (jid, attrs) {
/* Make sure new chat boxes are hidden by default. */
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
const { _converse } = this.__super__;
if (_converse.isSingleton()) {
attrs = attrs || {};
attrs.hidden = true;
}
......@@ -77,7 +78,8 @@
ChatBoxView: {
shouldShowOnTextMessage () {
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
const { _converse } = this.__super__;
if (_converse.isSingleton()) {
return false;
} else {
return this.__super__.shouldShowOnTextMessage.apply(this, arguments);
......@@ -89,7 +91,8 @@
* time. So before opening a chat, we make sure all other
* chats are hidden.
*/
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
const { _converse } = this.__super__;
if (_converse.isSingleton()) {
_.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
this.model.set('hidden', false);
}
......@@ -99,7 +102,8 @@
ChatRoomView: {
show (focus) {
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
const { _converse } = this.__super__;
if (_converse.isSingleton()) {
_.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
this.model.set('hidden', false);
}
......
<div class="list-item controlbox-padded available-chatroom d-flex flex-row {[ if (o.num_unread_general) { ]} unread-msgs {[ } ]}" data-room-jid="{{{o.jid}}}">
<div class="list-item controlbox-padded available-chatroom d-flex flex-row
{[ if (o.currently_open) { ]} open {[ } ]}
{[ if (o.num_unread_general) { ]} unread-msgs {[ } ]}"
data-room-jid="{{{o.jid}}}">
{[ if (o.num_unread) { ]}
<span class="msgs-indicator badge badge-info">{{{ o.num_unread }}}</span>
{[ } ]}
......@@ -6,17 +9,18 @@
data-room-jid="{{{o.jid}}}"
title="{{{o.open_title}}}" href="#">{{{o.name || o.jid}}}</a>
<a class="right close-room icon-leave"
data-room-jid="{{{o.jid}}}"
data-room-name="{{{o.name || o.jid}}}"
title="{{{o.info_leave_room}}}" href="#">&nbsp;</a>
{[ if (o.allow_bookmarks) { ]}
<a class="fa align-self-center {[ if (o.bookmarked) { ]} fa-bookmark remove-bookmark button-on {[ } else { ]} add-bookmark fa-bookmark-o {[ } ]}"
<a class="fa {[ if (o.bookmarked) { ]} fa-bookmark remove-bookmark button-on {[ } else { ]} add-bookmark fa-bookmark-o {[ } ]}"
data-room-jid="{{{o.jid}}}" data-bookmark-name="{{{o.name}}}"
title="{[ if (o.bookmarked) { ]} {{{o.info_remove_bookmark}}} {[ } else { ]} {{{o.info_add_bookmark}}} {[ } ]}"
href="#">&nbsp;</a>
{[ } ]}
<a class="room-info fa fa-info-circle align-self-center" data-room-jid="{{{o.jid}}}"
<a class="room-info fa fa-info-circle" data-room-jid="{{{o.jid}}}"
title="{{{o.info_title}}}" href="#">&nbsp;</a>
<a class="fa fa-times close-room"
data-room-jid="{{{o.jid}}}"
data-room-name="{{{o.name || o.jid}}}"
title="{{{o.info_leave_room}}}" href="#">&nbsp;</a>
</div>
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