mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-02 07:53:55 +03:00
Add first iteration of project switcher
- next to base refresh button
This commit is contained in:
parent
6e2139b224
commit
6d0d34fa65
@ -8,10 +8,10 @@
|
||||
</script>
|
||||
|
||||
<button
|
||||
on:click|stopPropagation
|
||||
class="{className} text-light-600 outline-blue-200 hover:text-light-800 focus:text-light-800 focus:outline-2 disabled:cursor-not-allowed disabled:text-light-200 dark:text-dark-400 hover:dark:text-dark-100 focus:dark:text-dark-600 dark:disabled:text-dark-400"
|
||||
class="{className} text-color-4 hover:text-color-1 outline-blue-200 focus:text-light-800 focus:outline-2 disabled:cursor-not-allowed disabled:text-light-200 dark:text-dark-400 hover:dark:text-dark-100 focus:dark:text-dark-600 dark:disabled:text-dark-400"
|
||||
{title}
|
||||
on:click
|
||||
>
|
||||
<slot />
|
||||
<svelte:component this={icon} />
|
||||
<svelte:component this={icon} class="h-3 w-3" />
|
||||
</button>
|
||||
|
24
packages/ui/src/lib/icons/IconDropDown.svelte
Normal file
24
packages/ui/src/lib/icons/IconDropDown.svelte
Normal file
@ -0,0 +1,24 @@
|
||||
<script lang="ts">
|
||||
let className = '';
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<svg
|
||||
class={className}
|
||||
width="10"
|
||||
height="12"
|
||||
viewBox="0 0 10 12"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M1 8L4.4 10.55C4.75556 10.8167 5.24444 10.8167 5.6 10.55L9 8"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
/>
|
||||
<path
|
||||
d="M1 4L4.4 1.45C4.75556 1.18333 5.24444 1.18333 5.6 1.45L9 4"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
/>
|
||||
</svg>
|
@ -19,27 +19,26 @@
|
||||
import Link from '$lib/components/Link.svelte';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import { syncToCloud } from '$lib/backend/cloud';
|
||||
import BaseBranch from './base/BaseBranch.svelte';
|
||||
|
||||
export let data: LayoutData;
|
||||
let {
|
||||
projectStore,
|
||||
update,
|
||||
sessionsStore,
|
||||
deltasStore,
|
||||
baseBranchStore,
|
||||
baseBranchesState,
|
||||
vbranchesState,
|
||||
branchController,
|
||||
branchesWithContent,
|
||||
remoteBranchStore,
|
||||
githubContextStore,
|
||||
pullRequestsStore
|
||||
} = data;
|
||||
|
||||
$: projectStore = data.projectStore;
|
||||
$: sessionsStore = data.sessionsStore;
|
||||
$: baseBranchStore = data.baseBranchStore;
|
||||
$: githubContextStore = data.githubContextStore;
|
||||
$: branchController = data.branchController;
|
||||
$: vbranchesState = data.vbranchesState;
|
||||
$: remoteBranchStore = data.remoteBranchStore;
|
||||
$: pullRequestsStore = data.pullRequestsStore;
|
||||
$: update = data.update;
|
||||
$: deltasStore = data.deltasStore;
|
||||
$: baseBranchesState = data.baseBranchesState;
|
||||
$: branchesWithContent = data.branchesWithContent;
|
||||
|
||||
const userSettings = getContext<SettingsStore>(SETTINGS_CONTEXT);
|
||||
|
||||
$: sessionId = $sessionsStore?.length > 0 ? $sessionsStore[0].id : undefined;
|
||||
$: projectState = projectStore.state;
|
||||
$: updateDeltasStore(sessionId);
|
||||
|
||||
let trayViewport: HTMLElement;
|
||||
@ -49,12 +48,12 @@
|
||||
if (sid) deltasStore.setSessionId(sid);
|
||||
}
|
||||
|
||||
onMount(() =>
|
||||
unsubscribe(
|
||||
onMount(() => {
|
||||
return unsubscribe(
|
||||
hotkeys.on('Meta+Shift+R', () => goto(`/old/${$projectStore?.id}/player`)),
|
||||
hotkeys.on('Meta+Shift+S', () => syncToCloud($projectStore?.id))
|
||||
)
|
||||
);
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if $baseBranchesState.isLoading}
|
||||
@ -64,13 +63,13 @@
|
||||
{@const project = $projectStore}
|
||||
<div class="relative flex w-full max-w-full" role="group" on:dragover|preventDefault>
|
||||
<div bind:this={trayViewport} class="z-30 flex flex-shrink">
|
||||
{#if project}
|
||||
{#if $projectStore}
|
||||
<Navigation
|
||||
branchesWithContentStore={branchesWithContent}
|
||||
{remoteBranchStore}
|
||||
{baseBranchStore}
|
||||
{branchController}
|
||||
{project}
|
||||
project={$projectStore}
|
||||
githubContext={$githubContextStore}
|
||||
user={$userStore}
|
||||
{update}
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
<div class="h-full flex-grow overflow-y-auto overscroll-none p-3">
|
||||
<div
|
||||
class="flex min-w-min max-w-4xl flex-col gap-y-6 overflow-visible rounded-lg px-5 py-4"
|
||||
class="flex max-w-4xl flex-col gap-y-6 overflow-visible rounded-lg px-5 py-4"
|
||||
style:background-color="var(--bg-surface)"
|
||||
style:border-color="var(--border-surface)"
|
||||
>
|
||||
|
@ -1,32 +1,34 @@
|
||||
<script lang="ts">
|
||||
import type { Project } from '$lib/backend/projects';
|
||||
import { projectsStore, type Project } from '$lib/backend/projects';
|
||||
import IconButton from '$lib/components/IconButton.svelte';
|
||||
import TimeAgo from '$lib/components/TimeAgo.svelte';
|
||||
import Tooltip from '$lib/components/Tooltip.svelte';
|
||||
import IconBranch from '$lib/icons/IconBranch.svelte';
|
||||
import IconDropDown from '$lib/icons/IconDropDown.svelte';
|
||||
import IconGithub from '$lib/icons/IconGithub.svelte';
|
||||
import IconRefresh from '$lib/icons/IconRefresh.svelte';
|
||||
import type { BranchController } from '$lib/vbranches/branchController';
|
||||
import type { BaseBranch, CustomStore } from '$lib/vbranches/types';
|
||||
import type { Readable } from '@square/svelte-store';
|
||||
import ProjectsPopup from './ProjectsPopup.svelte';
|
||||
|
||||
export let project: Project;
|
||||
export let branchController: BranchController;
|
||||
export let baseBranchStore: CustomStore<BaseBranch | undefined>;
|
||||
|
||||
let popup: ProjectsPopup;
|
||||
let baseContents: HTMLElement;
|
||||
let fetching = false;
|
||||
</script>
|
||||
|
||||
<a
|
||||
href="/{project.id}/base"
|
||||
class="flex flex-col rounded-lg p-3"
|
||||
<div
|
||||
class="relative flex flex-col rounded-lg p-3"
|
||||
style:background-color="var(--bg-card)"
|
||||
tabindex="0"
|
||||
bind:this={baseContents}
|
||||
>
|
||||
<div class="flex flex-grow items-center">
|
||||
<div class="flex flex-grow items-center gap-1">
|
||||
<span class="font-bold">{project.title}</span>
|
||||
<a href="/{project.id}/base" class="font-bold">{project.title}</a>
|
||||
{#if ($baseBranchStore?.behind || 0) > 0}
|
||||
<Tooltip label="Unmerged upstream commits">
|
||||
<div
|
||||
@ -37,21 +39,25 @@
|
||||
</Tooltip>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex">
|
||||
<Tooltip label="Fetch from upstream">
|
||||
<IconButton
|
||||
class="items-center justify-center align-top hover:bg-light-150 dark:hover:bg-dark-700"
|
||||
on:click={(e) => {
|
||||
fetching = true;
|
||||
branchController.fetchFromTarget().finally(() => (fetching = false));
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
<div class:animate-spin={fetching}>
|
||||
<IconRefresh class="h-5 w-5" />
|
||||
</div>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<div class="flex gap-x-2">
|
||||
<IconButton
|
||||
class="items-center justify-center align-top "
|
||||
icon={IconDropDown}
|
||||
on:click={(e) => {
|
||||
popup.show();
|
||||
}}
|
||||
/>
|
||||
<IconButton
|
||||
class="items-center justify-center align-top "
|
||||
on:click={(e) => {
|
||||
fetching = true;
|
||||
branchController.fetchFromTarget().finally(() => (fetching = false));
|
||||
}}
|
||||
>
|
||||
<div class:animate-spin={fetching}>
|
||||
<IconRefresh class="h-4 w-4" />
|
||||
</div>
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-grow items-center text-sm">
|
||||
@ -71,4 +77,5 @@
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<ProjectsPopup bind:this={popup} projects={$projectsStore} />
|
||||
|
@ -43,7 +43,7 @@
|
||||
<div class="flex h-7 flex-shrink-0" data-tauri-drag-region>
|
||||
<!-- Top spacer & drag region -->
|
||||
</div>
|
||||
<div class="mx-4 mb-4 mt-1">
|
||||
<div class="relative mx-4 mb-4 mt-1">
|
||||
<BaseBranchCard {project} {branchController} {baseBranchStore} />
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
|
@ -0,0 +1,42 @@
|
||||
<script lang="ts">
|
||||
import type { Project } from '$lib/backend/projects';
|
||||
import Spacer from '../settings/Spacer.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { clickOutside } from './clickOutside';
|
||||
import * as events from '$lib/utils/events';
|
||||
|
||||
export let projects: Project[];
|
||||
let hidden = true;
|
||||
|
||||
export function show() {
|
||||
hidden = false;
|
||||
}
|
||||
|
||||
function changeProject(projectId: string) {
|
||||
goto(location.href.replace($page.params.projectId, projectId));
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if !hidden}
|
||||
<div
|
||||
class="absolute top-full z-30 mt-2 w-full rounded shadow"
|
||||
style:background-color="var(--bg-card-highlight)"
|
||||
use:clickOutside={() => {
|
||||
hidden = true;
|
||||
}}
|
||||
>
|
||||
{#each projects as project}
|
||||
<button class="block px-3 py-2" on:click={() => changeProject(project.id)}>
|
||||
{project.title}
|
||||
</button>
|
||||
<Spacer type="card" />
|
||||
{/each}
|
||||
<button
|
||||
class="px-3 py-2"
|
||||
on:click={() => {
|
||||
events.emit('openNewProjectModal');
|
||||
}}>Add project</button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
@ -0,0 +1,14 @@
|
||||
export function clickOutside(node: HTMLElement, handler: () => void): { destroy: () => void } {
|
||||
function onClick(event: MouseEvent) {
|
||||
if (node && !node.contains(event.target as HTMLElement)) {
|
||||
handler();
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('click', onClick, true);
|
||||
return {
|
||||
destroy() {
|
||||
document.removeEventListener('click', onClick, true);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,3 +1,10 @@
|
||||
<script lang="ts"></script>
|
||||
<script lang="ts">
|
||||
export let type: 'card' | 'surface' = 'surface';
|
||||
</script>
|
||||
|
||||
<div class="h-[0.0625rem] shrink-0" style:background-color="var(--bg-surface-highlight)" />
|
||||
<div
|
||||
class="h-[0.0625rem] shrink-0"
|
||||
style:background-color={type == 'surface'
|
||||
? 'var(--bg-surface-highlight)}'
|
||||
: 'var(--bg-card-highlight'}
|
||||
/>
|
||||
|
Loading…
Reference in New Issue
Block a user