mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-26 11:08:38 +03:00
Merged origin/master into Update new branch styling
This commit is contained in:
commit
8d762f88d0
@ -1,6 +1,9 @@
|
||||
import { subscribeToFetches } from '$lib/backend/fetches';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Observable, shareReplay, startWith } from 'rxjs';
|
||||
|
||||
export function getFetchNotifications(projectId: string): Observable<void> {
|
||||
return new Observable((observer) => subscribeToFetches(projectId, () => observer.next()));
|
||||
export function getFetchNotifications(projectId: string): Observable<unknown> {
|
||||
return new Observable((observer) => subscribeToFetches(projectId, () => observer.next())).pipe(
|
||||
startWith(undefined),
|
||||
shareReplay(1)
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { getHead, subscribeToHead } from '$lib/backend/heads';
|
||||
import { Observable, concat, from } from 'rxjs';
|
||||
import { Observable, concat, from, shareReplay } from 'rxjs';
|
||||
|
||||
export function getHeads(projectId: string): Observable<string> {
|
||||
const head$ = from(getHead(projectId));
|
||||
const stream$ = new Observable<string>((subscriber) =>
|
||||
subscribeToHead(projectId, (head) => subscriber.next(head))
|
||||
);
|
||||
return concat(head$, stream$);
|
||||
return concat(head$, stream$).pipe(shareReplay(1));
|
||||
}
|
||||
|
@ -5,9 +5,8 @@ import {
|
||||
BehaviorSubject,
|
||||
Observable,
|
||||
catchError,
|
||||
combineLatestWith,
|
||||
combineLatest,
|
||||
map,
|
||||
merge,
|
||||
of,
|
||||
shareReplay,
|
||||
switchMap
|
||||
@ -24,8 +23,7 @@ export class RemoteBranchService {
|
||||
head$: Observable<any>,
|
||||
baseBranch$: Observable<any>
|
||||
) {
|
||||
this.branches$ = merge(fetches$, head$, baseBranch$).pipe(
|
||||
combineLatestWith(this.reload$),
|
||||
this.branches$ = combineLatest([baseBranch$, this.reload$, head$, fetches$]).pipe(
|
||||
switchMap(() => getRemoteBranchesData({ projectId })),
|
||||
map((branches) => branches.filter((b) => b.ahead != 0)),
|
||||
shareReplay(1),
|
||||
|
@ -2,7 +2,6 @@ import { BaseBranch, Branch } from './types';
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
import { UserError, invoke, listen } from '$lib/backend/ipc';
|
||||
import {
|
||||
merge,
|
||||
switchMap,
|
||||
Observable,
|
||||
shareReplay,
|
||||
@ -14,7 +13,8 @@ import {
|
||||
tap,
|
||||
map,
|
||||
firstValueFrom,
|
||||
timeout
|
||||
timeout,
|
||||
combineLatest
|
||||
} from 'rxjs';
|
||||
|
||||
export class VirtualBranchService {
|
||||
@ -83,8 +83,8 @@ export class BaseBranchService {
|
||||
error$ = new BehaviorSubject<any>(undefined);
|
||||
private reload$ = new BehaviorSubject<void>(undefined);
|
||||
|
||||
constructor(projectId: string, fetches$: Observable<void>, head$: Observable<string>) {
|
||||
this.base$ = merge(fetches$, head$, this.reload$).pipe(
|
||||
constructor(projectId: string, fetches$: Observable<unknown>, head$: Observable<string>) {
|
||||
this.base$ = combineLatest([fetches$, head$, this.reload$]).pipe(
|
||||
debounceTime(100),
|
||||
switchMap(() => getBaseBranch({ projectId })),
|
||||
catchError((e) => {
|
||||
|
@ -145,6 +145,8 @@
|
||||
{readonly}
|
||||
{branchController}
|
||||
{branch}
|
||||
{base}
|
||||
{githubService}
|
||||
projectId={project.id}
|
||||
on:action={(e) => {
|
||||
if (e.detail == 'generate-branch-name') {
|
||||
|
@ -2,17 +2,27 @@
|
||||
import IconButton from '$lib/components/IconButton.svelte';
|
||||
import Icon from '$lib/icons/Icon.svelte';
|
||||
import type { BranchController } from '$lib/vbranches/branchController';
|
||||
import type { Branch } from '$lib/vbranches/types';
|
||||
import type { BaseBranch, Branch } from '$lib/vbranches/types';
|
||||
import { fade } from 'svelte/transition';
|
||||
import BranchLabel from './BranchLabel.svelte';
|
||||
import BranchLanePopupMenu from './BranchLanePopupMenu.svelte';
|
||||
import { clickOutside } from '$lib/clickOutside';
|
||||
import Tag from './Tag.svelte';
|
||||
import { branchUrl } from './commitList';
|
||||
import type { GitHubService } from '$lib/github/service';
|
||||
import BranchIcon from '../navigation/BranchIcon.svelte';
|
||||
import { open } from '@tauri-apps/api/shell';
|
||||
|
||||
export let readonly = false;
|
||||
export let branch: Branch;
|
||||
export let base: BaseBranch | undefined | null;
|
||||
export let branchController: BranchController;
|
||||
export let projectId: string;
|
||||
|
||||
export let githubService: GitHubService;
|
||||
$: pr$ = githubService.get(branch.upstreamName);
|
||||
// $: prStatus$ = githubService.getStatus($pr$?.targetBranch);
|
||||
|
||||
let meatballButton: HTMLDivElement;
|
||||
let visible = false;
|
||||
|
||||
@ -24,7 +34,7 @@
|
||||
</script>
|
||||
|
||||
<div class="card__header relative" data-drag-handle>
|
||||
<div class="card__row" data-drag-handle>
|
||||
<div class="header__row" data-drag-handle>
|
||||
<div class="header__left">
|
||||
{#if !readonly}
|
||||
<div class="draggable" data-drag-handle>
|
||||
@ -48,17 +58,51 @@
|
||||
</div>
|
||||
</div>
|
||||
{#if branch.upstreamName}
|
||||
<div class="card__row text-base-11" data-drag-handle>
|
||||
<div class="card__remote">
|
||||
{#if !branch.upstream}
|
||||
{#if hasIntegratedCommits}
|
||||
<div class="status-tag deleted">deleted</div>
|
||||
{:else}
|
||||
<div class="status-tag pending">pending</div>
|
||||
{/if}
|
||||
<div class="header__remote-branch text-base-body-11" data-drag-handle>
|
||||
{#if !branch.upstream}
|
||||
{#if hasIntegratedCommits}
|
||||
<div class="status-tag deleted">deleted</div>
|
||||
{:else}
|
||||
<div class="status-tag pending">pending</div>
|
||||
{/if}
|
||||
<div>origin/{branch.upstreamName}</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div>origin/{branch.upstreamName}</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if branch.upstream}
|
||||
<div class="header__links">
|
||||
<BranchIcon name="remote-branch" color="neutral" />
|
||||
|
||||
<Tag
|
||||
icon="open-link"
|
||||
color="ghost"
|
||||
border
|
||||
clickable
|
||||
on:click={(e) => {
|
||||
const url = branchUrl(base, branch.upstream?.name);
|
||||
if (url) open(url);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
View remote branch
|
||||
</Tag>
|
||||
{#if $pr$?.htmlUrl}
|
||||
<Tag
|
||||
icon="pr-small"
|
||||
color="ghost"
|
||||
border
|
||||
clickable
|
||||
on:click={(e) => {
|
||||
const url = $pr$?.htmlUrl;
|
||||
if (url) open(url);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
View PR
|
||||
</Tag>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@ -72,12 +116,11 @@
|
||||
.card__header:hover .draggable {
|
||||
color: var(--clr-theme-scale-ntrl-40);
|
||||
}
|
||||
.card__row {
|
||||
.header__row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-8);
|
||||
align-items: center;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.header__left {
|
||||
@ -89,6 +132,15 @@
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.header__links {
|
||||
display: flex;
|
||||
gap: var(--space-6);
|
||||
align-items: center;
|
||||
padding-left: var(--space-28);
|
||||
margin-top: var(--space-10);
|
||||
fill: var(--clr-core-ntrl-50);
|
||||
}
|
||||
|
||||
.draggable {
|
||||
display: flex;
|
||||
cursor: grab;
|
||||
@ -103,14 +155,14 @@
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.card__remote {
|
||||
.header__remote-branch {
|
||||
color: var(--clr-theme-scale-ntrl-50);
|
||||
padding-left: var(--space-28);
|
||||
display: flex;
|
||||
gap: var(--space-4);
|
||||
text-overflow: ellipsis;
|
||||
overflow-x: hidden;
|
||||
white-space: nowrap;
|
||||
color: var(--clr-theme-scale-ntrl-50);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@ -118,10 +170,12 @@
|
||||
padding: var(--space-2) var(--space-4);
|
||||
border-radius: var(--radius-s);
|
||||
}
|
||||
|
||||
.pending {
|
||||
color: var(--clr-theme-scale-ntrl-40);
|
||||
background: var(--clr-theme-container-sub);
|
||||
}
|
||||
|
||||
.deleted {
|
||||
color: var(--clr-theme-scale-warn-30);
|
||||
background: var(--clr-theme-warn-container-dim);
|
||||
|
@ -29,15 +29,12 @@
|
||||
return c.isIntegrated;
|
||||
}
|
||||
});
|
||||
$: pr$ = githubService.get(branch.upstreamName);
|
||||
// $: prStatus$ = githubService.getStatus($pr$?.targetBranch);
|
||||
|
||||
let expanded = true;
|
||||
</script>
|
||||
|
||||
{#if commits.length > 0}
|
||||
<div class="commit-list" style:min-height={expanded ? `${2 * headerHeight}px` : undefined}>
|
||||
<CommitListHeader bind:expanded {branch} {pr$} {type} {base} bind:height={headerHeight} />
|
||||
<CommitListHeader bind:expanded {type} bind:height={headerHeight} />
|
||||
{#if expanded}
|
||||
<div class="commit-list__content">
|
||||
<div class="commits">
|
||||
|
@ -1,20 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { PullRequest } from '$lib/github/types';
|
||||
import type { BaseBranch, Branch } from '$lib/vbranches/types';
|
||||
import type { Observable } from 'rxjs';
|
||||
import { branchUrl, type CommitType } from './commitList';
|
||||
import { open } from '@tauri-apps/api/shell';
|
||||
import Link from '$lib/components/Link.svelte';
|
||||
import Icon from '$lib/icons/Icon.svelte';
|
||||
import Tag from './Tag.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import type { CommitType } from './commitList';
|
||||
|
||||
export let branch: Branch;
|
||||
export let expanded: boolean;
|
||||
export let pr$: Observable<PullRequest | undefined> | undefined;
|
||||
// export let prStatus$: Observable<PrStatus | undefined> | undefined;
|
||||
export let type: CommitType;
|
||||
export let base: BaseBranch | undefined | null;
|
||||
export let height: number | undefined;
|
||||
|
||||
let element: HTMLButtonElement | undefined = undefined;
|
||||
@ -38,32 +28,7 @@
|
||||
{#if type == 'local'}
|
||||
Local
|
||||
{:else if type == 'remote'}
|
||||
{#if branch.upstream}
|
||||
<Link
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={branchUrl(base, branch.upstream?.name)}
|
||||
class="inline-block max-w-full truncate"
|
||||
>
|
||||
Remote
|
||||
</Link>
|
||||
{#if $pr$?.htmlUrl}
|
||||
<Tag
|
||||
icon="pr-small"
|
||||
color="ghost"
|
||||
border
|
||||
clickable
|
||||
on:click={(e) => {
|
||||
const url = $pr$?.htmlUrl;
|
||||
if (url) open(url);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
View PR
|
||||
</Tag>
|
||||
{/if}
|
||||
{/if}
|
||||
Remote branch
|
||||
{:else if type == 'integrated'}
|
||||
Integrated
|
||||
{/if}
|
||||
|
@ -2,8 +2,11 @@ import type { BaseBranch } from '$lib/vbranches/types';
|
||||
|
||||
export type CommitType = 'local' | 'remote' | 'integrated';
|
||||
|
||||
export function branchUrl(target: BaseBranch | undefined | null, upstreamBranchName: string) {
|
||||
if (!target) return undefined;
|
||||
export function branchUrl(
|
||||
target: BaseBranch | undefined | null,
|
||||
upstreamBranchName: string | undefined
|
||||
) {
|
||||
if (!target || !upstreamBranchName) return undefined;
|
||||
const baseBranchName = target.branchName.split('/')[1];
|
||||
const parts = upstreamBranchName.split('/');
|
||||
const branchName = parts[parts.length - 1];
|
||||
|
@ -12,7 +12,6 @@
|
||||
justify-content: space-between;
|
||||
padding: var(--space-12);
|
||||
gap: var(--space-8);
|
||||
align-items: center;
|
||||
border-bottom: 1px solid var(--clr-theme-container-outline-light);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user