// ==UserScript==
// @name 高效探索 - 阿儿法营/稽木世界社区优化插件
// @namespace https://waterblock79.github.io/
// @version 0.2.0
// @description 提供优化、补丁及小功能提升社区内的探索效率和用户体验
// @author waterblock79
// @match http*://gitblock.cn/*
// @match http*://aerfaying.com/*
// @match http*://3eworld.cn/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=gitblock.cn
// @grant none
// @license MIT
// @downloadURL none
// ==/UserScript==
(function() {
const encodeHtml = Blockey.Utils.encodeHtml;
// === 在 ajax 上挂载事件 ===
$.ajaxSettings.xhr = function pf(){
try{
let xhr = new XMLHttpRequest;
xhr.onload = e => {
if(JSON.parse(e.target.response).userMap != undefined){
let userMap = JSON.parse(e.target.response).userMap;
Object.keys(userMap).forEach( key => window.userInfoCache[key] = userMap[key] )
}
}
return xhr;
}catch(e){}
};
// === 传入评论 ID,显示评论详尽信息 ===
window.showCommentInfo = (id) => {
Blockey.Utils.ajax({
url:'/WebApi/Comment/GetPage',
data: {
forType: Blockey.Utils.getContext().targetType,
forId: Blockey.Utils.getContext().target.id,
pageIndex: 1,
scrollToCommentId: id
},
success: (data) => {
data = data.scrollToThread.id == id ? data.scrollToThread : data.replies.filter( d => { return d.id == id } )[0] ;
let linkToComment = (location.href.includes('#') ? location.href.split('#')[0] : location.href) + '#commentId=' + id;
Blockey.Utils.confirm(
"评论",
` 评论时间
${ ( new Date(data.createTime) ).toLocaleString() }
评论链接
${linkToComment}
${ data.content }
`
)
}
})
}
//
// === 评论 ID 显示 & 点击显示详细信息事件 ===
if( localStorage.getItem('explore:comment_id') == null ){
localStorage.setItem('explore:comment_id',1)
}
setInterval(()=>{
let comments = document.querySelectorAll('.comment_comment_P_hgY');
for( let i = 0; i < comments.length; i++ ) {
comments[i].querySelector('.comment_time_3A6Cg').innerHTML +=
comments[i].querySelector('.comment_time_3A6Cg').innerHTML.includes('#') || localStorage.getItem('explore:comment_id') == 0 || comments[i].id == '' ?
`` : ` #${comments[i].id} `
}
},1000)
document.querySelector('.menu-bar_topnav_3HgyJ').style.zIndex = 999999999
//
// === 用户信息显示 ===
if(location.pathname.match(/\/Users\/(\w+\/?)/g) != null) { // 若链接匹配 /Users/NUMBER/ 或 /Users/NUMBER
// 轮询等待“加入时间”的元素被创建
let setUserInfo = setInterval ( () => {
if(document.querySelector('.profile-head_join_HPHzg') != null) {
// 请求用户邀请 API
Blockey.Utils.ajax({
url: `/WebApi/Users/${Blockey.Utils.getContext().target.id}/GetPagedInvitedUsers`,
data: {
pageIndex: 1, pageSize: 60
},
success: (data) => {
let length = data.invitorPath.length;
// 如果这个人是被邀请的,那就在在“xxxx-xx-xx加入”后面加上邀请信息
document.querySelector('.profile-head_join_HPHzg').querySelector('small').innerHTML +=
length == 1 ? '' : ` · 由${ encodeHtml(data.invitorPath[length-2].username) }邀请`;
}
})
// 清掉这个轮询
clearInterval(setUserInfo);
}
}, 200);
}
//
// === 修复作品“继续加载”的预览图尺寸问题 ===
let fixProjectImage = setInterval ( () => {
if(document.querySelector('.img-responsive') != null) {
document.querySelector('.img-responsive').style['width'] = '100%';
clearInterval(fixProjectImage);
}
}, 200);
//
// === 悬停在用户名链接上展示用户卡片 ===
if( localStorage.getItem('explore:user_box') == null ){
localStorage.setItem('explore:user_box',1)
}
;
let style = document.createElement('style');
style.innerHTML = '.comment_info_2Sjc0 { overflow: inherit !important } .'
document.head.appendChild(style);
;
window.userInfoCache = {};
let userBox = setInterval ( () => {
// 真人认证等级、用户等级所对应的 class
let humanVerifiedClass = {
1: "human-verified-icon_verifiedLevel-1_-X3x2",
2: "human-verified-icon_verifiedLevel-2_1Byk3",
3: "human-verified-icon_verifiedLevel-3_2hde9",
4: "human-verified-icon_verifiedLevel-4_2gbJU",
5: "human-verified-icon_verifiedLevel-5_2isZE",
},
levelClass = (level) => {
let classList = {
"level-0": "user-level_level-0_3HviE",
"level-1": "user-level_level-1_uTxh6",
"level-2": "user-level_level-2_3b_PK",
"level-3": "user-level_level-3_1Rr5c",
"level-4": "user-level_level-4_18jcT",
};
if(0 data.onmouseenter = (e)=>{
if( e.target.classList.contains('inBox') ) return;
// 有时候加载比较满慢会同时出现俩用户框,于是我觉得可以让在创建新用户框的时候先检测一下,清除掉不是属于自己的、多余的用户框
document.querySelectorAll('.user_box').forEach( d => { if (data.id != d.id ) { d.remove() } } )
// 传入数据,在该用户名下生成一个用户简讯框
let addUserBox = (data, commentId) => {
let dom = document.createElement('div');
dom.style = 'z-index: 797979;position: absolute;width: 75%;height: 7.5em;border: 1px #4c97ff solid;border-radius: 3px;background: white;display: flex;align-items: center;';
dom.classList.add('user_box');
dom.id = commentId;
data.user = data;
dom.innerHTML = `
${ data.user.adminLevel > 0 && localStorage.getItem('explore:show-admin-badge') != 'disabled' ?
`` : ``
}
Lv.${data.user.level}
${data.user.goldCoins} 金币
${new Date(data.user.createTime).toLocaleDateString().replaceAll('/','-')} 加入
`;
e.target.parentNode.appendChild(dom);
};
// 从用户名的链接提取用户 ID
let userId = Number(e.target.href.match(/[0-9]+/g)[0]);
// 如果这个用户的信息没被存下,那就发送请求获取数据
if( window.userInfoCache[userId] == undefined ) {
let cId = data.parentElement.parentElement.id; // 请求里面的 data 给代表这个链接元素的外面的 data 覆盖掉了......
$.ajax({ url: `/WebApi/Users/${e.target.href.match(/[0-9]+/g)[0]}/Get`, method: 'post', success: (data) => {
addUserBox( data, cId );
// 存好这个用户的数据,下回就不再请求了
window.userInfoCache[userId] = data;
} });
} else {
addUserBox( window.userInfoCache[userId], data.parentElement.parentElement.id )
}
} )
// 给每个评论的用户名加上“鼠标离开”的事件
document.querySelectorAll('a.comment_name_2ZnFZ').forEach( data => data.onmouseleave = data.classList.contains('inBox') ? null : ()=>{ document.querySelectorAll('.user_box').forEach( d => d.remove() ) } );
}, 300);
// 若未开启用户简讯框功能,那就清除掉这个轮询
if( localStorage.getItem('explore:user_box') == 0 ) {
clearInterval(userBox);
}
//
// === 在菜单中插入插件设置 ===
// 植入开启插件设置的函数
window.openSetting = () => {
Blockey.Utils.confirm('插件设置',`
主要功能
小功能
`);
}
// 在用户下拉栏里植入打开插件设置的摁键
document.querySelector('.user-dropdown-menu_wrapper_3RsXx').insertBefore( document.createElement('li'), document.querySelector('#nav-settings') ).innerHTML = `插件设置`;
//
// === 转化全屏蓝色加载 ===
// explore:loading = 0: 不改变, 1: 隐藏并启用左下加载提示, 2: 完全隐藏
if( localStorage.getItem('explore:loading') == null ){
localStorage.setItem('explore:loading', 1)
}
// 如果 explore:loading 设置是 1 或 2
if( localStorage.getItem('explore:loading') >= 1 ) {
var onLoading = false, onProjectLoading = false;
// 把原先的加载遮盖的 Class 加上 Display: none 屏蔽掉
;
let style = document.createElement('style');
style.innerHTML = '.loader_background_1-Rwn { display: none !important }'
document.head.appendChild(style);
;
// 一个小工具,传入选择器,若元素存在便返回 true
var elementExist = (dom) => { return document.querySelector(dom) != null ? true : false }
// 当 explore:loading 设置为 1 便显示左下角加载提示
if( localStorage.getItem('explore:loading') == 1 ) {
// 轮询检测原先全屏加载出现
setInterval(()=>{
// 检测全屏加载遮盖是否存在(用了 not 选择器来排除掉咱自己创建的那个作品加载遮盖)
if(elementExist('.loader_background_1-Rwn:not(#explore-loading-project)')){
// 如果 onLoading 还没被设为 true,那说明还没添加左下角加载提示,就加上先
if(onLoading == false){
// 隐藏原先全屏加载遮盖
document.querySelector('.loader_background_1-Rwn').style.display = 'none';
// 添加左下角加载提示
let loadingElement = document.createElement('div');
loadingElement.style = "width: 5em; height: 5em; position: fixed; background-color: #4c97ff; right: 5%; opacity: 0.8; bottom: 5%; border-radius: 8px;";
loadingElement.id = "explore-loading";
loadingElement.innerHTML = '';
document.body.appendChild(loadingElement)
// 把 onLoading 设为 true
onLoading = true;
// 然而隐藏了蓝色加载提示,作品加载的时候那个没加载出来的白色舞台就会暴露给用户,于是便要给加载中的作品来一个遮盖。
// 如果 onProjectLoading 还没被设为 true,而且是作品在加载(全屏加载遮盖带有类似“加载拓展”等的提示消息)、作品区已经被创建(检测页面上是否有作品区控制区域,就是绿旗、红六边形那个区域)
} else if ( onLoading == true && onProjectLoading == false && elementExist('.loader_message-container-outer_oYjTv') && elementExist('.stage-header_stage-header-wrapper_8psPs') ) {
// 这里检测是否是手机端依靠的是手机端的舞台区域的 class 是 ...-wrapper-mobile_2WJLy,和电脑端不一样
// 使作品区控制区域不可点击(如果是手机端就直接隐藏了)
document.querySelector('.stage-header_stage-header-wrapper_8psPs').style = elementExist('.stage-wrapper_stage-canvas-wrapper-mobile_2WJLy') ? 'display: none;' : 'opacity: 0.5; pointer-events: none;'; // 使其不可点击
// 对症下药,如果是手机端就改手机端的 ...-wrapper-mobile_2WJLy,如果是电脑端就改电脑端的 ...-wrapper_n2Q5r,给它用 Display: none 隐藏掉
document.querySelector( elementExist('.stage-wrapper_stage-canvas-wrapper-mobile_2WJLy') ? '.stage-wrapper_stage-canvas-wrapper-mobile_2WJLy' : '.stage-wrapper_stage-canvas-wrapper_n2Q5r').style = 'display: none'; // 隐藏
// 在作品区添加加载中的蓝色方框(这里其实是把原来的舞台隐藏掉,拿这个东西放上去,看起来像是给原来的舞台加了遮盖,但其实并不是遮盖)
let projectLoadingDOM = document.createElement('div');
projectLoadingDOM.style = "position: relative; border-radius: 8px; padding: 8px; display: block !important; z-index: 1 !important;";
projectLoadingDOM.id = "explore-loading-project";
projectLoadingDOM.classList.add("loader_background_1-Rwn");
projectLoadingDOM.innerHTML = '载入项目
正在创建积木……
载入角色……
载入声音……
加载扩展……
正在创建积木……
呼唤小猫……
传送Nano……
给Gobo充气 …
准备表情……
';
document.querySelector('.stage-wrapper_stage-wrapper_3k56F').appendChild(projectLoadingDOM);
// 把 onProjectLoading 设为 true
onProjectLoading = true;
}
// 如果全屏加载遮盖已经消失了,但是 onLoading 还是 true,说明还没给原来的左下角/作品加载提示移除掉
} else if ( onLoading == true ){
// 移除左下角加载提示
document.querySelector('#explore-loading').remove();
if( onProjectLoading == true ) {
// 把原来禁止点击的、隐藏的恢复原状
document.querySelector('.stage-header_stage-header-wrapper_8psPs').style = '';
document.querySelector( elementExist('.stage-wrapper_stage-canvas-wrapper-mobile_2WJLy') ? '.stage-wrapper_stage-canvas-wrapper-mobile_2WJLy' : '.stage-wrapper_stage-canvas-wrapper_n2Q5r').style = '';
// 移除加载的蓝色方框
document.querySelector('#explore-loading-project').remove();
onProjectLoading = false;
}
// 把 onLoading 设为 false
onLoading = false;
}
},100)
}
}
//
// 添加不文明用语警告的“不再提示”
window.disableBadWordsWarning = false;
setInterval(()=>{
if( document.querySelector('.body.box_box_tWy-0') == null ) return;
if ( document.querySelector('.body.box_box_tWy-0').innerHTML.includes('正在提交的内容中包含疑似不文明用语') ) {
// 禁用了不文明用语警告,那就直接点“确定”
if(window.disableBadWordsWarning) {
document.querySelector('.ok-button').click();
// 如果未禁用不文明用语警告,并且也还没有添加“不再提示”的 checkbox,那就添加上
} else if ( !document.querySelector('.body.box_box_tWy-0').childNodes[0].innerHTML.includes('checkbox') ){
document.querySelector('.body.box_box_tWy-0').childNodes[0].innerHTML += '
谢了,我知道该怎么做';
}
}
},200);
})();