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

Modmail sidebar adjustments #595

Merged
merged 12 commits into from
Aug 24, 2022
101 changes: 69 additions & 32 deletions extension/data/modules/newmodmailpro.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ export default new Module({
default: true,
description: 'Displays a "Show Source" button allowing you to display the message source in markdown.',
},
{
id: 'modmailSidebarAvatar',
type: 'selector',
values: ['Original', 'Compact', 'Hidden'],
default: 'original',
description: 'Change how the user avatar in the modmail sidebar looks.',
},
{
id: 'disableAvatarAnimation',
type: 'boolean',
default: false,
description: 'Disable the sidebar avatar animation effect.',
},
],
}, ({
modmailnightmode: modMailNightmode,
Expand All @@ -70,6 +83,8 @@ export default new Module({
sourceButton,
modmaillink: modmaillink,
openmailtab: openMailTab,
modmailSidebarAvatar,
disableAvatarAnimation,
}) => {
const $body = $('body');

Expand All @@ -82,24 +97,39 @@ export default new Module({
}

/**
* Searches for ban reason elements on page and makes included links clickable.
* Searches for elements in the sidebar and turns static text into clickable links where possible.
* For example: Links in ban reasons, username instances, etc.
* @function
*/
function reasonClickable () {
const $reasons = $body.find('.InfoBar__banText:not(.tb-reason-seen), .InfoBar__muteText:not(.tb-reason-seen)');
if ($reasons.length) {
$reasons.each(function () {
const $reason = $(this);
$reason.addClass('tb-reason-seen');

let reasonText = $reason.text();
// Three regex passes to avoid silly logic about whole urls, urls starting with a slash and those without it.
reasonText = reasonText.replace(/(\s|'|^)(https:\/\/.+?)(\s|'|$)/gi, '$1<a href="$2" target="_blank">$2</a>$3');
reasonText = reasonText.replace(/(\s|'|^)(\/u\/.+?|\/user\/.+?|\/r\/.+?)(\s|'|$)/gi, '$1<a href="https://www.reddit.com$2" target="_blank">$2</a>$3');
reasonText = reasonText.replace(/(\s|'|^)(u\/.+?|user\/.+?|r\/.+?)(\s|'|$)/gi, '$1<a href="https://www.reddit.com/$2" target="_blank">$2</a>$3');

$reason.html(reasonText);
});
function extraClickable () {
// Make ban reason links clickable.
if (clickableReason) {
const $reasons = $body.find('.InfoBar__banText:not(.tb-reason-seen), .InfoBar__muteText:not(.tb-reason-seen), .KarmaAndTrophies__BanStatus:not(.tb-reason-seen), .NewInfoBar__muteText:not(.tb-reason-seen)');
if ($reasons.length) {
$reasons.each(function () {
const $reason = $(this);
$reason.addClass('tb-reason-seen');

let reasonText = $reason.text();
// Three regex passes to avoid silly logic about whole urls, urls starting with a slash and those without it.
reasonText = reasonText.replace(/(\s|'|^)(https:\/\/.+?)(\s|'|$)/gi, '$1<a href="$2" target="_blank">$2</a>$3');
reasonText = reasonText.replace(/(\s|'|^)(\/u\/.+?|\/user\/.+?|\/r\/.+?)(\s|'|$)/gi, '$1<a href="https://www.reddit.com$2" target="_blank">$2</a>$3');
reasonText = reasonText.replace(/(\s|'|^)(u\/.+?|user\/.+?|r\/.+?)(\s|'|$)/gi, '$1<a href="https://www.reddit.com/$2" target="_blank">$2</a>$3');

$reason.html(reasonText);
});
}
}

// A few obvious elements in the sidebar should be clickable and lead to the user profile.
const $modIdCard = $body.find('.NewInfoBar__idCard .ModIdCard:not(.tb-profile-link-seen)');
if ($modIdCard.length) {
$modIdCard.addClass('tb-profile-link-seen');
const userProfileLink = $body.find('.ModIdCard__UserProfileLink a').attr('href');
const wrapElement = `<a href="${userProfileLink}" target="_blank" class="tb-sidebar-profile-link"></a>`;
$body.find('.ModIdCard__snoovatarContainer img.ModIdCard__snoovatar').wrap(wrapElement);
$body.find('.ModIdCard__UserNameContainer .ModIdCard__UserNameLink div').wrap(wrapElement);
$body.find('.ModIdCard__UserNameMetaData .ModIdCard__UserNameText').wrap(wrapElement);
}
}

Expand All @@ -108,13 +138,36 @@ export default new Module({
// Add a class to body
$body.addClass('tb-new-modmail');

// Set the sidebar avatar style.
$body.addClass(`tb-modmail-sidebar-avatar-${modmailSidebarAvatar}`);

if (disableAvatarAnimation) {
$body.addClass('tb-modmail-sidebar-no-animation');
}

/**
* Controls whether clicks events on the reply button are handled by us or Reddit. When the user clicks the
* button, we want to perform our own handling. However, in order to actually submit a reply once we're done
* with our own checks, we need to trigger the event again and let Reddit handle it normally.
*/
let shouldHijackClickHandler = true;

// Handle sidebar specific things when the user icon is clicked (mobile devices, small windows).
$body.on('click', '.icon-user', () => {
setTimeout(() => {
extraClickable();
}, 500);
});

// Handle sidebar specific things when arriving on a conversation view.
window.addEventListener('TBNewPage', event => {
if (event.detail.pageType === 'modmailConversation') {
setTimeout(() => {
extraClickable();
}, 500);
}
});

/**
* Submits the reply form, bypassing the submission button click. Should only be
* called from the handleSubmitButtonClick handler or embedded functions.
Expand Down Expand Up @@ -230,22 +283,6 @@ export default new Module({
$('html').addClass('tb-nightmode');
}

if (clickableReason) {
$body.on('click', '.icon-user', () => {
setTimeout(() => {
reasonClickable();
}, 500);
});

window.addEventListener('TBNewPage', event => {
if (event.detail.pageType === 'modmailConversation') {
setTimeout(() => {
reasonClickable();
}, 500);
}
});
}

if (sourceButton) {
let conversationCached = false;
window.addEventListener('TBNewPage', () => {
Expand Down
30 changes: 21 additions & 9 deletions extension/data/modules/oldreddit.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,28 +228,40 @@ function newModmailConversationAuthors () {
}

/**
* Makes sure to fire a jsAPI `TBuserHovercard` event for new modmail sidebar instances.
* Makes sure to fire a jsAPI `TBuserHovercard` (old sidebar) or `TBuserModmailSidebar` (new sidebar) event for new modmail sidebar instances.
* @function
*/
function newModmailSidebar () {
setTimeout(() => {
const $body = $('body');
if ($body.find('.ThreadViewer').length) {
$body.find('.ThreadViewer__infobar:not(.tb-seen), .ThreadViewerHeader__infobar:not(.tb-seen)').each(function () {
let $modmailSidebar = $body.find('.NewInfoBar__idCard:not(.tb-seen), .NewInfoBar__idCard:not(.tb-seen)');
let sidebarEvent = 'TBuserModmailSidebar';
let jsApiPlaceHolder = `
<div class="tb-jsapi-container">
<span data-name="toolbox"></span>
</div>
`;
if (!$modmailSidebar.length) {
$modmailSidebar = $body.find('.ThreadViewer__infobar:not(.tb-seen), .ThreadViewerHeader__infobar:not(.tb-seen)');
sidebarEvent = 'TBuserHovercard';
jsApiPlaceHolder = `
<div class="tb-jsapi-container InfoBar__recents">
<div class="InfoBar__recentsTitle">Toolbox functions:</div>
<span data-name="toolbox"></span>
</div>
`;
}
$modmailSidebar.each(function () {
const $infobar = $(this);
$infobar.addClass('tb-seen');
const info = TBCore.getThingInfo(this, true);
const $jsApiThingPlaceholder = $(`
<div class="tb-jsapi-container InfoBar__recents">
<div class="InfoBar__recentsTitle">Toolbox functions:</div>
<span data-name="toolbox"></span>
</div>
`).appendTo($infobar);
const $jsApiThingPlaceholder = $(jsApiPlaceHolder).appendTo($infobar);

const jsApiThingPlaceholder = $jsApiThingPlaceholder[0];

const detailObject = {
type: 'TBuserHovercard',
type: sidebarEvent,
data: {
user: {
username: info.user || '[deleted]',
Expand Down
127 changes: 127 additions & 0 deletions extension/data/styles/newmodmailpro.css
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,133 @@ html.tb-nightmode,
border: solid #46d160 2px;
}

/* Sidebar avatar styling - compact
*/
.tb-new-modmail.tb-modmail-sidebar-avatar-compact .NewInfoBar__idCard .tb-jsapi-container {
margin-top: 10px;
}

.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard {
width: unset;
height: 100px;
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
margin-top: 20px;
padding-left: 85px;
}

.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard:has(.ModIdCard__icon) {
height: 80px;
}

.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__snoovatarContainer {
position: absolute;
top: 0;
left: 15px;
width: unset;
padding: 0;
}

.tb-new-modmail.tb-modmail-sidebar-avatar-compact .particleWrapper {
top: -20px;
}

.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__UserNameContainer {
z-index: 1;
}

.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__topGlow,
.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__bottomGlow {
display: none;
}

.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__bannerImage {
position: absolute;
top: -20px;
left: 0;
width: 100%;
height: calc(100% + 20px);
margin: 0;
padding: 0;
opacity: 0.8;
}

.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__snoovatar {
height: 100px;
}

.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__icon {
margin-top: calc((100px - 60px - (1px * 2)) / 2);
width: unset;
height: 60px;
}

/* banner shenanigans */
.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__UserNameLink,
.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__UserNameMetaData{
justify-content: initial;
}

.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__UserProfileLink {
text-align: initial;
}

.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__bannerImage ~ .ModIdCard__UserNameContainer .ModIdCard__admin,
.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__bannerImage ~ .ModIdCard__UserNameContainer .ModIdCard__UserNameLink,
.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__bannerImage ~ .ModIdCard__UserNameMetaData,
.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__bannerImage ~ .ModIdCard__UserProfileLink {
color: #000000;
position: relative;
text-shadow:
2px 2px rgba(255, 255, 255, .5),
2px 1px rgba(255, 255, 255, .5),
2px 0 rgba(255, 255, 255, .5),
2px -1px rgba(255, 255, 255, .5),
2px -2px rgba(255, 255, 255, .5),
1px -2px rgba(255, 255, 255, .5),
0 -2px rgba(255, 255, 255, .5),
-1px -2px rgba(255, 255, 255, .5),
-2px -2px rgba(255, 255, 255, .5),
-2px -1px rgba(255, 255, 255, .5),
-2px 0 rgba(255, 255, 255, .5),
-2px 1px rgba(255, 255, 255, .5),
-2px 2px rgba(255, 255, 255, .5),
-1px 2px rgba(255, 255, 255, .5),
0 2px rgba(255, 255, 255, .5),
1px 2px rgba(255, 255, 255, .5);
}

.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__UserNameContainer .ModIdCard__admin,
.tb-new-modmail.tb-modmail-sidebar-avatar-compact .ModIdCard__bannerImage ~ .ModIdCard__UserNameContainer .ModIdCard__admin.ModIdCard__admin {
display: inline;
color: #ff4500;
}

/* Sidebar avatar styling - hidden
*/

.tb-new-modmail.tb-modmail-sidebar-avatar-hidden .ModIdCard__snoovatarContainer,
.tb-new-modmail.tb-modmail-sidebar-avatar-hidden .ModIdCard__bannerImage {
display: none;
}

.tb-new-modmail.tb-modmail-sidebar-avatar-hidden .ModIdCard {
padding-top: 20px;
}

/* Sidebar avatar styling - clickable profile links
*/
.tb-new-modmail a.tb-sidebar-profile-link {
color: #006dc6
}


.tb-new-modmail.tb-modmail-sidebar-no-animation .particleWrapper {
display: none;
}

/* misc fixes.
*/

Expand Down
25 changes: 25 additions & 0 deletions extension/data/styles/toolbox.css
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,31 @@ body.mod-toolbox-rd .tb-frontend-container[data-tb-type="userHovercard"] .tb-bra
line-height: 17px;
}


/* New modmail sidebar toolbox buttons styling
*/

body.mod-toolbox-rd .NewInfoBar__idCard .tb-jsapi-container {
width: 100%;
}

body.mod-toolbox-rd .tb-frontend-container[data-tb-type="TBuserModmailSidebar"] {
display: grid;
grid-template-columns: 47% 47%;
grid-template-rows: auto;
justify-content: center;
}

body.mod-toolbox-rd .tb-frontend-container[data-tb-type="TBuserModmailSidebar"] .tb-bracket-button {
margin-bottom: 5px;
height: 17px;
line-height: 17px;
}





/*
-----------
Comment rebuilding css
Expand Down
4 changes: 3 additions & 1 deletion extension/data/tbcore.js
Original file line number Diff line number Diff line change
Expand Up @@ -953,7 +953,9 @@ export function getThingInfo (sender, modCheck) {
kind = $threadBase.hasClass('.Thread__message') ? 'modmailmessage' : 'modmailthread';
spam = false;
ham = false;
user = $threadBase.find('.Message__author').first().text() || $body.find('.InfoBar__username').first().text();
user = $threadBase.find('.Message__author').first().text() ||
$body.find('.InfoBar__username').first().text() ||
$body.find('.ModIdCard__UserNameContainer').first().text();
} else {
const $entry = $($sender.closest('.entry')[0] || $sender.find('.entry')[0] || $sender);
const $thing = $($sender.closest('.thing')[0] || $sender);
Expand Down
1 change: 1 addition & 0 deletions extension/data/tblistener.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const listenerAliases = {
TBcommentOldReddit: ['comment'],
TBpost: ['post'],
TBuserHovercard: ['userHovercard'],
TBuserModmailSidebar: ['userHovercard'],
TBmodmailCommentAuthor: ['author'],
};

Expand Down