Skip to content

Commit

Permalink
iframe
Browse files Browse the repository at this point in the history
  • Loading branch information
liangfung committed Apr 1, 2024
1 parent a8bd535 commit 34cef2b
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 150 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,9 @@ function createActionBarWidget(state: EditorState): Tooltip {
const lineTo = state.doc.lineAt(selection.main.to)
const isMultiline = lineFrom.number !== lineTo.number
const pos = isMultiline ? lineTo.from : selection.main.from
const text = state.doc.sliceString(
state.selection.main.from,
state.selection.main.to
) || ''
const text =
state.doc.sliceString(state.selection.main.from, state.selection.main.to) ||
''

return {
pos,
Expand Down
151 changes: 55 additions & 96 deletions ee/tabby-ui/app/files/components/completion-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,14 @@ import {
import { Chat, ChatRef } from '@/components/chat'
import { ClearChatsButton } from '@/components/clear-chats-button'
import { EditChatTitleDialog } from '@/components/edit-chat-title-dialog'
import LoadingWrapper from '@/components/loading-wrapper'
import { ListSkeleton } from '@/components/skeleton'

import { SourceCodeBrowserContext } from './source-code-browser'
import LoadingWrapper from '@/components/loading-wrapper'
import { CodeBrowserQuickAction } from '../lib/event-emitter'
import { SourceCodeBrowserContext } from './source-code-browser'

interface CompletionPanelProps
extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
// open: boolean
// onOpenChange: (v: boolean) => void
}

const emptyMessages: Message[] = []
extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {}

enum CompletionPanelView {
CHAT,
Expand All @@ -57,47 +52,20 @@ export const CompletionPanel: React.FC<CompletionPanelProps> = ({
setPendingEvent,
setCompletionPanelViewType
} = React.useContext(SourceCodeBrowserContext)
const _hasHydrated = useStore(useChatStore, state => state._hasHydrated)
const chats = useStore(useChatStore, state => state.chats)
const activeChatId = useStore(useChatStore, state => state.activeChatId)
const chatId = activeChatId
const chat = getChatById(chats, chatId)
const chatRef = React.useRef<ChatRef>(null)
const appending = React.useRef(false)

// const quickActionBarCallback = (action: CodeBrowserQuickAction) => {
// let builtInPrompt = ''
// switch (action) {
// case 'explain':
// builtInPrompt = 'Explain the following code:'
// break
// case 'generate_unittest':
// builtInPrompt = 'Generate a unit test for the following code:'
// break
// case 'generate_doc':
// builtInPrompt = 'Generate documentation for the following code:'
// break
// default:
// break
// }
// const view = editorRef.current?.editorView
// const text =
// view?.state.doc.sliceString(
// view?.state.selection.main.from,
// view?.state.selection.main.to
// ) || ''

// const initialMessage = `${builtInPrompt}\n${'```'}${
// language ?? ''
// }\n${text}\n${'```'}\n`
// if (initialMessage) {
// window.open(
// `/playground?initialMessage=${encodeURIComponent(initialMessage)}`
// )
// }
// }

const getPrompt = ({ action, payload }: { action: CodeBrowserQuickAction, payload: string }) => {
const iframeRef = React.useRef<HTMLIFrameElement>(null)

const getPrompt = ({
action,
payload
}: {
action: CodeBrowserQuickAction
payload: string
}) => {
let builtInPrompt = ''
switch (action) {
case 'explain':
Expand All @@ -116,43 +84,29 @@ export const CompletionPanel: React.FC<CompletionPanelProps> = ({
}

React.useEffect(() => {
if (chatRef.current?.append && pendingEvent) {
setCompletionPanelViewType(CompletionPanelView.CHAT)
if (!appending.current) {
appending.current = true
const contentWindow = iframeRef.current?.contentWindow

const prompt = getPrompt(pendingEvent as any)
if (pendingEvent) {
setCompletionPanelViewType(CompletionPanelView.CHAT)

chatRef.current
?.append({
role: 'user',
content: prompt
})
.then(() => {
setPendingEvent(undefined)
appending.current = false
})
if (!chat) {
addChat(activeChatId, truncateText(prompt))
}
}
contentWindow?.postMessage({
action: 'append',
payload: getPrompt(pendingEvent)
})
setPendingEvent(undefined)
}
}, [pendingEvent, chatRef.current?.append])
}, [pendingEvent, iframeRef.current?.contentWindow])

return (
<div className={cn('h-full overflow relative', className)} {...props}>
<div className={cn('h-full flex flex-col', className)} {...props}>
<Header />
{completionPanelViewType === CompletionPanelView.CHAT && (
<LoadingWrapper loading={!activeChatId}>
<Chat
id={activeChatId}
// loading={_hasHydrated}
chatPanelClassName="w-full bottom-0 absolute lg:ml-0"
initialMessages={chat?.messages ?? emptyMessages}
key={activeChatId}
ref={chatRef}
/>
</LoadingWrapper>
<iframe
src={`/playground`}
className="border-0 w-full flex-1"
key={activeChatId}
ref={iframeRef}
/>
)}
{completionPanelViewType === CompletionPanelView.SESSIONS && (
<ChatSessions />
Expand Down Expand Up @@ -247,30 +201,28 @@ function ChatSessions({ className }: { className?: string }) {
}

function Header() {
const {
completionPanelViewType,
setCompletionPanelViewType,
setCompletionPanelVisible
} = React.useContext(SourceCodeBrowserContext)
const { setCompletionPanelVisible } = React.useContext(
SourceCodeBrowserContext
)

const onToggleChatHistory = () => {
setCompletionPanelViewType(
completionPanelViewType === CompletionPanelView.CHAT
? CompletionPanelView.SESSIONS
: CompletionPanelView.CHAT
)
}
// const onToggleChatHistory = () => {
// setCompletionPanelViewType(
// completionPanelViewType === CompletionPanelView.CHAT
// ? CompletionPanelView.SESSIONS
// : CompletionPanelView.CHAT
// )
// }

const onNewChatClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setActiveChatId(nanoid())
if (completionPanelViewType === CompletionPanelView.SESSIONS) {
setCompletionPanelViewType(CompletionPanelView.CHAT)
}
}
// const onNewChatClick = (e: React.MouseEvent<HTMLButtonElement>) => {
// setActiveChatId(nanoid())
// if (completionPanelViewType === CompletionPanelView.SESSIONS) {
// setCompletionPanelViewType(CompletionPanelView.CHAT)
// }
// }

return (
<div className="flex items-center justify-between bg-secondary px-2 py-1">
<div className="flex items-center gap-2">
<div className="flex items-center justify-between bg-secondary px-2 py-1 sticky top-0">
{/* <div className="flex items-center gap-2">
<Tooltip>
<TooltipTrigger asChild>
<Button size="icon" variant="ghost" onClick={onToggleChatHistory}>
Expand All @@ -287,9 +239,16 @@ function Header() {
</TooltipTrigger>
<TooltipContent side="bottom">Start a new chat</TooltipContent>
</Tooltip>
</div>
</div> */}
<div className="w-8"></div>
<Image src={tabbyLogo} alt="logo" width={32} />
<IconClose onClick={e => setCompletionPanelVisible(false)} />
<Button
size="icon"
variant="ghost"
onClick={e => setCompletionPanelVisible(false)}
>
<IconClose />
</Button>
</div>
)
}
64 changes: 32 additions & 32 deletions ee/tabby-ui/app/files/components/file-directory-breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,40 @@ const FileDirectoryBreadcrumb: React.FC<FileDirectoryBreadcrumbProps> = ({
)

return (
<div
className={cn('flex flex-nowrap items-center gap-1 leading-8', className)}
>
<div
className="cursor-pointer font-medium text-primary hover:underline"
onClick={e => setActivePath(undefined)}
>
Repositories
</div>
<div>/</div>
{currentFileRoutes?.map((route, idx) => {
const isRepo = idx === 0 && currentFileRoutes?.length > 1
const isActiveFile = idx === currentFileRoutes.length - 1
<div className={cn('flex flex-nowrap items-center gap-1', className)}>
<div className="flex items-center gap-1 flex-1 truncate">
<div
className="cursor-pointer font-medium text-primary hover:underline"
onClick={e => setActivePath(undefined)}
>
Repositories
</div>
<div>/</div>
{currentFileRoutes?.map((route, idx) => {
const isRepo = idx === 0 && currentFileRoutes?.length > 1
const isActiveFile = idx === currentFileRoutes.length - 1

return (
<React.Fragment key={route.fullPath}>
<div
className={cn(
isRepo || isActiveFile ? 'font-bold' : 'font-medium',
isActiveFile
? ''
: 'cursor-pointer text-primary hover:underline',
isRepo ? 'hover:underline' : undefined
)}
onClick={e => setActivePath(route.fullPath)}
>
{route.name}
</div>
{route.file.kind !== 'file' && <div>/</div>}
</React.Fragment>
)
})}
return (
<React.Fragment key={route.fullPath}>
<div
className={cn(
isRepo || isActiveFile ? 'font-bold' : 'font-medium',
isActiveFile
? ''
: 'cursor-pointer text-primary hover:underline',
isRepo ? 'hover:underline' : undefined
)}
onClick={e => setActivePath(route.fullPath)}
>
{route.name}
</div>
{route.file.kind !== 'file' && <div>/</div>}
</React.Fragment>
)
})}
</div>
{!!currentFileRoutes?.length && !!activePath && (
<CopyButton value={activePath} />
<CopyButton className="shrink-0" value={activePath} />
)}
</div>
)
Expand Down
Loading

0 comments on commit 34cef2b

Please sign in to comment.