1
Fork 0
tildes-reextended/source/content-scripts/features/miscellaneous/unignore-all-button.tsx

115 lines
2.9 KiB
TypeScript
Raw Permalink Normal View History

import {Component, render} from "preact";
import {log, querySelectorAll, sleep} from "../../../utilities/exports.js";
export function runUnignoreAllButtonFeature(): void {
if (addUnignoreAllButton()) {
log("Added Unignore All button.");
}
}
function addUnignoreAllButton(): boolean {
// Only add the button when we're on the ignore list page and the ignore list
// isn't empty.
if (
window.location.pathname !== "/ignored_topics" ||
document.querySelector("main > .empty") !== null
) {
return false;
}
const heading = document.querySelector(".heading-main") ?? undefined;
if (heading === undefined) {
return false;
}
const button = document.createDocumentFragment();
render(<UnignoreAllButton />, button);
heading.after(button);
return true;
}
type Props = Record<string, unknown>;
type State = {
isRunning: boolean;
remaining: number;
total: number;
wasCanceled: boolean;
};
class UnignoreAllButton extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
isRunning: false,
remaining: 0,
total: 0,
wasCanceled: false,
};
}
click = () => {
if (this.state.isRunning) {
// If we're already running, cancel the run.
this.setState({isRunning: false, wasCanceled: true});
window.setTimeout(() => {
// And after 5 seconds, return back to the default state.
this.setState({wasCanceled: false});
}, 5000);
return;
}
// Select the ignore buttons that have a HTTP DELETE method set. Since we're
// going to have Intercooler do all the work for us, we don't want to
// accidentally also select ignore buttons that would ignore the topics
// again.
const unignoreButtons = querySelectorAll<HTMLButtonElement>(
'button[name="topic-actions-ignore"][data-ic-delete-from]',
);
this.setState({
isRunning: true,
remaining: unignoreButtons.length,
total: unignoreButtons.length,
});
void this.unignoreAll(unignoreButtons);
};
unignoreAll = async (buttons: HTMLButtonElement[]) => {
let remaining = buttons.length;
for (const ignoreButton of buttons) {
// Stop the loop if the user canceled it.
if (!this.state.isRunning && this.state.wasCanceled) {
return;
}
ignoreButton.click();
remaining--;
this.setState({remaining});
await sleep(250);
}
this.setState({isRunning: false});
};
render() {
const {isRunning, remaining, total, wasCanceled} = this.state;
let text = "Unignore All";
if (isRunning) {
// When we're running show how many topics are remaining.
text = `Unignoring topics, ${remaining} out of ${total} remaining`;
} else if (wasCanceled) {
// If the user canceled, say that.
text = "Canceled unignoring all topics";
}
return (
<button class="btn" onClick={this.click}>
{text}
</button>
);
}
}