Skip to content

Commit 877b4ef

Browse files
committed
Merge branch 'fix/marketplace-review-round2': settings search, release attestations, 1.13 deprecations
2 parents ca4be04 + 4874316 commit 877b4ef

7 files changed

Lines changed: 156 additions & 12 deletions

File tree

.github/workflows/release.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ jobs:
1212
runs-on: ubuntu-latest
1313
permissions:
1414
contents: write
15+
# Required by attest-build-provenance to sign and store attestations.
16+
id-token: write
17+
attestations: write
1518

1619
steps:
1720
- name: Checkout code
@@ -44,6 +47,16 @@ jobs:
4447
- name: Validate release artifacts
4548
run: npm run release:check
4649

50+
# Provenance lets users cryptographically verify the assets were built
51+
# from this repository by this workflow (gh attestation verify).
52+
- name: Attest build provenance
53+
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
54+
with:
55+
subject-path: |
56+
main.js
57+
manifest.json
58+
styles.css
59+
4760
# Release notes come from the curated CHANGELOG.md section, not from
4861
# commit messages. A missing section means [Unreleased] was not renamed
4962
# before tagging, so fail instead of shipping empty notes.

package-lock.json

Lines changed: 19 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"eslint-plugin-simple-import-sort": "^12.1.1",
4747
"jest": "^30.3.0",
4848
"jest-environment-jsdom": "^30.3.0",
49-
"obsidian": "latest",
49+
"obsidian": "^1.13.1",
5050
"ts-jest": "^29.4.9",
5151
"typescript": "^6.0.2"
5252
},

src/features/settings/settings-tab.ts

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { App } from 'obsidian';
1+
import type { App, SettingDefinitionItem } from 'obsidian';
22
import { Notice, PluginSettingTab, Setting } from 'obsidian';
33

44
import type { ChatViewPlacement } from '../../core/types/settings';
@@ -20,6 +20,111 @@ export class QoderianSettingTab extends PluginSettingTab {
2020
this.plugin = plugin;
2121
}
2222

