✨ 添加安装检测和启动应用
This commit is contained in:
@@ -5,3 +5,4 @@ This template should help get you started developing with Tauri, Solid and Types
|
||||
## Recommended IDE Setup
|
||||
|
||||
- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
|
||||
##### 1.2 其他依赖
|
||||
|
||||
22
src-tauri/src/handlers/deb.rs
Normal file
22
src-tauri/src/handlers/deb.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use std::process::Command;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn check_is_installed(pkgname: String) -> Result<bool, String> {
|
||||
let output = Command::new("/opt/durapps/spark-store/bin/store-helper/check-is-installed")
|
||||
.arg(&pkgname)
|
||||
.output()
|
||||
.map_err(|e| format!("执行命令失败: {}", e))?;
|
||||
|
||||
Ok(output.status.success())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn launch_app(pkgname: String) -> Result<(), String> {
|
||||
Command::new("/opt/durapps/spark-store/bin/store-helper/ss-launcher")
|
||||
.arg(&pkgname)
|
||||
.spawn()
|
||||
.map_err(|e| format!("启动应用失败: {}", e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -4,3 +4,4 @@ pub mod app;
|
||||
pub mod home;
|
||||
pub mod file;
|
||||
pub mod download;
|
||||
pub mod deb;
|
||||
@@ -30,6 +30,8 @@ pub fn run() {
|
||||
handlers::download::pause_download,
|
||||
handlers::download::resume_download,
|
||||
handlers::download::cancel_download,
|
||||
handlers::deb::check_is_installed,
|
||||
handlers::deb::launch_app,
|
||||
utils::get_user_agent,
|
||||
])
|
||||
.on_window_event(|window, event| match event {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, createSignal } from 'solid-js';
|
||||
import { Component, createSignal, onMount } from 'solid-js';
|
||||
import { useParams } from '@solidjs/router';
|
||||
import { useAppDetailStore } from './store';
|
||||
import './AppDetail.css';
|
||||
@@ -16,6 +16,7 @@ import { useCollectionStore } from '@/features/collection/store';
|
||||
import { useDownloadsStore } from '@/features/downloads/store';
|
||||
import { Progress } from '@/components/ui/progress';
|
||||
import { X } from 'lucide-solid';
|
||||
import { checkIsInstalled, launchApp } from '@/lib/api/deb';
|
||||
|
||||
const AppDetail: Component = () => {
|
||||
const params = useParams();
|
||||
@@ -26,6 +27,7 @@ const AppDetail: Component = () => {
|
||||
const [newCollectionDesc, setNewCollectionDesc] = createSignal('');
|
||||
const [showNewCollectionDialog, setShowNewCollectionDialog] = createSignal(false);
|
||||
const [showCollectionDialog, setShowCollectionDialog] = createSignal(false);
|
||||
const [isInstalled, setIsInstalled] = createSignal(false);
|
||||
const [selectedCollections, setSelectedCollections] = createSignal<string[]>([]);
|
||||
|
||||
const handleCreateCollection = () => {
|
||||
@@ -45,6 +47,11 @@ const AppDetail: Component = () => {
|
||||
showToast({ description: '收藏单创建成功', variant: "success" });
|
||||
};
|
||||
|
||||
onMount(async () => {
|
||||
const installed = await checkIsInstalled(params.pkgname);
|
||||
setIsInstalled(installed);
|
||||
});
|
||||
|
||||
return (
|
||||
<div class="w-full h-full">
|
||||
{loading() ? (
|
||||
@@ -110,17 +117,36 @@ const AppDetail: Component = () => {
|
||||
<h2 class="app-name text-2xl font-bold pt-2">{app()?.Name}</h2>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 w-[120px]">
|
||||
{downloads().some(task => task.category === params.category && task.pkgname === params.pkgname) ? (
|
||||
<div class="flex flex-col gap-2 w-full pb-2">
|
||||
{downloads().map(download => {
|
||||
if (download.category === params.category && download.pkgname === params.pkgname) {
|
||||
{(() => {
|
||||
const downloadTask = downloads().find(task =>
|
||||
task.category === params.category &&
|
||||
task.pkgname === params.pkgname
|
||||
);
|
||||
|
||||
if (downloadTask?.status === 'installed' || isInstalled()) {
|
||||
return (
|
||||
<Button
|
||||
size="lg"
|
||||
class='w-full'
|
||||
onClick={() => {
|
||||
launchApp(params.pkgname)
|
||||
showToast({ description: '正在启动应用...' });
|
||||
}}
|
||||
>
|
||||
启动
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
if (downloadTask) {
|
||||
return (
|
||||
<div class="flex flex-col gap-2 w-full pb-2">
|
||||
<div class="flex items-center gap-2 group relative">
|
||||
<Progress value={download.progress} class="flex-1" />
|
||||
<Progress value={downloadTask.progress} class="flex-1" />
|
||||
<div class="flex items-center gap-2 group-hover:opacity-0 transition-opacity">
|
||||
<span class="text-sm text-muted-foreground">{download.progress}%</span>
|
||||
{download.speed && (
|
||||
<span class="text-sm text-muted-foreground">{download.speed}</span>
|
||||
<span class="text-sm text-muted-foreground">{downloadTask.progress}%</span>
|
||||
{downloadTask.speed && (
|
||||
<span class="text-sm text-muted-foreground">{downloadTask.speed}</span>
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
@@ -132,12 +158,11 @@ const AppDetail: Component = () => {
|
||||
<X />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
|
||||
return (
|
||||
<Button
|
||||
size="lg"
|
||||
class='w-full'
|
||||
@@ -159,7 +184,8 @@ const AppDetail: Component = () => {
|
||||
>
|
||||
安装
|
||||
</Button>
|
||||
)}
|
||||
);
|
||||
})()}
|
||||
<Dialog open={showCollectionDialog()} onOpenChange={setShowCollectionDialog}>
|
||||
<DialogTrigger>
|
||||
<Button variant="secondary" size="lg" class='w-full'>收藏</Button>
|
||||
|
||||
9
src/lib/api/deb.ts
Normal file
9
src/lib/api/deb.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
export async function checkIsInstalled(pkgname: string): Promise<boolean> {
|
||||
return await invoke('check_is_installed', { pkgname });
|
||||
}
|
||||
|
||||
export async function launchApp(pkgname: string) {
|
||||
await invoke('launch_app', { pkgname });
|
||||
}
|
||||
Reference in New Issue
Block a user