mirror of
https://github.com/olcubo/obsidian-cubox.git
synced 2026-07-22 05:43:25 +00:00
rebuild api
This commit is contained in:
parent
0b09074719
commit
5d1a864635
3 changed files with 254 additions and 169 deletions
111
src/cuboxApi.ts
111
src/cuboxApi.ts
|
|
@ -64,20 +64,18 @@ interface FoldersResponse {
|
|||
|
||||
export class CuboxApi {
|
||||
private endpoint: string;
|
||||
private apiKey: string;
|
||||
|
||||
constructor(options: CuboxApiOptions) {
|
||||
this.endpoint = `https://${options.domain}`;
|
||||
this.apiKey = options.apiKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试 API 连接是否有效
|
||||
*/
|
||||
async testConnection(): Promise<boolean> {
|
||||
async testConnection(apiKey: string): Promise<boolean> {
|
||||
try {
|
||||
// 尝试获取一篇文章来测试连接
|
||||
// const result = await this.getArticles(1, 1);
|
||||
const result = await this.getArticles(apiKey, { lastCardId: null, pageSize: 1 });
|
||||
new Notice('测试 Cubox 连接成功');
|
||||
return true;
|
||||
} catch (error) {
|
||||
|
|
@ -87,10 +85,10 @@ export class CuboxApi {
|
|||
}
|
||||
}
|
||||
|
||||
private async request(path: string, options: RequestInit = {}) {
|
||||
private async request(path: string, apiKey: string, options: RequestInit = {}) {
|
||||
const url = `${this.endpoint}${path}`;
|
||||
const headers = {
|
||||
'Authorization': `Bearer ${this.apiKey}`,
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
|
|
@ -111,63 +109,65 @@ export class CuboxApi {
|
|||
|
||||
/**
|
||||
* 获取文章列表
|
||||
* @param folderFilter 文件夹过滤数组
|
||||
* @param typeFilter 类型过滤
|
||||
* @param statusFilter 状态过滤 'all' | 'read' | 'starred' | 'annotated'
|
||||
* @param lastCardId 上一页最后一篇文章的ID
|
||||
* @param apiKey API密钥
|
||||
* @param params 请求参数
|
||||
*/
|
||||
async getArticles(
|
||||
folderFilter: string[],
|
||||
typeFilter: string[],
|
||||
statusFilter: string[],
|
||||
lastCardId: string | null = null
|
||||
): Promise<{ articles: any[], hasMore: boolean, lastCardId: string | null }> {
|
||||
apiKey: string,
|
||||
params: {
|
||||
lastCardId: string | null;
|
||||
pageSize?: number;
|
||||
folderFilter?: string[];
|
||||
typeFilter?: string[];
|
||||
statusFilter?: string[];
|
||||
} = { lastCardId: null }
|
||||
): Promise<{ articles: CuboxArticle[], hasMore: boolean, lastCardId: string | null }> {
|
||||
try {
|
||||
// 构建请求参数
|
||||
const params: any = {
|
||||
limit: 20,
|
||||
};
|
||||
const searchParams = new URLSearchParams();
|
||||
const pageSize = params.pageSize || 50;
|
||||
|
||||
if (params.lastCardId !== null && params.lastCardId.length > 0) {
|
||||
searchParams.append('lastCardId', params.lastCardId);
|
||||
}
|
||||
searchParams.append('pageSize', pageSize.toString());
|
||||
|
||||
// 添加文件夹过滤
|
||||
if (folderFilter && folderFilter.length > 0) {
|
||||
params.folder_id = folderFilter;
|
||||
if (params.folderFilter && params.folderFilter.length > 0) {
|
||||
params.folderFilter.forEach(folder => {
|
||||
searchParams.append('folderId', folder);
|
||||
});
|
||||
}
|
||||
|
||||
// 添加类型过滤
|
||||
if (typeFilter && typeFilter.length > 0) {
|
||||
params.type = typeFilter;
|
||||
if (params.typeFilter && params.typeFilter.length > 0) {
|
||||
params.typeFilter.forEach(type => {
|
||||
searchParams.append('type', type);
|
||||
});
|
||||
}
|
||||
|
||||
// 添加状态过滤 - 修改为支持多选
|
||||
if (statusFilter && statusFilter.length > 0) {
|
||||
// 添加状态过滤
|
||||
if (params.statusFilter && params.statusFilter.length > 0) {
|
||||
// 如果包含 'all',则不添加状态过滤
|
||||
if (!statusFilter.includes('all')) {
|
||||
// 处理多个状态过滤
|
||||
if (statusFilter.includes('read')) params.is_read = true;
|
||||
if (statusFilter.includes('starred')) params.is_starred = true;
|
||||
if (statusFilter.includes('archived')) params.is_archived = true;
|
||||
if (statusFilter.includes('annotated')) params.is_annotated = true;
|
||||
if (!params.statusFilter.includes('all')) {
|
||||
if (params.statusFilter.includes('read')) searchParams.append('isRead', 'true');
|
||||
if (params.statusFilter.includes('starred')) searchParams.append('isStarred', 'true');
|
||||
if (params.statusFilter.includes('archived')) searchParams.append('isArchived', 'true');
|
||||
if (params.statusFilter.includes('annotated')) searchParams.append('isAnnotated', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
const path = `/c/api/third-party/card/list?${searchParams.toString()}`;
|
||||
const response = await this.request(path, apiKey) as ListResponse;
|
||||
|
||||
// 添加分页参数
|
||||
if (lastCardId) {
|
||||
params.last_id = lastCardId;
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
const response = await this.request('/v2/article/list', params);
|
||||
|
||||
// 处理响应
|
||||
if (response && response.data) {
|
||||
return {
|
||||
articles: response.data.data || [],
|
||||
hasMore: response.data.has_more || false,
|
||||
lastCardId: response.data.last_id || null
|
||||
};
|
||||
}
|
||||
|
||||
return { articles: [], hasMore: false, lastCardId: null };
|
||||
const articles = response.data.list;
|
||||
const hasMore = articles.length >= pageSize;
|
||||
const lastCardId = articles.length > 0 ? articles[articles.length - 1].cardId : null;
|
||||
|
||||
return {
|
||||
articles,
|
||||
hasMore,
|
||||
lastCardId
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取文章列表失败:', error);
|
||||
throw error;
|
||||
|
|
@ -176,12 +176,13 @@ export class CuboxApi {
|
|||
|
||||
/**
|
||||
* 获取文章详情,包括内容
|
||||
* @param apiKey API密钥
|
||||
* @param articleId 文章ID
|
||||
*/
|
||||
async getArticleDetail(articleId: string): Promise<string | null> {
|
||||
async getArticleDetail(apiKey: string, articleId: string): Promise<string | null> {
|
||||
try {
|
||||
const path = `/c/api/third-party/card/content?cardId=${articleId}`;
|
||||
const response = await this.request(path) as ContentResponse;
|
||||
const response = await this.request(path, apiKey) as ContentResponse;
|
||||
|
||||
// 直接返回文章内容
|
||||
return response.data;
|
||||
|
|
@ -194,9 +195,10 @@ export class CuboxApi {
|
|||
|
||||
/**
|
||||
* 获取文章的高亮内容
|
||||
* @param apiKey API密钥
|
||||
* @param articleId 文章ID
|
||||
*/
|
||||
async getHighlights(articleId: string): Promise<CuboxHighlight[]> {
|
||||
async getHighlights(apiKey: string, articleId: string): Promise<CuboxHighlight[]> {
|
||||
try {
|
||||
// 这里需要实现获取高亮的API调用
|
||||
// 暂时返回空数组
|
||||
|
|
@ -210,11 +212,12 @@ export class CuboxApi {
|
|||
|
||||
/**
|
||||
* 获取用户的文件夹列表
|
||||
* @param apiKey API密钥
|
||||
*/
|
||||
async getFolders(): Promise<CuboxFolder[]> {
|
||||
async getFolders(apiKey: string): Promise<CuboxFolder[]> {
|
||||
try {
|
||||
const path = '/c/api/third-party/folder/list';
|
||||
const response = await this.request(path) as FoldersResponse;
|
||||
const response = await this.request(path, apiKey) as FoldersResponse;
|
||||
|
||||
return response.data.list.map(folder => ({
|
||||
...folder,
|
||||
|
|
|
|||
59
src/main.ts
59
src/main.ts
|
|
@ -155,7 +155,7 @@ export default class CuboxSyncPlugin extends Plugin {
|
|||
statusBarItemEl.setText(`正在同步 Cubox...`);
|
||||
|
||||
// 检查 API 连接
|
||||
const isConnected = await this.cuboxApi.testConnection();
|
||||
const isConnected = await this.cuboxApi.testConnection(this.settings.apiKey);
|
||||
if (!isConnected) {
|
||||
this.settings.syncing = false;
|
||||
await this.saveSettings();
|
||||
|
|
@ -175,10 +175,13 @@ export default class CuboxSyncPlugin extends Plugin {
|
|||
while (hasMore) {
|
||||
// 获取文章列表
|
||||
const result = await this.cuboxApi.getArticles(
|
||||
this.settings.folderFilter,
|
||||
this.settings.typeFilter,
|
||||
this.settings.statusFilter,
|
||||
lastCardId
|
||||
this.settings.apiKey,
|
||||
{
|
||||
lastCardId: lastCardId,
|
||||
folderFilter: this.settings.folderFilter,
|
||||
typeFilter: this.settings.typeFilter,
|
||||
statusFilter: this.settings.statusFilter
|
||||
}
|
||||
);
|
||||
|
||||
const { articles, hasMore: moreArticles, lastCardId: newLastCardId } = result;
|
||||
|
|
@ -190,11 +193,11 @@ export default class CuboxSyncPlugin extends Plugin {
|
|||
// 处理每篇文章
|
||||
for (const article of articles) {
|
||||
// 获取文章详情和高亮
|
||||
const content = await this.cuboxApi.getArticleDetail(article.cardId);
|
||||
const content = await this.cuboxApi.getArticleDetail(this.settings.apiKey, article.cardId);
|
||||
if (content === null) continue;
|
||||
|
||||
// 获取高亮内容
|
||||
const highlights = await this.cuboxApi.getHighlights(article.cardId);
|
||||
const highlights = await this.cuboxApi.getHighlights(this.settings.apiKey, article.cardId);
|
||||
|
||||
// 合并文章基本信息、内容和高亮
|
||||
const fullArticle = {
|
||||
|
|
@ -379,19 +382,29 @@ class CuboxSyncSettingTab extends PluginSettingTab {
|
|||
// 显示加载状态
|
||||
button.setButtonText('Loading folders...');
|
||||
|
||||
// 打开文件夹选择模态框
|
||||
const modal = new FolderSelectModal(
|
||||
this.app,
|
||||
this.plugin.cuboxApi,
|
||||
this.plugin.settings.folderFilter,
|
||||
async (selectedFolders) => {
|
||||
this.plugin.settings.folderFilter = selectedFolders;
|
||||
await this.plugin.saveSettings();
|
||||
// 更新按钮文本
|
||||
button.setButtonText(this.getFolderFilterButtonText());
|
||||
}
|
||||
);
|
||||
modal.open();
|
||||
try {
|
||||
// 先获取文件夹数据
|
||||
const folders = await this.plugin.cuboxApi.getFolders(this.plugin.settings.apiKey);
|
||||
|
||||
// 打开文件夹选择模态框,传入已获取的文件夹数据
|
||||
const modal = new FolderSelectModal(
|
||||
this.app,
|
||||
folders, // 直接传入获取到的文件夹数据
|
||||
this.plugin.settings.folderFilter,
|
||||
async (selectedFolders) => {
|
||||
this.plugin.settings.folderFilter = selectedFolders;
|
||||
await this.plugin.saveSettings();
|
||||
// 更新按钮文本
|
||||
button.setButtonText(this.getFolderFilterButtonText());
|
||||
}
|
||||
);
|
||||
modal.open();
|
||||
} catch (error) {
|
||||
console.error('获取文件夹列表失败:', error);
|
||||
new Notice('获取文件夹列表失败,请检查网络连接和 API Key');
|
||||
// 恢复按钮文本
|
||||
button.setButtonText(this.getFolderFilterButtonText());
|
||||
}
|
||||
}));
|
||||
|
||||
new Setting(containerEl)
|
||||
|
|
@ -453,7 +466,7 @@ class CuboxSyncSettingTab extends PluginSettingTab {
|
|||
|
||||
new Setting(containerEl)
|
||||
.setName('Sync Interval')
|
||||
.setDesc('Auto sync interval (in minutes). 0 means manual sync. Each item syncs only once. Subsequent updates won’t be synced, and modifications in Obsidian won’t affect Cubox. We recommend avoiding frequent updates.')
|
||||
.setDesc('Auto sync interval (in minutes). 0 means manual sync. Each item syncs only once. Subsequent updates won\'t be synced, and modifications in Obsidian won\'t affect Cubox. We recommend avoiding frequent updates.')
|
||||
.addText(text => text
|
||||
.setPlaceholder('Enter sync frequency in minutes')
|
||||
.setValue(String(this.plugin.settings.syncFrequency))
|
||||
|
|
@ -465,7 +478,7 @@ class CuboxSyncSettingTab extends PluginSettingTab {
|
|||
|
||||
new Setting(containerEl)
|
||||
.setName('Folder')
|
||||
.setDesc('Select the folder you’d like to sync to')
|
||||
.setDesc('Select the folder you\'d like to sync to')
|
||||
.addText(text => text
|
||||
.setPlaceholder('Enter target folder path')
|
||||
.setValue(this.plugin.settings.targetFolder)
|
||||
|
|
@ -569,7 +582,7 @@ class CuboxSyncSettingTab extends PluginSettingTab {
|
|||
.addButton(button => button
|
||||
.setButtonText('Test')
|
||||
.onClick(async () => {
|
||||
await this.plugin.cuboxApi.testConnection();
|
||||
await this.plugin.cuboxApi.testConnection(this.plugin.settings.apiKey);
|
||||
}));
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,23 @@
|
|||
import { App, Modal, Setting, Notice } from 'obsidian';
|
||||
import { CuboxApi, CuboxFolder } from '../cuboxApi';
|
||||
|
||||
// 定义一个虚拟的 ALL 文件夹 ID
|
||||
const ALL_FOLDERS_ID = 'all_folders';
|
||||
|
||||
export class FolderSelectModal extends Modal {
|
||||
private cuboxApi: CuboxApi;
|
||||
private selectedFolders: string[];
|
||||
private onConfirm: (selectedFolders: string[]) => void;
|
||||
private folders: CuboxFolder[] = [];
|
||||
private loading: boolean = true;
|
||||
private cuboxApi: CuboxApi;
|
||||
|
||||
constructor(
|
||||
app: App,
|
||||
cuboxApi: CuboxApi,
|
||||
folders: CuboxFolder[],
|
||||
initialSelectedFolders: string[],
|
||||
onConfirm: (selectedFolders: string[]) => void
|
||||
) {
|
||||
super(app);
|
||||
this.cuboxApi = cuboxApi;
|
||||
this.folders = folders;
|
||||
this.selectedFolders = [...initialSelectedFolders];
|
||||
this.onConfirm = onConfirm;
|
||||
}
|
||||
|
|
@ -24,102 +26,169 @@ export class FolderSelectModal extends Modal {
|
|||
const { contentEl } = this;
|
||||
|
||||
// 设置标题
|
||||
contentEl.createEl('h2', { text: '选择要同步的文件夹' });
|
||||
contentEl.createEl('h2', { text: 'Manage Cubox folders to be synced' });
|
||||
|
||||
// 添加说明
|
||||
contentEl.createEl('p', {
|
||||
text: '选择要从 Cubox 同步的文件夹。不选择任何文件夹将同步所有内容。'
|
||||
});
|
||||
// 创建文件夹列表
|
||||
const folderListEl = contentEl.createEl('div', { cls: 'folder-list' });
|
||||
|
||||
// 添加加载指示器
|
||||
const loadingEl = contentEl.createEl('div', { text: '正在加载文件夹...' });
|
||||
|
||||
try {
|
||||
// 获取文件夹列表
|
||||
this.folders = await this.cuboxApi.getFolders();
|
||||
this.loading = false;
|
||||
|
||||
// 移除加载指示器
|
||||
loadingEl.remove();
|
||||
|
||||
// 创建文件夹列表
|
||||
const folderListEl = contentEl.createEl('div', { cls: 'folder-list' });
|
||||
|
||||
// 添加"全部"选项
|
||||
new Setting(folderListEl)
|
||||
.setName('全部文件夹')
|
||||
.setDesc('同步所有文件夹的内容')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.selectedFolders.length === 0)
|
||||
// 添加"All Items"选项
|
||||
const allFoldersSetting = new Setting(folderListEl)
|
||||
.setName('All Items')
|
||||
.addToggle(toggle => {
|
||||
// 初始化状态:如果selectedFolders为空或包含ALL_FOLDERS_ID,则选中
|
||||
const isAllSelected = this.selectedFolders.length === 0 ||
|
||||
this.selectedFolders.includes(ALL_FOLDERS_ID);
|
||||
|
||||
toggle
|
||||
.setValue(isAllSelected)
|
||||
.onChange(value => {
|
||||
if (value) {
|
||||
// 如果选择"全部",清空已选文件夹
|
||||
this.selectedFolders = [];
|
||||
// 更新所有其他切换按钮
|
||||
folderListEl.querySelectorAll('.folder-toggle').forEach((el: HTMLElement) => {
|
||||
if (el.hasClass('is-enabled')) {
|
||||
// @ts-ignore
|
||||
el.click();
|
||||
}
|
||||
});
|
||||
// 如果选择"All Items",清空已选文件夹,只保留ALL_FOLDERS_ID
|
||||
this.selectedFolders = [ALL_FOLDERS_ID];
|
||||
|
||||
// 更新所有其他切换按钮为选中状态
|
||||
this.updateAllFolderToggles(folderListEl, true);
|
||||
} else {
|
||||
// 从选中列表移除ALL_FOLDERS_ID
|
||||
this.selectedFolders = this.selectedFolders.filter(id => id !== ALL_FOLDERS_ID);
|
||||
|
||||
// 如果没有其他选中的文件夹,默认选中第一个
|
||||
if (this.selectedFolders.length === 0 && this.folders.length > 0) {
|
||||
this.selectedFolders.push(this.folders[0].id);
|
||||
this.updateFolderToggle(folderListEl, this.folders[0].id, true);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// 添加每个文件夹的选项
|
||||
this.folders.forEach(folder => {
|
||||
new Setting(folderListEl)
|
||||
.setName(folder.nested_name)
|
||||
.addToggle(toggle => {
|
||||
toggle
|
||||
.setValue(this.selectedFolders.includes(folder.id))
|
||||
.onChange(value => {
|
||||
if (value) {
|
||||
// 添加到选中列表
|
||||
this.selectedFolders.push(folder.id);
|
||||
// 如果有选择具体文件夹,取消"全部"选项
|
||||
const allToggle = folderListEl.querySelector('.setting:first-child .toggle');
|
||||
if (allToggle && allToggle.hasClass('is-enabled')) {
|
||||
// @ts-ignore
|
||||
allToggle.click();
|
||||
}
|
||||
} else {
|
||||
// 从选中列表移除
|
||||
this.selectedFolders = this.selectedFolders.filter(id => id !== folder.id);
|
||||
}
|
||||
});
|
||||
|
||||
// 添加类名以便于选择
|
||||
toggle.toggleEl.addClass('folder-toggle');
|
||||
|
||||
return toggle;
|
||||
});
|
||||
|
||||
// 添加类名以便于选择
|
||||
toggle.toggleEl.addClass('all-folders-toggle');
|
||||
|
||||
return toggle;
|
||||
});
|
||||
|
||||
// 添加确认和取消按钮
|
||||
const buttonContainer = contentEl.createEl('div', { cls: 'button-container' });
|
||||
|
||||
buttonContainer.createEl('button', { text: '取消' })
|
||||
.addEventListener('click', () => {
|
||||
this.close();
|
||||
});
|
||||
|
||||
buttonContainer.createEl('button', { text: '确认', cls: 'mod-cta' })
|
||||
.addEventListener('click', () => {
|
||||
this.onConfirm(this.selectedFolders);
|
||||
this.close();
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取文件夹列表失败:', error);
|
||||
loadingEl.setText('获取文件夹列表失败,请检查网络连接');
|
||||
|
||||
// 添加重试按钮
|
||||
contentEl.createEl('button', { text: '重试' })
|
||||
.addEventListener('click', () => {
|
||||
this.close();
|
||||
new FolderSelectModal(this.app, this.cuboxApi, this.selectedFolders, this.onConfirm).open();
|
||||
|
||||
// 添加每个文件夹的选项
|
||||
this.folders.forEach(folder => {
|
||||
new Setting(folderListEl)
|
||||
.setName(folder.nested_name)
|
||||
.addToggle(toggle => {
|
||||
// 初始化状态:如果selectedFolders为空或包含ALL_FOLDERS_ID,则所有文件夹都选中
|
||||
const isSelected = this.selectedFolders.length === 0 ||
|
||||
this.selectedFolders.includes(ALL_FOLDERS_ID) ||
|
||||
this.selectedFolders.includes(folder.id);
|
||||
|
||||
toggle
|
||||
.setValue(isSelected)
|
||||
.onChange(value => {
|
||||
if (value) {
|
||||
// 添加到选中列表
|
||||
if (!this.selectedFolders.includes(folder.id)) {
|
||||
this.selectedFolders.push(folder.id);
|
||||
}
|
||||
|
||||
// 检查是否所有文件夹都被选中,如果是,自动选中"All Items"
|
||||
if (this.areAllFoldersSelected()) {
|
||||
if (!this.selectedFolders.includes(ALL_FOLDERS_ID)) {
|
||||
this.selectedFolders.push(ALL_FOLDERS_ID);
|
||||
}
|
||||
this.updateAllFoldersToggle(folderListEl, true);
|
||||
}
|
||||
} else {
|
||||
// 从选中列表移除
|
||||
this.selectedFolders = this.selectedFolders.filter(id => id !== folder.id);
|
||||
|
||||
// 如果取消选中任何文件夹,取消"All Items"选项
|
||||
if (this.selectedFolders.includes(ALL_FOLDERS_ID)) {
|
||||
this.selectedFolders = this.selectedFolders.filter(id => id !== ALL_FOLDERS_ID);
|
||||
this.updateAllFoldersToggle(folderListEl, false);
|
||||
}
|
||||
|
||||
// 如果没有选中的文件夹,默认选中"All Items"
|
||||
if (this.selectedFolders.length === 0) {
|
||||
this.selectedFolders.push(ALL_FOLDERS_ID);
|
||||
this.updateAllFoldersToggle(folderListEl, true);
|
||||
this.updateAllFolderToggles(folderListEl, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 添加类名以便于选择
|
||||
toggle.toggleEl.addClass('folder-toggle');
|
||||
toggle.toggleEl.setAttribute('data-folder-id', folder.id);
|
||||
|
||||
return toggle;
|
||||
});
|
||||
});
|
||||
|
||||
// 添加确认和取消按钮
|
||||
const buttonContainer = contentEl.createEl('div', { cls: 'button-container' });
|
||||
|
||||
buttonContainer.createEl('button', { text: '取消' })
|
||||
.addEventListener('click', () => {
|
||||
this.close();
|
||||
});
|
||||
|
||||
buttonContainer.createEl('button', { text: '确认', cls: 'mod-cta' })
|
||||
.addEventListener('click', () => {
|
||||
// 如果选中了ALL_FOLDERS_ID,则传递空数组表示同步所有内容
|
||||
const resultFolders = this.selectedFolders.includes(ALL_FOLDERS_ID)
|
||||
? []
|
||||
: this.selectedFolders;
|
||||
|
||||
this.onConfirm(resultFolders);
|
||||
this.close();
|
||||
});
|
||||
}
|
||||
|
||||
// 检查是否所有文件夹都被选中
|
||||
private areAllFoldersSelected(): boolean {
|
||||
// 如果没有文件夹,返回false
|
||||
if (this.folders.length === 0) return false;
|
||||
|
||||
// 检查每个文件夹是否都在selectedFolders中
|
||||
return this.folders.every(folder => this.selectedFolders.includes(folder.id));
|
||||
}
|
||||
|
||||
// 更新"All Items"切换按钮的状态
|
||||
private updateAllFoldersToggle(containerEl: HTMLElement, value: boolean): void {
|
||||
const allToggle = containerEl.querySelector('.all-folders-toggle') as HTMLElement;
|
||||
if (allToggle) {
|
||||
const isEnabled = allToggle.hasClass('is-enabled');
|
||||
if (value && !isEnabled) {
|
||||
// @ts-ignore
|
||||
allToggle.click();
|
||||
} else if (!value && isEnabled) {
|
||||
// @ts-ignore
|
||||
allToggle.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新所有文件夹切换按钮的状态
|
||||
private updateAllFolderToggles(containerEl: HTMLElement, value: boolean): void {
|
||||
containerEl.querySelectorAll('.folder-toggle').forEach((el: HTMLElement) => {
|
||||
const isEnabled = el.hasClass('is-enabled');
|
||||
if (value && !isEnabled) {
|
||||
// @ts-ignore
|
||||
el.click();
|
||||
} else if (!value && isEnabled) {
|
||||
// @ts-ignore
|
||||
el.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 更新特定文件夹切换按钮的状态
|
||||
private updateFolderToggle(containerEl: HTMLElement, folderId: string, value: boolean): void {
|
||||
const folderToggle = containerEl.querySelector(`.folder-toggle[data-folder-id="${folderId}"]`) as HTMLElement;
|
||||
if (folderToggle) {
|
||||
const isEnabled = folderToggle.hasClass('is-enabled');
|
||||
if (value && !isEnabled) {
|
||||
// @ts-ignore
|
||||
folderToggle.click();
|
||||
} else if (!value && isEnabled) {
|
||||
// @ts-ignore
|
||||
folderToggle.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue