Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 35 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
"devDependencies": {
"@electron-toolkit/preload": "^3.0.0",
"@electron-toolkit/utils": "^3.0.0",
"@iconify-json/tabler": "^1.2.33",
"@iconify/tailwind": "^1.2.0",
"@types/markdown-it": "^14.1.2",
"@types/node": "^25.2.3",
"@types/uuid": "^10.0.0",
Expand Down Expand Up @@ -70,8 +72,8 @@
{
"provider": "github",
"owner": "navidshad",
"repo": "vgtu-video-summarization"
"repo": "frameflow"
}
]
}
}
}
3 changes: 2 additions & 1 deletion src/renderer/src/components/graph/ChatInputNode.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<template>
<div class="glass-card glass-card-hover input-focus-ring p-3 rounded-2xl min-w-[320px]">
<div class="glass-card glass-card-hover input-focus-ring p-3 rounded-2xl min-w-[320px] cursor-move">
<Handle type="target" :position="Position.Top" class="w-3 h-3 bg-zinc-300 dark:bg-zinc-600 border-2 border-white dark:border-zinc-800" />

<BaseMessageInput
v-model="input"
v-model:attachedImages="attachedImages"
placeholder="Ask for summary, cover, etc..."
compact
class="nodrag interactive-in-pan"
@send="submit"
/>
</div>
Expand Down
20 changes: 10 additions & 10 deletions src/renderer/src/components/graph/ConversationNode.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="glass-card p-0 rounded-3xl min-w-[320px] overflow-hidden flex flex-col group relative"
<div class="glass-card p-0 rounded-3xl min-w-[320px] overflow-hidden flex flex-col group relative cursor-move"
:class="[isResizing ? '' : 'glass-card-hover transition-all duration-500']"
:style="{ width: nodeWidth + 'px', maxWidth: '800px' }">
<!-- Resize Handle -->
Expand All @@ -12,8 +12,8 @@

<!-- Header with Actions -->
<div
class="px-4 py-2 bg-black/5 dark:bg-white/5 border-b border-black/5 dark:border-white/5 flex items-center justify-between">
<div class="flex items-center space-x-2">
class="px-4 py-2 bg-black/5 dark:bg-white/5 border-b border-black/5 dark:border-white/5 flex items-center justify-between cursor-move">
<div class="flex items-center space-x-2 cursor-move">
<div class="w-2 h-2 rounded-full bg-primary shadow-[0_0_8px_rgba(var(--primary),0.5)]"></div>
<span
class="text-[10px] font-black uppercase tracking-widest text-zinc-500 dark:text-zinc-400">Conversation</span>
Expand Down Expand Up @@ -87,16 +87,16 @@
</div>
<template v-else>
<div v-html="renderMarkdown(msg.content)"
class="prose prose-sm max-w-none prose-p:my-0 prose-ul:my-2 prose-ol:my-2 prose-li:my-0 shadow-none border-none pointer-events-auto"
class="prose prose-sm max-w-none prose-p:my-0 prose-ul:my-2 prose-ol:my-2 prose-li:my-0 shadow-none border-none pointer-events-auto nodrag select-text cursor-text"
:class="msg.role === 'user' ? 'prose-invert text-white' : 'dark:prose-invert'"></div>
</template>

<!-- Attached Images -->
<div v-if="msg.attachedImages && msg.attachedImages.length > 0" class="mt-2 mb-1 flex flex-wrap gap-1.5">
<div v-if="msg.attachedImages && msg.attachedImages.length > 0" class="mt-2 mb-1 flex flex-wrap gap-1.5 nodrag">
<div v-for="(img, idx) in msg.attachedImages" :key="idx"
class="relative w-10 h-10 rounded-lg overflow-hidden group/img cursor-pointer transition-all duration-300 hover:scale-[1.1] shadow-sm border border-black/5 dark:border-white/10"
@click="openPreview(img)">
<img :src="mediaUrl(img)" class="w-full h-full object-cover" />
<img :src="mediaUrl(img)" class="w-full h-full object-cover" draggable="false" />
<div
class="absolute inset-0 bg-black/20 opacity-0 group-hover/img:opacity-100 transition-opacity flex items-center justify-center">
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
Expand All @@ -109,13 +109,13 @@

<!-- Files -->
<div v-if="msg.files && msg.files.filter((f: any) => f.type !== 'original').length > 0"
class="mt-3 space-y-2">
class="mt-3 space-y-2 nodrag">
<div v-for="file in msg.files.filter((f: any) => f.type !== 'original')" :key="file.url"
class="group/file p-2 bg-black/5 dark:bg-white/5 rounded-xl border border-black/5 dark:border-white/10 hover:border-primary/30 transition-all overflow-hidden">
class="group/file p-2 bg-black/5 dark:bg-white/5 rounded-xl border border-black/5 dark:border-white/10 hover:border-primary/30 transition-all overflow-hidden cursor-default">
<div v-if="file.url.match(/\.(jpg|jpeg|png|webp)$/i) || file.type === 'preview' || file.type === 'actual'"
class="mb-2 rounded-lg overflow-hidden border border-black/10 dark:border-white/10 aspect-video bg-black/20">
<img :src="mediaUrl(file.url)"
class="w-full h-full object-cover group-hover/file:scale-110 transition-transform duration-500" />
class="w-full h-full object-cover group-hover/file:scale-110 transition-transform duration-500" draggable="false" />
</div>

<div class="flex items-center justify-between gap-2">
Expand Down Expand Up @@ -186,7 +186,7 @@
<!-- Input Section -->
<BaseMessageInput v-if="data.hasInputInitially || showInput" v-model="input" v-model:attachedImages="attachedImages"
:placeholder="data.hasInputInitially ? 'Ask a follow-up...' : 'Branch from here...'" compact submitIcon="IconSend"
class="p-2 border-t border-black/5 dark:border-white/5 bg-black/[0.02] dark:bg-white/[0.02]" @send="submit" />
class="p-2 border-t border-black/5 dark:border-white/5 bg-black/[0.02] dark:bg-white/[0.02] nodrag interactive-in-pan" @send="submit" />

<Handle type="source" :position="Position.Bottom"
class="w-3 h-3 bg-blue-500 border-2 border-white dark:border-zinc-800" />
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/src/components/graph/FrameNode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class="frame-node rounded-[2rem] border-2 border-dashed relative group"
:class="[
selected ? 'border-primary bg-primary/5 ring-4 ring-primary/10' : 'border-zinc-300 dark:border-zinc-700 bg-zinc-400/5 dark:bg-zinc-400/5',
isResizing ? 'cursor-nwse-resize' : ''
isResizing ? 'cursor-nwse-resize' : (data.isLocked ? 'cursor-default' : 'cursor-move')
]"
:style="{
width: `${nodeWidth}px`,
Expand Down
41 changes: 15 additions & 26 deletions src/renderer/src/components/graph/GraphToolbar.vue
Original file line number Diff line number Diff line change
@@ -1,49 +1,38 @@
<template>
<div class="absolute left-6 top-6 z-30 flex items-center bg-zinc-100/80 dark:bg-zinc-900/80 backdrop-blur-md rounded-xl p-1 border border-zinc-200 dark:border-zinc-800 shadow-lg">
<SlimTooltip text="Pan View" placement="bottom">
<button
@click="$emit('update:modelValue', 'pan')"
<div
class="absolute left-6 top-6 z-30 flex items-center bg-zinc-100/80 dark:bg-zinc-900/80 backdrop-blur-md rounded-xl p-1 border border-zinc-200 dark:border-zinc-800 shadow-lg">
<SlimTooltip text="Pan Tool" placement="bottom">
<button @click="$emit('update:modelValue', 'pan')"
class="flex items-center justify-center w-9 h-9 rounded-lg transition-all duration-300"
:class="modelValue === 'pan' ? 'bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 shadow-sm ring-1 ring-zinc-200 dark:ring-zinc-700' : 'text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 hover:bg-zinc-200/50 dark:hover:bg-zinc-800/50'"
>
<svg class="w-4.5 h-4.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5"></path>
</svg>
:class="modelValue === 'pan' ? 'bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 shadow-sm ring-1 ring-zinc-200 dark:ring-zinc-700' : 'text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 hover:bg-zinc-200/50 dark:hover:bg-zinc-800/50'">
<Icon name="iconify tabler--hand-stop" class="w-5 h-5" />
</button>
</SlimTooltip>

<div class="w-px h-4 bg-zinc-200 dark:bg-zinc-800 mx-1"></div>

<SlimTooltip text="Select Tool" placement="bottom">
<button
@click="$emit('update:modelValue', 'select')"
<button @click="$emit('update:modelValue', 'select')"
class="flex items-center justify-center w-9 h-9 rounded-lg transition-all duration-300"
:class="modelValue === 'select' ? 'bg-primary text-white shadow-md shadow-primary/20 ring-1 ring-primary/20' : 'text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 hover:bg-zinc-200/50 dark:hover:bg-zinc-800/50'"
>
<svg class="w-4.5 h-4.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<rect x="4" y="4" width="16" height="16" rx="2" stroke-width="2.5" stroke="currentColor" fill="none" stroke-dasharray="4 2"></rect>
<path d="M7 7h1v1H7zM16 7h1v1h-1zM7 16h1v1H7zM16 16h1v1h-1z" fill="currentColor"></path>
</svg>
:class="modelValue === 'select' ? 'bg-primary text-white shadow-md shadow-primary/20 ring-1 ring-primary/20' : 'text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 hover:bg-zinc-200/50 dark:hover:bg-zinc-800/50'">
<Icon name="iconify tabler--pointer" class="w-5 h-5" />
</button>
</SlimTooltip>

