From 99a8e25411a64faec43587c8ee50dbc5a7614574 Mon Sep 17 00:00:00 2001
From: GyDi <segydi@foxmail.com>
Date: Mon, 17 Jan 2022 02:16:17 +0800
Subject: [PATCH] feat: support edit profile item

---
 src-tauri/Cargo.lock            | 12 ++++++++++++
 src-tauri/Cargo.toml            |  1 +
 src-tauri/src/cmds.rs           | 30 ++++++++++++++++++++++++++++++
 src-tauri/src/main.rs           |  7 +++----
 src/components/profile-item.tsx | 12 +++++++++++-
 src/services/cmds.ts            |  4 ++++
 6 files changed, 61 insertions(+), 5 deletions(-)

diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index d596529..3b2d757 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -58,6 +58,7 @@ dependencies = [
  "tauri-plugin-vibrancy",
  "tokio",
  "warp",
+ "which",
  "winreg 0.10.1",
 ]
 
@@ -4110,6 +4111,17 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "which"
+version = "4.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9"
+dependencies = [
+ "either",
+ "lazy_static",
+ "libc",
+]
+
 [[package]]
 name = "wildmatch"
 version = "2.1.0"
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 4b5f293..b4878e4 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -29,6 +29,7 @@ tokio = { version = "1", features = ["full"] }
 log = "0.4.14"
 log4rs = "1.0.0"
 warp = "0.3"
+which = "4.2.2"
 auto-launch = "0.2"
 port_scanner = "0.1.5"
 
diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs
index a164718..4ff3a2d 100644
--- a/src-tauri/src/cmds.rs
+++ b/src-tauri/src/cmds.rs
@@ -3,11 +3,13 @@ use crate::{
   states::{ClashState, ProfilesState, VergeState},
   utils::{
     config::{read_clash, save_clash},
+    dirs::app_home_dir,
     fetch::fetch_profile,
     sysopt::SysProxyConfig,
   },
 };
 use serde_yaml::Mapping;
+use std::process::Command;
 use tauri::State;
 
 /// get all profiles from `profiles.yaml`
@@ -142,6 +144,34 @@ pub fn patch_profile(
   }
 }
 
+/// run vscode command to edit the profile
+#[tauri::command]
+pub fn edit_profile(index: usize, profiles_state: State<'_, ProfilesState>) -> Result<(), String> {
+  let mut profiles = profiles_state.0.lock().unwrap();
+  let items = profiles.items.take().unwrap_or(vec![]);
+
+  if index >= items.len() {
+    profiles.items = Some(items);
+    return Err("the index out of bound".into());
+  }
+
+  let file = items[index].file.clone().unwrap_or("".into());
+  profiles.items = Some(items);
+
+  let path = app_home_dir().join("profiles").join(file);
+  if !path.exists() {
+    return Err("failed to open the file".into());
+  }
+
+  match which::which("code") {
+    Ok(code) => match Command::new(code).arg(path).status() {
+      Ok(_) => Ok(()),
+      Err(_) => Err("failed to open file by VScode".into()),
+    },
+    Err(_) => Err("please install VScode for edit".into()),
+  }
+}
+
 /// restart the sidecar
 #[tauri::command]
 pub fn restart_sidecar(
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index af0aa3b..f9d497c 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -3,8 +3,6 @@
   windows_subsystem = "windows"
 )]
 
-extern crate tauri;
-
 mod cmds;
 mod core;
 mod states;
@@ -82,13 +80,14 @@ fn main() -> std::io::Result<()> {
       cmds::get_verge_config,
       cmds::patch_verge_config,
       // profile
+      cmds::edit_profile,
+      cmds::patch_profile,
       cmds::import_profile,
       cmds::update_profile,
       cmds::delete_profile,
       cmds::select_profile,
-      cmds::patch_profile,
-      cmds::sync_profiles,
       cmds::get_profiles,
+      cmds::sync_profiles,
     ])
     .build(tauri::generate_context!())
     .expect("error while running tauri application")
diff --git a/src/components/profile-item.tsx b/src/components/profile-item.tsx
index b3670a6..7161ae7 100644
--- a/src/components/profile-item.tsx
+++ b/src/components/profile-item.tsx
@@ -14,7 +14,7 @@ import {
 import { useSWRConfig } from "swr";
 import { RefreshRounded } from "@mui/icons-material";
 import { CmdType } from "../services/types";
-import { updateProfile, deleteProfile } from "../services/cmds";
+import { updateProfile, deleteProfile, editProfile } from "../services/cmds";
 import Notice from "./notice";
 import parseTraffic from "../utils/parse-traffic";
 import relativeTime from "dayjs/plugin/relativeTime";
@@ -59,6 +59,15 @@ const ProfileItem: React.FC<Props> = (props) => {
   const progress = Math.round(((download + upload) * 100) / (total + 0.1));
   const fromnow = updated > 0 ? dayjs(updated * 1000).fromNow() : "";
 
+  const onEdit = async () => {
+    setAnchorEl(null);
+    try {
+      await editProfile(index);
+    } catch (err: any) {
+      Notice.error(err.toString());
+    }
+  };
+
   const onUpdateWrapper = (withProxy: boolean) => async () => {
     setAnchorEl(null);
     if (loading) return;
@@ -202,6 +211,7 @@ const ProfileItem: React.FC<Props> = (props) => {
         anchorPosition={position}
         anchorReference="anchorPosition"
       >
+        <MenuItem onClick={onEdit}>Edit</MenuItem>
         <MenuItem onClick={onUpdateWrapper(false)}>Update</MenuItem>
         <MenuItem onClick={onUpdateWrapper(true)}>Update(Proxy)</MenuItem>
         <MenuItem onClick={onDelete}>Delete</MenuItem>
diff --git a/src/services/cmds.ts b/src/services/cmds.ts
index eab9cc3..faca55f 100644
--- a/src/services/cmds.ts
+++ b/src/services/cmds.ts
@@ -9,6 +9,10 @@ export async function syncProfiles() {
   return invoke<void>("sync_profiles");
 }
 
+export async function editProfile(index: number) {
+  return invoke<void>("edit_profile", { index });
+}
+
 export async function importProfile(url: string) {
   return invoke<void>("import_profile", { url, withProxy: true });
 }
-- 
GitLab