mirror of
https://github.com/neosubhamoy/pytubepp-helper.git
synced 2026-02-04 11:22:22 +05:30
(refactor): migrated tauri project to v2
This commit is contained in:
167
package-lock.json
generated
167
package-lock.json
generated
@@ -14,7 +14,10 @@
|
||||
"@radix-ui/react-slot": "^1.1.1",
|
||||
"@radix-ui/react-toast": "^1.2.5",
|
||||
"@radix-ui/react-tooltip": "^1.1.7",
|
||||
"@tauri-apps/api": "^1",
|
||||
"@tauri-apps/api": "^2.0.0",
|
||||
"@tauri-apps/plugin-fs": "^2.2.0",
|
||||
"@tauri-apps/plugin-os": "^2.2.0",
|
||||
"@tauri-apps/plugin-shell": "^2.2.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"dotenv": "^16.4.5",
|
||||
@@ -28,7 +31,7 @@
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^1",
|
||||
"@tauri-apps/cli": "^2.2.7",
|
||||
"@types/node": "^22.2.0",
|
||||
"@types/react": "^18.2.15",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
@@ -1655,29 +1658,21 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@tauri-apps/api": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.6.0.tgz",
|
||||
"integrity": "sha512-rqI++FWClU5I2UBp4HXFvl+sBWkdigBkxnpJDQUWttNyG7IZP4FwQGhTNL5EOw0vI8i6eSAJ5frLqO7n7jbJdg==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.0.0.tgz",
|
||||
"integrity": "sha512-moKgCp2EX7X5GiOx/G/bmoEpkFQVVmyS98UaJU4xUVzan+E1BdwlAKcbip+cGldshYOqL4JSwAEN1OkRXeug0Q==",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"engines": {
|
||||
"node": ">= 14.6.0",
|
||||
"npm": ">= 6.6.0",
|
||||
"yarn": ">= 1.19.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/tauri"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.6.3.tgz",
|
||||
"integrity": "sha512-q46umd6QLRKDd4Gg6WyZBGa2fWvk0pbeUA5vFomm4uOs1/17LIciHv2iQ4UD+2Yv5H7AO8YiE1t50V0POiEGEw==",
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.2.7.tgz",
|
||||
"integrity": "sha512-ZnsS2B4BplwXP37celanNANiIy8TCYhvg5RT09n72uR/o+navFZtGpFSqljV8fy1Y4ixIPds8FrGSXJCN2BerA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"dependencies": {
|
||||
"semver": ">=7.5.2"
|
||||
},
|
||||
"bin": {
|
||||
"tauri": "tauri.js"
|
||||
},
|
||||
@@ -1689,27 +1684,27 @@
|
||||
"url": "https://opencollective.com/tauri"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@tauri-apps/cli-darwin-arm64": "1.6.3",
|
||||
"@tauri-apps/cli-darwin-x64": "1.6.3",
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": "1.6.3",
|
||||
"@tauri-apps/cli-linux-arm64-gnu": "1.6.3",
|
||||
"@tauri-apps/cli-linux-arm64-musl": "1.6.3",
|
||||
"@tauri-apps/cli-linux-x64-gnu": "1.6.3",
|
||||
"@tauri-apps/cli-linux-x64-musl": "1.6.3",
|
||||
"@tauri-apps/cli-win32-arm64-msvc": "1.6.3",
|
||||
"@tauri-apps/cli-win32-ia32-msvc": "1.6.3",
|
||||
"@tauri-apps/cli-win32-x64-msvc": "1.6.3"
|
||||
"@tauri-apps/cli-darwin-arm64": "2.2.7",
|
||||
"@tauri-apps/cli-darwin-x64": "2.2.7",
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": "2.2.7",
|
||||
"@tauri-apps/cli-linux-arm64-gnu": "2.2.7",
|
||||
"@tauri-apps/cli-linux-arm64-musl": "2.2.7",
|
||||
"@tauri-apps/cli-linux-x64-gnu": "2.2.7",
|
||||
"@tauri-apps/cli-linux-x64-musl": "2.2.7",
|
||||
"@tauri-apps/cli-win32-arm64-msvc": "2.2.7",
|
||||
"@tauri-apps/cli-win32-ia32-msvc": "2.2.7",
|
||||
"@tauri-apps/cli-win32-x64-msvc": "2.2.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-darwin-arm64": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.6.3.tgz",
|
||||
"integrity": "sha512-fQN6IYSL8bG4NvkdKE4sAGF4dF/QqqQq4hOAU+t8ksOzHJr0hUlJYfncFeJYutr/MMkdF7hYKadSb0j5EE9r0A==",
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.2.7.tgz",
|
||||
"integrity": "sha512-54kcpxZ3X1Rq+pPTzk3iIcjEVY4yv493uRx/80rLoAA95vAC0c//31Whz75UVddDjJfZvXlXZ3uSZ+bnCOnt0A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
@@ -1719,14 +1714,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-darwin-x64": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.6.3.tgz",
|
||||
"integrity": "sha512-1yTXZzLajKAYINJOJhZfmMhCzweHSgKQ3bEgJSn6t+1vFkOgY8Yx4oFgWcybrrWI5J1ZLZAl47+LPOY81dLcyA==",
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.2.7.tgz",
|
||||
"integrity": "sha512-Vgu2XtBWemLnarB+6LqQeLanDlRj7CeFN//H8bVVdjbNzxcSxsvbLYMBP8+3boa7eBnjDrqMImRySSgL6IrwTw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
@@ -1736,14 +1731,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.6.3.tgz",
|
||||
"integrity": "sha512-CjTEr9r9xgjcvos09AQw8QMRPuH152B1jvlZt4PfAsyJNPFigzuwed5/SF7XAd8bFikA7zArP4UT12RdBxrx7w==",
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.2.7.tgz",
|
||||
"integrity": "sha512-+Clha2iQAiK9zoY/KKW0KLHkR0k36O78YLx5Sl98tWkwI3OBZFg5H5WT1plH/4sbZIS2aLFN6dw58/JlY9Bu/g==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
@@ -1753,14 +1748,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.6.3.tgz",
|
||||
"integrity": "sha512-G9EUUS4M8M/Jz1UKZqvJmQQCKOzgTb8/0jZKvfBuGfh5AjFBu8LHvlFpwkKVm1l4951Xg4ulUp6P9Q7WRJ9XSA==",
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.2.7.tgz",
|
||||
"integrity": "sha512-Z/Lp4SQe6BUEOays9BQAEum2pvZF4w9igyXijP+WbkOejZx4cDvarFJ5qXrqSLmBh7vxrdZcLwoLk9U//+yQrg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
@@ -1770,14 +1765,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.6.3.tgz",
|
||||
"integrity": "sha512-MuBTHJyNpZRbPVG8IZBN8+Zs7aKqwD22tkWVBcL1yOGL4zNNTJlkfL+zs5qxRnHlUsn6YAlbW/5HKocfpxVwBw==",
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.7.tgz",
|
||||
"integrity": "sha512-+8HZ+txff/Y3YjAh80XcLXcX8kpGXVdr1P8AfjLHxHdS6QD4Md+acSxGTTNbplmHuBaSHJvuTvZf9tU1eDCTDg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
@@ -1787,14 +1782,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.6.3.tgz",
|
||||
"integrity": "sha512-Uvi7M+NK3tAjCZEY1WGel+dFlzJmqcvu3KND+nqa22762NFmOuBIZ4KJR/IQHfpEYqKFNUhJfCGnpUDfiC3Oxg==",
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.2.7.tgz",
|
||||
"integrity": "sha512-ahlSnuCnUntblp9dG7/w5ZWZOdzRFi3zl0oScgt7GF4KNAOEa7duADsxPA4/FT2hLRa0SvpqtD4IYFvCxoVv3Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
@@ -1804,14 +1799,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-x64-musl": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.6.3.tgz",
|
||||
"integrity": "sha512-rc6B342C0ra8VezB/OJom9j/N+9oW4VRA4qMxS2f4bHY2B/z3J9NPOe6GOILeg4v/CV62ojkLsC3/K/CeF3fqQ==",
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.2.7.tgz",
|
||||
"integrity": "sha512-+qKAWnJRSX+pjjRbKAQgTdFY8ecdcu8UdJ69i7wn3ZcRn2nMMzOO2LOMOTQV42B7/Q64D1pIpmZj9yblTMvadA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
@@ -1821,14 +1816,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-arm64-msvc": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.6.3.tgz",
|
||||
"integrity": "sha512-cSH2qOBYuYC4UVIFtrc1YsGfc5tfYrotoHrpTvRjUGu0VywvmyNk82+ZsHEnWZ2UHmu3l3lXIGRqSWveLln0xg==",
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.2.7.tgz",
|
||||
"integrity": "sha512-aa86nRnrwT04u9D9fhf5JVssuAZlUCCc8AjqQjqODQjMd4BMA2+d4K9qBMpEG/1kVh95vZaNsLogjEaqSTTw4A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
@@ -1838,14 +1833,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.6.3.tgz",
|
||||
"integrity": "sha512-T8V6SJQqE4PSWmYBl0ChQVmS6AR2hXFHURH2DwAhgSGSQ6uBXgwlYFcfIeQpBQA727K2Eq8X2hGfvmoySyHMRw==",
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.2.7.tgz",
|
||||
"integrity": "sha512-EiJ5/25tLSQOSGvv+t6o3ZBfOTKB5S3vb+hHQuKbfmKdRF0XQu2YPdIi1CQw1DU97ZAE0Dq4frvnyYEKWgMzVQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
@@ -1855,14 +1850,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.6.3.tgz",
|
||||
"integrity": "sha512-HUkWZ+lYHI/Gjkh2QjHD/OBDpqLVmvjZGpLK9losur1Eg974Jip6k+vsoTUxQBCBDfj30eDBct9E1FvXOspWeg==",
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.2.7.tgz",
|
||||
"integrity": "sha512-ZB8Kw90j8Ld+9tCWyD2fWCYfIrzbQohJ4DJSidNwbnehlZzP7wAz6Z3xjsvUdKtQ3ibtfoeTqVInzCCEpI+pWg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
@@ -1871,6 +1866,33 @@
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/plugin-fs": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-fs/-/plugin-fs-2.2.0.tgz",
|
||||
"integrity": "sha512-+08mApuONKI8/sCNEZ6AR8vf5vI9DXD4YfrQ9NQmhRxYKMLVhRW164vdW5BSLmMpuevftpQ2FVoL9EFkfG9Z+g==",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/plugin-os": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-os/-/plugin-os-2.2.0.tgz",
|
||||
"integrity": "sha512-HszbCdbisMlu5QhCNAN8YIWyz2v33abAWha6+uvV2CKX8P5VSct/y+kEe22JeyqrxCnWlQ3DRx7s49Byg7/0EA==",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/plugin-shell": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@tauri-apps/plugin-shell/-/plugin-shell-2.2.0.tgz",
|
||||
"integrity": "sha512-iC3Ic1hLmasoboG7BO+7p+AriSoqAwKrIk+Hpk+S/bjTQdXqbl2GbdclghI4gM32X0bls7xHzIFqhRdrlvJeaA==",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
||||
@@ -3343,19 +3365,6 @@
|
||||
"loose-envify": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/set-cookie-parser": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
"@radix-ui/react-slot": "^1.1.1",
|
||||
"@radix-ui/react-toast": "^1.2.5",
|
||||
"@radix-ui/react-tooltip": "^1.1.7",
|
||||
"@tauri-apps/api": "^1",
|
||||
"@tauri-apps/api": "^2.0.0",
|
||||
"@tauri-apps/plugin-fs": "^2.2.0",
|
||||
"@tauri-apps/plugin-os": "^2.2.0",
|
||||
"@tauri-apps/plugin-shell": "^2.2.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"dotenv": "^16.4.5",
|
||||
@@ -30,7 +33,7 @@
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^1",
|
||||
"@tauri-apps/cli": "^2.2.7",
|
||||
"@types/node": "^22.2.0",
|
||||
"@types/react": "^18.2.15",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
|
||||
2265
src-tauri/Cargo.lock
generated
2265
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -4,14 +4,15 @@ version = "0.6.0"
|
||||
description = "PytubePP Helper"
|
||||
authors = ["neosubhamoy"]
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1", features = [] }
|
||||
tauri-build = { version = "2", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "1", features = [ "os-all", "process-relaunch", "window-start-dragging", "window-close", "window-unmaximize", "process-exit", "window-show", "window-unminimize", "window-hide", "window-minimize", "window-maximize", "system-tray", "shell-all"] }
|
||||
tauri = { version = "2", features = ["tray-icon"] }
|
||||
directories = "5.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
@@ -19,11 +20,18 @@ tokio = { version = "1.39.2", features = ["full"] }
|
||||
tokio-tungstenite = "*"
|
||||
futures-util = "0.3.30"
|
||||
fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" }
|
||||
tauri-plugin-shell = "2"
|
||||
tauri-plugin-fs = "2"
|
||||
tauri-plugin-os = "2"
|
||||
|
||||
[features]
|
||||
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
|
||||
[lib]
|
||||
name = "pytubepp_helper_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
".",
|
||||
|
||||
18
src-tauri/capabilities/default.json
Normal file
18
src-tauri/capabilities/default.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "main-capability",
|
||||
"description": "default permissions",
|
||||
"local": true,
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"shell:default",
|
||||
"os:default",
|
||||
"fs:default",
|
||||
"core:window:allow-hide",
|
||||
"fs:allow-app-write",
|
||||
"fs:allow-app-write-recursive"
|
||||
]
|
||||
}
|
||||
98
src-tauri/capabilities/shell.json
Normal file
98
src-tauri/capabilities/shell.json
Normal file
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "shell-scope",
|
||||
"description": "allowed shell scopes",
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
{
|
||||
"identifier": "shell:allow-execute",
|
||||
"allow": [
|
||||
{
|
||||
"name": "detect-windows",
|
||||
"cmd": "systeminfo",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "detect-macos",
|
||||
"cmd": "sw_vers",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "detect-distro",
|
||||
"cmd": "grep",
|
||||
"args": ["^ID=", "/etc/os-release"]
|
||||
},
|
||||
{
|
||||
"name": "detect-pkgmngr",
|
||||
"cmd": "sh",
|
||||
"args": ["-c", "command -v apt || command -v dnf || command -v pacman"]
|
||||
},
|
||||
{
|
||||
"name": "is-apt-installed",
|
||||
"cmd": "apt",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-dnf-installed",
|
||||
"cmd": "dnf",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-python3-installed",
|
||||
"cmd": "python3",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-pip3-installed",
|
||||
"cmd": "pip3",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-winget-installed",
|
||||
"cmd": "winget",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-homebrew-installed",
|
||||
"cmd": "brew",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-python-installed",
|
||||
"cmd": "python",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-pip-installed",
|
||||
"cmd": "pip",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-ffmpeg-installed",
|
||||
"cmd": "ffmpeg",
|
||||
"args": ["-version"]
|
||||
},
|
||||
{
|
||||
"name": "is-nodejs-installed",
|
||||
"cmd": "node",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-pytubepp-installed",
|
||||
"cmd": "pytubepp",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "fetch-video-info",
|
||||
"cmd": "pytubepp",
|
||||
"args": [{ "validator": "\\S+" }, "--raw-info"]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"platforms": [
|
||||
"windows",
|
||||
"macOS",
|
||||
"linux"
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
use directories::ProjectDirs;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use directories::ProjectDirs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -10,9 +10,7 @@ pub struct Config {
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
port: 3030,
|
||||
}
|
||||
Self { port: 3030 }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
mod config;
|
||||
use config::load_config;
|
||||
use serde_json::Value;
|
||||
use std::io::{self, Read, Write};
|
||||
use websocket::client::ClientBuilder;
|
||||
use websocket::OwnedMessage;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use serde_json::Value;
|
||||
use websocket::client::ClientBuilder;
|
||||
use websocket::OwnedMessage;
|
||||
|
||||
fn get_websocket_url() -> String {
|
||||
let config = load_config();
|
||||
format!("ws://localhost:{}", config.port)
|
||||
}
|
||||
|
||||
fn connect_with_retry(url: &str, max_attempts: u32) -> Result<websocket::sync::Client<std::net::TcpStream>, Box<dyn std::error::Error>> {
|
||||
fn connect_with_retry(
|
||||
url: &str,
|
||||
max_attempts: u32,
|
||||
) -> Result<websocket::sync::Client<std::net::TcpStream>, Box<dyn std::error::Error>> {
|
||||
let mut attempts = 0;
|
||||
loop {
|
||||
match ClientBuilder::new(url).unwrap().connect_insecure() {
|
||||
@@ -26,7 +29,10 @@ fn connect_with_retry(url: &str, max_attempts: u32) -> Result<websocket::sync::C
|
||||
return Err(Box::new(e));
|
||||
}
|
||||
let wait_time = Duration::from_secs(2u64.pow(attempts));
|
||||
eprintln!("Connection attempt {} failed. Retrying in {:?}...", attempts, wait_time);
|
||||
eprintln!(
|
||||
"Connection attempt {} failed. Retrying in {:?}...",
|
||||
attempts, wait_time
|
||||
);
|
||||
sleep(wait_time);
|
||||
}
|
||||
}
|
||||
@@ -62,7 +68,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Ok(msg) => {
|
||||
eprintln!("Received message: {}", msg);
|
||||
msg
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error reading message: {:?}", e);
|
||||
return Err(e);
|
||||
@@ -70,10 +76,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
};
|
||||
|
||||
// Send immediate response to the extension
|
||||
write_stdout_message(&serde_json::json!({
|
||||
"status": "received",
|
||||
"message": "Message received by native host"
|
||||
}).to_string())?;
|
||||
write_stdout_message(
|
||||
&serde_json::json!({
|
||||
"status": "received",
|
||||
"message": "Message received by native host"
|
||||
})
|
||||
.to_string(),
|
||||
)?;
|
||||
|
||||
let parsed: Value = serde_json::from_str(&input)?;
|
||||
|
||||
@@ -84,10 +93,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Ok(client) => client,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to connect after multiple attempts: {:?}", e);
|
||||
write_stdout_message(&serde_json::json!({
|
||||
"status": "error",
|
||||
"message": "Failed to connect to Tauri app"
|
||||
}).to_string())?;
|
||||
write_stdout_message(
|
||||
&serde_json::json!({
|
||||
"status": "error",
|
||||
"message": "Failed to connect to Tauri app"
|
||||
})
|
||||
.to_string(),
|
||||
)?;
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
@@ -100,10 +112,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// Send Tauri app's response back to browser extension
|
||||
if let OwnedMessage::Text(text) = message {
|
||||
write_stdout_message(&serde_json::json!({
|
||||
"status": "success",
|
||||
"response": text
|
||||
}).to_string())?;
|
||||
write_stdout_message(
|
||||
&serde_json::json!({
|
||||
"status": "success",
|
||||
"response": text
|
||||
})
|
||||
.to_string(),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use directories::ProjectDirs;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use directories::ProjectDirs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -10,9 +10,7 @@ pub struct Config {
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
port: 3030,
|
||||
}
|
||||
Self { port: 3030 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +35,8 @@ pub fn load_config() -> Config {
|
||||
}
|
||||
|
||||
pub fn save_config(config: &Config) -> Result<(), String> {
|
||||
let config_dir = get_config_dir()
|
||||
.ok_or_else(|| "Could not determine config directory".to_string())?;
|
||||
let config_dir =
|
||||
get_config_dir().ok_or_else(|| "Could not determine config directory".to_string())?;
|
||||
|
||||
fs::create_dir_all(&config_dir)
|
||||
.map_err(|e| format!("Failed to create config directory: {}", e))?;
|
||||
@@ -47,8 +45,7 @@ pub fn save_config(config: &Config) -> Result<(), String> {
|
||||
let content = serde_json::to_string_pretty(config)
|
||||
.map_err(|e| format!("Failed to serialize config: {}", e))?;
|
||||
|
||||
fs::write(config_path, content)
|
||||
.map_err(|e| format!("Failed to write config file: {}", e))?;
|
||||
fs::write(config_path, content).map_err(|e| format!("Failed to write config file: {}", e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
495
src-tauri/src/lib.rs
Normal file
495
src-tauri/src/lib.rs
Normal file
@@ -0,0 +1,495 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
mod config;
|
||||
use config::{get_config_path, load_config, save_config, Config};
|
||||
use futures_util::{SinkExt, StreamExt};
|
||||
use serde_json::Value;
|
||||
use std::{env, process::Command, sync::Arc, time::Duration};
|
||||
use tauri::{
|
||||
menu::{Menu, MenuItem},
|
||||
tray::{TrayIconBuilder, TrayIconEvent, MouseButton, MouseButtonState},
|
||||
Manager, Emitter
|
||||
};
|
||||
use tokio::{
|
||||
net::{TcpListener, TcpStream},
|
||||
sync::{oneshot, Mutex},
|
||||
time::sleep,
|
||||
};
|
||||
use tokio_tungstenite::{accept_async, connect_async};
|
||||
|
||||
struct ResponseChannel {
|
||||
sender: Option<oneshot::Sender<String>>,
|
||||
}
|
||||
|
||||
struct WebSocketState {
|
||||
sender: Option<
|
||||
futures_util::stream::SplitSink<
|
||||
tokio_tungstenite::WebSocketStream<TcpStream>,
|
||||
tokio_tungstenite::tungstenite::Message,
|
||||
>,
|
||||
>,
|
||||
response_channel: ResponseChannel,
|
||||
server_abort: Option<tokio::sync::oneshot::Sender<()>>,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
async fn is_another_instance_running(port: u16) -> bool {
|
||||
match connect_async(format!("ws://127.0.0.1:{}", port)).await {
|
||||
Ok(_) => true,
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
async fn try_bind_ws_port(port: u16) -> Option<TcpListener> {
|
||||
match TcpListener::bind(format!("127.0.0.1:{}", port)).await {
|
||||
Ok(listener) => Some(listener),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
async fn start_websocket_server(app_handle: tauri::AppHandle, port: u16) -> Result<(), String> {
|
||||
let addr = format!("127.0.0.1:{}", port);
|
||||
|
||||
// First ensure any existing server is stopped
|
||||
{
|
||||
let state = app_handle.state::<Arc<Mutex<WebSocketState>>>();
|
||||
let mut state = state.lock().await;
|
||||
if let Some(old_abort) = state.server_abort.take() {
|
||||
let _ = old_abort.send(());
|
||||
// Give it a moment to shut down
|
||||
sleep(Duration::from_millis(200)).await;
|
||||
}
|
||||
}
|
||||
|
||||
// Now try to bind to the port
|
||||
let listener = TcpListener::bind(&addr)
|
||||
.await
|
||||
.map_err(|e| format!("Failed to bind to port {}: {}", port, e))?;
|
||||
|
||||
let (abort_sender, mut abort_receiver) = tokio::sync::oneshot::channel();
|
||||
|
||||
// Store the new abort sender
|
||||
{
|
||||
let state = app_handle.state::<Arc<Mutex<WebSocketState>>>();
|
||||
let mut state = state.lock().await;
|
||||
state.server_abort = Some(abort_sender);
|
||||
}
|
||||
|
||||
// Spawn the server task
|
||||
tokio::spawn(async move {
|
||||
println!("Starting WebSocket server on port {}", port);
|
||||
loop {
|
||||
tokio::select! {
|
||||
accept_result = listener.accept() => {
|
||||
match accept_result {
|
||||
Ok((stream, _)) => {
|
||||
let app_handle = app_handle.clone();
|
||||
tokio::spawn(handle_connection(stream, app_handle));
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error accepting connection: {}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = &mut abort_receiver => {
|
||||
println!("WebSocket server shutting down on port {}...", port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Wait a moment to ensure the server has started
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_config(state: tauri::State<'_, Arc<Mutex<WebSocketState>>>) -> Result<Config, String> {
|
||||
let state = state.lock().await;
|
||||
Ok(state.config.clone())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn get_config_file_path() -> Result<String, String> {
|
||||
match get_config_path() {
|
||||
Some(path) => Ok(path.to_string_lossy().into_owned()),
|
||||
None => Err("Could not determine config path".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn update_config(
|
||||
new_config: Config,
|
||||
state: tauri::State<'_, Arc<Mutex<WebSocketState>>>,
|
||||
app_handle: tauri::AppHandle,
|
||||
) -> Result<Config, String> {
|
||||
// Save the new config first
|
||||
save_config(&new_config)?;
|
||||
|
||||
// Update the state with new config
|
||||
{
|
||||
let mut state = state.lock().await;
|
||||
state.config = new_config.clone();
|
||||
}
|
||||
|
||||
// Start the new server (this will also handle stopping the old one)
|
||||
start_websocket_server(app_handle, new_config.port).await?;
|
||||
|
||||
Ok(new_config)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn reset_config(
|
||||
state: tauri::State<'_, Arc<Mutex<WebSocketState>>>,
|
||||
app_handle: tauri::AppHandle,
|
||||
) -> Result<Config, String> {
|
||||
let config = Config::default();
|
||||
save_config(&config)?;
|
||||
|
||||
{
|
||||
let mut state = state.lock().await;
|
||||
state.config = config.clone();
|
||||
}
|
||||
|
||||
start_websocket_server(app_handle, config.port).await?;
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn send_to_extension(
|
||||
message: String,
|
||||
state: tauri::State<'_, Arc<Mutex<WebSocketState>>>,
|
||||
) -> Result<(), String> {
|
||||
let mut state = state.lock().await;
|
||||
if let Some(sender) = &mut state.sender {
|
||||
sender
|
||||
.send(tokio_tungstenite::tungstenite::Message::Text(message))
|
||||
.await
|
||||
.map_err(|e| format!("Failed to send message: {}", e))?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err("No active WebSocket connection".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn receive_frontend_response(
|
||||
response: String,
|
||||
state: tauri::State<'_, Arc<Mutex<WebSocketState>>>,
|
||||
) -> Result<(), String> {
|
||||
let mut state = state.lock().await;
|
||||
if let Some(sender) = state.response_channel.sender.take() {
|
||||
sender
|
||||
.send(response)
|
||||
.map_err(|e| format!("Failed to send response: {:?}", e))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn fetch_video_info(url: String) {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let command = format!("pytubepp \"{}\" -i", &url);
|
||||
Command::new("cmd")
|
||||
.args(["/k", command.as_str()])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let command = format!("pytubepp \"{}\" -i", &url);
|
||||
Command::new("gnome-terminal")
|
||||
.args(["--", "bash", "-c", command.as_str()])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let command = format!("pytubepp \"{}\" -i", &url);
|
||||
let escaped_command = command.replace("\"", "\\\"");
|
||||
|
||||
let applescript = format!(
|
||||
"tell application \"Terminal\"\n\
|
||||
do script \"{}\"\n\
|
||||
activate\n\
|
||||
end tell",
|
||||
escaped_command
|
||||
);
|
||||
|
||||
Command::new("osascript")
|
||||
.arg("-e")
|
||||
.arg(applescript)
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn install_program(icommand: String) {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let command = format!("{}", &icommand);
|
||||
Command::new("cmd")
|
||||
.args(["/k", command.as_str()])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let command = format!("{}", &icommand);
|
||||
Command::new("gnome-terminal")
|
||||
.args(["--", "bash", "-c", command.as_str()])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let command = format!("{}", &icommand);
|
||||
let escaped_command = command.replace("\"", "\\\"");
|
||||
|
||||
let applescript = format!(
|
||||
"tell application \"Terminal\"\n\
|
||||
do script \"{}\"\n\
|
||||
activate\n\
|
||||
end tell",
|
||||
escaped_command
|
||||
);
|
||||
|
||||
Command::new("osascript")
|
||||
.arg("-e")
|
||||
.arg(applescript)
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn download_stream(url: String, stream: String, caption: Option<String>) {
|
||||
let caption = caption.unwrap_or("none".to_string());
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let command = format!("pytubepp \"{}\" -s {} -c {}", &url, &stream, &caption);
|
||||
Command::new("cmd")
|
||||
.args(["/k", command.as_str()])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let command = format!("pytubepp \"{}\" -s {} -c {}", &url, &stream, &caption);
|
||||
Command::new("gnome-terminal")
|
||||
.args(["--", "bash", "-c", command.as_str()])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let command = format!("pytubepp \"{}\" -s {} -c {}", &url, &stream, &caption);
|
||||
let escaped_command = command.replace("\"", "\\\"");
|
||||
|
||||
let applescript = format!(
|
||||
"tell application \"Terminal\"\n\
|
||||
do script \"{}\"\n\
|
||||
activate\n\
|
||||
end tell",
|
||||
escaped_command
|
||||
);
|
||||
|
||||
Command::new("osascript")
|
||||
.arg("-e")
|
||||
.arg(applescript)
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub async fn run() {
|
||||
let _ = fix_path_env::fix();
|
||||
|
||||
let config = load_config();
|
||||
let port = config.port;
|
||||
|
||||
let websocket_state = Arc::new(Mutex::new(WebSocketState {
|
||||
sender: None,
|
||||
response_channel: ResponseChannel { sender: None },
|
||||
server_abort: None,
|
||||
config,
|
||||
}));
|
||||
|
||||
// Check if another instance is running
|
||||
if is_another_instance_running(port).await {
|
||||
println!("Another instance is already running. Exiting...");
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
// Try to bind to the WebSocket port with a few retries
|
||||
let mut port_available = false;
|
||||
for _ in 0..3 {
|
||||
if let Some(_) = try_bind_ws_port(port).await {
|
||||
port_available = true;
|
||||
break;
|
||||
}
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
}
|
||||
|
||||
// If we couldn't bind to the port after retries, assume another instance is running
|
||||
if !port_available {
|
||||
println!("Could not bind to WebSocket port. Another instance might be running. Exiting...");
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let start_hidden = args.contains(&"--hidden".to_string());
|
||||
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_os::init())
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.manage(websocket_state.clone())
|
||||
.setup(move |app| {
|
||||
// Create menu items
|
||||
let quit = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)
|
||||
.map_err(|e| format!("Failed to create quit menu item: {}", e))?;
|
||||
let show = MenuItem::with_id(app, "show", "Show", true, None::<&str>)
|
||||
.map_err(|e| format!("Failed to create show menu item: {}", e))?;
|
||||
|
||||
// Create the menu
|
||||
let menu = Menu::with_items(app, &[&show, &quit])
|
||||
.map_err(|e| format!("Failed to create menu: {}", e))?;
|
||||
|
||||
// Create and store the tray icon
|
||||
let tray = TrayIconBuilder::with_id("main")
|
||||
.icon(app.default_window_icon().unwrap().clone())
|
||||
.menu(&menu)
|
||||
.tooltip("PytubePP Helper")
|
||||
.on_menu_event(|app, event| match event.id.as_ref() {
|
||||
"show" => {
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
let _ = window.show();
|
||||
let _ = window.set_focus();
|
||||
}
|
||||
}
|
||||
"quit" => {
|
||||
app.exit(0);
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
.on_tray_icon_event(|tray, event| {
|
||||
if let TrayIconEvent::Click {
|
||||
button: MouseButton::Left,
|
||||
button_state: MouseButtonState::Up,
|
||||
..
|
||||
} = event {
|
||||
let app = tray.app_handle();
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
let _ = window.show();
|
||||
let _ = window.set_focus();
|
||||
}
|
||||
}
|
||||
})
|
||||
.build(app)
|
||||
.map_err(|e| format!("Failed to create tray: {}", e))?;
|
||||
|
||||
// Store the tray handle in the app state
|
||||
app.manage(tray);
|
||||
|
||||
let window = app.get_webview_window("main").unwrap();
|
||||
if start_hidden {
|
||||
window.hide().unwrap();
|
||||
}
|
||||
|
||||
// Start the initial WebSocket server
|
||||
let app_handle = app.handle().clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = start_websocket_server(app_handle, port).await {
|
||||
println!("Failed to start initial WebSocket server: {}", e);
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
send_to_extension,
|
||||
fetch_video_info,
|
||||
install_program,
|
||||
download_stream,
|
||||
receive_frontend_response,
|
||||
get_config,
|
||||
update_config,
|
||||
reset_config,
|
||||
get_config_file_path
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
|
||||
async fn handle_connection(stream: TcpStream, app_handle: tauri::AppHandle) {
|
||||
let ws_stream = accept_async(stream).await.unwrap();
|
||||
let (ws_sender, mut ws_receiver) = ws_stream.split();
|
||||
|
||||
// Store the sender in the shared state
|
||||
{
|
||||
let state = app_handle.state::<Arc<Mutex<WebSocketState>>>();
|
||||
let mut state = state.lock().await;
|
||||
state.sender = Some(ws_sender);
|
||||
}
|
||||
|
||||
println!("New WebSocket connection established");
|
||||
|
||||
while let Some(msg) = ws_receiver.next().await {
|
||||
if let Ok(msg) = msg {
|
||||
if let Ok(text) = msg.to_text() {
|
||||
println!("Received message: {}", text);
|
||||
|
||||
// Parse the JSON message
|
||||
if let Ok(json_value) = serde_json::from_str::<Value>(text) {
|
||||
// Create a new channel for this request
|
||||
let (response_sender, response_receiver) = oneshot::channel();
|
||||
{
|
||||
let state = app_handle.state::<Arc<Mutex<WebSocketState>>>();
|
||||
let mut state = state.lock().await;
|
||||
state.response_channel.sender = Some(response_sender);
|
||||
}
|
||||
|
||||
// Emit an event to the frontend
|
||||
app_handle
|
||||
.emit_to("main", "websocket-message", json_value)
|
||||
.unwrap();
|
||||
|
||||
// Wait for the response from the frontend
|
||||
let response = response_receiver
|
||||
.await
|
||||
.unwrap_or_else(|e| format!("Error receiving response: {:?}", e));
|
||||
|
||||
// Send the response back through WebSocket
|
||||
let state = app_handle.state::<Arc<Mutex<WebSocketState>>>();
|
||||
let mut state = state.lock().await;
|
||||
if let Some(sender) = &mut state.sender {
|
||||
let _ = sender
|
||||
.send(tokio_tungstenite::tungstenite::Message::Text(response))
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("WebSocket connection closed");
|
||||
|
||||
// Remove the sender from the shared state when the connection closes
|
||||
let state = app_handle.state::<Arc<Mutex<WebSocketState>>>();
|
||||
let mut state = state.lock().await;
|
||||
state.sender = None;
|
||||
}
|
||||
@@ -1,454 +1,6 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
mod config;
|
||||
use config::{Config, load_config, save_config, get_config_path};
|
||||
use std::{process::Command, sync::Arc, env, time::Duration};
|
||||
use serde_json::Value;
|
||||
use tauri::{CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu};
|
||||
use tokio::{net::{TcpListener, TcpStream}, sync::{Mutex, oneshot}, time::sleep};
|
||||
use tokio_tungstenite::{accept_async, connect_async};
|
||||
use futures_util::{SinkExt, StreamExt};
|
||||
|
||||
struct ResponseChannel {
|
||||
sender: Option<oneshot::Sender<String>>,
|
||||
}
|
||||
|
||||
struct WebSocketState {
|
||||
sender: Option<futures_util::stream::SplitSink<tokio_tungstenite::WebSocketStream<TcpStream>, tokio_tungstenite::tungstenite::Message>>,
|
||||
response_channel: ResponseChannel,
|
||||
server_abort: Option<tokio::sync::oneshot::Sender<()>>,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
async fn is_another_instance_running(port: u16) -> bool {
|
||||
match connect_async(format!("ws://127.0.0.1:{}", port)).await {
|
||||
Ok(_) => true,
|
||||
Err(_) => false
|
||||
}
|
||||
}
|
||||
|
||||
async fn try_bind_ws_port(port: u16) -> Option<TcpListener> {
|
||||
match TcpListener::bind(format!("127.0.0.1:{}", port)).await {
|
||||
Ok(listener) => Some(listener),
|
||||
Err(_) => None
|
||||
}
|
||||
}
|
||||
|
||||
async fn start_websocket_server(app_handle: tauri::AppHandle, port: u16) -> Result<(), String> {
|
||||
let addr = format!("127.0.0.1:{}", port);
|
||||
|
||||
// First ensure any existing server is stopped
|
||||
{
|
||||
let state = app_handle.state::<Arc<Mutex<WebSocketState>>>();
|
||||
let mut state = state.lock().await;
|
||||
if let Some(old_abort) = state.server_abort.take() {
|
||||
let _ = old_abort.send(());
|
||||
// Give it a moment to shut down
|
||||
sleep(Duration::from_millis(200)).await;
|
||||
}
|
||||
}
|
||||
|
||||
// Now try to bind to the port
|
||||
let listener = TcpListener::bind(&addr).await
|
||||
.map_err(|e| format!("Failed to bind to port {}: {}", port, e))?;
|
||||
|
||||
let (abort_sender, mut abort_receiver) = tokio::sync::oneshot::channel();
|
||||
|
||||
// Store the new abort sender
|
||||
{
|
||||
let state = app_handle.state::<Arc<Mutex<WebSocketState>>>();
|
||||
let mut state = state.lock().await;
|
||||
state.server_abort = Some(abort_sender);
|
||||
}
|
||||
|
||||
// Spawn the server task
|
||||
tokio::spawn(async move {
|
||||
println!("Starting WebSocket server on port {}", port);
|
||||
loop {
|
||||
tokio::select! {
|
||||
accept_result = listener.accept() => {
|
||||
match accept_result {
|
||||
Ok((stream, _)) => {
|
||||
let app_handle = app_handle.clone();
|
||||
tokio::spawn(handle_connection(stream, app_handle));
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error accepting connection: {}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = &mut abort_receiver => {
|
||||
println!("WebSocket server shutting down on port {}...", port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Wait a moment to ensure the server has started
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_config(state: tauri::State<'_, Arc<Mutex<WebSocketState>>>) -> Result<Config, String> {
|
||||
let state = state.lock().await;
|
||||
Ok(state.config.clone())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn get_config_file_path() -> Result<String, String> {
|
||||
match get_config_path() {
|
||||
Some(path) => Ok(path.to_string_lossy().into_owned()),
|
||||
None => Err("Could not determine config path".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn update_config(
|
||||
new_config: Config,
|
||||
state: tauri::State<'_, Arc<Mutex<WebSocketState>>>,
|
||||
app_handle: tauri::AppHandle,
|
||||
) -> Result<Config, String> {
|
||||
// Save the new config first
|
||||
save_config(&new_config)?;
|
||||
|
||||
// Update the state with new config
|
||||
{
|
||||
let mut state = state.lock().await;
|
||||
state.config = new_config.clone();
|
||||
}
|
||||
|
||||
// Start the new server (this will also handle stopping the old one)
|
||||
start_websocket_server(app_handle, new_config.port).await?;
|
||||
|
||||
Ok(new_config)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn reset_config(
|
||||
state: tauri::State<'_, Arc<Mutex<WebSocketState>>>,
|
||||
app_handle: tauri::AppHandle,
|
||||
) -> Result<Config, String> {
|
||||
let config = Config::default();
|
||||
save_config(&config)?;
|
||||
|
||||
{
|
||||
let mut state = state.lock().await;
|
||||
state.config = config.clone();
|
||||
}
|
||||
|
||||
start_websocket_server(app_handle, config.port).await?;
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn send_to_extension(
|
||||
message: String,
|
||||
state: tauri::State<'_, Arc<Mutex<WebSocketState>>>,
|
||||
) -> Result<(), String> {
|
||||
let mut state = state.lock().await;
|
||||
if let Some(sender) = &mut state.sender {
|
||||
sender.send(tokio_tungstenite::tungstenite::Message::Text(message)).await
|
||||
.map_err(|e| format!("Failed to send message: {}", e))?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err("No active WebSocket connection".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn receive_frontend_response(
|
||||
response: String,
|
||||
state: tauri::State<'_, Arc<Mutex<WebSocketState>>>,
|
||||
) -> Result<(), String> {
|
||||
let mut state = state.lock().await;
|
||||
if let Some(sender) = state.response_channel.sender.take() {
|
||||
sender.send(response).map_err(|e| format!("Failed to send response: {:?}", e))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn fetch_video_info(url: String) {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let command = format!("pytubepp \"{}\" -i", &url);
|
||||
Command::new("cmd")
|
||||
.args(["/k", command.as_str()])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let command = format!("pytubepp \"{}\" -i", &url);
|
||||
Command::new("gnome-terminal")
|
||||
.args(["--", "bash", "-c", command.as_str()])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let command = format!("pytubepp \"{}\" -i", &url);
|
||||
let escaped_command = command.replace("\"", "\\\"");
|
||||
|
||||
let applescript = format!(
|
||||
"tell application \"Terminal\"\n\
|
||||
do script \"{}\"\n\
|
||||
activate\n\
|
||||
end tell",
|
||||
escaped_command
|
||||
);
|
||||
|
||||
Command::new("osascript")
|
||||
.arg("-e")
|
||||
.arg(applescript)
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn install_program(icommand: String) {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let command = format!("{}", &icommand);
|
||||
Command::new("cmd")
|
||||
.args(["/k", command.as_str()])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let command = format!("{}", &icommand);
|
||||
Command::new("gnome-terminal")
|
||||
.args(["--", "bash", "-c", command.as_str()])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let command = format!("{}", &icommand);
|
||||
let escaped_command = command.replace("\"", "\\\"");
|
||||
|
||||
let applescript = format!(
|
||||
"tell application \"Terminal\"\n\
|
||||
do script \"{}\"\n\
|
||||
activate\n\
|
||||
end tell",
|
||||
escaped_command
|
||||
);
|
||||
|
||||
Command::new("osascript")
|
||||
.arg("-e")
|
||||
.arg(applescript)
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn download_stream(url: String, stream: String, caption: Option<String>) {
|
||||
let caption = caption.unwrap_or("none".to_string());
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let command = format!("pytubepp \"{}\" -s {} -c {}", &url, &stream, &caption);
|
||||
Command::new("cmd")
|
||||
.args(["/k", command.as_str()])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let command = format!("pytubepp \"{}\" -s {} -c {}", &url, &stream, &caption);
|
||||
Command::new("gnome-terminal")
|
||||
.args(["--", "bash", "-c", command.as_str()])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let command = format!("pytubepp \"{}\" -s {} -c {}", &url, &stream, &caption);
|
||||
let escaped_command = command.replace("\"", "\\\"");
|
||||
|
||||
let applescript = format!(
|
||||
"tell application \"Terminal\"\n\
|
||||
do script \"{}\"\n\
|
||||
activate\n\
|
||||
end tell",
|
||||
escaped_command
|
||||
);
|
||||
|
||||
Command::new("osascript")
|
||||
.arg("-e")
|
||||
.arg(applescript)
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let _ = fix_path_env::fix();
|
||||
|
||||
let config = load_config();
|
||||
let port = config.port;
|
||||
|
||||
let websocket_state = Arc::new(Mutex::new(WebSocketState {
|
||||
sender: None,
|
||||
response_channel: ResponseChannel { sender: None },
|
||||
server_abort: None,
|
||||
config,
|
||||
}));
|
||||
|
||||
// Check if another instance is running
|
||||
if is_another_instance_running(port).await {
|
||||
println!("Another instance is already running. Exiting...");
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
// Try to bind to the WebSocket port with a few retries
|
||||
let mut port_available = false;
|
||||
for _ in 0..3 {
|
||||
if let Some(_) = try_bind_ws_port(port).await {
|
||||
port_available = true;
|
||||
break;
|
||||
}
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
}
|
||||
|
||||
// If we couldn't bind to the port after retries, assume another instance is running
|
||||
if !port_available {
|
||||
println!("Could not bind to WebSocket port. Another instance might be running. Exiting...");
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let start_hidden = args.contains(&"--hidden".to_string());
|
||||
|
||||
let tray_menu = SystemTrayMenu::new()
|
||||
.add_item(CustomMenuItem::new("show".to_string(), "Show"))
|
||||
.add_item(CustomMenuItem::new("quit".to_string(), "Quit"));
|
||||
|
||||
let system_tray = SystemTray::new().with_menu(tray_menu).with_tooltip("PytubePP Helper");
|
||||
|
||||
tauri::Builder::default()
|
||||
.system_tray(system_tray)
|
||||
.on_system_tray_event(|app, event| match event {
|
||||
SystemTrayEvent::LeftClick {
|
||||
position: _,
|
||||
size: _,
|
||||
..
|
||||
} => {
|
||||
let window = app.get_window("main").unwrap();
|
||||
window.show().unwrap();
|
||||
window.set_focus().unwrap();
|
||||
}
|
||||
SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
|
||||
"show" => {
|
||||
let window = app.get_window("main").unwrap();
|
||||
window.show().unwrap();
|
||||
window.set_focus().unwrap();
|
||||
}
|
||||
"quit" => {
|
||||
app.exit(0);
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
})
|
||||
.manage(websocket_state.clone())
|
||||
.setup(move |app| {
|
||||
let window = app.get_window("main").unwrap();
|
||||
|
||||
if start_hidden {
|
||||
window.hide().unwrap();
|
||||
}
|
||||
|
||||
// Start the initial WebSocket server
|
||||
let app_handle = app.handle();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = start_websocket_server(app_handle, port).await {
|
||||
println!("Failed to start initial WebSocket server: {}", e);
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
send_to_extension,
|
||||
fetch_video_info,
|
||||
install_program,
|
||||
download_stream,
|
||||
receive_frontend_response,
|
||||
get_config,
|
||||
update_config,
|
||||
reset_config,
|
||||
get_config_file_path
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
|
||||
async fn handle_connection(stream: TcpStream, app_handle: tauri::AppHandle) {
|
||||
let ws_stream = accept_async(stream).await.unwrap();
|
||||
let (ws_sender, mut ws_receiver) = ws_stream.split();
|
||||
|
||||
// Store the sender in the shared state
|
||||
{
|
||||
let state = app_handle.state::<Arc<Mutex<WebSocketState>>>();
|
||||
let mut state = state.lock().await;
|
||||
state.sender = Some(ws_sender);
|
||||
}
|
||||
|
||||
println!("New WebSocket connection established");
|
||||
|
||||
while let Some(msg) = ws_receiver.next().await {
|
||||
if let Ok(msg) = msg {
|
||||
if let Ok(text) = msg.to_text() {
|
||||
println!("Received message: {}", text);
|
||||
|
||||
// Parse the JSON message
|
||||
if let Ok(json_value) = serde_json::from_str::<Value>(text) {
|
||||
// Create a new channel for this request
|
||||
let (response_sender, response_receiver) = oneshot::channel();
|
||||
{
|
||||
let state = app_handle.state::<Arc<Mutex<WebSocketState>>>();
|
||||
let mut state = state.lock().await;
|
||||
state.response_channel.sender = Some(response_sender);
|
||||
}
|
||||
|
||||
// Emit an event to the frontend
|
||||
app_handle.emit_all("websocket-message", json_value).unwrap();
|
||||
|
||||
// Wait for the response from the frontend
|
||||
let response = response_receiver.await
|
||||
.unwrap_or_else(|e| format!("Error receiving response: {:?}", e));
|
||||
|
||||
// Send the response back through WebSocket
|
||||
let state = app_handle.state::<Arc<Mutex<WebSocketState>>>();
|
||||
let mut state = state.lock().await;
|
||||
if let Some(sender) = &mut state.sender {
|
||||
let _ = sender.send(tokio_tungstenite::tungstenite::Message::Text(response)).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("WebSocket connection closed");
|
||||
|
||||
// Remove the sender from the shared state when the connection closes
|
||||
let state = app_handle.state::<Arc<Mutex<WebSocketState>>>();
|
||||
let mut state = state.lock().await;
|
||||
state.sender = None;
|
||||
pytubepp_helper_lib::run().await;
|
||||
}
|
||||
@@ -1,39 +1,38 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
"beforeBuildCommand": "npm run build",
|
||||
"devPath": "http://localhost:1422",
|
||||
"distDir": "../dist"
|
||||
"frontendDist": "../dist",
|
||||
"devUrl": "http://localhost:1422"
|
||||
},
|
||||
"package": {
|
||||
"productName": "pytubepp-helper",
|
||||
"version": "0.6.0"
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
]
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
"all": false
|
||||
"productName": "pytubepp-helper",
|
||||
"mainBinaryName": "pytubepp-helper",
|
||||
"version": "0.6.0",
|
||||
"identifier": "com.neosubhamoy.pytubepp.helper",
|
||||
"plugins": {},
|
||||
"app": {
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"title": "PytubePP Helper",
|
||||
"width": 500,
|
||||
"height": 320
|
||||
"width": 510,
|
||||
"height": 345,
|
||||
"useHttpsScheme": true
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"identifier": "com.neosubhamoy.pytubepp.helper",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -2,141 +2,40 @@
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev && cargo build --manifest-path=./src-tauri/msghost/Cargo.toml",
|
||||
"beforeBuildCommand": "npm run build && cargo build --release --manifest-path=./src-tauri/msghost/Cargo.toml",
|
||||
"devPath": "http://localhost:1422",
|
||||
"distDir": "../dist"
|
||||
"devUrl": "http://localhost:1422",
|
||||
"frontendDist": "../dist"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
"all": false,
|
||||
"os": {
|
||||
"all": true
|
||||
},
|
||||
"shell": {
|
||||
"all": true,
|
||||
"execute": true,
|
||||
"sidecar": true,
|
||||
"open": true,
|
||||
"scope": [
|
||||
{
|
||||
"name": "detect-windows",
|
||||
"cmd": "systeminfo",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "detect-macos",
|
||||
"cmd": "sw_vers",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "detect-distro",
|
||||
"cmd": "grep",
|
||||
"args": ["^ID=", "/etc/os-release"]
|
||||
},
|
||||
{
|
||||
"name": "detect-pkgmngr",
|
||||
"cmd": "sh",
|
||||
"args": ["-c", "command -v apt || command -v dnf || command -v pacman"]
|
||||
},
|
||||
{
|
||||
"name": "is-apt-installed",
|
||||
"cmd": "apt",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-dnf-installed",
|
||||
"cmd": "dnf",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-python3-installed",
|
||||
"cmd": "python3",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-pip3-installed",
|
||||
"cmd": "pip3",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-winget-installed",
|
||||
"cmd": "winget",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-homebrew-installed",
|
||||
"cmd": "brew",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-python-installed",
|
||||
"cmd": "python",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-pip-installed",
|
||||
"cmd": "pip",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-ffmpeg-installed",
|
||||
"cmd": "ffmpeg",
|
||||
"args": ["-version"]
|
||||
},
|
||||
{
|
||||
"name": "is-nodejs-installed",
|
||||
"cmd": "node",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-pytubepp-installed",
|
||||
"cmd": "pytubepp",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "fetch-video-info",
|
||||
"cmd": "pytubepp",
|
||||
"args": [{ "validator": "\\S+" }, "--raw-info"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"window": {
|
||||
"all": false,
|
||||
"close": true,
|
||||
"hide": true,
|
||||
"show": true,
|
||||
"maximize": true,
|
||||
"minimize": true,
|
||||
"unmaximize": true,
|
||||
"unminimize": true,
|
||||
"startDragging": true
|
||||
},
|
||||
"process": {
|
||||
"all": false,
|
||||
"exit": true,
|
||||
"relaunch": true
|
||||
}
|
||||
},
|
||||
"identifier": "com.neosubhamoy.pytubepp.helper",
|
||||
"plugins": {},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "PytubePP Helper",
|
||||
"width": 510,
|
||||
"height": 345
|
||||
"height": 345,
|
||||
"useHttpsScheme": true
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": ["deb", "rpm"],
|
||||
"identifier": "com.neosubhamoy.pytubepp.helper",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"csp": null,
|
||||
"capabilities": [
|
||||
"main-capability",
|
||||
"shell-scope"
|
||||
]
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": ["deb", "rpm"],
|
||||
"licenseFile": "../LICENSE",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"linux": {
|
||||
"deb": {
|
||||
"depends": ["python3-pip", "ffmpeg", "gnome-terminal"],
|
||||
"files": {
|
||||
@@ -150,7 +49,6 @@
|
||||
"rpm": {
|
||||
"epoch": 0,
|
||||
"release": "1",
|
||||
"license": "MIT",
|
||||
"depends": ["python3-pip", "ffmpeg", "gnome-terminal"],
|
||||
"files": {
|
||||
"/etc/opt/chrome/native-messaging-hosts/com.neosubhamoy.pytubepp.helper.json": "./msghost-manifest/linux/chrome/com.neosubhamoy.pytubepp.helper.json",
|
||||
@@ -160,10 +58,6 @@
|
||||
"/etc/xdg/autostart/pytubepp-helper-autostart.desktop": "./autostart/pytubepp-helper-autostart.desktop"
|
||||
}
|
||||
}
|
||||
},
|
||||
"systemTray": {
|
||||
"iconPath": "icons/32x32.png",
|
||||
"iconAsTemplate": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,175 +2,71 @@
|
||||
"build": {
|
||||
"beforeDevCommand": "[[ -n \"$TARGET_ARCH\" ]] && ARCH=\"$TARGET_ARCH\" || ARCH=\"$(uname -m | sed 's/^arm64$/aarch64/')-apple-darwin\" && cargo build --target=$ARCH --manifest-path=./src-tauri/msghost/Cargo.toml && npm run dev",
|
||||
"beforeBuildCommand": "[[ -n \"$TARGET_ARCH\" ]] && ARCH=\"$TARGET_ARCH\" || ARCH=\"$(uname -m | sed 's/^arm64$/aarch64/')-apple-darwin\" && cargo build --release --target=$ARCH --manifest-path=./src-tauri/msghost/Cargo.toml && node copyFiles.${ARCH}.js && npm run build",
|
||||
"devPath": "http://localhost:1422",
|
||||
"distDir": "../dist"
|
||||
"devUrl": "http://localhost:1422",
|
||||
"frontendDist": "../dist"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
"all": false,
|
||||
"os": {
|
||||
"all": true
|
||||
},
|
||||
"shell": {
|
||||
"all": true,
|
||||
"execute": true,
|
||||
"sidecar": true,
|
||||
"open": true,
|
||||
"scope": [
|
||||
{
|
||||
"name": "detect-windows",
|
||||
"cmd": "systeminfo",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "detect-macos",
|
||||
"cmd": "sw_vers",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "detect-distro",
|
||||
"cmd": "grep",
|
||||
"args": ["^ID=", "/etc/os-release"]
|
||||
},
|
||||
{
|
||||
"name": "detect-pkgmngr",
|
||||
"cmd": "sh",
|
||||
"args": ["-c", "command -v apt || command -v dnf || command -v pacman"]
|
||||
},
|
||||
{
|
||||
"name": "is-apt-installed",
|
||||
"cmd": "apt",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-dnf-installed",
|
||||
"cmd": "dnf",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-python3-installed",
|
||||
"cmd": "python3",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-pip3-installed",
|
||||
"cmd": "pip3",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-winget-installed",
|
||||
"cmd": "winget",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-homebrew-installed",
|
||||
"cmd": "brew",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-python-installed",
|
||||
"cmd": "python",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-pip-installed",
|
||||
"cmd": "pip",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-ffmpeg-installed",
|
||||
"cmd": "ffmpeg",
|
||||
"args": ["-version"]
|
||||
},
|
||||
{
|
||||
"name": "is-nodejs-installed",
|
||||
"cmd": "node",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-pytubepp-installed",
|
||||
"cmd": "pytubepp",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "fetch-video-info",
|
||||
"cmd": "pytubepp",
|
||||
"args": [{ "validator": "\\S+" }, "--raw-info"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"fs": {
|
||||
"all": true,
|
||||
"copyFile": true,
|
||||
"exists": true,
|
||||
"createDir": true,
|
||||
"scope": [
|
||||
"$HOME/Library/LaunchAgents/",
|
||||
"$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts/",
|
||||
"$HOME/Library/Application Support/Chromium/NativeMessagingHosts/",
|
||||
"$HOME/Library/Application Support/Mozilla/NativeMessagingHosts/",
|
||||
"$RESOURCE/pytubepp-helper-msghost.json",
|
||||
"$RESOURCE/pytubepp-helper-msghost-moz.json",
|
||||
"$RESOURCE/pytubepp-helper-msghost",
|
||||
"$RESOURCE/pytubepp-helper-autostart.plist"
|
||||
]
|
||||
},
|
||||
"path": {
|
||||
"all": true
|
||||
},
|
||||
"window": {
|
||||
"all": false,
|
||||
"close": true,
|
||||
"hide": true,
|
||||
"show": true,
|
||||
"maximize": true,
|
||||
"minimize": true,
|
||||
"unmaximize": true,
|
||||
"unminimize": true,
|
||||
"startDragging": true
|
||||
},
|
||||
"process": {
|
||||
"all": false,
|
||||
"exit": true,
|
||||
"relaunch": true
|
||||
}
|
||||
},
|
||||
"identifier": "com.neosubhamoy.pytubepp.helper",
|
||||
"plugins": {},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "PytubePP Helper",
|
||||
"width": 515,
|
||||
"height": 365
|
||||
"height": 365,
|
||||
"useHttpsScheme": true
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": ["app", "dmg"],
|
||||
"identifier": "com.neosubhamoy.pytubepp.helper",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"macOS": {
|
||||
"minimumSystemVersion": "10.13",
|
||||
"license": "../LICENSE",
|
||||
"providerShortName": "neosubhamoy"
|
||||
},
|
||||
"resources": [
|
||||
"pytubepp-helper-msghost.json",
|
||||
"pytubepp-helper-msghost-moz.json",
|
||||
"pytubepp-helper-msghost",
|
||||
"pytubepp-helper-autostart.plist"
|
||||
"csp": null,
|
||||
"capabilities": [
|
||||
"main-capability",
|
||||
"shell-scope",
|
||||
{
|
||||
"identifier": "fs-scope",
|
||||
"description": "allowed file system scopes",
|
||||
"permissions": [
|
||||
{
|
||||
"identifier": "fs:scope",
|
||||
"allow": [
|
||||
{ "path": "$HOME/Library/LaunchAgents/" },
|
||||
{ "path": "$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts/" },
|
||||
{ "path": "$HOME/Library/Application Support/Chromium/NativeMessagingHosts/" },
|
||||
{ "path": "$HOME/Library/Application Support/Mozilla/NativeMessagingHosts/" },
|
||||
{ "path": "$HOME/Library/LaunchAgents/*" },
|
||||
{ "path": "$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts/*" },
|
||||
{ "path": "$HOME/Library/Application Support/Chromium/NativeMessagingHosts/*" },
|
||||
{ "path": "$HOME/Library/Application Support/Mozilla/NativeMessagingHosts/*" },
|
||||
{ "path": "$RESOURCE/pytubepp-helper-msghost.json" },
|
||||
{ "path": "$RESOURCE/pytubepp-helper-msghost-moz.json" },
|
||||
{ "path": "$RESOURCE/pytubepp-helper-msghost" },
|
||||
{ "path": "$RESOURCE/pytubepp-helper-autostart.plist" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"systemTray": {
|
||||
"iconPath": "icons/32x32.png",
|
||||
"iconAsTemplate": true
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": ["app", "dmg"],
|
||||
"licenseFile": "../LICENSE",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"macOS": {
|
||||
"minimumSystemVersion": "10.13",
|
||||
"providerShortName": "neosubhamoy"
|
||||
},
|
||||
"resources": [
|
||||
"pytubepp-helper-msghost.json",
|
||||
"pytubepp-helper-msghost-moz.json",
|
||||
"pytubepp-helper-msghost",
|
||||
"pytubepp-helper-autostart.plist"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -2,167 +2,66 @@
|
||||
"build": {
|
||||
"beforeDevCommand": "cargo build --manifest-path=./src-tauri/msghost/Cargo.toml && npm run dev",
|
||||
"beforeBuildCommand": "cargo build --release --manifest-path=./src-tauri/msghost/Cargo.toml && node copyFiles.js && npm run build",
|
||||
"devPath": "http://localhost:1422",
|
||||
"distDir": "../dist"
|
||||
"devUrl": "http://localhost:1422",
|
||||
"frontendDist": "../dist"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
"all": false,
|
||||
"os": {
|
||||
"all": true
|
||||
},
|
||||
"shell": {
|
||||
"all": true,
|
||||
"execute": true,
|
||||
"sidecar": true,
|
||||
"open": true,
|
||||
"scope": [
|
||||
{
|
||||
"name": "detect-windows",
|
||||
"cmd": "systeminfo",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "detect-macos",
|
||||
"cmd": "sw_vers",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "detect-distro",
|
||||
"cmd": "grep",
|
||||
"args": ["^ID=", "/etc/os-release"]
|
||||
},
|
||||
{
|
||||
"name": "detect-pkgmngr",
|
||||
"cmd": "sh",
|
||||
"args": ["-c", "command -v apt || command -v dnf || command -v pacman"]
|
||||
},
|
||||
{
|
||||
"name": "is-apt-installed",
|
||||
"cmd": "apt",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-dnf-installed",
|
||||
"cmd": "dnf",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-python3-installed",
|
||||
"cmd": "python3",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-pip3-installed",
|
||||
"cmd": "pip3",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-winget-installed",
|
||||
"cmd": "winget",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-homebrew-installed",
|
||||
"cmd": "brew",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-python-installed",
|
||||
"cmd": "python",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-pip-installed",
|
||||
"cmd": "pip",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-ffmpeg-installed",
|
||||
"cmd": "ffmpeg",
|
||||
"args": ["-version"]
|
||||
},
|
||||
{
|
||||
"name": "is-nodejs-installed",
|
||||
"cmd": "node",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "is-pytubepp-installed",
|
||||
"cmd": "pytubepp",
|
||||
"args": ["--version"]
|
||||
},
|
||||
{
|
||||
"name": "fetch-video-info",
|
||||
"cmd": "pytubepp",
|
||||
"args": [{ "validator": "\\S+" }, "--raw-info"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"fs": {
|
||||
"scope": [
|
||||
"$RESOURCE/pytubepp-helper-msghost.json",
|
||||
"$RESOURCE/pytubepp-helper-msghost-moz.json",
|
||||
"$RESOURCE/pytubepp-helper-msghost.exe"
|
||||
]
|
||||
},
|
||||
"window": {
|
||||
"all": false,
|
||||
"close": true,
|
||||
"hide": true,
|
||||
"show": true,
|
||||
"maximize": true,
|
||||
"minimize": true,
|
||||
"unmaximize": true,
|
||||
"unminimize": true,
|
||||
"startDragging": true
|
||||
},
|
||||
"process": {
|
||||
"all": false,
|
||||
"exit": true,
|
||||
"relaunch": true
|
||||
}
|
||||
},
|
||||
"identifier": "com.neosubhamoy.pytubepp.helper",
|
||||
"plugins": {},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "PytubePP Helper",
|
||||
"width": 510,
|
||||
"height": 345
|
||||
"height": 345,
|
||||
"useHttpsScheme": true
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": ["msi", "nsis"],
|
||||
"identifier": "com.neosubhamoy.pytubepp.helper",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"windows": {
|
||||
"wix": {
|
||||
"fragmentPaths": ["installer/windows/wix-fragment-registry.wxs"],
|
||||
"componentRefs": ["PytubeppHelperFragmentRegistryEntries"],
|
||||
"license": "../LICENSE"
|
||||
},
|
||||
"nsis": {
|
||||
"template": "installer/windows/nsis-template.nsi"
|
||||
"csp": null,
|
||||
"capabilities": [
|
||||
"main-capability",
|
||||
"shell-scope",
|
||||
{
|
||||
"identifier": "fs-scope",
|
||||
"description": "allowed file system scopes",
|
||||
"permissions": [
|
||||
{
|
||||
"identifier": "fs:scope",
|
||||
"allow": [
|
||||
{ "path": "$RESOURCE/pytubepp-helper-msghost.json" },
|
||||
{ "path": "$RESOURCE/pytubepp-helper-msghost-moz.json" },
|
||||
{ "path": "$RESOURCE/pytubepp-helper-msghost.exe" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
"pytubepp-helper-msghost.json",
|
||||
"pytubepp-helper-msghost-moz.json",
|
||||
"pytubepp-helper-msghost.exe"
|
||||
]
|
||||
},
|
||||
"systemTray": {
|
||||
"iconPath": "icons/icon.ico",
|
||||
"iconAsTemplate": true
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": ["msi", "nsis"],
|
||||
"licenseFile": "../LICENSE",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"windows": {
|
||||
"wix": {
|
||||
"fragmentPaths": ["installer/windows/wix-fragment-registry.wxs"],
|
||||
"componentRefs": ["PytubeppHelperFragmentRegistryEntries"]
|
||||
},
|
||||
"nsis": {
|
||||
"template": "installer/windows/nsis-template.nsi"
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
"pytubepp-helper-msghost.json",
|
||||
"pytubepp-helper-msghost-moz.json",
|
||||
"pytubepp-helper-msghost.exe"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from "react"
|
||||
import { useEffect } from "react";
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { appWindow } from '@tauri-apps/api/window';
|
||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
import { ThemeProvider } from "@/components/theme-provider";
|
||||
import { WebSocketMessage } from "@/types";
|
||||
import { sendStreamInfo } from "@/lib/utils";
|
||||
@@ -10,6 +10,8 @@ import { Toaster } from "@/components/ui/toaster";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
|
||||
function App({ children }: { children: React.ReactNode }) {
|
||||
const appWindow = getCurrentWebviewWindow()
|
||||
|
||||
useEffect(() => {
|
||||
const handleCloseRequested = (event: any) => {
|
||||
event.preventDefault();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { platform } from "@tauri-apps/api/os";
|
||||
import { platform } from "@tauri-apps/plugin-os";
|
||||
import { detectDistro, detectMacOs, detectPackageManager, detectWindows, extractDistroId, extractPkgMngrName, extractVersion } from "@/lib/utils";
|
||||
import { PlatformInfo } from "@/types";
|
||||
|
||||
@@ -16,7 +16,7 @@ export async function getPlatformInfo(): Promise<PlatformInfo> {
|
||||
const currentPlatform = await platform();
|
||||
|
||||
switch (currentPlatform) {
|
||||
case 'win32': {
|
||||
case 'windows': {
|
||||
const windowsResult = await detectWindows();
|
||||
if (windowsResult) {
|
||||
return {
|
||||
@@ -27,8 +27,7 @@ export async function getPlatformInfo(): Promise<PlatformInfo> {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'darwin': {
|
||||
case 'macos': {
|
||||
const macResult = await detectMacOs();
|
||||
if (macResult) {
|
||||
return {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { type ClassValue, clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import { Command } from '@tauri-apps/api/shell';
|
||||
import { invoke } from "@tauri-apps/api";
|
||||
import { fs } from '@tauri-apps/api';
|
||||
import { join, resourceDir, homeDir } from '@tauri-apps/api/path';
|
||||
import { Command } from "@tauri-apps/plugin-shell";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { join, resourceDir, homeDir } from "@tauri-apps/api/path";
|
||||
import * as fs from "@tauri-apps/plugin-fs"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
@@ -11,7 +11,7 @@ export function cn(...inputs: ClassValue[]) {
|
||||
|
||||
export async function isInstalled(program: string, arg: string): Promise<{ installed: boolean, output: string | null }> {
|
||||
try{
|
||||
const output = await new Command('is-' + program + '-installed', [arg]).execute();
|
||||
const output = await Command.create('is-' + program + '-installed', [arg]).execute();
|
||||
if (output.code === 0) {
|
||||
return { installed: true, output: output.stdout };
|
||||
} else {
|
||||
@@ -25,7 +25,7 @@ export async function isInstalled(program: string, arg: string): Promise<{ insta
|
||||
|
||||
export async function detectWindows(): Promise<string | null> {
|
||||
try{
|
||||
const output = await new Command('detect-windows', []).execute();
|
||||
const output = await Command.create('detect-windows', []).execute();
|
||||
if (output.code === 0) {
|
||||
return output.stdout;
|
||||
} else {
|
||||
@@ -39,7 +39,7 @@ export async function detectWindows(): Promise<string | null> {
|
||||
|
||||
export async function detectMacOs(): Promise<string | null> {
|
||||
try{
|
||||
const output = await new Command('detect-macos', []).execute();
|
||||
const output = await Command.create('detect-macos', []).execute();
|
||||
if (output.code === 0) {
|
||||
return output.stdout;
|
||||
} else {
|
||||
@@ -53,7 +53,7 @@ export async function detectMacOs(): Promise<string | null> {
|
||||
|
||||
export async function detectDistro(): Promise<string | null> {
|
||||
try{
|
||||
const output = await new Command('detect-distro', ['^ID=', '/etc/os-release']).execute();
|
||||
const output = await Command.create('detect-distro', ['^ID=', '/etc/os-release']).execute();
|
||||
if (output.code === 0) {
|
||||
return output.stdout;
|
||||
} else {
|
||||
@@ -67,7 +67,7 @@ export async function detectDistro(): Promise<string | null> {
|
||||
|
||||
export async function detectPackageManager(): Promise<string | null> {
|
||||
try{
|
||||
const output = await new Command('detect-pkgmngr', ['-c', 'command -v apt || command -v dnf || command -v pacman']).execute();
|
||||
const output = await Command.create('detect-pkgmngr', ['-c', 'command -v apt || command -v dnf || command -v pacman']).execute();
|
||||
if (output.code === 0) {
|
||||
return output.stdout;
|
||||
} else {
|
||||
@@ -118,7 +118,7 @@ export function extractVersion(output: string): string | null {
|
||||
export async function sendStreamInfo(url: string) {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const output = await new Command('fetch-video-info', [url, '--raw-info']).execute();
|
||||
const output = await Command.create('fetch-video-info', [url, '--raw-info']).execute();
|
||||
if (output.code === 0) {
|
||||
console.log(output.stdout);
|
||||
const sendStreamData = async () => {
|
||||
@@ -174,7 +174,7 @@ export async function registerMacFiles() {
|
||||
await fs.copyFile(sourcePath, destinationPath);
|
||||
console.log(`File ${file.source} copied successfully to ${destinationPath}`);
|
||||
} else {
|
||||
await fs.createDir(destinationDir, { recursive: true })
|
||||
await fs.mkdir(destinationDir, { recursive: true })
|
||||
console.log(`Created dir ${destinationDir}`);
|
||||
await fs.copyFile(sourcePath, destinationPath);
|
||||
console.log(`File ${file.source} copied successfully to ${destinationPath}`);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import clsx from "clsx";
|
||||
import { useState, useEffect } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
|
||||
import { InstalledPrograms } from "@/types";
|
||||
|
||||
@@ -2,7 +2,7 @@ import clsx from "clsx";
|
||||
import { z } from "zod";
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { getVersion } from "@tauri-apps/api/app";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ArrowLeft, Github, Globe, History, Save } from "lucide-react";
|
||||
|
||||
Reference in New Issue
Block a user