pref: optimize the diff to make it more accurately reflect changes (#11)
* pref: optimize the diff to make it more accurately reflect changes * pref: optimize the diff page selection
This commit is contained in:
@@ -3,7 +3,8 @@ import { atom, computed, type MapStore, map, type WritableAtom } from 'nanostore
|
||||
import { type EditorBridge, type EventPayload, editorBridge } from '~/.client/bridge';
|
||||
import { computePageModifications, diffPages } from '~/.client/utils/diff';
|
||||
import { isValidContent } from '~/.client/utils/html-parse';
|
||||
import type { Page, PageHistory } from '~/types/actions';
|
||||
import { normalizeContent } from '~/.client/utils/prettier';
|
||||
import type { ChangeSource, Page, PageHistory } from '~/types/actions';
|
||||
import type { PageMap, PageSection, SectionMap } from '~/types/pages';
|
||||
import { createScopedLogger } from '~/utils/logger';
|
||||
|
||||
@@ -156,69 +157,67 @@ export class PagesStore {
|
||||
this.modifiedPages.clear();
|
||||
}
|
||||
|
||||
async savePage(pageName: string, content: string) {
|
||||
async savePage(pageName: string, content: string, changeSource: ChangeSource) {
|
||||
const page = this.getPage(pageName);
|
||||
if (!page) {
|
||||
return false;
|
||||
}
|
||||
// 保存上一次的页面内容
|
||||
this.savePageHistory(pageName, content);
|
||||
try {
|
||||
this.pages.setKey(pageName, { ...page, content });
|
||||
logger.info('Page updated');
|
||||
// 保存上一次的页面内容
|
||||
this.savePageHistory(pageName, content, changeSource);
|
||||
} catch (error) {
|
||||
logger.error('Failed to update page content\n\n', error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async savePageHistory(pageName: string, newContent: string) {
|
||||
async savePageHistory(pageName: string, newContent: string, changeSource: ChangeSource) {
|
||||
const page = this.getPage(pageName);
|
||||
if (!page) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pageHistory = this.pageHistory.get()[pageName];
|
||||
// 如果不存在历史记录,则创建一个新的历史记录
|
||||
const normalizedCurrentContent = newContent?.replace(/\r\n/g, '\n').trim();
|
||||
const originalContent = pageHistory?.originalContent || page.content!;
|
||||
if (!pageHistory) {
|
||||
const newHistory: PageHistory = {
|
||||
originalContent: newContent,
|
||||
latestVersion: 1,
|
||||
latestModified: Date.now(),
|
||||
versions: [
|
||||
{
|
||||
version: 1,
|
||||
timestamp: Date.now(),
|
||||
content: newContent,
|
||||
changeSource,
|
||||
},
|
||||
],
|
||||
};
|
||||
this.pageHistory.setKey(pageName, newHistory);
|
||||
return;
|
||||
}
|
||||
|
||||
const lastVersion = pageHistory.versions.find((version) => version.version === pageHistory.latestVersion);
|
||||
if (!lastVersion) {
|
||||
return;
|
||||
}
|
||||
// 如果存在历史记录,则检查自上次版本以来是否有实际变化
|
||||
const originalContent = lastVersion?.content || page.content!;
|
||||
if (!originalContent) {
|
||||
return;
|
||||
}
|
||||
const normalizedOriginalContent = (pageHistory?.originalContent || page.content!).replace(/\r\n/g, '\n').trim();
|
||||
if (!pageHistory) {
|
||||
if (normalizedCurrentContent !== normalizedOriginalContent) {
|
||||
const newChanges = diffLines(page.content!, newContent);
|
||||
const newHistory: PageHistory = {
|
||||
originalContent: page.content!,
|
||||
lastModified: Date.now(),
|
||||
changes: newChanges,
|
||||
versions: [
|
||||
{
|
||||
timestamp: Date.now(),
|
||||
content: newContent,
|
||||
},
|
||||
],
|
||||
changeSource: 'auto-save',
|
||||
};
|
||||
this.pageHistory.setKey(pageName, newHistory);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果存在历史记录,则检查自上次版本以来是否有实际变化
|
||||
const lastVersion = pageHistory.versions[pageHistory.versions.length - 1];
|
||||
const normalizedLastContent = lastVersion?.content.replace(/\r\n/g, '\n').trim();
|
||||
const normalizedCurrentContent = normalizeContent(newContent);
|
||||
const normalizedLastContent = normalizeContent(lastVersion?.content);
|
||||
if (normalizedCurrentContent === normalizedLastContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unifiedDiff = diffPages(pageName, pageHistory.originalContent, newContent);
|
||||
const unifiedDiff = diffPages(pageName, lastVersion.content, newContent);
|
||||
if (!unifiedDiff) {
|
||||
return;
|
||||
}
|
||||
const newChanges = diffLines(pageHistory.originalContent, newContent);
|
||||
const newChanges = diffLines(lastVersion.content, newContent);
|
||||
|
||||
// 检查是否有显著变化
|
||||
const hasSignificantChanges = newChanges.some(
|
||||
@@ -230,16 +229,17 @@ export class PagesStore {
|
||||
|
||||
const newHistory: PageHistory = {
|
||||
originalContent: pageHistory.originalContent,
|
||||
lastModified: Date.now(),
|
||||
changes: [...pageHistory.changes, ...newChanges].slice(-100), // Limitar histórico de mudanças
|
||||
latestVersion: pageHistory.latestVersion + 1,
|
||||
latestModified: Date.now(),
|
||||
versions: [
|
||||
...pageHistory.versions,
|
||||
{
|
||||
version: pageHistory.latestVersion + 1,
|
||||
timestamp: Date.now(),
|
||||
content: newContent,
|
||||
changeSource,
|
||||
},
|
||||
].slice(-10), // 只保留最近的 10 个版本
|
||||
changeSource: 'auto-save',
|
||||
].slice(-20), // 只保留最近的 20 个版本
|
||||
};
|
||||
|
||||
this.pageHistory.setKey(pageName, newHistory);
|
||||
|
||||
@@ -4,7 +4,7 @@ import JSZip from 'jszip';
|
||||
import { atom, type WritableAtom } from 'nanostores';
|
||||
import { toast } from 'sonner';
|
||||
import { formatFile } from '~/.client/utils/prettier';
|
||||
import type { Page } from '~/types/actions';
|
||||
import type { ChangeSource, Page } from '~/types/actions';
|
||||
import type { PageMap } from '~/types/pages';
|
||||
import { base64ToBinary, getContentType, getExtensionFromMimeType, getFileName } from '~/utils/file-utils';
|
||||
import { createScopedLogger } from '~/utils/logger';
|
||||
@@ -66,11 +66,16 @@ export class WebBuilderStore {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动设置页面数据,通常用于初始化页面数据。
|
||||
* @param pages 页面数据
|
||||
*/
|
||||
setPages(pages: PageMap) {
|
||||
this.editorStore.setDocuments(pages, true);
|
||||
for (const [pageName, page] of Object.entries(pages)) {
|
||||
if (page) {
|
||||
this.pagesStore.setPage(pageName, page);
|
||||
this.pagesStore.savePageHistory(pageName, page.content as string, 'initial');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,27 +126,14 @@ export class WebBuilderStore {
|
||||
this.editorStore.updateDocumentContent(pageName, _html);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行保存,将 editorStore 中的当前页面内容同步保存至 PagesStore 中。
|
||||
* @returns
|
||||
*/
|
||||
async saveCurrentDocument() {
|
||||
const currentPage = this.editorStore.currentDocument.get();
|
||||
if (!currentPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.saveDocument(currentPage.name as string);
|
||||
}
|
||||
|
||||
async saveDocument(pageName: string) {
|
||||
async saveDocument(pageName: string, changeSource: ChangeSource) {
|
||||
const documents = this.editorStore.editorDocuments.get();
|
||||
const pageProperties = documents[pageName];
|
||||
if (pageProperties === undefined) {
|
||||
return;
|
||||
}
|
||||
// 触发 page 的保存
|
||||
this.pagesStore.savePage(pageName, pageProperties.content as string).then(() => {
|
||||
this.pagesStore.savePage(pageName, pageProperties.content as string, changeSource).then(() => {
|
||||
this.editorStore.removeUnsavedDocument(pageName, true);
|
||||
});
|
||||
}
|
||||
@@ -164,9 +156,9 @@ export class WebBuilderStore {
|
||||
this.editorStore.updateDocumentContent(pageName as string, page.content as string);
|
||||
}
|
||||
|
||||
async saveAllPages() {
|
||||
async saveAllPages(changeSource: ChangeSource) {
|
||||
for (const pageName of this.editorStore.unsavedDocuments.get()) {
|
||||
await this.saveDocument(pageName);
|
||||
await this.saveDocument(pageName, changeSource);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user