mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-24 05:29:51 +03:00
fix: cleanup dispatching contextMenu events
This commit is contained in:
parent
e062573c9f
commit
dac1af917b
@ -1,124 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { create } from '$lib/components/Differ/CodeHighlighter';
|
||||
import { SectionType } from '$lib/utils/fileSections';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import type { Line } from '$lib/utils/fileSections';
|
||||
|
||||
export let line: Line;
|
||||
export let sectionType: SectionType;
|
||||
export let filePath: string;
|
||||
export let minWidth = 1.75;
|
||||
export let selectable: boolean = false;
|
||||
export let selected: boolean = true;
|
||||
export let readonly: boolean = false;
|
||||
export let draggingDisabled: boolean = false;
|
||||
export let tabSize = 4;
|
||||
|
||||
const dispatch = createEventDispatcher<{ selected: boolean }>();
|
||||
|
||||
function toTokens(codeString: string): string[] {
|
||||
function sanitize(text: string) {
|
||||
var element = document.createElement('div');
|
||||
element.innerText = text;
|
||||
return element.innerHTML;
|
||||
}
|
||||
|
||||
let highlighter = create(codeString, filePath);
|
||||
let tokens: string[] = [];
|
||||
highlighter.highlight((text, classNames) => {
|
||||
const token = classNames
|
||||
? `<span class=${classNames}>${sanitize(text)}</span>`
|
||||
: sanitize(text);
|
||||
|
||||
tokens.push(token);
|
||||
});
|
||||
return tokens;
|
||||
}
|
||||
|
||||
$: isSelected = selectable && selected;
|
||||
</script>
|
||||
|
||||
<div class="code-line" role="group" style="--tab-size: {tabSize}" on:contextmenu|preventDefault>
|
||||
<div class="code-line__numbers-line">
|
||||
<button
|
||||
on:click={() => selectable && dispatch('selected', !selected)}
|
||||
class="numbers-line-count"
|
||||
class:selected={isSelected}
|
||||
style:min-width={minWidth + 'rem'}
|
||||
style:cursor={draggingDisabled ? 'default' : 'grab'}
|
||||
>
|
||||
{line.beforeLineNumber || ''}
|
||||
</button>
|
||||
<button
|
||||
on:click={() => selectable && dispatch('selected', !selected)}
|
||||
class="numbers-line-count"
|
||||
class:selected={isSelected}
|
||||
style:min-width={minWidth + 'rem'}
|
||||
style:cursor={draggingDisabled ? 'default' : 'grab'}
|
||||
>
|
||||
{line.afterLineNumber || ''}
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="line"
|
||||
class:readonly
|
||||
class:diff-line-deletion={sectionType === SectionType.RemovedLines}
|
||||
class:diff-line-addition={sectionType === SectionType.AddedLines}
|
||||
style:cursor={draggingDisabled ? 'default' : 'grab'}
|
||||
>
|
||||
<span class="selectable-wrapper" data-no-drag>
|
||||
{@html toTokens(line.content).join('')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.code-line {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-width: max-content;
|
||||
font-family: monospace;
|
||||
background-color: var(--clr-bg-1);
|
||||
white-space: pre;
|
||||
tab-size: var(--tab-size);
|
||||
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.line {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.code-line__numbers-line {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.numbers-line-count {
|
||||
color: var(--clr-text-3);
|
||||
border-color: var(--clr-border-2);
|
||||
background-color: var(--clr-bg-1-muted);
|
||||
font-size: 10px;
|
||||
flex-shrink: 0;
|
||||
user-select: none;
|
||||
border-right-width: 1px;
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
text-align: right;
|
||||
|
||||
&.selected {
|
||||
background-color: var(--hunk-line-selected-bg);
|
||||
border-color: var(--hunk-line-selected-border);
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.selectable-wrapper {
|
||||
cursor: text;
|
||||
display: inline-block;
|
||||
text-indent: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
</style>
|
@ -1,14 +1,8 @@
|
||||
<script lang="ts">
|
||||
import HunkContextMenu from './HunkContextMenu.svelte';
|
||||
import { Project } from '$lib/backend/projects';
|
||||
import { create } from '$lib/components/Differ/CodeHighlighter';
|
||||
import { getContext } from '$lib/utils/context';
|
||||
import { SectionType } from '$lib/utils/fileSections';
|
||||
import { onDestroy } from 'svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import type { Line } from '$lib/utils/fileSections';
|
||||
import type { ContentSection } from '$lib/utils/fileSections';
|
||||
import type { Hunk } from '$lib/vbranches/types';
|
||||
|
||||
export let lines: Line[];
|
||||
export let sectionType: SectionType;
|
||||
@ -19,26 +13,14 @@
|
||||
export let readonly: boolean = false;
|
||||
export let draggingDisabled: boolean = false;
|
||||
export let tabSize = 4;
|
||||
export let hunk: Hunk;
|
||||
export let subsection: ContentSection;
|
||||
|
||||
$: isSelected = selectable && selected;
|
||||
$: popupMenu = updateContextMenu(filePath);
|
||||
|
||||
const project = getContext(Project);
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
lineContextMenu: { lineNumber: number | undefined; event: MouseEvent };
|
||||
selected: boolean;
|
||||
}>();
|
||||
|
||||
function updateContextMenu(filePath: string) {
|
||||
if (popupMenu) popupMenu.$destroy();
|
||||
return new HunkContextMenu({
|
||||
target: document.body,
|
||||
props: { projectPath: project.vscodePath, filePath, readonly }
|
||||
});
|
||||
}
|
||||
|
||||
function toTokens(inputLine: string): string[] {
|
||||
function sanitize(text: string) {
|
||||
var element = document.createElement('div');
|
||||
@ -57,12 +39,6 @@
|
||||
});
|
||||
return tokens;
|
||||
}
|
||||
|
||||
onDestroy(() => {
|
||||
if (popupMenu) {
|
||||
popupMenu.$destroy();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div
|
||||
@ -75,15 +51,11 @@
|
||||
<div
|
||||
class="code-line"
|
||||
role="group"
|
||||
on:contextmenu={(e) => {
|
||||
on:contextmenu={(event) => {
|
||||
const lineNumber = line.afterLineNumber
|
||||
? line.afterLineNumber
|
||||
: line.beforeLineNumber;
|
||||
popupMenu.openByMouse(e, {
|
||||
hunk,
|
||||
lineNumber,
|
||||
section: subsection
|
||||
});
|
||||
dispatch('lineContextMenu', { event, lineNumber });
|
||||
}}
|
||||
>
|
||||
<div class="code-line__numbers-line">
|
@ -1,19 +1,22 @@
|
||||
<script lang="ts">
|
||||
import HunkSection from './HunkSection.svelte';
|
||||
import HunkContextMenu from './HunkContextMenu.svelte';
|
||||
import HunkLines from './HunkLines.svelte';
|
||||
import LargeDiffMessage from './LargeDiffMessage.svelte';
|
||||
import { Project } from '$lib/backend/projects';
|
||||
import { draggable } from '$lib/dragging/draggable';
|
||||
import { DraggableHunk } from '$lib/dragging/draggables';
|
||||
import { SETTINGS, type Settings } from '$lib/settings/userSettings';
|
||||
import { getContextStoreBySymbol, maybeGetContextStore } from '$lib/utils/context';
|
||||
import { getContext, getContextStoreBySymbol, maybeGetContextStore } from '$lib/utils/context';
|
||||
import { Ownership } from '$lib/vbranches/ownership';
|
||||
import { Branch, type Hunk } from '$lib/vbranches/types';
|
||||
import type { HunkSection as HunkSectionType } from '$lib/utils/fileSections';
|
||||
import { onDestroy } from 'svelte';
|
||||
import type { HunkSection } from '$lib/utils/fileSections';
|
||||
import type { Writable } from 'svelte/store';
|
||||
|
||||
export let viewport: HTMLDivElement | undefined = undefined;
|
||||
export let contents: HTMLDivElement | undefined = undefined;
|
||||
export let filePath: string;
|
||||
export let section: HunkSectionType;
|
||||
export let section: HunkSection;
|
||||
export let minWidth: number;
|
||||
export let selectable = false;
|
||||
export let isUnapplied: boolean;
|
||||
@ -24,6 +27,7 @@
|
||||
const selectedOwnership: Writable<Ownership> | undefined = maybeGetContextStore(Ownership);
|
||||
const userSettings = getContextStoreBySymbol<Settings>(SETTINGS);
|
||||
const branch = maybeGetContextStore(Branch);
|
||||
const project = getContext(Project);
|
||||
|
||||
function onHunkSelected(hunk: Hunk, isSelected: boolean) {
|
||||
if (!selectedOwnership) return;
|
||||
@ -33,9 +37,23 @@
|
||||
selectedOwnership.update((ownership) => ownership.remove(hunk.filePath, hunk.id));
|
||||
}
|
||||
}
|
||||
function updateContextMenu(filePath: string) {
|
||||
if (popupMenu) popupMenu.$destroy();
|
||||
return new HunkContextMenu({
|
||||
target: document.body,
|
||||
props: { projectPath: project.vscodePath, filePath, readonly }
|
||||
});
|
||||
}
|
||||
$: popupMenu = updateContextMenu(filePath);
|
||||
|
||||
$: draggingDisabled = readonly || isUnapplied;
|
||||
|
||||
onDestroy(() => {
|
||||
if (popupMenu) {
|
||||
popupMenu.$destroy();
|
||||
}
|
||||
});
|
||||
|
||||
let alwaysShow = false;
|
||||
</script>
|
||||
|
||||
@ -63,19 +81,24 @@
|
||||
{:else}
|
||||
{#each section.subSections as subsection}
|
||||
{@const hunk = section.hunk}
|
||||
<HunkSection
|
||||
<HunkLines
|
||||
lines={subsection.lines}
|
||||
{filePath}
|
||||
{readonly}
|
||||
{minWidth}
|
||||
{selectable}
|
||||
{draggingDisabled}
|
||||
{hunk}
|
||||
{subsection}
|
||||
tabSize={$userSettings.tabSize}
|
||||
selected={$selectedOwnership?.contains(hunk.filePath, hunk.id)}
|
||||
on:selected={(e) => onHunkSelected(hunk, e.detail)}
|
||||
sectionType={subsection.sectionType}
|
||||
on:lineContextMenu={(e) => {
|
||||
popupMenu.openByMouse(e.detail.event, {
|
||||
hunk,
|
||||
section: subsection,
|
||||
lineNumber: e.detail.lineNumber
|
||||
});
|
||||
}}
|
||||
/>
|
||||
{/each}
|
||||
{/if}
|
||||
|
Loading…
Reference in New Issue
Block a user