Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

自动暂停与自动关灯 #1785

Merged
merged 5 commits into from
Apr 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/client/resource-manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -678,5 +678,18 @@ Resource.manifest = {
},
},
autoPlayControl: '传统连播模式',
scrollOutPlayer: {
displayNames: {
scrollOutPlayer: '当播放器退出页面时',
scrollOutPlayerTriggerPlace: '选定触发位置',
scrollOutPlayerAutoPause: '自动暂停',
scrollOutPlayerAutoLightOn: '自动开灯'
},
reloadable: true,
dropdown:{
key: 'scrollOutPlayerTriggerPlace',
items: ['视频顶部' ,'视频中间', '视频底部']
}
}
}
export const resourceManifest = Resource.manifest
4 changes: 4 additions & 0 deletions src/client/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@ export const settings = {
fullscreenGiftBox: false,
autoPlayControl: true,
cache: {},
scrollOutPlayer: true,
scrollOutPlayerTriggerPlace: '视频中间',
scrollOutPlayerAutoPause: true,
scrollOutPlayerAutoLightOn: true,
}
const fixedSettings = {
seedsToCoins: false,
Expand Down
4 changes: 4 additions & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,10 @@ declare global {
liveSpeedBoost: boolean,
checkInCenter: boolean,
fullscreenGiftBox: boolean,
scrollOutPlayer: boolean,
scrollOutPlayerTriggerPlace: string[],
scrollOutPlayerAutoPause: boolean,
scrollOutPlayerAutoLightOn: boolean,
}
const GM_info: MonkeyInfo
function GM_xmlhttpRequest(details: MonkeyXhrDetails): { abort: () => void }
Expand Down
4 changes: 4 additions & 0 deletions src/utils/gui-settings/gui-settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +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="scrollOutPlayer" dependencies=""></checkbox>
<dropdown indent="1" key="scrollOutPlayerTriggerPlace" dependencies="scrollOutPlayer"></dropdown>
<checkbox indent="1" key="scrollOutPlayerAutoPause" dependencies="scrollOutPlayer"></checkbox>
<checkbox indent="1" key="scrollOutPlayerAutoLightOn" dependencies="scrollOutPlayer"></checkbox>
<category icon="style">样式</category>
<li class="indent-0 folded">
<label class="gui-settings-textbox-container">
Expand Down
4 changes: 4 additions & 0 deletions src/utils/gui-settings/tooltip/settings-tooltip.zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ export const toolTips = new Map<keyof BilibiliEvolvedSettings, string>([
[`fullscreenGiftBox`, /*html*/`在网页全屏状态下, 可以直接点开礼物包裹, 方便送辣条和小心心.`],
[`keymapPreset`, /*html*/`更换快捷键的预设.`],
[`autoPlayControl`, /*html*/`使用传统的连播模式, 视频有多P时 / 在收藏夹或稍后再看列表里时自动开启连播, 单P视频自动关闭连播防止播放推荐视频.`],
[`scrollOutPlayer`, /*html*/`当播放器被移出页面时触发动作.`],
[`scrollOutPlayerAutoPause`, /*html*/`当播放器的<span>选定触发位置</span>被移出页面时自动暂停播放, 且当播放器回来时恢复播放.`],
[`scrollOutPlayerAutoLightOn`, /*html*/`在没有开启自动暂停, 且开启了播放时自动关灯, 那么该功能会在播放器的<span>选定触发位置</span>被移出页面时自动开灯, 当播放器回来时自动关灯.
<b>注: 在自动暂停开启时, 该功能会被忽略</b>`]
]);
export default {
export: { toolTips },
Expand Down
147 changes: 147 additions & 0 deletions src/video/scroll-out-player.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
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.
let handlePlayerOut = function (_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 video el came back.
window.addEventListener('scroll', onPlayerBackEvent, {
passive: true,
});
// remove out listener when got out.
window.removeEventListener('scroll', onPlayerOutEvent);
}
}
};

// run callback when video el scroll back.
let handlePlayerBack = function (_mode: string, callback?: () => void) {
const videoClient = videoEl?.getBoundingClientRect();
if (videoClient?.top && videoClient.height) {
let toTop = getToTop(_mode, videoClient);
if (toTop >= 0) {
callback ? callback() : '';
// this will done by play listener
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.scrollOutPlayerAutoPause && !videoEl.paused) videoEl.pause();
// 满足条件: 自动开灯功能启用、自动关灯功能启用、没有启用自动暂停
// 补充: 当启用自动关灯与自动暂停时, 自动开灯动作由自动暂停完成
if (
settings.scrollOutPlayerAutoLightOn &&
settings.autoLightOff &&
!settings.scrollOutPlayerAutoPause
)
lightOn();
});
}

function onPlayerBackEvent() {
handlePlayerBack(mode, () => {
if (settings.scrollOutPlayerAutoPause && videoEl.paused) videoEl.play();
// 回来时自动关灯
// 满足条件: 自动开灯功能启用、自动关灯功能启用、没有启用自动暂停、视频播放中
if (
settings.scrollOutPlayerAutoLightOn &&
settings.autoLightOff &&
!settings.scrollOutPlayerAutoPause &&
!videoEl.paused
)
lightOff();
});
}

function addPlayerOutEvent() {
window.addEventListener('scroll', onPlayerOutEvent, { passive: true });
}

function removePlayerOutEvent() {
window.removeEventListener('scroll', onPlayerOutEvent);
}

function mountListener() {
Observer.videoChange(async () => {
videoEl.addEventListener('play', addPlayerOutEvent);
// onPlayerOutEvent 不会在我们手动暂停视频时移除, 所以需要监听暂停.
videoEl.addEventListener('pause', removePlayerOutEvent);
videoEl.addEventListener('ended', removePlayerOutEvent);
});
}

async function setup() {
await initLights();
addSettingsListener('triggerPlayerOutPlace', (value) => (mode = value));
videoEl = dq('.bilibili-player-video video') as HTMLVideoElement;
mountListener();
}
setup();

export default {
reload: () => {
window.addEventListener('scroll', onPlayerOutEvent);
mountListener();
},
unload: () => {
// remove all listener
Observer.videoChange(async () => {
videoEl.removeEventListener('play', addPlayerOutEvent);
videoEl.removeEventListener('pause', removePlayerOutEvent);
videoEl.removeEventListener('ended', removePlayerOutEvent);
});
window.removeEventListener('scroll', onPlayerOutEvent);
window.removeEventListener('scroll', onPlayerBackEvent);
},
};