From 211bc44793a80a51f52700544c538006fd602365 Mon Sep 17 00:00:00 2001 From: Jonson Petard <41122242+greenhat616@users.noreply.github.com> Date: Tue, 26 Dec 2023 22:37:16 +0800 Subject: [PATCH 1/9] fix(log): incorrect color in light mode --- src/components/log/log-item.module.scss | 10 ++++++++-- src/components/log/log-item.tsx | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/components/log/log-item.module.scss b/src/components/log/log-item.module.scss index 59aedd1247..5b5b8136ed 100644 --- a/src/components/log/log-item.module.scss +++ b/src/components/log/log-item.module.scss @@ -1,5 +1,4 @@ .item { - /* stylelint-disable-next-line selector-pseudo-class-no-unknown */ :global(.shiki) { margin-top: 0.25em; margin-bottom: 0; @@ -10,8 +9,15 @@ } span { - color: var(--shiki-dark) !important; white-space: normal; } } + + &.dark { + :global(.shiki) { + span { + color: var(--shiki-dark) !important; + } + } + } } diff --git a/src/components/log/log-item.tsx b/src/components/log/log-item.tsx index a484fee6d1..9cb61e5df5 100644 --- a/src/components/log/log-item.tsx +++ b/src/components/log/log-item.tsx @@ -68,7 +68,11 @@ const LogItem = (props: Props) => { } > Date: Tue, 26 Dec 2023 22:54:54 +0800 Subject: [PATCH 2/9] fix: open file, closing #197 --- backend/tauri/src/cmds.rs | 4 ++-- backend/tauri/src/utils/help.rs | 21 +++++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/backend/tauri/src/cmds.rs b/backend/tauri/src/cmds.rs index e9648c4de8..7d03e250cd 100644 --- a/backend/tauri/src/cmds.rs +++ b/backend/tauri/src/cmds.rs @@ -93,7 +93,7 @@ pub fn patch_profile(index: String, profile: PrfItem) -> CmdResult { } #[tauri::command] -pub fn view_profile(index: String) -> CmdResult { +pub fn view_profile(app_handle: tauri::AppHandle, index: String) -> CmdResult { let file = { wrap_err!(Config::profiles().latest().get_item(&index))? .file @@ -106,7 +106,7 @@ pub fn view_profile(index: String) -> CmdResult { ret_err!("the file not found"); } - wrap_err!(help::open_file(path)) + wrap_err!(help::open_file(app_handle, path)) } #[tauri::command] diff --git a/backend/tauri/src/utils/help.rs b/backend/tauri/src/utils/help.rs index 03a89f444a..5c2aaaa5d3 100644 --- a/backend/tauri/src/utils/help.rs +++ b/backend/tauri/src/utils/help.rs @@ -3,7 +3,10 @@ use nanoid::nanoid; use serde::{de::DeserializeOwned, Serialize}; use serde_yaml::{Mapping, Value}; use std::{fs, path::PathBuf, str::FromStr}; - +use tauri::{ + api::shell::{open, Program}, + Manager, +}; /// read data from yaml as struct T pub fn read_yaml(path: &PathBuf) -> Result { if !path.exists() { @@ -81,18 +84,20 @@ pub fn parse_str(target: &str, key: &str) -> Option { /// open file /// use vscode by default -pub fn open_file(path: PathBuf) -> Result<()> { +pub fn open_file(app: tauri::AppHandle, path: PathBuf) -> Result<()> { #[cfg(target_os = "macos")] let code = "Visual Studio Code"; #[cfg(not(target_os = "macos"))] let code = "code"; - // use vscode first - if let Err(err) = open::with(&path, code) { - log::error!(target: "app", "failed to open file with VScode `{err}`"); - // default open - open::that(path)?; - } + let _ = match Program::from_str(code) { + Ok(code) => open(&app.shell_scope(), &path.to_string_lossy(), Some(code)), + Err(err) => { + log::error!(target: "app", "Can't find VScode `{err}`"); + // default open + open(&app.shell_scope(), &path.to_string_lossy(), None) + } + }; Ok(()) } From ffe2bde3b69c9a2ecba1494045f8dbac135d0b49 Mon Sep 17 00:00:00 2001 From: Jonson Petard <41122242+greenhat616@users.noreply.github.com> Date: Tue, 26 Dec 2023 23:26:39 +0800 Subject: [PATCH 3/9] fix: dark mode flash in win --- backend/tauri/src/main.rs | 5 ++++- backend/tauri/src/utils/resolve.rs | 31 +++++++++++++++--------------- src/main.tsx | 2 +- src/pages/_layout.tsx | 6 ++++++ 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/backend/tauri/src/main.rs b/backend/tauri/src/main.rs index 0619f6c0df..246dc041b9 100644 --- a/backend/tauri/src/main.rs +++ b/backend/tauri/src/main.rs @@ -33,7 +33,10 @@ fn main() -> std::io::Result<()> { #[allow(unused_mut)] let mut builder = tauri::Builder::default() .system_tray(SystemTray::new()) - .setup(|app| Ok(resolve::resolve_setup(app))) + .setup(|app| { + resolve::resolve_setup(app); + Ok(()) + }) .on_system_tray_event(core::tray::Tray::on_system_tray_event) .invoke_handler(tauri::generate_handler![ // common diff --git a/backend/tauri/src/utils/resolve.rs b/backend/tauri/src/utils/resolve.rs index 9a1bf6aa41..4f11a065a8 100644 --- a/backend/tauri/src/utils/resolve.rs +++ b/backend/tauri/src/utils/resolve.rs @@ -142,8 +142,6 @@ pub fn create_window(app_handle: &AppHandle) { #[cfg(target_os = "windows")] { - use std::time::Duration; - use tokio::time::sleep; use window_shadows::set_shadow; match builder @@ -161,6 +159,7 @@ pub fn create_window(app_handle: &AppHandle) { trace_err!(win.set_fullscreen(true), "set win fullscreen"); } } + trace_err!(set_shadow(&win, true), "set win shadow"); log::trace!("try to calculate the monitor size"); let center = (|| -> Result { let mut center = false; @@ -182,22 +181,22 @@ pub fn create_window(app_handle: &AppHandle) { trace_err!(win.center(), "set win center"); } - log::trace!("try to create window"); - let app_handle = app_handle.clone(); + // log::trace!("try to create window"); + // let app_handle = app_handle.clone(); // 加点延迟避免界面闪一下 - tauri::async_runtime::spawn(async move { - // sleep(Duration::from_millis(888)).await; - - if let Some(window) = app_handle.get_window("main") { - trace_err!(set_shadow(&window, true), "set win shadow"); - trace_err!(window.show(), "set win visible"); - trace_err!(window.unminimize(), "set win unminimize"); - trace_err!(window.set_focus(), "set win focus"); - } else { - log::error!(target: "app", "failed to create window, get_window is None") - } - }); + // tauri::async_runtime::spawn(async move { + // // sleep(Duration::from_millis(888)).await; + + // if let Some(window) = app_handle.get_window("main") { + // trace_err!(set_shadow(&window, true), "set win shadow"); + // trace_err!(window.show(), "set win visible"); + // trace_err!(window.unminimize(), "set win unminimize"); + // trace_err!(window.set_focus(), "set win focus"); + // } else { + // log::error!(target: "app", "failed to create window, get_window is None") + // } + // }); } Err(err) => log::error!(target: "app", "failed to create window, {err}"), } diff --git a/src/main.tsx b/src/main.tsx index 6f6cf7ae7e..1e2fcfbc82 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -9,8 +9,8 @@ if (!window.ResizeObserver) { import React from "react"; import { createRoot } from "react-dom/client"; -import { RecoilRoot } from "recoil"; import { BrowserRouter } from "react-router-dom"; +import { RecoilRoot } from "recoil"; import { BaseErrorBoundary } from "./components/base"; import Layout from "./pages/_layout"; import "./services/i18n"; diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx index e83033eef8..08ab7ca07e 100644 --- a/src/pages/_layout.tsx +++ b/src/pages/_layout.tsx @@ -73,6 +73,12 @@ export default function Layout() { break; } }); + + setTimeout(() => { + appWindow.show(); + appWindow.unminimize(); + appWindow.setFocus(); + }, 50); }, []); useEffect(() => { From 50c777b97bac97555a6ee967bf8a57b99b92e8f8 Mon Sep 17 00:00:00 2001 From: Jonson Petard <41122242+greenhat616@users.noreply.github.com> Date: Tue, 26 Dec 2023 23:46:38 +0800 Subject: [PATCH 4/9] fix(ci): use dev commit hash when schedule dispatch --- .github/workflows/dev.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/dev.yaml b/.github/workflows/dev.yaml index 8b74b09c99..a1a8ca924e 100644 --- a/.github/workflows/dev.yaml +++ b/.github/workflows/dev.yaml @@ -159,6 +159,7 @@ jobs: - name: Set Env run: | echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV + echo "CURRENT_GIT_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV shell: bash - name: Update Tag uses: richardsimko/update-tag@v1.0.11 @@ -166,6 +167,7 @@ jobs: tag_name: pre-release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_SHA: ${{ env.CURRENT_GIT_SHA }} - run: | cat > release.txt << 'EOF' ## Clash Nyanpasu Nightly Build From 9e1d76ec9795ddb553ddcf8199cd57d3f221395b Mon Sep 17 00:00:00 2001 From: Jonson Petard <41122242+greenhat616@users.noreply.github.com> Date: Wed, 27 Dec 2023 10:18:24 +0800 Subject: [PATCH 5/9] fix(ci): use latest action --- .github/workflows/dev.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev.yaml b/.github/workflows/dev.yaml index a1a8ca924e..084aa3aa65 100644 --- a/.github/workflows/dev.yaml +++ b/.github/workflows/dev.yaml @@ -162,12 +162,12 @@ jobs: echo "CURRENT_GIT_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV shell: bash - name: Update Tag - uses: richardsimko/update-tag@v1.0.11 + uses: greenhat616/update-tag@v1 with: tag_name: pre-release + ref: dev env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_SHA: ${{ env.CURRENT_GIT_SHA }} - run: | cat > release.txt << 'EOF' ## Clash Nyanpasu Nightly Build From 6c992b7c5fb9221376c30aae8ff004297c14315d Mon Sep 17 00:00:00 2001 From: Jonson Petard <41122242+greenhat616@users.noreply.github.com> Date: Fri, 29 Dec 2023 12:12:29 +0800 Subject: [PATCH 6/9] fix(updater): allow to use elevated permission to copy and override core --- backend/tauri/Cargo.toml | 2 +- backend/tauri/src/core/updater.rs | 92 +++++++++++++++++++++++-------- 2 files changed, 69 insertions(+), 25 deletions(-) diff --git a/backend/tauri/Cargo.toml b/backend/tauri/Cargo.toml index fedd456e17..3c8a74be81 100644 --- a/backend/tauri/Cargo.toml +++ b/backend/tauri/Cargo.toml @@ -64,9 +64,9 @@ rs-snowflake = "0.6" rocksdb = "0.21" thiserror = { workspace = true, version = "1.0" } simd-json = "0.13.4" +runas = "=1.0.0" # blocked by https://github.com/mitsuhiko/rust-runas/issues/13 [target.'cfg(windows)'.dependencies] -runas = "=1.0.0" # blocked by https://github.com/mitsuhiko/rust-runas/issues/13 deelevate = "0.2.0" winreg = { version = "0.50", features = ["transactions"] } windows-sys = { version = "0.48", features = [ diff --git a/backend/tauri/src/core/updater.rs b/backend/tauri/src/core/updater.rs index 6f549378b7..1f054b1fee 100644 --- a/backend/tauri/src/core/updater.rs +++ b/backend/tauri/src/core/updater.rs @@ -1,18 +1,18 @@ use std::{collections::HashMap, io::Cursor, path::Path, sync::OnceLock}; +use super::CoreManager; use crate::config::ClashCore; use anyhow::{anyhow, Result}; use gunzip::Decompressor; -use log::debug; -use serde::{de, Deserialize, Serialize}; +use log::{debug, warn}; +use runas::Command as RunasCommand; +use serde::{Deserialize, Serialize}; #[cfg(target_family = "unix")] use std::os::unix::fs::PermissionsExt; use tempfile::{tempdir, TempDir}; use tokio::{join, sync::RwLock, task::spawn_blocking}; use zip::ZipArchive; -use super::CoreManager; - pub struct Updater { manifest_version: ManifestVersion, mirror: String, @@ -123,14 +123,15 @@ impl Updater { self.mirror.as_str(), "MetaCubeX/mihomo/releases/download/Prerelease-Alpha/version.txt" ); - Ok(client - .get(url) - .send() - .await? - .text() - .await? - .trim() - .to_string()) + let res = client.get(url).send().await?; + let status_code = res.status(); + if !status_code.is_success() { + anyhow::bail!( + "failed to get mihomo alpha version: response status is {}, expected 200", + status_code + ); + } + Ok(res.text().await?.trim().to_string()) } pub async fn update_core(&self, core_type: &ClashCore) -> Result<()> { @@ -165,10 +166,42 @@ impl Updater { let core_dir = core_dir.parent().ok_or(anyhow!("failed to get core dir"))?; let target_core = core_dir.join(target_core); debug!("copying core to {:?}", target_core); - std::fs::copy( - tmp_dir.path().join(core_type.clone().to_string()), - target_core, - )?; + let tmp_core_path = tmp_dir.path().join(core_type.clone().to_string()); + match std::fs::copy(tmp_core_path.clone(), target_core.clone()) { + Ok(_) => {} + Err(err) => { + warn!( + "failed to copy core: {}, trying to use elevated permission to copy and override core", + err + ); + #[cfg(target_os = "windows")] + { + // 防止 UAC 弹窗堵塞主线程 + tokio::task::spawn_blocking(move || { + RunasCommand::new("cmd") + .args(&[ + "/C", + "copy", + "/Y", + tmp_core_path.to_str().unwrap(), + target_core.to_str().unwrap(), + ]) + .status() + }) + .await??; + } + #[cfg(not(target_os = "windows"))] + { + RunasCommand::new("cp") + .args(&[ + "-f", + tmp_core_path.to_str().unwrap(), + target_core.to_str().unwrap(), + ]) + .status()?; + } + } + }; // 5. if core is used before, restart it if current_core == *core_type { @@ -235,7 +268,15 @@ impl Updater { let mut dst = std::fs::File::create(&file_path)?; let client = reqwest::Client::new(); - let mut buff = Cursor::new(client.get(url).send().await?.bytes().await?); + let res = client.get(url).send().await?; + let status_code = res.status(); + if !status_code.is_success() { + anyhow::bail!( + "failed to download core: response status is {}, expected 200", + status_code + ); + } + let mut buff = Cursor::new(res.bytes().await?); std::io::copy(&mut buff, &mut dst)?; Ok(artifact) } @@ -284,7 +325,7 @@ fn decompress_and_set_permission( }; let tmp_core = tmp_path.join(core_type.clone().to_string()); debug!("writing core to {:?} ({} bytes)", tmp_core, buff.len()); - let mut core_file = std::fs::File::create(tmp_core.to_owned())?; + let mut core_file = std::fs::File::create(&tmp_core)?; std::io::copy(&mut buff.as_slice(), &mut core_file)?; #[cfg(target_family = "unix")] { @@ -300,12 +341,15 @@ pub async fn get_latest_version_manifest(mirror: &str) -> Result() - .await?) + let res = client.get(url).send().await?; + let status_code = res.status(); + if !status_code.is_success() { + anyhow::bail!( + "failed to get latest version manifest: response status is {}, expected 200", + status_code + ); + } + Ok(res.json::().await?) } enum CoreTypeMeta { From 67e26bc0c63d7e87f60b6c872ad3f50d05a94f61 Mon Sep 17 00:00:00 2001 From: Jonson Petard <41122242+greenhat616@users.noreply.github.com> Date: Fri, 29 Dec 2023 12:22:31 +0800 Subject: [PATCH 7/9] fix(updater): add status code judge --- backend/tauri/src/core/updater.rs | 36 +++++++++++++++++-------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/backend/tauri/src/core/updater.rs b/backend/tauri/src/core/updater.rs index 1f054b1fee..7411650c92 100644 --- a/backend/tauri/src/core/updater.rs +++ b/backend/tauri/src/core/updater.rs @@ -174,10 +174,11 @@ impl Updater { "failed to copy core: {}, trying to use elevated permission to copy and override core", err ); - #[cfg(target_os = "windows")] - { - // 防止 UAC 弹窗堵塞主线程 - tokio::task::spawn_blocking(move || { + + // 防止 UAC 弹窗堵塞主线程 + let status_code = tokio::task::spawn_blocking(move || { + #[cfg(target_os = "windows")] + { RunasCommand::new("cmd") .args(&[ "/C", @@ -187,18 +188,21 @@ impl Updater { target_core.to_str().unwrap(), ]) .status() - }) - .await??; - } - #[cfg(not(target_os = "windows"))] - { - RunasCommand::new("cp") - .args(&[ - "-f", - tmp_core_path.to_str().unwrap(), - target_core.to_str().unwrap(), - ]) - .status()?; + } + #[cfg(not(target_os = "windows"))] + { + RunasCommand::new("cp") + .args(&[ + "-f", + tmp_core_path.to_str().unwrap(), + target_core.to_str().unwrap(), + ]) + .status()?; + } + }) + .await??; + if !status_code.success() { + anyhow::bail!("failed to copy core: {}", status_code); } } }; From ca1ed25d3b252da7fd7a8a50ee31fc316b4ccadf Mon Sep 17 00:00:00 2001 From: Jonson Petard <41122242+greenhat616@users.noreply.github.com> Date: Fri, 29 Dec 2023 15:30:22 +0800 Subject: [PATCH 8/9] fix: updater --- backend/tauri/Cargo.toml | 2 +- backend/tauri/src/core/updater.rs | 17 +++++++++-------- scripts/generate-latest-version.ts | 3 +-- .../setting/mods/clash-core-viewer.tsx | 13 ++++++++++--- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/backend/tauri/Cargo.toml b/backend/tauri/Cargo.toml index 3c8a74be81..65d9ca6c2f 100644 --- a/backend/tauri/Cargo.toml +++ b/backend/tauri/Cargo.toml @@ -40,13 +40,13 @@ tokio = { version = "1", features = ["full"] } serde = { version = "1.0", features = ["derive"] } reqwest = { version = "0.11", features = ["json", "rustls-tls"] } tauri = { version = "1.5.3", features = [ + "updater", "os-all", "global-shortcut-all", "notification-all", "process-all", "shell-all", "system-tray", - "updater", "window-all", ] } window-vibrancy = { version = "0.4.3" } diff --git a/backend/tauri/src/core/updater.rs b/backend/tauri/src/core/updater.rs index 7411650c92..cc7a8aedbe 100644 --- a/backend/tauri/src/core/updater.rs +++ b/backend/tauri/src/core/updater.rs @@ -155,7 +155,7 @@ impl Updater { .await??; // 3. if core is used, close it if current_core == *core_type { - CoreManager::global().stop_core()?; + tokio::task::spawn_blocking(move || CoreManager::global().stop_core()).await??; } // 4. replace core #[cfg(target_os = "windows")] @@ -174,7 +174,12 @@ impl Updater { "failed to copy core: {}, trying to use elevated permission to copy and override core", err ); - + let mut target_core_str = target_core.to_str().unwrap().to_string(); + if target_core_str.starts_with("\\\\?\\") { + target_core_str = target_core_str[4..].to_string(); + } + debug!("tmp core path: {:?}", tmp_core_path); + debug!("target core path: {:?}", target_core_str); // 防止 UAC 弹窗堵塞主线程 let status_code = tokio::task::spawn_blocking(move || { #[cfg(target_os = "windows")] @@ -185,18 +190,14 @@ impl Updater { "copy", "/Y", tmp_core_path.to_str().unwrap(), - target_core.to_str().unwrap(), + &target_core_str, ]) .status() } #[cfg(not(target_os = "windows"))] { RunasCommand::new("cp") - .args(&[ - "-f", - tmp_core_path.to_str().unwrap(), - target_core.to_str().unwrap(), - ]) + .args(&["-f", tmp_core_path.to_str().unwrap(), &target_core_str]) .status()?; } }) diff --git a/scripts/generate-latest-version.ts b/scripts/generate-latest-version.ts index 37d7cb514d..5130b9ae36 100644 --- a/scripts/generate-latest-version.ts +++ b/scripts/generate-latest-version.ts @@ -90,8 +90,7 @@ const resolveMihomoAlpha: LatestVersionResolver = async () => { const archMapping: ArchMapping = { // [SupportedArch.WindowsX86]: "mihomo-windows-386-{}.zip", - [SupportedArch.WindowsX86_64]: - "mihomo-windows-amd64-compatible-alpha-{}.zip", + [SupportedArch.WindowsX86_64]: "mihomo-windows-amd64-compatible-{}.zip", // [SupportedArch.WindowsAarch64]: "mihomo-windows-arm64-{}.zip", [SupportedArch.LinuxAarch64]: "mihomo-linux-arm64-{}.gz", [SupportedArch.LinuxAmd64]: "mihomo-linux-amd64-compatible-{}.gz", diff --git a/src/components/setting/mods/clash-core-viewer.tsx b/src/components/setting/mods/clash-core-viewer.tsx index 7fbade6cfa..078c6b22d3 100644 --- a/src/components/setting/mods/clash-core-viewer.tsx +++ b/src/components/setting/mods/clash-core-viewer.tsx @@ -70,7 +70,7 @@ export const ClashCoreViewer = forwardRef((props, ref) => { ...each, latest: each.core === "clash" - ? results["clash_premium"] + ? `n${results["clash_premium"]}` : results[each.core.replace(/-/g, "_") as keyof typeof results], })); setValidCores(buf); @@ -101,7 +101,7 @@ export const ClashCoreViewer = forwardRef((props, ref) => { } }); - useAsyncEffect(async () => { + const getCoreVersions = async () => { try { const versions = await Promise.all( VALID_CORE.reduce( @@ -126,7 +126,8 @@ export const ClashCoreViewer = forwardRef((props, ref) => { console.error(e); } } - }, []); + }; + useAsyncEffect(getCoreVersions, []); return ( ((props, ref) => { if (state === "start") setLock(true); else setLock(false); }} + onCoreUpdated={() => { + getCoreVersions(); + }} /> ))} @@ -194,11 +198,13 @@ function CoreElement({ core, lock, onCoreChanged, + onCoreUpdated, }: { selected: boolean; core: Core; lock: boolean; onCoreChanged: (core: string, state: "start" | "finish") => void; + onCoreUpdated?: (core: string) => void; }) { const { t } = useTranslation(); const { mutateVerge } = useVerge(); @@ -250,6 +256,7 @@ function CoreElement({ mutate("getVersion"); }, 100); useNotification(t("Success"), `Successfully updated to ${core}`); + onCoreUpdated?.(core); } catch (err: any) { useNotification(t("Error"), err?.message || err.toString()); } finally { From 46071c662798473d0ddec54c8952ee2ac41ba188 Mon Sep 17 00:00:00 2001 From: Jonson Petard <41122242+greenhat616@users.noreply.github.com> Date: Fri, 29 Dec 2023 18:13:07 +0800 Subject: [PATCH 9/9] fix: lint --- backend/tauri/src/core/updater.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tauri/src/core/updater.rs b/backend/tauri/src/core/updater.rs index cc7a8aedbe..d939f4082d 100644 --- a/backend/tauri/src/core/updater.rs +++ b/backend/tauri/src/core/updater.rs @@ -198,7 +198,7 @@ impl Updater { { RunasCommand::new("cp") .args(&["-f", tmp_core_path.to_str().unwrap(), &target_core_str]) - .status()?; + .status() } }) .await??;