Revert "feat: 添加收藏夹选择和取消收藏功能"
This commit is contained in:
+2
-18
@@ -63,15 +63,7 @@ class SequenceAnim extends Anim {
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
if (this.intervalId) {
|
||||
clearInterval(this.intervalId);
|
||||
this.intervalId = null;
|
||||
}
|
||||
// Remove self from global.animations to prevent memory leak
|
||||
if (global.animations && global.animations[this.pageId]) {
|
||||
const idx = global.animations[this.pageId].indexOf(this);
|
||||
if (idx !== -1) global.animations[this.pageId].splice(idx, 1);
|
||||
}
|
||||
clearInterval(this.intervalId!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,15 +124,7 @@ class DomAnim extends Anim {
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
if (this.intervalId) {
|
||||
clearInterval(this.intervalId);
|
||||
this.intervalId = null;
|
||||
}
|
||||
// Remove self from global.animations to prevent memory leak
|
||||
if (global.animations && global.animations[this.pageId]) {
|
||||
const idx = global.animations[this.pageId].indexOf(this);
|
||||
if (idx !== -1) global.animations[this.pageId].splice(idx, 1);
|
||||
}
|
||||
clearInterval(this.intervalId!);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-28
@@ -42,39 +42,16 @@ export default {
|
||||
global.settings = settings
|
||||
|
||||
console.log("appinit > initSavedContentManager")
|
||||
try {
|
||||
await savedcontent.SavedContentManager.initialize()
|
||||
} catch (e) {
|
||||
console.error("Failed to init SavedContentManager:", e)
|
||||
}
|
||||
await savedcontent.SavedContentManager.initialize()
|
||||
global.savedcontent = savedcontent
|
||||
|
||||
console.log("appinit > initDeviceInfo")
|
||||
try {
|
||||
global.DEVICE_INFO = await tools.getDeviceInformation()
|
||||
} catch (e) {
|
||||
console.error("Failed to get device info:", e)
|
||||
global.DEVICE_INFO = { screenShape: "round", product: "unknown" }
|
||||
}
|
||||
try {
|
||||
global.DEVICE_SERIAL = await tools.getDeviceSerial()
|
||||
} catch (e) {
|
||||
console.error("Failed to get device serial:", e)
|
||||
global.DEVICE_SERIAL = "unknown"
|
||||
}
|
||||
try {
|
||||
global.DEVICE_NETWORK_TYPE = await tools.getNetworkType()
|
||||
} catch (e) {
|
||||
console.error("Failed to get network type:", e)
|
||||
global.DEVICE_NETWORK_TYPE = "unknown"
|
||||
}
|
||||
global.DEVICE_INFO = await tools.getDeviceInformation()
|
||||
global.DEVICE_SERIAL = await tools.getDeviceSerial()
|
||||
global.DEVICE_NETWORK_TYPE = await tools.getNetworkType()
|
||||
|
||||
console.log("appinit > initBgImg")
|
||||
try {
|
||||
this.bgimg.Init()
|
||||
} catch (e) {
|
||||
console.error("Failed to init bgimg:", e)
|
||||
}
|
||||
this.bgimg.Init()
|
||||
global.bgimg = this.bgimg
|
||||
|
||||
console.log("appinit > createBiliClient")
|
||||
|
||||
+1
-2
@@ -35,7 +35,6 @@ export function PatchArticleContent(doms: any) {
|
||||
if (!dom) continue; // 避免空节点
|
||||
|
||||
if (dom.type === "img") {
|
||||
if (!dom.attributes || !dom.attributes.src) continue;
|
||||
// 如果图片的 src 包含 .png 或 .jpg 扩展名
|
||||
if (dom.attributes.src.includes(".png") || dom.attributes.src.includes(".jpg")) {
|
||||
// 确保 src 包含 http:// 或 https:// 前缀
|
||||
@@ -47,7 +46,7 @@ export function PatchArticleContent(doms: any) {
|
||||
|
||||
if(dom.attributes){
|
||||
// 如果图片过大,调整其尺寸
|
||||
if (parseInt(dom.attributes.height) > 500 || parseInt(dom.attributes.width) > 500) {
|
||||
if (parseInt(dom.attributes.height) > 500 || parseInt(dom.attributes.height) > 500) {
|
||||
dom.attributes.src += "@250h"; // 对应补丁操作
|
||||
dom.attributes._patched_sign = "large_picture_scaled"
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ class FileAPI {
|
||||
file.access({
|
||||
...options,
|
||||
success: () => resolve(true),
|
||||
fail: () => resolve(false),
|
||||
fail: (_, code: number) => reject(new Error(`Access failed with code ${code}`)),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -55,10 +55,8 @@ export const BilibiliClientAPIRequestMethods = {
|
||||
const response = await this.fetch.fetch({
|
||||
url,
|
||||
responseType: responseType,
|
||||
header: this.getHeaders(),
|
||||
timeout: 15000
|
||||
header: this.getHeaders()
|
||||
});
|
||||
if (!response || !response.data) return void 0;
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
global.logger.error(`GET请求失败,详细数据:`, error);
|
||||
@@ -88,10 +86,8 @@ export const BilibiliClientAPIRequestMethods = {
|
||||
responseType: 'json',
|
||||
method: 'POST',
|
||||
data,
|
||||
header: headers,
|
||||
timeout: 15000
|
||||
header: headers
|
||||
});
|
||||
if (!response || !response.data) return void 0;
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
global.logger.error(`POST请求失败,详细数据:`, error);
|
||||
|
||||
@@ -7,14 +7,6 @@ export const BilibiliClientFavFolderMethods = {
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
// 获取用户所有收藏夹及目标视频在各收藏夹中的收藏状态
|
||||
// 返回的每个 folder 对象中包含 fav_state 字段:0=未收藏, 1=已收藏
|
||||
async getUserFavouriteFoldersWithVideoState(this: any, mid: string, aid: string): Promise<any> {
|
||||
const url = `https://api.bilibili.com/x/v3/fav/folder/created/list-all?up_mid=${mid}&type=2&rid=${aid}`;
|
||||
const response = await this.getRequest(url);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
// 获取目标收藏夹元数据
|
||||
async getFavouriteFolderMetadata(this: any, mlid: string): Promise<any> {
|
||||
const url = `https://api.bilibili.com/x/v3/fav/folder/info?media_id=${mlid}`;
|
||||
|
||||
@@ -48,6 +48,8 @@ export const BilibiliClientMessageMethods = {
|
||||
headers["Host"] = "api.vc.bilibili.com"
|
||||
headers["Origin"] = "https://message.bilibili.com"
|
||||
headers["Referer"] = "https://message.bilibili.com/"
|
||||
headers["Content-Length"] = body.length.toString()
|
||||
|
||||
const response = await this.postRequestWbi(url, {
|
||||
w_sender_uid: this.accountInfo.mid,
|
||||
w_receiver_id: receiver_id,
|
||||
|
||||
@@ -20,7 +20,7 @@ export const BilibiliClientVideoActionMethods = {
|
||||
let defaultFolderID = 0;
|
||||
const folders = await this.getUserFavouriteFolders(this.accountInfo.mid);
|
||||
folders.list.forEach((folder: any) => {
|
||||
if (folder.attr === 1 || folder.id === 0) {
|
||||
if (folder.title === "默认收藏夹") {
|
||||
defaultFolderID = folder.id;
|
||||
}
|
||||
});
|
||||
@@ -38,56 +38,4 @@ export const BilibiliClientVideoActionMethods = {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// 取消收藏视频从默认收藏夹
|
||||
async unstarVideoFromDefaultFavFolderByBVID(this: any, bvid: string): Promise<any> {
|
||||
let defaultFolderID = 0;
|
||||
const folders = await this.getUserFavouriteFolders(this.accountInfo.mid);
|
||||
folders.list.forEach((folder: any) => {
|
||||
if (folder.attr === 1 || folder.id === 0) {
|
||||
defaultFolderID = folder.id;
|
||||
}
|
||||
});
|
||||
if (!defaultFolderID) return false;
|
||||
|
||||
try {
|
||||
const videoInfo = await this.getVideoInfoByBVID(bvid);
|
||||
const aid = videoInfo.aid;
|
||||
const url = `https://api.bilibili.com/x/v3/fav/resource/deal`;
|
||||
const data = `rid=${aid}&csrf=${this.biliJct}&type=2&add_media_ids=&del_media_ids=${defaultFolderID}`;
|
||||
const response = await this.postRequest(url, data, "application/x-www-form-urlencoded");
|
||||
return response.data.code;
|
||||
} catch (error) {
|
||||
global.logger.error("Error unstarring video: ", error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// 收藏视频至指定收藏夹(支持多个)
|
||||
async starVideoToFavFolders(this: any, aid: string, folderIds: string[]): Promise<any> {
|
||||
try {
|
||||
const add_media_ids = folderIds.join(',');
|
||||
const url = `https://api.bilibili.com/x/v3/fav/resource/deal`;
|
||||
const data = `rid=${aid}&csrf=${this.biliJct}&type=2&add_media_ids=${add_media_ids}&del_media_ids=`;
|
||||
const response = await this.postRequest(url, data, "application/x-www-form-urlencoded");
|
||||
return response.data.code;
|
||||
} catch (error) {
|
||||
global.logger.error("Error starring video to folders: ", error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
// 从指定收藏夹取消收藏视频(支持多个)
|
||||
async unstarVideoFromFavFolders(this: any, aid: string, folderIds: string[]): Promise<any> {
|
||||
try {
|
||||
const del_media_ids = folderIds.join(',');
|
||||
const url = `https://api.bilibili.com/x/v3/fav/resource/deal`;
|
||||
const data = `rid=${aid}&csrf=${this.biliJct}&type=2&add_media_ids=&del_media_ids=${del_media_ids}`;
|
||||
const response = await this.postRequest(url, data, "application/x-www-form-urlencoded");
|
||||
return response.data.code;
|
||||
} catch (error) {
|
||||
global.logger.error("Error unstarring video from folders: ", error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
}
|
||||
+10
-10
@@ -5,24 +5,24 @@ export const eula = ` <h1>澎湃哔哩(Hyperbili)用户协议</h1>
|
||||
<p>本客户端是基于哔哩哔哩网页端API开发的第三方工具,旨在为用户提供在部分搭载Xiaomi Vela OS的设备上浏览哔哩哔哩提供的内容的能力。本客户端不具备独立的账号系统,用户需通过哔哩哔哩官方App进行扫码登录。所有的服务和内容均来自哔哩哔哩平台,我们不对其内容的准确性、合法性或其他方面负责。</p>
|
||||
|
||||
<h2>2. 免责声明</h2>
|
||||
<div>
|
||||
<p>
|
||||
<p><strong>服务稳定性</strong>:我们将尽力维护客户端的正常运行,但不保证其无故障、无中断或随时可用。由于哔哩哔哩API变更、网络故障、服务器问题或其他不可抗力因素导致的服务中断、数据丢失或功能异常,AstralSight Studios不承担任何责任。</p>
|
||||
<p><strong>第三方内容</strong>:本客户端依赖哔哩哔哩平台提供的内容,AstralSight Studios不对任何第三方内容的准确性、合法性、完整性或适用性做出任何承诺或保证,用户需自行判断并承担使用风险。</p>
|
||||
<p><strong>责任限制</strong>:在任何情况下,AstralSight Studios不对用户因使用或无法使用本客户端导致的任何间接、附带、特殊或惩罚性损害承担责任。</p>
|
||||
<p><strong>不可抗力</strong>:对于因自然灾害、战争、网络攻击、政府行为、哔哩哔哩API关闭或变更等不可抗力事件造成的服务中断或损失,AstralSight Studios不承担任何责任。</p>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<h2>3. 账号安全与使用</h2>
|
||||
<p>用户通过哔哩哔哩官方App扫码登录并使用其哔哩哔哩账号。本客户端不会保存用户登录密码,但会保存用户的登录Token、与哔哩哔哩API交互产生的Cookies等,但不对其安全性(包括但不限于:存储安全性、传输安全性)负任何责任。用户需对其账号安全负责。如果因用户原因导致账号被盗或发生其他安全问题,AstralSight Studios不承担责任。</p>
|
||||
|
||||
<h2>4. 用户行为规范</h2>
|
||||
<p>用户在使用本客户端时应遵守国家法律法规、哔哩哔哩平台的相关规定,以及本协议中的条款。用户不得利用本客户端进行包括但不限于以下行为:</p>
|
||||
<div>
|
||||
<p>
|
||||
<p>传播非法、侵权、骚扰、诽谤、淫秽、欺诈性内容;</p>
|
||||
<p>侵犯他人知识产权、隐私权、名誉权等合法权益;</p>
|
||||
<p>进行批量数据抓取、自动化访问或未经授权的网络攻击;</p>
|
||||
<p>任何其他违反哔哩哔哩平台规则或法律法规的行为。</p>
|
||||
</div>
|
||||
</p>
|
||||
<p>对于上述行为,AstralSight Studios有权立即中止或终止用户的使用权限,且不承担任何法律责任。</p>
|
||||
|
||||
<h2>5. 开源许可</h2>
|
||||
@@ -39,29 +39,29 @@ export const eula = ` <h1>澎湃哔哩(Hyperbili)用户协议</h1>
|
||||
|
||||
<h2>1. 信息的收集</h2>
|
||||
<p>在使用本客户端的过程中,我们可能会收集但不限于以下信息:</p>
|
||||
<div>
|
||||
<p>
|
||||
<p><strong>设备信息</strong>:包括设备型号、操作系统、设备标识符等;</p>
|
||||
<p><strong>网络信息</strong>:包括IP地址、网络提供商、连接时长等;</p>
|
||||
<p><strong>操作日志</strong>:包括用户操作行为、功能使用情况、访问页面记录等;</p>
|
||||
<p><strong>其他数据</strong>:随着产品功能的扩展,我们可能收集更多种类的用户数据,具体收集内容将在未来版本的隐私政策中进行更新。</p>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<h2>2. 数据的使用</h2>
|
||||
<p>我们将收集到的用户数据用于以下目的:</p>
|
||||
<div>
|
||||
<p>
|
||||
<p>优化和改进客户端的功能与用户体验;</p>
|
||||
<p>分析用户行为,提升产品的使用效果;</p>
|
||||
<p>保障客户端的安全,防止恶意攻击和非法活动;</p>
|
||||
<p>满足法律法规要求,或配合相关部门的合法请求。</p>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<h2>3. 数据的共享</h2>
|
||||
<p>我们不会主动将用户的个人数据分享给任何第三方,除非在以下情形下:</p>
|
||||
<div>
|
||||
<p>
|
||||
<p>因任何不可抗力(包括但不限于 因资金短缺造成无法负担起数据存储费用、遭受网络攻击等)导致数据必须分享给第三方以进行包括但不限于数据存储、CDN分发、异地容灾等操作;</p>
|
||||
<p>遵守法律法规的要求,或响应执法机关、法院的合法请求;</p>
|
||||
<p>在维护客户端的合法权益时,为保护AstralSight Studios免受潜在侵害,可能会与相关合作伙伴或技术提供商共享必要数据。</p>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<h2>4. 数据的保护</h2>
|
||||
<p>我们将采取合理的技术手段和管理措施,保护用户数据免受未经授权的访问、泄露、篡改或破坏。然而,互联网环境中无法完全消除所有风险,用户应知晓并承担这些潜在风险。AstralSight Studios不对因用户行为或外部因素导致的数据泄露或损失负责。</p>
|
||||
|
||||
+2
-1
@@ -1,3 +1,5 @@
|
||||
const date = new Date()
|
||||
|
||||
const tips = [
|
||||
"你所热爱的,就是你热爱的",
|
||||
"让我猜猜你现在使用的设备是...?",
|
||||
@@ -30,7 +32,6 @@ const AprilFoolsDayTips = [
|
||||
]
|
||||
|
||||
export function getTips(): string{
|
||||
const date = new Date()
|
||||
// 愚人节特供
|
||||
if(date.getMonth() === 3 && date.getDate() === 1){
|
||||
return AprilFoolsDayTips[Math.floor(Math.random() * AprilFoolsDayTips.length)]
|
||||
|
||||
+1
-6
@@ -4,7 +4,7 @@ export async function Jump() {
|
||||
storage.get({
|
||||
key: "bilibili_account",
|
||||
success: async (bilibili_account) => {
|
||||
if (!bilibili_account || bilibili_account.length < 1) {
|
||||
if (bilibili_account.length < 1) {
|
||||
router.replace({
|
||||
uri: "pages/app/entry/login"
|
||||
})
|
||||
@@ -13,11 +13,6 @@ export async function Jump() {
|
||||
uri: "pages/app/entry/prepage"
|
||||
})
|
||||
}
|
||||
},
|
||||
fail: function () {
|
||||
router.replace({
|
||||
uri: "pages/app/entry/login"
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ class Logger {
|
||||
const message = args.map((arg) => this.safeStringify(arg)).join(' ');
|
||||
|
||||
// 在控制台输出日志
|
||||
console.log(`[${timestamp}] [${level.toUpperCase()}] ${message}`);
|
||||
console.log(`%c[${timestamp}] [${level.toUpperCase()}] ${message}`, style);
|
||||
|
||||
// 同步日志到文件
|
||||
this.flushLogToFile(`[${timestamp}] [${level.toUpperCase()}] ${message}`);
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"logLevel": "warn",
|
||||
"logLevel": "log",
|
||||
"designWidth": "device-width",
|
||||
"background": {
|
||||
"features": [
|
||||
|
||||
@@ -84,7 +84,7 @@ export default {
|
||||
onInit() {
|
||||
// 来自子组件push的object传递会变成字符串
|
||||
// 因此需要进行类型检查和手动parse
|
||||
if (typeof this.dyn !== "object") {
|
||||
if (typeof this.dyn != Object) {
|
||||
this.dyn = JSON.parse(this.dyn)
|
||||
console.log(this.dyn)
|
||||
}
|
||||
|
||||
@@ -48,8 +48,7 @@ export default {
|
||||
},
|
||||
replymode: false,
|
||||
reply_target: null,
|
||||
scrclass: "",
|
||||
input_text: { content: "" }
|
||||
scrclass: ""
|
||||
},
|
||||
async SendReply(evt) {
|
||||
this.replymode = false
|
||||
@@ -63,19 +62,19 @@ export default {
|
||||
let result
|
||||
try {
|
||||
result = this.secmode
|
||||
? await global.biliclient.GiveSecReply(
|
||||
this.type,
|
||||
this.oid,
|
||||
this.reply_target,
|
||||
content
|
||||
)
|
||||
: await global.biliclient.GiveTreeReply(
|
||||
? await global.biliclient.GiveTreeReply(
|
||||
this.type,
|
||||
this.oid,
|
||||
this.reply_target,
|
||||
this.rootrpid,
|
||||
content
|
||||
)
|
||||
: await global.biliclient.GiveSecReply(
|
||||
this.type,
|
||||
this.oid,
|
||||
this.reply_target,
|
||||
content
|
||||
)
|
||||
|
||||
if (result.code === 0) {
|
||||
prompt.showToast({message: "发送成功"})
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
import router from "@system.router"
|
||||
export default {
|
||||
private: {
|
||||
hotwords: [],
|
||||
hotwords: {},
|
||||
showHotwordsList: false,
|
||||
input_mode: false,
|
||||
anims: {
|
||||
|
||||
@@ -50,7 +50,7 @@ export default {
|
||||
user: {},
|
||||
stat: {},
|
||||
navnum: {},
|
||||
masterpiece: [],
|
||||
masterpiece: {},
|
||||
dynamiclist: {},
|
||||
anims: {
|
||||
show_loading: false
|
||||
|
||||
@@ -138,18 +138,6 @@
|
||||
import prompt from "@system.prompt";
|
||||
import request from "@system.request";
|
||||
import { asyncFile } from "../../../asyncapi/file";
|
||||
|
||||
// Music API stub — getSongUrl/getLyric are not yet implemented.
|
||||
// Wrapping in a safe object prevents ReferenceError crashes.
|
||||
const api = {
|
||||
getSongUrl(id, opts) {
|
||||
if (opts && opts.fail) opts.fail('Music API not implemented');
|
||||
},
|
||||
getLyric(id, opts) {
|
||||
if (opts && opts.fail) opts.fail('Music API not implemented');
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
props: { playlistId: { default: null }, startIndex: { default: 0 }, tracks: { default: null }, bvid: { default: null }, cachedAudioUri: { default: null }, cachedTitle: { default: null }, cachedCoverUrl: { default: null }, cachedAuthor: { default: null } },
|
||||
data: {
|
||||
@@ -413,9 +401,10 @@
|
||||
that.audioReady = true;
|
||||
}
|
||||
};
|
||||
// ontimeupdate is already set in bindAudioEvents() with pendingSongId guard.
|
||||
// Do NOT overwrite it here — the bindAudioEvents version handles both
|
||||
// playerState.playDuration and updateLyric().
|
||||
audio.ontimeupdate = () => {
|
||||
that.progress = audio.percent;
|
||||
that.updateLyric();
|
||||
};
|
||||
if (hasNewPlaylist || !fromAppStart) {
|
||||
if (that.videoMode) {
|
||||
} else {
|
||||
|
||||
@@ -52,73 +52,4 @@
|
||||
|
||||
.vidtoolimg {
|
||||
width: 62px;
|
||||
}
|
||||
|
||||
.fav-folder-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fav-folder-picker {
|
||||
width: 340px;
|
||||
height: 380px;
|
||||
background-color: #2a2a2a;
|
||||
border-radius: 16px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.fav-folder-picker-title {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.fav-folder-list {
|
||||
width: 100%;
|
||||
height: 260px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.fav-folder-item {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 10px 8px;
|
||||
margin-bottom: 4px;
|
||||
border-radius: 8px;
|
||||
background-color: #3a3a3a;
|
||||
}
|
||||
|
||||
.fav-folder-item-selected {
|
||||
background-color: #4a6fa5;
|
||||
}
|
||||
|
||||
.fav-folder-checkmark {
|
||||
font-size: 20px;
|
||||
color: #ffffff;
|
||||
margin-right: 10px;
|
||||
width: 28px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fav-folder-name {
|
||||
font-size: 18px;
|
||||
color: #ffffff;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.fav-folder-buttons {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
margin-top: 15px;
|
||||
}
|
||||
@@ -54,22 +54,6 @@
|
||||
</scroll>
|
||||
<full-screen-input style="position: absolute" if="{{replymode}}" @send="SendReply"
|
||||
@exit="ExitInput"></full-screen-input>
|
||||
<div class="fav-folder-overlay" if="{{favFolderPickerVisible}}">
|
||||
<div class="fav-folder-picker">
|
||||
<text class="fav-folder-picker-title">选择收藏夹</text>
|
||||
<scroll scroll-y="true" class="fav-folder-list">
|
||||
<div class="fav-folder-item {{folder.selected ? 'fav-folder-item-selected' : ''}}"
|
||||
for="folder in favFolders" @click="ToggleFolder(folder.id)">
|
||||
<text class="fav-folder-checkmark">{{folder.selected ? '✓' : '○'}}</text>
|
||||
<text class="fav-folder-name">{{folder.title}}</text>
|
||||
</div>
|
||||
</scroll>
|
||||
<div class="fav-folder-buttons">
|
||||
<default-button text="取消" @click="HideFavFolderPicker"></default-button>
|
||||
<default-button text="确认" @click="ConfirmAddToFav"></default-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -81,7 +65,7 @@ import {kmeansCircleGradientImage} from "@src/image/jpegkmeans.ts"
|
||||
|
||||
export default {
|
||||
public: {
|
||||
bvid: "" // 视频BVID
|
||||
bvid: 1 // 视频BVID
|
||||
},
|
||||
private: {
|
||||
vid: {},
|
||||
@@ -93,9 +77,7 @@ export default {
|
||||
starsrc: "/common/vidtool_star.png",
|
||||
replymode: false,
|
||||
renderingCover: false,
|
||||
scrclass: "",
|
||||
favFolderPickerVisible: false,
|
||||
favFolders: []
|
||||
scrclass: ""
|
||||
},
|
||||
computed: {
|
||||
stat_view() {
|
||||
@@ -199,7 +181,7 @@ export default {
|
||||
},
|
||||
async SendReply(evt) {
|
||||
this.replymode = false
|
||||
if (!evt.detail.content || evt.detail.content.length === 0) {
|
||||
if (evt.detail.content === 0) {
|
||||
return prompt.showToast({
|
||||
message: "评论内容不得为空!",
|
||||
duration: 2000
|
||||
@@ -238,83 +220,11 @@ export default {
|
||||
})
|
||||
},
|
||||
async AddToFav() {
|
||||
if (this.stared) {
|
||||
// 已收藏:从所有包含此视频的收藏夹中删除
|
||||
await this.ConfirmUnstarAll()
|
||||
} else {
|
||||
// 未收藏:弹出收藏夹选择窗口
|
||||
await this.ShowFavFolderPicker()
|
||||
}
|
||||
},
|
||||
async ShowFavFolderPicker() {
|
||||
try {
|
||||
var self = this
|
||||
var data = await global.biliclient.getUserFavouriteFoldersWithVideoState(
|
||||
global.biliclient.accountInfo.mid,
|
||||
this.vid.aid
|
||||
)
|
||||
var list = data.list || []
|
||||
this.favFolders = list.map(function(folder) {
|
||||
return {
|
||||
id: folder.id,
|
||||
title: folder.title,
|
||||
selected: folder.fav_state === 1
|
||||
}
|
||||
})
|
||||
this.favFolderPickerVisible = true
|
||||
} catch (e) {
|
||||
global.logger.error("获取收藏夹列表失败: ", e)
|
||||
prompt.showToast({message: "获取收藏夹列表失败,请重试"})
|
||||
}
|
||||
},
|
||||
HideFavFolderPicker() {
|
||||
this.favFolderPickerVisible = false
|
||||
},
|
||||
ToggleFolder(folderId) {
|
||||
this.favFolders = this.favFolders.map(function(f) {
|
||||
if (f.id === folderId) {
|
||||
return Object.assign({}, f, { selected: !f.selected })
|
||||
}
|
||||
return f
|
||||
})
|
||||
},
|
||||
async ConfirmAddToFav() {
|
||||
var selectedIds = this.favFolders
|
||||
.filter(function(f) { return f.selected })
|
||||
.map(function(f) { return f.id })
|
||||
this.favFolderPickerVisible = false
|
||||
if (selectedIds.length === 0) {
|
||||
prompt.showToast({message: "未选择任何收藏夹"})
|
||||
return
|
||||
}
|
||||
var result = await global.biliclient.starVideoToFavFolders(this.vid.aid, selectedIds)
|
||||
var message = result === 0 ? "收藏成功" : "收藏失败,请重试,或重新登录后再试"
|
||||
prompt.showToast({message: message})
|
||||
const result = await global.biliclient.starVideoToDefaultFavFolderByBVID(this.bvid)
|
||||
const message = result ? "收藏失败,请重试,或重新登录后再试" : "收藏成功"
|
||||
prompt.showToast({message})
|
||||
this.UpdateVideoToolbarStatus()
|
||||
},
|
||||
async ConfirmUnstarAll() {
|
||||
try {
|
||||
var data = await global.biliclient.getUserFavouriteFoldersWithVideoState(
|
||||
global.biliclient.accountInfo.mid,
|
||||
this.vid.aid
|
||||
)
|
||||
var list = data.list || []
|
||||
var staredFolderIds = list
|
||||
.filter(function(f) { return f.fav_state === 1 })
|
||||
.map(function(f) { return f.id })
|
||||
if (staredFolderIds.length === 0) {
|
||||
prompt.showToast({message: "该视频未被收藏"})
|
||||
return
|
||||
}
|
||||
var result = await global.biliclient.unstarVideoFromFavFolders(this.vid.aid, staredFolderIds)
|
||||
var message = result === 0 ? "取消收藏成功" : "取消收藏失败,请重试,或重新登录后再试"
|
||||
prompt.showToast({message: message})
|
||||
this.UpdateVideoToolbarStatus()
|
||||
} catch (e) {
|
||||
global.logger.error("取消收藏失败: ", e)
|
||||
prompt.showToast({message: "取消收藏失败,请重试"})
|
||||
}
|
||||
},
|
||||
async GenBlur(evt) {
|
||||
// 该Feature在现在任何设备上运行都会卡死,故注释
|
||||
/*
|
||||
|
||||
+1
-2
@@ -35,8 +35,7 @@ async function loadStorageIndex(): Promise<void> {
|
||||
const fileExists = await asyncFile.access({ uri: indexFileUri });
|
||||
if (fileExists) {
|
||||
const indexData = await asyncFile.readText({ uri: indexFileUri });
|
||||
const parsed = JSON.parse(indexData);
|
||||
storageIndex = Array.isArray(parsed) ? parsed : [];
|
||||
storageIndex = JSON.parse(indexData);
|
||||
} else {
|
||||
storageIndex = [];
|
||||
}
|
||||
|
||||
+5
-9
@@ -34,15 +34,11 @@ export function loadSettings(): void {
|
||||
key: 'settings',
|
||||
success: function (data) {
|
||||
if (data) {
|
||||
try {
|
||||
const storedSettings = JSON.parse(data);
|
||||
SETTINGS = {
|
||||
...SETTINGS,
|
||||
...storedSettings
|
||||
};
|
||||
} catch (e) {
|
||||
global.logger.warn('Failed to parse settings, using defaults:', e);
|
||||
}
|
||||
const storedSettings = JSON.parse(data);
|
||||
SETTINGS = {
|
||||
...SETTINGS,
|
||||
...storedSettings
|
||||
};
|
||||
}
|
||||
global.logger.log('Settings loaded:', SETTINGS);
|
||||
},
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { device, network, router } from "./tsimports"
|
||||
|
||||
export function formatNumber(num: number): string {
|
||||
if (num == null || isNaN(num)) return "0";
|
||||
if (num < 0) return "0";
|
||||
if (num < 1000) {
|
||||
return num.toString();
|
||||
}
|
||||
|
||||
+4
-9
@@ -18,7 +18,7 @@ function runVmPoolGC(){
|
||||
for(var name in global.vmPool){
|
||||
if(global.vmPool[name]){
|
||||
if(global.vmPool[name].$valid){
|
||||
continue
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,20 +46,15 @@ export function InitPage(vm){
|
||||
|
||||
export function OnBackPressTriggered(){
|
||||
GlobalActions.UpdateCurrentPageName()
|
||||
if (global.vmPool[global.currentPageName]) {
|
||||
global.vmPool[global.currentPageName].scrclass = "scroll-backanim"
|
||||
}
|
||||
global.vmPool[global.currentPageName].scrclass = "scroll-backanim"
|
||||
setTimeout(() => {
|
||||
GlobalActions.ClearCurrentVmSrcClass()
|
||||
router.back()
|
||||
|
||||
var pageStack = router.getPages()
|
||||
if (pageStack.length < 2) return
|
||||
var lastPageName = pageStack[pageStack.length - 2].name
|
||||
global.logger.log("lastpage=", lastPageName, "currentPage=", global.currentPageName)
|
||||
if (global.vmPool[lastPageName]) {
|
||||
global.vmPool[lastPageName].scrclass = ""
|
||||
global.vmPool[lastPageName].scrclass = "scroll-frombackanim"
|
||||
}
|
||||
global.vmPool[lastPageName].scrclass = ""
|
||||
global.vmPool[lastPageName].scrclass = "scroll-frombackanim"
|
||||
}, 150)
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import dayjs from "dayjs"
|
||||
import { fetch } from "./tsimports"
|
||||
|
||||
const TRACKER_URL: string = "https://tracker.hyperbili.astralsight.space/trackreport"
|
||||
// const TRACKER_URL: string = "http://192.168.1.247:4080/trackreport"
|
||||
//const TRACKER_URL: string = "https://tracker.hyperbili.astralsight.space/trackreport"
|
||||
const TRACKER_URL: string = "http://192.168.1.247:4080/trackreport"
|
||||
const TRACKER_SERVER_PROTOCOL_VERSION = "v1"
|
||||
|
||||
interface TrackedInfoUploadPacket {
|
||||
|
||||
Reference in New Issue
Block a user