Merge branch 'main' into dev-tauri2.0

This commit is contained in:
VirtualHotBar
2024-06-02 13:07:01 +08:00
15 changed files with 93 additions and 29 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "netmount-gui",
"private": true,
"version": "1.0.5",
"version": "1.0.6",
"type": "module",
"scripts": {
"dev": "vite",

2
src-tauri/Cargo.lock generated
View File

@@ -85,7 +85,7 @@ dependencies = [
[[package]]
name = "app"
version = "1.0.5"
version = "1.0.6"
dependencies = [
"anyhow",
"anyhow-tauri",

View File

@@ -1,7 +1,7 @@
[package]
name = "app"
description = "NetMount"
version = "1.0.5"
version = "1.0.6"
authors = ["VirtualHotBar"]
license = ""
repository = ""

View File

@@ -485,5 +485,8 @@
"description.lark": "Lark Drive lets you save and manage all your content in cloud storage anytime, anywhere, on any device.",
"description.neteasemusic": "NetEase Cloud Music is a music product focused on discovering and sharing.",
"description.thunderx": "Thunder X",
"description.thunderxexpert": "Thunder X Expert Edition"
"description.thunderxexpert": "Thunder X Expert Edition",
"restartself_to_take_effect": "Restart to take effect",
"unable_to_obtain_transmission_speed":"The specific transmission speed may not be available at present, but the transmission is still in progress."
}

View File

@@ -554,5 +554,8 @@
"description.lark": "Lark Drive允许您随时随地在任何设备上保存和管理云存储中的所有内容。",
"description.neteasemusic":"网易云音乐是一款专注于发现与分享的音乐产品。",
"description.thunderx": "迅雷X",
"description.thunderxexpert": "迅雷X专家版"
"description.thunderxexpert": "迅雷X专家版",
"restartself_to_take_effect": "重启软件以使更改生效",
"unable_to_obtain_transmission_speed":"当前可能无法获取具体传输速度,但传输仍在进行。"
}

View File

@@ -554,6 +554,8 @@
"description.lark": "Lark Drive讓您隨時隨地在任何裝置上保存和管理雲端儲存的所有內容。",
"description.neteasemusic": "網易雲音樂是一款專注於發現與分享的音樂產品。",
"description.thunderx": "迅雷X",
"description.thunderxexpert": "迅雷X專家版"
"description.thunderxexpert": "迅雷X專家版",
"restartself_to_take_effect": "更改設定需要重新啟動程式才能生效。",
"unable_to_obtain_transmission_speed":"當前可能無法獲取具體傳送速率,但傳輸仍在進行。"
}

View File

@@ -2,4 +2,4 @@ use app::init;
fn main(){
init()
}
}

View File

