Restructure diff view to get ready for mobile view

This commit is contained in:
Silvano Cerza 2025-03-01 18:31:39 +01:00
parent f72ce44504
commit f5ed38f341
2 changed files with 120 additions and 103 deletions

View file

@ -0,0 +1,113 @@
import * as React from "react";
import { ConflictFile, ConflictResolution } from "src/sync-manager";
import SplitDiffView from "./split-diff-view";
import FilesTabBar from "./files-tab-bar";
const DesktopApp = ({
initialFiles,
onResolveAllConflicts,
}: {
initialFiles: ConflictFile[];
onResolveAllConflicts: (resolutions: ConflictResolution[]) => void;
}) => {
const [files, setFiles] = React.useState(initialFiles);
const [resolvedConflicts, setResolvedConflicts] = React.useState<
ConflictResolution[]
>([]);
const [currentFileIndex, setCurrentFileIndex] = React.useState(0);
const currentFile = files.at(currentFileIndex);
const onConflictResolved = () => {
// Remove the file from the conflicts to resolve
const remainingFiles = files.filter(
(_, index) => index !== currentFileIndex,
);
setFiles(remainingFiles);
// Keep track of the resolved conflicts
const newResolvedConflicts = [
...resolvedConflicts,
{
filePath: currentFile!.filePath,
content: currentFile!.localContent,
},
];
setResolvedConflicts(newResolvedConflicts);
// Select the previous file only if we're not already at the start
if (currentFileIndex > 0) {
setCurrentFileIndex(currentFileIndex - 1);
}
if (remainingFiles.length === 0) {
// We solved all conflicts, we can resume syncing
onResolveAllConflicts(newResolvedConflicts);
}
};
return (
<React.StrictMode>
<div
style={{
height: "100%",
display: "flex",
flexDirection: "column",
justifyContent: "center",
}}
>
{files.length === 0 ? (
<div
style={{
position: "relative",
textAlign: "center",
alignSelf: "center",
}}
>
<div
style={{
margin: "20px 0",
fontWeight: "var(--h2-weight)",
fontSize: "var(--h2-size)",
lineHeight: "var(--line-height-tight)",
}}
>
No conflicts to resolve
</div>
<div
style={{
margin: "20px 0",
fontSize: "var(--font-text-size)",
color: "var(--text-muted)",
lineHeight: "var(--line-height-tight)",
}}
>
That's good, keep going
</div>
</div>
) : (
<>
<FilesTabBar
files={files.map((f) => f.filePath)}
currentFile={currentFile?.filePath || ""}
setCurrentFileIndex={setCurrentFileIndex}
/>
<SplitDiffView
oldText={currentFile?.remoteContent || ""}
newText={currentFile?.localContent || ""}
onOldTextChange={(content: string) => {
const tempFiles = [...files];
tempFiles[currentFileIndex].remoteContent = content;
setFiles(tempFiles);
}}
onNewTextChange={(content: string) => {
const tempFiles = [...files];
tempFiles[currentFileIndex].localContent = content;
setFiles(tempFiles);
}}
onConflictResolved={onConflictResolved}
/>
</>
)}
</div>
</React.StrictMode>
);
};
export default DesktopApp;

View file

@ -1,10 +1,8 @@
import { IconName, ItemView, Menu, WorkspaceLeaf } from "obsidian";
import { Root, createRoot } from "react-dom/client";
import SplitDiffView from "./split-diff-view";
import GitHubSyncPlugin from "src/main";
import * as React from "react";
import FilesTabBar from "./files-tab-bar";
import { ConflictFile, ConflictResolution } from "src/sync-manager";
import DesktopApp from "./desktop-app";
export const CONFLICTS_RESOLUTION_VIEW_TYPE = "conflicts-resolution-view";
@ -54,107 +52,13 @@ export class ConflictsResolutionView extends ItemView {
(container as HTMLElement).style.padding = "0";
this.root = createRoot(container);
}
const App = ({ initialFiles }: { initialFiles: ConflictFile[] }) => {
const [files, setFiles] = React.useState(initialFiles);
const [resolvedConflicts, setResolvedConflicts] = React.useState<
ConflictResolution[]
>([]);
const [currentFileIndex, setCurrentFileIndex] = React.useState(0);
const currentFile = files.at(currentFileIndex);
const onConflictResolved = () => {
// Remove the file from the conflicts to resolve
const remainingFiles = files.filter(
(_, index) => index !== currentFileIndex,
);
setFiles(remainingFiles);
// Keep track of the resolved conflicts
const newResolvedConflicts = [
...resolvedConflicts,
{
filePath: currentFile!.filePath,
content: currentFile!.localContent,
},
];
setResolvedConflicts(newResolvedConflicts);
// Select the previous file only if we're not already at the start
if (currentFileIndex > 0) {
setCurrentFileIndex(currentFileIndex - 1);
}
if (remainingFiles.length === 0) {
// We solved all conflicts, we can resume syncing
this.resolveAllConflicts(newResolvedConflicts);
}
};
return (
<React.StrictMode>
<div
style={{
height: "100%",
display: "flex",
flexDirection: "column",
justifyContent: "center",
}}
>
{files.length === 0 ? (
<div
style={{
position: "relative",
textAlign: "center",
alignSelf: "center",
}}
>
<div
style={{
margin: "20px 0",
fontWeight: "var(--h2-weight)",
fontSize: "var(--h2-size)",
lineHeight: "var(--line-height-tight)",
}}
>
No conflicts to resolve
</div>
<div
style={{
margin: "20px 0",
fontSize: "var(--font-text-size)",
color: "var(--text-muted)",
lineHeight: "var(--line-height-tight)",
}}
>
That's good, keep going
</div>
</div>
) : (
<>
<FilesTabBar
files={files.map((f) => f.filePath)}
currentFile={currentFile?.filePath || ""}
setCurrentFileIndex={setCurrentFileIndex}
/>
<SplitDiffView
oldText={currentFile?.remoteContent || ""}
newText={currentFile?.localContent || ""}
onOldTextChange={(content: string) => {
const tempFiles = [...files];
tempFiles[currentFileIndex].remoteContent = content;
setFiles(tempFiles);
}}
onNewTextChange={(content: string) => {
const tempFiles = [...files];
tempFiles[currentFileIndex].localContent = content;
setFiles(tempFiles);
}}
onConflictResolved={onConflictResolved}
/>
</>
)}
</div>
</React.StrictMode>
);
};
this.root.render(<App initialFiles={conflicts} />);
this.root.render(
<DesktopApp
initialFiles={conflicts}
onResolveAllConflicts={this.resolveAllConflicts.bind(this)}
/>,
);
}
async onClose() {