mirror of
https://github.com/KoboldAI/KoboldAI-Client.git
synced 2025-06-05 21:59:24 +02:00
@@ -2148,6 +2148,43 @@ body {
|
||||
border-radius: var(--radius_settings_button);
|
||||
}
|
||||
|
||||
/* Context Menu */
|
||||
#context-menu {
|
||||
position: absolute;
|
||||
cursor: default;
|
||||
|
||||
/* Nothing should be above the context menu (that I can think of) */
|
||||
z-index: 9999999;
|
||||
|
||||
/* TODO: Theme */
|
||||
background-color: #222f3a;
|
||||
border: 1px solid #485e6d;
|
||||
}
|
||||
|
||||
#context-menu > hr {
|
||||
/* TODO: Theme */
|
||||
border-top: 2px solid #485e6d;
|
||||
margin: 5px 5px;
|
||||
}
|
||||
|
||||
.context-menu-item {
|
||||
padding: 5px;
|
||||
padding-right: 25px;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.context-menu-item:hover {
|
||||
/* TODO: Theme */
|
||||
background-color: #273b48;
|
||||
}
|
||||
|
||||
.context-menu-item > .material-icons-outlined {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
font-size: 15px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/*---------------------------------- Global ------------------------------------------------*/
|
||||
.hidden {
|
||||
display: none;
|
||||
|
@@ -73,6 +73,22 @@ const finder_actions = [
|
||||
// {name: "", icon: "palette", func: function() { highlightEl("#biasing") }},
|
||||
];
|
||||
|
||||
const context_menu_actions = [
|
||||
{label: "Cut", icon: "content_cut", visibilityCondition: "SELECTION", click: cut},
|
||||
{label: "Copy", icon: "content_copy", visibilityCondition: "SELECTION", click: copy},
|
||||
{label: "Paste", icon: "content_paste", visibilityCondition: "SELECTION", click: paste},
|
||||
// Null makes a seperation bar
|
||||
null,
|
||||
{label: "Add to Memory", icon: "assignment", visibilityCondition: "SELECTION", click: push_selection_to_memory},
|
||||
{label: "Add to World Info Entry", icon: "auto_stories", visibilityCondition: "SELECTION", click: push_selection_to_world_info},
|
||||
{label: "Add as Bias", icon: "insights", visibilityCondition: "SELECTION", click: push_selection_to_phrase_bias},
|
||||
{label: "Retry from here", icon: "refresh", visibilityCondition: "CARET", click: retry_from_here},
|
||||
// Not implemented! See view_selection_probabiltiies
|
||||
// null,
|
||||
// {label: "View Token Probabilities", icon: "assessment", visibilityCondition: "SELECTION", click: view_selection_probabilities},
|
||||
// {label: "View Token Probabilities", icon: "account_tree", visibilityCondition: "SELECTION", click: view_selection_probabilities},
|
||||
];
|
||||
|
||||
|
||||
const map1 = new Map()
|
||||
map1.set('Top K Sampling', 0)
|
||||
@@ -2310,6 +2326,9 @@ function push_selection_to_phrase_bias() {
|
||||
}
|
||||
|
||||
function retry_from_here() {
|
||||
// TODO: Make this from the caret position (get_caret_position()) instead
|
||||
// of per action. Actions may start out well, but go off the rails later, so
|
||||
// we should be able to retry from any position.
|
||||
let chunk = null;
|
||||
for (element of document.getElementsByClassName("editing")) {
|
||||
if (element.id == 'story_prompt') {
|
||||
@@ -2331,16 +2350,25 @@ function retry_from_here() {
|
||||
}
|
||||
}
|
||||
|
||||
function view_selection_probabilities() {
|
||||
// Not quite sure how this should work yet. Probabilities are obviously on
|
||||
// the token level, which we have no UI representation of. There are other
|
||||
// token-level visualization features I'd like to implement (like something
|
||||
// for self-attention), so if that works out it might be best to have a
|
||||
// modifier key (i.e. alt) enter a "token selection mode" when held.
|
||||
console.log("Not implemented! :(");
|
||||
}
|
||||
|
||||
function copy() {
|
||||
document.execCommand("copy")
|
||||
document.execCommand("copy");
|
||||
}
|
||||
|
||||
function paste() {
|
||||
document.execCommand("paste")
|
||||
document.execCommand("paste");
|
||||
}
|
||||
|
||||
function cut() {
|
||||
document.execCommand("cut")
|
||||
document.execCommand("cut");
|
||||
}
|
||||
|
||||
function getSelectionText() {
|
||||
@@ -2359,6 +2387,15 @@ function getSelectionText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
function get_caret_position(target) {
|
||||
if (
|
||||
document.activeElement !== target &&
|
||||
!$.contains(target, document.activeElement)
|
||||
) return null;
|
||||
|
||||
return getSelection().focusOffset;
|
||||
}
|
||||
|
||||
function show_save_preset() {
|
||||
document.getElementById("save_preset").classList.remove("hidden");
|
||||
}
|
||||
@@ -3806,7 +3843,6 @@ function updateStandardSearchListings(query) {
|
||||
|
||||
function $e(tag, parent, attributes) {
|
||||
// Small helper function for dynamic UI creation
|
||||
// TODO: Support nested attributed with "." syntax.
|
||||
|
||||
let element = document.createElement(tag);
|
||||
|
||||
@@ -4127,6 +4163,34 @@ function process_cookies() {
|
||||
load_tweaks();
|
||||
}
|
||||
|
||||
function position_context_menu(contextMenu, x, y) {
|
||||
// Calculate where to position context menu based on window confines and
|
||||
// menu size.
|
||||
|
||||
let height = contextMenu.clientHeight;
|
||||
let width = contextMenu.clientWidth;
|
||||
|
||||
let bounds = {
|
||||
top: 0,
|
||||
bottom: window.innerHeight,
|
||||
left: 0,
|
||||
right: window.innerWidth,
|
||||
};
|
||||
|
||||
let farMenuBounds = {
|
||||
top: y,
|
||||
bottom: y + height,
|
||||
left: x,
|
||||
right: x + width,
|
||||
};
|
||||
|
||||
if (farMenuBounds.right > bounds.right) x -= farMenuBounds.right - bounds.right;
|
||||
if (farMenuBounds.bottom > bounds.bottom) y -= farMenuBounds.bottom - bounds.bottom;
|
||||
|
||||
contextMenu.style.left = `${x}px`;
|
||||
contextMenu.style.top = `${y}px`;
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
on_colab = document.getElementById("on_colab").textContent == "true";
|
||||
|
||||
@@ -4290,6 +4354,69 @@ $(document).ready(function(){
|
||||
debugContainer.addEventListener("click", function(e) {
|
||||
debugContainer.classList.add("hidden");
|
||||
});
|
||||
|
||||
// Context menu
|
||||
const contextMenu = $e("div", document.body, {id: "context-menu"});
|
||||
|
||||
for (const action of context_menu_actions) {
|
||||
// Null adds horizontal rule
|
||||
if (!action) {
|
||||
$e("hr", contextMenu);
|
||||
continue;
|
||||
}
|
||||
|
||||
let item = $e("div", contextMenu, {
|
||||
classes: ["context-menu-item", "noselect"],
|
||||
"visibility-condition": action.visibilityCondition
|
||||
});
|
||||
let icon = $e("span", item, {classes: ["material-icons-outlined"], innerText: action.icon});
|
||||
item.append(action.label);
|
||||
|
||||
item.addEventListener("mousedown", (e) => (e.preventDefault()));
|
||||
item.addEventListener("click", action.click);
|
||||
}
|
||||
|
||||
$("#gamescreen").contextmenu(function(event) {
|
||||
// Don't open browser context menu
|
||||
event.preventDefault();
|
||||
|
||||
// Close if open
|
||||
if (!contextMenu.classList.contains("hidden")) {
|
||||
contextMenu.classList.add("hidden");
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable non-applicable items
|
||||
$(".context-menu-item").addClass("disabled");
|
||||
|
||||
// A selection is made
|
||||
if (getSelectionText()) $(".context-menu-item[visibility-condition=SELECTION]").removeClass("disabled");
|
||||
|
||||
// The caret is placed
|
||||
if (get_caret_position($("#gamescreen")[0]) !== null) $(".context-menu-item[visibility-condition=CARET]").removeClass("disabled");
|
||||
|
||||
contextMenu.classList.remove("hidden");
|
||||
|
||||
// Set position to click position
|
||||
position_context_menu(contextMenu, event.originalEvent.x, event.originalEvent.y);
|
||||
|
||||
// Don't let the document contextmenu catch us and close our context menu
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
// When we make a browser context menu, close ours.
|
||||
$(document).contextmenu(function(event) {
|
||||
contextMenu.classList.add("hidden");
|
||||
});
|
||||
|
||||
// When we click outside of our context menu, close ours.
|
||||
$(document).click(function(event) {
|
||||
contextMenu.classList.add("hidden");
|
||||
});
|
||||
|
||||
window.addEventListener("blur", function(event) {
|
||||
contextMenu.classList.add("hidden");
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", function(event) {
|
||||
|
@@ -137,7 +137,5 @@
|
||||
<div id="file-upload-notice" class="hidden">
|
||||
<span class="material-icons-outlined">upload_file</span>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user