mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-04 05:40:58 +00:00
* feat(web-shell): use popovers for composer controls * fix(web-shell): address popover review feedback * fix(web-shell): update popover regression coverage * fix(web-shell): address popover review feedback * fix(web-shell): stabilize toolbar label collapse --------- Co-authored-by: ytahdn <ytahdn@gmail.com>
117 lines
2.7 KiB
TypeScript
117 lines
2.7 KiB
TypeScript
export interface ToolbarDropdownItem {
|
|
id: string;
|
|
label: string;
|
|
searchText?: string;
|
|
}
|
|
|
|
export function filterToolbarDropdownItems<T extends ToolbarDropdownItem>(
|
|
items: readonly T[],
|
|
query: string,
|
|
): T[] {
|
|
const normalized = query.trim().toLocaleLowerCase();
|
|
if (!normalized) return [...items];
|
|
return items.filter((item) =>
|
|
`${item.label}\n${item.searchText ?? ''}`
|
|
.toLocaleLowerCase()
|
|
.includes(normalized),
|
|
);
|
|
}
|
|
|
|
export function getToolbarItemVisibility({
|
|
availableWidth,
|
|
items,
|
|
}: {
|
|
availableWidth: number;
|
|
items: ReadonlyArray<{
|
|
id: string;
|
|
expansionWidth: number;
|
|
ready?: boolean;
|
|
}>;
|
|
}): Record<string, boolean> {
|
|
const visibility = Object.fromEntries(
|
|
items.map((item) => [item.id, item.ready !== false]),
|
|
);
|
|
let usedWidth = items.reduce(
|
|
(total, item) => total + (visibility[item.id] ? item.expansionWidth : 0),
|
|
0,
|
|
);
|
|
|
|
for (const item of items) {
|
|
if (usedWidth <= availableWidth) break;
|
|
if (!visibility[item.id]) continue;
|
|
visibility[item.id] = false;
|
|
usedWidth -= item.expansionWidth;
|
|
}
|
|
|
|
return visibility;
|
|
}
|
|
|
|
export function getToolbarItemVisibilityWithHysteresis({
|
|
availableWidth,
|
|
items,
|
|
currentVisibility,
|
|
expansionMargin,
|
|
}: {
|
|
availableWidth: number;
|
|
items: ReadonlyArray<{
|
|
id: string;
|
|
expansionWidth: number;
|
|
ready?: boolean;
|
|
}>;
|
|
currentVisibility: Readonly<Record<string, boolean>>;
|
|
expansionMargin: number;
|
|
}): Record<string, boolean> {
|
|
const collapseVisibility = getToolbarItemVisibility({
|
|
availableWidth,
|
|
items,
|
|
});
|
|
const expansionVisibility = getToolbarItemVisibility({
|
|
availableWidth: Math.max(0, availableWidth - expansionMargin),
|
|
items,
|
|
});
|
|
|
|
return Object.fromEntries(
|
|
items.map((item) => [
|
|
item.id,
|
|
currentVisibility[item.id]
|
|
? collapseVisibility[item.id]
|
|
: expansionVisibility[item.id],
|
|
]),
|
|
);
|
|
}
|
|
|
|
export function getToolbarExpansionBudget({
|
|
toolbarWidth,
|
|
leadingWidth,
|
|
rightWidth,
|
|
currentExpansionWidth,
|
|
gap,
|
|
}: {
|
|
toolbarWidth: number;
|
|
leadingWidth: number;
|
|
rightWidth: number;
|
|
currentExpansionWidth: number;
|
|
gap: number;
|
|
}): number {
|
|
const fixedLeadingWidth = Math.max(0, leadingWidth - currentExpansionWidth);
|
|
return Math.max(0, toolbarWidth - rightWidth - fixedLeadingWidth - gap);
|
|
}
|
|
|
|
export function resolveToolbarModelLabel({
|
|
currentModelLabel,
|
|
lastConfirmedModelLabel,
|
|
}: {
|
|
currentModelLabel: string;
|
|
lastConfirmedModelLabel: string;
|
|
}): {
|
|
modelLabel: string;
|
|
modelLabelReady: boolean;
|
|
nextConfirmedModelLabel: string;
|
|
} {
|
|
const nextConfirmedModelLabel = currentModelLabel || lastConfirmedModelLabel;
|
|
return {
|
|
modelLabel: nextConfirmedModelLabel,
|
|
modelLabelReady: Boolean(nextConfirmedModelLabel),
|
|
nextConfirmedModelLabel,
|
|
};
|
|
}
|