fixes
This commit is contained in:
parent
c5e137d4aa
commit
0fa9c8599f
@ -16,14 +16,18 @@ class ReelsMaster {
|
|||||||
container: null
|
container: null
|
||||||
};
|
};
|
||||||
private observer: MutationObserver | null = null;
|
private observer: MutationObserver | null = null;
|
||||||
private storedVolume: number | null = null;
|
private storedVolume: number = 0.5;
|
||||||
private storedMuted: boolean = false;
|
private storedMuted: boolean = false;
|
||||||
|
private videoVolumeListeners: WeakMap<HTMLVideoElement, () => void> = new WeakMap();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private init(): void {
|
private init(): void {
|
||||||
|
// Сразу начинаем следить за всеми видео для мгновенного применения громкости
|
||||||
|
this.setupGlobalVideoInterceptor();
|
||||||
|
|
||||||
if (document.readyState === 'loading') {
|
if (document.readyState === 'loading') {
|
||||||
document.addEventListener('DOMContentLoaded', () => this.start());
|
document.addEventListener('DOMContentLoaded', () => this.start());
|
||||||
} else {
|
} else {
|
||||||
@ -31,6 +35,78 @@ class ReelsMaster {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Перехватываем все видео сразу при их появлении и применяем сохраненную громкость
|
||||||
|
private setupGlobalVideoInterceptor(): void {
|
||||||
|
// Применяем к уже существующим видео
|
||||||
|
this.applyVolumeToAllVideos();
|
||||||
|
|
||||||
|
// Следим за новыми видео через MutationObserver
|
||||||
|
const videoObserver = new MutationObserver((mutations) => {
|
||||||
|
let hasNewVideo = false;
|
||||||
|
for (const mutation of mutations) {
|
||||||
|
for (const node of mutation.addedNodes) {
|
||||||
|
if (node instanceof HTMLVideoElement) {
|
||||||
|
hasNewVideo = true;
|
||||||
|
this.applyVolumeToVideo(node);
|
||||||
|
} else if (node instanceof HTMLElement) {
|
||||||
|
const videos = node.querySelectorAll('video');
|
||||||
|
if (videos.length > 0) {
|
||||||
|
hasNewVideo = true;
|
||||||
|
videos.forEach(video => this.applyVolumeToVideo(video));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
videoObserver.observe(document.documentElement, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyVolumeToAllVideos(): void {
|
||||||
|
document.querySelectorAll('video').forEach(video => {
|
||||||
|
this.applyVolumeToVideo(video);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyVolumeToVideo(video: HTMLVideoElement): void {
|
||||||
|
if (!window.location.pathname.includes('/reels/')) return;
|
||||||
|
|
||||||
|
// Применяем сохраненную громкость
|
||||||
|
video.volume = this.storedVolume;
|
||||||
|
video.muted = this.storedMuted;
|
||||||
|
|
||||||
|
// Добавляем слушатель на случай если Instagram перезапишет громкость
|
||||||
|
if (!this.videoVolumeListeners.has(video)) {
|
||||||
|
const listener = () => {
|
||||||
|
// Если громкость изменилась не нами, восстанавливаем
|
||||||
|
if (Math.abs(video.volume - this.storedVolume) > 0.01 || video.muted !== this.storedMuted) {
|
||||||
|
video.volume = this.storedVolume;
|
||||||
|
video.muted = this.storedMuted;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Слушаем первые несколько изменений громкости для борьбы с Instagram
|
||||||
|
let volumeChangeCount = 0;
|
||||||
|
const tempListener = () => {
|
||||||
|
volumeChangeCount++;
|
||||||
|
if (volumeChangeCount <= 5) {
|
||||||
|
video.volume = this.storedVolume;
|
||||||
|
video.muted = this.storedMuted;
|
||||||
|
} else {
|
||||||
|
video.removeEventListener('volumechange', tempListener);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
video.addEventListener('volumechange', tempListener);
|
||||||
|
video.addEventListener('loadedmetadata', listener);
|
||||||
|
video.addEventListener('play', listener);
|
||||||
|
this.videoVolumeListeners.set(video, listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private start(): void {
|
private start(): void {
|
||||||
console.log('Reels Master: Starting...');
|
console.log('Reels Master: Starting...');
|
||||||
this.checkForReels();
|
this.checkForReels();
|
||||||
@ -48,7 +124,9 @@ class ReelsMaster {
|
|||||||
if (currentUrl !== lastUrl) {
|
if (currentUrl !== lastUrl) {
|
||||||
lastUrl = currentUrl;
|
lastUrl = currentUrl;
|
||||||
console.log('Reels Master: URL changed to', currentUrl);
|
console.log('Reels Master: URL changed to', currentUrl);
|
||||||
setTimeout(() => this.checkForReels(), 500);
|
// Сразу применяем громкость ко всем видео
|
||||||
|
this.applyVolumeToAllVideos();
|
||||||
|
setTimeout(() => this.checkForReels(), 300);
|
||||||
}
|
}
|
||||||
}).observe(document.querySelector('body')!, {
|
}).observe(document.querySelector('body')!, {
|
||||||
subtree: true,
|
subtree: true,
|
||||||
@ -80,6 +158,10 @@ class ReelsMaster {
|
|||||||
|
|
||||||
console.log('Reels Master: Found new video element');
|
console.log('Reels Master: Found new video element');
|
||||||
this.currentVideo = video;
|
this.currentVideo = video;
|
||||||
|
|
||||||
|
// Убедимся что громкость применена к текущему видео
|
||||||
|
this.applyVolumeToVideo(video);
|
||||||
|
|
||||||
this.injectControls();
|
this.injectControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,14 +192,23 @@ class ReelsMaster {
|
|||||||
private injectControls(): void {
|
private injectControls(): void {
|
||||||
if (!this.currentVideo) return;
|
if (!this.currentVideo) return;
|
||||||
|
|
||||||
const actionButtons = this.findActionButtonsContainer();
|
// Ищем контейнер кнопок рядом с ТЕКУЩИМ видео, а не глобально
|
||||||
|
const actionButtons = this.findActionButtonsContainer(this.currentVideo);
|
||||||
if (!actionButtons) {
|
if (!actionButtons) {
|
||||||
console.log('Reels Master: Action buttons container not found');
|
console.log('Reels Master: Action buttons container not found');
|
||||||
setTimeout(() => this.injectControls(), 1000);
|
setTimeout(() => this.injectControls(), 500);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.controls.container) {
|
// Проверяем, есть ли уже наши контролы в этом контейнере
|
||||||
|
const existingControls = actionButtons.querySelector('.reels-master-controls');
|
||||||
|
if (existingControls) {
|
||||||
|
console.log('Reels Master: Controls already exist in this container');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Удаляем старые контролы из предыдущего контейнера
|
||||||
|
if (this.controls.container && this.controls.container.parentElement !== actionButtons) {
|
||||||
this.controls.container.remove();
|
this.controls.container.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,21 +219,40 @@ class ReelsMaster {
|
|||||||
this.controls.container.appendChild(this.controls.downloadButton);
|
this.controls.container.appendChild(this.controls.downloadButton);
|
||||||
actionButtons.insertBefore(this.controls.container, actionButtons.firstChild);
|
actionButtons.insertBefore(this.controls.container, actionButtons.firstChild);
|
||||||
|
|
||||||
if (this.storedVolume !== null && this.currentVideo) {
|
// Синхронизируем слайдер с текущей громкостью
|
||||||
this.currentVideo.volume = this.storedVolume;
|
if (this.controls.volumeSlider) {
|
||||||
}
|
this.controls.volumeSlider.value = String(this.storedVolume * 100);
|
||||||
if (this.currentVideo) {
|
|
||||||
this.currentVideo.muted = this.storedMuted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Reels Master: Controls injected');
|
console.log('Reels Master: Controls injected');
|
||||||
}
|
}
|
||||||
|
|
||||||
private findActionButtonsContainer(): HTMLElement | null {
|
// Ищем контейнер кнопок относительно конкретного видео
|
||||||
const likeButton = document.querySelector('svg[aria-label="Like"]');
|
private findActionButtonsContainer(video: HTMLVideoElement): HTMLElement | null {
|
||||||
|
// Ищем родительский контейнер рила для данного видео
|
||||||
|
let reelContainer = video.closest('article') || video.closest('[role="presentation"]');
|
||||||
|
|
||||||
|
if (!reelContainer) {
|
||||||
|
// Пробуем найти родителя вверх по дереву
|
||||||
|
let parent = video.parentElement;
|
||||||
|
for (let i = 0; i < 10 && parent; i++) {
|
||||||
|
if (parent.querySelector('svg[aria-label="Like"]')) {
|
||||||
|
reelContainer = parent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parent = parent.parentElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reelContainer) {
|
||||||
|
reelContainer = document.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ищем кнопку лайка внутри контейнера текущего рила
|
||||||
|
const likeButton = reelContainer.querySelector('svg[aria-label="Like"]');
|
||||||
if (likeButton) {
|
if (likeButton) {
|
||||||
let parent = likeButton.parentElement;
|
let parent = likeButton.parentElement;
|
||||||
while (parent) {
|
while (parent && parent !== reelContainer) {
|
||||||
const childDivs = parent.querySelectorAll(':scope > div');
|
const childDivs = parent.querySelectorAll(':scope > div');
|
||||||
if (childDivs.length >= 3) {
|
if (childDivs.length >= 3) {
|
||||||
const hasLike = parent.querySelector('svg[aria-label="Like"]');
|
const hasLike = parent.querySelector('svg[aria-label="Like"]');
|
||||||
@ -186,11 +296,13 @@ class ReelsMaster {
|
|||||||
|
|
||||||
volumeButton.onclick = () => {
|
volumeButton.onclick = () => {
|
||||||
if (this.currentVideo) {
|
if (this.currentVideo) {
|
||||||
this.currentVideo.muted = !this.currentVideo.muted;
|
this.storedMuted = !this.storedMuted;
|
||||||
this.storedMuted = this.currentVideo.muted;
|
|
||||||
|
// Применяем ко всем видео
|
||||||
|
this.applyVolumeToAllVideos();
|
||||||
|
|
||||||
if (this.controls.volumeSlider) {
|
if (this.controls.volumeSlider) {
|
||||||
this.controls.volumeSlider.value = this.currentVideo.muted ? '0' : String(this.currentVideo.volume * 100);
|
this.controls.volumeSlider.value = this.storedMuted ? '0' : String(this.storedVolume * 100);
|
||||||
}
|
}
|
||||||
this.updateVolumeIcon(volumeButton);
|
this.updateVolumeIcon(volumeButton);
|
||||||
}
|
}
|
||||||
@ -208,26 +320,23 @@ class ReelsMaster {
|
|||||||
slider.min = '0';
|
slider.min = '0';
|
||||||
slider.max = '100';
|
slider.max = '100';
|
||||||
|
|
||||||
let initialValue = '50';
|
// Используем сохраненную громкость
|
||||||
if (this.currentVideo) {
|
slider.value = String(this.storedVolume * 100);
|
||||||
if (this.currentVideo.muted) {
|
|
||||||
initialValue = '0';
|
|
||||||
} else {
|
|
||||||
initialValue = String(this.currentVideo.volume * 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
slider.value = initialValue;
|
|
||||||
|
|
||||||
slider.className = 'reels-master-volume-slider';
|
slider.className = 'reels-master-volume-slider';
|
||||||
|
|
||||||
slider.oninput = (e) => {
|
slider.oninput = (e) => {
|
||||||
if (this.currentVideo) {
|
if (this.currentVideo) {
|
||||||
const value = parseInt((e.target as HTMLInputElement).value);
|
const value = parseInt((e.target as HTMLInputElement).value);
|
||||||
this.currentVideo.volume = value / 100;
|
const newVolume = value / 100;
|
||||||
this.currentVideo.muted = value === 0;
|
const newMuted = value === 0;
|
||||||
|
|
||||||
this.storedVolume = this.currentVideo.volume;
|
// Сохраняем настройки
|
||||||
this.storedMuted = this.currentVideo.muted;
|
this.storedVolume = newVolume;
|
||||||
|
this.storedMuted = newMuted;
|
||||||
|
|
||||||
|
// Применяем ко всем видео сразу
|
||||||
|
this.applyVolumeToAllVideos();
|
||||||
|
|
||||||
const volumeControl = slider.closest('.reels-master-volume');
|
const volumeControl = slider.closest('.reels-master-volume');
|
||||||
const volumeButton = volumeControl?.querySelector('.reels-master-volume-button') as HTMLButtonElement;
|
const volumeButton = volumeControl?.querySelector('.reels-master-volume-button') as HTMLButtonElement;
|
||||||
@ -241,9 +350,7 @@ class ReelsMaster {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private updateVolumeIcon(button: HTMLButtonElement): void {
|
private updateVolumeIcon(button: HTMLButtonElement): void {
|
||||||
if (!this.currentVideo) return;
|
const volume = this.storedMuted ? 0 : this.storedVolume;
|
||||||
|
|
||||||
const volume = this.currentVideo.muted ? 0 : this.currentVideo.volume;
|
|
||||||
|
|
||||||
let icon = '';
|
let icon = '';
|
||||||
if (volume === 0) {
|
if (volume === 0) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user