215 lines
5.6 KiB
JavaScript
215 lines
5.6 KiB
JavaScript
const nav = require("../../data/links.json");
|
|
|
|
function countLinks(cat) {
|
|
let n = 0;
|
|
const groups = cat.groups || [];
|
|
for (let i = 0; i < groups.length; i++) {
|
|
n += (groups[i].links || []).length;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
function withCounts(categories) {
|
|
return (categories || []).map((c) =>
|
|
Object.assign({}, c, { linkCount: countLinks(c) })
|
|
);
|
|
}
|
|
|
|
Page({
|
|
data: {
|
|
brand: nav.brand || "游民导航",
|
|
tagline: nav.tagline || "",
|
|
footer: nav.footer || "",
|
|
brandIcon: nav.brandIcon || "/icons/_brand.webp",
|
|
categories: withCounts(nav.categories),
|
|
activeId: (nav.categories && nav.categories[0] && nav.categories[0].id) || "",
|
|
activeTitle:
|
|
(nav.categories && nav.categories[0] && nav.categories[0].title) || "",
|
|
theme: "light",
|
|
drawerOpen: false,
|
|
showTop: false,
|
|
toast: "",
|
|
statusBarHeight: 20,
|
|
navBarHeight: 44,
|
|
sheetOpen: false,
|
|
sheetLink: null,
|
|
},
|
|
|
|
_jumping: false,
|
|
_sectionTops: [],
|
|
_toastTimer: null,
|
|
|
|
onLoad() {
|
|
const sys = wx.getWindowInfo ? wx.getWindowInfo() : wx.getSystemInfoSync();
|
|
const statusBarHeight = sys.statusBarHeight || 20;
|
|
const menu = wx.getMenuButtonBoundingClientRect
|
|
? wx.getMenuButtonBoundingClientRect()
|
|
: null;
|
|
let navBarHeight = 44;
|
|
if (menu && menu.height) {
|
|
navBarHeight = (menu.top - statusBarHeight) * 2 + menu.height;
|
|
}
|
|
|
|
const app = getApp();
|
|
const theme = (app && app.globalData && app.globalData.theme) || "light";
|
|
|
|
this.setData({
|
|
statusBarHeight,
|
|
navBarHeight,
|
|
theme,
|
|
});
|
|
this._applyTheme(theme);
|
|
},
|
|
|
|
onReady() {
|
|
wx.nextTick(() => this._measureSections());
|
|
},
|
|
|
|
onShow() {
|
|
this._applyTheme(this.data.theme);
|
|
},
|
|
|
|
onPageScroll(e) {
|
|
const scrollTop = e.scrollTop || 0;
|
|
const showTop = scrollTop > 480;
|
|
if (showTop !== this.data.showTop) {
|
|
this.setData({ showTop });
|
|
}
|
|
if (this._jumping || !this._sectionTops.length) return;
|
|
|
|
const marker = scrollTop + this.data.statusBarHeight + this.data.navBarHeight + 24;
|
|
let current = this._sectionTops[0].id;
|
|
for (let i = 0; i < this._sectionTops.length; i++) {
|
|
if (this._sectionTops[i].top <= marker) current = this._sectionTops[i].id;
|
|
else break;
|
|
}
|
|
if (current !== this.data.activeId) {
|
|
const cat = this.data.categories.find((c) => c.id === current);
|
|
this.setData({
|
|
activeId: current,
|
|
activeTitle: (cat && cat.title) || "",
|
|
});
|
|
}
|
|
},
|
|
|
|
_measureSections() {
|
|
const query = wx.createSelectorQuery();
|
|
query.selectAll(".cat-panel").boundingClientRect();
|
|
query.selectViewport().scrollOffset();
|
|
query.exec((res) => {
|
|
const rects = (res && res[0]) || [];
|
|
const scroll = (res && res[1]) || { scrollTop: 0 };
|
|
this._sectionTops = rects.map((r) => ({
|
|
id: (r.id || "").replace(/^cat-/, ""),
|
|
top: (r.top || 0) + (scroll.scrollTop || 0),
|
|
}));
|
|
});
|
|
},
|
|
|
|
_applyTheme(theme) {
|
|
const dark = theme === "dark";
|
|
wx.setNavigationBarColor({
|
|
frontColor: dark ? "#ffffff" : "#000000",
|
|
backgroundColor: dark ? "#0a0f14" : "#e9eef4",
|
|
animation: { duration: 200, timingFunc: "easeIn" },
|
|
});
|
|
wx.setBackgroundColor({
|
|
backgroundColor: dark ? "#0a0f14" : "#e9eef4",
|
|
backgroundColorTop: dark ? "#0a0f14" : "#e9eef4",
|
|
backgroundColorBottom: dark ? "#0a0f14" : "#e9eef4",
|
|
});
|
|
},
|
|
|
|
openDrawer() {
|
|
this.setData({ drawerOpen: true });
|
|
},
|
|
|
|
closeDrawer() {
|
|
this.setData({ drawerOpen: false });
|
|
},
|
|
|
|
noop() {},
|
|
|
|
toggleTheme() {
|
|
const theme = this.data.theme === "dark" ? "light" : "dark";
|
|
this.setData({ theme });
|
|
try {
|
|
wx.setStorageSync("navmini-theme", theme);
|
|
} catch (e) {
|
|
/* ignore */
|
|
}
|
|
const app = getApp();
|
|
if (app && app.globalData) app.globalData.theme = theme;
|
|
this._applyTheme(theme);
|
|
},
|
|
|
|
onSelectCategory(e) {
|
|
const id = e.currentTarget.dataset.id;
|
|
if (!id) return;
|
|
const cat = this.data.categories.find((c) => c.id === id);
|
|
this.setData({
|
|
drawerOpen: false,
|
|
activeId: id,
|
|
activeTitle: (cat && cat.title) || "",
|
|
});
|
|
this._jumping = true;
|
|
wx.pageScrollTo({
|
|
selector: `#cat-${id}`,
|
|
duration: 320,
|
|
offsetTop: -(this.data.statusBarHeight + this.data.navBarHeight + 8),
|
|
complete: () => {
|
|
setTimeout(() => {
|
|
this._jumping = false;
|
|
this._measureSections();
|
|
}, 360);
|
|
},
|
|
});
|
|
},
|
|
|
|
onTapLink(e) {
|
|
const { id, catid, groupid } = e.currentTarget.dataset;
|
|
let link = null;
|
|
const cat = this.data.categories.find((c) => c.id === catid);
|
|
if (cat) {
|
|
const group = (cat.groups || []).find((g) => g.id === groupid);
|
|
if (group) link = (group.links || []).find((l) => l.id === id);
|
|
}
|
|
if (!link || !link.href) {
|
|
this._showToast("无效链接");
|
|
return;
|
|
}
|
|
this.setData({ sheetOpen: true, sheetLink: link });
|
|
},
|
|
|
|
closeSheet() {
|
|
this.setData({ sheetOpen: false, sheetLink: null });
|
|
},
|
|
|
|
copySheetUrl() {
|
|
const link = this.data.sheetLink;
|
|
if (!link || !link.href) return;
|
|
wx.setClipboardData({
|
|
data: link.href,
|
|
success: () => {
|
|
this._showToast("已复制,请到浏览器打开");
|
|
},
|
|
fail: () => {
|
|
this._showToast("复制失败");
|
|
},
|
|
});
|
|
},
|
|
|
|
backTop() {
|
|
wx.pageScrollTo({ scrollTop: 0, duration: 300 });
|
|
},
|
|
|
|
_showToast(msg) {
|
|
if (this._toastTimer) clearTimeout(this._toastTimer);
|
|
this.setData({ toast: msg });
|
|
this._toastTimer = setTimeout(() => {
|
|
this.setData({ toast: "" });
|
|
this._toastTimer = null;
|
|
}, 1800);
|
|
},
|
|
});
|