Skip to content

Instantly share code, notes, and snippets.

@ikariiin
Last active May 3, 2017 14:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ikariiin/827c8a280f6bc3c15603f8b8dcd945e2 to your computer and use it in GitHub Desktop.
Save ikariiin/827c8a280f6bc3c15603f8b8dcd945e2 to your computer and use it in GitHub Desktop.
const R11MATERIAL_STYLESHEET_MIN = `
@import url('https://fonts.googleapis.com/css?family=Roboto:400,100|Material+Icons');
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #CDDC39;
}
::-webkit-scrollbar-thumb {
background: rgba(20, 20, 20, 0.7);
}
.material-icons {
font-size: inherit !important;
line-height: inherit !important;
}
body {
font-family: 'Roboto', 'Roboto Condensed', sans-serif;
background: #363636;
color: #FFF;
}
img {
border-radius: 50%;
}
a {
color: #2196F3;
text-decoration: none;
}
a:visited {
color: #2196F3;
}
#input-area {
position: fixed;
bottom: 0;
left: 0;
background: transparent;
width: 100%;
z-index: 1000;
padding-bottom: 13px;
}
#input-area button {
display: inline-block;
z-index: 5000;
transition: 200ms all;
}
#input-area .button:hover {
background: rgba(255, 255, 255, 0.6);
}
#input-area #sayit-button {
width: 40px;
height: 40px;
color: #3F51B5;
border-radius: 50%;
background: transparent;
font-size: 20px;
text-align: center;
line-height: 40px;
border: none;
outline: none;
cursor: pointer;
}
button#sayit-button:hover {
background: rgba(255, 255, 255, 0.6);
}
button#upload-file {
width: 40px;
height: 40px;
background: transparent;
border: none;
line-height: 40px;
text-align: center;
color: #F44336;
border-radius: 50%;
outline: none;
cursor: pointer;
}
#input-area textarea {
font-family: inherit;
background: transparent;
border: none;
border-bottom: 2px solid #00BCD4;
height: 30px;
flex-grow: 1;
width: 100%;
outline: none;
position: absolute;
top: 0;
left: 0;
color: #FFF;
}
#input-area * {
display: block;
}
#input-area td[width='64'] {
margin: auto;
width: 34px;
height: 34px;
padding-top: 10px;
padding-right: 10px;
}
#input-area td[width='64'] img {
width: 34px;
height: 34px;
}
#input-area td.chat-input {
width: 90%;
position: relative;
}
#input-area tr {
display: flex !important;
align-items: center;
padding-left: 30px;
flex-direction: row
}
td#chat-buttons {
flex-grow: 1;
}
.drawer-handle {
position: fixed;
top: 10px;
left: 10px;
background: #FFF;
color: #212121;
height: 30px;
width: 30px;
line-height: 30px;
text-align: center;
font-size: 20px;
border-radius: 50%;
transition: 300ms all;
cursor: pointer;
z-index: 5000;
}
.drawer-handle.close {
left: calc(10px + 350px);
height: 50px;
width: 50px;
font-size: 30px;
line-height: 50px;
}
.material-drawer {
width: 350px;
height: 100%;
position: fixed;
top: 0;
left: -350px;
background: #364646;
transition: 300ms all;
overflow: auto;
z-index: 2000;
overflow-x: hidden;
}
.material-drawer.opened {
left: 0;
}
.material-drawer .chat-title {
display: block;
text-align: center;
font-size: 40px;
font-weight: 100;
padding-top: 20px;
}
.material-drawer .chat-description {
text-align: center;
padding: 0 10px 0 10px;
}
.material-drawer .list-container {
background: rgba(255, 255, 255, 0.1);
display: block;
/*max-height: 350px;
overflow: auto;*/
}
.list-container .title {
font-size: 12px;
text-transform: uppercase;
display: block;
padding: 10px 5px;
}
.list-container .user {
width: calc(100% - 20px);
display: flex;
padding: 5px 10px 5px 10px;
cursor: pointer;
transition: 300ms all;
}
.list-container .user:hover {
background: rgba(255, 255, 255, 0.34);
}
.list-container .user .image {
align-self: center;
}
.list-container .user .username {
flex-grow: 1;
padding: 0 0 0 30px;
line-height: 30px;
}
.material-drawer .tag-list {
text-align: center;
margin-bottom: 10px;
}
.material-drawer .tag-list .tag {
background: #3F51B5;
color: #FFF;
font-weight: 100;
padding: 5px 10px;
border-radius: 2.5px;
}
.star-list .item {
background: rgba(255, 255, 255, 0.078);
padding: 5px 10px 5px 10px;
margin: 1px 0;
display: flex;
align-items: center;
justify-content: center;
}
.star-list .item .star-container {
display: block;
min-width: 40px;
}
.star-container .star-icon {
cursor: pointer;
color: #009688;
}
.star-container .star-icon.owner {
color: #F44336;
}
.star-list .item .content {
flex-grow: 1;
min-width: calc(100% - 44.567px);
}
#chat, #sidebar, #container, .search-bar-container {
height: 0.1px !important;
width: 0.1.px !important;
overflow: auto;
}
body {
height: 100%;
overflow: hidden;
}
html {
height: 100%;
}
main {
width: 100%;
height: calc(100% - 50px);
overflow: auto;
}
main section.message-container {
width: calc(100% - 20px);
padding: 5px;
display: flex;
position: relative;
align-items: flex-start;
justify-content: flex-start;
background: #263238;
margin: 3px 5px;
align-items: center;
border-radius: 5px;
}
.message-container .avatar {
width: 60px;
height: 60px;
text-align: center;
}
.message-container .avatar img {
width: 48px;
height: 48px;
}
.message-container .message {
display: flex;
align-items: center;
justify-content: flex-start;
flex-grow: 1;
min-height: 48px;
background: rgba(255, 255, 255, 0.1);
margin: 0 0 0 10px;
padding: 5px 5px 5px 10px;
line-height: 1.4445;
border-radius: 5px;
}
button.reply {
background: #3F51B5;
color: #FFF;
width: 0.1px;
height: 0.1px;
text-align: center;
line-height: 30px;
font-size: 14px;
overflow: hidden;
outline: none;
border: none;
border-radius: 50%;
margin: 0 10px 0 0;
position: absolute;
top: 5px;
left: 5px;
cursor: pointer;
transition: 300ms all;
}
.message-container:hover button.reply {
width: 30px !important;
height: 30px !important;
}
button.reply:hover {
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.5);
}
.message-container .name {
font-size: 10px;
line-height: 1;
}
`;
/**
* Query Selector masking
* @param {String} name
*/
function qs(name) {
return document.querySelector(name);
}
/**
* Query Selector All masking
* @param {String} name
*/
function qsA(name) {
return document.querySelectorAll(name);
}
function getHighestResAvatar(url) {
return url.replace('?s=32', '?s=64').replace('?s=16', '?s=64');
}
Array.from(qsA('.more')).forEach((more) => {
more.click();
});
Array.from(qsA('.vote.img')).forEach((v) => {
v.remove();
});
function handleNewMessage(mutations) {
mutations.forEach((mutation) => {
let monologue = mutation.addedNodes[0];
let signature = monologue.childNodes[0];
let avatar = signature.childNodes[0].childNodes[0].childNodes[0];
let username = signature.childNodes[0].childNodes[1].innerHTML;
let messagesContainer = monologue.childNodes[1];
let messageId = monologue.getAttribute('class').match(/\d+/g)[0];
if(messagesContainer.childNodes.length == 1) {
if(typeof messagesContainer.childNodes[0].childNodes[0] == 'undefined') {
// Handle system message
return;
}
let messageContent = (messagesContainer.childNodes[0].childNodes[1].classList.contains('reply-info')) ? messagesContainer.childNodes[0].childNodes[2].innerHTML : messagesContainer.childNodes[0].childNodes[1].innerHTML;
let replyButton = '';
if(messagesContainer.childNodes[0].childNodes[1].classList.contains('reply-info')) {
let inReplyToId = messagesContainer.childNodes[0].childNodes[1].getAttribute('href').split('#')[1];
replyButton = '<button class="reply" data-reply-to="' + inReplyToId + '"><i class="material-icons">reply</i></button>';
}
qs('main').innerHTML += `<section class="message-container" data-message-id="` + messageId + `">` + replyButton +
`<span class="avatar">
<img src="` + getHighestResAvatar(avatar.getAttribute('src')) + `" />
<span class="name">` + ((username.length < 10) ? username : (username.substr(0, 10) + '...')) + `</span>
</span>
<span class="message">` + messageContent + `</span>
<span class="options-container"><i class="material-icons">more_vert</i></span>
</section>`;
}
});
}
let messagesObserver = new MutationObserver(handleNewMessage);
messagesObserver.observe(qs('#chat'), {childList: true});
function initMaterialChat() {
let chatContainer = qs('#chat');
let newChatContainer = document.createElement('main');
Array.from(chatContainer.childNodes).forEach((monologue) => {
if(monologue.classList.contains('system-message-container')) {
// Handle system message
return;
}
let signature = monologue.childNodes[0];
let avatar = signature.childNodes[0].childNodes[0].childNodes[0];
let username = signature.childNodes[0].childNodes[1].innerHTML;
let messagesContainer = monologue.childNodes[1];
let messageId = monologue.getAttribute('class').match(/\d+/g)[0];
if(messagesContainer.childNodes.length == 1) {
let messageContent = (messagesContainer.childNodes[0].childNodes[1].classList.contains('reply-info')) ? messagesContainer.childNodes[0].childNodes[2].innerHTML : messagesContainer.childNodes[0].childNodes[1].innerHTML;
let replyButton = '';
if(messagesContainer.childNodes[0].childNodes[1].classList.contains('reply-info')) {
let inReplyToId = messagesContainer.childNodes[0].childNodes[1].getAttribute('href').split('#')[1];
replyButton = '<button class="reply" data-reply-to="' + inReplyToId + '"><i class="material-icons">reply</i></button>';
}
newChatContainer.innerHTML += `<section class="message-container" data-message-id="` + messageId + `">` + replyButton +
`<span class="avatar">
<img src="` + getHighestResAvatar(avatar.getAttribute('src')) + `" />
<span class="name">` + ((username.length < 10) ? username : (username.substr(0, 10) + '...')) + `</span>
</span>
<span class="message">` + messageContent + `</span>
<span class="options-container"><i class="material-icons">more_vert</i></span>
</section>`;
} else {
Array.from(messagesContainer.childNodes).forEach((child, key) => {
let toAppend = `<section class="message-container">
<span class="avatar">
<img src="` + getHighestResAvatar(avatar.getAttribute('src')) + `" />
<span class="name">` + ((username.length < 10) ? username : (username.substr(0, 10) + '...')) + `</span>
</span>
`;
if(child.classList.contains('timestamp')) {
return;
}
let replyButton = '';
if(child.childNodes[1].classList.contains('reply-info')) {
let inReplyToId = child.childNodes[1].getAttribute('href').split('#')[1];
replyButton = '<button class="reply" data-reply-to="' + inReplyToId + '"><i class="material-icons">reply</i></button>';
}
let messageContent = (child.childNodes[1].classList.contains('reply-info')) ? child.childNodes[2].innerHTML : child.childNodes[1].innerHTML;
toAppend += messageContent + '</section>';
});
}
});
document.body.appendChild(newChatContainer);
}
/**
*
* @param {HTMLElement} drawer
*/
function fillDrawer(drawer) {
drawer.innerHTML += '<span class="chat-title">' + qs('#roomname').innerText + '</span>';
drawer.innerHTML += '<p class="chat-description">' + qs('#roomdesc').innerHTML + '</p>';
let drawerTags = document.createElement('div');
drawerTags.classList.add('tag-list');
Array.from(qs('#room-tags').childNodes).forEach((tag) => {
drawerTags.appendChild(tag);
});
drawer.appendChild(drawerTags);
let usersList = document.createElement('section');
usersList.classList.add('list-container');
let userListTitle = document.createElement('span');
userListTitle.classList.add('title');
userListTitle.innerText = 'Users Present';
usersList.appendChild(userListTitle);
// present users
Array.from(qs('#present-users').childNodes).forEach((users) => {
if(users.childNodes[0] != null) {
let userId = users.getAttribute('id').replace('present-user-', '');
let userImage = users.childNodes[0].childNodes[0].cloneNode();
userImage.classList.add('image');
let username = userImage.getAttribute('title');
let usernameElement = document.createElement('span');
usernameElement.classList.add('username');
usernameElement.innerText = username;
let userLastActivity = users.childNodes[1].childNodes[0].cloneNode();
let drawerUserElement = document.createElement('div');
drawerUserElement.classList.add('user');
drawerUserElement.appendChild(userImage);
drawerUserElement.appendChild(usernameElement);
drawerUserElement.setAttribute('data-username', username);
drawerUserElement.setAttribute('data-user-id', userId);
usersList.appendChild(drawerUserElement);
}
});
drawer.appendChild(usersList);
let starList = document.createElement('section');
starList.classList.add('list-container');
starList.classList.add('star-list');
starList.innerHTML += '<span class="title">Star List</span>';
Array.from(qs('.votesummary').childNodes[1].childNodes).forEach((starredItem, k) => {
if(k % 2) {
let messageId = starredItem.getAttribute('id').replace('summary_', '');
let starCountElement = starredItem.childNodes[1];
if(typeof starCountElement.childNodes[2] == 'undefined') {
return;
}
let starCount = starCountElement.childNodes[2].innerText;
let starredByMe = starCountElement.classList.contains('user-star');
let ownerStarred = starCountElement.classList.contains('owner-star');
starCountElement.remove();
starredItem.childNodes[starredItem.childNodes.length - 2].remove();
let tempStr = `<div class="item">
<span class="star-container" data-message-id="` + messageId + `">`;
if(starredByMe) {
if(ownerStarred) {
tempStr += '<span class="star-icon owner"><i class="material-icons">star</i></span>';
} else {
tempStr += '<span class="star-icon"><i class="material-icons">star</i></span>';
}
} else {
if(ownerStarred) {
tempStr += '<span class="star-icon owner"><i class="material-icons">star_border</i></span>';
} else {
tempStr += '<span class="star-icon"><i class="material-icons">star_border</i></span>';
}
}
tempStr += starCount + `</span>
<span class="content">` + starredItem.innerHTML + `</span>
</div>`;
starList.innerHTML += tempStr;
}
});
drawer.appendChild(starList);
}
function customButtons() {
qs('#sayit-button').innerHTML = '<i class="material-icons">send</i>';
qs('#upload-file').innerHTML = '<i class="material-icons">cloud_upload</i>';
}
qs('[rel="stylesheet"]').remove();
// Remove other stuffs
qs('#footer-legal').remove();
qs('#footer-logo').remove();
// Inject stylesheet
// But first create a style tag
let styleElement = document.createElement('style');
styleElement.innerText = R11MATERIAL_STYLESHEET_MIN;
document.head.appendChild(styleElement);
// Create search bar
let searchBarContainer = document.createElement("nav");
searchBarContainer.classList.add('search-bar-container');
let searchInput = document.createElement('input');
searchInput.classList.add('search-input');
searchBarContainer.appendChild(searchInput);
document.body.appendChild(searchBarContainer);
// Create a drawer handler
let drawerHandle = document.createElement('div');
drawerHandle.classList.add('drawer-handle');
drawerHandle.innerHTML = '<i class="material-icons">menu</i>';
document.body.appendChild(drawerHandle);
let drawer = document.createElement('aside');
drawer.classList.add('material-drawer');
document.body.appendChild(drawer);
fillDrawer(drawer);
// Create the custom messages from stock
initMaterialChat();
customButtons();
let drawerToggle = false;
drawerHandle.addEventListener('click', (e) => {
if(!drawerToggle) {
drawer.classList.add('opened');
drawerHandle.classList.add('close');
drawerHandle.innerHTML = '<i class="material-icons">arrow_back</i>';
drawerToggle = true;
} else {
drawer.classList.remove('opened');
drawerHandle.classList.remove('close');
drawerHandle.innerHTML = '<i class="material-icons">menu</i>';
drawerToggle = false;
}
});
qs('.drawer-handle').click();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment