mirror of
https://github.com/coalaura/whiskr.git
synced 2025-09-08 17:06:42 +00:00
better notifications
This commit is contained in:
@@ -127,6 +127,44 @@ body:not(.loading) #loading {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#notifications {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.notification {
|
||||
position: relative;
|
||||
background: #24273a;
|
||||
padding: 12px 15px;
|
||||
border-radius: 6px;
|
||||
width: 280px;
|
||||
margin-bottom: 10px;
|
||||
transition: 250ms;
|
||||
color: #ed8796;
|
||||
border: 2px solid #ed8796;
|
||||
left: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.notification.off-screen {
|
||||
height: 0px !important;
|
||||
border-width: 0px;
|
||||
left: calc(100% + 20px);
|
||||
padding: 0px 15px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.notification::before {
|
||||
content: "";
|
||||
background-image: url(icons/error.svg);
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
}
|
||||
|
||||
#page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -752,6 +790,7 @@ select {
|
||||
}
|
||||
|
||||
body.loading #version,
|
||||
.notification::before,
|
||||
#title-refresh,
|
||||
#loading .inner::after,
|
||||
.modal.loading .content::after,
|
||||
|
7
static/css/icons/error.svg
Normal file
7
static/css/icons/error.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
After Width: | Height: | Size: 1.1 KiB |
@@ -25,6 +25,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="notifications"></div>
|
||||
|
||||
<div id="page">
|
||||
<div id="title" class="hidden">
|
||||
<button id="title-refresh"></button>
|
||||
|
@@ -1,6 +1,7 @@
|
||||
(() => {
|
||||
const $version = document.getElementById("version"),
|
||||
$total = document.getElementById("total"),
|
||||
$notifications = document.getElementById("notifications"),
|
||||
$title = document.getElementById("title"),
|
||||
$titleRefresh = document.getElementById("title-refresh"),
|
||||
$titleText = document.getElementById("title-text"),
|
||||
@@ -55,6 +56,36 @@
|
||||
$total.textContent = formatMoney(totalCost);
|
||||
}
|
||||
|
||||
async function notify(msg, persistent = false) {
|
||||
console.warn(msg);
|
||||
|
||||
const notification = make("div", "notification", "off-screen");
|
||||
|
||||
notification.textContent = msg;
|
||||
|
||||
$notifications.appendChild(notification);
|
||||
|
||||
await wait(250);
|
||||
|
||||
notification.classList.remove("off-screen");
|
||||
|
||||
if (persistent) {
|
||||
return;
|
||||
}
|
||||
|
||||
await wait(5000);
|
||||
|
||||
notification.style.height = `${notification.getBoundingClientRect().height}px`;
|
||||
|
||||
notification.classList.add("off-screen");
|
||||
|
||||
await wait(250);
|
||||
|
||||
notification.remove();
|
||||
}
|
||||
|
||||
window.notify = notify;
|
||||
|
||||
function updateTitle() {
|
||||
$title.classList.toggle("hidden", !messages.length);
|
||||
|
||||
@@ -1077,7 +1108,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
alert(err.message);
|
||||
notify(err.message);
|
||||
}
|
||||
|
||||
titleController = null;
|
||||
@@ -1121,9 +1152,9 @@
|
||||
const data = await json("/-/data");
|
||||
|
||||
if (!data) {
|
||||
alert("Failed to load data.");
|
||||
notify("Failed to load data.", true);
|
||||
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// start icon preload
|
||||
@@ -1177,8 +1208,6 @@
|
||||
});
|
||||
|
||||
dropdown($prompt);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function clearMessages() {
|
||||
@@ -1190,8 +1219,8 @@
|
||||
function restore() {
|
||||
$message.value = loadValue("message", "");
|
||||
$role.value = loadValue("role", "user");
|
||||
$model.value = loadValue("model", modelList[0].id);
|
||||
$prompt.value = loadValue("prompt", promptList[0].key);
|
||||
$model.value = loadValue("model", modelList.length ? modelList[0].id : "");
|
||||
$prompt.value = loadValue("prompt", promptList.length ? promptList[0].key : "");
|
||||
$temperature.value = loadValue("temperature", 0.85);
|
||||
$iterations.value = loadValue("iterations", 3);
|
||||
$reasoningEffort.value = loadValue("reasoning-effort", "medium");
|
||||
@@ -1500,7 +1529,7 @@
|
||||
|
||||
pushAttachment(file);
|
||||
} catch (err) {
|
||||
alert(err.message);
|
||||
notify(err.message);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1661,9 +1690,5 @@
|
||||
restore();
|
||||
|
||||
document.body.classList.remove("loading");
|
||||
|
||||
setTimeout(() => {
|
||||
document.getElementById("loading").remove();
|
||||
}, 500);
|
||||
});
|
||||
})();
|
||||
|
@@ -66,6 +66,10 @@ function fillSelect($select, options, callback) {
|
||||
}
|
||||
}
|
||||
|
||||
function wait(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
}
|
||||
|
Reference in New Issue
Block a user