mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-30 20:09:50 +03:00
lane style updates
This commit is contained in:
parent
7f0434cbb1
commit
db309df701
@ -205,9 +205,10 @@
|
||||
flex-shrink: 1;
|
||||
align-items: flex-start;
|
||||
height: 100%;
|
||||
padding: 0 var(--space-8);
|
||||
/* padding: 0 var(--space-8); */
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -142,143 +142,164 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div bind:this={rsViewport} class="branch-card resize-viewport" data-tauri-drag-region>
|
||||
<ScrollableContainer>
|
||||
<div style:width={`${laneWidth || $defaultBranchWidthRem}rem`} class="branch-card__contents">
|
||||
<BranchHeader
|
||||
{readonly}
|
||||
{branchController}
|
||||
{branch}
|
||||
{base}
|
||||
{githubService}
|
||||
projectId={project.id}
|
||||
on:action={(e) => {
|
||||
if (e.detail == 'generate-branch-name') {
|
||||
generateBranchName();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<!-- DROPZONES -->
|
||||
<div class="branch-card" data-tauri-drag-region class:target-branch={branch.selectedForChanges}>
|
||||
<div
|
||||
bind:this={rsViewport}
|
||||
style:width={`${laneWidth || $defaultBranchWidthRem}rem`}
|
||||
class="branch-card__contents"
|
||||
class:first-child={branch.order == 0}
|
||||
>
|
||||
<BranchHeader
|
||||
{readonly}
|
||||
{branchController}
|
||||
{branch}
|
||||
{base}
|
||||
{githubService}
|
||||
projectId={project.id}
|
||||
on:action={(e) => {
|
||||
if (e.detail == 'generate-branch-name') {
|
||||
generateBranchName();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<!-- DROPZONES -->
|
||||
<DropzoneOverlay class="cherrypick-dz-marker" label="Apply here" />
|
||||
<DropzoneOverlay class="lane-dz-marker" label="Move here" />
|
||||
|
||||
<div
|
||||
class="branch-card__dropzone-wrapper"
|
||||
use:dropzone={{
|
||||
hover: 'cherrypick-dz-hover',
|
||||
active: 'cherrypick-dz-active',
|
||||
accepts: acceptCherrypick,
|
||||
onDrop: onCherrypicked
|
||||
}}
|
||||
use:dropzone={{
|
||||
hover: 'lane-dz-hover',
|
||||
active: 'lane-dz-active',
|
||||
accepts: acceptBranchDrop,
|
||||
onDrop: onBranchDrop
|
||||
}}
|
||||
>
|
||||
<DropzoneOverlay class="cherrypick-dz-marker" label="Apply here" />
|
||||
<DropzoneOverlay class="lane-dz-marker" label="Move here" />
|
||||
|
||||
<div
|
||||
class="branch-card__dropzone-wrapper"
|
||||
use:dropzone={{
|
||||
hover: 'cherrypick-dz-hover',
|
||||
active: 'cherrypick-dz-active',
|
||||
accepts: acceptCherrypick,
|
||||
onDrop: onCherrypicked
|
||||
}}
|
||||
use:dropzone={{
|
||||
hover: 'lane-dz-hover',
|
||||
active: 'lane-dz-active',
|
||||
accepts: acceptBranchDrop,
|
||||
onDrop: onBranchDrop
|
||||
}}
|
||||
>
|
||||
<DropzoneOverlay class="cherrypick-dz-marker" label="Apply here" />
|
||||
<DropzoneOverlay class="lane-dz-marker" label="Move here" />
|
||||
{#if branch.files?.length > 0}
|
||||
<div class="card">
|
||||
<BranchFiles
|
||||
{#if branch.files?.length > 0}
|
||||
<div class="card">
|
||||
<BranchFiles
|
||||
{branch}
|
||||
{readonly}
|
||||
{selectedOwnership}
|
||||
{selectedFiles}
|
||||
showCheckboxes={$commitBoxOpen}
|
||||
/>
|
||||
{#if branch.active}
|
||||
<CommitDialog
|
||||
projectId={project.id}
|
||||
{branchController}
|
||||
{branch}
|
||||
{readonly}
|
||||
{cloud}
|
||||
{selectedOwnership}
|
||||
{selectedFiles}
|
||||
showCheckboxes={$commitBoxOpen}
|
||||
{user}
|
||||
bind:expanded={commitBoxOpen}
|
||||
on:action={(e) => {
|
||||
if (e.detail == 'generate-branch-name') {
|
||||
generateBranchName();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{#if branch.active}
|
||||
<CommitDialog
|
||||
projectId={project.id}
|
||||
{branchController}
|
||||
{branch}
|
||||
{cloud}
|
||||
{selectedOwnership}
|
||||
{user}
|
||||
bind:expanded={commitBoxOpen}
|
||||
on:action={(e) => {
|
||||
if (e.detail == 'generate-branch-name') {
|
||||
generateBranchName();
|
||||
}
|
||||
{/if}
|
||||
</div>
|
||||
{:else if branch.commits.length == 0}
|
||||
<div class="new-branch card" data-dnd-ignore>
|
||||
<div class="new-branch__content">
|
||||
<div class="new-branch__image">
|
||||
<ImgThemed
|
||||
imgSet={{
|
||||
light: '/images/lane-new-light.webp',
|
||||
dark: '/images/lane-new-dark.webp'
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if branch.commits.length == 0}
|
||||
<div class="new-branch card" data-dnd-ignore>
|
||||
<div class="new-branch__content">
|
||||
<div class="new-branch__image">
|
||||
<ImgThemed
|
||||
imgSet={{
|
||||
light: '/images/lane-new-light.webp',
|
||||
dark: '/images/lane-new-dark.webp'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<h2 class="new-branch__title text-base-body-15 text-semibold">
|
||||
This is a new branch.
|
||||
</h2>
|
||||
<p class="new-branch__caption text-base-body-13">
|
||||
You can drag and drop files or parts of files here.
|
||||
</p>
|
||||
</div>
|
||||
<h2 class="new-branch__title text-base-body-15 text-semibold">This is a new branch.</h2>
|
||||
<p class="new-branch__caption text-base-body-13">
|
||||
You can drag and drop files or parts of files here.
|
||||
</p>
|
||||
</div>
|
||||
{:else}
|
||||
<!-- attention: these markers have custom css at the bottom of thise file -->
|
||||
<div class="no-changes card" data-dnd-ignore>
|
||||
<div class="new-branch__content">
|
||||
<div class="new-branch__image">
|
||||
<ImgThemed
|
||||
imgSet={{
|
||||
light: '/images/lane-no-changes-light.webp',
|
||||
dark: '/images/lane-no-changes-dark.webp'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<h2 class="new-branch__caption text-base-body-13">
|
||||
No uncommitted changes<br />on this branch
|
||||
</h2>
|
||||
</div>
|
||||
{:else}
|
||||
<!-- attention: these markers have custom css at the bottom of thise file -->
|
||||
<div class="no-changes card" data-dnd-ignore>
|
||||
<div class="new-branch__content">
|
||||
<div class="new-branch__image">
|
||||
<ImgThemed
|
||||
imgSet={{
|
||||
light: '/images/lane-no-changes-light.webp',
|
||||
dark: '/images/lane-no-changes-dark.webp'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<h2 class="new-branch__caption text-base-body-13">
|
||||
No uncommitted changes<br />on this branch
|
||||
</h2>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<BranchCommits
|
||||
{base}
|
||||
{branch}
|
||||
{project}
|
||||
{githubService}
|
||||
{branchController}
|
||||
{branchCount}
|
||||
{readonly}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</ScrollableContainer>
|
||||
<BranchCommits
|
||||
{base}
|
||||
{branch}
|
||||
{project}
|
||||
{githubService}
|
||||
{branchController}
|
||||
{branchCount}
|
||||
{readonly}
|
||||
/>
|
||||
|
||||
<Resizer
|
||||
viewport={rsViewport}
|
||||
direction="right"
|
||||
inside={$selectedFiles.length > 0}
|
||||
minWidth={320}
|
||||
on:width={(e) => {
|
||||
laneWidth = e.detail / (16 * $userSettings.zoom);
|
||||
lscache.set(laneWidthKey + branch.id, laneWidth, 7 * 1440); // 7 day ttl
|
||||
$defaultBranchWidthRem = laneWidth;
|
||||
}}
|
||||
/>
|
||||
<Resizer
|
||||
viewport={rsViewport}
|
||||
direction="right"
|
||||
inside={$selectedFiles.length > 0}
|
||||
minWidth={320}
|
||||
on:width={(e) => {
|
||||
laneWidth = e.detail / (16 * $userSettings.zoom);
|
||||
lscache.set(laneWidthKey + branch.id, laneWidth, 7 * 1440); // 7 day ttl
|
||||
$defaultBranchWidthRem = laneWidth;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<slot name="file-view" />
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.resize-viewport {
|
||||
.branch-card {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
--target-branch-background: var(--clr-theme-container-pale);
|
||||
display: flex;
|
||||
/* flex-direction: column; */
|
||||
user-select: none;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
/* padding: 8px; */
|
||||
/* border-radius: var(--radius-l); */
|
||||
background-color: var(--target-branch-background);
|
||||
|
||||
/* remover scrollbar */
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0px;
|
||||
background: transparent; /* Chrome/Safari/Webkit */
|
||||
}
|
||||
}
|
||||
|
||||
.branch-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
user-select: none;
|
||||
.target-branch {
|
||||
--target-branch-background: color-mix(
|
||||
in srgb,
|
||||
var(--clr-theme-scale-pop-60) 30%,
|
||||
var(--clr-theme-container-pale)
|
||||
);
|
||||
}
|
||||
|
||||
.branch-card__dropzone-wrapper {
|
||||
@ -286,15 +307,15 @@
|
||||
}
|
||||
|
||||
.branch-card__contents {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 20px;
|
||||
gap: var(--space-4);
|
||||
padding: var(--space-16) var(--space-8) var(--space-16) var(--space-8);
|
||||
padding: var(--space-8);
|
||||
}
|
||||
|
||||
.resize-viewport {
|
||||
position: relative;
|
||||
.first-child {
|
||||
/* padding-left: var(--space-16); */
|
||||
}
|
||||
|
||||
.new-branch__content {
|
||||
|
@ -148,7 +148,7 @@
|
||||
.header__wrapper {
|
||||
z-index: 10;
|
||||
position: sticky;
|
||||
top: var(--space-16);
|
||||
top: var(--space-8);
|
||||
}
|
||||
.header {
|
||||
z-index: 2;
|
||||
@ -170,7 +170,7 @@
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: var(--space-20);
|
||||
background: var(--clr-theme-container-pale);
|
||||
background: var(--target-branch-background);
|
||||
/* background-color: red; */
|
||||
}
|
||||
.header__info {
|
||||
|
@ -49,24 +49,26 @@
|
||||
{user}
|
||||
{selectedFiles}
|
||||
{githubService}
|
||||
/>
|
||||
|
||||
{#if selected}
|
||||
<FileCard
|
||||
conflicted={selected.conflicted}
|
||||
branchId={branch.id}
|
||||
file={selected}
|
||||
projectId={project.id}
|
||||
{projectPath}
|
||||
{branchController}
|
||||
{selectedOwnership}
|
||||
selectable={$commitBoxOpen && !readonly}
|
||||
on:close={() => {
|
||||
const selectedId = selected?.id;
|
||||
selectedFiles.update((fileIds) => fileIds.filter((file) => file.id != selectedId));
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
>
|
||||
<svelte:fragment slot="file-view">
|
||||
{#if selected}
|
||||
<FileCard
|
||||
conflicted={selected.conflicted}
|
||||
branchId={branch.id}
|
||||
file={selected}
|
||||
projectId={project.id}
|
||||
{projectPath}
|
||||
{branchController}
|
||||
{selectedOwnership}
|
||||
selectable={$commitBoxOpen && !readonly}
|
||||
on:close={() => {
|
||||
const selectedId = selected?.id;
|
||||
selectedFiles.update((fileIds) => fileIds.filter((file) => file.id != selectedId));
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</BranchCard>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
|
@ -131,137 +131,138 @@
|
||||
</div>
|
||||
{/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>
|
||||
<div
|
||||
tabindex="0"
|
||||
role="cell"
|
||||
use:draggable={{
|
||||
...draggableHunk(branchId, section.hunk),
|
||||
disabled: readonly || 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, sidx}
|
||||
{@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}
|
||||
{#if !subsection.expanded}
|
||||
<div
|
||||
role="group"
|
||||
class="border-color-3 flex w-full"
|
||||
class:border-t={sidx == section.subSections.length - 1 ||
|
||||
(sidx > 0 && sidx < section.subSections.length - 1)}
|
||||
class:border-b={sidx == 0 ||
|
||||
(sidx > 0 && sidx < section.subSections.length - 1)}
|
||||
on:contextmenu|preventDefault={(e) =>
|
||||
popupMenu.openByMouse(e, {
|
||||
section: section,
|
||||
hunk
|
||||
})}
|
||||
>
|
||||
<div
|
||||
class="bg-color-4 text-color-4 hover:text-color-2 border-color-3 border-r text-center"
|
||||
style:min-width={`calc(${2 * minWidth}rem - 1px)`}
|
||||
>
|
||||
<button
|
||||
class="flex justify-center py-0.5 text-sm"
|
||||
style:width={`calc(${2 * minWidth}rem - 1px)`}
|
||||
on:click={() => {
|
||||
if ('expanded' in subsection) {
|
||||
subsection.expanded = true;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{#if sidx == 0}
|
||||
<IconExpandUp />
|
||||
{:else if sidx == section.subSections.length - 1}
|
||||
<IconExpandDown />
|
||||
{:else}
|
||||
<IconExpandUpDown />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
<div class="bg-color-4 flex-grow" />
|
||||
</div>
|
||||
{/if}
|
||||
<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>
|
||||
<div
|
||||
tabindex="0"
|
||||
role="cell"
|
||||
use:draggable={{
|
||||
...draggableHunk(branchId, section.hunk),
|
||||
disabled: readonly || 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, sidx}
|
||||
{@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}
|
||||
</div>
|
||||
{#if !subsection.expanded}
|
||||
<div
|
||||
role="group"
|
||||
class="border-color-3 flex w-full"
|
||||
class:border-t={sidx == section.subSections.length - 1 ||
|
||||
(sidx > 0 && sidx < section.subSections.length - 1)}
|
||||
class:border-b={sidx == 0 ||
|
||||
(sidx > 0 && sidx < section.subSections.length - 1)}
|
||||
on:contextmenu|preventDefault={(e) =>
|
||||
popupMenu.openByMouse(e, {
|
||||
section: section,
|
||||
hunk
|
||||
})}
|
||||
>
|
||||
<div
|
||||
class="bg-color-4 text-color-4 hover:text-color-2 border-color-3 border-r text-center"
|
||||
style:min-width={`calc(${2 * minWidth}rem - 1px)`}
|
||||
>
|
||||
<button
|
||||
class="flex justify-center py-0.5 text-sm"
|
||||
style:width={`calc(${2 * minWidth}rem - 1px)`}
|
||||
on:click={() => {
|
||||
if ('expanded' in subsection) {
|
||||
subsection.expanded = true;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{#if sidx == 0}
|
||||
<IconExpandUp />
|
||||
{:else if sidx == section.subSections.length - 1}
|
||||
<IconExpandDown />
|
||||
{:else}
|
||||
<IconExpandUpDown />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
<div class="bg-color-4 flex-grow" />
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
</ScrollableContainer>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
<Resizer
|
||||
viewport={rsViewport}
|
||||
direction="right"
|
||||
inside
|
||||
minWidth={240}
|
||||
on:width={(e) => {
|
||||
fileWidth = e.detail / (16 * $userSettings.zoom);
|
||||
lscache.set(fileWidthKey + file.id, fileWidth, 7 * 1440); // 7 day ttl
|
||||
$defaultFileWidthRem = fileWidth;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<Resizer
|
||||
viewport={rsViewport}
|
||||
direction="right"
|
||||
inside
|
||||
minWidth={240}
|
||||
on:width={(e) => {
|
||||
fileWidth = e.detail / (16 * $userSettings.zoom);
|
||||
lscache.set(fileWidthKey + file.id, fileWidth, 7 * 1440); // 7 day ttl
|
||||
$defaultFileWidthRem = fileWidth;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.resize-viewport {
|
||||
position: relative;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
align-items: self-start;
|
||||
overflow: hidden;
|
||||
padding: var(--space-16) var(--space-6);
|
||||
padding: var(--space-8) var(--space-8) var(--space-8) 0;
|
||||
margin-left: calc(var(--space-4) * -1);
|
||||
}
|
||||
.file-card {
|
||||
background: var(--clr-theme-container-light);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
.hunks {
|
||||
|
Loading…
Reference in New Issue
Block a user