Add the (un)subscribe button to group list items.
This commit is contained in:
parent
73f3977b62
commit
d967bd2bbd
|
@ -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";
|
||||||
|
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue