mirror of
https://github.com/JoeanAmier/XHS-Downloader.git
synced 2026-03-22 15:07:17 +08:00
优化项目代码
This commit is contained in:
@@ -245,3 +245,8 @@ async with XHS(work_path=work_path,
|
||||
<li>基于本项目进行的任何二次开发、修改或编译的程序与原创作者无关,原创作者不承担与二次开发行为或其结果相关的任何责任,使用者应自行对因二次开发可能带来的各种情况负全部责任。</li>
|
||||
</ul>
|
||||
<b>在使用本项目的代码和功能之前,请您认真考虑并接受以上免责声明。如果您对上述声明有任何疑问或不同意,请不要使用本项目的代码和功能。如果您使用了本项目的代码和功能,则视为您已完全理解并接受上述免责声明,并自愿承担使用本项目的一切风险和后果。</b>
|
||||
|
||||
# 💡 代码参考
|
||||
|
||||
* https://textual.textualize.io/
|
||||
* https://docs.aiohttp.org/en/stable/
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
aiohttp>=3.9.0
|
||||
textual>=0.40.0
|
||||
aiohttp>=3.9.1
|
||||
textual>=0.47.1
|
||||
pyperclip>=1.8.2
|
||||
lxml>=4.9.3
|
||||
lxml>=5.1.0
|
||||
PyYAML>=6.0.1
|
||||
aiosqlite>=0.19.0
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from typing import Type
|
||||
|
||||
from textual.app import App
|
||||
from textual.widgets import RichLog
|
||||
|
||||
from source.application import XHS
|
||||
from source.module import (
|
||||
@@ -13,13 +14,16 @@ from source.translator import (
|
||||
English,
|
||||
)
|
||||
from .index import Index
|
||||
from .loading import Loading
|
||||
from .setting import Setting
|
||||
from .update import Update
|
||||
|
||||
__all__ = ["XHSDownloader"]
|
||||
|
||||
|
||||
class XHSDownloader(App):
|
||||
settings = Settings(ROOT)
|
||||
CSS_PATH = ROOT.joinpath("static/XHS-Downloader.tcss")
|
||||
SETTINGS = Settings(ROOT)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@@ -36,7 +40,7 @@ class XHSDownloader(App):
|
||||
await self.APP.__aexit__(exc_type, exc_value, traceback)
|
||||
|
||||
def __initialization(self) -> None:
|
||||
self.parameter = self.settings.run()
|
||||
self.parameter = self.SETTINGS.run()
|
||||
self.prompt = LANGUAGE.get(self.parameter["language"], Chinese)
|
||||
self.APP = XHS(**self.parameter, language_object=self.prompt)
|
||||
|
||||
@@ -47,11 +51,12 @@ class XHSDownloader(App):
|
||||
self.prompt),
|
||||
name="setting")
|
||||
self.install_screen(Index(self.APP, self.prompt), name="index")
|
||||
self.install_screen(Loading(self.prompt), name="loading")
|
||||
await self.push_screen("index")
|
||||
|
||||
async def action_settings(self):
|
||||
async def save_settings(data: dict) -> None:
|
||||
self.settings.update(data)
|
||||
self.SETTINGS.update(data)
|
||||
await self.refresh_screen()
|
||||
|
||||
await self.push_screen("setting", save_settings)
|
||||
@@ -62,12 +67,20 @@ class XHSDownloader(App):
|
||||
async def refresh_screen(self):
|
||||
self.pop_screen()
|
||||
self.__initialization()
|
||||
self.uninstall_screen("index")
|
||||
self.uninstall_screen("setting")
|
||||
self.uninstall_screen("loading")
|
||||
self.install_screen(Index(self.APP, self.prompt), name="index")
|
||||
self.install_screen(
|
||||
Setting(
|
||||
self.parameter,
|
||||
self.prompt),
|
||||
name="setting")
|
||||
self.uninstall_screen("index")
|
||||
self.install_screen(Index(self.APP, self.prompt), name="index")
|
||||
self.install_screen(Loading(self.prompt), name="loading")
|
||||
await self.push_screen("index")
|
||||
|
||||
def update_result(self, tip: str) -> None:
|
||||
self.query_one(RichLog).write(tip)
|
||||
|
||||
async def action_check_update(self):
|
||||
await self.push_screen(Update(self.APP, self.prompt), callback=self.update_result)
|
||||
|
||||
@@ -6,7 +6,6 @@ from rich.text import Text
|
||||
from textual import on
|
||||
from textual.app import ComposeResult
|
||||
from textual.binding import Binding
|
||||
from textual.containers import Center
|
||||
from textual.containers import HorizontalScroll
|
||||
from textual.containers import ScrollableContainer
|
||||
from textual.screen import Screen
|
||||
@@ -15,11 +14,9 @@ from textual.widgets import Footer
|
||||
from textual.widgets import Header
|
||||
from textual.widgets import Input
|
||||
from textual.widgets import Label
|
||||
from textual.widgets import ProgressBar
|
||||
from textual.widgets import RichLog
|
||||
|
||||
from source.application import XHS
|
||||
from source.module import ROOT
|
||||
from source.module import (
|
||||
VERSION_MAJOR,
|
||||
VERSION_MINOR,
|
||||
@@ -28,32 +25,20 @@ from source.module import (
|
||||
MASTER,
|
||||
ERROR,
|
||||
WARNING,
|
||||
INFO,
|
||||
LICENCE,
|
||||
REPOSITORY,
|
||||
RELEASES,
|
||||
GENERAL,
|
||||
USERSCRIPT,
|
||||
)
|
||||
from source.translator import (English, Chinese)
|
||||
from source.translator import (
|
||||
English,
|
||||
Chinese,
|
||||
)
|
||||
|
||||
__all__ = ["Index"]
|
||||
|
||||
|
||||
def show_state(function):
|
||||
async def inner(self, *args, **kwargs):
|
||||
self.close_disclaimer()
|
||||
self.bar.update(total=100, progress=100)
|
||||
result = await function(self, *args, **kwargs)
|
||||
self.bar.update(total=None)
|
||||
self.tip.write(Text(">" * 50, style=GENERAL))
|
||||
return result
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
class Index(Screen):
|
||||
CSS_PATH = ROOT.joinpath("static/XHS-Downloader.tcss")
|
||||
BINDINGS = [
|
||||
Binding(key="q", action="quit", description="退出程序/Quit"),
|
||||
Binding(key="u", action="check_update", description="检查更新/Update"),
|
||||
@@ -63,12 +48,10 @@ class Index(Screen):
|
||||
|
||||
def __init__(self, app: XHS, language: Chinese | English):
|
||||
super().__init__()
|
||||
self.app_ = app
|
||||
self.xhs = app
|
||||
self.prompt = language
|
||||
self.url = None
|
||||
self.tip = None
|
||||
self.bar = None
|
||||
self.disclaimer = True
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header()
|
||||
@@ -95,9 +78,7 @@ class Index(Screen):
|
||||
Button(self.prompt.reset_button, id="reset"),
|
||||
),
|
||||
)
|
||||
with Center():
|
||||
yield ProgressBar(total=None, show_percentage=False, show_eta=False)
|
||||
yield RichLog(markup=True)
|
||||
yield RichLog(markup=True, wrap=True)
|
||||
yield Footer()
|
||||
|
||||
def on_mount(self) -> None:
|
||||
@@ -105,17 +86,15 @@ class Index(Screen):
|
||||
VERSION_MINOR}{" Beta" if VERSION_BETA else ""}"
|
||||
self.url = self.query_one(Input)
|
||||
self.tip = self.query_one(RichLog)
|
||||
self.bar = self.query_one(ProgressBar)
|
||||
self.tip.write(Text("\n".join(self.prompt.disclaimer), style=MASTER))
|
||||
|
||||
def close_disclaimer(self):
|
||||
if self.disclaimer:
|
||||
self.tip.clear()
|
||||
self.disclaimer = False
|
||||
|
||||
@on(Button.Pressed, "#deal")
|
||||
def deal_button(self):
|
||||
create_task(self.deal())
|
||||
async def deal_button(self):
|
||||
if self.url.value:
|
||||
await create_task(self.deal())
|
||||
else:
|
||||
self.tip.write(Text(self.prompt.invalid_link, style=WARNING))
|
||||
self.tip.write(Text(">" * 50, style=GENERAL))
|
||||
|
||||
@on(Button.Pressed, "#reset")
|
||||
def reset_button(self):
|
||||
@@ -125,52 +104,13 @@ class Index(Screen):
|
||||
def paste_button(self):
|
||||
self.query_one(Input).value = paste()
|
||||
|
||||
@show_state
|
||||
async def deal(self):
|
||||
if not self.url.value:
|
||||
self.tip.write(Text(self.prompt.invalid_link, style=WARNING))
|
||||
return
|
||||
if any(await self.app_.extract(self.url.value, True, log=self.tip)):
|
||||
await self.app.push_screen("loading")
|
||||
if any(await self.xhs.extract(self.url.value, True, log=self.tip)):
|
||||
self.url.value = ""
|
||||
else:
|
||||
self.tip.write(Text(self.prompt.download_failure, style=ERROR))
|
||||
|
||||
@show_state
|
||||
async def action_check_update(self):
|
||||
self.tip.write(
|
||||
Text(
|
||||
self.prompt.check_update_notification,
|
||||
style=WARNING))
|
||||
try:
|
||||
url = await self.app_.html.request_url(RELEASES, False, self.tip)
|
||||
latest_major, latest_minor = map(
|
||||
int, url.split("/")[-1].split(".", 1))
|
||||
if latest_major > VERSION_MAJOR or latest_minor > VERSION_MINOR:
|
||||
self.tip.write(
|
||||
Text(
|
||||
self.prompt.official_version_update(
|
||||
latest_major,
|
||||
latest_minor),
|
||||
style=WARNING))
|
||||
self.tip.write(RELEASES)
|
||||
elif latest_minor == VERSION_MINOR and VERSION_BETA:
|
||||
self.tip.write(
|
||||
Text(
|
||||
self.prompt.development_version_update,
|
||||
style=WARNING))
|
||||
self.tip.write(RELEASES)
|
||||
elif VERSION_BETA:
|
||||
self.tip.write(
|
||||
Text(
|
||||
self.prompt.latest_development_version,
|
||||
style=WARNING))
|
||||
else:
|
||||
self.tip.write(
|
||||
Text(
|
||||
self.prompt.latest_official_version,
|
||||
style=INFO))
|
||||
except ValueError:
|
||||
self.tip.write(Text(self.prompt.check_update_failure, style=ERROR))
|
||||
self.app.pop_screen()
|
||||
|
||||
@staticmethod
|
||||
def action_user_script():
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
from textual.app import ComposeResult
|
||||
from textual.screen import Screen
|
||||
from textual.containers import Grid
|
||||
from textual.screen import ModalScreen
|
||||
from textual.widgets import Label
|
||||
from textual.widgets import LoadingIndicator
|
||||
|
||||
from source.translator import (
|
||||
English,
|
||||
Chinese,
|
||||
)
|
||||
|
||||
__all__ = ["Loading"]
|
||||
|
||||
|
||||
class Loading(Screen):
|
||||
class Loading(ModalScreen):
|
||||
def __init__(self, language: Chinese | English):
|
||||
super().__init__()
|
||||
self.prompt = language
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield LoadingIndicator()
|
||||
yield Grid(
|
||||
Label(self.prompt.processing),
|
||||
LoadingIndicator(),
|
||||
classes="loading",
|
||||
)
|
||||
|
||||
9
source/TUI/progress.py
Normal file
9
source/TUI/progress.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from textual.app import ComposeResult
|
||||
from textual.screen import Screen
|
||||
|
||||
__all__ = ["Progress"]
|
||||
|
||||
|
||||
class Progress(Screen):
|
||||
def compose(self) -> ComposeResult:
|
||||
pass
|
||||
@@ -12,7 +12,6 @@ from textual.widgets import Input
|
||||
from textual.widgets import Label
|
||||
from textual.widgets import Select
|
||||
|
||||
from source.module import ROOT
|
||||
from source.translator import (
|
||||
LANGUAGE,
|
||||
Chinese,
|
||||
@@ -23,7 +22,6 @@ __all__ = ["Setting"]
|
||||
|
||||
|
||||
class Setting(Screen):
|
||||
CSS_PATH = ROOT.joinpath("static/XHS-Downloader.tcss")
|
||||
BINDINGS = [
|
||||
Binding(key="q", action="quit", description="退出程序/Quit"),
|
||||
Binding(key="b", action="index", description="返回首页/Back"),
|
||||
|
||||
70
source/TUI/update.py
Normal file
70
source/TUI/update.py
Normal file
@@ -0,0 +1,70 @@
|
||||
from aiohttp import ClientTimeout
|
||||
from rich.text import Text
|
||||
from textual import work
|
||||
from textual.app import ComposeResult
|
||||
from textual.containers import Grid
|
||||
from textual.screen import ModalScreen
|
||||
from textual.widgets import Label
|
||||
from textual.widgets import LoadingIndicator
|
||||
|
||||
from source.application import XHS
|
||||
from source.module import (
|
||||
VERSION_MAJOR,
|
||||
VERSION_MINOR,
|
||||
VERSION_BETA,
|
||||
ERROR,
|
||||
WARNING,
|
||||
INFO,
|
||||
RELEASES,
|
||||
)
|
||||
from source.translator import (
|
||||
English,
|
||||
Chinese,
|
||||
)
|
||||
|
||||
__all__ = ["Update"]
|
||||
|
||||
|
||||
class Update(ModalScreen):
|
||||
def __init__(self, app: XHS, language: Chinese | English):
|
||||
super().__init__()
|
||||
self.xhs = app
|
||||
self.prompt = language
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Grid(
|
||||
Label(self.prompt.check_update_notification),
|
||||
LoadingIndicator(),
|
||||
classes="loading",
|
||||
)
|
||||
|
||||
@work()
|
||||
async def check_update(self) -> None:
|
||||
try:
|
||||
url = await self.xhs.html.request_url(RELEASES, False, None, timeout=ClientTimeout(connect=5))
|
||||
latest_major, latest_minor = map(
|
||||
int, url.split("/")[-1].split(".", 1))
|
||||
if latest_major > VERSION_MAJOR or latest_minor > VERSION_MINOR:
|
||||
tip = Text(
|
||||
f"{self.prompt.official_version_update(
|
||||
latest_major,
|
||||
latest_minor)}\n{RELEASES}",
|
||||
style=WARNING)
|
||||
elif latest_minor == VERSION_MINOR and VERSION_BETA:
|
||||
tip = Text(
|
||||
f"{self.prompt.development_version_update}\n{RELEASES}",
|
||||
style=WARNING)
|
||||
elif VERSION_BETA:
|
||||
tip = Text(
|
||||
self.prompt.latest_development_version,
|
||||
style=WARNING)
|
||||
else:
|
||||
tip = Text(
|
||||
self.prompt.latest_official_version,
|
||||
style=INFO)
|
||||
except ValueError:
|
||||
tip = Text(self.prompt.check_update_failure, style=ERROR)
|
||||
self.dismiss(tip)
|
||||
|
||||
def on_mount(self) -> None:
|
||||
self.check_update()
|
||||
@@ -1,3 +1,4 @@
|
||||
from asyncio import gather
|
||||
from pathlib import Path
|
||||
|
||||
from aiohttp import ClientError
|
||||
@@ -36,12 +37,13 @@ class Download:
|
||||
path = self.__generate_path(name)
|
||||
match type_:
|
||||
case "视频":
|
||||
await self.__download(urls[0], path, f"{name}", self.video_format, log, bar)
|
||||
tasks = self.__ready_download_video(urls, path, name, log)
|
||||
case "图文":
|
||||
for index, url in enumerate(urls, start=1):
|
||||
await self.__download(url, path, f"{name}_{index}", self.image_format, log, bar)
|
||||
tasks = self.__ready_download_image(urls, path, name, log)
|
||||
case _:
|
||||
raise ValueError
|
||||
tasks = [self.__download(url, path, name, format_, log, bar) for url, name, format_ in tasks]
|
||||
await gather(*tasks)
|
||||
return path
|
||||
|
||||
def __generate_path(self, name: str):
|
||||
@@ -49,6 +51,22 @@ class Download:
|
||||
path.mkdir(exist_ok=True)
|
||||
return path
|
||||
|
||||
def __ready_download_video(self, urls: list[str], path: Path, name: str, log) -> list:
|
||||
if any(path.glob(f"{name}.*")):
|
||||
logging(log, self.prompt.skip_download(name))
|
||||
return []
|
||||
return [(urls[0], name, self.video_format)]
|
||||
|
||||
def __ready_download_image(self, urls: list[str], path: Path, name: str, log) -> list:
|
||||
tasks = []
|
||||
for i, j in enumerate(urls, start=1):
|
||||
file = f"{name}_{i}"
|
||||
if any(path.glob(f"{file}.*")):
|
||||
logging(log, self.prompt.skip_download(file))
|
||||
continue
|
||||
tasks.append([j, file, self.image_format])
|
||||
return tasks
|
||||
|
||||
@re_download
|
||||
async def __download(self, url: str, path: Path, name: str, format_: str, log, bar):
|
||||
try:
|
||||
@@ -58,10 +76,7 @@ class Download:
|
||||
suffix = self.__extract_type(
|
||||
response.headers.get("Content-Type")) or format_
|
||||
temp = self.temp.joinpath(name)
|
||||
file = path.joinpath(name).with_suffix(f".{suffix}")
|
||||
if self.manager.is_exists(file):
|
||||
logging(log, self.prompt.skip_download(name))
|
||||
return True
|
||||
real = path.joinpath(name).with_suffix(f".{suffix}")
|
||||
# self.__create_progress(
|
||||
# bar, int(
|
||||
# response.headers.get(
|
||||
@@ -70,7 +85,7 @@ class Download:
|
||||
async for chunk in response.content.iter_chunked(self.chunk):
|
||||
f.write(chunk)
|
||||
# self.__update_progress(bar, len(chunk))
|
||||
self.manager.move(temp, file)
|
||||
self.manager.move(temp, real)
|
||||
# self.__create_progress(bar, None)
|
||||
logging(log, self.prompt.download_success(name))
|
||||
return True
|
||||
|
||||
@@ -21,11 +21,13 @@ class Html:
|
||||
url: str,
|
||||
content=True,
|
||||
log=None,
|
||||
**kwargs,
|
||||
) -> str:
|
||||
try:
|
||||
async with self.session.get(
|
||||
url,
|
||||
proxy=self.proxy,
|
||||
**kwargs,
|
||||
) as response:
|
||||
if response.status != 200:
|
||||
return ""
|
||||
|
||||
@@ -19,7 +19,7 @@ __all__ = ["Manager"]
|
||||
|
||||
|
||||
class Manager:
|
||||
NAME = compile(r"[^\u4e00-\u9fa5a-zA-Z0-9_]")
|
||||
NAME = compile(r"[^\u4e00-\u9fa5a-zA-Z0-9]")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
||||
@@ -6,13 +6,13 @@ class Chinese:
|
||||
disclaimer: tuple[str] = (
|
||||
"关于 XHS-Downloader 的 免责声明:",
|
||||
"",
|
||||
"1. 使用者对本项目的使用由使用者自行决定,并自行承担风险。作者对使用者使用本项目所产生的任何损失、责任、或风险概不负责。",
|
||||
"2. 本项目的作者提供的代码和功能是基于现有知识和技术的开发成果。作者尽力确保代码的正确性和安全性,但不保证代码完全没有错误或缺陷。",
|
||||
"3. 使用者在使用本项目时必须严格遵守 GNU General Public License v3.0 的要求,并在适当的地方注明使用了 GNU General Public License v3.0 的代码。",
|
||||
"4. 使用者在任何情况下均不得将本项目的作者、贡献者或其他相关方与使用者的使用行为联系起来,或要求其对使用者使用本项目所产生的任何损失或损害负责。",
|
||||
"5. 使用者在使用本项目的代码和功能时,必须自行研究相关法律法规,并确保其使用行为合法合规。任何因违反法律法规而导致的法律责任和风险,均由使用者自行承担。",
|
||||
"6. 本项目的作者不会提供 XHS-Downloader 项目的付费版本,也不会提供与 XHS-Downloader 项目相关的任何商业服务。",
|
||||
"7. 基于本项目进行的任何二次开发、修改或编译的程序与原创作者无关,原创作者不承担与二次开发行为或其结果相关的任何责任,使用者应自行对因"
|
||||
"1.使用者对本项目的使用由使用者自行决定,并自行承担风险。作者对使用者使用本项目所产生的任何损失、责任、或风险概不负责。",
|
||||
"2.本项目的作者提供的代码和功能是基于现有知识和技术的开发成果。作者尽力确保代码的正确性和安全性,但不保证代码完全没有错误或缺陷。",
|
||||
"3.使用者在使用本项目时必须严格遵守 GNU General Public License v3.0 的要求,并在适当的地方注明使用了 GNU General Public License v3.0 的代码。",
|
||||
"4.使用者在任何情况下均不得将本项目的作者、贡献者或其他相关方与使用者的使用行为联系起来,或要求其对使用者使用本项目所产生的任何损失或损害负责。",
|
||||
"5.使用者在使用本项目的代码和功能时,必须自行研究相关法律法规,并确保其使用行为合法合规。任何因违反法律法规而导致的法律责任和风险,均由使用者自行承担。",
|
||||
"6.本项目的作者不会提供 XHS-Downloader 项目的付费版本,也不会提供与 XHS-Downloader 项目相关的任何商业服务。",
|
||||
"7.基于本项目进行的任何二次开发、修改或编译的程序与原创作者无关,原创作者不承担与二次开发行为或其结果相关的任何责任,使用者应自行对因"
|
||||
"二次开发可能带来的各种情况负全部责任。",
|
||||
"",
|
||||
"在使用本项目的代码和功能之前,请您认真考虑并接受以上免责声明。如果您对上述声明有任何疑问或不同意,请不要使用本项目的代码和功能。如果"
|
||||
@@ -67,6 +67,8 @@ class Chinese:
|
||||
save_button: str = "保存配置"
|
||||
abandon_button: str = "放弃更改"
|
||||
|
||||
processing: str = "程序处理中..."
|
||||
|
||||
@staticmethod
|
||||
def request_error(url: str) -> str:
|
||||
return f"网络异常,请求 {url} 失败!"
|
||||
|
||||
@@ -85,6 +85,8 @@ class English(Chinese):
|
||||
save_button: str = "Save configuration"
|
||||
abandon_button: str = "Discard changes"
|
||||
|
||||
processing: str = "Processing..."
|
||||
|
||||
@staticmethod
|
||||
def request_error(url: str) -> str:
|
||||
return f"Network error, failed to access {url}!"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name XHS-Downloader
|
||||
// @namespace https://github.com/JoeanAmier/XHS-Downloader
|
||||
// @version 1.4
|
||||
// @version 1.4.1
|
||||
// @description 提取小红书作品/用户链接,下载小红书无水印图文/视频作品文件
|
||||
// @author JoeanAmier
|
||||
// @match http*://www.xiaohongshu.com/explore*
|
||||
@@ -385,16 +385,18 @@
|
||||
const buttons = [createButton("Download", "下载无水印作品文件", extractDownloadLinks), createButton("Post", "提取发布作品链接", extractAllLinksEvent, 0), createButton("Collection", "提取收藏作品链接", extractAllLinksEvent, 1), createButton("Favorite", "提取点赞作品链接", extractAllLinksEvent, 2), createButton("Feed", "提取发现作品链接", extractAllLinksEvent, -1), createButton("Search", "提取搜索作品链接", extractAllLinksEvent, 3), createButton("User", "提取搜索用户链接", extractAllLinksEvent, 4), createButton("About", "关于 XHS-Downloader", about,)]
|
||||
|
||||
const run = url => {
|
||||
if (url === "https://www.xiaohongshu.com/explore") {
|
||||
updateContainer(buttons.slice(4, 5));
|
||||
} else if (url.includes("https://www.xiaohongshu.com/explore/")) {
|
||||
updateContainer(buttons.slice(0, 1));
|
||||
} else if (url.includes("https://www.xiaohongshu.com/user/profile/")) {
|
||||
updateContainer(buttons.slice(1, 4));
|
||||
} else if (url.includes("https://www.xiaohongshu.com/search_result")) {
|
||||
updateContainer(buttons.slice(5, 7));
|
||||
}
|
||||
};
|
||||
setTimeout(function () {
|
||||
if (url === "https://www.xiaohongshu.com/explore") {
|
||||
updateContainer(buttons.slice(4, 5));
|
||||
} else if (url.includes("https://www.xiaohongshu.com/explore/")) {
|
||||
updateContainer(buttons.slice(0, 1));
|
||||
} else if (url.includes("https://www.xiaohongshu.com/user/profile/")) {
|
||||
updateContainer(buttons.slice(1, 4));
|
||||
} else if (url.includes("https://www.xiaohongshu.com/search_result")) {
|
||||
updateContainer(buttons.slice(5, 7));
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
|
||||
let currentUrl = window.location.href;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Screen, RichLog {
|
||||
ScrollableContainer, RichLog {
|
||||
background: #2f3542;
|
||||
}
|
||||
Button {
|
||||
@@ -44,3 +44,14 @@ Bar > .bar--indeterminate {
|
||||
Bar > .bar--complete {
|
||||
color: #ff7f50;
|
||||
}
|
||||
.loading {
|
||||
grid-size: 1 2;
|
||||
grid-gutter: 1;
|
||||
width: 40vw;
|
||||
height: 5;
|
||||
background: #353b48;
|
||||
border: double #747d8c;
|
||||
}
|
||||
ModalScreen {
|
||||
align: center middle;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user