Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bin/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const DEFAULT_PAKE_OPTIONS: PakeCliOptions = {
minWidth: 0,
minHeight: 0,
ignoreCertificateErrors: false,
refreshInterval: 0,
newWindow: false,
install: false,
};
Expand Down
14 changes: 14 additions & 0 deletions bin/helpers/cli-program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,20 @@ ${green('|_| \\__,_|_|\\_\\___| can turn any webpage into a desktop app with
.argParser(validateNumberInput)
.hideHelp(),
)
.addOption(
new Option(
'--refresh-interval <number>',
'Auto-refresh page interval in seconds (0 disables)',
)
.default(DEFAULT.refreshInterval)
.argParser((value) => {
const interval = parseInt(value);
if (isNaN(interval) || interval < 0) {
throw new Error('--refresh-interval must be a number >= 0');
}
return interval;
}),
)
.addOption(
new Option(
'--ignore-certificate-errors',
Expand Down
2 changes: 2 additions & 0 deletions bin/helpers/merge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export async function mergeConfig(
minWidth,
minHeight,
ignoreCertificateErrors,
refreshInterval,
newWindow,
} = options;

Expand Down Expand Up @@ -108,6 +109,7 @@ export async function mergeConfig(
min_width: minWidth,
min_height: minHeight,
ignore_certificate_errors: ignoreCertificateErrors,
refresh_interval: refreshInterval,
new_window: newWindow,
};
Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions });
Expand Down
4 changes: 4 additions & 0 deletions bin/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ export interface PakeCliOptions {
// Ignore certificate errors (for self-signed certs), default false
ignoreCertificateErrors: boolean;

// Auto-refresh page interval in seconds, default 0 (disabled)
refreshInterval: number;

// Turn on rapid build mode (app only, no dmg/deb/msi), good for debugging
iterativeBuild: boolean;

Expand Down Expand Up @@ -163,6 +166,7 @@ export interface WindowConfig {
min_width: number;
min_height: number;
ignore_certificate_errors: boolean;
refresh_interval: number;
new_window: boolean;
}

Expand Down
13 changes: 12 additions & 1 deletion dist/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ async function mergeConfig(url, options, tauriConf) {
await fsExtra.copy(sourcePath, destPath);
}
}));
const { width, height, fullscreen, maximize, hideTitleBar, alwaysOnTop, appVersion, darkMode, disabledWebShortcuts, activationShortcut, userAgent, showSystemTray, systemTrayIcon, useLocalFile, identifier, name = 'pake-app', resizable = true, inject, proxyUrl, installerLanguage, hideOnClose, incognito, title, wasm, enableDragDrop, multiInstance, multiWindow, startToTray, forceInternalNavigation, internalUrlRegex, zoom, minWidth, minHeight, ignoreCertificateErrors, newWindow, } = options;
const { width, height, fullscreen, maximize, hideTitleBar, alwaysOnTop, appVersion, darkMode, disabledWebShortcuts, activationShortcut, userAgent, showSystemTray, systemTrayIcon, useLocalFile, identifier, name = 'pake-app', resizable = true, inject, proxyUrl, installerLanguage, hideOnClose, incognito, title, wasm, enableDragDrop, multiInstance, multiWindow, startToTray, forceInternalNavigation, internalUrlRegex, zoom, minWidth, minHeight, ignoreCertificateErrors, refreshInterval, newWindow, } = options;
const { platform } = process;
const platformHideOnClose = hideOnClose ?? platform === 'darwin';
const tauriConfWindowOptions = {
Expand All @@ -510,6 +510,7 @@ async function mergeConfig(url, options, tauriConf) {
min_width: minWidth,
min_height: minHeight,
ignore_certificate_errors: ignoreCertificateErrors,
refresh_interval: refreshInterval,
new_window: newWindow,
};
Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions });
Expand Down Expand Up @@ -2073,6 +2074,7 @@ const DEFAULT_PAKE_OPTIONS = {
minWidth: 0,
minHeight: 0,
ignoreCertificateErrors: false,
refreshInterval: 0,
newWindow: false,
install: false,
};
Expand Down Expand Up @@ -2225,6 +2227,15 @@ ${green('|_| \\__,_|_|\\_\\___| can turn any webpage into a desktop app with
.default(DEFAULT_PAKE_OPTIONS.minHeight)
.argParser(validateNumberInput)
.hideHelp())
.addOption(new Option('--refresh-interval <number>', 'Auto-refresh page interval in seconds (0 disables)')
.default(DEFAULT_PAKE_OPTIONS.refreshInterval)
.argParser((value) => {
const interval = parseInt(value);
if (isNaN(interval) || interval < 0) {
throw new Error('--refresh-interval must be a number >= 0');
}
return interval;
}))
.addOption(new Option('--ignore-certificate-errors', 'Ignore certificate errors (for self-signed certificates)')
.default(DEFAULT_PAKE_OPTIONS.ignoreCertificateErrors)
.hideHelp())
Expand Down
13 changes: 13 additions & 0 deletions docs/cli-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,19 @@ Set the window title bar text. macOS shows no title if not specified; Windows/Li
--title "Google Translate"
```

#### [refresh-interval]

Auto-refresh the current page at a fixed interval in seconds. Default is `0` (disabled).

When enabled, Pake defers the refresh while the page is hidden or while the user is actively focused in an input, textarea, select, or contenteditable field.

```shell
--refresh-interval <number>

# Example: refresh every 5 minutes
pake https://news.ycombinator.com --name HackerNews --refresh-interval 300
```

#### [incognito]

Launch the application in incognito/private browsing mode. Default is `false`. When enabled, the webview will run in private mode, which means it won't store cookies, local storage, or browsing history. This is useful for privacy-sensitive applications.
Expand Down
1 change: 1 addition & 0 deletions src-tauri/pake.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"start_to_tray": false,
"force_internal_navigation": false,
"internal_url_regex": "",
"refresh_interval": 0,
"new_window": false
}
],
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/app/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ pub struct WindowConfig {
pub min_height: f64,
#[serde(default)]
pub ignore_certificate_errors: bool,
#[serde(default)]
pub refresh_interval: u32,
}

fn default_zoom() -> u32 {
Expand Down
56 changes: 56 additions & 0 deletions src-tauri/src/inject/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ document.addEventListener("DOMContentLoaded", () => {
const pakeConfig = window["pakeConfig"] || {};
const forceInternalNavigation = pakeConfig.force_internal_navigation === true;
const internalUrlRegex = pakeConfig.internal_url_regex || "";
const refreshIntervalSeconds = Number(pakeConfig.refresh_interval || 0);
let autoRefreshTimer = null;
let internalUrlPattern = null;
if (internalUrlRegex) {
try {
Expand Down Expand Up @@ -308,6 +310,60 @@ document.addEventListener("DOMContentLoaded", () => {
});
}

function shouldDeferAutoRefresh() {
if (document.hidden) {
return true;
}

const activeElement = document.activeElement;
if (!activeElement) {
return false;
}

const tagName = activeElement.tagName;
return (
activeElement.isContentEditable ||
tagName === "INPUT" ||
tagName === "TEXTAREA" ||
tagName === "SELECT"
);
}

function scheduleAutoRefresh(delayMs = refreshIntervalSeconds * 1000) {
if (refreshIntervalSeconds <= 0) {
return;
}

if (autoRefreshTimer) {
clearTimeout(autoRefreshTimer);
}

autoRefreshTimer = window.setTimeout(() => {
if (shouldDeferAutoRefresh()) {
scheduleAutoRefresh(5000);
return;
}

window.location.reload();
}, delayMs);
}

if (refreshIntervalSeconds > 0) {
scheduleAutoRefresh();

document.addEventListener("visibilitychange", () => {
if (!document.hidden) {
scheduleAutoRefresh();
}
});

window.addEventListener("beforeunload", () => {
if (autoRefreshTimer) {
clearTimeout(autoRefreshTimer);
}
});
}

document.addEventListener(
"paste",
(event) => {
Expand Down
9 changes: 9 additions & 0 deletions tests/unit/cli-options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,13 @@ describe('CLI options', () => {
expect(option?.defaultValue).toBe(false);
expect(option?.hidden).toBe(false);
});

it('registers --refresh-interval option', () => {
const option = program.options.find(
(item) => item.long === '--refresh-interval',
);

expect(option).toBeDefined();
expect(option?.defaultValue).toBe(0);
});
});
Loading