mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-19 15:41:31 +03:00
Added scrollbar to lanes and removed unused CSS vars
This commit is contained in:
parent
06f0490bf3
commit
bf27c3c474
@ -5,6 +5,7 @@
|
||||
import CommitDialog from './CommitDialog.svelte';
|
||||
import DropzoneOverlay from './DropzoneOverlay.svelte';
|
||||
import PullRequestCard from './PullRequestCard.svelte';
|
||||
import ScrollableContainer from './ScrollableContainer.svelte';
|
||||
import UpstreamCommits from './UpstreamCommits.svelte';
|
||||
import { ButlerAIProvider } from '$lib/backend/aiProviders';
|
||||
import { Summarizer } from '$lib/backend/summarizer';
|
||||
@ -44,6 +45,7 @@
|
||||
RemoteBranchData,
|
||||
RemoteCommit
|
||||
} from '$lib/vbranches/types';
|
||||
|
||||
export let branch: Branch;
|
||||
export let isUnapplied = false;
|
||||
export let project: Project;
|
||||
@ -63,6 +65,7 @@
|
||||
const aiGenEnabled = projectAiGenEnabled(project.id);
|
||||
const aiGenAutoBranchNamingEnabled = projectAiGenAutoBranchNamingEnabled(project.id);
|
||||
|
||||
let scrollViewport: HTMLElement;
|
||||
let rsViewport: HTMLElement;
|
||||
|
||||
const userSettings = getContext<SettingsStore>(SETTINGS_CONTEXT);
|
||||
@ -187,177 +190,201 @@
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="resizer-wrapper">
|
||||
<div class="resizer-wrapper" bind:this={scrollViewport}>
|
||||
<div
|
||||
class="branch-card"
|
||||
class="branch-card hide-native-scrollbar"
|
||||
data-tauri-drag-region
|
||||
class:target-branch={branch.active && branch.selectedForChanges}
|
||||
>
|
||||
<div
|
||||
bind:this={rsViewport}
|
||||
style:width={`${laneWidth || $defaultBranchWidthRem}rem`}
|
||||
class="branch-card__contents"
|
||||
<ScrollableContainer
|
||||
wide
|
||||
padding={{
|
||||
top: `var(--space-12)`,
|
||||
bottom: `var(--space-12)`
|
||||
}}
|
||||
>
|
||||
<BranchHeader
|
||||
{isUnapplied}
|
||||
{branchController}
|
||||
{branch}
|
||||
{base}
|
||||
bind:isLaneCollapsed
|
||||
projectId={project.id}
|
||||
on:action={(e) => {
|
||||
if (e.detail == 'generate-branch-name') {
|
||||
generateBranchName();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<PullRequestCard
|
||||
projectId={project.id}
|
||||
{branch}
|
||||
{branchService}
|
||||
{githubService}
|
||||
{isUnapplied}
|
||||
isLaneCollapsed={$isLaneCollapsed}
|
||||
/>
|
||||
{#if user?.role == 'admin' && unknownCommits && unknownCommits.length > 0 && !branch.conflicted}
|
||||
<UpstreamCommits
|
||||
upstream={upstreamData}
|
||||
branchId={branch.id}
|
||||
{project}
|
||||
{branchController}
|
||||
{branchCount}
|
||||
projectId={project.id}
|
||||
{selectedFiles}
|
||||
{base}
|
||||
/>
|
||||
{/if}
|
||||
<!-- DROPZONES -->
|
||||
<DropzoneOverlay class="cherrypick-dz-marker" label="Apply here" />
|
||||
<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: 'move-commit-dz-hover',
|
||||
active: 'move-commit-dz-active',
|
||||
accepts: acceptMoveCommit,
|
||||
onDrop: onCommitDrop,
|
||||
disabled: isUnapplied
|
||||
}}
|
||||
use:dropzone={{
|
||||
hover: 'cherrypick-dz-hover',
|
||||
active: 'cherrypick-dz-active',
|
||||
accepts: acceptCherrypick,
|
||||
onDrop: onCherrypicked,
|
||||
disabled: isUnapplied
|
||||
}}
|
||||
use:dropzone={{
|
||||
hover: 'lane-dz-hover',
|
||||
active: 'lane-dz-active',
|
||||
accepts: acceptBranchDrop,
|
||||
onDrop: onBranchDrop,
|
||||
disabled: isUnapplied
|
||||
}}
|
||||
bind:this={rsViewport}
|
||||
style:width={`${laneWidth || $defaultBranchWidthRem}rem`}
|
||||
class="branch-card__contents"
|
||||
>
|
||||
<BranchHeader
|
||||
{isUnapplied}
|
||||
{branchController}
|
||||
{branch}
|
||||
{base}
|
||||
bind:isLaneCollapsed
|
||||
projectId={project.id}
|
||||
on:action={(e) => {
|
||||
if (e.detail == 'generate-branch-name') {
|
||||
generateBranchName();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<PullRequestCard
|
||||
projectId={project.id}
|
||||
{branch}
|
||||
{branchService}
|
||||
{githubService}
|
||||
{isUnapplied}
|
||||
isLaneCollapsed={$isLaneCollapsed}
|
||||
/>
|
||||
{#if user?.role == 'admin' && unknownCommits && unknownCommits.length > 0 && !branch.conflicted}
|
||||
<UpstreamCommits
|
||||
upstream={upstreamData}
|
||||
branchId={branch.id}
|
||||
{project}
|
||||
{branchController}
|
||||
{branchCount}
|
||||
projectId={project.id}
|
||||
{selectedFiles}
|
||||
{base}
|
||||
/>
|
||||
{/if}
|
||||
<!-- DROPZONES -->
|
||||
<DropzoneOverlay class="cherrypick-dz-marker" label="Apply here" />
|
||||
<DropzoneOverlay class="cherrypick-dz-marker" label="Apply here" />
|
||||
<DropzoneOverlay class="lane-dz-marker" label="Move here" />
|
||||
<DropzoneOverlay class="move-commit-dz-marker" label="Move here" />
|
||||
|
||||
{#if branch.files?.length > 0}
|
||||
<div class="card">
|
||||
{#if branch.active && branch.conflicted}
|
||||
<div class="mb-2 bg-red-500 p-2 font-bold text-white">
|
||||
{#if branch.files.some((f) => f.conflicted)}
|
||||
This virtual branch conflicts with upstream changes. Please resolve all
|
||||
conflicts and commit before you can continue.
|
||||
{:else}
|
||||
Please commit your resolved conflicts to continue.
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
<BranchFiles
|
||||
branchId={branch.id}
|
||||
files={branch.files}
|
||||
{isUnapplied}
|
||||
{branchController}
|
||||
{project}
|
||||
{selectedOwnership}
|
||||
{selectedFiles}
|
||||
showCheckboxes={$commitBoxOpen}
|
||||
allowMultiple={true}
|
||||
readonly={false}
|
||||
/>
|
||||
{#if branch.active}
|
||||
<CommitDialog
|
||||
projectId={project.id}
|
||||
<div
|
||||
class="branch-card__dropzone-wrapper"
|
||||
use:dropzone={{
|
||||
hover: 'move-commit-dz-hover',
|
||||
active: 'move-commit-dz-active',
|
||||
accepts: acceptMoveCommit,
|
||||
onDrop: onCommitDrop,
|
||||
disabled: isUnapplied
|
||||
}}
|
||||
use:dropzone={{
|
||||
hover: 'cherrypick-dz-hover',
|
||||
active: 'cherrypick-dz-active',
|
||||
accepts: acceptCherrypick,
|
||||
onDrop: onCherrypicked,
|
||||
disabled: isUnapplied
|
||||
}}
|
||||
use:dropzone={{
|
||||
hover: 'lane-dz-hover',
|
||||
active: 'lane-dz-active',
|
||||
accepts: acceptBranchDrop,
|
||||
onDrop: onBranchDrop,
|
||||
disabled: isUnapplied
|
||||
}}
|
||||
>
|
||||
<DropzoneOverlay class="cherrypick-dz-marker" label="Apply here" />
|
||||
<DropzoneOverlay class="lane-dz-marker" label="Move here" />
|
||||
<DropzoneOverlay class="move-commit-dz-marker" label="Move here" />
|
||||
|
||||
{#if branch.files?.length > 0}
|
||||
<div class="card">
|
||||
{#if branch.active && branch.conflicted}
|
||||
<div class="mb-2 bg-red-500 p-2 font-bold text-white">
|
||||
{#if branch.files.some((f) => f.conflicted)}
|
||||
This virtual branch conflicts with upstream changes. Please resolve all
|
||||
conflicts and commit before you can continue.
|
||||
{:else}
|
||||
Please commit your resolved conflicts to continue.
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
<BranchFiles
|
||||
branchId={branch.id}
|
||||
files={branch.files}
|
||||
{isUnapplied}
|
||||
{branchController}
|
||||
{branch}
|
||||
{cloud}
|
||||
{project}
|
||||
{selectedOwnership}
|
||||
{user}
|
||||
bind:expanded={commitBoxOpen}
|
||||
on:action={(e) => {
|
||||
if (e.detail == 'generate-branch-name') {
|
||||
generateBranchName();
|
||||
}
|
||||
}}
|
||||
{selectedFiles}
|
||||
showCheckboxes={$commitBoxOpen}
|
||||
allowMultiple={true}
|
||||
readonly={false}
|
||||
/>
|
||||
{/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 branch.active}
|
||||
<CommitDialog
|
||||
projectId={project.id}
|
||||
{branchController}
|
||||
{branch}
|
||||
{cloud}
|
||||
{selectedOwnership}
|
||||
{user}
|
||||
bind:expanded={commitBoxOpen}
|
||||
on:action={(e) => {
|
||||
if (e.detail == 'generate-branch-name') {
|
||||
generateBranchName();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</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>
|
||||
{/if}
|
||||
</div>
|
||||
</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'
|
||||
}}
|
||||
/>
|
||||
{: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__caption text-base-body-13">
|
||||
No uncommitted changes<br />on this branch
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</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>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<BranchCommits
|
||||
{base}
|
||||
{branch}
|
||||
{project}
|
||||
{githubService}
|
||||
{branchController}
|
||||
{branchService}
|
||||
{branchCount}
|
||||
{isUnapplied}
|
||||
{selectedFiles}
|
||||
<BranchCommits
|
||||
{base}
|
||||
{branch}
|
||||
{project}
|
||||
{githubService}
|
||||
{branchController}
|
||||
{branchService}
|
||||
{branchCount}
|
||||
{isUnapplied}
|
||||
{selectedFiles}
|
||||
/>
|
||||
</div>
|
||||
</ScrollableContainer>
|
||||
<div class="divider-line">
|
||||
<Resizer
|
||||
viewport={rsViewport}
|
||||
direction="right"
|
||||
minWidth={320}
|
||||
sticky
|
||||
defaultLineColor={$selectedFiles.length > 0
|
||||
? 'transparent'
|
||||
: 'var(--clr-theme-container-outline-light)'}
|
||||
on:width={(e) => {
|
||||
laneWidth = e.detail / (16 * $userSettings.zoom);
|
||||
lscache.set(laneWidthKey + branch.id, laneWidth, 7 * 1440); // 7 day ttl
|
||||
$defaultBranchWidthRem = laneWidth;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider-line">
|
||||
<!-- <div class="divider-line">
|
||||
<Resizer
|
||||
viewport={rsViewport}
|
||||
direction="right"
|
||||
@ -372,7 +399,7 @@
|
||||
$defaultBranchWidthRem = laneWidth;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@ -388,19 +415,14 @@
|
||||
user-select: none;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0px;
|
||||
background: transparent; /* Chrome/Safari/Webkit */
|
||||
}
|
||||
}
|
||||
|
||||
.divider-line {
|
||||
z-index: 30;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
transform: translateX(var(--selected-resize-shift));
|
||||
}
|
||||
|
||||
.branch-card__dropzone-wrapper {
|
||||
|
@ -138,9 +138,6 @@
|
||||
user-select: none; /* here because of user-select draggable interference in board */
|
||||
position: relative;
|
||||
--target-branch-background: var(--clr-theme-container-pale);
|
||||
--selected-resize-shift: 0;
|
||||
--selected-target-branch-right-padding: 0;
|
||||
--selected-opacity: 1;
|
||||
background-color: var(--target-branch-background);
|
||||
}
|
||||
|
||||
@ -152,12 +149,6 @@
|
||||
);
|
||||
}
|
||||
|
||||
.file-selected {
|
||||
--selected-resize-shift: calc((var(--space-6) + 0.0625rem) * -1);
|
||||
--selected-target-branch-right-padding: calc(var(--space-4) * -1);
|
||||
--selected-opacity: 0;
|
||||
}
|
||||
|
||||
.file-preview {
|
||||
display: flex;
|
||||
position: relative;
|
||||
@ -167,6 +158,5 @@
|
||||
align-items: self-start;
|
||||
|
||||
padding: var(--space-12) var(--space-12) var(--space-12) 0;
|
||||
margin-left: var(--selected-target-branch-right-padding);
|
||||
}
|
||||
</style>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import Scrollbar from '$lib/components/Scrollbar.svelte';
|
||||
import Scrollbar, { type ScrollbarPadding } from '$lib/components/Scrollbar.svelte';
|
||||
import { onDestroy, onMount, createEventDispatcher } from 'svelte';
|
||||
|
||||
export let viewport: HTMLDivElement | undefined = undefined;
|
||||
@ -13,6 +13,10 @@
|
||||
export let initiallyVisible = false;
|
||||
export let showBorderWhenScrolled = false;
|
||||
|
||||
export let padding: ScrollbarPadding = {};
|
||||
export let shift = '0';
|
||||
export let thickness = '0.563rem';
|
||||
|
||||
let observer: ResizeObserver;
|
||||
|
||||
const dispatch = createEventDispatcher<{ dragging: boolean }>();
|
||||
@ -53,6 +57,9 @@
|
||||
{viewport}
|
||||
{contents}
|
||||
{initiallyVisible}
|
||||
{padding}
|
||||
{shift}
|
||||
{thickness}
|
||||
on:dragging={(e) => dispatch('dragging', e.detail)}
|
||||
/>
|
||||
</div>
|
||||
|
@ -1,3 +1,7 @@
|
||||
<script lang="ts" context="module">
|
||||
export type ScrollbarPadding = { top?: string; right?: string; bottom?: string; left?: string };
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { SETTINGS_CONTEXT, type SettingsStore } from '$lib/settings/userSettings';
|
||||
import { onDestroy, createEventDispatcher } from 'svelte';
|
||||
@ -10,6 +14,8 @@
|
||||
export let hideAfter = 1000;
|
||||
export let initiallyVisible = false;
|
||||
export let thickness = '0.563rem';
|
||||
export let padding: ScrollbarPadding = {};
|
||||
export let shift = '0';
|
||||
|
||||
export let horz = false;
|
||||
|
||||
@ -35,6 +41,11 @@
|
||||
$: teardownTrack = setupTrack(track);
|
||||
$: teardownContents = setupContents(contents);
|
||||
|
||||
$: paddingTop = padding.top ?? '0px';
|
||||
$: paddingBottom = padding.bottom ?? '0px';
|
||||
$: paddingRight = padding.right ?? '0px';
|
||||
$: paddingLeft = padding.left ?? '0px';
|
||||
|
||||
$: wholeHeight = viewport?.scrollHeight ?? 0;
|
||||
$: wholeWidth = viewport?.scrollWidth ?? 0;
|
||||
$: scrollTop = viewport?.scrollTop ?? 0;
|
||||
@ -71,7 +82,7 @@
|
||||
wholeHeight = viewport?.scrollHeight ?? 0;
|
||||
wholeWidth = viewport?.scrollWidth ?? 0;
|
||||
trackHeight = viewport?.clientHeight ?? 0;
|
||||
trackWidth = viewport?.clientWidth ?? 0;
|
||||
trackWidth = viewport?.clientWidth;
|
||||
}
|
||||
});
|
||||
|
||||
@ -261,27 +272,41 @@
|
||||
class:vert
|
||||
class:show-scrollbar={visible}
|
||||
class:thumb-dragging={isDragging}
|
||||
style:right={vert ? 0 : undefined}
|
||||
style:top={vert ? 0 : undefined}
|
||||
style:bottom={horz ? 0 : undefined}
|
||||
style:left={horz ? 0 : undefined}
|
||||
style:width={vert ? thickness : `80%`}
|
||||
style:height={vert ? `80%` : thickness}
|
||||
style:width={vert ? thickness : `100%`}
|
||||
style:height={vert ? `100%` : thickness}
|
||||
style:z-index={zIndex}
|
||||
style="
|
||||
--scrollbar-shift-vertical: {vert ? '0' : shift};
|
||||
--scrollbar-shift-horizontal: {horz ? '0' : shift};
|
||||
"
|
||||
>
|
||||
<div
|
||||
bind:this={thumb}
|
||||
class="scrollbar-thumb"
|
||||
style:left={vert ? undefined : `${thumbLeft}px`}
|
||||
style:top={vert ? `${thumbTop}px` : undefined}
|
||||
style:width={vert ? '100%' : `${thumbWidth}px`}
|
||||
style:height={vert ? `${thumbHeight}px` : '100%'}
|
||||
style="
|
||||
--thumb-width: {vert
|
||||
? '100%'
|
||||
: `calc(${thumbWidth.toFixed(0)}px - (${paddingRight} + ${paddingLeft}))`};
|
||||
--thumb-height: {vert
|
||||
? `calc(${thumbHeight.toFixed(0)}px - (${paddingBottom} + ${paddingTop}))`
|
||||
: '100%'};
|
||||
--thumb-top: {vert ? `calc(${thumbTop.toFixed(0)}px + ${paddingTop})` : 'auto'};
|
||||
--thumb-left: {vert ? 'auto' : `calc(${thumbLeft.toFixed(0)}px + ${paddingLeft})`};
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.scrollbar-track {
|
||||
/* scrollbar variables */
|
||||
--scrollbar-shift-vertical: 0;
|
||||
--scrollbar-shift-horizontal: 0;
|
||||
/* variable props */
|
||||
bottom: var(--scrollbar-shift-vertical);
|
||||
right: var(--scrollbar-shift-horizontal);
|
||||
/* other props */
|
||||
position: absolute;
|
||||
/* background-color: aqua; */
|
||||
transition:
|
||||
opacity 0.2s,
|
||||
width 0.1s,
|
||||
@ -289,6 +314,12 @@
|
||||
}
|
||||
|
||||
.scrollbar-thumb {
|
||||
/* variable props */
|
||||
width: var(--thumb-width);
|
||||
height: var(--thumb-height);
|
||||
top: var(--thumb-top);
|
||||
left: var(--thumb-left);
|
||||
/* other props */
|
||||
position: absolute;
|
||||
z-index: 30;
|
||||
background-color: var(--clr-theme-scale-ntrl-0);
|
||||
|
Loading…
Reference in New Issue
Block a user