Add first iteration of project switcher

- next to base refresh button
This commit is contained in:
Mattias Granlund 2023-11-12 21:43:22 +01:00
parent 6e2139b224
commit 6d0d34fa65
9 changed files with 143 additions and 50 deletions

View File

@ -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>

View 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>

View File

@ -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}

View File

@ -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)"
>

View File

@ -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} />

View File

@ -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">

View File

@ -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}

View File

@ -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);
}
};
}

View File

@ -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'}
/>