@@ -10,6 +10,19 @@ use std::fs;
use std::io::{self, Write};
//use tauri::AppHandle;
pub fn get_available_ports(count: usize) -> Vec<u16> {
use std::net::TcpListener;
let mut ports = Vec::new();
for _ in 0..count {
let listener = TcpListener::bind("127.0.0.1:0").expect("无法绑定端口");
let port = listener.local_addr().unwrap().port();
ports.push(port);
}
ports
}
#[cfg(target_os = "windows")]
pub fn set_window_shadow<R: Runtime>(app: &tauri::App<R>) {
{

View File

@@ -18,7 +18,7 @@ async function reupStats() {
rcloneInfo.stats = {
...stats,
realSpeed: realSpeed
realSpeed: realSpeed||0/* stats.speed */
}
//历史状态

View File

@@ -7,7 +7,7 @@ import { app } from "@tauri-apps/api";
import { nmConfig, osInfo, roConfig } from "../services/config";
import { Aria2 } from "../utils/aria2/aria2";
import { checkUpdate } from "./update/update";
import { getWinFspInstallState, installWinFsp, showPathInExplorer } from "../utils/utils";
import { getAvailablePorts, getWinFspInstallState, installWinFsp, showPathInExplorer } from "../utils/utils";
import { t } from "i18next";
import { FilterType, StorageInfoType, StorageParamItemType } from "../type/controller/storage/info";
import { storageInfoList, updateStorageInfoList } from "./storage/allList";
@@ -17,6 +17,7 @@ import { alistInfo } from "../services/alist";
import { addAlistInRclone } from "../utils/alist/alist";
import { restartRclone } from "../utils/rclone/process";
import { restartAlist } from "../utils/alist/process";
import { exit } from "./main";
export async function Test() {
console.log(nmConfig);
@@ -26,6 +27,10 @@ export async function Test() {
console.log(await rclone_api_post('/options/get'));
console.log(await rclone_api_post('/rc/list'),);
console.log((await getAvailablePorts(2))[1]);
//exit(true)
/* console.log(await rclone_api_post('/operations/publiclink',{
fs: convertStoragePath('S3_new',undefined,undefined,undefined,true),
remote :convertStoragePath('S3_new','Package/HotPE-V2.7.240201.7z',undefined,true,false),

View File

@@ -1,4 +1,4 @@
import { Alert, Button, Grid, Message, Space, Table, TableColumnProps, Typography } from '@arco-design/web-react'
import { Alert, Button, Grid, Message, Modal, Space, Table, TableColumnProps, Typography } from '@arco-design/web-react'
import React, { useEffect, useReducer, useState } from 'react'
import { rcloneInfo } from '../../services/rclone'
import { delMountStorage, isMounted, mountStorage, reupMount, unmountStorage } from '../../controller/storage/mount/mount'
@@ -14,6 +14,13 @@ import { restartRclone } from '../../utils/rclone/process'
const Row = Grid.Row;
const Col = Grid.Col;
function Mount_page() {
const { t } = useTranslation()
const [ignored, forceUpdate] = useReducer(x => x + 1, 0);//刷新组件
@@ -31,7 +38,7 @@ function Mount_page() {
{
title: t('storage_name'),
dataIndex: 'storageName',
width:'10rem',
width: '10rem',
ellipsis: true,
render: (text) => {
return <Typography.Ellipsis>{text}</Typography.Ellipsis>
@@ -40,13 +47,13 @@ function Mount_page() {
{
title: t('mount_status'),
dataIndex: 'mounted',
width:'5.5rem',
width: '5.5rem',
},
{
title: t('actions'),
dataIndex: 'actions',
align: 'right',
width:'14.3rem'
width: '14.3rem'
}
]
@@ -86,8 +93,18 @@ function Mount_page() {
<Button type='primary' onClick={async () => {
setWinFspInstalling(true)
if (await installWinFsp()) {
await restartRclone()
Message.success(t('install_success'))
//await restartRclone()
Modal.success({
title: t('install_success'),
simple: true,
maskClosable: false,
escToExit: false,
content: t('restartself_to_take_effect'),
onOk: () => {
exit(true);
},
});
/* Message.info(t('about_to_restart_self'))
setTimeout(() => {
exit(true)
@@ -95,8 +112,8 @@ function Mount_page() {
} else {
Message.error(t('install_failed'))
}
setWinFspInstalling(false)
await getWinFspState()
setWinFspInstalling(false)
}} loading={winFspInstalling}>{t('install')}</Button>
</>} />
<br />
@@ -114,14 +131,14 @@ function Mount_page() {
mounted: mounted ? t('mounted') : t('unmounted'),
actions: <Space>
{
mounted ? <>
mounted ? <>
<Button onClick={() => { unmountStorage(item.mountPath) }} status='danger' >{t('unmount')}</Button>
</> :
<>
<Button onClick={() => { delMountStorage(item.mountPath) }} status='danger' >{t('delete')}</Button>
<Button onClick={() => { navigate('./add?edit=true&mountPath='+item.mountPath) }} >{t('edit')}</Button>
<Button onClick={() => { navigate('./add?edit=true&mountPath=' + item.mountPath) }} >{t('edit')}</Button>
<Button onClick={() => { mountStorage(item) }} type='primary' >{t('mount')}</Button>
</>
</>
}
</Space>
}

View File

@@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'
import { rcloneInfo, rcloneStatsHistory } from '../../services/rclone'
import { hooks } from '../../services/hook'
import { RcloneTransferItem } from '../../type/rclone/stats'
import { Card, Descriptions, List, Progress, Space, Statistic, Grid, Typography } from '@arco-design/web-react'
import { Card, Descriptions, List, Progress, Space, Statistic, Grid, Typography, Alert } from '@arco-design/web-react'
import { formatETA, formatSize } from '../../utils/utils'
import { Area } from '@ant-design/charts'
import { NoData_module } from '../other/noData'
@@ -32,7 +32,17 @@ function Transmit_page() {
title={t('overview')}
bordered={false}
>
<Space direction='vertical' style={{ width: '100%' }}>
{
transmitList.length > 0 && rcloneInfo.stats.realSpeed === 0 &&
<Alert
style={{ margin: '0.1rem' }}
type='info'
content={t('unable_to_obtain_transmission_speed')}
/>
}
{rcloneInfo.stats.bytes > 0 && <Progress percent={~~(rcloneInfo.stats.bytes / rcloneInfo.stats.totalBytes * 100)} />}
<Descriptions colon=' :' data={[
@@ -81,11 +91,11 @@ function Transmit_page() {
{
transmitList.map((item, index) => {
return <List.Item key={index}>
<div style={{ width: '100%' ,display: 'flex' }}>
<div style={{width:'5rem'}}>
<div style={{ width: '100%', display: 'flex' }}>
<div style={{ width: '5rem' }}>
<Progress type={'circle'} percent={item.percentage} style={{ marginTop: '0.5rem' }} size='small' />
</div>
<div style={{width:'calc(100% - 5rem)',overflow:'auto'}}>
<div style={{ width: 'calc(100% - 5rem)', overflow: 'auto' }}>
<Typography.Ellipsis >{item.name}</Typography.Ellipsis>
<Descriptions
size='small'

View File

@@ -1,7 +1,7 @@
import { invoke } from "@tauri-apps/api/core";
import { Command } from "@tauri-apps/plugin-shell";
import { rcloneInfo } from "../../services/rclone";
import { formatPath, randomString, sleep } from "../utils";
import { formatPath, getAvailablePorts, randomString, sleep } from "../utils";
import { alistInfo } from "../../services/alist";
import { homeDir } from "@tauri-apps/api/path";
import { nmConfig, osInfo, roConfig } from "../../services/config";
@@ -21,7 +21,10 @@ const addParams = (): string[] => {
async function startAlist() {
alistInfo.endpoint.url='http://localhost:'+(alistInfo.alistConfig.scheme?.http_port||5573)
//自动分配端口
alistInfo.alistConfig.scheme!.http_port != (await getAvailablePorts(2))[1]
alistInfo.endpoint.url = 'http://localhost:' + (alistInfo.alistConfig.scheme?.http_port || 5573)
await setAlistPass(nmConfig.framework.alist.password)
alistInfo.endpoint.auth.token = await getAlistToken()
@@ -46,7 +49,7 @@ async function startAlist() {
while (true) {
await sleep(500)
if (await alist_api_ping()&&alistInfo.process.log.includes('start HTTP server')) {
if (await alist_api_ping() && alistInfo.process.log.includes('start HTTP server')) {
break;
}
}
@@ -56,9 +59,9 @@ async function stopAlist() {
alistInfo.process.child && await alistInfo.process.child.kill()
}
async function restartAlist() {
async function restartAlist() {
await stopAlist()
await startAlist()
}
export { addParams, startAlist, stopAlist, alistDataDir ,restartAlist}
export { addParams, startAlist, stopAlist, alistDataDir, restartAlist }

View File

@@ -2,7 +2,7 @@ import { invoke } from "@tauri-apps/api/core";
import { Command } from "@tauri-apps/plugin-shell";
import { rcloneInfo } from "../../services/rclone";
import { rclone_api_noop, rclone_api_post } from "./request";
import { formatPath, randomString, sleep } from "../utils";
import { formatPath, getAvailablePorts, randomString, sleep } from "../utils";
import { alistInfo } from "../../services/alist";
import { delStorage } from "../../controller/storage/storage";
import { nmConfig, osInfo, roConfig } from "../../services/config";
@@ -21,6 +21,9 @@ async function startRclone() {
rcloneInfo.endpoint.auth.pass = randomString(128)
} */
//自动分配端口
rcloneInfo.endpoint.localhost.port = (await getAvailablePorts(2))[1]
rcloneInfo.endpoint.url = 'http://localhost:' + rcloneInfo.endpoint.localhost.port.toString()
let args: string[] = [

View File

@@ -212,4 +212,9 @@ export async function showPathInExplorer(path: string, isDir?: boolean) {
export async function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
export async function getAvailablePorts(count: number = 1) {
return await invoke('get_available_ports',{count:count}) as number[]
}