Skip to content

Commit

Permalink
Merge pull request #347 from laradumps/feature-code-snippet
Browse files Browse the repository at this point in the history
[Feature] Log thrown Exception with code snippet
  • Loading branch information
luanfreitasdev authored Nov 30, 2024
2 parents e080ec3 + 10519b9 commit 0904cf8
Show file tree
Hide file tree
Showing 16 changed files with 396 additions and 52 deletions.
5 changes: 3 additions & 2 deletions src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function createWindow(): BrowserWindow {
const browserWindowOptions: BrowserWindowConstructorOptions = {
fullscreen: false,
fullscreenable: false,
width: isDev ? 1080 : 650,
width: isDev ? 1080 : 690,
height: 640,
resizable: true,
alwaysOnTop: false,
Expand All @@ -64,7 +64,8 @@ function createWindow(): BrowserWindow {
}

if (isMac) {
browserWindowOptions.titleBarStyle = "hidden";
browserWindowOptions.titleBarStyle = "hiddenInset";
browserWindowOptions.trafficLightPosition = { x: 12, y: 11 };
}

const win: BrowserWindow = new BrowserWindow(browserWindowOptions);
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,6 @@ const dispatch = (type: string, event: EventType, content: any): void => {
const serializablePayload = JSON.parse(JSON.stringify(payload.value.filter((payload: Payload) => payload.screen?.screen_name === content.screen.screen_name)));
console.log(payload);
if (content.screen.new_window) {
screenStore.hidden(content.screen.screen_name);
Expand Down Expand Up @@ -789,6 +788,7 @@ function registerDefaultLocalShortcuts() {
}"
>
<div
id="dumps-base"
class="mb-[40px] w-full"
:class="{
'-mt-2': screenStore.screen !== 'Queries',
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/AppGuide.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const tips = ref([
<li><span>Menu -> IDE</span></li>
<li><span>PHPStorm, vs code, vs code remote ...</span></li>
</div>
</div>`,
</div>`
]);
const currentTip = computed(() => tips.value[currentIndex.value]);
Expand Down
230 changes: 230 additions & 0 deletions src/renderer/components/CodeSnippet.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
<script setup lang="ts">
import { computed, defineProps, onMounted, onUnmounted, ref } from "vue";
import { CodeSnippet, Payload } from "@/types/Payload";
import hljs from "highlight.js/lib/core";
import DumpLink from "@/components/DumpLink.vue";
import { useAppearanceStore } from "@/store/appearance";
import { IdeHandle } from "@/types/IdeHandle";
import IconArrowLight from "@/components/Icons/IconArrowLight.vue";
const containerSize = ref(0);
const activeFileIndex = ref(0);
const props = defineProps<{
payload: Payload;
}>();
onMounted(() => {
window.addEventListener("keydown", handleKeydown);
});
onUnmounted(() => {
window.removeEventListener("keydown", handleKeydown);
});
const totalFiles = computed(() => props.payload.code_snippet.length);
const toggleFileVisibility = (index: number) => {
activeFileIndex.value = activeFileIndex.value === index ? null : index;
};
const navigateFiles = (direction: "next" | "prev") => {
if (direction === "next") {
activeFileIndex.value = (activeFileIndex.value + 1) % totalFiles.value;
return;
}
if (direction === "prev") {
activeFileIndex.value = (activeFileIndex.value - 1 + totalFiles.value) % totalFiles.value;
}
};
const handleKeydown = (event: KeyboardEvent) => {
if (event.key === "ArrowRight") {
navigateFiles("next");
return;
}
if (event.key === "ArrowLeft") {
navigateFiles("prev");
}
};
const getFileLineDisplay = (codeSnippet: any) => {
return codeSnippet.route;
};
const getLineContent = (lineContent: string) => {
return hljs.highlight(lineContent, { language: "php" }).value;
};
const getIdeHandleFromStack = (codeSnippet: CodeSnippet, lineNumber: string): IdeHandle => {
return {
workdir: props.payload.ide_handle.workdir,
project_path: props.payload.ide_handle.project_path,
real_path: codeSnippet.file,
line: lineNumber,
class_name: props.payload.ide_handle.class_name,
separator: props.payload.ide_handle.separator,
wsl_config: props.payload.ide_handle.wsl_config
};
};
const observeContainer = (id: string) => {
const element = document.getElementById(id);
if (element) {
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
containerSize.value = entry.contentRect.width;
}
});
resizeObserver.observe(element);
}
};
const containerWidth = computed(() => containerSize.value - 58 + "px");
observeContainer("dumps-base");
</script>

<template>
<div
v-for="(codeSnippet, index) in props.payload.code_snippet"
:key="index"
>
<div
:class="{ '!font-semibold': activeFileIndex === index }"
class="text-base-content tracking-wide !font-normal break-all flex items-center gap-2 cursor-pointer hover:text-base-content"
@click="toggleFileVisibility(index)"
>
<IconArrowLight
v-if="activeFileIndex === index"
class="size-4"
/>
{{ getFileLineDisplay(codeSnippet) }}
</div>

<div
v-if="activeFileIndex === index"
class="code-snippet rounded-md scrollable mt-2"
:style="{ maxWidth: containerWidth }"
>
<div
:id="`current-snippet-${index}`"
v-for="(lineContent, lineNumber) in codeSnippet.snippet"
:key="`${lineNumber}-code`"
:class="{ 'bg-red-500/20 shadow-lg font-normal': parseInt(lineNumber) === codeSnippet.line }"
class="flex items-center tracking-widest leading-6 hover:!bg-red-500/20 px-2 group/line"
>
<DumpLink
class="font-normal h-full text-base-content text-[11px]"
:label="lineNumber"
:show-icon="true"
:ide-handler="getIdeHandleFromStack(codeSnippet, lineNumber)"
/>
<span
class="language-php py-1.5 highlight whitespace-pre hljs h-full text-xs text-primary font-normal"
v-html="getLineContent(lineContent)"
></span>
</div>
</div>
</div>
</template>

<style>
.code-snippet {
@apply bg-base-300 border border-base-content/20;
}
[data-theme="light"] .code-snippet {
@apply !bg-white border border-base-content/10;
}
.scrollable {
overflow-x: auto;
overflow-y: hidden;
}
.line-number {
@apply inline-block w-[40px] select-none text-base-content;
}
.hljs {
@apply !bg-transparent font-normal text-xs leading-8;
}
.hljs,
.hljs-params {
@apply !text-base-content/80;
}
.hljs-comment,
.hljs-quote {
@apply !text-[#5c6370] italic;
}
.hljs-doctag,
.hljs-formula,
.hljs-keyword {
@apply !text-[#c678dd];
}
.hljs-deletion,
.hljs-name,
.hljs-section,
.hljs-selector-tag,
.hljs-subst {
@apply !text-[#e06c75];
}
.hljs-literal {
@apply !text-[#56b6c2];
}
.hljs-addition,
.hljs-attribute,
.hljs-meta .hljs-string,
.hljs-regexp,
.hljs-meta,
.hljs-string {
@apply !text-[#98c379];
}
.hljs-attr,
.hljs-number,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-pseudo,
.hljs-template-variable,
.hljs-type,
.hljs-variable {
@apply text-rose-400 !important;
}
.hljs-bullet,
.hljs-link,
.hljs-meta,
.hljs-selector-id,
.hljs-symbol,
.hljs-title {
@apply text-blue-400 !important;
}
.hljs-built_in,
.hljs-class,
.hljs-title.class_ {
@apply text-orange-400 !important;
}
.hljs-emphasis {
@apply italic;
}
.hljs-strong {
@apply font-semibold;
}
.hljs-link {
@apply underline;
}
</style>
21 changes: 11 additions & 10 deletions src/renderer/components/DumpItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -116,22 +116,21 @@ const isDuplicated = (sql) => {
const badgeClasses = computed(() => {
const { label, color } = props.payload;
const baseClass =
"badge font-medium text-xs text-neutral-content bg-neutral border border-neutral-content/20 shadow-lg rounded-box w-auto";
const baseClass = "badge font-medium text-xs text-neutral-content bg-neutral border border-neutral-content/20 shadow-lg rounded-box w-auto";
const dynamicClass = {
'!bg-error !text-error-content': ['error', 'emergency'].includes(label) || color === 'red',
'!bg-info !text-info-content': label === 'info' || color === 'blue',
'!bg-warning !text-warning-content': label === 'warning' || color === 'orange',
'!bg-gray-400! text-warning-content': label === 'debug',
'!bg-success !text-success-content': color === 'green',
'!bg-black': color === 'black',
"!bg-error !text-error-content": ["error", "emergency"].includes(label) || color === "red",
"!bg-info !text-info-content": label === "info" || color === "blue",
"!bg-warning !text-warning-content": label === "warning" || color === "orange",
"!bg-gray-400! text-warning-content": label === "debug",
"!bg-success !text-success-content": color === "green",
"!bg-black": color === "black"
};
const additionalClasses = Object.entries(dynamicClass)
.filter(([_, condition]) => condition)
.map(([className]) => className)
.join(' ');
.join(" ");
return `${baseClass} ${additionalClasses}`;
});
Expand All @@ -149,6 +148,7 @@ watch(collapseStore, (value) => {
[bgColor]: typeof bgColor !== 'undefined',
'collapse-open': open
}"
id=""
class="collapse bg-base-200/70 bg-laravel border border-base-content/5"
>
<div
Expand Down Expand Up @@ -203,7 +203,8 @@ watch(collapseStore, (value) => {

<div
v-if="props.payload.type !== `queries`"
:class="badgeClasses">
:class="badgeClasses"
>
{{ props.payload.label ?? props.payload.type }}
</div>

Expand Down
Loading

0 comments on commit 0904cf8

Please sign in to comment.