refactor(auto-pause): rename file to scroll-out-player, add more feature

This commit is contained in:
FoundTheWOUT 2021-04-27 16:32:07 +08:00
parent 530fea0cc3
commit ed92b2998c
7 changed files with 136 additions and 84 deletions

View File

@ -678,13 +678,16 @@ Resource.manifest = {
},
},
autoPlayControl: '传统连播模式',
autoPauseVideo: {
scrollOutPlayer: {
displayNames: {
autoPauseVideo: '自动暂停视频',
triggerPausePlace: '触发暂停位置'
scrollOutPlayer: '当播放器退出页面时',
triggerPlayerOutPlace: '选定触发位置',
autoPause: '自动暂停',
autoLightOn: '自动开灯'
},
reloadable: true,
dropdown:{
key: 'triggerPausePlace',
key: 'triggerPlayerOutPlace',
items: ['视频顶部' ,'视频中间', '视频底部']
}
}

View File

@ -256,8 +256,11 @@ export const settings = {
fullscreenGiftBox: false,
autoPlayControl: true,
cache: {},
autoPauseVideo: true,
triggerPausePlace: '视频中间',
scrollOutPlayer: true,
triggerPlayerOutPlace: '视频中间',
lightOOVideoOut: true,
autoPause: true,
autoLightOn: true,
}
const fixedSettings = {
seedsToCoins: false,

6
src/global.d.ts vendored
View File

@ -518,8 +518,10 @@ declare global {
liveSpeedBoost: boolean,
checkInCenter: boolean,
fullscreenGiftBox: boolean,
autoPauseVideo: boolean,
triggerPausePlace: string[],
scrollOutPlayer: boolean,
triggerPlayerOutPlace: string[],
autoPause: boolean,
autoLightOn: boolean,
}
const GM_info: MonkeyInfo
function GM_xmlhttpRequest(details: MonkeyXhrDetails): { abort: () => void }

View File

@ -75,8 +75,10 @@
<checkbox indent="0" key="removeVideoPopup" dependencies=""></checkbox>
<checkbox indent="0" key="removeVotePopup" dependencies=""></checkbox>
<checkbox indent="0" key="autoPlayControl" dependencies=""></checkbox>
<checkbox indent="0" key="autoPauseVideo" dependencies=""></checkbox>
<dropdown indent="1" key="triggerPausePlace" dependencies="autoPauseVideo"></dropdown>
<checkbox indent="0" key="scrollOutPlayer" dependencies=""></checkbox>
<dropdown indent="1" key="triggerPlayerOutPlace" dependencies="scrollOutPlayer"></dropdown>
<checkbox indent="1" key="autoPause" dependencies="scrollOutPlayer"></checkbox>
<checkbox indent="1" key="autoLightOn" dependencies="scrollOutPlayer"></checkbox>
<category icon="style">样式</category>
<li class="indent-0 folded">
<label class="gui-settings-textbox-container">

View File

@ -239,6 +239,10 @@ export const toolTips = new Map<keyof BilibiliEvolvedSettings, string>([
[`fullscreenGiftBox`, /*html*/`在网页全屏状态下, 可以直接点开礼物包裹, 方便送辣条和小心心.`],
[`keymapPreset`, /*html*/`更换快捷键的预设.`],
[`autoPlayControl`, /*html*/`使用传统的连播模式, 视频有多P时 / 在收藏夹或稍后再看列表里时自动开启连播, 单P视频自动关闭连播防止播放推荐视频.`],
[`scrollOutPlayer`, /*html*/`播放器被移出页面时触发动作.`],
[`autoPause`, /*html*/`播放器的<span>选定触发位置</span>被移出页面时自动暂停播放, 且当播放器回来时恢复播放.`],
[`autoLightOn`, /*html*/`在没有开启自动暂停, 且开启了播放时自动关灯, 那么该功能会在播放器的<span>选定触发位置</span>被移出页面时自动开灯, 当播放器回来时自动关灯.
<b>: 在自动暂停开启时, </b>`]
]);
export default {
export: { toolTips },

View File

@ -1,74 +0,0 @@
const video = dq('.bilibili-player-video video') as HTMLVideoElement;
let mode = '视频中间';
enum MODE {
TOP = '视频顶部',
MID = '视频中间',
BOT = '视频底部',
}
function getToTop(_mode: string, client: DOMRect): number {
switch (_mode) {
case MODE.TOP:
return client?.top;
case MODE.MID:
return client?.top + client?.height / 2;
case MODE.BOT:
return client?.top + client?.height;
default:
return 0;
}
}
// run callback when video el scroll out.
/**
*
* @param _mode - when callback should trigger
* @param callback
* @param handelScrollBack - a func which called onVideoBack
*/
function onVideoOut(_mode: string, callback?: () => void) {
const videoClient = video?.getBoundingClientRect();
if (videoClient?.top && videoClient.height) {
let toTop = getToTop(_mode, videoClient);
if (!video.paused && toTop <= 0) {
callback ? callback() : '';
window.removeEventListener('scroll', onVideoOutEvent);
// get ready to check when the video el came back.
window.addEventListener('scroll', onVideoBackEvent, {
passive: true,
});
}
}
}
function onVideoOutEvent() {
onVideoOut(mode, () => video.pause());
}
// run callback when video el scroll back.
function onVideoBack(_mode: string, callback?: () => void) {
const videoClient = video?.getBoundingClientRect();
if (videoClient?.top && videoClient.height) {
let toTop = getToTop(_mode, videoClient);
if (video.paused && toTop >= 0) {
callback ? callback() : '';
// this is do by
// window.addEventListener('scroll',onVideoOut)
window.removeEventListener('scroll', onVideoBackEvent);
}
}
}
function onVideoBackEvent() {
onVideoBack(mode, () => video.play());
}
(async () => {
addSettingsListener('triggerPausePlace', (value) => (mode = value));
Observer.videoChange(async () => {
video.addEventListener('play', () => {
window.addEventListener('scroll', onVideoOutEvent, { passive: true });
});
});
})();

View File

@ -0,0 +1,112 @@
let videoEl: HTMLVideoElement;
let mode = '视频中间';
enum MODE {
TOP = '视频顶部',
MID = '视频中间',
BOT = '视频底部',
}
function getToTop(_mode: string, client: DOMRect): number {
switch (_mode) {
case MODE.TOP:
return client?.top;
case MODE.MID:
return client?.top + client?.height / 2;
case MODE.BOT:
return client?.top + client?.height;
default:
return 0;
}
}
// run callback when video el scroll out.
function handlePlayerOut(_mode: string, callback?: () => void) {
const videoClient = videoEl?.getBoundingClientRect();
if (videoClient?.top && videoClient.height) {
let toTop = getToTop(_mode, videoClient);
if (toTop <= 0) {
callback ? callback() : '';
// get ready to check when the videoEl el came back.
window.addEventListener('scroll', onPlayerBackEvent, {
passive: true,
});
window.removeEventListener('scroll', onPlayerOutEvent);
}
}
}
// run callback when video el scroll back.
function handlePlayerBack(_mode: string, callback?: () => void) {
const videoClient = videoEl?.getBoundingClientRect();
if (videoClient?.top && videoClient.height) {
let toTop = getToTop(_mode, videoClient);
if (toTop >= 0) {
callback ? callback() : '';
window.addEventListener('scroll', onPlayerOutEvent, {
passive: true,
});
window.removeEventListener('scroll', onPlayerBackEvent);
}
}
}
let lightOff = () => {};
let lightOn = () => {};
async function initLights() {
await SpinQuery.unsafeJquery();
const settingsButton = await SpinQuery.any(() =>
unsafeWindow.$('.bilibili-player-video-btn-setting')
);
if (!settingsButton) {
return;
}
settingsButton.mouseover().mouseout();
const setLight = async (state: boolean) => {
const checkbox = (await SpinQuery.select(
'.bilibili-player-video-btn-setting-right-others-content-lightoff .bui-checkbox-input'
)) as HTMLInputElement;
checkbox.checked = state;
raiseEvent(checkbox, 'change');
};
lightOff = () => setLight(true);
lightOn = () => setLight(false);
}
function onPlayerOutEvent() {
handlePlayerOut(mode, () => {
if (settings.autoPause && !videoEl.paused) videoEl.pause();
// 满足条件: 自动开灯功能启用、自动关灯功能启用、没有启用自动暂停
// 补充: 当启用自动关灯与自动暂停时, 自动开灯动作由自动暂停完成
if (settings.autoLightOn && settings.autoLightOff && !settings.autoPause)
lightOn();
});
}
function onPlayerBackEvent() {
handlePlayerBack(mode, () => {
if (settings.autoPause && videoEl.paused) videoEl.play();
// 回来时自动关灯
// 满足条件: 自动开灯功能启用、自动关灯功能启用、没有启用自动暂停、视频播放中
if (settings.autoLightOn && settings.autoLightOff && !settings.autoPause && !videoEl.paused)
lightOff();
});
}
async function setup() {
await initLights();
addSettingsListener('triggerPlayerOutPlace', (value) => (mode = value));
videoEl = dq('.bilibili-player-video video') as HTMLVideoElement;
window.addEventListener('scroll', onPlayerOutEvent, { passive: true });
}
setup();
export default {
reload: () => {
window.addEventListener('scroll', onPlayerOutEvent, { passive: true });
},
unload: () => {
window.removeEventListener('scroll', onPlayerBackEvent);
window.removeEventListener('scroll', onPlayerOutEvent);
},
};