mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 10:51:22 +00:00
Initial Commit of speed dial improvement
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -22,20 +22,92 @@ assert.equal(
|
||||
"duplicate labels should use the opaque id without interpreting its contents"
|
||||
);
|
||||
|
||||
assert.equal(ctx.shouldRenderActionList(""), false, "an empty search keeps the action list hidden");
|
||||
assert.equal(ctx.shouldRenderActionList(" "), false, "whitespace-only search keeps the action list hidden");
|
||||
assert.equal(ctx.shouldRenderActionList(""), false, "an empty search keeps recent/empty list");
|
||||
assert.equal(ctx.shouldRenderActionList(" "), false, "whitespace-only search keeps recent/empty list");
|
||||
assert.equal(ctx.shouldRenderActionList("r"), true, "typing starts rendering matching actions");
|
||||
|
||||
// commandList: an empty query shows recents; a typed query filters all actions.
|
||||
assert.deepEqual(ctx.commandList(duplicateActions, [], ""), [],
|
||||
"empty query + no recents shows nothing");
|
||||
assert.deepEqual(ctx.commandList(duplicateActions, [duplicateActions[0]], ""),
|
||||
[duplicateActions[0]],
|
||||
"empty query shows the recent list");
|
||||
assert.deepEqual(ctx.commandList(duplicateActions, [], "rep"), duplicateActions,
|
||||
"a typed query filters actions (both identical titles match) instead of showing recents");
|
||||
|
||||
// filterTabs (tab phase): an empty query keeps the whole list; a typed query filters by title/id.
|
||||
const tabOptions = [
|
||||
{ id: "home", title: "Home" },
|
||||
{ id: "prepare", title: "Prepare" },
|
||||
{ id: "monitor", title: "Device" },
|
||||
{ id: "project", title: "Project" }
|
||||
];
|
||||
assert.deepEqual(ctx.filterTabs(tabOptions, ""), tabOptions,
|
||||
"empty query keeps the whole tab list");
|
||||
assert.equal(ctx.filterTabs(tabOptions, "prep").length, 1,
|
||||
"a typed query filters tabs by title");
|
||||
assert.equal(ctx.filterTabs(tabOptions, "Device").length, 1,
|
||||
"a typed query matches a tab title");
|
||||
assert.deepEqual(ctx.filterTabs(tabOptions, "zzz"), [],
|
||||
"a typed query with no match returns an empty list");
|
||||
|
||||
// tabTitle: pages added with an empty title (e.g. MainFrame's Home tab) fall back to the id.
|
||||
assert.equal(ctx.tabTitle({ id: "home", title: "" }), "Home",
|
||||
"an empty title falls back to the title-cased id");
|
||||
assert.equal(ctx.tabTitle({ id: "home" }), "Home",
|
||||
"a missing title falls back to the title-cased id");
|
||||
assert.equal(ctx.tabTitle({ id: "prepare", title: "Prepare" }), "Prepare",
|
||||
"a populated title is kept as-is");
|
||||
assert.equal(ctx.tabTitle({ id: "prepare", title: " Prepare" }), "Prepare",
|
||||
"a leading space from the Notebook button label is trimmed so the icon letter shows");
|
||||
assert.equal(ctx.filterTabs([{ id: "home", title: "" }], "home").length, 1,
|
||||
"an untitled tab still matches a typed query via the id/title fallback");
|
||||
assert.equal(ctx.filterTabs([{ id: "prepare", title: " Prepare" }], "prepare").length, 1,
|
||||
"a leading-space tab title still matches a typed query");
|
||||
|
||||
// settingCode: a setting tile uses the leaf option-name initial (label's last " : "-segment),
|
||||
// escalated by category, then a stable ordinal - so settings aren't all a generic "S".
|
||||
const settings = [
|
||||
{ opt_key: "layer_height", label: "Quality : Layer Height", category: "Quality", type: 0 },
|
||||
{ opt_key: "smooth", label: "Quality : Smooth", category: "Quality", type: 0 }
|
||||
];
|
||||
assert.equal(ctx.leafLabel({ label: "Quality : Layer Height", opt_key: "x" }), "Layer Height",
|
||||
"leafLabel takes the last segment of the label");
|
||||
assert.equal(ctx.settingCode(settings[0], settings), "L",
|
||||
"a unique leaf initial yields a single letter");
|
||||
// renderSettingRow iterates settingsResults, so the coded item is always a member of the list.
|
||||
const infillQ = { opt_key: "a", label: "Quality : Infill", category: "Quality", type: 0 };
|
||||
const infillS = { opt_key: "b", label: "Supports : Infill", category: "Supports", type: 0 };
|
||||
const sameLeaf = [infillQ, infillS];
|
||||
assert.equal(ctx.settingCode(infillQ, sameLeaf), "QI",
|
||||
"a colliding leaf initial escalates to category + initial");
|
||||
assert.equal(ctx.settingCode(infillS, sameLeaf), "SI",
|
||||
"a different category disambiguates the same leaf initial");
|
||||
const dupQ = [
|
||||
{ opt_key: "a", label: "Quality : Infill", category: "Quality", type: 0 },
|
||||
{ opt_key: "b", label: "Quality : Infill", category: "Quality", type: 0 }
|
||||
];
|
||||
assert.equal(ctx.settingCode(dupQ[0], dupQ), "QI1",
|
||||
"both title and category collide -> stable ordinal by opt_key");
|
||||
assert.equal(ctx.settingCode(dupQ[1], dupQ), "QI2",
|
||||
"the ordinal advances by opt_key order");
|
||||
|
||||
// selectedActionId: resolves the active list (recents for an empty query, filtered list otherwise).
|
||||
assert.equal(
|
||||
ctx.selectedActionId({ zone: "list", i: 0 }, duplicateActions, [], ""),
|
||||
ctx.selectedActionId({ zone: "list", i: 0 }, ctx.commandList(duplicateActions, [], ""), [], ""),
|
||||
null,
|
||||
"Enter with an empty query must not resolve to an action the blank list never showed"
|
||||
"Enter with an empty query and no recents must not resolve to an action the list never showed"
|
||||
);
|
||||
assert.equal(
|
||||
ctx.selectedActionId({ zone: "list", i: 0 }, duplicateActions, [], "rep"),
|
||||
ctx.selectedActionId({ zone: "list", i: 0 }, ctx.commandList(duplicateActions, [], "rep"), [], "rep"),
|
||||
"0123456789abcdef",
|
||||
"a typed query resolves the list selection"
|
||||
);
|
||||
assert.equal(
|
||||
ctx.selectedActionId({ zone: "list", i: 0 }, ctx.commandList(duplicateActions, [duplicateActions[0]], ""), [], ""),
|
||||
"0123456789abcdef",
|
||||
"Enter with an empty query resolves the recent entry"
|
||||
);
|
||||
assert.equal(
|
||||
ctx.selectedActionId({ zone: "fav", i: 0 }, duplicateActions, ["fedcba9876543210"], ""),
|
||||
"fedcba9876543210",
|
||||
|
||||
@@ -55,6 +55,28 @@ body {
|
||||
border: 1px solid var(--speed-tile-border, #d8d8d8);
|
||||
}
|
||||
.fav-tile.sel { outline: 2px solid var(--main-color, var(--orca-accent, #009688)); outline-offset: 2px; }
|
||||
/* Hover-revealed remove button in the tile's corner; sits inside the tile bounds so overflow:hidden clips it. */
|
||||
.fav-tile { position: relative; }
|
||||
.fav-unpin {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--muted, var(--orca-muted, #6b7280));
|
||||
background: rgba(127,127,127,.35);
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
}
|
||||
.fav-tile:hover .fav-unpin,
|
||||
.fav-tile.sel .fav-unpin { opacity: 1; }
|
||||
.fav-unpin:hover { background: rgba(127,127,127,.6); }
|
||||
.ctx-menu {
|
||||
position: fixed;
|
||||
z-index: 10;
|
||||
@@ -127,6 +149,15 @@ body {
|
||||
color: var(--muted, var(--orca-muted, #6b7280));
|
||||
}
|
||||
.dial-count[hidden] { display: none; }
|
||||
/* Section header inside the list (e.g. the "Recent" row above the recent entries). */
|
||||
.dial-group {
|
||||
padding: 8px 8px 2px;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .06em;
|
||||
color: var(--muted, var(--orca-muted, #6b7280));
|
||||
}
|
||||
.dial-list {
|
||||
flex: 0 1 auto;
|
||||
min-height: 0;
|
||||
|
||||
Reference in New Issue
Block a user