Files
note2any/src/preview-manager.ts
2025-10-21 21:47:02 +08:00

386 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 文件preview-manager.ts
* 作用:预览管理器,负责协调所有平台预览组件
*
* 职责:
* 1. 创建和管理所有子组件platform-chooser, wechat-preview, xhs-preview
* 2. 处理平台切换逻辑(唯一入口)
* 3. 管理文章渲染和状态同步
* 4. 提供统一的对外接口
*
* 设计模式:
* - 中介者模式Mediator: 协调各组件交互
* - 外观模式Facade: 提供简单的对外接口
*/
import { TFile, Notice, App } from 'obsidian';
import { PlatformType } from './platform-chooser';
import { WechatPreview } from './wechat/wechat-preview';
import { XiaohongshuPreview } from './xiaohongshu/xhs-preview';
import { ArticleRender } from './article-render';
import { NMPSettings } from './settings';
export class PreviewManager {
private container: HTMLElement;
private app: App;
private render: ArticleRender;
private settings: NMPSettings;
// 子组件
private wechatPreview: WechatPreview | null = null;
private xhsPreview: XiaohongshuPreview | null = null;
// UI 容器
private mainDiv: HTMLDivElement | null = null;
private wechatContainer: HTMLDivElement | null = null;
private xhsContainer: HTMLDivElement | null = null;
// 默认平台
private currentPlatform: PlatformType = 'wechat';
private currentFile: TFile | null = null;
constructor(container: HTMLElement, app: App, render: ArticleRender) {
this.container = container;
this.app = app;
this.render = render;
this.settings = NMPSettings.getInstance();
}
/**
* 构建界面(主入口)
*/
async build(): Promise<void> {
console.log('[PreviewManager] 开始构建界面');
// 清空容器
this.container.empty();
// 创建主容器
this.mainDiv = this.container.createDiv({ cls: 'note-preview' });
// 1. 创建并构建微信预览
this.createWechatPreview();
// 2. 创建并构建小红书预览
this.createXiaohongshuPreview();
// 3. 初始显示公众号平台
await this.switchPlatform('wechat');
console.log('[PreviewManager] 界面构建完成');
}
/**
* 创建微信预览组件
*/
private createWechatPreview(): void {
if (!this.mainDiv) return;
// 创建微信预览容器
this.wechatContainer = this.mainDiv.createDiv({ cls: 'wechat-preview-container' });
// 创建微信预览实例
this.wechatPreview = new WechatPreview(
this.wechatContainer,
this.app,
this.render
);
// 设置回调函数
this.wechatPreview.onRefreshCallback = async () => {
await this.refresh();
};
this.wechatPreview.onAppIdChangeCallback = (appId: string) => {
console.log(`[PreviewManager] 公众号切换: ${appId}`);
// 可以在这里处理公众号切换的额外逻辑
};
this.wechatPreview.onPlatformChangeCallback = (platform: string) => {
this.switchPlatform(platform as PlatformType);
};
// 构建 UI
this.wechatPreview.build();
}
private async publishCurrentPlatform(): Promise<void> {
if (this.currentPlatform === 'wechat') {
if (!this.wechatPreview) {
new Notice('微信预览未初始化');
return;
}
await this.wechatPreview.publish();
} else if (this.currentPlatform === 'xiaohongshu') {
if (!this.xhsPreview) {
new Notice('小红书预览未初始化');
return;
}
await this.xhsPreview.publish();
}
}
/**
* 创建小红书预览组件
*/
private createXiaohongshuPreview(): void {
if (!this.mainDiv) return;
// 创建小红书预览容器
this.xhsContainer = this.mainDiv.createDiv({ cls: 'xiaohongshu-preview-container' });
// 创建小红书预览实例
this.xhsPreview = new XiaohongshuPreview(this.xhsContainer, this.app);
// 设置回调函数
this.xhsPreview.onRefreshCallback = async () => {
await this.refresh();
};
this.xhsPreview.onPublishCallback = async () => {
await this.publishToXiaohongshu();
};
this.xhsPreview.onPlatformChangeCallback = async (platform: string) => {
if (platform === 'wechat') {
await this.switchPlatform('wechat');
}
};
// 构建 UI
this.xhsPreview.build();
}
/**
* 平台切换的唯一入口
*/
// 平台切换:公开以便外部(例如上下文菜单)调用
async switchPlatform(platform: PlatformType): Promise<void> {
console.log(`[PreviewManager] 平台切换: ${this.currentPlatform}${platform}`);
const previousPlatform = this.currentPlatform;
this.currentPlatform = platform;
if (platform === 'wechat') {
// 显示微信,隐藏小红书
this.showWechat();
this.hideXiaohongshu();
// 同步主题设置
if (this.wechatPreview) {
this.wechatPreview.updateStyleAndHighlight(
this.settings.defaultStyle,
this.settings.defaultHighlight
);
}
// 如果有当前文件且是从其他平台切换过来,重新渲染
if (this.currentFile && previousPlatform !== 'wechat') {
await this.renderForWechat(this.currentFile);
}
} else if (platform === 'xiaohongshu') {
// 显示小红书,隐藏微信
this.showXiaohongshu();
this.hideWechat();
// 同步主题设置
if (this.xhsPreview) {
this.xhsPreview.updateStyleAndHighlight(
this.settings.defaultStyle,
this.settings.defaultHighlight
);
}
// 如果有当前文件且是从其他平台切换过来,重新渲染
if (this.currentFile && previousPlatform !== 'xiaohongshu') {
await this.renderForXiaohongshu(this.currentFile);
}
}
}
/**
* 显示微信预览
*/
private showWechat(): void {
if (this.wechatContainer) {
this.wechatContainer.style.display = 'flex';
}
if (this.wechatPreview) {
this.wechatPreview.show();
}
}
/**
* 隐藏微信预览
*/
private hideWechat(): void {
if (this.wechatContainer) {
this.wechatContainer.style.display = 'none';
}
if (this.wechatPreview) {
this.wechatPreview.hide();
}
}
/**
* 显示小红书预览
*/
private showXiaohongshu(): void {
if (this.xhsContainer) {
this.xhsContainer.style.display = 'flex';
}
if (this.xhsPreview) {
this.xhsPreview.show();
}
}
/**
* 隐藏小红书预览
*/
private hideXiaohongshu(): void {
if (this.xhsContainer) {
this.xhsContainer.style.display = 'none';
}
if (this.xhsPreview) {
this.xhsPreview.hide();
}
}
/**
* 设置当前文件(对外接口)
*/
async setFile(file: TFile | null): Promise<void> {
if (!file) {
this.currentFile = null;
this.wechatPreview?.setFile(null);
return;
}
// 只处理 Markdown 文件
if (file.extension.toLowerCase() !== 'md') {
return;
}
console.log(`[PreviewManager] 设置文件: ${file.path}`);
this.currentFile = file;
this.wechatPreview?.setFile(file);
// 根据当前平台渲染
if (this.currentPlatform === 'wechat') {
await this.renderForWechat(file);
} else if (this.currentPlatform === 'xiaohongshu') {
await this.renderForXiaohongshu(file);
}
}
/**
* 刷新预览(对外接口)
*/
async refresh(): Promise<void> {
if (!this.currentFile) {
new Notice('请先打开一个笔记文件');
return;
}
console.log(`[PreviewManager] 刷新预览: ${this.currentFile.path}`);
await this.setFile(this.currentFile);
}
/**
* 渲染微信预览
*/
private async renderForWechat(file: TFile): Promise<void> {
try {
console.log(`[PreviewManager] 渲染微信预览: ${file.path}`);
// 使用 ArticleRender 渲染 Markdown
await this.render.renderMarkdown(file);
// 确保预览持有当前文件引用
this.wechatPreview?.setFile(file);
// 微信预览已经通过 ArticleRender 更新了
// 这里可以添加额外的微信特定逻辑
console.log('[PreviewManager] 微信预览渲染完成');
} catch (error) {
console.error('[PreviewManager] 渲染微信预览失败:', error);
new Notice('渲染失败: ' + (error instanceof Error ? error.message : String(error)));
}
}
/**
* 渲染小红书预览
*/
private async renderForXiaohongshu(file: TFile): Promise<void> {
try {
console.log(`[PreviewManager] 渲染小红书预览: ${file.path}`);
// 使用 ArticleRender 渲染 Markdown
await this.render.renderMarkdown(file);
const articleHTML = this.render.articleHTML;
if (articleHTML && this.xhsPreview) {
// 渲染到小红书预览
await this.xhsPreview.renderArticle(articleHTML, file);
console.log('[PreviewManager] 小红书预览渲染完成');
} else {
console.warn('[PreviewManager] 没有可渲染的内容');
}
} catch (error) {
console.error('[PreviewManager] 渲染小红书预览失败:', error);
new Notice('渲染失败: ' + (error instanceof Error ? error.message : String(error)));
}
}
/**
* 发布到小红书
*/
private async publishToXiaohongshu(): Promise<void> {
console.log('[PreviewManager] 发布到小红书');
// 这里实现发布逻辑
// 可以调用 xhsPreview 的相关方法
new Notice('发布功能开发中...');
}
/**
* 获取当前平台
*/
getCurrentPlatform(): PlatformType {
return this.currentPlatform;
}
/**
* 获取当前文件
*/
getCurrentFile(): TFile | null {
return this.currentFile;
}
/**
* 清理资源
*/
destroy(): void {
console.log('[PreviewManager] 清理资源');
if (this.wechatPreview) {
this.wechatPreview.destroy();
this.wechatPreview = null;
}
if (this.xhsPreview) {
this.xhsPreview.destroy();
this.xhsPreview = null;
}
this.mainDiv = null;
this.wechatContainer = null;
this.xhsContainer = null;
this.currentFile = null;
}
/** 获取微信预览实例(发布操作需要) */
getWechatPreview(): WechatPreview | null { return this.wechatPreview; }
}