mirror of
https://github.com/andy-stack/vaultkeeper-ai.git
synced 2026-07-22 16:30:27 +00:00
- Add horizontal margin to conversation divider in TopBar - Adjust grid row sizing in conversation history modal - Remove margin from modals on mobile screens (≤600px) - Reduce bottom margin for diff mobile controls - Remove redundant background styling from diff button container - Fix diff view height calculation on mobile to avoid control overlap
416 lines
10 KiB
Svelte
416 lines
10 KiB
Svelte
<script lang="ts">
|
|
import { Copy } from "Enums/Copy";
|
|
import type VaultkeeperAIPlugin from "main";
|
|
import { DropdownComponent, setIcon } from "obsidian";
|
|
import { Resolve } from "Services/DependencyService";
|
|
import { Services } from "Services/Services";
|
|
import type { StreamingMarkdownService } from "Services/StreamingMarkdownService";
|
|
import type { WorkSpaceService } from "Services/WorkSpaceService";
|
|
import { fade } from "svelte/transition";
|
|
import { onMount } from "svelte";
|
|
|
|
export let onClose: () => void;
|
|
export let initialTopic: number = 1;
|
|
|
|
const plugin: VaultkeeperAIPlugin = Resolve<VaultkeeperAIPlugin>(Services.VaultkeeperAIPlugin);
|
|
const streamingMarkdownService: StreamingMarkdownService = Resolve<StreamingMarkdownService>(Services.StreamingMarkdownService);
|
|
const workSpaceService: WorkSpaceService = Resolve<WorkSpaceService>(Services.WorkSpaceService);
|
|
|
|
let closeButton: HTMLButtonElement;
|
|
let dropdownContainer: HTMLDivElement;
|
|
let contentContainer: HTMLDivElement;
|
|
|
|
const topics: Record<number, { title: string; content: string }> = {
|
|
1: {
|
|
title: Copy.HelpModalAboutTitle,
|
|
content: Copy.HelpModalAboutContent
|
|
},
|
|
2: {
|
|
title: Copy.HelpModalGuideTitle,
|
|
content: Copy.HelpModalGuideContent
|
|
},
|
|
3: {
|
|
title: Copy.HelpModalTroubleshootTitle,
|
|
content: Copy.HelpModalTroubleshootContent
|
|
},
|
|
4: {
|
|
title: Copy.HelpModalPrivacyTitle,
|
|
content: Copy.HelpModalPrivacyContent
|
|
}
|
|
};
|
|
|
|
let selectedTopic: number = initialTopic;
|
|
let title: string = topics[selectedTopic].title;
|
|
let content: string = streamingMarkdownService.formatText(topics[selectedTopic].content);
|
|
|
|
function selectTopic(topicNumber: number) {
|
|
title = "";
|
|
content = "";
|
|
selectedTopic = topicNumber;
|
|
setTimeout(() => {
|
|
title = topics[selectedTopic].title;
|
|
content = streamingMarkdownService.formatText(topics[selectedTopic].content);
|
|
}, 200);
|
|
}
|
|
|
|
$: if (closeButton) {
|
|
setIcon(closeButton, 'circle-x');
|
|
}
|
|
|
|
async function handleLinkClick(evt: MouseEvent) {
|
|
const target = evt.target as HTMLElement;
|
|
|
|
// Check for both internal wikilinks and regular markdown links
|
|
const link = target.closest('a') as HTMLAnchorElement | null;
|
|
if (!link) {
|
|
return;
|
|
}
|
|
|
|
const href = link.getAttribute('href');
|
|
if (!href || !href.startsWith('#/page/')) {
|
|
return;
|
|
}
|
|
|
|
evt.preventDefault();
|
|
evt.stopPropagation();
|
|
|
|
const encodedPath = href.replace('#/page/', '');
|
|
const notePath = decodeURIComponent(encodedPath);
|
|
await workSpaceService.openNote(notePath);
|
|
onClose();
|
|
}
|
|
|
|
onMount(() => {
|
|
if (dropdownContainer) {
|
|
const dropdown = new DropdownComponent(dropdownContainer);
|
|
|
|
// Add all topic options
|
|
Object.entries(topics).forEach(([key, topic]) => {
|
|
dropdown.addOption(key, topic.title);
|
|
});
|
|
|
|
// Set initial value
|
|
dropdown.setValue(selectedTopic.toString());
|
|
|
|
// Handle changes
|
|
dropdown.onChange((value) => {
|
|
selectTopic(Number(value));
|
|
});
|
|
}
|
|
|
|
if (contentContainer) {
|
|
plugin.registerDomEvent(contentContainer, 'click', handleLinkClick);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<div class="help-modal-container">
|
|
<div class="help-modal-top-bar">
|
|
<div class="help-modal-top-bar-content">
|
|
{#if title !== ""}
|
|
<div id="help-modal-title" transition:fade={{ duration: 100 }}>
|
|
{title}
|
|
</div>
|
|
{/if}
|
|
<button
|
|
bind:this={closeButton}
|
|
id="close-button"
|
|
class="top-bar-button clickable-icon"
|
|
on:click={onClose}
|
|
aria-label={Copy.HelpModalCloseAriaLabel}
|
|
></button>
|
|
</div>
|
|
</div>
|
|
<div class="help-modal-body">
|
|
<div class="help-modal-dropdown" bind:this={dropdownContainer}></div>
|
|
<div id="help-modal-version-string-mobile">
|
|
{Copy.PluginVersionPrefix}{plugin.manifest.version}
|
|
</div>
|
|
<div class="help-modal-topics">
|
|
<div
|
|
class="help-modal-topic-frame"
|
|
class:hidden={selectedTopic !== 1}
|
|
on:click={() => selectTopic(1)}
|
|
on:keydown={(e) => e.key === 'Enter' && selectTopic(1)}
|
|
role="button"
|
|
tabindex="0">
|
|
<div class="help-modal-topic-item">
|
|
{topics[1].title}
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="help-modal-topic-frame"
|
|
class:hidden={selectedTopic !== 2}
|
|
on:click={() => selectTopic(2)}
|
|
on:keydown={(e) => e.key === 'Enter' && selectTopic(2)}
|
|
role="button"
|
|
tabindex="0">
|
|
<div class="help-modal-topic-item">
|
|
{topics[2].title}
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="help-modal-topic-frame"
|
|
class:hidden={selectedTopic !== 3}
|
|
on:click={() => selectTopic(3)}
|
|
on:keydown={(e) => e.key === 'Enter' && selectTopic(3)}
|
|
role="button"
|
|
tabindex="0">
|
|
<div class="help-modal-topic-item">
|
|
{topics[3].title}
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="help-modal-topic-frame"
|
|
class:hidden={selectedTopic !== 4}
|
|
on:click={() => selectTopic(4)}
|
|
on:keydown={(e) => e.key === 'Enter' && selectTopic(4)}
|
|
role="button"
|
|
tabindex="0">
|
|
<div class="help-modal-topic-item">
|
|
{topics[4].title}
|
|
</div>
|
|
</div>
|
|
<div id="help-modal-version-string">
|
|
{Copy.PluginVersionPrefix}{plugin.manifest.version}
|
|
</div>
|
|
</div>
|
|
<div class="help-modal-content" bind:this={contentContainer}>
|
|
{#if content !== ""}
|
|
<div transition:fade={{ duration: 100 }}>
|
|
{@html content}
|
|
{#if selectedTopic === 1}
|
|
<a
|
|
href="{plugin.manifest.authorUrl}/vaultkeeper-ai"
|
|
style="text-decoration: none; display: inline-flex; align-items: center; gap: 0.5em; margin: 0 0 1em 0;">
|
|
<svg
|
|
width="1em"
|
|
height="1em"
|
|
viewBox="0 0 98 96"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
aria-label={Copy.GitHubIconAriaLabel}
|
|
style="display: inline-block; vertical-align: middle;">
|
|
<path fill-rule="evenodd" clip-rule="evenodd" d={Copy.GitHubIconPath} fill="currentColor"/>
|
|
</svg>
|
|
<span>{Copy.GitHubLinkText}</span>
|
|
</a>
|
|
<br>
|
|
<span style="display: inline-block; margin-bottom: 1em;">{Copy.CoffeeLinkIntroText}</span>
|
|
<br>
|
|
<a href={(plugin.manifest as any).fundingUrl} style="text-decoration: none; display: inline-flex; align-items: center; gap: 0.5em;">
|
|
<span>{Copy.CoffeeIcon}</span>
|
|
<span>{Copy.CoffeeLinkText}</span>
|
|
</a>
|
|
<p style="margin-top: 2em; font-style: italic;">{Copy.ThankYouMessage}</p>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.help-modal-container {
|
|
display: grid;
|
|
grid-template-rows: auto var(--size-4-1) 1fr var(--size-4-2);
|
|
grid-template-columns: var(--size-4-2) 1fr var(--size-4-2);
|
|
max-height: 60vh;
|
|
min-height: 60vh;
|
|
margin: 10px;
|
|
}
|
|
|
|
.help-modal-top-bar {
|
|
grid-row: 1;
|
|
grid-column: 2;
|
|
height: var(--size-4-16);
|
|
display: grid;
|
|
grid-template-rows: var(--size-4-2) 1fr var(--size-4-2);
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.help-modal-top-bar-content {
|
|
grid-row: 2;
|
|
grid-column: 1;
|
|
display: grid;
|
|
grid-template-rows: auto;
|
|
grid-template-columns: var(--size-4-2) 1fr auto var(--size-4-2);
|
|
background-color: var(--background-secondary-alt);
|
|
border-radius: var(--radius-m);
|
|
}
|
|
|
|
#help-modal-title {
|
|
grid-row: 1;
|
|
grid-column: 2 / 4;
|
|
display: inline-block;
|
|
text-align: center;
|
|
align-self: center;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
width: 100%;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
#close-button {
|
|
grid-row: 1;
|
|
grid-column: 3;
|
|
z-index: 1;
|
|
}
|
|
|
|
.help-modal-body {
|
|
grid-row: 3;
|
|
grid-column: 2;
|
|
display: grid;
|
|
grid-template-rows: auto var(--size-4-3) auto var(--size-4-3) auto var(--size-4-3) auto 1fr;
|
|
grid-template-columns: auto var(--size-4-2) 1fr;
|
|
height: 100%;
|
|
width: 100%;
|
|
overflow: auto;
|
|
}
|
|
|
|
.help-modal-dropdown {
|
|
display: none;
|
|
}
|
|
|
|
#help-modal-version-string-mobile {
|
|
display: none;
|
|
}
|
|
|
|
.help-modal-topic-frame {
|
|
grid-column: 1 / 4;
|
|
display: grid;
|
|
grid-template-rows: auto;
|
|
grid-template-columns: auto var(--size-4-2) 1fr;
|
|
width: 150%;
|
|
padding: var(--size-4-2) var(--size-4-1);
|
|
border-radius: var(--radius-m);
|
|
cursor: pointer;
|
|
background-color: var(--alt-background-primary);
|
|
transition: background-color 0.25s ease-in-out;
|
|
}
|
|
|
|
.help-modal-topic-frame.hidden {
|
|
background-color: transparent;
|
|
}
|
|
|
|
.help-modal-topic-frame:nth-child(1) {
|
|
grid-row: 1;
|
|
}
|
|
|
|
.help-modal-topic-frame:nth-child(2) {
|
|
grid-row: 3;
|
|
}
|
|
|
|
.help-modal-topic-frame:nth-child(3) {
|
|
grid-row: 5;
|
|
}
|
|
|
|
.help-modal-topic-frame:nth-child(4) {
|
|
grid-row: 7;
|
|
}
|
|
|
|
.help-modal-topics {
|
|
grid-row: 1 / 9;
|
|
grid-column: 1;
|
|
display: grid;
|
|
max-width: 150px;
|
|
grid-template-rows: auto var(--size-4-3) auto var(--size-4-3) auto var(--size-4-3) auto 1fr;
|
|
grid-template-columns: auto var(--size-4-2) 1fr;
|
|
}
|
|
|
|
.help-modal-topic-item {
|
|
grid-column: 1;
|
|
display: inline-block;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
padding: var(--size-4-1) var(--size-4-3);
|
|
cursor: pointer;
|
|
transition: color 0.15s ease-in-out;
|
|
}
|
|
|
|
.help-modal-topic-item:hover {
|
|
color: var(--text-normal);
|
|
}
|
|
|
|
.help-modal-topic-item:nth-child(1) {
|
|
grid-row: 1;
|
|
}
|
|
|
|
.help-modal-topic-item:nth-child(2) {
|
|
grid-row: 3;
|
|
}
|
|
|
|
.help-modal-topic-item:nth-child(3) {
|
|
grid-row: 5;
|
|
}
|
|
|
|
.help-modal-topic-item:nth-child(4) {
|
|
grid-row: 7;
|
|
}
|
|
|
|
#help-modal-version-string {
|
|
grid-row: 8;
|
|
grid-column: 1;
|
|
align-self: flex-end;
|
|
padding: var(--size-4-1) var(--size-4-3);
|
|
font-size: var(--font-smallest);
|
|
}
|
|
|
|
.help-modal-content {
|
|
grid-row: 1 / 9;
|
|
grid-column: 3;
|
|
height: 100%;
|
|
border-radius: var(--radius-m);
|
|
background-color: var(--alt-background-primary);
|
|
padding: 0 var(--size-4-2) var(--size-4-2) var(--size-4-3);
|
|
overflow-y: auto;
|
|
}
|
|
|
|
/* Mobile styles */
|
|
:global(.is-mobile) .help-modal-body {
|
|
grid-template-rows: auto var(--size-4-2) 1fr var(--size-4-2) auto;
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
:global(.is-mobile) .help-modal-dropdown {
|
|
display: block;
|
|
grid-row: 1;
|
|
grid-column: 1;
|
|
width: 100%;
|
|
}
|
|
|
|
.help-modal-dropdown :global(.dropdown) {
|
|
width: 100%;
|
|
border: solid;
|
|
border-width: 1px;
|
|
border-color: var(--color-accent) !important;
|
|
outline: none;
|
|
}
|
|
|
|
@media (max-width: 600px) {
|
|
.help-modal-container {
|
|
margin: 0px;
|
|
}
|
|
}
|
|
|
|
:global(.is-mobile) #help-modal-version-string-mobile {
|
|
display: block;
|
|
grid-row: 5;
|
|
grid-column: 1;
|
|
align-self: flex-end;
|
|
padding: var(--size-4-1) var(--size-4-2);
|
|
font-size: var(--font-smallest);
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
:global(.is-mobile) .help-modal-topics {
|
|
display: none;
|
|
}
|
|
|
|
:global(.is-mobile) .help-modal-content {
|
|
grid-row: 3;
|
|
grid-column: 1;
|
|
padding: var(--size-4-2);
|
|
}
|
|
</style>
|