mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-28 05:30:29 +08:00
open file
This commit is contained in:
parent
c5c90caa1b
commit
df41310237
@ -1,9 +1,17 @@
|
||||
import { exec, execFile, execSync } from 'child_process'
|
||||
import { dialog, nativeTheme } from 'electron'
|
||||
import { dialog, nativeTheme, shell } from 'electron'
|
||||
import { readFile } from 'fs/promises'
|
||||
import path from 'path'
|
||||
import { promisify } from 'util'
|
||||
import { exePath, mihomoCorePath, resourcesDir, resourcesFilesDir, taskDir } from '../utils/dirs'
|
||||
import {
|
||||
exePath,
|
||||
mihomoCorePath,
|
||||
overridePath,
|
||||
profilePath,
|
||||
resourcesDir,
|
||||
resourcesFilesDir,
|
||||
taskDir
|
||||
} from '../utils/dirs'
|
||||
import { copyFileSync, writeFileSync } from 'fs'
|
||||
|
||||
export function getFilePath(ext: string[]): string[] | undefined {
|
||||
@ -18,6 +26,15 @@ export async function readTextFile(filePath: string): Promise<string> {
|
||||
return await readFile(filePath, 'utf8')
|
||||
}
|
||||
|
||||
export function openFile(type: 'profile' | 'override', id: string, ext?: 'yaml' | 'js'): void {
|
||||
if (type === 'profile') {
|
||||
shell.openPath(profilePath(id))
|
||||
}
|
||||
if (type === 'override') {
|
||||
shell.openPath(overridePath(id, ext || 'js'))
|
||||
}
|
||||
}
|
||||
|
||||
export async function openUWPTool(): Promise<void> {
|
||||
const execFilePromise = promisify(execFile)
|
||||
const uwpToolPath = path.join(resourcesDir(), 'files', 'enableLoopback.exe')
|
||||
|
||||
@ -49,7 +49,14 @@ import {
|
||||
import { isEncryptionAvailable, manualGrantCorePermition, restartCore } from '../core/manager'
|
||||
import { triggerSysProxy } from '../sys/sysproxy'
|
||||
import { checkUpdate, downloadAndInstallUpdate } from '../resolve/autoUpdater'
|
||||
import { getFilePath, openUWPTool, readTextFile, setNativeTheme, setupFirewall } from '../sys/misc'
|
||||
import {
|
||||
getFilePath,
|
||||
openFile,
|
||||
openUWPTool,
|
||||
readTextFile,
|
||||
setNativeTheme,
|
||||
setupFirewall
|
||||
} from '../sys/misc'
|
||||
import { getRuntimeConfig, getRuntimeConfigStr } from '../core/factory'
|
||||
import { isPortable, setPortable } from './dirs'
|
||||
import { listWebdavBackups, webdavBackup, webdavDelete, webdavRestore } from '../resolve/backup'
|
||||
@ -171,6 +178,7 @@ export function registerIpcMainHandlers(): void {
|
||||
ipcMain.handle('setNativeTheme', (_e, theme) => {
|
||||
setNativeTheme(theme)
|
||||
})
|
||||
ipcMain.handle('openFile', (_e, type, id, ext) => openFile(type, id, ext))
|
||||
ipcMain.handle('copyEnv', ipcErrorWrapper(copyEnv))
|
||||
ipcMain.handle('alert', (_e, msg) => {
|
||||
dialog.showErrorBox('Mihomo Party', msg)
|
||||
|
||||
@ -7,23 +7,7 @@ interface Props {
|
||||
connection: IMihomoConnectionDetail
|
||||
onClose: () => void
|
||||
}
|
||||
// sourceIP: string
|
||||
// destinationIP: string
|
||||
// destinationGeoIP: string
|
||||
// destinationIPASN: string
|
||||
// sourcePort: string
|
||||
// destinationPort: string
|
||||
// inboundIP: string
|
||||
// inboundPort: string
|
||||
// inboundName: string
|
||||
// inboundUser: string
|
||||
// host: string
|
||||
// dnsMode: string
|
||||
// specialProxy: string
|
||||
// specialRules: string
|
||||
// remoteDestination: string
|
||||
// dscp: number
|
||||
// sniffHost: string
|
||||
|
||||
const ConnectionDetailModal: React.FC<Props> = (props) => {
|
||||
const { connection, onClose } = props
|
||||
return (
|
||||
|
||||
@ -16,6 +16,7 @@ import EditInfoModal from './edit-info-modal'
|
||||
import { useSortable } from '@dnd-kit/sortable'
|
||||
import { CSS } from '@dnd-kit/utilities'
|
||||
import ExecLogModal from './exec-log-modal'
|
||||
import { openFile } from '@renderer/utils/ipc'
|
||||
|
||||
interface Props {
|
||||
info: IOverrideItem
|
||||
@ -48,6 +49,13 @@ const menuItems: MenuItem[] = [
|
||||
color: 'default',
|
||||
className: ''
|
||||
} as MenuItem,
|
||||
{
|
||||
key: 'open-file',
|
||||
label: '打开文件',
|
||||
showDivider: false,
|
||||
color: 'default',
|
||||
className: ''
|
||||
} as MenuItem,
|
||||
{
|
||||
key: 'exec-log',
|
||||
label: '执行日志',
|
||||
@ -68,8 +76,8 @@ const OverrideItem: React.FC<Props> = (props) => {
|
||||
const { info, addOverrideItem, removeOverrideItem, mutateOverrideConfig, updateOverrideItem } =
|
||||
props
|
||||
const [updating, setUpdating] = useState(false)
|
||||
const [openInfo, setOpenInfo] = useState(false)
|
||||
const [openFile, setOpenFile] = useState(false)
|
||||
const [openInfoEditor, setOpenInfoEditor] = useState(false)
|
||||
const [openFileEditor, setOpenFileEditor] = useState(false)
|
||||
const [openLog, setOpenLog] = useState(false)
|
||||
const {
|
||||
attributes,
|
||||
@ -87,11 +95,15 @@ const OverrideItem: React.FC<Props> = (props) => {
|
||||
const onMenuAction = (key: Key): void => {
|
||||
switch (key) {
|
||||
case 'edit-info': {
|
||||
setOpenInfo(true)
|
||||
setOpenInfoEditor(true)
|
||||
break
|
||||
}
|
||||
case 'edit-file': {
|
||||
setOpenFile(true)
|
||||
setOpenFileEditor(true)
|
||||
break
|
||||
}
|
||||
case 'open-file': {
|
||||
openFile('override', info.id, info.ext)
|
||||
break
|
||||
}
|
||||
case 'exec-log': {
|
||||
@ -128,17 +140,17 @@ const OverrideItem: React.FC<Props> = (props) => {
|
||||
zIndex: isDragging ? 'calc(infinity)' : undefined
|
||||
}}
|
||||
>
|
||||
{openFile && (
|
||||
{openFileEditor && (
|
||||
<EditFileModal
|
||||
id={info.id}
|
||||
language={info.ext === 'yaml' ? 'yaml' : 'javascript'}
|
||||
onClose={() => setOpenFile(false)}
|
||||
onClose={() => setOpenFileEditor(false)}
|
||||
/>
|
||||
)}
|
||||
{openInfo && (
|
||||
{openInfoEditor && (
|
||||
<EditInfoModal
|
||||
item={info}
|
||||
onClose={() => setOpenInfo(false)}
|
||||
onClose={() => setOpenInfoEditor(false)}
|
||||
updateOverrideItem={updateOverrideItem}
|
||||
/>
|
||||
)}
|
||||
@ -148,7 +160,7 @@ const OverrideItem: React.FC<Props> = (props) => {
|
||||
isPressable
|
||||
onPress={() => {
|
||||
if (disableOpen) return
|
||||
setOpenFile(true)
|
||||
setOpenFileEditor(true)
|
||||
}}
|
||||
>
|
||||
<CardBody>
|
||||
|
||||
@ -18,6 +18,7 @@ import EditFileModal from './edit-file-modal'
|
||||
import EditInfoModal from './edit-info-modal'
|
||||
import { useSortable } from '@dnd-kit/sortable'
|
||||
import { CSS } from '@dnd-kit/utilities'
|
||||
import { openFile } from '@renderer/utils/ipc'
|
||||
|
||||
interface Props {
|
||||
info: IProfileItem
|
||||
@ -51,8 +52,8 @@ const ProfileItem: React.FC<Props> = (props) => {
|
||||
const total = extra?.total ?? 0
|
||||
const [updating, setUpdating] = useState(false)
|
||||
const [selecting, setSelecting] = useState(false)
|
||||
const [openInfo, setOpenInfo] = useState(false)
|
||||
const [openFile, setOpenFile] = useState(false)
|
||||
const [openInfoEditor, setOpenInfoEditor] = useState(false)
|
||||
const [openFileEditor, setOpenFileEditor] = useState(false)
|
||||
const {
|
||||
attributes,
|
||||
listeners,
|
||||
@ -78,6 +79,13 @@ const ProfileItem: React.FC<Props> = (props) => {
|
||||
{
|
||||
key: 'edit-file',
|
||||
label: '编辑文件',
|
||||
showDivider: false,
|
||||
color: 'default',
|
||||
className: ''
|
||||
} as MenuItem,
|
||||
{
|
||||
key: 'open-file',
|
||||
label: '打开文件',
|
||||
showDivider: true,
|
||||
color: 'default',
|
||||
className: ''
|
||||
@ -105,11 +113,15 @@ const ProfileItem: React.FC<Props> = (props) => {
|
||||
const onMenuAction = async (key: Key): Promise<void> => {
|
||||
switch (key) {
|
||||
case 'edit-info': {
|
||||
setOpenInfo(true)
|
||||
setOpenInfoEditor(true)
|
||||
break
|
||||
}
|
||||
case 'edit-file': {
|
||||
setOpenFile(true)
|
||||
setOpenFileEditor(true)
|
||||
break
|
||||
}
|
||||
case 'open-file': {
|
||||
openFile('profile', info.id)
|
||||
break
|
||||
}
|
||||
case 'delete': {
|
||||
@ -147,11 +159,11 @@ const ProfileItem: React.FC<Props> = (props) => {
|
||||
zIndex: isDragging ? 'calc(infinity)' : undefined
|
||||
}}
|
||||
>
|
||||
{openFile && <EditFileModal id={info.id} onClose={() => setOpenFile(false)} />}
|
||||
{openInfo && (
|
||||
{openFileEditor && <EditFileModal id={info.id} onClose={() => setOpenFileEditor(false)} />}
|
||||
{openInfoEditor && (
|
||||
<EditInfoModal
|
||||
item={info}
|
||||
onClose={() => setOpenInfo(false)}
|
||||
onClose={() => setOpenInfoEditor(false)}
|
||||
updateProfileItem={updateProfileItem}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -297,6 +297,14 @@ export async function setNativeTheme(theme: 'system' | 'light' | 'dark'): Promis
|
||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('setNativeTheme', theme))
|
||||
}
|
||||
|
||||
export async function openFile(
|
||||
type: 'profile' | 'override',
|
||||
id: string,
|
||||
ext?: 'yaml' | 'js'
|
||||
): Promise<void> {
|
||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('openFile', type, id, ext))
|
||||
}
|
||||
|
||||
export async function registerShortcut(
|
||||
oldShortcut: string,
|
||||
newShortcut: string,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user