Skip to content

Commit c5056d6

Browse files
committed
feat: multi-provider AI settings with themed dialog
Add support for multiple named API providers with an active selection dropdown, replacing the single flat-pref settings dialog. Includes Mustache template, migration from old prefs, and light/dark theme support.
1 parent 7b0b370 commit c5056d6

2 files changed

Lines changed: 204 additions & 11 deletions

File tree

src/nls/root/strings.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1940,6 +1940,20 @@ define({
19401940
"AI_SETTINGS_SAVE": "Save",
19411941
"AI_SETTINGS_RESET": "Reset",
19421942
"AI_SETTINGS_CUSTOM_ENDPOINT_NOTICE": "Using custom API endpoint: {0}",
1943+
"AI_SETTINGS_ACTIVE_PROVIDER": "Active Provider",
1944+
"AI_SETTINGS_DEFAULT_PROVIDER": "Default (Local Claude Code)",
1945+
"AI_SETTINGS_PROVIDERS": "Providers",
1946+
"AI_SETTINGS_ADD_PROVIDER": "+ Add Provider",
1947+
"AI_SETTINGS_EDIT": "Edit",
1948+
"AI_SETTINGS_DELETE": "Delete",
1949+
"AI_SETTINGS_PROVIDER_NAME": "Name",
1950+
"AI_SETTINGS_PROVIDER_NAME_PLACEHOLDER": "e.g. My API Provider",
1951+
"AI_SETTINGS_SAVE_PROVIDER": "Save Provider",
1952+
"AI_SETTINGS_DELETE_PROVIDER": "Delete Provider",
1953+
"AI_SETTINGS_DELETE_ACTIVE_CONFIRM": "\"{0}\" is the active provider. Deleting it will revert to the default. Continue?",
1954+
"AI_SETTINGS_NAME_REQUIRED": "Provider name is required.",
1955+
"AI_SETTINGS_NAME_DUPLICATE": "A provider with this name already exists.",
1956+
"AI_SETTINGS_DONE": "Done",
19431957

19441958
// demo start - Phoenix Code Playground - Interactive Onboarding
19451959
"DEMO_SECTION1_TITLE": "Edit in Live Preview",

src/styles/Extn-AIChatPanel.less

Lines changed: 190 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,11 +1620,171 @@
16201620

16211621
/* ── AI Settings Dialog ────────────────────────────────────────────── */
16221622
.ai-settings-dialog {
1623-
.ai-settings-form {
1623+
.ai-settings-section-label {
1624+
font-size: 12px;
1625+
font-weight: 600;
1626+
color: @bc-text-medium;
1627+
margin-bottom: 6px;
1628+
1629+
.dark & {
1630+
color: @dark-bc-text-medium;
1631+
}
1632+
}
1633+
1634+
.ai-settings-select-wrapper {
1635+
position: relative;
1636+
}
1637+
1638+
.ai-settings-active-select {
1639+
width: 100%;
1640+
box-sizing: border-box;
1641+
padding: 6px 28px 6px 10px;
1642+
height: 30px;
1643+
border: 1px solid @bc-panel-border;
1644+
border-radius: @bc-border-radius;
1645+
background: @bc-input-bg;
1646+
color: @bc-text;
1647+
font-size: 13px;
1648+
outline: none;
1649+
appearance: none;
1650+
-webkit-appearance: none;
1651+
cursor: pointer;
1652+
1653+
&:focus {
1654+
border-color: @bc-btn-border-focused;
1655+
}
1656+
1657+
.dark & {
1658+
border-color: @dark-bc-panel-border;
1659+
background: @dark-bc-input-bg;
1660+
color: @dark-bc-text;
1661+
1662+
&:focus {
1663+
border-color: @dark-bc-btn-border-focused;
1664+
}
1665+
}
1666+
}
1667+
1668+
.ai-settings-select-arrow {
1669+
position: absolute;
1670+
right: 10px;
1671+
top: 10px;
1672+
font-size: 10px;
1673+
line-height: 1;
1674+
color: @bc-text-quiet;
1675+
pointer-events: none;
1676+
1677+
.dark & {
1678+
color: @dark-bc-text-quiet;
1679+
}
1680+
}
1681+
1682+
.ai-settings-divider {
1683+
border: none;
1684+
border-top: 1px solid @bc-panel-separator;
1685+
margin: 14px 0;
1686+
1687+
.dark & {
1688+
border-top-color: @dark-bc-panel-separator;
1689+
}
1690+
}
1691+
1692+
.ai-settings-provider-list {
1693+
display: flex;
1694+
flex-direction: column;
1695+
gap: 6px;
1696+
margin-bottom: 10px;
1697+
}
1698+
1699+
.ai-settings-provider-card {
1700+
display: flex;
1701+
align-items: center;
1702+
justify-content: space-between;
1703+
padding: 8px 10px;
1704+
border: 1px solid @bc-panel-border;
1705+
border-radius: @bc-border-radius;
1706+
background: @bc-panel-bg-alt;
1707+
1708+
.dark & {
1709+
border-color: @dark-bc-panel-border;
1710+
background: @dark-bc-panel-bg-alt;
1711+
}
1712+
}
1713+
1714+
.ai-settings-provider-info {
16241715
display: flex;
16251716
flex-direction: column;
1626-
gap: 14px;
1627-
padding: 4px 0;
1717+
gap: 2px;
1718+
min-width: 0;
1719+
flex: 1;
1720+
}
1721+
1722+
.ai-settings-provider-name {
1723+
font-size: 13px;
1724+
font-weight: 600;
1725+
color: @bc-text;
1726+
white-space: nowrap;
1727+
overflow: hidden;
1728+
text-overflow: ellipsis;
1729+
1730+
.dark & {
1731+
color: @dark-bc-text;
1732+
}
1733+
}
1734+
1735+
.ai-settings-provider-url {
1736+
font-size: 11px;
1737+
color: @bc-text-quiet;
1738+
white-space: nowrap;
1739+
overflow: hidden;
1740+
text-overflow: ellipsis;
1741+
1742+
.dark & {
1743+
color: @dark-bc-text-quiet;
1744+
}
1745+
}
1746+
1747+
.ai-settings-provider-actions {
1748+
display: flex;
1749+
gap: 4px;
1750+
margin-left: 10px;
1751+
flex-shrink: 0;
1752+
}
1753+
1754+
.ai-settings-add-btn {
1755+
margin-bottom: 10px;
1756+
}
1757+
1758+
.ai-settings-edit-form {
1759+
display: flex;
1760+
flex-direction: column;
1761+
gap: 10px;
1762+
padding: 12px;
1763+
border: 1px solid @bc-btn-border-focused;
1764+
border-radius: @bc-border-radius;
1765+
background: @bc-panel-bg-alt;
1766+
margin-bottom: 10px;
1767+
1768+
.dark & {
1769+
border-color: @dark-bc-btn-border-focused;
1770+
background: @dark-bc-panel-bg-alt;
1771+
}
1772+
}
1773+
1774+
.ai-settings-edit-error {
1775+
font-size: 12px;
1776+
color: @bc-error;
1777+
min-height: 0;
1778+
1779+
&:not(:empty) {
1780+
min-height: 16px;
1781+
}
1782+
}
1783+
1784+
.ai-settings-edit-actions {
1785+
display: flex;
1786+
justify-content: flex-end;
1787+
gap: 8px;
16281788
}
16291789

16301790
.ai-settings-field {
@@ -1635,28 +1795,47 @@
16351795
label {
16361796
font-size: 12px;
16371797
font-weight: 600;
1638-
color: @project-panel-text-2;
1798+
color: @bc-text-medium;
1799+
1800+
.dark & {
1801+
color: @dark-bc-text-medium;
1802+
}
16391803
}
16401804

16411805
input {
16421806
width: 100%;
16431807
box-sizing: border-box;
16441808
padding: 8px 10px;
16451809
height: 30px;
1646-
border: 1px solid rgba(255, 255, 255, 0.15);
1647-
border-radius: 3px;
1648-
background: rgba(0, 0, 0, 0.2);
1649-
color: @project-panel-text-1;
1810+
border: 1px solid @bc-panel-border;
1811+
border-radius: @bc-border-radius;
1812+
background: @bc-input-bg;
1813+
color: @bc-text;
16501814
font-size: 13px;
16511815
outline: none;
16521816

16531817
&:focus {
1654-
border-color: rgba(76, 175, 80, 0.5);
1818+
border-color: @bc-btn-border-focused;
16551819
}
16561820

16571821
&::placeholder {
1658-
color: @project-panel-text-2;
1659-
opacity: 0.5;
1822+
color: @bc-text-quiet;
1823+
opacity: 0.7;
1824+
}
1825+
1826+
.dark & {
1827+
border-color: @dark-bc-panel-border;
1828+
background: @dark-bc-input-bg;
1829+
color: @dark-bc-text;
1830+
1831+
&:focus {
1832+
border-color: @dark-bc-btn-border-focused;
1833+
}
1834+
1835+
&::placeholder {
1836+
color: @dark-bc-text-quiet;
1837+
opacity: 0.7;
1838+
}
16601839
}
16611840
}
16621841
}

0 commit comments

Comments
 (0)