23+
/**
24+
* Declarative mirror of display() for Obsidian's settings search (1.13+).
25+
* Rendering stays imperative in display(); these definitions only feed the
26+
* search index, so every entry is a plain name/desc row grouped under the
27+
* same headings the page shows.
28+
*/
29+
getSettingDefinitions(): SettingDefinitionItem[] {
30+
setLocale(this.plugin.settings.locale as Locale);
31+
32+
return [
33+
{
34+
type: 'group',
35+
heading: t('settings.setup'),
36+
items: [
37+
{ name: t('settings.cliPath.name'), desc: t('settings.cliPath.desc') },
38+
],
39+
},
40+
{ name: t('settings.language.name'), desc: t('settings.language.desc') },
41+
{
42+
type: 'group',
43+
heading: t('settings.display'),
44+
items: [
45+
{ name: t('settings.maxTabs.name'), desc: t('settings.maxTabs.desc') },
46+
{ name: t('settings.chatViewPlacement.name'), desc: t('settings.chatViewPlacement.desc') },
47+
{ name: t('settings.enableAutoScroll.name'), desc: t('settings.enableAutoScroll.desc') },
48+
{ name: t('settings.deferMathRenderingDuringStreaming.name'), desc: t('settings.deferMathRenderingDuringStreaming.desc') },
49+
{ name: t('settings.expandFileEditsByDefault.name'), desc: t('settings.expandFileEditsByDefault.desc') },
50+
],
51+
},
52+
{
53+
type: 'group',
54+
heading: t('settings.conversations'),
55+
items: [
56+
{ name: t('settings.autoTitle.name'), desc: t('settings.autoTitle.desc') },
57+
{
58+
name: t('settings.titleModel.name'),
59+
desc: t('settings.titleModel.desc'),
60+
visible: () => this.plugin.settings.enableAutoTitleGeneration,
61+
},
62+
],
63+
},
64+
{
65+
type: 'group',
66+
heading: t('settings.content'),
67+
items: [
68+
{ name: t('settings.userName.name'), desc: t('settings.userName.desc') },
69+
{ name: t('settings.systemPrompt.name'), desc: t('settings.systemPrompt.desc') },
70+
{ name: t('settings.excludedTags.name'), desc: t('settings.excludedTags.desc') },
71+
{ name: t('settings.mediaFolder.name'), desc: t('settings.mediaFolder.desc') },
72+
],
73+
},
74+
{
75+
type: 'group',
76+
heading: t('settings.input'),
77+
items: [
78+
{ name: t('settings.requireCommandOrControlEnterToSend.name'), desc: t('settings.requireCommandOrControlEnterToSend.desc') },
79+
{ name: t('settings.navMappings.name'), desc: t('settings.navMappings.desc') },
80+
],
81+
},
82+
{
83+
type: 'group',
84+
heading: t('settings.safety'),
85+
items: [
86+
{ name: t('settings.loadUserSettings.name'), desc: t('settings.loadUserSettings.desc') },
87+
],
88+
},
89+
{
90+
type: 'group',
91+
heading: t('settings.slashCommands.name'),
92+
items: [
93+
{ name: t('settings.slashCommands.commands'), desc: t('settings.slashCommands.commandsDesc') },
94+
{ name: t('settings.slashCommands.skills'), desc: t('settings.slashCommands.skillsDesc') },
95+
],
96+
},
97+
{
98+
type: 'group',
99+
heading: t('settings.subagents.name'),
100+
items: [
101+
{ name: t('settings.subagents.name'), desc: t('settings.subagents.desc') },
102+
],
103+
},
104+
{
105+
type: 'group',
106+
heading: t('settings.mcpServers.name'),
107+
items: [
108+
{ name: t('settings.mcpServers.name'), desc: t('settings.mcpServers.desc') },
109+
],
110+
},
111+
{
112+
type: 'group',
113+
heading: t('settings.plugins.name'),
114+
items: [
115+
{ name: t('settings.plugins.name'), desc: t('settings.plugins.desc') },
116+
],
117+
},
118+
{
119+
type: 'group',
120+
heading: t('settings.experimental'),
121+
items: [
122+
{ name: t('settings.enableBangBash.name'), desc: t('settings.enableBangBash.desc') },
123+
],
124+
},
125+
];
126+
}
127+
23128
display(): void {
24129
const { containerEl } = this;
25130
containerEl.empty();
@@ -97,7 +202,6 @@ export class QoderianSettingTab extends PluginSettingTab {
97202
slider
98203
.setLimits(3, 10, 1)
99204
.setValue(this.plugin.settings.maxTabs ?? 3)
100-
.setDynamicTooltip()
101205
.onChange(async (value) => {
102206
this.plugin.settings.maxTabs = value;
103207
await this.plugin.saveSettings();

src/shared/modals/confirm-modal.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type App,Modal, Setting } from 'obsidian';
1+
import { type App,Modal, requireApiVersion, Setting } from 'obsidian';
22

33
import { t } from '../../i18n/i18n';
44

@@ -39,16 +39,23 @@ class ConfirmModal extends Modal {
3939
.setButtonText(t('common.cancel'))
4040
.onClick(() => this.close())
4141
)
42-
.addButton(btn =>
42+
.addButton(btn => {
4343
btn
4444
.setButtonText(this.confirmText)
45-
.setWarning()
4645
.onClick(() => {
4746
this.resolved = true;
4847
this.resolve(true);
4948
this.close();
50-
})
51-
);
49+
});
50+
// setDestructive replaced setWarning in 1.13. On older installs
51+
// covered by minAppVersion, apply the class the deprecated
52+
// setWarning() used to add instead of calling the API.
53+
if (requireApiVersion('1.13.0')) {
54+
btn.setDestructive();
55+
} else {
56+
btn.buttonEl.addClass('mod-warning');
57+
}
58+
});
5259
}
5360

5461
onClose() {

tests/__mocks__/obsidian.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,10 @@ export const MarkdownRenderer = {
263263

264264
export const setIcon = jest.fn();
265265

266+
// Tests run against the newest API surface, so version gates take the
267+
// modern branch by default.
268+
export const requireApiVersion = jest.fn(() => true);
269+
266270
export const addIcon = jest.fn();
267271

268272
// Notice mock that tracks constructor calls

tests/unit/shared/modals/confirm-modal.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ jest.mock('obsidian', () => {
4646
_onClick: null as null | (() => void),
4747
setButtonText: jest.fn().mockReturnThis(),
4848
setWarning: jest.fn().mockReturnThis(),
49+
setDestructive: jest.fn().mockReturnThis(),
4950
onClick: jest.fn((handler: () => void) => {
5051
btn._onClick = handler;
5152
return btn;

0 commit comments

Comments
 (0)