mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-20 08:01:46 +03:00
Added project avatar
This commit is contained in:
parent
ada64ac160
commit
40cc56db9b
@ -8,7 +8,7 @@
|
|||||||
import { navCollapsed } from '$lib/config/config';
|
import { navCollapsed } from '$lib/config/config';
|
||||||
import { persisted } from '$lib/persisted/persisted';
|
import { persisted } from '$lib/persisted/persisted';
|
||||||
import { SETTINGS_CONTEXT, type SettingsStore } from '$lib/settings/userSettings';
|
import { SETTINGS_CONTEXT, type SettingsStore } from '$lib/settings/userSettings';
|
||||||
import { platform } from '@tauri-apps/api/os';
|
import { type Platform, platform } from '@tauri-apps/api/os';
|
||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
import type { User } from '$lib/backend/cloud';
|
import type { User } from '$lib/backend/cloud';
|
||||||
import type { Project, ProjectService } from '$lib/backend/projects';
|
import type { Project, ProjectService } from '$lib/backend/projects';
|
||||||
@ -41,11 +41,12 @@
|
|||||||
$: isNavCollapsedPersist = navCollapsed();
|
$: isNavCollapsedPersist = navCollapsed();
|
||||||
let isNavCollapsed = $isNavCollapsedPersist;
|
let isNavCollapsed = $isNavCollapsedPersist;
|
||||||
|
|
||||||
// Detect is the platform is Mac
|
// Detect is the platform
|
||||||
let isMacos = false;
|
let platformName: Platform | undefined;
|
||||||
|
|
||||||
platform().then((name) => {
|
platform().then((name) => {
|
||||||
isMacos = name === 'darwin';
|
platformName = name;
|
||||||
|
console.log('platformName:', platformName);
|
||||||
});
|
});
|
||||||
|
|
||||||
// check if resizing
|
// check if resizing
|
||||||
@ -96,24 +97,29 @@
|
|||||||
|
|
||||||
{#if isNavCollapsed}
|
{#if isNavCollapsed}
|
||||||
<div class="collapsed-nav-wrapper">
|
<div class="collapsed-nav-wrapper">
|
||||||
<div class="card collapsed-nav">
|
{#if platformName}
|
||||||
<div class="collapsed-nav__info">
|
{#if platformName === 'darwin'}
|
||||||
<h3 class="collapsed-nav__label text-base-13 text-bold">
|
<div class="drag-region" data-tauri-drag-region />
|
||||||
{project?.title}
|
{/if}
|
||||||
</h3>
|
<div class="card collapsed-nav">
|
||||||
<DomainButton
|
<div class="collapsed-nav__info">
|
||||||
href={`/${project.id}/board`}
|
<h3 class="collapsed-nav__label text-base-13 text-bold">
|
||||||
domain="workspace"
|
{project?.title}
|
||||||
{branchController}
|
</h3>
|
||||||
{baseBranchService}
|
<DomainButton
|
||||||
{isNavCollapsed}
|
href={`/${project.id}/board`}
|
||||||
></DomainButton>
|
domain="workspace"
|
||||||
<BaseBranchCard {project} {baseBranchService} {githubService} {isNavCollapsed} />
|
{branchController}
|
||||||
|
{baseBranchService}
|
||||||
|
{isNavCollapsed}
|
||||||
|
></DomainButton>
|
||||||
|
<BaseBranchCard {project} {baseBranchService} {githubService} {isNavCollapsed} />
|
||||||
|
</div>
|
||||||
|
<div class="collapsed-nav__footer">
|
||||||
|
<Footer {user} projectId={project.id} {isNavCollapsed} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapsed-nav__footer">
|
{/if}
|
||||||
<Footer {user} projectId={project.id} {isNavCollapsed} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div
|
<div
|
||||||
@ -123,24 +129,26 @@
|
|||||||
role="menu"
|
role="menu"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
{#if isMacos}
|
{#if platformName}
|
||||||
<div class="drag-region" data-tauri-drag-region />
|
{#if platformName === 'darwin'}
|
||||||
{/if}
|
<div class="drag-region" data-tauri-drag-region />
|
||||||
<div class="navigation-top">
|
{/if}
|
||||||
<ProjectSelector {project} {projectService} />
|
<div class="navigation-top">
|
||||||
<div class="domains">
|
<ProjectSelector {project} {projectService} />
|
||||||
<BaseBranchCard {project} {baseBranchService} {githubService} {isNavCollapsed} />
|
<div class="domains">
|
||||||
<DomainButton
|
<BaseBranchCard {project} {baseBranchService} {githubService} {isNavCollapsed} />
|
||||||
href={`/${project.id}/board`}
|
<DomainButton
|
||||||
domain="workspace"
|
href={`/${project.id}/board`}
|
||||||
{branchController}
|
domain="workspace"
|
||||||
{baseBranchService}
|
{branchController}
|
||||||
{isNavCollapsed}
|
{baseBranchService}
|
||||||
></DomainButton>
|
{isNavCollapsed}
|
||||||
|
></DomainButton>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<Branches projectId={project.id} {branchService} {githubService} />
|
||||||
<Branches projectId={project.id} {branchService} {githubService} />
|
<Footer {user} projectId={project.id} {isNavCollapsed} />
|
||||||
<Footer {user} projectId={project.id} {isNavCollapsed} />
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</aside>
|
</aside>
|
||||||
@ -164,6 +172,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigation {
|
.navigation {
|
||||||
|
width: 17.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
69
gitbutler-ui/src/lib/components/ProjectAvatar.svelte
Normal file
69
gitbutler-ui/src/lib/components/ProjectAvatar.svelte
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export let name: string | undefined;
|
||||||
|
|
||||||
|
const gradients = [
|
||||||
|
'#E78D8D',
|
||||||
|
'#62CDCD',
|
||||||
|
'#EC90D2',
|
||||||
|
'#7DC8D8',
|
||||||
|
'#F1BC55',
|
||||||
|
'#6B6B4C',
|
||||||
|
'#9785DE',
|
||||||
|
'#99CE63',
|
||||||
|
'#636ECE',
|
||||||
|
'#5FD2B0'
|
||||||
|
];
|
||||||
|
|
||||||
|
const stringToGradient = (string: string | undefined) => {
|
||||||
|
if (!string) {
|
||||||
|
return `linear-gradient(45deg, ${gradients[0][0]} 15%, ${gradients[0][1]} 90%)`;
|
||||||
|
}
|
||||||
|
// trim the string, remove all spaces
|
||||||
|
const trimmedString = string.trim().replace(/\s/g, '');
|
||||||
|
|
||||||
|
// this is how we take the first letter. It works with emojies.
|
||||||
|
const startHash = trimmedString.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
|
||||||
|
|
||||||
|
// Covert the hash number into the number we can
|
||||||
|
const gradient = startHash % gradients.length;
|
||||||
|
|
||||||
|
// and return the linear-gradient
|
||||||
|
return gradients[gradient];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getFirstLetter = (name: string | undefined) => {
|
||||||
|
if (!name) return '';
|
||||||
|
return name[0].toUpperCase();
|
||||||
|
};
|
||||||
|
|
||||||
|
$: firstLetter = getFirstLetter(name);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="project-avatar" style:background-color={stringToGradient(name)}>
|
||||||
|
<svg class="avatar-letter" viewBox="0 0 24 24">
|
||||||
|
<text x="50%" y="52%" text-anchor="middle" alignment-baseline="middle">
|
||||||
|
{firstLetter.toUpperCase()}
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.project-avatar {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: var(--space-24);
|
||||||
|
height: var(--space-24);
|
||||||
|
border-radius: var(--radius-m);
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-letter {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-letter text {
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 16px;
|
||||||
|
fill: var(--clr-core-ntrl-100);
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import ProjectAvatar from './ProjectAvatar.svelte';
|
||||||
import ProjectsPopup from './ProjectsPopup.svelte';
|
import ProjectsPopup from './ProjectsPopup.svelte';
|
||||||
import { clickOutside } from '$lib/clickOutside';
|
import { clickOutside } from '$lib/clickOutside';
|
||||||
import Icon from '$lib/components/Icon.svelte';
|
import Icon from '$lib/components/Icon.svelte';
|
||||||
@ -11,43 +12,44 @@
|
|||||||
let visible: boolean = false;
|
let visible: boolean = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="wrapper">
|
<div
|
||||||
<div
|
class="wrapper"
|
||||||
class="relative"
|
use:clickOutside={{
|
||||||
use:clickOutside={{
|
handler: () => {
|
||||||
handler: () => {
|
popup.hide();
|
||||||
popup.hide();
|
visible = false;
|
||||||
visible = false;
|
},
|
||||||
},
|
enabled: visible
|
||||||
enabled: visible
|
}}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="button"
|
||||||
|
on:click={(e) => {
|
||||||
|
visible = popup.toggle();
|
||||||
|
e.preventDefault();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button
|
<ProjectAvatar name={project?.title} />
|
||||||
class="button"
|
<span class="button__label text-base-14 text-bold">{project?.title}</span>
|
||||||
on:click={(e) => {
|
<div class="button__icon">
|
||||||
visible = popup.toggle();
|
<Icon name="select-chevron" />
|
||||||
e.preventDefault();
|
</div>
|
||||||
}}
|
</button>
|
||||||
>
|
<ProjectsPopup bind:this={popup} {projectService} />
|
||||||
<span class="button__label text-base-14 text-bold">{project?.title}</span>
|
|
||||||
<div class="button__icon">
|
|
||||||
<Icon name="select-chevron" />
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<ProjectsPopup bind:this={popup} {projectService} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="postcss">
|
<style lang="postcss">
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
position: relative;
|
||||||
margin-top: var(--space-10);
|
margin-top: var(--space-10);
|
||||||
margin-bottom: var(--space-16);
|
margin-bottom: var(--space-16);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
gap: var(--space-10);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: var(--space-12);
|
padding: var(--space-10);
|
||||||
border-radius: var(--radius-m);
|
border-radius: var(--radius-m);
|
||||||
|
|
||||||
background-color: var(--clr-theme-container-pale);
|
background-color: var(--clr-theme-container-pale);
|
||||||
@ -75,6 +77,9 @@
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
color: var(--clr-theme-scale-ntrl-0);
|
color: var(--clr-theme-scale-ntrl-0);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button__icon {
|
.button__icon {
|
||||||
|
Loading…
Reference in New Issue
Block a user