diff --git a/bard-ai/Chats.ts b/bard-ai/Chats.ts index 213c8aa..71b3ef5 100644 --- a/bard-ai/Chats.ts +++ b/bard-ai/Chats.ts @@ -5,6 +5,7 @@ export type ChatsT = Array; export default class Chats { chat: Chat; chats: Array = []; + constructor() { this.chat = new Bard.Chat(); } @@ -21,4 +22,8 @@ export default class Chats { return response; } + + newChat = () => { + this.chat = new Bard.Chat(); + }; } diff --git a/package.json b/package.json index 1dd024f..000bed9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-sample-plugin", - "version": "0.1.3", + "version": "0.3.0", "description": "This is a sample plugin for Obsidian (https://obsidian.md)", "main": "main.js", "scripts": { diff --git a/src/components/View/execButtons/Refresh.tsx b/src/components/View/AppCommands/Refresh.tsx similarity index 100% rename from src/components/View/execButtons/Refresh.tsx rename to src/components/View/AppCommands/Refresh.tsx diff --git a/src/components/View/AppCommands/index.tsx b/src/components/View/AppCommands/index.tsx new file mode 100644 index 0000000..c357a7c --- /dev/null +++ b/src/components/View/AppCommands/index.tsx @@ -0,0 +1,34 @@ +import * as React from "react"; +import styled from "styled-components"; + +import { LucideIconButton } from "../../LucideIconButton"; +import RefreshButton from "../AppCommands/Refresh"; +import { MessageCircle } from "lucide-react"; +import { ChatGlobalContext } from "src/machines/chat.context"; + +const AppCommandButtonsContainer = styled.div` + width: 100%; + display: flex; + justify-content: center; + gap: 10px; +`; +export default function AppCommands() { + const globalContext = React.useContext(ChatGlobalContext); + + return ( + + + { + globalContext.chatService.send({ + type: "NEW_CHAT", + }); + }} + aria-label="New Chat" + aria-labeldelay="300" + > + + + + ); +} diff --git a/src/components/View/app.tsx b/src/components/View/app.tsx index fa0d472..1a4b428 100644 --- a/src/components/View/app.tsx +++ b/src/components/View/app.tsx @@ -1,15 +1,12 @@ import * as React from "react"; import styled from "styled-components"; -import { MessageCircle } from "lucide-react"; import { useApp } from "../hooks/useApp"; import ChatsSection from "./chats"; -import { LucideIconButton } from "../LucideIconButton"; -import RefreshButton from "./execButtons/Refresh"; - import ChatInput from "../chatInput"; +import AppCommands from "./AppCommands/index"; const AppContainer = styled.div` height: 100%; @@ -26,13 +23,6 @@ const CommandsAppContainer = styled.div` gap: 10px; `; -const AppCommandButtonsContainer = styled.div` - width: 100%; - display: flex; - justify-content: center; - gap: 10px; -`; - export default function ReactView() { const App = useApp(); @@ -47,15 +37,7 @@ export default function ReactView() { - - - - - - + diff --git a/src/components/View/chats.tsx b/src/components/View/chats.tsx index a2969ac..eb8db31 100644 --- a/src/components/View/chats.tsx +++ b/src/components/View/chats.tsx @@ -1,4 +1,4 @@ -import { Copy, Sparkles, User } from "lucide-react"; +import { Check, Copy, Sparkles, User } from "lucide-react"; import * as React from "react"; import styled from "styled-components"; import { LucideIconButton } from "../LucideIconButton"; @@ -8,6 +8,7 @@ import { useActor } from "@xstate/react"; import { queryBardValidRes } from "bard-ai"; import ReactMarkdown from "../memoizedMarkdownReact"; +import { Notice } from "obsidian"; const ChatsContainer = styled.div` display: flex; @@ -23,6 +24,10 @@ const ChatCardStyled = styled.div` flex-direction: column; justify-content: center; gap: 10px; + + li { + margin-bottom: 15px; + } } p { padding: 0; @@ -75,6 +80,23 @@ function RenderChatCard({ maxLen: number; idx: number; }) { + const [state, setState] = React.useState("idle"); + + const copyToClipboard = () => { + if (state == "idle") { + if (typeof chat == "string") navigator.clipboard.writeText(chat); + else { + navigator.clipboard.writeText(chat.content); + } + + setState("copied"); + new Notice("Copied to Clipboard!"); + setTimeout(() => { + setState("idle"); + }, 500); + } + }; + if (typeof chat == "string") { return ( @@ -107,8 +129,16 @@ function RenderChatCard({
- - + + {state == "copied" ? ( + + ) : ( + + )}
diff --git a/src/machines/chat.context.tsx b/src/machines/chat.context.tsx index 1f57e36..1ad6fd3 100644 --- a/src/machines/chat.context.tsx +++ b/src/machines/chat.context.tsx @@ -1,4 +1,4 @@ -import { ActorRefFrom } from "xstate"; +import { ActorRefFrom, assign } from "xstate"; import { chatMachine } from "./chat"; import * as React from "react"; import { useInterpret } from "@xstate/react"; @@ -34,6 +34,13 @@ export const ChatGlobalStateProvider = ({ }; }, }, + actions: { + newChat: assign((ctx, event) => { + newChat(); + + return Object.assign({}, { ...ctx, chats: [] }); + }), + }, }); return ( diff --git a/src/machines/chat.ts b/src/machines/chat.ts index a7c5bfb..ca4274c 100644 --- a/src/machines/chat.ts +++ b/src/machines/chat.ts @@ -23,6 +23,9 @@ export const chatMachine = createMachine( states: { inputting: { on: { + NEW_CHAT: { + actions: "newChat", + }, SUBMIT: { actions: assign< chatMachineContextT, diff --git a/src/plugin/view.tsx b/src/plugin/view.tsx index 5cc1fa7..df3d989 100644 --- a/src/plugin/view.tsx +++ b/src/plugin/view.tsx @@ -80,7 +80,10 @@ export class BardObsidianView extends ItemView { ); } - newChat() {} + newChat = () => { + console.log("new chat"); + this.chats.newChat(); + }; chatToBard = async (ask: string) => { console.log(ask);