文件
mynode/packages/lib/services/conflict/loadConflictData.ts
chen 301194963b
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
feat: Initial clean release of CHM
2026-11-04 11:29:39 +08:00

68 行
2.1 KiB
TypeScript

import Note from '../../models/Note';
import ConflictNoteState from '../../models/ConflictNoteState';
import { autoMerge, MergedSection, twoWayDiff } from './diffNotes';
import { viewerDiffOptions } from './boundedDiff3';
import isConflictResolutionEnabled from './isConflictResolutionEnabled';
export enum ConflictDataStatus {
Ok = 'ok',
// No three-way data for this note (no state row, or it is still encrypted or
// locked), so show the read-only conflict view
Unavailable = 'unavailable',
}
export interface ConflictData {
status: ConflictDataStatus;
sections: MergedSection[];
localTitle: string;
remoteTitle: string;
titleConflict: boolean;
}
const unavailable = (): ConflictData => {
return {
status: ConflictDataStatus.Unavailable,
sections: [],
localTitle: '',
remoteTitle: '',
titleConflict: false,
};
};
// Sections are recomputed on each call because they were never stored.
export default async (noteId: string): Promise<ConflictData> => {
if (!isConflictResolutionEnabled()) return unavailable();
const note = await Note.load(noteId);
if (!note) return unavailable();
// No readable body to diff against yet - decryption re-saves the note, so the
// merge can be recomputed then.
if (note.encryption_applied || note.is_locked) return unavailable();
const state = await ConflictNoteState.byNoteId(noteId);
if (!state) return unavailable();
// The remote version stays as the original note.
const remoteNote = note.conflict_original_id ? await Note.load(note.conflict_original_id) : null;
if (!remoteNote) return unavailable();
if (remoteNote.encryption_applied || remoteNote.is_locked) return unavailable();
const localBody = note.body ?? '';
const remoteBody = remoteNote.body ?? '';
const baseBody = state.base_body ?? '';
const merged = baseBody ? autoMerge(baseBody, localBody, remoteBody, viewerDiffOptions) : twoWayDiff(localBody, remoteBody);
const localTitle = note.title ?? '';
const remoteTitle = remoteNote.title ?? '';
return {
status: ConflictDataStatus.Ok,
sections: merged.sections,
localTitle,
remoteTitle,
titleConflict: localTitle !== remoteTitle,
};
};