🚧 chat view WIP

This commit is contained in:
John Mavrick 2023-11-08 23:37:34 -08:00
parent e9ac83fd1b
commit 50debaa04d
7 changed files with 1874 additions and 339 deletions

38
main.ts
View File

@ -1,4 +1,5 @@
import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian';
import { App, Editor, MarkdownView, Modal, Plugin, PluginSettingTab, Setting } from 'obsidian';
import { AppView, VIEW_TYPE } from './src/ui/window';
// Remember to rename these classes and interfaces!
@ -12,14 +13,17 @@ const DEFAULT_SETTINGS: MyPluginSettings = {
export default class MyPlugin extends Plugin {
settings: MyPluginSettings;
view: AppView;
async onload() {
await this.loadSettings();
this.registerView(
VIEW_TYPE,
(leaf) => (new AppView(leaf, this))
);
// This creates an icon in the left ribbon.
const ribbonIconEl = this.addRibbonIcon('dice', 'Sample Plugin', (evt: MouseEvent) => {
// Called when the user clicks the icon.
new Notice('This is a notice!');
const ribbonIconEl = this.addRibbonIcon('dice', 'Open Agent View', (evt: MouseEvent) => {
this.activateView();
});
// Perform additional things with the ribbon
ribbonIconEl.addClass('my-plugin-ribbon-class');
@ -28,6 +32,15 @@ export default class MyPlugin extends Plugin {
const statusBarItemEl = this.addStatusBarItem();
statusBarItemEl.setText('Status Bar Text');
this.addCommand({
id: "habitica-view-open",
name: "Open Writing Assistant",
hotkeys: [{ modifiers: ["Mod", "Shift"], key: "h"}],
callback: () => {
this.activateView();
}
});
// This adds a simple command that can be triggered anywhere
this.addCommand({
id: 'open-sample-modal-simple',
@ -89,6 +102,19 @@ export default class MyPlugin extends Plugin {
async saveSettings() {
await this.saveData(this.settings);
}
async activateView() {
this.app.workspace.detachLeavesOfType(VIEW_TYPE);
await this.app.workspace.getRightLeaf(false).setViewState({
type: VIEW_TYPE,
active: true,
});
this.app.workspace.revealLeaf(
this.app.workspace.getLeavesOfType(VIEW_TYPE)[0]
);
}
}
class SampleModal extends Modal {
@ -131,4 +157,4 @@ class SampleSettingTab extends PluginSettingTab {
await this.plugin.saveSettings();
}));
}
}
}

2016
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,10 @@
"typescript": "4.7.4"
},
"dependencies": {
"openai": "^4.16.1"
"@types/react": "^18.2.37",
"@types/react-dom": "^18.2.15",
"openai": "^4.16.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}

44
src/ui/PluginView.tsx Normal file
View File

@ -0,0 +1,44 @@
import React, { useState } from 'react';
const PluginView = () => {
const [messages, setMessages] = useState([
{
type: 'received',
text: `# Please send me a message indicating the following:\n- The type of writing (e.g. essay, blog post, etc.)\n- Topic\n- Audience\n- Length (in words)\n- Structure (optional) (e.g. introduction, body, conclusion)`
},
{
type: 'sent',
text: 'Hello, how are you?'
}
]);
const [newMessage, setNewMessage] = useState('');
const handleSend = () => {
setMessages([...messages, { type: 'sent', text: newMessage }]);
setNewMessage('');
};
return (
<div className="agent-view-container">
<h2>Writing Assistant</h2>
<div className="chat-container">
{messages.map((message, index) => (
<div key={index} className={`chat-message ${message.type}`}>
<p className="text" dangerouslySetInnerHTML={{ __html: message.text.replace(/\n-/g, '<br/>-') }} />
</div>
))}
</div>
<div className="chat-input container">
<textarea
className="chat-input input"
placeholder="Type your message here..."
value={newMessage}
onChange={e => setNewMessage(e.target.value)}
/>
<button className="chat-input send" onClick={handleSend}>Send</button>
</div>
</div>
);
};
export default PluginView;

47
src/ui/window.tsx Normal file
View File

@ -0,0 +1,47 @@
import { ItemView,WorkspaceLeaf } from "obsidian";
import * as React from "react";
import { Root, createRoot } from "react-dom/client";
import PluginView from './PluginView';
import { App } from "obsidian";
import MyPlugin from '../../main'
export const VIEW_TYPE = "example-view";
export const AppContext = React.createContext<App | undefined>(undefined);
export const useApp = (): App | undefined => {
return React.useContext(AppContext);
};
export class AppView extends ItemView {
root: Root | null = null;
plugin: MyPlugin;
constructor(leaf: WorkspaceLeaf, plugin: MyPlugin) {
super(leaf)
this.plugin = plugin
}
getViewType() {
return VIEW_TYPE
}
getDisplayText() {
return "Habitica Pane"
}
getIcon(): string {
return "popup-open"
}
async onOpen() {
this.root = createRoot(this.containerEl.children[1]);
this.root.render(
<AppContext.Provider value={this.app}>
<PluginView />
</AppContext.Provider>
);
}
async onClose() {
this.root?.unmount();
}
}

View File

@ -1,8 +1,56 @@
/*
.agent-view-container {
height: 100%;
}
.chat-container {
width: 100%;
max-height: 100%;
margin: 0 auto;
padding: 20px;
overflow-y: scroll;
border: 1px solid var(--blockquote-border-color);
border-radius: 10px;
margin: 0.5rem 0;
display: flex;
flex-direction: column;
align-items: flex-start;
box-shadow: 0px 0px 10px rgba(0,0,0,0.1);
}
This CSS file will be included with your plugin, and
available in the app when your plugin is enabled.
.chat-message {
width: 90%;
padding: 10px;
margin-bottom: 10px;
border-radius: 5px;
}
If your plugin does not need CSS, delete this file.
.chat-message.sent {
background-color: var(--color-blue);
align-self: flex-end;
}
*/
.chat-message.received {
background-color: var(--color-base-50);
align-self: flex-start;
}
.chat-message p.text {
color: white;
}
.chat-input div.container {
display: flex;
max-height: 50%;
flex-direction: row;
justify-content: space-between;
margin-top: 10px;
}
.chat-input textarea.input {
max-height: 100%;
flex-grow: 1;
resize: vertical;
}
.chat-input button.send {
width: 15%;
}

View File

@ -1,5 +1,6 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"inlineSourceMap": true,
"inlineSources": true,
@ -10,6 +11,7 @@
"moduleResolution": "node",
"importHelpers": true,
"isolatedModules": true,
"jsx": "react",
"strictNullChecks": true,
"lib": [
"DOM",
@ -20,5 +22,5 @@
},
"include": [
"**/*.ts"
]
, "src/ui/window.tsx" ]
}