mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-08-02 18:10:18 +05:30
fix(polish): address 3 review blockers + 1 security issue
1. ThemeSettings: change 'auto' radio value to 'system' to match the v5 settingsSchema enum. Storing 'auto' silently wipes all settings on next launch. 2. UpdateBanner: render an 'available' branch so users see a CTA when a new version is detected (the store already had this state, but the banner was silent). Added a test. 3. feed-config: remove the unused resolveFeedUrl / FEEDS exports. feedConfigFor is the actual implementation used by the IPC handler. Updated tests to match. 4. main/index.js: tighten app:open-external regex to https:// only.
This commit is contained in:
+1
-1
@@ -2260,7 +2260,7 @@ ipcMain.on('app:quit', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('app:open-external', (_event, url) => {
|
ipcMain.on('app:open-external', (_event, url) => {
|
||||||
if (typeof url === 'string' && /^https?:\/\//i.test(url)) {
|
if (typeof url === 'string' && /^https:\/\//i.test(url)) {
|
||||||
shell.openExternal(url).catch((e) => console.error('[app:open-external]', e));
|
shell.openExternal(url).catch((e) => console.error('[app:open-external]', e));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,33 +1,3 @@
|
|||||||
const REPO = 'amitwh/markdown-converter';
|
|
||||||
|
|
||||||
const FEEDS = {
|
|
||||||
github: {
|
|
||||||
base: `https://github.com/${REPO}/releases/download`,
|
|
||||||
},
|
|
||||||
concreteinfo: {
|
|
||||||
base: 'https://updates.concreteinfo.co.in/v5',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
function platformSuffix(platform) {
|
|
||||||
if (platform === 'darwin' || platform === 'mac') return 'mac';
|
|
||||||
if (platform === 'win32' || platform === 'windows') return 'windows';
|
|
||||||
return 'linux';
|
|
||||||
}
|
|
||||||
|
|
||||||
function feedForChannel(channel, version, platform) {
|
|
||||||
const suffix = platformSuffix(platform);
|
|
||||||
const f = FEEDS[channel] || FEEDS.github;
|
|
||||||
if (channel === 'github') {
|
|
||||||
return `${f.base}/v${version}/latest-${suffix}.yml`;
|
|
||||||
}
|
|
||||||
return `${f.base}/latest-${suffix}.yml`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveFeedUrl(channel, version, platform) {
|
|
||||||
return feedForChannel(channel, version, platform);
|
|
||||||
}
|
|
||||||
|
|
||||||
function feedConfigFor(channel) {
|
function feedConfigFor(channel) {
|
||||||
if (channel === 'github') {
|
if (channel === 'github') {
|
||||||
return { provider: 'github', owner: 'amitwh', repo: 'markdown-converter' };
|
return { provider: 'github', owner: 'amitwh', repo: 'markdown-converter' };
|
||||||
@@ -35,4 +5,4 @@ function feedConfigFor(channel) {
|
|||||||
return { provider: 'generic', url: 'https://updates.concreteinfo.co.in/v5' };
|
return { provider: 'generic', url: 'https://updates.concreteinfo.co.in/v5' };
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { resolveFeedUrl, feedConfigFor, FEEDS };
|
module.exports = { feedConfigFor };
|
||||||
|
|||||||
@@ -18,6 +18,17 @@ export function UpdateBanner() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state === 'available') {
|
||||||
|
return (
|
||||||
|
<div data-testid="update-banner" className="bg-blue-50 border-b border-blue-200 px-4 py-2 text-sm">
|
||||||
|
A new version (v{version}) is available.{' '}
|
||||||
|
<button onClick={() => useUpdaterStore.getState().check()} className="underline">
|
||||||
|
Download now
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (state === 'downloading') {
|
if (state === 'downloading') {
|
||||||
return (
|
return (
|
||||||
<div data-testid="update-banner" className="bg-blue-50 border-b border-blue-200 px-4 py-2 text-sm">
|
<div data-testid="update-banner" className="bg-blue-50 border-b border-blue-200 px-4 py-2 text-sm">
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ export function ThemeSettings() {
|
|||||||
<div className="space-y-5 text-sm">
|
<div className="space-y-5 text-sm">
|
||||||
<div>
|
<div>
|
||||||
<Label>Mode</Label>
|
<Label>Mode</Label>
|
||||||
<RadioGroup value={theme} onValueChange={(v) => setSetting('theme', v as 'light' | 'dark' | 'auto')}>
|
<RadioGroup value={theme} onValueChange={(v) => setSetting('theme', v as 'light' | 'dark' | 'system')}>
|
||||||
<div className="flex items-center gap-2"><RadioGroupItem value="light" id="theme-light" /><Label htmlFor="theme-light">Light</Label></div>
|
<div className="flex items-center gap-2"><RadioGroupItem value="light" id="theme-light" /><Label htmlFor="theme-light">Light</Label></div>
|
||||||
<div className="flex items-center gap-2"><RadioGroupItem value="dark" id="theme-dark" /><Label htmlFor="theme-dark">Dark</Label></div>
|
<div className="flex items-center gap-2"><RadioGroupItem value="dark" id="theme-dark" /><Label htmlFor="theme-dark">Dark</Label></div>
|
||||||
<div className="flex items-center gap-2"><RadioGroupItem value="auto" id="theme-auto" /><Label htmlFor="theme-auto">Auto (system)</Label></div>
|
<div className="flex items-center gap-2"><RadioGroupItem value="system" id="theme-system" /><Label htmlFor="theme-system">System</Label></div>
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -40,6 +40,13 @@ describe('UpdateBanner', () => {
|
|||||||
expect(screen.getByText(/couldn.?t check/i)).toBeInTheDocument();
|
expect(screen.getByText(/couldn.?t check/i)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('shows download CTA when state is available', () => {
|
||||||
|
useUpdaterStore.setState({ state: 'available', version: '5.0.2' });
|
||||||
|
render(<UpdateBanner />);
|
||||||
|
expect(screen.getByText(/5\.0\.2/)).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(/download/i)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
test('restart button calls ipc.updater.install', () => {
|
test('restart button calls ipc.updater.install', () => {
|
||||||
useUpdaterStore.setState({ state: 'ready', version: '5.0.2' });
|
useUpdaterStore.setState({ state: 'ready', version: '5.0.2' });
|
||||||
render(<UpdateBanner />);
|
render(<UpdateBanner />);
|
||||||
|
|||||||
@@ -1,36 +1,5 @@
|
|||||||
const { resolveFeedUrl, feedConfigFor, FEEDS } = require('../../../../src/main/updater/feed-config');
|
const { feedConfigFor } = require('../../../../src/main/updater/feed-config');
|
||||||
|
|
||||||
describe('feed-config', () => {
|
|
||||||
test('resolves github channel to GitHub Releases feed', () => {
|
|
||||||
const url = resolveFeedUrl('github', '5.0.2', 'mac');
|
|
||||||
expect(url).toBe('https://github.com/amitwh/markdown-converter/releases/download/v5.0.2/latest-mac.yml');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('resolves concreteinfo channel to CI feed', () => {
|
|
||||||
const url = resolveFeedUrl('concreteinfo', '5.0.2', 'mac');
|
|
||||||
expect(url).toBe('https://updates.concreteinfo.co.in/v5/latest-mac.yml');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('resolves windows platform correctly', () => {
|
|
||||||
const url = resolveFeedUrl('github', '5.0.2', 'windows');
|
|
||||||
expect(url).toContain('latest-windows.yml');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('resolves linux platform correctly', () => {
|
|
||||||
const url = resolveFeedUrl('github', '5.0.2', 'linux');
|
|
||||||
expect(url).toContain('latest-linux.yml');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('falls back to github on unknown channel', () => {
|
|
||||||
const url = resolveFeedUrl('something-weird', '5.0.2', 'mac');
|
|
||||||
expect(url).toContain('github.com');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('exports both feeds as constants', () => {
|
|
||||||
expect(FEEDS.github).toBeDefined();
|
|
||||||
expect(FEEDS.concreteinfo).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('feedConfigFor', () => {
|
describe('feedConfigFor', () => {
|
||||||
test('returns github provider config for github channel', () => {
|
test('returns github provider config for github channel', () => {
|
||||||
const config = feedConfigFor('github');
|
const config = feedConfigFor('github');
|
||||||
|
|||||||
Reference in New Issue
Block a user