1
Fork 0

Add the (un)subscribe button to group list items.

This commit is contained in:
Bauke 2023-07-14 20:10:08 +02:00
parent 73f3977b62
commit d967bd2bbd
Signed by: Bauke
GPG Key ID: C1C0F29952BCF558
7 changed files with 156 additions and 1 deletions

View File

@ -2,6 +2,7 @@ export * from "./anonymize-usernames.js";
export * from "./autocomplete.js"; export * from "./autocomplete.js";
export * from "./back-to-top.js"; export * from "./back-to-top.js";
export * from "./comment-anchor-fix.js"; export * from "./comment-anchor-fix.js";
export * from "./group-list-subscribe-button.js";
export * from "./hide-topics.js"; export * from "./hide-topics.js";
export * from "./hide-votes.js"; export * from "./hide-votes.js";
export * from "./jump-to-new-comment.js"; export * from "./jump-to-new-comment.js";

View File

@ -0,0 +1,127 @@
import {Component, render} from "preact";
import {log, pluralize, querySelectorAll} from "../../utilities/exports.js";
export function runGroupListSubscribeButtonFeature(): void {
const count = addSubscribeButtonsToGroupList();
if (count > 0) {
const pluralized = `${count} ${pluralize(count, "subscribe button")}`;
log(`Added ${pluralized} to the group list`);
}
}
function addSubscribeButtonsToGroupList(): number {
if (window.location.pathname !== "/groups") {
return 0;
}
const csrfToken = document.querySelector<HTMLMetaElement>(
'meta[name="csrftoken"]',
)?.content;
if (csrfToken === undefined) {
log("No CSRF token found", true);
return 0;
}
let count = 0;
for (const listItem of querySelectorAll<HTMLLIElement>(
".group-list li:not(.trx-group-list-subscribe-button)",
)) {
const group = listItem.querySelector(".link-group")?.textContent?.slice(1);
if (group === undefined) {
log(`Missing expected group in list item`, true);
log(listItem, true);
continue;
}
const button = document.createDocumentFragment();
render(
<SubscribeButton
csrfToken={csrfToken}
group={group}
listItem={listItem}
/>,
button,
);
const activity =
listItem.querySelector(".group-list-activity") ?? undefined;
if (activity === undefined) {
listItem.append(button);
} else {
activity.before(button);
}
listItem.classList.add("trx-group-list-subscribe-button");
count++;
}
return count;
}
type Props = {
csrfToken: string;
listItem: HTMLLIElement;
group: string;
};
type State = {
isSubscribed: boolean;
};
class SubscribeButton extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
isSubscribed: props.listItem.classList.contains(
"group-list-item-subscribed",
),
};
}
clickHandler = async () => {
const {csrfToken, group} = this.props;
const {isSubscribed} = this.state;
const response = await window.fetch(
`https://tildes.net/api/web/group/${group}/subscribe`,
{
headers: {
"X-CSRF-Token": csrfToken,
"X-IC-Request": "true",
},
method: isSubscribed ? "DELETE" : "PUT",
referrer: "https://tildes.net",
},
);
if (response.status !== 200) {
log(`Unexpected status code: ${response.status}`, true);
return;
}
this.setState({isSubscribed: !isSubscribed});
};
render() {
const {listItem} = this.props;
const {isSubscribed} = this.state;
if (isSubscribed) {
listItem.classList.add("group-list-item-subscribed");
listItem.classList.remove("group-list-item-not-subscribed");
} else {
listItem.classList.add("group-list-item-not-subscribed");
listItem.classList.remove("group-list-item-subscribed");
}
return (
<button
class={`btn btn-sm ${isSubscribed ? "btn-used" : ""}`}
onClick={this.clickHandler}
>
{isSubscribed ? "Unsubscribe" : "Subscribe"}
</button>
);
}
}

View File

@ -13,6 +13,7 @@ import {
UserLabelsFeature, UserLabelsFeature,
runAnonymizeUsernamesFeature, runAnonymizeUsernamesFeature,
runCommentAnchorFixFeature, runCommentAnchorFixFeature,
runGroupListSubscribeButtonFeature,
runHideTopicsFeature, runHideTopicsFeature,
runHideVotesFeature, runHideVotesFeature,
runMarkdownToolbarFeature, runMarkdownToolbarFeature,
@ -25,6 +26,7 @@ async function initialize() {
const start = window.performance.now(); const start = window.performance.now();
initializeGlobals(); initializeGlobals();
const enabledFeatures = await fromStorage(Data.EnabledFeatures); const enabledFeatures = await fromStorage(Data.EnabledFeatures);
const miscEnabled = await fromStorage(Data.MiscellaneousEnabledFeatures);
window.TildesReExtended.debug = enabledFeatures.value.has(Feature.Debug); window.TildesReExtended.debug = enabledFeatures.value.has(Feature.Debug);
// Any features that will use the knownGroups data should be added to this // Any features that will use the knownGroups data should be added to this
@ -146,11 +148,14 @@ async function initialize() {
); );
} }
const miscEnabled = await fromStorage(Data.MiscellaneousEnabledFeatures);
if (miscEnabled.value.has(MiscellaneousFeature.CommentAnchorFix)) { if (miscEnabled.value.has(MiscellaneousFeature.CommentAnchorFix)) {
runCommentAnchorFixFeature(); runCommentAnchorFixFeature();
} }
if (miscEnabled.value.has(MiscellaneousFeature.GroupListSubscribeButtons)) {
runGroupListSubscribeButtonFeature();
}
if (miscEnabled.value.has(MiscellaneousFeature.TopicInfoIgnore)) { if (miscEnabled.value.has(MiscellaneousFeature.TopicInfoIgnore)) {
runTopicInfoIgnore(); runTopicInfoIgnore();
} }

View File

@ -25,6 +25,14 @@ function FeatureDescription({
); );
} }
if (feature === MiscellaneousFeature.GroupListSubscribeButtons) {
return (
<p class="description">
Add Subscribe and Unsubscribe buttons to the group list.
</p>
);
}
if (feature === MiscellaneousFeature.TopicInfoIgnore) { if (feature === MiscellaneousFeature.TopicInfoIgnore) {
return ( return (
<p class="description"> <p class="description">

View File

@ -1,6 +1,7 @@
// Scripts // Scripts
@import "scripts/autocomplete"; @import "scripts/autocomplete";
@import "scripts/back-to-top"; @import "scripts/back-to-top";
@import "scripts/group-list-subscribe-button";
@import "scripts/hide-topics"; @import "scripts/hide-topics";
@import "scripts/jump-to-new-comment"; @import "scripts/jump-to-new-comment";
@import "scripts/markdown-toolbar"; @import "scripts/markdown-toolbar";

View File

@ -0,0 +1,12 @@
.group-list {
.trx-group-list-subscribe-button {
// Remove the text-indent set by Tildes so it the button is left-aligned
// properly.
text-indent: unset;
button {
// Add some space between the button and the activity text.
margin-right: 0.5rem;
}
}
}

View File

@ -21,6 +21,7 @@ export enum Feature {
*/ */
export enum MiscellaneousFeature { export enum MiscellaneousFeature {
CommentAnchorFix = "comment-anchor-fix", CommentAnchorFix = "comment-anchor-fix",
GroupListSubscribeButtons = "group-list-subscribe-buttons",
TopicInfoIgnore = "topic-info-ignore", TopicInfoIgnore = "topic-info-ignore",
} }