@@ -0,0 +1,12 @@
|
||||
interface MenuState {
|
||||
isOpen: boolean;
|
||||
handleToggleMenu(): void;
|
||||
}
|
||||
|
||||
export const menu = (): MenuState => ({
|
||||
isOpen: false,
|
||||
|
||||
handleToggleMenu() {
|
||||
this.isOpen = !this.isOpen;
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,29 @@
|
||||
interface ThemeModeState {
|
||||
init(): void;
|
||||
storedTheme: string;
|
||||
handleToggleThemeMode(): void;
|
||||
}
|
||||
|
||||
export const themeMode = ():ThemeModeState => ({
|
||||
storedTheme: '',
|
||||
|
||||
init() {
|
||||
const storedTheme = localStorage.getItem("theme-mode") || (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
|
||||
|
||||
if (!storedTheme) return;
|
||||
|
||||
document.documentElement.setAttribute("data-color-scheme", storedTheme);
|
||||
|
||||
this.storedTheme = storedTheme;
|
||||
},
|
||||
|
||||
handleToggleThemeMode() {
|
||||
const targetTheme = this.storedTheme === "dark" ? "light" : "dark";
|
||||
|
||||
document.documentElement.setAttribute("data-color-scheme", targetTheme);
|
||||
|
||||
this.storedTheme = targetTheme;
|
||||
|
||||
localStorage.setItem("theme-mode", targetTheme);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
interface upvoteState {
|
||||
init(): void;
|
||||
upvotedNames: string[];
|
||||
getIsUpvoted(id: string): boolean;
|
||||
handleUpvote(name: string): void;
|
||||
}
|
||||
|
||||
export const upvote = (key: string, group: string, plural: string): upvoteState => ({
|
||||
upvotedNames: [],
|
||||
|
||||
init() {
|
||||
this.upvotedNames = JSON.parse(localStorage.getItem(`walker.upvoted.${key}.names`) || "[]");
|
||||
},
|
||||
|
||||
getIsUpvoted(id: string) {
|
||||
return this.upvotedNames.includes(id);
|
||||
},
|
||||
|
||||
async handleUpvote(name) {
|
||||
if (this.getIsUpvoted(name)) return
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.open("POST", "/apis/api.halo.run/v1alpha1/trackers/upvote");
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
|
||||
xhr.onload = () => {
|
||||
this.upvotedNames = [...this.upvotedNames, name];
|
||||
localStorage.setItem(`walker.upvoted.${key}.names`, JSON.stringify(this.upvotedNames));
|
||||
|
||||
const upvoteNode = document.querySelector("[data-upvote-" + key + '-name="' + name + '"]');
|
||||
|
||||
if (!upvoteNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
const upvoteCount = parseInt(upvoteNode.textContent || "0");
|
||||
upvoteNode.textContent = upvoteCount + 1 + "";
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
alert("网络请求失败,请稍后再试");
|
||||
};
|
||||
xhr.send(
|
||||
JSON.stringify({
|
||||
group: group,
|
||||
plural: plural,
|
||||
name: name,
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
在新议题中引用
屏蔽一个用户