mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2025-01-04 15:53:30 +03:00
Refactor hunk viewer (and break it out from FileCard)
- necessary for aligning commit diff viewer and branch diff viewer
This commit is contained in:
commit
4de440e444
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import RenderedLine from './RenderedLine.svelte';
|
||||
import HunkLine from './HunkLine.svelte';
|
||||
import { invoke } from '$lib/backend/ipc';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import Modal from '$lib/components/Modal.svelte';
|
||||
@ -141,7 +141,7 @@
|
||||
{#if 'hunk' in section}
|
||||
{#each section.subSections as subsection}
|
||||
{#each subsection.lines.slice(0, subsection.expanded ? subsection.lines.length : 0) as line}
|
||||
<RenderedLine
|
||||
<HunkLine
|
||||
{line}
|
||||
{minWidth}
|
||||
sectionType={subsection.sectionType}
|
||||
|
@ -1,22 +1,19 @@
|
||||
<script lang="ts">
|
||||
import FileCardHeader from './FileCardHeader.svelte';
|
||||
import HunkContextMenu from './HunkContextMenu.svelte';
|
||||
import RenderedLine from './RenderedLine.svelte';
|
||||
import HunkViewer from './HunkViewer.svelte';
|
||||
import Icon from '$lib/components/Icon.svelte';
|
||||
import Resizer from '$lib/components/Resizer.svelte';
|
||||
import ScrollableContainer from '$lib/components/ScrollableContainer.svelte';
|
||||
import { draggable } from '$lib/dragging/draggable';
|
||||
import { draggableHunk } from '$lib/dragging/draggables';
|
||||
import { persisted } from '$lib/persisted/persisted';
|
||||
import { SETTINGS_CONTEXT, type SettingsStore } from '$lib/settings/userSettings';
|
||||
import { ContentSection, HunkSection, parseFileSections } from '$lib/utils/fileSections';
|
||||
import lscache from 'lscache';
|
||||
import { onDestroy, getContext } from 'svelte';
|
||||
import { getContext } from 'svelte';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
import { slide } from 'svelte/transition';
|
||||
import type { BranchController } from '$lib/vbranches/branchController';
|
||||
import type { Ownership } from '$lib/vbranches/ownership';
|
||||
import type { File, Hunk } from '$lib/vbranches/types';
|
||||
import type { File } from '$lib/vbranches/types';
|
||||
import type { Writable } from 'svelte/store';
|
||||
|
||||
export let projectId: string;
|
||||
@ -37,16 +34,6 @@
|
||||
|
||||
const userSettings = getContext<SettingsStore>(SETTINGS_CONTEXT);
|
||||
|
||||
function updateContextMenu(file: File) {
|
||||
if (popupMenu) popupMenu.$destroy();
|
||||
return new HunkContextMenu({
|
||||
target: document.body,
|
||||
props: { projectPath, file, branchController }
|
||||
});
|
||||
}
|
||||
|
||||
$: popupMenu = updateContextMenu(file);
|
||||
|
||||
let sections: (HunkSection | ContentSection)[] = [];
|
||||
|
||||
function parseFile(file: File) {
|
||||
@ -72,20 +59,6 @@
|
||||
.filter((section): section is HunkSection => section instanceof HunkSection)
|
||||
.some((section) => section.hunk.locked);
|
||||
|
||||
function onHunkSelected(hunk: Hunk, isSelected: boolean) {
|
||||
if (isSelected) {
|
||||
selectedOwnership.update((ownership) => ownership.addHunk(hunk.filePath, hunk.id));
|
||||
} else {
|
||||
selectedOwnership.update((ownership) => ownership.removeHunk(hunk.filePath, hunk.id));
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy(() => {
|
||||
if (popupMenu) {
|
||||
popupMenu.$destroy();
|
||||
}
|
||||
});
|
||||
|
||||
function computedAddedRemoved(section: HunkSection | ContentSection): {
|
||||
added: any;
|
||||
removed: any;
|
||||
@ -145,44 +118,18 @@
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div
|
||||
tabindex="0"
|
||||
role="cell"
|
||||
use:draggable={{
|
||||
...draggableHunk(branchId, section.hunk),
|
||||
disabled: isUnapplied || section.hunk.locked
|
||||
}}
|
||||
on:dblclick
|
||||
class="hunk"
|
||||
class:opacity-60={section.hunk.locked && !isFileLocked}
|
||||
>
|
||||
<div class="hunk__inner custom-scrollbar">
|
||||
<div class="hunk__inner_inner">
|
||||
{#each section.subSections as subsection}
|
||||
{@const hunk = section.hunk}
|
||||
{#each subsection.lines.slice(0, subsection.expanded ? subsection.lines.length : 0) as line}
|
||||
<RenderedLine
|
||||
{line}
|
||||
{minWidth}
|
||||
{selectable}
|
||||
selected={$selectedOwnership.containsHunk(hunk.filePath, hunk.id)}
|
||||
on:selected={(e) => onHunkSelected(hunk, e.detail)}
|
||||
sectionType={subsection.sectionType}
|
||||
filePath={file.path}
|
||||
on:contextmenu={(e) =>
|
||||
popupMenu.openByMouse(e, {
|
||||
hunk,
|
||||
section: subsection,
|
||||
lineNumber: line.afterLineNumber
|
||||
? line.afterLineNumber
|
||||
: line.beforeLineNumber
|
||||
})}
|
||||
/>
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<HunkViewer
|
||||
{file}
|
||||
{section}
|
||||
{branchId}
|
||||
{selectable}
|
||||
{isUnapplied}
|
||||
{projectPath}
|
||||
{selectedOwnership}
|
||||
{branchController}
|
||||
{isFileLocked}
|
||||
{minWidth}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
@ -259,35 +206,6 @@
|
||||
flex-direction: column;
|
||||
gap: var(--space-10);
|
||||
}
|
||||
.hunk {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-x: hidden;
|
||||
&:focus-within {
|
||||
& .hunk__inner {
|
||||
overflow-x: auto;
|
||||
border-color: var(--clr-theme-container-outline-pale);
|
||||
}
|
||||
}
|
||||
}
|
||||
.hunk__inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: var(--clr-theme-container-light);
|
||||
border-radius: var(--radius-s);
|
||||
border: 1px solid var(--clr-theme-container-outline-light);
|
||||
overflow-x: hidden;
|
||||
transition: border-color var(--transition-fast);
|
||||
user-select: text;
|
||||
}
|
||||
.hunk__inner_inner {
|
||||
/* TODO: Rename this class */
|
||||
width: 100%;
|
||||
min-width: max-content;
|
||||
user-select: text !important;
|
||||
cursor: grab;
|
||||
}
|
||||
.indicators {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -58,7 +58,7 @@
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="line flex-grow overflow-hidden whitespace-pre pl-0.5"
|
||||
class="line"
|
||||
class:diff-line-deletion={sectionType === SectionType.RemovedLines}
|
||||
class:diff-line-addition={sectionType === SectionType.AddedLines}
|
||||
>
|
||||
@ -75,6 +75,12 @@
|
||||
min-width: max-content;
|
||||
font-family: monospace;
|
||||
background-color: var(----clr-theme-container-light);
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.line {
|
||||
flex-grow: 1;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.code-line__numbers-line {
|
||||
@ -86,5 +92,6 @@
|
||||
.selectable-wrapper {
|
||||
cursor: text;
|
||||
display: inline-block;
|
||||
padding-left: var(--space-4);
|
||||
}
|
||||
</style>
|
104
gitbutler-ui/src/lib/components/HunkViewer.svelte
Normal file
104
gitbutler-ui/src/lib/components/HunkViewer.svelte
Normal file
@ -0,0 +1,104 @@
|
||||
<script lang="ts">
|
||||
import HunkContextMenu from './HunkContextMenu.svelte';
|
||||
import HunkLine from './HunkLine.svelte';
|
||||
import { draggable } from '$lib/dragging/draggable';
|
||||
import { draggableHunk } from '$lib/dragging/draggables';
|
||||
import { onDestroy } from 'svelte';
|
||||
import type { HunkSection } from '$lib/utils/fileSections';
|
||||
import type { BranchController } from '$lib/vbranches/branchController';
|
||||
import type { Ownership } from '$lib/vbranches/ownership';
|
||||
import type { File } from '$lib/vbranches/types';
|
||||
import type { Hunk } from '$lib/vbranches/types';
|
||||
import type { Writable } from 'svelte/store';
|
||||
|
||||
export let file: File;
|
||||
export let section: HunkSection;
|
||||
export let branchId: string;
|
||||
export let projectPath: string | undefined;
|
||||
|
||||
export let minWidth: number;
|
||||
export let selectable = false;
|
||||
export let isUnapplied: boolean;
|
||||
export let isFileLocked: boolean;
|
||||
|
||||
export let branchController: BranchController;
|
||||
export let selectedOwnership: Writable<Ownership>;
|
||||
|
||||
function onHunkSelected(hunk: Hunk, isSelected: boolean) {
|
||||
if (isSelected) {
|
||||
selectedOwnership.update((ownership) => ownership.addHunk(hunk.filePath, hunk.id));
|
||||
} else {
|
||||
selectedOwnership.update((ownership) => ownership.removeHunk(hunk.filePath, hunk.id));
|
||||
}
|
||||
}
|
||||
|
||||
function updateContextMenu(file: File) {
|
||||
if (popupMenu) popupMenu.$destroy();
|
||||
return new HunkContextMenu({
|
||||
target: document.body,
|
||||
props: { projectPath, file, branchController }
|
||||
});
|
||||
}
|
||||
|
||||
$: popupMenu = updateContextMenu(file);
|
||||
|
||||
onDestroy(() => {
|
||||
if (popupMenu) {
|
||||
popupMenu.$destroy();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div
|
||||
tabindex="0"
|
||||
role="cell"
|
||||
use:draggable={{
|
||||
...draggableHunk(branchId, section.hunk),
|
||||
disabled: isUnapplied || section.hunk.locked
|
||||
}}
|
||||
on:contextmenu|preventDefault
|
||||
class="hunk"
|
||||
class:opacity-60={section.hunk.locked && !isFileLocked}
|
||||
>
|
||||
<div class="hunk__bg-stretch">
|
||||
{#each section.subSections as subsection}
|
||||
{@const hunk = section.hunk}
|
||||
{#each subsection.lines.slice(0, subsection.expanded ? subsection.lines.length : 0) as line}
|
||||
<HunkLine
|
||||
{line}
|
||||
{minWidth}
|
||||
{selectable}
|
||||
selected={$selectedOwnership.containsHunk(hunk.filePath, hunk.id)}
|
||||
on:selected={(e) => onHunkSelected(hunk, e.detail)}
|
||||
sectionType={subsection.sectionType}
|
||||
filePath={file.path}
|
||||
on:contextmenu={(e) =>
|
||||
popupMenu.openByMouse(e, {
|
||||
hunk,
|
||||
section: subsection,
|
||||
lineNumber: line.afterLineNumber ? line.afterLineNumber : line.beforeLineNumber
|
||||
})}
|
||||
/>
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.hunk {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-x: auto;
|
||||
cursor: grab;
|
||||
|
||||
background: var(--clr-theme-container-light);
|
||||
border-radius: var(--radius-s);
|
||||
border: 1px solid var(--clr-theme-container-outline-light);
|
||||
transition: border-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.hunk__bg-stretch {
|
||||
width: 100%;
|
||||
min-width: max-content;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user