// ==UserScript==
// @name MiGerritPlus
// @namespace thbeliefNameSpace
// @icon https://cnbj1.fds.api.xiaomi.com/info-app-webfile/common-resource/ico/favicon.ico
// @version 1.4.0
// @description some extention for miui gerrit
// @author thbelief
// @match *://gerrit.pt.mioffice.cn/*
// @require https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_deleteValue
// @grant GM_xmlhttpRequest
// @grant GM_notification
// @grant GM_setClipboard
// @grant GM_addStyle
// @grant GM_getResourceText
// @grant GM_getResourceURL
// @grant GM.setValue
// @grant GM.getValue
// @grant GM.registerMenuCommand
// @grant GM.deleteValue
// @grant GM.xmlHttpRequest
// @grant GM.notification
// @grant GM.setClipboard
// @grant unsafeWindow
// @run-at document-end
// @license AGPL
// @downloadURL none
// ==/UserScript==
(function () {
'use strict'
// code region start
/**
* some config
*/
var TAG = "MiGerritPlus"
// control is print log
var isDebug = true
var dashBoardSelf = "https://gerrit.pt.mioffice.cn/dashboard/self"
var intervalTime = 150
var checkboxInsertIndex = 3
// need hide group array
var hideGroupArray = new Array("Your Turn", "Incoming reviews", "CCed on", "Recently closed")
print("origin start")
toastr().info("welcome to use " + TAG)
loadToastrCss()
$(document).ready(function () { main() })
// cur url
var curHerf = window.location.href
// reload because not success sometimes
var isNeedReloadMain = false
// save checkbox and change
var selectChangeMap = new Map()
// copyButton
var copyButton = createClipIcon()
/**
* History and window.hashchange is not role
* so use interval
*/
setInterval(function () {
if (curHerf != window.location.href || isNeedReloadMain) {
isNeedReloadMain = false;
curHerf = window.location.href
print("cur url = " + curHerf)
if (curHerf != dashBoardSelf) {
copyButton.remove()
print("Not dashBoardSelf.Remove copy button")
}
if (curHerf === dashBoardSelf) {
main()
}
}
}, intervalTime);
function loadToastrCss(){
var css = ".toast-title{font-weight:bold}.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a,.toast-message label{color:#fff}.toast-message a:hover{color:#ccc;text-decoration:none}.toast-close-button{position:relative;right:-0.3em;top:-0.3em;float:right;font-size:20px;font-weight:bold;color:#fff;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;opacity:.8;-ms-filter:alpha(opacity=80);filter:alpha(opacity=80)}.toast-close-button:hover,.toast-close-button:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;-ms-filter:alpha(opacity=40);filter:alpha(opacity=40)}button.toast-close-button{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.toast-top-center{top:0;right:0;width:100%}.toast-bottom-center{bottom:0;right:0;width:100%}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:999999}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#toast-container>div{position:relative;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px 3px 3px 3px;-webkit-border-radius:3px 3px 3px 3px;border-radius:3px 3px 3px 3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#fff;opacity:.8;-ms-filter:alpha(opacity=80);filter:alpha(opacity=80)}#toast-container>:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:alpha(opacity=100);filter:alpha(opacity=100);cursor:pointer}#toast-container.toast-top-center>div,#toast-container.toast-bottom-center>div{width:300px;margin:auto}#toast-container.toast-top-full-width>div,#toast-container.toast-bottom-full-width>div{width:96%;margin:auto}.toast{background-color:#030303}.toast-success{background-color:#51a351}.toast-error{background-color:#bd362f}.toast-info{background-color:#2f96b4}.toast-warning{background-color:#f89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4;-ms-filter:alpha(opacity=40);filter:alpha(opacity=40)}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container .toast-close-button{right:-0.2em;top:-0.2em}}@media all and (min-width:241px) and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container .toast-close-button{right:-0.2em;top:-0.2em}}@media all and (min-width:481px) and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}}"
GM_addStyle(css)
}
function print(content) {
if (!isDebug) {
return;
}
console.log(TAG + ": " + content)
}
function main() {
print("main")
var rootDom = document.body.querySelector("gr-app").shadowRoot.getElementById("app-element").shadowRoot.getRootNode();
var mainHeader = rootDom.querySelector("gr-main-header").shadowRoot.getRootNode()
// insert copy button
insertClipIcon(mainHeader.querySelector(".links"))
// remove footer
var footerDom = rootDom.querySelector("footer")
if (footerDom != null) {
print("remove footer")
footerDom.remove()
}
var mainDom = rootDom.querySelector("main")
if (mainDom === null) {
print("main is null")
return
}
var changeDom = mainDom.querySelector("gr-dashboard-view")
if (changeDom === null) {
isNeedReloadMain = true
return
}
var changeList = changeDom.shadowRoot.getRootNode().querySelector("gr-change-list").shadowRoot.getRootNode().querySelectorAll("gr-change-list-section")
// cardArray is per change card
var cardArray = new Array()
for (var i = 0; i < changeList.length; i++) {
cardArray[i] = changeList[i].shadowRoot.getRootNode()
}
if (cardArray.length === 0) {
toastr().warning("operate fail.try to retry")
isNeedReloadMain = true
}
print("cardArray = " + cardArray)
for (var i = 0; i < cardArray.length; i++) {
var curGroupDom = cardArray[i].querySelector(".section-name")
var groupHeaderDom = cardArray[i].querySelector(".groupHeader")
// hide which need to hide group
if (curGroupDom != null && hideGroupArray.includes(curGroupDom.innerText)) {
print("remove " + curGroupDom.innerText)
if (groupHeaderDom !== null) {
groupHeaderDom.remove()
}
var groupContentDom = cardArray[i].querySelector(".groupContent")
if (groupContentDom !== null) {
groupContentDom.remove()
}
// remove noChanges item
var noChangesDom = cardArray[i].querySelector(".noChanges")
if (noChangesDom !== null) {
noChangesDom.remove()
}
// remove group title
if (i != 0) {
var groupTitleDom = cardArray[i].querySelector(".groupTitle")
if (groupTitleDom !== null) {
groupTitleDom.remove()
}
}
}
var groupContentDom = cardArray[i].querySelector(".groupContent")
if (groupContentDom !== null) {
var groupTitleDom = groupContentDom.querySelector(".groupTitle")
if(groupTitleDom.querySelectorAll(".subject").length <= 1){
insertCheckBoxTitle(groupTitleDom)
var list = groupContentDom.querySelectorAll("gr-change-list-item")
insertCheckBox(list)
}
}
}
}
/**
* insert checkbox title
* @param list
*/
function insertCheckBoxTitle(groupTitle) {
var tdList = groupTitle.querySelectorAll("td")
groupTitle.insertBefore(createCheckBoxTitle(), tdList[checkboxInsertIndex])
}
/**
* create checkbox title
* @returns
*/
function createCheckBoxTitle() {
var td = document.createElement("td")
td.className = "subject"
td.innerText = "Select"
return td
}
/**
* insert checkbox to every change
* @param {*} list
*/
function insertCheckBox(list) {
for (var i = 0; i < list.length; i++) {
var tdList = list[i].shadowRoot.getRootNode().querySelectorAll("td")
var cellNumberNode = list[i].shadowRoot.getRootNode().querySelector(".number")
var titleNode = list[i].shadowRoot.getRootNode().querySelector(".content")
var repoNode = list[i].shadowRoot.getRootNode().querySelector(".fullRepo")
var branchNode = list[i].shadowRoot.getRootNode().querySelector(".branch")
const change = new Change(cellNumberNode.querySelector("a").innerText, titleNode.innerText, cellNumberNode.querySelector("a").href, repoNode.innerText, branchNode.querySelector("a").innerText)
list[i].shadowRoot.getRootNode().insertBefore(createCheckBox(change), tdList[checkboxInsertIndex])
}
}
/**
* create checkbox
* @param {*} change
* @returns
*/
function createCheckBox(change) {
var td = document.createElement("td")
var input = document.createElement("input")
input.type = "checkbox"
input.setAttribute("style", "width:20px;height:20px;")
input.onclick = function () {
selectChangeMap.get(this).setIsChecked(this.checked)
//console.log(selectChangeMap.get(this))
}
td.setAttribute("display", "table-cell")
td.setAttribute("vertical-align", "middle")
td.setAttribute("white-space", "nowrap")
td.appendChild(input)
selectChangeMap.set(input, change)
return td
}
/**
* insert copy button
* @param {*} links
*/
function insertClipIcon(links) {
if (links == null) {
return
}
var button = links.querySelector(".copyToClipboard")
// just need one
if (button == null) {
links.appendChild(copyButton)
}
}
/**
* get changes which checked by myselef
* @returns
*/
function getCheckedChange() {
var changes = new Array()
var index = 0
selectChangeMap.forEach(function (value, key) {
if (value.isChecked()) {
key.checked = false
changes[index++] = value
}
})
return changes
}
/**
* create copy button
* @returns
*/
function createClipIcon() {
/**
*