Add Nebot plugin with chat UI and adaptive typing
Introduces the Nebot plugin, including main process logic for chat session management, IPC handlers, and Ollama API integration. Adds a dedicated chat UI with adaptive typing animation, markdown rendering, settings modal, and supporting assets (CSS, HTML, JS, markdown bundle). Includes documentation for model selection and testing instructions.
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
:root {
|
||||
--bg: #12141c;
|
||||
--bg-alt: #181b25;
|
||||
--panel: #1f2430;
|
||||
--border: rgba(255,255,255,0.08);
|
||||
--accent: #7b61ff;
|
||||
--accent-glow: 180 100% 60%;
|
||||
--text: #e6e8ef;
|
||||
--muted: #9aa0b1;
|
||||
--danger: #ff4d61;
|
||||
font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,sans-serif;
|
||||
}
|
||||
|
||||
html,body { height:100%; margin:0; background:radial-gradient(circle at 20% 20%, #1c2030, #0f1116); color:var(--text); }
|
||||
body { display:flex; }
|
||||
|
||||
.app { display:flex; flex:1; width:100%; overflow:hidden; }
|
||||
.sidebar { width:280px; background:linear-gradient(180deg,#1b1f29,#161921); border-right:1px solid var(--border); display:flex; flex-direction:column; }
|
||||
.sidebar-header { padding:14px 16px 10px; display:flex; align-items:center; justify-content:space-between; gap:8px; }
|
||||
.sidebar-header h1 { font-size:18px; margin:0; letter-spacing:.5px; background:linear-gradient(90deg,#a48bff,#6cb6ff); -webkit-background-clip:text; color:transparent; }
|
||||
.sidebar-header button { background:var(--accent); color:#fff; border:0; width:34px; height:34px; border-radius:10px; cursor:pointer; font-size:18px; display:flex; align-items:center; justify-content:center; }
|
||||
.sidebar-header button:hover { filter:brightness(1.1); }
|
||||
.chat-list { list-style:none; margin:0; padding:4px 10px 10px; flex:1; overflow:auto; }
|
||||
.chat-item { padding:10px 10px; margin:4px 0; border:1px solid var(--border); border-radius:12px; cursor:pointer; background:rgba(255,255,255,0.03); display:flex; gap:8px; align-items:center; }
|
||||
.chat-item:hover { background:rgba(255,255,255,0.06); }
|
||||
.chat-item.active { border-color:var(--accent); background:linear-gradient(90deg,rgba(123,97,255,0.25),rgba(123,97,255,0.12)); }
|
||||
.chat-title { flex:1; font-size:13px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
||||
.delete-btn { background:transparent; border:0; color:var(--muted); cursor:pointer; font-size:14px; }
|
||||
.delete-btn:hover { color:var(--danger); }
|
||||
.sidebar-footer { padding:10px; border-top:1px solid var(--border); }
|
||||
.sidebar-footer button { width:100%; background:#262d3a; color:var(--text); border:1px solid var(--border); padding:8px 12px; border-radius:10px; cursor:pointer; }
|
||||
.sidebar-footer button:hover { border-color:var(--accent); color:#fff; }
|
||||
|
||||
.main { display:flex; flex:1; flex-direction:column; position:relative; }
|
||||
.messages { flex:1; overflow:auto; padding:18px 22px 20px; display:flex; flex-direction:column; gap:14px; scroll-behavior:smooth; }
|
||||
.msg { padding:12px 14px; border-radius:14px; max-width:870px; line-height:1.55; font-size:14px; white-space:pre-wrap; word-break:break-word; }
|
||||
.msg.user { align-self:flex-end; background:linear-gradient(180deg,#2d3344,#252b38); border:1px solid rgba(123,97,255,0.4); }
|
||||
.msg.assistant { align-self:flex-start; background:linear-gradient(180deg,#232836,#1d202a); border:1px solid rgba(255,255,255,0.1); }
|
||||
.msg.streaming { position:relative; }
|
||||
.msg.streaming:after { content:""; position:absolute; left:0; bottom:0; height:2px; width:100%; background:linear-gradient(90deg,rgba(123,97,255,0),rgba(123,97,255,.8),rgba(123,97,255,0)); animation:stream 1.2s linear infinite; }
|
||||
|
||||
/* Typing animation cursor */
|
||||
.markdown.typing:after {
|
||||
content: "▋";
|
||||
color: var(--accent);
|
||||
animation: blink 1s infinite;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0%, 50% { opacity: 1; }
|
||||
51%, 100% { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes stream { from { background-position:0 0; } to { background-position:200% 0; } }
|
||||
|
||||
.composer { display:flex; gap:12px; padding:16px 18px; background:linear-gradient(180deg,#181c25,#14171f); border-top:1px solid var(--border); }
|
||||
.composer textarea { flex:1; resize:none; max-height:200px; min-height:46px; padding:12px 14px; font-size:14px; border-radius:12px; border:1px solid var(--border); background:#1c212d; color:var(--text); outline:none; line-height:1.5; }
|
||||
.composer textarea:focus { border-color:var(--accent); box-shadow:0 0 0 3px rgba(123,97,255,0.25); }
|
||||
.composer button { width:110px; border:0; background:var(--accent); color:#fff; font-weight:600; border-radius:12px; cursor:pointer; font-size:14px; }
|
||||
.composer button:hover { filter:brightness(1.1); }
|
||||
|
||||
.settings-modal { position:fixed; inset:0; background:rgba(0,0,0,0.55); backdrop-filter:blur(6px); display:flex; align-items:center; justify-content:center; z-index:99999; }
|
||||
.settings-card { width:460px; max-width:90%; background:linear-gradient(180deg,#222836,#1b1f29); border:1px solid var(--border); border-radius:18px; padding:20px 22px 24px; display:flex; flex-direction:column; gap:14px; }
|
||||
.settings-card h2 { margin:0 0 4px; font-size:18px; }
|
||||
.settings-card label { font-size:12px; text-transform:uppercase; letter-spacing:.05em; color:var(--muted); font-weight:600; }
|
||||
.settings-card input, .settings-card textarea { width:100%; margin-top:4px; background:#1d2430; border:1px solid var(--border); color:var(--text); border-radius:10px; padding:10px 12px; font-size:13px; resize:vertical; min-height:42px; }
|
||||
.settings-card input[type="checkbox"] { width:auto; margin:0; transform:scale(1.2); }
|
||||
.settings-card input[type="range"] { padding:0; height:6px; background:var(--border); border-radius:3px; -webkit-appearance:none; appearance:none; }
|
||||
.settings-card input[type="range"]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:16px; height:16px; border-radius:50%; background:var(--accent); cursor:pointer; }
|
||||
.settings-card input[type="range"]::-moz-range-thumb { width:16px; height:16px; border-radius:50%; background:var(--accent); cursor:pointer; border:none; }
|
||||
.settings-card textarea { min-height:100px; }
|
||||
.settings-card input:focus, .settings-card textarea:focus { border-color:var(--accent); outline:none; box-shadow:0 0 0 2px rgba(123,97,255,0.25); }
|
||||
.settings-actions { display:flex; justify-content:flex-end; gap:10px; margin-top:4px; }
|
||||
.settings-actions button { background:#2a3242; color:var(--text); padding:8px 14px; border:1px solid var(--border); border-radius:10px; cursor:pointer; }
|
||||
.settings-actions button.primary { background:var(--accent); color:#fff; border:0; }
|
||||
.settings-actions button:hover { border-color:var(--accent); }
|
||||
.settings-actions button.primary:hover { filter:brightness(1.1); }
|
||||
|
||||
.empty { opacity:.5; font-size:14px; text-align:center; padding:40px 0; }
|
||||
|
||||
/* Enhanced Markdown Styles */
|
||||
.markdown { color: inherit; }
|
||||
.markdown * { color: inherit; }
|
||||
|
||||
/* Typography */
|
||||
.markdown :is(h1,h2,h3,h4,h5,h6) {
|
||||
margin: 1.2em 0 0.5em;
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
}
|
||||
.markdown h1 { font-size: 1.5em; border-bottom: 1px solid var(--border); padding-bottom: 0.3em; }
|
||||
.markdown h2 { font-size: 1.3em; }
|
||||
.markdown h3 { font-size: 1.15em; }
|
||||
.markdown h4 { font-size: 1.05em; }
|
||||
.markdown h5 { font-size: 1em; }
|
||||
.markdown h6 { font-size: 0.9em; color: var(--muted); }
|
||||
|
||||
.markdown p {
|
||||
margin: 0.8em 0;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Lists */
|
||||
.markdown :is(ul,ol) {
|
||||
margin: 0.8em 0;
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
.markdown li {
|
||||
margin: 0.3em 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.markdown ul li { list-style-type: disc; }
|
||||
.markdown ol li { list-style-type: decimal; }
|
||||
|
||||
/* Code */
|
||||
.markdown code {
|
||||
background: rgba(0,0,0,0.4);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 6px;
|
||||
font-size: 0.9em;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.markdown pre {
|
||||
background: rgba(0,0,0,0.5);
|
||||
padding: 1em 1.2em;
|
||||
border: 1px solid rgba(255,255,255,0.12);
|
||||
border-radius: 12px;
|
||||
overflow-x: auto;
|
||||
margin: 1em 0;
|
||||
line-height: 1.45;
|
||||
}
|
||||
.markdown pre code {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
border: none;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
/* Blockquotes */
|
||||
.markdown blockquote {
|
||||
margin: 1em 0;
|
||||
padding: 0.8em 1.2em;
|
||||
border-left: 4px solid var(--accent);
|
||||
background: rgba(123,97,255,0.08);
|
||||
border-radius: 0 8px 8px 0;
|
||||
font-style: italic;
|
||||
}
|
||||
.markdown blockquote p { margin: 0.5em 0; }
|
||||
|
||||
/* Links */
|
||||
.markdown a {
|
||||
color: #6cb6ff;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
.markdown a:hover {
|
||||
border-bottom-color: #6cb6ff;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
.markdown table {
|
||||
border-collapse: collapse;
|
||||
margin: 1em 0;
|
||||
width: 100%;
|
||||
}
|
||||
.markdown th, .markdown td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.6em 0.8em;
|
||||
text-align: left;
|
||||
}
|
||||
.markdown th {
|
||||
background: rgba(255,255,255,0.05);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Horizontal rule */
|
||||
.markdown hr {
|
||||
border: none;
|
||||
height: 1px;
|
||||
background: var(--border);
|
||||
margin: 2em 0;
|
||||
}
|
||||
|
||||
/* Inline emphasis */
|
||||
.markdown strong { font-weight: 600; }
|
||||
.markdown em { font-style: italic; }
|
||||
|
||||
/* Syntax highlighting theme adjustments */
|
||||
.markdown .hljs {
|
||||
background: transparent !important;
|
||||
color: var(--text) !important;
|
||||
}
|
||||
.markdown .hljs-keyword { color: #c792ea; }
|
||||
.markdown .hljs-string { color: #ecc48d; }
|
||||
.markdown .hljs-number { color: #f78c6c; }
|
||||
.markdown .hljs-comment { color: var(--muted); }
|
||||
.markdown .hljs-function { color: #82aaff; }
|
||||
.markdown .hljs-variable { color: #ffcb6b; }
|
||||
.markdown .hljs-type { color: #c3e88d; }
|
||||
.markdown .hljs-built_in { color: #ff5370; }
|
||||
|
||||
/* Local lightweight highlight.js theme (replaces removed CDN stylesheet) */
|
||||
.markdown pre code .hljs-title { color: #82aaff; }
|
||||
.markdown pre code .hljs-attr { color: #ecc48d; }
|
||||
.markdown pre code .hljs-symbol { color: #c792ea; }
|
||||
.markdown pre code .hljs-meta { color: #7f848e; }
|
||||
.markdown pre code .hljs-params { color: #c3e88d; }
|
||||
.markdown pre code .hljs-property { color: #ffcb6b; }
|
||||
Reference in New Issue
Block a user