<div class="w-px h-4 bg-zinc-200 dark:bg-zinc-800 mx-1"></div>

<SlimTooltip text="Group Frames" placement="bottom">
<button
@click="$emit('update:modelValue', 'frame')"
<button @click="$emit('update:modelValue', 'frame')"
class="flex items-center justify-center w-9 h-9 rounded-lg transition-all duration-300"
:class="modelValue === 'frame' ? 'bg-secondary text-white shadow-md shadow-secondary/20 ring-1 ring-secondary/20' : 'text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 hover:bg-zinc-200/50 dark:hover:bg-zinc-800/50'"
>
<svg class="w-4.5 h-4.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M4 5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5zM14 5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1V5zM4 15a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-4zM14 15a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1v-4z" />
</svg>
:class="modelValue === 'frame' ? 'bg-secondary text-white shadow-md shadow-secondary/20 ring-1 ring-secondary/20' : 'text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 hover:bg-zinc-200/50 dark:hover:bg-zinc-800/50'">
<Icon name="iconify tabler--layout-grid" class="w-5 h-5" />
</button>
</SlimTooltip>
</div>
</template>

<script setup lang="ts">
import { Icon, IconButton } from 'pilotui/elements'
import SlimTooltip from '../SlimTooltip.vue'
type ToolMode = 'pan' | 'select' | 'frame'

Expand Down
14 changes: 7 additions & 7 deletions src/renderer/src/components/graph/ImageCollectionNode.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<template>
<div class="glass-card glass-card-hover p-0 rounded-3xl min-w-[300px] max-w-[340px] overflow-hidden flex flex-col group transition-all duration-300">
<div class="glass-card glass-card-hover p-0 rounded-3xl min-w-[300px] max-w-[340px] overflow-hidden flex flex-col group transition-all duration-300 cursor-move">
<Handle v-if="data.hasInput !== false" type="target" :position="Position.Top" class="w-3 h-3 bg-zinc-500 border-2 border-white dark:border-zinc-800" />

<!-- Gallery Section -->
<div class="p-4 bg-zinc-950/5 dark:bg-black/40 border-b border-black/5 dark:border-white/5">
<div class="p-4 bg-zinc-950/5 dark:bg-black/40 border-b border-black/5 dark:border-white/5 cursor-move">
<div class="flex items-center justify-between mb-3">
<div class="flex flex-col">
<div class="text-[10px] text-zinc-500 uppercase tracking-[0.2em] font-black leading-none mb-1">Source Collection</div>
Expand All @@ -19,10 +19,10 @@
<div
v-for="(img, idx) in visibleImages"
:key="idx"
class="relative aspect-square rounded-xl overflow-hidden border border-black/5 dark:border-white/10 group/img cursor-pointer"
class="relative aspect-square rounded-xl overflow-hidden border border-black/5 dark:border-white/10 group/img cursor-pointer nodrag"
@click="openLightbox(idx)"
>
<img :src="mediaUrl(img)" class="w-full h-full object-cover transition-transform duration-500 group-hover/img:scale-110" />
<img :src="mediaUrl(img)" class="w-full h-full object-cover transition-transform duration-500 group-hover/img:scale-110" draggable="false" />
<div v-if="idx === 5 && sourceImages.length > 6" class="absolute inset-0 bg-black/60 backdrop-blur-[2px] flex items-center justify-center text-white text-xs font-bold font-mono">
+{{ sourceImages.length - 6 }}
</div>
Expand All @@ -31,8 +31,8 @@
</div>

<!-- Active Tasks Progress -->
<div v-if="activeTasks.length > 0" class="p-3 bg-white/5 border-b border-white/5 space-y-2">
<div v-for="task in activeTasks" :key="task.id" class="text-[10px]">
<div v-if="activeTasks.length > 0" class="p-3 bg-white/5 border-b border-white/5 space-y-2 nodrag cursor-text">
<div v-for="task in activeTasks" :key="task.id" class="text-[10px] select-text">
<div class="flex justify-between items-center mb-1 text-zinc-400">
<span class="truncate pr-2 font-bold uppercase tracking-tight">{{ task.status || task.name }}</span>
<span>{{ task.progress !== undefined ? `${task.progress}%` : '' }}</span>
Expand All @@ -48,7 +48,7 @@
v-model:attachedImages="attachedImages"
placeholder="Start a new analysis..."
compact
class="p-2 border-t border-black/5 dark:border-white/5 bg-black/[0.02] dark:bg-white/[0.02]"
class="p-2 border-t border-black/5 dark:border-white/5 bg-black/[0.02] dark:bg-white/[0.02] nodrag"
@send="submit"
/>

