import React from 'dom-chef'; import {CachedValue} from 'webext-storage-cache'; import {$, $$} from 'select-dom'; import elementReady from 'element-ready'; import pluralize from './pluralize.js'; import featureLink from './feature-link.js'; import {importedFeatures} from '../../readme.md'; export const state = new CachedValue('bisect', {maxAge: {minutes: 15}}); // Split current list of features in half and create an options-like object to be applied on load // Bisecting 4 features: enable 2 // Bisecting 3 features: enable 1 // Bisecting 2 features: enable 1 // Bisecting 1 feature: enable 0 // This is the last step, if the user says Yes, it's not caused by a JS feature const getMiddleStep = (list: any[]): number => Math.floor(list.length / 2); async function onChoiceButtonClick({currentTarget: button}: React.MouseEvent): Promise { const answer = button.value; const bisectedFeatures = (await state.get())!; if (bisectedFeatures.length > 1) { await state.set(answer === 'yes' ? bisectedFeatures.slice(0, getMiddleStep(bisectedFeatures)) : bisectedFeatures.slice(getMiddleStep(bisectedFeatures)), ); button.parentElement!.replaceWith(
Reloading…
); location.reload(); return; } // Last step, no JS feature was enabled if (answer === 'yes') { createMessageBox( <>

Unable to identify feature. It might be a CSS-only feature, a meta-feature, or unrelated to Refined GitHub.

Try disabling Refined GitHub to see if the change or issue is caused by the extension.

); } else { const feature = ( {bisectedFeatures[0]} ); createMessageBox(<>The change or issue is caused by {feature}.); } await state.delete(); window.removeEventListener('visibilitychange', hideMessage); } async function onEndButtonClick(): Promise { await state.delete(); location.reload(); } function createMessageBox(message: Element | string, extraButtons?: Element): void { $('#rgh-bisect-dialog')?.remove(); document.body.append(

{message}

{extraButtons}
, ); } async function hideMessage(): Promise { if (!await state.get()) { createMessageBox('Process completed in another tab'); } } export default async function bisectFeatures(): Promise | void> { // `bisect` stores the list of features to be split in half const bisectedFeatures = await state.get(); if (!bisectedFeatures) { return; } console.log(`Bisecting ${bisectedFeatures.length} features:\n${bisectedFeatures.join('\n')}`); const steps = Math.ceil(Math.log2(Math.max(bisectedFeatures.length))) + 1; await elementReady('body'); createMessageBox( `Do you see the change or issue? (${pluralize(steps, 'last step', '$$ steps remaining')})`,
, ); // Enable "Yes"/"No" buttons once the page is done loading window.addEventListener('load', () => { for (const button of $$('#rgh-bisect-dialog [aria-disabled]')) { button.removeAttribute('aria-disabled'); } }); // Hide message when the process is done elsewhere window.addEventListener('visibilitychange', hideMessage); const half = getMiddleStep(bisectedFeatures); const temporaryOptions: Record = {}; for (const feature of importedFeatures) { const index = bisectedFeatures.indexOf(feature); temporaryOptions[`feature:${feature}`] = index > -1 && index < half; } console.log(temporaryOptions); return temporaryOptions; }