diff --git a/Assets/vaultkeeper-mono.svg b/Assets/vaultkeeper-mono.svg new file mode 100644 index 0000000..2a7ad97 --- /dev/null +++ b/Assets/vaultkeeper-mono.svg @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/Assets/vaultkeeper-social-1280x330.png b/Assets/vaultkeeper-social-1280x330.png new file mode 100644 index 0000000..5863ab8 Binary files /dev/null and b/Assets/vaultkeeper-social-1280x330.png differ diff --git a/Enums/Copy.ts b/Enums/Copy.ts index 79acb97..21ec19f 100644 --- a/Enums/Copy.ts +++ b/Enums/Copy.ts @@ -223,7 +223,7 @@ If you find any issues or have a feature request, please feel free to raise them 1. **Add an API key**: Go to Settings and add at least one API key (Claude, Gemini, OpenAI, or Mistral) 2. **Select a model**: Choose your preferred AI model from the dropdown -3. **Open the chat**: Click the sparkles icon in the sidebar to start chatting`, +3. **Open the chat**: Click the plugin icon in the sidebar to start chatting`, HelpModalChatModesTitle = "Chat modes", HelpModalChatModesContent = `#### Chat modes diff --git a/Modals/HelpModalSvelte.svelte b/Modals/HelpModalSvelte.svelte index f63b681..cf97247 100644 --- a/Modals/HelpModalSvelte.svelte +++ b/Modals/HelpModalSvelte.svelte @@ -8,11 +8,13 @@ import type { WorkSpaceService } from "Services/WorkSpaceService"; import { fade } from "svelte/transition"; import { onMount } from "svelte"; + import type { AssetsService } from "Services/AssetsService"; export let onClose: () => void; export let initialTopic: number = 1; const plugin: VaultkeeperAIPlugin = Resolve(Services.VaultkeeperAIPlugin); + const assetsService: AssetsService = Resolve(Services.AssetsService); const streamingMarkdownService: StreamingMarkdownService = Resolve(Services.StreamingMarkdownService); const workSpaceService: WorkSpaceService = Resolve(Services.WorkSpaceService); @@ -166,6 +168,9 @@
{#if contentVisible} + {#if selectedTopic === 1} + Plugin Banner + {/if}
{#if selectedTopic === 1} @@ -190,7 +195,7 @@ {Copy.CoffeeIcon} {Copy.CoffeeLinkText} -

{Copy.ThankYouMessage}

+

{Copy.ThankYouMessage}

{/if}
{#if selectedTopic === 1} @@ -323,6 +328,13 @@ overflow-y: auto; } + .help-modal-banner { + margin-top: var(--size-2-2); + margin-left: calc(var(--size-4-2) * -1); + width: calc(100% + (var(--size-4-2) * 2) - var(--size-2-2)); + border-radius: var(--radius-s); + } + .help-modal-version-string { /* Absorbs leftover vertical space so the version sits bottom-right on tall screens, but collapses and scrolls naturally when content overflows. */ diff --git a/Services/AssetsService.ts b/Services/AssetsService.ts new file mode 100644 index 0000000..7b39fd1 --- /dev/null +++ b/Services/AssetsService.ts @@ -0,0 +1,33 @@ +import type VaultkeeperAIPlugin from "main"; +import { Resolve } from "./DependencyService"; +import { Services } from "./Services"; +import { addIcon } from "obsidian"; + +export class AssetsService { + + private readonly plugin: VaultkeeperAIPlugin; + + public pluginIcon: string = ""; + public bannerSource: string = ""; + + public constructor() { + this.plugin = Resolve(Services.VaultkeeperAIPlugin); + } + + public async loadAssets(): Promise { + this.pluginIcon = this.addIcon( + await this.plugin.app.vault.adapter.read(`${this.plugin.manifest.dir}/Assets/vaultkeeper-mono.svg`), + "vaultkeeper-ai-icon" + ); + + this.bannerSource = this.plugin.app.vault.adapter.getResourcePath( + `${this.plugin.manifest.dir}/Assets/vaultkeeper-social-1280x330.png` + ); + } + + private addIcon(icon: string, name: string): string { + addIcon(name, icon); + return name; + } + +} \ No newline at end of file diff --git a/Services/QuickActions/QuickActionsService.ts b/Services/QuickActions/QuickActionsService.ts index 568bfe1..16c5a9f 100644 --- a/Services/QuickActions/QuickActionsService.ts +++ b/Services/QuickActions/QuickActionsService.ts @@ -6,10 +6,12 @@ import type { SettingsService } from "Services/SettingsService"; import { WorkSpaceService } from "Services/WorkSpaceService"; import type { QuickActionsDefinitionsService } from "./QuickActionsDefinitionsService"; import type { HelpModal } from "Modals/HelpModal"; +import { AssetsService } from "Services/AssetsService"; export class QuickActionsService { private readonly plugin: VaultkeeperAIPlugin; + private readonly assetsService: AssetsService; private readonly settingsService: SettingsService; private readonly workSpaceService: WorkSpaceService; private readonly quickActionsDefinitionsService: QuickActionsDefinitionsService; @@ -21,6 +23,7 @@ export class QuickActionsService { public constructor() { this.plugin = Resolve(Services.VaultkeeperAIPlugin); + this.assetsService = Resolve(Services.AssetsService); this.settingsService = Resolve(Services.SettingsService); this.workSpaceService = Resolve(Services.WorkSpaceService); this.quickActionsDefinitionsService = Resolve(Services.QuickActionsDefinitionsService); @@ -181,7 +184,7 @@ export class QuickActionsService { ); menu.showAtMouseEvent(evt); }); - setIcon(button, "sparkles"); + setIcon(button, this.assetsService.pluginIcon); actionsEl.prepend(button); } } diff --git a/Services/ServiceRegistration.ts b/Services/ServiceRegistration.ts index f8fbb4e..5571eed 100644 --- a/Services/ServiceRegistration.ts +++ b/Services/ServiceRegistration.ts @@ -2,6 +2,7 @@ import { AIProvider, fromModel } from "Enums/ApiProvider"; import { Environment } from "Enums/Environment"; import type VaultkeeperAIPlugin from "main"; +import { AssetsService } from "./AssetsService"; // Services import { RegisterSingleton, RegisterTransient, Resolve } from "./DependencyService"; @@ -64,6 +65,7 @@ import { QuickActionsService } from "./QuickActions/QuickActionsService"; export async function RegisterPlugin(plugin: VaultkeeperAIPlugin) { RegisterSingleton(Services.VaultkeeperAIPlugin, plugin); RegisterSingleton(Services.SettingsService, new SettingsService(await plugin.loadData() as Partial)); + RegisterSingleton(Services.AssetsService, new AssetsService()); } export function RegisterDependencies() { diff --git a/Services/Services.ts b/Services/Services.ts index 77d3eed..69d3f3d 100644 --- a/Services/Services.ts +++ b/Services/Services.ts @@ -1,6 +1,7 @@ export class Services { static VaultkeeperAIPlugin = Symbol("VaultkeeperAIPlugin"); static SettingsService = Symbol("SettingsService"); + static AssetsService = Symbol("AssetsService"); static EventService = Symbol("EventService"); static AbortService = Symbol("AbortService"); static HTMLService = Symbol("HTMLService"); diff --git a/Views/MainView.ts b/Views/MainView.ts index 4aff540..3bd8f80 100644 --- a/Views/MainView.ts +++ b/Views/MainView.ts @@ -2,6 +2,9 @@ import { ItemView, WorkspaceLeaf } from 'obsidian'; import { mount, unmount } from 'svelte'; import ChatWindow from 'Components/ChatWindow.svelte'; import TopBar from 'Components/TopBar.svelte'; +import { AssetsService } from 'Services/AssetsService'; +import { Resolve } from 'Services/DependencyService'; +import { Services } from 'Services/Services'; export const VIEW_TYPE_MAIN = 'vaultkeeper-ai-main-view'; @@ -12,8 +15,11 @@ interface ChatWindowComponent { export class MainView extends ItemView { + private readonly assetsService: AssetsService; + constructor(leaf: WorkspaceLeaf) { super(leaf); + this.assetsService = Resolve(Services.AssetsService); } topBar: ReturnType | undefined; @@ -28,7 +34,7 @@ export class MainView extends ItemView { } public getIcon(): string { - return 'sparkles'; + return this.assetsService.pluginIcon; } protected override onOpen(): Promise { diff --git a/main.ts b/main.ts index c68ae82..391e353 100644 --- a/main.ts +++ b/main.ts @@ -14,11 +14,16 @@ import type { Diff2HtmlUIConfig } from "diff2html/lib/ui/js/diff2html-ui"; import "katex/dist/katex.min.css"; import 'highlight.js/styles/monokai.min.css'; import 'diff2html/bundles/css/diff2html.min.css'; +import type { AssetsService } from "Services/AssetsService"; export default class VaultkeeperAIPlugin extends Plugin { public async onload() { await RegisterPlugin(this); + + const assetsService = Resolve(Services.AssetsService); + + await assetsService.loadAssets(); RegisterDependencies(); this.registerView( @@ -38,7 +43,7 @@ export default class VaultkeeperAIPlugin extends Plugin { } }); - this.addRibbonIcon("sparkles", "Vaultkeeper AI", async () => { + this.addRibbonIcon(assetsService.pluginIcon, "Vaultkeeper AI", async () => { await this.activateMainView(); });