Expand Down
14 changes: 7 additions & 7 deletions src/renderer/src/components/graph/MediaNode.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<template>
<div class="glass-card glass-card-hover p-0 rounded-3xl min-w-[280px] max-w-[320px] overflow-hidden flex flex-col group transition-all duration-300">
<div class="glass-card glass-card-hover p-0 rounded-3xl min-w-[280px] max-w-[320px] overflow-hidden flex flex-col group transition-all duration-300 cursor-move">
<Handle v-if="data.hasInput !== false" type="target" :position="Position.Top" class="w-3 h-3 bg-zinc-500 border-2 border-white dark:border-zinc-800" />

<!-- Video Preview Section -->
<div class="relative aspect-video bg-black overflow-hidden group/player">
<div class="relative aspect-video bg-black overflow-hidden group/player cursor-move">
<video
v-if="videoUrl"
ref="videoRef"
Expand Down Expand Up @@ -48,8 +48,8 @@
</div>

<!-- Metadata Details Section -->
<div v-if="showDetails" class="px-4 py-3 bg-white/5 border-b border-white/5 space-y-2 animate-in slide-in-from-top duration-300">
<div class="grid grid-cols-2 gap-3">
<div v-if="showDetails" class="px-4 py-3 bg-white/5 border-b border-white/5 space-y-2 animate-in slide-in-from-top duration-300 nodrag cursor-text">
<div class="grid grid-cols-2 gap-3 select-text">
<div class="flex flex-col gap-0.5">
<span class="text-[9px] font-bold text-zinc-500 dark:text-zinc-500 uppercase tracking-widest">Resolution</span>
<span class="text-[11px] text-zinc-700 dark:text-zinc-200 font-mono">{{ metadata?.width }}x{{ metadata?.height }}</span>
Expand Down Expand Up @@ -78,8 +78,8 @@
</div>

<!-- Background Tasks Progress -->
<div v-if="activeTasks.length > 0" class="p-3 bg-white/5 border-b border-white/5 space-y-2">
<div v-for="task in activeTasks" :key="task.id" class="text-[10px]">
<div v-if="activeTasks.length > 0" class="p-3 bg-white/5 border-b border-white/5 space-y-2 nodrag cursor-text">
<div v-for="task in activeTasks" :key="task.id" class="text-[10px] select-text">
<div class="flex justify-between items-center mb-1 text-zinc-400">
<span class="truncate pr-2 font-bold uppercase tracking-tight">{{ task.status || task.name }}</span>
<span>{{ task.progress !== undefined ? `${task.progress}%` : '' }}</span>
Expand All @@ -95,7 +95,7 @@
v-model:attachedImages="attachedImages"
placeholder="Start a new analysis..."
compact
class="p-2 border-t border-black/5 dark:border-white/5 bg-black/[0.02] dark:bg-white/[0.02]"
class="p-2 border-t border-black/5 dark:border-white/5 bg-black/[0.02] dark:bg-white/[0.02] nodrag"
@send="submit"
/>

Expand Down
6 changes: 3 additions & 3 deletions src/renderer/src/components/graph/MessageNode.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div
class="glass-card glass-card-hover p-4 rounded-2xl min-w-[200px] max-w-[300px]"
class="glass-card glass-card-hover p-4 rounded-2xl min-w-[200px] max-w-[300px] cursor-move"
:class="[
data.sender === 'user'
? 'bg-primary/10 border-primary/20 text-primary-dark shadow-sm shadow-primary/5'
Expand All @@ -14,12 +14,12 @@
<button
v-if="data.sender === 'user'"
@click.stop="videoStore.retryMessage(id)"
class="bg-blue-100 dark:bg-zinc-700/50 hover:bg-blue-200 dark:hover:bg-zinc-600 rounded px-1.5 py-0.5 text-[9px] uppercase font-bold transition-colors cursor-pointer pointer-events-auto"
class="bg-blue-100 dark:bg-zinc-700/50 hover:bg-blue-200 dark:hover:bg-zinc-600 rounded px-1.5 py-0.5 text-[9px] uppercase font-bold transition-colors cursor-pointer pointer-events-auto nodrag"
>
Retry
</button>
</div>
<div class="text-sm whitespace-pre-wrap leading-snug">{{ data.text }}</div>
<div class="text-sm whitespace-pre-wrap leading-snug nodrag select-text cursor-text">{{ data.text }}</div>

<Handle type="source" :position="Position.Bottom" class="w-3 h-3 bg-blue-500 border-2 border-white dark:border-zinc-800" />
</div>
Expand Down
Loading
Loading