Compare commits
5 Commits
v1.0.0
...
e3f28283ef
| Author | SHA1 | Date | |
|---|---|---|---|
| e3f28283ef | |||
| 20e8f1ee71 | |||
| b006f571bf | |||
| ea3cc8b26c | |||
| 2bb541fba6 |
@@ -1 +1,29 @@
|
|||||||
tem
|
# hikari-desktop
|
||||||
|
|
||||||
|
Desktop companion application featuring Hikari.
|
||||||
|
|
||||||
|
## Live Version
|
||||||
|
|
||||||
|
This page is currently deployed. [View the live website.](https://git.nhcarrigan.com/nhcarrigan/hikari-desktop/releases)
|
||||||
|
|
||||||
|
## Feedback and Bugs
|
||||||
|
|
||||||
|
If you have feedback or a bug report, please [log a ticket on our forum](https://support.nhcarrigan.com).
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
If you would like to contribute to the project, you may create a Pull Request containing your proposed changes and we will review it as soon as we are able! Please review our [contributing guidelines](CONTRIBUTING.md) first.
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
Before interacting with our community, please read our [Code of Conduct](CODE_OF_CONDUCT.md).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This software is licensed under our [global software license](https://docs.nhcarrigan.com/#/license).
|
||||||
|
|
||||||
|
Copyright held by Naomi Carrigan.
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
We may be contacted through our [Chat Server](http://chat.nhcarrigan.com) or via email at `contact@nhcarrigan.com`
|
||||||
|
|||||||
@@ -1602,7 +1602,7 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hikari-desktop"
|
name = "hikari-desktop"
|
||||||
version = "0.3.0"
|
version = "1.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 181 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 338 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 466 KiB |
|
Before Width: | Height: | Size: 878 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 58 KiB |
@@ -155,6 +155,30 @@
|
|||||||
terminalElement.removeEventListener("copy", handleCopy);
|
terminalElement.removeEventListener("copy", handleCopy);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Copy message content to clipboard
|
||||||
|
async function copyMessage(content: string) {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(content);
|
||||||
|
// Optionally capture to clipboard history
|
||||||
|
await clipboardStore.captureClipboard(content, null, "Message from chat");
|
||||||
|
|
||||||
|
// Visual feedback could be added here if needed
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to copy message:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// State for showing "Copied!" feedback
|
||||||
|
let copiedMessageId: string | null = null;
|
||||||
|
|
||||||
|
async function handleCopyMessage(messageId: string, content: string) {
|
||||||
|
await copyMessage(content);
|
||||||
|
copiedMessageId = messageId;
|
||||||
|
setTimeout(() => {
|
||||||
|
copiedMessageId = null;
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -185,7 +209,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
{#each lines as line (line.id)}
|
{#each lines as line (line.id)}
|
||||||
<div class="terminal-line mb-2 {getLineClass(line.type)}">
|
<div class="terminal-line mb-2 {getLineClass(line.type)} relative group">
|
||||||
<span class="terminal-timestamp text-xs mr-2">{formatTime(line.timestamp)}</span>
|
<span class="terminal-timestamp text-xs mr-2">{formatTime(line.timestamp)}</span>
|
||||||
{#if getLinePrefix(line.type)}
|
{#if getLinePrefix(line.type)}
|
||||||
<span class="terminal-prefix mr-2">{getLinePrefix(line.type)}</span>
|
<span class="terminal-prefix mr-2">{getLinePrefix(line.type)}</span>
|
||||||
@@ -193,11 +217,33 @@
|
|||||||
{#if line.toolName}
|
{#if line.toolName}
|
||||||
<span class="terminal-tool-name mr-2">[{line.toolName}]</span>
|
<span class="terminal-tool-name mr-2">[{line.toolName}]</span>
|
||||||
{/if}
|
{/if}
|
||||||
{#if line.type === "assistant"}
|
{#if line.type === "assistant" || line.type === "user"}
|
||||||
|
<div class="message-content-wrapper">
|
||||||
<Markdown
|
<Markdown
|
||||||
content={maskPaths(line.content, hidePaths)}
|
content={maskPaths(line.content, hidePaths)}
|
||||||
searchQuery={currentSearchQuery}
|
searchQuery={currentSearchQuery}
|
||||||
/>
|
/>
|
||||||
|
<button
|
||||||
|
class="copy-message-btn opacity-0 group-hover:opacity-100 transition-opacity"
|
||||||
|
onclick={() => handleCopyMessage(line.id, line.content)}
|
||||||
|
title="Copy message"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="14"
|
||||||
|
height="14"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||||
|
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
||||||
|
</svg>
|
||||||
|
<span class="copy-text">{copiedMessageId === line.id ? "Copied!" : "Copy"}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<HighlightedText
|
<HighlightedText
|
||||||
content={maskPaths(line.content, hidePaths)}
|
content={maskPaths(line.content, hidePaths)}
|
||||||
@@ -267,4 +313,45 @@
|
|||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: 0 2px;
|
padding: 0 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Message content wrapper for positioning */
|
||||||
|
.message-content-wrapper {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy button styling */
|
||||||
|
.copy-message-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4em;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
color: var(--text-secondary);
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.85em;
|
||||||
|
font-family: inherit;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-message-btn:hover {
|
||||||
|
background: var(--bg-hover);
|
||||||
|
color: var(--text-primary);
|
||||||
|
border-color: var(--border-hover, var(--border-color));
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-message-btn svg {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure relative positioning for parent */
|
||||||
|
.terminal-line {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||