Last active
May 3, 2017 14:37
-
-
Save ikariiin/827c8a280f6bc3c15603f8b8dcd945e2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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