Open Khoj Chat as a Pane instead of a Modal

- Allows having it open on the side as you traverse your Obsidian notes
- Allow faster time to response, having responses visible for context
- Enables ambient interactions
This commit is contained in:
Debanjum Singh Solanky 2024-05-06 21:47:28 +08:00
parent 88daa841fd
commit 9f65e8de98
2 changed files with 49 additions and 13 deletions

View file

@ -1,6 +1,8 @@
import { App, MarkdownRenderer, Modal, request, requestUrl, setIcon } from 'obsidian';
import { ItemView, MarkdownRenderer, WorkspaceLeaf, request, requestUrl, setIcon } from 'obsidian';
import { KhojSetting } from 'src/settings';
export const KHOJ_CHAT_VIEW = "khoj-chat-view";
export interface ChatJsonResult {
image?: string;
detail?: string;
@ -9,7 +11,7 @@ export interface ChatJsonResult {
}
export class KhojChatModal extends Modal {
export class KhojChatView extends ItemView {
result: string;
setting: KhojSetting;
region: string;
@ -17,13 +19,13 @@ export class KhojChatModal extends Modal {
countryName: string;
timezone: string;
constructor(app: App, setting: KhojSetting) {
super(app);
constructor(leaf: WorkspaceLeaf, setting: KhojSetting) {
super(leaf);
this.setting = setting;
// Register Modal Keybindings to send user message
this.scope.register([], 'Enter', async () => { await this.chat() });
// this.scope.register([], 'Enter', async () => { await this.chat() });
fetch("https://ipapi.co/json")
.then(response => response.json())
@ -39,6 +41,18 @@ export class KhojChatModal extends Modal {
});
}
getViewType(): string {
return KHOJ_CHAT_VIEW;
}
getDisplayText(): string {
return "Khoj";
}
getIcon(): string {
return "message-circle";
}
async chat() {
// Get text in chat input element
let input_el = <HTMLTextAreaElement>this.contentEl.getElementsByClassName("khoj-chat-input")[0];
@ -503,7 +517,7 @@ export class KhojChatModal extends Modal {
event.preventDefault();
const transcribeButton = <HTMLButtonElement>this.contentEl.getElementsByClassName("khoj-transcribe")[0];
const chatInput = <HTMLTextAreaElement>this.contentEl.getElementsByClassName("khoj-chat-input")[0];
const sendButton = <HTMLButtonElement>this.modalEl.getElementsByClassName("khoj-chat-send")[0]
const sendButton = <HTMLButtonElement>this.contentEl.getElementsByClassName("khoj-chat-send")[0]
const generateRequestBody = async (audioBlob: Blob, boundary_string: string) => {
const boundary = `------${boundary_string}`;
@ -606,7 +620,7 @@ export class KhojChatModal extends Modal {
clearTimeout(this.sendMessageTimeout);
// Revert to showing send-button and hide the stop-send-button
let sendButton = <HTMLButtonElement>this.modalEl.getElementsByClassName("khoj-chat-send")[0];
let sendButton = <HTMLButtonElement>this.contentEl.getElementsByClassName("khoj-chat-send")[0];
setIcon(sendButton, "arrow-up-circle");
let sendImg = <SVGElement>sendButton.getElementsByClassName("lucide-arrow-up-circle")[0]
sendImg.addEventListener('click', async (_) => { await this.chat() });
@ -637,7 +651,7 @@ export class KhojChatModal extends Modal {
}
scrollChatToBottom() {
let sendButton = <HTMLButtonElement>this.modalEl.getElementsByClassName("khoj-chat-send")[0];
let sendButton = <HTMLButtonElement>this.contentEl.getElementsByClassName("khoj-chat-send")[0];
sendButton.scrollIntoView({ behavior: "auto", block: "center" });
}
}

View file

@ -1,7 +1,7 @@
import { Plugin } from 'obsidian';
import { Plugin, WorkspaceLeaf } from 'obsidian';
import { KhojSetting, KhojSettingTab, DEFAULT_SETTINGS } from 'src/settings'
import { KhojSearchModal } from 'src/search_modal'
import { KhojChatModal } from 'src/chat_modal'
import { KhojChatView, KHOJ_CHAT_VIEW } from 'src/chat_view'
import { updateContentIndex, canConnectToBackend } from './utils';
@ -30,12 +30,14 @@ export default class Khoj extends Plugin {
this.addCommand({
id: 'chat',
name: 'Chat',
callback: () => { new KhojChatModal(this.app, this.settings).open(); }
callback: () => { this.activateView(KHOJ_CHAT_VIEW); }
});
this.registerView(KHOJ_CHAT_VIEW, (leaf) => new KhojChatView(leaf, this.settings));
// Create an icon in the left ribbon.
this.addRibbonIcon('message-circle', 'Khoj', (_: MouseEvent) => {
new KhojChatModal(this.app, this.settings).open()
this.activateView(KHOJ_CHAT_VIEW);
});
// Add a settings tab so the user can configure khoj
@ -69,4 +71,24 @@ export default class Khoj extends Plugin {
this.unload();
}
async activateView(viewType: string) {
const { workspace } = this.app;
let leaf: WorkspaceLeaf | null = null;
const leaves = workspace.getLeavesOfType(viewType);
if (leaves.length > 0) {
// A leaf with our view already exists, use that
leaf = leaves[0];
} else {
// Our view could not be found in the workspace, create a new leaf
// in the right sidebar for it
leaf = workspace.getRightLeaf(false);
await leaf.setViewState({ type: viewType, active: true });
}
// "Reveal" the leaf in case it is in a collapsed sidebar
workspace.revealLeaf(leaf);
}
}