// ==UserScript==
// @name gitlab小帮手:一键复制url与commit信息,一键展开收起diff模块,便捷选择commit信息创建pr,自动设置指派人和review人
// @name:zh-CN gitlab小帮手:一键复制url与commit信息,一键展开收起diff模块,便捷选择commit信息创建pr,自动设置指派人和review人
// @namespace http://tampermonkey.net/
// @version 0.5.0
// @description 1.一键复制url与commit信息;2.一键展开收起diff模块;3.自动设置指派人和review人
// @author zzailianlian
// @require https://unpkg.com/clipboard@2.0.11/dist/clipboard.min.js
// @match *://gitlab.babytree-inc.com/**/merge_requests/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=meitun-test.com
// @license MIT
// @run-at document-idle
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_addElement
// @downloadURL https://update.greasyfork.icu/scripts/449585/gitlab%E5%B0%8F%E5%B8%AE%E6%89%8B%3A%E4%B8%80%E9%94%AE%E5%A4%8D%E5%88%B6url%E4%B8%8Ecommit%E4%BF%A1%E6%81%AF%EF%BC%8C%E4%B8%80%E9%94%AE%E5%B1%95%E5%BC%80%E6%94%B6%E8%B5%B7diff%E6%A8%A1%E5%9D%97%EF%BC%8C%E4%BE%BF%E6%8D%B7%E9%80%89%E6%8B%A9commit%E4%BF%A1%E6%81%AF%E5%88%9B%E5%BB%BApr%EF%BC%8C%E8%87%AA%E5%8A%A8%E8%AE%BE%E7%BD%AE%E6%8C%87%E6%B4%BE%E4%BA%BA%E5%92%8Creview%E4%BA%BA.user.js
// @updateURL https://update.greasyfork.icu/scripts/449585/gitlab%E5%B0%8F%E5%B8%AE%E6%89%8B%3A%E4%B8%80%E9%94%AE%E5%A4%8D%E5%88%B6url%E4%B8%8Ecommit%E4%BF%A1%E6%81%AF%EF%BC%8C%E4%B8%80%E9%94%AE%E5%B1%95%E5%BC%80%E6%94%B6%E8%B5%B7diff%E6%A8%A1%E5%9D%97%EF%BC%8C%E4%BE%BF%E6%8D%B7%E9%80%89%E6%8B%A9commit%E4%BF%A1%E6%81%AF%E5%88%9B%E5%BB%BApr%EF%BC%8C%E8%87%AA%E5%8A%A8%E8%AE%BE%E7%BD%AE%E6%8C%87%E6%B4%BE%E4%BA%BA%E5%92%8Creview%E4%BA%BA.meta.js
// ==/UserScript==
(function () {
'use strict';
// 因为有些dom是异步渲染的,因此需要用到loopObserver来确保dom刷新时执行指定操作
function loopObserver({ getObserver = () => {}, action = () => {} }) {
const interval = setInterval(() => {
const observerRecords = getObserver();
if (observerRecords) {
action();
clearInterval(interval);
}
}, 200);
}
// commit列表
function initCommitList() {
loopObserver({
getObserver: () => document.querySelectorAll('li .commit'),
action: () => {
const commitList = Array.from(document.querySelectorAll('li .commit'))?.map(dom => ({
commitContent: dom.querySelector('.commit-row-message').innerText,
commitAuthor: dom.querySelector('.commit-author-link').innerText,
}));
function insertCommentTitle(e) {
const innerCommitDom = e.target.querySelector('span') || e.target;
document.querySelector('input[required="required"]').value = innerCommitDom.innerText;
}
if (commitList.length <= 1) return;
if (document.querySelector('div.text-muted')) {
document.querySelector('div.text-muted').innerHTML = `
${commitList
.map(
commit =>
`
${commit.commitAuthor}:${commit.commitContent}
`
)
.join('')}
`;
}
if (document.querySelector('.optional-commit-info-wrapper')) {
document.querySelector('.optional-commit-info-wrapper').onclick = insertCommentTitle;
}
},
});
}
// Array.from(document.querySelectorAll('a.commit-row-message')).map(item=>item.innerText)
// 复制按钮
function initCopyBtn() {
const commitDom = $('.detail-page-description h2');
const btn = $('');
btn.on('click', copyUrlAndCommitInfo);
const commitText = $('.detail-page-description h2:not(button)').text();
commitDom.append(btn);
const info = `${window.location.href.match(/.+merge_requests\/\d+/)?.[0]}
${commitText}`;
function copyUrlAndCommitInfo() {
copyText(info);
}
}
// 展开收起diff
function initExpandBtn() {
const expandBtn = $(
''
);
let intervalTimer = setInterval(() => {
if (document.querySelector('#__expand_btn')) return;
if ($('.mr-version-menus-container').length) {
$('.mr-version-menus-container').css({ zIndex: '-1' }).prepend(expandBtn);
expandBtn.on('click', function () {
const originIsClicked = $(this).attr('isclicked');
const isClicked = originIsClicked == 'true';
$(this).attr('isclicked', originIsClicked == 'true' ? 'false' : 'true');
if (isClicked) {
$('aside').map(function () {
$(this).attr('style', '');
});
$('aside').eq(0).parent().attr('style', '');
$('aside').eq(0).next().attr('style', '');
$('.diff-files-holder').attr('style', '');
} else {
$('aside').map(function () {
$(this).css({ width: 0 });
});
$('.diff-files-holder').attr('style', 'max-width:unset');
$('aside').eq(0).parent().css({ paddingLeft: 0 });
$('aside')
.eq(0)
.next()
.css({ paddingRight: isClicked ? null : 0 });
}
});
clearInterval(intervalTimer);
}
}, 200);
}
window.addEventListener('load', function () {
initCopyBtn();
initExpandBtn();
document.querySelector('.diffs-tab').addEventListener(
'click',
function () {
initExpandBtn();
},
true
);
initCommitList();
initAssignAndReviewer();
});
// 更改assign跟reviewer的人
function initAssignAndReviewer() {
const assign = 'zhaoqian';
const reviewer = 'zhaoqian';
if (location.href.includes('merge_requests')) {
// Assign自动赋值
loopObserver({
getObserver: () => document.querySelector('.merge-request-assignee'),
action: () => {
document.querySelector('.merge-request-assignee button').click();
document.querySelector('.merge-request-assignee input[type="search"]').value = assign;
loopObserver({
getObserver: () =>
document.querySelectorAll('.merge-request-assignee .dropdown-content a .dropdown-menu-user-username')
.length === 1,
action: () => {
document
.querySelector('.merge-request-assignee .dropdown-content a .dropdown-menu-user-username')
.click();
// Reviewer自动赋值
loopObserver({
getObserver: () => document.querySelector('.merge-request-reviewer'),
action: () => {
document.querySelector('.merge-request-reviewer button').click();
document.querySelector('.merge-request-reviewer input[type="search"]').value = reviewer;
loopObserver({
getObserver: () =>
document.querySelectorAll(
'.merge-request-reviewer .dropdown-content a .dropdown-menu-user-username'
).length === 1,
action: () => {
document
.querySelector('.merge-request-reviewer .dropdown-content a .dropdown-menu-user-username')
.click();
},
});
},
});
},
});
},
});
}
}
// 复制文案
function copyText(value) {
if (value == null || value === '') return false;
let textarea = document.createElement('textarea');
textarea.style.height = '0';
textarea.style.width = '0';
textarea.value = value;
const firstDiv = document.body.querySelector('div');
firstDiv.parentNode.insertBefore(textarea, firstDiv);
textarea.focus();
textarea.setSelectionRange ? textarea.setSelectionRange(0, textarea.value.length) : textarea.select();
let result = document.execCommand('copy');
firstDiv.parentNode.removeChild(textarea);
return result;
}
})();