mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-30 01:17:37 +03:00
Extract FileDiff component from FileCard
This commit is contained in:
parent
3e1a77e83a
commit
d838d39600
@ -18,7 +18,7 @@
|
||||
import { dropzone } from '$lib/dragging/dropzone';
|
||||
import { persisted } from '$lib/persisted/persisted';
|
||||
import { SETTINGS_CONTEXT, type SettingsStore } from '$lib/settings/userSettings';
|
||||
import { computedAddedRemoved } from '$lib/vbranches/fileStatus';
|
||||
import { computeAddedRemovedByFiles } from '$lib/utils/metrics';
|
||||
import { filesToOwnership, type Ownership } from '$lib/vbranches/ownership';
|
||||
import lscache from 'lscache';
|
||||
import { getContext, onMount } from 'svelte';
|
||||
@ -77,7 +77,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: linesTouched = computedAddedRemoved(...branch.files);
|
||||
$: linesTouched = computeAddedRemovedByFiles(...branch.files);
|
||||
$: if (
|
||||
branch.name.toLowerCase().includes('virtual branch') &&
|
||||
linesTouched.added + linesTouched.removed > 4
|
||||
|
@ -1,7 +1,5 @@
|
||||
<script lang="ts">
|
||||
import FileCardHeader from './FileCardHeader.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 { persisted } from '$lib/persisted/persisted';
|
||||
@ -15,6 +13,7 @@
|
||||
import type { Ownership } from '$lib/vbranches/ownership';
|
||||
import type { File } from '$lib/vbranches/types';
|
||||
import type { Writable } from 'svelte/store';
|
||||
import FileDiff from './FileDiff.svelte';
|
||||
|
||||
export let projectId: string;
|
||||
export let branchId: string;
|
||||
@ -59,23 +58,6 @@
|
||||
.filter((section): section is HunkSection => section instanceof HunkSection)
|
||||
.some((section) => section.hunk.locked);
|
||||
|
||||
function computedAddedRemoved(section: HunkSection | ContentSection): {
|
||||
added: any;
|
||||
removed: any;
|
||||
} {
|
||||
if (section instanceof HunkSection) {
|
||||
const lines = section.hunk.diff.split('\n');
|
||||
return {
|
||||
added: lines.filter((l) => l.startsWith('+')).length,
|
||||
removed: lines.filter((l) => l.startsWith('-')).length
|
||||
};
|
||||
}
|
||||
return {
|
||||
added: 0,
|
||||
removed: 0
|
||||
};
|
||||
}
|
||||
|
||||
fileWidth = lscache.get(fileWidthKey + file.id);
|
||||
</script>
|
||||
|
||||
@ -99,42 +81,16 @@
|
||||
{/if}
|
||||
|
||||
<ScrollableContainer wide>
|
||||
<div class="hunks">
|
||||
{#if file.binary}
|
||||
Binary content not shown
|
||||
{:else if file.large}
|
||||
Diff too large to be shown
|
||||
{:else}
|
||||
{#each sections as section}
|
||||
{@const { added, removed } = computedAddedRemoved(section)}
|
||||
{#if 'hunk' in section}
|
||||
<div class="hunk-wrapper">
|
||||
<div class="indicators text-base-11">
|
||||
<span class="added">+{added}</span>
|
||||
<span class="removed">+{removed}</span>
|
||||
{#if section.hunk.locked}
|
||||
<div title={section.hunk.lockedTo}>
|
||||
<Icon name="locked-small" color="warn" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<HunkViewer
|
||||
{file}
|
||||
{section}
|
||||
{branchId}
|
||||
{selectable}
|
||||
{isUnapplied}
|
||||
{projectPath}
|
||||
{selectedOwnership}
|
||||
{branchController}
|
||||
{isFileLocked}
|
||||
{minWidth}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
<FileDiff
|
||||
{file}
|
||||
{projectPath}
|
||||
{isFileLocked}
|
||||
{isUnapplied}
|
||||
{branchController}
|
||||
{selectable}
|
||||
{branchId}
|
||||
{selectedOwnership}
|
||||
/>
|
||||
</ScrollableContainer>
|
||||
</div>
|
||||
|
||||
|
@ -3,7 +3,8 @@
|
||||
import Tag from './Tag.svelte';
|
||||
import IconButton from '$lib/components/IconButton.svelte';
|
||||
import { getVSIFileIcon } from '$lib/ext-icons';
|
||||
import { computeFileStatus, computedAddedRemoved } from '$lib/vbranches/fileStatus';
|
||||
import { computeFileStatus } from '$lib/utils/fileStatus';
|
||||
import { computeAddedRemovedByFiles } from '$lib/utils/metrics';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import type { File } from '$lib/vbranches/types';
|
||||
|
||||
@ -11,7 +12,7 @@
|
||||
export let isFileLocked: boolean;
|
||||
|
||||
const dispatch = createEventDispatcher<{ close: void }>();
|
||||
$: fileStats = computedAddedRemoved(file);
|
||||
$: fileStats = computeAddedRemovedByFiles(file);
|
||||
$: fileStatus = computeFileStatus(file);
|
||||
|
||||
function boldenFilename(filepath: string): { filename: string; path: string } {
|
||||
|
57
gitbutler-ui/src/lib/components/FileDiff.svelte
Normal file
57
gitbutler-ui/src/lib/components/FileDiff.svelte
Normal file
@ -0,0 +1,57 @@
|
||||
<script lang="ts">
|
||||
import HunkViewer from './HunkViewer.svelte';
|
||||
import Icon from './Icon.svelte';
|
||||
import { computeAddedRemovedByFiles, computeAddedRemovedByHunk } from '$lib/utils/metrics';
|
||||
import type { HunkSection, ContentSection } 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 { Writable } from 'svelte/store';
|
||||
|
||||
export let branchId: string;
|
||||
export let file: File;
|
||||
export let sections: (HunkSection | ContentSection)[] = [];
|
||||
export let projectPath: string | undefined;
|
||||
export let branchController: BranchController;
|
||||
export let isUnapplied: boolean;
|
||||
export let selectable = false;
|
||||
export let selectedOwnership: Writable<Ownership>;
|
||||
export let isFileLocked: boolean;
|
||||
</script>
|
||||
|
||||
<div class="hunks">
|
||||
{#if file.binary}
|
||||
Binary content not shown
|
||||
{:else if file.large}
|
||||
Diff too large to be shown
|
||||
{:else}
|
||||
{#each sections as section}
|
||||
{@const { added, removed } = computeAddedRemovedByHunk(section)}
|
||||
{#if 'hunk' in section}
|
||||
<div class="hunk-wrapper">
|
||||
<div class="indicators text-base-11">
|
||||
<span class="added">+{added}</span>
|
||||
<span class="removed">+{removed}</span>
|
||||
{#if section.hunk.locked}
|
||||
<div title={section.hunk.lockedTo}>
|
||||
<Icon name="locked-small" color="warn" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<HunkViewer
|
||||
{file}
|
||||
{section}
|
||||
{branchId}
|
||||
{selectable}
|
||||
{isUnapplied}
|
||||
{projectPath}
|
||||
{selectedOwnership}
|
||||
{branchController}
|
||||
{isFileLocked}
|
||||
{minWidth}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { FileStatus } from '$lib/vbranches/fileStatus';
|
||||
import type { FileStatus } from '$lib/utils/fileStatus';
|
||||
|
||||
export let status: FileStatus;
|
||||
</script>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import FileStatusCircle from './FileStatusCircle.svelte';
|
||||
import Icon from '$lib/components/Icon.svelte';
|
||||
import { computeFileStatus } from '$lib/vbranches/fileStatus';
|
||||
import { computeFileStatus } from '$lib/utils/fileStatus';
|
||||
import type { File } from '$lib/vbranches/types';
|
||||
|
||||
export let file: File;
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import Tag, { type TagColor } from './Tag.svelte';
|
||||
import type { FileStatus } from '$lib/vbranches/fileStatus';
|
||||
import type { FileStatus } from '$lib/utils/fileStatus';
|
||||
|
||||
export let status: FileStatus;
|
||||
|
||||
|
15
gitbutler-ui/src/lib/utils/fileStatus.ts
Normal file
15
gitbutler-ui/src/lib/utils/fileStatus.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import type { File } from '$lib/vbranches/types';
|
||||
|
||||
export type FileStatus = 'A' | 'M' | 'D';
|
||||
|
||||
export function computeFileStatus(file: File): FileStatus {
|
||||
if (file.hunks.length == 1) {
|
||||
const changeType = file.hunks[0].changeType;
|
||||
if (changeType == 'added') {
|
||||
return 'A';
|
||||
} else if (changeType == 'deleted') {
|
||||
return 'D';
|
||||
}
|
||||
}
|
||||
return 'M';
|
||||
}
|
32
gitbutler-ui/src/lib/utils/metrics.ts
Normal file
32
gitbutler-ui/src/lib/utils/metrics.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { HunkSection, type ContentSection } from './fileSections';
|
||||
import type { File } from '$lib/vbranches/types';
|
||||
|
||||
export function computeAddedRemovedByFiles(...files: File[]) {
|
||||
return files
|
||||
.flatMap((f) => f.hunks)
|
||||
.map((h) => h.diff.split('\n'))
|
||||
.reduce(
|
||||
(acc, lines) => ({
|
||||
added: acc.added + lines.filter((l) => l.startsWith('+')).length,
|
||||
removed: acc.removed + lines.filter((l) => l.startsWith('-')).length
|
||||
}),
|
||||
{ added: 0, removed: 0 }
|
||||
);
|
||||
}
|
||||
|
||||
export function computeAddedRemovedByHunk(section: HunkSection | ContentSection): {
|
||||
added: any;
|
||||
removed: any;
|
||||
} {
|
||||
if (section instanceof HunkSection) {
|
||||
const lines = section.hunk.diff.split('\n');
|
||||
return {
|
||||
added: lines.filter((l) => l.startsWith('+')).length,
|
||||
removed: lines.filter((l) => l.startsWith('-')).length
|
||||
};
|
||||
}
|
||||
return {
|
||||
added: 0,
|
||||
removed: 0
|
||||
};
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
import type { File } from './types';
|
||||
|
||||
export type FileStatus = 'A' | 'M' | 'D';
|
||||
|
||||
export function computedAddedRemoved(...files: File[]) {
|
||||
return files
|
||||
.flatMap((f) => f.hunks)
|
||||
.map((h) => h.diff.split('\n'))
|
||||
.reduce(
|
||||
(acc, lines) => ({
|
||||
added: acc.added + lines.filter((l) => l.startsWith('+')).length,
|
||||
removed: acc.removed + lines.filter((l) => l.startsWith('-')).length
|
||||
}),
|
||||
{ added: 0, removed: 0 }
|
||||
);
|
||||
}
|
||||
|
||||
export function computeFileStatus(file: File): FileStatus {
|
||||
if (file.hunks.length == 1) {
|
||||
const changeType = file.hunks[0].changeType;
|
||||
if (changeType == 'added') {
|
||||
return 'A';
|
||||
} else if (changeType == 'deleted') {
|
||||
return 'D';
|
||||
}
|
||||
}
|
||||
return 'M';
|
||||
}
|
Loading…
Reference in New Issue
Block a user