feat: auto-install the bundled kernel version and add an X button to dismiss the launch popup
This commit is contained in:
1 parent
462766d0d2
commit
2ea7080a7e
3 files changed
+92
No files matched your search
@@ -5627,6 +5627,33 @@ fn install_bundled_core(
|
||||
result
|
||||
}
|
||||
|
||||
fn core_needs_bundled_bootstrap(install_dir: &Path) -> bool {
|
||||
find_core_binary(install_dir).is_none()
|
||||
}
|
||||
|
||||
fn auto_install_bundled_core_if_missing(app: &tauri::AppHandle) -> Result<bool, String> {
|
||||
let install_dir = core_install_dir()?;
|
||||
if !core_needs_bundled_bootstrap(&install_dir) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let (info, archive_path) = bundled_core_archive()?
|
||||
.ok_or_else(|| "未检测到 CPA 内核,且当前发行包没有匹配的离线内核".to_string())?;
|
||||
let window = app
|
||||
.get_webview_window("main")
|
||||
.map(|webview| webview.as_ref().window())
|
||||
.ok_or_else(|| "无法获取主窗口,不能自动安装离线内核".to_string())?;
|
||||
let state = app.state::<CoreDownloadState>();
|
||||
state.start(CancellationToken::new(), Some(info.version.clone()))?;
|
||||
let result = install_bundled_core_inner(&window, state.inner(), &info, &archive_path);
|
||||
if result.is_err() {
|
||||
let _ = cleanup_core_work_dirs();
|
||||
}
|
||||
state.finish(&window, result.clone());
|
||||
result?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn cancel_core_install(state: tauri::State<'_, CoreDownloadState>) {
|
||||
state.cancel();
|
||||
@@ -10545,6 +10572,12 @@ fn main() {
|
||||
return;
|
||||
};
|
||||
|
||||
match auto_install_bundled_core_if_missing(&core_app) {
|
||||
Ok(true) => eprintln!("未检测到 CPA 内核,已自动安装内置离线版本"),
|
||||
Ok(false) => {}
|
||||
Err(error) => eprintln!("自动安装 CPA 离线内核失败: {error}"),
|
||||
}
|
||||
|
||||
if config.run_on_startup {
|
||||
if let Err(error) = start_core_process_inner(process_state.inner(), &config) {
|
||||
eprintln!("自动启动 CPA 内核失败: {error}");
|
||||
@@ -12612,6 +12645,21 @@ mod tests {
|
||||
fs::remove_dir_all(root).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bundled_core_bootstrap_runs_only_when_no_core_binary_exists() {
|
||||
let root = agent_test_home("bundled-bootstrap-detection");
|
||||
let install_dir = root.join("cpa-core");
|
||||
|
||||
assert!(core_needs_bundled_bootstrap(&install_dir));
|
||||
|
||||
let existing_version = install_dir.join("existing-version");
|
||||
fs::create_dir_all(&existing_version).unwrap();
|
||||
fs::write(existing_version.join(core_binary_name()), b"existing core").unwrap();
|
||||
|
||||
assert!(!core_needs_bundled_bootstrap(&install_dir));
|
||||
fs::remove_dir_all(root).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bundled_core_locations_include_macos_app_resources() {
|
||||
let contents_dir = agent_test_home("bundled-macos-resources")
|
||||
|
||||
+11
@@ -18,6 +18,7 @@ import {
|
||||
PackageOpen,
|
||||
ServerCog,
|
||||
Settings,
|
||||
X,
|
||||
} from 'lucide-react';
|
||||
import appLogo from './assets/logo.jpg';
|
||||
import { CoreRuntimeProvider, useCoreRuntime } from './coreRuntime';
|
||||
@@ -387,6 +388,16 @@ function AppContent() {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="close-dialog-dismiss"
|
||||
aria-label={t('common.cancel')}
|
||||
title={t('common.cancel')}
|
||||
disabled={windowsClosePrompt.resolvingAction !== null}
|
||||
onClick={() => setWindowsClosePrompt(null)}
|
||||
>
|
||||
<X size={17} aria-hidden="true" />
|
||||
</button>
|
||||
<div className="close-dialog-heading">
|
||||
<span>{t('app.close.eyebrow')}</span>
|
||||
<h2 id="close-dialog-title">{t('app.close.title')}</h2>
|
||||
|
||||
@@ -1542,6 +1542,7 @@ input:focus-visible {
|
||||
}
|
||||
|
||||
.close-dialog {
|
||||
position: relative;
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
width: min(430px, 100%);
|
||||
@@ -1556,6 +1557,38 @@ input:focus-visible {
|
||||
.close-dialog-heading {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
padding-right: 34px;
|
||||
}
|
||||
|
||||
.close-dialog-dismiss {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
display: grid;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
place-items: center;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 7px;
|
||||
background: transparent;
|
||||
color: #7a746c;
|
||||
}
|
||||
|
||||
.close-dialog-dismiss:hover:not(:disabled) {
|
||||
border-color: #d5d2cb;
|
||||
background: #f0ede6;
|
||||
color: #2d2a26;
|
||||
}
|
||||
|
||||
.close-dialog-dismiss:focus-visible {
|
||||
outline: 3px solid rgba(66, 99, 127, 0.3);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.close-dialog-dismiss:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.close-dialog-heading span {
|
||||
|
||||
Reference in new issue
Block a user