386 lines
11 KiB
TypeScript
386 lines
11 KiB
TypeScript
/**
|
||
* 文件: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; }
|
||
}
|